From patchwork Thu Jul 18 14:03:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "plaisthos (Code Review)" X-Patchwork-Id: 3768 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:6242:b0:5a1:d4fc:4ac6 with SMTP id v2csp15701mad; Thu, 18 Jul 2024 07:04:08 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCVop1TLMT/OcoDk0lIzFCzkci5c4WamfN60vUo+aoexqiAmirBTxFaLjdunp5M1tTP9U2PeWxcj75ZbgQt50jfVRm+iR6c= X-Google-Smtp-Source: AGHT+IFH5WoIvg9jEufNI/FA5fI4U8rNojTNGEKU/ULdU5tXOgipnS+GDixeiUDnCca4x/jl5Ftr X-Received: by 2002:a05:6a21:38a:b0:1c0:f305:b9d9 with SMTP id adf61e73a8af0-1c3fddb4c1dmr2899764637.6.1721311448375; Thu, 18 Jul 2024 07:04:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1721311448; cv=none; d=google.com; s=arc-20160816; b=KwpFO96dixef/Qm6JS0DsUuxIUYV0UPB+CL85MUH69OXFm4vgF0ctJnBpaGY+KbSyX ohvhRNIVn+17sOIVkpyd42DveosLt6iVSQ2TLB06FaAo8fVOQzXJx9ykDsAGs/VZZQOT dNPi8fcCCvfPWeZZxBTYgoIYRmITUOU9Sxqj2ITJA0DyPUyGsdaaYDJXyr8R51gZfRql 9s47mAq5/jZHA1/htoev90vhHVsLwE5ZOdbcTwXqmwuAJy6lsHn7uziZ8tFmrLBsAtq3 191qFmJ3+bKZIc1CZOvjK45byb5Jihinkx1P2Let9QIUNkBOOY6meOYnBuKLGz1x2jJA 9Nyw== 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=j5cpG0Okyxz3amZRzvLjJrfKZbb34BopCMu9Fxp5CAE=; fh=U7wEyxtwz2o5+UdevFSA47vNeG9knhWH0KV//QhD5a0=; b=N8FcH2xqiqsYKMoQgKCyJSYNET78r1f82fXLfKSITJNodSSwLyufTBiduuhMA/DUHP R2tVL/KiFpX5+to8zsaTYFFn7NSDgGbkMAA5N/0UeSQJ+StM3PO+DP91lOFTq1HfLRTT aZK2DsULeTmGS7QphLRUTVQ1R5ArQD1L7p+uDY9LDJGks1YGypoK6dVvKBcCOp9iHNcC 5kDmxm9Cg6fFytgpCh7Ofb63pDLmj50z1TXR/Vq2Lf+cV2T6fmdyrpFZb5msUbn3yn/H nBKHIuDOvolGcmGELh03K4tKrCpEoQfSnF/ltIuFwe7TIFAGq99a65XB1lq33hIoblS5 GV2A==; 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=gOmct1LT; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=JVkqFqX9; dkim=neutral (body hash did not verify) header.i=@openvpn.net header.s=google header.b=I9ZeE4Pi; 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; dara=fail header.i=@openvpn.net Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 41be03b00d2f7-78e3bea950asi12280334a12.61.2024.07.18.07.04.08 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 18 Jul 2024 07:04:08 -0700 (PDT) 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=gOmct1LT; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=JVkqFqX9; dkim=neutral (body hash did not verify) header.i=@openvpn.net header.s=google header.b=I9ZeE4Pi; 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; dara=fail header.i=@openvpn.net Received: from [127.0.0.1] (helo=sfs-ml-3.v29.lw.sourceforge.com) by sfs-ml-3.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1sURja-0004v2-C5; Thu, 18 Jul 2024 14:03:49 +0000 Received: from [172.30.29.67] (helo=mx.sourceforge.net) by sfs-ml-3.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1sURjZ-0004uv-Cs for openvpn-devel@lists.sourceforge.net; Thu, 18 Jul 2024 14:03:48 +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=vhqEmGGE4IlCIsqxng8A3U5W0Uc2wicMN8VgzaEbxwk=; b=gOmct1LTw7Y4XZWaGQkHKY132F mbvfu6T+o1s0aweVOMZTmz6dbuXVVSZNSZnpvZOthnONfM/yK6YQk+nF9yIMIPnFIZyL8egKEvT8i DpcEjZiGZkfSpCb2w/9BJHO834Ew1VkS19D4RuZOSSAs4P/INvLiFrjKmCFfBdTRnsis=; 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=vhqEmGGE4IlCIsqxng8A3U5W0Uc2wicMN8VgzaEbxwk=; b=J VkqFqX9xi18SiYLUEJvEK9onhr3JAK+o2SLveswmxISWlr3yPT7AFTkmk5fpZNMqIjF8g8Dad2sbf BCkM8d7aTOoJLRGBFyv5+h82Kve9xKcXBJLpQ7X9JQOh6UtHEFclT5QKlmqbcgRCAiDWFCqVf5uj1 P3TycaNsee9xweyI=; Received: from mail-wr1-f47.google.com ([209.85.221.47]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.95) id 1sURjW-0002sQ-86 for openvpn-devel@lists.sourceforge.net; Thu, 18 Jul 2024 14:03:48 +0000 Received: by mail-wr1-f47.google.com with SMTP id ffacd0b85a97d-367a3d1a378so761503f8f.1 for ; Thu, 18 Jul 2024 07:03:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=openvpn.net; s=google; t=1721311414; x=1721916214; 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=vhqEmGGE4IlCIsqxng8A3U5W0Uc2wicMN8VgzaEbxwk=; b=I9ZeE4Pik6ZVYQfuAB7hXk3sHMidoNJN2j264PIJfGVLKFFPxmf/xfBZY8d/s8mfRH 5alR8g2LEhLBaSEjIGa2DnF1VT4sZDKxm4d8OklCqxm3nhZ5m4M8EK7Cspy5CBtEMzTG wiCFyTGGIUOXoNDhFmGW18aBqKOxrRCrxF4G98qgl6WYEKnXTsT59GPSl1gzOdsIjEzY TPscA1Ztnodri32BRDT5HLBGz16YRSDtvfA9b7EinsiZCkjl9obutexsHUlbKU1mmiey Blbli4Fza1drf3FkbmVWjGwReqEnPb/AUYErJ8x1WVcHDHSfTxmRob2mrgkoB5rcecLQ jBbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721311414; x=1721916214; 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=vhqEmGGE4IlCIsqxng8A3U5W0Uc2wicMN8VgzaEbxwk=; b=ISiL7zKaAQx7m5YdQSPYmlQ9BANjcUqYCvmdz7O/u2eVJL+y6+Ys0KtJ5AUbUd6qqU K+8O4cxKI3/NOxHEgFURIWXVy/GpGw6jWh4BcG8/nozUHznE2YygG6vZIURbel/9R8Oa YF3chMKMGaqa2TRzNWK3UezOzhq/pKeNP2XRvR+o7585VMmWW5rIJ10fkCpCwtKoN+Fs 159+qX2mxnuK8ftoldWjA/vcsjdjvrb1JYQE5CElPekZOkxGtO+Uvwju45h+hkDTbJQl kvkBlWbs+HJVuyA6B1XddzKIx4XiAHD+Yt60zTXICmCWdd0/I/PnxaMdvLq4P7UkJWle xhBg== X-Gm-Message-State: AOJu0YyRSDNJJV3i4uyHxL/6z+HWfHTYVVLCMfDw2v70dMAaXBWb1Vu8 IsyVg9oDDBti0VMDg5rOVIwcatLegbNAIXZVXWdhp0wx5BygQfYTdd5fCM5XTfFhU29l2+b8RbL C X-Received: by 2002:a5d:58cf:0:b0:366:ee01:30d6 with SMTP id ffacd0b85a97d-36831730063mr4707361f8f.49.1721311413474; Thu, 18 Jul 2024 07:03:33 -0700 (PDT) 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 ffacd0b85a97d-3680dab3ed9sm14596847f8f.9.2024.07.18.07.03.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Jul 2024 07:03:32 -0700 (PDT) From: "mrbff (Code Review)" X-Google-Original-From: "mrbff (Code Review)" X-Gerrit-PatchSet: 1 Date: Thu, 18 Jul 2024 14:03:32 +0000 To: plaisthos , flichtenheld Auto-Submitted: auto-generated X-Gerrit-MessageType: newchange X-Gerrit-Change-Id: I3dbd61fef20d683734b55b73e40afe56c3b733e1 X-Gerrit-Change-Number: 678 X-Gerrit-Project: openvpn X-Gerrit-ChangeURL: X-Gerrit-Commit: c0c3c4f44e48fbda18cbffc5338d0be33b5c3daa References: Message-ID: <86d445f5c4c6a61c2c7ee28d5d981ebb4138ed23-HTML@gerrit.openvpn.net> MIME-Version: 1.0 User-Agent: Gerrit/3.8.2 X-Spam-Score: -5.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: (-5.2 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [URIs: openvpn.net] -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at https://www.dnswl.org/, high trust [209.85.221.47 listed in list.dnswl.org] 0.0 RCVD_IN_VALIDITY_CERTIFIED_BLOCKED RBL: ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. [209.85.221.47 listed in sa-accredit.habeas.com] 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. [209.85.221.47 listed in bl.score.senderscore.com] -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.221.47 listed in wl.mailspike.net] -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 Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.0 T_KAM_HTML_FONT_INVALID Test for Invalidly Named or Formatted Colors in HTML X-Headers-End: 1sURjW-0002sQ-86 Subject: [Openvpn-devel] [L] Change in openvpn[master]: route: extended logic to omit gateway when unnecessary 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: marco@mandelbit.com, 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?1804925872973405896?= X-GMAIL-MSGID: =?utf-8?q?1804925872973405896?= 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/+/678?usp=email to review the following change. Change subject: route: extended logic to omit gateway when unnecessary ...................................................................... route: extended logic to omit gateway when unnecessary Extracted and extended the logic behind 'gateway_needed' both in add_route() and add_route_ipv6(). Other than checking the dev-type, special routes and if the gateway is on-link, - set gateway_needed to true if the vpn instance is a multipoint server and DCO is enabled. - set gateway_needed to false if the gateway is in the vpn subnet. Additionally, extended support for these checks and conditions to DARWIN and BSD-based operating systems. These changes ensure that the gateway is only included when necessary, optimizing route configuration and potentially reducing redundant route entries. Change-Id: I3dbd61fef20d683734b55b73e40afe56c3b733e1 Signed-off-by: Marco Baffo --- M src/openvpn/forward.c M src/openvpn/init.c M src/openvpn/init.h M src/openvpn/route.c M src/openvpn/route.h M src/openvpn/tun.c M src/openvpn/tun.h 7 files changed, 253 insertions(+), 128 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/78/678/1 diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 71b7167..35773ec 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -448,7 +448,7 @@ check_add_routes_action(struct context *c, const bool errors) { bool route_status = do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list, - c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx); + c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx, c->mode == CM_TOP); int flags = (errors ? ISC_ERRORS : 0); flags |= (!route_status ? ISC_ROUTE_ERRORS : 0); diff --git a/src/openvpn/init.c b/src/openvpn/init.c index a49e563..b0a718e 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -1689,13 +1689,14 @@ const struct tuntap *tt, const struct plugin_list *plugins, struct env_set *es, - openvpn_net_ctx_t *ctx) + openvpn_net_ctx_t *ctx, + const bool is_multipoint) { bool ret = true; if (!options->route_noexec && ( route_list || route_ipv6_list ) ) { ret = add_routes(route_list, route_ipv6_list, tt, ROUTE_OPTION_FLAGS(options), - es, ctx); + es, ctx, is_multipoint); setenv_int(es, "redirect_gateway", route_did_redirect_default_gateway(route_list)); } #ifdef ENABLE_MANAGEMENT @@ -1898,7 +1899,7 @@ c->options.dev_node, &gc); do_ifconfig(c->c1.tuntap, guess, c->c2.frame.tun_mtu, c->c2.es, - &c->net_ctx); + &c->net_ctx, c->mode == CM_TOP); } /* possibly add routes */ @@ -1906,7 +1907,7 @@ { /* Ignore route_delay, would cause ROUTE_BEFORE_TUN to be ignored */ bool status = do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list, - c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx); + c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx, c->mode == CM_TOP); *error_flags |= (status ? 0 : ISC_ROUTE_ERRORS); } #ifdef TARGET_ANDROID @@ -1934,7 +1935,7 @@ && 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); + c->c2.frame.tun_mtu, c->c2.es, &c->net_ctx, c->mode == CM_TOP); } /* run the up script */ @@ -1960,7 +1961,7 @@ if ((route_order() == ROUTE_AFTER_TUN) && (!c->options.route_delay_defined)) { int status = do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list, - c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx); + c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx, c->mode == CM_TOP); *error_flags |= (status ? 0 : ISC_ROUTE_ERRORS); } @@ -2086,7 +2087,7 @@ delete_routes(c->c1.route_list, c->c1.route_ipv6_list, c->c1.tuntap, ROUTE_OPTION_FLAGS(&c->options), - c->c2.es, &c->net_ctx); + c->c2.es, &c->net_ctx, c->mode == CM_TOP); } /* actually close tun/tap device based on --down-pre flag */ diff --git a/src/openvpn/init.h b/src/openvpn/init.h index ea7eb30..82eec7e 100644 --- a/src/openvpn/init.h +++ b/src/openvpn/init.h @@ -74,7 +74,7 @@ bool do_route(const struct options *options, struct route_list *route_list, struct route_ipv6_list *route_ipv6_list, const struct tuntap *tt, const struct plugin_list *plugins, struct env_set *es, - openvpn_net_ctx_t *ctx); + openvpn_net_ctx_t *ctx, const bool is_multipoint); void close_instance(struct context *c); diff --git a/src/openvpn/route.c b/src/openvpn/route.c index bc8f561..2999cb6 100644 --- a/src/openvpn/route.c +++ b/src/openvpn/route.c @@ -927,7 +927,8 @@ unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es, - openvpn_net_ctx_t *ctx) + openvpn_net_ctx_t *ctx, + const bool is_multipoint) { struct route_ipv4 r; CLEAR(r); @@ -935,7 +936,7 @@ r.network = network; r.netmask = netmask; r.gateway = gateway; - return add_route(&r, tt, flags, rgi, es, ctx); + return add_route(&r, tt, flags, rgi, es, ctx, is_multipoint); } static void @@ -964,7 +965,8 @@ unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es, - openvpn_net_ctx_t *ctx) + openvpn_net_ctx_t *ctx, + const bool is_multipoint) { int ret = true; for (int i = 0; i < rb->n_bypass; ++i) @@ -972,7 +974,7 @@ if (rb->bypass[i]) { ret = add_route3(rb->bypass[i], IPV4_NETMASK_HOST, gateway, tt, - flags | ROUTE_REF_GW, rgi, es, ctx) && ret; + flags | ROUTE_REF_GW, rgi, es, ctx, is_multipoint) && ret; } } return ret; @@ -1007,7 +1009,7 @@ static bool redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es, - openvpn_net_ctx_t *ctx) + openvpn_net_ctx_t *ctx, const bool is_multipoint) { const char err[] = "NOTE: unable to redirect IPv4 default gateway --"; bool ret = true; @@ -1059,7 +1061,7 @@ { ret = add_route3(rl->spec.remote_host, IPV4_NETMASK_HOST, rl->rgi.gateway.addr, tt, flags | ROUTE_REF_GW, - &rl->rgi, es, ctx); + &rl->rgi, es, ctx, is_multipoint); rl->iflags |= RL_DID_LOCAL; } else @@ -1071,7 +1073,7 @@ /* route DHCP/DNS server traffic through original default gateway */ ret = add_bypass_routes(&rl->spec.bypass, rl->rgi.gateway.addr, tt, flags, - &rl->rgi, es, ctx) && ret; + &rl->rgi, es, ctx, is_multipoint) && ret; if (rl->flags & RG_REROUTE_GW) { @@ -1079,11 +1081,11 @@ { /* add new default route (1st component) */ ret = add_route3(0x00000000, 0x80000000, rl->spec.remote_endpoint, - tt, flags, &rl->rgi, es, ctx) && ret; + tt, flags, &rl->rgi, es, ctx, is_multipoint) && ret; /* add new default route (2nd component) */ ret = add_route3(0x80000000, 0x80000000, rl->spec.remote_endpoint, - tt, flags, &rl->rgi, es, ctx) && ret; + tt, flags, &rl->rgi, es, ctx, is_multipoint) && ret; } else { @@ -1097,7 +1099,7 @@ /* add new default route */ ret = add_route3(0, 0, rl->spec.remote_endpoint, tt, - flags, &rl->rgi, es, ctx) && ret; + flags, &rl->rgi, es, ctx, is_multipoint) && ret; } } @@ -1112,7 +1114,8 @@ undo_redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es, - openvpn_net_ctx_t *ctx) + openvpn_net_ctx_t *ctx, + const bool is_multipoint) { if (rl && rl->iflags & RL_DID_REDIRECT_DEFAULT_GATEWAY) { @@ -1173,7 +1176,7 @@ if (rl->rgi.flags & RGI_ADDR_DEFINED) { add_route3(0, 0, rl->rgi.gateway.addr, tt, - flags | ROUTE_REF_GW, &rl->rgi, es, ctx); + flags | ROUTE_REF_GW, &rl->rgi, es, ctx, is_multipoint); } } } @@ -1185,9 +1188,10 @@ bool add_routes(struct route_list *rl, struct route_ipv6_list *rl6, const struct tuntap *tt, unsigned int flags, - const struct env_set *es, openvpn_net_ctx_t *ctx) + const struct env_set *es, openvpn_net_ctx_t *ctx, + const bool is_multipoint) { - bool ret = redirect_default_route_to_vpn(rl, tt, flags, es, ctx); + bool ret = redirect_default_route_to_vpn(rl, tt, flags, es, ctx, is_multipoint); if (rl && !(rl->iflags & RL_ROUTES_ADDED) ) { struct route_ipv4 *r; @@ -1220,7 +1224,7 @@ { delete_route(r, tt, flags, &rl->rgi, es, ctx); } - ret = add_route(r, tt, flags, &rl->rgi, es, ctx) && ret; + ret = add_route(r, tt, flags, &rl->rgi, es, ctx, is_multipoint) && ret; } rl->iflags |= RL_ROUTES_ADDED; } @@ -1242,7 +1246,7 @@ { delete_route_ipv6(r, tt, flags, es, ctx); } - ret = add_route_ipv6(r, tt, flags, es, ctx) && ret; + ret = add_route_ipv6(r, tt, flags, es, ctx, is_multipoint) && ret; } rl6->iflags |= RL_ROUTES_ADDED; } @@ -1253,7 +1257,8 @@ void delete_routes(struct route_list *rl, struct route_ipv6_list *rl6, const struct tuntap *tt, unsigned int flags, - const struct env_set *es, openvpn_net_ctx_t *ctx) + const struct env_set *es, openvpn_net_ctx_t *ctx, + const bool is_multipoint) { if (rl && rl->iflags & RL_ROUTES_ADDED) { @@ -1265,7 +1270,7 @@ rl->iflags &= ~RL_ROUTES_ADDED; } - undo_redirect_default_route_to_vpn(rl, tt, flags, es, ctx); + undo_redirect_default_route_to_vpn(rl, tt, flags, es, ctx, is_multipoint); if (rl) { @@ -1561,13 +1566,47 @@ } #endif +static bool +is_gateway_needed_ipv4(const struct route_ipv4 *r4, + const struct route_gateway_info *rgi, + const struct tuntap *tt, + const bool is_multipoint) +{ + +#ifndef _WIN32 + + if (rgi && (rgi->flags & RGI_IFACE_DEFINED) && rgi->iface[0] != 0) /* vpn server special route */ + { + if (rgi->flags & RGI_ADDR_DEFINED && r4->gateway != 0) + { + return true; + } + } + +#endif + + if (tt->type == DEV_TYPE_TAP + && !( (r4->flags & RT_METRIC_DEFINED) && r4->metric == 0 ) ) + { + return true; + } + + if (is_multipoint && !tt->options.disable_dco) + { + return true; + } + + return false; +} + bool add_route(struct route_ipv4 *r, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, /* may be NULL */ const struct env_set *es, - openvpn_net_ctx_t *ctx) + openvpn_net_ctx_t *ctx, + const bool is_multipoint) { int status = 0; int is_local_route; @@ -1581,15 +1620,11 @@ struct argv argv = argv_new(); struct gc_arena gc = gc_new(); -#if defined(TARGET_LINUX) - const char *iface = tt->actual_name; - if (rgi && rgi->iface[0] != '\0') /* vpn server special route */ +#ifndef _WIN32 + const char *device = tt->actual_name; + if (rgi && (rgi->flags & RGI_IFACE_DEFINED)) /* vpn server special route */ { - iface = rgi->iface; - if (r->gateway != 0) - { - gateway_needed = true; - } + device = rgi->iface; } #endif @@ -1607,10 +1642,7 @@ goto done; } - if (tt->type == DEV_TYPE_TAP && !(r->flags & RT_METRIC_DEFINED && r->metric == 0)) - { - gateway_needed = true; - } + gateway_needed = is_gateway_needed_ipv4(r, rgi, tt, is_multipoint); if (gateway_needed && r->gateway == 0) { @@ -1627,7 +1659,7 @@ if (is_on_link(is_local_route, flags, rgi)) { - iface = rgi->iface; + device = rgi->iface; } if (r->flags & RT_METRIC_DEFINED) @@ -1638,7 +1670,7 @@ status = RTA_SUCCESS; int ret = net_route_v4_add(ctx, &r->network, netmask_to_netbits2(r->netmask), gateway_needed ? &r->gateway : NULL, - iface, 0, metric); + device, 0, metric); if (ret == -EEXIST) { msg(D_ROUTE, "NOTE: Linux route add command failed because route exists"); @@ -1655,7 +1687,7 @@ if (rgi) { - snprintf(out, sizeof(out), "%s %s %s dev %s", network, netmask, gateway, rgi->iface); + snprintf(out, sizeof(out), "%s %s %s dev %s", network, netmask, gateway, device); } else { @@ -1759,7 +1791,7 @@ "ERROR: Solaris route add command failed"); status = ret ? RTA_SUCCESS : RTA_ERROR; -#elif defined(TARGET_FREEBSD) +#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) argv_printf(&argv, "%s add", ROUTE_PATH); @@ -1771,40 +1803,23 @@ } #endif - argv_printf_cat(&argv, "-net %s %s %s", - network, - gateway, - netmask); - - /* FIXME -- add on-link support for FreeBSD */ - - argv_msg(D_ROUTE, &argv); - bool ret = openvpn_execve_check(&argv, es, 0, - "ERROR: FreeBSD route add command failed"); - status = ret ? RTA_SUCCESS : RTA_ERROR; - -#elif defined(TARGET_DRAGONFLY) - - argv_printf(&argv, "%s add", - ROUTE_PATH); - -#if 0 - if (r->flags & RT_METRIC_DEFINED) + if (gateway_needed) { - argv_printf_cat(&argv, "-rtt %d", r->metric); + argv_printf_cat(&argv, "-net %s %s %s", + network, + gateway, + netmask); } -#endif - - argv_printf_cat(&argv, "-net %s %s %s", - network, - gateway, - netmask); - - /* FIXME -- add on-link support for Dragonfly */ + else + { + argv_printf_cat(&argv, "-net %s -iface %s", + network, + device); + } argv_msg(D_ROUTE, &argv); bool ret = openvpn_execve_check(&argv, es, 0, - "ERROR: DragonFly route add command failed"); + "ERROR: BSD route add command failed"); status = ret ? RTA_SUCCESS : RTA_ERROR; #elif defined(TARGET_DARWIN) @@ -1830,10 +1845,19 @@ } else { - argv_printf_cat(&argv, "-net %s %s %s", - network, - gateway, - netmask); + if (gateway_needed) + { + argv_printf_cat(&argv, "-net %s %s %s", + network, + gateway, + netmask); + } + else + { + argv_printf_cat(&argv, "-net %s -interface %s", + network, + device); + } } argv_msg(D_ROUTE, &argv); @@ -1853,11 +1877,19 @@ } #endif - argv_printf_cat(&argv, "-net %s %s -netmask %s", - network, - gateway, - netmask); - + if (gateway_needed) + { + argv_printf_cat(&argv, "-net %s %s -netmask %s", + network, + gateway, + netmask); + } + else + { + argv_printf_cat(&argv, "-net %s -interface %s", + network, + device); + } /* FIXME -- add on-link support for OpenBSD/NetBSD */ argv_msg(D_ROUTE, &argv); @@ -1923,10 +1955,98 @@ } } +static inline struct in6_addr +netbits_to_netmask_ipv6(const int netbits) +{ + struct in6_addr netmask = {{{0}}}; + + if (netbits > 0 && netbits <= 128) + { + const int full_bytes = netbits / 8; + int i; + for (i = 0; i < full_bytes; i++) + { + netmask.s6_addr[i] = 0xFF; + } + if (netbits % 8) + { + netmask.s6_addr[i] = (0xFF << (8 - (netbits % 8))); + } + } + + return netmask; +} + +static bool +is_gateway_in_vpn_subnet_ipv6(const struct in6_addr *gateway, + const struct in6_addr *vpn_subnet, + int netbits) +{ + struct in6_addr netmask = netbits_to_netmask_ipv6(netbits); + + for (int i = 0; i < 16; i++) + { + if ((gateway->s6_addr[i] & netmask.s6_addr[i]) != (vpn_subnet->s6_addr[i] & netmask.s6_addr[i])) + { + return false; + } + } + return true; +} + +static bool +is_gateway_needed_ipv6(const struct route_ipv6 *r6, + const struct tuntap *tt, + const char *network, + const bool is_multipoint) +{ + +#ifndef _WIN32 + if (r6->iface != NULL) /* VPN server special route */ + { + if (!IN6_IS_ADDR_UNSPECIFIED(&r6->gateway)) + { + return true; + } + } +#endif + + /* + * Filter out routes which are essentially no-ops + * (not currently done for IPv6) + */ + + /* On "tun" interface, we never set a gateway if the operating system + * can do "route to interface" - it does not add value, as the target + * dev already fully qualifies the route destination on point-to-point + * interfaces. OTOH, on "tap" interface, we must always set the + * gateway unless the route is to be an on-link network + */ + if (tt->type == DEV_TYPE_TAP + && !( (r6->flags & RT_METRIC_DEFINED) && r6->metric == 0 ) ) + { + return true; + } + + /* if is server and dco enabled, the gateway is needed*/ + if (is_multipoint && !tt->options.disable_dco) + { + return true; + } + + if (is_gateway_in_vpn_subnet_ipv6(&r6->gateway, &tt->local_ipv6, tt->netbits_ipv6)) + { + msg(D_ROUTE, "Ignoring gateway in VPN subnet for route %s/%d", network, r6->netbits); + return false; + } + + return false; +} + bool add_route_ipv6(struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flags, const struct env_set *es, - openvpn_net_ctx_t *ctx) + openvpn_net_ctx_t *ctx, const bool is_multipoint) { int status = 0; bool gateway_needed = false; @@ -1941,13 +2061,9 @@ #ifndef _WIN32 const char *device = tt->actual_name; - if (r6->iface != NULL) /* vpn server special route */ + if (r6->iface != NULL) { device = r6->iface; - if (!IN6_IS_ADDR_UNSPECIFIED(&r6->gateway) ) - { - gateway_needed = true; - } } #endif @@ -1955,6 +2071,8 @@ const char *network = print_in6_addr( r6->network, 0, &gc); const char *gateway = print_in6_addr( r6->gateway, 0, &gc); + gateway_needed = is_gateway_needed_ipv6(r6, tt, network, is_multipoint); + #if defined(TARGET_DARWIN) \ || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) \ || defined(TARGET_OPENBSD) || defined(TARGET_NETBSD) @@ -1982,23 +2100,6 @@ r6->adapter_index ? r6->adapter_index : tt->adapter_index); #endif - /* - * Filter out routes which are essentially no-ops - * (not currently done for IPv6) - */ - - /* On "tun" interface, we never set a gateway if the operating system - * can do "route to interface" - it does not add value, as the target - * dev already fully qualifies the route destination on point-to-point - * interfaces. OTOH, on "tap" interface, we must always set the - * gateway unless the route is to be an on-link network - */ - if (tt->type == DEV_TYPE_TAP - && !( (r6->flags & RT_METRIC_DEFINED) && r6->metric == 0 ) ) - { - gateway_needed = true; - } - if (gateway_needed && IN6_IS_ADDR_UNSPECIFIED(&r6->gateway)) { msg(M_WARN, "ROUTE6 WARNING: " PACKAGE_NAME " needs a gateway " @@ -2011,6 +2112,7 @@ #if defined(TARGET_LINUX) int metric = -1; + if ((r6->flags & RT_METRIC_DEFINED) && (r6->metric > 0)) { metric = r6->metric; @@ -2121,9 +2223,18 @@ #elif defined(TARGET_OPENBSD) - argv_printf(&argv, "%s add -inet6 %s -prefixlen %d %s", + argv_printf(&argv, "%s add -inet6 %s -prefixlen %d ", ROUTE_PATH, - network, r6->netbits, gateway ); + network, r6->netbits); + + if (gateway_needed) + { + argv_printf_cat(&argv, "%s", gateway); + } + else + { + argv_printf_cat(&argv, "-iface %s", device) + } argv_msg(D_ROUTE, &argv); bool ret = openvpn_execve_check(&argv, es, 0, @@ -2132,9 +2243,18 @@ #elif defined(TARGET_NETBSD) - argv_printf(&argv, "%s add -inet6 %s/%d %s", + argv_printf(&argv, "%s add -inet6 %s/%d ", ROUTE_PATH, - network, r6->netbits, gateway ); + network, r6->netbits); + + if (gateway_needed) + { + argv_printf_cat(&argv, "%s", gateway); + } + else + { + argv_printf_cat(&argv, "-iface %s", device) + } argv_msg(D_ROUTE, &argv); bool ret = openvpn_execve_check(&argv, es, 0, diff --git a/src/openvpn/route.h b/src/openvpn/route.h index 421e7d2..ca2cbcd 100644 --- a/src/openvpn/route.h +++ b/src/openvpn/route.h @@ -271,13 +271,13 @@ void route_ipv6_clear_host_bits( struct route_ipv6 *r6 ); -bool add_route_ipv6(struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx); +bool add_route_ipv6(struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx, const bool is_multipoint); void delete_route_ipv6(const struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx); bool add_route(struct route_ipv4 *r, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es, - openvpn_net_ctx_t *ctx); + openvpn_net_ctx_t *ctx, const bool is_multipoint); void add_route_to_option_list(struct route_option_list *l, const char *network, @@ -312,14 +312,16 @@ bool add_routes(struct route_list *rl, struct route_ipv6_list *rl6, const struct tuntap *tt, unsigned int flags, - const struct env_set *es, openvpn_net_ctx_t *ctx); + const struct env_set *es, openvpn_net_ctx_t *ctx, + const bool is_multipoint); void delete_routes(struct route_list *rl, struct route_ipv6_list *rl6, const struct tuntap *tt, unsigned int flags, const struct env_set *es, - openvpn_net_ctx_t *ctx); + openvpn_net_ctx_t *ctx, + const bool is_multipoint); void setenv_routes(struct env_set *es, const struct route_list *rl); diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index ce3d882..3082d89 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -1020,7 +1020,7 @@ */ static void add_route_connected_v6_net(struct tuntap *tt, - const struct env_set *es) + const struct env_set *es, const bool is_multipoint) { struct route_ipv6 r6; @@ -1030,7 +1030,7 @@ r6.gateway = tt->local_ipv6; r6.metric = 0; /* connected route */ r6.flags = RT_DEFINED | RT_METRIC_DEFINED; - add_route_ipv6(&r6, tt, 0, es, NULL); + add_route_ipv6(&r6, tt, 0, es, NULL, is_multipoint); } void @@ -1087,7 +1087,8 @@ */ static void do_ifconfig_ipv6(struct tuntap *tt, const char *ifname, int tun_mtu, - const struct env_set *es, openvpn_net_ctx_t *ctx) + const struct env_set *es, openvpn_net_ctx_t *ctx, + const bool is_multipoint) { #if !defined(TARGET_LINUX) struct argv argv = argv_new(); @@ -1205,7 +1206,7 @@ #if defined(TARGET_OPENBSD) || defined(TARGET_NETBSD) \ || defined(TARGET_DARWIN) /* and, hooray, we explicitly need to add a route... */ - add_route_connected_v6_net(tt, es); + add_route_connected_v6_net(tt, es, is_multipoint); #endif #elif defined(TARGET_AIX) argv_printf(&argv, "%s %s inet6 %s/%d mtu %d up", IFCONFIG_PATH, ifname, @@ -1231,7 +1232,7 @@ do_address_service(true, AF_INET6, tt); if (tt->type == DEV_TYPE_TUN) { - add_route_connected_v6_net(tt, es); + add_route_connected_v6_net(tt, es, is_multipoint); } do_dns_service(true, AF_INET6, tt); do_set_mtu_service(tt, AF_INET6, tun_mtu); @@ -1259,7 +1260,7 @@ netsh_command(&argv, 4, M_FATAL); if (tt->type == DEV_TYPE_TUN) { - add_route_connected_v6_net(tt, es); + add_route_connected_v6_net(tt, es, is_multipoint); } /* set ipv6 dns servers if any are specified */ netsh_set_dns6_servers(tt->options.dns6, tt->options.dns6_len, tt->adapter_index); @@ -1291,7 +1292,7 @@ */ static void do_ifconfig_ipv4(struct tuntap *tt, const char *ifname, int tun_mtu, - const struct env_set *es, openvpn_net_ctx_t *ctx) + const struct env_set *es, openvpn_net_ctx_t *ctx, const bool is_multipoint) { #if !defined(_WIN32) && !defined(TARGET_ANDROID) /* @@ -1415,7 +1416,7 @@ r.netmask = tt->remote_netmask; r.gateway = tt->local; r.metric = 0; - add_route(&r, tt, 0, NULL, es, NULL); + add_route(&r, tt, 0, NULL, es, NULL, is_multipoint); } #elif defined(TARGET_OPENBSD) @@ -1462,7 +1463,7 @@ r.network = tt->local & tt->remote_netmask; r.netmask = tt->remote_netmask; r.gateway = remote_end; - add_route(&r, tt, 0, NULL, es, NULL); + add_route(&r, tt, 0, NULL, es, NULL, is_multipoint); } #elif defined(TARGET_NETBSD) @@ -1504,7 +1505,7 @@ r.network = tt->local & tt->remote_netmask; r.netmask = tt->remote_netmask; r.gateway = remote_end; - add_route(&r, tt, 0, NULL, es, NULL); + add_route(&r, tt, 0, NULL, es, NULL, is_multipoint); } #elif defined(TARGET_DARWIN) @@ -1554,7 +1555,7 @@ r.network = tt->local & tt->remote_netmask; r.netmask = tt->remote_netmask; r.gateway = tt->local; - add_route(&r, tt, 0, NULL, es, NULL); + add_route(&r, tt, 0, NULL, es, NULL, is_multipoint); } #elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) @@ -1648,7 +1649,7 @@ /* execute the ifconfig command through the shell */ void do_ifconfig(struct tuntap *tt, const char *ifname, int tun_mtu, - const struct env_set *es, openvpn_net_ctx_t *ctx) + const struct env_set *es, openvpn_net_ctx_t *ctx, const bool is_multipoint) { msg(D_LOW, "do_ifconfig, ipv4=%d, ipv6=%d", tt->did_ifconfig_setup, tt->did_ifconfig_ipv6_setup); @@ -1668,12 +1669,12 @@ if (tt->did_ifconfig_setup) { - do_ifconfig_ipv4(tt, ifname, tun_mtu, es, ctx); + do_ifconfig_ipv4(tt, ifname, tun_mtu, es, ctx, is_multipoint); } if (tt->did_ifconfig_ipv6_setup) { - do_ifconfig_ipv6(tt, ifname, tun_mtu, es, ctx); + do_ifconfig_ipv6(tt, ifname, tun_mtu, es, ctx, is_multipoint); } /* release resources potentially allocated during interface setup */ diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index 33b9552..f1ad9cf 100644 --- a/src/openvpn/tun.h +++ b/src/openvpn/tun.h @@ -319,7 +319,7 @@ * @param ctx the networking API opaque context */ void do_ifconfig(struct tuntap *tt, const char *ifname, int tun_mtu, - const struct env_set *es, openvpn_net_ctx_t *ctx); + const struct env_set *es, openvpn_net_ctx_t *ctx, const bool is_multipoint); /** * undo_ifconfig - undo configuration of the tunnel interface @@ -754,6 +754,7 @@ } const char *tun_stat(const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc); + bool tun_name_is_fixed(const char *dev); static inline bool