summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2013-03-25 16:58:57 +0200
committerPatrik Flykt <patrik.flykt@linux.intel.com>2013-03-27 16:00:19 +0200
commita1ef3bc2f851d56d1899c0eb5676e491b2a98ff5 (patch)
treeb3d99710a29fb7d40d24f9aeb3351efe0a6579b0
parentff0d2b9c6e427035d5fdf1d412b80892294b6ead (diff)
downloadconnman-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.
-rw-r--r--vpn/plugins/openvpn.c88
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);