$Id: NMAP_MODIFICATIONS 9853 2008-08-30 04:39:30Z david $

This is Dug Song's excellent Libdnet networking library version 1.10.
It has been stripped down for inclusion within Nmap and modified as follows:

o Removed the following directories:
  python, test, man

o Removed all filenames from EXTRA_libdnet_la_SOURCES sources, as
  they aren't needed with GNU automake 1.9.2

o Removed the fw-* files except for fw-none because Nmap doesn't use
  the firewall API.  Changed configure.in to always use fw-non.

o Removed files in now-removed dires that were reference from
  configure.in:318

o Ran "aclocal -I . -I config" to regenerate aclocal.m4 with my newer
  aclocal.

o Replaced config.guess config.sub and missing in config dir with
  versions from Autoconf 2.59.

o Added this NMAP_MODIFICATIONS file.

o Added include/winconfig.h, which is a modified config.h to better support
  Windows compilation via Visual Studio.  Added conditional includes
  for it to a bunch of the dnet source files.

o A number of portability changes to remove errors/warnings during
  Win32 Visual Studio.Net compilation.  This was mostly a matter of
  adding casts and a few extra include files.

o Added libdnet-stripped.vcproj -- A Visual Studio.Net project file
  for dnet.

o Rewrote eth_open() for Win32 as its technique for translating from
  a dnet-named interface to a pcap-named one did not work on any of my
  systems.

