[hipl-commit] [trunk] Rev 3893: Continuing splitting misc.c (bug id 1139). Separated checksums.

  • From: Miika Komu <miika@xxxxxx>
  • To: hipl-commit@xxxxxxxxxxxxx
  • Date: Tue, 9 Mar 2010 23:23:42 +0200

Committer: Miika Komu <miika@xxxxxx>
Date: Tue Mar 09 23:23:38 2010 +0200
Revision: 3893
Revision-id: miika@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Branch nick: trunk

Log:
  Continuing splitting misc.c (bug id 1139). Separated checksums.

Modified:
  A  lib/tool/checksum.c
  A  lib/tool/checksum.h
  M  Makefile.am
  M  firewall/firewall_defines.h
  M  firewall/firewalldb.c
  M  firewall/proxy.c
  M  firewall/user_ipsec_esp.c
  M  hipd/input.h
  M  hipd/output.c
  M  lib/core/builder.c
  M  lib/core/builder.h
  M  lib/core/misc.c
  M  lib/core/misc.h

=== modified file 'Makefile.am'
--- Makefile.am 2010-03-09 19:28:57 +0000
+++ Makefile.am 2010-03-09 21:23:38 +0000
@@ -268,7 +268,8 @@
 
 lib_tool_libhiptool_la_SOURCES = lib/tool/pk.c \
                                  lib/tool/nlink.c \
-                                 lib/tool/lutil.c
+                                 lib/tool/lutil.c \
+                                 lib/tool/checksum.c
 
 ############################ NOTE ##################################
 #

=== modified file 'firewall/firewall_defines.h'
--- firewall/firewall_defines.h 2010-03-09 18:26:22 +0000
+++ firewall/firewall_defines.h 2010-03-09 21:23:38 +0000
@@ -136,63 +136,4 @@
     struct hip_esp *esp_data;
 };
 
-typedef struct pseudo_v6 {
-    struct  in6_addr src;
-    struct in6_addr  dst;
-    uint16_t         length;
-    uint16_t         zero1;
-    uint8_t          zero2;
-    uint8_t          next;
-} pseudo_v6;
-
-static inline uint16_t inchksum(const void *data, uint32_t length)
-{
-    long sum            = 0;
-    const uint16_t *wrd =  (uint16_t *) data;
-    long slen           = (long) length;
-
-    while (slen > 1) {
-        sum  += *wrd++;
-        slen -= 2;
-    }
-
-    if (slen > 0) {
-        sum += *((uint8_t *) wrd);
-    }
-
-    while (sum >> 16) {
-        sum = (sum & 0xffff) + (sum >> 16);
-    }
-
-    return (uint16_t) sum;
-}
-
-static inline uint16_t ipv6_checksum(uint8_t protocol,
-                                     struct in6_addr *src,
-                                     struct in6_addr *dst,
-                                     void *data, uint16_t len)
-{
-    uint32_t chksum = 0;
-    pseudo_v6 pseudo;
-    memset(&pseudo, 0, sizeof(pseudo_v6));
-
-    pseudo.src    = *src;
-    pseudo.dst    = *dst;
-    pseudo.length = htons(len);
-    pseudo.next   = protocol;
-
-    chksum        = inchksum(&pseudo, sizeof(pseudo_v6));
-    chksum       += inchksum(data, len);
-
-    chksum        = (chksum >> 16) + (chksum & 0xffff);
-    chksum       += (chksum >> 16);
-
-    chksum        = (uint16_t) (~chksum);
-    if (chksum == 0) {
-        chksum = 0xffff;
-    }
-
-    return chksum;
-}
-
 #endif /*HIP_FIREWALL_FIREWALL_DEFINES_H*/

=== modified file 'firewall/firewalldb.c'
--- firewall/firewalldb.c       2010-03-05 08:57:28 +0000
+++ firewall/firewalldb.c       2010-03-09 21:23:38 +0000
@@ -25,6 +25,7 @@
 #include "lib/core/debug.h"
 #include "lib/core/hashtable.h"
 #include "lib/core/misc.h"
+#include "lib/tool/checksum.h"
 
 #define DISABLE_hip_firewall_hldb_dump
 #define DISABLE_firewall_init_raw_sock_esp_v6

