瀏覽代碼

[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.)
tags/v0.9.8
Michael Brown 15 年之前
父節點
當前提交
c345336435
共有 1 個檔案被更改,包括 22 行新增6 行删除
  1. 22
    6
      src/net/udp/dhcp.c

+ 22
- 6
src/net/udp/dhcp.c 查看文件

@@ -224,6 +224,8 @@ struct dhcp_session {
224 224
 	int no_pxedhcp;
225 225
 	/** ProxyDHCP server */
226 226
 	struct in_addr proxy_server;
227
+	/** ProxyDHCP port */
228
+	uint16_t proxy_port;
227 229
 	/** ProxyDHCP server priority */
228 230
 	int proxy_priority;
229 231
 
@@ -357,6 +359,8 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
357 359
 				  vci, sizeof ( vci ) );
358 360
 	has_pxeclient = ( ( vci_len >= ( int ) sizeof ( vci ) ) &&
359 361
 			  ( strncmp ( "PXEClient", vci, sizeof (vci) ) == 0 ));
362
+
363
+	/* Identify presence of vendor-specific options */
360 364
 	pxeopts_len = dhcppkt_fetch ( dhcppkt, DHCP_VENDOR_ENCAP, NULL, 0 );
361 365
 	has_pxeopts = ( pxeopts_len >= 0 );
362 366
 	if ( has_pxeclient )
@@ -386,9 +390,17 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp,
386 390
 	}
387 391
 
388 392
 	/* Select as ProxyDHCP offer, if applicable */
389
-	if ( has_pxeclient && ( ! has_pxeopts ) && ( msgtype == DHCPOFFER ) &&
393
+	if ( has_pxeclient && ( msgtype == DHCPOFFER ) &&
390 394
 	     ( 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
+		 */
391 401
 		dhcp->proxy_server = server_id;
402
+		dhcp->proxy_port = ( has_pxeopts ? htons ( BOOTPS_PORT )
403
+				     : htons ( PXE_PORT ) );
392 404
 		dhcp->proxy_priority = priority;
393 405
 	}
394 406
 
@@ -527,7 +539,11 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
527 539
 	}
528 540
 
529 541
 	/* 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 ) ) ) ) {
531 547
 		dhcp_set_state ( dhcp, &dhcp_state_proxy );
532 548
 		return;
533 549
 	}
@@ -569,8 +585,8 @@ static int dhcp_proxy_tx ( struct dhcp_session *dhcp,
569 585
 			   struct sockaddr_in *peer ) {
570 586
 	int rc;
571 587
 
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 ) );
574 590
 
575 591
 	/* Set server ID */
576 592
 	if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
@@ -580,7 +596,7 @@ static int dhcp_proxy_tx ( struct dhcp_session *dhcp,
580 596
 
581 597
 	/* Set server address */
582 598
 	peer->sin_addr = dhcp->proxy_server;
583
-	peer->sin_port = htons ( PXE_PORT );
599
+	peer->sin_port = dhcp->proxy_port;
584 600
 
585 601
 	return 0;
586 602
 }
@@ -608,7 +624,7 @@ static void dhcp_proxy_rx ( struct dhcp_session *dhcp,
608 624
 	DBGC ( dhcp, "\n" );
609 625
 
610 626
 	/* Filter out unacceptable responses */
611
-	if ( peer->sin_port != htons ( PXE_PORT ) )
627
+	if ( peer->sin_port != dhcp->proxy_port )
612 628
 		return;
613 629
 	if ( msgtype != DHCPACK )
614 630
 		return;

Loading…
取消
儲存