diff --git a/.gitignore b/.gitignore index f793204262..d70517f4d8 100644 --- a/.gitignore +++ b/.gitignore @@ -249,7 +249,6 @@ test-*.trs /src/core/devices/wifi/tests/test-devices-wifi /src/core/devices/wwan/tests/test-service-providers /src/core/dhcp/nm-dhcp-helper -/src/core/dhcp/tests/test-dhcp-dhclient /src/core/dhcp/tests/test-dhcp-options /src/core/dhcp/tests/test-dhcp-utils /src/core/dnsmasq/tests/test-dnsmasq-utils @@ -427,11 +426,9 @@ test-*.trs /src/devices/wifi/tests/test-wifi-ap-utils /src/devices/wwan/tests/test-service-providers /src/dhcp-manager/nm-dhcp-helper -/src/dhcp-manager/tests/test-dhcp-dhclient /src/dhcp-manager/tests/test-dhcp-options /src/dhcp-manager/tests/test-dhcp-utils /src/dhcp/nm-dhcp-helper -/src/dhcp/tests/test-dhcp-dhclient /src/dhcp/tests/test-dhcp-options /src/dhcp/tests/test-dhcp-utils /src/dnsmasq-manager/tests/test-dnsmasq-utils diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d24b6f318f..dae81ef3b1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -61,9 +61,9 @@ variables: # This is done by running `ci-fairy generate-template` and possibly bumping # ".default_tag". ALPINE_TAG: 'tag-9a076a2431b8' - CENTOS_TAG: 'tag-caf6673db1a7' + CENTOS_TAG: 'tag-e1774f6bed52' DEBIAN_TAG: 'tag-e394e8e726e1' - FEDORA_TAG: 'tag-caf6673db1a7' + FEDORA_TAG: 'tag-e1774f6bed52' UBUNTU_TAG: 'tag-e394e8e726e1' ALPINE_EXEC: 'bash .gitlab-ci/alpine-install.sh' diff --git a/NEWS b/NEWS index 2b805b95e0..511d31bb89 100644 --- a/NEWS +++ b/NEWS @@ -71,6 +71,8 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE! secrets when activating a connection, matching the connection editor. * Fix an out-of-bounds read in the internal DHCPv4 client that an on-link attacker could trigger with a malformed UDP packet, crashing NetworkManager. +* Drop support for dhclient as a DHCP backend, which has been deprecated + since NetworkManager-1.50. ============================================= NetworkManager-1.56 diff --git a/config.h.meson b/config.h.meson index e220c3f0c6..6eb4f03f81 100644 --- a/config.h.meson +++ b/config.h.meson @@ -1,9 +1,6 @@ /* Define if building universal (internal helper macro) */ #mesondefine AC_APPLE_UNIVERSAL_BUILD -/* Define to path of dhclient binary */ -#mesondefine DHCLIENT_PATH - /* Define to path of dhcpcd binary */ #mesondefine DHCPCD_PATH @@ -221,9 +218,6 @@ /* Define if you want connectivity checking support */ #mesondefine WITH_CONCHECK -/* Define if you have dhclient */ -#mesondefine WITH_DHCLIENT - /* Define if you have dhcpcd */ #mesondefine WITH_DHCPCD diff --git a/contrib/fedora/REQUIRED_PACKAGES b/contrib/fedora/REQUIRED_PACKAGES index 557c6c73a7..4865020210 100755 --- a/contrib/fedora/REQUIRED_PACKAGES +++ b/contrib/fedora/REQUIRED_PACKAGES @@ -93,7 +93,6 @@ install \ # some packages don't exist in certain distributions. Install them one-by-one, and ignore errors. install_ignore_missing \ black \ - dhclient \ iproute-tc \ libasan \ libpsl-devel \ diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index ba12235ddf..c7521bff33 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -42,11 +42,6 @@ Release: __RELEASE_VERSION__%{?dist} %global systemd_units_cloud_setup nm-cloud-setup.service nm-cloud-setup.timer ############################################################################### -%if 0%{?fedora} > 40 || 0%{?rhel} >= 10 -%bcond_with dhclient -%else -%bcond_without dhclient -%endif %bcond_without adsl %bcond_without bluetooth %bcond_without wwan @@ -585,11 +580,6 @@ Preferably use nmcli instead. -Dnft=%{_sbindir}/nft \ -Diptables=%{_sbindir}/iptables \ -Dip6tables=%{_sbindir}/ip6tables \ -%if %{with dhclient} - -Ddhclient=%{_sbindir}/dhclient \ -%else - -Ddhclient=no \ -%endif -Ddhcpcd=no \ -Dcrypto=gnutls \ %if %{with debug} diff --git a/contrib/fedora/rpm/build_clean.sh b/contrib/fedora/rpm/build_clean.sh index 68599bda3b..4accc0d324 100755 --- a/contrib/fedora/rpm/build_clean.sh +++ b/contrib/fedora/rpm/build_clean.sh @@ -218,7 +218,6 @@ if [[ $NO_DIST != 1 ]]; then -Dlibaudit=yes-disabled-by-default \ -Dpolkit=true \ -Dnm_cloud_setup=true \ - -Ddhclient=/usr/sbin/dhclient \ -Dconfig_dhcp_default=internal \ -Dconfig_dns_rc_manager_default=auto \ -Diptables=/usr/sbin/iptables \ diff --git a/contrib/fedora/rpm/configure-for-system.sh b/contrib/fedora/rpm/configure-for-system.sh index 58daed4ef5..066d7fc90d 100755 --- a/contrib/fedora/rpm/configure-for-system.sh +++ b/contrib/fedora/rpm/configure-for-system.sh @@ -263,11 +263,7 @@ if [ -z "$P_LOGGING_BACKEND_DEFAULT" ] ; then fi if [ -z "$P_DHCP_DEFAULT" ] ; then - if [ "$P_FEDORA" -ge 31 -o "$P_RHEL" -ge 8 ] ; then - P_DHCP_DEFAULT=internal - else - P_DHCP_DEFAULT=dhclient - fi + P_DHCP_DEFAULT=internal fi if [ -z "$P_FIREWALLD_ZONE" ] ; then @@ -377,7 +373,6 @@ meson setup\ -Dnft="${D_SBINDIR}/nft" \ -Diptables="${D_SBINDIR}/iptables" \ -Dip6tables="${D_SBINDIR}/ip6tables" \ - -Ddhclient="${D_SBINDIR}/dhclient" \ -Ddhcpcd=no \ -Dconfig_dhcp_default="$P_DHCP_DEFAULT" \ "-Dcrypto=$P_CRYPTO" \ diff --git a/contrib/scripts/nm-ci-run.sh b/contrib/scripts/nm-ci-run.sh index 1f2b44e69f..49b31f6dca 100755 --- a/contrib/scripts/nm-ci-run.sh +++ b/contrib/scripts/nm-ci-run.sh @@ -194,7 +194,6 @@ meson setup build \ -D ofono=true \ -D teamdctl=$_WITH_LIBTEAM \ \ - -D dhclient=/bin/nowhere/dhclient \ -D dhcpcd=/bin/nowhere/dhcpd \ \ -D netconfig=/bin/nowhere/netconfig \ diff --git a/meson.build b/meson.build index 71d42bebb4..07928128a1 100644 --- a/meson.build +++ b/meson.build @@ -681,7 +681,7 @@ config_dhcp_default = get_option('config_dhcp_default') config_h.set_quoted('NM_CONFIG_DEFAULT_MAIN_DHCP', config_dhcp_default) config_dhcp_clients_enabled = [ 'internal' ] dhcp_summary = '' -foreach client : [ 'dhcpcd', 'dhclient' ] +foreach client : [ 'dhcpcd' ] client_path = get_option(client) client_enable = (client_path != 'no') if client_enable @@ -713,9 +713,6 @@ foreach client : [ 'dhcpcd', 'dhclient' ] dhcp_summary += (' ' + client_path) config_dhcp_clients_enabled += client endif - if (client == 'dhclient') - dhcp_summary += ' (deprecated)' - endif dhcp_summary += '\n' endforeach diff --git a/meson_options.txt b/meson_options.txt index 531db6b73c..fce9b92384 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -64,9 +64,8 @@ option('netconfig', type: 'string', value: '', description: 'Enable SUSE netconf option('config_dns_rc_manager_default', type: 'combo', choices: ['auto', 'symlink', 'file', 'netconfig', 'resolvconf'], value: 'auto', description: 'Configure default value for main.rc-manager setting') # dhcp clients -option('dhclient', type: 'string', value: 'no', description: 'Enable dhclient support (deprecated)') option('dhcpcd', type: 'string', value: '', description: 'Enable dhcpcd support') -option('config_dhcp_default', type: 'combo', choices: ['dhclient', 'dhcpcd', 'internal', 'nettools'], value: 'internal', description: 'Default configuration option for main.dhcp setting, used as fallback if the configuration option is unset') +option('config_dhcp_default', type: 'combo', choices: ['dhcpcd', 'internal', 'nettools'], value: 'internal', description: 'Default configuration option for main.dhcp setting, used as fallback if the configuration option is unset') # miscellaneous option('introspection', type: 'boolean', value: true, description: 'Enable introspection for this build') diff --git a/po/POTFILES.in b/po/POTFILES.in index 605683df42..9f8743b283 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -28,8 +28,6 @@ src/core/devices/wifi/nm-device-olpc-mesh.c src/core/devices/wifi/nm-device-wifi.c src/core/devices/wifi/nm-wifi-utils.c src/core/devices/wwan/nm-modem-broadband.c -src/core/dhcp/nm-dhcp-dhclient-utils.c -src/core/dhcp/nm-dhcp-dhclient.c src/core/dhcp/nm-dhcp-manager.c src/core/dns/nm-dns-manager.c src/core/main-utils.c diff --git a/src/core/dhcp/nm-dhcp-dhclient-utils.c b/src/core/dhcp/nm-dhcp-dhclient-utils.c deleted file mode 100644 index 286f7aa19f..0000000000 --- a/src/core/dhcp/nm-dhcp-dhclient-utils.c +++ /dev/null @@ -1,763 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2011 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include "nm-dhcp-dhclient-utils.h" - -#include -#include -#include -#include - -#include "libnm-glib-aux/nm-dedup-multi.h" - -#include "nm-dhcp-utils.h" -#include "nm-utils.h" -#include "libnm-platform/nm-platform.h" -#include "NetworkManagerUtils.h" - -#define TIMEOUT_TAG "timeout " -#define RETRY_TAG "retry " -#define CLIENTID_TAG "send dhcp-client-identifier" - -#define HOSTNAME4_TAG "send host-name" -#define HOSTNAME4_FORMAT HOSTNAME4_TAG " \"%s\"; # added by NetworkManager" - -#define FQDN_TAG_PREFIX "send fqdn." -#define FQDN_TAG FQDN_TAG_PREFIX "fqdn" -#define FQDN_FORMAT FQDN_TAG " \"%s\"; # added by NetworkManager" - -#define ALSOREQ_TAG "also request " -#define REQ_TAG "request " - -#define MUDURLv4_DEF "option mudurl code 161 = text;\n" -#define MUDURLv4_FMT "send mudurl \"%s\";\n" - -#define MUDURLv6_DEF "option dhcp6.mudurl code 112 = text;\n" -#define MUDURLv6_FMT "send dhcp6.mudurl \"%s\";\n" - -static void -add_request(GPtrArray *array, const char *item) -{ - guint i; - - for (i = 0; i < array->len; i++) { - if (nm_streq(array->pdata[i], item)) - return; - } - g_ptr_array_add(array, g_strdup(item)); -} - -static gboolean -grab_request_options(GPtrArray *store, const char *line) -{ - gs_free const char **line_v = NULL; - gsize i; - - /* Grab each 'request' or 'also request' option and save for later */ - line_v = nm_strsplit_set(line, "\t ,"); - for (i = 0; line_v && line_v[i]; i++) { - const char *ss = nm_str_skip_leading_spaces(line_v[i]); - gsize l; - gboolean end = FALSE; - - if (!ss[0]) - continue; - if (ss[0] == ';') { - /* all done */ - return TRUE; - } - - if (!g_ascii_isalnum(ss[0])) - continue; - - l = strlen(ss); - - while (l > 0 && g_ascii_isspace(ss[l - 1])) { - ((char *) ss)[l - 1] = '\0'; - l--; - } - if (l > 0 && ss[l - 1] == ';') { - /* Remove the EOL marker */ - ((char *) ss)[l - 1] = '\0'; - end = TRUE; - } - - if (ss[0]) - add_request(store, ss); - - if (end) - return TRUE; - } - - return FALSE; -} - -static void -add_ip4_config(GString *str, - GBytes *client_id, - const char *hostname, - gboolean use_fqdn, - NMDhcpHostnameFlags hostname_flags) -{ - if (client_id) { - const char *p; - gsize l; - guint i; - - p = g_bytes_get_data(client_id, &l); - nm_assert(p); - - /* Allow type 0 (non-hardware address) to be represented as a string - * as long as all the characters are printable. - */ - for (i = 1; (p[0] == 0) && i < l; i++) { - if (!g_ascii_isprint(p[i]) || p[i] == '\\' || p[i] == '"') - break; - } - - g_string_append(str, CLIENTID_TAG " "); - 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) - g_string_append_c(str, ':'); - g_string_append_printf(str, "%02x", (guint8) p[i]); - } - } else { - /* Printable; just add to the line with type 0 */ - g_string_append_c(str, '"'); - g_string_append(str, "\\x00"); - g_string_append_len(str, p + 1, l - 1); - g_string_append_c(str, '"'); - } - g_string_append(str, "; # added by NetworkManager\n"); - } - - if (hostname) { - if (use_fqdn) { - g_string_append_printf(str, FQDN_FORMAT "\n", hostname); - - g_string_append_printf(str, - FQDN_TAG_PREFIX "encoded %s;\n", - (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED) ? "on" - : "off"); - - g_string_append_printf( - str, - FQDN_TAG_PREFIX "server-update %s;\n", - (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) ? "on" : "off"); - - g_string_append_printf(str, - FQDN_TAG_PREFIX "no-client-update %s;\n", - (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE) ? "on" - : "off"); - } else - g_string_append_printf(str, HOSTNAME4_FORMAT "\n", hostname); - } - - g_string_append_c(str, '\n'); - - /* Define options for classless static routes */ - g_string_append( - str, - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n"); - g_string_append(str, - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n"); - /* Web Proxy Auto-Discovery option (bgo #368423) */ - g_string_append(str, "option wpad code 252 = string;\n"); - - g_string_append_c(str, '\n'); -} - -static void -add_hostname6(GString *str, const char *hostname, NMDhcpHostnameFlags hostname_flags) -{ - if (hostname) { - g_string_append_printf(str, FQDN_FORMAT "\n", hostname); - if (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) - g_string_append(str, FQDN_TAG_PREFIX "server-update on;\n"); - if (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE) - g_string_append(str, FQDN_TAG_PREFIX "no-client-update on;\n"); - g_string_append_c(str, '\n'); - } -} - -static void -add_mud_url_config(GString *str, const char *mud_url, int addr_family) -{ - if (mud_url) { - if (addr_family == AF_INET) { - g_string_append(str, MUDURLv4_DEF); - g_string_append_printf(str, MUDURLv4_FMT, mud_url); - } else { - g_string_append(str, MUDURLv6_DEF); - g_string_append_printf(str, MUDURLv6_FMT, mud_url); - } - } -} - -static GBytes * -read_client_id(const char *str) -{ - gs_free char *s = NULL; - char *p; - int i = 0; - int j = 0; - gsize l; - - nm_assert(NM_STR_HAS_PREFIX(str, CLIENTID_TAG)); - str += NM_STRLEN(CLIENTID_TAG); - - if (!g_ascii_isspace(*str)) - return NULL; - while (g_ascii_isspace(*str)) - str++; - - if (*str == '"') { - /* Parse string literal with escape sequences */ - s = g_strdup(str + 1); - p = strrchr(s, '"'); - if (p) - *p = '\0'; - else - return NULL; - - if (!s[0]) - return NULL; - - while (s[i]) { - if (s[i] == '\\' && s[i + 1] == 'x' && g_ascii_isxdigit(s[i + 2]) - && g_ascii_isxdigit(s[i + 3])) { - s[j++] = (g_ascii_xdigit_value(s[i + 2]) << 4) + g_ascii_xdigit_value(s[i + 3]); - i += 4; - continue; - } - if (s[i] == '\\' && s[i + 1] >= '0' && s[i + 1] <= '7' && s[1 + 2] >= '0' - && s[i + 2] <= '7' && s[1 + 3] >= '0' && s[i + 3] <= '7') { - s[j++] = ((s[i + 1] - '0') << 6) + ((s[i + 2] - '0') << 3) + (s[i + 3] - '0'); - i += 4; - continue; - } - s[j++] = s[i++]; - } - return g_bytes_new_take(g_steal_pointer(&s), j); - } - - /* Otherwise, try to read a hexadecimal sequence */ - s = g_strdup(str); - g_strchomp(s); - l = strlen(s); - if (l > 0 && s[l - 1] == ';') - s[l - 1] = '\0'; - - return nm_utils_hexstr2bin(s); -} - -static gboolean -read_interface(const char *line, char *interface, guint size) -{ - gs_free char *dup = g_strdup(line + NM_STRLEN("interface")); - char *ptr = dup, *end; - - while (g_ascii_isspace(*ptr)) - ptr++; - - if (*ptr == '"') { - ptr++; - end = strchr(ptr, '"'); - if (!end) - return FALSE; - *end = '\0'; - } else { - end = strchr(ptr, ' '); - if (!end) - end = strchr(ptr, '{'); - if (!end) - return FALSE; - *end = '\0'; - } - - if (ptr[0] == '\0' || strlen(ptr) + 1 > size) - return FALSE; - - g_snprintf(interface, size, "%s", ptr); - - return TRUE; -} - -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, - gboolean use_fqdn, - NMDhcpHostnameFlags hostname_flags, - const char *mud_url, - const char *const *reject_servers, - const char *orig_path, - const char *orig_contents, - GBytes **out_new_client_id) -{ - nm_auto_free_gstring GString *new_contents = NULL; - gs_unref_ptrarray GPtrArray *fqdn_opts = NULL; - gs_unref_ptrarray GPtrArray *reqs = NULL; - gboolean reset_reqlist = FALSE; - int i; - - g_return_val_if_fail(!anycast_address || nm_utils_hwaddr_valid(anycast_address, ETH_ALEN), - NULL); - g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), NULL); - g_return_val_if_fail(!reject_servers || addr_family == AF_INET, NULL); - nm_assert(!out_new_client_id || !*out_new_client_id); - - new_contents = g_string_new(_("# Created by NetworkManager\n")); - reqs = g_ptr_array_new_full(5, g_free); - - if (orig_contents) { - gs_free const char **lines = NULL; - gsize line_i; - nm_auto_free_gstring GString *blocks_stack = NULL; - guint blocks_skip = 0; - gboolean in_alsoreq = FALSE; - gboolean in_req = FALSE; - char intf[IFNAMSIZ]; - - blocks_stack = g_string_new(NULL); - g_string_append_printf(new_contents, _("# Merged from %s\n\n"), orig_path); - intf[0] = '\0'; - - lines = nm_strsplit_set(orig_contents, "\n\r"); - for (line_i = 0; lines && lines[line_i]; line_i++) { - const char *line = nm_str_skip_leading_spaces(lines[line_i]); - const char *p; - - if (line[0] == '\0') - continue; - - g_strchomp((char *) line); - - p = line; - if (in_req) { - /* pass */ - } else if (strchr(p, '{')) { - if (NM_STR_HAS_PREFIX(p, "lease") || NM_STR_HAS_PREFIX(p, "alias") - || NM_STR_HAS_PREFIX(p, "interface") || NM_STR_HAS_PREFIX(p, "pseudo")) { - /* skip over these blocks, except 'interface' when it - * matches the current interface */ - blocks_skip++; - g_string_append_c(blocks_stack, 'b'); - if (!intf[0] && NM_STR_HAS_PREFIX(p, "interface")) { - if (read_interface(p, intf, sizeof(intf))) - continue; - } - } else { - /* allow other blocks (conditionals) */ - if (!strchr(p, '}')) /* '} else {' */ - g_string_append_c(blocks_stack, 'c'); - } - } else if (strchr(p, '}')) { - if (blocks_stack->len > 0) { - if (blocks_stack->str[blocks_stack->len - 1] == 'b') { - g_string_truncate(blocks_stack, blocks_stack->len - 1); - nm_assert(blocks_skip > 0); - blocks_skip--; - intf[0] = '\0'; - continue; - } - g_string_truncate(blocks_stack, blocks_stack->len - 1); - } - } - - if (blocks_skip > 0 && !intf[0]) - continue; - - if (intf[0] && !nm_streq(intf, interface)) - continue; - - /* Some timing parameters in dhclient should not be imported (timeout, retry). - * The retry parameter will be simply not used as we will exit on first failure. - * The timeout one instead may affect NetworkManager behavior: if the timeout - * elapses before dhcp-timeout dhclient will report failure and cause NM to - * fail the dhcp process before dhcp-timeout. So, always skip importing timeout - * as we will need to add one greater than dhcp-timeout. - */ - if (NM_STR_HAS_PREFIX(p, TIMEOUT_TAG) || NM_STR_HAS_PREFIX(p, RETRY_TAG)) - continue; - - if (NM_STR_HAS_PREFIX(p, CLIENTID_TAG)) { - /* 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 */ - if (out_new_client_id) - nm_clear_pointer(out_new_client_id, g_bytes_unref); - NM_SET_OUT(out_new_client_id, read_client_id(p)); - /* fall-through. We keep the line... */ - } - - /* Override config file hostname and use one from the connection */ - if (hostname) { - if (NM_STR_HAS_PREFIX(p, HOSTNAME4_TAG)) - continue; - if (NM_STR_HAS_PREFIX(p, FQDN_TAG)) - continue; - } - - /* To let user's FQDN options (except "fqdn.fqdn") override the - * default ones set by NM, add them later - */ - if (NM_STR_HAS_PREFIX(p, FQDN_TAG_PREFIX)) { - if (!fqdn_opts) - fqdn_opts = g_ptr_array_new_full(5, g_free); - g_ptr_array_add(fqdn_opts, g_strdup(p + NM_STRLEN(FQDN_TAG_PREFIX))); - continue; - } - - /* Ignore 'script' since we pass our own */ - if (g_str_has_prefix(p, "script ")) - continue; - - /* Check for "request" */ - if (NM_STR_HAS_PREFIX(p, REQ_TAG)) { - in_req = TRUE; - p += NM_STRLEN(REQ_TAG); - g_ptr_array_set_size(reqs, 0); - reset_reqlist = TRUE; - } - - /* Save all request options for later use */ - if (in_req) { - in_req = !grab_request_options(reqs, p); - continue; - } - - /* Check for "also require" */ - if (NM_STR_HAS_PREFIX(p, ALSOREQ_TAG)) { - in_alsoreq = TRUE; - p += NM_STRLEN(ALSOREQ_TAG); - } - - if (in_alsoreq) { - in_alsoreq = !grab_request_options(reqs, p); - continue; - } - - /* Existing configuration line is OK, add it to new configuration */ - g_string_append(new_contents, line); - g_string_append_c(new_contents, '\n'); - } - } else - g_string_append_c(new_contents, '\n'); - - /* ensure dhclient timeout is greater than dhcp-timeout: as dhclient timeout default value is - * 60 seconds, we need this only if dhcp-timeout is greater than 60. - */ - if (timeout >= 60) { - timeout = timeout < G_MAXINT32 ? timeout + 1 : G_MAXINT32; - g_string_append_printf(new_contents, "timeout %u;\n", timeout); - } - - add_mud_url_config(new_contents, mud_url, addr_family); - - if (reject_servers && reject_servers[0]) { - g_string_append(new_contents, "reject "); - for (i = 0; reject_servers[i]; i++) { - if (i != 0) - g_string_append(new_contents, ", "); - g_string_append(new_contents, reject_servers[i]); - } - g_string_append(new_contents, ";\n"); - } - - 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"); - add_request(reqs, "static-routes"); - add_request(reqs, "wpad"); - add_request(reqs, "ntp-servers"); - add_request(reqs, "root-path"); - } else { - add_hostname6(new_contents, hostname, hostname_flags); - add_request(reqs, "dhcp6.name-servers"); - add_request(reqs, "dhcp6.domain-search"); - - /* FIXME: internal client does not support requesting client-id option. Does this even work? */ - add_request(reqs, "dhcp6.client-id"); - } - - if (reset_reqlist) - g_string_append(new_contents, "request; # override dhclient defaults\n"); - /* And add it to the dhclient configuration */ - for (i = 0; i < reqs->len; i++) - g_string_append_printf(new_contents, "also request %s;\n", (char *) reqs->pdata[i]); - - if (fqdn_opts) { - for (i = 0; i < fqdn_opts->len; i++) { - const char *t = fqdn_opts->pdata[i]; - - if (i == 0) - g_string_append_printf(new_contents, "\n# FQDN options from %s\n", orig_path); - g_string_append_printf(new_contents, FQDN_TAG_PREFIX "%s\n", t); - } - } - - g_string_append_c(new_contents, '\n'); - - if (anycast_address) { - g_string_append_printf(new_contents, - "interface \"%s\" {\n" - " initial-interval 1; \n" - " anycast-mac ethernet %s;\n" - "}\n", - interface, - anycast_address); - } - - return g_string_free(g_steal_pointer(&new_contents), FALSE); -} - -/* In the lease file, dhclient will write "option dhcp6.client-id $HEXSTR". This - * function does the same. */ -static char * -nm_dhcp_dhclient_escape_duid_as_hex(GBytes *duid) -{ - const guint8 *s; - gsize len; - - nm_assert(duid); - - s = g_bytes_get_data(duid, &len); - return nm_utils_bin2hexstr_fuller(s, len, ':', FALSE, FALSE, NULL); -} - -/* Roughly follow what dhclient's quotify_buf() and pretty_escape() functions do */ -char * -nm_dhcp_dhclient_escape_duid(GBytes *duid) -{ - char *escaped; - const guint8 *s, *s0; - gsize len; - char *d; - - g_return_val_if_fail(duid, NULL); - - s0 = g_bytes_get_data(duid, &len); - s = s0; - - d = escaped = g_malloc((len * 4) + 1); - while (s < (s0 + len)) { - if (!g_ascii_isprint(*s)) { - *d++ = '\\'; - *d++ = '0' + ((*s >> 6) & 0x7); - *d++ = '0' + ((*s >> 3) & 0x7); - *d++ = '0' + (*s++ & 0x7); - } else if (*s == '"' || *s == '\'' || *s == '$' || *s == '`' || *s == '\\' || *s == '|' - || *s == '&') { - *d++ = '\\'; - *d++ = *s++; - } else - *d++ = *s++; - } - *d++ = '\0'; - return escaped; -} - -static gboolean -isoctal(const guint8 *p) -{ - return (p[0] >= '0' && p[0] <= '3' && p[1] >= '0' && p[1] <= '7' && p[2] >= '0' && p[2] <= '7'); -} - -GBytes * -nm_dhcp_dhclient_unescape_duid(const char *duid) -{ - GByteArray *unescaped; - const guint8 *p = (const guint8 *) duid; - guint i, len; - guint8 octal; - - /* FIXME: it's wrong to have an "unescape-duid" function. dhclient - * defines a file format with escaping. So we need a general unescape - * function that can handle dhclient syntax. */ - - len = strlen(duid); - unescaped = g_byte_array_sized_new(len); - for (i = 0; i < len; i++) { - if (p[i] == '\\') { - i++; - if (isdigit(p[i])) { - /* Octal escape sequence */ - if (i + 2 >= len || !isoctal(p + i)) - goto error; - octal = ((p[i] - '0') << 6) + ((p[i + 1] - '0') << 3) + (p[i + 2] - '0'); - g_byte_array_append(unescaped, &octal, 1); - i += 2; - } else { - /* FIXME: don't warn on untrusted data. Either signal an error, or accept - * it silently. */ - - /* One of ", ', $, `, \, |, or & */ - g_warn_if_fail(p[i] == '"' || p[i] == '\'' || p[i] == '$' || p[i] == '`' - || p[i] == '\\' || p[i] == '|' || p[i] == '&'); - g_byte_array_append(unescaped, &p[i], 1); - } - } else - g_byte_array_append(unescaped, &p[i], 1); - } - - return g_byte_array_free_to_bytes(unescaped); - -error: - g_byte_array_free(unescaped, TRUE); - return NULL; -} - -#define DEFAULT_DUID_PREFIX "default-duid \"" - -/* Beware: @error may be unset even if the function returns %NULL. */ -GBytes * -nm_dhcp_dhclient_read_duid(const char *leasefile, GError **error) -{ - gs_free char *contents = NULL; - gs_free const char **contents_v = NULL; - gsize i; - - if (!g_file_test(leasefile, G_FILE_TEST_EXISTS)) - return NULL; - - if (!g_file_get_contents(leasefile, &contents, NULL, error)) - return NULL; - - contents_v = nm_strsplit_set(contents, "\n\r"); - for (i = 0; contents_v && contents_v[i]; i++) { - const char *p = nm_str_skip_leading_spaces(contents_v[i]); - GBytes *duid; - - if (!NM_STR_HAS_PREFIX(p, DEFAULT_DUID_PREFIX)) - continue; - - p += NM_STRLEN(DEFAULT_DUID_PREFIX); - - g_strchomp((char *) p); - - if (!NM_STR_HAS_SUFFIX(p, "\";")) - continue; - - ((char *) p)[strlen(p) - 2] = '\0'; - - duid = nm_dhcp_dhclient_unescape_duid(p); - if (duid) - return duid; - } - - return NULL; -} - -gboolean -nm_dhcp_dhclient_save_duid(const char *leasefile, - GBytes *duid, - gboolean enforce_duid, - GError **error) -{ - gs_free char *escaped_duid = NULL; - gs_free const char **lines = NULL; - nm_auto_free_gstring GString *s = NULL; - const char *const *iter; - gs_free char *conflicting_duid_line = NULL; - gs_free char *contents = NULL; - gsize contents_len = 0; - - g_return_val_if_fail(leasefile != NULL, FALSE); - - if (!duid) { - nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "missing duid"); - g_return_val_if_reached(FALSE); - } - - escaped_duid = nm_dhcp_dhclient_escape_duid(duid); - nm_assert(escaped_duid); - - if (g_file_test(leasefile, G_FILE_TEST_EXISTS)) { - if (!g_file_get_contents(leasefile, &contents, &contents_len, error)) { - g_prefix_error(error, "failed to read lease file %s: ", leasefile); - return FALSE; - } - - lines = nm_strsplit_set_with_empty(contents, "\n"); - } - - s = g_string_sized_new(contents_len + 50); - g_string_append_printf(s, DEFAULT_DUID_PREFIX "%s\";\n", escaped_duid); - - /* Preserve existing leasefile contents */ - if (lines) { - for (iter = lines; *iter; iter++) { - const char *str = *iter; - const char *l; - gboolean ends_with_r; - gsize l_len; - gsize prefix_len; - - l = nm_str_skip_leading_spaces(str); - l_len = strlen(l); - prefix_len = l - str; - - ends_with_r = l_len > 0 && l[l_len - 1u] == '\r'; - if (ends_with_r) { - ((char *) l)[--l_len] = '\0'; - } - - if (NM_STR_HAS_PREFIX(l, DEFAULT_DUID_PREFIX)) { - /* We always add our line on top. This line can be skipped. */ - continue; - } - - if (enforce_duid & NM_STR_HAS_PREFIX(l, "option dhcp6.client-id ")) { - /* we want to use our duid. Skip the per-lease client-id. */ - if (!conflicting_duid_line) { - gs_free char *duid_hex = nm_dhcp_dhclient_escape_duid_as_hex(duid); - - conflicting_duid_line = g_strdup_printf("option dhcp6.client-id %s;", duid_hex); - } - /* We adjust the duid line and set what we want. */ - l = conflicting_duid_line; - } - - g_string_append_len(s, str, prefix_len); - g_string_append(s, l); - if (ends_with_r) { - g_string_append_c(s, '\r'); - g_string_append_c(s, '\n'); - } else if ((iter[1]) != NULL) { - /* avoid to add an extra '\n' at the end of file */ - g_string_append_c(s, '\n'); - } - } - } - - if (contents && strlen(contents) == contents_len && nm_streq(contents, s->str)) { - /* The file is already as we want it. We are done. */ - return TRUE; - } - - if (!g_file_set_contents(leasefile, s->str, -1, error)) { - g_prefix_error(error, "failed to set DUID in lease file %s: ", leasefile); - return FALSE; - } - - return TRUE; -} diff --git a/src/core/dhcp/nm-dhcp-dhclient-utils.h b/src/core/dhcp/nm-dhcp-dhclient-utils.h deleted file mode 100644 index 34b2617512..0000000000 --- a/src/core/dhcp/nm-dhcp-dhclient-utils.h +++ /dev/null @@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2010 Red Hat, Inc. - */ - -#ifndef __NETWORKMANAGER_DHCP_DHCLIENT_UTILS_H__ -#define __NETWORKMANAGER_DHCP_DHCLIENT_UTILS_H__ - -#include "nm-setting-ip4-config.h" -#include "nm-setting-ip6-config.h" - -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, - gboolean use_fqdn, - NMDhcpHostnameFlags hostname_flags, - const char *mud_url, - const char *const *reject_servers, - const char *orig_path, - const char *orig_contents, - GBytes **out_new_client_id); - -char *nm_dhcp_dhclient_escape_duid(GBytes *duid); - -GBytes *nm_dhcp_dhclient_unescape_duid(const char *duid); - -GBytes *nm_dhcp_dhclient_read_duid(const char *leasefile, GError **error); - -gboolean nm_dhcp_dhclient_save_duid(const char *leasefile, - GBytes *duid, - gboolean enforce_duid, - GError **error); - -#endif /* __NETWORKMANAGER_DHCP_DHCLIENT_UTILS_H__ */ diff --git a/src/core/dhcp/nm-dhcp-dhclient.c b/src/core/dhcp/nm-dhcp-dhclient.c deleted file mode 100644 index 7e00599cd8..0000000000 --- a/src/core/dhcp/nm-dhcp-dhclient.c +++ /dev/null @@ -1,741 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2005 - 2012 Red Hat, Inc. - */ - -#include -#define __CONFIG_H__ - -#define _XOPEN_SOURCE -#include -#undef _XOPEN_SOURCE - -#include "src/core/nm-default-daemon.h" - -#if WITH_DHCLIENT - -#include -#include -#include -#include -#include -#include - -#include "libnm-glib-aux/nm-dedup-multi.h" - -#include "nm-utils.h" -#include "nm-dhcp-dhclient-utils.h" -#include "nm-dhcp-manager.h" -#include "NetworkManagerUtils.h" -#include "nm-dhcp-listener.h" -#include "nm-dhcp-client-logging.h" - -/*****************************************************************************/ - -static const char * -_addr_family_to_path_part(int addr_family) -{ - nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); - return (addr_family == AF_INET6) ? "6" : ""; -} - -/*****************************************************************************/ - -#define NM_TYPE_DHCP_DHCLIENT (nm_dhcp_dhclient_get_type()) -#define NM_DHCP_DHCLIENT(obj) \ - (_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclient)) -#define NM_DHCP_DHCLIENT_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclientClass)) -#define NM_IS_DHCP_DHCLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_DHCLIENT)) -#define NM_IS_DHCP_DHCLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_DHCLIENT)) -#define NM_DHCP_DHCLIENT_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclientClass)) - -typedef struct _NMDhcpDhclient NMDhcpDhclient; -typedef struct _NMDhcpDhclientClass NMDhcpDhclientClass; - -static GType nm_dhcp_dhclient_get_type(void); - -/*****************************************************************************/ - -typedef struct { - char *conf_file; - const char *def_leasefile; - char *lease_file; - char *pid_file; - NMDhcpListener *dhcp_listener; -} NMDhcpDhclientPrivate; - -struct _NMDhcpDhclient { - NMDhcpClient parent; - NMDhcpDhclientPrivate _priv; -}; - -struct _NMDhcpDhclientClass { - NMDhcpClientClass parent; -}; - -G_DEFINE_TYPE(NMDhcpDhclient, nm_dhcp_dhclient, NM_TYPE_DHCP_CLIENT) - -#define NM_DHCP_DHCLIENT_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMDhcpDhclient, NM_IS_DHCP_DHCLIENT) - -/*****************************************************************************/ - -static GBytes *read_duid_from_lease(NMDhcpDhclient *self); - -/*****************************************************************************/ - -static const char * -nm_dhcp_dhclient_get_path(void) -{ - return nm_utils_find_helper("dhclient", DHCLIENT_PATH, NULL); -} - -/** - * get_dhclient_leasefile(): - * @addr_family: AF_INET or AF_INET6 - * @iface: the interface name of the device on which DHCP will be done - * @uuid: the connection UUID to which the returned lease should belong - * @out_preferred_path: on return, the "most preferred" leasefile path - * - * Returns the path of an existing leasefile (if any) for this interface and - * connection UUID. Also returns the "most preferred" leasefile path, which - * may be different than any found leasefile. - * - * Returns: an existing leasefile, or %NULL if no matching leasefile could be found - */ -static char * -get_dhclient_leasefile(int addr_family, - const char *iface, - const char *uuid, - char **out_preferred_path) -{ - gs_free char *path = NULL; - - if (nm_dhcp_utils_get_leasefile_path(addr_family, "dhclient", iface, uuid, &path)) { - NM_SET_OUT(out_preferred_path, g_strdup(path)); - return g_steal_pointer(&path); - } - - NM_SET_OUT(out_preferred_path, g_steal_pointer(&path)); - - /* If the leasefile we're looking for doesn't exist yet in the new location - * (eg, /var/lib/NetworkManager) then look in old locations to maintain - * backwards compatibility with external tools (like dracut) that put - * leasefiles there. - */ - - /* Old Debian, SUSE, and Mandriva location */ - g_free(path); - path = g_strdup_printf(LOCALSTATEDIR "/lib/dhcp/dhclient%s-%s-%s.lease", - _addr_family_to_path_part(addr_family), - uuid, - iface); - if (g_file_test(path, G_FILE_TEST_EXISTS)) - return g_steal_pointer(&path); - - /* Old Red Hat and Fedora location */ - g_free(path); - path = g_strdup_printf(LOCALSTATEDIR "/lib/dhclient/dhclient%s-%s-%s.lease", - _addr_family_to_path_part(addr_family), - uuid, - iface); - if (g_file_test(path, G_FILE_TEST_EXISTS)) - return g_steal_pointer(&path); - - /* Fail */ - return NULL; -} - -static char * -find_existing_config(NMDhcpDhclient *self, int addr_family, const char *iface, const char *uuid) -{ - char *path; - - /* NetworkManager-overridden configuration can be used to ship DHCP config - * with NetworkManager itself. It can be uuid-specific, device-specific - * or generic. - */ - if (uuid) { - path = g_strdup_printf(NMCONFDIR "/dhclient%s-%s.conf", - _addr_family_to_path_part(addr_family), - uuid); - _LOGD("looking for existing config %s", path); - if (g_file_test(path, G_FILE_TEST_EXISTS)) - return path; - g_free(path); - } - - path = g_strdup_printf(NMCONFDIR "/dhclient%s-%s.conf", - _addr_family_to_path_part(addr_family), - iface); - _LOGD("looking for existing config %s", path); - if (g_file_test(path, G_FILE_TEST_EXISTS)) - return path; - g_free(path); - - path = g_strdup_printf(NMCONFDIR "/dhclient%s.conf", _addr_family_to_path_part(addr_family)); - _LOGD("looking for existing config %s", path); - if (g_file_test(path, G_FILE_TEST_EXISTS)) - return path; - g_free(path); - - /* Distribution's dhclient configuration is used so that we can use - * configuration shipped with dhclient (if any). - * - * This replaces conditional compilation based on distribution name. Fedora - * and Debian store the configs in /etc/dhcp while upstream defaults to /etc - * which is then used by many other distributions. Some distributions - * (including Fedora) don't even provide a default configuration file. - */ - path = g_strdup_printf(SYSCONFDIR "/dhcp/dhclient%s-%s.conf", - _addr_family_to_path_part(addr_family), - iface); - _LOGD("looking for existing config %s", path); - if (g_file_test(path, G_FILE_TEST_EXISTS)) - return path; - g_free(path); - - path = g_strdup_printf(SYSCONFDIR "/dhclient%s-%s.conf", - _addr_family_to_path_part(addr_family), - iface); - _LOGD("looking for existing config %s", path); - if (g_file_test(path, G_FILE_TEST_EXISTS)) - return path; - g_free(path); - - path = - g_strdup_printf(SYSCONFDIR "/dhcp/dhclient%s.conf", _addr_family_to_path_part(addr_family)); - _LOGD("looking for existing config %s", path); - if (g_file_test(path, G_FILE_TEST_EXISTS)) - return path; - g_free(path); - - path = g_strdup_printf(SYSCONFDIR "/dhclient%s.conf", _addr_family_to_path_part(addr_family)); - _LOGD("looking for existing config %s", path); - if (g_file_test(path, G_FILE_TEST_EXISTS)) - return path; - g_free(path); - - return NULL; -} - -/* NM provides interface-specific options; thus the same dhclient config - * file cannot be used since DHCP transactions can happen in parallel. - * Since some distros don't have default per-interface dhclient config files, - * read their single config file and merge that into a custom per-interface - * config file along with the NM options. - */ -static char * -create_dhclient_config(NMDhcpDhclient *self, - int addr_family, - const char *iface, - const char *uuid, - GBytes *client_id, - gboolean send_client_id, - const char *anycast_address, - const char *hostname, - guint32 timeout, - gboolean use_fqdn, - NMDhcpHostnameFlags hostname_flags, - const char *mud_url, - const char *const *reject_servers, - GBytes **out_new_client_id) -{ - gs_free char *orig_path = NULL; - gs_free char *orig_content = NULL; - char *new_path = NULL; - gs_free char *new_content = NULL; - GError *error = NULL; - - g_return_val_if_fail(iface != NULL, NULL); - - new_path = g_strdup_printf(NMSTATEDIR "/dhclient%s-%s.conf", - _addr_family_to_path_part(addr_family), - iface); - _LOGD("creating composite dhclient config %s", new_path); - - orig_path = find_existing_config(self, addr_family, iface, uuid); - if (orig_path) - _LOGD("merging existing dhclient config %s", orig_path); - else - _LOGD("no existing dhclient configuration to merge"); - - if (orig_path && g_file_test(orig_path, G_FILE_TEST_EXISTS)) { - if (!g_file_get_contents(orig_path, &orig_content, NULL, &error)) { - _LOGW("error reading dhclient configuration %s: %s", orig_path, error->message); - g_error_free(error); - } - } - - new_content = nm_dhcp_dhclient_create_config(iface, - addr_family, - client_id, - send_client_id, - anycast_address, - hostname, - timeout, - use_fqdn, - hostname_flags, - mud_url, - reject_servers, - orig_path, - orig_content, - out_new_client_id); - nm_assert(new_content); - - if (!g_file_set_contents(new_path, new_content, -1, &error)) { - _LOGW("error creating dhclient configuration: %s", error->message); - g_error_free(error); - g_free(new_path); - return NULL; - } - - return new_path; -} - -static gboolean -dhclient_start(NMDhcpClient *client, - gboolean set_mode, - gboolean release, - gboolean set_duid, - pid_t *out_pid, - GError **error) -{ - NMDhcpDhclient *self = NM_DHCP_DHCLIENT(client); - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self); - gs_unref_ptrarray GPtrArray *argv = NULL; - pid_t pid; - gs_free_error GError *local = NULL; - const char *iface; - const char *uuid; - const char *system_bus_address; - const char *dhclient_path; - char *binary_name; - gs_free char *cmd_str = NULL; - gs_free char *pid_file = NULL; - gs_free char *system_bus_address_env = NULL; - gs_free char *preferred_leasefile_path = NULL; - int addr_family; - const NMDhcpClientConfig *client_config; - char pd_length_str[16]; - - g_return_val_if_fail(!priv->pid_file, FALSE); - client_config = nm_dhcp_client_get_config(client); - addr_family = client_config->addr_family; - - NM_SET_OUT(out_pid, 0); - - dhclient_path = nm_dhcp_dhclient_get_path(); - if (!dhclient_path) { - nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "dhclient binary not found"); - return FALSE; - } - - iface = client_config->iface; - uuid = client_config->uuid; - - pid_file = g_strdup_printf(NMRUNDIR "/dhclient%s-%s.pid", - _addr_family_to_path_part(addr_family), - iface); - - /* Kill any existing dhclient from the pidfile */ - binary_name = g_path_get_basename(dhclient_path); - nm_dhcp_client_stop_existing(pid_file, binary_name); - g_free(binary_name); - - if (release) { - /* release doesn't use the pidfile after killing an old client */ - nm_clear_g_free(&pid_file); - } - - g_free(priv->lease_file); - priv->lease_file = get_dhclient_leasefile(addr_family, iface, uuid, &preferred_leasefile_path); - nm_assert(preferred_leasefile_path); - if (!priv->lease_file) { - /* No existing leasefile, dhclient will create one at the preferred path */ - priv->lease_file = g_steal_pointer(&preferred_leasefile_path); - } else if (!nm_streq0(priv->lease_file, preferred_leasefile_path)) { - gs_unref_object GFile *src = g_file_new_for_path(priv->lease_file); - gs_unref_object GFile *dst = g_file_new_for_path(preferred_leasefile_path); - - /* Try to copy the existing leasefile to the preferred location */ - if (!g_file_copy(src, dst, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &local)) { - gs_free char *s_path = NULL; - gs_free char *d_path = NULL; - - /* Failure; just use the existing leasefile */ - _LOGW("failed to copy leasefile %s to %s: %s", - (s_path = g_file_get_path(src)), - (d_path = g_file_get_path(dst)), - local->message); - g_clear_error(&local); - } else { - /* Success; use the preferred leasefile path */ - g_free(priv->lease_file); - priv->lease_file = g_file_get_path(dst); - } - } - - /* Save the DUID to the leasefile dhclient will actually use */ - if (set_duid && addr_family == AF_INET6) { - if (!nm_dhcp_dhclient_save_duid(priv->lease_file, - nm_dhcp_client_get_effective_client_id(client), - client_config->v6.enforce_duid, - &local)) { - nm_utils_error_set(error, - NM_UTILS_ERROR_UNKNOWN, - "failed to save DUID to '%s': %s", - priv->lease_file, - local->message); - return FALSE; - } - } - - argv = g_ptr_array_new(); - g_ptr_array_add(argv, (gpointer) dhclient_path); - - g_ptr_array_add(argv, (gpointer) "-d"); - - /* Be quiet. dhclient logs to syslog anyway. And we duplicate the syslog - * to stderr in case of NM running with --debug. - */ - g_ptr_array_add(argv, (gpointer) "-q"); - - if (release) - g_ptr_array_add(argv, (gpointer) "-r"); - - if (!release && client_config->addr_family == AF_INET && client_config->v4.request_broadcast) { - g_ptr_array_add(argv, (gpointer) "-B"); - } - - if (addr_family == AF_INET6) { - guint prefixes = client_config->v6.needed_prefixes; - const char *mode_opt; - - g_ptr_array_add(argv, (gpointer) "-6"); - - if (!set_mode) - mode_opt = NULL; - else if (!client_config->v6.info_only) - mode_opt = "-N"; - else if (prefixes == 0) - mode_opt = "-S"; - else - mode_opt = NULL; - - if (mode_opt) - g_ptr_array_add(argv, (gpointer) mode_opt); - - if (prefixes > 0 && client_config->v6.pd_hint_length > 0) { - if (!IN6_IS_ADDR_UNSPECIFIED(&client_config->v6.pd_hint_addr)) { - _LOGW("dhclient only supports a length as prefix delegation hint, not a prefix"); - } - - nm_sprintf_buf(pd_length_str, "%u", client_config->v6.pd_hint_length); - g_ptr_array_add(argv, "--prefix-len-hint"); - g_ptr_array_add(argv, pd_length_str); - } - - while (prefixes--) - g_ptr_array_add(argv, (gpointer) "-P"); - } - g_ptr_array_add(argv, (gpointer) "-sf"); /* Set script file */ - g_ptr_array_add(argv, (gpointer) nm_dhcp_helper_path); - - if (pid_file) { - g_ptr_array_add(argv, (gpointer) "-pf"); /* Set pid file */ - g_ptr_array_add(argv, (gpointer) pid_file); - } - - g_ptr_array_add(argv, (gpointer) "-lf"); /* Set lease file */ - g_ptr_array_add(argv, (gpointer) priv->lease_file); - - if (priv->conf_file) { - g_ptr_array_add(argv, (gpointer) "-cf"); /* Set interface config file */ - g_ptr_array_add(argv, (gpointer) priv->conf_file); - } - - if (client_config->v4.dscp_explicit) { - _LOGW("dhclient does not support specifying a custom DSCP value; the TOS field will be set " - "to LOWDELAY (0x10)."); - } - - if (client_config->v4.ipv6_only_preferred) { - _LOGW("the dhclient backend does not support the \"IPv6-Only Preferred\" option; ignoring " - "it"); - } - - /* Usually the system bus address is well-known; but if it's supposed - * to be something else, we need to push it to dhclient, since dhclient - * sanitizes the environment it gives the action scripts. - */ - system_bus_address = getenv("DBUS_SYSTEM_BUS_ADDRESS"); - if (system_bus_address) { - system_bus_address_env = g_strdup_printf("DBUS_SYSTEM_BUS_ADDRESS=%s", system_bus_address); - g_ptr_array_add(argv, (gpointer) "-e"); - g_ptr_array_add(argv, (gpointer) system_bus_address_env); - } - - g_ptr_array_add(argv, (gpointer) iface); - g_ptr_array_add(argv, NULL); - - _LOGD("running: %s", (cmd_str = g_strjoinv(" ", (char **) argv->pdata))); - - if (!g_spawn_async(NULL, - (char **) argv->pdata, - NULL, - G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_STDOUT_TO_DEV_NULL - | G_SPAWN_STDERR_TO_DEV_NULL, - nm_utils_setpgid, - NULL, - &pid, - &local)) { - nm_utils_error_set(error, - NM_UTILS_ERROR_UNKNOWN, - "dhclient failed to start: %s", - local->message); - return FALSE; - } - - _LOGI("dhclient started with pid %lld", (long long int) pid); - - if (!release) - nm_dhcp_client_watch_child(client, pid); - - priv->pid_file = g_steal_pointer(&pid_file); - - NM_SET_OUT(out_pid, pid); - return TRUE; -} - -static gboolean -ip4_start(NMDhcpClient *client, GError **error) -{ - NMDhcpDhclient *self = NM_DHCP_DHCLIENT(client); - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self); - gs_unref_bytes GBytes *new_client_id = NULL; - const NMDhcpClientConfig *client_config; - - client_config = nm_dhcp_client_get_config(client); - - nm_assert(client_config->addr_family == AF_INET); - - priv->conf_file = create_dhclient_config(self, - AF_INET, - 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, - client_config->use_fqdn, - client_config->hostname_flags, - client_config->mud_url, - client_config->reject_servers, - &new_client_id); - if (!priv->conf_file) { - nm_utils_error_set_literal(error, - NM_UTILS_ERROR_UNKNOWN, - "error creating dhclient configuration file"); - return FALSE; - } - - /* Note that the effective-client-id for IPv4 here might be unknown/NULL. */ - nm_assert(!new_client_id || !client_config->client_id); - nm_dhcp_client_set_effective_client_id(client, client_config->client_id ?: new_client_id); - - return dhclient_start(client, FALSE, FALSE, FALSE, NULL, error); -} - -static gboolean -ip6_start(NMDhcpClient *client, const struct in6_addr *ll_addr, GError **error) -{ - NMDhcpDhclient *self = NM_DHCP_DHCLIENT(client); - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self); - const NMDhcpClientConfig *config; - gs_unref_bytes GBytes *effective_client_id = NULL; - - config = nm_dhcp_client_get_config(client); - - nm_assert(config->addr_family == AF_INET6); - - if (config->v6.iaid_explicit) - _LOGW("dhclient does not support specifying an IAID for DHCPv6, it will be ignored"); - - priv->conf_file = create_dhclient_config(self, - AF_INET6, - config->iface, - config->uuid, - NULL, - TRUE, - config->anycast_address, - config->hostname, - config->timeout, - TRUE, - config->hostname_flags, - config->mud_url, - NULL, - NULL); - if (!priv->conf_file) { - nm_utils_error_set_literal(error, - NM_UTILS_ERROR_UNKNOWN, - "error creating dhclient configuration file"); - return FALSE; - } - - nm_assert(config->client_id); - if (!config->v6.enforce_duid) - effective_client_id = read_duid_from_lease(self); - nm_dhcp_client_set_effective_client_id(client, effective_client_id ?: config->client_id); - - return dhclient_start(client, TRUE, FALSE, TRUE, NULL, error); -} - -static void -stop(NMDhcpClient *client, gboolean release) -{ - NMDhcpDhclient *self = NM_DHCP_DHCLIENT(client); - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self); - int errsv; - - NM_DHCP_CLIENT_CLASS(nm_dhcp_dhclient_parent_class)->stop(client, release); - - if (priv->conf_file) - if (remove(priv->conf_file) == -1) { - errsv = errno; - _LOGD("could not remove dhcp config file \"%s\": %d (%s)", - priv->conf_file, - errsv, - nm_strerror_native(errsv)); - } - if (priv->pid_file) { - if (remove(priv->pid_file) == -1) { - errsv = errno; - _LOGD("could not remove dhcp pid file \"%s\": %s (%d)", - priv->pid_file, - nm_strerror_native(errsv), - errsv); - } - nm_clear_g_free(&priv->pid_file); - } - - if (release) { - pid_t rpid = -1; - - if (dhclient_start(client, FALSE, TRUE, FALSE, &rpid, NULL)) { - /* Wait a few seconds for the release to happen */ - nm_dhcp_client_stop_pid(rpid, nm_dhcp_client_get_iface(client)); - } - } -} - -static GBytes * -read_duid_from_lease(NMDhcpDhclient *self) -{ - NMDhcpClient *client = NM_DHCP_CLIENT(self); - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self); - const NMDhcpClientConfig *client_config; - GBytes *duid = NULL; - gs_free char *leasefile = NULL; - GError *error = NULL; - - client_config = nm_dhcp_client_get_config(client); - - /* Look in interface-specific leasefile first for backwards compat */ - leasefile = get_dhclient_leasefile(AF_INET6, - nm_dhcp_client_get_iface(client), - client_config->uuid, - NULL); - if (leasefile) { - _LOGD("looking for DUID in '%s'", leasefile); - duid = nm_dhcp_dhclient_read_duid(leasefile, &error); - if (error) { - _LOGW("failed to read leasefile '%s': %s", leasefile, error->message); - g_clear_error(&error); - } - if (duid) - return duid; - } - - /* Otherwise, read the default machine-wide DUID */ - _LOGD("looking for default DUID in '%s'", priv->def_leasefile); - duid = nm_dhcp_dhclient_read_duid(priv->def_leasefile, &error); - if (error) { - _LOGW("failed to read leasefile '%s': %s", priv->def_leasefile, error->message); - g_clear_error(&error); - } - - return duid; -} - -/*****************************************************************************/ - -static void -nm_dhcp_dhclient_init(NMDhcpDhclient *self) -{ - static const char *const FILES[] = { - SYSCONFDIR "/dhclient6.leases", /* default */ - LOCALSTATEDIR "/lib/dhcp/dhclient6.leases", - LOCALSTATEDIR "/lib/dhclient/dhclient6.leases", - }; - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self); - int i; - - priv->def_leasefile = FILES[0]; - for (i = 0; i < G_N_ELEMENTS(FILES); i++) { - if (g_file_test(FILES[i], G_FILE_TEST_EXISTS)) { - priv->def_leasefile = FILES[i]; - break; - } - } - - priv->dhcp_listener = g_object_ref(nm_dhcp_listener_get()); - g_signal_connect(priv->dhcp_listener, - NM_DHCP_LISTENER_EVENT, - G_CALLBACK(nm_dhcp_client_handle_event), - self); -} - -static void -dispose(GObject *object) -{ - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(object); - - if (priv->dhcp_listener) { - g_signal_handlers_disconnect_by_func(priv->dhcp_listener, - G_CALLBACK(nm_dhcp_client_handle_event), - NM_DHCP_DHCLIENT(object)); - g_clear_object(&priv->dhcp_listener); - } - - nm_clear_g_free(&priv->pid_file); - nm_clear_g_free(&priv->conf_file); - nm_clear_g_free(&priv->lease_file); - - G_OBJECT_CLASS(nm_dhcp_dhclient_parent_class)->dispose(object); -} - -static void -nm_dhcp_dhclient_class_init(NMDhcpDhclientClass *dhclient_class) -{ - NMDhcpClientClass *client_class = NM_DHCP_CLIENT_CLASS(dhclient_class); - GObjectClass *object_class = G_OBJECT_CLASS(dhclient_class); - - object_class->dispose = dispose; - - client_class->ip4_start = ip4_start; - client_class->ip6_start = ip6_start; - client_class->stop = stop; -} - -const NMDhcpClientFactory _nm_dhcp_client_factory_dhclient = { - .name = "dhclient", - .get_type_4 = nm_dhcp_dhclient_get_type, - .get_type_6 = nm_dhcp_dhclient_get_type, - .get_path = nm_dhcp_dhclient_get_path, -}; - -#endif /* WITH_DHCLIENT */ diff --git a/src/core/dhcp/nm-dhcp-listener.c b/src/core/dhcp/nm-dhcp-listener.c index 095131cc80..cead130857 100644 --- a/src/core/dhcp/nm-dhcp-listener.c +++ b/src/core/dhcp/nm-dhcp-listener.c @@ -36,9 +36,6 @@ const NMDhcpClientFactory *const _nm_dhcp_manager_factories[6] = { #endif &_nm_dhcp_client_factory_systemd, &_nm_dhcp_client_factory_nettools, -#if WITH_DHCLIENT - &_nm_dhcp_client_factory_dhclient, -#endif }; /*****************************************************************************/ diff --git a/src/core/dhcp/tests/meson.build b/src/core/dhcp/tests/meson.build index e43c8cab36..8b2a7b764f 100644 --- a/src/core/dhcp/tests/meson.build +++ b/src/core/dhcp/tests/meson.build @@ -1,7 +1,6 @@ # SPDX-License-Identifier: LGPL-2.1-or-later test_units = [ - 'test-dhcp-dhclient', 'test-dhcp-utils', ] diff --git a/src/core/dhcp/tests/test-dhclient-commented-duid.leases b/src/core/dhcp/tests/test-dhclient-commented-duid.leases deleted file mode 100644 index 3e46ae7d0b..0000000000 --- a/src/core/dhcp/tests/test-dhclient-commented-duid.leases +++ /dev/null @@ -1,2 +0,0 @@ -#default-duid "\000\001\000\001\030y\246\023`g \354Lp"; - diff --git a/src/core/dhcp/tests/test-dhclient-duid.leases b/src/core/dhcp/tests/test-dhclient-duid.leases deleted file mode 100644 index 229331d47f..0000000000 --- a/src/core/dhcp/tests/test-dhclient-duid.leases +++ /dev/null @@ -1,2 +0,0 @@ -default-duid "\000\001\000\001\030y\246\023`g \354Lp"; - diff --git a/src/core/dhcp/tests/test-dhcp-dhclient.c b/src/core/dhcp/tests/test-dhcp-dhclient.c deleted file mode 100644 index 6a7b7185a3..0000000000 --- a/src/core/dhcp/tests/test-dhcp-dhclient.c +++ /dev/null @@ -1,1478 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2010 Red Hat, Inc. - */ - -#include "src/core/nm-default-daemon.h" - -#include -#include -#include - -#include "libnm-glib-aux/nm-dedup-multi.h" - -#include "NetworkManagerUtils.h" -#include "dhcp/nm-dhcp-dhclient-utils.h" -#include "dhcp/nm-dhcp-utils.h" -#include "nm-utils.h" -#include "libnm-platform/nm-platform.h" - -#include "nm-test-utils-core.h" - -#define TEST_DIR NM_BUILD_SRCDIR "/src/core/dhcp/tests" -#define TEST_MUDURL "https://example.com/mud.json" - -static void -test_config(const char *orig, - const char *expected, - int addr_family, - const char *hostname, - guint32 timeout, - gboolean use_fqdn, - NMDhcpHostnameFlags hostname_flags, - const char *dhcp_client_id, - GBytes *expected_new_client_id, - const char *iface, - 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; - gboolean send_client_id = TRUE; - - 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); - } - - new = nm_dhcp_dhclient_create_config(iface, - addr_family, - client_id, - send_client_id, - anycast_addr, - hostname, - timeout, - use_fqdn, - hostname_flags, - mud_url, - NULL, - "/path/to/dhclient.conf", - orig, - &new_client_id); - g_assert(new != NULL); - - if (!nm_streq(new, expected)) { - g_message("\n* OLD ---------------------------------\n" - "%s" - "\n- NEW -----------------------------------\n" - "%s" - "\n+ EXPECTED ++++++++++++++++++++++++++++++\n" - "%s" - "\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - orig, - new, - expected); - } - g_assert_cmpstr(new, ==, expected); - - if (expected_new_client_id) { - g_assert(new_client_id); - g_assert(g_bytes_equal(new_client_id, expected_new_client_id)); - } else - g_assert(new_client_id == NULL); -} - -/*****************************************************************************/ - -static const char *orig_missing_expected = - "# Created by NetworkManager\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_orig_missing(void) -{ - test_config(NULL, - orig_missing_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *orig_missing_add_mud_url_expected = - "# Created by NetworkManager\n" - "\n" - "option mudurl code 161 = text;\n" - "send mudurl \"https://example.com/mud.json\";\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_orig_missing_add_mud_url(void) -{ - test_config(NULL, - orig_missing_add_mud_url_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - TEST_MUDURL); -} - -/*****************************************************************************/ - -static const char *override_client_id_orig = "send dhcp-client-identifier 00:30:04:20:7A:08;\n"; - -static const char *override_client_id_expected = - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send dhcp-client-identifier 11:22:33:44:55:66; # 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_override_client_id(void) -{ - test_config(override_client_id_orig, - override_client_id_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - "11:22:33:44:55:66", - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *quote_client_id_expected = - "# Created by NetworkManager\n" - "\n" - "send dhcp-client-identifier \"\\x00abcd\"; # 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_quote_client_id(void) -{ - test_config(NULL, - quote_client_id_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - "abcd", - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *quote_client_id_expected_2 = - "# Created by NetworkManager\n" - "\n" - "send dhcp-client-identifier 00:61:5c:62:63; # 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_quote_client_id_2(void) -{ - test_config(NULL, - quote_client_id_expected_2, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - "a\\bc", - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *hex_zero_client_id_expected = - "# Created by NetworkManager\n" - "\n" - "send dhcp-client-identifier 00:11:22:33; # 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_hex_zero_client_id(void) -{ - test_config(NULL, - hex_zero_client_id_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - "00:11:22:33", - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *ascii_client_id_expected = - "# Created by NetworkManager\n" - "\n" - "send dhcp-client-identifier \"\\x00qb:cd:ef:12:34:56\"; # 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_ascii_client_id(void) -{ - test_config(NULL, - ascii_client_id_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - "qb:cd:ef:12:34:56", - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *hex_single_client_id_expected = - "# Created by NetworkManager\n" - "\n" - "send dhcp-client-identifier ab:cd:0e:12:34:56; # 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_hex_single_client_id(void) -{ - test_config(NULL, - hex_single_client_id_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - "ab:cd:e:12:34:56", - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *existing_hex_client_id_orig = "send dhcp-client-identifier 10:30:04:20:7A:08;\n"; - -static const char *existing_hex_client_id_expected = - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send dhcp-client-identifier 10:30:04:20:7A:08;\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_existing_hex_client_id(void) -{ - gs_unref_bytes GBytes *new_client_id = NULL; - const guint8 bytes[] = {0x10, 0x30, 0x04, 0x20, 0x7A, 0x08}; - - new_client_id = g_bytes_new(bytes, sizeof(bytes)); - test_config(existing_hex_client_id_orig, - existing_hex_client_id_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - new_client_id, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *existing_escaped_client_id_orig = - "send dhcp-client-identifier \"\\044test\\xfe\";\n"; - -static const char *existing_escaped_client_id_expected = - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send dhcp-client-identifier \"\\044test\\xfe\";\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_existing_escaped_client_id(void) -{ - gs_unref_bytes GBytes *new_client_id = NULL; - - new_client_id = g_bytes_new("$test\xfe", 6); - test_config(existing_escaped_client_id_orig, - existing_escaped_client_id_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - new_client_id, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -#define EACID "qb:cd:ef:12:34:56" - -static const char *existing_ascii_client_id_orig = - "send dhcp-client-identifier \"\\x00" EACID "\";\n"; - -static const char *existing_ascii_client_id_expected = - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send dhcp-client-identifier \"\\x00" EACID "\";\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_existing_ascii_client_id(void) -{ - gs_unref_bytes GBytes *new_client_id = NULL; - char buf[NM_STRLEN(EACID) + 1] = {0}; - - memcpy(buf + 1, EACID, NM_STRLEN(EACID)); - new_client_id = g_bytes_new(buf, sizeof(buf)); - test_config(existing_ascii_client_id_orig, - existing_ascii_client_id_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - new_client_id, - "eth0", - 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 = - "# Created by NetworkManager\n" - "\n" - "send fqdn.fqdn \"foo.bar.com\"; # added by NetworkManager\n" - "send fqdn.encoded on;\n" - "send fqdn.server-update off;\n" - "send fqdn.no-client-update on;\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_fqdn(void) -{ - test_config(NULL, - fqdn_expected, - AF_INET, - "foo.bar.com", - 0, - TRUE, - NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED | NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE, - NULL, - NULL, - "eth0", - NULL, - NULL); -} - -static const char *fqdn_options_override_orig = - "\n" - "send fqdn.fqdn \"foobar.com\"\n" /* NM must ignore this ... */ - "send fqdn.encoded off;\n" /* ... and honor these */ - "send fqdn.server-update off;\n"; - -static const char *fqdn_options_override_expected = - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send fqdn.fqdn \"example2.com\"; # added by NetworkManager\n" - "send fqdn.encoded off;\n" - "send fqdn.server-update on;\n" - "send fqdn.no-client-update off;\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" - "# FQDN options from /path/to/dhclient.conf\n" - "send fqdn.encoded off;\n" - "send fqdn.server-update off;\n\n"; - -static void -test_fqdn_options_override(void) -{ - test_config(fqdn_options_override_orig, - fqdn_options_override_expected, - AF_INET, - "example2.com", - 0, - NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, - TRUE, - NULL, - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *override_hostname_orig = "send host-name \"foobar\";\n"; - -static const char *override_hostname_expected = - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send host-name \"blahblah\"; # 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_override_hostname(void) -{ - test_config(override_hostname_orig, - override_hostname_expected, - AF_INET, - "blahblah", - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *override_hostname6_orig = "send fqdn.fqdn \"foobar\";\n"; - -static const char *override_hostname6_expected = - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send fqdn.fqdn \"blahblah.local\"; # added by NetworkManager\n" - "send fqdn.server-update on;\n" - "\n" - "also request dhcp6.name-servers;\n" - "also request dhcp6.domain-search;\n" - "also request dhcp6.client-id;\n" - "\n"; - -static void -test_override_hostname6(void) -{ - test_config(override_hostname6_orig, - override_hostname6_expected, - AF_INET6, - "blahblah.local", - 0, - TRUE, - NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, - NULL, - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *nonfqdn_hostname6_expected = - "# Created by NetworkManager\n" - "\n" - "send fqdn.fqdn \"blahblah\"; # added by NetworkManager\n" - "send fqdn.no-client-update on;\n" - "\n" - "also request dhcp6.name-servers;\n" - "also request dhcp6.domain-search;\n" - "also request dhcp6.client-id;\n" - "\n"; - -static void -test_nonfqdn_hostname6(void) -{ - /* Non-FQDN hostname can now be used with dhclient */ - test_config(NULL, - nonfqdn_hostname6_expected, - AF_INET6, - "blahblah", - 0, - TRUE, - NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE, - NULL, - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *existing_alsoreq_orig = "also request something;\n" - "also request another-thing;\n"; - -static const char *existing_alsoreq_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 something;\n" - "also request another-thing;\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_existing_alsoreq(void) -{ - test_config(existing_alsoreq_orig, - existing_alsoreq_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *existing_req_orig = "request something;\n" - "also request some-other-thing;\n" - "request another-thing;\n" - "also request yet-another-thing;\n"; - -static const char *existing_req_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" - "request; # override dhclient defaults\n" - "also request another-thing;\n" - "also request yet-another-thing;\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_existing_req(void) -{ - test_config(existing_req_orig, - existing_req_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *existing_multiline_alsoreq_orig = - "also request something another-thing yet-another-thing\n" - " foobar baz blah;\n"; - -static const char *existing_multiline_alsoreq_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 something;\n" - "also request another-thing;\n" - "also request yet-another-thing;\n" - "also request foobar;\n" - "also request baz;\n" - "also request blah;\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_existing_multiline_alsoreq(void) -{ - test_config(existing_multiline_alsoreq_orig, - existing_multiline_alsoreq_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static void -test_one_duid(const char *escaped, const guint8 *unescaped, guint len) -{ - gs_unref_bytes GBytes *t1 = NULL; - gs_unref_bytes GBytes *t2 = NULL; - gs_free char *w = NULL; - - t1 = nm_dhcp_dhclient_unescape_duid(escaped); - g_assert(t1); - g_assert(nm_g_bytes_equal_mem(t1, unescaped, len)); - - t2 = g_bytes_new(unescaped, len); - w = nm_dhcp_dhclient_escape_duid(t2); - g_assert(w); - g_assert_cmpstr(escaped, ==, w); -} - -static void -test_duids(void) -{ - const guint8 test1_u[] = - {0x00, 0x01, 0x00, 0x01, 0x13, 0x6f, 0x13, 0x6e, 0x00, 0x22, 0xfa, 0x8c, 0xd6, 0xc2}; - const char *test1_s = "\\000\\001\\000\\001\\023o\\023n\\000\\\"\\372\\214\\326\\302"; - - const guint8 test2_u[] = - {0x00, 0x01, 0x00, 0x01, 0x17, 0x57, 0xee, 0x39, 0x00, 0x23, 0x15, 0x08, 0x7E, 0xac}; - const char *test2_s = "\\000\\001\\000\\001\\027W\\3569\\000#\\025\\010~\\254"; - - const guint8 test3_u[] = - {0x00, 0x01, 0x00, 0x01, 0x17, 0x58, 0xe8, 0x58, 0x00, 0x23, 0x15, 0x08, 0x7e, 0xac}; - const char *test3_s = "\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254"; - - const guint8 test4_u[] = - {0x00, 0x01, 0x00, 0x01, 0x15, 0xd5, 0x31, 0x97, 0x00, 0x16, 0xeb, 0x04, 0x45, 0x18}; - const char *test4_s = "\\000\\001\\000\\001\\025\\3251\\227\\000\\026\\353\\004E\\030"; - - const char *bad_s = "\\000\\001\\000\\001\\425\\3251\\227\\000\\026\\353\\004E\\030"; - - test_one_duid(test1_s, test1_u, sizeof(test1_u)); - test_one_duid(test2_s, test2_u, sizeof(test2_u)); - test_one_duid(test3_s, test3_u, sizeof(test3_u)); - test_one_duid(test4_s, test4_u, sizeof(test4_u)); - - /* Invalid octal digit */ - g_assert(nm_dhcp_dhclient_unescape_duid(bad_s) == NULL); -} - -static void -test_read_duid_from_leasefile(void) -{ - const guint8 expected[] = - {0x00, 0x01, 0x00, 0x01, 0x18, 0x79, 0xa6, 0x13, 0x60, 0x67, 0x20, 0xec, 0x4c, 0x70}; - gs_unref_bytes GBytes *duid = NULL; - GError *error = NULL; - - duid = nm_dhcp_dhclient_read_duid(TEST_DIR "/test-dhclient-duid.leases", &error); - nmtst_assert_success(duid, error); - - g_assert(nm_g_bytes_equal_mem(duid, expected, G_N_ELEMENTS(expected))); -} - -static void -test_read_commented_duid_from_leasefile(void) -{ - GBytes *duid; - GError *error = NULL; - - duid = nm_dhcp_dhclient_read_duid(TEST_DIR "/test-dhclient-commented-duid.leases", &error); - g_assert_no_error(error); - g_assert(duid == NULL); -} - -/*****************************************************************************/ - -static void -_check_duid_impl(const guint8 *duid_bin, - gsize duid_len, - gboolean enforce_duid, - const char *old_content, - const char *new_content) -{ - gs_free_error GError *error = NULL; - gs_free char *contents = NULL; - gboolean success; - const char *path = NM_BUILD_BUILDDIR "/src/core/dhcp/tests/check-duid.lease"; - gs_unref_bytes GBytes *duid = NULL; - gsize contents_len; - - g_assert(duid_bin); - g_assert(duid_len > 0); - - if (!nm_str_is_empty(old_content) || nmtst_get_rand_bool()) { - success = g_file_set_contents(path, old_content ?: "", -1, &error); - nmtst_assert_success(success, error); - } else - nmtst_file_unlink_if_exists(path); - - duid = g_bytes_new(duid_bin, duid_len); - - success = nm_dhcp_dhclient_save_duid(path, duid, enforce_duid, &error); - nmtst_assert_success(success, error); - - success = g_file_get_contents(path, &contents, &contents_len, &error); - nmtst_assert_success(success, error); - g_assert(contents); - - nmtst_file_unlink(path); - - if (!nm_streq0(new_content, contents)) - g_error("FAILING:\n\nEXPECTED:\n%s\nACTUAL:\n%s\n\n", new_content, contents); - - g_assert_cmpstr(new_content, ==, contents); - g_assert_cmpint(contents_len, ==, strlen(contents)); -} - -#define _DUID(...) ((const guint8[]) {__VA_ARGS__}) - -#define _check_duid(duid, enforce_duid, old_content, new_content) \ - _check_duid_impl((duid), sizeof(duid), (enforce_duid), (old_content), (new_content)) - -static void -test_write_duid(void) -{ - _check_duid(_DUID(000, 001, 000, 001, 027, 'X', 0350, 'X', 0, '#', 025, 010, '~', 0254), - FALSE, - NULL, - "default-duid \"\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254\";\n"); - - _check_duid( - _DUID(000, 001, 000, 001, 023, 'o', 023, 'n', 000, '"', 0372, 0214, 0326, 0302), - FALSE, - "default-duid \"\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254\";\n", - "default-duid \"\\000\\001\\000\\001\\023o\\023n\\000\\\"\\372\\214\\326\\302\";\n"); - - _check_duid(_DUID(000, 001, 000, 001, 023, 'o', 023, 'n', 000, '"', 0372, 0214, 0326, 0302), - FALSE, - "#default-duid \"\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254\";\n", - "default-duid " - "\"\\000\\001\\000\\001\\023o\\023n\\000\\\"\\372\\214\\326\\302\";\n#default-duid " - "\"\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254\";\n"); - _check_duid( - _DUID(000, 001, 000, 001, 023, 'o', 023, 'n', 000, '"', 0372, 0214, 0326, 0302), - FALSE, - "### Commented old DUID ###\n#default-duid " - "\"\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254\";\n", - "default-duid \"\\000\\001\\000\\001\\023o\\023n\\000\\\"\\372\\214\\326\\302\";\n### " - "Commented old DUID ###\n#default-duid " - "\"\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254\";\n"); - - _check_duid( - _DUID(0xaa, 0xb, 0xcc, 0xd, 0xee, 0xf), - FALSE, - "default-duid \"\\252\\013\\314\\015\\356\\017\";\nlease6 {\n interface \"eth1\";\n " - " ia-na f1:ce:00:01 {\n starts 1671015678;\n renew 60;\n rebind 105;\n " - "iaaddr 192:168:121::1:112c {\n starts 1671015678;\n preferred-life 120;\n " - " max-life 120;\n }\n }\n option fqdn.encoded true;\n option " - "fqdn.server-update true;\n option fqdn.no-client-update false;\n option fqdn.fqdn " - "\"dff6de4fcb0f\";\n option fqdn.hostname \"dff6de4fcb0f\";\n option dhcp6.client-id " - "aa:b:cc:d:ee:f;\n option dhcp6.server-id 0:1:0:1:2b:2c:4d:1d:0:0:0:0:0:0;\n option " - "dhcp6.name-servers 192:168:121:0:ce0f:f1ff:fece:1;\n option dhcp6.fqdn " - "1:c:64:66:66:36:64:65:34:66:63:62:30:66;\n option dhcp6.status-code success " - "\"success\";\n}\n", - "default-duid \"\\252\\013\\314\\015\\356\\017\";\nlease6 {\n interface \"eth1\";\n " - " ia-na f1:ce:00:01 {\n starts 1671015678;\n renew 60;\n rebind 105;\n " - "iaaddr 192:168:121::1:112c {\n starts 1671015678;\n preferred-life 120;\n " - " max-life 120;\n }\n }\n option fqdn.encoded true;\n option " - "fqdn.server-update true;\n option fqdn.no-client-update false;\n option fqdn.fqdn " - "\"dff6de4fcb0f\";\n option fqdn.hostname \"dff6de4fcb0f\";\n option dhcp6.client-id " - "aa:b:cc:d:ee:f;\n option dhcp6.server-id 0:1:0:1:2b:2c:4d:1d:0:0:0:0:0:0;\n option " - "dhcp6.name-servers 192:168:121:0:ce0f:f1ff:fece:1;\n option dhcp6.fqdn " - "1:c:64:66:66:36:64:65:34:66:63:62:30:66;\n option dhcp6.status-code success " - "\"success\";\n}\n"); - - _check_duid( - _DUID(0xaa, 0xb, 0xcc, 0xd, 0xee, 0xf), - FALSE, - "default-duid \"\\252\\013\\314\\015\\356\\017\";\nlease6 {\n interface \"eth1\";\n " - " ia-na f1:ce:00:01 {\n starts 1671015678;\n renew 60;\n rebind 105;\n " - "iaaddr 192:168:121::1:112c {\n starts 1671015678;\n preferred-life 120;\n " - " max-life 120;\n }\n }\n option fqdn.encoded true;\n option " - "fqdn.server-update true;\n option fqdn.no-client-update false;\n option fqdn.fqdn " - "\"dff6de4fcb0f\";\n option fqdn.hostname \"dff6de4fcb0f\";\n option dhcp6.client-id " - "aa:b:cc:d:ee:f;\n option dhcp6.server-id 0:1:0:1:2b:2c:4d:1d:0:0:0:0:0:0;\n option " - "dhcp6.name-servers 192:168:121:0:ce0f:f1ff:fece:1;\n option dhcp6.fqdn " - "1:c:64:66:66:36:64:65:34:66:63:62:30:66;\n option dhcp6.status-code success " - "\"success\";\r\n}\n", - "default-duid \"\\252\\013\\314\\015\\356\\017\";\nlease6 {\n interface \"eth1\";\n " - " ia-na f1:ce:00:01 {\n starts 1671015678;\n renew 60;\n rebind 105;\n " - "iaaddr 192:168:121::1:112c {\n starts 1671015678;\n preferred-life 120;\n " - " max-life 120;\n }\n }\n option fqdn.encoded true;\n option " - "fqdn.server-update true;\n option fqdn.no-client-update false;\n option fqdn.fqdn " - "\"dff6de4fcb0f\";\n option fqdn.hostname \"dff6de4fcb0f\";\n option dhcp6.client-id " - "aa:b:cc:d:ee:f;\n option dhcp6.server-id 0:1:0:1:2b:2c:4d:1d:0:0:0:0:0:0;\n option " - "dhcp6.name-servers 192:168:121:0:ce0f:f1ff:fece:1;\n option dhcp6.fqdn " - "1:c:64:66:66:36:64:65:34:66:63:62:30:66;\n option dhcp6.status-code success " - "\"success\";\r\n}\n"); - - _check_duid( - _DUID(0xaa, 0xb, 0xcc, 0xd, 0xee, 0xe), - FALSE, - "default-duid \"\\252\\013\\314\\015\\356\\017\";\nlease6 {\n interface \"eth1\";\n " - " ia-na f1:ce:00:01 {\n starts 1671015678;\n renew 60;\n rebind 105;\n " - "iaaddr 192:168:121::1:112c {\n starts 1671015678;\n preferred-life 120;\n " - " max-life 120;\n }\n }\n option fqdn.encoded true;\n option " - "fqdn.server-update true;\n option fqdn.no-client-update false;\n option fqdn.fqdn " - "\"dff6de4fcb0f\";\n option fqdn.hostname \"dff6de4fcb0f\";\n option dhcp6.client-id " - "aa:b:cc:d:ee:f;\n option dhcp6.server-id 0:1:0:1:2b:2c:4d:1d:0:0:0:0:0:0;\n option " - "dhcp6.name-servers 192:168:121:0:ce0f:f1ff:fece:1;\n option dhcp6.fqdn " - "1:c:64:66:66:36:64:65:34:66:63:62:30:66;\n option dhcp6.status-code success " - "\"success\";\r\n}\n", - "default-duid \"\\252\\013\\314\\015\\356\\016\";\nlease6 {\n interface \"eth1\";\n " - " ia-na f1:ce:00:01 {\n starts 1671015678;\n renew 60;\n rebind 105;\n " - "iaaddr 192:168:121::1:112c {\n starts 1671015678;\n preferred-life 120;\n " - " max-life 120;\n }\n }\n option fqdn.encoded true;\n option " - "fqdn.server-update true;\n option fqdn.no-client-update false;\n option fqdn.fqdn " - "\"dff6de4fcb0f\";\n option fqdn.hostname \"dff6de4fcb0f\";\n option dhcp6.client-id " - "aa:b:cc:d:ee:f;\n option dhcp6.server-id 0:1:0:1:2b:2c:4d:1d:0:0:0:0:0:0;\n option " - "dhcp6.name-servers 192:168:121:0:ce0f:f1ff:fece:1;\n option dhcp6.fqdn " - "1:c:64:66:66:36:64:65:34:66:63:62:30:66;\n option dhcp6.status-code success " - "\"success\";\r\n}\n"); - - _check_duid( - _DUID(0xaa, 0xb, 0xcc, 0xd, 0xee, 0xe), - TRUE, - "default-duid \"\\252\\013\\314\\015\\356\\017\";\nlease6 {\n interface \"eth1\";\n " - " ia-na f1:ce:00:01 {\n starts 1671015678;\n renew 60;\n rebind 105;\n " - "iaaddr 192:168:121::1:112c {\n starts 1671015678;\n preferred-life 120;\n " - " max-life 120;\n }\n }\n option fqdn.encoded true;\n option " - "fqdn.server-update true;\n option fqdn.no-client-update false;\n option fqdn.fqdn " - "\"dff6de4fcb0f\";\n option fqdn.hostname \"dff6de4fcb0f\";\n option dhcp6.client-id " - "aa:b:cc:d:ee:f;\n option dhcp6.server-id 0:1:0:1:2b:2c:4d:1d:0:0:0:0:0:0;\n option " - "dhcp6.name-servers 192:168:121:0:ce0f:f1ff:fece:1;\n option dhcp6.fqdn " - "1:c:64:66:66:36:64:65:34:66:63:62:30:66;\n option dhcp6.status-code success " - "\"success\";\n}\n", - "default-duid \"\\252\\013\\314\\015\\356\\016\";\nlease6 {\n interface \"eth1\";\n " - " ia-na f1:ce:00:01 {\n starts 1671015678;\n renew 60;\n rebind 105;\n " - "iaaddr 192:168:121::1:112c {\n starts 1671015678;\n preferred-life 120;\n " - " max-life 120;\n }\n }\n option fqdn.encoded true;\n option " - "fqdn.server-update true;\n option fqdn.no-client-update false;\n option fqdn.fqdn " - "\"dff6de4fcb0f\";\n option fqdn.hostname \"dff6de4fcb0f\";\n option dhcp6.client-id " - "aa:b:cc:d:ee:e;\n option dhcp6.server-id 0:1:0:1:2b:2c:4d:1d:0:0:0:0:0:0;\n option " - "dhcp6.name-servers 192:168:121:0:ce0f:f1ff:fece:1;\n option dhcp6.fqdn " - "1:c:64:66:66:36:64:65:34:66:63:62:30:66;\n option dhcp6.status-code success " - "\"success\";\n}\n"); -} - -/*****************************************************************************/ - -static const char *interface1_orig = "interface \"eth0\" {\n" - "\talso request my-option;\n" - "\tinitial-delay 5;\n" - "}\n" - "interface \"eth1\" {\n" - "\talso request another-option;\n" - "\tinitial-delay 0;\n" - "}\n" - "\n" - "also request yet-another-option;\n"; - -static const char *interface1_expected = - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "initial-delay 5;\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 my-option;\n" - "also request yet-another-option;\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_interface1(void) -{ - test_config(interface1_orig, - interface1_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -static const char *interface2_orig = "interface eth0 {\n" - "\talso request my-option;\n" - "\tinitial-delay 5;\n" - " }\n" - "interface eth1 {\n" - "\tinitial-delay 0;\n" - "\trequest another-option;\n" - " } \n" - "\n" - "also request yet-another-option;\n"; - -static const char *interface2_expected = - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "initial-delay 0;\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" - "request; # override dhclient defaults\n" - "also request another-option;\n" - "also request yet-another-option;\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_interface2(void) -{ - test_config(interface2_orig, - interface2_expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth1", - NULL, - NULL); -} - -static void -test_structured(void) -{ - gs_unref_bytes GBytes *new_client_id = NULL; - const guint8 bytes[] = "sad-and-useless"; - - static const char *const orig = - "interface \"eth0\" { \n" - " send host-name \"useless.example.com\";\n" - " hardware ethernet de:ad:80:86:ba:be;\n" - " send dhcp-client-identifier \"sad-and-useless\";\n" - " script \"/bin/useless\";\n" - " send dhcp-lease-time 8086;\n" - " request subnet-mask, broadcast-address, time-offset, routers,\n" - " domain-search, domain-name, host-name;\n" - " require subnet-mask;\n" - "} \n" - "\n" - " interface \"eth1\" { \n" - " send host-name \"sad.example.com\";\n" - " hardware ethernet de:ca:f6:66:ca:fe;\n" - " send dhcp-client-identifier \"useless-and-miserable\";\n" - " script \"/bin/miserable\";\n" - " send dhcp-lease-time 1337;\n" - " request subnet-mask, broadcast-address, time-offset, routers,\n" - " domain-search, domain-name, domain-name-servers, host-name;\n" - " require subnet-mask, domain-name-servers;\n" - " if not option domain-name = \"example.org\" {\n" - " prepend domain-name-servers 127.0.0.1;\n" - " } else {\n" - " prepend domain-name-servers 127.0.0.2;\n" - " } \n" - " } \n" - "\n" - "pseudo \"secondary\" \"eth0\" { \n" - " send dhcp-client-identifier \"sad-useless-and-secondary\";\n" - " script \"/bin/secondary\";\n" - " send host-name \"secondary.useless.example.com\";\n" - " send dhcp-lease-time 666;\n" - " request routers;\n" - " require routers;\n" - " } \n" - "\n" - " pseudo \"tertiary\" \"eth0\" { \n" - " send dhcp-client-identifier \"sad-useless-and-tertiary\";\n" - " script \"/bin/tertiary\";\n" - " send host-name \"tertiary.useless.example.com\";\n" - "} \n" - "\n" - " alias{ \n" - " interface \"eth0\";\n" - " fixed-address 192.0.2.1;\n" - " option subnet-mask 255.255.255.0;\n" - " } \n" - " lease { \n" - " interface \"eth0\";\n" - " fixed-address 192.0.2.2;\n" - " option subnet-mask 255.255.255.0;\n" - " } \n" - "if not option domain-name = \"example.org\" {\n" - " prepend domain-name-servers 127.0.0.1;\n" - " if not option domain-name = \"useless.example.com\" {\n" - " prepend domain-name-servers 127.0.0.2;\n" - " }\n" - "}\n"; - - static const char *const expected = - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send host-name \"useless.example.com\";\n" - "hardware ethernet de:ad:80:86:ba:be;\n" - "send dhcp-client-identifier \"sad-and-useless\";\n" - "send dhcp-lease-time 8086;\n" - "require subnet-mask;\n" - "if not option domain-name = \"example.org\" {\n" - "prepend domain-name-servers 127.0.0.1;\n" - "if not option domain-name = \"useless.example.com\" {\n" - "prepend domain-name-servers 127.0.0.2;\n" - "}\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" - "request; # override dhclient defaults\n" - "also request subnet-mask;\n" - "also request broadcast-address;\n" - "also request time-offset;\n" - "also request routers;\n" - "also request domain-search;\n" - "also request domain-name;\n" - "also request host-name;\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"; - - new_client_id = g_bytes_new(bytes, sizeof(bytes) - 1); - test_config(orig, - expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - new_client_id, - "eth0", - NULL, - NULL); -} - -static void -test_config_req_intf(void) -{ - static const char *const orig = "request subnet-mask, broadcast-address, routers,\n" - "\trfc3442-classless-static-routes,\n" - "\tinterface-mtu, host-name, domain-name, domain-search,\n" - "\tdomain-name-servers, nis-domain, nis-servers,\n" - "\tnds-context, nds-servers, nds-tree-name,\n" - "\tnetbios-name-servers, netbios-dd-server,\n" - "\tnetbios-node-type, netbios-scope, ntp-servers;\n" - ""; - static const char *const 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" - "request; # override dhclient defaults\n" - "also request subnet-mask;\n" - "also request broadcast-address;\n" - "also request routers;\n" - "also request rfc3442-classless-static-routes;\n" - "also request interface-mtu;\n" - "also request host-name;\n" - "also request domain-name;\n" - "also request domain-search;\n" - "also request domain-name-servers;\n" - "also request nis-domain;\n" - "also request nis-servers;\n" - "also request nds-context;\n" - "also request nds-servers;\n" - "also request nds-tree-name;\n" - "also request netbios-name-servers;\n" - "also request netbios-dd-server;\n" - "also request netbios-node-type;\n" - "also request netbios-scope;\n" - "also request ntp-servers;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request root-path;\n" - "\n"; - - test_config(orig, - expected, - AF_INET, - NULL, - 0, - FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - NULL); -} - -/*****************************************************************************/ - -NMTST_DEFINE(); - -int -main(int argc, char **argv) -{ - nmtst_init_with_logging(&argc, &argv, NULL, "DEFAULT"); - - g_test_add_func("/dhcp/dhclient/orig_missing", test_orig_missing); - g_test_add_func("/dhcp/dhclient/orig_missing_add_mud_url", test_orig_missing_add_mud_url); - g_test_add_func("/dhcp/dhclient/override_client_id", test_override_client_id); - g_test_add_func("/dhcp/dhclient/quote_client_id/1", test_quote_client_id); - g_test_add_func("/dhcp/dhclient/quote_client_id/2", test_quote_client_id_2); - g_test_add_func("/dhcp/dhclient/hex_zero_client_id", test_hex_zero_client_id); - g_test_add_func("/dhcp/dhclient/ascii_client_id", test_ascii_client_id); - g_test_add_func("/dhcp/dhclient/hex_single_client_id", test_hex_single_client_id); - 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); - g_test_add_func("/dhcp/dhclient/override_hostname6", test_override_hostname6); - g_test_add_func("/dhcp/dhclient/nonfqdn_hostname6", test_nonfqdn_hostname6); - g_test_add_func("/dhcp/dhclient/existing_req", test_existing_req); - g_test_add_func("/dhcp/dhclient/existing_alsoreq", test_existing_alsoreq); - g_test_add_func("/dhcp/dhclient/existing_multiline_alsoreq", test_existing_multiline_alsoreq); - g_test_add_func("/dhcp/dhclient/duids", test_duids); - g_test_add_func("/dhcp/dhclient/interface/1", test_interface1); - g_test_add_func("/dhcp/dhclient/interface/2", test_interface2); - g_test_add_func("/dhcp/dhclient/config/req_intf", test_config_req_intf); - g_test_add_func("/dhcp/dhclient/structured", test_structured); - - g_test_add_func("/dhcp/dhclient/read_duid_from_leasefile", test_read_duid_from_leasefile); - g_test_add_func("/dhcp/dhclient/read_commented_duid_from_leasefile", - test_read_commented_duid_from_leasefile); - - g_test_add_func("/dhcp/dhclient/test_write_duid", test_write_duid); - - return g_test_run(); -} diff --git a/src/core/meson.build b/src/core/meson.build index 4a3dfd8e11..947dedc5e9 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -128,8 +128,6 @@ libNetworkManager = static_library( 'devices/nm-device-wireguard.c', 'devices/nm-device-wpan.c', 'devices/nm-lldp-listener.c', - 'dhcp/nm-dhcp-dhclient.c', - 'dhcp/nm-dhcp-dhclient-utils.c', 'dhcp/nm-dhcp-dhcpcd.c', 'dhcp/nm-dhcp-listener.c', 'dns/nm-dns-dnsmasq.c', diff --git a/tools/nm-in-container b/tools/nm-in-container index e4ee8b9431..359c5e96cd 100755 --- a/tools/nm-in-container +++ b/tools/nm-in-container @@ -204,7 +204,6 @@ RUN dnf install -y \\ cscope \\ dbus-devel \\ dbus-x11 \\ - dhclient \\ dnsmasq \\ firewalld-filesystem \\ gcc-c++ \\ diff --git a/tools/nm-in-vm b/tools/nm-in-vm index cf42b03881..55f436d6f3 100755 --- a/tools/nm-in-vm +++ b/tools/nm-in-vm @@ -287,7 +287,6 @@ do_build() { --delete "/etc/NetworkManager/system-connections/*" \ --append-line "/etc/bashrc:. /etc/bashrc.my" \ --run-command "updatedb" \ - --append-line "/etc/dhcp/dhclient.conf:send host-name = gethostname();" \ --firstboot-command "systemctl enable --now dhcp-host" virt-install \