]> sjero.net Git - dccpping/blob - checksums.c
Add manpage
[dccpping] / checksums.c
1 /******************************************************************************
2 Author: Samuel Jero <sj323707@ohio.edu>
3
4 Date: 10/2012
5
6 Description: IPv4 and IPv6 Checksum code
7 ******************************************************************************/
8 #include <string.h>
9 #include <arpa/inet.h>
10 #include "checksums.h"
11
12 /*Stupid Solaris*/
13 #ifndef u_int32_t
14 #define u_int32_t uint32_t
15 #endif
16 #ifndef u_int16_t
17 #define u_int16_t uint16_t
18 #endif
19
20 //Pseudo Headers for checksums
21 struct ip6_pseudo_hdr{
22         unsigned char src[IP6_ADDR_LEN];
23         unsigned char dest[IP6_ADDR_LEN];
24         unsigned int len;
25         unsigned char zero[3];
26         unsigned char nxt;
27 };
28 struct ip4_pseudo_hdr{
29         unsigned char src[IP4_ADDR_LEN];
30         unsigned char dest[IP4_ADDR_LEN];
31         unsigned int len;
32         unsigned char zero[3];
33         unsigned char nxt;
34 };
35
36 /*From http://gitorious.org/freebsd/freebsd/blobs/HEAD/sbin/dhclient/packet.c
37  * under GNU GPL*/
38 u_int32_t checksum(unsigned char *buf, unsigned nbytes, u_int32_t sum)
39 {
40         int i;
41         /* Checksum all the pairs of bytes first... */
42         for (i = 0; i < (nbytes & ~1U); i += 2) {
43                 sum += (u_int16_t)ntohs(*((u_int16_t *)(buf + i)));
44                 if (sum > 0xFFFF)
45                         sum -= 0xFFFF;
46         }
47         /*
48          * If there's a single byte left over, checksum it, too.
49          * Network byte order is big-endian, so the remaining byte is
50          * the high byte.
51          */
52         if (i < nbytes) {
53                 sum += buf[i] << 8;
54                 if (sum > 0xFFFF)
55                         sum -= 0xFFFF;
56         }
57         return (sum);
58 }
59
60 /*From http://gitorious.org/freebsd/freebsd/blobs/HEAD/sbin/dhclient/packet.c
61  * under GNU GPL*/
62 u_int32_t wrapsum(u_int32_t sum)
63 {
64         sum = ~sum & 0xFFFF;
65         return (htons(sum));
66 }
67
68 u_int16_t ipv6_pseudohdr_chksum(unsigned char* buff, int len, unsigned char* dest, unsigned char* src, int type){
69         struct ip6_pseudo_hdr hdr;
70
71         //create pseudo header
72         memset(&hdr, 0, sizeof(struct ip6_pseudo_hdr));
73         memcpy(hdr.src, src, IP6_ADDR_LEN);
74         memcpy(hdr.dest, dest, IP6_ADDR_LEN);
75         hdr.nxt=type;
76         hdr.len=htonl(len);
77
78         //calculate total checksum
79         return wrapsum(checksum((unsigned char*)&hdr,sizeof(struct ip6_pseudo_hdr),checksum(buff,len,0)));
80 }
81
82 u_int16_t ipv4_pseudohdr_chksum(unsigned char* buff, int len, unsigned char* dest, unsigned char* src, int type){
83         struct ip4_pseudo_hdr hdr;
84
85         //create pseudo header
86         memset(&hdr, 0, sizeof(struct ip4_pseudo_hdr));
87         memcpy(hdr.src, src, IP4_ADDR_LEN);
88         memcpy(hdr.dest, dest, IP4_ADDR_LEN);
89         hdr.nxt=type;
90         hdr.len=htonl(len);
91
92         //calculate total checksum
93         return wrapsum(checksum((unsigned char*)&hdr,sizeof(struct ip4_pseudo_hdr),checksum(buff,len,0)));
94 }
95
96 u_int16_t ipv4_chksum(unsigned char* buff, int len){
97         return wrapsum(checksum(buff,len,0));
98 }