13c73a0368e995f047c14388a05dcfba599053befVlad Yasevich/*
23c73a0368e995f047c14388a05dcfba599053befVlad Yasevich * IPv6 library code, needed by static components when full IPv6 support is
33c73a0368e995f047c14388a05dcfba599053befVlad Yasevich * not configured or static.  These functions are needed by GSO/GRO implementation.
43c73a0368e995f047c14388a05dcfba599053befVlad Yasevich */
53c73a0368e995f047c14388a05dcfba599053befVlad Yasevich#include <linux/export.h>
65188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings#include <net/ip.h>
73c73a0368e995f047c14388a05dcfba599053befVlad Yasevich#include <net/ipv6.h>
83c73a0368e995f047c14388a05dcfba599053befVlad Yasevich#include <net/ip6_fib.h>
93ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang#include <net/addrconf.h>
106dfac5c33620de7f5ecd9dd07e2e2bb6549c4d55Hannes Frederic Sowa#include <net/secure_seq.h>
113c73a0368e995f047c14388a05dcfba599053befVlad Yasevich
125188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings/* This function exists only for tap drivers that must support broken
135188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings * clients requesting UFO without specifying an IPv6 fragment ID.
145188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings *
155188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings * This is similar to ipv6_select_ident() but we use an independent hash
165188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings * seed to limit information leakage.
175188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings *
185188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings * The network header must be set before calling this.
195188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings */
205188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchingsvoid ipv6_proxy_select_ident(struct sk_buff *skb)
215188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings{
225188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings	static u32 ip6_proxy_idents_hashrnd __read_mostly;
235188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings	struct in6_addr buf[2];
245188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings	struct in6_addr *addrs;
255188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings	u32 hash, id;
265188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings
275188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings	addrs = skb_header_pointer(skb,
285188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings				   skb_network_offset(skb) +
295188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings				   offsetof(struct ipv6hdr, saddr),
305188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings				   sizeof(buf), buf);
315188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings	if (!addrs)
325188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings		return;
335188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings
345188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings	net_get_random_once(&ip6_proxy_idents_hashrnd,
355188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings			    sizeof(ip6_proxy_idents_hashrnd));
365188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings
375188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings	hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd);
385188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings	hash = __ipv6_addr_jhash(&addrs[0], hash);
395188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings
405188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings	id = ip_idents_reserve(hash, 1);
415188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings	skb_shinfo(skb)->ip6_frag_id = htonl(id);
425188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings}
435188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben HutchingsEXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
445188cd44c55db3e92cd9e77a40b5baa7ed4340f7Ben Hutchings
453c73a0368e995f047c14388a05dcfba599053befVlad Yasevichint ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
463c73a0368e995f047c14388a05dcfba599053befVlad Yasevich{
473c73a0368e995f047c14388a05dcfba599053befVlad Yasevich	u16 offset = sizeof(struct ipv6hdr);
483c73a0368e995f047c14388a05dcfba599053befVlad Yasevich	struct ipv6_opt_hdr *exthdr =
493c73a0368e995f047c14388a05dcfba599053befVlad Yasevich				(struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
5029a3cad5c6ae9e7fbf1509d01d39c3c3c38f11f9Simon Horman	unsigned int packet_len = skb_tail_pointer(skb) -
5129a3cad5c6ae9e7fbf1509d01d39c3c3c38f11f9Simon Horman		skb_network_header(skb);
523c73a0368e995f047c14388a05dcfba599053befVlad Yasevich	int found_rhdr = 0;
533c73a0368e995f047c14388a05dcfba599053befVlad Yasevich	*nexthdr = &ipv6_hdr(skb)->nexthdr;
543c73a0368e995f047c14388a05dcfba599053befVlad Yasevich
553c73a0368e995f047c14388a05dcfba599053befVlad Yasevich	while (offset + 1 <= packet_len) {
563c73a0368e995f047c14388a05dcfba599053befVlad Yasevich
573c73a0368e995f047c14388a05dcfba599053befVlad Yasevich		switch (**nexthdr) {
583c73a0368e995f047c14388a05dcfba599053befVlad Yasevich
593c73a0368e995f047c14388a05dcfba599053befVlad Yasevich		case NEXTHDR_HOP:
603c73a0368e995f047c14388a05dcfba599053befVlad Yasevich			break;
613c73a0368e995f047c14388a05dcfba599053befVlad Yasevich		case NEXTHDR_ROUTING:
623c73a0368e995f047c14388a05dcfba599053befVlad Yasevich			found_rhdr = 1;
633c73a0368e995f047c14388a05dcfba599053befVlad Yasevich			break;
643c73a0368e995f047c14388a05dcfba599053befVlad Yasevich		case NEXTHDR_DEST:
653c73a0368e995f047c14388a05dcfba599053befVlad Yasevich#if IS_ENABLED(CONFIG_IPV6_MIP6)
663c73a0368e995f047c14388a05dcfba599053befVlad Yasevich			if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
673c73a0368e995f047c14388a05dcfba599053befVlad Yasevich				break;
683c73a0368e995f047c14388a05dcfba599053befVlad Yasevich#endif
693c73a0368e995f047c14388a05dcfba599053befVlad Yasevich			if (found_rhdr)
703c73a0368e995f047c14388a05dcfba599053befVlad Yasevich				return offset;
713c73a0368e995f047c14388a05dcfba599053befVlad Yasevich			break;
7267ba4152e8b77eada6a9c64e3c2c84d6112794fcIan Morris		default:
733c73a0368e995f047c14388a05dcfba599053befVlad Yasevich			return offset;
743c73a0368e995f047c14388a05dcfba599053befVlad Yasevich		}
753c73a0368e995f047c14388a05dcfba599053befVlad Yasevich
763c73a0368e995f047c14388a05dcfba599053befVlad Yasevich		offset += ipv6_optlen(exthdr);
773c73a0368e995f047c14388a05dcfba599053befVlad Yasevich		*nexthdr = &exthdr->nexthdr;
783c73a0368e995f047c14388a05dcfba599053befVlad Yasevich		exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
793c73a0368e995f047c14388a05dcfba599053befVlad Yasevich						 offset);
803c73a0368e995f047c14388a05dcfba599053befVlad Yasevich	}
813c73a0368e995f047c14388a05dcfba599053befVlad Yasevich
823c73a0368e995f047c14388a05dcfba599053befVlad Yasevich	return offset;
833c73a0368e995f047c14388a05dcfba599053befVlad Yasevich}
843c73a0368e995f047c14388a05dcfba599053befVlad YasevichEXPORT_SYMBOL(ip6_find_1stfragopt);
853ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang
863ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang#if IS_ENABLED(CONFIG_IPV6)
873ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wangint ip6_dst_hoplimit(struct dst_entry *dst)
883ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang{
893ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang	int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
903ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang	if (hoplimit == 0) {
913ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang		struct net_device *dev = dst->dev;
923ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang		struct inet6_dev *idev;
933ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang
943ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang		rcu_read_lock();
953ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang		idev = __in6_dev_get(dev);
963ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang		if (idev)
973ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang			hoplimit = idev->cnf.hop_limit;
983ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang		else
993ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang			hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit;
1003ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang		rcu_read_unlock();
1013ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang	}
1023ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang	return hoplimit;
1033ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang}
1043ce9b35ff6de8dfebb0b0045e667c000f632e563Cong WangEXPORT_SYMBOL(ip6_dst_hoplimit);
1053ce9b35ff6de8dfebb0b0045e667c000f632e563Cong Wang#endif
106788787b55913d456b9851d926d9a80ff00892c34Cong Wang
107788787b55913d456b9851d926d9a80ff00892c34Cong Wangint __ip6_local_out(struct sk_buff *skb)
108788787b55913d456b9851d926d9a80ff00892c34Cong Wang{
109788787b55913d456b9851d926d9a80ff00892c34Cong Wang	int len;
110788787b55913d456b9851d926d9a80ff00892c34Cong Wang
111788787b55913d456b9851d926d9a80ff00892c34Cong Wang	len = skb->len - sizeof(struct ipv6hdr);
112788787b55913d456b9851d926d9a80ff00892c34Cong Wang	if (len > IPV6_MAXPLEN)
113788787b55913d456b9851d926d9a80ff00892c34Cong Wang		len = 0;
114788787b55913d456b9851d926d9a80ff00892c34Cong Wang	ipv6_hdr(skb)->payload_len = htons(len);
115f6c20c596f41fe6331cee2053b270bf12142b04ehuizhang	IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
116788787b55913d456b9851d926d9a80ff00892c34Cong Wang
117788787b55913d456b9851d926d9a80ff00892c34Cong Wang	return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL,
118788787b55913d456b9851d926d9a80ff00892c34Cong Wang		       skb_dst(skb)->dev, dst_output);
119788787b55913d456b9851d926d9a80ff00892c34Cong Wang}
120788787b55913d456b9851d926d9a80ff00892c34Cong WangEXPORT_SYMBOL_GPL(__ip6_local_out);
121788787b55913d456b9851d926d9a80ff00892c34Cong Wang
122788787b55913d456b9851d926d9a80ff00892c34Cong Wangint ip6_local_out(struct sk_buff *skb)
123788787b55913d456b9851d926d9a80ff00892c34Cong Wang{
124788787b55913d456b9851d926d9a80ff00892c34Cong Wang	int err;
125788787b55913d456b9851d926d9a80ff00892c34Cong Wang
126788787b55913d456b9851d926d9a80ff00892c34Cong Wang	err = __ip6_local_out(skb);
127788787b55913d456b9851d926d9a80ff00892c34Cong Wang	if (likely(err == 1))
128788787b55913d456b9851d926d9a80ff00892c34Cong Wang		err = dst_output(skb);
129788787b55913d456b9851d926d9a80ff00892c34Cong Wang
130788787b55913d456b9851d926d9a80ff00892c34Cong Wang	return err;
131788787b55913d456b9851d926d9a80ff00892c34Cong Wang}
132788787b55913d456b9851d926d9a80ff00892c34Cong WangEXPORT_SYMBOL_GPL(ip6_local_out);
133