int intf_loop(intf_t *intf, intf_handler callback, void *arg) { struct intf_entry *entry; struct lifreq *lifr, *llifr, *plifr; char *p, ebuf[BUFSIZ]; int ret; entry = (struct intf_entry *)ebuf; intf->lifc.lifc_buf = (caddr_t)intf->ifcbuf; intf->lifc.lifc_len = sizeof(intf->ifcbuf); if (ioctl(intf->fd, SIOCGLIFCONF, &intf->lifc) < 0) return (-1); llifr = (struct lifreq *)&intf->lifc.lifc_buf[intf->lifc.lifc_len]; for (lifr = intf->lifc.lifc_req; lifr < llifr; lifr = NEXTLIFR(lifr)) { /* XXX - Linux, Solaris ifaliases */ if ((p = strchr(lifr->lifr_name, ':')) != NULL) *p = '\0'; for (plifr = intf->lifc.lifc_req; plifr < lifr; plifr = NEXTLIFR(lifr)) { if (strcmp(lifr->lifr_name, plifr->lifr_name) == 0) break; } if (lifr > intf->lifc.lifc_req && plifr < llifr) continue; memset(ebuf, 0, sizeof(ebuf)); strlcpy(entry->intf_name, lifr->lifr_name, sizeof(entry->intf_name)); entry->intf_len = sizeof(ebuf); /* Repair the alias name back up */ if (p) *p = ':'; if (_intf_get_noalias(intf, entry) < 0) return (-1); if (_intf_get_aliases(intf, entry) < 0) return (-1); if ((ret = (*callback)(entry, arg)) != 0) return (ret); } return (0); }
int intf_loop(intf_t *intf, intf_handler callback, void *arg) { struct intf_entry *entry; struct lifreq *lifr, *llifr, *plifr; char *p, ebuf[BUFSIZ]; int ret; entry = (struct intf_entry *)ebuf; /* http://www.unix.com/man-page/opensolaris/7p/if_tcp */ intf->lifc.lifc_family = AF_UNSPEC; intf->lifc.lifc_flags = 0; #ifdef LIFC_UNDER_IPMP intf->lifc.lifc_flags |= LIFC_UNDER_IPMP; #endif intf->lifc.lifc_buf = (caddr_t)intf->ifcbuf; intf->lifc.lifc_len = sizeof(intf->ifcbuf); if (ioctl(intf->fd, SIOCGLIFCONF, &intf->lifc) < 0) return (-1); llifr = (struct lifreq *)&intf->lifc.lifc_buf[intf->lifc.lifc_len]; for (lifr = intf->lifc.lifc_req; lifr < llifr; lifr = NEXTLIFR(lifr)) { /* XXX - Linux, Solaris ifaliases */ if ((p = strchr(lifr->lifr_name, ':')) != NULL) *p = '\0'; for (plifr = intf->lifc.lifc_req; plifr < lifr; plifr = NEXTLIFR(lifr)) { if (strcmp(lifr->lifr_name, plifr->lifr_name) == 0) break; } if (lifr > intf->lifc.lifc_req && plifr < lifr) continue; memset(ebuf, 0, sizeof(ebuf)); strlcpy(entry->intf_name, lifr->lifr_name, sizeof(entry->intf_name)); entry->intf_len = sizeof(ebuf); /* Repair the alias name back up */ if (p) *p = ':'; /* Ignore IPMP interfaces. These are virtual interfaces made up * of physical interfaces. IPMP interfaces do not support things * like packet sniffing; it is necessary to use one of the * underlying physical interfaces instead. This works as long as * the physical interface's test address is on the same subnet * as the IPMP interface's address. */ if (ioctl(intf->fd, SIOCGLIFFLAGS, lifr) >= 0) ; else if (intf->fd6 != -1 && ioctl(intf->fd6, SIOCGLIFFLAGS, lifr) >= 0) ; else return (-1); if (lifr->lifr_flags & IFF_IPMP) { continue; } if (_intf_get_noalias(intf, entry) < 0) return (-1); if (_intf_get_aliases(intf, entry) < 0) return (-1); if ((ret = (*callback)(entry, arg)) != 0) return (ret); } return (0); }
static int _intf_get_aliases(intf_t *intf, struct intf_entry *entry) { struct lifreq *lifr, *llifr; struct lifreq tmplifr; struct addr *ap, *lap; char *p; if (intf->lifc.lifc_len < (int)sizeof(*lifr)) { errno = EINVAL; return (-1); } entry->intf_alias_num = 0; ap = entry->intf_alias_addrs; llifr = (struct lifreq *)intf->lifc.lifc_buf + (intf->lifc.lifc_len / sizeof(*llifr)); lap = (struct addr *)((u_char *)entry + entry->intf_len); /* Get addresses for this interface. */ for (lifr = intf->lifc.lifc_req; lifr < llifr && (ap + 1) < lap; lifr = NEXTLIFR(lifr)) { /* XXX - Linux, Solaris ifaliases */ if ((p = strchr(lifr->lifr_name, ':')) != NULL) *p = '\0'; if (strcmp(lifr->lifr_name, entry->intf_name) != 0) { if (p) *p = ':'; continue; } /* Fix the name back up */ if (p) *p = ':'; if (addr_ston((struct sockaddr *)&lifr->lifr_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(tmplifr.lifr_name, lifr->lifr_name, sizeof(tmplifr.lifr_name)); if (ioctl(intf->fd, SIOCGIFNETMASK, &tmplifr) == 0) addr_stob((struct sockaddr *)&tmplifr.lifr_addr, &ap->addr_bits); } else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) { if (memcmp(&ap->addr_ip6, &entry->intf_addr.addr_ip6, IP6_ADDR_LEN) == 0 || memcmp(&ap->addr_ip6, &entry->intf_dst_addr.addr_ip6, IP6_ADDR_LEN) == 0) continue; strlcpy(tmplifr.lifr_name, lifr->lifr_name, sizeof(tmplifr.lifr_name)); if (ioctl(intf->fd6, SIOCGLIFNETMASK, &tmplifr) == 0) { addr_stob((struct sockaddr *)&tmplifr.lifr_addr, &ap->addr_bits); } else perror("SIOCGLIFNETMASK"); } ap++, entry->intf_alias_num++; } entry->intf_len = (u_char *)ap - (u_char *)entry; return (0); }