diff options
Diffstat (limited to 'src/dhcp')
| -rw-r--r-- | src/dhcp/nm-dhcp-client-logging.h | 4 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-client.c | 27 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-client.h | 14 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient-utils.c | 85 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient-utils.h | 6 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient.c | 30 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhcpcd.c | 32 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-listener.c | 2 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-manager.c | 54 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-systemd.c | 29 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-utils.h | 4 | ||||
| -rw-r--r-- | src/dhcp/tests/test-dhcp-dhclient.c | 129 |
12 files changed, 283 insertions, 133 deletions
diff --git a/src/dhcp/nm-dhcp-client-logging.h b/src/dhcp/nm-dhcp-client-logging.h index 8dd18bf2..1047a7d7 100644 --- a/src/dhcp/nm-dhcp-client-logging.h +++ b/src/dhcp/nm-dhcp-client-logging.h @@ -42,7 +42,7 @@ ? LOGD_DHCP \ : (nm_dhcp_client_get_ipv6 (_self) ? LOGD_DHCP6 : LOGD_DHCP4); \ \ - nm_log (_level, _domain, \ + nm_log (_level, _domain, __ifname, NULL, \ "%s%s%s%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ _NMLOG_PREFIX_NAME, \ (_domain == LOGD_DHCP4 ? "4" : (_domain == LOGD_DHCP6 ? "6" : "")), \ @@ -65,7 +65,7 @@ if (nm_logging_enabled (_level, _domain)) { \ const char *__ifname = (ifname); \ \ - nm_log (_level, _domain, \ + nm_log (_level, _domain, __ifname, NULL, \ "%s%s%s%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ _NMLOG_PREFIX_NAME, \ (_domain == LOGD_DHCP4 ? "4" : (_domain == LOGD_DHCP6 ? "6" : "")), \ diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c index ba7c6dbf..0906f5be 100644 --- a/src/dhcp/nm-dhcp-client.c +++ b/src/dhcp/nm-dhcp-client.c @@ -68,7 +68,7 @@ typedef struct _NMDhcpClientPrivate { GByteArray * duid; GBytes * client_id; char * hostname; - char * fqdn; + gboolean use_fqdn; NMDhcpState state; pid_t pid; @@ -147,6 +147,14 @@ nm_dhcp_client_get_priority (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->priority; } +guint32 +nm_dhcp_client_get_timeout (NMDhcpClient *self) +{ + g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), 0); + + return NM_DHCP_CLIENT_GET_PRIVATE (self)->timeout; +} + GBytes * nm_dhcp_client_get_client_id (NMDhcpClient *self) { @@ -178,12 +186,12 @@ nm_dhcp_client_get_hostname (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->hostname; } -const char * -nm_dhcp_client_get_fqdn (NMDhcpClient *self) +gboolean +nm_dhcp_client_get_use_fqdn (NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); + g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->fqdn; + return NM_DHCP_CLIENT_GET_PRIVATE (self)->use_fqdn; } /*****************************************************************************/ @@ -298,7 +306,6 @@ nm_dhcp_client_set_state (NMDhcpClient *self, g_assert ( (priv->ipv6 && NM_IS_IP6_CONFIG (ip_config)) || (!priv->ipv6 && NM_IS_IP4_CONFIG (ip_config))); g_assert (options); - g_assert_cmpint (g_hash_table_size (options), >, 0); } else { g_assert (ip_config == NULL); g_assert (options == NULL); @@ -409,7 +416,7 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self, const char *dhcp_client_id, const char *dhcp_anycast_addr, const char *hostname, - const char *fqdn, + gboolean use_fqdn, const char *last_ip4_address) { NMDhcpClientPrivate *priv; @@ -430,8 +437,7 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self, g_clear_pointer (&priv->hostname, g_free); priv->hostname = g_strdup (hostname); - g_free (priv->fqdn); - priv->fqdn = g_strdup (fqdn); + priv->use_fqdn = use_fqdn; return NM_DHCP_CLIENT_GET_CLASS (self)->ip4_start (self, dhcp_anycast_addr, last_ip4_address); } @@ -571,7 +577,7 @@ nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name) if (start_time == 0) goto out; - nm_sprintf_buf (proc_path, "/proc/%lu/cmdline", (long unsigned) pid); + nm_sprintf_buf (proc_path, "/proc/%lu/cmdline", (unsigned long) pid); if (!g_file_get_contents (proc_path, &proc_contents, NULL, NULL)) goto out; @@ -904,7 +910,6 @@ dispose (GObject *object) g_clear_pointer (&priv->iface, g_free); g_clear_pointer (&priv->hostname, g_free); - g_clear_pointer (&priv->fqdn, g_free); g_clear_pointer (&priv->uuid, g_free); g_clear_pointer (&priv->client_id, g_bytes_unref); diff --git a/src/dhcp/nm-dhcp-client.h b/src/dhcp/nm-dhcp-client.h index 7a083ae7..e41a59a2 100644 --- a/src/dhcp/nm-dhcp-client.h +++ b/src/dhcp/nm-dhcp-client.h @@ -19,10 +19,10 @@ #ifndef __NETWORKMANAGER_DHCP_CLIENT_H__ #define __NETWORKMANAGER_DHCP_CLIENT_H__ -#include <nm-setting-ip4-config.h> -#include <nm-setting-ip6-config.h> -#include <nm-ip4-config.h> -#include <nm-ip6-config.h> +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" +#include "nm-ip4-config.h" +#include "nm-ip6-config.h" #define NM_TYPE_DHCP_CLIENT (nm_dhcp_client_get_type ()) #define NM_DHCP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP_CLIENT, NMDhcpClient)) @@ -117,17 +117,19 @@ const GByteArray *nm_dhcp_client_get_hw_addr (NMDhcpClient *self); guint32 nm_dhcp_client_get_priority (NMDhcpClient *self); +guint32 nm_dhcp_client_get_timeout (NMDhcpClient *self); + GBytes *nm_dhcp_client_get_client_id (NMDhcpClient *self); const char *nm_dhcp_client_get_hostname (NMDhcpClient *self); -const char *nm_dhcp_client_get_fqdn (NMDhcpClient *self); +gboolean nm_dhcp_client_get_use_fqdn (NMDhcpClient *self); gboolean nm_dhcp_client_start_ip4 (NMDhcpClient *self, const char *dhcp_client_id, const char *dhcp_anycast_addr, const char *hostname, - const char *fqdn, + gboolean use_fqdn, const char *last_ip4_address); gboolean nm_dhcp_client_start_ip6 (NMDhcpClient *self, diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/dhcp/nm-dhcp-dhclient-utils.c index f36451b2..216319b3 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.c +++ b/src/dhcp/nm-dhcp-dhclient-utils.c @@ -93,29 +93,21 @@ grab_request_options (GPtrArray *store, const char* line) static void -add_hostname4 (GString *str, const char *hostname, const char *fqdn) +add_hostname4 (GString *str, const char *hostname, gboolean use_fqdn) { - char *plain_hostname, *dot; - - if (fqdn) { - g_string_append_printf (str, FQDN_FORMAT "\n", fqdn); - g_string_append (str, - "send fqdn.encoded on;\n" - "send fqdn.server-update on;\n"); - } else if (hostname) { - plain_hostname = g_strdup (hostname); - dot = strchr (plain_hostname, '.'); - /* get rid of the domain */ - if (dot) - *dot = '\0'; - - g_string_append_printf (str, HOSTNAME4_FORMAT "\n", plain_hostname); - g_free (plain_hostname); + if (hostname) { + if (use_fqdn) { + g_string_append_printf (str, FQDN_FORMAT "\n", hostname); + g_string_append (str, + "send fqdn.encoded on;\n" + "send fqdn.server-update on;\n"); + } else + g_string_append_printf (str, HOSTNAME4_FORMAT "\n", hostname); } } static void -add_ip4_config (GString *str, GBytes *client_id, const char *hostname, const char *fqdn) +add_ip4_config (GString *str, GBytes *client_id, const char *hostname, gboolean use_fqdn) { if (client_id) { const char *p; @@ -150,7 +142,7 @@ add_ip4_config (GString *str, GBytes *client_id, const char *hostname, const cha g_string_append (str, "; # added by NetworkManager\n"); } - add_hostname4 (str, hostname, fqdn); + add_hostname4 (str, hostname, use_fqdn); g_string_append_c (str, '\n'); @@ -232,13 +224,46 @@ nm_dhcp_dhclient_get_client_id_from_config_file (const char *path) return NULL; } +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; + + snprintf (interface, size, "%s", ptr); + + return TRUE; +} + char * nm_dhcp_dhclient_create_config (const char *interface, gboolean is_ip6, GBytes *client_id, const char *anycast_addr, const char *hostname, - const char *fqdn, + gboolean use_fqdn, const char *orig_path, const char *orig_contents, GBytes **out_new_client_id) @@ -258,8 +283,10 @@ nm_dhcp_dhclient_create_config (const char *interface, char **lines, **line; gboolean in_alsoreq = FALSE; gboolean in_req = FALSE; + char intf[IFNAMSIZ]; g_string_append_printf (new_contents, _("# Merged from %s\n\n"), orig_path); + intf[0] = '\0'; lines = g_strsplit_set (orig_contents, "\n\r", 0); for (line = lines; lines && *line; line++) { @@ -268,6 +295,20 @@ nm_dhcp_dhclient_create_config (const char *interface, if (!strlen (g_strstrip (p))) continue; + if ( !intf[0] + && g_str_has_prefix (p, "interface")) { + if (read_interface (p, intf, sizeof (intf))) + continue; + } + + if (intf[0] && strchr (p, '}')) { + intf[0] = '\0'; + continue; + } + + if (intf[0] && !nm_streq (intf, interface)) + continue; + if (!strncmp (p, CLIENTID_TAG, strlen (CLIENTID_TAG))) { /* Override config file "dhcp-client-id" and use one from the connection */ if (client_id) @@ -279,7 +320,7 @@ nm_dhcp_dhclient_create_config (const char *interface, } /* Override config file hostname and use one from the connection */ - if (hostname || fqdn) { + if (hostname) { if (strncmp (p, HOSTNAME4_TAG, strlen (HOSTNAME4_TAG)) == 0) continue; if (strncmp (p, FQDN_TAG, strlen (FQDN_TAG)) == 0) @@ -339,7 +380,7 @@ nm_dhcp_dhclient_create_config (const char *interface, add_request (reqs, "dhcp6.domain-search"); add_request (reqs, "dhcp6.client-id"); } else { - add_ip4_config (new_contents, client_id, hostname, fqdn); + add_ip4_config (new_contents, client_id, hostname, use_fqdn); add_request (reqs, "rfc3442-classless-static-routes"); add_request (reqs, "ms-classless-static-routes"); add_request (reqs, "static-routes"); diff --git a/src/dhcp/nm-dhcp-dhclient-utils.h b/src/dhcp/nm-dhcp-dhclient-utils.h index 83d5a23d..994b1b9f 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.h +++ b/src/dhcp/nm-dhcp-dhclient-utils.h @@ -19,15 +19,15 @@ #ifndef __NETWORKMANAGER_DHCP_DHCLIENT_UTILS_H__ #define __NETWORKMANAGER_DHCP_DHCLIENT_UTILS_H__ -#include <nm-setting-ip4-config.h> -#include <nm-setting-ip6-config.h> +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" char *nm_dhcp_dhclient_create_config (const char *interface, gboolean is_ip6, GBytes *client_id, const char *anycast_addr, const char *hostname, - const char *fqdn, + gboolean use_fqdn, const char *orig_path, const char *orig_contents, GBytes **out_new_client_id); diff --git a/src/dhcp/nm-dhcp-dhclient.c b/src/dhcp/nm-dhcp-dhclient.c index 64d93744..a56e5a3c 100644 --- a/src/dhcp/nm-dhcp-dhclient.c +++ b/src/dhcp/nm-dhcp-dhclient.c @@ -182,7 +182,7 @@ merge_dhclient_config (NMDhcpDhclient *self, GBytes *client_id, const char *anycast_addr, const char *hostname, - const char *fqdn, + gboolean use_fqdn, const char *orig_path, GBytes **out_new_client_id, GError **error) @@ -206,7 +206,7 @@ merge_dhclient_config (NMDhcpDhclient *self, if (is_ip6 && hostname && !strchr (hostname, '.')) _LOGW ("hostname is not a FQDN, it will be ignored"); - new = nm_dhcp_dhclient_create_config (iface, is_ip6, client_id, anycast_addr, hostname, fqdn, orig_path, orig, out_new_client_id); + new = nm_dhcp_dhclient_create_config (iface, is_ip6, client_id, anycast_addr, hostname, use_fqdn, orig_path, orig, out_new_client_id); g_assert (new); success = g_file_set_contents (conf_file, new, -1, error); g_free (new); @@ -294,7 +294,7 @@ create_dhclient_config (NMDhcpDhclient *self, GBytes *client_id, const char *dhcp_anycast_addr, const char *hostname, - const char *fqdn, + gboolean use_fqdn, GBytes **out_new_client_id) { char *orig = NULL, *new = NULL; @@ -314,7 +314,7 @@ create_dhclient_config (NMDhcpDhclient *self, error = NULL; success = merge_dhclient_config (self, iface, new, is_ip6, client_id, dhcp_anycast_addr, - hostname, fqdn, orig, out_new_client_id, &error); + hostname, use_fqdn, orig, out_new_client_id, &error); if (!success) { _LOGW ("error creating dhclient configuration: %s", error->message); g_error_free (error); @@ -342,6 +342,8 @@ dhclient_start (NMDhcpClient *client, char *binary_name, *cmd_str, *pid_file = NULL, *system_bus_address_env = NULL; gboolean ipv6, success; char *escaped, *preferred_leasefile_path = NULL; + guint32 timeout; + char timeout_str[64]; g_return_val_if_fail (priv->pid_file == NULL, FALSE); @@ -444,6 +446,17 @@ dhclient_start (NMDhcpClient *client, g_ptr_array_add (argv, (gpointer) priv->conf_file); } + /* Specify a timeout longer than configuration's one, + * so that dhclient doesn't send back a FAIL event before + * that time. + */ + timeout = nm_dhcp_client_get_timeout (client); + if (timeout >= 60) { + timeout = timeout < G_MAXINT32 ? timeout + 1 : G_MAXINT32; + g_ptr_array_add (argv, (gpointer) "-timeout"); + g_ptr_array_add (argv, (gpointer) nm_sprintf_buf (timeout_str, "%u", (unsigned) timeout)); + } + /* 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. @@ -492,17 +505,18 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self); GBytes *client_id; gs_unref_bytes GBytes *new_client_id = NULL; - const char *iface, *uuid, *hostname, *fqdn; + const char *iface, *uuid, *hostname; gboolean success = FALSE; + gboolean use_fqdn; iface = nm_dhcp_client_get_iface (client); uuid = nm_dhcp_client_get_uuid (client); client_id = nm_dhcp_client_get_client_id (client); hostname = nm_dhcp_client_get_hostname (client); - fqdn = nm_dhcp_client_get_fqdn (client); + use_fqdn = nm_dhcp_client_get_use_fqdn (client); priv->conf_file = create_dhclient_config (self, iface, FALSE, uuid, client_id, dhcp_anycast_addr, - hostname, fqdn, &new_client_id); + hostname, use_fqdn, &new_client_id); if (priv->conf_file) { if (new_client_id) nm_dhcp_client_set_client_id (client, new_client_id); @@ -530,7 +544,7 @@ ip6_start (NMDhcpClient *client, uuid = nm_dhcp_client_get_uuid (client); hostname = nm_dhcp_client_get_hostname (client); - priv->conf_file = create_dhclient_config (self, iface, TRUE, uuid, NULL, dhcp_anycast_addr, hostname, NULL, NULL); + priv->conf_file = create_dhclient_config (self, iface, TRUE, uuid, NULL, dhcp_anycast_addr, hostname, TRUE, NULL); if (!priv->conf_file) { _LOGW ("error creating dhclient configuration file"); return FALSE; diff --git a/src/dhcp/nm-dhcp-dhcpcd.c b/src/dhcp/nm-dhcp-dhcpcd.c index c8643881..66a31acf 100644 --- a/src/dhcp/nm-dhcp-dhcpcd.c +++ b/src/dhcp/nm-dhcp-dhcpcd.c @@ -88,9 +88,8 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last GPtrArray *argv = NULL; pid_t pid = -1; GError *error = NULL; - char *pid_contents = NULL, *binary_name, *cmd_str, *dot; - const char *iface, *dhcpcd_path, *hostname, *fqdn; - gs_free char *prefix = NULL; + char *pid_contents = NULL, *binary_name, *cmd_str; + const char *iface, *dhcpcd_path, *hostname; g_return_val_if_fail (priv->pid_file == NULL, FALSE); @@ -138,22 +137,17 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last #endif hostname = nm_dhcp_client_get_hostname (client); - fqdn = nm_dhcp_client_get_fqdn (client); - - if (fqdn) { - g_ptr_array_add (argv, (gpointer) "-h"); - g_ptr_array_add (argv, (gpointer) fqdn); - g_ptr_array_add (argv, (gpointer) "-F"); - g_ptr_array_add (argv, (gpointer) "both"); - } else if (hostname) { - prefix = strdup (hostname); - dot = strchr (prefix, '.'); - /* get rid of the domain */ - if (dot) - *dot = '\0'; - - g_ptr_array_add (argv, (gpointer) "-h"); /* Send hostname to DHCP server */ - g_ptr_array_add (argv, (gpointer) prefix); + + if (hostname) { + if (nm_dhcp_client_get_use_fqdn (client)) { + g_ptr_array_add (argv, (gpointer) "-h"); + g_ptr_array_add (argv, (gpointer) hostname); + g_ptr_array_add (argv, (gpointer) "-F"); + g_ptr_array_add (argv, (gpointer) "both"); + } else { + g_ptr_array_add (argv, (gpointer) "-h"); + g_ptr_array_add (argv, (gpointer) hostname); + } } g_ptr_array_add (argv, (gpointer) iface); diff --git a/src/dhcp/nm-dhcp-listener.c b/src/dhcp/nm-dhcp-listener.c index 56bd9d17..ca697ab3 100644 --- a/src/dhcp/nm-dhcp-listener.c +++ b/src/dhcp/nm-dhcp-listener.c @@ -92,7 +92,7 @@ NM_DEFINE_SINGLETON_GETTER (NMDhcpListener, nm_dhcp_listener_get, NM_TYPE_DHCP_L const NMDhcpListener *_self = (self); \ char _prefix[64]; \ \ - nm_log ((level), (_NMLOG_DOMAIN), \ + nm_log ((level), (_NMLOG_DOMAIN), NULL, NULL, \ "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ (_self != singleton_instance \ ? nm_sprintf_buf (_prefix, "%s[%p]", _NMLOG_PREFIX_NAME, _self) \ diff --git a/src/dhcp/nm-dhcp-manager.c b/src/dhcp/nm-dhcp-manager.c index 9c1fbb38..fff9f9ec 100644 --- a/src/dhcp/nm-dhcp-manager.c +++ b/src/dhcp/nm-dhcp-manager.c @@ -163,7 +163,7 @@ client_start (NMDhcpManager *self, guint32 timeout, const char *dhcp_anycast_addr, const char *hostname, - const char *fqdn, + gboolean hostname_use_fqdn, gboolean info_only, NMSettingIP6ConfigPrivacy privacy, const char *last_ip4_address, @@ -209,7 +209,7 @@ client_start (NMDhcpManager *self, if (ipv6) success = nm_dhcp_client_start_ip6 (client, dhcp_anycast_addr, ipv6_ll_addr, hostname, info_only, privacy, needed_prefixes); else - success = nm_dhcp_client_start_ip4 (client, dhcp_client_id, dhcp_anycast_addr, hostname, fqdn, last_ip4_address); + success = nm_dhcp_client_start_ip4 (client, dhcp_client_id, dhcp_anycast_addr, hostname, hostname_use_fqdn, last_ip4_address); if (!success) { remove_client (self, client); @@ -219,15 +219,6 @@ client_start (NMDhcpManager *self, return client; } -static const char * -get_send_hostname (NMDhcpManager *self, const char *setting_hostname) -{ - NMDhcpManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (self); - - /* Always prefer the explicit dhcp-send-hostname if given */ - return setting_hostname ? setting_hostname : priv->default_hostname; -} - /* Caller owns a reference to the NMDhcpClient on return */ NMDhcpClient * nm_dhcp_manager_start_ip4 (NMDhcpManager *self, @@ -244,18 +235,41 @@ nm_dhcp_manager_start_ip4 (NMDhcpManager *self, const char *dhcp_anycast_addr, const char *last_ip_address) { + NMDhcpManagerPrivate *priv; const char *hostname = NULL; - const char *fqdn = NULL; + gs_free char *hostname_tmp = NULL; + gboolean use_fqdn = FALSE; + char *dot; g_return_val_if_fail (NM_IS_DHCP_MANAGER (self), NULL); + priv = NM_DHCP_MANAGER_GET_PRIVATE (self); if (send_hostname) { - hostname = get_send_hostname (self, dhcp_hostname); - fqdn = dhcp_fqdn; + /* Use, in order of preference: + * 1. FQDN from configuration + * 2. hostname from configuration + * 3. system hostname (only host part) + */ + if (dhcp_fqdn) { + hostname = dhcp_fqdn; + use_fqdn = TRUE; + } else if (dhcp_hostname) + hostname = dhcp_hostname; + else { + hostname = priv->default_hostname; + if (hostname) { + hostname_tmp = g_strdup (hostname); + dot = strchr (hostname_tmp, '.'); + if (dot) + *dot = '\0'; + hostname = hostname_tmp; + } + } } + return client_start (self, iface, ifindex, hwaddr, uuid, priority, FALSE, NULL, dhcp_client_id, timeout, dhcp_anycast_addr, hostname, - fqdn, FALSE, 0, last_ip_address, 0); + use_fqdn, FALSE, 0, last_ip_address, 0); } /* Caller owns a reference to the NMDhcpClient on return */ @@ -275,14 +289,18 @@ nm_dhcp_manager_start_ip6 (NMDhcpManager *self, NMSettingIP6ConfigPrivacy privacy, guint needed_prefixes) { + NMDhcpManagerPrivate *priv; const char *hostname = NULL; g_return_val_if_fail (NM_IS_DHCP_MANAGER (self), NULL); + priv = NM_DHCP_MANAGER_GET_PRIVATE (self); - if (send_hostname) - hostname = get_send_hostname (self, dhcp_hostname); + if (send_hostname) { + /* Always prefer the explicit dhcp-hostname if given */ + hostname = dhcp_hostname ? dhcp_hostname : priv->default_hostname; + } return client_start (self, iface, ifindex, hwaddr, uuid, priority, TRUE, - ll_addr, NULL, timeout, dhcp_anycast_addr, hostname, NULL, info_only, + ll_addr, NULL, timeout, dhcp_anycast_addr, hostname, TRUE, info_only, privacy, NULL, needed_prefixes); } diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/dhcp/nm-dhcp-systemd.c index 7067275b..aa902701 100644 --- a/src/dhcp/nm-dhcp-systemd.c +++ b/src/dhcp/nm-dhcp-systemd.c @@ -580,7 +580,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last const uint8_t *client_id = NULL; size_t client_id_len = 0; struct in_addr last_addr = { 0 }; - const char *hostname, *fqdn; + const char *hostname; int r, i; gboolean success = FALSE; guint16 arp_type; @@ -687,28 +687,13 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last hostname = nm_dhcp_client_get_hostname (client); if (hostname) { - char *prefix, *dot; - - prefix = strdup (hostname); - dot = strchr (prefix, '.'); - /* get rid of the domain */ - if (dot) - *dot = '\0'; - - r = sd_dhcp_client_set_hostname (priv->client4, prefix); - free (prefix); - - if (r < 0) { - _LOGW ("failed to set DHCP hostname (%d)", r); - goto error; - } - } - - fqdn = nm_dhcp_client_get_fqdn (client); - if (fqdn) { - r = sd_dhcp_client_set_hostname (priv->client4, fqdn); + /* FIXME: sd-dhcp decides which hostname/FQDN option to send (12 or 81) + * only based on whether the hostname has a domain part or not. At the + * moment there is no way to force one or another. + */ + r = sd_dhcp_client_set_hostname (priv->client4, hostname); if (r < 0) { - _LOGW ("failed to set DHCP FQDN (%d)", r); + _LOGW ("failed to set DHCP hostname to '%s' (%d)", hostname, r); goto error; } } diff --git a/src/dhcp/nm-dhcp-utils.h b/src/dhcp/nm-dhcp-utils.h index b45c5e89..05982b16 100644 --- a/src/dhcp/nm-dhcp-utils.h +++ b/src/dhcp/nm-dhcp-utils.h @@ -21,8 +21,8 @@ #include <stdlib.h> -#include <nm-ip4-config.h> -#include <nm-ip6-config.h> +#include "nm-ip4-config.h" +#include "nm-ip6-config.h" NMIP4Config *nm_dhcp_utils_ip4_config_from_options (int ifindex, const char *iface, diff --git a/src/dhcp/tests/test-dhcp-dhclient.c b/src/dhcp/tests/test-dhcp-dhclient.c index f4cf9c9f..40a3e072 100644 --- a/src/dhcp/tests/test-dhcp-dhclient.c +++ b/src/dhcp/tests/test-dhcp-dhclient.c @@ -40,7 +40,7 @@ test_config (const char *orig, const char *expected, gboolean ipv6, const char *hostname, - const char *fqdn, + gboolean use_fqdn, const char *dhcp_client_id, GBytes *expected_new_client_id, const char *iface, @@ -60,7 +60,7 @@ test_config (const char *orig, client_id, anycast_addr, hostname, - fqdn, + use_fqdn, "/path/to/dhclient.conf", orig, &new_client_id); @@ -105,7 +105,7 @@ static const char *orig_missing_expected = \ static void test_orig_missing (void) { - test_config (NULL, orig_missing_expected, FALSE, NULL, NULL, NULL, NULL, "eth0", NULL); + test_config (NULL, orig_missing_expected, FALSE, NULL, FALSE, NULL, NULL, "eth0", NULL); } /*****************************************************************************/ @@ -134,7 +134,7 @@ static void test_override_client_id (void) { test_config (override_client_id_orig, override_client_id_expected, - FALSE, NULL, NULL, + FALSE, NULL, FALSE, "11:22:33:44:55:66", NULL, "eth0", @@ -163,7 +163,7 @@ static void test_quote_client_id (void) { test_config (NULL, quote_client_id_expected, - FALSE, NULL, NULL, + FALSE, NULL, FALSE, "1234", NULL, "eth0", @@ -192,7 +192,7 @@ static void test_ascii_client_id (void) { test_config (NULL, ascii_client_id_expected, - FALSE, NULL, NULL, + FALSE, NULL, FALSE, "qb:cd:ef:12:34:56", NULL, "eth0", @@ -221,7 +221,7 @@ static void test_hex_single_client_id (void) { test_config (NULL, hex_single_client_id_expected, - FALSE, NULL, NULL, + FALSE, NULL, FALSE, "ab:cd:e:12:34:56", NULL, "eth0", @@ -258,7 +258,7 @@ test_existing_hex_client_id (void) new_client_id = g_bytes_new (bytes, sizeof (bytes)); test_config (existing_hex_client_id_orig, existing_hex_client_id_expected, - FALSE, NULL, NULL, + FALSE, NULL, FALSE, NULL, new_client_id, "eth0", @@ -298,7 +298,7 @@ test_existing_ascii_client_id (void) 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, - FALSE, NULL, NULL, + FALSE, NULL, FALSE, NULL, new_client_id, "eth0", @@ -327,8 +327,8 @@ static void test_fqdn (void) { test_config (NULL, fqdn_expected, - FALSE, NULL, - "foo.bar.com", NULL, + FALSE, "foo.bar.com", + TRUE, NULL, NULL, "eth0", NULL); @@ -367,8 +367,8 @@ test_fqdn_options_override (void) { test_config (fqdn_options_override_orig, fqdn_options_override_expected, - FALSE, NULL, - "example2.com", NULL, + FALSE, "example2.com", + TRUE, NULL, NULL, "eth0", NULL); @@ -400,7 +400,7 @@ static void test_override_hostname (void) { test_config (override_hostname_orig, override_hostname_expected, - FALSE, "blahblah", NULL, + FALSE, "blahblah", FALSE, NULL, NULL, "eth0", @@ -429,7 +429,7 @@ static void test_override_hostname6 (void) { test_config (override_hostname6_orig, override_hostname6_expected, - TRUE, "blahblah.local", NULL, + TRUE, "blahblah.local", TRUE, NULL, NULL, "eth0", @@ -452,7 +452,7 @@ test_nonfqdn_hostname6 (void) /* Non-FQDN hostname can't be used with dhclient */ test_config (NULL, nonfqdn_hostname6_expected, TRUE, "blahblah", - NULL, NULL, + TRUE, NULL, NULL, "eth0", NULL); @@ -487,7 +487,7 @@ test_existing_alsoreq (void) { test_config (existing_alsoreq_orig, existing_alsoreq_expected, FALSE, NULL, - NULL, + FALSE, NULL, NULL, "eth0", @@ -526,7 +526,7 @@ test_existing_req (void) { test_config (existing_req_orig, existing_req_expected, FALSE, NULL, - NULL, + FALSE, NULL, NULL, "eth0", @@ -565,7 +565,7 @@ static void test_existing_multiline_alsoreq (void) { test_config (existing_multiline_alsoreq_orig, existing_multiline_alsoreq_expected, - FALSE, NULL, NULL, + FALSE, NULL, FALSE, NULL, NULL, "eth0", @@ -744,6 +744,95 @@ test_write_existing_commented_duid (void) /*****************************************************************************/ +static const char *interface1_orig = \ + "interface \"eth0\" {\n" + " also request my-option;\n" + " initial-delay 5;\n" + "}\n" + "interface \"eth1\" {\n" + " also request another-option;\n" + " initial-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" + "\n"; + +static void +test_interface1 (void) +{ + test_config (interface1_orig, interface1_expected, + FALSE, NULL, FALSE, + NULL, + NULL, + "eth0", + NULL); +} + +/*****************************************************************************/ + +static const char *interface2_orig = \ + "interface eth0 {\n" + " also request my-option;\n" + " initial-delay 5;\n" + " }\n" + "interface eth1 {\n" + " initial-delay 0;\n" + " request 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" + "\n"; + +static void +test_interface2 (void) +{ + test_config (interface2_orig, interface2_expected, + FALSE, NULL, FALSE, + NULL, + NULL, + "eth1", + NULL); +} + +/*****************************************************************************/ + static void test_read_lease_ip4_config_basic (void) { @@ -891,6 +980,8 @@ main (int argc, char **argv) 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/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); |