Advertisement
DanFloyd

Wifi Sniffer Tool

Aug 9th, 2015
221
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 29.42 KB | None | 0 0
  1. /* THIS IS ALSO AVAILABLE ON GITHUB - SEARCH FOR WIFIMON PROJECT OR EMAIL ME */
  2.  
  3. /* WIFIMON - wifi monitor, analyzer, utility tool                                               */
  4. /* Authors: Daniele Paolini  -> daniele.paolini@hotmail.it                                      */
  5. /*          Lorenzo Vannucci -> ucci.dibuti@gmail.com                                           */
  6. /*          Marco Venturini  -> alexander00@hotmail.it                                          */
  7. /* To compile: gcc wifimon.c -o wifimon -lpcap -Wall -pedantic                                  */
  8. /* Run as root! Please set your network device in monitor mode!                                 */
  9. /*                                                                                              */
  10. /* This code is distributed under the GPL License. For more info check:                         */
  11. /* http://www.gnu.org/copyleft/gpl.html                                                         */
  12.  
  13. #include <pcap.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18. #include <arpa/inet.h>
  19. #include <time.h>
  20. #include <sys/time.h>
  21. #include <ctype.h>
  22. #include <netinet/ether.h>
  23. #include <signal.h>
  24. #include <float.h>
  25.  
  26. #define FILTER "type mgt subtype beacon"      /*beacon frame filter*/
  27.  
  28. /* TYPE DEFINITIONS */
  29. typedef struct _access_point{
  30.   unsigned char        *mac_address;          /*mac address of the ap*/
  31.   float                ssi_signal_temp_sum,   /*temporary signals sum*/
  32.                        data_rate_temp_sum,    /*temporary rates sum*/
  33.                        data_rate_min,         /*minimum data rate*/
  34.                        data_rate_max,         /*maximum data rate*/
  35.                        data_rate_sum,         /*data rates sum*/
  36.                        ssi_signal_min,        /*minimum ssi signal*/
  37.                        ssi_signal_sum,        /*signals sum*/
  38.                        ssi_signal_max,        /*maximum ssi signal*/
  39.                        tap_counter_temp;
  40.   time_t               data_rate_min_ts,      /*arrival time of minimum data rate*/
  41.                        data_rate_max_ts,      /*arrival time of maximum data rate*/
  42.                        ssi_signal_max_ts,     /*arrival time of maximum ssi signal*/
  43.                        ssi_signal_min_ts;     /*arrival time of minimum ssi signal*/
  44.   int                  tap_counter,           /*tap counter*/
  45.                        channel;               /*channel*/
  46.   struct _access_point *next;                 /*pointer at next element in list*/
  47. } access_point;                               /*stores all info about an access point*/
  48.  
  49. typedef struct _ssid{
  50.   char*        ssid_name;
  51.   int          num_ap;
  52.   access_point *list_ap;
  53.   struct _ssid *next;                         /*stores all info about a ssid*/
  54. } ssid;
  55.  
  56. /* GLOBAL VARIABLES */
  57. pcap_t                       *descr;          /*pcap handler descriptor*/
  58. static volatile sig_atomic_t signal_flag;     /*represent incoming SIGINT signal*/
  59. static int                   packet_count;    /*pkt info*/
  60. int                          ssid_len,        /*pkt info*/
  61.                              live,            /*if it's set, live mode will be activated*/
  62.                              json_flag,       /*if it's set, json report will be written*/
  63.                              write_log;       /*if it's set, a log file will be written*/
  64.  
  65. u_int16_t                    radiotap_len;    /*pkt info*/
  66. int8_t                       ssi_signal;      /*pkt info*/
  67. float                        data_rate;       /*pkt info*/
  68. time_t                       in_time;         /*used for managing timestamp*/
  69. struct tm                    *time_now;       /*used for managing timestamp*/
  70. char                         tmbuf[64],       /*used for managing timestamp*/
  71.                              buf[64];         /*used for managing timestamp*/
  72. FILE                         *out,            /*output file descriptor*/
  73.                              *json;           /*json report file descriptor*/
  74. ssid                         *ssid_list;      /*list of ssid*/
  75.  
  76. /* FUNCTIONS DEFINITION - see implementation below the main function */
  77. static void          print_usage();
  78. static void          print_help();
  79. static void          packet_callback(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
  80. static void          sigint_handler();
  81. static ssid*         add_ssid(char* name, ssid *list);
  82. static ssid*         search_ssid(char* name, ssid *list);
  83. static access_point* add_ap(unsigned char* mac, access_point* list);
  84. static access_point* search_ap(unsigned char* mac, access_point* list);
  85. static void          update(float signal, float rate, time_t ts, int channel, access_point* ap);
  86. static int           mac_compare(unsigned char* a, unsigned char* b);
  87. static void          print_mac(unsigned char* data, FILE* file_desc);
  88. int                  select_channel(u_int16_t frequency);
  89.  
  90. /* MAIN FUNCTION */
  91. int main(int argc, char* argv[]){
  92.  
  93.   int                opt;
  94.  
  95.   char               *output_file = NULL,
  96.                      *input_file = NULL,
  97.                      *device = NULL;
  98.   char               error_buffer[PCAP_ERRBUF_SIZE];
  99.   const u_char       *packet;
  100.  
  101.   pcap_if_t          *devpointer = NULL;
  102.   bpf_u_int32        mask;                     /*my net mask*/
  103.   bpf_u_int32        net;                          /*my ip address*/
  104.   struct in_addr     address;
  105.   struct bpf_program compiled_filter;
  106.   struct pcap_pkthdr *header;
  107.  
  108.   struct sigaction   sigint_action;            /* struct for signal registration */
  109.   sigset_t           new_set,                  /* signal mask */
  110.                      old_set;                  /* signal mask */
  111.   ssid               *ssid_iterator;
  112.   access_point       *ap_iterator;
  113.   struct tm *time_now;
  114.   char tmbuf[64], buf1[64], buf2[64], buf3[64], buf4[64];
  115.  
  116.   memset(error_buffer, 0, PCAP_ERRBUF_SIZE);
  117.  
  118.   (void)header; /*get rid of the 'unused variable warning' superfluous in this case*/
  119.   (void)packet; /*get rid of the 'unused variable warning' superfluous in this case*/
  120.  
  121.   packet_count = 0;
  122.   signal_flag = 0;
  123.   write_log = 0;
  124.   live = 0;
  125.   descr = NULL;
  126.   ssid_list = NULL;
  127.  
  128.   /* parsing command line */
  129.   while((opt=getopt(argc, argv, "jhl:do:i:")) != -1){
  130.     switch(opt){
  131.       case 'h': /* printing help message */
  132.                 print_help(argv[0]);
  133.                 return(EXIT_SUCCESS);
  134.                 break;
  135.       case 'd': /* printing all availables devices */
  136.                 if(pcap_findalldevs(&devpointer, error_buffer) == 0) {
  137.                   int i = 0;
  138.                   fprintf(stdout,"Available devices:\n");
  139.                   while(devpointer) {
  140.                     printf(" %d. %s\n", i++, devpointer->name);
  141.                     devpointer = devpointer->next;
  142.                   }
  143.                 }
  144.                 fprintf(stdout,"\n\n\n");
  145.                 return(EXIT_FAILURE);
  146.       case 'o': /* saving a log file - parameter needed */
  147.                 output_file = malloc((strlen(optarg) + 1)*sizeof(*output_file));
  148.                 if(output_file== NULL){
  149.                   fprintf(stderr,"SEVERE ERROR: memory allocation fail\n");
  150.                   return(EXIT_FAILURE);
  151.                 }
  152.                 snprintf(output_file,strlen(optarg) + 1,"%s",optarg);
  153.                 write_log = 1;
  154.                 break;
  155.       case 'i': /* reading an input file - parameter needed */
  156.                 input_file = malloc((strlen(optarg) + 1)*sizeof(*input_file));
  157.                 if(input_file == NULL){
  158.                   fprintf(stderr,"SEVERE ERROR: memory allocation fail\n");
  159.                   return(EXIT_FAILURE);
  160.                 }
  161.                 snprintf(input_file,strlen(optarg) + 1,"%s",optarg);
  162.                 break;
  163.       case 'l': /* reading the device name - parameter needed */
  164.                 live = 1;
  165.                 device = malloc((strlen(optarg) + 1)*sizeof(*device));
  166.                 if(device == NULL){
  167.                   fprintf(stderr,"SEVERE ERROR: memory allocation fail\n");
  168.                   return(EXIT_FAILURE);
  169.                 }
  170.                 snprintf(device,strlen(optarg) + 1,"%s",optarg);
  171.                 break;
  172.       case 'j': /* json report */
  173.                 json_flag = 1;
  174.                 json = fopen("report.json","w");
  175.                 break;
  176.       default:  /* wrong option management */
  177.                 print_help(argv[0]);
  178.                 return(EXIT_FAILURE);
  179.     }
  180.   }
  181.  
  182.   /* checking parameter */
  183.   if(write_log){
  184.     /* write log file option */
  185.     if(output_file == NULL){
  186.       fprintf(stderr,"ERROR: You must select an output file\n");
  187.       print_help(argv[0]);
  188.       return(EXIT_FAILURE);
  189.     }
  190.  
  191.     if(access(output_file, F_OK | W_OK | X_OK) == -1){
  192.       fprintf(stderr,"ERROR: You must select a valid output file\n");
  193.       print_help(argv[0]);
  194.       return(EXIT_FAILURE);
  195.     }
  196.     out = fopen(output_file,"w");
  197.   }
  198.  
  199.   fprintf(stdout,"\nWIFIMON - wifi monitoring tool\n\n");
  200.   fprintf(stdout,"  @  This software will scan the air to monitor all the access points near to you");
  201.   fprintf(stdout," and display relevant info about them.\n");
  202.   fprintf(stdout,"  @  This open source software is released under GPL licence and provided without any warranty.\n");
  203.   fprintf(stdout,"  @  The sniffed packets will not be analyzed to infringe your privacy.\n");
  204.   fprintf(stdout,"  @  Use and modify at your own risk.\n\n\n");
  205.  
  206.   if(live){
  207.  
  208.     /* setting signal mask */
  209.     if(sigfillset(&new_set) == -1){
  210.        perror("ERROR: Cannot set signal mask, ");
  211.          return(EXIT_FAILURE);
  212.     }
  213.  
  214.     /* masking all signals during SIGINT handler installation */
  215.     if(sigprocmask(SIG_SETMASK, &new_set, &old_set) == -1){
  216.       perror("ERROR: Cannot set process's signal mask, ");
  217.         return(EXIT_FAILURE);
  218.     }
  219.  
  220.     /* registering SIGINT handler */
  221.     memset(&sigint_action,'\0',sizeof(sigint_action));
  222.     sigint_action.sa_handler = &sigint_handler;
  223.     sigint_action.sa_flags = SA_RESTART;
  224.     if(sigaction(SIGINT, &sigint_action, NULL) == -1){
  225.       perror("ERROR: Cannot install handler for [SIGINT], ");
  226.       return(EXIT_FAILURE);
  227.     }
  228.  
  229.     /* unmasking signals */
  230.     if(sigprocmask(SIG_SETMASK, &old_set, NULL) == -1){
  231.       perror("ERROR: Cannot restore process's signal mask, ");
  232.       return(EXIT_FAILURE);
  233.     }
  234.  
  235.     /* live mode ON */
  236.     fprintf(stdout,"Live capture mode: ON\n");
  237.  
  238.     /* checking parameter */
  239.     if(device == NULL){
  240.       fprintf(stderr,"ERROR: You must select a device file in order to work offline\n");
  241.       fprintf(stderr,"NOTE: Use -d option as root to see the list of all available devices\n");
  242.       print_usage(argv[0]);
  243.       return(EXIT_FAILURE);
  244.     }
  245.  
  246.     /* looking up for my netmask and my ip address */
  247.     if (pcap_lookupnet(device, &net, &mask, error_buffer) == -1) {
  248.       fprintf(stderr, "ERROR: Can't get netmask for device %s\n", device);
  249.           net = 0;
  250.           mask = 0;
  251.       return(EXIT_FAILURE);
  252.       }
  253.  
  254.     /* printing info */
  255.     address.s_addr = mask;
  256.     fprintf(stdout,"Monitor Mask: %s\n",inet_ntoa(address));
  257.     address.s_addr = net;
  258.     fprintf(stdout,"Monitor IP: %s\n\n",inet_ntoa(address));
  259.  
  260.     /* opening device in promiscuos mode with 1 second timeout - BUFSIZ is in pcap.h */
  261.     if((descr = pcap_open_live(device, BUFSIZ, 1, 1000, error_buffer)) == NULL){
  262.       fprintf(stderr, "ERROR: %s\n", error_buffer);
  263.       return(EXIT_FAILURE);
  264.     }
  265.  
  266.     /* setting beacon filter */
  267.     if (pcap_compile(descr, &compiled_filter, FILTER, 1, net) == -1) {
  268.       fprintf(stderr, "ERROR: Couldn't parse filter %s: %s\n", FILTER, pcap_geterr(descr));
  269.       return(EXIT_FAILURE);
  270.     }
  271.  
  272.     /* applying beacon filter */
  273.     if (pcap_setfilter(descr, &compiled_filter) == -1) {
  274.       fprintf(stderr, "ERROR: Couldn't apply filter %s: %s\n", FILTER, pcap_geterr(descr));
  275.       return(EXIT_FAILURE);
  276.     }
  277.  
  278.     fprintf(stdout, "Monitoring in progress...\n\n");
  279.     fprintf(stdout, "Press [ctrl+c] or send [SIGINT] to this process [pid:%d] to exit and ",getpid());
  280.     fprintf(stdout,"display statistics\n\n");
  281.  
  282.     /* pcap loop */
  283.     if (pcap_loop(descr, -1, packet_callback, NULL) == -1){
  284.       fprintf(stderr, "ERROR: Pcap loop error: %s\n", pcap_geterr(descr));
  285.     }
  286.  
  287.     /* freeing the heap */
  288.     free(device);
  289.  
  290.   } else{
  291.  
  292.     /* live mode OFF */
  293.     fprintf(stdout,"Live capture mode: OFF\n");
  294.  
  295.     /* checking parameter */
  296.     if(input_file == NULL){
  297.       fprintf(stderr,"ERROR: You must select an input file in order to work offline\n");
  298.       print_usage(argv[0]);
  299.       return(EXIT_FAILURE);
  300.     }
  301.  
  302.     /* opening pcap file */
  303.     if((descr = pcap_open_offline(input_file, error_buffer)) == NULL){
  304.       fprintf(stderr, "ERROR: %s\n", error_buffer);
  305.       return(EXIT_FAILURE);
  306.     }
  307.  
  308.     /* setting beacon filter */
  309.     if (pcap_compile(descr, &compiled_filter, FILTER, 1, net) == -1) {
  310.       fprintf(stderr, "ERROR: Couldn't parse filter %s: %s\n", FILTER, pcap_geterr(descr));
  311.     return(EXIT_FAILURE);
  312.     }
  313.  
  314.     /* applying beacon filter */
  315.     if (pcap_setfilter(descr, &compiled_filter) == -1) {
  316.       fprintf(stderr, "ERROR: Couldn't apply filter %s: %s\n", FILTER, pcap_geterr(descr));
  317.     return(EXIT_FAILURE);
  318.     }
  319.  
  320.     /* reading packets in the pcap file */
  321.     if (pcap_loop(descr, -1, packet_callback, NULL) < 0){
  322.       fprintf(stderr, "ERROR: Pcap loop error: %s\n", pcap_geterr(descr));
  323.     }
  324.  
  325.     /* freeing the heap */
  326.     free(input_file);
  327.  
  328.   }
  329.  
  330.   /*printing final statistics*/
  331.   fprintf(stdout,"\n\nFinal statistics:\n");
  332.   ssid_iterator = ssid_list;
  333.   while(ssid_iterator != NULL){
  334.     fprintf(stdout,"[SSID] name: %s / number of access points: %d\n",ssid_iterator->ssid_name,
  335.                                                                         ssid_iterator->num_ap);
  336.  
  337.     if(json_flag){
  338.       fprintf(json,"{ \"ssid\": {\n");
  339.       fprintf(json,"    \"name\": \"%s\",\n",ssid_iterator->ssid_name);
  340.       fprintf(json,"    \"number of access point\": \"%d\",\n",ssid_iterator->num_ap);
  341.       fprintf(json,"    \"aplist\": {\n");
  342.       fprintf(json,"    \"ap\": [\n");
  343.     }
  344.     ap_iterator = ssid_iterator->list_ap;
  345.     while(ap_iterator != NULL){
  346.       fprintf(stdout,"  [AP] mac:           ");
  347.       print_mac(ap_iterator->mac_address,stdout);
  348.       fprintf(stdout,"\n");
  349.       fprintf(stdout,"       data rate avg: %f Mbps\n", (float)(ap_iterator->data_rate_sum / (float)ap_iterator->tap_counter));
  350.       fprintf(stdout,"       signal avg:    %f Dbm\n", (float)(ap_iterator->ssi_signal_sum / (float)ap_iterator->tap_counter));
  351.       fprintf(stdout,"       channel:       %d\n",ap_iterator->channel);
  352.       fprintf(stdout,"       max data rate  %f Mbps\n",ap_iterator->data_rate_max);
  353.       time_now = localtime(&ap_iterator->data_rate_max_ts);
  354.       strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", time_now);
  355.       snprintf(buf1, sizeof(buf1), "%s", tmbuf);
  356.       fprintf(stdout,"         at time:     %s\n",buf1);
  357.       fprintf(stdout,"       min data rate  %f Mbps\n",ap_iterator->data_rate_min);
  358.       time_now = localtime(&ap_iterator->data_rate_min_ts);
  359.       strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", time_now);
  360.       snprintf(buf2, sizeof(buf2), "%s", tmbuf);
  361.       fprintf(stdout,"         at time:     %s\n",buf2);
  362.       fprintf(stdout,"       max ssi signal %f Dbm\n",ap_iterator->ssi_signal_max);
  363.       time_now = localtime(&ap_iterator->ssi_signal_max_ts);
  364.       strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", time_now);
  365.       snprintf(buf3, sizeof(buf3), "%s", tmbuf);
  366.       fprintf(stdout,"         at time:     %s\n",buf3);
  367.       fprintf(stdout,"       min ssi signal %f Dbm\n",ap_iterator->ssi_signal_min);
  368.       time_now = localtime(&ap_iterator->ssi_signal_min_ts);
  369.       strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", time_now);
  370.       snprintf(buf4, sizeof(buf4), "%s", tmbuf);
  371.       fprintf(stdout,"         at time:     %s\n",buf4);
  372.       if(json_flag){
  373.         fprintf(json,"          {\"mac\": \"");
  374.         print_mac(ap_iterator->mac_address,json);
  375.         fprintf(json,"\",\n          \"data rate\":\"%f\",\n          \"signal\": \"%f\",\n          \"channel\":\"%d\",\n          \"max data rate\": \"%f\",\n          \"max data rate time\": \"%s\",\n          \"min data rate\": \"%f\",\n          \"min data rate time\": \"%s\",\n          \"max signal\": \"%f\",\n          \"max signal time\": \"%s\",\n          \"min signal\": \"%f\",\n          \"min signal time\": \"%s\"},\n",
  376.                                 (float)(ap_iterator->data_rate_temp_sum / (float)ap_iterator->tap_counter_temp),
  377.                                 (float)(ap_iterator->ssi_signal_temp_sum / (float)ap_iterator->tap_counter_temp),
  378.                                 ap_iterator->channel,
  379.                                 ap_iterator->data_rate_max,
  380.                                 buf1,
  381.                                 ap_iterator->data_rate_min,
  382.                                 buf2,
  383.                                 ap_iterator->ssi_signal_max,
  384.                                 buf3,
  385.                                 ap_iterator->ssi_signal_min,
  386.                                 buf4
  387.                                 );
  388.       }
  389.       ap_iterator = ap_iterator->next;
  390.     }
  391.     fprintf(stdout,"\n");
  392.     if(json_flag)
  393.       fprintf(json,"\b          ]}\n     }\n}\n");
  394.     ssid_iterator = ssid_iterator->next;
  395.   }
  396.   fprintf(stdout,"\n\n");
  397.  
  398.  
  399.   /* closing pcap handler descriptor and freeing heap */
  400.   pcap_close(descr);
  401.   if(write_log){
  402.     free(output_file);
  403.     fclose(out);
  404.   }
  405.   if(json_flag)
  406.     fclose(json);
  407.   return(EXIT_SUCCESS);
  408. }
  409.  
  410. /* FUNCTIONS IMPLEMENTATION */
  411.  
  412. /* prints usage message*/
  413. static void print_usage(char* s){
  414.   fprintf(stdout,"Usage: %s [OPTIONS] [PARAMETERS]\n",s);
  415.   fprintf(stdout,"NOTE: in order to work properly you must run this program as root and your\nnetwork interface must");
  416.   fprintf(stdout," work in monitor mode.\n");
  417. }
  418.  
  419.  
  420. /* prints help message*/
  421. static void print_help(char* s){
  422.   print_usage(s);
  423.   fprintf(stdout,"Option list:\n  -l    live mode:    needs a parameter, capture packets directly from the\n");
  424.   fprintf(stdout,"                      network interface passed as a parameter\n");
  425.   fprintf(stdout,"  -d    device list:  display all network devices availables on this machine\n");
  426.   fprintf(stdout,"                      and exit\n");
  427.   fprintf(stdout,"  -i    input file:   needs a parameter, [mandatory] if live mode is off,\n");
  428.   fprintf(stdout,"                      specifies the file from which to read the packets\n");
  429.   fprintf(stdout,"                      [pcap compatible format is needed]\n");
  430.   fprintf(stdout,"  -o    output file:  needs a parameter, specifies where to save the log file\n");
  431.   fprintf(stdout,"                      of all packets\n");
  432.   fprintf(stdout,"  -j    json report:  prints the report of the monitoring in json format into\n");
  433.   fprintf(stdout,"                      a file named 'report.json'\n");
  434.   fprintf(stdout,"  -h    help:         display this help message\n");
  435. }
  436.  
  437. /* forces 'packet_callback()' to terminate */
  438. static void sigint_handler(){
  439.   signal_flag = 1;
  440. }
  441.  
  442. /* manages incoming beacon frames */
  443. static void packet_callback(u_char *args, const struct pcap_pkthdr *header, const u_char *packet){
  444.  
  445.   int x, ssid_len, channel;
  446.   u_int16_t radiotap_len, channel_frequency=0;
  447.   u_int8_t c1=0, c2=0;
  448.   float ssi_signal, data_rate;
  449.   time_t time;
  450.   struct tm *time_now;
  451.   char tmbuf[64], buf[64];
  452.   unsigned char *temp_mac = NULL;
  453.   char* temp_ssid = NULL;
  454.   ssid* temp_ssid_address = NULL, *ssid_iterator = NULL;
  455.   access_point* temp_ap_address = NULL, *ap_iterator = NULL;
  456.  
  457.   if(signal_flag){
  458.     /* incoming SIGINT, forcing termination */
  459.     pcap_breakloop(descr);
  460.   }
  461.  
  462.   packet_count ++;
  463.  
  464.   /*retrieving initial info*/
  465.   time = header->ts.tv_sec;
  466.   time_now = localtime(&time);
  467.   strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", time_now);
  468.   snprintf(buf, sizeof(buf), "%s.%06d", tmbuf, (int) header->ts.tv_usec);
  469.   radiotap_len = (u_int16_t) *(packet + 2);
  470.   temp_mac = malloc((sizeof(unsigned char)*6) + 1);
  471.   if(temp_mac == NULL){
  472.     fprintf(stderr,"SEVERE ERROR: memory allocation fail\n");
  473.     exit(EXIT_FAILURE);
  474.   }
  475.   ssid_len = (u_int8_t) packet[radiotap_len + 37];
  476.   temp_ssid = malloc((ssid_len+1)*sizeof(*temp_ssid));
  477.   if(temp_ssid == NULL){
  478.     fprintf(stderr,"SEVERE ERROR: memory allocation fail\n");
  479.     exit(EXIT_FAILURE);
  480.   }
  481.   for(x=0;x<ssid_len;x++)
  482.     *(temp_ssid + x) = (char) *(packet + radiotap_len + 38 + x);
  483.   *(temp_ssid + x) = '\0';
  484.  
  485.   if(write_log){
  486.     /* printing intial info*/
  487.     fprintf(out,"==================================================\n");
  488.     fprintf(out,"Reading packet       %d#\n", packet_count);
  489.     fprintf(out,"Packet size :        %d\n", header->len);
  490.     fprintf(out,"Packet timestamp :   %s\n", buf);
  491.     fprintf(out,"AP SSID:             %s\n",temp_ssid);
  492.   }
  493.  
  494.   /* retrieving other info */
  495.   switch(radiotap_len){
  496.     case 18 :{
  497.       for(x=0;x<6;x++)
  498.         temp_mac[x] = (unsigned char) *(packet + 18 + 16 + x);
  499.       temp_mac[x] = '\0';
  500.       ssi_signal = (int8_t) *(packet + 14);
  501.       data_rate = (float) *(packet + 9) / 2.0 ;
  502.       c1 = *(packet + 10);
  503.       c2 = *(packet + 11);
  504.       channel_frequency = (c2 << 8) + c1;
  505.       break;
  506.     }
  507.     case 25 :{
  508.       for(x=0;x<6;x++)
  509.         temp_mac[x] = (unsigned char) *(packet + 25 + 16 + x);
  510.       temp_mac[x] = '\0';
  511.       ssi_signal = (int8_t) *(packet + 22);
  512.       data_rate = (float) *(packet + 17) / 2.0 ;
  513.       c1 = *(packet + 18);
  514.       c2 = *(packet + 19);
  515.       channel_frequency = (c2 << 8) + c1;
  516.       break;
  517.  
  518.     }
  519.     case 26 :{
  520.       for(x=0;x<6;x++)
  521.         temp_mac[x] = (unsigned char) *(packet + 25 + 16 + x);
  522.       temp_mac[x] = '\0';
  523.       ssi_signal = (int8_t) *(packet + 22);
  524.       data_rate = (float) *(packet + 17) / 2.0 ;
  525.       c1 = *(packet + 18);
  526.       c2 = *(packet + 19);
  527.       channel_frequency = (c2 << 8) + c1;
  528.       break;
  529.  
  530.     }
  531.     case 30 :{
  532.       for(x=0;x<6;x++)
  533.         temp_mac[x] = (unsigned char) *(packet + 25 + 16 + x);
  534.       temp_mac[x] = '\0';
  535.       ssi_signal = (int8_t) *(packet + 22);
  536.       data_rate = (float) *(packet + 17) / 2.0 ;
  537.       c1 = *(packet + 18);
  538.       c2 = *(packet + 19);
  539.       channel_frequency = (c2 << 8) + c1;
  540.       break;
  541.  
  542.     }
  543.     case 36 :{
  544.       for(x=0;x<6;x++)
  545.         temp_mac[x] = (unsigned char) *(packet + 36 + 16 + x);
  546.       temp_mac[x] = '\0';
  547.       ssi_signal = (int8_t) *(packet + 34);
  548.       data_rate = (float) *(packet + 25) / 2.0 ;
  549.       c1 = *(packet + 26);
  550.       c2 = *(packet + 27);
  551.       channel_frequency = (c2 << 8) + c1;
  552.       break;
  553.     }
  554.     default :{
  555.       fprintf(stdout, "WARNING: This network interface it's not yet supported, results may be incorrect\n");
  556.       for(x=0;x<6;x++)
  557.         temp_mac[x] = (unsigned char) *(packet + 36 + 16 + x);
  558.         temp_mac[x] = '\0';
  559.         ssi_signal = (int8_t) *(packet + 34);
  560.         data_rate = (float) *(packet + 25) / 2.0 ;
  561.         c1 = *(packet + 26);
  562.         c2 = *(packet + 27);
  563.         channel_frequency = (c2 << 8) + c1;
  564.     }
  565.   }
  566.  
  567.   if(write_log){
  568.     /* printing other info */
  569.     fprintf(out,"AP address :         ");
  570.     print_mac(temp_mac,out);
  571.     fprintf(out,"\n");
  572.     fprintf(out,"SSI signal :         %d Dbm\n", (int) ssi_signal);
  573.     fprintf(out,"Data rate :          %f Mb/s\n", (float) data_rate);
  574.     fprintf(out,"==================================================\n");
  575.   }
  576.  
  577.   channel = select_channel(channel_frequency);
  578.  
  579.   temp_ssid_address = search_ssid(temp_ssid, ssid_list);
  580.   if(temp_ssid_address != NULL){
  581.     /* previously stored ssid */
  582.     temp_ap_address = search_ap(temp_mac, temp_ssid_address->list_ap);
  583.     if(temp_ap_address != NULL){
  584.       /* previously stored ap */
  585.       update(ssi_signal, data_rate, time, channel, temp_ap_address);
  586.     } else{
  587.       /* new ap */
  588.       temp_ssid_address->list_ap = add_ap(temp_mac, temp_ssid_address->list_ap);
  589.       update(ssi_signal, data_rate, time, channel, temp_ap_address);
  590.       temp_ssid_address->num_ap ++;
  591.     }
  592.   } else{
  593.     /* new ssid */
  594.     ssid_list = add_ssid(temp_ssid, ssid_list);
  595.     ssid_list->list_ap = add_ap(temp_mac, ssid_list->list_ap);
  596.     ssid_list->num_ap ++;
  597.     update(ssi_signal, data_rate, time, channel, ssid_list->list_ap);
  598.   }
  599.  
  600.   if(live){
  601.     /* printing temporary statistics every 100 packets */
  602.     ssid_iterator = ssid_list;
  603.     if(packet_count%100 == 0 && ssid_iterator != NULL){
  604.       fprintf(stdout,"Temporary statistics:\n\n");
  605.       while(ssid_iterator != NULL){
  606.         fprintf(stdout,"[SSID] name: %s / number of access points: %d\n",ssid_iterator->ssid_name,
  607.                                                                             ssid_iterator->num_ap);
  608.         ap_iterator = ssid_iterator->list_ap;
  609.         while(ap_iterator != NULL){
  610.           if(ap_iterator->tap_counter_temp > 0){
  611.             /* if tap_counter_temp == 0 we've temporary lost the connection with ap, so not print it */
  612.             fprintf(stdout,"  [AP] mac: ");
  613.             print_mac(ap_iterator->mac_address,stdout);
  614.             fprintf(stdout," / data rate: %f Mbps / signal: %f Dbm / channel: %d\n",
  615.                                       (float)(ap_iterator->data_rate_temp_sum / (float)ap_iterator->tap_counter_temp),
  616.                                       (float)(ap_iterator->ssi_signal_temp_sum / (float)ap_iterator->tap_counter_temp),
  617.                                       channel);
  618.             /* resetting counters */
  619.             ap_iterator->tap_counter_temp= 0;
  620.             ap_iterator->data_rate_temp_sum = 0;
  621.             ap_iterator->ssi_signal_temp_sum = 0;
  622.           }
  623.           ap_iterator = ap_iterator->next;
  624.         }
  625.         fprintf(stdout,"\n");
  626.         ssid_iterator = ssid_iterator->next;
  627.       }
  628.       fprintf(stdout,"\n\n");
  629.     }
  630.   }
  631. }
  632.  
  633. /* returns the pointer at the structure that contains 'name' if it's in the list, NULL otherwise */
  634. static ssid* search_ssid(char* name, ssid *list){
  635.  
  636.   ssid* this = list;
  637.  
  638.   while(this != NULL){
  639.     if(strcmp(this->ssid_name, name) == 0)
  640.       return this;
  641.     this = this->next;
  642.   }
  643.   return NULL;
  644. }
  645.  
  646. /* returns the new list obtained by adding name on top of the list */
  647. static ssid* add_ssid(char* name, ssid *list){
  648.  
  649.   ssid *new_ssid = malloc(sizeof(ssid));
  650.   if(new_ssid == NULL){
  651.     fprintf(stderr,"SEVERE ERROR: memory allocation fail\n");
  652.     exit(EXIT_FAILURE);
  653.   }
  654.  
  655.   new_ssid->ssid_name = name;
  656.   new_ssid->list_ap = NULL;
  657.   new_ssid->num_ap = 0;
  658.  
  659.   new_ssid->next = list;
  660.  
  661.   return new_ssid;
  662. }
  663.  
  664. /* returns the pointer at the structure contains 'mac' if it's present in the list, NULL otherwise */
  665. static access_point* search_ap(unsigned char* mac, access_point* list){
  666.  
  667.   access_point* this = list;
  668.  
  669.   while(this != NULL){
  670.     if(mac_compare(this->mac_address,mac)==0)
  671.       return this;
  672.     this = this->next;
  673.   }
  674.   return NULL;
  675. }
  676.  
  677. /* returns the new list obtained by adding 'mac' on top of the list */
  678. static access_point* add_ap(unsigned char* mac, access_point* list){
  679.  
  680.   access_point *new_ap = malloc(sizeof(access_point));
  681.   if(new_ap == NULL){
  682.     fprintf(stderr,"SEVERE ERROR: memory allocation fail\n");
  683.     exit(EXIT_FAILURE);
  684.   }
  685.  
  686.   new_ap->mac_address = mac;
  687.   new_ap->ssi_signal_sum = 0;
  688.   new_ap->ssi_signal_temp_sum = 0;
  689.   new_ap->data_rate_temp_sum = 0;
  690.   new_ap->tap_counter_temp = 0;
  691.   new_ap->data_rate_sum = 0;
  692.   new_ap->data_rate_min = FLT_MAX;
  693.   new_ap->data_rate_max = FLT_MIN;
  694.   new_ap->ssi_signal_max = -500.0;
  695.   new_ap->ssi_signal_min = FLT_MAX;
  696.   new_ap->data_rate_min_ts = 0;
  697.   new_ap->data_rate_max_ts = 0;
  698.   new_ap->ssi_signal_max_ts = 0;
  699.   new_ap->ssi_signal_min_ts = 0;
  700.   new_ap->tap_counter = 0;
  701.   new_ap->channel = 0;
  702.  
  703.   new_ap->next = list;
  704.  
  705.   return new_ap;
  706. }
  707.  
  708. /* updates statistics of the ap */
  709. static void update(float signal, float rate, time_t ts, int channel, access_point* ap){
  710.     if(ap != NULL){
  711.         ap->tap_counter ++;
  712.     ap->tap_counter_temp ++;
  713.         ap->ssi_signal_sum += signal;
  714.     ap->ssi_signal_temp_sum += signal;
  715.     ap->data_rate_sum += rate;
  716.     ap->data_rate_temp_sum += rate;
  717.     if(signal < ap->ssi_signal_min){
  718.       ap->ssi_signal_min = signal;
  719.       ap->ssi_signal_min_ts = ts;
  720.     }
  721.     if(signal > ap->ssi_signal_max){
  722.       ap->ssi_signal_max = signal;
  723.       ap->ssi_signal_max_ts = ts;
  724.     }
  725.     if(rate < ap->data_rate_min){
  726.       ap->data_rate_min = rate;
  727.       ap->data_rate_min_ts = ts;
  728.     }
  729.     if(rate > ap->data_rate_max){
  730.       ap->data_rate_max = rate;
  731.       ap->data_rate_max_ts = ts;
  732.     }
  733.     ap->channel = channel;
  734.     }
  735. }
  736.  
  737. /* compares two mac address */
  738. int mac_compare(unsigned char *a, unsigned char *b){
  739.     int i=0, bol=0;
  740.     while(*(a+i)!='\0' && *(b+i)!='\0' && bol==0){
  741.         if(*(a+i) != *(b+i))
  742.             bol=1;
  743.         i++;
  744.     }
  745.     return bol;
  746. }
  747.  
  748. /* print mac address on stdout */
  749. void print_mac(unsigned char* data, FILE* file_desc){
  750.     fprintf(file_desc, "%-.2X:%-.2X:%-.2X:%-.2X:%-.2X:%-.2X", data[0], data[1], data[2],    data[3], data[4], data[5]);
  751. }
  752.  
  753. /* returns correct channel corresponding at 'frequency', 0 if not supported */
  754. int select_channel(u_int16_t frequency){
  755.     switch(frequency){
  756.         case 2412:
  757.             return 1;
  758.         case 2417:
  759.             return 2;
  760.         case 2422:
  761.             return 3;
  762.         case 2427:
  763.             return 4;
  764.         case 2432:
  765.             return 5;
  766.         case 2437:
  767.             return 6;
  768.         case 2442:
  769.             return 7;
  770.         case 2447:
  771.             return 8;
  772.         case 2452:
  773.             return 9;
  774.         case 2457:
  775.             return 10;
  776.         case 2462:
  777.             return 11;
  778.         case 2467:
  779.             return 12;
  780.         case 2472:
  781.             return 13;
  782.         case 2484:
  783.             return 14;
  784.     }
  785.     return 0;
  786. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement