绑定到设备的原始套接字未收到所有数据包

时间:2019-07-19 21:22:22

标签: c linux sockets linux-kernel raw-sockets

我已将原始套接字设置绑定到已经处于混杂模式的设备:

int sock = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);
if(sock == -1)
{
   return -1;
}

struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, "eth0", IFNAMSIZ);
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
{
    close(sock);
    return -2;
}

while(1) {
  packet_size = recvfrom(sock , buffer , 65536 , 0 , NULL, NULL);
  // packet processing...
}

我的问题是我只在套接字上接收到IP目标与绑定到的设备的IP(eth0)匹配的数据包。如何接收设备正在接收的所有TCP数据包?我可以在Wireshark中看到该设备上的所有TCP数据包,但是我在原始套接字中看到的唯一数据包是那些寻址到设备IP的数据包。

1 个答案:

答案 0 :(得分:3)

接收仅定向到设备IP的数据包的原因是您使用的是PF_INET原始套接字。使用PF_INET原始套接字时-skb遍历堆栈时会面临不同的健全性检查(请参见下文)。

F.e。 :

int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
    /*...*/

    /* When the interface is in promisc. mode, drop all the crap
     * that it receives, do not try to analyse it.
     */
    if (skb->pkt_type == PACKET_OTHERHOST)
        goto drop;

因此呼叫跟踪类似于:__netif_receive_skb_core()-> ip_rcv()-> ...-> ip_local_deliver()-> ...-> raw_local_deliver()-> { {1}}-> ...-> raw_rcv()(您可以通过trace-cmd检查跟踪)。

但是tcpdump / Wireshark在tcp_rcv()附近(即在进行一些完整性检查之前)获取了数据包。因此,差异会让您感到困惑。

因此,如果您希望__netif_receive_skb_core()绕过Linux内核网络堆栈的大部分-您应该使用PF_PACKET原始套接字。

Useful link