上一篇博客简单讲述了libpcap的工作流程及简单使用,今天我们需要做的是继续使用libpcap抓取我们感兴趣的流量,并进行简单的解析:
测试环境是centos 7
下面贴一张arp帧结构图:
下面我们实现的是通过pcap过滤抓取arp报文,解析其中的Ethernet address 和proctocal address并打印出来
分析是arp request还是reply,前面就不做过多解释,代码比较简单,直接贴:
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <stdint.h>
5 #include <pcap.h>
6 #include <arpa/inet.h>
7
8 #define MAXBYTES2CAPTURE 2048
9 #define ARP_REQUEST 1
10 #define ARP_REPLY 2
11
12 typedef struct arphdr {
13 u_int16_t htype; //hardware type
14 u_int16_t ptype; //protocol type
15 u_char hlen; //hardware address length
16 u_char plen; //protocol address length
17 u_int16_t oper; //operation code
18 u_char sha[6]; //sendHardware address
19 u_char spa[4]; //sender ip address
20 u_char tha[6]; //target hardware address
21 u_char tpa[4]; //target ip address
22 } arphdr_t;
23
24 int main(int argc, char **argv)
25 {
26 int i = 0;
27 bpf_u_int32 net = 0;
28 bpf_u_int32 mask = 0;
29 struct bpf_program filter; /*place to store the filter program*/
30 char errbuf[PCAP_ERRBUF_SIZE];
31 pcap_t *handle = NULL; /*interface handle*/
32 struct pcap_pkthdr pkthdr; /**/
33 const unsigned char *packet = NULL; /*received raw data*/
34 arphdr_t *arpheader = NULL; /*point to arp header*/
35
36 if (argc != 2) {
37 printf("USAGE: arpsniffer <interface>\n");
38 exit(1);
39 }
40
41 memset(errbuf, 0, PCAP_ERRBUF_SIZE);
42 /*open network device for packet capture*/
43 handle = pcap_open_live(argv[1], MAXBYTES2CAPTURE, 0, 512, errbuf);
44 if (handle == NULL) {
45 fprintf(stderr, "Couldn't open device %s: %s\n", argv[1], errbuf);
46 exit(1);
47 }
48
49 /*look up device network addr and mask*/
50 if (pcap_lookupnet(argv[1], &net, &mask, errbuf) == -1) {
51 fprintf(stderr, "Couldn't get netmask for device %s: %s\n", argv[1], errbuf);
52 exit(1);
53 }
54
55 /*complie the filter expression of filter program*/
56 pcap_compile(handle, &filter, "arp", 0, mask);
57
58 pcap_setfilter(handle, &filter);
59
60 while(1) {
61 /*Get one packet if null continue wait*/
62 if ((packet = pcap_next(handle, &pkthdr)) == NULL) {
63 continue;
64 }
65
66 arpheader = (struct arphdr *)(packet + 14); /*Point to the ARP header*/
67 printf("\n------------- ARP --------------\n");
68 printf("Received Packet Size: %d bytes\n", pkthdr.len);
69 printf("Hardware type: %s\n", (ntohs(arpheader->htype) == 1)?"Ethernet":"Unknown");
70 printf("Protocol type: %s\n", (ntohs(arpheader->ptype) == 0x0800)?"IPv4":"Unknown");
71 printf("Operation : %s\n", (ntohs(arpheader->oper) == ARP_REQUEST)?"ARP_REQUEST":"ARP_REPLY");
72
73 /*If is Ethernet and IPv4 print packet contents*/
74 if (ntohs(arpheader->htype) == 1 && ntohs(arpheader->ptype) == 0x0800) {
75 printf("\nSoucre MAC:%02x:%02x:%02X:%02x:%02x:%02x\n",
76 arpheader->sha[0], arpheader->sha[1],
77 arpheader->sha[2], arpheader->sha[3],
78 arpheader->sha[4], arpheader->sha[5]);
79 printf("Soucre IP:%d.%d.%d.%d\n",
80 arpheader->spa[0], arpheader->spa[1],
81 arpheader->spa[2], arpheader->spa[3]);
82 printf("\nDestination MAC:%02x:%02x:%02X:%02x:%02x:%02x\n",
83 arpheader->tha[0], arpheader->tha[1],
84 arpheader->tha[2], arpheader->tha[3],
85 arpheader->tha[4], arpheader->tha[5]);
86 printf("Destination IP:%d.%d.%d.%d\n",
87 arpheader->tpa[0], arpheader->tpa[1],
88 arpheader->tpa[2], arpheader->tpa[3]);
89 }
90 }
91 return 0;
92 }
下面是运行结果:
1 [root@localhost pcap_arp]# ./pcap enp0s3
2
3 ------------- ARP --------------
4 Received Packet Size: 60 bytes
5 Hardware type: Ethernet
6 Ptotocol type: IPv4
7 Operation : ARP_REQUEST
8
9 Soucre MAC:b0:83:FE:99:5a:5b
10 Soucre IP:192.168.16.139
11
12 Destination MAC:08:00:27:25:e7:52
13 Destination IP:192.168.16.125
14
15 ------------- ARP --------------
16 Received Packet Size: 42 bytes
17 Hardware type: Ethernet
18 Ptotocol type: IPv4
19 Operation : ARP_REPLY
20
21 Soucre MAC:08:00:27:25:e7:52
22 Soucre IP:192.168.16.125
23
24 Destination MAC:b0:83:FE:99:5a:5b
25 Destination IP:192.168.16.139
Makefile:
1 #
2 #design of ARP sniffer
3 #
4
5 CFLAGS = -g
6 LDFLAGS = -lpcap
7
8 OBJS = test.o
9 TARGET = pcap
10
11 RM = rm -f
12
13 $(TARGET):$(OBJS)
14 $(CC) $(LDFLAGS) -o $@ $^
15
16 %.o:%.c
17 $(CC) $(CFLAGS) -c -o $@ $<
18
19 .PHONY:clean
20
21 clean:
22 $(RM) $(TARGET) $(OBJS)