]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[dhcpv6] Include RFC5970 client architecture options in DHCPv6 requests
authorMichael Brown <mcb30@ipxe.org>
Mon, 4 Jul 2016 12:18:49 +0000 (13:18 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 4 Jul 2016 12:18:49 +0000 (13:18 +0100)
RFC5970 defines DHCPv6 options 61 (client system architecture type)
and 62 (client network interface identifier), with contents equivalent
to DHCPv4 options 93 and 94 respectively.

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

index 9307b6cae4c38e125a21e7e60b6384d2d296826e..48cb76337b960c9791363261ca8ded0a39623d60 100644 (file)
@@ -157,6 +157,12 @@ struct dhcpv6_user_class_option {
 /** DHCPv6 bootfile parameters option */
 #define DHCPV6_BOOTFILE_PARAM 60
 
+/** DHCPv6 client system architecture option */
+#define DHCPV6_CLIENT_ARCHITECTURE 61
+
+/** DHCPv6 client network interface identifier option */
+#define DHCPV6_CLIENT_NDI 62
+
 /** DHCPv6 syslog server option
  *
  * This option code has not yet been assigned by IANA.  Please update
@@ -164,6 +170,33 @@ struct dhcpv6_user_class_option {
  */
 #define DHCPV6_LOG_SERVERS 0xffffffffUL
 
+/** Construct a DHCPv6 option code */
+#define DHCPV6_CODE( code ) \
+       ( ( (code) >> 8 ) & 0xff ), ( ( (code) >> 0 ) & 0xff )
+
+/** Construct a DHCPv6 option length */
+#define DHCPV6_LEN( len ) \
+       ( ( (len) >> 8 ) & 0xff ), ( ( (len) >> 0 ) & 0xff )
+
+/** Construct a DHCPv6 option from a list of bytes */
+#define DHCPV6_OPTION( ... ) \
+       DHCPV6_LEN ( VA_ARG_COUNT ( __VA_ARGS__ ) ), __VA_ARGS__
+
+/** Construct a DHCPv6 option from a list of characters */
+#define DHCPV6_STRING( ... ) DHCPV6_OPTION ( __VA_ARGS__ )
+
+/** Construct a byte-valued DHCPv6 option */
+#define DHCPV6_BYTE( value ) DHCPV6_OPTION ( value )
+
+/** Construct a word-valued DHCPv6 option */
+#define DHCPV6_WORD( value ) DHCPV6_OPTION ( ( ( (value) >> 8 ) & 0xff ), \
+                                            ( ( (value) >> 0 ) & 0xff ) )
+/** Construct a dword-valued DHCPv6 option */
+#define DHCPV6_DWORD( value ) DHCPV6_OPTION ( ( ( (value) >> 24 ) & 0xff ), \
+                                             ( ( (value) >> 16 ) & 0xff ), \
+                                             ( ( (value) >>  8 ) & 0xff ), \
+                                             ( ( (value) >>  0 ) & 0xff ) )
+
 /**
  * Any DHCPv6 option
  *
index a6354377592a648b87e73ef6cba1c5e1515ff64a..8b216e9a271326612db6ce48ceee32f0a3b72362 100644 (file)
@@ -40,6 +40,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/crc32.h>
 #include <ipxe/errortab.h>
 #include <ipxe/ipv6.h>
+#include <ipxe/dhcp_arch.h>
 #include <ipxe/dhcpv6.h>
 
 /** @file
@@ -364,10 +365,17 @@ static int dhcpv6_register ( struct dhcpv6_option_list *options,
  *
  */
 
-/** Options to be requested */
-static uint16_t dhcpv6_requested_options[] = {
-       htons ( DHCPV6_DNS_SERVERS ), htons ( DHCPV6_DOMAIN_LIST ),
-       htons ( DHCPV6_BOOTFILE_URL ), htons ( DHCPV6_BOOTFILE_PARAM ),
+/** Raw option data for options common to all DHCPv6 requests */
+static uint8_t dhcpv6_request_options_data[] = {
+       DHCPV6_CODE ( DHCPV6_OPTION_REQUEST ),
+       DHCPV6_OPTION ( DHCPV6_CODE ( DHCPV6_DNS_SERVERS ),
+                       DHCPV6_CODE ( DHCPV6_DOMAIN_LIST ),
+                       DHCPV6_CODE ( DHCPV6_BOOTFILE_URL ),
+                       DHCPV6_CODE ( DHCPV6_BOOTFILE_PARAM ) ),
+       DHCPV6_CODE ( DHCPV6_CLIENT_ARCHITECTURE ),
+       DHCPV6_WORD ( DHCP_ARCH_CLIENT_ARCHITECTURE ),
+       DHCPV6_CODE ( DHCPV6_CLIENT_NDI ),
+       DHCPV6_OPTION ( DHCP_ARCH_CLIENT_NDI )
 };
 
 /**
@@ -565,15 +573,14 @@ static int dhcpv6_tx ( struct dhcpv6_session *dhcpv6 ) {
        struct dhcpv6_duid_option *server_id;
        struct dhcpv6_ia_na_option *ia_na;
        struct dhcpv6_iaaddr_option *iaaddr;
-       struct dhcpv6_option_request_option *option_request;
        struct dhcpv6_user_class_option *user_class;
        struct dhcpv6_elapsed_time_option *elapsed;
        struct dhcpv6_header *dhcphdr;
        struct io_buffer *iobuf;
+       void *options;
        size_t client_id_len;
        size_t server_id_len;
        size_t ia_na_len;
-       size_t option_request_len;
        size_t user_class_string_len;
        size_t user_class_len;
        size_t elapsed_len;
@@ -592,16 +599,14 @@ static int dhcpv6_tx ( struct dhcpv6_session *dhcpv6 ) {
        } else {
                ia_na_len = 0;
        }
-       option_request_len = ( sizeof ( *option_request ) +
-                              sizeof ( dhcpv6_requested_options ) );
        user_class_string_len = dhcpv6_user_class ( NULL, 0 );
        user_class_len = ( sizeof ( *user_class ) +
                           sizeof ( user_class->user_class[0] ) +
                           user_class_string_len );
        elapsed_len = sizeof ( *elapsed );
        total_len = ( sizeof ( *dhcphdr ) + client_id_len + server_id_len +
-                     ia_na_len + option_request_len + user_class_len +
-                     elapsed_len );
+                     ia_na_len + sizeof ( dhcpv6_request_options_data ) +
+                     user_class_len + elapsed_len );
 
        /* Allocate packet */
        iobuf = xfer_alloc_iob ( &dhcpv6->xfer, total_len );
@@ -652,13 +657,10 @@ static int dhcpv6_tx ( struct dhcpv6_session *dhcpv6 ) {
                }
        }
 
-       /* Construct option request */
-       option_request = iob_put ( iobuf, option_request_len );
-       option_request->header.code = htons ( DHCPV6_OPTION_REQUEST );
-       option_request->header.len = htons ( option_request_len -
-                                            sizeof ( option_request->header ));
-       memcpy ( option_request->requested, dhcpv6_requested_options,
-                sizeof ( dhcpv6_requested_options ) );
+       /* Construct fixed request options */
+       options = iob_put ( iobuf, sizeof ( dhcpv6_request_options_data ) );
+       memcpy ( options, dhcpv6_request_options_data,
+                sizeof ( dhcpv6_request_options_data ) );
 
        /* Construct user class */
        user_class = iob_put ( iobuf, user_class_len );