In Debian-based Linux there are two popular Dynamic Host Configuration Protocol (DHCP) clients: dynamic host client, also known as dhclient, and DHCP client daemon, also known as dhcpcd. As a reminder, a DHCP client is a system process that obtains an IP address, DNS server, and potentially additional parameters for the Linux host in order to be able to connect and operate on a network. It obtains all of the above information from a DHCP server which runs on another host within the network.
Both dhclient and dhcpcd give the option to execute arbitrary code and scripts when specific events occur. The mechanism that aids this process is called ‘hooks’. In this post, we will cover which specific, conventions you need to follow to make this work.
DHCLIENT Hooks
dhclient is the older of the two, and is actually getting deprecated. Newer Linux distributions are migrating to dhcpcd. However, it’s been the main DHCP client for at least two decades, and it’s going to be a while until it disappears completely. I still use it in certain cases.
The dhclieht hooks work in two directories:
- /etc/dhcp/dhclient-enter-hooks.d
- /etc/dhcp/dhclient-exit-hook.d
Any executable script present in the first ‘enter directory’ is executed prior to any dhclient processing. Any script in the ‘exit directory’ is executed after dhclient has finished.
DHCPCD Hooks
dhcpcd is a bit different because it uses two files instead of directories to execute user-defined scripts:
- /etc/dhcpcd.enter-hook
- /etc/dhcpcd.exit-hook
The actual script that you want to execute has to be in this file. I found it a bit less flexible than the dhclient mechanism that you can throw multiple scripts in a directory. However, if you have multiple scripts you want to execute, you can easily save them as individual scripts on your system and call them from /etc/dhcpcd.enter-hook or /etc/dhcpcd.exit-hook.
Variables
When a script is called by dhclient or dhcpcd, it has certain environment variables that are set by the hook mechanism. These variables hold values that have to do with how the network host is configured. To a certain extent the variable names are the same between dhclient and dhcpcd. This is very convenient if you are migrating from dhclient to dhcpcd or transferring scripts from one to the other. You might be able to use the same scripts without modifications – but always be sure to verify before you make the switch.
I could give you a list of all the variables for dhclient and dhcpcd, but it’s better to be able to extract each one of them dynamically. The following script can do this for you:
echo “================” >> /tmp/variables.txt echo "Environment Variables" >> /tmp/variables.txt printenv >> /tmp/variables.txt echo “===============” >> /tmp/variables.txt echo "Shell Variables" >> /tmp/variables.txt set >> /tmp/variables.txt
For dhclient create an executable script in /etc/dhcp/dhclient-enter-hooks.d or /etc/dhcp/dhclient-exit-hook.d and bounce the interface with if down eth0; ifup eth0.
For dhcpcd, copy the code above in any of the files /etc/dhcpcd.enter-hook or /etc/dhcpcd.exit-hook and bounce the interface with ip link set dev eth0 down; ip link set dev up.
Once you do that, examine the contents of the file /tmp/variables.txt and you will see a long list of variables with their values. You will understand what you can use and what values they take.
For example, there are variable such as $interface which holds the interface that DHCP did the inquiry for, $old_ip_address, $new_ip_address etc.
One important variable is $reason that holds the reason the event happened. It can take values such as BOUND (a new lease was obtained), RENEW (a lease was renewed), etc. You can find a full list of the reasons online for dhclient and dhcpcd.
DHCP Hooks Example
As an example, we will add a DNS server in /etc/resolv.conf when a new IP address is obtained. The same script works for both dhclient and dhcpcd without any modifications because the variables used ($interface and $reason) are the same in both and the values they take are also the same.
#!/bin/bash if [ “${interface}” = “eth0” ]; then case “${reason}” in BOUND|RENEW|REBIND|REBOOT) echo “nameserver 1.1.1.1” >> /etc/resolv.conf ;; esac fi
For dhclient, you have to create a new executable file and save it in /etc/dhcp/dhclient-exit-hook.d. For dhcpcd you can put the script in /etc/dhcpcd.exit-hook.
Each time interface eth0 get a new IP, apart from the DNS servers provided by the DHCP server, 1.1.1.1 will be added at the end.
You can use the hooks mechanism to do anything you can imagine around the manipulation of interfaces, routing rules, DNS servers, etc. It’s a very flexible set up, and the hook mechanism is used in other aspects of a Linux system.