]> sjero.net Git - ltp2tcp/commitdiff
Checksum Computation!! master
authorSamuel Jero <sj323707@ohio.edu>
Fri, 28 Jun 2013 18:50:22 +0000 (14:50 -0400)
committerSamuel Jero <sj323707@ohio.edu>
Fri, 28 Jun 2013 18:50:22 +0000 (14:50 -0400)
Makefile
checksums.c [new file with mode: 0644]
checksums.h [new file with mode: 0644]
encap.c

index 4cb99c2281ceace362b5bd43497061718d93a1c9..6cfd851f9532c2668dd8472fb787461ad5442859 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -22,8 +22,8 @@ MANDIR = /usr/local/man
 
 all: ltp2tcp
 
-ltp2tcp: main.o ltp.o encap.o udp.o dccp.o sll.o Makefile
-       gcc ${CFLAGS} ${LDLIBS} --std=gnu99 main.o ltp.o encap.o udp.o dccp.o sll.o -oltp2tcp
+ltp2tcp: main.o ltp.o encap.o udp.o dccp.o sll.o checksums.o Makefile
+       gcc ${CFLAGS} ${LDLIBS} --std=gnu99 main.o ltp.o encap.o udp.o dccp.o sll.o checksums.o -oltp2tcp
        
 main.o: ltp2tcp.c ltp2tcp.h
        gcc -c ${CFLAGS} ${LDLIBS} --std=gnu99 ltp2tcp.c -omain.o
@@ -42,6 +42,9 @@ dccp.o: dccp_encap.c encap.h ltp2tcp.h
 
 sll.o: sll_encap.c encap.h ltp2tcp.h
        gcc -c ${CFLAGS} ${LDLIBS} --std=gnu99 sll_encap.c -osll.o
+       
+checksums.o: checksums.c checksums.h
+       gcc -c ${CFLAGS} ${LDLIBS} --std=gnu99 -c checksums.c -ochecksums.o
 
 
 install: ltptrace
diff --git a/checksums.c b/checksums.c
new file mode 100644 (file)
index 0000000..ab29590
--- /dev/null
@@ -0,0 +1,112 @@
+/******************************************************************************
+IPv4 and IPv6 Header Checksum Code
+
+Copyright (C) 2013  Samuel Jero <sj323707@ohio.edu>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Author: Samuel Jero <sj323707@ohio.edu>
+Date: 02/2013
+******************************************************************************/
+#include <string.h>
+#include <arpa/inet.h>
+#include "checksums.h"
+
+/*Stupid Solaris*/
+#ifndef u_int32_t
+#define u_int32_t uint32_t
+#endif
+#ifndef u_int16_t
+#define u_int16_t uint16_t
+#endif
+
+//Pseudo Headers for checksums
+struct ip6_pseudo_hdr{
+       u_char          src[IP6_ADDR_LEN];
+       u_char          dest[IP6_ADDR_LEN];
+       unsigned int len;
+       u_char          zero[3];
+       u_char          nxt;
+};
+struct ip4_pseudo_hdr{
+       u_char          src[IP4_ADDR_LEN];
+       u_char          dest[IP4_ADDR_LEN];
+       unsigned int len;
+       u_char          zero[3];
+       u_char          nxt;
+};
+
+/*From http://gitorious.org/freebsd/freebsd/blobs/HEAD/sbin/dhclient/packet.c
+ * under GNU GPL*/
+u_int32_t checksum(u_char *buf, unsigned nbytes, u_int32_t sum)
+{
+       int i;
+       /* Checksum all the pairs of bytes first... */
+       for (i = 0; i < (nbytes & ~1U); i += 2) {
+               sum += (u_int16_t)ntohs(*((u_int16_t *)(buf + i)));
+               if (sum > 0xFFFF)
+                       sum -= 0xFFFF;
+       }
+       /*
+        * If there's a single byte left over, checksum it, too.
+        * Network byte order is big-endian, so the remaining byte is
+        * the high byte.
+        */
+       if (i < nbytes) {
+               sum += buf[i] << 8;
+               if (sum > 0xFFFF)
+                       sum -= 0xFFFF;
+       }
+       return (sum);
+}
+
+/*From http://gitorious.org/freebsd/freebsd/blobs/HEAD/sbin/dhclient/packet.c
+ * under GNU GPL*/
+u_int32_t wrapsum(u_int32_t sum)
+{
+       sum = ~sum & 0xFFFF;
+       return (htons(sum));
+}
+
+u_int16_t ipv6_pseudohdr_chksum(u_char* buff, int len, u_char* dest, u_char* src, int type){
+       struct ip6_pseudo_hdr hdr;
+
+       //create pseudo header
+       memset(&hdr, 0, sizeof(struct ip6_pseudo_hdr));
+       memcpy(hdr.src, src, IP6_ADDR_LEN);
+       memcpy(hdr.dest, dest, IP6_ADDR_LEN);
+       hdr.nxt=type;
+       hdr.len=htonl(len);
+
+       //calculate total checksum
+       return wrapsum(checksum((unsigned char*)&hdr,sizeof(struct ip6_pseudo_hdr),checksum(buff,len,0)));
+}
+
+u_int16_t ipv4_pseudohdr_chksum(u_char* buff, int len, u_char* dest, u_char* src, int type){
+       struct ip4_pseudo_hdr hdr;
+
+       //create pseudo header
+       memset(&hdr, 0, sizeof(struct ip4_pseudo_hdr));
+       memcpy(hdr.src, src, IP4_ADDR_LEN);
+       memcpy(hdr.dest, dest, IP4_ADDR_LEN);
+       hdr.nxt=type;
+       hdr.len=htonl(len);
+
+       //calculate total checksum
+       return wrapsum(checksum((u_char*)&hdr,sizeof(struct ip4_pseudo_hdr),checksum(buff,len,0)));
+}
+
+u_int16_t ipv4_chksum(u_char* buff, int len){
+       return wrapsum(checksum(buff,len,0));
+}
diff --git a/checksums.h b/checksums.h
new file mode 100644 (file)
index 0000000..6f1088b
--- /dev/null
@@ -0,0 +1,36 @@
+/******************************************************************************
+IPv4 and IPv6 Header Checksum Code
+
+Copyright (C) 2013  Samuel Jero <sj323707@ohio.edu>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Author: Samuel Jero <sj323707@ohio.edu>
+Date: 02/2013
+******************************************************************************/
+#ifndef CHECKUMS_H
+#define CHECKSUMS_H
+
+#include <ctype.h>
+#include <sys/types.h>
+
+#define IP4_ADDR_LEN   4
+#define IP6_ADDR_LEN   16
+
+u_int16_t ipv6_pseudohdr_chksum(u_char* buff, int len, u_char* dest, u_char* src, int type);
+u_int16_t ipv4_pseudohdr_chksum(u_char* buff, int len, u_char* dest, u_char* src, int type);
+u_int16_t ipv4_chksum(u_char* buff, int len);
+
+
+#endif
diff --git a/encap.c b/encap.c
index 2f08235931d94854adc8663a8859d3a8b83def2d..c841ba29e5d76098a67f3bf2b26af1626a22b4a4 100644 (file)
--- a/encap.c
+++ b/encap.c
@@ -28,6 +28,7 @@ Notes:
        2)Uses some special types from Linux (u_char, u_int32_t)
 ******************************************************************************/
 #include "ltp2tcp.h"
+#include "checksums.h"
 
 
 
