Nmap Development mailing list archives

[PATCH] Fix IPv6 scanning against link-local addresses


From: Kris Katterjohn <katterjohn () gmail com>
Date: Mon, 19 May 2008 13:20:02 -0500

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hey everyone,

In the recent discussion on IPv6 support on Windows, Jah noted[1] that
Nmap wasn't handling the Zone ID[2] correctly.  This prohibited scanning
IPv6 link-local addresses, usually by way of ICMP net or host unreaches.

But Windows wasn't the only OS not working; I found out I couldn't scan
link-local addresses on Linux either.

I've attached a small patch to make Nmap understand the percent syntax
for IPv6 Zone IDs, both numeric indexes and interface names.  Windows
only supports numeric indexes, but Linux and some other OSs can also
handle interface names as well. Ex:

fe80::20f:b0ff:fec6:15af%2 (Windows can only do this)
fe80::20f:b0ff:fec6:15af%eth0 (Linux and others can do this too)

I've tested it on Windows XP and Linux, and they both work great against
link-local addresses now.  The local target host is running Windows XP
(no firewall), and I'm getting syn-ack's for ports 135 (msrpc) and 1025,
and conn-refused's for other ports instead of the *-unreach's (Windows)
and no-response's (Linux) I was getting before.

I had a hunch that the struct sockaddr_in6 sin6_scope_id member was the
way to handle this, and it certainly seems to be.  If the zone ID passed
to Nmap is numeric, that number is just stored in that member.  If the
ID is not fully numeric, it is assumed to be an interface name.  I added
the ifindex member to struct interface_info and I look it up with
getInterfaceByName().

Any testing will be appreciated, especially on other OSs (like Vista and
*BSD).

Thanks,
Kris Katterjohn

[1] http://seclists.org/nmap-dev/2008/q2/0278.html
[2] http://en.wikipedia.org/wiki/Ipv6#Zone_indices

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQIVAwUBSDHE0P9K37xXYl36AQK5MQ/+MJBLNls8uss9MlsFNut+SG8hO2bYwSXc
g8bPPyFeKDhIAUqhSd73uqRjH93NJBA6gU07yH4AsBh0twBBkaLS3YmD1vo98F9r
RAYBdZWnQPH9uI8HA5BLrnsQQHk3FKFICZM7bFx2wgbV/JOXkS4hrzAb1lgWfqQP
8ArdGigRRRb08ANQaoMysM/Qvrdo9dGW4Xyqq2RmlqZAF5iTQyx9jfxsVxVI6EVJ
4jcHkHHqyKjsSIGf3derETIPoU/jTGsvcykUs22WTj//kHT7waPIDqZ1oMAG2s7m
Zo9K8YsdFUFF0cypzCpbuhQsnUFWpxdRu9/I7qrb1CpumA/UPZNyE/CqNhHnLsVK
7R2xG5MIoNKX8Rgox8BDum4E/XZm3Yr/4enj5BR+nmG/Vx7pKUgpPrOB+Yu3V7Yi
1xLN6PArskZ00JkdyIc3+Kg34jawzgVVGR5Lk2YlqEVEqm04hEmNuVoqj0LKHlHu
NFLqpyGvbeQkQPYm3RVRsqNeEBYqjPd/dPZbWTvunwxPc2eQFRU/vzMGG+1IU1Zi
77DgrmjwZB02gT4hP07UUHzU1H3/iHeGBaG3R90csGSh+eYVPNf8DIpFH40AaRNC
bidUAwhhJjK7u0ztkqvTVVctLHLNKQu3XGfYt8QUGpCSA7exeegK20iacXUDEOGA
ZomAhZCacK0=
=QxQo
-----END PGP SIGNATURE-----
Index: tcpip.cc
===================================================================
--- tcpip.cc    (revision 7540)
+++ tcpip.cc    (working copy)
@@ -2824,6 +2824,8 @@
        mydevs[numifaces].device_type = devt_p2p;
       else mydevs[numifaces].device_type = devt_other;
 
+      mydevs[numifaces].ifindex = ifr->ifr_ifindex;
+
       if (ifflags & IFF_UP)
        mydevs[numifaces].device_up = true;
       else mydevs[numifaces].device_up = false;
Index: tcpip.h
===================================================================
--- tcpip.h     (revision 7540)
+++ tcpip.h     (working copy)
@@ -290,6 +290,7 @@
   devtype device_type; /* devt_ethernet, devt_loopback, devt_p2p, devt_other */
   bool device_up; /* True if the device is up (enabled) */
   u8 mac[6]; /* Interface MAC address if device_type is devt_ethernet */
+  u32 ifindex; /* Interface index, used for IPv6 scope zone ID */
 };
 
 struct route_nfo {
Index: TargetGroup.cc
===================================================================
--- TargetGroup.cc      (revision 7540)
+++ TargetGroup.cc      (working copy)
@@ -104,6 +104,7 @@
 #include "TargetGroup.h"
 #include "NmapOps.h"
 #include "nmap_error.h"
+#include "tcpip.h"
 
 extern NmapOps o;
 
@@ -295,8 +296,32 @@
       return 1;
     }
     assert(result->ai_addrlen == sizeof(struct sockaddr_in6));
+    memset(&ip6, 0, sizeof ip6);
     struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) result->ai_addr;
-    memcpy(ip6.s6_addr, sin6->sin6_addr.s6_addr, 16);
+    memcpy(ip6.sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, 16);
+    if ((r = strchr(hostexp, '%'))) {
+      r++;
+      if (strspn(r, "0123456789") == strlen(r))
+        ip6.sin6_scope_id = atoi(r);
+      else {
+#ifdef WIN32
+        error("Invalid zone ID for IPv6 address: %s (should be a numeric index)", hostexp);
+        free(hostexp);
+        freeaddrinfo(result);
+        return 1;
+#else
+        struct interface_info *ifn = getInterfaceByName(r);
+        if (ifn)
+          ip6.sin6_scope_id = ifn->ifindex;
+        else {
+          error("Invalid zone ID for IPv6 address: %s (should be a valid interface name or a numeric index)", hostexp);
+          free(hostexp);
+          freeaddrinfo(result);
+          return 1;
+        }
+#endif
+      }
+    }
     ipsleft = 1;
     freeaddrinfo(result);
 #else // HAVE_IPV6
@@ -443,7 +468,8 @@
 #ifdef SIN_LEN
     sin6->sin6_len = *sslen;
 #endif /* SIN_LEN */
-    memcpy(sin6->sin6_addr.s6_addr, ip6.s6_addr, 16);
+    memcpy(sin6->sin6_addr.s6_addr, ip6.sin6_addr.s6_addr, 16);
+    sin6->sin6_scope_id = ip6.sin6_scope_id;
 #else
     fatal("IPV6 not supported on this platform");
 #endif // HAVE_IPV6
Index: TargetGroup.h
===================================================================
--- TargetGroup.h       (revision 7540)
+++ TargetGroup.h       (working copy)
@@ -143,7 +143,7 @@
   void Initialize();
 
 #if HAVE_IPV6
-  struct in6_addr ip6;
+  struct sockaddr_in6 ip6;
 #endif
 
   /* These 4 are used for the '/mask' style of specifying target 

_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org

Current thread: