原帖: http://blog.csdn.net/htttw/article/details/7521053
libpcap是一個網絡數據包捕獲函數庫,功能非常強大,Linux下著名的tcpdump就是以它爲基礎的。今天我們利用它來完成一個我們自己的網絡嗅探器(sniffer)
首先先介紹一下本次實驗的環境:
Ubuntu 11.04,IP:192.168.1.1,廣播地址:192.168.1.255,子網掩碼:255.255.255.0
可以使用下面的命令設置:
sudo ifconfig eth0 192.168.1.1 broadcast 192.168.1.255 netmask 255.255.255.0
1.安裝
在http://www.tcpdump.org/下載libpcap(tcpdump的源碼也可以從這個網站下載)
解壓
./configure
make
sudo make install
2.使用
安裝好libpcap後,我們要使用它啦,先寫一個簡單的程序,並介紹如何使用libpcap庫編譯它:
Makefile:
- all: test.c
- gcc -g -Wall -o test test.c -lpcap
- clean:
- rm -rf *.o test
其後的程序的Makefile均類似,故不再重複
test1.c
- #include <pcap.h>
- #include <stdio.h>
- int main()
- {
- char errBuf[PCAP_ERRBUF_SIZE], * device;
- device = pcap_lookupdev(errBuf);
- if(device)
- {
- printf("success: device: %s\n", device);
- }
- else
- {
- printf("error: %s\n", errBuf);
- }
- return 0;
- }
可以成功編譯,不過運行的時候卻提示找不到libpcap.so.1,因爲libpcap.so.1默認安裝到了/usr/local/lib下,我們做一個符號鏈接到/usr/lib/下即可:
運行test的時候輸出"no suitable device found",原因是我們沒有以root權限運行,root權限運行後就正常了:
下面開始正式講解如何使用libpcap:
首先要使用libpcap,我們必須包含pcap.h頭文件,可以在/usr/local/include/pcap/pcap.h找到,其中包含了每個類型定義的詳細說明。
1.獲取網絡接口
首先我們需要獲取監聽的網絡接口:
我們可以手動指定或讓libpcap自動選擇,先介紹如何讓libpcap自動選擇:
char * pcap_lookupdev(char * errbuf)
上面這個函數返回第一個合適的網絡接口的字符串指針,如果出錯,則errbuf存放出錯信息字符串,errbuf至少應該是PCAP_ERRBUF_SIZE個字節長度的。注意,很多libpcap函數都有這個參數。
pcap_lookupdev()一般可以在跨平臺的,且各個平臺上的網絡接口名稱都不相同的情況下使用。
如果我們手動指定要監聽的網絡接口,則這一步跳過,我們在第二步中將要監聽的網絡接口字符串硬編碼在pcap_open_live裏。
2.釋放網絡接口
在操作爲網絡接口後,我們應該要釋放它:
void pcap_close(pcap_t * p)
該函數用於關閉pcap_open_live()獲取的pcap_t的網絡接口對象並釋放相關資源。
3.打開網絡接口
獲取網絡接口後,我們需要打開它:
pcap_t * pcap_open_live(const char * device, int snaplen, int promisc, int to_ms, char * errbuf)
上面這個函數會返回指定接口的pcap_t類型指針,後面的所有操作都要使用這個指針。
第一個參數是第一步獲取的網絡接口字符串,可以直接使用硬編碼。
第二個參數是對於每個數據包,從開頭要抓多少個字節,我們可以設置這個值來只抓每個數據包的頭部,而不關心具體的內容。典型的以太網幀長度是1518字節,但其他的某些協議的數據包會更長一點,但任何一個協議的一個數據包長度都必然小於65535個字節。
第三個參數指定是否打開混雜模式(Promiscuous Mode),0表示非混雜模式,任何其他值表示混合模式。如果要打開混雜模式,那麼網卡必須也要打開混雜模式,可以使用如下的命令打開eth0混雜模式:
ifconfig eth0 promisc
第四個參數指定需要等待的毫秒數,超過這個數值後,第3步獲取數據包的這幾個函數就會立即返回。0表示一直等待直到有數據包到來。
第五個參數是存放出錯信息的數組。
4.獲取數據包
打開網絡接口後就已經開始監聽了,那如何知道收到了數據包呢?有下面3種方法:
a)
u_char * pcap_next(pcap_t * p, struct pcap_pkthdr * h)
如果返回值爲NULL,表示沒有抓到包
第一個參數是第2步返回的pcap_t類型的指針
第二個參數是保存收到的第一個數據包的pcap_pkthdr類型的指針
pcap_pkthdr類型的定義如下:
- struct pcap_pkthdr
- {
- struct timeval ts; /* time stamp */
- bpf_u_int32 caplen; /* length of portion present */
- bpf_u_int32 len; /* length this packet (off wire) */
- };
注意這個函數只要收到一個數據包後就會立即返回
b)
int pcap_loop(pcap_t * p, int cnt, pcap_handler callback, u_char * user)
第一個參數是第2步返回的pcap_t類型的指針
第二個參數是需要抓的數據包的個數,一旦抓到了cnt個數據包,pcap_loop立即返回。負數的cnt表示pcap_loop永遠循環抓包,直到出現錯誤。
第三個參數是一個回調函數指針,它必須是如下的形式:
void callback(u_char * userarg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
第一個參數是pcap_loop的最後一個參數,當收到足夠數量的包後pcap_loop會調用callback回調函數,同時將pcap_loop()的user參數傳遞給它
第二個參數是收到的數據包的pcap_pkthdr類型的指針
第三個參數是收到的數據包數據
c)
int pcap_dispatch(pcap_t * p, int cnt, pcap_handler callback, u_char * user)
這個函數和pcap_loop()非常類似,只是在超過to_ms毫秒後就會返回(to_ms是pcap_open_live()的第4個參數)
例子:
test2:
- #include <pcap.h>
- #include <time.h>
- #include <stdlib.h>
- #include <stdio.h>
- int main()
- {
- char errBuf[PCAP_ERRBUF_SIZE], * devStr;
- /* get a device */
- devStr = pcap_lookupdev(errBuf);
- if(devStr)
- {
- printf("success: device: %s\n", devStr);
- }
- else
- {
- printf("error: %s\n", errBuf);
- exit(1);
- }
- /* open a device, wait until a packet arrives */
- pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);
- if(!device)
- {
- printf("error: pcap_open_live(): %s\n", errBuf);
- exit(1);
- }
- /* wait a packet to arrive */
- struct pcap_pkthdr packet;
- const u_char * pktStr = pcap_next(device, &packet);
- if(!pktStr)
- {
- printf("did not capture a packet!\n");
- exit(1);
- }
- printf("Packet length: %d\n", packet.len);
- printf("Number of bytes: %d\n", packet.caplen);
- printf("Recieved time: %s\n", ctime((const time_t *)&packet.ts.tv_sec));
- pcap_close(device);
- return 0;
- }
打開兩個終端,先ping 192.168.1.10,由於我們的ip是192.168.1.1,因此我們可以收到廣播的數據包,另一個終端運行test,就會抓到這個包。
下面的這個程序會把收到的數據包內容全部打印出來,運行方式和上一個程序一樣:
test3:
- #include <pcap.h>
- #include <time.h>
- #include <stdlib.h>
- #include <stdio.h>
- void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
- {
- int * id = (int *)arg;
- printf("id: %d\n", ++(*id));
- printf("Packet length: %d\n", pkthdr->len);
- printf("Number of bytes: %d\n", pkthdr->caplen);
- printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec));
- int i;
- for(i=0; i<pkthdr->len; ++i)
- {
- printf(" %02x", packet[i]);
- if( (i + 1) % 16 == 0 )
- {
- printf("\n");
- }
- }
- printf("\n\n");
- }
- int main()
- {
- char errBuf[PCAP_ERRBUF_SIZE], * devStr;
- /* get a device */
- devStr = pcap_lookupdev(errBuf);
- if(devStr)
- {
- printf("success: device: %s\n", devStr);
- }
- else
- {
- printf("error: %s\n", errBuf);
- exit(1);
- }
- /* open a device, wait until a packet arrives */
- pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);
- if(!device)
- {
- printf("error: pcap_open_live(): %s\n", errBuf);
- exit(1);
- }
- /* wait loop forever */
- int id = 0;
- pcap_loop(device, -1, getPacket, (u_char*)&id);
- pcap_close(device);
- return 0;
- }
從上圖可以看出,如果我們沒有按Ctrl+c,test會一直抓到包,因爲我們將pcap_loop()設置爲永遠循環
由於ping屬於icmp協議,並且發出icmp協議數據包之前必須先通過arp協議獲取目的主機的mac地址,因此我們抓到的包是arp協議的,而arp協議的數據包長度正好是42字節(14字節的以太網幀頭+28字節的arp數據)。具體內容請參考相關網絡協議說明。
5.分析數據包
我們既然已經抓到數據包了,那麼我們要開始分析了,這部分留給讀者自己完成,具體內容可以參考相關的網絡協議說明。在本文的最後,我會示範性的寫一個分析arp協議的sniffer,僅供參考。要特別注意一點,網絡上的數據是網絡字節順序的,因此分析前需要轉換爲主機字節順序(ntohs()函數)。
6.過濾數據包
我們抓到的數據包往往很多,如何過濾掉我們不感興趣的數據包呢?
幾乎所有的操作系統(BSD, AIX, Mac OS, Linux等)都會在內核中提供過濾數據包的方法,主要都是基於BSD Packet Filter(BPF)結構的。libpcap利用BPF來過濾數據包。
過濾數據包需要完成3件事:
a) 構造一個過濾表達式
b) 編譯這個表達式
c) 應用這個過濾器
a)
BPF使用一種類似於彙編語言的語法書寫過濾表達式,不過libpcap和tcpdump都把它封裝成更高級且更容易的語法了,具體可以man tcpdump,以下是一些例子:
src host 192.168.1.177
只接收源ip地址是192.168.1.177的數據包
dst port 80
只接收tcp/udp的目的端口是80的數據包
not tcp
只接收不使用tcp協議的數據包
tcp[13] == 0x02 and (dst port 22 or dst port 23)
只接收SYN標誌位置位且目標端口是22或23的數據包(tcp首部開始的第13個字節)
icmp[icmptype] == icmp-echoreply or icmp[icmptype] == icmp-echo
只接收icmp的ping請求和ping響應的數據包
ehter dst 00:e0:09:c1:0e:82
只接收以太網mac地址是00:e0:09:c1:0e:82的數據包
ip[8] == 5
只接收ip的ttl=5的數據包(ip首部開始的第8個字節)
b)
構造完過濾表達式後,我們需要編譯它,使用如下函數:
int pcap_compile(pcap_t * p, struct bpf_program * fp, char * str, int optimize, bpf_u_int32 netmask)
fp:這是一個傳出參數,存放編譯後的bpf
str:過濾表達式
optimize:是否需要優化過濾表達式
metmask:簡單設置爲0即可
c)
最後我們需要應用這個過濾表達式:
int pcap_setfilter(pcap_t * p, struct bpf_program * fp)
第二個參數fp就是前一步pcap_compile()的第二個參數
應用完過濾表達式之後我們便可以使用pcap_loop()或pcap_next()等抓包函數來抓包了。
下面的程序演示瞭如何過濾數據包,我們只接收目的端口是80的數據包:
test4.c
- #include <pcap.h>
- #include <time.h>
- #include <stdlib.h>
- #include <stdio.h>
- void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
- {
- int * id = (int *)arg;
- printf("id: %d\n", ++(*id));
- printf("Packet length: %d\n", pkthdr->len);
- printf("Number of bytes: %d\n", pkthdr->caplen);
- printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec));
- int i;
- for(i=0; i<pkthdr->len; ++i)
- {
- printf(" %02x", packet[i]);
- if( (i + 1) % 16 == 0 )
- {
- printf("\n");
- }
- }
- printf("\n\n");
- }
- int main()
- {
- char errBuf[PCAP_ERRBUF_SIZE], * devStr;
- /* get a device */
- devStr = pcap_lookupdev(errBuf);
- if(devStr)
- {
- printf("success: device: %s\n", devStr);
- }
- else
- {
- printf("error: %s\n", errBuf);
- exit(1);
- }
- /* open a device, wait until a packet arrives */
- pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);
- if(!device)
- {
- printf("error: pcap_open_live(): %s\n", errBuf);
- exit(1);
- }
- /* construct a filter */
- struct bpf_program filter;
- pcap_compile(device, &filter, "dst port 80", 1, 0);
- pcap_setfilter(device, &filter);
- /* wait loop forever */
- int id = 0;
- pcap_loop(device, -1, getPacket, (u_char*)&id);
- pcap_close(device);
- return 0;
- }
在下面的這一個例子中,客戶機通過tcp的9732端口連接服務器,發送字符'A',之後服務器將'A'+1即'B'返回給客戶機,具體實現可以參考:http://blog.csdn.net/htttw/article/details/7519964
服務器的ip是192.168.56.101,客戶機的ip是192.168.56.1
服務器:
Makefile:
- all: tcp_client.c tcp_server.c
- gcc -g -Wall -o tcp_client tcp_client.c
- gcc -g -Wall -o tcp_server tcp_server.c
- clean:
- rm -rf *.o tcp_client tcp_server
tcp_server:
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #define PORT 9832
- #define SERVER_IP "192.168.56.101"
- int main()
- {
- /* create a socket */
- int server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
- struct sockaddr_in server_addr;
- server_addr.sin_family = AF_INET;
- server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
- server_addr.sin_port = htons(PORT);
- /* bind with the local file */
- bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
- /* listen */
- listen(server_sockfd, 5);
- char ch;
- int client_sockfd;
- struct sockaddr_in client_addr;
- socklen_t len = sizeof(client_addr);
- while(1)
- {
- printf("server waiting:\n");
- /* accept a connection */
- client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &len);
- /* exchange data */
- read(client_sockfd, &ch, 1);
- printf("get char from client: %c\n", ch);
- ++ch;
- write(client_sockfd, &ch, 1);
- /* close the socket */
- close(client_sockfd);
- }
- return 0;
- }
tcp_client:
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #define PORT 9832
- #define SERVER_IP "192.168.56.101"
- int main()
- {
- /* create a socket */
- int sockfd = socket(AF_INET, SOCK_STREAM, 0);
- struct sockaddr_in address;
- address.sin_family = AF_INET;
- address.sin_addr.s_addr = inet_addr(SERVER_IP);
- address.sin_port = htons(PORT);
- /* connect to the server */
- int result = connect(sockfd, (struct sockaddr *)&address, sizeof(address));
- if(result == -1)
- {
- perror("connect failed: ");
- exit(1);
- }
- /* exchange data */
- char ch = 'A';
- write(sockfd, &ch, 1);
- read(sockfd, &ch, 1);
- printf("get char from server: %c\n", ch);
- /* close the socket */
- close(sockfd);
- return 0;
- }
在客戶機上運行下列命令來清空記錄服務器的arp緩存:
sudo arp -d 192.168.56.101
arp -a後發現已經刪除了記錄服務器的arp緩存
抓包的結果如下所示,由於包太多了,無法全部截圖,因此我把所有內容保存在下面的文本中了:
全部的包如下:
- hutao@hutao-VirtualBox:~/test3$ sudo ./test
- success: device: eth0
- id: 1
- Packet length: 60
- Number of bytes: 60
- Recieved time: Sat Apr 28 19:57:50 2012
- ff ff ff ff ff ff 0a 00 27 00 00 00 08 06 00 01
- 08 00 06 04 00 01 0a 00 27 00 00 00 c0 a8 38 01
- 00 00 00 00 00 00 c0 a8 38 65 00 00 00 00 00 00
- 00 00 00 00 00 00 00 00 00 00 00 00
- id: 2
- Packet length: 42
- Number of bytes: 42
- Recieved time: Sat Apr 28 19:57:50 2012
- 0a 00 27 00 00 00 08 00 27 9c ff b1 08 06 00 01
- 08 00 06 04 00 02 08 00 27 9c ff b1 c0 a8 38 65
- 0a 00 27 00 00 00 c0 a8 38 01
- id: 3
- Packet length: 74
- Number of bytes: 74
- Recieved time: Sat Apr 28 19:57:50 2012
- 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
- 00 3c d4 af 40 00 40 06 74 55 c0 a8 38 01 c0 a8
- 38 65 8e 20 26 68 79 e1 63 8c 00 00 00 00 a0 02
- 39 08 d4 13 00 00 02 04 05 b4 04 02 08 0a 00 14
- b7 23 00 00 00 00 01 03 03 06
- id: 4
- Packet length: 74
- Number of bytes: 74
- Recieved time: Sat Apr 28 19:57:50 2012
- 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
- 00 3c 00 00 40 00 40 06 49 05 c0 a8 38 65 c0 a8
- 38 01 26 68 8e 20 b6 c4 e6 e5 79 e1 63 8d a0 12
- 38 90 f1 e5 00 00 02 04 05 b4 04 02 08 0a 00 57
- a1 2c 00 14 b7 23 01 03 03 05
- id: 5
- Packet length: 66
- Number of bytes: 66
- Recieved time: Sat Apr 28 19:57:50 2012
- 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
- 00 34 d4 b0 40 00 40 06 74 5c c0 a8 38 01 c0 a8
- 38 65 8e 20 26 68 79 e1 63 8d b6 c4 e6 e6 80 10
- 00 e5 fb c1 00 00 01 01 08 0a 00 14 b7 24 00 57
- a1 2c
- id: 6
- Packet length: 67
- Number of bytes: 67
- Recieved time: Sat Apr 28 19:57:50 2012
- 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
- 00 35 d4 b1 40 00 40 06 74 5a c0 a8 38 01 c0 a8
- 38 65 8e 20 26 68 79 e1 63 8d b6 c4 e6 e6 80 18
- 00 e5 ba b7 00 00 01 01 08 0a 00 14 b7 25 00 57
- a1 2c 41
- id: 7
- Packet length: 66
- Number of bytes: 66
- Recieved time: Sat Apr 28 19:57:50 2012
- 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
- 00 34 47 cb 40 00 40 06 01 42 c0 a8 38 65 c0 a8
- 38 01 26 68 8e 20 b6 c4 e6 e6 79 e1 63 8e 80 10
- 01 c5 f1 dd 00 00 01 01 08 0a 00 57 a1 2e 00 14
- b7 25
- id: 8
- Packet length: 67
- Number of bytes: 67
- Recieved time: Sat Apr 28 19:57:50 2012
- 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
- 00 35 47 cc 40 00 40 06 01 40 c0 a8 38 65 c0 a8
- 38 01 26 68 8e 20 b6 c4 e6 e6 79 e1 63 8e 80 18
- 01 c5 f1 de 00 00 01 01 08 0a 00 57 a1 2e 00 14
- b7 25 42
- id: 9
- Packet length: 66
- Number of bytes: 66
- Recieved time: Sat Apr 28 19:57:50 2012
- 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
- 00 34 47 cd 40 00 40 06 01 40 c0 a8 38 65 c0 a8
- 38 01 26 68 8e 20 b6 c4 e6 e7 79 e1 63 8e 80 11
- 01 c5 f1 dd 00 00 01 01 08 0a 00 57 a1 2e 00 14
- b7 25
- id: 10
- Packet length: 66
- Number of bytes: 66
- Recieved time: Sat Apr 28 19:57:50 2012
- 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
- 00 34 d4 b2 40 00 40 06 74 5a c0 a8 38 01 c0 a8
- 38 65 8e 20 26 68 79 e1 63 8e b6 c4 e6 e7 80 10
- 00 e5 fb bc 00 00 01 01 08 0a 00 14 b7 25 00 57
- a1 2e
- id: 11
- Packet length: 66
- Number of bytes: 66
- Recieved time: Sat Apr 28 19:57:50 2012
- 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
- 00 34 d4 b3 40 00 40 06 74 59 c0 a8 38 01 c0 a8
- 38 65 8e 20 26 68 79 e1 63 8e b6 c4 e6 e7 80 11
- 00 e5 fb bb 00 00 01 01 08 0a 00 14 b7 25 00 57
- a1 2e
- id: 12
- Packet length: 66
- Number of bytes: 66
- Recieved time: Sat Apr 28 19:57:50 2012
- 0a 00 27 00 00 00 08 00 27 9c ff b1 08 00 45 00
- 00 34 47 ce 40 00 40 06 01 3f c0 a8 38 65 c0 a8
- 38 01 26 68 8e 20 b6 c4 e6 e8 79 e1 63 8f 80 10
- 01 c5 f1 dd 00 00 01 01 08 0a 00 57 a1 2e 00 14
- b7 25
- id: 13
- Packet length: 66
- Number of bytes: 66
- Recieved time: Sat Apr 28 19:57:50 2012
- 08 00 27 9c ff b1 0a 00 27 00 00 00 08 00 45 00
- 00 34 d4 b4 40 00 40 06 74 58 c0 a8 38 01 c0 a8
- 38 65 8e 20 26 68 79 e1 63 8f b6 c4 e6 e8 80 10
- 00 e5 fb b9 00 00 01 01 08 0a 00 14 b7 26 00 57
- a1 2e
仔細研究即可發現服務器與客戶機是如何通過tcp通信的。
下面的這個程序可以獲取eth0的ip和子網掩碼等信息:
test5:
- #include <stdio.h>
- #include <stdlib.h>
- #include <pcap.h>
- #include <errno.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- int main()
- {
- /* ask pcap to find a valid device for use to sniff on */
- char * dev; /* name of the device */
- char errbuf[PCAP_ERRBUF_SIZE];
- dev = pcap_lookupdev(errbuf);
- /* error checking */
- if(!dev)
- {
- printf("pcap_lookupdev() error: %s\n", errbuf);
- exit(1);
- }
- /* print out device name */
- printf("dev name: %s\n", dev);
- /* ask pcap for the network address and mask of the device */
- bpf_u_int32 netp; /* ip */
- bpf_u_int32 maskp; /* subnet mask */
- int ret; /* return code */
- ret = pcap_lookupnet(dev, &netp, &maskp, errbuf);
- if(ret == -1)
- {
- printf("pcap_lookupnet() error: %s\n", errbuf);
- exit(1);
- }
- /* get the network address in a human readable form */
- char * net; /* dot notation of the network address */
- char * mask; /* dot notation of the network mask */
- struct in_addr addr;
- addr.s_addr = netp;
- net = inet_ntoa(addr);
- if(!net)
- {
- perror("inet_ntoa() ip error: ");
- exit(1);
- }
- printf("ip: %s\n", net);
- /* do the same as above for the device's mask */
- addr.s_addr = maskp;
- mask = inet_ntoa(addr);
- if(!mask)
- {
- perror("inet_ntoa() sub mask error: ");
- exit(1);
- }
- printf("sub mask: %s\n", mask);
- return 0;
- }
結果如圖:
int pcap_lookupnet(const char * device, bpf_u_int32 * netp, bpf_u_int32 * maskp, char * errbuf)
可以獲取指定設備的ip地址,子網掩碼等信息
netp:傳出參數,指定網絡接口的ip地址
maskp:傳出參數,指定網絡接口的子網掩碼
我們使用inet_ntoa()將其轉換爲可讀的點分十進制形式的字符串
本文的絕大部分來源於libpcap的官方文檔:libpcapHakin9LuisMartinGarcia.pdf,可以在官網下載,文檔只有9頁,不過很詳細,還包括了數據鏈路層,網絡層,傳輸層,應用層等的分析。很好!
更多參考可以man pcap
最後爲了方便大家,本文的所有代碼和上述的pdf文檔都一併上傳上來了:
http://download.csdn.net/detail/htttw/4264686
完成!