Skip to content

Commit c345336

Browse files
author
Michael Brown
committed
[dhcp] Choose ProxyDHCP port based on presence of PXE options
If the ProxyDHCPOFFER already includes PXE options (i.e. option 60 is set to "PXEClient" and option 43 is present) then assume that the ProxyDHCPREQUEST can be sent to port 67, rather than port 4011. This is a reasonable assumption, since in that case the ProxyDHCP server has already demonstrated by responding to the DHCPDISCOVER that it is listening on port 67. (If the ProxyDHCP server were not listening on port 67, then the standard DHCP server would have been configured to respond with option 60 set to "PXEClient" but no option 43 present.) The PXE specification is ambiguous on this point; the specified behaviour covers only the cases in which option 43 is *not* present in the ProxyDHCPOFFER. In these cases, we will continue to send the ProxyDHCPREQUEST to port 4011. This change is required in order to allow us to interoperate with dnsmasq, which listens only on port 67. (dnsmasq relies on unspecified behaviour of the Intel PXE stack, which it seems will retain the ProxyDHCPOFFER as an options source and never issue a ProxyDHCPREQUEST, thereby enabling dnsmasq to omit listening on port 4011.)
1 parent f51d613 commit c345336

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

src/net/udp/dhcp.c

+22-6
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ struct dhcp_session {
224224
int no_pxedhcp;
225225
/** ProxyDHCP server */
226226
struct in_addr proxy_server;
227+
/** ProxyDHCP port */
228+
uint16_t proxy_port;
227229
/** ProxyDHCP server priority */
228230
int proxy_priority;
229231

@@ -357,6 +359,8 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
357359
vci, sizeof ( vci ) );
358360
has_pxeclient = ( ( vci_len >= ( int ) sizeof ( vci ) ) &&
359361
( strncmp ( "PXEClient", vci, sizeof (vci) ) == 0 ));
362+
363+
/* Identify presence of vendor-specific options */
360364
pxeopts_len = dhcppkt_fetch ( dhcppkt, DHCP_VENDOR_ENCAP, NULL, 0 );
361365
has_pxeopts = ( pxeopts_len >= 0 );
362366
if ( has_pxeclient )
@@ -386,9 +390,17 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
386390
}
387391

388392
/* Select as ProxyDHCP offer, if applicable */
389-
if ( has_pxeclient && ( ! has_pxeopts ) && ( msgtype == DHCPOFFER ) &&
393+
if ( has_pxeclient && ( msgtype == DHCPOFFER ) &&
390394
( priority >= dhcp->proxy_priority ) ) {
395+
/* If the offer already includes the PXE options, then
396+
* assume that we can send the ProxyDHCPREQUEST to
397+
* port 67 (since the DHCPDISCOVER that triggered this
398+
* ProxyDHCPOFFER was sent to port 67). Otherwise,
399+
* send the ProxyDHCPREQUEST to port 4011.
400+
*/
391401
dhcp->proxy_server = server_id;
402+
dhcp->proxy_port = ( has_pxeopts ? htons ( BOOTPS_PORT )
403+
: htons ( PXE_PORT ) );
392404
dhcp->proxy_priority = priority;
393405
}
394406

@@ -527,7 +539,11 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
527539
}
528540

529541
/* Start ProxyDHCPREQUEST if applicable */
530-
if ( dhcp->proxy_server.s_addr && ( ! dhcp->no_pxedhcp ) ) {
542+
if ( dhcp->proxy_server.s_addr /* Have ProxyDHCP server */ &&
543+
( ! dhcp->no_pxedhcp ) /* ProxyDHCP not disabled */ &&
544+
( /* ProxyDHCP server is not just the DHCP server itself */
545+
( dhcp->proxy_server.s_addr != dhcp->server.s_addr ) ||
546+
( dhcp->proxy_port != htons ( BOOTPS_PORT ) ) ) ) {
531547
dhcp_set_state ( dhcp, &dhcp_state_proxy );
532548
return;
533549
}
@@ -569,8 +585,8 @@ static int dhcp_proxy_tx ( struct dhcp_session *dhcp,
569585
struct sockaddr_in *peer ) {
570586
int rc;
571587

572-
DBGC ( dhcp, "DHCP %p ProxyDHCP REQUEST to %s:%d\n",
573-
dhcp, inet_ntoa ( dhcp->proxy_server ), PXE_PORT );
588+
DBGC ( dhcp, "DHCP %p ProxyDHCP REQUEST to %s:%d\n", dhcp,
589+
inet_ntoa ( dhcp->proxy_server ), ntohs ( dhcp->proxy_port ) );
574590

575591
/* Set server ID */
576592
if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
@@ -580,7 +596,7 @@ static int dhcp_proxy_tx ( struct dhcp_session *dhcp,
580596

581597
/* Set server address */
582598
peer->sin_addr = dhcp->proxy_server;
583-
peer->sin_port = htons ( PXE_PORT );
599+
peer->sin_port = dhcp->proxy_port;
584600

585601
return 0;
586602
}
@@ -608,7 +624,7 @@ static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
608624
DBGC ( dhcp, "\n" );
609625

610626
/* Filter out unacceptable responses */
611-
if ( peer->sin_port != htons ( PXE_PORT ) )
627+
if ( peer->sin_port != dhcp->proxy_port )
612628
return;
613629
if ( msgtype != DHCPACK )
614630
return;

0 commit comments

Comments
 (0)