691505aed9
and cherry-pick diverse other patches from upstream.
1823 lines
64 KiB
Diff
1823 lines
64 KiB
Diff
From 941e4d6dd31ae1d915878b1aac8a87183cb947a7 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Tue, 11 Feb 2014 13:08:23 +0100
|
|
Subject: [PATCH 01/15] platform: refactor link_get() not to use auto_nl_object
|
|
|
|
The previous implementation called nl_object_get() and nl_object_put()
|
|
each time in link_get(). As nl_object_get() and nl_object_put()
|
|
causes debug logging in libnl, this clutters the output.
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
(cherry picked from commit e02b1a86208df7c7f2ae1d79e65597f02d8f6d27)
|
|
---
|
|
src/platform/nm-linux-platform.c | 4 ++--
|
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
|
index 9fc264a..0ab311a 100644
|
|
--- a/src/platform/nm-linux-platform.c
|
|
+++ b/src/platform/nm-linux-platform.c
|
|
@@ -1487,7 +1487,7 @@ static struct rtnl_link *
|
|
link_get (NMPlatform *platform, int ifindex)
|
|
{
|
|
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
|
- auto_nl_object struct rtnl_link *rtnllink = rtnl_link_get (priv->link_cache, ifindex);
|
|
+ struct rtnl_link *rtnllink = rtnl_link_get (priv->link_cache, ifindex);
|
|
|
|
if (!rtnllink) {
|
|
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
|
@@ -1497,10 +1497,10 @@ link_get (NMPlatform *platform, int ifindex)
|
|
/* physical interfaces must be found by udev before they can be used */
|
|
if (!link_is_announceable (platform, rtnllink)) {
|
|
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
|
+ rtnl_link_put (rtnllink);
|
|
return NULL;
|
|
}
|
|
|
|
- nl_object_get ((struct nl_object *) rtnllink);
|
|
return rtnllink;
|
|
}
|
|
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 487371f7104c019489c7c71c8d6f0a0c5e145c8a Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Thu, 13 Feb 2014 14:42:26 +0100
|
|
Subject: [PATCH 02/15] platform: add debug logging when adding/deleting routes
|
|
|
|
Also, change the logging of nm_platform_ip._address_delete()
|
|
to log what we are about to do, *before* checking for existing
|
|
addresses.
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
(cherry picked from commit e54a3ccaf8a5a95c6bf9ca2da1a0ee98db0b6541)
|
|
---
|
|
src/platform/nm-platform.c | 34 ++++++++++++++++++++++++++++++++--
|
|
1 file changed, 32 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
|
index bc10d7c..8bdfaf4 100644
|
|
--- a/src/platform/nm-platform.c
|
|
+++ b/src/platform/nm-platform.c
|
|
@@ -1281,13 +1281,14 @@ nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen)
|
|
g_return_val_if_fail (plen > 0, FALSE);
|
|
g_return_val_if_fail (klass->ip4_address_delete, FALSE);
|
|
|
|
+ debug ("address: deleting IPv4 address %s/%d", nm_utils_inet4_ntop (address, NULL), plen);
|
|
+
|
|
if (!nm_platform_ip4_address_exists (ifindex, address, plen)) {
|
|
debug ("address doesn't exists");
|
|
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
|
return FALSE;
|
|
}
|
|
|
|
- debug ("address: deleting IPv4 address %s/%d", nm_utils_inet4_ntop (address, NULL), plen);
|
|
return klass->ip4_address_delete (platform, ifindex, address, plen);
|
|
}
|
|
|
|
@@ -1300,13 +1301,14 @@ nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen)
|
|
g_return_val_if_fail (plen > 0, FALSE);
|
|
g_return_val_if_fail (klass->ip6_address_delete, FALSE);
|
|
|
|
+ debug ("address: deleting IPv6 address %s/%d", nm_utils_inet6_ntop (&address, NULL), plen);
|
|
+
|
|
if (!nm_platform_ip6_address_exists (ifindex, address, plen)) {
|
|
debug ("address doesn't exists");
|
|
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
|
return FALSE;
|
|
}
|
|
|
|
- debug ("address: deleting IPv6 address %s/%d", nm_utils_inet6_ntop (&address, NULL), plen);
|
|
return klass->ip6_address_delete (platform, ifindex, address, plen);
|
|
}
|
|
|
|
@@ -1530,6 +1532,18 @@ nm_platform_ip4_route_add (int ifindex,
|
|
g_return_val_if_fail (mss >= 0, FALSE);
|
|
g_return_val_if_fail (klass->ip4_route_add, FALSE);
|
|
|
|
+ if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
|
|
+ NMPlatformIP4Route route = { 0 };
|
|
+
|
|
+ route.ifindex = ifindex;
|
|
+ route.network = network;
|
|
+ route.plen = plen;
|
|
+ route.gateway = gateway;
|
|
+ route.metric = metric;
|
|
+ route.mss = mss;
|
|
+
|
|
+ debug ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (&route));
|
|
+ }
|
|
return klass->ip4_route_add (platform, ifindex, network, plen, gateway, metric, mss);
|
|
}
|
|
|
|
@@ -1543,6 +1557,18 @@ nm_platform_ip6_route_add (int ifindex,
|
|
g_return_val_if_fail (mss >= 0, FALSE);
|
|
g_return_val_if_fail (klass->ip6_route_add, FALSE);
|
|
|
|
+ if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
|
|
+ NMPlatformIP6Route route = { 0 };
|
|
+
|
|
+ route.ifindex = ifindex;
|
|
+ route.network = network;
|
|
+ route.plen = plen;
|
|
+ route.gateway = gateway;
|
|
+ route.metric = metric;
|
|
+ route.mss = mss;
|
|
+
|
|
+ debug ("route: adding or updating IPv6 route: %s", nm_platform_ip6_route_to_string (&route));
|
|
+ }
|
|
return klass->ip6_route_add (platform, ifindex, network, plen, gateway, metric, mss);
|
|
}
|
|
|
|
@@ -1554,6 +1580,8 @@ nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, int metr
|
|
g_return_val_if_fail (platform, FALSE);
|
|
g_return_val_if_fail (klass->ip4_route_delete, FALSE);
|
|
|
|
+ debug ("route: deleting IPv4 route %s/%d, metric=%d", nm_utils_inet4_ntop (network, NULL), plen, metric);
|
|
+
|
|
if (!nm_platform_ip4_route_exists (ifindex, network, plen, metric)) {
|
|
debug ("route not found");
|
|
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
|
@@ -1572,6 +1600,8 @@ nm_platform_ip6_route_delete (int ifindex,
|
|
g_return_val_if_fail (platform, FALSE);
|
|
g_return_val_if_fail (klass->ip6_route_delete, FALSE);
|
|
|
|
+ debug ("route: deleting IPv6 route %s/%d, metric=%d", nm_utils_inet6_ntop (&network, NULL), plen, metric);
|
|
+
|
|
if (!nm_platform_ip6_route_exists (ifindex, network, plen, metric)) {
|
|
debug ("route not found");
|
|
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From f3856114c4bec9d14af401b85b50853c11cb1eeb Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Tue, 11 Feb 2014 22:10:05 +0100
|
|
Subject: [PATCH 03/15] platform: cleanup object_type_from_nl_object()
|
|
|
|
- change object_type_from_nl_object() to accept unknown object
|
|
types.
|
|
- replace g_assert_not_reached() with g_return_if_fail().
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
(cherry picked from commit dc54b2e3b2565b9af6478f98e004eaa478809e51)
|
|
---
|
|
src/platform/nm-linux-platform.c | 49 +++++++++++++++++++++++++---------------
|
|
1 file changed, 31 insertions(+), 18 deletions(-)
|
|
|
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
|
index 0ab311a..58a0f72 100644
|
|
--- a/src/platform/nm-linux-platform.c
|
|
+++ b/src/platform/nm-linux-platform.c
|
|
@@ -141,12 +141,13 @@ nm_rtnl_addr_set_prefixlen (struct rtnl_addr *rtnladdr, int plen)
|
|
#define rtnl_addr_set_prefixlen nm_rtnl_addr_set_prefixlen
|
|
|
|
typedef enum {
|
|
+ UNKNOWN_OBJECT_TYPE,
|
|
LINK,
|
|
IP4_ADDRESS,
|
|
IP6_ADDRESS,
|
|
IP4_ROUTE,
|
|
IP6_ROUTE,
|
|
- N_TYPES
|
|
+ N_TYPES,
|
|
} ObjectType;
|
|
|
|
typedef enum {
|
|
@@ -159,9 +160,10 @@ typedef enum {
|
|
static ObjectType
|
|
object_type_from_nl_object (const struct nl_object *object)
|
|
{
|
|
- const char *type_str = nl_object_get_type (object);
|
|
+ const char *type_str;
|
|
|
|
- g_assert (object);
|
|
+ if (!object || !(type_str = nl_object_get_type (object)))
|
|
+ return UNKNOWN_OBJECT_TYPE;
|
|
|
|
if (!strcmp (type_str, "route/link"))
|
|
return LINK;
|
|
@@ -172,7 +174,7 @@ object_type_from_nl_object (const struct nl_object *object)
|
|
case AF_INET6:
|
|
return IP6_ADDRESS;
|
|
default:
|
|
- g_assert_not_reached ();
|
|
+ return UNKNOWN_OBJECT_TYPE;
|
|
}
|
|
} else if (!strcmp (type_str, "route/route")) {
|
|
switch (rtnl_route_get_family ((struct rtnl_route *) object)) {
|
|
@@ -181,10 +183,10 @@ object_type_from_nl_object (const struct nl_object *object)
|
|
case AF_INET6:
|
|
return IP6_ROUTE;
|
|
default:
|
|
- g_assert_not_reached ();
|
|
+ return UNKNOWN_OBJECT_TYPE;
|
|
}
|
|
} else
|
|
- g_assert_not_reached ();
|
|
+ return UNKNOWN_OBJECT_TYPE;
|
|
}
|
|
|
|
/* libnl inclues LINK_ATTR_FAMILY in oo_id_attrs of link_obj_ops and thus
|
|
@@ -231,7 +233,10 @@ get_kernel_object (struct nl_sock *sock, struct nl_object *needle)
|
|
return NULL;
|
|
}
|
|
}
|
|
- default:
|
|
+ case IP4_ADDRESS:
|
|
+ case IP6_ADDRESS:
|
|
+ case IP4_ROUTE:
|
|
+ case IP6_ROUTE:
|
|
/* Fallback to a one-time cache allocation. */
|
|
{
|
|
struct nl_cache *cache;
|
|
@@ -247,6 +252,9 @@ get_kernel_object (struct nl_sock *sock, struct nl_object *needle)
|
|
nl_cache_free (cache);
|
|
return object;
|
|
}
|
|
+ default:
|
|
+ g_return_val_if_reached (NULL);
|
|
+ return NULL;
|
|
}
|
|
}
|
|
|
|
@@ -264,7 +272,8 @@ add_kernel_object (struct nl_sock *sock, struct nl_object *object)
|
|
case IP6_ROUTE:
|
|
return rtnl_route_add (sock, (struct rtnl_route *) object, NLM_F_CREATE | NLM_F_REPLACE);
|
|
default:
|
|
- g_assert_not_reached ();
|
|
+ g_return_val_if_reached (-NLE_INVAL);
|
|
+ return -NLE_INVAL;
|
|
}
|
|
}
|
|
|
|
@@ -282,7 +291,8 @@ delete_kernel_object (struct nl_sock *sock, struct nl_object *object)
|
|
case IP6_ROUTE:
|
|
return rtnl_route_delete (sock, (struct rtnl_route *) object, 0);
|
|
default:
|
|
- g_assert_not_reached ();
|
|
+ g_return_val_if_reached (-NLE_INVAL);
|
|
+ return -NLE_INVAL;
|
|
}
|
|
}
|
|
|
|
@@ -931,11 +941,11 @@ init_ip6_route (NMPlatformIP6Route *route, struct rtnl_route *rtnlroute)
|
|
/* Object and cache manipulation */
|
|
|
|
static const char *signal_by_type_and_status[N_TYPES][N_STATUSES] = {
|
|
- { NM_PLATFORM_LINK_ADDED, NM_PLATFORM_LINK_CHANGED, NM_PLATFORM_LINK_REMOVED },
|
|
- { NM_PLATFORM_IP4_ADDRESS_ADDED, NM_PLATFORM_IP4_ADDRESS_CHANGED, NM_PLATFORM_IP4_ADDRESS_REMOVED },
|
|
- { NM_PLATFORM_IP6_ADDRESS_ADDED, NM_PLATFORM_IP6_ADDRESS_CHANGED, NM_PLATFORM_IP6_ADDRESS_REMOVED },
|
|
- { NM_PLATFORM_IP4_ROUTE_ADDED, NM_PLATFORM_IP4_ROUTE_CHANGED, NM_PLATFORM_IP4_ROUTE_REMOVED },
|
|
- { NM_PLATFORM_IP6_ROUTE_ADDED, NM_PLATFORM_IP6_ROUTE_CHANGED, NM_PLATFORM_IP6_ROUTE_REMOVED }
|
|
+ [LINK] = { NM_PLATFORM_LINK_ADDED, NM_PLATFORM_LINK_CHANGED, NM_PLATFORM_LINK_REMOVED },
|
|
+ [IP4_ADDRESS] = { NM_PLATFORM_IP4_ADDRESS_ADDED, NM_PLATFORM_IP4_ADDRESS_CHANGED, NM_PLATFORM_IP4_ADDRESS_REMOVED },
|
|
+ [IP6_ADDRESS] = { NM_PLATFORM_IP6_ADDRESS_ADDED, NM_PLATFORM_IP6_ADDRESS_CHANGED, NM_PLATFORM_IP6_ADDRESS_REMOVED },
|
|
+ [IP4_ROUTE] = { NM_PLATFORM_IP4_ROUTE_ADDED, NM_PLATFORM_IP4_ROUTE_CHANGED, NM_PLATFORM_IP4_ROUTE_REMOVED },
|
|
+ [IP6_ROUTE] = { NM_PLATFORM_IP6_ROUTE_ADDED, NM_PLATFORM_IP6_ROUTE_CHANGED, NM_PLATFORM_IP6_ROUTE_REMOVED }
|
|
};
|
|
|
|
static struct nl_cache *
|
|
@@ -953,7 +963,8 @@ choose_cache (NMPlatform *platform, struct nl_object *object)
|
|
case IP6_ROUTE:
|
|
return priv->route_cache;
|
|
default:
|
|
- g_assert_not_reached ();
|
|
+ g_return_val_if_reached (NULL);
|
|
+ return NULL;
|
|
}
|
|
}
|
|
|
|
@@ -1095,7 +1106,7 @@ announce_object (NMPlatform *platform, const struct nl_object *object, ObjectSta
|
|
}
|
|
return;
|
|
default:
|
|
- error ("Announcing object: object type unknown: %d", object_type);
|
|
+ g_return_if_reached ();
|
|
}
|
|
}
|
|
|
|
@@ -1951,7 +1962,8 @@ master_category (NMPlatform *platform, int master)
|
|
case NM_LINK_TYPE_BOND:
|
|
return "bonding";
|
|
default:
|
|
- g_assert_not_reached ();
|
|
+ g_return_val_if_reached (NULL);
|
|
+ return NULL;
|
|
}
|
|
}
|
|
|
|
@@ -1969,7 +1981,8 @@ slave_category (NMPlatform *platform, int slave)
|
|
case NM_LINK_TYPE_BRIDGE:
|
|
return "brport";
|
|
default:
|
|
- g_assert_not_reached ();
|
|
+ g_return_val_if_reached (NULL);
|
|
+ return NULL;
|
|
}
|
|
}
|
|
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 2cb128ebad2ff78002a7c822bc3c07a7797ca188 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Thu, 13 Feb 2014 16:08:36 +0100
|
|
Subject: [PATCH 04/15] platform: add function choose_cache_by_type()
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
(cherry picked from commit a5f3fcae295b2bc9e39cf37b95c7e87a45eec76a)
|
|
---
|
|
src/platform/nm-linux-platform.c | 10 ++++++++--
|
|
1 file changed, 8 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
|
index 58a0f72..db026f4 100644
|
|
--- a/src/platform/nm-linux-platform.c
|
|
+++ b/src/platform/nm-linux-platform.c
|
|
@@ -949,11 +949,11 @@ static const char *signal_by_type_and_status[N_TYPES][N_STATUSES] = {
|
|
};
|
|
|
|
static struct nl_cache *
|
|
-choose_cache (NMPlatform *platform, struct nl_object *object)
|
|
+choose_cache_by_type (NMPlatform *platform, ObjectType object_type)
|
|
{
|
|
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
|
|
|
- switch (object_type_from_nl_object (object)) {
|
|
+ switch (object_type) {
|
|
case LINK:
|
|
return priv->link_cache;
|
|
case IP4_ADDRESS:
|
|
@@ -968,6 +968,12 @@ choose_cache (NMPlatform *platform, struct nl_object *object)
|
|
}
|
|
}
|
|
|
|
+static struct nl_cache *
|
|
+choose_cache (NMPlatform *platform, struct nl_object *object)
|
|
+{
|
|
+ return choose_cache_by_type (platform, object_type_from_nl_object (object));
|
|
+}
|
|
+
|
|
static gboolean
|
|
object_has_ifindex (struct nl_object *object, int ifindex)
|
|
{
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 3f3bf82c93ba7741af785971628780d9ab42fd6b Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Tue, 11 Feb 2014 20:16:03 +0100
|
|
Subject: [PATCH 05/15] platform: fix caching for link types
|
|
|
|
This bug was present since a long time, however libnl3-v3.2.23
|
|
(commit fdd1ba220dd7b780400e9d0652cde80e59f63572) changed the returned
|
|
family of bridge link objects, which breaks NetworkManager.
|
|
|
|
This resulted in error messages such as:
|
|
|
|
DBG<4> object.c:207 nl_object_get: New reference to object 0x19c34b0, total 2
|
|
DBG<5> route/link.c:895 link_keygen: link 0x19c34b0 key (dev 9 fam 7) keysz 8, hash 0x2b2
|
|
DBG<2> hashtable.c:127 nl_hash_table_add: Warning: Add to hashtable found duplicate...
|
|
DBG<4> object.c:221 nl_object_put: Returned object reference 0x19c34b0, 1 remaining
|
|
NetworkManager[17745]: <error> [1392114373.475432] [platform/nm-linux-platform.c:1328] event_notification(): netlink cache error: Object exists
|
|
|
|
Even before the change of libnl, I saw the following error lines
|
|
<debug> [...] [platform/nm-linux-platform.c:1216] event_notification(): netlink event (type 16) for link: virbr0 (4)
|
|
<error> [...] [platform/nm-linux-platform.c:1265] event_notification(): netlink cache error: Object exists
|
|
Hence, the caching mechanism for libnl objects already had a bug.
|
|
|
|
For rtnl link objects, the identifier consists of family and ifindex.
|
|
Since in upper layers, we don't easily know the family, we need a way to find
|
|
the objects inside the cache. We do this, by only caching links of family
|
|
AF_UNSPEC.
|
|
|
|
Objects that we receive via event_notification() are never cached. They are only used
|
|
to trigger refetching the kernel_object. Their family is irrelevant, we
|
|
only need to know, that something about this ifindex changed.
|
|
|
|
For objects retrieved via get_kernel_object(), we only get link objects of
|
|
family AF_UNSPEC or AF_BRIDGE. In any case, we reset (coerce) their family
|
|
before caching. This way, inside the link cache, there are only objects with
|
|
(coerced) family AF_UNSPEC. We loose the information, which family the
|
|
link had, however we don't need it anyway.
|
|
|
|
https://bugzilla.gnome.org/show_bug.cgi?id=719905
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=1063290
|
|
|
|
Duplicates:
|
|
https://bugzilla.gnome.org/show_bug.cgi?id=724225
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=1063800
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
(cherry picked from commit a6f92665555c39dd609db42b4c350b1691149d17)
|
|
---
|
|
src/platform/nm-linux-platform.c | 52 ++++++++++++++++++++++++++++------------
|
|
1 file changed, 37 insertions(+), 15 deletions(-)
|
|
|
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
|
index db026f4..3a15169 100644
|
|
--- a/src/platform/nm-linux-platform.c
|
|
+++ b/src/platform/nm-linux-platform.c
|
|
@@ -189,26 +189,47 @@ object_type_from_nl_object (const struct nl_object *object)
|
|
return UNKNOWN_OBJECT_TYPE;
|
|
}
|
|
|
|
-/* libnl inclues LINK_ATTR_FAMILY in oo_id_attrs of link_obj_ops and thus
|
|
- * refuses to search for items that lack this attribute. I believe this is a
|
|
- * bug or a bad design at the least. Address family is not an identifying
|
|
- * attribute of a network interface and IMO is not an attribute of a network
|
|
- * interface at all.
|
|
- */
|
|
+static void
|
|
+_nl_link_family_unset (struct nl_object *obj, int *family)
|
|
+{
|
|
+ if (!obj || object_type_from_nl_object (obj) != LINK)
|
|
+ *family = AF_UNSPEC;
|
|
+ else {
|
|
+ *family = rtnl_link_get_family ((struct rtnl_link *) obj);
|
|
+
|
|
+ /* Always explicitly set the family to AF_UNSPEC, even if rtnl_link_get_family() might
|
|
+ * already return %AF_UNSPEC. The reason is, that %AF_UNSPEC is the default family
|
|
+ * and libnl nl_object_identical() function will only succeed, if the family is
|
|
+ * explicitly set (which we cannot be sure, unless setting it). */
|
|
+ rtnl_link_set_family ((struct rtnl_link *) obj, AF_UNSPEC);
|
|
+ }
|
|
+}
|
|
+
|
|
+/* In our link cache, we coerce the family of all link objects to AF_UNSPEC.
|
|
+ * Thus, before searching for an object, we fixup @needle to have the right
|
|
+ * id (by resetting the family). */
|
|
static struct nl_object *
|
|
nm_nl_cache_search (struct nl_cache *cache, struct nl_object *needle)
|
|
{
|
|
- if (object_type_from_nl_object (needle) == LINK)
|
|
- rtnl_link_set_family ((struct rtnl_link *) needle, AF_UNSPEC);
|
|
+ int family;
|
|
+ struct nl_object *obj;
|
|
+
|
|
+ _nl_link_family_unset (needle, &family);
|
|
+ obj = nl_cache_search (cache, needle);
|
|
+ if (family != AF_UNSPEC) {
|
|
+ /* restore the family of the @needle instance. If the family was
|
|
+ * unset before, we cannot make it unset again. Thus, in that case
|
|
+ * we cannot undo _nl_link_family_unset() entirely. */
|
|
+ rtnl_link_set_family ((struct rtnl_link *) needle, family);
|
|
+ }
|
|
|
|
- return nl_cache_search (cache, needle);
|
|
+ return obj;
|
|
}
|
|
-#define nl_cache_search nm_nl_cache_search
|
|
|
|
/* Ask the kernel for an object identical (as in nl_cache_identical) to the
|
|
* needle argument. This is a kernel counterpart for nl_cache_search.
|
|
*
|
|
- * libnl 3.2 doesn't seem to provide such functionality.
|
|
+ * The returned object must be freed by the caller with nl_object_put().
|
|
*/
|
|
static struct nl_object *
|
|
get_kernel_object (struct nl_sock *sock, struct nl_object *needle)
|
|
@@ -225,6 +246,7 @@ get_kernel_object (struct nl_sock *sock, struct nl_object *needle)
|
|
nle = rtnl_link_get_kernel (sock, ifindex, name, (struct rtnl_link **) &kernel_object);
|
|
switch (nle) {
|
|
case -NLE_SUCCESS:
|
|
+ _nl_link_family_unset (kernel_object, &nle);
|
|
return kernel_object;
|
|
case -NLE_NODEV:
|
|
return NULL;
|
|
@@ -1128,7 +1150,7 @@ refresh_object (NMPlatform *platform, struct nl_object *object, gboolean removed
|
|
int nle;
|
|
|
|
cache = choose_cache (platform, object);
|
|
- cached_object = nl_cache_search (choose_cache (platform, object), object);
|
|
+ cached_object = nm_nl_cache_search (cache, object);
|
|
kernel_object = get_kernel_object (priv->nlh, object);
|
|
|
|
if (removed) {
|
|
@@ -1223,7 +1245,7 @@ delete_object (NMPlatform *platform, struct nl_object *obj)
|
|
* for delete_kernel_object() and we need to search the cache first. If
|
|
* that problem is fixed, we can use 'object' directly.
|
|
*/
|
|
- cached_object = nl_cache_search (choose_cache (platform, object), object);
|
|
+ cached_object = nm_nl_cache_search (choose_cache (platform, object), object);
|
|
g_return_val_if_fail (cached_object, FALSE);
|
|
|
|
nle = delete_kernel_object (priv->nlh, cached_object);
|
|
@@ -1285,7 +1307,7 @@ event_notification (struct nl_msg *msg, gpointer user_data)
|
|
g_return_val_if_fail (object, NL_OK);
|
|
|
|
cache = choose_cache (platform, object);
|
|
- cached_object = nl_cache_search (cache, object);
|
|
+ cached_object = nm_nl_cache_search (cache, object);
|
|
kernel_object = get_kernel_object (priv->nlh, object);
|
|
|
|
/* Just for debugging */
|
|
@@ -1321,7 +1343,7 @@ event_notification (struct nl_msg *msg, gpointer user_data)
|
|
* already removed and announced.
|
|
*/
|
|
if (event == RTM_DELLINK) {
|
|
- if (!link_is_announceable (platform, (struct rtnl_link *) object))
|
|
+ if (!link_is_announceable (platform, (struct rtnl_link *) cached_object))
|
|
return NL_OK;
|
|
}
|
|
announce_object (platform, cached_object, REMOVED, NM_PLATFORM_REASON_EXTERNAL);
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 127ba70a6e7f50e94752e32eecb8e45fababb4a3 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Tue, 11 Feb 2014 20:12:12 +0100
|
|
Subject: [PATCH 06/15] platform: log the link family in event_notification()
|
|
and get_kernel_object()
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
(cherry picked from commit ebbd6575ffc78f500062303fe18ecb908b2e29ea)
|
|
---
|
|
src/platform/nm-linux-platform.c | 58 ++++++++++++++++++++++++++++------------
|
|
1 file changed, 41 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
|
index 3a15169..1667ba5 100644
|
|
--- a/src/platform/nm-linux-platform.c
|
|
+++ b/src/platform/nm-linux-platform.c
|
|
@@ -234,24 +234,36 @@ nm_nl_cache_search (struct nl_cache *cache, struct nl_object *needle)
|
|
static struct nl_object *
|
|
get_kernel_object (struct nl_sock *sock, struct nl_object *needle)
|
|
{
|
|
+ struct nl_object *object = NULL;
|
|
+ ObjectType type = object_type_from_nl_object (needle);
|
|
|
|
- switch (object_type_from_nl_object (needle)) {
|
|
+ switch (type) {
|
|
case LINK:
|
|
{
|
|
- struct nl_object *kernel_object;
|
|
int ifindex = rtnl_link_get_ifindex ((struct rtnl_link *) needle);
|
|
const char *name = rtnl_link_get_name ((struct rtnl_link *) needle);
|
|
int nle;
|
|
|
|
- nle = rtnl_link_get_kernel (sock, ifindex, name, (struct rtnl_link **) &kernel_object);
|
|
+ nle = rtnl_link_get_kernel (sock, ifindex, name, (struct rtnl_link **) &object);
|
|
switch (nle) {
|
|
case -NLE_SUCCESS:
|
|
- _nl_link_family_unset (kernel_object, &nle);
|
|
- return kernel_object;
|
|
+ if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
|
|
+ name = rtnl_link_get_name ((struct rtnl_link *) object);
|
|
+ debug ("get_kernel_object for link: %s (%d, family %d)",
|
|
+ name ? name : "(unknown)",
|
|
+ rtnl_link_get_ifindex ((struct rtnl_link *) object),
|
|
+ rtnl_link_get_family ((struct rtnl_link *) object));
|
|
+ }
|
|
+
|
|
+ _nl_link_family_unset (object, &nle);
|
|
+ return object;
|
|
case -NLE_NODEV:
|
|
+ debug ("get_kernel_object for link %s (%d) had no result",
|
|
+ name ? name : "(unknown)", ifindex);
|
|
return NULL;
|
|
default:
|
|
- error ("Netlink error: %s", nl_geterror (nle));
|
|
+ error ("get_kernel_object for link %s (%d) failed: %s (%d)",
|
|
+ name ? name : "(unknown)", ifindex, nl_geterror (nle), nle);
|
|
return NULL;
|
|
}
|
|
}
|
|
@@ -262,16 +274,25 @@ get_kernel_object (struct nl_sock *sock, struct nl_object *needle)
|
|
/* Fallback to a one-time cache allocation. */
|
|
{
|
|
struct nl_cache *cache;
|
|
- struct nl_object *object;
|
|
int nle;
|
|
|
|
nle = nl_cache_alloc_and_fill (
|
|
nl_cache_ops_lookup (nl_object_get_type (needle)),
|
|
sock, &cache);
|
|
- g_return_val_if_fail (!nle, NULL);
|
|
+ if (nle) {
|
|
+ error ("get_kernel_object for type %d failed: %s (%d)",
|
|
+ type, nl_geterror (nle), nle);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
object = nl_cache_search (cache, needle);
|
|
|
|
nl_cache_free (cache);
|
|
+
|
|
+ if (object)
|
|
+ debug ("get_kernel_object for type %d returned %p", type, object);
|
|
+ else
|
|
+ debug ("get_kernel_object for type %d had no result", type);
|
|
return object;
|
|
}
|
|
default:
|
|
@@ -1306,19 +1327,22 @@ event_notification (struct nl_msg *msg, gpointer user_data)
|
|
nl_msg_parse (msg, ref_object, &object);
|
|
g_return_val_if_fail (object, NL_OK);
|
|
|
|
+ if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
|
|
+ if (object_type_from_nl_object (object) == LINK) {
|
|
+ const char *name = rtnl_link_get_name ((struct rtnl_link *) object);
|
|
+
|
|
+ debug ("netlink event (type %d) for link: %s (%d, family %d)",
|
|
+ event, name ? name : "(unknown)",
|
|
+ rtnl_link_get_ifindex ((struct rtnl_link *) object),
|
|
+ rtnl_link_get_family ((struct rtnl_link *) object));
|
|
+ } else
|
|
+ debug ("netlink event (type %d)", event);
|
|
+ }
|
|
+
|
|
cache = choose_cache (platform, object);
|
|
cached_object = nm_nl_cache_search (cache, object);
|
|
kernel_object = get_kernel_object (priv->nlh, object);
|
|
|
|
- /* Just for debugging */
|
|
- if (object_type_from_nl_object (object) == LINK) {
|
|
- int ifindex = rtnl_link_get_ifindex ((struct rtnl_link *) object);
|
|
- const char *name = rtnl_link_get_name ((struct rtnl_link *) object);
|
|
- debug ("netlink event (type %d) for link: %s (%d)",
|
|
- event, name ? name : "(unknown)", ifindex);
|
|
- } else
|
|
- debug ("netlink event (type %d)", event);
|
|
-
|
|
hack_empty_master_iff_lower_up (platform, kernel_object);
|
|
|
|
/* Removed object */
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From f36f0e24686f0c40aace88a50ba996ef2d6440af Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Thu, 13 Feb 2014 18:12:41 +0100
|
|
Subject: [PATCH 07/15] core: add function
|
|
nm_utils_ip6_address_clear_host_address()
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
(cherry picked from commit e8775dd9fc7b4867b2a541a163d14c630bf1085b)
|
|
---
|
|
src/NetworkManagerUtils.c | 44 +++++++++++++++++++++++++++++
|
|
src/NetworkManagerUtils.h | 3 ++
|
|
src/rdisc/nm-lndp-rdisc.c | 27 ++----------------
|
|
src/tests/test-general.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
4 files changed, 120 insertions(+), 25 deletions(-)
|
|
|
|
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
|
|
index 8d646d3..1ab5eee 100644
|
|
--- a/src/NetworkManagerUtils.c
|
|
+++ b/src/NetworkManagerUtils.c
|
|
@@ -75,6 +75,50 @@ nm_ethernet_address_is_valid (const struct ether_addr *test_addr)
|
|
}
|
|
|
|
|
|
+/* nm_utils_ip4_address_clear_host_address:
|
|
+ * @addr: source ip6 address
|
|
+ * @plen: prefix length of network
|
|
+ *
|
|
+ * returns: the input address, with the host address set to 0.
|
|
+ */
|
|
+in_addr_t
|
|
+nm_utils_ip4_address_clear_host_address (in_addr_t addr, guint8 plen)
|
|
+{
|
|
+ return addr & nm_utils_ip4_prefix_to_netmask (plen);
|
|
+}
|
|
+
|
|
+ /* nm_utils_ip6_address_clear_host_address:
|
|
+ * @dst: destination output buffer, will contain the network part of the @src address
|
|
+ * @src: source ip6 address
|
|
+ * @plen: prefix length of network
|
|
+ *
|
|
+ * Note: this function is self assignment save, to update @src inplace, set both
|
|
+ * @dst and @src to the same destination.
|
|
+ */
|
|
+void
|
|
+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);
|
|
+
|
|
+ if (plen < 128) {
|
|
+ guint nbytes = plen / 8;
|
|
+ guint nbits = plen % 8;
|
|
+
|
|
+ if (nbytes && dst != src)
|
|
+ memcpy (dst, src, nbytes);
|
|
+ if (nbits) {
|
|
+ dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits)));
|
|
+ nbytes++;
|
|
+ }
|
|
+ if (nbytes <= 15)
|
|
+ memset (&dst->s6_addr[nbytes], 0, 16 - nbytes);
|
|
+ } else if (src != dst)
|
|
+ *dst = *src;
|
|
+}
|
|
+
|
|
+
|
|
int
|
|
nm_spawn_process (const char *args)
|
|
{
|
|
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
|
|
index cae7944..8558bf5 100644
|
|
--- a/src/NetworkManagerUtils.h
|
|
+++ b/src/NetworkManagerUtils.h
|
|
@@ -35,6 +35,9 @@
|
|
|
|
gboolean nm_ethernet_address_is_valid (const struct ether_addr *test_addr);
|
|
|
|
+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);
|
|
+
|
|
int nm_spawn_process (const char *args);
|
|
|
|
gboolean nm_match_spec_string (const GSList *specs, const char *string);
|
|
diff --git a/src/rdisc/nm-lndp-rdisc.c b/src/rdisc/nm-lndp-rdisc.c
|
|
index 5fb2877..3b0b036 100644
|
|
--- a/src/rdisc/nm-lndp-rdisc.c
|
|
+++ b/src/rdisc/nm-lndp-rdisc.c
|
|
@@ -428,29 +428,6 @@ fill_address_from_mac (struct in6_addr *address, const char *mac)
|
|
memcpy (identifier + 5, mac + 3, 3);
|
|
}
|
|
|
|
-/* Ensure the given address is masked with its prefix and that all host
|
|
- * bits are set to zero. Some IPv6 router advertisement daemons (eg, radvd)
|
|
- * don't enforce this in their configuration.
|
|
- */
|
|
-static void
|
|
-set_address_masked (struct in6_addr *dst, struct in6_addr *src, guint8 plen)
|
|
-{
|
|
- guint nbytes = plen / 8;
|
|
- guint nbits = plen % 8;
|
|
-
|
|
- g_return_if_fail (plen <= 128);
|
|
- g_assert (src);
|
|
- g_assert (dst);
|
|
-
|
|
- if (plen >= 128)
|
|
- *dst = *src;
|
|
- else {
|
|
- memset (dst, 0, sizeof (*dst));
|
|
- memcpy (dst, src, nbytes);
|
|
- dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits)));
|
|
- }
|
|
-}
|
|
-
|
|
static int
|
|
receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|
{
|
|
@@ -529,7 +506,7 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|
/* Device route */
|
|
memset (&route, 0, sizeof (route));
|
|
route.plen = ndp_msg_opt_prefix_len (msg, offset);
|
|
- set_address_masked (&route.network, ndp_msg_opt_prefix (msg, offset), route.plen);
|
|
+ nm_utils_ip6_address_clear_host_address (&route.network, ndp_msg_opt_prefix (msg, offset), route.plen);
|
|
route.timestamp = now;
|
|
if (ndp_msg_opt_prefix_flag_on_link (msg, offset)) {
|
|
route.lifetime = ndp_msg_opt_prefix_valid_time (msg, offset);
|
|
@@ -560,7 +537,7 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|
memset (&route, 0, sizeof (route));
|
|
route.gateway = gateway.address;
|
|
route.plen = ndp_msg_opt_route_prefix_len (msg, offset);
|
|
- set_address_masked (&route.network, ndp_msg_opt_route_prefix (msg, offset), route.plen);
|
|
+ nm_utils_ip6_address_clear_host_address (&route.network, ndp_msg_opt_route_prefix (msg, offset), route.plen);
|
|
route.timestamp = now;
|
|
route.lifetime = ndp_msg_opt_route_lifetime (msg, offset);
|
|
route.preference = translate_preference (ndp_msg_opt_route_preference (msg, offset));
|
|
diff --git a/src/tests/test-general.c b/src/tests/test-general.c
|
|
index 649653c..3fd7115 100644
|
|
--- a/src/tests/test-general.c
|
|
+++ b/src/tests/test-general.c
|
|
@@ -60,6 +60,76 @@ test_nm_utils_ascii_str_to_int64 (void)
|
|
test_nm_utils_ascii_str_to_int64_do ("\r\n\t10000\t\n\t\n", 10, 0, 10000, -1, 0, 10000);
|
|
}
|
|
|
|
+/* Reference implementation for nm_utils_ip6_address_clear_host_address.
|
|
+ * Taken originally from set_address_masked(), src/rdisc/nm-lndp-rdisc.c
|
|
+ **/
|
|
+static void
|
|
+ip6_address_clear_host_address_reference (struct in6_addr *dst, struct in6_addr *src, guint8 plen)
|
|
+{
|
|
+ guint nbytes = plen / 8;
|
|
+ guint nbits = plen % 8;
|
|
+
|
|
+ g_return_if_fail (plen <= 128);
|
|
+ g_assert (src);
|
|
+ g_assert (dst);
|
|
+
|
|
+ if (plen >= 128)
|
|
+ *dst = *src;
|
|
+ else {
|
|
+ memset (dst, 0, sizeof (*dst));
|
|
+ memcpy (dst, src, nbytes);
|
|
+ dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits)));
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+_randomize_in6_addr (struct in6_addr *addr, GRand *rand)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i=0; i < 4; i++)
|
|
+ ((guint32 *)addr)[i] = g_rand_int (rand);
|
|
+}
|
|
+
|
|
+static void
|
|
+test_nm_utils_ip6_address_clear_host_address (void)
|
|
+{
|
|
+ GRand *rand = g_rand_new ();
|
|
+ int plen, i;
|
|
+
|
|
+ g_rand_set_seed (rand, 0);
|
|
+
|
|
+ for (plen = 0; plen <= 128; plen++) {
|
|
+ for (i =0; i<50; i++) {
|
|
+ struct in6_addr addr_src, addr_ref;
|
|
+ struct in6_addr addr1, addr2;
|
|
+
|
|
+ _randomize_in6_addr (&addr_src, rand);
|
|
+ _randomize_in6_addr (&addr_ref, rand);
|
|
+ _randomize_in6_addr (&addr1, rand);
|
|
+ _randomize_in6_addr (&addr2, rand);
|
|
+
|
|
+ addr1 = addr_src;
|
|
+ ip6_address_clear_host_address_reference (&addr_ref, &addr1, plen);
|
|
+
|
|
+ _randomize_in6_addr (&addr1, rand);
|
|
+ _randomize_in6_addr (&addr2, rand);
|
|
+ addr1 = addr_src;
|
|
+ nm_utils_ip6_address_clear_host_address (&addr2, &addr1, plen);
|
|
+ g_assert_cmpint (memcmp (&addr1, &addr_src, sizeof (struct in6_addr)), ==, 0);
|
|
+ g_assert_cmpint (memcmp (&addr2, &addr_ref, sizeof (struct in6_addr)), ==, 0);
|
|
+
|
|
+ /* test for self assignment/inplace update. */
|
|
+ _randomize_in6_addr (&addr1, rand);
|
|
+ addr1 = addr_src;
|
|
+ nm_utils_ip6_address_clear_host_address (&addr1, &addr1, plen);
|
|
+ g_assert_cmpint (memcmp (&addr1, &addr_ref, sizeof (struct in6_addr)), ==, 0);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ g_rand_free (rand);
|
|
+}
|
|
+
|
|
/*******************************************/
|
|
|
|
int
|
|
@@ -70,6 +140,7 @@ main (int argc, char **argv)
|
|
g_type_init ();
|
|
|
|
g_test_add_func ("/general/nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
|
|
+ g_test_add_func ("/general/nm_utils_ip6_address_clear_host_address", test_nm_utils_ip6_address_clear_host_address);
|
|
|
|
return g_test_run ();
|
|
}
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 6ca079e27897c4ac5d6dbb31a872d9ef0c7b5bf6 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Thu, 13 Feb 2014 19:47:04 +0100
|
|
Subject: [PATCH 08/15] platform: clear host identifier before adding a route
|
|
|
|
Adding IPv4 routes, with a non-zero host identifer fails with an
|
|
error message. Adding IPv6 addresses, does not return an error,
|
|
but it seems to have no effect.
|
|
|
|
Thus we have to make sure that the host part of routes
|
|
is always zero.
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
(cherry picked from commit d6add4de5c5ae934a355bb72a14ab4d5d4b2472f)
|
|
---
|
|
src/platform/nm-linux-platform.c | 30 ++++++++++++++++++++++++++++--
|
|
1 file changed, 28 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
|
index 1667ba5..802a47b 100644
|
|
--- a/src/platform/nm-linux-platform.c
|
|
+++ b/src/platform/nm-linux-platform.c
|
|
@@ -2582,16 +2582,42 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
|
|
return routes;
|
|
}
|
|
|
|
+static void
|
|
+clear_host_address (int family, const void *network, int plen, void *dst)
|
|
+{
|
|
+ g_return_if_fail (plen == (guint8)plen);
|
|
+ g_return_if_fail (network);
|
|
+
|
|
+ switch (family) {
|
|
+ case AF_INET:
|
|
+ *((in_addr_t *) dst) = nm_utils_ip4_address_clear_host_address (*((in_addr_t *) network), plen);
|
|
+ break;
|
|
+ case AF_INET6:
|
|
+ nm_utils_ip6_address_clear_host_address ((struct in6_addr *) dst, (const struct in6_addr *) network, plen);
|
|
+ break;
|
|
+ default:
|
|
+ g_assert_not_reached ();
|
|
+ }
|
|
+}
|
|
+
|
|
static struct nl_object *
|
|
build_rtnl_route (int family, int ifindex, gconstpointer network, int plen, gconstpointer gateway, int metric, int mss)
|
|
{
|
|
+ guint32 network_clean[4];
|
|
struct rtnl_route *rtnlroute = rtnl_route_alloc ();
|
|
struct rtnl_nexthop *nexthop = rtnl_route_nh_alloc ();
|
|
int addrlen = (family == AF_INET) ? sizeof (in_addr_t) : sizeof (struct in6_addr);
|
|
/* Workaround a libnl bug by using zero destination address length for default routes */
|
|
- auto_nl_addr struct nl_addr *dst = nl_addr_build (family, network, plen ? addrlen : 0);
|
|
+ auto_nl_addr struct nl_addr *dst = NULL;
|
|
auto_nl_addr struct nl_addr *gw = gateway ? nl_addr_build (family, gateway, addrlen) : NULL;
|
|
|
|
+ /* There seem to be problems adding a route with non-zero host identifier.
|
|
+ * Adding IPv6 routes is simply ignored, without error message.
|
|
+ * In the IPv4 case, we got an error. Thus, we have to make sure, that
|
|
+ * the address is sane. */
|
|
+ clear_host_address (family, network, plen, network_clean);
|
|
+ dst = nl_addr_build (family, network_clean, plen ? addrlen : 0);
|
|
+
|
|
g_assert (rtnlroute && dst && nexthop);
|
|
|
|
nl_addr_set_prefixlen (dst, plen);
|
|
@@ -2635,7 +2661,7 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
|
|
static gboolean
|
|
ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric)
|
|
{
|
|
- struct in6_addr gateway = in6addr_any;
|
|
+ struct in6_addr gateway = IN6ADDR_ANY_INIT;
|
|
|
|
return delete_object (platform, build_rtnl_route (AF_INET6, ifindex, &network, plen, &gateway, metric, 0));
|
|
}
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 30b274644625c85c6e5e199df3edbc5e98efe846 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Thu, 13 Feb 2014 15:11:05 +0100
|
|
Subject: [PATCH 09/15] platform: refactor delete_object() and allow deletion
|
|
of objects that are not cached
|
|
|
|
- refactor delete_object() by merging with delete_kernel_object()
|
|
|
|
- allow deletion of object that we cannot find in the cache
|
|
currently. The kernel might have such an address, even if we don't
|
|
have it currently cached. In this case, fall back to @obj.
|
|
|
|
Also try to work around an issue, that we cannot delete an IPv4 route without
|
|
knowing its scope.
|
|
|
|
- suppress logging error message for NLE_NOADDR, which is a common
|
|
failure when deleting an address. But at the same time, add some more
|
|
debug logging, for NLE_NOADDR and NLE_OBJ_NOTFOUND.
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
(cherry picked from commit 5f5c7284d16c5f24200bbbd40c5e9a83f84516cd)
|
|
---
|
|
src/platform/nm-linux-platform.c | 88 ++++++++++++++++++++++++++--------------
|
|
1 file changed, 57 insertions(+), 31 deletions(-)
|
|
|
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
|
index 802a47b..8652163 100644
|
|
--- a/src/platform/nm-linux-platform.c
|
|
+++ b/src/platform/nm-linux-platform.c
|
|
@@ -320,25 +320,6 @@ add_kernel_object (struct nl_sock *sock, struct nl_object *object)
|
|
}
|
|
}
|
|
|
|
-/* libnl 3.2 doesn't seem to provide such a generic way to delete libnl-route objects. */
|
|
-static int
|
|
-delete_kernel_object (struct nl_sock *sock, struct nl_object *object)
|
|
-{
|
|
- switch (object_type_from_nl_object (object)) {
|
|
- case LINK:
|
|
- return rtnl_link_delete (sock, (struct rtnl_link *) object);
|
|
- case IP4_ADDRESS:
|
|
- case IP6_ADDRESS:
|
|
- return rtnl_addr_delete (sock, (struct rtnl_addr *) object, 0);
|
|
- case IP4_ROUTE:
|
|
- case IP6_ROUTE:
|
|
- return rtnl_route_delete (sock, (struct rtnl_route *) object, 0);
|
|
- default:
|
|
- g_return_val_if_reached (-NLE_INVAL);
|
|
- return -NLE_INVAL;
|
|
- }
|
|
-}
|
|
-
|
|
/* nm_rtnl_link_parse_info_data(): Re-fetches a link from the kernel
|
|
* and parses its IFLA_INFO_DATA using a caller-provided parser.
|
|
*
|
|
@@ -1234,6 +1215,8 @@ add_object (NMPlatform *platform, struct nl_object *obj)
|
|
.dp_fd = stderr,
|
|
};
|
|
|
|
+ g_return_val_if_fail (object, FALSE);
|
|
+
|
|
nle = add_kernel_object (priv->nlh, object);
|
|
|
|
/* NLE_EXIST is considered equivalent to success to avoid race conditions. You
|
|
@@ -1258,26 +1241,48 @@ static gboolean
|
|
delete_object (NMPlatform *platform, struct nl_object *obj)
|
|
{
|
|
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
|
- auto_nl_object struct nl_object *object = obj;
|
|
+ auto_nl_object struct nl_object *obj_cleanup = obj;
|
|
auto_nl_object struct nl_object *cached_object = NULL;
|
|
+ struct nl_object *object;
|
|
+ int object_type;
|
|
int nle;
|
|
|
|
- /* FIXME: For some reason the result of build_rtnl_route() is not suitable
|
|
- * for delete_kernel_object() and we need to search the cache first. If
|
|
- * that problem is fixed, we can use 'object' directly.
|
|
- */
|
|
- cached_object = nm_nl_cache_search (choose_cache (platform, object), object);
|
|
- g_return_val_if_fail (cached_object, FALSE);
|
|
+ object_type = object_type_from_nl_object (obj);
|
|
+ g_return_val_if_fail (object_type != UNKNOWN_OBJECT_TYPE, FALSE);
|
|
|
|
- nle = delete_kernel_object (priv->nlh, cached_object);
|
|
+ cached_object = nm_nl_cache_search (choose_cache_by_type (platform, object_type), obj);
|
|
+ object = cached_object ? cached_object : obj;
|
|
+
|
|
+ switch (object_type) {
|
|
+ case LINK:
|
|
+ nle = rtnl_link_delete (priv->nlh, (struct rtnl_link *) object);
|
|
+ break;
|
|
+ case IP4_ADDRESS:
|
|
+ case IP6_ADDRESS:
|
|
+ nle = rtnl_addr_delete (priv->nlh, (struct rtnl_addr *) object, 0);
|
|
+ break;
|
|
+ case IP4_ROUTE:
|
|
+ case IP6_ROUTE:
|
|
+ nle = rtnl_route_delete (priv->nlh, (struct rtnl_route *) object, 0);
|
|
+ break;
|
|
+ default:
|
|
+ g_assert_not_reached ();
|
|
+ }
|
|
|
|
- /* NLE_OBJ_NOTFOUND is considered equivalent to success to avoid race conditions. You
|
|
- * never know when something deletes the same object just before NetworkManager.
|
|
- */
|
|
switch (nle) {
|
|
case -NLE_SUCCESS:
|
|
+ break;
|
|
case -NLE_OBJ_NOTFOUND:
|
|
+ debug("delete_object failed with \"%s\" (%d), meaning the object was already removed",
|
|
+ nl_geterror (nle), nle);
|
|
break;
|
|
+ case -NLE_NOADDR:
|
|
+ if (object_type == IP4_ADDRESS || object_type == IP6_ADDRESS) {
|
|
+ debug("delete_object for address failed with \"%s\" (%d), meaning the address was already removed",
|
|
+ nl_geterror (nle), nle);
|
|
+ break;
|
|
+ }
|
|
+ /* fall-through to error, because we only expect this for addresses. */
|
|
default:
|
|
error ("Netlink error: %s", nl_geterror (nle));
|
|
return FALSE;
|
|
@@ -2626,6 +2631,7 @@ build_rtnl_route (int family, int ifindex, gconstpointer network, int plen, gcon
|
|
rtnl_route_set_tos (rtnlroute, 0);
|
|
rtnl_route_set_dst (rtnlroute, dst);
|
|
rtnl_route_set_priority (rtnlroute, metric);
|
|
+ rtnl_route_set_family (rtnlroute, family);
|
|
|
|
rtnl_route_nh_set_ifindex (nexthop, ifindex);
|
|
if (gw && !nl_addr_iszero (gw))
|
|
@@ -2654,8 +2660,28 @@ static gboolean
|
|
ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric)
|
|
{
|
|
in_addr_t gateway = 0;
|
|
+ struct nl_object *route = build_rtnl_route (AF_INET, ifindex, &network, plen, &gateway, metric, 0);
|
|
+
|
|
+ g_return_val_if_fail (route, FALSE);
|
|
+
|
|
+ /* When searching for a matching IPv4 route to delete, the kernel
|
|
+ * searches for a matching scope, unless the RTM_DELROUTE message
|
|
+ * specifies RT_SCOPE_NOWHERE (see fib_table_delete()).
|
|
+ *
|
|
+ * However, if we set the scope of @rtnlroute to RT_SCOPE_NOWHERE (or
|
|
+ * leave it unset), rtnl_route_build_msg() will reset the scope to
|
|
+ * rtnl_route_guess_scope() -- which might be the wrong scope.
|
|
+ *
|
|
+ * As a workaround, we set the scope to RT_SCOPE_UNIVERSE, so libnl
|
|
+ * will not overwrite it. But this only works if we guess correctly.
|
|
+ *
|
|
+ * As a better workaround, we don't use @rtnlroute as argument for
|
|
+ * rtnl_route_delete(), but we look into our cache, if we already have
|
|
+ * this route ready.
|
|
+ **/
|
|
+ rtnl_route_set_scope ((struct rtnl_route *) route, RT_SCOPE_UNIVERSE);
|
|
|
|
- return delete_object (platform, build_rtnl_route (AF_INET, ifindex, &network, plen, &gateway, metric, 0));
|
|
+ return delete_object (platform, route);
|
|
}
|
|
|
|
static gboolean
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From e41a50cfdce7b89df43bf28a7e2ee381156108ee Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Thu, 13 Feb 2014 14:56:38 +0100
|
|
Subject: [PATCH 10/15] platform: do not check for _exists() before deleting
|
|
addresses and routes
|
|
|
|
Before, nm_platform_ip4_address_exists(), et al. look into the cache to see
|
|
whether the address/route already exists and returned an error if it
|
|
did.
|
|
|
|
Change the semantic of the delete functions, to return success in case of
|
|
"nothing to delete". Also always try to delete the object in the
|
|
kernel. The reason is, that the cache might be out of date and the
|
|
caller really wants to delete it. So, to be sure, we always delete.
|
|
|
|
In most cases the object is actually in the cache (because that is
|
|
how the caller came to know that such an object might exist).
|
|
In those cases, the lookup was not useful either, because the object
|
|
was actually cached.
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
(cherry picked from commit 2bc90a5f2d3dabc84a6ce3a8eb6a0e2582c1c9f2)
|
|
---
|
|
src/platform/nm-fake-platform.c | 24 ++++++++++++------------
|
|
src/platform/nm-platform.c | 28 ----------------------------
|
|
src/platform/tests/test-address.c | 8 ++++----
|
|
src/platform/tests/test-route.c | 8 ++++----
|
|
4 files changed, 20 insertions(+), 48 deletions(-)
|
|
|
|
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
|
|
index 4394472..d0127c4 100644
|
|
--- a/src/platform/nm-fake-platform.c
|
|
+++ b/src/platform/nm-fake-platform.c
|
|
@@ -827,7 +827,7 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
|
|
}
|
|
}
|
|
|
|
- g_assert_not_reached ();
|
|
+ return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
@@ -850,7 +850,7 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int
|
|
}
|
|
}
|
|
|
|
- g_assert_not_reached ();
|
|
+ return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
@@ -1064,11 +1064,11 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
|
|
NMPlatformIP4Route *route = ip4_route_get (platform, ifindex, network, plen, metric);
|
|
NMPlatformIP4Route deleted_route;
|
|
|
|
- g_assert (route);
|
|
-
|
|
- memcpy (&deleted_route, route, sizeof (deleted_route));
|
|
- memset (route, 0, sizeof (*route));
|
|
- g_signal_emit_by_name (platform, NM_PLATFORM_IP4_ROUTE_REMOVED, ifindex, &deleted_route, NM_PLATFORM_REASON_INTERNAL);
|
|
+ if (route) {
|
|
+ memcpy (&deleted_route, route, sizeof (deleted_route));
|
|
+ memset (route, 0, sizeof (*route));
|
|
+ g_signal_emit_by_name (platform, NM_PLATFORM_IP4_ROUTE_REMOVED, ifindex, &deleted_route, NM_PLATFORM_REASON_INTERNAL);
|
|
+ }
|
|
|
|
return TRUE;
|
|
}
|
|
@@ -1079,11 +1079,11 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, in
|
|
NMPlatformIP6Route *route = ip6_route_get (platform, ifindex, network, plen, metric);
|
|
NMPlatformIP6Route deleted_route;
|
|
|
|
- g_assert (route);
|
|
-
|
|
- memcpy (&deleted_route, route, sizeof (deleted_route));
|
|
- memset (route, 0, sizeof (*route));
|
|
- g_signal_emit_by_name (platform, NM_PLATFORM_IP6_ROUTE_REMOVED, ifindex, &deleted_route, NM_PLATFORM_REASON_INTERNAL);
|
|
+ if (route) {
|
|
+ memcpy (&deleted_route, route, sizeof (deleted_route));
|
|
+ memset (route, 0, sizeof (*route));
|
|
+ g_signal_emit_by_name (platform, NM_PLATFORM_IP6_ROUTE_REMOVED, ifindex, &deleted_route, NM_PLATFORM_REASON_INTERNAL);
|
|
+ }
|
|
|
|
return TRUE;
|
|
}
|
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
|
index 8bdfaf4..8485e74 100644
|
|
--- a/src/platform/nm-platform.c
|
|
+++ b/src/platform/nm-platform.c
|
|
@@ -1282,13 +1282,6 @@ nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen)
|
|
g_return_val_if_fail (klass->ip4_address_delete, FALSE);
|
|
|
|
debug ("address: deleting IPv4 address %s/%d", nm_utils_inet4_ntop (address, NULL), plen);
|
|
-
|
|
- if (!nm_platform_ip4_address_exists (ifindex, address, plen)) {
|
|
- debug ("address doesn't exists");
|
|
- platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
return klass->ip4_address_delete (platform, ifindex, address, plen);
|
|
}
|
|
|
|
@@ -1302,13 +1295,6 @@ nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen)
|
|
g_return_val_if_fail (klass->ip6_address_delete, FALSE);
|
|
|
|
debug ("address: deleting IPv6 address %s/%d", nm_utils_inet6_ntop (&address, NULL), plen);
|
|
-
|
|
- if (!nm_platform_ip6_address_exists (ifindex, address, plen)) {
|
|
- debug ("address doesn't exists");
|
|
- platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
return klass->ip6_address_delete (platform, ifindex, address, plen);
|
|
}
|
|
|
|
@@ -1581,13 +1567,6 @@ nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, int metr
|
|
g_return_val_if_fail (klass->ip4_route_delete, FALSE);
|
|
|
|
debug ("route: deleting IPv4 route %s/%d, metric=%d", nm_utils_inet4_ntop (network, NULL), plen, metric);
|
|
-
|
|
- if (!nm_platform_ip4_route_exists (ifindex, network, plen, metric)) {
|
|
- debug ("route not found");
|
|
- platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
return klass->ip4_route_delete (platform, ifindex, network, plen, metric);
|
|
}
|
|
|
|
@@ -1601,13 +1580,6 @@ nm_platform_ip6_route_delete (int ifindex,
|
|
g_return_val_if_fail (klass->ip6_route_delete, FALSE);
|
|
|
|
debug ("route: deleting IPv6 route %s/%d, metric=%d", nm_utils_inet6_ntop (&network, NULL), plen, metric);
|
|
-
|
|
- if (!nm_platform_ip6_route_exists (ifindex, network, plen, metric)) {
|
|
- debug ("route not found");
|
|
- platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
return klass->ip6_route_delete (platform, ifindex, network, plen, metric);
|
|
}
|
|
|
|
diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c
|
|
index 0f0ccc8..20f1bd9 100644
|
|
--- a/src/platform/tests/test-address.c
|
|
+++ b/src/platform/tests/test-address.c
|
|
@@ -89,8 +89,8 @@ test_ip4_address (void)
|
|
accept_signal (address_removed);
|
|
|
|
/* Remove address again */
|
|
- g_assert (!nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN));
|
|
- error (NM_PLATFORM_ERROR_NOT_FOUND);
|
|
+ g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN));
|
|
+ no_error ();
|
|
|
|
free_signal (address_added);
|
|
free_signal (address_changed);
|
|
@@ -145,8 +145,8 @@ test_ip6_address (void)
|
|
accept_signal (address_removed);
|
|
|
|
/* Remove address again */
|
|
- g_assert (!nm_platform_ip6_address_delete (ifindex, addr, IP6_PLEN));
|
|
- error (NM_PLATFORM_ERROR_NOT_FOUND);
|
|
+ g_assert (nm_platform_ip6_address_delete (ifindex, addr, IP6_PLEN));
|
|
+ no_error ();
|
|
|
|
free_signal (address_added);
|
|
free_signal (address_changed);
|
|
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
|
|
index 6c764ad..f333ffc 100644
|
|
--- a/src/platform/tests/test-route.c
|
|
+++ b/src/platform/tests/test-route.c
|
|
@@ -113,8 +113,8 @@ test_ip4_route ()
|
|
accept_signal (route_removed);
|
|
|
|
/* Remove route again */
|
|
- g_assert (!nm_platform_ip4_route_delete (ifindex, network, plen, metric));
|
|
- error (NM_PLATFORM_ERROR_NOT_FOUND);
|
|
+ g_assert (nm_platform_ip4_route_delete (ifindex, network, plen, metric));
|
|
+ no_error ();
|
|
|
|
free_signal (route_added);
|
|
free_signal (route_changed);
|
|
@@ -196,8 +196,8 @@ test_ip6_route ()
|
|
accept_signal (route_removed);
|
|
|
|
/* Remove route again */
|
|
- g_assert (!nm_platform_ip6_route_delete (ifindex, network, plen, metric));
|
|
- error (NM_PLATFORM_ERROR_NOT_FOUND);
|
|
+ g_assert (nm_platform_ip6_route_delete (ifindex, network, plen, metric));
|
|
+ no_error ();
|
|
|
|
free_signal (route_added);
|
|
free_signal (route_changed);
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From a544160ae6bc97123ecc4d1a7d501a59ebd63151 Mon Sep 17 00:00:00 2001
|
|
From: Dan Winship <danw@gnome.org>
|
|
Date: Thu, 20 Feb 2014 14:28:30 -0500
|
|
Subject: [PATCH 11/15] platform: fix macvlan flags checking
|
|
|
|
You can't do an #ifdef on an enum value, so we were actually never
|
|
requesting IFLA_MACVLAN_FLAGS.
|
|
|
|
(cherry picked from commit 4e273c4be84f4c4946e957595557d6cefe8acab3)
|
|
---
|
|
src/platform/nm-linux-platform.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
|
|
index 8652163..367df79 100644
|
|
--- a/src/platform/nm-linux-platform.c
|
|
+++ b/src/platform/nm-linux-platform.c
|
|
@@ -2186,7 +2186,7 @@ tun_get_properties (NMPlatform *platform, int ifindex, NMPlatformTunProperties *
|
|
|
|
static const struct nla_policy macvlan_info_policy[IFLA_MACVLAN_MAX + 1] = {
|
|
[IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
|
|
-#ifdef IFLA_MACVLAN_FLAGS
|
|
+#ifdef MACVLAN_FLAG_NOPROMISC
|
|
[IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 },
|
|
#endif
|
|
};
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From a08ad7ff329bdca3913432d0f8e39999c1a4eda7 Mon Sep 17 00:00:00 2001
|
|
From: Dan Winship <danw@gnome.org>
|
|
Date: Thu, 13 Feb 2014 14:22:26 -0500
|
|
Subject: [PATCH 12/15] core: remove some unused code
|
|
|
|
We never pass any delay_seconds value to schedule_activate_check()
|
|
except "0", so just remove that argument.
|
|
|
|
(cherry picked from commit a217a742f1207e4451f401280048f64e10cfd5be)
|
|
---
|
|
src/nm-policy.c | 23 ++++++++++-------------
|
|
1 file changed, 10 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/src/nm-policy.c b/src/nm-policy.c
|
|
index 34216c8..71f53e6 100644
|
|
--- a/src/nm-policy.c
|
|
+++ b/src/nm-policy.c
|
|
@@ -1015,17 +1015,14 @@ auto_activate_device (gpointer user_data)
|
|
}
|
|
|
|
static ActivateData *
|
|
-activate_data_new (NMPolicy *policy, NMDevice *device, guint delay_seconds)
|
|
+activate_data_new (NMPolicy *policy, NMDevice *device)
|
|
{
|
|
ActivateData *data;
|
|
|
|
data = g_malloc0 (sizeof (ActivateData));
|
|
data->policy = policy;
|
|
data->device = g_object_ref (device);
|
|
- if (delay_seconds > 0)
|
|
- data->autoactivate_id = g_timeout_add_seconds (delay_seconds, auto_activate_device, data);
|
|
- else
|
|
- data->autoactivate_id = g_idle_add (auto_activate_device, data);
|
|
+ data->autoactivate_id = g_idle_add (auto_activate_device, data);
|
|
|
|
nm_device_add_pending_action (device, "autoactivate");
|
|
|
|
@@ -1215,7 +1212,7 @@ sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
|
|
}
|
|
|
|
static void
|
|
-schedule_activate_check (NMPolicy *policy, NMDevice *device, guint delay_seconds)
|
|
+schedule_activate_check (NMPolicy *policy, NMDevice *device)
|
|
{
|
|
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy);
|
|
ActivateData *data;
|
|
@@ -1241,7 +1238,7 @@ schedule_activate_check (NMPolicy *policy, NMDevice *device, guint delay_seconds
|
|
|
|
/* Schedule an auto-activation if there isn't one already for this device */
|
|
if (find_pending_activation (priv->pending_activation_checks, device) == NULL) {
|
|
- data = activate_data_new (policy, device, delay_seconds);
|
|
+ data = activate_data_new (policy, device);
|
|
priv->pending_activation_checks = g_slist_append (priv->pending_activation_checks, data);
|
|
}
|
|
}
|
|
@@ -1493,7 +1490,7 @@ device_state_changed (NMDevice *device,
|
|
update_routing_and_dns (policy, FALSE);
|
|
|
|
/* Device is now available for auto-activation */
|
|
- schedule_activate_check (policy, device, 0);
|
|
+ schedule_activate_check (policy, device);
|
|
break;
|
|
|
|
case NM_DEVICE_STATE_PREPARE:
|
|
@@ -1601,25 +1598,25 @@ device_autoconnect_changed (NMDevice *device,
|
|
gpointer user_data)
|
|
{
|
|
if (nm_device_get_autoconnect (device))
|
|
- schedule_activate_check ((NMPolicy *) user_data, device, 0);
|
|
+ schedule_activate_check ((NMPolicy *) user_data, device);
|
|
}
|
|
|
|
static void
|
|
wireless_networks_changed (NMDevice *device, GObject *ap, gpointer user_data)
|
|
{
|
|
- schedule_activate_check ((NMPolicy *) user_data, device, 0);
|
|
+ schedule_activate_check ((NMPolicy *) user_data, device);
|
|
}
|
|
|
|
static void
|
|
nsps_changed (NMDevice *device, GObject *nsp, gpointer user_data)
|
|
{
|
|
- schedule_activate_check ((NMPolicy *) user_data, device, 0);
|
|
+ schedule_activate_check ((NMPolicy *) user_data, device);
|
|
}
|
|
|
|
static void
|
|
modem_enabled_changed (NMDevice *device, gpointer user_data)
|
|
{
|
|
- schedule_activate_check ((NMPolicy *) (user_data), device, 0);
|
|
+ schedule_activate_check ((NMPolicy *) (user_data), device);
|
|
}
|
|
|
|
typedef struct {
|
|
@@ -1837,7 +1834,7 @@ schedule_activate_all (NMPolicy *policy)
|
|
|
|
devices = nm_manager_get_devices (priv->manager);
|
|
for (iter = devices; iter; iter = g_slist_next (iter))
|
|
- schedule_activate_check (policy, NM_DEVICE (iter->data), 0);
|
|
+ schedule_activate_check (policy, NM_DEVICE (iter->data));
|
|
}
|
|
|
|
static void
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 15f5ab2f836fe3463e94c356da83382333f7dc3e Mon Sep 17 00:00:00 2001
|
|
From: Dan Winship <danw@gnome.org>
|
|
Date: Thu, 13 Feb 2014 14:25:30 -0500
|
|
Subject: [PATCH 13/15] Revert "core: fix warning about pending action
|
|
"autoactivate""
|
|
|
|
This change removed the "autoactivate" pending action too soon,
|
|
creating a window where the device had no pending actions, allowing
|
|
the manager to declare startup complete while devices were still being
|
|
activated.
|
|
|
|
This reverts commit a16b7a82538e59af19557e03ae54e2e6afb5a891.
|
|
|
|
(cherry picked from commit 93285054ae5ef290d879a753f88824b5027e9c8a)
|
|
---
|
|
src/nm-policy.c | 9 ++++-----
|
|
1 file changed, 4 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/src/nm-policy.c b/src/nm-policy.c
|
|
index 71f53e6..142cf65 100644
|
|
--- a/src/nm-policy.c
|
|
+++ b/src/nm-policy.c
|
|
@@ -937,10 +937,10 @@ typedef struct {
|
|
static void
|
|
activate_data_free (ActivateData *data)
|
|
{
|
|
- if (data->autoactivate_id) {
|
|
- nm_device_remove_pending_action (data->device, "autoactivate");
|
|
+ nm_device_remove_pending_action (data->device, "autoactivate");
|
|
+
|
|
+ if (data->autoactivate_id)
|
|
g_source_remove (data->autoactivate_id);
|
|
- }
|
|
g_object_unref (data->device);
|
|
memset (data, 0, sizeof (*data));
|
|
g_free (data);
|
|
@@ -960,9 +960,8 @@ auto_activate_device (gpointer user_data)
|
|
policy = data->policy;
|
|
priv = NM_POLICY_GET_PRIVATE (policy);
|
|
|
|
- priv->pending_activation_checks = g_slist_remove (priv->pending_activation_checks, data);
|
|
data->autoactivate_id = 0;
|
|
- nm_device_remove_pending_action (data->device, "autoactivate");
|
|
+ priv->pending_activation_checks = g_slist_remove (priv->pending_activation_checks, data);
|
|
|
|
// FIXME: if a device is already activating (or activated) with a connection
|
|
// but another connection now overrides the current one for that device,
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From 784f7161c8496557756bb1544bf1f9c9bb8b9ebb Mon Sep 17 00:00:00 2001
|
|
From: Dan Winship <danw@gnome.org>
|
|
Date: Thu, 13 Feb 2014 14:45:25 -0500
|
|
Subject: [PATCH 14/15] core: don't recursively schedule an autoactivate check
|
|
on a device
|
|
|
|
NMPolicy's auto_activate_device() was immediately removing the device
|
|
from priv->pending_activation_checks, which meant that if
|
|
nm_manager_activate_connection() had some side effect that would cause
|
|
schedule_activation_check() to be called again, another
|
|
auto-activation check could be queued while the first was still in
|
|
progress (causing a warning). Fix this by not removing the device from
|
|
the list until the activation attempt is complete.
|
|
|
|
This requires some additional minor changes to correctly handle the
|
|
possibility of remove_device() being triggered as a side effect of
|
|
nm_manager_activate_connection().
|
|
|
|
Also merge activate_data_new() into schedule_activation_check() so
|
|
that all the "start an auto-activation" code is in one place.
|
|
|
|
(cherry picked from commit 4f0c70e94534abafde6a0459af74b68a7da724d9)
|
|
---
|
|
src/nm-policy.c | 56 +++++++++++++++++++++++++-------------------------------
|
|
1 file changed, 25 insertions(+), 31 deletions(-)
|
|
|
|
diff --git a/src/nm-policy.c b/src/nm-policy.c
|
|
index 142cf65..90fbc36 100644
|
|
--- a/src/nm-policy.c
|
|
+++ b/src/nm-policy.c
|
|
@@ -937,12 +937,14 @@ typedef struct {
|
|
static void
|
|
activate_data_free (ActivateData *data)
|
|
{
|
|
+ NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (data->policy);
|
|
+
|
|
nm_device_remove_pending_action (data->device, "autoactivate");
|
|
+ priv->pending_activation_checks = g_slist_remove (priv->pending_activation_checks, data);
|
|
|
|
if (data->autoactivate_id)
|
|
g_source_remove (data->autoactivate_id);
|
|
g_object_unref (data->device);
|
|
- memset (data, 0, sizeof (*data));
|
|
g_free (data);
|
|
}
|
|
|
|
@@ -961,7 +963,6 @@ auto_activate_device (gpointer user_data)
|
|
priv = NM_POLICY_GET_PRIVATE (policy);
|
|
|
|
data->autoactivate_id = 0;
|
|
- priv->pending_activation_checks = g_slist_remove (priv->pending_activation_checks, data);
|
|
|
|
// FIXME: if a device is already activating (or activated) with a connection
|
|
// but another connection now overrides the current one for that device,
|
|
@@ -1014,21 +1015,6 @@ auto_activate_device (gpointer user_data)
|
|
}
|
|
|
|
static ActivateData *
|
|
-activate_data_new (NMPolicy *policy, NMDevice *device)
|
|
-{
|
|
- ActivateData *data;
|
|
-
|
|
- data = g_malloc0 (sizeof (ActivateData));
|
|
- data->policy = policy;
|
|
- data->device = g_object_ref (device);
|
|
- data->autoactivate_id = g_idle_add (auto_activate_device, data);
|
|
-
|
|
- nm_device_add_pending_action (device, "autoactivate");
|
|
-
|
|
- return data;
|
|
-}
|
|
-
|
|
-static ActivateData *
|
|
find_pending_activation (GSList *list, NMDevice *device)
|
|
{
|
|
GSList *iter;
|
|
@@ -1226,20 +1212,33 @@ schedule_activate_check (NMPolicy *policy, NMDevice *device)
|
|
if (!nm_device_autoconnect_allowed (device))
|
|
return;
|
|
|
|
- /* If the device already has an activation in-progress or waiting for
|
|
- * authentication, don't start an auto-activation for it.
|
|
- */
|
|
+ if (find_pending_activation (priv->pending_activation_checks, device))
|
|
+ return;
|
|
+
|
|
active_connections = nm_manager_get_active_connections (priv->manager);
|
|
for (iter = active_connections; iter; iter = iter->next) {
|
|
if (nm_active_connection_get_device (NM_ACTIVE_CONNECTION (iter->data)) == device)
|
|
return;
|
|
}
|
|
|
|
- /* Schedule an auto-activation if there isn't one already for this device */
|
|
- if (find_pending_activation (priv->pending_activation_checks, device) == NULL) {
|
|
- data = activate_data_new (policy, device);
|
|
- priv->pending_activation_checks = g_slist_append (priv->pending_activation_checks, data);
|
|
- }
|
|
+ nm_device_add_pending_action (device, "autoactivate");
|
|
+
|
|
+ data = g_malloc0 (sizeof (ActivateData));
|
|
+ data->policy = policy;
|
|
+ data->device = g_object_ref (device);
|
|
+ data->autoactivate_id = g_idle_add (auto_activate_device, data);
|
|
+ priv->pending_activation_checks = g_slist_append (priv->pending_activation_checks, data);
|
|
+}
|
|
+
|
|
+static void
|
|
+clear_pending_activate_check (NMPolicy *policy, NMDevice *device)
|
|
+{
|
|
+ NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy);
|
|
+ ActivateData *data;
|
|
+
|
|
+ data = find_pending_activation (priv->pending_activation_checks, device);
|
|
+ if (data && data->autoactivate_id)
|
|
+ activate_data_free (data);
|
|
}
|
|
|
|
static gboolean
|
|
@@ -1676,15 +1675,10 @@ device_removed (NMManager *manager, NMDevice *device, gpointer user_data)
|
|
{
|
|
NMPolicy *policy = (NMPolicy *) user_data;
|
|
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy);
|
|
- ActivateData *tmp;
|
|
GSList *iter;
|
|
|
|
/* Clear any idle callbacks for this device */
|
|
- tmp = find_pending_activation (priv->pending_activation_checks, device);
|
|
- if (tmp) {
|
|
- priv->pending_activation_checks = g_slist_remove (priv->pending_activation_checks, tmp);
|
|
- activate_data_free (tmp);
|
|
- }
|
|
+ clear_pending_activate_check (policy, device);
|
|
|
|
/* Clear any signal handlers for this device */
|
|
iter = priv->dev_ids;
|
|
--
|
|
1.8.5.3
|
|
|
|
|
|
From f7eea6e922d6e99fbe0eefb7a71f87d0562e0226 Mon Sep 17 00:00:00 2001
|
|
From: Thomas Haller <thaller@redhat.com>
|
|
Date: Tue, 18 Feb 2014 12:52:16 +0100
|
|
Subject: [PATCH 15/15] platform: refactor address_to_string() to return device
|
|
as numeric if ifname is unknown
|
|
|
|
Signed-off-by: Thomas Haller <thaller@redhat.com>
|
|
(cherry picked from commit a6767f215e0b7ab55949e4410d399f315a225578)
|
|
---
|
|
src/platform/nm-platform.c | 57 +++++++++++++++++++++++++++-------------------
|
|
1 file changed, 33 insertions(+), 24 deletions(-)
|
|
|
|
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
|
|
index 8485e74..fcd4b19 100644
|
|
--- a/src/platform/nm-platform.c
|
|
+++ b/src/platform/nm-platform.c
|
|
@@ -1813,6 +1813,27 @@ source_to_string (NMPlatformSource source)
|
|
return "unknown";
|
|
}
|
|
|
|
+#define TO_STRING_DEV_BUF_SIZE (5+15+1)
|
|
+static void
|
|
+_to_string_dev (int ifindex, char *buf, size_t size)
|
|
+{
|
|
+ g_assert (buf && size >= TO_STRING_DEV_BUF_SIZE);
|
|
+
|
|
+ if (ifindex){
|
|
+ const char *name = ifindex > 0 ? nm_platform_link_get_name (ifindex) : NULL;
|
|
+
|
|
+ strcpy (buf, " dev ");
|
|
+ buf += 5;
|
|
+ size -= 5;
|
|
+
|
|
+ if (name)
|
|
+ g_strlcpy (buf, name, size);
|
|
+ else
|
|
+ g_snprintf (buf, size, "%d", ifindex);
|
|
+ } else
|
|
+ buf[0] = 0;
|
|
+}
|
|
+
|
|
/**
|
|
* nm_platform_ip4_address_to_string:
|
|
* @route: pointer to NMPlatformIP4Address address structure
|
|
@@ -1831,8 +1852,7 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address)
|
|
static char buffer[256];
|
|
char s_address[INET_ADDRSTRLEN];
|
|
char s_peer[INET_ADDRSTRLEN];
|
|
- const char *s_dev;
|
|
- char *str_dev;
|
|
+ char str_dev[TO_STRING_DEV_BUF_SIZE];
|
|
char *str_peer = NULL;
|
|
|
|
g_return_val_if_fail (address, "(unknown)");
|
|
@@ -1844,16 +1864,14 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address)
|
|
str_peer = g_strconcat (" ptp ", s_peer, NULL);
|
|
}
|
|
|
|
- s_dev = address->ifindex > 0 ? nm_platform_link_get_name (address->ifindex) : NULL;
|
|
- str_dev = s_dev ? g_strconcat (" dev ", s_dev, NULL) : NULL;
|
|
+ _to_string_dev (address->ifindex, str_dev, sizeof (str_dev));
|
|
|
|
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,
|
|
source_to_string (address->source));
|
|
- g_free (str_dev);
|
|
g_free (str_peer);
|
|
return buffer;
|
|
}
|
|
@@ -1877,9 +1895,8 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address)
|
|
char s_flags[256];
|
|
char s_address[INET6_ADDRSTRLEN];
|
|
char s_peer[INET6_ADDRSTRLEN];
|
|
- const char *s_dev;
|
|
char *str_flags;
|
|
- char *str_dev;
|
|
+ char str_dev[TO_STRING_DEV_BUF_SIZE];
|
|
char *str_peer = NULL;
|
|
|
|
g_return_val_if_fail (address, "(unknown)");
|
|
@@ -1891,8 +1908,7 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address)
|
|
str_peer = g_strconcat (" ptp ", s_peer, NULL);
|
|
}
|
|
|
|
- s_dev = address->ifindex > 0 ? nm_platform_link_get_name (address->ifindex) : NULL;
|
|
- str_dev = s_dev ? g_strconcat (" dev ", s_dev, NULL) : NULL;
|
|
+ _to_string_dev (address->ifindex, str_dev, sizeof (str_dev));
|
|
|
|
rtnl_addr_flags2str(address->flags, s_flags, sizeof (s_flags));
|
|
|
|
@@ -1916,11 +1932,10 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address)
|
|
s_address, address->plen, (guint)address->lifetime, (guint)address->preferred,
|
|
(guint)address->timestamp,
|
|
str_peer ? str_peer : "",
|
|
- str_dev ? str_dev : "",
|
|
+ str_dev,
|
|
str_flags ? str_flags : "",
|
|
source_to_string (address->source));
|
|
g_free (str_flags);
|
|
- g_free (str_dev);
|
|
g_free (str_peer);
|
|
return buffer;
|
|
}
|
|
@@ -1942,23 +1957,20 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route)
|
|
{
|
|
static char buffer[256];
|
|
char s_network[INET_ADDRSTRLEN], s_gateway[INET_ADDRSTRLEN];
|
|
- const char *s_dev;
|
|
- char *str_dev;
|
|
+ char str_dev[TO_STRING_DEV_BUF_SIZE];
|
|
|
|
g_return_val_if_fail (route, "(unknown)");
|
|
|
|
inet_ntop (AF_INET, &route->network, s_network, sizeof(s_network));
|
|
inet_ntop (AF_INET, &route->gateway, s_gateway, sizeof(s_gateway));
|
|
|
|
- s_dev = route->ifindex > 0 ? nm_platform_link_get_name (route->ifindex) : NULL;
|
|
- str_dev = s_dev ? g_strconcat (" dev ", s_dev, NULL) : NULL;
|
|
+ _to_string_dev (route->ifindex, str_dev, sizeof (str_dev));
|
|
|
|
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 : "",
|
|
+ str_dev,
|
|
route->metric, route->mss,
|
|
source_to_string (route->source));
|
|
- g_free (str_dev);
|
|
return buffer;
|
|
}
|
|
|
|
@@ -1979,23 +1991,20 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route)
|
|
{
|
|
static char buffer[256];
|
|
char s_network[INET6_ADDRSTRLEN], s_gateway[INET6_ADDRSTRLEN];
|
|
- const char *s_dev;
|
|
- char *str_dev;
|
|
+ char str_dev[TO_STRING_DEV_BUF_SIZE];
|
|
|
|
g_return_val_if_fail (route, "(unknown)");
|
|
|
|
inet_ntop (AF_INET6, &route->network, s_network, sizeof(s_network));
|
|
inet_ntop (AF_INET6, &route->gateway, s_gateway, sizeof(s_gateway));
|
|
|
|
- s_dev = route->ifindex > 0 ? nm_platform_link_get_name (route->ifindex) : NULL;
|
|
- str_dev = s_dev ? g_strconcat (" dev ", s_dev, NULL) : NULL;
|
|
+ _to_string_dev (route->ifindex, str_dev, sizeof (str_dev));
|
|
|
|
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 : "",
|
|
+ str_dev,
|
|
route->metric, route->mss,
|
|
source_to_string (route->source));
|
|
- g_free (str_dev);
|
|
return buffer;
|
|
}
|
|
|
|
--
|
|
1.8.5.3
|
|
|