?
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-------------------------------------