$Id$ This is Dug Song's excellent Libdnet networking library version 1.10. It has been stripped down for inclusion within Nmap and modified as follows: o Removed the following directories: python, test, man o Removed all filenames from EXTRA_libdnet_la_SOURCES sources, as they aren't needed with GNU automake 1.9.2 o Removed the fw-* files except for fw-none because Nmap doesn't use the firewall API. Changed configure.in to always use fw-non. o Removed files in now-removed dires that were reference from configure.in:318 o Ran "aclocal -I . -I config" to regenerate aclocal.m4 with my newer aclocal. o Replaced config.guess config.sub and missing in config dir with versions from Autoconf 2.59. o Added this NMAP_MODIFICATIONS file. o Added include/winconfig.h, which is a modified config.h to better support Windows compilation via Visual Studio. Added conditional includes for it to a bunch of the dnet source files. o A number of portability changes to remove errors/warnings during Win32 Visual Studio.Net compilation. This was mostly a matter of adding casts and a few extra include files. o Added libdnet-stripped.vcproj -- A Visual Studio.Net project file for dnet. o Rewrote eth_open() for Win32 as its technique for translating from a dnet-named interface to a pcap-named one did not work on any of my systems. o Added intf_get_pcap_devname() function for Win32. This tries to convert a dnet if name into its pcap equivalent. It is a hack, but arguably better than the hacks that were there before. The main down side is that it won't work with interfaces that don't have an IPv4 address configured. o Increase the number of available bpf devices from 32 to 128. Patch: --- eth-bsd.c (revision 2774) +++ eth-bsd.c (working copy) @@ -45,7 +45,7 @@ int i; if ((e = calloc(1, sizeof(*e))) != NULL) { - for (i = 0; i < 32; i++) { + for (i = 0; i < 128; i++) { snprintf(file, sizeof(file), "/dev/bpf%d", i); e->fd = open(file, O_WRONLY); if (e->fd != -1 || errno != EBUSY) o Made some code changes to intf.c (the patch below). This does the following: o Preserve the alias qualifier from interface name in more cases (e.g. don't blow away :2 from eth0:2 when it may still be needed. o Set the SO_BROADCAST flag on the interface list descriptor so that broadcast/network IPs can be investigated. o Update _match_intf_src so that it checks interface aliases for the given source address rather than only the main interface address. diff -Nruw old/src/intf.c nmap-3.83.new/src/intf.c --- src/intf.c 2005-05-03 09:41:35.000000000 -0700 +++ src/intf.c 2005-07-16 20:55:05.000000000 -0700 @@ -119,12 +119,16 @@ intf_open(void) { intf_t *intf; + int one = 1; if ((intf = calloc(1, sizeof(*intf))) != NULL) { intf->fd = intf->fd6 = -1; if ((intf->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return (intf_close(intf)); + + setsockopt(intf->fd, SOL_SOCKET, SO_BROADCAST, + (const char *) &one, sizeof(one)); #ifdef SIOCGIFNETMASK_IN6 if ((intf->fd6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { # ifdef EPROTONOSUPPORT @@ -472,6 +476,7 @@ _intf_get_aliases(intf_t *intf, struct intf_entry *entry) { struct ifreq *ifr, *lifr; + struct ifreq tmpifr; struct addr *ap, *lap; char *p; @@ -492,9 +497,12 @@ if ((p = strchr(ifr->ifr_name, ':')) != NULL) *p = '\0'; - if (strcmp(ifr->ifr_name, entry->intf_name) != 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; @@ -506,6 +514,11 @@ 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) { @@ -547,10 +560,22 @@ static int _match_intf_src(const struct intf_entry *entry, void *arg) { + int matched = 0; + int cnt; struct intf_entry *save = (struct intf_entry *)arg; if (entry->intf_addr.addr_type == ADDR_TYPE_IP && - entry->intf_addr.addr_ip == save->intf_addr.addr_ip) { + entry->intf_addr.addr_ip == save->intf_addr.addr_ip) + matched = 1; + + for (cnt = 0; !matched && cnt < (int) entry->intf_alias_num; cnt++) { + if (entry->intf_alias_addrs[cnt].addr_type != ADDR_TYPE_IP) + continue; + if (entry->intf_alias_addrs[cnt].addr_ip == save->intf_addr.addr_ip) + matched = 1; + } + + if (matched) { /* XXX - truncated result if entry is too small. */ if (save->intf_len < entry->intf_len) memcpy(save, entry, save->intf_len); @@ -678,14 +703,18 @@ if ((p = strchr(ifr->ifr_name, ':')) != NULL) *p = '\0'; - if (pifr != NULL && strcmp(ifr->ifr_name, pifr->ifr_name) == 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)); 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) o Consider Windows interfaces to be down if they are disconnected, unreachable, or otherwise non-operational: --- intf-win32.c (revision 2976) +++ intf-win32.c (working copy) @@ -116,7 +116,9 @@ /* Get interface flags. */ entry->intf_flags = 0; - if (ifrow->dwAdminStatus == MIB_IF_ADMIN_STATUS_UP) + if (ifrow->dwAdminStatus == MIB_IF_ADMIN_STATUS_UP && + (ifrow->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL || + ifrow->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED)) entry->intf_flags |= INTF_FLAG_UP; if (ifrow->dwType == MIB_IF_TYPE_LOOPBACK) entry->intf_flags |= INTF_FLAG_LOOPBACK;