ipv6分组分析器

IPv6分组分析器 

开发思路:

本问题的目的是深入了解IPv6分组格式;掌握程序抓包方法。

具体开发思路为:

1.      先显示出所有网络适配器的列表,然后让用户选择想在哪个适配器上截获数据包。

2.      使用winpcap在用户所选择的网络适配器上进行截获。

3.      将截获的数据包的信息显示出来

 

流程:

²  需求分析

IPv6_packet_analyzer是程序抓包工具。需要能够侦听所有进出本主机的数据包,并过滤出IPV6格式的数据包。对IPV6头而言,需要显示版本、下一个头或协议类型:TCP或UDP、流标签、载荷长度、跳数限制、源IP地址、目的IP地址。

 

²  概要设计

1.            编程环境

本软件是在VC环境下编写,使用WinPcap中定义的头文件和lib文件为支持,运用WinPcap提供的数据包捕获程序执行核心操作。

2.            模块分析

Ø  本软件使用的主要模块及其功能如下:

1.网络适配器选择及显示模块

2.抓包和数据包分析线程

 

²  详细设计

Ø  主要数据结构

 

 

typedef struct ip_address{//128位的IP地址

    WORD byte[8];

}ip6_address;

 

typedef struct ip_header{

    u_char  ver_traffic;        // 版本(4比特) + 通信流类别(前4比特)

    u_char  traffic_flow;    // 通信流类别(后4比特) + 流标签(前4比特)

    u_short flow;           // 流标签(后16比特)

    u_short payloadlen;      // 有效载荷长度(两个字节)

    u_char nexthead;       // 下一个报头(1个字节)

    u_char  hoplim;            // 跳限制

    ip6_address  saddr;      // 源地址

    ip6_address  daddr;      // 目的地址

}ip6_header;

Ø  主要代码描述

Ø  查找主机上所有的适配器并显示

    HTREEITEM root = m_treeCtrl.InsertItem(_T("Network Adpater"));

 

        if(alldevs==NULL){//查找所有网卡

        if (pcap_findalldevs(&alldevs, errbuf) == -1)

                     return FALSE;

       }

 

       pcap_if_t *tempdev=alldevs;

              for (dev=alldevs;dev;dev=dev->next)

              {

                     char *temp;

                     temp=dev->name;

                     HTREEITEM h=m_treeCtrl.InsertItem(_T(temp),root);

              }

      

       DWORD log = GetWindowLong(m_listCtrl.GetSafeHwnd(),GWL_STYLE);

       log |= LVS_REPORT;

       SetWindowLong(m_listCtrl.GetSafeHwnd(),GWL_STYLE,log);

       m_listCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT);

       m_listCtrl.InsertColumn(0,"项目名称",LVCFMT_LEFT,150);

       m_listCtrl.InsertColumn(1,"项目属性",LVCFMT_LEFT,300);

       m_treeCtrl.Expand(root,TVE_EXPAND);

      

       if(dev!=NULL){//当前已有网卡被绑定,责显示该网卡信息

 

              m_listCtrl.DeleteAllItems();

              m_listCtrl.InsertItem(0,"名称",0);

              m_listCtrl.InsertItem(1,"描述",0);

 

              if(dev->name!=NULL){

                     m_listCtrl.SetItemText(0,1,dev->name);

              }

              else{

                     m_listCtrl.SetItemText(0,1,"没有找到");

              }

              if(dev->description!=NULL){

                     m_listCtrl.SetItemText(1,1,dev->description);

              }

              else{

                     m_listCtrl.SetItemText(1,1,"没有找到");

              }

             

       }//当前已有网卡被绑定,显示该网卡信息

 

Ø  显示选定网卡

       HTREEITEM h=m_treeCtrl.GetSelectedItem();

       if (m_treeCtrl.GetParentItem(h)==NULL)

              return;

       dev=alldevs;

 

       while(strcmp(dev->name,m_treeCtrl.GetItemText(h))!=0)//找到被选中网卡

              dev=dev->next;

       m_listCtrl.DeleteAllItems();

       m_listCtrl.InsertItem(0,"名称",0);

       m_listCtrl.InsertItem(1,"描述",0);

      

      

       if(dev!=NULL){//显示选中网卡内容

              if(dev->name!=NULL){

                     m_listCtrl.SetItemText(0,1,dev->name);

              }

              else{

                     m_listCtrl.SetItemText(0,1,"Not Found");

              }

              if(dev->description!=NULL){

                     m_listCtrl.SetItemText(1,1,dev->description);

              }

              else{

                     m_listCtrl.SetItemText(1,1,"没有找到");

              }

             

       }           

 

