From a4c8f6b74733d0cf1d8c730aabd2ff5a7be0c124 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Fri, 30 Nov 2012 11:30:35 +0200 Subject: [PATCH] vpn: Add initial support for async connect Needed for agent VPN support. --- vpn/plugins/l2tp.c | 27 +++++++++++++++++++-------- vpn/plugins/openconnect.c | 23 ++++++++++++++++------- vpn/plugins/openvpn.c | 14 ++++++++++---- vpn/plugins/pptp.c | 24 +++++++++++++++++------- vpn/plugins/vpn.c | 5 +++-- vpn/plugins/vpn.h | 3 ++- vpn/plugins/vpnc.c | 18 +++++++++++++----- vpn/vpn-provider.c | 9 ++++++++- vpn/vpn-provider.h | 6 +++++- 9 files changed, 93 insertions(+), 36 deletions(-) diff --git a/vpn/plugins/l2tp.c b/vpn/plugins/l2tp.c index 4cb4b6a..05341d5 100644 --- a/vpn/plugins/l2tp.c +++ b/vpn/plugins/l2tp.c @@ -447,7 +447,8 @@ static void l2tp_died(struct connman_task *task, int exit_code, void *user_data) } static int l2tp_connect(struct vpn_provider *provider, - struct connman_task *task, const char *if_name) + struct connman_task *task, const char *if_name, + vpn_provider_connect_cb_t cb, void *user_data) { const char *host; char *l2tp_name, *pppd_name; @@ -455,13 +456,16 @@ static int l2tp_connect(struct vpn_provider *provider, int err; if (connman_task_set_notify(task, "getsec", - l2tp_get_sec, provider)) - return -ENOMEM; + l2tp_get_sec, provider) != 0) { + err = -ENOMEM; + goto done; + } host = vpn_provider_get_string(provider, "Host"); if (host == NULL) { connman_error("Host not set; cannot enable VPN"); - return -EINVAL; + err = -EINVAL; + goto done; } l2tp_name = g_strdup_printf("/var/run/connman/connman-xl2tpd.conf"); @@ -470,7 +474,8 @@ static int l2tp_connect(struct vpn_provider *provider, if (l2tp_fd < 0) { g_free(l2tp_name); connman_error("Error writing l2tp config"); - return -EIO; + err = -EIO; + goto done; } pppd_name = g_strdup_printf("/var/run/connman/connman-ppp-option.conf"); @@ -481,7 +486,8 @@ static int l2tp_connect(struct vpn_provider *provider, g_free(l2tp_name); g_free(pppd_name); close(l2tp_fd); - return -EIO; + err = -EIO; + goto done; } l2tp_write_config(provider, pppd_name, l2tp_fd); @@ -498,10 +504,15 @@ static int l2tp_connect(struct vpn_provider *provider, NULL, NULL, NULL); if (err < 0) { connman_error("l2tp failed to start"); - return -EIO; + err = -EIO; + goto done; } - return 0; +done: + if (cb != NULL) + cb(provider, user_data, err); + + return err; } static int l2tp_error_code(int exit_code) diff --git a/vpn/plugins/openconnect.c b/vpn/plugins/openconnect.c index 0f54108..143e175 100644 --- a/vpn/plugins/openconnect.c +++ b/vpn/plugins/openconnect.c @@ -161,21 +161,24 @@ static int oc_notify(DBusMessage *msg, struct vpn_provider *provider) } static int oc_connect(struct vpn_provider *provider, - struct connman_task *task, const char *if_name) + struct connman_task *task, const char *if_name, + vpn_provider_connect_cb_t cb, void *user_data) { const char *vpnhost, *vpncookie, *cafile, *certsha1, *mtu; - int fd, err; + int fd, err = 0; vpnhost = vpn_provider_get_string(provider, "Host"); if (!vpnhost) { connman_error("Host not set; cannot enable VPN"); - return -EINVAL; + err = -EINVAL; + goto done; } vpncookie = vpn_provider_get_string(provider, "OpenConnect.Cookie"); if (!vpncookie) { connman_error("OpenConnect.Cookie not set; cannot enable VPN"); - return -EINVAL; + err = -EINVAL; + goto done; } certsha1 = vpn_provider_get_string(provider, @@ -207,17 +210,23 @@ static int oc_connect(struct vpn_provider *provider, &fd, NULL, NULL); if (err < 0) { connman_error("openconnect failed to start"); - return -EIO; + err = -EIO; + goto done; } if (write(fd, vpncookie, strlen(vpncookie)) != (ssize_t)strlen(vpncookie) || write(fd, "\n", 1) != 1) { connman_error("openconnect failed to take cookie on stdin"); - return -EIO; + err = -EIO; + goto done; } - return 0; +done: + if (cb != NULL) + cb(provider, user_data, err); + + return err; } static int oc_save(struct vpn_provider *provider, GKeyFile *keyfile) diff --git a/vpn/plugins/openvpn.c b/vpn/plugins/openvpn.c index 84583cd..87549ca 100644 --- a/vpn/plugins/openvpn.c +++ b/vpn/plugins/openvpn.c @@ -229,10 +229,11 @@ static int task_append_config_data(struct vpn_provider *provider, } static int ov_connect(struct vpn_provider *provider, - struct connman_task *task, const char *if_name) + struct connman_task *task, const char *if_name, + vpn_provider_connect_cb_t cb, void *user_data) { const char *option; - int err, fd; + int err = 0, fd; option = vpn_provider_get_string(provider, "Host"); if (option == NULL) { @@ -304,10 +305,15 @@ static int ov_connect(struct vpn_provider *provider, NULL, &fd, &fd); if (err < 0) { connman_error("openvpn failed to start"); - return -EIO; + err = -EIO; + goto done; } - return 0; +done: + if (cb != NULL) + cb(provider, user_data, err); + + return err; } static struct vpn_driver vpn_driver = { diff --git a/vpn/plugins/pptp.c b/vpn/plugins/pptp.c index 6843793..1da5144 100644 --- a/vpn/plugins/pptp.c +++ b/vpn/plugins/pptp.c @@ -241,27 +241,32 @@ static void pptp_write_bool_option(struct connman_task *task, } static int pptp_connect(struct vpn_provider *provider, - struct connman_task *task, const char *if_name) + struct connman_task *task, const char *if_name, + vpn_provider_connect_cb_t cb, void *user_data) { const char *opt_s, *host; char *str; int err, i; if (connman_task_set_notify(task, "getsec", - pptp_get_sec, provider)) - return -ENOMEM; + pptp_get_sec, provider)) { + err = -ENOMEM; + goto done; + } host = vpn_provider_get_string(provider, "Host"); if (host == NULL) { connman_error("Host not set; cannot enable VPN"); - return -EINVAL; + err = -EINVAL; + goto done; } str = g_strdup_printf("%s %s --nolaunchpppd --loglevel 2", PPTP, host); if (str == NULL) { connman_error("can not allocate memory"); - return -ENOMEM; + err = -ENOMEM; + goto done; } connman_task_add_argument(task, "pty", str); @@ -299,10 +304,15 @@ static int pptp_connect(struct vpn_provider *provider, NULL, NULL, NULL); if (err < 0) { connman_error("pptp failed to start"); - return -EIO; + err = -EIO; + goto done; } - return 0; +done: + if (cb != NULL) + cb(provider, user_data, err); + + return err; } static int pptp_error_code(int exit_code) diff --git a/vpn/plugins/vpn.c b/vpn/plugins/vpn.c index d0b3381..66a75d2 100644 --- a/vpn/plugins/vpn.c +++ b/vpn/plugins/vpn.c @@ -353,7 +353,8 @@ exist_err: return ret; } -static int vpn_connect(struct vpn_provider *provider) +static int vpn_connect(struct vpn_provider *provider, + vpn_provider_connect_cb_t cb, void *user_data) { struct vpn_data *data = vpn_provider_get_data(provider); struct vpn_driver_data *vpn_driver_data; @@ -410,7 +411,7 @@ static int vpn_connect(struct vpn_provider *provider) } ret = vpn_driver_data->vpn_driver->connect(provider, data->task, - data->if_name); + data->if_name, cb, user_data); if (ret < 0) { stop_vpn(provider); connman_task_destroy(data->task); diff --git a/vpn/plugins/vpn.h b/vpn/plugins/vpn.h index 6693cdb..d1e322c 100644 --- a/vpn/plugins/vpn.h +++ b/vpn/plugins/vpn.h @@ -44,7 +44,8 @@ struct vpn_driver { int flags; int (*notify) (DBusMessage *msg, struct vpn_provider *provider); int (*connect) (struct vpn_provider *provider, - struct connman_task *task, const char *if_name); + struct connman_task *task, const char *if_name, + vpn_provider_connect_cb_t cb, void *user_data); void (*disconnect) (void); int (*error_code) (int exit_code); int (*save) (struct vpn_provider *provider, GKeyFile *keyfile); diff --git a/vpn/plugins/vpnc.c b/vpn/plugins/vpnc.c index 9fd1dec..9f69850 100644 --- a/vpn/plugins/vpnc.c +++ b/vpn/plugins/vpnc.c @@ -263,20 +263,23 @@ static int vc_save(struct vpn_provider *provider, GKeyFile *keyfile) } static int vc_connect(struct vpn_provider *provider, - struct connman_task *task, const char *if_name) + struct connman_task *task, const char *if_name, + vpn_provider_connect_cb_t cb, void *user_data) { const char *option; - int err, fd; + int err = 0, fd; option = vpn_provider_get_string(provider, "Host"); if (option == NULL) { connman_error("Host not set; cannot enable VPN"); - return -EINVAL; + err = -EINVAL; + goto done; } option = vpn_provider_get_string(provider, "VPNC.IPSec.ID"); if (option == NULL) { connman_error("Group not set; cannot enable VPN"); - return -EINVAL; + err = -EINVAL; + goto done; } connman_task_add_argument(task, "--non-inter", NULL); @@ -298,13 +301,18 @@ static int vc_connect(struct vpn_provider *provider, &fd, NULL, NULL); if (err < 0) { connman_error("vpnc failed to start"); - return -EIO; + err = -EIO; + goto done; } err = vc_write_config_data(provider, fd); close(fd); +done: + if (cb != NULL) + cb(provider, user_data, err); + return err; } diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c index f529122..1630dad 100644 --- a/vpn/vpn-provider.c +++ b/vpn/vpn-provider.c @@ -975,6 +975,12 @@ int __vpn_provider_disconnect(struct vpn_provider *provider) return 0; } +static void connect_cb(struct vpn_provider *provider, void *user_data, + int error) +{ + DBG("provider %p user %p error %d", provider, user_data, error); +} + int __vpn_provider_connect(struct vpn_provider *provider) { int err; @@ -982,7 +988,8 @@ int __vpn_provider_connect(struct vpn_provider *provider) DBG("provider %p", provider); if (provider->driver != NULL && provider->driver->connect != NULL) - err = provider->driver->connect(provider); + err = provider->driver->connect(provider, + connect_cb, NULL); else return -EOPNOTSUPP; diff --git a/vpn/vpn-provider.h b/vpn/vpn-provider.h index 0f139b0..b462042 100644 --- a/vpn/vpn-provider.h +++ b/vpn/vpn-provider.h @@ -101,12 +101,16 @@ int vpn_provider_append_route(struct vpn_provider *provider, const char *vpn_provider_get_driver_name(struct vpn_provider *provider); const char *vpn_provider_get_save_group(struct vpn_provider *provider); +typedef void (* vpn_provider_connect_cb_t) (struct vpn_provider *provider, + void *user_data, int error); + struct vpn_provider_driver { const char *name; enum vpn_provider_type type; int (*probe) (struct vpn_provider *provider); int (*remove) (struct vpn_provider *provider); - int (*connect) (struct vpn_provider *provider); + int (*connect) (struct vpn_provider *provider, + vpn_provider_connect_cb_t cb, void *user_data); int (*disconnect) (struct vpn_provider *provider); int (*save) (struct vpn_provider *provider, GKeyFile *keyfile); }; -- 2.7.4