[PATCH v0 7/9] vpn: Introduce VPN_FLAG_NO_DAEMON

Daniel Wagner wagi at monom.org
Fri Jul 19 04:21:36 PDT 2019


Add VPN_FLAG_NO_DAEMON to skip forking and monitoring an external
task. Since the state machine inside vpn.c is driven by the external
events we need to fake the event via update_provider_state(). We can't
directly progress the state machine because we are still processing an
D-Bus message after calling vpn_driver->connect(). So defer the call
to update_provider_state via the idle loop.
---
 vpn/plugins/vpn.c | 51 +++++++++++++++++++++++++++++++++++++++++++----
 vpn/plugins/vpn.h |  3 ++-
 2 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/vpn/plugins/vpn.c b/vpn/plugins/vpn.c
index eef8550e6a9c..96a06299be09 100644
--- a/vpn/plugins/vpn.c
+++ b/vpn/plugins/vpn.c
@@ -89,7 +89,7 @@ static int stop_vpn(struct vpn_provider *provider)
 	vpn_driver_data = g_hash_table_lookup(driver_hash, name);
 
 	if (vpn_driver_data && vpn_driver_data->vpn_driver &&
-			vpn_driver_data->vpn_driver->flags == VPN_FLAG_NO_TUN)
+			vpn_driver_data->vpn_driver->flags & VPN_FLAG_NO_TUN)
 		return 0;
 
 	memset(&ifr, 0, sizeof(ifr));
@@ -540,6 +540,27 @@ static void vpn_task_setup(gpointer user_data)
 		connman_error("error setting uid %d %s", uid, strerror(errno));
 }
 
+
+static gboolean update_provider_state(gpointer data)
+{
+	struct vpn_provider *provider = data;
+	struct vpn_data *vpn_data;
+	int index;
+
+	DBG("");
+
+	vpn_data = vpn_provider_get_data(provider);
+
+	index = vpn_provider_get_index(provider);
+	DBG("index to watch %d", index);
+	vpn_provider_ref(provider);
+	vpn_data->watch = vpn_rtnl_add_newlink_watch(index,
+						vpn_newlink, provider);
+	connman_inet_ifup(index);
+
+	return FALSE;
+}
+
 static int vpn_connect(struct vpn_provider *provider,
 			vpn_provider_connect_cb_t cb,
 			const char *dbus_sender, void *user_data)
@@ -595,7 +616,7 @@ static int vpn_connect(struct vpn_provider *provider,
 		goto exist_err;
 	}
 
-	if (vpn_driver_data->vpn_driver->flags != VPN_FLAG_NO_TUN) {
+	if (!(vpn_driver_data->vpn_driver->flags & VPN_FLAG_NO_TUN)) {
 		if (vpn_driver_data->vpn_driver->device_flags) {
 			tun_flags = vpn_driver_data->vpn_driver->device_flags(provider);
 		}
@@ -604,6 +625,26 @@ static int vpn_connect(struct vpn_provider *provider,
 			goto exist_err;
 	}
 
+
+	if (vpn_driver_data && vpn_driver_data->vpn_driver &&
+			vpn_driver_data->vpn_driver->flags & VPN_FLAG_NO_DAEMON) {
+
+		ret = vpn_driver_data->vpn_driver->connect(provider,
+						NULL, NULL, NULL, NULL, NULL);
+		if (ret) {
+			stop_vpn(provider);
+			goto exist_err;
+		}
+
+		DBG("%s started with dev %s",
+			vpn_driver_data->provider_driver.name, data->if_name);
+
+		data->state = VPN_STATE_CONNECT;
+
+		g_timeout_add(1, update_provider_state, provider);
+		return -EINPROGRESS;
+	}
+
 	vpn_plugin_data =
 		vpn_settings_get_vpn_plugin_config(vpn_driver_data->name);
 	data->task = connman_task_create(vpn_driver_data->program,
@@ -689,7 +730,8 @@ static int vpn_disconnect(struct vpn_provider *provider)
 		vpn_provider_set_state(provider, VPN_PROVIDER_STATE_DISCONNECT);
 	}
 
-	connman_task_stop(data->task);
+	if (data->task)
+		connman_task_stop(data->task);
 
 	return 0;
 }
@@ -713,7 +755,8 @@ static int vpn_remove(struct vpn_provider *provider)
 		data->watch = 0;
 	}
 
-	connman_task_stop(data->task);
+	if (data->task)
+		connman_task_stop(data->task);
 
 	g_usleep(G_USEC_PER_SEC);
 	stop_vpn(provider);
diff --git a/vpn/plugins/vpn.h b/vpn/plugins/vpn.h
index 265fd82f62e4..71e04f618fd2 100644
--- a/vpn/plugins/vpn.h
+++ b/vpn/plugins/vpn.h
@@ -28,7 +28,8 @@
 extern "C" {
 #endif
 
-#define VPN_FLAG_NO_TUN	1
+#define VPN_FLAG_NO_TUN     1
+#define VPN_FLAG_NO_DAEMON  2
 
 enum vpn_state {
 	VPN_STATE_UNKNOWN       = 0,
-- 
2.20.1


More information about the connman mailing list