From patchwork Wed Apr 25 09:57:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 322 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director9.mail.ord1d.rsapps.net ([172.27.255.58]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id E5eqJjXe4FqdPwAAIUCqbw for ; Wed, 25 Apr 2018 15:59:49 -0400 Received: from proxy20.mail.iad3a.rsapps.net ([172.27.255.58]) by director9.mail.ord1d.rsapps.net (Dovecot) with LMTP id O0XMCTXe4FqiTQAAalYnBA ; Wed, 25 Apr 2018 15:59:49 -0400 Received: from smtp28.gate.iad3a ([172.27.255.58]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy20.mail.iad3a.rsapps.net with LMTP id YJR4HzXe4FqpAgAAtfLT2w ; Wed, 25 Apr 2018 15:59:49 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp28.gate.iad3a.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: 35475f56-48c3-11e8-a363-52540000591c-1-1 Received: from [216.105.38.7] ([216.105.38.7:30491] helo=lists.sourceforge.net) by smtp28.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 98/D9-13310-43ED0EA5; Wed, 25 Apr 2018 15:59:49 -0400 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fBQZ2-0008Q4-FE; Wed, 25 Apr 2018 19:58:52 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fBQZ0-0008Px-Tk for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:58:50 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=9Y51vj7itw1cJyrokp2/v9bAZEM5Ecxxgcgu33f97vs=; b=ksxBT4vxmju6wgNs3Z65FeMG93 rmUJghrwWGYycwCVDXlt/aDy7N8iFuDr7jlDeneaDcOMTg201z8hzqOytOWnjjhAHW6DjPbBvz8gb n4ulI91wQtyLxgqcI0YUpqEGr/TaeqQl409R8NIEIIr9vr4YEfOTRbGYToczn2GKKzsw=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=9Y51vj7itw1cJyrokp2/v9bAZEM5Ecxxgcgu33f97vs=; b=c3re8YYvxgfcLCU4TWuM6jIBtL Q/mjtzwGJYzknTlowcyN5/hMxmTZ7mT38dxx5SgsOaCcRilBgtbe9QKMtGnWtYva1vpUGjCJfhKf7 /t7rtJ7wh9TxOiIhVNcaVUFRri/7vT89BNZX2uCLVPH+yZECk0UQuzFNsdodkcjOszG4=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fBQYx-007Na9-VJ for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:58:50 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Thu, 26 Apr 2018 03:57:15 +0800 Message-Id: <20180425195722.20744-2-a@unstable.cc> In-Reply-To: <20180425195722.20744-1-a@unstable.cc> References: <20180425195722.20744-1-a@unstable.cc> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [5.148.176.60 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1fBQYx-007Na9-VJ Subject: [Openvpn-devel] [RFC 1/8] event/multi: add event_arg object to make event handling more generic X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox In order to prepare the event handling code to deal with multiple listening sockets, we have to make sure that it is possible to distinguish which of these sockets have been pocked by an incoming connection request. To achieve that, this patch changes the object being passed as event handler argument, from a "partly integer evaluated variable" to a full struct with a proper type attribute. This struct will allow the code to carry around the particular listening socket where the connection is being established. This change affects the TCP server code path only as UDP servers use only one socket to handle all clients i/o. Signed-off-by: Antonio Quartulli --- src/openvpn/event.h | 14 ++++++++++ src/openvpn/mtcp.c | 62 +++++++++++++++++++++++++------------------- src/openvpn/multi.c | 3 +++ src/openvpn/multi.h | 1 + src/openvpn/socket.c | 2 ++ src/openvpn/socket.h | 2 ++ 6 files changed, 58 insertions(+), 26 deletions(-) diff --git a/src/openvpn/event.h b/src/openvpn/event.h index 4af6371e..33ff8890 100644 --- a/src/openvpn/event.h +++ b/src/openvpn/event.h @@ -85,6 +85,20 @@ struct event_set struct event_set_functions func; }; +typedef enum { + EVENT_ARG_MULTI_INSTANCE = 0, + EVENT_ARG_LINK_SOCKET, +} event_arg_t; + +/* generic event argument object to pass to event_ctl() */ +struct event_arg +{ + event_arg_t type; + union { + struct multi_instance *mi; /* if type = EVENT_ARG_MULTI_INSTANCE */ + } u; +}; + /* * maxevents on input: desired max number of event_t descriptors * simultaneously set with event_ctl diff --git a/src/openvpn/mtcp.c b/src/openvpn/mtcp.c index 3756c270..234c077c 100644 --- a/src/openvpn/mtcp.c +++ b/src/openvpn/mtcp.c @@ -58,7 +58,6 @@ /* * Special tags passed to event.[ch] functions */ -#define MTCP_SOCKET ((void *)1) #define MTCP_TUN ((void *)2) #define MTCP_SIG ((void *)3) /* Only on Windows */ #ifdef ENABLE_MANAGEMENT @@ -259,7 +258,7 @@ multi_tcp_set_global_rw_flags(struct multi_context *m, struct multi_instance *mi socket_set(mi->context.c2.link_socket, m->mtcp->es, mbuf_defined(mi->tcp_link_out_deferred) ? EVENT_WRITE : EVENT_READ, - mi, + &mi->ev_arg, &mi->tcp_rwflags); } } @@ -269,7 +268,8 @@ multi_tcp_wait(const struct context *c, struct multi_tcp *mtcp) { int status; - socket_set_listen_persistent(c->c2.link_socket, mtcp->es, MTCP_SOCKET); + socket_set_listen_persistent(c->c2.link_socket, mtcp->es, + &c->c2.link_socket->ev_arg); tun_set(c->c1.tuntap, mtcp->es, EVENT_READ, MTCP_TUN, &mtcp->tun_rwflags); #ifdef ENABLE_MANAGEMENT if (management) @@ -679,21 +679,43 @@ multi_tcp_process_io(struct multi_context *m) for (i = 0; i < mtcp->n_esr; ++i) { struct event_set_return *e = &mtcp->esr[i]; + struct event_arg *ev_arg = (struct event_arg *)e->arg; - /* incoming data for instance? */ + /* incoming data for instance or listening socket? */ if (e->arg >= MTCP_N) { - struct multi_instance *mi = (struct multi_instance *) e->arg; - if (mi) + switch (ev_arg->type) { - if (e->rwflags & EVENT_WRITE) - { - multi_tcp_action(m, mi, TA_SOCKET_WRITE_READY, false); - } - else if (e->rwflags & EVENT_READ) - { - multi_tcp_action(m, mi, TA_SOCKET_READ, false); - } + struct multi_instance *mi; + + /* react to event on child instance */ + case EVENT_ARG_MULTI_INSTANCE: + if (!ev_arg->u.mi) + { + msg(D_MULTI_ERRORS, "MULTI: mtcp_proc_io: null minstance"); + break; + } + + mi = ev_arg->u.mi; + if (e->rwflags & EVENT_WRITE) + { + multi_tcp_action(m, mi, TA_SOCKET_WRITE_READY, false); + } + else if (e->rwflags & EVENT_READ) + { + multi_tcp_action(m, mi, TA_SOCKET_READ, false); + } + break; + /* new incoming TCP client attempting to connect? */ + case EVENT_ARG_LINK_SOCKET: + ASSERT(m->top.c2.link_socket); + socket_reset_listen_persistent(m->top.c2.link_socket); + mi = multi_create_instance_tcp(m); + if (mi) + { + multi_tcp_action(m, mi, TA_INITIAL, false); + } + break; } } else @@ -718,18 +740,6 @@ multi_tcp_process_io(struct multi_context *m) multi_tcp_action(m, NULL, TA_TUN_READ, false); } } - /* new incoming TCP client attempting to connect? */ - else if (e->arg == MTCP_SOCKET) - { - struct multi_instance *mi; - ASSERT(m->top.c2.link_socket); - socket_reset_listen_persistent(m->top.c2.link_socket); - mi = multi_create_instance_tcp(m); - if (mi) - { - multi_tcp_action(m, mi, TA_INITIAL, false); - } - } /* signal received? */ else if (e->arg == MTCP_SIG) { diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 3da8c110..f877c060 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -841,6 +841,9 @@ multi_create_instance(struct multi_context *m, const struct mroute_addr *real) goto err; } + mi->ev_arg.type = EVENT_ARG_MULTI_INSTANCE; + mi->ev_arg.u.mi = mi; + perf_pop(); gc_free(&gc); return mi; diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index d7e5c298..c52445ed 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -75,6 +75,7 @@ struct deferred_signal_schedule_entry */ struct multi_instance { struct schedule_entry se; /* this must be the first element of the structure */ + struct event_arg ev_arg; struct gc_arena gc; bool defined; bool halt; diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 211e7441..e0620f09 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -1712,6 +1712,8 @@ link_socket_new(void) ALLOC_OBJ_CLEAR(sock, struct link_socket); sock->sd = SOCKET_UNDEFINED; sock->ctrl_sd = SOCKET_UNDEFINED; + sock->ev_arg.type = EVENT_ARG_LINK_SOCKET; + return sock; } diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h index 479d1150..46000246 100644 --- a/src/openvpn/socket.h +++ b/src/openvpn/socket.h @@ -165,6 +165,8 @@ struct link_socket { struct link_socket_info info; + struct event_arg ev_arg; + socket_descriptor_t sd; socket_descriptor_t ctrl_sd; /* only used for UDP over Socks */ From patchwork Wed Apr 25 09:57:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 324 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director7.mail.ord1d.rsapps.net ([172.27.255.51]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id vBFEDjje4FrqOQAAIUCqbw for ; Wed, 25 Apr 2018 15:59:52 -0400 Received: from proxy3.mail.iad3a.rsapps.net ([172.27.255.51]) by director7.mail.ord1d.rsapps.net (Dovecot) with LMTP id of+aDjje4FrRaAAAovjBpQ ; Wed, 25 Apr 2018 15:59:52 -0400 Received: from smtp13.gate.iad3a ([172.27.255.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy3.mail.iad3a.rsapps.net with LMTP id OAppEzje4FoqJgAAYaqY3Q ; Wed, 25 Apr 2018 15:59:52 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp13.gate.iad3a.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: 36b456b4-48c3-11e8-a2a0-5254004b83b1-1-1 Received: from [216.105.38.7] ([216.105.38.7:48536] helo=lists.sourceforge.net) by smtp13.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id E5/94-28091-73ED0EA5; Wed, 25 Apr 2018 15:59:51 -0400 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fBQZ9-0000pI-Ik; Wed, 25 Apr 2018 19:58:59 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fBQZ7-0000ou-GM for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:58:57 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=9Mem1bkbl+o7S88Cf8zA3Sm8++ufPZ6HCMODaYriVI0=; b=C/TmNtEHPuRdCK73VfwWs4mmVz OeEU0h3sPe3IdCEPFNSdXz98734X74BUbvGyoT72pKJg+XXmc8+SVgcgOq26275gM7Od3TToamZZr piSAWeG3okWx05ExR/OwEmji9N4rARLZKBC7PGBu4GJTC5H89i4Cy23/MIsKGw3HKb5w=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=9Mem1bkbl+o7S88Cf8zA3Sm8++ufPZ6HCMODaYriVI0=; b=MSUmwbXjxbCWDTyGQ/6zxzOIOO diY054WnlsiYe0vifKVCWVsqg5Xpq0FHHZcbZze6NSPJGyvKDOXND9G/iYBRrhGTnqrbQLPitASjk NHWHan5lieH0HNZILANgjQZOCwWxboFvNDPCFkqQY7pix95kA6xpGf4siOgESKzu4dxc=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-3.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fBQZ5-00Bt3J-Cg for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:58:57 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Thu, 26 Apr 2018 03:57:16 +0800 Message-Id: <20180425195722.20744-3-a@unstable.cc> In-Reply-To: <20180425195722.20744-1-a@unstable.cc> References: <20180425195722.20744-1-a@unstable.cc> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [5.148.176.60 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1fBQZ5-00Bt3J-Cg Subject: [Openvpn-devel] [RFC 2/8] pass link_socket object to i/o functions X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox In order to prepare the code to work with distinct sockets, it is essential that i/o functions do not operate on any hard-coded socket object (i.e. c->c2.link_socket). This patch changes all the low-level i/o functionis to work with a socket specified as argument rather than a fixed one. Signed-off-by: Antonio Quartulli --- src/openvpn/event.h | 1 + src/openvpn/forward.c | 49 ++++++++++++++++++++++--------------------- src/openvpn/forward.h | 17 ++++++++------- src/openvpn/mtcp.c | 2 +- src/openvpn/mudp.c | 2 +- src/openvpn/multi.h | 2 +- src/openvpn/openvpn.c | 2 +- src/openvpn/socket.c | 1 + 8 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/openvpn/event.h b/src/openvpn/event.h index 33ff8890..be199ad9 100644 --- a/src/openvpn/event.h +++ b/src/openvpn/event.h @@ -96,6 +96,7 @@ struct event_arg event_arg_t type; union { struct multi_instance *mi; /* if type = EVENT_ARG_MULTI_INSTANCE */ + struct link_socket *ls; /* if type = EVENT_ARG_LINK_SOCKET */ } u; }; diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 7d9a338d..c5ddf385 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -663,9 +663,9 @@ check_timeout_random_component(struct context *c) */ static inline void -socks_postprocess_incoming_link(struct context *c) +socks_postprocess_incoming_link(struct context *c, struct link_socket *ls) { - if (c->c2.link_socket->socks_proxy && c->c2.link_socket->info.proto == PROTO_UDP) + if (ls->socks_proxy && ls->info.proto == PROTO_UDP) { socks_process_incoming_udp(&c->c2.buf, &c->c2.from); } @@ -673,13 +673,14 @@ socks_postprocess_incoming_link(struct context *c) static inline void socks_preprocess_outgoing_link(struct context *c, + struct link_socket *ls, struct link_socket_actual **to_addr, int *size_delta) { - if (c->c2.link_socket->socks_proxy && c->c2.link_socket->info.proto == PROTO_UDP) + if (ls->socks_proxy && ls->info.proto == PROTO_UDP) { *size_delta += socks_process_outgoing_udp(&c->c2.to_link, c->c2.to_link_addr); - *to_addr = &c->c2.link_socket->socks_relay; + *to_addr = &ls->socks_relay; } } @@ -704,7 +705,7 @@ link_socket_write_post_size_adjust(int *size, */ void -read_incoming_link(struct context *c) +read_incoming_link(struct context *c, struct link_socket *ls) { /* * Set up for recvfrom call to read datagram @@ -719,17 +720,17 @@ read_incoming_link(struct context *c) c->c2.buf = c->c2.buffers->read_link_buf; ASSERT(buf_init(&c->c2.buf, FRAME_HEADROOM_ADJ(&c->c2.frame, FRAME_HEADROOM_MARKER_READ_LINK))); - status = link_socket_read(c->c2.link_socket, + status = link_socket_read(ls, &c->c2.buf, &c->c2.from); - if (socket_connection_reset(c->c2.link_socket, status)) + if (socket_connection_reset(ls, status)) { #if PORT_SHARE - if (port_share && socket_foreign_protocol_detected(c->c2.link_socket)) + if (port_share && socket_foreign_protocol_detected(ls)) { - const struct buffer *fbuf = socket_foreign_protocol_head(c->c2.link_socket); - const int sd = socket_foreign_protocol_sd(c->c2.link_socket); + const struct buffer *fbuf = socket_foreign_protocol_head(ls); + const int sd = socket_foreign_protocol_sd(ls); port_share_redirect(port_share, fbuf, sd); register_signal(c, SIGTERM, "port-share-redirect"); } @@ -763,10 +764,10 @@ read_incoming_link(struct context *c) } /* check recvfrom status */ - check_status(status, "read", c->c2.link_socket, NULL); + check_status(status, "read", ls, NULL); /* Remove socks header if applicable */ - socks_postprocess_incoming_link(c); + socks_postprocess_incoming_link(c, ls); perf_pop(); } @@ -996,11 +997,11 @@ process_incoming_link_part2(struct context *c, struct link_socket_info *lsi, con } static void -process_incoming_link(struct context *c) +process_incoming_link(struct context *c, struct link_socket *ls) { perf_push(PERF_PROC_IN_LINK); - struct link_socket_info *lsi = get_link_socket_info(c); + struct link_socket_info *lsi = &ls->info; const uint8_t *orig_buf = c->c2.buf.data; process_incoming_link_part1(c, lsi, false); @@ -1293,7 +1294,7 @@ process_ip_header(struct context *c, unsigned int flags, struct buffer *buf) */ void -process_outgoing_link(struct context *c) +process_outgoing_link(struct context *c, struct link_socket *ls) { struct gc_arena gc = gc_new(); int error_code = 0; @@ -1335,7 +1336,7 @@ process_outgoing_link(struct context *c) #if PASSTOS_CAPABILITY /* Set TOS */ - link_socket_set_tos(c->c2.link_socket); + link_socket_set_tos(ls); #endif /* Log packet send */ @@ -1346,7 +1347,7 @@ process_outgoing_link(struct context *c) } #endif msg(D_LINK_RW, "%s WRITE [%d] to %s: %s", - proto2ascii(c->c2.link_socket->info.proto, c->c2.link_socket->info.af, true), + proto2ascii(ls->info.proto, ls->info.af, true), BLEN(&c->c2.to_link), print_link_socket_actual(c->c2.to_link_addr, &gc), PROTO_DUMP(&c->c2.to_link, &gc)); @@ -1357,10 +1358,10 @@ process_outgoing_link(struct context *c) int size_delta = 0; /* If Socks5 over UDP, prepend header */ - socks_preprocess_outgoing_link(c, &to_addr, &size_delta); + socks_preprocess_outgoing_link(c, ls, &to_addr, &size_delta); /* Send packet */ - size = link_socket_write(c->c2.link_socket, + size = link_socket_write(ls, &c->c2.to_link, to_addr); @@ -1393,7 +1394,7 @@ process_outgoing_link(struct context *c) /* Check return status */ error_code = openvpn_errno(); - check_status(size, "write", c->c2.link_socket, NULL); + check_status(size, "write", ls, NULL); if (size > 0) { @@ -1797,7 +1798,7 @@ io_wait_dowork(struct context *c, const unsigned int flags) } void -process_io(struct context *c) +process_io(struct context *c, struct link_socket *ls) { const unsigned int status = c->c2.event_set_status; @@ -1812,7 +1813,7 @@ process_io(struct context *c) /* TCP/UDP port ready to accept write */ if (status & SOCKET_WRITE) { - process_outgoing_link(c); + process_outgoing_link(c, ls); } /* TUN device ready to accept write */ else if (status & TUN_WRITE) @@ -1822,10 +1823,10 @@ process_io(struct context *c) /* Incoming data on TCP/UDP port */ else if (status & SOCKET_READ) { - read_incoming_link(c); + read_incoming_link(c, ls); if (!IS_SIG(c)) { - process_incoming_link(c); + process_incoming_link(c, ls); } } /* Incoming data on TUN device */ diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 924cc5e2..16639f75 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -63,7 +63,8 @@ void pre_select(struct context *c); -void process_io(struct context *c); +void process_io(struct context *ci, struct link_socket *ls); + const char *wait_status_string(struct context *c, struct gc_arena *gc); @@ -124,10 +125,11 @@ int get_server_poll_remaining_time(struct event_timeout *server_poll_timeout); * context associated with the appropriate VPN tunnel for which data is * available to be read. * - * @param c - The context structure which contains the external - * network socket from which to read incoming packets. + * @param c The context structure which contains the external + * network socket from which to read incoming packets. + * @param ls The socket where the packet can be read from. */ -void read_incoming_link(struct context *c); +void read_incoming_link(struct context *c, struct link_socket *ls); /** * Starts processing a packet read from the external network interface. @@ -193,10 +195,11 @@ void process_incoming_link_part2(struct context *c, struct link_socket_info *lsi * * If an error occurs, it is logged and the packet is dropped. * - * @param c - The context structure of the VPN tunnel associated with the - * packet. + * @param c The context structure of the VPN tunnel associated with the + * packet. + * @param ls The socket to be used to send the packet. */ -void process_outgoing_link(struct context *c); +void process_outgoing_link(struct context *c, struct link_socket *ls); /**************************************************************************/ diff --git a/src/openvpn/mtcp.c b/src/openvpn/mtcp.c index 234c077c..51f339d0 100644 --- a/src/openvpn/mtcp.c +++ b/src/openvpn/mtcp.c @@ -470,7 +470,7 @@ multi_tcp_dispatch(struct multi_context *m, struct multi_instance *mi, const int ASSERT(mi); ASSERT(mi->context.c2.link_socket); set_prefix(mi); - read_incoming_link(&mi->context); + read_incoming_link(&mi->context, mi->context.c2.link_socket); clear_prefix(); if (!IS_SIG(&mi->context)) { diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c index b3690ab7..80efefb3 100644 --- a/src/openvpn/mudp.c +++ b/src/openvpn/mudp.c @@ -227,7 +227,7 @@ multi_process_io_udp(struct multi_context *m) /* Incoming data on UDP port */ else if (status & SOCKET_READ) { - read_incoming_link(&m->top); + read_incoming_link(&m->top, m->top.c2.link_socket); if (!IS_SIG(&m->top)) { multi_process_incoming_link(m, NULL, mpp_flags); diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index c52445ed..5fb8402f 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -637,7 +637,7 @@ multi_process_outgoing_link_dowork(struct multi_context *m, struct multi_instanc { bool ret = true; set_prefix(mi); - process_outgoing_link(&mi->context); + process_outgoing_link(&mi->context, mi->context.c2.link_socket); ret = multi_process_post(m, mi, mpp_flags); clear_prefix(); return ret; diff --git a/src/openvpn/openvpn.c b/src/openvpn/openvpn.c index b9e914a8..b52063a2 100644 --- a/src/openvpn/openvpn.c +++ b/src/openvpn/openvpn.c @@ -115,7 +115,7 @@ tunnel_point_to_point(struct context *c) } /* process the I/O which triggered select */ - process_io(c); + process_io(c, c->c2.link_socket); P2P_CHECK_SIG(); perf_pop(); diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index e0620f09..564948a2 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -1713,6 +1713,7 @@ link_socket_new(void) sock->sd = SOCKET_UNDEFINED; sock->ctrl_sd = SOCKET_UNDEFINED; sock->ev_arg.type = EVENT_ARG_LINK_SOCKET; + sock->ev_arg.u.ls = sock; return sock; } From patchwork Wed Apr 25 09:57:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 327 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director8.mail.ord1d.rsapps.net ([172.27.255.58]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id vpefCUDe4FrkSwAAIUCqbw for ; Wed, 25 Apr 2018 16:00:00 -0400 Received: from proxy1.mail.iad3a.rsapps.net ([172.27.255.58]) by director8.mail.ord1d.rsapps.net (Dovecot) with LMTP id +zR6HEDe4FrdJgAAfY0hYg ; Wed, 25 Apr 2018 16:00:00 -0400 Received: from smtp24.gate.iad3a ([172.27.255.58]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy1.mail.iad3a.rsapps.net with LMTP id IKHoGUDe4FqcTwAA8TVjwQ ; Wed, 25 Apr 2018 16:00:00 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp24.gate.iad3a.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: 3bdedeca-48c3-11e8-9470-5254009f6f51-1-1 Received: from [216.105.38.7] ([216.105.38.7:62280] helo=lists.sourceforge.net) by smtp24.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id E9/59-05391-04ED0EA5; Wed, 25 Apr 2018 16:00:00 -0400 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fBQZ5-0008R0-MG; Wed, 25 Apr 2018 19:58:55 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fBQZ4-0008Qt-CX for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:58:54 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=L4jrwU7N/7uW3NcQmkl16WiYAwvzn6OH+r16qrXRhnY=; b=nGpUisij2SKajw0gTIsUnFeHqG Kcvgo0lNjBwnZ94DMSh6H2ExnkQdpGC+hDC3RDwAy45DRJ1vzNYdCnN7hukw/KooQhQgKBswQl8uZ pHhnNBA657vkz2pRp4isxoEUAJjHa2rFJ5YrPZuueWi29jDL9jh+/J8W8HiMvRfuReSg=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=L4jrwU7N/7uW3NcQmkl16WiYAwvzn6OH+r16qrXRhnY=; b=S0taslKEbgdyK0krwnUzAU2lFi rDkea8CHoF6jlYm1wY04ZpeENnsFtFn8eZ0CJimd7ZasXi/a6PKzSu59dheY0t6sNYdLA6fowencl 7tHlDEm035JWCWTK30RMkjQFgczFKdtmndDE1p793I1ItupkZDHO/yRzjRvusHsDA58U=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fBQZ2-007NaT-Pa for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:58:54 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Thu, 26 Apr 2018 03:57:17 +0800 Message-Id: <20180425195722.20744-4-a@unstable.cc> In-Reply-To: <20180425195722.20744-1-a@unstable.cc> References: <20180425195722.20744-1-a@unstable.cc> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [5.148.176.60 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1fBQZ2-007NaT-Pa Subject: [Openvpn-devel] [RFC 3/8] io_work: convert shift argument to uintptr_t X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox Instead of passing the shift argument as pointer, pass directly its integer value. This will allow the code to distinguish a shift value from a real object pointer, like we already do in multi_tcp_process_io(). This change will allow us later to pass an event_arg object as event handler argument instead of a simple integer value. Signed-off-by: Antonio Quartulli --- src/openvpn/forward.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index c5ddf385..a4e4d98a 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1607,11 +1607,11 @@ io_wait_dowork(struct context *c, const unsigned int flags) struct event_set_return esr[4]; /* These shifts all depend on EVENT_READ and EVENT_WRITE */ - static int socket_shift = 0; /* depends on SOCKET_READ and SOCKET_WRITE */ - static int tun_shift = 2; /* depends on TUN_READ and TUN_WRITE */ - static int err_shift = 4; /* depends on ES_ERROR */ + static uintptr_t socket_shift = 0; /* depends on SOCKET_READ and SOCKET_WRITE */ + static uintptr_t tun_shift = 2; /* depends on TUN_READ and TUN_WRITE */ + static uintptr_t err_shift = 4; /* depends on ES_ERROR */ #ifdef ENABLE_MANAGEMENT - static int management_shift = 6; /* depends on MANAGEMENT_READ and MANAGEMENT_WRITE */ + static uintptr_t management_shift = 6; /* depends on MANAGEMENT_READ and MANAGEMENT_WRITE */ #endif #ifdef ENABLE_ASYNC_PUSH static int file_shift = 8; /* listening inotify events */ @@ -1628,7 +1628,7 @@ io_wait_dowork(struct context *c, const unsigned int flags) */ if (flags & IOW_WAIT_SIGNAL) { - wait_signal(c->c2.event_set, (void *)&err_shift); + wait_signal(c->c2.event_set, (void *)err_shift); } /* @@ -1714,13 +1714,13 @@ io_wait_dowork(struct context *c, const unsigned int flags) /* * Configure event wait based on socket, tuntap flags. */ - socket_set(c->c2.link_socket, c->c2.event_set, socket, (void *)&socket_shift, NULL); - tun_set(c->c1.tuntap, c->c2.event_set, tuntap, (void *)&tun_shift, NULL); + socket_set(c->c2.link_socket, c->c2.event_set, socket, (void *)socket_shift, NULL); + tun_set(c->c1.tuntap, c->c2.event_set, tuntap, (void *)tun_shift, NULL); #ifdef ENABLE_MANAGEMENT if (management) { - management_socket_set(management, c->c2.event_set, (void *)&management_shift, NULL); + management_socket_set(management, c->c2.event_set, (void *)management_shift, NULL); } #endif @@ -1728,7 +1728,7 @@ io_wait_dowork(struct context *c, const unsigned int flags) /* arm inotify watcher */ if (c->options.mode == MODE_SERVER) { - event_ctl(c->c2.event_set, c->c2.inotify_fd, EVENT_READ, (void *)&file_shift); + event_ctl(c->c2.event_set, c->c2.inotify_fd, EVENT_READ, (void *)file_shift); } #endif @@ -1771,7 +1771,7 @@ io_wait_dowork(struct context *c, const unsigned int flags) for (i = 0; i < status; ++i) { const struct event_set_return *e = &esr[i]; - c->c2.event_set_status |= ((e->rwflags & 3) << *((int *)e->arg)); + c->c2.event_set_status |= ((e->rwflags & 3) << (uintptr_t)e->arg); } } else if (status == 0) From patchwork Wed Apr 25 09:57:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 321 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director9.mail.ord1d.rsapps.net ([172.27.255.56]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id XkhNATXe4FrkSwAAIUCqbw for ; Wed, 25 Apr 2018 15:59:49 -0400 Received: from proxy2.mail.iad3a.rsapps.net ([172.27.255.56]) by director9.mail.ord1d.rsapps.net (Dovecot) with LMTP id NUXMCTXe4FqiTQAAalYnBA ; Wed, 25 Apr 2018 15:59:49 -0400 Received: from smtp22.gate.iad3a ([172.27.255.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy2.mail.iad3a.rsapps.net with LMTP id 6AHQDjXe4FrWOgAABcWvHw ; Wed, 25 Apr 2018 15:59:49 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp22.gate.iad3a.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: 34e565ee-48c3-11e8-8797-5254005ae9fe-1-1 Received: from [216.105.38.7] ([216.105.38.7:25802] helo=lists.sourceforge.net) by smtp22.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 0A/11-19165-43ED0EA5; Wed, 25 Apr 2018 15:59:48 -0400 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fBQZ7-0000ov-Gy; Wed, 25 Apr 2018 19:58:57 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fBQZ6-0000on-8x for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:58:56 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=Dlg53LzlfYkXMxlRUSuPIeS9lcNfCnlgSimT2aEVXag=; b=CMob4t8+iS3V8U6HvR8GsGMpWP U7UdyRCQteEMRTO4o0nsm+V4X7UdaEkSSVIhRK2BgoZCwIrHm/kJApLkLJIiS5rAq4myv1ETKSawl TqGR3gIa3oFxiWmb0k61yM7LbJOf3Z+qdoEb9/3v2MHaK4Pg1cM7xD278SuUJL8H4zAQ=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=Dlg53LzlfYkXMxlRUSuPIeS9lcNfCnlgSimT2aEVXag=; b=KUV1fKxMZDQaR46Os7zE9cx/WC WPt/XZfrS2GzcbT8mz2TwBjRw4ekoTkFAzhyJ76Li8PRdzg1QZ6MnCbG3Uvyn8HkgFUZH4W9IugEC S2d22rP9smFv9T5CvmrOoJXDDrjTv32Bsb7tErZDtCUP0P6Jm0stMwwly6PAbsf4f4a0=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fBQZ4-007NaZ-PU for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:58:56 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Thu, 26 Apr 2018 03:57:18 +0800 Message-Id: <20180425195722.20744-5-a@unstable.cc> In-Reply-To: <20180425195722.20744-1-a@unstable.cc> References: <20180425195722.20744-1-a@unstable.cc> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [5.148.176.60 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1fBQZ4-007NaZ-PU Subject: [Openvpn-devel] [RFC 4/8] io_work: pass event_arg object to event handler in case of socket event X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox In order to allow the code to work with multiple listening sockets it is essential to allow the generic multi_io event handler to distinguish between the various socket objects. This can be achieved by passing an event_arg object that contains a pointer to the link_socket. This code path is used on clients as well as UDP servers. Signed-off-by: Antonio Quartulli --- src/openvpn/event.h | 6 ++++++ src/openvpn/forward.c | 25 +++++++++++++++++++++++-- src/openvpn/mtcp.c | 4 +--- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/openvpn/event.h b/src/openvpn/event.h index be199ad9..fd0ede04 100644 --- a/src/openvpn/event.h +++ b/src/openvpn/event.h @@ -41,6 +41,12 @@ #define EVENT_METHOD_US_TIMEOUT (1<<0) #define EVENT_METHOD_FAST (1<<1) +/* + * The following constant is used as boundary between integer value + * and real addresses when passing arguments to event handlers as (void *) + */ +#define MULTI_N ((void *)16) /* upper bound on MTCP_x */ + #ifdef _WIN32 typedef const struct rw_handle *event_t; diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index a4e4d98a..1b5dad9b 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1714,7 +1714,8 @@ io_wait_dowork(struct context *c, const unsigned int flags) /* * Configure event wait based on socket, tuntap flags. */ - socket_set(c->c2.link_socket, c->c2.event_set, socket, (void *)socket_shift, NULL); + socket_set(c->c2.link_socket, c->c2.event_set, socket, + &c->c2.link_socket->ev_arg, NULL); tun_set(c->c1.tuntap, c->c2.event_set, tuntap, (void *)tun_shift, NULL); #ifdef ENABLE_MANAGEMENT @@ -1771,7 +1772,27 @@ io_wait_dowork(struct context *c, const unsigned int flags) for (i = 0; i < status; ++i) { const struct event_set_return *e = &esr[i]; - c->c2.event_set_status |= ((e->rwflags & 3) << (uintptr_t)e->arg); + uintptr_t shift; + + if (e->arg >= MULTI_N) + { + struct event_arg *ev_arg = (struct event_arg *)e->arg; + if (ev_arg->type != EVENT_ARG_LINK_SOCKET) + { + c->c2.event_set_status = ES_ERROR; + msg(D_LINK_ERRORS, + "io_work: non socket event delivered"); + return; + } + + shift = socket_shift; + } + else + { + shift = (uintptr_t)e->arg; + } + + c->c2.event_set_status |= ((e->rwflags & 3) << shift); } } else if (status == 0) diff --git a/src/openvpn/mtcp.c b/src/openvpn/mtcp.c index 51f339d0..0be97ae4 100644 --- a/src/openvpn/mtcp.c +++ b/src/openvpn/mtcp.c @@ -68,8 +68,6 @@ #define MTCP_FILE_CLOSE_WRITE ((void *)5) #endif -#define MTCP_N ((void *)16) /* upper bound on MTCP_x */ - struct ta_iow_flags { unsigned int flags; @@ -682,7 +680,7 @@ multi_tcp_process_io(struct multi_context *m) struct event_arg *ev_arg = (struct event_arg *)e->arg; /* incoming data for instance or listening socket? */ - if (e->arg >= MTCP_N) + if (e->arg >= MULTI_N) { switch (ev_arg->type) { From patchwork Wed Apr 25 09:57:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 326 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director12.mail.ord1d.rsapps.net ([172.27.255.59]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id 1GYPAz/e4FrySwAAIUCqbw for ; Wed, 25 Apr 2018 15:59:59 -0400 Received: from proxy19.mail.iad3a.rsapps.net ([172.27.255.59]) by director12.mail.ord1d.rsapps.net (Dovecot) with LMTP id uf97Gj/e4FovJwAAIasKDg ; Wed, 25 Apr 2018 15:59:59 -0400 Received: from smtp22.gate.iad3a ([172.27.255.59]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy19.mail.iad3a.rsapps.net with LMTP id +AMIHz/e4FpuXgAAXy6Yeg ; Wed, 25 Apr 2018 15:59:59 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp22.gate.iad3a.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: 3b2a69f4-48c3-11e8-8797-5254005ae9fe-1-1 Received: from [216.105.38.7] ([216.105.38.7:58381] helo=lists.sourceforge.net) by smtp22.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 00/31-19165-E3ED0EA5; Wed, 25 Apr 2018 15:59:59 -0400 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fBQZB-00016e-Pf; Wed, 25 Apr 2018 19:59:01 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fBQZ9-00016F-PE for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:58:59 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=WiHdmt89jcBfUD6hNMiauFQ+PfaTDNQoOSX2P41NVcU=; b=CYxjw/0CgNHiAP5b15BZtVNNBO orlfkKTE2Bq3FznJ/+yEGowRUEBPNcllNc6v88a62uhm4LqUvYQM0Tdck+HO/X4JDfrMUrzuerkVk a3ELmVV5vlzySQHzsYrrvZA6TnMaxBR1jFrBslF/+MpclZ8OFFG71KUr6ePDM+S5traE=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=WiHdmt89jcBfUD6hNMiauFQ+PfaTDNQoOSX2P41NVcU=; b=EBM/37iJy5BBa/Tkf5QUoKjYhB gVW8zWNDk/sxrhHPTPeRfY2/NAibk6bykqI6NNeT13Ad+KxlcqAo8rp4HzsYxWu4YO2rvCBBOGESg USyoNO7zLRNYIAi83CuJ9rUgwz/OT5hRdlfdJqMLqHWzBFjmYgHB8riKYz2eGcBXYJOw=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-3.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fBQZ7-00Bt3b-4Z for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:58:59 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Thu, 26 Apr 2018 03:57:19 +0800 Message-Id: <20180425195722.20744-6-a@unstable.cc> In-Reply-To: <20180425195722.20744-1-a@unstable.cc> References: <20180425195722.20744-1-a@unstable.cc> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [5.148.176.60 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1fBQZ7-00Bt3b-4Z Subject: [Openvpn-devel] [RFC 5/8] allow tcp/udp server to listen on multiple ports at the same time X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox Signed-off-by: Antonio Quartulli --- src/openvpn/event.h | 1 + src/openvpn/forward-inline.h | 15 ++- src/openvpn/forward.c | 51 ++++++--- src/openvpn/forward.h | 18 ++-- src/openvpn/init.c | 197 +++++++++++++++++++++++------------ src/openvpn/init.h | 3 +- src/openvpn/mtcp.c | 57 ++++++---- src/openvpn/mudp.c | 19 +++- src/openvpn/mudp.h | 6 +- src/openvpn/multi.c | 24 +++-- src/openvpn/multi.h | 14 ++- src/openvpn/openvpn.c | 2 +- src/openvpn/openvpn.h | 9 +- src/openvpn/ping-inline.h | 2 +- src/openvpn/socket.c | 13 +++ src/openvpn/socket.h | 6 +- 16 files changed, 289 insertions(+), 148 deletions(-) diff --git a/src/openvpn/event.h b/src/openvpn/event.h index fd0ede04..2b9c1b58 100644 --- a/src/openvpn/event.h +++ b/src/openvpn/event.h @@ -100,6 +100,7 @@ typedef enum { struct event_arg { event_arg_t type; + bool pending; /* in UDP/P2P mode marks sockets waiting for processing */ union { struct multi_instance *mi; /* if type = EVENT_ARG_MULTI_INSTANCE */ struct link_socket *ls; /* if type = EVENT_ARG_LINK_SOCKET */ diff --git a/src/openvpn/forward-inline.h b/src/openvpn/forward-inline.h index feb0ba70..29751a1b 100644 --- a/src/openvpn/forward-inline.h +++ b/src/openvpn/forward-inline.h @@ -55,7 +55,8 @@ check_tls_errors(struct context *c) if (c->c2.tls_multi && c->c2.tls_exit_signal) { - if (link_socket_connection_oriented(c->c2.link_socket)) + /* all sockets are of the same type, so just check the first one */ + if (link_socket_connection_oriented(c->c2.link_sockets[0])) { if (c->c2.tls_multi->n_soft_errors) { @@ -254,16 +255,21 @@ context_reschedule_sec(struct context *c, int sec) } } +/* + * This function is invoked only on single-link contexts + * (i.e. p2p or child contexts), therefore we can explicitly + * work on the first socket + */ static inline struct link_socket_info * get_link_socket_info(struct context *c) { - if (c->c2.link_socket_info) + if (c->c2.link_socket_infos && c->c2.link_socket_infos[0]) { - return c->c2.link_socket_info; + return c->c2.link_socket_infos[0]; } else { - return &c->c2.link_socket->info; + return &c->c2.link_sockets[0]->info; } } @@ -330,6 +336,7 @@ io_wait(struct context *c, const unsigned int flags) } } +/* invoked only on single-link instances */ #define CONNECTION_ESTABLISHED(c) (get_link_socket_info(c)->connection_established) #endif /* EVENT_INLINE_H */ diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 1b5dad9b..76c73a6d 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -58,12 +58,18 @@ const char * wait_status_string(struct context *c, struct gc_arena *gc) { struct buffer out = alloc_buf_gc(64, gc); - buf_printf(&out, "I/O WAIT %s|%s|%s|%s %s", + int i; + + buf_printf(&out, "I/O WAIT %s|%s| %s", tun_stat(c->c1.tuntap, EVENT_READ, gc), tun_stat(c->c1.tuntap, EVENT_WRITE, gc), - socket_stat(c->c2.link_socket, EVENT_READ, gc), - socket_stat(c->c2.link_socket, EVENT_WRITE, gc), tv_string(&c->c2.timeval, gc)); + for (i = 0; i < c->c1.link_sockets_num; i++) + { + buf_printf(&out, "\n %s|%s", + socket_stat(c->c2.link_sockets[i], EVENT_READ, gc), + socket_stat(c->c2.link_sockets[i], EVENT_WRITE, gc)); + } return BSTR(&out); } @@ -396,6 +402,7 @@ check_status_file_dowork(struct context *c) #ifdef ENABLE_FRAGMENT /* * Should we deliver a datagram fragment to remote? + * c is expected to be a single-link context (p2p or child) */ void check_fragment_dowork(struct context *c) @@ -405,7 +412,7 @@ check_fragment_dowork(struct context *c) /* OS MTU Hint? */ if (lsi->mtu_changed) { - frame_adjust_path_mtu(&c->c2.frame_fragment, c->c2.link_socket->mtu, + frame_adjust_path_mtu(&c->c2.frame_fragment, c->c2.link_sockets[0]->mtu, c->options.ce.proto); lsi->mtu_changed = false; } @@ -895,7 +902,9 @@ process_incoming_link_part1(struct context *c, struct link_socket_info *lsi, boo decrypt_status = openvpn_decrypt(&c->c2.buf, c->c2.buffers->decrypt_buf, co, &c->c2.frame, ad_start); - if (!decrypt_status && link_socket_connection_oriented(c->c2.link_socket)) + if (!decrypt_status + /* all sockets are of the same type, so just check the first one */ + && link_socket_connection_oriented(c->c2.link_sockets[0])) { /* decryption errors are fatal in TCP mode */ register_signal(c, SIGUSR1, "decryption-error"); /* SOFT-SIGUSR1 -- decryption error in TCP mode */ @@ -1156,7 +1165,7 @@ drop_if_recursive_routing(struct context *c, struct buffer *buf) */ void -process_incoming_tun(struct context *c) +process_incoming_tun(struct context *c, struct link_socket *out_ls) { struct gc_arena gc = gc_new(); @@ -1187,7 +1196,8 @@ process_incoming_tun(struct context *c) * The --passtos and --mssfix options require * us to examine the IP header (IPv4 or IPv6). */ - process_ip_header(c, PIPV4_PASSTOS|PIP_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf); + process_ip_header(c, PIPV4_PASSTOS|PIP_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf, + out_ls); #ifdef PACKET_TRUNCATION_CHECK /* if (c->c2.buf.len > 1) --c->c2.buf.len; */ @@ -1209,7 +1219,8 @@ process_incoming_tun(struct context *c) } void -process_ip_header(struct context *c, unsigned int flags, struct buffer *buf) +process_ip_header(struct context *c, unsigned int flags, struct buffer *buf, + struct link_socket *ls) { if (!c->options.ce.mssfix) { @@ -1251,7 +1262,7 @@ process_ip_header(struct context *c, unsigned int flags, struct buffer *buf) /* extract TOS from IP header */ if (flags & PIPV4_PASSTOS) { - link_socket_extract_tos(c->c2.link_socket, &ipbuf); + link_socket_extract_tos(ls, &ipbuf); } #endif @@ -1445,7 +1456,7 @@ process_outgoing_link(struct context *c, struct link_socket *ls) */ void -process_outgoing_tun(struct context *c) +process_outgoing_tun(struct context *c, struct link_socket *in_ls) { struct gc_arena gc = gc_new(); @@ -1464,7 +1475,8 @@ process_outgoing_tun(struct context *c) * The --mssfix option requires * us to examine the IP header (IPv4 or IPv6). */ - process_ip_header(c, PIP_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun); + process_ip_header(c, PIP_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun, + in_ls); if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN(&c->c2.frame)) { @@ -1616,6 +1628,7 @@ io_wait_dowork(struct context *c, const unsigned int flags) #ifdef ENABLE_ASYNC_PUSH static int file_shift = 8; /* listening inotify events */ #endif + int i; /* * Decide what kind of events we want to wait for. @@ -1714,8 +1727,11 @@ io_wait_dowork(struct context *c, const unsigned int flags) /* * Configure event wait based on socket, tuntap flags. */ - socket_set(c->c2.link_socket, c->c2.event_set, socket, - &c->c2.link_socket->ev_arg, NULL); + for (i = 0; i < c->c1.link_sockets_num; i++) + { + socket_set(c->c2.link_sockets[i], c->c2.event_set, socket, + &c->c2.link_sockets[i]->ev_arg, NULL); + } tun_set(c->c1.tuntap, c->c2.event_set, tuntap, (void *)tun_shift, NULL); #ifdef ENABLE_MANAGEMENT @@ -1747,7 +1763,7 @@ io_wait_dowork(struct context *c, const unsigned int flags) if (!c->sig->signal_received) { - if (!(flags & IOW_CHECK_RESIDUAL) || !socket_read_residual(c->c2.link_socket)) + if (!(flags & IOW_CHECK_RESIDUAL) || !sockets_read_residual(c)) { int status; @@ -1786,6 +1802,9 @@ io_wait_dowork(struct context *c, const unsigned int flags) } shift = socket_shift; + /* mark socket so that the multi code knows where we + * have pending i/o */ + ev_arg->pending = true; } else { @@ -1839,7 +1858,7 @@ process_io(struct context *c, struct link_socket *ls) /* TUN device ready to accept write */ else if (status & TUN_WRITE) { - process_outgoing_tun(c); + process_outgoing_tun(c, ls); } /* Incoming data on TCP/UDP port */ else if (status & SOCKET_READ) @@ -1856,7 +1875,7 @@ process_io(struct context *c, struct link_socket *ls) read_incoming_tun(c); if (!IS_SIG(c)) { - process_incoming_tun(c); + process_incoming_tun(c, ls); } } } diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 16639f75..45f8cc59 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -227,10 +227,12 @@ void read_incoming_tun(struct context *c); * * If an error occurs, it is logged and the packet is dropped. * - * @param c - The context structure of the VPN tunnel associated with the - * packet. + * @param c The context structure of the VPN tunnel associated with + * the packet. + * @param out_ls Socket that will be used to send out the packet. + * */ -void process_incoming_tun(struct context *c); +void process_incoming_tun(struct context *c, struct link_socket *out_ls); /** @@ -242,10 +244,11 @@ void process_incoming_tun(struct context *c); * * If an error occurs, it is logged and the packet is dropped. * - * @param c - The context structure of the VPN tunnel associated with - * the packet. + * @param c The context structure of the VPN tunnel associated + * with the packet. + * @param in_ls Socket where the packet was received. */ -void process_outgoing_tun(struct context *c); +void process_outgoing_tun(struct context *c, struct link_socket *in_ls); /**************************************************************************/ @@ -258,7 +261,8 @@ bool send_control_channel_string(struct context *c, const char *str, int msgleve #define PIPV4_EXTRACT_DHCP_ROUTER (1<<3) #define PIPV4_CLIENT_NAT (1<<4) -void process_ip_header(struct context *c, unsigned int flags, struct buffer *buf); +void process_ip_header(struct context *c, unsigned int flags, struct buffer *buf, + struct link_socket *ls); #if P2MP void schedule_exit(struct context *c, const int n_seconds, const int signal); diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 36c1a4c4..a2b474c8 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -440,11 +440,11 @@ next_connection_entry(struct context *c) { /* Check if there is another resolved address to try for * the current connection */ - if (c->c1.link_socket_addr.current_remote - && c->c1.link_socket_addr.current_remote->ai_next) + if (c->c1.link_socket_addrs[0].current_remote + && c->c1.link_socket_addrs[0].current_remote->ai_next) { - c->c1.link_socket_addr.current_remote = - c->c1.link_socket_addr.current_remote->ai_next; + c->c1.link_socket_addrs[0].current_remote = + c->c1.link_socket_addrs[0].current_remote->ai_next; } else { @@ -455,13 +455,13 @@ next_connection_entry(struct context *c) if (!c->options.persist_remote_ip) { /* close_instance should have cleared the addrinfo objects */ - ASSERT(c->c1.link_socket_addr.current_remote == NULL); - ASSERT(c->c1.link_socket_addr.remote_list == NULL); + ASSERT(c->c1.link_socket_addrs[0].current_remote == NULL); + ASSERT(c->c1.link_socket_addrs[0].remote_list == NULL); } else { - c->c1.link_socket_addr.current_remote = - c->c1.link_socket_addr.remote_list; + c->c1.link_socket_addrs[0].current_remote = + c->c1.link_socket_addrs[0].remote_list; } /* @@ -611,6 +611,13 @@ uninit_proxy(struct context *c) uninit_proxy_dowork(c); } +static void +do_link_socket_addr_new(struct context *c) +{ + ALLOC_ARRAY_CLEAR_GC(c->c1.link_socket_addrs, struct link_socket_addr, + c->c1.link_sockets_num, &c->gc); +} + void context_init_1(struct context *c) { @@ -620,6 +627,10 @@ context_init_1(struct context *c) init_connection_list(c); + c->c1.link_sockets_num = 1; + + do_link_socket_addr_new(c); + #if defined(ENABLE_PKCS11) if (c->first_time) { @@ -1531,7 +1542,7 @@ initialization_sequence_completed(struct context *c, const unsigned int flags) CLEAR(local); actual = &get_link_socket_info(c)->lsa->actual; remote = actual->dest; - getsockname(c->c2.link_socket->sd, &local.addr.sa, &sa_len); + getsockname(c->c2.link_sockets[0]->sd, &local.addr.sa, &sa_len); #if ENABLE_IP_PKTINFO if (!addr_defined(&local)) { @@ -1641,8 +1652,8 @@ do_init_tun(struct context *c) c->options.ifconfig_ipv6_local, c->options.ifconfig_ipv6_netbits, c->options.ifconfig_ipv6_remote, - c->c1.link_socket_addr.bind_local, - c->c1.link_socket_addr.remote_list, + c->c1.link_socket_addrs[0].bind_local, + c->c1.link_socket_addrs[0].remote_list, !c->options.ifconfig_nowarn, c->c2.es); @@ -1691,16 +1702,16 @@ do_open_tun(struct context *c) do_alloc_route_list(c); /* parse and resolve the route option list */ - ASSERT(c->c2.link_socket); + ASSERT(c->c2.link_sockets); if (c->options.routes && c->c1.route_list) { do_init_route_list(&c->options, c->c1.route_list, - &c->c2.link_socket->info, c->c2.es); + &c->c2.link_sockets[0]->info, c->c2.es); } if (c->options.routes_ipv6 && c->c1.route_ipv6_list) { do_init_route_ipv6_list(&c->options, c->c1.route_ipv6_list, - &c->c2.link_socket->info, c->c2.es); + &c->c2.link_sockets[0]->info, c->c2.es); } /* do ifconfig */ @@ -2175,14 +2186,28 @@ do_deferred_options(struct context *c, const unsigned int found) if (found & OPT_P_SOCKBUF) { + int i; + msg(D_PUSH, "OPTIONS IMPORT: --sndbuf/--rcvbuf options modified"); - link_socket_update_buffer_sizes(c->c2.link_socket, c->options.rcvbuf, c->options.sndbuf); + + for (i = 0; i < c->c1.link_sockets_num; i++) + { + link_socket_update_buffer_sizes(c->c2.link_sockets[i], + c->options.rcvbuf, + c->options.sndbuf); + } } if (found & OPT_P_SOCKFLAGS) { + int i; + msg(D_PUSH, "OPTIONS IMPORT: --socket-flags option modified"); - link_socket_update_flags(c->c2.link_socket, c->options.sockflags); + for (i = 0; i < c->c1.link_sockets_num; i++) + { + link_socket_update_flags(c->c2.link_sockets[i], + c->options.sockflags); + } } if (found & OPT_P_PERSIST) @@ -3189,18 +3214,28 @@ do_init_fragment(struct context *c) static void do_link_socket_new(struct context *c) { - ASSERT(!c->c2.link_socket); - c->c2.link_socket = link_socket_new(); + int i; + + ASSERT(!c->c2.link_sockets); + + ALLOC_ARRAY_GC(c->c2.link_sockets, struct link_socket *, + c->c1.link_sockets_num, &c->c2.gc); + + for (i = 0; i < c->c1.link_sockets_num; i++) + { + c->c2.link_sockets[i] = link_socket_new(); + } c->c2.link_socket_owned = true; } /* - * bind the TCP/UDP socket + * bind TCP/UDP sockets */ static void do_init_socket_1(struct context *c, const int mode) { unsigned int sockflags = c->options.sockflags; + int i; #if PORT_SHARE if (c->options.port_share_host && c->options.port_share_port) @@ -3209,45 +3244,53 @@ do_init_socket_1(struct context *c, const int mode) } #endif - link_socket_init_phase1(c->c2.link_socket, - c->options.ce.local, - c->options.ce.local_port, - c->options.ce.remote, - c->options.ce.remote_port, - c->c1.dns_cache, - c->options.ce.proto, - c->options.ce.af, - c->options.ce.bind_ipv6_only, - mode, - c->c2.accept_from, - c->c1.http_proxy, - c->c1.socks_proxy, + for (i = 0; i < c->c1.link_sockets_num; i++) + { + /* init each socket with its specific port */ + link_socket_init_phase1(c->c2.link_sockets[i], + c->options.ce.local, + c->options.ce.local_port, + c->options.ce.remote, + c->options.ce.remote_port, + c->c1.dns_cache, + c->options.ce.proto, + c->options.ce.af, + c->options.ce.bind_ipv6_only, + mode, + c->c2.accept_from, + c->c1.http_proxy, + c->c1.socks_proxy, #ifdef ENABLE_DEBUG - c->options.gremlin, + c->options.gremlin, #endif - c->options.ce.bind_local, - c->options.ce.remote_float, - c->options.inetd, - &c->c1.link_socket_addr, - c->options.ipchange, - c->plugins, - c->options.resolve_retry_seconds, - c->options.ce.mtu_discover_type, - c->options.rcvbuf, - c->options.sndbuf, - c->options.mark, - &c->c2.server_poll_interval, - sockflags); + c->options.ce.bind_local, + c->options.ce.remote_float, + c->options.inetd, + &c->c1.link_socket_addrs[i], + c->options.ipchange, + c->plugins, + c->options.resolve_retry_seconds, + c->options.ce.mtu_discover_type, + c->options.rcvbuf, + c->options.sndbuf, + c->options.mark, + &c->c2.server_poll_interval, + sockflags); + } } /* - * finalize the TCP/UDP socket + * finalize TCP/UDP sockets */ static void do_init_socket_2(struct context *c) { - link_socket_init_phase2(c->c2.link_socket, &c->c2.frame, - c->sig); + int i; + + for (i = 0; i < c->c1.link_sockets_num; i++) + { + link_socket_init_phase2(c->c2.link_sockets[i], &c->c2.frame, c->sig); + } } /* @@ -3410,10 +3453,15 @@ do_close_free_key_schedule(struct context *c, bool free_ssl_ctx) static void do_close_link_socket(struct context *c) { - if (c->c2.link_socket && c->c2.link_socket_owned) + if (c->c2.link_sockets && c->c2.link_socket_owned) { - link_socket_close(c->c2.link_socket); - c->c2.link_socket = NULL; + int i; + + for (i = 0; i < c->c1.link_sockets_num; i++) + { + link_socket_close(c->c2.link_sockets[i]); + } + c->c2.link_sockets = NULL; } @@ -3424,27 +3472,33 @@ do_close_link_socket(struct context *c) && ( (c->options.persist_remote_ip) || ( c->sig->source != SIG_SOURCE_HARD - && ((c->c1.link_socket_addr.current_remote && c->c1.link_socket_addr.current_remote->ai_next) + && ((c->c1.link_socket_addrs[0].current_remote + && c->c1.link_socket_addrs[0].current_remote->ai_next) || c->options.no_advance)) ))) { - clear_remote_addrlist(&c->c1.link_socket_addr, !c->options.resolve_in_advance); + clear_remote_addrlist(&c->c1.link_socket_addrs[0], + !c->options.resolve_in_advance); } /* Clear the remote actual address when persist_remote_ip is not in use */ if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_remote_ip)) { - CLEAR(c->c1.link_socket_addr.actual); + CLEAR(c->c1.link_socket_addrs[0].actual); } - if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_local_ip)) + for (int i = 0; i < c->c1.link_sockets_num; i++) { - if (c->c1.link_socket_addr.bind_local && !c->options.resolve_in_advance) + if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_local_ip)) { - freeaddrinfo(c->c1.link_socket_addr.bind_local); - } + if (c->c1.link_socket_addrs[i].bind_local + && !c->options.resolve_in_advance) + { + freeaddrinfo(c->c1.link_socket_addrs[i].bind_local); + } - c->c1.link_socket_addr.bind_local = NULL; + c->c1.link_socket_addrs[i].bind_local = NULL; + } } } @@ -4311,7 +4365,8 @@ close_instance(struct context *c) void inherit_context_child(struct context *dest, - const struct context *src) + const struct context *src, + struct link_socket *ls) { CLEAR(*dest); @@ -4345,7 +4400,7 @@ inherit_context_child(struct context *dest, * The CM_TOP context does the socket listen(), * and the CM_CHILD_TCP context does the accept(). */ - dest->c2.accept_from = src->c2.link_socket; + dest->c2.accept_from = ls; } #ifdef ENABLE_PLUGIN @@ -4366,18 +4421,26 @@ inherit_context_child(struct context *dest, /* UDP inherits some extra things which TCP does not */ if (dest->mode == CM_CHILD_UDP) { + ASSERT(!dest->c2.link_sockets); + /* inherit buffers */ dest->c2.buffers = src->c2.buffers; + ALLOC_ARRAY_GC(dest->c2.link_sockets, struct link_socket *, 1, + &dest->gc); + /* inherit parent link_socket and tuntap */ - dest->c2.link_socket = src->c2.link_socket; + dest->c2.link_sockets[0] = ls; - ALLOC_OBJ_GC(dest->c2.link_socket_info, struct link_socket_info, &dest->gc); - *dest->c2.link_socket_info = src->c2.link_socket->info; + ALLOC_ARRAY_GC(dest->c2.link_socket_infos, struct link_socket_info *, 1, + &dest->gc); + ALLOC_OBJ_GC(dest->c2.link_socket_infos[0], struct link_socket_info, + &dest->gc); + *dest->c2.link_socket_infos[0] = ls->info; /* locally override some link_socket_info fields */ - dest->c2.link_socket_info->lsa = &dest->c1.link_socket_addr; - dest->c2.link_socket_info->connection_established = false; + dest->c2.link_socket_infos[0]->lsa = &dest->c1.link_socket_addrs[0]; + dest->c2.link_socket_infos[0]->connection_established = false; } } diff --git a/src/openvpn/init.h b/src/openvpn/init.h index c8ebe768..590dd81b 100644 --- a/src/openvpn/init.h +++ b/src/openvpn/init.h @@ -97,7 +97,8 @@ void reset_coarse_timers(struct context *c); bool do_deferred_options(struct context *c, const unsigned int found); void inherit_context_child(struct context *dest, - const struct context *src); + const struct context *src, + struct link_socket *ls); void inherit_context_top(struct context *dest, const struct context *src); diff --git a/src/openvpn/mtcp.c b/src/openvpn/mtcp.c index 0be97ae4..78d127b6 100644 --- a/src/openvpn/mtcp.c +++ b/src/openvpn/mtcp.c @@ -120,13 +120,13 @@ pract(int action) } static struct multi_instance * -multi_create_instance_tcp(struct multi_context *m) +multi_create_instance_tcp(struct multi_context *m, struct link_socket *ls) { struct gc_arena gc = gc_new(); struct multi_instance *mi = NULL; struct hash *hash = m->hash; - mi = multi_create_instance(m, NULL); + mi = multi_create_instance(m, NULL, ls); if (mi) { struct hash_element *he; @@ -174,13 +174,16 @@ multi_tcp_instance_specific_init(struct multi_context *m, struct multi_instance /* buffer for queued TCP socket output packets */ mi->tcp_link_out_deferred = mbuf_init(m->top.options.n_bcast_buf); - ASSERT(mi->context.c2.link_socket); - ASSERT(mi->context.c2.link_socket->info.lsa); - ASSERT(mi->context.c2.link_socket->mode == LS_MODE_TCP_ACCEPT_FROM); - ASSERT(mi->context.c2.link_socket->info.lsa->actual.dest.addr.sa.sa_family == AF_INET - || mi->context.c2.link_socket->info.lsa->actual.dest.addr.sa.sa_family == AF_INET6 + ASSERT(mi->context.c2.link_sockets); + ASSERT(mi->context.c2.link_sockets[0]); + ASSERT(mi->context.c2.link_sockets[0]->info.lsa); + ASSERT(mi->context.c2.link_sockets[0]->mode == LS_MODE_TCP_ACCEPT_FROM); + ASSERT(mi->context.c2.link_sockets[0]->info.lsa->actual.dest.addr.sa.sa_family == AF_INET + || mi->context.c2.link_sockets[0]->info.lsa->actual.dest.addr.sa.sa_family == AF_INET6 ); - if (!mroute_extract_openvpn_sockaddr(&mi->real, &mi->context.c2.link_socket->info.lsa->actual.dest, true)) + if (!mroute_extract_openvpn_sockaddr(&mi->real, + &mi->context.c2.link_sockets[0]->info.lsa->actual.dest, + true)) { msg(D_MULTI_ERRORS, "MULTI TCP: TCP client address is undefined"); return false; @@ -239,7 +242,7 @@ multi_tcp_free(struct multi_tcp *mtcp) void multi_tcp_dereference_instance(struct multi_tcp *mtcp, struct multi_instance *mi) { - struct link_socket *ls = mi->context.c2.link_socket; + struct link_socket *ls = mi->context.c2.link_sockets[0]; if (ls && mi->socket_set_called) { event_del(mtcp->es, socket_event_handle(ls)); @@ -253,7 +256,7 @@ multi_tcp_set_global_rw_flags(struct multi_context *m, struct multi_instance *mi if (mi) { mi->socket_set_called = true; - socket_set(mi->context.c2.link_socket, + socket_set(mi->context.c2.link_sockets[0], m->mtcp->es, mbuf_defined(mi->tcp_link_out_deferred) ? EVENT_WRITE : EVENT_READ, &mi->ev_arg, @@ -265,9 +268,14 @@ static inline int multi_tcp_wait(const struct context *c, struct multi_tcp *mtcp) { - int status; - socket_set_listen_persistent(c->c2.link_socket, mtcp->es, - &c->c2.link_socket->ev_arg); + int status, i; + + for (i = 0; i < c->c1.link_sockets_num; i++) + { + socket_set_listen_persistent(c->c2.link_sockets[i], mtcp->es, + &c->c2.link_sockets[i]->ev_arg); + } + tun_set(c->c1.tuntap, mtcp->es, EVENT_READ, MTCP_TUN, &mtcp->tun_rwflags); #ifdef ENABLE_MANAGEMENT if (management) @@ -466,16 +474,18 @@ multi_tcp_dispatch(struct multi_context *m, struct multi_instance *mi, const int case TA_SOCKET_READ: case TA_SOCKET_READ_RESIDUAL: ASSERT(mi); - ASSERT(mi->context.c2.link_socket); + ASSERT(mi->context.c2.link_sockets); + ASSERT(mi->context.c2.link_sockets[0]); set_prefix(mi); - read_incoming_link(&mi->context, mi->context.c2.link_socket); + read_incoming_link(&mi->context, mi->context.c2.link_sockets[0]); clear_prefix(); if (!IS_SIG(&mi->context)) { - multi_process_incoming_link(m, mi, mpp_flags); + multi_process_incoming_link(m, mi, mpp_flags, + mi->context.c2.link_sockets[0]); if (!IS_SIG(&mi->context)) { - stream_buf_read_setup(mi->context.c2.link_socket); + stream_buf_read_setup(mi->context.c2.link_sockets[0]); } } break; @@ -551,7 +561,7 @@ multi_tcp_post(struct multi_context *m, struct multi_instance *mi, const int act break; case MTP_NONE: - if (mi && socket_read_residual(c->c2.link_socket)) + if (mi && sockets_read_residual(c)) { newaction = TA_SOCKET_READ_RESIDUAL; } @@ -706,9 +716,14 @@ multi_tcp_process_io(struct multi_context *m) break; /* new incoming TCP client attempting to connect? */ case EVENT_ARG_LINK_SOCKET: - ASSERT(m->top.c2.link_socket); - socket_reset_listen_persistent(m->top.c2.link_socket); - mi = multi_create_instance_tcp(m); + if (!ev_arg->u.ls) + { + msg(D_MULTI_ERRORS, "MULTI: mtcp_proc_io: null socket"); + break; + } + + socket_reset_listen_persistent(ev_arg->u.ls); + mi = multi_create_instance_tcp(m, ev_arg->u.ls); if (mi) { multi_tcp_action(m, mi, TA_INITIAL, false); diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c index 80efefb3..bfe24c01 100644 --- a/src/openvpn/mudp.c +++ b/src/openvpn/mudp.c @@ -48,7 +48,8 @@ */ struct multi_instance * -multi_get_create_instance_udp(struct multi_context *m, bool *floated) +multi_get_create_instance_udp(struct multi_context *m, bool *floated, + struct link_socket *ls) { struct gc_arena gc = gc_new(); struct mroute_addr real; @@ -102,7 +103,7 @@ multi_get_create_instance_udp(struct multi_context *m, bool *floated) { if (frequency_limit_event_allowed(m->new_connection_limiter)) { - mi = multi_create_instance(m, &real); + mi = multi_create_instance(m, &real, ls); if (mi) { int i; @@ -227,10 +228,18 @@ multi_process_io_udp(struct multi_context *m) /* Incoming data on UDP port */ else if (status & SOCKET_READ) { - read_incoming_link(&m->top, m->top.c2.link_socket); - if (!IS_SIG(&m->top)) + int i; + for (i = 0; i < m->top.c1.link_sockets_num; i++) { - multi_process_incoming_link(m, NULL, mpp_flags); + if (!m->top.c2.link_sockets[i]->ev_arg.pending) + continue; + + read_incoming_link(&m->top, m->top.c2.link_sockets[i]); + if (!IS_SIG(&m->top)) + { + multi_process_incoming_link(m, NULL, mpp_flags, + m->top.c2.link_sockets[i]); + } } } /* Incoming data on TUN device */ diff --git a/src/openvpn/mudp.h b/src/openvpn/mudp.h index 7e311519..3ab442ba 100644 --- a/src/openvpn/mudp.h +++ b/src/openvpn/mudp.h @@ -58,13 +58,15 @@ void tunnel_server_udp(struct context *top); * it. If no entry exists, this function handles its creation, and if * successful, returns the newly created instance. * - * @param m - The single multi_context structure. + * @param m - The single multi_context structure. + * @param ls - Listening socket where this instance is connecting to * * @return A pointer to a multi_instance if one already existed for the * packet's source address or if one was a newly created successfully. * NULL if one did not yet exist and a new one was not created. */ -struct multi_instance *multi_get_create_instance_udp(struct multi_context *m, bool *floated); +struct multi_instance *multi_get_create_instance_udp(struct multi_context *m, bool *floated, + struct link_socket *ls); #endif #endif diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index f877c060..a6534c16 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -765,7 +765,8 @@ multi_uninit(struct multi_context *m) * Create a client instance object for a newly connected client. */ struct multi_instance * -multi_create_instance(struct multi_context *m, const struct mroute_addr *real) +multi_create_instance(struct multi_context *m, const struct mroute_addr *real, + struct link_socket *ls) { struct gc_arena gc = gc_new(); struct multi_instance *mi; @@ -789,7 +790,7 @@ multi_create_instance(struct multi_context *m, const struct mroute_addr *real) } mi->did_open_context = true; - inherit_context_child(&mi->context, &m->top); + inherit_context_child(&mi->context, &m->top, ls); if (IS_SIG(&mi->context)) { goto err; @@ -2409,7 +2410,8 @@ multi_process_post(struct multi_context *m, struct multi_instance *mi, const uns } void -multi_process_float(struct multi_context *m, struct multi_instance *mi) +multi_process_float(struct multi_context *m, struct multi_instance *mi, + struct link_socket *ls) { struct mroute_addr real; struct hash *hash = m->hash; @@ -2465,8 +2467,8 @@ multi_process_float(struct multi_context *m, struct multi_instance *mi) mi->context.c2.to_link_addr = &mi->context.c2.from; /* inherit parent link_socket and link_socket_info */ - mi->context.c2.link_socket = m->top.c2.link_socket; - mi->context.c2.link_socket_info->lsa->actual = m->top.c2.from; + mi->context.c2.link_sockets[0] = ls; + mi->context.c2.link_socket_infos[0]->lsa->actual = m->top.c2.from; tls_update_remote_addr(mi->context.c2.tls_multi, &mi->context.c2.from); @@ -2486,7 +2488,8 @@ done: * i.e. client -> server direction. */ bool -multi_process_incoming_link(struct multi_context *m, struct multi_instance *instance, const unsigned int mpp_flags) +multi_process_incoming_link(struct multi_context *m, struct multi_instance *instance, const unsigned int mpp_flags, + struct link_socket *ls) { struct gc_arena gc = gc_new(); @@ -2507,7 +2510,7 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst #ifdef MULTI_DEBUG_EVENT_LOOP printf("TCP/UDP -> TUN [%d]\n", BLEN(&m->top.c2.buf)); #endif - multi_set_pending(m, multi_get_create_instance_udp(m, &floated)); + multi_set_pending(m, multi_get_create_instance_udp(m, &floated, ls)); } else { @@ -2547,7 +2550,7 @@ multi_process_incoming_link(struct multi_context *m, struct multi_instance *inst { if (floated) { - multi_process_float(m, m->pending); + multi_process_float(m, m->pending, ls); } process_incoming_link_part2(c, lsi, orig_buf); @@ -2816,7 +2819,7 @@ multi_process_incoming_tun(struct multi_context *m, const unsigned int mpp_flags } /* encrypt in instance context */ - process_incoming_tun(c); + process_incoming_tun(c, c->c2.link_sockets[0]); /* postprocess and set wakeup */ ret = multi_process_post(m, m->pending, mpp_flags); @@ -2849,7 +2852,8 @@ multi_get_queue(struct mbuf_set *ms) { pip_flags |= PIP_MSSFIX; } - process_ip_header(&item.instance->context, pip_flags, &item.instance->context.c2.buf); + process_ip_header(&item.instance->context, pip_flags, &item.instance->context.c2.buf, + item.instance->context.c2.link_sockets[0]); encrypt_sign(&item.instance->context, true); mbuf_free_buf(item.buffer); diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 5fb8402f..a7bb0852 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -238,7 +238,8 @@ void multi_top_init(struct multi_context *m, const struct context *top); void multi_top_free(struct multi_context *m); -struct multi_instance *multi_create_instance(struct multi_context *m, const struct mroute_addr *real); +struct multi_instance *multi_create_instance(struct multi_context *m, const struct mroute_addr *real, + struct link_socket *ls); void multi_close_instance(struct multi_context *m, struct multi_instance *mi, bool shutdown); @@ -252,7 +253,8 @@ bool multi_process_timeout(struct multi_context *m, const unsigned int mpp_flags * existing peer. Updates multi_instance with new address, * updates hashtables in multi_context. */ -void multi_process_float(struct multi_context *m, struct multi_instance *mi); +void multi_process_float(struct multi_context *m, struct multi_instance *mi, + struct link_socket *ls); #define MPP_PRE_SELECT (1<<0) #define MPP_CONDITIONAL_PRE_SELECT (1<<1) @@ -307,8 +309,10 @@ bool multi_process_post(struct multi_context *m, struct multi_instance *mi, cons * when using TCP transport. Otherwise NULL, as is * the case when using UDP transport. * @param mpp_flags - Fast I/O optimization flags. + * @param ls - Socket where the packet was received. */ -bool multi_process_incoming_link(struct multi_context *m, struct multi_instance *instance, const unsigned int mpp_flags); +bool multi_process_incoming_link(struct multi_context *m, struct multi_instance *instance, const unsigned int mpp_flags, + struct link_socket *ls); /** @@ -624,7 +628,7 @@ multi_process_outgoing_tun(struct multi_context *m, const unsigned int mpp_flags mi->context.c2.to_tun.len); #endif set_prefix(mi); - process_outgoing_tun(&mi->context); + process_outgoing_tun(&mi->context, mi->context.c2.link_sockets[0]); ret = multi_process_post(m, mi, mpp_flags); clear_prefix(); return ret; @@ -637,7 +641,7 @@ multi_process_outgoing_link_dowork(struct multi_context *m, struct multi_instanc { bool ret = true; set_prefix(mi); - process_outgoing_link(&mi->context, mi->context.c2.link_socket); + process_outgoing_link(&mi->context, mi->context.c2.link_sockets[0]); ret = multi_process_post(m, mi, mpp_flags); clear_prefix(); return ret; diff --git a/src/openvpn/openvpn.c b/src/openvpn/openvpn.c index b52063a2..4cd6ecf1 100644 --- a/src/openvpn/openvpn.c +++ b/src/openvpn/openvpn.c @@ -115,7 +115,7 @@ tunnel_point_to_point(struct context *c) } /* process the I/O which triggered select */ - process_io(c, c->c2.link_socket); + process_io(c, c->c2.link_sockets[0]); P2P_CHECK_SIG(); perf_pop(); diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h index c5c767c0..17509d75 100644 --- a/src/openvpn/openvpn.h +++ b/src/openvpn/openvpn.h @@ -149,7 +149,8 @@ struct context_0 */ struct context_1 { - struct link_socket_addr link_socket_addr; + int link_sockets_num; + struct link_socket_addr *link_socket_addrs; /**< Local and remote addresses on the * external network. */ @@ -247,9 +248,11 @@ struct context_2 unsigned int event_set_status; - struct link_socket *link_socket; /* socket used for TCP/UDP connection to remote */ + struct link_socket **link_sockets; + struct link_socket_info **link_socket_infos; + bool link_socket_owned; - struct link_socket_info *link_socket_info; + const struct link_socket *accept_from; /* possibly do accept() on a parent link_socket */ struct link_socket_actual *to_link_addr; /* IP address of remote */ diff --git a/src/openvpn/ping-inline.h b/src/openvpn/ping-inline.h index 1a5c8bc3..d5f5d0d6 100644 --- a/src/openvpn/ping-inline.h +++ b/src/openvpn/ping-inline.h @@ -37,7 +37,7 @@ check_ping_restart(struct context *c) && event_timeout_trigger(&c->c2.ping_rec_interval, &c->c2.timeval, (!c->options.ping_timer_remote - || link_socket_actual_defined(&c->c1.link_socket_addr.actual)) + || link_socket_actual_defined(&c->c1.link_socket_addrs[0].actual)) ? ETT_DEFAULT : 15)) { check_ping_restart_dowork(c); diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 564948a2..84d828e6 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -54,6 +54,19 @@ const int proto_overhead[] = { /* indexed by PROTO_x */ IPv6_TCP_HEADER_SIZE, }; +bool +sockets_read_residual(const struct context *c) +{ + int i; + + for (i = 0; i < c->c1.link_sockets_num; i++) + { + if (c->c2.link_sockets[i]->stream_buf.residual_fully_formed) + return true; + } + return false; +} + /* * Convert sockflags/getaddr_flags into getaddr_flags */ diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h index 46000246..c80a230d 100644 --- a/src/openvpn/socket.h +++ b/src/openvpn/socket.h @@ -1220,11 +1220,7 @@ link_socket_set_tos(struct link_socket *ls) * Socket I/O wait functions */ -static inline bool -socket_read_residual(const struct link_socket *s) -{ - return s && s->stream_buf.residual_fully_formed; -} +bool sockets_read_residual(const struct context *c); static inline event_t socket_event_handle(const struct link_socket *s) From patchwork Wed Apr 25 09:57:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 325 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director11.mail.ord1d.rsapps.net ([172.27.255.1]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id S8/ADj3e4FqcWAAAIUCqbw for ; Wed, 25 Apr 2018 15:59:57 -0400 Received: from proxy6.mail.iad3a.rsapps.net ([172.27.255.1]) by director11.mail.ord1d.rsapps.net (Dovecot) with LMTP id 04YjCD3e4FozOAAAvGGmqA ; Wed, 25 Apr 2018 15:59:57 -0400 Received: from smtp34.gate.iad3a ([172.27.255.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy6.mail.iad3a.rsapps.net with LMTP id sK3dBT3e4FqPbQAA8udqhg ; Wed, 25 Apr 2018 15:59:57 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp34.gate.iad3a.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: 39c00eac-48c3-11e8-b24d-525400865cc7-1-1 Received: from [216.105.38.7] ([216.105.38.7:39475] helo=lists.sourceforge.net) by smtp34.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 82/AC-03217-C3ED0EA5; Wed, 25 Apr 2018 15:59:56 -0400 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fBQZG-00017t-V0; Wed, 25 Apr 2018 19:59:06 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fBQZF-00017d-Gi for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:59:05 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=bfDuMYy+lNV8OKfV/j0KlWI8aAr6esWeb2hiXOdCxQ8=; b=k5PDgOZ/1byH6jKNyZfYaPdFKI vgWbi1f12GdQb0erx7nD3tIHEoUiBT6fokJjly8Ckv96gBUn1MJvC/Q5P7hzauSB0kWU1kZ0EHdKS iZGomLtmwZ/x2qnI2zHn0v+fW2hp+HvdH2vTaLdFC3t1rWbaBRG2/jaiu3WQWtuEOjRs=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=bfDuMYy+lNV8OKfV/j0KlWI8aAr6esWeb2hiXOdCxQ8=; b=KvkFGNmk2paPQx4DERaoC2T2B3 qT0MOWqG9EXwsDnUZ8giNrrsA8GuSegyVhdot/FTUyJVweRVXIi//UTDiGbbSl/gz5lOzg5VRK+VV yLsrfqtaYK6BmZWdvlAFmLy8bW+qf8LLyoU1ZXQabO07tp1cIofph1EJ4Spw0uVuPPGg=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fBQZE-009L9F-36 for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:59:05 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Thu, 26 Apr 2018 03:57:20 +0800 Message-Id: <20180425195722.20744-7-a@unstable.cc> In-Reply-To: <20180425195722.20744-1-a@unstable.cc> References: <20180425195722.20744-1-a@unstable.cc> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [5.148.176.60 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1fBQZE-009L9F-36 Subject: [Openvpn-devel] [RFC 6/8] if a local IPv6 address is provided, socket must be v6-only X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox Signed-off-by: Antonio Quartulli --- src/openvpn/socket.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 84d828e6..79fbc6a8 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -988,9 +988,15 @@ bind_local(struct link_socket *sock, const sa_family_t ai_family) } else { + bool v6only = sock->info.bind_ipv6_only; + + /* force binding IPv6-only if an address was specified + * an it is a IPv6 */ + if (sock->local_host && ai_family == AF_INET6) + v6only = true; + socket_bind(sock->sd, sock->info.lsa->bind_local, - ai_family, - "TCP/UDP", sock->info.bind_ipv6_only); + ai_family, "TCP/UDP", v6only); } } } From patchwork Wed Apr 25 09:57:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 328 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director11.mail.ord1d.rsapps.net ([172.27.255.9]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id jyr/Akfe4FrySwAAIUCqbw for ; Wed, 25 Apr 2018 16:00:07 -0400 Received: from proxy9.mail.iad3a.rsapps.net ([172.27.255.9]) by director11.mail.ord1d.rsapps.net (Dovecot) with LMTP id 6aDnAEfe4FpmOAAAvGGmqA ; Wed, 25 Apr 2018 16:00:07 -0400 Received: from smtp5.gate.iad3a ([172.27.255.9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy9.mail.iad3a.rsapps.net with LMTP id QDWLBEfe4FprFgAAGuSQww ; Wed, 25 Apr 2018 16:00:07 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp5.gate.iad3a.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: 3f91fb6a-48c3-11e8-94c3-525400de824c-1-1 Received: from [216.105.38.7] ([216.105.38.7:27937] helo=lists.sourceforge.net) by smtp5.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 5D/95-16262-64ED0EA5; Wed, 25 Apr 2018 16:00:06 -0400 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fBQZH-0008Sn-Rz; Wed, 25 Apr 2018 19:59:07 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fBQZH-0008SY-6W for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:59:07 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=SofSjai1r/yUWSa5boXgKbCjiaJzE8WKH/RvkBd29mU=; b=bt/ph1Pdd5hFZIG+tLT96p61gg NEd752Nl+0t4ULPqSY32kNdNS3wn8FnIWRvTFB895noNjIzt4kuHeMdo8Rhz/HR3P5DRpOCZXBmk2 jeDJ3upAABsdyipHHuPQcLqfMMqDLN2qCnfICQ+7sRLo02JNs6jr3XSjwOLsIAcHP0co=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=SofSjai1r/yUWSa5boXgKbCjiaJzE8WKH/RvkBd29mU=; b=I4osvWh+8RVsX25r85dS3PEUvu 2JTn59LgA+Ube/yXgK+z4wUoRsk6w5XYYTzED2pZvRuJza6yhJUcJ8Bveg0BKErbnunMQ89bG9i0t qK/LO1GaSxFcI8+zWDecHKMsxe/IqxBlZJoSnFLAcIYyRCSWhMbMOq88tth2uantjO/Y=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fBQZD-009L9U-MB for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:59:07 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Thu, 26 Apr 2018 03:57:21 +0800 Message-Id: <20180425195722.20744-8-a@unstable.cc> In-Reply-To: <20180425195722.20744-1-a@unstable.cc> References: <20180425195722.20744-1-a@unstable.cc> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [5.148.176.60 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1fBQZD-009L9U-MB Subject: [Openvpn-devel] [RFC 7/8] allow user to specify 'local' multiple times in config files X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox It is now possible to specify 'local' multiple times in a server config to let it listen on multiple sockets (address:port) of the same protocol. Signed-off-by: Antonio Quartulli --- doc/openvpn.8 | 10 ++- src/openvpn/init.c | 9 +-- src/openvpn/options.c | 162 ++++++++++++++++++++++++++++++++++-------- src/openvpn/options.h | 15 +++- src/openvpn/socket.c | 18 +++-- 5 files changed, 174 insertions(+), 40 deletions(-) diff --git a/doc/openvpn.8 b/doc/openvpn.8 index 4114f408..658bda23 100644 --- a/doc/openvpn.8 +++ b/doc/openvpn.8 @@ -201,10 +201,16 @@ a new mode ("server") which implements a multi\-client server capability. .\"********************************************************* .TP -.B \-\-local host -Local host name or IP address for bind. +.B \-\-local host|* [port] +Local host name or IP address and port for bind. If specified, OpenVPN will bind to this address only. If unspecified, OpenVPN will bind to all interfaces. +Multiple occurrencies of this option are allowed on +a server, where it will listen on all the configured +ip:port couples. 'ip' can also be '*', where it will +just be treated as 'any host'. +To listen on IPv4 or IPv6 only, it is possible to use +0.0.0.0 or :: respectivaly. .\"********************************************************* .TP .B \-\-remote host [port] [proto] diff --git a/src/openvpn/init.c b/src/openvpn/init.c index a2b474c8..41bc5094 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -627,7 +627,7 @@ context_init_1(struct context *c) init_connection_list(c); - c->c1.link_sockets_num = 1; + c->c1.link_sockets_num = c->options.ce.local_list->len; do_link_socket_addr_new(c); @@ -3248,8 +3248,8 @@ do_init_socket_1(struct context *c, const int mode) { /* init each socket with its specific port */ link_socket_init_phase1(c->c2.link_sockets[i], - c->options.ce.local, - c->options.ce.local_port, + c->options.ce.local_list->array[i]->local, + c->options.ce.local_list->array[i]->port, c->options.ce.remote, c->options.ce.remote_port, c->c1.dns_cache, @@ -3263,7 +3263,7 @@ do_init_socket_1(struct context *c, const int mode) #ifdef ENABLE_DEBUG c->options.gremlin, #endif - c->options.ce.bind_local, + c->options.ce.local_list->array[i]->bind_local, c->options.ce.remote_float, c->options.inetd, &c->c1.link_socket_addrs[i], @@ -4422,6 +4422,7 @@ inherit_context_child(struct context *dest, if (dest->mode == CM_CHILD_UDP) { ASSERT(!dest->c2.link_sockets); + ASSERT(dest->options.ce.local_list); /* inherit buffers */ dest->c2.buffers = src->c2.buffers; diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 426057ab..884a8f35 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -118,7 +118,13 @@ static const char usage_message[] = "--version : Show copyright and version information.\n" "\n" "Tunnel Options:\n" - "--local host : Local host name or ip address. Implies --bind.\n" + "--local host|* [port] : Local host name or ip address and port. '*' can be used\n" + " as hostname and means 'any host' (openvpn will listen on\n" + " what is returned by the OS). Implies --bind.\n" + " 0.0.0.0 or :: can be used to specifically open a socket\n" + " listening on any IPv4 or IPv6 address respectively.\n" + " The user can specify multiple --local entries to have\n" + " a server listen on multiple sockets at the same time.\n" "--remote host [port] : Remote host name or ip address.\n" "--remote-random : If multiple --remote options specified, choose one randomly.\n" "--remote-random-hostname : Add a random string to remote DNS name.\n" @@ -963,8 +969,9 @@ setenv_connection_entry(struct env_set *es, const int i) { setenv_str_i(es, "proto", proto2ascii(e->proto, e->af, false), i); - setenv_str_i(es, "local", e->local, i); - setenv_str_i(es, "local_port", e->local_port, i); + /* expected to befor single socket contexts only */ + setenv_str_i(es, "local", e->local_list->array[0]->local, i); + setenv_str_i(es, "local_port", e->local_list->array[0]->port, i); setenv_str_i(es, "remote", e->remote, i); setenv_str_i(es, "remote_port", e->remote_port, i); @@ -1472,8 +1479,12 @@ static void show_connection_entry(const struct connection_entry *o) { msg(D_SHOW_PARMS, " proto = %s", proto2ascii(o->proto, o->af, false)); - SHOW_STR(local); - SHOW_STR(local_port); + msg(D_SHOW_PARMS, " Local Sockets:"); + for (int i = 0; i < o->local_list->len; i++) + { + msg(D_SHOW_PARMS, " [%s]:%s", o->local_list->array[i]->local, + o->local_list->array[i]->port); + } SHOW_STR(remote); SHOW_STR(remote_port); SHOW_BOOL(remote_float); @@ -1908,6 +1919,37 @@ options_postprocess_http_proxy_override(struct options *o) #endif /* ifdef ENABLE_MANAGEMENT */ +static struct local_list * +alloc_local_list_if_undef(struct connection_entry *ce, struct gc_arena *gc) +{ + if (!ce->local_list) + { + ALLOC_OBJ_CLEAR_GC(ce->local_list, struct local_list, gc); + } + return ce->local_list; +} + +static struct local_entry * +alloc_local_entry(struct connection_entry *ce, const int msglevel, + struct gc_arena *gc) +{ + struct local_list *l = alloc_local_list_if_undef(ce, gc); + struct local_entry *e; + + if (l->len >= CONNECTION_LIST_SIZE) + { + msg(msglevel, "Maximum number of 'local' options (%d) exceeded", + CONNECTION_LIST_SIZE); + + return NULL; + } + + ALLOC_OBJ_CLEAR_GC(e, struct local_entry, gc); + l->array[l->len++] = e; + + return e; +} + static struct connection_list * alloc_connection_list_if_undef(struct options *options) { @@ -2053,11 +2095,19 @@ options_postprocess_verify_ce(const struct options *options, const struct connec msg(M_USAGE, "only one of --daemon or --inetd may be specified"); } - if (options->inetd && (ce->local || ce->remote)) + if (options->inetd && (ce->local_list->len > 1 + || ce->local_list->array[0]->local + || strcmp(ce->local_list->array[0]->local, "*") + || ce->remote)) { msg(M_USAGE, "--local or --remote cannot be used with --inetd"); } + if (ce->remote && ce->local_list->len > 1) + { + msg(M_USAGE, "multiple --local do not make sense in Client mode"); + } + if (options->inetd && ce->proto == PROTO_TCP_CLIENT) { msg(M_USAGE, "--proto tcp-client cannot be used with --inetd"); @@ -2109,25 +2159,12 @@ options_postprocess_verify_ce(const struct options *options, const struct connec * Sanity check on --local, --remote, and --ifconfig */ - if (proto_is_net(ce->proto) - && string_defined_equal(ce->local, ce->remote) - && string_defined_equal(ce->local_port, ce->remote_port)) - { - msg(M_USAGE, "--remote and --local addresses are the same"); - } - if (string_defined_equal(ce->remote, options->ifconfig_local) || string_defined_equal(ce->remote, options->ifconfig_remote_netmask)) { msg(M_USAGE, "--local and --remote addresses must be distinct from --ifconfig addresses"); } - if (string_defined_equal(ce->local, options->ifconfig_local) - || string_defined_equal(ce->local, options->ifconfig_remote_netmask)) - { - msg(M_USAGE, "--local addresses must be distinct from --ifconfig addresses"); - } - if (string_defined_equal(options->ifconfig_local, options->ifconfig_remote_netmask)) { msg(M_USAGE, "local and remote/netmask --ifconfig addresses must be different"); @@ -2138,11 +2175,6 @@ options_postprocess_verify_ce(const struct options *options, const struct connec msg(M_USAGE, "--bind and --nobind can't be used together"); } - if (ce->local && !ce->bind_local) - { - msg(M_USAGE, "--local and --nobind don't make sense when used together"); - } - if (ce->local_port_defined && !ce->bind_local) { msg(M_USAGE, "--lport and --nobind don't make sense when used together"); @@ -2153,6 +2185,29 @@ options_postprocess_verify_ce(const struct options *options, const struct connec msg(M_USAGE, "--nobind doesn't make sense unless used with --remote"); } + for (int i = 0; i < ce->local_list->len; i++) + { + struct local_entry *le = ce->local_list->array[i]; + + if (proto_is_net(ce->proto) + && string_defined_equal(le->local, ce->remote) + && string_defined_equal(le->port, ce->remote_port)) + { + msg(M_USAGE, "--remote and a --local addresses are the same"); + } + + if (string_defined_equal(le->local, options->ifconfig_local) + || string_defined_equal(le->local, options->ifconfig_remote_netmask)) + { + msg(M_USAGE, "--local addresses must be distinct from --ifconfig addresses"); + } + + if (le->local && !ce->bind_local) + { + msg(M_USAGE, "--local and --nobind don't make sense when used together"); + } + } + /* * Check for consistency of management options */ @@ -2817,12 +2872,12 @@ options_postprocess_mutate_ce(struct options *o, struct connection_entry *ce) } #endif - if (ce->proto == PROTO_TCP_CLIENT && !ce->local && !ce->local_port_defined && !ce->bind_defined) + if (ce->proto == PROTO_TCP_CLIENT && !ce->local_list && !ce->local_port_defined && !ce->bind_defined) { ce->bind_local = false; } - if (ce->proto == PROTO_UDP && ce->socks_proxy_server && !ce->local && !ce->local_port_defined && !ce->bind_defined) + if (ce->proto == PROTO_UDP && ce->socks_proxy_server && !ce->local_list && !ce->local_port_defined && !ce->bind_defined) { ce->bind_local = false; } @@ -2868,7 +2923,16 @@ options_postprocess_mutate_ce(struct options *o, struct connection_entry *ce) ce->tun_mtu_extra = TAP_MTU_EXTRA_DEFAULT; } } +} +static void +options_postprocess_mutate_le(struct options *o, struct local_entry *le) +{ + /* use the global port if none is specified */ + if (!le->port) + { + le->port = o->ce.local_port; + } } #ifdef _WIN32 @@ -3019,6 +3083,29 @@ options_postprocess_mutate(struct options *o) options_postprocess_mutate_ce(o, o->connection_list->array[i]); } + if (o->ce.local_list) + { + for (i = 0; i < o->ce.local_list->len; i++) + { + options_postprocess_mutate_le(o, o->ce.local_list->array[i]); + } + } + else + { + /* if no 'local' directive was specified, convert the global port + * setting to a listen entry */ + struct local_entry *e = alloc_local_entry(&o->ce, M_USAGE, &o->gc); + ASSERT(e); + e->port = o->ce.local_port; + e->bind_local = o->ce.bind_local; + } + + /* use the same listen list for every outgoing connection */ + for (i = 0; i < o->connection_list->len; ++i) + { + o->connection_list->array[i]->local_list = o->ce.local_list; + } + if (o->tls_server) { /* Check that DH file is specified, or explicitly disabled */ @@ -5267,10 +5354,29 @@ add_option(struct options *options, VERIFY_PERMISSION(OPT_P_UP); options->ifconfig_nowarn = true; } - else if (streq(p[0], "local") && p[1] && !p[2]) + else if (streq(p[0], "local") && p[1] && !p[3]) { + struct local_entry *e; + VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_CONNECTION); - options->ce.local = p[1]; + + e = alloc_local_entry(&options->ce, M_USAGE, &options->gc); + ASSERT(e); + + /* '*' is treated as 'ask the system to get some socket', + * therefore force binding on a particular address only when + * actually specified. */ + if (strcmp(p[1], "*") != 0) + { + e->local = p[1]; + e->bind_local = true; + } + + if (p[2]) + { + e->port = p[2]; + e->bind_local = true; + } } else if (streq(p[0], "remote-random") && !p[1]) { diff --git a/src/openvpn/options.h b/src/openvpn/options.h index f7d0145a..fb8c32fd 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -83,14 +83,21 @@ struct options_pre_pull #error "At least one of OpenSSL or mbed TLS needs to be defined." #endif +struct local_entry +{ + const char *local; + const char *port; + bool bind_local; +}; + struct connection_entry { + struct local_list *local_list; int proto; sa_family_t af; const char *local_port; bool local_port_defined; const char *remote_port; - const char *local; const char *remote; bool remote_float; bool bind_defined; @@ -142,6 +149,12 @@ struct remote_entry #define CONNECTION_LIST_SIZE 64 +struct local_list +{ + int len; + struct local_entry *array[CONNECTION_LIST_SIZE]; +}; + struct connection_list { int len; diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 79fbc6a8..9d961347 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -232,7 +232,7 @@ do_preresolve_host(struct context *c, void do_preresolve(struct context *c) { - int i; + int i, j; struct connection_list *l = c->options.connection_list; const unsigned int preresolve_flags = GETADDR_RESOLVE |GETADDR_UPDATE_MANAGEMENT_STATE @@ -305,11 +305,19 @@ do_preresolve(struct context *c) } } - if (ce->bind_local) + flags |= GETADDR_PASSIVE; + flags &= ~GETADDR_RANDOMIZE; + + for (j = 0; j < ce->local_list->len; j++) { - flags |= GETADDR_PASSIVE; - flags &= ~GETADDR_RANDOMIZE; - status = do_preresolve_host(c, ce->local, ce->local_port, ce->af, flags); + struct local_entry *le = ce->local_list->array[j]; + + if (!le->local) + { + continue; + } + + status = do_preresolve_host(c, le->local, le->port, ce->af, flags); if (status != 0) { goto err; From patchwork Wed Apr 25 09:57:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 320 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director7.mail.ord1d.rsapps.net ([172.27.255.54]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id 2F4GBzTe4FrkSwAAIUCqbw for ; Wed, 25 Apr 2018 15:59:48 -0400 Received: from proxy16.mail.iad3a.rsapps.net ([172.27.255.54]) by director7.mail.ord1d.rsapps.net (Dovecot) with LMTP id i/03GjTe4FoKZwAAovjBpQ ; Wed, 25 Apr 2018 15:59:48 -0400 Received: from smtp39.gate.iad3a ([172.27.255.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy16.mail.iad3a.rsapps.net with LMTP id UB8yGDTe4FoFGgAADc5QwQ ; Wed, 25 Apr 2018 15:59:48 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp39.gate.iad3a.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: 3464e5f4-48c3-11e8-ac8e-525400eea4e4-1-1 Received: from [216.105.38.7] ([216.105.38.7:16201] helo=lists.sourceforge.net) by smtp39.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.1.56364 r(Core:4.2.1.14)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id AD/16-18310-33ED0EA5; Wed, 25 Apr 2018 15:59:47 -0400 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fBQZI-0008T1-1z; Wed, 25 Apr 2018 19:59:08 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fBQZH-0008Sf-Cq for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:59:07 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=mdkeJNVp1X0wNmfWns0+vZVDzkTG0gwcrPIVTjQiFPk=; b=JQsqW7ra+RaI1m7nAAPI8pwlFE 1y4eOnMYBcFrS7drtA+1v754EVK0sBuFYKrDlfm7wMlxLNcx0rOZ7/A0RqYKOoWuAsi8CqT+vd8pV umq56IUhReL3TNJedo2fYmRT+h+xAhSihj1scz0RoTtt27tLc5Vqhxku67HCziCJJMU0=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=mdkeJNVp1X0wNmfWns0+vZVDzkTG0gwcrPIVTjQiFPk=; b=jthBj6Oxi1YvJUGGQiOa7twrmq lU5gxEDUbTrQxNv1XR/MMoEK/8FmQApf1MmKFRkldmcEykEGRNI+DX6R4FIPemm8orhjVvij+jLCf xjPbSBzSw5l6rT0s5qQKI366g0gKqxr9/W4X3xkigt1hd64sv80hGhdhRUGjXV1LXLkI=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-3.v28.lw.sourceforge.com with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1fBQZF-00Bt3y-8F for openvpn-devel@lists.sourceforge.net; Wed, 25 Apr 2018 19:59:06 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Thu, 26 Apr 2018 03:57:22 +0800 Message-Id: <20180425195722.20744-9-a@unstable.cc> In-Reply-To: <20180425195722.20744-1-a@unstable.cc> References: <20180425195722.20744-1-a@unstable.cc> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [5.148.176.60 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1fBQZF-00Bt3y-8F Subject: [Openvpn-devel] [RFC 8/8] override ai_family if 'local' numeric address was specified X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Antonio Quartulli MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox This change ensures that when a numeric IP address is specified as argument to a 'local' directive, its ai_family overrides the one extracted from the 'proto' config option. Signed-off-by: Antonio Quartulli --- src/openvpn/socket.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 9d961347..3dd44b83 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -378,9 +378,8 @@ openvpn_getaddrinfo(unsigned int flags, signal_received = &sigrec; } - /* try numeric ipv6 addr first */ + /* try numeric ip addr first */ CLEAR(hints); - hints.ai_family = ai_family; hints.ai_flags = AI_NUMERICHOST; if (flags & GETADDR_PASSIVE) @@ -408,6 +407,10 @@ openvpn_getaddrinfo(unsigned int flags, const char *fmt; int level = 0; + /* this is not a numeric IP, therefore force resolution using the + * provided ai_family */ + hints.ai_family = ai_family; + if (hostname && (flags & GETADDR_RANDOMIZE)) { hostname = hostname_randomize(hostname, &gc); @@ -1599,6 +1602,10 @@ resolve_bind_local(struct link_socket *sock, const sa_family_t af) sock->local_host, sock->local_port, gai_strerror(status)); } + + /* the resolved 'local entry' might have a different family than what + * was globally configured */ + sock->info.af = sock->info.lsa->bind_local->ai_family; } gc_free(&gc);