int _intf_get_noalias(intf_t *intf, struct intf_entry *entry) { struct lifreq lifr; /* Get interface index. */ entry->intf_index = if_nametoindex(entry->intf_name); if (entry->intf_index == 0) return (-1); strlcpy(lifr.lifr_name, entry->intf_name, sizeof(lifr.lifr_name)); /* Get interface flags. */ if (ioctl(intf->fd, SIOCGLIFFLAGS, &lifr) < 0) return (-1); entry->intf_flags = intf_iff_to_flags(lifr.lifr_flags); _intf_set_type(entry); /* Get interface MTU. */ #ifdef SIOCSIFMTU if (ioctl(intf->fd, SIOCGLIFMTU, &lifr) < 0) #endif return (-1); entry->intf_mtu = lifr.lifr_mtu; entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type = entry->intf_link_addr.addr_type = ADDR_TYPE_NONE; /* Get primary interface address. */ if (ioctl(intf->fd, SIOCGLIFADDR, &lifr) == 0) { addr_ston((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr); if (ioctl(intf->fd, SIOCGLIFNETMASK, &lifr) < 0) return (-1); addr_stob((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr.addr_bits); } /* Get other addresses. */ if (entry->intf_type == INTF_TYPE_TUN) { if (ioctl(intf->fd, SIOCGLIFDSTADDR, &lifr) == 0) { if (addr_ston((struct sockaddr *)&lifr.lifr_addr, &entry->intf_dst_addr) < 0) return (-1); } } else if (entry->intf_type == INTF_TYPE_ETH) { eth_t *eth; if ((eth = eth_open(entry->intf_name)) != NULL) { if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) { entry->intf_link_addr.addr_type = ADDR_TYPE_ETH; entry->intf_link_addr.addr_bits = ETH_ADDR_BITS; } eth_close(eth); } } return (0); }
static int _radix_walk(int fd, struct radix_node *rn, route_handler callback, void *arg) { struct radix_node rnode; struct rtentry rt; struct sockaddr_in sin; struct route_entry entry; int ret = 0; again: _kread(fd, rn, &rnode, sizeof(rnode)); if (rnode.rn_b < 0) { if (!(rnode.rn_flags & RNF_ROOT)) { entry.intf_name[0] = '\0'; _kread(fd, rn, &rt, sizeof(rt)); _kread(fd, rt_key(&rt), &sin, sizeof(sin)); addr_ston((struct sockaddr *)&sin, &entry.route_dst); if (!(rt.rt_flags & RTF_HOST)) { _kread(fd, rt_mask(&rt), &sin, sizeof(sin)); addr_stob((struct sockaddr *)&sin, &entry.route_dst.addr_bits); } _kread(fd, rt.rt_gateway, &sin, sizeof(sin)); addr_ston((struct sockaddr *)&sin, &entry.route_gw); entry.metric = 0; if ((ret = callback(&entry, arg)) != 0) return (ret); } if ((rn = rnode.rn_dupedkey)) goto again; } else { rn = rnode.rn_r; if ((ret = _radix_walk(fd, rnode.rn_l, callback, arg)) != 0) return (ret); if ((ret = _radix_walk(fd, rn, callback, arg)) != 0) return (ret); } return (ret); }
static int _intf_get_aliases(intf_t *intf, struct intf_entry *entry) { struct ifreq *ifr, *lifr; struct ifreq tmpifr; struct addr *ap, *lap; char *p; if (intf->ifc.ifc_len < (int)sizeof(*ifr)) { errno = EINVAL; return (-1); } entry->intf_alias_num = 0; ap = entry->intf_alias_addrs; lifr = (struct ifreq *)intf->ifc.ifc_buf + (intf->ifc.ifc_len / sizeof(*lifr)); lap = (struct addr *)((u_char *)entry + entry->intf_len); /* Get addresses for this interface. */ for (ifr = intf->ifc.ifc_req; ifr < lifr && (ap + 1) < lap; ifr = NEXTIFR(ifr)) { /* XXX - Linux, Solaris ifaliases */ if ((p = strchr(ifr->ifr_name, ':')) != NULL) *p = '\0'; if (strcmp(ifr->ifr_name, entry->intf_name) != 0) { if (p) *p = ':'; continue; } if (p) *p = ':'; /* Fix the name back up */ if (addr_ston(&ifr->ifr_addr, ap) < 0) continue; /* XXX */ if (ap->addr_type == ADDR_TYPE_ETH) { memcpy(&entry->intf_link_addr, ap, sizeof(*ap)); continue; } else if (ap->addr_type == ADDR_TYPE_IP) { if (ap->addr_ip == entry->intf_addr.addr_ip || ap->addr_ip == entry->intf_dst_addr.addr_ip) continue; strlcpy(tmpifr.ifr_name, ifr->ifr_name, sizeof(tmpifr.ifr_name)); if (ioctl(intf->fd, SIOCGIFNETMASK, &tmpifr) == 0) addr_stob(&tmpifr.ifr_addr, &ap->addr_bits); } #ifdef SIOCGIFNETMASK_IN6 else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) { struct in6_ifreq ifr6; /* XXX - sizeof(ifr) < sizeof(ifr6) */ memcpy(&ifr6, ifr, sizeof(ifr6)); if (ioctl(intf->fd6, SIOCGIFNETMASK_IN6, &ifr6) == 0) { addr_stob((struct sockaddr *)&ifr6.ifr_addr, &ap->addr_bits); } else perror("SIOCGIFNETMASK_IN6"); } #endif ap++, entry->intf_alias_num++; } entry->intf_len = (u_char *)ap - (u_char *)entry; return (0); }
static int _intf_get_noalias(intf_t *intf, struct intf_entry *entry) { struct ifreq ifr; strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name)); /* Get interface flags. */ if (ioctl(intf->fd, SIOCGIFFLAGS, &ifr) < 0) return (-1); entry->intf_flags = intf_iff_to_flags(ifr.ifr_flags); _intf_set_type(entry); /* Get interface MTU. */ #ifdef SIOCGIFMTU if (ioctl(intf->fd, SIOCGIFMTU, &ifr) < 0) #endif return (-1); entry->intf_mtu = ifr.ifr_mtu; entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type = entry->intf_link_addr.addr_type = ADDR_TYPE_NONE; /* Get primary interface address. */ if (ioctl(intf->fd, SIOCGIFADDR, &ifr) == 0) { addr_ston(&ifr.ifr_addr, &entry->intf_addr); if (ioctl(intf->fd, SIOCGIFNETMASK, &ifr) < 0) return (-1); addr_stob(&ifr.ifr_addr, &entry->intf_addr.addr_bits); } /* Get other addresses. */ if (entry->intf_type == INTF_TYPE_TUN) { if (ioctl(intf->fd, SIOCGIFDSTADDR, &ifr) == 0) { if (addr_ston(&ifr.ifr_addr, &entry->intf_dst_addr) < 0) return (-1); } } else if (entry->intf_type == INTF_TYPE_ETH) { #if defined(SIOCGIFHWADDR) if (ioctl(intf->fd, SIOCGIFHWADDR, &ifr) < 0) return (-1); if (addr_ston(&ifr.ifr_addr, &entry->intf_link_addr) < 0) return (-1); #elif defined(SIOCRPHYSADDR) /* Tru64 */ struct ifdevea *ifd = (struct ifdevea *)𝔦 /* XXX */ if (ioctl(intf->fd, SIOCRPHYSADDR, ifd) < 0) return (-1); addr_pack(&entry->intf_link_addr, ADDR_TYPE_ETH, ETH_ADDR_BITS, ifd->current_pa, ETH_ADDR_LEN); #else eth_t *eth; if ((eth = eth_open(entry->intf_name)) != NULL) { if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) { entry->intf_link_addr.addr_type = ADDR_TYPE_ETH; entry->intf_link_addr.addr_bits = ETH_ADDR_BITS; } eth_close(eth); } #endif } return (0); }
int route_loop(route_t *r, route_handler callback, void *arg) { struct route_entry entry; struct strbuf msg; struct T_optmgmt_req *tor; struct T_optmgmt_ack *toa; struct T_error_ack *tea; struct opthdr *opt; u_char buf[8192]; int flags, rc, rtable, ret; tor = (struct T_optmgmt_req *)buf; toa = (struct T_optmgmt_ack *)buf; tea = (struct T_error_ack *)buf; tor->PRIM_type = T_OPTMGMT_REQ; tor->OPT_offset = sizeof(*tor); tor->OPT_length = sizeof(*opt); tor->MGMT_flags = T_CURRENT; opt = (struct opthdr *)(tor + 1); opt->level = MIB2_IP; opt->name = opt->len = 0; msg.maxlen = sizeof(buf); msg.len = sizeof(*tor) + sizeof(*opt); msg.buf = buf; if (putmsg(r->ip_fd, &msg, NULL, 0) < 0) return (-1); opt = (struct opthdr *)(toa + 1); msg.maxlen = sizeof(buf); for (;;) { mib2_ipRouteEntry_t *rt, *rtend; flags = 0; if ((rc = getmsg(r->ip_fd, &msg, NULL, &flags)) < 0) return (-1); /* See if we're finished. */ if (rc == 0 && msg.len >= sizeof(*toa) && toa->PRIM_type == T_OPTMGMT_ACK && toa->MGMT_flags == T_SUCCESS && opt->len == 0) break; if (msg.len >= sizeof(*tea) && tea->PRIM_type == T_ERROR_ACK) return (-1); if (rc != MOREDATA || msg.len < (int)sizeof(*toa) || toa->PRIM_type != T_OPTMGMT_ACK || toa->MGMT_flags != T_SUCCESS) return (-1); rtable = (opt->level == MIB2_IP && opt->name == MIB2_IP_21); msg.maxlen = sizeof(buf) - (sizeof(buf) % sizeof(*rt)); msg.len = 0; flags = 0; do { struct sockaddr_in sin; rc = getmsg(r->ip_fd, NULL, &msg, &flags); if (rc != 0 && rc != MOREDATA) return (-1); if (!rtable) continue; rt = (mib2_ipRouteEntry_t *)msg.buf; rtend = (mib2_ipRouteEntry_t *)(msg.buf + msg.len); sin.sin_family = AF_INET; for ( ; rt < rtend; rt++) { if ((rt->ipRouteInfo.re_ire_type & (IRE_BROADCAST|IRE_ROUTE_REDIRECT| IRE_LOCAL|IRE_ROUTE)) != 0 || rt->ipRouteNextHop == IP_ADDR_ANY) continue; sin.sin_addr.s_addr = rt->ipRouteNextHop; addr_ston((struct sockaddr *)&sin, &entry.route_gw); sin.sin_addr.s_addr = rt->ipRouteDest; addr_ston((struct sockaddr *)&sin, &entry.route_dst); sin.sin_addr.s_addr = rt->ipRouteMask; addr_stob((struct sockaddr *)&sin, &entry.route_dst.addr_bits); if ((ret = callback(&entry, arg)) != 0) return (ret); } } while (rc == MOREDATA); } tor = (struct T_optmgmt_req *)buf; toa = (struct T_optmgmt_ack *)buf; tea = (struct T_error_ack *)buf; tor->PRIM_type = T_OPTMGMT_REQ; tor->OPT_offset = sizeof(*tor); tor->OPT_length = sizeof(*opt); tor->MGMT_flags = T_CURRENT; opt = (struct opthdr *)(tor + 1); opt->level = MIB2_IP6; opt->name = opt->len = 0; msg.maxlen = sizeof(buf); msg.len = sizeof(*tor) + sizeof(*opt); msg.buf = buf; if (putmsg(r->ip_fd, &msg, NULL, 0) < 0) return (-1); opt = (struct opthdr *)(toa + 1); msg.maxlen = sizeof(buf); for (;;) { mib2_ipv6RouteEntry_t *rt, *rtend; flags = 0; if ((rc = getmsg(r->ip_fd, &msg, NULL, &flags)) < 0) return (-1); /* See if we're finished. */ if (rc == 0 && msg.len >= sizeof(*toa) && toa->PRIM_type == T_OPTMGMT_ACK && toa->MGMT_flags == T_SUCCESS && opt->len == 0) break; if (msg.len >= sizeof(*tea) && tea->PRIM_type == T_ERROR_ACK) return (-1); if (rc != MOREDATA || msg.len < (int)sizeof(*toa) || toa->PRIM_type != T_OPTMGMT_ACK || toa->MGMT_flags != T_SUCCESS) return (-1); rtable = (opt->level == MIB2_IP6 && opt->name == MIB2_IP6_ROUTE); msg.maxlen = sizeof(buf) - (sizeof(buf) % sizeof(*rt)); msg.len = 0; flags = 0; do { struct sockaddr_in6 sin6; rc = getmsg(r->ip_fd, NULL, &msg, &flags); if (rc != 0 && rc != MOREDATA) return (-1); if (!rtable) continue; rt = (mib2_ipv6RouteEntry_t *)msg.buf; rtend = (mib2_ipv6RouteEntry_t *)(msg.buf + msg.len); sin6.sin6_family = AF_INET6; for ( ; rt < rtend; rt++) { if ((rt->ipv6RouteInfo.re_ire_type & (IRE_BROADCAST|IRE_ROUTE_REDIRECT| IRE_LOCAL|IRE_ROUTE)) != 0 || memcmp(&rt->ipv6RouteNextHop, IP6_ADDR_UNSPEC, IP6_ADDR_LEN) == 0) continue; sin6.sin6_addr = rt->ipv6RouteNextHop; addr_ston((struct sockaddr *)&sin6, &entry.route_gw); sin6.sin6_addr = rt->ipv6RouteDest; addr_ston((struct sockaddr *)&sin6, &entry.route_dst); entry.route_dst.addr_bits = rt->ipv6RoutePfxLength; if ((ret = callback(&entry, arg)) != 0) return (ret); } } while (rc == MOREDATA); } return (0); }
int route_loop(route_t *r, route_handler callback, void *arg) { struct rt_msghdr *rtm; struct route_entry entry; struct sockaddr *sa; char *buf, *lim, *next; int ret; #ifdef HAVE_SYS_SYSCTL_H int mib[6] = { CTL_NET, PF_ROUTE, 0, 0 /* XXX */, NET_RT_DUMP, 0 }; size_t len; if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) return (-1); if (len == 0) return (0); if ((buf = malloc(len)) == NULL) return (-1); if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { free(buf); return (-1); } lim = buf + len; next = buf; #elif defined(HAVE_GETKERNINFO) int len = getkerninfo(KINFO_RT_DUMP,0,0,0); if (len == 0) return (0); if ((buf = malloc(len)) == NULL) return (-1); if (getkerninfo(KINFO_RT_DUMP,buf,&len,0) < 0) { free(buf); return (-1); } lim = buf + len; next = buf; #else /* HAVE_STREAMS_ROUTE */ struct rt_giarg giarg, *gp; memset(&giarg, 0, sizeof(giarg)); giarg.gi_op = KINFO_RT_DUMP; if (ioctl(r->fd, RTSTR_GETROUTE, &giarg) < 0) return (-1); if ((buf = malloc(giarg.gi_size)) == NULL) return (-1); gp = (struct rt_giarg *)buf; gp->gi_size = giarg.gi_size; gp->gi_op = KINFO_RT_DUMP; gp->gi_where = buf; gp->gi_arg = RTF_UP | RTF_GATEWAY; if (ioctl(r->fd, RTSTR_GETROUTE, buf) < 0) { free(buf); return (-1); } lim = buf + gp->gi_size; next = buf + sizeof(giarg); #endif /* This loop assumes that RTA_DST, RTA_GATEWAY, and RTA_NETMASK have the * values, 1, 2, and 4 respectively. Cf. Unix Network Programming, * p. 494, function get_rtaddrs. */ for (ret = 0; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; sa = (struct sockaddr *)(rtm + 1); if ((rtm->rtm_addrs & RTA_DST) == 0) /* Need a destination. */ continue; if (addr_ston(sa, &entry.route_dst) < 0) continue; if ((rtm->rtm_addrs & RTA_GATEWAY) == 0) /* Need a gateway. */ continue; sa = NEXTSA(sa); if (addr_ston_gateway(&entry.route_dst, sa, &entry.route_gw) < 0) continue; if (entry.route_dst.addr_type != entry.route_gw.addr_type || (entry.route_dst.addr_type != ADDR_TYPE_IP && entry.route_dst.addr_type != ADDR_TYPE_IP6)) continue; if (rtm->rtm_addrs & RTA_NETMASK) { sa = NEXTSA(sa); if (addr_stob(sa, &entry.route_dst.addr_bits) < 0) continue; } if ((ret = callback(&entry, arg)) != 0) break; } free(buf); return (ret); }
static Bool RecordRoutingInfoIPv4(NicInfoV3 *nicInfo) { GPtrArray *routes = NULL; guint i; Bool ret = FALSE; if ((routes = SlashProcNet_GetRoute()) == NULL) { return FALSE; } for (i = 0; i < routes->len; i++) { struct rtentry *rtentry; struct sockaddr_in *sin_dst; struct sockaddr_in *sin_gateway; struct sockaddr_in *sin_genmask; InetCidrRouteEntry *icre; uint32_t ifIndex; /* Check to see if we're going above our limit. See bug 605821. */ if (nicInfo->routes.routes_len == NICINFO_MAX_ROUTES) { g_message("%s: route limit (%d) reached, skipping overflow.", __FUNCTION__, NICINFO_MAX_ROUTES); break; } rtentry = g_ptr_array_index(routes, i); if ((rtentry->rt_flags & RTF_UP) == 0 || !GuestInfoGetNicInfoIfIndex(nicInfo, if_nametoindex(rtentry->rt_dev), &ifIndex)) { continue; } icre = XDRUTIL_ARRAYAPPEND(nicInfo, routes, 1); ASSERT_MEM_ALLOC(icre); sin_dst = (struct sockaddr_in *)&rtentry->rt_dst; sin_gateway = (struct sockaddr_in *)&rtentry->rt_gateway; sin_genmask = (struct sockaddr_in *)&rtentry->rt_genmask; GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin_dst, &icre->inetCidrRouteDest); addr_stob((struct sockaddr *)sin_genmask, (uint16_t *)&icre->inetCidrRoutePfxLen); /* * Gateways are optional (ex: one can bind a route to an interface w/o * specifying a next hop address). */ if (rtentry->rt_flags & RTF_GATEWAY) { TypedIpAddress *ip = Util_SafeCalloc(1, sizeof *ip); GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin_gateway, ip); icre->inetCidrRouteNextHop = ip; } /* * Interface, metric. */ icre->inetCidrRouteIfIndex = ifIndex; icre->inetCidrRouteMetric = rtentry->rt_metric; } ret = TRUE; SlashProcNet_FreeRoute(routes); return ret; }
static int _intf_get_aliases(intf_t *intf, struct intf_entry *entry) { struct ifreq *ifr, *lifr; struct ifreq tmpifr; struct addr *ap, *lap; char *p; if (intf->ifc.ifc_len < (int)sizeof(*ifr)) { errno = EINVAL; return (-1); } entry->intf_alias_num = 0; ap = entry->intf_alias_addrs; lifr = (struct ifreq *)intf->ifc.ifc_buf + (intf->ifc.ifc_len / sizeof(*lifr)); lap = (struct addr *)((u_char *)entry + entry->intf_len); /* Get addresses for this interface. */ for (ifr = intf->ifc.ifc_req; ifr < lifr && (ap + 1) < lap; ifr = NEXTIFR(ifr)) { /* XXX - Linux, Solaris ifaliases */ if ((p = strchr(ifr->ifr_name, ':')) != NULL) *p = '\0'; if (strcmp(ifr->ifr_name, entry->intf_name) != 0) { if (p) *p = ':'; continue; } /* Fix the name back up */ if (p) *p = ':'; if (addr_ston(&ifr->ifr_addr, ap) < 0) continue; /* XXX */ if (ap->addr_type == ADDR_TYPE_ETH) { memcpy(&entry->intf_link_addr, ap, sizeof(*ap)); continue; } else if (ap->addr_type == ADDR_TYPE_IP) { if (ap->addr_ip == entry->intf_addr.addr_ip || ap->addr_ip == entry->intf_dst_addr.addr_ip) continue; strlcpy(tmpifr.ifr_name, ifr->ifr_name, sizeof(tmpifr.ifr_name)); if (ioctl(intf->fd, SIOCGIFNETMASK, &tmpifr) == 0) addr_stob(&tmpifr.ifr_addr, &ap->addr_bits); } #ifdef SIOCGIFNETMASK_IN6 else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) { struct in6_ifreq ifr6; /* XXX - sizeof(ifr) < sizeof(ifr6) */ memcpy(&ifr6, ifr, sizeof(ifr6)); if (ioctl(intf->fd6, SIOCGIFNETMASK_IN6, &ifr6) == 0) { addr_stob((struct sockaddr *)&ifr6.ifr_addr, &ap->addr_bits); } else perror("SIOCGIFNETMASK_IN6"); } #else #ifdef SIOCGIFNETMASK6 else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) { struct in6_ifreq ifr6; /* XXX - sizeof(ifr) < sizeof(ifr6) */ memcpy(&ifr6, ifr, sizeof(ifr6)); if (ioctl(intf->fd6, SIOCGIFNETMASK6, &ifr6) == 0) { /* For some reason this is 0 after the ioctl. */ ifr6.ifr_Addr.sin6_family = AF_INET6; addr_stob((struct sockaddr *)&ifr6.ifr_Addr, &ap->addr_bits); } else perror("SIOCGIFNETMASK6"); } #endif #endif ap++, entry->intf_alias_num++; } #ifdef HAVE_LINUX_PROCFS #define PROC_INET6_FILE "/proc/net/if_inet6" { FILE *f; char buf[256], s[8][5], name[INTF_NAME_LEN]; u_int idx, bits, scope, flags; if ((f = fopen(PROC_INET6_FILE, "r")) != NULL) { while (ap < lap && fgets(buf, sizeof(buf), f) != NULL) { sscanf(buf, "%04s%04s%04s%04s%04s%04s%04s%04s %x %02x %02x %02x %32s\n", s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], &idx, &bits, &scope, &flags, name); if (strcmp(name, entry->intf_name) == 0) { snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d", s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], bits); addr_aton(buf, ap); ap++, entry->intf_alias_num++; } } fclose(f); } } #endif entry->intf_len = (u_char *)ap - (u_char *)entry; return (0); }
int _intf_get_noalias(intf_t *intf, struct intf_entry *entry) { struct lifreq lifr; int fd; /* Get interface index. */ entry->intf_index = if_nametoindex(entry->intf_name); if (entry->intf_index == 0) return (-1); strlcpy(lifr.lifr_name, entry->intf_name, sizeof(lifr.lifr_name)); /* Get interface flags. Here he also check whether we need to use fd or * fd6 in the rest of the function. Using the wrong address family in * the ioctls gives ENXIO on Solaris. */ if (ioctl(intf->fd, SIOCGLIFFLAGS, &lifr) >= 0) fd = intf->fd; else if (intf->fd6 != -1 && ioctl(intf->fd6, SIOCGLIFFLAGS, &lifr) >= 0) fd = intf->fd6; else return (-1); entry->intf_flags = intf_iff_to_flags(lifr.lifr_flags); _intf_set_type(entry); /* Get interface MTU. */ #ifdef SIOCGLIFMTU if (ioctl(fd, SIOCGLIFMTU, &lifr) < 0) #endif return (-1); entry->intf_mtu = lifr.lifr_mtu; entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type = entry->intf_link_addr.addr_type = ADDR_TYPE_NONE; /* Get primary interface address. */ if (ioctl(fd, SIOCGLIFADDR, &lifr) == 0) { addr_ston((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr); if (ioctl(fd, SIOCGLIFNETMASK, &lifr) < 0) return (-1); addr_stob((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr.addr_bits); } /* Get other addresses. */ if (entry->intf_type == INTF_TYPE_TUN) { if (ioctl(fd, SIOCGLIFDSTADDR, &lifr) == 0) { if (addr_ston((struct sockaddr *)&lifr.lifr_addr, &entry->intf_dst_addr) < 0) return (-1); } } else if (entry->intf_type == INTF_TYPE_ETH) { eth_t *eth; if ((eth = eth_open(entry->intf_name)) != NULL) { if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) { entry->intf_link_addr.addr_type = ADDR_TYPE_ETH; entry->intf_link_addr.addr_bits = ETH_ADDR_BITS; } eth_close(eth); } } return (0); }
static int _intf_get_noalias(intf_t *intf, struct intf_entry *entry) { struct ifreq ifr; #ifdef HAVE_GETKERNINFO int size; struct kinfo_ndd *nddp; void *end; #endif /* Get interface index. */ entry->intf_index = if_nametoindex(entry->intf_name); if (entry->intf_index == 0) return (-1); strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name)); /* Get interface flags. */ if (ioctl(intf->fd, SIOCGIFFLAGS, &ifr) < 0) return (-1); entry->intf_flags = intf_iff_to_flags(ifr.ifr_flags); _intf_set_type(entry); /* Get interface MTU. */ #ifdef SIOCGIFMTU if (ioctl(intf->fd, SIOCGIFMTU, &ifr) < 0) #endif return (-1); entry->intf_mtu = ifr.ifr_mtu; entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type = entry->intf_link_addr.addr_type = ADDR_TYPE_NONE; /* Get primary interface address. */ if (ioctl(intf->fd, SIOCGIFADDR, &ifr) == 0) { addr_ston(&ifr.ifr_addr, &entry->intf_addr); if (ioctl(intf->fd, SIOCGIFNETMASK, &ifr) < 0) return (-1); addr_stob(&ifr.ifr_addr, &entry->intf_addr.addr_bits); } /* Get other addresses. */ if (entry->intf_type == INTF_TYPE_TUN) { if (ioctl(intf->fd, SIOCGIFDSTADDR, &ifr) == 0) { if (addr_ston(&ifr.ifr_addr, &entry->intf_dst_addr) < 0) return (-1); } } else if (entry->intf_type == INTF_TYPE_ETH) { #if defined(HAVE_GETKERNINFO) /* AIX also defines SIOCGIFHWADDR, but it fails silently? * This is the method IBM recommends here: * http://www-01.ibm.com/support/knowledgecenter/ssw_aix_53/com.ibm.aix.progcomm/doc/progcomc/skt_sndother_ex.htm%23ssqinc2joyc?lang=en */ /* How many bytes will be returned? */ size = getkerninfo(KINFO_NDD, 0, 0, 0); if (size <= 0) { return -1; } nddp = (struct kinfo_ndd *)malloc(size); if (!nddp) { return -1; } /* Get all Network Device Driver (NDD) info */ if (getkerninfo(KINFO_NDD, nddp, &size, 0) < 0) { free(nddp); return -1; } /* Loop over the returned values until we find a match */ end = (void *)nddp + size; while ((void *)nddp < end) { if (!strcmp(nddp->ndd_alias, entry->intf_name) || !strcmp(nddp->ndd_name, entry->intf_name)) { addr_pack(&entry->intf_link_addr, ADDR_TYPE_ETH, ETH_ADDR_BITS, nddp->ndd_addr, ETH_ADDR_LEN); break; } else nddp++; } free(nddp); #elif defined(SIOCGIFHWADDR) if (ioctl(intf->fd, SIOCGIFHWADDR, &ifr) < 0) return (-1); if (addr_ston(&ifr.ifr_addr, &entry->intf_link_addr) < 0) return (-1); #elif defined(SIOCRPHYSADDR) /* Tru64 */ struct ifdevea *ifd = (struct ifdevea *)𝔦 /* XXX */ if (ioctl(intf->fd, SIOCRPHYSADDR, ifd) < 0) return (-1); addr_pack(&entry->intf_link_addr, ADDR_TYPE_ETH, ETH_ADDR_BITS, ifd->current_pa, ETH_ADDR_LEN); #else eth_t *eth; if ((eth = eth_open(entry->intf_name)) != NULL) { if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) { entry->intf_link_addr.addr_type = ADDR_TYPE_ETH; entry->intf_link_addr.addr_bits = ETH_ADDR_BITS; } eth_close(eth); } #endif } return (0); }
int route_loop(route_t *r, route_handler callback, void *arg) { struct rt_msghdr *rtm; struct route_entry entry; struct sockaddr *sa; char *buf, *lim, *next; int ret; #ifdef HAVE_SYS_SYSCTL_H int mib[6] = { CTL_NET, PF_ROUTE, 0, 0 /* XXX */, NET_RT_DUMP, 0 }; size_t len; if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) return (-1); if (len == 0) return (0); if ((buf = malloc(len)) == NULL) return (-1); if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { free(buf); return (-1); } lim = buf + len; next = buf; #else /* HAVE_STREAMS_ROUTE */ struct rt_giarg giarg, *gp; memset(&giarg, 0, sizeof(giarg)); giarg.gi_op = KINFO_RT_DUMP; if (ioctl(r->fd, RTSTR_GETROUTE, &giarg) < 0) return (-1); if ((buf = malloc(giarg.gi_size)) == NULL) return (-1); gp = (struct rt_giarg *)buf; gp->gi_size = giarg.gi_size; gp->gi_op = KINFO_RT_DUMP; gp->gi_where = buf; gp->gi_arg = RTF_UP | RTF_GATEWAY; if (ioctl(r->fd, RTSTR_GETROUTE, buf) < 0) { free(buf); return (-1); } lim = buf + gp->gi_size; next = buf + sizeof(giarg); #endif for (ret = 0; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; sa = (struct sockaddr *)(rtm + 1); if (addr_ston(sa, &entry.route_dst) < 0 || (rtm->rtm_addrs & RTA_GATEWAY) == 0) continue; sa = NEXTSA(sa); if (addr_ston(sa, &entry.route_gw) < 0) continue; if (entry.route_dst.addr_type != entry.route_gw.addr_type || (entry.route_dst.addr_type != ADDR_TYPE_IP && entry.route_dst.addr_type != ADDR_TYPE_IP6)) continue; if (rtm->rtm_addrs & RTA_NETMASK) { sa = NEXTSA(sa); if (addr_stob(sa, &entry.route_dst.addr_bits) < 0) continue; } if ((ret = callback(&entry, arg)) != 0) break; } free(buf); return (ret); }