[ipxe-devel] [PATCH 2/7] dhcpv6: Fallback to using DUID-LL for empty UUID

Hannes Reinecke hare at suse.de
Wed Apr 1 07:26:16 UTC 2015


If the system UUID is empty we cannot use it as a
DUID for DCHPv6.
So fallback to use DUID-LL in these cases.

Signed-off-by: Hannes Reinecke <hare at suse.de>
---
 src/include/ipxe/dhcpv6.h | 13 +++++++++++++
 src/net/udp/dhcpv6.c      | 35 ++++++++++++++++++++++++++---------
 2 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/src/include/ipxe/dhcpv6.h b/src/include/ipxe/dhcpv6.h
index 9307b6c..a6527c2 100644
--- a/src/include/ipxe/dhcpv6.h
+++ b/src/include/ipxe/dhcpv6.h
@@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
 #include <stdint.h>
 #include <ipxe/in.h>
+#include <ipxe/if_ether.h>
 #include <ipxe/uuid.h>
 
 /** DHCPv6 server port */
@@ -32,6 +33,16 @@ struct dhcpv6_option {
 	uint8_t data[0];
 } __attribute__ (( packed ));
 
+/** DHCP unique identifier based on UUID (DUID-LL) */
+struct dhcpv6_duid_ll {
+	/** Type */
+	uint16_t type;
+	/** Hardware type */
+	uint16_t hw_type;
+	/** IPv6 link-layer address */
+	uint8_t ll_addr[ETH_ALEN];
+} __attribute__ (( packed ));
+
 /** DHCP unique identifier based on UUID (DUID-UUID) */
 struct dhcpv6_duid_uuid {
 	/** Type */
@@ -40,6 +51,8 @@ struct dhcpv6_duid_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
 
diff --git a/src/net/udp/dhcpv6.c b/src/net/udp/dhcpv6.c
index a635437..7ff24b0 100644
--- a/src/net/udp/dhcpv6.c
+++ b/src/net/udp/dhcpv6.c
@@ -462,7 +462,12 @@ struct dhcpv6_session {
 	/** Start time (in ticks) */
 	unsigned long start;
 	/** Client DUID */
-	struct dhcpv6_duid_uuid client_duid;
+	union {
+		struct dhcpv6_duid_uuid uuid;
+		struct dhcpv6_duid_ll ll;
+		uint8_t raw[24];
+	} client_duid;
+	int client_duid_len;
 	/** Server DUID, if known */
 	void *server_duid;
 	/** Server DUID length */
@@ -582,7 +587,7 @@ static int dhcpv6_tx ( struct dhcpv6_session *dhcpv6 ) {
 
 	/* Calculate lengths */
 	client_id_len = ( sizeof ( *client_id ) +
-			  sizeof ( dhcpv6->client_duid ) );
+			  dhcpv6->client_duid_len );
 	server_id_len = ( dhcpv6->server_duid ? ( sizeof ( *server_id ) +
 						  dhcpv6->server_duid_len ) :0);
 	if ( dhcpv6->state->flags & DHCPV6_TX_IA_NA ) {
@@ -618,8 +623,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,
-		 sizeof ( dhcpv6->client_duid ) );
+	memcpy ( client_id->duid, &dhcpv6->client_duid.raw,
+		 dhcpv6->client_duid_len );
 
 	/* Construct server identifier, if applicable */
 	if ( server_id_len ) {
@@ -752,8 +757,8 @@ static int dhcpv6_rx ( struct dhcpv6_session *dhcpv6,
 
 	/* Verify client identifier */
 	if ( ( rc = dhcpv6_check_duid ( &options, DHCPV6_CLIENT_ID,
-					&dhcpv6->client_duid,
-					sizeof ( dhcpv6->client_duid ) ) ) !=0){
+					&dhcpv6->client_duid.raw,
+					dhcpv6->client_duid_len ) ) !=0){
 		DBGC ( dhcpv6, "DHCPv6 %s received %s without correct client "
 		       "ID: %s\n", dhcpv6->netdev->name,
 		       dhcpv6_type_name ( dhcphdr->type ), strerror ( rc ) );
@@ -898,6 +903,7 @@ int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
 		   int stateful ) {
 	struct ll_protocol *ll_protocol = netdev->ll_protocol;
 	struct dhcpv6_session *dhcpv6;
+	union uuid null_uuid;
 	struct {
 		union {
 			struct sockaddr_in6 sin6;
@@ -935,15 +941,26 @@ int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
 	addresses.server.sin6.sin6_port = htons ( DHCPV6_SERVER_PORT );
 
 	/* Construct client DUID from system UUID */
-	dhcpv6->client_duid.type = htons ( DHCPV6_DUID_UUID );
+	dhcpv6->client_duid_len = 18;
+	dhcpv6->client_duid.uuid.type = htons ( DHCPV6_DUID_UUID );
 	if ( ( len = fetch_uuid_setting ( NULL, &uuid_setting,
-					  &dhcpv6->client_duid.uuid ) ) < 0 ) {
+					  &dhcpv6->client_duid.uuid.uuid ) ) <= 0 ) {
 		rc = len;
 		DBGC ( dhcpv6, "DHCPv6 %s could not create DUID-UUID: %s\n",
 		       dhcpv6->netdev->name, strerror ( rc ) );
 		goto err_client_duid;
 	}
-
+	memset(&null_uuid, 0, sizeof(null_uuid));
+	if (!memcmp( &dhcpv6->client_duid.uuid.uuid, &null_uuid,
+		     sizeof(null_uuid) )) {
+		DBGC ( dhcpv6, "DHCPv6 %s empty DUID-UUID, using DUID-LL\n",
+		       dhcpv6->netdev->name );
+		dhcpv6->client_duid.ll.type = htons ( DHCPV6_DUID_LL );
+		dhcpv6->client_duid.ll.hw_type = ll_protocol->ll_proto & 0xFFFF;
+		memcpy( dhcpv6->client_duid.ll.ll_addr, netdev->ll_addr,
+			ETH_ALEN );
+		dhcpv6->client_duid_len = ETH_ALEN + 4;
+	}
 	/* 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,
-- 
1.8.4.5




More information about the ipxe-devel mailing list