aboutsummaryrefslogtreecommitdiff
path: root/net/sctp/bind_addr.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-21 15:05:58 +0200
committerIngo Molnar <mingo@elte.hu>2008-07-21 15:05:58 +0200
commit1c29dd9a9e2f83ffb02e50bb3619c3b9db8fd526 (patch)
treeb5691dd5aa48ac32fdbaef44afcbcc92f01592d3 /net/sctp/bind_addr.c
parent32172561889868c0ea422ea8570f0413963a815f (diff)
parent14b395e35d1afdd8019d11b92e28041fad591b71 (diff)
Merge branch 'linus' into x86/paravirt-spinlocks
Diffstat (limited to 'net/sctp/bind_addr.c')
-rw-r--r--net/sctp/bind_addr.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 80e6df06967..f62bc246893 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,
return match;
}
+/* 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;
+}
+
/* 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)