* @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
*/
* @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;
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;
}
/* 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;
}
* @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;
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;
* @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 */
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 */
* @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,
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 */
struct dhcphdr *dhcphdr;
uint8_t msgtype = 0;
struct in_addr server_id = { 0 };
+ struct in_addr pseudo_id;
int rc = 0;
/* Sanity checks */
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 "
}
/* 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: