diff --git a/SOURCES/0040-rh1255507-dhcp-fqdn.patch b/SOURCES/0040-rh1255507-dhcp-fqdn.patch new file mode 100644 index 0000000..27c4497 --- /dev/null +++ b/SOURCES/0040-rh1255507-dhcp-fqdn.patch @@ -0,0 +1,1221 @@ +From 8ebc427d13b7aabc22c6431432207649ca58908b Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 13 Oct 2015 14:10:01 +0200 +Subject: [PATCH 1/7] libnm-core: add a 'dhcp-fqdn' property to + NMSettingIP4Config + +The property contains the fully qualified domain name to be sent to +DHCP server using the FQDN option. The property is mutually exclusive +with 'dhcp-hostname'. + +Note: differently from upstream, libnm does not export the getter for +the property, in order to avoid symbol versioning problems. + +(cherry picked from commit cb40194532208108c3fb5cbf3c5b12a749fb6ad8) +--- + libnm-core/nm-core-internal.h | 2 ++ + libnm-core/nm-setting-ip-config.c | 2 ++ + libnm-core/nm-setting-ip4-config.c | 69 ++++++++++++++++++++++++++++++++++++++ + libnm-core/nm-setting-ip4-config.h | 1 + + libnm-core/tests/test-general.c | 1 + + 5 files changed, 75 insertions(+) + +diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h +index 73a379c..86b1aa3 100644 +--- a/libnm-core/nm-core-internal.h ++++ b/libnm-core/nm-core-internal.h +@@ -157,6 +157,8 @@ GByteArray *nm_utils_rsa_key_encrypt (const guint8 *data, + int nm_utils_bond_mode_string_to_int (const char *mode); + const char *nm_utils_bond_mode_int_to_string (int mode); + ++const char *nm_setting_ip4_config_get_dhcp_fqdn (NMSettingIP4Config *setting); ++ + gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback); + + gboolean _nm_dbus_error_has_name (GError *error, +diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c +index 4b73d5f..71e4e8c 100644 +--- a/libnm-core/nm-setting-ip-config.c ++++ b/libnm-core/nm-setting-ip-config.c +@@ -2304,6 +2304,8 @@ nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class) + * + * If the #NMSettingIPConfig:dhcp-send-hostname property is %TRUE, then the + * specified name will be sent to the DHCP server when acquiring a lease. ++ * This property and #NMSettingIP4Config:dhcp-fqdn are mutually exclusive and ++ * cannot be set at the same time. + **/ + g_object_class_install_property + (object_class, PROP_DHCP_HOSTNAME, +diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c +index 81cc1f8..14faf79 100644 +--- a/libnm-core/nm-setting-ip4-config.c ++++ b/libnm-core/nm-setting-ip4-config.c +@@ -59,11 +59,13 @@ NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP4_CONFIG) + + typedef struct { + char *dhcp_client_id; ++ char *dhcp_fqdn; + } NMSettingIP4ConfigPrivate; + + enum { + PROP_0, + PROP_DHCP_CLIENT_ID, ++ PROP_DHCP_FQDN, + + LAST_PROP + }; +@@ -99,6 +101,23 @@ nm_setting_ip4_config_get_dhcp_client_id (NMSettingIP4Config *setting) + return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dhcp_client_id; + } + ++/** ++ * nm_setting_ip4_config_get_dhcp_fqdn: ++ * @setting: the #NMSettingIP4Config ++ * ++ * Returns the value contained in the #NMSettingIP4Config:dhcp-fqdn ++ * property. ++ * ++ * Returns: the configured FQDN to send to the DHCP server ++ **/ ++const char * ++nm_setting_ip4_config_get_dhcp_fqdn (NMSettingIP4Config *setting) ++{ ++ g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), NULL); ++ ++ return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dhcp_fqdn; ++} ++ + static gboolean + verify (NMSetting *setting, NMConnection *connection, GError **error) + { +@@ -180,6 +199,31 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) + return FALSE; + } + ++ if (priv->dhcp_fqdn && !*priv->dhcp_fqdn) { ++ g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, ++ _("property is empty")); ++ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DHCP_FQDN); ++ return FALSE; ++ } ++ ++ if (priv->dhcp_fqdn && !strchr (priv->dhcp_fqdn, '.')) { ++ g_set_error (error, ++ NM_CONNECTION_ERROR, ++ NM_CONNECTION_ERROR_INVALID_PROPERTY, ++ _("'%s' is not a valid FQDN"), priv->dhcp_fqdn); ++ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DHCP_FQDN); ++ return FALSE; ++ } ++ ++ if (priv->dhcp_fqdn && nm_setting_ip_config_get_dhcp_hostname (s_ip)) { ++ g_set_error_literal (error, ++ NM_CONNECTION_ERROR, ++ NM_CONNECTION_ERROR_INVALID_PROPERTY, ++ _("property cannot be set when dhcp-hostname is also set")); ++ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DHCP_FQDN); ++ return FALSE; ++ } ++ + return TRUE; + } + +@@ -194,6 +238,7 @@ finalize (GObject *object) + NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (object); + + g_free (priv->dhcp_client_id); ++ g_free (priv->dhcp_fqdn); + + G_OBJECT_CLASS (nm_setting_ip4_config_parent_class)->finalize (object); + } +@@ -209,6 +254,10 @@ set_property (GObject *object, guint prop_id, + g_free (priv->dhcp_client_id); + priv->dhcp_client_id = g_value_dup_string (value); + break; ++ case PROP_DHCP_FQDN: ++ g_free (priv->dhcp_fqdn); ++ priv->dhcp_fqdn = g_value_dup_string (value); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -225,6 +274,9 @@ get_property (GObject *object, guint prop_id, + case PROP_DHCP_CLIENT_ID: + g_value_set_string (value, nm_setting_ip4_config_get_dhcp_client_id (s_ip4)); + break; ++ case PROP_DHCP_FQDN: ++ g_value_set_string (value, nm_setting_ip4_config_get_dhcp_fqdn (s_ip4)); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -600,6 +652,23 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + ++ /** ++ * NMSettingIP4Config:dhcp-fqdn: ++ * ++ * If the #NMSettingIPConfig:dhcp-send-hostname property is %TRUE, then the ++ * specified FQDN will be sent to the DHCP server when acquiring a lease. This ++ * property and #NMSettingIPConfig:dhcp-hostname are mutually exclusive and ++ * cannot be set at the same time. ++ * ++ * Since: 1.0.6-rhel7.2 ++ */ ++ g_object_class_install_property ++ (object_class, PROP_DHCP_FQDN, ++ g_param_spec_string (NM_SETTING_IP4_CONFIG_DHCP_FQDN, "", "", ++ NULL, ++ G_PARAM_READWRITE | ++ G_PARAM_STATIC_STRINGS)); ++ + /* IP4-specific property overrides */ + + /* ---dbus--- +diff --git a/libnm-core/nm-setting-ip4-config.h b/libnm-core/nm-setting-ip4-config.h +index e944dfe..ef23649 100644 +--- a/libnm-core/nm-setting-ip4-config.h ++++ b/libnm-core/nm-setting-ip4-config.h +@@ -41,6 +41,7 @@ G_BEGIN_DECLS + #define NM_SETTING_IP4_CONFIG_SETTING_NAME "ipv4" + + #define NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID "dhcp-client-id" ++#define NM_SETTING_IP4_CONFIG_DHCP_FQDN "dhcp-fqdn" + + /** + * NM_SETTING_IP4_CONFIG_METHOD_AUTO: +diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c +index 42b55c1..e517a44 100644 +--- a/libnm-core/tests/test-general.c ++++ b/libnm-core/tests/test-general.c +@@ -2003,6 +2003,7 @@ test_connection_diff_a_only (void) + { NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, NM_SETTING_DIFF_RESULT_IN_A }, + { NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A }, + { NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A }, ++ { NM_SETTING_IP4_CONFIG_DHCP_FQDN, NM_SETTING_DIFF_RESULT_IN_A }, + { NM_SETTING_IP_CONFIG_NEVER_DEFAULT, NM_SETTING_DIFF_RESULT_IN_A }, + { NM_SETTING_IP_CONFIG_MAY_FAIL, NM_SETTING_DIFF_RESULT_IN_A }, + { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN }, +-- +2.5.5 + +From 23a942115b0091ab3df0f5c22377d53e8d9d3fa0 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Fri, 16 Oct 2015 11:55:58 +0200 +Subject: [PATCH 2/7] ifcfg-rh: support the DHCP_FQDN variable + +Add support for the DHCP_FQDN ifcfg-rh variable which maps to the +ipv4.dhcp-fqdn property. + +(cherry picked from commit 5002342d94a1b166a2c577055e4160c98e30be87) +--- + libnm-core/nm-setting-ip4-config.c | 11 ++++++++++- + src/settings/plugins/ifcfg-rh/reader.c | 11 ++++++++++- + src/settings/plugins/ifcfg-rh/writer.c | 5 +++++ + 3 files changed, 25 insertions(+), 2 deletions(-) + +diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c +index 14faf79..7d37ac2 100644 +--- a/libnm-core/nm-setting-ip4-config.c ++++ b/libnm-core/nm-setting-ip4-config.c +@@ -601,7 +601,8 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) + /* ---ifcfg-rh--- + * property: dhcp-hostname + * variable: DHCP_HOSTNAME +- * description: Hostname to send to the DHCP server. ++ * description: Hostname to send to the DHCP server. When both DHCP_HOSTNAME and ++ * DHCP_FQDN are specified only the latter is used. + * ---end--- + */ + +@@ -662,6 +663,14 @@ nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class) + * + * Since: 1.0.6-rhel7.2 + */ ++ /* ---ifcfg-rh--- ++ * property: dhcp-fqdn ++ * variable: DHCP_FQDN ++ * description: FQDN to send to the DHCP server. When both DHCP_HOSTNAME and ++ * DHCP_FQDN are specified only the latter is used. ++ * example: DHCP_FQDN=foo.bar.com ++ * ---end--- ++ */ + g_object_class_install_property + (object_class, PROP_DHCP_FQDN, + g_param_spec_string (NM_SETTING_IP4_CONFIG_DHCP_FQDN, "", "", +diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c +index a1b2813..9e644c1 100644 +--- a/src/settings/plugins/ifcfg-rh/reader.c ++++ b/src/settings/plugins/ifcfg-rh/reader.c +@@ -990,10 +990,19 @@ make_ip4_setting (shvarFile *ifcfg, + /* Handle DHCP settings */ + if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { + value = svGetValue (ifcfg, "DHCP_HOSTNAME", FALSE); +- if (value && strlen (value)) ++ if (value && *value) + g_object_set (s_ip4, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, value, NULL); + g_free (value); + ++ value = svGetValue (ifcfg, "DHCP_FQDN", FALSE); ++ if (value && *value) { ++ g_object_set (s_ip4, ++ NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, NULL, ++ NM_SETTING_IP4_CONFIG_DHCP_FQDN, value, ++ NULL); ++ } ++ g_free (value); ++ + g_object_set (s_ip4, + NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, + svTrueValue (ifcfg, "DHCP_SEND_HOSTNAME", TRUE), +diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c +index 4f9498b..f88df5e 100644 +--- a/src/settings/plugins/ifcfg-rh/writer.c ++++ b/src/settings/plugins/ifcfg-rh/writer.c +@@ -2086,6 +2086,10 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) + if (value) + svSetValue (ifcfg, "DHCP_HOSTNAME", value, FALSE); + ++ value = nm_setting_ip4_config_get_dhcp_fqdn (NM_SETTING_IP4_CONFIG (s_ip4)); ++ if (value) ++ svSetValue (ifcfg, "DHCP_FQDN", value, FALSE); ++ + /* Missing DHCP_SEND_HOSTNAME means TRUE, and we prefer not write it explicitly + * in that case, because it is NM-specific variable + */ +@@ -2656,6 +2660,7 @@ write_connection (NMConnection *connection, + + if (!utils_ignore_ip_config (connection)) { + svSetValue (ifcfg, "DHCP_HOSTNAME", NULL, FALSE); ++ svSetValue (ifcfg, "DHCP_FQDN", NULL, FALSE); + + if (!write_ip4_setting (connection, ifcfg, error)) + goto out; +-- +2.5.5 + +From 2bcf63c65b9d8ed94e90ba00ac9e56181dbeba13 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 13 Oct 2015 14:21:59 +0200 +Subject: [PATCH 3/7] cli: add ipv4.dhcp-fqdn property + +(cherry picked from commit cba0f4e3c4f70a291d212f30772758dcc114ef17) +--- + clients/cli/settings.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/clients/cli/settings.c b/clients/cli/settings.c +index efac7b2..3e0f23e 100644 +--- a/clients/cli/settings.c ++++ b/clients/cli/settings.c +@@ -280,8 +280,9 @@ NmcOutputField nmc_fields_setting_ip4_config[] = { + SETTING_FIELD (NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, 15), /* 10 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, 19), /* 11 */ + SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, 14), /* 12 */ +- SETTING_FIELD (NM_SETTING_IP_CONFIG_NEVER_DEFAULT, 15), /* 13 */ +- SETTING_FIELD (NM_SETTING_IP_CONFIG_MAY_FAIL, 12), /* 14 */ ++ SETTING_FIELD (NM_SETTING_IP4_CONFIG_DHCP_FQDN, 20), /* 13 */ ++ SETTING_FIELD (NM_SETTING_IP_CONFIG_NEVER_DEFAULT, 15), /* 14 */ ++ SETTING_FIELD (NM_SETTING_IP_CONFIG_MAY_FAIL, 12), /* 15 */ + {NULL, NULL, 0, NULL, FALSE, FALSE, 0} + }; + #define NMC_FIELDS_SETTING_IP4_CONFIG_ALL "name"","\ +@@ -297,6 +298,7 @@ NmcOutputField nmc_fields_setting_ip4_config[] = { + NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID","\ + NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME","\ + NM_SETTING_IP_CONFIG_DHCP_HOSTNAME","\ ++ NM_SETTING_IP4_CONFIG_DHCP_FQDN","\ + NM_SETTING_IP_CONFIG_NEVER_DEFAULT","\ + NM_SETTING_IP_CONFIG_MAY_FAIL + #define NMC_FIELDS_SETTING_IP4_CONFIG_COMMON NMC_FIELDS_SETTING_IP4_CONFIG_ALL +@@ -1351,6 +1353,7 @@ DEFINE_GETTER (nmc_property_ipv4_get_ignore_auto_dns, NM_SETTING_IP_CONFIG_IGNOR + DEFINE_GETTER (nmc_property_ipv4_get_dhcp_client_id, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID) + DEFINE_GETTER (nmc_property_ipv4_get_dhcp_send_hostname, NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME) + DEFINE_GETTER (nmc_property_ipv4_get_dhcp_hostname, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME) ++DEFINE_GETTER (nmc_property_ipv4_get_dhcp_fqdn, NM_SETTING_IP4_CONFIG_DHCP_FQDN) + DEFINE_GETTER (nmc_property_ipv4_get_never_default, NM_SETTING_IP_CONFIG_NEVER_DEFAULT) + DEFINE_GETTER (nmc_property_ipv4_get_may_fail, NM_SETTING_IP_CONFIG_MAY_FAIL) + +@@ -5750,6 +5753,13 @@ nmc_properties_init (void) + NULL, + NULL, + NULL); ++ nmc_add_prop_funcs (GLUE (IP4_CONFIG, DHCP_FQDN), ++ nmc_property_ipv4_get_dhcp_fqdn, ++ nmc_property_set_string, ++ NULL, ++ NULL, ++ NULL, ++ NULL); + nmc_add_prop_funcs (GLUE_IP (4, NEVER_DEFAULT), + nmc_property_ipv4_get_never_default, + nmc_property_set_bool, +@@ -7042,8 +7052,10 @@ setting_ip4_config_details (NMSetting *setting, NmCli *nmc, const char *one_pro + set_val_str (arr, 10, nmc_property_ipv4_get_dhcp_client_id (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 11, nmc_property_ipv4_get_dhcp_send_hostname (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 12, nmc_property_ipv4_get_dhcp_hostname (setting, NMC_PROPERTY_GET_PRETTY)); +- set_val_str (arr, 13, nmc_property_ipv4_get_never_default (setting, NMC_PROPERTY_GET_PRETTY)); +- set_val_str (arr, 14, nmc_property_ipv4_get_may_fail (setting, NMC_PROPERTY_GET_PRETTY)); ++ set_val_str (arr, 13, nmc_property_ipv4_get_dhcp_fqdn (setting, NMC_PROPERTY_GET_PRETTY)); ++ set_val_str (arr, 14, nmc_property_ipv4_get_never_default (setting, NMC_PROPERTY_GET_PRETTY)); ++ set_val_str (arr, 15, nmc_property_ipv4_get_may_fail (setting, NMC_PROPERTY_GET_PRETTY)); ++ + g_ptr_array_add (nmc->output_data, arr); + + print_data (nmc); /* Print all data */ +-- +2.5.5 + +From 0e0a48bdf1f4f975b74dd5bb717681be94f98a55 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Mon, 19 Oct 2015 11:32:18 +0200 +Subject: [PATCH 4/7] dhcp-manager: strip hostname sent by dhcpcd + +The dhclient DHCP backend strips the domain part from the hostname +option sent to server; for consistency among different backends +uniform the dhcpcd client to do the same. + +(cherry picked from commit dbbb08eb01b750532f3dfabf1b397f0adf01f710) +--- + src/dhcp-manager/nm-dhcp-dhcpcd.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.c b/src/dhcp-manager/nm-dhcp-dhcpcd.c +index 86aba4d..b80512e 100644 +--- a/src/dhcp-manager/nm-dhcp-dhcpcd.c ++++ b/src/dhcp-manager/nm-dhcp-dhcpcd.c +@@ -39,6 +39,7 @@ + #include "nm-logging.h" + #include "NetworkManagerUtils.h" + #include "nm-dhcp-listener.h" ++#include "gsystem-local-alloc.h" + + G_DEFINE_TYPE (NMDhcpDhcpcd, nm_dhcp_dhcpcd, NM_TYPE_DHCP_CLIENT) + +@@ -65,8 +66,9 @@ 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; ++ char *pid_contents = NULL, *binary_name, *cmd_str, *dot; + const char *iface, *dhcpcd_path, *hostname; ++ gs_free char *prefix = NULL; + + g_return_val_if_fail (priv->pid_file == NULL, FALSE); + +@@ -115,8 +117,14 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last + + hostname = nm_dhcp_client_get_hostname (client); + 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) hostname ); ++ g_ptr_array_add (argv, (gpointer) prefix); + } + + g_ptr_array_add (argv, (gpointer) iface); +-- +2.5.5 + +From 242b566a4bc1637d8d87969b792ef79860a4cfaa Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Mon, 19 Oct 2015 10:42:29 +0200 +Subject: [PATCH 5/7] dhcp-manager: strip hostname sent by internal DHCP client + +The dhclient DHCP backend strips the domain part from the hostname +option sent to server; for consistency among different backends +uniform the internal client to do the same. + +(cherry picked from commit c09b12240eccd57bb1279e44a55cd76712aa8c0c) +--- + src/dhcp-manager/nm-dhcp-systemd.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/src/dhcp-manager/nm-dhcp-systemd.c b/src/dhcp-manager/nm-dhcp-systemd.c +index 2bd0d72..0c0233b 100644 +--- a/src/dhcp-manager/nm-dhcp-systemd.c ++++ b/src/dhcp-manager/nm-dhcp-systemd.c +@@ -629,7 +629,17 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last + + hostname = nm_dhcp_client_get_hostname (client); + if (hostname) { +- r = sd_dhcp_client_set_hostname (priv->client4, 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) { + nm_log_warn (LOGD_DHCP4, "(%s): failed to set DHCP hostname (%d)", iface, r); + goto error; +-- +2.5.5 + +From 05d36fa103161a7c8e9c826ce362e44c7d94a14a Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 13 Oct 2015 15:13:26 +0200 +Subject: [PATCH 6/7] dhcp4: send FQDN option when ipv4.dhcp-fqdn is set + +Modify the 3 DHCP client backends to support the new property. + +(cherry picked from commit c3573ebf2bb4958ee2ebf08e7ebac351765b92ef) +--- + src/devices/nm-device.c | 9 ++++- + src/dhcp-manager/nm-dhcp-client.c | 12 +++++++ + src/dhcp-manager/nm-dhcp-client.h | 3 ++ + src/dhcp-manager/nm-dhcp-dhclient-utils.c | 20 +++++++---- + src/dhcp-manager/nm-dhcp-dhclient-utils.h | 1 + + src/dhcp-manager/nm-dhcp-dhclient.c | 14 +++++--- + src/dhcp-manager/nm-dhcp-dhcpcd.c | 11 ++++-- + src/dhcp-manager/nm-dhcp-manager.c | 13 ++++--- + src/dhcp-manager/nm-dhcp-manager.h | 1 + + src/dhcp-manager/nm-dhcp-systemd.c | 11 +++++- + src/dhcp-manager/tests/test-dhcp-dhclient.c | 55 +++++++++++++++++++++++------ + src/nm-iface-helper.c | 3 ++ + 12 files changed, 122 insertions(+), 31 deletions(-) + +diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c +index 98d50b2..7e1444c 100644 +--- a/src/devices/nm-device.c ++++ b/src/devices/nm-device.c +@@ -3627,6 +3627,7 @@ dhcp4_start (NMDevice *self, + nm_device_get_ip4_route_metric (self), + nm_setting_ip_config_get_dhcp_send_hostname (s_ip4), + nm_setting_ip_config_get_dhcp_hostname (s_ip4), ++ nm_setting_ip4_config_get_dhcp_fqdn (NM_SETTING_IP4_CONFIG (s_ip4)), + nm_setting_ip4_config_get_dhcp_client_id (NM_SETTING_IP4_CONFIG (s_ip4)), + priv->dhcp_timeout, + priv->dhcp_anycast_address, +@@ -8302,7 +8303,7 @@ nm_device_spawn_iface_helper (NMDevice *self) + g_ptr_array_add (argv, g_strdup ("--dhcp4-required")); + + if (priv->dhcp4_client) { +- const char *hostname; ++ const char *hostname, *fqdn; + GBytes *client_id; + + client_id = nm_dhcp_client_get_client_id (priv->dhcp4_client); +@@ -8318,6 +8319,12 @@ nm_device_spawn_iface_helper (NMDevice *self) + g_ptr_array_add (argv, g_strdup ("--dhcp4-hostname")); + g_ptr_array_add (argv, g_strdup (hostname)); + } ++ ++ fqdn = nm_dhcp_client_get_fqdn (priv->dhcp4_client); ++ if (fqdn) { ++ g_ptr_array_add (argv, g_strdup ("--dhcp4-fqdn")); ++ g_ptr_array_add (argv, g_strdup (fqdn)); ++ } + } + + configured = TRUE; +diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c +index 7f5d5a2..fb4e2e6 100644 +--- a/src/dhcp-manager/nm-dhcp-client.c ++++ b/src/dhcp-manager/nm-dhcp-client.c +@@ -49,6 +49,7 @@ typedef struct { + GByteArray * duid; + GBytes * client_id; + char * hostname; ++ char * fqdn; + + NMDhcpState state; + pid_t pid; +@@ -178,6 +179,14 @@ nm_dhcp_client_get_hostname (NMDhcpClient *self) + return NM_DHCP_CLIENT_GET_PRIVATE (self)->hostname; + } + ++const char * ++nm_dhcp_client_get_fqdn (NMDhcpClient *self) ++{ ++ g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); ++ ++ return NM_DHCP_CLIENT_GET_PRIVATE (self)->fqdn; ++} ++ + /********************************************/ + + static const char *state_table[NM_DHCP_STATE_MAX + 1] = { +@@ -410,6 +419,7 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self, + const char *dhcp_client_id, + const char *dhcp_anycast_addr, + const char *hostname, ++ const char *fqdn, + const char *last_ip4_address) + { + NMDhcpClientPrivate *priv; +@@ -428,6 +438,8 @@ 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); + + return NM_DHCP_CLIENT_GET_CLASS (self)->ip4_start (self, dhcp_anycast_addr, last_ip4_address); + } +diff --git a/src/dhcp-manager/nm-dhcp-client.h b/src/dhcp-manager/nm-dhcp-client.h +index 971c9dc..591736e 100644 +--- a/src/dhcp-manager/nm-dhcp-client.h ++++ b/src/dhcp-manager/nm-dhcp-client.h +@@ -130,10 +130,13 @@ 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_start_ip4 (NMDhcpClient *self, + const char *dhcp_client_id, + const char *dhcp_anycast_addr, + const char *hostname, ++ const char *fqdn, + const char *last_ip4_address); + + gboolean nm_dhcp_client_start_ip6 (NMDhcpClient *self, +diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.c b/src/dhcp-manager/nm-dhcp-dhclient-utils.c +index 41ce535..2fc3535 100644 +--- a/src/dhcp-manager/nm-dhcp-dhclient-utils.c ++++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.c +@@ -57,24 +57,29 @@ add_also_request (GPtrArray *array, const char *item) + } + + static void +-add_hostname4 (GString *str, const char *format, const char *hostname) ++add_hostname4 (GString *str, const char *hostname, const char *fqdn) + { + char *plain_hostname, *dot; + +- if (hostname) { ++ 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, format, plain_hostname); ++ g_string_append_printf (str, HOSTNAME4_FORMAT "\n", plain_hostname); + g_free (plain_hostname); + } + } + + static void +-add_ip4_config (GString *str, GBytes *client_id, const char *hostname) ++add_ip4_config (GString *str, GBytes *client_id, const char *hostname, const char *fqdn) + { + if (client_id) { + const char *p; +@@ -109,7 +114,7 @@ add_ip4_config (GString *str, GBytes *client_id, const char *hostname) + g_string_append (str, "; # added by NetworkManager\n"); + } + +- add_hostname4 (str, HOSTNAME4_FORMAT "\n", hostname); ++ add_hostname4 (str, hostname, fqdn); + + g_string_append_c (str, '\n'); + +@@ -197,6 +202,7 @@ nm_dhcp_dhclient_create_config (const char *interface, + GBytes *client_id, + const char *anycast_addr, + const char *hostname, ++ const char *fqdn, + const char *orig_path, + const char *orig_contents, + GBytes **out_new_client_id) +@@ -234,7 +240,7 @@ nm_dhcp_dhclient_create_config (const char *interface, + } + + /* Override config file hostname and use one from the connection */ +- if (hostname) { ++ if (hostname || fqdn) { + if (strncmp (p, HOSTNAME4_TAG, strlen (HOSTNAME4_TAG)) == 0) + continue; + if (strncmp (p, FQDN_TAG, strlen (FQDN_TAG)) == 0) +@@ -300,7 +306,7 @@ nm_dhcp_dhclient_create_config (const char *interface, + add_also_request (alsoreq, "dhcp6.domain-search"); + add_also_request (alsoreq, "dhcp6.client-id"); + } else { +- add_ip4_config (new_contents, client_id, hostname); ++ add_ip4_config (new_contents, client_id, hostname, fqdn); + add_also_request (alsoreq, "rfc3442-classless-static-routes"); + add_also_request (alsoreq, "ms-classless-static-routes"); + add_also_request (alsoreq, "static-routes"); +diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.h b/src/dhcp-manager/nm-dhcp-dhclient-utils.h +index a1828ad..6a24ac5 100644 +--- a/src/dhcp-manager/nm-dhcp-dhclient-utils.h ++++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.h +@@ -30,6 +30,7 @@ char *nm_dhcp_dhclient_create_config (const char *interface, + GBytes *client_id, + const char *anycast_addr, + const char *hostname, ++ const char *fqdn, + const char *orig_path, + const char *orig_contents, + GBytes **out_new_client_id); +diff --git a/src/dhcp-manager/nm-dhcp-dhclient.c b/src/dhcp-manager/nm-dhcp-dhclient.c +index 91515dd..11778e8 100644 +--- a/src/dhcp-manager/nm-dhcp-dhclient.c ++++ b/src/dhcp-manager/nm-dhcp-dhclient.c +@@ -156,6 +156,7 @@ merge_dhclient_config (const char *iface, + GBytes *client_id, + const char *anycast_addr, + const char *hostname, ++ const char *fqdn, + const char *orig_path, + GBytes **out_new_client_id, + GError **error) +@@ -176,7 +177,7 @@ merge_dhclient_config (const char *iface, + } + } + +- new = nm_dhcp_dhclient_create_config (iface, is_ip6, client_id, anycast_addr, hostname, orig_path, orig, out_new_client_id); ++ new = nm_dhcp_dhclient_create_config (iface, is_ip6, client_id, anycast_addr, hostname, fqdn, orig_path, orig, out_new_client_id); + g_assert (new); + success = g_file_set_contents (conf_file, new, -1, error); + g_free (new); +@@ -263,6 +264,7 @@ create_dhclient_config (const char *iface, + GBytes *client_id, + const char *dhcp_anycast_addr, + const char *hostname, ++ const char *fqdn, + GBytes **out_new_client_id) + { + char *orig = NULL, *new = NULL; +@@ -288,7 +290,7 @@ create_dhclient_config (const char *iface, + } + + error = NULL; +- success = merge_dhclient_config (iface, new, is_ip6, client_id, dhcp_anycast_addr, hostname, orig, out_new_client_id, &error); ++ success = merge_dhclient_config (iface, new, is_ip6, client_id, dhcp_anycast_addr, hostname, fqdn, orig, out_new_client_id, &error); + if (!success) { + nm_log_warn (LOGD_DHCP, "(%s): error creating dhclient%s configuration: %s", + iface, is_ip6 ? "6" : "", error->message); +@@ -468,15 +470,17 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last + NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client); + GBytes *client_id; + gs_unref_bytes GBytes *new_client_id = NULL; +- const char *iface, *uuid, *hostname; ++ const char *iface, *uuid, *hostname, *fqdn; + gboolean success = FALSE; + + 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); + +- priv->conf_file = create_dhclient_config (iface, FALSE, uuid, client_id, dhcp_anycast_addr, hostname, &new_client_id); ++ priv->conf_file = create_dhclient_config (iface, FALSE, uuid, client_id, dhcp_anycast_addr, ++ hostname, fqdn, &new_client_id); + if (priv->conf_file) { + if (new_client_id) + nm_dhcp_client_set_client_id (client, new_client_id); +@@ -501,7 +505,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 (iface, TRUE, uuid, NULL, dhcp_anycast_addr, hostname, NULL); ++ priv->conf_file = create_dhclient_config (iface, TRUE, uuid, NULL, dhcp_anycast_addr, hostname, NULL, NULL); + if (!priv->conf_file) { + nm_log_warn (LOGD_DHCP6, "(%s): error creating dhclient6 configuration file.", iface); + return FALSE; +diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.c b/src/dhcp-manager/nm-dhcp-dhcpcd.c +index b80512e..017d70c 100644 +--- a/src/dhcp-manager/nm-dhcp-dhcpcd.c ++++ b/src/dhcp-manager/nm-dhcp-dhcpcd.c +@@ -67,7 +67,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last + pid_t pid = -1; + GError *error = NULL; + char *pid_contents = NULL, *binary_name, *cmd_str, *dot; +- const char *iface, *dhcpcd_path, *hostname; ++ const char *iface, *dhcpcd_path, *hostname, *fqdn; + gs_free char *prefix = NULL; + + g_return_val_if_fail (priv->pid_file == NULL, FALSE); +@@ -116,7 +116,14 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last + #endif + + hostname = nm_dhcp_client_get_hostname (client); +- if (hostname) { ++ 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 */ +diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c +index 20ddefc..c7bb024 100644 +--- a/src/dhcp-manager/nm-dhcp-manager.c ++++ b/src/dhcp-manager/nm-dhcp-manager.c +@@ -224,6 +224,7 @@ client_start (NMDhcpManager *self, + guint32 timeout, + const char *dhcp_anycast_addr, + const char *hostname, ++ const char *fqdn, + gboolean info_only, + NMSettingIP6ConfigPrivacy privacy, + const char *last_ip4_address) +@@ -267,7 +268,7 @@ client_start (NMDhcpManager *self, + if (ipv6) + success = nm_dhcp_client_start_ip6 (client, dhcp_anycast_addr, hostname, info_only, privacy); + else +- success = nm_dhcp_client_start_ip4 (client, dhcp_client_id, dhcp_anycast_addr, hostname, last_ip4_address); ++ success = nm_dhcp_client_start_ip4 (client, dhcp_client_id, dhcp_anycast_addr, hostname, fqdn, last_ip4_address); + + if (!success) { + remove_client (self, client); +@@ -296,20 +297,24 @@ nm_dhcp_manager_start_ip4 (NMDhcpManager *self, + guint32 priority, + gboolean send_hostname, + const char *dhcp_hostname, ++ const char *dhcp_fqdn, + const char *dhcp_client_id, + guint32 timeout, + const char *dhcp_anycast_addr, + const char *last_ip_address) + { + const char *hostname = NULL; ++ const char *fqdn = NULL; + + g_return_val_if_fail (NM_IS_DHCP_MANAGER (self), NULL); + +- if (send_hostname) ++ if (send_hostname) { + hostname = get_send_hostname (self, dhcp_hostname); ++ fqdn = dhcp_fqdn; ++ } + return client_start (self, iface, ifindex, hwaddr, uuid, priority, FALSE, + dhcp_client_id, timeout, dhcp_anycast_addr, hostname, +- FALSE, 0, last_ip_address); ++ fqdn, FALSE, 0, last_ip_address); + } + + /* Caller owns a reference to the NMDhcpClient on return */ +@@ -334,7 +339,7 @@ nm_dhcp_manager_start_ip6 (NMDhcpManager *self, + if (send_hostname) + hostname = get_send_hostname (self, dhcp_hostname); + return client_start (self, iface, ifindex, hwaddr, uuid, priority, TRUE, +- NULL, timeout, dhcp_anycast_addr, hostname, info_only, ++ NULL, timeout, dhcp_anycast_addr, hostname, NULL, info_only, + privacy, NULL); + } + +diff --git a/src/dhcp-manager/nm-dhcp-manager.h b/src/dhcp-manager/nm-dhcp-manager.h +index bf6cc77..b02ae04 100644 +--- a/src/dhcp-manager/nm-dhcp-manager.h ++++ b/src/dhcp-manager/nm-dhcp-manager.h +@@ -59,6 +59,7 @@ NMDhcpClient * nm_dhcp_manager_start_ip4 (NMDhcpManager *manager, + guint32 priority, + gboolean send_hostname, + const char *dhcp_hostname, ++ const char *dhcp_fqdn, + const char *dhcp_client_id, + guint32 timeout, + const char *dhcp_anycast_addr, +diff --git a/src/dhcp-manager/nm-dhcp-systemd.c b/src/dhcp-manager/nm-dhcp-systemd.c +index 0c0233b..38ed3f9 100644 +--- a/src/dhcp-manager/nm-dhcp-systemd.c ++++ b/src/dhcp-manager/nm-dhcp-systemd.c +@@ -530,7 +530,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; ++ const char *hostname, *fqdn; + int r, i; + + g_assert (priv->client4 == NULL); +@@ -646,6 +646,15 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last + } + } + ++ fqdn = nm_dhcp_client_get_fqdn (client); ++ if (fqdn) { ++ r = sd_dhcp_client_set_hostname (priv->client4, fqdn); ++ if (r < 0) { ++ nm_log_warn (LOGD_DHCP4, "(%s): failed to set DHCP FQDN (%d)", iface, r); ++ goto error; ++ } ++ } ++ + r = sd_dhcp_client_start (priv->client4); + if (r < 0) { + nm_log_warn (LOGD_DHCP4, "(%s): failed to start DHCP (%d)", iface, r); +diff --git a/src/dhcp-manager/tests/test-dhcp-dhclient.c b/src/dhcp-manager/tests/test-dhcp-dhclient.c +index 459915e..9e294e0 100644 +--- a/src/dhcp-manager/tests/test-dhcp-dhclient.c ++++ b/src/dhcp-manager/tests/test-dhcp-dhclient.c +@@ -41,6 +41,7 @@ test_config (const char *orig, + const char *expected, + gboolean ipv6, + const char *hostname, ++ const char *fqdn, + const char *dhcp_client_id, + GBytes *expected_new_client_id, + const char *iface, +@@ -60,6 +61,7 @@ test_config (const char *orig, + client_id, + anycast_addr, + hostname, ++ fqdn, + "/path/to/dhclient.conf", + orig, + &new_client_id); +@@ -104,7 +106,7 @@ static const char *orig_missing_expected = \ + static void + test_orig_missing (void) + { +- test_config (NULL, orig_missing_expected, FALSE, NULL, NULL, NULL, "eth0", NULL); ++ test_config (NULL, orig_missing_expected, FALSE, NULL, NULL, NULL, NULL, "eth0", NULL); + } + + /*******************************************/ +@@ -133,7 +135,7 @@ static void + test_override_client_id (void) + { + test_config (override_client_id_orig, override_client_id_expected, +- FALSE, NULL, ++ FALSE, NULL, NULL, + "11:22:33:44:55:66", + NULL, + "eth0", +@@ -162,7 +164,7 @@ static void + test_quote_client_id (void) + { + test_config (NULL, quote_client_id_expected, +- FALSE, NULL, ++ FALSE, NULL, NULL, + "1234", + NULL, + "eth0", +@@ -191,7 +193,7 @@ static void + test_ascii_client_id (void) + { + test_config (NULL, ascii_client_id_expected, +- FALSE, NULL, ++ FALSE, NULL, NULL, + "qb:cd:ef:12:34:56", + NULL, + "eth0", +@@ -220,7 +222,7 @@ static void + test_hex_single_client_id (void) + { + test_config (NULL, hex_single_client_id_expected, +- FALSE, NULL, ++ FALSE, NULL, NULL, + "ab:cd:e:12:34:56", + NULL, + "eth0", +@@ -257,7 +259,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, ++ FALSE, NULL, NULL, + NULL, + new_client_id, + "eth0", +@@ -297,12 +299,41 @@ test_existing_ascii_client_id (void) + memcpy (buf + 1, EACID, 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, ++ FALSE, NULL, NULL, + NULL, + new_client_id, + "eth0", + 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 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\n"; ++ ++static void ++test_fqdn (void) ++{ ++ test_config (NULL, fqdn_expected, ++ FALSE, NULL, ++ "foo.bar.com", NULL, ++ NULL, ++ "eth0", ++ NULL); ++} + + /*******************************************/ + +@@ -330,7 +361,7 @@ static void + test_override_hostname (void) + { + test_config (override_hostname_orig, override_hostname_expected, +- FALSE, "blahblah", ++ FALSE, "blahblah", NULL, + NULL, + NULL, + "eth0", +@@ -359,7 +390,7 @@ static void + test_override_hostname6 (void) + { + test_config (override_hostname6_orig, override_hostname6_expected, +- TRUE, "blahblah.local", ++ TRUE, "blahblah.local", NULL, + NULL, + NULL, + "eth0", +@@ -382,7 +413,7 @@ test_nonfqdn_hostname6 (void) + /* Non-FQDN hostname can't be used with dhclient */ + test_config (NULL, nonfqdn_hostname6_expected, + TRUE, "blahblah", +- NULL, ++ NULL, NULL, + NULL, + "eth0", + NULL); +@@ -419,6 +450,7 @@ test_existing_alsoreq (void) + FALSE, NULL, + NULL, + NULL, ++ NULL, + "eth0", + NULL); + } +@@ -455,7 +487,7 @@ static void + test_existing_multiline_alsoreq (void) + { + test_config (existing_multiline_alsoreq_orig, existing_multiline_alsoreq_expected, +- FALSE, NULL, ++ FALSE, NULL, NULL, + NULL, + NULL, + "eth0", +@@ -772,6 +804,7 @@ main (int argc, char **argv) + 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-ascii-client-id", test_existing_ascii_client_id); ++ g_test_add_func ("/dhcp/dhclient/fqdn", test_fqdn); + 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); +diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c +index 18966c5..9b5f6d2 100644 +--- a/src/nm-iface-helper.c ++++ b/src/nm-iface-helper.c +@@ -71,6 +71,7 @@ static struct { + char *dhcp4_address; + char *dhcp4_clientid; + char *dhcp4_hostname; ++ char *dhcp4_fqdn; + char *iid_str; + char *opt_log_level; + char *opt_log_domains; +@@ -292,6 +293,7 @@ do_early_setup (int *argc, char **argv[]) + { "dhcp4-required", '4', 0, G_OPTION_ARG_NONE, &global_opt.dhcp4_required, N_("Whether DHCPv4 must be successful"), NULL }, + { "dhcp4-clientid", 'c', 0, G_OPTION_ARG_STRING, &global_opt.dhcp4_clientid, N_("Hex-encoded DHCPv4 client ID"), NULL }, + { "dhcp4-hostname", 'h', 0, G_OPTION_ARG_STRING, &global_opt.dhcp4_hostname, N_("Hostname to send to DHCP server"), N_("barbar") }, ++ { "dhcp4-fqdn", 'F', 0, G_OPTION_ARG_STRING, &global_opt.dhcp4_fqdn, N_("FQDN to send to DHCP server"), N_("host.domain.org") }, + { "priority4", '\0', 0, G_OPTION_ARG_INT64, &priority64_v4, N_("Route priority for IPv4"), N_("0") }, + { "priority6", '\0', 0, G_OPTION_ARG_INT64, &priority64_v6, N_("Route priority for IPv6"), N_("1024") }, + { "iid", 'e', 0, G_OPTION_ARG_STRING, &global_opt.iid_str, N_("Hex-encoded Interface Identifier"), "" }, +@@ -449,6 +451,7 @@ main (int argc, char *argv[]) + global_opt.priority_v4, + !!global_opt.dhcp4_hostname, + global_opt.dhcp4_hostname, ++ global_opt.dhcp4_fqdn, + global_opt.dhcp4_clientid, + 45, + NULL, +-- +2.5.5 + +From c419f3ee10c2d7f897f90478e55f26355f7f2d51 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Fri, 27 May 2016 13:33:50 +0200 +Subject: [PATCH 7/7] dhcp: let users override FQDN dhclient options + +When the ipv4.dhcp-fqdn property is set, NM adds the following options +to dhclient.conf: + + send fqdn.fqdn "foo.bar"; + send fqdn.encoded on; + send fqdn.server-update on; + +which enable the S (server-update) and E (encoded) flags in DHCP +option 81, since they are sensible default values and dhclient +requires a "send fqdn.server-update [on|off]" directive in order to +send the option. + +Users may want to change these flags according to their server's +configuration, but this is not possible at the moment since NM options +are placed after user's ones, overriding them. + +To fix this, collect user's fqdn options and add them after NM +configuration; note that the fqdn.fqdn option still can't be +overridden by users, as NM must control the FQDN sent to server. + +Fixes: c3573ebf2bb4958ee2ebf08e7ebac351765b92ef +(cherry picked from commit f940428c659eb9bd797da4545dd000bfa18ca99c) +--- + src/dhcp-manager/nm-dhcp-dhclient-utils.c | 26 +++++++++++++++--- + src/dhcp-manager/tests/test-dhcp-dhclient.c | 41 +++++++++++++++++++++++++++++ + 2 files changed, 64 insertions(+), 3 deletions(-) + +diff --git a/src/dhcp-manager/nm-dhcp-dhclient-utils.c b/src/dhcp-manager/nm-dhcp-dhclient-utils.c +index 2fc3535..dc47cd3 100644 +--- a/src/dhcp-manager/nm-dhcp-dhclient-utils.c ++++ b/src/dhcp-manager/nm-dhcp-dhclient-utils.c +@@ -39,8 +39,9 @@ + #define HOSTNAME4_TAG "send host-name" + #define HOSTNAME4_FORMAT HOSTNAME4_TAG " \"%s\"; # added by NetworkManager" + +-#define FQDN_TAG "send fqdn.fqdn" +-#define FQDN_FORMAT FQDN_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 " + +@@ -208,13 +209,14 @@ nm_dhcp_dhclient_create_config (const char *interface, + GBytes **out_new_client_id) + { + GString *new_contents; +- GPtrArray *alsoreq; ++ GPtrArray *alsoreq, *fqdn_opts; + int i; + + g_return_val_if_fail (!anycast_addr || nm_utils_hwaddr_valid (anycast_addr, ETH_ALEN), NULL); + + new_contents = g_string_new (_("# Created by NetworkManager\n")); + alsoreq = g_ptr_array_sized_new (5); ++ fqdn_opts = g_ptr_array_sized_new (5); + + if (orig_contents) { + char **lines, **line; +@@ -247,6 +249,14 @@ nm_dhcp_dhclient_create_config (const char *interface, + continue; + } + ++ /* To let user's FQDN options (except "fqdn.fqdn") override the ++ * default ones set by NM, add them later ++ */ ++ if (!strncmp (p, FQDN_TAG_PREFIX, strlen (FQDN_TAG_PREFIX))) { ++ g_ptr_array_add (fqdn_opts, g_strdup (p + strlen (FQDN_TAG_PREFIX))); ++ continue; ++ } ++ + /* Ignore 'script' since we pass our own */ + if (g_str_has_prefix (p, "script ")) + continue; +@@ -323,6 +333,16 @@ nm_dhcp_dhclient_create_config (const char *interface, + } + g_ptr_array_free (alsoreq, TRUE); + ++ for (i = 0; i < fqdn_opts->len; i++) { ++ char *t = g_ptr_array_index (fqdn_opts, 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_free (t); ++ } ++ g_ptr_array_free (fqdn_opts, TRUE); ++ + g_string_append_c (new_contents, '\n'); + + if (anycast_addr) { +diff --git a/src/dhcp-manager/tests/test-dhcp-dhclient.c b/src/dhcp-manager/tests/test-dhcp-dhclient.c +index 9e294e0..9dcea21 100644 +--- a/src/dhcp-manager/tests/test-dhcp-dhclient.c ++++ b/src/dhcp-manager/tests/test-dhcp-dhclient.c +@@ -335,6 +335,46 @@ test_fqdn (void) + 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 on;\n" ++ "send fqdn.server-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" ++ "\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, ++ FALSE, NULL, ++ "example2.com", NULL, ++ NULL, ++ "eth0", ++ NULL); ++} ++ + /*******************************************/ + + static const char *override_hostname_orig = \ +@@ -805,6 +845,7 @@ main (int argc, char **argv) + g_test_add_func ("/dhcp/dhclient/existing-hex-client-id", test_existing_hex_client_id); + g_test_add_func ("/dhcp/dhclient/existing-ascii-client-id", test_existing_ascii_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); +-- +2.5.5 + diff --git a/SPECS/NetworkManager.spec b/SPECS/NetworkManager.spec index 411643c..d464e8e 100644 --- a/SPECS/NetworkManager.spec +++ b/SPECS/NetworkManager.spec @@ -10,7 +10,7 @@ %define snapshot %{nil} %define git_sha %{nil} %define realversion 1.0.6 -%define release_version 30 +%define release_version 31 %define epoch_version 1 %define obsoletes_nmver 1:1.0.0-1 @@ -119,6 +119,7 @@ Patch36: 0036-rh1267327-wifi-scan.patch Patch37: 0037-rh1276426-wifi-crash-missing-bssid.patch Patch38: 0038-rh1288110-fix-activation-eth-zero-mac.patch Patch39: 0039-rh1309899-reapply-ip-config-after-link-up.patch +Patch40: 0040-rh1255507-dhcp-fqdn.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -437,6 +438,7 @@ by nm-connection-editor and nm-applet in a non-graphical environment. %patch37 -p1 %patch38 -p1 %patch39 -p1 +%patch40 -p1 %build @@ -747,6 +749,9 @@ fi %endif %changelog +* Thu Jul 7 2016 Beniamino Galvani - 1:1.0.6-31 +- dhcp: add support for FQDN option (rh #1255507) + * Tue Jun 7 2016 Thomas Haller - 1:1.0.6-30 - device: reapply IP configuration after link comes up for MTU change (rh#1309899)