]> sjero.net Git - ltp2tcp/blob - checksums.c
Checksum Computation!!
[ltp2tcp] / checksums.c
1 /******************************************************************************
2 IPv4 and IPv6 Header Checksum Code
3
4 Copyright (C) 2013  Samuel Jero <sj323707@ohio.edu>
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19 Author: Samuel Jero <sj323707@ohio.edu>
20 Date: 02/2013
21 ******************************************************************************/
22 #include <string.h>
23 #include <arpa/inet.h>
24 #include "checksums.h"
25
26 /*Stupid Solaris*/
27 #ifndef u_int32_t
28 #define u_int32_t uint32_t
29 #endif
30 #ifndef u_int16_t
31 #define u_int16_t uint16_t
32 #endif
33
34 //Pseudo Headers for checksums
35 struct ip6_pseudo_hdr{
36         u_char          src[IP6_ADDR_LEN];
37         u_char          dest[IP6_ADDR_LEN];
38         unsigned int len;
39         u_char          zero[3];
40         u_char          nxt;
41 };
42 struct ip4_pseudo_hdr{
43         u_char          src[IP4_ADDR_LEN];
44         u_char          dest[IP4_ADDR_LEN];
45         unsigned int len;
46         u_char          zero[3];
47         u_char          nxt;
48 };
49
50 /*From http://gitorious.org/freebsd/freebsd/blobs/HEAD/sbin/dhclient/packet.c
51  * under GNU GPL*/
52 u_int32_t checksum(u_char *buf, unsigned nbytes, u_int32_t sum)
53 {
54         int i;
55         /* Checksum all the pairs of bytes first... */
56         for (i = 0; i < (nbytes & ~1U); i += 2) {
57                 sum += (u_int16_t)ntohs(*((u_int16_t *)(buf + i)));
58                 if (sum > 0xFFFF)
59                         sum -= 0xFFFF;
60         }
61         /*
62          * If there's a single byte left over, checksum it, too.
63          * Network byte order is big-endian, so the remaining byte is
64          * the high byte.
65          */
66         if (i < nbytes) {
67                 sum += buf[i] << 8;
68                 if (sum > 0xFFFF)
69                         sum -= 0xFFFF;
70         }
71         return (sum);
72 }
73
74 /*From http://gitorious.org/freebsd/freebsd/blobs/HEAD/sbin/dhclient/packet.c
75  * under GNU GPL*/
76 u_int32_t wrapsum(u_int32_t sum)
77 {
78         sum = ~sum & 0xFFFF;
79         return (htons(sum));
80 }
81
82 u_int16_t ipv6_pseudohdr_chksum(u_char* buff, int len, u_char* dest, u_char* src, int type){
83         struct ip6_pseudo_hdr hdr;
84
85         //create pseudo header
86         memset(&hdr, 0, sizeof(struct ip6_pseudo_hdr));
87         memcpy(hdr.src, src, IP6_ADDR_LEN);
88         memcpy(hdr.dest, dest, IP6_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 ip6_pseudo_hdr),checksum(buff,len,0)));
94 }
95
96 u_int16_t ipv4_pseudohdr_chksum(u_char* buff, int len, u_char* dest, u_char* src, int type){
97         struct ip4_pseudo_hdr hdr;
98
99         //create pseudo header
100         memset(&hdr, 0, sizeof(struct ip4_pseudo_hdr));
101         memcpy(hdr.src, src, IP4_ADDR_LEN);
102         memcpy(hdr.dest, dest, IP4_ADDR_LEN);
103         hdr.nxt=type;
104         hdr.len=htonl(len);
105
106         //calculate total checksum
107         return wrapsum(checksum((u_char*)&hdr,sizeof(struct ip4_pseudo_hdr),checksum(buff,len,0)));
108 }
109
110 u_int16_t ipv4_chksum(u_char* buff, int len){
111         return wrapsum(checksum(buff,len,0));
112 }