mirror of
https://github.com/nmap/nmap.git
synced 2026-02-11 07:56:35 +00:00
Fix addrset matching with overlapping CIDR specs. Fixes #2257
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
|
||||
#include <limits.h> /* CHAR_BIT */
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user