struct pseudo_IP_header /* The pseudo IP header (checksum calc) */
{
unsigned long int source, destination;
char zero_byte, protocol;
unsigned short TCP_UDP_len;
};
/* caculate the checksum*/
unsigned short in_cksum(unsigned short *addr, int len)
{
register int nleft = len;
register unsigned short *w = addr;
register int sum = 0;
unsigned short answer = 0;
while(nleft > 1)
{
sum += *w++;
nleft -= 2;
}
if(nleft == 1)
{
*(u_char *) (&answer) = *(u_char *) w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}
/*
fix the tcp checksum
*/
void fix_tcp_checksum(unsigned char *buf)
{
char sp_pseudo_ip_construct[PKT_BUF_SIZE];
struct tcphdr *sp_help_tcp;
struct pseudo_IP_header *sp_help_pseudo;
struct iphdr *ip_hdr;
memset(sp_pseudo_ip_construct, 0, PKT_BUF_SIZE);
sp_help_tcp = (struct tcphdr *) (buf + IP_HEAD_BASE);
sp_help_pseudo = (struct pseudo_IP_header *) sp_pseudo_ip_construct;
ip_hdr = (struct iphdr *) buf;
sp_help_tcp->check = 0;
sp_help_pseudo->source = ip_hdr->saddr;
sp_help_pseudo->destination = ip_hdr->daddr;
sp_help_pseudo->zero_byte = 0;
sp_help_pseudo->protocol = 6;
sp_help_pseudo->TCP_UDP_len =
htons(ntohs(ip_hdr->tot_len) - ip_hdr->ihl * 4);
memcpy(sp_pseudo_ip_construct + 12, sp_help_tcp,
ntohs(ip_hdr->tot_len) - ip_hdr->ihl * 4);
sp_help_tcp->check =
in_cksum((unsigned short *) sp_pseudo_ip_construct,
ntohs(ip_hdr->tot_len) - ip_hdr->ihl * 4 + 12);
}