diff options
Diffstat (limited to 'net/sctp/bind_addr.c')
-rw-r--r-- | net/sctp/bind_addr.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 80e6df06967a..f62bc2468935 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c | |||
@@ -348,6 +348,43 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp, | |||
348 | return match; | 348 | return match; |
349 | } | 349 | } |
350 | 350 | ||
351 | /* Does the address 'addr' conflict with any addresses in | ||
352 | * the bp. | ||
353 | */ | ||
354 | int sctp_bind_addr_conflict(struct sctp_bind_addr *bp, | ||
355 | const union sctp_addr *addr, | ||
356 | struct sctp_sock *bp_sp, | ||
357 | struct sctp_sock *addr_sp) | ||
358 | { | ||
359 | struct sctp_sockaddr_entry *laddr; | ||
360 | int conflict = 0; | ||
361 | struct sctp_sock *sp; | ||
362 | |||
363 | /* Pick the IPv6 socket as the basis of comparison | ||
364 | * since it's usually a superset of the IPv4. | ||
365 | * If there is no IPv6 socket, then default to bind_addr. | ||
366 | */ | ||
367 | if (sctp_opt2sk(bp_sp)->sk_family == AF_INET6) | ||
368 | sp = bp_sp; | ||
369 | else if (sctp_opt2sk(addr_sp)->sk_family == AF_INET6) | ||
370 | sp = addr_sp; | ||
371 | else | ||
372 | sp = bp_sp; | ||
373 | |||
374 | rcu_read_lock(); | ||
375 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { | ||
376 | if (!laddr->valid) | ||
377 | continue; | ||
378 | |||
379 | conflict = sp->pf->cmp_addr(&laddr->a, addr, sp); | ||
380 | if (conflict) | ||
381 | break; | ||
382 | } | ||
383 | rcu_read_unlock(); | ||
384 | |||
385 | return conflict; | ||
386 | } | ||
387 | |||
351 | /* Get the state of the entry in the bind_addr_list */ | 388 | /* Get the state of the entry in the bind_addr_list */ |
352 | int sctp_bind_addr_state(const struct sctp_bind_addr *bp, | 389 | int sctp_bind_addr_state(const struct sctp_bind_addr *bp, |
353 | const union sctp_addr *addr) | 390 | const union sctp_addr *addr) |