]> sjero.net Git - dccp2tcp/commitdiff
Checksum computation!
authorSamuel Jero <sj323707@ohio.edu>
Sun, 3 Feb 2013 05:21:52 +0000 (00:21 -0500)
committerSamuel Jero <sj323707@ohio.edu>
Sun, 3 Feb 2013 05:21:52 +0000 (00:21 -0500)
Makefile
README
ccid2.c
checksums.c [new file with mode: 0644]
checksums.h [new file with mode: 0644]
dccp2tcp.c
dccp2tcp.h
dccp2tcp.pod
encap.c

index c48aa22390b07a009590c5301ac809a8e8f1176b..6a534c997784ac861e8c936b92180a9d6f3d0053 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -22,8 +22,8 @@ MANDIR = /usr/local/man
 
 all: dccp2tcp dccp2tcp.1
 
-dccp2tcp: dccp2tcp.o encap.o connections.o ccid2.o
-       gcc ${CFLAGS} ${LDLIBS} --std=gnu99 dccp2tcp.o encap.o connections.o ccid2.o -odccp2tcp
+dccp2tcp: dccp2tcp.o encap.o connections.o ccid2.o checksums.o
+       gcc ${CFLAGS} ${LDLIBS} --std=gnu99 dccp2tcp.o encap.o connections.o ccid2.o checksums.o -odccp2tcp
 
 dccp2tcp.o: dccp2tcp.h dccp2tcp.c
        gcc ${CFLAGS} ${LDLIBS} --std=gnu99 -c dccp2tcp.c -odccp2tcp.o
@@ -36,6 +36,9 @@ ccid2.o: ccid2.c dccp2tcp.h
        
 connections.o: dccp2tcp.h connections.c
        gcc ${CFLAGS} ${LDLIBS} --std=gnu99 -c connections.c -oconnections.o
+       
+checksums.o: checksums.c checksums.h
+       gcc ${CFLAGS} ${LDLIBS} --std=gnu99 -c checksums.c -ochecksums.o
 
 dccp2tcp.1: dccp2tcp.pod
        pod2man -s 1 -c "dccp2tcp" dccp2tcp.pod > dccp2tcp.1
diff --git a/README b/README
index f0fc8c2cd42104b194bda107e86b83d1b55f4836..68c09cad12b5cab0b3e07b54521b1fc9403d9c8d 100644 (file)
--- a/README
+++ b/README
@@ -36,9 +36,8 @@ xplot a2b_tsg.xpl a2b_rtt.xpl
 This program does have several important limitations:
        1)CCID2 ONLY
        2)DCCP MUST use 48 bit sequence numbers.
-       3)Checksums are not computed (they are zeroed).
-       4)DCCP DATA packets are not implemented (Linux doesn't use them)
-       5)DCCP Ack packets show up as TCP packets containing one byte
+       3)DCCP DATA packets are not implemented (Linux doesn't use them)
+       4)DCCP Ack packets show up as TCP packets containing one byte
 
 
 dccp2tcp is free software: you can redistribute it and/or modify
diff --git a/ccid2.c b/ccid2.c
index 677ce3ef9dd97f4dec926e496dfb7a5e3c6237e1..f8ebb2e57cdb856c92166ed0516f6b9c53e0a0e4 100644 (file)
--- a/ccid2.c
+++ b/ccid2.c
@@ -2,7 +2,7 @@
 Utility to convert a DCCP flow to a TCP flow for DCCP analysis via
                tcptrace.
 
-Copyright (C) 2012  Samuel Jero <sj323707@ohio.edu>
+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
@@ -18,14 +18,13 @@ 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: 11/2012
+Date: 02/2013
 
 Notes:
        1)CCID2 ONLY
        2)DCCP MUST use 48 bit sequence numbers
-       3)Checksums are not computed (they are zeroed)
-       4)DCCP DATA packets are not implemented (Linux doesn't use them)
-       5)DCCP Ack packets show up as TCP packets containing one byte
+       3)DCCP DATA packets are not implemented (Linux doesn't use them)
+       4)DCCP Ack packets show up as TCP packets containing one byte
 ******************************************************************************/
 #include "dccp2tcp.h"
 
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
index f7756612ea9130851974a2490306924dbd03f6ba..fb648cf2f8e4508f56eb71264a8295d6a4c41ce6 100644 (file)
@@ -23,9 +23,8 @@ Date: 11/2012
 Notes:
        1)CCID2 ONLY
        2)DCCP MUST use 48 bit sequence numbers
-       3)Checksums are not computed (they are zeroed)
-       4)DCCP DATA packets are not implemented (Linux doesn't use them)
-       5)DCCP Ack packets show up as TCP packets containing one byte
+       3)DCCP DATA packets are not implemented (Linux doesn't use them)
+       4)DCCP Ack packets show up as TCP packets containing one byte
 ******************************************************************************/
 #include "dccp2tcp.h"
 
