荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: georgehill (清风浮云 人生), 信区: Linux
标  题: snort源码分析(4)(转寄)
发信站: BBS 荔园晨风站 (Tue Oct 10 16:52:46 2000), 站内信件

【 以下文字转载自 georgehill 的信箱 】
【 原文由 georgehill.bbs@smth.org 所发表 】
发信人: shuke (莫失莫忘), 信区: Security
标  题: snort源码分析(4)(转寄)
发信站: BBS 水木清华站 (Tue Oct 10 11:42:22 2000)


    现在看看snort如何实现对数据包的分析和检测入侵的。

    在main函数的最后部分有如下语句,比较重要:

/* Read all packets on the device.  Continue until cnt packets read */
if(pcap_loop(pd, pv.pkt_cnt, (pcap_handler)ProcessPacket, NULL) < 0)
{
......
}

    这里pcap_loop函数有4个参数,分别解释:

    pd是一个全局变量,表示文件描述符,在前面OpenPcap的调用中已经被正确地
赋值。前面说过,snort可以实时采集网络数据,也可以从文件读取数据进行分析。
在不同情况打开文件(或设备)时,pd分别用来处理文件,或者网卡设备接口。

    pd是struct pcap类型的指针,该结构包括实际的文件描述符,缓冲区,等等
域,用来处理从相应的文件获取信息。

    OpenPcap函数中对pd赋值的语句分别为:

      /* get the device file descriptor,打开网卡接口 */
      pd = pcap_open_live(pv.interface, snaplen,
                   pv.promisc_flag ? PROMISC : 0, READ_TIMEOUT, errorbuf);

      或者

      /* open the file,打开文件 */
      pd = pcap_open_offline(intf, errorbuf);

    于是,这个参数表明从哪里取得待分析的数据。

    第2个参数是pv.pkt_cnt,表示总共要捕捉的包的数量。在main函数初始化时,
缺省设置为-1,成为永真循环,一直捕捉直到程序退出:

   /* initialize the packet counter to loop forever */
   pv.pkt_cnt = -1;

    或者在命令行中设置要捕捉的包的数量。前面ParseCmdLine(解析命令行)函数
的调用中,遇到参数n,重新设定pv.pkt_cnt的值。ParseCmdLine中相关语句如下:

         case 'n': /* grab x packets and exit */
                 pv.pkt_cnt = atoi(optarg);

    第3个参数是回调函数,该回调函数处理捕捉到的数据包。这里为函数
ProcessPacket,下面将详细解释该函数。

    第4个参数是字符串指针,表示用户,这里设置为空。

    在说明处理包的函数ProcessPacket之前,有必要解释一下pcap_loop的实现。
我们看到main函数只在if条件判断中调用了一次pacp_loop,那么循环一定是在
pcap_loop中做的了。察看pcap.c文件中pcap_loop的实现部分,我们发现的确如此:

int
pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
        register int n;

        for (;;) {  //for循环
                if (p->sf.rfile != NULL)
                        n = pcap_offline_read(p, cnt, callback, user);
                else {
                        /*
                         * XXX keep reading until we get something
                         * (or an error occurs)
                         */
                        do {  //do循环
                                n = pcap_read(p, cnt, callback, user);
                        } while (n == 0);
                }
                if (n <= 0)
                        return (n);  //遇到错误,返回
                if (cnt > 0) {
                        cnt -= n;
                        if (cnt <= 0)
                                return (0);  //到达指定数量,返回
                }
                //只有以上两种返回情况
        }
}


    现在看看ProcessPacket的实现了,这个回调函数用来处理数据包。该函数是
是pcap_handler类型的,pcap.h中类型的定义如下:

typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
                             const u_char *);

    第1个参数这里没有什么用;

    第2个参数为pcap_pkthdr结构指针,记录时间戳、包长、捕捉的长度;

    第3个参数字符串指针为数据包。

    函数如下:
void ProcessPacket(char *user, struct pcap_pkthdr *pkthdr, u_char *pkt)
{
   Packet p;  //Packet结构在decode.h中定义,用来记录数据包的各种信息

   /* call the packet decoder,调用拆包函数,这里grinder是一个全局
   函数指针,已经在main的SetPktProcessor调用中设置为正确的拆包函数 */
   (*grinder)(&p, pkthdr, pkt);

   /* print the packet to the screen,如果选择了详细显示方式,
   那么把包的数据,显示到标准输出 */
   if(pv.verbose_flag)
   {
      ......  //省略
   }

   /* check or log the packet as necessary
   如果工作在使用检测规则的方式,就调用Preprocess进行检测,
   否则,仅仅进行日志,记录该包的信息*/
   if(!pv.use_rules)
   {
      ...   //进行日志,省略
   }
   else
   {
      Preprocess(&p);
   }

   //清除缓冲区
   ClearDumpBuf();

}

    这里Preprocess函数进行实际检测。
--

      垆边人似月,皓腕凝霜雪


※ 修改:·shuke 於 Oct 10 11:47:15 修改本文·[FROM:   166.111.69.59]
※ 来源:·BBS 水木清华站 smth.org·[FROM: 166.111.69.59]
--
※ 转载:·BBS 荔园晨风站 bbs.szu.edu.cn·[FROM: 192.168.1.115]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店