diff --git a/CHANGELOG b/CHANGELOG index 456658f11..92530d9e2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ #Nmap Changelog ($Id$); -*-text-*- +o [GH#2257] Fix an issue in addrset matching that was causing all targets to be + excluded if the --excludefile listed a CIDR range that contains an earlier, + smaller CIDR range. [Daniel Miller] + o [NSE][GH#2237] Prevent the ssl-* NSE scripts from probing ports that were excluded from version scan, usually 9100-9107, since JetDirect will print anything sent to these ports. [Daniel Miller] diff --git a/nbase/nbase_addrset.c b/nbase/nbase_addrset.c index 27acb9552..be1bb9a27 100644 --- a/nbase/nbase_addrset.c +++ b/nbase/nbase_addrset.c @@ -65,6 +65,7 @@ #include /* CHAR_BIT */ #include +#include #include "nbase.h" @@ -295,7 +296,7 @@ static struct trie_node *new_trie_node(const u32 *addr, const u32 *mask) /* Split a node into 2: one that matches the greatest common prefix with addr * and one that does not. */ -static void trie_split (struct trie_node *this, const u32 *addr) +static void trie_split (struct trie_node *this, const u32 *addr, const u32 *mask) { struct trie_node *new_node; u32 new_mask[4] = {0,0,0,0}; @@ -303,10 +304,31 @@ static void trie_split (struct trie_node *this, const u32 *addr) /* Calculate the mask of the common prefix */ for (i=0; i < 4; i++) { new_mask[i] = common_mask(this->addr[i], addr[i]); + if (new_mask[i] > this->mask[i]){ + /* Addrs have more bits in common than we care about for this node. */ + new_mask[i] = this->mask[i]; + } + if (new_mask[i] > mask[i]) { + /* new addr's mask is broader, so this node is superseded. */ + this->mask[i] = mask[i]; + for (i++; i < 4; i++) { + this->mask[i] = 0; + } + /* The longer mask is superseded. Delete following nodes. */ + trie_free(this->next_bit_one); + trie_free(this->next_bit_zero); + /* Anything below here will always match. */ + this->next_bit_one = this->next_bit_zero = TRIE_NODE_TRUE; + return; + } if (new_mask[i] < 0xffffffff) { break; } } + if (new_mask[i] >= this->mask[i]) { + /* This node completely contains the new addr and mask. No need to split or add */ + return; + } /* Make a copy of this node to continue matching what it has been */ new_node = new_trie_node(this->addr, this->mask); new_node->next_bit_one = this->next_bit_one; @@ -329,35 +351,14 @@ static void trie_split (struct trie_node *this, const u32 *addr) /* Helper for address insertion */ static void _trie_insert (struct trie_node *this, const u32 *addr, const u32 *mask) { - u8 i; + /* On entry, at least the 1st bit must match this node */ + assert(this == TRIE_NODE_TRUE || (this->addr[0] ^ addr[0]) < (1 << 31)); + while (this != NULL && this != TRIE_NODE_TRUE) { - if (addr_matches(this->mask, this->addr, addr)) { - if (1 & this->mask[3]) { - /* 1. end of address: duplicate. return; */ - return; - } - } - else { - /* Split the netmask to ensure a match */ - trie_split(this, addr); - } - - for (i=0; i < 4; i++) { - if (this->mask[i] > mask[i]) { - /* broader mask, truncate this one */ - this->mask[i] = mask[i]; - for (; i < 4; i++) { - this->mask[i] = 0; - } - /* The longer mask is superseded. Delete following nodes. */ - trie_free(this->next_bit_one); - trie_free(this->next_bit_zero); - /* Anything below here will always match. */ - this->next_bit_one = this->next_bit_zero = TRIE_NODE_TRUE; - return; - } - } + /* Split the node if necessary to ensure a match */ + trie_split(this, addr, mask); + /* At this point, this node matches the addr up to this->mask. */ if (addr_next_bit_is_one(this->mask, addr)) { /* next bit is one: insert on the one branch */ if (this->next_bit_one == NULL) { diff --git a/ncat/test/test-addrset.sh b/ncat/test/test-addrset.sh index 285c7b675..819afe2f3 100755 --- a/ncat/test/test-addrset.sh +++ b/ncat/test/test-addrset.sh @@ -21,10 +21,10 @@ test_addrset() { result=$(echo $result) TESTS=$(expr $TESTS + 1); if [ "$ret" != "0" ]; then - echo "FAIL $ADDRSET returned $ret." + echo "FAIL $specs: $ADDRSET returned $ret." TEST_FAIL=$(expr $TEST_FAIL + 1) elif [ "$result" != "$expected" ]; then - echo "FAIL \"$result\" !=" + echo "FAIL $specs: \"$result\" !=" echo " \"$expected\"." TEST_FAIL=$(expr $TEST_FAIL + 1) else