Blob Blame History Raw
From 3547c4d09a1d10b150a61bcbdc2418d750f7f616 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Fri, 1 Apr 2022 08:39:56 +0200
Subject: [PATCH 1/2] dhcp: set "src" for DHCPv4 routes

Let's set the "src" (RTA_PREFSRC) of DHCP routes.
This helps with source address selection.

This can matter if the interface also has static addresses
configured.

Systemd-networkd also does this ([1], [2]).

[1] https://github.com/systemd/systemd/commit/ac2dce5f36bb8b1a877ff765e6a4dfde6bfb2d49
[2] https://github.com/systemd/systemd/blob/5b89bff55f45235f72d30d90fd489fe2247ad00d/src/network/networkd-dhcp4.c#L395

Related: https://bugzilla.redhat.com/show_bug.cgi?id=1995372

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1173
(cherry picked from commit 2dc7a3d9f9135959adf415405bdcb05a7387c1d4)
(cherry picked from commit 10b9e07bfc3ae044b35a7dc6559aa6a4583bd7e8)
(cherry picked from commit f2942d11a75e5fb0bda35f8b659d0643f1f418b2)
---
 src/core/dhcp/nm-dhcp-nettools.c | 16 ++++++++++++----
 src/core/dhcp/nm-dhcp-systemd.c  |  4 +++-
 src/core/dhcp/nm-dhcp-utils.c    | 26 +++++++++++++++-----------
 3 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c
index d7fbe3561599..769b0325f23d 100644
--- a/src/core/dhcp/nm-dhcp-nettools.c
+++ b/src/core/dhcp/nm-dhcp-nettools.c
@@ -154,6 +154,7 @@ static gboolean
 lease_parse_address(NDhcp4ClientLease *lease,
                     NML3ConfigData    *l3cd,
                     GHashTable        *options,
+                    in_addr_t         *out_address,
                     GError           **error)
 {
     struct in_addr a_address;
@@ -268,6 +269,8 @@ lease_parse_address(NDhcp4ClientLease *lease,
                                         .preferred    = a_lifetime,
                                     }));
 
+    NM_SET_OUT(out_address, a_address.s_addr);
+
     return TRUE;
 }
 
