From: Daniel Wagner Date: Fri, 17 Dec 2010 14:52:03 +0000 (+0100) Subject: openvpn: Append routes X-Git-Tag: 0.65~30 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=16df8f375026ff34697d4053814457fa101e9418;p=platform%2Fupstream%2Fconnman.git openvpn: Append routes --- diff --git a/plugins/openvpn.c b/plugins/openvpn.c index 15169bd..7cea4e6 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; }