Skip to content

dhcpcd Does Not Send an ARP Probe to Detect Duplicate Address by Default #488

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
shuangye opened this issue Mar 14, 2025 · 4 comments
Open

Comments

@shuangye
Copy link

I use dhcpcd with the default /etc/dhcpcd.conf, and enabled "hostname" option, no other changes.

root@localhost:~# ip a show eth0.168
3: eth0.168@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ba:cd:d7:65:ae:14 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::b8cd:d7ff:fe65:ae14/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
root@localhost:~# dhcpcd -T eth0.168
dhcpcd-10.0.5 starting
duid_get: cannot write duid: Read-only file system
DUID 00:03:00:01:ba:cd:d7:65:ae:14
eth0.168: IAID ff:00:00:a8
eth0.168: soliciting an IPv6 router
eth0.168: soliciting a DHCP lease
eth0.168: offered 192.168.31.151 from 192.168.31.1
interface=eth0.168
pid=1892
protocol=dhcp
reason=TEST
ifcarrier=up
ifflags=69699
ifmetric=1003
ifmtu=1500
ifwireless=0
new_broadcast_address=192.168.31.255
new_dhcp_lease_time=43200
new_dhcp_message_type=2
new_dhcp_rebinding_time=37800
new_dhcp_renewal_time=21600
new_dhcp_server_identifier=192.168.31.1
new_domain_name_servers=192.168.31.1
new_host_name=MiWiFi-R3G-srv
new_ip_address=192.168.31.151
new_network_number=192.168.31.0
new_routers=192.168.31.1
new_subnet_cidr=24
new_subnet_mask=255.255.255.0
new_vendor_encapsulated_options=6d69776966692d5233472d322e32382e32342d313031
dhcpcd exited
root@localhost:~# uname -a
Linux localhost 6.1.75-dirty #111 SMP Thu Mar 13 10:25:09 CST 2025 aarch64 GNU/Linux

In another terminal, I run tcpdump -v -i eth0.168 and found that no arp probe was sent.

Is there an option to enable DAD?

@shuangye
Copy link
Author

Just noticed that sometimes it sends the probe:

root@localhost:~# dhcpcd  eth0.168
dhcpcd-10.0.5 starting
duid_get: cannot write duid: Read-only file system
DUID 00:03:00:01:ba:cd:d7:65:ae:14
eth0.168: IAID ff:00:00:a8
eth0.168: soliciting an IPv6 router
eth0.168: soliciting a DHCP lease
eth0.168: offered 192.168.31.151 from 192.168.31.1
eth0.168: probing address 192.168.31.151/24
eth0.168: leased 192.168.31.151 for 43200 seconds
dhcp_writefile: /var/db/dhcpcd/eth0.168.lease: Read-only file system
eth0.168: adding route to 192.168.31.0/24
eth0.168: adding default route via 192.168.31.1

Sometimes not:

root@localhost:~# dhcpcd  eth0.168
dhcpcd-10.0.5 starting
duid_get: cannot write duid: Read-only file system
DUID 00:03:00:01:ba:cd:d7:65:ae:14
eth0.168: IAID ff:00:00:a8
eth0.168: soliciting a DHCP lease
eth0.168: offered 192.168.31.151 from 192.168.31.1
eth0.168: leased 192.168.31.151 for 43200 seconds
dhcp_writefile: /var/db/dhcpcd/eth0.168.lease: Read-only file system
eth0.168: adding route to 192.168.31.0/24
eth0.168: adding default route via 192.168.31.1

@shuangye
Copy link
Author

shuangye commented Mar 14, 2025

After studying dhcpcd code, seems if the interface already has an IP address before the DHCP offer, dhcpcd will skip probing.

The problem is that, even I use the following commands to remove all IP addresses from the interface:

root@localhost:~# ip a flush dev eth0.168
root@localhost:~# ip a show dev eth0.168
3: eth0.168@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ba:cd:d7:65:ae:14 brd ff:ff:ff:ff:ff:ff

dhcpcd still gets an IP address from eth0.168. Code:

// src/dhcp.c
static int
dhcp_arp_address(struct interface *ifp)
{
		// ia is not NULL here. I printed ia->addr.s_addr, it is still the previous IP address before it was removed
		if (ia == NULL) {
			state->state = DHS_PROBE;
			get_lease(ifp, &l, state->offer, state->offer_len);
			logerr("%s: probing address %s/%d",
			    ifp->name, inet_ntoa(l.addr), inet_ntocidr(l.mask));
			/* We need to handle DAD. */
			arp_probe(astate);
			return 0;
		}
}

As a workaround, I have to use these commands:

ip a flush dev eth0.168
ip a show dev eth0.168
ip link set dev eth0.168 down
ip link set dev eth0.168 up
killall -9 dhcpcd
dhcpcd eth0.168

@rsmarples
Copy link
Member

You are correct, dhcpcd will only perform the initial ARP probe if the address does not exist on the interface.
Once dhcpcd is running, it will listen to ARP and Defend it's address if someone else wants to claim it via ARP.

I suppose the question becomes what value do you think you gain from ARP probing an address which exists on your interface already?

@shuangye
Copy link
Author

I think skipping ARP probing is reasonable when the interface already has an IP address. But since I have removed all IP addresses with ip a flush dev eth0.168, dhcpcd should perform the probe. It does not because it uses a stale IP address here

dhcpcd/src/dhcp.c

Line 2641 in e8b2c8f

if (ia == NULL) {

BTW, if DHCP server offers a different IP adress as the existing one, I think dhcpcd should perform the probe too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants