网络编程第三方库——libpcap库(接收)

一、主要作用

1、捕获各种数据包
eg:网络流量统计

2、过滤网络数据包
eg:过滤掉本地的一些数据,类似防火墙

3、分析网络数据包
eg:分析网络协议,数据的采集

4、存储网络数据包
eg:保存捕获的数据以为将来进行分析

二、ubuntu安装指令

sudo apt-get install libpcap-dev

三、使用libcap库的开发步骤

①打开网络设备
②设备过滤规则(可选)
③捕获数据
④关闭网络设备

头文件:#include <pcap.h>
编译时需要加上: -lpcap

四、 捕获网络数据常用函数

①查看设备名称

pcap_lookupdev( )

原型

char *pcap_lookupdev(char *errbuf)

功能:得到可用的网络设备名指针

参数:errbuf:存放相关的错误信息

返回值:成功返回设备名指针;
      失败返回NULL

例子:

char *dev = NULL;
char *err_buf[100]="";
dev = pcap_lookupdev(err_buf);
if(dev ==NULL)
{
	perror("pcap_lookupdev");
	exit(-1);
}

②打开捕获数据接口,获取句柄

pcap_open_live( )

原型:

pcap_t *pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf);

功能:打开一个用于捕获数据的接口

参数:device:网络接口的名字
	 snaplen:捕获数据包的长度
	 promise:1代表混杂模式,其他代表非混杂模式
	 to_ms:等待时间
	 ebuf:存储错误信息

返回值:返回一个Libpcap句柄 

例子:

char error_content[PACP_ERRBUF_SIZE]="";
pcap_t * pcap_handle=NULL;
pcap_handle = pcap_open_live("eth0",1024,1,0,error_content);

③获取设备IP

pcap_lookupnet( )
原型:

int pcap_lookupnet(char *device, buf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf);

功能:获得指定网络设备的网络号和掩码

函数:device:网络设备名
	 netp:存放网络号的指针
	 maskp:存放掩码的指针
	 errbuf:存放出错信息

返回值:成功:0,失败:-1
     

例子:

unsigned int net_ip;    //网络地址
unsigned int net_mask;    //子网掩码
 
res = pcap_lookupnet(dev, &net_ip, &net_mask, error_content);
if(res == -1)
{
    perror("pcap_lookupnet");
    exit(-1);
}

④设置过滤规则(以下两个函数配合使用)

1、pcap_compile( ) 将用户的规则转换成pcap的规则
原型:

int pcap_compile(pcap_t *p, struct bpf_program *program, char *buf,
                 int optimize, bpf_u_int32 mask);
功能:编译BPF过滤规则

参数:p:Libpcap句柄
     program:bpf过滤规则(pcap识别的规则)
     buf:过滤规则字符串(用户识别的规则)
     optimize:优化
     mask:掩码

返回值:成功返回0,失败返回-1

例子:

struct bpf_program bpf_filter;
char *bpf_filter_string = "arp or ip";
if(pcap_compile(pcap_handle,&bpf_filter,bpf_filter_string,0,0xffffff00)<0)//编译BPF过滤规则
{
	perror("pcap_compile");
}

2、pcap_setfillter( ) 将pcap识别的规则,设置到pcap结束数据的句柄中
原型:

int pcap_setfilter(pcap *p, struct bpf_program *fp);

功能:设置BPF过滤规则

参数:p:Libpcap句柄
    fp:BPF过滤规则

返回值:成功返回0,失败返回-1

例子:

if(pcap_setfilter(pcap_handle,&bpf_filter<0) )
{
	perror("pcap_setfilter");
}

过滤规则:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
设置捕获源端口9000的报文规则

#include <stdio.h>
#include <pcap.h>

//pcap_loop每收到一个报文,就会调用一次回调函数
void callback(u_char *arg,const struct pcap_pkthdr *packet_header,const u_char *packet_content)
{
	unsigned char *msg = packet_content;
	
	printf("报文长度:%u\n",packet_header->caplen);
	//msg的地址解析和原始套接字一样
	//解析msg的mac地址
	char src_mac[18] = "";
	char dst_mac[18] = "";
	sprintf(dst_mac,"02x:02x:02x:02x:02x:02x",msg[0],msg[1],msg[2],msg[3],msg[4],msg[5]);
	sprintf(src_mac,"02x:02x:02x:02x:02x:02x",msg[0+6],msg[1+6],msg[2+6],msg[3+6],msg[4+6],msg[5+6]);
	printf("%s--->%s\n",src_mac,dst_mac);
}

