【问题标题】:capturing both incoming and outgoing packets using raw socket使用原始套接字捕获传入和传出的数据包
【发布时间】:2017-03-03 08:52:02
【问题描述】:

我正在用 C 语言编写一个工具,用于记录在我的 Linux 系统上运行的不同应用程序的数据使用情况。为此,我创建了一个原始套接字,然后将其与“eth0”绑定,这是我的接口名称。但我的问题是,这个套接字只捕获传入的数据包(即:目标 MAC 地址作为我系统 MAC 地址的数据包)。我找不到任何将源 MAC 地址作为系统 MAC 地址的数据包。所以这意味着我自己的机器写入的数据包不会被原始套接字捕获。但我想在两个方向上捕获数据包以识别上传和下载的数据大小。有人可以帮忙吗?

int main()
{
    int rs,len;
    struct sockaddr_ll addr;
    char buf[65535];

    rs = socket(PF_PACKET,SOCK_RAW,htons(ETH_ALL));
    setsockopt(rs,SOL_SOCKET,SO_BINDDEVICE,"eth0",4);
    while(recvfrom(rs,buf,65535,&addr,&len) > 0){
        //print packets
    }
    return 0;
}

【问题讨论】:

    标签: c sockets network-programming raw-sockets


    【解决方案1】:

    我在搜索您的问题时发现了这一点。我没试过这个。也许这会起作用。

      int v=0;
        v = PACKET_MASK_ANY & ~(1<<PACKET_OUTGOING) & ~(1 << PACKET_LOOPBACK);
        setsockopt( raw_sock, SOL_PACKET, PACKET_RECV_TYPE, &v, sizeof(v));
    

    【讨论】:

    • 感谢您的回复。但是我的 /usr/include 目录中没有名为 PACKET_MASK_ANY 的宏
    • #define PACKET_MASK_ANY 0xffffffff /* 数据包类型位掩码 / #define PACKET_OUTGOING 4 / 任何类型的输出 */ #define PACKET_RECV_TYPE 18
    • 没有名为 PACKET_RECV_TYPE 的套接字操作宏。你是喀拉拉邦的吗?
    • 实际上这个补丁是在 openwrt 中完成的。我希望它应该工作。是的,我来自喀拉拉邦
    • Go for Packet mmap tx/rx ring 概念。
    【解决方案2】:

    来自socket(7)

    SO_BINDTODEVICE

    将此套接字绑定到特定设备,如“eth0”,在传递的接口名称中指定。 [...] 请注意,这仅适用于某些套接字类型, 特别是 AF_INET 套接字。数据包套接字不支持它(在那里使用普通的 bind(2))。

    您应该查看packet(7) 手册页。

    下载 libpcap 库源代码并查看它的作用可能很有启发性(如果您不能只使用 libpcap 而不是自己滚动)。它肯定会收到传出的数据包和传入的数据包。

    它似乎进行了这些调用(有许多受支持的选项和配置,因此您必须通过无数的 ifdef 来确切地发现发生了什么——请参阅pcap-linux.c):

    fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL);
    ...
    struct sockaddr_ll sll;
    memset(&sll, 0, sizeof(sll));
    sll.sll_family          = AF_PACKET;
    sll.sll_ifindex         = ifindex;   // Interface index from SIOCGIFINDEX
    sll.sll_protocol        = htons(ETH_P_ALL);
    bind(fd, (struct sockaddr *) &sll, sizeof(sll));
    ...
    struct packet_mreq      mr;
    memset(&mr, 0, sizeof(mr));
    mr.mr_ifindex = handlep->ifindex;
    mr.mr_type    = PACKET_MR_PROMISC;
    setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr))
    

    还有一件事要记住。在收到自己的盒子发来的包时,经常会出现外发包中的校验和(IP、TCP、UDP)不正确的情况。这是因为大多数现代网络控制器都支持校验和卸载。这意味着卡将在数据包被 DMA 进入卡内存后计算校验和。因此,那些用于传出数据包的数据包在程序缓冲区(由内核从本地内存中填充)中将不正确。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-17
      • 1970-01-01
      • 1970-01-01
      • 2011-09-14
      • 2018-02-12
      相关资源
      最近更新 更多