Browse Source

[dhcp] Send broadcast PXE boot server discovery requests to port 67

We currently send all boot server discovery requests to port 4011.
Section 2.2.1 of the PXE spec states that boot server discovery
packets should be "sent broadcast (port 67), multicast (port 4011), or
unicast (port 4011)".  Adjust our behaviour so that any boot server
discovery packets that are sent to the broadcast address are directed
to port 67 rather than port 4011.

This is required for operation with dnsmasq as a PXE server, since
dnsmasq listens only on port 67, and relies upon this (specified)
behaviour.

This change may break some setups using the (itself very broken) Linux
PXE server from kano.org.uk.  This server will, in its default
configuration, listen only on port 4011.  It never constructs a boot
server list (PXE_BOOT_SERVERS, option 43.8), and uses the wrong
definitions for the discovery control bits (PXE_DISCOVERY_CONTROL,
option 43.6).  The upshot is that it will always instruct the client
to perform multicast and broadcast discovery only.  In setups lacking
a valid multicast route on the server side, this used to work because
gPXE would eventually give up on the (non-responsive) multicast
address and send a broadcast request to port 4011, which the Linux PXE
server would respond to.  Now that gPXE correctly sends this broadcast
request to port 67 instead, it is never seen by the Linux PXE server,
and the boot fails.  The fix is to either (a) set up a multicast route
correctly on the server side before starting the PXE server, or (b)
edit /etc/pxe.conf to contain the server's unicast address in the
"multicast_address" field (a hack that happens to work).

Suggested-by: Simon Kelley <simon@thekelleys.org.uk>
tags/v0.9.8
Michael Brown 15 years ago
parent
commit
3961c1ca02
1 changed files with 8 additions and 6 deletions
  1. 8
    6
      src/net/udp/dhcp.c

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

670
 	struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
670
 	struct dhcp_pxe_boot_menu_item menu_item = { 0, 0 };
671
 	int rc;
671
 	int rc;
672
 
672
 
673
+	/* Set server address */
674
+	peer->sin_addr = *(dhcp->pxe_attempt);
675
+	peer->sin_port = ( ( peer->sin_addr.s_addr == INADDR_BROADCAST ) ?
676
+			   htons ( BOOTPS_PORT ) : htons ( PXE_PORT ) );
677
+
673
 	DBGC ( dhcp, "DHCP %p PXEBS REQUEST to %s:%d for type %d\n",
678
 	DBGC ( dhcp, "DHCP %p PXEBS REQUEST to %s:%d for type %d\n",
674
-	       dhcp, inet_ntoa ( *(dhcp->pxe_attempt) ), PXE_PORT,
679
+	       dhcp, inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ),
675
 	       ntohs ( dhcp->pxe_type ) );
680
 	       ntohs ( dhcp->pxe_type ) );
676
 
681
 
677
 	/* Set boot menu item */
682
 	/* Set boot menu item */
680
 				    &menu_item, sizeof ( menu_item ) ) ) != 0 )
685
 				    &menu_item, sizeof ( menu_item ) ) ) != 0 )
681
 		return rc;
686
 		return rc;
682
 
687
 
683
-	/* Set server address */
684
-	peer->sin_addr = *(dhcp->pxe_attempt);
685
-	peer->sin_port = htons ( PXE_PORT );
686
-
687
 	return 0;
688
 	return 0;
688
 }
689
 }
689
 
690
 
743
 	DBGC ( dhcp, "\n" );
744
 	DBGC ( dhcp, "\n" );
744
 
745
 
745
 	/* Filter out unacceptable responses */
746
 	/* Filter out unacceptable responses */
746
-	if ( peer->sin_port != htons ( PXE_PORT ) )
747
+	if ( ( peer->sin_port != htons ( BOOTPS_PORT ) ) &&
748
+	     ( peer->sin_port != htons ( PXE_PORT ) ) )
747
 		return;
749
 		return;
748
 	if ( msgtype != DHCPACK )
750
 	if ( msgtype != DHCPACK )
749
 		return;
751
 		return;

Loading…
Cancel
Save