int main()
{
	//1.创建一个pcap句柄
	pcap_t *pcap_handle = NULL;
	pcap_handle = pcap_open_live("enp0s3",1500,0,0,NULL);

	//设置过滤规则
	struct bpf_program program;
	pcap_compile(pcap_handle,&program,"src port 9000",0,0xffffff00);
	pcap_setfilter(pcap_handle,&program);
	//2.接收数据
	//带阻塞
	pcap_loop(pcap_handle,5,callback,NULL);

	//关闭句柄
	pcap_close(pcap_handle);

	return 0;
}

⑤捕获接收数据

1、pcap_next( ) ;调用一次只接收一个报文

struct pcap_pkthdr结构体头信息:记录接收数据的时间及报文长度在这里插入图片描述

原型:

const u_cahr *pcap_next(pacp_t *p, struct pcap_pkthdr *h);

功能:捕获一个网络数据包

参数:p:Libpcap句柄
	h:数据包头

返回值:捕获的数据包的地址

例子:

#include <stdio.h>
#include <pcap.h>

int main()
{
	//1.创建一个pcap句柄
	pcap_t *pcap_handle = NULL;
	pcap_handle = pcap_open_live("enp0s3",1500,0,0,NULL);

	//2.接收数据
	//定义头信息
	struct pcap_pkthdr pck_hdr;	//记录收到数据的时间和报文长度
	unsigned char *msg = "";	//存放接收到的帧数据 msg:ip udp/tcp data
	msg = pcap_next(pcap_handle, &pck_hdr);
	printf("报文长度:%u\n",pck_hdr.caplen);
	//msg的地址解析和原始套接字一样
	//解析msg的mac地址
	char src_mac[18] = "";
	char dst_mac[18] = "";
	sprintf(dst_mac,"02x:02x:02x:02x:02x:02x",msg[0],msg[1],msg[2],msg[3],msg[4],msg[5]);
	sprintf(src_mac,"02x:02x:02x:02x:02x:02x",msg[0+6],msg[1+6],msg[2+6],msg[3+6],msg[4+6],msg[5+6]);
	printf("%s--->%s\n",src_mac,dst_mac);


	//关闭句柄
	pcap_close(pcap_handle);

	return 0;
}

2、pcap_loop( ); 调用一次不停接收报文
原型:

int pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user);

功能:循环捕获网络数据包,指导遇到错误或者满足退出条件。每捕获一个数据包就会调用callback指示的回调函数,
	所以,可以再回调函数中进行数据包的处理操作。

参数:p:Libpcap句柄
    cnt:指定捕获数据包的个数,如果是-1,就会永无休止的捕获。
    callbcak:回调函数
    user:向回调函数中传递的参数

返回值:成功返回0;失败返回负数

回调函数如何定义
在这里插入图片描述

定义回调函数:

定义回调函数
void callback(unsigned char *argument, 
              const struct pcap_pkthdr *packet_header,
		      const unsigned char *packet_content);

/*参数1:argument存放pcap_loop传递过来的user用户数据
  参数2:packet_header存放接收到的报文的时间以及长度
  参数3:packet_content接收到的网络帧数据
*/

例子:

#include <stdio.h>
#include <pcap.h>

//pcap_loop每收到一个报文,就会调用一次回调函数
void callback(u_char *arg,const struct pcap_pkthdr *packet_header,const u_char *packet_content)
{
	unsigned char *msg = packet_content;
	
	printf("报文长度:%u\n",packet_header->caplen);
	//msg的地址解析和原始套接字一样
	//解析msg的mac地址
	char src_mac[18] = "";
	char dst_mac[18] = "";
	sprintf(dst_mac,"02x:02x:02x:02x:02x:02x",msg[0],msg[1],msg[2],msg[3],msg[4],msg[5]);
	sprintf(src_mac,"02x:02x:02x:02x:02x:02x",msg[0+6],msg[1+6],msg[2+6],msg[3+6],msg[4+6],msg[5+6]);
	printf("%s--->%s\n",src_mac,dst_mac);
}

int main()
{
	//1.创建一个pcap句柄
	pcap_t *pcap_handle = NULL;
	pcap_handle = pcap_open_live("enp0s3",1500,0,0,NULL);

	//2.接收数据
	//带阻塞
	pcap_loop(pcap_handle,5,callback,NULL);

	//关闭句柄
	pcap_close(pcap_handle);

	return 0;
}

⑥关闭接口句柄

pcap_close( )
原型:

void pcap_close(pcap_t *p);

功能:关闭libpcap操作,并销毁相应的资源。

参数:p:需要关闭的Libpcap句柄

例子:

pcap_close(pacap_handle);
  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值