summary refs log tree commit diff
path: root/src/core/dhcp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/dhcp')
-rw-r--r--src/core/dhcp/nm-dhcp-client-logging.h7
-rw-r--r--src/core/dhcp/nm-dhcp-client.c10
-rw-r--r--src/core/dhcp/nm-dhcp-client.h9
-rw-r--r--src/core/dhcp/nm-dhcp-dhclient.c12
-rw-r--r--src/core/dhcp/nm-dhcp-helper.c31
-rw-r--r--src/core/dhcp/nm-dhcp-options.c2
-rw-r--r--src/core/dhcp/nm-dhcp-options.h3
-rw-r--r--src/core/dhcp/nm-dhcp-systemd.c29
8 files changed, 85 insertions, 18 deletions
diff --git a/src/core/dhcp/nm-dhcp-client-logging.h b/src/core/dhcp/nm-dhcp-client-logging.h
index 2b0d8d06..3a2b927a 100644
--- a/src/core/dhcp/nm-dhcp-client-logging.h
+++ b/src/core/dhcp/nm-dhcp-client-logging.h
@@ -41,16 +41,19 @@ _nm_dhcp_client_get_domain(NMDhcpClient *self)
         if (nm_logging_enabled(_level, _NMLOG_DOMAIN)) {                                 \
             NMDhcpClient     *_self    = (NMDhcpClient *) (self);                        \
             const char       *__ifname = _self ? nm_dhcp_client_get_iface(_self) : NULL; \
+            const char       *_type    = nm_dhcp_client_get_iface_type_for_log(_self);   \
             const NMLogDomain _domain  = _nm_dhcp_client_get_domain(_self);              \
                                                                                          \
             nm_log(_level,                                                               \
                    _domain,                                                              \
                    __ifname,                                                             \
                    NULL,                                                                 \
-                   "%s%s%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__),                    \
+                   "%s%s%s%s%s%s%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__),            \
                    _NMLOG_PREFIX_NAME,                                                   \
                    (_domain == LOGD_DHCP4 ? "4" : (_domain == LOGD_DHCP6 ? "6" : "")),   \
-                   NM_PRINT_FMT_QUOTED(__ifname, " (", __ifname, ")", "")                \
+                   (__ifname || _type) ? " " : "",                                       \
+                   NM_PRINT_FMT_QUOTED(__ifname, "(", __ifname, ")", ""),                \
+                   NM_PRINT_FMT_QUOTED(_type, "[", _type, "]", "")                       \
                        _NM_UTILS_MACRO_REST(__VA_ARGS__));                               \
         }                                                                                \
     }                                                                                    \
diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c
index b10ce410..6978bd3c 100644
--- a/src/core/dhcp/nm-dhcp-client.c
+++ b/src/core/dhcp/nm-dhcp-client.c
@@ -196,6 +196,14 @@ nm_dhcp_client_get_iface(NMDhcpClient *self)
     return priv->config.iface;
 }
 
