1 /* 2 * IPv6 library code, needed by static components when full IPv6 support is 3 * not configured or static. These functions are needed by GSO/GRO implementation. 4 */ 5 #include <linux/export.h> 6 #include <net/ipv6.h> 7 #include <net/ip6_fib.h> 8 #include <net/addrconf.h> 9 #include <net/secure_seq.h> 10 11 int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) 12 { 13 u16 offset = sizeof(struct ipv6hdr); 14 struct ipv6_opt_hdr *exthdr = 15 (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1); 16 unsigned int packet_len = skb_tail_pointer(skb) - 17 skb_network_header(skb); 18 int found_rhdr = 0; 19 *nexthdr = &ipv6_hdr(skb)->nexthdr; 20 21 while (offset + 1 <= packet_len) { 22 23 switch (**nexthdr) { 24 25 case NEXTHDR_HOP: 26 break; 27 case NEXTHDR_ROUTING: 28 found_rhdr = 1; 29 break; 30 case NEXTHDR_DEST: 31 #if IS_ENABLED(CONFIG_IPV6_MIP6) 32 if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0) 33 break; 34 #endif 35 if (found_rhdr) 36 return offset; 37 break; 38 default : 39 return offset; 40 } 41 42 offset += ipv6_optlen(exthdr); 43 *nexthdr = &exthdr->nexthdr; 44 exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) + 45 offset); 46 } 47 48 return offset; 49 } 50 EXPORT_SYMBOL(ip6_find_1stfragopt); 51 52 #if IS_ENABLED(CONFIG_IPV6) 53 int ip6_dst_hoplimit(struct dst_entry *dst) 54 { 55 int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT); 56 if (hoplimit == 0) { 57 struct net_device *dev = dst->dev; 58 struct inet6_dev *idev; 59 60 rcu_read_lock(); 61 idev = __in6_dev_get(dev); 62 if (idev) 63 hoplimit = idev->cnf.hop_limit; 64 else 65 hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit; 66 rcu_read_unlock(); 67 } 68 return hoplimit; 69 } 70 EXPORT_SYMBOL(ip6_dst_hoplimit); 71 #endif 72 73 int __ip6_local_out(struct sk_buff *skb) 74 { 75 int len; 76 77 len = skb->len - sizeof(struct ipv6hdr); 78 if (len > IPV6_MAXPLEN) 79 len = 0; 80 ipv6_hdr(skb)->payload_len = htons(len); 81 IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); 82 83 return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, 84 skb_dst(skb)->dev, dst_output); 85 } 86 EXPORT_SYMBOL_GPL(__ip6_local_out); 87 88 int ip6_local_out(struct sk_buff *skb) 89 { 90 int err; 91 92 err = __ip6_local_out(skb); 93 if (likely(err == 1)) 94 err = dst_output(skb); 95 96 return err; 97 } 98 EXPORT_SYMBOL_GPL(ip6_local_out); 99