about summary refs log tree commit diff
path: root/src/core/dhcp/nm-dhcp-systemd.c
diff options
context:
space:
mode:
authorSebastien Bacher <seb128@ubuntu.com>2022-05-17 15:30:19 +0200
committerSebastien Bacher <seb128@ubuntu.com>2022-05-17 15:30:19 +0200
commit1e636d8e5e986b9f2260c36bb87fb499d724085c (patch)
treeac613b9372adf622496a7d616050d7e1c09b4fba /src/core/dhcp/nm-dhcp-systemd.c
parentf4966e573c855d4667e6c236d8197d9949020e21 (diff)
parent1a31bc3c63474ca02c83b02add85ea4e740e5597 (diff)
Merge remote-tracking branch 'debian/debian/master' into ubuntu/master
Diffstat (limited to 'src/core/dhcp/nm-dhcp-systemd.c')
-rw-r--r--src/core/dhcp/nm-dhcp-systemd.c177
1 files changed, 83 insertions, 94 deletions
diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c
index 0884def3..4a718de9 100644
--- a/src/core/dhcp/nm-dhcp-systemd.c
+++ b/src/core/dhcp/nm-dhcp-systemd.c
@@ -81,16 +81,20 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
     const struct in_addr                   *addr_list;
     char                                    addr_str[NM_UTILS_INET_ADDRSTRLEN];
     const char                             *s;
-    nm_auto_free_gstring GString           *str            = NULL;
-    nm_auto_free sd_dhcp_route            **routes         = NULL;
-    const char *const                      *search_domains = NULL;
+    nm_auto_free_gstring GString           *str              = NULL;
+    nm_auto_free sd_dhcp_route            **routes_static    = NULL;
+    nm_auto_free sd_dhcp_route            **routes_classless = NULL;
+    const char *const                      *search_domains   = NULL;
+    guint32                                 default_route_metric_offset;
     guint16                                 mtu;
-    int                                     i, num;
+    int                                     i;
+    int                                     num;
+    int                                     is_classless;
+    int                                     n_routes_static;
+    int                                     n_routes_classless;
     const void                             *data;
     gsize                                   data_len;
     gboolean                                has_router_from_classless = FALSE;
-    gboolean                                has_classless_route       = FALSE;
-    gboolean                                has_static_route          = FALSE;
     const gint32                            ts      = nm_utils_get_monotonic_timestamp_sec();
     gint64                                  ts_time = time(NULL);
     struct in_addr                          a_address;
@@ -226,44 +230,27 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
         nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_HOST_NAME, s);
     }
 
