Blame view

net/sctp/input.c 34.9 KB
47505b8bc   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
60c778b25   Vlad Yasevich   [SCTP]: Stop clai...
2
  /* SCTP kernel implementation
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3
4
5
6
7
8
9
   * Copyright (c) 1999-2000 Cisco, Inc.
   * Copyright (c) 1999-2001 Motorola, Inc.
   * Copyright (c) 2001-2003 International Business Machines, Corp.
   * Copyright (c) 2001 Intel Corp.
   * Copyright (c) 2001 Nokia, Inc.
   * Copyright (c) 2001 La Monte H.P. Yarroll
   *
60c778b25   Vlad Yasevich   [SCTP]: Stop clai...
10
   * This file is part of the SCTP kernel implementation
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
   *
   * These functions handle all input from the IP layer into SCTP.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
   * Please send any bug reports or fixes you make to the
   * email address(es):
91705c61b   Daniel Borkmann   net: sctp: trivia...
16
   *    lksctp developers <linux-sctp@vger.kernel.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
23
24
25
26
   * Written or modified by:
   *    La Monte H.P. Yarroll <piggy@acm.org>
   *    Karl Knutson <karl@athena.chicago.il.us>
   *    Xingang Guo <xingang.guo@intel.com>
   *    Jon Grimm <jgrimm@us.ibm.com>
   *    Hui Huang <hui.huang@nokia.com>
   *    Daisy Chang <daisyc@us.ibm.com>
   *    Sridhar Samudrala <sri@us.ibm.com>
   *    Ardelle Fan <ardelle.fan@intel.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
31
32
33
   */
  
  #include <linux/types.h>
  #include <linux/list.h> /* For struct list_head */
  #include <linux/socket.h>
  #include <linux/ip.h>
  #include <linux/time.h> /* For struct timeval */
5a0e3ad6a   Tejun Heo   include cleanup: ...
34
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
38
39
40
41
  #include <net/ip.h>
  #include <net/icmp.h>
  #include <net/snmp.h>
  #include <net/sock.h>
  #include <net/xfrm.h>
  #include <net/sctp/sctp.h>
  #include <net/sctp/sm.h>
9ad0977fe   Vlad Yasevich   [SCTP]: Use crc32...
42
  #include <net/sctp/checksum.h>
dcfc23cac   Pavel Emelyanov   mib: add struct n...
43
  #include <net/net_namespace.h>
0eb71a9da   NeilBrown   rhashtable: split...
44
  #include <linux/rhashtable.h>
532ae2f10   Xin Long   sctp: do reusepor...
45
  #include <net/sock_reuseport.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
  
  /* Forward declarations for internal helpers. */
  static int sctp_rcv_ootb(struct sk_buff *);
4110cc255   Eric W. Biederman   sctp: Make the as...
49
50
  static struct sctp_association *__sctp_rcv_lookup(struct net *net,
  				      struct sk_buff *skb,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  				      const union sctp_addr *paddr,
575659936   Nicolas Dichtel   sctp: fix a typo ...
52
  				      const union sctp_addr *laddr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  				      struct sctp_transport **transportp);
532ae2f10   Xin Long   sctp: do reusepor...
54
55
56
57
  static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(
  					struct net *net, struct sk_buff *skb,
  					const union sctp_addr *laddr,
  					const union sctp_addr *daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  static struct sctp_association *__sctp_lookup_association(
4110cc255   Eric W. Biederman   sctp: Make the as...
59
  					struct net *net,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
  					const union sctp_addr *local,
  					const union sctp_addr *peer,
  					struct sctp_transport **pt);
50b1a782f   Zhu Yi   sctp: use limited...
63
  static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb);
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
64

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
  
  /* Calculate the SCTP checksum of an SCTP packet.  */
