-
Notifications
You must be signed in to change notification settings - Fork 2
Adding IPv6 Support
The quick and really dirty method would be to not even bother explicitly assigning a v6 address directly to machines. Instead, just bolt an IPv6 address column onto the existing subnet table, and then at export time derive an IPv6 address using the existing IPv4 address as a seed.
This, of course, would preclude support for any new IPv6 specific address assignment behavior, such as allocating more than a /128, or an IPv6 only registration. It would also make searching based on IPv6 addresses exceedingly slow, if not virtually impossible (NetMon impact?).
The simple IPv4 method of assigning an address to a new record uses a clever trick of joining the address column of the machine table with itself plus one. Where everything is built around a one to one mapping between machines and IP addresses, this works fine.
For IPv6, however, there is the possibility of allocating ranges to a machine. It's not uncommon to see plans to hand out /96 or even /64 address allocations to a machine via DHCP.
Now, the simple case would be to point out that we currently have an actual policy in place against making anything that netops doesn't run a router, so tough - you'll get a /128 and you'll like it. But do we really want to limit ourselves to that choice? Policy develops over time, and regardless of which way we end up going, it would be nice if that direction were a choice based on where we want to go, rather than a tool limitation.
Lifting this restriction means two main changes:
- An address assignment must include a mask, in addition to the base address. (Question: must the allocation size be defined per subnet, or is it legal to hand out different allocation sizes to different hosts? (Yay address fragmentation issues!))
- Automatic address allocation routines must be smart enough to search through for entire blocks of adequate size.
All of a sudden, QuickReg becomes at least an order of magnitude hairier, as previously simple constants become unknowns. Here's the reference workflow for QuickReg.
- A machine comes up on the network and requests an address via DHCP.
- DHCP allow/deny statements give it an address from a subnet or pool which restricts the machine to a limited network.
- User opens up browser, which gets redirected to the QuickReg site with directions on how to proceed.
- User registers computer, which causes it to be reclassified in DHCP configuration.
- When machine renews DHCP lease, it gets moved into production network with unhindered connectivity.
On v4, when a machine connects to QuickReg in step 3 it is trivial to from the IP address to the MAC address via either the router ARP tables, or by querying the DHCP server via OMAPI. We should be able to use the NDP tables to go from a v6 address to a MAC address, and would then have to also query the DHCP server to find the DUID that v6 address was assigned to.
This should, in theory, allow us to correlate together the v4 address, v6 address, MAC, and DUID tuple in use by the client machine, and in turn reserve both a v4 and v6 address simultaneously.
Not only is there no requirement that changes to the DUID and MAC track each other, the completely different nature of the two (a simple pseudo-random generated value in a file or registry key vs a unique manufacturer assigned address burned into a ROM) virtually guarantees that circumstances that cause a change in one, will not cause a change in the other. The relevant QuickReg question becomes, how do we deal with the case where the MAC address is registered, but the DUID is unknown, or vice versa?
For example, if the DUID is regenerated due to an OS install, the v4 address will be the production one, but the v6 address, based on the never before seen DUID, will be dropped into a QuickReg pool. At that point, any v4 connections will work fine, but v6 ones will mysteriously fail due to the QuickReg restrictions. In particular, attempts to view websites will work fine for v4 sites, and only get redirected to QuickReg on v6 sites.
Both v4 and v6 stacks are capable of operating completely independently of each other. Checking the status of a machine and manipulating its behavior via selective DHCP was easy when everything was v4. With the DUID fun and games thrown into the mix, though, we now are faced with the difficulty of attempting to make consistent behavior in two different stacks, with only a tenuous at best relationship between the two unique identifiers.
Storing IPv4 addresses are easy - they fit nice and neatly into a 32 bit unsigned int. IPv6 addresses, on the other hand, are a gargantuan 128 bits wide. MySQL, sadly, has no native 128 bit int column type. So what are the options?
(Note that whichever option is chosen here must be reflected in NetMon as well.)
Sorry, MySQL, but none of these hacks are viable in my opinion - you lose. Oh, and being bought by Sun and having the FOSS license threatened, having the lead developers leave the project, getting forked several times into other projects like Drizzle, and the fact that you're releasing Falcon, the new preferred table type but still leaving proper FK support out - yeah, none of those exactly inspire me to stand up and defend you against PostgreSQL, either.
It would be possible to split each IPv6 address into an upper and lower 64 bit half, and store each half in a native 64 bit unsigned int column. This would require that any query with any conditions on an IPv6 address also be split up in a pair of conditions. Clunky, crude, and it would make bitmask operations a royal pain, but functional and it should be reasonably fast.
MySQL does have a decimal column that can be configured to store a 39 digit number. This has the advantage that the entire address is stored in a single column again. However, a decimal column isn't quite the same as an integer column. Annoyingly, bitwise operations (such as '|' and '&') are only defined for up to 64 bit integers, so their inputs and outputs get truncated, which in turn makes them useless for any of the standard subnet mask based operations.
It's quite possible to just treat the address as an opaque object. This is quite simple, but it most likely makes any kind of searching other than equality painfully slow, and wouldn't allow for any mask operations.
It may be possible to extend MySQL using the UDF interface enough to add functions that can perform the needed 128 bit masking operations, either on a new 128 bit int column type or on the existing decimal(39) column type. Anyone know enough about MySQL to say whether or not this is possible, and if so, how much work it might be?
The PostgreSQL engine has native support for IP address objects, including both IPv4 and IPv6 support. It also includes storing a mask along with the address, and useful helper functions that neatly do the work normally done with bit masking tricks.
While hairy, a lot of the work in adapting the code has already been done. Frank Sweetser has a local branch (very hacked up, not suitable for general distribution) which includes support for most read and write operations (untested).
Currently, the dynamic range for a given subnet is defined by all of the machine table entries in that subnet that are of type “pool”. The DHCP extract script coalesces the entries together into one or more range statements in the DHCP server configuration file.
For IPv4, with no more than a few thousand possible IP addresses per subnet, of which rarely more than a couple of hundred are used for the dynamic pool, this is not a problem. With IPv6, though, subnet sizes are so ludicrously large that if we were to allocate a similar percentage of the subnet to the dynamic pool, the pool entries would quickly overwhelm the machine table. For example, allocating 5% of a typcal /64 subnet would require inserting just over 9.22×1017 records.
Instead, DHCP pools should probably be recreated as their own first class objects in the database. This would allow the range to be stored as an extent, rather than internally enumerating each and every address. In addition, we would be able to define multiple pools per subnet, and have different policies for each one, possibly including different DHCP options, assuming that the DHCP server supports it.
ANAME records are a NetReg creation that are used to allow a single hostname to map to multiple A records. They will have to be expanded to also encompass AAAA records as well.
Currently, NetReg determines the host and domain portion of a hostname by splitting it on the first dot. This may not always correspond to the DNS zone file configuration, however. For example, we have 130.215.0.0/16 allocated, so we have the DNS zone 215.130.in-addr.arpa. The PTR record for, say, 130.215.201.24 would then be a host portion of 24.201 in a domain of 215.130.in-addr.arpa. NetReg handles this with the rev-permissible zone 201.215.130.in-addr.arpa, which provides extra records that give the standard hostname splitting format the necessary records to match on.
In the case of a class B reversal zone, this means there are 256 extra rev-permissible zones - no big deal. For IPv6 addresses, however, things get much, much worse. Take a typical /48 allocation. Since IPv6 is split up in 4 bit segments, instead of 8 bit ones, 44 bits worth of rev-permissible zones equates to 11 levels of rv-permissible zones between the delegated zone and the reversal record. At 11 levels of 16 possible values, this means you'd need 16^11 or 17,592,186,044,416 zones. I don't know about you, but I'd prefer not to have to add that many extra rows to the dns_zone table if I can avoid it.
Instead, the only practical way to handle this is to make the process of matching a given hostname to the correct DNS zone record intelligently find the longest matching zone, regardless of the number of segments. Luckily, once implemented, this match can be applied to both IPv4 and 6 reversal lookups, so there shouldn't be any need to special case IPv6 reversals.
Question - in the case where a host is configured with an allocation other than a /128, what reversal records if any should be created?
Overall, updating NetMon should be pretty straightforward, as most of the functionality is just simple dump into tables level functionality.
- NDP
- DHCP
- Wifi client
- Need to check on wireless support for reporting v6 client addresses
The various search routines will have to be handled not only to accept IPv6 addresses in searches, but also, when handed a hostname, to search for all 4 and 6 addresses assigned to that hostname.
Regardless of whatever decision is made about IPv6 allocation sizes, we should be prepared to do address plus mask based searches, as there's no guarantee that NetReg will always be the sole authoritative source of all address assignments.