Message ID | 20221026164522.3773718-1-arne@rfc2549.org |
---|---|
State | Changes Requested |
Headers | show |
Series | [Openvpn-devel,v2,1/3] Move dco_installed from sock->info to sock->info.lsa.actual | expand |
Hi, > @@ -1190,7 +1190,7 @@ link_socket_write(struct link_socket *sock, > struct buffer *buf, > struct link_socket_actual *to) > { > - if (proto_is_udp(sock->info.proto) || sock->info.dco_installed) > + if (proto_is_udp(sock->info.proto) || to->dco_installed) > { Previously we used to check the dco flag from sock->info and now it is changed to "to", which is a separate member in c->c2 (c->c2.to_link_addr vs c->c2.link_socket). Why not use "sock->info.lsa->actual.dco_installed" ? My understanding is that this patch only moves the flag to a different place and is not supposed to change the behavior. Besides, below we call link_socket_write_win32(), which down the stack checks dco flag from "sock", not from "to": static inline int link_socket_write_win32(struct link_socket *sock, struct buffer *buf, struct link_socket_actual *to) { int err = 0; int status = 0; sockethandle_t sh = { .s = sock->sd, .is_handle = sock->info.lsa->actual.dco_installed }; This doesn't look consistent. -Lev
Hi, On 26/10/2022 18:45, Arne Schwabe wrote: > For tcp this makes no difference as the remote address of the > socket never changes. For udp this allows OpenVPN to differentiate > if a reconnecting client is using the same address as before or > from a different one. This allow sending via the normal userspace > socket in that case. > > Patch v2: fix windows code path > > Signed-off-by: Arne Schwabe <arne@rfc2549.org> I couldn't test this patch extensively, but it looks good to me. This basically completes what I discussed with Arne some weeks ago. Acked-by: Antonio Quartulli <a@unstable.cc> However, please ensure to get this patch through the test rig before merging. Regards, > --- > src/openvpn/dco.c | 7 ++++--- > src/openvpn/dco_linux.c | 2 +- > src/openvpn/forward.c | 8 ++++---- > src/openvpn/init.c | 2 +- > src/openvpn/mtcp.c | 6 +++--- > src/openvpn/socket.c | 8 ++++---- > src/openvpn/socket.h | 12 ++++++------ > 7 files changed, 23 insertions(+), 22 deletions(-) > > diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c > index a76cdd0cd..1f402bfc2 100644 > --- a/src/openvpn/dco.c > +++ b/src/openvpn/dco.c > @@ -448,7 +448,7 @@ dco_p2p_add_new_peer(struct context *c) > } > > c->c2.tls_multi->dco_peer_added = true; > - c->c2.link_socket->info.dco_installed = true; > + c->c2.link_socket->info.lsa->actual.dco_installed = true; > > return 0; > } > @@ -522,7 +522,7 @@ dco_multi_add_new_peer(struct multi_context *m, struct multi_instance *mi) > { > struct context *c = &mi->context; > > - int peer_id = mi->context.c2.tls_multi->peer_id; > + int peer_id = c->c2.tls_multi->peer_id; > struct sockaddr *remoteaddr, *localaddr = NULL; > struct sockaddr_storage local = { 0 }; > int sd = c->c2.link_socket->sd; > @@ -531,6 +531,7 @@ dco_multi_add_new_peer(struct multi_context *m, struct multi_instance *mi) > { > /* the remote address will be inferred from the TCP socket endpoint */ > remoteaddr = NULL; > + c->c2.link_socket->info.lsa->actual.dco_installed = true; > } > else > { > @@ -575,7 +576,7 @@ dco_multi_add_new_peer(struct multi_context *m, struct multi_instance *mi) > { > msg(D_DCO|M_ERRNO, "error closing TCP socket after DCO handover"); > } > - c->c2.link_socket->info.dco_installed = true; > + c->c2.link_socket->info.lsa->actual.dco_installed = true; > c->c2.link_socket->sd = SOCKET_UNDEFINED; > } > > diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c > index 98e10507b..109358205 100644 > --- a/src/openvpn/dco_linux.c > +++ b/src/openvpn/dco_linux.c > @@ -285,7 +285,7 @@ ovpn_nl_cb_finish(struct nl_msg (*msg) __attribute__ ((unused)), void *arg) > * > * We pass the error code to the user by means of a variable pointed by *arg > * (supplied by the user when setting this callback) and we parse the kernel > - * reply to see if it contains a human readable error. If found, it is printed. > + * reply to see if it contains a human-readable error. If found, it is printed. > */ > static int > ovpn_nl_cb_error(struct sockaddr_nl (*nla) __attribute__ ((unused)), > diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c > index 20d9a7598..622be8411 100644 > --- a/src/openvpn/forward.c > +++ b/src/openvpn/forward.c > @@ -1643,13 +1643,13 @@ process_ip_header(struct context *c, unsigned int flags, struct buffer *buf) > * standard Overlapped I/O. > * > * Hide that complexity (...especially if more platforms show up > - * in future...) in a small inline function. > + * in the future...) in a small inline function. > */ > static inline bool > -should_use_dco_socket(struct link_socket *sock) > +should_use_dco_socket(struct link_socket_actual *actual) > { > #if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) > - return sock->info.dco_installed; > + return actual->dco_installed; > #else > return false; > #endif > @@ -1728,7 +1728,7 @@ process_outgoing_link(struct context *c) > socks_preprocess_outgoing_link(c, &to_addr, &size_delta); > > /* Send packet */ > - if (should_use_dco_socket(c->c2.link_socket)) > + if (should_use_dco_socket(c->c2.to_link_addr)) > { > size = dco_do_write(&c->c1.tuntap->dco, > c->c2.tls_multi->peer_id, > diff --git a/src/openvpn/init.c b/src/openvpn/init.c > index fe554ffd5..ac8a31055 100644 > --- a/src/openvpn/init.c > +++ b/src/openvpn/init.c > @@ -3644,7 +3644,7 @@ do_close_link_socket(struct context *c) > * closed in do_close_tun(). Set it to UNDEFINED so > * we won't use WinSock API to close it. */ > if (tuntap_is_dco_win(c->c1.tuntap) && c->c2.link_socket > - && c->c2.link_socket->info.dco_installed) > + && c->c2.link_socket->info.lsa->actual.dco_installed) > { > c->c2.link_socket->sd = SOCKET_UNDEFINED; > } > diff --git a/src/openvpn/mtcp.c b/src/openvpn/mtcp.c > index 1abb903f2..07da15a6d 100644 > --- a/src/openvpn/mtcp.c > +++ b/src/openvpn/mtcp.c > @@ -402,7 +402,7 @@ multi_tcp_wait_lite(struct multi_context *m, struct multi_instance *mi, const in > > tv_clear(&c->c2.timeval); /* ZERO-TIMEOUT */ > > - if (mi && mi->context.c2.link_socket->info.dco_installed) > + if (mi && mi->context.c2.link_socket->info.lsa->actual.dco_installed) > { > /* If we got a socket that has been handed over to the kernel > * we must not call the normal socket function to figure out > @@ -537,7 +537,7 @@ multi_tcp_dispatch(struct multi_context *m, struct multi_instance *mi, const int > > case TA_INITIAL: > ASSERT(mi); > - if (!mi->context.c2.link_socket->info.dco_installed) > + if (!mi->context.c2.link_socket->info.lsa->actual.dco_installed) > { > multi_tcp_set_global_rw_flags(m, mi); > } > @@ -590,7 +590,7 @@ multi_tcp_post(struct multi_context *m, struct multi_instance *mi, const int act > } > else > { > - if (!c->c2.link_socket->info.dco_installed) > + if (!c->c2.link_socket->info.lsa->actual.dco_installed) > { > multi_tcp_set_global_rw_flags(m, mi); > } > diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c > index 4a9825619..82787f9f2 100644 > --- a/src/openvpn/socket.c > +++ b/src/openvpn/socket.c > @@ -2147,7 +2147,7 @@ create_socket_dco_win(struct context *c, struct link_socket *sock, > get_server_poll_remaining_time(sock->server_poll_timeout), > signal_received); > > - sock->info.dco_installed = true; > + sock->info.lsa->actual.dco_installed = true; > > if (*signal_received) > { > @@ -3480,7 +3480,7 @@ link_socket_write_udp_posix_sendmsg(struct link_socket *sock, > static int > socket_get_last_error(const struct link_socket *sock) > { > - if (sock->info.dco_installed) > + if (sock->info.lsa->actual.dco_installed) > { > return GetLastError(); > } > @@ -3521,7 +3521,7 @@ socket_recv_queue(struct link_socket *sock, int maxsize) > ASSERT(ResetEvent(sock->reads.overlapped.hEvent)); > sock->reads.flags = 0; > > - if (sock->info.dco_installed) > + if (sock->info.lsa->actual.dco_installed) > { > status = ReadFile((HANDLE)sock->sd, wsabuf[0].buf, wsabuf[0].len, > &sock->reads.size, &sock->reads.overlapped); > @@ -3626,7 +3626,7 @@ socket_send_queue(struct link_socket *sock, struct buffer *buf, const struct lin > ASSERT(ResetEvent(sock->writes.overlapped.hEvent)); > sock->writes.flags = 0; > > - if (sock->info.dco_installed) > + if (sock->info.lsa->actual.dco_installed) > { > status = WriteFile((HANDLE)sock->sd, wsabuf[0].buf, wsabuf[0].len, > &sock->writes.size, &sock->writes.overlapped); > diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h > index 462afa31b..7935e421f 100644 > --- a/src/openvpn/socket.h > +++ b/src/openvpn/socket.h > @@ -88,6 +88,7 @@ struct link_socket_actual > /*int dummy;*/ /* add offset to force a bug if dest not explicitly dereferenced */ > > struct openvpn_sockaddr dest; > + bool dco_installed; > #if ENABLE_IP_PKTINFO > union { > #if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) > @@ -121,7 +122,6 @@ struct link_socket_info > sa_family_t af; /* Address family like AF_INET, AF_INET6 or AF_UNSPEC*/ > bool bind_ipv6_only; > int mtu_changed; /* Set to true when mtu value is changed */ > - bool dco_installed; > }; > > /* > @@ -1050,9 +1050,9 @@ link_socket_read_udp_win32(struct link_socket *sock, > struct link_socket_actual *from) > { > sockethandle_t sh = { .s = sock->sd }; > - if (sock->info.dco_installed) > + if (sock->info.lsa->actual.dco_installed) > { > - addr_copy_sa(&from->dest, &sock->info.lsa->actual.dest); > + *from = sock->info.lsa->actual; > sh.is_handle = true; > } > return sockethandle_finalize(sh, &sock->reads, buf, from); > @@ -1073,7 +1073,7 @@ link_socket_read(struct link_socket *sock, > struct link_socket_actual *from) > { > if (proto_is_udp(sock->info.proto) > - || sock->info.dco_installed) > + || sock->info.lsa->actual.dco_installed) > /* unified UDPv4 and UDPv6, for DCO the kernel > * will strip the length header */ > { > @@ -1116,7 +1116,7 @@ link_socket_write_win32(struct link_socket *sock, > { > int err = 0; > int status = 0; > - sockethandle_t sh = { .s = sock->sd, .is_handle = sock->info.dco_installed }; > + sockethandle_t sh = { .s = sock->sd, .is_handle = sock->info.lsa->actual.dco_installed }; > if (overlapped_io_active(&sock->writes)) > { > status = sockethandle_finalize(sh, &sock->writes, NULL, NULL); > @@ -1190,7 +1190,7 @@ link_socket_write(struct link_socket *sock, > struct buffer *buf, > struct link_socket_actual *to) > { > - if (proto_is_udp(sock->info.proto) || sock->info.dco_installed) > + if (proto_is_udp(sock->info.proto) || to->dco_installed) > { > /* unified UDPv4 and UDPv6 and DCO (kernel adds size header) */ > return link_socket_write_udp(sock, buf, to);
Hi, On Wed, Oct 26, 2022 at 06:45:22PM +0200, Arne Schwabe wrote: > For tcp this makes no difference as the remote address of the > socket never changes. For udp this allows OpenVPN to differentiate > if a reconnecting client is using the same address as before or > from a different one. This allow sending via the normal userspace > socket in that case. > > Patch v2: fix windows code path Subjected this to the usual torturing, and while everything *looks* good, it breaks FreeBSD tcp client (old code) --> Linux DCO server (master + patch) freshly started regular TCP/TLS server instance, handshakes just fine, until the PUSH_REPLY wants to be sent (peer-id allocation?), then 2022-11-23 14:22:50 us=358335 freebsd-14-amd64/194.97.140.5:54725 Data Channel MTU parms [ mss_fix:1366 max_frag:0 tun_mtu:1500 tun_max_mtu:1600 headroom:136 payload:1768 tailroom:562 ET:0 ] 2022-11-23 14:22:50 us=358871 freebsd-14-amd64/194.97.140.5:54725 SENT CONTROL [freebsd-14-amd64]: 'PUSH_REPLY,route 10.220.0.0 255.255.0.0,route-ipv6 fd00:abcd:220::/48,tun-ipv6,route-gateway 10.220.1.1,topology subnet,ping 10,ping-restart 30,compress stub-v2,ifconfig-ipv6 fd00:abcd:220:1::1002/64 fd00:abcd:220:1::1,ifconfig 10.220.1.4 255.255.255.0,peer-id 0,cipher AES-256-GCM' (status=1) 2022-11-23 14:22:50 us=359153 freebsd-14-amd64/194.97.140.5:54725 write TCPv6_SERVER []: Bad file descriptor (fd=-1,code=9) 2022-11-23 14:22:52 us=525667 freebsd-14-amd64/194.97.140.5:54725 PUSH: Received control message: 'PUSH_REQUEST' 2022-11-23 14:22:52 us=526099 freebsd-14-amd64/194.97.140.5:54725 write TCPv6_SERVER []: Bad file descriptor (fd=-1,code=9) 2022-11-23 14:22:56 us=611511 freebsd-14-amd64/194.97.140.5:54725 write TCPv6_SERVER []: Bad file descriptor (fd=-1,code=9) 2022-11-23 14:23:04 us=694791 freebsd-14-amd64/194.97.140.5:54725 PUSH: Received control message: 'PUSH_REQUEST' 2022-11-23 14:23:04 us=694916 freebsd-14-amd64/194.97.140.5:54725 write TCPv6_SERVER []: Bad file descriptor (fd=-1,code=9) 2022-11-23 14:23:04 us=694966 freebsd-14-amd64/194.97.140.5:54725 PUSH: Received control message: 'PUSH_REQUEST' 2022-11-23 14:23:05 us=853345 freebsd-14-amd64/194.97.140.5:54725 write TCPv6_SERVER []: Bad file descriptor (fd=-1,code=9) on the client I have 2022-11-23 14:22:50 Control Channel: TLSv1.2, cipher TLSv1.2 ECDHE-RSA-CHACHA20-POLY1305, peer certificate: 2048 bit RSA, signature: RSA-SHA1 2022-11-23 14:22:50 [server] Peer Connection Initiated with [AF_INET]195.30.8.84:51194 2022-11-23 14:22:51 SENT CONTROL [server]: 'PUSH_REQUEST' (status=1) 2022-11-23 14:22:56 SENT CONTROL [server]: 'PUSH_REQUEST' (status=1) 2022-11-23 14:23:00 TLS Error: local/remote TLS keys are out of sync: [AF_INET]195.30.8.84:51194 (received key id: 0, known key ids: [key#0 state=S_ACTIVE auth=KS_AUTH_TRUE id=0 sid=934b2d6e 14c3286f] [key#1 state=S_UNDEF auth=KS_AUTH_FALSE id=0 sid=00000000 00000000] [key#2 state=S_UNDEF auth=KS_AUTH_FALSE id=0 sid=00000000 00000000]) 2022-11-23 14:23:01 SENT CONTROL [server]: 'PUSH_REQUEST' (status=1) 2022-11-23 14:23:06 SENT CONTROL [server]: 'PUSH_REQUEST' (status=1) 2022-11-23 14:23:10 TLS Error: local/remote TLS keys are out of sync: [AF_INET]195.30.8.84:51194 (received key id: 0, known key ids: [key#0 state=S_ACTIVE auth=KS_AUTH_TRUE id=0 sid=934b2d6e 14c3286f] [key#1 state=S_UNDEF auth=KS_AUTH_FALSE id=0 sid=00000000 00000000] [key#2 state=S_UNDEF auth=KS_AUTH_FALSE id=0 sid=00000000 00000000]) Not exactly sure why it hickups. This is fully reproduceable, so if you want me to increas debug, just let me know. gert
Hi, On Tue, Nov 01, 2022 at 11:21:40AM +0200, Lev Stipakov wrote: > > @@ -1190,7 +1190,7 @@ link_socket_write(struct link_socket *sock, > > struct buffer *buf, > > struct link_socket_actual *to) > > { > > - if (proto_is_udp(sock->info.proto) || sock->info.dco_installed) > > + if (proto_is_udp(sock->info.proto) || to->dco_installed) > > { > > Previously we used to check the dco flag from sock->info and now it is changed > to "to", which is a separate member in c->c2 (c->c2.to_link_addr vs > c->c2.link_socket). > > Why not use "sock->info.lsa->actual.dco_installed" ? My understanding > is that this patch > only moves the flag to a different place and is not supposed to change > the behavior. For the sake of the archives: I asked Arne today, and the reply was "this is not pretty, but with Antonio's upcoming changes to DCO, it's likely that the dco_installed field goes away, or is reworked significantly". So for now, we leave it as it is, knowing it's working but not perfect. gert
diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c index a76cdd0cd..1f402bfc2 100644 --- a/src/openvpn/dco.c +++ b/src/openvpn/dco.c @@ -448,7 +448,7 @@ dco_p2p_add_new_peer(struct context *c) } c->c2.tls_multi->dco_peer_added = true; - c->c2.link_socket->info.dco_installed = true; + c->c2.link_socket->info.lsa->actual.dco_installed = true; return 0; } @@ -522,7 +522,7 @@ dco_multi_add_new_peer(struct multi_context *m, struct multi_instance *mi) { struct context *c = &mi->context; - int peer_id = mi->context.c2.tls_multi->peer_id; + int peer_id = c->c2.tls_multi->peer_id; struct sockaddr *remoteaddr, *localaddr = NULL; struct sockaddr_storage local = { 0 }; int sd = c->c2.link_socket->sd; @@ -531,6 +531,7 @@ dco_multi_add_new_peer(struct multi_context *m, struct multi_instance *mi) { /* the remote address will be inferred from the TCP socket endpoint */ remoteaddr = NULL; + c->c2.link_socket->info.lsa->actual.dco_installed = true; } else { @@ -575,7 +576,7 @@ dco_multi_add_new_peer(struct multi_context *m, struct multi_instance *mi) { msg(D_DCO|M_ERRNO, "error closing TCP socket after DCO handover"); } - c->c2.link_socket->info.dco_installed = true; + c->c2.link_socket->info.lsa->actual.dco_installed = true; c->c2.link_socket->sd = SOCKET_UNDEFINED; } diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 98e10507b..109358205 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -285,7 +285,7 @@ ovpn_nl_cb_finish(struct nl_msg (*msg) __attribute__ ((unused)), void *arg) * * We pass the error code to the user by means of a variable pointed by *arg * (supplied by the user when setting this callback) and we parse the kernel - * reply to see if it contains a human readable error. If found, it is printed. + * reply to see if it contains a human-readable error. If found, it is printed. */ static int ovpn_nl_cb_error(struct sockaddr_nl (*nla) __attribute__ ((unused)), diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 20d9a7598..622be8411 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1643,13 +1643,13 @@ process_ip_header(struct context *c, unsigned int flags, struct buffer *buf) * standard Overlapped I/O. * * Hide that complexity (...especially if more platforms show up - * in future...) in a small inline function. + * in the future...) in a small inline function. */ static inline bool -should_use_dco_socket(struct link_socket *sock) +should_use_dco_socket(struct link_socket_actual *actual) { #if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) - return sock->info.dco_installed; + return actual->dco_installed; #else return false; #endif @@ -1728,7 +1728,7 @@ process_outgoing_link(struct context *c) socks_preprocess_outgoing_link(c, &to_addr, &size_delta); /* Send packet */ - if (should_use_dco_socket(c->c2.link_socket)) + if (should_use_dco_socket(c->c2.to_link_addr)) { size = dco_do_write(&c->c1.tuntap->dco, c->c2.tls_multi->peer_id, diff --git a/src/openvpn/init.c b/src/openvpn/init.c index fe554ffd5..ac8a31055 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -3644,7 +3644,7 @@ do_close_link_socket(struct context *c) * closed in do_close_tun(). Set it to UNDEFINED so * we won't use WinSock API to close it. */ if (tuntap_is_dco_win(c->c1.tuntap) && c->c2.link_socket - && c->c2.link_socket->info.dco_installed) + && c->c2.link_socket->info.lsa->actual.dco_installed) { c->c2.link_socket->sd = SOCKET_UNDEFINED; } diff --git a/src/openvpn/mtcp.c b/src/openvpn/mtcp.c index 1abb903f2..07da15a6d 100644 --- a/src/openvpn/mtcp.c +++ b/src/openvpn/mtcp.c @@ -402,7 +402,7 @@ multi_tcp_wait_lite(struct multi_context *m, struct multi_instance *mi, const in tv_clear(&c->c2.timeval); /* ZERO-TIMEOUT */ - if (mi && mi->context.c2.link_socket->info.dco_installed) + if (mi && mi->context.c2.link_socket->info.lsa->actual.dco_installed) { /* If we got a socket that has been handed over to the kernel * we must not call the normal socket function to figure out @@ -537,7 +537,7 @@ multi_tcp_dispatch(struct multi_context *m, struct multi_instance *mi, const int case TA_INITIAL: ASSERT(mi); - if (!mi->context.c2.link_socket->info.dco_installed) + if (!mi->context.c2.link_socket->info.lsa->actual.dco_installed) { multi_tcp_set_global_rw_flags(m, mi); } @@ -590,7 +590,7 @@ multi_tcp_post(struct multi_context *m, struct multi_instance *mi, const int act } else { - if (!c->c2.link_socket->info.dco_installed) + if (!c->c2.link_socket->info.lsa->actual.dco_installed) { multi_tcp_set_global_rw_flags(m, mi); } diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 4a9825619..82787f9f2 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -2147,7 +2147,7 @@ create_socket_dco_win(struct context *c, struct link_socket *sock, get_server_poll_remaining_time(sock->server_poll_timeout), signal_received); - sock->info.dco_installed = true; + sock->info.lsa->actual.dco_installed = true; if (*signal_received) { @@ -3480,7 +3480,7 @@ link_socket_write_udp_posix_sendmsg(struct link_socket *sock, static int socket_get_last_error(const struct link_socket *sock) { - if (sock->info.dco_installed) + if (sock->info.lsa->actual.dco_installed) { return GetLastError(); } @@ -3521,7 +3521,7 @@ socket_recv_queue(struct link_socket *sock, int maxsize) ASSERT(ResetEvent(sock->reads.overlapped.hEvent)); sock->reads.flags = 0; - if (sock->info.dco_installed) + if (sock->info.lsa->actual.dco_installed) { status = ReadFile((HANDLE)sock->sd, wsabuf[0].buf, wsabuf[0].len, &sock->reads.size, &sock->reads.overlapped); @@ -3626,7 +3626,7 @@ socket_send_queue(struct link_socket *sock, struct buffer *buf, const struct lin ASSERT(ResetEvent(sock->writes.overlapped.hEvent)); sock->writes.flags = 0; - if (sock->info.dco_installed) + if (sock->info.lsa->actual.dco_installed) { status = WriteFile((HANDLE)sock->sd, wsabuf[0].buf, wsabuf[0].len, &sock->writes.size, &sock->writes.overlapped); diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h index 462afa31b..7935e421f 100644 --- a/src/openvpn/socket.h +++ b/src/openvpn/socket.h @@ -88,6 +88,7 @@ struct link_socket_actual /*int dummy;*/ /* add offset to force a bug if dest not explicitly dereferenced */ struct openvpn_sockaddr dest; + bool dco_installed; #if ENABLE_IP_PKTINFO union { #if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) @@ -121,7 +122,6 @@ struct link_socket_info sa_family_t af; /* Address family like AF_INET, AF_INET6 or AF_UNSPEC*/ bool bind_ipv6_only; int mtu_changed; /* Set to true when mtu value is changed */ - bool dco_installed; }; /* @@ -1050,9 +1050,9 @@ link_socket_read_udp_win32(struct link_socket *sock, struct link_socket_actual *from) { sockethandle_t sh = { .s = sock->sd }; - if (sock->info.dco_installed) + if (sock->info.lsa->actual.dco_installed) { - addr_copy_sa(&from->dest, &sock->info.lsa->actual.dest); + *from = sock->info.lsa->actual; sh.is_handle = true; } return sockethandle_finalize(sh, &sock->reads, buf, from); @@ -1073,7 +1073,7 @@ link_socket_read(struct link_socket *sock, struct link_socket_actual *from) { if (proto_is_udp(sock->info.proto) - || sock->info.dco_installed) + || sock->info.lsa->actual.dco_installed) /* unified UDPv4 and UDPv6, for DCO the kernel * will strip the length header */ { @@ -1116,7 +1116,7 @@ link_socket_write_win32(struct link_socket *sock, { int err = 0; int status = 0; - sockethandle_t sh = { .s = sock->sd, .is_handle = sock->info.dco_installed }; + sockethandle_t sh = { .s = sock->sd, .is_handle = sock->info.lsa->actual.dco_installed }; if (overlapped_io_active(&sock->writes)) { status = sockethandle_finalize(sh, &sock->writes, NULL, NULL); @@ -1190,7 +1190,7 @@ link_socket_write(struct link_socket *sock, struct buffer *buf, struct link_socket_actual *to) { - if (proto_is_udp(sock->info.proto) || sock->info.dco_installed) + if (proto_is_udp(sock->info.proto) || to->dco_installed) { /* unified UDPv4 and UDPv6 and DCO (kernel adds size header) */ return link_socket_write_udp(sock, buf, to);
For tcp this makes no difference as the remote address of the socket never changes. For udp this allows OpenVPN to differentiate if a reconnecting client is using the same address as before or from a different one. This allow sending via the normal userspace socket in that case. Patch v2: fix windows code path Signed-off-by: Arne Schwabe <arne@rfc2549.org> --- src/openvpn/dco.c | 7 ++++--- src/openvpn/dco_linux.c | 2 +- src/openvpn/forward.c | 8 ++++---- src/openvpn/init.c | 2 +- src/openvpn/mtcp.c | 6 +++--- src/openvpn/socket.c | 8 ++++---- src/openvpn/socket.h | 12 ++++++------ 7 files changed, 23 insertions(+), 22 deletions(-)