2

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.

  • Thanks to @Vlad Lazarenko it now works. I thought it would be the bind, however none of the other examples found elsewhere ever used bind, and therefore it was omitted. As far as anyone else wanting to do the same type of task. After compiling. chown root exe, then chmod a+s exe. Although you must have root privileges to perform either action. – Gary Barnes Jan 24 '14 at 17:10

2 Answers2

2

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.

Community
  • 1
  • 1
1

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;
}
Ansh David
  • 654
  • 1
  • 10
  • 26