raw sockets und checksums
-
hello,
I have started to code with raw sockets under win2k. I have succesfully construct
a ack-packet with the correct checksums, but if i construct a packet with a payload, the checksum is always incorrect( i have examined this with ethereal).please take a lock at the following sourcecodes.
--------------------------head.h-----------------------------------------------
#include <winsock2.h> #include <windows.h> #include <ws2tcpip.h> #include <stdio.h> unsigned short checksum(unsigned short *addr, int len); struct tcpheader { unsigned short int th_sport; unsigned short int th_dport; unsigned int th_seq; unsigned int th_ack; unsigned char th_x2:4, th_off:4; unsigned char th_flags; unsigned short int th_win; unsigned short int th_sum; unsigned short int th_urp; }; /* total tcp header length: 20 bytes (=160 bits) */ struct ipheader { unsigned char ip_hl:4, ip_v:4; /* this means that each member is 4 bits */ unsigned char ip_tos; unsigned short int ip_len; unsigned short int ip_id; unsigned short int ip_off; unsigned char ip_ttl; unsigned char ip_p; unsigned short int ip_sum; unsigned int ip_src; unsigned int ip_dst; }; /* total ip header length: 20 bytes (=160 bits) */ // Psuedo Header struct body { unsigned char data [40]; }; struct ps_hdr { unsigned int source_address; // Source Address => 4 Bytes unsigned int dest_address; // Destination Address => 4 Bytes unsigned char placeholder; // Place Holder => 1 Bytes unsigned char protocol; // Protocol => 1 Bytes unsigned short tcp_length; // TCP Length => + 2 Bytes struct tcpheader tcp; struct body data; };
---------------------------------EOF-----------------------------------------
--------------------------------main.cpp-----------------------------------
#include "head.h" #define PORT 25 int main (void) { WSADATA wsd; char *datagram=""; int bOpt = 1; char info[30] ="das ist ein test"; if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) { printf("WSAStartup() failed: %d\n", GetLastError()); return -1; } // Create a raw socket SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (s == INVALID_SOCKET) { printf("WSASocket() failed: %d\n", WSAGetLastError()); return -1; } struct ipheader *iph = (struct ipheader *) malloc(sizeof(struct ipheader)); struct tcpheader *tcph = (struct tcpheader *) malloc( sizeof (struct tcpheader)); struct body *bo = (struct body *) malloc( sizeof (struct body)); struct ps_hdr *ps = (struct ps_hdr *) malloc( sizeof (struct ps_hdr)); datagram = (char *) malloc(sizeof(struct ipheader) + sizeof(struct tcpheader)+sizeof (struct body)); struct sockaddr_in sin; iph= (struct ipheader *) datagram; tcph= (struct tcpheader *) (datagram+ sizeof(struct ipheader)); bo= (struct body *) (datagram+sizeof(struct ipheader)+ sizeof(struct tcpheader)); memset(bo->data,'\0',strlen((char *)bo->data)); sin.sin_family = AF_INET; sin.sin_port = htons (PORT); sin.sin_addr.s_addr = inet_addr ("193.99.144.71"); printf("%i\n",sizeof(datagram)); iph->ip_hl = 5; iph->ip_v = 4; iph->ip_tos = 0; iph->ip_len = sizeof (struct ipheader) + sizeof (struct tcpheader)+sizeof(struct body); iph->ip_id = 1; iph->ip_off = 0; iph->ip_ttl = 255; iph->ip_p = 6; iph->ip_sum = 0; iph->ip_src = inet_addr ("192.168.0.113"); iph->ip_dst = sin.sin_addr.s_addr; tcph->th_sport = htons (1234); tcph->th_dport = htons (PORT); tcph->th_seq = rand(); tcph->th_ack = htons (6234); tcph->th_x2 = 0; tcph->th_off = 5; tcph->th_flags = 16; // SYN tcph->th_win = htons(65535); tcph->th_sum = 0; tcph->th_urp = 0; // Build the Psuedo Header ps->source_address = inet_addr ("192.168.0.113"); ps->dest_address = sin.sin_addr.s_addr; ps->placeholder = 0; ps->protocol = IPPROTO_TCP; ps->tcp_length = htons(sizeof(struct tcpheader)+sizeof(struct body)); ps->tcp = *tcph; ps->data=*bo; strcpy((char *)bo->data,info); // Calculate Checksum tcph->th_sum = checksum((unsigned short *)ps, sizeof(struct ps_hdr)); iph->ip_sum = checksum((unsigned short *)iph, sizeof(struct ipheader)); // ENABLE IPHDRINCL if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt)) == SOCKET_ERROR) { printf("setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError()); return -1; } // Send The Packet if (sendto(s, datagram, iph->ip_len, 0, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR) { printf("sendto() failed: %d\n", WSAGetLastError()); return -1; } return 0; }
------------------------------------------EOF--------------------------------
--------------------------------------check.cpp----------------------------
#include "head.h" unsigned short checksum(unsigned short *addr, int len) { register int sum = 0; u_short answer = 0; register u_short *w = addr; register int nleft = len; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) { *(u_char *) (&answer) = *(u_char *) w; sum += answer; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff);/* add hi 16 to low 16 */ sum += (sum >> 16);/* add carry */ answer = ~sum;/* truncate to 16 bits */ return (answer); }
----------------------------------EOF-------------------------------------