9.3.2 使用过滤器的实例

此处展示如何把高级语言描述的过滤表达式编译为虚拟机字节码,结果以C程序格式输出,这与Tcpdump或WinDump采用-dd参数的输出格式一致。实例程序的使用格式如下:


filter_nopcap[-O]过滤表达式


添加-O参数表示将不对输出的指令进行优化处理。

实例程序的主要部分如下,其完整代码见[ch9/filter_nopcap工程]:


defne WIN32

defne HAVE_REMOTE

include<stdio.h>

include"pcap.h"

defne flter_len 1024

int main(int argc,char*argv[])

{

int offset=0;

charflter_buf=(char)malloc(flter_len);

int optimize=1;//优化

int arg_begin=1;

memset(flter_buf,0x0,flter_len);

if(argc<=1)

{//如果命令不带参数,默认过滤表达式为"ip",且不执行优化

strcpy(flter_buf,"ip");

optimize=0;//不优化

}

else

{

/决定是否需要优化指令/

if(strcmp(argv[1],"-O")==0)

{

optimize=0;//不优化

arg_begin=2;

}

else

{

optimize=1;//优化

arg_begin=1;

}

/从命令行中获得过滤表达式/

for(int i=arg_begin;i<argc;i++)

{

strcpy(flter_buf+offset,argv[i]);

offset=offset+strlen(argv[i])+1;

memset(flter_buf+offset-1,'',1);

}

}

/打印过滤表达式/

printf(“过滤表达式:%s\n”,filter_buf);

/设置网络掩码,以太网IP协议/

bpf_u_int32 netmask=0xffffff;

struct bpf_program program;

/执行转换/

int ret=pcap_compile_nopcap(96,

DLT_EN10MB,

&program,

flter_buf,

optimize,

netmask

);

if(ret<0)

{

printf("error.\n");

free(flter_buf);

return-1;

}

/打印指令条数/

printf("program.bf_len=%d\n",program.bf_len);

/打印各指令/

for(int i=0;i<program.bf_len;i++)

{

printf("{0x%x,%u,%u,0x%.8x},\n",

program.bf_insns[i].code,program.bf_insns[i].jt,

program.bf_insns[i].jf,program.bf_insns[i].k);

}

/释放资源/

pcap_freecode(&program);

free(flter_buf);

return 0;

}


实例程序的测试结果如下:


>flter_nopcap ip or arp//优化

过滤表达式:ip or arp

program.bf_len=5

{0x28,0,0,0x0000000c},

{0x15,1,0,0x00000800},

{0x15,0,1,0x00000806},

{0x6,0,0,0x00000060},

{0x6,0,0,0x00000000},

>flter_nopcap-O ip or arp//不优化

过滤表达式:ip or arp

program.bf_len=6

{0x28,0,0,0x0000000c},

{0x15,2,0,0x00000800},

{0x28,0,0,0x0000000c},

{0x15,0,1,0x00000806},

{0x6,0,0,0x00000060},

{0x6,0,0,0x00000000},


接下来,使用Tcpdump工具来验证实例程序对过滤表达式的转换是否正确。


$tcpdump-dd ip or arp//优化

{0x28,0,0,0x0000000c},

{0x15,1,0,0x00000800},

{0x15,0,1,0x00000806},

{0x6,0,0,0x00000060},

{0x6,0,0,0x00000000},

$tcpdump-Odd ip or arp//不优化

{0x28,0,0,0x0000000c},

{0x15,2,0,0x00000800},

{0x28,0,0,0x0000000c},

{0x15,0,1,0x00000806},

{0x6,0,0,0x00000060},

{0x6,0,0,0x00000000},


由上述结果可知,实例程序的输出结果与采用Tcpdump工具获得的输出一致。

要想了解如何在捕获数据包的情况下使用过滤器,可参见第10.1.2节中的相关内容。