4

I need to set up a raw socket for incoming packets only on a specific interface (has both eth0 and eth1, eth1 only). In other words, I need only incoming packets on one specific interface.

Comparing to other sniffers

In ifconfig there is an RX Packets field for each interface. While this remains constant, this sniffer will still register as receiving packets. Perhaps RX Packets is limited to certain protocols? I have also compared this to a python sniffer - the same problem exists. The python sniffer will not return as many packets as this c sniffer does. I cannot compare this to wireshark as I am unable to install it on the system, it is embedded.

Bindings

I thought perhaps I binded this incorrectly, but that seems to be working. Having two of these running, one on eth0 and the other on eth1 gives different results/

Suspected issue

It seems to me the problem is in the recvfrom command not filtering to only incoming packets, but instead reading from the buffer, whether that be incoming or outgoing. Perhaps there is a way to look at the address to see if the packet is incoming or outgoing, as in python, or perhaps recvfrom is already doing this.

Note

Near the end the program prints packet sizes sniffed and times that size packet has been received. Here is the trimmed down code. Thanks in advance.

#include<errno.h>  //error codes
#include<linux/if_packet.h>
#include<linux/if_ether.h>
#include<time.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<netinet/in.h>
#include<stdio.h>
#include<stdlib.h>
#include<net/if.h>
const int TIME_INTERVAL = 2;
const int BUF_LENGTH = 65534;
int main()
{
    int sock_errno(void), data_size=0, raw_sock;
    long recv_count = 0, last_count = 0, rate = 0;
    time_t start;
    socklen_t clilen;
    struct sockaddr_in cliaddr, servaddr; 
    char buffer[BUF_LENGTH];
    int hist[BUF_LENGTH];
    int i;
    for (i = 0; i < BUF_LENGTH; i++)
        hist[i] = 0;
    int table[BUF_LENGTH];
    int index = 0;

    //Create a raw socket that shall sniff
    raw_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    //bind to interface
    clilen = sizeof(struct sockaddr_in);
    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr));
    snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth1");
    setsockopt(raw_sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr));
    start = time(NULL);
    while (1)
    {
        data_size = recvfrom(raw_sock, buffer, BUF_LENGTH, 0, (struct sockaddr*)&cliaddr, &clilen);
        recv_count = recv_count + data_size;

        hist[data_size] = hist[data_size] + 1;

        if (time(NULL) - start > TIME_INTERVAL) // display data every time interval
        {
            start = time(NULL);
            rate = (float)(recv_count - last_count) / TIME_INTERVAL;
            printf("(I) Bytes received: %d\n", recv_count);

            for (i=0; i<BUF_LENGTH; i++) {
                if (hist[i] > 0) //only print received packet sizes
                {
                    printf("%d - ", i); //print packet size
                    printf("%d\n", hist[i]); //print received counter
                }
            }
            printf("\n\n");

        }
    }
    close(raw_sock);
    return 0;
}
Harrichael
  • 95
  • 1
  • 9
  • Of course you would get different results when running on two different interfaces, as both interfaces will get different packages. – Some programmer dude Jul 25 '14 at 21:18
  • Exactly, it was to confirm I was indeed binding them correctly. – Harrichael Jul 25 '14 at 21:24
  • Then could you please elaborate a little more on your problem? What have you tried to do to solve whatever the problem is? How did it work or not work? – Some programmer dude Jul 25 '14 at 21:26
  • It is sniffing packets that are not being picked up by the ifconfig command or another sniffer written in python. – Harrichael Jul 25 '14 at 21:29
  • 1
    The [`ifconfig`](http://man7.org/linux/man-pages/man8/ifconfig.8.html) command is not a packet sniffer, it's to configure interfaces. Also, have compared to a professional sniffer such as [Wireshark](http://www.wireshark.org/)? – Some programmer dude Jul 25 '14 at 21:38
  • It seems I'm doing something similar. And now found this article. What did you add to make this program only pick up the packets what ifconfig counts? – Cprogrammer Nov 17 '21 at 15:33

1 Answers1

2

see the answer to Raw Socket promiscuous mode not sniffing what I write

looking at http://man7.org/linux/man-pages/man7/packet.7.html change the type of cliaddr to struct sockaddr_ll you can then look at cliaddr.sll_pkttype to determine incoming or outgoing

struct sockaddr_ll {
           unsigned short sll_family;   /* Always AF_PACKET */
           unsigned short sll_protocol; /* Physical layer protocol */
           int            sll_ifindex;  /* Interface number */
           unsigned short sll_hatype;   /* ARP hardware type */
           unsigned char  sll_pkttype;  /* Packet type */
           unsigned char  sll_halen;    /* Length of address */
           unsigned char  sll_addr[8];  /* Physical layer address */
       };

sll_pkttype contains the packet type. Valid types are PACKET_HOST for a packet addressed to the local host, PACKET_BROADCAST for a physical layer broadcast packet, PACKET_MULTICAST for a packet sent to a physical layer multicast address, PACKET_OTHERHOST for a packet to some other host that has been caught by a device driver in promiscuous mode, and PACKET_OUTGOING for a packet originated from the local host that is looped back to a packet socket.

Community
  • 1
  • 1
Lee Ballard
  • 1,049
  • 11
  • 13