Browse Source

[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 years ago
parent
commit
c345336435
1 changed files with 22 additions and 6 deletions
  1. 22
    6
      src/net/udp/dhcp.c

+ 22
- 6
src/net/udp/dhcp.c View File

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

Loading…
Cancel
Save