【问题标题】:Capturing tshark standard output with popen in C在 C 中使用 popen 捕获 tshark 标准输出
【发布时间】:2014-11-28 10:00:06
【问题描述】:

我正在尝试通过 C 中的程序从 tshark 捕获标准输出。 为此,我使用 popen() 调用打开 tshark 进程并从返回的 FILE 流中读取。

代码示例:

#include <stdio.h>
#include <stdlib.h>

int main() {

    FILE* pipe_fd = popen("tshark -i eth0 -R icmp -2 -T fields -e icmp.checksum -e icmp.seq", "r");
    //FILE* pipe_fd = popen("lsof", "r");

    if (!pipe_fd) {
        fprintf(stderr, "popen failed.\n");
        return EXIT_FAILURE;
    }

    char buffer[2048];
    while (NULL != fgets(buffer, sizeof(buffer), pipe_fd)) {
        fprintf(stdout, "SO: %s", buffer);
    }

    pclose(pipe_fd);
    printf("tdr FINISHED!\n");
    return 0;
}

当我运行它时,我只得到数据包编号计数,即,我没有得到数据包字段信息,只有数据包计数,每个数字在同一个地方覆盖前面的数字(没有行滚动发生)。

像这样,我猜是 4 个数据包:

tomas@ubuntu64:~$ sudo ./main
tshark: Lua: Error during loading:
 [string "/usr/share/wireshark/init.lua"]:46: dofile has been disabled due to running Wireshark as superuser. See http://wiki.wireshark.org/CaptureSetup/CapturePrivileges for help in running Wireshark as an unprivileged user.
Running as user "root" and group "root". This could be dangerous.
Capturing on 'eth0'
4 

但是,如果我在 C 程序中将“tshark”命令参数更改为“lsof”,则可以得到标准输出。

tomas@ubuntu64:~$ sudo ./main
lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1000/gvfs
      Output information may be incomplete.
SO: COMMAND     PID   TID       USER   FD      TYPE             DEVICE SIZE/OFF       NODE NAME
SO: init          1             root  cwd       DIR                8,1     4096          2 /
SO: init          1             root  rtd       DIR                8,1     4096          2 /
SO: init          1             root  txt       REG                8,1   265848     791529 /sbin/init
SO: init          1             root  mem       REG                8,1    47712     824514 /lib/x86_64-linux-gnu/libnss_files-2.19.so
...

有了这个结果,我假设 tshark 将信息发送到标准输出的方式有些特殊。有人知道这种行为吗? 我去查一下tshark源码,看看能不能说清楚。

最后一点。

当我通过 shell 运行 tshark 时,我经常会丢失数据包编号,例如:

tomas@ubuntu64:~$ sudo tshark -i eth0 -R icmp -2 -T fields -e icmp.checksum -e icmp.seq
tshark: Lua: Error during loading:
 [string "/usr/share/wireshark/init.lua"]:46: dofile has been disabled due to running Wireshark as superuser. See http://wiki.wireshark.org/CaptureSetup/CapturePrivileges for help in running Wireshark as an unprivileged user.
Running as user "root" and group "root". This could be dangerous.
Capturing on 'eth0'
0x0ee5  63045
1 0x8ae3    63046
2 0xcfdf    63047
3 0xe4d9    63048
4 0x9db7    63049
5 0x6798    63050
6 0x0175    63051
7 0x9e54    63052
0xa654  63052
9 0xe050    63053
0xe850  63053
11 0x8389   63054
0x8b89  63054
13 0x9b81   63055
0xa381  63055

缺少打印的数据包编号 8、10、12、14。

当我将标准输出重定向到文件时,它不会发送计数:

tomas@ubuntu64:~$ sudo tshark -i eth0 -R icmp -2 -T fields -e icmp.checksum -e icmp.seq > kk
tomas@ubuntu64:~$ cat kk 
0x2073  63321
0x2873  63321
0x7c6a  63322

另一个线索表明 tshark 以不同方式处理打印的数据包计数和信息。

问候, 汤姆

【问题讨论】:

  • 为什么要popen tshark?捕获实际数据并离线分析,或者使用 libpcap 之类的不是更好吗?这似乎有点奇怪。
  • 你知道,这是出现在一份规范文档中的先决条件。如果不能那样做,我想我必须弄清楚。
  • 先决条件是什么?我的意思是,这一切的输出必须去某处,我很好奇它的用途。
  • 好奇心害死猫... Somewhere 是通过 rsyslogd 配置的远程机器。虽然我开始认为这条路让我无处可去...
  • 好的,所以您正在尝试使用 tshark 捕获(发送到文本)一些网络流量,并将其发送到 syslog。而不是所有这些,也许您可​​以只配置您的以太网交换机来进行端口镜像并将实际数据发送到目标机器并在那里处理它。只是一个想法。

标签: c pipe stdout popen tshark


【解决方案1】:

好吧,即使我最终不使用这种与 tshark 一起工作的方式,我想我还是找到了用于popen tshark 的选项。在手册页中,选项 -l

在打印每个数据包的信息后刷新标准输出。 (严格来说,如果 -V 是,这不是行缓冲的 指定的;但是,如果 -V 不是,则它与行缓冲相同 指定,因为每个数据包只打印一行,并且 -l 是 通常在将实时捕获传输到程序或脚本时使用,因此 一旦看到数据包,数据包的输出就会显示出来,并且 剖析,它应该和真正的行缓冲一样工作。我们的确是 这是 Microsoft Visual C++ C 中缺陷的一种解决方法 图书馆。)

这在将 TShark 的输出通过管道传输到另一个时可能很有用 程序,因为这意味着输出通过管道传输到的程序 一旦 TShark 看到 数据包并生成该输出,而不是仅在 包含该数据的标准输出缓冲区已满。

我测试了它,它似乎工作。 以防万一有人需要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-19
    • 2015-09-21
    • 2015-03-15
    • 2017-01-19
    • 1970-01-01
    • 2011-08-12
    相关资源
    最近更新 更多