socket.c 257 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* SCTP kernel implementation
Linus Torvalds's avatar
Linus Torvalds committed
3
4
5
6
7
8
9
 * (C) Copyright IBM Corp. 2001, 2004
 * Copyright (c) 1999-2000 Cisco, Inc.
 * Copyright (c) 1999-2001 Motorola, Inc.
 * Copyright (c) 2001-2003 Intel Corp.
 * Copyright (c) 2001-2002 Nokia, Inc.
 * Copyright (c) 2001 La Monte H.P. Yarroll
 *
10
 * This file is part of the SCTP kernel implementation
Linus Torvalds's avatar
Linus Torvalds committed
11
12
13
14
15
16
17
18
19
20
 *
 * These functions interface with the sockets layer to implement the
 * SCTP Extensions for the Sockets API.
 *
 * Note that the descriptions from the specification are USER level
 * functions--this file is the functions which populate the struct proto
 * for SCTP which is the BOTTOM of the sockets interface.
 *
 * Please send any bug reports or fixes you make to the
 * email address(es):
21
 *    lksctp developers <linux-sctp@vger.kernel.org>
Linus Torvalds's avatar
Linus Torvalds committed
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 *
 * Written or modified by:
 *    La Monte H.P. Yarroll <piggy@acm.org>
 *    Narasimha Budihal     <narsi@refcode.org>
 *    Karl Knutson          <karl@athena.chicago.il.us>
 *    Jon Grimm             <jgrimm@us.ibm.com>
 *    Xingang Guo           <xingang.guo@intel.com>
 *    Daisy Chang           <daisyc@us.ibm.com>
 *    Sridhar Samudrala     <samudrala@us.ibm.com>
 *    Inaky Perez-Gonzalez  <inaky.gonzalez@intel.com>
 *    Ardelle Fan	    <ardelle.fan@intel.com>
 *    Ryan Layer	    <rmlayer@us.ibm.com>
 *    Anup Pemmaiah         <pemmaiah@cc.usu.edu>
 *    Kevin Gao             <kevin.gao@intel.com>
 */

38
39
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

Herbert Xu's avatar
Herbert Xu committed
40
#include <crypto/hash.h>
Linus Torvalds's avatar
Linus Torvalds committed
41
42
43
44
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/wait.h>
#include <linux/time.h>
45
#include <linux/sched/signal.h>
Linus Torvalds's avatar
Linus Torvalds committed
46
#include <linux/ip.h>
47
#include <linux/capability.h>
Linus Torvalds's avatar
Linus Torvalds committed
48
49
50
#include <linux/fcntl.h>
#include <linux/poll.h>
#include <linux/init.h>
51
#include <linux/slab.h>
52
#include <linux/file.h>
53
#include <linux/compat.h>
NeilBrown's avatar
NeilBrown committed
54
#include <linux/rhashtable.h>
Linus Torvalds's avatar
Linus Torvalds committed
55
56
57
58
59
60

#include <net/ip.h>
#include <net/icmp.h>
#include <net/route.h>
#include <net/ipv6.h>
#include <net/inet_common.h>
61
#include <net/busy_poll.h>
Linus Torvalds's avatar
Linus Torvalds committed
62
63

#include <linux/socket.h> /* for sa_family_t */
64
#include <linux/export.h>
Linus Torvalds's avatar
Linus Torvalds committed
65
66
67
#include <net/sock.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
68
#include <net/sctp/stream_sched.h>
Linus Torvalds's avatar
Linus Torvalds committed
69
70

/* Forward declarations for internal helper functions. */
71
static bool sctp_writeable(struct sock *sk);
Linus Torvalds's avatar
Linus Torvalds committed
72
static void sctp_wfree(struct sk_buff *skb);
73
static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
74
				size_t msg_len);
75
static int sctp_wait_for_packet(struct sock *sk, int *err, long *timeo_p);
Linus Torvalds's avatar
Linus Torvalds committed
76
77
78
static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p);
static int sctp_wait_for_accept(struct sock *sk, long timeo);
static void sctp_wait_for_close(struct sock *sk, long timeo);
79
static void sctp_destruct_sock(struct sock *sk);
Linus Torvalds's avatar
Linus Torvalds committed
80
81
82
83
84
85
86
87
88
89
static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
					union sctp_addr *addr, int len);
static int sctp_bindx_add(struct sock *, struct sockaddr *, int);
static int sctp_bindx_rem(struct sock *, struct sockaddr *, int);
static int sctp_send_asconf_add_ip(struct sock *, struct sockaddr *, int);
static int sctp_send_asconf_del_ip(struct sock *, struct sockaddr *, int);
static int sctp_send_asconf(struct sctp_association *asoc,
			    struct sctp_chunk *chunk);
static int sctp_do_bind(struct sock *, union sctp_addr *, int);
static int sctp_autobind(struct sock *sk);
90
91
92
static int sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
			     struct sctp_association *assoc,
			     enum sctp_socket_type type);
Linus Torvalds's avatar
Linus Torvalds committed
93

94
static unsigned long sctp_memory_pressure;
Eric Dumazet's avatar
Eric Dumazet committed
95
static atomic_long_t sctp_memory_allocated;
96
struct percpu_counter sctp_sockets_allocated;
97

98
static void sctp_enter_memory_pressure(struct sock *sk)
99
100
101
102
103
{
	sctp_memory_pressure = 1;
}


