Blame view

net/ipv6/udp.c 44.4 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
  /*
   *	UDP over IPv6
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
4
   *	Linux INET6 implementation
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
   *
   *	Authors:
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
7
   *	Pedro Roque		<roque@di.fc.ul.pt>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
   *
   *	Based on linux/ipv4/udp.c
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
14
15
16
17
   *	Fixes:
   *	Hideaki YOSHIFUJI	:	sin6_scope_id support
   *	YOSHIFUJI Hideaki @USAGI and:	Support IPV6_V6ONLY socket option, which
   *	Alexey Kuznetsov		allow both IPv4 and IPv6 sockets to bind
   *					a single port at the same time.
   *      Kazunori MIYAZAWA @USAGI:       change process style to use ip6_append_data
   *      YOSHIFUJI Hideaki @USAGI:	convert /proc/net/udp6 to seq_file.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
  #include <linux/errno.h>
  #include <linux/types.h>
  #include <linux/socket.h>
  #include <linux/sockios.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
27
28
29
  #include <linux/net.h>
  #include <linux/in6.h>
  #include <linux/netdevice.h>
  #include <linux/if_arp.h>
  #include <linux/ipv6.h>
  #include <linux/icmpv6.h>
  #include <linux/init.h>
1781f7f58   Herbert Xu   [UDP]: Restore mi...
30
  #include <linux/module.h>
3305b80c2   Herbert Xu   [IP]: Simplify an...
31
  #include <linux/skbuff.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
32
  #include <linux/slab.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
33
  #include <linux/uaccess.h>
0e219ae48   Paolo Abeni   net: use indirect...
34
  #include <linux/indirect_call_wrapper.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35

496611d7b   Craig Gallek   inet: create IPv6...
36
  #include <net/addrconf.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
  #include <net/ndisc.h>
  #include <net/protocol.h>
  #include <net/transp_v6.h>
  #include <net/ip6_route.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  #include <net/raw.h>
c752f0739   Arnaldo Carvalho de Melo   [TCP]: Move the t...
42
  #include <net/tcp_states.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
  #include <net/ip6_checksum.h>
e7cc08245   Stefano Brivio   udp: Support for ...
44
  #include <net/ip6_tunnel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
  #include <net/xfrm.h>
0bd84065b   subashab@codeaurora.org   net: ipv6: Fix UD...
46
  #include <net/inet_hashtables.h>
72289b96c   Tom Herbert   soreuseport: UDP/...
47
  #include <net/inet6_hashtables.h>
076bb0c82   Eliezer Tamir   net: rename inclu...
48
  #include <net/busy_poll.h>
e32ea7e74   Craig Gallek   soreuseport: fast...
49
  #include <net/sock_reuseport.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
  
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
22911fc58   Eric Dumazet   net: skb_free_dat...
53
  #include <trace/events/skb.h>
ba4e58eca   Gerrit Renker   [NET]: Supporting...
54
  #include "udp_impl.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55

6eada0110   Eric Dumazet   netns: constify n...
56
57
58
59
60
  static u32 udp6_ehashfn(const struct net *net,
  			const struct in6_addr *laddr,
  			const u16 lport,
  			const struct in6_addr *faddr,
  			const __be16 fport)
b50026b5a   Hannes Frederic Sowa   ipv6: split inet6...
61
  {
1bbdceef1   Hannes Frederic Sowa   inet: convert ine...
62
63
64
65
66
67
68
69
70
71
72
73
  	static u32 udp6_ehash_secret __read_mostly;
  	static u32 udp_ipv6_hash_secret __read_mostly;
  
  	u32 lhash, fhash;
  
  	net_get_random_once(&udp6_ehash_secret,
  			    sizeof(udp6_ehash_secret));
  	net_get_random_once(&udp_ipv6_hash_secret,
  			    sizeof(udp_ipv6_hash_secret));
  
  	lhash = (__force u32)laddr->s6_addr32[3];
  	fhash = __ipv6_addr_jhash(faddr, udp_ipv6_hash_secret);
b50026b5a   Hannes Frederic Sowa   ipv6: split inet6...
74
  	return __inet6_ehashfn(lhash, lport, fhash, fport,
1bbdceef1   Hannes Frederic Sowa   inet: convert ine...
75
  			       udp_ipv6_hash_secret + net_hash_mix(net));
b50026b5a   Hannes Frederic Sowa   ipv6: split inet6...
76
  }
6ba5a3c52   Pavel Emelyanov   [UDP]: Make full ...
77
  int udp_v6_get_port(struct sock *sk, unsigned short snum)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  {
30fff9231   Eric Dumazet   udp: bind() optim...
79
  	unsigned int hash2_nulladdr =
f0b1e64c1   Martin KaFai Lau   udp: Move udp[46]...
80
  		ipv6_portaddr_hash(sock_net(sk), &in6addr_any, snum);
9a52e97e2   Jeffrin Jose   net:ipv6:fixed a ...
81
  	unsigned int hash2_partial =
f0b1e64c1   Martin KaFai Lau   udp: Move udp[46]...
82
  		ipv6_portaddr_hash(sock_net(sk), &sk->sk_v6_rcv_saddr, 0);
30fff9231   Eric Dumazet   udp: bind() optim...
83

d4cada4ae   Eric Dumazet   udp: split sk_has...
84
  	/* precompute partial secondary hash */
30fff9231   Eric Dumazet   udp: bind() optim...
85
  	udp_sk(sk)->udp_portaddr_hash = hash2_partial;
fe38d2a1c   Josef Bacik   inet: collapse ip...
86
  	return udp_lib_get_port(sk, snum, hash2_nulladdr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
  }
f7c46156f   Alexey Kodanev   udp6: add missing...
88
  void udp_v6_rehash(struct sock *sk)
719f83585   Eric Dumazet   udp: add rehash o...
89
  {
f0b1e64c1   Martin KaFai Lau   udp: Move udp[46]...
90
  	u16 new_hash = ipv6_portaddr_hash(sock_net(sk),
efe4208f4   Eric Dumazet   ipv6: make lookup...
91
  					  &sk->sk_v6_rcv_saddr,
719f83585   Eric Dumazet   udp: add rehash o...
92
93
94
95
  					  inet_sk(sk)->inet_num);
  
  	udp_lib_rehash(sk, new_hash);
  }
d1e37288c   Su, Xuemin   udp reuseport: fi...
96
97
98
  static int compute_score(struct sock *sk, struct net *net,
  			 const struct in6_addr *saddr, __be16 sport,
  			 const struct in6_addr *daddr, unsigned short hnum,
735453730   Tim Beale   udp: Remove unuse...
99
  			 int dif, int sdif)
645ca708f   Eric Dumazet   udp: introduce st...
100
  {
60c04aecd   Joe Perches   udp: Neaten and r...
101
102
  	int score;
  	struct inet_sock *inet;
6da5b0f02   Mike Manning   net: ensure unbou...
103
  	bool dev_match;
60c04aecd   Joe Perches   udp: Neaten and r...
104
105
106
107
108
  
  	if (!net_eq(sock_net(sk), net) ||
  	    udp_sk(sk)->udp_port_hash != hnum ||
  	    sk->sk_family != PF_INET6)
  		return -1;
23b0269e5   Peter Oskolkov   net: udp6: prefer...
109
110
  	if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, daddr))
  		return -1;
60c04aecd   Joe Perches   udp: Neaten and r...
111
112
113
114
115
116
117
118
  	score = 0;
  	inet = inet_sk(sk);
  
  	if (inet->inet_dport) {
  		if (inet->inet_dport != sport)
  			return -1;
  		score++;
  	}
60c04aecd   Joe Perches   udp: Neaten and r...
119
120
121
122
123
  	if (!ipv6_addr_any(&sk->sk_v6_daddr)) {
  		if (!ipv6_addr_equal(&sk->sk_v6_daddr, saddr))
  			return -1;
  		score++;
  	}
6da5b0f02   Mike Manning   net: ensure unbou...
124
125
126
127
  	dev_match = udp_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif);
  	if (!dev_match)
  		return -1;
  	score++;
60c04aecd   Joe Perches   udp: Neaten and r...
128

7170a9777   Eric Dumazet   net: annotate acc...
129
  	if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id())
70da268b5   Eric Dumazet   net: SO_INCOMING_...
130
  		score++;
645ca708f   Eric Dumazet   udp: introduce st...
131
132
  	return score;
  }
a57066b1a   David S. Miller   Merge git://git.k...
133
134
135
136
137
138
  static struct sock *lookup_reuseport(struct net *net, struct sock *sk,
  				     struct sk_buff *skb,
  				     const struct in6_addr *saddr,
  				     __be16 sport,
  				     const struct in6_addr *daddr,
  				     unsigned int hnum)
2a08748cd   Jakub Sitnicki   udp6: Extract hel...
139
140
141
142
143
144
145
146
  {
  	struct sock *reuse_sk = NULL;
  	u32 hash;
  
  	if (sk->sk_reuseport && sk->sk_state != TCP_ESTABLISHED) {
  		hash = udp6_ehashfn(net, daddr, hnum, saddr, sport);
  		reuse_sk = reuseport_select_sock(sk, hash, skb,
  						 sizeof(struct udphdr));
2a08748cd   Jakub Sitnicki   udp6: Extract hel...
147
148
149
  	}
  	return reuse_sk;
  }
d1e37288c   Su, Xuemin   udp reuseport: fi...
150
  /* called with rcu_read_lock() */
fddc17def   Eric Dumazet   ipv6: udp: optimi...
151
152
  static struct sock *udp6_lib_lookup2(struct net *net,
  		const struct in6_addr *saddr, __be16 sport,
1801b570d   David Ahern   net: ipv6: add se...
153
  		const struct in6_addr *daddr, unsigned int hnum,
735453730   Tim Beale   udp: Remove unuse...
154
155
  		int dif, int sdif, struct udp_hslot *hslot2,
  		struct sk_buff *skb)
fddc17def   Eric Dumazet   ipv6: udp: optimi...
156
157
  {
  	struct sock *sk, *result;
e94a62f50   Paolo Abeni   net/reuseport: dr...
158
  	int score, badness;
fddc17def   Eric Dumazet   ipv6: udp: optimi...
159

fddc17def   Eric Dumazet   ipv6: udp: optimi...
160
161
  	result = NULL;
  	badness = -1;
ca065d0cf   Eric Dumazet   udp: no longer us...
162
  	udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
d1e37288c   Su, Xuemin   udp reuseport: fi...
163
  		score = compute_score(sk, net, saddr, sport,
735453730   Tim Beale   udp: Remove unuse...
164
  				      daddr, hnum, dif, sdif);
fddc17def   Eric Dumazet   ipv6: udp: optimi...
165
  		if (score > badness) {
2a08748cd   Jakub Sitnicki   udp6: Extract hel...
166
167
  			result = lookup_reuseport(net, sk, skb,
  						  saddr, sport, daddr, hnum);
a57066b1a   David S. Miller   Merge git://git.k...
168
169
  			/* Fall back to scoring if group has connections */
  			if (result && !reuseport_has_conns(sk, false))
2a08748cd   Jakub Sitnicki   udp6: Extract hel...
170
  				return result;
a57066b1a   David S. Miller   Merge git://git.k...
171
  			result = result ? : sk;
ca065d0cf   Eric Dumazet   udp: no longer us...
172
  			badness = score;
fddc17def   Eric Dumazet   ipv6: udp: optimi...
173
174
  		}
  	}
fddc17def   Eric Dumazet   ipv6: udp: optimi...
175
176
  	return result;
  }
6d4201b13   Jakub Sitnicki   udp6: Run SK_LOOK...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
  static inline struct sock *udp6_lookup_run_bpf(struct net *net,
  					       struct udp_table *udptable,
  					       struct sk_buff *skb,
  					       const struct in6_addr *saddr,
  					       __be16 sport,
  					       const struct in6_addr *daddr,
  					       u16 hnum)
  {
  	struct sock *sk, *reuse_sk;
  	bool no_reuseport;
  
  	if (udptable != &udp_table)
  		return NULL; /* only UDP is supported */
  
  	no_reuseport = bpf_sk_lookup_run_v6(net, IPPROTO_UDP,
  					    saddr, sport, daddr, hnum, &sk);
  	if (no_reuseport || IS_ERR_OR_NULL(sk))
  		return sk;
  
  	reuse_sk = lookup_reuseport(net, sk, skb, saddr, sport, daddr, hnum);
c64c9c282   Jakub Sitnicki   udp, bpf: Ignore ...
197
  	if (reuse_sk)
6d4201b13   Jakub Sitnicki   udp6: Run SK_LOOK...
198
199
200
  		sk = reuse_sk;
  	return sk;
  }
ca065d0cf   Eric Dumazet   udp: no longer us...
201
  /* rcu_read_lock() must be held */
