diff options
author | Pavel Šimerda <psimerda@redhat.com> | 2013-06-21 03:14:40 +0200 |
---|---|---|
committer | Pavel Šimerda <psimerda@redhat.com> | 2013-06-21 04:02:32 +0200 |
commit | 40cb2f4c2944e0f885d39a5b52d7de9b206dcc80 (patch) | |
tree | 7cd66b87c113c0bb5701a45f44ff00dd430e1c0b | |
parent | 35dd05cc4336cf91f511f95469f61c57747b1622 (diff) |
platform: remove cached addresses and routes for deleted devices
-rw-r--r-- | src/platform/nm-fake-platform.c | 28 | ||||
-rw-r--r-- | src/platform/nm-linux-platform.c | 38 |
2 files changed, 66 insertions, 0 deletions
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index 95757aa1..816af0c1 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -212,8 +212,10 @@ link_add (NMPlatform *platform, const char *name, NMLinkType type) static gboolean link_delete (NMPlatform *platform, int ifindex) { + NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); NMFakePlatformLink *device = link_get (platform, ifindex); NMPlatformLink deleted_device; + int i; if (!device || !device->link.ifindex) return FALSE; @@ -221,6 +223,32 @@ link_delete (NMPlatform *platform, int ifindex) memcpy (&deleted_device, &device->link, sizeof (deleted_device)); memset (&device->link, 0, sizeof (device->link)); + /* Remove addresses and routes which belong to the deleted interface */ + for (i = 0; i < priv->ip4_addresses->len; i++) { + NMPlatformIP4Address *address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i); + + if (address->ifindex == ifindex) + memset (address, 0, sizeof (*address)); + } + for (i = 0; i < priv->ip6_addresses->len; i++) { + NMPlatformIP6Address *address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i); + + if (address->ifindex == ifindex) + memset (address, 0, sizeof (*address)); + } + for (i = 0; i < priv->ip4_routes->len; i++) { + NMPlatformIP4Route *route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i); + + if (route->ifindex == ifindex) + memset (route, 0, sizeof (*route)); + } + for (i = 0; i < priv->ip6_routes->len; i++) { + NMPlatformIP6Route *route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i); + + if (route->ifindex == ifindex) + memset (route, 0, sizeof (*route)); + } + g_signal_emit_by_name (platform, NM_PLATFORM_LINK_REMOVED, ifindex, &deleted_device); return TRUE; diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 05cdc284..c9cbadbf 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -855,6 +855,37 @@ add_object (NMPlatform *platform, struct nl_object *obj) return refresh_object (platform, object, add_kernel_object (priv->nlh, object)); } +static void +remove_if_ifindex (struct nl_object *object, gpointer user_data) +{ + int ifindex = *(int *) user_data; + + switch (object_type_from_nl_object (object)) { + case IP4_ADDRESS: + case IP6_ADDRESS: + if (ifindex != rtnl_addr_get_ifindex ((struct rtnl_addr *) object)) + break; + nl_cache_remove (object); + break; + case IP4_ROUTE: + case IP6_ROUTE: + { + struct rtnl_route *rtnlroute = (struct rtnl_route *) object; + struct rtnl_nexthop *nexthop; + + if (rtnl_route_get_nnexthops (rtnlroute) != 1) + break; + nexthop = rtnl_route_nexthop_n (rtnlroute, 0); + if (ifindex != rtnl_route_nh_get_ifindex (nexthop)) + break; + nl_cache_remove (object); + } + break; + default: + break; + } +} + /* Decreases the reference count if @obj for convenience */ static gboolean delete_object (NMPlatform *platform, struct nl_object *obj) @@ -870,6 +901,13 @@ delete_object (NMPlatform *platform, struct nl_object *obj) return FALSE; nl_cache_remove (cached_object); + if (object_type_from_nl_object (object) == LINK) { + int ifindex = rtnl_link_get_ifindex ((struct rtnl_link *) object); + + nl_cache_foreach (priv->address_cache, remove_if_ifindex, &ifindex); + nl_cache_foreach (priv->route_cache, remove_if_ifindex, &ifindex); + } + announce_object (platform, cached_object, REMOVED); return TRUE; |