airodump.c
上传用户:fubang
上传日期:2009-06-18
资源大小:2071k
文件大小:50k
源码类别:

其他

开发平台:

Unix_Linux

  1. /*
  2.  *  pcap-compatible 802.11 packet sniffer
  3.  *
  4.  *  Copyright (C) 2004,2005  Christophe Devine
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20. #include <sys/socket.h>
  21. #include <sys/ioctl.h>
  22. #include <sys/types.h>
  23. #include <sys/wait.h>
  24. #include <sys/time.h>
  25. #include <netpacket/packet.h>
  26. #include <linux/if_ether.h>
  27. #include <linux/wireless.h>
  28. #include <arpa/inet.h>
  29. #include <unistd.h>
  30. #include <signal.h>
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <errno.h>
  35. #include <time.h>
  36. #include "pcap.h"
  37. #include "uniqueiv.c"
  38. /* some constants */
  39. #define FORMAT_CAP 1
  40. #define FORMAT_IVS 2
  41. #define ARPHRD_IEEE80211        801
  42. #define ARPHRD_IEEE80211_PRISM  802
  43. #define ARPHRD_IEEE80211_FULL   803
  44. #define REFRESH_RATE 100000  /* delay in us between updates */
  45. #define BROADCAST_ADDR "xFFxFFxFFxFFxFFxFF"
  46. #define NB_PWR  5       /* size of signal power ring buffer */
  47. #define NB_PRB 10       /* size of probed ESSID ring buffer */
  48. char *f_ext[4] = { "txt", "gps", "cap", "ivs" };
  49. int bg_chans[] = { 1, 7, 13, 2, 8, 3, 14, 9, 4, 10, 5, 11, 6, 12, 0 };
  50. /* linked list of detected access points */
  51. struct AP_info
  52. {
  53.     struct AP_info *prev;     /* prev. AP in list         */
  54.     struct AP_info *next;     /* next  AP in list         */
  55.     time_t tinit, tlast;      /* first and last time seen */
  56.     int channel;              /* AP radio channel         */
  57.     int max_speed;            /* AP maximum speed in Mb/s */
  58.     int avg_power;            /* averaged signal power    */
  59.     int power_index;          /* index in power ring buf. */
  60.     int power_lvl[NB_PWR];    /* signal power ring buffer */
  61.     int preamble;             /* 0 = long, 1 = short      */
  62.     int encryption;           /* 0 = none, > 1 = WEP/WPA  */
  63.     unsigned long nb_bcn;     /* total number of beacons  */
  64.     unsigned long nb_pkt;     /* total number of packets  */
  65.     unsigned long nb_data;    /* number of  data packets  */
  66.     unsigned char bssid[6];   /* the access point's MAC   */
  67.     unsigned char essid[36];  /* ascii network identifier */
  68.     unsigned char lanip[4];   /* last detected ip address */
  69.                               /* if non-encrypted network */
  70.     unsigned char **uiv_root; /* unique iv root structure */
  71.                               /* if wep-encrypted network */
  72. };
  73. /* linked list of detected clients */
  74. struct ST_info
  75. {
  76.     struct ST_info *prev;    /* the prev client in list   */
  77.     struct ST_info *next;    /* the next client in list   */
  78.     struct AP_info *base;    /* AP this client belongs to */
  79.     time_t tinit, tlast;     /* first and last time seen  */
  80.     unsigned long nb_pkt;    /* total number of packets   */
  81.     unsigned char stmac[6];  /* the client's MAC address  */
  82.     int probe_index;         /* probed ESSIDs ring index  */
  83.     char probes[NB_PRB][36]; /* probed ESSIDs ring buffer */
  84.     int power;               /* last signal power         */
  85. };
  86. /* bunch of global stuff */
  87. struct globals
  88. {
  89.     struct AP_info *ap_1st, *ap_end;
  90.     struct ST_info *st_1st, *st_end;
  91.     unsigned char prev_bssid[6];
  92.     int f_index;            /* outfiles index       */
  93.     FILE *f_txt;            /* output csv file      */
  94.     FILE *f_gps;            /* output gps file      */
  95.     FILE *f_cap;            /* output cap file      */
  96.     FILE *f_ivs;            /* output ivs file      */
  97.     int battery;            /* remaining battery %  */
  98.     int channel;            /* current channel #    */
  99.     int ch_pipe[2];         /* current channel pipe */
  100.     int gc_pipe[2];         /* gps coordinates pipe */
  101.     float gps_loc[5];       /* gps coordinates      */
  102.     int save_gps;           /* keep gps file flag   */
  103.     int is_wlanng;          /* set if wlan-ng       */
  104.     int is_orinoco;         /* set if orinoco       */
  105.     int do_exit;            /* interrupt flag       */
  106.     struct winsize ws;      /* console window size  */
  107. }
  108. G;
  109. /* setup the output files */
  110. int dump_initialize( char *prefix, int ivs_only )
  111. {
  112.     int i;
  113.     FILE *f;
  114.     char ofn[1024];
  115.     /* check not to overflow the ofn buffer */
  116.     if( strlen( prefix ) >= sizeof( ofn ) - 10 )
  117.         prefix[sizeof( ofn ) - 10] = '';
  118.     /* make sure not to overwrite any existing file */
  119.     memset( ofn, 0, sizeof( ofn ) );
  120.     G.f_index = 1;
  121.     do
  122.     {
  123.         for( i = 0; i < 4; i++ )
  124.         {
  125.             snprintf( ofn,  sizeof( ofn ) - 1, "%s-%02d.%s",
  126.                       prefix, G.f_index, f_ext[i] );
  127.             if( ( f = fopen( ofn, "rb+" ) ) != NULL )
  128.             {
  129.                 fclose( f );
  130.                 G.f_index++;
  131.                 break;
  132.             }
  133.         }
  134.     }
  135.     while( i < 4 );
  136.     /* create the output CVS & GPS files */
  137.     snprintf( ofn,  sizeof( ofn ) - 1, "%s-%02d.txt",
  138.               prefix, G.f_index );
  139.     if( ( G.f_txt = fopen( ofn, "wb+" ) ) == NULL )
  140.     {
  141.         perror( "fopen failed" );
  142.         fprintf( stderr, "Could not create "%s".n", ofn );
  143.         return( 1 );
  144.     }
  145.     snprintf( ofn,  sizeof( ofn ) - 1, "%s-%02d.gps",
  146.               prefix, G.f_index );
  147.     if( ( G.f_gps = fopen( ofn, "wb+" ) ) == NULL )
  148.     {
  149.         perror( "fopen failed" );
  150.         fprintf( stderr, "Could not create "%s".n", ofn );
  151.         return( 1 );
  152.     }
  153.     /* create the output packet capture file */
  154.     if( ivs_only == 0 )
  155.     {
  156.         struct pcap_file_header pfh;
  157.         snprintf( ofn,  sizeof( ofn ) - 1, "%s-%02d.cap",
  158.                   prefix, G.f_index );
  159.         if( ( G.f_cap = fopen( ofn, "wb+" ) ) == NULL )
  160.         {
  161.             perror( "fopen failed" );
  162.             fprintf( stderr, "Could not create "%s".n", ofn );
  163.             return( 1 );
  164.         }
  165.         pfh.magic           = TCPDUMP_MAGIC;
  166.         pfh.version_major   = PCAP_VERSION_MAJOR;
  167.         pfh.version_minor   = PCAP_VERSION_MINOR;
  168.         pfh.thiszone        = 0;
  169.         pfh.sigfigs         = 0;
  170.         pfh.snaplen         = 65535;
  171.         pfh.linktype        = LINKTYPE_IEEE802_11;
  172.         if( fwrite( &pfh, 1, sizeof( pfh ), G.f_cap ) !=
  173.                     (size_t) sizeof( pfh ) )
  174.         {
  175.             perror( "fwrite(pcap file header) failed" );
  176.             return( 1 );
  177.         }
  178.     }
  179.     else
  180.     {
  181.         snprintf( ofn,  sizeof( ofn ) - 1, "%s-%02d.ivs",
  182.                   prefix, G.f_index );
  183.         if( ( G.f_ivs = fopen( ofn, "wb+" ) ) == NULL )
  184.         {
  185.             perror( "fopen failed" );
  186.             fprintf( stderr, "Could not create "%s".n", ofn );
  187.             return( 1 );
  188.         }
  189.         if( fwrite( IVSONLY_MAGIC, 1, 4, G.f_ivs ) != (size_t) 4 )
  190.         {
  191.             perror( "fwrite(IVs file header) failed" );
  192.             return( 1 );
  193.         }
  194.     }
  195.     return( 0 );
  196. }
  197. int dump_add_packet( unsigned char *h80211, int caplen, int power )
  198. {
  199.     int i, n, z;
  200.     unsigned char *p, c;
  201.     unsigned char bssid[6];
  202.     unsigned char stmac[6];
  203.     struct pcap_pkthdr pkh;
  204.     struct timeval tv;
  205.     struct AP_info *ap_cur = NULL;
  206.     struct ST_info *st_cur = NULL;
  207.     struct AP_info *ap_prv = NULL;
  208.     struct ST_info *st_prv = NULL;
  209.     /* skip packets smaller than a 802.11 header */
  210.     if( caplen < 24 )
  211.         goto write_packet;
  212.     /* skip (uninteresting) control frames */
  213.     if( ( h80211[0] & 0x0C ) == 0x04 )
  214.         goto write_packet;
  215.     /* locate the access point's MAC address */
  216.     switch( h80211[1] & 3 )
  217.     {
  218.         case  0: memcpy( bssid, h80211 + 16, 6 ); break;
  219.         case  1: memcpy( bssid, h80211 +  4, 6 ); break;
  220.         case  2: memcpy( bssid, h80211 + 10, 6 ); break;
  221.         default: memcpy( bssid, h80211 +  4, 6 ); break;
  222.     }
  223.     /* update our chained list of access points */
  224.     ap_cur = G.ap_1st;
  225.     ap_prv = NULL;
  226.     while( ap_cur != NULL )
  227.     {
  228.         if( ! memcmp( ap_cur->bssid, bssid, 6 ) )
  229.             break;
  230.         ap_prv = ap_cur;
  231.         ap_cur = ap_cur->next;
  232.     }
  233.     /* if it's a new access point, add it */
  234.     if( ap_cur == NULL )
  235.     {
  236.         if( ! ( ap_cur = (struct AP_info *) malloc(
  237.                          sizeof( struct AP_info ) ) ) )
  238.         {
  239.             perror( "malloc failed" );
  240.             return( 1 );
  241.         }
  242.         memset( ap_cur, 0, sizeof( struct AP_info ) );
  243.         if( G.ap_1st == NULL )
  244.             G.ap_1st = ap_cur;
  245.         else
  246.             ap_prv->next  = ap_cur;
  247.         memcpy( ap_cur->bssid, bssid, 6 );
  248.         ap_cur->prev = ap_prv;
  249.         ap_cur->tinit = time( NULL );
  250.         ap_cur->tlast = time( NULL );
  251.         ap_cur->avg_power   = -1;
  252.         ap_cur->power_index = -1;
  253.         for( i = 0; i < NB_PWR; i++ )
  254.             ap_cur->power_lvl[i] = -1;
  255.         ap_cur->channel    = -1;
  256.         ap_cur->max_speed  = -1;
  257.         ap_cur->encryption = -1;
  258.         ap_cur->uiv_root = uniqueiv_init();
  259.         G.ap_end = ap_cur;
  260.     }
  261.     /* update the last time seen */
  262.     ap_cur->tlast = time( NULL );
  263.     /* only update power if packets comes from
  264.      * the AP: either type == mgmt and SA != BSSID,
  265.      * or FromDS == 1 and ToDS == 0 */
  266.     if( ( ( h80211[1] & 3 ) == 0 &&
  267.             memcmp( h80211 + 10, bssid, 6 ) == 0 ) ||
  268.         ( ( h80211[1] & 3 ) == 2 ) )
  269.     {
  270.         ap_cur->power_index = ( ap_cur->power_index + 1 ) % NB_PWR;
  271.         ap_cur->power_lvl[ap_cur->power_index] = power;
  272.         ap_cur->avg_power = 0;
  273.         for( i = 0, n = 0; i < NB_PWR; i++ )
  274.         {
  275.             if( ap_cur->power_lvl[i] != -1 )
  276.             {
  277.                 ap_cur->avg_power += ap_cur->power_lvl[i];
  278.                 n++;
  279.             }
  280.         }
  281.         if( n > 0 )
  282.             ap_cur->avg_power /= n;
  283.         else
  284.             ap_cur->avg_power = -1;
  285.     }
  286.     if( h80211[0] == 0x80 )
  287.         ap_cur->nb_bcn++;
  288.     ap_cur->nb_pkt++;
  289.     /* locate the station MAC in the 802.11 header */
  290.     switch( h80211[1] & 3 )
  291.     {
  292.         case  0:
  293.             /* if management, check that SA != BSSID */
  294.             if( memcmp( h80211 + 10, bssid, 6 ) == 0 )
  295.                 goto skip_station;
  296.             memcpy( stmac, h80211 + 10, 6 );
  297.             break;
  298.         case  1:
  299.             /* ToDS packet, must come from a client */
  300.             memcpy( stmac, h80211 + 10, 6 );
  301.             break;
  302.         case  2:
  303.             /* FromDS packet, reject broadcast MACs */
  304.             if( h80211[4] != 0 ) goto skip_station;
  305.             memcpy( stmac, h80211 +  4, 6 ); break;
  306.         default: goto skip_station;
  307.     }
  308.     /* update our chained list of wireless stations */
  309.     st_cur = G.st_1st;
  310.     st_prv = NULL;
  311.     while( st_cur != NULL )
  312.     {
  313.         if( ! memcmp( st_cur->stmac, stmac, 6 ) )
  314.             break;
  315.         st_prv = st_cur;
  316.         st_cur = st_cur->next;
  317.     }
  318.     /* if it's a new client, add it */
  319.     if( st_cur == NULL )
  320.     {
  321.         if( ! ( st_cur = (struct ST_info *) malloc(
  322.                          sizeof( struct ST_info ) ) ) )
  323.         {
  324.             perror( "malloc failed" );
  325.             return( 1 );
  326.         }
  327.         memset( st_cur, 0, sizeof( struct ST_info ) );
  328.         if( G.st_1st == NULL )
  329.             G.st_1st = st_cur;
  330.         else
  331.             st_prv->next  = st_cur;
  332.         memcpy( st_cur->stmac, stmac, 6 );
  333.         st_cur->prev = st_prv;
  334.         st_cur->tinit = time( NULL );
  335.         st_cur->tlast = time( NULL );
  336.         st_cur->power = -1;
  337.         st_cur->probe_index = -1;
  338.         for( i = 0; i < NB_PRB; i++ )
  339.             memset( st_cur->probes[i], 0, sizeof(
  340.                     st_cur->probes[i] ) );
  341.         G.st_end = st_cur;
  342.     }
  343.     if( st_cur->base == NULL ||
  344.         memcmp( ap_cur->bssid, BROADCAST_ADDR, 6 ) != 0 )
  345.         st_cur->base = ap_cur;
  346.     /* update the last time seen */
  347.     st_cur->tlast = time( NULL );
  348.     /* only update power if packets comes from the 
  349.      * client: either type == Mgmt and SA != BSSID,
  350.      * or FromDS == 0 and ToDS == 1 */
  351.     if( ( ( h80211[1] & 3 ) == 0 &&
  352.             memcmp( h80211 + 10, bssid, 6 ) != 0 ) ||
  353.         ( ( h80211[1] & 3 ) == 1 ) )
  354.     {
  355.         st_cur->power = power;
  356.     }
  357.     st_cur->nb_pkt++;
  358. skip_station:
  359.     /* packet parsing: Probe Request */
  360.     if( h80211[0] == 0x40 && st_cur != NULL )
  361.     {
  362.         p = h80211 + 24;
  363.         while( p < h80211 + caplen )
  364.         {
  365.             if( p + 2 + p[1] > h80211 + caplen )
  366.                 break;
  367.             if( p[0] == 0x00 && p[1] > 0 && p[2] != '' &&
  368.                 ( p[1] > 1 || p[2] != ' ' ) )
  369.             {
  370.                 n = ( p[1] > 32 ) ? 32 : p[1];
  371.                 for( i = 0; i < n; i++ )
  372.                     if( p[2 + i] > 0 && p[2 + i] < ' ' )
  373.                         goto skip_probe;
  374.                 /* got a valid ASCII probed ESSID, check if it's
  375.                    already in the ring buffer */
  376.                 for( i = 0; i < NB_PRB; i++ )
  377.                     if( memcmp( st_cur->probes[i], p + 2, n ) == 0 )
  378.                         goto skip_probe;
  379.                 st_cur->probe_index = ( st_cur->probe_index + 1 ) % NB_PRB;
  380.                 memset( st_cur->probes[st_cur->probe_index], 0, 36 );
  381.                 memcpy( st_cur->probes[st_cur->probe_index], p + 2, n );
  382.                 for( i = 0; i < n; i++ )
  383.                 {
  384.                     c = p[2 + i];
  385.                     if( c == 0 || ( c > 126 && c < 160 ) ) c = '.';
  386.                     st_cur->probes[st_cur->probe_index][i] = c;
  387.                 }
  388.             }
  389.             p += 2 + p[1];
  390.         }
  391.     }
  392. skip_probe:
  393.     /* packet parsing: Beacon or Probe Response */
  394.     if( h80211[0] == 0x80 || h80211[0] == 0x50 )
  395.     {
  396.         if( ap_cur->encryption < 0 )
  397.             ap_cur->encryption = ( h80211[34] & 0x10 ) >> 4;
  398.         ap_cur->preamble = ( h80211[34] & 0x20 ) >> 5;
  399.         p = h80211 + 36;
  400.         while( p < h80211 + caplen )
  401.         {
  402.             if( p + 2 + p[1] > h80211 + caplen )
  403.                 break;
  404.             if( p[0] == 0x00 && p[1] > 0 && p[2] != '' &&
  405.                 ( p[1] > 1 || p[2] != ' ' ) )
  406.             {
  407.                 /* found a non-cloaked ESSID */
  408.                 n = ( p[1] > 32 ) ? 32 : p[1];
  409.                 memset( ap_cur->essid, 0, 36 );
  410.                 memcpy( ap_cur->essid, p + 2, n );
  411.                 for( i = 0; i < n; i++ )
  412.                     if( ( ap_cur->essid[i] >   0 && ap_cur->essid[i] <  32 ) ||
  413.                         ( ap_cur->essid[i] > 126 && ap_cur->essid[i] < 160 ) )
  414.                         ap_cur->essid[i] = '.';
  415.             }
  416.             /* get the maximum speed in Mb and the AP's channel */
  417.             if( p[0] == 0x01 || p[0] == 0x32 )
  418.                 ap_cur->max_speed = ( p[1 + p[1]] & 0x7F ) / 2;
  419.             if( p[0] == 0x03 )
  420.                 ap_cur->channel = p[2];
  421.             p += 2 + p[1];
  422.         }
  423.     }
  424.     /* packet parsing: Association Request */
  425.     if( h80211[0] == 0x00 )
  426.     {
  427.         p = h80211 + 28;
  428.         while( p < h80211 + caplen )
  429.         {
  430.             if( p + 2 + p[1] > h80211 + caplen )
  431.                 break;
  432.             if( p[0] == 0x00 && p[1] > 0 && p[2] != '' &&
  433.                 ( p[1] > 1 || p[2] != ' ' ) )
  434.             {
  435.                 /* found a non-cloaked ESSID */
  436.                 n = ( p[1] > 32 ) ? 32 : p[1];
  437.                 memset( ap_cur->essid, 0, 33 );
  438.                 memcpy( ap_cur->essid, p + 2, n );
  439.                 for( i = 0; i < n; i++ )
  440.                     if( ap_cur->essid[i] < 32 ||
  441.                       ( ap_cur->essid[i] > 126 && ap_cur->essid[i] < 160 ) )
  442.                         ap_cur->essid[i] = '.';
  443.             }
  444.             p += 2 + p[1];
  445.         }
  446.     }
  447.     /* packet parsing: some data */
  448.     if( ( h80211[0] & 0x0C ) == 0x08 )
  449.     {
  450.         /* update the channel if we didn't get any beacon */
  451.         if( ap_cur->channel == -1 )
  452.             ap_cur->channel = G.channel;
  453.         /* check the SNAP header to see if data is encrypted */
  454.         z = ( ( h80211[1] & 3 ) != 3 ) ? 24 : 30;
  455.         if( z + 26 > caplen )
  456.             goto write_packet;
  457.         if( h80211[z] == h80211[z + 1] && h80211[z + 2] == 0x03 )
  458.         {
  459.             if( ap_cur->encryption < 0 )
  460.                 ap_cur->encryption = 0;
  461.             /* if ethertype == IPv4, find the LAN address */
  462.             if( h80211[z + 6] == 0x08 && h80211[z + 7] == 0x00 &&
  463.                 ( h80211[1] & 3 ) == 0x01 )
  464.                     memcpy( ap_cur->lanip, &h80211[z + 20], 4 );
  465.             if( h80211[z + 6] == 0x08 && h80211[z + 7] == 0x06 )
  466.                 memcpy( ap_cur->lanip, &h80211[z + 22], 4 );
  467.         }
  468.         else
  469.             ap_cur->encryption = 2 + ( ( h80211[z + 3] & 0x20 ) >> 5 );
  470.         if( z + 10 > caplen )
  471.             goto write_packet;
  472.         if( ap_cur->encryption == 2 )
  473.         {
  474.             /* WEP: check if we've already seen this IV */
  475.             if( ! uniqueiv_check( ap_cur->uiv_root, &h80211[z] ) )
  476.             {
  477.                 /* first time seen IVs */
  478.                 if( G.f_ivs != NULL )
  479.                 {
  480.                     unsigned char iv_info[64];
  481.                     if( memcmp( G.prev_bssid, ap_cur->bssid, 6 ) == 0 )
  482.                     {
  483.                         iv_info[0] = 0xFF;
  484.                         memcpy( iv_info + 1, &h80211[z    ], 3 );
  485.                         memcpy( iv_info + 4, &h80211[z + 4], 2 );
  486.                         n =  6;
  487.                     }
  488.                     else
  489.                     {
  490.                         memcpy( G.prev_bssid, ap_cur->bssid,  6 );
  491.                         memcpy( iv_info     , ap_cur->bssid,  6 );
  492.                         memcpy( iv_info + 6 , &h80211[z    ], 3 );
  493.                         memcpy( iv_info + 9 , &h80211[z + 4], 2 );
  494.                         n = 11;
  495.                     }
  496.                     if( fwrite( iv_info, 1, n, G.f_ivs ) != (size_t) n )
  497.                     {
  498.                         perror( "fwrite(IV info) failed" );
  499.                         return( 1 );
  500.                     }
  501.                 }
  502.                 uniqueiv_mark( ap_cur->uiv_root, &h80211[z] );
  503.                 ap_cur->nb_data++;
  504.             }
  505.         }
  506.         else
  507.             ap_cur->nb_data++;
  508.     }
  509. write_packet:
  510.     if( G.f_cap != NULL )
  511.     {
  512.         pkh.caplen = pkh.len = caplen;
  513.         gettimeofday( &tv, NULL );
  514.         pkh.tv_sec  =   tv.tv_sec;
  515.         pkh.tv_usec = ( tv.tv_usec & ~0x1ff ) + power + 64;
  516.         n = sizeof( pkh );
  517.         if( fwrite( &pkh, 1, n, G.f_cap ) != (size_t) n )
  518.         {
  519.             perror( "fwrite(packet header) failed" );
  520.             return( 1 );
  521.         }
  522.         fflush( stdout );
  523.         n = pkh.caplen;
  524.         if( fwrite( h80211, 1, n, G.f_cap ) != (size_t) n )
  525.         {
  526.             perror( "fwrite(packet data) failed" );
  527.             return( 1 );
  528.         }
  529.         fflush( stdout );
  530.     }
  531.     return( 0 );
  532. }
  533. void dump_sort_power( void )
  534. {
  535.     time_t tt = time( NULL );
  536.     /* thanks to Arnaud Cornet :-) */
  537.     struct AP_info *new_ap_1st = NULL;
  538.     struct AP_info *new_ap_end = NULL;
  539.     struct ST_info *new_st_1st = NULL;
  540.     struct ST_info *new_st_end = NULL;
  541.     struct ST_info *st_cur, *st_min;
  542.     struct AP_info *ap_cur, *ap_min;
  543.     /* sort the aps by power first */
  544.     while( G.ap_1st )
  545.     {
  546.         ap_min = NULL;
  547.         ap_cur = G.ap_1st;
  548.         while( ap_cur != NULL )
  549.         {
  550.             if( tt - ap_cur->tlast > 20 )
  551.                 ap_min = ap_cur;
  552.             ap_cur = ap_cur->next;
  553.         }
  554.         if( ap_min == NULL )
  555.         {
  556.             ap_min = ap_cur = G.ap_1st;
  557.             while( ap_cur != NULL )
  558.             {
  559.                 if( ap_cur->avg_power < ap_min->avg_power)
  560.                     ap_min = ap_cur;
  561.                 ap_cur = ap_cur->next;
  562.             }
  563.         }
  564.         if( ap_min == G.ap_1st )
  565.             G.ap_1st = ap_min->next;
  566.         if( ap_min == G.ap_end )
  567.             G.ap_end = ap_min->prev;
  568.         if( ap_min->next )
  569.             ap_min->next->prev = ap_min->prev;
  570.         if( ap_min->prev )
  571.             ap_min->prev->next = ap_min->next;
  572.         if( new_ap_end )
  573.         {
  574.             new_ap_end->next = ap_min;
  575.             ap_min->prev = new_ap_end;
  576.             new_ap_end = ap_min;
  577.             new_ap_end->next = NULL;
  578.         }
  579.         else
  580.         {
  581.             new_ap_1st = new_ap_end = ap_min;
  582.             ap_min->next = ap_min->prev = NULL;
  583.         }
  584.     }
  585.     G.ap_1st = new_ap_1st;
  586.     G.ap_end = new_ap_end;
  587.     /* now sort the stations */
  588.     while( G.st_1st )
  589.     {
  590.         st_min = NULL;
  591.         st_cur = G.st_1st;
  592.         while( st_cur != NULL )
  593.         {
  594.             if( tt - st_cur->tlast > 60 )
  595.                 st_min = st_cur;
  596.             st_cur = st_cur->next;
  597.         }
  598.         if( st_min == NULL )
  599.         {
  600.             st_min = st_cur = G.st_1st;
  601.             while( st_cur != NULL )
  602.             {
  603.                 if( st_cur->power < st_min->power)
  604.                     st_min = st_cur;
  605.                 st_cur = st_cur->next;
  606.             }
  607.         }
  608.         if( st_min == G.st_1st )
  609.             G.st_1st = st_min->next;
  610.         if( st_min == G.st_end )
  611.             G.st_end = st_min->prev;
  612.         if( st_min->next )
  613.             st_min->next->prev = st_min->prev;
  614.         if( st_min->prev )
  615.             st_min->prev->next = st_min->next;
  616.         if( new_st_end )
  617.         {
  618.             new_st_end->next = st_min;
  619.             st_min->prev = new_st_end;
  620.             new_st_end = st_min;
  621.             new_st_end->next = NULL;
  622.         }
  623.         else
  624.         {
  625.             new_st_1st = new_st_end = st_min;
  626.             st_min->next = st_min->prev = NULL;
  627.         }
  628.     }
  629.     G.st_1st = new_st_1st;
  630.     G.st_end = new_st_end;
  631. }
  632. void dump_print( int ws_row, int ws_col )
  633. {
  634.     time_t tt;
  635.     struct tm *lt;
  636.     int nlines, i, n;
  637.     char strbuf[512];
  638.     char ssid_list[512];
  639.     struct AP_info *ap_cur;
  640.     struct ST_info *st_cur;
  641.     nlines = 2;
  642.     if( nlines >= ws_row )
  643.         return;
  644.     tt = time( NULL );
  645.     lt = localtime( &tt );
  646.     /* display the channel, battery, position and current time */
  647.     memset( strbuf, ' ', ws_col - 1 );
  648.     strbuf[ws_col - 1] = '';
  649.     fprintf( stderr, "%sn", strbuf );
  650.     snprintf( strbuf, sizeof( strbuf ) - 1,
  651.               " CH %2d ][ BAT %3d%% ][ GPS %8.3f %8.3f %8.3f %6.2f "
  652.               "][ %04d-%02d-%02d %02d:%02d ", G.channel, G.battery,
  653.               G.gps_loc[0], G.gps_loc[1], G.gps_loc[2], G.gps_loc[3],
  654.               1900 + lt->tm_year, 1 + lt->tm_mon, lt->tm_mday,
  655.               lt->tm_hour, lt->tm_min );
  656.     strbuf[ws_col - 1] = '';
  657.     fprintf( stderr, "%sn", strbuf );
  658.     /* print some informations about each detected AP */
  659.     nlines += 3;
  660.     if( nlines >= ws_row )
  661.         return;
  662.     memset( strbuf, ' ', ws_col - 1 );
  663.     strbuf[ws_col - 1] = '';
  664.     fprintf( stderr, "%sn", strbuf );
  665.     memcpy( strbuf, " BSSID              PWR  Beacons"
  666.                     "   # Data  CH  MB  ENC   ESSID", 62 );
  667.     strbuf[ws_col - 1] = '';
  668.     fprintf( stderr, "%sn", strbuf );
  669.     memset( strbuf, ' ', ws_col - 1 );
  670.     strbuf[ws_col - 1] = '';
  671.     fprintf( stderr, "%sn", strbuf );
  672.     ap_cur = G.ap_end;
  673.     while( ap_cur != NULL )
  674.     {
  675.         /* skip APs with only one packet, or those older than 2 min.
  676.          * always skip if bssid == broadcast */
  677.         if( ap_cur->nb_pkt < 2 || time( NULL ) - ap_cur->tlast > 120 ||
  678.             memcmp( ap_cur->bssid, BROADCAST_ADDR, 6 ) == 0 )
  679.         {
  680.             ap_cur = ap_cur->prev;
  681.             continue;
  682.         }
  683.         nlines++;
  684.         if( nlines >= ws_row )
  685.             return;
  686.         fprintf( stderr, " %02X:%02X:%02X:%02X:%02X:%02X",
  687.                 ap_cur->bssid[0], ap_cur->bssid[1],
  688.                 ap_cur->bssid[2], ap_cur->bssid[3],
  689.                 ap_cur->bssid[4], ap_cur->bssid[5] );
  690.         fprintf( stderr, "  %3d %8ld %8ld",
  691.                  ap_cur->avg_power,
  692.                  ap_cur->nb_bcn,
  693.                  ap_cur->nb_data );
  694.         fprintf( stderr, " %3d %3d%c ",
  695.                  ap_cur->channel, ap_cur->max_speed,
  696.                  ( ap_cur->preamble ) ? '.' : ' ' );
  697.         switch( ap_cur->encryption )
  698.         {
  699.             case  0: fprintf( stderr, "OPN " ); break;
  700.             case  1: fprintf( stderr, "WEP?" ); break;
  701.             case  2: fprintf( stderr, "WEP " ); break;
  702.             case  3: fprintf( stderr, "WPA " ); break;
  703.             default: fprintf( stderr, "    " ); break;
  704.         }
  705.         if( ws_col > 58 )
  706.         {
  707.             memset( strbuf, 0, sizeof( strbuf ) );
  708.             snprintf( strbuf,  sizeof( strbuf ) - 1,
  709.                       "%-256s", ap_cur->essid );
  710.             strbuf[ws_col - 58] = '';
  711.             fprintf( stderr, "  %s", strbuf );
  712.         }
  713.         fprintf( stderr, "n" );
  714.         ap_cur = ap_cur->prev;
  715.     }
  716.     /* print some informations about each detected station */
  717.     nlines += 3;
  718.     if( nlines >= ws_row )
  719.         return;
  720.     memset( strbuf, ' ', ws_col - 1 );
  721.     strbuf[ws_col - 1] = '';
  722.     fprintf( stderr, "%sn", strbuf );
  723.     memcpy( strbuf, " BSSID              STATION "
  724.             "           PWR  Packets  Probes", 59 );
  725.     strbuf[ws_col - 1] = '';
  726.     fprintf( stderr, "%sn", strbuf );
  727.     memset( strbuf, ' ', ws_col - 1 );
  728.     strbuf[ws_col - 1] = '';
  729.     fprintf( stderr, "%sn", strbuf );
  730.     ap_cur = G.ap_end;
  731.     while( ap_cur != NULL )
  732.     {
  733.         if( ap_cur->nb_pkt < 2 ||
  734.             time( NULL ) - ap_cur->tlast > 120 )
  735.         {
  736.             ap_cur = ap_cur->prev;
  737.             continue;
  738.         }
  739.         if( nlines >= ws_row )
  740.             return;
  741.         st_cur = G.st_end;
  742.         while( st_cur != NULL )
  743.         {
  744.             if( st_cur->base != ap_cur ||
  745.                 time( NULL ) - st_cur->tlast > 120 )
  746.             {
  747.                 st_cur = st_cur->prev;
  748.                 continue;
  749.             }
  750.             nlines++;
  751.             if( ws_row != 0 && nlines > ws_row )
  752.                 return;
  753.             if( ! memcmp( ap_cur->bssid, BROADCAST_ADDR, 6 ) )
  754.                 fprintf( stderr, " (not associated) " );
  755.             else
  756.                 fprintf( stderr, " %02X:%02X:%02X:%02X:%02X:%02X",
  757.                         ap_cur->bssid[0], ap_cur->bssid[1],
  758.                         ap_cur->bssid[2], ap_cur->bssid[3],
  759.                         ap_cur->bssid[4], ap_cur->bssid[5] );
  760.             fprintf( stderr, "  %02X:%02X:%02X:%02X:%02X:%02X",
  761.                     st_cur->stmac[0], st_cur->stmac[1],
  762.                     st_cur->stmac[2], st_cur->stmac[3],
  763.                     st_cur->stmac[4], st_cur->stmac[5] );
  764.             fprintf( stderr, "  %3d", st_cur->power );
  765.             fprintf( stderr, " %8ld", st_cur->nb_pkt );
  766.             if( ws_col > 53 )
  767.             {
  768.                 memset( ssid_list, 0, sizeof( ssid_list ) );
  769.                 for( i = 0, n = 0; i < NB_PRB; i++ )
  770.                 {
  771.                     if( st_cur->probes[i][0] == '' )
  772.                         continue;
  773.                     snprintf( ssid_list + n, sizeof( ssid_list ) - n - 1,
  774.                               "%c%s", ( i > 0 ) ? ',' : ' ',
  775.                               st_cur->probes[i] );
  776.                     n += ( 1 + strlen( st_cur->probes[i] ) );
  777.                     if( n >= (int) sizeof( ssid_list ) )
  778.                         break;
  779.                 }
  780.                 memset( strbuf, 0, sizeof( strbuf ) );
  781.                 snprintf( strbuf,  sizeof( strbuf ) - 1,
  782.                           "%-256s", ssid_list );
  783.                 strbuf[ws_col - 53] = '';
  784.                 fprintf( stderr, " %s", strbuf );
  785.             }
  786.             fprintf( stderr, "n" );
  787.             st_cur = st_cur->prev;
  788.         }
  789.         ap_cur = ap_cur->prev;
  790.     }
  791. }
  792. void dump_write_csv( void )
  793. {
  794.     int i, n;
  795.     struct tm *ltime;
  796.     char ssid_list[512];
  797.     struct AP_info *ap_cur;
  798.     struct ST_info *st_cur;
  799.     fseek( G.f_txt, 0, SEEK_SET );
  800.     fprintf( G.f_txt,
  801.         "rnBSSID, First time seen, Last time seen, channel, Speed, "
  802.         "Privacy, Power, # beacons, # data, LAN IP, ESSIDrn" );
  803.     ap_cur = G.ap_1st;
  804.     while( ap_cur != NULL )
  805.     {
  806.         if( memcmp( ap_cur->bssid, BROADCAST_ADDR, 6 ) == 0 )
  807.         {
  808.             ap_cur = ap_cur->next;
  809.             continue;
  810.         }
  811.         if( ap_cur->nb_pkt < 2 )
  812.         {
  813.             ap_cur = ap_cur->next;
  814.             continue;
  815.         }
  816.         fprintf( G.f_txt, "%02X:%02X:%02X:%02X:%02X:%02X, ",
  817.                  ap_cur->bssid[0], ap_cur->bssid[1],
  818.                  ap_cur->bssid[2], ap_cur->bssid[3],
  819.                  ap_cur->bssid[4], ap_cur->bssid[5] );
  820.         ltime = localtime( &ap_cur->tinit );
  821.         fprintf( G.f_txt, "%04d-%02d-%02d %02d:%02d:%02d, ",
  822.                  1900 + ltime->tm_year, 1 + ltime->tm_mon,
  823.                  ltime->tm_mday, ltime->tm_hour,
  824.                  ltime->tm_min,  ltime->tm_sec );
  825.         ltime = localtime( &ap_cur->tlast );
  826.         fprintf( G.f_txt, "%04d-%02d-%02d %02d:%02d:%02d, ",
  827.                  1900 + ltime->tm_year, 1 + ltime->tm_mon,
  828.                  ltime->tm_mday, ltime->tm_hour,
  829.                  ltime->tm_min,  ltime->tm_sec );
  830.         fprintf( G.f_txt, "%2d, %3d, ",
  831.                  ap_cur->channel,
  832.                  ap_cur->max_speed );
  833.         switch( ap_cur->encryption )
  834.         {
  835.             case  0: fprintf( G.f_txt, "OPN " ); break;
  836.             case  1: fprintf( G.f_txt, "WEP?" ); break;
  837.             case  2: fprintf( G.f_txt, "WEP " ); break;
  838.             case  3: fprintf( G.f_txt, "WPA " ); break;
  839.             default: fprintf( G.f_txt, "    " ); break;
  840.         }
  841.         fprintf( G.f_txt, ", %3d, %8ld, %8ld, ",
  842.                  ap_cur->avg_power,
  843.                  ap_cur->nb_bcn,
  844.                  ap_cur->nb_data );
  845.         fprintf( G.f_txt, "%3d.%3d.%3d.%3d, ",
  846.                  ap_cur->lanip[0], ap_cur->lanip[1],
  847.                  ap_cur->lanip[2], ap_cur->lanip[2] );
  848.         fprintf( G.f_txt, "%-32srn", ap_cur->essid );
  849.         ap_cur = ap_cur->next;
  850.     }
  851.     fprintf( G.f_txt,
  852.         "rnStation MAC, First time seen, Last time seen, "
  853.         "Power, # packets, BSSID, Probed ESSIDsrn" );
  854.     st_cur = G.st_1st;
  855.     while( st_cur != NULL )
  856.     {
  857.         ap_cur = st_cur->base;
  858.         if( ap_cur->nb_pkt < 2 )
  859.         {
  860.             st_cur = st_cur->next;
  861.             continue;
  862.         }
  863.         fprintf( G.f_txt, "%02X:%02X:%02X:%02X:%02X:%02X, ",
  864.                  st_cur->stmac[0], st_cur->stmac[1],
  865.                  st_cur->stmac[2], st_cur->stmac[3],
  866.                  st_cur->stmac[4], st_cur->stmac[5] );
  867.         ltime = localtime( &st_cur->tinit );
  868.         fprintf( G.f_txt, "%04d-%02d-%02d %02d:%02d:%02d, ",
  869.                  1900 + ltime->tm_year, 1 + ltime->tm_mon,
  870.                  ltime->tm_mday, ltime->tm_hour,
  871.                  ltime->tm_min,  ltime->tm_sec );
  872.         ltime = localtime( &st_cur->tlast );
  873.         fprintf( G.f_txt, "%04d-%02d-%02d %02d:%02d:%02d, ",
  874.                  1900 + ltime->tm_year, 1 + ltime->tm_mon,
  875.                  ltime->tm_mday, ltime->tm_hour,
  876.                  ltime->tm_min,  ltime->tm_sec );
  877.         fprintf( G.f_txt, "%3d, %8ld, ",
  878.                  st_cur->power,
  879.                  st_cur->nb_pkt );
  880.         if( ! memcmp( ap_cur->bssid, BROADCAST_ADDR, 6 ) )
  881.             fprintf( G.f_txt, "(not associated) ," );
  882.         else
  883.             fprintf( G.f_txt, "%02X:%02X:%02X:%02X:%02X:%02X,",
  884.                      ap_cur->bssid[0], ap_cur->bssid[1],
  885.                      ap_cur->bssid[2], ap_cur->bssid[3],
  886.                      ap_cur->bssid[4], ap_cur->bssid[5] );
  887.         memset( ssid_list, 0, sizeof( ssid_list ) );
  888.         for( i = 0, n = 0; i < NB_PRB; i++ )
  889.         {
  890.             if( st_cur->probes[i][0] == '' )
  891.                 continue;
  892.             snprintf( ssid_list + n, sizeof( ssid_list ) - n - 1,
  893.                       "%c%s", ( i > 0 ) ? ',' : ' ', st_cur->probes[i] );
  894.             n += ( 1 + strlen( st_cur->probes[i] ) );
  895.             if( n >= (int) sizeof( ssid_list ) )
  896.                 break;
  897.         }
  898.         fprintf( G.f_txt, "%srn", ssid_list );
  899.         st_cur = st_cur->next;
  900.     }
  901.     fprintf( G.f_txt, "rn" );
  902.     fflush( G.f_txt );
  903.     sync();
  904. }
  905. void update_battery( void )
  906. {
  907.     FILE *f;
  908.     char line[256], *p;
  909.     int a, total, b, remaining, i;
  910.     G.battery = -1;
  911.     if( ( f = fopen( "/proc/apm", "r" ) ) != NULL )
  912.     {
  913.         /* old fashioned APM interface */
  914.         memset( line, 0, sizeof( line ) );
  915.         fgets( line, sizeof( line ) - 1, f );
  916.         p = strtok( line, " " );
  917.         for( i = 0; i < 6; i++ )
  918.         {
  919.             if( p == NULL ) return;
  920.             p = strtok( NULL, " " );
  921.         }
  922.         if( p == NULL ) return;
  923.         sscanf( p, "%d%%", &G.battery );
  924.         return;
  925.     }
  926.     total = 1;
  927.     remaining = 0;
  928.     for( i = 0; i < 4; i++ )
  929.     {
  930.         /* ACPI interface w/ multiple batteries support */
  931.         memset( line, 0, sizeof( line ) );
  932.         snprintf( line,  sizeof( line ) - 1,
  933.                   "/proc/acpi/battery/BAT%d/info", i );
  934.         if( ( f = fopen( line, "r" ) ) == NULL )
  935.             continue;
  936.         while( fgets( line, sizeof( line ), f ) != NULL )
  937.         {
  938.             if( memcmp( line, "design capacity:         ", 25 ) == 0 )
  939.             {
  940.                 sscanf( line + 25, "%d", &a );
  941.                 break;
  942.             }   
  943.         }
  944.         fclose( f );
  945.         memset( line, 0, sizeof( line ) );
  946.         snprintf( line,  sizeof( line ) - 1,
  947.                   "/proc/acpi/battery/BAT%d/state", i );
  948.         if( ( f = fopen( line, "r" ) ) == NULL )
  949.             continue;
  950.         while( fgets( line, sizeof( line ), f ) != NULL )
  951.         {
  952.             if( memcmp( line, "remaining capacity:      ", 25 ) == 0 )
  953.             {
  954.                 sscanf( line + 25, "%d", &b );
  955.                 break;
  956.             }   
  957.         }
  958.         fclose( f );
  959.         total += a;
  960.         remaining += b;
  961.     }
  962.     G.battery = ( 100 * remaining ) / total;
  963. }
  964. void gps_tracker( void )
  965. {
  966.     int gpsd_sock;
  967.     char line[256], *p;
  968.     struct sockaddr_in gpsd_addr;
  969.     /* attempt to connect to localhost, port 2947 */
  970.     gpsd_sock = socket( AF_INET, SOCK_STREAM, 0 );
  971.     if( gpsd_sock < 0 )
  972.         return;
  973.     gpsd_addr.sin_family      = AF_INET;
  974.     gpsd_addr.sin_port        = htons( 2947 );
  975.     gpsd_addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
  976.     if( connect( gpsd_sock, (struct sockaddr *) &gpsd_addr,
  977.                  sizeof( gpsd_addr ) ) < 0 )
  978.         return;
  979.     /* loop reading the GPS coordinates */
  980.     while( 1 )
  981.     {
  982.         sleep( 1 );
  983.         memset( G.gps_loc, 0, sizeof( float ) * 5 );
  984.         /* read position, speed, heading, altitude */
  985.         memset( line, 0, sizeof( line ) );
  986.         snprintf( line,  sizeof( line ) - 1, "PVTADrn" );
  987.         if( send( gpsd_sock, line, 3, 0 ) != 3 )
  988.             return;
  989.         memset( line, 0, sizeof( line ) );
  990.         if( recv( gpsd_sock, line, sizeof( line ) - 1, 0 ) <= 0 )
  991.             return;
  992.         if( memcmp( line, "GPSD,P=", 7 ) != 0 )
  993.             continue;
  994.         /* make sure the coordinates are present */
  995.         if( line[7] == '?' )
  996.             continue;
  997.         sscanf( line + 7, "%f %f", &G.gps_loc[0], &G.gps_loc[1] );
  998.         if( ( p = strstr( line, "V=" ) ) == NULL ) continue;
  999.         sscanf( p + 2, "%f", &G.gps_loc[2] ); /* speed */
  1000.         if( ( p = strstr( line, "T=" ) ) == NULL ) continue;
  1001.         sscanf( p + 2, "%f", &G.gps_loc[3] ); /* heading */
  1002.         if( ( p = strstr( line, "A=" ) ) == NULL ) continue;
  1003.         sscanf( p + 2, "%f", &G.gps_loc[4] ); /* altitude */
  1004.         fputs( line, G.f_gps );
  1005.         G.save_gps = 1;
  1006.         write( G.gc_pipe[1], G.gps_loc, sizeof( float ) * 5 );
  1007.         kill( getppid(), SIGUSR2 );
  1008.     }
  1009. }
  1010. void sighandler( int signum )
  1011. {
  1012.     signal( signum, sighandler );
  1013.     if( signum == SIGUSR1 )
  1014.         read( G.ch_pipe[0], &G.channel, sizeof( int ) );
  1015.     if( signum == SIGUSR2 )
  1016.         read( G.gc_pipe[0], &G.gps_loc, sizeof( float ) * 5 );
  1017.     if( signum == SIGINT || signum == SIGTERM )
  1018.     {
  1019.         alarm( 1 );
  1020.         G.do_exit = 1;
  1021.         signal( SIGALRM, sighandler );
  1022.         printf( "n" );
  1023.     }
  1024.     if( signum == SIGSEGV )
  1025.     {
  1026.         fprintf( stderr, "Caught signal 11 (SIGSEGV). Please"
  1027.                          " contact the author!33[?25hnn" );
  1028.         fflush( stdout );
  1029.         exit( 1 );
  1030.     }
  1031.     if( signum == SIGALRM )
  1032.     {
  1033.         fprintf( stderr, "Caught signal 14 (SIGALRM). Please"
  1034.                          " contact the author!33[?25hnn" );
  1035.         fflush( stdout );
  1036.         exit( 1 );
  1037.     }
  1038.     if( signum == SIGCHLD )
  1039.         wait( NULL );
  1040.     if( signum == SIGWINCH )
  1041.     {
  1042.         fprintf( stderr, "33[2J" );
  1043.         fflush( stdout );
  1044.     }
  1045. }
  1046. int disable_wep_key( char *interface, int fd_raw )
  1047. {
  1048.     struct iwreq wrq;
  1049.     memset( &wrq, 0, sizeof( struct iwreq ) );
  1050.     strncpy( wrq.ifr_name, interface, IFNAMSIZ );
  1051.     wrq.u.data.flags = IW_ENCODE_DISABLED | IW_ENCODE_NOKEY;
  1052.     return( ioctl( fd_raw, SIOCSIWENCODE, &wrq ) != 0 );
  1053. }
  1054. int set_channel( char *interface, int fd_raw, int channel )
  1055. {
  1056.     char s[32];
  1057.     int pid, status;
  1058.     struct iwreq wrq;
  1059.     if( G.is_wlanng )
  1060.     {
  1061.         memset( s, 0, sizeof( s ) );
  1062.         snprintf( s,  sizeof( s ) - 1, "channel=%d", channel );
  1063.         if( ( pid = fork() ) == 0 )
  1064.         {
  1065.             close( 0 ); close( 1 ); close( 2 ); chdir( "/" );
  1066.             execlp( "wlanctl-ng", "wlanctl-ng", interface,
  1067.                     "lnxreq_wlansniff", s, NULL );
  1068.             exit( 1 );
  1069.         }
  1070.         waitpid( pid, &status, 0 );
  1071.         if( WIFEXITED(status) )
  1072.             return( WEXITSTATUS(status) );
  1073.         else
  1074.             return( 1 );
  1075.     }
  1076.     if( G.is_orinoco )
  1077.     {
  1078.         memset( s, 0, sizeof( s ) );
  1079.         snprintf( s,  sizeof( s ) - 1, "%d", channel );
  1080.         if( ( pid = fork() ) == 0 )
  1081.         {
  1082.             close( 0 ); close( 1 ); close( 2 ); chdir( "/" );
  1083.             execlp( "iwpriv", "iwpriv", interface,
  1084.                     "monitor", "1", s, NULL );
  1085.             exit( 1 );
  1086.         }
  1087.         waitpid( pid, &status, 0 );
  1088.     }
  1089.     memset( &wrq, 0, sizeof( struct iwreq ) );
  1090.     strncpy( wrq.ifr_name, interface, IFNAMSIZ );
  1091.     wrq.u.freq.m = (double) channel;
  1092.     wrq.u.freq.e = (double) 0;
  1093.     if( ioctl( fd_raw, SIOCSIWFREQ, &wrq ) < 0 )
  1094.     {
  1095.         usleep( 10000 ); /* madwifi needs a second chance */
  1096.         if( ioctl( fd_raw, SIOCSIWFREQ, &wrq ) < 0 )
  1097.         {
  1098. /*          perror( "ioctl(SIOCSIWFREQ) failed" ); */
  1099.             return( 1 );
  1100.         }
  1101.     }
  1102.     return( 0 );
  1103. }
  1104. int set_monitor( char *interface, int fd_raw )
  1105. {
  1106.     int pid, status;
  1107.     struct iwreq wrq;
  1108.     if( G.is_wlanng )
  1109.     {
  1110.         if( ( pid = fork() ) == 0 )
  1111.         {
  1112.             close( 0 ); close( 1 ); close( 2 ); chdir( "/" );
  1113.             execlp( "wlanctl-ng", "wlanctl-ng", interface,
  1114.                     "lnxreq_wlansniff", "enable=true",
  1115.                     "prismheader=true", "wlanheader=false",
  1116.                     "stripfcs=true", "keepwepflags=true", NULL );
  1117.             exit( 1 );
  1118.         }
  1119.         waitpid( pid, &status, 0 );
  1120.         if( WIFEXITED(status) )
  1121.             return( WEXITSTATUS(status) );
  1122.         else
  1123.             return( 1 );
  1124.     }
  1125.     memset( &wrq, 0, sizeof( struct iwreq ) );
  1126.     strncpy( wrq.ifr_name, interface, IFNAMSIZ );
  1127.     wrq.u.mode = IW_MODE_MONITOR;
  1128.     if( ioctl( fd_raw, SIOCSIWMODE, &wrq ) < 0 )
  1129.     {
  1130.         perror( "ioctl(SIOCSIWMODE) failed" );
  1131.         return( 1 );
  1132.     }
  1133.     set_channel( interface, fd_raw, 10 );
  1134.     return( 0 );
  1135. }
  1136. void channel_hopper( char *interface, int fd_raw )
  1137. {
  1138.     int ch, ch_idx = 0;
  1139.     while( getppid() != 1 )
  1140.     {
  1141.         ch_idx++;
  1142.         if( bg_chans[ch_idx] ==  0 )
  1143.             ch_idx = 0;
  1144.         if( bg_chans[ch_idx] == -1 ) 
  1145.         {
  1146.             usleep( 10000 );
  1147.             continue;
  1148.         }
  1149.         ch = bg_chans[ch_idx];
  1150.         if( set_channel( interface, fd_raw, ch ) == 0 )
  1151.         {
  1152.             write( G.ch_pipe[1], &ch, sizeof( int ) );
  1153.             kill( getppid(), SIGUSR1 );
  1154.             usleep( 350000 );
  1155.         }
  1156.         else
  1157.             bg_chans[ch_idx] = -1;      /* remove invalid channel */
  1158.     }
  1159.     exit( 0 );
  1160. }
  1161. char usage[] =
  1162. "n"
  1163. "  airodump %d.%d - (C) 2004,2005 Christophe Devinen"
  1164. "n"
  1165. "  usage: airodump <interface> <output prefix> [channel] [IVs flag]n"
  1166. "n"
  1167. "  Specify 0 as the channel to hop between 2.4 GHz channels.n"
  1168. "  Set the optional IVs flag to 1 to only save the capturedn"
  1169. "  IVs - the resulting file is only useful for WEP cracking.n"
  1170. "n"
  1171. "  If the gpsd daemon is running, airodump will retrieve andn"
  1172. "  save the current GPS coordinates in text format.n"
  1173. "n";
  1174. int main( int argc, char *argv[] )
  1175. {
  1176.     long time_slept;
  1177.     int n, caplen, pid;
  1178.     int fd_raw, arptype;
  1179.     int ivs_only, power;
  1180.     time_t tt1, tt2, tt3;
  1181.     unsigned char *buffer;
  1182.     unsigned char *h80211;
  1183.     struct ifreq ifr;
  1184.     struct packet_mreq mr;
  1185.     struct sockaddr_ll sll;
  1186.     struct timeval tv0;
  1187.     struct timeval tv1;
  1188.     struct timeval tv2;
  1189.     struct winsize ws;
  1190.     fd_set rfds;
  1191.     /* initialize a bunch of variables */
  1192.     memset( &G, 0, sizeof( G ) );
  1193.     ivs_only    =  0;
  1194.     power       = -1;
  1195.     fd_raw      = -1;
  1196.     arptype     =  0;
  1197.     time_slept  =  0;
  1198.     /* check the arguments */
  1199.     if( argc < 3 || argc > 5 )
  1200.     {
  1201.         printf( usage, _MAJ, _MIN );
  1202.         return( 1 );
  1203.     }
  1204.     if( argc > 3 )
  1205.         G.channel = atoi( argv[3] );
  1206.     if( argc > 4 )
  1207.         ivs_only  = atoi( argv[4] );
  1208.     /* create the raw socket and drop privileges */
  1209.     fd_raw = socket( PF_PACKET, SOCK_RAW, htons( ETH_P_ALL ) );
  1210.     if( fd_raw < 0 )
  1211.     {
  1212.         perror( "socket(PF_PACKET) failed" );
  1213.         fprintf( stderr, "This program requires root privileges.n" );
  1214.         return( 1 );
  1215.     }
  1216.     setuid( getuid() );
  1217.     /* reserve the buffer space */
  1218.     if( ( buffer = (unsigned char *) malloc( 65536 ) ) == NULL )
  1219.     {
  1220.         perror( "malloc failed" );
  1221.         return( 1 );
  1222.     }
  1223.     /* find the interface index */
  1224.     memset( &ifr, 0, sizeof( ifr ) );
  1225.     strncpy( ifr.ifr_name, argv[1], sizeof( ifr.ifr_name ) - 1 );
  1226.     if( ioctl( fd_raw, SIOCGIFINDEX, &ifr ) < 0 )
  1227.     {
  1228.         fprintf( stderr, "%s is not a network interface.n", argv[1] );
  1229.         return( 1 );
  1230.     }
  1231.     memset( &sll, 0, sizeof( sll ) );
  1232.     sll.sll_family   = AF_PACKET;
  1233.     sll.sll_ifindex  = ifr.ifr_ifindex;
  1234.     sll.sll_protocol = htons( ETH_P_ALL );
  1235.     if( memcmp( argv[1], "wlan", 4 ) == 0 )
  1236.     {
  1237.         if( ( pid = fork() ) == 0 )     /* wlan-ng brain damage */
  1238.         {
  1239.             close( 0 ); close( 1 ); close( 2 ); chdir( "/" );
  1240.             execlp( "wlanctl-ng", "wlanctl-ng", argv[1],
  1241.                     "lnxreq_ifstate", "ifstate=enable", NULL );
  1242.             exit( 1 );
  1243.         }
  1244.         waitpid( pid, &n, 0 );
  1245.         if( WIFEXITED(n) && WEXITSTATUS(n) == 0 )
  1246.             G.is_wlanng = 1;
  1247.         if( ! fork() )                  /* hostap card reset */
  1248.         {
  1249.             close( 0 ); close( 1 ); close( 2 ); chdir( "/" );
  1250.             execlp( "iwpriv", "iwpriv", argv[1], "reset", "1", NULL );
  1251.             exit( 1 );
  1252.         }
  1253.         wait( NULL );
  1254.     }
  1255.     /* test if orinoco */
  1256.     if( memcmp( argv[1], "eth", 3 ) == 0 )
  1257.     {
  1258.         if( ( pid = fork() ) == 0 )
  1259.         {
  1260.             close( 0 ); close( 1 ); close( 2 ); chdir( "/" );
  1261.             execlp( "iwpriv", "iwpriv", argv[1], "get_port3", NULL );
  1262.             exit( 1 );
  1263.         }
  1264.         waitpid( pid, &n, 0 );
  1265.         if( WIFEXITED(n) && WEXITSTATUS(n) == 0 )
  1266.             G.is_orinoco = 1;
  1267.     }
  1268.     /* make sure the interface is up */
  1269.     ifr.ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;        
  1270.     if( ioctl( fd_raw, SIOCSIFFLAGS, &ifr ) < 0 )
  1271.     {
  1272.         perror( "ioctl(SIOCSIFFLAGS) failed" );
  1273.         return( 1 );
  1274.     }
  1275.     set_monitor( argv[1], fd_raw );
  1276.     /* bind the raw socket to the interface */
  1277.     if( bind( fd_raw, (struct sockaddr *) &sll,
  1278.               sizeof( sll ) ) < 0 )
  1279.     {
  1280.         perror( "bind(ETH_P_ALL) failed" );
  1281.         return( 1 );
  1282.     }
  1283.     /* couple of iwprivs to enable the prism header */
  1284.     if( ! fork() )  /* hostap */
  1285.     {
  1286.         close( 0 ); close( 1 ); close( 2 ); chdir( "/" );
  1287.         execlp( "iwpriv", "iwpriv", argv[1], "monitor_type", "1", NULL );
  1288.         exit( 1 );
  1289.     }
  1290.     wait( NULL );
  1291.     if( ! fork() )  /* r8180 */
  1292.     {
  1293.         close( 0 ); close( 1 ); close( 2 ); chdir( "/" );
  1294.         execlp( "iwpriv", "iwpriv", argv[1], "prismhdr", "1", NULL );
  1295.         exit( 1 );
  1296.     }
  1297.     wait( NULL );
  1298.     if( ! fork() )  /* prism54 */
  1299.     {
  1300.         close( 0 ); close( 1 ); close( 2 ); chdir( "/" );
  1301.         execlp( "iwpriv", "iwpriv", argv[1], "set_prismhdr", "1", NULL );
  1302.         exit( 1 );
  1303.     }
  1304.     wait( NULL );
  1305.     /* make sure the WEP key is off */
  1306.     disable_wep_key( argv[1], fd_raw );
  1307.     /* start a child to hop between channels */
  1308.     if( G.channel == 0 )
  1309.     {
  1310.         pipe( G.ch_pipe );
  1311.         signal( SIGUSR1, sighandler );
  1312.         if( ! fork() )
  1313.         {
  1314.             channel_hopper( argv[1], fd_raw );
  1315.             exit( 1 );
  1316.         }
  1317.     }
  1318.     else
  1319.         set_channel( argv[1], fd_raw, G.channel );
  1320.     /* start the GPS tracker */
  1321.     pipe( G.gc_pipe );
  1322.     signal( SIGUSR2, sighandler );
  1323.     if( ! fork() )
  1324.     {
  1325.         gps_tracker();
  1326.         exit( 1 );
  1327.     }
  1328.     usleep( 50000 );
  1329.     waitpid( -1, NULL, WNOHANG );
  1330.     /* lookup the hardware type */
  1331.     if( ioctl( fd_raw, SIOCGIFHWADDR, &ifr ) < 0 )
  1332.     {
  1333.         perror( "ioctl(SIOCGIFHWADDR) failed" );
  1334.         return( 1 );
  1335.     }
  1336.     arptype = ifr.ifr_hwaddr.sa_family;
  1337.     if( arptype != ARPHRD_IEEE80211 &&
  1338.         arptype != ARPHRD_IEEE80211_PRISM &&
  1339.         arptype != ARPHRD_IEEE80211_FULL )
  1340.     {
  1341.         if( arptype == 1 )
  1342.             fprintf( stderr, "nARP linktype is set to 1 (Ethernet) " );
  1343.         else
  1344.             fprintf( stderr, "nUnsupported hardware link type %4d ",
  1345.                      arptype );
  1346.         fprintf( stderr, "- expected ARPHRD_IEEE80211nor ARPHRD_IEEE8021"
  1347.                          "1_PRISM instead.  Make sure RFMON is enabled:n"
  1348.                          "run 'ifconfig %s up; iwconfig %s mode Monitor "
  1349.                          "channel <#>'nn", argv[1], argv[1] );
  1350.         return( 1 );
  1351.     }
  1352.     /* enable promiscuous mode */
  1353.     memset( &mr, 0, sizeof( mr ) );
  1354.     mr.mr_ifindex = sll.sll_ifindex;
  1355.     mr.mr_type    = PACKET_MR_PROMISC;
  1356.     if( setsockopt( fd_raw, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
  1357.                     &mr, sizeof( mr ) ) < 0 )
  1358.     {
  1359.         perror( "setsockopt(PACKET_MR_PROMISC) failed" );
  1360.         return( 1 );
  1361.     }
  1362.     /* open or create the output files */
  1363.     if( dump_initialize( argv[2], ivs_only ) )
  1364.         return( 1 );
  1365.     signal( SIGINT,   sighandler );
  1366.     signal( SIGSEGV,  sighandler );
  1367.     signal( SIGTERM,  sighandler );
  1368.     signal( SIGWINCH, sighandler );
  1369.     sighandler( SIGWINCH );
  1370.     fprintf( stderr, "33[?25l33[2Jn" );
  1371.     update_battery();
  1372.     tt1 = time( NULL );
  1373.     tt2 = time( NULL );
  1374.     tt3 = time( NULL );
  1375.     while( 1 )
  1376.     {
  1377.         if( G.do_exit ) break;
  1378.         if( time( NULL ) - tt1 >= 20 )
  1379.         {
  1380.             /* update the csv stats file */
  1381.             tt1 = time( NULL );
  1382.             dump_write_csv();
  1383.             /* sort the APs by power */
  1384.             dump_sort_power();
  1385.         }
  1386.         if( time( NULL ) - tt2 > 3 )
  1387.         {
  1388.             /* update the battery state */
  1389.             tt2 = time( NULL );
  1390.             update_battery();
  1391.             /* flush the output files */
  1392.             if( G.f_cap != NULL ) fflush( G.f_cap );
  1393.             if( G.f_ivs != NULL ) fflush( G.f_ivs );
  1394.         }
  1395.         /* capture one packet */
  1396.         FD_ZERO( &rfds );
  1397.         FD_SET( fd_raw, &rfds );
  1398.         tv0.tv_sec  = 0;
  1399.         tv0.tv_usec = REFRESH_RATE;
  1400.         gettimeofday( &tv1, NULL );
  1401.         if( select( fd_raw + 1, &rfds, NULL, NULL, &tv0 ) < 0 )
  1402.         {
  1403.             if( errno == EINTR ) continue;
  1404.             perror( "select failed" );
  1405.             return( 1 );
  1406.         }
  1407.         gettimeofday( &tv2, NULL );
  1408.         time_slept += 1000000 * ( tv2.tv_sec  - tv1.tv_sec  )
  1409.                               + ( tv2.tv_usec - tv1.tv_usec );
  1410.         if( time_slept > REFRESH_RATE )
  1411.         {
  1412.             time_slept = 0;
  1413.             /* update the window size */
  1414.             if( ioctl( 0, TIOCGWINSZ, &ws ) < 0 )
  1415.             {
  1416.                 ws.ws_row = 25;
  1417.                 ws.ws_col = 80;
  1418.             }
  1419.             if( ws.ws_col <   1 ) ws.ws_col =   1;
  1420.             if( ws.ws_col > 300 ) ws.ws_col = 300;
  1421.             /* display the list of access points we have */
  1422.             fprintf( stderr, "33[1;1H" );
  1423.             dump_print( ws.ws_row, ws.ws_col );
  1424.             fprintf( stderr, "33[J" );
  1425.             fflush( stdout );
  1426.             continue;
  1427.         }
  1428.         if( ! FD_ISSET( fd_raw, &rfds ) )
  1429.             continue;
  1430.         /* one packet available for reading */
  1431.         memset( buffer, 0, 4096 );
  1432.         if( ( caplen = read( fd_raw, buffer, 65535 ) ) < 0 )
  1433.         {
  1434.             perror( "read failed" );
  1435.             return( 1 );
  1436.         }
  1437.         /* if device is an atheros, remove the FCS */
  1438.         if( ! memcmp( argv[1], "ath", 3 ) )
  1439.             caplen -= 4;
  1440.         /* prism (wlan-ng) header parsing */
  1441.         h80211 = buffer;
  1442.         if( arptype == ARPHRD_IEEE80211_PRISM )
  1443.         {
  1444.             if( buffer[7] == 0x40 )
  1445.             {
  1446.                 /* prism54 uses a different format */
  1447.                 power = buffer[0x33];
  1448.                 n = 0x40;
  1449.             }
  1450.             else
  1451.             {
  1452.                 power = *(int *)( buffer + 0x5C );
  1453.                 if( ! memcmp( argv[1], "ath", 3 ) )
  1454.                     power -= *(int *)( buffer + 0x68 );
  1455.                 n = *(int *)( buffer + 4 );
  1456.             }
  1457.             if( n <= 0 || n >= caplen )
  1458.                 continue;
  1459.             h80211 += n;
  1460.             caplen -= n;
  1461.         }
  1462.         /* radiotap header parsing */
  1463.         if( arptype == ARPHRD_IEEE80211_FULL )
  1464.         {
  1465.             if( buffer[0] != 0 )
  1466.             {
  1467.                 fprintf( stderr, "Wrong radiotap header version.n" );
  1468.                 return( 1 );
  1469.             }
  1470.             n = *(unsigned short *)( buffer + 2 );
  1471.             if( *(int *)( buffer + 4 ) == 0x0000082E )
  1472.                 power = buffer[14];     /* ipw2200 1.0.7 */
  1473.             if( n <= 0 || n >= caplen )
  1474.                 continue;
  1475.             h80211 += n;
  1476.             caplen -= n;
  1477.         }
  1478.         dump_add_packet( h80211, caplen, power );
  1479.     }
  1480.     dump_write_csv();
  1481.     if( G.f_txt != NULL ) fclose( G.f_txt );
  1482.     if( G.f_gps != NULL ) fclose( G.f_gps );
  1483.     if( G.f_cap != NULL ) fclose( G.f_cap );
  1484.     if( G.f_ivs != NULL ) fclose( G.f_ivs );
  1485.     if( ! G.save_gps )
  1486.     {
  1487.         sprintf( (char *) buffer, "%s-%02d.gps", argv[2], G.f_index );
  1488.         unlink(  (char *) buffer );
  1489.     }
  1490.     fprintf( stderr, "33[?25h" );
  1491.     fflush( stdout );
  1492.     return( 0 );
  1493. }