fce823381   Pavel Emelyanov   udp: Export code ...
202
  struct sock *__udp6_lib_lookup(struct net *net,
1801b570d   David Ahern   net: ipv6: add se...
203
204
205
206
  			       const struct in6_addr *saddr, __be16 sport,
  			       const struct in6_addr *daddr, __be16 dport,
  			       int dif, int sdif, struct udp_table *udptable,
  			       struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
  	unsigned short hnum = ntohs(dport);
23b0269e5   Peter Oskolkov   net: udp6: prefer...
209
210
  	unsigned int hash2, slot2;
  	struct udp_hslot *hslot2;
6d4201b13   Jakub Sitnicki   udp6: Run SK_LOOK...
211
  	struct sock *result, *sk;
645ca708f   Eric Dumazet   udp: introduce st...
212

23b0269e5   Peter Oskolkov   net: udp6: prefer...
213
214
215
  	hash2 = ipv6_portaddr_hash(net, daddr, hnum);
  	slot2 = hash2 & udptable->mask;
  	hslot2 = &udptable->hash2[slot2];
6d4201b13   Jakub Sitnicki   udp6: Run SK_LOOK...
216
  	/* Lookup connected or non-wildcard sockets */
23b0269e5   Peter Oskolkov   net: udp6: prefer...
217
  	result = udp6_lib_lookup2(net, saddr, sport,
735453730   Tim Beale   udp: Remove unuse...
218
  				  daddr, hnum, dif, sdif,
23b0269e5   Peter Oskolkov   net: udp6: prefer...
219
  				  hslot2, skb);
6d4201b13   Jakub Sitnicki   udp6: Run SK_LOOK...
220
221
222
223
224
225
226
227
228
229
230
231
  	if (!IS_ERR_OR_NULL(result) && result->sk_state == TCP_ESTABLISHED)
  		goto done;
  
  	/* Lookup redirect from BPF */
  	if (static_branch_unlikely(&bpf_sk_lookup_enabled)) {
  		sk = udp6_lookup_run_bpf(net, udptable, skb,
  					 saddr, sport, daddr, hnum);
  		if (sk) {
  			result = sk;
  			goto done;
  		}
  	}
23b0269e5   Peter Oskolkov   net: udp6: prefer...
232

6d4201b13   Jakub Sitnicki   udp6: Run SK_LOOK...
233
234
235
  	/* Got non-wildcard socket or error on first lookup */
  	if (result)
  		goto done;
fddc17def   Eric Dumazet   ipv6: udp: optimi...
236

6d4201b13   Jakub Sitnicki   udp6: Run SK_LOOK...
237
238
239
240
241
242
243
244
245
  	/* Lookup wildcard sockets */
  	hash2 = ipv6_portaddr_hash(net, &in6addr_any, hnum);
  	slot2 = hash2 & udptable->mask;
  	hslot2 = &udptable->hash2[slot2];
  
  	result = udp6_lib_lookup2(net, saddr, sport,
  				  &in6addr_any, hnum, dif, sdif,
  				  hslot2, skb);
  done:
26f8113cc   Enrico Weigelt   net: ipv6: drop u...
246
  	if (IS_ERR(result))
23b0269e5   Peter Oskolkov   net: udp6: prefer...
247
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
249
  	return result;
  }
fce823381   Pavel Emelyanov   udp: Export code ...
250
  EXPORT_SYMBOL_GPL(__udp6_lib_lookup);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251

607c4aaf0   KOVACS Krisztian   inet: Add udplib_...
252
253
  static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
  					  __be16 sport, __be16 dport,
645ca708f   Eric Dumazet   udp: introduce st...
254
  					  struct udp_table *udptable)
607c4aaf0   KOVACS Krisztian   inet: Add udplib_...
255
  {
b71d1d426   Eric Dumazet   inet: constify ip...
256
  	const struct ipv6hdr *iph = ipv6_hdr(skb);
607c4aaf0   KOVACS Krisztian   inet: Add udplib_...
257

ed7cbbce5   Alexander Duyck   udp: Resolve NULL...
258
  	return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport,
adf30907d   Eric Dumazet   net: skb->dst acc...
259
  				 &iph->daddr, dport, inet6_iif(skb),
1801b570d   David Ahern   net: ipv6: add se...
260
  				 inet6_sdif(skb), udptable, skb);
607c4aaf0   KOVACS Krisztian   inet: Add udplib_...
261
  }
63058308c   Tom Herbert   udp: Add udp6_lib...
262
263
264
265
  struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
  				 __be16 sport, __be16 dport)
  {
  	const struct ipv6hdr *iph = ipv6_hdr(skb);
63058308c   Tom Herbert   udp: Add udp6_lib...
266

ed7cbbce5   Alexander Duyck   udp: Resolve NULL...
267
  	return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport,
63058308c   Tom Herbert   udp: Add udp6_lib...
268
  				 &iph->daddr, dport, inet6_iif(skb),
257a525fe   Martin KaFai Lau   bpf: udp: Avoid c...
269
  				 inet6_sdif(skb), &udp_table, NULL);
63058308c   Tom Herbert   udp: Add udp6_lib...
270
271
  }
  EXPORT_SYMBOL_GPL(udp6_lib_lookup_skb);
ca065d0cf   Eric Dumazet   udp: no longer us...
272
273
274
  /* Must be called under rcu_read_lock().
   * Does increment socket refcount.
   */
6e86000c2   Arnd Bergmann   netfilter: provid...
275
  #if IS_ENABLED(CONFIG_NF_TPROXY_IPV6) || IS_ENABLED(CONFIG_NF_SOCKET_IPV6)
aa976fc01   Balazs Scheidler   tproxy: added udp...
276
277
278
  struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
  			     const struct in6_addr *daddr, __be16 dport, int dif)
  {
ca065d0cf   Eric Dumazet   udp: no longer us...
279
280
281
  	struct sock *sk;
  
  	sk =  __udp6_lib_lookup(net, saddr, sport, daddr, dport,
1801b570d   David Ahern   net: ipv6: add se...
282
  				dif, 0, &udp_table, NULL);
41c6d650f   Reshetova, Elena   net: convert sock...
283
  	if (sk && !refcount_inc_not_zero(&sk->sk_refcnt))
ca065d0cf   Eric Dumazet   udp: no longer us...
284
285
  		sk = NULL;
  	return sk;
aa976fc01   Balazs Scheidler   tproxy: added udp...
286
287
  }
  EXPORT_SYMBOL_GPL(udp6_lib_lookup);
ca065d0cf   Eric Dumazet   udp: no longer us...
288
  #endif
aa976fc01   Balazs Scheidler   tproxy: added udp...
289

