From 9c744c8e212184571ee804cc9f580f9704325bc8 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Thu, 1 Nov 2012 13:08:55 -0700 Subject: Make interface selection work for interfaces with multiple addresses on them. Windows supports IPv4 and IPv6 by default, so interfaces will have two addresses, and libnet failed when the first address was IPv6. --- libnet/src/libnet_if_addr.c | 65 +++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/libnet/src/libnet_if_addr.c b/libnet/src/libnet_if_addr.c index d97d2e1..9807539 100644 --- a/libnet/src/libnet_if_addr.c +++ b/libnet/src/libnet_if_addr.c @@ -292,43 +292,58 @@ static int8_t *iptos(uint32_t in) } int -libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, char *dev, register char *errbuf) +libnet_ifaddrlist(register struct libnet_ifaddr_list **ipaddrp, char *dev_unused, register char *errbuf) { int nipaddr = 0; int i = 0; static struct libnet_ifaddr_list ifaddrlist[MAX_IPADDR]; - pcap_if_t *alldevs = NULL; - pcap_if_t *d = NULL; + pcap_if_t *devlist = NULL; + pcap_if_t *dev = NULL; int8_t err[PCAP_ERRBUF_SIZE]; /* Retrieve the interfaces list */ - if (pcap_findalldevs(&alldevs, err) == -1) + if (pcap_findalldevs(&devlist, 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) + for (dev = devlist; dev; dev = dev->next) { - if(!d->addresses) - continue; - if(d->addresses->addr->sa_family != AF_INET && d->addresses->addr->sa_family != AF_INET6) - continue; - if(d->flags & PCAP_IF_LOOPBACK) - continue; - - ifaddrlist[i].device = strdup(d->name); - ifaddrlist[i].addr = ((struct sockaddr_in *)d->addresses->addr)->sin_addr.s_addr; - ++i; - ++nipaddr; + struct pcap_addr* pcapaddr; + for(pcapaddr = dev->addresses; pcapaddr; pcapaddr = pcapaddr->next) { + struct sockaddr* addr = pcapaddr->addr; +#if 0 + printf("if name '%s' description '%s' loop? %d\n", dev->name, dev->description, dev->flags); + { + char p[NI_MAXHOST] = ""; + int sz = sizeof(struct sockaddr_storage); + int r; + r = getnameinfo(addr, sz, p, sizeof(p), NULL,0, NI_NUMERICHOST); + printf(" addr %s\n", r ? gai_strerror(r) : p); + } +#endif + + if(dev->flags & PCAP_IF_LOOPBACK) + continue; + + /* this code ignores IPv6 addresses, a limitation of the libnet_ifaddr_list struct */ + + if(addr->sa_family == AF_INET) { + ifaddrlist[i].device = strdup(dev->name); + ifaddrlist[i].addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; + ++i; + ++nipaddr; + } + } } - pcap_freealldevs(alldevs); + pcap_freealldevs(devlist); *ipaddrp = ifaddrlist; - return (nipaddr); + + return nipaddr; } #endif /* __WIN32__ */ @@ -364,7 +379,6 @@ libnet_select_device(libnet_t *l) c = libnet_ifaddrlist(&address_list, l->device, err_buf); if (c < 0) { - /* err msg set in libnet_ifaddrlist() */ return (-1); } else if (c == 0) @@ -377,16 +391,15 @@ libnet_select_device(libnet_t *l) al = address_list; if (l->device) { - /* - * Then we have an IP address in l->device => do lookup - */ addr = libnet_name2addr4(l, l->device, 0); for (i = c; i; --i, ++address_list) { - if (((addr == -1) && !(strncmp(l->device, address_list->device, - strlen(l->device)))) || - (address_list->addr == addr)) + if ( + 0 == strcmp(l->device, address_list->device) + || + address_list->addr == addr + ) { /* free the "user supplied device" - see libnet_init() */ free(l->device); -- cgit v1.2.1