Linus Torvalds's avatar
Linus Torvalds committed
104
105
106
/* Get the sndbuf space available at the time on the association.  */
static inline int sctp_wspace(struct sctp_association *asoc)
{
107
	struct sock *sk = asoc->base.sk;
Linus Torvalds's avatar
Linus Torvalds committed
108

109
110
	return asoc->ep->sndbuf_policy ? sk->sk_sndbuf - asoc->sndbuf_used
				       : sk_stream_wspace(sk);
Linus Torvalds's avatar
Linus Torvalds committed
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
}

/* Increment the used sndbuf space count of the corresponding association by
 * the size of the outgoing data chunk.
 * Also, set the skb destructor for sndbuf accounting later.
 *
 * Since it is always 1-1 between chunk and skb, and also a new skb is always
 * allocated for chunk bundling in sctp_packet_transmit(), we can use the
 * destructor in the data chunk skb for the purpose of the sndbuf space
 * tracking.
 */
static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
{
	struct sctp_association *asoc = chunk->asoc;
	struct sock *sk = asoc->base.sk;

	/* The sndbuf space is tracked per association.  */
	sctp_association_hold(asoc);

Xin Long's avatar
Xin Long committed
130
131
132
	if (chunk->shkey)
		sctp_auth_shkey_hold(chunk->shkey);

133
134
	skb_set_owner_w(chunk->skb, sk);

Linus Torvalds's avatar
Linus Torvalds committed
135
136
	chunk->skb->destructor = sctp_wfree;
	/* Save the chunk pointer in skb for sctp_wfree to use later.  */
137
	skb_shinfo(chunk->skb)->destructor_arg = chunk;
Linus Torvalds's avatar
Linus Torvalds committed
138

139
	refcount_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
140
141
	asoc->sndbuf_used += chunk->skb->truesize + sizeof(struct sctp_chunk);
	sk->sk_wmem_queued += chunk->skb->truesize + sizeof(struct sctp_chunk);
142
	sk_mem_charge(sk, chunk->skb->truesize);
Linus Torvalds's avatar
Linus Torvalds committed
143
144
}

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
static void sctp_clear_owner_w(struct sctp_chunk *chunk)
{
	skb_orphan(chunk->skb);
}

static void sctp_for_each_tx_datachunk(struct sctp_association *asoc,
				       void (*cb)(struct sctp_chunk *))

{
	struct sctp_outq *q = &asoc->outqueue;
	struct sctp_transport *t;
	struct sctp_chunk *chunk;

	list_for_each_entry(t, &asoc->peer.transport_addr_list, transports)
		list_for_each_entry(chunk, &t->transmitted, transmitted_list)
			cb(chunk);

162
	list_for_each_entry(chunk, &q->retransmit, transmitted_list)
163
164
		cb(chunk);

165
	list_for_each_entry(chunk, &q->sacked, transmitted_list)
166
167
		cb(chunk);

168
	list_for_each_entry(chunk, &q->abandoned, transmitted_list)
169
170
171
172
173
174
		cb(chunk);

	list_for_each_entry(chunk, &q->out_chunk_list, list)
		cb(chunk);
}

175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
static void sctp_for_each_rx_skb(struct sctp_association *asoc, struct sock *sk,
				 void (*cb)(struct sk_buff *, struct sock *))

{
	struct sk_buff *skb, *tmp;

	sctp_skb_for_each(skb, &asoc->ulpq.lobby, tmp)
		cb(skb, sk);

	sctp_skb_for_each(skb, &asoc->ulpq.reasm, tmp)
		cb(skb, sk);

	sctp_skb_for_each(skb, &asoc->ulpq.reasm_uo, tmp)
		cb(skb, sk);
}

Linus Torvalds's avatar
Linus Torvalds committed
191
192
193
194
195
196
197
198
199
200
201
202
/* Verify that this is a valid address. */
static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
				   int len)
{
	struct sctp_af *af;

	/* Verify basic sockaddr. */
	af = sctp_sockaddr_af(sctp_sk(sk), addr, len);
	if (!af)
		return -EINVAL;

	/* Is this a valid SCTP address?  */
203
	if (!af->addr_valid(addr, sctp_sk(sk), NULL))
Linus Torvalds's avatar
Linus Torvalds committed
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
		return -EINVAL;

	if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr)))
		return -EINVAL;

	return 0;
}

/* Look up the association by its id.  If this is not a UDP-style
 * socket, the ID field is always ignored.
 */
struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id)
{
	struct sctp_association *asoc = NULL;

	/* If this is not a UDP-style socket, assoc id should be ignored. */
	if (!sctp_style(sk, UDP)) {
		/* Return NULL if the socket state is not ESTABLISHED. It
		 * could be a TCP-style listening socket or a socket which
		 * hasn't yet called connect() to establish an association.
		 */
225
		if (!sctp_sstate(sk, ESTABLISHED) && !sctp_sstate(sk, CLOSING))
Linus Torvalds's avatar
Linus Torvalds committed
226
227
228
229
230
231
232
233
234
235
			return NULL;

		/* Get the first and the only association from the list. */
		if (!list_empty(&sctp_sk(sk)->ep->asocs))
			asoc = list_entry(sctp_sk(sk)->ep->asocs.next,
					  struct sctp_association, asocs);
		return asoc;
	}

	/* Otherwise this is a UDP-style socket. */
236
	if (id <= SCTP_ALL_ASSOC)
Linus Torvalds's avatar
Linus Torvalds committed
237
238
239
240
		return NULL;

	spin_lock_bh(&sctp_assocs_id_lock);
	asoc = (struct sctp_association *)idr_find(&sctp_assocs_id, (int)id);
241
242
	if (asoc && (asoc->base.sk != sk || asoc->base.dead))
		asoc = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
243
244
245
246
247
248
249
250
251
252
253
254
255
256
	spin_unlock_bh(&sctp_assocs_id_lock);

	return asoc;
}

