.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Handle incoming frames |
---|
3 | 4 | * Linux ethernet bridge |
---|
4 | 5 | * |
---|
5 | 6 | * Authors: |
---|
6 | 7 | * Lennert Buytenhek <buytenh@gnu.org> |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or |
---|
9 | | - * modify it under the terms of the GNU General Public License |
---|
10 | | - * as published by the Free Software Foundation; either version |
---|
11 | | - * 2 of the License, or (at your option) any later version. |
---|
12 | 8 | */ |
---|
13 | 9 | |
---|
14 | 10 | #include <linux/slab.h> |
---|
.. | .. |
---|
16 | 12 | #include <linux/netdevice.h> |
---|
17 | 13 | #include <linux/etherdevice.h> |
---|
18 | 14 | #include <linux/netfilter_bridge.h> |
---|
| 15 | +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE |
---|
| 16 | +#include <net/netfilter/nf_queue.h> |
---|
| 17 | +#endif |
---|
19 | 18 | #include <linux/neighbour.h> |
---|
20 | 19 | #include <net/arp.h> |
---|
| 20 | +#include <net/dsa.h> |
---|
21 | 21 | #include <linux/export.h> |
---|
22 | 22 | #include <linux/rculist.h> |
---|
23 | 23 | #include "br_private.h" |
---|
24 | 24 | #include "br_private_tunnel.h" |
---|
25 | | - |
---|
26 | | -/* Hook for brouter */ |
---|
27 | | -br_should_route_hook_t __rcu *br_should_route_hook __read_mostly; |
---|
28 | | -EXPORT_SYMBOL(br_should_route_hook); |
---|
29 | 25 | |
---|
30 | 26 | static int |
---|
31 | 27 | br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb) |
---|
.. | .. |
---|
47 | 43 | u64_stats_update_end(&brstats->syncp); |
---|
48 | 44 | |
---|
49 | 45 | vg = br_vlan_group_rcu(br); |
---|
| 46 | + |
---|
| 47 | + /* Reset the offload_fwd_mark because there could be a stacked |
---|
| 48 | + * bridge above, and it should not think this bridge it doing |
---|
| 49 | + * that bridge's work forwarding out its ports. |
---|
| 50 | + */ |
---|
| 51 | + br_switchdev_frame_unmark(skb); |
---|
| 52 | + |
---|
50 | 53 | /* Bridge is just like any other port. Make sure the |
---|
51 | 54 | * packet is allowed except in promisc modue when someone |
---|
52 | 55 | * may be running packet capture. |
---|
.. | .. |
---|
81 | 84 | bool local_rcv, mcast_hit = false; |
---|
82 | 85 | struct net_bridge *br; |
---|
83 | 86 | u16 vid = 0; |
---|
| 87 | + u8 state; |
---|
84 | 88 | |
---|
85 | 89 | if (!p || p->state == BR_STATE_DISABLED) |
---|
86 | 90 | goto drop; |
---|
87 | 91 | |
---|
88 | | - if (!br_allowed_ingress(p->br, nbp_vlan_group_rcu(p), skb, &vid)) |
---|
| 92 | + state = p->state; |
---|
| 93 | + if (!br_allowed_ingress(p->br, nbp_vlan_group_rcu(p), skb, &vid, |
---|
| 94 | + &state)) |
---|
89 | 95 | goto out; |
---|
90 | 96 | |
---|
91 | 97 | nbp_switchdev_frame_mark(p, skb); |
---|
.. | .. |
---|
93 | 99 | /* insert into forwarding database after filtering to avoid spoofing */ |
---|
94 | 100 | br = p->br; |
---|
95 | 101 | if (p->flags & BR_LEARNING) |
---|
96 | | - br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false); |
---|
| 102 | + br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, 0); |
---|
97 | 103 | |
---|
98 | 104 | local_rcv = !!(br->dev->flags & IFF_PROMISC); |
---|
99 | 105 | if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) { |
---|
.. | .. |
---|
108 | 114 | } |
---|
109 | 115 | } |
---|
110 | 116 | |
---|
111 | | - if (p->state == BR_STATE_LEARNING) |
---|
| 117 | + if (state == BR_STATE_LEARNING) |
---|
112 | 118 | goto drop; |
---|
113 | 119 | |
---|
114 | 120 | BR_INPUT_SKB_CB(skb)->brdev = br->dev; |
---|
.. | .. |
---|
120 | 126 | br_do_proxy_suppress_arp(skb, br, vid, p); |
---|
121 | 127 | } else if (IS_ENABLED(CONFIG_IPV6) && |
---|
122 | 128 | skb->protocol == htons(ETH_P_IPV6) && |
---|
123 | | - br->neigh_suppress_enabled && |
---|
| 129 | + br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED) && |
---|
124 | 130 | pskb_may_pull(skb, sizeof(struct ipv6hdr) + |
---|
125 | 131 | sizeof(struct nd_msg)) && |
---|
126 | 132 | ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) { |
---|
.. | .. |
---|
156 | 162 | if (dst) { |
---|
157 | 163 | unsigned long now = jiffies; |
---|
158 | 164 | |
---|
159 | | - if (dst->is_local) |
---|
| 165 | + if (test_bit(BR_FDB_LOCAL, &dst->flags)) |
---|
160 | 166 | return br_pass_frame_up(skb); |
---|
161 | 167 | |
---|
162 | 168 | if (now != dst->used) |
---|
.. | .. |
---|
186 | 192 | u16 vid = 0; |
---|
187 | 193 | |
---|
188 | 194 | /* check if vlan is allowed, to avoid spoofing */ |
---|
189 | | - if (p->flags & BR_LEARNING && br_should_learn(p, skb, &vid)) |
---|
190 | | - br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false); |
---|
| 195 | + if ((p->flags & BR_LEARNING) && |
---|
| 196 | + nbp_state_should_learn(p) && |
---|
| 197 | + !br_opt_get(p->br, BROPT_NO_LL_LEARN) && |
---|
| 198 | + br_should_learn(p, skb, &vid)) |
---|
| 199 | + br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, 0); |
---|
191 | 200 | } |
---|
192 | 201 | |
---|
193 | 202 | /* note: already called with rcu_read_lock */ |
---|
.. | .. |
---|
199 | 208 | return 1; |
---|
200 | 209 | } |
---|
201 | 210 | |
---|
| 211 | +static int nf_hook_bridge_pre(struct sk_buff *skb, struct sk_buff **pskb) |
---|
| 212 | +{ |
---|
| 213 | +#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE |
---|
| 214 | + struct nf_hook_entries *e = NULL; |
---|
| 215 | + struct nf_hook_state state; |
---|
| 216 | + unsigned int verdict, i; |
---|
| 217 | + struct net *net; |
---|
| 218 | + int ret; |
---|
| 219 | + |
---|
| 220 | + net = dev_net(skb->dev); |
---|
| 221 | +#ifdef HAVE_JUMP_LABEL |
---|
| 222 | + if (!static_key_false(&nf_hooks_needed[NFPROTO_BRIDGE][NF_BR_PRE_ROUTING])) |
---|
| 223 | + goto frame_finish; |
---|
| 224 | +#endif |
---|
| 225 | + |
---|
| 226 | + e = rcu_dereference(net->nf.hooks_bridge[NF_BR_PRE_ROUTING]); |
---|
| 227 | + if (!e) |
---|
| 228 | + goto frame_finish; |
---|
| 229 | + |
---|
| 230 | + nf_hook_state_init(&state, NF_BR_PRE_ROUTING, |
---|
| 231 | + NFPROTO_BRIDGE, skb->dev, NULL, NULL, |
---|
| 232 | + net, br_handle_frame_finish); |
---|
| 233 | + |
---|
| 234 | + for (i = 0; i < e->num_hook_entries; i++) { |
---|
| 235 | + verdict = nf_hook_entry_hookfn(&e->hooks[i], skb, &state); |
---|
| 236 | + switch (verdict & NF_VERDICT_MASK) { |
---|
| 237 | + case NF_ACCEPT: |
---|
| 238 | + if (BR_INPUT_SKB_CB(skb)->br_netfilter_broute) { |
---|
| 239 | + *pskb = skb; |
---|
| 240 | + return RX_HANDLER_PASS; |
---|
| 241 | + } |
---|
| 242 | + break; |
---|
| 243 | + case NF_DROP: |
---|
| 244 | + kfree_skb(skb); |
---|
| 245 | + return RX_HANDLER_CONSUMED; |
---|
| 246 | + case NF_QUEUE: |
---|
| 247 | + ret = nf_queue(skb, &state, i, verdict); |
---|
| 248 | + if (ret == 1) |
---|
| 249 | + continue; |
---|
| 250 | + return RX_HANDLER_CONSUMED; |
---|
| 251 | + default: /* STOLEN */ |
---|
| 252 | + return RX_HANDLER_CONSUMED; |
---|
| 253 | + } |
---|
| 254 | + } |
---|
| 255 | +frame_finish: |
---|
| 256 | + net = dev_net(skb->dev); |
---|
| 257 | + br_handle_frame_finish(net, NULL, skb); |
---|
| 258 | +#else |
---|
| 259 | + br_handle_frame_finish(dev_net(skb->dev), NULL, skb); |
---|
| 260 | +#endif |
---|
| 261 | + return RX_HANDLER_CONSUMED; |
---|
| 262 | +} |
---|
| 263 | + |
---|
202 | 264 | /* |
---|
203 | 265 | * Return NULL if skb is handled |
---|
204 | 266 | * note: already called with rcu_read_lock |
---|
205 | 267 | */ |
---|
206 | | -rx_handler_result_t br_handle_frame(struct sk_buff **pskb) |
---|
| 268 | +static rx_handler_result_t br_handle_frame(struct sk_buff **pskb) |
---|
207 | 269 | { |
---|
208 | 270 | struct net_bridge_port *p; |
---|
209 | 271 | struct sk_buff *skb = *pskb; |
---|
210 | 272 | const unsigned char *dest = eth_hdr(skb)->h_dest; |
---|
211 | | - br_should_route_hook_t *rhook; |
---|
212 | 273 | |
---|
213 | 274 | if (unlikely(skb->pkt_type == PACKET_LOOPBACK)) |
---|
214 | 275 | return RX_HANDLER_PASS; |
---|
.. | .. |
---|
219 | 280 | skb = skb_share_check(skb, GFP_ATOMIC); |
---|
220 | 281 | if (!skb) |
---|
221 | 282 | return RX_HANDLER_CONSUMED; |
---|
| 283 | + |
---|
| 284 | + memset(skb->cb, 0, sizeof(struct br_input_skb_cb)); |
---|
222 | 285 | |
---|
223 | 286 | p = br_port_get_rcu(skb->dev); |
---|
224 | 287 | if (p->flags & BR_VLAN_TUNNEL) { |
---|
.. | .. |
---|
287 | 350 | } |
---|
288 | 351 | } |
---|
289 | 352 | |
---|
| 353 | + if (unlikely(br_mrp_process(p, skb))) |
---|
| 354 | + return RX_HANDLER_PASS; |
---|
| 355 | + |
---|
290 | 356 | forward: |
---|
291 | 357 | switch (p->state) { |
---|
292 | 358 | case BR_STATE_FORWARDING: |
---|
293 | | - rhook = rcu_dereference(br_should_route_hook); |
---|
294 | | - if (rhook) { |
---|
295 | | - if ((*rhook)(skb)) { |
---|
296 | | - *pskb = skb; |
---|
297 | | - return RX_HANDLER_PASS; |
---|
298 | | - } |
---|
299 | | - dest = eth_hdr(skb)->h_dest; |
---|
300 | | - } |
---|
301 | | - /* fall through */ |
---|
302 | 359 | case BR_STATE_LEARNING: |
---|
303 | 360 | if (ether_addr_equal(p->br->dev->dev_addr, dest)) |
---|
304 | 361 | skb->pkt_type = PACKET_HOST; |
---|
305 | 362 | |
---|
306 | | - NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, |
---|
307 | | - dev_net(skb->dev), NULL, skb, skb->dev, NULL, |
---|
308 | | - br_handle_frame_finish); |
---|
309 | | - break; |
---|
| 363 | + return nf_hook_bridge_pre(skb, pskb); |
---|
310 | 364 | default: |
---|
311 | 365 | drop: |
---|
312 | 366 | kfree_skb(skb); |
---|
313 | 367 | } |
---|
314 | 368 | return RX_HANDLER_CONSUMED; |
---|
315 | 369 | } |
---|
| 370 | + |
---|
| 371 | +/* This function has no purpose other than to appease the br_port_get_rcu/rtnl |
---|
| 372 | + * helpers which identify bridged ports according to the rx_handler installed |
---|
| 373 | + * on them (so there _needs_ to be a bridge rx_handler even if we don't need it |
---|
| 374 | + * to do anything useful). This bridge won't support traffic to/from the stack, |
---|
| 375 | + * but only hardware bridging. So return RX_HANDLER_PASS so we don't steal |
---|
| 376 | + * frames from the ETH_P_XDSA packet_type handler. |
---|
| 377 | + */ |
---|
| 378 | +static rx_handler_result_t br_handle_frame_dummy(struct sk_buff **pskb) |
---|
| 379 | +{ |
---|
| 380 | + return RX_HANDLER_PASS; |
---|
| 381 | +} |
---|
| 382 | + |
---|
| 383 | +rx_handler_func_t *br_get_rx_handler(const struct net_device *dev) |
---|
| 384 | +{ |
---|
| 385 | + if (netdev_uses_dsa(dev)) |
---|
| 386 | + return br_handle_frame_dummy; |
---|
| 387 | + |
---|
| 388 | + return br_handle_frame; |
---|
| 389 | +} |
---|