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