b01a24078   Eric W. Biederman   sctp: Make the mi...
67
  static inline int sctp_rcv_checksum(struct net *net, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
  {
2c0fd387b   Arnaldo Carvalho de Melo   [SCTP]: Introduce...
69
  	struct sctphdr *sh = sctp_hdr(skb);
4458f04c0   Vlad Yasevich   sctp: Clean up sc...
70
  	__le32 cmp = sh->checksum;
024ec3dea   Joe Stringer   net/sctp: Refacto...
71
  	__le32 val = sctp_compute_cksum(skb, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
  
  	if (val != cmp) {
  		/* CRC failure, dump it. */
08e3baef6   Eric Dumazet   net: sctp: rename...
75
  		__SCTP_INC_STATS(net, SCTP_MIB_CHECKSUMERRORS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
78
79
  		return -1;
  	}
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
82
83
84
85
86
87
88
89
90
  /*
   * This is the routine which IP calls when receiving an SCTP packet.
   */
  int sctp_rcv(struct sk_buff *skb)
  {
  	struct sock *sk;
  	struct sctp_association *asoc;
  	struct sctp_endpoint *ep = NULL;
  	struct sctp_ep_common *rcvr;
  	struct sctp_transport *transport = NULL;
  	struct sctp_chunk *chunk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
94
  	union sctp_addr src;
  	union sctp_addr dest;
  	int family;
  	struct sctp_af *af;
4cdadcbcb   Eric W. Biederman   sctp: Make the en...
95
  	struct net *net = dev_net(skb->dev);
1dd27cde3   Daniel Axtens   net: use skb_is_g...
96
  	bool is_gso = skb_is_gso(skb) && skb_is_gso_sctp(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97

cb3f837ba   wangweidong   sctp: fix checkpa...
98
  	if (skb->pkt_type != PACKET_HOST)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
  		goto discard_it;
08e3baef6   Eric Dumazet   net: sctp: rename...
100
  	__SCTP_INC_STATS(net, SCTP_MIB_INSCTPPACKS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101

3acb50c18   Marcelo Ricardo Leitner   sctp: delay as mu...
102
103
104
105
106
  	/* If packet is too small to contain a single chunk, let's not
  	 * waste time on it anymore.
  	 */
  	if (skb->len < sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr) +
  		       skb_transport_offset(skb))
28cd77527   Herbert Xu   [SCTP]: Always li...
107
  		goto discard_it;
4c2f24549   Marcelo Ricardo Leitner   sctp: linearize e...
108
109
110
111
  	/* If the packet is fragmented and we need to do crc checking,
  	 * it's better to just linearize it otherwise crc computing
  	 * takes longer.
  	 */
1dd27cde3   Daniel Axtens   net: use skb_is_g...
112
  	if ((!is_gso && skb_linearize(skb)) ||
4c2f24549   Marcelo Ricardo Leitner   sctp: linearize e...
113
  	    !pskb_may_pull(skb, sizeof(struct sctphdr)))
3acb50c18   Marcelo Ricardo Leitner   sctp: delay as mu...
114
  		goto discard_it;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115

3acb50c18   Marcelo Ricardo Leitner   sctp: delay as mu...
116
  	/* Pull up the IP header. */
ea2ae17d6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
117
  	__skb_pull(skb, skb_transport_offset(skb));
202863fe4   Tom Herbert   sctp: Change sctp...
118
119
120
121
  
  	skb->csum_valid = 0; /* Previous value not applicable */
  	if (skb_csum_unnecessary(skb))
  		__skb_decr_checksum_unnecessary(skb);
90017accf   Marcelo Ricardo Leitner   sctp: Add GSO sup...
122
  	else if (!sctp_checksum_disable &&
1dd27cde3   Daniel Axtens   net: use skb_is_g...
123
  		 !is_gso &&
90017accf   Marcelo Ricardo Leitner   sctp: Add GSO sup...
124
  		 sctp_rcv_checksum(net, skb) < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  		goto discard_it;
202863fe4   Tom Herbert   sctp: Change sctp...
126
  	skb->csum_valid = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
127

3acb50c18   Marcelo Ricardo Leitner   sctp: delay as mu...
128
  	__skb_pull(skb, sizeof(struct sctphdr));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129

eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
130
  	family = ipver2af(ip_hdr(skb)->version);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
  	af = sctp_get_af_specific(family);
  	if (unlikely(!af))
  		goto discard_it;
e7487c86d   Marcelo Ricardo Leitner   sctp: avoid ident...
134
  	SCTP_INPUT_CB(skb)->af = af;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  
  	/* Initialize local addresses for lookups. */
  	af->from_skb(&src, skb, 1);
  	af->from_skb(&dest, skb, 0);
  
  	/* If the packet is to or from a non-unicast address,
  	 * silently discard the packet.
  	 *
  	 * This is not clearly defined in the RFC except in section
  	 * 8.4 - OOTB handling.  However, based on the book "Stream Control
  	 * Transmission Protocol" 2.1, "It is important to note that the
  	 * IP address of an SCTP transport address must be a routable
  	 * unicast address.  In other words, IP multicast addresses and
  	 * IP broadcast addresses cannot be used in an SCTP transport
  	 * address."
  	 */
5636bef73   Vlad Yasevich   [SCTP]: Reject sc...
151
152
  	if (!af->addr_valid(&src, NULL, skb) ||
  	    !af->addr_valid(&dest, NULL, skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  		goto discard_it;
4110cc255   Eric W. Biederman   sctp: Make the as...
154
  	asoc = __sctp_rcv_lookup(net, skb, &src, &dest, &transport);
1c7d1fc14   Al Viro   [SCTP]: Switch sc...
155

0fd9a65a7   Neil Horman   [SCTP] Support SO...
156
  	if (!asoc)
532ae2f10   Xin Long   sctp: do reusepor...
157
  		ep = __sctp_rcv_lookup_endpoint(net, skb, &dest, &src);
0fd9a65a7   Neil Horman   [SCTP] Support SO...
158
159
160
161
162
163
164
165
166
  
  	/* Retrieve the common input handling substructure. */
  	rcvr = asoc ? &asoc->base : &ep->base;
  	sk = rcvr->sk;
  
  	/*
  	 * If a frame arrives on an interface and the receiving socket is
  	 * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB
  	 */
8d72651d8   wangweidong   sctp: fix checkpa...
167
  	if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) {
dae399d7f   Xin Long   sctp: hold transp...
168
169
  		if (transport) {
  			sctp_transport_put(transport);
0fd9a65a7   Neil Horman   [SCTP] Support SO...
170
  			asoc = NULL;
dae399d7f   Xin Long   sctp: hold transp...
171
  			transport = NULL;
0fd9a65a7   Neil Horman   [SCTP] Support SO...
172
173
174
175
  		} else {
  			sctp_endpoint_put(ep);
  			ep = NULL;
  		}
2ce955035   Eric W. Biederman   sctp: Make the ct...
176
  		sk = net->sctp.ctl_sock;
0fd9a65a7   Neil Horman   [SCTP] Support SO...
177
178
  		ep = sctp_sk(sk)->ep;
  		sctp_endpoint_hold(ep);
0fd9a65a7   Neil Horman   [SCTP] Support SO...
179
180
  		rcvr = &ep->base;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
183
184
185
186
187
188
189
  	/*
  	 * RFC 2960, 8.4 - Handle "Out of the blue" Packets.
  	 * An SCTP packet is called an "out of the blue" (OOTB)
  	 * packet if it is correctly formed, i.e., passed the
  	 * receiver's checksum check, but the receiver is not
  	 * able to identify the association to which this
  	 * packet belongs.
  	 */
  	if (!asoc) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  		if (sctp_rcv_ootb(skb)) {
08e3baef6   Eric Dumazet   net: sctp: rename...
191
  			__SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
  			goto discard_release;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
  	if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb, family))
  		goto discard_release;
895b5c9f2   Florian Westphal   netfilter: drop b...
197
  	nf_reset_ct(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198

fda9ef5d6   Dmitry Mishin   [NET]: Fix sk->sk...
199
  	if (sk_filter(sk, skb))
d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
200
  		goto discard_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
  
  	/* Create an SCTP packet structure. */
cea8768f3   Marcelo Ricardo Leitner   sctp: allow sctp_...
203
  	chunk = sctp_chunkify(skb, asoc, sk, GFP_ATOMIC);
2babf9daa   Herbert Xu   [SCTP]: Fix up sc...
204
  	if (!chunk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
  		goto discard_release;
79af02c25   David S. Miller   [SCTP]: Use struc...
206
  	SCTP_INPUT_CB(skb)->chunk = chunk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
211
  	/* Remember what endpoint is to handle this packet. */
  	chunk->rcvr = rcvr;
  
  	/* Remember the SCTP header. */
3acb50c18   Marcelo Ricardo Leitner   sctp: delay as mu...
212
  	chunk->sctp_hdr = sctp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
  
  	/* Set the source and destination addresses of the incoming chunk.  */
d55c41b11   Al Viro   [SCTP]: Switch ->...
215
  	sctp_init_addrs(chunk, &src, &dest);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
220
221
222
223
  
  	/* Remember where we came from.  */
  	chunk->transport = transport;
  
  	/* Acquire access to the sock lock. Note: We are safe from other
  	 * bottom halves on this lock, but a user may be in the lock too,
  	 * so check if it is busy.
  	 */
5bc1d1b4a   wangweidong   sctp: remove macr...
224
  	bh_lock_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225

ae53b5bd7   Vlad Yasevich   sctp: Fix another...
226
227
228
229
230
231
232
233
  	if (sk != rcvr->sk) {
  		/* Our cached sk is different from the rcvr->sk.  This is
  		 * because migrate()/accept() may have moved the association
  		 * to a new socket and released all the sockets.  So now we
  		 * are holding a lock on the old socket while the user may
  		 * be doing something with the new socket.  Switch our veiw
  		 * of the current sk.
  		 */
5bc1d1b4a   wangweidong   sctp: remove macr...
234
  		bh_unlock_sock(sk);
ae53b5bd7   Vlad Yasevich   sctp: Fix another...
235
  		sk = rcvr->sk;
5bc1d1b4a   wangweidong   sctp: remove macr...
236
  		bh_lock_sock(sk);
ae53b5bd7   Vlad Yasevich   sctp: Fix another...
237
  	}
819be8108   Xin Long   sctp: add chunks ...
238
  	if (sock_owned_by_user(sk) || !sctp_newsk_ready(sk)) {
50b1a782f   Zhu Yi   sctp: use limited...
239
  		if (sctp_add_backlog(sk, skb)) {
5bc1d1b4a   wangweidong   sctp: remove macr...
240
  			bh_unlock_sock(sk);
50b1a782f   Zhu Yi   sctp: use limited...
241
242
243
244
  			sctp_chunk_free(chunk);
  			skb = NULL; /* sctp_chunk_free already freed the skb */
  			goto discard_release;
  		}
08e3baef6   Eric Dumazet   net: sctp: rename...
245
  		__SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_BACKLOG);
ac0b04627   Sridhar Samudrala   [SCTP]: Extend /p...
246
  	} else {
08e3baef6   Eric Dumazet   net: sctp: rename...
247
  		__SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_SOFTIRQ);
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
248
  		sctp_inq_push(&chunk->rcvr->inqueue, chunk);
ac0b04627   Sridhar Samudrala   [SCTP]: Extend /p...
249
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250

5bc1d1b4a   wangweidong   sctp: remove macr...
251
  	bh_unlock_sock(sk);
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
252
253
  
  	/* Release the asoc/ep ref we took in the lookup calls. */
dae399d7f   Xin Long   sctp: hold transp...
254
255
  	if (transport)
  		sctp_transport_put(transport);
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
256
257
  	else
  		sctp_endpoint_put(ep);
7a48f923b   Sridhar Samudrala   [SCTP]: Fix poten...
258

2babf9daa   Herbert Xu   [SCTP]: Fix up sc...
259
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
  
  discard_it:
08e3baef6   Eric Dumazet   net: sctp: rename...
262
  	__SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_DISCARDS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  	kfree_skb(skb);
2babf9daa   Herbert Xu   [SCTP]: Fix up sc...
264
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
  
  discard_release:
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
267
  	/* Release the asoc/ep ref we took in the lookup calls. */
dae399d7f   Xin Long   sctp: hold transp...
268
269
  	if (transport)
  		sctp_transport_put(transport);
0fd9a65a7   Neil Horman   [SCTP] Support SO...
270
  	else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
  		sctp_endpoint_put(ep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
273
274
  
  	goto discard_it;
  }
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
275
276
277
278
  /* Process the backlog queue of the socket.  Every skb on
   * the backlog holds a ref on an association or endpoint.
   * We hold this ref throughout the state machine to make
   * sure that the structure we need is still around.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
281
   */
  int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
  {
79af02c25   David S. Miller   [SCTP]: Use struc...
282
  	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
283
  	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
dae399d7f   Xin Long   sctp: hold transp...
284
  	struct sctp_transport *t = chunk->transport;
d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
285
  	struct sctp_ep_common *rcvr = NULL;
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
286
  	int backloged = 0;
7a48f923b   Sridhar Samudrala   [SCTP]: Fix poten...
287

d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
288
  	rcvr = chunk->rcvr;
c4d2444e9   Sridhar Samudrala   [SCTP]: Fix coupl...
289

61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
  	/* If the rcvr is dead then the association or endpoint
  	 * has been deleted and we can safely drop the chunk
  	 * and refs that we are holding.
  	 */
  	if (rcvr->dead) {
  		sctp_chunk_free(chunk);
  		goto done;
  	}
  
  	if (unlikely(rcvr->sk != sk)) {
  		/* In this case, the association moved from one socket to
  		 * another.  We are currently sitting on the backlog of the
  		 * old socket, so we need to move.
  		 * However, since we are here in the process context we
  		 * need to take make sure that the user doesn't own
  		 * the new socket when we process the packet.
  		 * If the new socket is user-owned, queue the chunk to the
  		 * backlog of the new socket without dropping any refs.
  		 * Otherwise, we can safely push the chunk on the inqueue.
  		 */
  
  		sk = rcvr->sk;
eefc1b1d1   Marcelo Ricardo Leitner   sctp: fix BH hand...
312
  		local_bh_disable();
5bc1d1b4a   wangweidong   sctp: remove macr...
313
  		bh_lock_sock(sk);
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
314

819be8108   Xin Long   sctp: add chunks ...
315
  		if (sock_owned_by_user(sk) || !sctp_newsk_ready(sk)) {
8265792bf   Eric Dumazet   net: silence KCSA...
316
  			if (sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf)))
50b1a782f   Zhu Yi   sctp: use limited...
317
318
319
  				sctp_chunk_free(chunk);
  			else
  				backloged = 1;
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
320
321
  		} else
  			sctp_inq_push(inqueue, chunk);
5bc1d1b4a   wangweidong   sctp: remove macr...
322
  		bh_unlock_sock(sk);
eefc1b1d1   Marcelo Ricardo Leitner   sctp: fix BH hand...
323
  		local_bh_enable();
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
324
325
326
327
328
  
  		/* If the chunk was backloged again, don't drop refs */
  		if (backloged)
  			return 0;
  	} else {
819be8108   Xin Long   sctp: add chunks ...
329
  		if (!sctp_newsk_ready(sk)) {
8265792bf   Eric Dumazet   net: silence KCSA...
330
  			if (!sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf)))
819be8108   Xin Long   sctp: add chunks ...
331
332
333
334
335
  				return 0;
  			sctp_chunk_free(chunk);
  		} else {
  			sctp_inq_push(inqueue, chunk);
  		}
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
336
337
338
339
340
  	}
  
  done:
  	/* Release the refs we took in sctp_add_backlog */
  	if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
dae399d7f   Xin Long   sctp: hold transp...
341
  		sctp_transport_put(t);
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
342
343
344
345
  	else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
  		sctp_endpoint_put(sctp_ep(rcvr));
  	else
  		BUG();
d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
346
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
  }
50b1a782f   Zhu Yi   sctp: use limited...
348
  static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
c4d2444e9   Sridhar Samudrala   [SCTP]: Fix coupl...
349
  {
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
350
  	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
dae399d7f   Xin Long   sctp: hold transp...
351
  	struct sctp_transport *t = chunk->transport;
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
352
  	struct sctp_ep_common *rcvr = chunk->rcvr;
50b1a782f   Zhu Yi   sctp: use limited...
353
  	int ret;
c4d2444e9   Sridhar Samudrala   [SCTP]: Fix coupl...
354

8265792bf   Eric Dumazet   net: silence KCSA...
355
  	ret = sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf));
50b1a782f   Zhu Yi   sctp: use limited...
356
357
358
359
360
361
  	if (!ret) {
  		/* Hold the assoc/ep while hanging on the backlog queue.
  		 * This way, we know structures we need will not disappear
  		 * from us
  		 */
  		if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
dae399d7f   Xin Long   sctp: hold transp...
362
  			sctp_transport_hold(t);
50b1a782f   Zhu Yi   sctp: use limited...
363
364
365
366
367
368
  		else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
  			sctp_endpoint_hold(sctp_ep(rcvr));
  		else
  			BUG();
  	}
  	return ret;
61c9fed41   Vladislav Yasevich   [SCTP]: A better ...
369

c4d2444e9   Sridhar Samudrala   [SCTP]: Fix coupl...
370
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
373
374
  /* Handle icmp frag needed error. */
  void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
  			   struct sctp_transport *t, __u32 pmtu)
  {
91bd6b1e0   Wei Yongjun   sctp: Drop ICMP p...
375
  	if (!t || (t->pathmtu <= pmtu))
52ccb8e90   Frank Filz   [SCTP]: Update SC...
376
  		return;
8a4794914   Vlad Yasevich   [SCTP] Flag a pmt...
377
  	if (sock_owned_by_user(sk)) {
d805397c3   Xin Long   sctp: use the pmt...
378
  		atomic_set(&t->mtu_info, pmtu);
8a4794914   Vlad Yasevich   [SCTP] Flag a pmt...
379
380
381
382
  		asoc->pmtu_pending = 1;
  		t->pmtu_pending = 1;
  		return;
  	}
cc35c3d1e   Marcelo Ricardo Leitner   sctp: do not retr...
383
384
385
386
387
388
  	if (!(t->param_flags & SPP_PMTUD_ENABLE))
  		/* We can't allow retransmitting in such case, as the
  		 * retransmission would be sized just as before, and thus we
  		 * would get another icmp, and retransmit again.
  		 */
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389

b6c5734db   Marcelo Ricardo Leitner   sctp: fix the han...
390
391
392
393
394
395
  	/* Update transports view of the MTU. Return if no update was needed.
  	 * If an update wasn't needed/possible, it also doesn't make sense to
  	 * try to retransmit now.
  	 */
  	if (!sctp_transport_update_pmtu(t, pmtu))
  		return;
52ccb8e90   Frank Filz   [SCTP]: Update SC...
396

cc35c3d1e   Marcelo Ricardo Leitner   sctp: do not retr...
397
398
399
400
  	/* Update association pmtu. */
  	sctp_assoc_sync_pmtu(asoc);
  
  	/* Retransmit with the new pmtu setting. */
52ccb8e90   Frank Filz   [SCTP]: Update SC...
401
  	sctp_retransmit(&asoc->outqueue, t, SCTP_RTXR_PMTUD);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
  }
ec18d9a26   David S. Miller   ipv6: Add redirec...
403
404
  void sctp_icmp_redirect(struct sock *sk, struct sctp_transport *t,
  			struct sk_buff *skb)
55be7a9c6   David S. Miller   ipv4: Add redirec...
405
406
  {
  	struct dst_entry *dst;
1cc276cec   Xin Long   sctp: add the mis...
407
  	if (sock_owned_by_user(sk) || !t)
55be7a9c6   David S. Miller   ipv4: Add redirec...
408
409
  		return;
  	dst = sctp_transport_dst_check(t);
1ed5c48f2   David S. Miller   net: Remove check...
410
  	if (dst)
6700c2709   David S. Miller   net: Pass optiona...
411
  		dst->ops->redirect(dst, sk, skb);
55be7a9c6   David S. Miller   ipv4: Add redirec...
412
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
415
416
417
418
419
420
421
422
423
424
  /*
   * SCTP Implementer's Guide, 2.37 ICMP handling procedures
   *
   * ICMP8) If the ICMP code is a "Unrecognized next header type encountered"
   *        or a "Protocol Unreachable" treat this message as an abort
   *        with the T bit set.
   *
   * This function sends an event to the state machine, which will abort the
   * association.
   *
   */
  void sctp_icmp_proto_unreachable(struct sock *sk,
d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
425
426
  			   struct sctp_association *asoc,
  			   struct sctp_transport *t)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  {
50b5d6ad6   Vlad Yasevich   sctp: Fix a race ...
428
429
430
431
432
433
  	if (sock_owned_by_user(sk)) {
  		if (timer_pending(&t->proto_unreach_timer))
  			return;
  		else {
  			if (!mod_timer(&t->proto_unreach_timer,
  						jiffies + (HZ/20)))
057a10fa1   Xin Long   sctp: change to h...
434
  				sctp_transport_hold(t);
50b5d6ad6   Vlad Yasevich   sctp: Fix a race ...
435
  		}
50b5d6ad6   Vlad Yasevich   sctp: Fix a race ...
436
  	} else {
55e26eb95   Eric W. Biederman   sctp: Push struct...
437
  		struct net *net = sock_net(sk);
bb33381d0   Daniel Borkmann   net: sctp: rework...
438
439
440
  		pr_debug("%s: unrecognized next header type "
  			 "encountered!
  ", __func__);
25cc4ae91   Ying Xue   net: remove redun...
441
  		if (del_timer(&t->proto_unreach_timer))
057a10fa1   Xin Long   sctp: change to h...
442
  			sctp_transport_put(t);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443

55e26eb95   Eric W. Biederman   sctp: Push struct...
444
  		sctp_do_sm(net, SCTP_EVENT_T_OTHER,
50b5d6ad6   Vlad Yasevich   sctp: Fix a race ...
445
446
447
448
  			   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
  			   asoc->state, asoc->ep, asoc, t,
  			   GFP_ATOMIC);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
450
451
  }
  
  /* Common lookup code for icmp/icmpv6 error handler. */
4110cc255   Eric W. Biederman   sctp: Make the as...
452
  struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
  			     struct sctphdr *sctphdr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
455
456
  			     struct sctp_association **app,
  			     struct sctp_transport **tpp)
  {
804ec7ebe   Davide Caratti   sctp: fix ICMP pr...
457
  	struct sctp_init_chunk *chunkhdr, _chunkhdr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
460
461
  	union sctp_addr saddr;
  	union sctp_addr daddr;
  	struct sctp_af *af;
  	struct sock *sk = NULL;
8de8c8738   Sridhar Samudrala   [SCTP]: Set sk_er...
462
  	struct sctp_association *asoc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
  	struct sctp_transport *transport = NULL;
7115e632f   Wei Yongjun   sctp: Validate In...
464
  	__u32 vtag = ntohl(sctphdr->vtag);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465

d1ad1ff29   Sridhar Samudrala   [SCTP]: Fix poten...
466
  	*app = NULL; *tpp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
468
469
470
471
472
473
474
475
476
477
478
479
  
  	af = sctp_get_af_specific(family);
  	if (unlikely(!af)) {
  		return NULL;
  	}
  
  	/* Initialize local addresses for lookups. */
  	af->from_skb(&saddr, skb, 1);
  	af->from_skb(&daddr, skb, 0);
  
  	/* Look for an association that matches the incoming ICMP error
  	 * packet.
  	 */
4110cc255   Eric W. Biederman   sctp: Make the as...
480
  	asoc = __sctp_lookup_association(net, &saddr, &daddr, &transport);
d1ad1ff29   Sridhar Samudrala   [SCTP]: Fix poten...
481
482
  	if (!asoc)
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483

d1ad1ff29   Sridhar Samudrala   [SCTP]: Fix poten...
484
  	sk = asoc->base.sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485

7115e632f   Wei Yongjun   sctp: Validate In...
486
487
488
489
490
491
492
493
494
495
496
497
498
  	/* RFC 4960, Appendix C. ICMP Handling
  	 *
  	 * ICMP6) An implementation MUST validate that the Verification Tag
  	 * contained in the ICMP message matches the Verification Tag of
  	 * the peer.  If the Verification Tag is not 0 and does NOT
  	 * match, discard the ICMP message.  If it is 0 and the ICMP
  	 * message contains enough bytes to verify that the chunk type is
  	 * an INIT chunk and that the Initiate Tag matches the tag of the
  	 * peer, continue with ICMP7.  If the ICMP message is too short
  	 * or the chunk type or the Initiate Tag does not match, silently
  	 * discard the packet.
  	 */
  	if (vtag == 0) {
804ec7ebe   Davide Caratti   sctp: fix ICMP pr...
499
500
501
502
503
504
  		/* chunk header + first 4 octects of init header */
  		chunkhdr = skb_header_pointer(skb, skb_transport_offset(skb) +
  					      sizeof(struct sctphdr),
  					      sizeof(struct sctp_chunkhdr) +
  					      sizeof(__be32), &_chunkhdr);
  		if (!chunkhdr ||
7115e632f   Wei Yongjun   sctp: Validate In...
505
  		    chunkhdr->chunk_hdr.type != SCTP_CID_INIT ||
804ec7ebe   Davide Caratti   sctp: fix ICMP pr...
506
  		    ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag)
7115e632f   Wei Yongjun   sctp: Validate In...
507
  			goto out;
804ec7ebe   Davide Caratti   sctp: fix ICMP pr...
508

7115e632f   Wei Yongjun   sctp: Validate In...
509
  	} else if (vtag != asoc->c.peer_vtag) {
d1ad1ff29   Sridhar Samudrala   [SCTP]: Fix poten...
510
511
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512

5bc1d1b4a   wangweidong   sctp: remove macr...
513
  	bh_lock_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
516
517
518
  
  	/* If too many ICMPs get dropped on busy
  	 * servers this needs to be solved differently.
  	 */
  	if (sock_owned_by_user(sk))
02a1d6e7a   Eric Dumazet   net: rename NET_{...
519
  		__NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
522
523
524
525
  	*app = asoc;
  	*tpp = transport;
  	return sk;
  
  out:
dae399d7f   Xin Long   sctp: hold transp...
526
  	sctp_transport_put(transport);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
528
529
530
  	return NULL;
  }
  
  /* Common cleanup code for icmp/icmpv6 error handler. */
dae399d7f   Xin Long   sctp: hold transp...
531
  void sctp_err_finish(struct sock *sk, struct sctp_transport *t)
887cf3d13   Jules Irenge   sctp: Add missing...
532
  	__releases(&((__sk)->sk_lock.slock))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533
  {
5bc1d1b4a   wangweidong   sctp: remove macr...
534
  	bh_unlock_sock(sk);
dae399d7f   Xin Long   sctp: hold transp...
535
  	sctp_transport_put(t);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
  }
  
  /*
   * This routine is called by the ICMP module when it gets some
   * sort of error condition.  If err < 0 then the socket should
   * be closed and the error returned to the user.  If err > 0
   * it's just the icmp type << 8 | icmp code.  After adjustment
   * header points to the first 8 bytes of the sctp header.  We need
   * to find the appropriate port.
   *
   * The locking strategy used here is very "optimistic". When
   * someone else accesses the socket the ICMP is just dropped
   * and for some paths there is no check at all.
   * A more general error queue to queue errors for later handling
   * is probably better.
   *
   */
32bbd8793   Stefano Brivio   net: Convert prot...
553
  int sctp_v4_err(struct sk_buff *skb, __u32 info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
  {
b71d1d426   Eric Dumazet   inet: constify ip...
555
  	const struct iphdr *iph = (const struct iphdr *)skb->data;
a27ef749e   Arnaldo Carvalho de Melo   [SCTP]: Eliminate...
556
  	const int ihlen = iph->ihl * 4;
88c7664f1   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
557
558
  	const int type = icmp_hdr(skb)->type;
  	const int code = icmp_hdr(skb)->code;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
  	struct sock *sk;
8de8c8738   Sridhar Samudrala   [SCTP]: Set sk_er...
560
  	struct sctp_association *asoc = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561
562
  	struct sctp_transport *transport;
  	struct inet_sock *inet;
aef6de511   Simon Horman   sctp: Correct byt...
563
  	__u16 saveip, savesctp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
  	int err;
4110cc255   Eric W. Biederman   sctp: Make the as...
565
  	struct net *net = dev_net(skb->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
  	/* Fix up skb to look at the embedded net header. */
b0e380b1d   Arnaldo Carvalho de Melo   [SK_BUFF]: unions...
568
569
  	saveip = skb->network_header;
  	savesctp = skb->transport_header;
31c7711b5   Arnaldo Carvalho de Melo   [SK_BUFF]: Some m...
570
  	skb_reset_network_header(skb);
a27ef749e   Arnaldo Carvalho de Melo   [SCTP]: Eliminate...
571
  	skb_set_transport_header(skb, ihlen);
4110cc255   Eric W. Biederman   sctp: Make the as...
572
  	sk = sctp_err_lookup(net, AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
2e07fa9cd   Arnaldo Carvalho de Melo   [SK_BUFF]: Use of...
573
  	/* Put back, the original values. */
b0e380b1d   Arnaldo Carvalho de Melo   [SK_BUFF]: unions...
574
575
  	skb->network_header = saveip;
  	skb->transport_header = savesctp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
  	if (!sk) {
5d3848bc3   Eric Dumazet   net: rename ICMP_...
577
  		__ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
32bbd8793   Stefano Brivio   net: Convert prot...
578
  		return -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
  	}
  	/* Warning:  The sock lock is held.  Remember to call
  	 * sctp_err_finish!
  	 */
  
  	switch (type) {
  	case ICMP_PARAMETERPROB:
  		err = EPROTO;
  		break;
  	case ICMP_DEST_UNREACH:
  		if (code > NR_ICMP_UNREACH)
  			goto out_unlock;
  
  		/* PMTU discovery (RFC1191) */
  		if (ICMP_FRAG_NEEDED == code) {
3822a5ff4   Marcelo Ricardo Leitner   sctp: align MTU t...
594
  			sctp_icmp_frag_needed(sk, asoc, transport,
e2f036a97   Marcelo Ricardo Leitner   sctp: rename WORD...
595
  					      SCTP_TRUNC4(info));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
  			goto out_unlock;
8d72651d8   wangweidong   sctp: fix checkpa...
597
  		} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
  			if (ICMP_PROT_UNREACH == code) {
d1ad1ff29   Sridhar Samudrala   [SCTP]: Fix poten...
599
  				sctp_icmp_proto_unreachable(sk, asoc,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
  							    transport);
  				goto out_unlock;
  			}
  		}
  		err = icmp_err_convert[code].errno;
  		break;
  	case ICMP_TIME_EXCEEDED:
  		/* Ignore any time exceeded errors due to fragment reassembly
  		 * timeouts.
  		 */
  		if (ICMP_EXC_FRAGTIME == code)
  			goto out_unlock;
  
  		err = EHOSTUNREACH;
  		break;
55be7a9c6   David S. Miller   ipv4: Add redirec...
615
616
  	case ICMP_REDIRECT:
  		sctp_icmp_redirect(sk, transport, skb);
3f96a5321   Daniel Borkmann   net: sctp: rfc444...
617
  		/* Fall through to out_unlock. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
618
619
620
621
622
623
624
625
626
627
628
629
630
  	default:
  		goto out_unlock;
  	}
  
  	inet = inet_sk(sk);
  	if (!sock_owned_by_user(sk) && inet->recverr) {
  		sk->sk_err = err;
  		sk->sk_error_report(sk);
  	} else {  /* Only an error on timeout */
  		sk->sk_err_soft = err;
  	}
  
  out_unlock:
dae399d7f   Xin Long   sctp: hold transp...
631
  	sctp_err_finish(sk, transport);
32bbd8793   Stefano Brivio   net: Convert prot...
632
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633
634
635
636
637
638
639
640
641
642
643
644
645
646
  }
  
  /*
   * RFC 2960, 8.4 - Handle "Out of the blue" Packets.
   *
   * This function scans all the chunks in the OOTB packet to determine if
   * the packet should be discarded right away.  If a response might be needed
   * for this packet, or, if further processing is possible, the packet will
   * be queued to a proper inqueue for the next phase of handling.
   *
   * Output:
   * Return 0 - If further processing is needed.
   * Return 1 - If the packet can be discarded right away.
   */
046752104   sebastian@breakpoint.cc   sctp: make locall...
647
  static int sctp_rcv_ootb(struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
  {
922dbc5be   Xin Long   sctp: remove the ...
649
  	struct sctp_chunkhdr *ch, _ch;
3acb50c18   Marcelo Ricardo Leitner   sctp: delay as mu...
650
  	int ch_end, offset = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
  
  	/* Scan through all the chunks in the packet.  */
a7d1f1b66   Tsutomu Fujii   [SCTP]: Fix sctp_...
653
  	do {
3acb50c18   Marcelo Ricardo Leitner   sctp: delay as mu...
654
  		/* Make sure we have at least the header there */
922dbc5be   Xin Long   sctp: remove the ...
655
  		if (offset + sizeof(_ch) > skb->len)
3acb50c18   Marcelo Ricardo Leitner   sctp: delay as mu...
656
657
658
  			break;
  
  		ch = skb_header_pointer(skb, offset, sizeof(*ch), &_ch);
a7d1f1b66   Tsutomu Fujii   [SCTP]: Fix sctp_...
659
  		/* Break out if chunk length is less then minimal. */
922dbc5be   Xin Long   sctp: remove the ...
660
  		if (ntohs(ch->length) < sizeof(_ch))
a7d1f1b66   Tsutomu Fujii   [SCTP]: Fix sctp_...
661
  			break;
e2f036a97   Marcelo Ricardo Leitner   sctp: rename WORD...
662
  		ch_end = offset + SCTP_PAD4(ntohs(ch->length));
3acb50c18   Marcelo Ricardo Leitner   sctp: delay as mu...
663
  		if (ch_end > skb->len)
a7d1f1b66   Tsutomu Fujii   [SCTP]: Fix sctp_...
664
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
666
667
668
669
670
671
672
673
674
675
676
677
678
  
  		/* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the
  		 * receiver MUST silently discard the OOTB packet and take no
  		 * further action.
  		 */
  		if (SCTP_CID_ABORT == ch->type)
  			goto discard;
  
  		/* RFC 8.4, 6) If the packet contains a SHUTDOWN COMPLETE
  		 * chunk, the receiver should silently discard the packet
  		 * and take no further action.
  		 */
  		if (SCTP_CID_SHUTDOWN_COMPLETE == ch->type)
  			goto discard;
3c77f961b   Vlad Yasevich   SCTP: Discard OOT...
679
680
681
682
683
684
685
  		/* RFC 4460, 2.11.2
  		 * This will discard packets with INIT chunk bundled as
  		 * subsequent chunks in the packet.  When INIT is first,
  		 * the normal INIT processing will discard the chunk.
  		 */
  		if (SCTP_CID_INIT == ch->type && (void *)ch != skb->data)
  			goto discard;
3acb50c18   Marcelo Ricardo Leitner   sctp: delay as mu...
686
687
  		offset = ch_end;
  	} while (ch_end < skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
689
690
691
692
693
694
695
  
  	return 0;
  
  discard:
  	return 1;
  }
  
  /* Insert endpoint into the hash table.  */
76c6d988a   Xin Long   sctp: add sock_re...
696
  static int __sctp_hash_endpoint(struct sctp_endpoint *ep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
  {
76c6d988a   Xin Long   sctp: add sock_re...
698
699
  	struct sock *sk = ep->base.sk;
  	struct net *net = sock_net(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
  	struct sctp_hashbucket *head;
76c6d988a   Xin Long   sctp: add sock_re...
701
  	struct sctp_ep_common *epb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
703
  
  	epb = &ep->base;
4cdadcbcb   Eric W. Biederman   sctp: Make the en...
704
  	epb->hashent = sctp_ep_hashfn(net, epb->bind_addr.port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
  	head = &sctp_ep_hashtable[epb->hashent];
76c6d988a   Xin Long   sctp: add sock_re...
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
  	if (sk->sk_reuseport) {
  		bool any = sctp_is_ep_boundall(sk);
  		struct sctp_ep_common *epb2;
  		struct list_head *list;
  		int cnt = 0, err = 1;
  
  		list_for_each(list, &ep->base.bind_addr.address_list)
  			cnt++;
  
  		sctp_for_each_hentry(epb2, &head->chain) {
  			struct sock *sk2 = epb2->sk;
  
  			if (!net_eq(sock_net(sk2), net) || sk2 == sk ||
  			    !uid_eq(sock_i_uid(sk2), sock_i_uid(sk)) ||
  			    !sk2->sk_reuseport)
  				continue;
  
  			err = sctp_bind_addrs_check(sctp_sk(sk2),
  						    sctp_sk(sk), cnt);
  			if (!err) {
  				err = reuseport_add_sock(sk, sk2, any);
  				if (err)
  					return err;
  				break;
  			} else if (err < 0) {
  				return err;
  			}
  		}
  
  		if (err) {
  			err = reuseport_alloc(sk, any);
  			if (err)
  				return err;
  		}
  	}
387602dfd   wangweidong   sctp: remove macr...
741
  	write_lock(&head->lock);
d970dbf84   Vlad Yasevich   SCTP: Convert cus...
742
  	hlist_add_head(&epb->node, &head->chain);
387602dfd   wangweidong   sctp: remove macr...
743
  	write_unlock(&head->lock);
76c6d988a   Xin Long   sctp: add sock_re...
744
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
746
747
  }
  
  /* Add an endpoint to the hash. Local BH-safe. */
76c6d988a   Xin Long   sctp: add sock_re...
748
  int sctp_hash_endpoint(struct sctp_endpoint *ep)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749
  {
76c6d988a   Xin Long   sctp: add sock_re...
750
  	int err;
79b91130a   wangweidong   sctp: remove macr...
751
  	local_bh_disable();
76c6d988a   Xin Long   sctp: add sock_re...
752
  	err = __sctp_hash_endpoint(ep);
79b91130a   wangweidong   sctp: remove macr...
753
  	local_bh_enable();
76c6d988a   Xin Long   sctp: add sock_re...
754
755
  
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
757
758
759
760
  }
  
  /* Remove endpoint from the hash table.  */
  static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
  {
76c6d988a   Xin Long   sctp: add sock_re...
761
  	struct sock *sk = ep->base.sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
762
763
764
765
  	struct sctp_hashbucket *head;
  	struct sctp_ep_common *epb;
  
  	epb = &ep->base;
76c6d988a   Xin Long   sctp: add sock_re...
766
  	epb->hashent = sctp_ep_hashfn(sock_net(sk), epb->bind_addr.port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
768
  
  	head = &sctp_ep_hashtable[epb->hashent];
76c6d988a   Xin Long   sctp: add sock_re...
769
770
  	if (rcu_access_pointer(sk->sk_reuseport_cb))
  		reuseport_detach_sock(sk);
387602dfd   wangweidong   sctp: remove macr...
771
  	write_lock(&head->lock);
2eebc1e18   Neil Horman   sctp: Fix list co...
772
  	hlist_del_init(&epb->node);
387602dfd   wangweidong   sctp: remove macr...
773
  	write_unlock(&head->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
775
776
777
778
  }
  
  /* Remove endpoint from the hash.  Local BH-safe. */
  void sctp_unhash_endpoint(struct sctp_endpoint *ep)
  {
79b91130a   wangweidong   sctp: remove macr...
779
  	local_bh_disable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
780
  	__sctp_unhash_endpoint(ep);
79b91130a   wangweidong   sctp: remove macr...
781
  	local_bh_enable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782
  }
532ae2f10   Xin Long   sctp: do reusepor...
783
784
785
786
787
788
789
790
791
792
793
794
795
  static inline __u32 sctp_hashfn(const struct net *net, __be16 lport,
  				const union sctp_addr *paddr, __u32 seed)
  {
  	__u32 addr;
  
  	if (paddr->sa.sa_family == AF_INET6)
  		addr = jhash(&paddr->v6.sin6_addr, 16, seed);
  	else
  		addr = (__force __u32)paddr->v4.sin_addr.s_addr;
  
  	return  jhash_3words(addr, ((__force __u32)paddr->v4.sin_port) << 16 |
  			     (__force __u32)lport, net_hash_mix(net), seed);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
  /* Look up an endpoint. */
532ae2f10   Xin Long   sctp: do reusepor...
797
798
799
800
  static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(
  					struct net *net, struct sk_buff *skb,
  					const union sctp_addr *laddr,
  					const union sctp_addr *paddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
801
802
803
804
  {
  	struct sctp_hashbucket *head;
  	struct sctp_ep_common *epb;
  	struct sctp_endpoint *ep;
532ae2f10   Xin Long   sctp: do reusepor...
805
806
  	struct sock *sk;
  	__be16 lport;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
  	int hash;
532ae2f10   Xin Long   sctp: do reusepor...
808
809
  	lport = laddr->v4.sin_port;
  	hash = sctp_ep_hashfn(net, ntohs(lport));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810
811
  	head = &sctp_ep_hashtable[hash];
  	read_lock(&head->lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
812
  	sctp_for_each_hentry(epb, &head->chain) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
813
  		ep = sctp_ep(epb);
4cdadcbcb   Eric W. Biederman   sctp: Make the en...
814
  		if (sctp_endpoint_is_match(ep, net, laddr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
816
  			goto hit;
  	}
2ce955035   Eric W. Biederman   sctp: Make the ct...
817
  	ep = sctp_sk(net->sctp.ctl_sock)->ep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818
819
  
  hit:
532ae2f10   Xin Long   sctp: do reusepor...
820
821
822
823
824
825
826
827
828
  	sk = ep->base.sk;
  	if (sk->sk_reuseport) {
  		__u32 phash = sctp_hashfn(net, lport, paddr, 0);
  
  		sk = reuseport_select_sock(sk, phash, skb,
  					   sizeof(struct sctphdr));
  		if (sk)
  			ep = sctp_sk(sk)->ep;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
  	sctp_endpoint_hold(ep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830
831
832
  	read_unlock(&head->lock);
  	return ep;
  }
d6c0256a6   Xin Long   sctp: add the rha...
833
834
  /* rhashtable for transport */
  struct sctp_hash_cmp_arg {
7fda702f9   Xin Long   sctp: use new rhl...
835
836
  	const union sctp_addr	*paddr;
  	const struct net	*net;
8d32503ef   Xin Long   sctp: fix some ty...
837
  	__be16			lport;
d6c0256a6   Xin Long   sctp: add the rha...
838
839
840
841
842
  };
  
  static inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg,
  				const void *ptr)
  {
715f5552b   Xin Long   sctp: hold the tr...
843
  	struct sctp_transport *t = (struct sctp_transport *)ptr;
d6c0256a6   Xin Long   sctp: add the rha...
844
  	const struct sctp_hash_cmp_arg *x = arg->key;
715f5552b   Xin Long   sctp: hold the tr...
845
  	int err = 1;
d6c0256a6   Xin Long   sctp: add the rha...
846

d6c0256a6   Xin Long   sctp: add the rha...
847
  	if (!sctp_cmp_addr_exact(&t->ipaddr, x->paddr))
715f5552b   Xin Long   sctp: hold the tr...
848
849
850
  		return err;
  	if (!sctp_transport_hold(t))
  		return err;
312434617   Xin Long   sctp: cache netns...
851
  	if (!net_eq(t->asoc->base.net, x->net))
7fda702f9   Xin Long   sctp: use new rhl...
852
853
  		goto out;
  	if (x->lport != htons(t->asoc->base.bind_addr.port))
715f5552b   Xin Long   sctp: hold the tr...
854
  		goto out;
d6c0256a6   Xin Long   sctp: add the rha...
855

715f5552b   Xin Long   sctp: hold the tr...
856
857
858
859
  	err = 0;
  out:
  	sctp_transport_put(t);
  	return err;
d6c0256a6   Xin Long   sctp: add the rha...
860
  }
8d32503ef   Xin Long   sctp: fix some ty...
861
  static inline __u32 sctp_hash_obj(const void *data, u32 len, u32 seed)
d6c0256a6   Xin Long   sctp: add the rha...
862
863
  {
  	const struct sctp_transport *t = data;
d6c0256a6   Xin Long   sctp: add the rha...
864

312434617   Xin Long   sctp: cache netns...
865
  	return sctp_hashfn(t->asoc->base.net,
532ae2f10   Xin Long   sctp: do reusepor...
866
867
  			   htons(t->asoc->base.bind_addr.port),
  			   &t->ipaddr, seed);
d6c0256a6   Xin Long   sctp: add the rha...
868
  }
8d32503ef   Xin Long   sctp: fix some ty...
869
  static inline __u32 sctp_hash_key(const void *data, u32 len, u32 seed)
d6c0256a6   Xin Long   sctp: add the rha...
870
871
  {
  	const struct sctp_hash_cmp_arg *x = data;
d6c0256a6   Xin Long   sctp: add the rha...
872

532ae2f10   Xin Long   sctp: do reusepor...
873
  	return sctp_hashfn(x->net, x->lport, x->paddr, seed);
d6c0256a6   Xin Long   sctp: add the rha...
874
875
876
877
878
879
880
881
882
883
884
885
  }
  
  static const struct rhashtable_params sctp_hash_params = {
  	.head_offset		= offsetof(struct sctp_transport, node),
  	.hashfn			= sctp_hash_key,
  	.obj_hashfn		= sctp_hash_obj,
  	.obj_cmpfn		= sctp_hash_cmp,
  	.automatic_shrinking	= true,
  };
  
  int sctp_transport_hashtable_init(void)
  {
7fda702f9   Xin Long   sctp: use new rhl...
886
  	return rhltable_init(&sctp_transport_hashtable, &sctp_hash_params);
d6c0256a6   Xin Long   sctp: add the rha...
887
888
889
890
  }
  
  void sctp_transport_hashtable_destroy(void)
  {
7fda702f9   Xin Long   sctp: use new rhl...
891
  	rhltable_destroy(&sctp_transport_hashtable);
d6c0256a6   Xin Long   sctp: add the rha...
892
  }
7fda702f9   Xin Long   sctp: use new rhl...
893
  int sctp_hash_transport(struct sctp_transport *t)
d6c0256a6   Xin Long   sctp: add the rha...
894
  {
cd2b70875   Xin Long   sctp: check dupli...
895
896
  	struct sctp_transport *transport;
  	struct rhlist_head *tmp, *list;
d6c0256a6   Xin Long   sctp: add the rha...
897
  	struct sctp_hash_cmp_arg arg;
7fda702f9   Xin Long   sctp: use new rhl...
898
  	int err;
d6c0256a6   Xin Long   sctp: add the rha...
899

dd7445ad6   Xin Long   sctp: the temp as...
900
  	if (t->asoc->temp)
7fda702f9   Xin Long   sctp: use new rhl...
901
  		return 0;
dd7445ad6   Xin Long   sctp: the temp as...
902

4e7696d90   Xin Long   sctp: get netns f...
903
  	arg.net   = t->asoc->base.net;
7fda702f9   Xin Long   sctp: use new rhl...
904
905
  	arg.paddr = &t->ipaddr;
  	arg.lport = htons(t->asoc->base.bind_addr.port);
d6c0256a6   Xin Long   sctp: add the rha...
906

5179b2669   Xin Long   sctp: call rcu_re...
907
  	rcu_read_lock();
cd2b70875   Xin Long   sctp: check dupli...
908
909
910
911
912
  	list = rhltable_lookup(&sctp_transport_hashtable, &arg,
  			       sctp_hash_params);
  
  	rhl_for_each_entry_rcu(transport, tmp, list, node)
  		if (transport->asoc->ep == t->asoc->ep) {
5179b2669   Xin Long   sctp: call rcu_re...
913
  			rcu_read_unlock();
27af86bb0   Xin Long   sctp: do not pr_e...
914
  			return -EEXIST;
cd2b70875   Xin Long   sctp: check dupli...
915
  		}
5179b2669   Xin Long   sctp: call rcu_re...
916
  	rcu_read_unlock();
cd2b70875   Xin Long   sctp: check dupli...
917

7fda702f9   Xin Long   sctp: use new rhl...
918
919
920
921
922
923
924
  	err = rhltable_insert_key(&sctp_transport_hashtable, &arg,
  				  &t->node, sctp_hash_params);
  	if (err)
  		pr_err_once("insert transport fail, errno %d
  ", err);
  
  	return err;
d6c0256a6   Xin Long   sctp: add the rha...
925
926
927
928
  }
  
  void sctp_unhash_transport(struct sctp_transport *t)
  {
dd7445ad6   Xin Long   sctp: the temp as...
929
930
  	if (t->asoc->temp)
  		return;
7fda702f9   Xin Long   sctp: use new rhl...
931
932
  	rhltable_remove(&sctp_transport_hashtable, &t->node,
  			sctp_hash_params);
d6c0256a6   Xin Long   sctp: add the rha...
933
  }
7fda702f9   Xin Long   sctp: use new rhl...
934
  /* return a transport with holding it */
d6c0256a6   Xin Long   sctp: add the rha...
935
936
937
938
939
  struct sctp_transport *sctp_addrs_lookup_transport(
  				struct net *net,
  				const union sctp_addr *laddr,
  				const union sctp_addr *paddr)
  {
7fda702f9   Xin Long   sctp: use new rhl...
940
941
  	struct rhlist_head *tmp, *list;
  	struct sctp_transport *t;
d6c0256a6   Xin Long   sctp: add the rha...
942
  	struct sctp_hash_cmp_arg arg = {
d6c0256a6   Xin Long   sctp: add the rha...
943
944
  		.paddr = paddr,
  		.net   = net,
7fda702f9   Xin Long   sctp: use new rhl...
945
  		.lport = laddr->v4.sin_port,
d6c0256a6   Xin Long   sctp: add the rha...
946
  	};
7fda702f9   Xin Long   sctp: use new rhl...
947
948
949
950
951
952
953
954
955
956
957
958
959
960
  	list = rhltable_lookup(&sctp_transport_hashtable, &arg,
  			       sctp_hash_params);
  
  	rhl_for_each_entry_rcu(t, tmp, list, node) {
  		if (!sctp_transport_hold(t))
  			continue;
  
  		if (sctp_bind_addr_match(&t->asoc->base.bind_addr,
  					 laddr, sctp_sk(t->asoc->base.sk)))
  			return t;
  		sctp_transport_put(t);
  	}
  
  	return NULL;
d6c0256a6   Xin Long   sctp: add the rha...
961
  }
7fda702f9   Xin Long   sctp: use new rhl...
962
  /* return a transport without holding it, as it's only used under sock lock */
d6c0256a6   Xin Long   sctp: add the rha...
963
964
965
966
  struct sctp_transport *sctp_epaddr_lookup_transport(
  				const struct sctp_endpoint *ep,
  				const union sctp_addr *paddr)
  {
7fda702f9   Xin Long   sctp: use new rhl...
967
968
  	struct rhlist_head *tmp, *list;
  	struct sctp_transport *t;
65a5124a7   Xin Long   sctp: support to ...
969
  	struct sctp_hash_cmp_arg arg = {
65a5124a7   Xin Long   sctp: support to ...
970
  		.paddr = paddr,
4e7696d90   Xin Long   sctp: get netns f...
971
  		.net   = ep->base.net,
7fda702f9   Xin Long   sctp: use new rhl...
972
  		.lport = htons(ep->base.bind_addr.port),
65a5124a7   Xin Long   sctp: support to ...
973
  	};
d6c0256a6   Xin Long   sctp: add the rha...
974

7fda702f9   Xin Long   sctp: use new rhl...
975
976
977
978
979
980
981
982
  	list = rhltable_lookup(&sctp_transport_hashtable, &arg,
  			       sctp_hash_params);
  
  	rhl_for_each_entry_rcu(t, tmp, list, node)
  		if (ep == t->asoc->ep)
  			return t;
  
  	return NULL;
d6c0256a6   Xin Long   sctp: add the rha...
983
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
984
985
  /* Look up an association. */
  static struct sctp_association *__sctp_lookup_association(
4110cc255   Eric W. Biederman   sctp: Make the as...
986
  					struct net *net,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987
988
989
990
  					const union sctp_addr *local,
  					const union sctp_addr *peer,
  					struct sctp_transport **pt)
  {
4f0087812   Xin Long   sctp: apply rhash...
991
  	struct sctp_transport *t;
1eed67793   Xin Long   sctp: fix the tra...
992
  	struct sctp_association *asoc = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
993

4f0087812   Xin Long   sctp: apply rhash...
994
  	t = sctp_addrs_lookup_transport(net, local, peer);
7fda702f9   Xin Long   sctp: use new rhl...
995
  	if (!t)
1eed67793   Xin Long   sctp: fix the tra...
996
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
997

1eed67793   Xin Long   sctp: fix the tra...
998
  	asoc = t->asoc;
4f0087812   Xin Long   sctp: apply rhash...
999
  	*pt = t;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1000

1eed67793   Xin Long   sctp: fix the tra...
1001
  out:
1eed67793   Xin Long   sctp: fix the tra...
1002
  	return asoc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1003
  }
4f0087812   Xin Long   sctp: apply rhash...
1004
  /* Look up an association. protected by RCU read lock */
dda919285   Daniel Borkmann   net: sctp: remove...
1005
  static
4110cc255   Eric W. Biederman   sctp: Make the as...
1006
1007
  struct sctp_association *sctp_lookup_association(struct net *net,
  						 const union sctp_addr *laddr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1008
  						 const union sctp_addr *paddr,
dda919285   Daniel Borkmann   net: sctp: remove...
1009
  						 struct sctp_transport **transportp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1010
1011
  {
  	struct sctp_association *asoc;
f46c7011b   Xin Long   sctp: move rcu_re...
1012
  	rcu_read_lock();
4110cc255   Eric W. Biederman   sctp: Make the as...
1013
  	asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
f46c7011b   Xin Long   sctp: move rcu_re...
1014
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1015
1016
1017
1018
1019
  
  	return asoc;
  }
  
  /* Is there an association matching the given local and peer addresses? */
530665385   Xin Long   sctp: remove unne...
1020
1021
1022
  bool sctp_has_association(struct net *net,
  			  const union sctp_addr *laddr,
  			  const union sctp_addr *paddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1023
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1024
  	struct sctp_transport *transport;
530665385   Xin Long   sctp: remove unne...
1025
  	if (sctp_lookup_association(net, laddr, paddr, &transport)) {
dae399d7f   Xin Long   sctp: hold transp...
1026
  		sctp_transport_put(transport);
530665385   Xin Long   sctp: remove unne...
1027
  		return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1028
  	}
530665385   Xin Long   sctp: remove unne...
1029
  	return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
  }
  
  /*
   * SCTP Implementors Guide, 2.18 Handling of address
   * parameters within the INIT or INIT-ACK.
   *
   * D) When searching for a matching TCB upon reception of an INIT
   *    or INIT-ACK chunk the receiver SHOULD use not only the
   *    source address of the packet (containing the INIT or
   *    INIT-ACK) but the receiver SHOULD also use all valid
   *    address parameters contained within the chunk.
   *
   * 2.18.3 Solution description
   *
   * This new text clearly specifies to an implementor the need
   * to look within the INIT or INIT-ACK. Any implementation that
   * does not do this, may not be able to establish associations
   * in certain circumstances.
   *
   */
4110cc255   Eric W. Biederman   sctp: Make the as...
1050
1051
  static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
  	struct sk_buff *skb,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1052
1053
1054
1055
1056
  	const union sctp_addr *laddr, struct sctp_transport **transportp)
  {
  	struct sctp_association *asoc;
  	union sctp_addr addr;
  	union sctp_addr *paddr = &addr;
2c0fd387b   Arnaldo Carvalho de Melo   [SCTP]: Introduce...
1057
  	struct sctphdr *sh = sctp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1058
  	union sctp_params params;
01a992bea   Xin Long   sctp: remove the ...
1059
  	struct sctp_init_chunk *init;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1060
  	struct sctp_af *af;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
  	/*
  	 * This code will NOT touch anything inside the chunk--it is
  	 * strictly READ-ONLY.
  	 *
  	 * RFC 2960 3  SCTP packet Format
  	 *
  	 * Multiple chunks can be bundled into one SCTP packet up to
  	 * the MTU size, except for the INIT, INIT ACK, and SHUTDOWN
  	 * COMPLETE chunks.  These chunks MUST NOT be bundled with any
  	 * other chunk in a packet.  See Section 6.10 for more details
  	 * on chunk bundling.
  	 */
  
  	/* Find the start of the TLVs and the end of the chunk.  This is
  	 * the region we search for address parameters.
  	 */
01a992bea   Xin Long   sctp: remove the ...
1077
  	init = (struct sctp_init_chunk *)skb->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1078
1079
1080
1081
1082
1083
1084
1085
  
  	/* Walk the parameters looking for embedded addresses. */
  	sctp_walk_params(params, init, init_hdr.params) {
  
  		/* Note: Ignoring hostname addresses. */
  		af = sctp_get_af_specific(param_type2af(params.p->type));
  		if (!af)
  			continue;
dd86d136f   Al Viro   [SCTP]: Switch ->...
1086
  		af->from_addr_param(paddr, params.addr, sh->source, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1087

7c17fcc72   Xin Long   sctp: return back...
1088
  		asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
1090
1091
1092
1093
1094
  		if (asoc)
  			return asoc;
  	}
  
  	return NULL;
  }
df2185771   Vlad Yasevich   [SCTP]: Update as...
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
  /* ADD-IP, Section 5.2
   * When an endpoint receives an ASCONF Chunk from the remote peer
   * special procedures may be needed to identify the association the
   * ASCONF Chunk is associated with. To properly find the association
   * the following procedures SHOULD be followed:
   *
   * D2) If the association is not found, use the address found in the
   * Address Parameter TLV combined with the port number found in the
   * SCTP common header. If found proceed to rule D4.
   *
   * D2-ext) If more than one ASCONF Chunks are packed together, use the
   * address found in the ASCONF Address Parameter TLV of each of the
   * subsequent ASCONF Chunks. If found, proceed to rule D4.
   */
  static struct sctp_association *__sctp_rcv_asconf_lookup(
4110cc255   Eric W. Biederman   sctp: Make the as...
1110
  					struct net *net,
922dbc5be   Xin Long   sctp: remove the ...
1111
  					struct sctp_chunkhdr *ch,
df2185771   Vlad Yasevich   [SCTP]: Update as...
1112
  					const union sctp_addr *laddr,
bc92dd194   Al Viro   [SCTP]: fix misan...
1113
  					__be16 peer_port,
df2185771   Vlad Yasevich   [SCTP]: Update as...
1114
1115
  					struct sctp_transport **transportp)
  {
68d754694   Xin Long   sctp: remove the ...
1116
  	struct sctp_addip_chunk *asconf = (struct sctp_addip_chunk *)ch;
df2185771   Vlad Yasevich   [SCTP]: Update as...
1117
1118
1119
1120
1121
1122
  	struct sctp_af *af;
  	union sctp_addr_param *param;
  	union sctp_addr paddr;
  
  	/* Skip over the ADDIP header and find the Address parameter */
  	param = (union sctp_addr_param *)(asconf + 1);
6a435732a   Shan Wei   sctp: use common ...
1123
  	af = sctp_get_af_specific(param_type2af(param->p.type));
df2185771   Vlad Yasevich   [SCTP]: Update as...
1124
1125
1126
1127
  	if (unlikely(!af))
  		return NULL;
  
  	af->from_addr_param(&paddr, param, peer_port, 0);
4110cc255   Eric W. Biederman   sctp: Make the as...
1128
  	return __sctp_lookup_association(net, laddr, &paddr, transportp);
df2185771   Vlad Yasevich   [SCTP]: Update as...
1129
  }
bbd0d5980   Vlad Yasevich   [SCTP]: Implement...
1130
1131
1132
1133
1134
1135
1136
  /* SCTP-AUTH, Section 6.3:
  *    If the receiver does not find a STCB for a packet containing an AUTH
  *    chunk as the first chunk and not a COOKIE-ECHO chunk as the second
  *    chunk, it MUST use the chunks after the AUTH chunk to look up an existing
  *    association.
  *
  * This means that any chunks that can help us identify the association need
25985edce   Lucas De Marchi   Fix common misspe...
1137
  * to be looked at to find this association.
bbd0d5980   Vlad Yasevich   [SCTP]: Implement...
1138
  */
4110cc255   Eric W. Biederman   sctp: Make the as...
1139
1140
  static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
  				      struct sk_buff *skb,
bbd0d5980   Vlad Yasevich   [SCTP]: Implement...
1141
1142
1143
  				      const union sctp_addr *laddr,
  				      struct sctp_transport **transportp)
  {
df2185771   Vlad Yasevich   [SCTP]: Update as...
1144
  	struct sctp_association *asoc = NULL;
922dbc5be   Xin Long   sctp: remove the ...
1145
  	struct sctp_chunkhdr *ch;
df2185771   Vlad Yasevich   [SCTP]: Update as...
1146
1147
1148
1149
1150
1151
  	int have_auth = 0;
  	unsigned int chunk_num = 1;
  	__u8 *ch_end;
  
  	/* Walk through the chunks looking for AUTH or ASCONF chunks
  	 * to help us find the association.
bbd0d5980   Vlad Yasevich   [SCTP]: Implement...
1152
  	 */
922dbc5be   Xin Long   sctp: remove the ...
1153
  	ch = (struct sctp_chunkhdr *)skb->data;
df2185771   Vlad Yasevich   [SCTP]: Update as...
1154
1155
  	do {
  		/* Break out if chunk length is less then minimal. */
922dbc5be   Xin Long   sctp: remove the ...
1156
  		if (ntohs(ch->length) < sizeof(*ch))
df2185771   Vlad Yasevich   [SCTP]: Update as...
1157
  			break;
e2f036a97   Marcelo Ricardo Leitner   sctp: rename WORD...
1158
  		ch_end = ((__u8 *)ch) + SCTP_PAD4(ntohs(ch->length));
df2185771   Vlad Yasevich   [SCTP]: Update as...
1159
1160
  		if (ch_end > skb_tail_pointer(skb))
  			break;
cb3f837ba   wangweidong   sctp: fix checkpa...
1161
  		switch (ch->type) {
f7010e614   wangweidong   sctp: fix checkpa...
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
  		case SCTP_CID_AUTH:
  			have_auth = chunk_num;
  			break;
  
  		case SCTP_CID_COOKIE_ECHO:
  			/* If a packet arrives containing an AUTH chunk as
  			 * a first chunk, a COOKIE-ECHO chunk as the second
  			 * chunk, and possibly more chunks after them, and
  			 * the receiver does not have an STCB for that
  			 * packet, then authentication is based on
  			 * the contents of the COOKIE- ECHO chunk.
  			 */
  			if (have_auth == 1 && chunk_num == 2)
  				return NULL;
  			break;
  
  		case SCTP_CID_ASCONF:
  			if (have_auth || net->sctp.addip_noauth)
  				asoc = __sctp_rcv_asconf_lookup(
  						net, ch, laddr,
  						sctp_hdr(skb)->source,
  						transportp);
  		default:
  			break;
df2185771   Vlad Yasevich   [SCTP]: Update as...
1186
1187
1188
1189
  		}
  
  		if (asoc)
  			break;
922dbc5be   Xin Long   sctp: remove the ...
1190
  		ch = (struct sctp_chunkhdr *)ch_end;
df2185771   Vlad Yasevich   [SCTP]: Update as...
1191
1192
1193
1194
  		chunk_num++;
  	} while (ch_end < skb_tail_pointer(skb));
  
  	return asoc;
bbd0d5980   Vlad Yasevich   [SCTP]: Implement...
1195
1196
1197
1198
1199
1200
1201
1202
  }
  
  /*
   * There are circumstances when we need to look inside the SCTP packet
   * for information to help us find the association.   Examples
   * include looking inside of INIT/INIT-ACK chunks or after the AUTH
   * chunks.
   */
4110cc255   Eric W. Biederman   sctp: Make the as...
1203
1204
  static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net,
  				      struct sk_buff *skb,
bbd0d5980   Vlad Yasevich   [SCTP]: Implement...
1205
1206
1207
  				      const union sctp_addr *laddr,
  				      struct sctp_transport **transportp)
  {
922dbc5be   Xin Long   sctp: remove the ...
1208
  	struct sctp_chunkhdr *ch;
bbd0d5980   Vlad Yasevich   [SCTP]: Implement...
1209

90017accf   Marcelo Ricardo Leitner   sctp: Add GSO sup...
1210
1211
1212
1213
1214
  	/* We do not allow GSO frames here as we need to linearize and
  	 * then cannot guarantee frame boundaries. This shouldn't be an
  	 * issue as packets hitting this are mostly INIT or INIT-ACK and
  	 * those cannot be on GSO-style anyway.
  	 */
1dd27cde3   Daniel Axtens   net: use skb_is_g...
1215
  	if (skb_is_gso(skb) && skb_is_gso_sctp(skb))
90017accf   Marcelo Ricardo Leitner   sctp: Add GSO sup...
1216
  		return NULL;
922dbc5be   Xin Long   sctp: remove the ...
1217
  	ch = (struct sctp_chunkhdr *)skb->data;
bbd0d5980   Vlad Yasevich   [SCTP]: Implement...
1218

df2185771   Vlad Yasevich   [SCTP]: Update as...
1219
1220
1221
1222
1223
  	/* The code below will attempt to walk the chunk and extract
  	 * parameter information.  Before we do that, we need to verify
  	 * that the chunk length doesn't cause overflow.  Otherwise, we'll
  	 * walk off the end.
  	 */
e2f036a97   Marcelo Ricardo Leitner   sctp: rename WORD...
1224
  	if (SCTP_PAD4(ntohs(ch->length)) > skb->len)
df2185771   Vlad Yasevich   [SCTP]: Update as...
1225
  		return NULL;
bbd0d5980   Vlad Yasevich   [SCTP]: Implement...
1226
  	/* If this is INIT/INIT-ACK look inside the chunk too. */
f482f2fcd   wangweidong   sctp: remove the ...
1227
  	if (ch->type == SCTP_CID_INIT || ch->type == SCTP_CID_INIT_ACK)
4110cc255   Eric W. Biederman   sctp: Make the as...
1228
  		return __sctp_rcv_init_lookup(net, skb, laddr, transportp);
bbd0d5980   Vlad Yasevich   [SCTP]: Implement...
1229

f482f2fcd   wangweidong   sctp: remove the ...
1230
  	return __sctp_rcv_walk_lookup(net, skb, laddr, transportp);
bbd0d5980   Vlad Yasevich   [SCTP]: Implement...
1231
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1232
  /* Lookup an association for an inbound skb. */
4110cc255   Eric W. Biederman   sctp: Make the as...
1233
1234
  static struct sctp_association *__sctp_rcv_lookup(struct net *net,
  				      struct sk_buff *skb,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1235
1236
1237
1238
1239
  				      const union sctp_addr *paddr,
  				      const union sctp_addr *laddr,
  				      struct sctp_transport **transportp)
  {
  	struct sctp_association *asoc;
4110cc255   Eric W. Biederman   sctp: Make the as...
1240
  	asoc = __sctp_lookup_association(net, laddr, paddr, transportp);
b77b7565a   Marcelo Ricardo Leitner   sctp: add pr_debu...
1241
1242
  	if (asoc)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1243
1244
1245
1246
1247
  
  	/* Further lookup for INIT/INIT-ACK packets.
  	 * SCTP Implementors Guide, 2.18 Handling of address
  	 * parameters within the INIT or INIT-ACK.
  	 */
b77b7565a   Marcelo Ricardo Leitner   sctp: add pr_debu...
1248
1249
1250
  	asoc = __sctp_rcv_lookup_harder(net, skb, laddr, transportp);
  	if (asoc)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1251

b77b7565a   Marcelo Ricardo Leitner   sctp: add pr_debu...
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
  	if (paddr->sa.sa_family == AF_INET)
  		pr_debug("sctp: asoc not found for src:%pI4:%d dst:%pI4:%d
  ",
  			 &laddr->v4.sin_addr, ntohs(laddr->v4.sin_port),
  			 &paddr->v4.sin_addr, ntohs(paddr->v4.sin_port));
  	else
  		pr_debug("sctp: asoc not found for src:%pI6:%d dst:%pI6:%d
  ",
  			 &laddr->v6.sin6_addr, ntohs(laddr->v6.sin6_port),
  			 &paddr->v6.sin6_addr, ntohs(paddr->v6.sin6_port));
  
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1264
1265
  	return asoc;
  }