From 926ed1e125b42109bdc91e56ed256f26d618319b Mon Sep 17 00:00:00 2001 From: Samuel Jero Date: Sun, 3 Feb 2013 00:21:52 -0500 Subject: [PATCH] Checksum computation! --- Makefile | 7 +++- README | 5 +-- ccid2.c | 9 ++--- checksums.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++ checksums.h | 36 +++++++++++++++++ dccp2tcp.c | 32 ++++++++++++--- dccp2tcp.h | 6 +-- dccp2tcp.pod | 3 +- encap.c | 10 +++-- 9 files changed, 196 insertions(+), 24 deletions(-) create mode 100644 checksums.c create mode 100644 checksums.h diff --git a/Makefile b/Makefile index c48aa22..6a534c9 100644 --- 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 f0fc8c2..68c09ca 100644 --- 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 677ce3e..f8ebb2e 100644 --- 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 +Copyright (C) 2013 Samuel Jero 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 . Author: Samuel Jero -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 index 0000000..ab29590 --- /dev/null +++ b/checksums.c @@ -0,0 +1,112 @@ +/****************************************************************************** +IPv4 and IPv6 Header Checksum Code + +Copyright (C) 2013 Samuel Jero + +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 . + +Author: Samuel Jero +Date: 02/2013 +******************************************************************************/ +#include +#include +#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 index 0000000..6f1088b --- /dev/null +++ b/checksums.h @@ -0,0 +1,36 @@ +/****************************************************************************** +IPv4 and IPv6 Header Checksum Code + +Copyright (C) 2013 Samuel Jero + +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 . + +Author: Samuel Jero +Date: 02/2013 +******************************************************************************/ +#ifndef CHECKUMS_H +#define CHECKSUMS_H + +#include +#include + +#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/dccp2tcp.c b/dccp2tcp.c index f775661..fb648cf 100644 --- a/dccp2tcp.c +++ b/dccp2tcp.c @@ -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(){ diff --git a/dccp2tcp.h b/dccp2tcp.h index 62b2e99..e3b373c 100644 --- a/dccp2tcp.h +++ b/dccp2tcp.h @@ -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 #include #include +#include "checksums.h" #define MAX_PACKET 1600 /*Maximum size of TCP packet */ diff --git a/dccp2tcp.pod b/dccp2tcp.pod index e5b4336..4976902 100644 --- a/dccp2tcp.pod +++ b/dccp2tcp.pod @@ -15,8 +15,7 @@ In order to utilize this program effectively you will also need B, whi from http://www.tcptrace.org and the version of B available from http://www.tcptrace.org under "Useful Companion Programs". -B 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 only supports DCCP CCID 2 with 48 bit sequence numbers at this time. =head1 OPTIONS diff --git a/encap.c b/encap.c index f729878..f583f09 100644 --- 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 #include @@ -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); -- 2.39.2