You are not logged in.

#1 2012-10-30 01:30:24

leetow2003
Member
Registered: 2012-04-08
Posts: 25

How to simulate tcp three-way handshake

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

#2 2013-07-03 09:46:52

weiwei
Member
Registered: 2013-07-03
Posts: 1

Re: How to simulate tcp three-way handshake

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

Board footer

Powered by FluxBB