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.
> 

Reply via email to