int intf_loop(intf_t *intf, intf_handler callback, void *arg) { struct intf_entry *entry; struct ifreq *ifr, *lifr, *pifr; char *p, ebuf[BUFSIZ]; int ret; entry = (struct intf_entry *)ebuf; intf->ifc.ifc_buf = (caddr_t)intf->ifcbuf; intf->ifc.ifc_len = sizeof(intf->ifcbuf); if (ioctl(intf->fd, SIOCGIFCONF, &intf->ifc) < 0) return (-1); pifr = NULL; lifr = (struct ifreq *)&intf->ifc.ifc_buf[intf->ifc.ifc_len]; for (ifr = intf->ifc.ifc_req; ifr < lifr; ifr = NEXTIFR(ifr)) { /* XXX - Linux, Solaris ifaliases */ if ((p = strchr(ifr->ifr_name, ':')) != NULL) *p = '\0'; if (pifr != NULL && strcmp(ifr->ifr_name, pifr->ifr_name) == 0) { if (p) *p = ':'; continue; } memset(ebuf, 0, sizeof(ebuf)); strlcpy(entry->intf_name, ifr->ifr_name, sizeof(entry->intf_name)); strlcpy(entry->os_intf_name, ifr->ifr_name, sizeof(entry->os_intf_name)); strlcpy(entry->pcap_intf_name, ifr->ifr_name, sizeof(entry->pcap_intf_name)); intf_get_drv_info(intf, entry); 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); pifr = ifr; } return (0); }
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); }
int libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, int8_t *dev, register int8_t *errbuf) { register struct libnet_ifaddr_list *al; struct ifreq *ifr, *lifr, *pifr, nifr; int8_t device[sizeof(nifr.ifr_name)]; static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR]; char *p; struct ifconf ifc; struct ifreq ibuf[MAX_IPADDR]; register int fd, nipaddr; #ifdef HAVE_LINUX_PROCFS FILE *fp; char buf[2048]; #endif fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): socket error: %s\n", __func__, strerror(errno)); return (-1); } #ifdef HAVE_LINUX_PROCFS if ((fp = fopen(PROC_DEV_FILE, "r")) == NULL) { snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): fopen(proc_dev_file) failed: %s\n", __func__, strerror(errno)); return (-1); } #endif memset(&ifc, 0, sizeof(ifc)); ifc.ifc_len = sizeof(ibuf); ifc.ifc_buf = (caddr_t)ibuf; if(ioctl(fd, SIOCGIFCONF, &ifc) < 0) { snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): ioctl(SIOCGIFCONF) error: %s\n", __func__, strerror(errno)); return(-1); } pifr = NULL; lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len]; al = ifaddrlist; nipaddr = 0; #ifdef HAVE_LINUX_PROCFS while (fgets(buf, sizeof(buf), fp)) { if ((p = strchr(buf, ':')) == NULL) { continue; } *p = '\0'; for(p = buf; *p == ' '; p++) ; strncpy(nifr.ifr_name, p, sizeof(nifr.ifr_name) - 1); nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0'; #else /* !HAVE_LINUX_PROCFS */ for (ifr = ifc.ifc_req; ifr < lifr; ifr = NEXTIFR(ifr)) { /* XXX LINUX SOLARIS ifalias */ if((p = strchr(ifr->ifr_name, ':'))) { *p='\0'; } if (pifr && strcmp(ifr->ifr_name, pifr->ifr_name) == 0) { continue; } strncpy(nifr.ifr_name, ifr->ifr_name, sizeof(nifr.ifr_name) - 1); nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0'; #endif /* save device name */ strncpy(device, nifr.ifr_name, sizeof(device) - 1); device[sizeof(device) - 1] = '\0'; if (ioctl(fd, SIOCGIFFLAGS, &nifr) < 0) { pifr = ifr; continue; } if ((nifr.ifr_flags & IFF_UP) == 0) { pifr = ifr; continue; } if (dev == NULL && LIBNET_ISLOOPBACK(&nifr)) { pifr = ifr; continue; } strncpy(nifr.ifr_name, device, sizeof(device) - 1); nifr.ifr_name[sizeof(nifr.ifr_name) - 1] = '\0'; if (ioctl(fd, SIOCGIFADDR, (int8_t *)&nifr) < 0) { if (errno != EADDRNOTAVAIL) { snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): SIOCGIFADDR: dev=%s: %s\n", __func__, device, strerror(errno)); close(fd); return (-1); } else /* device has no IP address => set to 0 */ { al->addr = 0; } } else { al->addr = ((struct sockaddr_in *)&nifr.ifr_addr)->sin_addr.s_addr; } if ((al->device = strdup(device)) == NULL) { snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): strdup not enough memory\n", __func__); return(-1); } ++al; ++nipaddr; #ifndef HAVE_LINUX_PROCFS pifr = ifr; #endif } /* while|for */ #ifdef HAVE_LINUX_PROCFS if (ferror(fp)) { snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): ferror: %s\n", __func__, strerror(errno)); return (-1); } fclose(fp); #endif *ipaddrp = ifaddrlist; return (nipaddr); } #else /* From tcptraceroute, convert a numeric IP address to a string */ #define IPTOSBUFFERS 12 static int8_t *iptos(u_int32_t in) { static int8_t output[IPTOSBUFFERS][ 3 * 4 + 3 + 1]; static int16_t which; u_int8_t *p; p = (u_int8_t *)∈ which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1); snprintf(output[which], IPTOSBUFFERS, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); return output[which]; } int libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, int8_t *dev, register int8_t *errbuf) { int nipaddr = 0; int i = 0; static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR]; pcap_if_t *alldevs; pcap_if_t *d; int8_t err[PCAP_ERRBUF_SIZE]; /* Retrieve the interfaces list */ if (pcap_findalldevs(&alldevs, err) == -1) { snprintf(errbuf, LIBNET_ERRBUF_SIZE, "%s(): error in pcap_findalldevs: %s\n", __func__, err); return (-1); } /* Scan the list printing every entry */ for (d = alldevs; d; d = d->next) { if((!d->addresses) || (d->addresses->addr->sa_family != AF_INET)) continue; if(d->flags & PCAP_IF_LOOPBACK) continue; /* XXX - strdup */ ifaddrlist[i].device = strdup(d->name); ifaddrlist[i].addr = (u_int32_t) strdup(iptos(((struct sockaddr_in *) d->addresses->addr)->sin_addr.s_addr)); ++i; ++nipaddr; } *ipaddrp = ifaddrlist; return (nipaddr); }
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); }