title: why can't my program (coded with libpcap) capture wireless 80211 packets?
body: <p>I have written a program to capture wireless network packets from my network interface card(ralink 2870(USB),atheros(PCI),etc).Now I am not able to capture the correct format packet I needed,even no packets was captured.1st,I tried turned my card to monitor mode or add a interface mon0 for it.but it output "do not support that interface".2nd,this program can only clarify the "this is the ethernet link type" via pcap_datalink(),why?my wlan0 interface is that link type?. Here is my code:</p>
  
  <pre><code>#include&lt;stdio.h&gt;
  #include&lt;stdlib.h&gt;
  #include&lt;string.h&gt;
  #include&lt;signal.h&gt;
  #include&lt;unistd.h&gt;
  #include&lt;net/if.h&gt;
  #include&lt;netinet/if_ether.h&gt;
  #include&lt;pcap.h&gt;
  
  /*ugly shortcuts - Defining our header types*/
  #define ETH_HEADER_SIZE 14          
  #define AVS_HEADER_SIZE 64          /*AVS capture header size*/
  #define DATA_80211_FRAME_SIZE 24    /*header for 802.11 data packet*/
  #define LLC_HEADER_SIZE 8           /*LLC frame for encapsulation*/
  #define MAC_MASK (0XFF)
  /*
  #define uint8 unsigned char;
  #define int8 char;
  #define uint16 int;
  #define int16 int;
  #define u_int32_t unsigned int;
  #define int32 signed int;
  */
  
  /*for the sake of clarity we'll use globals for a few things*/
  char *device;       /*device to sniff on*/
  int verbose = 0;    /*verbose output about the device*/
  int wired = 0;      /*flag for the opened pcap session*/
  pcap_t *handle;     /*handle for the opened pcap session*/
  
  /*8 bytes SNAP LLC header format*/
  struct snap_header_t{
  u_int8_t dsap;
  u_int8_t ssap;
  u_int8_t ctl;
  u_int16_t org;
  u_int8_t org2;
  u_int16_t ether_type;   /* ethernet type */
  
  }__attribute__((__PACKED__));
  
  //24 bytes 80211 header
  struct wireless_80211_header_t{
  u_int16_t fc;   /*2 bytes */
  u_int16_t dur;  /*2 bytes duration*/
  u_int8_t da[6]; /*6 bytes destination*/
  u_int8_t sa[6]; /*6 bytes source*/
  u_int8_t bssid[6];  /*6 bytes bssid*/
  u_int16_t seq_ctrl; /*2 bytes sequence control*/
  };
  
  //64 bytes AVS header
  struct AVS_header_t
  {
  u_int32_t version;
  u_int32_t length;
  u_int64_t mactime;
  u_int64_t hosttime;
  u_int32_t phytype;
  u_int32_t channel;
  u_int32_t datarate;
  u_int32_t antenna;
  u_int32_t priority;
  u_int32_t ssi_type;
  int32_t ssi_signal;
  int32_t ssi_noise;
  u_int32_t preamble;
  u_int32_t encoding;
  };
  
  /*========defined but not used=========*/
  /*prism value */
  struct prism_value{
  u_int32_t did;
  u_int16_t status;
  u_int16_t len;
  u_int32_t data;
  };
  
  /*prism header for traditional wireless card*/
  struct prism_header{
  u_int32_t msgcode;
  u_int32_t msglen;
  struct prism_value hosttime;
  struct prism_value mactime;
  struct prism_value channel;
  struct prism_value rssi;
  struct prism_value sq;
  struct prism_value signal;
  struct prism_value noise;
  struct prism_value rate;
  struct prism_value istx;
  struct prism_value frmlen;
  };
  /*===============================*/
  
  /*gracefully handle a Control + C action*/
  void
  ctrl_c()
  {
  printf("\nExiting\n");
  pcap_breakloop(handle); /*tell pcap_loop or pcap_dispatch to stop capturing*/
  pcap_close(handle);
  exit(0);
  }
  
  /*Usage of this program*/
  void
  usage (char *name)
  {
  printf("\n%s - simple ARP sniffer\n",name);
  printf("Usage: %s [-i interface] [-l] [-v]\n",name);
  printf("\t-i\tinterface to sniff on\n");
  printf("\t-l\tlist available interfaces\n");
  printf("\t-v\tprint verbose info\n");
  exit(1);
  }
  
  /*callback function to process a packet when captured*/
  void
  process_packet(u_char *args, const struct pcap_pkthdr *header,\
      const u_char *packet)
  {
  struct ether_header *eth_header; /*in ethernet.h included by if_eth.h*/
  struct wireless_80211_header_t *wireless_header; /*80211 header*/
  struct snap_header_t *llc_header; /*RFC 1042 encapsulation header*/
  struct ether_arp *arp_packet;   /*from if_eth.h*/
  
  if(wired)   /*global flag - wired or wireless*/
  {
      eth_header = (struct ether_header *) packet;
      arp_packet = (struct ether_arp *) (packet + ETH_HEADER_SIZE);
      if(ntohs(eth_header-&gt;ether_type) != ETHERTYPE_ARP)return;
  }
  else
  {
      /*wireless*/
      wireless_header = (struct wireless_80211_header_t *)
          (packet + AVS_HEADER_SIZE);
  
      llc_header = (struct snap_header_t *)
          (packet + AVS_HEADER_SIZE + DATA_80211_FRAME_SIZE);
      arp_packet = (struct ether_arp *)
          (packet + AVS_HEADER_SIZE + DATA_80211_FRAME_SIZE + LLC_HEADER_SIZE);
      if(ntohs(llc_header-&gt;ether_type) != ETHERTYPE_ARP)return;
  }
  
  printf("SRC: %.2X.%.2X.%.2X.%.2X.%.2X.%.2X--&gt; DES:"
              "%.2X.%.2X.%.2X.%.2X.%.2X.%.2X\n",
              wireless_header-&gt;sa[0]&amp;MAC_MASK,
              wireless_header-&gt;sa[1]&amp;MAC_MASK,
              wireless_header-&gt;sa[2]&amp;MAC_MASK,
              wireless_header-&gt;sa[3]&amp;MAC_MASK,
              wireless_header-&gt;sa[4]&amp;MAC_MASK,
              wireless_header-&gt;sa[5]&amp;MAC_MASK,
              wireless_header-&gt;da[0]&amp;MAC_MASK,
              wireless_header-&gt;da[1]&amp;MAC_MASK,
              wireless_header-&gt;da[2]&amp;MAC_MASK,
              wireless_header-&gt;da[3]&amp;MAC_MASK,
              wireless_header-&gt;da[4]&amp;MAC_MASK,
              wireless_header-&gt;da[5]&amp;MAC_MASK);
  
  printf("Src: %d.%d.%d.%d--&gt; Des: %d.%d.%d.%d\n",
          arp_packet-&gt;arp_spa[0],
          arp_packet-&gt;arp_spa[1],
          arp_packet-&gt;arp_spa[2],
          arp_packet-&gt;arp_spa[3],
          arp_packet-&gt;arp_tpa[0],
          arp_packet-&gt;arp_tpa[1],
          arp_packet-&gt;arp_tpa[2],
          arp_packet-&gt;arp_tpa[3]);
  
  }/*end of process_packet*/
  
  /*the main function*/
  int
  main(int argc,char *argv[])
  {
  char opt;                           /*for option processing*/
  char errbuf[PCAP_ERRBUF_SIZE];  /*pcap error messages buffer*/
  struct pcap_pkthdr header;      /*packet header from pcap*/
  const u_char *packet;           /*packet*/
  bpf_u_int32 netp;       /*ip address of interface*/
  bpf_u_int32 maskp;      /*subnet mask of interface*/
  char *filter = "arp";   /*filter for BPF (human readable)*/
  struct bpf_program fp;  /*compiled BPF filter*/
  int ret;                /*gegeric return value*/
  pcap_if_t *alldevsp;    /*list of interfaces*/
  
  while((opt = getopt(argc, argv, "i:vl")) &gt; 0)
  {
      switch(opt)
      {
          case 'i':
              device = optarg;
              break;
          case 'l':
              if(pcap_findalldevs (&amp;alldevsp,errbuf) &lt; 0)
              {
                  fprintf(stderr,"erros in find all devs: %s\n",errbuf);
                  exit(1);
              }
              while(alldevsp != NULL)
              {
                  printf("%s\n",alldevsp-&gt;name);
                  alldevsp = alldevsp-&gt;next;
              }
              exit(0);
          case 'v':
              verbose = 1;
              break;
          default:
              usage(argv[0]);
              break;
      }//end of switch
  
  }//end of while
  
  /*setup signal handler to Control+C will graceful*/
  signal(SIGINT,ctrl_c);
  
  
  /*find device for sniffing if needed*/
  if(device == NULL)/*if user hasn't specified a device*/
  {
      device = pcap_lookupdev(errbuf);/*let pcap find a compatible device*/
      if(device == NULL)//there was an error
      {
          fprintf(stderr,"%s\n",errbuf);
          exit(1);
      }
  }
  
  /*set errbuf to 0 length string to check for warnings*/
  //memset(errbuf,PCAP_ERRBUF_SIZE,0);
  errbuf[0] = 0;
  
  /*open device for sniffing*/
  handle = pcap_open_live(device, /*device to sniff on*/
                          BUFSIZ, /*maximum number of bytes to capture per packet*/
                          1,      /*set 1 for promisc mode,0 to not*/
                          0,      /*0,snigg until an error occurs*/
                          errbuf);
  
  if(handle == NULL)
  {
          fprintf(stderr,"%s\n",errbuf);
          exit(1);
  }
  if(strlen(errbuf) &gt; 0)
  {
          fprintf(stderr,"warning: %s\n",errbuf);
          errbuf[0] = 0;
  }
  if(verbose)
  {
          printf("Using device: %s\n",device);
          printf("libpcap version: %s\n",(char *)pcap_lib_version);
  }
  
  /*find out the datalink type of the connection*/
  if(pcap_datalink (handle) == DLT_EN10MB)
  {
      wired = 1;/*ethernet link*/
      printf("this is a ethernet link\n");
  }
  else if((pcap_datalink (handle) == DLT_IEEE802_11_RADIO_AVS)\
  ||(pcap_datalink (handle) == DLT_IEEE802_11_RADIO)\
  ||(pcap_datalink (handle) == DLT_IEEE802_11)\
  ||(pcap_datalink (handle) == DLT_PRISM_HEADER))
  {
      wired = 0;
      printf("this is a wireless link\n");
  }
  else
  {
      fprintf(stderr,"do not support this interface type!\n");
      exit(1);
  }
  
  /*get the IP subnet mask of the device,so we set a filter on it*/
  if(pcap_lookupnet(device,&amp;netp,&amp;maskp,errbuf) == -1)
  {
      fprintf(stderr,"%s\n",errbuf);
      exit(1);
  }
  
  /*compile the filter,so we can capture only stuff we are interested in*/
  if(pcap_compile(handle,&amp;fp,filter,0,maskp) == -1)
  {
      fprintf(stderr,"%s\n",pcap_geterr(handle));
      exit(1);
  }
  
  /*set the filter for the device we have opened*/
  if(pcap_setfilter(handle,&amp;fp) == -1)
  {
      fprintf(stderr,"%s\n",pcap_geterr(handle));
      exit(1);
  }
  
  /*it will be nice and free the memory used for the compiled filter*/
  pcap_freecode(&amp;fp);
  
  /*the 'main loop' of capturing packet with our callback function*/
  if((ret = pcap_loop(handle, /*our session created previous*/
                          -1, /*(count) a negative number means sniff until error*/
              process_packet, /*callback function*/
                      NULL)) &lt; 0)/*arg can be transfer to callback function*/
  {
      if(ret == -1)
      {   fprintf(stderr,"%s\n",pcap_geterr(handle));
          exit(1);
      }/*otherwise return should be -2,meaning pcap_breakloop has been called*/
  }
  
  /*close our session*/
  pcap_close(handle);
  
  return 0;
  }
  </code></pre>