Blame view

net/ipv6/output_core.c 4.28 KB
3c73a0368   Vlad Yasevich   ipv6: Update ipv6...
1
2
3
4
5
  /*
   * IPv6 library code, needed by static components when full IPv6 support is
   * not configured or static.  These functions are needed by GSO/GRO implementation.
   */
  #include <linux/export.h>
5188cd44c   Ben Hutchings   drivers/net, ipv6...
6
  #include <net/ip.h>
3c73a0368   Vlad Yasevich   ipv6: Update ipv6...
7
8
  #include <net/ipv6.h>
  #include <net/ip6_fib.h>
3ce9b35ff   Cong Wang   ipv6: move ip6_ds...
9
  #include <net/addrconf.h>
6dfac5c33   Hannes Frederic Sowa   ipv6: strengthen ...
10
  #include <net/secure_seq.h>
a263653ed   Pablo Neira Ayuso   netfilter: don't ...
11
  #include <linux/netfilter.h>
3c73a0368   Vlad Yasevich   ipv6: Update ipv6...
12

5a352dd0a   Hannes Frederic Sowa   ipv6: hash net pt...
13
  static u32 __ipv6_select_ident(struct net *net, u32 hashrnd,
fd0273d79   Martin KaFai Lau   ipv6: Remove exte...
14
15
  			       const struct in6_addr *dst,
  			       const struct in6_addr *src)
0508c07f5   Vlad Yasevich   ipv6: Select frag...
16
17
18
19
20
  {
  	u32 hash, id;
  
  	hash = __ipv6_addr_jhash(dst, hashrnd);
  	hash = __ipv6_addr_jhash(src, hash);
5a352dd0a   Hannes Frederic Sowa   ipv6: hash net pt...
21
  	hash ^= net_hash_mix(net);
0508c07f5   Vlad Yasevich   ipv6: Select frag...
22
23
24
25
26
27
28
29
30
31
32
  
  	/* Treat id of 0 as unset and if we get 0 back from ip_idents_reserve,
  	 * set the hight order instead thus minimizing possible future
  	 * collisions.
  	 */
  	id = ip_idents_reserve(hash, 1);
  	if (unlikely(!id))
  		id = 1 << 31;
  
  	return id;
  }
5188cd44c   Ben Hutchings   drivers/net, ipv6...
33
34
35
36
37
38
39
40
  /* This function exists only for tap drivers that must support broken
   * clients requesting UFO without specifying an IPv6 fragment ID.
   *
   * This is similar to ipv6_select_ident() but we use an independent hash
   * seed to limit information leakage.
   *
   * The network header must be set before calling this.
   */
60335608e   Willem de Bruijn   net: accept UFO d...
41
  __be32 ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
5188cd44c   Ben Hutchings   drivers/net, ipv6...
42
43
44
45
  {
  	static u32 ip6_proxy_idents_hashrnd __read_mostly;
  	struct in6_addr buf[2];
  	struct in6_addr *addrs;
0508c07f5   Vlad Yasevich   ipv6: Select frag...
46
  	u32 id;
5188cd44c   Ben Hutchings   drivers/net, ipv6...
47
48
49
50
51
52
  
  	addrs = skb_header_pointer(skb,
  				   skb_network_offset(skb) +
  				   offsetof(struct ipv6hdr, saddr),
  				   sizeof(buf), buf);
  	if (!addrs)
60335608e   Willem de Bruijn   net: accept UFO d...
53
  		return 0;
5188cd44c   Ben Hutchings   drivers/net, ipv6...
54
55
56
  
  	net_get_random_once(&ip6_proxy_idents_hashrnd,
  			    sizeof(ip6_proxy_idents_hashrnd));
5a352dd0a   Hannes Frederic Sowa   ipv6: hash net pt...
57
  	id = __ipv6_select_ident(net, ip6_proxy_idents_hashrnd,
0508c07f5   Vlad Yasevich   ipv6: Select frag...
58
  				 &addrs[1], &addrs[0]);
60335608e   Willem de Bruijn   net: accept UFO d...
59
  	return htonl(id);
5188cd44c   Ben Hutchings   drivers/net, ipv6...
60
61
  }
  EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
7f1598678   Eric Dumazet   ipv6: ipv6_select...
62
63
64
  __be32 ipv6_select_ident(struct net *net,
  			 const struct in6_addr *daddr,
  			 const struct in6_addr *saddr)
0508c07f5   Vlad Yasevich   ipv6: Select frag...
65
66
67
68
69
  {
  	static u32 ip6_idents_hashrnd __read_mostly;
  	u32 id;
  
  	net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd));
fd0273d79   Martin KaFai Lau   ipv6: Remove exte...
70
  	id = __ipv6_select_ident(net, ip6_idents_hashrnd, daddr, saddr);
286c2349f   Martin KaFai Lau   ipv6: Clean up ip...
71
  	return htonl(id);
0508c07f5   Vlad Yasevich   ipv6: Select frag...
72
73
  }
  EXPORT_SYMBOL(ipv6_select_ident);
