TCP Checksum errors
by OffByMan from LinuxQuestions.org on (#6PV45)
Hello, I am currently having trouble with TCP Checksums. According to wireshark the IP Checksum is correct, but the TCP Checksum is not, and they use the same function. I have made sure to disable any TCP offloading in case that was the issue, but it has not helped. I am getting stumped at this point. Here is the code snippet below if anyone has any ideas of what may be causing the issue. Sorry if the code is messy, I am new to C and was creating this to get some practice. Thank you so much in advance!
---SNIP----
char *arg4 = argv[4];
char *f;
int total = 0;
char *end = NULL;
f = strtok(arg4,"/");
char datagram[4096], source_ip[32], *data, *pseudogram;
struct iphdr *iph = (struct iphdr *) datagram;
struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip));
struct sockaddr_in sin;
struct pseudo_header psh;
while(f != NULL){
printf("The User flags: %s\n",f);
if (strcmp(f,"FIN") == 0) {
total |= TH_FIN;
}
if (strcmp(f,"SYN") == 0) {
total |= TH_SYN;
}
if (strcmp(f,"RST") == 0) {
total |= TH_RST;
}
if (strcmp(f,"PSH") == 0) {
total |= TH_PSH;
}
if (strcmp(f,"ACK") == 0) {
total |= TH_ACK;
}
if (strcmp(f,"URG") == 0) {
total |= TH_URG;
}
f = strtok(NULL,"/");
}
printf("\nHost: %s\n\n", argv[1]);
for(i = 0; i <= len; ++i)
{
char portStr[6];
snprintf(portStr,sizeof(portStr),"%d", portList[i]);
int rawsock = socket(PF_INET,SOCK_RAW,IPPROTO_RAW);
if (rawsock < 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rawsock));
puts("Failed to create socket\n");
exit(EXIT_FAILURE);
}
memset(datagram, 0, 4096);
data = datagram + sizeof(struct iphdr) + sizeof(struct tcphdr);
//strcpy(data, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
short portcon = atoi(portStr);
strcpy(source_ip, "192.168.1.6");
sin.sin_family = AF_INET;
sin.sin_port = htons(portcon);
sin.sin_addr.s_addr = inet_addr (argv[1]);
//Fill in the IP header
iph ->ihl = 5;
iph ->version = 4;
iph -> tos = 0;
iph -> tot_len = sizeof(struct iphdr) + sizeof (struct tcphdr) + strlen(data);
iph -> id = htonl (54321);
iph -> frag_off = 0;
iph -> ttl = 255;
iph -> protocol = IPPROTO_TCP;
iph -> check = 0;
iph -> saddr = inet_addr (source_ip);
iph -> daddr = sin.sin_addr.s_addr;
iph -> check = csum((unsigned short *) datagram, iph -> tot_len);
tcph->source = htons (39192);
tcph->dest = htons (portcon);
tcph->seq = 1;
tcph->ack_seq = 0;
tcph->doff = 5;//tcp header size
tcph->fin = (total & TH_FIN) ? 1 : 0;
tcph->syn = (total & TH_SYN) ? 1 : 0;
tcph->rst = (total & TH_RST) ? 1 : 0;
tcph->psh = (total & TH_PUSH) ? 1 : 0;
tcph->ack = (total & TH_ACK) ? 1 : 0;
tcph->urg = (total & TH_URG) ? 1 : 0;
tcph->window = htons (5840);
tcph->check = 0;
tcph->urg_ptr = 0;
//Now the TCP checksum
psh.source_address = inet_addr(source_ip);
psh.dest_address = inet_addr("192.168.1.1");
psh.placeholder = 0;
psh.protocol = IPPROTO_RAW;
psh.tcp_length = sizeof(struct tcphdr) + strlen(data);
int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr)+ strlen(data);
pseudogram = malloc(psize);
memcpy(pseudogram , (char*) &psh , sizeof (struct pseudo_header));
memcpy(pseudogram + sizeof(struct pseudo_header) , tcph , sizeof(struct tcphdr) + strlen(data));
tcph->check = htons(csum((unsigned short*) pseudogram , psize));
int one = 1;
free(pseudogram);
if (setsockopt (rawsock, IPPROTO_IP, IP_HDRINCL, &one, sizeof (one)) < 0)
{
perror("Error setting IP_HDRINCL");
close(sock);
exit(0);
}
if (sendto (rawsock, datagram, iph->tot_len ,0, (struct sockaddr *) &sin, sizeof (sin)) < 0)
{
perror("sendto failed");
}
else
{
printf("Packet sent to port %s\n", portStr);
close(sock);
}
sleep(1);
}
}
---Checksum function---
unsigned short csum(unsigned short *ptr, int nbytes){
long sum;
unsigned short oddbyte;
unsigned short answer;
sum = 0;
while(nbytes >1 ){
sum += *ptr++;
nbytes -= 2;
}
if(nbytes == 1){
oddbyte = 0;
*((u_char*)&oddbyte)=*(u_char*)ptr;
sum+=oddbyte;
}
sum = (sum>>16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}
---SNIP----
char *arg4 = argv[4];
char *f;
int total = 0;
char *end = NULL;
f = strtok(arg4,"/");
char datagram[4096], source_ip[32], *data, *pseudogram;
struct iphdr *iph = (struct iphdr *) datagram;
struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip));
struct sockaddr_in sin;
struct pseudo_header psh;
while(f != NULL){
printf("The User flags: %s\n",f);
if (strcmp(f,"FIN") == 0) {
total |= TH_FIN;
}
if (strcmp(f,"SYN") == 0) {
total |= TH_SYN;
}
if (strcmp(f,"RST") == 0) {
total |= TH_RST;
}
if (strcmp(f,"PSH") == 0) {
total |= TH_PSH;
}
if (strcmp(f,"ACK") == 0) {
total |= TH_ACK;
}
if (strcmp(f,"URG") == 0) {
total |= TH_URG;
}
f = strtok(NULL,"/");
}
printf("\nHost: %s\n\n", argv[1]);
for(i = 0; i <= len; ++i)
{
char portStr[6];
snprintf(portStr,sizeof(portStr),"%d", portList[i]);
int rawsock = socket(PF_INET,SOCK_RAW,IPPROTO_RAW);
if (rawsock < 0)
{
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rawsock));
puts("Failed to create socket\n");
exit(EXIT_FAILURE);
}
memset(datagram, 0, 4096);
data = datagram + sizeof(struct iphdr) + sizeof(struct tcphdr);
//strcpy(data, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
short portcon = atoi(portStr);
strcpy(source_ip, "192.168.1.6");
sin.sin_family = AF_INET;
sin.sin_port = htons(portcon);
sin.sin_addr.s_addr = inet_addr (argv[1]);
//Fill in the IP header
iph ->ihl = 5;
iph ->version = 4;
iph -> tos = 0;
iph -> tot_len = sizeof(struct iphdr) + sizeof (struct tcphdr) + strlen(data);
iph -> id = htonl (54321);
iph -> frag_off = 0;
iph -> ttl = 255;
iph -> protocol = IPPROTO_TCP;
iph -> check = 0;
iph -> saddr = inet_addr (source_ip);
iph -> daddr = sin.sin_addr.s_addr;
iph -> check = csum((unsigned short *) datagram, iph -> tot_len);
tcph->source = htons (39192);
tcph->dest = htons (portcon);
tcph->seq = 1;
tcph->ack_seq = 0;
tcph->doff = 5;//tcp header size
tcph->fin = (total & TH_FIN) ? 1 : 0;
tcph->syn = (total & TH_SYN) ? 1 : 0;
tcph->rst = (total & TH_RST) ? 1 : 0;
tcph->psh = (total & TH_PUSH) ? 1 : 0;
tcph->ack = (total & TH_ACK) ? 1 : 0;
tcph->urg = (total & TH_URG) ? 1 : 0;
tcph->window = htons (5840);
tcph->check = 0;
tcph->urg_ptr = 0;
//Now the TCP checksum
psh.source_address = inet_addr(source_ip);
psh.dest_address = inet_addr("192.168.1.1");
psh.placeholder = 0;
psh.protocol = IPPROTO_RAW;
psh.tcp_length = sizeof(struct tcphdr) + strlen(data);
int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr)+ strlen(data);
pseudogram = malloc(psize);
memcpy(pseudogram , (char*) &psh , sizeof (struct pseudo_header));
memcpy(pseudogram + sizeof(struct pseudo_header) , tcph , sizeof(struct tcphdr) + strlen(data));
tcph->check = htons(csum((unsigned short*) pseudogram , psize));
int one = 1;
free(pseudogram);
if (setsockopt (rawsock, IPPROTO_IP, IP_HDRINCL, &one, sizeof (one)) < 0)
{
perror("Error setting IP_HDRINCL");
close(sock);
exit(0);
}
if (sendto (rawsock, datagram, iph->tot_len ,0, (struct sockaddr *) &sin, sizeof (sin)) < 0)
{
perror("sendto failed");
}
else
{
printf("Packet sent to port %s\n", portStr);
close(sock);
}
sleep(1);
}
}
---Checksum function---
unsigned short csum(unsigned short *ptr, int nbytes){
long sum;
unsigned short oddbyte;
unsigned short answer;
sum = 0;
while(nbytes >1 ){
sum += *ptr++;
nbytes -= 2;
}
if(nbytes == 1){
oddbyte = 0;
*((u_char*)&oddbyte)=*(u_char*)ptr;
sum+=oddbyte;
}
sum = (sum>>16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}