From 3547c4d09a1d10b150a61bcbdc2418d750f7f616 Mon Sep 17 00:00:00 2001 From: Thomas Haller 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 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