void route_Add(struct sticky_route **rp, int type, const struct ncprange *dst, const struct ncpaddr *gw) { struct sticky_route *r; int dsttype = type & ROUTE_DSTANY; r = NULL; while (*rp) { if ((dsttype && dsttype == ((*rp)->type & ROUTE_DSTANY)) || (!dsttype && ncprange_equal(&(*rp)->dst, dst))) { /* Oops, we already have this route - unlink it */ free(r); /* impossible really */ r = *rp; *rp = r->next; } else rp = &(*rp)->next; } if (!r) r = (struct sticky_route *)malloc(sizeof(struct sticky_route)); r->type = type; r->next = NULL; ncprange_copy(&r->dst, dst); ncpaddr_copy(&r->gw, gw); *rp = r; }
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; }