aboutsummaryrefslogtreecommitdiff
path: root/net/sctp/bind_addr.c
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2008-07-18 23:05:40 -0700
committerDavid S. Miller <davem@davemloft.net>2008-07-18 23:05:40 -0700
commit7dab83de50c7b2b7ceac695a0b56fa6c0f95b0bc (patch)
tree979c6905f2ef643acccfea9ab9ed926e764e72c8 /net/sctp/bind_addr.c
parent6d0ccbac688207ca0616ab5094932af4db4747b3 (diff)
sctp: Support ipv6only AF_INET6 sockets.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
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)