Переглянути джерело

Use RFC4390 whenever hardware address exceeds 16 bytes; this allows us

to construct DHCP packets suitable for Infiniband.
tags/v0.9.3
Michael Brown 16 роки тому
джерело
коміт
af303db75d
2 змінених файлів з 43 додано та 2 видалено
  1. 7
    0
      src/include/gpxe/dhcp.h
  2. 36
    2
      src/net/udp/dhcp.c

+ 7
- 0
src/include/gpxe/dhcp.h Переглянути файл

@@ -432,6 +432,13 @@ struct dhcphdr {
432 432
 /** Opcode for a reply from server to client */
433 433
 #define BOOTP_REPLY 2
434 434
 
435
+/** BOOTP reply must be broadcast
436
+ *
437
+ * Clients that cannot accept unicast BOOTP replies must set this
438
+ * flag.
439
+ */
440
+#define BOOTP_FL_BROADCAST 0x8000
441
+
435 442
 /** DHCP magic cookie */
436 443
 #define DHCP_MAGIC_COOKIE 0x63825363UL
437 444
 

+ 36
- 2
src/net/udp/dhcp.c Переглянути файл

@@ -298,6 +298,7 @@ static int create_dhcp_packet ( struct net_device *netdev, uint8_t msgtype,
298 298
 				void *data, size_t max_len,
299 299
 				struct dhcp_packet *dhcppkt ) {
300 300
 	struct dhcphdr *dhcphdr = data;
301
+	unsigned int hlen;
301 302
 	int rc;
302 303
 
303 304
 	/* Sanity check */
@@ -309,9 +310,17 @@ static int create_dhcp_packet ( struct net_device *netdev, uint8_t msgtype,
309 310
 	dhcphdr->xid = dhcp_xid ( netdev );
310 311
 	dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
311 312
 	dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto );
312
-	dhcphdr->hlen = netdev->ll_protocol->ll_addr_len;
313
-	memcpy ( dhcphdr->chaddr, netdev->ll_addr, dhcphdr->hlen );
314 313
 	dhcphdr->op = dhcp_op[msgtype];
314
+	/* If hardware length exceeds the chaddr field length, don't
315
+	 * use the chaddr field.  This is as per RFC4390.
316
+	 */
317
+	hlen = netdev->ll_protocol->ll_addr_len;
318
+	if ( hlen > sizeof ( dhcphdr->chaddr ) ) {
319
+		hlen = 0;
320
+		dhcphdr->flags = htons ( BOOTP_FL_BROADCAST );
321
+	}
322
+	dhcphdr->hlen = hlen;
323
+	memcpy ( dhcphdr->chaddr, netdev->ll_addr, hlen );
315 324
 
316 325
 	/* Initialise DHCP packet structure */
317 326
 	dhcppkt->dhcphdr = dhcphdr;
@@ -494,6 +503,14 @@ struct dhcp_netdev_desc {
494 503
 	uint16_t device;
495 504
 } __attribute__ (( packed ));
496 505
 
506
+/** DHCP client identifier */
507
+struct dhcp_client_id {
508
+	/** Link-layer protocol */
509
+	uint8_t ll_proto;
510
+	/** Link-layer address */
511
+	uint8_t ll_addr[MAX_LL_ADDR_LEN];
512
+} __attribute__ (( packed ));
513
+
497 514
 /**
498 515
  * Create DHCP request
499 516
  *
@@ -511,7 +528,9 @@ int create_dhcp_request ( struct net_device *netdev, int msgtype,
511 528
 			  struct dhcp_packet *dhcppkt ) {
512 529
 	struct device_description *desc = &netdev->dev->desc;
513 530
 	struct dhcp_netdev_desc dhcp_desc;
531
+	struct dhcp_client_id client_id;
514 532
 	size_t dhcp_features_len;
533
+	size_t ll_addr_len;
515 534
 	int rc;
516 535
 
517 536
 	/* Create DHCP packet */
@@ -570,6 +589,21 @@ int create_dhcp_request ( struct net_device *netdev, int msgtype,
570 589
 		return rc;
571 590
 	}
572 591
 
592
+	/* Add DHCP client identifier.  Required for Infiniband, and
593
+	 * doesn't hurt other link layers.
594
+	 */
595
+	client_id.ll_proto = netdev->ll_protocol->ll_proto;
596
+	ll_addr_len = netdev->ll_protocol->ll_addr_len;
597
+	assert ( ll_addr_len <= sizeof ( client_id.ll_addr ) );
598
+	memcpy ( client_id.ll_addr, netdev->ll_addr, ll_addr_len );
599
+	if ( ( rc = set_dhcp_packet_option ( dhcppkt, DHCP_CLIENT_ID,
600
+					     &client_id,
601
+					     ( ll_addr_len + 1 ) ) ) != 0 ) {
602
+		DBG ( "DHCP could not set client ID: %s\n",
603
+		      strerror ( rc ) );
604
+		return rc;
605
+	}
606
+
573 607
 	return 0;
574 608
 }
575 609
 

Завантаження…
Відмінити
Зберегти