summaryrefslogtreecommitdiff
path: root/vpn
diff options
context:
space:
mode:
authorSeonah Moon <seonah1.moon@samsung.com>2018-01-08 13:42:54 +0900
committerSeonah Moon <seonah1.moon@samsung.com>2018-01-08 13:43:31 +0900
commit9362752a471a5c892d679548fbf2828d5fc5684b (patch)
tree83c7d29a28556906938f5c2198d81e2d35f86f92 /vpn
parent22633ced6225d294ce8483efbf2b39ea0c0c1b65 (diff)
downloadconnman-9362752a471a5c892d679548fbf2828d5fc5684b.tar.gz
connman-9362752a471a5c892d679548fbf2828d5fc5684b.tar.bz2
connman-9362752a471a5c892d679548fbf2828d5fc5684b.zip
Imported Upstream version 1.35upstream/1.35
Change-Id: I174854914d9fd06a813270b57d1f7bc2bac63c6a Signed-off-by: Seonah Moon <seonah1.moon@samsung.com>
Diffstat (limited to 'vpn')
-rw-r--r--vpn/connman-vpn.conf8
-rw-r--r--vpn/connman-vpn.service.in5
-rw-r--r--vpn/plugins/l2tp.c9
-rw-r--r--vpn/plugins/openconnect.c2
-rw-r--r--vpn/plugins/openvpn.c92
-rw-r--r--vpn/plugins/pptp.c7
-rw-r--r--vpn/plugins/vpn.c44
-rw-r--r--vpn/plugins/vpn.h1
-rw-r--r--vpn/plugins/vpnc.c34
-rw-r--r--vpn/vpn-config.c4
-rw-r--r--vpn/vpn-provider.c68
-rw-r--r--vpn/vpn-provider.h2
12 files changed, 238 insertions, 38 deletions
diff --git a/vpn/connman-vpn.conf b/vpn/connman-vpn.conf
new file mode 100644
index 00000000..99a96ce8
--- /dev/null
+++ b/vpn/connman-vpn.conf
@@ -0,0 +1,8 @@
+[General]
+
+# Set input request timeout. Default is 300 seconds
+# The request for inputs like passphrase will timeout
+# after certain amount of time. Use this setting to
+# increase the value in case of different user
+# interface designs.
+# InputRequestTimeout = 300
diff --git a/vpn/connman-vpn.service.in b/vpn/connman-vpn.service.in
index de65a70d..e98fb714 100644
--- a/vpn/connman-vpn.service.in
+++ b/vpn/connman-vpn.service.in
@@ -1,13 +1,14 @@
[Unit]
Description=ConnMan VPN service
-Requires=dbus.socket
-After=dbus.socket
[Service]
Type=dbus
BusName=net.connman.vpn
ExecStart=@sbindir@/connman-vpnd -n
StandardOutput=null
+CapabilityBoundingSet=CAP_KILL CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
+ProtectHome=read-only
+ProtectSystem=full
[Install]
WantedBy=multi-user.target
diff --git a/vpn/plugins/l2tp.c b/vpn/plugins/l2tp.c
index 22f9dcf8..a0d22c4d 100644
--- a/vpn/plugins/l2tp.c
+++ b/vpn/plugins/l2tp.c
@@ -108,13 +108,13 @@ struct {
{ "PPPD.RefuseMSCHAP2", "refuse-mschapv2", OPT_PPPD, NULL, OPT_BOOL },
{ "PPPD.NoBSDComp", "nobsdcomp", OPT_PPPD, NULL, OPT_BOOL },
{ "PPPD.NoPcomp", "nopcomp", OPT_PPPD, NULL, OPT_BOOL },
- { "PPPD.UseAccomp", "accomp", OPT_PPPD, NULL, OPT_BOOL },
+ { "PPPD.UseAccomp", "noaccomp", OPT_PPPD, NULL, OPT_BOOL },
{ "PPPD.NoDeflate", "nodeflate", OPT_PPPD, NULL, OPT_BOOL },
{ "PPPD.ReqMPPE", "require-mppe", OPT_PPPD, NULL, OPT_BOOL },
{ "PPPD.ReqMPPE40", "require-mppe-40", OPT_PPPD, NULL, OPT_BOOL },
{ "PPPD.ReqMPPE128", "require-mppe-128", OPT_PPPD, NULL, OPT_BOOL },
{ "PPPD.ReqMPPEStateful", "mppe-stateful", OPT_PPPD, NULL, OPT_BOOL },
- { "PPPD.NoVJ", "no-vj-comp", OPT_PPPD, NULL, OPT_BOOL },
+ { "PPPD.NoVJ", "novj", OPT_PPPD, NULL, OPT_BOOL },
};
static DBusConnection *connection;
@@ -497,8 +497,9 @@ static void request_input_reply(DBusMessage *reply, void *user_data)
DBG("provider %p", l2tp_reply->provider);
- if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
- error = dbus_message_get_error_name(reply);
+ if (!reply || dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
+ if (reply)
+ error = dbus_message_get_error_name(reply);
goto done;
}
diff --git a/vpn/plugins/openconnect.c b/vpn/plugins/openconnect.c
index 5feaed9d..87679bfa 100644
--- a/vpn/plugins/openconnect.c
+++ b/vpn/plugins/openconnect.c
@@ -315,7 +315,7 @@ static void request_input_cookie_reply(DBusMessage *reply, void *user_data)
DBG("provider %p", data->provider);
- if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
+ if (!reply || dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
goto err;
if (!vpn_agent_check_reply_has_dict(reply))
diff --git a/vpn/plugins/openvpn.c b/vpn/plugins/openvpn.c
index 9ee5795c..e3395097 100644
--- a/vpn/plugins/openvpn.c
+++ b/vpn/plugins/openvpn.c
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <stdio.h>
#include <net/if.h>
+#include <linux/if_tun.h>
#include <glib.h>
@@ -71,6 +72,8 @@ struct {
{ "OpenVPN.CompLZO", "--comp-lzo", 0 },
{ "OpenVPN.RemoteCertTls", "--remote-cert-tls", 1 },
{ "OpenVPN.ConfigFile", "--config", 1 },
+ { "OpenVPN.DeviceType", NULL, 1 },
+ { "OpenVPN.Verb", "--verb", 1 },
};
struct nameserver_entry {
@@ -156,7 +159,7 @@ static int ov_notify(DBusMessage *msg, struct vpn_provider *provider)
{
DBusMessageIter iter, dict;
const char *reason, *key, *value;
- char *address = NULL, *gateway = NULL, *peer = NULL;
+ char *address = NULL, *gateway = NULL, *peer = NULL, *netmask = NULL;
struct connman_ipaddress *ipaddress;
GSList *nameserver_list = NULL;
@@ -192,6 +195,9 @@ static int ov_notify(DBusMessage *msg, struct vpn_provider *provider)
if (!strcmp(key, "ifconfig_local"))
address = g_strdup(value);
+ if (!strcmp(key, "ifconfig_netmask"))
+ netmask = g_strdup(value);
+
if (!strcmp(key, "ifconfig_remote"))
peer = g_strdup(value);
@@ -218,11 +224,12 @@ static int ov_notify(DBusMessage *msg, struct vpn_provider *provider)
g_free(address);
g_free(gateway);
g_free(peer);
+ g_free(netmask);
return VPN_STATE_FAILURE;
}
- connman_ipaddress_set_ipv4(ipaddress, address, NULL, gateway);
+ connman_ipaddress_set_ipv4(ipaddress, address, netmask, gateway);
connman_ipaddress_set_peer(ipaddress, peer);
vpn_provider_set_ipaddress(provider, ipaddress);
@@ -256,6 +263,7 @@ static int ov_notify(DBusMessage *msg, struct vpn_provider *provider)
g_free(address);
g_free(gateway);
g_free(peer);
+ g_free(netmask);
connman_ipaddress_free(ipaddress);
return VPN_STATE_CONNECT;
@@ -306,13 +314,54 @@ static int task_append_config_data(struct vpn_provider *provider,
return 0;
}
+static gboolean can_read_data(GIOChannel *chan,
+ GIOCondition cond, gpointer data)
+{
+ void (*cbf)(const char *format, ...) = data;
+ gchar *str;
+ gsize size;
+
+ if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+ return FALSE;
+
+ g_io_channel_read_line(chan, &str, &size, NULL, NULL);
+ cbf(str);
+ g_free(str);
+
+ return TRUE;
+}
+
+static int setup_log_read(int stdout_fd, int stderr_fd)
+{
+ GIOChannel *chan;
+ int watch;
+
+ chan = g_io_channel_unix_new(stdout_fd);
+ g_io_channel_set_close_on_unref(chan, TRUE);
+ watch = g_io_add_watch(chan, G_IO_IN | G_IO_NVAL | G_IO_ERR | G_IO_HUP,
+ can_read_data, connman_debug);
+ g_io_channel_unref(chan);
+
+ if (watch == 0)
+ return -EIO;
+
+ chan = g_io_channel_unix_new(stderr_fd);
+ g_io_channel_set_close_on_unref(chan, TRUE);
+ watch = g_io_add_watch(chan, G_IO_IN | G_IO_NVAL | G_IO_ERR | G_IO_HUP,
+ can_read_data, connman_error);
+ g_io_channel_unref(chan);
+
+ return watch == 0? -EIO : 0;
+}
+
static int ov_connect(struct vpn_provider *provider,
struct connman_task *task, const char *if_name,
vpn_provider_connect_cb_t cb, const char *dbus_sender,
void *user_data)
{
const char *option;
- int err = 0, fd;
+ int stdout_fd, stderr_fd;
+ int err = 0;
option = vpn_provider_get_string(provider, "Host");
if (!option) {
@@ -341,8 +390,6 @@ static int ov_connect(struct vpn_provider *provider,
connman_task_add_argument(task, "--client", NULL);
}
- connman_task_add_argument(task, "--syslog", NULL);
-
connman_task_add_argument(task, "--script-security", "2");
connman_task_add_argument(task, "--up",
@@ -362,7 +409,15 @@ static int ov_connect(struct vpn_provider *provider,
connman_task_get_path(task));
connman_task_add_argument(task, "--dev", if_name);
- connman_task_add_argument(task, "--dev-type", "tun");
+ option = vpn_provider_get_string(provider, "OpenVPN.DeviceType");
+ if (option) {
+ connman_task_add_argument(task, "--dev-type", option);
+ } else {
+ /*
+ * Default to tun for backwards compatibility.
+ */
+ connman_task_add_argument(task, "--dev-type", "tun");
+ }
connman_task_add_argument(task, "--persist-tun", NULL);
@@ -379,15 +434,15 @@ static int ov_connect(struct vpn_provider *provider,
*/
connman_task_add_argument(task, "--ping-restart", "0");
- fd = fileno(stderr);
err = connman_task_run(task, vpn_died, provider,
- NULL, &fd, &fd);
+ NULL, &stdout_fd, &stderr_fd);
if (err < 0) {
connman_error("openvpn failed to start");
err = -EIO;
goto done;
}
+ err = setup_log_read(stdout_fd, stderr_fd);
done:
if (cb)
cb(provider, user_data, err);
@@ -395,10 +450,31 @@ done:
return err;
}
+static int ov_device_flags(struct vpn_provider *provider)
+{
+ const char *option;
+
+ option = vpn_provider_get_string(provider, "OpenVPN.DeviceType");
+ if (!option) {
+ return IFF_TUN;
+ }
+
+ if (g_str_equal(option, "tap")) {
+ return IFF_TAP;
+ }
+
+ if (!g_str_equal(option, "tun")) {
+ connman_warn("bad OpenVPN.DeviceType value, falling back to tun");
+ }
+
+ return IFF_TUN;
+}
+
static struct vpn_driver vpn_driver = {
.notify = ov_notify,
.connect = ov_connect,
.save = ov_save,
+ .device_flags = ov_device_flags,
};
static int openvpn_init(void)
diff --git a/vpn/plugins/pptp.c b/vpn/plugins/pptp.c
index 9f2a214d..27b1d508 100644
--- a/vpn/plugins/pptp.c
+++ b/vpn/plugins/pptp.c
@@ -77,7 +77,7 @@ struct {
{ "PPPD.RequirMPPE40", "require-mppe-40", NULL, OPT_BOOL },
{ "PPPD.RequirMPPE128", "require-mppe-128", NULL, OPT_BOOL },
{ "PPPD.RequirMPPEStateful", "mppe-stateful", NULL, OPT_BOOL },
- { "PPPD.NoVJ", "no-vj-comp", NULL, OPT_BOOL },
+ { "PPPD.NoVJ", "novj", NULL, OPT_BOOL },
};
static DBusConnection *connection;
@@ -289,8 +289,9 @@ static void request_input_reply(DBusMessage *reply, void *user_data)
DBG("provider %p", pptp_reply->provider);
- if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
- error = dbus_message_get_error_name(reply);
+ if (!reply || dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
+ if (reply)
+ error = dbus_message_get_error_name(reply);
goto done;
}
diff --git a/vpn/plugins/vpn.c b/vpn/plugins/vpn.c
index b438d06e..9a423850 100644
--- a/vpn/plugins/vpn.c
+++ b/vpn/plugins/vpn.c
@@ -56,6 +56,7 @@ struct vpn_data {
unsigned int watch;
enum vpn_state state;
struct connman_task *task;
+ int tun_flags;
};
struct vpn_driver_data {
@@ -89,7 +90,7 @@ static int stop_vpn(struct vpn_provider *provider)
return 0;
memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+ ifr.ifr_flags = data->tun_flags | IFF_NO_PI;
sprintf(ifr.ifr_name, "%s", data->if_name);
fd = open("/dev/net/tun", O_RDWR | O_CLOEXEC);
@@ -195,6 +196,34 @@ int vpn_set_ifname(struct vpn_provider *provider, const char *ifname)
return 0;
}
+static int vpn_set_state(struct vpn_provider *provider,
+ enum vpn_provider_state state)
+{
+ struct vpn_data *data = vpn_provider_get_data(provider);
+ if (!data)
+ return -EINVAL;
+
+ switch (state) {
+ case VPN_PROVIDER_STATE_UNKNOWN:
+ return -EINVAL;
+ case VPN_PROVIDER_STATE_IDLE:
+ data->state = VPN_STATE_IDLE;
+ break;
+ case VPN_PROVIDER_STATE_CONNECT:
+ case VPN_PROVIDER_STATE_READY:
+ data->state = VPN_STATE_CONNECT;
+ break;
+ case VPN_PROVIDER_STATE_DISCONNECT:
+ data->state = VPN_STATE_DISCONNECT;
+ break;
+ case VPN_PROVIDER_STATE_FAILURE:
+ data->state = VPN_STATE_FAILURE;
+ break;
+ }
+
+ return 0;
+}
+
static void vpn_newlink(unsigned flags, unsigned change, void *user_data)
{
struct vpn_provider *provider = user_data;
@@ -307,7 +336,7 @@ static DBusMessage *vpn_notify(struct connman_task *task,
return NULL;
}
-static int vpn_create_tun(struct vpn_provider *provider)
+static int vpn_create_tun(struct vpn_provider *provider, int flags)
{
struct vpn_data *data = vpn_provider_get_data(provider);
struct ifreq ifr;
@@ -327,7 +356,7 @@ static int vpn_create_tun(struct vpn_provider *provider)
}
memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+ ifr.ifr_flags = flags | IFF_NO_PI;
for (i = 0; i < 256; i++) {
sprintf(ifr.ifr_name, "vpn%d", i);
@@ -343,6 +372,7 @@ static int vpn_create_tun(struct vpn_provider *provider)
goto exist_err;
}
+ data->tun_flags = flags;
data->if_name = (char *)g_strdup(ifr.ifr_name);
if (!data->if_name) {
connman_error("Failed to allocate memory");
@@ -384,7 +414,7 @@ static int vpn_connect(struct vpn_provider *provider,
struct vpn_data *data = vpn_provider_get_data(provider);
struct vpn_driver_data *vpn_driver_data;
const char *name;
- int ret = 0;
+ int ret = 0, tun_flags = IFF_TUN;
enum vpn_state state = VPN_STATE_UNKNOWN;
if (data)
@@ -432,7 +462,10 @@ static int vpn_connect(struct vpn_provider *provider,
}
if (vpn_driver_data->vpn_driver->flags != VPN_FLAG_NO_TUN) {
- ret = vpn_create_tun(provider);
+ if (vpn_driver_data->vpn_driver->device_flags) {
+ tun_flags = vpn_driver_data->vpn_driver->device_flags(provider);
+ }
+ ret = vpn_create_tun(provider, tun_flags);
if (ret < 0)
goto exist_err;
}
@@ -572,6 +605,7 @@ int vpn_register(const char *name, struct vpn_driver *vpn_driver,
data->provider_driver.probe = vpn_probe;
data->provider_driver.remove = vpn_remove;
data->provider_driver.save = vpn_save;
+ data->provider_driver.set_state = vpn_set_state;
if (!driver_hash)
driver_hash = g_hash_table_new_full(g_str_hash,
diff --git a/vpn/plugins/vpn.h b/vpn/plugins/vpn.h
index bf56728d..cb94bdcd 100644
--- a/vpn/plugins/vpn.h
+++ b/vpn/plugins/vpn.h
@@ -50,6 +50,7 @@ struct vpn_driver {
void (*disconnect) (struct vpn_provider *provider);
int (*error_code) (struct vpn_provider *provider, int exit_code);
int (*save) (struct vpn_provider *provider, GKeyFile *keyfile);
+ int (*device_flags) (struct vpn_provider *provider);
};
int vpn_register(const char *name, struct vpn_driver *driver,
diff --git a/vpn/plugins/vpnc.c b/vpn/plugins/vpnc.c
index 09674bd8..af9dbe76 100644
--- a/vpn/plugins/vpnc.c
+++ b/vpn/plugins/vpnc.c
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <stdio.h>
#include <net/if.h>
+#include <linux/if_tun.h>
#include <glib.h>
@@ -72,7 +73,7 @@ struct {
{ "VPNC.LocalPort", "Local Port", "0", OPT_STRING, true, },
{ "VPNC.CiscoPort", "Cisco UDP Encapsulation Port", "0", OPT_STRING,
true },
- { "VPNC.AppVersion", "Application Version", NULL, OPT_STRING, true },
+ { "VPNC.AppVersion", "Application version", NULL, OPT_STRING, true },
{ "VPNC.NATTMode", "NAT Traversal Mode", "cisco-udp", OPT_STRING,
true },
{ "VPNC.DPDTimeout", "DPD idle timeout (our side)", NULL, OPT_STRING,
@@ -287,7 +288,15 @@ static int vc_connect(struct vpn_provider *provider,
connman_task_add_argument(task, "--no-detach", NULL);
connman_task_add_argument(task, "--ifname", if_name);
- connman_task_add_argument(task, "--ifmode", "tun");
+ option = vpn_provider_get_string(provider, "VPNC.DeviceType");
+ if (option) {
+ connman_task_add_argument(task, "--ifmode", option);
+ } else {
+ /*
+ * Default to tun for backwards compatibility.
+ */
+ connman_task_add_argument(task, "--ifmode", "tun");
+ }
connman_task_add_argument(task, "--script",
SCRIPTDIR "/openconnect-script");
@@ -329,11 +338,32 @@ static int vc_error_code(struct vpn_provider *provider, int exit_code)
}
}
+static int vc_device_flags(struct vpn_provider *provider)
+{
+ const char *option;
+
+ option = vpn_provider_get_string(provider, "VPNC.DeviceType");
+ if (!option) {
+ return IFF_TUN;
+ }
+
+ if (g_str_equal(option, "tap")) {
+ return IFF_TAP;
+ }
+
+ if (!g_str_equal(option, "tun")) {
+ connman_warn("bad VPNC.DeviceType value, falling back to tun");
+ }
+
+ return IFF_TUN;
+}
+
static struct vpn_driver vpn_driver = {
.notify = vc_notify,
.connect = vc_connect,
.error_code = vc_error_code,
.save = vc_save,
+ .device_flags = vc_device_flags,
};
static int vpnc_init(void)
diff --git a/vpn/vpn-config.c b/vpn/vpn-config.c
index 293c64e0..c88a99ab 100644
--- a/vpn/vpn-config.c
+++ b/vpn/vpn-config.c
@@ -484,12 +484,12 @@ static void config_notify_handler(struct inotify_event *event,
if (event->mask & IN_CREATE)
return;
- if (event->mask & IN_DELETE) {
+ if (event->mask & (IN_DELETE | IN_MOVED_FROM)) {
g_hash_table_remove(config_table, ident);
return;
}
- if (event->mask & IN_MODIFY) {
+ if (event->mask & (IN_MODIFY | IN_MOVED_TO)) {
struct vpn_config *config;
char *path = get_dir();
diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c
index 16c0c2be..d2b3e3aa 100644
--- a/vpn/vpn-provider.c
+++ b/vpn/vpn-provider.c
@@ -501,6 +501,12 @@ static DBusMessage *do_connect(DBusConnection *conn, DBusMessage *msg,
return NULL;
}
+static DBusMessage *do_connect2(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ return do_connect(conn, msg, data);
+}
+
static DBusMessage *do_disconnect(DBusConnection *conn, DBusMessage *msg,
void *data)
{
@@ -527,6 +533,9 @@ static const GDBusMethodTable connection_methods[] = {
GDBUS_ARGS({ "name", "s" }), NULL,
clear_property) },
{ GDBUS_ASYNC_METHOD("Connect", NULL, NULL, do_connect) },
+ { GDBUS_ASYNC_METHOD("Connect2",
+ GDBUS_ARGS({ "dbus_sender", "s" }),
+ NULL, do_connect2) },
{ GDBUS_METHOD("Disconnect", NULL, NULL, do_disconnect) },
{ },
};
@@ -549,6 +558,12 @@ static void resolv_result(GResolvResultStatus status,
provider->host_ip = g_strdupv(results);
vpn_provider_unref(provider);
+
+ /* Remove the resolver here so that it will not be left
+ * hanging around and cause double free in unregister_provider()
+ */
+ g_resolv_unref(provider->resolv);
+ provider->resolv = NULL;
}
static void provider_resolv_host_addr(struct vpn_provider *provider)
@@ -680,14 +695,11 @@ static struct vpn_route *get_route(char *route_str)
in_addr_t addr;
struct in_addr netmask_in;
unsigned char prefix_len = 32;
+ char *ptr;
+ long int value = strtol(netmask, &ptr, 10);
- if (netmask) {
- char *ptr;
- long int value = strtol(netmask, &ptr, 10);
- if (ptr != netmask && *ptr == '\0' &&
- value <= 32)
- prefix_len = value;
- }
+ if (ptr != netmask && *ptr == '\0' && value <= 32)
+ prefix_len = value;
addr = 0xffffffff << (32 - prefix_len);
netmask_in.s_addr = htonl(addr);
@@ -796,16 +808,20 @@ static gchar **create_network_list(GSList *networks, gsize *count)
{
GSList *list;
gchar **result = NULL;
+ gchar **prev_result;
unsigned int num_elems = 0;
for (list = networks; list; list = g_slist_next(list)) {
struct vpn_route *route = list->data;
int family;
+ prev_result = result;
result = g_try_realloc(result,
(num_elems + 1) * sizeof(gchar *));
- if (!result)
+ if (!result) {
+ g_free(prev_result);
return NULL;
+ }
switch (route->family) {
case AF_INET:
@@ -826,9 +842,12 @@ static gchar **create_network_list(GSList *networks, gsize *count)
num_elems++;
}
+ prev_result = result;
result = g_try_realloc(result, (num_elems + 1) * sizeof(gchar *));
- if (!result)
+ if (!result) {
+ g_free(prev_result);
return NULL;
+ }
result[num_elems] = NULL;
*count = num_elems;
@@ -1081,10 +1100,22 @@ int __vpn_provider_connect(struct vpn_provider *provider, DBusMessage *msg)
DBG("provider %p", provider);
if (provider->driver && provider->driver->connect) {
+ const char *dbus_sender = dbus_message_get_sender(msg);
+
dbus_message_ref(msg);
+
+ if (dbus_message_has_signature(msg,
+ DBUS_TYPE_STRING_AS_STRING)) {
+ const char *sender = NULL;
+
+ dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING,
+ &sender, DBUS_TYPE_INVALID);
+ if (sender && sender[0])
+ dbus_sender = sender;
+ }
+
err = provider->driver->connect(provider, connect_cb,
- dbus_message_get_sender(msg),
- msg);
+ dbus_sender, msg);
} else
return -EOPNOTSUPP;
@@ -1560,6 +1591,9 @@ int vpn_provider_indicate_error(struct vpn_provider *provider,
break;
}
+ if (provider->driver && provider->driver->set_state)
+ provider->driver->set_state(provider, provider->state);
+
return 0;
}
@@ -1605,6 +1639,18 @@ static void unregister_provider(gpointer data)
connection_unregister(provider);
+ /* If the provider has any DNS resolver queries pending,
+ * they need to be cleared here because the unref will not
+ * be able to do that (because the provider_resolv_host_addr()
+ * has increased the ref count by 1). This is quite rare as
+ * normally the resolving either returns a value or has a
+ * timeout which clears the memory. Typically resolv_result() will
+ * unref the provider but in this case that call has not yet
+ * happened.
+ */
+ if (provider->resolv)
+ vpn_provider_unref(provider);
+
vpn_provider_unref(provider);
}
diff --git a/vpn/vpn-provider.h b/vpn/vpn-provider.h
index 8105d7f1..bdc5f5c1 100644
--- a/vpn/vpn-provider.h
+++ b/vpn/vpn-provider.h
@@ -132,6 +132,8 @@ struct vpn_provider_driver {
void *user_data);
int (*disconnect) (struct vpn_provider *provider);
int (*save) (struct vpn_provider *provider, GKeyFile *keyfile);
+ int (*set_state)(struct vpn_provider *provider,
+ enum vpn_provider_state state);
};
int vpn_provider_driver_register(struct vpn_provider_driver *driver);