2 * Handle bridge arp/nd proxy/suppress
4 * Copyright (C) 2017 Cumulus Networks
5 * Copyright (c) 2017 Roopa Prabhu <roopa@cumulusnetworks.com>
8 * Roopa Prabhu <roopa@cumulusnetworks.com>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
16 #include <linux/kernel.h>
17 #include <linux/netdevice.h>
18 #include <linux/etherdevice.h>
19 #include <linux/neighbour.h>
21 #include <linux/if_vlan.h>
22 #include <linux/inetdevice.h>
23 #include <net/addrconf.h>
24 #include <net/ipv6_stubs.h>
25 #if IS_ENABLED(CONFIG_IPV6)
26 #include <net/ip6_checksum.h>
29 #include "br_private.h"
31 void br_recalculate_neigh_suppress_enabled(struct net_bridge
*br
)
33 struct net_bridge_port
*p
;
34 bool neigh_suppress
= false;
36 list_for_each_entry(p
, &br
->port_list
, list
) {
37 if (p
->flags
& BR_NEIGH_SUPPRESS
) {
38 neigh_suppress
= true;
43 br_opt_toggle(br
, BROPT_NEIGH_SUPPRESS_ENABLED
, neigh_suppress
);
46 #if IS_ENABLED(CONFIG_INET)
47 static void br_arp_send(struct net_bridge
*br
, struct net_bridge_port
*p
,
48 struct net_device
*dev
, __be32 dest_ip
, __be32 src_ip
,
49 const unsigned char *dest_hw
,
50 const unsigned char *src_hw
,
51 const unsigned char *target_hw
,
52 __be16 vlan_proto
, u16 vlan_tci
)
54 struct net_bridge_vlan_group
*vg
;
58 netdev_dbg(dev
, "arp send dev %s dst %pI4 dst_hw %pM src %pI4 src_hw %pM\n",
59 dev
->name
, &dest_ip
, dest_hw
, &src_ip
, src_hw
);
62 arp_send(ARPOP_REPLY
, ETH_P_ARP
, dest_ip
, dev
, src_ip
,
63 dest_hw
, src_hw
, target_hw
);
67 skb
= arp_create(ARPOP_REPLY
, ETH_P_ARP
, dest_ip
, dev
, src_ip
,
68 dest_hw
, src_hw
, target_hw
);
73 vg
= nbp_vlan_group_rcu(p
);
75 vg
= br_vlan_group_rcu(br
);
76 pvid
= br_get_pvid(vg
);
77 if (pvid
== (vlan_tci
& VLAN_VID_MASK
))
81 __vlan_hwaccel_put_tag(skb
, vlan_proto
, vlan_tci
);
86 skb_reset_mac_header(skb
);
87 __skb_pull(skb
, skb_network_offset(skb
));
88 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
89 skb
->pkt_type
= PACKET_HOST
;
95 static int br_chk_addr_ip(struct net_device
*dev
, void *data
)
97 __be32 ip
= *(__be32
*)data
;
98 struct in_device
*in_dev
;
101 in_dev
= __in_dev_get_rcu(dev
);
103 addr
= inet_confirm_addr(dev_net(dev
), in_dev
, 0, ip
,
112 static bool br_is_local_ip(struct net_device
*dev
, __be32 ip
)
114 if (br_chk_addr_ip(dev
, &ip
))
117 /* check if ip is configured on upper dev */
118 if (netdev_walk_all_upper_dev_rcu(dev
, br_chk_addr_ip
, &ip
))
124 void br_do_proxy_suppress_arp(struct sk_buff
*skb
, struct net_bridge
*br
,
125 u16 vid
, struct net_bridge_port
*p
)
127 struct net_device
*dev
= br
->dev
;
128 struct net_device
*vlandev
= dev
;
134 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= 0;
136 if ((dev
->flags
& IFF_NOARP
) ||
137 !pskb_may_pull(skb
, arp_hdr_len(dev
)))
142 if (parp
->ar_pro
!= htons(ETH_P_IP
) ||
143 parp
->ar_hln
!= dev
->addr_len
||
147 arpptr
= (u8
*)parp
+ sizeof(struct arphdr
);
149 arpptr
+= dev
->addr_len
; /* sha */
150 memcpy(&sip
, arpptr
, sizeof(sip
));
151 arpptr
+= sizeof(sip
);
152 arpptr
+= dev
->addr_len
; /* tha */
153 memcpy(&tip
, arpptr
, sizeof(tip
));
155 if (ipv4_is_loopback(tip
) ||
156 ipv4_is_multicast(tip
))
159 if (br_opt_get(br
, BROPT_NEIGH_SUPPRESS_ENABLED
)) {
160 if (p
&& (p
->flags
& BR_NEIGH_SUPPRESS
))
162 if (ipv4_is_zeronet(sip
) || sip
== tip
) {
163 /* prevent flooding to neigh suppress ports */
164 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= 1;
169 if (parp
->ar_op
!= htons(ARPOP_REQUEST
))
173 vlandev
= __vlan_find_dev_deep_rcu(br
->dev
, skb
->vlan_proto
,
179 if (br_opt_get(br
, BROPT_NEIGH_SUPPRESS_ENABLED
) &&
180 br_is_local_ip(vlandev
, tip
)) {
181 /* its our local ip, so don't proxy reply
182 * and don't forward to neigh suppress ports
184 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= 1;
188 n
= neigh_lookup(&arp_tbl
, &tip
, vlandev
);
190 struct net_bridge_fdb_entry
*f
;
192 if (!(n
->nud_state
& NUD_VALID
)) {
197 f
= br_fdb_find_rcu(br
, n
->ha
, vid
);
199 bool replied
= false;
201 if ((p
&& (p
->flags
& BR_PROXYARP
)) ||
202 (f
->dst
&& (f
->dst
->flags
& (BR_PROXYARP_WIFI
|
203 BR_NEIGH_SUPPRESS
)))) {
205 br_arp_send(br
, p
, skb
->dev
, sip
, tip
,
206 sha
, n
->ha
, sha
, 0, 0);
208 br_arp_send(br
, p
, skb
->dev
, sip
, tip
,
211 skb_vlan_tag_get(skb
));
215 /* If we have replied or as long as we know the
216 * mac, indicate to arp replied
219 br_opt_get(br
, BROPT_NEIGH_SUPPRESS_ENABLED
))
220 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= 1;
228 #if IS_ENABLED(CONFIG_IPV6)
229 struct nd_msg
*br_is_nd_neigh_msg(struct sk_buff
*skb
, struct nd_msg
*msg
)
233 m
= skb_header_pointer(skb
, skb_network_offset(skb
) +
234 sizeof(struct ipv6hdr
), sizeof(*msg
), msg
);
238 if (m
->icmph
.icmp6_code
!= 0 ||
239 (m
->icmph
.icmp6_type
!= NDISC_NEIGHBOUR_SOLICITATION
&&
240 m
->icmph
.icmp6_type
!= NDISC_NEIGHBOUR_ADVERTISEMENT
))
246 static void br_nd_send(struct net_bridge
*br
, struct net_bridge_port
*p
,
247 struct sk_buff
*request
, struct neighbour
*n
,
248 __be16 vlan_proto
, u16 vlan_tci
, struct nd_msg
*ns
)
250 struct net_device
*dev
= request
->dev
;
251 struct net_bridge_vlan_group
*vg
;
252 struct sk_buff
*reply
;
254 struct ipv6hdr
*pip6
;
255 int na_olen
= 8; /* opt hdr + ETH_ALEN for target */
264 len
= LL_RESERVED_SPACE(dev
) + sizeof(struct ipv6hdr
) +
265 sizeof(*na
) + na_olen
+ dev
->needed_tailroom
;
267 reply
= alloc_skb(len
, GFP_ATOMIC
);
271 reply
->protocol
= htons(ETH_P_IPV6
);
273 skb_reserve(reply
, LL_RESERVED_SPACE(dev
));
274 skb_push(reply
, sizeof(struct ethhdr
));
275 skb_set_mac_header(reply
, 0);
277 daddr
= eth_hdr(request
)->h_source
;
279 /* Do we need option processing ? */
280 ns_olen
= request
->len
- (skb_network_offset(request
) +
281 sizeof(struct ipv6hdr
)) - sizeof(*ns
);
282 for (i
= 0; i
< ns_olen
- 1; i
+= (ns
->opt
[i
+ 1] << 3)) {
283 if (ns
->opt
[i
] == ND_OPT_SOURCE_LL_ADDR
) {
284 daddr
= ns
->opt
+ i
+ sizeof(struct nd_opt_hdr
);
289 /* Ethernet header */
290 ether_addr_copy(eth_hdr(reply
)->h_dest
, daddr
);
291 ether_addr_copy(eth_hdr(reply
)->h_source
, n
->ha
);
292 eth_hdr(reply
)->h_proto
= htons(ETH_P_IPV6
);
293 reply
->protocol
= htons(ETH_P_IPV6
);
295 skb_pull(reply
, sizeof(struct ethhdr
));
296 skb_set_network_header(reply
, 0);
297 skb_put(reply
, sizeof(struct ipv6hdr
));
300 pip6
= ipv6_hdr(reply
);
301 memset(pip6
, 0, sizeof(struct ipv6hdr
));
303 pip6
->priority
= ipv6_hdr(request
)->priority
;
304 pip6
->nexthdr
= IPPROTO_ICMPV6
;
305 pip6
->hop_limit
= 255;
306 pip6
->daddr
= ipv6_hdr(request
)->saddr
;
307 pip6
->saddr
= *(struct in6_addr
*)n
->primary_key
;
309 skb_pull(reply
, sizeof(struct ipv6hdr
));
310 skb_set_transport_header(reply
, 0);
312 na
= (struct nd_msg
*)skb_put(reply
, sizeof(*na
) + na_olen
);
314 /* Neighbor Advertisement */
315 memset(na
, 0, sizeof(*na
) + na_olen
);
316 na
->icmph
.icmp6_type
= NDISC_NEIGHBOUR_ADVERTISEMENT
;
317 na
->icmph
.icmp6_router
= (n
->flags
& NTF_ROUTER
) ? 1 : 0;
318 na
->icmph
.icmp6_override
= 1;
319 na
->icmph
.icmp6_solicited
= 1;
320 na
->target
= ns
->target
;
321 ether_addr_copy(&na
->opt
[2], n
->ha
);
322 na
->opt
[0] = ND_OPT_TARGET_LL_ADDR
;
323 na
->opt
[1] = na_olen
>> 3;
325 na
->icmph
.icmp6_cksum
= csum_ipv6_magic(&pip6
->saddr
,
327 sizeof(*na
) + na_olen
,
329 csum_partial(na
, sizeof(*na
) + na_olen
, 0));
331 pip6
->payload_len
= htons(sizeof(*na
) + na_olen
);
333 skb_push(reply
, sizeof(struct ipv6hdr
));
334 skb_push(reply
, sizeof(struct ethhdr
));
336 reply
->ip_summed
= CHECKSUM_UNNECESSARY
;
339 vg
= nbp_vlan_group_rcu(p
);
341 vg
= br_vlan_group_rcu(br
);
342 pvid
= br_get_pvid(vg
);
343 if (pvid
== (vlan_tci
& VLAN_VID_MASK
))
347 __vlan_hwaccel_put_tag(reply
, vlan_proto
, vlan_tci
);
349 netdev_dbg(dev
, "nd send dev %s dst %pI6 dst_hw %pM src %pI6 src_hw %pM\n",
350 dev
->name
, &pip6
->daddr
, daddr
, &pip6
->saddr
, n
->ha
);
353 dev_queue_xmit(reply
);
355 skb_reset_mac_header(reply
);
356 __skb_pull(reply
, skb_network_offset(reply
));
357 reply
->ip_summed
= CHECKSUM_UNNECESSARY
;
358 reply
->pkt_type
= PACKET_HOST
;
364 static int br_chk_addr_ip6(struct net_device
*dev
, void *data
)
366 struct in6_addr
*addr
= (struct in6_addr
*)data
;
368 if (ipv6_chk_addr(dev_net(dev
), addr
, dev
, 0))
374 static bool br_is_local_ip6(struct net_device
*dev
, struct in6_addr
*addr
)
377 if (br_chk_addr_ip6(dev
, addr
))
380 /* check if ip is configured on upper dev */
381 if (netdev_walk_all_upper_dev_rcu(dev
, br_chk_addr_ip6
, addr
))
387 void br_do_suppress_nd(struct sk_buff
*skb
, struct net_bridge
*br
,
388 u16 vid
, struct net_bridge_port
*p
, struct nd_msg
*msg
)
390 struct net_device
*dev
= br
->dev
;
391 struct net_device
*vlandev
= NULL
;
392 struct in6_addr
*saddr
, *daddr
;
393 struct ipv6hdr
*iphdr
;
396 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= 0;
398 if (p
&& (p
->flags
& BR_NEIGH_SUPPRESS
))
401 if (msg
->icmph
.icmp6_type
== NDISC_NEIGHBOUR_ADVERTISEMENT
&&
402 !msg
->icmph
.icmp6_solicited
) {
403 /* prevent flooding to neigh suppress ports */
404 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= 1;
408 if (msg
->icmph
.icmp6_type
!= NDISC_NEIGHBOUR_SOLICITATION
)
411 iphdr
= ipv6_hdr(skb
);
412 saddr
= &iphdr
->saddr
;
413 daddr
= &iphdr
->daddr
;
415 if (ipv6_addr_any(saddr
) || !ipv6_addr_cmp(saddr
, daddr
)) {
416 /* prevent flooding to neigh suppress ports */
417 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= 1;
422 /* build neigh table lookup on the vlan device */
423 vlandev
= __vlan_find_dev_deep_rcu(br
->dev
, skb
->vlan_proto
,
431 if (br_is_local_ip6(vlandev
, &msg
->target
)) {
432 /* its our own ip, so don't proxy reply
433 * and don't forward to arp suppress ports
435 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= 1;
439 n
= neigh_lookup(ipv6_stub
->nd_tbl
, &msg
->target
, vlandev
);
441 struct net_bridge_fdb_entry
*f
;
443 if (!(n
->nud_state
& NUD_VALID
)) {
448 f
= br_fdb_find_rcu(br
, n
->ha
, vid
);
450 bool replied
= false;
452 if (f
->dst
&& (f
->dst
->flags
& BR_NEIGH_SUPPRESS
)) {
454 br_nd_send(br
, p
, skb
, n
,
456 skb_vlan_tag_get(skb
), msg
);
458 br_nd_send(br
, p
, skb
, n
, 0, 0, msg
);
462 /* If we have replied or as long as we know the
463 * mac, indicate to NEIGH_SUPPRESS ports that we
467 br_opt_get(br
, BROPT_NEIGH_SUPPRESS_ENABLED
))
468 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= 1;