diff options
Diffstat (limited to 'src/dhcp')
| -rw-r--r-- | src/dhcp/meson.build | 6 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-client-logging.h | 18 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-client.c | 120 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-client.h | 35 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient-utils.c | 74 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient-utils.h | 17 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient.c | 57 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhcpcanon.c | 20 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhcpcd.c | 21 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-helper-api.h | 21 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-helper.c | 18 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-listener.c | 22 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-listener.h | 18 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-manager.c | 107 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-manager.h | 24 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-nettools.c | 378 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-options.c | 19 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-options.h | 18 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-systemd.c | 225 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-utils.c | 70 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-utils.h | 24 | ||||
| -rw-r--r-- | src/dhcp/tests/meson.build | 3 | ||||
| -rw-r--r-- | src/dhcp/tests/test-dhcp-dhclient.c | 57 | ||||
| -rw-r--r-- | src/dhcp/tests/test-dhcp-utils.c | 17 |
24 files changed, 696 insertions, 693 deletions
diff --git a/src/dhcp/meson.build b/src/dhcp/meson.build index c1f28be0..609fe663 100644 --- a/src/dhcp/meson.build +++ b/src/dhcp/meson.build @@ -1,6 +1,6 @@ name = 'nm-dhcp-helper' -cflags = [ +c_flags = [ '-DG_LOG_DOMAIN="@0@"'.format(name), '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_GLIB', ] @@ -8,8 +8,8 @@ cflags = [ executable( name, name + '.c', - dependencies: libnm_core_dep, - c_args: cflags, + dependencies: glib_nm_default_dep, + c_args: c_flags, link_args: ldflags_linker_script_binary, link_depends: linker_script_binary, install: true, diff --git a/src/dhcp/nm-dhcp-client-logging.h b/src/dhcp/nm-dhcp-client-logging.h index d9b53f58..4e69c698 100644 --- a/src/dhcp/nm-dhcp-client-logging.h +++ b/src/dhcp/nm-dhcp-client-logging.h @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c index 9f585c5d..0a07b26c 100644 --- a/src/dhcp/nm-dhcp-client.c +++ b/src/dhcp/nm-dhcp-client.c @@ -1,19 +1,6 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2010 Red Hat, Inc. - * */ #include "nm-default.h" @@ -59,7 +46,10 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDhcpClient, PROP_ROUTE_TABLE, PROP_TIMEOUT, PROP_UUID, + PROP_IAID, + PROP_IAID_EXPLICIT, PROP_HOSTNAME, + PROP_HOSTNAME_FLAGS, ); typedef struct _NMDhcpClientPrivate { @@ -78,12 +68,15 @@ typedef struct _NMDhcpClientPrivate { guint32 route_table; guint32 route_metric; guint32 timeout; + guint32 iaid; NMDhcpState state; + NMDhcpHostnameFlags hostname_flags; bool info_only:1; bool use_fqdn:1; + bool iaid_explicit:1; } NMDhcpClientPrivate; -G_DEFINE_TYPE_EXTENDED (NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT, {}) +G_DEFINE_ABSTRACT_TYPE (NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT) #define NM_DHCP_CLIENT_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR (self, NMDhcpClient, NM_IS_DHCP_CLIENT) @@ -199,6 +192,22 @@ nm_dhcp_client_get_timeout (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->timeout; } +guint32 +nm_dhcp_client_get_iaid (NMDhcpClient *self) +{ + g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), 0); + + return NM_DHCP_CLIENT_GET_PRIVATE (self)->iaid; +} + +gboolean +nm_dhcp_client_get_iaid_explicit (NMDhcpClient *self) +{ + g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); + + return NM_DHCP_CLIENT_GET_PRIVATE (self)->iaid_explicit; +} + GBytes * nm_dhcp_client_get_client_id (NMDhcpClient *self) { @@ -279,6 +288,14 @@ nm_dhcp_client_get_hostname (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->hostname; } +NMDhcpHostnameFlags +nm_dhcp_client_get_hostname_flags (NMDhcpClient *self) +{ + g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NM_DHCP_HOSTNAME_FLAG_NONE); + + return NM_DHCP_CLIENT_GET_PRIVATE (self)->hostname_flags; +} + gboolean nm_dhcp_client_get_info_only (NMDhcpClient *self) { @@ -419,6 +436,17 @@ nm_dhcp_client_set_state (NMDhcpClient *self, if ((priv->state == new_state) && (new_state != NM_DHCP_STATE_BOUND)) return; + if (_LOGI_ENABLED ()) { + gs_free const char **keys = NULL; + guint i, nkeys; + + keys = nm_utils_strdict_get_keys (options, TRUE, &nkeys); + for (i = 0; i < nkeys; i++) { + _LOGI ("option %-20s => '%s'", keys[i], + (char *) g_hash_table_lookup (options, keys[i])); + } + } + if ( priv->addr_family == AF_INET6 && new_state == NM_DHCP_STATE_BOUND) { char *start, *iaid; @@ -686,7 +714,7 @@ nm_dhcp_client_stop (NMDhcpClient *self, gboolean release) _LOGI ("canceled DHCP transaction, DHCP client pid %d", old_pid); else _LOGI ("canceled DHCP transaction"); - g_assert (priv->pid == -1); + nm_assert (priv->pid == -1); nm_dhcp_client_set_state (self, NM_DHCP_STATE_DONE, NULL, NULL); } @@ -807,6 +835,15 @@ maybe_add_option (NMDhcpClient *self, } } +void +nm_dhcp_client_emit_ipv6_prefix_delegated (NMDhcpClient *self, + const NMPlatformIP6Address *prefix) +{ + g_signal_emit (G_OBJECT (self), + signals[SIGNAL_PREFIX_DELEGATED], 0, + prefix); +} + gboolean nm_dhcp_client_handle_event (gpointer unused, const char *iface, @@ -853,15 +890,6 @@ nm_dhcp_client_handle_event (gpointer unused, g_variant_unref (value); } - if (nm_logging_enabled (LOGL_DEBUG, LOGD_DHCP6)) { - GHashTableIter hash_iter; - gpointer key, val; - - g_hash_table_iter_init (&hash_iter, str_options); - while (g_hash_table_iter_next (&hash_iter, &key, &val)) - _LOGD ("option '%s'=>'%s'", (const char *) key, (const char *) val); - } - /* Create the IP config */ if (g_hash_table_size (str_options) > 0) { if (priv->addr_family == AF_INET) { @@ -887,9 +915,7 @@ nm_dhcp_client_handle_event (gpointer unused, /* If we got an IPv6 prefix to delegate, we don't change the state * of the DHCP client instance. Instead, we just signal the prefix * to the device. */ - g_signal_emit (G_OBJECT (self), - signals[SIGNAL_PREFIX_DELEGATED], 0, - &prefix); + nm_dhcp_client_emit_ipv6_prefix_delegated (self, &prefix); } else { /* Fail if no valid IP config was received */ if ( new_state == NM_DHCP_STATE_BOUND @@ -932,6 +958,12 @@ get_property (GObject *object, guint prop_id, case PROP_UUID: g_value_set_string (value, priv->uuid); break; + case PROP_IAID: + g_value_set_uint (value, priv->iaid); + break; + case PROP_IAID_EXPLICIT: + g_value_set_boolean (value, priv->iaid_explicit); + break; case PROP_HOSTNAME: g_value_set_string (value, priv->hostname); break; @@ -1001,10 +1033,22 @@ set_property (GObject *object, guint prop_id, /* construct-only */ priv->uuid = g_value_dup_string (value); break; + case PROP_IAID: + /* construct-only */ + priv->iaid = g_value_get_uint (value); + break; + case PROP_IAID_EXPLICIT: + /* construct-only */ + priv->iaid_explicit = g_value_get_boolean (value); + break; case PROP_HOSTNAME: /* construct-only */ priv->hostname = g_value_dup_string (value); break; + case PROP_HOSTNAME_FLAGS: + /* construct-only */ + priv->hostname_flags = g_value_get_uint (value); + break; case PROP_ROUTE_TABLE: priv->route_table = g_value_get_uint (value); break; @@ -1120,12 +1164,30 @@ nm_dhcp_client_class_init (NMDhcpClientClass *client_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_IAID] = + g_param_spec_uint (NM_DHCP_CLIENT_IAID, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_IAID_EXPLICIT] = + g_param_spec_boolean (NM_DHCP_CLIENT_IAID_EXPLICIT, "", "", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_HOSTNAME] = g_param_spec_string (NM_DHCP_CLIENT_HOSTNAME, "", "", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_HOSTNAME_FLAGS] = + g_param_spec_uint (NM_DHCP_CLIENT_HOSTNAME_FLAGS, "", "", + 0, G_MAXUINT32, NM_DHCP_HOSTNAME_FLAG_NONE, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_ROUTE_TABLE] = g_param_spec_uint (NM_DHCP_CLIENT_ROUTE_TABLE, "", "", 0, G_MAXUINT32, RT_TABLE_MAIN, diff --git a/src/dhcp/nm-dhcp-client.h b/src/dhcp/nm-dhcp-client.h index 9eb76f33..6a431fa8 100644 --- a/src/dhcp/nm-dhcp-client.h +++ b/src/dhcp/nm-dhcp-client.h @@ -1,17 +1,5 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2010 Red Hat, Inc. */ @@ -46,6 +34,9 @@ #define NM_DHCP_CLIENT_ROUTE_TABLE "route-table" #define NM_DHCP_CLIENT_TIMEOUT "timeout" #define NM_DHCP_CLIENT_UUID "uuid" +#define NM_DHCP_CLIENT_IAID "iaid" +#define NM_DHCP_CLIENT_IAID_EXPLICIT "iaid-explicit" +#define NM_DHCP_CLIENT_HOSTNAME_FLAGS "hostname-flags" #define NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED "state-changed" #define NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED "prefix-delegated" @@ -142,10 +133,16 @@ void nm_dhcp_client_set_route_metric (NMDhcpClient *self, guint32 route_metric); guint32 nm_dhcp_client_get_timeout (NMDhcpClient *self); +guint32 nm_dhcp_client_get_iaid (NMDhcpClient *self); + +gboolean nm_dhcp_client_get_iaid_explicit (NMDhcpClient *self); + GBytes *nm_dhcp_client_get_client_id (NMDhcpClient *self); const char *nm_dhcp_client_get_hostname (NMDhcpClient *self); +NMDhcpHostnameFlags nm_dhcp_client_get_hostname_flags (NMDhcpClient *self); + gboolean nm_dhcp_client_get_info_only (NMDhcpClient *self); gboolean nm_dhcp_client_get_use_fqdn (NMDhcpClient *self); @@ -202,20 +199,28 @@ void nm_dhcp_client_set_client_id_bin (NMDhcpClient *self, const guint8 *client_id, gsize len); +void nm_dhcp_client_emit_ipv6_prefix_delegated (NMDhcpClient *self, + const NMPlatformIP6Address *prefix); + /***************************************************************************** * Client data *****************************************************************************/ typedef struct { - GType (*get_type)(void); + GType (*get_type) (void); + GType (*get_type_per_addr_family) (int addr_family); const char *name; const char *(*get_path) (void); + bool experimental:1; } NMDhcpClientFactory; +GType nm_dhcp_nettools_get_type (void); + extern const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcanon; extern const NMDhcpClientFactory _nm_dhcp_client_factory_dhclient; extern const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcd; extern const NMDhcpClientFactory _nm_dhcp_client_factory_internal; +extern const NMDhcpClientFactory _nm_dhcp_client_factory_systemd; extern const NMDhcpClientFactory _nm_dhcp_client_factory_nettools; #endif /* __NETWORKMANAGER_DHCP_CLIENT_H__ */ diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/dhcp/nm-dhcp-dhclient-utils.c index 98f8c13a..f31c493c 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.c +++ b/src/dhcp/nm-dhcp-dhclient-utils.c @@ -1,18 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * Copyright (C) 2011 Red Hat, Inc. */ @@ -106,21 +93,11 @@ grab_request_options (GPtrArray *store, const char* line) } static void -add_hostname4 (GString *str, const char *hostname, gboolean use_fqdn) -{ - 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, gboolean use_fqdn) +add_ip4_config (GString *str, + GBytes *client_id, + const char *hostname, + gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags) { if (client_id) { const char *p; @@ -128,7 +105,7 @@ add_ip4_config (GString *str, GBytes *client_id, const char *hostname, gboolean guint i; p = g_bytes_get_data (client_id, &l); - g_assert (p); + nm_assert (p); /* Allow type 0 (non-hardware address) to be represented as a string * as long as all the characters are printable. @@ -156,7 +133,27 @@ add_ip4_config (GString *str, GBytes *client_id, const char *hostname, gboolean g_string_append (str, "; # added by NetworkManager\n"); } - add_hostname4 (str, hostname, use_fqdn); + 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'); @@ -172,12 +169,16 @@ add_ip4_config (GString *str, GBytes *client_id, const char *hostname, gboolean } static void -add_hostname6 (GString *str, const char *hostname) +add_hostname6 (GString *str, + const char *hostname, + NMDhcpHostnameFlags hostname_flags) { if (hostname) { g_string_append_printf (str, FQDN_FORMAT "\n", hostname); - g_string_append (str, - "send fqdn.server-update on;\n"); + 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'); } } @@ -284,6 +285,7 @@ nm_dhcp_dhclient_create_config (const char *interface, const char *hostname, guint32 timeout, gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, const char *orig_path, const char *orig_contents, GBytes **out_new_client_id) @@ -450,7 +452,7 @@ nm_dhcp_dhclient_create_config (const char *interface, } if (addr_family == AF_INET) { - add_ip4_config (new_contents, client_id, hostname, use_fqdn); + 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"); @@ -458,7 +460,7 @@ nm_dhcp_dhclient_create_config (const char *interface, add_request (reqs, "ntp-servers"); add_request (reqs, "root-path"); } else { - add_hostname6 (new_contents, hostname); + add_hostname6 (new_contents, hostname, hostname_flags); add_request (reqs, "dhcp6.name-servers"); add_request (reqs, "dhcp6.domain-search"); diff --git a/src/dhcp/nm-dhcp-dhclient-utils.h b/src/dhcp/nm-dhcp-dhclient-utils.h index 8ca893c3..0cf53887 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.h +++ b/src/dhcp/nm-dhcp-dhclient-utils.h @@ -1,17 +1,5 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2010 Red Hat, Inc. */ @@ -28,6 +16,7 @@ char *nm_dhcp_dhclient_create_config (const char *interface, const char *hostname, guint32 timeout, gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, 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 54b50479..869966fb 100644 --- a/src/dhcp/nm-dhcp-dhclient.c +++ b/src/dhcp/nm-dhcp-dhclient.c @@ -1,19 +1,5 @@ -/* nm-dhcp-dhclient.c - dhclient specific hooks for NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2012 Red Hat, Inc. */ @@ -38,7 +24,6 @@ #include "nm-glib-aux/nm-dedup-multi.h" #include "nm-utils.h" -#include "nm-config.h" #include "nm-dhcp-dhclient-utils.h" #include "nm-dhcp-manager.h" #include "NetworkManagerUtils.h" @@ -118,35 +103,14 @@ get_dhclient_leasefile (int addr_family, const char *uuid, char **out_preferred_path) { - gs_free char *rundir_path = NULL; gs_free char *path = NULL; - /* First, see if the lease file is in /run */ - rundir_path = g_strdup_printf (NMRUNDIR "/dhclient%s-%s-%s.lease", - _addr_family_to_path_part (addr_family), - uuid, - iface); - - if (g_file_test (rundir_path, G_FILE_TEST_EXISTS)) { - NM_SET_OUT (out_preferred_path, g_strdup (rundir_path)); - return g_steal_pointer (&rundir_path); - } - - /* /var/lib/NetworkManager is the preferred leasefile path */ - path = g_strdup_printf (NMSTATEDIR "/dhclient%s-%s-%s.lease", - _addr_family_to_path_part (addr_family), - uuid, - iface); - - if (g_file_test (path, G_FILE_TEST_EXISTS)) { + 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); } - if (nm_config_get_configure_and_quit (nm_config_get ()) == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD) - NM_SET_OUT (out_preferred_path, g_steal_pointer (&rundir_path)); - else - NM_SET_OUT (out_preferred_path, 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 @@ -182,6 +146,7 @@ merge_dhclient_config (NMDhcpDhclient *self, const char *hostname, guint32 timeout, gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, const char *orig_path, GBytes **out_new_client_id, GError **error) @@ -210,10 +175,11 @@ merge_dhclient_config (NMDhcpDhclient *self, hostname, timeout, use_fqdn, + hostname_flags, orig_path, orig, out_new_client_id); - g_assert (new); + nm_assert (new); return g_file_set_contents (conf_file, new, @@ -301,6 +267,7 @@ create_dhclient_config (NMDhcpDhclient *self, const char *hostname, guint32 timeout, gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, GBytes **out_new_client_id) { gs_free char *orig = NULL; @@ -328,6 +295,7 @@ create_dhclient_config (NMDhcpDhclient *self, hostname, timeout, use_fqdn, + hostname_flags, orig, out_new_client_id, &error)) { @@ -527,6 +495,7 @@ ip4_start (NMDhcpClient *client, nm_dhcp_client_get_hostname (client), nm_dhcp_client_get_timeout (client), nm_dhcp_client_get_use_fqdn (client), + nm_dhcp_client_get_hostname_flags (client), &new_client_id); if (!priv->conf_file) { nm_utils_error_set_literal (error, @@ -558,6 +527,9 @@ ip6_start (NMDhcpClient *client, NMDhcpDhclient *self = NM_DHCP_DHCLIENT (client); NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self); + if (nm_dhcp_client_get_iaid_explicit (client)) + _LOGW ("dhclient does not support specifying an IAID for DHCPv6, it will be ignored"); + priv->conf_file = create_dhclient_config (self, AF_INET6, nm_dhcp_client_get_iface (client), @@ -567,6 +539,7 @@ ip6_start (NMDhcpClient *client, nm_dhcp_client_get_hostname (client), nm_dhcp_client_get_timeout (client), TRUE, + nm_dhcp_client_get_hostname_flags (client), NULL); if (!priv->conf_file) { nm_utils_error_set_literal (error, @@ -723,7 +696,7 @@ nm_dhcp_dhclient_class_init (NMDhcpDhclientClass *dhclient_class) } const NMDhcpClientFactory _nm_dhcp_client_factory_dhclient = { - .name = "dhclient", + .name = "dhclient", .get_type = nm_dhcp_dhclient_get_type, .get_path = nm_dhcp_dhclient_get_path, }; diff --git a/src/dhcp/nm-dhcp-dhcpcanon.c b/src/dhcp/nm-dhcp-dhcpcanon.c index 2d2113cc..f9cc0f0a 100644 --- a/src/dhcp/nm-dhcp-dhcpcanon.c +++ b/src/dhcp/nm-dhcp-dhcpcanon.c @@ -1,19 +1,5 @@ -/* nm-dhcp-dhcpcanon.c - dhcpcanon specific hooks for NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2017 juga <juga at riseup dot net> */ @@ -248,7 +234,7 @@ nm_dhcp_dhcpcanon_class_init (NMDhcpDhcpcanonClass *dhcpcanon_class) } const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcanon = { - .name = "dhcpcanon", + .name = "dhcpcanon", .get_type = nm_dhcp_dhcpcanon_get_type, .get_path = nm_dhcp_dhcpcanon_get_path, }; diff --git a/src/dhcp/nm-dhcp-dhcpcd.c b/src/dhcp/nm-dhcp-dhcpcd.c index c300bbe2..1690bce5 100644 --- a/src/dhcp/nm-dhcp-dhcpcd.c +++ b/src/dhcp/nm-dhcp-dhcpcd.c @@ -1,22 +1,7 @@ -/* nm-dhcp-dhcpcd.c - dhcpcd specific hooks for NetworkManager - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 Roy Marples * Copyright (C) 2010 Dan Williams <dcbw@redhat.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * */ #include "nm-default.h" @@ -242,7 +227,7 @@ nm_dhcp_dhcpcd_class_init (NMDhcpDhcpcdClass *dhcpcd_class) } const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcd = { - .name = "dhcpcd", + .name = "dhcpcd", .get_type = nm_dhcp_dhcpcd_get_type, .get_path = nm_dhcp_dhcpcd_get_path, }; diff --git a/src/dhcp/nm-dhcp-helper-api.h b/src/dhcp/nm-dhcp-helper-api.h index c1a3c71c..a03049aa 100644 --- a/src/dhcp/nm-dhcp-helper-api.h +++ b/src/dhcp/nm-dhcp-helper-api.h @@ -1,21 +1,6 @@ -/* NetworkManager -- Network link manager - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2016 Red Hat, Inc. +// SPDX-License-Identifier: LGPL-2.1+ +/* + * Copyright (C) 2016 Red Hat, Inc. */ #ifndef __NM_DHCP_HELPER_API_H__ diff --git a/src/dhcp/nm-dhcp-helper.c b/src/dhcp/nm-dhcp-helper.c index 9acc4045..17f9db7f 100644 --- a/src/dhcp/nm-dhcp-helper.c +++ b/src/dhcp/nm-dhcp-helper.c @@ -1,19 +1,5 @@ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2007 - 2013 Red Hat, Inc. */ diff --git a/src/dhcp/nm-dhcp-listener.c b/src/dhcp/nm-dhcp-listener.c index 88aafeb0..a54b9643 100644 --- a/src/dhcp/nm-dhcp-listener.c +++ b/src/dhcp/nm-dhcp-listener.c @@ -1,19 +1,6 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2014 - 2016 Red Hat, Inc. - * +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014 - 2016 Red Hat, Inc. */ #include "nm-default.h" @@ -38,7 +25,7 @@ /*****************************************************************************/ -const NMDhcpClientFactory *const _nm_dhcp_manager_factories[5] = { +const NMDhcpClientFactory *const _nm_dhcp_manager_factories[6] = { /* the order here matters, as we will try the plugins in this order to find * the first available plugin. */ @@ -52,6 +39,7 @@ const NMDhcpClientFactory *const _nm_dhcp_manager_factories[5] = { &_nm_dhcp_client_factory_dhcpcd, #endif &_nm_dhcp_client_factory_internal, + &_nm_dhcp_client_factory_systemd, &_nm_dhcp_client_factory_nettools, }; diff --git a/src/dhcp/nm-dhcp-listener.h b/src/dhcp/nm-dhcp-listener.h index d9724062..c2b90dc3 100644 --- a/src/dhcp/nm-dhcp-listener.h +++ b/src/dhcp/nm-dhcp-listener.h @@ -1,18 +1,6 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2014 Red Hat, Inc. +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2014 Red Hat, Inc. */ #ifndef __NETWORKMANAGER_DHCP_LISTENER_H__ diff --git a/src/dhcp/nm-dhcp-manager.c b/src/dhcp/nm-dhcp-manager.c index 304a7b99..10ed9589 100644 --- a/src/dhcp/nm-dhcp-manager.c +++ b/src/dhcp/nm-dhcp-manager.c @@ -1,22 +1,7 @@ -/* nm-dhcp-manager.c - Handle the DHCP daemon for NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2013 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. - * */ #include "nm-default.h" @@ -32,6 +17,7 @@ #include <stdio.h> #include "nm-glib-aux/nm-dedup-multi.h" +#include "systemd/nm-sd-utils-shared.h" #include "nm-config.h" #include "NetworkManagerUtils.h" @@ -89,10 +75,11 @@ _client_factory_available (const NMDhcpClientFactory *client_factory) return NULL; } -static const NMDhcpClientFactory * -_client_factory_get_effective (const NMDhcpClientFactory *client_factory, - int addr_family) +static GType +_client_factory_get_gtype (const NMDhcpClientFactory *client_factory, + int addr_family) { + GType gtype; nm_auto_unref_gtypeclass NMDhcpClientClass *klass = NULL; nm_assert (client_factory); @@ -118,23 +105,38 @@ _client_factory_get_effective (const NMDhcpClientFactory *client_factory, * to those plugins. But we don't intend to do so. The internal plugin is the way forward and * not extending other plugins. */ + if (client_factory->get_type_per_addr_family) + gtype = client_factory->get_type_per_addr_family (addr_family); + else + gtype = client_factory->get_type (); + if (client_factory == &_nm_dhcp_client_factory_internal) { - /* already using internal plugin. Nothing to do. */ - return client_factory; + /* we are already using the internal plugin. Nothing to do. */ + goto out; } - klass = g_type_class_ref (client_factory->get_type ()); + klass = g_type_class_ref (gtype); nm_assert (NM_IS_DHCP_CLIENT_CLASS (klass)); if (addr_family == AF_INET6) { - return klass->ip6_start - ? client_factory - : &_nm_dhcp_client_factory_internal; + if (!klass->ip6_start) + gtype = _client_factory_get_gtype (&_nm_dhcp_client_factory_internal, addr_family); + } else { + if (!klass->ip4_start) + gtype = _client_factory_get_gtype (&_nm_dhcp_client_factory_internal, addr_family); } - return klass->ip4_start - ? client_factory - : &_nm_dhcp_client_factory_internal; + +out: + nm_assert (g_type_is_a (gtype, NM_TYPE_DHCP_CLIENT)); + nm_assert (({ + nm_auto_unref_gtypeclass NMDhcpClientClass *k = g_type_class_ref (gtype); + + (addr_family == AF_INET6 && k->ip6_start) + || (addr_family == AF_INET && k->ip4_start); + })); + + return gtype; } /*****************************************************************************/ @@ -211,10 +213,13 @@ client_start (NMDhcpManager *self, const struct in6_addr *ipv6_ll_addr, GBytes *dhcp_client_id, gboolean enforce_duid, + guint32 iaid, + gboolean iaid_explicit, guint32 timeout, const char *dhcp_anycast_addr, const char *hostname, gboolean hostname_use_fqdn, + NMDhcpHostnameFlags hostname_flags, gboolean info_only, NMSettingIP6ConfigPrivacy privacy, const char *last_ip4_address, @@ -225,7 +230,7 @@ client_start (NMDhcpManager *self, NMDhcpClient *client; gboolean success = FALSE; gsize hwaddr_len; - const NMDhcpClientFactory *client_factory; + GType gtype; g_return_val_if_fail (NM_IS_DHCP_MANAGER (self), NULL); g_return_val_if_fail (iface, NULL); @@ -251,12 +256,21 @@ client_start (NMDhcpManager *self, g_return_val_if_reached (NULL) ; } + if (hostname) { + if ( (hostname_use_fqdn && !nm_sd_dns_name_is_valid (hostname)) + || (!hostname_use_fqdn && !nm_sd_hostname_is_valid (hostname, FALSE))) { + nm_log_warn (LOGD_DHCP , "dhcp%c: %s '%s' is invalid, will be ignored", + nm_utils_addr_family_to_char (addr_family), + hostname_use_fqdn ? "FQDN" : "hostname", + hostname); + hostname = NULL; + } + } + nm_assert (g_bytes_get_size (hwaddr) == g_bytes_get_size (bcast_hwaddr)); priv = NM_DHCP_MANAGER_GET_PRIVATE (self); - client_factory = _client_factory_get_effective (priv->client_factory, addr_family); - /* Kill any old client instance */ client = get_client_for_ifindex (self, addr_family, ifindex); if (client) { @@ -271,7 +285,14 @@ client_start (NMDhcpManager *self, g_object_unref (client); } - client = g_object_new (client_factory->get_type (), + gtype = _client_factory_get_gtype (priv->client_factory, addr_family); + + nm_log_trace (LOGD_DHCP , "dhcp%c: creating IPv%c DHCP client of type %s", + nm_utils_addr_family_to_char (addr_family), + nm_utils_addr_family_to_char (addr_family), + g_type_name (gtype)); + + client = g_object_new (gtype, NM_DHCP_CLIENT_MULTI_IDX, multi_idx, NM_DHCP_CLIENT_ADDR_FAMILY, addr_family, NM_DHCP_CLIENT_INTERFACE, iface, @@ -279,10 +300,13 @@ client_start (NMDhcpManager *self, NM_DHCP_CLIENT_HWADDR, hwaddr, NM_DHCP_CLIENT_BROADCAST_HWADDR, bcast_hwaddr, NM_DHCP_CLIENT_UUID, uuid, + NM_DHCP_CLIENT_IAID, (guint) iaid, + NM_DHCP_CLIENT_IAID_EXPLICIT, iaid_explicit, NM_DHCP_CLIENT_HOSTNAME, hostname, NM_DHCP_CLIENT_ROUTE_TABLE, (guint) route_table, NM_DHCP_CLIENT_ROUTE_METRIC, (guint) route_metric, NM_DHCP_CLIENT_TIMEOUT, (guint) timeout, + NM_DHCP_CLIENT_HOSTNAME_FLAGS, (guint) hostname_flags, NM_DHCP_CLIENT_FLAGS, (guint) (0 | (hostname_use_fqdn ? NM_DHCP_CLIENT_FLAGS_USE_FQDN : 0) | (info_only ? NM_DHCP_CLIENT_FLAGS_INFO_ONLY : 0) @@ -357,6 +381,7 @@ nm_dhcp_manager_start_ip4 (NMDhcpManager *self, gboolean send_hostname, const char *dhcp_hostname, const char *dhcp_fqdn, + NMDhcpHostnameFlags hostname_flags, GBytes *dhcp_client_id, guint32 timeout, const char *dhcp_anycast_addr, @@ -408,10 +433,13 @@ nm_dhcp_manager_start_ip4 (NMDhcpManager *self, NULL, dhcp_client_id, FALSE, + 0, + FALSE, timeout, dhcp_anycast_addr, hostname, use_fqdn, + hostname_flags, FALSE, 0, last_ip_address, @@ -433,8 +461,11 @@ nm_dhcp_manager_start_ip6 (NMDhcpManager *self, guint32 route_metric, gboolean send_hostname, const char *dhcp_hostname, + NMDhcpHostnameFlags hostname_flags, GBytes *duid, gboolean enforce_duid, + guint32 iaid, + gboolean iaid_explicit, guint32 timeout, const char *dhcp_anycast_addr, gboolean info_only, @@ -465,10 +496,13 @@ nm_dhcp_manager_start_ip6 (NMDhcpManager *self, ll_addr, duid, enforce_duid, + iaid, + iaid_explicit, timeout, dhcp_anycast_addr, hostname, TRUE, + hostname_flags, info_only, privacy, NULL, @@ -529,9 +563,10 @@ nm_dhcp_manager_init (NMDhcpManager *self) if (!f) continue; - nm_log_dbg (LOGD_DHCP, "dhcp-init: enabled DHCP client '%s' (%s)%s", - f->name, g_type_name (f->get_type ()), - _client_factory_available (f) ? "" : " (not available)"); + nm_log_dbg (LOGD_DHCP, "dhcp-init: enabled DHCP client '%s'%s%s", + f->name, + _client_factory_available (f) ? "" : " (not available)", + f->experimental ? " (undocumented internal plugin)" : ""); } /* Client-specific setup */ diff --git a/src/dhcp/nm-dhcp-manager.h b/src/dhcp/nm-dhcp-manager.h index ff0d6f54..fb1c9834 100644 --- a/src/dhcp/nm-dhcp-manager.h +++ b/src/dhcp/nm-dhcp-manager.h @@ -1,19 +1,5 @@ -/* nm-dhcp-manager.c - Handle the DHCP daemon for NetworkManager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2010 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -56,6 +42,7 @@ NMDhcpClient * nm_dhcp_manager_start_ip4 (NMDhcpManager *manager, gboolean send_hostname, const char *dhcp_hostname, const char *dhcp_fqdn, + NMDhcpHostnameFlags hostname_flags, GBytes *dhcp_client_id, guint32 timeout, const char *dhcp_anycast_addr, @@ -74,8 +61,11 @@ NMDhcpClient * nm_dhcp_manager_start_ip6 (NMDhcpManager *manager, guint32 route_metric, gboolean send_hostname, const char *dhcp_hostname, + NMDhcpHostnameFlags hostname_flags, GBytes *duid, gboolean enforce_duid, + guint32 iaid, + gboolean iaid_explicit, guint32 timeout, const char *dhcp_anycast_addr, gboolean info_only, @@ -86,7 +76,7 @@ NMDhcpClient * nm_dhcp_manager_start_ip6 (NMDhcpManager *manager, /* For testing only */ extern const char* nm_dhcp_helper_path; -extern const NMDhcpClientFactory *const _nm_dhcp_manager_factories[5]; +extern const NMDhcpClientFactory *const _nm_dhcp_manager_factories[6]; void nmtst_dhcp_manager_unget (gpointer singleton_instance); diff --git a/src/dhcp/nm-dhcp-nettools.c b/src/dhcp/nm-dhcp-nettools.c index a71a7a13..e557c004 100644 --- a/src/dhcp/nm-dhcp-nettools.c +++ b/src/dhcp/nm-dhcp-nettools.c @@ -1,19 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2014-2019 Red Hat, Inc. + * Copyright (C) 2014 - 2019 Red Hat, Inc. */ #include "nm-default.h" @@ -42,6 +29,7 @@ #include "nm-dhcp-client-logging.h" #include "n-dhcp4/src/n-dhcp4.h" #include "systemd/nm-sd-utils-shared.h" +#include "systemd/nm-sd-utils-dhcp.h" /*****************************************************************************/ @@ -55,8 +43,6 @@ typedef struct _NMDhcpNettools NMDhcpNettools; typedef struct _NMDhcpNettoolsClass NMDhcpNettoolsClass; -static GType nm_dhcp_nettools_get_type (void); - /*****************************************************************************/ typedef struct { @@ -65,6 +51,7 @@ typedef struct { NDhcp4ClientLease *lease; GIOChannel *channel; guint event_id; + char *lease_file; } NMDhcpNettoolsPrivate; struct _NMDhcpNettools { @@ -85,13 +72,6 @@ G_DEFINE_TYPE (NMDhcpNettools, nm_dhcp_nettools, NM_TYPE_DHCP_CLIENT) #define DHCP_MAX_FQDN_LENGTH 255 enum { - DHCP_FQDN_FLAG_S = (1 << 0), - DHCP_FQDN_FLAG_O = (1 << 1), - DHCP_FQDN_FLAG_E = (1 << 2), - DHCP_FQDN_FLAG_N = (1 << 3), -}; - -enum { NM_IN_ADDR_CLASS_A, NM_IN_ADDR_CLASS_B, NM_IN_ADDR_CLASS_C, @@ -354,28 +334,21 @@ lease_get_u16 (NDhcp4ClientLease *lease, return TRUE; } -#define LOG_LEASE(domain, ...) \ - G_STMT_START { \ - _LOG2I ((domain), (iface), " "__VA_ARGS__); \ - } G_STMT_END - static gboolean lease_parse_address (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options, GError **error) { char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - const gint64 ts = nm_utils_get_monotonic_timestamp_ns (); - const gint64 ts_clock_boottime = nm_utils_monotonic_timestamp_as_boottime (ts, 1); struct in_addr a_address; struct in_addr a_netmask; struct in_addr a_next_server; guint32 a_plen; guint64 nettools_lifetime; - gint64 a_lifetime; - gint64 a_expiry; + guint32 a_lifetime; + guint32 a_timestamp; + guint64 a_expiry; n_dhcp4_client_lease_get_yiaddr (lease, &a_address); if (a_address.s_addr == INADDR_ANY) { @@ -383,29 +356,47 @@ lease_parse_address (NDhcp4ClientLease *lease, return FALSE; } - /* n_dhcp4_client_lease_get_lifetime() never fails */ n_dhcp4_client_lease_get_lifetime (lease, &nettools_lifetime); - /* FIXME: n_dhcp4_client_lease_get_lifetime() returns the time in nsec of CLOCK_BOOTTIME. - * We want to retrieve the original lifetime value in seconds, so we approximate it in a_lifetime. - * Use a nettools API to retrieve the original value as passed by the server. - */ + if (nettools_lifetime == G_MAXUINT64) { + a_timestamp = 0; a_lifetime = NM_PLATFORM_LIFETIME_PERMANENT; - a_expiry = NM_PLATFORM_LIFETIME_PERMANENT; + a_expiry = G_MAXUINT64; } else { - gint64 ts_time = time (NULL); - - a_lifetime = ((gint64) nettools_lifetime - ts_clock_boottime) / NM_UTILS_NS_PER_SECOND; - /* A lease time of 0 is allowed on some dhcp servers, so, let's accept it. */ - if (a_lifetime < 0) - a_lifetime = 0; - else if (a_lifetime > NM_PLATFORM_LIFETIME_PERMANENT) - a_lifetime = NM_PLATFORM_LIFETIME_PERMANENT - 1; - - if (ts_time > NM_PLATFORM_LIFETIME_PERMANENT - a_lifetime) - a_expiry = NM_PLATFORM_LIFETIME_PERMANENT - 1; - else - a_expiry = ts_time + a_lifetime; + guint64 nettools_basetime; + guint64 lifetime; + gint64 ts; + + n_dhcp4_client_lease_get_basetime (lease, &nettools_basetime); + + /* usually we shouldn't assert against external libraries like n-dhcp4. + * Here we still do it... it seems safe enough. */ + nm_assert (nettools_basetime > 0); + nm_assert (nettools_lifetime >= nettools_basetime); + nm_assert (((nettools_lifetime - nettools_basetime) % NM_UTILS_NS_PER_SECOND) == 0); + nm_assert ((nettools_lifetime - nettools_basetime) / NM_UTILS_NS_PER_SECOND <= G_MAXUINT32); + + if (nettools_lifetime <= nettools_basetime) { + /* A lease time of 0 is allowed on some dhcp servers, so, let's accept it. */ + lifetime = 0; + } else { + lifetime = nettools_lifetime - nettools_basetime; + + /* we "ceil" the value to the next second. In practice, we don't expect any sub-second values + * from n-dhcp4 anyway, so this should have no effect. */ + lifetime += NM_UTILS_NS_PER_SECOND - 1; + } + + ts = nm_utils_monotonic_timestamp_from_boottime (nettools_basetime, 1); + + /* the timestamp must be positive, because we only started nettools DHCP client + * after obtaining the first monotonic timestamp. Hence, the lease must have been + * received afterwards. */ + nm_assert (ts >= NM_UTILS_NS_PER_SECOND); + + a_timestamp = ts / NM_UTILS_NS_PER_SECOND; + a_lifetime = NM_MIN (lifetime / NM_UTILS_NS_PER_SECOND, NM_PLATFORM_LIFETIME_PERMANENT - 1); + a_expiry = time (NULL) + ((lifetime - (nm_utils_clock_gettime_ns (CLOCK_BOOTTIME) - nettools_basetime)) / NM_UTILS_NS_PER_SECOND); } if (!lease_get_in_addr (lease, NM_DHCP_OPTION_DHCP4_SUBNET_MASK, &a_netmask)) { @@ -416,7 +407,6 @@ lease_parse_address (NDhcp4ClientLease *lease, nm_utils_inet4_ntop (a_address.s_addr, addr_str); a_plen = nm_utils_ip4_netmask_to_prefix (a_netmask.s_addr); - LOG_LEASE (LOGD_DHCP4, "address %s/%u", addr_str, a_plen); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, @@ -426,20 +416,17 @@ lease_parse_address (NDhcp4ClientLease *lease, NM_DHCP_OPTION_DHCP4_SUBNET_MASK, nm_utils_inet4_ntop (a_netmask.s_addr, addr_str)); - LOG_LEASE (LOGD_DHCP4, "%s '%u' seconds (at %lld)", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME), - (guint) a_lifetime, - (long long) a_expiry); nm_dhcp_option_add_option_u64 (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, (guint64) a_lifetime); - nm_dhcp_option_add_option_u64 (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NM_EXPIRY, - (guint64) a_expiry); + if (a_expiry != G_MAXUINT64) { + nm_dhcp_option_add_option_u64 (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NM_EXPIRY, + a_expiry); + } n_dhcp4_client_lease_get_siaddr (lease, &a_next_server); @@ -457,7 +444,7 @@ lease_parse_address (NDhcp4ClientLease *lease, .peer_address = a_address.s_addr, .plen = a_plen, .addr_source = NM_IP_CONFIG_SOURCE_DHCP, - .timestamp = ts / NM_UTILS_NS_PER_SECOND, + .timestamp = a_timestamp, .lifetime = a_lifetime, .preferred = a_lifetime, })); @@ -467,7 +454,6 @@ lease_parse_address (NDhcp4ClientLease *lease, static void lease_parse_domain_name_servers (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options) { @@ -498,7 +484,6 @@ lease_parse_domain_name_servers (NDhcp4ClientLease *lease, nm_ip4_config_add_nameserver (ip4_config, addr.s_addr); } - LOG_LEASE (LOGD_DHCP4, "nameserver '%s'", str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, @@ -507,7 +492,6 @@ lease_parse_domain_name_servers (NDhcp4ClientLease *lease, static void lease_parse_routes (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options, guint32 route_table, @@ -537,11 +521,6 @@ lease_parse_routes (NDhcp4ClientLease *lease, nm_utils_inet4_ntop (dest.s_addr, dest_str); nm_utils_inet4_ntop (gateway.s_addr, gateway_str); - LOG_LEASE (LOGD_DHCP4, - "classless static route %s/%d gw %s", - dest_str, - (int) plen, - gateway_str); g_string_append_printf (nm_gstring_add_space_delimiter (str), "%s/%d %s", dest_str, @@ -586,11 +565,6 @@ lease_parse_routes (NDhcp4ClientLease *lease, nm_utils_inet4_ntop (dest.s_addr, dest_str); nm_utils_inet4_ntop (gateway.s_addr, gateway_str); - LOG_LEASE (LOGD_DHCP4, - "static route %s/%d gw %s", - dest_str, - (int) plen, - gateway_str); g_string_append_printf (nm_gstring_add_space_delimiter (str), "%s/%d %s", dest_str, @@ -667,7 +641,6 @@ lease_parse_routes (NDhcp4ClientLease *lease, }), NULL); } - LOG_LEASE (LOGD_DHCP4, "router %s", str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROUTER, @@ -677,7 +650,6 @@ lease_parse_routes (NDhcp4ClientLease *lease, static void lease_parse_mtu (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options) { @@ -689,7 +661,6 @@ lease_parse_mtu (NDhcp4ClientLease *lease, if (mtu < 68) return; - LOG_LEASE (LOGD_DHCP4, "mtu %u", mtu); nm_dhcp_option_add_option_u64 (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, @@ -699,7 +670,6 @@ lease_parse_mtu (NDhcp4ClientLease *lease, static void lease_parse_metered (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options) { @@ -715,13 +685,12 @@ lease_parse_metered (NDhcp4ClientLease *lease, metered = !!memmem (data, n_data, "ANDROID_METERED", NM_STRLEN ("ANDROID_METERED")); } - LOG_LEASE (LOGD_DHCP4, "%s", metered ? "metered" : "unmetered"); + /* TODO: expose the vendor specific option when present */ nm_ip4_config_set_metered (ip4_config, metered); } static void lease_parse_ntps (NDhcp4ClientLease *lease, - const char *iface, GHashTable *options) { nm_auto_free_gstring GString *str = NULL; @@ -742,13 +711,14 @@ lease_parse_ntps (NDhcp4ClientLease *lease, g_string_append (nm_gstring_add_space_delimiter (str), addr_str); } - LOG_LEASE (LOGD_DHCP4, "ntp server '%s'", str->str); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NTP_SERVER, str->str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NTP_SERVER, + str->str); } static void lease_parse_hostname (NDhcp4ClientLease *lease, - const char *iface, GHashTable *options) { nm_auto_free_gstring GString *str = NULL; @@ -765,13 +735,14 @@ lease_parse_hostname (NDhcp4ClientLease *lease, if (is_localhost(str->str)) return; - LOG_LEASE (LOGD_DHCP4, "hostname '%s'", str->str); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_HOST_NAME, str->str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_HOST_NAME, + str->str); } static void lease_parse_domainname (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options) { @@ -798,13 +769,14 @@ lease_parse_domainname (NDhcp4ClientLease *lease, g_string_append (nm_gstring_add_space_delimiter (str), *d); nm_ip4_config_add_domain (ip4_config, *d); } - LOG_LEASE (LOGD_DHCP4, "domain name '%s'", str->str); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, str->str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, + str->str); } static void lease_parse_search_domains (NDhcp4ClientLease *lease, - const char *iface, NMIP4Config *ip4_config, GHashTable *options) { @@ -832,7 +804,6 @@ lease_parse_search_domains (NDhcp4ClientLease *lease, g_string_append (nm_gstring_add_space_delimiter (str), domain->str); nm_ip4_config_add_search (ip4_config, domain->str); } - LOG_LEASE (LOGD_DHCP4, "domain search '%s'", str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, @@ -841,7 +812,6 @@ lease_parse_search_domains (NDhcp4ClientLease *lease, static void lease_parse_root_path (NDhcp4ClientLease *lease, - const char *iface, GHashTable *options) { nm_auto_free_gstring GString *str = NULL; @@ -854,16 +824,17 @@ lease_parse_root_path (NDhcp4ClientLease *lease, return; str = g_string_new_len ((char *)data, n_data); - LOG_LEASE (LOGD_DHCP4, "root path '%s'", str->str); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROOT_PATH, str->str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_ROOT_PATH, + str->str); } static void lease_parse_wpad (NDhcp4ClientLease *lease, - const char *iface, GHashTable *options) { - nm_auto_free_gstring GString *str = NULL; + gs_free char *wpad = NULL; uint8_t *data; size_t n_data; int r; @@ -872,12 +843,44 @@ lease_parse_wpad (NDhcp4ClientLease *lease, if (r) return; - str = g_string_new_len ((char *)data, n_data); - LOG_LEASE (LOGD_DHCP4, "wpad '%s'", str->str); + nm_utils_buf_utf8safe_escape ((char *)data, n_data, 0, &wpad); + if (wpad == NULL) + wpad = g_strndup ((char *)data, n_data); + nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, - str->str); + wpad); +} + +static void +lease_parse_private_options (NDhcp4ClientLease *lease, + GHashTable *options) +{ + int i; + + for (i = NM_DHCP_OPTION_DHCP4_PRIVATE_224; i <= NM_DHCP_OPTION_DHCP4_PRIVATE_254; i++) { + gs_free char *option_string = NULL; + guint8 *data; + gsize n_data; + int r; + + /* We manage private options 249 (private classless static route) and 252 (wpad) in a special + * way, so skip them as we here just manage all (the other) private options as raw data */ + if (NM_IN_SET (i, NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE, + NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY)) + continue; + + r = n_dhcp4_client_lease_query (lease, i, &data, &n_data); + if (r) + continue; + + option_string = nm_utils_bin2hexstr_full (data, n_data, ':', FALSE, NULL); + nm_dhcp_option_take_option (options, + _nm_dhcp_option_dhcp4_options, + i, + g_steal_pointer (&option_string)); + } } static NMIP4Config * @@ -896,22 +899,23 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, g_return_val_if_fail (lease != NULL, NULL); ip4_config = nm_ip4_config_new (multi_idx, ifindex); - options = out_options ? nm_dhcp_option_create_options_dict () : NULL; + options = nm_dhcp_option_create_options_dict (); - if (!lease_parse_address (lease, iface, ip4_config, options, error)) + if (!lease_parse_address (lease, ip4_config, options, error)) return NULL; - lease_parse_routes (lease, iface, ip4_config, options, route_table, route_metric); - lease_parse_domain_name_servers (lease, iface, ip4_config, options); - lease_parse_domainname (lease, iface, ip4_config, options); - lease_parse_search_domains (lease, iface, ip4_config, options); - lease_parse_mtu (lease, iface, ip4_config, options); - lease_parse_metered (lease, iface, ip4_config, options); + lease_parse_routes (lease, ip4_config, options, route_table, route_metric); + lease_parse_domain_name_servers (lease, ip4_config, options); + lease_parse_domainname (lease, ip4_config, options); + lease_parse_search_domains (lease, ip4_config, options); + lease_parse_mtu (lease, ip4_config, options); + lease_parse_metered (lease, ip4_config, options); - lease_parse_hostname (lease, iface, options); - lease_parse_ntps (lease, iface, options); - lease_parse_root_path (lease, iface, options); - lease_parse_wpad (lease, iface, options); + lease_parse_hostname (lease, options); + lease_parse_ntps (lease, options); + lease_parse_root_path (lease, options); + lease_parse_wpad (lease, options); + lease_parse_private_options (lease, options); NM_SET_OUT (out_options, g_steal_pointer (&options)); return g_steal_pointer (&ip4_config); @@ -920,8 +924,34 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, /*****************************************************************************/ static void +lease_save (NDhcp4ClientLease *lease, const char *lease_file) +{ + struct in_addr a_address; + nm_auto_free_gstring GString *new_contents = NULL; + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + + nm_assert (lease); + nm_assert (lease_file); + + new_contents = g_string_new ("# This is private data. Do not parse.\n"); + + n_dhcp4_client_lease_get_yiaddr (lease, &a_address); + if (a_address.s_addr == INADDR_ANY) + return; + + g_string_append_printf (new_contents, + "ADDRESS=%s\n", nm_utils_inet4_ntop (a_address.s_addr, sbuf)); + + g_file_set_contents (lease_file, + new_contents->str, + -1, + NULL); +} + +static void bound4_handle (NMDhcpNettools *self, NDhcp4ClientLease *lease) { + NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE (self); const char *iface = nm_dhcp_client_get_iface (NM_DHCP_CLIENT (self)); gs_unref_object NMIP4Config *ip4_config = NULL; gs_unref_hashtable GHashTable *options = NULL; @@ -945,6 +975,7 @@ bound4_handle (NMDhcpNettools *self, NDhcp4ClientLease *lease) } nm_dhcp_option_add_requests_to_options (options, _nm_dhcp_option_dhcp4_options); + lease_save (lease, priv->lease_file); nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), NM_DHCP_STATE_BOUND, @@ -1015,6 +1046,27 @@ dhcp4_event_cb (GIOChannel *source, return G_SOURCE_CONTINUE; } +G_GNUC_PRINTF (3, 4) +static void +nettools_log (int level, void *data, const char *fmt, ...) +{ + NMDhcpNettools *self = data; + NMLogLevel nm_level; + gs_free char *msg = NULL; + va_list ap; + + nm_level = nm_log_level_from_syslog (level); + if (nm_logging_enabled (nm_level, LOGD_DHCP4)) { + va_start (ap, fmt); + msg = g_strdup_vprintf (fmt, ap); + va_end (ap); + nm_log (nm_level, LOGD_DHCP4, NULL , NULL, + "dhcp4 (%s): %s", + nm_dhcp_client_get_iface (NM_DHCP_CLIENT (self)), + msg); + } +} + static gboolean nettools_create (NMDhcpNettools *self, const char *dhcp_anycast_addr, @@ -1084,11 +1136,15 @@ nettools_create (NMDhcpNettools *self, return FALSE; } + n_dhcp4_client_config_set_log_level (config, nm_log_level_to_syslog (nm_logging_get_level (LOGD_DHCP4))); + n_dhcp4_client_config_set_log_func (config, nettools_log, self); n_dhcp4_client_config_set_ifindex (config, nm_dhcp_client_get_ifindex (NM_DHCP_CLIENT (self))); n_dhcp4_client_config_set_transport (config, transport); n_dhcp4_client_config_set_mac (config, hwaddr_arr, hwaddr_len); n_dhcp4_client_config_set_broadcast_mac (config, bcast_hwaddr_arr, bcast_hwaddr_len); - r = n_dhcp4_client_config_set_client_id (config, client_id_arr, client_id_len); + r = n_dhcp4_client_config_set_client_id (config, + client_id_arr, + NM_MIN (client_id_len, 1 + _NM_SD_MAX_CLIENT_ID_LEN)); if (r) { nm_utils_error_set_errno (error, r, "failed to set client-id: %s"); return FALSE; @@ -1157,6 +1213,22 @@ decline (NMDhcpClient *client, return TRUE; } +static guint8 +fqdn_flags_to_wire (NMDhcpHostnameFlags flags) +{ + guint r = 0; + + /* RFC 4702 section 2.1 */ + if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) + r |= (1 << 0); + if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED) + r |= (1 << 2); + if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE) + r |= (1 << 3); + + return r; +} + static gboolean ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, @@ -1166,6 +1238,7 @@ ip4_start (NMDhcpClient *client, nm_auto (n_dhcp4_client_probe_config_freep) NDhcp4ClientProbeConfig *config = NULL; NMDhcpNettools *self = NM_DHCP_NETTOOLS (client); NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE (self); + gs_free char *lease_file = NULL; struct in_addr last_addr = { 0 }; const char *hostname; int r, i; @@ -1187,11 +1260,32 @@ ip4_start (NMDhcpClient *client, */ n_dhcp4_client_probe_config_set_start_delay (config, 1); - if (last_ip4_address) { + nm_dhcp_utils_get_leasefile_path (AF_INET, + "internal", + nm_dhcp_client_get_iface (client), + nm_dhcp_client_get_uuid (client), + &lease_file); + + if (last_ip4_address) inet_pton (AF_INET, last_ip4_address, &last_addr); - n_dhcp4_client_probe_config_set_requested_ip (config, last_addr); + else { + /* + * TODO: we stick to the systemd-networkd lease file format. Quite easy for now to + * just use the functions in systemd code. Anyway, as in the end we just use the + * ip address from all the options found in the lease, write a function that parses + * the lease file just for the assigned address and returns it in &last_address. + * Then drop reference to systemd-networkd structures and functions. + */ + nm_auto (sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; + + dhcp_lease_load (&lease, lease_file); + if (lease) + sd_dhcp_lease_get_address (lease, &last_addr); } + if (last_addr.s_addr) + n_dhcp4_client_probe_config_set_requested_ip (config, last_addr); + /* Add requested options */ for (i = 0; _nm_dhcp_option_dhcp4_options[i].name; i++) { if (_nm_dhcp_option_dhcp4_options[i].include) { @@ -1204,26 +1298,38 @@ ip4_start (NMDhcpClient *client, hostname = nm_dhcp_client_get_hostname (client); if (hostname) { if (nm_dhcp_client_get_use_fqdn (client)) { - uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH]; - - buffer[0] = DHCP_FQDN_FLAG_S | /* Request server to perform A RR DNS updates */ - DHCP_FQDN_FLAG_E; /* Canonical wire format */ - buffer[1] = 0; /* RCODE1 (deprecated) */ - buffer[2] = 0; /* RCODE2 (deprecated) */ - - r = nm_sd_dns_name_to_wire_format (hostname, - buffer + 3, - sizeof (buffer) - 3, - FALSE); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to convert DHCP FQDN: %s"); - return FALSE; + uint8_t buffer[255]; + NMDhcpHostnameFlags flags; + size_t fqdn_len; + + flags = nm_dhcp_client_get_hostname_flags (client); + buffer[0] = fqdn_flags_to_wire (flags); + buffer[1] = 0; /* RCODE1 (deprecated) */ + buffer[2] = 0; /* RCODE2 (deprecated) */ + + if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED) { + r = nm_sd_dns_name_to_wire_format (hostname, + buffer + 3, + sizeof (buffer) - 3, + FALSE); + if (r <= 0) { + nm_utils_error_set_errno (error, r, "failed to convert DHCP FQDN: %s"); + return FALSE; + } + fqdn_len = r; + } else { + fqdn_len = strlen (hostname); + if (fqdn_len > sizeof (buffer) - 3) { + nm_utils_error_set (error, r, "failed to set DHCP FQDN: name too long"); + return FALSE; + } + memcpy (buffer + 3, hostname, fqdn_len); } r = n_dhcp4_client_probe_config_append_option (config, NM_DHCP_OPTION_DHCP4_CLIENT_FQDN, buffer, - 3 + r); + 3 + fqdn_len); if (r) { nm_utils_error_set_errno (error, r, "failed to set DHCP FQDN: %s"); return FALSE; @@ -1240,6 +1346,9 @@ ip4_start (NMDhcpClient *client, } } + g_free (priv->lease_file); + priv->lease_file = g_steal_pointer (&lease_file); + r = n_dhcp4_client_probe (priv->client, &priv->probe, config); if (r) { nm_utils_error_set_errno (error, r, "failed to start DHCP client: %s"); @@ -1279,6 +1388,7 @@ dispose (GObject *object) { NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE ((NMDhcpNettools *) object); + nm_clear_pointer (&priv->lease_file, g_free); nm_clear_pointer (&priv->channel, g_io_channel_unref); nm_clear_g_source (&priv->event_id); nm_clear_pointer (&priv->lease, n_dhcp4_client_lease_unref); @@ -1303,7 +1413,7 @@ nm_dhcp_nettools_class_init (NMDhcpNettoolsClass *class) } const NMDhcpClientFactory _nm_dhcp_client_factory_nettools = { - .name = "nettools", - .get_type = nm_dhcp_nettools_get_type, - .get_path = NULL, + .name = "nettools", + .get_type = nm_dhcp_nettools_get_type, + .experimental = TRUE, }; diff --git a/src/dhcp/nm-dhcp-options.c b/src/dhcp/nm-dhcp-options.c index 22e7d90e..4c003f31 100644 --- a/src/dhcp/nm-dhcp-options.c +++ b/src/dhcp/nm-dhcp-options.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. + * Copyright (C) 2019 Red Hat, Inc. */ #include "nm-default.h" @@ -237,6 +223,7 @@ nm_dhcp_option_take_option (GHashTable *options, nm_assert (options); nm_assert (requests); nm_assert (value); + nm_assert (g_utf8_validate (value, -1, NULL)); g_hash_table_insert (options, (gpointer) nm_dhcp_option_request_string (requests, option), diff --git a/src/dhcp/nm-dhcp-options.h b/src/dhcp/nm-dhcp-options.h index f56edb19..bf9ccd57 100644 --- a/src/dhcp/nm-dhcp-options.h +++ b/src/dhcp/nm-dhcp-options.h @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2019 Red Hat, Inc. + * Copyright (C) 2019 Red Hat, Inc. */ #ifndef __NM_DHCP_OPTIONS_H__ diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/dhcp/nm-dhcp-systemd.c index 96409345..1518d465 100644 --- a/src/dhcp/nm-dhcp-systemd.c +++ b/src/dhcp/nm-dhcp-systemd.c @@ -1,18 +1,5 @@ +// SPDX-License-Identifier: LGPL-2.1+ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * Copyright (C) 2014 Red Hat, Inc. */ @@ -30,7 +17,6 @@ #include "nm-std-aux/unaligned.h" #include "nm-utils.h" -#include "nm-config.h" #include "nm-dhcp-utils.h" #include "nm-dhcp-options.h" #include "nm-core-utils.h" @@ -81,13 +67,6 @@ G_DEFINE_TYPE (NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT) /*****************************************************************************/ -#define LOG_LEASE(domain, ...) \ -G_STMT_START { \ - if (log_lease) { \ - _LOG2D ((domain), (iface), " "__VA_ARGS__); \ - } \ -} G_STMT_END - static NMIP4Config * lease_to_ip4_config (NMDedupMultiIndex *multi_idx, const char *iface, @@ -95,7 +74,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, sd_dhcp_lease *lease, guint32 route_table, guint32 route_metric, - gboolean log_lease, GHashTable **out_options, GError **error) { @@ -151,25 +129,17 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, options = out_options ? nm_dhcp_option_create_options_dict () : NULL; nm_utils_inet4_ntop (a_address.s_addr, addr_str); - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS), - addr_str); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, addr_str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, + addr_str); a_plen = nm_utils_ip4_netmask_to_prefix (a_netmask.s_addr); - LOG_LEASE (LOGD_DHCP4, "%s '%u'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_SUBNET_MASK), - (guint) a_plen); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_SUBNET_MASK, nm_utils_inet4_ntop (a_netmask.s_addr, addr_str)); - LOG_LEASE (LOGD_DHCP4, "%s '%u' seconds (at %lld)", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME), - (guint) a_lifetime, - (long long) (ts_time + a_lifetime)); nm_dhcp_option_add_option_u64 (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, @@ -200,9 +170,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, if (sd_dhcp_lease_get_server_identifier (lease, &server_id) >= 0) { nm_utils_inet4_ntop (server_id.s_addr, addr_str); - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_SERVER_ID), - addr_str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_SERVER_ID, @@ -211,9 +178,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, if (sd_dhcp_lease_get_broadcast (lease, &broadcast) >= 0) { nm_utils_inet4_ntop (broadcast.s_addr, addr_str); - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_BROADCAST), - addr_str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_BROADCAST, @@ -235,9 +199,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, } nm_ip4_config_add_nameserver (ip4_config, addr_list[i].s_addr); } - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER), - str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, @@ -251,9 +212,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, g_string_append (nm_gstring_add_space_delimiter (str), search_domains[i]); nm_ip4_config_add_search (ip4_config, search_domains[i]); } - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST), - str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, @@ -264,10 +222,10 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, gs_strfreev char **domains = NULL; char **d; - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME), - s); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, s); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, + s); /* Multiple domains sometimes stuffed into option 15 "Domain Name". * As systemd escapes such characters, split them at \\032. */ @@ -277,10 +235,10 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, } if (sd_dhcp_lease_get_hostname (lease, &s) >= 0) { - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_HOST_NAME), - s); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_HOST_NAME, s); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_HOST_NAME, + s); } num = sd_dhcp_lease_get_routes (lease, &routes); @@ -333,14 +291,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, nm_utils_inet4_ntop (network_net, network_net_str); nm_utils_inet4_ntop (r_gateway.s_addr, gateway_str); - LOG_LEASE (LOGD_DHCP4, - "%sstatic_route %s/%d gw %s", - option == NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE - ? "rfc3442_classless_" - : "", - network_net_str, - (int) r_plen, - gateway_str); g_string_append_printf (nm_gstring_add_space_delimiter ( option == NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE ? str_classless : str_static), @@ -442,17 +392,14 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, }), NULL); } - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROUTER), - str->str); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROUTER, str->str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_ROUTER, + str->str); } if ( sd_dhcp_lease_get_mtu (lease, &mtu) >= 0 && mtu) { - LOG_LEASE (LOGD_DHCP4, "%s '%u'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU), - mtu); nm_dhcp_option_add_option_u64 (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, @@ -467,9 +414,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, nm_utils_inet4_ntop (addr_list[i].s_addr, addr_str); g_string_append (nm_gstring_add_space_delimiter (str), addr_str); } - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NTP_SERVER), - str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NTP_SERVER, @@ -477,16 +421,13 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, } if (sd_dhcp_lease_get_root_path (lease, &s) >= 0) { - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROOT_PATH), - s); - nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROOT_PATH, s); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_ROOT_PATH, + s); } if (sd_dhcp_lease_get_t1 (lease, &renewal) >= 0) { - LOG_LEASE (LOGD_DHCP4, "%s '%u'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME), - renewal); nm_dhcp_option_add_option_u64 (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME, @@ -494,9 +435,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, } if (sd_dhcp_lease_get_t2 (lease, &rebinding) >= 0) { - LOG_LEASE (LOGD_DHCP4, "%s '%u'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME), - rebinding); nm_dhcp_option_add_option_u64 (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME, @@ -504,9 +442,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, } if (sd_dhcp_lease_get_timezone (lease, &s) >= 0) { - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE), - s); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE, @@ -525,9 +460,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, option_string = nm_utils_bin2hexstr_full (private_options[i].data, private_options[i].data_len, ':', FALSE, NULL); - LOG_LEASE (LOGD_DHCP4, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, private_options[i].code), - option_string); if (!options) { g_free (option_string); continue; @@ -544,37 +476,6 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, /*****************************************************************************/ -static char * -get_leasefile_path (int addr_family, const char *iface, const char *uuid) -{ - char *rundir_path; - char *statedir_path; - - rundir_path = g_strdup_printf (NMRUNDIR "/internal%s-%s-%s.lease", - addr_family == AF_INET6 ? "6" : "", - uuid, - iface); - - if (g_file_test (rundir_path, G_FILE_TEST_EXISTS)) - return rundir_path; - - statedir_path = g_strdup_printf (NMSTATEDIR "/internal%s-%s-%s.lease", - addr_family == AF_INET6 ? "6" : "", - uuid, - iface); - - if ( g_file_test (statedir_path, G_FILE_TEST_EXISTS) - || nm_config_get_configure_and_quit (nm_config_get ()) != NM_CONFIG_CONFIGURE_AND_QUIT_INITRD) { - g_free (rundir_path); - return statedir_path; - } else { - g_free (statedir_path); - return rundir_path; - } -} - -/*****************************************************************************/ - static void bound4_handle (NMDhcpSystemd *self) { @@ -600,7 +501,6 @@ bound4_handle (NMDhcpSystemd *self) lease, nm_dhcp_client_get_route_table (NM_DHCP_CLIENT (self)), nm_dhcp_client_get_route_metric (NM_DHCP_CLIENT (self)), - TRUE, &options, &error); if (!ip4_config) { @@ -713,9 +613,11 @@ ip4_start (NMDhcpClient *client, return FALSE; } - lease_file = get_leasefile_path (AF_INET, - nm_dhcp_client_get_iface (client), - nm_dhcp_client_get_uuid (client)); + nm_dhcp_utils_get_leasefile_path (AF_INET, + "internal", + nm_dhcp_client_get_iface (client), + nm_dhcp_client_get_uuid (client), + &lease_file); if (last_ip4_address) inet_pton (AF_INET, last_ip4_address, &last_addr); @@ -814,9 +716,9 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx, const char *iface, int ifindex, sd_dhcp6_lease *lease, - gboolean log_lease, gboolean info_only, GHashTable **out_options, + gint32 ts, GError **error) { gs_unref_object NMIP6Config *ip6_config = NULL; @@ -827,7 +729,6 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx, char **domains; nm_auto_free_gstring GString *str = NULL; int num, i; - const gint32 ts = nm_utils_get_monotonic_timestamp_s (); g_return_val_if_fail (lease, NULL); @@ -838,7 +739,6 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx, sd_dhcp6_lease_reset_address_iter (lease); nm_gstring_prepare (&str); while (sd_dhcp6_lease_get_address (lease, &tmp_addr, &lft_pref, &lft_valid) >= 0) { - char sbuf[400]; const NMPlatformIP6Address address = { .plen = 128, .address = tmp_addr, @@ -852,10 +752,6 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx, nm_utils_inet6_ntop (&tmp_addr, addr_str); g_string_append (nm_gstring_add_space_delimiter (str), addr_str); - - LOG_LEASE (LOGD_DHCP6, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp6_options, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS), - nm_platform_ip6_address_to_string (&address, sbuf, sizeof (sbuf))); }; if (str->len) nm_dhcp_option_add_option (options, @@ -880,9 +776,6 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx, g_string_append (nm_gstring_add_space_delimiter (str), addr_str); nm_ip6_config_add_nameserver (ip6_config, &dns[i]); } - LOG_LEASE (LOGD_DHCP6, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp6_options, NM_DHCP_OPTION_DHCP6_DNS_SERVERS), - str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp6_options, NM_DHCP_OPTION_DHCP6_DNS_SERVERS, @@ -896,9 +789,6 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx, g_string_append (nm_gstring_add_space_delimiter (str), domains[i]); nm_ip6_config_add_search (ip6_config, domains[i]); } - LOG_LEASE (LOGD_DHCP6, "%s '%s'", - nm_dhcp_option_request_string (_nm_dhcp_option_dhcp6_options, NM_DHCP_OPTION_DHCP6_DOMAIN_LIST), - str->str); nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp6_options, NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, @@ -913,10 +803,12 @@ static void bound6_handle (NMDhcpSystemd *self) { NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self); + const gint32 ts = nm_utils_get_monotonic_timestamp_s (); const char *iface = nm_dhcp_client_get_iface (NM_DHCP_CLIENT (self)); gs_unref_object NMIP6Config *ip6_config = NULL; gs_unref_hashtable GHashTable *options = NULL; gs_free_error GError *error = NULL; + NMPlatformIP6Address prefix = { 0 }; sd_dhcp6_lease *lease; if ( sd_dhcp6_client_get_lease (priv->client6, &lease) < 0 @@ -932,9 +824,9 @@ bound6_handle (NMDhcpSystemd *self) iface, nm_dhcp_client_get_ifindex (NM_DHCP_CLIENT (self)), lease, - TRUE, nm_dhcp_client_get_info_only (NM_DHCP_CLIENT (self)), &options, + ts, &error); if (!ip6_config) { @@ -947,6 +839,16 @@ bound6_handle (NMDhcpSystemd *self) NM_DHCP_STATE_BOUND, NM_IP_CONFIG_CAST (ip6_config), options); + + sd_dhcp6_lease_reset_pd_prefix_iter (lease); + while (!sd_dhcp6_lease_get_pd (lease, + &prefix.address, + &prefix.plen, + &prefix.preferred, + &prefix.lifetime)) { + prefix.timestamp = ts; + nm_dhcp_client_emit_ipv6_prefix_delegated (NM_DHCP_CLIENT (self), &prefix); + } } static void @@ -990,7 +892,6 @@ ip6_start (NMDhcpClient *client, nm_auto (sd_dhcp6_client_unrefp) sd_dhcp6_client *sd_client = NULL; GBytes *hwaddr; const char *hostname; - const char *iface; int r, i; const guint8 *duid_arr; gsize duid_len; @@ -1015,22 +916,13 @@ ip6_start (NMDhcpClient *client, return FALSE; } - if (needed_prefixes > 0) { - _LOGW ("dhcp-client6: prefix delegation not yet supported, won't supply %d prefixes", - needed_prefixes); - } - _LOGT ("dhcp-client6: set %p", sd_client); if (nm_dhcp_client_get_info_only (client)) sd_dhcp6_client_set_information_request (sd_client, 1); - iface = nm_dhcp_client_get_iface (client); - r = sd_dhcp6_client_set_iaid (sd_client, - nm_utils_create_dhcp_iaid (TRUE, - (const guint8 *) iface, - strlen (iface))); + nm_dhcp_client_get_iaid (client)); if (r < 0) { nm_utils_error_set_errno (error, r, "failed to set IAID: %s"); return FALSE; @@ -1082,6 +974,18 @@ ip6_start (NMDhcpClient *client, } } + if (needed_prefixes > 0) { + if (needed_prefixes > 1) + _LOGW ("dhcp-client6: only one prefix request is supported"); + /* FIXME: systemd-networkd API only allows to request a + * single prefix */ + r = sd_dhcp6_client_set_prefix_delegation (sd_client, TRUE); + if (r < 0) { + nm_utils_error_set_errno (error, r, "failed to enable prefix delegation: %s"); + return FALSE; + } + } + r = sd_dhcp6_client_set_local_address (sd_client, ll_addr); if (r < 0) { nm_utils_error_set_errno (error, r, "failed to set local address: %s"); @@ -1182,8 +1086,25 @@ nm_dhcp_systemd_class_init (NMDhcpSystemdClass *sdhcp_class) client_class->stop = stop; } +const NMDhcpClientFactory _nm_dhcp_client_factory_systemd = { + .name = "systemd", + .get_type = nm_dhcp_systemd_get_type, + .experimental = TRUE, +}; + +/*****************************************************************************/ + +static GType +_get_type_per_addr_family (int addr_family) +{ + nm_assert_addr_family (addr_family); + + if (addr_family == AF_INET) + return nm_dhcp_nettools_get_type (); + return nm_dhcp_systemd_get_type (); +} + const NMDhcpClientFactory _nm_dhcp_client_factory_internal = { - .name = "internal", - .get_type = nm_dhcp_systemd_get_type, - .get_path = NULL, + .name = "internal", + .get_type_per_addr_family = _get_type_per_addr_family, }; diff --git a/src/dhcp/nm-dhcp-utils.c b/src/dhcp/nm-dhcp-utils.c index 3f9368f2..c5da3e02 100644 --- a/src/dhcp/nm-dhcp-utils.c +++ b/src/dhcp/nm-dhcp-utils.c @@ -1,19 +1,6 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2005 - 2010 Red Hat, Inc. - * */ #include "nm-default.h" @@ -25,6 +12,7 @@ #include "nm-dhcp-utils.h" #include "nm-utils.h" +#include "nm-config.h" #include "NetworkManagerUtils.h" #include "platform/nm-platform.h" #include "nm-dhcp-client-logging.h" @@ -762,3 +750,55 @@ nm_dhcp_utils_client_id_string_to_bytes (const char *client_id) return bytes; } +/** + * nm_dhcp_utils_get_leasefile_path: + * @addr_family: the IP address family + * @plugin_name: the name of the plugin part of the lease file name + * @iface: the interface name to which the lease relates to + * @uuid: uuid of the connection to which the lease relates to + * @out_leasefile_path: will store the computed lease file path + * + * Constructs the lease file name on the basis of the calling plugin, + * interface name and connection uuid. Then returns in @out_leasefile_path + * the full path of the lease filename. + * + * Returns: TRUE if the lease file already exists, FALSE otherwise. + */ +gboolean +nm_dhcp_utils_get_leasefile_path (int addr_family, + const char *plugin_name, + const char *iface, + const char *uuid, + char **out_leasefile_path) +{ + gs_free char *rundir_path = NULL; + gs_free char *statedir_path = NULL; + + rundir_path = g_strdup_printf (NMRUNDIR "/%s%s-%s-%s.lease", + plugin_name, + addr_family == AF_INET6 ? "6" : "", + uuid, + iface); + + if (g_file_test (rundir_path, G_FILE_TEST_EXISTS)) { + *out_leasefile_path = g_steal_pointer (&rundir_path); + return TRUE; + } + + statedir_path = g_strdup_printf (NMSTATEDIR "/%s%s-%s-%s.lease", + plugin_name, + addr_family == AF_INET6 ? "6" : "", + uuid, + iface); + + if (g_file_test (statedir_path, G_FILE_TEST_EXISTS)) { + *out_leasefile_path = g_steal_pointer (&statedir_path); + return TRUE; + } + + if (nm_config_get_configure_and_quit (nm_config_get ()) == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD) + *out_leasefile_path = g_steal_pointer (&rundir_path); + else + *out_leasefile_path = g_steal_pointer (&statedir_path); + return FALSE; +} diff --git a/src/dhcp/nm-dhcp-utils.h b/src/dhcp/nm-dhcp-utils.h index 39ae7693..e4c33314 100644 --- a/src/dhcp/nm-dhcp-utils.h +++ b/src/dhcp/nm-dhcp-utils.h @@ -1,17 +1,5 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2014 Red Hat, Inc. */ @@ -40,7 +28,13 @@ NMPlatformIP6Address nm_dhcp_utils_ip6_prefix_from_options (GHashTable *options) char *nm_dhcp_utils_duid_to_string (GBytes *duid); -GBytes * nm_dhcp_utils_client_id_string_to_bytes (const char *client_id); +GBytes *nm_dhcp_utils_client_id_string_to_bytes (const char *client_id); + +gboolean nm_dhcp_utils_get_leasefile_path (int addr_family, + const char *plugin_name, + const char *iface, + const char *uuid, + char **out_leasefile_path); #endif /* __NETWORKMANAGER_DHCP_UTILS_H__ */ diff --git a/src/dhcp/tests/meson.build b/src/dhcp/tests/meson.build index 43b33951..031e2efd 100644 --- a/src/dhcp/tests/meson.build +++ b/src/dhcp/tests/meson.build @@ -7,7 +7,8 @@ foreach test_unit: test_units exe = executable( test_unit, test_unit + '.c', - dependencies: test_nm_dep, + dependencies: libnetwork_manager_test_dep, + c_args: test_c_flags, ) test( diff --git a/src/dhcp/tests/test-dhcp-dhclient.c b/src/dhcp/tests/test-dhcp-dhclient.c index 9e51fceb..761f9cdb 100644 --- a/src/dhcp/tests/test-dhcp-dhclient.c +++ b/src/dhcp/tests/test-dhcp-dhclient.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+ /* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * * Copyright (C) 2010 Red Hat, Inc. - * */ #include "nm-default.h" @@ -43,6 +29,7 @@ test_config (const char *orig, const char *hostname, guint32 timeout, gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, const char *dhcp_client_id, GBytes *expected_new_client_id, const char *iface, @@ -64,6 +51,7 @@ test_config (const char *orig, hostname, timeout, use_fqdn, + hostname_flags, "/path/to/dhclient.conf", orig, &new_client_id); @@ -108,7 +96,11 @@ static const char *orig_missing_expected = \ static void test_orig_missing (void) { - test_config (NULL, orig_missing_expected, AF_INET, NULL, 0, FALSE, NULL, NULL, "eth0", NULL); + test_config (NULL, + orig_missing_expected, + AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, NULL, "eth0", NULL); } /*****************************************************************************/ @@ -139,6 +131,7 @@ 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", @@ -169,6 +162,7 @@ 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", @@ -199,6 +193,7 @@ 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", @@ -229,6 +224,7 @@ 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", @@ -259,6 +255,7 @@ 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", @@ -289,6 +286,7 @@ 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", @@ -327,6 +325,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, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, new_client_id, "eth0", @@ -364,6 +363,7 @@ test_existing_escaped_client_id (void) 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", @@ -405,6 +405,7 @@ test_existing_ascii_client_id (void) 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", @@ -417,7 +418,8 @@ static const char *fqdn_expected = \ "\n" "send fqdn.fqdn \"foo.bar.com\"; # added by NetworkManager\n" "send fqdn.encoded on;\n" - "send fqdn.server-update 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" @@ -435,7 +437,10 @@ test_fqdn (void) { test_config (NULL, fqdn_expected, AF_INET, "foo.bar.com", 0, - TRUE, NULL, + TRUE, + NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED + | NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE, + NULL, NULL, "eth0", NULL); @@ -452,8 +457,9 @@ static const char *fqdn_options_override_expected = \ "# Merged from /path/to/dhclient.conf\n" "\n" "send fqdn.fqdn \"example2.com\"; # added by NetworkManager\n" - "send fqdn.encoded on;\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" @@ -476,6 +482,7 @@ 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", @@ -510,6 +517,7 @@ 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", @@ -538,6 +546,7 @@ 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", @@ -550,7 +559,7 @@ static const char *nonfqdn_hostname6_expected = \ "# Created by NetworkManager\n" "\n" "send fqdn.fqdn \"blahblah\"; # added by NetworkManager\n" - "send fqdn.server-update on;\n" + "send fqdn.no-client-update on;\n" "\n" "also request dhcp6.name-servers;\n" "also request dhcp6.domain-search;\n" @@ -563,6 +572,7 @@ 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", @@ -599,6 +609,7 @@ 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", @@ -638,6 +649,7 @@ 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", @@ -678,6 +690,7 @@ 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", @@ -917,6 +930,7 @@ test_interface1 (void) { test_config (interface1_orig, interface1_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, NULL, "eth0", @@ -963,6 +977,7 @@ test_interface2 (void) { test_config (interface2_orig, interface2_expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, NULL, "eth1", @@ -1074,6 +1089,7 @@ test_structured (void) 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", @@ -1129,6 +1145,7 @@ test_config_req_intf (void) test_config (orig, expected, AF_INET, NULL, 0, FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, NULL, NULL, "eth0", diff --git a/src/dhcp/tests/test-dhcp-utils.c b/src/dhcp/tests/test-dhcp-utils.c index e4d4c348..d0389069 100644 --- a/src/dhcp/tests/test-dhcp-utils.c +++ b/src/dhcp/tests/test-dhcp-utils.c @@ -1,19 +1,6 @@ -/* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * +// SPDX-License-Identifier: GPL-2.0+ +/* * Copyright (C) 2008 - 2014 Red Hat, Inc. - * */ #include "nm-default.h" |