~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/ipv6/output_core.c

Version: ~ [ linux-5.9-rc6 ] ~ [ linux-5.8.10 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.66 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.146 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.198 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.236 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.236 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp