数据包分析
想要知道如何解析IP数据包,就要知道不同的IP数据包的包头结构,于是我们上⽹查查资料:
以太网数据包
ARP数据包
IPv4
IPv6
TCP
UDP
ICMP
ICMPv6
根据以上数据包头结构,我们就有了我们的protocol.h文件,声明各种数据包:
#ifndef PROTOCOL_H #define PROTOCOL_H #define HAVE_REMOTE #define PROTO_ICMP 1 #define PROTO_TCP 6 #define PROTO_UDP 17 #include <iostream> #include <QObject> #include "_bsd_types.h" #include "pcap.h" using namespace std; //IPV4 typedef struct ip_address{ u_char byte1; u_char byte2; u_char byte3; u_char byte4; }ip_address; typedef struct ipv6_address { u_char byte1; u_char byte2; u_char byte3; u_char byte4; u_char byte5; u_char byte6; u_char byte7; u_char byte8; }ipv6_address; typedef struct ipv4_header{ u_char ver_ihl; u_char tos; u_short tlen; u_short Identification; u_short flags_fo; u_char ttl; u_char proto; u_short crc; ip_address srcaddr; ip_address dstaddr; u_int op_pad; }ipv4_header; typedef struct ipv6_header{ u_int ver:4, flowtype:8, flowtip:20; u_short len; u_char pnext; u_char lim; ipv6_address srcaddr; ipv6_address dstaddr; }ipv6_header; typedef struct tcp_header{ u_short srcport; u_short dstport; u_int seq; u_int ack_seq; u_short resl:4, doff:4, fin:1, syn:1, pst:1, psh:1, ack:1, urg:1, ece:1, cwr:1; u_short window; u_short check; u_short urg_ptr; u_int opt; }tcp_header; typedef struct udp_header{ u_short srcport; u_short dstport; u_short tlen; u_short crc; }udp_header; typedef struct icmp_header{ u_char type; u_char code; u_char seq; u_char crc; }icmp_header; typedef struct icmp6_header{ u_char type; u_char code; u_char seq; u_char crc; u_char op_type; u_char op_len; u_char op_ethaddr[6]; }icmp6_header; typedef struct pkg_count{ int n_tcp; int n_udp; int n_icmp; int n_icmp6; int n_http; int n_arp; int n_ipv4; int n_ipv6; int n_other; int n_ttl; }pkg_count; typedef struct arp_header{ u_short hardware; u_short proto; u_char ml; u_char ipl; u_short opt; u_char sm[6]; ip_address sip; u_char dm[6]; ip_address dip; }arp_hearder; typedef struct eth_header{ u_char smac[6]; u_char dmac[6]; u_short type; }eth_header; typedef struct pkg_data { QString pkgtype; int time[6]; int len; eth_header *ethh; ipv4_header *ipv4h; ipv6_header *ipv6h; arp_header *arph; udp_header *udph; tcp_header *tcph; icmp_header *icmph; icmp6_header *icmp6; void *apph; }pkg_data; #endif // PROTOCOL_H
再对数据包的结构进行了解后,我们就需要对这些包进行解析,所以我们需要一个packettools类,里面用静态函数写出包的解析,供我们在别的地方调用:
#ifndef PACKETTOOLS_H #define PACKETTOOLS_H #include <QObject> #include <QTextEdit> #include "protocol.h" #include "iostream" using namespace std; class PacketTools { public: static int unpcak_Frame(const u_char *pkg, pkg_data *data, pkg_count *pkgCnts); static int unpcak_Arp(const u_char *pkg, pkg_data *data, pkg_count *pkgCnts); static int unpack_Ip(const u_char *pkg, pkg_data *data, pkg_count *pkgCnts); static int unpack_Ipv6(const u_char *pkg, pkg_data *data, pkg_count *pkgCnts); static int unpack_Icmp(const u_char *pkg, pkg_data *data, pkg_count *pkgCnts); static int unpack_Icmp6(const u_char *pkg, pkg_data *data, pkg_count *pkgCnts); static int unpack_Tcp(const u_char *pkg, pkg_data *data, pkg_count *pkgCnts); static int unpack_Udp(const u_char *pkg, pkg_data *data, pkg_count *pkgCnts); static int pack_Print(u_char *pkg, int size, QTextEdit *edit); }; #endif // PACKETTOOLS_H
主要一点就是要知道父类数据包的type字段对子类数据包的分类,然后将数据包拷贝储存到全局容器里面。