Blame view

net/sctp/bind_addr.c 13.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
   * (C) Copyright IBM Corp. 2001, 2003
   * Copyright (c) Cisco 1999,2000
   * Copyright (c) Motorola 1999,2000,2001
   * Copyright (c) La Monte H.P. Yarroll 2001
   *
60c778b25   Vlad Yasevich   [SCTP]: Stop clai...
8
   * This file is part of the SCTP kernel implementation.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
   *
   * A collection class to handle the storage of transport addresses.
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
   * Please send any bug reports or fixes you make to the
   * email address(es):
91705c61b   Daniel Borkmann   net: sctp: trivia...
14
   *    lksctp developers <linux-sctp@vger.kernel.org>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
18
19
20
   * Written or modified by:
   *    La Monte H.P. Yarroll <piggy@acm.org>
   *    Karl Knutson          <karl@athena.chicago.il.us>
   *    Jon Grimm             <jgrimm@us.ibm.com>
   *    Daisy Chang           <daisyc@us.ibm.com>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
   */
  
  #include <linux/types.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
24
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
29
30
31
32
  #include <linux/in.h>
  #include <net/sock.h>
  #include <net/ipv6.h>
  #include <net/if_inet6.h>
  #include <net/sctp/sctp.h>
  #include <net/sctp/sm.h>
  
  /* Forward declarations for internal helpers. */
1c662018d   Xin Long   sctp: remove the ...
33
34
35
  static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
  			      union sctp_addr *addr, enum sctp_scope scope,
  			      gfp_t gfp, int flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
40
41
42
  static void sctp_bind_addr_clean(struct sctp_bind_addr *);
  
  /* First Level Abstractions. */
  
  /* Copy 'src' to 'dest' taking 'scope' into account.  Omit addresses
   * in 'src' which have a broader scope than 'scope'.
   */
4db67e808   Eric W. Biederman   sctp: Make the ad...
43
  int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  			const struct sctp_bind_addr *src,
1c662018d   Xin Long   sctp: remove the ...
45
  			enum sctp_scope scope, gfp_t gfp,
3182cd84f   Alexey Dobriyan   [SCTP]: __nocast ...
46
  			int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
  {
  	struct sctp_sockaddr_entry *addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
53
54
  	int error = 0;
  
  	/* All addresses share the same port.  */
  	dest->port = src->port;
  
  	/* Extract the addresses which are relevant for this scope.  */
9dbc15f05   Robert P. J. Day   [SCTP]: "list_for...
55
  	list_for_each_entry(addr, &src->address_list, list) {
4db67e808   Eric W. Biederman   sctp: Make the ad...
56
  		error = sctp_copy_one_addr(net, dest, &addr->a, scope,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
60
61
62
63
64
65
66
  					   gfp, flags);
  		if (error < 0)
  			goto out;
  	}
  
  	/* If there are no addresses matching the scope and
  	 * this is global scope, try to get a link scope address, with
  	 * the assumption that we must be sitting behind a NAT.
  	 */
  	if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) {
9dbc15f05   Robert P. J. Day   [SCTP]: "list_for...
67
  		list_for_each_entry(addr, &src->address_list, list) {
4db67e808   Eric W. Biederman   sctp: Make the ad...
68
  			error = sctp_copy_one_addr(net, dest, &addr->a,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
73
74
75
76
77
78
79
80
81
  						   SCTP_SCOPE_LINK, gfp,
  						   flags);
  			if (error < 0)
  				goto out;
  		}
  	}
  
  out:
  	if (error)
  		sctp_bind_addr_clean(dest);
  
  	return error;
  }
