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

output_core.c (3797B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * IPv6 library code, needed by static components when full IPv6 support is
      4 * not configured or static.  These functions are needed by GSO/GRO implementation.
      5 */
      6#include <linux/export.h>
      7#include <net/ip.h>
      8#include <net/ipv6.h>
      9#include <net/ip6_fib.h>
     10#include <net/addrconf.h>
     11#include <net/secure_seq.h>
     12#include <linux/netfilter.h>
     13
     14static u32 __ipv6_select_ident(struct net *net,
     15			       const struct in6_addr *dst,
     16			       const struct in6_addr *src)
     17{
     18	u32 id;
     19
     20	do {
     21		id = prandom_u32();
     22	} while (!id);
     23
     24	return id;
     25}
     26
     27/* This function exists only for tap drivers that must support broken
     28 * clients requesting UFO without specifying an IPv6 fragment ID.
     29 *
     30 * This is similar to ipv6_select_ident() but we use an independent hash
     31 * seed to limit information leakage.
     32 *
     33 * The network header must be set before calling this.
     34 */
     35__be32 ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
     36{
     37	struct in6_addr buf[2];
     38	struct in6_addr *addrs;
     39	u32 id;
     40
     41	addrs = skb_header_pointer(skb,
     42				   skb_network_offset(skb) +
     43				   offsetof(struct ipv6hdr, saddr),
     44				   sizeof(buf), buf);
     45	if (!addrs)
     46		return 0;
     47
     48	id = __ipv6_select_ident(net, &addrs[1], &addrs[0]);
     49	return htonl(id);
     50}
     51EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
     52
     53__be32 ipv6_select_ident(struct net *net,
     54			 const struct in6_addr *daddr,
     55			 const struct in6_addr *saddr)
     56{
     57	u32 id;
     58
     59	id = __ipv6_select_ident(net, daddr, saddr);
     60	return htonl(id);
     61}
     62EXPORT_SYMBOL(ipv6_select_ident);
     63
     64int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
     65{
     66	unsigned int offset = sizeof(struct ipv6hdr);
     67	unsigned int packet_len = skb_tail_pointer(skb) -
     68		skb_network_header(skb);
     69	int found_rhdr = 0;
     70	*nexthdr = &ipv6_hdr(skb)->nexthdr;
     71
     72	while (offset <= packet_len) {
     73		struct ipv6_opt_hdr *exthdr;
     74
     75		switch (**nexthdr) {
     76
     77		case NEXTHDR_HOP:
     78			break;
     79		case NEXTHDR_ROUTING:
     80			found_rhdr = 1;
     81			break;
     82		case NEXTHDR_DEST:
     83#if IS_ENABLED(CONFIG_IPV6_MIP6)
     84			if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
     85				break;
     86#endif
     87			if (found_rhdr)
     88				return offset;
     89			break;
     90		default:
     91			return offset;
     92		}
     93
     94		if (offset + sizeof(struct ipv6_opt_hdr) > packet_len)
     95			return -EINVAL;
     96
     97		exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
     98						 offset);
     99		offset += ipv6_optlen(exthdr);
    100		if (offset > IPV6_MAXPLEN)
    101			return -EINVAL;
    102		*nexthdr = &exthdr->nexthdr;
    103	}
    104
    105	return -EINVAL;
    106}
    107EXPORT_SYMBOL(ip6_find_1stfragopt);
    108
    109#if IS_ENABLED(CONFIG_IPV6)
    110int ip6_dst_hoplimit(struct dst_entry *dst)
    111{
    112	int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
    113	if (hoplimit == 0) {
    114		struct net_device *dev = dst->dev;
    115		struct inet6_dev *idev;
    116
    117		rcu_read_lock();
    118		idev = __in6_dev_get(dev);
    119		if (idev)
    120			hoplimit = idev->cnf.hop_limit;
    121		else
    122			hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit;
    123		rcu_read_unlock();
    124	}
    125	return hoplimit;
    126}
    127EXPORT_SYMBOL(ip6_dst_hoplimit);
    128#endif
    129
    130int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
    131{
    132	int len;
    133
    134	len = skb->len - sizeof(struct ipv6hdr);
    135	if (len > IPV6_MAXPLEN)
    136		len = 0;
    137	ipv6_hdr(skb)->payload_len = htons(len);
    138	IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
    139
    140	/* if egress device is enslaved to an L3 master device pass the
    141	 * skb to its handler for processing
    142	 */
    143	skb = l3mdev_ip6_out(sk, skb);
    144	if (unlikely(!skb))
    145		return 0;
    146
    147	skb->protocol = htons(ETH_P_IPV6);
    148
    149	return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
    150		       net, sk, skb, NULL, skb_dst(skb)->dev,
    151		       dst_output);
    152}
    153EXPORT_SYMBOL_GPL(__ip6_local_out);
    154
    155int ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
    156{
    157	int err;
    158
    159	err = __ip6_local_out(net, sk, skb);
    160	if (likely(err == 1))
    161		err = dst_output(net, sk, skb);
    162
    163	return err;
    164}
    165EXPORT_SYMBOL_GPL(ip6_local_out);