diff --git a/nbase/nbase_addrset.c b/nbase/nbase_addrset.c index 6f91bc1b2a..849044e4e3 100644 --- a/nbase/nbase_addrset.c +++ b/nbase/nbase_addrset.c @@ -477,30 +477,32 @@ static int sockaddr_to_addr(const struct sockaddr *sa, u32 *addr) static int sockaddr_to_mask (const struct sockaddr *sa, int bits, u32 *mask) { - s8 i; - int unmasked_bits = 0; + int i, k; if (bits >= 0) { if (sa->sa_family == AF_INET) { - unmasked_bits = 32 - bits; + bits += 96; } #ifdef HAVE_IPV6 else if (sa->sa_family == AF_INET6) { - unmasked_bits = 128 - bits; + ; /* do nothing */ } #endif else { return 0; } } + else + bits = 128; + k = bits / 32; for (i=0; i < 4; i++) { - if (unmasked_bits <= 32 * (3 - i)) { + if (i < k) { mask[i] = 0xffffffff; } - else if (unmasked_bits >= 32 * (4 - i)) { + else if (i > k) { mask[i] = 0; } else { - mask[i] = ~((1 << (unmasked_bits - (32 * (4 - i)))) - 1); + mask[i] = 0xfffffffe << (31 - bits % 32); } } return 1; diff --git a/ncat/test/test-addrset.sh b/ncat/test/test-addrset.sh index 7f54023c52..285c7b675a 100755 --- a/ncat/test/test-addrset.sh +++ b/ncat/test/test-addrset.sh @@ -208,6 +208,25 @@ test_addrset "1:2::0003/120" "1:2::3 1:2::0 1:2::ff" <<EOF 1:3::3 EOF +# IPv6 CIDR netmask. +test_addrset "1:2::3:4:5/95" "1:2::3:4:5 1:2::2:0:0 1:2::3:ffff:ffff" <<EOF +1:2::3:4:5 +1:2::1:ffff:ffff +1:2::2:0:0 +1:2::3:ffff:ffff +1:2::4:0:0 +1:3::3 +EOF + +# IPv6 CIDR netmask. +test_addrset "11::2/15" "11::2:3:4:5 10::1 11:ffff:ffff:ffff:ffff:ffff:ffff:ffff" <<EOF +11::2:3:4:5 +9:ffff:ffff:ffff:ffff:ffff:ffff:ffff +10::1 +11:ffff:ffff:ffff:ffff:ffff:ffff:ffff +12::0 +EOF + # /128 netmask. test_addrset "1:2::0003/128" "1:2::3" <<EOF 1:2::3