[SCTP]: Switch sctp_add_bind_addr() to net-endian.
[powerpc.git] / net / sctp / sm_make_chunk.c
index 17b5092..46cfcca 100644 (file)
@@ -111,7 +111,7 @@ static const struct sctp_paramhdr prsctp_param = {
  * provided chunk, as most cause codes will be embedded inside an
  * abort chunk.
  */
-void  sctp_init_cause(struct sctp_chunk *chunk, __u16 cause_code,
+void  sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
                      const void *payload, size_t paylen)
 {
        sctp_errhdr_t err;
@@ -951,7 +951,7 @@ nodata:
 /* 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;
@@ -1032,7 +1032,8 @@ void sctp_init_addrs(struct sctp_chunk *chunk, union sctp_addr *src,
                     union sctp_addr *dest)
 {
        memcpy(&chunk->source, src, sizeof(union sctp_addr));
-       memcpy(&chunk->dest, dest, sizeof(union sctp_addr));
+       flip_to_h(&chunk->source_h, &chunk->source);
+       flip_to_h(&chunk->dest, dest);
 }
 
 /* Extract the source address from a chunk.  */
@@ -1040,10 +1041,10 @@ const union sctp_addr *sctp_source(const struct sctp_chunk *chunk)
 {
        /* If we have a known transport, use that.  */
        if (chunk->transport) {
-               return &chunk->transport->ipaddr;
+               return &chunk->transport->ipaddr_h;
        } else {
                /* Otherwise, extract it from the IP header.  */
-               return &chunk->source;
+               return &chunk->source_h;
        }
 }
 
@@ -1190,7 +1191,7 @@ void sctp_chunk_assign_ssn(struct sctp_chunk *chunk)
        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
@@ -1282,10 +1283,8 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
 
        retval = kmalloc(*cookie_len, GFP_ATOMIC);
 
-       if (!retval) {
-               *cookie_len = 0;
+       if (!retval)
                goto nodata;
-       }
 
        /* Clear this memory since we are sending this data structure
         * out on the network.
@@ -1321,19 +1320,29 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
               ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len);
 
        if (sctp_sk(ep->base.sk)->hmac) {
+               struct hash_desc desc;
+
                /* Sign the message.  */
                sg.page = virt_to_page(&cookie->c);
                sg.offset = (unsigned long)(&cookie->c) % PAGE_SIZE;
                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;
 
-               sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen,
-                                &sg, 1, cookie->signature);
+               if (crypto_hash_setkey(desc.tfm, key, keylen) ||
+                   crypto_hash_digest(&desc, &sg, bodysize, cookie->signature))
+                       goto free_cookie;
        }
 
-nodata:
        return retval;
+
+free_cookie:
+       kfree(retval);
+nodata:
+       *cookie_len = 0;
+       return NULL;
 }
 
 /* Unpack the cookie from COOKIE ECHO chunk, recreating the association.  */
