Reading from a promiscuous network device

2019-02-03 12:50发布

I want to write a real-time analysis tool for wireless traffic.

Does anyone know how to read from a promiscuous (or sniffing) device in C?

I know that you need to have root access to do it. I was wondering if anyone knows what functions are necessary to do this. Normal sockets don't seem to make sense here.

5条回答
狗以群分
2楼-- · 2019-02-03 13:22

I once had to listen on raw ethernet frames and ended up creating a wrapper for this. By calling the function with the device name, ex eth0 I got a socket in return that was in promiscuous mode. What you need to do is to create a raw socket and then put it into promiscuous mode. Here is how I did it.

int raw_init (const char *device)
{
    struct ifreq ifr;
    int raw_socket;

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

    /* Open A Raw Socket */
    if ((raw_socket = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 1)
    {
        printf ("ERROR: Could not open socket, Got #?\n");
        exit (1);
    }

    /* Set the device to use */
    strcpy (ifr.ifr_name, device);

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

    /* Set the old flags plus the IFF_PROMISC flag */
    ifr.ifr_flags |= IFF_PROMISC;
    if (ioctl (raw_socket, SIOCSIFFLAGS, &ifr) == -1)
    {
        perror ("Error: Could not set flag IFF_PROMISC");
        exit (1);
    }
    printf ("Entering promiscuous mode\n");

    /* Configure the device */

    if (ioctl (raw_socket, SIOCGIFINDEX, &ifr) < 0)
    {
        perror ("Error: Error getting the device index.\n");
        exit (1);
    }

    return raw_socket;
}

Then when you have your socket you can just use select to handle packets as they arrive.

查看更多
Viruses.
3楼-- · 2019-02-03 13:24

You could use the pcap library (see http://www.tcpdump.org/pcap.htm) which is also used by tcpdump and Wireshark.

查看更多
Deceive 欺骗
4楼-- · 2019-02-03 13:28

On Linux you use a PF_PACKET socket to read data from a raw device, such as an ethernet interface running in promiscuous mode:

s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))

This will send copies of every packet received up to your socket. It is quite likely that you don't really want every packet, though. The kernel can perform a first level of filtering using BPF, the Berkeley Packet Filter. BPF is essentially a stack-based virtual machine: it handles a small set of instructions such as:

ldh = load halfword (from packet)  
jeq = jump if equal  
ret = return with exit code  

BPF's exit code tells the kernel whether to copy the packet to the socket or not. It is possible to write relatively small BPF programs directly, using setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, ). (WARNING: The kernel takes a struct sock_fprog, not a struct bpf_program, do not mix those up or your program will not work on some platforms).

For anything reasonably complex, you really want to use libpcap. BPF is limited in what it can do, in particular in the number of instructions it can execute per packet. libpcap will take care of splitting a complex filter up into two pieces, with the kernel performing a first level of filtering and the more-capable user-space code dropping the packets it didn't actually want to see.

libpcap also abstracts the kernel interface out of your application code. Linux and BSD use similar APIs, but Solaris requires DLPI and Windows uses something else.

查看更多
Luminary・发光体
5楼-- · 2019-02-03 13:28

WireShark on linux has the capability to capture the PLCP (physical layer convergence protocol) header information.

查看更多
爷的心禁止访问
6楼-- · 2019-02-03 13:42

Why wouldn't you use something like WireShark?

It is open source, so at least you could learn a few things from it if you don't want to just use it.

查看更多
登录 后发表回答