summaryrefslogtreecommitdiffstats
path: root/src/net/udp
diff options
context:
space:
mode:
authorMichael Brown2007-09-13 02:53:04 +0200
committerMichael Brown2007-09-21 02:15:58 +0200
commitaf303db75d467e1268806303766db02150d101d6 (patch)
treeaa7d4fee31153ed4f501d9abd7ed9ea591663dae /src/net/udp
parentAdd const attribute to byte-swapping functions (diff)
downloadipxe-af303db75d467e1268806303766db02150d101d6.tar.gz
ipxe-af303db75d467e1268806303766db02150d101d6.tar.xz
ipxe-af303db75d467e1268806303766db02150d101d6.zip
Use RFC4390 whenever hardware address exceeds 16 bytes; this allows us
to construct DHCP packets suitable for Infiniband.
Diffstat (limited to 'src/net/udp')
-rw-r--r--src/net/udp/dhcp.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c
index 9e48fe11..8e34ccb6 100644
--- a/src/net/udp/dhcp.c
+++ b/src/net/udp/dhcp.c
@@ -298,6 +298,7 @@ static int create_dhcp_packet ( struct net_device *netdev, uint8_t msgtype,
void *data, size_t max_len,
struct dhcp_packet *dhcppkt ) {
struct dhcphdr *dhcphdr = data;
+ unsigned int hlen;
int rc;
/* Sanity check */
@@ -309,9 +310,17 @@ static int create_dhcp_packet ( struct net_device *netdev, uint8_t msgtype,
dhcphdr->xid = dhcp_xid ( netdev );
dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto );
- dhcphdr->hlen = netdev->ll_protocol->ll_addr_len;
- memcpy ( dhcphdr->chaddr, netdev->ll_addr, dhcphdr->hlen );
dhcphdr->op = dhcp_op[msgtype];
+ /* If hardware length exceeds the chaddr field length, don't
+ * use the chaddr field. This is as per RFC4390.
+ */
+ hlen = netdev->ll_protocol->ll_addr_len;
+ if ( hlen > sizeof ( dhcphdr->chaddr ) ) {
+ hlen = 0;
+ dhcphdr->flags = htons ( BOOTP_FL_BROADCAST );
+ }
+ dhcphdr->hlen = hlen;
+ memcpy ( dhcphdr->chaddr, netdev->ll_addr, hlen );
/* Initialise DHCP packet structure */
dhcppkt->dhcphdr = dhcphdr;
@@ -494,6 +503,14 @@ struct dhcp_netdev_desc {
uint16_t device;
} __attribute__ (( packed ));
+/** DHCP client identifier */
+struct dhcp_client_id {
+ /** Link-layer protocol */
+ uint8_t ll_proto;
+ /** Link-layer address */
+ uint8_t ll_addr[MAX_LL_ADDR_LEN];
+} __attribute__ (( packed ));
+
/**
* Create DHCP request
*
@@ -511,7 +528,9 @@ int create_dhcp_request ( struct net_device *netdev, int msgtype,
struct dhcp_packet *dhcppkt ) {
struct device_description *desc = &netdev->dev->desc;
struct dhcp_netdev_desc dhcp_desc;
+ struct dhcp_client_id client_id;
size_t dhcp_features_len;
+ size_t ll_addr_len;
int rc;
/* Create DHCP packet */
@@ -570,6 +589,21 @@ int create_dhcp_request ( struct net_device *netdev, int msgtype,
return rc;
}
+ /* Add DHCP client identifier. Required for Infiniband, and
+ * doesn't hurt other link layers.
+ */
+ client_id.ll_proto = netdev->ll_protocol->ll_proto;
+ ll_addr_len = netdev->ll_protocol->ll_addr_len;
+ assert ( ll_addr_len <= sizeof ( client_id.ll_addr ) );
+ memcpy ( client_id.ll_addr, netdev->ll_addr, ll_addr_len );
+ if ( ( rc = set_dhcp_packet_option ( dhcppkt, DHCP_CLIENT_ID,
+ &client_id,
+ ( ll_addr_len + 1 ) ) ) != 0 ) {
+ DBG ( "DHCP could not set client ID: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
return 0;
}