You are not logged in.
I want to simulate tcp three-way handshake,I find
the first handshake SYN=1 is success,because the server
gives me the right packet ACK=SYN=1,and then I the third handshake,
but it always display overtime,I want to know how to correct?
I run in Linux.
Look:
#define DESTPORT 80
#define LOCALPORT 8888
/* Buffer Size */
#define SND_BUF_SIZE 1024*5
/* Buffer */
static int g_iSendBufSize = SND_BUF_SIZE;
static int g_iRecvBufSize = SND_BUF_SIZE;
static unsigned long seqno,ackno;//save sequence no and ackment no
extern int errno;
/* Prseuheader */
struct prseuheader
{
unsigned long s_addr;
unsigned long d_addr;
unsigned char zero;
unsigned char prototp;
unsigned short len;
};
/* IP Head */
struct IP_Head
{
unsigned char length:4;
unsigned char version:4;
unsigned char tos;
unsigned short total_length;
unsigned short id;
unsigned short flagoff;
unsigned char ttl;
unsigned char protocol;
unsigned short chksum;
unsigned int source;
unsigned int dest;
};
/* TCP Head */
struct TCP_Head
{
unsigned short source_port;
unsigned short dest_port;
unsigned int seqno;
unsigned int ackno;
unsigned char rev1:4;
unsigned char len:4;
unsigned char fin:1;
unsigned char syn:1;
unsigned char rst:1;
unsigned char psh:1;
unsigned char ack:1;
unsigned char urg:1;
unsigned char rev2:2;
unsigned short winsize;
unsigned short chksum;
unsigned short urgent;
};
/* Check sum */
unsigned short checksum(unsigned short* buffer, int size)
{
unsigned long cksum = 0;
while(size>1)
{
cksum += *buffer++;
size -= 2;
}
if(size)
{
cksum += *(u_char*)buffer;
}
cksum = (cksum>>16) + (cksum&0xffff);
cksum += (cksum>>16);
return (unsigned short)(~cksum);
}
//Create SOCK_RAW
int creat_raw()
{
int sk;
sk=socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
if(sk<0)
{
strerror(errno);
return -1;
}
return sk;
}
//Set sock option
int set_option(int sk)
{
int iRet,on;
on=1;
iRet = setsockopt(sk, IPPROTO_IP, IP_HDRINCL,&on,sizeof(on));
if (iRet<0)
{
strerror(errno);
return -1;
}
return 0;
}
/* fill ip head */
int fill_iph(unsigned char buffer[])
{
struct IP_Head *pIph;
int total_len=sizeof(struct IP_Head)+sizeof(struct TCP_Head);
pIph=(struct IP_Head*)buffer;
pIph->length =5;
pIph->version =4;
pIph->tos =0;
pIph->total_length=htons(total_len);
pIph->id =0;
pIph->flagoff =htons(0x4000);
pIph->ttl =255;
pIph->protocol=6;
pIph->chksum =0;
pIph->source =inet_addr("192.168.30.128"); //Local PC
pIph->dest =inet_addr("192.168.1.6"); //remote PC
pIph->chksum =checksum((unsigned short*)pIph,sizeof(struct IP_Head));
return 0;
}
/* fill tcp head */
int fill_tcp(unsigned char buffer[],unsigned char control)
{
struct TCP_Head *pTcph;
pTcph=(struct TCP_Head*)(buffer+sizeof(struct IP_Head));
pTcph->source_port =htons(LOCALPORT);
pTcph->dest_port =htons(DESTPORT);
pTcph->seqno =htonl(seqno);
pTcph->ackno =htonl(ackno);
pTcph->rev1 =0;
pTcph->len =5;
pTcph->fin =control&0x01 ?1:0;
pTcph->syn =control&0x02 ?1:0;
pTcph->rst =control&0x04 ?1:0;
pTcph->psh =control&0x10 ?1:0;
pTcph->ack =control&0x20 ?1:0;
pTcph->urg =control&0x40 ?1:0;
pTcph->rev2 =0;
pTcph->winsize =htons(1000);
pTcph->chksum =0;
pTcph->urgent =0;
return 0;
}
//send tcp packet
int sendto_packet(int sk,unsigned char buffer[])
{
int iRet;
struct IP_Head *pIph;
struct TCP_Head *pTcph;
struct prseuheader theheader;
char tcpbuff[32]; //it include prseuheader and tcp head
int total_len=sizeof(struct IP_Head)+sizeof(struct TCP_Head);
struct sockaddr_in addr;
pIph=(struct IP_Head*)buffer;
pTcph=(struct TCP_Head*)(buffer+sizeof(struct IP_Head));
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=pIph->dest;
addr.sin_port=htons(DESTPORT);
bzero(tcpbuff,32);
theheader.s_addr = pIph->source;
theheader.d_addr = pIph->dest;
theheader.zero = 0;
theheader.prototp = 6;
theheader.len = htons(20); //the size of TCP head
memcpy(tcpbuff,&theheader,12);
memcpy(tcpbuff+12,pTcph,20);
pTcph->chksum=0;
pTcph->chksum=checksum((unsigned short *)tcpbuff,32);
iRet=sendto(sk,buffer,total_len,0,(struct sockaddr*)&addr,sizeof(struct sockaddr_in));
if(iRet<0)
{
strerror(errno);
return -1;
}
return 0;
}
//receive tcp packet and display IP Head and TCP Head
int recvfrom_packet(int sk,unsigned char buffer[])
{
int iRet;
int lenfrom=sizeof(struct sockaddr_in);
struct sockaddr_in addr;
struct in_addr in;
struct IP_Head *pIph;
struct TCP_Head *pTcph;
fd_set fdR;
struct timeval timeout;
//Set Non-block
bzero(&addr,sizeof(struct sockaddr_in));
timeout.tv_sec=5;
timeout.tv_usec=0;
FD_ZERO(&fdR);
FD_SET(sk,&fdR);
iRet=select(sk+1,&fdR,NULL,NULL,&timeout);
if(iRet<=0)
{
strerror(errno);
printf("%d\n",iRet); //the third,the codes always display 0,it mean overtime
return -1;
}
else
{
iRet=recvfrom(sk,buffer,g_iRecvBufSize,0,(struct sockaddr*)&addr,&lenfrom);
if(iRet<0)
{
printf("error recvfrom\n");
return -1;
}
else
{
//Display IP Head
pIph=(struct IP_Head*)buffer;
printf("Parse IP......\n");
printf("length:%x\n",pIph->length);
printf("version:%x\n",pIph->version);
printf("tos:%x\n",pIph->tos);
printf("total_length:%d\n",ntohs(pIph->total_length));
printf("id:%d\n",ntohs(pIph->id));
printf("flagoff:%x\n",ntohs(pIph->flagoff));
printf("ttl:%d\n",pIph->ttl);
printf("protocol:%d\n",pIph->protocol);
printf("cksum:%x\n",ntohs(pIph->chksum));
in.s_addr=pIph->source;
printf("SIP:%s\n",inet_ntoa(in));
in.s_addr=pIph->dest;
printf("DIP:%s\n",inet_ntoa(in));
//Display TCP Head
pTcph=(struct TCP_Head*)(buffer+pIph->length*4);
printf("Parse TCP......\n");
printf("source_port:%d\n",ntohs(pTcph->source_port));
printf("dest_port:%d\n",ntohs(pTcph->dest_port));
printf("seqno:%d\n",ntohl(pTcph->seqno));
printf("ackno:%d\n",ntohl(pTcph->ackno));
printf("len:%d\n",pTcph->len);
printf("fin:%d\n",pTcph->fin);
printf("syn:%d\n",pTcph->syn);
printf("rst:%d\n",pTcph->rst);
printf("psh:%d\n",pTcph->psh);
printf("ack:%d\n",pTcph->ack);
printf("urg:%d\n",pTcph->urg);
printf("winsize:%d\n",ntohs(pTcph->winsize));
printf("urgent:%d\n",ntohs(pTcph->urgent));
printf("\n");
seqno=ntohl(pTcph->seqno);
ackno=ntohl(pTcph->ackno);
return 0;
}//else
}//else
}
//Main
int main()
{
int sk;
unsigned char buffers[g_iSendBufSize]; //send buffer
unsigned char bufferr[g_iRecvBufSize]; //receive buffer
int iRet;
unsigned long temp;
sk=creat_raw();
if(sk<0)
{
printf("Creat socket error.\n");
return -1;
}
iRet=set_option(sk);
if(iRet<0)
{
printf("Set socket option error.\n");
close(sk);
return -1;
}
//the first
bzero(buffers,g_iSendBufSize);
bzero(bufferr,g_iRecvBufSize);
fill_iph(buffers);
seqno=0;
ackno=0;
fill_tcp(buffers,0x02);
iRet=sendto_packet(sk,buffers);
if(iRet<0)
{
printf("Sendto_packet error.\n");
close(sk);
return -1;
}
iRet=recvfrom_packet(sk,bufferr);
if(iRet<0)
{
printf("Recvfrom_packet error.\n");
printf("time is over or error opertion \n");
close(sk);
return -1;
}
//the third
bzero(buffers,g_iSendBufSize);
bzero(bufferr,g_iRecvBufSize);
fill_iph(buffers);
temp=seqno;
seqno=ackno;
ackno=temp+1;
fill_tcp(buffers,0x10);
iRet=sendto_packet(sk,buffers);
if(iRet<0)
{
printf("Sendto_packet error.\n");
close(sk);
return -1;
}
iRet=recvfrom_packet(sk,bufferr);
if(iRet<0)
{
printf("Recvfrom_packet error.\n");
printf("time is over or error opertion \n");
close(sk);
return -1;
}
close(sk);
return 0;
Offline
You send the first handshake SYN=1 by SOCK_RAW, the packet does not go through L4, and the
8888 port is not open. When the linux get the server's ACK=SYN=1 packet, it does not recogise the packet in L4,
so it send a RST=1 packet to the server, and the server close the connect. You will never get what
you want.
Last edited by weiwei (2013-07-03 09:49:22)
Offline