cb891fa6a   Paolo Abeni   udp6: fix jumbogr...
290
291
292
293
294
295
296
297
  /* do not use the scratch area len for jumbogram: their length execeeds the
   * scratch area space; note that the IP6CB flags is still in the first
   * cacheline, so checking for jumbograms is cheap
   */
  static int udp6_skb_len(struct sk_buff *skb)
  {
  	return unlikely(inet6_is_jumbogram(skb)) ? skb->len : udp_skb_len(skb);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298
  /*
67ba4152e   Ian Morris   ipv6: White-space...
299
300
   *	This should be easy, if there is something there we
   *	return it, otherwise we block.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
   */
1b7841404   Ying Xue   net: Remove iocb ...
302
  int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
304
305
306
  		  int noblock, int flags, int *addr_len)
  {
  	struct ipv6_pinfo *np = inet6_sk(sk);
  	struct inet_sock *inet = inet_sk(sk);
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
307
  	struct sk_buff *skb;
59c2cdae2   David S. Miller   Revert "udp: remo...
308
  	unsigned int ulen, copied;
fd69c399c   Paolo Abeni   datagram: remove ...
309
  	int off, err, peeking = flags & MSG_PEEK;
759e5d006   Herbert Xu   [UDP]: Clean up U...
310
  	int is_udplite = IS_UDPLITE(sk);
543fc3fb4   Paolo Abeni   udpv6: add the re...
311
  	struct udp_mib __percpu *mib;
197c949e7   Eric Dumazet   udp: properly sup...
312
  	bool checksum_valid = false;
f26ba1751   Wei Yongjun   udp: Fix the SNMP...
313
  	int is_udp4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
  	if (flags & MSG_ERRQUEUE)
85fbaa750   Hannes Frederic Sowa   inet: fix addr_le...
316
  		return ipv6_recv_error(sk, msg, len, addr_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317

4b340ae20   Brian Haley   IPv6: Complete IP...
318
  	if (np->rxpmtu && np->rxopt.bits.rxpmtu)
85fbaa750   Hannes Frederic Sowa   inet: fix addr_le...
319
  		return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
4b340ae20   Brian Haley   IPv6: Complete IP...
320

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
  try_again:
a0917e0bc   Matthew Dawson   datagram: When pe...
322
  	off = sk_peek_offset(sk, flags);
fd69c399c   Paolo Abeni   datagram: remove ...
323
  	skb = __skb_recv_udp(sk, flags, noblock, &off, &err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
  	if (!skb)
627d2d6b5   samanthakumar   udp: enable MSG_P...
325
  		return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326

cb891fa6a   Paolo Abeni   udp6: fix jumbogr...
327
  	ulen = udp6_skb_len(skb);
59c2cdae2   David S. Miller   Revert "udp: remo...
328
  	copied = len;
627d2d6b5   samanthakumar   udp: enable MSG_P...
329
330
  	if (copied > ulen - off)
  		copied = ulen - off;
59c2cdae2   David S. Miller   Revert "udp: remo...
331
  	else if (copied < ulen)
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
332
  		msg->msg_flags |= MSG_TRUNC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333

f26ba1751   Wei Yongjun   udp: Fix the SNMP...
334
  	is_udp4 = (skb->protocol == htons(ETH_P_IP));
029a37434   Paolo Abeni   udp6: cleanup sta...
335
  	mib = __UDPX_MIB(sk, is_udp4);
f26ba1751   Wei Yongjun   udp: Fix the SNMP...
336

ba4e58eca   Gerrit Renker   [NET]: Supporting...
337
  	/*
759e5d006   Herbert Xu   [UDP]: Clean up U...
338
339
340
  	 * If checksum is needed at all, try to do it while copying the
  	 * data.  If the data is truncated, or if we only want a partial
  	 * coverage checksum (UDP-Lite), do it before the copy.
ba4e58eca   Gerrit Renker   [NET]: Supporting...
341
  	 */
ba4e58eca   Gerrit Renker   [NET]: Supporting...
342

d21dbdfe0   Eric Dumazet   udp: avoid one ca...
343
344
  	if (copied < ulen || peeking ||
  	    (is_udplite && UDP_SKB_CB(skb)->partial_cov)) {
67a51780a   Paolo Abeni   ipv6: udp: levera...
345
346
  		checksum_valid = udp_skb_csum_unnecessary(skb) ||
  				!__udp_lib_checksum_complete(skb);
197c949e7   Eric Dumazet   udp: properly sup...
347
  		if (!checksum_valid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
  			goto csum_copy_err;
ba4e58eca   Gerrit Renker   [NET]: Supporting...
349
  	}
67a51780a   Paolo Abeni   ipv6: udp: levera...
350
351
352
353
354
355
  	if (checksum_valid || udp_skb_csum_unnecessary(skb)) {
  		if (udp_skb_is_linear(skb))
  			err = copy_linear_skb(skb, copied, off, &msg->msg_iter);
  		else
  			err = skb_copy_datagram_msg(skb, off, msg, copied);
  	} else {
627d2d6b5   samanthakumar   udp: enable MSG_P...
356
  		err = skb_copy_and_csum_datagram_msg(skb, off, msg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
358
359
  		if (err == -EINVAL)
  			goto csum_copy_err;
  	}
22911fc58   Eric Dumazet   net: skb_free_dat...
360
  	if (unlikely(err)) {
fd69c399c   Paolo Abeni   datagram: remove ...
361
  		if (!peeking) {
979402b16   Eric Dumazet   udp: increment UD...
362
  			atomic_inc(&sk->sk_drops);
029a37434   Paolo Abeni   udp6: cleanup sta...
363
  			SNMP_INC_STATS(mib, UDP_MIB_INERRORS);
979402b16   Eric Dumazet   udp: increment UD...
364
  		}
850cbaddb   Paolo Abeni   udp: use it's own...
365
  		kfree_skb(skb);
627d2d6b5   samanthakumar   udp: enable MSG_P...
366
  		return err;
22911fc58   Eric Dumazet   net: skb_free_dat...
367
  	}
fd69c399c   Paolo Abeni   datagram: remove ...
368
  	if (!peeking)
029a37434   Paolo Abeni   udp6: cleanup sta...
369
  		SNMP_INC_STATS(mib, UDP_MIB_INDATAGRAMS);
cb75994ec   Wang Chen   [UDP]: Defer InDa...
370

3b885787e   Neil Horman   net: Generalize s...
371
  	sock_recv_ts_and_drops(msg, sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
373
374
  
  	/* Copy the address. */
  	if (msg->msg_name) {
342dfc306   Steffen Hurrle   net: add build-ti...
375
  		DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
  		sin6->sin6_family = AF_INET6;
4bedb4520   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
377
  		sin6->sin6_port = udp_hdr(skb)->source;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
  		sin6->sin6_flowinfo = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379

842df0739   Hannes Frederic Sowa   ipv6: use newly i...
380
  		if (is_udp4) {
b301e82cf   Brian Haley   IPv6: use ipv6_ad...
381
382
  			ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr,
  					       &sin6->sin6_addr);
842df0739   Hannes Frederic Sowa   ipv6: use newly i...
383
384
  			sin6->sin6_scope_id = 0;
  		} else {
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
385
  			sin6->sin6_addr = ipv6_hdr(skb)->saddr;
842df0739   Hannes Frederic Sowa   ipv6: use newly i...
386
387
  			sin6->sin6_scope_id =
  				ipv6_iface_scope_id(&sin6->sin6_addr,
4330487ac   Duan Jiong   net: use inet6_ii...
388
  						    inet6_iif(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
  		}
bceaa9024   Hannes Frederic Sowa   inet: prevent lea...
390
  		*addr_len = sizeof(*sin6);
983695fa6   Daniel Borkmann   bpf: fix unconnec...
391
392
393
394
  
  		if (cgroup_bpf_enabled)
  			BPF_CGROUP_RUN_PROG_UDP6_RECVMSG_LOCK(sk,
  						(struct sockaddr *)sin6);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  	}
4b261c75a   Hannes Frederic Sowa   ipv6: make IPV6_R...
396

bcd1665e3   Paolo Abeni   udp: add support ...
397
398
  	if (udp_sk(sk)->gro_enabled)
  		udp_cmsg_recv(msg, sk, skb);
4b261c75a   Hannes Frederic Sowa   ipv6: make IPV6_R...
399
400
  	if (np->rxopt.all)
  		ip6_datagram_recv_common_ctl(sk, msg, skb);
f26ba1751   Wei Yongjun   udp: Fix the SNMP...
401
  	if (is_udp4) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
  		if (inet->cmsg_flags)
ad959036a   Paolo Abeni   net/sock: add an ...
403
  			ip_cmsg_recv_offset(msg, sk, skb,
10df8e615   Eric Dumazet   udp: fix IP_CHECK...
404
  					    sizeof(struct udphdr), off);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
  	} else {
  		if (np->rxopt.all)
4b261c75a   Hannes Frederic Sowa   ipv6: make IPV6_R...
407
  			ip6_datagram_recv_specific_ctl(sk, msg, skb);
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
408
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409

59c2cdae2   David S. Miller   Revert "udp: remo...
410
  	err = copied;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
  	if (flags & MSG_TRUNC)
759e5d006   Herbert Xu   [UDP]: Clean up U...
412
  		err = ulen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413

850cbaddb   Paolo Abeni   udp: use it's own...
414
  	skb_consume_udp(sk, skb, peeking ? -err : err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
417
  	return err;
  
  csum_copy_err:
2276f58ac   Paolo Abeni   udp: use a separa...
418
419
  	if (!__sk_queue_drop_skb(sk, &udp_sk(sk)->reader_queue, skb, flags,
  				 udp_skb_destructor)) {
029a37434   Paolo Abeni   udp6: cleanup sta...
420
421
  		SNMP_INC_STATS(mib, UDP_MIB_CSUMERRORS);
  		SNMP_INC_STATS(mib, UDP_MIB_INERRORS);
0856f9395   Wei Yongjun   udp: Fix the SNMP...
422
  	}
850cbaddb   Paolo Abeni   udp: use it's own...
423
  	kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424

beb39db59   Eric Dumazet   udp: fix behavior...
425
426
  	/* starting over for a new packet, but check if we need to yield */
  	cond_resched();
9cfaa8def   Xufeng Zhang   udp/recvmsg: Clea...
427
  	msg->msg_flags &= ~MSG_TRUNC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
428
429
  	goto try_again;
  }
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
430
431
432
  DEFINE_STATIC_KEY_FALSE(udpv6_encap_needed_key);
  void udpv6_encap_enable(void)
  {
9c4806014   Paolo Abeni   udp: fix jump lab...
433
  	static_branch_inc(&udpv6_encap_needed_key);
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
434
435
  }
  EXPORT_SYMBOL(udpv6_encap_enable);
e7cc08245   Stefano Brivio   udp: Support for ...
436
437
438
439
440
  /* Handler for tunnels with arbitrary destination ports: no socket lookup, go
   * through error handlers in encapsulations looking for a match.
   */
  static int __udp6_lib_err_encap_no_sk(struct sk_buff *skb,
  				      struct inet6_skb_parm *opt,
424a7cd07   Paolo Abeni   udpv6: fix possib...
441
  				      u8 type, u8 code, int offset, __be32 info)
e7cc08245   Stefano Brivio   udp: Support for ...
442
443
444
445
446
  {
  	int i;
  
  	for (i = 0; i < MAX_IPTUN_ENCAP_OPS; i++) {
  		int (*handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
424a7cd07   Paolo Abeni   udpv6: fix possib...
447
448
  			       u8 type, u8 code, int offset, __be32 info);
  		const struct ip6_tnl_encap_ops *encap;
e7cc08245   Stefano Brivio   udp: Support for ...
449

424a7cd07   Paolo Abeni   udpv6: fix possib...
450
451
  		encap = rcu_dereference(ip6tun_encaps[i]);
  		if (!encap)
e7cc08245   Stefano Brivio   udp: Support for ...
452
  			continue;
424a7cd07   Paolo Abeni   udpv6: fix possib...
453
  		handler = encap->err_handler;
e7cc08245   Stefano Brivio   udp: Support for ...
454
455
456
457
458
459
  		if (handler && !handler(skb, opt, type, code, offset, info))
  			return 0;
  	}
  
  	return -ENOENT;
  }
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
460
461
462
463
464
465
466
  /* Try to match ICMP errors to UDP tunnels by looking up a socket without
   * reversing source and destination port: this will match tunnels that force the
   * same destination port on both endpoints (e.g. VXLAN, GENEVE). Note that
   * lwtunnels might actually break this assumption by being configured with
   * different destination ports on endpoints, in this case we won't be able to
   * trace ICMP messages back to them.
   *
e7cc08245   Stefano Brivio   udp: Support for ...
467
468
469
470
   * If this doesn't match any socket, probe tunnels with arbitrary destination
   * ports (e.g. FoU, GUE): there, the receiving socket is useless, as the port
   * we've sent packets to won't necessarily match the local destination port.
   *
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
471
472
473
   * Then ask the tunnel implementation to match the error against a valid
   * association.
   *
e7cc08245   Stefano Brivio   udp: Support for ...
474
475
   * Return an error if we can't find a match, the socket if we need further
   * processing, zero otherwise.
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
476
477
478
479
480
   */
  static struct sock *__udp6_lib_err_encap(struct net *net,
  					 const struct ipv6hdr *hdr, int offset,
  					 struct udphdr *uh,
  					 struct udp_table *udptable,
e7cc08245   Stefano Brivio   udp: Support for ...
481
482
483
  					 struct sk_buff *skb,
  					 struct inet6_skb_parm *opt,
  					 u8 type, u8 code, __be32 info)
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
484
  {
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
485
  	int network_offset, transport_offset;
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
486
  	struct sock *sk;
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
487
488
489
490
491
492
493
494
  	network_offset = skb_network_offset(skb);
  	transport_offset = skb_transport_offset(skb);
  
  	/* Network header needs to point to the outer IPv6 header inside ICMP */
  	skb_reset_network_header(skb);
  
  	/* Transport header needs to point to the UDP header */
  	skb_set_transport_header(skb, offset);
e7cc08245   Stefano Brivio   udp: Support for ...
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
  	sk = __udp6_lib_lookup(net, &hdr->daddr, uh->source,
  			       &hdr->saddr, uh->dest,
  			       inet6_iif(skb), 0, udptable, skb);
  	if (sk) {
  		int (*lookup)(struct sock *sk, struct sk_buff *skb);
  		struct udp_sock *up = udp_sk(sk);
  
  		lookup = READ_ONCE(up->encap_err_lookup);
  		if (!lookup || lookup(sk, skb))
  			sk = NULL;
  	}
  
  	if (!sk) {
  		sk = ERR_PTR(__udp6_lib_err_encap_no_sk(skb, opt, type, code,
  							offset, info));
  	}
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
511
512
513
  
  	skb_set_transport_header(skb, transport_offset);
  	skb_set_network_header(skb, network_offset);
e7cc08245   Stefano Brivio   udp: Support for ...
514

a36e185e8   Stefano Brivio   udp: Handle ICMP ...
515
516
  	return sk;
  }
32bbd8793   Stefano Brivio   net: Convert prot...
517
518
519
  int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
  		   u8 type, u8 code, int offset, __be32 info,
  		   struct udp_table *udptable)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
521
  {
  	struct ipv6_pinfo *np;
b71d1d426   Eric Dumazet   inet: constify ip...
522
523
524
  	const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
  	const struct in6_addr *saddr = &hdr->saddr;
  	const struct in6_addr *daddr = &hdr->daddr;
67ba4152e   Ian Morris   ipv6: White-space...
525
  	struct udphdr *uh = (struct udphdr *)(skb->data+offset);
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
526
  	bool tunnel = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
  	struct sock *sk;
e0d8c1b73   Wei Wang   ipv6: pass up EMS...
528
  	int harderr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
  	int err;
7304fe468   Duan Jiong   net: fix the coun...
530
  	struct net *net = dev_net(skb->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531

e32ea7e74   Craig Gallek   soreuseport: fast...
532
  	sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source,
4ac30c4b3   Martin KaFai Lau   bpf: udp: ipv6: A...
533
  			       inet6_iif(skb), inet6_sdif(skb), udptable, NULL);
63159f29b   Ian Morris   ipv6: coding styl...
534
  	if (!sk) {
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
535
  		/* No socket for error: try tunnels before discarding */
e7cc08245   Stefano Brivio   udp: Support for ...
536
  		sk = ERR_PTR(-ENOENT);
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
537
538
  		if (static_branch_unlikely(&udpv6_encap_needed_key)) {
  			sk = __udp6_lib_err_encap(net, hdr, offset, uh,
e7cc08245   Stefano Brivio   udp: Support for ...
539
540
541
542
  						  udptable, skb,
  						  opt, type, code, info);
  			if (!sk)
  				return 0;
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
543
  		}
e7cc08245   Stefano Brivio   udp: Support for ...
544
  		if (IS_ERR(sk)) {
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
545
546
  			__ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
  					  ICMP6_MIB_INERRORS);
e7cc08245   Stefano Brivio   udp: Support for ...
547
  			return PTR_ERR(sk);
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
548
  		}
e7cc08245   Stefano Brivio   udp: Support for ...
549

a36e185e8   Stefano Brivio   udp: Handle ICMP ...
550
  		tunnel = true;
7304fe468   Duan Jiong   net: fix the coun...
551
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552

e0d8c1b73   Wei Wang   ipv6: pass up EMS...
553
554
  	harderr = icmpv6_err_convert(type, code, &err);
  	np = inet6_sk(sk);
93b36cf34   Hannes Frederic Sowa   ipv6: support IPV...
555
556
557
  	if (type == ICMPV6_PKT_TOOBIG) {
  		if (!ip6_sk_accept_pmtu(sk))
  			goto out;
81aded246   David S. Miller   ipv6: Handle PMTU...
558
  		ip6_sk_update_pmtu(skb, sk, info);
e0d8c1b73   Wei Wang   ipv6: pass up EMS...
559
560
  		if (np->pmtudisc != IPV6_PMTUDISC_DONT)
  			harderr = 1;
93b36cf34   Hannes Frederic Sowa   ipv6: support IPV...
561
  	}
1a462d189   Duan Jiong   net: udp: do not ...
562
  	if (type == NDISC_REDIRECT) {
a36e185e8   Stefano Brivio   udp: Handle ICMP ...
563
564
565
566
567
568
  		if (tunnel) {
  			ip6_redirect(skb, sock_net(sk), inet6_iif(skb),
  				     sk->sk_mark, sk->sk_uid);
  		} else {
  			ip6_sk_redirect(skb, sk);
  		}
1a462d189   Duan Jiong   net: udp: do not ...
569
570
  		goto out;
  	}
81aded246   David S. Miller   ipv6: Handle PMTU...
571

a36e185e8   Stefano Brivio   udp: Handle ICMP ...
572
573
574
  	/* Tunnels don't have an application socket: don't pass errors back */
  	if (tunnel)
  		goto out;
e0d8c1b73   Wei Wang   ipv6: pass up EMS...
575
576
577
578
  	if (!np->recverr) {
  		if (!harderr || sk->sk_state != TCP_ESTABLISHED)
  			goto out;
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
  		ipv6_icmp_error(sk, skb, err, uh->dest, ntohl(info), (u8 *)(uh+1));
e0d8c1b73   Wei Wang   ipv6: pass up EMS...
580
  	}
b1faf5666   Eric Dumazet   net: sock_queue_e...
581

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
583
584
  	sk->sk_err = err;
  	sk->sk_error_report(sk);
  out:
32bbd8793   Stefano Brivio   net: Convert prot...
585
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
  }
a3f96c47c   Paolo Abeni   udp: make *udp*_q...
587
  static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
f7ad74fef   Benjamin LaHaise   net/ipv6/udp: UDP...
588
589
  {
  	int rc;
efe4208f4   Eric Dumazet   ipv6: make lookup...
590
  	if (!ipv6_addr_any(&sk->sk_v6_daddr)) {
f7ad74fef   Benjamin LaHaise   net/ipv6/udp: UDP...
591
  		sock_rps_save_rxhash(sk, skb);
005ec9743   Shawn Bohrer   udp: Only allow b...
592
  		sk_mark_napi_id(sk, skb);
2c8c56e15   Eric Dumazet   net: introduce SO...
593
  		sk_incoming_cpu_update(sk);
e68b6e50f   Eric Dumazet   udp: enable busy ...
594
595
  	} else {
  		sk_mark_napi_id_once(sk, skb);
005ec9743   Shawn Bohrer   udp: Only allow b...
596
  	}
f7ad74fef   Benjamin LaHaise   net/ipv6/udp: UDP...
597

850cbaddb   Paolo Abeni   udp: use it's own...
598
  	rc = __udp_enqueue_schedule_skb(sk, skb);
f7ad74fef   Benjamin LaHaise   net/ipv6/udp: UDP...
599
600
601
602
603
  	if (rc < 0) {
  		int is_udplite = IS_UDPLITE(sk);
  
  		/* Note that an ENOMEM error is charged twice */
  		if (rc == -ENOMEM)
e61da9e25   Eric Dumazet   udp: prepare for ...
604
  			UDP6_INC_STATS(sock_net(sk),
02c223470   Eric Dumazet   net: udp: rename ...
605
  					 UDP_MIB_RCVBUFERRORS, is_udplite);
e61da9e25   Eric Dumazet   udp: prepare for ...
606
  		UDP6_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
f7ad74fef   Benjamin LaHaise   net/ipv6/udp: UDP...
607
608
609
  		kfree_skb(skb);
  		return -1;
  	}
850cbaddb   Paolo Abeni   udp: use it's own...
610

f7ad74fef   Benjamin LaHaise   net/ipv6/udp: UDP...
611
612
  	return 0;
  }
32bbd8793   Stefano Brivio   net: Convert prot...
613
614
615
  static __inline__ int udpv6_err(struct sk_buff *skb,
  				struct inet6_skb_parm *opt, u8 type,
  				u8 code, int offset, __be32 info)
ba4e58eca   Gerrit Renker   [NET]: Supporting...
616
  {
32bbd8793   Stefano Brivio   net: Convert prot...
617
  	return __udp6_lib_err(skb, opt, type, code, offset, info, &udp_table);
ba4e58eca   Gerrit Renker   [NET]: Supporting...
618
  }
cf329aa42   Paolo Abeni   udp: cope with UD...
619
  static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
620
  {
ba4e58eca   Gerrit Renker   [NET]: Supporting...
621
  	struct udp_sock *up = udp_sk(sk);
b2bf1e265   Wang Chen   [UDP]: Clean up f...
622
  	int is_udplite = IS_UDPLITE(sk);
a18135eb9   David S. Miller   [IPV6]: Add UDP_M...
623

ba4e58eca   Gerrit Renker   [NET]: Supporting...
624
625
  	if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
  		goto drop;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626

88ab31081   Davidlohr Bueso   net/udp: Update u...
627
  	if (static_branch_unlikely(&udpv6_encap_needed_key) && up->encap_type) {
d7f3f6216   Benjamin LaHaise   net/ipv6/udp: UDP...
628
629
630
631
632
633
634
635
636
637
638
639
640
641
  		int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
  
  		/*
  		 * This is an encapsulation socket so pass the skb to
  		 * the socket's udp_encap_rcv() hook. Otherwise, just
  		 * fall through and pass this up the UDP socket.
  		 * up->encap_rcv() returns the following value:
  		 * =0 if skb was successfully passed to the encap
  		 *    handler or was discarded by it.
  		 * >0 if skb should be passed on to UDP.
  		 * <0 if skb should be resubmitted as proto -N
  		 */
  
  		/* if we're overly short, let UDP handle it */
6aa7de059   Mark Rutland   locking/atomics: ...
642
  		encap_rcv = READ_ONCE(up->encap_rcv);
e5aed006b   Hannes Frederic Sowa   udp: prevent skbs...
643
  		if (encap_rcv) {
d7f3f6216   Benjamin LaHaise   net/ipv6/udp: UDP...
644
  			int ret;
0a80966b1   Tom Herbert   net: Verify UDP c...
645
646
647
  			/* Verify checksum before giving to encap */
  			if (udp_lib_checksum_complete(skb))
  				goto csum_error;
d7f3f6216   Benjamin LaHaise   net/ipv6/udp: UDP...
648
649
  			ret = encap_rcv(sk, skb);
  			if (ret <= 0) {
02c223470   Eric Dumazet   net: udp: rename ...
650
651
652
  				__UDP_INC_STATS(sock_net(sk),
  						UDP_MIB_INDATAGRAMS,
  						is_udplite);
d7f3f6216   Benjamin LaHaise   net/ipv6/udp: UDP...
653
654
655
656
657
658
  				return -ret;
  			}
  		}
  
  		/* FALLTHROUGH -- it's a UDP Packet */
  	}
ba4e58eca   Gerrit Renker   [NET]: Supporting...
659
660
661
  	/*
  	 * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c).
  	 */
b0a422772   Miaohe Lin   net: udp: Fix wro...
662
  	if ((up->pcflag & UDPLITE_RECV_CC)  &&  UDP_SKB_CB(skb)->partial_cov) {
ba4e58eca   Gerrit Renker   [NET]: Supporting...
663
664
  
  		if (up->pcrlen == 0) {          /* full coverage was set  */
ba7a46f16   Joe Perches   net: Convert LIMI...
665
666
667
  			net_dbg_ratelimited("UDPLITE6: partial coverage %d while full coverage %d requested
  ",
  					    UDP_SKB_CB(skb)->cscov, skb->len);
ba4e58eca   Gerrit Renker   [NET]: Supporting...
668
669
670
  			goto drop;
  		}
  		if (UDP_SKB_CB(skb)->cscov  <  up->pcrlen) {
ba7a46f16   Joe Perches   net: Convert LIMI...
671
672
673
  			net_dbg_ratelimited("UDPLITE6: coverage %d too small, need min %d
  ",
  					    UDP_SKB_CB(skb)->cscov, up->pcrlen);
ba4e58eca   Gerrit Renker   [NET]: Supporting...
674
675
  			goto drop;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
  	}
4b943faed   Paolo Abeni   udp/v6: prefetch ...
677
  	prefetch(&sk->sk_rmem_alloc);
ce25d66ad   Eric Dumazet   Possible problem ...
678
679
680
  	if (rcu_access_pointer(sk->sk_filter) &&
  	    udp_lib_checksum_complete(skb))
  		goto csum_error;
ba66bbe54   Daniel Borkmann   udp: use sk_filte...
681
  	if (sk_filter_trim_cap(sk, skb, sizeof(struct udphdr)))
a61276977   Michal Kubeček   udp: prevent bugc...
682
  		goto drop;
ba4e58eca   Gerrit Renker   [NET]: Supporting...
683

e6afc8ace   samanthakumar   udp: remove heade...
684
  	udp_csum_pull_header(skb);
cb80ef463   Benjamin LaHaise   net/ipv6/udp: UDP...
685

d826eb14e   Eric Dumazet   ipv4: PKTINFO doe...
686
  	skb_dst_drop(skb);
cb75994ec   Wang Chen   [UDP]: Defer InDa...
687

850cbaddb   Paolo Abeni   udp: use it's own...
688
  	return __udpv6_queue_rcv_skb(sk, skb);
3e215c8d1   James M Leddy   udp: Add MIB coun...
689

6a5dc9e59   Eric Dumazet   net: Add MIB coun...
690
  csum_error:
02c223470   Eric Dumazet   net: udp: rename ...
691
  	__UDP6_INC_STATS(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite);
ba4e58eca   Gerrit Renker   [NET]: Supporting...
692
  drop:
02c223470   Eric Dumazet   net: udp: rename ...
693
  	__UDP6_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
cb80ef463   Benjamin LaHaise   net/ipv6/udp: UDP...
694
  	atomic_inc(&sk->sk_drops);
ba4e58eca   Gerrit Renker   [NET]: Supporting...
695
696
  	kfree_skb(skb);
  	return -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
  }
cf329aa42   Paolo Abeni   udp: cope with UD...
698
699
700
701
702
703
704
705
706
707
  static int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
  {
  	struct sk_buff *next, *segs;
  	int ret;
  
  	if (likely(!udp_unexpected_gso(sk, skb)))
  		return udpv6_queue_rcv_one_skb(sk, skb);
  
  	__skb_push(skb, -skb_mac_offset(skb));
  	segs = udp_rcv_segment(sk, skb, false);
1a186c14c   Jason A. Donenfeld   net: udp: use skb...
708
  	skb_list_walk_safe(segs, skb, next) {
cf329aa42   Paolo Abeni   udp: cope with UD...
709
710
711
712
713
714
715
716
717
  		__skb_pull(skb, skb_transport_offset(skb));
  
  		ret = udpv6_queue_rcv_one_skb(sk, skb);
  		if (ret > 0)
  			ip6_protocol_deliver_rcu(dev_net(skb->dev), skb, ret,
  						 true);
  	}
  	return 0;
  }
5cf3d4619   David Held   udp: Simplify __u...
718
719
720
  static bool __udp_v6_is_mcast_sock(struct net *net, struct sock *sk,
  				   __be16 loc_port, const struct in6_addr *loc_addr,
  				   __be16 rmt_port, const struct in6_addr *rmt_addr,
7bd2db404   Dewi Morgan   ipv6: do not drop...
721
  				   int dif, int sdif, unsigned short hnum)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
  {
5cf3d4619   David Held   udp: Simplify __u...
723
  	struct inet_sock *inet = inet_sk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724

5cf3d4619   David Held   udp: Simplify __u...
725
726
727
728
729
730
731
732
  	if (!net_eq(sock_net(sk), net))
  		return false;
  
  	if (udp_sk(sk)->udp_port_hash != hnum ||
  	    sk->sk_family != PF_INET6 ||
  	    (inet->inet_dport && inet->inet_dport != rmt_port) ||
  	    (!ipv6_addr_any(&sk->sk_v6_daddr) &&
  		    !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) ||
7bd2db404   Dewi Morgan   ipv6: do not drop...
733
  	    !udp_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif) ||
33b4b015e   Henning Rogge   net/ipv6/udp: Fix...
734
735
  	    (!ipv6_addr_any(&sk->sk_v6_rcv_saddr) &&
  		    !ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr)))
5cf3d4619   David Held   udp: Simplify __u...
736
737
738
739
  		return false;
  	if (!inet6_mc_check(sk, loc_addr, rmt_addr))
  		return false;
  	return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
740
  }
4068579e1   Tom Herbert   net: Implmement R...
741
742
743
744
745
  static void udp6_csum_zero_error(struct sk_buff *skb)
  {
  	/* RFC 2460 section 8.1 says that we SHOULD log
  	 * this error. Well, it is reasonable.
  	 */
ba7a46f16   Joe Perches   net: Convert LIMI...
746
747
748
749
  	net_dbg_ratelimited("IPv6: udp checksum is 0 for [%pI6c]:%u->[%pI6c]:%u
  ",
  			    &ipv6_hdr(skb)->saddr, ntohs(udp_hdr(skb)->source),
  			    &ipv6_hdr(skb)->daddr, ntohs(udp_hdr(skb)->dest));
4068579e1   Tom Herbert   net: Implmement R...
750
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
751
752
753
754
  /*
   * Note: called only from the BH handler context,
   * so we don't need to lock the hashes.
   */
e31634931   Pavel Emelyanov   udp: provide a st...
755
  static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
b71d1d426   Eric Dumazet   inet: constify ip...
756
  		const struct in6_addr *saddr, const struct in6_addr *daddr,
36cbb2452   Rick Jones   udp: Increment UD...
757
  		struct udp_table *udptable, int proto)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758
  {
ca065d0cf   Eric Dumazet   udp: no longer us...
759
  	struct sock *sk, *first = NULL;
4bedb4520   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
760
  	const struct udphdr *uh = udp_hdr(skb);
5cf3d4619   David Held   udp: Simplify __u...
761
762
  	unsigned short hnum = ntohs(uh->dest);
  	struct udp_hslot *hslot = udp_hashslot(udptable, net, hnum);
ca065d0cf   Eric Dumazet   udp: no longer us...
763
  	unsigned int offset = offsetof(typeof(*sk), sk_node);
2dc41cff7   David Held   udp: Use hash2 fo...
764
  	unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10);
ca065d0cf   Eric Dumazet   udp: no longer us...
765
  	int dif = inet6_iif(skb);
7bd2db404   Dewi Morgan   ipv6: do not drop...
766
  	int sdif = inet6_sdif(skb);
ca065d0cf   Eric Dumazet   udp: no longer us...
767
768
  	struct hlist_node *node;
  	struct sk_buff *nskb;
2dc41cff7   David Held   udp: Use hash2 fo...
769
770
  
  	if (use_hash2) {
f0b1e64c1   Martin KaFai Lau   udp: Move udp[46]...
771
  		hash2_any = ipv6_portaddr_hash(net, &in6addr_any, hnum) &
73e2d5e34   Pablo Neira   udp: restore UDPl...
772
  			    udptable->mask;
f0b1e64c1   Martin KaFai Lau   udp: Move udp[46]...
773
  		hash2 = ipv6_portaddr_hash(net, daddr, hnum) & udptable->mask;
2dc41cff7   David Held   udp: Use hash2 fo...
774
  start_lookup:
73e2d5e34   Pablo Neira   udp: restore UDPl...
775
  		hslot = &udptable->hash2[hash2];
2dc41cff7   David Held   udp: Use hash2 fo...
776
777
  		offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
778

ca065d0cf   Eric Dumazet   udp: no longer us...
779
780
  	sk_for_each_entry_offset_rcu(sk, node, &hslot->head, offset) {
  		if (!__udp_v6_is_mcast_sock(net, sk, uh->dest, daddr,
7bd2db404   Dewi Morgan   ipv6: do not drop...
781
782
  					    uh->source, saddr, dif, sdif,
  					    hnum))
ca065d0cf   Eric Dumazet   udp: no longer us...
783
784
785
786
787
788
789
790
791
792
793
794
795
  			continue;
  		/* If zero checksum and no_check is not on for
  		 * the socket then skip it.
  		 */
  		if (!uh->check && !udp_sk(sk)->no_check6_rx)
  			continue;
  		if (!first) {
  			first = sk;
  			continue;
  		}
  		nskb = skb_clone(skb, GFP_ATOMIC);
  		if (unlikely(!nskb)) {
  			atomic_inc(&sk->sk_drops);
02c223470   Eric Dumazet   net: udp: rename ...
796
797
798
799
  			__UDP6_INC_STATS(net, UDP_MIB_RCVBUFERRORS,
  					 IS_UDPLITE(sk));
  			__UDP6_INC_STATS(net, UDP_MIB_INERRORS,
  					 IS_UDPLITE(sk));
ca065d0cf   Eric Dumazet   udp: no longer us...
800
  			continue;
95766fff6   Hideo Aoki   [UDP]: Add memory...
801
  		}
a1ab77f97   Eric Dumazet   ipv6: udp: Optimi...
802

ca065d0cf   Eric Dumazet   udp: no longer us...
803
804
805
  		if (udpv6_queue_rcv_skb(sk, nskb) > 0)
  			consume_skb(nskb);
  	}
a1ab77f97   Eric Dumazet   ipv6: udp: Optimi...
806

2dc41cff7   David Held   udp: Use hash2 fo...
807
808
809
810
811
  	/* Also lookup *:port if we are using hash2 and haven't done so yet. */
  	if (use_hash2 && hash2 != hash2_any) {
  		hash2 = hash2_any;
  		goto start_lookup;
  	}
ca065d0cf   Eric Dumazet   udp: no longer us...
812
813
814
  	if (first) {
  		if (udpv6_queue_rcv_skb(first, skb) > 0)
  			consume_skb(skb);
a1ab77f97   Eric Dumazet   ipv6: udp: Optimi...
815
  	} else {
ca065d0cf   Eric Dumazet   udp: no longer us...
816
  		kfree_skb(skb);
02c223470   Eric Dumazet   net: udp: rename ...
817
818
  		__UDP6_INC_STATS(net, UDP_MIB_IGNOREDMULTI,
  				 proto == IPPROTO_UDPLITE);
a1ab77f97   Eric Dumazet   ipv6: udp: Optimi...
819
  	}
ba4e58eca   Gerrit Renker   [NET]: Supporting...
820
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
821
  }
64f0f5d18   Paolo Abeni   udp6: set rx_dst_...
822
823
824
825
826
827
828
829
  static void udp6_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)
  {
  	if (udp_sk_rx_dst_set(sk, dst)) {
  		const struct rt6_info *rt = (const struct rt6_info *)dst;
  
  		inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt);
  	}
  }
eb63f2964   Paolo Abeni   udp6: add missing...
830
831
832
833
834
835
836
837
838
  /* wrapper for udp_queue_rcv_skb tacking care of csum conversion and
   * return code conversion for ip layer consumption
   */
  static int udp6_unicast_rcv_skb(struct sock *sk, struct sk_buff *skb,
  				struct udphdr *uh)
  {
  	int ret;
  
  	if (inet_get_convert_csum(sk) && uh->check && !IS_UDPLITE(sk))
e4aa33ad5   Li RongQing   net: remove unuse...
839
  		skb_checksum_try_convert(skb, IPPROTO_UDP, ip6_compute_pseudo);
eb63f2964   Paolo Abeni   udp6: add missing...
840
841
  
  	ret = udpv6_queue_rcv_skb(sk, skb);
84dad5595   Paolo Abeni   udp6: fix encap r...
842
  	/* a return value > 0 means to resubmit the input */
eb63f2964   Paolo Abeni   udp6: add missing...
843
  	if (ret > 0)
84dad5595   Paolo Abeni   udp6: fix encap r...
844
  		return ret;
eb63f2964   Paolo Abeni   udp6: add missing...
845
846
  	return 0;
  }
645ca708f   Eric Dumazet   udp: introduce st...
847
  int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
759e5d006   Herbert Xu   [UDP]: Clean up U...
848
  		   int proto)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
849
  {
ca065d0cf   Eric Dumazet   udp: no longer us...
850
  	const struct in6_addr *saddr, *daddr;
3ffe533c8   Alexey Dobriyan   ipv6: drop unused...
851
  	struct net *net = dev_net(skb->dev);
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
852
  	struct udphdr *uh;
ca065d0cf   Eric Dumazet   udp: no longer us...
853
  	struct sock *sk;
71489e21d   Joe Stringer   net: Track socket...
854
  	bool refcounted;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
856
857
  	u32 ulen = 0;
  
  	if (!pskb_may_pull(skb, sizeof(struct udphdr)))
d6bc0149d   Bjørn Mork   ipv6: udp: make s...
858
  		goto discard;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859

0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
860
861
  	saddr = &ipv6_hdr(skb)->saddr;
  	daddr = &ipv6_hdr(skb)->daddr;
4bedb4520   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
862
  	uh = udp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
863
864
  
  	ulen = ntohs(uh->len);
ba4e58eca   Gerrit Renker   [NET]: Supporting...
865
866
  	if (ulen > skb->len)
  		goto short_packet;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867

759e5d006   Herbert Xu   [UDP]: Clean up U...
868
869
  	if (proto == IPPROTO_UDP) {
  		/* UDP validates ulen. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
870

ba4e58eca   Gerrit Renker   [NET]: Supporting...
871
872
873
  		/* Check for jumbo payload */
  		if (ulen == 0)
  			ulen = skb->len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874

ba4e58eca   Gerrit Renker   [NET]: Supporting...
875
876
  		if (ulen < sizeof(*uh))
  			goto short_packet;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
877

ba4e58eca   Gerrit Renker   [NET]: Supporting...
878
879
880
  		if (ulen < skb->len) {
  			if (pskb_trim_rcsum(skb, ulen))
  				goto short_packet;
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
881
882
  			saddr = &ipv6_hdr(skb)->saddr;
  			daddr = &ipv6_hdr(skb)->daddr;
4bedb4520   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
883
  			uh = udp_hdr(skb);
ba4e58eca   Gerrit Renker   [NET]: Supporting...
884
  		}
ba4e58eca   Gerrit Renker   [NET]: Supporting...
885
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
886

759e5d006   Herbert Xu   [UDP]: Clean up U...
887
  	if (udp6_csum_init(skb, uh, proto))
6a5dc9e59   Eric Dumazet   net: Add MIB coun...
888
  		goto csum_error;
759e5d006   Herbert Xu   [UDP]: Clean up U...
889

c9f2c1ae1   Paolo Abeni   udp6: fix socket ...
890
  	/* Check if the socket is already available, e.g. due to early demux */
71489e21d   Joe Stringer   net: Track socket...
891
  	sk = skb_steal_sock(skb, &refcounted);
c9f2c1ae1   Paolo Abeni   udp6: fix socket ...
892
893
894
895
896
  	if (sk) {
  		struct dst_entry *dst = skb_dst(skb);
  		int ret;
  
  		if (unlikely(sk->sk_rx_dst != dst))
64f0f5d18   Paolo Abeni   udp6: set rx_dst_...
897
  			udp6_sk_rx_dst_set(sk, dst);
c9f2c1ae1   Paolo Abeni   udp6: fix socket ...
898

eb63f2964   Paolo Abeni   udp6: add missing...
899
  		if (!uh->check && !udp_sk(sk)->no_check6_rx) {
71489e21d   Joe Stringer   net: Track socket...
900
901
  			if (refcounted)
  				sock_put(sk);
eb63f2964   Paolo Abeni   udp6: add missing...
902
903
  			goto report_csum_error;
  		}
c9f2c1ae1   Paolo Abeni   udp6: fix socket ...
904

eb63f2964   Paolo Abeni   udp6: add missing...
905
  		ret = udp6_unicast_rcv_skb(sk, skb, uh);
71489e21d   Joe Stringer   net: Track socket...
906
907
  		if (refcounted)
  			sock_put(sk);
eb63f2964   Paolo Abeni   udp6: add missing...
908
  		return ret;
c9f2c1ae1   Paolo Abeni   udp6: fix socket ...
909
  	}
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
910
911
  	/*
  	 *	Multicast receive code
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
  	 */
ba4e58eca   Gerrit Renker   [NET]: Supporting...
913
  	if (ipv6_addr_is_multicast(daddr))
e31634931   Pavel Emelyanov   udp: provide a st...
914
  		return __udp6_lib_mcast_deliver(net, skb,
36cbb2452   Rick Jones   udp: Increment UD...
915
  				saddr, daddr, udptable, proto);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916
917
  
  	/* Unicast */
607c4aaf0   KOVACS Krisztian   inet: Add udplib_...
918
  	sk = __udp6_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
53b24b8f9   Ian Morris   ipv6: coding styl...
919
  	if (sk) {
eb63f2964   Paolo Abeni   udp6: add missing...
920
921
922
  		if (!uh->check && !udp_sk(sk)->no_check6_rx)
  			goto report_csum_error;
  		return udp6_unicast_rcv_skb(sk, skb, uh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
923
  	}
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
924

eb63f2964   Paolo Abeni   udp6: add missing...
925
926
  	if (!uh->check)
  		goto report_csum_error;
4068579e1   Tom Herbert   net: Implmement R...
927

cb80ef463   Benjamin LaHaise   net/ipv6/udp: UDP...
928
  	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
c377411f2   Eric Dumazet   net: sk_add_backl...
929
  		goto discard;
cb80ef463   Benjamin LaHaise   net/ipv6/udp: UDP...
930
931
  
  	if (udp_lib_checksum_complete(skb))
6a5dc9e59   Eric Dumazet   net: Add MIB coun...
932
  		goto csum_error;
cb80ef463   Benjamin LaHaise   net/ipv6/udp: UDP...
933

02c223470   Eric Dumazet   net: udp: rename ...
934
  	__UDP6_INC_STATS(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE);
cb80ef463   Benjamin LaHaise   net/ipv6/udp: UDP...
935
936
937
  	icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
  
  	kfree_skb(skb);
add459aa1   Stephen Hemminger   [UDP]: ipv6 style...
938
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939

1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
940
  short_packet:
ba7a46f16   Joe Perches   net: Convert LIMI...
941
942
943
944
945
946
  	net_dbg_ratelimited("UDP%sv6: short packet: From [%pI6c]:%u %d/%d to [%pI6c]:%u
  ",
  			    proto == IPPROTO_UDPLITE ? "-Lite" : "",
  			    saddr, ntohs(uh->source),
  			    ulen, skb->len,
  			    daddr, ntohs(uh->dest));
6a5dc9e59   Eric Dumazet   net: Add MIB coun...
947
  	goto discard;
eb63f2964   Paolo Abeni   udp6: add missing...
948
949
950
  
  report_csum_error:
  	udp6_csum_zero_error(skb);
6a5dc9e59   Eric Dumazet   net: Add MIB coun...
951
  csum_error:
02c223470   Eric Dumazet   net: udp: rename ...
952
  	__UDP6_INC_STATS(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
  discard:
02c223470   Eric Dumazet   net: udp: rename ...
954
  	__UDP6_INC_STATS(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955
  	kfree_skb(skb);
add459aa1   Stephen Hemminger   [UDP]: ipv6 style...
956
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957
  }
ba4e58eca   Gerrit Renker   [NET]: Supporting...
958

0bd84065b   subashab@codeaurora.org   net: ipv6: Fix UD...
959

5425077d7   subashab@codeaurora.org   net: ipv6: Add ea...
960
961
962
  static struct sock *__udp6_lib_demux_lookup(struct net *net,
  			__be16 loc_port, const struct in6_addr *loc_addr,
  			__be16 rmt_port, const struct in6_addr *rmt_addr,
4297a0ef0   David Ahern   net: ipv6: add se...
963
  			int dif, int sdif)
5425077d7   subashab@codeaurora.org   net: ipv6: Add ea...
964
  {
0bd84065b   subashab@codeaurora.org   net: ipv6: Fix UD...
965
  	unsigned short hnum = ntohs(loc_port);
f0b1e64c1   Martin KaFai Lau   udp: Move udp[46]...
966
  	unsigned int hash2 = ipv6_portaddr_hash(net, loc_addr, hnum);
0bd84065b   subashab@codeaurora.org   net: ipv6: Fix UD...
967
968
969
  	unsigned int slot2 = hash2 & udp_table.mask;
  	struct udp_hslot *hslot2 = &udp_table.hash2[slot2];
  	const __portpair ports = INET_COMBINED_PORTS(rmt_port, hnum);
5425077d7   subashab@codeaurora.org   net: ipv6: Add ea...
970
  	struct sock *sk;
0bd84065b   subashab@codeaurora.org   net: ipv6: Fix UD...
971
  	udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
85cb73ff9   Wei Wang   net: ipv6: reset ...
972
  		if (sk->sk_state == TCP_ESTABLISHED &&
4297a0ef0   David Ahern   net: ipv6: add se...
973
  		    INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif, sdif))
0bd84065b   subashab@codeaurora.org   net: ipv6: Fix UD...
974
975
976
977
978
  			return sk;
  		/* Only check first socket in chain */
  		break;
  	}
  	return NULL;
5425077d7   subashab@codeaurora.org   net: ipv6: Add ea...
979
  }
97ff7ffb1   Paolo Abeni   net: use indirect...
980
  INDIRECT_CALLABLE_SCOPE void udp_v6_early_demux(struct sk_buff *skb)
5425077d7   subashab@codeaurora.org   net: ipv6: Add ea...
981
982
983
984
985
986
  {
  	struct net *net = dev_net(skb->dev);
  	const struct udphdr *uh;
  	struct sock *sk;
  	struct dst_entry *dst;
  	int dif = skb->dev->ifindex;
4297a0ef0   David Ahern   net: ipv6: add se...
987
  	int sdif = inet6_sdif(skb);
5425077d7   subashab@codeaurora.org   net: ipv6: Add ea...
988
989
990
991
992
993
994
995
996
997
998
  
  	if (!pskb_may_pull(skb, skb_transport_offset(skb) +
  	    sizeof(struct udphdr)))
  		return;
  
  	uh = udp_hdr(skb);
  
  	if (skb->pkt_type == PACKET_HOST)
  		sk = __udp6_lib_demux_lookup(net, uh->dest,
  					     &ipv6_hdr(skb)->daddr,
  					     uh->source, &ipv6_hdr(skb)->saddr,
4297a0ef0   David Ahern   net: ipv6: add se...
999
  					     dif, sdif);
5425077d7   subashab@codeaurora.org   net: ipv6: Add ea...
1000
1001
  	else
  		return;
41c6d650f   Reshetova, Elena   net: convert sock...
1002
  	if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt))
5425077d7   subashab@codeaurora.org   net: ipv6: Add ea...
1003
1004
1005
1006
1007
1008
1009
1010
1011
  		return;
  
  	skb->sk = sk;
  	skb->destructor = sock_efree;
  	dst = READ_ONCE(sk->sk_rx_dst);
  
  	if (dst)
  		dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);
  	if (dst) {
d24406c85   Wei Wang   udp: call dst_hol...
1012
1013
1014
1015
1016
  		/* set noref for now.
  		 * any place which wants to hold dst has to call
  		 * dst_hold_safe()
  		 */
  		skb_dst_set_noref(skb, dst);
5425077d7   subashab@codeaurora.org   net: ipv6: Add ea...
1017
1018
  	}
  }
0e219ae48   Paolo Abeni   net: use indirect...
1019
  INDIRECT_CALLABLE_SCOPE int udpv6_rcv(struct sk_buff *skb)
ba4e58eca   Gerrit Renker   [NET]: Supporting...
1020
  {
645ca708f   Eric Dumazet   udp: introduce st...
1021
  	return __udp6_lib_rcv(skb, &udp_table, IPPROTO_UDP);
ba4e58eca   Gerrit Renker   [NET]: Supporting...
1022
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
1024
1025
1026
1027
1028
  /*
   * Throw away all pending data and cancel the corking. Socket is locked.
   */
  static void udp_v6_flush_pending_frames(struct sock *sk)
  {
  	struct udp_sock *up = udp_sk(sk);
36d926b94   Denis V. Lunev   [IPV6]: inet_sk(s...
1029
1030
1031
  	if (up->pending == AF_INET)
  		udp_flush_pending_frames(sk);
  	else if (up->pending) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1032
1033
1034
  		up->len = 0;
  		up->pending = 0;
  		ip6_flush_pending_frames(sk);
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1035
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
  }
d74bad4e7   Andrey Ignatov   bpf: Hooks for sy...
1037
1038
1039
  static int udpv6_pre_connect(struct sock *sk, struct sockaddr *uaddr,
  			     int addr_len)
  {
bddc028a4   Tetsuo Handa   udpv6: Check addr...
1040
1041
  	if (addr_len < offsetofend(struct sockaddr, sa_family))
  		return -EINVAL;
d74bad4e7   Andrey Ignatov   bpf: Hooks for sy...
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
  	/* The following checks are replicated from __ip6_datagram_connect()
  	 * and intended to prevent BPF program called below from accessing
  	 * bytes that are out of the bound specified by user in addr_len.
  	 */
  	if (uaddr->sa_family == AF_INET) {
  		if (__ipv6_only_sock(sk))
  			return -EAFNOSUPPORT;
  		return udp_pre_connect(sk, uaddr, addr_len);
  	}
  
  	if (addr_len < SIN6_LEN_RFC2133)
  		return -EINVAL;
  
  	return BPF_CGROUP_RUN_PROG_INET6_CONNECT_LOCK(sk, uaddr);
  }
493c6be3f   Sridhar Samudrala   udpv6: Fix HW che...
1057
  /**
67ba4152e   Ian Morris   ipv6: White-space...
1058
1059
1060
1061
   *	udp6_hwcsum_outgoing  -  handle outgoing HW checksumming
   *	@sk:	socket we are sending on
   *	@skb:	sk_buff containing the filled-in UDP header
   *		(checksum field must be zeroed out)
b51cd7c83   Andrew Lunn   net: ipv6: kernel...
1062
1063
1064
   *	@saddr: source address
   *	@daddr: destination address
   *	@len:	length of packet
493c6be3f   Sridhar Samudrala   udpv6: Fix HW che...
1065
1066
1067
1068
1069
1070
1071
   */
  static void udp6_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
  				 const struct in6_addr *saddr,
  				 const struct in6_addr *daddr, int len)
  {
  	unsigned int offset;
  	struct udphdr *uh = udp_hdr(skb);
d39d938c8   Vlad Yasevich   ipv6: Introduce u...
1072
  	struct sk_buff *frags = skb_shinfo(skb)->frag_list;
493c6be3f   Sridhar Samudrala   udpv6: Fix HW che...
1073
  	__wsum csum = 0;
d39d938c8   Vlad Yasevich   ipv6: Introduce u...
1074
  	if (!frags) {
493c6be3f   Sridhar Samudrala   udpv6: Fix HW che...
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
  		/* Only one fragment on the socket.  */
  		skb->csum_start = skb_transport_header(skb) - skb->head;
  		skb->csum_offset = offsetof(struct udphdr, check);
  		uh->check = ~csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, 0);
  	} else {
  		/*
  		 * HW-checksum won't work as there are two or more
  		 * fragments on the socket so that all csums of sk_buffs
  		 * should be together
  		 */
  		offset = skb_transport_offset(skb);
  		skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
63ecc3d94   Subash Abhinov Kasiviswanathan   udpv6: Fix the ch...
1087
  		csum = skb->csum;
493c6be3f   Sridhar Samudrala   udpv6: Fix HW che...
1088
1089
  
  		skb->ip_summed = CHECKSUM_NONE;
d39d938c8   Vlad Yasevich   ipv6: Introduce u...
1090
1091
1092
  		do {
  			csum = csum_add(csum, frags->csum);
  		} while ((frags = frags->next));
493c6be3f   Sridhar Samudrala   udpv6: Fix HW che...
1093
1094
1095
1096
1097
1098
1099
  
  		uh->check = csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP,
  					    csum);
  		if (uh->check == 0)
  			uh->check = CSUM_MANGLED_0;
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1100
1101
1102
  /*
   *	Sending
   */
bec1f6f69   Willem de Bruijn   udp: generate gso...
1103
1104
  static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
  			   struct inet_cork *cork)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1105
  {
d39d938c8   Vlad Yasevich   ipv6: Introduce u...
1106
  	struct sock *sk = skb->sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1107
  	struct udphdr *uh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108
  	int err = 0;
b2bf1e265   Wang Chen   [UDP]: Clean up f...
1109
  	int is_udplite = IS_UDPLITE(sk);
868c86bcb   Al Viro   [NET]: annotate c...
1110
  	__wsum csum = 0;
d39d938c8   Vlad Yasevich   ipv6: Introduce u...
1111
1112
  	int offset = skb_transport_offset(skb);
  	int len = skb->len - offset;
4094871db   Josh Hunt   udp: only do GSO ...
1113
  	int datalen = len - sizeof(*uh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1114
1115
1116
1117
  
  	/*
  	 * Create a UDP header
  	 */
4bedb4520   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1118
  	uh = udp_hdr(skb);
1958b856c   David S. Miller   net: Put fl6_* ma...
1119
1120
  	uh->source = fl6->fl6_sport;
  	uh->dest = fl6->fl6_dport;
d39d938c8   Vlad Yasevich   ipv6: Introduce u...
1121
  	uh->len = htons(len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1122
  	uh->check = 0;
bec1f6f69   Willem de Bruijn   udp: generate gso...
1123
1124
1125
  	if (cork->gso_size) {
  		const int hlen = skb_network_header_len(skb) +
  				 sizeof(struct udphdr);
0f149c9fe   Willem de Bruijn   udp: with udp_seg...
1126
1127
  		if (hlen + cork->gso_size > cork->fragsize) {
  			kfree_skb(skb);
bec1f6f69   Willem de Bruijn   udp: generate gso...
1128
  			return -EINVAL;
0f149c9fe   Willem de Bruijn   udp: with udp_seg...
1129
1130
1131
  		}
  		if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) {
  			kfree_skb(skb);
bec1f6f69   Willem de Bruijn   udp: generate gso...
1132
  			return -EINVAL;
0f149c9fe   Willem de Bruijn   udp: with udp_seg...
1133
1134
1135
  		}
  		if (udp_sk(sk)->no_check6_tx) {
  			kfree_skb(skb);
a8c744a8b   Willem de Bruijn   udp: disable gso ...
1136
  			return -EINVAL;
0f149c9fe   Willem de Bruijn   udp: with udp_seg...
1137
  		}
ff06342cb   Willem de Bruijn   udp: exclude gso ...
1138
  		if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
0f149c9fe   Willem de Bruijn   udp: with udp_seg...
1139
1140
  		    dst_xfrm(skb_dst(skb))) {
  			kfree_skb(skb);
bec1f6f69   Willem de Bruijn   udp: generate gso...
1141
  			return -EIO;
0f149c9fe   Willem de Bruijn   udp: with udp_seg...
1142
  		}
bec1f6f69   Willem de Bruijn   udp: generate gso...
1143

4094871db   Josh Hunt   udp: only do GSO ...
1144
1145
1146
1147
1148
1149
  		if (datalen > cork->gso_size) {
  			skb_shinfo(skb)->gso_size = cork->gso_size;
  			skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
  			skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(datalen,
  								 cork->gso_size);
  		}
a8c744a8b   Willem de Bruijn   udp: disable gso ...
1150
  		goto csum_partial;
bec1f6f69   Willem de Bruijn   udp: generate gso...
1151
  	}
b2bf1e265   Wang Chen   [UDP]: Clean up f...
1152
  	if (is_udplite)
d39d938c8   Vlad Yasevich   ipv6: Introduce u...
1153
1154
  		csum = udplite_csum(skb);
  	else if (udp_sk(sk)->no_check6_tx) {   /* UDP csum disabled */
4068579e1   Tom Herbert   net: Implmement R...
1155
1156
1157
  		skb->ip_summed = CHECKSUM_NONE;
  		goto send;
  	} else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
a8c744a8b   Willem de Bruijn   udp: disable gso ...
1158
  csum_partial:
d39d938c8   Vlad Yasevich   ipv6: Introduce u...
1159
  		udp6_hwcsum_outgoing(sk, skb, &fl6->saddr, &fl6->daddr, len);
493c6be3f   Sridhar Samudrala   udpv6: Fix HW che...
1160
1161
  		goto send;
  	} else
d39d938c8   Vlad Yasevich   ipv6: Introduce u...
1162
  		csum = udp_csum(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1163

ba4e58eca   Gerrit Renker   [NET]: Supporting...
1164
  	/* add protocol-dependent pseudo-header */
4c9483b2f   David S. Miller   ipv6: Convert to ...
1165
  	uh->check = csum_ipv6_magic(&fl6->saddr, &fl6->daddr,
d39d938c8   Vlad Yasevich   ipv6: Introduce u...
1166
  				    len, fl6->flowi6_proto, csum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1167
  	if (uh->check == 0)
f6ab02880   Al Viro   [NET]: Make mangl...
1168
  		uh->check = CSUM_MANGLED_0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1169

493c6be3f   Sridhar Samudrala   udpv6: Fix HW che...
1170
  send:
d39d938c8   Vlad Yasevich   ipv6: Introduce u...
1171
  	err = ip6_send_skb(skb);
6ce9e7b5f   Eric Dumazet   ip: Report qdisc ...
1172
1173
  	if (err) {
  		if (err == -ENOBUFS && !inet6_sk(sk)->recverr) {
6aef70a85   Eric Dumazet   net: snmp: kill v...
1174
1175
  			UDP6_INC_STATS(sock_net(sk),
  				       UDP_MIB_SNDBUFERRORS, is_udplite);
6ce9e7b5f   Eric Dumazet   ip: Report qdisc ...
1176
1177
  			err = 0;
  		}
6aef70a85   Eric Dumazet   net: snmp: kill v...
1178
1179
1180
1181
  	} else {
  		UDP6_INC_STATS(sock_net(sk),
  			       UDP_MIB_OUTDATAGRAMS, is_udplite);
  	}
d39d938c8   Vlad Yasevich   ipv6: Introduce u...
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
  	return err;
  }
  
  static int udp_v6_push_pending_frames(struct sock *sk)
  {
  	struct sk_buff *skb;
  	struct udp_sock  *up = udp_sk(sk);
  	struct flowi6 fl6;
  	int err = 0;
  
  	if (up->pending == AF_INET)
  		return udp_push_pending_frames(sk);
  
  	/* ip6_finish_skb will release the cork, so make a copy of
  	 * fl6 here.
  	 */
  	fl6 = inet_sk(sk)->cork.fl.u.ip6;
  
  	skb = ip6_finish_skb(sk);
  	if (!skb)
  		goto out;
bec1f6f69   Willem de Bruijn   udp: generate gso...
1203
  	err = udp_v6_send_skb(skb, &fl6, &inet_sk(sk)->cork.base);
d39d938c8   Vlad Yasevich   ipv6: Introduce u...
1204

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205
1206
1207
1208
1209
  out:
  	up->len = 0;
  	up->pending = 0;
  	return err;
  }
1b7841404   Ying Xue   net: Remove iocb ...
1210
  int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1211
1212
1213
1214
1215
  {
  	struct ipv6_txoptions opt_space;
  	struct udp_sock *up = udp_sk(sk);
  	struct inet_sock *inet = inet_sk(sk);
  	struct ipv6_pinfo *np = inet6_sk(sk);
342dfc306   Steffen Hurrle   net: add build-ti...
1216
  	DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
20c59de2e   Arnaud Ebalard   ipv6: Refactor up...
1217
  	struct in6_addr *daddr, *final_p, final;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1218
  	struct ipv6_txoptions *opt = NULL;
45f6fad84   Eric Dumazet   ipv6: add complet...
1219
  	struct ipv6_txoptions *opt_to_free = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1220
  	struct ip6_flowlabel *flowlabel = NULL;
4c9483b2f   David S. Miller   ipv6: Convert to ...
1221
  	struct flowi6 fl6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1222
  	struct dst_entry *dst;
26879da58   Wei Wang   ipv6: add new str...
1223
  	struct ipcm6_cookie ipc6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224
  	int addr_len = msg->msg_namelen;
9f542f616   Alexey Kodanev   ipv6: udp: conver...
1225
  	bool connected = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
  	int ulen = len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1227
1228
  	int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
  	int err;
b2bf1e265   Wang Chen   [UDP]: Clean up f...
1229
  	int is_udplite = IS_UDPLITE(sk);
ba4e58eca   Gerrit Renker   [NET]: Supporting...
1230
  	int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1231

b515430ac   Willem de Bruijn   ipv6: ipcm6_cooki...
1232
  	ipcm6_init(&ipc6);
bec1f6f69   Willem de Bruijn   udp: generate gso...
1233
  	ipc6.gso_size = up->gso_size;
5fdaa88df   Willem de Bruijn   ipv6: fold sockcm...
1234
  	ipc6.sockc.tsflags = sk->sk_tsflags;
c6af0c227   Willem de Bruijn   ip: support SO_MA...
1235
  	ipc6.sockc.mark = sk->sk_mark;
26879da58   Wei Wang   ipv6: add new str...
1236

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
  	/* destination address check */
  	if (sin6) {
  		if (addr_len < offsetof(struct sockaddr, sa_data))
  			return -EINVAL;
  
  		switch (sin6->sin6_family) {
  		case AF_INET6:
  			if (addr_len < SIN6_LEN_RFC2133)
  				return -EINVAL;
  			daddr = &sin6->sin6_addr;
052d2369d   Jonathan T. Leighton   ipv6: Handle IPv4...
1247
1248
1249
1250
  			if (ipv6_addr_any(daddr) &&
  			    ipv6_addr_v4mapped(&np->saddr))
  				ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
  						       daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
  			break;
  		case AF_INET:
  			goto do_udp_sendmsg;
  		case AF_UNSPEC:
  			msg->msg_name = sin6 = NULL;
  			msg->msg_namelen = addr_len = 0;
  			daddr = NULL;
  			break;
  		default:
  			return -EINVAL;
  		}
  	} else if (!up->pending) {
  		if (sk->sk_state != TCP_ESTABLISHED)
  			return -EDESTADDRREQ;
efe4208f4   Eric Dumazet   ipv6: make lookup...
1265
  		daddr = &sk->sk_v6_daddr;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1266
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1267
1268
1269
  		daddr = NULL;
  
  	if (daddr) {
e773e4faa   Brian Haley   [IPV6]: Add v4map...
1270
  		if (ipv6_addr_v4mapped(daddr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1271
1272
  			struct sockaddr_in sin;
  			sin.sin_family = AF_INET;
c720c7e83   Eric Dumazet   inet: rename some...
1273
  			sin.sin_port = sin6 ? sin6->sin6_port : inet->inet_dport;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1274
1275
1276
1277
1278
1279
  			sin.sin_addr.s_addr = daddr->s6_addr32[3];
  			msg->msg_name = &sin;
  			msg->msg_namelen = sizeof(sin);
  do_udp_sendmsg:
  			if (__ipv6_only_sock(sk))
  				return -ENETUNREACH;
1b7841404   Ying Xue   net: Remove iocb ...
1280
  			return udp_sendmsg(sk, msg, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1281
1282
1283
1284
  		}
  	}
  
  	if (up->pending == AF_INET)
1b7841404   Ying Xue   net: Remove iocb ...
1285
  		return udp_sendmsg(sk, msg, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1286
1287
  
  	/* Rough check on arithmetic overflow,
b59e139bb   YOSHIFUJI Hideaki   [IPv6]: Fix incor...
1288
  	   better check is made in ip6_append_data().
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1289
1290
1291
  	   */
  	if (len > INT_MAX - sizeof(struct udphdr))
  		return -EMSGSIZE;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1292

03485f2ad   Vlad Yasevich   udpv6: Add lockle...
1293
  	getfrag  =  is_udplite ?  udplite_getfrag : ip_generic_getfrag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
  	if (up->pending) {
  		/*
  		 * There are pending frames.
  		 * The socket lock must be held while it's corked.
  		 */
  		lock_sock(sk);
  		if (likely(up->pending)) {
  			if (unlikely(up->pending != AF_INET6)) {
  				release_sock(sk);
  				return -EAFNOSUPPORT;
  			}
  			dst = NULL;
  			goto do_append_data;
  		}
  		release_sock(sk);
  	}
  	ulen += sizeof(struct udphdr);
4c9483b2f   David S. Miller   ipv6: Convert to ...
1311
  	memset(&fl6, 0, sizeof(fl6));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1312
1313
1314
1315
  
  	if (sin6) {
  		if (sin6->sin6_port == 0)
  			return -EINVAL;
1958b856c   David S. Miller   net: Put fl6_* ma...
1316
  		fl6.fl6_dport = sin6->sin6_port;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
1318
1319
  		daddr = &sin6->sin6_addr;
  
  		if (np->sndflow) {
4c9483b2f   David S. Miller   ipv6: Convert to ...
1320
1321
1322
  			fl6.flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK;
  			if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) {
  				flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
59c820b23   Willem de Bruijn   ipv6: elide flowl...
1323
  				if (IS_ERR(flowlabel))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1324
  					return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325
1326
1327
1328
1329
1330
1331
1332
  			}
  		}
  
  		/*
  		 * Otherwise it will be difficult to maintain
  		 * sk->sk_dst_cache.
  		 */
  		if (sk->sk_state == TCP_ESTABLISHED &&
efe4208f4   Eric Dumazet   ipv6: make lookup...
1333
1334
  		    ipv6_addr_equal(daddr, &sk->sk_v6_daddr))
  			daddr = &sk->sk_v6_daddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
1336
1337
  
  		if (addr_len >= sizeof(struct sockaddr_in6) &&
  		    sin6->sin6_scope_id &&
842df0739   Hannes Frederic Sowa   ipv6: use newly i...
1338
  		    __ipv6_addr_needs_scope_id(__ipv6_addr_type(daddr)))
4c9483b2f   David S. Miller   ipv6: Convert to ...
1339
  			fl6.flowi6_oif = sin6->sin6_scope_id;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1340
1341
1342
  	} else {
  		if (sk->sk_state != TCP_ESTABLISHED)
  			return -EDESTADDRREQ;
1958b856c   David S. Miller   net: Put fl6_* ma...
1343
  		fl6.fl6_dport = inet->inet_dport;
efe4208f4   Eric Dumazet   ipv6: make lookup...
1344
  		daddr = &sk->sk_v6_daddr;
4c9483b2f   David S. Miller   ipv6: Convert to ...
1345
  		fl6.flowlabel = np->flow_label;
9f542f616   Alexey Kodanev   ipv6: udp: conver...
1346
  		connected = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1347
  	}
4c9483b2f   David S. Miller   ipv6: Convert to ...
1348
1349
  	if (!fl6.flowi6_oif)
  		fl6.flowi6_oif = sk->sk_bound_dev_if;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1350

4c9483b2f   David S. Miller   ipv6: Convert to ...
1351
1352
  	if (!fl6.flowi6_oif)
  		fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
9f690db7f   Yang Hongyang   ipv6: fix the out...
1353

c6af0c227   Willem de Bruijn   ip: support SO_MA...
1354
  	fl6.flowi6_mark = ipc6.sockc.mark;
e2d118a1c   Lorenzo Colitti   net: inet: Suppor...
1355
  	fl6.flowi6_uid = sk->sk_uid;
51953d5bc   Brian Haley   Use sk_mark for I...
1356

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1357
1358
1359
1360
  	if (msg->msg_controllen) {
  		opt = &opt_space;
  		memset(opt, 0, sizeof(struct ipv6_txoptions));
  		opt->tot_len = sizeof(*opt);
26879da58   Wei Wang   ipv6: add new str...
1361
  		ipc6.opt = opt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1362

2e8de8576   Willem de Bruijn   udp: add gso segm...
1363
1364
1365
  		err = udp_cmsg_send(sk, msg, &ipc6.gso_size);
  		if (err > 0)
  			err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, &fl6,
5fdaa88df   Willem de Bruijn   ipv6: fold sockcm...
1366
  						    &ipc6);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1367
1368
1369
1370
  		if (err < 0) {
  			fl6_sock_release(flowlabel);
  			return err;
  		}
4c9483b2f   David S. Miller   ipv6: Convert to ...
1371
1372
  		if ((fl6.flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) {
  			flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
59c820b23   Willem de Bruijn   ipv6: elide flowl...
1373
  			if (IS_ERR(flowlabel))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1374
1375
1376
1377
  				return -EINVAL;
  		}
  		if (!(opt->opt_nflen|opt->opt_flen))
  			opt = NULL;
9f542f616   Alexey Kodanev   ipv6: udp: conver...
1378
  		connected = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1379
  	}
45f6fad84   Eric Dumazet   ipv6: add complet...
1380
1381
1382
1383
  	if (!opt) {
  		opt = txopt_get(np);
  		opt_to_free = opt;
  	}
df9890c31   YOSHIFUJI Hideaki   [IPV6]: Fix sendi...
1384
1385
1386
  	if (flowlabel)
  		opt = fl6_merge_options(&opt_space, flowlabel, opt);
  	opt = ipv6_fixup_options(&opt_space, opt);
26879da58   Wei Wang   ipv6: add new str...
1387
  	ipc6.opt = opt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1388

4c9483b2f   David S. Miller   ipv6: Convert to ...
1389
  	fl6.flowi6_proto = sk->sk_protocol;
e8e369840   Andrey Ignatov   bpf: Fix [::] -> ...
1390
  	fl6.daddr = *daddr;
4c9483b2f   David S. Miller   ipv6: Convert to ...
1391
  	if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr))
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
1392
  		fl6.saddr = np->saddr;
1958b856c   David S. Miller   net: Put fl6_* ma...
1393
  	fl6.fl6_sport = inet->inet_sport;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1394

1cedee13d   Andrey Ignatov   bpf: Hooks for sy...
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
  	if (cgroup_bpf_enabled && !connected) {
  		err = BPF_CGROUP_RUN_PROG_UDP6_SENDMSG_LOCK(sk,
  					   (struct sockaddr *)sin6, &fl6.saddr);
  		if (err)
  			goto out_no_dst;
  		if (sin6) {
  			if (ipv6_addr_v4mapped(&sin6->sin6_addr)) {
  				/* BPF program rewrote IPv6-only by IPv4-mapped
  				 * IPv6. It's currently unsupported.
  				 */
  				err = -ENOTSUPP;
  				goto out_no_dst;
  			}
  			if (sin6->sin6_port == 0) {
  				/* BPF program set invalid port. Reject it. */
  				err = -EINVAL;
  				goto out_no_dst;
  			}
  			fl6.fl6_dport = sin6->sin6_port;
  			fl6.daddr = sin6->sin6_addr;
  		}
  	}
e8e369840   Andrey Ignatov   bpf: Fix [::] -> ...
1417
1418
  	if (ipv6_addr_any(&fl6.daddr))
  		fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
4c9483b2f   David S. Miller   ipv6: Convert to ...
1419
  	final_p = fl6_update_dst(&fl6, opt, &final);
20c59de2e   Arnaud Ebalard   ipv6: Refactor up...
1420
  	if (final_p)
9f542f616   Alexey Kodanev   ipv6: udp: conver...
1421
  		connected = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1422

4c9483b2f   David S. Miller   ipv6: Convert to ...
1423
1424
  	if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) {
  		fl6.flowi6_oif = np->mcast_oif;
9f542f616   Alexey Kodanev   ipv6: udp: conver...
1425
  		connected = false;
c4062dfc4   Erich E. Hoover   ipv6: Implement I...
1426
1427
  	} else if (!fl6.flowi6_oif)
  		fl6.flowi6_oif = np->ucast_oif;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1428

4c9483b2f   David S. Miller   ipv6: Convert to ...
1429
  	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
beb8d13be   Venkat Yekkirala   [MLSXFRM]: Add fl...
1430

38b7097b5   Hannes Frederic Sowa   ipv6: use TOS mar...
1431
1432
1433
1434
  	if (ipc6.tclass < 0)
  		ipc6.tclass = np->tclass;
  
  	fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
4f858c56b   Alexey Kodanev   ipv6: udp: set ds...
1435
  	dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p, connected);
68d0c6d34   David S. Miller   ipv6: Consolidate...
1436
1437
1438
  	if (IS_ERR(dst)) {
  		err = PTR_ERR(dst);
  		dst = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1439
  		goto out;
14e50e57a   David S. Miller   [XFRM]: Allow pac...
1440
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1441

26879da58   Wei Wang   ipv6: add new str...
1442
1443
  	if (ipc6.hlimit < 0)
  		ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1444
1445
1446
1447
  
  	if (msg->msg_flags&MSG_CONFIRM)
  		goto do_confirm;
  back_from_confirm:
03485f2ad   Vlad Yasevich   udpv6: Add lockle...
1448
1449
  	/* Lockless fast path for the non-corking case */
  	if (!corkreq) {
1cd7884df   Willem de Bruijn   udp: expose inet ...
1450
  		struct inet_cork_full cork;
03485f2ad   Vlad Yasevich   udpv6: Add lockle...
1451
1452
1453
  		struct sk_buff *skb;
  
  		skb = ip6_make_skb(sk, getfrag, msg, ulen,
26879da58   Wei Wang   ipv6: add new str...
1454
  				   sizeof(struct udphdr), &ipc6,
03485f2ad   Vlad Yasevich   udpv6: Add lockle...
1455
  				   &fl6, (struct rt6_info *)dst,
5fdaa88df   Willem de Bruijn   ipv6: fold sockcm...
1456
  				   msg->msg_flags, &cork);
03485f2ad   Vlad Yasevich   udpv6: Add lockle...
1457
1458
  		err = PTR_ERR(skb);
  		if (!IS_ERR_OR_NULL(skb))
bec1f6f69   Willem de Bruijn   udp: generate gso...
1459
  			err = udp_v6_send_skb(skb, &fl6, &cork.base);
4f858c56b   Alexey Kodanev   ipv6: udp: set ds...
1460
  		goto out;
03485f2ad   Vlad Yasevich   udpv6: Add lockle...
1461
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1462
1463
1464
1465
1466
  	lock_sock(sk);
  	if (unlikely(up->pending)) {
  		/* The socket is already corked while preparing it. */
  		/* ... which is an evident application bug. --ANK */
  		release_sock(sk);
ba7a46f16   Joe Perches   net: Convert LIMI...
1467
1468
  		net_dbg_ratelimited("udp cork app bug 2
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1469
1470
1471
1472
1473
1474
1475
  		err = -EINVAL;
  		goto out;
  	}
  
  	up->pending = AF_INET6;
  
  do_append_data:
26879da58   Wei Wang   ipv6: add new str...
1476
1477
  	if (ipc6.dontfrag < 0)
  		ipc6.dontfrag = np->dontfrag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1478
  	up->len += ulen;
26879da58   Wei Wang   ipv6: add new str...
1479
1480
  	err = ip6_append_data(sk, getfrag, msg, ulen, sizeof(struct udphdr),
  			      &ipc6, &fl6, (struct rt6_info *)dst,
5fdaa88df   Willem de Bruijn   ipv6: fold sockcm...
1481
  			      corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1482
1483
1484
  	if (err)
  		udp_v6_flush_pending_frames(sk);
  	else if (!corkreq)
4c0a6cb0d   Gerrit Renker   [UDP(-Lite)]: con...
1485
  		err = udp_v6_push_pending_frames(sk);
1e0c14f49   Herbert Xu   [UDP]: Fix MSG_PR...
1486
1487
  	else if (unlikely(skb_queue_empty(&sk->sk_write_queue)))
  		up->pending = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1488

03485f2ad   Vlad Yasevich   udpv6: Add lockle...
1489
1490
1491
  	if (err > 0)
  		err = np->recverr ? net_xmit_errno(err) : 0;
  	release_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1492
  out:
a3c960899   YOSHIFUJI Hideaki   [IPV6] UDP: Possi...
1493
  	dst_release(dst);
1cedee13d   Andrey Ignatov   bpf: Hooks for sy...
1494
  out_no_dst:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1495
  	fl6_sock_release(flowlabel);
45f6fad84   Eric Dumazet   ipv6: add complet...
1496
  	txopt_put(opt_to_free);
cd562c985   YOSHIFUJI Hideaki   [IPV6]: Just incr...
1497
  	if (!err)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1498
  		return len;
a18135eb9   David S. Miller   [IPV6]: Add UDP_M...
1499
1500
1501
1502
1503
1504
1505
1506
  	/*
  	 * ENOBUFS = no kernel mem, SOCK_NOSPACE = no sndbuf space.  Reporting
  	 * ENOBUFS might not be good (it's not tunable per se), but otherwise
  	 * we don't have a good statistic (IpOutDiscards but it can be too many
  	 * things).  We could add another new stat but at least for now that
  	 * seems like overkill.
  	 */
  	if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) {
6aef70a85   Eric Dumazet   net: snmp: kill v...
1507
1508
  		UDP6_INC_STATS(sock_net(sk),
  			       UDP_MIB_SNDBUFERRORS, is_udplite);
a18135eb9   David S. Miller   [IPV6]: Add UDP_M...
1509
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1510
1511
1512
  	return err;
  
  do_confirm:
0dec879f6   Julian Anastasov   net: use dst_conf...
1513
1514
  	if (msg->msg_flags & MSG_PROBE)
  		dst_confirm_neigh(dst, &fl6.daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1515
1516
1517
1518
1519
  	if (!(msg->msg_flags&MSG_PROBE) || len)
  		goto back_from_confirm;
  	err = 0;
  	goto out;
  }
7d06b2e05   Brian Haley   net: change proto...
1520
  void udpv6_destroy_sock(struct sock *sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1521
  {
44046a593   Tom Parkin   udp: add encap_de...
1522
  	struct udp_sock *up = udp_sk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1523
1524
1525
  	lock_sock(sk);
  	udp_v6_flush_pending_frames(sk);
  	release_sock(sk);
60fb9567b   Paolo Abeni   udp: implement co...
1526
1527
1528
1529
1530
1531
1532
1533
  	if (static_branch_unlikely(&udpv6_encap_needed_key)) {
  		if (up->encap_type) {
  			void (*encap_destroy)(struct sock *sk);
  			encap_destroy = READ_ONCE(up->encap_destroy);
  			if (encap_destroy)
  				encap_destroy(sk);
  		}
  		if (up->encap_enabled)
9c4806014   Paolo Abeni   udp: fix jump lab...
1534
  			static_branch_dec(&udpv6_encap_needed_key);
44046a593   Tom Parkin   udp: add encap_de...
1535
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1536
  	inet6_destroy_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1537
1538
1539
1540
1541
  }
  
  /*
   *	Socket option code for UDP
   */
a7b75c5a8   Christoph Hellwig   net: pass a sockp...
1542
1543
  int udpv6_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval,
  		     unsigned int optlen)
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1544
  {
db8dac20d   David S. Miller   [UDP]: Revert udp...
1545
  	if (level == SOL_UDP  ||  level == SOL_UDPLITE)
91ac1ccaf   Christoph Hellwig   net/udp: switch u...
1546
  		return udp_lib_setsockopt(sk, level, optname,
a7b75c5a8   Christoph Hellwig   net: pass a sockp...
1547
  					  optval, optlen,
4c0a6cb0d   Gerrit Renker   [UDP(-Lite)]: con...
1548
  					  udp_v6_push_pending_frames);
ba4e58eca   Gerrit Renker   [NET]: Supporting...
1549
  	return ipv6_setsockopt(sk, level, optname, optval, optlen);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1550
  }
ba4e58eca   Gerrit Renker   [NET]: Supporting...
1551
1552
  int udpv6_getsockopt(struct sock *sk, int level, int optname,
  		     char __user *optval, int __user *optlen)
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1553
  {
db8dac20d   David S. Miller   [UDP]: Revert udp...
1554
  	if (level == SOL_UDP  ||  level == SOL_UDPLITE)
4c0a6cb0d   Gerrit Renker   [UDP(-Lite)]: con...
1555
  		return udp_lib_getsockopt(sk, level, optname, optval, optlen);
ba4e58eca   Gerrit Renker   [NET]: Supporting...
1556
  	return ipv6_getsockopt(sk, level, optname, optval, optlen);
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1557
  }
a8e3bb347   David Ahern   net: Add comment ...
1558
1559
1560
  /* thinking of making this const? Don't.
   * early_demux can change based on sysctl.
   */
dddb64bcb   subashab@codeaurora.org   net: Add sysctl t...
1561
  static struct inet6_protocol udpv6_protocol = {
5425077d7   subashab@codeaurora.org   net: ipv6: Add ea...
1562
  	.early_demux	=	udp_v6_early_demux,
dddb64bcb   subashab@codeaurora.org   net: Add sysctl t...
1563
  	.early_demux_handler =  udp_v6_early_demux,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1564
1565
1566
1567
1568
1569
1570
  	.handler	=	udpv6_rcv,
  	.err_handler	=	udpv6_err,
  	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
  };
  
  /* ------------------------------------------------------------------------ */
  #ifdef CONFIG_PROC_FS
ba4e58eca   Gerrit Renker   [NET]: Supporting...
1571
  int udp6_seq_show(struct seq_file *seq, void *v)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1572
  {
17ef66afc   Lorenzo Colitti   net: ipv6: Unify ...
1573
1574
1575
1576
1577
1578
1579
  	if (v == SEQ_START_TOKEN) {
  		seq_puts(seq, IPV6_SEQ_DGRAM_HEADER);
  	} else {
  		int bucket = ((struct udp_iter_state *)seq->private)->bucket;
  		struct inet_sock *inet = inet_sk(v);
  		__u16 srcp = ntohs(inet->inet_sport);
  		__u16 destp = ntohs(inet->inet_dport);
6c206b200   Paolo Abeni   udp: fix rx queue...
1580
1581
  		__ip6_dgram_sock_seq_show(seq, v, srcp, destp,
  					  udp_rqueue_get(v), bucket);
17ef66afc   Lorenzo Colitti   net: ipv6: Unify ...
1582
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1583
1584
  	return 0;
  }
c35063722   Christoph Hellwig   proc: introduce p...
1585
  const struct seq_operations udp6_seq_ops = {
a3d2599b2   Christoph Hellwig   ipv{4,6}/udp{,lit...
1586
1587
1588
1589
1590
  	.start		= udp_seq_start,
  	.next		= udp_seq_next,
  	.stop		= udp_seq_stop,
  	.show		= udp6_seq_show,
  };
c35063722   Christoph Hellwig   proc: introduce p...
1591
  EXPORT_SYMBOL(udp6_seq_ops);
73cb88ecb   Arjan van de Ven   net: make the tcp...
1592

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1593
  static struct udp_seq_afinfo udp6_seq_afinfo = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1594
  	.family		= AF_INET6,
645ca708f   Eric Dumazet   udp: introduce st...
1595
  	.udp_table	= &udp_table,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1596
  };
2c8c1e729   Alexey Dobriyan   net: spread __net...
1597
  int __net_init udp6_proc_init(struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1598
  {
c35063722   Christoph Hellwig   proc: introduce p...
1599
1600
  	if (!proc_create_net_data("udp6", 0444, net->proc_net, &udp6_seq_ops,
  			sizeof(struct udp_iter_state), &udp6_seq_afinfo))
a3d2599b2   Christoph Hellwig   ipv{4,6}/udp{,lit...
1601
1602
  		return -ENOMEM;
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1603
  }
ec120da6f   Ian Morris   ipv6: trivial whi...
1604
1605
  void udp6_proc_exit(struct net *net)
  {
a3d2599b2   Christoph Hellwig   ipv{4,6}/udp{,lit...
1606
  	remove_proc_entry("udp6", net->proc_net);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1607
1608
1609
1610
1611
1612
  }
  #endif /* CONFIG_PROC_FS */
  
  /* ------------------------------------------------------------------------ */
  
  struct proto udpv6_prot = {
1e8029515   Tonghao Zhang   udp: Move the udp...
1613
1614
1615
  	.name			= "UDPv6",
  	.owner			= THIS_MODULE,
  	.close			= udp_lib_close,
d74bad4e7   Andrey Ignatov   bpf: Hooks for sy...
1616
  	.pre_connect		= udpv6_pre_connect,
1e8029515   Tonghao Zhang   udp: Move the udp...
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
  	.connect		= ip6_datagram_connect,
  	.disconnect		= udp_disconnect,
  	.ioctl			= udp_ioctl,
  	.init			= udp_init_sock,
  	.destroy		= udpv6_destroy_sock,
  	.setsockopt		= udpv6_setsockopt,
  	.getsockopt		= udpv6_getsockopt,
  	.sendmsg		= udpv6_sendmsg,
  	.recvmsg		= udpv6_recvmsg,
  	.release_cb		= ip6_datagram_release_cb,
  	.hash			= udp_lib_hash,
  	.unhash			= udp_lib_unhash,
  	.rehash			= udp_v6_rehash,
  	.get_port		= udp_v6_get_port,
  	.memory_allocated	= &udp_memory_allocated,
  	.sysctl_mem		= sysctl_udp_mem,
  	.sysctl_wmem_offset     = offsetof(struct net, ipv4.sysctl_udp_wmem_min),
  	.sysctl_rmem_offset     = offsetof(struct net, ipv4.sysctl_udp_rmem_min),
  	.obj_size		= sizeof(struct udp6_sock),
  	.h.udp_table		= &udp_table,
1e8029515   Tonghao Zhang   udp: Move the udp...
1637
  	.diag_destroy		= udp_abort,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1638
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1639
1640
1641
1642
1643
  static struct inet_protosw udpv6_protosw = {
  	.type =      SOCK_DGRAM,
  	.protocol =  IPPROTO_UDP,
  	.prot =      &udpv6_prot,
  	.ops =       &inet6_dgram_ops,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1644
1645
  	.flags =     INET_PROTOSW_PERMANENT,
  };
7f4e4868f   Daniel Lezcano   [IPV6]: make the ...
1646
  int __init udpv6_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1647
  {
7f4e4868f   Daniel Lezcano   [IPV6]: make the ...
1648
  	int ret;
3336288a9   Vlad Yasevich   ipv6: Switch to u...
1649
1650
  	ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP);
  	if (ret)
c6b641a4c   Vlad Yasevich   ipv6: Pull IPv6 G...
1651
  		goto out;
3336288a9   Vlad Yasevich   ipv6: Switch to u...
1652

7f4e4868f   Daniel Lezcano   [IPV6]: make the ...
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
  	ret = inet6_register_protosw(&udpv6_protosw);
  	if (ret)
  		goto out_udpv6_protocol;
  out:
  	return ret;
  
  out_udpv6_protocol:
  	inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
  	goto out;
  }
09f7709f4   Daniel Lezcano   [IPV6]: fix secti...
1663
  void udpv6_exit(void)
7f4e4868f   Daniel Lezcano   [IPV6]: make the ...
1664
1665
1666
  {
  	inet6_unregister_protosw(&udpv6_protosw);
  	inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1667
  }