From patchwork Sun Jun 22 11:03:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 4288 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:bd0c:b0:668:42a9:9967 with SMTP id gi12csp1930345mab; Sun, 22 Jun 2025 04:03:30 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCWo1Ir3eW52qaFbj88xMWAwrNiWnYUhDub7pJ3y8NzPbgm3rgBVq4nQln+QQjf6H51d23+aYSRYujw=@openvpn.net X-Google-Smtp-Source: AGHT+IEHXW3V9eF5Sf5VQ2wUvRfhmzNnf3nyp/yh1WEUssBarEV+alaLzBK2QzT51vPFtdDTJxbu X-Received: by 2002:a05:6808:1793:b0:40a:72b7:d545 with SMTP id 5614622812f47-40ac6f49aa0mr6370746b6e.38.1750590210263; Sun, 22 Jun 2025 04:03:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1750590210; cv=none; d=google.com; s=arc-20240605; b=Zg3wvOowPxHvjTaEvq/oUg4nKyu2C/Z6P+gkmZb2Xt6J0xLWIWpCSVwGMjkuu2xBpq 9y4+jSOQRtlfbDgDpHaeXcicvcrnxdElkLJGryVlGi7rHAWAgPcs9OO8t4Gq6c7lxoII 2gEeIkg2fSugVmx3U8EWCHuMKb7FVDYijsojb+54L8VMNNMLeP2ty9U9oo00T9hrH0NQ ziUvAyOInNjAQiw5w6KYHC8DogJDIefZ6z+NEbRY+dmrSOIHf3ImRV8A8dwcSVwx07BP rvfGN1OLkd8XhtquPfW5DlqDLtQ0pLYM+icRrjETjzLZVo21UdOPsLJiDgO3oo5jIkH2 OrWA== 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:dkim-signature; bh=G18L9m7nh+wlxYxmTZGg2Wx1Oda8ZimPB294TiStqio=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=iLraQQzxnzYwV7BU+BUVvnCx9j8opJBa2eKG/VHTSbmsB8JidjgEjh09Q/sC9VjTMS Xq1uQsnePZkeba9V67cqpsNt7fZDTdQG6JTYKKUQR4+mQFG3P7wZL2GNS0ELcYyUa1cs K8gV3VD14ERthOf52SNXD/QFYB4T19+7CnPQP7V+br7mwkXFVmiAvdgEYb4KmMCLpqN9 HJfC/8nW99i6nUkD5Gdkr3fQrspBEuUJyGuehdsVWkWuFt//Yu7wCGqYHP2VzKpjZnLs MQVArTNRJNzF+yF8wsUKWm2iDpZIRHRGxFHtwruCRy0x6T7m64iBKPVn33rB2szFi6vh kEdQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=B53xshyN; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=fjdJn9N4; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=OCVZbdZX; 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 5614622812f47-40ac6d64a27si3541323b6e.239.2025.06.22.04.03.29 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sun, 22 Jun 2025 04:03:29 -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=pass header.i=@lists.sourceforge.net header.s=beta header.b=B53xshyN; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=fjdJn9N4; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=OCVZbdZX; 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 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:References:In-Reply-To:Message-ID:Date:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=G18L9m7nh+wlxYxmTZGg2Wx1Oda8ZimPB294TiStqio=; b=B53xshyNH3Y+9tQiGDZTwxsSv5 STkr8PkP3dpILhwYnnrXnhupZ0rY1SlxsUci2BfDHZzOdcw2ANGSAkuI2uRuMjG2V8t8FfUsMEtCj 8fWopI766Q43riJCUQ2PzG6shUjTfuRUgRHpmiIfl1/N5yxuZLTBuCkuDMYYp9lFPjnU=; 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 1uTITu-0000TY-Qr; Sun, 22 Jun 2025 11:03:26 +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 1uTITs-0000TK-So for openvpn-devel@lists.sourceforge.net; Sun, 22 Jun 2025 11:03:24 +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=zrWz6pZqeI4o9JWjA3SCsqDjmCTgiueDGRTXThfmwxg=; b=fjdJn9N4QBvwggyc8VN2pgV7hX sihqaJuoyxNW5AVKsJzKOMMaIJUaLEBUNtTtkFkQHA2xBr3+82cTUdH8iSY8NEdUlKM4SJ4SvnsNT O3sNe/kUcDIPqeA5DWpUbK8iZDJF/AhSFeRO1rfNJAGV84zFwaD9hhfG1swA+SwadMsc=; 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=zrWz6pZqeI4o9JWjA3SCsqDjmCTgiueDGRTXThfmwxg=; b=OCVZbdZXzioj5vi0iPblcMOS0h lyP6jO8NDgVoI7RdKwc9s1cRrt2pZq0BK4c58A/+GMTrxnAPNEgqdgnHKGGpkls705dRvRjLVyO8v CwXKNgQv91mlCrtzMXK6+3AyR9p14dPX4k0O/GEwTijC1OOoXf8LQOLIpLcpLSAcgacg=; Received: from [193.149.48.143] (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 1uTITr-0001QP-I1 for openvpn-devel@lists.sourceforge.net; Sun, 22 Jun 2025 11:03:24 +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 55MB3B7m001165 for ; Sun, 22 Jun 2025 13:03:11 +0200 Received: (from gert@localhost) by blue.greenie.muc.de (8.17.1.9/8.17.1.9/Submit) id 55MB3B0P001164 for openvpn-devel@lists.sourceforge.net; Sun, 22 Jun 2025 13:03:11 +0200 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Sun, 22 Jun 2025 13:03:05 +0200 Message-ID: <20250622110311.1140-1-gert@greenie.muc.de> X-Mailer: git-send-email 2.49.0 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-2.hosts.colo.sdot.me", 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: Gianmarco De Gregori Add the ability for users to specify a custom routing table where routes should be installed in. As of now routes are always installed in the main routing table of the operating system, however, with [...] Content analysis details: (1.3 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-Headers-End: 1uTITr-0001QP-I1 Subject: [Openvpn-devel] [PATCH v9] Route: add support for user defined routing table 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?1793423908084889484?= X-GMAIL-MSGID: =?utf-8?q?1835626880461880239?= From: Gianmarco De Gregori Add the ability for users to specify a custom routing table where routes should be installed in. As of now routes are always installed in the main routing table of the operating system, however, with the new --route-table option it is possibile to specify the ID of the default routing table to be used by --route(-ipv6). Please note: this feature is currently supported only by Linux/SITNL. Support for other platforms should be added in related backends. Trac #1399 Change-Id: I3e4ebef484d2a04a383a65ede5617ee98bf218a7 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/+/524 This mail reflects revision 9 of this Change. Acked-by according to Gerrit (reflected above): Gert Doering diff --git a/doc/man-sections/vpn-network-options.rst b/doc/man-sections/vpn-network-options.rst index 40b8c19..4a64e8d 100644 --- a/doc/man-sections/vpn-network-options.rst +++ b/doc/man-sections/vpn-network-options.rst @@ -389,6 +389,14 @@ Like ``--redirect-gateway``, but omit actually changing the default gateway. Useful when pushing private subnets. +--route-table id + Specify a default table id for use with --route. + By default, OpenVPN installs routes in the main routing + table of the operating system, but with this option, + a user defined routing table can be used instead. + + (Supported on Linux only, on other platforms this is a no-op). + --route args Add route to routing table after connection is established. Multiple routes can be specified. Routes will be automatically torn down in @@ -463,14 +471,20 @@ Setup IPv6 routing in the system to send the specified IPv6 network into OpenVPN's *tun*. - Valid syntax: + Valid syntaxes: :: - route-ipv6 ipv6addr/bits [gateway] [metric] + route-ipv6 ipv6addr/bits + route-ipv6 ipv6addr/bits gateway + route-ipv6 ipv6addr/bits gateway metric - The gateway parameter is only used for IPv6 routes across *tap* devices, - and if missing, the ``ipv6remote`` field from ``--ifconfig-ipv6`` or - ``--route-ipv6-gateway`` is used. + ``gateway`` + Only used for IPv6 routes across *tap* devices, + and if missing, the ``ipv6remote`` field from ``--ifconfig-ipv6`` or + ``--route-ipv6-gateway`` is used. + + ``metric`` + default taken from ``--route-metric`` if set, otherwise :code:`0`. --route-gateway arg Specify a default *gateway* for use with ``--route``. diff --git a/src/openvpn/helper.c b/src/openvpn/helper.c index 8761826..7cef9db 100644 --- a/src/openvpn/helper.c +++ b/src/openvpn/helper.c @@ -118,7 +118,8 @@ print_in_addr_t(network, 0, &o->gc), print_in_addr_t(netmask, 0, &o->gc), NULL, - NULL); + NULL, + o->route_default_table_id); } static void diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 7d4eb85..77747a2 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -1566,7 +1566,7 @@ { add_route_ipv6_to_option_list( options->routes_ipv6, string_alloc(opt_list[i], options->routes_ipv6->gc), - NULL, NULL ); + NULL, NULL, options->route_default_table_id); } } diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 3cf8c2a..7e26069 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -213,6 +213,10 @@ " pass --ifconfig parms by environment to scripts.\n" "--ifconfig-nowarn : Don't warn if the --ifconfig option on this side of the\n" " connection doesn't match the remote side.\n" +#ifdef TARGET_LINUX + "--route-table table_id : Specify a custom routing table for use with --route(-ipv6).\n" + " If not specified, the id of the default routing table will be used.\n" +#endif "--route network [netmask] [gateway] [metric] :\n" " Add route to routing table after connection\n" " is established. Multiple routes can be specified.\n" @@ -829,6 +833,7 @@ o->ce.mssfix = 0; o->ce.mssfix_default = true; o->ce.mssfix_encap = true; + o->route_default_table_id = 0; o->route_delay_window = 30; o->resolve_retry_seconds = RESOLV_RETRY_INFINITE; o->resolve_in_advance = false; @@ -1799,6 +1804,7 @@ SHOW_STR(route_script); SHOW_STR(route_default_gateway); SHOW_INT(route_default_metric); + SHOW_INT(route_default_table_id); SHOW_BOOL(route_noexec); SHOW_INT(route_delay); SHOW_INT(route_delay_window); @@ -7064,6 +7070,14 @@ cnol_check_alloc(options); add_client_nat_to_option_list(options->client_nat, p[1], p[2], p[3], p[4], msglevel); } + else if (streq(p[0], "route-table") && p[1] && !p[2]) + { +#ifndef ENABLE_SITNL + msg(M_WARN, "NOTE: --route-table is supported only on Linux when SITNL is built-in"); +#endif + VERIFY_PERMISSION(OPT_P_ROUTE_TABLE); + options->route_default_table_id = positive_atoi(p[1], msglevel); + } else if (streq(p[0], "route") && p[1] && !p[5]) { VERIFY_PERMISSION(OPT_P_ROUTE); @@ -7085,8 +7099,9 @@ msg(msglevel, "route parameter gateway '%s' must be a valid address", p[3]); goto err; } + /* p[4] is metric, if specified */ } - add_route_to_option_list(options->routes, p[1], p[2], p[3], p[4]); + add_route_to_option_list(options->routes, p[1], p[2], p[3], p[4], options->route_default_table_id); } else if (streq(p[0], "route-ipv6") && p[1] && !p[4]) { @@ -7104,9 +7119,9 @@ msg(msglevel, "route-ipv6 parameter gateway '%s' must be a valid address", p[2]); goto err; } - /* p[3] is metric, if present */ + /* p[3] is metric, if specified */ } - add_route_ipv6_to_option_list(options->routes_ipv6, p[1], p[2], p[3]); + add_route_ipv6_to_option_list(options->routes_ipv6, p[1], p[2], p[3], options->route_default_table_id); } else if (streq(p[0], "max-routes") && !p[2]) { diff --git a/src/openvpn/options.h b/src/openvpn/options.h index 46ec32b..56e85d7 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -427,6 +427,7 @@ const char *route_predown_script; const char *route_default_gateway; const char *route_ipv6_default_gateway; + int route_default_table_id; int route_default_metric; bool route_noexec; int route_delay; @@ -758,6 +759,7 @@ #define OPT_P_PEER_ID (1<<28) #define OPT_P_INLINE (1<<29) #define OPT_P_PUSH_MTU (1<<30) +#define OPT_P_ROUTE_TABLE (1<<31) #define OPT_P_DEFAULT (~(OPT_P_INSTANCE|OPT_P_PULL_MODE)) diff --git a/src/openvpn/route.c b/src/openvpn/route.c index bd79a28..156262a 100644 --- a/src/openvpn/route.c +++ b/src/openvpn/route.c @@ -330,13 +330,11 @@ r->option = ro; /* network */ - if (!is_route_parm_defined(ro->network)) { goto fail; } - /* get_special_addr replaces specialaddr with a special ip addr * like gw. getaddrinfo is called to convert a a addrinfo struct */ @@ -442,6 +440,9 @@ r->flags |= RT_DEFINED; + /* routing table id */ + r->table_id = ro->table_id; + return true; fail: @@ -498,6 +499,9 @@ r6->flags |= RT_DEFINED; + /* routing table id */ + r6->table_id = r6o->table_id; + return true; fail: @@ -511,7 +515,8 @@ const char *network, const char *netmask, const char *gateway, - const char *metric) + const char *metric, + int table_id) { struct route_option *ro; ALLOC_OBJ_GC(ro, struct route_option, l->gc); @@ -519,6 +524,7 @@ ro->netmask = netmask; ro->gateway = gateway; ro->metric = metric; + ro->table_id = table_id; ro->next = l->routes; l->routes = ro; @@ -528,13 +534,15 @@ add_route_ipv6_to_option_list(struct route_ipv6_option_list *l, const char *prefix, const char *gateway, - const char *metric) + const char *metric, + int table_id) { struct route_ipv6_option *ro; ALLOC_OBJ_GC(ro, struct route_ipv6_option, l->gc); ro->prefix = prefix; ro->gateway = gateway; ro->metric = metric; + ro->table_id = table_id; ro->next = l->routes_ipv6; l->routes_ipv6 = ro; } @@ -1610,9 +1618,10 @@ metric = r->metric; } + status = RTA_SUCCESS; int ret = net_route_v4_add(ctx, &r->network, netmask_to_netbits2(r->netmask), - &r->gateway, iface, 0, metric); + &r->gateway, iface, r->table_id, metric); if (ret == -EEXIST) { msg(D_ROUTE, "NOTE: Linux route add command failed because route exists"); @@ -2007,7 +2016,7 @@ status = RTA_SUCCESS; int ret = net_route_v6_add(ctx, &r6->network, r6->netbits, gateway_needed ? &r6->gateway : NULL, - device, 0, metric); + device, r6->table_id, metric); if (ret == -EEXIST) { msg(D_ROUTE, "NOTE: Linux route add command failed because route exists"); @@ -2227,7 +2236,7 @@ } if (net_route_v4_del(ctx, &r->network, netmask_to_netbits2(r->netmask), - &r->gateway, NULL, 0, metric) < 0) + &r->gateway, NULL, r->table_id, metric) < 0) { msg(M_WARN, "ERROR: Linux route delete command failed"); } @@ -2452,7 +2461,7 @@ } if (net_route_v6_del(ctx, &r6->network, r6->netbits, - gateway_needed ? &r6->gateway : NULL, device, 0, + gateway_needed ? &r6->gateway : NULL, device, r6->table_id, metric) < 0) { msg(M_WARN, "ERROR: Linux route v6 delete command failed"); diff --git a/src/openvpn/route.h b/src/openvpn/route.h index aa3114c..237375c 100644 --- a/src/openvpn/route.h +++ b/src/openvpn/route.h @@ -69,6 +69,7 @@ in_addr_t remote_host; int remote_host_local; /* TLA_x value */ struct route_bypass bypass; + int table_id; int default_metric; }; @@ -77,6 +78,7 @@ const char *network; const char *netmask; const char *gateway; + int table_id; const char *metric; }; @@ -101,6 +103,7 @@ const char *prefix; /* e.g. "2001:db8:1::/64" */ const char *gateway; /* e.g. "2001:db8:0::2" */ const char *metric; /* e.g. "5" */ + int table_id; }; struct route_ipv6_option_list { @@ -119,6 +122,7 @@ in_addr_t network; in_addr_t netmask; in_addr_t gateway; + int table_id; int metric; }; @@ -129,6 +133,7 @@ unsigned int netbits; struct in6_addr gateway; int metric; + int table_id; /* gateway interface */ #ifdef _WIN32 DWORD adapter_index; /* interface or ~0 if undefined */ @@ -290,12 +295,14 @@ const char *network, const char *netmask, const char *gateway, - const char *metric); + const char *metric, + int table_id); void add_route_ipv6_to_option_list(struct route_ipv6_option_list *l, const char *prefix, const char *gateway, - const char *metric); + const char *metric, + int table_id); bool init_route_list(struct route_list *rl, const struct route_option_list *opt,