Commit bd8b01e5 authored by Sridhar Samudrala's avatar Sridhar Samudrala Committed by Jon Grimm

[SCTP] Cleanup of association bind address list initialization.

parent 69ab3709
...@@ -69,7 +69,6 @@ typedef enum { ...@@ -69,7 +69,6 @@ typedef enum {
SCTP_CMD_INIT_FAILED, /* High level, do init failure work. */ SCTP_CMD_INIT_FAILED, /* High level, do init failure work. */
SCTP_CMD_REPORT_DUP, /* Report a duplicate TSN. */ SCTP_CMD_REPORT_DUP, /* Report a duplicate TSN. */
SCTP_CMD_REPORT_BIGGAP, /* Narc on a TSN (it was too high). */ SCTP_CMD_REPORT_BIGGAP, /* Narc on a TSN (it was too high). */
SCTP_CMD_SET_BIND_ADDR, /* Set the association bind_addr. */
SCTP_CMD_STRIKE, /* Mark a strike against a transport. */ SCTP_CMD_STRIKE, /* Mark a strike against a transport. */
SCTP_CMD_TRANSMIT, /* Transmit the outqueue. */ SCTP_CMD_TRANSMIT, /* Transmit the outqueue. */
SCTP_CMD_HB_TIMERS_START, /* Start the heartbeat timers. */ SCTP_CMD_HB_TIMERS_START, /* Start the heartbeat timers. */
......
...@@ -1636,6 +1636,10 @@ void sctp_assoc_sync_pmtu(sctp_association_t *); ...@@ -1636,6 +1636,10 @@ void sctp_assoc_sync_pmtu(sctp_association_t *);
void sctp_assoc_rwnd_increase(sctp_association_t *, int); void sctp_assoc_rwnd_increase(sctp_association_t *, int);
void sctp_assoc_rwnd_decrease(sctp_association_t *, int); void sctp_assoc_rwnd_decrease(sctp_association_t *, int);
int sctp_assoc_set_bind_addr_from_ep(sctp_association_t *, int);
int sctp_assoc_set_bind_addr_from_cookie(sctp_association_t *,
sctp_cookie_t *, int);
int sctp_cmp_addr_exact(const union sctp_addr *ss1, int sctp_cmp_addr_exact(const union sctp_addr *ss1,
const union sctp_addr *ss2); const union sctp_addr *ss2);
sctp_chunk_t *sctp_get_ecne_prepend(sctp_association_t *asoc); sctp_chunk_t *sctp_get_ecne_prepend(sctp_association_t *asoc);
......
...@@ -1044,3 +1044,40 @@ void sctp_assoc_rwnd_decrease(sctp_association_t *asoc, int len) ...@@ -1044,3 +1044,40 @@ void sctp_assoc_rwnd_decrease(sctp_association_t *asoc, int len)
SCTP_DEBUG_PRINTK("%s: asoc %p rwnd decreased by %d to (%u, %u)\n", SCTP_DEBUG_PRINTK("%s: asoc %p rwnd decreased by %d to (%u, %u)\n",
__FUNCTION__, asoc, len, asoc->rwnd, asoc->rwnd_over); __FUNCTION__, asoc, len, asoc->rwnd, asoc->rwnd_over);
} }
/* Build the bind address list for the association based on info from the
* local endpoint and the remote peer.
*/
int sctp_assoc_set_bind_addr_from_ep(sctp_association_t *asoc, int priority)
{
sctp_scope_t scope;
int flags;
/* Use scoping rules to determine the subset of addresses from
* the endpoint.
*/
scope = sctp_scope(&asoc->peer.active_path->ipaddr);
flags = (PF_INET6 == asoc->base.sk->family) ? SCTP_ADDR6_ALLOWED : 0;
if (asoc->peer.ipv4_address)
flags |= SCTP_ADDR4_PEERSUPP;
if (asoc->peer.ipv6_address)
flags |= SCTP_ADDR6_PEERSUPP;
return sctp_bind_addr_copy(&asoc->base.bind_addr,
&asoc->ep->base.bind_addr,
scope, priority, flags);
}
/* Build the association's bind address list from the cookie. */
int sctp_assoc_set_bind_addr_from_cookie(sctp_association_t *asoc,
sctp_cookie_t *cookie, int priority)
{
int var_size2 = ntohs(cookie->peer_init->chunk_hdr.length);
int var_size3 = cookie->raw_addr_list_len;
__u8 *raw_addr_list = (__u8 *)cookie + sizeof(sctp_cookie_t) +
var_size2;
return sctp_raw_to_bind_addrs(&asoc->base.bind_addr, raw_addr_list,
var_size3, asoc->ep->base.bind_addr.port,
priority);
}
...@@ -242,35 +242,10 @@ sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *asoc, ...@@ -242,35 +242,10 @@ sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *asoc,
sctp_cookie_param_t *cookie; sctp_cookie_param_t *cookie;
int cookie_len; int cookie_len;
size_t chunksize; size_t chunksize;
int error;
sctp_scope_t scope;
sctp_bind_addr_t *bp = NULL;
int flags;
retval = NULL; retval = NULL;
/* Build up the bind address list for the association based on addrs = sctp_bind_addrs_to_raw(&asoc->base.bind_addr, &addrs_len, priority);
* info from the local endpoint and the remote peer.
*/
bp = sctp_bind_addr_new(priority);
if (!bp)
goto nomem_bindaddr;
/* Look for supported address types parameter and then build
* our address list based on that.
*/
scope = sctp_scope(&asoc->peer.active_path->ipaddr);
flags = (PF_INET6 == asoc->base.sk->family) ? SCTP_ADDR6_ALLOWED : 0;
if (asoc->peer.ipv4_address)
flags |= SCTP_ADDR4_PEERSUPP;
if (asoc->peer.ipv6_address)
flags |= SCTP_ADDR6_PEERSUPP;
error = sctp_bind_addr_copy(bp, &asoc->ep->base.bind_addr,
scope, priority, flags);
if (error)
goto nomem_copyaddr;
addrs = sctp_bind_addrs_to_raw(bp, &addrs_len, priority);
if (!addrs.v) if (!addrs.v)
goto nomem_rawaddr; goto nomem_rawaddr;
...@@ -333,9 +308,6 @@ sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *asoc, ...@@ -333,9 +308,6 @@ sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *asoc,
nomem_cookie: nomem_cookie:
kfree(addrs.v); kfree(addrs.v);
nomem_rawaddr: nomem_rawaddr:
nomem_copyaddr:
sctp_bind_addr_free(bp);
nomem_bindaddr:
return retval; return retval;
} }
...@@ -1363,11 +1335,10 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep, ...@@ -1363,11 +1335,10 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
sctp_signed_cookie_t *cookie; sctp_signed_cookie_t *cookie;
sctp_cookie_t *bear_cookie; sctp_cookie_t *bear_cookie;
int headersize, bodysize; int headersize, bodysize;
int fixed_size, var_size1, var_size2, var_size3; int fixed_size;
__u8 digest_buf[SCTP_SIGNATURE_SIZE]; __u8 digest_buf[SCTP_SIGNATURE_SIZE];
int secret; int secret;
sctp_scope_t scope; sctp_scope_t scope;
__u8 *raw_addr_list;
headersize = sizeof(sctp_chunkhdr_t) + SCTP_SECRET_SIZE; headersize = sizeof(sctp_chunkhdr_t) + SCTP_SECRET_SIZE;
bodysize = ntohs(chunk->chunk_hdr->length) - headersize; bodysize = ntohs(chunk->chunk_hdr->length) - headersize;
...@@ -1388,9 +1359,6 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep, ...@@ -1388,9 +1359,6 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
/* Process the cookie. */ /* Process the cookie. */
cookie = chunk->subh.cookie_hdr; cookie = chunk->subh.cookie_hdr;
bear_cookie = &cookie->c; bear_cookie = &cookie->c;
var_size1 = ntohs(chunk->chunk_hdr->length) - fixed_size;
var_size2 = ntohs(bear_cookie->peer_init->chunk_hdr.length);
var_size3 = bear_cookie->raw_addr_list_len;
/* Check the signature. */ /* Check the signature. */
secret = ep->current_key; secret = ep->current_key;
...@@ -1455,12 +1423,8 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep, ...@@ -1455,12 +1423,8 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
/* Populate the association from the cookie. */ /* Populate the association from the cookie. */
retval->c = *bear_cookie; retval->c = *bear_cookie;
/* Build the bind address list based on the cookie. */ if (sctp_assoc_set_bind_addr_from_cookie(retval, bear_cookie,
raw_addr_list = (__u8 *) bear_cookie + GFP_ATOMIC) < 0) {
sizeof(sctp_cookie_t) + var_size2;
if (sctp_raw_to_bind_addrs(&retval->base.bind_addr, raw_addr_list,
var_size3, retval->base.bind_addr.port,
priority)) {
*error = -SCTP_IERROR_NOMEM; *error = -SCTP_IERROR_NOMEM;
goto fail; goto fail;
} }
......
...@@ -75,8 +75,6 @@ static void sctp_cmd_hb_timers_start(sctp_cmd_seq_t *, sctp_association_t *); ...@@ -75,8 +75,6 @@ static void sctp_cmd_hb_timers_start(sctp_cmd_seq_t *, sctp_association_t *);
static void sctp_cmd_hb_timers_stop(sctp_cmd_seq_t *, sctp_association_t *); static void sctp_cmd_hb_timers_stop(sctp_cmd_seq_t *, sctp_association_t *);
static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *, sctp_association_t *, static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *, sctp_association_t *,
struct sctp_transport *); struct sctp_transport *);
static void sctp_cmd_set_bind_addrs(sctp_cmd_seq_t *, sctp_association_t *,
sctp_bind_addr_t *);
static void sctp_cmd_transport_reset(sctp_cmd_seq_t *, sctp_association_t *, static void sctp_cmd_transport_reset(sctp_cmd_seq_t *, sctp_association_t *,
struct sctp_transport *); struct sctp_transport *);
static void sctp_cmd_transport_on(sctp_cmd_seq_t *, sctp_association_t *, static void sctp_cmd_transport_on(sctp_cmd_seq_t *, sctp_association_t *,
...@@ -546,11 +544,6 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype, ...@@ -546,11 +544,6 @@ int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
SCTP_DEBUG_PRINTK("vtag mismatch!\n"); SCTP_DEBUG_PRINTK("vtag mismatch!\n");
break; break;
case SCTP_CMD_SET_BIND_ADDR:
sctp_cmd_set_bind_addrs(commands, asoc,
command->obj.bp);
break;
case SCTP_CMD_STRIKE: case SCTP_CMD_STRIKE:
/* Mark one strike against a transport. */ /* Mark one strike against a transport. */
sctp_do_8_2_transport_strike(asoc, sctp_do_8_2_transport_strike(asoc,
...@@ -1160,23 +1153,6 @@ static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *cmds, ...@@ -1160,23 +1153,6 @@ static void sctp_cmd_hb_timer_update(sctp_cmd_seq_t *cmds,
sctp_transport_hold(t); sctp_transport_hold(t);
} }
/* Helper function to break out SCTP_CMD_SET_BIND_ADDR handling. */
void sctp_cmd_set_bind_addrs(sctp_cmd_seq_t *cmds, sctp_association_t *asoc,
sctp_bind_addr_t *bp)
{
struct list_head *pos, *temp;
list_for_each_safe(pos, temp, &bp->address_list) {
list_del_init(pos);
list_add_tail(pos, &asoc->base.bind_addr.address_list);
}
/* Free the temporary bind addr header, otherwise
* there will a memory leak.
*/
sctp_bind_addr_free(bp);
}
/* Helper function to handle the reception of an HEARTBEAT ACK. */ /* Helper function to handle the reception of an HEARTBEAT ACK. */
static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
sctp_association_t *asoc, sctp_association_t *asoc,
......
...@@ -262,6 +262,9 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const sctp_endpoint_t *ep, ...@@ -262,6 +262,9 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const sctp_endpoint_t *ep,
len = ntohs(err_chunk->chunk_hdr->length) - len = ntohs(err_chunk->chunk_hdr->length) -
sizeof(sctp_chunkhdr_t); sizeof(sctp_chunkhdr_t);
if (sctp_assoc_set_bind_addr_from_ep(new_asoc, GFP_ATOMIC) < 0)
goto nomem_ack;
repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len); repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len);
if (!repl) if (!repl)
goto nomem_ack; goto nomem_ack;
...@@ -1181,6 +1184,10 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( ...@@ -1181,6 +1184,10 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
len = ntohs(err_chunk->chunk_hdr->length) - len = ntohs(err_chunk->chunk_hdr->length) -
sizeof(sctp_chunkhdr_t); sizeof(sctp_chunkhdr_t);
} }
if (sctp_assoc_set_bind_addr_from_ep(new_asoc, GFP_ATOMIC) < 0)
goto nomem;
repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len); repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len);
if (!repl) if (!repl)
goto nomem; goto nomem;
...@@ -3234,10 +3241,6 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const sctp_endpoint_t *ep, ...@@ -3234,10 +3241,6 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const sctp_endpoint_t *ep,
sctp_cmd_seq_t *commands) sctp_cmd_seq_t *commands)
{ {
sctp_chunk_t *repl; sctp_chunk_t *repl;
sctp_bind_addr_t *bp;
sctp_scope_t scope;
int error;
int flags;
/* The comment below says that we enter COOKIE-WAIT AFTER /* The comment below says that we enter COOKIE-WAIT AFTER
* sending the INIT, but that doesn't actually work in our * sending the INIT, but that doesn't actually work in our
...@@ -3246,35 +3249,6 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const sctp_endpoint_t *ep, ...@@ -3246,35 +3249,6 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const sctp_endpoint_t *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_COOKIE_WAIT)); SCTP_STATE(SCTP_STATE_COOKIE_WAIT));
/* Build up the bind address list for the association based on
* info from the local endpoint and the remote peer.
*/
bp = sctp_bind_addr_new(GFP_ATOMIC);
if (!bp)
goto nomem;
/* Use scoping rules to determine the subset of addresses from
* the endpoint.
*/
scope = sctp_scope(&asoc->peer.active_path->ipaddr);
flags = (PF_INET6 == asoc->base.sk->family) ? SCTP_ADDR6_ALLOWED : 0;
if (asoc->peer.ipv4_address)
flags |= SCTP_ADDR4_PEERSUPP;
if (asoc->peer.ipv6_address)
flags |= SCTP_ADDR6_PEERSUPP;
error = sctp_bind_addr_copy(bp, &ep->base.bind_addr, scope,
GFP_ATOMIC, flags);
if (error)
goto nomem;
/* FIXME: Either move address assignment out of this function
* or else move the association allocation/init into this function.
* The association structure is brand new before calling this
* function, so would not be a sideeffect if the allocation
* moved into this function. --jgrimm
*/
sctp_add_cmd_sf(commands, SCTP_CMD_SET_BIND_ADDR, (sctp_arg_t) bp);
/* RFC 2960 5.1 Normal Establishment of an Association /* RFC 2960 5.1 Normal Establishment of an Association
* *
* A) "A" first sends an INIT chunk to "Z". In the INIT, "A" * A) "A" first sends an INIT chunk to "Z". In the INIT, "A"
...@@ -3283,7 +3257,7 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const sctp_endpoint_t *ep, ...@@ -3283,7 +3257,7 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const sctp_endpoint_t *ep,
* 1 to 4294967295 (see 5.3.1 for Tag value selection). ... * 1 to 4294967295 (see 5.3.1 for Tag value selection). ...
*/ */
repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); repl = sctp_make_init(asoc, &asoc->base.bind_addr, GFP_ATOMIC, 0);
if (!repl) if (!repl)
goto nomem; goto nomem;
...@@ -3302,9 +3276,6 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const sctp_endpoint_t *ep, ...@@ -3302,9 +3276,6 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const sctp_endpoint_t *ep,
return SCTP_DISPOSITION_CONSUME; return SCTP_DISPOSITION_CONSUME;
nomem: nomem:
if (bp)
sctp_bind_addr_free(bp);
return SCTP_DISPOSITION_NOMEM; return SCTP_DISPOSITION_NOMEM;
} }
......
...@@ -924,6 +924,15 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, ...@@ -924,6 +924,15 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
/* Prime the peer's transport structures. */ /* Prime the peer's transport structures. */
transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL); transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL);
if (!transport) {
err = -ENOMEM;
goto out_free;
}
err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
if (err < 0) {
err = -ENOMEM;
goto out_free;
}
} }
/* ASSERT: we have a valid association at this point. */ /* ASSERT: we have a valid association at this point. */
...@@ -1513,6 +1522,15 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr, ...@@ -1513,6 +1522,15 @@ SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
/* Prime the peer's transport structures. */ /* Prime the peer's transport structures. */
transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL); transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL);
if (!transport) {
sctp_association_free(asoc);
goto out_unlock;
}
err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
if (err < 0) {
sctp_association_free(asoc);
goto out_unlock;
}
err = sctp_primitive_ASSOCIATE(asoc, NULL); err = sctp_primitive_ASSOCIATE(asoc, NULL);
if (err < 0) { if (err < 0) {
......
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