📄 tcp_get.cpp
字号:
// 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 + -