zoukankan      html  css  js  c++  java
  • libpcap报文解析: ipv4、ipv6(待优化)

      1 #include <string.h>
      2 #include <stdlib.h>
      3 #include <pcap.h>
      4 #include <netinet/in.h>
      5 #include "packet_header.h"
      6 
      7 #define MAXBYTE2CAPTURE 2048
      8 
      9 int isprint(char c)
     10 {
     11     return 0;
     12 }
     13 
     14 void print_buf(u_char* pBuf, u_int32 len)
     15 {
     16     if (!pBuf)
     17     {
     18         return;
     19     }
     20 
     21     for(int i=0; i<len; i++)
     22     {
     23         printf("%02x ",  (u_char*)pBuf[i]);
     24 
     25         if ((i%16 == 0 && i!=0) || i == len-1)
     26         {
     27             printf("
    ");
     28         }
     29     }
     30 }
     31 
     32 void parse_ethII(u_char* pData, u_int32 len)
     33 {
     34     if (!pData || len <14)
     35     {
     36         return;
     37     }
     38 
     39     printf("eth II frame: 
    ");
     40     print_buf(pData, 14);
     41 
     42     /* parse src mac and dst mac */
     43     EthHeader_t* pEth = (EthHeader_t*)pData;
     44     printf("destination: %02x:%02x:%02x:%02x:%02x:%02x ",
     45         pEth->dest_hwaddr[0],
     46         pEth->dest_hwaddr[1],
     47         pEth->dest_hwaddr[2],
     48         pEth->dest_hwaddr[3],
     49         pEth->dest_hwaddr[4],
     50         pEth->dest_hwaddr[5]);
     51 
     52     printf("source : %02x:%02x:%02x:%02x:%02x:%02x",
     53         pEth->source_hwaddr[0],
     54         pEth->source_hwaddr[1],
     55         pEth->source_hwaddr[2],
     56         pEth->source_hwaddr[3],
     57         pEth->source_hwaddr[4],
     58         pEth->source_hwaddr[5]);
     59 
     60     /* parse frame type */
     61     printf("
    frame type: 0x%x
    ", ntohs(pEth->frame_type));
     62 }
     63 
     64 
     65 void parse_ipheader(u_char* pData, u_int32 len)
     66 {
     67     if (!pData || len <14)
     68     {
     69         return;
     70     }
     71 
     72     printf("ip header: 
    ");
     73     print_buf(pData, 20);
     74 
     75     /* parse ip header */
     76     IPHeader_t* pIpHeader = (IPHeader_t*)pData;
     77     printf("	version     : %02x
    "
     78            "	tos         : %02x
    "
     79            "	total length: %d(0x%02x)
    "
     80            "	id          : %d(0x%02x)
    "
     81            "	segment flag: %d(0x%02x)
    "
     82            "	ttl         : %02x
    "
     83            "	protocol    : %02x
    "
     84            "	checksum    : %d(0x%02x)
    "
     85            "	src ip      : %d.%d.%d.%d
    "
     86            "	dst ip      : %d.%d.%d.%d
    ",
     87         pIpHeader->Ver_HLen,
     88         pIpHeader->TOS,
     89         ntohs(pIpHeader->TotalLen), ntohs(pIpHeader->TotalLen),
     90         ntohs(pIpHeader->ID), ntohs(pIpHeader->ID),
     91         ntohs(pIpHeader->Flag_Segment), ntohs(pIpHeader->Flag_Segment),
     92         pIpHeader->TTL,
     93         pIpHeader->Protocol,
     94         ntohs(pIpHeader->Checksum), ntohs(pIpHeader->Checksum),
     95         pIpHeader->SrcIP[0],pIpHeader->SrcIP[1],pIpHeader->SrcIP[2],pIpHeader->SrcIP[3],
     96         pIpHeader->DstIP[0],pIpHeader->DstIP[1],pIpHeader->DstIP[2],pIpHeader->DstIP[3]);
     97 }
     98 
     99 void parse_ip6header(u_char* pData, u_int32 len)
    100 {
    101     if (!pData || len <14)
    102     {
    103         return;
    104     }
    105 
    106     printf("ipv6 header: 
    ");
    107     print_buf(pData, 40);
    108 
    109     /* parse ipv6 header */
    110     IPv6Header_t* pIpv6Header = (IPv6Header_t*)pData;
    111     printf("	version           : %x
    "
    112            "	traffic class     : %x
    "
    113            "	flow label        : %x
    "
    114            "	payload length    : %x
    "
    115            "	next header       : %x
    "
    116            "	hop limit         : %x
    "
    117            "	source            : %x
    "
    118            "	destination       : %x
    ",
    119            pIpv6Header->ip6_ctlun.ip6_un2_vfc,
    120            pIpv6Header->ip6_ctlun.ip6_unl.ip6_unl_flow,
    121            pIpv6Header->ip6_ctlun.ip6_unl.ip6_unl_flow,
    122            pIpv6Header->ip6_ctlun.ip6_unl.ip6_unl_plen,
    123            pIpv6Header->ip6_ctlun.ip6_unl.ip6_unl_nxt,
    124            pIpv6Header->ip6_ctlun.ip6_unl.ip6_unl_hlim,
    125            pIpv6Header->ip6_src,
    126            pIpv6Header->ip6_dst);
    127 }
    128 
    129 
    130 void parse_packet(const u_char* packet, u_int32 len)
    131 {
    132     u_short ftype = 0;
    133 
    134     if (!packet)
    135     {
    136         return ;
    137     }
    138 
    139     u_char* pMbuf = (u_char*)packet;
    140     parse_ethII(pMbuf, len);
    141 
    142     ftype = ntohs(((EthHeader_t*)pMbuf)->frame_type);
    143     switch(ftype)
    144     {
    145         case 0x0800:  /* ipv4 */
    146             pMbuf = (u_char*)packet + 14;
    147             parse_ipheader(pMbuf, len-14);
    148             break;
    149         case 0x86dd: /* ipv6 */
    150             pMbuf = (u_char*)packet + 14;
    151             parse_ip6header(pMbuf, len-14);
    152             break;
    153         default:
    154             printf("frame type : 0x%x
    ", ftype);
    155             break;
    156     }
    157 
    158     printf("
    ");
    159 }
    160 
    161 void processPacket(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
    162 {
    163     int i = 0, *counter = (int *)arg;
    164 
    165     printf("--------------------------------------------
    ");
    166     printf("Packet Count: %d
    ", ++(*counter));
    167     printf("Received Packet Size: %d
    ", pkthdr->len);
    168     printf("Payload:
    ");
    169 
    170 #if 1
    171     for (i = 0; i < pkthdr->len; i++)
    172     {
    173         if (isprint(packet[i]))
    174         {
    175             printf("%02d ", packet[i]);
    176         }
    177         else
    178         {
    179             printf("%02x ", packet[i]);
    180         }
    181 
    182         if ((i % 16 == 0 && i != 0) || i == pkthdr->len-1)
    183         {
    184             printf("
    ");
    185         }
    186 
    187     }
    188 #endif
    189 
    190     parse_packet(packet, pkthdr->len);
    191 
    192     return;
    193 }
    194 
    195 int main()
    196 {
    197 
    198     int i = 0, count = 0;
    199     pcap_t *descr = NULL;
    200     char errbuf[PCAP_ERRBUF_SIZE], *device = NULL;
    201     memset(errbuf, 0, PCAP_ERRBUF_SIZE);
    202 
    203     /* Get the name of the first device suitable for capture */
    204     device = pcap_lookupdev(errbuf);
    205     if (!device)
    206     {
    207         printf("Open device failed.");
    208         return -1;
    209     }
    210 
    211     printf("Opening device %s
    ", device);
    212 
    213     /* Open device in promiscuous mode */
    214     descr = pcap_open_live(device, MAXBYTE2CAPTURE, 1, 512, errbuf);
    215 
    216     /* Loop forever & call processPacket() for every received packet */
    217     pcap_loop(descr, -1, processPacket, (u_char *)&count);
    218 
    219     return 0;
    220 }
    #ifndef PACKET_HEADER_H
    #define PACKET_HEADER_H
    
    #ifndef u_char
    #define u_char unsigned char
    #endif
    
    #ifndef u_int8
    #define u_int8 unsigned char
    #endif
    
    #ifndef u_int16
    #define u_int16 unsigned short
    #endif
    
    #ifndef u_int32
    #define u_int32 unsigned int
    #endif
    
    #ifndef u_int64
    #define u_int64 unsigned long long
    #endif
    
    #ifndef u_short
    #define u_short unsigned short
    #endif
    
    /* 以太帧头 */
    typedef struct tagEthHeader_t
    {
        //Pcap捕获的数据帧头
        u_int8 dest_hwaddr[6];   //目的MAC地址
        u_int8 source_hwaddr[6]; //源MAC地址
        u_short frame_type;      //帧类型
    }EthHeader_t;
    
    //IP数据报头
    typedef struct tagIPHeader_t
    {
        //IP数据报头
        u_int8  Ver_HLen; //版本+报头长度
        u_int8  TOS;      //服务类型
        u_int16 TotalLen;//总长度
        u_int16 ID;      //标识
        u_int16 Flag_Segment; //标志+片偏移
        u_int8  TTL;      //生存周期
        u_int8  Protocol; //协议类型
        u_int16 Checksum;//头部校验和
        u_int8 SrcIP[4];   //源IP地址
        u_int8 DstIP[4];   //目的IP地址
    } IPHeader_t;
    
    //IPv6基本首部
    #if 0
    typedef struct tagIPv6Header_t
    {
        u_char    version:4;      // 4-bit版本号
        u_char  traffic_class:8;  // 8-bit流量等级
        u_int32 label:20;       // 20-bit流标签
        u_short    payload_len;    // 16-bit 载荷长度
        u_char    next_header;    // 8-bit 下一首部
        u_char    hop_limit;        // 8-bit 跳数限制
        struct
        {
            u_int64 prefix_subnetid;
            u_char interface_id[8];
        } src_ip;                // 128-bit 源地址
        struct
        {
            u_int64 prefix_subnetid;
            u_char interface_id[8];
        } dst_ip;                // 128-bit 目的地址
    
    } IPv6Header_t;
    
    typedef struct in6_addr {
      union {
        u_char  Byte[16];
        u_short Word[8];
      } u;
    } IN6_ADDR, *PIN6_ADDR, FAR *LPIN6_ADDR;
    
    #endif
    
    
    typedef struct tagIPv6Header_t
    {
        union
        {
            struct ip6_hdrctl
            {
                u_int32_t ip6_unl_flow;/* 4位的版本,8位的传输与分类,20位的流标识符 */
                u_int16_t ip6_unl_plen;/* 报头长度 */
                u_int8_t ip6_unl_nxt;  /* 下一个报头 */
                u_int8_t ip6_unl_hlim; /* 跨度限制 */
            }ip6_unl ;
    
            u_int8_t ip6_un2_vfc;/* 4位的版本号,跨度为4位的传输分类 */
        }ip6_ctlun ;
    
    #define ip6_vfc              ip6_ctlun.ip6_un2_vfc
    #define ip6_flow             ip6_ctlun.ip6_unl.ip6_unl_flow
    #define ip6_plen             ip6_ctlun.ip6_unl.ip6_unl_plen
    #define ip6_nxt              ip6_ctlun.ip6_unl.ip6_unl_nxt
    #define ip6_hlim             ip6_ctlun.ip6_unl.ip6_unl_hlim
    #define ip6_hops             ip6_ctlun.ip6_unl.ip6_unl_hops
    
        struct in6_addr ip6_src;/* 发送端地址 */
        struct in6_addr ip6_dst;/* 接收端地址 */
    }IPv6Header_t;
    
    //TCP数据报头
    typedef struct tagTCPHeader_t
    {
        //TCP数据报头
        u_int16 SrcPort; //源端口
        u_int16 DstPort; //目的端口
        u_int32 SeqNO;   //序号
        u_int32 AckNO;   //确认号
    } TCPHeader_t;
    
    #endif
  • 相关阅读:
    Docker 系列(四):Docker 容器数据卷简单使用
    【QML 动态对象】使用JS中的语句动态创建和销毁组件
    【QML 动态对象】Loader动态加载组件
    vue-cli2.0全局使用sass变量
    两边+居中 布局
    跳转子路由后左侧菜单跳转为空白页,路由地址出错
    el-tree可搜索单选
    el-tree固定高度加滚动条
    前端 权限控制 方式
    综合分析类
  • 原文地址:https://www.cnblogs.com/kernel0815/p/3803302.html
Copyright © 2011-2022 走看看