From: Samuel Jero Date: Fri, 28 Jun 2013 18:50:22 +0000 (-0400) Subject: Checksum Computation!! X-Git-Url: http://sjero.net/git/?p=ltp2tcp;a=commitdiff_plain Checksum Computation!! --- diff --git a/Makefile b/Makefile index 4cb99c2..6cfd851 100644 --- 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 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/encap.c b/encap.c index 2f08235..c841ba2 100644 --- 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;