Browse Source

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

to construct DHCP packets suitable for Infiniband.
tags/v0.9.3
Michael Brown 17 years ago
parent
commit
af303db75d
2 changed files with 43 additions and 2 deletions
  1. 7
    0
      src/include/gpxe/dhcp.h
  2. 36
    2
      src/net/udp/dhcp.c

+ 7
- 0
src/include/gpxe/dhcp.h View File

432
 /** Opcode for a reply from server to client */
432
 /** Opcode for a reply from server to client */
433
 #define BOOTP_REPLY 2
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
 /** DHCP magic cookie */
442
 /** DHCP magic cookie */
436
 #define DHCP_MAGIC_COOKIE 0x63825363UL
443
 #define DHCP_MAGIC_COOKIE 0x63825363UL
437
 
444
 

+ 36
- 2
src/net/udp/dhcp.c View File

298
 				void *data, size_t max_len,
298
 				void *data, size_t max_len,
299
 				struct dhcp_packet *dhcppkt ) {
299
 				struct dhcp_packet *dhcppkt ) {
300
 	struct dhcphdr *dhcphdr = data;
300
 	struct dhcphdr *dhcphdr = data;
301
+	unsigned int hlen;
301
 	int rc;
302
 	int rc;
302
 
303
 
303
 	/* Sanity check */
304
 	/* Sanity check */
309
 	dhcphdr->xid = dhcp_xid ( netdev );
310
 	dhcphdr->xid = dhcp_xid ( netdev );
310
 	dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
311
 	dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
311
 	dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto );
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
 	dhcphdr->op = dhcp_op[msgtype];
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
 	/* Initialise DHCP packet structure */
325
 	/* Initialise DHCP packet structure */
317
 	dhcppkt->dhcphdr = dhcphdr;
326
 	dhcppkt->dhcphdr = dhcphdr;
494
 	uint16_t device;
503
 	uint16_t device;
495
 } __attribute__ (( packed ));
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
  * Create DHCP request
515
  * Create DHCP request
499
  *
516
  *
511
 			  struct dhcp_packet *dhcppkt ) {
528
 			  struct dhcp_packet *dhcppkt ) {
512
 	struct device_description *desc = &netdev->dev->desc;
529
 	struct device_description *desc = &netdev->dev->desc;
513
 	struct dhcp_netdev_desc dhcp_desc;
530
 	struct dhcp_netdev_desc dhcp_desc;
531
+	struct dhcp_client_id client_id;
514
 	size_t dhcp_features_len;
532
 	size_t dhcp_features_len;
533
+	size_t ll_addr_len;
515
 	int rc;
534
 	int rc;
516
 
535
 
517
 	/* Create DHCP packet */
536
 	/* Create DHCP packet */
570
 		return rc;
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
 	return 0;
607
 	return 0;
574
 }
608
 }
575
 
609
 

Loading…
Cancel
Save