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); } }
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 filter_AdjustAddr(struct filter *filter, struct ncpaddr *local, struct ncpaddr *remote, struct in_addr *dns) { struct filterent *fp; int n; for (fp = filter->rule, n = 0; n < MAXFILTERS; fp++, n++) if (fp->f_action != A_NONE) { if (local) { if (fp->f_srctype == T_MYADDR && ncpaddr_family(local) == AF_INET) ncprange_sethost(&fp->f_src, local); if (fp->f_dsttype == T_MYADDR && ncpaddr_family(local) == AF_INET) ncprange_sethost(&fp->f_dst, local); #ifndef NOINET6 if (fp->f_srctype == T_MYADDR6 && ncpaddr_family(local) == AF_INET6) ncprange_sethost(&fp->f_src, local); if (fp->f_dsttype == T_MYADDR6 && ncpaddr_family(local) == AF_INET6) ncprange_sethost(&fp->f_dst, local); #endif } if (remote) { if (fp->f_srctype == T_HISADDR && ncpaddr_family(remote) == AF_INET) ncprange_sethost(&fp->f_src, remote); if (fp->f_dsttype == T_HISADDR && ncpaddr_family(remote) == AF_INET) ncprange_sethost(&fp->f_dst, remote); #ifndef NOINET6 if (fp->f_srctype == T_HISADDR6 && ncpaddr_family(remote) == AF_INET6) ncprange_sethost(&fp->f_src, remote); if (fp->f_dsttype == T_HISADDR6 && ncpaddr_family(remote) == AF_INET6) ncprange_sethost(&fp->f_dst, remote); #endif } if (dns) { if (fp->f_srctype == T_DNS0) ncprange_setip4host(&fp->f_src, dns[0]); if (fp->f_dsttype == T_DNS0) ncprange_setip4host(&fp->f_dst, dns[0]); if (fp->f_srctype == T_DNS1) ncprange_setip4host(&fp->f_src, dns[1]); if (fp->f_dsttype == T_DNS1) ncprange_setip4host(&fp->f_dst, dns[1]); } } }
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; }
static int iface_addr_Add(const char *name, struct iface_addr *addr, int s) { struct ifaliasreq ifra; #ifndef NOINET6 struct in6_aliasreq ifra6; #endif struct sockaddr_in *me4, *msk4, *peer4; struct sockaddr_storage ssme, sspeer, ssmsk; int res; ncprange_getsa(&addr->ifa, &ssme, &ssmsk); ncpaddr_getsa(&addr->peer, &sspeer); res = 0; switch (ncprange_family(&addr->ifa)) { case AF_INET: memset(&ifra, '\0', sizeof ifra); strncpy(ifra.ifra_name, name, sizeof ifra.ifra_name - 1); me4 = (struct sockaddr_in *)&ifra.ifra_addr; memcpy(me4, &ssme, sizeof *me4); msk4 = (struct sockaddr_in *)&ifra.ifra_mask; memcpy(msk4, &ssmsk, sizeof *msk4); peer4 = (struct sockaddr_in *)&ifra.ifra_broadaddr; if (ncpaddr_family(&addr->peer) == AF_UNSPEC) { peer4->sin_family = AF_INET; peer4->sin_len = sizeof(*peer4); peer4->sin_addr.s_addr = INADDR_NONE; } else memcpy(peer4, &sspeer, sizeof *peer4); res = ID0ioctl(s, SIOCAIFADDR, &ifra); if (log_IsKept(LogDEBUG)) { char buf[100]; snprintf(buf, sizeof buf, "%s", ncprange_ntoa(&addr->ifa)); log_Printf(LogWARN, "%s: AIFADDR %s -> %s returns %d\n", ifra.ifra_name, buf, ncpaddr_ntoa(&addr->peer), res); } break; #ifndef NOINET6 case AF_INET6: memset(&ifra6, '\0', sizeof ifra6); strncpy(ifra6.ifra_name, name, sizeof ifra6.ifra_name - 1); memcpy(&ifra6.ifra_addr, &ssme, sizeof ifra6.ifra_addr); memcpy(&ifra6.ifra_prefixmask, &ssmsk, sizeof ifra6.ifra_prefixmask); if (ncpaddr_family(&addr->peer) == AF_UNSPEC) ifra6.ifra_dstaddr.sin6_family = AF_UNSPEC; else if (memcmp(&((struct sockaddr_in6 *)&ssmsk)->sin6_addr, &in6mask128, sizeof in6mask128) == 0) memcpy(&ifra6.ifra_dstaddr, &sspeer, sizeof ifra6.ifra_dstaddr); ifra6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; ifra6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; res = ID0ioctl(s, SIOCAIFADDR_IN6, &ifra6); break; #endif } if (res == -1) { char dst[40]; const char *end = #ifndef NOINET6 ncprange_family(&addr->ifa) == AF_INET6 ? "_IN6" : #endif ""; if (ncpaddr_family(&addr->peer) == AF_UNSPEC) log_Printf(LogWARN, "iface add: ioctl(SIOCAIFADDR%s, %s): %s\n", end, ncprange_ntoa(&addr->ifa), strerror(errno)); else { snprintf(dst, sizeof dst, "%s", ncpaddr_ntoa(&addr->peer)); log_Printf(LogWARN, "iface add: ioctl(SIOCAIFADDR%s, %s -> %s): %s\n", end, ncprange_ntoa(&addr->ifa), dst, strerror(errno)); } } return res != -1; }