上一篇博客简单讲述了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> "); 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 ", 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 ", 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(" ------------- ARP -------------- "); 68 printf("Received Packet Size: %d bytes ", pkthdr.len); 69 printf("Hardware type: %s ", (ntohs(arpheader->htype) == 1)?"Ethernet":"Unknown"); 70 printf("Protocol type: %s ", (ntohs(arpheader->ptype) == 0x0800)?"IPv4":"Unknown"); 71 printf("Operation : %s ", (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(" Soucre MAC:%02x:%02x:%02X:%02x:%02x:%02x ", 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 ", 80 arpheader->spa[0], arpheader->spa[1], 81 arpheader->spa[2], arpheader->spa[3]); 82 printf(" Destination MAC:%02x:%02x:%02X:%02x:%02x:%02x ", 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 ", 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)