[network-manager-openconnect] Create persistent tundev on demand for each connection.
- From: David Woodhouse <dwmw2 src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [network-manager-openconnect] Create persistent tundev on demand for each connection.
- Date: Thu, 29 Mar 2012 12:41:59 +0000 (UTC)
commit 85d9cebaf76c28d356bb0eb8da0cd364ab8f6b78
Author: David Woodhouse <David Woodhouse intel com>
Date: Thu Mar 29 13:40:21 2012 +0100
Create persistent tundev on demand for each connection.
We theoretically support having more than one VPN connection at a time.
That's not going to work too well if we create *one* tun device at
startup, and use that device for all the connections.
Create the device at connection time, and tear it down when openconnect
dies.
src/nm-openconnect-service.c | 178 +++++++++++++++++++++---------------------
1 files changed, 90 insertions(+), 88 deletions(-)
---
diff --git a/src/nm-openconnect-service.c b/src/nm-openconnect-service.c
index 168d154..bbf4193 100644
--- a/src/nm-openconnect-service.c
+++ b/src/nm-openconnect-service.c
@@ -50,6 +50,7 @@ G_DEFINE_TYPE (NMOPENCONNECTPlugin, nm_openconnect_plugin, NM_TYPE_VPN_PLUGIN)
typedef struct {
GPid pid;
+ char *tun_name;
} NMOPENCONNECTPluginPrivate;
#define NM_OPENCONNECT_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_OPENCONNECT_PLUGIN, NMOPENCONNECTPluginPrivate))
@@ -97,7 +98,6 @@ static ValidProperty valid_secrets[] = {
static uid_t tun_owner;
static gid_t tun_group;
-static char *tun_name = NULL;
typedef struct ValidateInfo {
ValidProperty *table;
@@ -210,8 +210,86 @@ nm_openconnect_secrets_validate (NMSettingVPN *s_vpn, GError **error)
return *error ? FALSE : TRUE;
}
+static char *
+create_persistent_tundev(void)
+{
+ struct passwd *pw;
+ struct ifreq ifr;
+ int fd;
+ int i;
+
+ pw = getpwnam(NM_OPENCONNECT_USER);
+ if (!pw)
+ return NULL;
+
+ tun_owner = pw->pw_uid;
+ tun_group = pw->pw_gid;
+
+ fd = open("/dev/net/tun", O_RDWR);
+ if (fd < 0) {
+ perror("open /dev/net/tun");
+ exit(EXIT_FAILURE);
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+
+ for (i = 0; i < 256; i++) {
+ sprintf(ifr.ifr_name, "vpn%d", i);
+
+ if (!ioctl(fd, TUNSETIFF, (void *)&ifr))
+ break;
+ }
+ if (i == 256)
+ exit(EXIT_FAILURE);
+
+ if (ioctl(fd, TUNSETOWNER, tun_owner) < 0) {
+ perror("TUNSETOWNER");
+ exit(EXIT_FAILURE);
+ }
+
+ if (ioctl(fd, TUNSETPERSIST, 1)) {
+ perror("TUNSETPERSIST");
+ exit(EXIT_FAILURE);
+ }
+ close(fd);
+ g_warning("Created tundev %s\n", ifr.ifr_name);
+ return g_strdup(ifr.ifr_name);
+}
+
+static void
+destroy_persistent_tundev(char *tun_name)
+{
+ struct ifreq ifr;
+ int fd;
+
+ fd = open("/dev/net/tun", O_RDWR);
+ if (fd < 0) {
+ perror("open /dev/net/tun");
+ exit(EXIT_FAILURE);
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+ strcpy(ifr.ifr_name, tun_name);
+
+ if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) {
+ perror("TUNSETIFF");
+ exit(EXIT_FAILURE);
+ }
+
+ if (ioctl(fd, TUNSETPERSIST, 0)) {
+ perror("TUNSETPERSIST");
+ exit(EXIT_FAILURE);
+ }
+ g_warning("Destroyed tundev %s\n", tun_name);
+ close(fd);
+}
+
static void openconnect_drop_child_privs(gpointer user_data)
{
+ char *tun_name = user_data;
+
if (tun_name) {
if (initgroups(NM_OPENCONNECT_USER, tun_group) ||
setgid(tun_group) || setuid(tun_owner)) {
@@ -244,6 +322,12 @@ openconnect_watch_cb (GPid pid, gint status, gpointer user_data)
waitpid (priv->pid, NULL, WNOHANG);
priv->pid = 0;
+ if (priv->tun_name) {
+ destroy_persistent_tundev (priv->tun_name);
+ g_free (priv->tun_name);
+ priv->tun_name = NULL;
+ }
+
/* Must be after data->state is set since signals use data->state */
switch (error) {
case 2:
@@ -266,6 +350,7 @@ nm_openconnect_start_openconnect_binary (NMOPENCONNECTPlugin *plugin,
NMSettingVPN *s_vpn,
GError **error)
{
+ NMOPENCONNECTPluginPrivate *priv = NM_OPENCONNECT_PLUGIN_GET_PRIVATE (plugin);
GPid pid;
const char **openconnect_binary = NULL;
GPtrArray *openconnect_argv;
@@ -345,9 +430,10 @@ nm_openconnect_start_openconnect_binary (NMOPENCONNECTPlugin *plugin,
g_ptr_array_add (openconnect_argv, (gpointer) "--script");
g_ptr_array_add (openconnect_argv, (gpointer) NM_OPENCONNECT_HELPER_PATH);
- if (tun_name) {
+ priv->tun_name = create_persistent_tundev ();
+ if (priv->tun_name) {
g_ptr_array_add (openconnect_argv, (gpointer) "--interface");
- g_ptr_array_add (openconnect_argv, (gpointer) tun_name);
+ g_ptr_array_add (openconnect_argv, (gpointer) priv->tun_name);
}
g_ptr_array_add (openconnect_argv, (gpointer) props_vpn_gw);
@@ -356,7 +442,7 @@ nm_openconnect_start_openconnect_binary (NMOPENCONNECTPlugin *plugin,
if (!g_spawn_async_with_pipes (NULL, (char **) openconnect_argv->pdata, NULL,
G_SPAWN_DO_NOT_REAP_CHILD,
- openconnect_drop_child_privs, NULL,
+ openconnect_drop_child_privs, priv->tun_name,
&pid, &stdin_fd, NULL, NULL, error)) {
g_ptr_array_free (openconnect_argv, TRUE);
g_warning ("openconnect failed to start. error: '%s'", (*error)->message);
@@ -507,86 +593,6 @@ quit_mainloop (NMOPENCONNECTPlugin *plugin, gpointer user_data)
g_main_loop_quit ((GMainLoop *) user_data);
}
-static void
-create_persistent_tundev(void)
-{
- struct passwd *pw;
- struct ifreq ifr;
- int fd;
- int i;
-
- pw = getpwnam(NM_OPENCONNECT_USER);
- if (!pw)
- return;
-
- tun_owner = pw->pw_uid;
- tun_group = pw->pw_gid;
-
- fd = open("/dev/net/tun", O_RDWR);
- if (fd < 0) {
- perror("open /dev/net/tun");
- exit(EXIT_FAILURE);
- }
-
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
-
- for (i = 0; i < 256; i++) {
- if (tun_name)
- g_free(tun_name);
-
- sprintf(ifr.ifr_name, "vpn%d", i);
-
- if (!ioctl(fd, TUNSETIFF, (void *)&ifr))
- break;
- }
- if (i == 256)
- exit(EXIT_FAILURE);
-
- if (ioctl(fd, TUNSETOWNER, tun_owner) < 0) {
- perror("TUNSETOWNER");
- exit(EXIT_FAILURE);
- }
-
- if (ioctl(fd, TUNSETPERSIST, 1)) {
- perror("TUNSETPERSIST");
- exit(EXIT_FAILURE);
- }
- tun_name = g_strdup(ifr.ifr_name);
- close(fd);
-}
-
-static void
-destroy_persistent_tundev(void)
-{
- struct ifreq ifr;
- int fd;
-
- if (!tun_name)
- return;
-
- fd = open("/dev/net/tun", O_RDWR);
- if (fd < 0) {
- perror("open /dev/net/tun");
- exit(EXIT_FAILURE);
- }
-
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
- strcpy(ifr.ifr_name, tun_name);
-
- if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) {
- perror("TUNSETIFF");
- exit(EXIT_FAILURE);
- }
-
- if (ioctl(fd, TUNSETPERSIST, 0)) {
- perror("TUNSETPERSIST");
- exit(EXIT_FAILURE);
- }
- close(fd);
-}
-
int main (int argc, char *argv[])
{
NMOPENCONNECTPlugin *plugin;
@@ -597,8 +603,6 @@ int main (int argc, char *argv[])
if (system ("/sbin/modprobe tun") == -1)
exit (EXIT_FAILURE);
- create_persistent_tundev();
-
plugin = nm_openconnect_plugin_new ();
if (!plugin)
exit (EXIT_FAILURE);
@@ -614,7 +618,5 @@ int main (int argc, char *argv[])
g_main_loop_unref (main_loop);
g_object_unref (plugin);
- destroy_persistent_tundev();
-
exit (EXIT_SUCCESS);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]