summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/devices/nm-device-wireguard.c42
-rw-r--r--src/core/devices/wifi/nm-device-iwd.c12
-rw-r--r--src/core/initrd/nmi-cmdline-reader.c16
-rw-r--r--src/core/initrd/tests/test-cmdline-reader.c64
-rw-r--r--src/core/platform/nmp-object.h8
-rw-r--r--src/core/platform/tests/test-common.c15
-rw-r--r--src/core/platform/tests/test-route.c2
7 files changed, 131 insertions, 28 deletions
diff --git a/src/core/devices/nm-device-wireguard.c b/src/core/devices/nm-device-wireguard.c
index fd057ded..5bee09e6 100644
--- a/src/core/devices/nm-device-wireguard.c
+++ b/src/core/devices/nm-device-wireguard.c
@@ -729,7 +729,7 @@ _peers_resolve_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
     PeerData *                peer_data;
     gs_free_error GError *resolv_error = NULL;
     GList *               list;
-    gboolean              changed = FALSE;
+    gboolean              changed;
     NMSockAddrUnion       sockaddr;
     gint64                retry_in_msec;
     char                  s_sockaddr[100];
@@ -775,36 +775,49 @@ _peers_resolve_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
     }
 
     sockaddr = (NMSockAddrUnion) NM_SOCK_ADDR_UNION_INIT_UNSPEC;
