all: drop remaining references to dhclient

This commit is contained in:
Jan Vaclav 2026-06-09 12:07:07 +02:00
parent 40c16b2627
commit 8b0da1a646
11 changed files with 22 additions and 94 deletions

View file

@ -54,17 +54,14 @@ complexity out of `NMDevice`.
mean that it gave up. It will keep retrying, it's just that there is little
hope of getting a new lease. This happens, when you try to run DHCP on a Layer3
link (WireGuard). There is little hope to succeed, but `NMDhcpClient`
(theoretically) will retry and may recover from this. Another example is when
we fail to start dhclient because it's not installed. In that case, we are not
optimistic to recover, however `NMDhcpDhclient` will retry (with backoff
timeout) and might still recover from this. For most cases, `NMDevice` will
(theoretically) will retry and may recover from this. For most cases, `NMDevice` will
treat the no-lease cases the same, but in case of "bad" it might give up
earlier.
When a lease expires, that does not necessarily mean that we are now in a bad
state. It might mean that the DHCP server is temporarily down, but we might
recover from that easily. "bad" really means, something is wrong on our side
which prevents us from getting a lease. Also, imagine `dhclient` dies (we would
which prevents us from getting a lease. Also, imagine the DHCP client dies (we would
try to restart, but assume that fails too), but we still have a valid lease,
then possibly `NMDhcpClient` should still pretend all is good and we still have
a lease until it expires. It may be we can recover before that happens. The
@ -88,8 +85,7 @@ optionally does ACD first, then configures the IP address first and calls
different lease). With this, the above state "has a lease" has actually three
flavors: "has a lease but not yet ACD probed" and "has a lease but
accepted/declined" (but `NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED` gets only emitted
when we get the lease, not when we accept/decline it). With `dhclient`, when we
receive a lease, it means "has a lease but accepted" right away.
when we get the lease, not when we accept/decline it).
- for IPv6 prefix delegation, there is also `needed_prefixes` and
`NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED`. Currently `needed_prefixes` needs

View file