-    num = sd_dhcp_lease_get_routes(lease, &routes);
-    if (num > 0) {
-        nm_auto_free_gstring GString *str_classless               = NULL;
-        nm_auto_free_gstring GString *str_static                  = NULL;
-        guint32                       default_route_metric_offset = 0;
+    default_route_metric_offset = 0;
+    n_routes_static             = sd_dhcp_lease_get_static_routes(lease, &routes_static);
+    n_routes_classless          = sd_dhcp_lease_get_classless_routes(lease, &routes_classless);
+    for (is_classless = 1; is_classless >= 0; is_classless--) {
+        int                   n_routes = (is_classless ? n_routes_classless : n_routes_static);
+        sd_dhcp_route *const *routes   = (is_classless ? routes_classless : routes_static);
 
-        for (i = 0; i < num; i++) {
-            switch (sd_dhcp_route_get_option(routes[i])) {
-            case NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE:
-                has_classless_route = TRUE;
-                break;
-            case NM_DHCP_OPTION_DHCP4_STATIC_ROUTE:
-                has_static_route = TRUE;
-                break;
-            }
-        }
+        if (n_routes <= 0)
+            continue;
 
-        if (has_classless_route)
-            str_classless = g_string_sized_new(30);
-        if (has_static_route)
-            str_static = g_string_sized_new(30);
+        nm_gstring_prepare(&str);
 
-        for (i = 0; i < num; i++) {
+        for (i = 0; i < n_routes; i++) {
             char           network_net_str[NM_UTILS_INET_ADDRSTRLEN];
             char           gateway_str[NM_UTILS_INET_ADDRSTRLEN];
             guint8         r_plen;
             struct in_addr r_network;
             struct in_addr r_gateway;
             in_addr_t      network_net;
-            int            option;
             guint32        m;
 
-            option = sd_dhcp_route_get_option(routes[i]);
-            if (!NM_IN_SET(option,
-                           NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE,
-                           NM_DHCP_OPTION_DHCP4_STATIC_ROUTE))
-                continue;
-
             if (sd_dhcp_route_get_destination(routes[i], &r_network) < 0)
                 continue;
             if (sd_dhcp_route_get_destination_prefix_length(routes[i], &r_plen) < 0 || r_plen > 32)
@@ -275,31 +262,28 @@ 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);
 
-            g_string_append_printf(
-                nm_gstring_add_space_delimiter(option == NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE
-                                                   ? str_classless
-                                                   : str_static),
-                "%s/%d %s",
-                network_net_str,
-                (int) r_plen,
-                gateway_str);
+            g_string_append_printf(nm_gstring_add_space_delimiter(str),
+                                   "%s/%d %s",
+                                   network_net_str,
+                                   (int) r_plen,
+                                   gateway_str);
 
-            if (option == NM_DHCP_OPTION_DHCP4_STATIC_ROUTE && has_classless_route) {
+            if (!is_classless && n_routes_classless > 0) {
                 /* RFC 3443: if the DHCP server returns both a Classless Static Routes
                  * option and a Static Routes option, the DHCP client MUST ignore the
                  * Static Routes option. */
                 continue;
             }
 
-            if (r_plen == 0 && option == NM_DHCP_OPTION_DHCP4_STATIC_ROUTE) {
-                /* for option 33 (static route), RFC 2132 says:
-                 *
-                 * The default route (0.0.0.0) is an illegal destination for a static
-                 * route. */
-                continue;
-            }
-
             if (r_plen == 0) {
+                if (!is_classless) {
+                    /* for option 33 (static route), RFC 2132 says:
+                     *
+                     * The default route (0.0.0.0) is an illegal destination for a static
+                     * route. */
+                    continue;
+                }
+
                 /* if there are multiple default routes, we add them with differing
                  * metrics. */
                 m                         = default_route_metric_offset++;
@@ -309,10 +293,11 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
 
             nm_l3_config_data_add_route_4(l3cd,
                                           &((const NMPlatformIP4Route){
+                                              .rt_source     = NM_IP_CONFIG_SOURCE_DHCP,
                                               .network       = network_net,
                                               .plen          = r_plen,
                                               .gateway       = r_gateway.s_addr,
-                                              .rt_source     = NM_IP_CONFIG_SOURCE_DHCP,
+                                              .pref_src      = a_address.s_addr,
                                               .metric_any    = TRUE,
                                               .metric        = m,
                                               .table_any     = TRUE,
@@ -320,21 +305,18 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
                                           }));
         }
 
-        if (str_classless && str_classless->len > 0)
+        if (str->len > 0) {
             nm_dhcp_option_add_option(options,
                                       AF_INET,
-                                      NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE,
-                                      str_classless->str);
-        if (str_static && str_static->len > 0)
-            nm_dhcp_option_add_option(options,
-                                      AF_INET,
-                                      NM_DHCP_OPTION_DHCP4_STATIC_ROUTE,
-                                      str_static->str);
+                                      is_classless ? NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE
+                                                   : NM_DHCP_OPTION_DHCP4_STATIC_ROUTE,
+                                      str->str);
+        }
     }
 
     num = sd_dhcp_lease_get_router(lease, &a_router);
     if (num > 0) {
-        guint32 default_route_metric_offset = 0;
+        default_route_metric_offset = 0;
 
         nm_gstring_prepare(&str);
         for (i = 0; i < num; i++) {
@@ -366,6 +348,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
                                           &((const NMPlatformIP4Route){
                                               .rt_source     = NM_IP_CONFIG_SOURCE_DHCP,
                                               .gateway       = a_router[i].s_addr,
+                                              .pref_src      = a_address.s_addr,
                                               .table_any     = TRUE,
                                               .table_coerced = 0,
                                               .metric_any    = TRUE,
@@ -768,14 +751,12 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
     gs_unref_hashtable GHashTable          *options = NULL;
     struct in6_addr                         tmp_addr;
     const struct in6_addr                  *dns;
-    uint32_t                                lft_pref, lft_valid;
     char                                    addr_str[NM_UTILS_INET_ADDRSTRLEN];
     char                                  **domains;
     char                                  **ntp_fqdns;
     const struct in6_addr                  *ntp_addrs;
     const char                             *s;
-    nm_auto_free_gstring GString           *str               = NULL;
-    gboolean                                has_any_addresses = FALSE;
+    nm_auto_free_gstring GString           *str = NULL;
     int                                     num, i;
 
     nm_assert(lease);
@@ -784,36 +765,45 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
 
     options = nm_dhcp_option_create_options_dict();
 
-    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) {
-        const NMPlatformIP6Address address = {
-            .plen        = 128,
-            .address     = tmp_addr,
-            .timestamp   = ts,
-            .lifetime    = lft_valid,
-            .preferred   = lft_pref,
-            .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
-        };
-
-        nm_l3_config_data_add_address_6(l3cd, &address);
+    if (!info_only) {
+        gboolean has_any_addresses = FALSE;
+        uint32_t lft_pref;
+        uint32_t lft_valid;
 
-        _nm_utils_inet6_ntop(&tmp_addr, addr_str);
-        g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
+        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) {
+            const NMPlatformIP6Address address = {
+                .plen        = 128,
+                .address     = tmp_addr,
+                .timestamp   = ts,
+                .lifetime    = lft_valid,
+                .preferred   = lft_pref,
+                .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
+            };
+
+            nm_l3_config_data_add_address_6(l3cd, &address);
+
+            _nm_utils_inet6_ntop(&tmp_addr, addr_str);
+            g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
 
-        has_any_addresses = TRUE;
-    }
+            has_any_addresses = TRUE;
+        }
 
-    if (str->len) {
-        nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS, str->str);
-    }
+        if (str->len) {
+            nm_dhcp_option_add_option(options,
+                                      AF_INET6,
+                                      NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS,
+                                      str->str);
+        }
 
-    if (!info_only && !has_any_addresses) {
-        g_set_error_literal(error,
-                            NM_MANAGER_ERROR,
-                            NM_MANAGER_ERROR_FAILED,
-                            "no address received in managed mode");
-        return NULL;
+        if (!has_any_addresses) {
+            g_set_error_literal(error,
+                                NM_MANAGER_ERROR,
+                                NM_MANAGER_ERROR_FAILED,
+                                "no address received in managed mode");
+            return NULL;
+        }
     }
 
     num = sd_dhcp6_lease_get_dns(lease, &dns);
@@ -983,11 +973,10 @@ ip6_start(NMDhcpClient *client, const struct in6_addr *ll_addr, GError **error)
 
     _LOGT("dhcp-client6: set %p", sd_client);
 
-    if (client_config->v6.info_only) {
-        sd_dhcp6_client_set_address_request(sd_client, 0);
-        if (client_config->v6.needed_prefixes == 0)
-            sd_dhcp6_client_set_information_request(sd_client, 1);
-    }
+    sd_dhcp6_client_set_address_request(sd_client, !client_config->v6.info_only);
+    sd_dhcp6_client_set_information_request(sd_client,
+                                            client_config->v6.info_only
+                                                && client_config->v6.needed_prefixes == 0);
 
     r = sd_dhcp6_client_set_iaid(sd_client, client_config->v6.iaid);
     if (r < 0) {