/* Look up the transport from an address and an assoc id. If both address and
 * id are specified, the associations matching the address and the id should be
 * the same.
 */
static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
					      struct sockaddr_storage *addr,
					      sctp_assoc_t id)
{
	struct sctp_association *addr_asoc = NULL, *id_asoc = NULL;
257
	struct sctp_af *af = sctp_get_af_specific(addr->ss_family);
Linus Torvalds's avatar
Linus Torvalds committed
258
	union sctp_addr *laddr = (union sctp_addr *)addr;
259
260
	struct sctp_transport *transport;

261
	if (!af || sctp_verify_addr(sk, laddr, af->sockaddr_len))
262
		return NULL;
Linus Torvalds's avatar
Linus Torvalds committed
263
264

	addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep,
265
					       laddr,
Linus Torvalds's avatar
Linus Torvalds committed
266
267
268
269
270
271
272
273
274
					       &transport);

	if (!addr_asoc)
		return NULL;

	id_asoc = sctp_id2assoc(sk, id);
	if (id_asoc && (id_asoc != addr_asoc))
		return NULL;

275
	sctp_get_pf_specific(sk->sk_family)->addr_to_user(sctp_sk(sk),
Linus Torvalds's avatar
Linus Torvalds committed
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
						(union sctp_addr *)addr);

	return transport;
}

/* API 3.1.2 bind() - UDP Style Syntax
 * The syntax of bind() is,
 *
 *   ret = bind(int sd, struct sockaddr *addr, int addrlen);
 *
 *   sd      - the socket descriptor returned by socket().
 *   addr    - the address structure (struct sockaddr_in or struct
 *             sockaddr_in6 [RFC 2553]),
 *   addr_len - the size of the address structure.
 */
291
static int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len)
Linus Torvalds's avatar
Linus Torvalds committed
292
293
294
{
	int retval = 0;

295
	lock_sock(sk);
Linus Torvalds's avatar
Linus Torvalds committed
296

297
298
	pr_debug("%s: sk:%p, addr:%p, addr_len:%d\n", __func__, sk,
		 addr, addr_len);
Linus Torvalds's avatar
Linus Torvalds committed
299
300
301

	/* Disallow binding twice. */
	if (!sctp_sk(sk)->ep->base.bind_addr.port)
302
		retval = sctp_do_bind(sk, (union sctp_addr *)addr,
Linus Torvalds's avatar
Linus Torvalds committed
303
304
305
306
				      addr_len);
	else
		retval = -EINVAL;

307
	release_sock(sk);
Linus Torvalds's avatar
Linus Torvalds committed
308
309
310
311

	return retval;
}

312
static int sctp_get_port_local(struct sock *, union sctp_addr *);
Linus Torvalds's avatar
Linus Torvalds committed
313
314
315
316
317
318
319
320
321
322
323

/* Verify this is a valid sockaddr. */
static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
					union sctp_addr *addr, int len)
{
	struct sctp_af *af;

	/* Check minimum size.  */
	if (len < sizeof (struct sockaddr))
		return NULL;

324
325
326
	if (!opt->pf->af_supported(addr->sa.sa_family, opt))
		return NULL;

327
328
329
330
331
332
333
334
	if (addr->sa.sa_family == AF_INET6) {
		if (len < SIN6_LEN_RFC2133)
			return NULL;
		/* V4 mapped address are really of AF_INET family */
		if (ipv6_addr_v4mapped(&addr->v6.sin6_addr) &&
		    !opt->pf->af_supported(AF_INET, opt))
			return NULL;
	}
Linus Torvalds's avatar
Linus Torvalds committed
335
336
337
338
339
340
341
342
343
344
345

	/* If we get this far, af is valid. */
	af = sctp_get_af_specific(addr->sa.sa_family);

	if (len < af->sockaddr_len)
		return NULL;

	return af;
}

