]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/sctp/sm_make_chunk.c
[NETFILTER]: ipt annotations
[linux-2.6-omap-h63xx.git] / net / sctp / sm_make_chunk.c
index 2a8773691695243fe6b4901f4b3a7f3328b78665..7745bdea7817acab1709df3e454785822ac2933a 100644 (file)
@@ -806,38 +806,26 @@ no_mem:
 
 /* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error.  */
 struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc,
-                                  const struct sctp_chunk *chunk,
-                                  const struct msghdr *msg)
+                                       const struct msghdr *msg,
+                                       size_t paylen)
 {
        struct sctp_chunk *retval;
-       void *payload = NULL, *payoff;
-       size_t paylen = 0;
-       struct iovec *iov = NULL;
-       int iovlen = 0;
-
-       if (msg) {
-               iov = msg->msg_iov;
-               iovlen = msg->msg_iovlen;
-               paylen = get_user_iov_size(iov, iovlen);
-       }
+       void *payload = NULL;
+       int err;
 
-       retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen);
+       retval = sctp_make_abort(asoc, NULL, sizeof(sctp_errhdr_t) + paylen);
        if (!retval)
                goto err_chunk;
 
        if (paylen) {
                /* Put the msg_iov together into payload.  */
-               payload = kmalloc(paylen, GFP_ATOMIC);
+               payload = kmalloc(paylen, GFP_KERNEL);
                if (!payload)
                        goto err_payload;
-               payoff = payload;
 
-               for (; iovlen > 0; --iovlen) {
-                       if (copy_from_user(payoff, iov->iov_base,iov->iov_len))
-                               goto err_copy;
-                       payoff += iov->iov_len;
-                       iov++;
-               }
+               err = memcpy_fromiovec(payload, msg->msg_iov, paylen);
+               if (err < 0)
+                       goto err_copy;
        }
 
        sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen);
@@ -1294,10 +1282,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.
@@ -1333,19 +1319,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.  */
@@ -1366,6 +1362,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.
@@ -1401,17 +1398,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! */
@@ -1493,7 +1498,7 @@ 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,
+               sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, 1,
                                   GFP_ATOMIC);
        }
 
@@ -2017,7 +2022,7 @@ static int sctp_process_param(struct sctp_association *asoc,
                af->from_addr_param(&addr, param.addr, asoc->peer.port, 0);
                scope = sctp_scope(peer_addr);
                if (sctp_in_scope(&addr, scope))
-                       if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE))
+                       if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED))
                                return 0;
                break;
 
@@ -2418,7 +2423,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_ACTIVE);
+               peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_UNCONFIRMED);
                if (!peer)
                        return SCTP_ERROR_RSRC_LOW;
 
@@ -2565,6 +2570,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
        union sctp_addr_param *addr_param;
        struct list_head *pos;
        struct sctp_transport *transport;
+       struct sctp_sockaddr_entry *saddr;
        int retval = 0;
 
        addr_param = (union sctp_addr_param *)
@@ -2578,7 +2584,11 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
        case SCTP_PARAM_ADD_IP:
                sctp_local_bh_disable();
                sctp_write_lock(&asoc->base.addr_lock);
-               retval = sctp_add_bind_addr(bp, &addr, GFP_ATOMIC);
+               list_for_each(pos, &bp->address_list) {
+                       saddr = list_entry(pos, struct sctp_sockaddr_entry, list);
+                       if (sctp_cmp_addr_exact(&saddr->a, &addr))
+                               saddr->use_as_src = 1;
+               }
                sctp_write_unlock(&asoc->base.addr_lock);
                sctp_local_bh_enable();
                break;
@@ -2591,6 +2601,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
                list_for_each(pos, &asoc->peer.transport_addr_list) {
                        transport = list_entry(pos, struct sctp_transport,
                                                 transports);
+                       dst_release(transport->dst);
                        sctp_transport_route(transport, NULL,
                                             sctp_sk(asoc->base.sk));
                }