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,
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:
if (error)
sctp_bind_addr_clean(dest);
......@@ -214,6 +230,14 @@ union sctp_params sctp_bind_addrs_to_raw(const sctp_bind_addr_t *bp,
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);
if (!retval.v)
goto end_raw;
......
......@@ -177,12 +177,9 @@ sctp_chunk_t *sctp_make_init(const struct sctp_association *asoc,
* can be IPv4 and/or IPv6 in any combination.
*/
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);
if (!addrs.v)
goto nodata;
init.init_tag = htonl(asoc->c.my_vtag);
init.a_rwnd = htonl(asoc->rwnd);
......@@ -252,9 +249,8 @@ sctp_chunk_t *sctp_make_init_ack(const struct sctp_association *asoc,
retval = NULL;
/* Note: there may be no addresses to embed. */
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.a_rwnd = htonl(asoc->rwnd);
......@@ -313,8 +309,8 @@ sctp_chunk_t *sctp_make_init_ack(const struct sctp_association *asoc,
nomem_chunk:
kfree(cookie);
nomem_cookie:
if (addrs.v)
kfree(addrs.v);
nomem_rawaddr:
return retval;
}
......@@ -840,7 +836,7 @@ sctp_chunk_t *sctp_make_abort_user(const struct sctp_association *asoc,
payoff = payload;
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;
payoff += iov->iov_len;
iov++;
......@@ -1542,6 +1538,12 @@ struct sctp_association *sctp_unpack_cookie(
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->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