cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

br_arp_nd_proxy.c (11679B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Handle bridge arp/nd proxy/suppress
      4 *
      5 *  Copyright (C) 2017 Cumulus Networks
      6 *  Copyright (c) 2017 Roopa Prabhu <roopa@cumulusnetworks.com>
      7 *
      8 *  Authors:
      9 *	Roopa Prabhu <roopa@cumulusnetworks.com>
     10 */
     11
     12#include <linux/kernel.h>
     13#include <linux/netdevice.h>
     14#include <linux/etherdevice.h>
     15#include <linux/neighbour.h>
     16#include <net/arp.h>
     17#include <linux/if_vlan.h>
     18#include <linux/inetdevice.h>
     19#include <net/addrconf.h>
     20#include <net/ipv6_stubs.h>
     21#if IS_ENABLED(CONFIG_IPV6)
     22#include <net/ip6_checksum.h>
     23#endif
     24
     25#include "br_private.h"
     26
     27void br_recalculate_neigh_suppress_enabled(struct net_bridge *br)
     28{
     29	struct net_bridge_port *p;
     30	bool neigh_suppress = false;
     31
     32	list_for_each_entry(p, &br->port_list, list) {
     33		if (p->flags & BR_NEIGH_SUPPRESS) {
     34			neigh_suppress = true;
     35			break;
     36		}
     37	}
     38
     39	br_opt_toggle(br, BROPT_NEIGH_SUPPRESS_ENABLED, neigh_suppress);
     40}
     41
     42#if IS_ENABLED(CONFIG_INET)
     43static void br_arp_send(struct net_bridge *br, struct net_bridge_port *p,
     44			struct net_device *dev, __be32 dest_ip, __be32 src_ip,
     45			const unsigned char *dest_hw,
     46			const unsigned char *src_hw,
     47			const unsigned char *target_hw,
     48			__be16 vlan_proto, u16 vlan_tci)
     49{
     50	struct net_bridge_vlan_group *vg;
     51	struct sk_buff *skb;
     52	u16 pvid;
     53
     54	netdev_dbg(dev, "arp send dev %s dst %pI4 dst_hw %pM src %pI4 src_hw %pM\n",
     55		   dev->name, &dest_ip, dest_hw, &src_ip, src_hw);
     56
     57	if (!vlan_tci) {
     58		arp_send(ARPOP_REPLY, ETH_P_ARP, dest_ip, dev, src_ip,
     59			 dest_hw, src_hw, target_hw);
     60		return;
     61	}
     62
     63	skb = arp_create(ARPOP_REPLY, ETH_P_ARP, dest_ip, dev, src_ip,
     64			 dest_hw, src_hw, target_hw);
     65	if (!skb)
     66		return;
     67
     68	if (p)
     69		vg = nbp_vlan_group_rcu(p);
     70	else
     71		vg = br_vlan_group_rcu(br);
     72	pvid = br_get_pvid(vg);
     73	if (pvid == (vlan_tci & VLAN_VID_MASK))
     74		vlan_tci = 0;
     75
     76	if (vlan_tci)
     77		__vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci);
     78
     79	if (p) {
     80		arp_xmit(skb);
     81	} else {
     82		skb_reset_mac_header(skb);
     83		__skb_pull(skb, skb_network_offset(skb));
     84		skb->ip_summed = CHECKSUM_UNNECESSARY;
     85		skb->pkt_type = PACKET_HOST;
     86
     87		netif_rx(skb);
     88	}
     89}
     90
     91static int br_chk_addr_ip(struct net_device *dev,
     92			  struct netdev_nested_priv *priv)
     93{
     94	__be32 ip = *(__be32 *)priv->data;
     95	struct in_device *in_dev;
     96	__be32 addr = 0;
     97
     98	in_dev = __in_dev_get_rcu(dev);
     99	if (in_dev)
    100		addr = inet_confirm_addr(dev_net(dev), in_dev, 0, ip,
    101					 RT_SCOPE_HOST);
    102
    103	if (addr == ip)
    104		return 1;
    105
    106	return 0;
    107}
    108
    109static bool br_is_local_ip(struct net_device *dev, __be32 ip)
    110{
    111	struct netdev_nested_priv priv = {
    112		.data = (void *)&ip,
    113	};
    114
    115	if (br_chk_addr_ip(dev, &priv))
    116		return true;
    117
    118	/* check if ip is configured on upper dev */
    119	if (netdev_walk_all_upper_dev_rcu(dev, br_chk_addr_ip, &priv))
    120		return true;
    121
    122	return false;
    123}
    124
    125void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
    126			      u16 vid, struct net_bridge_port *p)
    127{
    128	struct net_device *dev = br->dev;
    129	struct net_device *vlandev = dev;
    130	struct neighbour *n;
    131	struct arphdr *parp;
    132	u8 *arpptr, *sha;
    133	__be32 sip, tip;
    134
    135	BR_INPUT_SKB_CB(skb)->proxyarp_replied = 0;
    136
    137	if ((dev->flags & IFF_NOARP) ||
    138	    !pskb_may_pull(skb, arp_hdr_len(dev)))
    139		return;
    140
    141	parp = arp_hdr(skb);
    142
    143	if (parp->ar_pro != htons(ETH_P_IP) ||
    144	    parp->ar_hln != dev->addr_len ||
    145	    parp->ar_pln != 4)
    146		return;
    147
    148	arpptr = (u8 *)parp + sizeof(struct arphdr);
    149	sha = arpptr;
    150	arpptr += dev->addr_len;	/* sha */
    151	memcpy(&sip, arpptr, sizeof(sip));
    152	arpptr += sizeof(sip);
    153	arpptr += dev->addr_len;	/* tha */
    154	memcpy(&tip, arpptr, sizeof(tip));
    155
    156	if (ipv4_is_loopback(tip) ||
    157	    ipv4_is_multicast(tip))
    158		return;
    159
    160	if (br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) {
    161		if (p && (p->flags & BR_NEIGH_SUPPRESS))
    162			return;
    163		if (parp->ar_op != htons(ARPOP_RREQUEST) &&
    164		    parp->ar_op != htons(ARPOP_RREPLY) &&
    165		    (ipv4_is_zeronet(sip) || sip == tip)) {
    166			/* prevent flooding to neigh suppress ports */
    167			BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1;
    168			return;
    169		}
    170	}
    171
    172	if (parp->ar_op != htons(ARPOP_REQUEST))
    173		return;
    174
    175	if (vid != 0) {
    176		vlandev = __vlan_find_dev_deep_rcu(br->dev, skb->vlan_proto,
    177						   vid);
    178		if (!vlandev)
    179			return;
    180	}
    181
    182	if (br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED) &&
    183	    br_is_local_ip(vlandev, tip)) {
    184		/* its our local ip, so don't proxy reply
    185		 * and don't forward to neigh suppress ports
    186		 */
    187		BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1;
    188		return;
    189	}
    190
    191	n = neigh_lookup(&arp_tbl, &tip, vlandev);
    192	if (n) {
    193		struct net_bridge_fdb_entry *f;
    194
    195		if (!(n->nud_state & NUD_VALID)) {
    196			neigh_release(n);
    197			return;
    198		}
    199
    200		f = br_fdb_find_rcu(br, n->ha, vid);
    201		if (f) {
    202			bool replied = false;
    203
    204			if ((p && (p->flags & BR_PROXYARP)) ||
    205			    (f->dst && (f->dst->flags & (BR_PROXYARP_WIFI |
    206							 BR_NEIGH_SUPPRESS)))) {
    207				if (!vid)
    208					br_arp_send(br, p, skb->dev, sip, tip,
    209						    sha, n->ha, sha, 0, 0);
    210				else
    211					br_arp_send(br, p, skb->dev, sip, tip,
    212						    sha, n->ha, sha,
    213						    skb->vlan_proto,
    214						    skb_vlan_tag_get(skb));
    215				replied = true;
    216			}
    217
    218			/* If we have replied or as long as we know the
    219			 * mac, indicate to arp replied
    220			 */
    221			if (replied ||
    222			    br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED))
    223				BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1;
    224		}
    225
    226		neigh_release(n);
    227	}
    228}
    229#endif
    230
    231#if IS_ENABLED(CONFIG_IPV6)
    232struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *msg)
    233{
    234	struct nd_msg *m;
    235
    236	m = skb_header_pointer(skb, skb_network_offset(skb) +
    237			       sizeof(struct ipv6hdr), sizeof(*msg), msg);
    238	if (!m)
    239		return NULL;
    240
    241	if (m->icmph.icmp6_code != 0 ||
    242	    (m->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION &&
    243	     m->icmph.icmp6_type != NDISC_NEIGHBOUR_ADVERTISEMENT))
    244		return NULL;
    245
    246	return m;
    247}
    248
    249static void br_nd_send(struct net_bridge *br, struct net_bridge_port *p,
    250		       struct sk_buff *request, struct neighbour *n,
    251		       __be16 vlan_proto, u16 vlan_tci, struct nd_msg *ns)
    252{
    253	struct net_device *dev = request->dev;
    254	struct net_bridge_vlan_group *vg;
    255	struct sk_buff *reply;
    256	struct nd_msg *na;
    257	struct ipv6hdr *pip6;
    258	int na_olen = 8; /* opt hdr + ETH_ALEN for target */
    259	int ns_olen;
    260	int i, len;
    261	u8 *daddr;
    262	u16 pvid;
    263
    264	if (!dev)
    265		return;
    266
    267	len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) +
    268		sizeof(*na) + na_olen + dev->needed_tailroom;
    269
    270	reply = alloc_skb(len, GFP_ATOMIC);
    271	if (!reply)
    272		return;
    273
    274	reply->protocol = htons(ETH_P_IPV6);
    275	reply->dev = dev;
    276	skb_reserve(reply, LL_RESERVED_SPACE(dev));
    277	skb_push(reply, sizeof(struct ethhdr));
    278	skb_set_mac_header(reply, 0);
    279
    280	daddr = eth_hdr(request)->h_source;
    281
    282	/* Do we need option processing ? */
    283	ns_olen = request->len - (skb_network_offset(request) +
    284				  sizeof(struct ipv6hdr)) - sizeof(*ns);
    285	for (i = 0; i < ns_olen - 1; i += (ns->opt[i + 1] << 3)) {
    286		if (!ns->opt[i + 1]) {
    287			kfree_skb(reply);
    288			return;
    289		}
    290		if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
    291			daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
    292			break;
    293		}
    294	}
    295
    296	/* Ethernet header */
    297	ether_addr_copy(eth_hdr(reply)->h_dest, daddr);
    298	ether_addr_copy(eth_hdr(reply)->h_source, n->ha);
    299	eth_hdr(reply)->h_proto = htons(ETH_P_IPV6);
    300	reply->protocol = htons(ETH_P_IPV6);
    301
    302	skb_pull(reply, sizeof(struct ethhdr));
    303	skb_set_network_header(reply, 0);
    304	skb_put(reply, sizeof(struct ipv6hdr));
    305
    306	/* IPv6 header */
    307	pip6 = ipv6_hdr(reply);
    308	memset(pip6, 0, sizeof(struct ipv6hdr));
    309	pip6->version = 6;
    310	pip6->priority = ipv6_hdr(request)->priority;
    311	pip6->nexthdr = IPPROTO_ICMPV6;
    312	pip6->hop_limit = 255;
    313	pip6->daddr = ipv6_hdr(request)->saddr;
    314	pip6->saddr = *(struct in6_addr *)n->primary_key;
    315
    316	skb_pull(reply, sizeof(struct ipv6hdr));
    317	skb_set_transport_header(reply, 0);
    318
    319	na = (struct nd_msg *)skb_put(reply, sizeof(*na) + na_olen);
    320
    321	/* Neighbor Advertisement */
    322	memset(na, 0, sizeof(*na) + na_olen);
    323	na->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
    324	na->icmph.icmp6_router = (n->flags & NTF_ROUTER) ? 1 : 0;
    325	na->icmph.icmp6_override = 1;
    326	na->icmph.icmp6_solicited = 1;
    327	na->target = ns->target;
    328	ether_addr_copy(&na->opt[2], n->ha);
    329	na->opt[0] = ND_OPT_TARGET_LL_ADDR;
    330	na->opt[1] = na_olen >> 3;
    331
    332	na->icmph.icmp6_cksum = csum_ipv6_magic(&pip6->saddr,
    333						&pip6->daddr,
    334						sizeof(*na) + na_olen,
    335						IPPROTO_ICMPV6,
    336						csum_partial(na, sizeof(*na) + na_olen, 0));
    337
    338	pip6->payload_len = htons(sizeof(*na) + na_olen);
    339
    340	skb_push(reply, sizeof(struct ipv6hdr));
    341	skb_push(reply, sizeof(struct ethhdr));
    342
    343	reply->ip_summed = CHECKSUM_UNNECESSARY;
    344
    345	if (p)
    346		vg = nbp_vlan_group_rcu(p);
    347	else
    348		vg = br_vlan_group_rcu(br);
    349	pvid = br_get_pvid(vg);
    350	if (pvid == (vlan_tci & VLAN_VID_MASK))
    351		vlan_tci = 0;
    352
    353	if (vlan_tci)
    354		__vlan_hwaccel_put_tag(reply, vlan_proto, vlan_tci);
    355
    356	netdev_dbg(dev, "nd send dev %s dst %pI6 dst_hw %pM src %pI6 src_hw %pM\n",
    357		   dev->name, &pip6->daddr, daddr, &pip6->saddr, n->ha);
    358
    359	if (p) {
    360		dev_queue_xmit(reply);
    361	} else {
    362		skb_reset_mac_header(reply);
    363		__skb_pull(reply, skb_network_offset(reply));
    364		reply->ip_summed = CHECKSUM_UNNECESSARY;
    365		reply->pkt_type = PACKET_HOST;
    366
    367		netif_rx(reply);
    368	}
    369}
    370
    371static int br_chk_addr_ip6(struct net_device *dev,
    372			   struct netdev_nested_priv *priv)
    373{
    374	struct in6_addr *addr = (struct in6_addr *)priv->data;
    375
    376	if (ipv6_chk_addr(dev_net(dev), addr, dev, 0))
    377		return 1;
    378
    379	return 0;
    380}
    381
    382static bool br_is_local_ip6(struct net_device *dev, struct in6_addr *addr)
    383
    384{
    385	struct netdev_nested_priv priv = {
    386		.data = (void *)addr,
    387	};
    388
    389	if (br_chk_addr_ip6(dev, &priv))
    390		return true;
    391
    392	/* check if ip is configured on upper dev */
    393	if (netdev_walk_all_upper_dev_rcu(dev, br_chk_addr_ip6, &priv))
    394		return true;
    395
    396	return false;
    397}
    398
    399void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
    400		       u16 vid, struct net_bridge_port *p, struct nd_msg *msg)
    401{
    402	struct net_device *dev = br->dev;
    403	struct net_device *vlandev = NULL;
    404	struct in6_addr *saddr, *daddr;
    405	struct ipv6hdr *iphdr;
    406	struct neighbour *n;
    407
    408	BR_INPUT_SKB_CB(skb)->proxyarp_replied = 0;
    409
    410	if (p && (p->flags & BR_NEIGH_SUPPRESS))
    411		return;
    412
    413	if (msg->icmph.icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT &&
    414	    !msg->icmph.icmp6_solicited) {
    415		/* prevent flooding to neigh suppress ports */
    416		BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1;
    417		return;
    418	}
    419
    420	if (msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION)
    421		return;
    422
    423	iphdr = ipv6_hdr(skb);
    424	saddr = &iphdr->saddr;
    425	daddr = &iphdr->daddr;
    426
    427	if (ipv6_addr_any(saddr) || !ipv6_addr_cmp(saddr, daddr)) {
    428		/* prevent flooding to neigh suppress ports */
    429		BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1;
    430		return;
    431	}
    432
    433	if (vid != 0) {
    434		/* build neigh table lookup on the vlan device */
    435		vlandev = __vlan_find_dev_deep_rcu(br->dev, skb->vlan_proto,
    436						   vid);
    437		if (!vlandev)
    438			return;
    439	} else {
    440		vlandev = dev;
    441	}
    442
    443	if (br_is_local_ip6(vlandev, &msg->target)) {
    444		/* its our own ip, so don't proxy reply
    445		 * and don't forward to arp suppress ports
    446		 */
    447		BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1;
    448		return;
    449	}
    450
    451	n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, vlandev);
    452	if (n) {
    453		struct net_bridge_fdb_entry *f;
    454
    455		if (!(n->nud_state & NUD_VALID)) {
    456			neigh_release(n);
    457			return;
    458		}
    459
    460		f = br_fdb_find_rcu(br, n->ha, vid);
    461		if (f) {
    462			bool replied = false;
    463
    464			if (f->dst && (f->dst->flags & BR_NEIGH_SUPPRESS)) {
    465				if (vid != 0)
    466					br_nd_send(br, p, skb, n,
    467						   skb->vlan_proto,
    468						   skb_vlan_tag_get(skb), msg);
    469				else
    470					br_nd_send(br, p, skb, n, 0, 0, msg);
    471				replied = true;
    472			}
    473
    474			/* If we have replied or as long as we know the
    475			 * mac, indicate to NEIGH_SUPPRESS ports that we
    476			 * have replied
    477			 */
    478			if (replied ||
    479			    br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED))
    480				BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1;
    481		}
    482		neigh_release(n);
    483	}
    484}
    485#endif