Skip to content

Commit 81ac272

Browse files
mwetterwdavem330
authored andcommitted
net: ipconfig: Allow DNS to be overwritten by DHCPACK
Some DHCP server implementations only send the important requested DHCP options in the final BOOTP reply (DHCPACK). One example is systemd-networkd. However, RFC2131, in section 4.3.1 states: > The server MUST return to the client: > [...] > o Parameters requested by the client, according to the following > rules: > > -- IF the server has been explicitly configured with a default > value for the parameter, the server MUST include that value > in an appropriate option in the 'option' field, ELSE I've reported the issue here: systemd/systemd#27471 Linux PNP DHCP client implementation only takes into account the DNS servers received in the first BOOTP reply (DHCPOFFER). This usually isn't an issue as servers are required to put the same values in the DHCPOFFER and DHCPACK. However, RFC2131, in section 4.3.2 states: > Any configuration parameters in the DHCPACK message SHOULD NOT > conflict with those in the earlier DHCPOFFER message to which the > client is responding. The client SHOULD use the parameters in the > DHCPACK message for configuration. When making Linux PNP DHCP client (cmdline ip=dhcp) interact with systemd-networkd DHCP server, an interesting "protocol misunderstanding" happens: Because DNS servers were only specified in the DHCPACK and not in the DHCPOFFER, Linux will not catch the correct DNS servers: in the first BOOTP reply (DHCPOFFER), it sees that there is no DNS, and sets as fallback the IP of the DHCP server itself. When the second BOOTP reply comes (DHCPACK), it's already too late: the kernel will not overwrite the fallback setting it has set previously. This patch makes the kernel overwrite its DNS fallback by DNS servers specified in the DHCPACK if any. Signed-off-by: Martin Wetterwald <martin@wetterwald.eu> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 9d142ed commit 81ac272

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

net/ipv4/ipconfig.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ static int ic_proto_have_if __initdata;
173173
/* MTU for boot device */
174174
static int ic_dev_mtu __initdata;
175175

176+
/* DHCPACK can overwrite DNS if fallback was set upon first BOOTP reply */
177+
static int ic_nameservers_fallback __initdata;
178+
176179
#ifdef IPCONFIG_DYNAMIC
177180
static DEFINE_SPINLOCK(ic_recv_lock);
178181
static volatile int ic_got_reply __initdata; /* Proto(s) that replied */
@@ -938,7 +941,8 @@ static void __init ic_do_bootp_ext(u8 *ext)
938941
if (servers > CONF_NAMESERVERS_MAX)
939942
servers = CONF_NAMESERVERS_MAX;
940943
for (i = 0; i < servers; i++) {
941-
if (ic_nameservers[i] == NONE)
944+
if (ic_nameservers[i] == NONE ||
945+
ic_nameservers_fallback)
942946
memcpy(&ic_nameservers[i], ext+1+4*i, 4);
943947
}
944948
break;
@@ -1158,8 +1162,10 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
11581162
ic_addrservaddr = b->iph.saddr;
11591163
if (ic_gateway == NONE && b->relay_ip)
11601164
ic_gateway = b->relay_ip;
1161-
if (ic_nameservers[0] == NONE)
1165+
if (ic_nameservers[0] == NONE) {
11621166
ic_nameservers[0] = ic_servaddr;
1167+
ic_nameservers_fallback = 1;
1168+
}
11631169
ic_got_reply = IC_BOOTP;
11641170

11651171
drop_unlock:

0 commit comments

Comments
 (0)