diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index 61bef998..7d5237bc 100644 --- a/src/net/udp/dhcp.c +++ b/src/net/udp/dhcp.c @@ -154,22 +154,23 @@ struct dhcp_session_state { * @v dhcppkt DHCP packet * @v peer Destination address */ - int ( * tx ) ( struct dhcp_session *dhcp, - struct dhcp_packet *dhcppkt, + int ( * tx ) ( struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer ); - /** Handle received packet + /** + * Handle received packet * * @v dhcp DHCP session * @v dhcppkt DHCP packet * @v peer DHCP server address * @v msgtype DHCP message type * @v server_id DHCP server ID + * @v pseudo_id DHCP server pseudo-ID */ - void ( * rx ) ( struct dhcp_session *dhcp, - struct dhcp_packet *dhcppkt, - struct sockaddr_in *peer, - uint8_t msgtype, struct in_addr server_id ); - /** Handle timer expiry + void ( * rx ) ( struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, + struct sockaddr_in *peer, uint8_t msgtype, + struct in_addr server_id, struct in_addr pseudo_id ); + /** + * Handle timer expiry * * @v dhcp DHCP session */ @@ -340,11 +341,13 @@ static int dhcp_discovery_tx ( struct dhcp_session *dhcp, * @v peer DHCP server address * @v msgtype DHCP message type * @v server_id DHCP server ID + * @v pseudo_id DHCP server pseudo-ID */ static void dhcp_discovery_rx ( struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer, uint8_t msgtype, - struct in_addr server_id ) { + struct in_addr server_id, + struct in_addr pseudo_id ) { struct in_addr ip; char vci[9]; /* "PXEClient" */ int vci_len; @@ -356,8 +359,11 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp, DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp, dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ) ); - if ( server_id.s_addr != peer->sin_addr.s_addr ) - DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) ); + if ( ( server_id.s_addr != peer->sin_addr.s_addr ) || + ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) { + DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) ); + DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) ); + } /* Identify offered IP address */ ip = dhcppkt->dhcphdr->yiaddr; @@ -398,10 +404,10 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp, } /* Select as ProxyDHCP offer, if applicable */ - if ( server_id.s_addr && has_pxeclient && + if ( pseudo_id.s_addr && has_pxeclient && ( priority >= dhcp->proxy_priority ) ) { dhcppkt_put ( dhcp->proxy_offer ); - dhcp->proxy_server = server_id; + dhcp->proxy_server = pseudo_id; dhcp->proxy_offer = dhcppkt_get ( dhcppkt ); dhcp->proxy_priority = priority; } @@ -510,11 +516,13 @@ static int dhcp_request_tx ( struct dhcp_session *dhcp, * @v peer DHCP server address * @v msgtype DHCP message type * @v server_id DHCP server ID + * @v pseudo_id DHCP server pseudo-ID */ static void dhcp_request_rx ( struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer, uint8_t msgtype, - struct in_addr server_id ) { + struct in_addr server_id, + struct in_addr pseudo_id ) { struct in_addr ip; struct settings *parent; struct settings *settings; @@ -523,8 +531,11 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp, DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp, dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ) ); - if ( server_id.s_addr != peer->sin_addr.s_addr ) - DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) ); + if ( ( server_id.s_addr != peer->sin_addr.s_addr ) || + ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) { + DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) ); + DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) ); + } /* Identify leased IP address */ ip = dhcppkt->dhcphdr->yiaddr; @@ -641,19 +652,24 @@ static int dhcp_proxy_tx ( struct dhcp_session *dhcp, * @v peer DHCP server address * @v msgtype DHCP message type * @v server_id DHCP server ID + * @v pseudo_id DHCP server pseudo-ID */ static void dhcp_proxy_rx ( struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer, uint8_t msgtype, - struct in_addr server_id ) { + struct in_addr server_id, + struct in_addr pseudo_id ) { struct settings *settings = &dhcppkt->settings; int rc; DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp, dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ) ); - if ( server_id.s_addr != peer->sin_addr.s_addr ) - DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) ); + if ( ( server_id.s_addr != peer->sin_addr.s_addr ) || + ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) { + DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) ); + DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) ); + } DBGC ( dhcp, "\n" ); /* Filter out unacceptable responses */ @@ -661,8 +677,7 @@ static void dhcp_proxy_rx ( struct dhcp_session *dhcp, return; if ( ( msgtype != DHCPOFFER ) && ( msgtype != DHCPACK ) ) return; - if ( server_id.s_addr /* Linux PXE server omits server ID */ && - ( server_id.s_addr != dhcp->proxy_server.s_addr ) ) + if ( ( pseudo_id.s_addr != dhcp->proxy_server.s_addr ) ) return; /* Register settings */ @@ -772,19 +787,24 @@ static int dhcp_pxebs_accept ( struct dhcp_session *dhcp, * @v peer DHCP server address * @v msgtype DHCP message type * @v server_id DHCP server ID + * @v pseudo_id DHCP server pseudo-ID */ static void dhcp_pxebs_rx ( struct dhcp_session *dhcp, struct dhcp_packet *dhcppkt, struct sockaddr_in *peer, uint8_t msgtype, - struct in_addr server_id ) { + struct in_addr server_id, + struct in_addr pseudo_id ) { struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 }; int rc; DBGC ( dhcp, "DHCP %p %s from %s:%d", dhcp, dhcp_msgtype_name ( msgtype ), inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ) ); - if ( server_id.s_addr != peer->sin_addr.s_addr ) - DBGC ( dhcp, " (%s)", inet_ntoa ( server_id ) ); + if ( ( server_id.s_addr != peer->sin_addr.s_addr ) || + ( pseudo_id.s_addr != peer->sin_addr.s_addr ) ) { + DBGC ( dhcp, " (%s/", inet_ntoa ( server_id ) ); + DBGC ( dhcp, "%s)", inet_ntoa ( pseudo_id ) ); + } /* Identify boot menu item */ dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU_ITEM, @@ -801,8 +821,7 @@ static void dhcp_pxebs_rx ( struct dhcp_session *dhcp, return; if ( menu_item.type != dhcp->pxe_type ) return; - if ( ! dhcp_pxebs_accept ( dhcp, ( server_id.s_addr ? - server_id : peer->sin_addr ) ) ) + if ( ! dhcp_pxebs_accept ( dhcp, pseudo_id ) ) return; /* Register settings */ @@ -1134,6 +1153,7 @@ static int dhcp_deliver ( struct dhcp_session *dhcp, struct dhcphdr *dhcphdr; uint8_t msgtype = 0; struct in_addr server_id = { 0 }; + struct in_addr pseudo_id; int rc = 0; /* Sanity checks */ @@ -1168,6 +1188,13 @@ static int dhcp_deliver ( struct dhcp_session *dhcp, dhcppkt_fetch ( dhcppkt, DHCP_SERVER_IDENTIFIER, &server_id, sizeof ( server_id ) ); + /* Identify server pseudo-ID */ + pseudo_id = server_id; + if ( ! pseudo_id.s_addr ) + pseudo_id = dhcppkt->dhcphdr->siaddr; + if ( ! pseudo_id.s_addr ) + pseudo_id = peer->sin_addr; + /* Check for matching transaction ID */ if ( dhcphdr->xid != dhcp->xid ) { DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction " @@ -1190,7 +1217,7 @@ static int dhcp_deliver ( struct dhcp_session *dhcp, } /* Handle packet based on current state */ - dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id ); + dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id, pseudo_id ); err_chaddr: err_xid: