Table of Contents

Week 8 (July 11 to July 17)

Day 1 (July 11)

I began reworking the DHCPv6 code today to implement the necessary infrastructure for passing through the state machine. This will be quite similar to DHCPv4's state machine, with generic functions containing logic for transmission and receive that is the same across all states.

As part of these changes, I removed a lot of old testing solicit code and re-implemented it into the new infrastructure. This has worked well, with the DHCPv6 server sending ADVERTISE packets in response to the SOLICIT packet. I just have to set the right options to request an address (an IA_{NA|TA} option, for example).

At some point I will also need to modify the “settings” (gpxe/settings.h) code in gPXE to handle IPv6 addresses as well as IPv4 addresses. This will be useful for setting DNS nameservers and such, and I think I may also need to bring some of the settings changes into my stateless autoconfiguration code so that the IPv6 address of the network device is accessible.

I am now on a part time contract, so I have a bit more time in the day to work on gPXE code.

Day 2 (July 12)

I spent a fair bit of time today reading the RFCs for DHCPv6, trying to wrap my head around temporary and non-temporary addresses, and the IA_TA/IA_NA options in DHCPv6. This understanding is critical to being able to implement these features in gPXE properly.

I also implemented more of the SOLICIT state handling today. I can now send a request for an address, with the rapid commit option, and get an immediate reply from the DHCPv6 server. I managed to implement handling of this reply (generically, so there is no code duplication for a 4-way handshake transaction) but without the gpxe/settings.h changes I mentioned in yesterday's entry, I'm a bit stuck. So I'll be adding a few TODO comments in the code, and then continuing to implement the rest of the state machine. This way I can test each aspect of the DHCPv6 code and then sort out the settings changes later.

At some point I also need to install the ISC dhcpd, so I can test my DHCPv6 code with more than one server. At the moment I'm using WIDE's DHCPv6 server, which should work fine for this initial implementation phase.

Day 3 (July 13)

I managed to clean up some of the DHCPv6 option handling this evening, which makes reading through the code a bit nicer. This also came as a result of wanting to separate traversing the option list from actually using data in those options - another readability thing.

I'm fairly happy with how DHCPv6 is at with respect to rapid commits. It easily handles a transaction with a rapid commit and can get to the stage where I would set IP addresses and nameservers quite quickly. Tonight, though, I worked on the 4-way handshake (SOLICIT, ADVERTISE, REQUEST, REPLY). This has gone very well, with the code in place to send a REQUEST in response to an ADVERTISE - which means I'm now at the same stage here as with rapid commits (needing to set IP addresses and such). I do need to write a lot more code for the REPLY and ADVERTISE handling however - we need to confirm the response is actually for our own client ID, and that the server does not change between an advertisement and a reply. But everything is in place now to make that work.

Still haven't really looked into the gpxe/settings.h changes yet. Once DHCPv6 is cleaned up a bit and slightly more spec-friendly, I might have a look at this.

Day 4 (July 14)

Took some time to read the DHCPv6 specification again to make sure my progress is still “on the mark”. I've made note of a few places where I may need to make some changes, which typically involve server/client verification and the correct response to unexpected packets.

So far so good though.

Day 5 (July 15)

I managed to implement checking of both the Client ID and Server ID in all packets that are received from a server this evening. This will keep gPXE from accepting DHCPv6-assigned addresses that don't actually belong to it, as well as keeping to the standard.

The initial of DHCPv6 is essentially complete at this stage, as a full transaction can be performed both with and without rapid commit support, as well as a standard Information Request (to retrieve only DNS servers, for example). Still lacking is the support for actually configuring gPXE with the outcome of a DHCPv6 session, but this will involve the previously mentioned settings.h changes. That will be the next thing I implement.

I'm also not sure about how to set up routing for DHCPv6 addresses yet. The RFC does not actually state that an IPv6 prefix or router information is provided as part of a standard address assignment, so it is impossible to globally route packets without a router advertisement. I'm half tempted to perform a router advertisement as the first stage in a DHCPv6 session, and store the resulting router and prefix for later use. This would require the router solicitation function to change a bit to return a bit more information, but I don't see that being a problem. The alternative is to try and manipulate existing IPv6 miniroutes or inject new routes hoping that it “just works”.

One important note about completing this basic DHCPv6 support - aside from IPv6 fragmentation and proper handling of IPv6 extension headers, IPv6 support is now “functionally complete” in gPXE. Hurrah! :)

Day 6 (July 16)

I implemented the changes to settings.h today. This has gone very well so far:

26711	2957.453307	2001:44b8:1::6	2001:44b8:7222:a50:20c:29ff:fe54:c23d	DNS	Standard query response AAAA 2001:470:1f07:121b::1

That's an AAAA response to gPXE querying “AAAA” - all over IPv6! The nameserver was obtained via DHCPv6.

I still need to implement some way for DHCPv6 to get enough information out of a router solicitation to make an address assignment globally routable, but that won't take too long at all. I think I can even do it without having to change too much of the existing router solicit code.

Update (0039 UTC):

I've managed to fix some routing issues in IPv6 and rework router solicitations as needed to allow DHCPv6 to get information about the routers and prefixes available. This means DHCPv6 can now assign a fully routable address, rather than having to assume the address is a /128 or something.

This means DHCPv6 is essentially “complete” in the sense that it can be used as a complete alternative to SLAAC. It does not yet have any features related to network booting, nor does it have features that gPXE's DHCPv4 implementation has such as caching.

I just need to merge and rebase the commits related to DHCPv6 and rename and reimplement the “ipv6” command now that this is complete. The complete user-visible IPv6 interface is now essentially complete; the remainder of my project is backend work.

Day 7 (July 17)

I FINALLY implemented time out handling for router solicitations today, which means gPXE won't hang anymore if a router advertisement daemon isn't available on the network. This let me try out DHCPv6 without any router advertisements - and it worked as expected. It assigned a /128 address, which was not able to be routed.

I also fixed some interesting bugs from the past couple of days in the DHCPv6 code and updated the NDP router solicit code a bit to send a source link-local address with router advertisements (which helps the router avoid sending a neighbour solicit). I also managed to find a bug in the NDP code where the layout of “struct router_advert” was incorrect, causing the flags such as OTHERCONF and MANAGED to never be seen. This was fortunately easy to resolve, and now gPXE can ask for only DNS information on a network where router advertisements are used for autoconfiguration (ie, mine! :) ).

During my testing I have noticed that there are a few issues with the neighbour solicit/advertisement code, which I will be looking at soon. The biggest issue so far is that processing of neighbour advertisements makes some rather significant assumptions about the layout of the incoming packet. I'd like to change that to parse the options in the packet and handle each as necessary.

I also made some ip6mgmt.c changes today. These basically mean DHCPv6 only gets used in environments where router advertisements are not available, or where router advertisements suggest using a DHCPv6 server for additional configuration. I think this command is well and truly ready to be renamed from “ipv6” to something more like “ipv6-enable” or something, but I'm not sure exactly what to name it.