8e71a11c9   Vlad Yasevich   [SCTP]: Fix the b...
82
83
84
85
86
87
88
89
90
91
  /* Exactly duplicate the address lists.  This is necessary when doing
   * peer-offs and accepts.  We don't want to put all the current system
   * addresses into the endpoint.  That's useless.  But we do want duplicat
   * the list of bound addresses that the older endpoint used.
   */
  int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
  			const struct sctp_bind_addr *src,
  			gfp_t gfp)
  {
  	struct sctp_sockaddr_entry *addr;
8e71a11c9   Vlad Yasevich   [SCTP]: Fix the b...
92
93
94
95
  	int error = 0;
  
  	/* All addresses share the same port.  */
  	dest->port = src->port;
9dbc15f05   Robert P. J. Day   [SCTP]: "list_for...
96
  	list_for_each_entry(addr, &src->address_list, list) {
133800d1f   Marcelo Ricardo Leitner   sctp: fix copying...
97
98
  		error = sctp_add_bind_addr(dest, &addr->a, sizeof(addr->a),
  					   1, gfp);
8e71a11c9   Vlad Yasevich   [SCTP]: Fix the b...
99
100
101
102
103
104
  		if (error < 0)
  			break;
  	}
  
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
107
108
109
  /* Initialize the SCTP_bind_addr structure for either an endpoint or
   * an association.
   */
  void sctp_bind_addr_init(struct sctp_bind_addr *bp, __u16 port)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
113
114
115
116
  	INIT_LIST_HEAD(&bp->address_list);
  	bp->port = port;
  }
  
  /* Dispose of the address list. */
  static void sctp_bind_addr_clean(struct sctp_bind_addr *bp)
  {
c182f90bc   Jacek Luczak   SCTP: fix race be...
117
  	struct sctp_sockaddr_entry *addr, *temp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
  
  	/* Empty the bind address list. */
c182f90bc   Jacek Luczak   SCTP: fix race be...
120
121
  	list_for_each_entry_safe(addr, temp, &bp->address_list, list) {
  		list_del_rcu(&addr->list);
5d4145216   David S. Miller   sctp: Fix build f...
122
  		kfree_rcu(addr, rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
125
126
127
128
129
130
131
  		SCTP_DBG_OBJCNT_DEC(addr);
  	}
  }
  
  /* Dispose of an SCTP_bind_addr structure  */
  void sctp_bind_addr_free(struct sctp_bind_addr *bp)
  {
  	/* Empty the bind address list. */
  	sctp_bind_addr_clean(bp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
135
  }
  
  /* Add an address to the bind address list in the SCTP_bind_addr structure. */
  int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
133800d1f   Marcelo Ricardo Leitner   sctp: fix copying...
136
  		       int new_size, __u8 addr_state, gfp_t gfp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
140
  {
  	struct sctp_sockaddr_entry *addr;
  
  	/* Add the address to the bind address list.  */
939cfa75a   Daniel Borkmann   net: sctp: get ri...
141
  	addr = kzalloc(sizeof(*addr), gfp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
  	if (!addr)
  		return -ENOMEM;
133800d1f   Marcelo Ricardo Leitner   sctp: fix copying...
144
  	memcpy(&addr->a, new, min_t(size_t, sizeof(*new), new_size));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
147
148
  
  	/* Fix up the port if it has not yet been set.
  	 * Both v4 and v6 have the port at the same offset.
  	 */
5ab7b859a   Al Viro   [SCTP]: Switch sc...
149
150
  	if (!addr->a.v4.sin_port)
  		addr->a.v4.sin_port = htons(bp->port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151

f57d96b2e   Vlad Yasevich   [SCTP]: Change us...
152
  	addr->state = addr_state;
293035479   Vlad Yasevich   [SCTP]: Add RCU s...
153
  	addr->valid = 1;
dc022a987   Sridhar Samudrala   [SCTP]: ADDIP: Do...
154

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
  	INIT_LIST_HEAD(&addr->list);
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
156
157
158
159
160
  
  	/* We always hold a socket lock when calling this function,
  	 * and that acts as a writer synchronizing lock.
  	 */
  	list_add_tail_rcu(&addr->list, &bp->address_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
163
164
165
166
167
168
  	SCTP_DBG_OBJCNT_INC(addr);
  
  	return 0;
  }
  
  /* Delete an address from the bind address list in the SCTP_bind_addr
   * structure.
   */
0ed90fb0f   Vlad Yasevich   SCTP: Update RCU ...
169
  int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
  {
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
171
  	struct sctp_sockaddr_entry *addr, *temp;
22626216c   Chidambar 'ilLogict' Zinnoury   [SCTP]: Fix local...
172
  	int found = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173

559cf710b   Vlad Yasevich   [SCTP]: Convert b...
174
175
176
177
  	/* We hold the socket lock when calling this function,
  	 * and that acts as a writer synchronizing lock.
  	 */
  	list_for_each_entry_safe(addr, temp, &bp->address_list, list) {
c9a08505e   Al Viro   [SCTP]: Switch sc...
178
  		if (sctp_cmp_addr_exact(&addr->a, del_addr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  			/* Found the exact match. */
22626216c   Chidambar 'ilLogict' Zinnoury   [SCTP]: Fix local...
180
  			found = 1;
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
181
182
183
  			addr->valid = 0;
  			list_del_rcu(&addr->list);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
  		}
  	}
22626216c   Chidambar 'ilLogict' Zinnoury   [SCTP]: Fix local...
186
  	if (found) {
1231f0baa   Lai Jiangshan   net,rcu: convert ...
187
  		kfree_rcu(addr, rcu);
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
188
  		SCTP_DBG_OBJCNT_DEC(addr);
0ed90fb0f   Vlad Yasevich   SCTP: Update RCU ...
189
  		return 0;
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
190
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
193
194
195
196
197
198
199
  	return -EINVAL;
  }
  
  /* Create a network byte-order representation of all the addresses
   * formated as SCTP parameters.
   *
   * The second argument is the return value for the length.
   */
  union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
3182cd84f   Alexey Dobriyan   [SCTP]: __nocast ...
200
  					 int *addrs_len,
dd0fc66fb   Al Viro   [PATCH] gfp flags...
201
  					 gfp_t gfp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  {
  	union sctp_params addrparms;
  	union sctp_params retval;
  	int addrparms_len;
  	union sctp_addr_param rawaddr;
  	int len;
  	struct sctp_sockaddr_entry *addr;
  	struct list_head *pos;
  	struct sctp_af *af;
  
  	addrparms_len = 0;
  	len = 0;
  
  	/* Allocate enough memory at once. */
  	list_for_each(pos, &bp->address_list) {
  		len += sizeof(union sctp_addr_param);
  	}
  
  	/* Don't even bother embedding an address if there
  	 * is only one.
  	 */
  	if (len == sizeof(union sctp_addr_param)) {
  		retval.v = NULL;
  		goto end_raw;
  	}
  
  	retval.v = kmalloc(len, gfp);
  	if (!retval.v)
  		goto end_raw;
  
  	addrparms = retval;
9dbc15f05   Robert P. J. Day   [SCTP]: "list_for...
233
  	list_for_each_entry(addr, &bp->address_list, list) {
6244be4e0   Al Viro   [SCTP]: Trivial p...
234
235
  		af = sctp_get_af_specific(addr->a.v4.sin_family);
  		len = af->to_addr_param(&addr->a, &rawaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
  		memcpy(addrparms.v, &rawaddr, len);
  		addrparms.v += len;
  		addrparms_len += len;
  	}
  
  end_raw:
  	*addrs_len = addrparms_len;
  	return retval;
  }
  
  /*
   * Create an address list out of the raw address list format (IPv4 and IPv6
   * address parameters).
   */
  int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
dd0fc66fb   Al Viro   [PATCH] gfp flags...
251
  			   int addrs_len, __u16 port, gfp_t gfp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
  {
  	union sctp_addr_param *rawaddr;
  	struct sctp_paramhdr *param;
  	union sctp_addr addr;
  	int retval = 0;
  	int len;
  	struct sctp_af *af;
  
  	/* Convert the raw address to standard address format */
  	while (addrs_len) {
  		param = (struct sctp_paramhdr *)raw_addr_list;
  		rawaddr = (union sctp_addr_param *)raw_addr_list;
  
  		af = sctp_get_af_specific(param_type2af(param->type));
  		if (unlikely(!af)) {
  			retval = -EINVAL;
  			sctp_bind_addr_clean(bp);
  			break;
  		}
dd86d136f   Al Viro   [SCTP]: Switch ->...
271
  		af->from_addr_param(&addr, rawaddr, htons(port), 0);
b8607805d   Xin Long   sctp: not copying...
272
273
  		if (sctp_bind_addr_state(bp, &addr) != -1)
  			goto next;
133800d1f   Marcelo Ricardo Leitner   sctp: fix copying...
274
275
  		retval = sctp_add_bind_addr(bp, &addr, sizeof(addr),
  					    SCTP_ADDR_SRC, gfp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
279
280
  		if (retval) {
  			/* Can't finish building the list, clean up. */
  			sctp_bind_addr_clean(bp);
  			break;
  		}
b8607805d   Xin Long   sctp: not copying...
281
  next:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
285
286
287
288
289
290
291
292
293
294
  		len = ntohs(param->length);
  		addrs_len -= len;
  		raw_addr_list += len;
  	}
  
  	return retval;
  }
  
  /********************************************************************
   * 2nd Level Abstractions
   ********************************************************************/
  
  /* Does this contain a specified address?  Allow wildcarding. */
d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
295
  int sctp_bind_addr_match(struct sctp_bind_addr *bp,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
  			 const union sctp_addr *addr,
  			 struct sctp_sock *opt)
  {
  	struct sctp_sockaddr_entry *laddr;
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
300
301
302
303
304
305
306
307
308
309
  	int match = 0;
  
  	rcu_read_lock();
  	list_for_each_entry_rcu(laddr, &bp->address_list, list) {
  		if (!laddr->valid)
  			continue;
  		if (opt->pf->cmp_addr(&laddr->a, addr, opt)) {
  			match = 1;
  			break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
  	}
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
311
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312

559cf710b   Vlad Yasevich   [SCTP]: Convert b...
313
  	return match;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314
  }
76c6d988a   Xin Long   sctp: add sock_re...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
  int sctp_bind_addrs_check(struct sctp_sock *sp,
  			  struct sctp_sock *sp2, int cnt2)
  {
  	struct sctp_bind_addr *bp2 = &sp2->ep->base.bind_addr;
  	struct sctp_bind_addr *bp = &sp->ep->base.bind_addr;
  	struct sctp_sockaddr_entry *laddr, *laddr2;
  	bool exist = false;
  	int cnt = 0;
  
  	rcu_read_lock();
  	list_for_each_entry_rcu(laddr, &bp->address_list, list) {
  		list_for_each_entry_rcu(laddr2, &bp2->address_list, list) {
  			if (sp->pf->af->cmp_addr(&laddr->a, &laddr2->a) &&
  			    laddr->valid && laddr2->valid) {
  				exist = true;
  				goto next;
  			}
  		}
  		cnt = 0;
  		break;
  next:
  		cnt++;
  	}
  	rcu_read_unlock();
  
  	return (cnt == cnt2) ? 0 : (exist ? -EEXIST : 1);
  }
7dab83de5   Vlad Yasevich   sctp: Support ipv...
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
  /* Does the address 'addr' conflict with any addresses in
   * the bp.
   */
  int sctp_bind_addr_conflict(struct sctp_bind_addr *bp,
  			    const union sctp_addr *addr,
  			    struct sctp_sock *bp_sp,
  			    struct sctp_sock *addr_sp)
  {
  	struct sctp_sockaddr_entry *laddr;
  	int conflict = 0;
  	struct sctp_sock *sp;
  
  	/* Pick the IPv6 socket as the basis of comparison
  	 * since it's usually a superset of the IPv4.
  	 * If there is no IPv6 socket, then default to bind_addr.
  	 */
  	if (sctp_opt2sk(bp_sp)->sk_family == AF_INET6)
  		sp = bp_sp;
  	else if (sctp_opt2sk(addr_sp)->sk_family == AF_INET6)
  		sp = addr_sp;
  	else
  		sp = bp_sp;
  
  	rcu_read_lock();
  	list_for_each_entry_rcu(laddr, &bp->address_list, list) {
  		if (!laddr->valid)
  			continue;
  
  		conflict = sp->pf->cmp_addr(&laddr->a, addr, sp);
  		if (conflict)
  			break;
  	}
  	rcu_read_unlock();
  
  	return conflict;
  }
75205f478   Vlad Yasevich   [SCTP]: Implement...
378
379
380
381
382
383
  /* Get the state of the entry in the bind_addr_list */
  int sctp_bind_addr_state(const struct sctp_bind_addr *bp,
  			 const union sctp_addr *addr)
  {
  	struct sctp_sockaddr_entry *laddr;
  	struct sctp_af *af;
75205f478   Vlad Yasevich   [SCTP]: Implement...
384
385
386
  
  	af = sctp_get_af_specific(addr->sa.sa_family);
  	if (unlikely(!af))
3cab2afb1   Xin Long   sctp: remove rcu_...
387
  		return -1;
75205f478   Vlad Yasevich   [SCTP]: Implement...
388

75205f478   Vlad Yasevich   [SCTP]: Implement...
389
390
391
  	list_for_each_entry_rcu(laddr, &bp->address_list, list) {
  		if (!laddr->valid)
  			continue;
3cab2afb1   Xin Long   sctp: remove rcu_...
392
393
  		if (af->cmp_addr(&laddr->a, addr))
  			return laddr->state;
75205f478   Vlad Yasevich   [SCTP]: Implement...
394
  	}
75205f478   Vlad Yasevich   [SCTP]: Implement...
395

3cab2afb1   Xin Long   sctp: remove rcu_...
396
  	return -1;
75205f478   Vlad Yasevich   [SCTP]: Implement...
397
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
400
401
402
403
404
405
406
407
408
409
  /* Find the first address in the bind address list that is not present in
   * the addrs packed array.
   */
  union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
  					const union sctp_addr	*addrs,
  					int			addrcnt,
  					struct sctp_sock	*opt)
  {
  	struct sctp_sockaddr_entry	*laddr;
  	union sctp_addr			*addr;
  	void 				*addr_buf;
  	struct sctp_af			*af;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410
  	int				i;
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
411
412
413
414
415
  	/* This is only called sctp_send_asconf_del_ip() and we hold
  	 * the socket lock in that code patch, so that address list
  	 * can't change.
  	 */
  	list_for_each_entry(laddr, &bp->address_list, list) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
417
  		addr_buf = (union sctp_addr *)addrs;
  		for (i = 0; i < addrcnt; i++) {
ea1107338   Joe Perches   net: Remove casts...
418
  			addr = addr_buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
  			af = sctp_get_af_specific(addr->v4.sin_family);
d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
420
  			if (!af)
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
421
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422

5f242a13e   Al Viro   [SCTP]: Switch ->...
423
  			if (opt->pf->cmp_addr(&laddr->a, addr, opt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
426
427
428
  				break;
  
  			addr_buf += af->sockaddr_len;
  		}
  		if (i == addrcnt)
5ae955cff   Al Viro   [SCTP]: sctp_make...
429
  			return &laddr->a;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
431
432
433
434
435
  	}
  
  	return NULL;
  }
  
  /* Copy out addresses from the global local address list. */
4db67e808   Eric W. Biederman   sctp: Make the ad...
436
  static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
1c662018d   Xin Long   sctp: remove the ...
437
438
  			      union sctp_addr *addr, enum sctp_scope scope,
  			      gfp_t gfp, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
  {
  	int error = 0;
52cae8f06   Vlad Yasevich   sctp: try harder ...
441
  	if (sctp_is_any(NULL, addr)) {
4db67e808   Eric W. Biederman   sctp: Make the ad...
442
  		error = sctp_copy_local_addr_list(net, dest, scope, gfp, flags);
e7ff4a703   Eric W. Biederman   sctp: Push struct...
443
  	} else if (sctp_in_scope(net, addr, scope)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
445
446
447
448
  		/* Now that the address is in scope, check to see if
  		 * the address type is supported by local sock as
  		 * well as the remote peer.
  		 */
  		if ((((AF_INET == addr->sa.sa_family) &&
dc43f7e80   Marcelo Ricardo Leitner   sctp: Don't adver...
449
  		      (flags & SCTP_ADDR4_ALLOWED) &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
452
453
  		      (flags & SCTP_ADDR4_PEERSUPP))) ||
  		    (((AF_INET6 == addr->sa.sa_family) &&
  		      (flags & SCTP_ADDR6_ALLOWED) &&
  		      (flags & SCTP_ADDR6_PEERSUPP))))
133800d1f   Marcelo Ricardo Leitner   sctp: fix copying...
454
455
  			error = sctp_add_bind_addr(dest, addr, sizeof(*addr),
  						   SCTP_ADDR_SRC, gfp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
457
458
459
460
461
  	}
  
  	return error;
  }
  
  /* Is this a wildcard address?  */
52cae8f06   Vlad Yasevich   sctp: try harder ...
462
  int sctp_is_any(struct sock *sk, const union sctp_addr *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
  {
52cae8f06   Vlad Yasevich   sctp: try harder ...
464
465
466
467
468
469
470
471
472
473
  	unsigned short fam = 0;
  	struct sctp_af *af;
  
  	/* Try to get the right address family */
  	if (addr->sa.sa_family != AF_UNSPEC)
  		fam = addr->sa.sa_family;
  	else if (sk)
  		fam = sk->sk_family;
  
  	af = sctp_get_af_specific(fam);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
  	if (!af)
  		return 0;
52cae8f06   Vlad Yasevich   sctp: try harder ...
476

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
478
479
480
  	return af->is_any(addr);
  }
  
  /* Is 'addr' valid for 'scope'?  */
1c662018d   Xin Long   sctp: remove the ...
481
482
  int sctp_in_scope(struct net *net, const union sctp_addr *addr,
  		  enum sctp_scope scope)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
  {
1c662018d   Xin Long   sctp: remove the ...
484
  	enum sctp_scope addr_scope = sctp_scope(addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
486
487
488
489
490
491
492
493
494
495
  
  	/* The unusable SCTP addresses will not be considered with
  	 * any defined scopes.
  	 */
  	if (SCTP_SCOPE_UNUSABLE == addr_scope)
  		return 0;
  	/*
  	 * For INIT and INIT-ACK address list, let L be the level of
  	 * of requested destination address, sender and receiver
  	 * SHOULD include all of its addresses with level greater
  	 * than or equal to L.
723884339   Bhaskar Dutta   sctp: Sysctl conf...
496
497
498
  	 *
  	 * Address scoping can be selectively controlled via sysctl
  	 * option
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
  	 */
e1fc3b14f   Eric W. Biederman   sctp: Make sysctl...
500
  	switch (net->sctp.scope_policy) {
723884339   Bhaskar Dutta   sctp: Sysctl conf...
501
  	case SCTP_SCOPE_POLICY_DISABLE:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  		return 1;
723884339   Bhaskar Dutta   sctp: Sysctl conf...
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
  	case SCTP_SCOPE_POLICY_ENABLE:
  		if (addr_scope <= scope)
  			return 1;
  		break;
  	case SCTP_SCOPE_POLICY_PRIVATE:
  		if (addr_scope <= scope || SCTP_SCOPE_PRIVATE == addr_scope)
  			return 1;
  		break;
  	case SCTP_SCOPE_POLICY_LINK:
  		if (addr_scope <= scope || SCTP_SCOPE_LINK == addr_scope)
  			return 1;
  		break;
  	default:
  		break;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
519
520
  
  	return 0;
  }
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
521
522
523
524
525
526
527
528
529
530
531
532
533
534
  int sctp_is_ep_boundall(struct sock *sk)
  {
  	struct sctp_bind_addr *bp;
  	struct sctp_sockaddr_entry *addr;
  
  	bp = &sctp_sk(sk)->ep->base.bind_addr;
  	if (sctp_list_single_entry(&bp->address_list)) {
  		addr = list_entry(bp->address_list.next,
  				  struct sctp_sockaddr_entry, list);
  		if (sctp_is_any(sk, &addr->a))
  			return 1;
  	}
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
538
539
  /********************************************************************
   * 3rd Level Abstractions
   ********************************************************************/
  
  /* What is the scope of 'addr'?  */
1c662018d   Xin Long   sctp: remove the ...
540
  enum sctp_scope sctp_scope(const union sctp_addr *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
543
544
545
546
547
548
549
  {
  	struct sctp_af *af;
  
  	af = sctp_get_af_specific(addr->sa.sa_family);
  	if (!af)
  		return SCTP_SCOPE_UNUSABLE;
  
  	return af->scope((union sctp_addr *)addr);
  }