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;
    }
}

 

 
posted @ 2014-07-17 12:33  xaf_dfg  阅读(939)  评论(0编辑  收藏  举报