|
@@ -826,6 +826,46 @@ static struct dhcp_session_state dhcp_state_pxebs = {
|
826
|
826
|
*
|
827
|
827
|
*/
|
828
|
828
|
|
|
829
|
+/**
|
|
830
|
+ * Construct DHCP client hardware address field and broadcast flag
|
|
831
|
+ *
|
|
832
|
+ * @v netdev Network device
|
|
833
|
+ * @v hlen DHCP hardware address length to fill in
|
|
834
|
+ * @v flags DHCP flags to fill in
|
|
835
|
+ * @ret chaddr DHCP client hardware address
|
|
836
|
+ */
|
|
837
|
+void * dhcp_chaddr ( struct net_device *netdev, uint8_t *hlen,
|
|
838
|
+ uint16_t *flags ) {
|
|
839
|
+ struct ll_protocol *ll_protocol = netdev->ll_protocol;
|
|
840
|
+ typeof ( ( ( struct dhcphdr * ) NULL )->chaddr ) chaddr;
|
|
841
|
+
|
|
842
|
+ /* If the link-layer address cannot fit into the chaddr field
|
|
843
|
+ * (as is the case for IPoIB) then try using the hardware
|
|
844
|
+ * address instead. If we do this, set the broadcast flag,
|
|
845
|
+ * since chaddr then does not represent a valid link-layer
|
|
846
|
+ * address for the return path.
|
|
847
|
+ *
|
|
848
|
+ * If even the hardware address is too large, use an empty
|
|
849
|
+ * chaddr field and set the broadcast flag.
|
|
850
|
+ *
|
|
851
|
+ * This goes against RFC4390, but RFC4390 mandates that we use
|
|
852
|
+ * a DHCP client identifier that conforms with RFC4361, which
|
|
853
|
+ * we cannot do without either persistent (NIC-independent)
|
|
854
|
+ * storage, or by eliminating the hardware address completely
|
|
855
|
+ * from the DHCP packet, which seems unfriendly to users.
|
|
856
|
+ */
|
|
857
|
+ if ( ( *hlen = ll_protocol->ll_addr_len ) <= sizeof ( chaddr ) ) {
|
|
858
|
+ return netdev->ll_addr;
|
|
859
|
+ }
|
|
860
|
+ *flags = htons ( BOOTP_FL_BROADCAST );
|
|
861
|
+ if ( ( *hlen = ll_protocol->hw_addr_len ) <= sizeof ( chaddr ) ) {
|
|
862
|
+ return netdev->hw_addr;
|
|
863
|
+ } else {
|
|
864
|
+ *hlen = 0;
|
|
865
|
+ return NULL;
|
|
866
|
+ }
|
|
867
|
+}
|
|
868
|
+
|
829
|
869
|
/**
|
830
|
870
|
* Create a DHCP packet
|
831
|
871
|
*
|
|
@@ -846,7 +886,7 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
|
846
|
886
|
const void *options, size_t options_len,
|
847
|
887
|
void *data, size_t max_len ) {
|
848
|
888
|
struct dhcphdr *dhcphdr = data;
|
849
|
|
- unsigned int hlen;
|
|
889
|
+ void *chaddr;
|
850
|
890
|
int rc;
|
851
|
891
|
|
852
|
892
|
/* Sanity check */
|
|
@@ -859,16 +899,8 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
|
859
|
899
|
dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
|
860
|
900
|
dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto );
|
861
|
901
|
dhcphdr->op = dhcp_op[msgtype];
|
862
|
|
- /* If hardware length exceeds the chaddr field length, don't
|
863
|
|
- * use the chaddr field. This is as per RFC4390.
|
864
|
|
- */
|
865
|
|
- hlen = netdev->ll_protocol->ll_addr_len;
|
866
|
|
- if ( hlen > sizeof ( dhcphdr->chaddr ) ) {
|
867
|
|
- hlen = 0;
|
868
|
|
- dhcphdr->flags = htons ( BOOTP_FL_BROADCAST );
|
869
|
|
- }
|
870
|
|
- dhcphdr->hlen = hlen;
|
871
|
|
- memcpy ( dhcphdr->chaddr, netdev->ll_addr, hlen );
|
|
902
|
+ chaddr = dhcp_chaddr ( netdev, &dhcphdr->hlen, &dhcphdr->flags );
|
|
903
|
+ memcpy ( dhcphdr->chaddr, chaddr, dhcphdr->hlen );
|
872
|
904
|
memcpy ( dhcphdr->options, options, options_len );
|
873
|
905
|
|
874
|
906
|
/* Initialise DHCP packet structure */
|