libpcap折腾系列之获取系统网卡信息

libpcap是是unix/linux平台下的网络数据包捕获库,大多数的网络监控软件都是以它为基础的,例如Tcpdump。

最近想在我的Openwrt路由器上开发一个数据包分析工具,需要学习一下libpcap的功能,于是乎写篇博文记录一下经过。

首先接触到的是获取系统中所有的网卡的函数pcap_findalldevs,该函数可以获取所有网卡设备,获取到的设备是一个pcap_if_t类型的结构体,里边有该设备的具体信息,包括网卡IP。下边是一个示例程序:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <pcap.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>


int main(int argc, char *argv[])
{
pcap_if_t *alldevs;
pcap_if_t *device;
pcap_addr_t *a;
char *net;
char *mask;
char errbuf[PCAP_ERRBUF_SIZE];
struct in_addr addr;
struct sockaddr_in *eth_addr;

if(pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
exit(EXIT_FAILURE);
}
device = alldevs;
for(; device != NULL; device = device->next)
{
printf("Device name: %s\n", device->name);
printf("Description: %s\n", device->description);
printf("\tLoopback: %s\n", (device->flags & PCAP_IF_LOOPBACK)?"yes":"no");

for(a = device->addresses; a; a = a->next)
{
printf("\tAddress Family Name: #%d\n", a->addr->sa_family);
switch(a->addr->sa_family)
{
case AF_INET:
printf("\tAddress Family Name: AF_INET\n");
if(a->addr)
printf("\tAddress: %s\n", inet_ntoa(((struct sockaddr_in*)a->addr)->sin_addr));
if(a->netmask)
printf("\tNetmask: %s\n", inet_ntoa(((struct sockaddr_in*)a->netmask)->sin_addr));
if(a->broadaddr)
printf("\tBroadcast Address: %s\n", inet_ntoa(((struct sockaddr_in*)a->broadaddr)->sin_addr));
if(a->dstaddr)
printf("\tDestination Address: %s\n", inet_ntoa(((struct sockaddr_in*)a->dstaddr)->sin_addr));
break;
case AF_INET6:
printf("\tAddress Family Name: AF_INET6\n");
if(a->addr){
char addr_str[46];
printf("\tAddress: %s\n", inet_ntop(AF_INET6, &((struct sockaddr_in6*)a->addr)->sin6_addr, addr_str, sizeof(addr_str)));
printf("\tAddress %s\n", "ipv6");
}
break;
default:
printf("\tAddress Family Name: Unknown\n");
break;

}
}
printf("\n");
}
}

进行编译:

1
#gcc pcap_eth_info.c -o eth_info -lpcap

运行结果:

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
41
42
43
# ./eth_info
Device name: enp0s3
Description: (null)
Loopback: no
Address Family Name: #17
Address Family Name: Unknown
Address Family Name: #2
Address Family Name: AF_INET
Address: 192.168.10.214
Netmask: 255.255.255.0
Broadcask Address: 192.168.10.255
Address Family Name: #10
Address Family Name: AF_INET6
Address ipv6

Device name: any
Description: Pseudo-device that captures on all interfaces
Loopback: no

Device name: lo
Description: (null)
Loopback: yes
Address Family Name: #17
Address Family Name: Unknown
Address Family Name: #2
Address Family Name: AF_INET
Address: 127.0.0.1
Netmask: 255.0.0.0
Address Family Name: #10
Address Family Name: AF_INET6
Address ipv6

Device name: nflog
Description: Linux netfilter log (NFLOG) interface
Loopback: no

Device name: nfqueue
Description: Linux netfilter queue (NFQUEUE) interface
Loopback: no

Device name: usbmon1
Description: USB bus number 1
Loopback: no

接下来会涉及到如何在网卡上捕获数据包,解开数据包。