summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Šimerda <psimerda@redhat.com>2013-05-02 08:02:44 +0200
committerPavel Šimerda <psimerda@redhat.com>2013-06-25 09:50:35 +0200
commitef73aa3b2c10092324a7dcf62e7bb427b2ea6437 (patch)
tree5452ed1c154a2ff1404d1ce46d53fe1759b8a7e5
parentbd0fd1cd1dc0a5167c5c2cb0c0a86c4a293eeb31 (diff)
platform: route utility functions
-rw-r--r--src/platform/nm-platform.c129
-rw-r--r--src/platform/nm-platform.h3
2 files changed, 132 insertions, 0 deletions
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 6140d7a8..287d953d 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -1404,6 +1404,135 @@ nm_platform_ip6_route_exists (int ifindex, struct in6_addr network, int plen, in
return klass->ip6_route_exists (platform, ifindex, network, plen, metric);
}
+static gboolean
+array_contains_ip4_route (const GArray *routes, const NMPlatformIP4Route *route)
+{
+ int i;
+
+ for (i = 0; i < routes->len; i++) {
+ if (!memcmp (&g_array_index (routes, NMPlatformIP4Route, i), route, sizeof (*route)))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+array_contains_ip6_route (const GArray *routes, const NMPlatformIP6Route *route)
+{
+ int i;
+
+ for (i = 0; i < routes->len; i++) {
+ if (!memcmp (&g_array_index (routes, NMPlatformIP6Route, i), route, sizeof (*route)))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * nm_platform_ip4_route_sync:
+ * @ifindex: Interface index
+ * @known_routes: List of routes
+ *
+ * A convenience function to synchronize routes for a specific interface
+ * with the least possible disturbance. It simply removes routes that are
+ * not listed and adds routes that are.
+ *
+ * Returns: %TRUE on success.
+ */
+gboolean
+nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes)
+{
+ GArray *routes;
+ NMPlatformIP4Route *route;
+ const NMPlatformIP4Route *known_route;
+ int i;
+
+ /* Delete unknown routes */
+ routes = nm_platform_ip4_route_get_all (ifindex);
+ for (i = 0; i < routes->len; i++) {
+ route = &g_array_index (routes, NMPlatformIP4Route, i);
+ route->ifindex = 0;
+
+ if (!known_routes || !array_contains_ip4_route (known_routes, route))
+ nm_platform_ip4_route_delete (ifindex, route->network, route->plen, route->metric);
+ }
+ g_array_free (routes, TRUE);
+
+ if (!known_routes)
+ return TRUE;
+
+ /* Add missing routes */
+ for (i = 0; i < known_routes->len; i++) {
+ known_route = &g_array_index (known_routes, NMPlatformIP4Route, i);
+
+ if (!nm_platform_ip4_route_exists (ifindex,
+ known_route->network, known_route->plen, known_route->metric))
+ if (!nm_platform_ip4_route_add (ifindex,
+ known_route->network, known_route->plen, known_route->gateway,
+ known_route->metric, known_route->mss))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * nm_platform_ip6_route_sync:
+ * @ifindex: Interface index
+ * @known_routes: List of routes
+ *
+ * A convenience function to synchronize routes for a specific interface
+ * with the least possible disturbance. It simply removes routes that are
+ * not listed and adds routes that are.
+ *
+ * Returns: %TRUE on success.
+ */
+gboolean
+nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes)
+{
+ GArray *routes;
+ NMPlatformIP6Route *route;
+ const NMPlatformIP6Route *known_route;
+ int i;
+
+ /* Delete unknown routes */
+ routes = nm_platform_ip6_route_get_all (ifindex);
+ for (i = 0; i < routes->len; i++) {
+ route = &g_array_index (routes, NMPlatformIP6Route, i);
+ route->ifindex = 0;
+
+ if (!known_routes || !array_contains_ip6_route (known_routes, route))
+ nm_platform_ip6_route_delete (ifindex, route->network, route->plen, route->metric);
+ }
+ g_array_free (routes, TRUE);
+
+ if (!known_routes)
+ return TRUE;
+
+ /* Add missing routes */
+ for (i = 0; i < known_routes->len; i++) {
+ known_route = &g_array_index (known_routes, NMPlatformIP6Route, i);
+
+ if (!nm_platform_ip6_route_exists (ifindex,
+ known_route->network, known_route->plen, known_route->metric))
+ if (!nm_platform_ip6_route_add (ifindex,
+ known_route->network, known_route->plen, known_route->gateway,
+ known_route->metric, known_route->mss))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+nm_platform_route_flush (int ifindex)
+{
+ return nm_platform_ip4_route_sync (ifindex, NULL)
+ && nm_platform_ip6_route_sync (ifindex, NULL);
+}
+
/******************************************************************/
static void
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 6a262465..fbc7976a 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -383,6 +383,9 @@ gboolean nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen,
gboolean nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, int metric);
gboolean nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, int metric);
gboolean nm_platform_ip6_route_exists (int ifindex, struct in6_addr network, int plen, int metric);
+gboolean nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes);
+gboolean nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes);
+gboolean nm_platform_route_flush (int ifindex);
#define auto_g_free __attribute__((cleanup(put_g_free)))
static void __attribute__((unused))