summary refs log tree commit diff
path: root/src/core/dhcp/nm-dhcp-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/dhcp/nm-dhcp-client.c')
-rw-r--r--src/core/dhcp/nm-dhcp-client.c160
1 files changed, 91 insertions, 69 deletions
diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c
index 3b0343fd..ab8243d0 100644
--- a/src/core/dhcp/nm-dhcp-client.c
+++ b/src/core/dhcp/nm-dhcp-client.c
@@ -13,15 +13,16 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <linux/rtnetlink.h>
+#include <linux/if_ether.h>
 
-#include "nm-glib-aux/nm-dedup-multi.h"
-#include "nm-glib-aux/nm-random-utils.h"
+#include "libnm-glib-aux/nm-dedup-multi.h"
+#include "libnm-glib-aux/nm-random-utils.h"
 
 #include "NetworkManagerUtils.h"
 #include "nm-utils.h"
 #include "nm-dhcp-utils.h"
 #include "nm-dhcp-options.h"
-#include "platform/nm-platform.h"
+#include "libnm-platform/nm-platform.h"
 
 #include "nm-dhcp-client-logging.h"
 
@@ -33,6 +34,7 @@ static guint signals[LAST_SIGNAL] = {0};
 
 NM_GOBJECT_PROPERTIES_DEFINE(NMDhcpClient,
                              PROP_ADDR_FAMILY,
+                             PROP_ANYCAST_ADDRESS,
                              PROP_FLAGS,
                              PROP_HWADDR,
                              PROP_BROADCAST_HWADDR,
@@ -61,6 +63,7 @@ typedef struct _NMDhcpClientPrivate {
     char *              hostname;
     const char **       reject_servers;
     char *              mud_url;
+    char *              anycast_address;
     GBytes *            vendor_class_identifier;
     pid_t               pid;
     guint               timeout_id;
@@ -73,8 +76,7 @@ typedef struct _NMDhcpClientPrivate {
     guint32             iaid;
     NMDhcpState         state;
     NMDhcpHostnameFlags hostname_flags;
-    bool                info_only : 1;
-    bool                use_fqdn : 1;
+    NMDhcpClientFlags   client_flags;
     bool                iaid_explicit : 1;
 } NMDhcpClientPrivate;
 
@@ -282,6 +284,14 @@ nm_dhcp_client_set_client_id_bin(NMDhcpClient *self,
 }
 
 const char *
+nm_dhcp_client_get_anycast_address(NMDhcpClient *self)
+{
+    g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
+
+    return NM_DHCP_CLIENT_GET_PRIVATE(self)->anycast_address;
+}
+
+const char *
 nm_dhcp_client_get_hostname(NMDhcpClient *self)
 {
     g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
@@ -297,20 +307,12 @@ nm_dhcp_client_get_hostname_flags(NMDhcpClient *self)
     return NM_DHCP_CLIENT_GET_PRIVATE(self)->hostname_flags;
 }
 
-gboolean
-nm_dhcp_client_get_info_only(NMDhcpClient *self)
+NMDhcpClientFlags
+nm_dhcp_client_get_client_flags(NMDhcpClient *self)
 {
-    g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE);
+    g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NM_DHCP_CLIENT_FLAGS_NONE);
 
-    return NM_DHCP_CLIENT_GET_PRIVATE(self)->info_only;
-}
-
-gboolean
-nm_dhcp_client_get_use_fqdn(NMDhcpClient *self)
-{
-    g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE);
-
-    return NM_DHCP_CLIENT_GET_PRIVATE(self)->use_fqdn;
+    return NM_DHCP_CLIENT_GET_PRIVATE(self)->client_flags;
 }
 
 const char *
@@ -339,29 +341,25 @@ nm_dhcp_client_get_reject_servers(NMDhcpClient *self)
 
 /*****************************************************************************/
 
