From: Florian Obser Subject: Re: dhcpleased: patch xid problem To: Andre S Cc: tech@openbsd.org Date: Sun, 11 Feb 2024 16:22:16 +0100 On 2024-02-03 22:41 +03, Andre S wrote: > I am faced with the problem of receiving dhcp data from my internet > service provider. A laptop with OpenBSD cannot receive dhcp data. > However, a Windows 7 laptop receives dhcp data without problems. > I captured packets on ports 67 and 68 on an OpenBSD laptop using the > tcpdump utility. I also captured packets on ports 67 and 68 on > a Windows 7 laptop using the Wireshark utility. A comparison of the > captured packets in the Wireshark utility showed that the dhcp discover, > dhcp offer and dhcp request packets captured in Windows 7 have the > same xid. And the packets captured in OpenBSD dhcpdiscover, dhcpoffer > have the same xid, and the dhcp request packet has a different xid. >   > Link to screenshots. > Wireshark screenshot from Win 7 laptop   https://i.imgur.com/PISB64U.png > Wireshark screenshot from OpenBSD laptop https://i.imgur.com/oIsPJjj.png >   >   > According to Florian commit, a new xid is generated whenever the state > changes https://marc.info/?l=openbsd-tech&m=163939439719215 . > But according to the table in section 4.4.1 rfc2131 in the packet > dhcp request 'xid' from server DHCPOFFER message. And "The DHCPREQUEST > message contains the same 'xid' as the DHCPOFFER message." https://www.ietf.org/rfc/rfc2131.txt >   >   > I prepared a patch that when changing the dhcpleased state from > IF_INIT to IF_REQUESTING, the xid does not change. In case of my > internet service provider, the problem is gone. >   > Amazing that anything works at all, ever. As far as I can tell only table 5 suggests that we need to keep the xid for the whole DHCPDISCOVER / DHCPOFFER / DHCPREQUEST / DHCPACK exchange of messages. Oh well, Could you try this instead? This only creates a new xid when we start a new exchange of messages to get a new lease / renew an existing lease. diff --git engine.c engine.c index 6d371a5a112..0268b247938 100644 --- engine.c +++ engine.c @@ -1385,8 +1385,6 @@ state_transition(struct dhcpleased_iface *iface, enum if_state new_state) char ifnamebuf[IF_NAMESIZE], *if_name; iface->state = new_state; - if (new_state != old_state) - iface->xid = arc4random(); switch (new_state) { case IF_DOWN: @@ -1426,6 +1424,7 @@ state_transition(struct dhcpleased_iface *iface, enum if_state new_state) case IF_DOWN: case IF_IPV6_ONLY: iface->timo.tv_sec = START_EXP_BACKOFF; + iface->xid = arc4random(); break; case IF_BOUND: fatal("invalid transition Bound -> Init"); @@ -1436,8 +1435,10 @@ state_transition(struct dhcpleased_iface *iface, enum if_state new_state) case IF_REBOOTING: if (old_state == IF_REBOOTING) iface->timo.tv_sec *= 2; - else + else { iface->timo.tv_sec = START_EXP_BACKOFF; + iface->xid = arc4random(); + } request_dhcp_request(iface); break; case IF_REQUESTING: @@ -1458,6 +1459,7 @@ state_transition(struct dhcpleased_iface *iface, enum if_state new_state) if (old_state == IF_BOUND) { iface->timo.tv_sec = (iface->rebinding_time - iface->renewal_time) / 2; /* RFC 2131 4.4.5 */ + iface->xid = arc4random(); } else iface->timo.tv_sec /= 2; -- In my defence, I have been left unsupervised.