⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp_get.cpp

📁 通过完成接收IP层提交的报文
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// TCP_GET.cpp : Defines the entry point for the console application.
//


#include "StdAfx.h"
#include "pcap.h"
#include <stdlib.h>
#include <stdio.h>
#include <remote-ext.h>
#include "malloc.h"
#include "TCP_GET.h"

static  struct  tcp_register * tcpreg[5];
struct  tcp_linker  * tcplink[20], * tcplink_tmp;;
struct  tcpfrag	* tcpfrag_new, * tcpfrag_tmp;
static  tcplinksum=0, tcpregsum=0;

int main(int argc, char* argv[])
{   
	pcap_if_t *alldevs;
	pcap_if_t *d;
	int inum;
	int i=0,j=0,n=0;
	pcap_t *adhandle;
	char errbuf[PCAP_ERRBUF_SIZE];
	pcap_dumper_t *dumpfile;
	char  Arppacket[]="PacketCont.txt";

	firstinit();///初始化全局变量
	tcp_register_func();///自定义应用程序注册函数,表示需要进行处理的某类tcp数据报;

	/* Retrieve the device list */
	if(pcap_findalldevs(&alldevs, errbuf) == -1)
	{
		fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
		exit(1);
	}
	/* Print the list */
	for(d=alldevs; d; d=d->next)
	{
		printf("%d. %s", ++n, d->name);
		if (d->description)
			printf(" (%s)\n", d->description);
		else
			printf(" (No description available)\n");
	}
	if(n==0)
	{
		printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
		return -1;
	}
	
	printf("Enter the interface number (1-%d):",n);
	scanf("%d", &inum);
	
	if(inum < 1 || inum > n)
	{
		printf("\nInterface number out of range.\n");
		/* Free the device list */
		pcap_freealldevs(alldevs);
		return -1;
	}
	/* Jump to the selected adapter */
	for(d=alldevs, n=0; n< inum-1 ;d=d->next, n++);
	/* Open the adapter */
	if ((adhandle= pcap_open_live(d->name,	// name of the device
							 65536,			// portion of the packet to capture. 
											// 65536 grants that the whole packet will be captured on all the MACs.
							 1,				// promiscuous mode (nonzero means promiscuous)
							 1000,			// read timeout
							 errbuf			// error buffer
							 )) == NULL)
	{
		fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
		/* Free the device list */
		pcap_freealldevs(alldevs);
		return -1;
	}
    /* Check the link layer. We support only Ethernet for simplicity. */
    if(pcap_datalink(adhandle) != DLT_EN10MB)
    {
        fprintf(stderr,"\nThis program works only on Ethernet networks.\n");
        /* Free the device list */
        pcap_freealldevs(alldevs);
        return -1;
    }
   	/* Open the dump file */
	dumpfile = pcap_dump_open(adhandle, Arppacket);
	if(dumpfile==NULL)
	{
		fprintf(stderr,"\nError opening output file\n");
		return -1;
	}
    printf("\nlistening on %s... Press Ctrl+C to stop...\n\n", d->description);
	/* At this point, we don't need any more the device list. Free it */
	pcap_freealldevs(alldevs);
	/* start the capture */
	pcap_loop(adhandle, 0, packet_handler, (unsigned char *)dumpfile);
		
	pcap_close(adhandle);
	pcap_dump_close(dumpfile);
    return  0;
}

