All of lore.kernel.org
 help / color / mirror / Atom feed
* IPv6: routing/forwarding/masking link-local addresses
@ 2016-03-31  9:44 Michal Kazior
  2016-04-04  8:15 ` [RFC] ipv6: allow bypassing cross-intf routing limits Michal Kazior
  0 siblings, 1 reply; 5+ messages in thread
From: Michal Kazior @ 2016-03-31  9:44 UTC (permalink / raw)
  To: Network Development, linux-wireless

Hi,

The most commonly used framing/addressing in 802.11 is 3addr. This is
how most Access Points work and Clients follow suit.

However it is impossible to put a 3addr Client interface into a bridge
because it's not possible to properly distinguish RA/TA/DA/SA
addresses.

There is 4addr framing in 802.11 (often referred to as WDS or
Repeater) but it's a loose standard and various vendors implement it
differently. For this kind of framing to work both AP and Client must
support the same flavor of the framing. Many APs don't even allow the
user to enable WDS. This makes it troublesome to extend wireless
networks without replacing AP equipment (upgrading AP software isn't
always an option).

There is already a userspace tool which solves this problem for IPv4
called relayd [1]. It forwards ARP/DHCP packets (and replaces MAC
addresses accordingly) between non-bridged interfaces and adds
additional route entries to the firewall to, effectively, act as a
bridge transparently. via routing. Compared to ARP Proxy it doesn't
require IP address configuration on local interfaces.

I'm trying to add IPv6 support for relayd. The problem is I can't get
link-local addresses to route properly.

I can easily get things like 2000::/32 to route perfectly fine but
fe80:: just won't work. Upon inspection I've noticed:

; ip link add veth0 type veth peer name veth1
; ip link set veth0 up
; ip link set veth1 up
; ip route add fe80::1 dev veth0
; ip route add 2000::1 dev veth0
; ip route get iif veth1 fe80::1
fe80::1 from :: dev veth1  metric 0
    cache  iif veth1
; ip route get iif veth1 2000::1
2000::1 from :: dev veth0  metric 0
    cache  iif veth1
; ip link del veth0

If I remove default fe80::/64 routes I get:

; ip link del veth0
; ip link add veth0 type veth peer name veth1
; ip link set veth0 up
; ip link set veth1 up
; ip route del fe80::/64 dev veth0
; ip route del fe80::/64 dev veth1
; ip route add fe80::1 dev veth0
; ip route add 2000::1 dev veth0
; ip route get iif veth1 fe80::1
unreachable fe80::1 from :: dev lo  table unspec  proto kernel  metric
4294967295  error -101 iif veth1
; ip route get iif veth1 2000::1
2000::1 from :: dev veth0  metric 0
    cache  iif veth1

The fe80:: route gets ignored completely in both cases.

My question is: can I make it work (a kernel knob I'm not aware of) or
does it require patching the kernel? Thoughts/ideas/hints?


Michał

[1]: http://git.openwrt.org/?p=project/relayd.git;a=summary

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [RFC] ipv6: allow bypassing cross-intf routing limits
  2016-03-31  9:44 IPv6: routing/forwarding/masking link-local addresses Michal Kazior
@ 2016-04-04  8:15 ` Michal Kazior
  2016-04-14 12:46   ` [PATCH] " Michal Kazior
  0 siblings, 1 reply; 5+ messages in thread
From: Michal Kazior @ 2016-04-04  8:15 UTC (permalink / raw)
  To: netdev; +Cc: Michal Kazior

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 <michal.kazior@tieto.com>
---
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;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH] ipv6: allow bypassing cross-intf routing limits
  2016-04-04  8:15 ` [RFC] ipv6: allow bypassing cross-intf routing limits Michal Kazior
@ 2016-04-14 12:46   ` Michal Kazior
  2016-04-16 22:49     ` David Miller
  0 siblings, 1 reply; 5+ messages in thread
From: Michal Kazior @ 2016-04-14 12:46 UTC (permalink / raw)
  To: netdev; +Cc: davem, Michal Kazior

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 <michal.kazior@tieto.com>
---
For more background see:

  http://www.spinics.net/lists/netdev/msg371022.html
  https://lists.openwrt.org/pipermail/openwrt-devel/2016-April/040783.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;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] ipv6: allow bypassing cross-intf routing limits
  2016-04-14 12:46   ` [PATCH] " Michal Kazior
@ 2016-04-16 22:49     ` David Miller
  2016-04-18  9:38       ` Michal Kazior
  0 siblings, 1 reply; 5+ messages in thread
From: David Miller @ 2016-04-16 22:49 UTC (permalink / raw)
  To: michal.kazior; +Cc: netdev

From: Michal Kazior <michal.kazior@tieto.com>
Date: Thu, 14 Apr 2016 14:46:28 +0200

> 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 <michal.kazior@tieto.com>

Sorry, whilst I realize your problem, I'm not going to add what is
explicitly a violation of the way link-local addresses are meant to
work and the very much intentional restrictions the RFCs place upon
them (they MUST not be routed).

I also didn't see any real discussions in response to your original
proposals, not from even one person I know is knowledgable about ipv6
and the implications your change would have, and that is extremely
troubling.

I tried to let your patches sit for several days in order to let that
kind of discussion happen, but it didn't.

So, you'll need to find another way to achieve your goals.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] ipv6: allow bypassing cross-intf routing limits
  2016-04-16 22:49     ` David Miller
@ 2016-04-18  9:38       ` Michal Kazior
  0 siblings, 0 replies; 5+ messages in thread
From: Michal Kazior @ 2016-04-18  9:38 UTC (permalink / raw)
  To: David Miller; +Cc: Network Development

On 17 April 2016 at 00:49, David Miller <davem@davemloft.net> wrote:
> From: Michal Kazior <michal.kazior@tieto.com>
> Date: Thu, 14 Apr 2016 14:46:28 +0200
>
>> 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 <michal.kazior@tieto.com>
>
> Sorry, whilst I realize your problem, I'm not going to add what is
> explicitly a violation of the way link-local addresses are meant to
> work and the very much intentional restrictions the RFCs place upon
> them (they MUST not be routed).
>
> I also didn't see any real discussions in response to your original
> proposals, not from even one person I know is knowledgable about ipv6
> and the implications your change would have, and that is extremely
> troubling.
>
> I tried to let your patches sit for several days in order to let that
> kind of discussion happen, but it didn't.

I totally understand. Thanks anyway.


> So, you'll need to find another way to achieve your goals.

Hmm.. I actually do have another idea in mind already.

I was wondering about about implementing a link device in a similar
fashion to macvlan, bridge, et al, i.e. the device would take an
interface (wlan interface in my case) as a slave and perform L2
address mangling (which should be enough to accommodate the addressing
deficiency in wireless client modes). The device would obviously need
to do some L3/L4 packet inspection and manipulation.

Would something like that be acceptable? Thoughts?


Michał

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-04-18  9:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-31  9:44 IPv6: routing/forwarding/masking link-local addresses Michal Kazior
2016-04-04  8:15 ` [RFC] ipv6: allow bypassing cross-intf routing limits Michal Kazior
2016-04-14 12:46   ` [PATCH] " Michal Kazior
2016-04-16 22:49     ` David Miller
2016-04-18  9:38       ` Michal Kazior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.