From patchwork Mon Dec 30 16:23:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 4031 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:998b:b0:5e7:b9eb:58e8 with SMTP id d11csp7845494mav; Mon, 30 Dec 2024 08:24:00 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCXtkAuYU54675vhwfKM3E8soL6HP7WM78U1aHUNFHX3vOgcG7YYwfKCC2xa+1zdqjXAAGXjc7m31co=@openvpn.net X-Google-Smtp-Source: AGHT+IGeS/o2UuAa0ftSB7lsoG/L4+DhtGy6DD03BDWww380p5525/sacxwZ67fFlJkSUwGZdmNq X-Received: by 2002:a05:6830:3107:b0:71d:3faf:b652 with SMTP id 46e09a7af769-720ff6850e7mr24343126a34.6.1735575840135; Mon, 30 Dec 2024 08:24:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1735575840; cv=none; d=google.com; s=arc-20240605; b=KjwjGpIqHqNE+0dHgLUq+8NJCVnz3c8RNb9zf9PVsnNIVKRyiOv5XwV2hBOT6i0naZ 7k9K1kWkih+gDWW19eRP2wOf6VJTBIQvC1gTbMSTTMLbxuzAkyM2nfpaZnIKG9wNqlR0 MpZpYMK/sMdmTeySsULlufHKZwGbTePgU9YyPJU/jMmqGT0SR5SWySPNwKbxdZrv5sR4 FLgljkPPvqU8U2G98vN/GThfF0ZeRQYev8fz3y2NqQMcnJ6iUmjIHRPpgdrHkYnPG6Og BrJ3JAFkEzr04vWtWKXP1XlC9B4zbMva9lIgF8DJYfWEqnGdetdE5Bfmq76XFrojLe4/ BQsw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature; bh=1zpU20t5l9yRWZgNUlRxiW7fyHAgUYh8aG3qeUsMJ0E=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=Xldi0jrfqAZBtDel71lm7HEZ9bBMcTPgHnPKpzxHSEmtwKnJFc6Xwe5hMZ6PgZvnwu RCUYWRFbBoxm8sAPVfnY7KcebQyXidGgh3LuSauC9Sh68bY0wkIdyGT6Kw2ice5qAQjD pvUb9szkKHT3ceQp/t3wu5kyYSvo2/logsADy2ACrZB9r4Nsl7moZU9ZDUXAlbSloPse UV7qG5lAIsVM3E+UpqYla+n8J3eaIzq2sHiI5dpt9rvG00ty73auZLkouBUdogbUZt46 ssDcuje93P8kV0lkYd/i0BJ5fFhobnmYvulm99YmLtuD2EEwKVgjQ5FobzONBIZxv7Qz wnzg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=crOU4kNn; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="YFBafEZ/"; 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=muc.de Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 46e09a7af769-71fc9a4c529si14648603a34.303.2024.12.30.08.23.59 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 30 Dec 2024 08:24:00 -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=crOU4kNn; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b="YFBafEZ/"; 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=muc.de 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.95) (envelope-from ) id 1tSIYd-0005of-MB; Mon, 30 Dec 2024 16:23:55 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1tSIYc-0005oS-OW for openvpn-devel@lists.sourceforge.net; Mon, 30 Dec 2024 16:23:54 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: 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=Oyd6o6GMXPhJVVWMiDXMFcysXNjmq6qd4YAqMMu8/uU=; b=crOU4kNnNwBbCCD66A7mHJgRit Wcc0uprsDiD/nCM4Xblk7K4z1MsHQHeGZWJATNSyTtdH9ZeF4iheZ2xNNDEfHmXQZQadUHPXx+0Kk FtasJcxh3ZpqKELZ7W5rmSP5lSKdPjcNiUrkj4MAPjnUZYwGOxPK+mbKvJ+eYlkRfSko=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: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=Oyd6o6GMXPhJVVWMiDXMFcysXNjmq6qd4YAqMMu8/uU=; b=YFBafEZ/0bvs5jAlov58sIPvqi 8ZU3Hvfou5+L2RNsBaF1iSdKIXKoaXB3TD1N3Y7aXQlK4JN3omE6WKgAQgAbvyiHnnk+5D4vr6nfL ZzSrb60zjFrzEzAwS7NZ37HprAh6uCW6QuhSqAPI7XxhRGmIkxTaugSHOca83RfyX4nU=; Received: from dhcp-174.greenie.muc.de ([193.149.48.174] helo=blue.greenie.muc.de) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1tSIYZ-0007YL-7h for openvpn-devel@lists.sourceforge.net; Mon, 30 Dec 2024 16:23:54 +0000 Received: from blue.greenie.muc.de (localhost [127.0.0.1]) by blue.greenie.muc.de (8.17.1.9/8.17.1.9) with ESMTP id 4BUGNcdZ021411 for ; Mon, 30 Dec 2024 17:23:38 +0100 Received: (from gert@localhost) by blue.greenie.muc.de (8.17.1.9/8.17.1.9/Submit) id 4BUGNcmJ021410 for openvpn-devel@lists.sourceforge.net; Mon, 30 Dec 2024 17:23:38 +0100 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Mon, 30 Dec 2024 17:23:37 +0100 Message-ID: <20241230162338.21401-1-gert@greenie.muc.de> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: 0.0 (/) X-Spam-Report: Spam detection software, running on the system "util-spamd-1.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: From: Antonio Quartulli Introduce internal changes preparing the server to handle multiple sockets concurrently for both TCP and UDP protocols. While no user-visible features are implemented yet, these modifications are ess [...] Content analysis details: (0.0 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 RCVD_IN_VALIDITY_SAFE_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [193.149.48.174 listed in sa-trusted.bondedsender.org] 0.0 RCVD_IN_VALIDITY_RPBL_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [193.149.48.174 listed in bl.score.senderscore.com] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record X-Headers-End: 1tSIYZ-0007YL-7h Subject: [Openvpn-devel] [PATCH v11] Adapt socket handling to support listening on multiple sockets 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: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1819883172250544050?= X-GMAIL-MSGID: =?utf-8?q?1819883172250544050?= From: Antonio Quartulli Introduce internal changes preparing the server to handle multiple sockets concurrently for both TCP and UDP protocols. While no user-visible features are implemented yet, these modifications are essential for enabling future functionality such as listening on multiple ports. Key changes are: converting link_socket from a single pointer to an array in various contexts, in order to be able to store multiple sockets at once. Change-Id: Ia0a889e800f0b36aed770ee36e31afeec5df6084 Signed-off-by: Antonio Quartulli Signed-off-by: Gianmarco De Gregori Acked-by: Gert Doering --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/434 This mail reflects revision 11 of this Change. Acked-by according to Gerrit (reflected above): Gert Doering diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c index dcc80d3..8f2adb5 100644 --- a/src/openvpn/dco.c +++ b/src/openvpn/dco.c @@ -478,11 +478,11 @@ return 0; } - struct link_socket *ls = c->c2.link_socket; + struct link_socket *sock = c->c2.link_sockets[0]; - ASSERT(ls->info.connection_established); + ASSERT(sock->info.connection_established); - struct sockaddr *remoteaddr = &ls->info.lsa->actual.dest.addr.sa; + struct sockaddr *remoteaddr = &sock->info.lsa->actual.dest.addr.sa; struct tls_multi *multi = c->c2.tls_multi; #ifdef TARGET_FREEBSD /* In Linux in P2P mode the kernel automatically removes an existing peer @@ -494,7 +494,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; @@ -527,12 +527,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) { @@ -577,7 +577,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) @@ -587,8 +587,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/forward.c b/src/openvpn/forward.c index 2c72001..f3f3503 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -58,12 +58,17 @@ 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", + + 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 (int 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); } @@ -99,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) { @@ -567,6 +572,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) @@ -1123,7 +1129,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 + /* on the instance context we have only one socket, 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 */ @@ -1451,7 +1459,7 @@ */ void -process_incoming_tun(struct context *c) +process_incoming_tun(struct context *c, struct link_socket *out_sock) { struct gc_arena gc = gc_new(); @@ -1484,7 +1492,7 @@ */ unsigned int flags = PIPV4_PASSTOS | PIP_MSSFIX | PIPV4_CLIENT_NAT | PIPV6_ICMP_NOHOST_CLIENT; - process_ip_header(c, flags, &c->c2.buf); + process_ip_header(c, flags, &c->c2.buf, out_sock); #ifdef PACKET_TRUNCATION_CHECK /* if (c->c2.buf.len > 1) --c->c2.buf.len; */ @@ -1645,7 +1653,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 *sock) { if (!c->options.ce.mssfix) { @@ -1679,7 +1688,7 @@ /* extract TOS from IP header */ if (flags & PIPV4_PASSTOS) { - link_socket_extract_tos(c->c2.link_socket, &ipbuf); + link_socket_extract_tos(sock, &ipbuf); } #endif @@ -1887,7 +1896,7 @@ */ void -process_outgoing_tun(struct context *c) +process_outgoing_tun(struct context *c, struct link_socket *in_sock) { /* * Set up for write() call to TUN/TAP @@ -1904,9 +1913,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_sock); if (c->c2.to_tun.len <= c->c2.frame.buf.payload_size) { @@ -2180,8 +2188,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 (int 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) @@ -2219,7 +2230,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; @@ -2311,7 +2322,7 @@ /* TUN device ready to accept write */ else if (status & TUN_WRITE) { - process_outgoing_tun(c); + process_outgoing_tun(c, sock); } /* Incoming data on TCP/UDP port */ else if (status & SOCKET_READ) @@ -2328,7 +2339,7 @@ read_incoming_tun(c); if (!IS_SIG(c)) { - process_incoming_tun(c); + process_incoming_tun(c, sock); } } else if (status & DCO_READ) diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 4cd470a..ca2a695 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_sock 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_sock); /** @@ -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_sock Socket where the packet was received. */ -void process_outgoing_tun(struct context *c); +void process_outgoing_tun(struct context *c, struct link_socket *in_sock); /**************************************************************************/ @@ -304,20 +307,21 @@ #define PIPV6_ICMP_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 *sock); bool schedule_exit(struct context *c); 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 a23cb24..850cd12 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -536,12 +536,12 @@ { /* 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->options.advance_next_remote) { - 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 { @@ -557,20 +557,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; @@ -735,6 +735,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) { @@ -744,6 +751,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) { @@ -1644,7 +1655,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)) { @@ -1770,8 +1781,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, @@ -1954,17 +1965,16 @@ do_alloc_route_list(c); /* parse and resolve the route option list */ - ASSERT(c->c2.link_socket); + ASSERT(c->c2.link_sockets[0]); 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 */ @@ -1977,8 +1987,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 */ @@ -1993,6 +2002,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); @@ -2004,8 +2014,7 @@ /* 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 */ @@ -2486,7 +2495,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 @@ -2709,13 +2718,23 @@ if (found & OPT_P_SOCKBUF) { 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 (int 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) { msg(D_PUSH, "OPTIONS IMPORT: --socket-flags option modified"); - link_socket_update_flags(c->c2.link_socket, c->options.sockflags); + for (int 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) @@ -3791,12 +3810,63 @@ static void do_link_socket_new(struct context *c) { - ASSERT(!c->c2.link_socket); - c->c2.link_socket = link_socket_new(); + ASSERT(!c->c2.link_sockets); + + ALLOC_ARRAY_GC(c->c2.link_sockets, struct link_socket *, + c->c1.link_sockets_num, &c->c2.gc); + + for (int 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_phase1(struct context *c) +{ + for (int 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 args */ + link_socket_init_phase1(c, i, mode); + } +} + +/* + * finalize TCP/UDP sockets + */ +static void +do_init_socket_phase2(struct context *c) +{ + for (int i = 0; i < c->c1.link_sockets_num; i++) + { + link_socket_init_phase2(c, c->c2.link_sockets[i]); + } +} + +/* * Print MTU INFO */ static void @@ -3951,15 +4021,21 @@ /* 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_socket->sd = SOCKET_UNDEFINED; + for (int i = 0; i < c->c1.link_sockets_num; i++) + { + c->c2.link_sockets[i]->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; + for (int i = 0; i < c->c1.link_sockets_num; i++) + { + link_socket_close(c->c2.link_sockets[i]); + } + c->c2.link_sockets = NULL; } @@ -3970,28 +4046,36 @@ && ( (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); + for (int i = 0; i < c->c1.link_sockets_num; i++) + { + CLEAR(c->c1.link_socket_addrs[i].actual); + } } if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_local_ip)) { - if (c->c1.link_socket_addr.bind_local && !c->options.resolve_in_advance) + for (int i = 0; i < c->c1.link_sockets_num; i++) { - 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; + } } } @@ -4474,7 +4558,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); @@ -4515,21 +4598,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) { @@ -4672,7 +4740,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_phase1(c); } /* initialize tun/tap device object, @@ -4715,15 +4783,18 @@ /* 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_phase2(c); /* Update dynamic frame calculation as exact transport socket information * (IP vs IPv6) may be only available after socket phase2 has finished. * This is only needed for --static or no crypto, NCP will recalculate this * in tls_session_update_crypto_params (P2MP) */ - frame_calculate_dynamic(&c->c2.frame, &c->c1.ks.key_type, &c->options, - get_link_socket_info(c)); + for (int i = 0; i < c->c1.link_sockets_num; i++) + { + frame_calculate_dynamic(&c->c2.frame, &c->c1.ks.key_type, &c->options, + &c->c2.link_sockets[i]->info); + } } /* @@ -4851,7 +4922,8 @@ void inherit_context_child(struct context *dest, - const struct context *src) + const struct context *src, + struct link_socket *ls) { CLEAR(*dest); @@ -4864,6 +4936,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 */ @@ -4888,7 +4962,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 @@ -4903,28 +4977,33 @@ */ dest->c1.tuntap = src->c1.tuntap; + /* 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_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_infos[0]->lsa = &dest->c1.link_socket_addrs[0]; + dest->c2.link_socket_infos[0]->connection_established = false; + } + init_instance(dest, src->c2.es, CC_NO_CLOSE | CC_USR1_TO_HUP); if (IS_SIG(dest)) { return; } - - /* UDP inherits some extra things which TCP does not */ - if (dest->mode == CM_CHILD_UDP) - { - /* inherit buffers */ - dest->c2.buffers = src->c2.buffers; - - /* inherit parent link_socket and tuntap */ - dest->c2.link_socket = src->c2.link_socket; - - ALLOC_OBJ_GC(dest->c2.link_socket_info, struct link_socket_info, &dest->gc); - *dest->c2.link_socket_info = src->c2.link_socket->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; - } } void diff --git a/src/openvpn/init.h b/src/openvpn/init.h index ea7eb30..11c32ac 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 ebdec25..89dee7d 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 a2841f0..b5bbf13 100644 --- a/src/openvpn/mtcp.c +++ b/src/openvpn/mtcp.c @@ -114,13 +114,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; @@ -170,13 +170,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; @@ -232,7 +235,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)); @@ -247,7 +250,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, @@ -261,8 +264,12 @@ { int status; unsigned int *persistent = &mtcp->tun_rwflags; - socket_set_listen_persistent(c->c2.link_socket, mtcp->es, - &c->c2.link_socket->ev_arg); + + for (int 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)) @@ -480,16 +487,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; @@ -565,7 +574,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; } @@ -720,9 +729,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.sock) + { + msg(D_MULTI_ERRORS, "MULTI: mtcp_proc_io: null socket"); + break; + } + + socket_reset_listen_persistent(ev_arg->u.sock); + mi = multi_create_instance_tcp(m, ev_arg->u.sock); if (mi) { multi_tcp_action(m, mi, TA_INITIAL, false); diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c index 5fbd7b0..6137578 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 = {0}; @@ -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); + process_outgoing_link(&m->top, m->top.c2.link_sockets[0]); m->hmac_reply_dest = NULL; } } @@ -326,7 +327,7 @@ * Process an I/O event. */ static void -multi_process_io_udp(struct multi_context *m) +multi_process_io_udp(struct multi_context *m, struct link_socket *sock) { const unsigned int status = m->top.c2.event_set_status; const unsigned int mpp_flags = m->top.c2.fast_io @@ -380,10 +381,10 @@ /* Incoming data on UDP port */ else if (status & SOCKET_READ) { - read_incoming_link(&m->top, m->top.c2.link_socket); + read_incoming_link(&m->top, sock); if (!IS_SIG(&m->top)) { - multi_process_incoming_link(m, NULL, mpp_flags); + multi_process_incoming_link(m, NULL, mpp_flags, sock); } } /* Incoming data on TUN device */ @@ -514,7 +515,11 @@ else { /* process I/O */ - multi_process_io_udp(&multi); + + /* Since there's only one link_socket just use the first, in an upcoming + * patch this will be changed by using the link_socket returned by the + * event set */ + multi_process_io_udp(&multi, top->c2.link_sockets[0]); MULTI_CHECK_SIG(&multi); } diff --git a/src/openvpn/mudp.h b/src/openvpn/mudp.h index 14e90d0..b378754 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 45b3cfa..67bb58f 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -750,7 +750,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 +774,7 @@ generate_prefix(mi); } - inherit_context_child(&mi->context, &m->top); + inherit_context_child(&mi->context, &m->top, ls); if (IS_SIG(&mi->context)) { goto err; @@ -3124,7 +3125,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 = {0}; struct hash *hash = m->hash; @@ -3180,8 +3182,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); @@ -3329,7 +3331,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(); @@ -3350,7 +3353,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 { @@ -3391,7 +3394,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); @@ -3610,7 +3613,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); @@ -3642,7 +3645,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 93ac9e7..9b6834a 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -275,7 +275,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); @@ -289,7 +290,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) @@ -354,8 +356,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); /** @@ -669,7 +673,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; @@ -684,7 +688,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 c52540c..977d02d 100644 --- a/src/openvpn/openvpn.c +++ b/src/openvpn/openvpn.c @@ -91,7 +91,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 8dfcab4..df43bba 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. */ @@ -233,11 +234,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/ping.h b/src/openvpn/ping.h index 887172c..4a87895 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 b895bd4..f9f2a3b 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 */ @@ -1454,7 +1469,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) @@ -1851,9 +1865,9 @@ } void -link_socket_init_phase1(struct context *c, int mode) +link_socket_init_phase1(struct context *c, int sock_index, int mode) { - struct link_socket *sock = c->c2.link_socket; + struct link_socket *sock = c->c2.link_sockets[sock_index]; struct options *o = &c->options; ASSERT(sock); @@ -1879,19 +1893,20 @@ sock->socket_buffer_sizes.sndbuf = o->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->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.lsa = &c->c1.link_socket_addrs[sock_index]; sock->info.bind_ipv6_only = o->ce.bind_ipv6_only; sock->info.ipchange_command = o->ipchange; sock->info.plugins = c->plugins; @@ -2186,9 +2201,9 @@ /* 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; @@ -2234,7 +2249,6 @@ { create_socket(sock, sock->info.lsa->current_remote); } - } /* If socket has not already been created create it now */ @@ -2253,7 +2267,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); } } diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h index 465d92b..16106d4 100644 --- a/src/openvpn/socket.h +++ b/src/openvpn/socket.h @@ -344,9 +344,13 @@ /* * Initialize link_socket object. */ -void link_socket_init_phase1(struct context *c, int mode); +void +link_socket_init_phase1(struct context *c, + int sock_index, + int mode); -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); @@ -1228,11 +1232,12 @@ * Socket I/O wait functions */ -static inline bool -socket_read_residual(const struct link_socket *sock) -{ - return sock && sock->stream_buf.residual_fully_formed; -} +/* + * Extends the pre-existing read residual logic + * to all initialized sockets, ensuring the complete + * packet is read. + */ +bool sockets_read_residual(const struct context *c); static inline event_t socket_event_handle(const struct link_socket *sock)