dhclient runs out of all available addresses in the pool in case of abnormal script termination
Preface
Some Linux distribution, eg. CentOS Linux 7.x or 8.x, use NetworkManager to configure network interfaces. The dhclient command started by NetworkManager looks like this:
/sbin/dhclient -d -q -sf /usr/libexec/nm-dhcp-helper \
-pf /run/NetworkManager/dhclient-<iface_name>.pid \
-lf /var/lib/NetworkManager/dhclient-<connection_uuid>-<iface_name>.lease \
-cf /var/lib/NetworkManager/dhclient-<iface_name>.conf <iface_name>
When dhclient receive answer from server on lease renewal it use script or binary specified by -sf
option for IP validity checking.
/* If the BOUND/RENEW code detects another machine using the
offered address, it exits nonzero. We need to send a
DHCPDECLINE and toss the lease. */
if (script_go(client)) {
make_decline(client, client->new);
send_decline(client);
destroy_client_lease(client->new);
But the script_go
function return non-zero result in the 2 cases:
- Launched process exit status is non-zero. In this case
script_go
function return value > 0. - Launched process terminated by signal, eg. SIGTEM. In this case
script_go
function return value < 0.
Problem description
Let's imagine the next situation. nm-dhcp-helper
or other script or binary specified by -sf
option starting at some time will always terminates by SIGSEGV due to filesystem damage or some dynamic library incompatibility. In this case the dhclient will send DECLINE and retry lease renewal after 10 seconds timeout. This will repeat infinitely until all available addresses in the DHCP pool will be marked as invalid and other clients will not be able to lease an IP address.
Solution
To eliminate the possibility of a repetition of such a situation, it is enough in the above code fragment to replace a line
if (script_go(client)) {
by
if (script_go(client) > 0) {