int iface_Delete(struct iface *iface, struct ncp *ncp, const struct ncpaddr *del) { struct ncpaddr found; unsigned n; int res, s; if ((s = ID0socket(ncpaddr_family(del), SOCK_DGRAM, 0)) == -1) { log_Printf(LogERROR, "iface_Delete: socket(): %s\n", strerror(errno)); return 0; } for (n = res = 0; n < iface->addrs; n++) { ncprange_getaddr(&iface->addr[n].ifa, &found); if (ncpaddr_equal(&found, del)) { if (iface_addr_Zap(iface->name, iface->addr + n, s)) { ncp_IfaceAddrDeleted(ncp, iface->addr + n); bcopy(iface->addr + n + 1, iface->addr + n, (iface->addrs - n - 1) * sizeof *iface->addr); iface->addrs--; res = 1; } break; } } close(s); return res; }
void iface_Clear(struct iface *iface, struct ncp *ncp, int family, int how) { int addrs, af, inskip, in6skip, s4 = -1, s6 = -1, *s; unsigned n; if (iface->addrs) { inskip = in6skip = how == IFACE_CLEAR_ALL ? 0 : 1; addrs = 0; for (n = 0; n < iface->addrs; n++) { af = ncprange_family(&iface->addr[n].ifa); if (family == 0 || family == af) { if (!iface->addr[n].system && (how & IFACE_SYSTEM)) continue; switch (af) { case AF_INET: if (inskip) { inskip = 0; continue; } s = &s4; break; #ifndef NOINET6 case AF_INET6: if (in6skip) { in6skip = 0; continue; } s = &s6; break; #endif default: continue; } if (*s == -1 && (*s = ID0socket(af, SOCK_DGRAM, 0)) == -1) log_Printf(LogERROR, "iface_Clear: socket(): %s\n", strerror(errno)); else if (iface_addr_Zap(iface->name, iface->addr + n, *s)) { ncp_IfaceAddrDeleted(ncp, iface->addr + n); bcopy(iface->addr + n + 1, iface->addr + n, (iface->addrs - n - 1) * sizeof *iface->addr); iface->addrs--; n--; } } } /* Don't bother realloc()ing - we have little to gain */ if (s4) close(s4); if (s6) close(s6); } }
int iface_Add(struct iface *iface, struct ncp *ncp, const struct ncprange *ifa, const struct ncpaddr *peer, int how) { int af, removed, s; unsigned n; struct ncpaddr ncplocal; struct iface_addr *addr, newaddr; af = ncprange_family(ifa); if ((s = ID0socket(af, SOCK_DGRAM, 0)) == -1) { log_Printf(LogERROR, "iface_Add: socket(): %s\n", strerror(errno)); return 0; } ncprange_getaddr(ifa, &ncplocal); for (n = 0; n < iface->addrs; n++) { if (ncprange_contains(&iface->addr[n].ifa, &ncplocal) || ncpaddr_equal(&iface->addr[n].peer, peer)) { /* Replace this sockaddr */ if (!(how & IFACE_FORCE_ADD)) { close(s); return 0; /* errno = EEXIST; */ } if (ncprange_equal(&iface->addr[n].ifa, ifa) && ncpaddr_equal(&iface->addr[n].peer, peer)) { close(s); ncp_IfaceAddrAdded(ncp, iface->addr + n); return 1; /* Already there */ } removed = iface_addr_Zap(iface->name, iface->addr + n, s); if (removed) ncp_IfaceAddrDeleted(ncp, iface->addr + n); ncprange_copy(&iface->addr[n].ifa, ifa); ncpaddr_copy(&iface->addr[n].peer, peer); if (!iface_addr_Add(iface->name, iface->addr + n, s)) { if (removed) { bcopy(iface->addr + n + 1, iface->addr + n, (iface->addrs - n - 1) * sizeof *iface->addr); iface->addrs--; n--; } close(s); return 0; } close(s); ncp_IfaceAddrAdded(ncp, iface->addr + n); return 1; } } addr = (struct iface_addr *)realloc (iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]); if (addr == NULL) { log_Printf(LogERROR, "iface_inAdd: realloc: %s\n", strerror(errno)); close(s); return 0; } iface->addr = addr; ncprange_copy(&newaddr.ifa, ifa); ncpaddr_copy(&newaddr.peer, peer); newaddr.system = !!(how & IFACE_SYSTEM); if (!iface_addr_Add(iface->name, &newaddr, s)) { close(s); return 0; } if (how & IFACE_ADD_FIRST) { /* Stuff it at the start of our list */ n = 0; bcopy(iface->addr, iface->addr + 1, iface->addrs * sizeof *iface->addr); } else n = iface->addrs; iface->addrs++; memcpy(iface->addr + n, &newaddr, sizeof(*iface->addr)); close(s); ncp_IfaceAddrAdded(ncp, iface->addr + n); return 1; }