diff options
author | Jukka Rissanen <jukka.rissanen@linux.intel.com> | 2013-03-25 16:58:57 +0200 |
---|---|---|
committer | Patrik Flykt <patrik.flykt@linux.intel.com> | 2013-03-27 16:00:19 +0200 |
commit | a1ef3bc2f851d56d1899c0eb5676e491b2a98ff5 (patch) | |
tree | b3d99710a29fb7d40d24f9aeb3351efe0a6579b0 /vpn | |
parent | ff0d2b9c6e427035d5fdf1d412b80892294b6ead (diff) | |
download | connman-a1ef3bc2f851d56d1899c0eb5676e491b2a98ff5.tar.gz connman-a1ef3bc2f851d56d1899c0eb5676e491b2a98ff5.tar.bz2 connman-a1ef3bc2f851d56d1899c0eb5676e491b2a98ff5.zip |
openvpn: Set the nameservers in correct order
The nameservers that we get from OpenVPN server can be received
in any order. Make sure that we sort them in correct order before
sending them to connmand.
Diffstat (limited to 'vpn')
-rw-r--r-- | vpn/plugins/openvpn.c | 88 |
1 files changed, 71 insertions, 17 deletions
diff --git a/vpn/plugins/openvpn.c b/vpn/plugins/openvpn.c index 87549ca0..d938eb14 100644 --- a/vpn/plugins/openvpn.c +++ b/vpn/plugins/openvpn.c @@ -23,6 +23,7 @@ #include <config.h> #endif +#include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> @@ -72,13 +73,19 @@ struct { { "OpenVPN.ConfigFile", "--config", 1 }, }; -static void ov_append_dns_entries(const char *key, const char *value, - char **dns_entries) +struct nameserver_entry { + int id; + char *nameserver; +}; + +static struct nameserver_entry *ov_append_dns_entries(const char *key, + const char *value) { + struct nameserver_entry *entry = NULL; gchar **options; if (g_str_has_prefix(key, "foreign_option_") == FALSE) - return; + return NULL; options = g_strsplit(value, " ", 3); if (options[0] != NULL && @@ -87,28 +94,48 @@ static void ov_append_dns_entries(const char *key, const char *value, !strcmp(options[1], "DNS") && options[2] != NULL) { - if (*dns_entries != NULL) { - char *tmp; + entry = g_try_new(struct nameserver_entry, 1); + if (entry == NULL) + return NULL; - tmp = g_strjoin(" ", *dns_entries, - options[2], NULL); - g_free(*dns_entries); - *dns_entries = tmp; - } else { - *dns_entries = g_strdup(options[2]); - } + entry->nameserver = g_strdup(options[2]); + entry->id = atoi(key + 15); /* foreign_option_XXX */ } g_strfreev(options); + + return entry; +} + +static gint cmp_ns(gconstpointer a, gconstpointer b) +{ + struct nameserver_entry *entry_a = (struct nameserver_entry *)a; + struct nameserver_entry *entry_b = (struct nameserver_entry *)b; + + if (entry_a->id < entry_b->id) + return -1; + + if (entry_a->id > entry_b->id) + return 1; + + return 0; +} + +static void free_ns_entry(gpointer data) +{ + struct nameserver_entry *entry = data; + + g_free(entry->nameserver); + g_free(entry); } static int ov_notify(DBusMessage *msg, struct vpn_provider *provider) { DBusMessageIter iter, dict; const char *reason, *key, *value; - char *nameservers = NULL; char *address = NULL, *gateway = NULL, *peer = NULL; struct connman_ipaddress *ipaddress; + GSList *nameserver_list = NULL; dbus_message_iter_init(msg, &iter); @@ -126,6 +153,7 @@ static int ov_notify(DBusMessage *msg, struct vpn_provider *provider) dbus_message_iter_recurse(&iter, &dict); while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + struct nameserver_entry *ns_entry = NULL; DBusMessageIter entry; dbus_message_iter_recurse(&dict, &entry); @@ -153,14 +181,16 @@ static int ov_notify(DBusMessage *msg, struct vpn_provider *provider) if (g_str_has_prefix(key, "route_") == TRUE) vpn_provider_append_route(provider, key, value); - ov_append_dns_entries(key, value, &nameservers); + if ((ns_entry = ov_append_dns_entries(key, value)) != NULL) + nameserver_list = g_slist_prepend(nameserver_list, + ns_entry); dbus_message_iter_next(&dict); } ipaddress = connman_ipaddress_alloc(AF_INET); if (ipaddress == NULL) { - g_free(nameservers); + g_slist_free_full(nameserver_list, free_ns_entry); g_free(address); g_free(gateway); g_free(peer); @@ -172,9 +202,33 @@ static int ov_notify(DBusMessage *msg, struct vpn_provider *provider) connman_ipaddress_set_peer(ipaddress, peer); vpn_provider_set_ipaddress(provider, ipaddress); - vpn_provider_set_nameservers(provider, nameservers); + if (nameserver_list != NULL) { + char *nameservers = NULL; + GSList *tmp; + + nameserver_list = g_slist_sort(nameserver_list, cmp_ns); + for (tmp = nameserver_list; tmp != NULL; + tmp = g_slist_next(tmp)) { + struct nameserver_entry *ns = tmp->data; + + if (nameservers == NULL) { + nameservers = g_strdup(ns->nameserver); + } else { + char *str; + str = g_strjoin(" ", nameservers, + ns->nameserver, NULL); + g_free(nameservers); + nameservers = str; + } + } + + g_slist_free_full(nameserver_list, free_ns_entry); + + vpn_provider_set_nameservers(provider, nameservers); + + g_free(nameservers); + } - g_free(nameservers); g_free(address); g_free(gateway); g_free(peer); |