@@ -1354,6 +1363,7 @@ struct sctp_association *sctp_unpack_cookie(
        sctp_scope_t scope;
        struct sk_buff *skb = chunk->skb;
        struct timeval tv;
+       struct hash_desc desc;
 
        /* Header size is static data prior to the actual cookie, including
         * any padding.
@@ -1389,17 +1399,25 @@ struct sctp_association *sctp_unpack_cookie(
        sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE;
        sg.length = bodysize;
        key = (char *)ep->secret_key[ep->current_key];
+       desc.tfm = sctp_sk(ep->base.sk)->hmac;
+       desc.flags = 0;
 
        memset(digest, 0x00, SCTP_SIGNATURE_SIZE);
-       sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg,
-                        1, digest);
+       if (crypto_hash_setkey(desc.tfm, key, keylen) ||
+           crypto_hash_digest(&desc, &sg, bodysize, digest)) {
+               *error = -SCTP_IERROR_NOMEM;
+               goto fail;
+       }
 
        if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {
                /* Try the previous key. */
                key = (char *)ep->secret_key[ep->last_key];
                memset(digest, 0x00, SCTP_SIGNATURE_SIZE);
-               sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen,
-                                &sg, 1, digest);
+               if (crypto_hash_setkey(desc.tfm, key, keylen) ||
+                   crypto_hash_digest(&desc, &sg, bodysize, digest)) {
+                       *error = -SCTP_IERROR_NOMEM;
+                       goto fail;
+               }
 
                if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {
                        /* Yikes!  Still bad signature! */
@@ -1421,7 +1439,7 @@ no_hmac:
                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;
@@ -1430,8 +1448,16 @@ no_hmac:
        /* Check to see if the cookie is stale.  If there is already
         * an association, there is no need to check cookie's expiration
         * for init collision case of lost COOKIE ACK.
+        * If skb has been timestamped, then use the stamp, otherwise
+        * use current time.  This introduces a small possibility that
+        * that a cookie may be considered expired, but his would only slow
+        * down the new association establishment instead of every packet.
         */
-       skb_get_timestamp(skb, &tv);
+       if (sock_flag(ep->base.sk, SOCK_TIMESTAMP))
+               skb_get_timestamp(skb, &tv);
+       else
+               do_gettimeofday(&tv);
+
        if (!asoc && tv_lt(bear_cookie->expiration, tv)) {
                __u16 len;
                /*
@@ -1481,7 +1507,9 @@ no_hmac:
 
        /* Also, add the destination address. */
        if (list_empty(&retval->base.bind_addr.address_list)) {
-               sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, 1,
+               union sctp_addr tmp;
+               flip_to_n(&tmp, &chunk->dest);
+               sctp_add_bind_addr(&retval->base.bind_addr, &tmp, 1,
                                   GFP_ATOMIC);
        }
 
@@ -1816,6 +1844,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
        struct sctp_transport *transport;
        struct list_head *pos, *temp;
        char *cookie;
+       union sctp_addr tmp;
 
        /* We must include the address that the INIT packet came from.
         * This is the only address that matters for an INIT packet.
@@ -1827,9 +1856,11 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
         * 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(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE))
+       if (peer_addr) {
+               flip_to_n(&tmp, peer_addr);
+               if(!sctp_assoc_add_peer(asoc, &tmp, gfp, SCTP_ACTIVE))
                        goto nomem;
+       }
 
        /* Process the initialization parameters.  */
 
@@ -1990,6 +2021,7 @@ static int sctp_process_param(struct sctp_association *asoc,
        sctp_scope_t scope;
        time_t stale;
        struct sctp_af *af;
+       union sctp_addr tmp;
 
        /* We maintain all INIT parameters in network byte order all the
         * time.  This allows us to not worry about whether the parameters
@@ -2003,9 +2035,10 @@ static int sctp_process_param(struct sctp_association *asoc,
        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);
+               flip_to_n(&tmp, &addr);
                scope = sctp_scope(peer_addr);
-               if (sctp_in_scope(&addr, scope))
-                       if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED))
+               if (sctp_in_scope(&tmp, scope))
+                       if (!sctp_assoc_add_peer(asoc, &tmp, gfp, SCTP_UNCONFIRMED))
                                return 0;
                break;
 
@@ -2205,7 +2238,7 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
                                              union sctp_addr         *laddr,
                                              struct sockaddr         *addrs,
                                              int                     addrcnt,
-                                             __u16                   flags)
+                                             __be16                  flags)
 {
        sctp_addip_param_t      param;
        struct sctp_chunk       *retval;
@@ -2339,13 +2372,13 @@ static struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *as
 
 /* 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)
+                             __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;
@@ -2379,7 +2412,7 @@ static void sctp_add_asconf_response(struct sctp_chunk *chunk, __u32 crr_id,
 }
 
 /* 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)
 {
@@ -2388,7 +2421,8 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
        union sctp_addr addr;
        struct list_head *pos;
        union sctp_addr_param *addr_param;
-                                
+       union sctp_addr tmp, tmp_addr;
+
        addr_param = (union sctp_addr_param *)
                        ((void *)asconf_param + sizeof(sctp_addip_param_t));
 
@@ -2397,6 +2431,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
                return SCTP_ERROR_INV_PARAM;
 
        af->from_addr_param(&addr, addr_param, asoc->peer.port, 0);
+       flip_to_n(&tmp_addr, &addr);
        switch (asconf_param->param_hdr.type) {
        case SCTP_PARAM_ADD_IP:
                /* ADDIP 4.3 D9) If an endpoint receives an ADD IP address
@@ -2406,7 +2441,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
                 * Due to Resource Shortage'.
                 */
 
-               peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_UNCONFIRMED);
+               peer = sctp_assoc_add_peer(asoc, &tmp_addr, GFP_ATOMIC, SCTP_UNCONFIRMED);
                if (!peer)
                        return SCTP_ERROR_RSRC_LOW;
 
@@ -2431,13 +2466,14 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
                 * an Error Cause TLV set to the new error code 'Request to
                 * Delete Source IP Address'
                 */
-               if (sctp_cmp_addr_exact(sctp_source(asconf), &addr))
+               flip_to_n(&tmp, sctp_source(asconf));
+               if (sctp_cmp_addr_exact(&tmp, &tmp_addr))
                        return SCTP_ERROR_DEL_SRC_IP;
 
-               sctp_assoc_del_peer(asoc, &addr);
+               sctp_assoc_del_peer(asoc, &tmp_addr);
                break;
        case SCTP_PARAM_SET_PRIMARY:
-               peer = sctp_assoc_lookup_paddr(asoc, &addr);
+               peer = sctp_assoc_lookup_paddr(asoc, &tmp_addr);
                if (!peer)
                        return SCTP_ERROR_INV_PARAM;
 
@@ -2462,7 +2498,7 @@ 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;
@@ -2555,6 +2591,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
        struct sctp_transport *transport;
        struct sctp_sockaddr_entry *saddr;
        int retval = 0;
+       union sctp_addr tmp;
 
        addr_param = (union sctp_addr_param *)
                        ((void *)asconf_param + sizeof(sctp_addip_param_t));
@@ -2562,6 +2599,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
        /* 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);
+       flip_to_n(&tmp, &addr);
 
        switch (asconf_param->param_hdr.type) {
        case SCTP_PARAM_ADD_IP:
@@ -2569,7 +2607,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
                sctp_write_lock(&asoc->base.addr_lock);
                list_for_each(pos, &bp->address_list) {
                        saddr = list_entry(pos, struct sctp_sockaddr_entry, list);
-                       if (sctp_cmp_addr_exact(&saddr->a, &addr))
+                       if (sctp_cmp_addr_exact(&saddr->a, &tmp))
                                saddr->use_as_src = 1;
                }
                sctp_write_unlock(&asoc->base.addr_lock);
@@ -2578,7 +2616,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
        case SCTP_PARAM_DEL_IP:
                sctp_local_bh_disable();
                sctp_write_lock(&asoc->base.addr_lock);
-               retval = sctp_del_bind_addr(bp, &addr);
+               retval = sctp_del_bind_addr(bp, &tmp);
                sctp_write_unlock(&asoc->base.addr_lock);
                sctp_local_bh_enable();
                list_for_each(pos, &asoc->peer.transport_addr_list) {
@@ -2605,7 +2643,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
  * 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)
 {
@@ -2613,7 +2651,7 @@ static __u16 sctp_get_asconf_response(struct sctp_chunk *asconf_ack,
        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;
@@ -2669,7 +2707,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
        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.