我已将原始套接字设置绑定到已经处于混杂模式的设备:
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的数据包。
答案 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
原始套接字。