linux 下 tcpdump 详解 前篇(libpcap库源码分析)

本文介绍了Linux系统下tcpdump工具和libpcap库的使用,重点探讨libpcap库的原理,包括libpcap的主要接口函数:pcap_open_live、pcap_compile、pcap_setfilter和pcap_loop。文章分析了libpcap如何创建socket、设置过滤规则以及循环捕获网络数据包,并强调了libpcap在不同环境和协议下的处理方式。
摘要由CSDN通过智能技术生成

一 概述

用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具。 至于tcpdump参数如何使用,这不是本章讨论的重点。
liunx系统抓包工具,毫无疑问就是tcpdump。而windows的抓包工具,wireshark也是一款主流的抓包工具。wireshark 使用了winpcap库。tcpdump 基于 libpcap库。而winpcap库是类似于linux下的libpcap。 因此本文着重探讨libpcap库的原理。

二 libpcap库使用

在了解libpcap库原理前,先说下libpcap 库的几个接口。一般情况下我们要使用libpcap库抓包,会用到下面几个接口函数
1.打开一个用于捕获数据的网络接口

 pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
 
 / * -------------------------------------
	 device:网络接口的名字,为第一步获取的网络接口字符串(pcap_lookupdev() 的返回值 ),也可人为指定,如“eth0”。

	 snaplen:捕获数据包的长度,长度不能大于 65535 个字节。

	 promise:“1” 代表混杂模式,其它非混杂模式。

	 to_ms:指定需要等待的毫秒数,超过这个数值后,获取数据包的函数就会立即返回(这个函数不会阻塞,后面的抓包函数才会阻塞)。0 表示一直等待直到有数据包到来。

	 ebuf:存储错误信息。
 -------------------------------------------------------*/

2 获取指定网卡的 ip 地址,子网掩码

int	pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
 / *-------------------------------------
	 device:网络设备名,为第一步获取的网络接口字符串(pcap_lookupdev() 的返回值 ),也可人为指定,如“eth0”。
 
	 netp:存放 ip 地址的指针,bpf_u_int32 为 32 位无符号整型
 
 	maskp:存放子网掩码的指针,bpf_u_int32 为 32 位无符号整型
 
	 errbuf:存放出错信息
 -------------------------------------------------------*/

3 编译 BPF 过滤规则

int	pcap_compile(pcap_t *, struct bpf_program *, const char *, int, bpf_u_int32);
 / * -------------------------------------
	 p:pcap_open_live() 返回的 pcap_t 类型的指针

	 fp:存放编译后的 bpf,应用过滤规则时需要用到这个指针

	 buf:过滤条件

	 optimize:是否需要优化过滤表达式

	 mask:指定本地网络的网络掩码,不需要时可写 0
 -------------------------------------------------------*/

4 应用 BPF 过滤规则,让bpf规则生效

int pcap_setfilter( pcap_t * p,  struct bpf_program * fp );
 / * -------------------------------------
	 p:pcap_open_live() 返回的 pcap_t 类型的指针

 	fp:pcap_compile() 的第二个参数
 -------------------------------------------------------*/

5 循环捕获网络数据包

int	pcap_loop(pcap_t *, int, pcap_handler, u_char *);
 / * -------------------------------------
	p:pcap_open_live()返回的 pcap_t 类型的指针。

	cnt:指定捕获数据包的个数,一旦抓到了 cnt 个数据包,pcap_loop 立即返回。如果是 -1,就会永无休止的捕获,直到出现错误。

	callback:回调函数,名字任意,根据需要自行起名。

	user:向回调函数中传递的参数。

	callback 回调函数的定义:void  callback(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)

		userarg:pcap_loop() 的最后一个参数,当收到足够数量的包后 pcap_loop 会调用callback 回调函数,同时将pcap_loop()的user参数传递给它
		pkthdr:是收到数据包的 pcap_pkthdr 类型的指针,和 pcap_next() 第二个参数是一样的。
		packet :收到的数据包数据
 -------------------------------------------------------*/

6 释放网络接口

void pcap_close(pcap_t *p);

libpcap 用到最多的6个接口,还有一个查找网络接口设备名
char *pcap_lookupdev(char *errbuf); 你要是自己知道要抓的那个网口,就可以直接指定即可。
libpcap主要有两个重要的功能 (抓包 ,过滤)

  • 首先网络设备驱动程序会收集数据,会复制一份给内核BPF过滤器
  • 但是应用层大多数只关心自己想要的数据。因此应用层每个抓包模块,都会有自己想过滤的数据包,最终符合过滤规则的就把数据传给应用层。

在这里插入图片描述
看图可以简单理解下,这里不深入内核底层的交互,中篇会再细说。回归正题,接下来看代码集成libpcap抓包使用。

static void ethernet_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
	// 程序对抓到包的处理
	return;
}

static void * sniffer_thread_callback(void *param) {
	pthread_detach(pthread_self());
	printf("sniffer_thread_callback enter\n");
	int nDev =-(TYPE32)param;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值