Index | Thread | Search

From:
Florian Obser <florian@openbsd.org>
Subject:
Re: dhcpleased: patch xid problem
To:
Andre S <andre.s@list.ru>
Cc:
tech@openbsd.org
Date:
Sun, 11 Feb 2024 16:22:16 +0100

Download raw body.

Thread
On 2024-02-03 22:41 +03, Andre S <andre.s@list.ru> 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.