=== modified file 'firewall/proxy.c'
--- firewall/proxy.c    2010-03-05 08:47:53 +0000
+++ firewall/proxy.c    2010-03-09 21:23:38 +0000
@@ -10,6 +10,7 @@
 #include "firewall/proxy.h"
 #include "firewall/proxyconndb.h"
 #include "firewall/firewall_defines.h"
+#include "lib/tool/checksum.h"
 
 int hip_proxy_raw_sock_tcp_v4          = 0;
 int hip_proxy_raw_sock_tcp_v6          = 0;

=== modified file 'firewall/user_ipsec_esp.c'
--- firewall/user_ipsec_esp.c   2010-03-03 13:16:18 +0000
+++ firewall/user_ipsec_esp.c   2010-03-09 21:23:38 +0000
@@ -33,48 +33,11 @@
 #include "esp_prot_api.h"
 #include "lib/core/prefix.h"
 #include "lib/core/misc.h"
+#include "lib/tool/checksum.h"
 
 /* for some reason the ICV for ESP authentication is truncated to 12 bytes */
 #define ICV_LENGTH 12
 
-/** calculates the IP-checksum
- *
- * @param ip_hdr    packet to be checksumed
- * @param ip_hl     header length field inside the header
- * @return          the IP checksum
- */
-static uint16_t checksum_ip(struct ip *ip_hdr, const unsigned int ip_hl)
-{
-    uint16_t checksum = 0;
-    unsigned long sum = 0;
-    int count         = ip_hl * 4;
-    unsigned short *p = (unsigned short *) ip_hdr;
-
-    /*
-     * this checksum algorithm can be found
-     * in RFC 1071 section 4.1
-     */
-
-    /* one's complement sum 16-bit words of data */
-    while (count > 1) {
-        sum   += *p++;
-        count -= 2;
-    }
-    /* add left-over byte, if any */
-    if (count > 0) {
-        sum += (unsigned char) *p;
-    }
-
-    /*  Fold 32-bit sum to 16 bits */
-    while (sum >> 16) {
-        sum = (sum & 0xffff) + (sum >> 16);
-    }
-    /* take the one's complement of the sum */
-    checksum = (uint16_t) (~sum);
-
-    return checksum;
-}
-
 /** adds an UDP-header to the packet
  *
  * @param udp_hdr       location of the udp_hdr

=== modified file 'hipd/input.h'
--- hipd/input.h        2010-03-09 18:26:22 +0000
+++ hipd/input.h        2010-03-09 21:23:38 +0000
@@ -34,22 +34,6 @@
     struct in6_addr sin6_addr;
 };
 
-struct pseudo_header6 {
-    unsigned char src_addr[16];
-    unsigned char dst_addr[16];
-    uint32_t           packet_length;
-    unsigned char zero[3];
-    uint8_t            next_hdr;
-};
-
-struct pseudo_header {
-    unsigned char src_addr[4];
-    unsigned char dst_addr[4];
-    uint8_t            zero;
-    uint8_t            protocol;
-    uint16_t           packet_length;
-};
-
 /**
  * Checks for illegal controls in a HIP packet Controls field.
  *

=== modified file 'hipd/output.c'
--- hipd/output.c       2010-03-09 18:26:22 +0000
+++ hipd/output.c       2010-03-09 21:23:38 +0000
@@ -27,49 +27,13 @@
 #endif
 
 #include "lib/core/hip_udp.h"
+#include "lib/tool/checksum.h"
 
 enum number_dh_keys_t { ONE, TWO };
 
 enum number_dh_keys_t number_dh_keys = TWO;
 
 /**
- * Standard BSD internet checksum routine from nmap
- * for calculating the checksum field of the TCP header
- */
-unsigned short in_cksum(uint16_t *ptr, int nbytes)
-{
-    register uint32_t sum;
-    uint16_t oddbyte;
-    register uint16_t answer;
-
-    /*
-     * Our algorithm is simple, using a 32-bit accumulator (sum),
-     * we add sequential 16-bit words to it, and at the end, fold back
-     * all the carry bits from the top 16 bits into the lower 16 bits.
-     */
-    sum = 0;
-    while (nbytes > 1) {
-        sum    += *ptr++;
-        nbytes -= 2;
-    }
-
-    /* mop up an odd byte, if necessary */
-    if (nbytes == 1) {
-        oddbyte                = 0;     /* make sure top half is zero */
-        *((u_char *) &oddbyte) = *(u_char *) ptr;          /* one byte only */
-        sum                   += oddbyte;
-    }
-
-    /*
-     * Add back carry outs from top 16 bits to low 16 bits.
-     */
-    sum    = (sum >> 16) + (sum & 0xffff);      /* add high-16 to low-16 */
-    sum   += (sum >> 16);                       /* add carry */
-    answer = ~sum;              /* ones-complement, then truncate to 16 bits */
-    return answer;
-}
-
-/**
  * @brief Sends a TCP packet through a raw socket.
  *
  * @param  hdr

=== modified file 'lib/core/builder.c'
--- lib/core/builder.c  2010-03-09 18:26:22 +0000
+++ lib/core/builder.c  2010-03-09 21:23:38 +0000
@@ -73,6 +73,7 @@
 #include "hipd/input.h"
 #include "lib/core/crypto.h"
 #include "lib/core/hostid.h"
+#include "lib/tool/checksum.h"
 
 /* ARRAY_SIZE is defined in linux/kernel.h, but it is in #ifdef __KERNEL__ */
 #ifndef ARRAY_SIZE
