迷失在libpcap中 - 如何使用setnonblock()/我应该使用pcap_dispatch()或pcap_next_ex()实时?

时间:2015-03-05 13:37:38

标签: c multithreading freebsd libpcap

我正在构建一个网络嗅探器,它将在PFSense上运行以监控IPsec VPN。我正在FreeBSD 8.4下编译。

我选择在C中使用libpcap作为数据包捕获引擎,使用Redis作为存储系统。 每秒将有数百个数据包来处理,系统将全天运行。

目标是让网页显示有关网络活动的图表,如果可能的话,每隔几分钟或几秒钟更新一次。 当我的嗅探器捕获一个数据包时,它将确定它的大小,谁(一个地理站点,在我们的VPN上下文中)发送它,谁和何时。然后,这些信息需要存储在数据库中。

我已经做了很多研究,但是我对libpcap有点失落,特别是我应该捕获数据包的方式。

1)我应该使用什么功能来检索数据包? pcap_loop? pcap_dispatch?还是pcap_next_ex?根据我在网上看到的,循环和调度是阻塞执行,所以pcap_next_ex似乎是解决方案。

2)我们什么时候应该使用pcap_setnonblock?我的意思是哪个捕捉功能? pcap_loop?那么如果我使用pcap_loop,执行将不会被阻止?

3)多线程是实现这一目标的吗?一个线程一直在运行捕获数据包,分析它们并将一些数据存储在一个数组中,另一个线程每隔几分钟就会清空这个数组?

我想的越多,我就越迷茫,所以如果我不清楚请不要犹豫,请原谅我。

欢迎任何帮助。

编辑:

我目前正在尝试实现一个工作池,回调函数只在作业队列中放置一个新作业。任何帮助仍然欢迎。我稍后会发布更多细节。

1 个答案:

答案 0 :(得分:1)

  

1)我应该使用什么功能来检索数据包? pcap_loop? pcap_dispatch?还是pcap_next_ex?根据我在网上看到的,循环和调度是阻塞执行,所以pcap_next_ex似乎是解决方案。

如果没有准备好数据包,那么这些功能的所有都会阻止等待数据包,并且您无法将pcap_t置于非阻塞模式。

pcap_loop()包含一个无限运行的循环(或直到pcap_breakloop()被调用,并且发生错误,或者,如果指定了计数,则计数用完)。因此,它可能会等待不止一次。

pcap_dispatch()阻止等待一批数据包到达,如果没有可用的数据包,则循环处理批处理,然后返回,因此它最多只等待一次。

pcap_next()pcap_next_ex()等待数据包可用,然后返回。

  

2)我们什么时候应该使用pcap_setnonblock?我的意思是哪个捕捉功能? pcap_loop?所以,如果我使用pcap_loop,执行不会被阻止?

不,它不会,但这意味着对pcap_loop()的调用可能会在不处理任何数据包的情况下返回;您必须再次调用它来处理稍后到达的任何数据包。非阻塞和pcap_loop()并非真正有用;您也可以使用pcap_dispatch()pcap_next_ex()

  

3)多线程是实现这一目标的吗?一个线程一直运行捕获数据包,分析它们并将一些数据存储在一个数组中,第二个线程每隔几分钟就会清空这个数组?

(该数组可能是一个队列,第一个线程将数据包附加到队列的末尾,第二个线程从队列的头部删除数据包并将其放入数据库。)

这是一种可能性,虽然我不确定它是否应该基于计时器。鉴于许多数据包捕获机制 - 包括* BSD和OS X使用的BPF - 分批传送数据包,也许你应该有一个类似

的循环
for (;;) {
    pcap_dispatch(p, -1, callback);
    wake up dumper thread;
}

(简化了 - 你可能想要检查来自pcap_dispatch()的返回值中的错误。)

回调会将传递给它的数据包添加到队列的末尾。

转储程序线程将从队列头部提取数据包并将其添加到数据库中。

这不需要pcap_t无阻塞。在单CPU核心机器上,它将依赖于调度程序对时间进行切片的线程。

  

我目前正在尝试实现一个工作池,回调函数只在作业队列中放置一个新作业。

请注意,一旦回调函数返回,第二个参数指向的const struct pcap_pkthdr结构和第三个参数指向的原始数据包数据都不会有效,所以如果要处理它们在这项工作中,您必须复制它们 - 包括您将在该工作中处理的所有数据包数据的副本。您可能想要考虑在回调例程中进行一些处理,即使它只计算需要保存的数据包数据(例如,IP源和目标地址)并复制它,因为这可能比复制更便宜整个数据包。