3c73a0368   Vlad Yasevich   ipv6: Update ipv6...
74
75
  int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
  {
6399f1fae   Sabrina Dubroca   ipv6: avoid overf...
76
  	unsigned int offset = sizeof(struct ipv6hdr);
29a3cad5c   Simon Horman   ipv6: Correct com...
77
78
  	unsigned int packet_len = skb_tail_pointer(skb) -
  		skb_network_header(skb);
3c73a0368   Vlad Yasevich   ipv6: Update ipv6...
79
80
  	int found_rhdr = 0;
  	*nexthdr = &ipv6_hdr(skb)->nexthdr;
2423496af   Craig Gallek   ipv6: Prevent ove...
81
82
  	while (offset <= packet_len) {
  		struct ipv6_opt_hdr *exthdr;
3c73a0368   Vlad Yasevich   ipv6: Update ipv6...
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  
  		switch (**nexthdr) {
  
  		case NEXTHDR_HOP:
  			break;
  		case NEXTHDR_ROUTING:
  			found_rhdr = 1;
  			break;
  		case NEXTHDR_DEST:
  #if IS_ENABLED(CONFIG_IPV6_MIP6)
  			if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
  				break;
  #endif
  			if (found_rhdr)
  				return offset;
  			break;
67ba4152e   Ian Morris   ipv6: White-space...
99
  		default:
3c73a0368   Vlad Yasevich   ipv6: Update ipv6...
100
101
  			return offset;
  		}
2423496af   Craig Gallek   ipv6: Prevent ove...
102
103
  		if (offset + sizeof(struct ipv6_opt_hdr) > packet_len)
  			return -EINVAL;
3c73a0368   Vlad Yasevich   ipv6: Update ipv6...
104
105
  		exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
  						 offset);
3de33e1ba   Stefano Brivio   ipv6: accept 64k ...
106
107
  		offset += ipv6_optlen(exthdr);
  		if (offset > IPV6_MAXPLEN)
6399f1fae   Sabrina Dubroca   ipv6: avoid overf...
108
  			return -EINVAL;
2423496af   Craig Gallek   ipv6: Prevent ove...
109
  		*nexthdr = &exthdr->nexthdr;
3c73a0368   Vlad Yasevich   ipv6: Update ipv6...
110
  	}
2423496af   Craig Gallek   ipv6: Prevent ove...
111
  	return -EINVAL;
3c73a0368   Vlad Yasevich   ipv6: Update ipv6...
112
113
  }
  EXPORT_SYMBOL(ip6_find_1stfragopt);
3ce9b35ff   Cong Wang   ipv6: move ip6_ds...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  
  #if IS_ENABLED(CONFIG_IPV6)
  int ip6_dst_hoplimit(struct dst_entry *dst)
  {
  	int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
  	if (hoplimit == 0) {
  		struct net_device *dev = dst->dev;
  		struct inet6_dev *idev;
  
  		rcu_read_lock();
  		idev = __in6_dev_get(dev);
  		if (idev)
  			hoplimit = idev->cnf.hop_limit;
  		else
  			hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit;
  		rcu_read_unlock();
  	}
  	return hoplimit;
  }
  EXPORT_SYMBOL(ip6_dst_hoplimit);
  #endif
788787b55   Cong Wang   ipv6: move ip6_lo...
135

cf91a99da   Eric W. Biederman   ipv4, ipv6: Pass ...
136
  int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
788787b55   Cong Wang   ipv6: move ip6_lo...
137
138
139
140
141
142
143
  {
  	int len;
  
  	len = skb->len - sizeof(struct ipv6hdr);
  	if (len > IPV6_MAXPLEN)
  		len = 0;
  	ipv6_hdr(skb)->payload_len = htons(len);
f6c20c596   huizhang   net: ipv6: Fixed ...
144
  	IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
788787b55   Cong Wang   ipv6: move ip6_lo...
145

a8e3e1a9f   David Ahern   net: l3mdev: Add ...
146
147
148
149
150
151
  	/* if egress device is enslaved to an L3 master device pass the
  	 * skb to its handler for processing
  	 */
  	skb = l3mdev_ip6_out(sk, skb);
  	if (unlikely(!skb))
  		return 0;
b4e479a96   Eli Cooper   ipv6: Set skb->pr...
152
  	skb->protocol = htons(ETH_P_IPV6);
29a26a568   Eric W. Biederman   netfilter: Pass s...
153
154
  	return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
  		       net, sk, skb, NULL, skb_dst(skb)->dev,
13206b6bf   Eric W. Biederman   net: Pass net int...
155
  		       dst_output);
788787b55   Cong Wang   ipv6: move ip6_lo...
156
157
  }
  EXPORT_SYMBOL_GPL(__ip6_local_out);
33224b16f   Eric W. Biederman   ipv4, ipv6: Pass ...
158
  int ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
788787b55   Cong Wang   ipv6: move ip6_lo...
159
160
  {
  	int err;
cf91a99da   Eric W. Biederman   ipv4, ipv6: Pass ...
161
  	err = __ip6_local_out(net, sk, skb);
788787b55   Cong Wang   ipv6: move ip6_lo...
162
  	if (likely(err == 1))
13206b6bf   Eric W. Biederman   net: Pass net int...
163
  		err = dst_output(net, sk, skb);
788787b55   Cong Wang   ipv6: move ip6_lo...
164
165
166
167
  
  	return err;
  }
  EXPORT_SYMBOL_GPL(ip6_local_out);