Receive packets directly into a buffer that can be retained in the send
queue, rather than a buffer contained in the instance (whence they must be
copied).

Signed-off-by: Zane Bitter <zane.bit...@gmail.com>
---
 exec/totemudp.c |  145 +++++++++++++++++++++++++++----------------------------
 1 files changed, 71 insertions(+), 74 deletions(-)

diff --git a/exec/totemudp.c b/exec/totemudp.c
index 42739d6..70cd5b6 100644
--- a/exec/totemudp.c
+++ b/exec/totemudp.c
@@ -170,12 +170,8 @@ struct totemudp_instance {
 
        void *udp_context;
 
-       char iov_buffer[FRAME_SIZE_MAX];
-
        char iov_buffer_flush[FRAME_SIZE_MAX];
 
-       struct iovec totemudp_iov_recv;
-
        struct iovec totemudp_iov_recv_flush;
 
        struct totemudp_socket totemudp_sockets;
@@ -232,9 +228,6 @@ static void totemudp_instance_initialize (struct 
totemudp_instance *instance)
 
        instance->netif_state_report = NETIF_STATE_REPORT_UP | 
NETIF_STATE_REPORT_DOWN;
 
-       instance->totemudp_iov_recv.iov_base = instance->iov_buffer;
-
-       instance->totemudp_iov_recv.iov_len = FRAME_SIZE_MAX; //sizeof 
(instance->iov_buffer);
        instance->totemudp_iov_recv_flush.iov_base = instance->iov_buffer_flush;
 
        instance->totemudp_iov_recv_flush.iov_len = FRAME_SIZE_MAX; //sizeof 
(instance->iov_buffer);
@@ -258,11 +251,11 @@ do {                                                      
                \
 
 static int authenticate_and_decrypt_sober (
        struct totemudp_instance *instance,
+       struct security_header *header,
        struct iovec *iov,
        unsigned int iov_len)
 {
        unsigned char keys[48];
-       struct security_header *header = (struct security_header 
*)iov[0].iov_base;
        prng_state keygen_prng_state;
        prng_state stream_prng_state;
        unsigned char *hmac_key = &keys[32];
@@ -271,6 +264,8 @@ static int authenticate_and_decrypt_sober (
        unsigned char digest_comparison[HMAC_HASH_SIZE];
        unsigned long len;
 
+       assert (iov_len == 1);
+
        /*
         * Generate MAC, CIPHER, IV keys from private key
         */
@@ -295,8 +290,9 @@ static int authenticate_and_decrypt_sober (
        hmac_init (&instance->totemudp_hmac_state, DIGEST_SHA1, hmac_key, 16);
 
        hmac_process (&instance->totemudp_hmac_state,
-               (unsigned char *)iov->iov_base + HMAC_HASH_SIZE,
-               iov->iov_len - HMAC_HASH_SIZE);
+               (unsigned char *)header + HMAC_HASH_SIZE,
+               sizeof (*header) - HMAC_HASH_SIZE);
+       hmac_process (&instance->totemudp_hmac_state, iov->iov_base, 
iov->iov_len);
 
        len = hash_descriptor[DIGEST_SHA1]->hashsize;
        assert (HMAC_HASH_SIZE >= len);
@@ -309,10 +305,7 @@ static int authenticate_and_decrypt_sober (
        /*
         * Decrypt the contents of the message with the cipher key
         */
-       sober128_read ((unsigned char*)iov->iov_base +
-                       sizeof (struct security_header),
-               iov->iov_len - sizeof (struct security_header),
-               &stream_prng_state);
+       sober128_read (iov->iov_base, iov->iov_len, &stream_prng_state);
 
        return (0);
 }
@@ -574,21 +567,19 @@ out:
 
 static int authenticate_and_decrypt_nss (
        struct totemudp_instance *instance,
+       struct security_header *header,
        struct iovec *iov,
        unsigned int iov_len)
 {
        PK11Context*  enc_context = NULL;
-       SECStatus     rv1, rv2;
+       SECStatus     rv;
        int           tmp1_outlen;
        unsigned int  tmp2_outlen;
        unsigned char outbuf[FRAME_SIZE_MAX];
        unsigned char digest[HMAC_HASH_SIZE];
-       unsigned char *outdata;
        int           result_len;
-       unsigned char *data;
        unsigned char *inbuf;
        size_t        datalen;
-       struct security_header *header = (struct security_header 
*)iov[0].iov_base;
        SECItem no_params;
        SECItem ivdata;
 
@@ -608,10 +599,6 @@ static int authenticate_and_decrypt_nss (
                inbuf = (unsigned char *)iov[0].iov_base;
                datalen = iov[0].iov_len;
        }
-       data = inbuf + sizeof (struct security_header) - 16;
-       datalen = datalen - sizeof (struct security_header) + 16;
-
-       outdata = outbuf + sizeof (struct security_header);
 
        /* Check the digest */
        enc_context = PK11_CreateContextBySymKey (
@@ -628,14 +615,18 @@ static int authenticate_and_decrypt_nss (
                return -1;
        }
 
-       PK11_DigestBegin(enc_context);
+       rv = PK11_DigestBegin(enc_context);
+
+       rv |= PK11_DigestOp(enc_context,
+               (unsigned char *)header + HMAC_HASH_SIZE,
+               sizeof (*header) - HMAC_HASH_SIZE);
+       rv |= PK11_DigestOp(enc_context, inbuf, datalen);
 
-       rv1 = PK11_DigestOp(enc_context, data, datalen);
-       rv2 = PK11_DigestFinal(enc_context, digest, &tmp2_outlen, 
sizeof(digest));
+       rv |= PK11_DigestFinal(enc_context, digest, &tmp2_outlen, 
sizeof(digest));
 
        PK11_DestroyContext(enc_context, PR_TRUE);
 
-       if (rv1 != SECSuccess || rv2 != SECSuccess) {
+       if (rv != SECSuccess) {
                log_printf(instance->totemudp_log_level_security, "Digest check 
failed\n");
                return -1;
        }
@@ -645,12 +636,6 @@ static int authenticate_and_decrypt_nss (
                return -1;
        }
 
-       /*
-        * Get rid of salt
-        */
-       data += 16;
-       datalen -= 16;
-
        /* Create cipher context for decryption */
        ivdata.type = siBuffer;
        ivdata.data = header->salt;
@@ -667,26 +652,27 @@ static int authenticate_and_decrypt_nss (
                return -1;
        }
 
-       rv1 = PK11_CipherOp(enc_context, outdata, &tmp1_outlen,
-                           sizeof(outbuf) - sizeof (struct security_header),
-                           data, datalen);
-       if (rv1 != SECSuccess) {
+       rv = PK11_CipherOp(enc_context, outbuf, &tmp1_outlen,
+               sizeof(outbuf), inbuf, datalen);
+       if (rv != SECSuccess) {
                log_printf(instance->totemudp_log_level_security,
                        "PK11_CipherOp (decrypt) failed (err %d)\n",
                        PR_GetError());
        }
-       rv2 = PK11_DigestFinal(enc_context, outdata + tmp1_outlen, &tmp2_outlen,
-                              sizeof(outbuf) - tmp1_outlen);
+       rv |= PK11_DigestFinal(enc_context, outbuf + tmp1_outlen, &tmp2_outlen,
+               sizeof(outbuf) - tmp1_outlen);
        PK11_DestroyContext(enc_context, PR_TRUE);
-       result_len = tmp1_outlen + tmp2_outlen + sizeof (struct 
security_header);
+       result_len = tmp1_outlen + tmp2_outlen;
 
        /* Copy it back to the buffer */
        copy_to_iovec(iov, iov_len, outbuf, result_len);
-       if (iov_len > 1)
+       if (iov_len > 1) {
                free(inbuf);
+       }
 
-       if (rv1 != SECSuccess || rv2 != SECSuccess)
+       if (rv != SECSuccess) {
                return -1;
+       }
 
        return 0;
 }
@@ -795,6 +781,7 @@ static int encrypt_and_sign_worker (
 
 static int authenticate_and_decrypt (
        struct totemudp_instance *instance,
+       struct security_header *security_header,
        struct iovec *iov,
        unsigned int iov_len)
 {
@@ -809,7 +796,7 @@ static int authenticate_and_decrypt (
        iov[iov_len-1].iov_len -= 1;
 
        if (type == TOTEM_CRYPTO_SOBER)
-               res = authenticate_and_decrypt_sober(instance, iov, iov_len);
+               res = authenticate_and_decrypt_sober(instance, security_header, 
iov, iov_len);
 
        /*
         * Only try higher crypto options if NEW has been requested
@@ -817,7 +804,7 @@ static int authenticate_and_decrypt (
        if (instance->totem_config->crypto_accept == TOTEM_CRYPTO_ACCEPT_NEW) {
 #ifdef HAVE_LIBNSS
                if (type == TOTEM_CRYPTO_NSS)
-                   res = authenticate_and_decrypt_nss(instance, iov, iov_len);
+                   res = authenticate_and_decrypt_nss(instance, 
security_header, iov, iov_len);
 #endif
        }
 
@@ -827,7 +814,7 @@ static int authenticate_and_decrypt (
         */
        if (res == -1) {
                iov[iov_len-1].iov_len += 1;
-               res = authenticate_and_decrypt_sober(instance, iov, iov_len);
+               res = authenticate_and_decrypt_sober(instance, security_header, 
iov, iov_len);
        }
 
        return res;
@@ -1173,14 +1160,26 @@ static int net_deliver_fn (
 {
        struct totemudp_instance *instance = (struct totemudp_instance *)data;
        struct msghdr msg_recv;
-       struct iovec *iovec;
+       struct iovec iovec[2];
+       struct iovec *buf_iov = iovec;
+       unsigned int iovlen = 1;
        struct sockaddr_storage system_from;
        int bytes_received;
-       int res = 0;
-       unsigned char *msg_offset;
-       unsigned int size_delv;
+       struct security_header security_header;
+       char *buffer;
 
-       iovec = &instance->totemudp_iov_recv;
+       if (instance->totem_config->secauth == 1) {
+             iovec->iov_base = &security_header;
+             iovec->iov_len = sizeof (security_header);
+             buf_iov++;
+             iovlen++;
+       }
+       buffer = totemudp_buffer_alloc();
+       if (!buffer) {
+               return (-1);
+       }
+       buf_iov->iov_base = buffer;
+       buf_iov->iov_len = FRAME_SIZE_MAX;
 
        /*
         * Receive datagram
@@ -1188,7 +1187,7 @@ static int net_deliver_fn (
        msg_recv.msg_name = &system_from;
        msg_recv.msg_namelen = sizeof (struct sockaddr_storage);
        msg_recv.msg_iov = iovec;
-       msg_recv.msg_iovlen = 1;
+       msg_recv.msg_iovlen = iovlen;
 #if !defined(COROSYNC_SOLARIS)
        msg_recv.msg_control = 0;
        msg_recv.msg_controllen = 0;
@@ -1205,33 +1204,33 @@ static int net_deliver_fn (
                instance->stats_recv += bytes_received;
        }
 
-       if ((instance->totem_config->secauth == 1) &&
-               (bytes_received < sizeof (struct security_header))) {
+       if (instance->totem_config->secauth == 1) {
+               int res = 0;
 
-               log_printf (instance->totemudp_log_level_security, "Received 
message is too short...  ignoring %d.\n", bytes_received);
-               return (0);
-       }
+               if (bytes_received < sizeof (struct security_header)) {
+
+                       log_printf (instance->totemudp_log_level_security,
+                               "Received message is too short...  ignoring 
%d.\n",
+                               bytes_received);
+                       return (0);
+               }
+
+               buf_iov->iov_len = bytes_received - sizeof (struct 
security_header);
 
-       iovec->iov_len = bytes_received;
-       if (instance->totem_config->secauth == 1) {
                /*
                 * Authenticate and if authenticated, decrypt datagram
                 */
 
-               res = authenticate_and_decrypt (instance, iovec, 1);
+               res = authenticate_and_decrypt (instance, &security_header, 
buf_iov, 1);
                if (res == -1) {
-                       log_printf (instance->totemudp_log_level_security, 
"Received message has invalid digest... ignoring.\n");
+                       log_printf (instance->totemudp_log_level_security,
+                               "Received message has invalid digest... 
ignoring.\n");
                        log_printf (instance->totemudp_log_level_security,
                                "Invalid packet data\n");
-                       iovec->iov_len = FRAME_SIZE_MAX;
                        return 0;
                }
-               msg_offset = (unsigned char *)iovec->iov_base +
-                       sizeof (struct security_header);
-               size_delv = bytes_received - sizeof (struct security_header);
        } else {
-               msg_offset = (void *)iovec->iov_base;
-               size_delv = bytes_received;
+               buf_iov->iov_len = bytes_received;
        }
 
        /*
@@ -1239,10 +1238,13 @@ static int net_deliver_fn (
         */
        instance->totemudp_deliver_fn (
                instance->context,
-               msg_offset,
-               size_delv);
+               buf_iov->iov_base,
+               buf_iov->iov_len);
+
+       if (!totembuf_is_retained (buffer)) {
+               totemudp_buffer_release (buffer);
+       }
 
-       iovec->iov_len = FRAME_SIZE_MAX;
        return (0);
 }
 
@@ -1788,7 +1790,6 @@ int totemudp_initialize (
         */
        instance->totem_interface = &totem_config->interfaces[interface_no];
        totemip_copy (&instance->mcast_address, 
&instance->totem_interface->mcast_addr);
-       memset (instance->iov_buffer, 0, FRAME_SIZE_MAX);
 
        /*
        * If threaded send requested, initialize thread group data structure
@@ -1838,11 +1839,7 @@ void *totemudp_buffer_alloc (void)
 
 void *totemudp_buffer_retain (void *ptr)
 {
-       void *new_buf = totemudp_buffer_alloc();
-       if (new_buf) {
-               memcpy (new_buf, ptr, FRAME_SIZE_MAX);
-       }
-       return new_buf;
+       return totembuf_retain (ptr);
 }
 
 void totemudp_buffer_release (void *ptr)

_______________________________________________
Openais mailing list
Openais@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/openais

Reply via email to