LIBPCAP用户命令编译过程发现

本文深入剖析libpcap库中用户命令如何被编译成BPF指令的过程,详细解释了`pcap_compile()`、`icode_to_fcode()`和`gen_retblk()`等关键函数的作用,以及在TCPDUMP中的应用。通过对源代码的阅读,阐述了命令解析和执行的路径,揭示了libpcap如何将用户输入转化为内核中BPF解释器可执行的指令。

本文以笔者对libpcap用户名另编译和执行过程为主线,在libpcap源代码中进行挖掘,旨在记录当下本人对源代码阅读的思路和阅读代码过程中的整理和参考文献汇总。

TCPDUMP是允许用于命令行操作的网络数据包嗅探工具,其工作流程主要有两个部分:用户字符串命令解析(compile)、以及解析后指令下发至设备进行运作。通过参考tcpdump-4.3.0中tcpdump.c文件,发现其对用户字符串命令的解析过程通过调用libpcap库中的pcap_compile()函数来实现,具体如下所示,于是转战libpcap寻找用户命令解析和执行的真正所在。

if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
  error("%s", pcap_geterr(pd));

一、有关用户字符串指令解析为BPF指令过程

(1)pcap_compile()

首先定位到tcpdump调用的pcap_compile()函数位置,处于gencode.c文件中,具体格式如下所示:

int
pcap_compile(pcap_t *p, struct bpf_program *program,
	     const char *buf, int optimize, bpf_u_int32 mask)
{
	int result;

	EnterCriticalSection(&g_PcapCompileCriticalSection);

	result = pcap_compile_unsafe(p, program, buf, optimize, mask);

	LeaveCriticalSection(&g_PcapCompileCriticalSection);
	
	return result;
}

这里先对pcap_compile()函数做一个解释,pcap_compile函数返回int类型值,由tcpdump.c中对pcap_compile()使用的情况可知,其返回值目的在于辨识该函数对用户命令的编译是否正确执行。该函数有五个参数,pcap_t 类型指针p、bpf_program结构指针program、指向字符串的指针buf、整型optimize和无符号整型mask。

参数一:pcap_t(即pcap)是贯穿libpcap各个函数的libpcap自定义结构体类型,其定义存在于pcap-int.h中,本人对该结构体设计原因的理解是:该结构体囊括了用于包过滤过程中所需要使用的所有参数,于是其先用于接受用户的包过滤命令并以pcap规定格式进行保存,后用于向下BPF内核包过滤命令解释器(很多部分会翻译成BPF虚拟机,但本人认为解释器一说更为贴切和易于理解)传递参数和向网络接口设备进行配置。

struct pcap {
#ifdef WIN32
	ADAPTER *adapter;
	LPPACKET Packet;
	int nonblock;
#else
	int fd;                
	int selectable_fd;
	int send_fd;
#endif /* WIN32 */

#ifdef HAVE_LIBDLPI
	dlpi_handle_t dlpi_hd;
#endif
	int snapshot;           //用户期望捕获数据包的最大长度
	int linktype;		/* Network linktype */
	int linktype_ext;       /* Extended information stored in the linktype field of a file */
	int tzoff;		/* timezone offset */
	int offset;		/* offset for proper alignment */
	int activated;		/* true if the capture is really started */
	int oldstyle;		/* if we're opening with pcap_open_live() */

	int break_loop;		/* flag set to force break from packet-reading loop */

#ifdef PCAP_FDDIPAD
	int fddipad;
#endif

#ifdef MSDOS
        void (*wait_proc)(void); /*          call proc while waiting */
#endif

	struct pcap_sf sf;
	struct pcap_md md;
	struct pcap_opt opt;

	/*
	 * Read buffer.
	 */
	int bufsize;
	u_char *buffer;
	u_char *bp;
	int cc;

	/*
	 * Place holder for pcap_next().
	 */
	u_char *pkt;

	/* We're accepting only packets in this direction/these directions. */
	pcap_direction_t direction;

	/*
	 * Methods.『?』
	 */
	activate_op_t activate_op;
	can_set_rfmon_op_t can_set_rfmon_op;
	read_op_t read_op;
	inject_op_t inject_op;
	setfilter_op_t setfilter_op;
	setdirection_op_t setdirection_op;
	set_datalink_op_t set_datalink_op;
	getnonblock_op_t getnonblock_op;
	setnonblock_op_t setnonblock_op;
	stats_op_t stats_op;

	/*
	 * Routine to use as callback for pcap_next()/pcap_next_ex().
	 */
	pcap_handler oneshot_callback;

#ifdef WIN32
	/*
	 * These are, at least currently, specific to the Win32 NPF
	 * driver.
	 */
	setbuff_op_t setbuff_op;
	setmode_op_t setmode_op;
	setmintocopy_op_t setmintocopy_op;
#endif
	cleanup_op_t cleanup_op;

	/*
	 * Placeholder for filter code if bpf not in kernel.
	 */
	struct bpf_program fcode;             

	char errbuf[PCAP_ERRBUF_SIZE + 1];    //函数调用出错信息缓存
	int dlt_count;
	u_int *dlt_list;
	int tstamp_type_count;
	u_int *tstamp_type_list;

	struct pcap_pkthdr pcap_header;	/* This is needed for
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值