[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