1. Libpcap的安装:
下载压缩包,解压
./configure
make
sudo make install
2. Libpcap的使用
注意两点:
-lpcap
使用root权限
自动获取网络接口:
char * pcap_lookupdev(char * errbuf)
参数:如果出错,则errbuf存放出错信息字符串,errbuf至少应该是PCAP_ERRBUF_SIZE个字节长度的
返回值:返回第一个合适的网络接口的字符串指针
打开网络接口:
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表示一直等待直到有数据包到来。
第五个参数:存放出错信息的数组。
释放网络接口:
void pcap_close(pcap_t * p)
获取数据包:
int pcap_loop(pcap_t * p, int cnt, pcap_handler callback, u_char * user)
第一个参数:返回的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类型的指针
第三个参数:收到的数据包数据
#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 8888
#define SERVER_IP "192.168.1.153"
int main()
{
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(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
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(client_sockfd);
}
return 0;
}
根据以上代码编写客户端,运行后可查看接收到的具体数据包。
int pcap_lookupnet(const char * device, bpf_u_int32 * netp, bpf_u_int32 * maskp, char * errbuf)
可以获取指定设备的ip地址,子网掩码等信息
netp:传出参数,指定网络接口的ip地址
maskp:传出参数,指定网络接口的子网掩码
pcap_lookupnet()失败返回-1