@@ -74,6 +75,7 @@ int fill_eip4_encap(struct eip4_en_p *eip, const u_char* data, int dlen, struct
 /* encapsulation manipulation after conversion */
 int eip4_post(struct eip4_en_p *eip, int tlen, u_char* data){
        struct iphdr *iph;
+       struct tcphdr *tcph;
 
        /* Move data pointer to start of IPv4 header*/
        data+=sizeof(struct ether_header);
@@ -86,7 +88,17 @@ int eip4_post(struct eip4_en_p *eip, int tlen, u_char* data){
 
        /*Adjust IPv4 header to account for packet's total length*/
        iph=(struct iphdr*)data;
-       iph->tot_len=htons(sizeof(struct iphdr)+tlen);
+       iph->tot_len=htons(iph->ihl*4+tlen);
+
+       /*Compute IPv4 Checksum*/
+       iph->check=0;
+       iph->check=ipv4_chksum(data,iph->ihl*4);
+
+       /*Compute TCP Checksum*/
+       data+=iph->ihl*4;
+       tcph=(struct tcphdr*)data;
+       tcph->check=0;
+       tcph->check=ipv4_pseudohdr_chksum(data, tlen, (u_char*)&iph->daddr, (u_char*)&iph->saddr, iph->protocol);
        return 0;
 }
 
@@ -135,6 +147,10 @@ int eip4_handshake(struct eip4_en_p *eip, struct pcap_pkthdr *h){
                iph->check=htonl(0);
                iph->tot_len=htons(sizeof(struct iphdr)+sizeof(struct tcphdr)+4);
 
+               /*Compute IPv4 Checksum*/
+               iph->check=0;
+               iph->check=ipv4_chksum((u_char*)iph,iph->ihl*4);
+
                /*Build TCP header*/
                ptr+=sizeof(struct ether_header)+ sizeof(struct iphdr);
                tcph=(struct tcphdr*)ptr;
@@ -161,6 +177,11 @@ int eip4_handshake(struct eip4_en_p *eip, struct pcap_pkthdr *h){
                ptr++;
                *ptr=2;
 
+               /*Compute TCP Checksum*/
+               tcph->check=0;
+               tcph->check=ipv4_pseudohdr_chksum((u_char*)tcph,tcph->doff*4,
+                                                                               (u_char*)&iph->daddr, (u_char*)&iph->saddr, iph->protocol);
+
                /*Save To Packet Capture*/
                pcap_dump((u_char*)state.out,&nh, data);
 
@@ -188,6 +209,10 @@ int eip4_handshake(struct eip4_en_p *eip, struct pcap_pkthdr *h){
                iph->daddr=temp;
                iph->tot_len=htons(sizeof(struct iphdr)+sizeof(struct tcphdr)+4);
 
+               /*Compute IPv4 Checksum*/
+               iph->check=0;
+               iph->check=ipv4_chksum((u_char*)iph,iph->ihl*4);
+
                /*Build TCP header*/
                ptr+=sizeof(struct ether_header)+ sizeof(struct iphdr);
                tcph=(struct tcphdr*)ptr;
@@ -214,6 +239,11 @@ int eip4_handshake(struct eip4_en_p *eip, struct pcap_pkthdr *h){
                ptr++;
                *ptr=2;
 
+               /*Compute TCP Checksum*/
+               tcph->check=0;
+               tcph->check=ipv4_pseudohdr_chksum((u_char*)tcph,tcph->doff*4 ,
+                                                                       (u_char*)&iph->daddr, (u_char*)&iph->saddr, iph->protocol);
+
                /*Save To Packet Capture*/
                pcap_dump((u_char*)state.out,&nh, data);
 
@@ -237,6 +267,10 @@ int eip4_handshake(struct eip4_en_p *eip, struct pcap_pkthdr *h){
                iph->check=htonl(0);
                iph->tot_len=htons(sizeof(struct iphdr)+sizeof(struct tcphdr));
 
+               /*Compute IPv4 Checksum*/
+               iph->check=0;
+               iph->check=ipv4_chksum((u_char*)iph,iph->ihl*4);
+
                /*Build TCP header*/
                ptr+=sizeof(struct ether_header)+ sizeof(struct iphdr);
                tcph=(struct tcphdr*)ptr;
@@ -257,6 +291,11 @@ int eip4_handshake(struct eip4_en_p *eip, struct pcap_pkthdr *h){
                tcph->ack_seq=htonl(state.ack_num);
                tcph->window=htons(WIN_FACTOR);
 
+               /*Compute TCP Checksum*/
+               tcph->check=0;
+               tcph->check=ipv4_pseudohdr_chksum((u_char*)tcph,tcph->doff*4,
+                                                               (u_char*)&iph->daddr, (u_char*)&iph->saddr, iph->protocol);
+
                /*Save To Packet Capture*/
                pcap_dump((u_char*)state.out,&nh, data);
        return 0;
@@ -307,6 +346,10 @@ int eip4_fin(struct eip4_en_p *eip){
                iph->check=htonl(0);
                iph->tot_len=htons(sizeof(struct iphdr)+sizeof(struct tcphdr));
 
+               /*Compute IPv4 Checksum*/
+               iph->check=0;
+               iph->check=ipv4_chksum((u_char*)iph,iph->ihl*4);
+
                /*Build TCP header*/
                ptr+=sizeof(struct ether_header)+ sizeof(struct iphdr);
                tcph=(struct tcphdr*)ptr;
@@ -330,6 +373,11 @@ int eip4_fin(struct eip4_en_p *eip){
                /*Update Sequence Number to include the fin packet in the sequence number space*/
                state.seq_num++;
 
+               /*Compute TCP Checksum*/
+               tcph->check=0;
+               tcph->check=ipv4_pseudohdr_chksum((u_char*)tcph,tcph->doff*4,
+                                                               (u_char*)&iph->daddr, (u_char*)&iph->saddr, iph->protocol);
+
                /* Save To Packet Capture*/
                pcap_dump((u_char*)state.out,&nh, data);
 
@@ -356,6 +404,10 @@ int eip4_fin(struct eip4_en_p *eip){
                iph->daddr=temp;
                iph->tot_len=htons(sizeof(struct iphdr)+sizeof(struct tcphdr));
 
+               /*Compute IPv4 Checksum*/
+               iph->check=0;
+               iph->check=ipv4_chksum((u_char*)iph,iph->ihl*4);
+
                /*Build TCP header*/
                ptr+=sizeof(struct ether_header)+ sizeof(struct iphdr);
                tcph=(struct tcphdr*)ptr;
@@ -376,6 +428,11 @@ int eip4_fin(struct eip4_en_p *eip){
                tcph->ack_seq=htonl(state.seq_num);
                tcph->window=htons(WIN_FACTOR);
 
+               /*Compute TCP Checksum*/
+               tcph->check=0;
+               tcph->check=ipv4_pseudohdr_chksum((u_char*)tcph,sizeof(struct tcphdr),
+                                                               (u_char*)&iph->daddr, (u_char*)&iph->saddr, iph->protocol);
+
                /*Save To Packet Capture*/
                pcap_dump((u_char*)state.out,&nh, data);
 
@@ -399,6 +456,10 @@ int eip4_fin(struct eip4_en_p *eip){
                iph->check=htonl(0);
                iph->tot_len=htons(sizeof(struct iphdr)+sizeof(struct tcphdr));
 
+               /*Compute IPv4 Checksum*/
+               iph->check=0;
+               iph->check=ipv4_chksum((u_char*)iph,iph->ihl*4);
+
                /*Build TCP header*/
                ptr+=sizeof(struct ether_header)+ sizeof(struct iphdr);
                tcph=(struct tcphdr*)ptr;
@@ -419,6 +480,11 @@ int eip4_fin(struct eip4_en_p *eip){
                tcph->ack_seq=htonl(state.ack_num);
                tcph->window=htons(WIN_FACTOR);
 
+               /*Compute TCP Checksum*/
+               tcph->check=0;
+               tcph->check=ipv4_pseudohdr_chksum((u_char*)tcph,tcph->doff*4,
+                                                               (u_char*)&iph->daddr, (u_char*)&iph->saddr, iph->protocol);
+
                /*Save To Packet Capture*/
                pcap_dump((u_char*)state.out,&nh, data);
        return 0;