From patchwork Mon Apr 4 08:15:55 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Kazior X-Patchwork-Id: 605751 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3qdlC36prMz9sBM for ; Mon, 4 Apr 2016 18:14:39 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=tieto.com header.i=@tieto.com header.b=w+2W6EHR; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754773AbcDDIOh (ORCPT ); Mon, 4 Apr 2016 04:14:37 -0400 Received: from mail-lb0-f171.google.com ([209.85.217.171]:34303 "EHLO mail-lb0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754682AbcDDIOe (ORCPT ); Mon, 4 Apr 2016 04:14:34 -0400 Received: by mail-lb0-f171.google.com with SMTP id vo2so148738329lbb.1 for ; Mon, 04 Apr 2016 01:14:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tieto.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=fMUp5H2o8edWcJSDHGcKNFP75PsW6liXOffOdHDGiE4=; b=w+2W6EHRPRLcMw8Y6zKuGXHsrF21WP1xrNL7hp/QQr+rh4NA5B5RplZBEM/rdb+XMx RU+pO2jdliNbWCRiEKakFgEoW+wTB22RP5YFmq4mtmyQbP9EUDhJu/Cd8gJqkWj10KmQ OBUbGzD/ojUCqlXeymMlKud7m2KliVSwN7D3U= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=fMUp5H2o8edWcJSDHGcKNFP75PsW6liXOffOdHDGiE4=; b=YNJdl79qFHHSWRahqUElm3RX854IX0dIr7PFZUfhhNS2uNAuZWTWAJiElLp0620j1W raFRNnd7yu63wk0msQN6xYLmvRvAVR1H11vLpBIy0AUiijx47i6GpP40l38vGNEcfNyX ZdU9k2AVy6eX/ImvjgCZ1HaJdgN4Dkbtdn97DNfNfsYweBb8xybC+vHezPaHLqhmXIAC kVCeF2uA5s1qFPGYUSE/O4Y/fCU2QF/ufgvuI9n94vtAV7X9HtaviOn6MdUUGdozmCMm iKNtIk8c8kfV/f0gouPVh0F2z2hyOrLPlblNdDXdmOPBuv8fz/aPxkH/nbIMjOAW4396 2uLg== X-Gm-Message-State: AD7BkJJgrk6aEpN3i7Fd2dYbT5lWaHSI8ihfuAm+9VJXLqStCMHLJOzbhd8B8ZUhi4oDy0JXV54QExyzVxQQtDuubYq3WTgbX6PkR0hbLK1sstC5FnQQF5p+7h45XtNnivV1HYp7q8l9nRTtsrJJ8s15W2cG/1215FOQKFNC57aWT5p4Lqlcok9xB64B X-Received: by 10.112.205.68 with SMTP id le4mr7272509lbc.62.1459757673013; Mon, 04 Apr 2016 01:14:33 -0700 (PDT) Received: from localhost.localdomain ([91.198.246.10]) by smtp.gmail.com with ESMTPSA id a13sm4596976lfa.10.2016.04.04.01.14.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 04 Apr 2016 01:14:31 -0700 (PDT) From: Michal Kazior To: netdev@vger.kernel.org Cc: Michal Kazior Subject: [RFC] ipv6: allow bypassing cross-intf routing limits Date: Mon, 4 Apr 2016 10:15:55 +0200 Message-Id: <1459757755-25424-1-git-send-email-michal.kazior@tieto.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: References: X-DomainID: tieto.com Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org There are some use-cases to allow link-local routing for bridging purposes. One of these is allowing transparent 802.11 bridging. Due to 802.11 framing limitations many Access Points make it impossible to create bridges on Client endpoints because they can't maintain Destination/Source/Transmitter/Receiver address distinction with only 3 addresses in frame header. The default behavior, i.e. link-local traffic being non-routable, remains. The user has to explicitly enable the bypass when defining a given route. Signed-off-by: Michal Kazior --- For more background see: http://www.spinics.net/lists/netdev/msg371022.html include/uapi/linux/rtnetlink.h | 8 ++++++-- net/ipv6/ip6_output.c | 11 +++++++++-- net/ipv6/route.c | 4 ++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h index ca764b5da86d..a577eec0e56e 100644 --- a/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h @@ -424,9 +424,13 @@ enum { #define RTAX_FEATURE_SACK (1 << 1) #define RTAX_FEATURE_TIMESTAMP (1 << 2) #define RTAX_FEATURE_ALLFRAG (1 << 3) +#define RTAX_FEATURE_XFACE (1 << 4) -#define RTAX_FEATURE_MASK (RTAX_FEATURE_ECN | RTAX_FEATURE_SACK | \ - RTAX_FEATURE_TIMESTAMP | RTAX_FEATURE_ALLFRAG) +#define RTAX_FEATURE_MASK (RTAX_FEATURE_ECN | \ + RTAX_FEATURE_SACK | \ + RTAX_FEATURE_TIMESTAMP | \ + RTAX_FEATURE_ALLFRAG | \ + RTAX_FEATURE_XFACE) struct rta_session { __u8 proto; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 9428345d3a07..9abb42acb6ad 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -283,6 +283,7 @@ static int ip6_forward_proxy_check(struct sk_buff *skb) u8 nexthdr = hdr->nexthdr; __be16 frag_off; int offset; + int feat = dst_metric_raw(skb_dst(skb), RTAX_FEATURES); if (ipv6_ext_hdr(nexthdr)) { offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr, &frag_off); @@ -320,8 +321,11 @@ static int ip6_forward_proxy_check(struct sk_buff *skb) * The proxying router can't forward traffic sent to a link-local * address, so signal the sender and discard the packet. This * behavior is clarified by the MIPv6 specification. + * + * It's useful to allow an override for transparent traffic relay. */ - if (ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL) { + if ((ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL) && + !(feat & RTAX_FEATURE_XFACE)) { dst_link_failure(skb); return -1; } @@ -485,12 +489,15 @@ int ip6_forward(struct sk_buff *skb) inet_putpeer(peer); } else { int addrtype = ipv6_addr_type(&hdr->saddr); + int feat = dst_metric_raw(dst, RTAX_FEATURES); /* This check is security critical. */ if (addrtype == IPV6_ADDR_ANY || addrtype & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LOOPBACK)) goto error; - if (addrtype & IPV6_ADDR_LINKLOCAL) { + + if ((addrtype & IPV6_ADDR_LINKLOCAL) && + !(feat & RTAX_FEATURE_XFACE)) { icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0); goto error; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index ed446639219c..560c99853907 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -629,8 +629,12 @@ static inline enum rt6_nud_state rt6_check_neigh(struct rt6_info *rt) static int rt6_score_route(struct rt6_info *rt, int oif, int strict) { + int feat = dst_metric_raw(&rt->dst, RTAX_FEATURES); int m; + if (feat & RTAX_FEATURE_XFACE) + strict &= ~RT6_LOOKUP_F_IFACE; + m = rt6_check_dev(rt, oif); if (!m && (strict & RT6_LOOKUP_F_IFACE)) return RT6_NUD_FAIL_HARD;