]> sjero.net Git - dccpping/blob - checksums.c
Separate out Address detection, packet building, and checksums. Can now send both...
[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 //Pseudo Headers for checksums
13 struct ip6_pseudo_hdr{
14         unsigned char src[IP6_ADDR_LEN];
15         unsigned char dest[IP6_ADDR_LEN];
16         unsigned int len;
17         unsigned char zero[3];
18         unsigned char nxt;
19 };
20 struct ip4_pseudo_hdr{
21         unsigned char src[IP4_ADDR_LEN];
22         unsigned char dest[IP4_ADDR_LEN];
23         unsigned int len;
24         unsigned char zero[3];
25         unsigned char nxt;
26 };
27
28 /*From http://gitorious.org/freebsd/freebsd/blobs/HEAD/sbin/dhclient/packet.c
29  * under GNU GPL*/
30 u_int32_t checksum(unsigned char *buf, unsigned nbytes, u_int32_t sum)
31 {
32         int i;
33         /* Checksum all the pairs of bytes first... */
34         for (i = 0; i < (nbytes & ~1U); i += 2) {
35                 sum += (u_int16_t)ntohs(*((u_int16_t *)(buf + i)));
36                 if (sum > 0xFFFF)
37                         sum -= 0xFFFF;
38         }
39         /*
40          * If there's a single byte left over, checksum it, too.
41          * Network byte order is big-endian, so the remaining byte is
42          * the high byte.
43          */
44         if (i < nbytes) {
45                 sum += buf[i] << 8;
46                 if (sum > 0xFFFF)
47                         sum -= 0xFFFF;
48         }
49         return (sum);
50 }
51
52 /*From http://gitorious.org/freebsd/freebsd/blobs/HEAD/sbin/dhclient/packet.c
53  * under GNU GPL*/
54 u_int32_t wrapsum(u_int32_t sum)
55 {
56         sum = ~sum & 0xFFFF;
57         return (htons(sum));
58 }
59
60 u_int16_t ipv6_pseudohdr_chksum(unsigned char* buff, int len, unsigned char* dest, unsigned char* src, int type){
61         struct ip6_pseudo_hdr hdr;
62
63         //create pseudo header
64         memset(&hdr, 0, sizeof(struct ip6_pseudo_hdr));
65         memcpy(hdr.src, src, IP6_ADDR_LEN);
66         memcpy(hdr.dest, dest, IP6_ADDR_LEN);
67         hdr.nxt=type;
68         hdr.len=htonl(len);
69
70         //calculate total checksum
71         return wrapsum(checksum((unsigned char*)&hdr,sizeof(struct ip6_pseudo_hdr),checksum(buff,len,0)));
72 }
73
74 u_int16_t ipv4_pseudohdr_chksum(unsigned char* buff, int len, unsigned char* dest, unsigned char* src, int type){
75         struct ip4_pseudo_hdr hdr;
76
77         //create pseudo header
78         memset(&hdr, 0, sizeof(struct ip4_pseudo_hdr));
79         memcpy(hdr.src, src, IP4_ADDR_LEN);
80         memcpy(hdr.dest, dest, IP4_ADDR_LEN);
81         hdr.nxt=type;
82         hdr.len=htonl(len);
83
84         //calculate total checksum
85         return wrapsum(checksum((unsigned char*)&hdr,sizeof(struct ip4_pseudo_hdr),checksum(buff,len,0)));
86 }
87
88 u_int16_t ipv4_chksum(unsigned char* buff, int len){
89         return wrapsum(checksum(buff,len,0));
90 }