@ -266,9 +266,8 @@ nm_dhcp_client_create_options_dict(NMDhcpClient *self, gboolean static_keys)
guint option = IS_IPv4 ? NM_DHCP_OPTION_DHCP4_CLIENT_ID : NM_DHCP_OPTION_DHCP6_CLIENT_ID;
gs_free char *str = nm_dhcp_utils_duid_to_string(effective_client_id);
/* Note that for the nm-dhcp-helper based plugins (dhclient), the plugin
* may send the used client-id/DUID via the environment variables and
* overwrite them yet again. */
/* Note that nm-dhcp-helper based plugins may send the used client-id/DUID
* via the environment variables and overwrite them yet again. */
nm_dhcp_option_take_option(options,
static_keys,
@ -827,8 +826,7 @@ _nm_dhcp_client_notify(NMDhcpClient *self,
if (!IS_IPv4 && l3cd) {
/* nm_dhcp_utils_merge_new_dhcp6_lease() relies on "life_starts" option
* for merging, which is only set by dhclient. Internal client never sets that,
* but it supports multiple IP addresses per lease. */
* for merging. The internal client supports multiple IP addresses per lease. */
if (nm_dhcp_utils_merge_new_dhcp6_lease(priv->l3cd_next, l3cd, &l3cd_merged)) {
_LOGD("lease merged with existing one");
l3cd = nm_l3_config_data_seal(l3cd_merged);
@ -1692,21 +1690,14 @@ maybe_add_option(NMDhcpClient *self, GHashTable *hash, const char *key, GVariant
g_hash_table_insert(hash, g_strdup(key), str_value);
/* dhclient has no special labels for private dhcp options: it uses "unknown_xyz"
* labels for that. We need to identify those to alias them to our "private_xyz"
* format unused in the internal dchp plugins.
*/
/* "unknown_xyz" labels are aliased to our "private_xyz" format. */
if ((priv_opt_num = label_is_unknown_xyz(key)) > 0) {
gs_free guint8 *check_val = NULL;
char *hex_str = NULL;
gsize len;
/* dhclient passes values from dhcp private options in its own "string" format:
* if the raw values are printable as ascii strings, it will pass the string
* representation; if the values are not printable as an ascii string, it will
* pass a string displaying the hex values (hex string). Try to enforce passing
* always an hex string, converting string representation if needed.
*/
/* Private options may arrive as printable ascii strings or as hex strings.
* Normalize to always use hex string format. */
check_val = nm_utils_hexstr2bin_alloc(str_value, FALSE, TRUE, ":", 0, &len);
hex_str = nm_utils_bin2hexstr_full(check_val ?: (guint8 *) str_value,
check_val ? len : strlen(str_value),

View file

@ -53,8 +53,8 @@ typedef enum _nm_packed {
* As such, it's never officially in a non-recoverable state.
* However, there are cases when it really looks like we won't
* be able to get a lease. For example, if the underlying interface
* is layer 3 only, if we have no IPv6 link local address for a prolonged
* time, or if dhclient is not installed.
* is layer 3 only, or if we have no IPv6 link local address for a prolonged
* time.
* But even these cases are potentially recoverable. This is only
* a hint to the user (which they might ignore).
*
@ -311,7 +311,6 @@ typedef struct {
GType nm_dhcp_nettools_get_type(void);
extern const NMDhcpClientFactory _nm_dhcp_client_factory_dhclient;
extern const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcd;
extern const NMDhcpClientFactory _nm_dhcp_client_factory_internal;
extern const NMDhcpClientFactory _nm_dhcp_client_factory_systemd;

View file

@ -205,8 +205,7 @@ do_notify:
if (!NM_IN_STRSET(s_err, "org.freedesktop.DBus.Error.UnknownMethod")) {
/* Some unexpected error. We treat that as a failure. In particular,
* the daemon will fail the request if ACD fails. This causes nm-dhcp-helper
* to fail, which in turn causes dhclient to send a DECLINE. */
* the daemon will fail the request if ACD fails. */
_LOGW("failure to call notify: %s (try signal via Event)", error->message);
success = FALSE;
goto out;

View file

@ -91,11 +91,6 @@ static const NMDhcpClientFactory *
_client_factory_available(const NMDhcpClientFactory *client_factory)
{
if (client_factory) {
if (nm_streq(client_factory->name, "dhclient")) {
_LOGW(AF_UNSPEC,
"attempting to used a deprecated DHCP client '%s' ",
client_factory->name);
}
if (!client_factory->get_path || client_factory->get_path())
return client_factory;
}
@ -110,25 +105,8 @@ _client_factory_get_gtype(const NMDhcpClientFactory *client_factory, int addr_fa
nm_assert(client_factory);
/* currently, the chosen DHCP plugin for IPv4 and IPv6 is configured in NetworkManager.conf
* and cannot be reloaded. It would be nice to configure the plugin per address family
* or to be able to reload it.
*
* Note that certain options in NetworkManager.conf depend on the chosen DHCP plugin.
* See "dhcp-plugin:" in "Device List Format" (`man NetworkManager.conf`).
* Supporting reloading the plugin would also require to re-evalate the decisions from
* the "Device List Format". Likewise, having per-address family plugins would make the
* "main.dhcp" setting and "dhcp-plugin:" match non-sensical because these configurations
* currently are address family independent.
*
* So actually, we don't want that complexity. We want to phase out all plugins in favor
* of the internal plugin.
* However, certain existing plugins are well known to not support an address family.
* In those cases, we should just silently fallback to the internal plugin.
*
* This could be a problem with forward compatibility if we ever intended to add IPv6 support
* to those plugins. But we don't intend to do so. The internal plugin is the way forward and
* not extending other plugins. */
/* If the factory does not support an address family, silently fall back
* to the internal plugin. */
if (NM_IS_IPv4(addr_family))
get_type_fcn = client_factory->get_type_4;
@ -205,30 +183,10 @@ nm_dhcp_manager_start_client(NMDhcpManager *self, NMDhcpClientConfig *config, GE
client = g_object_new(gtype, NM_DHCP_CLIENT_CONFIG, config, NULL);
/* unfortunately, our implementations work differently per address-family regarding client-id/DUID.
/* - for IPv4, the calling code may determine a client-id (from NM's connection profile).
* If present, it is taken. If not present, the default is just "mac".
*
* - for IPv4, the calling code may determine a client-id (from NM's connection profile).
* If present, it is taken. If not present, the DHCP plugin uses a plugin specific default.
* - for "internal" plugin, the default is just "mac".
* - for "dhclient", we try to get the configuration from dhclient's /etc/dhcp or fallback
* to whatever dhclient uses by default.
* We do it this way, because for dhclient the user may configure a default
* outside of NM, and we want to honor that. Worse, dhclient could be a wapper
* script where the wrapper script overwrites the client-id. We need to distinguish
* between: force a particular client-id and leave it unspecified to whatever dhclient
* wants.
*
* - for IPv6, the calling code always determines a client-id. It also specifies @enforce_duid,
* to determine whether the given client-id must be used.
* - for "internal" plugin @enforce_duid doesn't matter and the given client-id is
* always used.
* - for "dhclient", @enforce_duid FALSE means to first try to load the DUID from the
* lease file, and only otherwise fallback to the given client-id.
* - other plugins don't support DHCPv6.
* It's done this way, so that existing dhclient setups don't change behavior on upgrade.
*
* This difference is cumbersome and only exists because of "dhclient" which supports hacking the
* default outside of NetworkManager API.
* - for IPv6, the calling code always determines a client-id.
*/
if (!nm_dhcp_client_start(client, error))

View file

@ -269,7 +269,7 @@ lease_parse_address(NMDhcpNettools *self /* for logging context only */,
char str2[NM_INET_ADDRSTRLEN];
/* Some DHCP servers may not set the subnet-mask (issue#1037).
* Do the same as the dhclient plugin and use a default. */
* Use a default. */
a_plen = nm_ip4_addr_get_default_prefix(a_address.s_addr);
a_netmask = nm_ip4_addr_netmask_from_prefix(a_plen);
_LOGT("missing subnet mask (option 1). Guess %s based on IP address %s",

View file

@ -1,5 +1,5 @@
[main]
dhcp=dhclient
dhcp=internal
plugin=foo,bar,baz
no-auto-default=11:11:11:11:11:11
rc-managed=unmanaged

View file

@ -1,5 +1,5 @@
[main]
dhcp=dhclient
dhcp=internal
plugins=foo,bar,baz
no-auto-default=11:11:11:11:11:11

View file

@ -162,7 +162,7 @@ test_config_simple(void)
g_assert_cmpstr(nm_config_data_get_config_main_file(nm_config_get_data_orig(config)),
==,
TEST_DIR "/NetworkManager.conf");
g_assert_cmpstr(_config_get_dhcp_client_a(config), ==, "dhclient");
g_assert_cmpstr(_config_get_dhcp_client_a(config), ==, "internal");
g_assert_cmpstr(nm_config_get_log_level(config), ==, "INFO");
g_assert_cmpint(nm_config_data_get_connectivity_interval(nm_config_get_data_orig(config)),
==,
@ -297,7 +297,7 @@ test_config_override(void)
g_assert_cmpstr(nm_config_data_get_config_main_file(nm_config_get_data_orig(config)),
==,
TEST_DIR "/NetworkManager.conf");
g_assert_cmpstr(_config_get_dhcp_client_a(config), ==, "dhclient");
g_assert_cmpstr(_config_get_dhcp_client_a(config), ==, "internal");
g_assert_cmpstr(nm_config_get_log_level(config), ==, "INFO");
g_assert_cmpint(nm_config_data_get_connectivity_interval(nm_config_get_data_orig(config)),
==,

View file

@ -1,14 +0,0 @@
[Unit]
Description=dhclient service to get connectivity with the host
After=network.target
[Service]
Type=simple
Restart=on-failure
User=root
RestartSec=5
ExecStart=dhclient -d host_net
ExecStop=dhclient -r host_net
[Install]
WantedBy=multi-user.target

View file

@ -124,7 +124,6 @@ do_build() {
"home-gdb_history:/root/.gdb_history"
"home-behaverc:/root/.behaverc"
"systemd-10-host-net.link:/etc/systemd/network/10-host-net.link"
"systemd-dhcp-host.service:/etc/systemd/system/dhcp-host.service"
"systemd-20-nm.override:/etc/systemd/system/NetworkManager.service.d/20-nm.override"
)