[ipxe-devel] [PATCH 02/11] dhcpv6: Fallback to using DUID-LL for empty UUID
Hannes Reinecke
hare at suse.de
Thu May 7 09:24:57 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/core/uuid.c | 2 ++
src/include/ipxe/dhcpv6.h | 13 +++++++++++++
src/include/ipxe/uuid.h | 2 ++
src/net/udp/dhcpv6.c | 28 +++++++++++++++++++++-------
4 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/src/core/uuid.c b/src/core/uuid.c
index b8d21de..5992232 100644
--- a/src/core/uuid.c
+++ b/src/core/uuid.c
@@ -34,6 +34,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
*/
+const union uuid null_uuid;
+
/**
* Convert UUID to printable string
*
diff --git a/src/include/ipxe/dhcpv6.h b/src/include/ipxe/dhcpv6.h
index 9307b6c..5d0b657 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 Ethernet Link-layer address (DUID-LL) */
+struct dhcpv6_duid_eth_ll {
+ /** Type */
+ uint16_t type;
+ /** Hardware type: Ethernet */
+ uint16_t hw_type;
+ /** Ethernet 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/include/ipxe/uuid.h b/src/include/ipxe/uuid.h
index 6c45eb9..7f16b38 100644
--- a/src/include/ipxe/uuid.h
+++ b/src/include/ipxe/uuid.h
@@ -49,4 +49,6 @@ static inline void uuid_mangle ( union uuid *uuid ) {
extern char * uuid_ntoa ( const union uuid *uuid );
+extern const union uuid null_uuid;
+
#endif /* _IPXE_UUID_H */
diff --git a/src/net/udp/dhcpv6.c b/src/net/udp/dhcpv6.c
index a635437..e3953d2 100644
--- a/src/net/udp/dhcpv6.c
+++ b/src/net/udp/dhcpv6.c
@@ -462,7 +462,11 @@ 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_eth_ll ll;
+ } client_duid;
+ int client_duid_len;
/** Server DUID, if known */
void *server_duid;
/** Server DUID length */
@@ -582,7 +586,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 ) {
@@ -619,7 +623,7 @@ static int dhcpv6_tx ( struct dhcpv6_session *dhcpv6 ) {
client_id->header.len = htons ( client_id_len -
sizeof ( client_id->header ) );
memcpy ( client_id->duid, &dhcpv6->client_duid,
- sizeof ( dhcpv6->client_duid ) );
+ dhcpv6->client_duid_len );
/* Construct server identifier, if applicable */
if ( server_id_len ) {
@@ -753,7 +757,7 @@ 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_len ) ) !=0){
DBGC ( dhcpv6, "DHCPv6 %s received %s without correct client "
"ID: %s\n", dhcpv6->netdev->name,
dhcpv6_type_name ( dhcphdr->type ), strerror ( rc ) );
@@ -935,15 +939,25 @@ 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 = sizeof(struct dhcpv6_duid_uuid);
+ 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;
}
-
+ 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;
+ memcpy( dhcpv6->client_duid.ll.ll_addr, netdev->ll_addr,
+ ll_protocol->ll_addr_len );
+ dhcpv6->client_duid_len = sizeof(struct dhcpv6_duid_eth_ll);
+ }
/* 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