4

I'm having an issue where by pcap_datalink() is always returning 1. To my understanding this is LINKTYPE_ETHERNET. But, the device I am using is a wireless card and in my case en0.

This is stopping me from putting the card into monitor mode, and stopping my WLAN filters from working. I've tried to run this on both OSX and Linux with the same results. I also run as root.

Here's the part of my code that's causing the problem. For the example, assume dev is set to en0 (wireless device on Mac).

#include <stdio.h>
#include <pcap.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    pcap_t *pcap_h;
    char *dev, errbuf[PCAP_ERRBUF_SIZE];
    struct bpf_program fp;
    struct pcap_pkthdr header;
    const u_char *packet;

    if(argc < 2)
    {
        printf("Usage: %s device\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    dev = argv[1];

    if((pcap_h = pcap_create(dev, errbuf)) == NULL)
    {
        printf("pcap_create() failed: %s\n", errbuf);
        exit(EXIT_FAILURE);
    }

    if(pcap_can_set_rfmon(pcap_h) == 0)
    {
        printf("Monitor mode can not be set.\n");
    }

    if(pcap_set_rfmon(pcap_h, 1) != 0)
    {
        printf("Failed to set monitor mode.\n");
        exit(EXIT_FAILURE);
    }

    if(pcap_activate(pcap_h) != 0)
    {
        printf("pcap_activate() failed\n");
        exit(EXIT_FAILURE);
    }

    /*
     * Compile a filter to sniff 802.11 probe requests
     * Filter: type mgt subtype probe-req
     */ 
    if(pcap_compile(pcap_h, &fp, "type mgt subtype probe-req", 0, PCAP_NETMASK_UNKNOWN) == -1)
    {
        printf("pcap_compile() failed: %s\n", pcap_geterr(pcap_h));
        exit(EXIT_FAILURE);
    }

    /*
     * Set the compiled filter
     */ 
    if(pcap_setfilter(pcap_h, &fp) == -1)
    {
        printf("pcap_setfilter() failed: %s\n", pcap_geterr(pcap_h));
        exit(EXIT_FAILURE);
    }

    pcap_freecode(&fp);

    packet = pcap_next(pcap_h, &header);

    printf("Header: %d\n", header.len); 
    pcap_close(pcap_h);
    return 0;
}

Any idea's why pcap_datalink() is always returning 1?

Edit

Updated code, and added pcap_set_rfmon() before the call to pcap_activate(). I get an error:

pcap_compile() failed: 802.11 link-layer types supported only on 802.11
James Jeffery
  • 12,093
  • 19
  • 74
  • 108
  • What error are you getting and where? – o_weisman Sep 02 '15 at 12:58
  • I am not getting an error, any errors I am getting such as monitor mode and filters are because my wireless device is being reported to have an Ethernet link layer (which is the title of this question) ... where monitor mode is impossible. – James Jeffery Sep 02 '15 at 13:04
  • `en0` should be the name of an Ethernet interface, not a wireless interface. In that case, if you ask PCAP for its link type, then `LINKTYPE_ETHERNET` (== 1) is an utterly reasonable result. These days almost every machine has an ethernet interface, including those that also have wireless interfaces. Are you sure you're looking at the interface you intend to look at? – John Bollinger Sep 02 '15 at 13:23
  • `en0` on my mac is the wireless interface. I do not have an Ethernet connection on my macbook. When compiled and ran on my Linux machine I use `wlan1` (have also tried `mon1` when set with `airmon-ng start wlan1`). `wlan1` is my Alpha card which supports monitor mode and packet injection. I can get the intended results when using `tcpdump` on my macbook, which is why I'm puzzled. – James Jeffery Sep 02 '15 at 13:41
  • In your call to pcap_compile(), the last parameter is 0. Whereas, see the man page: "If the netmask of the network on which packets are being captured isn't known to the program, or if packets are being captured on the Linux "any" pseudo-interface that can capture on more than one network, a value of PCAP_NETMASK_UNKNOWN can be supplied". And this value is not 0: in /usr/include/pcap/pcap.h:272:#define PCAP_NETMASK_UNKNOWN 0xffffffff – jbm Sep 02 '15 at 14:05
  • Minor: as soon as you have done pcap_setfilter(), you should do a pcap_freecode(&fp) – jbm Sep 02 '15 at 14:08
  • @jbm but if device is in monitor mode it can't be connected to an access point so there would be no netmask. – James Jeffery Sep 02 '15 at 14:09
  • @jbm ah thanks for that :) Noted about `PCAP_NETMASK_UNKNOWN` too. Just realised what you meant. – James Jeffery Sep 02 '15 at 14:09
  • "`en0` should be the name of an Ethernet interface, not a wireless interface." One could argue that it should be, but, for better or worse, that's not how OS X works; it calls Ethernet and Wi-Fi interfaces "enN". (I think Linux also used to do that at one point.) –  Sep 02 '15 at 20:44
  • "but if device is in monitor mode it can't be connected to an access point" Not true for the AirPort interface on my MacBook Pro; I can capture in monitor mode and remain associated with a wireless network. –  Sep 02 '15 at 20:44

