From 0d47952611198ef6b1163f366dc03922d20b1475 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 09:42:04 +0200 Subject: Adding upstream version 7.94+git20230807.3be01efb1+dfsg. Signed-off-by: Daniel Baumann --- libdnet-stripped/NMAP_MODIFICATIONS | 2575 +++++++++++++++++++++++++++++++++++ 1 file changed, 2575 insertions(+) create mode 100644 libdnet-stripped/NMAP_MODIFICATIONS (limited to 'libdnet-stripped/NMAP_MODIFICATIONS') diff --git a/libdnet-stripped/NMAP_MODIFICATIONS b/libdnet-stripped/NMAP_MODIFICATIONS new file mode 100644 index 0000000..adb143e --- /dev/null +++ b/libdnet-stripped/NMAP_MODIFICATIONS @@ -0,0 +1,2575 @@ +$Id$ + +This is Dug Song's excellent Libdnet networking library version 1.12. +It has been stripped down for inclusion within Nmap and modified as follows: + +o Removed the following directories: + python, test, man, trunk + +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 dirs that were referenced in the AC_OUTPUT + at the end of configure.in + +o Ran "aclocal -I . -I config" to regenerate aclocal.m4 with my newer + aclocal. + +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 Regenerated build files with Autoconf 2.63, Automake 1.10.1, and + libtool 2.2.6. + +o Added a check for socklen_t in configure.in and used socklen_t when + calling getsockname and getsockopt to avoid a "pointer targets differ + in signedness" warning on platforms where socklen_t is unsigned. + +o Made the following change for Windows Vista support (thanks to Dan +Griffin): +--- old/intf-win32.c 2005-12-28 16:30:38.000000000 -0800 ++++ intf-win32.c 2006-11-26 20:46:13.000000000 -0800 +@@ -31,7 +31,7 @@ + int max; + }; + +-#define MIB_IF_TYPE_MAX 32 /* XXX - ipifcons.h */ ++#define MIB_IF_TYPE_MAX MAX_IF_TYPE /* XXX - ipifcons.h */ + + struct intf_handle { + struct ifcombo ifcombo[MIB_IF_TYPE_MAX]; + +o Removed config.sub, config.guess, install-sh, ltmain.sh, and missing from the + config directory. These files are found in the parent (i.e., Nmap's) + directory. Also removed config/mkinstalldirs because it is replaced with + $(install_sh) -d. Change Makefile.am not to use ac_aux_dir, which is an + internal Autoconf variable. +Index: configure.in +=================================================================== +--- configure.in (revision 6317) ++++ configure.in (working copy) +@@ -6,8 +6,6 @@ + dnl $Id$ + + AC_INIT(include/dnet.h) +-AC_CONFIG_AUX_DIR(config) +-AC_SUBST(ac_aux_dir) + + AM_INIT_AUTOMAKE(libdnet, 1.10) + AM_CONFIG_HEADER(include/config.h) +Index: Makefile.am +=================================================================== +--- Makefile.am (revision 6317) ++++ Makefile.am (working copy) +@@ -10,16 +10,12 @@ + + CLEANFILES = dnet-config + +-AUX_DIST = $(ac_aux_dir)/acinclude.m4 \ +- $(ac_aux_dir)/config.guess \ +- $(ac_aux_dir)/config.sub \ +- $(ac_aux_dir)/install-sh \ +- $(ac_aux_dir)/ltmain.sh \ +- $(ac_aux_dir)/missing \ +- $(ac_aux_dir)/mkinstalldirs ++aux_dir = config + ++AUX_DIST = $(aux_dir)/acinclude.m4 ++ + dist-hook: +- (cd $(distdir) && mkdir $(ac_aux_dir)) ++ (cd $(distdir) && mkdir $(aux_dir)) + for file in $(AUX_DIST); do \ + cp $$file $(distdir)/$$file; \ + done + +o Remember the entry->intf_len before zeroing entry in _ifrow_to_entry. +intf_loop relies on passing the length inside the structure to make sure +interface aliases are accounted for. +Index: src/intf-win32.c +=================================================================== +--- src/intf-win32.c (revision 6288) ++++ src/intf-win32.c (working copy) +@@ -103,7 +103,12 @@ + struct addr *ap, *lap; + int i; + ++ /* The total length of the entry may be passed in inside entry. ++ Remember it and clear the entry. */ ++ u_int intf_len = entry->intf_len; + memset(entry, 0, sizeof(*entry)); ++ /* Restore the length. */ ++ entry->intf_len = intf_len; + + for (i = 0; i < intf->ifcombo[ifrow->dwType].cnt; i++) { + if (intf->ifcombo[ifrow->dwType].idx[i] == ifrow->dwIndex) + +o Forced interface type numbers to be canonicalized to internal numbers to +avoid accessing uninitialized memory when an unknown device name is +given. +Index: libdnet-stripped/src/intf-win32.c +=================================================================== +--- libdnet-stripped/src/intf-win32.c (revision 6413) ++++ libdnet-stripped/src/intf-win32.c (working copy) +@@ -42,9 +42,12 @@ + static char * + _ifcombo_name(int type) + { +- char *name = "net"; /* XXX */ ++ /* Unknown interface types get the prefix "net". */ ++ char *name = "net"; + +- if (type == MIB_IF_TYPE_ETHERNET) { ++ if (type == MIB_IF_TYPE_ETHERNET || type == IF_TYPE_IEEE80211) { ++ /* INTF_TYPE_IEEE80211 is used for wireless devices on ++ Windows Vista. */ + name = "eth"; + } else if (type == MIB_IF_TYPE_TOKENRING) { + name = "tr"; +@@ -60,9 +63,12 @@ + return (name); + } + ++/* Return a canonical internal interface type number for the given ++ * device string. */ + static int + _ifcombo_type(const char *device) + { ++ /* Unknown device names (like "net") get mapped to INTF_TYPE_OTHER. */ + int type = INTF_TYPE_OTHER; + + if (strncmp(device, "eth", 3) == 0) { +@@ -81,6 +87,20 @@ + return (type); + } + ++/* Map an MIB_IFROW.dwType interface type into an internal interface ++ type. The internal types are never exposed to users of this library; ++ they exist only for the sake of ordering interface types within an ++ intf_handle, which has an array of ifcombo structures ordered by ++ type. Entries in an intf_handle must not be stored or accessed by a ++ raw MIB_IFROW.dwType number because they will not be able to be found ++ by a device name such as "net0" if the device name does not map ++ exactly to the dwType. */ ++static int ++_if_type_canonicalize(int type) ++{ ++ return _ifcombo_type(_ifcombo_name(type)); ++} ++ + static void + _ifcombo_add(struct ifcombo *ifc, DWORD idx) + { +@@ -102,6 +122,7 @@ + { + struct addr *ap, *lap; + int i; ++ int type; + + /* The total length of the entry may be passed in inside entry. + Remember it and clear the entry. */ +@@ -110,14 +131,15 @@ + /* Restore the length. */ + entry->intf_len = intf_len; + +- for (i = 0; i < intf->ifcombo[ifrow->dwType].cnt; i++) { +- if (intf->ifcombo[ifrow->dwType].idx[i] == ifrow->dwIndex) ++ type = _if_type_canonicalize(ifrow->dwType); ++ for (i = 0; i < intf->ifcombo[type].cnt; i++) { ++ if (intf->ifcombo[type].idx[i] == ifrow->dwIndex) + break; + } +- /* XXX - dwType matches MIB-II ifType. */ ++ /* XXX - type matches MIB-II ifType. */ + snprintf(entry->intf_name, sizeof(entry->intf_name), "%s%lu", +- _ifcombo_name(ifrow->dwType), i); +- entry->intf_type = (uint16_t)ifrow->dwType; ++ _ifcombo_name(type), i); ++ entry->intf_type = (uint16_t)type; + + /* Get interface flags. */ + entry->intf_flags = 0; +@@ -201,9 +223,11 @@ + * XXX - like IP_ADAPTER_INFO ComboIndex + */ + for (i = 0; i < intf->iftable->dwNumEntries; i++) { ++ int type; + ifrow = &intf->iftable->table[i]; +- if (ifrow->dwType < MIB_IF_TYPE_MAX) { +- _ifcombo_add(&intf->ifcombo[ifrow->dwType], ++ type = _if_type_canonicalize(ifrow->dwType); ++ if (type < MIB_IF_TYPE_MAX) { ++ _ifcombo_add(&intf->ifcombo[type], + ifrow->dwIndex); + } else + return (-1); + +Index: configure.in +=================================================================== +--- configure.in (revision 17500) ++++ configure.in (working copy) +@@ -32,6 +32,7 @@ + AC_PROG_CC + AC_PROG_INSTALL + AC_LIBTOOL_DLOPEN ++AC_DISABLE_SHARED + AM_PROG_LIBTOOL + + dnl Checks for Python. + +o Made eth_get_pcap_devname compare interface descriptions as well as + MAC addresses when assigning interface names like eth0 on Windows. + Only comparing MAC addresses failed in the case of "teamed" + interfaces, when three interfaces (two physical, one virtual) could + have the same hardware address. + +Index: include/dnet/intf.h +=================================================================== +--- include/dnet/intf.h (revision 17541) ++++ include/dnet/intf.h (revision 17542) +@@ -60,6 +60,7 @@ + int intf_get(intf_t *i, struct intf_entry *entry); + int intf_get_src(intf_t *i, struct intf_entry *entry, struct addr *src); + int intf_get_dst(intf_t *i, struct intf_entry *entry, struct addr *dst); ++int intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen); + int intf_set(intf_t *i, const struct intf_entry *entry); + int intf_loop(intf_t *i, intf_handler callback, void *arg); + intf_t *intf_close(intf_t *i); +Index: src/eth-win32.c +=================================================================== +--- src/eth-win32.c (revision 17541) ++++ src/eth-win32.c (revision 17542) +@@ -34,56 +34,25 @@ + eth_open(const char *device) + { + eth_t *eth; +- intf_t *intf; +- struct intf_entry ifent; +- eth_addr_t ea; +- char *p, *buf; +- ULONG len; ++ char pcapdev[128]; + +- /* Get interface entry. */ +- memset(&ifent, 0, sizeof(ifent)); +- if ((intf = intf_open()) != NULL) { +- strlcpy(ifent.intf_name, device, sizeof(ifent.intf_name)); +- intf_get(intf, &ifent); +- intf_close(intf); +- } +- if (ifent.intf_link_addr.addr_type != ADDR_TYPE_ETH) ++ if (eth_get_pcap_devname(device, pcapdev, sizeof(pcapdev)) != 0) + return (NULL); + +- /* Get Packet driver adapter name/desc lists. */ +- buf = NULL; +- PacketGetAdapterNames(buf, &len); +- if (len > 0 && (buf = malloc(len)) != NULL) { +- if (!PacketGetAdapterNames(buf, &len)) { +- free(buf); +- buf = NULL; +- } +- } +- if (buf == NULL) ++ if ((eth = calloc(1, sizeof(*eth))) == NULL) + return (NULL); +- +- /* XXX - find adapter with matching interface MAC address. */ +- if ((eth = calloc(1, sizeof(*eth))) == NULL) { +- free(buf); ++ eth->lpa = PacketOpenAdapter(pcapdev); ++ if (eth->lpa == NULL) { ++ eth_close(eth); + return (NULL); + } +- for (p = buf; *p != '\0'; p += strlen(p) + 1) { +- if ((eth->lpa = PacketOpenAdapter(p)) != NULL) { +- if (eth->lpa->hFile != INVALID_HANDLE_VALUE && +- eth_get(eth, &ea) == 0 && +- memcmp(&ea, &ifent.intf_link_addr.addr_eth, +- ETH_ADDR_LEN) == 0) { +- PacketSetBuff(eth->lpa, 512000); +- eth->pkt = PacketAllocatePacket(); +- break; +- } +- PacketCloseAdapter(eth->lpa); +- } ++ PacketSetBuff(eth->lpa, 512000); ++ eth->pkt = PacketAllocatePacket(); ++ if (eth->pkt == NULL) { ++ eth_close(eth); ++ return NULL; + } +- free(buf); +- if (eth->pkt == NULL) +- eth = eth_close(eth); +- ++ + return (eth); + } + +@@ -142,61 +111,8 @@ + return (-1); + } + +- +-/* Converts a dnet interface name (ifname) to its pcap equivalent, which is stored in +-pcapdev (up to a length of pcapdevlen). Returns 0 and fills in pcapdev if successful. */ +-int eth_get_pcap_devname(const char *ifname, char *pcapdev, int pcapdevlen) { +- intf_t *intf; +- struct intf_entry ie; +- pcap_if_t *pcapdevs; +- pcap_if_t *pdev; +- char pname[128]; +- +- if ((intf = intf_open()) == NULL) +- return -1; +- +- pname[0] = '\0'; +- memset(&ie, 0, sizeof(ie)); +- strlcpy(ie.intf_name, ifname, sizeof(ie.intf_name)); +- if (intf_get(intf, &ie) != 0) { +- intf_close(intf); +- return -1; +- } +- intf_close(intf); +- +- /* Next we must find the pcap device name corresponding to the device. +- The device description used to be compared with those from PacketGetAdapterNames(), but +- that was unrelaible because dnet and pcap sometimes give different descriptions. For example, +- dnet gave me "AMD PCNET Family PCI Ethernet Adapter - Packet Scheduler Miniport" for one of my +- adapters (in vmware), while pcap described it as "VMware Accelerated AMD PCNet Adapter (Microsoft's +- Packet Scheduler)". Then IP addresses used to be compared, but that proved to be unreliable +- as well. Now we compare hardware addresses much like eth_open() does */ +- if (pcap_findalldevs(&pcapdevs, NULL) == -1) +- return -1; +- +- if (pname[0] == '\0' && ie.intf_link_addr.addr_type == ADDR_TYPE_ETH) { +- for(pdev=pcapdevs; pdev && !pname[0]; pdev = pdev->next) { +- eth_t eth; +- eth_addr_t ea; +- +- eth.lpa = PacketOpenAdapter(pdev->name); +- if (eth.lpa == NULL) +- continue; +- if (eth.lpa->hFile != INVALID_HANDLE_VALUE && +- eth_get(ð, &ea) == 0 && +- memcmp(&ea, &ie.intf_link_addr.addr_eth, +- ETH_ADDR_LEN) == 0) { +- /* Found it -- Yay! */ +- strlcpy(pname, pdev->name, sizeof(pname)); +- } +- PacketCloseAdapter(eth.lpa); +- } +- } +- +- pcap_freealldevs(pcapdevs); +- if (pname[0]) { +- strlcpy(pcapdev, pname, pcapdevlen); +- return 0; +- } +- return -1; ++int ++eth_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen) ++{ ++ return intf_get_pcap_devname(intf_name, pcapdev, pcapdevlen); + } +Index: src/intf-win32.c +=================================================================== +--- src/intf-win32.c (revision 17541) ++++ src/intf-win32.c (revision 17542) +@@ -21,6 +21,9 @@ + #include + + #include "dnet.h" ++#include "pcap.h" ++#include ++#include + + struct ifcombo { + DWORD *idx; +@@ -384,3 +387,89 @@ + } + return (NULL); + } ++ ++/* Converts a libdnet interface name to its pcap equivalent. The pcap name is ++ stored in pcapdev up to a length of pcapdevlen, including the terminating ++ '\0'. Returns -1 on error. */ ++int ++intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen) ++{ ++ wchar_t descr_wc[512]; ++ pcap_if_t *pcapdevs; ++ pcap_if_t *pdev; ++ intf_t *intf; ++ MIB_IFROW ifrow; ++ ++ if ((intf = intf_open()) == NULL) ++ return (-1); ++ if (_refresh_tables(intf) < 0) { ++ intf_close(intf); ++ return (-1); ++ } ++ ifrow.dwIndex = _find_ifindex(intf, intf_name); ++ intf_close(intf); ++ ++ if (GetIfEntry(&ifrow) != NO_ERROR) ++ return (-1); ++ ++ /* OID_GEN_FRIENDLY_NAME returns a wide-character string, so convert ++ the description to wide characters for string comparison. */ ++ mbstowcs(descr_wc, ifrow.bDescr, sizeof(descr_wc) / sizeof(descr_wc[0]) - 1); ++ descr_wc[sizeof(descr_wc) / sizeof(descr_wc[0]) - 1] = L'\0'; ++ ++ if (pcap_findalldevs(&pcapdevs, NULL) == -1) ++ return (-1); ++ ++ /* Loop through all the pcap devices until we find a match. pcap gets ++ its interface list from the registry; dnet gets it from GetIfList. ++ We must match them up using values common to both data sets. We do ++ it by comparing hardware addresses and interface descriptions. */ ++ for (pdev = pcapdevs; pdev != NULL; pdev = pdev->next) { ++ PACKET_OID_DATA *data; ++ u_char buf[512]; ++ LPADAPTER lpa; ++ ++ lpa = PacketOpenAdapter(pdev->name); ++ if (lpa == NULL) ++ continue; ++ if (lpa->hFile == INVALID_HANDLE_VALUE) ++ goto close_adapter; ++ ++ data = (PACKET_OID_DATA *) buf; ++ ++ /* Check the MAC address if available. */ ++ data->Oid = OID_802_3_CURRENT_ADDRESS; ++ data->Length = sizeof(buf) - sizeof(*data); ++ if (PacketRequest(lpa, FALSE, data) == TRUE) { ++ if (data->Length != ifrow.dwPhysAddrLen) ++ goto close_adapter; ++ if (memcmp(ifrow.bPhysAddr, data->Data, data->Length) != 0) ++ goto close_adapter; ++ } ++ ++ /* Distinct interfaces can have the same MAC address in the ++ case of "teamed" interfaces. Additionally check the ++ description string. */ ++ data->Oid = OID_GEN_FRIENDLY_NAME; ++ data->Length = sizeof(buf) - sizeof(*data); ++ if (PacketRequest(lpa, FALSE, data) != TRUE) ++ goto close_adapter; ++ if (wcscmp(descr_wc, (wchar_t *) data->Data) != 0) ++ goto close_adapter; ++ ++ /* Found it. */ ++ PacketCloseAdapter(lpa); ++ break; ++ ++close_adapter: ++ PacketCloseAdapter(lpa); ++ } ++ ++ if (pdev != NULL) ++ strlcpy(pcapdev, pdev->name, pcapdevlen); ++ pcap_freealldevs(pcapdevs); ++ if (pdev == NULL) ++ return -1; ++ else ++ return 0; ++} + +o Changed the name of sctp_chunkhdr to dnet_sctp_chunkhdr to avoid a + conflict with a struct of the same name in in FreeBSD + and Linux. + +Index: include/dnet/sctp.h +=================================================================== +--- include/dnet/sctp.h (revision 20087) ++++ include/dnet/sctp.h (working copy) +@@ -36,7 +36,7 @@ + sctp_pack_p->sh_vtag = htonl(vtag); \ + } while (0) + +-struct sctp_chunkhdr { ++struct dnet_sctp_chunkhdr { + uint8_t sch_type; /* chunk type */ + uint8_t sch_flags; /* chunk flags */ + uint16_t sch_length; /* chunk length */ +@@ -70,7 +70,7 @@ + #define SCTP_TYPEFLAG_SKIP 2 + + #define sctp_pack_chunkhdr(hdr, type, flags, length) do { \ +- struct sctp_chunkhdr *sctp_pack_chp = (struct sctp_chunkhdr *)(hdr);\ ++ struct dnet_sctp_chunkhdr *sctp_pack_chp = (struct dnet_sctp_chunkhdr *)(hdr);\ + sctp_pack_chp->sch_type = type; \ + sctp_pack_chp->sch_flags = flags; \ + sctp_pack_chp->sch_length = htons(length); \ +@@ -80,7 +80,7 @@ + * INIT chunk + */ + struct sctp_chunkhdr_init { +- struct sctp_chunkhdr chunkhdr; ++ struct dnet_sctp_chunkhdr chunkhdr; + + uint32_t schi_itag; /* Initiate Tag */ + uint32_t schi_arwnd; /* Advertised Receiver Window Credit */ +@@ -105,7 +105,7 @@ + * INIT ACK chunk + */ + struct sctp_chunkhdr_init_ack { +- struct sctp_chunkhdr chunkhdr; ++ struct dnet_sctp_chunkhdr chunkhdr; + + uint32_t schia_itag; /* Initiate Tag */ + uint32_t schia_arwnd; /* Advertised Receiver Window Credit */ +@@ -130,7 +130,7 @@ + * ABORT chunk + */ + struct sctp_chunkhdr_abort { +- struct sctp_chunkhdr chunkhdr; ++ struct dnet_sctp_chunkhdr chunkhdr; + + /* empty */ + } __attribute__((__packed__)); +@@ -145,7 +145,7 @@ + * SHUTDOWN ACK chunk + */ + struct sctp_chunkhdr_shutdown_ack { +- struct sctp_chunkhdr chunkhdr; ++ struct dnet_sctp_chunkhdr chunkhdr; + + /* empty */ + } __attribute__((__packed__)); +@@ -160,7 +160,7 @@ + * COOKIE ECHO chunk + */ + struct sctp_chunkhdr_cookie_echo { +- struct sctp_chunkhdr chunkhdr; ++ struct dnet_sctp_chunkhdr chunkhdr; + + /* empty */ + } __attribute__((__packed__)); + +o Allowed reading interface indexes that exceed 255 on Linux. + +--- libdnet-stripped/src/intf.c ++++ libdnet-stripped/src/intf.c +@@ -560,7 +560,7 @@ _intf_get_aliases(intf_t *intf, struct intf_entry *entry) + 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 %02x %02x %02x %02x %32s\n", ++ 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) { + +o Gave priority to the IFF_LOOPBACK flag when setting interface type. + +--- libdnet-stripped/src/intf.c ++++ libdnet-stripped/src/intf.c +@@ -374,12 +374,12 @@ intf_set(intf_t *intf, const struct intf_entry *entry) + static void + _intf_set_type(struct intf_entry *entry) + { +- if ((entry->intf_flags & INTF_FLAG_BROADCAST) != 0) ++ if ((entry->intf_flags & INTF_FLAG_LOOPBACK) != 0) ++ entry->intf_type = INTF_TYPE_LOOPBACK; ++ else if ((entry->intf_flags & INTF_FLAG_BROADCAST) != 0) + entry->intf_type = INTF_TYPE_ETH; + else if ((entry->intf_flags & INTF_FLAG_POINTOPOINT) != 0) + entry->intf_type = INTF_TYPE_TUN; +- else if ((entry->intf_flags & INTF_FLAG_LOOPBACK) != 0) +- entry->intf_type = INTF_TYPE_LOOPBACK; + else + entry->intf_type = INTF_TYPE_OTHER; + } + +===CHANGES ALREADY MERGED TO UPSTREAM LIBDNET GO BELOW THIS LINE=== + +o Fixed the ip6_pack_hdr macro with respect to traffic class and flow + label. + +Index: include/dnet/ip6.h +=================================================================== +--- include/dnet/ip6.h (revision 20527) ++++ include/dnet/ip6.h (revision 20528) +@@ -164,8 +164,8 @@ + + #define ip6_pack_hdr(hdr, fc, fl, plen, nxt, hlim, src, dst) do { \ + struct ip6_hdr *ip6 = (struct ip6_hdr *)(hdr); \ +- ip6->ip6_flow = htonl(((uint32_t)(fc) << 28) & \ +- (IP6_FLOWLABEL_MASK | (fl))); \ ++ ip6->ip6_flow = htonl(((uint32_t)(fc) << 20) | \ ++ (0x000fffff & (fl))); \ + ip6->ip6_vfc = (IP6_VERSION | ((fc) >> 4)); \ + ip6->ip6_plen = htons((plen)); \ + ip6->ip6_nxt = (nxt); ip6->ip6_hlim = (hlim); \ + + +o Added some missing #ifdef AF_LINK guards to enable compiling on + Android. http://seclists.org/nmap-dev/2010/q2/1021. [Vlatko Kosturjak] + +Index: src/addr.c +=================================================================== +--- src/addr.c (revision 19860) ++++ src/addr.c (working copy) +@@ -253,7 +253,11 @@ + # ifdef HAVE_SOCKADDR_SA_LEN + so->sdl.sdl_len = sizeof(so->sdl); + # endif ++# ifdef AF_LINK + so->sdl.sdl_family = AF_LINK; ++# else ++ so->sdl.sdl_family = AF_UNSPEC; ++# endif + so->sdl.sdl_alen = ETH_ADDR_LEN; + memcpy(LLADDR(&so->sdl), &a->addr_eth, ETH_ADDR_LEN); + #else +@@ -300,6 +304,7 @@ + + switch (sa->sa_family) { + #ifdef HAVE_NET_IF_DL_H ++# ifdef AF_LINK + case AF_LINK: + if (so->sdl.sdl_alen != ETH_ADDR_LEN) { + errno = EINVAL; +@@ -309,6 +314,7 @@ + a->addr_bits = ETH_ADDR_BITS; + memcpy(&a->addr_eth, LLADDR(&so->sdl), ETH_ADDR_LEN); + break; ++# endif + #endif + case AF_UNSPEC: + case ARP_HRD_ETH: /* XXX- Linux arp(7) */ + + +Index: config/acinclude.m4 +=================================================================== +--- config/acinclude.m4 (revision 17391) ++++ config/acinclude.m4 (working copy) +@@ -135,14 +135,18 @@ + dnl usage: AC_DNET_LINUX_PF_PACKET + dnl results: HAVE_LINUX_PF_PACKET + dnl ++dnl This is a Linux-specific check, even though other operating systems ++dnl (OpenSolaris) may have the PF_PACKET interface. The eth-linux.c code ++dnl activated by this check is specific to Linux. + AC_DEFUN(AC_DNET_LINUX_PF_PACKET, +- [AC_MSG_CHECKING(for Linux PF_PACKET sockets) +- AC_CACHE_VAL(ac_cv_dnet_linux_pf_packet, +- if test -f /usr/include/netpacket/packet.h ; then +- ac_cv_dnet_linux_pf_packet=yes +- else +- ac_cv_dnet_linux_pf_packet=no +- fi) ++ [AC_CHECK_DECL([ETH_P_ALL], ++ ac_cv_dnet_linux_pf_packet=yes, ++ ac_cv_dnet_linux_pf_packet=no, ++ [ ++#include ++#include ++]) ++ AC_MSG_CHECKING(for Linux PF_PACKET sockets) + AC_MSG_RESULT($ac_cv_dnet_linux_pf_packet) + if test $ac_cv_dnet_linux_pf_packet = yes ; then + AC_DEFINE(HAVE_LINUX_PF_PACKET, 1, + +o Changed the PPA extraction from DLPI interface names to use the last + string of digits, not the first. It was being fooled by the name + e1000g0, thinking the PPA was 1000. + +Index: src/eth-dlpi.c +=================================================================== +--- src/eth-dlpi.c (revision 16878) ++++ src/eth-dlpi.c (working copy) +@@ -113,6 +113,20 @@ + } + return (ppa); + } ++#else ++static int ++dev_find_ppa(const char *dev) ++{ ++ const char *p; ++ ++ p = dev + strlen(dev); ++ while (p > dev && strchr("0123456789", *(p - 1)) != NULL) ++ p--; ++ if (*p == '\0') ++ return NULL; ++ ++ return p; ++} + #endif + + eth_t * +@@ -138,7 +152,7 @@ + #else + e->fd = -1; + snprintf(dev, sizeof(dev), "/dev/%s", device); +- if ((p = strpbrk(dev, "0123456789")) == NULL) { ++ if ((p = dev_find_ppa(dev)) == NULL) { + errno = EINVAL; + return (eth_close(e)); + } + +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. + +o merged upstream libdnet r655 + +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 Fix a compiler "may be used unitialized" warning: +o Merged upstream r654 + +Index: addr-util.c +=================================================================== +--- addr-util.c (revision 3855) ++++ addr-util.c (working copy) +@@ -177,6 +177,8 @@ + struct { int base, len; } best, cur; + char *p = dst; + int i; ++ ++ cur.len = best.len = 0; + + if (len < 46) + return (NULL); + + +o Added eth_get_pcap_devname() that matches up a dnet name to its pcap + equivalent by matching hardwar addresses. It's similar to the code + used in eth_open() + +o Handle the case of sa_len == 0 (meaning 0.0.0.0) in addr_stob. +o Merged upstream to libdnet r654 +Index: src/addr.c +=================================================================== +--- src/addr.c (revision 12591) ++++ src/addr.c (working copy) +@@ -385,11 +385,17 @@ + } else + #endif + { ++ p = (u_char *)&so->sin.sin_addr.s_addr; + #ifdef HAVE_SOCKADDR_SA_LEN +- if ((len = sa->sa_len - IP_ADDR_LEN) > IP_ADDR_LEN) ++ len = sa->sa_len - ((void *) p - (void *) sa); ++ /* Handles the special case of sa->sa_len == 0. */ ++ if (len < 0) ++ len = 0; ++ else if (len > IP_ADDR_LEN) ++ len = IP_ADDR_LEN; ++#else ++ len = IP_ADDR_LEN; + #endif +- len = IP_ADDR_LEN; +- p = (u_char *)&so->sin.sin_addr.s_addr; + } + for (n = i = 0; i < len; i++, n += 8) { + if (p[i] != 0xff) + +o Fixed a case where an open file may not be closed in intf_loop() [Josh] +Index: src/intf.c +=================================================================== +--- src/intf.c (revision 14004) ++++ src/intf.c (working copy) +@@ -677,8 +677,10 @@ + intf->ifc.ifc_buf = (caddr_t)intf->ifcbuf; + intf->ifc.ifc_len = sizeof(intf->ifcbuf); + +- if (ioctl(intf->fd, SIOCGIFCONF, &intf->ifc) < 0) ++ if (ioctl(intf->fd, SIOCGIFCONF, &intf->ifc) < 0) { ++ fclose(fp); + return (-1); ++ } + + ret = 0; + while (fgets(buf, sizeof(buf), fp) != NULL) { + +o Added casts to calls of ctype functions so that their arguments are explicitly +o Merged upstream libdnet r656 +cast to (int) [Josh Marlow] +Index: src/blob.c +=================================================================== +--- src/blob.c (revision 14763) ++++ src/blob.c (working copy) +@@ -162,7 +162,7 @@ + for (p = (char *)fmt; *p != '\0'; p++) { + if (*p == '%') { + p++; +- if (isdigit((int)*p)) { ++ if (isdigit((int) (unsigned char) *p)) { + len = strtol(p, &p, 10); + } else if (*p == '*') { + len = va_arg(*ap, int); +Index: src/intf-win32.c +=================================================================== +--- src/intf-win32.c (revision 14763) ++++ src/intf-win32.c (working copy) +@@ -234,7 +234,7 @@ + char *p = (char *)device; + int n, type = _ifcombo_type(device); + +- while (isalpha(*p)) p++; ++ while (isalpha((int) (unsigned char) *p)) p++; + n = atoi(p); + + return (intf->ifcombo[type].idx[n]); + +o Made some AIX/HP-UX portability changes sent in by Peter O'Gorman +(nmap-dev@mlists.thewrittenword.com), part 2: +Index: src/arp-ioctl.c +=================================================================== +--- src/arp-ioctl.c (revision 3309) ++++ src/arp-ioctl.c (working copy) +@@ -383,7 +383,7 @@ + } + return (ret); + } +-#elif defined(HAVE_NET_RADIX_H) ++#elif defined(HAVE_NET_RADIX_H) && !defined(_AIX) + /* XXX - Tru64, others? */ + #include + #include +Index: src/intf.c +=================================================================== +--- src/intf.c (revision 3309) ++++ src/intf.c (working copy) +@@ -284,7 +284,9 @@ + /* Set interface MTU. */ + if (entry->intf_mtu != 0) { + ifr.ifr_mtu = entry->intf_mtu; ++#ifdef SIOCSIFMTU + if (ioctl(intf->fd, SIOCSIFMTU, &ifr) < 0) ++#endif + return (-1); + } + /* Set interface address. */ +@@ -396,7 +398,9 @@ + _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; + + +o Made some AIX/HP-UX portability changes sent in by Peter O'Gorman + (nmap-dev@mlists.thewrittenword.com), part 1. + Merged to libdnet r653. + +o Added SCTP support. [Daniel Roethlisberger] + Merged to libdnet r651 and r652. + +o Applied a fix for building on GNU/kFreeBSD from Peter Salinger: +--- configure (revision 15144) ++++ configure (working copy) +@@ -14712,12 +14712,22 @@ + + elif test "$ac_cv_header_net_if_tun_h" = yes ; then + if test "$ac_cv_header_stropts_h" = yes ; then +- case " $LIBOBJS " in ++ case "$host_os" in ++ *kfreebsd*) ++ case " $LIBOBJS " in ++ *" tun-bsd.$ac_objext "* ) ;; ++ *) LIBOBJS="$LIBOBJS tun-bsd.$ac_objext" ++ ;; ++esac ++;; ++ *) ++ case " $LIBOBJS " in + *" tun-solaris.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS tun-solaris.$ac_objext" + ;; + esac +- ++;; ++ esac + else + case " $LIBOBJS " in + *" tun-bsd.$ac_objext "* ) ;; + +o Made a change to open bpf devices in read/write mode, to work around a + bug in Mac OS X 10.6. See http://seclists.org/nmap-dev/2009/q4/277. + +Index: src/eth-bsd.c +=================================================================== +--- src/eth-bsd.c (revision 16023) ++++ src/eth-bsd.c (working copy) +@@ -47,7 +47,11 @@ + if ((e = calloc(1, sizeof(*e))) != NULL) { + for (i = 0; i < 128; i++) { + snprintf(file, sizeof(file), "/dev/bpf%d", i); +- e->fd = open(file, O_WRONLY); ++ /* This would be O_WRONLY, but Mac OS X 10.6 has a bug ++ where that prevents other users of the interface ++ from seeing incoming traffic, even in other ++ processes. */ ++ e->fd = open(file, O_RDWR); + if (e->fd != -1 || errno != EBUSY) + break; + } + +o Ignored Solaris IPMP interfaces. + +diff --git src/intf.c src/intf.c +index 9f4ba19..25ae999 100644 +--- src/intf.c ++++ src/intf.c +@@ -941,6 +941,22 @@ intf_loop(intf_t *intf, intf_handler callback, void *arg) + + /* 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); + +o Fixed a bug that caused Nmap to fail to find any network interface when + at least one of them is in the monitor mode. The fix was to define the + ARP_HRD_IEEE80211_RADIOTAP 802.11 radiotap header identifier in the + libdnet-stripped code. Network interfaces that are in this mode are used + by radiotap for 802.11 frame injection and reception. The bug was + reported by Tom Eichstaedt and Henri Doreau. + http://seclists.org/nmap-dev/2012/q2/449 + http://seclists.org/nmap-dev/2012/q2/478 + [Djalal Harouni, Henri Doreau] + +Index: libdnet-stripped/include/dnet/arp.h +=================================================================== +--- libdnet-stripped/include/dnet/arp.h (revision 28761) ++++ libdnet-stripped/include/dnet/arp.h (working copy) +@@ -39,6 +39,8 @@ + #define ARP_HRD_ETH 0x0001 /* ethernet hardware */ + #define ARP_HRD_IEEE802 0x0006 /* IEEE 802 hardware */ + ++#define ARP_HRD_IEEE80211_RADIOTAP 0x0323 /* IEEE 802.11 + radiotap header */ ++ + /* + * Protocol address format + */ +Index: libdnet-stripped/src/addr.c +=================================================================== +--- libdnet-stripped/src/addr.c (revision 28761) ++++ libdnet-stripped/src/addr.c (working copy) +@@ -318,6 +318,7 @@ + #endif + case AF_UNSPEC: + case ARP_HRD_ETH: /* XXX- Linux arp(7) */ ++ case ARP_HRD_IEEE80211_RADIOTAP: /* IEEE 802.11 + radiotap header */ + a->addr_type = ADDR_TYPE_ETH; + a->addr_bits = ETH_ADDR_BITS; + memcpy(&a->addr_eth, sa->sa_data, ETH_ADDR_LEN); + +o Added addr_ston support for ARPHRD_VOID devices. + +diff --git libdnet-stripped/include/dnet/arp.h libdnet-stripped/include/dnet/arp.h +index 2f3d0bf..ec020b4 100644 +--- libdnet-stripped/include/dnet/arp.h ++++ libdnet-stripped/include/dnet/arp.h +@@ -40,6 +40,7 @@ struct arp_hdr { + #define ARP_HRD_IEEE802 0x0006 /* IEEE 802 hardware */ + + #define ARP_HRD_IEEE80211_RADIOTAP 0x0323 /* IEEE 802.11 + radiotap header */ ++#define ARP_HRD_VOID 0xFFFF /* Void type, nothing is known */ + + /* + * Protocol address format +diff --git libdnet-stripped/src/addr.c libdnet-stripped/src/addr.c +index 392d44f..bf3e9e7 100644 +--- libdnet-stripped/src/addr.c ++++ libdnet-stripped/src/addr.c +@@ -343,6 +343,9 @@ addr_ston(const struct sockaddr *sa, struct addr *a) + a->addr_bits = IP_ADDR_BITS; + a->addr_ip = so->sin.sin_addr.s_addr; + break; ++ case ARP_HRD_VOID: ++ memset(&a->addr_eth, 0, ETH_ADDR_LEN); ++ break; + default: + errno = EINVAL; + return (-1); + +o Fixed strict aliasing warnings in ip6_ntop. + +diff --git libdnet-stripped/src/addr-util.c libdnet-stripped/src/addr-util.c +index 6a32958..973f16c 100644 +--- libdnet-stripped/src/addr-util.c ++++ libdnet-stripped/src/addr-util.c +@@ -174,6 +174,7 @@ ip_pton(const char *p, ip_addr_t *ip) + char * + ip6_ntop(const ip6_addr_t *ip6, char *dst, size_t len) + { ++ uint16_t data[IP6_ADDR_LEN / 2]; + struct { int base, len; } best, cur; + char *p = dst; + int i; +@@ -183,12 +184,18 @@ ip6_ntop(const ip6_addr_t *ip6, char *dst, size_t len) + if (len < 46) + return (NULL); + ++ /* Copy into 16-bit array. */ ++ for (i = 0; i < IP6_ADDR_LEN / 2; i++) { ++ data[i] = ip6->data[2 * i] << 8; ++ data[i] |= ip6->data[2 * i + 1]; ++ } ++ + best.base = cur.base = -1; + /* + * Algorithm borrowed from Vixie's inet_pton6() + */ + for (i = 0; i < IP6_ADDR_LEN; i += 2) { +- if (*((uint16_t *)&ip6->data[i]) == 0) { ++ if (data[i / 2] == 0) { + if (cur.base == -1) { + cur.base = i; + cur.len = 0; +@@ -215,13 +222,13 @@ ip6_ntop(const ip6_addr_t *ip6, char *dst, size_t len) + i += best.len; + } else if (i == 12 && best.base == 0 && + (best.len == 10 || (best.len == 8 && +- *((uint16_t *)&ip6->data[10]) == 0xffff))) { +- if (ip_ntop((ip_addr_t *)&ip6->data[12], p, ++ data[5] == 0xffff))) { ++ if (ip_ntop((ip_addr_t *)&data[6], p, + len - (p - dst)) == NULL) + return (NULL); + return (dst); + } else p += sprintf(p, "%x:", +- ntohs(*((uint16_t *)&ip6->data[i]))); ++ ntohs(data[i / 2])); + } + if (best.base + 2 + best.len == IP6_ADDR_LEN) { + *p = '\0'; + +o Fixed interface listing on platforms where ifr_addr does not take up + the whole of struct ifreq. + +diff --git libdnet-stripped/src/intf.c libdnet-stripped/src/intf.c +index 865e500..4fe059c 100644 +--- libdnet-stripped/src/intf.c ++++ libdnet-stripped/src/intf.c +@@ -64,9 +64,10 @@ + #endif + + #ifdef HAVE_SOCKADDR_SA_LEN +-# define NEXTIFR(i) ((struct ifreq *)((u_char *)&i->ifr_addr + \ +- (i->ifr_addr.sa_len ? i->ifr_addr.sa_len : \ +- sizeof(i->ifr_addr)))) ++# define max(a, b) ((a) > (b) ? (a) : (b)) ++# define NEXTIFR(i) ((struct ifreq *) \ ++ max((u_char *)i + sizeof(struct ifreq), \ ++ (u_char *)&i->ifr_addr + i->ifr_addr.sa_len)) + #else + # define NEXTIFR(i) (i + 1) + #endif + +o Support IEEE 802.11 devices and make addr_ston able to handle them + +Index: libdnet-stripped/include/dnet/arp.h +=================================================================== +--- libdnet-stripped/include/dnet/arp.h (revision 29875) ++++ libdnet-stripped/include/dnet/arp.h (working copy) +@@ -39,6 +39,7 @@ + #define ARP_HRD_ETH 0x0001 /* ethernet hardware */ + #define ARP_HRD_IEEE802 0x0006 /* IEEE 802 hardware */ + ++#define ARP_HDR_IEEE80211 0x0321 /* IEEE 802.11 */ + #define ARP_HRD_IEEE80211_RADIOTAP 0x0323 /* IEEE 802.11 + radiotap header */ + #define ARP_HRD_VOID 0xFFFF /* Void type, nothing is known */ + +Index: libdnet-stripped/src/addr.c +=================================================================== +--- libdnet-stripped/src/addr.c (revision 29875) ++++ libdnet-stripped/src/addr.c (working copy) +@@ -318,6 +318,7 @@ + #endif + case AF_UNSPEC: + case ARP_HRD_ETH: /* XXX- Linux arp(7) */ ++ case ARP_HDR_IEEE80211: /* IEEE 802.11 */ + case ARP_HRD_IEEE80211_RADIOTAP: /* IEEE 802.11 + radiotap header */ + a->addr_type = ADDR_TYPE_ETH; + a->addr_bits = ETH_ADDR_BITS; + +o Support IP-over-InfiniBand devices and make addr_ston able to handle + them. However, this support is not complete since IPoIB interfaces + use 20 bytes for the hardware address, and currently we only report + and handle 6 bytes. Nmap IP level scans should work without any + problem, please see Nmap's '--send-ip' switch. + + For more information, please see this thread: + http://seclists.org/nmap-dev/2012/q3/642 + +Index: libdnet-stripped/include/dnet/arp.h +=================================================================== +--- libdnet-stripped/include/dnet/arp.h (revision 29876) ++++ libdnet-stripped/include/dnet/arp.h (working copy) +@@ -39,6 +39,7 @@ + #define ARP_HRD_ETH 0x0001 /* ethernet hardware */ + #define ARP_HRD_IEEE802 0x0006 /* IEEE 802 hardware */ + ++#define ARP_HRD_INFINIBAND 0x0020 /* InfiniBand */ + #define ARP_HDR_IEEE80211 0x0321 /* IEEE 802.11 */ + #define ARP_HRD_IEEE80211_RADIOTAP 0x0323 /* IEEE 802.11 + radiotap header */ + #define ARP_HRD_VOID 0xFFFF /* Void type, nothing is known */ +Index: libdnet-stripped/src/addr.c +=================================================================== +--- libdnet-stripped/src/addr.c (revision 29876) ++++ libdnet-stripped/src/addr.c (working copy) +@@ -318,6 +318,7 @@ + #endif + case AF_UNSPEC: + case ARP_HRD_ETH: /* XXX- Linux arp(7) */ ++ case ARP_HRD_INFINIBAND: /* InfiniBand */ + case ARP_HDR_IEEE80211: /* IEEE 802.11 */ + case ARP_HRD_IEEE80211_RADIOTAP: /* IEEE 802.11 + radiotap header */ + a->addr_type = ADDR_TYPE_ETH; + +o Added the interface name to struct route_entry, and caused it to be + filled in on Linux, Windows, and OS X. + +diff --git a/libdnet-stripped/include/dnet/route.h b/libdnet-stripped/include/dnet/route.h +index 3807b45..7969772 100644 +--- a/libdnet-stripped/include/dnet/route.h ++++ b/libdnet-stripped/include/dnet/route.h +@@ -15,6 +15,7 @@ + * Routing table entry + */ + struct route_entry { ++ char intf_name[INTF_NAME_LEN]; /* interface name */ + struct addr route_dst; /* destination address */ + struct addr route_gw; /* gateway address */ + }; +diff --git a/libdnet-stripped/src/route-bsd.c b/libdnet-stripped/src/route-bsd.c +index 9bfd58d..33f2985 100644 +--- a/libdnet-stripped/src/route-bsd.c ++++ b/libdnet-stripped/src/route-bsd.c +@@ -35,6 +35,7 @@ + #define route_t oroute_t /* XXX - unixware */ + #include + #undef route_t ++#include + #include + + #include +@@ -76,7 +77,7 @@ route_msg_print(struct rt_msghdr *rtm) + #endif + + static int +-route_msg(route_t *r, int type, struct addr *dst, struct addr *gw) ++route_msg(route_t *r, int type, char intf_name[INTF_NAME_LEN], struct addr *dst, struct addr *gw) + { + struct addr net; + struct rt_msghdr *rtm; +@@ -153,6 +154,16 @@ route_msg(route_t *r, int type, struct addr *dst, struct addr *gw) + errno = ESRCH; + return (-1); + } ++ ++ if (intf_name != NULL) { ++ char namebuf[IF_NAMESIZE]; ++ ++ if (if_indextoname(rtm->rtm_index, namebuf) == NULL) { ++ errno = ESRCH; ++ return (-1); ++ } ++ strlcpy(intf_name, namebuf, sizeof(intf_name)); ++ } + } + return (0); + } +@@ -185,7 +196,7 @@ route_add(route_t *r, const struct route_entry *entry) + + memcpy(&rtent, entry, sizeof(rtent)); + +- if (route_msg(r, RTM_ADD, &rtent.route_dst, &rtent.route_gw) < 0) ++ if (route_msg(r, RTM_ADD, NULL, &rtent.route_dst, &rtent.route_gw) < 0) + return (-1); + + return (0); +@@ -201,7 +212,7 @@ route_delete(route_t *r, const struct route_entry *entry) + if (route_get(r, &rtent) < 0) + return (-1); + +- if (route_msg(r, RTM_DELETE, &rtent.route_dst, &rtent.route_gw) < 0) ++ if (route_msg(r, RTM_DELETE, NULL, &rtent.route_dst, &rtent.route_gw) < 0) + return (-1); + + return (0); +@@ -210,8 +221,9 @@ route_delete(route_t *r, const struct route_entry *entry) + int + route_get(route_t *r, struct route_entry *entry) + { +- if (route_msg(r, RTM_GET, &entry->route_dst, &entry->route_gw) < 0) ++ if (route_msg(r, RTM_GET, entry->intf_name, &entry->route_dst, &entry->route_gw) < 0) + return (-1); ++ entry->intf_name[0] = '\0'; + + return (0); + } +@@ -315,9 +327,14 @@ route_loop(route_t *r, route_handler callback, void *arg) + * values, 1, 2, and 4 respectively. Cf. Unix Network Programming, + * p. 494, function get_rtaddrs. */ + for (ret = 0; next < lim; next += rtm->rtm_msglen) { ++ char namebuf[IF_NAMESIZE]; + rtm = (struct rt_msghdr *)next; + sa = (struct sockaddr *)(rtm + 1); + ++ if (if_indextoname(rtm->rtm_index, namebuf) == NULL) ++ continue; ++ strlcpy(entry.intf_name, namebuf, sizeof(entry.intf_name)); ++ + if ((rtm->rtm_addrs & RTA_DST) == 0) + /* Need a destination. */ + continue; +@@ -443,6 +460,8 @@ route_loop(route_t *r, route_handler callback, void *arg) + rt->ipRouteNextHop == IP_ADDR_ANY) + continue; + ++ entry.intf_name[0] = '\0'; ++ + sin.sin_addr.s_addr = rt->ipRouteNextHop; + addr_ston((struct sockaddr *)&sin, + &entry.route_gw); +@@ -535,6 +554,8 @@ route_loop(route_t *r, route_handler callback, void *arg) + memcmp(&rt->ipv6RouteNextHop, IP6_ADDR_UNSPEC, IP6_ADDR_LEN) == 0) + continue; + ++ entry.intf_name[0] = '\0'; ++ + sin6.sin6_addr = rt->ipv6RouteNextHop; + addr_ston((struct sockaddr *)&sin6, + &entry.route_gw); +@@ -576,6 +597,7 @@ _radix_walk(int fd, struct radix_node *rn, route_handler callback, void *arg) + _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); +diff --git a/libdnet-stripped/src/route-hpux.c b/libdnet-stripped/src/route-hpux.c +index a22efdf..a542347 100644 +--- a/libdnet-stripped/src/route-hpux.c ++++ b/libdnet-stripped/src/route-hpux.c +@@ -116,6 +116,7 @@ route_get(route_t *r, struct route_entry *entry) + errno = ESRCH; + return (-1); + } ++ entry->intf_name[0] = '\0'; + entry->route_gw.addr_type = ADDR_TYPE_IP; + entry->route_gw.addr_bits = IP_ADDR_BITS; + memcpy(&entry->route_gw.addr_ip, &rtr.rtr_gwayaddr, IP_ADDR_LEN); +@@ -147,8 +148,6 @@ route_loop(route_t *r, route_handler callback, void *arg) + } + close_mib(fd); + +- entry.route_dst.addr_type = entry.route_gw.addr_type = ADDR_TYPE_IP; +- entry.route_dst.addr_bits = entry.route_gw.addr_bits = IP_ADDR_BITS; + n /= sizeof(*rtentries); + ret = 0; + +@@ -157,6 +156,9 @@ route_loop(route_t *r, route_handler callback, void *arg) + rtentries[i].Type != NMREMOTE) + continue; + ++ entry.intf_name[0] = '\0'; ++ entry.route_dst.addr_type = entry.route_gw.addr_type = ADDR_TYPE_IP; ++ entry.route_dst.addr_bits = entry.route_gw.addr_bits = IP_ADDR_BITS; + entry.route_dst.addr_ip = rtentries[i].Dest; + addr_mtob(&rtentries[i].Mask, IP_ADDR_LEN, + &entry.route_dst.addr_bits); +diff --git a/libdnet-stripped/src/route-linux.c b/libdnet-stripped/src/route-linux.c +index bc788d6..a80b71b 100644 +--- a/libdnet-stripped/src/route-linux.c ++++ b/libdnet-stripped/src/route-linux.c +@@ -14,6 +14,7 @@ + #include + + #include ++#include + #include + #include + #include +@@ -192,18 +193,31 @@ route_get(route_t *r, struct route_entry *entry) + + i -= NLMSG_LENGTH(sizeof(*nmsg)); + +- while (RTA_OK(rta, i)) { ++ entry->route_gw.addr_type = ADDR_TYPE_NONE; ++ entry->intf_name[0] = '\0'; ++ for (rta = RTM_RTA(rmsg); RTA_OK(rta, i); rta = RTA_NEXT(rta, i)) { + if (rta->rta_type == RTA_GATEWAY) { + entry->route_gw.addr_type = entry->route_dst.addr_type; + memcpy(entry->route_gw.addr_data8, RTA_DATA(rta), alen); + entry->route_gw.addr_bits = alen * 8; +- return (0); ++ } else if (rta->rta_type == RTA_OIF) { ++ char ifbuf[IFNAMSIZ]; ++ char *p; ++ int intf_index; ++ ++ intf_index = *(int *) RTA_DATA(rta); ++ p = if_indextoname(intf_index, ifbuf); ++ if (p == NULL) ++ return (-1); ++ strlcpy(entry->intf_name, ifbuf, sizeof(entry->intf_name)); + } +- rta = RTA_NEXT(rta, i); + } +- errno = ESRCH; ++ if (entry->route_gw.addr_type == ADDR_TYPE_NONE) { ++ errno = ESRCH; ++ return (-1); ++ } + +- return (-1); ++ return (0); + } + + int +@@ -228,6 +242,8 @@ route_loop(route_t *r, route_handler callback, void *arg) + if (i < 11 || !(iflags & RTF_UP)) + continue; + ++ strlcpy(entry.intf_name, ifbuf, sizeof(entry.intf_name)); ++ + entry.route_dst.addr_type = entry.route_gw.addr_type = + ADDR_TYPE_IP; + +@@ -259,6 +275,8 @@ route_loop(route_t *r, route_handler callback, void *arg) + if (i < 21 || !(iflags & RTF_UP)) + continue; + ++ strlcpy(entry.intf_name, ifbuf, sizeof(entry.intf_name)); ++ + snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d", + d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], + dlen); +diff --git a/libdnet-stripped/src/route-win32.c b/libdnet-stripped/src/route-win32.c +index f12c8f7..ff86851 100644 +--- a/libdnet-stripped/src/route-win32.c ++++ b/libdnet-stripped/src/route-win32.c +@@ -99,6 +99,8 @@ route_get(route_t *route, struct route_entry *entry) + { + MIB_IPFORWARDROW ipfrow; + DWORD mask; ++ intf_t *intf; ++ struct intf_entry intf_entry; + + if (entry->route_dst.addr_type != ADDR_TYPE_IP || + GetBestRoute(entry->route_dst.addr_ip, +@@ -118,6 +120,14 @@ route_get(route_t *route, struct route_entry *entry) + entry->route_gw.addr_type = ADDR_TYPE_IP; + entry->route_gw.addr_bits = IP_ADDR_BITS; + entry->route_gw.addr_ip = ipfrow.dwForwardNextHop; ++ ++ entry->intf_name[0] = '\0'; ++ intf = intf_open(); ++ if (intf_get_index(intf, &intf_entry, ++ AF_INET, ipfrow.dwForwardIfIndex) == 0) { ++ strlcpy(entry->intf_name, intf_entry.intf_name, sizeof(entry->intf_name)); ++ } ++ intf_close(intf); + + return (0); + } +@@ -126,6 +136,7 @@ static int + route_loop_getipforwardtable(route_t *r, route_handler callback, void *arg) + { + struct route_entry entry; ++ intf_t *intf; + ULONG len; + int i, ret; + +@@ -139,23 +150,40 @@ route_loop_getipforwardtable(route_t *r, route_handler callback, void *arg) + else if (ret != ERROR_INSUFFICIENT_BUFFER) + return (-1); + } +- entry.route_dst.addr_type = ADDR_TYPE_IP; +- entry.route_dst.addr_bits = IP_ADDR_BITS; +- +- entry.route_gw.addr_type = ADDR_TYPE_IP; +- entry.route_gw.addr_bits = IP_ADDR_BITS; ++ ++ intf = intf_open(); + ++ ret = 0; + for (i = 0; i < (int)r->ipftable->dwNumEntries; i++) { ++ struct intf_entry intf_entry; ++ ++ entry.route_dst.addr_type = ADDR_TYPE_IP; ++ entry.route_dst.addr_bits = IP_ADDR_BITS; ++ ++ entry.route_gw.addr_type = ADDR_TYPE_IP; ++ entry.route_gw.addr_bits = IP_ADDR_BITS; ++ + entry.route_dst.addr_ip = r->ipftable->table[i].dwForwardDest; + addr_mtob(&r->ipftable->table[i].dwForwardMask, IP_ADDR_LEN, + &entry.route_dst.addr_bits); + entry.route_gw.addr_ip = + r->ipftable->table[i].dwForwardNextHop; ++ ++ /* Look up the interface name. */ ++ entry.intf_name[0] = '\0'; ++ intf_entry.intf_len = sizeof(intf_entry); ++ if (intf_get_index(intf, &intf_entry, ++ AF_INET, r->ipftable->table[i].dwForwardIfIndex) == 0) { ++ strlcpy(entry.intf_name, intf_entry.intf_name, sizeof(entry.intf_name)); ++ } + + if ((ret = (*callback)(&entry, arg)) != 0) +- return (ret); ++ break; + } +- return (0); ++ ++ intf_close(intf); ++ ++ return ret; + } + + static int +@@ -163,6 +191,7 @@ route_loop_getipforwardtable2(GETIPFORWARDTABLE2 GetIpForwardTable2, + route_t *r, route_handler callback, void *arg) + { + struct route_entry entry; ++ intf_t *intf; + ULONG i; + int ret; + +@@ -170,18 +199,34 @@ route_loop_getipforwardtable2(GETIPFORWARDTABLE2 GetIpForwardTable2, + if (ret != NO_ERROR) + return (-1); + ++ intf = intf_open(); ++ ++ ret = 0; + for (i = 0; i < r->ipftable2->NumEntries; i++) { ++ struct intf_entry intf_entry; + MIB_IPFORWARD_ROW2 *row; + + row = &r->ipftable2->Table[i]; + addr_ston((struct sockaddr *) &row->DestinationPrefix.Prefix, &entry.route_dst); + entry.route_dst.addr_bits = row->DestinationPrefix.PrefixLength; + addr_ston((struct sockaddr *) &row->NextHop, &entry.route_gw); ++ ++ /* Look up the interface name. */ ++ entry.intf_name[0] = '\0'; ++ intf_entry.intf_len = sizeof(intf_entry); ++ if (intf_get_index(intf, &intf_entry, ++ row->DestinationPrefix.Prefix.si_family, ++ row->InterfaceIndex) == 0) { ++ strlcpy(entry.intf_name, intf_entry.intf_name, sizeof(entry.intf_name)); ++ } + + if ((ret = (*callback)(&entry, arg)) != 0) +- return (ret); ++ break; + } +- return (0); ++ ++ intf_close(intf); ++ ++ return ret; + } + + int + +o Add some checks for allocation functions returning NULL. + +commit 5b8a67e968aff12df2bc3cf189b96c16eec6ae3f +Author: David Fifield +Date: Wed Nov 21 16:47:21 2012 -0800 + + Check some libdnet mallocs for failure. + + Patch based on one by Bill Parker. + http://seclists.org/nmap-dev/2012/q4/261 + +diff --git a/libdnet-stripped/src/arp-win32.c b/libdnet-stripped/src/arp-win32.c +index 98b01c5..4434804 100644 +--- a/libdnet-stripped/src/arp-win32.c ++++ b/libdnet-stripped/src/arp-win32.c +@@ -108,6 +108,8 @@ arp_loop(arp_t *arp, arp_handler callback, void *arg) + if (arp->iptable) + free(arp->iptable); + arp->iptable = malloc(len); ++ if (arp->iptable == NULL) ++ return (-1); + ret = GetIpNetTable(arp->iptable, &len, FALSE); + if (ret == NO_ERROR) + break; +diff --git a/libdnet-stripped/src/route-win32.c b/libdnet-stripped/src/route-win32.c +index ff86851..b4536b3 100644 +--- a/libdnet-stripped/src/route-win32.c ++++ b/libdnet-stripped/src/route-win32.c +@@ -35,6 +35,8 @@ route_open(void) + route_t *r; + + r = calloc(1, sizeof(route_t)); ++ if (r == NULL) ++ return NULL; + r->iphlpapi = GetModuleHandle("iphlpapi.dll"); + + return r; +@@ -144,6 +146,8 @@ route_loop_getipforwardtable(route_t *r, route_handler callback, void *arg) + if (r->ipftable) + free(r->ipftable); + r->ipftable = malloc(len); ++ if (r->ipftable == NULL) ++ return (-1); + ret = GetIpForwardTable(r->ipftable, &len, FALSE); + if (ret == NO_ERROR) + break; + +o Add metric to struct route_entry. + +diff --git a/libdnet-stripped/include/dnet/route.h b/libdnet-stripped/include/dnet/route.h +index 7969772..b4bd4cc 100644 +--- a/libdnet-stripped/include/dnet/route.h ++++ b/libdnet-stripped/include/dnet/route.h +@@ -18,6 +18,7 @@ struct route_entry { + char intf_name[INTF_NAME_LEN]; /* interface name */ + struct addr route_dst; /* destination address */ + struct addr route_gw; /* gateway address */ ++ int metric; /* per-route metric */ + }; + + typedef struct route_handle route_t; +diff --git a/libdnet-stripped/src/route-bsd.c b/libdnet-stripped/src/route-bsd.c +index 33f2985..44e7dd2 100644 +--- a/libdnet-stripped/src/route-bsd.c ++++ b/libdnet-stripped/src/route-bsd.c +@@ -224,6 +224,7 @@ route_get(route_t *r, struct route_entry *entry) + if (route_msg(r, RTM_GET, entry->intf_name, &entry->route_dst, &entry->route_gw) < 0) + return (-1); + entry->intf_name[0] = '\0'; ++ entry->metric = 0; + + return (0); + } +@@ -359,6 +360,8 @@ route_loop(route_t *r, route_handler callback, void *arg) + continue; + } + ++ entry.metric = 0; ++ + if ((ret = callback(&entry, arg)) != 0) + break; + } +@@ -473,6 +476,8 @@ route_loop(route_t *r, route_handler callback, void *arg) + sin.sin_addr.s_addr = rt->ipRouteMask; + addr_stob((struct sockaddr *)&sin, + &entry.route_dst.addr_bits); ++ ++ entry.metric = 0; + + if ((ret = callback(&entry, arg)) != 0) + return (ret); +@@ -608,6 +613,7 @@ _radix_walk(int fd, struct radix_node *rn, route_handler callback, void *arg) + } + _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); + } +diff --git a/libdnet-stripped/src/route-hpux.c b/libdnet-stripped/src/route-hpux.c +index a542347..07e7f8c 100644 +--- a/libdnet-stripped/src/route-hpux.c ++++ b/libdnet-stripped/src/route-hpux.c +@@ -120,6 +120,7 @@ route_get(route_t *r, struct route_entry *entry) + entry->route_gw.addr_type = ADDR_TYPE_IP; + entry->route_gw.addr_bits = IP_ADDR_BITS; + memcpy(&entry->route_gw.addr_ip, &rtr.rtr_gwayaddr, IP_ADDR_LEN); ++ entry->metric = 0; + + return (0); + } +@@ -163,6 +164,7 @@ route_loop(route_t *r, route_handler callback, void *arg) + addr_mtob(&rtentries[i].Mask, IP_ADDR_LEN, + &entry.route_dst.addr_bits); + entry.route_gw.addr_ip = rtentries[i].NextHop; ++ entry.metric = 0; + + if ((ret = callback(&entry, arg)) != 0) + break; +diff --git a/libdnet-stripped/src/route-linux.c b/libdnet-stripped/src/route-linux.c +index a80b71b..b14c527 100644 +--- a/libdnet-stripped/src/route-linux.c ++++ b/libdnet-stripped/src/route-linux.c +@@ -252,6 +252,7 @@ route_loop(route_t *r, route_handler callback, void *arg) + continue; + + entry.route_gw.addr_bits = IP_ADDR_BITS; ++ entry.metric = metric; + + if ((ret = callback(&entry, arg)) != 0) + break; +@@ -260,17 +261,17 @@ route_loop(route_t *r, route_handler callback, void *arg) + } + if (ret == 0 && (fp = fopen(PROC_IPV6_ROUTE_FILE, "r")) != NULL) { + char s[33], d[8][5], n[8][5]; +- int i, iflags; ++ int i, iflags, metric; + u_int slen, dlen; + + while (fgets(buf, sizeof(buf), fp) != NULL) { + i = sscanf(buf, "%04s%04s%04s%04s%04s%04s%04s%04s %02x " + "%32s %02x %04s%04s%04s%04s%04s%04s%04s%04s " +- "%*x %*x %*x %x %15s", ++ "%x %*x %*x %x %15s", + d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], + &dlen, s, &slen, + n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], +- &iflags, ifbuf); ++ &metric, &iflags, ifbuf); + + if (i < 21 || !(iflags & RTF_UP)) + continue; +@@ -285,6 +286,7 @@ route_loop(route_t *r, route_handler callback, void *arg) + n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], + IP6_ADDR_BITS); + addr_aton(buf, &entry.route_gw); ++ entry.metric = metric; + + if ((ret = callback(&entry, arg)) != 0) + break; +diff --git a/libdnet-stripped/src/route-win32.c b/libdnet-stripped/src/route-win32.c +index b4536b3..c69b29b 100644 +--- a/libdnet-stripped/src/route-win32.c ++++ b/libdnet-stripped/src/route-win32.c +@@ -122,6 +122,7 @@ route_get(route_t *route, struct route_entry *entry) + entry->route_gw.addr_type = ADDR_TYPE_IP; + entry->route_gw.addr_bits = IP_ADDR_BITS; + entry->route_gw.addr_ip = ipfrow.dwForwardNextHop; ++ entry->metric = ipfrow.dwForwardMetric1; + + entry->intf_name[0] = '\0'; + intf = intf_open(); +@@ -172,6 +173,7 @@ route_loop_getipforwardtable(route_t *r, route_handler callback, void *arg) + &entry.route_dst.addr_bits); + entry.route_gw.addr_ip = + r->ipftable->table[i].dwForwardNextHop; ++ entry.metric = r->ipftable->table[i].dwForwardMetric1; + + /* Look up the interface name. */ + entry.intf_name[0] = '\0'; +@@ -209,6 +211,8 @@ route_loop_getipforwardtable2(GETIPFORWARDTABLE2 GetIpForwardTable2, + for (i = 0; i < r->ipftable2->NumEntries; i++) { + struct intf_entry intf_entry; + MIB_IPFORWARD_ROW2 *row; ++ MIB_IPINTERFACE_ROW ifrow; ++ ULONG metric; + + row = &r->ipftable2->Table[i]; + addr_ston((struct sockaddr *) &row->DestinationPrefix.Prefix, &entry.route_dst); +@@ -223,6 +227,18 @@ route_loop_getipforwardtable2(GETIPFORWARDTABLE2 GetIpForwardTable2, + row->InterfaceIndex) == 0) { + strlcpy(entry.intf_name, intf_entry.intf_name, sizeof(entry.intf_name)); + } ++ ++ ifrow.Family = row->DestinationPrefix.Prefix.si_family; ++ ifrow.InterfaceLuid = row->InterfaceLuid; ++ ifrow.InterfaceIndex = row->InterfaceIndex; ++ if (GetIpInterfaceEntry(&ifrow) != NO_ERROR) { ++ return (-1); ++ } ++ metric = ifrow.Metric + row->Metric; ++ if (metric < INT_MAX) ++ entry.metric = metric; ++ else ++ entry.metric = INT_MAX; + + if ((ret = (*callback)(&entry, arg)) != 0) + break; + +o Support Appletalk devices and make addr_ston able to handle + them. However, this support is not complete since ipddp interfaces + use different size hardware addresses than Ethernet. + Nmap IP level scans should work without any + problem, please see Nmap's '--send-ip' switch. + + For more information, please see this thread: + http://seclists.org/nmap-dev/2013/q1/214 + +Index: libdnet-stripped/include/dnet/arp.h +=================================================================== +--- libdnet-stripped/include/dnet/arp.h (revision 30609) ++++ libdnet-stripped/include/dnet/arp.h (working copy) +@@ -40,6 +40,7 @@ + #define ARP_HRD_IEEE802 0x0006 /* IEEE 802 hardware */ + + #define ARP_HRD_INFINIBAND 0x0020 /* InfiniBand */ ++#define ARP_HRD_APPLETALK 0x0309 /* AppleTalk DDP */ + #define ARP_HDR_IEEE80211 0x0321 /* IEEE 802.11 */ + #define ARP_HRD_IEEE80211_RADIOTAP 0x0323 /* IEEE 802.11 + radiotap header */ + #define ARP_HRD_VOID 0xFFFF /* Void type, nothing is known */ +Index: libdnet-stripped/src/addr.c +=================================================================== +--- libdnet-stripped/src/addr.c (revision 30609) ++++ libdnet-stripped/src/addr.c (working copy) +@@ -318,6 +318,7 @@ + #endif + case AF_UNSPEC: + case ARP_HRD_ETH: /* XXX- Linux arp(7) */ ++ case ARP_HRD_APPLETALK: /* AppleTalk DDP */ + case ARP_HRD_INFINIBAND: /* InfiniBand */ + case ARP_HDR_IEEE80211: /* IEEE 802.11 */ + case ARP_HRD_IEEE80211_RADIOTAP: /* IEEE 802.11 + radiotap header */ + + +o Added compatibility patch for OpenBSD to not SIOCIFNETMASK before + SIOCIFADDR. (Giovanni Bechis) + +diff --git a/libdnet-stripped/src/intf.c b/libdnet-stripped/src/intf.c +index 4fe059c..184c077 100644 +--- a/libdnet-stripped/src/intf.c ++++ b/libdnet-stripped/src/intf.c +@@ -77,7 +77,13 @@ + /* XXX - superset of ifreq, for portable SIOC{A,D}IFADDR */ + struct dnet_ifaliasreq { + char ifra_name[IFNAMSIZ]; +- struct sockaddr ifra_addr; ++ union { ++ struct sockaddr ifrau_addr; ++ int ifrau_align; ++ } ifra_ifrau; ++#ifndef ifra_addr ++#define ifra_addr ifra_ifrau.ifrau_addr ++#endif + struct sockaddr ifra_brdaddr; + struct sockaddr ifra_mask; + int ifra_cookie; /* XXX - IRIX!@#$ */ +@@ -308,7 +314,7 @@ intf_set(intf_t *intf, const struct intf_entry *entry) + } + /* Set interface address. */ + if (entry->intf_addr.addr_type == ADDR_TYPE_IP) { +-#ifdef BSD ++#if defined(BSD) && !defined(__OPENBSD__) + /* XXX - why must this happen before SIOCSIFADDR? */ + if (addr_btos(entry->intf_addr.addr_bits, + &ifr.ifr_addr) == 0) { + +o Use the RT_ROUNDUP preprocessor macro for 64-bit rt_msghdr alignment + on NetBSD. + +diff --git a/libdnet-stripped/src/route-bsd.c b/libdnet-stripped/src/route-bsd.c +index 44e7dd2..47f3705 100644 +--- a/libdnet-stripped/src/route-bsd.c ++++ b/libdnet-stripped/src/route-bsd.c +@@ -47,8 +47,14 @@ + + #include "dnet.h" + ++#if defined(RT_ROUNDUP) && defined(__NetBSD__) ++/* NetBSD defines this macro rounding to 64-bit boundaries. ++ http://fxr.watson.org/fxr/ident?v=NETBSD;i=RT_ROUNDUP */ ++#define ROUNDUP(a) RT_ROUNDUP(a) ++#else + #define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (RT_MSGHDR_ALIGNMENT - 1))) : RT_MSGHDR_ALIGNMENT) ++#endif + + #ifdef HAVE_SOCKADDR_SA_LEN + #define NEXTSA(s) \ +o Fix hw address getting on AIX + +diff --git a/libdnet-stripped/src/intf.c b/libdnet-stripped/src/intf.c +index 184c077..2df6a4d 100644 +--- a/libdnet-stripped/src/intf.c ++++ b/libdnet-stripped/src/intf.c +@@ -20,6 +20,10 @@ + # include + #endif + /* XXX - AIX */ ++#ifdef HAVE_GETKERNINFO ++#include ++#include ++#endif + #ifndef IP_MULTICAST + # define IP_MULTICAST + #endif +@@ -477,6 +481,11 @@ 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); +@@ -517,7 +526,39 @@ _intf_get_noalias(intf_t *intf, struct intf_entry *entry) + return (-1); + } + } else if (entry->intf_type == INTF_TYPE_ETH) { +-#if defined(SIOCGIFHWADDR) ++#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) + +o Support 802.11 Prism interfaces in monitor mode + +diff --git a/libdnet-stripped/include/dnet/arp.h b/libdnet-stripped/include/dnet/arp.h +index 9bfdcaf..728f8c3 100644 +--- a/libdnet-stripped/include/dnet/arp.h ++++ b/libdnet-stripped/include/dnet/arp.h +@@ -42,6 +42,7 @@ struct arp_hdr { + #define ARP_HRD_INFINIBAND 0x0020 /* InfiniBand */ + #define ARP_HRD_APPLETALK 0x0309 /* AppleTalk DDP */ + #define ARP_HDR_IEEE80211 0x0321 /* IEEE 802.11 */ ++#define ARP_HRD_IEEE80211_PRISM 0x0322 /* IEEE 802.11 + prism header */ + #define ARP_HRD_IEEE80211_RADIOTAP 0x0323 /* IEEE 802.11 + radiotap header */ + #define ARP_HRD_VOID 0xFFFF /* Void type, nothing is known */ + +diff --git a/libdnet-stripped/src/addr.c b/libdnet-stripped/src/addr.c +index 8953b5b..05a0692 100644 +--- a/libdnet-stripped/src/addr.c ++++ b/libdnet-stripped/src/addr.c +@@ -321,6 +321,7 @@ addr_ston(const struct sockaddr *sa, struct addr *a) + case ARP_HRD_APPLETALK: /* AppleTalk DDP */ + case ARP_HRD_INFINIBAND: /* InfiniBand */ + case ARP_HDR_IEEE80211: /* IEEE 802.11 */ ++ case ARP_HRD_IEEE80211_PRISM: /* IEEE 802.11 + prism header */ + case ARP_HRD_IEEE80211_RADIOTAP: /* IEEE 802.11 + radiotap header */ + a->addr_type = ADDR_TYPE_ETH; + a->addr_bits = ETH_ADDR_BITS; + +o Fix a crash when pcap_findalldevs encounters errors and tries to write to + errbuf. As demonstrated by WinPcap crashing on Surface Pro 3 + +diff --git a/libdnet-stripped/src/intf-win32.c b/libdnet-stripped/src/intf-win32.c +index 22c2d59..22c1e6a 100644 +--- a/libdnet-stripped/src/intf-win32.c ++++ b/libdnet-stripped/src/intf-win32.c +@@ -425,6 +425,7 @@ intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen) + pcap_if_t *pcapdevs; + pcap_if_t *pdev, *selected; + intf_t *intf; ++ char errbuf[PCAP_ERRBUF_SIZE]; + + if ((intf = intf_open()) == NULL) + return (-1); +@@ -439,7 +440,7 @@ intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen) + return (-1); + } + +- if (pcap_findalldevs(&pcapdevs, NULL) == -1) { ++ if (pcap_findalldevs(&pcapdevs, errbuf) == -1) { + intf_close(intf); + return (-1); + } + +o Fix a crash on Windows 8.1 with certain down interfaces: + http://seclists.org/nmap-dev/2015/q1/282 + +diff --git a/libdnet-stripped/src/intf-win32.c b/libdnet-stripped/src/intf-win32.c +index 22c1e6a..3c09f9c 100644 +--- a/libdnet-stripped/src/intf-win32.c ++++ b/libdnet-stripped/src/intf-win32.c +@@ -262,7 +262,8 @@ _find_adapter_address(intf_t *intf, const char *device) + n = atoi(p); + + for (a = intf->iftable; a != NULL; a = a->Next) { +- if (intf->ifcombo[type].idx[n].ipv4 == a->IfIndex && ++ if ( intf->ifcombo[type].idx != NULL && ++ intf->ifcombo[type].idx[n].ipv4 == a->IfIndex && + intf->ifcombo[type].idx[n].ipv6 == a->Ipv6IfIndex) { + return a; + } + +o Fix address detection on Solaris due to SIOCGLIFFLAGS ioctl overwriting the + lifreq that _intf_get_aliases expects to be holding the output of + SIOCGLIFCONF ioctl. http://seclists.org/nmap-dev/2015/q2/1 + +diff --git a/libdnet-stripped/src/intf.c b/libdnet-stripped/src/intf.c +index 2df6a4d..b71fb82 100644 +--- a/libdnet-stripped/src/intf.c ++++ b/libdnet-stripped/src/intf.c +@@ -953,6 +953,8 @@ intf_loop(intf_t *intf, intf_handler callback, void *arg) + struct lifreq *lifr, *llifr, *plifr; + char *p, ebuf[BUFSIZ]; + int ret; ++ struct lifreq lifrflags; ++ memset(&lifrflags, 0, sizeof(struct lifreq)); + + entry = (struct intf_entry *)ebuf; + +@@ -996,14 +998,15 @@ intf_loop(intf_t *intf, intf_handler callback, void *arg) + * 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) ++ strlcpy(lifrflags.lifr_name, lifr->lifr_name, sizeof(lifrflags.lifr_name)); ++ if (ioctl(intf->fd, SIOCGLIFFLAGS, &lifrflags) >= 0) + ; +- else if (intf->fd6 != -1 && ioctl(intf->fd6, SIOCGLIFFLAGS, lifr) >= 0) ++ else if (intf->fd6 != -1 && ioctl(intf->fd6, SIOCGLIFFLAGS, &lifrflags) >= 0) + ; + else + return (-1); + #ifdef IFF_IPMP +- if (lifr->lifr_flags & IFF_IPMP) { ++ if (lifrflags.lifr_flags & IFF_IPMP) { + continue; + } + #endif + +o Avoid a strange hang with the WinPCAP driver when running multiple instances + of Nmap concurrently. + +diff --git a/libdnet-stripped/src/eth-win32.c b/libdnet-stripped/src/eth-win32.c +index 9cbb3f9..de0320e 100644 +--- a/libdnet-stripped/src/eth-win32.c ++++ b/libdnet-stripped/src/eth-win32.c +@@ -35,13 +35,21 @@ eth_open(const char *device) + { + eth_t *eth; + char pcapdev[128]; ++ HANDLE pcapMutex; ++ DWORD wait; + + if (eth_get_pcap_devname(device, pcapdev, sizeof(pcapdev)) != 0) + return (NULL); + + if ((eth = calloc(1, sizeof(*eth))) == NULL) + return (NULL); ++ pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex"); ++ wait = WaitForSingleObject(pcapMutex, INFINITE); + eth->lpa = PacketOpenAdapter(pcapdev); ++ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) { ++ ReleaseMutex(pcapMutex); ++ } ++ CloseHandle(pcapMutex); + if (eth->lpa == NULL) { + eth_close(eth); + return (NULL); +@@ -67,11 +75,21 @@ eth_send(eth_t *eth, const void *buf, size_t len) + eth_t * + eth_close(eth_t *eth) + { ++ HANDLE pcapMutex; ++ DWORD wait; + if (eth != NULL) { + if (eth->pkt != NULL) + PacketFreePacket(eth->pkt); + if (eth->lpa != NULL) ++ { ++ pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex"); ++ wait = WaitForSingleObject(pcapMutex, INFINITE); + PacketCloseAdapter(eth->lpa); ++ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) { ++ ReleaseMutex(pcapMutex); ++ } ++ CloseHandle(pcapMutex); ++ } + free(eth); + } + return (NULL); +diff --git a/libdnet-stripped/src/intf-win32.c b/libdnet-stripped/src/intf-win32.c +index 3c09f9c..77225b6 100644 +--- a/libdnet-stripped/src/intf-win32.c ++++ b/libdnet-stripped/src/intf-win32.c +@@ -427,6 +427,8 @@ intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen) + pcap_if_t *pdev, *selected; + intf_t *intf; + char errbuf[PCAP_ERRBUF_SIZE]; ++ HANDLE pcapMutex; ++ DWORD wait; + + if ((intf = intf_open()) == NULL) + return (-1); +@@ -441,10 +443,20 @@ intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen) + return (-1); + } + ++ pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex"); ++ wait = WaitForSingleObject(pcapMutex, INFINITE); + if (pcap_findalldevs(&pcapdevs, errbuf) == -1) { ++ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) { ++ ReleaseMutex(pcapMutex); ++ } ++ CloseHandle(pcapMutex); + intf_close(intf); + return (-1); + } ++ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) { ++ ReleaseMutex(pcapMutex); ++ } ++ CloseHandle(pcapMutex); + + /* Loop through all the pcap devices until we find a match. */ + selected = NULL; + +o (LATER REVERTED) Use a mutex on Windows to avoid a hang when accessing WinPCAP driver. + Reported by multiple users on Windows 8.1 and Windows Server 2012 R2. + Seems to hang when the WinPCAP driver is accessed via OpenServiceA by + multiple processes at once. Users report that this change, which uses a + mutex to avoid concurrent access, fixes the hang. + +diff --git a/libdnet-stripped/src/eth-win32.c b/libdnet-stripped/src/eth-win32.c +index 9cbb3f9..de0320e 100644 +--- a/libdnet-stripped/src/eth-win32.c ++++ b/libdnet-stripped/src/eth-win32.c +@@ -35,13 +35,21 @@ eth_open(const char *device) + { + eth_t *eth; + char pcapdev[128]; ++ HANDLE pcapMutex; ++ DWORD wait; + + if (eth_get_pcap_devname(device, pcapdev, sizeof(pcapdev)) != 0) + return (NULL); + + if ((eth = calloc(1, sizeof(*eth))) == NULL) + return (NULL); ++ pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex"); ++ wait = WaitForSingleObject(pcapMutex, INFINITE); + eth->lpa = PacketOpenAdapter(pcapdev); ++ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) { ++ ReleaseMutex(pcapMutex); ++ } ++ CloseHandle(pcapMutex); + if (eth->lpa == NULL) { + eth_close(eth); + return (NULL); +@@ -67,11 +75,21 @@ eth_send(eth_t *eth, const void *buf, size_t len) + eth_t * + eth_close(eth_t *eth) + { ++ HANDLE pcapMutex; ++ DWORD wait; + if (eth != NULL) { + if (eth->pkt != NULL) + PacketFreePacket(eth->pkt); + if (eth->lpa != NULL) ++ { ++ pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex"); ++ wait = WaitForSingleObject(pcapMutex, INFINITE); + PacketCloseAdapter(eth->lpa); ++ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) { ++ ReleaseMutex(pcapMutex); ++ } ++ CloseHandle(pcapMutex); ++ } + free(eth); + } + return (NULL); +diff --git a/libdnet-stripped/src/intf-win32.c b/libdnet-stripped/src/intf-win32.c +index 3c09f9c..77225b6 100644 +--- a/libdnet-stripped/src/intf-win32.c ++++ b/libdnet-stripped/src/intf-win32.c +@@ -427,6 +427,8 @@ intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen) + pcap_if_t *pdev, *selected; + intf_t *intf; + char errbuf[PCAP_ERRBUF_SIZE]; ++ HANDLE pcapMutex; ++ DWORD wait; + + if ((intf = intf_open()) == NULL) + return (-1); +@@ -441,10 +443,20 @@ intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen) + return (-1); + } + ++ pcapMutex = CreateMutex(NULL, 0, "Global\\DnetPcapHangAvoidanceMutex"); ++ wait = WaitForSingleObject(pcapMutex, INFINITE); + if (pcap_findalldevs(&pcapdevs, errbuf) == -1) { ++ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) { ++ ReleaseMutex(pcapMutex); ++ } ++ CloseHandle(pcapMutex); + intf_close(intf); + return (-1); + } ++ if (wait == WAIT_ABANDONED || wait == WAIT_OBJECT_0) { ++ ReleaseMutex(pcapMutex); ++ } ++ CloseHandle(pcapMutex); + + /* Loop through all the pcap devices until we find a match. */ + selected = NULL; + +o Avoid bailing completely when an interface is encountered with an unsupported + hardware address type. Caused "INTERFACES: NONE FOUND!" bugs in Nmap. + +diff --git a/libdnet-stripped/src/intf.c b/libdnet-stripped/src/intf.c +index b71fb82..315e7b0 100644 +--- a/libdnet-stripped/src/intf.c ++++ b/libdnet-stripped/src/intf.c +@@ -561,8 +561,11 @@ _intf_get_noalias(intf_t *intf, struct intf_entry *entry) + #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); ++ if (addr_ston(&ifr.ifr_addr, &entry->intf_link_addr) < 0) { ++ /* Likely we got an unsupported address type. Just use NONE for now. */ ++ entry->intf_link_addr.addr_type = ADDR_TYPE_NONE; ++ entry->intf_link_addr.addr_bits = 0; ++ } + #elif defined(SIOCRPHYSADDR) + /* Tru64 */ + struct ifdevea *ifd = (struct ifdevea *)𝔦 /* XXX */ + +o Retrieve the correct network prefix length for an adapter on Windows. If more + than one address was configured on an adapter, the same prefix length would + be used for both. This incorrect behavior is still used on Windows XP and + earlier. Reported by Niels Bohr. [Daniel Miller] + +diff --git a/libdnet-stripped/src/intf-win32.c b/libdnet-stripped/src/intf-win32.c +index 77225b6..baf02ce 100644 +--- a/libdnet-stripped/src/intf-win32.c ++++ b/libdnet-stripped/src/intf-win32.c +@@ -177,12 +177,23 @@ _adapter_address_to_entry(intf_t *intf, IP_ADAPTER_ADDRESSES *a, + OnLinkPrefixLength member that is stored right with the + unicast address. */ + bits = 0; ++ if (addr->Length >= 48) { ++ /* "The size of the IP_ADAPTER_UNICAST_ADDRESS structure changed on ++ * Windows Vista and later. The Length member should be used to determine ++ * which version of the IP_ADAPTER_UNICAST_ADDRESS structure is being ++ * used." ++ * Empirically, 48 is the value on Windows 8.1, so should include the ++ * OnLinkPrefixLength member.*/ ++ bits = addr->OnLinkPrefixLength; ++ } ++ else { + for (prefix = a->FirstPrefix; prefix != NULL; prefix = prefix->Next) { + if (prefix->Address.lpSockaddr->sa_family == addr->Address.lpSockaddr->sa_family) { + bits = (unsigned short) prefix->PrefixLength; + break; + } + } ++ } + + if (entry->intf_addr.addr_type == ADDR_TYPE_NONE) { + /* Set primary address if unset. */ + +o Avoid buffer overrun from scanning 32 chars plus terminator into a 16-byte buffer. + +diff --git a/libdnet-stripped/src/intf.c b/libdnet-stripped/src/intf.c +index 315e7b0..6180d85 100644 +--- a/libdnet-stripped/src/intf.c ++++ b/libdnet-stripped/src/intf.c +@@ -776,7 +776,8 @@ _intf_get_aliases(intf_t *intf, struct intf_entry *entry) + 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", ++ /* scan up to INTF_NAME_LEN-1 bytes to reserve space for null terminator */ ++ sscanf(buf, "%04s%04s%04s%04s%04s%04s%04s%04s %x %02x %02x %02x %15s\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) { + +o Detect SNMP MIB2 STREAMS on Solaris even if /dev/ip is not present, as it is + not in some Zones configurations. Using /dev/arp is proper in this case. + +diff --git a/libdnet-stripped/config/acinclude.m4 b/libdnet-stripped/config/acinclude.m4 +index 622c6a2..3145975 100644 +--- a/libdnet-stripped/config/acinclude.m4 ++++ b/libdnet-stripped/config/acinclude.m4 +@@ -161,12 +161,12 @@ dnl results: HAVE_STREAMS_MIB2 + dnl + AC_DEFUN(AC_DNET_STREAMS_MIB2, + [AC_MSG_CHECKING(for SNMP MIB2 STREAMS) +- AC_CACHE_VAL(ac_cv_dnet_streams_mib2, +- if test -f /usr/include/inet/mib2.h -a -c /dev/ip ; then ++ AC_CACHE_VAL(ac_cv_dnet_streams_mib2,[ ++ if test -f /usr/include/inet/mib2.h -a '(' -c /dev/ip -o -c /dev/arp ')' ; then + ac_cv_dnet_streams_mib2=yes + else + ac_cv_dnet_streams_mib2=no +- fi) ++ fi]) + AC_MSG_RESULT($ac_cv_dnet_streams_mib2) + if test $ac_cv_dnet_streams_mib2 = yes ; then + AC_DEFINE(HAVE_STREAMS_MIB2, 1, + +o Fix route detection on FreeBSD 11, where net/route.h requires sys/types.h + +Index: configure.in +=================================================================== +--- configure.in (revision 36845) ++++ configure.in (working copy) +@@ -165,10 +165,10 @@ + AC_CHECK_HEADERS(fcntl.h unistd.h) + AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi.h sys/dlpihdr.h sys/dlpi_ext.h \ + sys/ioctl.h sys/mib.h sys/ndd_var.h sys/socket.h sys/sockio.h \ +- sys/sysctl.h sys/time.h) ++ sys/sysctl.h sys/time.h sys/types.h) + AC_CHECK_HEADERS(net/bpf.h net/if.h net/if_var.h \ + net/if_arp.h net/if_dl.h net/pfilt.h \ +- net/pfvar.h net/radix.h net/raw.h net/route.h netinet/in_var.h \ ++ net/pfvar.h net/radix.h net/raw.h netinet/in_var.h \ + netinet/in6_var.h \ + net/if_tun.h linux/if_tun.h netinet/ip_fw.h linux/ip_fw.h \ + linux/ip_fwchains.h linux/netfilter_ipv4/ipchains_core.h) +@@ -175,6 +175,12 @@ + AC_CHECK_HEADERS(ip_fil_compat.h netinet/ip_fil_compat.h ip_compat.h \ + netinet/ip_compat.h ip_fil.h netinet/ip_fil.h) + AC_CHECK_HEADERS(hpsecurity.h stropts.h) ++ AC_CHECK_HEADERS(net/route.h, [], [], ++ [ ++#ifdef HAVE_SYS_SOCKET_H ++#include ++#endif ++ ]) + fi + + dnl Checks for typedefs, structures, and compiler characteristics. + +o Ensure we read 1 byte less than buffer size to allow for automatically-appended null char. + +diff --git a/libdnet-stripped/src/arp-ioctl.c b/libdnet-stripped/src/arp-ioctl.c +index 434142e..31b9f8c 100644 +--- a/libdnet-stripped/src/arp-ioctl.c ++++ b/libdnet-stripped/src/arp-ioctl.c +@@ -218,7 +218,7 @@ arp_loop(arp_t *a, arp_handler callback, void *arg) + + ret = 0; + while (fgets(buf, sizeof(buf), fp) != NULL) { +- i = sscanf(buf, "%s 0x%x 0x%x %100s %100s %100s\n", ++ i = sscanf(buf, "%s 0x%x 0x%x %99s %99s %99s\n", + ipbuf, &type, &flags, macbuf, maskbuf, devbuf); + + if (i < 4 || (flags & ATF_COM) == 0) + +o REVERTED the change that added a mutex protecting calls to OpenServiceA. We + are optimistic that Npcap does not have the reported problem. + +o Add support for new loopback behavior in Npcap 0.9983. There is no KM-TEST + adapter in GetAdaptersAddresses in this case. + +diff --git a/libdnet-stripped/src/intf-win32.c b/libdnet-stripped/src/intf-win32.c +index 1399db2..352da4c 100644 +--- a/libdnet-stripped/src/intf-win32.c ++++ b/libdnet-stripped/src/intf-win32.c +@@ -26,6 +26,7 @@ + #include + + int g_has_npcap_loopback = 0; ++#define _DEVICE_PREFIX "\\Device\\" + + struct ifcombo { + struct { +@@ -214,6 +215,10 @@ _adapter_address_to_entry(intf_t *intf, IP_ADAPTER_ADDRESSES *a, + + #define NPCAP_SERVICE_REGISTRY_KEY "SYSTEM\\CurrentControlSet\\Services\\npcap" + ++/* The name of the Npcap loopback adapter is stored in the npcap service's ++ * Registry key in the LoopbackAdapter value. For legacy loopback support, this ++ * is a name like "NPF_{GUID}", but for newer Npcap the name is "NPF_Loopback" ++ */ + int intf_get_loopback_name(char *buffer, int buf_size) + { + HKEY hKey; +@@ -252,43 +257,65 @@ _update_tables_for_npcap_loopback(IP_ADAPTER_ADDRESSES *p) + IP_ADAPTER_ADDRESSES *a_original_loopback_prev = NULL; + IP_ADAPTER_ADDRESSES *a_original_loopback = NULL; + IP_ADAPTER_ADDRESSES *a_npcap_loopback = NULL; +- char npcap_loopback_name[1024]; +- int has_npcap_loopback = 0; ++ static char npcap_loopback_name[1024] = {0}; + +- g_has_npcap_loopback = has_npcap_loopback = intf_get_loopback_name(npcap_loopback_name, 1024); +- if (has_npcap_loopback == 0) ++ /* Don't bother hitting the registry every time. Not ideal for long-running ++ * processes, but works for Nmap. */ ++ if (npcap_loopback_name[0] == '\0') ++ g_has_npcap_loopback = intf_get_loopback_name(npcap_loopback_name, 1024); ++ if (g_has_npcap_loopback == 0) + return p; + + if (!p) + return p; + ++ /* Loop through the addresses looking for the dummy loopback interface from Windows. */ + for (a = p; a != NULL; a = a->Next) { + if (a->IfType == IF_TYPE_SOFTWARE_LOOPBACK) { ++ /* Dummy loopback. Keep track of it. */ + a_original_loopback = a; + a_original_loopback_prev = a_prev; + } +- else if (strcmp(a->AdapterName, npcap_loopback_name + strlen("\\Device\\")) == 0) { ++ else if (strcmp(a->AdapterName, npcap_loopback_name + strlen(_DEVICE_PREFIX) - 1) == 0) { ++ /* Legacy loopback adapter. The modern one doesn't show up in GetAdaptersAddresses. */ + a_npcap_loopback = a; + } + a_prev = a; + } + +- if (!a_original_loopback || !a_npcap_loopback) ++ /* If there's no loopback on this system, something's wrong. Windows is ++ * supposed to create this. */ ++ if (!a_original_loopback) + return p; +- +- a_npcap_loopback->IfType = a_original_loopback->IfType; +- a_npcap_loopback->FirstUnicastAddress = a_original_loopback->FirstUnicastAddress; +- a_npcap_loopback->FirstPrefix = a_original_loopback->FirstPrefix; +- memset(a_npcap_loopback->PhysicalAddress, 0, ETH_ADDR_LEN); +- if (a_original_loopback_prev) { +- a_original_loopback_prev->Next = a_original_loopback_prev->Next->Next; ++ /* If we didn't find the legacy adapter, use the modern adapter name. */ ++ if (!a_npcap_loopback) { ++ /* Overwrite the name we got from the Registry, in case it's a broken legacy ++ * install, in which case we'll never find the legacy adapter anyway. */ ++ strlcpy(npcap_loopback_name, _DEVICE_PREFIX "NPF_Loopback", 1024); ++ /* Overwrite the AdapterName from the system's own loopback adapter with ++ * the NPF_Loopback name. This is what we use to open the adapter with ++ * Packet.dll later. */ ++ a_original_loopback->AdapterName = npcap_loopback_name + sizeof(_DEVICE_PREFIX) - 1; + return p; + } +- else if (a_original_loopback == p) { +- return a_original_loopback->Next; +- } + else { +- return p; ++ /* Legacy loopback adapter was found. Copy some key info from the system's ++ * loopback adapter. */ ++ a_npcap_loopback->IfType = a_original_loopback->IfType; ++ a_npcap_loopback->FirstUnicastAddress = a_original_loopback->FirstUnicastAddress; ++ a_npcap_loopback->FirstPrefix = a_original_loopback->FirstPrefix; ++ memset(a_npcap_loopback->PhysicalAddress, 0, ETH_ADDR_LEN); ++ /* Unlink the original loopback adapter from the list. We'll use Npcap's instead. */ ++ if (a_original_loopback_prev) { ++ a_original_loopback_prev->Next = a_original_loopback_prev->Next->Next; ++ return p; ++ } ++ else if (a_original_loopback == p) { ++ return a_original_loopback->Next; ++ } ++ else { ++ return p; ++ } + } + } + +@@ -551,11 +578,17 @@ intf_get_pcap_devname_cached(const char *intf_name, char *pcapdev, int pcapdevle + for (pdev = pcapdevs; pdev != NULL; pdev = pdev->next) { + char *name; + +- if (pdev->name == NULL) +- continue; +- name = strchr(pdev->name, '{'); +- if (name == NULL) ++ if (pdev->name == NULL || strlen(pdev->name) < sizeof(_DEVICE_PREFIX)) + continue; ++ /* "\\Device\\NPF_{GUID}" ++ * "\\Device\\NPF_Loopback" ++ * Find the '{'after device prefix. ++ */ ++ name = strchr(pdev->name + sizeof(_DEVICE_PREFIX) - 1, '{'); ++ if (name == NULL) { ++ /* If no GUID, just match the whole device name */ ++ name = pdev->name + sizeof(_DEVICE_PREFIX) - 1; ++ } + if (strcmp(name, a->AdapterName) == 0) + break; + } + +o Remove call to FreeLibrary after GetModuleHandle. Windows API docs say: +"do not pass a handle returned by GetModuleHandle to the FreeLibrary function. +Doing so can cause a DLL module to be unmapped prematurely." + +diff --git a/libdnet-stripped/src/route-win32.c b/libdnet-stripped/src/route-win32.c +index c69b29b..8a9d2bc 100644 +--- a/libdnet-stripped/src/route-win32.c ++++ b/libdnet-stripped/src/route-win32.c +@@ -269,8 +269,6 @@ route_t * + route_close(route_t *r) + { + if (r != NULL) { +- if (r->iphlpapi != NULL) +- FreeLibrary(r->iphlpapi); + if (r->ipftable != NULL) + free(r->ipftable); + if (r->ipftable2 != NULL) +o Additional fix for route detection on FreeBSD 11, where net/route.h + requires sys/types.h +--- a/libdnet-stripped/configure.in 2020-10-14 21:08:09.275534843 -0600 ++++ b/libdnet-stripped/configure.in 2022-03-23 18:02:44.842111434 -0600 +@@ -177,6 +177,7 @@ + AC_CHECK_HEADERS(hpsecurity.h stropts.h) + AC_CHECK_HEADERS(net/route.h, [], [], + [ ++AC_INCLUDES_DEFAULT + #ifdef HAVE_SYS_SOCKET_H + #include + #endif -- cgit v1.2.3