zoukankan      html  css  js  c++  java
  • pcap 解析

    http://wenku.baidu.com/link?url=BkRDW0md1bM_MRfJVykSTu7_Ppe4mj1Zauxfmb9_gvCFPohUpa59m-IbEq2DWGLmTr1kW_-dkAGCAIOpBhUTk6ormkcfj8vU-Zl-My4MQ9a

    该网页内容基本已经够用,下面是一些需要修改或注意的地方。

    1.

    struct pcap_pkthdr

    {

          struct timeval ts;   ts是一个结构struct timeval,它有两个部分,第一部分是1900开始以来的秒数,第二部分是当前秒之后的毫秒数

    //我的经验是微妙,即第二部分达到1000000,前部分加1.

          bpf_u_int32 caplen;  表示抓到的数据长度

          bpf_u_int32 len;    表示数据包的实际长度

    }

     以下是我部分程序结果:第二列是发送给IP(第一列的第一个udp包的时间),第三列是在发送包后从IP接收到的第一个udp包的时间,第三列是后者减前者,理论上第三列值为正数,但是出现负数,是因为我计算时先秒数相减*1000,在加上毫秒数,

    但实际上应该秒数之差*1000,000 +第二部分时间差。

    110.153.127.193:asnaacceler8db    1403334193:459623    1403334203:546418    96795
    110.247.139.26:27234    1403334343:455958    1403334343:508050    52092
    110.73.32.219:6289    1403334249:379281    1403334249:438474    59193
    111.206.126.81:5829    1403334279:983416    1403334280:107169    -875247//由该行看书第二部分时间达到10^6后,进位到第一部分时间,
    112.132.132.243:28525 1403334268:430188 1403334268:734291 304103 112.81.95.111:tksocket 1403334206:465030 1403334206:525732 60702 112.93.191.212:28980 1403334262:448167 1403334262:542576 94409

    2. pcap文件的内容是以网络字节,我们读取后使用时要转化成主机字节

    
    
    linux系统 :#include <arpa/inet.h>
    Windows系统 :#include<Winsock2.h>
    uint16_t ntohs(uint16_t netshort);
    //实际作用 输入 二字节 0xoabd,输出0xbdoa,即小端到大端的转换 
    
    uint32_t ntohl(uint32_t netlong);
    以下内容来自于http://www.cnblogs.com/jacktu/archive/2008/11/24/1339789.html
    不同的CPU有不同的字节序类型 这些字节序是指整数在内存中保存的顺序 这个叫做主机序 
    最常见的有两种
    1. Little endian:将低序字节存储在起始地址
    2. Big endian:将高序字节存储在起始地址

    LE little-endian 
    最符合人的思维的字节序 
    地址低位存储值的低位 
    地址高位存储值的高位 
    怎么讲是最符合人的思维的字节序,是因为从人的第一观感来说 
    低位值小,就应该放在内存地址小的地方,也即内存地址低位 
    反之,高位值就应该放在内存地址大的地方,也即内存地址高位 

    BE big-endian 
    最直观的字节序 
    地址低位存储值的高位 
    地址高位存储值的低位 
    为什么说直观,不要考虑对应关系 
    只需要把内存地址从左到右按照由低到高的顺序写出 
    把值按照通常的高位到低位的顺序写出 
    两者对照,一个字节一个字节的填充进去 

    例子:在内存中双字0x01020304(DWORD)的存储方式 

    内存地址 
    4000 4001 4002 4003 
    LE 04 03 02 01 
    BE 01 02 03 04 

    例子:如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
          big-endian  little-endian
    0x0000  0x12      0xcd
    0x0001  0x23      0xab
    0x0002  0xab      0x34
    0x0003  0xcd      0x12
    x86系列CPU都是little-endian的字节序. 

    网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。

    为了进行转换 bsd socket提供了转换的函数 有下面四个
    htons 把unsigned short类型从主机序转换到网络序
    htonl 把unsigned long类型从主机序转换到网络序
    ntohs 把unsigned short类型从网络序转换到主机序
    ntohl 把unsigned long类型从网络序转换到主机序

    在使用little endian的系统中 这些函数会把字节序进行转换 
    在使用big endian类型的系统中 这些函数会定义成空宏

    同样 在网络程序开发时 或是跨平台开发时 也应该注意保证只用一种字节序 不然两方的解释不一样就会产生bug.

    注:
    1、网络与主机字节转换函数:htons ntohs htonl ntohl (s 就是short l是long h是host n是network)
    2、不同的CPU上运行不同的操作系统,字节序也是不同的,参见下表。
    处理器    操作系统    字节排序
    Alpha    全部    Little endian
    HP-PA    NT    Little endian
    HP-PA    UNIX    Big endian
    Intelx86    全部    Little endian <-----x86系统是小端字节序系统
    Motorola680x()    全部    Big endian
    MIPS    NT    Little endian
    MIPS    UNIX    Big endian
    PowerPC    NT    Little endian
    PowerPC    非NT    Big endian  <-----PPC系统是大端字节序系统
    RS/6000    UNIX    Big endian
    SPARC    UNIX    Big endian
    IXP1200 ARM核心    全部    Little endian 
     
    下面贴一部分pcap解析代码:
    头文件:
    #ifndef PCAP_H
    #define PCAP_H
    #include <map>
    using namespace std;
    typedef short _Int16;
    typedef unsigned short u_Int16;
    typedef unsigned long _Int32;
    typedef char _Int8;
    typedef char Byte;
    struct __file_header
    {
        _Int32 iMagic;
        _Int16  iMaVersion;  
        _Int16  iMiVersion;  
        _Int32  iTimezone;  
        _Int32  iSigFlags;  
        _Int32  iSnapLen;  
        _Int32  iLinkType;  
    };
    
    struct __pkthdr
    {
        _Int32 iTimeSecond;
        _Int32 iTimeSS;
        _Int32 iPLength;/* length of portion present */
        _Int32 iLength; /* length this packet (off wire) */
    };
    struct FrameHeader_t
    {
        _Int8 DstMAC[6];
        _Int8 SrcMAC[6];
        _Int16 FrameType;
    };
    struct IPHeader_t
    {
        _Int8 Ver_HLen;
        _Int8 TOS;
        _Int16 TotalLen;
        _Int16 ID;
        _Int16 Flag_Segment;
        _Int8 TTL;
        _Int8 Protocal;
        _Int16 Checksum;
        _Int32 SrcIP;
        _Int32 DstIP;
    };
    struct TCPHeader_t
    {
        u_Int16 srcPort;
        u_Int16 dstPort;
        _Int32 sequence_num;
        _Int32 ACK_num;
        _Int8 dataoffset;  //4 bit offset +4 bit reserved
        _Int8 flag;   //2 bits reserved+6 bits flag
        u_Int16 wind;
        u_Int16 checksum;
        u_Int16 urgent_point;
    };
    struct UDPHeader_t
    {
        _Int16 srcPort;
        _Int16 dstPort;
        _Int16 Length;
        _Int16 Checksum;
    };
    
    //void readpcap();
    void read_analse_pcap_tcp();
    void read_analse_pcap_udp();
    extern map<string,string> peer;
    #endif
    /**对每个IP地址,分析pcap文件中与该ip地址进行tcp通信的每个tcp数据包的sequence number ,acknumber,wind,flag,结果如wireshark 工具中的statistics的follow graph **/
    const string pcapfilename="F:\江苏loss-0.6.pcap";
    void read_analse_pcap_tcp()
    {
        ifstream tcpinfile(tcpinfilename);
        if (tcpinfile==NULL) 
        {
            cout<<"tcpinfile open error!"<<endl;
            return ;
        }
        string tcpline,tcpword;
        vector<string> cdn_ip_list;
        istringstream tcplinestream;
        getline(tcpinfile,tcpline);
        char *word;
        char line2[200];
        const char* line1;
        char * leftline;
        while(getline(tcpinfile,tcpline))
        {
            line1=tcpline.c_str();
            strcpy_s(line2,line1);
            word=strtok_s(line2,",",&leftline);
            int i=0;
            while(word!=NULL &&i<2)
            {
                word=strtok_s(NULL,",",&leftline);
                i++;
            }
            cdn_ip_list.push_back(string(word));
        }
        struct    __pkthdr data ;  //struct  声明 即可实例化
        cout<<"s data:"<<sizeof(data)<<endl;
        struct __file_header    header;  
        struct FrameHeader_t ethernethdr;
        struct IPHeader_t ipheader,ipheader1;
        struct TCPHeader_t tcpheader,tcpheader1;
        FILE* pFile = fopen( pcapfilename.c_str(), "rb");  
        if(pFile==0)
        {
            cout<<"open pcap file failed!"<<endl;
            return ;
        }
        fseek(pFile,0,SEEK_END);
        long iFileLen=ftell(pFile);
        fseek(pFile,0,SEEK_SET);
        Byte * pBuffer=new Byte[iFileLen];
        fread((void*)pBuffer,1,iFileLen,pFile);
        fclose(pFile);
        Byte * tcpbytes=new Byte[20];
        for(vector<string>::iterator it=cdn_ip_list.begin();it!=cdn_ip_list.end();it++)
        {
            cout<<"*it"<<*it<<endl;
            //cin>>x;
            ofstream outfile("F:\RTMFP\measurement data\ME4\"+*it+".txt");
            if(outfile==0)
            {
                cout<<"*it file open failed!"<<endl;
            }
            int iIndex=sizeof(struct __file_header);
            int iNo=1;
            cout<<"iFileLen:"<<iFileLen<<endl;
            unsigned int initseqin=0,initseqout=0;
            int count=0;
            while(iIndex<=iFileLen)
            {
                count++;
                memcpy((void*)&data,(void*)(pBuffer+iIndex),sizeof(struct __pkthdr));
                memcpy((void*)&ethernethdr,(void*)(pBuffer+iIndex+sizeof(struct __pkthdr)),sizeof(struct FrameHeader_t));
                if(ethernethdr.FrameType==8)
                {
                    memcpy((void*)&ipheader,(void*)(pBuffer+iIndex+sizeof(struct __pkthdr)+sizeof(struct FrameHeader_t)),sizeof(struct IPHeader_t));
                    //
                    if((int)ipheader.Protocal==6&&(longtoip(ipheader.SrcIP)==*it||longtoip(ipheader.DstIP)==*it))
                    {
                        int ipheaderlen=ipheader.Ver_HLen&15;
                        cout<<count<<":count"<<endl;
                        cout<<ipheaderlen<<":ipheaderlen"<<endl;
                        cout<<"iphd.."<<sizeof(struct IPHeader_t)<<endl;
                        
                        cout<<longtoip(ipheader.SrcIP)<<"--->"<<longtoip(ipheader.DstIP)<<endl;
                        memcpy((void*)&tcpheader,(void*)(pBuffer+iIndex+sizeof(struct __pkthdr)+sizeof(struct FrameHeader_t)+ipheaderlen*4),sizeof(struct TCPHeader_t));
                        /**要注意网络字节与主机字节的转换**/
                        cout<<(int)(tcpheader.flag)<<":tcpheader.flag"<<endl;
                        memcpy((void*)tcpbytes,(void*)(pBuffer+iIndex+sizeof(struct __pkthdr)+sizeof(struct FrameHeader_t)+ipheaderlen*4),20);
                        cout<<int(tcpbytes[4])<<" "<<int(tcpbytes[5])<<" "<<int(tcpbytes[6])<<" "<<int(tcpbytes[7])<<" "<<int(tcpbytes[8])<<endl;
                //        cin>>x;
                        if(tcpheader.flag==2)
                        {
                            if(longtoip(ipheader.SrcIP)==*it)
                            {
                                initseqin=ntohl(tcpheader.sequence_num);
                                outfile<<"host<-----"<<*it<<" 0  * "<<ntohs(tcpheader.wind)<<" "<<int(tcpheader.flag)<<endl;
                                //initseqout=tcpheader.sequence_num;
                            }
                        
                            else if(longtoip(ipheader.DstIP)==*it)
                            {
                                 initseqout=ntohl(tcpheader.sequence_num);
                                 outfile<<"host----->"<<*it<<" 0 * "<<ntohs(tcpheader.wind)<<" "<<int(tcpheader.flag)<<endl;
                                 //initseqin=tcpheader.sequence_num;
                            }
                        }
                        else if(tcpheader.flag==18) 
                        {
                            if(longtoip(ipheader.SrcIP)==*it)
                            {
                                initseqin=ntohl(tcpheader.sequence_num);
                                outfile<<"host<-----"<<*it<<" 0  1 "<<ntohs(tcpheader.wind)<<" "<<int(tcpheader.flag)<<endl;
                                //initseqout=tcpheader.sequence_num;
                            }
                        
                            else if(longtoip(ipheader.DstIP)==*it)
                            {
                                initseqout=ntohl(tcpheader.sequence_num);
                                outfile<<"host----->"<<*it<<" 0  1 "<<ntohs(tcpheader.wind)<<" "<<int(tcpheader.flag)<<endl;
                                // initseqin=tcpheader.sequence_num;
                            }
                            iIndex+=sizeof(struct __pkthdr)+data.iPLength;
                            break;
                        }    
                    }
                }
                iIndex+=sizeof(struct __pkthdr)+data.iPLength;
            }
    
            cout<<initseqin<<" init "<<initseqout<<endl;
            //cin>>x;
        //    iIndex+=sizeof(struct __pkthdr)+data.iPLength;
            while(iIndex<=iFileLen)
            {
                count++;
                memcpy((void*)&data,(void*)(pBuffer+iIndex),sizeof(struct __pkthdr));
                memcpy((void*)&ethernethdr,(void*)(pBuffer+iIndex+sizeof(struct __pkthdr)),sizeof(struct FrameHeader_t));
                if(ethernethdr.FrameType==8)
                {
                    memcpy((void*)&ipheader,(void*)(pBuffer+iIndex+sizeof(struct __pkthdr)+sizeof(struct FrameHeader_t)),sizeof(struct IPHeader_t));
                    if((int)ipheader.Protocal==6&&(longtoip(ipheader.SrcIP)==*it||longtoip(ipheader.DstIP)==*it))
                    {
                        int ipheaderlen=ipheader.Ver_HLen&15;
                        //cout<<"count22222222222222222::"<<count<<endl;
                        memcpy((void*)&tcpheader,(void*)(pBuffer+iIndex+sizeof(struct __pkthdr)+sizeof(struct FrameHeader_t)+ipheaderlen*4),sizeof(struct TCPHeader_t));
                        if(longtoip(ipheader.SrcIP)==*it)
                        {
                            outfile<<"host<-----"<<*it<<" "<<ntohl(tcpheader.sequence_num)-initseqin<<" "<<ntohl(tcpheader.ACK_num)-initseqout<<" "<<ntohs(tcpheader.wind)<<" "<<int(tcpheader.flag)<<endl;
                        }
                        else
                        {
                            outfile<<"host----->"<<*it<<" "<<ntohl(tcpheader.sequence_num)-initseqout<<" "<<ntohl(tcpheader.ACK_num)-initseqin<<" "<<ntohs(tcpheader.wind)<<" "<<int(tcpheader.flag)<<endl;
                        }
                    }
                }
                iIndex+=sizeof(struct __pkthdr)+data.iPLength;
            }
            cout<<*it<<" end--"<<endl;
            cin>>x;
        }
    }
  • 相关阅读:
    愚公移山
    唐雎不辱使命
    渡易水歌
    论语
    智子疑邻
    学弈
    SQL Merge 语法 单表查询
    大道之行也
    Java开发人员最常犯的10个错误
    模拟Spring手撕一个简单的IOC容器
  • 原文地址:https://www.cnblogs.com/xaf-dfg/p/3818378.html
Copyright © 2011-2022 走看看