1 Answers1

3

Are you shure this is what's is stopping you from putting the card into monitor mode, and stopping your WLAN filters from working, or do you do this call to pcap_datalink() as a check trying to pinpoint the issue?

Be aware that, from PCAP-LINKTYPE(7):

For a live capture or ``savefile'', libpcap supplies, as the return value of the pcap_datalink(3PCAP) routine, a value that indicates the type of link-layer header at the beginning of the packets it provides. This is not necessarily the type of link-layer header that the packets being captured have on the network from which they're being captured; for example, packets from an IEEE 802.11 network might be provided by libpcap with Ethernet headers that the network adapter or the network adapter driver generates from the 802.11 headers.

So I would not take this LINKTYPE_ETHERNET / DLT_EN10MB return value as the sure indication of a problem here.

EDIT: Also, pcap_set_rfmon() is supposed to be call before the handle is activated, which is not visible in your code.

pcap is rather touchy about the order things should be done. Have a look at the man pages for pcap_can_set_rfmon and pcap_set_rfmon.

The order should be:

  • pcap_create
  • pcap_can_set_rfmon
  • pcap_set_rfmon (if so far so good)
  • then and only then, pcap_activate
jbm
  • 3,063
  • 1
  • 16
  • 25
  • Interesting. But I don't get how you call pcap_set_rfmon(pcap_h, 0). From the man page, I'd rather do pcap_set_rfmon(pcap_h, 1): man page says "If rfmon (second parameter) is non-zero, monitor mode will be set, otherwise it will not be set." Also, at this point in chasing the issue, I'd try the pcap_can_set_rfmon() before that. – jbm Sep 02 '15 at 14:01
  • I tried `pcap_can_set_rfmon()`. Will update code to show it in there, and yeah probably best I keep it in there too :). I have tried with `1` and still had the same issue. – James Jeffery Sep 02 '15 at 14:04
  • This is odd. I added `pcap_can_set_rfmon()` before `pcap_set_rfmon()` and it works. Or maybe I didn't compile when I set it to `1` the first time. Either way, this answer solved it :) – James Jeffery Sep 02 '15 at 14:07
  • Your welcome. I'm doing "wired" pcap right now, but may have to do 802.11 too in a not to distant future. So I learn from the troubles you get in :) – jbm Sep 02 '15 at 14:11
  • "I added pcap_can_set_rfmon() before pcap_set_rfmon() and it works. Or maybe I didn't compile when I set it to 1 the first time. Either way, this answer solved it :)" Try removing `pcap_can_set_rfmon()` and recompiling and see if it works. That'll indicate which of those is the answer. –  Sep 02 '15 at 20:42