From patchwork Wed Nov 15 13:45:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "plaisthos (Code Review)" X-Patchwork-Id: 3447 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7300:3c06:b0:f2:62eb:61c1 with SMTP id e6csp2926442dys; Wed, 15 Nov 2023 05:46:32 -0800 (PST) X-Google-Smtp-Source: AGHT+IHEBeTZFTaSOC10GM9BOX6z8mTO6vht/2eniAxq/tJ6H6W/iFGzBBq4praFQPyEhZ5fU/Cx X-Received: by 2002:a05:6a00:8c8c:b0:6c4:d9a8:5ed6 with SMTP id ii12-20020a056a008c8c00b006c4d9a85ed6mr2865298pfb.0.1700055992158; Wed, 15 Nov 2023 05:46:32 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700055992; cv=none; d=google.com; s=arc-20160816; b=CzlTIdbFMHYjrUwondLkPIz5Mj2ghCW1Mr89A13405U4OJNacw2SyJZGDq90o47b8r q6zmCxhVxr/wSTW7DxsmK6qiHJAmkfb1826ZzNwF0c97NB9yExcC7axyMi5ScV6jtgxE i3dYwFx1MJ5/MjzqlY9mWHJstr3Op8VnNqpIEtuNPOIdMYWDqJ1e689C6ZBtiA7Ynnui IIxlzmFE9DvgO+SE2hW7bZjUzI4JGXjxYsfM2jzTeQWUbHU8NF4QXFos0JqVyPUuYV+G /c8JT7U+ydlfYh9wtCD4nYZXpCe7oYdgKg3F10uybVPDzy2N53wj033U+O4R/IY+q+44 0W2g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:cc:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject:user-agent :mime-version:message-id:references:auto-submitted:to:date:from :dkim-signature:dkim-signature:dkim-signature; bh=+TCw4j1W/TO67533HEMG2WHc3uaaXhZqajB2tu9wCNo=; fh=U7wEyxtwz2o5+UdevFSA47vNeG9knhWH0KV//QhD5a0=; b=k29pOmv0H836G05LDVMbTK08RN3DiR1Fpq+cuOzIe1kCYv1dtoeb+Tt8+Arlt0RiuJ s2Uk0/1PLvqvv7+ZPJXgGyow9Jz2lnxrBg19PlqO4Bid9XQ8DD+HjiX3crHAursu6B/C DGCg8RkrmPC008M+gSeQ9O2DfpLxPUZO1Kz1JkZJhreomM6QA8yd8RPidsOQxSk5IirM cOzHl5dFnxCaNC0Cz6z5IwnEM+xi6RC7wEDHZ9QQHodx/ZTv3ZKo+/iJn5E77dWk+Ub2 uxyVQROJ4DzqonplYsj/C4j1Y/UWXKC93QhqNFs5GqxDX3OwZsS3n5xiWTjQF3XhnfjB y+Jw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=NtTnpCUp; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=CsZoIOGR; dkim=neutral (body hash did not verify) header.i=@openvpn.net header.s=google header.b=Dz9BJTmr; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=openvpn.net Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id j69-20020a638048000000b00565db2812a0si10348188pgd.60.2023.11.15.05.46.31 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 15 Nov 2023 05:46:32 -0800 (PST) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=NtTnpCUp; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=CsZoIOGR; dkim=neutral (body hash did not verify) header.i=@openvpn.net header.s=google header.b=Dz9BJTmr; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=openvpn.net 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.95) (envelope-from ) id 1r3GD4-0001SK-G3; Wed, 15 Nov 2023 13:45:38 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1r3GCw-0001Rf-Lq for openvpn-devel@lists.sourceforge.net; Wed, 15 Nov 2023 13:45:30 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Type:Content-Transfer-Encoding:MIME-Version :Message-ID:Reply-To:References:Subject:List-Unsubscribe:List-Id:Cc:To:Date: From:Sender:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:List-Help: List-Subscribe:List-Post:List-Owner:List-Archive; bh=Y2/Dsl2xbz6+HaQ6DD1xqS1hGCK3C6OueTz/VwUe2UI=; b=NtTnpCUpG6AYyrd7i0jLQuZdx7 soHv/t0ApA0Qb+QMCPemBMfmVSbqlCf6Nv6ZAvLSKbII3SyrD+K6c8tlcpnyNvVkoDARVUoefl4pB fOlQshRDuRO/fFTl7i3XatJtEpeFllzWovjkuBwM2s6sfpcBi0/lYN/GLgAsLDe8YJzY=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Type:Content-Transfer-Encoding:MIME-Version:Message-ID:Reply-To: References:Subject:List-Unsubscribe:List-Id:Cc:To:Date:From:Sender:Content-ID :Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To: Resent-Cc:Resent-Message-ID:In-Reply-To:List-Help:List-Subscribe:List-Post: List-Owner:List-Archive; bh=Y2/Dsl2xbz6+HaQ6DD1xqS1hGCK3C6OueTz/VwUe2UI=; b=C sZoIOGRCVBSQieTenLhjloVzqvJcK+9GWJt+Euf6wyreVg9EUSqBY5hnS4PWNIKtpXxbEu8Sxta70 zpxLKCAAFkWiVoTdo/8PxTOoNEbqQxYHYal/usHdGlmt1tpuNr0OR7fCw7LFq5HBlJvI7NO95x+qj lOPfS9OLCkKoW928=; Received: from mail-wm1-f50.google.com ([209.85.128.50]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.95) id 1r3GCl-006VpW-9W for openvpn-devel@lists.sourceforge.net; Wed, 15 Nov 2023 13:45:30 +0000 Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-4083f61322fso53187425e9.1 for ; Wed, 15 Nov 2023 05:45:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvpn.net; s=google; t=1700055913; x=1700660713; darn=lists.sourceforge.net; h=user-agent:content-disposition:content-transfer-encoding :mime-version:message-id:reply-to:references:subject :list-unsubscribe:list-id:auto-submitted:cc:to:date:from:from:to:cc :subject:date:message-id:reply-to; bh=Y2/Dsl2xbz6+HaQ6DD1xqS1hGCK3C6OueTz/VwUe2UI=; b=Dz9BJTmrzr0gdK8SrtM/wQTCIvs1d6ap1wcNQZWCTP8pCVaD1Uz3i4o/kPN4nNzjPz rzN/56nrKHM4oRAVHyoSAlO1IEbccRUQrXHz4izYWPFCJrkIDkOkVwnUpoBaP/4GT1od zIzyjvydzIZep5kf2lPdVjIXr+pHNiOCvPddrIR5p8KMsJJkjT9mDWeDx5MY5pzoFZ9S WwaAD3vqjVrQd05KfGvmsxSWlwnUMOG71hU953r4X7Q0iAVUuou5fIa5HpR0xLU1zFE+ uZBtXbigobW3jJNdDrUc8/S+iFuerPJNbRWcUzz1y9IZ3mVqWIyW99IKhJKp/fHHUB3v b/HQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700055913; x=1700660713; h=user-agent:content-disposition:content-transfer-encoding :mime-version:message-id:reply-to:references:subject :list-unsubscribe:list-id:auto-submitted:cc:to:date:from :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Y2/Dsl2xbz6+HaQ6DD1xqS1hGCK3C6OueTz/VwUe2UI=; b=KZSjYsWDKydJhcyUVRMeT/AMGQ33992mIXlhGjLPAkdPgg1MOlKQsZvBlssYK+sHie 62WZvOgicvhdAeJ3LaDHk3PqhvklJ1mqNNl85hbhl08qc3siRWMKvoAO7BVkXaNK7XPP niWeBHLPVxMNv+r7LhwFd2Wt86zKkpiwBMdLIV8l6elG7xQt6cw8YeIrEqJpPUKTv/yb 3xazr1AE10shEqJM4O5w2o2x800BL2+NN2A51rYSl+e1yLVnJ8sFfUjbZifRq0e4ONyT +jLl0dmLA3dT4+XY+AkqPFhO16UMGoJBGGZY045Xz0Ec9L62YCrAGx7h0tgZ59Sm4Yj3 14HA== X-Gm-Message-State: AOJu0Yw2NM65CDUvNVx/voR1mvIaVgP3BpHdTrcnV07jvVx6KV6CInxF HxEKEv7bjbRgdTc70xnFMdTM9g== X-Received: by 2002:a05:600c:4f0e:b0:406:5359:769f with SMTP id l14-20020a05600c4f0e00b004065359769fmr11007147wmq.0.1700055911850; Wed, 15 Nov 2023 05:45:11 -0800 (PST) Received: from gerrit.openvpn.in (ec2-18-159-0-78.eu-central-1.compute.amazonaws.com. [18.159.0.78]) by smtp.gmail.com with ESMTPSA id q2-20020adf9dc2000000b0032db4825495sm10741034wre.22.2023.11.15.05.45.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Nov 2023 05:45:11 -0800 (PST) From: "ordex (Code Review)" X-Google-Original-From: "ordex (Code Review)" X-Gerrit-PatchSet: 1 Date: Wed, 15 Nov 2023 13:45:10 +0000 To: plaisthos , flichtenheld Auto-Submitted: auto-generated X-Gerrit-MessageType: newchange X-Gerrit-Change-Id: Ia0a889e800f0b36aed770ee36e31afeec5df6084 X-Gerrit-Change-Number: 434 X-Gerrit-Project: openvpn X-Gerrit-ChangeURL: X-Gerrit-Commit: 0adaec5476063f91e1fae3f41ed33c1b0225684b References: Message-ID: <3772879ca9877fe0c4e8b08504c1cf51fcd03ee3-HTML@gerrit.openvpn.net> MIME-Version: 1.0 User-Agent: Gerrit/3.8.2 X-Spam-Score: -0.2 (/) X-Spam-Report: Spam detection software, running on the system "util-spamd-2.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Attention is currently required from: flichtenheld, plaisthos. Hello plaisthos, flichtenheld, I'd like you to do a code review. Please visit Content analysis details: (-0.2 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.128.50 listed in wl.mailspike.net] -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [209.85.128.50 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 WEIRD_PORT URI: Uses non-standard port number for HTTP 0.0 HTML_MESSAGE BODY: HTML included in message -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.0 T_SCC_BODY_TEXT_LINE No description available. 0.0 T_KAM_HTML_FONT_INVALID Test for Invalidly Named or Formatted Colors in HTML X-Headers-End: 1r3GCl-006VpW-9W Subject: [Openvpn-devel] [L] Change in openvpn[master]: 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: , Reply-To: a@unstable.cc, arne-openvpn@rfc2549.org, openvpn-devel@lists.sourceforge.net, frank@lichtenheld.com Cc: openvpn-devel Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1782637912114426074?= X-GMAIL-MSGID: =?utf-8?q?1782637912114426074?= X-getmail-filter-classifier: gerrit message type newchange Attention is currently required from: flichtenheld, plaisthos. Hello plaisthos, flichtenheld, I'd like you to do a code review. Please visit http://gerrit.openvpn.net/c/openvpn/+/434?usp=email to review the following change. Change subject: allow tcp/udp server to listen on multiple ports at the same time ...................................................................... allow tcp/udp server to listen on multiple ports at the same time Change-Id: Ia0a889e800f0b36aed770ee36e31afeec5df6084 Signed-off-by: Antonio Quartulli --- M src/openvpn/dco.c M src/openvpn/event.h M src/openvpn/forward.c M src/openvpn/forward.h M src/openvpn/init.c M src/openvpn/init.h M src/openvpn/mss.c M src/openvpn/mtcp.c M src/openvpn/mudp.c M src/openvpn/mudp.h M src/openvpn/multi.c M src/openvpn/multi.h M src/openvpn/openvpn.c M src/openvpn/openvpn.h M src/openvpn/ovpn_dco_win.h M src/openvpn/ping.h M src/openvpn/socket.c M src/openvpn/socket.h 18 files changed, 458 insertions(+), 231 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/34/434/1 diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c index cd3e0ad..6f6d7f0 100644 --- a/src/openvpn/dco.c +++ b/src/openvpn/dco.c @@ -460,7 +460,7 @@ return 0; } - struct link_socket *ls = c->c2.link_socket; + struct link_socket *ls = c->c2.link_sockets[0]; ASSERT(ls->info.connection_established); @@ -476,7 +476,7 @@ } #endif int ret = dco_new_peer(&c->c1.tuntap->dco, multi->peer_id, - c->c2.link_socket->sd, NULL, remoteaddr, NULL, NULL); + c->c2.link_sockets[0]->sd, NULL, remoteaddr, NULL, NULL); if (ret < 0) { return ret; @@ -509,12 +509,12 @@ #if ENABLE_IP_PKTINFO struct context *c = &mi->context; - if (!proto_is_udp(c->c2.link_socket->info.proto) || !(c->options.sockflags & SF_USE_IP_PKTINFO)) + if (!proto_is_udp(c->c2.link_sockets[0]->info.proto) || !(c->options.sockflags & SF_USE_IP_PKTINFO)) { return false; } - struct link_socket_actual *actual = &c->c2.link_socket_info->lsa->actual; + struct link_socket_actual *actual = &c->c2.link_socket_infos[0]->lsa->actual; switch (actual->dest.addr.sa.sa_family) { @@ -559,7 +559,7 @@ int peer_id = c->c2.tls_multi->peer_id; struct sockaddr *remoteaddr, *localaddr = NULL; struct sockaddr_storage local = { 0 }; - int sd = c->c2.link_socket->sd; + int sd = c->c2.link_sockets[0]->sd; if (c->mode == CM_CHILD_TCP) @@ -569,8 +569,8 @@ } else { - ASSERT(c->c2.link_socket_info->connection_established); - remoteaddr = &c->c2.link_socket_info->lsa->actual.dest.addr.sa; + ASSERT(c->c2.link_socket_infos[0]->connection_established); + remoteaddr = &c->c2.link_socket_infos[0]->lsa->actual.dest.addr.sa; } /* In server mode we need to fetch the remote addresses from the push config */ diff --git a/src/openvpn/event.h b/src/openvpn/event.h index f04318f..3c11b9a 100644 --- a/src/openvpn/event.h +++ b/src/openvpn/event.h @@ -141,6 +141,7 @@ 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.c b/src/openvpn/forward.c index 9700c6c..9a6dcd8 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -57,12 +57,18 @@ 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); } @@ -98,7 +104,7 @@ { if (c->c2.tls_multi && c->c2.tls_exit_signal) { - if (link_socket_connection_oriented(c->c2.link_socket)) + if (link_socket_connection_oriented(c->c2.link_sockets[0])) { if (c->c2.tls_multi->n_soft_errors) { @@ -551,6 +557,7 @@ #ifdef ENABLE_FRAGMENT /* * Should we deliver a datagram fragment to remote? + * c is expected to be a single-link context (p2p or child) */ static void check_fragment(struct context *c) @@ -1107,7 +1114,9 @@ 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->sig, SIGUSR1, "decryption-error"); /* SOFT-SIGUSR1 -- decryption error in TCP mode */ @@ -1429,7 +1438,7 @@ */ void -process_incoming_tun(struct context *c) +process_incoming_tun(struct context *c, struct link_socket *out_ls) { struct gc_arena gc = gc_new(); @@ -1462,7 +1471,8 @@ */ unsigned int flags = PIPV4_PASSTOS | PIP_MSSFIX | PIPV4_CLIENT_NAT | PIPV6_IMCP_NOHOST_CLIENT; - process_ip_header(c, flags, &c->c2.buf); + process_ip_header(c, flags, &c->c2.buf, + out_ls); #ifdef PACKET_TRUNCATION_CHECK /* if (c->c2.buf.len > 1) --c->c2.buf.len; */ @@ -1623,7 +1633,8 @@ } 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) { @@ -1669,7 +1680,7 @@ /* 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 @@ -1878,7 +1889,7 @@ */ void -process_outgoing_tun(struct context *c) +process_outgoing_tun(struct context *c, struct link_socket *in_ls) { /* * Set up for write() call to TUN/TAP @@ -1895,9 +1906,8 @@ * 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 | PIP_OUTGOING, - &c->c2.to_tun); + process_ip_header(c, PIP_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIP_OUTGOING, &c->c2.to_tun, + in_ls); if (c->c2.to_tun.len <= c->c2.frame.buf.payload_size) { @@ -2059,6 +2069,7 @@ #if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) static int dco_shift = DCO_SHIFT; /* Event from DCO linux kernel module */ #endif + int i; /* * Decide what kind of events we want to wait for. @@ -2164,8 +2175,11 @@ /* * 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); #if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) if (socket & EVENT_READ && c->c2.did_open_tun) @@ -2203,7 +2217,7 @@ 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; @@ -2242,6 +2256,9 @@ } shift = socket_shift; + /* mark socket so that the multi code knows where we + * have pending i/o */ + ev_arg->pending = true; } else { @@ -2295,7 +2312,7 @@ /* 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) @@ -2312,7 +2329,7 @@ read_incoming_tun(c); if (!IS_SIG(c)) { - process_incoming_tun(c); + process_incoming_tun(c, ls); } } else if (status & DCO_READ) diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index fdc9f0e..333dcdc 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -231,10 +231,12 @@ * * 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); /** @@ -246,10 +248,11 @@ * * 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); /**************************************************************************/ @@ -303,20 +306,21 @@ #define PIPV6_IMCP_NOHOST_CLIENT (1<<5) #define PIPV6_IMCP_NOHOST_SERVER (1<<6) -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); void schedule_exit(struct context *c, const int n_seconds, const int signal); 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) { - 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; } } diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 8c707a4..f8dd01f 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -533,12 +533,11 @@ { /* 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 - && !c->options.advance_next_remote) + 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 { @@ -554,20 +553,20 @@ * skipped by management on the previous loop. * If so, clear the addrinfo objects as close_instance does */ - if (c->c1.link_socket_addr.remote_list) + if (c->c1.link_socket_addrs[0].remote_list) { - clear_remote_addrlist(&c->c1.link_socket_addr, + clear_remote_addrlist(&c->c1.link_socket_addrs[0], !c->options.resolve_in_advance); } /* 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; } int advance_count = 1; @@ -730,6 +729,13 @@ 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) { @@ -739,6 +745,10 @@ init_connection_list(c); + c->c1.link_sockets_num = 1; + + do_link_socket_addr_new(c); + #if defined(ENABLE_PKCS11) if (c->first_time) { @@ -1667,7 +1677,7 @@ 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)) { @@ -1781,8 +1791,8 @@ 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, &c->net_ctx, @@ -1856,17 +1866,16 @@ 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->net_ctx); + &c->c2.link_sockets[0]->info, c->c2.es, &c->net_ctx); } 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->net_ctx); + &c->c2.link_sockets[0]->info, c->c2.es, &c->net_ctx); } /* do ifconfig */ @@ -1879,8 +1888,7 @@ c->options.dev_type, c->options.dev_node, &gc); - do_ifconfig(c->c1.tuntap, guess, c->c2.frame.tun_mtu, c->c2.es, - &c->net_ctx); + do_ifconfig(c->c1.tuntap, guess, c->c2.frame.tun_mtu, c->c2.es, &c->net_ctx); } /* possibly add routes */ @@ -1895,6 +1903,7 @@ /* Store the old fd inside the fd so open_tun can use it */ c->c1.tuntap->fd = oldtunfd; #endif + if (dco_enabled(&c->options)) { ovpn_dco_init(c->mode, &c->c1.tuntap->dco); @@ -1907,16 +1916,14 @@ /* set the hardware address */ if (c->options.lladdr) { - set_lladdr(&c->net_ctx, c->c1.tuntap->actual_name, c->options.lladdr, - c->c2.es); + set_lladdr(&c->net_ctx, c->c1.tuntap->actual_name, c->options.lladdr, c->c2.es); } /* do ifconfig */ if (!c->options.ifconfig_noexec && ifconfig_order() == IFCONFIG_AFTER_TUN_OPEN) { - do_ifconfig(c->c1.tuntap, c->c1.tuntap->actual_name, - c->c2.frame.tun_mtu, c->c2.es, &c->net_ctx); + do_ifconfig(c->c1.tuntap, c->c1.tuntap->actual_name, c->c2.frame.tun_mtu, c->c2.es, &c->net_ctx); } /* run the up script */ @@ -2427,7 +2434,7 @@ { msg(M_NONFATAL, "dco-win doesn't yet support reopening TUN device"); /* prevent link_socket_close() from closing handle with WinSock API */ - c->c2.link_socket->sd = SOCKET_UNDEFINED; + c->c2.link_sockets[0]->sd = SOCKET_UNDEFINED; return false; } else @@ -2657,14 +2664,28 @@ 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) @@ -3747,12 +3768,103 @@ 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 TCP/UDP sockets + */ +static void +do_init_socket_1(struct context *c) +{ + unsigned int sockflags = c->options.sockflags; + int i; + +#if PORT_SHARE + if (c->options.port_share_host && c->options.port_share_port) + { + sockflags |= SF_PORT_SHARE; + } +#endif + + for (i = 0; i < c->c1.link_sockets_num; i++) + { + int mode = LS_MODE_DEFAULT; + + /* mode allows CM_CHILD_TCP + * instances to inherit acceptable fds + * from a top-level parent */ + if (c->options.mode == MODE_SERVER) + { + /* initializing listening socket */ + if (c->mode == CM_TOP) + { + mode = LS_MODE_TCP_LISTEN; + } + /* initializing socket to client */ + else if (c->mode == CM_CHILD_TCP) + { + mode = LS_MODE_TCP_ACCEPT_FROM; + } + } + + /* 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, +#endif + c->options.ce.bind_local, + c->options.ce.remote_float, + &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 TCP/UDP sockets + */ +static void +do_init_socket_2(struct context *c) +{ + int i; + for (i = 0; i < c->c1.link_sockets_num; i++) + { + link_socket_init_phase2(c, c->c2.link_sockets[i]); + } +} + +/* * Print MTU INFO */ static void @@ -3907,15 +4019,20 @@ /* in dco-win case, link socket is a tun handle which is * closed in do_close_tun(). Set it to UNDEFINED so * we won't use WinSock API to close it. */ - if (tuntap_is_dco_win(c->c1.tuntap) && c->c2.link_socket) + if (tuntap_is_dco_win(c->c1.tuntap) && c->c2.link_sockets && c->c2.link_sockets[0]) { - c->c2.link_socket->sd = SOCKET_UNDEFINED; + c->c2.link_sockets[0]->sd = SOCKET_UNDEFINED; } - 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; } @@ -3926,28 +4043,33 @@ && ( (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; + } } } @@ -4430,7 +4552,6 @@ { const struct options *options = &c->options; const bool child = (c->mode == CM_CHILD_TCP || c->mode == CM_CHILD_UDP); - int link_socket_mode = LS_MODE_DEFAULT; /* init garbage collection level */ gc_init(&c->c2.gc); @@ -4471,21 +4592,6 @@ /* map in current connection entry */ next_connection_entry(c); - /* link_socket_mode allows CM_CHILD_TCP - * instances to inherit acceptable fds - * from a top-level parent */ - if (c->options.ce.proto == PROTO_TCP_SERVER) - { - if (c->mode == CM_TOP) - { - link_socket_mode = LS_MODE_TCP_LISTEN; - } - else if (c->mode == CM_CHILD_TCP) - { - link_socket_mode = LS_MODE_TCP_ACCEPT_FROM; - } - } - /* should we disable paging? */ if (c->first_time && options->mlock) { @@ -4628,7 +4734,7 @@ /* bind the TCP/UDP socket */ if (c->mode == CM_P2P || c->mode == CM_TOP || c->mode == CM_CHILD_TCP) { - link_socket_init_phase1(c, link_socket_mode); + do_init_socket_1(c); } /* initialize tun/tap device object, @@ -4671,7 +4777,7 @@ /* finalize the TCP/UDP socket */ if (c->mode == CM_P2P || c->mode == CM_TOP || c->mode == CM_CHILD_TCP) { - link_socket_init_phase2(c); + do_init_socket_2(c); /* Update dynamic frame calculation as exact transport socket information @@ -4807,7 +4913,8 @@ void inherit_context_child(struct context *dest, - const struct context *src) + const struct context *src, + struct link_socket *ls) { CLEAR(*dest); @@ -4820,6 +4927,8 @@ /* c1 init */ packet_id_persist_init(&dest->c1.pid_persist); + dest->c1.link_sockets_num = 1; + do_link_socket_addr_new(dest); dest->c1.ks.key_type = src->c1.ks.key_type; /* inherit SSL context */ @@ -4844,7 +4953,7 @@ * 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 @@ -4868,18 +4977,26 @@ /* 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; - /* inherit parent link_socket and tuntap */ - dest->c2.link_socket = src->c2.link_socket; + ALLOC_ARRAY_GC(dest->c2.link_sockets, struct link_socket *, 1, + &dest->gc); - ALLOC_OBJ_GC(dest->c2.link_socket_info, struct link_socket_info, &dest->gc); - *dest->c2.link_socket_info = src->c2.link_socket->info; + /* inherit parent link_socket and tuntap */ + dest->c2.link_sockets[0] = ls; + + 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 7731f5a..85de096 100644 --- a/src/openvpn/init.h +++ b/src/openvpn/init.h @@ -95,7 +95,8 @@ 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/mss.c b/src/openvpn/mss.c index 1566c64..9b6360f 100644 --- a/src/openvpn/mss.c +++ b/src/openvpn/mss.c @@ -357,7 +357,7 @@ struct link_socket_info *lsi = get_link_socket_info(c); struct options *o = &c->options; - int pmtu = c->c2.link_socket->mtu; + int pmtu = c->c2.link_sockets[0]->mtu; sa_family_t af = lsi->lsa->actual.dest.addr.sa.sa_family; int proto = lsi->proto; diff --git a/src/openvpn/mtcp.c b/src/openvpn/mtcp.c index 3772acf..06073cd 100644 --- a/src/openvpn/mtcp.c +++ b/src/openvpn/mtcp.c @@ -115,13 +115,13 @@ #endif /* ENABLE_DEBUG */ 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; @@ -171,13 +171,16 @@ /* 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; @@ -233,7 +236,7 @@ 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)); @@ -248,7 +251,7 @@ 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, @@ -260,10 +263,14 @@ multi_tcp_wait(const struct context *c, struct multi_tcp *mtcp) { - int status; + int i, status; unsigned int *persistent = &mtcp->tun_rwflags; - socket_set_listen_persistent(c->c2.link_socket, mtcp->es, - &c->c2.link_socket->ev_arg); + + 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); + } #ifdef _WIN32 if (tuntap_is_wintun(c->c1.tuntap)) @@ -481,16 +488,18 @@ 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; @@ -566,7 +575,7 @@ break; case MTP_NONE: - if (mi && socket_read_residual(c->c2.link_socket)) + if (mi && sockets_read_residual(c)) { newaction = TA_SOCKET_READ_RESIDUAL; } @@ -721,9 +730,14 @@ /* 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); @@ -757,9 +771,9 @@ 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); + ASSERT(m->top.c2.link_sockets[0]); + socket_reset_listen_persistent(m->top.c2.link_sockets[0]); + mi = multi_create_instance_tcp(m, m->top.c2.link_sockets[0]); if (mi) { multi_tcp_action(m, mi, TA_INITIAL, false); diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c index 5bd7354..dd45720 100644 --- a/src/openvpn/mudp.c +++ b/src/openvpn/mudp.c @@ -185,7 +185,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; @@ -256,7 +257,7 @@ * connect-freq but not against connect-freq-initial */ reflect_filter_rate_limit_decrease(m->initial_rate_limiter); - mi = multi_create_instance(m, &real); + mi = multi_create_instance(m, &real, ls); if (mi) { hash_add_fast(hash, bucket, &mi->real, hv, mi); @@ -317,7 +318,7 @@ msg_set_prefix("Connection Attempt"); m->top.c2.to_link = m->hmac_reply; m->top.c2.to_link_addr = m->hmac_reply_dest; - process_outgoing_link(&m->top, &m->top.c2.link_socket[0]); + process_outgoing_link(&m->top, m->top.c2.link_sockets[0]); m->hmac_reply_dest = NULL; } } @@ -380,10 +381,20 @@ /* 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 8383c64..1088246 100644 --- a/src/openvpn/mudp.h +++ b/src/openvpn/mudp.h @@ -55,12 +55,14 @@ * 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 /* ifndef MUDP_H */ diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index af04dc8..e9a3945 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -682,7 +682,10 @@ multi_client_disconnect_script(m, mi); } - close_context(&mi->context, SIGTERM, CC_GC_FREE); + if (mi->did_open_context) + { + close_context(&mi->context, SIGTERM, CC_GC_FREE); + } multi_tcp_instance_specific_free(mi); @@ -750,7 +753,8 @@ * 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; @@ -773,7 +777,8 @@ generate_prefix(mi); } - inherit_context_child(&mi->context, &m->top); + mi->did_open_context = true; + inherit_context_child(&mi->context, &m->top, ls); if (IS_SIG(&mi->context)) { goto err; @@ -3128,7 +3133,8 @@ } 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; @@ -3184,8 +3190,8 @@ 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); @@ -3333,7 +3339,8 @@ * 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(); @@ -3354,7 +3361,7 @@ #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 { @@ -3395,7 +3402,7 @@ /* nonzero length means that we have a valid, decrypted packed */ if (floated && c->c2.buf.len > 0) { - multi_process_float(m, m->pending); + multi_process_float(m, m->pending, ls); } process_incoming_link_part2(c, lsi, orig_buf); @@ -3614,7 +3621,7 @@ } /* 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); @@ -3646,7 +3653,8 @@ { 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 a736809..0d4ec63 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -125,6 +125,7 @@ in_addr_t reporting_addr; /* IP address shown in status listing */ struct in6_addr reporting_addr_ipv6; /* IPv6 address in status listing */ + bool did_open_context; bool did_real_hash; bool did_iter; #ifdef ENABLE_MANAGEMENT @@ -269,7 +270,8 @@ 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); @@ -283,7 +285,8 @@ * 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) @@ -348,8 +351,10 @@ * 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); /** @@ -663,7 +668,7 @@ #endif set_prefix(mi); vlan_process_outgoing_tun(m, 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; @@ -678,7 +683,7 @@ { 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 060f192..22eecf9 100644 --- a/src/openvpn/openvpn.c +++ b/src/openvpn/openvpn.c @@ -89,7 +89,7 @@ } /* 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 5b2be63..0ed9286 100644 --- a/src/openvpn/openvpn.h +++ b/src/openvpn/openvpn.h @@ -154,7 +154,8 @@ */ 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. */ @@ -237,11 +238,11 @@ /* bitmask for event status. Check event.h for possible values */ 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; - /** This variable is used instead link_socket->info for P2MP UDP childs */ - 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/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h index e8bd074..787ba2a 100644 --- a/src/openvpn/ovpn_dco_win.h +++ b/src/openvpn/ovpn_dco_win.h @@ -104,7 +104,7 @@ LONG Major; LONG Minor; LONG Patch; -} OVPN_VERSION, * POVPN_VERSION; +} OVPN_VERSION, *POVPN_VERSION; #define OVPN_IOCTL_NEW_PEER CTL_CODE(FILE_DEVICE_UNKNOWN, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) #define OVPN_IOCTL_GET_STATS CTL_CODE(FILE_DEVICE_UNKNOWN, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) diff --git a/src/openvpn/ping.h b/src/openvpn/ping.h index 6243cf6..9501f39 100644 --- a/src/openvpn/ping.h +++ b/src/openvpn/ping.h @@ -63,7 +63,7 @@ && 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)) { trigger_ping_timeout_signal(c); diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 0ccddbe..f2bd624 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -42,6 +42,21 @@ #include "memdbg.h" +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 */ @@ -999,7 +1014,6 @@ create_socket_tcp(struct addrinfo *addrinfo) { socket_descriptor_t sd; - ASSERT(addrinfo); ASSERT(addrinfo->ai_socktype == SOCK_STREAM); @@ -1031,7 +1045,6 @@ create_socket_udp(struct addrinfo *addrinfo, const unsigned int flags) { socket_descriptor_t sd; - ASSERT(addrinfo); ASSERT(addrinfo->ai_socktype == SOCK_DGRAM); @@ -1441,7 +1454,6 @@ #ifdef TARGET_ANDROID protect_fd_nonlocal(sd, remote); #endif - set_nonblock(sd); status = connect(sd, remote, af_addr_size(remote->sa_family)); if (status) @@ -1834,60 +1846,75 @@ } void -link_socket_init_phase1(struct context *c, int mode) +link_socket_init_phase1(struct link_socket *sock, + const char *local_host, + const char *local_port, + const char *remote_host, + const char *remote_port, + struct cached_dns_entry *dns_cache, + int proto, + sa_family_t af, + bool bind_ipv6_only, + int mode, + const struct link_socket *accept_from, + struct http_proxy_info *http_proxy, + struct socks_proxy_info *socks_proxy, +#ifdef ENABLE_DEBUG + int gremlin, +#endif + bool bind_local, + bool remote_float, + struct link_socket_addr *lsa, + const char *ipchange_command, + const struct plugin_list *plugins, + int resolve_retry_seconds, + int mtu_discover_type, + int rcvbuf, + int sndbuf, + int mark, + struct event_timeout *server_poll_timeout, + unsigned int sockflags) { - struct link_socket *sock = c->c2.link_socket; - struct options *o = &c->options; ASSERT(sock); - const char *remote_host = o->ce.remote; - const char *remote_port = o->ce.remote_port; - - sock->local_host = o->ce.local; - sock->local_port = o->ce.local_port; + sock->local_host = local_host; + sock->local_port = local_port; sock->remote_host = remote_host; sock->remote_port = remote_port; - sock->dns_cache = c->c1.dns_cache; - sock->http_proxy = c->c1.http_proxy; - sock->socks_proxy = c->c1.socks_proxy; - sock->bind_local = o->ce.bind_local; - sock->resolve_retry_seconds = o->resolve_retry_seconds; - sock->mtu_discover_type = o->ce.mtu_discover_type; + sock->dns_cache = dns_cache; + sock->http_proxy = http_proxy; + sock->socks_proxy = socks_proxy; + sock->bind_local = bind_local; + sock->resolve_retry_seconds = resolve_retry_seconds; + sock->mtu_discover_type = mtu_discover_type; #ifdef ENABLE_DEBUG - sock->gremlin = o->gremlin; + sock->gremlin = gremlin; #endif - sock->socket_buffer_sizes.rcvbuf = o->rcvbuf; - sock->socket_buffer_sizes.sndbuf = o->sndbuf; + sock->socket_buffer_sizes.rcvbuf = rcvbuf; + sock->socket_buffer_sizes.sndbuf = sndbuf; - sock->sockflags = o->sockflags; -#if PORT_SHARE - if (o->port_share_host && o->port_share_port) - { - sock->sockflags |= SF_PORT_SHARE; - } -#endif - sock->mark = o->mark; - sock->bind_dev = o->bind_dev; + sock->sockflags = sockflags; + sock->mark = mark; - sock->info.proto = o->ce.proto; - sock->info.af = o->ce.af; - sock->info.remote_float = o->ce.remote_float; - sock->info.lsa = &c->c1.link_socket_addr; - sock->info.bind_ipv6_only = o->ce.bind_ipv6_only; - sock->info.ipchange_command = o->ipchange; - sock->info.plugins = c->plugins; - sock->server_poll_timeout = &c->c2.server_poll_interval; + sock->info.proto = proto; + sock->info.af = af; + sock->info.remote_float = remote_float; + sock->info.lsa = lsa; + sock->info.bind_ipv6_only = bind_ipv6_only; + sock->info.ipchange_command = ipchange_command; + sock->info.plugins = plugins; + sock->server_poll_timeout = server_poll_timeout; sock->mode = mode; if (mode == LS_MODE_TCP_ACCEPT_FROM) { - ASSERT(c->c2.accept_from); + ASSERT(accept_from); ASSERT(sock->info.proto == PROTO_TCP_SERVER); - sock->sd = c->c2.accept_from->sd; + sock->sd = accept_from->sd; /* inherit (possibly guessed) info AF from parent context */ - sock->info.af = c->c2.accept_from->info.af; + sock->info.af = accept_from->info.af; } /* are we running in HTTP proxy mode? */ @@ -1896,8 +1923,8 @@ ASSERT(sock->info.proto == PROTO_TCP_CLIENT); /* the proxy server */ - sock->remote_host = c->c1.http_proxy->options.server; - sock->remote_port = c->c1.http_proxy->options.port; + sock->remote_host = http_proxy->options.server; + sock->remote_port = http_proxy->options.port; /* the OpenVPN server we will use the proxy to connect to */ sock->proxy_dest_host = remote_host; @@ -1906,9 +1933,10 @@ /* or in Socks proxy mode? */ else if (sock->socks_proxy) { + /* the proxy server */ - sock->remote_host = c->c1.socks_proxy->server; - sock->remote_port = c->c1.socks_proxy->port; + sock->remote_host = socks_proxy->server; + sock->remote_port = socks_proxy->port; /* the OpenVPN server we will use the proxy to connect to */ sock->proxy_dest_host = remote_host; @@ -2166,22 +2194,21 @@ /* finalize socket initialization */ void -link_socket_init_phase2(struct context *c) +link_socket_init_phase2(struct context *c, + struct link_socket *sock) { - struct link_socket *sock = c->c2.link_socket; const struct frame *frame = &c->c2.frame; struct signal_info *sig_info = c->sig; - const char *remote_dynamic = NULL; - struct signal_info sig_save = {0}; + int sig_save = 0; ASSERT(sock); ASSERT(sig_info); if (sig_info->signal_received) { - sig_save = *sig_info; - sig_save.signal_received = signal_reset(sig_info, 0); + sig_save = sig_info->signal_received; + sig_info->signal_received = 0; } /* initialize buffers */ @@ -2203,7 +2230,7 @@ /* If a valid remote has been found, create the socket with its addrinfo */ if (sock->info.lsa->current_remote) { -#if defined(_WIN32) +#if defined (_WIN32) if (dco_enabled(&c->options)) { create_socket_dco_win(c, sock, sig_info); @@ -2214,7 +2241,6 @@ { create_socket(sock, sock->info.lsa->current_remote); } - } /* If socket has not already been created create it now */ @@ -2233,7 +2259,6 @@ addr_family_name(sock->info.lsa->bind_local->ai_family)); sock->info.af = sock->info.lsa->bind_local->ai_family; } - create_socket(sock, sock->info.lsa->bind_local); } } @@ -2242,7 +2267,7 @@ if (sock->sd == SOCKET_UNDEFINED) { msg(M_WARN, "Could not determine IPv4/IPv6 protocol"); - register_signal(sig_info, SIGUSR1, "Could not determine IPv4/IPv6 protocol"); + sig_info->signal_received = SIGUSR1; goto done; } @@ -2253,7 +2278,8 @@ if (sock->info.proto == PROTO_TCP_SERVER) { - phase2_tcp_server(sock, remote_dynamic, sig_info); + phase2_tcp_server(sock, remote_dynamic, + sig_info); } else if (sock->info.proto == PROTO_TCP_CLIENT) { @@ -2279,16 +2305,11 @@ linksock_print_addr(sock); done: - if (sig_save.signal_received) + if (sig_save) { - /* Always restore the saved signal -- register/throw_signal will handle priority */ - if (sig_save.source == SIG_SOURCE_HARD && sig_info == &siginfo_static) + if (!sig_info->signal_received) { - throw_signal(sig_save.signal_received); - } - else - { - register_signal(sig_info, sig_save.signal_received, sig_save.signal_text); + sig_info->signal_received = sig_save; } } } diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h index 39e30b8..2098333 100644 --- a/src/openvpn/socket.h +++ b/src/openvpn/socket.h @@ -329,9 +329,38 @@ /* * Initialize link_socket object. */ -void link_socket_init_phase1(struct context *c, int mode); +void +link_socket_init_phase1(struct link_socket *sock, + const char *local_host, + const char *local_port, + const char *remote_host, + const char *remote_port, + struct cached_dns_entry *dns_cache, + int proto, + sa_family_t af, + bool bind_ipv6_only, + int mode, + const struct link_socket *accept_from, + struct http_proxy_info *http_proxy, + struct socks_proxy_info *socks_proxy, +#ifdef ENABLE_DEBUG + int gremlin, +#endif + bool bind_local, + bool remote_float, + struct link_socket_addr *lsa, + const char *ipchange_command, + const struct plugin_list *plugins, + int resolve_retry_seconds, + int mtu_discover_type, + int rcvbuf, + int sndbuf, + int mark, + struct event_timeout *server_poll_timeout, + unsigned int sockflags); -void link_socket_init_phase2(struct context *c); +void link_socket_init_phase2(struct context *c, + struct link_socket *sock); void do_preresolve(struct context *c); @@ -1239,11 +1268,7 @@ * 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)