Message ID | 1593427748-29801-2-git-send-email-max@rfc2324.org |
---|---|
State | Accepted |
Headers | show |
Series | [Openvpn-devel,v2,1/2] Add --bind-dev option. | expand |
Acked-by: Gert Doering <gert@greenie.muc.de> Your patch has been applied to the master branch. I have stared at the code (looks reasonable) and run t_client tests on Linux and FreeBSD (pass, no major surprise). I have not actually tested the functionality, because I do not have a test rig with VRF (or multiple ethernet links) around. From what I found so far, what SO_BINDTODEVICE does is "ensure that packets sent via that socket go out via the specified interface, and only that interface" and "packets coming in have been received on that interface". Besides "a network interface" you can also specify the name of a "VRF device" (which seems to be a Linux abstraction to group together "Interfaces and Routes" under one umbrella). So you can use this for VRFs ("--bind-dev outer-vrf") or to select one particular interface (*and* routes) inside "global" or "VRF". I have tested the latter ("--bind-to lo") which makes connection setup *fail* - obviously. Trying to bind to nonexistant devices gives a proper error message in v2 now 2020-06-29 13:27:03 WARN: setsockopt SO_BINDTODEVICE=MyTunnelIsLongerThanYours failed: No such device (errno=19) Googling for SO_BINDTODEVICE shows lots of confusion on how this is used and what it does, but I consider the kernel documentation to be authoritative (Documentation/networking/vrf.txt) and that says "what you do is correct": Applications ------------ Applications that are to work within a VRF need to bind their socket to the VRF device: setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, dev, strlen(dev)+1); (note the "strlen(dev)+1" part, and "not a struct ifreq") Your patch has been applied to the master branch. commit 19d3c602e7a3881cf7c2244b7c40b9958c0b7ebc Author: Maximilian Wilhelm Date: Mon Jun 29 12:49:07 2020 +0200 Add --bind-dev option. Signed-off-by: Maximilian Wilhelm <max@sdn.clinic> Acked-by: Gert Doering <gert@greenie.muc.de> Message-Id: <1593427748-29801-2-git-send-email-max@rfc2324.org> URL: https://www.mail-archive.com/search?l=mid&q=1593427748-29801-2-git-send-email-max@rfc2324.org Signed-off-by: Gert Doering <gert@greenie.muc.de> -- kind regards, Gert Doering
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 9580d1d..34e2bfd 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 @@ -6084,6 +6087,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..61463bc 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -1138,6 +1138,18 @@ 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); + if (setsockopt (sock->sd, SOL_SOCKET, SO_BINDTODEVICE, sock->bind_dev, strlen (sock->bind_dev) + 1) != 0) + { + msg(M_WARN|M_ERRNO, "WARN: setsockopt SO_BINDTODEVICE=%s failed", sock->bind_dev); + } + + } +#endif + bind_local(sock, addr->ai_family); } @@ -1880,6 +1892,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 +1919,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* */