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 #if IS_ENABLED(CONFIG_IPV6)
25 #include <net/ip6_checksum.h>
28 #include "br_private.h"
30 void br_recalculate_neigh_suppress_enabled(struct net_bridge
*br
)
32 struct net_bridge_port
*p
;
33 bool neigh_suppress
= false;
35 list_for_each_entry(p
, &br
->port_list
, list
) {
36 if (p
->flags
& BR_NEIGH_SUPPRESS
) {
37 neigh_suppress
= true;
42 br
->neigh_suppress_enabled
= neigh_suppress
;
45 #if IS_ENABLED(CONFIG_INET)
46 static void br_arp_send(struct net_bridge
*br
, struct net_bridge_port
*p
,
47 struct net_device
*dev
, __be32 dest_ip
, __be32 src_ip
,
48 const unsigned char *dest_hw
,
49 const unsigned char *src_hw
,
50 const unsigned char *target_hw
,
51 __be16 vlan_proto
, u16 vlan_tci
)
53 struct net_bridge_vlan_group
*vg
;
57 netdev_dbg(dev
, "arp send dev %s dst %pI4 dst_hw %pM src %pI4 src_hw %pM\n",
58 dev
->name
, &dest_ip
, dest_hw
, &src_ip
, src_hw
);
61 arp_send(ARPOP_REPLY
, ETH_P_ARP
, dest_ip
, dev
, src_ip
,
62 dest_hw
, src_hw
, target_hw
);
66 skb
= arp_create(ARPOP_REPLY
, ETH_P_ARP
, dest_ip
, dev
, src_ip
,
67 dest_hw
, src_hw
, target_hw
);
72 vg
= nbp_vlan_group_rcu(p
);
74 vg
= br_vlan_group_rcu(br
);
75 pvid
= br_get_pvid(vg
);
76 if (pvid
== (vlan_tci
& VLAN_VID_MASK
))
80 __vlan_hwaccel_put_tag(skb
, vlan_proto
, vlan_tci
);
85 skb_reset_mac_header(skb
);
86 __skb_pull(skb
, skb_network_offset(skb
));
87 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
88 skb
->pkt_type
= PACKET_HOST
;
94 static int br_chk_addr_ip(struct net_device
*dev
, void *data
)
96 __be32 ip
= *(__be32
*)data
;
97 struct in_device
*in_dev
;
100 in_dev
= __in_dev_get_rcu(dev
);
102 addr
= inet_confirm_addr(dev_net(dev
), in_dev
, 0, ip
,
111 static bool br_is_local_ip(struct net_device
*dev
, __be32 ip
)
113 if (br_chk_addr_ip(dev
, &ip
))
116 /* check if ip is configured on upper dev */
117 if (netdev_walk_all_upper_dev_rcu(dev
, br_chk_addr_ip
, &ip
))
123 void br_do_proxy_suppress_arp(struct sk_buff
*skb
, struct net_bridge
*br
,
124 u16 vid
, struct net_bridge_port
*p
)
126 struct net_device
*dev
= br
->dev
;
127 struct net_device
*vlandev
= dev
;
133 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= false;
135 if ((dev
->flags
& IFF_NOARP
) ||
136 !pskb_may_pull(skb
, arp_hdr_len(dev
)))
141 if (parp
->ar_pro
!= htons(ETH_P_IP
) ||
142 parp
->ar_hln
!= dev
->addr_len
||
146 arpptr
= (u8
*)parp
+ sizeof(struct arphdr
);
148 arpptr
+= dev
->addr_len
; /* sha */
149 memcpy(&sip
, arpptr
, sizeof(sip
));
150 arpptr
+= sizeof(sip
);
151 arpptr
+= dev
->addr_len
; /* tha */
152 memcpy(&tip
, arpptr
, sizeof(tip
));
154 if (ipv4_is_loopback(tip
) ||
155 ipv4_is_multicast(tip
))
158 if (br
->neigh_suppress_enabled
) {
159 if (p
&& (p
->flags
& BR_NEIGH_SUPPRESS
))
161 if (ipv4_is_zeronet(sip
) || sip
== tip
) {
162 /* prevent flooding to neigh suppress ports */
163 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= true;
168 if (parp
->ar_op
!= htons(ARPOP_REQUEST
))
172 vlandev
= __vlan_find_dev_deep_rcu(br
->dev
, skb
->vlan_proto
,
178 if (br
->neigh_suppress_enabled
&& br_is_local_ip(vlandev
, tip
)) {
179 /* its our local ip, so don't proxy reply
180 * and don't forward to neigh suppress ports
182 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= true;
186 n
= neigh_lookup(&arp_tbl
, &tip
, vlandev
);
188 struct net_bridge_fdb_entry
*f
;
190 if (!(n
->nud_state
& NUD_VALID
)) {
195 f
= br_fdb_find_rcu(br
, n
->ha
, vid
);
197 bool replied
= false;
199 if ((p
&& (p
->flags
& BR_PROXYARP
)) ||
200 (f
->dst
&& (f
->dst
->flags
& (BR_PROXYARP_WIFI
|
201 BR_NEIGH_SUPPRESS
)))) {
203 br_arp_send(br
, p
, skb
->dev
, sip
, tip
,
204 sha
, n
->ha
, sha
, 0, 0);
206 br_arp_send(br
, p
, skb
->dev
, sip
, tip
,
209 skb_vlan_tag_get(skb
));
213 /* If we have replied or as long as we know the
214 * mac, indicate to arp replied
216 if (replied
|| br
->neigh_suppress_enabled
)
217 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= true;
225 #if IS_ENABLED(CONFIG_IPV6)
226 struct nd_msg
*br_is_nd_neigh_msg(struct sk_buff
*skb
, struct nd_msg
*msg
)
230 m
= skb_header_pointer(skb
, skb_network_offset(skb
) +
231 sizeof(struct ipv6hdr
), sizeof(*msg
), msg
);
235 if (m
->icmph
.icmp6_code
!= 0 ||
236 (m
->icmph
.icmp6_type
!= NDISC_NEIGHBOUR_SOLICITATION
&&
237 m
->icmph
.icmp6_type
!= NDISC_NEIGHBOUR_ADVERTISEMENT
))
243 static void br_nd_send(struct net_bridge
*br
, struct net_bridge_port
*p
,
244 struct sk_buff
*request
, struct neighbour
*n
,
245 __be16 vlan_proto
, u16 vlan_tci
, struct nd_msg
*ns
)
247 struct net_device
*dev
= request
->dev
;
248 struct net_bridge_vlan_group
*vg
;
249 struct sk_buff
*reply
;
251 struct ipv6hdr
*pip6
;
252 int na_olen
= 8; /* opt hdr + ETH_ALEN for target */
261 len
= LL_RESERVED_SPACE(dev
) + sizeof(struct ipv6hdr
) +
262 sizeof(*na
) + na_olen
+ dev
->needed_tailroom
;
264 reply
= alloc_skb(len
, GFP_ATOMIC
);
268 reply
->protocol
= htons(ETH_P_IPV6
);
270 skb_reserve(reply
, LL_RESERVED_SPACE(dev
));
271 skb_push(reply
, sizeof(struct ethhdr
));
272 skb_set_mac_header(reply
, 0);
274 daddr
= eth_hdr(request
)->h_source
;
276 /* Do we need option processing ? */
277 ns_olen
= request
->len
- (skb_network_offset(request
) +
278 sizeof(struct ipv6hdr
)) - sizeof(*ns
);
279 for (i
= 0; i
< ns_olen
- 1; i
+= (ns
->opt
[i
+ 1] << 3)) {
280 if (ns
->opt
[i
] == ND_OPT_SOURCE_LL_ADDR
) {
281 daddr
= ns
->opt
+ i
+ sizeof(struct nd_opt_hdr
);
286 /* Ethernet header */
287 ether_addr_copy(eth_hdr(reply
)->h_dest
, daddr
);
288 ether_addr_copy(eth_hdr(reply
)->h_source
, n
->ha
);
289 eth_hdr(reply
)->h_proto
= htons(ETH_P_IPV6
);
290 reply
->protocol
= htons(ETH_P_IPV6
);
292 skb_pull(reply
, sizeof(struct ethhdr
));
293 skb_set_network_header(reply
, 0);
294 skb_put(reply
, sizeof(struct ipv6hdr
));
297 pip6
= ipv6_hdr(reply
);
298 memset(pip6
, 0, sizeof(struct ipv6hdr
));
300 pip6
->priority
= ipv6_hdr(request
)->priority
;
301 pip6
->nexthdr
= IPPROTO_ICMPV6
;
302 pip6
->hop_limit
= 255;
303 pip6
->daddr
= ipv6_hdr(request
)->saddr
;
304 pip6
->saddr
= *(struct in6_addr
*)n
->primary_key
;
306 skb_pull(reply
, sizeof(struct ipv6hdr
));
307 skb_set_transport_header(reply
, 0);
309 na
= (struct nd_msg
*)skb_put(reply
, sizeof(*na
) + na_olen
);
311 /* Neighbor Advertisement */
312 memset(na
, 0, sizeof(*na
) + na_olen
);
313 na
->icmph
.icmp6_type
= NDISC_NEIGHBOUR_ADVERTISEMENT
;
314 na
->icmph
.icmp6_router
= 0; /* XXX: should be 1 ? */
315 na
->icmph
.icmp6_override
= 1;
316 na
->icmph
.icmp6_solicited
= 1;
317 na
->target
= ns
->target
;
318 ether_addr_copy(&na
->opt
[2], n
->ha
);
319 na
->opt
[0] = ND_OPT_TARGET_LL_ADDR
;
320 na
->opt
[1] = na_olen
>> 3;
322 na
->icmph
.icmp6_cksum
= csum_ipv6_magic(&pip6
->saddr
,
324 sizeof(*na
) + na_olen
,
326 csum_partial(na
, sizeof(*na
) + na_olen
, 0));
328 pip6
->payload_len
= htons(sizeof(*na
) + na_olen
);
330 skb_push(reply
, sizeof(struct ipv6hdr
));
331 skb_push(reply
, sizeof(struct ethhdr
));
333 reply
->ip_summed
= CHECKSUM_UNNECESSARY
;
336 vg
= nbp_vlan_group_rcu(p
);
338 vg
= br_vlan_group_rcu(br
);
339 pvid
= br_get_pvid(vg
);
340 if (pvid
== (vlan_tci
& VLAN_VID_MASK
))
344 __vlan_hwaccel_put_tag(reply
, vlan_proto
, vlan_tci
);
346 netdev_dbg(dev
, "nd send dev %s dst %pI6 dst_hw %pM src %pI6 src_hw %pM\n",
347 dev
->name
, &pip6
->daddr
, daddr
, &pip6
->saddr
, n
->ha
);
350 dev_queue_xmit(reply
);
352 skb_reset_mac_header(reply
);
353 __skb_pull(reply
, skb_network_offset(reply
));
354 reply
->ip_summed
= CHECKSUM_UNNECESSARY
;
355 reply
->pkt_type
= PACKET_HOST
;
361 static int br_chk_addr_ip6(struct net_device
*dev
, void *data
)
363 struct in6_addr
*addr
= (struct in6_addr
*)data
;
365 if (ipv6_chk_addr(dev_net(dev
), addr
, dev
, 0))
371 static bool br_is_local_ip6(struct net_device
*dev
, struct in6_addr
*addr
)
374 if (br_chk_addr_ip6(dev
, addr
))
377 /* check if ip is configured on upper dev */
378 if (netdev_walk_all_upper_dev_rcu(dev
, br_chk_addr_ip6
, addr
))
384 void br_do_suppress_nd(struct sk_buff
*skb
, struct net_bridge
*br
,
385 u16 vid
, struct net_bridge_port
*p
, struct nd_msg
*msg
)
387 struct net_device
*dev
= br
->dev
;
388 struct net_device
*vlandev
= NULL
;
389 struct in6_addr
*saddr
, *daddr
;
390 struct ipv6hdr
*iphdr
;
393 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= false;
395 if (p
&& (p
->flags
& BR_NEIGH_SUPPRESS
))
398 if (msg
->icmph
.icmp6_type
== NDISC_NEIGHBOUR_ADVERTISEMENT
&&
399 !msg
->icmph
.icmp6_solicited
) {
400 /* prevent flooding to neigh suppress ports */
401 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= true;
405 if (msg
->icmph
.icmp6_type
!= NDISC_NEIGHBOUR_SOLICITATION
)
408 iphdr
= ipv6_hdr(skb
);
409 saddr
= &iphdr
->saddr
;
410 daddr
= &iphdr
->daddr
;
412 if (ipv6_addr_any(saddr
) || !ipv6_addr_cmp(saddr
, daddr
)) {
413 /* prevent flooding to neigh suppress ports */
414 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= true;
419 /* build neigh table lookup on the vlan device */
420 vlandev
= __vlan_find_dev_deep_rcu(br
->dev
, skb
->vlan_proto
,
428 if (br_is_local_ip6(vlandev
, &msg
->target
)) {
429 /* its our own ip, so don't proxy reply
430 * and don't forward to arp suppress ports
432 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= true;
436 n
= neigh_lookup(ipv6_stub
->nd_tbl
, &msg
->target
, vlandev
);
438 struct net_bridge_fdb_entry
*f
;
440 if (!(n
->nud_state
& NUD_VALID
)) {
445 f
= br_fdb_find_rcu(br
, n
->ha
, vid
);
447 bool replied
= false;
449 if (f
->dst
&& (f
->dst
->flags
& BR_NEIGH_SUPPRESS
)) {
451 br_nd_send(br
, p
, skb
, n
,
453 skb_vlan_tag_get(skb
), msg
);
455 br_nd_send(br
, p
, skb
, n
, 0, 0, msg
);
459 /* If we have replied or as long as we know the
460 * mac, indicate to NEIGH_SUPPRESS ports that we
463 if (replied
|| br
->neigh_suppress_enabled
)
464 BR_INPUT_SKB_CB(skb
)->proxyarp_replied
= true;