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
原文地址:https://www.cnblogs.com/kernel0815/p/3803302.html