Blame view

net/sctp/bind_addr.c 14 KB
60c778b25   Vlad Yasevich   [SCTP]: Stop clai...
1
  /* SCTP kernel implementation
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
   * (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...
7
   * This file is part of the SCTP kernel implementation.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
   *
   * A collection class to handle the storage of transport addresses.
   *
60c778b25   Vlad Yasevich   [SCTP]: Stop clai...
11
   * This SCTP implementation is free software;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
   * you can redistribute it and/or modify it under the terms of
   * the GNU General Public License as published by
   * the Free Software Foundation; either version 2, or (at your option)
   * any later version.
   *
60c778b25   Vlad Yasevich   [SCTP]: Stop clai...
17
   * This SCTP implementation is distributed in the hope that it
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
   * will be useful, but WITHOUT ANY WARRANTY; without even the implied
   *                 ************************
   * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   * See the GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with GNU CC; see the file COPYING.  If not, write to
   * the Free Software Foundation, 59 Temple Place - Suite 330,
   * Boston, MA 02111-1307, USA.
   *
   * Please send any bug reports or fixes you make to the
   * email address(es):
   *    lksctp developers <lksctp-developers@lists.sourceforge.net>
   *
   * Or submit a bug report through the following website:
   *    http://www.sf.net/projects/lksctp
   *
   * 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>
   *
   * Any bugs reported given to us we will try to fix... any fixes shared will
   * be incorporated into the next SCTP release.
   */
  
  #include <linux/types.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
46
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
50
51
52
53
54
55
  #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. */
  static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *,
dd0fc66fb   Al Viro   [PATCH] gfp flags...
56
  			      sctp_scope_t scope, gfp_t gfp,
3182cd84f   Alexey Dobriyan   [SCTP]: __nocast ...
57
  			      int flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
62
63
64
  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'.
   */
d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
65
  int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  			const struct sctp_bind_addr *src,
dd0fc66fb   Al Viro   [PATCH] gfp flags...
67
  			sctp_scope_t scope, gfp_t gfp,
