summaryrefslogtreecommitdiff
path: root/vpn/plugins/openvpn.c
diff options
context:
space:
mode:
Diffstat (limited to 'vpn/plugins/openvpn.c')
-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);