+    changed  = FALSE;
 
     if (!resolv_error) {
         GList *iter;
 
         for (iter = list; iter; iter = iter->next) {
-            GInetAddress *a = iter->data;
-            GSocketFamily f = g_inet_address_get_family(a);
+            GInetAddress *   a = iter->data;
+            NMSockAddrUnion  sockaddr_tmp;
+            NMSockAddrUnion *s;
 
-            if (f == G_SOCKET_FAMILY_IPV4) {
+            s = sockaddr.sa.sa_family == AF_UNSPEC ? &sockaddr : &sockaddr_tmp;
+
+            switch (g_inet_address_get_family(a)) {
+            case G_SOCKET_FAMILY_IPV4:
                 nm_assert(g_inet_address_get_native_size(a) == sizeof(struct in_addr));
-                sockaddr.in = (struct sockaddr_in){
+                s->in = (struct sockaddr_in){
                     .sin_family = AF_INET,
                     .sin_port   = htons(nm_sock_addr_endpoint_get_port(
                         _nm_wireguard_peer_get_endpoint(peer_data->peer))),
                 };
-                memcpy(&sockaddr.in.sin_addr, g_inet_address_to_bytes(a), sizeof(struct in_addr));
+                memcpy(&s->in.sin_addr, g_inet_address_to_bytes(a), sizeof(struct in_addr));
                 break;
-            }
-            if (f == G_SOCKET_FAMILY_IPV6) {
+            case G_SOCKET_FAMILY_IPV6:
                 nm_assert(g_inet_address_get_native_size(a) == sizeof(struct in6_addr));
-                sockaddr.in6 = (struct sockaddr_in6){
+                s->in6 = (struct sockaddr_in6){
                     .sin6_family   = AF_INET6,
                     .sin6_port     = htons(nm_sock_addr_endpoint_get_port(
                         _nm_wireguard_peer_get_endpoint(peer_data->peer))),
                     .sin6_scope_id = 0,
                     .sin6_flowinfo = 0,
                 };
-                memcpy(&sockaddr.in6.sin6_addr,
-                       g_inet_address_to_bytes(a),
-                       sizeof(struct in6_addr));
+                memcpy(&s->in6.sin6_addr, g_inet_address_to_bytes(a), sizeof(struct in6_addr));
+                break;
+            default:
+                continue;
+            }
+
+            changed = TRUE;
+            if (peer_data->ep_resolv.sockaddr.sa.sa_family == AF_UNSPEC)
+                break;
+
+            if (nm_sock_addr_union_cmp(&peer_data->ep_resolv.sockaddr, &sockaddr) == 0) {
+                changed = FALSE;
                 break;
             }
         }
@@ -819,11 +832,8 @@ _peers_resolve_cb(GObject *source_object, GAsyncResult *res, gpointer user_data)
          * a possibly good IP address, since WireGuard supports automatic roaming
          * anyway. Either the IP address is still good (and we would wrongly
          * reject it), or it isn't -- in which case it does not hurt much. */
-    } else {
-        if (nm_sock_addr_union_cmp(&peer_data->ep_resolv.sockaddr, &sockaddr) != 0)
-            changed = TRUE;
+    } else if (changed)
         peer_data->ep_resolv.sockaddr = sockaddr;
-    }
 
     if (resolv_error || peer_data->ep_resolv.sockaddr.sa.sa_family == AF_UNSPEC) {
         /* while it technically did not fail, something is probably odd. Retry frequently to
diff --git a/src/core/devices/wifi/nm-device-iwd.c b/src/core/devices/wifi/nm-device-iwd.c
index f0de90d3..95ade44b 100644
--- a/src/core/devices/wifi/nm-device-iwd.c
+++ b/src/core/devices/wifi/nm-device-iwd.c
@@ -1282,15 +1282,13 @@ get_agent_request_network_path(GDBusMethodInvocation *invocation)
     const char *network_path = NULL;
 
     if (nm_streq(method_name, "RequestPassphrase"))
-        g_variant_get(params, "(o)", &network_path);
+        g_variant_get(params, "(&o)", &network_path);
     else if (nm_streq(method_name, "RequestPrivateKeyPassphrase"))
-        g_variant_get(params, "(o)", &network_path);
+        g_variant_get(params, "(&o)", &network_path);
     else if (nm_streq(method_name, "RequestUserNameAndPassword"))
-        g_variant_get(params, "(o)", &network_path);
-    else if (nm_streq(method_name, "RequestUserPassword")) {
-        const char *user;
-        g_variant_get(params, "(os)", &network_path, &user);
-    }
+        g_variant_get(params, "(&o)", &network_path);
+    else if (nm_streq(method_name, "RequestUserPassword"))
+        g_variant_get(params, "(&os)", &network_path, NULL);
 
     return network_path;
 }
diff --git a/src/core/initrd/nmi-cmdline-reader.c b/src/core/initrd/nmi-cmdline-reader.c
index d95b0f9b..508ef2b2 100644
--- a/src/core/initrd/nmi-cmdline-reader.c
+++ b/src/core/initrd/nmi-cmdline-reader.c
@@ -147,6 +147,8 @@ reader_create_connection(Reader *                 reader,
                  type_name,
                  NM_SETTING_CONNECTION_MULTI_CONNECT,
                  multi_connect,
+                 NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES,
+                 1,
                  NULL);
 
     if (nm_streq0(type_name, NM_SETTING_INFINIBAND_SETTING_NAME)) {
@@ -1065,6 +1067,8 @@ nmi_cmdline_reader_parse(const char *       sysfs_dir,
     gs_unref_ptrarray GPtrArray *routes      = NULL;
     gs_unref_ptrarray GPtrArray *znets       = NULL;
     int                          i;
+    guint64                      dhcp_timeout   = 90;
+    guint64                      dhcp_num_tries = 1;
 
     reader = reader_new();
 
@@ -1082,7 +1086,15 @@ nmi_cmdline_reader_parse(const char *       sysfs_dir,
         else if (nm_streq(tag, "rd.peerdns"))
             reader->ignore_auto_dns = !_nm_utils_ascii_str_to_bool(argument, TRUE);
         else if (nm_streq(tag, "rd.net.timeout.dhcp")) {
-            reader->dhcp_timeout = _nm_utils_ascii_str_to_int64(argument, 10, 0, G_MAXINT32, 0);
+            if (nm_streq0(argument, "infinity")) {
+                dhcp_timeout = G_MAXINT32;
+            } else {
+                dhcp_timeout =
+                    _nm_utils_ascii_str_to_int64(argument, 10, 1, G_MAXINT32, dhcp_timeout);
+            }
+        } else if (nm_streq(tag, "rd.net.dhcp.retry")) {
+            dhcp_num_tries =
+                _nm_utils_ascii_str_to_int64(argument, 10, 1, G_MAXINT32, dhcp_num_tries);
         } else if (nm_streq(tag, "rd.net.dhcp.vendor-class")) {
             if (nm_utils_validate_dhcp4_vendor_class_id(argument, NULL))
                 nm_utils_strdup_reset(&reader->dhcp4_vci, argument);
@@ -1092,6 +1104,8 @@ nmi_cmdline_reader_parse(const char *       sysfs_dir,
         }
     }
 
+    reader->dhcp_timeout = NM_CLAMP(dhcp_timeout * dhcp_num_tries, 1, G_MAXINT32);
+
     for (i = 0; argv[i]; i++) {
         gs_free char *argument_clone = NULL;
         char *        argument;
diff --git a/src/core/initrd/tests/test-cmdline-reader.c b/src/core/initrd/tests/test-cmdline-reader.c
index cb65cd33..33fb22d3 100644
--- a/src/core/initrd/tests/test-cmdline-reader.c
+++ b/src/core/initrd/tests/test-cmdline-reader.c
@@ -230,10 +230,68 @@ test_dhcp_with_mtu(void)
 }
 
 static void
+test_dhcp_timeout(void)
+{
+    struct {
+        const char *const *cmdline;
+        int                timeout;
+    } data[] = {
+        {NM_MAKE_STRV("ip=dhcp"), 90},
+        {NM_MAKE_STRV("ip=dhcp", "rd.net.timeout.dhcp=0"), 90},
+        {NM_MAKE_STRV("ip=dhcp", "rd.net.timeout.dhcp=foobar"), 90},
+        {NM_MAKE_STRV("ip=dhcp", "rd.net.timeout.dhcp=42"), 42},
+        {NM_MAKE_STRV("ip=dhcp", "rd.net.dhcp.retry=2"), 180},
+        {NM_MAKE_STRV("ip=dhcp", "rd.net.dhcp.retry=3", "rd.net.timeout.dhcp=40"), 120},
+        {NM_MAKE_STRV("ip=dhcp", "rd.net.timeout.dhcp=infinity"), G_MAXINT32},
+        {NM_MAKE_STRV("ip=dhcp", "rd.net.timeout.dhcp=infinity", "rd.net.dhcp.retry=100"),
+         G_MAXINT32},
+    };
+    guint i;
+
+    for (i = 0; i < G_N_ELEMENTS(data); i++) {
+        gs_unref_object NMConnection *connection = NULL;
+        NMSettingConnection *         s_con;
+        NMSettingIPConfig *           s_ip4;
+        NMSettingIPConfig *           s_ip6;
+
+        connection = _parse_con(data[i].cmdline, "default_connection");
+
+        s_con = nm_connection_get_setting_connection(connection);
+        g_assert(s_con);
+        g_assert_cmpstr(nm_setting_connection_get_connection_type(s_con),
+                        ==,
+                        NM_SETTING_WIRED_SETTING_NAME);
+        g_assert_cmpstr(nm_setting_connection_get_id(s_con), ==, "Wired Connection");
+        g_assert_cmpint(nm_setting_connection_get_timestamp(s_con), ==, 0);
+        g_assert_cmpint(nm_setting_connection_get_multi_connect(s_con),
+                        ==,
+                        NM_CONNECTION_MULTI_CONNECT_MULTIPLE);
+        g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1);
+        g_assert_cmpint(nm_setting_connection_get_autoconnect_retries(s_con), ==, 1);
+        g_assert(nm_setting_connection_get_autoconnect(s_con));
+
+        s_ip4 = nm_connection_get_setting_ip4_config(connection);
+        g_assert(s_ip4);
+        g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4),
+                        ==,
+                        NM_SETTING_IP4_CONFIG_METHOD_AUTO);
+        g_assert_cmpint(nm_setting_ip_config_get_dhcp_timeout(s_ip4), ==, data[i].timeout);
+
+        s_ip6 = nm_connection_get_setting_ip6_config(connection);
+        g_assert(s_ip6);
+        g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6),
+                        ==,
+                        NM_SETTING_IP6_CONFIG_METHOD_AUTO);
+        g_assert_cmpint(nm_setting_ip_config_get_dhcp_timeout(s_ip6), ==, data[i].timeout);
+    }
+}
+
+static void
 test_if_auto_with_mtu(void)
 {
     const char *const *ARGV                  = NM_MAKE_STRV("ip=eth0:auto:1666");
     gs_unref_object NMConnection *connection = NULL;
+    NMSettingConnection *         s_con;
     NMSettingWired *              s_wired;
     NMSettingIPConfig *           s_ip4;
     NMSettingIPConfig *           s_ip6;
@@ -242,6 +300,10 @@ test_if_auto_with_mtu(void)
 
     g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0");
 
+    s_con = nm_connection_get_setting_connection(connection);
+    g_assert(s_con);
+    g_assert_cmpint(nm_setting_connection_get_autoconnect_retries(s_con), ==, 1);
+
     s_wired = nm_connection_get_setting_wired(connection);
     g_assert(s_wired);
     g_assert_cmpint(nm_setting_wired_get_mtu(s_wired), ==, 1666);
@@ -250,6 +312,7 @@ test_if_auto_with_mtu(void)
     g_assert(s_ip4);
     g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
     g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4));
+    g_assert_cmpint(nm_setting_ip_config_get_dhcp_timeout(s_ip4), ==, 90);
 
     s_ip6 = nm_connection_get_setting_ip6_config(connection);
     g_assert(s_ip6);
@@ -2074,6 +2137,7 @@ main(int argc, char **argv)
     g_test_add_func("/initrd/cmdline/auto", test_auto);
     g_test_add_func("/initrd/cmdline/dhcp_with_hostname", test_dhcp_with_hostname);
     g_test_add_func("/initrd/cmdline/dhcp_with_mtu", test_dhcp_with_mtu);
+    g_test_add_func("/initrd/cmdline/dhcp_timeout", test_dhcp_timeout);
     g_test_add_func("/initrd/cmdline/if_auto_with_mtu", test_if_auto_with_mtu);
     g_test_add_func("/initrd/cmdline/if_dhcp6", test_if_dhcp6);
     g_test_add_func("/initrd/cmdline/if_auto_with_mtu_and_mac", test_if_auto_with_mtu_and_mac);
diff --git a/src/core/platform/nmp-object.h b/src/core/platform/nmp-object.h
index dc2cc86b..19f6bcd7 100644
--- a/src/core/platform/nmp-object.h
+++ b/src/core/platform/nmp-object.h
@@ -34,10 +34,14 @@ typedef union {
     struct sockaddr_in6 in6;
 } NMSockAddrUnion;
 
+G_STATIC_ASSERT(sizeof(NMSockAddrUnion) == sizeof(((NMSockAddrUnion *) NULL)->in6));
+
+/* we initialize the largest union member, to ensure that all fields are initialized. */
+
 #define NM_SOCK_ADDR_UNION_INIT_UNSPEC \
     {                                  \
-        .sa = {                        \
-            .sa_family = AF_UNSPEC,    \
+        .in6 = {                       \
+            .sin6_family = AF_UNSPEC,  \
         },                             \
     }
 
diff --git a/src/core/platform/tests/test-common.c b/src/core/platform/tests/test-common.c
index 87e5329a..4a117d59 100644
--- a/src/core/platform/tests/test-common.c
+++ b/src/core/platform/tests/test-common.c
@@ -2563,7 +2563,20 @@ main(int argc, char **argv)
 
         if (unshare(CLONE_NEWNET | CLONE_NEWNS) != 0) {
             errsv = errno;
-            g_error("unshare(CLONE_NEWNET|CLONE_NEWNS) failed with %s (%d)",
+            if (errsv == EPERM) {
+#ifdef REQUIRE_ROOT_TESTS
+                g_print("Fail test: unshare(CLONE_NEWNET|CLONE_NEWNS) failed with %s (%d)\n",
+                        nm_strerror_native(errsv),
+                        errsv);
+                return EXIT_FAILURE;
+#else
+                g_print("Skipping test: unshare(CLONE_NEWNET|CLONE_NEWNS) failed with %s (%d)\n",
+                        nm_strerror_native(errsv),
+                        errsv);
+                return g_test_run();
+#endif
+            }
+            g_error("Fail test: unshare(CLONE_NEWNET|CLONE_NEWNS) failed with %s (%d)",
                     nm_strerror_native(errsv),
                     errsv);
         }
diff --git a/src/core/platform/tests/test-route.c b/src/core/platform/tests/test-route.c
index 47587865..645bb5b1 100644
--- a/src/core/platform/tests/test-route.c
+++ b/src/core/platform/tests/test-route.c
@@ -446,7 +446,7 @@ test_ip6_route(void)
                          metric,
                          mss);
     g_assert(nmtstp_ip6_route_get(NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0));
-    accept_signal(route_added);
+    accept_signals(route_added, 1, 2);
 
     /* Add route again */
     nmtstp_ip6_route_add(NM_PLATFORM_GET,