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 route_Change(struct bundle *bundle, struct sticky_route *r, const struct ncpaddr *me, const struct ncpaddr *peer) { struct ncpaddr dst; for (; r; r = r->next) { ncprange_getaddr(&r->dst, &dst); if (ncpaddr_family(me) == AF_INET) { if ((r->type & ROUTE_DSTMYADDR) && !ncpaddr_equal(&dst, me)) { rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0); ncprange_sethost(&r->dst, me); if (r->type & ROUTE_GWHISADDR) ncpaddr_copy(&r->gw, peer); } else if ((r->type & ROUTE_DSTHISADDR) && !ncpaddr_equal(&dst, peer)) { rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0); ncprange_sethost(&r->dst, peer); if (r->type & ROUTE_GWHISADDR) ncpaddr_copy(&r->gw, peer); } else if ((r->type & ROUTE_DSTDNS0) && !ncpaddr_equal(&dst, peer)) { if (bundle->ncp.ipcp.ns.dns[0].s_addr == INADDR_NONE) continue; rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0); if (r->type & ROUTE_GWHISADDR) ncpaddr_copy(&r->gw, peer); } else if ((r->type & ROUTE_DSTDNS1) && !ncpaddr_equal(&dst, peer)) { if (bundle->ncp.ipcp.ns.dns[1].s_addr == INADDR_NONE) continue; rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0); if (r->type & ROUTE_GWHISADDR) ncpaddr_copy(&r->gw, peer); } else if ((r->type & ROUTE_GWHISADDR) && !ncpaddr_equal(&r->gw, peer)) ncpaddr_copy(&r->gw, peer); #ifndef NOINET6 } else if (ncpaddr_family(me) == AF_INET6) { if ((r->type & ROUTE_DSTMYADDR6) && !ncpaddr_equal(&dst, me)) { rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0); ncprange_sethost(&r->dst, me); if (r->type & ROUTE_GWHISADDR) ncpaddr_copy(&r->gw, peer); } else if ((r->type & ROUTE_DSTHISADDR6) && !ncpaddr_equal(&dst, peer)) { rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0); ncprange_sethost(&r->dst, peer); if (r->type & ROUTE_GWHISADDR) ncpaddr_copy(&r->gw, peer); } else if ((r->type & ROUTE_GWHISADDR6) && !ncpaddr_equal(&r->gw, peer)) ncpaddr_copy(&r->gw, peer); #endif } rt_Set(bundle, RTM_ADD, &r->dst, &r->gw, 1, 0); } }
const char * ncprange_ntoa(const struct ncprange *range) { char *res; struct ncpaddr addr; int len; if (!ncprange_getaddr(range, &addr)) return "<AF_UNSPEC>"; res = ncpaddr_ntowa(&addr); len = strlen(res); if (len >= NCP_ASCIIBUFFERSIZE - 1) return res; switch (range->ncprange_family) { case AF_INET: if (range->ncprange_ip4width == -1) { /* A non-contiguous mask */ for (; len >= 3; res[len -= 2] = '\0') if (strcmp(res + len - 2, ".0")) break; snprintf(res + len, sizeof res - len, "&0x%08lx", (unsigned long)ntohl(range->ncprange_ip4mask.s_addr)); } else if (range->ncprange_ip4width < 32) snprintf(res + len, sizeof res - len, "/%d", range->ncprange_ip4width); return res; #ifndef NOINET6 case AF_INET6: if (range->ncprange_ip6width != 128) snprintf(res + len, sizeof res - len, "/%d", range->ncprange_ip6width); return res; #endif } return "<AF_UNSPEC>"; }
int iface_Show(struct cmdargs const *arg) { struct ncpaddr ncpaddr; struct iface *iface = arg->bundle->iface, *current; unsigned f; int flags; #ifndef NOINET6 int scopeid, width; #endif struct in_addr mask; current = iface_Create(iface->name); flags = iface->flags = current->flags; iface_Free(current); prompt_Printf(arg->prompt, "%s (idx %d) <", iface->name, iface->index); for (f = 0; f < sizeof if_flags / sizeof if_flags[0]; f++) if ((if_flags[f].flag & flags)) { prompt_Printf(arg->prompt, "%s%s", flags == iface->flags ? "" : ",", if_flags[f].value); flags &= ~if_flags[f].flag; } #if 0 if (flags) prompt_Printf(arg->prompt, "%s0x%x", flags == iface->flags ? "" : ",", flags); #endif prompt_Printf(arg->prompt, "> mtu %lu has %d address%s:\n", iface->mtu, iface->addrs, iface->addrs == 1 ? "" : "es"); for (f = 0; f < iface->addrs; f++) { ncprange_getaddr(&iface->addr[f].ifa, &ncpaddr); switch (ncprange_family(&iface->addr[f].ifa)) { case AF_INET: prompt_Printf(arg->prompt, " inet %s --> ", ncpaddr_ntoa(&ncpaddr)); if (ncpaddr_family(&iface->addr[f].peer) == AF_UNSPEC) prompt_Printf(arg->prompt, "255.255.255.255"); else prompt_Printf(arg->prompt, "%s", ncpaddr_ntoa(&iface->addr[f].peer)); ncprange_getip4mask(&iface->addr[f].ifa, &mask); prompt_Printf(arg->prompt, " netmask 0x%08lx", (long)ntohl(mask.s_addr)); break; #ifndef NOINET6 case AF_INET6: prompt_Printf(arg->prompt, " inet6 %s", ncpaddr_ntoa(&ncpaddr)); if (ncpaddr_family(&iface->addr[f].peer) != AF_UNSPEC) prompt_Printf(arg->prompt, " --> %s", ncpaddr_ntoa(&iface->addr[f].peer)); ncprange_getwidth(&iface->addr[f].ifa, &width); if (ncpaddr_family(&iface->addr[f].peer) == AF_UNSPEC) prompt_Printf(arg->prompt, " prefixlen %d", width); if ((scopeid = ncprange_scopeid(&iface->addr[f].ifa)) != -1) prompt_Printf(arg->prompt, " scopeid 0x%x", (unsigned)scopeid); break; #endif } prompt_Printf(arg->prompt, "\n"); } return 0; }
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; }