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节中的相关内容。