@@ -1990,93 +1991,6 @@
 }
 
 /**
- * Calculates the checksum of a HIP packet with pseudo-header.
- *
- * @param data a pointer to a hip_common structure
- * @param src  The source address of the packet as a sockaddr_in or 
sockaddr_in6
- *             structure in network byte order. IPv6 mapped addresses are not 
supported.
- * @param dst  The destination address of the packet as a sockaddr_in or 
sockaddr_in6
- *             structure in network byte order. IPv6 mapped addresses are not 
supported.
- * @return     the checksum
- * @note       Checksumming is from Boeing's HIPD.
- */
-uint16_t hip_checksum_packet(char *data, struct sockaddr *src, struct sockaddr 
*dst)
-{
-    uint16_t checksum      = 0;
-    unsigned long sum = 0;
-    int count         = 0, length = 0;
-    unsigned short *p = NULL;     /* 16-bit */
-    struct pseudo_header pseudoh;
-    struct pseudo_header6 pseudoh6;
-    uint32_t src_network, dst_network;
-    struct in6_addr *src6, *dst6;
-    struct hip_common *hiph = (struct hip_common *) data;
-
-    if (src->sa_family == AF_INET) {
-        /* IPv4 checksum based on UDP-- Section 6.1.2 */
-        src_network = ((struct sockaddr_in *) src)->sin_addr.s_addr;
-        dst_network = ((struct sockaddr_in *) dst)->sin_addr.s_addr;
-
-        memset(&pseudoh, 0, sizeof(struct pseudo_header));
-        memcpy(&pseudoh.src_addr, &src_network, 4);
-        memcpy(&pseudoh.dst_addr, &dst_network, 4);
-        pseudoh.protocol      = IPPROTO_HIP;
-        length                = (hiph->payload_len + 1) * 8;
-        pseudoh.packet_length = htons(length);
-
-        count                 = sizeof(struct pseudo_header); /* count always 
even number */
-        p                     = (unsigned short *) &pseudoh;
-    } else {
-        /* IPv6 checksum based on IPv6 pseudo-header */
-        src6 = &((struct sockaddr_in6 *) src)->sin6_addr;
-        dst6 = &((struct sockaddr_in6 *) dst)->sin6_addr;
-
-        memset(&pseudoh6, 0, sizeof(struct pseudo_header6));
-        memcpy(&pseudoh6.src_addr[0], src6, 16);
-        memcpy(&pseudoh6.dst_addr[0], dst6, 16);
-        length                 = (hiph->payload_len + 1) * 8;
-        pseudoh6.packet_length = htonl(length);
-        pseudoh6.next_hdr      = IPPROTO_HIP;
-
-        count                  = sizeof(struct pseudo_header6); /* count 
always even number */
-        p                      = (unsigned short *) &pseudoh6;
-    }
-    /*
-     * this checksum algorithm can be found
-     * in RFC 1071 section 4.1
-     */
-
-    /* sum the pseudo-header */
-    /* count and p are initialized above per protocol */
-    while (count > 1) {
-        sum   += *p++;
-        count -= 2;
-    }
-
-    /* one's complement sum 16-bit words of data */
-    HIP_DEBUG("Checksumming %d bytes of data.\n", length);
-    count = length;
-    p     = (unsigned short *) data;
-    while (count > 1) {
-        sum   += *p++;
-        count -= 2;
-    }
-    /* add left-over byte, if any */
-    if (count > 0) {
-        sum += (unsigned char) *p;
-    }
-
-    /*  Fold 32-bit sum to 16 bits */
-    while (sum >> 16) {
-        sum = (sum & 0xffff) + (sum >> 16);
-    }
-    /* take the one's complement of the sum */
-    checksum = ~sum;
-
-    return checksum;
-}
-
-/**
  * sanity checking for a HIP control packet originating from the network
  *
  * @param src  The source address of the packet as a sockaddr_in or 
sockaddr_in6

=== modified file 'lib/core/builder.h'
--- lib/core/builder.h  2010-03-09 18:26:22 +0000
+++ lib/core/builder.h  2010-03-09 21:23:38 +0000
@@ -183,7 +183,6 @@
                               struct sockaddr *src,
                               struct sockaddr *dst,
                               int len);
-uint16_t hip_checksum_packet(char *data, struct sockaddr *src, struct sockaddr 
*dst);
 int hip_check_userspace_msg(const struct hip_common *);
 int hip_check_userspace_msg_type(const struct hip_common *);
 void hip_dump_msg(const struct hip_common *);

=== modified file 'lib/core/misc.c'
--- lib/core/misc.c     2010-03-09 18:26:22 +0000
+++ lib/core/misc.c     2010-03-09 21:23:38 +0000
@@ -283,56 +283,6 @@
 }
 
 /**
- * Generate the IPv4 header checksum
- *
- * @param s     source address
- * @param d     destination address
- * @param c     data
- * @return the calculated IPv4 header checksum
- */
-uint16_t ipv4_checksum(uint8_t protocol, void *s, void *d, void *c, uint16_t 
len)
-{
-    uint8_t *src   = s;
-    uint8_t *dst   = d;
-    uint8_t *data  = c;
-    uint16_t word16;
-    uint32_t sum;
-    uint16_t i;
-
-    /* initialize sum to zero */
-    sum = 0;
-
-    /* make 16 bit words out of every two adjacent 8 bit words and */
-    /* calculate the sum of all 16 vit words */
-    for (i = 0; i < len; i = i + 2) {
-        word16 = ((((uint16_t) (data[i] << 8))) & 0xFF00) + (((uint16_t) 
data[i + 1]) & 0xFF);
-        sum    = sum + (unsigned long) word16;
-    }
-    /* add the TCP pseudo header which contains:
-       the IP source and destination addresses, */
-    for (i = 0; i < 4; i = i + 2) {
-        word16 = ((src[i] << 8) & 0xFF00) + (src[i + 1] & 0xFF);
-        sum    = sum + word16;
-    }
-    for (i = 0; i < 4; i = i + 2) {
-        word16 = ((dst[i] << 8) & 0xFF00) + (dst[i + 1] & 0xFF);
-        sum    = sum + word16;
-    }
-    /* the protocol number and the length of the TCP packet */
-    sum = sum + protocol + len;
-
-    /* keep only the last 16 bits of the 32 bit calculated sum
-       and add the carries */
-    while (sum >> 16) {
-        sum = (sum & 0xFFFF) + (sum >> 16);
-    }
-
-    /* Take the one's complement of sum */
-    sum = ~sum;
-    return htons((unsigned short) sum);
-}
-
-/**
  * convert a string into a binary IPv4 address (a wrapper for inet_pton())
  *
  * @param str the string to convert

=== modified file 'lib/core/misc.h'
--- lib/core/misc.h     2010-03-09 18:26:22 +0000
+++ lib/core/misc.h     2010-03-09 21:23:38 +0000
@@ -189,8 +189,6 @@
                                 struct in6_addr *src_hit,
                                 struct in6_addr *dst_hit);
 
-uint16_t ipv4_checksum(uint8_t protocol, void *s, void *d, void *c, uint16_t 
len);
-
 /* openSSL wrapper functions for base64 encoding and decoding */
 
 unsigned char *base64_encode(unsigned char *, unsigned int);

