diff options
author | Michael Brown <mcb30@ipxe.org> | 2023-02-03 19:36:57 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2023-02-03 19:51:58 +0000 |
commit | 8450fa4a7b9a8236a43b74639fc80bada994ce07 (patch) | |
tree | e432e583f9e87ec6f146ab7e7e789f04df7544f5 | |
parent | 4e456d992889569e2dbb0426f2438797ab06ca1f (diff) | |
download | ipxe-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.c | 6 |
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; |