NetworkManager/0003-platform-caching-and-d...

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