2

I have a raw socket set up bound to a device that is already in promiscuous mode:

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...
}

And my issue is that I am only receiving packets on my socket with IP destination matching the IP of the device (eth0) I am bound to. How can I receive all the TCP packets that the device is receiving? I can see all the TCP packets on the device in Wireshark, but the only packets that I see in my raw socket are those addressed to the device IP.

red0ct
  • 4,840
  • 3
  • 17
  • 44
TheoretiCAL
  • 19,461
  • 8
  • 43
  • 65
  • this code block: `if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) { close(sock); return -2; }` needs to be removed from your code as the `ifr` struct is not yet initialized – user3629249 Jul 20 '19 at 21:46
  • @user3629249 updated code block, apologies that was just a mistake when copying over a simplified version of the code – TheoretiCAL Jul 21 '19 at 03:34
  • Shouldn't you be setting the packet mask also? Seet this https://stackoverflow.com/questions/12177708/raw-socket-promiscuous-mode-not-sniffing-what-i-write and https://stackoverflow.com/questions/114804/reading-from-a-promiscuous-network-device – Tarun Lalwani Jul 22 '19 at 07:50
  • @TarunLalwani Thanks, I've added a packet mask for the specific interface I'm interested in – TheoretiCAL Jul 22 '19 at 22:48

1 Answers1

3

The reason of receiving packets directed only to IP of your device is that you are using PF_INET raw socket. When PF_INET raw socket is used - skb faces different sanity checks when goes across the stack (see below).

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;

So the call trace is something like: __netif_receive_skb_core()->ip_rcv()->...->ip_local_deliver()->...->raw_local_deliver()->raw_rcv()->...->tcp_rcv() (you can check trace through the trace-cmd).

But tcpdump/Wireshark obtains packets around __netif_receive_skb_core(), i.e. before some sanity checks. Hence is discrepancy that confused you.

Therefore if you want skb's to bypass a large part of Linux kernel network stack - you should use PF_PACKET raw sockets.

Useful link

red0ct
  • 4,840
  • 3
  • 17
  • 44
  • PACKET_MMAP is the better mechanism to capture both incoming and outgoing packets if they are transferred with an high speed. https://www.mjmwired.net/kernel/Documentation/networking/packet_mmap.txt – Ajith C Narayanan Aug 27 '19 at 09:38