]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[dhcpv6] Allow stateful DHCPv6 to apply obtained IPv6 addresses
authorMichael Brown <mcb30@ipxe.org>
Fri, 15 Nov 2013 15:23:09 +0000 (15:23 +0000)
committerMichael Brown <mcb30@ipxe.org>
Fri, 15 Nov 2013 15:23:09 +0000 (15:23 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/net/udp/dhcpv6.c

index ebd7221f915c6bd2a6213e829f1de36f9a1718f3..42d11194fafc54bd9e611c84c7325b311ba79ef6 100644 (file)
@@ -35,6 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/in.h>
 #include <ipxe/crc32.h>
 #include <ipxe/errortab.h>
+#include <ipxe/ipv6.h>
 #include <ipxe/dhcpv6.h>
 
 /** @file
@@ -408,16 +409,19 @@ enum dhcpv6_session_state_flags {
        /** Include leased IPv6 address within request */
        DHCPV6_TX_IAADDR = 0x02,
        /** Record received server ID */
-       DHCPV6_RX_SERVER_ID = 0x04,
+       DHCPV6_RX_RECORD_SERVER_ID = 0x04,
        /** Record received IPv6 address */
-       DHCPV6_RX_IAADDR = 0x08,
+       DHCPV6_RX_RECORD_IAADDR = 0x08,
+       /** Apply received IPv6 address */
+       DHCPV6_RX_APPLY_IAADDR = 0x10,
 };
 
 /** DHCPv6 request state */
 static struct dhcpv6_session_state dhcpv6_request = {
        .tx_type = DHCPV6_REQUEST,
        .rx_type = DHCPV6_REPLY,
-       .flags = ( DHCPV6_TX_IA_NA | DHCPV6_TX_IAADDR | DHCPV6_RX_IAADDR ),
+       .flags = ( DHCPV6_TX_IA_NA | DHCPV6_TX_IAADDR |
+                  DHCPV6_RX_RECORD_IAADDR | DHCPV6_RX_APPLY_IAADDR ),
        .next = NULL,
 };
 
@@ -425,7 +429,8 @@ static struct dhcpv6_session_state dhcpv6_request = {
 static struct dhcpv6_session_state dhcpv6_solicit = {
        .tx_type = DHCPV6_SOLICIT,
        .rx_type = DHCPV6_ADVERTISE,
-       .flags = ( DHCPV6_TX_IA_NA | DHCPV6_RX_SERVER_ID | DHCPV6_RX_IAADDR ),
+       .flags = ( DHCPV6_TX_IA_NA | DHCPV6_RX_RECORD_SERVER_ID |
+                  DHCPV6_RX_RECORD_IAADDR ),
        .next = &dhcpv6_request,
 };
 
@@ -785,7 +790,7 @@ static int dhcpv6_rx ( struct dhcpv6_session *dhcpv6,
        }
 
        /* Record identity association address, if applicable */
-       if ( dhcpv6->state->flags & DHCPV6_RX_IAADDR ) {
+       if ( dhcpv6->state->flags & DHCPV6_RX_RECORD_IAADDR ) {
                if ( ( rc = dhcpv6_iaaddr ( &options, dhcpv6->iaid,
                                            &dhcpv6->lease ) ) != 0 ) {
                        DBGC ( dhcpv6, "DHCPv6 %s received %s with unusable "
@@ -802,7 +807,7 @@ static int dhcpv6_rx ( struct dhcpv6_session *dhcpv6,
        }
 
        /* Record server ID, if applicable */
-       if ( dhcpv6->state->flags & DHCPV6_RX_SERVER_ID ) {
+       if ( dhcpv6->state->flags & DHCPV6_RX_RECORD_SERVER_ID ) {
                assert ( dhcpv6->server_duid == NULL );
                option = dhcpv6_option ( &options, DHCPV6_SERVER_ID );
                if ( ! option ) {
@@ -822,6 +827,19 @@ static int dhcpv6_rx ( struct dhcpv6_session *dhcpv6,
                         dhcpv6->server_duid_len );
        }
 
+       /* Apply identity association address, if applicable */
+       if ( dhcpv6->state->flags & DHCPV6_RX_APPLY_IAADDR ) {
+               if ( ( rc = ipv6_set_address ( dhcpv6->netdev,
+                                              &dhcpv6->lease ) ) != 0 ) {
+                       DBGC ( dhcpv6, "DHCPv6 %s could not apply %s: %s\n",
+                              dhcpv6->netdev->name,
+                              inet6_ntoa ( &dhcpv6->lease ), strerror ( rc ) );
+                       /* This is plausibly the error we want to return */
+                       dhcpv6->rc = rc;
+                       goto done;
+               }
+       }
+
        /* Transition to next state or complete DHCPv6, as applicable */
        if ( dhcpv6->state->next ) {