]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[dhcpv6] Use DUID-UUID form of client DUID
authorMichael Brown <mcb30@ipxe.org>
Thu, 5 Dec 2013 03:18:59 +0000 (03:18 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 5 Dec 2013 03:18:59 +0000 (03:18 +0000)
Use the system UUID to generate the client DUID-UUID as per RFC 6355.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/dhcpv6.h
src/net/udp/dhcpv6.c

index 70cccf0ba9c93ccad08fe212a0477907bfd012a7..57758e5167aa1a8c0b7e2043b14514c69491365e 100644 (file)
@@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 
 #include <stdint.h>
 #include <ipxe/in.h>
+#include <ipxe/uuid.h>
 
 /** DHCPv6 server port */
 #define DHCPV6_SERVER_PORT 547
@@ -31,18 +32,16 @@ struct dhcpv6_option {
        uint8_t data[0];
 } __attribute__ (( packed ));
 
-/** DHCP unique identifier based on link-layer address (DUID-LL) */
-struct dhcpv6_duid_ll {
+/** DHCP unique identifier based on UUID (DUID-UUID) */
+struct dhcpv6_duid_uuid {
        /** Type */
        uint16_t type;
-       /** Hardware type */
-       uint16_t htype;
-       /** Link-layer address */
-       uint8_t ll_addr[0];
+       /** UUID */
+       union uuid uuid;
 } __attribute__ (( packed ));
 
-/** DHCP unique identifier based on link-layer address (DUID-LL) */
-#define DHCPV6_DUID_LL 3
+/** DHCP unique identifier based on UUID (DUID-UUID) */
+#define DHCPV6_DUID_UUID 4
 
 /** DHCPv6 client or server identifier option */
 struct dhcpv6_duid_option {
index d38c5d94608da1f9adeab1da6db107d630d6985b..61c26f24d48d67d6d81e4e7408a2214a7700ddb4 100644 (file)
@@ -457,9 +457,7 @@ struct dhcpv6_session {
        /** Start time (in ticks) */
        unsigned long start;
        /** Client DUID */
-       void *client_duid;
-       /** Client DUID length */
-       size_t client_duid_len;
+       struct dhcpv6_duid_uuid client_duid;
        /** Server DUID, if known */
        void *server_duid;
        /** Server DUID length */
@@ -578,7 +576,8 @@ static int dhcpv6_tx ( struct dhcpv6_session *dhcpv6 ) {
        int rc;
 
        /* Calculate lengths */
-       client_id_len = ( sizeof ( *client_id ) + dhcpv6->client_duid_len );
+       client_id_len = ( sizeof ( *client_id ) +
+                         sizeof ( dhcpv6->client_duid ) );
        server_id_len = ( dhcpv6->server_duid ? ( sizeof ( *server_id ) +
                                                  dhcpv6->server_duid_len ) :0);
        if ( dhcpv6->state->flags & DHCPV6_TX_IA_NA ) {
@@ -614,8 +613,8 @@ static int dhcpv6_tx ( struct dhcpv6_session *dhcpv6 ) {
        client_id->header.code = htons ( DHCPV6_CLIENT_ID );
        client_id->header.len = htons ( client_id_len -
                                        sizeof ( client_id->header ) );
-       memcpy ( client_id->duid, dhcpv6->client_duid,
-                dhcpv6->client_duid_len );
+       memcpy ( client_id->duid, &dhcpv6->client_duid,
+                sizeof ( dhcpv6->client_duid ) );
 
        /* Construct server identifier, if applicable */
        if ( server_id_len ) {
@@ -748,8 +747,8 @@ static int dhcpv6_rx ( struct dhcpv6_session *dhcpv6,
 
        /* Verify client identifier */
        if ( ( rc = dhcpv6_check_duid ( &options, DHCPV6_CLIENT_ID,
-                                       dhcpv6->client_duid,
-                                       dhcpv6->client_duid_len ) ) != 0 ) {
+                                       &dhcpv6->client_duid,
+                                       sizeof ( dhcpv6->client_duid ) ) ) !=0){
                DBGC ( dhcpv6, "DHCPv6 %s received %s without correct client "
                       "ID: %s\n", dhcpv6->netdev->name,
                       dhcpv6_type_name ( dhcphdr->type ), strerror ( rc ) );
@@ -904,14 +903,12 @@ int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
                        struct sockaddr sa;
                } server;
        } addresses;
-       struct dhcpv6_duid_ll *client_duid;
-       size_t client_duid_len;
        uint32_t xid;
+       int len;
        int rc;
 
        /* Allocate and initialise structure */
-       client_duid_len = ( sizeof ( *client_duid ) + ll_protocol->ll_addr_len);
-       dhcpv6 = zalloc ( sizeof ( *dhcpv6 ) + client_duid_len );
+       dhcpv6 = zalloc ( sizeof ( *dhcpv6 ) );
        if ( ! dhcpv6 )
                return -ENOMEM;
        ref_init ( &dhcpv6->refcnt, dhcpv6_free );
@@ -921,8 +918,6 @@ int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
        xid = random();
        memcpy ( dhcpv6->xid, &xid, sizeof ( dhcpv6->xid ) );
        dhcpv6->start = currticks();
-       dhcpv6->client_duid = ( ( ( void * ) dhcpv6 ) + sizeof ( *dhcpv6 ) );
-       dhcpv6->client_duid_len = client_duid_len;
        timer_init ( &dhcpv6->timer, dhcpv6_timer_expired, &dhcpv6->refcnt );
 
        /* Construct client and server addresses */
@@ -935,12 +930,17 @@ int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
        addresses.server.sin6.sin6_scope_id = netdev->index;
        addresses.server.sin6.sin6_port = htons ( DHCPV6_SERVER_PORT );
 
-       /* Construct client DUID and IAID from link-layer address */
-       client_duid = dhcpv6->client_duid;
-       client_duid->type = htons ( DHCPV6_DUID_LL );
-       client_duid->htype = ll_protocol->ll_proto;
-       memcpy ( client_duid->ll_addr, netdev->ll_addr,
-                ll_protocol->ll_addr_len );
+       /* Construct client DUID from system UUID */
+       dhcpv6->client_duid.type = htons ( DHCPV6_DUID_UUID );
+       if ( ( len = fetch_uuid_setting ( NULL, &uuid_setting,
+                                         &dhcpv6->client_duid.uuid ) ) < 0 ) {
+               rc = len;
+               DBGC ( dhcpv6, "DHCPv6 %s could not create DUID-UUID: %s\n",
+                      dhcpv6->netdev->name, strerror ( rc ) );
+               goto err_client_duid;
+       }
+
+       /* Construct IAID from link-layer address */
        dhcpv6->iaid = crc32_le ( 0, netdev->ll_addr, ll_protocol->ll_addr_len);
        DBGC ( dhcpv6, "DHCPv6 %s has XID %02x%02x%02x\n", dhcpv6->netdev->name,
               dhcpv6->xid[0], dhcpv6->xid[1], dhcpv6->xid[2] );
@@ -965,6 +965,7 @@ int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
 
  err_open_socket:
        dhcpv6_finished ( dhcpv6, rc );
+ err_client_duid:
        ref_put ( &dhcpv6->refcnt );
        return rc;
 }