summaryrefslogtreecommitdiff
path: root/vpn
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2013-03-25 14:58:57 (GMT)
committerPatrik Flykt <patrik.flykt@linux.intel.com>2013-03-27 14:00:19 (GMT)
commita1ef3bc2f851d56d1899c0eb5676e491b2a98ff5 (patch)
treeb3d99710a29fb7d40d24f9aeb3351efe0a6579b0 /vpn
parentff0d2b9c6e427035d5fdf1d412b80892294b6ead (diff)
downloadconnman-a1ef3bc2f851d56d1899c0eb5676e491b2a98ff5.zip
connman-a1ef3bc2f851d56d1899c0eb5676e491b2a98ff5.tar.gz
connman-a1ef3bc2f851d56d1899c0eb5676e491b2a98ff5.tar.bz2
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.c88
1 files changed, 71 insertions, 17 deletions
diff --git a/vpn/plugins/openvpn.c b/vpn/plugins/openvpn.c
index 87549ca..d938eb1 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);