from this site: http://www.enderunix.org/docs/en/rawipspoof/
I pulled the following functions
unsigned short in_cksum(unsigned short *addr, int len)
{
int nleft = len;
int sum = 0;
unsigned short *w = addr;
unsigned short answer = 0;
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
if (nleft == 1) {
*(unsigned char *) (&answer) = *(unsigned char *) w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}
unsigned short in_cksum_tcp(int src, int dst, unsigned short *addr, int len)
{
struct psd_tcp buf;
u_short ans;
memset(&buf, 0, sizeof(buf));
buf.src.s_addr = src;
buf.dst.s_addr = dst;
buf.pad = 0;
buf.proto = IPPROTO_TCP;
buf.tcp_len = htons(len);
memcpy(&(buf.tcp), addr, len);
ans = in_cksum((unsigned short *)&buf, 12 + len);
return (ans);
}
However, when I run this against incoming TCP packets that I am seeing, I do not get the same checksum result as they currently have ( I save the incoming TCP checksum and set the one on the packet to zero before trying to run the checksum function)
Now, when I run "in_cksum" against the IP header, I get the right answer.
Here is the TCP psuedo header from that site:
struct psd_tcp {
struct in_addr src;
struct in_addr dst;
unsigned char pad;
unsigned char proto;
unsigned short tcp_len;
struct tcphdr tcp;
};
Is it missing something to make this work?
Well, your main mistake is forgetting to include the TCP payload in the checksum calculation, just the header (oops). See RFC 793, Section 3.1 (http://www.ietf.org/rfc/rfc793.txt) for a description of this:
The checksum field is the 16 bit one's complement of the one's complement sum of all 16 bit words in the header and text.
Of course this is me assuming that the 'len' argument is the length of the TCP header; if it includes the payload then you've got different problems (memcpy to a buffer smaller than the source...).
Note that when you are checksumming the payload, there's another little thing in the RFC that's easy to miss:
If a segment contains an odd number of header and text octets to be checksummed, the last octet is padded on the right with zeros to form a 16 bit word for checksum purposes.
Just remember to pad the payload with zeroes as necessary before computing your checksum.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With