我想在Linux上用C语言编写一个使用Libpcap的小应用程序。
目前,它开始嗅探并等待数据包。但这不是我真正需要的。我希望它等待N秒,然后停止聆听。
我怎样才能做到这一点?
这是我的代码:
void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
printf("got packet\n);
}
int main()
{
int ret = 0;
char *dev = NULL; /* capture device name */
char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
pcap_t *handle; /* packet capture handle */
char filter_exp[] = "udp dst port 1500"; /* filter expression */
struct bpf_program fp; /* compiled filter program (expression) */
bpf_u_int32 mask; /* subnet mask */
bpf_u_int32 net; /* ip */
int num_packets = 10; /* number of packets to capture */
/* get network number and mask associated with capture device */
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
dev, errbuf);
net = 0;
mask = 0;
}
/* print capture info */
printf("Device: %s\n", dev);
printf("Number of packets: %d\n", num_packets);
printf("Filter expression: %s\n", filter_exp);
/* open capture device */
handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);
if (handle == NULL) {
fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
exit(EXIT_FAILURE);
}
/* compile the filter expression */
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n",
filter_exp, pcap_geterr(handle));
exit(EXIT_FAILURE);
}
/* apply the compiled filter */
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Couldn't install filter %s: %s\n",
filter_exp, pcap_geterr(handle));
exit(EXIT_FAILURE);
}
/* now we can set our callback function */
pcap_loop(handle, num_packets, got_packet, NULL);
/* cleanup */
pcap_freecode(&fp);
pcap_close(handle);
}
答案 0 :(得分:6)
当您想要停止收听时,您应该致电pcap_breakloop()
。所以一种方法是:
SIGALRM
信号安装信号处理程序,pcap_breakloop()
以使pcap_loop()
返回。代码:
void alarm_handler(int sig)
{
pcap_breakloop(handle);
}
int main()
{
...
alarm(N);
signal(SIGALRM, alarm_handler);
/* now we can set our callback function */
pcap_loop(handle, num_packets, got_packet, NULL);
/* cleanup */
pcap_freecode(&fp);
pcap_close(handle);
}
注意:至于使用libpcap的读取超时来执行此操作,它将不会也无法工作,man pcap明确警告它:
读取超时不能用于导致读取数据包的调用在有限的时间内返回[...]这意味着不应使用读取超时,例如,在交互式应用程序中允许该数据包捕获循环以定期轮询用户输入,因为即使没有数据包到达,也无法保证在超时到期后呼叫读取数据包将返回。
答案 1 :(得分:2)
如果您从 tcpdump 网站查看this页面,可以看到以下内容:
打开设备进行嗅探
创建嗅探会话的任务非常简单。为此,我们使用pcap_open_live()。该函数的原型(来自pcap手册页)如下:
pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms,
char *ebuf)
第一个参数是我们在上一节中指定的设备。 snaplen是一个整数,它定义了pcap要捕获的最大字节数。 promisc,当设置为true时,将接口带入混杂模式(但是,即使设置为false,也可能在特定情况下接口处于混杂模式,无论如何)。 to_ms是读取超时(以毫秒为单位)(值为0表示没有超时;至少在某些平台上,这意味着您可能要等到足够数量的数据包到达才能看到任何数据包,因此您应该使用非零超时)。最后,ebuf是一个字符串,我们可以存储任何错误消息(正如我们上面用errbuf所做的那样)。该函数返回会话处理程序。
如果这不起作用,请告诉我们。
答案 2 :(得分:0)
我一直在研究和测试这些代码片段。在某个地方,我注意到观察到当你退出pcap_loop时,尽管你可能已经看过数据包,但退出条件表明你没有看到过。我假设数据包的所有处理必须在回调函数的范围内进行。因此,如果我想快速重置并为另一个数据包做好准备,我将需要生成另一个进程来处理每个数据包。
答案 3 :(得分:0)
老帖子,但我正在研究并遇到了这个。
从pcap_loop()的手册页中,它明确地说,“当实时读取超时发生时它不会返回;相反,它会尝试读取更多数据包。”
但pcap_dispatch()和pcap_next()的手册页都表明它们在超时时返回。
答案 4 :(得分:0)
您可以使用pcap_next()函数并使用pcap_set_timeout设置超时,对于libpcap 1.8.1,您需要立即模式,请参见https://github.com/the-tcpdump-group/libpcap/issues/572。