/* Callback function invoked by libpcap for every incoming packet */
void packet_handler(u_char *dumpfile, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
  struct tm* ltime;
  char timestr[16];
  ip_header* ih;			/* IPv4 header */	
  u_int ip_len;
  ethernet_header* eh;    /*ethernetpacket header*/
  u_int j=0, uh_len=0; 
  u_short iphead_len=0;
  static int order=1;
  short int returnvalue;
  u_short  flags_fo_tmp;
  short int link_posi=-1;
  eh = (ethernet_header *)pkt_data;
  eh->ether_type=ntohs(eh->ether_type);
  printf("%.2x",eh->ether_type);
  ltime=localtime(&header->ts.tv_sec);
  /* convert the timestamp to readable format */
  strftime( timestr, sizeof timestr, "%H:%M:%S", ltime);
  ih = (ip_header*)((u_char *)eh + 14);  /* 14==length of ethernet header */
  /* print timestamp and length of the packet */
  printf("Frame No:%-4d    Time: %s   TimeSpend(us): %.6d    Length(byte): %d\n",order++,timestr, header->ts.tv_usec, header->len);
  printf("以太网类型:%04x:", eh->ether_type);
   /* 获得以太网类型 */
  switch (eh->ether_type)
   {
        case 0x0800:
            printf("上层协议是IP协议\n");   
            break;
        case 0x0806:
            printf("上层协议是ARP协议");
            goto exitpoint;
        case 0x8035:
            printf("上层协议是RARP协议");
            goto exitpoint;
        default:
            printf("上层协议是其它协议:除IP/ARP/RARP协议");
			goto exitpoint;
   }   
  
  ip_len = (ih->ver_ihl & 0x0f) * 4;					// IP 报文头的长度
  ih->identification=ntohs(ih->identification);			//交换高低字节次序 
  ih->crc=ntohs(ih->crc);	
  ih->tlen=ntohs(ih->tlen);
  ih->flags_fo=ntohs(ih->flags_fo);
  flags_fo_tmp=(ih->flags_fo&0x1d00)>>10;
  flags_fo_tmp+=(ih->flags_fo&0x03ff)<<3;	
  ih->flags_fo=(ih->flags_fo&0x2000)+flags_fo_tmp;		// 上三行操作得到该分片的偏移量
  uh_len=ih->tlen-ip_len;								// IP报文总长度减去IP报文头的长度==该分组的长度
  switch (ih->proto)
   {
	 case 0x01:
      //    printf("传输层采用协议为ICMP协议");
		 break;
	 case 0x06:
           printf("传输层采用协议为TCP协议");
		   if ((ih->saddr.byte1==0)&&(ih->saddr.byte2==0)&&(ih->saddr.byte3==0)&&(ih->saddr.byte4==0)&&
    			(ih->daddr.byte1==0)&&(ih->daddr.byte2==0)&&(ih->daddr.byte3==0)&&(ih->daddr.byte4==0))
				break;		/////-1均表示不被处理的报文;
			iphead_len = (ih->ver_ihl & 0xf) * 4;
			tcpfrag_new=(tcpfrag *)((u_char*)ih + iphead_len);
			tcpfrag_new->sport=ntohs(tcpfrag_new->sport);
			tcpfrag_new->dport=ntohs(tcpfrag_new->dport);
			tcpfrag_new->seq=ntohl(tcpfrag_new->seq);
			tcpfrag_new->ack=ntohl(tcpfrag_new->ack);
			tcpfrag_new->headlen_6res_6flag=ntohs(tcpfrag_new->headlen_6res_6flag);

            ////查找TCP连接表是否已经存在该连接的信息;
			link_posi=find_tcplink(ih, pkt_data);
			if (link_posi>-1)	///// -1表示未找到连接项,>-1表示找到连接项或新建了一个连接;	
			{	
				////调用tcp重组递交上层处理,开始合流流程,提交上层;
				returnvalue=tcp_reassemble(ih, pkt_data, link_posi);  
			    switch(returnvalue) {
			    case -1:  printf("重复报文到达,丢弃数据\n");
			    	break;
			    case  0:  printf("失序报文到达,缓存数据\n");
			    	break;
			    default:  printf("提交%d 个报文\n",returnvalue);
			    }
			}			
			 break;
     case 0x11:
        //   printf("传输层采用协议为UDP协议");
           break;
     default:
       //    printf("传输层采用其它协议:除TCP/UDP/ICMP协议");
		   break;
   }
	   	
 // 截获的所有IP报文都保存到dumpfile对应的文件“PacketCont.txt”中;
exitpoint:  pcap_dump(dumpfile, header, pkt_data); 
			printf("\n****************************\n\n\n\n");
}


