core/platform: add address/route sources (rh#1005416, bgo#722843)

Tag addresses and routes with their source.  We'll use this later to do
(or not do) operations based on where the item came from.

One thing to note is that when synchronizing items with the kernel, all
items are read as source=KERNEL even when they originally came from
NetworkManager, since the kernel has no way of providing this source
information.  This requires the source 'priority', which
nm_ip*_config_add_address() and nm_ip*_config_add_route() must respect
to ensure that NM-owned routes don't have their source overwritten
when merging various IP configs in ip*_config_merge_and_apply().

Also of note is that memcmp() can no longer be used to compare
addresses/routes in nm-platform.c, but this had problems before
anyway with ifindex, so that workaround from nm_platform_ip4_route_sync()
can be removed.

https://bugzilla.gnome.org/show_bug.cgi?id=722843
https://bugzilla.redhat.com/show_bug.cgi?id=1005416
This commit is contained in:
Dan Williams
2014-01-06 14:14:14 -06:00
parent d7c369712b
commit 067db6f8d7
14 changed files with 425 additions and 16 deletions

View File

@@ -2310,12 +2310,14 @@ aipd_get_ip4_config (NMDevice *self, guint32 lla)
memset (&address, 0, sizeof (address));
address.address = lla;
address.plen = 16;
address.source = NM_PLATFORM_SOURCE_IP4LL;
nm_ip4_config_add_address (config, &address);
/* Add a multicast route for link-local connections: destination= 224.0.0.0, netmask=240.0.0.0 */
memset (&route, 0, sizeof (route));
route.network = htonl (0xE0000000L);
route.plen = 4;
route.source = NM_PLATFORM_SOURCE_IP4LL;
nm_ip4_config_add_route (config, &route);
return config;
@@ -2834,6 +2836,7 @@ shared4_new_config (NMDevice *self, NMConnection *connection, NMDeviceStateReaso
}
config = nm_ip4_config_new ();
address.source = NM_PLATFORM_SOURCE_SHARED;
nm_ip4_config_add_address (config, &address);
/* Remove the address lock when the object gets disposed */
@@ -3327,6 +3330,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
address.timestamp = discovered_address->timestamp;
address.lifetime = discovered_address->lifetime;
address.preferred = discovered_address->preferred;
address.source = NM_PLATFORM_SOURCE_RDISC;
nm_ip6_config_add_address (priv->ac_ip6_config, &address);
}
@@ -3349,6 +3353,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *device
route.network = discovered_route->network;
route.plen = discovered_route->plen;
route.gateway = discovered_route->gateway;
route.source = NM_PLATFORM_SOURCE_RDISC;
nm_ip6_config_add_route (priv->ac_ip6_config, &route);
}

View File

@@ -866,6 +866,7 @@ ip4_process_dhcpcd_rfc3442_routes (const char *str,
route.network = rt_addr;
route.plen = rt_cidr;
route.gateway = rt_route;
route.source = NM_PLATFORM_SOURCE_DHCP;
nm_ip4_config_add_route (ip4_config, &route);
}
}
@@ -968,6 +969,7 @@ ip4_process_dhclient_rfc3442_routes (const char *str,
char addr[INET_ADDRSTRLEN];
/* normal route */
route.source = NM_PLATFORM_SOURCE_DHCP;
nm_ip4_config_add_route (ip4_config, &route);
nm_log_info (LOGD_DHCP4, " classless static route %s/%d gw %s",
@@ -1087,6 +1089,7 @@ process_classful_routes (GHashTable *options, NMIP4Config *ip4_config)
route.plen = 32;
}
route.gateway = rt_route;
route.source = NM_PLATFORM_SOURCE_DHCP;
nm_ip4_config_add_route (ip4_config, &route);
nm_log_info (LOGD_DHCP, " static route %s",
@@ -1252,6 +1255,7 @@ ip4_options_to_config (NMDHCPClient *self)
nm_log_info (LOGD_DHCP4, " lease time %d", address.lifetime);
}
address.source = NM_PLATFORM_SOURCE_DHCP;
nm_ip4_config_add_address (ip4_config, &address);
str = g_hash_table_lookup (priv->options, "new_host_name");
@@ -1419,6 +1423,7 @@ ip6_options_to_config (NMDHCPClient *self)
}
address.address = tmp_addr;
address.source = NM_PLATFORM_SOURCE_DHCP;
nm_ip6_config_add_address (ip6_config, &address);
nm_log_info (LOGD_DHCP6, " address %s", str);
} else if (priv->info_only == FALSE) {

View File

@@ -625,6 +625,7 @@ nm_dhcp_dhclient_read_lease_ip_configs (const char *iface,
address.plen = nm_utils_ip4_get_default_prefix (address.address);
address.lifetime = address.preferred = expiry;
address.source = NM_PLATFORM_SOURCE_DHCP;
ip4 = nm_ip4_config_new ();
nm_ip4_config_add_address (ip4, &address);

View File

@@ -656,6 +656,7 @@ static_stage3_done (NMModemBroadband *self)
memset (&address, 0, sizeof (address));
address.address = address_network;
address.plen = mm_bearer_ip_config_get_prefix (self->priv->ipv4_config);
address.source = NM_PLATFORM_SOURCE_WWAN;
nm_ip4_config_add_address (config, &address);
nm_log_info (LOGD_MB, " address %s/%d",

View File

@@ -620,6 +620,7 @@ static_stage3_done (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
/* IP address */
address.address = g_value_get_uint (g_value_array_get_nth (ret_array, 0));
address.plen = 32;
address.source = NM_PLATFORM_SOURCE_WWAN;
nm_ip4_config_add_address (config, &address);
nm_log_info (LOGD_MB, " address %s/%d",

View File

@@ -335,6 +335,7 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIP4Config *setting)
address.plen = nm_ip4_address_get_prefix (s_addr);
address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
address.source = NM_PLATFORM_SOURCE_USER;
nm_ip4_config_add_address (config, &address);
}
@@ -351,6 +352,7 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIP4Config *setting)
route.plen = nm_ip4_route_get_prefix (s_route);
route.gateway = nm_ip4_route_get_next_hop (s_route);
route.metric = nm_ip4_route_get_metric (s_route);
route.source = NM_PLATFORM_SOURCE_USER;
nm_ip4_config_add_route (config, &route);
}
@@ -981,10 +983,21 @@ nm_ip4_config_reset_addresses (NMIP4Config *config)
}
}
/**
* nm_ip4_config_add_address:
* @config: the #NMIP4Config
* @new: the new address to add to @config
*
* Adds the new address to @config. If an address with the same basic properties
* (address, prefix) already exists in @config, it is overwritten with the
* lifetime and preferred of @new. The source is also overwritten by the source
* from @new if that source is higher priority.
*/
void
nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
NMPlatformSource old_source;
int i;
g_return_if_fail (new != NULL);
@@ -995,7 +1008,10 @@ nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new)
if (addresses_are_duplicate (item, new, FALSE)) {
if (nm_platform_ip4_address_cmp (item, new) == 0)
return;
old_source = item->source;
memcpy (item, new, sizeof (*item));
/* Restore highest priority source */
item->source = MAX (old_source, new->source);
goto NOTIFY;
}
}
@@ -1061,10 +1077,21 @@ nm_ip4_config_reset_routes (NMIP4Config *config)
}
}
/**
* nm_ip4_config_add_route:
* @config: the #NMIP4Config
* @new: the new route to add to @config
*
* Adds the new route to @config. If a route with the same basic properties
* (network, prefix) already exists in @config, it is overwritten including the
* gateway and metric of @new. The source is also overwritten by the source
* from @new if that source is higher priority.
*/
void
nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
NMPlatformSource old_source;
int i;
g_return_if_fail (new != NULL);
@@ -1075,7 +1102,10 @@ nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new)
if (routes_are_duplicate (item, new, FALSE)) {
if (nm_platform_ip4_route_cmp (item, new) == 0)
return;
old_source = item->source;
memcpy (item, new, sizeof (*item));
/* Restore highest priority source */
item->source = MAX (old_source, new->source);
goto NOTIFY;
}
}
@@ -1500,6 +1530,19 @@ nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only
}
}
/**
* nm_ip4_config_equal:
* @a: first config to compare
* @b: second config to compare
*
* Compares two #NMIP4Configs for basic equality. This means that all
* attributes must exist in the same order in both configs (addresses, routes,
* domains, DNS servers, etc) but some attributes (address lifetimes, and address
* and route sources) are ignored.
*
* Returns: %TRUE if the configurations are basically equal to each other,
* %FALSE if not
*/
gboolean
nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b)
{

View File

@@ -330,6 +330,7 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIP6Config *setting)
address.plen = nm_ip6_address_get_prefix (s_addr);
address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
address.source = NM_PLATFORM_SOURCE_USER;
nm_ip6_config_add_address (config, &address);
}
@@ -346,6 +347,7 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIP6Config *setting)
route.plen = nm_ip6_route_get_prefix (s_route);
route.gateway = *nm_ip6_route_get_next_hop (s_route);
route.metric = nm_ip6_route_get_metric (s_route);
route.source = NM_PLATFORM_SOURCE_USER;
nm_ip6_config_add_route (config, &route);
}
@@ -887,10 +889,21 @@ nm_ip6_config_reset_addresses (NMIP6Config *config)
}
}
/**
* nm_ip6_config_add_address:
* @config: the #NMIP6Config
* @new: the new address to add to @config
*
* Adds the new address to @config. If an address with the same basic properties
* (address, prefix) already exists in @config, it is overwritten with the
* lifetime and preferred of @new. The source is also overwritten by the source
* from @new if that source is higher priority.
*/
void
nm_ip6_config_add_address (NMIP6Config *config, const NMPlatformIP6Address *new)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
NMPlatformSource old_source;
int i;
g_return_if_fail (new != NULL);
@@ -901,8 +914,11 @@ nm_ip6_config_add_address (NMIP6Config *config, const NMPlatformIP6Address *new)
if (IN6_ARE_ADDR_EQUAL (&item->address, &new->address)) {
if (nm_platform_ip6_address_cmp (item, new) == 0)
return;
old_source = item->source;
/* Copy over old item to get new lifetime, timestamp, preferred */
*item = *new;
/* But restore highest priority source */
item->source = MAX (old_source, new->source);
goto NOTIFY;
}
}
@@ -969,10 +985,21 @@ nm_ip6_config_reset_routes (NMIP6Config *config)
}
}
/**
* nm_ip6_config_add_route:
* @config: the #NMIP6Config
* @new: the new route to add to @config
*
* Adds the new route to @config. If a route with the same basic properties
* (network, prefix) already exists in @config, it is overwritten including the
* gateway and metric of @new. The source is also overwritten by the source
* from @new if that source is higher priority.
*/
void
nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
NMPlatformSource old_source;
int i;
g_return_if_fail (new != NULL);
@@ -983,7 +1010,10 @@ nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new)
if (routes_are_duplicate (item, new, FALSE)) {
if (nm_platform_ip6_route_cmp (item, new) == 0)
return;
old_source = item->source;
*item = *new;
/* Restore highest priority source */
item->source = MAX (old_source, new->source);
goto NOTIFY;
}
}
@@ -1268,6 +1298,19 @@ nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only
}
}
/**
* nm_ip6_config_equal:
* @a: first config to compare
* @b: second config to compare
*
* Compares two #NMIP6Configs for basic equality. This means that all
* attributes must exist in the same order in both configs (addresses, routes,
* domains, DNS servers, etc) but some attributes (address lifetimes, and address
* and route sources) are ignored.
*
* Returns: %TRUE if the configurations are basically equal to each other,
* %FALSE if not
*/
gboolean
nm_ip6_config_equal (const NMIP6Config *a, const NMIP6Config *b)
{

View File

@@ -2196,6 +2196,7 @@ ip4_address_get_all (NMPlatform *platform, int ifindex)
for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) {
if (nl_object_is_marked (object)) {
init_ip4_address (&address, (struct rtnl_addr *) object);
address.source = NM_PLATFORM_SOURCE_KERNEL;
g_array_append_val (addresses, address);
nl_object_unmark (object);
}
@@ -2219,6 +2220,7 @@ ip6_address_get_all (NMPlatform *platform, int ifindex)
for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) {
if (nl_object_is_marked (object)) {
init_ip6_address (&address, (struct rtnl_addr *) object);
address.source = NM_PLATFORM_SOURCE_KERNEL;
g_array_append_val (addresses, address);
nl_object_unmark (object);
}
@@ -2410,6 +2412,7 @@ ip4_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
for (object = nl_cache_get_first (priv->route_cache); object; object = nl_cache_get_next (object)) {
if (nl_object_is_marked (object)) {
if (init_ip4_route (&route, (struct rtnl_route *) object)) {
route.source = NM_PLATFORM_SOURCE_KERNEL;
if (route.plen != 0 || include_default)
g_array_append_val (routes, route);
}
@@ -2435,6 +2438,7 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
for (object = nl_cache_get_first (priv->route_cache); object; object = nl_cache_get_next (object)) {
if (nl_object_is_marked (object)) {
if (init_ip6_route (&route, (struct rtnl_route *) object)) {
route.source = NM_PLATFORM_SOURCE_KERNEL;
if (route.plen != 0 || include_default)
g_array_append_val (routes, route);
}

View File

@@ -1563,9 +1563,15 @@ array_contains_ip4_route (const GArray *routes, const NMPlatformIP4Route *route)
guint len = routes ? routes->len : 0;
guint i;
for (i = 0; i < len; i++)
if (!memcmp (&g_array_index (routes, NMPlatformIP4Route, i), route, sizeof (*route)))
for (i = 0; i < len; i++) {
NMPlatformIP4Route *c = &g_array_index (routes, NMPlatformIP4Route, i);
if (route->network == c->network &&
route->plen == c->plen &&
route->gateway == c->gateway &&
route->metric == c->metric)
return TRUE;
}
return FALSE;
}
@@ -1576,9 +1582,15 @@ array_contains_ip6_route (const GArray *routes, const NMPlatformIP6Route *route)
guint len = routes ? routes->len : 0;
guint i;
for (i = 0; i < len; i++)
if (!memcmp (&g_array_index (routes, NMPlatformIP6Route, i), route, sizeof (*route)))
for (i = 0; i < len; i++) {
NMPlatformIP6Route *c = &g_array_index (routes, NMPlatformIP6Route, i);
if (IN6_ARE_ADDR_EQUAL (&route->network, &c->network) &&
route->plen == c->plen &&
IN6_ARE_ADDR_EQUAL (&route->gateway, &c->gateway) &&
route->metric == c->metric)
return TRUE;
}
return FALSE;
}
@@ -1606,7 +1618,6 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes)
routes = nm_platform_ip4_route_get_all (ifindex, FALSE);
for (i = 0; i < routes->len; i++) {
route = &g_array_index (routes, NMPlatformIP4Route, i);
route->ifindex = 0;
if (!array_contains_ip4_route (known_routes, route))
nm_platform_ip4_route_delete (ifindex, route->network, route->plen, route->metric);
@@ -1684,6 +1695,34 @@ nm_platform_route_flush (int ifindex)
/******************************************************************/
static const char *
source_to_string (NMPlatformSource source)
{
switch (source) {
case NM_PLATFORM_SOURCE_KERNEL:
return "kernel";
case NM_PLATFORM_SOURCE_SHARED:
return "shared";
case NM_PLATFORM_SOURCE_IP4LL:
return "ipv4ll";
case NM_PLATFORM_SOURCE_PPP:
return "ppp";
case NM_PLATFORM_SOURCE_WWAN:
return "wwan";
case NM_PLATFORM_SOURCE_VPN:
return "vpn";
case NM_PLATFORM_SOURCE_DHCP:
return "dhcp";
case NM_PLATFORM_SOURCE_RDISC:
return "rdisc";
case NM_PLATFORM_SOURCE_USER:
return "user";
default:
break;
}
return "unknown";
}
/**
* nm_platform_ip4_address_to_string:
* @route: pointer to NMPlatformIP4Address address structure
@@ -1718,11 +1757,12 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address)
s_dev = address->ifindex > 0 ? nm_platform_link_get_name (address->ifindex) : NULL;
str_dev = s_dev ? g_strconcat (" dev ", s_dev, NULL) : NULL;
g_snprintf (buffer, sizeof (buffer), "%s/%d lft %u pref %u time %u%s%s",
g_snprintf (buffer, sizeof (buffer), "%s/%d lft %u pref %u time %u%s%s src %s",
s_address, address->plen, (guint)address->lifetime, (guint)address->preferred,
(guint)address->timestamp,
str_peer ? str_peer : "",
str_dev ? str_dev : "");
str_dev ? str_dev : "",
source_to_string (address->source));
g_free (str_dev);
g_free (str_peer);
return buffer;
@@ -1767,12 +1807,13 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address)
rtnl_addr_flags2str(address->flags, s_flags, sizeof(s_flags));
str_flags = s_flags[0] ? g_strconcat (" flags ", s_flags, NULL) : NULL;
g_snprintf (buffer, sizeof (buffer), "%s/%d lft %u pref %u time %u%s%s%s",
g_snprintf (buffer, sizeof (buffer), "%s/%d lft %u pref %u time %u%s%s%s src %s",
s_address, address->plen, (guint)address->lifetime, (guint)address->preferred,
(guint)address->timestamp,
str_peer ? str_peer : "",
str_dev ? str_dev : "",
str_flags ? str_flags : "");
str_flags ? str_flags : "",
source_to_string (address->source));
g_free (str_flags);
g_free (str_dev);
g_free (str_peer);
@@ -1807,10 +1848,11 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route)
s_dev = route->ifindex > 0 ? nm_platform_link_get_name (route->ifindex) : NULL;
str_dev = s_dev ? g_strconcat (" dev ", s_dev, NULL) : NULL;
g_snprintf (buffer, sizeof (buffer), "%s/%d via %s%s metric %u mss %u",
g_snprintf (buffer, sizeof (buffer), "%s/%d via %s%s metric %u mss %u src %s",
s_network, route->plen, s_gateway,
str_dev ? str_dev : "",
route->metric, route->mss);
route->metric, route->mss,
source_to_string (route->source));
g_free (str_dev);
return buffer;
}
@@ -1843,10 +1885,11 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route)
s_dev = route->ifindex > 0 ? nm_platform_link_get_name (route->ifindex) : NULL;
str_dev = s_dev ? g_strconcat (" dev ", s_dev, NULL) : NULL;
g_snprintf (buffer, sizeof (buffer), "%s/%d via %s%s metric %u mss %u",
g_snprintf (buffer, sizeof (buffer), "%s/%d via %s%s metric %u mss %u src %s",
s_network, route->plen, s_gateway,
str_dev ? str_dev : "",
route->metric, route->mss);
route->metric, route->mss,
source_to_string (route->source));
g_free (str_dev);
return buffer;
}
@@ -1879,9 +1922,10 @@ int
nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b)
{
_CMP_POINTER (a, b);
_CMP_FIELD (a, b, ifindex);
_CMP_FIELD (a, b, source);
_CMP_FIELD_MEMCMP (a, b, address);
_CMP_FIELD_MEMCMP (a, b, peer_address);
_CMP_FIELD (a, b, ifindex);
_CMP_FIELD (a, b, plen);
_CMP_FIELD (a, b, timestamp);
_CMP_FIELD (a, b, lifetime);
@@ -1894,6 +1938,7 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A
{
_CMP_POINTER (a, b);
_CMP_FIELD (a, b, ifindex);
_CMP_FIELD (a, b, source);
_CMP_FIELD_MEMCMP (a, b, address);
_CMP_FIELD_MEMCMP (a, b, peer_address);
_CMP_FIELD (a, b, plen);
@@ -1909,6 +1954,7 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
{
_CMP_POINTER (a, b);
_CMP_FIELD (a, b, ifindex);
_CMP_FIELD (a, b, source);
_CMP_FIELD_MEMCMP (a, b, network);
_CMP_FIELD (a, b, plen);
_CMP_FIELD_MEMCMP (a, b, gateway);
@@ -1922,6 +1968,7 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
{
_CMP_POINTER (a, b);
_CMP_FIELD (a, b, ifindex);
_CMP_FIELD (a, b, source);
_CMP_FIELD_MEMCMP (a, b, network);
_CMP_FIELD (a, b, plen);
_CMP_FIELD_MEMCMP (a, b, gateway);

View File

@@ -119,8 +119,23 @@ typedef struct {
#define NM_PLATFORM_LIFETIME_PERMANENT G_MAXUINT32
typedef enum {
/* In priority order; higher number == higher priority */
NM_PLATFORM_SOURCE_UNKNOWN,
NM_PLATFORM_SOURCE_KERNEL,
NM_PLATFORM_SOURCE_SHARED,
NM_PLATFORM_SOURCE_IP4LL,
NM_PLATFORM_SOURCE_PPP,
NM_PLATFORM_SOURCE_WWAN,
NM_PLATFORM_SOURCE_VPN,
NM_PLATFORM_SOURCE_DHCP,
NM_PLATFORM_SOURCE_RDISC,
NM_PLATFORM_SOURCE_USER,
} NMPlatformSource;
typedef struct {
int ifindex;
NMPlatformSource source;
in_addr_t address;
in_addr_t peer_address; /* PTP peer address */
int plen;
@@ -131,6 +146,7 @@ typedef struct {
typedef struct {
int ifindex;
NMPlatformSource source;
struct in6_addr address;
struct in6_addr peer_address;
int plen;
@@ -142,6 +158,7 @@ typedef struct {
typedef struct {
int ifindex;
NMPlatformSource source;
in_addr_t network;
int plen;
in_addr_t gateway;
@@ -151,6 +168,7 @@ typedef struct {
typedef struct {
int ifindex;
NMPlatformSource source;
struct in6_addr network;
int plen;
struct in6_addr gateway;

View File

@@ -550,6 +550,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager,
address.plen = g_value_get_uint (val);
if (address.address && address.plen) {
address.source = NM_PLATFORM_SOURCE_PPP;
nm_ip4_config_add_address (config, &address);
} else {
nm_log_err (LOGD_PPP, "invalid IPv4 address received!");

View File

@@ -173,6 +173,119 @@ test_subtract (void)
g_object_unref (dst);
}
static void
test_compare_with_source (void)
{
NMIP4Config *a, *b;
NMPlatformIP4Address addr;
NMPlatformIP4Route route;
a = nm_ip4_config_new ();
b = nm_ip4_config_new ();
/* Address */
addr_init (&addr, "1.2.3.4", NULL, 24);
addr.source = NM_PLATFORM_SOURCE_USER;
nm_ip4_config_add_address (a, &addr);
addr.source = NM_PLATFORM_SOURCE_VPN;
nm_ip4_config_add_address (b, &addr);
/* Route */
route_new (&route, "10.0.0.0", 8, "192.168.1.1");
route.source = NM_PLATFORM_SOURCE_USER;
nm_ip4_config_add_route (a, &route);
route.source = NM_PLATFORM_SOURCE_VPN;
nm_ip4_config_add_route (b, &route);
/* Assert that the configs are basically the same, eg that the source is ignored */
g_assert (nm_ip4_config_equal (a, b));
g_object_unref (a);
g_object_unref (b);
}
static void
test_add_address_with_source (void)
{
NMIP4Config *a;
NMPlatformIP4Address addr;
const NMPlatformIP4Address *test_addr;
a = nm_ip4_config_new ();
/* Test that a higher priority source is not overwritten */
addr_init (&addr, "1.2.3.4", NULL, 24);
addr.source = NM_PLATFORM_SOURCE_USER;
nm_ip4_config_add_address (a, &addr);
test_addr = nm_ip4_config_get_address (a, 0);
g_assert_cmpint (test_addr->source, ==, NM_PLATFORM_SOURCE_USER);
addr.source = NM_PLATFORM_SOURCE_VPN;
nm_ip4_config_add_address (a, &addr);
test_addr = nm_ip4_config_get_address (a, 0);
g_assert_cmpint (test_addr->source, ==, NM_PLATFORM_SOURCE_USER);
/* Test that a lower priority address source is overwritten */
nm_ip4_config_del_address (a, 0);
addr.source = NM_PLATFORM_SOURCE_KERNEL;
nm_ip4_config_add_address (a, &addr);
test_addr = nm_ip4_config_get_address (a, 0);
g_assert_cmpint (test_addr->source, ==, NM_PLATFORM_SOURCE_KERNEL);
addr.source = NM_PLATFORM_SOURCE_USER;
nm_ip4_config_add_address (a, &addr);
test_addr = nm_ip4_config_get_address (a, 0);
g_assert_cmpint (test_addr->source, ==, NM_PLATFORM_SOURCE_USER);
g_object_unref (a);
}
static void
test_add_route_with_source (void)
{
NMIP4Config *a;
NMPlatformIP4Route route;
const NMPlatformIP4Route *test_route;
a = nm_ip4_config_new ();
/* Test that a higher priority source is not overwritten */
route_new (&route, "1.2.3.4", 24, "1.2.3.1");
route.source = NM_PLATFORM_SOURCE_USER;
nm_ip4_config_add_route (a, &route);
test_route = nm_ip4_config_get_route (a, 0);
g_assert_cmpint (test_route->source, ==, NM_PLATFORM_SOURCE_USER);
route.source = NM_PLATFORM_SOURCE_VPN;
nm_ip4_config_add_route (a, &route);
test_route = nm_ip4_config_get_route (a, 0);
g_assert_cmpint (test_route->source, ==, NM_PLATFORM_SOURCE_USER);
/* Test that a lower priority address source is overwritten */
nm_ip4_config_del_route (a, 0);
route.source = NM_PLATFORM_SOURCE_KERNEL;
nm_ip4_config_add_route (a, &route);
test_route = nm_ip4_config_get_route (a, 0);
g_assert_cmpint (test_route->source, ==, NM_PLATFORM_SOURCE_KERNEL);
route.source = NM_PLATFORM_SOURCE_USER;
nm_ip4_config_add_route (a, &route);
test_route = nm_ip4_config_get_route (a, 0);
g_assert_cmpint (test_route->source, ==, NM_PLATFORM_SOURCE_USER);
g_object_unref (a);
}
/*******************************************/
int
@@ -183,6 +296,9 @@ main (int argc, char **argv)
g_type_init ();
g_test_add_func ("/ip4-config/subtract", test_subtract);
g_test_add_func ("/ip4-config/compare-with-source", test_compare_with_source);
g_test_add_func ("/ip4-config/add-address-with-source", test_add_address_with_source);
g_test_add_func ("/ip4-config/add-route-with-source", test_add_route_with_source);
return g_test_run ();
}

View File

@@ -160,6 +160,119 @@ test_subtract (void)
g_object_unref (dst);
}
static void
test_compare_with_source (void)
{
NMIP6Config *a, *b;
NMPlatformIP6Address addr;
NMPlatformIP6Route route;
a = nm_ip6_config_new ();
b = nm_ip6_config_new ();
/* Address */
addr_init (&addr, "1122:3344:5566::7788", NULL, 64);
addr.source = NM_PLATFORM_SOURCE_USER;
nm_ip6_config_add_address (a, &addr);
addr.source = NM_PLATFORM_SOURCE_VPN;
nm_ip6_config_add_address (b, &addr);
/* Route */
route_new (&route, "abcd:1234:4321::", 24, "abcd:1234:4321:cdde::2");
route.source = NM_PLATFORM_SOURCE_USER;
nm_ip6_config_add_route (a, &route);
route.source = NM_PLATFORM_SOURCE_VPN;
nm_ip6_config_add_route (b, &route);
/* Assert that the configs are basically the same, eg that the source is ignored */
g_assert (nm_ip6_config_equal (a, b));
g_object_unref (a);
g_object_unref (b);
}
static void
test_add_address_with_source (void)
{
NMIP6Config *a;
NMPlatformIP6Address addr;
const NMPlatformIP6Address *test_addr;
a = nm_ip6_config_new ();
/* Test that a higher priority source is not overwritten */
addr_init (&addr, "1122:3344:5566::7788", NULL, 64);
addr.source = NM_PLATFORM_SOURCE_USER;
nm_ip6_config_add_address (a, &addr);
test_addr = nm_ip6_config_get_address (a, 0);
g_assert_cmpint (test_addr->source, ==, NM_PLATFORM_SOURCE_USER);
addr.source = NM_PLATFORM_SOURCE_VPN;
nm_ip6_config_add_address (a, &addr);
test_addr = nm_ip6_config_get_address (a, 0);
g_assert_cmpint (test_addr->source, ==, NM_PLATFORM_SOURCE_USER);
/* Test that a lower priority address source is overwritten */
nm_ip6_config_del_address (a, 0);
addr.source = NM_PLATFORM_SOURCE_KERNEL;
nm_ip6_config_add_address (a, &addr);
test_addr = nm_ip6_config_get_address (a, 0);
g_assert_cmpint (test_addr->source, ==, NM_PLATFORM_SOURCE_KERNEL);
addr.source = NM_PLATFORM_SOURCE_USER;
nm_ip6_config_add_address (a, &addr);
test_addr = nm_ip6_config_get_address (a, 0);
g_assert_cmpint (test_addr->source, ==, NM_PLATFORM_SOURCE_USER);
g_object_unref (a);
}
static void
test_add_route_with_source (void)
{
NMIP6Config *a;
NMPlatformIP6Route route;
const NMPlatformIP6Route *test_route;
a = nm_ip6_config_new ();
/* Test that a higher priority source is not overwritten */
route_new (&route, "abcd:1234:4321::", 24, "abcd:1234:4321:cdde::2");
route.source = NM_PLATFORM_SOURCE_USER;
nm_ip6_config_add_route (a, &route);
test_route = nm_ip6_config_get_route (a, 0);
g_assert_cmpint (test_route->source, ==, NM_PLATFORM_SOURCE_USER);
route.source = NM_PLATFORM_SOURCE_VPN;
nm_ip6_config_add_route (a, &route);
test_route = nm_ip6_config_get_route (a, 0);
g_assert_cmpint (test_route->source, ==, NM_PLATFORM_SOURCE_USER);
/* Test that a lower priority address source is overwritten */
nm_ip6_config_del_route (a, 0);
route.source = NM_PLATFORM_SOURCE_KERNEL;
nm_ip6_config_add_route (a, &route);
test_route = nm_ip6_config_get_route (a, 0);
g_assert_cmpint (test_route->source, ==, NM_PLATFORM_SOURCE_KERNEL);
route.source = NM_PLATFORM_SOURCE_USER;
nm_ip6_config_add_route (a, &route);
test_route = nm_ip6_config_get_route (a, 0);
g_assert_cmpint (test_route->source, ==, NM_PLATFORM_SOURCE_USER);
g_object_unref (a);
}
/*******************************************/
int
@@ -170,6 +283,9 @@ main (int argc, char **argv)
g_type_init ();
g_test_add_func ("/ip6-config/subtract", test_subtract);
g_test_add_func ("/ip6-config/compare-with-source", test_compare_with_source);
g_test_add_func ("/ip6-config/add-address-with-source", test_add_address_with_source);
g_test_add_func ("/ip6-config/add-route-with-source", test_add_route_with_source);
return g_test_run ();
}

View File

@@ -333,6 +333,7 @@ add_ip4_vpn_gateway_route (NMIP4Config *config, NMDevice *parent_device, guint32
if (nm_ip4_config_destination_is_direct (parent_config, vpn_gw, 32))
route.gateway = 0;
route.source = NM_PLATFORM_SOURCE_VPN;
nm_ip4_config_add_route (config, &route);
/* Ensure there's a route to the parent device's gateway through the
@@ -343,6 +344,7 @@ add_ip4_vpn_gateway_route (NMIP4Config *config, NMDevice *parent_device, guint32
memset (&route, 0, sizeof (route));
route.network = parent_gw;
route.plen = 32;
route.source = NM_PLATFORM_SOURCE_VPN;
nm_ip4_config_add_route (config, &route);
}
@@ -378,6 +380,7 @@ add_ip6_vpn_gateway_route (NMIP6Config *config,
if (nm_ip6_config_destination_is_direct (parent_config, vpn_gw, 128))
route.gateway = in6addr_any;
route.source = NM_PLATFORM_SOURCE_VPN;
nm_ip6_config_add_route (config, &route);
/* Ensure there's a route to the parent device's gateway through the
@@ -388,6 +391,7 @@ add_ip6_vpn_gateway_route (NMIP6Config *config,
memset (&route, 0, sizeof (route));
route.network = *parent_gw;
route.plen = 128;
route.source = NM_PLATFORM_SOURCE_VPN;
nm_ip6_config_add_route (config, &route);
}
@@ -944,6 +948,7 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy,
address.plen = g_value_get_uint (val);
if (address.address && address.plen) {
address.source = NM_PLATFORM_SOURCE_VPN;
nm_ip4_config_add_address (config, &address);
} else {
nm_log_err (LOGD_VPN, "invalid IP4 config received!");
@@ -1002,6 +1007,7 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy,
route.network = nm_ip4_route_get_dest (item);
route.plen = nm_ip4_route_get_prefix (item);
route.gateway = nm_ip4_route_get_next_hop (item);
route.source = NM_PLATFORM_SOURCE_VPN;
/* Ignore host routes to the VPN gateway since NM adds one itself
* below. Since NM knows more about the routing situation than
@@ -1094,9 +1100,10 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy,
if (val)
address.plen = g_value_get_uint (val);
if (!IN6_IS_ADDR_UNSPECIFIED (&address.address) && address.plen)
if (!IN6_IS_ADDR_UNSPECIFIED (&address.address) && address.plen) {
address.source = NM_PLATFORM_SOURCE_VPN;
nm_ip6_config_add_address (config, &address);
else {
} else {
nm_log_err (LOGD_VPN, "invalid IP6 config received!");
g_object_unref (config);
nm_vpn_connection_config_maybe_complete (connection, FALSE);
@@ -1145,6 +1152,7 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy,
route.network = *nm_ip6_route_get_dest (item);
route.plen = nm_ip6_route_get_prefix (item);
route.gateway = *nm_ip6_route_get_next_hop (item);
route.source = NM_PLATFORM_SOURCE_VPN;
/* Ignore host routes to the VPN gateway since NM adds one itself
* below. Since NM knows more about the routing situation than