【概述】
数据是从链路层到应用层一层一层装配起来的,因此,对于捕获到的数据包,需要一层一层的进行解析。同时,由于每一层可能有多种协议要工作,因此在解析数据包时,要根据不同的特征来判断上层协议。
在网络层,有 ARP、IPv4、IPv6 这三种情况,在链路层的 MAC 头结构中,定义了一个 type 字段,用于指示网络层的数据包的类型,根据协议栈的规定,有:
- ARP包:type=0x0806
- IPv4包:type=0x0800
- IPv6包:type=0x86dd
在传输层,当下层数据包是 IPv4 包时,有 ICMPv4、TCP、UDP 三种情况,在网络层的 IPv4 头结构中,定义了一个 proto 字段,用来对应指示传输层的数据包类型,根据协议栈规定,有:
- ICMPv4包:proto=1
- TCP包:proto=6
- UDP包:proto=17
而当下层数据包是 IPv6 包时,有 ICMPv6、TCP、UDP 三种情况,在网络层的 IPv6 头结构中,定义了 next_head 字段,用来指示对应传输层的数据包类型,根据协议栈规定,有:
- ICMPv6包:next_head=0x3a
- TCP包:next_head=0x06
- UDP包:next_head=0x11
在应用层,这里只支持 HTTP 协议,因此只要 TCP 头结构中的源端口 src_port 或目的端口 dest_port 是否为 80 端口即可。
流程结构图如下:
根据流程图,将负责解析的函数写到 analysis.h 头文件中,其中包含以下几个模块:
- 数据链路层:解析数据帧
- 网络层:解析ARP包
- 网络层:解析IPv4包
- 网络层:解析IPv6包
- 传输层:解析ICMPv4包
- 传输层:解析ICMPv6包
- 传输层:解析TCP包(包含解析HTTP包)
- 传输层:解析UDP包
【数据链路层】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| int analyse_data_frame(const u_char *packet, struct data_packet *data, struct packet_count *count){ struct eth_header *ethHeader = (struct eth_header*)packet; data->ethh = (struct eth_header*)malloc(sizeof(struct eth_header)); if (data->ethh == NULL) return -1;
for (int i = 0; i < 6; i++) { data->ethh->src[i] = ethHeader->src[i]; data->ethh->dest[i] = ethHeader->dest[i]; } count->num_sum++; data->ethh->type = ntohs(ethHeader->type);
switch (data->ethh->type) { case PROTO_ARP: return analyse_ARP((u_char*)packet + 14, data, count); break; case PROTO_IP_V4: return analyse_IPv4((u_char*)packet + 14, data, count); break; case PROTO_IP_V6: return analyse_IPv6((u_char*)packet + 14, data, count); break; default: count->num_other++; return -1; } return 1; }
|
【网络层】
解析ARP包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| int analyse_ARP(const u_char *packet, struct data_packet *data, struct packet_count *count) { struct arp_header *arph = (struct arp_header*)packet; data->arph = (struct arp_header*)malloc(sizeof(struct arp_header));
if (data->arph == NULL) return -1;
for (int i = 0; i < 6; i++){ if (i < 4) { data->arph->dest_ip[i] = arph->dest_ip[i]; data->arph->src_ip[i] = arph->src_ip[i]; } data->arph->dest_mac[i] = arph->dest_mac[i]; data->arph->src_mac[i] = arph->src_mac[i]; }
data->arph->hard_len = arph->hard_len; data->arph->hard_type = ntohs(arph->hard_type); data->arph->oper = ntohs(arph->oper); data->arph->pro_len = arph->pro_len; data->arph->pro_type = ntohs(arph->pro_type); strcpy(data->type, "ARP");
count->num_arp++; return 1; }
|
解析IPv4包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| int analyse_IPv4(const u_char *packet, struct data_packet *data, struct packet_count *count) { struct ipv4_header *iph = (struct ipv4_header*)packet; data->ip4h = (struct ipv4_header*)malloc(sizeof(struct ipv4_header));
if (data->ip4h == NULL) return -1;
data->ip4h->check = iph->check; data->ip4h->src_addr = iph->src_addr; data->ip4h->dest_addr = iph->dest_addr; data->ip4h->frag_off = iph->frag_off; data->ip4h->id = iph->id; data->ip4h->proto = iph->proto; data->ip4h->total_len = ntohs(iph->total_len); data->ip4h->tos = iph->tos; data->ip4h->ttl = iph->ttl; data->ip4h->ihl = iph->ihl; data->ip4h->version = iph->version; data->ip4h->opt = iph->opt;
count->num_ip4++;
int iplen = iph->ihl * 4; switch (iph->proto) { case V4_PROTO_UDP: return analyse_UDP((u_char*)iph + iplen, data, count); break; case V4_PROTO_TCP: return analyse_TCP((u_char*)iph + iplen, data, count); break; case V4_PROTO_ICMP_V4: return analyse_ICMPv4((u_char*)iph + iplen, data, count); break; default: return-1; } return 1; }
|
解析IPv6包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| int analyse_IPv6(const u_char *packet, struct data_packet *data, struct packet_count *count) { struct ipv6_header *iph6 = (struct ipv6_header*)packet; data->ip6h = (struct ipv6_header*)malloc(sizeof(struct ipv6_header));
if (data->ip6h == NULL) return -1;
for (int i = 0; i < 16; i++) { data->ip6h->src_addr[i] = iph6->src_addr[i]; data->ip6h->dest_addr[i] = iph6->dest_addr[i]; }
data->ip6h->version = iph6->version; data->ip6h->flowtype = iph6->flowtype; data->ip6h->flowid = iph6->flowid; data->ip6h->plen = ntohs(iph6->plen); data->ip6h->next_head = iph6->next_head; data->ip6h->hop_limit = iph6->hop_limit;
count->num_ip6++;
switch (iph6->next_head){ case V6_PROTO_ICMP_V6: return analyse_ICMPv6 ((u_char*)iph6 + 40, data, count); break; case V6_PROTO_UDP: return analyse_UDP((u_char*)iph6 + 40, data, count); break; case V6_PROTO_TCP: return analyse_TCP((u_char*)iph6 + 40, data, count); break; default: return-1; } return 1; }
|
【传输层】
解析ICMPv4包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| int analyse_ICMPv4(const u_char *packet, struct data_packet *data, struct packet_count *count) { struct icmpv4_header* icmph = (struct icmpv4_header*)packet; data->icmp4h = (struct icmpv4_header*)malloc(sizeof(struct icmpv4_header));
if (data->icmp4h == NULL) return -1;
data->icmp4h->check = icmph->check; data->icmp4h->code = icmph->code; data->icmp4h->seq = icmph->seq; data->icmp4h->type = icmph->type; strcpy(data->type, "ICMP");
count->num_icmp4++; return 1; }
|
解析ICMPv6包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| int analyse_ICMPv6(const u_char *packet, struct data_packet *data, struct packet_count *count) { struct icmpv6_header* icmph6 = (struct icmpv6_header*)packet; data->icmp6h = (struct icmpv6_header*)malloc(sizeof(struct icmpv6_header));
if (data->icmp6h == NULL) return -1;
for (int i = 0; i < 6; i++) data->icmp6h->op_eth_addr[i] = icmph6->op_eth_addr[i]; data->icmp6h->check = icmph6->check; data->icmp6h->code = icmph6->code; data->icmp6h->seq = icmph6->seq; data->icmp6h->type = icmph6->type; data->icmp6h->op_len = icmph6->op_len; data->icmp6h->op_type = icmph6->op_type; strcpy(data->type, "ICMPv6");
count->num_icmp6++; return 1; }
|
解析TCP包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| int analyse_TCP(const u_char *packet, struct data_packet *data, struct packet_count *count) { struct tcp_header *tcph = (struct tcp_header*)packet; data->tcph = (struct tcp_header*)malloc(sizeof(struct tcp_header));
if (NULL == data->tcph) return -1;
data->tcph->ack_seq = tcph->ack_seq; data->tcph->check = tcph->check; data->tcph->doff = tcph->doff; data->tcph->res1 = tcph->res1; data->tcph->cwr = tcph->cwr; data->tcph->ece = tcph->ece; data->tcph->urg = tcph->urg; data->tcph->ack = tcph->ack; data->tcph->psh = tcph->psh; data->tcph->rst = tcph->rst; data->tcph->syn = tcph->syn; data->tcph->fin = tcph->fin; data->tcph->dest_port = ntohs(tcph->dest_port); data->tcph->src_port = ntohs(tcph->src_port); data->tcph->seq = tcph->seq; data->tcph->urg_ptr = tcph->urg_ptr; data->tcph->window = tcph->window; data->tcph->opt = tcph->opt;
if (ntohs(tcph->dest_port) == 80 || ntohs(tcph->src_port) == 80) { count->num_http++; strcpy(data->type, "HTTP"); } else { count->num_tcp++; strcpy(data->type, "TCP"); } return 1; }
|
解析UDP包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| int analyse_UDP(const u_char *packet, struct data_packet *data, struct packet_count *count) { struct udp_header* udph = (struct udp_header*)packet; data->udph = (struct udp_header*)malloc(sizeof(struct udp_header)); if (NULL == data->udph) return -1;
data->udph->check = udph->check; data->udph->dport = ntohs(udph->dport); data->udph->len = ntohs(udph->len); data->udph->sport = ntohs(udph->sport); strcpy(data->type, "UDP");
count->num_udp++; return 1; }
|