From patchwork Mon Sep 7 16:53:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladislav Grishenko X-Patchwork-Id: 1420 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director8.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id wAoDKIbyVl+tbQAAIUCqbw (envelope-from ) for ; Mon, 07 Sep 2020 22:55:02 -0400 Received: from proxy9.mail.iad3b.rsapps.net ([172.31.255.6]) by director8.mail.ord1d.rsapps.net with LMTP id gKvjJ4byVl9lVgAAfY0hYg (envelope-from ) for ; Mon, 07 Sep 2020 22:55:02 -0400 Received: from smtp30.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy9.mail.iad3b.rsapps.net with LMTPS id 8De8IIbyVl8FLQAAC4PSzw (envelope-from ) for ; Mon, 07 Sep 2020 22:55:02 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp30.gate.iad3b.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dkim=fail (signature verification failed) header.d=yandex-team.ru; dmarc=fail (p=none; dis=none) header.from=yandex-team.ru X-Suspicious-Flag: YES X-Classification-ID: b00c7562-f17e-11ea-9eb2-525400502618-1-1 Received: from [216.105.38.7] ([216.105.38.7:55494] helo=lists.sourceforge.net) by smtp30.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id AB/CC-02192-582F65F5; Mon, 07 Sep 2020 22:55:01 -0400 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1kFTla-0004v5-HW; Tue, 08 Sep 2020 02:53:54 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kFTlZ-0004us-Cr for openvpn-devel@lists.sourceforge.net; Tue, 08 Sep 2020 02:53:53 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:To: From:Sender:Reply-To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=2B+y85hEXpuEKZow9zEKJq0QMGfilmrqJXxz+ahMK2s=; b=iW8TKjBwhoHSdFTxZ3Z8U+lkMv y582+duCcJEtDR8TroQPnh+vSc4s7vToj2PS3/SUAVC1sGGivSlaV+1/TOP1axDSVfi2kCddoQfHc 6uI2AVCqlgiGNLZIVYjMwhuS3HDUw9uh7c9O6YVC3ZXTNUSfD4lGHd0IKf93cTnCldXc=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=2B+y85hEXpuEKZow9zEKJq0QMGfilmrqJXxz+ahMK2s=; b=kdcH9aSWPMBwm05s53VO72C5+X 8uyLbkEmZmfgi8fS4iU9YWrfmWH2jG/Kg3noQbYbYi9PrM43ShSXN5+rR7MWom9RRptnUM6L4e+jb Ss/CNqkkq+bWoBVXb0lkkxG/8L6sXXA1UVJMtMwlSeO4tTmPl+KmM5jLstfgdx8bFUuU=; Received: from forwardcorp1j.mail.yandex.net ([5.45.199.163]) by sfi-mx-3.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.2) id 1kFTlR-00GOsQ-NK for openvpn-devel@lists.sourceforge.net; Tue, 08 Sep 2020 02:53:53 +0000 Received: from myt5-23f0be3aa648.qloud-c.yandex.net (myt5-23f0be3aa648.qloud-c.yandex.net [IPv6:2a02:6b8:c12:3e29:0:640:23f0:be3a]) by forwardcorp1j.mail.yandex.net (Yandex) with ESMTP id D8B102E0456 for ; Tue, 8 Sep 2020 05:53:36 +0300 (MSK) Received: from myt5-70c90f7d6d7d.qloud-c.yandex.net (myt5-70c90f7d6d7d.qloud-c.yandex.net [2a02:6b8:c12:3e2c:0:640:70c9:f7d]) by myt5-23f0be3aa648.qloud-c.yandex.net (mxbackcorp/Yandex) with ESMTP id fA3WxFMlGT-raw0VUVo; Tue, 08 Sep 2020 05:53:36 +0300 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1599533616; bh=2B+y85hEXpuEKZow9zEKJq0QMGfilmrqJXxz+ahMK2s=; h=In-Reply-To:Message-Id:References:Date:Subject:To:From; b=tXzKpCpUPn98JuoGehle9GcfMb5gzfi0AbNAceTxOTvR6zA3esCEpmv/W976K9ClK t+dE4utyUviawj7O3ai0xXURmhl9NH0g+AgqMo2yRp9k4ZOT5Ofr9KT44Z8ysdhp8k QT0tjYknm+uvDAS5XUMRQfCe+nGKIQVAt55KVoYQ= Received: from 178.154.189.45-vpn.dhcp.yndx.net (178.154.189.45-vpn.dhcp.yndx.net [178.154.189.45]) by myt5-70c90f7d6d7d.qloud-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id o5AlzF1PAA-raluhTdE; Tue, 08 Sep 2020 05:53:36 +0300 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (Client certificate not present) From: Vladislav Grishenko To: openvpn-devel@lists.sourceforge.net Date: Tue, 8 Sep 2020 07:53:30 +0500 Message-Id: <20200908025330.17364-1-themiron@yandex-team.ru> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200907151139.GA75094@greenie.muc.de> References: <20200907151139.GA75094@greenie.muc.de> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-Headers-End: 1kFTlR-00GOsQ-NK Subject: [Openvpn-devel] [PATCH v2] Fix best gateway selection over netlink 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: , MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox Netlink route request with NLM_F_DUMP flag set means to return all entries matching criteria passed in message content - matching supplied family & dst address in our case. So, gateway from the first ipv4 route was always used. On kernels earlier than 2.6.38 default routes are the last ones, so some host/net route w/o gateway is likely be returned as first, causing gateway to be invalid or empty. After refactoring in 2.6.38 kernel first routes are the default (or more specific 0.0.0.0/n), so it's gateway is usually valid, hiding the problem. Fix this behavior by requesting exact route with corresponding full prefix size, and filter dumped routes against default route /0 if dst was not set. Empty dst is not valid address, so it's handled as default route request too. If there's several default routes dumped with different metrics, the first one will be less-numbered, so we can stop w/o additional iteration for metric comparison. Tested on 5.4.0, 4.1.51 and 2.6.36 kernels. Signed-off-by: Vladislav Grishenko --- src/openvpn/networking_sitnl.c | 47 +++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/src/openvpn/networking_sitnl.c b/src/openvpn/networking_sitnl.c index 713a213a..81d52710 100644 --- a/src/openvpn/networking_sitnl.c +++ b/src/openvpn/networking_sitnl.c @@ -90,7 +90,7 @@ struct sitnl_route_req { char buf[256]; }; -typedef int (*sitnl_parse_reply_cb)(struct nlmsghdr *msg, void *arg); +typedef int (*sitnl_parse_reply_cb)(struct nlmsghdr *req, struct nlmsghdr *msg, void *arg); /** * Object returned by route request operation @@ -345,6 +345,13 @@ sitnl_send(struct nlmsghdr *payload, pid_t peer, unsigned int groups, * continue; * } */ + + if (h->nlmsg_type == NLMSG_DONE) + { + ret = 0; + goto out; + } + if (h->nlmsg_type == NLMSG_ERROR) { err = (struct nlmsgerr *)NLMSG_DATA(h); @@ -360,7 +367,11 @@ sitnl_send(struct nlmsghdr *payload, pid_t peer, unsigned int groups, ret = 0; if (cb) { - ret = cb(h, arg_cb); + int r = cb(payload, h, arg_cb); + if (r <= 0) + { + ret = r; + } } } else @@ -375,8 +386,12 @@ sitnl_send(struct nlmsghdr *payload, pid_t peer, unsigned int groups, if (cb) { - ret = cb(h, arg_cb); - goto out; + int r = cb(payload, h, arg_cb); + if (r <= 0) + { + ret = r; + goto out; + } } else { @@ -413,14 +428,21 @@ typedef struct { } route_res_t; static int -sitnl_route_save(struct nlmsghdr *n, void *arg) +sitnl_route_save(struct nlmsghdr *req, struct nlmsghdr *n, void *arg) { route_res_t *res = arg; + struct rtmsg *q = NLMSG_DATA(req); struct rtmsg *r = NLMSG_DATA(n); struct rtattr *rta = RTM_RTA(r); int len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)); unsigned int ifindex = 0; + /* if dumped, filter out non-default routes */ + if (q->rtm_dst_len == 0 && r->rtm_dst_len) + { + return 1; + } + while (RTA_OK(rta, len)) { switch (rta->rta_type) @@ -477,11 +499,24 @@ sitnl_route_best_gw(sa_family_t af_family, const inet_address_t *dst, { case AF_INET: res.addr_size = sizeof(in_addr_t); - req.n.nlmsg_flags |= NLM_F_DUMP; + /* + * kernel can't return 0.0.0.0/32 host route, therefore + * need to dump all the routes and filter them in cb() + */ + if (!dst || dst->ipv4 == htonl(INADDR_ANY)) + { + req.n.nlmsg_flags |= NLM_F_DUMP; + } + else + { + req.r.rtm_dst_len = 32; + } break; case AF_INET6: res.addr_size = sizeof(struct in6_addr); + /* kernel cat return 0.0.0.0/128 host route */ + req.r.rtm_dst_len = 128; break; default: