#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
-extern kmem_cache_t *sctp_chunk_cachep;
+extern struct kmem_cache *sctp_chunk_cachep;
SCTP_STATIC
struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
int padlen;
__u16 len;
- /* Cause code constants are now defined in network order. */
+ /* Cause code constants are now defined in network order. */
err.cause = cause_code;
len = sizeof(sctp_errhdr_t) + paylen;
padlen = len % 4;
err.length = htons(len);
len += padlen;
- sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
- chunk->subh.err_hdr = sctp_addto_chunk(chunk, paylen, payload);
+ chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
+ sctp_addto_chunk(chunk, paylen, payload);
}
/* 3.3.2 Initiation (INIT) (1)
int num_types, addrs_len = 0;
struct sctp_sock *sp;
sctp_supported_addrs_param_t sat;
- __u16 types[2];
- sctp_adaption_ind_param_t aiparam;
+ __be16 types[2];
+ sctp_adaptation_ind_param_t aiparam;
/* RFC 2960 3.3.2 Initiation (INIT) (1)
*
sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);
if (sctp_prsctp_enable)
sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);
- aiparam.param_hdr.type = SCTP_PARAM_ADAPTION_LAYER_IND;
+ aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND;
aiparam.param_hdr.length = htons(sizeof(aiparam));
- aiparam.adaption_ind = htonl(sp->adaption_ind);
+ aiparam.adaptation_ind = htonl(sp->adaptation_ind);
sctp_addto_chunk(retval, sizeof(aiparam), &aiparam);
nodata:
kfree(addrs.v);
sctp_cookie_param_t *cookie;
int cookie_len;
size_t chunksize;
- sctp_adaption_ind_param_t aiparam;
+ sctp_adaptation_ind_param_t aiparam;
retval = NULL;
*/
chunksize = sizeof(initack) + addrs_len + cookie_len + unkparam_len;
- /* Tell peer that we'll do ECN only if peer advertised such cap. */
+ /* Tell peer that we'll do ECN only if peer advertised such cap. */
if (asoc->peer.ecn_capable)
chunksize += sizeof(ecap_param);
- /* Tell peer that we'll do PR-SCTP only if peer advertised. */
+ /* Tell peer that we'll do PR-SCTP only if peer advertised. */
if (asoc->peer.prsctp_capable)
chunksize += sizeof(prsctp_param);
if (asoc->peer.prsctp_capable)
sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);
- aiparam.param_hdr.type = SCTP_PARAM_ADAPTION_LAYER_IND;
+ aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND;
aiparam.param_hdr.length = htons(sizeof(aiparam));
- aiparam.adaption_ind = htonl(sctp_sk(asoc->base.sk)->adaption_ind);
+ aiparam.adaptation_ind = htonl(sctp_sk(asoc->base.sk)->adaptation_ind);
sctp_addto_chunk(retval, sizeof(aiparam), &aiparam);
/* We need to remove the const qualifier at this point. */
if (retval && chunk)
retval->transport = chunk->transport;
- return retval;
+ return retval;
}
/* Create an ABORT. Note that we set the T bit if we have no
const struct sctp_chunk *chunk, __u32 tsn)
{
struct sctp_chunk *retval;
- __u32 payload;
+ __be32 payload;
retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t)
+ sizeof(tsn));
return retval;
}
-/* Make an ABORT chunk with a PROTOCOL VIOLATION cause code. */
+/* Make an ABORT chunk with a PROTOCOL VIOLATION cause code. */
struct sctp_chunk *sctp_make_abort_violation(
const struct sctp_association *asoc,
const struct sctp_chunk *chunk,
/* Create an Operation Error chunk. */
struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
const struct sctp_chunk *chunk,
- __u16 cause_code, const void *payload,
+ __be16 cause_code, const void *payload,
size_t paylen)
{
struct sctp_chunk *retval;
{
struct sctp_chunk *retval;
- retval = kmem_cache_alloc(sctp_chunk_cachep, SLAB_ATOMIC);
+ retval = kmem_cache_zalloc(sctp_chunk_cachep, GFP_ATOMIC);
if (!retval)
goto nodata;
- memset(retval, 0, sizeof(struct sctp_chunk));
if (!sk) {
SCTP_DEBUG_PRINTK("chunkifying skb %p w/o an sk\n", skb);
if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
ssn = 0;
} else {
- sid = htons(chunk->subh.data_hdr->stream);
+ sid = ntohs(chunk->subh.data_hdr->stream);
if (chunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
ssn = sctp_ssn_next(&chunk->asoc->ssnmap->out, sid);
else
ssn = sctp_ssn_peek(&chunk->asoc->ssnmap->out, sid);
- ssn = htons(ssn);
}
- chunk->subh.data_hdr->ssn = ssn;
+ chunk->subh.data_hdr->ssn = htons(ssn);
chunk->has_ssn = 1;
}
/* Header size is static data prior to the actual cookie, including
* any padding.
*/
- headersize = sizeof(sctp_paramhdr_t) +
- (sizeof(struct sctp_signed_cookie) -
+ headersize = sizeof(sctp_paramhdr_t) +
+ (sizeof(struct sctp_signed_cookie) -
sizeof(struct sctp_cookie));
bodysize = sizeof(struct sctp_cookie)
+ ntohs(init_chunk->chunk_hdr->length) + addrs_len;
- (bodysize % SCTP_COOKIE_MULTIPLE);
*cookie_len = headersize + bodysize;
- retval = kmalloc(*cookie_len, GFP_ATOMIC);
-
- if (!retval)
- goto nodata;
-
/* Clear this memory since we are sending this data structure
* out on the network.
*/
- memset(retval, 0x00, *cookie_len);
+ retval = kzalloc(*cookie_len, GFP_ATOMIC);
+ if (!retval)
+ goto nodata;
+
cookie = (struct sctp_signed_cookie *) retval->body;
/* Set up the parameter header. */
/* Remember PR-SCTP capability. */
cookie->c.prsctp_capable = asoc->peer.prsctp_capable;
- /* Save adaption indication in the cookie. */
- cookie->c.adaption_ind = asoc->peer.adaption_ind;
+ /* Save adaptation indication in the cookie. */
+ cookie->c.adaptation_ind = asoc->peer.adaptation_ind;
/* Set an expiration time for the cookie. */
do_gettimeofday(&cookie->c.expiration);
memcpy((__u8 *)&cookie->c.peer_init[0] +
ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len);
- if (sctp_sk(ep->base.sk)->hmac) {
+ if (sctp_sk(ep->base.sk)->hmac) {
struct hash_desc desc;
/* Sign the message. */
sg.length = bodysize;
keylen = SCTP_SECRET_SIZE;
key = (char *)ep->secret_key[ep->current_key];
- desc.tfm = sctp_sk(ep->base.sk)->hmac;
- desc.flags = 0;
+ desc.tfm = sctp_sk(ep->base.sk)->hmac;
+ desc.flags = 0;
if (crypto_hash_setkey(desc.tfm, key, keylen) ||
crypto_hash_digest(&desc, &sg, bodysize, cookie->signature))
* any padding.
*/
headersize = sizeof(sctp_chunkhdr_t) +
- (sizeof(struct sctp_signed_cookie) -
+ (sizeof(struct sctp_signed_cookie) -
sizeof(struct sctp_cookie));
bodysize = ntohs(chunk->chunk_hdr->length) - headersize;
fixed_size = headersize + sizeof(struct sctp_cookie);
goto fail;
}
- if (ntohs(chunk->sctp_hdr->source) != bear_cookie->peer_addr.v4.sin_port ||
+ if (chunk->sctp_hdr->source != bear_cookie->peer_addr.v4.sin_port ||
ntohs(chunk->sctp_hdr->dest) != bear_cookie->my_port) {
*error = -SCTP_IERROR_BAD_PORTS;
goto fail;
suseconds_t usecs = (tv.tv_sec -
bear_cookie->expiration.tv_sec) * 1000000L +
tv.tv_usec - bear_cookie->expiration.tv_usec;
+ __be32 n = htonl(usecs);
- usecs = htonl(usecs);
sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,
- &usecs, sizeof(usecs));
+ &n, sizeof(n));
*error = -SCTP_IERROR_STALE_COOKIE;
} else
*error = -SCTP_IERROR_NOMEM;
retval->addip_serial = retval->c.initial_tsn;
retval->adv_peer_ack_point = retval->ctsn_ack_point;
retval->peer.prsctp_capable = retval->c.prsctp_capable;
- retval->peer.adaption_ind = retval->c.adaption_ind;
+ retval->peer.adaptation_ind = retval->c.adaptation_ind;
/* The INIT stuff will be done by the side effects. */
return retval;
********************************************************************/
struct __sctp_missing {
- __u32 num_missing;
- __u16 type;
+ __be32 num_missing;
+ __be16 type;
} __attribute__((packed));
/*
if (*errp) {
report.num_missing = htonl(1);
report.type = paramtype;
- sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM,
+ sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM,
&report, sizeof(report));
}
struct sctp_chunk **errp)
{
char error[] = "The following parameter had invalid length:";
- size_t payload_len = WORD_ROUND(sizeof(error)) +
+ size_t payload_len = WORD_ROUND(sizeof(error)) +
sizeof(sctp_paramhdr_t);
case SCTP_PARAM_HEARTBEAT_INFO:
case SCTP_PARAM_UNRECOGNIZED_PARAMETERS:
case SCTP_PARAM_ECN_CAPABLE:
- case SCTP_PARAM_ADAPTION_LAYER_IND:
+ case SCTP_PARAM_ADAPTATION_LAYER_IND:
break;
case SCTP_PARAM_HOST_NAME_ADDRESS:
case SCTP_PARAM_FWD_TSN_SUPPORT:
if (sctp_prsctp_enable)
break;
- /* Fall Through */
+ /* Fall Through */
default:
SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n",
ntohs(param.p->type), cid);
/* Verify stream values are non-zero. */
if ((0 == peer_init->init_hdr.num_outbound_streams) ||
- (0 == peer_init->init_hdr.num_inbound_streams)) {
+ (0 == peer_init->init_hdr.num_inbound_streams) ||
+ (0 == peer_init->init_hdr.init_tag) ||
+ (SCTP_DEFAULT_MINWINDOW > ntohl(peer_init->init_hdr.a_rwnd))) {
sctp_process_inv_mandatory(asoc, chunk, errp);
return 0;
* added as the primary transport. The source address seems to
* be a a better choice than any of the embedded addresses.
*/
- if (peer_addr)
+ if (peer_addr) {
if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE))
goto nomem;
+ }
/* Process the initialization parameters. */
sctp_walk_params(param, peer_init, init_hdr.params) {
if (!sctp_process_param(asoc, param, peer_addr, gfp))
- goto clean_up;
+ goto clean_up;
}
/* Walk list of transports, removing transports in the UNKNOWN state. */
/* Copy cookie in case we need to resend COOKIE-ECHO. */
cookie = asoc->peer.cookie;
if (cookie) {
- asoc->peer.cookie = kmalloc(asoc->peer.cookie_len, gfp);
+ asoc->peer.cookie = kmemdup(cookie, asoc->peer.cookie_len, gfp);
if (!asoc->peer.cookie)
goto clean_up;
- memcpy(asoc->peer.cookie, cookie, asoc->peer.cookie_len);
}
/* RFC 2960 7.2.1 The initial value of ssthresh MAY be arbitrarily
*/
/* Allocate storage for the negotiated streams if it is not a temporary
- * association.
+ * association.
*/
if (!asoc->temp) {
int assoc_id;
/* Fall through. */
case SCTP_PARAM_IPV4_ADDRESS:
af = sctp_get_af_specific(param_type2af(param.p->type));
- af->from_addr_param(&addr, param.addr, asoc->peer.port, 0);
+ af->from_addr_param(&addr, param.addr, htons(asoc->peer.port), 0);
scope = sctp_scope(peer_addr);
if (sctp_in_scope(&addr, scope))
if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED))
asoc->peer.ecn_capable = 1;
break;
- case SCTP_PARAM_ADAPTION_LAYER_IND:
- asoc->peer.adaption_ind = param.aind->adaption_ind;
+ case SCTP_PARAM_ADAPTATION_LAYER_IND:
+ asoc->peer.adaptation_ind = param.aind->adaptation_ind;
break;
case SCTP_PARAM_FWD_TSN_SUPPORT:
asoc->peer.prsctp_capable = 1;
break;
}
- /* Fall Through */
+ /* Fall Through */
default:
/* Any unrecognized parameters should have been caught
* and handled by sctp_verify_param() which should be
* | ASCONF Parameter #N |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
- * Address Parameter and other parameter will not be wrapped in this function
+ * Address Parameter and other parameter will not be wrapped in this function
*/
static struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
union sctp_addr *addr,
union sctp_addr *laddr,
struct sockaddr *addrs,
int addrcnt,
- __u16 flags)
+ __be16 flags)
{
sctp_addip_param_t param;
struct sctp_chunk *retval;
* | Address Parameter |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
- * Create an ASCONF chunk with Set Primary IP address parameter.
+ * Create an ASCONF chunk with Set Primary IP address parameter.
*/
struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
union sctp_addr *addr)
* | ASCONF Parameter Response#N |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
- * Create an ASCONF_ACK chunk with enough space for the parameter responses.
+ * Create an ASCONF_ACK chunk with enough space for the parameter responses.
*/
static struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *asoc,
__u32 serial, int vparam_len)
}
/* Add response parameters to an ASCONF_ACK chunk. */
-static void sctp_add_asconf_response(struct sctp_chunk *chunk, __u32 crr_id,
- __u16 err_code, sctp_addip_param_t *asconf_param)
+static void sctp_add_asconf_response(struct sctp_chunk *chunk, __be32 crr_id,
+ __be16 err_code, sctp_addip_param_t *asconf_param)
{
sctp_addip_param_t ack_param;
sctp_errhdr_t err_param;
int asconf_param_len = 0;
int err_param_len = 0;
- __u16 response_type;
+ __be16 response_type;
if (SCTP_ERROR_NO_ERROR == err_code) {
response_type = SCTP_PARAM_SUCCESS_REPORT;
ntohs(asconf_param->param_hdr.length);
}
- /* Add Success Indication or Error Cause Indication parameter. */
+ /* Add Success Indication or Error Cause Indication parameter. */
ack_param.param_hdr.type = response_type;
ack_param.param_hdr.length = htons(sizeof(ack_param) +
err_param_len +
}
/* Process a asconf parameter. */
-static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
+static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
struct sctp_chunk *asconf,
sctp_addip_param_t *asconf_param)
{
union sctp_addr addr;
struct list_head *pos;
union sctp_addr_param *addr_param;
-
+
addr_param = (union sctp_addr_param *)
((void *)asconf_param + sizeof(sctp_addip_param_t));
if (unlikely(!af))
return SCTP_ERROR_INV_PARAM;
- af->from_addr_param(&addr, addr_param, asoc->peer.port, 0);
+ af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0);
switch (asconf_param->param_hdr.type) {
case SCTP_PARAM_ADD_IP:
/* ADDIP 4.3 D9) If an endpoint receives an ADD IP address
- * request and does not have the local resources to add this
- * new address to the association, it MUST return an Error
- * Cause TLV set to the new error code 'Operation Refused
- * Due to Resource Shortage'.
- */
+ * request and does not have the local resources to add this
+ * new address to the association, it MUST return an Error
+ * Cause TLV set to the new error code 'Operation Refused
+ * Due to Resource Shortage'.
+ */
peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_UNCONFIRMED);
if (!peer)
break;
case SCTP_PARAM_DEL_IP:
/* ADDIP 4.3 D7) If a request is received to delete the
- * last remaining IP address of a peer endpoint, the receiver
- * MUST send an Error Cause TLV with the error cause set to the
- * new error code 'Request to Delete Last Remaining IP Address'.
- */
+ * last remaining IP address of a peer endpoint, the receiver
+ * MUST send an Error Cause TLV with the error cause set to the
+ * new error code 'Request to Delete Last Remaining IP Address'.
+ */
pos = asoc->peer.transport_addr_list.next;
if (pos->next == &asoc->peer.transport_addr_list)
return SCTP_ERROR_DEL_LAST_IP;
return SCTP_ERROR_NO_ERROR;
}
-/* Process an incoming ASCONF chunk with the next expected serial no. and
+/* Process an incoming ASCONF chunk with the next expected serial no. and
* return an ASCONF_ACK chunk to be sent in response.
*/
struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
sctp_addip_param_t *asconf_param;
struct sctp_chunk *asconf_ack;
- __u16 err_code;
+ __be16 err_code;
int length = 0;
int chunk_len = asconf->skb->len;
__u32 serial;
hdr = (sctp_addiphdr_t *)asconf->skb->data;
serial = ntohl(hdr->serial);
- /* Skip the addiphdr and store a pointer to address parameter. */
+ /* Skip the addiphdr and store a pointer to address parameter. */
length = sizeof(sctp_addiphdr_t);
addr_param = (union sctp_addr_param *)(asconf->skb->data + length);
chunk_len -= length;
/* Skip the address parameter and store a pointer to the first
* asconf paramter.
- */
+ */
length = ntohs(addr_param->v4.param_hdr.length);
asconf_param = (sctp_addip_param_t *)((void *)addr_param + length);
chunk_len -= length;
- /* create an ASCONF_ACK chunk.
+ /* create an ASCONF_ACK chunk.
* Based on the definitions of parameters, we know that the size of
* ASCONF_ACK parameters are less than or equal to the twice of ASCONF
* paramters.
/* ADDIP 4.3 D11) When an endpoint receiving an ASCONF to add
* an IP address sends an 'Out of Resource' in its response, it
* MUST also fail any subsequent add or delete requests bundled
- * in the ASCONF.
+ * in the ASCONF.
*/
if (SCTP_ERROR_RSRC_LOW == err_code)
goto done;
length);
chunk_len -= length;
}
-
+
done:
asoc->peer.addip_serial++;
/* If we are sending a new ASCONF_ACK hold a reference to it in assoc
- * after freeing the reference to old asconf ack if any.
+ * after freeing the reference to old asconf ack if any.
*/
if (asconf_ack) {
if (asoc->addip_last_asconf_ack)
/* We have checked the packet before, so we do not check again. */
af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type));
- af->from_addr_param(&addr, addr_param, bp->port, 0);
+ af->from_addr_param(&addr, addr_param, htons(bp->port), 0);
switch (asconf_param->param_hdr.type) {
case SCTP_PARAM_ADD_IP:
/* Get the corresponding ASCONF response error code from the ASCONF_ACK chunk
* for the given asconf parameter. If there is no response for this parameter,
- * return the error code based on the third argument 'no_err'.
+ * return the error code based on the third argument 'no_err'.
* ADDIP 4.1
* A7) If an error response is received for a TLV parameter, all TLVs with no
* response before the failed TLV are considered successful if not reported.
* All TLVs after the failed response are considered unsuccessful unless a
* specific success indication is present for the parameter.
*/
-static __u16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
+static __be16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
sctp_addip_param_t *asconf_param,
int no_err)
{
sctp_errhdr_t *err_param;
int length;
int asconf_ack_len = asconf_ack->skb->len;
- __u16 err_code;
+ __be16 err_code;
if (no_err)
err_code = SCTP_ERROR_NO_ERROR;
/* Skip the addiphdr from the asconf_ack chunk and store a pointer to
* the first asconf_ack parameter.
- */
+ */
length = sizeof(sctp_addiphdr_t);
asconf_ack_param = (sctp_addip_param_t *)(asconf_ack->skb->data +
length);
int all_param_pass = 0;
int no_err = 1;
int retval = 0;
- __u16 err_code = SCTP_ERROR_NO_ERROR;
+ __be16 err_code = SCTP_ERROR_NO_ERROR;
/* Skip the chunkhdr and addiphdr from the last asconf sent and store
* a pointer to address parameter.
- */
+ */
length = sizeof(sctp_addip_chunk_t);
addr_param = (union sctp_addr_param *)(asconf->skb->data + length);
asconf_len -= length;
/* Skip the address parameter in the last asconf sent and store a
* pointer to the first asconf paramter.
- */
+ */
length = ntohs(addr_param->v4.param_hdr.length);
asconf_param = (sctp_addip_param_t *)((void *)addr_param + length);
asconf_len -= length;
case SCTP_ERROR_INV_PARAM:
/* Disable sending this type of asconf parameter in
* future.
- */
+ */
asoc->peer.addip_disabled_mask |=
asconf_param->param_hdr.type;
break;
/* Skip the processed asconf parameter and move to the next
* one.
- */
+ */
length = ntohs(asconf_param->param_hdr.length);
asconf_param = (sctp_addip_param_t *)((void *)asconf_param +
length);
return retval;
}
-/* Make a FWD TSN chunk. */
+/* Make a FWD TSN chunk. */
struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
__u32 new_cum_tsn, size_t nstreams,
struct sctp_fwdtsn_skip *skiplist)
{
struct sctp_chunk *retval = NULL;
struct sctp_fwdtsn_chunk *ftsn_chunk;
- struct sctp_fwdtsn_hdr ftsn_hdr;
+ struct sctp_fwdtsn_hdr ftsn_hdr;
struct sctp_fwdtsn_skip skip;
size_t hint;
int i;