o Increase the number of available bpf devices from 32 to 128.  Patch:
--- eth-bsd.c   (revision 2774)
+++ eth-bsd.c   (working copy)
@@ -45,7 +45,7 @@
        int i;
 
        if ((e = calloc(1, sizeof(*e))) != NULL) {
-               for (i = 0; i < 32; i++) {
+               for (i = 0; i < 128; i++) {
                        snprintf(file, sizeof(file), "/dev/bpf%d", i);
                        e->fd = open(file, O_WRONLY);
                        if (e->fd != -1 || errno != EBUSY)


o Made some code changes to intf.c (the patch below).  This does the following:

  o Preserve the alias qualifier from interface name in more cases
    (e.g. don't blow away :2 from eth0:2 when it may still be needed.

  o Set the SO_BROADCAST flag on the interface list descriptor so that
    broadcast/network IPs can be investigated.

  o Update _match_intf_src so that it checks interface aliases for the
    given source address rather than only the main interface address.

diff -Nruw old/src/intf.c nmap-3.83.new/src/intf.c
--- src/intf.c  2005-05-03 09:41:35.000000000 -0700
+++ src/intf.c  2005-07-16 20:55:05.000000000 -0700
@@ -119,12 +119,16 @@
 intf_open(void)
 {
        intf_t *intf;
+       int one = 1;
 
        if ((intf = calloc(1, sizeof(*intf))) != NULL) {
                intf->fd = intf->fd6 = -1;
 
                if ((intf->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
                        return (intf_close(intf));
+
+               setsockopt(intf->fd, SOL_SOCKET, SO_BROADCAST, 
+                          (const char *) &one, sizeof(one));
 #ifdef SIOCGIFNETMASK_IN6
                if ((intf->fd6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
 #  ifdef EPROTONOSUPPORT
@@ -472,6 +476,7 @@
 _intf_get_aliases(intf_t *intf, struct intf_entry *entry)
 {
        struct ifreq *ifr, *lifr;
+       struct ifreq tmpifr;
        struct addr *ap, *lap;
        char *p;
 
@@ -492,9 +497,12 @@
                if ((p = strchr(ifr->ifr_name, ':')) != NULL)
                        *p = '\0';
 
-               if (strcmp(ifr->ifr_name, entry->intf_name) != 0)
+               if (strcmp(ifr->ifr_name, entry->intf_name) != 0) {
+                 if (p) *p = ':';
                        continue;
+               }
 
+               if (p) *p = ':'; /* Fix the name back up */
                if (addr_ston(&ifr->ifr_addr, ap) < 0)
                        continue;
 
@@ -506,6 +514,11 @@
                        if (ap->addr_ip == entry->intf_addr.addr_ip ||
                            ap->addr_ip == entry->intf_dst_addr.addr_ip)
                                continue;
+                       strlcpy(tmpifr.ifr_name, ifr->ifr_name, 
+                              sizeof(tmpifr.ifr_name));
+                       if (ioctl(intf->fd, SIOCGIFNETMASK, &tmpifr) == 0)
+                         addr_stob(&tmpifr.ifr_addr, &ap->addr_bits);
+
                }
 #ifdef SIOCGIFNETMASK_IN6
                else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) {
@@ -547,10 +560,22 @@
 static int
 _match_intf_src(const struct intf_entry *entry, void *arg)
 {
+       int matched = 0;
+       int cnt;
        struct intf_entry *save = (struct intf_entry *)arg;
 
        if (entry->intf_addr.addr_type == ADDR_TYPE_IP &&
-           entry->intf_addr.addr_ip == save->intf_addr.addr_ip) {
+           entry->intf_addr.addr_ip == save->intf_addr.addr_ip)
+         matched = 1;
+  
+       for (cnt = 0; !matched && cnt < (int) entry->intf_alias_num; cnt++) {
+         if (entry->intf_alias_addrs[cnt].addr_type != ADDR_TYPE_IP)
+           continue;
+         if (entry->intf_alias_addrs[cnt].addr_ip == save->intf_addr.addr_ip)
+           matched = 1;
+       }
+
+       if (matched) {
                /* XXX - truncated result if entry is too small. */
                if (save->intf_len < entry->intf_len)
                        memcpy(save, entry, save->intf_len);
@@ -678,14 +703,18 @@
                if ((p = strchr(ifr->ifr_name, ':')) != NULL)
                        *p = '\0';
 
-               if (pifr != NULL && strcmp(ifr->ifr_name, pifr->ifr_name) == 0)
+               if (pifr != NULL && strcmp(ifr->ifr_name, pifr->ifr_name) == 0) {
+                 if (p) *p = ':';
                        continue;
+               }
 
                memset(ebuf, 0, sizeof(ebuf));
                strlcpy(entry->intf_name, ifr->ifr_name,
                    sizeof(entry->intf_name));
                entry->intf_len = sizeof(ebuf);
 
+               /* Repair the alias name back up. */
+               if (p) *p = ':';
                if (_intf_get_noalias(intf, entry) < 0)
                        return (-1);
                if (_intf_get_aliases(intf, entry) < 0)



o Consider Windows interfaces to be down if they are disconnected, unreachable, or otherwise non-operational:

--- intf-win32.c        (revision 2976)
+++ intf-win32.c        (working copy)
@@ -116,7 +116,9 @@

        /* Get interface flags. */
        entry->intf_flags = 0;
-       if (ifrow->dwAdminStatus == MIB_IF_ADMIN_STATUS_UP)
+       if (ifrow->dwAdminStatus == MIB_IF_ADMIN_STATUS_UP &&
+           (ifrow->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL ||
+            ifrow->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED))
                entry->intf_flags |= INTF_FLAG_UP;
        if (ifrow->dwType == MIB_IF_TYPE_LOOPBACK)
                entry->intf_flags |= INTF_FLAG_LOOPBACK;

o Made some AIX/HP-UX portability changes sent in by Peter O'Gorman
(nmap-dev@mlists.thewrittenword.com):


Index: include/dnet/ip6.h
===================================================================
--- include/dnet/ip6.h  (revision 3309)
+++ include/dnet/ip6.h  (working copy)
@@ -25,7 +25,9 @@
 } ip6_addr_t;

 #ifndef __GNUC__
+#ifndef __attribute__
 # define __attribute__(x)
+#endif
 # pragma pack(1)
 #endif

Index: include/dnet/ip.h
===================================================================
--- include/dnet/ip.h   (revision 3309)
+++ include/dnet/ip.h   (working copy)
@@ -25,7 +25,9 @@
 typedef uint32_t       ip_addr_t;

 #ifndef __GNUC__
+#ifndef __attribute__
 # define __attribute__(x)
+#endif
 # pragma pack(1)
 #endif

Index: include/dnet/arp.h
===================================================================
--- include/dnet/arp.h  (revision 3309)
+++ include/dnet/arp.h  (working copy)
@@ -16,7 +16,9 @@
 #define ARP_ETHIP_LEN  20      /* base ARP message length */

 #ifndef __GNUC__
+#ifndef __attribute__
 # define __attribute__(x)
+#endif
 # pragma pack(1)
 #endif

Index: include/dnet/tcp.h
===================================================================
--- include/dnet/tcp.h  (revision 3309)
+++ include/dnet/tcp.h  (working copy)
@@ -17,7 +17,9 @@
 #define TCP_HDR_LEN_MAX        (TCP_HDR_LEN + TCP_OPT_LEN_MAX)

 #ifndef __GNUC__
+#ifndef __attribute__
 # define __attribute__(x)
+#endif
 # pragma pack(1)
 #endif

Index: include/dnet/icmp.h
===================================================================
--- include/dnet/icmp.h (revision 3309)
+++ include/dnet/icmp.h (working copy)
@@ -16,7 +16,9 @@
 #define ICMP_LEN_MIN   8       /* minimum ICMP message size, with header */

 #ifndef __GNUC__
+#ifndef __attribute__
 # define __attribute__(x)
+#endif
 # pragma pack(1)
 #endif

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 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 Fix a compiler "may be used unitialized" warning:
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 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: NMAP_MODIFICATIONS 9853 2008-08-30 04:39:30Z david $
 
 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);

Added eth_get_pcap_devname that matches up a dnet name to its pcap
equivalent. It starts by matching interfaces IP addresses, then falls
back to matching hardware addresses. The hardware address matching code
is adapted from libdnet 1.11.

Copied include/dnet/os.h from libdnet 1.12 to avoid a duplicate typedef
of ssize_t.