Ø  打开指定的适配器

HTREEITEM h=This->m_treeCtrl.GetSelectedItem();

This->dev=This->alldevs;

while(strcmp(This->dev->name,This->m_treeCtrl.GetItemText(h))!=0)//找到被选中网卡

This->dev=This->dev->next;

if ( (adhandle= pcap_open(This->dev->name, 

                             65536,     

                                       

                             PCAP_OPENFLAG_PROMISCUOUS,       

                             1000,    

                             NULL,     

                             errbuf    

                             ) ) == NULL)

    {

        AfxMessageBox("网卡打开失败!");

              return -1;

    }

 

Ø  捕包并进行包信息分析

    ip6_header *i6h;

       int res=-1;

    struct pcap_pkthdr * header;

    const unsigned char * pkt_data;

       This->Packetno=0;

       while(!This->isStop&&(res = pcap_next_ex( adhandle, &header, &pkt_data)) >= 0){

 

        if(res == 0)

            //超时时间到

            continue;

   

       i6h = (ip6_header *) (pkt_data +14);

       u_int ve = (i6h->ver_traffic) & 0xf0;

       u_int traffic=i6h->ver_traffic&0xf+(i6h->traffic_flow&0xf0)*8;//通信流类别

       u_int flowlabel = (i6h->traffic_flow & 0xf) * 32 * 1024 + ntohs(i6h->flow);//流标签

      

       CString sPacketno,sve,straffic,sflowlabel,spayloadlen,shoplimit;

       char temp[100];

       itoa(This->Packetno,temp,10);

       sPacketno=temp;

    ltoa(flowlabel,temp,10);

    sflowlabel = temp;

    ltoa(traffic,temp,10);

    straffic = temp;

    ltoa(ve,temp,10);

    sve = temp;

    itoa(ntohs(i6h->payloadlen),temp,10);

    spayloadlen = temp;

    itoa(i6h->hoplim,temp,10);

    shoplimit = temp;

 

       CString nhtype;

       switch(i6h->nexthead)

       {

              case 6: nhtype="TCP";break;

              case 17: nhtype="UDP"; break;

              case 43: nhtype="Routing";break;

              case 44: nhtype="Fragment";break;

              case 58: nhtype="ICMP6";break;

              default : nhtype ="type unknown";

       }

      

       CString srcip,desip;

        //打印ip地址

        for (int i=0;i<8;i++)

        {

            itoa(ntohs(i6h->saddr.byte[i]),temp,16);

            srcip += temp;

            if(i<7)

                srcip +=":";

        }

        for (int j=0;j<8;j++)

        {

             itoa(ntohs(i6h->daddr.byte[i]),temp,16);

            desip += temp;

            if(j<7)

                desip += ":";

        }

        This->m_listCtrlip.InsertItem(This->Packetno,sPacketno);

        This->m_listCtrlip.SetItemText(This->Packetno,1,sve);

        This->m_listCtrlip.SetItemText(This->Packetno,2,straffic);

        This->m_listCtrlip.SetItemText(This->Packetno,3,sflowlabel);

        This->m_listCtrlip.SetItemText(This->Packetno,4,spayloadlen);

        This->m_listCtrlip.SetItemText(This->Packetno,5,nhtype);

        This->m_listCtrlip.SetItemText(This->Packetno,6,shoplimit);

        This->m_listCtrlip.SetItemText(This->Packetno,7,srcip);

        This->m_listCtrlip.SetItemText(This->Packetno,8,desip);  

        This->Packetno++;

       }

       This->isStop=false;

注:

此线程函数通过对isStop的值的判断来确定是否终止。

 

        

关键问题:

1.      采用何种方法进行捕包

2.      如何对IPV6的包进行数据分析

 

解决方法:

1.      采用winpcap中函数实现抓包。包括查找设备,打开设备,抓包等。通过本项目学会了如何使用这一系列的库函数。

2.      定义了IPV6的数据包头以及IP地址的结构体,通过找到数据包头的指针对包头的信息进行分析。

 

进一步的改进:

增加了GUI图形界面,主要通过树形控件显示设备列表,通过列表控件显示选定网卡信息,通过另一个列表控件显示IPV6包的详细信息。在图形化界面中应注意线程的调用。本软件未进行统计信息的显示,可进一步改进。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值