summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2022-04-19 18:09:49 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2022-05-03 09:12:12 +0200
commit6ab5c4e578b8d18e16c2d17c9d7f009b804ccc5b (patch)
treeadb591510b5fb10f7ff8eb20edee2304e5088b2f
parent96d8637ceda382733f027615c36e0beb80abfca1 (diff)
downloadNetworkManager-6ab5c4e578b8d18e16c2d17c9d7f009b804ccc5b.tar.gz
core: save DHCP lease information in state file in /run
DHCP leases for a given interface are already exported on D-Bus through DHCP4Config and DHCP6Config objects. It is useful to have the same information also available on the filesystem so that it can be easily used by scripts. NM already saves some information about DHCP leases in /var, however that directory can only be accessed by root, for good reasons. Append lease options to the existing state file /run/NetworkManager/devices/$ifindex. Contrary to /var this directory is not persistent, but it seems more correct to expose the lease only when it is active and not after it expired or after a reboot. Since the file is in keyfile format, we add new [dhcp4] and [dhcp6] sections; however, since some options have the same name for DHCPv4 and DHCPv6, we add a "dhcp4." or "dhcp6." prefix to make the parsing by scripts (e.g. via "grep") easier. The option name is the same we use on D-Bus. Since some DHCPv6 options also have a "dhcp6_" prefix, the key name can contain "dhcp6" twice. The new sections look like this: [dhcp4] dhcp4.broadcast_address=172.25.1.255 dhcp4.dhcp_lease_time=120 dhcp4.dhcp_server_identifier=172.25.1.4 dhcp4.domain_name_servers=172.25.1.4 dhcp4.domain_search=example.com dhcp4.expiry=1641214444 dhcp4.ip_address=172.25.1.182 dhcp4.next_server=172.25.1.4 dhcp4.routers=172.25.1.4 dhcp4.subnet_mask=255.255.255.0 [dhcp6] dhcp6.dhcp6_name_servers=fd01::1 dhcp6.dhcp6_ntp_servers=ntp.example.com dhcp6.ip6_address=fd01::1aa
-rw-r--r--NEWS3
-rw-r--r--src/core/devices/nm-device.c1
-rw-r--r--src/core/nm-config.c46
-rw-r--r--src/core/nm-config.h5
-rw-r--r--src/core/nm-manager.c18
5 files changed, 49 insertions, 24 deletions
diff --git a/NEWS b/NEWS
index 4bf6269ac8..9db05c5b7f 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,9 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
* Static IPv6 addresses from "ipv6.addresses" are now interpreted with
first address being preferred. Their order got inverted. This is now
consistent with IPv4.
+* The device state file /run/NetworkManager/devices/$ifindex now has
+ new sections [dhcp4] and [dhcp6] containing the DHCP options for the
+ current lease.
=============================================
NetworkManager-1.38
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index d1702f23a5..d77f3fa501 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -10064,6 +10064,7 @@ _dev_ipdhcpx_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_d
FALSE);
if (notify_data->lease_update.accepted) {
+ nm_manager_write_device_state(priv->manager, self, NULL);
if (priv->ipdhcp_data_x[IS_IPv4].state != NM_DEVICE_IP_STATE_READY) {
_dev_ipdhcpx_set_state(self, addr_family, NM_DEVICE_IP_STATE_READY);
nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_X(IS_IPv4),
diff --git a/src/core/nm-config.c b/src/core/nm-config.c
index ea1c2ab300..cdc070900f 100644
--- a/src/core/nm-config.c
+++ b/src/core/nm-config.c
@@ -11,7 +11,9 @@
#include <stdio.h>
#include "nm-utils.h"
+#include "nm-dhcp-config.h"
#include "devices/nm-device.h"
+#include "dhcp/nm-dhcp-options.h"
#include "NetworkManagerUtils.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "libnm-core-intern/nm-keyfile-internal.h"
@@ -2573,13 +2575,16 @@ nm_config_device_state_write(int ifindex,
NMTernary nm_owned,
guint32 route_metric_default_aspired,
guint32 route_metric_default_effective,
- const char *next_server,
- const char *root_path,
- const char *dhcp_bootfile)
+ NMDhcpConfig *dhcp4_config,
+ NMDhcpConfig *dhcp6_config)
{
char path[NM_STRLEN(NM_CONFIG_DEVICE_STATE_DIR "/") + DEVICE_STATE_FILENAME_LEN_MAX + 1];
- GError *local = NULL;
- nm_auto_unref_keyfile GKeyFile *kf = NULL;
+ GError *local = NULL;
+ nm_auto_unref_keyfile GKeyFile *kf = NULL;
+ const char *root_path = NULL;
+ const char *next_server = NULL;
+ const char *dhcp_bootfile = NULL;
+ int IS_IPv4;
g_return_val_if_fail(ifindex > 0, FALSE);
g_return_val_if_fail(!connection_uuid || *connection_uuid, FALSE);
@@ -2630,6 +2635,15 @@ nm_config_device_state_write(int ifindex,
route_metric_default_aspired);
}
}
+
+ if (dhcp4_config) {
+ next_server = nm_dhcp_config_get_option(dhcp4_config, "next_server");
+ root_path = nm_dhcp_config_get_option(dhcp4_config, "root_path");
+ dhcp_bootfile = nm_dhcp_config_get_option(dhcp4_config, "filename");
+ if (!dhcp_bootfile)
+ dhcp_bootfile = nm_dhcp_config_get_option(dhcp4_config, "bootfile_name");
+ }
+
if (next_server) {
g_key_file_set_string(kf,
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
@@ -2649,6 +2663,28 @@ nm_config_device_state_write(int ifindex,
dhcp_bootfile);
}
+ for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
+ NMDhcpConfig *dhcp_config = IS_IPv4 ? dhcp4_config : dhcp6_config;
+ gs_free NMUtilsNamedValue *values = NULL;
+ guint i;
+ guint num;
+
+ if (!dhcp_config)
+ continue;
+
+ values = nm_dhcp_config_get_option_values(dhcp_config, &num);
+ for (i = 0; i < num; i++) {
+ gs_free char *name_full = NULL;
+ const char *prefix = IS_IPv4 ? "dhcp4" : "dhcp6";
+
+ if (NM_STR_HAS_PREFIX(values[i].name, NM_DHCP_OPTION_REQPREFIX))
+ continue;
+
+ name_full = g_strdup_printf("%s.%s", prefix, values[i].name);
+ g_key_file_set_string(kf, prefix, name_full, values[i].value_str);
+ }
+ }
+
if (!g_key_file_save_to_file(kf, path, &local)) {
_LOGW("device-state: write #%d (%s) failed: %s", ifindex, path, local->message);
g_error_free(local);
diff --git a/src/core/nm-config.h b/src/core/nm-config.h
index 2c23ff200e..d7498f92be 100644
--- a/src/core/nm-config.h
+++ b/src/core/nm-config.h
@@ -183,9 +183,8 @@ gboolean nm_config_device_state_write(int
NMTernary nm_owned,
guint32 route_metric_default_aspired,
guint32 route_metric_default_effective,
- const char *next_server,
- const char *root_path,
- const char *dhcp_bootfile);
+ NMDhcpConfig *dhcp4_config,
+ NMDhcpConfig *dhcp6_config);
void nm_config_device_state_prune_stale(GHashTable *preserve_ifindexes,
NMPlatform *preserve_in_platform);
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c
index 191d65bf65..ee661e499e 100644
--- a/src/core/nm-manager.c
+++ b/src/core/nm-manager.c
@@ -7039,10 +7039,6 @@ nm_manager_write_device_state(NMManager *self, NMDevice *device, int *out_ifinde
guint32 route_metric_default_aspired;
guint32 route_metric_default_effective;
NMTernary nm_owned;
- NMDhcpConfig *dhcp_config;
- const char *next_server = NULL;
- const char *root_path = NULL;
- const char *dhcp_bootfile = NULL;
NM_SET_OUT(out_ifindex, 0);
@@ -7084,15 +7080,6 @@ nm_manager_write_device_state(NMManager *self, NMDevice *device, int *out_ifinde
TRUE,
&route_metric_default_aspired);
- dhcp_config = nm_device_get_dhcp_config(device, AF_INET);
- if (dhcp_config) {
- root_path = nm_dhcp_config_get_option(dhcp_config, "root_path");
- next_server = nm_dhcp_config_get_option(dhcp_config, "next_server");
- dhcp_bootfile = nm_dhcp_config_get_option(dhcp_config, "filename");
- if (!dhcp_bootfile)
- dhcp_bootfile = nm_dhcp_config_get_option(dhcp_config, "bootfile_name");
- }
-
if (!nm_config_device_state_write(ifindex,
managed_type,
perm_hw_addr_fake,
@@ -7100,9 +7087,8 @@ nm_manager_write_device_state(NMManager *self, NMDevice *device, int *out_ifinde
nm_owned,
route_metric_default_aspired,
route_metric_default_effective,
- next_server,
- root_path,
- dhcp_bootfile))
+ nm_device_get_dhcp_config(device, AF_INET),
+ nm_device_get_dhcp_config(device, AF_INET6)))
return FALSE;
NM_SET_OUT(out_ifindex, ifindex);