/* Bind a local address either to an endpoint or to an association.  */
346
static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
Linus Torvalds's avatar
Linus Torvalds committed
347
{
348
	struct net *net = sock_net(sk);
Linus Torvalds's avatar
Linus Torvalds committed
349
350
351
352
353
354
355
356
357
	struct sctp_sock *sp = sctp_sk(sk);
	struct sctp_endpoint *ep = sp->ep;
	struct sctp_bind_addr *bp = &ep->base.bind_addr;
	struct sctp_af *af;
	unsigned short snum;
	int ret = 0;

	/* Common sockaddr verification. */
	af = sctp_sockaddr_af(sp, addr, len);
358
	if (!af) {
359
360
		pr_debug("%s: sk:%p, newaddr:%p, len:%d EINVAL\n",
			 __func__, sk, addr, len);
Linus Torvalds's avatar
Linus Torvalds committed
361
		return -EINVAL;
362
363
364
365
	}

	snum = ntohs(addr->v4.sin_port);

366
367
	pr_debug("%s: sk:%p, new addr:%pISc, port:%d, new port:%d, len:%d\n",
		 __func__, sk, &addr->sa, bp->port, snum, len);
Linus Torvalds's avatar
Linus Torvalds committed
368
369
370
371
372

	/* PF specific bind() address verification. */
	if (!sp->pf->bind_verify(sp, addr))
		return -EADDRNOTAVAIL;

373
374
375
376
377
378
379
380
	/* We must either be unbound, or bind to the same port.
	 * It's OK to allow 0 ports if we are already bound.
	 * We'll just inhert an already bound port in this case
	 */
	if (bp->port) {
		if (!snum)
			snum = bp->port;
		else if (snum != bp->port) {
381
382
			pr_debug("%s: new port %d doesn't match existing port "
				 "%d\n", __func__, snum, bp->port);
383
384
			return -EINVAL;
		}
Linus Torvalds's avatar
Linus Torvalds committed
385
386
	}

387
	if (snum && snum < inet_prot_sock(net) &&
388
	    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
Linus Torvalds's avatar
Linus Torvalds committed
389
390
		return -EACCES;

391
392
393
394
395
396
	/* See if the address matches any of the addresses we may have
	 * already bound before checking against other endpoints.
	 */
	if (sctp_bind_addr_match(bp, addr, sp))
		return -EINVAL;

Linus Torvalds's avatar
Linus Torvalds committed
397
398
399
400
	/* Make sure we are allowed to bind here.
	 * The function sctp_get_port_local() does duplicate address
	 * detection.
	 */
401
	addr->v4.sin_port = htons(snum);
402
	if (sctp_get_port_local(sk, addr))
403
		return -EADDRINUSE;
Linus Torvalds's avatar
Linus Torvalds committed
404
405
406

	/* Refresh ephemeral port.  */
	if (!bp->port)
407
		bp->port = inet_sk(sk)->inet_num;
Linus Torvalds's avatar
Linus Torvalds committed
408

409
410
411
	/* Add the address to the bind address list.
	 * Use GFP_ATOMIC since BHs will be disabled.
	 */
412
413
	ret = sctp_add_bind_addr(bp, addr, af->sockaddr_len,
				 SCTP_ADDR_SRC, GFP_ATOMIC);
Linus Torvalds's avatar
Linus Torvalds committed
414
415
416

	/* Copy back into socket for getsockname() use. */
	if (!ret) {
417
		inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num);
418
		sp->pf->to_sk_saddr(addr, sk);
Linus Torvalds's avatar
Linus Torvalds committed
419
420
421
422
423
424
425
	}

	return ret;
}

 /* ADDIP Section 4.1.1 Congestion Control of ASCONF Chunks
 *
426
 * R1) One and only one ASCONF Chunk MAY be in transit and unacknowledged
Linus Torvalds's avatar
Linus Torvalds committed
427
 * at any one time.  If a sender, after sending an ASCONF chunk, decides
428
 * it needs to transfer another ASCONF Chunk, it MUST wait until the
Linus Torvalds's avatar
Linus Torvalds committed
429
 * ASCONF-ACK Chunk returns from the previous ASCONF Chunk before sending a
430
431
 * subsequent ASCONF. Note this restriction binds each side, so at any
 * time two ASCONF may be in-transit on any given association (one sent
Linus Torvalds's avatar
Linus Torvalds committed
432
433
434
435
436
 * from each endpoint).
 */
static int sctp_send_asconf(struct sctp_association *asoc,
			    struct sctp_chunk *chunk)
{
437
	struct net 	*net = sock_net(asoc->base.sk);
Linus Torvalds's avatar
Linus Torvalds committed
438
439
440
441
	int		retval = 0;

	/* If there is an outstanding ASCONF chunk, queue it for later
	 * transmission.
442
	 */
Linus Torvalds's avatar
Linus Torvalds committed
443
	if (asoc->addip_last_asconf) {
444
		list_add_tail(&chunk->list, &asoc->addip_chunk_list);
445
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
446
447
448
449
	}

	/* Hold the chunk until an ASCONF_ACK is received. */
	sctp_chunk_hold(chunk);
450
	retval = sctp_primitive_ASCONF(net, asoc, chunk);
Linus Torvalds's avatar
Linus Torvalds committed
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
	if (retval)
		sctp_chunk_free(chunk);
	else
		asoc->addip_last_asconf = chunk;

out:
	return retval;
}

/* Add a list of addresses as bind addresses to local endpoint or
 * association.
 *
 * Basically run through each address specified in the addrs/addrcnt
 * array/length pair, determine if it is IPv6 or IPv4 and call
 * sctp_do_bind() on it.
 *
 * If any of them fails, then the operation will be reversed and the
 * ones that were added will be removed.
 *
 * Only sctp_setsockopt_bindx() is supposed to call this function.
 */
472
static int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt)
Linus Torvalds's avatar
Linus Torvalds committed
473
474
475
476
477
478
479
{
	int cnt;
	int retval = 0;
	void *addr_buf;
	struct sockaddr *sa_addr;
	struct sctp_af *af;

480
481
	pr_debug("%s: sk:%p, addrs:%p, addrcnt:%d\n", __func__, sk,
		 addrs, addrcnt);
Linus Torvalds's avatar
Linus Torvalds committed
482
483
484
485
486
487

	addr_buf = addrs;
	for (cnt = 0; cnt < addrcnt; cnt++) {
		/* The list may contain either IPv4 or IPv6 address;
		 * determine the address length for walking thru the list.
		 */
Joe Perches's avatar
Joe Perches committed
488
		sa_addr = addr_buf;
Linus Torvalds's avatar
Linus Torvalds committed
489
490
491
492
493
494
		af = sctp_get_af_specific(sa_addr->sa_family);
		if (!af) {
			retval = -EINVAL;
			goto err_bindx_add;
		}

495
		retval = sctp_do_bind(sk, (union sctp_addr *)sa_addr,
Linus Torvalds's avatar
Linus Torvalds committed
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
				      af->sockaddr_len);

		addr_buf += af->sockaddr_len;

err_bindx_add:
		if (retval < 0) {
			/* Failed. Cleanup the ones that have been added */
			if (cnt > 0)
				sctp_bindx_rem(sk, addrs, cnt);
			return retval;
		}
	}

	return retval;
}

