mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-07 03:10:16 +01:00
core: merge branch 'th/bgo738590_dhcp_server_route' (bgo #738590)
https://bugzilla.gnome.org/show_bug.cgi?id=738590 Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
commit
119c0625af
8 changed files with 99 additions and 11 deletions
|
|
@ -120,15 +120,15 @@ nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen)
|
|||
* @src: source ip6 address
|
||||
* @plen: prefix length of network
|
||||
*
|
||||
* Note: this function is self assignment save, to update @src inplace, set both
|
||||
* Note: this function is self assignment safe, to update @src inplace, set both
|
||||
* @dst and @src to the same destination.
|
||||
*/
|
||||
void
|
||||
const struct in6_addr *
|
||||
nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen)
|
||||
{
|
||||
g_return_if_fail (plen <= 128);
|
||||
g_return_if_fail (src);
|
||||
g_return_if_fail (dst);
|
||||
g_return_val_if_fail (plen <= 128, NULL);
|
||||
g_return_val_if_fail (src, NULL);
|
||||
g_return_val_if_fail (dst, NULL);
|
||||
|
||||
if (plen < 128) {
|
||||
guint nbytes = plen / 8;
|
||||
|
|
@ -144,6 +144,8 @@ nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_
|
|||
memset (&dst->s6_addr[nbytes], 0, 16 - nbytes);
|
||||
} else if (src != dst)
|
||||
*dst = *src;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,22 @@
|
|||
gboolean nm_ethernet_address_is_valid (gconstpointer addr, gssize len);
|
||||
|
||||
in_addr_t nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen);
|
||||
void nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);
|
||||
const struct in6_addr *nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen);
|
||||
|
||||
/**
|
||||
* nm_utils_ip6_route_metric_normalize:
|
||||
* @metric: the route metric
|
||||
*
|
||||
* For IPv6 route, kernel treats the value 0 as IP6_RT_PRIO_USER (1024).
|
||||
* Thus, when comparing metric (values), we want to treat zero as NM_PLATFORM_ROUTE_METRIC_DEFAULT.
|
||||
*
|
||||
* Returns: @metric, if @metric is not zero, otherwise 1024.
|
||||
*/
|
||||
static inline guint32
|
||||
nm_utils_ip6_route_metric_normalize (guint32 metric)
|
||||
{
|
||||
return metric ? metric : 1024 /*NM_PLATFORM_ROUTE_METRIC_DEFAULT*/;
|
||||
}
|
||||
|
||||
int nm_spawn_process (const char *args);
|
||||
|
||||
|
|
|
|||
|
|
@ -451,13 +451,13 @@ nm_dhcp_utils_ip4_config_from_options (const char *iface,
|
|||
str = g_hash_table_lookup (options, "dhcp_server_identifier");
|
||||
if (str) {
|
||||
if (inet_pton (AF_INET, str, &tmp_addr) > 0) {
|
||||
NMPlatformIP4Route route;
|
||||
guint32 mask = nm_utils_ip4_prefix_to_netmask (address.plen);
|
||||
|
||||
nm_log_info (LOGD_DHCP4, " server identifier %s", str);
|
||||
if ((tmp_addr & mask) != (address.address & mask)) {
|
||||
/* DHCP server not on assigned subnet, route needed */
|
||||
memset (&route, 0, sizeof (route));
|
||||
if ( nm_utils_ip4_address_clear_host_address(tmp_addr, address.plen) != nm_utils_ip4_address_clear_host_address(address.address, address.plen)
|
||||
&& !nm_ip4_config_get_direct_route_for_host (ip4_config, tmp_addr)) {
|
||||
/* DHCP server not on assigned subnet and the no direct route was returned. Add route */
|
||||
NMPlatformIP4Route route = { 0 };
|
||||
|
||||
route.network = tmp_addr;
|
||||
route.plen = 32;
|
||||
/* this will be a device route if gwaddr is 0 */
|
||||
|
|
|
|||
|
|
@ -1191,6 +1191,36 @@ nm_ip4_config_get_route (const NMIP4Config *config, guint i)
|
|||
return &g_array_index (priv->routes, NMPlatformIP4Route, i);
|
||||
}
|
||||
|
||||
const NMPlatformIP4Route *
|
||||
nm_ip4_config_get_direct_route_for_host (const NMIP4Config *config, guint32 host)
|
||||
{
|
||||
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
||||
int i;
|
||||
NMPlatformIP4Route *best_route = NULL;
|
||||
|
||||
g_return_val_if_fail (host, NULL);
|
||||
|
||||
for (i = 0; i < priv->routes->len; i++ ) {
|
||||
NMPlatformIP4Route *item = &g_array_index (priv->routes, NMPlatformIP4Route, i);
|
||||
|
||||
if (item->gateway != 0)
|
||||
continue;
|
||||
|
||||
if (best_route && best_route->plen > item->plen)
|
||||
continue;
|
||||
|
||||
if (nm_utils_ip4_address_clear_host_address (host, item->plen) != nm_utils_ip4_address_clear_host_address (item->network, item->plen))
|
||||
continue;
|
||||
|
||||
if (best_route && best_route->metric <= item->metric)
|
||||
continue;
|
||||
|
||||
best_route = item;
|
||||
}
|
||||
|
||||
return best_route;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -92,6 +92,8 @@ void nm_ip4_config_del_route (NMIP4Config *config, guint i);
|
|||
guint32 nm_ip4_config_get_num_routes (const NMIP4Config *config);
|
||||
const NMPlatformIP4Route *nm_ip4_config_get_route (const NMIP4Config *config, guint32 i);
|
||||
|
||||
const NMPlatformIP4Route *nm_ip4_config_get_direct_route_for_host (const NMIP4Config *config, guint32 host);
|
||||
|
||||
/* Nameservers */
|
||||
void nm_ip4_config_reset_nameservers (NMIP4Config *config);
|
||||
void nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 nameserver);
|
||||
|
|
|
|||
|
|
@ -1196,6 +1196,41 @@ nm_ip6_config_get_route (const NMIP6Config *config, guint i)
|
|||
return &g_array_index (priv->routes, NMPlatformIP6Route, i);
|
||||
}
|
||||
|
||||
const NMPlatformIP6Route *
|
||||
nm_ip6_config_get_direct_route_for_host (const NMIP6Config *config, const struct in6_addr *host)
|
||||
{
|
||||
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
|
||||
int i;
|
||||
struct in6_addr network2, host2;
|
||||
NMPlatformIP6Route *best_route = NULL;
|
||||
|
||||
g_return_val_if_fail (host && !IN6_IS_ADDR_UNSPECIFIED (host), NULL);
|
||||
|
||||
for (i = 0; i < priv->routes->len; i++ ) {
|
||||
NMPlatformIP6Route *item = &g_array_index (priv->routes, NMPlatformIP6Route, i);
|
||||
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED (&item->gateway))
|
||||
continue;
|
||||
|
||||
if (best_route && best_route->plen > item->plen)
|
||||
continue;
|
||||
|
||||
nm_utils_ip6_address_clear_host_address (&host2, host, item->plen);
|
||||
nm_utils_ip6_address_clear_host_address (&network2, &item->network, item->plen);
|
||||
|
||||
if (!IN6_ARE_ADDR_EQUAL (&network2, &host2))
|
||||
continue;
|
||||
|
||||
if (best_route &&
|
||||
nm_utils_ip6_route_metric_normalize (best_route->metric) <= nm_utils_ip6_route_metric_normalize (item->metric))
|
||||
continue;
|
||||
|
||||
best_route = item;
|
||||
}
|
||||
|
||||
return best_route;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -93,6 +93,8 @@ void nm_ip6_config_del_route (NMIP6Config *config, guint i);
|
|||
guint32 nm_ip6_config_get_num_routes (const NMIP6Config *config);
|
||||
const NMPlatformIP6Route *nm_ip6_config_get_route (const NMIP6Config *config, guint32 i);
|
||||
|
||||
const NMPlatformIP6Route *nm_ip6_config_get_direct_route_for_host (const NMIP6Config *config, const struct in6_addr *host);
|
||||
|
||||
/* Nameservers */
|
||||
void nm_ip6_config_reset_nameservers (NMIP6Config *config);
|
||||
void nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *nameserver);
|
||||
|
|
|
|||
|
|
@ -216,6 +216,8 @@ G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPAddress, address_ptr) == G_STRUCT_
|
|||
#undef __NMPlatformIPAddress_COMMON
|
||||
|
||||
|
||||
/* Adding an IPv6 route with metric 0, kernel translates to IP6_RT_PRIO_USER (1024).
|
||||
* Thus, the value is not choosen arbitraily, but matches kernel IPv6 default. */
|
||||
#define NM_PLATFORM_ROUTE_METRIC_DEFAULT 1024
|
||||
|
||||
#define __NMPlatformIPRoute_COMMON \
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue