Thanks Florian, here's a tcpdump from the Apple (NetBSD) router. This implementatin isn't losing the default route.
tcpdump -n -i mgi1 -s1500 -vv port 67 or 68 tcpdump: listening on mgi1, link-type EN10MB (Ethernet), capture size 1500 bytes 07:15:36.010329 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], length: 328) 0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] UDP, length: 300 07:15:40.326961 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], length: 328) 0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] UDP, length: 300 07:15:47.010316 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], length: 328) 0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] UDP, length: 300 07:15:47.065803 IP (tos 0xc0, ttl 128, id 47543, offset 0, flags [none], length: 328) 202.63.66.1.67 > 255.255.255.255.68: [udp sum ok] UDP, length: 300 07:15:47.066581 IP (tos 0x10, ttl 128, id 0, offset 0, flags [none], length: 328) 0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] UDP, length: 300 07:15:47.281209 IP (tos 0xc0, ttl 128, id 59063, offset 0, flags [none], length: 328) 202.63.66.1.67 > 255.255.255.255.68: [udp sum ok] UDP, length: 300 07:20:42.239765 IP (tos 0x0, ttl 64, id 31050, offset 0, flags [none], length: 328, bad cksum 0 (->e6b6)!) 202.63.67.36.68 > 202.63.66.1.67: [bad udp cksum 8b57!] UDP, length: 300 07:20:42.288197 IP (tos 0xc0, ttl 128, id 45441, offset 0, flags [none], length: 328) 202.63.66.1.67 > 202.63.67.36.68: [udp sum ok] UDP, length: 300 07:25:07.019747 IP (tos 0x0, ttl 64, id 18503, offset 0, flags [none], length: 328, bad cksum 0 (->17ba)!) 202.63.67.36.68 > 202.63.66.1.67: [bad udp cksum 8b57!] UDP, length: 300 07:25:07.085454 IP (tos 0xc0, ttl 128, id 28472, offset 0, flags [none], length: 328) 202.63.66.1.67 > 202.63.67.36.68: [udp sum ok] UDP, length: 300 07:30:08.019746 IP (tos 0x0, ttl 64, id 46516, offset 0, flags [none], length: 328, bad cksum 0 (->aa4c)!) 202.63.67.36.68 > 202.63.66.1.67: [bad udp cksum 8b57!] UDP, length: 300 07:30:08.068323 IP (tos 0xc0, ttl 128, id 21000, offset 0, flags [none], length: 328) 202.63.66.1.67 > 202.63.67.36.68: [udp sum ok] UDP, length: 300 On Wed, May 10, 2023 at 04:38:25PM +0200, Florian Obser wrote: > ( this is a good dhcp state diagram to follow along at home: > https://commons.wikimedia.org/wiki/File:DHCP_Client_State_Diagram_-_en.png ) > > On 2023-05-10 23:07 +10, David Diggles <da...@elven.com.au> wrote: > > I probably should have done numeric tcpdump output. Here's both again. > > > > tcpdump: WARNING: snaplen raised from 116 to 1500 > > 22:36:40.276682 0.0.0.0.68 > 255.255.255.255.67: xid:0x74253f08 > > vend-rfc1048 DHCP:REQUEST HN:"sarah" CID:1.220.159.219.40.20.191 > > PR:SM+DG+NS+HN+DN+BR+119+121 RQ:202.63.67.36 [tos 0x10] > > dhcpleased starts up and we have a lease file in /var/db/dhcpleased/, we > are in INIT-REBOOT and ask the dhcp server via broadcast if we can use > our previous IP address 202.63.67.36. We go to state REBOOTING. > > > 22:36:40.327371 202.63.66.1.67 > 255.255.255.255.68: xid:0x74253f08 > > flags:0x8000 Y:202.63.67.36 S:172.21.116.42 ether dc:9f:db:28:14:bf > > vend-rfc1048 DHCP:ACK SM:255.255.254.0 DG:202.63.66.1 > > NS:119.40.106.35,119.40.106.36 NTP:125.253.59.254 LT:600 SID:202.63.66.1 > > CID:1.220.159.219.40.20.191 [tos 0xc0] > > dhcp server: yeah, that's fine (DHCP:ACK). Lifetime is 600 seconds. We > configure the interface and go into state BOUND. > > some time passes > > > 22:41:40.422661 202.63.67.36.56480 > 202.63.66.1.67: (request) > > xid:0xa180ce6b C:202.63.67.36 vend-rfc1048 DHCP:REQUEST HN:"sarah" > > CID:1.220.159.219.40.20.191 PR:SM+DG+NS+HN+DN+BR+119+121 > > Time T1 expires, we send a unicast DHCPREQUEST to the dhcpserver: is it > OK to hold on to our IP address? We go into state RENEWING. > > > 22:41:40.434534 202.63.66.1.67 > 202.63.67.36.68: xid:0xa180ce6b > > C:202.63.67.36 S:172.21.116.42 vend-rfc1048 DHCP:NACK SID:202.63.66.1 > > CID:1.220.159.219.40.20.191 [tos 0xc0] > > dhcp server: Absolutely not! DHCP:NACK. > > RFC 2131 has this: > > If the client receives a DHCPNAK message, it cannot reuse its > remembered network address. It must instead request a new > address by restarting the configuration process, this time > using the (non-abbreviated) procedure described in section > 3.1. This action also corresponds to the client moving to > the INIT state in the DHCP state diagram. > > There is not a lot of wiggle room, we MUST remove our address. We go to > state INIT. > > > 22:41:40.442012 0.0.0.0.68 > 255.255.255.255.67: xid:0x6a13ec33 > > vend-rfc1048 DHCP:DISCOVER HN:"sarah" CID:1.220.159.219.40.20.191 > > PR:SM+DG+NS+HN+DN+BR+119+121 [tos 0x10] > > dhcpleased, broadcast: could I please have a lease? go to state SELECTING > > > 22:41:41.532272 0.0.0.0.68 > 255.255.255.255.67: xid:0x6a13ec33 > > vend-rfc1048 DHCP:DISCOVER HN:"sarah" CID:1.220.159.219.40.20.191 > > PR:SM+DG+NS+HN+DN+BR+119+121 [tos 0x10] > > dhcpleased, broadcast: could I please have a lease? pretty please? with > sugar on top? stay in state SELECTING > > > 22:41:41.653804 202.63.66.1.67 > 255.255.255.255.68: xid:0x6a13ec33 > > flags:0x8000 Y:202.63.67.36 S:172.21.116.42 ether dc:9f:db:28:14:bf > > vend-rfc1048 DHCP:OFFER SM:255.255.254.0 DG:202.63.66.1 > > NS:119.40.106.35,119.40.106.36 NTP:125.253.59.254 LT:600 SID:202.63.66.1 > > CID:1.220.159.219.40.20.191 [tos 0xc0] > > server: ok fine, do you like this one? > > > 22:41:41.658881 0.0.0.0.68 > 255.255.255.255.67: xid:0xdafa3da4 > > vend-rfc1048 DHCP:REQUEST HN:"sarah" CID:1.220.159.219.40.20.191 > > PR:SM+DG+NS+HN+DN+BR+119+121 RQ:202.63.67.36 SID:202.63.66.1 [tos 0x10] > > dhcpleased: looks, good, is it ok if I use this one? go to state REQUESTING > > > 22:41:42.414218 202.63.66.1.67 > 255.255.255.255.68: xid:0xdafa3da4 > > flags:0x8000 Y:202.63.67.36 S:172.21.116.42 ether dc:9f:db:28:14:bf > > vend-rfc1048 DHCP:ACK SM:255.255.254.0 DG:202.63.66.1 > > NS:119.40.106.35,119.40.106.36 NTP:125.253.59.254 LT:600 SID:202.63.66.1 > > CID:1.220.159.219.40.20.191 [tos 0xc0] > > dhcp server: yes, that's fine. > dhcpleased: configure address, go to state BOUND. > > This process repeats every 5 minutes. > > To me it looks like the server just NACKS all unicast requests. As far > as I remember our broadcast DHCPREQUESTs are exactly the same as our > unicast DHCPREQUESTs, so it's not the contents of the packet. > > You were saying this works with other implementations? I would be > interested in seeing a tcpdump for those. > > > 22:46:42.512451 202.63.67.36.63976 > 202.63.66.1.67: (request) > > xid:0x953f83f1 C:202.63.67.36 vend-rfc1048 DHCP:REQUEST HN:"sarah" > > CID:1.220.159.219.40.20.191 PR:SM+DG+NS+HN+DN+BR+119+121 > > 22:46:42.525222 202.63.66.1.67 > 202.63.67.36.68: xid:0x953f83f1 > > C:202.63.67.36 S:172.21.116.42 vend-rfc1048 DHCP:NACK SID:202.63.66.1 > > CID:1.220.159.219.40.20.191 [tos 0xc0] > > 22:46:42.531574 0.0.0.0.68 > 255.255.255.255.67: xid:0x66009a6e > > vend-rfc1048 DHCP:DISCOVER HN:"sarah" CID:1.220.159.219.40.20.191 > > PR:SM+DG+NS+HN+DN+BR+119+121 [tos 0x10] > > 22:46:43.622162 0.0.0.0.68 > 255.255.255.255.67: xid:0x66009a6e > > vend-rfc1048 DHCP:DISCOVER HN:"sarah" CID:1.220.159.219.40.20.191 > > PR:SM+DG+NS+HN+DN+BR+119+121 [tos 0x10] > > 22:46:43.762685 202.63.66.1.67 > 255.255.255.255.68: xid:0x66009a6e > > flags:0x8000 Y:202.63.67.36 S:172.21.116.42 ether dc:9f:db:28:14:bf > > vend-rfc1048 DHCP:OFFER SM:255.255.254.0 DG:202.63.66.1 > > NS:119.40.106.35,119.40.106.36 NTP:125.253.59.254 LT:600 > > SID:202.63.66.1 CID:1.220.159.219.40.20.191 [tos 0xc0] > > 22:46:43.768051 0.0.0.0.68 > 255.255.255.255.67: xid:0xfe3d764f > > vend-rfc1048 DHCP:REQUEST HN:"sarah" CID:1.220.159.219.40.20.191 > > PR:SM+DG+NS+HN+DN+BR+119+121 RQ:202.63.67.36 SID:202.63.66.1 [tos > > 0x10] > > 22:46:44.526556 202.63.66.1.67 > 255.255.255.255.68: xid:0xfe3d764f > > flags:0x8000 Y:202.63.67.36 S:172.21.116.42 ether dc:9f:db:28:14:bf > > vend-rfc1048 DHCP:ACK SM:255.255.254.0 DG:202.63.66.1 > > NS:119.40.106.35,119.40.106.36 NTP:125.253.59.254 LT:600 > > SID:202.63.66.1 CID:1.220.159.219.40.20.191 [tos 0xc0] > > > > state_transition[cnmac2] Down -> Rebooting, timo: 1 > > DHCPREQUEST on cnmac2 > > parse_dhcp, from: 0e:a2:00:04:00:03, to: ff:ff:ff:ff:ff:ff > > parse_dhcp: 202.63.66.1:67 -> 255.255.255.255:68 > > dhcp_hdr op: Boot Reply (2) > > dhcp_hdr htype: Ethernet (1) > > dhcp_hdr hlen: 6 > > dhcp_hdr hops: 0 > > dhcp_hdr xid: 0x74253f08 > > dhcp_hdr secs: 0 > > dhcp_hdr flags: 0x8000 > > dhcp_hdr ciaddr: 0.0.0.0 > > dhcp_hdr yiaddr: 202.63.67.36 > > dhcp_hdr siaddr: 172.21.116.42 > > dhcp_hdr giaddr: 0.0.0.0 > > dhcp_hdr chaddr: dc:9f:db:28:14:bf (00000000000000000000) > > DHO_DHCP_MESSAGE_TYPE: DHCPACK > > DHO_SUBNET_MASK: 255.255.254.0 > > DHO_ROUTER: 202.63.66.1 > > DHO_DOMAIN_NAME_SERVERS: 119.40.106.35 (1/2) > > DHO_DOMAIN_NAME_SERVERS: 119.40.106.36 (2/2) > > DHO_42, len: 4 > > DHO_DHCP_LEASE_TIME 600s > > DHO_DHCP_SERVER_IDENTIFIER: 202.63.66.1 > > DHO_END > > DHCPACK on cnmac2 from 0e:a2:00:04:00:03/202.63.66.1 to > > ff:ff:ff:ff:ff:ff/255.255.255.255 > > adding 202.63.67.36 to cnmac2 (lease from 202.63.66.1) > > adding nameservers 119.40.106.35 119.40.106.36 (lease from 202.63.66.1 on > > cnmac2) > > state_transition[cnmac2] Rebooting -> Bound, timo: 300 > > configure_interface cnmac2 > > iface_timeout[3]: Bound > > state_transition[cnmac2] Bound -> Renewing, timo: 112 > > DHCPREQUEST on cnmac2 > > parse_dhcp, from: 0e:a2:00:04:00:03, to: dc:9f:db:28:14:bf > > parse_dhcp: 202.63.66.1:67 -> 202.63.67.36:68 > > dhcp_hdr op: Boot Reply (2) > > dhcp_hdr htype: Ethernet (1) > > dhcp_hdr hlen: 6 > > dhcp_hdr hops: 0 > > dhcp_hdr xid: 0xa180ce6b > > dhcp_hdr secs: 0 > > dhcp_hdr flags: 0x0 > > dhcp_hdr ciaddr: 202.63.67.36 > > dhcp_hdr yiaddr: 0.0.0.0 > > dhcp_hdr siaddr: 172.21.116.42 > > dhcp_hdr giaddr: 0.0.0.0 > > dhcp_hdr chaddr: dc:9f:db:28:14:bf (00000000000000000000) > > DHO_DHCP_MESSAGE_TYPE: DHCPNAK > > DHO_DHCP_SERVER_IDENTIFIER: 202.63.66.1 > > DHO_END > > DHCPNAK on cnmac2 from 0e:a2:00:04:00:03/202.63.66.1 to > > dc:9f:db:28:14:bf/202.63.67.36 > > deleting nameservers 119.40.106.35 119.40.106.36 (lease from 202.63.66.1 on > > cnmac2) > > deleting 202.63.67.36 from cnmac2 (lease from 202.63.66.1) > > state_transition[cnmac2] Renewing -> Init, timo: 1 > > DHCPDISCOVER on cnmac2 > > deconfigure_interface cnmac2 > > iface_timeout[3]: Init > > state_transition[cnmac2] Init -> Init, timo: 2 > > DHCPDISCOVER on cnmac2 > > parse_dhcp, from: 0e:a2:00:04:00:03, to: ff:ff:ff:ff:ff:ff > > parse_dhcp: 202.63.66.1:67 -> 255.255.255.255:68 > > dhcp_hdr op: Boot Reply (2) > > dhcp_hdr htype: Ethernet (1) > > dhcp_hdr hlen: 6 > > dhcp_hdr hops: 0 > > dhcp_hdr xid: 0x6a13ec33 > > dhcp_hdr secs: 0 > > dhcp_hdr flags: 0x8000 > > dhcp_hdr ciaddr: 0.0.0.0 > > dhcp_hdr yiaddr: 202.63.67.36 > > dhcp_hdr siaddr: 172.21.116.42 > > dhcp_hdr giaddr: 0.0.0.0 > > dhcp_hdr chaddr: dc:9f:db:28:14:bf (00000000000000000000) > > DHO_DHCP_MESSAGE_TYPE: DHCPOFFER > > DHO_SUBNET_MASK: 255.255.254.0 > > DHO_ROUTER: 202.63.66.1 > > DHO_DOMAIN_NAME_SERVERS: 119.40.106.35 (1/2) > > DHO_DOMAIN_NAME_SERVERS: 119.40.106.36 (2/2) > > DHO_42, len: 4 > > DHO_DHCP_LEASE_TIME 600s > > DHO_DHCP_SERVER_IDENTIFIER: 202.63.66.1 > > DHO_END > > DHCPOFFER on cnmac2 from 0e:a2:00:04:00:03/202.63.66.1 to > > ff:ff:ff:ff:ff:ff/255.255.255.255 > > state_transition[cnmac2] Init -> Requesting, timo: 1 > > DHCPREQUEST on cnmac2 > > parse_dhcp, from: 0e:a2:00:04:00:03, to: ff:ff:ff:ff:ff:ff > > parse_dhcp: 202.63.66.1:67 -> 255.255.255.255:68 > > dhcp_hdr op: Boot Reply (2) > > dhcp_hdr htype: Ethernet (1) > > dhcp_hdr hlen: 6 > > dhcp_hdr hops: 0 > > dhcp_hdr xid: 0xdafa3da4 > > dhcp_hdr secs: 0 > > dhcp_hdr flags: 0x8000 > > dhcp_hdr ciaddr: 0.0.0.0 > > dhcp_hdr yiaddr: 202.63.67.36 > > dhcp_hdr siaddr: 172.21.116.42 > > dhcp_hdr giaddr: 0.0.0.0 > > dhcp_hdr chaddr: dc:9f:db:28:14:bf (00000000000000000000) > > DHO_DHCP_MESSAGE_TYPE: DHCPACK > > DHO_SUBNET_MASK: 255.255.254.0 > > DHO_ROUTER: 202.63.66.1 > > DHO_DOMAIN_NAME_SERVERS: 119.40.106.35 (1/2) > > DHO_DOMAIN_NAME_SERVERS: 119.40.106.36 (2/2) > > DHO_42, len: 4 > > DHO_DHCP_LEASE_TIME 600s > > DHO_DHCP_SERVER_IDENTIFIER: 202.63.66.1 > > DHO_END > > DHCPACK on cnmac2 from 0e:a2:00:04:00:03/202.63.66.1 to > > ff:ff:ff:ff:ff:ff/255.255.255.255 > > adding 202.63.67.36 to cnmac2 (lease from 202.63.66.1) > > adding nameservers 119.40.106.35 119.40.106.36 (lease from 202.63.66.1 on > > cnmac2) > > state_transition[cnmac2] Requesting -> Bound, timo: 300 > > configure_interface cnmac2 > > iface_timeout[3]: Bound > > state_transition[cnmac2] Bound -> Renewing, timo: 112 > > DHCPREQUEST on cnmac2 > > parse_dhcp, from: 0e:a2:00:04:00:03, to: dc:9f:db:28:14:bf > > parse_dhcp: 202.63.66.1:67 -> 202.63.67.36:68 > > dhcp_hdr op: Boot Reply (2) > > dhcp_hdr htype: Ethernet (1) > > dhcp_hdr hlen: 6 > > dhcp_hdr hops: 0 > > dhcp_hdr xid: 0x953f83f1 > > dhcp_hdr secs: 0 > > dhcp_hdr flags: 0x0 > > dhcp_hdr ciaddr: 202.63.67.36 > > dhcp_hdr yiaddr: 0.0.0.0 > > dhcp_hdr siaddr: 172.21.116.42 > > dhcp_hdr giaddr: 0.0.0.0 > > dhcp_hdr chaddr: dc:9f:db:28:14:bf (00000000000000000000) > > DHO_DHCP_MESSAGE_TYPE: DHCPNAK > > DHO_DHCP_SERVER_IDENTIFIER: 202.63.66.1 > > DHO_END > > DHCPNAK on cnmac2 from 0e:a2:00:04:00:03/202.63.66.1 to > > dc:9f:db:28:14:bf/202.63.67.36 > > deleting nameservers 119.40.106.35 119.40.106.36 (lease from 202.63.66.1 on > > cnmac2) > > deleting 202.63.67.36 from cnmac2 (lease from 202.63.66.1) > > state_transition[cnmac2] Renewing -> Init, timo: 1 > > DHCPDISCOVER on cnmac2 > > deconfigure_interface cnmac2 > > iface_timeout[3]: Init > > state_transition[cnmac2] Init -> Init, timo: 2 > > DHCPDISCOVER on cnmac2 > > parse_dhcp, from: 0e:a2:00:04:00:03, to: ff:ff:ff:ff:ff:ff > > parse_dhcp: 202.63.66.1:67 -> 255.255.255.255:68 > > dhcp_hdr op: Boot Reply (2) > > dhcp_hdr htype: Ethernet (1) > > dhcp_hdr hlen: 6 > > dhcp_hdr hops: 0 > > dhcp_hdr xid: 0x66009a6e > > dhcp_hdr secs: 0 > > dhcp_hdr flags: 0x8000 > > dhcp_hdr ciaddr: 0.0.0.0 > > dhcp_hdr yiaddr: 202.63.67.36 > > dhcp_hdr siaddr: 172.21.116.42 > > dhcp_hdr giaddr: 0.0.0.0 > > dhcp_hdr chaddr: dc:9f:db:28:14:bf (00000000000000000000) > > DHO_DHCP_MESSAGE_TYPE: DHCPOFFER > > DHO_SUBNET_MASK: 255.255.254.0 > > DHO_ROUTER: 202.63.66.1 > > DHO_DOMAIN_NAME_SERVERS: 119.40.106.35 (1/2) > > DHO_DOMAIN_NAME_SERVERS: 119.40.106.36 (2/2) > > DHO_42, len: 4 > > DHO_DHCP_LEASE_TIME 600s > > DHO_DHCP_SERVER_IDENTIFIER: 202.63.66.1 > > DHO_END > > DHCPOFFER on cnmac2 from 0e:a2:00:04:00:03/202.63.66.1 to > > ff:ff:ff:ff:ff:ff/255.255.255.255 > > state_transition[cnmac2] Init -> Requesting, timo: 1 > > DHCPREQUEST on cnmac2 > > parse_dhcp, from: 0e:a2:00:04:00:03, to: ff:ff:ff:ff:ff:ff > > parse_dhcp: 202.63.66.1:67 -> 255.255.255.255:68 > > dhcp_hdr op: Boot Reply (2) > > dhcp_hdr htype: Ethernet (1) > > dhcp_hdr hlen: 6 > > dhcp_hdr hops: 0 > > dhcp_hdr xid: 0xfe3d764f > > dhcp_hdr secs: 0 > > dhcp_hdr flags: 0x8000 > > dhcp_hdr ciaddr: 0.0.0.0 > > dhcp_hdr yiaddr: 202.63.67.36 > > dhcp_hdr siaddr: 172.21.116.42 > > dhcp_hdr giaddr: 0.0.0.0 > > dhcp_hdr chaddr: dc:9f:db:28:14:bf (00000000000000000000) > > DHO_DHCP_MESSAGE_TYPE: DHCPACK > > DHO_SUBNET_MASK: 255.255.254.0 > > DHO_ROUTER: 202.63.66.1 > > DHO_DOMAIN_NAME_SERVERS: 119.40.106.35 (1/2) > > DHO_DOMAIN_NAME_SERVERS: 119.40.106.36 (2/2) > > DHO_42, len: 4 > > DHO_DHCP_LEASE_TIME 600s > > DHO_DHCP_SERVER_IDENTIFIER: 202.63.66.1 > > DHO_END > > DHCPACK on cnmac2 from 0e:a2:00:04:00:03/202.63.66.1 to > > ff:ff:ff:ff:ff:ff/255.255.255.255 > > adding 202.63.67.36 to cnmac2 (lease from 202.63.66.1) > > adding nameservers 119.40.106.35 119.40.106.36 (lease from 202.63.66.1 on > > cnmac2) > > state_transition[cnmac2] Requesting -> Bound, timo: 300 > > configure_interface cnmac2 > > > > -- > In my defence, I have been left unsupervised. >