/* * arp_SetProxy - Make a proxy ARP entry for the peer. */ int arp_SetProxy(struct bundle *bundle, struct in_addr addr, int s) { struct arpreq arpreq; struct { struct sockaddr_dl sdl; char space[128]; } dls; memset(&arpreq, '\0', sizeof arpreq); /* * Get the hardware address of an interface on the same subnet as our local * address. */ if (!arp_EtherAddr(addr, &dls.sdl, 1)) { log_Printf(LOG_PHASE_BIT, "Cannot determine ethernet address for " "proxy ARP\n"); return 0; } arpreq.arp_ha.sa_len = sizeof(struct sockaddr); arpreq.arp_ha.sa_family = AF_UNSPEC; memcpy(arpreq.arp_ha.sa_data, LLADDR(&dls.sdl), dls.sdl.sdl_alen); SET_SA_FAMILY(arpreq.arp_pa, AF_INET); ((struct sockaddr_in *)&arpreq.arp_pa)->sin_addr.s_addr = addr.s_addr; arpreq.arp_flags = ATF_PERM | ATF_PUBL; if (ID0ioctl(s, SIOCSARP, (caddr_t) & arpreq) < 0) { log_Printf(LogERROR, "arp_SetProxy: ioctl(SIOCSARP): %s\n", strerror(errno)); return 0; } return 1; }
int iface_Name(struct iface *iface, const char *name) { struct ifreq ifr; int s; char *newname; if ((newname = strdup(name)) == NULL) { log_Printf(LogWARN, "iface name: strdup failed: %s\n", strerror(errno)); return 0; } if ((s = ID0socket(PF_INET, SOCK_DGRAM, 0)) == -1) { log_Printf(LogERROR, "iface name: socket(): %s\n", strerror(errno)); free(newname); return 0; } strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); ifr.ifr_data = newname; if (ID0ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) { log_Printf(LogWARN, "iface name: ioctl(SIOCSIFNAME, %s -> %s): %s\n", name, newname, strerror(errno)); free(newname); return 0; } free(iface->name); iface->name = newname; return 1; }
static int iface_ChangeFlags(const char *ifname, int flags, int how) { struct ifreq ifrq; int s, new_flags; s = ID0socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { log_Printf(LogERROR, "iface_ChangeFlags: socket: %s\n", strerror(errno)); return 0; } memset(&ifrq, '\0', sizeof ifrq); strncpy(ifrq.ifr_name, ifname, sizeof ifrq.ifr_name - 1); ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0'; if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) { log_Printf(LogERROR, "iface_ChangeFlags: ioctl(SIOCGIFFLAGS): %s\n", strerror(errno)); close(s); return 0; } #ifdef __FreeBSD__ new_flags = (ifrq.ifr_flags & 0xffff) | (ifrq.ifr_flagshigh << 16); #else new_flags = ifrq.ifr_flags & 0xffff; #endif if (how == IFACE_ADDFLAGS) new_flags |= flags; else new_flags &= ~flags; ifrq.ifr_flags = new_flags & 0xffff; #ifdef __FreeBSD__ ifrq.ifr_flagshigh = new_flags >> 16; #endif if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) { log_Printf(LogERROR, "iface_ChangeFlags: ioctl(SIOCSIFFLAGS): %s\n", strerror(errno)); close(s); return 0; } close(s); return 1; /* Success */ }
static int iface_ChangeFlags(const char *ifname, int flags, int how) { struct ifreq ifrq; int s; s = ID0socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { log_Printf(LogERROR, "iface_ChangeFlags: socket: %s\n", strerror(errno)); return 0; } memset(&ifrq, '\0', sizeof ifrq); strncpy(ifrq.ifr_name, ifname, sizeof ifrq.ifr_name - 1); ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0'; if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) { log_Printf(LogERROR, "iface_ChangeFlags: ioctl(SIOCGIFFLAGS): %s\n", strerror(errno)); close(s); return 0; } if (how == IFACE_ADDFLAGS) ifrq.ifr_flags |= flags; else ifrq.ifr_flags &= ~flags; if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) { log_Printf(LogERROR, "iface_ChangeFlags: ioctl(SIOCSIFFLAGS): %s\n", strerror(errno)); close(s); return 0; } close(s); return 1; /* Success */ }
/* * arp_ClearProxy - Delete the proxy ARP entry for the peer. */ int arp_ClearProxy(struct bundle *bundle, struct in_addr addr, int s) { struct arpreq arpreq; memset(&arpreq, '\0', sizeof arpreq); SET_SA_FAMILY(arpreq.arp_pa, AF_INET); ((struct sockaddr_in *)&arpreq.arp_pa)->sin_addr.s_addr = addr.s_addr; if (ID0ioctl(s, SIOCDARP, (caddr_t) & arpreq) < 0) { log_Printf(LogERROR, "arp_ClearProxy: ioctl(SIOCDARP): %s\n", strerror(errno)); return 0; } return 1; }
void iface_Destroy(struct iface *iface) { struct ifreq ifr; int s; if (iface != NULL) { if ((s = ID0socket(PF_INET, SOCK_DGRAM, 0)) == -1) { log_Printf(LogERROR, "iface_Destroy: socket(): %s\n", strerror(errno)); } else { strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); if (ID0ioctl(s, SIOCIFDESTROY, (caddr_t)&ifr) < 0) log_Printf(LogWARN, "iface_Destroy: ioctl(SIOCIFDESTROY, %s): %s\n", iface->name, strerror(errno)); } iface_Free(iface); } }
void tun_configure(struct bundle *bundle) { #ifdef __NetBSD__ struct ifreq ifr; int s; s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { log_Printf(LogERROR, "tun_configure: socket(): %s\n", strerror(errno)); return; } sprintf(ifr.ifr_name, "tun%d", bundle->unit); ifr.ifr_mtu = bundle->iface->mtu; if (ioctl(s, SIOCSIFMTU, &ifr) < 0) log_Printf(LogERROR, "tun_configure: ioctl(SIOCSIFMTU): %s\n", strerror(errno)); close(s); #else struct tuninfo info; memset(&info, '\0', sizeof info); info.type = IFT_PPP; info.mtu = bundle->iface->mtu; info.baudrate = bundle->bandwidth; #ifdef __OpenBSD__ info.flags = IFF_UP|IFF_POINTOPOINT|IFF_MULTICAST; #endif if (ID0ioctl(bundle->dev.fd, TUNSIFINFO, &info) < 0) log_Printf(LogERROR, "tun_configure: ioctl(TUNSIFINFO): %s\n", strerror(errno)); #endif }
int iface_Descr(struct cmdargs const *arg) { struct ifreq ifr; struct iface *iface; size_t sz, len; int s, n, ifdescr_maxlen; char *descr; sz = sizeof(int); if (sysctlbyname("net.ifdescr_maxlen", &ifdescr_maxlen, &sz, NULL, 0) < 0) { log_Printf(LogERROR, "iface descr: sysctl failed: %s\n", strerror(errno)); return 1; } if (ifdescr_maxlen < 1) { log_Printf(LogERROR, "iface descr: sysctl net.ifdescr_maxlen < 1\n"); return 1; } sz = sizeof(char) * ifdescr_maxlen; if ((descr = malloc(sz)) == NULL) { log_Printf(LogERROR, "iface descr: malloc failed: %s\n", strerror(errno)); return 1; } *descr = '\0'; n = arg->argn; while (n < arg->argc) { if (n > arg->argn && (len = strlcat(descr, " ", sz)) >= sz) break; if ((len = strlcat(descr, arg->argv[n], sz)) >= sz) break; ++n; } if (len >= sz) { log_Printf(LogERROR, "iface descr: description exceeds maximum (%d)\n", ifdescr_maxlen-1); free(descr); return 1; } if ((s = ID0socket(PF_INET, SOCK_DGRAM, 0)) == -1) { log_Printf(LogERROR, "iface descr: socket(): %s\n", strerror(errno)); free(descr); return 1; } iface = arg->bundle->iface; strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); ifr.ifr_buffer.length = strlen(descr) + 1; ifr.ifr_buffer.buffer = descr; if (ID0ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0) { log_Printf(LogWARN, "iface descr: ioctl(SIOCSIFDESCR, %s): %s\n", descr, strerror(errno)); free(descr); return 1; } free(iface->descr); iface->descr = descr; 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; }