Main Page | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

scanner.c

Go to the documentation of this file.
00001 /*
00002  * File : scanner.c
00003  * Project : WifiScanner (c) 2002-2004 Hervé Schauer Consultants
00004  * Usage : This utility is written for use with IEEE 802.11 adapters based
00005  * on Intersil's PRISM II chipset (PCMCIA).
00006  * 
00007  * Base code was from prismstumbler Jan Fernquist <Jan.B.Fernquist@telia.com>
00008  * and wlanctl from www.linux-wlan.org
00009  *
00010  * This program is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU General Public License
00012  * as published by the Free Software Foundation; either version 2
00013  * of the License, or (at your option) any later version.
00014  * 
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  * 
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023  *
00024  * 
00025  */
00026 
00027 
00028 #include <include.h>
00029 #include <src/interface.h>
00030 #include <src/driver.h>
00031 #include <src/functions.h>
00032 #include <src/analyse.h>
00033 #include <src/scanner.h>
00034 #include <src/crt_io.h>
00035 #include <src/conversion.h>
00036 #ifdef WITH_WIRETAP
00037 #include <wtap.h>
00038 #endif
00039 
00040 
00041 /*
00042 */
00043 void Bye(void);
00044 void HelpAndBye(void);
00045 void VersionAndBye(void);
00046 void DispConf(ConfigStruct * config);
00047 
00048 void parse_keystring();
00049 void check_keys();
00050 
00051 static UINT8 ID[] =
00052     "$Id: scanner.c,v 1.54 2005/02/23 11:36:53 poggij Exp $";
00053 
00054 /*
00055  * Use globals, ugly ... 
00056  */
00057 ConfigStruct config;
00058 
00059 ScanResult_t Res;
00060 WINDOW *Title_WND, *Panel_WND, *Sum_WND, *RealTime_WND;
00061 Statistics_t Stats;
00062 UINT8 CursesIsInUse = (UINT8) 0;        /* To know if curses environment is in use */
00063 
00064 #ifdef WITH_THREAD
00065 
00066 pthread_mutex_t screen_mutex = PTHREAD_MUTEX_INITIALIZER;
00067 pthread_t thread_ChgChan, thread_RefreshRTW, thread_checkkey;
00068 UINT8 stop_sniffing = (UINT8) 0;
00069 #else
00070 static UINT8 stop_sniffing = (UINT8) 0;
00071 #endif
00072 
00073 char keystring[KEYBOARD_BUFFER];
00074 int keyindex = 0;
00075 
00079 RETSIGTYPE stop_signal(void)
00080 {
00081   // We don't need to stop, if we know that we will stop
00082   if (!stop_sniffing) {
00083 #ifdef WITH_THREAD
00084     // Clean and Force STOP the thread
00085     pthread_mutex_unlock(&screen_mutex);
00086     //pthread_kill( &thread_ChgChan, (int) 1);
00087     pthread_mutex_destroy(&screen_mutex);
00088 #endif
00089     warning("Received CTRL-C - sniffing aborted\n\n");
00090     stop_sniffing = (UINT8) 1;
00091   }
00092 }
00093 
00094 /*
00095  *  Display help text and leave
00096  */
00097 void HelpAndBye(void)
00098 {
00099   fprintf(stderr, "%s", HELPTEXT);
00100   fprintf(stderr, "\nPlease send Bug report to : %s\n\n", WIFISCANNER_BUG);
00101   exit(EXIT_SUCCESS);
00102 }
00103 
00104 // Just exit, not sure this function is usefull
00105 void Bye(void)
00106 {
00107   exit(EXIT_SUCCESS);
00108 }
00109 
00110 #ifdef WITH_THREAD
00111 void ChangeChannel_th(void *ptr1)
00112 {
00113   struct timeb binary_now, TimeScann;
00114   char *devname;
00115   register UINT32 TTSBCC;
00116   register UINT32 TTSBCC100;
00117 
00118   //struct timespec delay;
00119 
00120   ftime(&TimeScann);
00121   devname = (char *) ptr1;
00122   /* For other OS than Linux :
00123      delay.tv_sec = 0;
00124      delay.tv_nsec = config.TimeToSleepBeforeChangeChannel * 100000;
00125    */
00126 
00127   while (stop_sniffing == 0) {
00128         /*** Time trigger for change channel ***/
00129     TTSBCC = config.TimeToSleepBeforeChangeChannel;
00130     TTSBCC100 = config.TimeToSleepBeforeChangeChannel * 100;
00131     // Save time, so we change channel only when it's time
00132     ftime(&binary_now);
00133     // is it time to change channel ?
00134     if (config.SingleChannel == 0 &&
00135         ((binary_now.time - TimeScann.time) * 1000) +
00136         ((binary_now.millitm - TimeScann.millitm)) >=
00137         (signed long) TTSBCC) {
00138       /* it's time to change Channel */
00139       ftime(&TimeScann);
00140       if (NextChannel(devname, config.ChannelHop)) {
00141         stop_sniffing = 2;
00142         debug(2, "devname = %s, ChannelHop=%d\n",
00143               devname, config.ChannelHop);
00144         debug(0, "Can't change Channel\n");
00145         break;                  // Exit while (stop_sniffing == 0)
00146       }
00147     }
00148     //pthread_delay_np (&delay);
00149     usleep(TTSBCC100);
00150   }
00151   pthread_exit(0);
00152 }
00153 #endif
00154 
00155 
00156 /*
00157  * Keyboard Handling
00158  */
00159 #ifdef WITH_THREAD
00160 void check_keys_th()
00161 {
00162   UINT8 car;
00163 
00164   nodelay(stdscr, TRUE);        // FIXME move it ...
00165   while (stop_sniffing == 0) {
00166     if ((car = tolower(getch())) != ERR) {
00167       if ((car >= ' ') && (car <= '~')) {
00168         // Check if it's not a bad char
00169         keystring[keyindex] = car;
00170         debug(3, "We Hit : #%c# - keyindex=%d\n", keystring[keyindex],
00171               keyindex);
00172         keyindex = (keyindex + 1) % KEYBOARD_BUFFER;
00173         pthread_mutex_lock(&screen_mutex);
00174         mvwprintw(Sum_WND, 11, 11, "(%-4s)", keystring);
00175         wrefresh(Sum_WND);
00176         pthread_mutex_unlock(&screen_mutex);
00177         parse_keystring();
00178       }
00179     }
00180     //pthread_delay_np (&delay);
00181     usleep(100000);
00182   }
00183 }
00184 #else
00185 void check_keys()
00186 {
00187   nodelay(stdscr, TRUE);        // FIXME move it ...
00188   if ((keystring[keyindex] = tolower(getch())) != ERR) {
00189     if ((keystring[keyindex] >= ' ') && (keystring[keyindex] <= '~')) {
00190       // Check if it's not a bad char
00191       debug(3, "We Hit : #%c# - keyindex=%d\n", keystring[keyindex],
00192             keyindex);
00193       keyindex = (keyindex + 1) % KEYBOARD_BUFFER;
00194       mvwprintw(Sum_WND, 11, 11, "(%-4s)", keystring);
00195       wrefresh(Sum_WND);
00196       parse_keystring();
00197     } else {
00198       keystring[keyindex] = 0;
00199     }
00200   }
00201 }
00202 #endif
00203 
00204 
00205 
00206 /******** MAIN ********/
00207 
00208 int main(int argc, char **argv)
00209 {
00210   int recvlen;                  // Size of packet received
00211 
00212   //int MaxPacketPerChannel;    // Number of packet received before the next channel is select
00213   struct tm *ascii_now = NULL;  // The timestamp in ASCII (human readable)
00214   struct timeb binary_now;
00215   unsigned char msgbuf[MAX_BUFFER_SIZE];        // packet container
00216 
00217 #ifdef WITHOUT_THREAD
00218   struct timeb TimeScann;
00219 #endif
00220 #ifdef WITH_WIRETAP
00221   struct wtap_pkthdr packet_hdr_info;   // pointer to the header of wtap packet 
00222   int wtap_error;
00223   wtap_dumper *dump_file = NULL;        // pointer to the file used to save pcap data
00224 #else
00225   char *dump_file = NULL;
00226 #endif
00227   UINT64 CatchPacket = 0;
00228   char PacketStatus[256];
00229   FILE *OutFile = NULL, *OutDumpFile = NULL, *OutDotFile = NULL;
00230   UINT8 GotItOne = FALSE;
00231   UINT8 ids_warning = (UINT8) 0;
00232   char strChannel[8];
00233   UINT8 ActifChannel = 0;
00234   int ret;
00235 
00236 
00237   // Wifiscanner Info Banner
00238   fprintf(stderr,
00239           "WifiScanner v%s (c) 2002-2004 Hervé Schauer Consultants (",
00240           WIFISCANNER_VERSION);
00241   fprintf(stderr, "Jerome.Poggi@hsc-labs.com)\n\n");
00242 
00243   // Root permissions test
00244   if (getuid() != 0) {
00245     warning
00246         ("Hum hum, you seem to be not have the root capabilities...\n"
00247          "wifiscanner -h for help\n"
00248          "Try to obtain root capabilities and re-run me :-)\n");
00249     Bye();
00250   }
00251   // Configuration declaration
00252   InitConfiguration(&config);
00253 
00254   /* parse command line */
00255   ParseCommandLine(argc, argv, &config);
00256   DispConf(&config);
00257 
00258   // For information
00259   debug(3, "Size of ClientInfo_t struct : %6d bytes\n",
00260         sizeof(ClientInfo_t));
00261   debug(3, "Size of ClientInfo_t array  : %6d bytes\n",
00262         (sizeof(ClientInfo_t) * MAX_NUMBER_OF_DETECTED_CLIENT));
00263 
00264   // We try to interract with the card, if it's not possible we exit
00265   if (openCard(config.devname)) {
00266     fatal("The interface can not be found or initialize\n");
00267   }
00268   // Sanity check
00269   if (config.OutFileName) {
00270     if ((OutFile = fopen(config.OutFileName, "a")) == NULL) {
00271       fatal("Cant open outfile %s for writing\n", config.OutFileName);
00272     }
00273   }
00274 #ifdef WITH_WIRETAP
00275   // Sanity check
00276   if (config.OutDumpFileName) {
00277     dump_file =
00278         wtap_dump_open(config.OutDumpFileName, WTAP_FILE_PCAP,
00279                        WTAP_ENCAP_IEEE_802_11, 2344, &wtap_error);
00280     if (!dump_file) {
00281       fatal("Cannot make the dump file!\n");
00282     }
00283   }
00284 #endif
00285 
00286 
00287   fprintf(stderr, "Install interrupt handler...\n");
00288   if (signal(SIGINT, (__sighandler_t) stop_signal) == SIG_ERR) {
00289     fatal("AAAARRRGGG ! Can't install the SIGINT handler !\n");
00290   }
00291   if (signal(SIGTERM, (__sighandler_t) stop_signal) == SIG_ERR) {
00292     fatal("AAAARRRGGG ! Can't install the SIGTERM handler !\n");
00293   }
00294   if (signal(SIGHUP, (__sighandler_t) stop_signal) == SIG_ERR) {
00295     fatal("AAAARRRGGG ! Can't install the SIGHUP handler !\n");
00296   }
00297   fprintf(stderr, "Beginning scan of the 802.11b networks...\n");
00298   fprintf(stderr, "Use CTRL-C or Q to stop sniffing\n");
00299 
00300   if (config.TypeOfCard == CISCO_CVS_CARD) {
00301     ret = openPacket(config.devname2);
00302     if (ret < 0) {
00303       fprintf(stderr, "Can't open pcap %s device (err: %d = %s)\n",
00304               config.devname2, errno, strerror(errno));
00305       exit(EXIT_FAILURE);
00306     }
00307   } else {
00308     ret = openPacket(config.devname);
00309     if (ret < 0) {
00310       fprintf(stderr, "Can't open pcap %s device (err: %d = %s)\n",
00311               config.devname, errno, strerror(errno));
00312 #ifdef WITH_WIRETAP
00313       //wtap_dump_close(dump_file, &wtap_error);
00314 #endif
00315       exit(EXIT_FAILURE);
00316     }
00317   }
00318 
00319 #ifdef HAVE_LIBNCURSES
00320   /* Initialisation of NCURSES */
00321   CursesIsInUse = TRUE;
00322   InitScreen(config.CheckScreenSize);
00323   if (config.IDS_is_ON == TRUE)
00324     mvwprintw(Sum_WND, 17, 3, "IDS is ON ");
00325 #else
00326   if (config.IDS_is_ON == TRUE)
00327     fprintf(stderr, "IDS is ON");
00328 #endif
00329 
00330   /*** 
00331    * Change my Priority and put all keyboard input to trash
00332    ***/
00333 
00334   (void) setvbuf(stdin, NULL, _IONBF, 0);       // Input go to trash :-)
00335   (void) setpriority(PRIO_PROCESS, 0, -15);     // take more CPU than normal
00336 
00337   /***
00338    *  Initialisation of the selected channel in single channel scan 
00339    ***/
00340   if (config.SingleChannel &&
00341       !selectChannel(config.devname, config.SingleChannel)) {
00342     //stop_sniffing = 1;
00343     warning("Can't initialize Channel number %d !\n",
00344             config.SingleChannel);
00345     //sleep (5);
00346   }
00347 
00348 
00349 
00350 /*
00351  * We install our threads here 
00352  */
00353 #ifdef WITH_THREAD
00354   // Thread for changing channel
00355   // ---------------------------
00356   if ((config.TypeOfCard != CISCO_CVS_CARD)
00357       && (config.TypeOfCard != CISCO_CARD)) {
00358     ret =
00359         pthread_create(&thread_ChgChan, NULL, (void *) &ChangeChannel_th,
00360                        (void *) config.devname);
00361     if (ret < 0)
00362       fatal("Boom ! Thread to change channel cannot create (err:%d)\n",
00363             ret);
00364   }
00365   // Thread to refresh screen only one time per second
00366   // -------------------------------------------------
00367   if (config.DebugLevel < 2) {
00368     ret =
00369         pthread_create(&thread_RefreshRTW, NULL,
00370                        (void *) &RefreshRealTime_WND_th, (void *) NULL);
00371     if (ret < 0)
00372       fatal("Boom ! Thread to refresh screen cannot create (err:%d)\n",
00373             ret);
00374   }
00375   // Thread to check keyboard
00376   // ------------------------
00377   ret =
00378       pthread_create(&thread_checkkey, NULL, (void *) &check_keys_th,
00379                      (void *) config.devname);
00380   if (ret < 0)
00381     fatal("Boom ! Thread to manage keyboard cannot create (err:%d)\n",
00382           ret);
00383 #else
00384   ftime(&TimeScann);
00385 #endif
00386 
00387   /*****
00388     This is the linear and threaded scheduler
00389     TODO : To convert in more thread (Work in progress) :-)
00390     TODO : It's better to be ONLY threaded
00391   ******/
00392   while (stop_sniffing == 0) {
00393 
00394 #ifdef WITHOUT_THREAD
00395     check_keys();
00396         /*** Time trigger for change channel ***/
00397     // Save time, so we change channel only when it's time
00398     ftime(&binary_now);
00399     // is it time to change channel ?
00400     if (((binary_now.time - TimeScann.time) * 1000) +
00401         (binary_now.millitm - TimeScann.millitm) >=
00402         (config.TimeToSleepBeforeChangeChannel)) {
00403       /* it's time to change Channel */
00404       if (!config.SingleChannel) {
00405         ftime(&TimeScann);
00406         if (NextChannel(config.devname, config.ChannelHop)) {
00407           stop_sniffing = 2;
00408           debug(0, "Can't change Channel\n");
00409           break;                // Exit while (stop_sniffing == 0)
00410         }
00411       }
00412     }
00413 #endif
00414 
00415         /*** Get packet process ***/
00416     memset(msgbuf, 0, MAX_BUFFER_SIZE);
00417     recvlen =
00418         getPacket(msgbuf, MAX_BUFFER_SIZE, TIMEOUT_TRY_TO_READ_PAQUET);
00419     if (recvlen > 0) {
00420       // Get it one ? Yes ! so analyse it
00421       Stats.Packets++;
00422       GotItOne = TRUE;
00423       // Save the hardware channel before the washing machine
00424       ActifChannel = Res.SChannel;
00425       memset(&Res, 0, sizeof(Res));
00426       Res.SChannel = ActifChannel;
00427       // Print the packet number and size
00428       debug(2, "Packet number : %ld\n", CatchPacket);
00429       debug(2, "recvlen = %X\n", recvlen);
00430 
00431       // Just an Hexdump packet
00432       if (config.DebugLevel >= 2) {
00433         DumpHexPaquets(RealTime_WND, msgbuf, recvlen);
00434         //wrefresh(RealTime_WND);
00435       }
00436       /* END DEBUG */
00437 
00438 #ifdef WITH_WIRETAP
00439  /*** Write DATA to DumpFile ***/
00440       if (config.OutDumpFileName) {
00441         /*
00442          * Setup Wiretap packet header 
00443          */
00444         gettimeofday(&packet_hdr_info.ts, NULL);
00445         packet_hdr_info.caplen = recvlen;
00446         packet_hdr_info.len = recvlen;
00447         packet_hdr_info.pkt_encap = WTAP_ENCAP_IEEE_802_11;
00448 
00449         /*
00450          * Now we can save the frame to the capture file 
00451          */
00452         if (!wtap_dump
00453             (dump_file, &packet_hdr_info, NULL, &msgbuf, &wtap_error)) {
00454           stop_sniffing = 4;
00455           debug(0, "Can't save DATA\n");
00456           goto NoPacketIsCatched;
00457         }
00458       }
00459 #endif
00460 
00461       /*
00462        * Analyse Data and Write Result
00463        */
00464       if (processPacket(msgbuf, recvlen)) {
00465         // Define how and what we display for channel
00466         ChannelToStr(strChannel, Res.Channel, Res.SChannel);
00467         //debug (0, "SSID = '%s'\n", Res.SSID);
00468 
00469         // Save the maximum strength of signal for print an hitogram
00470         if (Stats.MaxSignal[ActifChannel - 1] < Res.Signal)
00471           Stats.MaxSignal[ActifChannel - 1] = Res.Signal;
00472 
00473         // Different date format.
00474         ftime(&binary_now);
00475         if (config.DateFormat == 0) {
00476           snprintf(PacketStatus, 256,
00477                    "%d.%03d,\"%s\",%s,%s,%s,%03d,%03d,%s,%s,%s,%s,%s,%s,%s\n",
00478                    (int) binary_now.time,
00479                    binary_now.millitm,
00480                    Res.SSID, strChannel,
00481                    BoolToWepNoWep(Res.hasWep),
00482                    BoolToStaAp(GET_TYPE_BIT_AP(Res.TypeOfClient)),
00483                    Res.Signal, Res.Noise,
00484                    Res.DestMac, Res.SrcMac,
00485                    Res.BssId,
00486                    RateToString(Res.Rate),
00487                    TypeOfClientToString(Res.TypeOfClient),
00488                    SubTypeOfClientToString
00489                    (Res.TypeOfClient), Res.TypeOfPacket);
00490         } else {
00491           ascii_now = localtime(&binary_now.time);
00492           snprintf(PacketStatus, 256,
00493                    "%02d/%02d/%04d %02d:%02d:%02d.%03d,"
00494                    "\"%s\",%s,%s,%s,%03d,%03d,%s,%s,%s,%s,%s,%s,%s\n",
00495                    ascii_now->tm_mon + 1,
00496                    ascii_now->tm_mday,
00497                    ascii_now->tm_year + 1900,
00498                    ascii_now->tm_hour,
00499                    ascii_now->tm_min,
00500                    (binary_now.millitm == 1000) ?
00501                    (ascii_now->tm_sec + 1) : ascii_now->tm_sec,
00502                    (binary_now.millitm == 1000) ?
00503                    0 : binary_now.millitm,
00504                    Res.SSID, strChannel, BoolToWepNoWep(Res.hasWep),
00505                    BoolToStaAp(GET_TYPE_BIT_AP(Res.TypeOfClient)),
00506                    Res.Signal, Res.Noise, Res.DestMac, Res.SrcMac,
00507                    Res.BssId, RateToString(Res.Rate),
00508                    TypeOfClientToString(Res.TypeOfClient),
00509                    SubTypeOfClientToString(Res.TypeOfClient),
00510                    Res.TypeOfPacket);
00511         }
00512 
00513         // SWITCH : DISPLAY or NOT a sort of Packet
00514         if (!((DO_NOT_DISPLAY_ACK)
00515               || (DO_NOT_DISPLAY_BEACON)
00516               || (DO_NOT_DISPLAY_CONTROL)
00517               || (DO_NOT_DISPLAY_DATA))) {
00518 #ifdef HAVE_LIBNCURSES
00519           wprintw(RealTime_WND, "%s", PacketStatus);
00520 #else
00521           fprintf(stdout, "%s", PacketStatus);
00522 #endif                          //#ifdef HAVE_LIBNCURSES
00523         }
00525         if (OutFile) {
00526           fprintf(OutFile, "%s", PacketStatus);
00527           fflush(OutFile);
00528         }
00530         debug(1, "--- END OF PACKET PROCESSING ---\n");
00531 #ifdef HAVE_LIBNCURSES
00532         WritePanel(TRUE);
00533         //RefreshRealTime_WND(GotItOne);
00534 #else
00535         fflush(stdout);
00536 #endif                          // #ifdef HAVE_LIBNCURSES
00537       } else {                  /* if (processPacket */
00538         /* Packet is not analysed */
00539         // Init of time
00540         //ftime (&binary_now);
00541 
00542         if (Res.TypeOfPacket != NULL) {
00543           if (config.DateFormat == 0) {
00544             snprintf(PacketStatus, 256,
00545                      "%d.%03d,%s\n",
00546                      (int) binary_now.
00547                      time, binary_now.millitm, Res.TypeOfPacket);
00548           } else {
00549             ascii_now = localtime(&binary_now.time);
00550             snprintf(PacketStatus, 256,
00551                      "%02d/%02d/%04d %02d:%02d:%02d.%03d,%s\n",
00552                      ascii_now->tm_mon + 1,
00553                      ascii_now->tm_mday,
00554                      ascii_now->tm_year + 1900,
00555                      ascii_now->tm_hour,
00556                      ascii_now->tm_min,
00557                      ascii_now->tm_sec,
00558                      binary_now.millitm, Res.TypeOfPacket);
00559           }
00560 
00561 #ifdef HAVE_LIBNCURSES
00562           wprintw(RealTime_WND, "%s", PacketStatus);
00563           WritePanel(FALSE);
00564           //RefreshRealTime_WND(GotItOne);
00565 #else
00566           fprintf(stdout, "%s\n", PacketStatus);
00567 #endif                          // #ifdef HAVE_LIBNCURSES
00568 
00569           // Write it also on file if wanted
00570           if (OutFile) {
00571             fprintf(OutFile, "%s", PacketStatus);
00572           }
00573         }
00574       }
00575       // Exit if we reach the maximum of packets wanted
00576       ++CatchPacket;
00577       if ((config.MaxPacket != 0)
00578           && (CatchPacket >= (config.MaxPacket + Stats.INVLD))) {
00579         stop_sniffing = 5;      // Exit the principal loop
00580         warning("Max packets reached\n");
00581       }
00582     } else {
00583       // No packet ? so sleep and wait
00584       /* An another solution is to used "blocking" IO */
00585       //if (config.SingleChannel)
00586       //usleep (TIMEOUT_TRY_TO_READ_PAQUET);
00587       usleep(config.TimeToSleepBeforeChangeChannel * 10);
00588     }
00589   NoPacketIsCatched:
00590 
00591     if (GotItOne) {
00592       if ((config.IDS_is_ON == TRUE) && ((ids_warning = IDS()) != 0)) {
00593         ascii_now = localtime(&binary_now.time);
00594 #ifdef HAVE_LIBNCURSES
00595         if (config.DateFormat == 0) {
00596           mvwprintw(Panel_WND, ROW_WND_PANEL - 1, 24, "IDS WARNING (%d)",
00597                     (int) binary_now.time);
00598         } else {
00599           mvwprintw(Panel_WND, ROW_WND_PANEL - 1, 24,
00600                     "IDS WARNING (%02d/%02d/%04d %02d:%02d:%02d)",
00601                     ascii_now->tm_mon + 1, ascii_now->tm_mday,
00602                     ascii_now->tm_year + 1900, ascii_now->tm_hour,
00603                     ascii_now->tm_min, ascii_now->tm_sec);
00604         }
00605 #else
00606         if (config.DateFormat == 0) {
00607 
00608           fprintf(stderr, "IDS WARNING (%d)", (int) binary_now.time);
00609         } else {
00610           fprintf(stderr,
00611                   "IDS WARNING (%02d/%02d/%04d %02d:%02d:%02d)",
00612                   ascii_now->tm_mon + 1,
00613                   ascii_now->tm_mday,
00614                   ascii_now->tm_year + 1900,
00615                   ascii_now->tm_hour,
00616                   ascii_now->tm_min, ascii_now->tm_sec);
00617         }
00618 #endif
00619       }
00620     }
00621 #ifdef HAVE_LIBNCURSES
00622     WriteSummary();
00623     RefreshRealTime_WND(GotItOne);
00624 #endif
00625     // For refreshing screen only one time per second
00626     GotItOne = FALSE;
00627   }                             /* while still sniffing */
00628 
00629 #ifdef WITH_THREAD
00630   // Destroy MUTEX
00631   pthread_mutex_destroy(&screen_mutex);
00632   // Wait thread to exit
00633   if (!config.SingleChannel) {  // TODO check if thread_ChgChan if is null and kill thread if not
00634     void *ret;
00635 
00636     warning("Waiting thread_ChgChan to exit...");
00637     (void) pthread_join(thread_ChgChan, &ret);
00638     warning("OK\n");
00639   }
00640   if (config.DebugLevel < 2) {
00641     void *ret;
00642 
00643     warning("Waiting thread_RefreshRTW to exit...");
00644     (void) pthread_join(thread_RefreshRTW, &ret);
00645     warning("OK\n");
00646   }
00647 #endif
00648   if (config.DebugLevel > 0) {
00649     warning("Wait 5 seconds before exit...\n");
00650     sleep(5);
00651   }
00652 
00653   EndCurses();                  
00654 
00655   if (OutFile) {                
00656     fclose(OutFile);
00657   }
00658 #ifdef WITH_WIRETAP
00659   if (OutDumpFile) {            
00660     wtap_dump_close(dump_file, &wtap_error);
00661   }
00662 #endif
00663 
00664   closePacket();                
00665   shutCard(config.devname);     
00666 
00667   LogWriteReport();             
00668 
00669   if (config.OutDotFileName) {  
00670     if ((OutDotFile = fopen(config.OutDotFileName, "w")) == NULL) {
00671       fatal("Cant open outfile %s for writing\n", config.OutDotFileName);
00672     }
00673     LogWriteDOT(OutDotFile);
00674     fclose(OutDotFile);
00675   }
00676 
00677   if (!config.SingleChannel) {
00678     LogWriteHisto();
00679   }
00680 
00681   debug(1, "Stop Sniffing = %d\n", stop_sniffing);
00682   exit(EXIT_SUCCESS);
00683 }
00684 
00685 
00686 /*
00687  * Parse key buffer & fire commands
00688  */
00689 
00690 #define CLEAR_KEYBOARD_BUFFER       memset (keystring, 0, KEYBOARD_BUFFER);keyindex = 0;
00691 
00692 void parse_keystring()
00693 {
00694 
00695   switch (keyindex) {
00696   case 1:
00697     switch (keystring[0]) {
00698     case '+':                  // Go to next channel
00699     case '-':                  // Go to previous channel
00700       if ((keystring[0] == '+')
00701           && (config.SingleChannel < 14))
00702         config.SingleChannel++;
00703       if ((keystring[0] == '-')
00704           && (config.SingleChannel > 0))
00705         config.SingleChannel--;
00706 
00707       config.SingleChannel = (config.SingleChannel % (CHANNEL_MAX + 1));
00708 
00709       selectChannel(config.devname, config.SingleChannel);
00710       CLEAR_KEYBOARD_BUFFER;
00711       break;
00712     case 'a':                  // Go to next channel
00713     case 'w':                  // Go to previous channel
00714       if ((keystring[0] == 'a') && (config.FirstNIC > 0))
00715         config.FirstNIC--;
00716       if (keystring[0] == 'w')
00717         config.FirstNIC++;
00718       debug(3, "config.FirstNIC = %d\n", config.FirstNIC);
00719       CLEAR_KEYBOARD_BUFFER;
00720       break;
00721     case 'q':                  // It's time to exit
00722       // We don't need to stop, if we know that we will stop
00723       if (!stop_sniffing) {
00724 #ifdef WITH_THREAD
00725         // Clean and Force STOP the thread
00726         pthread_mutex_unlock(&screen_mutex);
00727         pthread_mutex_destroy(&screen_mutex);
00728 #endif
00729         warning("Q was hit - sniffing aborted\n\n");
00730         stop_sniffing = (UINT8) 1;
00731       }
00732       break;
00733     case 's':                  // change channel more Slowly
00734       config.TimeToSleepBeforeChangeChannel += 10;
00735       debug(2,
00736             "config.TimeToSleepBeforeChangeChannel = %d ms\n",
00737             config.TimeToSleepBeforeChangeChannel);
00738       CLEAR_KEYBOARD_BUFFER;
00739       break;
00740     case 'f':                  // change channel more Fast
00741       config.TimeToSleepBeforeChangeChannel -= 10;
00742       if (config.TimeToSleepBeforeChangeChannel < 10)
00743         config.TimeToSleepBeforeChangeChannel = 10;
00744       debug(2,
00745             "config.TimeToSleepBeforeChangeChannel = %d ms\n",
00746             config.TimeToSleepBeforeChangeChannel);
00747       CLEAR_KEYBOARD_BUFFER;
00748       break;
00749     case 'd':                  // default TimeToSleepBeforeChangeChannel
00750       config.TimeToSleepBeforeChangeChannel =
00751           TIME_TO_SLEEP_BEFORE_CHANGE_CHANNEL;
00752       debug(2,
00753             "config.TimeToSleepBeforeChangeChannel = %d ms\n",
00754             config.TimeToSleepBeforeChangeChannel);
00755       CLEAR_KEYBOARD_BUFFER;
00756       break;
00757     case 'h':
00758       warning("Help :\n" "Q for quit\n"
00759               "C??C to scan channel ??\n"
00760               "+ - to increment or decrement channel to scan\n"
00761               "A W to scroll in the upper window\n"
00762               "F S D for scan more fast, more slow and default time\n"
00763               "J+ J- for changing channel hop\n"
00764               "V+ V- for changing verbose level\n"
00765               "N abcd for hiding/showing Ack, Beacon, Control and Data\n");
00766       CLEAR_KEYBOARD_BUFFER;
00767       break;
00768     case 'c':                  // a 4 key option
00769     case 'j':                  // a 2 key option
00770     case 'v':                  // a 2 key option
00771     case 'n':                  // a 2 key option
00772       break;
00773     default:                   // the user hit the keyboard, but don't know what he do
00774       CLEAR_KEYBOARD_BUFFER;
00775       break;
00776     }
00777     break;
00778   case 2:
00779     switch (keystring[0]) {
00780     case 'c':
00781       break;
00782     case 'j':
00783       switch (keystring[1]) {
00784       case '+':                // Go to next channel hop
00785         if (config.ChannelHop < HOP_MAX)
00786           config.ChannelHop++;
00787         break;
00788       case '-':                // Go to previous channel hop
00789         if (config.ChannelHop > HOP_MIN)
00790           config.ChannelHop--;
00791         break;
00792       default:
00793         break;
00794       }
00795       debug(2, "config.ChannelHop = %d\n", config.ChannelHop);
00796       CLEAR_KEYBOARD_BUFFER;
00797       break;
00798     case 'v':
00799       switch (keystring[1]) {
00800       case '+':                // Be more verbose
00801         if (config.DebugLevel < MAX_DEBUG_LEVEL)
00802           config.DebugLevel++;
00803         break;
00804       case '-':                // Be less verbose
00805         if (config.DebugLevel > 0)
00806           config.DebugLevel--;
00807         break;
00808       default:
00809         CLEAR_KEYBOARD_BUFFER;
00810         break;
00811       }
00812       debug(1, "DebugLevel=%d\n", config.DebugLevel);
00813       CLEAR_KEYBOARD_BUFFER;
00814       keyindex = 0;
00815       memset(keystring, 0, KEYBOARD_BUFFER);
00816       break;
00817     case 'n':
00818       switch (keystring[1]) {
00819       case 'a':
00820         SWITCH_BIT(config.DoNotDisplay, 0);
00821         debug(1, "Switch display of ACK\n");
00822         break;
00823       case 'b':
00824         SWITCH_BIT(config.DoNotDisplay, 1);
00825         debug(1, "Switch display of BEACON\n");
00826         break;
00827       case 'c':
00828         SWITCH_BIT(config.DoNotDisplay, 2);
00829         debug(1, "Switch display of CONTROL\n");
00830         break;
00831       case 'd':
00832         SWITCH_BIT(config.DoNotDisplay, 3);
00833         debug(1, "Switch display of DATA\n");
00834         break;
00835       case 's':
00836         SWITCH_BIT(config.DoNotDisplay, 4);
00837         debug(1, "Switch display of STATION\n");
00838         break;
00839       default:
00840         CLEAR_KEYBOARD_BUFFER;
00841         break;
00842       }
00843       CLEAR_KEYBOARD_BUFFER;
00844       break;
00845     default:
00846       CLEAR_KEYBOARD_BUFFER;
00847       break;
00848     }
00849     break;
00850   case 3:
00851     break;
00852   case 4:
00853     // Sequence : C??C
00854     // Change channel to a fixed channel
00855     if (keystring[0] == 'c' && keystring[3] == 'c') {
00856       keystring[3] = '\0';
00857       register int chan = 0;
00858 
00859       if (keystring[1] == '0')
00860         chan = atoi(keystring + 2);
00861       else
00862         chan = atoi(keystring + 1);
00863 
00864       if (chan >= 0 && chan < CHANNEL_MAX) {
00865         config.SingleChannel = (UINT8) chan;
00866         selectChannel(config.devname, config.SingleChannel);
00867         memset(keystring, 0, KEYBOARD_BUFFER);
00868         keyindex = 0;
00869       }
00870       debug(2, "Scan only channel %d\n", config.SingleChannel);
00871     } else {
00872       CLEAR_KEYBOARD_BUFFER;
00873     }
00874     break;
00875   default:                     // the user hit the keyboard, but don't know what he do
00876     CLEAR_KEYBOARD_BUFFER;      // So we think that it was sleeping  ;-) and forget ...
00877     break;
00878   }
00879 }

Generated on Fri Feb 25 12:02:37 2005 for WifiScanner by  doxygen 1.4.1