All pastes #676993 Raw Edit

Untitled

public text v1 · immutable
#676993 ·published 2007-08-31 16:02 UTC
rendered paste body
/* Build a cookie representing asoc.
 * This INCLUDES the param header needed to put the cookie in the INIT ACK.
 */
static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
                                      const struct sctp_association *asoc,
                                      const struct sctp_chunk *init_chunk,
                                      int *cookie_len,
                                      const __u8 *raw_addrs, int addrs_len)
{
        sctp_cookie_param_t *retval;
        struct sctp_signed_cookie *cookie;
        struct scatterlist sg;
        int headersize, bodysize;
        unsigned int keylen;
        char *key;

        headersize = sizeof(sctp_paramhdr_t) + SCTP_SECRET_SIZE;
        bodysize = sizeof(struct sctp_cookie)
                + ntohs(init_chunk->chunk_hdr->length) + addrs_len;

        /* Pad out the cookie to a multiple to make the signature
         * functions simpler to write.
         */
        if (bodysize % SCTP_COOKIE_MULTIPLE)
                bodysize += SCTP_COOKIE_MULTIPLE
                        - (bodysize % SCTP_COOKIE_MULTIPLE);
        *cookie_len = headersize + bodysize;

        retval = (sctp_cookie_param_t *)kmalloc(*cookie_len, GFP_ATOMIC);

        if (!retval) {
                *cookie_len = 0;
                goto nodata;
        }

        /* Clear this memory since we are sending this data structure
         * out on the network.
         */
        memset(retval, 0x00, *cookie_len);
        cookie = (struct sctp_signed_cookie *) retval->body;

        /* Set up the parameter header.  */
        retval->p.type = SCTP_PARAM_STATE_COOKIE;
        retval->p.length = htons(*cookie_len);

        /* Copy the cookie part of the association itself.  */
        cookie->c = asoc->c;
        /* Save the raw address list length in the cookie. */
        cookie->c.raw_addr_list_len = addrs_len;

        /* 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;

        /* Set an expiration time for the cookie.  */
        do_gettimeofday(&cookie->c.expiration);
        TIMEVAL_ADD(asoc->cookie_life, cookie->c.expiration);

        /* Copy the peer's init packet.  */
        memcpy(&cookie->c.peer_init[0], init_chunk->chunk_hdr,
               ntohs(init_chunk->chunk_hdr->length));

        /* Copy the raw local address list of the association. */
        memcpy((__u8 *)&cookie->c.peer_init[0] +
               ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len);

        if (sctp_sk(ep->base.sk)->hmac) {
                /* 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];

                sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen,
                                 &sg, 1, cookie->signature);
        }

nodata:
        return retval;
}