/* Send an ASCONF chunk with Add IP address parameters to all the peers of the
 * associations that are part of the endpoint indicating that a list of local
 * addresses are added to the endpoint.
 *
516
 * If any of the addresses is already in the bind address list of the
Linus Torvalds's avatar
Linus Torvalds committed
517
518
519
520
521
 * association, we do not send the chunk for that association.  But it will not
 * affect other associations.
 *
 * Only sctp_setsockopt_bindx() is supposed to call this function.
 */
522
static int sctp_send_asconf_add_ip(struct sock		*sk,
Linus Torvalds's avatar
Linus Torvalds committed
523
524
525
				   struct sockaddr	*addrs,
				   int 			addrcnt)
{
526
	struct net *net = sock_net(sk);
Linus Torvalds's avatar
Linus Torvalds committed
527
528
529
530
531
532
533
	struct sctp_sock		*sp;
	struct sctp_endpoint		*ep;
	struct sctp_association		*asoc;
	struct sctp_bind_addr		*bp;
	struct sctp_chunk		*chunk;
	struct sctp_sockaddr_entry	*laddr;
	union sctp_addr			*addr;
534
	union sctp_addr			saveaddr;
Linus Torvalds's avatar
Linus Torvalds committed
535
536
537
538
539
540
	void				*addr_buf;
	struct sctp_af			*af;
	struct list_head		*p;
	int 				i;
	int 				retval = 0;

541
	if (!net->sctp.addip_enable)
Linus Torvalds's avatar
Linus Torvalds committed
542
543
544
545
546
		return retval;

	sp = sctp_sk(sk);
	ep = sp->ep;

547
548
	pr_debug("%s: sk:%p, addrs:%p, addrcnt:%d\n",
		 __func__, sk, addrs, addrcnt);
Linus Torvalds's avatar
Linus Torvalds committed
549

550
	list_for_each_entry(asoc, &ep->asocs, asocs) {
Linus Torvalds's avatar
Linus Torvalds committed
551
552
553
554
555
556
557
558
559
560
		if (!asoc->peer.asconf_capable)
			continue;

		if (asoc->peer.addip_disabled_mask & SCTP_PARAM_ADD_IP)
			continue;

		if (!sctp_state(asoc, ESTABLISHED))
			continue;

		/* Check if any address in the packed array of addresses is
561
562
		 * in the bind address list of the association. If so,
		 * do not send the asconf chunk to its peer, but continue with
Linus Torvalds's avatar
Linus Torvalds committed
563
564
565
566
		 * other associations.
		 */
		addr_buf = addrs;
		for (i = 0; i < addrcnt; i++) {
Joe Perches's avatar
Joe Perches committed
567
			addr = addr_buf;
Linus Torvalds's avatar
Linus Torvalds committed
568
569
570
571
572
573
574
575
576
577
578
579
580
581
			af = sctp_get_af_specific(addr->v4.sin_family);
			if (!af) {
				retval = -EINVAL;
				goto out;
			}

			if (sctp_assoc_lookup_laddr(asoc, addr))
				break;

			addr_buf += af->sockaddr_len;
		}
		if (i < addrcnt)
			continue;

582
583
		/* Use the first valid address in bind addr list of
		 * association as Address Parameter of ASCONF CHUNK.
Linus Torvalds's avatar
Linus Torvalds committed
584
585
586
587
		 */
		bp = &asoc->base.bind_addr;
		p = bp->address_list.next;
		laddr = list_entry(p, struct sctp_sockaddr_entry, list);
588
		chunk = sctp_make_asconf_update_ip(asoc, &laddr->a, addrs,
Linus Torvalds's avatar
Linus Torvalds committed
589
590
591
592
593
594
						   addrcnt, SCTP_PARAM_ADD_IP);
		if (!chunk) {
			retval = -ENOMEM;
			goto out;
		}

595
596
		/* Add the new addresses to the bind address list with
		 * use_as_src set to 0.
Linus Torvalds's avatar
Linus Torvalds committed
597
		 */
598
599
		addr_buf = addrs;
		for (i = 0; i < addrcnt; i++) {
Joe Perches's avatar
Joe Perches committed
600
			addr = addr_buf;
601
602
			af = sctp_get_af_specific(addr->v4.sin_family);
			memcpy(&saveaddr, addr, af->sockaddr_len);
603
			retval = sctp_add_bind_addr(bp, &saveaddr,
604
						    sizeof(saveaddr),
605
						    SCTP_ADDR_NEW, GFP_ATOMIC);
606
607
			addr_buf += af->sockaddr_len;
		}
608
609
610
611
612
613
614
615
616
		if (asoc->src_out_of_asoc_ok) {
			struct sctp_transport *trans;

			list_for_each_entry(trans,
			    &asoc->peer.transport_addr_list, transports) {
				trans->cwnd = min(4*asoc->pathmtu, max_t(__u32,
				    2*asoc->pathmtu, 4380));
				trans->ssthresh = asoc->peer.i.a_rwnd;
				trans->rto = asoc->rto_initial;
617
				sctp_max_rto(asoc, trans);
618
				trans->rtt = trans->srtt = trans->rttvar = 0;
619
				/* Clear the source and route cache */
620
				sctp_transport_route(trans, NULL,
621
						     sctp_sk(asoc->base.sk));
622
623
624
			}
		}
		retval = sctp_send_asconf(asoc, chunk);
Linus Torvalds's avatar
Linus Torvalds committed
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
	}

out:
	return retval;
}