short int find_tcplink(ip_header* ih, const u_char *pkt_data)
{
	short int i=0, newlinkok=-1;
////tcp连接表为空时直接判定是否含有被注册和SYN==1;
	if  (tcplinksum==0)	  
	{
	 newlinkok=find_tcpreg(ih,pkt_data);
     return  newlinkok;    ////返回值>-1表示tcp连接表中有连接,需进行tcp合流;
	}
////   tcp连接表不为空时先查找是否已建立连接;//	if (tcplinksum!=0)  
	else			/////   注意补充加减连接数操作;
	{
		for(i=0;i<20;i++)   
		{
		  if (tcpfrag_new->sport!=tcplink[i]->sport)   continue;
		  if (tcpfrag_new->dport!=tcplink[i]->dport)   continue;
		  if ((ih->saddr.byte1!=tcplink[i]->saddr.byte1)||(ih->saddr.byte2!=tcplink[i]->saddr.byte2)||
			(ih->saddr.byte3!=tcplink[i]->saddr.byte3)||(ih->saddr.byte4!=tcplink[i]->saddr.byte4))
				continue;
		  if ((ih->daddr.byte1!=tcplink[i]->daddr.byte1)||(ih->daddr.byte2!=tcplink[i]->daddr.byte2)||
			(ih->daddr.byte3!=tcplink[i]->daddr.byte3)||(ih->daddr.byte4!=tcplink[i]->daddr.byte4))
				continue;
		  return  i;
		}
		if (i==20)   ///表示没有找到连接项,看是否有注册项完成新建“两个”连接;返回连接位置x,x+1;
		  {	 newlinkok=find_tcpreg(ih,pkt_data);
			 return  newlinkok;   ////返回值为请求方的存放位置,+1为返回方的存放位置;
		  }
		else
			return  i;   /////  返回值 i 为该连接在连接表中的位置;
	}	
}

//////  该tcp报文是否被注册且SYN=1,若是新连接且有注册则新建连接;

short int find_tcpreg(ip_header* ih, const u_char *pkt_data)
{
	int i=0, j=0, matchsum_sd=0, matchsum_ds=0;
	////查找tcp注册表时,可能是还没有任何连接或连接表中没有连接项;
	if ((tcpfrag_new->headlen_6res_6flag&0x0002)!=0x0002)   
		return  -1;
	for(i=0;i<tcpregsum;i++)
	{
		if (((tcpreg[i]->saddr.byte1==0)&&(tcpreg[i]->saddr.byte2==0)&&(tcpreg[i]->saddr.byte3==0)&&(tcpreg[i]->saddr.byte4==0))
			 || ((ih->saddr.byte1==tcpreg[i]->saddr.byte1)&&(ih->saddr.byte2==tcpreg[i]->saddr.byte2)&&
				(ih->saddr.byte3==tcpreg[i]->saddr.byte3)&&(ih->saddr.byte4==tcpreg[i]->saddr.byte4)))
			matchsum_sd++;
		if ((tcpreg[i]->sport==0)||(tcpfrag_new->sport==tcpreg[i]->sport))
			matchsum_sd++;
		if (((tcpreg[i]->daddr.byte1==0)&&(tcpreg[i]->daddr.byte2==0)&&(tcpreg[i]->daddr.byte3==0)&&(tcpreg[i]->daddr.byte4==0))
			 || ((ih->daddr.byte1==tcpreg[i]->daddr.byte1)&&(ih->daddr.byte2==tcpreg[i]->daddr.byte2)&&
			(ih->daddr.byte3==tcpreg[i]->daddr.byte3)&&(ih->daddr.byte4==tcpreg[i]->daddr.byte4))
		    )
			matchsum_sd++;
		if ((tcpreg[i]->dport==0)||(tcpfrag_new->dport==tcpreg[i]->dport))
			matchsum_sd++;
		if (matchsum_sd==4)   
		{
			/////查找TCP连接表,找一个连接记录项为空的位置,新建一个连接;
			for(j=0;j<20;j=j+2)
				if ((tcplink[j]->nullflag==0) &&(tcplink[j+1]->nullflag==0))
				{
					tcplink[j]->saddr=ih->saddr;
					tcplink[j]->daddr=ih->daddr;
					tcplink[j]->sport=tcpfrag_new->sport;
					tcplink[j]->dport=tcpfrag_new->dport;
					tcplink[j]->nullflag=1;
					tcplink[j]->app_process=tcpreg[i]->app_process;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -