478 lines · 12.7 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* *	Handle incoming frames *	Linux ethernet bridge * *	Authors: *	Lennert Buytenhek		<buytenh@gnu.org> */ #include <linux/slab.h>#include <linux/kernel.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/netfilter_bridge.h>#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE#include <net/netfilter/nf_queue.h>#endif#include <linux/neighbour.h>#include <net/arp.h>#include <net/dsa.h>#include <linux/export.h>#include <linux/rculist.h>#include "br_private.h"#include "br_private_tunnel.h" static intbr_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb){	br_drop_fake_rtable(skb);	return netif_receive_skb(skb);} static int br_pass_frame_up(struct sk_buff *skb, bool promisc){	struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;	struct net_bridge *br = netdev_priv(brdev);	struct net_bridge_vlan_group *vg; 	dev_sw_netstats_rx_add(brdev, skb->len); 	vg = br_vlan_group_rcu(br); 	/* Reset the offload_fwd_mark because there could be a stacked	 * bridge above, and it should not think this bridge it doing	 * that bridge's work forwarding out its ports.	 */	br_switchdev_frame_unmark(skb); 	/* Bridge is just like any other port.  Make sure the	 * packet is allowed except in promisc mode when someone	 * may be running packet capture.	 */	if (!(brdev->flags & IFF_PROMISC) &&	    !br_allowed_egress(vg, skb)) {		kfree_skb(skb);		return NET_RX_DROP;	} 	indev = skb->dev;	skb->dev = brdev;	skb = br_handle_vlan(br, NULL, vg, skb);	if (!skb)		return NET_RX_DROP;	/* update the multicast stats if the packet is IGMP/MLD */	br_multicast_count(br, NULL, skb, br_multicast_igmp_type(skb),			   BR_MCAST_DIR_TX); 	BR_INPUT_SKB_CB(skb)->promisc = promisc; 	return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,		       dev_net(indev), NULL, skb, indev, NULL,		       br_netif_receive_skb);} /* note: already called with rcu_read_lock */int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb){	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;	struct net_bridge_port *p = br_port_get_rcu(skb->dev);	enum br_pkt_type pkt_type = BR_PKT_UNICAST;	struct net_bridge_fdb_entry *dst = NULL;	struct net_bridge_mcast_port *pmctx;	struct net_bridge_mdb_entry *mdst;	bool local_rcv, mcast_hit = false;	struct net_bridge_mcast *brmctx;	struct net_bridge_vlan *vlan;	struct net_bridge *br;	bool promisc;	u16 vid = 0;	u8 state; 	if (!p)		goto drop; 	br = p->br; 	if (br_mst_is_enabled(p)) {		state = BR_STATE_FORWARDING;	} else {		if (p->state == BR_STATE_DISABLED) {			reason = SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE;			goto drop;		} 		state = p->state;	} 	brmctx = &p->br->multicast_ctx;	pmctx = &p->multicast_ctx;	if (!br_allowed_ingress(p->br, nbp_vlan_group_rcu(p), skb, &vid,				&state, &vlan))		goto out; 	if (test_bit(BR_PORT_LOCKED_BIT, &p->flags)) {		struct net_bridge_fdb_entry *fdb_src =			br_fdb_find_rcu(br, eth_hdr(skb)->h_source, vid); 		if (!fdb_src) {			/* FDB miss. Create locked FDB entry if MAB is enabled			 * and drop the packet.			 */			if (test_bit(BR_PORT_MAB_BIT, &p->flags))				br_fdb_update(br, p, eth_hdr(skb)->h_source,					      vid, BIT(BR_FDB_LOCKED));			goto drop;		} else if (READ_ONCE(fdb_src->dst) != p ||			   test_bit(BR_FDB_LOCAL, &fdb_src->flags)) {			/* FDB mismatch. Drop the packet without roaming. */			goto drop;		} else if (test_bit(BR_FDB_LOCKED, &fdb_src->flags)) {			/* FDB match, but entry is locked. Refresh it and drop			 * the packet.			 */			br_fdb_update(br, p, eth_hdr(skb)->h_source, vid,				      BIT(BR_FDB_LOCKED));			goto drop;		}	} 	nbp_switchdev_frame_mark(p, skb); 	/* insert into forwarding database after filtering to avoid spoofing */	if (test_bit(BR_LEARNING_BIT, &p->flags))		br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, 0); 	promisc = !!(br->dev->flags & IFF_PROMISC);	local_rcv = promisc; 	if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {		/* by definition the broadcast is also a multicast address */		if (is_broadcast_ether_addr(eth_hdr(skb)->h_dest)) {			pkt_type = BR_PKT_BROADCAST;			local_rcv = true;		} else {			pkt_type = BR_PKT_MULTICAST;			if (br_multicast_rcv(&brmctx, &pmctx, vlan, skb, vid))				goto drop;		}	} 	if (state == BR_STATE_LEARNING) {		reason = SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE;		goto drop;	} 	BR_INPUT_SKB_CB(skb)->brdev = br->dev;	BR_INPUT_SKB_CB(skb)->src_port_isolated = test_bit(BR_ISOLATED_BIT, &p->flags); 	if (IS_ENABLED(CONFIG_INET) &&	    (skb->protocol == htons(ETH_P_ARP) ||	     skb->protocol == htons(ETH_P_RARP))) {		br_do_proxy_suppress_arp(skb, br, vid, p);	} else if (ipv6_mod_enabled() &&		   skb->protocol == htons(ETH_P_IPV6) &&		   br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED) &&		   pskb_may_pull(skb, sizeof(struct ipv6hdr) +				 sizeof(struct nd_msg)) &&		   ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) {			struct nd_msg *msg; 			msg = br_is_nd_neigh_msg(skb);			if (msg)				br_do_suppress_nd(skb, br, vid, p, msg);	} 	switch (pkt_type) {	case BR_PKT_MULTICAST:		mdst = br_mdb_entry_skb_get(brmctx, skb, vid);		if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) &&		    br_multicast_querier_exists(brmctx, eth_hdr(skb), mdst)) {			if ((mdst && mdst->host_joined) ||			    br_multicast_is_router(brmctx, skb) ||			    br->dev->flags & IFF_ALLMULTI) {				local_rcv = true;				DEV_STATS_INC(br->dev, multicast);			}			mcast_hit = true;		} else {			local_rcv = true;			DEV_STATS_INC(br->dev, multicast);		}		break;	case BR_PKT_UNICAST:		dst = br_fdb_find_rcu(br, eth_hdr(skb)->h_dest, vid);		if (unlikely(!dst && vid &&			     br_opt_get(br, BROPT_FDB_LOCAL_VLAN_0))) {			dst = br_fdb_find_rcu(br, eth_hdr(skb)->h_dest, 0);			if (dst &&			    (!test_bit(BR_FDB_LOCAL, &dst->flags) ||			     test_bit(BR_FDB_ADDED_BY_USER, &dst->flags)))				dst = NULL;		}		break;	default:		break;	} 	if (dst) {		unsigned long now = jiffies; 		if (test_bit(BR_FDB_LOCAL, &dst->flags))			return br_pass_frame_up(skb, false); 		if (now != READ_ONCE(dst->used))			WRITE_ONCE(dst->used, now);		br_forward(READ_ONCE(dst->dst), skb, local_rcv, false);	} else {		if (!mcast_hit)			br_flood(br, skb, pkt_type, local_rcv, false, vid);		else			br_multicast_flood(mdst, skb, brmctx, local_rcv, false);	} 	if (local_rcv)		return br_pass_frame_up(skb, promisc); out:	return 0;drop:	kfree_skb_reason(skb, reason);	goto out;}EXPORT_SYMBOL_GPL(br_handle_frame_finish); static void __br_handle_local_finish(struct sk_buff *skb){	struct net_bridge_port *p = br_port_get_rcu(skb->dev);	u16 vid = 0; 	/* check if vlan is allowed, to avoid spoofing */	if (test_bit(BR_LEARNING_BIT, &p->flags) &&	    nbp_state_should_learn(p) &&	    !br_opt_get(p->br, BROPT_NO_LL_LEARN) &&	    br_should_learn(p, skb, &vid))		br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, 0);} /* note: already called with rcu_read_lock */static int br_handle_local_finish(struct net *net, struct sock *sk, struct sk_buff *skb){	__br_handle_local_finish(skb); 	/* return 1 to signal the okfn() was called so it's ok to use the skb */	return 1;} static int nf_hook_bridge_pre(struct sk_buff *skb, struct sk_buff **pskb){#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE	struct nf_hook_entries *e = NULL;	struct nf_hook_state state;	unsigned int verdict, i;	struct net *net;	int ret; 	net = dev_net(skb->dev);#ifdef CONFIG_JUMP_LABEL	if (!static_key_false(&nf_hooks_needed[NFPROTO_BRIDGE][NF_BR_PRE_ROUTING]))		goto frame_finish;#endif 	e = rcu_dereference(net->nf.hooks_bridge[NF_BR_PRE_ROUTING]);	if (!e)		goto frame_finish; 	nf_hook_state_init(&state, NF_BR_PRE_ROUTING,			   NFPROTO_BRIDGE, skb->dev, NULL, NULL,			   net, br_handle_frame_finish); 	for (i = 0; i < e->num_hook_entries; i++) {		verdict = nf_hook_entry_hookfn(&e->hooks[i], skb, &state);		switch (verdict & NF_VERDICT_MASK) {		case NF_ACCEPT:			if (BR_INPUT_SKB_CB(skb)->br_netfilter_broute) {				*pskb = skb;				return RX_HANDLER_PASS;			}			break;		case NF_DROP:			kfree_skb(skb);			return RX_HANDLER_CONSUMED;		case NF_QUEUE:			ret = nf_queue(skb, &state, i, verdict);			if (ret == 1)				continue;			return RX_HANDLER_CONSUMED;		default: /* STOLEN */			return RX_HANDLER_CONSUMED;		}	}frame_finish:	net = dev_net(skb->dev);	br_handle_frame_finish(net, NULL, skb);#else	br_handle_frame_finish(dev_net(skb->dev), NULL, skb);#endif	return RX_HANDLER_CONSUMED;} #define BR_CFM_MRP_OPTS \	((IS_ENABLED(CONFIG_BRIDGE_CFM) ? BIT(BROPT_CFM_ENABLED) : 0UL) | \	 (IS_ENABLED(CONFIG_BRIDGE_MRP) ? BIT(BROPT_MRP_ENABLED) : 0UL)) /* Return 0 if the frame was not processed otherwise 1 * note: already called with rcu_read_lock */static int br_process_frame_type(struct net_bridge_port *p,				 struct sk_buff *skb){	struct net_bridge *br = p->br; 	if (skb->protocol == htons(ETH_P_CFM) &&	    br_opt_get(br, BROPT_CFM_ENABLED))		return br_cfm_frame_rx(p, skb); 	if (skb->protocol == htons(ETH_P_MRP) &&	    br_opt_get(br, BROPT_MRP_ENABLED))		return br_mrp_process(p, skb); 	return 0;} /* * Return NULL if skb is handled * note: already called with rcu_read_lock */static rx_handler_result_t br_handle_frame(struct sk_buff **pskb){	enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;	struct net_bridge_port *p;	struct sk_buff *skb = *pskb;	const unsigned char *dest = eth_hdr(skb)->h_dest; 	if (unlikely(skb->pkt_type == PACKET_LOOPBACK))		return RX_HANDLER_PASS; 	if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) {		reason = SKB_DROP_REASON_MAC_INVALID_SOURCE;		goto drop;	} 	skb = skb_share_check(skb, GFP_ATOMIC);	if (!skb)		return RX_HANDLER_CONSUMED; 	memset(skb->cb, 0, sizeof(struct br_input_skb_cb));	br_tc_skb_miss_set(skb, false); 	p = br_port_get_rcu(skb->dev);	if (test_bit(BR_VLAN_TUNNEL_BIT, &p->flags))		br_handle_ingress_vlan_tunnel(skb, p, nbp_vlan_group_rcu(p)); 	if (unlikely(is_link_local_ether_addr(dest))) {		u16 fwd_mask = p->br->group_fwd_mask_required; 		/*		 * See IEEE 802.1D Table 7-10 Reserved addresses		 *		 * Assignment		 		Value		 * Bridge Group Address		01-80-C2-00-00-00		 * (MAC Control) 802.3		01-80-C2-00-00-01		 * (Link Aggregation) 802.3	01-80-C2-00-00-02		 * 802.1X PAE address		01-80-C2-00-00-03		 *		 * 802.1AB LLDP 		01-80-C2-00-00-0E		 *		 * Others reserved for future standardization		 */		fwd_mask |= p->group_fwd_mask;		switch (dest[5]) {		case 0x00:	/* Bridge Group Address */			/* If STP is turned off,			   then must forward to keep loop detection */			if (p->br->stp_enabled == BR_NO_STP ||			    fwd_mask & (1u << dest[5]))				goto forward;			*pskb = skb;			__br_handle_local_finish(skb);			return RX_HANDLER_PASS; 		case 0x01:	/* IEEE MAC (Pause) */			reason = SKB_DROP_REASON_MAC_IEEE_MAC_CONTROL;			goto drop; 		case 0x0E:	/* 802.1AB LLDP */			fwd_mask |= p->br->group_fwd_mask;			if (fwd_mask & (1u << dest[5]))				goto forward;			*pskb = skb;			__br_handle_local_finish(skb);			return RX_HANDLER_PASS; 		default:			/* Allow selective forwarding for most other protocols */			fwd_mask |= p->br->group_fwd_mask;			if (fwd_mask & (1u << dest[5]))				goto forward;		} 		BR_INPUT_SKB_CB(skb)->promisc = false; 		/* The else clause should be hit when nf_hook():		 *   - returns < 0 (drop/error)		 *   - returns = 0 (stolen/nf_queue)		 * Thus return 1 from the okfn() to signal the skb is ok to pass		 */		if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,			    dev_net(skb->dev), NULL, skb, skb->dev, NULL,			    br_handle_local_finish) == 1) {			return RX_HANDLER_PASS;		} else {			return RX_HANDLER_CONSUMED;		}	} 	if (unlikely((READ_ONCE(p->br->options) & BR_CFM_MRP_OPTS) &&		     br_process_frame_type(p, skb)))		return RX_HANDLER_PASS; forward:	if (br_mst_is_enabled(p))		goto defer_stp_filtering; 	switch (p->state) {	case BR_STATE_FORWARDING:	case BR_STATE_LEARNING:defer_stp_filtering:		if (ether_addr_equal(p->br->dev->dev_addr, dest))			skb->pkt_type = PACKET_HOST; 		return nf_hook_bridge_pre(skb, pskb);	default:		reason = SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE;drop:		kfree_skb_reason(skb, reason);	}	return RX_HANDLER_CONSUMED;} /* This function has no purpose other than to appease the br_port_get_rcu/rtnl * helpers which identify bridged ports according to the rx_handler installed * on them (so there _needs_ to be a bridge rx_handler even if we don't need it * to do anything useful). This bridge won't support traffic to/from the stack, * but only hardware bridging. So return RX_HANDLER_PASS so we don't steal * frames from the ETH_P_XDSA packet_type handler. */static rx_handler_result_t br_handle_frame_dummy(struct sk_buff **pskb){	return RX_HANDLER_PASS;} rx_handler_func_t *br_get_rx_handler(const struct net_device *dev){	if (netdev_uses_dsa(dev))		return br_handle_frame_dummy; 	return br_handle_frame;}