/* Remove a list of addresses from bind addresses list.  Do not remove the
 * last address.
 *
 * Basically run through each address specified in the addrs/addrcnt
 * array/length pair, determine if it is IPv6 or IPv4 and call
 * sctp_del_bind() on it.
 *
 * If any of them fails, then the operation will be reversed and the
 * ones that were removed will be added back.
 *
 * At least one address has to be left; if only one address is
 * available, the operation will return -EBUSY.
 *
 * Only sctp_setsockopt_bindx() is supposed to call this function.
 */
646
static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
Linus Torvalds's avatar
Linus Torvalds committed
647
648
649
650
651
652
653
{
	struct sctp_sock *sp = sctp_sk(sk);
	struct sctp_endpoint *ep = sp->ep;
	int cnt;
	struct sctp_bind_addr *bp = &ep->base.bind_addr;
	int retval = 0;
	void *addr_buf;
654
	union sctp_addr *sa_addr;
Linus Torvalds's avatar
Linus Torvalds committed
655
656
	struct sctp_af *af;

657
658
	pr_debug("%s: sk:%p, addrs:%p, addrcnt:%d\n",
		 __func__, sk, addrs, addrcnt);
Linus Torvalds's avatar
Linus Torvalds committed
659
660
661
662
663
664
665
666
667
668
669
670
671

	addr_buf = addrs;
	for (cnt = 0; cnt < addrcnt; cnt++) {
		/* If the bind address list is empty or if there is only one
		 * bind address, there is nothing more to be removed (we need
		 * at least one address here).
		 */
		if (list_empty(&bp->address_list) ||
		    (sctp_list_single_entry(&bp->address_list))) {
			retval = -EBUSY;
			goto err_bindx_rem;
		}

Joe Perches's avatar
Joe Perches committed
672
		sa_addr = addr_buf;
673
		af = sctp_get_af_specific(sa_addr->sa.sa_family);
Linus Torvalds's avatar
Linus Torvalds committed
674
675
676
677
		if (!af) {
			retval = -EINVAL;
			goto err_bindx_rem;
		}
678
679
680
681
682
683

		if (!af->addr_valid(sa_addr, sp, NULL)) {
			retval = -EADDRNOTAVAIL;
			goto err_bindx_rem;
		}

684
685
		if (sa_addr->v4.sin_port &&
		    sa_addr->v4.sin_port != htons(bp->port)) {
Linus Torvalds's avatar
Linus Torvalds committed
686
687
688
689
			retval = -EINVAL;
			goto err_bindx_rem;
		}

690
691
692
		if (!sa_addr->v4.sin_port)
			sa_addr->v4.sin_port = htons(bp->port);

Linus Torvalds's avatar
Linus Torvalds committed
693
694
695
696
697
698
699
		/* FIXME - There is probably a need to check if sk->sk_saddr and
		 * sk->sk_rcv_addr are currently set to one of the addresses to
		 * be removed. This is something which needs to be looked into
		 * when we are fixing the outstanding issues with multi-homing
		 * socket routing and failover schemes. Refer to comments in
		 * sctp_do_bind(). -daisy
		 */
700
		retval = sctp_del_bind_addr(bp, sa_addr);
Linus Torvalds's avatar
Linus Torvalds committed
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718

		addr_buf += af->sockaddr_len;
err_bindx_rem:
		if (retval < 0) {
			/* Failed. Add the ones that has been removed back */
			if (cnt > 0)
				sctp_bindx_add(sk, addrs, cnt);
			return retval;
		}
	}

	return retval;
}

/* Send an ASCONF chunk with Delete IP address parameters to all the peers of
 * the associations that are part of the endpoint indicating that a list of
 * local addresses are removed from the endpoint.
 *
719
 * If any of the addresses is already in the bind address list of the
Linus Torvalds's avatar
Linus Torvalds committed
720
721
722
723
724
725
726
727
728
 * association, we do not send the chunk for that association.  But it will not
 * affect other associations.
 *
 * Only sctp_setsockopt_bindx() is supposed to call this function.
 */