=== added file 'lib/tool/checksum.c'
--- lib/tool/checksum.c 1970-01-01 00:00:00 +0000
+++ lib/tool/checksum.c 2010-03-09 21:23:38 +0000
@@ -0,0 +1,332 @@
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * @brief Checksum functions
+ *
+ * @author Miika Komu <miika@xxxxxx>
+ * @note check if some of the checksum algos are redundant
+ */
+
+/* required for s6_addr */
+#define _BSD_SOURCE
+
+#include <netinet/ip.h>
+#include <sys/types.h>
+#include <string.h>
+#include "config.h"
+#include "checksum.h"
+#include "lib/core/debug.h"
+
+struct pseudo_header {
+    unsigned char src_addr[4];
+    unsigned char dst_addr[4];
+    uint8_t            zero;
+    uint8_t            protocol;
+    uint16_t           packet_length;
+};
+typedef struct pseudo_v6 {
+    struct  in6_addr src;
+    struct in6_addr  dst;
+    uint16_t         length;
+    uint16_t         zero1;
+    uint8_t          zero2;
+    uint8_t          next;
+} pseudo_v6;
+
+/** @todo this is redundant with pseudo_v6 */
+struct pseudo_header6 {
+    unsigned char src_addr[16];
+    unsigned char dst_addr[16];
+    uint32_t           packet_length;
+    unsigned char zero[3];
+    uint8_t            next_hdr;
+};
+
+/**
+ * Generate the IPv4 header checksum
+ *
+ * @param s     source address
+ * @param d     destination address
+ * @param c     data
+ * @return the calculated IPv4 header checksum
+ */
+uint16_t ipv4_checksum(uint8_t protocol, void *s, void *d, void *c, uint16_t 
len)
+{
+    uint8_t *src   = s;
+    uint8_t *dst   = d;
+    uint8_t *data  = c;
+    uint16_t word16;
+    uint32_t sum;
+    uint16_t i;
+
+    /* initialize sum to zero */
+    sum = 0;
+
+    /* make 16 bit words out of every two adjacent 8 bit words and */
+    /* calculate the sum of all 16 vit words */
+    for (i = 0; i < len; i = i + 2) {
+        word16 = ((((uint16_t) (data[i] << 8))) & 0xFF00) + (((uint16_t) 
data[i + 1]) & 0xFF);
+        sum    = sum + (unsigned long) word16;
+    }
+    /* add the TCP pseudo header which contains:
+       the IP source and destination addresses, */
+    for (i = 0; i < 4; i = i + 2) {
+        word16 = ((src[i] << 8) & 0xFF00) + (src[i + 1] & 0xFF);
+        sum    = sum + word16;
+    }
+    for (i = 0; i < 4; i = i + 2) {
+        word16 = ((dst[i] << 8) & 0xFF00) + (dst[i + 1] & 0xFF);
+        sum    = sum + word16;
+    }
+    /* the protocol number and the length of the TCP packet */
+    sum = sum + protocol + len;
+
+    /* keep only the last 16 bits of the 32 bit calculated sum
+       and add the carries */
+    while (sum >> 16) {
+        sum = (sum & 0xFFFF) + (sum >> 16);
+    }
+
+    /* Take the one's complement of sum */
+    sum = ~sum;
+    return htons((unsigned short) sum);
+}
+
+/**
+ * calculate IPv6 checksum
+ *
+ * @param protocol the protocol
+ * @param src source address
+ * @param dst destination address
+ * @param data the data to checksum
+ * @param len the length of the data
+ * @return the calculated checksum
+ */
+uint16_t ipv6_checksum(uint8_t protocol,
+                       struct in6_addr *src,
+                       struct in6_addr *dst,
+                       void *data, uint16_t len)
+{
+    uint32_t chksum = 0;
+    pseudo_v6 pseudo;
+    memset(&pseudo, 0, sizeof(pseudo_v6));
+
+    pseudo.src    = *src;
+    pseudo.dst    = *dst;
+    pseudo.length = htons(len);
+    pseudo.next   = protocol;
+
+    chksum        = inchksum(&pseudo, sizeof(pseudo_v6));
+    chksum       += inchksum(data, len);
+
+    chksum        = (chksum >> 16) + (chksum & 0xffff);
+    chksum       += (chksum >> 16);
+
+    chksum        = (uint16_t) (~chksum);
+    if (chksum == 0) {
+        chksum = 0xffff;
+    }
+
+    return chksum;
+}
+
+/** calculate an IP checksum
+ *
+ * @param ip_hdr    packet to be checksumed
+ * @param ip_hl     header length field inside the header
+ * @return          the IP checksum
+ * @note taken from  RFC 1071 section 4.1
+ */
+uint16_t checksum_ip(struct ip *ip_hdr, const unsigned int ip_hl)
+{
+    uint16_t checksum = 0;
+    unsigned long sum = 0;
+    int count         = ip_hl * 4;
+    unsigned short *p = (unsigned short *) ip_hdr;
+
+    /*
+     * this checksum algorithm can be found
+     * in RFC 1071 section 4.1
+     */
+
+    /* one's complement sum 16-bit words of data */
+    while (count > 1) {
+        sum   += *p++;
+        count -= 2;
+    }
+    /* add left-over byte, if any */
+    if (count > 0) {
+        sum += (unsigned char) *p;
+    }
+
+    /*  Fold 32-bit sum to 16 bits */
+    while (sum >> 16) {
+        sum = (sum & 0xffff) + (sum >> 16);
+    }
+    /* take the one's complement of the sum */
+    checksum = (uint16_t) (~sum);
+
+    return checksum;
+}
+
+/**
+ * yet another checksummer
+ *
+ * @param data the data to checksum
+ * @param length the length of the data
+ * @return the calculated checksum
+ */
+uint16_t inchksum(const void *data, uint32_t length)
+{
+    long sum            = 0;
+    const uint16_t *wrd =  (uint16_t *) data;
+    long slen           = (long) length;
+
+    while (slen > 1) {
+        sum  += *wrd++;
+        slen -= 2;
+    }
+
+    if (slen > 0) {
+        sum += *((uint8_t *) wrd);
+    }
+
+    while (sum >> 16) {
+        sum = (sum & 0xffff) + (sum >> 16);
+    }
+
+    return (uint16_t) sum;
+}
+
+/**
+ * Standard BSD internet checksum routine from nmap
+ * for calculating the checksum field of the TCP header.
+ *
+ * @param ptr the data to checksum
+ * @param nbytes the length of data
+ * @return the checksum
+ *
+ * @note borrowed from Steven's network programming manual
+ */
+unsigned short in_cksum(uint16_t *ptr, int nbytes)
+{
+    register uint32_t sum;
+    uint16_t oddbyte;
+    register uint16_t answer;
+
+    /*
+     * Our algorithm is simple, using a 32-bit accumulator (sum),
+     * we add sequential 16-bit words to it, and at the end, fold back
+     * all the carry bits from the top 16 bits into the lower 16 bits.
+     */
+    sum = 0;
+    while (nbytes > 1) {
+        sum    += *ptr++;
+        nbytes -= 2;
+    }
+
+    /* mop up an odd byte, if necessary */
+    if (nbytes == 1) {
+        oddbyte                = 0;     /* make sure top half is zero */
+        *((u_char *) &oddbyte) = *(u_char *) ptr;          /* one byte only */
+        sum                   += oddbyte;
+    }
+
+    /*
+     * Add back carry outs from top 16 bits to low 16 bits.
+     */
+    sum    = (sum >> 16) + (sum & 0xffff);      /* add high-16 to low-16 */
+    sum   += (sum >> 16);                       /* add carry */
+    answer = ~sum;              /* ones-complement, then truncate to 16 bits */
+    return answer;
+}
+
+/**
+ * Calculates the checksum of a HIP packet with pseudo-header.
+ *
+ * @param data a pointer to a hip_common structure
+ * @param src  The source address of the packet as a sockaddr_in or 
sockaddr_in6
+ *             structure in network byte order. IPv6 mapped addresses are not 
supported.
+ * @param dst  The destination address of the packet as a sockaddr_in or 
sockaddr_in6
+ *             structure in network byte order. IPv6 mapped addresses are not 
supported.
+ * @return     the checksum
+ * @note       Checksumming is from Boeing's HIPD.
+ */
+uint16_t hip_checksum_packet(char *data, struct sockaddr *src, struct sockaddr 
*dst)
+{
+    uint16_t checksum      = 0;
+    unsigned long sum = 0;
+    int count         = 0, length = 0;
+    unsigned short *p = NULL;     /* 16-bit */
+    struct pseudo_header pseudoh;
+    struct pseudo_header6 pseudoh6;
+    uint32_t src_network, dst_network;
+    struct in6_addr *src6, *dst6;
+    struct hip_common *hiph = (struct hip_common *) data;
+
+    if (src->sa_family == AF_INET) {
+        /* IPv4 checksum based on UDP-- Section 6.1.2 */
+        src_network = ((struct sockaddr_in *) src)->sin_addr.s_addr;
+        dst_network = ((struct sockaddr_in *) dst)->sin_addr.s_addr;
+
+        memset(&pseudoh, 0, sizeof(struct pseudo_header));
+        memcpy(&pseudoh.src_addr, &src_network, 4);
+        memcpy(&pseudoh.dst_addr, &dst_network, 4);
+        pseudoh.protocol      = IPPROTO_HIP;
+        length                = (hiph->payload_len + 1) * 8;
+        pseudoh.packet_length = htons(length);
+
+        count                 = sizeof(struct pseudo_header); /* count always 
even number */
+        p                     = (unsigned short *) &pseudoh;
+    } else {
+        /* IPv6 checksum based on IPv6 pseudo-header */
+        src6 = &((struct sockaddr_in6 *) src)->sin6_addr;
+        dst6 = &((struct sockaddr_in6 *) dst)->sin6_addr;
+
+        memset(&pseudoh6, 0, sizeof(struct pseudo_header6));
+        memcpy(&pseudoh6.src_addr[0], src6, 16);
+        memcpy(&pseudoh6.dst_addr[0], dst6, 16);
+        length                 = (hiph->payload_len + 1) * 8;
+        pseudoh6.packet_length = htonl(length);
+        pseudoh6.next_hdr      = IPPROTO_HIP;
+
+        count                  = sizeof(struct pseudo_header6); /* count 
always even number */
+        p                      = (unsigned short *) &pseudoh6;
+    }
+    /*
+     * this checksum algorithm can be found
+     * in RFC 1071 section 4.1
+     */
+
+    /* sum the pseudo-header */
+    /* count and p are initialized above per protocol */
+    while (count > 1) {
+        sum   += *p++;
+        count -= 2;
+    }
+
+    /* one's complement sum 16-bit words of data */
+    HIP_DEBUG("Checksumming %d bytes of data.\n", length);
+    count = length;
+    p     = (unsigned short *) data;
+    while (count > 1) {
+        sum   += *p++;
+        count -= 2;
+    }
+    /* add left-over byte, if any */
+    if (count > 0) {
+        sum += (unsigned char) *p;
+    }
+
+    /*  Fold 32-bit sum to 16 bits */
+    while (sum >> 16) {
+        sum = (sum & 0xffff) + (sum >> 16);
+    }
+    /* take the one's complement of the sum */
+    checksum = ~sum;
+
+    return checksum;
+}
+

