summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorDaniel Wagner <daniel.wagner@bmw-carit.de>2010-12-17 15:52:03 +0100
committerSamuel Ortiz <sameo@linux.intel.com>2010-12-21 01:34:50 +0100
commit16df8f375026ff34697d4053814457fa101e9418 (patch)
treeb64e611d5d35571099f009b729db3eaa08f7b7e8 /plugins
parent0159e2d07b2934d3229b9510f0ab5ba9c6711617 (diff)
downloadconnman-16df8f375026ff34697d4053814457fa101e9418.tar.gz
connman-16df8f375026ff34697d4053814457fa101e9418.tar.bz2
connman-16df8f375026ff34697d4053814457fa101e9418.zip
openvpn: Append routes
Diffstat (limited to 'plugins')
-rw-r--r--plugins/openvpn.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/plugins/openvpn.c b/plugins/openvpn.c
index 15169bde..7cea4e6e 100644
--- a/plugins/openvpn.c
+++ b/plugins/openvpn.c
@@ -42,12 +42,112 @@
static DBusConnection *connection;
+struct ov_route {
+ char *host;
+ char *netmask;
+ char *gateway;
+};
+
+static void destroy_route(gpointer user_data)
+{
+ struct ov_route *route = user_data;
+
+ g_free(route->host);
+ g_free(route->netmask);
+ g_free(route->gateway);
+ g_free(route);
+}
+
+static void ov_provider_append_routes(gpointer key, gpointer value,
+ gpointer user_data)
+{
+ struct ov_route *route = value;
+ struct connman_provider *provider = user_data;
+
+ connman_provider_append_route(provider, route->host, route->netmask,
+ route->gateway);
+}
+
+static struct ov_route *ov_route_lookup(const char *key, const char *prefix_key,
+ GHashTable *routes)
+{
+ if (g_str_has_prefix(key, prefix_key)) {
+ unsigned long idx;
+ const char *start;
+ char *end;
+ struct ov_route *route;
+
+ start = key + strlen(prefix_key);
+ idx = g_ascii_strtoull(start, &end, 10);
+
+ if (idx == 0 && start == end) {
+ connman_error("string conversion failed %s", start);
+ return NULL;
+ }
+
+ route = g_hash_table_lookup(routes, GINT_TO_POINTER(idx));
+ if (route == NULL) {
+ route = g_try_new0(struct ov_route, 1);
+ if (route == NULL) {
+ connman_error("out of memory");
+ return NULL;
+ }
+
+ g_hash_table_replace(routes, GINT_TO_POINTER(idx),
+ route);
+ }
+
+ return route;
+ }
+
+ return NULL;
+}
+
+static void ov_append_route(const char *key, const char *value, GHashTable *routes)
+{
+ struct ov_route *route;
+
+ /*
+ * OpenVPN pushes routing tupples (host, nw, gw) as several
+ * environment values, e.g.
+ *
+ * route_gateway_2 = 10.242.2.13
+ * route_netmask_2 = 255.255.0.0
+ * route_network_2 = 192.168.0.0
+ * route_gateway_1 = 10.242.2.13
+ * route_netmask_1 = 255.255.255.255
+ * route_network_1 = 10.242.2.1
+ *
+ * The hash table is used to group the separate environment
+ * variables together. It also makes sure all tupples are
+ * complete even when OpenVPN pushes the information in a
+ * wrong order (unlikely).
+ */
+
+ route = ov_route_lookup(key, "route_network_", routes);
+ if (route != NULL) {
+ route->host = g_strdup(value);
+ return;
+ }
+
+ route = ov_route_lookup(key, "route_netmask_", routes);
+ if (route != NULL) {
+ route->netmask = g_strdup(value);
+ return;
+ }
+
+ route = ov_route_lookup(key, "route_gateway_", routes);
+ if (route != NULL)
+ route->gateway = g_strdup(value);
+}
+
static int ov_notify(DBusMessage *msg, struct connman_provider *provider)
{
DBusMessageIter iter, dict;
const char *reason, *key, *value;
const char *domain = NULL;
char *dns_entries = NULL;
+ GHashTable *routes;
dbus_message_iter_init(msg, &iter);
@@ -71,6 +171,9 @@ static int ov_notify(DBusMessage *msg, struct connman_provider *provider)
dbus_message_iter_recurse(&iter, &dict);
+ routes = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, destroy_route);
+
while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
DBusMessageIter entry;
@@ -115,6 +218,8 @@ static int ov_notify(DBusMessage *msg, struct connman_provider *provider)
g_strfreev(options);
}
+ ov_append_route(key, value, routes);
+
dbus_message_iter_next(&dict);
}
@@ -123,6 +228,10 @@ static int ov_notify(DBusMessage *msg, struct connman_provider *provider)
g_free(dns_entries);
}
+ g_hash_table_foreach(routes, ov_provider_append_routes, provider);
+
+ g_hash_table_destroy(routes);
+
return VPN_STATE_CONNECT;
}