summaryrefslogtreecommitdiffstats
path: root/libdnet-stripped/NMAP_MODIFICATIONS
diff options
context:
space:
mode:
Diffstat (limited to 'libdnet-stripped/NMAP_MODIFICATIONS')
-rw-r--r--libdnet-stripped/NMAP_MODIFICATIONS2575
1 files changed, 2575 insertions, 0 deletions
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(&eth, &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 <string.h>
+
+ #include "dnet.h"
++#include "pcap.h"
++#include <Packet32.h>
++#include <Ntddndis.h>
+
+ 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 <netinet/sctp.h> 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 <netpacket/packet.h>
++#include <linux/if_ether.h>
++])
++ 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 <netinet/if_ether.h>
+ #include <nlist.h>
+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 <net/route.h>
+ #undef route_t
++#include <net/if.h>
+ #include <netinet/in.h>
+
+ #include <errno.h>
+@@ -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 <sys/uio.h>
+
+ #include <asm/types.h>
++#include <net/if.h>
+ #include <netinet/in.h>
+ #include <linux/netlink.h>
+ #include <linux/rtnetlink.h>
+@@ -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 <david@bamsoftware.com>
+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 <sys/sockio.h>
+ #endif
+ /* XXX - AIX */
++#ifdef HAVE_GETKERNINFO
++#include <sys/ndd_var.h>
++#include <sys/kinfo.h>
++#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 *)&ifr; /* 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 <sys/socket.h>
++#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 <Ntddndis.h>
+
+ 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 <sys/socket.h>
+ #endif