=== added file 'lib/tool/checksum.h'
--- lib/tool/checksum.h 1970-01-01 00:00:00 +0000
+++ lib/tool/checksum.h 2010-03-09 21:23:38 +0000
@@ -0,0 +1,18 @@
+#ifndef HIP_LIB_CORE_CHECKSUM_H
+#define HIP_LIB_CORE_CHECKSUM_H
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include "lib/core/protodefs.h"
+
+uint16_t ipv4_checksum(uint8_t protocol, void *s, void *d, void *c, uint16_t 
len);
+uint16_t ipv6_checksum(uint8_t protocol,
+                       struct in6_addr *src,
+                       struct in6_addr *dst,
+                       void *data, uint16_t len);
+uint16_t checksum_ip(struct ip *ip_hdr, const unsigned int ip_hl);
+unsigned short in_cksum(uint16_t *ptr, int nbytes);
+uint16_t inchksum(const void *data, uint32_t length);
+uint16_t hip_checksum_packet(char *data, struct sockaddr *src, struct sockaddr 
*dst);
+
+#endif /* HIP_LIB_CORE_CHECKSUM_H */

Other related posts:

  • » [hipl-commit] [trunk] Rev 3893: Continuing splitting misc.c (bug id 1139). Separated checksums. - Miika Komu