|  | @@ -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 */
 |