📄 375.htm
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>apue</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center"> ● UNIX网络编程 (BM: clown) </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="370.htm">上一层</a>][<a href="376.htm">下一篇</a>]
<hr><p align="left"><small>发信人: shuke (莫失莫忘), 信区: Security <br>
标 题: snort源码分析(4) <br>
发信站: BBS 水木清华站 (Tue Oct 10 11:42:22 2000) <br>
<br>
<br>
现在看看snort如何实现对数据包的分析和检测入侵的。 <br>
<br>
在main函数的最后部分有如下语句,比较重要: <br>
<br>
/* Read all packets on the device. Continue until cnt packets read */ <br>
if(pcap_loop(pd, pv.pkt_cnt, (pcap_handler)ProcessPacket, NULL) < 0) <br>
{ <br>
...... <br>
} <br>
<br>
这里pcap_loop函数有4个参数,分别解释: <br>
<br>
pd是一个全局变量,表示文件描述符,在前面OpenPcap的调用中已经被正确地 <br>
赋值。前面说过,snort可以实时采集网络数据,也可以从文件读取数据进行分析。 <br>
在不同情况打开文件(或设备)时,pd分别用来处理文件,或者网卡设备接口。 <br>
<br>
pd是struct pcap类型的指针,该结构包括实际的文件描述符,缓冲区,等等 <br>
域,用来处理从相应的文件获取信息。 <br>
<br>
OpenPcap函数中对pd赋值的语句分别为: <br>
<br>
/* get the device file descriptor,打开网卡接口 */ <br>
pd = pcap_open_live(pv.interface, snaplen, <br>
pv.promisc_flag ? PROMISC : 0, READ_TIMEOUT, errorbuf); <br>
<br>
或者 <br>
<br>
/* open the file,打开文件 */ <br>
pd = pcap_open_offline(intf, errorbuf); <br>
<br>
于是,这个参数表明从哪里取得待分析的数据。 <br>
<br>
第2个参数是pv.pkt_cnt,表示总共要捕捉的包的数量。在main函数初始化时, <br>
缺省设置为-1,成为永真循环,一直捕捉直到程序退出: <br>
<br>
/* initialize the packet counter to loop forever */ <br>
pv.pkt_cnt = -1; <br>
<br>
或者在命令行中设置要捕捉的包的数量。前面ParseCmdLine(解析命令行)函数 <br>
的调用中,遇到参数n,重新设定pv.pkt_cnt的值。ParseCmdLine中相关语句如下: <br>
<br>
case 'n': /* grab x packets and exit */ <br>
pv.pkt_cnt = atoi(optarg); <br>
<br>
第3个参数是回调函数,该回调函数处理捕捉到的数据包。这里为函数 <br>
ProcessPacket,下面将详细解释该函数。 <br>
<br>
第4个参数是字符串指针,表示用户,这里设置为空。 <br>
<br>
在说明处理包的函数ProcessPacket之前,有必要解释一下pcap_loop的实现。 <br>
我们看到main函数只在if条件判断中调用了一次pacp_loop,那么循环一定是在 <br>
pcap_loop中做的了。察看pcap.c文件中pcap_loop的实现部分,我们发现的确如此: <br>
<br>
int <br>
pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) <br>
{ <br>
register int n; <br>
<br>
for (;;) { //for循环 <br>
if (p->sf.rfile != NULL) <br>
n = pcap_offline_read(p, cnt, callback, user); <br>
else { <br>
/* <br>
* XXX keep reading until we get something <br>
* (or an error occurs) <br>
*/ <br>
do { //do循环 <br>
n = pcap_read(p, cnt, callback, user); <br>
} while (n == 0); <br>
} <br>
if (n <= 0) <br>
return (n); //遇到错误,返回 <br>
if (cnt > 0) { <br>
cnt -= n; <br>
if (cnt <= 0) <br>
return (0); //到达指定数量,返回 <br>
} <br>
//只有以上两种返回情况 <br>
} <br>
} <br>
<br>
<br>
现在看看ProcessPacket的实现了,这个回调函数用来处理数据包。该函数是 <br>
是pcap_handler类型的,pcap.h中类型的定义如下: <br>
<br>
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, <br>
const u_char *); <br>
<br>
第1个参数这里没有什么用; <br>
<br>
第2个参数为pcap_pkthdr结构指针,记录时间戳、包长、捕捉的长度; <br>
<br>
第3个参数字符串指针为数据包。 <br>
<br>
函数如下: <br>
void ProcessPacket(char *user, struct pcap_pkthdr *pkthdr, u_char *pkt) <br>
{ <br>
Packet p; //Packet结构在decode.h中定义,用来记录数据包的各种信息 <br>
<br>
/* call the packet decoder,调用拆包函数,这里grinder是一个全局 <br>
函数指针,已经在main的SetPktProcessor调用中设置为正确的拆包函数 */ <br>
(*grinder)(&p, pkthdr, pkt); <br>
<br>
/* print the packet to the screen,如果选择了详细显示方式, <br>
那么把包的数据,显示到标准输出 */ <br>
if(pv.verbose_flag) <br>
{ <br>
...... //省略 <br>
} <br>
<br>
/* check or log the packet as necessary <br>
如果工作在使用检测规则的方式,就调用Preprocess进行检测, <br>
否则,仅仅进行日志,记录该包的信息*/ <br>
if(!pv.use_rules) <br>
{ <br>
... //进行日志,省略 <br>
} <br>
else <br>
{ <br>
Preprocess(&p); <br>
} <br>
<br>
//清除缓冲区 <br>
ClearDumpBuf(); <br>
<br>
} <br>
<br>
这里Preprocess函数进行实际检测。 <br>
-- <br>
<br>
垆边人似月,皓腕凝霜雪 <br>
<br>
<br>
※ 修改:·shuke 於 Oct 10 11:47:15 修改本文·[FROM: 166.111.69.59] <br>
</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="370.htm">上一层</a>][<a href="376.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -