[PATCH v2 02/16] vpn: Add initial support for async connect

Jukka Rissanen jukka.rissanen at linux.intel.com
Tue Nov 27 02:51:34 PST 2012


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);
 };
-- 
1.7.11.4




More information about the connman mailing list