diff options
author | Seonah Moon <seonah1.moon@samsung.com> | 2018-01-23 14:50:50 +0900 |
---|---|---|
committer | Seonah Moon <seonah1.moon@samsung.com> | 2018-01-23 14:50:55 +0900 |
commit | 30602f521a85820a9f6b7ac04876400e00c68b15 (patch) | |
tree | f035a4fcc014a034f3b492886d1e8395f327fd25 /vpn | |
parent | a079cfe6f815f8c69055de834d1ccbdf1fd94ba7 (diff) | |
parent | 9362752a471a5c892d679548fbf2828d5fc5684b (diff) | |
download | connman-30602f521a85820a9f6b7ac04876400e00c68b15.tar.gz connman-30602f521a85820a9f6b7ac04876400e00c68b15.tar.bz2 connman-30602f521a85820a9f6b7ac04876400e00c68b15.zip |
Updated connman to version 1.35
Change-Id: I13526fbf80296a79be15548fc226a308941ac9ec
Signed-off-by: Taesub Kim <taesub.kim@samsung.com>
Diffstat (limited to 'vpn')
-rw-r--r-- | vpn/connman-vpn.conf | 8 | ||||
-rwxr-xr-x | vpn/connman-vpn.service.in | 4 | ||||
-rwxr-xr-x | vpn/main.c | 5 | ||||
-rwxr-xr-x | vpn/plugins/l2tp.c | 9 | ||||
-rwxr-xr-x | vpn/plugins/openconnect.c | 2 | ||||
-rwxr-xr-x | vpn/plugins/openvpn.c | 92 | ||||
-rwxr-xr-x | vpn/plugins/pptp.c | 7 | ||||
-rwxr-xr-x | vpn/plugins/vpn.c | 44 | ||||
-rwxr-xr-x | vpn/plugins/vpn.h | 1 | ||||
-rwxr-xr-x | vpn/plugins/vpnc.c | 34 | ||||
-rwxr-xr-x | vpn/vpn-config.c | 4 | ||||
-rwxr-xr-x | vpn/vpn-provider.c | 68 | ||||
-rwxr-xr-x | vpn/vpn-provider.h | 2 |
13 files changed, 243 insertions, 37 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 03eaf226..a8f2948f 100755 --- a/vpn/connman-vpn.service.in +++ b/vpn/connman-vpn.service.in @@ -11,8 +11,10 @@ BusName=net.connman.vpn SmackProcessLabel=System ExecStart=@bindir@/connman-vpnd -n StandardOutput=null -Capabilities=cap_setgid,cap_net_admin,cap_net_bind_service,cap_net_broadcast,cap_net_raw,cap_dac_override=i +Capabilities=cap_net_admin,cap_net_bind_service,cap_net_broadcast,cap_net_raw,cap_dac_override=i SecureBits=keep-caps +ProtectHome=read-only +ProtectSystem=full [Install] WantedBy=multi-user.target @@ -256,6 +256,11 @@ unsigned int connman_timeout_browser_launch(void) return connman_vpn_settings.timeout_browserlaunch; } +const char *connman_option_get_string(const char *key) +{ + return NULL; +} + int main(int argc, char *argv[]) { GOptionContext *context; diff --git a/vpn/plugins/l2tp.c b/vpn/plugins/l2tp.c index 22f9dcf8..a0d22c4d 100755 --- 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 100755 --- 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 e226afd1..d115df6e 100755 --- 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); @@ -381,15 +436,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); @@ -397,10 +452,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 100755 --- 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 e65dacac..f6e24c4c 100755 --- 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; @@ -357,7 +386,7 @@ static void vpn_event(struct vpn_provider *provider, int state) } #endif -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; @@ -377,7 +406,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); @@ -393,6 +422,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"); @@ -434,7 +464,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) @@ -482,7 +512,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; } @@ -628,6 +661,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 af7e8f8e..1888d5ff 100755 --- a/vpn/plugins/vpn.h +++ b/vpn/plugins/vpn.h @@ -57,6 +57,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 100755 --- 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 a5be332d..5f0e749a 100755 --- a/vpn/vpn-config.c +++ b/vpn/vpn-config.c @@ -498,12 +498,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 925f6997..67239e40 100755 --- 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 100755 --- 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); |