3182cd84f   Alexey Dobriyan   [SCTP]: __nocast ...
68
  			int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
  {
  	struct sctp_sockaddr_entry *addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
73
74
75
76
  	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...
77
  	list_for_each_entry(addr, &src->address_list, list) {
02a8a4db3   Al Viro   [SCTP]: sctp_copy...
78
  		error = sctp_copy_one_addr(dest, &addr->a, scope,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
82
83
84
85
86
87
88
  					   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...
89
  		list_for_each_entry(addr, &src->address_list, list) {
02a8a4db3   Al Viro   [SCTP]: sctp_copy...
90
  			error = sctp_copy_one_addr(dest, &addr->a,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
94
95
96
97
98
99
100
101
102
103
  						   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...
104
105
106
107
108
109
110
111
112
113
  /* 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...
114
115
116
117
  	int error = 0;
  
  	/* All addresses share the same port.  */
  	dest->port = src->port;
9dbc15f05   Robert P. J. Day   [SCTP]: "list_for...
118
  	list_for_each_entry(addr, &src->address_list, list) {
8e71a11c9   Vlad Yasevich   [SCTP]: Fix the b...
119
120
121
122
123
124
125
  		error = sctp_add_bind_addr(dest, &addr->a, 1, gfp);
  		if (error < 0)
  			break;
  	}
  
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  /* 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)
  {
  	bp->malloced = 0;
  
  	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...
140
  	struct sctp_sockaddr_entry *addr, *temp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
  
  	/* Empty the bind address list. */
c182f90bc   Jacek Luczak   SCTP: fix race be...
143
144
  	list_for_each_entry_safe(addr, temp, &bp->address_list, list) {
  		list_del_rcu(&addr->list);
5d4145216   David S. Miller   sctp: Fix build f...
145
  		kfree_rcu(addr, rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
  		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);
  
  	if (bp->malloced) {
  		kfree(bp);
  		SCTP_DBG_OBJCNT_DEC(bind_addr);
  	}
  }
  
  /* 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,
f57d96b2e   Vlad Yasevich   [SCTP]: Change us...
164
  		       __u8 addr_state, gfp_t gfp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
167
168
169
170
171
  {
  	struct sctp_sockaddr_entry *addr;
  
  	/* Add the address to the bind address list.  */
  	addr = t_new(struct sctp_sockaddr_entry, gfp);
  	if (!addr)
  		return -ENOMEM;
5ab7b859a   Al Viro   [SCTP]: Switch sc...
172
  	memcpy(&addr->a, new, sizeof(*new));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
174
175
176
  
  	/* 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...
177
178
  	if (!addr->a.v4.sin_port)
  		addr->a.v4.sin_port = htons(bp->port);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  	INIT_LIST_HEAD(&addr->list);
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
184
185
186
187
188
  
  	/* 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
189
190
191
192
193
194
195
196
  	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 ...
197
  int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  {
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
199
  	struct sctp_sockaddr_entry *addr, *temp;
22626216c   Chidambar 'ilLogict' Zinnoury   [SCTP]: Fix local...
200
  	int found = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201

559cf710b   Vlad Yasevich   [SCTP]: Convert b...
202
203
204
205
  	/* 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...
206
  		if (sctp_cmp_addr_exact(&addr->a, del_addr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  			/* Found the exact match. */
22626216c   Chidambar 'ilLogict' Zinnoury   [SCTP]: Fix local...
208
  			found = 1;
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
209
210
211
  			addr->valid = 0;
  			list_del_rcu(&addr->list);
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
  		}
  	}
22626216c   Chidambar 'ilLogict' Zinnoury   [SCTP]: Fix local...
214
  	if (found) {
1231f0baa   Lai Jiangshan   net,rcu: convert ...
215
  		kfree_rcu(addr, rcu);
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
216
  		SCTP_DBG_OBJCNT_DEC(addr);
0ed90fb0f   Vlad Yasevich   SCTP: Update RCU ...
217
  		return 0;
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
218
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
221
222
223
224
225
226
227
  	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 ...
228
  					 int *addrs_len,
dd0fc66fb   Al Viro   [PATCH] gfp flags...
229
  					 gfp_t gfp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
  {
  	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...
261
  	list_for_each_entry(addr, &bp->address_list, list) {
6244be4e0   Al Viro   [SCTP]: Trivial p...
262
263
  		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
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  		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...
279
  			   int addrs_len, __u16 port, gfp_t gfp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
  {
  	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 ->...
299
  		af->from_addr_param(&addr, rawaddr, htons(port), 0);
f57d96b2e   Vlad Yasevich   [SCTP]: Change us...
300
  		retval = sctp_add_bind_addr(bp, &addr, SCTP_ADDR_SRC, gfp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
  		if (retval) {
  			/* Can't finish building the list, clean up. */
  			sctp_bind_addr_clean(bp);
  			break;
  		}
  
  		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...
320
  int sctp_bind_addr_match(struct sctp_bind_addr *bp,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
322
323
324
  			 const union sctp_addr *addr,
  			 struct sctp_sock *opt)
  {
  	struct sctp_sockaddr_entry *laddr;
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
325
326
327
328
329
330
331
332
333
334
  	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
335
  	}
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
336
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337

559cf710b   Vlad Yasevich   [SCTP]: Convert b...
338
  	return match;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  }
7dab83de5   Vlad Yasevich   sctp: Support ipv...
340
341
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
  /* 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...
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
  /* 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;
  	int state = -1;
  
  	af = sctp_get_af_specific(addr->sa.sa_family);
  	if (unlikely(!af))
  		return state;
  
  	rcu_read_lock();
  	list_for_each_entry_rcu(laddr, &bp->address_list, list) {
  		if (!laddr->valid)
  			continue;
  		if (af->cmp_addr(&laddr->a, addr)) {
  			state = laddr->state;
  			break;
  		}
  	}
  	rcu_read_unlock();
  
  	return state;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
402
403
404
405
406
407
408
409
410
411
412
  /* 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
413
  	int				i;
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
414
415
416
417
418
  	/* 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
419
420
  		addr_buf = (union sctp_addr *)addrs;
  		for (i = 0; i < addrcnt; i++) {
ea1107338   Joe Perches   net: Remove casts...
421
  			addr = addr_buf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
  			af = sctp_get_af_specific(addr->v4.sin_family);
d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
423
  			if (!af)
559cf710b   Vlad Yasevich   [SCTP]: Convert b...
424
  				break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425

5f242a13e   Al Viro   [SCTP]: Switch ->...
426
  			if (opt->pf->cmp_addr(&laddr->a, addr, opt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
428
429
430
431
  				break;
  
  			addr_buf += af->sockaddr_len;
  		}
  		if (i == addrcnt)
5ae955cff   Al Viro   [SCTP]: sctp_make...
432
  			return &laddr->a;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
436
437
438
  	}
  
  	return NULL;
  }
  
  /* Copy out addresses from the global local address list. */
d808ad9ab   YOSHIFUJI Hideaki   [NET] SCTP: Fix w...
439
  static int sctp_copy_one_addr(struct sctp_bind_addr *dest,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
  			      union sctp_addr *addr,
dd0fc66fb   Al Viro   [PATCH] gfp flags...
441
  			      sctp_scope_t scope, gfp_t gfp,
3182cd84f   Alexey Dobriyan   [SCTP]: __nocast ...
442
  			      int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
444
  {
  	int error = 0;
52cae8f06   Vlad Yasevich   sctp: try harder ...
445
  	if (sctp_is_any(NULL, addr)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
447
448
449
450
451
452
453
454
455
456
  		error = sctp_copy_local_addr_list(dest, scope, gfp, flags);
  	} else if (sctp_in_scope(addr, scope)) {
  		/* 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) &&
  		      (flags & SCTP_ADDR4_PEERSUPP))) ||
  		    (((AF_INET6 == addr->sa.sa_family) &&
  		      (flags & SCTP_ADDR6_ALLOWED) &&
  		      (flags & SCTP_ADDR6_PEERSUPP))))
f57d96b2e   Vlad Yasevich   [SCTP]: Change us...
457
458
  			error = sctp_add_bind_addr(dest, addr, SCTP_ADDR_SRC,
  						    gfp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
461
462
463
464
  	}
  
  	return error;
  }
  
  /* Is this a wildcard address?  */
52cae8f06   Vlad Yasevich   sctp: try harder ...
465
  int sctp_is_any(struct sock *sk, const union sctp_addr *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
  {
52cae8f06   Vlad Yasevich   sctp: try harder ...
467
468
469
470
471
472
473
474
475
476
  	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
477
478
  	if (!af)
  		return 0;
52cae8f06   Vlad Yasevich   sctp: try harder ...
479

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
  	return af->is_any(addr);
  }
  
  /* Is 'addr' valid for 'scope'?  */
  int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope)
  {
  	sctp_scope_t addr_scope = sctp_scope(addr);
  
  	/* 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...
498
499
500
  	 *
  	 * Address scoping can be selectively controlled via sysctl
  	 * option
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
  	 */
723884339   Bhaskar Dutta   sctp: Sysctl conf...
502
503
  	switch (sctp_scope_policy) {
  	case SCTP_SCOPE_POLICY_DISABLE:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
  		return 1;
723884339   Bhaskar Dutta   sctp: Sysctl conf...
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
  	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
520
521
522
  
  	return 0;
  }
9f7d653b6   Michio Honda   sctp: Add Auto-AS...
523
524
525
526
527
528
529
530
531
532
533
534
535
536
  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
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
  /********************************************************************
   * 3rd Level Abstractions
   ********************************************************************/
  
  /* What is the scope of 'addr'?  */
  sctp_scope_t sctp_scope(const union sctp_addr *addr)
  {
  	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);
  }