-static const char *state_table[NM_DHCP_STATE_MAX + 1] = {
-    [NM_DHCP_STATE_UNKNOWN]    = "unknown",
-    [NM_DHCP_STATE_BOUND]      = "bound",
-    [NM_DHCP_STATE_EXTENDED]   = "extended",
-    [NM_DHCP_STATE_TIMEOUT]    = "timeout",
-    [NM_DHCP_STATE_EXPIRE]     = "expire",
-    [NM_DHCP_STATE_DONE]       = "done",
-    [NM_DHCP_STATE_FAIL]       = "fail",
-    [NM_DHCP_STATE_TERMINATED] = "terminated",
-};
-
-static const char *
-state_to_string(NMDhcpState state)
-{
-    if ((gsize) state < G_N_ELEMENTS(state_table))
-        return state_table[state];
-    return NULL;
-}
+NM_UTILS_LOOKUP_STR_DEFINE(nm_dhcp_state_to_string,
+                           NMDhcpState,
+                           NM_UTILS_LOOKUP_DEFAULT(NULL),
+                           NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_BOUND, "bound"),
+                           NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_DONE, "done"),
+                           NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_EXPIRE, "expire"),
+                           NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_EXTENDED, "extended"),
+                           NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_FAIL, "fail"),
+                           NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_NOOP, "noop"),
+                           NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_TERMINATED, "terminated"),
+                           NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_TIMEOUT, "timeout"),
+                           NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_STATE_UNKNOWN, "unknown"),
+                           NM_UTILS_LOOKUP_ITEM_IGNORE(__NM_DHCP_STATE_MAX), );
 
 static NMDhcpState
 reason_to_state(NMDhcpClient *self, const char *iface, const char *reason)
 {
-    if (g_ascii_strcasecmp(reason, "bound") == 0 || g_ascii_strcasecmp(reason, "bound6") == 0)
+    if (g_ascii_strcasecmp(reason, "bound") == 0 || g_ascii_strcasecmp(reason, "bound6") == 0
+        || g_ascii_strcasecmp(reason, "static") == 0)
         return NM_DHCP_STATE_BOUND;
     else if (g_ascii_strcasecmp(reason, "renew") == 0 || g_ascii_strcasecmp(reason, "renew6") == 0
              || g_ascii_strcasecmp(reason, "reboot") == 0
@@ -493,8 +491,8 @@ nm_dhcp_client_set_state(NMDhcpClient *self,
         const char *addr = nm_g_hash_table_lookup(options, req_str);
 
         _LOGI("state changed %s -> %s%s%s%s",
-              state_to_string(priv->state),
-              state_to_string(new_state),
+              nm_dhcp_state_to_string(priv->state),
+              nm_dhcp_state_to_string(new_state),
               NM_PRINT_FMT_QUOTED(addr, ", address=", addr, "", ""));
     }
 
@@ -519,20 +517,12 @@ daemon_watch_cb(GPid pid, int status, gpointer user_data)
 {
     NMDhcpClient *       self = NM_DHCP_CLIENT(user_data);
     NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+    gs_free char *       desc = NULL;
 
     g_return_if_fail(priv->watch_id);
     priv->watch_id = 0;
 
-    if (WIFEXITED(status))
-        _LOGI("client pid %d exited with status %d", pid, WEXITSTATUS(status));
-    else if (WIFSIGNALED(status))
-        _LOGI("client pid %d killed by signal %d", pid, WTERMSIG(status));
-    else if (WIFSTOPPED(status))
-        _LOGI("client pid %d stopped by signal %d", pid, WSTOPSIG(status));
-    else if (WIFCONTINUED(status))
-        _LOGI("client pid %d resumed (by SIGCONT)", pid);
-    else
-        _LOGW("client died abnormally");
+    _LOGI("client pid %d %s", pid, (desc = nm_utils_get_process_exit_status_desc(status)));
 
     priv->pid = -1;
 
@@ -583,7 +573,6 @@ nm_dhcp_client_stop_watch_child(NMDhcpClient *self, pid_t pid)
 gboolean
 nm_dhcp_client_start_ip4(NMDhcpClient *self,
                          GBytes *      client_id,
-                         const char *  dhcp_anycast_addr,
                          const char *  last_ip4_address,
                          GError **     error)
 {
@@ -603,10 +592,7 @@ nm_dhcp_client_start_ip4(NMDhcpClient *self,
 
     nm_dhcp_client_set_client_id(self, client_id);
 
-    return NM_DHCP_CLIENT_GET_CLASS(self)->ip4_start(self,
-                                                     dhcp_anycast_addr,
-                                                     last_ip4_address,
-                                                     error);
+    return NM_DHCP_CLIENT_GET_CLASS(self)->ip4_start(self, last_ip4_address, error);
 }
 
 gboolean
@@ -643,7 +629,6 @@ gboolean
 nm_dhcp_client_start_ip6(NMDhcpClient *            self,
                          GBytes *                  client_id,
                          gboolean                  enforce_duid,
-                         const char *              dhcp_anycast_addr,
                          const struct in6_addr *   ll_addr,
                          NMSettingIP6ConfigPrivacy privacy,
                          guint                     needed_prefixes,
@@ -672,8 +657,11 @@ nm_dhcp_client_start_ip6(NMDhcpClient *            self,
     else
         _LOGI("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout);
 
-    return NM_DHCP_CLIENT_GET_CLASS(self)
-        ->ip6_start(self, dhcp_anycast_addr, ll_addr, privacy, needed_prefixes, error);
+    return NM_DHCP_CLIENT_GET_CLASS(self)->ip6_start(self,
+                                                     ll_addr,
+                                                     privacy,
+                                                     needed_prefixes,
+                                                     error);
 }
 
 void
@@ -903,8 +891,8 @@ nm_dhcp_client_handle_event(gpointer      unused,
     old_state = priv->state;
     new_state = reason_to_state(self, priv->iface, reason);
     _LOGD("DHCP state '%s' -> '%s' (reason: '%s')",
-          state_to_string(old_state),
-          state_to_string(new_state),
+          nm_dhcp_state_to_string(old_state),
+          nm_dhcp_state_to_string(new_state),
           reason);
 
     if (new_state == NM_DHCP_STATE_NOOP)
@@ -935,12 +923,12 @@ nm_dhcp_client_handle_event(gpointer      unused,
                                                           priv->route_metric));
             } else {
                 prefix    = nm_dhcp_utils_ip6_prefix_from_options(str_options);
-                ip_config = NM_IP_CONFIG_CAST(
-                    nm_dhcp_utils_ip6_config_from_options(nm_dhcp_client_get_multi_idx(self),
-                                                          priv->ifindex,
-                                                          priv->iface,
-                                                          str_options,
-                                                          priv->info_only));
+                ip_config = NM_IP_CONFIG_CAST(nm_dhcp_utils_ip6_config_from_options(
+                    nm_dhcp_client_get_multi_idx(self),
+                    priv->ifindex,
+                    priv->iface,
+                    str_options,
+                    NM_FLAGS_HAS(priv->client_flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY)));
             }
         } else
             g_warn_if_reached();
@@ -1057,11 +1045,8 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
     case PROP_FLAGS:
         /* construct-only */
         flags = g_value_get_uint(value);
-        nm_assert(
-            (flags & ~((guint)(NM_DHCP_CLIENT_FLAGS_INFO_ONLY | NM_DHCP_CLIENT_FLAGS_USE_FQDN)))
-            == 0);
-        priv->info_only = NM_FLAGS_HAS(flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY);
-        priv->use_fqdn  = NM_FLAGS_HAS(flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN);
+        nm_assert(!NM_FLAGS_ANY(flags, ~((guint) NM_DHCP_CLIENT_FLAGS_ALL)));
+        priv->client_flags = flags;
         break;
     case PROP_MULTI_IDX:
         /* construct-only */
@@ -1085,6 +1070,10 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
         /* construct-only */
         priv->hwaddr = g_value_dup_boxed(value);
         break;
+    case PROP_ANYCAST_ADDRESS:
+        /* construct-only */
+        priv->anycast_address = g_value_dup_string(value);
+        break;
     case PROP_BROADCAST_HWADDR:
         /* construct-only */
         priv->bcast_hwaddr = g_value_dup_boxed(value);
@@ -1158,6 +1147,28 @@ nm_dhcp_client_init(NMDhcpClient *self)
     priv->pid = -1;
 }
 
+#if NM_MORE_ASSERTS
+static void
+constructed(GObject *object)
+{
+    NMDhcpClient *       self = NM_DHCP_CLIENT(object);
+    NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+    /* certain flags only make sense with certain address family. Assert
+     * for that. */
+    if (NM_IS_IPv4(priv->addr_family))
+        nm_assert(!NM_FLAGS_ANY(priv->client_flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY));
+    else {
+        nm_assert(NM_FLAGS_HAS(priv->client_flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN));
+        nm_assert(!NM_FLAGS_ANY(priv->client_flags, NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST));
+    }
+
+    nm_assert(!priv->anycast_address || nm_utils_hwaddr_valid(priv->anycast_address, ETH_ALEN));
+
+    G_OBJECT_CLASS(nm_dhcp_client_parent_class)->constructed(object);
+}
+#endif
+
 static void
 dispose(GObject *object)
 {
@@ -1177,6 +1188,7 @@ dispose(GObject *object)
     nm_clear_g_free(&priv->iface);
     nm_clear_g_free(&priv->hostname);
     nm_clear_g_free(&priv->uuid);
+    nm_clear_g_free(&priv->anycast_address);
     nm_clear_g_free(&priv->mud_url);
     nm_clear_g_free(&priv->reject_servers);
     nm_clear_pointer(&priv->client_id, g_bytes_unref);
@@ -1196,6 +1208,9 @@ nm_dhcp_client_class_init(NMDhcpClientClass *client_class)
 
     g_type_class_add_private(client_class, sizeof(NMDhcpClientPrivate));
 
+#if NM_MORE_ASSERTS
+    object_class->constructed = constructed;
+#endif
     object_class->dispose      = dispose;
     object_class->get_property = get_property;
     object_class->set_property = set_property;
@@ -1248,6 +1263,13 @@ nm_dhcp_client_class_init(NMDhcpClientClass *client_class)
                          AF_UNSPEC,
                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
 
+    obj_properties[PROP_ANYCAST_ADDRESS] =
+        g_param_spec_string(NM_DHCP_CLIENT_ANYCAST_ADDRESS,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
     obj_properties[PROP_UUID] =
         g_param_spec_string(NM_DHCP_CLIENT_UUID,
                             "",