This options allows the user to specify a network device the OpenVPN process
  should use when making a connection or binding to an address. This translates
  in setting the SO_BINDTODEVICE option to the corresponding socket (on Linux).

  When for example using VRFs on Linux [0] this allows making connections using
  the non-default VRF and having the tun/tap interface in the default VRF.

  Thanks to David Ahern (Cumulus Networks) for insights on this.

  [0] 
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/networking/vrf.txt

Signed-off-by: Maximilian Wilhelm <max@sdn.clinic>
---
 src/openvpn/init.c    |  1 +
 src/openvpn/options.c | 10 ++++++++++
 src/openvpn/options.h |  1 +
 src/openvpn/socket.c  | 10 ++++++++++
 src/openvpn/socket.h  |  2 ++
 5 files changed, 24 insertions(+)

diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index 2af25c1..dd1747f 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -3445,6 +3445,7 @@ do_init_socket_1(struct context *c, const int mode)
                             c->options.rcvbuf,
                             c->options.sndbuf,
                             c->options.mark,
+                            c->options.bind_dev,
                             &c->c2.server_poll_interval,
                             sockflags);
 }
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 3484f7d..6b36269 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -294,6 +294,9 @@ static const char usage_message[] =
 #if defined(TARGET_LINUX) && HAVE_DECL_SO_MARK
     "--mark value    : Mark encrypted packets being sent with value. The mark 
value\n"
     "                  can be matched in policy routing and packetfilter 
rules.\n"
+    "--bind-dev dev  : Bind to the given device when making connection to a 
peer or\n"
+    "                  listening for connections. This allows sending 
encrypted packets\n"
+    "                  via a VRF present on the system.\n"
 #endif
     "--txqueuelen n  : Set the tun/tap TX queue length to n (Linux only).\n"
 #ifdef ENABLE_MEMSTATS
@@ -6064,6 +6067,13 @@ add_option(struct options *options,
             }
         }
     }
+#ifdef TARGET_LINUX
+    else if (streq (p[0], "bind-dev") && p[1])
+    {
+        VERIFY_PERMISSION (OPT_P_SOCKFLAGS);
+        options->bind_dev = p[1];
+    }
+#endif
     else if (streq(p[0], "txqueuelen") && p[1] && !p[2])
     {
         VERIFY_PERMISSION(OPT_P_GENERAL);
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index 375a4fc..c83a46a 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -352,6 +352,7 @@ struct options
 
     /* mark value */
     int mark;
+    char *bind_dev;
 
     /* socket flags */
     unsigned int sockflags;
diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
index f2fb54d..fd92d52 100644
--- a/src/openvpn/socket.c
+++ b/src/openvpn/socket.c
@@ -1138,6 +1138,14 @@ create_socket(struct link_socket *sock, struct addrinfo 
*addr)
     /* set socket to --mark packets with given value */
     socket_set_mark(sock->sd, sock->mark);
 
+#if defined(TARGET_LINUX)
+    if (sock->bind_dev)
+    {
+        msg (M_INFO, "Using bind-dev %s", sock->bind_dev);
+        setsockopt (sock->sd, SOL_SOCKET, SO_BINDTODEVICE, sock->bind_dev, 
strlen (sock->bind_dev) + 1);
+    }
+#endif
+
     bind_local(sock, addr->ai_family);
 }
 
@@ -1880,6 +1888,7 @@ link_socket_init_phase1(struct link_socket *sock,
                         int rcvbuf,
                         int sndbuf,
                         int mark,
+                        const char *bind_dev,
                         struct event_timeout *server_poll_timeout,
                         unsigned int sockflags)
 {
@@ -1906,6 +1915,7 @@ link_socket_init_phase1(struct link_socket *sock,
 
     sock->sockflags = sockflags;
     sock->mark = mark;
+    sock->bind_dev = bind_dev;
 
     sock->info.proto = proto;
     sock->info.af = af;
diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h
index 38e5138..8db9e8b 100644
--- a/src/openvpn/socket.h
+++ b/src/openvpn/socket.h
@@ -212,6 +212,7 @@ struct link_socket
 #define SF_GETADDRINFO_DGRAM (1<<4)
     unsigned int sockflags;
     int mark;
+    const char *bind_dev;
 
     /* for stream sockets */
     struct stream_buf stream_buf;
@@ -326,6 +327,7 @@ link_socket_init_phase1(struct link_socket *sock,
                         int rcvbuf,
                         int sndbuf,
                         int mark,
+                        const char *bind_dev,
                         struct event_timeout *server_poll_timeout,
                         unsigned int sockflags);
 /* Reenable uncrustify *INDENT-ON* */
-- 
2.1.4



_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to