dhcp (dhclient): honor ipv4.dhcp-client-id=none

If the client-id has been set to "none", the DHCP client-id option
(option 61) mustn't be sent. Honor this when the dhclient plugin is
used.

If dhclient has been called with the -i option (Use  a DUID with DHCPv4
clients), it will send a Client-ID even without setting one in dhclient.conf.
In this case, this option needs to be explicitly overwritten with:
  send dhcp-client-identifier = "";

At least in RHEL 8, dhclient is launched with `-i` turned on by default.
This commit is contained in:
Íñigo Huguet 2023-09-27 15:49:41 +02:00
parent 12f694902d
commit 8639a3e5f7
4 changed files with 108 additions and 7 deletions

View file

@ -120,7 +120,10 @@ add_ip4_config(GString *str,
}
g_string_append(str, CLIENTID_TAG " ");
if (i < l) {
if (l == 0) {
/* An empty value effectively unsets the client-id to avoid sending it */
g_string_append(str, "\"\"");
} else if (i < l) {
/* Unprintable; convert to a hex string */
for (i = 0; i < l; i++) {
if (i > 0)
@ -293,6 +296,7 @@ char *
nm_dhcp_dhclient_create_config(const char *interface,
int addr_family,
GBytes *client_id,
gboolean send_client_id,
const char *anycast_address,
const char *hostname,
guint32 timeout,
@ -391,8 +395,8 @@ nm_dhcp_dhclient_create_config(const char *interface,
continue;
if (NM_STR_HAS_PREFIX(p, CLIENTID_TAG)) {
/* Override config file "dhcp-client-id" and use one from the connection */
if (client_id)
/* Skip "dhcp-client-id" if the connection has defined a custom one or "none" */
if (client_id || !send_client_id)
continue;
/* Otherwise, capture and return the existing client id */
@ -477,6 +481,8 @@ nm_dhcp_dhclient_create_config(const char *interface,
}
if (addr_family == AF_INET) {
nm_auto_unref_bytes GBytes *client_id_none = NULL;
client_id = send_client_id ? client_id : (client_id_none = g_bytes_new_static("", 0));
add_ip4_config(new_contents, client_id, hostname, use_fqdn, hostname_flags);
add_request(reqs, "rfc3442-classless-static-routes");
add_request(reqs, "ms-classless-static-routes");

View file

@ -12,6 +12,7 @@
char *nm_dhcp_dhclient_create_config(const char *interface,
int addr_family,
GBytes *client_id,
gboolean send_client_id,
const char *anycast_addr,
const char *hostname,
guint32 timeout,

View file

@ -233,6 +233,7 @@ create_dhclient_config(NMDhcpDhclient *self,
const char *iface,
const char *uuid,
GBytes *client_id,
gboolean send_client_id,
const char *anycast_address,
const char *hostname,
guint32 timeout,
@ -271,6 +272,7 @@ create_dhclient_config(NMDhcpDhclient *self,
new_content = nm_dhcp_dhclient_create_config(iface,
addr_family,
client_id,
send_client_id,
anycast_address,
hostname,
timeout,
@ -515,6 +517,7 @@ ip4_start(NMDhcpClient *client, GError **error)
client_config->iface,
client_config->uuid,
client_config->client_id,
client_config->v4.send_client_id,
client_config->anycast_address,
client_config->hostname,
client_config->timeout,
@ -557,6 +560,7 @@ ip6_start(NMDhcpClient *client, const struct in6_addr *ll_addr, GError **error)
config->iface,
config->uuid,
NULL,
TRUE,
config->anycast_address,
config->hostname,
config->timeout,

View file

@ -36,11 +36,14 @@ test_config(const char *orig,
const char *anycast_addr,
const char *mud_url)
{
gs_free char *new = NULL;
gs_unref_bytes GBytes *client_id = NULL;
gs_unref_bytes GBytes *new_client_id = NULL;
gs_free char *new = NULL;
gs_unref_bytes GBytes *client_id = NULL;
gs_unref_bytes GBytes *new_client_id = NULL;
gboolean send_client_id = TRUE;
if (dhcp_client_id) {
if (nm_streq0(dhcp_client_id, "none")) {
send_client_id = FALSE;
} else if (dhcp_client_id) {
client_id = nm_dhcp_utils_client_id_string_to_bytes(dhcp_client_id);
g_assert(client_id);
}
@ -48,6 +51,7 @@ test_config(const char *orig,
new = nm_dhcp_dhclient_create_config(iface,
addr_family,
client_id,
send_client_id,
anycast_addr,
hostname,
timeout,
@ -502,6 +506,90 @@ test_existing_ascii_client_id(void)
NULL,
NULL);
}
/*****************************************************************************/
static const char *none_client_id_orig = "send dhcp-client-identifier 10:30:04:20:7A:08;\n";
static const char *none_client_id_expected =
"# Created by NetworkManager\n"
"# Merged from /path/to/dhclient.conf\n"
"\n"
"send dhcp-client-identifier \"\"; # added by NetworkManager\n"
"\n"
"option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n"
"option ms-classless-static-routes code 249 = array of unsigned integer 8;\n"
"option wpad code 252 = string;\n"
"\n"
"also request rfc3442-classless-static-routes;\n"
"also request ms-classless-static-routes;\n"
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
"also request root-path;\n"
"\n";
static void
test_none_client_id(void)
{
const char *connection_client_id = "none";
gs_unref_bytes GBytes *expected_client_id = NULL;
test_config(none_client_id_orig,
none_client_id_expected,
AF_INET,
NULL,
0,
FALSE,
NM_DHCP_HOSTNAME_FLAG_NONE,
connection_client_id,
expected_client_id,
"eth0",
NULL,
NULL);
}
/*****************************************************************************/
static const char *missing_client_id_orig = "";
static const char *missing_client_id_expected =
"# Created by NetworkManager\n"
"# Merged from /path/to/dhclient.conf\n"
"\n"
"\n"
"option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n"
"option ms-classless-static-routes code 249 = array of unsigned integer 8;\n"
"option wpad code 252 = string;\n"
"\n"
"also request rfc3442-classless-static-routes;\n"
"also request ms-classless-static-routes;\n"
"also request static-routes;\n"
"also request wpad;\n"
"also request ntp-servers;\n"
"also request root-path;\n"
"\n";
static void
test_missing_client_id(void)
{
const char *connection_client_id = NULL;
gs_unref_bytes GBytes *expected_client_id = NULL;
test_config(missing_client_id_orig,
missing_client_id_expected,
AF_INET,
NULL,
0,
FALSE,
NM_DHCP_HOSTNAME_FLAG_NONE,
connection_client_id,
expected_client_id,
"eth0",
NULL,
NULL);
}
/*****************************************************************************/
static const char *fqdn_expected =
@ -1364,6 +1452,8 @@ main(int argc, char **argv)
g_test_add_func("/dhcp/dhclient/existing-hex-client-id", test_existing_hex_client_id);
g_test_add_func("/dhcp/dhclient/existing-client-id", test_existing_escaped_client_id);
g_test_add_func("/dhcp/dhclient/existing-ascii-client-id", test_existing_ascii_client_id);
g_test_add_func("/dhcp/dhclient/none-client-id", test_none_client_id);
g_test_add_func("/dhcp/dhclient/missing-client-id", test_missing_client_id);
g_test_add_func("/dhcp/dhclient/fqdn", test_fqdn);
g_test_add_func("/dhcp/dhclient/fqdn_options_override", test_fqdn_options_override);
g_test_add_func("/dhcp/dhclient/override_hostname", test_override_hostname);