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