static int sctp_send_asconf_del_ip(struct sock		*sk,
				   struct sockaddr	*addrs,
				   int			addrcnt)
{
729
	struct net *net = sock_net(sk);
Linus Torvalds's avatar
Linus Torvalds committed
730
731
732
	struct sctp_sock	*sp;
	struct sctp_endpoint	*ep;
	struct sctp_association	*asoc;
733
	struct sctp_transport	*transport;
Linus Torvalds's avatar
Linus Torvalds committed
734
735
736
737
738
	struct sctp_bind_addr	*bp;
	struct sctp_chunk	*chunk;
	union sctp_addr		*laddr;
	void			*addr_buf;
	struct sctp_af		*af;
739
	struct sctp_sockaddr_entry *saddr;
Linus Torvalds's avatar
Linus Torvalds committed
740
741
	int 			i;
	int 			retval = 0;
742
	int			stored = 0;
Linus Torvalds's avatar
Linus Torvalds committed
743

744
	chunk = NULL;
745
	if (!net->sctp.addip_enable)
Linus Torvalds's avatar
Linus Torvalds committed
746
747
748
749
750
		return retval;

	sp = sctp_sk(sk);
	ep = sp->ep;

751
752
	pr_debug("%s: sk:%p, addrs:%p, addrcnt:%d\n",
		 __func__, sk, addrs, addrcnt);
Linus Torvalds's avatar
Linus Torvalds committed
753

754
	list_for_each_entry(asoc, &ep->asocs, asocs) {
Linus Torvalds's avatar
Linus Torvalds committed
755
756
757
758
759
760
761
762
763
764
765

		if (!asoc->peer.asconf_capable)
			continue;

		if (asoc->peer.addip_disabled_mask & SCTP_PARAM_DEL_IP)
			continue;

		if (!sctp_state(asoc, ESTABLISHED))
			continue;

		/* Check if any address in the packed array of addresses is
766
		 * not present in the bind address list of the association.
Linus Torvalds's avatar
Linus Torvalds committed
767
768
769
770
771
		 * If so, do not send the asconf chunk to its peer, but
		 * continue with other associations.
		 */
		addr_buf = addrs;
		for (i = 0; i < addrcnt; i++) {
Joe Perches's avatar
Joe Perches committed
772
			laddr = addr_buf;
Linus Torvalds's avatar
Linus Torvalds committed
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
			af = sctp_get_af_specific(laddr->v4.sin_family);
			if (!af) {
				retval = -EINVAL;
				goto out;
			}

			if (!sctp_assoc_lookup_laddr(asoc, laddr))
				break;

			addr_buf += af->sockaddr_len;
		}
		if (i < addrcnt)
			continue;

		/* Find one address in the association's bind address list
		 * that is not in the packed array of addresses. This is to
		 * make sure that we do not delete all the addresses in the
		 * association.
		 */
		bp = &asoc->base.bind_addr;
		laddr = sctp_find_unmatch_addr(bp, (union sctp_addr *)addrs,
					       addrcnt, sp);
795
796
797
798
799
		if ((laddr == NULL) && (addrcnt == 1)) {
			if (asoc->asconf_addr_del_pending)
				continue;
			asoc->asconf_addr_del_pending =
			    kzalloc(sizeof(union sctp_addr), GFP_ATOMIC);
800
801
802
803
			if (asoc->asconf_addr_del_pending == NULL) {
				retval = -ENOMEM;
				goto out;
			}
804
805
806
807
808
809
810
811
812
813
814
815
816
			asoc->asconf_addr_del_pending->sa.sa_family =
				    addrs->sa_family;
			asoc->asconf_addr_del_pending->v4.sin_port =
				    htons(bp->port);
			if (addrs->sa_family == AF_INET) {
				struct sockaddr_in *sin;

				sin = (struct sockaddr_in *)addrs;
				asoc->asconf_addr_del_pending->v4.sin_addr.s_addr = sin->sin_addr.s_addr;
			} else if (addrs->sa_family == AF_INET6) {
				struct sockaddr_in6 *sin6;

				sin6 = (struct sockaddr_in6 *)addrs;
Alexey Dobriyan's avatar
Alexey Dobriyan committed
817
				asoc->asconf_addr_del_pending->v6.sin6_addr = sin6->sin6_addr;
818
			}
819
820
821
822
823

			pr_debug("%s: keep the last address asoc:%p %pISc at %p\n",
				 __func__, asoc, &asoc->asconf_addr_del_pending->sa,
				 asoc->asconf_addr_del_pending);

824
825
826
827
			asoc->src_out_of_asoc_ok = 1;
			stored = 1;
			goto skip_mkasconf;
		}
Linus Torvalds's avatar
Linus Torvalds committed
828

829
830
831
		if (laddr == NULL)
			return -EINVAL;

832
833
834
835
		/* We do not need RCU protection throughout this loop
		 * because this is done under a socket lock from the
		 * setsockopt call.
		 */
Linus Torvalds's avatar
Linus Torvalds committed
836
837
838
839
840
841
842
		chunk = sctp_make_asconf_update_ip(asoc, laddr, addrs, addrcnt,
						   SCTP_PARAM_DEL_IP);
		if (!chunk) {
			retval = -ENOMEM;
			goto out;
		}

843
skip_mkasconf:
844
845
846
847
848
		/* Reset use_as_src flag for the addresses in the bind address
		 * list that are to be deleted.
		 */
		addr_buf = addrs;
		for (i = 0; i < addrcnt; i++) {
Joe Perches's avatar
Joe Perches committed
849
			laddr = addr_buf;
850
			af = sctp_get_af_specific(laddr->v4.sin_family);
851
			list_for_each_entry(saddr, &bp->address_list, list) {
852
				if (sctp_cmp_addr_exact(&saddr->a, laddr))
853
					saddr->state = SCTP_ADDR_DEL;
854
855
856
			}
			addr_buf += af->sockaddr_len;
		}
Linus Torvalds's avatar
Linus Torvalds committed
857

858
859
860
		/* Update the route and saddr entries for all the transports
		 * as some of the addresses in the bind address list are
		 * about to be deleted and cannot be used as source addresses.
Linus Torvalds's avatar
Linus Torvalds committed
861
		 */
862
863
		list_for_each_entry(transport, &asoc->peer.transport_addr_list,
					transports) {
864
865
866
867
			sctp_transport_route(transport, NULL,
					     sctp_sk(asoc->base.sk));
		}

868
869
870
		if (stored)
			/* We don't need to transmit ASCONF */
			continue;
871
		retval = sctp_send_asconf(asoc, chunk);
Linus Torvalds's avatar
Linus Torvalds committed
872
873
874
875
876
	}
out:
	return retval;
}

