From df9533d0455eb3e31f7da1ad4728802f7d8dd879 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Jan 2015 14:50:47 +0100 Subject: default-route: improve logging format for default route entries The previous syntax (s/S for synced, n/N for never-default) is confusing. Indicate 'never-default' by '0', vs. '1'. Indicated synced/non-synced as '+sync' and '-sync'. --- src/nm-default-route-manager.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c index c09341a5e3..1ab7fdc63b 100644 --- a/src/nm-default-route-manager.c +++ b/src/nm-default-route-manager.c @@ -76,14 +76,14 @@ NM_DEFINE_SINGLETON_GETTER (NMDefaultRouteManager, nm_default_route_manager_get, #define _LOGW(addr_family, ...) _LOG (LOGL_WARN , addr_family, __VA_ARGS__) #define _LOGE(addr_family, ...) _LOG (LOGL_ERR , addr_family, __VA_ARGS__) -#define LOG_ENTRY_FMT "entry[%u/%s:%p:%s:%c%c]" +#define LOG_ENTRY_FMT "entry[%u/%s:%p:%s:%c:%csync]" #define LOG_ENTRY_ARGS(entry_idx, entry) \ (entry_idx), \ NM_IS_DEVICE ((entry)->source.pointer) ? "dev" : "vpn", \ (entry)->source.pointer, \ NM_IS_DEVICE ((entry)->source.pointer) ? nm_device_get_iface ((entry)->source.device) : nm_vpn_connection_get_connection_id ((entry)->source.vpn), \ - ((entry)->never_default ? 'N' : 'n'), \ - ((entry)->synced ? 'S' : 's') + ((entry)->never_default ? '0' : '1'), \ + ((entry)->synced ? '+' : '-') /***********************************************************************************/ -- cgit v1.2.1 From 92d800b2e35b4c36c13dfb088f1d7a69b83f7191 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 20 Nov 2014 23:36:50 +0100 Subject: core: refactor subtract() functions in NMIP?Config Factor out code of the nm_ip4_config_subtract() and nm_ip6_config_subtract() functions. The code can be reused in the following commit. --- src/nm-ip4-config.c | 206 ++++++++++++++++++++++++++++++++++------------------ src/nm-ip6-config.c | 147 ++++++++++++++++++++++++------------- 2 files changed, 230 insertions(+), 123 deletions(-) diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index fd46678026..6e86365c92 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -541,6 +541,117 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src) g_object_thaw_notify (G_OBJECT (dst)); } +/*******************************************************************************/ + +static int +_addresses_get_index (const NMIP4Config *self, const NMPlatformIP4Address *addr) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->addresses->len; i++) { + const NMPlatformIP4Address *a = &g_array_index (priv->addresses, NMPlatformIP4Address, i); + + if (addr->address == a->address && + addr->plen == a->plen) + return (int) i; + } + return -1; +} + +static int +_nameservers_get_index (const NMIP4Config *self, guint32 ns) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->nameservers->len; i++) { + guint32 n = g_array_index (priv->nameservers, guint32, i); + + if (ns == n) + return (int) i; + } + return -1; +} + +static int +_routes_get_index (const NMIP4Config *self, const NMPlatformIP4Route *route) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->routes->len; i++) { + const NMPlatformIP4Route *r = &g_array_index (priv->routes, NMPlatformIP4Route, i); + + if ( route->network == r->network + && route->plen == r->plen) + return (int) i; + } + return -1; +} + +static int +_domains_get_index (const NMIP4Config *self, const char *domain) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->domains->len; i++) { + const char *d = g_ptr_array_index (priv->domains, i); + + if (g_strcmp0 (domain, d) == 0) + return (int) i; + } + return -1; +} + +static int +_searches_get_index (const NMIP4Config *self, const char *search) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->searches->len; i++) { + const char *s = g_ptr_array_index (priv->searches, i); + + if (g_strcmp0 (search, s) == 0) + return (int) i; + } + return -1; +} + +static int +_nis_servers_get_index (const NMIP4Config *self, guint32 nis_server) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->nis->len; i++) { + guint32 n = g_array_index (priv->nis, guint32, i); + + if (n == nis_server) + return (int) i; + } + return -1; +} + +static int +_wins_get_index (const NMIP4Config *self, guint32 wins_server) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->wins->len; i++) { + guint32 n = g_array_index (priv->wins, guint32, i); + + if (n == wins_server) + return (int) i; + } + return -1; +} + +/*******************************************************************************/ + /** * nm_ip4_config_subtract: * @dst: config from which to remove everything in @src @@ -551,7 +662,8 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src) void nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) { - guint32 i, j; + guint32 i; + gint idx; g_return_if_fail (src != NULL); g_return_if_fail (dst != NULL); @@ -560,31 +672,16 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) /* addresses */ for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++) { - const NMPlatformIP4Address *src_addr = nm_ip4_config_get_address (src, i); - - for (j = 0; j < nm_ip4_config_get_num_addresses (dst); j++) { - const NMPlatformIP4Address *dst_addr = nm_ip4_config_get_address (dst, j); - - if (src_addr->address == dst_addr->address && - src_addr->plen == dst_addr->plen) { - nm_ip4_config_del_address (dst, j); - break; - } - } + idx = _addresses_get_index (dst, nm_ip4_config_get_address (src, i)); + if (idx >= 0) + nm_ip4_config_del_address (dst, idx); } /* nameservers */ for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) { - guint32 src_ns = nm_ip4_config_get_nameserver (src, i); - - for (j = 0; j < nm_ip4_config_get_num_nameservers (dst); j++) { - guint32 dst_ns = nm_ip4_config_get_nameserver (dst, j); - - if (dst_ns == src_ns) { - nm_ip4_config_del_nameserver (dst, j); - break; - } - } + idx = _nameservers_get_index (dst, nm_ip4_config_get_nameserver (src, i)); + if (idx >= 0) + nm_ip4_config_del_nameserver (dst, idx); } /* default gateway */ @@ -596,44 +693,23 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) /* routes */ for (i = 0; i < nm_ip4_config_get_num_routes (src); i++) { - const NMPlatformIP4Route *src_route = nm_ip4_config_get_route (src, i); - - for (j = 0; j < nm_ip4_config_get_num_routes (dst); j++) { - const NMPlatformIP4Route *dst_route = nm_ip4_config_get_route (dst, j); - - if (src_route->network == dst_route->network && src_route->plen == dst_route->plen) { - nm_ip4_config_del_route (dst, j); - break; - } - } + idx = _routes_get_index (dst, nm_ip4_config_get_route (src, i)); + if (idx >= 0) + nm_ip4_config_del_route (dst, idx); } /* domains */ for (i = 0; i < nm_ip4_config_get_num_domains (src); i++) { - const char *src_domain = nm_ip4_config_get_domain (src, i); - - for (j = 0; j < nm_ip4_config_get_num_domains (dst); j++) { - const char *dst_domain = nm_ip4_config_get_domain (dst, j); - - if (g_strcmp0 (src_domain, dst_domain) == 0) { - nm_ip4_config_del_domain (dst, j); - break; - } - } + idx = _domains_get_index (dst, nm_ip4_config_get_domain (src, i)); + if (idx >= 0) + nm_ip4_config_del_domain (dst, idx); } /* dns searches */ for (i = 0; i < nm_ip4_config_get_num_searches (src); i++) { - const char *src_search = nm_ip4_config_get_search (src, i); - - for (j = 0; j < nm_ip4_config_get_num_searches (dst); j++) { - const char *dst_search = nm_ip4_config_get_search (dst, j); - - if (g_strcmp0 (src_search, dst_search) == 0) { - nm_ip4_config_del_search (dst, j); - break; - } - } + idx = _searches_get_index (dst, nm_ip4_config_get_search (src, i)); + if (idx >= 0) + nm_ip4_config_del_search (dst, idx); } /* MSS */ @@ -646,16 +722,9 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) /* NIS */ for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++) { - guint32 src_nis = nm_ip4_config_get_nis_server (src, i); - - for (j = 0; j < nm_ip4_config_get_num_nis_servers (dst); j++) { - guint32 dst_nis = nm_ip4_config_get_nis_server (dst, j); - - if (dst_nis == src_nis) { - nm_ip4_config_del_nis_server (dst, j); - break; - } - } + idx = _nis_servers_get_index (dst, nm_ip4_config_get_nis_server (src, i)); + if (idx >= 0) + nm_ip4_config_del_nis_server (dst, idx); } if (g_strcmp0 (nm_ip4_config_get_nis_domain (src), nm_ip4_config_get_nis_domain (dst)) == 0) @@ -663,16 +732,9 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) /* WINS */ for (i = 0; i < nm_ip4_config_get_num_wins (src); i++) { - guint32 src_wins = nm_ip4_config_get_wins (src, i); - - for (j = 0; j < nm_ip4_config_get_num_wins (dst); j++) { - guint32 dst_wins = nm_ip4_config_get_wins (dst, j); - - if (dst_wins == src_wins) { - nm_ip4_config_del_wins (dst, j); - break; - } - } + idx = _wins_get_index (dst, nm_ip4_config_get_wins (src, i)); + if (idx >= 0) + nm_ip4_config_del_wins (dst, idx); } g_object_thaw_notify (G_OBJECT (dst)); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index db64e72618..950adc1967 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -653,6 +653,85 @@ nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6 return FALSE; } +/*******************************************************************************/ + +static int +_addresses_get_index (const NMIP6Config *self, const NMPlatformIP6Address *addr) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->addresses->len; i++) { + const NMPlatformIP6Address *a = &g_array_index (priv->addresses, NMPlatformIP6Address, i); + + if (IN6_ARE_ADDR_EQUAL (&addr->address, &a->address)) + return (int) i; + } + return -1; +} + +static int +_nameservers_get_index (const NMIP6Config *self, const struct in6_addr *ns) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->nameservers->len; i++) { + const struct in6_addr *n = &g_array_index (priv->nameservers, struct in6_addr, i); + + if (IN6_ARE_ADDR_EQUAL (ns, n)) + return (int) i; + } + return -1; +} + +static int +_routes_get_index (const NMIP6Config *self, const NMPlatformIP6Route *route) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->routes->len; i++) { + const NMPlatformIP6Route *r = &g_array_index (priv->routes, NMPlatformIP6Route, i); + + if (routes_are_duplicate (route, r, FALSE)) + return (int) i; + } + return -1; +} + +static int +_domains_get_index (const NMIP6Config *self, const char *domain) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->domains->len; i++) { + const char *d = g_ptr_array_index (priv->domains, i); + + if (g_strcmp0 (domain, d) == 0) + return (int) i; + } + return -1; +} + +static int +_searches_get_index (const NMIP6Config *self, const char *search) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + guint i; + + for (i = 0; i < priv->searches->len; i++) { + const char *s = g_ptr_array_index (priv->searches, i); + + if (g_strcmp0 (search, s) == 0) + return (int) i; + } + return -1; +} + +/*******************************************************************************/ + /** * nm_ip6_config_subtract: * @dst: config from which to remove everything in @src @@ -663,7 +742,8 @@ nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6 void nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src) { - guint32 i, j; + guint i; + gint idx; const struct in6_addr *dst_tmp, *src_tmp; g_return_if_fail (src != NULL); @@ -673,30 +753,16 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src) /* addresses */ for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++) { - const NMPlatformIP6Address *src_addr = nm_ip6_config_get_address (src, i); - - for (j = 0; j < nm_ip6_config_get_num_addresses (dst); j++) { - const NMPlatformIP6Address *dst_addr = nm_ip6_config_get_address (dst, j); - - if (IN6_ARE_ADDR_EQUAL (&src_addr->address, &dst_addr->address)) { - nm_ip6_config_del_address (dst, j); - break; - } - } + idx = _addresses_get_index (dst, nm_ip6_config_get_address (src, i)); + if (idx >= 0) + nm_ip6_config_del_address (dst, idx); } /* nameservers */ for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++) { - const struct in6_addr *src_ns = nm_ip6_config_get_nameserver (src, i); - - for (j = 0; j < nm_ip6_config_get_num_nameservers (dst); j++) { - const struct in6_addr *dst_ns = nm_ip6_config_get_nameserver (dst, j); - - if (IN6_ARE_ADDR_EQUAL (src_ns, dst_ns)) { - nm_ip6_config_del_nameserver (dst, j); - break; - } - } + idx = _nameservers_get_index (dst, nm_ip6_config_get_nameserver (src, i)); + if (idx >= 0) + nm_ip6_config_del_nameserver (dst, idx); } /* default gateway */ @@ -710,44 +776,23 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src) /* routes */ for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) { - const NMPlatformIP6Route *src_route = nm_ip6_config_get_route (src, i); - - for (j = 0; j < nm_ip6_config_get_num_routes (dst); j++) { - const NMPlatformIP6Route *dst_route = nm_ip6_config_get_route (dst, j); - - if (routes_are_duplicate (src_route, dst_route, FALSE)) { - nm_ip6_config_del_route (dst, j); - break; - } - } + idx = _routes_get_index (dst, nm_ip6_config_get_route (src, i)); + if (idx >= 0) + nm_ip6_config_del_route (dst, idx); } /* domains */ for (i = 0; i < nm_ip6_config_get_num_domains (src); i++) { - const char *src_domain = nm_ip6_config_get_domain (src, i); - - for (j = 0; j < nm_ip6_config_get_num_domains (dst); j++) { - const char *dst_domain = nm_ip6_config_get_domain (dst, j); - - if (g_strcmp0 (src_domain, dst_domain) == 0) { - nm_ip6_config_del_domain (dst, j); - break; - } - } + idx = _domains_get_index (dst, nm_ip6_config_get_domain (src, i)); + if (idx >= 0) + nm_ip6_config_del_domain (dst, idx); } /* dns searches */ for (i = 0; i < nm_ip6_config_get_num_searches (src); i++) { - const char *src_search = nm_ip6_config_get_search (src, i); - - for (j = 0; j < nm_ip6_config_get_num_searches (dst); j++) { - const char *dst_search = nm_ip6_config_get_search (dst, j); - - if (g_strcmp0 (src_search, dst_search) == 0) { - nm_ip6_config_del_search (dst, j); - break; - } - } + idx = _searches_get_index (dst, nm_ip6_config_get_search (src, i)); + if (idx >= 0) + nm_ip6_config_del_search (dst, idx); } if (nm_ip6_config_get_mss (src) == nm_ip6_config_get_mss (dst)) -- cgit v1.2.1 From 49d700e862cd16ab398439790ebe889856f1e6cb Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 20 Nov 2014 23:39:21 +0100 Subject: core: add intersect() functions to NMIP?Config --- src/nm-ip4-config.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/nm-ip4-config.h | 1 + src/nm-ip6-config.c | 70 +++++++++++++++++++++++++++++++++++++++++++++ src/nm-ip6-config.h | 1 + 4 files changed, 154 insertions(+) diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 6e86365c92..97ca718a5e 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -740,6 +740,88 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) g_object_thaw_notify (G_OBJECT (dst)); } +void +nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src) +{ + guint32 i; + gint idx; + + g_return_if_fail (src != NULL); + g_return_if_fail (dst != NULL); + + g_object_freeze_notify (G_OBJECT (dst)); + + /* addresses */ + for (i = 0; i < nm_ip4_config_get_num_addresses (dst); ) { + idx = _addresses_get_index (src, nm_ip4_config_get_address (dst, i)); + if (idx < 0) + nm_ip4_config_del_address (dst, i); + else + i++; + } + + /* nameservers */ + for (i = 0; i < nm_ip4_config_get_num_nameservers (dst); ) { + idx = _nameservers_get_index (src, nm_ip4_config_get_nameserver (dst, i)); + if (idx < 0) + nm_ip4_config_del_nameserver (dst, i); + else + i++; + } + + /* default gateway */ + if ( !nm_ip4_config_get_num_addresses (dst) + || (nm_ip4_config_get_gateway (src) != nm_ip4_config_get_gateway (dst))) + nm_ip4_config_set_gateway (dst, 0); + + /* routes */ + for (i = 0; i < nm_ip4_config_get_num_routes (dst); ) { + idx = _routes_get_index (src, nm_ip4_config_get_route (dst, i)); + if (idx < 0) + nm_ip4_config_del_route (dst, i); + else + i++; + } + + /* domains */ + for (i = 0; i < nm_ip4_config_get_num_domains (dst); ) { + idx = _domains_get_index (src, nm_ip4_config_get_domain (dst, i)); + if (idx < 0) + nm_ip4_config_del_domain (dst, i); + else + i++; + } + + /* dns searches */ + for (i = 0; i < nm_ip4_config_get_num_searches (dst); ) { + idx = _searches_get_index (src, nm_ip4_config_get_search (dst, i)); + if (idx < 0) + nm_ip4_config_del_search (dst, i); + else + i++; + } + + /* NIS */ + for (i = 0; i < nm_ip4_config_get_num_nis_servers (dst); ) { + idx = _nis_servers_get_index (src, nm_ip4_config_get_nis_server (dst, i)); + if (idx < 0) + nm_ip4_config_del_nis_server (dst, i); + else + i++; + } + + /* WINS */ + for (i = 0; i < nm_ip4_config_get_num_wins (dst); ) { + idx = _wins_get_index (src, nm_ip4_config_get_wins (dst, i)); + if (idx < 0) + nm_ip4_config_del_wins (dst, i); + else + i++; + } + + g_object_thaw_notify (G_OBJECT (dst)); +} + /** * nm_ip4_config_replace: diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 5ac455d84f..2b3b24e6af 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -71,6 +71,7 @@ NMSetting *nm_ip4_config_create_setting (const NMIP4Config *config); /* Utility functions */ void nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src); void nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src); +void nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src); gboolean nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes); gboolean nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 dest, int plen); void nm_ip4_config_dump (const NMIP4Config *config, const char *detail); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 950adc1967..a148d826e6 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -801,6 +801,76 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src) g_object_thaw_notify (G_OBJECT (dst)); } +void +nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src) +{ + guint i; + gint idx; + const struct in6_addr *dst_tmp, *src_tmp; + + g_return_if_fail (src != NULL); + g_return_if_fail (dst != NULL); + + g_object_freeze_notify (G_OBJECT (dst)); + + /* addresses */ + for (i = 0; i < nm_ip6_config_get_num_addresses (dst); ) { + idx = _addresses_get_index (src, nm_ip6_config_get_address (dst, i)); + if (idx < 0) + nm_ip6_config_del_address (dst, i); + else + i++; + } + + /* nameservers */ + for (i = 0; i < nm_ip6_config_get_num_nameservers (dst); ) { + idx = _nameservers_get_index (src, nm_ip6_config_get_nameserver (dst, i)); + if (idx < 0) + nm_ip6_config_del_nameserver (dst, i); + else + i++; + } + + /* default gateway */ + dst_tmp = nm_ip6_config_get_gateway (dst); + if (dst_tmp) { + src_tmp = nm_ip6_config_get_gateway (src); + if ( !nm_ip6_config_get_num_addresses (dst) + || !src_tmp + || !IN6_ARE_ADDR_EQUAL (src_tmp, dst_tmp)) + nm_ip6_config_set_gateway (dst, NULL); + } + + /* routes */ + for (i = 0; i < nm_ip6_config_get_num_routes (dst); ) { + idx = _routes_get_index (src, nm_ip6_config_get_route (dst, i)); + if (idx < 0) + nm_ip6_config_del_route (dst, i); + else + i++; + } + + /* domains */ + for (i = 0; i < nm_ip6_config_get_num_domains (src); ) { + idx = _domains_get_index (src, nm_ip6_config_get_domain (dst, i)); + if (idx < 0) + nm_ip6_config_del_domain (dst, i); + else + i++; + } + + /* dns searches */ + for (i = 0; i < nm_ip6_config_get_num_searches (src); i++) { + idx = _searches_get_index (src, nm_ip6_config_get_search (dst, i)); + if (idx < 0) + nm_ip6_config_del_search (dst, i); + else + i++; + } + + g_object_thaw_notify (G_OBJECT (dst)); +} + /** * nm_ip6_config_replace: * @dst: config which will be replaced with everything in @src diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index f1d2dc8dd9..04c9e00341 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -71,6 +71,7 @@ NMSetting *nm_ip6_config_create_setting (const NMIP6Config *config); /* Utility functions */ void nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src); void nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src); +void nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src); gboolean nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes); int nm_ip6_config_destination_is_direct (const NMIP6Config *config, const struct in6_addr *dest, int plen); void nm_ip6_config_dump (const NMIP6Config *config, const char *detail); -- cgit v1.2.1 From 4a83afd530fd5e466be3ac653ac632c9c0157614 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 21 Nov 2014 18:56:32 +0100 Subject: device: refactor ipx_config_merge_and_apply() No functional change, but restructure code to make it clearer(?). --- src/devices/nm-device.c | 247 ++++++++++++++++++++++++++---------------------- 1 file changed, 136 insertions(+), 111 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 607ff3785f..f2fc68898d 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -2874,6 +2874,7 @@ ip4_config_merge_and_apply (NMDevice *self, NMConnection *connection; gboolean success; NMIP4Config *composite; + gboolean has_direct_route; const guint32 default_route_metric = nm_device_get_ip4_route_metric (self); /* Merge all the configs into the composite config */ @@ -2901,70 +2902,81 @@ ip4_config_merge_and_apply (NMDevice *self, * be redundant, so don't bother. */ connection = nm_device_get_connection (self); + if ( connection + && !nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) { + nm_ip4_config_merge_setting (composite, + nm_connection_get_setting_ip4_config (connection), + default_route_metric); + } + + /* Add the default route. + * + * We keep track of the default route of a device in a private field. + * NMDevice needs to know the default route at this point, because the gateway + * might require a direct route (see below). + * + * But also, we don't want to add the default route to priv->ip4_config, + * because the default route from the setting might not be the same that + * NMDefaultRouteManager eventually configures (because the it might + * tweak the effective metric). + */ + + /* unless we come to a different conclusion below, we have no default route and + * the route is assumed. */ priv->default_route.v4_has = FALSE; priv->default_route.v4_is_assumed = TRUE; - if (connection) { - gboolean assumed = nm_device_uses_assumed_connection (self); - NMPlatformIP4Route *route = &priv->default_route.v4; - if (!nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) { - nm_ip4_config_merge_setting (composite, - nm_connection_get_setting_ip4_config (connection), - default_route_metric); + if (!connection) + goto END_ADD_DEFAULT_ROUTE; + + if ( !nm_device_uses_assumed_connection (self) + && nm_default_route_manager_ip4_connection_has_default_route (nm_default_route_manager_get (), connection)) { + guint32 gateway; + + priv->default_route.v4_is_assumed = FALSE; + + if ( !(!commit && priv->ext_ip4_config_had_any_addresses) + && !( commit && nm_ip4_config_get_num_addresses (composite))) { + /* without addresses we can have no default route. */ + goto END_ADD_DEFAULT_ROUTE; } - /* Add the default route. - * - * We keep track of the default route of a device in a private field. - * NMDevice needs to know the default route at this point, because the gateway - * might require a direct route (see below). - * - * But also, we don't want to add the default route to priv->ip4_config, - * because the default route from the setting might not be the same that - * NMDefaultRouteManager eventually configures (because the it might - * tweak the effective metric). - */ - if ( !assumed - && nm_default_route_manager_ip4_connection_has_default_route (nm_default_route_manager_get (), connection)) { - guint32 gateway = 0; - - priv->default_route.v4_is_assumed = FALSE; - if ( (!commit && priv->ext_ip4_config_had_any_addresses) - || ( commit && nm_ip4_config_get_num_addresses (composite))) { - /* For managed interfaces, we can only configure a gateway, if either the external config indicates - * that we already have addresses, or if we are about to commit any addresses. - * Otherwise adding a default route will fail, because NMDefaultRouteManager does not add any - * addresses for the route. */ - gateway = nm_ip4_config_get_gateway (composite); - if ( gateway - || nm_device_get_device_type (self) == NM_DEVICE_TYPE_MODEM) { - memset (route, 0, sizeof (*route)); - route->source = NM_IP_CONFIG_SOURCE_USER; - route->gateway = gateway; - route->metric = default_route_metric; - route->mss = nm_ip4_config_get_mss (composite); - priv->default_route.v4_has = TRUE; - - if ( gateway - && !nm_ip4_config_get_subnet_for_host (composite, gateway) - && !nm_ip4_config_get_direct_route_for_host (composite, gateway)) { - /* add a direct route to the gateway */ - NMPlatformIP4Route r = *route; - - r.network = gateway; - r.plen = 32; - r.gateway = 0; - nm_ip4_config_add_route (composite, &r); - } - } - } - } else { - /* For interfaces that are assumed and that have no default-route by configuration, we assume - * the default connection and pick up whatever is configured. */ - priv->default_route.v4_has = _device_get_default_route_from_platform (self, AF_INET, (NMPlatformIPRoute *) route); + gateway = nm_ip4_config_get_gateway (composite); + if ( !gateway + && nm_device_get_device_type (self) != NM_DEVICE_TYPE_MODEM) + goto END_ADD_DEFAULT_ROUTE; + + has_direct_route = ( gateway == 0 + || nm_ip4_config_get_subnet_for_host (composite, gateway) + || nm_ip4_config_get_direct_route_for_host (composite, gateway)); + + /* In the (!has_direct_route && !commit) case it is not clear whether + * adding the default route will succeed. Still give it a try and add it */ + + priv->default_route.v4_has = TRUE; + memset (&priv->default_route.v4, 0, sizeof (priv->default_route.v4)); + priv->default_route.v4.source = NM_IP_CONFIG_SOURCE_USER; + priv->default_route.v4.gateway = gateway; + priv->default_route.v4.metric = default_route_metric; + priv->default_route.v4.mss = nm_ip4_config_get_mss (composite); + + if (!has_direct_route && commit) { + NMPlatformIP4Route r = priv->default_route.v4; + + /* add a direct route to the gateway */ + r.network = gateway; + r.plen = 32; + r.gateway = 0; + nm_ip4_config_add_route (composite, &r); } + } else { + /* For interfaces that are assumed and that have no default-route by configuration, we assume + * the default connection and pick up whatever is configured. */ + priv->default_route.v4_has = _device_get_default_route_from_platform (self, AF_INET, (NMPlatformIPRoute *) &priv->default_route.v4); } +END_ADD_DEFAULT_ROUTE: + /* Allow setting MTU etc */ if (commit) { if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit) @@ -3438,6 +3450,7 @@ ip6_config_merge_and_apply (NMDevice *self, NMConnection *connection; gboolean success; NMIP6Config *composite; + gboolean has_direct_route; /* If no config was passed in, create a new one */ composite = nm_ip6_config_new (); @@ -3464,69 +3477,81 @@ ip6_config_merge_and_apply (NMDevice *self, * be redundant, so don't bother. */ connection = nm_device_get_connection (self); + if ( connection + && !nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) { + nm_ip6_config_merge_setting (composite, + nm_connection_get_setting_ip6_config (connection), + nm_device_get_ip6_route_metric (self)); + } + + /* Add the default route. + * + * We keep track of the default route of a device in a private field. + * NMDevice needs to know the default route at this point, because the gateway + * might require a direct route (see below). + * + * But also, we don't want to add the default route to priv->ip6_config, + * because the default route from the setting might not be the same that + * NMDefaultRouteManager eventually configures (because the it might + * tweak the effective metric). + */ + + /* unless we come to a different conclusion below, we have no default route and + * the route is assumed. */ priv->default_route.v6_has = FALSE; priv->default_route.v6_is_assumed = TRUE; - if (connection) { - gboolean assumed = nm_device_uses_assumed_connection (self); - NMPlatformIP6Route *route = &priv->default_route.v6; - if (!nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) { - nm_ip6_config_merge_setting (composite, - nm_connection_get_setting_ip6_config (connection), - nm_device_get_ip6_route_metric (self)); + if (!connection) + goto END_ADD_DEFAULT_ROUTE; + + if ( !nm_device_uses_assumed_connection (self) + && nm_default_route_manager_ip6_connection_has_default_route (nm_default_route_manager_get (), connection)) { + const struct in6_addr *gateway; + + priv->default_route.v6_is_assumed = FALSE; + + if ( !(!commit && priv->ext_ip6_config_had_any_addresses) + && !( commit && nm_ip6_config_get_num_addresses (composite))) { + /* without addresses we can have no default route. */ + goto END_ADD_DEFAULT_ROUTE; } - /* Add the default route. - * - * We keep track of the default route of a device in a private field. - * NMDevice needs to know the default route at this point, because the gateway - * might require a direct route (see below). - * - * But also, we don't want to add the default route to priv->ip4_config, - * because the default route from the setting might not be the same that - * NMDefaultRouteManager eventually configures (because the it might - * tweak the effective metric). - */ - if ( !assumed - && nm_default_route_manager_ip6_connection_has_default_route (nm_default_route_manager_get (), connection)) { - const struct in6_addr *gateway = NULL; - - priv->default_route.v6_is_assumed = FALSE; - if ( (!commit && priv->ext_ip6_config_had_any_addresses) - || ( commit && nm_ip6_config_get_num_addresses (composite))) { - /* For managed interfaces, we can only configure a gateway, if either the external config indicates - * that we already have addresses, or if we are about to commit any addresses. - * Otherwise adding a default route will fail, because NMDefaultRouteManager does not add any - * addresses for the route. */ - gateway = nm_ip6_config_get_gateway (composite); - if (gateway) { - memset (route, 0, sizeof (*route)); - route->source = NM_IP_CONFIG_SOURCE_USER; - route->gateway = *gateway; - route->metric = nm_device_get_ip6_route_metric (self); - route->mss = nm_ip6_config_get_mss (composite); - priv->default_route.v6_has = TRUE; - - if ( gateway - && !nm_ip6_config_get_subnet_for_host (composite, gateway) - && !nm_ip6_config_get_direct_route_for_host (composite, gateway)) { - /* add a direct route to the gateway */ - NMPlatformIP6Route r = *route; - - r.network = *gateway; - r.plen = 128; - r.gateway = in6addr_any; - nm_ip6_config_add_route (composite, &r); - } - } - } - } else { - /* For interfaces that are assumed and that have no default-route by configuration, we assume - * the default connection and pick up whatever is configured. */ - priv->default_route.v6_has = _device_get_default_route_from_platform (self, AF_INET6, (NMPlatformIPRoute *) route); + gateway = nm_ip6_config_get_gateway (composite); + if (!gateway) + goto END_ADD_DEFAULT_ROUTE; + + + has_direct_route = ( nm_ip6_config_get_subnet_for_host (composite, gateway) + || nm_ip6_config_get_direct_route_for_host (composite, gateway)); + + + /* In the (!has_direct_route && !commit) case it is not clear whether + * adding the default route will succeed. Still give it a try and add it */ + + priv->default_route.v6_has = TRUE; + memset (&priv->default_route.v6, 0, sizeof (priv->default_route.v6)); + priv->default_route.v6.source = NM_IP_CONFIG_SOURCE_USER; + priv->default_route.v6.gateway = *gateway; + priv->default_route.v6.metric = nm_device_get_ip6_route_metric (self); + priv->default_route.v6.mss = nm_ip6_config_get_mss (composite); + + if (!has_direct_route && commit) { + NMPlatformIP6Route r = priv->default_route.v6; + + /* add a direct route to the gateway */ + r.network = *gateway; + r.plen = 128; + r.gateway = in6addr_any; + nm_ip6_config_add_route (composite, &r); } + } else { + /* For interfaces that are assumed and that have no default-route by configuration, we assume + * the default connection and pick up whatever is configured. */ + priv->default_route.v6_has = _device_get_default_route_from_platform (self, AF_INET6, (NMPlatformIPRoute *) &priv->default_route.v6); } +END_ADD_DEFAULT_ROUTE: + nm_ip6_config_addresses_sort (composite, priv->rdisc ? priv->rdisc_use_tempaddr : NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); -- cgit v1.2.1 From 2c0644908524b6d9256d377b28194ba3d10535d5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 20 Jan 2015 14:19:08 +0100 Subject: device: require a direct route for IPv6 gateway In the IPv4 case, we check whether we have a direct route to the gateway also by looking at the configured addresses/subnets. That is correct, because every IPv4 address also implies a subnet route. For IPv6, we explicitly add all subnet routes manually (noprefixroute), hence, we have a direct route exactly if we have it in our list. Regardless of the configured IPv6 prefixes. --- src/devices/nm-device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index f2fc68898d..7219b0616b 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -3521,8 +3521,8 @@ ip6_config_merge_and_apply (NMDevice *self, goto END_ADD_DEFAULT_ROUTE; - has_direct_route = ( nm_ip6_config_get_subnet_for_host (composite, gateway) - || nm_ip6_config_get_direct_route_for_host (composite, gateway)); + has_direct_route = nm_ip6_config_get_direct_route_for_host (composite, gateway) != NULL; + /* In the (!has_direct_route && !commit) case it is not clear whether -- cgit v1.2.1 From 557667df12fc05b76326d6406553985effeeb2ac Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 21 Nov 2014 13:13:48 +0100 Subject: device: better accept external IP changes When receiving IP changes via platform event, remove all missing addresses and routes from our internal configurations (such as wwan, vpn, dhcp). The effect is that on the next commit, those addresses and routes will not be re-added as they were explicitly removed by the user. However on a new DHCP lease or similar events, the addresses will be added anew. Another important improvement is that the NMIPxConfig of the active device reflects when addresses or routes get removed externally. Before we would continue to expose those entires although they were not actually configured on the device. https://bugzilla.gnome.org/show_bug.cgi?id=740443 --- src/devices/nm-device.c | 134 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 100 insertions(+), 34 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 7219b0616b..77aaedbac7 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -239,9 +239,9 @@ typedef struct { /* IP4 configuration info */ NMIP4Config * ip4_config; /* Combined config from VPN, settings, and device */ IpState ip4_state; + NMIP4Config * con_ip4_config; /* config from the setting */ NMIP4Config * dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */ NMIP4Config * ext_ip4_config; /* Stuff added outside NM */ - gboolean ext_ip4_config_had_any_addresses; NMIP4Config * wwan_ip4_config; /* WWAN configuration */ struct { gboolean v4_has; @@ -276,10 +276,10 @@ typedef struct { /* IP6 configuration info */ NMIP6Config * ip6_config; IpState ip6_state; + NMIP6Config * con_ip6_config; /* config from the setting */ NMIP6Config * vpn6_config; /* routes added by a VPN which uses this device */ NMIP6Config * wwan_ip6_config; NMIP6Config * ext_ip6_config; /* Stuff added outside NM */ - gboolean ext_ip6_config_had_any_addresses; gboolean nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */ NMRDisc * rdisc; @@ -2835,6 +2835,43 @@ _device_get_default_route_from_platform (NMDevice *self, int addr_family, NMPlat return success; } +/*********************************************/ + +static void +ensure_con_ipx_config (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *connection; + + g_assert (!!priv->con_ip4_config == !!priv->con_ip6_config); + + if (priv->con_ip4_config) + return; + + connection = nm_device_get_connection (self); + if (!connection) + return; + + priv->con_ip4_config = nm_ip4_config_new (); + priv->con_ip6_config = nm_ip6_config_new (); + + nm_ip4_config_merge_setting (priv->con_ip4_config, + nm_connection_get_setting_ip4_config (connection), + nm_device_get_ip4_route_metric (self)); + nm_ip6_config_merge_setting (priv->con_ip6_config, + nm_connection_get_setting_ip6_config (connection), + nm_device_get_ip6_route_metric (self)); + + if (nm_device_uses_assumed_connection (self)) { + /* For assumed connections ignore all addresses and routes. */ + nm_ip4_config_reset_addresses (priv->con_ip4_config); + nm_ip4_config_reset_routes (priv->con_ip4_config); + + nm_ip6_config_reset_addresses (priv->con_ip6_config); + nm_ip6_config_reset_routes (priv->con_ip6_config); + } +} + /*********************************************/ /* DHCPv4 stuff */ @@ -2884,6 +2921,9 @@ ip4_config_merge_and_apply (NMDevice *self, } composite = nm_ip4_config_new (); + + ensure_con_ipx_config (self); + if (priv->dev_ip4_config) nm_ip4_config_merge (composite, priv->dev_ip4_config); if (priv->vpn4_config) @@ -2897,17 +2937,12 @@ ip4_config_merge_and_apply (NMDevice *self, if (priv->wwan_ip4_config) nm_ip4_config_merge (composite, priv->wwan_ip4_config); - /* Merge user overrides into the composite config. Generated+assumed - * connections come from the system not the user and merging them would - * be redundant, so don't bother. - */ + /* Merge user overrides into the composite config. For assumed connection, + * con_ip4_config is empty. */ + if (priv->con_ip4_config) + nm_ip4_config_merge (composite, priv->con_ip4_config); + connection = nm_device_get_connection (self); - if ( connection - && !nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) { - nm_ip4_config_merge_setting (composite, - nm_connection_get_setting_ip4_config (connection), - default_route_metric); - } /* Add the default route. * @@ -2935,8 +2970,7 @@ ip4_config_merge_and_apply (NMDevice *self, priv->default_route.v4_is_assumed = FALSE; - if ( !(!commit && priv->ext_ip4_config_had_any_addresses) - && !( commit && nm_ip4_config_get_num_addresses (composite))) { + if (!nm_ip4_config_get_num_addresses (composite)) { /* without addresses we can have no default route. */ goto END_ADD_DEFAULT_ROUTE; } @@ -3454,7 +3488,8 @@ ip6_config_merge_and_apply (NMDevice *self, /* If no config was passed in, create a new one */ composite = nm_ip6_config_new (); - g_assert (composite); + + ensure_con_ipx_config (self); /* Merge all the IP configs into the composite config */ if (priv->ac_ip6_config) @@ -3472,17 +3507,12 @@ ip6_config_merge_and_apply (NMDevice *self, if (priv->wwan_ip6_config) nm_ip6_config_merge (composite, priv->wwan_ip6_config); - /* Merge user overrides into the composite config. Generated+assumed - * connections come from the system not the user and merging them would - * be redundant, so don't bother. - */ + /* Merge user overrides into the composite config. For assumed connections, + * con_ip6_config is empty. */ + if (priv->con_ip6_config) + nm_ip6_config_merge (composite, priv->con_ip6_config); + connection = nm_device_get_connection (self); - if ( connection - && !nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) { - nm_ip6_config_merge_setting (composite, - nm_connection_get_setting_ip6_config (connection), - nm_device_get_ip6_route_metric (self)); - } /* Add the default route. * @@ -3510,8 +3540,7 @@ ip6_config_merge_and_apply (NMDevice *self, priv->default_route.v6_is_assumed = FALSE; - if ( !(!commit && priv->ext_ip6_config_had_any_addresses) - && !( commit && nm_ip6_config_get_num_addresses (composite))) { + if (!nm_ip6_config_get_num_addresses (composite)) { /* without addresses we can have no default route. */ goto END_ADD_DEFAULT_ROUTE; } @@ -6523,13 +6552,31 @@ update_ip_config (NMDevice *self, gboolean initial) /* IPv4 */ g_clear_object (&priv->ext_ip4_config); priv->ext_ip4_config = nm_ip4_config_capture (ifindex, capture_resolv_conf); - priv->ext_ip4_config_had_any_addresses = ( priv->ext_ip4_config - && nm_ip4_config_get_num_addresses (priv->ext_ip4_config) > 0); if (priv->ext_ip4_config) { if (initial) { g_clear_object (&priv->dev_ip4_config); capture_lease_config (self, priv->ext_ip4_config, &priv->dev_ip4_config, NULL, NULL); } + ensure_con_ipx_config (self); + + /* This function was called upon external changes. Remove the configuration + * (adresses,routes) that is no longer present externally from the interal + * config. This way, we don't readd addresses that were manually removed + * by the user. */ + if (priv->con_ip4_config) + nm_ip4_config_intersect (priv->con_ip4_config, priv->ext_ip4_config); + if (priv->dev_ip4_config) + nm_ip4_config_intersect (priv->dev_ip4_config, priv->ext_ip4_config); + if (priv->vpn4_config) + nm_ip4_config_intersect (priv->vpn4_config, priv->ext_ip4_config); + if (priv->wwan_ip4_config) + nm_ip4_config_intersect (priv->wwan_ip4_config, priv->ext_ip4_config); + + /* Remove parts from ext_ip4_config to only contain the information that + * was configured externally -- we already have the same configuration from + * internal origins. */ + if (priv->con_ip4_config) + nm_ip4_config_subtract (priv->ext_ip4_config, priv->con_ip4_config); if (priv->dev_ip4_config) nm_ip4_config_subtract (priv->ext_ip4_config, priv->dev_ip4_config); if (priv->vpn4_config) @@ -6543,14 +6590,34 @@ update_ip_config (NMDevice *self, gboolean initial) /* IPv6 */ g_clear_object (&priv->ext_ip6_config); priv->ext_ip6_config = nm_ip6_config_capture (ifindex, capture_resolv_conf, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); - priv->ext_ip6_config_had_any_addresses = ( priv->ext_ip6_config - && nm_ip6_config_get_num_addresses (priv->ext_ip6_config) > 0); if (priv->ext_ip6_config) { /* Check this before modifying ext_ip6_config */ linklocal6_just_completed = priv->linklocal6_timeout_id && have_ip6_address (priv->ext_ip6_config, TRUE); + ensure_con_ipx_config (self); + + /* This function was called upon external changes. Remove the configuration + * (adresses,routes) that is no longer present externally from the interal + * config. This way, we don't readd addresses that were manually removed + * by the user. */ + if (priv->con_ip6_config) + nm_ip6_config_intersect (priv->con_ip6_config, priv->ext_ip6_config); + if (priv->ac_ip6_config) + nm_ip6_config_intersect (priv->ac_ip6_config, priv->ext_ip6_config); + if (priv->dhcp6_ip6_config) + nm_ip6_config_intersect (priv->dhcp6_ip6_config, priv->ext_ip6_config); + if (priv->wwan_ip6_config) + nm_ip6_config_intersect (priv->wwan_ip6_config, priv->ext_ip6_config); + if (priv->vpn6_config) + nm_ip6_config_intersect (priv->vpn6_config, priv->ext_ip6_config); + + /* Remove parts from ext_ip6_config to only contain the information that + * was configured externally -- we already have the same configuration from + * internal origins. */ + if (priv->con_ip6_config) + nm_ip6_config_subtract (priv->ext_ip6_config, priv->con_ip6_config); if (priv->ac_ip6_config) nm_ip6_config_subtract (priv->ext_ip6_config, priv->ac_ip6_config); if (priv->dhcp6_ip6_config) @@ -7142,20 +7209,19 @@ _cleanup_generic_post (NMDevice *self, gboolean deconfigure) */ nm_device_set_ip4_config (self, NULL, 0, TRUE, &ignored); nm_device_set_ip6_config (self, NULL, TRUE, &ignored); + g_clear_object (&priv->con_ip4_config); g_clear_object (&priv->dev_ip4_config); g_clear_object (&priv->ext_ip4_config); g_clear_object (&priv->wwan_ip4_config); g_clear_object (&priv->vpn4_config); g_clear_object (&priv->ip4_config); + g_clear_object (&priv->con_ip6_config); g_clear_object (&priv->ac_ip6_config); g_clear_object (&priv->ext_ip6_config); g_clear_object (&priv->vpn6_config); g_clear_object (&priv->wwan_ip6_config); g_clear_object (&priv->ip6_config); - priv->ext_ip4_config_had_any_addresses = FALSE; - priv->ext_ip6_config_had_any_addresses = FALSE; - clear_act_request (self); /* Clear legacy IPv4 address property */ -- cgit v1.2.1 From da708059dabb2854d11eed1a403398327b31535b Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 21 Nov 2014 20:21:37 +0100 Subject: device: always pickup externally configured default routes for a device Even more eagerly pickup external default routes from the device. For assumed devices we already picked up the default route. (a) For assumed devices we already did not enforce the default route at all. Instead it was always picked up by from the actualy system configuration. Note that this is the case for assumed-generated connections and for assuming existing connections. That means that when NM assumes a connection at startup, it will never actively manage the default route on that interface. It will only react on what is present. (b) For managed devices that have by configuration no default route, still pick up the default route. That means, that even a device that is managed and never-default=yes, can have the default route -- if configured externally. (c) Only during a commit phase (i.e. when we have new configuraiton to be applied), we enforce the default route or its absence. (d) During any IP change event from platform, we again pickup whatever is present. That means if you remove the default route from a managed interface, NM will not re-add it until anything triggers (c). This also means, that during the commit phase, we add default routes as 'synced' to the default-route-manager, but the following event from platform, will change the route entry immediately to 'non-synced'. That is expected and correct. --- src/devices/nm-device.c | 168 +++++++++++++++++++++++++++--------------------- 1 file changed, 94 insertions(+), 74 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 77aaedbac7..caed116f51 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -2913,6 +2913,7 @@ ip4_config_merge_and_apply (NMDevice *self, NMIP4Config *composite; gboolean has_direct_route; const guint32 default_route_metric = nm_device_get_ip4_route_metric (self); + guint32 gateway; /* Merge all the configs into the composite config */ if (config) { @@ -2961,56 +2962,65 @@ ip4_config_merge_and_apply (NMDevice *self, priv->default_route.v4_has = FALSE; priv->default_route.v4_is_assumed = TRUE; - if (!connection) + if (!commit) { + /* during a non-commit event, we always pickup whatever is configured. */ goto END_ADD_DEFAULT_ROUTE; + } - if ( !nm_device_uses_assumed_connection (self) - && nm_default_route_manager_ip4_connection_has_default_route (nm_default_route_manager_get (), connection)) { - guint32 gateway; + if (nm_device_uses_assumed_connection (self)) + goto END_ADD_DEFAULT_ROUTE; - priv->default_route.v4_is_assumed = FALSE; - if (!nm_ip4_config_get_num_addresses (composite)) { - /* without addresses we can have no default route. */ - goto END_ADD_DEFAULT_ROUTE; - } + /* we are about to commit (for a non-assumed connection). Enforce whatever we have + * configured. */ + priv->default_route.v4_is_assumed = FALSE; - gateway = nm_ip4_config_get_gateway (composite); - if ( !gateway - && nm_device_get_device_type (self) != NM_DEVICE_TYPE_MODEM) - goto END_ADD_DEFAULT_ROUTE; - - has_direct_route = ( gateway == 0 - || nm_ip4_config_get_subnet_for_host (composite, gateway) - || nm_ip4_config_get_direct_route_for_host (composite, gateway)); - - /* In the (!has_direct_route && !commit) case it is not clear whether - * adding the default route will succeed. Still give it a try and add it */ - - priv->default_route.v4_has = TRUE; - memset (&priv->default_route.v4, 0, sizeof (priv->default_route.v4)); - priv->default_route.v4.source = NM_IP_CONFIG_SOURCE_USER; - priv->default_route.v4.gateway = gateway; - priv->default_route.v4.metric = default_route_metric; - priv->default_route.v4.mss = nm_ip4_config_get_mss (composite); - - if (!has_direct_route && commit) { - NMPlatformIP4Route r = priv->default_route.v4; - - /* add a direct route to the gateway */ - r.network = gateway; - r.plen = 32; - r.gateway = 0; - nm_ip4_config_add_route (composite, &r); - } - } else { - /* For interfaces that are assumed and that have no default-route by configuration, we assume - * the default connection and pick up whatever is configured. */ - priv->default_route.v4_has = _device_get_default_route_from_platform (self, AF_INET, (NMPlatformIPRoute *) &priv->default_route.v4); + if ( !connection + || !nm_default_route_manager_ip4_connection_has_default_route (nm_default_route_manager_get (), connection)) + goto END_ADD_DEFAULT_ROUTE; + + if (!nm_ip4_config_get_num_addresses (composite)) { + /* without addresses we can have no default route. */ + goto END_ADD_DEFAULT_ROUTE; + } + + gateway = nm_ip4_config_get_gateway (composite); + if ( !gateway + && nm_device_get_device_type (self) != NM_DEVICE_TYPE_MODEM) + goto END_ADD_DEFAULT_ROUTE; + + has_direct_route = ( gateway == 0 + || nm_ip4_config_get_subnet_for_host (composite, gateway) + || nm_ip4_config_get_direct_route_for_host (composite, gateway)); + + priv->default_route.v4_has = TRUE; + memset (&priv->default_route.v4, 0, sizeof (priv->default_route.v4)); + priv->default_route.v4.source = NM_IP_CONFIG_SOURCE_USER; + priv->default_route.v4.gateway = gateway; + priv->default_route.v4.metric = default_route_metric; + priv->default_route.v4.mss = nm_ip4_config_get_mss (composite); + + if (!has_direct_route) { + NMPlatformIP4Route r = priv->default_route.v4; + + /* add a direct route to the gateway */ + r.network = gateway; + r.plen = 32; + r.gateway = 0; + nm_ip4_config_add_route (composite, &r); } END_ADD_DEFAULT_ROUTE: + if (priv->default_route.v4_is_assumed) { + /* If above does not explicitly assign a default route, we always pick up the + * default route based on what is currently configured. + * That means that even managed connections with never-default, can + * get a default route (if configured externally). + */ + priv->default_route.v4_has = _device_get_default_route_from_platform (self, AF_INET, (NMPlatformIPRoute *) &priv->default_route.v4); + } + /* Allow setting MTU etc */ if (commit) { if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit) @@ -3485,6 +3495,7 @@ ip6_config_merge_and_apply (NMDevice *self, gboolean success; NMIP6Config *composite; gboolean has_direct_route; + const struct in6_addr *gateway; /* If no config was passed in, create a new one */ composite = nm_ip6_config_new (); @@ -3531,56 +3542,65 @@ ip6_config_merge_and_apply (NMDevice *self, priv->default_route.v6_has = FALSE; priv->default_route.v6_is_assumed = TRUE; - if (!connection) + if (!commit) { + /* during a non-commit event, we always pickup whatever is configured. */ goto END_ADD_DEFAULT_ROUTE; + } - if ( !nm_device_uses_assumed_connection (self) - && nm_default_route_manager_ip6_connection_has_default_route (nm_default_route_manager_get (), connection)) { - const struct in6_addr *gateway; + if (nm_device_uses_assumed_connection (self)) + goto END_ADD_DEFAULT_ROUTE; - priv->default_route.v6_is_assumed = FALSE; - if (!nm_ip6_config_get_num_addresses (composite)) { - /* without addresses we can have no default route. */ - goto END_ADD_DEFAULT_ROUTE; - } + /* we are about to commit (for a non-assumed connection). Enforce whatever we have + * configured. */ + priv->default_route.v6_is_assumed = FALSE; + + if ( !connection + || !nm_default_route_manager_ip6_connection_has_default_route (nm_default_route_manager_get (), connection)) + goto END_ADD_DEFAULT_ROUTE; - gateway = nm_ip6_config_get_gateway (composite); - if (!gateway) - goto END_ADD_DEFAULT_ROUTE; + if (!nm_ip6_config_get_num_addresses (composite)) { + /* without addresses we can have no default route. */ + goto END_ADD_DEFAULT_ROUTE; + } + gateway = nm_ip6_config_get_gateway (composite); + if (!gateway) + goto END_ADD_DEFAULT_ROUTE; - has_direct_route = nm_ip6_config_get_direct_route_for_host (composite, gateway) != NULL; + has_direct_route = nm_ip6_config_get_direct_route_for_host (composite, gateway) != NULL; - /* In the (!has_direct_route && !commit) case it is not clear whether - * adding the default route will succeed. Still give it a try and add it */ - priv->default_route.v6_has = TRUE; - memset (&priv->default_route.v6, 0, sizeof (priv->default_route.v6)); - priv->default_route.v6.source = NM_IP_CONFIG_SOURCE_USER; - priv->default_route.v6.gateway = *gateway; - priv->default_route.v6.metric = nm_device_get_ip6_route_metric (self); - priv->default_route.v6.mss = nm_ip6_config_get_mss (composite); + priv->default_route.v6_has = TRUE; + memset (&priv->default_route.v6, 0, sizeof (priv->default_route.v6)); + priv->default_route.v6.source = NM_IP_CONFIG_SOURCE_USER; + priv->default_route.v6.gateway = *gateway; + priv->default_route.v6.metric = nm_device_get_ip6_route_metric (self); + priv->default_route.v6.mss = nm_ip6_config_get_mss (composite); - if (!has_direct_route && commit) { - NMPlatformIP6Route r = priv->default_route.v6; + if (!has_direct_route) { + NMPlatformIP6Route r = priv->default_route.v6; - /* add a direct route to the gateway */ - r.network = *gateway; - r.plen = 128; - r.gateway = in6addr_any; - nm_ip6_config_add_route (composite, &r); - } - } else { - /* For interfaces that are assumed and that have no default-route by configuration, we assume - * the default connection and pick up whatever is configured. */ - priv->default_route.v6_has = _device_get_default_route_from_platform (self, AF_INET6, (NMPlatformIPRoute *) &priv->default_route.v6); + /* add a direct route to the gateway */ + r.network = *gateway; + r.plen = 128; + r.gateway = in6addr_any; + nm_ip6_config_add_route (composite, &r); } END_ADD_DEFAULT_ROUTE: + if (priv->default_route.v6_is_assumed) { + /* If above does not explicitly assign a default route, we always pick up the + * default route based on what is currently configured. + * That means that even managed connections with never-default, can + * get a default route (if configured externally). + */ + priv->default_route.v6_has = _device_get_default_route_from_platform (self, AF_INET6, (NMPlatformIPRoute *) &priv->default_route.v6); + } + nm_ip6_config_addresses_sort (composite, priv->rdisc ? priv->rdisc_use_tempaddr : NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); -- cgit v1.2.1