Discussion:
IPv6 prefix-length struggle
(too old to reply)
ElChino
2016-11-27 14:11:42 UTC
Permalink
I'm having some troubles figuring out the CIDR "prefix length"
of a IPv6 addresses range.

Specifically, in some code that reads MaxMind's GeoIPv6.dat records,
the low and high IP-numbers of IPv6-blocks are given like:
IP-num low: 76:96:42:219::
IP-num high: 76:96:42:219:ffff:ffff:ffff:ffff
(belonging to 'United States')

I need to figure out how to print this using CIDR notation.
E.g. if I have the 2 above addresses in
struct in6_addr a, b;

I've cooked up this function after much head-scratching:

static int network_len128 (const struct in6_addr *a, const struct in6_addr *b)
{
int i, j, bits = 0;
BYTE v;

for (i = 15; i >= 0; i--)
{
v = (a->s6_bytes[i] ^ b->s6_bytes[i]);
for (j = 0; j < 8; j++, bits++)
if ((v & (1 << j)) == 0)
goto quit;
}
quit:
return (bits);
}

Figuring I had to go backwards from LSB to MSB and stop counting
when 2 bits are equal.

The above code (+inet_ntop(&a..)) will print "76:96:42:219::/64".
Does this make sense for you experts?
Jorgen Grahn
2016-11-27 19:10:52 UTC
Permalink
Post by ElChino
I'm having some troubles figuring out the CIDR "prefix length"
of a IPv6 addresses range.
Specifically, in some code that reads MaxMind's GeoIPv6.dat records,
IP-num high: 76:96:42:219:ffff:ffff:ffff:ffff
(belonging to 'United States')
I need to figure out how to print this using CIDR notation.
E.g. if I have the 2 above addresses in
struct in6_addr a, b;
...
Post by ElChino
The above code (+inet_ntop(&a..)) will print "76:96:42:219::/64".
Does this make sense for you experts?
I'm no expert and I've not read your code. However, at least the
/result/ is correct. 76:96:42:219:: and 76:96:42:219:ffff:ffff:ffff:ffff
differ after 4 identical words, i.e. 64 bits.

The best thing would be if people stopped using any notation but
addr/len. Is there any reason to use first--last or address, mask
today? For IPv6?

/Jorgen
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
ElChino
2016-11-27 20:58:50 UTC
Permalink
Post by Jorgen Grahn
....
Post by ElChino
The above code (+inet_ntop(&a..)) will print "76:96:42:219::/64".
Does this make sense for you experts?
I'm no expert and I've not read your code. However, at least the
/result/ is correct. 76:96:42:219:: and 76:96:42:219:ffff:ffff:ffff:ffff
differ after 4 identical words, i.e. 64 bits.
Incidentally, for that block "/64" was correct. But I think it should be:
return (128 - bits);
instead. Since AFAICS, prefix-length is the number of high-order bits in
the address that are fixed. No?
Post by Jorgen Grahn
The best thing would be if people stopped using any notation but
addr/len. Is there any reason to use first--last or address, mask
today? For IPv6?
Agree, not at all. But in that example, the IP-low + IP-high was
just how the MaxMind database stored the data (in binary).
Barry Margolin
2016-11-27 22:13:16 UTC
Permalink
Post by Jorgen Grahn
Post by ElChino
I'm having some troubles figuring out the CIDR "prefix length"
of a IPv6 addresses range.
Specifically, in some code that reads MaxMind's GeoIPv6.dat records,
IP-num high: 76:96:42:219:ffff:ffff:ffff:ffff
(belonging to 'United States')
I need to figure out how to print this using CIDR notation.
E.g. if I have the 2 above addresses in
struct in6_addr a, b;
...
Post by ElChino
The above code (+inet_ntop(&a..)) will print "76:96:42:219::/64".
Does this make sense for you experts?
I'm no expert and I've not read your code. However, at least the
/result/ is correct. 76:96:42:219:: and 76:96:42:219:ffff:ffff:ffff:ffff
differ after 4 identical words, i.e. 64 bits.
The best thing would be if people stopped using any notation but
addr/len. Is there any reason to use first--last or address, mask
today? For IPv6?
Ranges are useful for databases. In SQL can write

WHERE addr BETWEEN range_start AND range_end
--
Barry Margolin
Arlington, MA
Jorgen Grahn
2016-11-28 18:09:04 UTC
Permalink
...
Post by Barry Margolin
Post by Jorgen Grahn
The best thing would be if people stopped using any notation but
addr/len. Is there any reason to use first--last or address, mask
today? For IPv6?
Ranges are useful for databases. In SQL can write
WHERE addr BETWEEN range_start AND range_end
Yes, and the internals of a routing table might not use prefix
lengths, either. But I was more thinking about user-visible
interfaces.

/Jorgen
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Miquel van Smoorenburg
2016-12-02 10:22:24 UTC
Permalink
Post by Barry Margolin
Ranges are useful for databases. In SQL can write
WHERE addr BETWEEN range_start AND range_end
That is indeed how I've often seen it used, but you would need 128-bit
integer support for IPv6, and I know of no SQL database that supports
that. You might get away with 64-bit integers and storing only the
first 64 bits of the IPv6 address. Or store the first and last 64
bits seperately, but that gets complicated quick.

Modern databases (well, postgres) support more than just string /
integer / date types: it has 'inet' and 'cidr' types, and special
operators for them ('<<' = 'in'). So you can simply write

SELECT range WHERE addr << range

Mike.

Loading...