tags:

views:

1091

answers:

2

Following on from this post I am interested in searching IPv6 address ranges.

Under IPv4 I would be able to determine the start and end IP addresses provided by an ISP and using those integer values as range bounds quickly search a DataBase to see if any entries in the DB fell into that range.

How will this be impacted by IPv6? Will ISP's still have IPv6 addresses in ranges like they do now? And how would you efficiently search these ranges if you were storing the IPv6 addresses as two bigint's in a SQL Server DB?

+4  A: 

It is not correct to use IP addresses (neither IPv4, nor IPv6) in ranges. The correct way to group a particular "range" of IP addresses is using prefixes (CIDR notation) or masks (obsolete, only valid for IPv4, and insanity ensues if you try to use a non-contiguous mask).

Sometimes you will see someone (sometimes even applications, home routers, etc) using IPv4 ranges, but that is just the wrong way to do it.

Using Classless Inter-Domain Routing (CIDR) you will have a tuple <Address, Prefix>, where Address is a 128-bit unsigned integer and Prefix is a tiny (0..128) unsigned integer. The prefix tells how many most-significant bits of the Address represents the network address, leaving the other 128-Prefix least-significant bits to represent a particular host in that network.

So, for example, an IPv6 "range" of 2620:0:860:2::/64 (wikimedia.org) represents all hosts from 2620:0:860:2:: up to 2620:0:860:2:FFFF:FFFF:FFFF:FFFF.

You shouldn't use two "bigint"s to store such a value in a database, but use any native representation in a single column, unless you want to make your developer life a nightmare. If your DBMS doesn't support integers this big, besides replacing your DBMS, I suggest using a fixed-size binary data column, 16 bytes long.

Juliano
+3  A: 

Using a DBMS with proper support for IPv6 addresses would not be a bad idea. Here is an example with PostgreSQL, version 8.3:

mydb=> CREATE TABLE Networks (name TEXT, prefix INET);
CREATE TABLE
mydb=> INSERT INTO Networks VALUES ('Documentation', '2001:DB8::/32');
INSERT 0 1
mydb=> INSERT INTO Networks VALUES ('ULA', 'FC00::/7');
INSERT 0 1
mydb=> INSERT INTO Networks VALUES ('Orchid', '2001:10::/28');
INSERT 0 1

mydb=> SELECT * FROM Networks;
 name      |    prefix     
---------------+---------------
 Documentation | 2001:db8::/32
 ULA           | fc00::/7
 Orchid        | 2001:10::/28
(3 rows)

mydb=> SELECT * FROM Networks WHERE '2001:DB8::dcaf:BAD' << prefix;
 name      |    prefix     
---------------+---------------
 Documentation | 2001:db8::/32
(1 row)
bortzmeyer