+const char *
+nm_dhcp_client_get_iface_type_for_log(NMDhcpClient *self)
+{
+    NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+    return priv->config.iface_type_log;
+}
+
 NMDedupMultiIndex *
 nm_dhcp_client_get_multi_idx(NMDhcpClient *self)
 {
@@ -1823,6 +1831,7 @@ config_init(NMDhcpClientConfig *config, const NMDhcpClientConfig *src)
     nm_g_bytes_ref(config->client_id);
 
     config->iface           = g_strdup(config->iface);
+    config->iface_type_log  = g_strdup(config->iface_type_log);
     config->uuid            = g_strdup(config->uuid);
     config->anycast_address = g_strdup(config->anycast_address);
     config->hostname        = g_strdup(config->hostname);
@@ -1885,6 +1894,7 @@ config_clear(NMDhcpClientConfig *config)
     nm_clear_pointer(&config->client_id, g_bytes_unref);
 
     nm_clear_g_free((gpointer *) &config->iface);
+    nm_clear_g_free((gpointer *) &config->iface_type_log);
     nm_clear_g_free((gpointer *) &config->uuid);
     nm_clear_g_free((gpointer *) &config->anycast_address);
     nm_clear_g_free((gpointer *) &config->hostname);
diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h
index f43770a0..903ea6ac 100644
--- a/src/core/dhcp/nm-dhcp-client.h
+++ b/src/core/dhcp/nm-dhcp-client.h
@@ -103,6 +103,10 @@ typedef struct {
 
     const char *iface;
 
+    /* Interface type for logging; only set for some devices whose names can be
+     * ambiguous. */
+    const char *iface_type_log;
+
     /* The hardware address */
     GBytes *hwaddr;
 
@@ -174,6 +178,10 @@ typedef struct {
             /* Number to prefixes (IA_PD) to request */
             guint needed_prefixes;
 
+            /* A hint to send to server for prefix delegation (IA_PD). */
+            struct in6_addr pd_hint_addr;
+            guint8          pd_hint_length;
+
             /* Use Information-request to get stateless configuration
              * parameters (don't request a IA_NA) */
             bool info_only : 1;
@@ -260,6 +268,7 @@ gboolean nm_dhcp_client_server_id_is_rejected(NMDhcpClient *self, gconstpointer
 
 int                nm_dhcp_client_get_addr_family(NMDhcpClient *self);
 const char        *nm_dhcp_client_get_iface(NMDhcpClient *self);
+const char        *nm_dhcp_client_get_iface_type_for_log(NMDhcpClient *self);
 NMDedupMultiIndex *nm_dhcp_client_get_multi_idx(NMDhcpClient *self);
 int                nm_dhcp_client_get_ifindex(NMDhcpClient *self);
 
diff --git a/src/core/dhcp/nm-dhcp-dhclient.c b/src/core/dhcp/nm-dhcp-dhclient.c
index 35b2fb2e..4aab4b1e 100644
--- a/src/core/dhcp/nm-dhcp-dhclient.c
+++ b/src/core/dhcp/nm-dhcp-dhclient.c
@@ -356,6 +356,7 @@ dhclient_start(NMDhcpClient *client,
     gs_free char                *preferred_leasefile_path = NULL;
     int                          addr_family;
     const NMDhcpClientConfig    *client_config;
+    char                         pd_length_str[16];
 
     g_return_val_if_fail(!priv->pid_file, FALSE);
     client_config = nm_dhcp_client_get_config(client);
@@ -463,6 +464,17 @@ dhclient_start(NMDhcpClient *client,
 
         if (mode_opt)
             g_ptr_array_add(argv, (gpointer) mode_opt);
+
+        if (prefixes > 0 && client_config->v6.pd_hint_length > 0) {
+            if (!IN6_IS_ADDR_UNSPECIFIED(&client_config->v6.pd_hint_addr)) {
+                _LOGW("dhclient only supports a length as prefix delegation hint, not a prefix");
+            }
+
+            nm_sprintf_buf(pd_length_str, "%u", client_config->v6.pd_hint_length);
+            g_ptr_array_add(argv, "--prefix-len-hint");
+            g_ptr_array_add(argv, pd_length_str);
+        }
+
         while (prefixes--)
             g_ptr_array_add(argv, (gpointer) "-P");
     }
diff --git a/src/core/dhcp/nm-dhcp-helper.c b/src/core/dhcp/nm-dhcp-helper.c
index 213d9496..ee95abb7 100644
--- a/src/core/dhcp/nm-dhcp-helper.c
+++ b/src/core/dhcp/nm-dhcp-helper.c
@@ -21,21 +21,22 @@
 #define _NMLOG_ENABLED(level) ((level) <= LOG_ERR)
 #endif
 
-#define _NMLOG(always_enabled, level, ...)                                                       \
-    G_STMT_START                                                                                 \
-    {                                                                                            \
-        if ((always_enabled) || _NMLOG_ENABLED(level)) {                                         \
-            GTimeVal _tv;                                                                        \
-                                                                                                 \
-            g_get_current_time(&_tv);                                                            \
-            g_print(                                                                             \
-                "nm-dhcp-helper[%ld] %-7s [%ld.%04ld] " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) "\n", \
-                (long) getpid(),                                                                 \
-                nm_utils_syslog_to_str(level),                                                   \
-                _tv.tv_sec,                                                                      \
-                _tv.tv_usec / 100 _NM_UTILS_MACRO_REST(__VA_ARGS__));                            \
-        }                                                                                        \
-    }                                                                                            \
+#define _NMLOG(always_enabled, level, ...)                                     \
+    G_STMT_START                                                               \
+    {                                                                          \
+        if ((always_enabled) || _NMLOG_ENABLED(level)) {                       \
+            gint64 _tv;                                                        \
+                                                                               \
+            _tv = g_get_real_time();                                           \
+            g_print("nm-dhcp-helper[%ld] %-7s [%" G_GINT64_FORMAT              \
+                    ".%04d] " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) "\n",         \
+                    (long) getpid(),                                           \
+                    nm_utils_syslog_to_str(level),                             \
+                    (_tv / NM_UTILS_USEC_PER_SEC),                             \
+                    ((int) ((_tv % NM_UTILS_USEC_PER_SEC) / (((gint64) 100)))) \
+                        _NM_UTILS_MACRO_REST(__VA_ARGS__));                    \
+        }                                                                      \
+    }                                                                          \
     G_STMT_END
 
 #define _LOGD(...) _NMLOG(TRUE, LOG_INFO, __VA_ARGS__)
diff --git a/src/core/dhcp/nm-dhcp-options.c b/src/core/dhcp/nm-dhcp-options.c
index 33a9f4ed..7c47c82e 100644
--- a/src/core/dhcp/nm-dhcp-options.c
+++ b/src/core/dhcp/nm-dhcp-options.c
@@ -199,6 +199,7 @@ const NMDhcpOption _nm_dhcp_option_dhcp6_options[] = {
 
     REQ(NM_DHCP_OPTION_DHCP6_DNS_SERVERS, "dhcp6_name_servers", TRUE),
     REQ(NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, "dhcp6_domain_search", TRUE),
+    REQ(NM_DHCP_OPTION_DHCP6_IA_PD, "ip6_prefix", FALSE),
     REQ(NM_DHCP_OPTION_DHCP6_SNTP_SERVERS, "dhcp6_sntp_servers", TRUE),
     REQ(NM_DHCP_OPTION_DHCP6_FQDN, "fqdn_fqdn", FALSE),
     REQ(NM_DHCP_OPTION_DHCP6_NTP_SERVER, "dhcp6_ntp_servers", TRUE),
@@ -237,6 +238,7 @@ static const NMDhcpOption *const _sorted_options_6[G_N_ELEMENTS(_nm_dhcp_option_
     A(14),
     A(15),
     A(16),
+    A(17),
 #undef A
 };
 
diff --git a/src/core/dhcp/nm-dhcp-options.h b/src/core/dhcp/nm-dhcp-options.h
index 050080d9..1c61c74d 100644
--- a/src/core/dhcp/nm-dhcp-options.h
+++ b/src/core/dhcp/nm-dhcp-options.h
@@ -161,6 +161,7 @@ typedef enum {
     NM_DHCP_OPTION_DHCP6_SERVER_ID    = 2,
     NM_DHCP_OPTION_DHCP6_DNS_SERVERS  = 23,
     NM_DHCP_OPTION_DHCP6_DOMAIN_LIST  = 24,
+    NM_DHCP_OPTION_DHCP6_IA_PD        = 25, /* RFC 8415 */
     NM_DHCP_OPTION_DHCP6_SNTP_SERVERS = 31,
     NM_DHCP_OPTION_DHCP6_FQDN         = 39,
     NM_DHCP_OPTION_DHCP6_NTP_SERVER   = 56, /* RFC 5908 */
@@ -188,7 +189,7 @@ typedef struct {
 } NMDhcpOption;
 
 extern const NMDhcpOption _nm_dhcp_option_dhcp4_options[143];
-extern const NMDhcpOption _nm_dhcp_option_dhcp6_options[17];
+extern const NMDhcpOption _nm_dhcp_option_dhcp6_options[18];
 
 static inline const char *
 nm_dhcp_option_get_name(const NMDhcpOption *option)
diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c
index 6f9312da..0fc5f928 100644
--- a/src/core/dhcp/nm-dhcp-systemd.c
+++ b/src/core/dhcp/nm-dhcp-systemd.c
@@ -155,6 +155,26 @@ lease_to_ip6_config(NMDhcpSystemd *self, sd_dhcp6_lease *lease, gint32 ts, GErro
                                   str->str);
     }
 
+    {
+        struct in6_addr prefix;
+        uint8_t         prefix_len;
+
+        nm_gstring_prepare(&str);
+        sd_dhcp6_lease_reset_pd_prefix_iter(lease);
+        while (!sd_dhcp6_lease_get_pd(lease, &prefix, &prefix_len, NULL, NULL)) {
+            nm_gstring_add_space_delimiter(str);
+            nm_inet6_ntop(&prefix, addr_str);
+            g_string_append_printf(str, "%s/%u", addr_str, prefix_len);
+        }
+        if (str->len > 0) {
+            nm_dhcp_option_add_option(options,
+                                      TRUE,
+                                      AF_INET6,
+                                      NM_DHCP_OPTION_DHCP6_IA_PD,
+                                      str->str);
+        }
+    }
+
     num = sd_dhcp6_lease_get_domains(lease, &domains);
     if (num > 0) {
         nm_gstring_prepare(&str);
@@ -366,6 +386,15 @@ ip6_start(NMDhcpClient *client, const struct in6_addr *ll_addr, GError **error)
             _LOGW("dhcp-client6: only one prefix request is supported");
         }
         prefix_delegation = TRUE;
+        if (client_config->v6.pd_hint_length > 0) {
+            r = sd_dhcp6_client_set_prefix_delegation_hint(sd_client,
+                                                           client_config->v6.pd_hint_length,
+                                                           &client_config->v6.pd_hint_addr);
+            if (r < 0) {
+                nm_utils_error_set_errno(error, r, "failed to set prefix delegation hint: %s");
+                return FALSE;
+            }
+        }
     }
     r = sd_dhcp6_client_set_prefix_delegation(sd_client, prefix_delegation);
     if (r < 0) {