Commit 544dea83 authored by Jon Grimm's avatar Jon Grimm Committed by Sridhar Samudrala

[SCTP] Allow private to global association.

The sctp scoping rules try to prevent accidentally sending
non-routable addresses to a peer as alternate addresses.  However,
the current implementation is way too strict in that one can't
even try to send from a private address to a global address (a
pretty common real world setup with host behind NAT) even 
when that's the _only_ address available.

If we find no addresses available, try looking for a private address 
to send with, as a fallback.  
Additionally, if we are sending with only a single address, don't
bother embedding this address in the INIT/INIT-ACK chunk.  
parent 293f0d65
...@@ -80,6 +80,22 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src, ...@@ -80,6 +80,22 @@ int sctp_bind_addr_copy(sctp_bind_addr_t *dest, const sctp_bind_addr_t *src,
goto out; 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)) {
list_for_each(pos, &src->address_list) {
addr = list_entry(pos, struct sockaddr_storage_list,
list);
error = sctp_copy_one_addr(dest, &addr->a,
SCTP_SCOPE_LINK, gfp,
flags);
if (error < 0)
goto out;
}
}
out: out:
if (error) if (error)
sctp_bind_addr_clean(dest); sctp_bind_addr_clean(dest);
...@@ -214,6 +230,14 @@ union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp, ...@@ -214,6 +230,14 @@ union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp,
len += sizeof(sctp_addr_param_t); len += sizeof(sctp_addr_param_t);
} }
/* Don't even bother embedding an address if there
* is only one.
*/
if (len == sizeof(sctp_addr_param_t)) {
retval.v = NULL;
goto end_raw;
}
retval.v = kmalloc(len, gfp); retval.v = kmalloc(len, gfp);
if (!retval.v) if (!retval.v)
goto end_raw; goto end_raw;
......
...@@ -177,12 +177,9 @@ sctp_chunk_t *sctp_make_init(const struct sctp_association *asoc, ...@@ -177,12 +177,9 @@ sctp_chunk_t *sctp_make_init(const struct sctp_association *asoc,
* can be IPv4 and/or IPv6 in any combination. * can be IPv4 and/or IPv6 in any combination.
*/ */
retval = NULL; retval = NULL;
addrs.v = NULL;
/* Convert the provided bind address list to raw format */ /* Convert the provided bind address list to raw format. */
addrs = sctp_bind_addrs_to_raw(bp, &addrs_len, gfp); addrs = sctp_bind_addrs_to_raw(bp, &addrs_len, gfp);
if (!addrs.v)
goto nodata;
init.init_tag = htonl(asoc->c.my_vtag); init.init_tag = htonl(asoc->c.my_vtag);
init.a_rwnd = htonl(asoc->rwnd); init.a_rwnd = htonl(asoc->rwnd);
...@@ -252,9 +249,8 @@ sctp_chunk_t *sctp_make_init_ack(const struct sctp_association *asoc, ...@@ -252,9 +249,8 @@ sctp_chunk_t *sctp_make_init_ack(const struct sctp_association *asoc,
retval = NULL; retval = NULL;
/* Note: there may be no addresses to embed. */
addrs = sctp_bind_addrs_to_raw(&asoc->base.bind_addr, &addrs_len, gfp); addrs = sctp_bind_addrs_to_raw(&asoc->base.bind_addr, &addrs_len, gfp);
if (!addrs.v)
goto nomem_rawaddr;
initack.init_tag = htonl(asoc->c.my_vtag); initack.init_tag = htonl(asoc->c.my_vtag);
initack.a_rwnd = htonl(asoc->rwnd); initack.a_rwnd = htonl(asoc->rwnd);
...@@ -313,8 +309,8 @@ sctp_chunk_t *sctp_make_init_ack(const struct sctp_association *asoc, ...@@ -313,8 +309,8 @@ sctp_chunk_t *sctp_make_init_ack(const struct sctp_association *asoc,
nomem_chunk: nomem_chunk:
kfree(cookie); kfree(cookie);
nomem_cookie: nomem_cookie:
if (addrs.v)
kfree(addrs.v); kfree(addrs.v);
nomem_rawaddr:
return retval; return retval;
} }
...@@ -840,7 +836,7 @@ sctp_chunk_t *sctp_make_abort_user(const struct sctp_association *asoc, ...@@ -840,7 +836,7 @@ sctp_chunk_t *sctp_make_abort_user(const struct sctp_association *asoc,
payoff = payload; payoff = payload;
for (; iovlen > 0; --iovlen) { for (; iovlen > 0; --iovlen) {
if (copy_from_user(payoff, iov->iov_base, iov->iov_len)) if (copy_from_user(payoff, iov->iov_base,iov->iov_len))
goto err_copy; goto err_copy;
payoff += iov->iov_len; payoff += iov->iov_len;
iov++; iov++;
...@@ -1542,6 +1538,12 @@ struct sctp_association *sctp_unpack_cookie( ...@@ -1542,6 +1538,12 @@ struct sctp_association *sctp_unpack_cookie(
goto fail; goto fail;
} }
/* Also, add the destination address. */
if (list_empty(&retval->base.bind_addr.address_list)) {
sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest,
GFP_ATOMIC);
}
retval->next_tsn = retval->c.initial_tsn; retval->next_tsn = retval->c.initial_tsn;
retval->ctsn_ack_point = retval->next_tsn - 1; retval->ctsn_ack_point = retval->next_tsn - 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment