addr->valid = 1;
INIT_LIST_HEAD(&addr->list);
- INIT_RCU_HEAD(&addr->rcu);
/* We always hold a socket lock when calling this function,
* and that acts as a writer synchronizing lock.
{
int error = 0;
- if (sctp_is_any(addr)) {
+ if (sctp_is_any(NULL, addr)) {
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
}
/* Is this a wildcard address? */
-int sctp_is_any(const union sctp_addr *addr)
+int sctp_is_any(struct sock *sk, const union sctp_addr *addr)
{
- struct sctp_af *af = sctp_get_af_specific(addr->sa.sa_family);
+ 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);
if (!af)
return 0;
+
return af->is_any(addr);
}
* of requested destination address, sender and receiver
* SHOULD include all of its addresses with level greater
* than or equal to L.
+ *
+ * Address scoping can be selectively controlled via sysctl
+ * option
*/
- if (addr_scope <= scope)
+ switch (sctp_scope_policy) {
+ case SCTP_SCOPE_POLICY_DISABLE:
return 1;
+ 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;
+ }
return 0;
}