From 620b98ee4b9d8fa87c56bfa72b4391c1eed9dce6 Mon Sep 17 00:00:00 2001 From: Joshua Oreman Date: Tue, 25 May 2010 16:17:40 -0400 Subject: [PATCH] [dhcp] Honor PXEBS_SKIP option in discovery control It is permissible for a DHCP packet containing PXE options to specify only "discovery control", instead of the more typical boot menu + prompt options. This is the strategy used by older versions of dnsmasq; by specifying the discovery control as PXEBS_SKIP, they cause vendor PXE ROMs to ignore boot server discovery and just use the filename and next-server options in the initial (Proxy)DHCP packet. Modify iPXE to accept this behavior, to be more compatible with the Intel firmware. Signed-off-by: Joshua Oreman Tested-by: Kyle Kienapfel Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/net/udp/dhcp.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index 63d1ecc6..ac03412d 100644 --- a/src/net/udp/dhcp.c +++ b/src/net/udp/dhcp.c @@ -401,6 +401,7 @@ static void dhcp_rx_offer ( struct dhcp_session *dhcp, int has_pxeclient; int pxeopts_len; int has_pxeopts; + uint8_t discovery_control = 0; struct dhcp_offer *offer; int i; @@ -439,9 +440,32 @@ static void dhcp_rx_offer ( struct dhcp_session *dhcp, has_pxeclient = ( ( vci_len >= ( int ) sizeof ( vci ) ) && ( strncmp ( "PXEClient", vci, sizeof (vci) ) == 0 )); - /* Identify presence of PXE-specific options */ + /* + * Identify presence of PXE-specific options + * + * The Intel firmware appears to check for: + * - PXE_DISCOVERY_CONTROL exists and has bit 3 set, or + * - both PXE_BOOT_MENU and PXE_BOOT_MENU_PROMPT exist + * + * If DISCOVERY_CONTROL bit 3 is set, the firmware treats this + * packet like a "normal" non-PXE DHCP packet with respect to + * boot filename, except that it can come from ProxyDHCP. This + * is the scheme that dnsmasq uses in the simple case. + * + * Otherwise, if one of the boot menu / boot menu prompt + * options exists but not both, the firmware signals an + * error. If neither exists, the packet is not considered to + * contain DHCP options. + * + * In an effort to preserve semantics but be more flexible, we + * check only for bit 3 of DISCOVERY_CONTROL or the presence + * of BOOT_MENU. We don't care (yet) about the menu prompt. + */ pxeopts_len = dhcppkt_fetch ( dhcppkt, DHCP_PXE_BOOT_MENU, NULL, 0 ); - has_pxeopts = ( pxeopts_len >= 0 ); + dhcppkt_fetch ( dhcppkt, DHCP_PXE_DISCOVERY_CONTROL, + &discovery_control, sizeof ( discovery_control ) ); + has_pxeopts = ( ( pxeopts_len >= 0 ) || + ( discovery_control & PXEBS_SKIP ) ); if ( has_pxeclient ) DBGC ( dhcp, "%s", ( has_pxeopts ? " pxe" : " proxy" ) );