877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
/* set addr events to assocs in the endpoint.  ep and addr_wq must be locked */
int sctp_asconf_mgmt(struct sctp_sock *sp, struct sctp_sockaddr_entry *addrw)
{
	struct sock *sk = sctp_opt2sk(sp);
	union sctp_addr *addr;
	struct sctp_af *af;

	/* It is safe to write port space in caller. */
	addr = &addrw->a;
	addr->v4.sin_port = htons(sp->ep->base.bind_addr.port);
	af = sctp_get_af_specific(addr->sa.sa_family);
	if (!af)
		return -EINVAL;
	if (sctp_verify_addr(sk, addr, af->sockaddr_len))
		return -EINVAL;

	if (addrw->state == SCTP_ADDR_NEW)
		return sctp_send_asconf_add_ip(sk, (struct sockaddr *)addr, 1);
	else
		return sctp_send_asconf_del_ip(sk, (struct sockaddr *)addr, 1);
}

Linus Torvalds's avatar
Linus Torvalds committed
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
/* Helper for tunneling sctp_bindx() requests through sctp_setsockopt()
 *
 * API 8.1
 * int sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt,
 *                int flags);
 *
 * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
 * If the sd is an IPv6 socket, the addresses passed can either be IPv4
 * or IPv6 addresses.
 *
 * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see
 * Section 3.1.2 for this usage.
 *
 * addrs is a pointer to an array of one or more socket addresses. Each
 * address is contained in its appropriate structure (i.e. struct
 * sockaddr_in or struct sockaddr_in6) the family of the address type
Ville Nuorvala's avatar
Ville Nuorvala committed
915
 * must be used to distinguish the address length (note that this
Linus Torvalds's avatar
Linus Torvalds committed
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
 * representation is termed a "packed array" of addresses). The caller
 * specifies the number of addresses in the array with addrcnt.
 *
 * On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns
 * -1, and sets errno to the appropriate error code.
 *
 * For SCTP, the port given in each socket address must be the same, or
 * sctp_bindx() will fail, setting errno to EINVAL.
 *
 * The flags parameter is formed from the bitwise OR of zero or more of
 * the following currently defined flags:
 *
 * SCTP_BINDX_ADD_ADDR
 *
 * SCTP_BINDX_REM_ADDR
 *
 * SCTP_BINDX_ADD_ADDR directs SCTP to add the given addresses to the
 * association, and SCTP_BINDX_REM_ADDR directs SCTP to remove the given
 * addresses from the association. The two flags are mutually exclusive;
 * if both are given, sctp_bindx() will fail with EINVAL. A caller may
 * not remove all addresses from an association; sctp_bindx() will
 * reject such an attempt with EINVAL.
 *
 * An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate
 * additional addresses with an endpoint after calling bind().  Or use
 * sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening
 * socket is associated with so that no new association accepted will be
 * associated with those addresses. If the endpoint supports dynamic
 * address a SCTP_BINDX_REM_ADDR or SCTP_BINDX_ADD_ADDR may cause a
 * endpoint to send the appropriate message to the peer to change the
 * peers address lists.
 *
 * Adding and removing addresses from a connected association is
 * optional functionality. Implementations that do not support this
 * functionality should return EOPNOTSUPP.
 *
 * Basically do nothing but copying the addresses from user to kernel
 * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk.
954
955
 * This is used for tunneling the sctp_bindx() request through sctp_setsockopt()
 * from userspace.
Linus Torvalds's avatar
Linus Torvalds committed
956
957
958
959
960
961
962
963
964
965
966
967
 *
 * On exit there is no need to do sockfd_put(), sys_setsockopt() does
 * it.
 *
 * sk        The sk of the socket
 * addrs     The pointer to the addresses in user land
 * addrssize Size of the addrs buffer
 * op        Operation to perform (add or remove, see the flags of
 *           sctp_bindx)
 *
 * Returns 0 if ok, <0 errno code on error.
 */
968
static int sctp_setsockopt_bindx(struct sock *sk,
969
970
				 struct sockaddr __user *addrs,
				 int addrs_size, int op)
Linus Torvalds's avatar
Linus Torvalds committed
971
972
973
974
975
976
977
978
979
{
	struct sockaddr *kaddrs;
	int err;
	int addrcnt = 0;
	int walk_size = 0;
	struct sockaddr *sa_addr;
	void *addr_buf;
	struct sctp_af *af;

980
981
	pr_debug("%s: sk:%p addrs:%p addrs_size:%d opt:%d\n",
		 __func__, sk, addrs, addrs_size, op);
Linus Torvalds's avatar
Linus Torvalds committed
982
983
984
985

	if (unlikely(addrs_size <= 0))
		return -EINVAL;

986
	kaddrs = memdup_user(addrs, addrs_size);
987
	if (IS_ERR(kaddrs))
988
		return PTR_ERR(kaddrs);
Linus Torvalds's avatar
Linus Torvalds committed
989

990
	/* Walk through the addrs buffer and count the number of addresses. */
Linus Torvalds's avatar
Linus Torvalds committed
991
992
	addr_buf = kaddrs;
	while (walk_size < addrs_size) {
993
		if (walk_size + sizeof(sa_family_t) > addrs_size) {
994
			kfree(kaddrs);
995
996
997
			return -EINVAL;
		}

Joe Perches's avatar
Joe Perches committed
998
		sa_addr = addr_buf;
Linus Torvalds's avatar
Linus Torvalds committed
999
1000
		af = sctp_get_af_specific(sa_addr->sa_family);

For faster browsing, not all history is shown. View entire blame