From e15b874fdd05e9952e94e36292b57071e96127ed Mon Sep 17 00:00:00 2001
From: Mark Nunberg <mnunb...@haskalah.org>
List-Post: openvpn-devel@lists.sourceforge.net
Date: Sun, 26 Feb 2012 09:37:33 -0800
Subject: [PATCH] Allow management socket over inherited file descriptor
Allows a direct management channel over a forked-and-execed openvpn
process (or possibly other means) instead of having to use a bound TCP
or UNIX socket. Helpful for wrapper applications and advanced scripts,
so that they leave less clutter in the local connection table and/or
filesystem
---
manage.c | 22 ++++++++++++++++++++--
manage.h | 1 +
options.c | 9 ++++++++-
3 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/manage.c b/manage.c
index ce6fae7..f597ed9 100644
--- a/manage.c
+++ b/manage.c
@@ -1587,7 +1587,7 @@ man_listen (struct management *man)
}
else
#endif
- {
+ {
man->connection.sd_top = create_socket_tcp ();
socket_bind (man->connection.sd_top, &man->settings.local,
"MANAGEMENT");
}
@@ -1612,9 +1612,11 @@ man_listen (struct management *man)
}
else
#endif
+ {
msg (D_MANAGEMENT, "MANAGEMENT: TCP Socket listening on %s",
print_sockaddr (&man->settings.local, &gc));
}
+ }
#ifdef WIN32
man_start_ne32 (man);
@@ -1623,6 +1625,16 @@ man_listen (struct management *man)
gc_free (&gc);
}
+static void man_connect_from_sockfd(struct management *man)
+{
+ /*We have a socket already opened for us. Simple enough*/
+ man->connection.sd_top = SOCKET_UNDEFINED;
+ man->connection.state = MS_INITIAL;
+ man->connection.sd_cli = man->settings.local.addr.in4.sin_port;
+ man_record_peer_info(man);
+ man_new_connection_post(man, "Connected from sockfd");
+}
+
static void
man_connect (struct management *man)
{
@@ -2029,6 +2041,10 @@ man_settings_init (struct man_settings *ms,
sockaddr_unix_init (&ms->local_unix, addr);
else
#endif
+ if(ms->flags & MF_SOCKFD) {
+ ms->local.addr.in4.sin_port = atoi(addr);
+ }
+ else
{
/*
* Initialize socket address
@@ -2111,7 +2127,9 @@ man_connection_init (struct management *man)
/*
* Listen/connect socket
*/
- if (man->settings.flags & MF_CONNECT_AS_CLIENT)
+ if(man->settings.flags & MF_SOCKFD)
+ man_connect_from_sockfd(man);
+ else if (man->settings.flags & MF_CONNECT_AS_CLIENT)
man_connect (man);
else
man_listen (man);
diff --git a/manage.h b/manage.h
index f681f8d..ab939ff 100644
--- a/manage.h
+++ b/manage.h
@@ -339,6 +339,7 @@ struct management *management_init (void);
#if MANAGEMENT_QUERY_REMOTE
#define MF_QUERY_REMOTE (1<<11)
#endif
+#define MF_SOCKFD (1<<12)
bool management_open (struct management *man,
const char *addr,
diff --git a/options.c b/options.c
index 736495e..07a2972 100644
--- a/options.c
+++ b/options.c
@@ -371,6 +371,10 @@ static const char usage_message[] =
" To listen on a unix domain socket, specific the
pathname\n"
" in place of ip and use 'unix' as the port number.\n"
#endif
+ " To specify a numeric file descriptor of a connected\n"
+ " socket (in the case of openvpn running as a forked
process)\n"
+ " specify the file descriptor number as the
pathname, and \n"
+ " 'sockfd' as the port number\n"
"--management-client : Management interface will connect as a TCP
client to\n"
" ip/port rather than listen as a TCP server.\n"
"--management-query-passwords : Query management channel for private
key\n"
@@ -4076,7 +4080,10 @@ add_option (struct options *options,
msg (msglevel, "MANAGEMENT: this platform does not support unix
domain sockets");
goto err;
#endif
- }
+ } else if(streq(p[2], "sockfd")) {
+ options->management_flags |= MF_SOCKFD;
+ /*Check to see if socket address is too big..*/
+ }
else
{
port = atoi (p[2]);
--
1.7.2.5