@@ -204,6 +203,7 @@ return;
 /*do all the dccp to tcp conversions*/
 int convert_packet(struct packet *new, const struct const_packet* old)
 {
+       struct tcphdr                           *tcph;
        struct dccp_hdr                         *dccph;
        struct dccp_hdr_ext             *dccphex;
        struct host                                     *h1=NULL;
@@ -221,6 +221,7 @@ int convert_packet(struct packet *new, const struct const_packet* old)
        }
 
        /*cast header pointers*/
+       tcph=(struct tcphdr*)new->data;
        dccph=(struct dccp_hdr*)old->data;
        dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
 
@@ -246,13 +247,32 @@ int convert_packet(struct packet *new, const struct const_packet* old)
 
        /*TODO: Add CCID detection*/
        if(h1->type==CCID2 && h2->type==CCID2){
-               return ccid2_convert_packet(new,old);
+               if(ccid2_convert_packet(new,old)==0){
+                       return 0;
+               }
        }
        if(h1->type==CCID3 && h2->type==CCID3){
-               //return ccid3_convert_packet(new,old);
+               //ccid3_convert_packet(new,old);
+       }
+       if(ccid2_convert_packet(new,old)==0){
+               return 0;
+       }
+
+       /*Compute TCP checksums*/
+       if(new->id_len==IP4_ADDR_LEN){
+                       tcph->check=0;
+                       tcph->check=ipv4_pseudohdr_chksum(new->data,
+                                       new->length, new->dest_id, new->src_id, 6);
+       }else if(new->id_len==IP6_ADDR_LEN){
+                       tcph->check=0;
+                       tcph->check=ipv6_pseudohdr_chksum(new->data,
+                                       new->length, new->dest_id, new->src_id, 6);
+       }else{
+               tcph->check=0;
+               dbgprintf(2,"Unknown ID Length, can't do checksums");
        }
 
-       return ccid2_convert_packet(new,old);
+       return 1;
 }
 
 void version(){
index 62b2e998a298c0272e1eadc5962b00a107eb2c97..e3b373ccc1d369c46935b8c935bcb0307fe7c564 100644 (file)
@@ -23,9 +23,8 @@ Date: 11/2012
 Notes:
        1)CCID2 ONLY
        2)DCCP MUST use 48 bit sequence numbers
-       3)Checksums are not computed (they are zeroed)
-       4)DCCP DATA packets are not implemented (Linux doesn't use them)
-       5)DCCP Ack packets show up as TCP packets containing one byte
+       3)DCCP DATA packets are not implemented (Linux doesn't use them)
+       4)DCCP Ack packets show up as TCP packets containing one byte
 ******************************************************************************/
 #ifndef _DCCP2TCP_H
 #define _DCCP2TCP_H
@@ -53,6 +52,7 @@ Notes:
 #include <ctype.h>
 #include <pcap.h>
 #include <linux/dccp.h>
+#include "checksums.h"
 
 
 #define MAX_PACKET     1600    /*Maximum size of TCP packet */
index e5b4336858d08fdb2c31cbaf4805598fc96f305f..4976902e0adf8f67c75542ca25ff96a7116492c7 100644 (file)
@@ -15,8 +15,7 @@ In order to utilize this program effectively you will also need B<tcptrace>, whi
 from http://www.tcptrace.org and the version of B<xplot> available from http://www.tcptrace.org under
 "Useful Companion Programs".
 
-B<dccp2tcp> only supports DCCP CCID 2 with 48 bit sequence numbers at this time. Further, checksums are
-not computed on the output packets---they are simply zeroed.
+B<dccp2tcp> only supports DCCP CCID 2 with 48 bit sequence numbers at this time.
 
 =head1 OPTIONS
 
diff --git a/encap.c b/encap.c
index f729878763594e9ceb9d5f6f5809f1670f4793ee..f583f0994303568d4aeb2d62ffc19f99a7e594aa 100644 (file)
--- a/encap.c
+++ b/encap.c
@@ -23,12 +23,12 @@ Date: 11/2012
 Notes:
        1)CCID2 ONLY
        2)DCCP MUST use 48 bit sequence numbers
-       3)Checksums are not computed (they are zeroed)
-       4)DCCP DATA packets are not implemented (Linux doesn't use them)
-       5)DCCP Ack packets show up as TCP packets containing one byte
+       3)DCCP DATA packets are not implemented (Linux doesn't use them)
+       4)DCCP Ack packets show up as TCP packets containing one byte
 ******************************************************************************/
 #include "dccp2tcp.h"
 #include "encap.h"
+#include "checksums.h"
 #include <pcap/sll.h>
 #include <netinet/ip6.h>
 
@@ -279,6 +279,10 @@ int ipv4_encap(struct packet *new, const struct const_packet *old)
                /*Adjust IPv4 header to account for packet's total length*/
                iph->tot_len=htons(new->length);
 
+               /*Compute IPv4 Checksum*/
+               iph->check=0;
+               iph->check=ipv4_chksum(new->data,iph->ihl*4);
+
                /*Cleanup*/
                free(nnew.src_id);
                free(nnew.dest_id);