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

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

Version: ~ [ linux-5.11 ] ~ [ linux-5.10.17 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.99 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.176 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.221 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.257 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.257 ] ~ [ 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 __be32 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 0;
 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         return 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         unsigned int offset = sizeof(struct ipv6hdr);
 82         unsigned int packet_len = skb_tail_pointer(skb) -
 83                 skb_network_header(skb);
 84         int found_rhdr = 0;
 85         *nexthdr = &ipv6_hdr(skb)->nexthdr;
 86 
 87         while (offset <= packet_len) {
 88                 struct ipv6_opt_hdr *exthdr;
 89 
 90                 switch (**nexthdr) {
 91 
 92                 case NEXTHDR_HOP:
 93                         break;
 94                 case NEXTHDR_ROUTING:
 95                         found_rhdr = 1;
 96                         break;
 97                 case NEXTHDR_DEST:
 98 #if IS_ENABLED(CONFIG_IPV6_MIP6)
 99                         if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
100                                 break;
101 #endif
102                         if (found_rhdr)
103                                 return offset;
104                         break;
105                 default:
106                         return offset;
107                 }
108 
109                 if (offset + sizeof(struct ipv6_opt_hdr) > packet_len)
110                         return -EINVAL;
111 
112                 exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
113                                                  offset);
114                 offset += ipv6_optlen(exthdr);
115                 if (offset > IPV6_MAXPLEN)
116                         return -EINVAL;
117                 *nexthdr = &exthdr->nexthdr;
118         }
119 
120         return -EINVAL;
121 }
122 EXPORT_SYMBOL(ip6_find_1stfragopt);
123 
124 #if IS_ENABLED(CONFIG_IPV6)
125 int ip6_dst_hoplimit(struct dst_entry *dst)
126 {
127         int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
128         if (hoplimit == 0) {
129                 struct net_device *dev = dst->dev;
130                 struct inet6_dev *idev;
131 
132                 rcu_read_lock();
133                 idev = __in6_dev_get(dev);
134                 if (idev)
135                         hoplimit = idev->cnf.hop_limit;
136                 else
137                         hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit;
138                 rcu_read_unlock();
139         }
140         return hoplimit;
141 }
142 EXPORT_SYMBOL(ip6_dst_hoplimit);
143 #endif
144 
145 int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
146 {
147         int len;
148 
149         len = skb->len - sizeof(struct ipv6hdr);
150         if (len > IPV6_MAXPLEN)
151                 len = 0;
152         ipv6_hdr(skb)->payload_len = htons(len);
153         IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
154 
155         /* if egress device is enslaved to an L3 master device pass the
156          * skb to its handler for processing
157          */
158         skb = l3mdev_ip6_out(sk, skb);
159         if (unlikely(!skb))
160                 return 0;
161 
162         skb->protocol = htons(ETH_P_IPV6);
163 
164         return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
165                        net, sk, skb, NULL, skb_dst(skb)->dev,
166                        dst_output);
167 }
168 EXPORT_SYMBOL_GPL(__ip6_local_out);
169 
170 int ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
171 {
172         int err;
173 
174         err = __ip6_local_out(net, sk, skb);
175         if (likely(err == 1))
176                 err = dst_output(net, sk, skb);
177 
178         return err;
179 }
180 EXPORT_SYMBOL_GPL(ip6_local_out);
181 

~ [ 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