Gary Barnes
Gary Barnes

Reputation: 73

Sniffing an ethernet interface on linux

I am trying to capture only packets from a specific interface and instead I am getting packets from all of the interfaces. what am I doing wrong?

bool Snooper::raw_init (const char *device)
{

uid_t    privid = geteuid();
int      retval;
bool     retVal = false;

do {
    if ((retval = setuid(0)) != 0) {
        perror("seteuid error");
        break;
    }

    cap_t caps = cap_get_proc();
    cap_value_t cap_list[2];
    cap_list[0] = CAP_NET_RAW;
    cap_list[1] = CAP_SETUID;
    if ((retval = cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_list, CAP_SET)) == -1) {
        perror("cap_set_flag error");
        break;
    }
    if ((retval = cap_set_proc(caps)) == -1) {
        perror("cap_set_proc error");
        break;
    }

    struct ifreq ifr;
    memset(&ifr, 0, sizeof (struct ifreq));

    /* Open A Raw Socket */
    if ((m_sockfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL))) < 1) {
        perror("Snooper::raw_init:socket Error");
        break;
    }

    /* Set the device to use */
    strncpy(ifr.ifr_name, device, strlen(device) + 1);

    /* Get the current flags that the device might have */
    if (ioctl(m_sockfd, SIOCGIFFLAGS, &ifr) == -1) {
        perror("Error: Could not retrieve the flags from the device.\n");
        break;
    }

    printf("The interface is ::: %s\n", device);
    perror("Retrieved flags from interface successfully");

    /* Set the old flags plus the IFF_PROMISC flag */
    ifr.ifr_flags |= IFF_PROMISC;
    if (ioctl(m_sockfd, SIOCSIFFLAGS, &ifr) == -1) {
        perror("Error: Could not set flag IFF_PROMISC");
        break;
    }
    printf("Setting interface ::: %s ::: to promisc\n", device);

    /* Configure the device */
    if (ioctl(m_sockfd, SIOCGIFINDEX, &ifr) < 0) {
        perror("Error: Error getting the device index.\n");
        break;
    }
    retVal = true;
} while(false);

if ((retval = seteuid(privid)) != 0) {
    perror("seteuid error");
}
return retVal;
}

I first validate that I can suid to root since IFF_PROMISC requires it. Then create the socket for UDP traffic, preform the IOCtl for the device, and finally IOCtl for PROMISC.

Now that I have a socket ready I loop on a recv, however I get packets from the other interfaces as well.

Upvotes: 2

Views: 2722

Answers (2)

Ansh David
Ansh David

Reputation: 672

A small pcap Program that might be able to help You

#include<stdio.h> 
#include<stdlib.h>
#include<string.h>
#include<pcap/pcap.h>
#include<netinet/if_ether.h>
#include<netinet/ip.h>
#include<netinet/tcp.h>

void process_packet(u_char *args, const struct pcap_pkthdr *header,
                               const u_char *buffer)
{
//  printf("In Process_Packet\n");
struct ethhdr *eth = (struct ethhdr *)(buffer);

printf("%.2x: %.2x: %.2x: %.2x: %.2x: %.2x: %.2x:\n ", eth->h_dest[0], eth->h_dest[1], eth->h_dest[2], eth->h_dest[3], eth->h_dest[4], eth->h_dest[5], eth->h_dest[6]);

printf("%x \n", htons(eth->h_proto));

if(htons(eth->h_proto)== ETHERTYPE_ARP)
{
    printf("ARP PACKET\n");
}

struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr));

int ipheader = iph-> ihl *4;

printf("Source IP Address :%s\n ", inet_ntoa(iph->saddr));

printf("Destination IP Address :%s\n ", inet_ntoa(iph->daddr));
}
int main()
{
pcap_if_t *alldevspec,*devices;
pcap_addr_t *a;
pcap_t *handle;
const char filter_exp[]="IP";
bpf_u_int32 netp;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fp;
int ret=0, count =1, n=0;
char devs[100][100],*devicename;

ret = pcap_findalldevs(&alldevspec,errbuf);

if(ret < 0)
{
    printf("Error in finding the devices\n");
    return -1;
}

for(devices = alldevspec; devices!= NULL; devices = devices->next)
{
    printf("%d %s-%s \n",count, devices->name,devices->description);

    for(a=devices->addresses;a;a=a->next)
    {
        printf("family %d \n", (a->addr)->sa_family);

        if(devices->name != NULL)
        {
            strcpy(devs[count], devices->name);
        }

        switch((a->addr)->sa_family)
        {
            case AF_INET:
            printf("%s \n",inet_ntoa(((struct sockaddr_in*)a->addr)->sin_addr.s_addr));
            break;

            case AF_INET6:
            break;
        }
    }
++count;
}

printf("Enter the device u want to select\n");
scanf("%d",&n);
devicename = devs[n];

handle = pcap_open_live(devicename,65536,1,-1,errbuf);

if(handle == NULL)
{
    printf("Error in opening the device\n");
    return -1;
}

pcap_compile(handle,&fp, filter_exp,-1,netp);
pcap_setfilter(handle, &fp);
pcap_loop(handle,-1,process_packet,NULL);

return 0;
}

Upvotes: 1

user405725
user405725

Reputation:

To capture packets from a specific interface, you have to bind your socket to that interface using bind function. You can check out this answer for an example.

Upvotes: 2

Related Questions