From 0674925f73f96f5ac52c3a3a5b1799f5ac6d8522 Mon Sep 17 00:00:00 2001 From: david Date: Mon, 10 Sep 2012 01:17:28 +0000 Subject: [PATCH] Skip over entire ifreq struct in NEXTIFR. On platforms supporting sa_len, NEXTIFR would skip over sa_len bytes starting at the beginning of ifr_addr, and assume that was the end of the struct. (The idea being that a large address such as a sockaddr_in6 could overflow the nominal struct boundary.) This logic was wrong when there was something else in the union bigger than sa_len; we would increment into somewhere in the middle of the same struct. This exhibited itself on NetBSD, where struct ifreq has a sockaddr_storage member in its internal union: struct ifreq { char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ union { struct sockaddr ifru_addr; struct sockaddr ifru_dstaddr; struct sockaddr ifru_broadaddr; struct sockaddr_storage ifru_space; No, we skip over sa_len bytes, or to the nominal end of the struct, whichever is larger. Unix Network Programming gets this wrong too; in figure 17.8 they do ptr += sizeof(ifr->ifr_name) + max(sizeof(struct sockaddr), ifr->ifr_addr.sa_len); --- CHANGELOG | 3 +++ libdnet-stripped/NMAP_MODIFICATIONS | 22 ++++++++++++++++++++++ libdnet-stripped/src/intf.c | 7 ++++--- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index dea75d81b..1ad132139 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ # Nmap Changelog ($Id$); -*-text-*- +o Fixed interface listing on NetBSD. The bug was first noticed by + Fredrik Pettai and diagnosed by Jan Schaumann. [David Fifield] + o [Ncat] Applied a blocking-socket workaround for a bug that could prevent some sends from working in listen mode. The problem was reported by Jonas Wielicki. [Alex Weber, David Fifield] diff --git a/libdnet-stripped/NMAP_MODIFICATIONS b/libdnet-stripped/NMAP_MODIFICATIONS index 7f9fe6590..1db45b682 100644 --- a/libdnet-stripped/NMAP_MODIFICATIONS +++ b/libdnet-stripped/NMAP_MODIFICATIONS @@ -1177,3 +1177,25 @@ index 6a32958..973f16c 100644 } 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 diff --git a/libdnet-stripped/src/intf.c b/libdnet-stripped/src/intf.c index 865e50080..4fe059c70 100644 --- a/libdnet-stripped/src/intf.c +++ b/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