@@ -326,6 +329,7 @@ lease_parse_address_list(NDhcp4ClientLease       *lease,
 static void
 lease_parse_routes(NDhcp4ClientLease *lease,
                    NML3ConfigData    *l3cd,
+                   in_addr_t          lease_address,
                    GHashTable        *options,
                    NMStrBuf          *sbuf)
 {
@@ -373,10 +377,11 @@ lease_parse_routes(NDhcp4ClientLease *lease,
 
             nm_l3_config_data_add_route_4(l3cd,
                                           &((const NMPlatformIP4Route){
+                                              .rt_source     = NM_IP_CONFIG_SOURCE_DHCP,
                                               .network       = dest,
                                               .plen          = plen,
                                               .gateway       = gateway,
-                                              .rt_source     = NM_IP_CONFIG_SOURCE_DHCP,
+                                              .pref_src      = lease_address,
                                               .table_any     = TRUE,
                                               .table_coerced = 0,
                                               .metric_any    = TRUE,
@@ -416,10 +421,11 @@ lease_parse_routes(NDhcp4ClientLease *lease,
 
             nm_l3_config_data_add_route_4(l3cd,
                                           &((const NMPlatformIP4Route){
+                                              .rt_source     = NM_IP_CONFIG_SOURCE_DHCP,
                                               .network       = dest,
                                               .plen          = plen,
                                               .gateway       = gateway,
-                                              .rt_source     = NM_IP_CONFIG_SOURCE_DHCP,
+                                              .pref_src      = lease_address,
                                               .table_any     = TRUE,
                                               .table_coerced = 0,
                                               .metric_any    = TRUE,
@@ -464,6 +470,7 @@ lease_parse_routes(NDhcp4ClientLease *lease,
                                           &((const NMPlatformIP4Route){
                                               .rt_source     = NM_IP_CONFIG_SOURCE_DHCP,
                                               .gateway       = gateway,
+                                              .pref_src      = lease_address,
                                               .table_any     = TRUE,
                                               .table_coerced = 0,
                                               .metric_any    = TRUE,
@@ -547,6 +554,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
     const char                             *v_str;
     guint16                                 v_u16;
     in_addr_t                               v_inaddr;
+    in_addr_t                               lease_address;
     struct in_addr                          v_inaddr_s;
     int                                     r;
 
@@ -556,7 +564,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
 
     options = nm_dhcp_option_create_options_dict();
 
-    if (!lease_parse_address(lease, l3cd, options, error))
+    if (!lease_parse_address(lease, l3cd, options, &lease_address, error))
         return NULL;
 
     r = n_dhcp4_client_lease_get_server_identifier(lease, &v_inaddr_s);
@@ -575,7 +583,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
                                           v_inaddr);
     }
 
-    lease_parse_routes(lease, l3cd, options, &sbuf);
+    lease_parse_routes(lease, l3cd, lease_address, options, &sbuf);
 
     lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, options, &sbuf);
 
diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c
index 0884def35dc6..d17646154f67 100644
--- a/src/core/dhcp/nm-dhcp-systemd.c
+++ b/src/core/dhcp/nm-dhcp-systemd.c
@@ -309,10 +309,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,
@@ -366,6 +367,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,
diff --git a/src/core/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c
index 4a138086b957..c71796f8bd9d 100644
--- a/src/core/dhcp/nm-dhcp-utils.c
+++ b/src/core/dhcp/nm-dhcp-utils.c
@@ -28,7 +28,8 @@ static gboolean
 ip4_process_dhcpcd_rfc3442_routes(const char     *iface,
                                   const char     *str,
                                   NML3ConfigData *l3cd,
-                                  guint32        *gwaddr)
+                                  in_addr_t       address,
+                                  guint32        *out_gwaddr)
 {
     gs_free const char **routes = NULL;
     const char         **r;
@@ -79,7 +80,7 @@ ip4_process_dhcpcd_rfc3442_routes(const char     *iface,
         have_routes = TRUE;
         if (rt_cidr == 0 && rt_addr == 0) {
             /* FIXME: how to handle multiple routers? */
-            *gwaddr = rt_route;
+            *out_gwaddr = rt_route;
         } else {
             _LOG2I(LOGD_DHCP4,
                    iface,
@@ -91,13 +92,13 @@ ip4_process_dhcpcd_rfc3442_routes(const char     *iface,
             nm_l3_config_data_add_route_4(
                 l3cd,
                 &((const NMPlatformIP4Route){
+                    .rt_source  = NM_IP_CONFIG_SOURCE_DHCP,
                     .network    = nm_utils_ip4_address_clear_host_address(rt_addr, rt_cidr),
                     .plen       = rt_cidr,
                     .gateway    = rt_route,
-                    .rt_source  = NM_IP_CONFIG_SOURCE_DHCP,
+                    .pref_src   = address,
                     .metric_any = TRUE,
                     .table_any  = TRUE,
-
                 }));
         }
     }
@@ -158,7 +159,8 @@ static gboolean
 ip4_process_dhclient_rfc3442_routes(const char     *iface,
                                     const char     *str,
                                     NML3ConfigData *l3cd,
-                                    guint32        *gwaddr)
+                                    in_addr_t       address,
+                                    guint32        *out_gwaddr)
 {
     gs_free const char **octets = NULL;
     const char *const   *o;
@@ -182,13 +184,14 @@ ip4_process_dhclient_rfc3442_routes(const char     *iface,
         have_routes = TRUE;
         if (!route.plen) {
             /* gateway passed as classless static route */
-            *gwaddr = route.gateway;
+            *out_gwaddr = route.gateway;
         } else {
             char b1[INET_ADDRSTRLEN];
             char b2[INET_ADDRSTRLEN];
 
             /* normal route */
             route.rt_source     = NM_IP_CONFIG_SOURCE_DHCP;
+            route.pref_src      = address;
             route.table_any     = TRUE;
             route.table_coerced = 0;
             route.metric_any    = TRUE;
@@ -212,14 +215,15 @@ static gboolean
 ip4_process_classless_routes(const char     *iface,
                              GHashTable     *options,
                              NML3ConfigData *l3cd,
-                             guint32        *gwaddr)
+                             in_addr_t       address,
+                             guint32        *out_gwaddr)
 {
     const char *str, *p;
 
     g_return_val_if_fail(options != NULL, FALSE);
     g_return_val_if_fail(l3cd != NULL, FALSE);
 
-    *gwaddr = 0;
+    *out_gwaddr = 0;
 
     /* dhcpd/dhclient in Fedora has support for rfc3442 implemented using a
      * slightly different format:
@@ -266,10 +270,10 @@ ip4_process_classless_routes(const char     *iface,
 
     if (strchr(str, '/')) {
         /* dhcpcd format */
-        return ip4_process_dhcpcd_rfc3442_routes(iface, str, l3cd, gwaddr);
+        return ip4_process_dhcpcd_rfc3442_routes(iface, str, l3cd, address, out_gwaddr);
     }
 
-    return ip4_process_dhclient_rfc3442_routes(iface, str, l3cd, gwaddr);
+    return ip4_process_dhclient_rfc3442_routes(iface, str, l3cd, address, out_gwaddr);
 }
 
 static void
@@ -422,7 +426,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
     /* Routes: if the server returns classless static routes, we MUST ignore
      * the 'static_routes' option.
      */
-    if (!ip4_process_classless_routes(iface, options, l3cd, &gateway))
+    if (!ip4_process_classless_routes(iface, options, l3cd, address.address, &gateway))
         process_classful_routes(iface, options, l3cd);
 
     if (gateway) {
-- 
2.36.1


From ebfc7c2c58e6125346baf9b530e71b2571dc0c10 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Wed, 13 Apr 2022 10:43:13 +0200
Subject: [PATCH 2/2] dhcp/dhclient: fix setting "src" attribute for certain
 routes

Fixes: 2dc7a3d9f913 ('dhcp: set "src" for DHCPv4 routes')
(cherry picked from commit 197e73ac7c53556b32ff048c9720907be3217487)
(cherry picked from commit 0c6d242dc0b67b6269657acf33bf9d1f0830f0b4)
(cherry picked from commit b0a7dda2eae1493a3a285ed1d08178409266ba07)
---
 src/core/dhcp/nm-dhcp-utils.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/core/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c
index c71796f8bd9d..35a2c6543759 100644
--- a/src/core/dhcp/nm-dhcp-utils.c
+++ b/src/core/dhcp/nm-dhcp-utils.c
@@ -277,7 +277,10 @@ ip4_process_classless_routes(const char     *iface,
 }
 
 static void
-process_classful_routes(const char *iface, GHashTable *options, NML3ConfigData *l3cd)
+process_classful_routes(const char     *iface,
+                        GHashTable     *options,
+                        NML3ConfigData *l3cd,
+                        in_addr_t       address)
 {
     gs_free const char **searches = NULL;
     const char         **s;
@@ -325,6 +328,7 @@ process_classful_routes(const char *iface, GHashTable *options, NML3ConfigData *
             route.plen = 32;
         }
         route.gateway       = rt_route;
+        route.pref_src      = address;
         route.rt_source     = NM_IP_CONFIG_SOURCE_DHCP;
         route.table_any     = TRUE;
         route.table_coerced = 0;
@@ -427,7 +431,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
      * the 'static_routes' option.
      */
     if (!ip4_process_classless_routes(iface, options, l3cd, address.address, &gateway))
-        process_classful_routes(iface, options, l3cd);
+        process_classful_routes(iface, options, l3cd, address.address);
 
     if (gateway) {
         _LOG2I(LOGD_DHCP4, iface, "  gateway %s", _nm_utils_inet4_ntop(gateway, sbuf));
@@ -457,6 +461,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
         const NMPlatformIP4Route r = {
             .rt_source     = NM_IP_CONFIG_SOURCE_DHCP,
             .gateway       = gateway,
+            .pref_src      = address.address,
             .table_any     = TRUE,
             .table_coerced = 0,
             .metric_any    = TRUE,
-- 
2.36.1