aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2023-02-03 19:36:57 +0000
committerMichael Brown <mcb30@ipxe.org>2023-02-03 19:51:58 +0000
commit8450fa4a7b9a8236a43b74639fc80bada994ce07 (patch)
treee432e583f9e87ec6f146ab7e7e789f04df7544f5
parent4e456d992889569e2dbb0426f2438797ab06ca1f (diff)
downloadipxe-8450fa4a7b9a8236a43b74639fc80bada994ce07.zip
ipxe-8450fa4a7b9a8236a43b74639fc80bada994ce07.tar.gz
ipxe-8450fa4a7b9a8236a43b74639fc80bada994ce07.tar.bz2
[dhcp] Ignore DHCPNAK unless originating from the selected DHCP serverdhcpnak
RFC 2131 leaves undefined the behaviour of the client in response to a DHCPNAK that comes from a server other than the selected DHCP server. A substantial amount of online documentation suggests using multiple independent DHCP servers with non-overlapping ranges in the same subnet in order to provide some minimal redundancy. Experimentation shows that in this setup, at least ISC dhcpd will send a DHCPNAK in response to the client's DHCPREQUEST for an address that is not within the range defined on that server. (Since the requested address does lie within the subnet defined on that server, this will happen regardless of the "authoritative" parameter.) The client will therefore receive a DHCPACK from the selected DHCP server along with one or more DHCPNAKs from each of the non-selected DHCP servers. Filter out responses from non-selected DHCP servers before checking for a DHCPNAK, so that these arguably spurious DHCPNAKs will not cause iPXE to return to the discovery state. Continue to check for DHCPNAK before filtering out responses for non-selected lease addresses, since experimentation shows that the DHCPNAK will usually have an empty yiaddr field. Reported-by: Anders Blomdell <anders.blomdell@control.lth.se> Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/net/udp/dhcp.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c
index b7b84e7..a1a481e 100644
--- a/src/net/udp/dhcp.c
+++ b/src/net/udp/dhcp.c
@@ -571,6 +571,10 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
if ( peer->sin_port != htons ( BOOTPS_PORT ) )
return;
+ /* Filter out non-selected servers */
+ if ( server_id.s_addr != dhcp->server.s_addr )
+ return;
+
/* Handle DHCPNAK */
if ( msgtype == DHCPNAK ) {
dhcp_defer ( dhcp );
@@ -580,8 +584,6 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
/* Filter out unacceptable responses */
if ( msgtype /* BOOTP */ && ( msgtype != DHCPACK ) )
return;
- if ( server_id.s_addr != dhcp->server.s_addr )
- return;
if ( ip.s_addr != dhcp->offer.s_addr )
return;