dhcppython icon indicating copy to clipboard operation
dhcppython copied to clipboard

Sample client gets confused by its own packets.

Open tomkcook opened this issue 11 months ago • 2 comments

Sample output running the client on linux-aarch64-raspi:

DEBUG:root: Creating socket to receiving data, binding to ('', 67)
INFO:root: Binding to wlan0
INFO:root: Bound <module 'socket' from '/usr/lib/python3.12/socket.py'>
DEBUG:root: Creating socket to send data, binding to ('', 68)
INFO:root: Binding to wlan0
INFO:root: Bound <module 'socket' from '/usr/lib/python3.12/socket.py'>
DEBUG:root: listening sockets: [<socket.socket fd=6, family=2, type=2, proto=0, laddr=('0.0.0.0', 67)>, <socket.socket fd=7, family=2, type=2, proto=0, laddr=('0.0.0.0', 68)>]
DEBUG:root: write sockets: [<socket.socket fd=7, family=2, type=2, proto=0, laddr=('0.0.0.0', 68)>]
DEBUG:root: Synthetizing discover packet
DEBUG:root: Constructed discover packet: DHCPPacket(op='BOOTREQUEST', htype='ETHERNET', hlen=6, hops=0, xid=3500635024, secs=0, flags=32768, ciaddr=IPv4Address('0.0.0.0'), yiaddr=IPv4Address('0.0.0.0'), 
siaddr=IPv4Address('0.0.0.0'), giaddr=IPv4Address('0.0.0.0'), chaddr='CC:14:4E:94:CC:F2', sname=b'', file=b'', options=OptionList([MessageType(code=53, length=1, data=b'\x01')]))
DEBUG:root: Sending discover packet to 255.255.255.255 with tx_id=3500635024
DEBUG:root: Select: ([], [<socket.socket fd=7, family=2, type=2, proto=0, laddr=('0.0.0.0', 68)>], [])
DEBUG:root: Connecting to 255.255.255.255:67
DEBUG:root: Sending data 
b'\x01\x01\x06\x00\xd0\xa7s\x90\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcc\x14N\x94\xcc\xf2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x
00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00c\x82Sc5\x01\x01\xff'
DEBUG:root: Packet Sent
DEBUG:root: Listening for offer packet...
DEBUG:root: Listening on wlan0, UDP ports [67]
DEBUG:root: Select: ([<socket.socket fd=6, family=2, type=2, proto=0, laddr=('0.0.0.0', 67)>], [<socket.socket fd=7, family=2, type=2, proto=0, laddr=('0.0.0.0', 68)>], [])
DEBUG:root: Received data from ('0.0.0.0', 68): 
b'\x01\x01\x06\x00\xd0\xa7s\x90\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xcc\x14N\x94\xcc\xf2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x
00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00c\x82Sc5\x01\x01\xff'
DEBUG:root: DHCP message type does not match expected: DHCPDISCOVER != DHCPOFFER
DEBUG:root: DHCPPacket(op='BOOTREQUEST', htype='ETHERNET', hlen=6, hops=0, xid=3500635024, secs=0, flags=32768, ciaddr=IPv4Address('0.0.0.0'), yiaddr=IPv4Address('0.0.0.0'), 
siaddr=IPv4Address('0.0.0.0'), giaddr=IPv4Address('0.0.0.0'), chaddr='CC:14:4E:94:CC:F2', sname=b'', file=b'', options=OptionList([MessageType(code=53, length=1, data=b'\x01'), End(code=255, length=0, 
data=b'')]))
DEBUG:root: Select: ([], [<socket.socket fd=7, family=2, type=2, proto=0, laddr=('0.0.0.0', 68)>], [])
DEBUG:root: Attempt 1 - No sockets available to read from... sleeping for 10 ms
DEBUG:root: Select: ([], [<socket.socket fd=7, family=2, type=2, proto=0, laddr=('0.0.0.0', 68)>], [])
DEBUG:root: Attempt 2 - No sockets available to read from... sleeping for 10 ms
DEBUG:root: Select: ([], [<socket.socket fd=7, family=2, type=2, proto=0, laddr=('0.0.0.0', 68)>], [])
DEBUG:root: Attempt 3 - No sockets available to read from... sleeping for 10 ms
DEBUG:root: Select: ([], [<socket.socket fd=7, family=2, type=2, proto=0, laddr=('0.0.0.0', 68)>], [])
DEBUG:root: Attempt 4 - No sockets available to read from... sleeping for 10 ms
DEBUG:root: Select: ([], [<socket.socket fd=7, family=2, type=2, proto=0, laddr=('0.0.0.0', 68)>], [])
DEBUG:root: Attempt 5 - No sockets available to read from... sleeping for 10 ms

Seems reasonably clear that it is seeing its own broadcast message and getting confused by it.

tomkcook avatar Feb 12 '25 11:02 tomkcook

tcpdump shows the DHCP reply landing correctly so not clear why the library doesn't see it, even though it rejects its own packet and then listens again.

tomkcook avatar Feb 12 '25 11:02 tomkcook

FWIW I tracked this down. The version of Linux I'm using doesn't deliver UDP broadcasts to a socket bound to (0.0.0.0, 68) if the interface doesn't already have an IP address. You have to use raw sockets for the listener instead, which then means you have to either use BPF to do the filtering in the kernel (yikes) or do it all in userspace (slow).

I've also found that the REQUEST packet sent by the client doesn't have enough info for dnsmasq to generate a valid ACK. Instead of setting Client-IP you need to set the Requested IP option.

tomkcook avatar Feb 12 '25 16:02 tomkcook