Hi
I have a problem with raw socket. I want send SYN packet but I have a problem with checksum. When I send the packet to second komputer I see it in ethereal on the second computer( on the close port), but it shows that the packet has Incorect checksum. And the second komputer don't send packet to my kmoputer ( I have no reply ACK).I build RAW SOCKET like bellow:
#include <netdb.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
//15
struct psd_tcp
{
struct in_addr src;
struct in_addr dst;
unsigned char pad;
unsigned char proto;
unsigned short tcp_len;
struct tcphdr tcp;
};
unsigned short in_cksum_tcp(int src, int dst, unsigned short *addr, int len)
{
struct psd_tcp buf;
u_short ans;
printf("\nrozmiar in_cksum: %d, %d \n",sizeof(struct psd_tcp),sizeof(buf));
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);
}
unsigned short in_cksum(unsigned short *addr, int len)
{
register int sum = 0;
u_short answer = 0;
register u_short *w = addr;
register int nleft = len;
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);
}
int main( int argc, char **argv)
{
int sd;
struct ip ip;
printf("\nrozmiar: %d, %d\n",sizeof(ip),sizeof(struct ip));
struct tcphdr tcp;
const int on = 1;
struct sockaddr_in sin;
u_char *packet;
packet = (u_char *)malloc(60);
ip.ip_hl = 0x5;
ip.ip_v = 0x4;
ip.ip_tos = 0x0;
ip.ip_len = sizeof(struct ip) + sizeof(struct tcphdr);
ip.ip_id = htons(12830);
ip.ip_off = 0x0;
ip.ip_ttl = 64;
ip.ip_p = IPPROTO_TCP;
ip.ip_sum = 0x0;
ip.ip_src.s_addr = inet_addr("192.168.2.9");
ip.ip_dst.s_addr = inet_addr("192.168.2.33");
ip.ip_sum = in_cksum((unsigned short *)&ip, sizeof(ip));
memcpy(packet, &ip, sizeof(ip));
tcp.source = htons(3333);
tcp.dest = htons(445);
tcp.seq = htonl(0x131123);
tcp.doff = sizeof(struct tcphdr)/4;
//tcp.flags = TH_SYN;
tcp.syn = 1;
tcp.ack = 0;
tcp.psh = 0;
tcp.urg = 0;
tcp.fin = 0;
tcp.rst = 0;
tcp.window = htons(32768);
tcp.check = 0;
tcp.check = in_cksum_tcp(ip.ip_src.s_addr, ip.ip_dst.s_addr, (unsigned short *)&tcp, sizeof(tcp));
memcpy((packet + sizeof(ip)),&tcp, sizeof(tcp));
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ip.ip_dst.s_addr;
if((sd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0)
{
perror("socket()");
return 0;
}
setsockopt(sd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));
if(sendto(sd, packet, 60, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0)
{
perror("sendto()");
exit(1);
}
/* if((recv(sd, packet, sizeof(packet),0))==-1)
{
perror("recv()");
exit(1);
}*/
if((recvfrom(sd, packet, sizeof(packet), 0, NULL, 0))==-1)
{
perror("recvfrom()");
exit(1);
}
return 0;
}
this is exactly my code. I run it after debian.It hasn't errors, but have several warnings :
syn3.c: In function `in_cksum_tcp':
syn3.c:33: warning: implicit declaration of function `memset'
syn3.c:39: warning: implicit declaration of function `memcpy'
syn3.c:40: warning: implicit declaration of function `in_cksum'
syn3.c: At top level:
syn3.c:45: warning: type mismatch with previous implicit declaration
syn3.c:40: warning: previous implicit declaration of `in_cksum'
syn3.c:45: warning: `in_cksum' was previously implicitly declared to return `int'
I think that 'Implicity declaration' is beacuse the functions are under int main(). I realy don't know why the cksum is bad I copy out cksum's code from other side.
Best Regards
bndifek