|  | @@ -154,22 +154,23 @@ struct dhcp_session_state {
 | 
		
	
		
			
			| 154 | 154 |  	 * @v dhcppkt		DHCP packet
 | 
		
	
		
			
			| 155 | 155 |  	 * @v peer		Destination address
 | 
		
	
		
			
			| 156 | 156 |  	 */
 | 
		
	
		
			
			| 157 |  | -	int ( * tx ) ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 158 |  | -		       struct dhcp_packet *dhcppkt,
 | 
		
	
		
			
			|  | 157 | +	int ( * tx ) ( struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt,
 | 
		
	
		
			
			| 159 | 158 |  		       struct sockaddr_in *peer );
 | 
		
	
		
			
			| 160 |  | -	/** Handle received packet
 | 
		
	
		
			
			|  | 159 | +	/**
 | 
		
	
		
			
			|  | 160 | +	 * Handle received packet
 | 
		
	
		
			
			| 161 | 161 |  	 *
 | 
		
	
		
			
			| 162 | 162 |  	 * @v dhcp		DHCP session
 | 
		
	
		
			
			| 163 | 163 |  	 * @v dhcppkt		DHCP packet
 | 
		
	
		
			
			| 164 | 164 |  	 * @v peer		DHCP server address
 | 
		
	
		
			
			| 165 | 165 |  	 * @v msgtype		DHCP message type
 | 
		
	
		
			
			| 166 | 166 |  	 * @v server_id		DHCP server ID
 | 
		
	
		
			
			|  | 167 | +	 * @v pseudo_id		DHCP server pseudo-ID
 | 
		
	
		
			
			| 167 | 168 |  	 */
 | 
		
	
		
			
			| 168 |  | -	void ( * rx ) ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 169 |  | -			struct dhcp_packet *dhcppkt,
 | 
		
	
		
			
			| 170 |  | -			struct sockaddr_in *peer,
 | 
		
	
		
			
			| 171 |  | -			uint8_t msgtype, struct in_addr server_id );
 | 
		
	
		
			
			| 172 |  | -	/** Handle timer expiry
 | 
		
	
		
			
			|  | 169 | +	void ( * rx ) ( struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt,
 | 
		
	
		
			
			|  | 170 | +			struct sockaddr_in *peer, uint8_t msgtype,
 | 
		
	
		
			
			|  | 171 | +			struct in_addr server_id, struct in_addr pseudo_id );
 | 
		
	
		
			
			|  | 172 | +	/**
 | 
		
	
		
			
			|  | 173 | +	 * Handle timer expiry
 | 
		
	
		
			
			| 173 | 174 |  	 *
 | 
		
	
		
			
			| 174 | 175 |  	 * @v dhcp		DHCP session
 | 
		
	
		
			
			| 175 | 176 |  	 */
 | 
		
	
	
		
			
			|  | @@ -340,11 +341,13 @@ static int dhcp_discovery_tx ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 340 | 341 |   * @v peer		DHCP server address
 | 
		
	
		
			
			| 341 | 342 |   * @v msgtype		DHCP message type
 | 
		
	
		
			
			| 342 | 343 |   * @v server_id		DHCP server ID
 | 
		
	
		
			
			|  | 344 | + * @v pseudo_id		DHCP server pseudo-ID
 | 
		
	
		
			
			| 343 | 345 |   */
 | 
		
	
		
			
			| 344 | 346 |  static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 345 | 347 |  				struct dhcp_packet *dhcppkt,
 | 
		
	
		
			
			| 346 | 348 |  				struct sockaddr_in *peer, uint8_t msgtype,
 | 
		
	
		
			
			| 347 |  | -				struct in_addr server_id ) {
 | 
		
	
		
			
			|  | 349 | +				struct in_addr server_id,
 | 
		
	
		
			
			|  | 350 | +				struct in_addr pseudo_id ) {
 | 
		
	
		
			
			| 348 | 351 |  	struct in_addr ip;
 | 
		
	
		
			
			| 349 | 352 |  	char vci[9]; /* "PXEClient" */
 | 
		
	
		
			
			| 350 | 353 |  	int vci_len;
 | 
		
	
	
		
			
			|  | @@ -356,8 +359,11 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 356 | 359 |  	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
 | 
		
	
		
			
			| 357 | 360 |  	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
 | 
		
	
		
			
			| 358 | 361 |  	       ntohs ( peer->sin_port ) );
 | 
		
	
		
			
			| 359 |  | -	if ( server_id.s_addr != peer->sin_addr.s_addr )
 | 
		
	
		
			
			| 360 |  | -		DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
 | 
		
	
		
			
			|  | 362 | +	if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
 | 
		
	
		
			
			|  | 363 | +	     ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
 | 
		
	
		
			
			|  | 364 | +		DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
 | 
		
	
		
			
			|  | 365 | +		DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
 | 
		
	
		
			
			|  | 366 | +	}
 | 
		
	
		
			
			| 361 | 367 |  
 | 
		
	
		
			
			| 362 | 368 |  	/* Identify offered IP address */
 | 
		
	
		
			
			| 363 | 369 |  	ip = dhcppkt->dhcphdr->yiaddr;
 | 
		
	
	
		
			
			|  | @@ -398,10 +404,10 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 398 | 404 |  	}
 | 
		
	
		
			
			| 399 | 405 |  
 | 
		
	
		
			
			| 400 | 406 |  	/* Select as ProxyDHCP offer, if applicable */
 | 
		
	
		
			
			| 401 |  | -	if ( server_id.s_addr && has_pxeclient &&
 | 
		
	
		
			
			|  | 407 | +	if ( pseudo_id.s_addr && has_pxeclient &&
 | 
		
	
		
			
			| 402 | 408 |  	     ( priority >= dhcp->proxy_priority ) ) {
 | 
		
	
		
			
			| 403 | 409 |  		dhcppkt_put ( dhcp->proxy_offer );
 | 
		
	
		
			
			| 404 |  | -		dhcp->proxy_server = server_id;
 | 
		
	
		
			
			|  | 410 | +		dhcp->proxy_server = pseudo_id;
 | 
		
	
		
			
			| 405 | 411 |  		dhcp->proxy_offer = dhcppkt_get ( dhcppkt );
 | 
		
	
		
			
			| 406 | 412 |  		dhcp->proxy_priority = priority;
 | 
		
	
		
			
			| 407 | 413 |  	}
 | 
		
	
	
		
			
			|  | @@ -510,11 +516,13 @@ static int dhcp_request_tx ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 510 | 516 |   * @v peer		DHCP server address
 | 
		
	
		
			
			| 511 | 517 |   * @v msgtype		DHCP message type
 | 
		
	
		
			
			| 512 | 518 |   * @v server_id		DHCP server ID
 | 
		
	
		
			
			|  | 519 | + * @v pseudo_id		DHCP server pseudo-ID
 | 
		
	
		
			
			| 513 | 520 |   */
 | 
		
	
		
			
			| 514 | 521 |  static void dhcp_request_rx ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 515 | 522 |  			      struct dhcp_packet *dhcppkt,
 | 
		
	
		
			
			| 516 | 523 |  			      struct sockaddr_in *peer, uint8_t msgtype,
 | 
		
	
		
			
			| 517 |  | -			      struct in_addr server_id ) {
 | 
		
	
		
			
			|  | 524 | +			      struct in_addr server_id,
 | 
		
	
		
			
			|  | 525 | +			      struct in_addr pseudo_id ) {
 | 
		
	
		
			
			| 518 | 526 |  	struct in_addr ip;
 | 
		
	
		
			
			| 519 | 527 |  	struct settings *parent;
 | 
		
	
		
			
			| 520 | 528 |  	struct settings *settings;
 | 
		
	
	
		
			
			|  | @@ -523,8 +531,11 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 523 | 531 |  	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
 | 
		
	
		
			
			| 524 | 532 |  	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
 | 
		
	
		
			
			| 525 | 533 |  	       ntohs ( peer->sin_port ) );
 | 
		
	
		
			
			| 526 |  | -	if ( server_id.s_addr != peer->sin_addr.s_addr )
 | 
		
	
		
			
			| 527 |  | -		DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
 | 
		
	
		
			
			|  | 534 | +	if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
 | 
		
	
		
			
			|  | 535 | +	     ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
 | 
		
	
		
			
			|  | 536 | +		DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
 | 
		
	
		
			
			|  | 537 | +		DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
 | 
		
	
		
			
			|  | 538 | +	}
 | 
		
	
		
			
			| 528 | 539 |  
 | 
		
	
		
			
			| 529 | 540 |  	/* Identify leased IP address */
 | 
		
	
		
			
			| 530 | 541 |  	ip = dhcppkt->dhcphdr->yiaddr;
 | 
		
	
	
		
			
			|  | @@ -641,19 +652,24 @@ static int dhcp_proxy_tx ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 641 | 652 |   * @v peer		DHCP server address
 | 
		
	
		
			
			| 642 | 653 |   * @v msgtype		DHCP message type
 | 
		
	
		
			
			| 643 | 654 |   * @v server_id		DHCP server ID
 | 
		
	
		
			
			|  | 655 | + * @v pseudo_id		DHCP server pseudo-ID
 | 
		
	
		
			
			| 644 | 656 |   */
 | 
		
	
		
			
			| 645 | 657 |  static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 646 | 658 |  			    struct dhcp_packet *dhcppkt,
 | 
		
	
		
			
			| 647 | 659 |  			    struct sockaddr_in *peer, uint8_t msgtype,
 | 
		
	
		
			
			| 648 |  | -			    struct in_addr server_id ) {
 | 
		
	
		
			
			|  | 660 | +			    struct in_addr server_id,
 | 
		
	
		
			
			|  | 661 | +			    struct in_addr pseudo_id ) {
 | 
		
	
		
			
			| 649 | 662 |  	struct settings *settings = &dhcppkt->settings;
 | 
		
	
		
			
			| 650 | 663 |  	int rc;
 | 
		
	
		
			
			| 651 | 664 |  
 | 
		
	
		
			
			| 652 | 665 |  	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
 | 
		
	
		
			
			| 653 | 666 |  	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
 | 
		
	
		
			
			| 654 | 667 |  	       ntohs ( peer->sin_port ) );
 | 
		
	
		
			
			| 655 |  | -	if ( server_id.s_addr != peer->sin_addr.s_addr )
 | 
		
	
		
			
			| 656 |  | -		DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
 | 
		
	
		
			
			|  | 668 | +	if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
 | 
		
	
		
			
			|  | 669 | +	     ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
 | 
		
	
		
			
			|  | 670 | +		DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
 | 
		
	
		
			
			|  | 671 | +		DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
 | 
		
	
		
			
			|  | 672 | +	}
 | 
		
	
		
			
			| 657 | 673 |  	DBGC ( dhcp, "\n" );
 | 
		
	
		
			
			| 658 | 674 |  
 | 
		
	
		
			
			| 659 | 675 |  	/* Filter out unacceptable responses */
 | 
		
	
	
		
			
			|  | @@ -661,8 +677,7 @@ static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 661 | 677 |  		return;
 | 
		
	
		
			
			| 662 | 678 |  	if ( ( msgtype != DHCPOFFER ) && ( msgtype != DHCPACK ) )
 | 
		
	
		
			
			| 663 | 679 |  		return;
 | 
		
	
		
			
			| 664 |  | -	if ( server_id.s_addr /* Linux PXE server omits server ID */ &&
 | 
		
	
		
			
			| 665 |  | -	     ( server_id.s_addr != dhcp->proxy_server.s_addr ) )
 | 
		
	
		
			
			|  | 680 | +	if ( ( pseudo_id.s_addr != dhcp->proxy_server.s_addr ) )
 | 
		
	
		
			
			| 666 | 681 |  		return;
 | 
		
	
		
			
			| 667 | 682 |  
 | 
		
	
		
			
			| 668 | 683 |  	/* Register settings */
 | 
		
	
	
		
			
			|  | @@ -772,19 +787,24 @@ static int dhcp_pxebs_accept ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 772 | 787 |   * @v peer		DHCP server address
 | 
		
	
		
			
			| 773 | 788 |   * @v msgtype		DHCP message type
 | 
		
	
		
			
			| 774 | 789 |   * @v server_id		DHCP server ID
 | 
		
	
		
			
			|  | 790 | + * @v pseudo_id		DHCP server pseudo-ID
 | 
		
	
		
			
			| 775 | 791 |   */
 | 
		
	
		
			
			| 776 | 792 |  static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 777 | 793 |  			    struct dhcp_packet *dhcppkt,
 | 
		
	
		
			
			| 778 | 794 |  			    struct sockaddr_in *peer, uint8_t msgtype,
 | 
		
	
		
			
			| 779 |  | -			    struct in_addr server_id ) {
 | 
		
	
		
			
			|  | 795 | +			    struct in_addr server_id,
 | 
		
	
		
			
			|  | 796 | +			    struct in_addr pseudo_id ) {
 | 
		
	
		
			
			| 780 | 797 |  	struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
 | 
		
	
		
			
			| 781 | 798 |  	int rc;
 | 
		
	
		
			
			| 782 | 799 |  
 | 
		
	
		
			
			| 783 | 800 |  	DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp,
 | 
		
	
		
			
			| 784 | 801 |  	       dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ),
 | 
		
	
		
			
			| 785 | 802 |  	       ntohs ( peer->sin_port ) );
 | 
		
	
		
			
			| 786 |  | -	if ( server_id.s_addr != peer->sin_addr.s_addr )
 | 
		
	
		
			
			| 787 |  | -		DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) );
 | 
		
	
		
			
			|  | 803 | +	if ( ( server_id.s_addr != peer->sin_addr.s_addr ) ||
 | 
		
	
		
			
			|  | 804 | +	     ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) {
 | 
		
	
		
			
			|  | 805 | +		DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) );
 | 
		
	
		
			
			|  | 806 | +		DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) );
 | 
		
	
		
			
			|  | 807 | +	}
 | 
		
	
		
			
			| 788 | 808 |  
 | 
		
	
		
			
			| 789 | 809 |  	/* Identify boot menu item */
 | 
		
	
		
			
			| 790 | 810 |  	dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM,
 | 
		
	
	
		
			
			|  | @@ -801,8 +821,7 @@ static void dhcp_pxebs_rx ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 801 | 821 |  		return;
 | 
		
	
		
			
			| 802 | 822 |  	if ( menu_item.type != dhcp->pxe_type )
 | 
		
	
		
			
			| 803 | 823 |  		return;
 | 
		
	
		
			
			| 804 |  | -	if ( ! dhcp_pxebs_accept ( dhcp, ( server_id.s_addr ?
 | 
		
	
		
			
			| 805 |  | -					   server_id : peer->sin_addr ) ) )
 | 
		
	
		
			
			|  | 824 | +	if ( ! dhcp_pxebs_accept ( dhcp, pseudo_id ) )
 | 
		
	
		
			
			| 806 | 825 |  		return;
 | 
		
	
		
			
			| 807 | 826 |  
 | 
		
	
		
			
			| 808 | 827 |  	/* Register settings */
 | 
		
	
	
		
			
			|  | @@ -1134,6 +1153,7 @@ static int dhcp_deliver ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 1134 | 1153 |  	struct dhcphdr *dhcphdr;
 | 
		
	
		
			
			| 1135 | 1154 |  	uint8_t msgtype = 0;
 | 
		
	
		
			
			| 1136 | 1155 |  	struct in_addr server_id = { 0 };
 | 
		
	
		
			
			|  | 1156 | +	struct in_addr pseudo_id;
 | 
		
	
		
			
			| 1137 | 1157 |  	int rc = 0;
 | 
		
	
		
			
			| 1138 | 1158 |  
 | 
		
	
		
			
			| 1139 | 1159 |  	/* Sanity checks */
 | 
		
	
	
		
			
			|  | @@ -1168,6 +1188,13 @@ static int dhcp_deliver ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 1168 | 1188 |  	dhcppkt_fetch ( dhcppkt, DHCP_SERVER_IDENTIFIER,
 | 
		
	
		
			
			| 1169 | 1189 |  			&server_id, sizeof ( server_id ) );
 | 
		
	
		
			
			| 1170 | 1190 |  
 | 
		
	
		
			
			|  | 1191 | +	/* Identify server pseudo-ID */
 | 
		
	
		
			
			|  | 1192 | +	pseudo_id = server_id;
 | 
		
	
		
			
			|  | 1193 | +	if ( ! pseudo_id.s_addr )
 | 
		
	
		
			
			|  | 1194 | +		pseudo_id = dhcppkt->dhcphdr->siaddr;
 | 
		
	
		
			
			|  | 1195 | +	if ( ! pseudo_id.s_addr )
 | 
		
	
		
			
			|  | 1196 | +		pseudo_id = peer->sin_addr;
 | 
		
	
		
			
			|  | 1197 | +
 | 
		
	
		
			
			| 1171 | 1198 |  	/* Check for matching transaction ID */
 | 
		
	
		
			
			| 1172 | 1199 |  	if ( dhcphdr->xid != dhcp->xid ) {
 | 
		
	
		
			
			| 1173 | 1200 |  		DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction "
 | 
		
	
	
		
			
			|  | @@ -1190,7 +1217,7 @@ static int dhcp_deliver ( struct dhcp_session *dhcp,
 | 
		
	
		
			
			| 1190 | 1217 |  	}
 | 
		
	
		
			
			| 1191 | 1218 |  
 | 
		
	
		
			
			| 1192 | 1219 |  	/* Handle packet based on current state */
 | 
		
	
		
			
			| 1193 |  | -	dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id );
 | 
		
	
		
			
			|  | 1220 | +	dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id, pseudo_id );
 | 
		
	
		
			
			| 1194 | 1221 |  
 | 
		
	
		
			
			| 1195 | 1222 |   err_chaddr:
 | 
		
	
		
			
			| 1196 | 1223 |   err_xid:
 |