Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

snort.c

Go to the documentation of this file.
00001 /* $Id$ */
00002 /*
00003 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
00004 **
00005 ** This program is free software; you can redistribute it and/or modify
00006 ** it under the terms of the GNU General Public License as published by
00007 ** the Free Software Foundation; either version 2 of the License, or
00008 ** (at your option) any later version.
00009 **
00010 ** This program is distributed in the hope that it will be useful,
00011 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 ** GNU General Public License for more details.
00014 **
00015 ** You should have received a copy of the GNU General Public License
00016 ** along with this program; if not, write to the Free Software
00017 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018 */
00019 
00020 
00021 /* Oct. 3, 2005 -  Per the GPL (2.0), this code has been modified by NitroSecurity,
00022 and in keeping with the GPL, NitroSecurity releases these changes under version 2 
00023 of the GPL. Also, as per version 2 of the GPL, there is no expressed or implied warranty.
00024 If this code decides to have your computer for lunch, it's your problem, not ours.
00025 This code is in working development, and as such is unsuitable for most anything.
00026 NitroSecurity - Dave Remien */
00027 
00028 
00029 
00030 /*
00031  *
00032  * Program: Snort
00033  *
00034  * Purpose: Check out the README file for info on what you can do
00035  *          with Snort.
00036  *
00037  * Author: Martin Roesch (roesch@clark.net)
00038  *
00039  * Comments: Ideas and code stolen liberally from Mike Borella's IP Grab
00040  *           program. Check out his stuff at http://www.borella.net.  I
00041  *           also have ripped some util functions from TCPdump, plus Mike's
00042  *           prog is derived from it as well.  All hail TCPdump....
00043  *
00044  */
00045 
00046 /*  I N C L U D E S  **********************************************************/
00047 #ifdef HAVE_CONFIG_H
00048 #include "config.h"
00049 #endif
00050 
00051 #include <errno.h>
00052 #include <sys/types.h>
00053 #include <stdlib.h>
00054 #include <unistd.h>
00055 #include <string.h>
00056 #ifdef TIMESTATS
00057 #include <signal.h> /* added for new hourly stats function in util.c */
00058 #include <time.h>   /* added for new time stats function in util.c */
00059 #endif
00060 #ifdef HAVE_STRINGS_H
00061 #include <strings.h>
00062 #endif
00063 #include <sys/stat.h>
00064 #ifndef WIN32
00065 #include <grp.h>
00066 #include <pwd.h>
00067 #include <sys/socket.h>
00068 #include <netinet/in.h>
00069 #include <arpa/inet.h>
00070 #endif  /* !WIN32 */
00071 #include <timersub.h>
00072 
00073 #include "snort.h"
00074 #include "rules.h"
00075 #include "plugbase.h"
00076 #include "signal.h"
00077 #include "debug.h"
00078 #include "util.h"
00079 #include "parser.h"
00080 #include "tag.h"
00081 #include "log.h"
00082 #include "detect.h"
00083 #include "mstring.h"
00084 #include "fpcreate.h"
00085 #include "fpdetect.h"
00086 #include "sfthreshold.h"
00087 #include "packet_time.h"
00088 #include "src/preprocessors/flow/flow_print.h"
00089 #include "src/detection-plugins/sp_flowbits.h"
00090 #include "src/preprocessors/spp_perfmonitor.h"
00091 #include "src/preprocessors/spp_bait_and_switch.h"
00092 
00093 #ifdef HAVE_LIBPRELUDE
00094  #include "src/output-plugins/spo_alert_prelude.h"
00095 #endif
00096 
00097 #include "event_queue.h"
00098 #include "asn1.h"
00099 #include "inline.h"
00100 #include "mpse.h"
00101 
00102 #ifndef DLT_LANE8023
00103 /*
00104  * Old OPEN BSD Log format is 17.
00105  * Define DLT_OLDPFLOG unless DLT_LANE8023 (Suse 6.3) is already
00106  * defined in bpf.h.
00107  */
00108 #define DLT_OLDPFLOG 17
00109 #endif
00110 
00111 /*  G L O B A L S  ************************************************************/
00112 extern OutputFuncNode *AlertList;
00113 extern OutputFuncNode *LogList;
00114 #ifdef TIMESTATS
00115 long start_time;    /* tracks how many seconds snort actually ran */
00116 #endif
00117 
00118 extern int errno;
00119 /*extern char *malloc_options;*/
00120 
00121 #ifdef NFNETLINKQ
00122 extern u_int16_t nfqueue_num;
00123 extern struct nfq_handle *nfqh;
00124 extern struct nfq_q_handle *qhndl;
00125 #endif /* NFNETLINKQ */
00126 
00127 /* exported variables *********************************************************/
00128 u_int8_t runMode = 0;   /* snort run mode */
00129 PV pv;                  /* program vars */
00130 int datalink;           /* the datalink value */
00131 char *progname;         /* name of the program (from argv[0]) */
00132 char **progargs;
00133 char *username;
00134 char *groupname;
00135 unsigned long userid = 0;
00136 unsigned long groupid = 0;
00137 struct passwd *pw;
00138 struct group *gr;
00139 char *pcap_cmd;         /* the BPF command string */
00140 char *pktidx;           /* index ptr for the current packet */
00141 pcap_t *pd;             /* pcap handle */
00142 
00143 int g_drop_pkt;        /* inline drop pkt flag */ 
00144 
00145 /* deprecated? */
00146 FILE *alert;            /* alert file ptr */
00147 FILE *binlog_ptr;       /* binary log file ptr */
00148 int flow;               /* flow var (probably obsolete) */
00149 int thiszone;           /* time zone info */
00150 PacketCount pc;         /* packet count information */
00151 u_long netmasks[33];    /* precalculated netmask array */
00152 struct pcap_pkthdr *g_pkthdr;   /* packet header ptr */
00153 u_char *g_pkt;          /* ptr to the packet data */
00154 u_long g_caplen;        /* length of the current packet */
00155 char *protocol_names[256];
00156 u_int snaplen;
00157 
00158 
00159 grinder_t grinder;
00160 runtime_config snort_runtime;   /* run-time configuration struct */
00161 
00162 /*
00163  * you may need to ajust this on the systems which don't have standard
00164  * paths defined
00165  */
00166 #ifndef _PATH_VARRUN
00167 char _PATH_VARRUN[STD_BUF];
00168 #endif
00169 
00170 SFPERF sfPerf;
00171 
00172 /* locally defined functions **************************************************/
00173 static char *ConfigFileSearch();
00174 static int ProcessAlertCommandLine();
00175 static int ProcessLogCommandLine();
00176 static void Restart();
00177 
00178 /* Signal handler declarations ************************************************/
00179 static void SigTermHandler(int signal);
00180 static void SigIntHandler(int signal);
00181 static void SigQuitHandler(int signal);
00182 static void SigHupHandler(int signal);
00183 static void SigUsrHandler(int signal);
00184 
00185 /*
00186  *
00187  * Function: main(int, char *)
00188  *
00189  * Purpose:  Handle program entry and exit, call main prog sections
00190  *           This can handle both regular (command-line) style
00191  *           startup, as well as Win32 Service style startup.
00192  *
00193  * Arguments: See command line args in README file
00194  *
00195  * Returns: 0 => normal exit, 1 => exit on error
00196  *
00197  */
00198 int main(int argc, char* argv[]) 
00199 {
00200 #if defined(WIN32) && defined(ENABLE_WIN32_SERVICE)
00201     /* Do some sanity checking, because some people seem to forget to
00202      * put spaces between their parameters
00203      */
00204     if( argc > 1 &&
00205         ( _stricmp(argv[1], (SERVICE_CMDLINE_PARAM SERVICE_INSTALL_CMDLINE_PARAM))==0   ||
00206           _stricmp(argv[1], (SERVICE_CMDLINE_PARAM SERVICE_UNINSTALL_CMDLINE_PARAM))==0 ||
00207           _stricmp(argv[1], (SERVICE_CMDLINE_PARAM SERVICE_SHOW_CMDLINE_PARAM))==0       ) )
00208     {
00209         FatalError("You must have a space after the '%s' command-line parameter\n",
00210                    SERVICE_CMDLINE_PARAM);
00211         exit(0);
00212     }
00213 
00214     /* If the first parameter is "/SERVICE", then start Snort as a Win32 service */
00215     if( argc>1 && _stricmp(argv[1],SERVICE_CMDLINE_PARAM)==0)
00216     {
00217         return SnortServiceMain(argc, argv);
00218     }
00219 #endif /* WIN32 && ENABLE_WIN32_SERVICE */
00220 
00221     return SnortMain(argc,argv);
00222 }
00223 
00224 /*
00225  *
00226  * Function: SnortMain(int, char *)
00227  *
00228  * Purpose:  The real place that the program handles entry and exit.  Called
00229  *           called by main(), or by SnortServiceMain().
00230  *
00231  * Arguments: See command line args in README file
00232  *
00233  * Returns: 0 => normal exit, 1 => exit on error
00234  *
00235  */
00236 int SnortMain(int argc, char *argv[])
00237 {
00238 #ifndef WIN32
00239     #if defined(LINUX) || defined(FREEBSD) || defined(OPENBSD) || defined(SOLARIS)
00240         sigset_t set;
00241 
00242         sigemptyset(&set);
00243         sigprocmask(SIG_SETMASK, &set, NULL);
00244     #else
00245         sigsetmask(0);
00246     #endif
00247 #endif  /* !WIN32 */
00248 
00249     /*    malloc_options = "AX";*/
00250 
00251     /* Make this prog behave nicely when signals come along.
00252      * Windows doesn't like all of these signals, and will
00253      * set errno for some.  Ignore/reset this error so it
00254      * doesn't interfere with later checks of errno value.
00255      */
00256     signal(SIGTERM, SigTermHandler);    if(errno!=0) errno=0;
00257     signal(SIGINT, SigIntHandler);      if(errno!=0) errno=0;
00258     signal(SIGQUIT, SigQuitHandler);    if(errno!=0) errno=0;
00259     signal(SIGHUP, SigHupHandler);      if(errno!=0) errno=0;
00260     signal(SIGUSR1, SigUsrHandler);    if(errno!=0) errno=0;
00261     signal(SIGNAL_SNORT_ROTATE_STATS, SigUsrHandler);
00262                                         if(errno!=0) errno=0;
00263 
00264     /*
00265      * set a global ptr to the program name so other functions can tell what
00266      * the program name is
00267      */
00268     progname = argv[0];
00269     progargs = argv;
00270 
00271 #ifdef WIN32
00272     if (!init_winsock())
00273         FatalError("Could not Initialize Winsock!\n");
00274 #endif
00275 
00276     memset(&pv, 0, sizeof(PV));
00277     
00278     /*
00279      * setup some lookup data structs
00280      */
00281     InitNetmasks();
00282     InitProtoNames();
00283 
00284     /*
00285     **  This intializes the detection engine for later configuration
00286     */
00287     /* TODO: only do this when we know we are going into IDS mode */
00288     fpInitDetectionEngine();
00289 
00290     /* initialize the packet counter to loop forever */
00291     pv.pkt_cnt = -1;
00292 
00293     /* set the alert filename to NULL */
00294     pv.alert_filename = NULL;
00295 
00296     /* set the default alert mode */
00297     pv.alert_mode = ALERT_FULL;
00298 
00299     /* set the default assurance mode (used with stream 4) */
00300     pv.assurance_mode = ASSURE_ALL;
00301 
00302     pv.use_utc = 0;
00303 
00304     pv.log_mode = 0;
00305 
00306     /*
00307      * provide (limited) status messages by default
00308      */
00309     pv.quiet_flag = 0;
00310 
00311     /* initialize "rotate performance stats file" flag */
00312     pv.rotate_perf_file = 0;
00313 
00314     InitDecoderFlags();
00315     
00316     /* turn on checksum verification by default */
00317     pv.checksums_mode = DO_IP_CHECKSUMS | DO_TCP_CHECKSUMS |
00318                         DO_UDP_CHECKSUMS | DO_ICMP_CHECKSUMS;
00319 
00320     /* Default event log ID of instance 0 on CPU 0 */
00321     pv.event_log_id = 0x0000;
00322 
00323 #if defined(WIN32) && defined(ENABLE_WIN32_SERVICE)
00324     /* initialize flags which control the Win32 service */
00325     pv.terminate_service_flag = 0;
00326     pv.pause_service_flag = 0;
00327 #endif  /* WIN32 && ENABLE_WIN32_SERVICE */
00328 
00329     /* chew up the command line */
00330     ParseCmdLine(argc, argv);
00331 
00332     /* If we are running non-root, install a dummy handler instead. */
00333     if (userid != 0)
00334         signal(SIGHUP, SigCantHupHandler);
00335     
00336     /* determine what run mode we are going to be in */
00337     if(pv.test_mode_flag)
00338     {
00339         if(!pv.quiet_flag)
00340         {
00341             if (pv.config_file)
00342                 LogMessage("Running in Test mode with config file: %s\n",
00343                     pv.config_file);
00344             else if((pv.config_file = ConfigFileSearch()))
00345                 LogMessage("Running in Test mode with inferred config file: %s\n",
00346                     pv.config_file);
00347         }
00348     }
00349 
00350     if(pv.config_file)
00351     {
00352         runMode = MODE_IDS;
00353         if(!pv.quiet_flag)
00354             LogMessage("Running in IDS mode\n");
00355     }
00356     else if(pv.log_mode || pv.log_dir)
00357     {
00358         runMode = MODE_PACKET_LOG;
00359         if(!pv.quiet_flag)
00360             LogMessage("Running in packet logging mode\n");
00361     }
00362     else if(pv.verbose_flag)
00363     {
00364         runMode = MODE_PACKET_DUMP;
00365         if(!pv.quiet_flag)
00366             LogMessage("Running in packet dump mode\n");
00367     }
00368     else if((pv.config_file = ConfigFileSearch()))
00369     {
00370         runMode = MODE_IDS;
00371         if(!pv.quiet_flag)
00372             LogMessage("Running in IDS mode with inferred config file: %s\n",
00373                     pv.config_file);
00374     }
00375     else
00376     {
00377         /* unable to determine a run mode */
00378         DisplayBanner();
00379         ShowUsage(progname);
00380         PrintError("\n\nUh, you need to tell me to do something...\n\n");
00381         exit(1);
00382     }
00383         
00384     /* set the default logging dir if not set yet */
00385     /* XXX should probably be done after reading config files */
00386     if(!pv.log_dir)
00387     {
00388         if(!(pv.log_dir = strdup(DEFAULT_LOG_DIR)))
00389             FatalError("Out of memory setting default log dir\n");
00390     }
00391     
00392     /*
00393     **  Validate the log directory for logging packets
00394     */
00395     /* 
00396      * MFR - 16/9/05 Changing to call CheckLogDir only in logger mode so
00397      * we don't bail by accident if there's a logdir config option in the
00398      * snort.conf file
00399      */
00400     if(runMode == MODE_PACKET_LOG)
00401     {
00402         CheckLogDir();
00403     
00404         if(!pv.quiet_flag)
00405         {
00406             LogMessage("Log directory = %s\n", pv.log_dir);
00407         }
00408     }
00409 
00410     /* if we are in packet log mode, make sure we have a logging mode set */
00411     if(runMode == MODE_PACKET_LOG && !pv.log_mode)
00412     {
00413         /* MFR - 16/9/05 Changing default logging mode to PCAP */
00414         pv.log_mode = LOG_PCAP;
00415     }
00416     
00417     /*
00418      * if we're not reading packets from a file, open the network interface
00419      * for reading.. (interfaces are being initalized before the config file
00420      * is read, so some plugins would be able to start up properly.
00421      */
00422 #ifdef GIDS
00423 #ifdef IPFW
00424     /* Check to see if we got a Divert port or not */
00425     if(!pv.divert_port)
00426     {
00427         pv.divert_port = 8000;
00428     }
00429 
00430     /* Check to see if we got a Reinjection rule or not */
00431     if(!pv.ipfw_reinject_rule)
00432     {
00433         pv.ipfw_reinject_rule = 0;
00434     }
00435 
00436 #endif /* IPFW */
00437 
00438     if (InlineMode())
00439     {
00440         InitInline();
00441     }
00442     else
00443 #endif /* GIDS */
00444 
00445     if(!pv.readmode_flag && !pv.test_mode_flag)
00446     {
00447         DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Opening interface: %s\n", 
00448                     PRINT_INTERFACE(pv.interface)););
00449         /* open up our libpcap packet capture interface */
00450         OpenPcap();
00451     }
00452     else if(!pv.test_mode_flag)
00453     {
00454         DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Opening file: %s\n", 
00455                     pv.readfile););
00456 
00457         /* open the packet file for readback */
00458         OpenPcap();
00459     }
00460 
00461     /* extract the config directory from the config filename */
00462     if(pv.config_file)
00463     {
00464         /* is there a directory seperator in the filename */
00465         if(strrchr(pv.config_file,'/'))
00466         {
00467             char *tmp;
00468             /* lazy way, we waste a few bytes of memory here */
00469             if(!(pv.config_dir = strdup(pv.config_file)))
00470                 FatalError("Out of memory extracting config dir\n");
00471 
00472             tmp = strrchr(pv.config_dir,'/');
00473             *(++tmp) = '\0';
00474         }
00475         else
00476         {
00477 #ifdef WIN32
00478         /* is there a directory seperator in the filename */
00479         if(strrchr(pv.config_file,'\\'))
00480         {
00481             char *tmp;
00482             /* lazy way, we waste a few bytes of memory here */
00483             if(!(pv.config_dir = strdup(pv.config_file)))
00484                 FatalError("Out of memory extracting config dir\n");
00485 
00486             tmp = strrchr(pv.config_dir,'\\');
00487             *(++tmp) = '\0';
00488         }
00489         else
00490 #endif
00491             if(!(pv.config_dir = strdup("./")))
00492                 FatalError("Out of memory extracting config dir\n");
00493         }
00494         DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Config file = %s, config dir = "
00495                     "%s\n", pv.config_file, pv.config_dir););
00496     }
00497 
00498     /* XXX do this after reading the config file? */
00499     if(pv.use_utc == 1)
00500     {
00501         thiszone = 0;
00502     }
00503     else
00504     {
00505         /* set the timezone (ripped from tcpdump) */
00506         thiszone = gmt2local(0);
00507     }
00508 
00509     if(!pv.quiet_flag)
00510     {
00511         LogMessage("\n        --== Initializing Snort ==--\n");
00512     }
00513 
00514     if(runMode == MODE_IDS && pv.rules_order_flag)
00515     {
00516         if(!pv.quiet_flag)
00517         {
00518             LogMessage("Rule application order changed to Pass->Alert->Log\n");
00519         }
00520     }
00521 
00522     /*
00523      * if daemon mode requested, fork daemon first, otherwise on linux
00524      * interface will be reset.
00525      */
00526     if(pv.daemon_flag)
00527     {
00528         DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Entering daemon mode\n"););
00529         openlog("snort", LOG_PID | LOG_CONS, LOG_DAEMON ); 
00530         GoDaemon();
00531     }
00532 
00533 #ifdef TIMESTATS
00534     /*
00535      * Establish a handler for SIGALRM signals
00536      */
00537     signal (SIGALRM, DropHourlyStats);
00538 
00539     /* Set an alarm to go off in approximately one hour... */
00540     alarm(3600);
00541 #endif
00542 
00543     InitOutputPlugins();
00544     
00545     /* create the PID file */
00546     /* TODO should be part of the GoDaemon process */
00547     if((runMode == MODE_IDS) || pv.log_mode || pv.daemon_flag 
00548             || *pv.pidfile_suffix)
00549     {
00550         /* ... then create a PID file if not reading from a file */
00551         if (!pv.readmode_flag && (pv.daemon_flag || *pv.pidfile_suffix))
00552         {
00553 #ifndef WIN32
00554 #ifdef GIDS
00555             if (InlineMode())
00556             {
00557                 CreatePidFile("inline");
00558             }
00559             else
00560             {
00561 #else
00562             CreatePidFile(pv.interface);
00563 #endif /* GIDS */
00564 #ifdef GIDS
00565             }
00566 #endif /* GIDS */
00567 #else
00568             CreatePidFile("WIN32");
00569 #endif
00570         }
00571     }
00572 
00573 
00574     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Setting Packet Processor\n"););
00575 
00576     /* set the packet processor (ethernet, slip, t/r, etc ) */
00577     SetPktProcessor();
00578 
00579     /* if we're using the rules system, it gets initialized here */
00580     if(runMode == MODE_IDS)
00581     {
00582         /* initialize all the plugin modules */
00583         InitPreprocessors();
00584         InitPlugIns();
00585         InitTag();
00586 
00587 #ifdef DEBUG
00588         DumpPreprocessors();
00589         DumpPlugIns();
00590         DumpOutputPlugins();
00591 #endif
00592 
00593         /* setup the default rule action anchor points */
00594         CreateDefaultRules();
00595 
00596         if(pv.rules_order_flag)
00597         {
00598 #ifdef GIDS
00599 #ifndef IPFW
00600             OrderRuleLists("activation dynamic pass drop sdrop reject alert log");
00601 #else
00602             OrderRuleLists("activation dynamic pass drop sdrop reject reinject alert log");
00603 #endif /* IPFW */
00604 #else
00605             if(InlineMode())
00606                 OrderRuleLists("activation dynamic pass drop alert log");
00607             
00608             OrderRuleLists("pass activation dynamic alert log");
00609 #endif /* GIDS */
00610         }
00611 
00612         if(!(pv.quiet_flag && !pv.daemon_flag))
00613             LogMessage("Parsing Rules file %s\n", pv.config_file);
00614 
00615         ParseRulesFile(pv.config_file, 0);
00616     
00617         CheckLogDir();
00618 
00619         OtnXMatchDataInitialize();
00620 
00621         FlowBitsVerify();
00622 
00623         asn1_init_mem(512);
00624 
00625         /*
00626         **  Handles Fatal Errors itself.
00627         */
00628         SnortEventqInit();
00629         
00630 #ifdef GIDS
00631         if (InlineMode())
00632         {
00633             InitInlinePostConfig();
00634         }
00635 #endif /* GIDS */
00636 
00637         if(!(pv.quiet_flag && !pv.daemon_flag))
00638         {
00639             print_thresholding();
00640             printRuleOrder();
00641             LogMessage("Log directory = %s\n", pv.log_dir);
00642         }
00643     }
00644 
00645     
00646 #ifndef WIN32
00647     /* Drop the Chrooted Settings */
00648     if(pv.chroot_dir)
00649         SetChroot(pv.chroot_dir, &pv.log_dir);
00650     
00651     /* Drop privileges if requested, when initialization is done */
00652     SetUidGid();
00653     
00654 #endif /*WIN32*/
00655 
00656 #ifdef HAVE_LIBPRELUDE
00657     AlertPreludeSetupAfterSetuid();
00658 #endif
00659     
00660     /* 
00661      * if we are in IDS mode and either an alert option was specified on the
00662      * command line or we do not have any alert plugins active, set them up
00663      * now
00664      */
00665     if(runMode == MODE_IDS &&
00666        (pv.alert_cmd_override || !pv.alert_plugin_active))
00667     {
00668         ProcessAlertCommandLine();
00669     }
00670 
00671     /* 
00672      * if we are in IDS mode or packet log mode and either a log option was 
00673      * specified on the command line or we do not have any log plugins active, 
00674      * set them up now
00675      */
00676     if((runMode == MODE_IDS || runMode == MODE_PACKET_LOG) &&
00677             (pv.log_cmd_override || !pv.log_plugin_active))
00678     {
00679         ProcessLogCommandLine();
00680     }
00681             
00682     /*
00683     **  Create Fast Packet Classification Arrays
00684     **  from RTN list.  These arrays will be used to
00685     **  classify incoming packets through protocol.
00686     */
00687     fpCreateFastPacketDetection();
00688 
00689     if(!pv.quiet_flag)
00690     {
00691         mpsePrintSummary();
00692     }
00693 
00694     if(!pv.quiet_flag)
00695     {
00696         LogMessage("\n        --== Initialization Complete ==--\n");
00697     }
00698 
00699     /* Tell 'em who wrote it, and what "it" is */
00700     if(!pv.quiet_flag)
00701         DisplayBanner();
00702 
00703     if(pv.test_mode_flag)
00704     {
00705         LogMessage("\nSnort sucessfully loaded all rules and checked all rule "
00706                 "chains!\n");
00707         CleanExit(0);
00708     }
00709 
00710     if(pv.daemon_flag)
00711     {
00712         LogMessage("Snort initialization completed successfully (pid=%u)\n",getpid());
00713     }
00714 
00715 #ifdef TIMESTATS
00716     start_time = time(&start_time); /* start counting seconds */
00717 #endif
00718 
00719 #ifdef GIDS
00720     if (InlineMode())
00721     {
00722 #ifdef NFNETLINKQ
00723         NfnetlinkQLoop();
00724 #else
00725 #ifndef IPFW
00726         IpqLoop();
00727 #else
00728         IpfwLoop();
00729 #endif /* IPFW */
00730 #endif /* NFNETLINKQ */
00731     }
00732     else
00733     {
00734 #endif /* GIDS */
00735 
00736     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Entering pcap loop\n"););
00737 
00738     InterfaceThread(NULL);
00739 
00740 #ifdef GIDS
00741     }
00742 #endif /* GIDS */
00743     
00744     return 0;
00745 }
00746 
00747 /*
00748  */
00749 void PcapProcessPacket(char *user, struct pcap_pkthdr * pkthdr, u_char * pkt)
00750 {
00751     pc.total++;
00752 
00753     /*
00754     ** Save off the time of each and every packet 
00755     */ 
00756     packet_time_update(pkthdr->ts.tv_sec);
00757 
00758 
00759     /* reset the thresholding subsystem checks for this packet */
00760     sfthreshold_reset();
00761 
00762     SnortEventqReset();
00763 
00764 #if defined(WIN32) && defined(ENABLE_WIN32_SERVICE)
00765     if( pv.terminate_service_flag || pv.pause_service_flag )
00766     {
00767         ClearDumpBuf();  /* cleanup and return without processing */
00768         return;
00769     }
00770 #endif  /* WIN32 && ENABLE_WIN32_SERVICE */
00771 
00772     /* Collect some "on the wire" stats about packet size, etc */
00773     UpdateWireStats(&(sfPerf.sfBase), pkthdr->caplen);
00774 
00775     ProcessPacket(user, pkthdr, pkt, NULL);
00776     return;
00777 }
00778 
00779 void ProcessPacket(char *user, struct pcap_pkthdr * pkthdr, u_char * pkt, void *ft)
00780 {
00781     Packet p;
00782 
00783     /* reset the packet flags for each packet */
00784     p.packet_flags = 0;
00785     g_drop_pkt = 0;
00786 
00787     /* call the packet decoder */
00788     (*grinder) (&p, pkthdr, pkt);
00789 
00790     if (ft)
00791     {
00792         p.packet_flags |= PKT_REBUILT_FRAG;
00793         p.fragtracker = ft;
00794     }
00795 
00796     /* print the packet to the screen */
00797     if(pv.verbose_flag)
00798     {
00799         if(p.iph != NULL)
00800             PrintIPPkt(stdout, p.iph->ip_proto, &p);
00801         else if(p.ah != NULL)
00802             PrintArpHeader(stdout, &p);
00803         else if(p.eplh != NULL)
00804         {
00805             PrintEapolPkt(stdout, &p);
00806         }
00807         else if(p.wifih && pv.showwifimgmt_flag)
00808         {
00809             PrintWifiPkt(stdout, &p);
00810         }
00811     }
00812 
00813     switch(runMode)
00814     {
00815         case MODE_PACKET_LOG:
00816             CallLogPlugins(&p, NULL, NULL, NULL);
00817             break;
00818         case MODE_IDS:
00819             /* allow the user to throw away TTLs that won't apply to the
00820                detection engine as a whole. */
00821             if(pv.min_ttl && p.iph != NULL && (p.iph->ip_ttl < pv.min_ttl))
00822             {
00823                 DEBUG_WRAP(DebugMessage(DEBUG_DECODE,
00824                             "MinTTL reached in main detection loop\n"););
00825                 return;
00826             } 
00827             
00828             /* just throw away the packet if we are configured to ignore this port */
00829             if ( p.packet_flags & PKT_IGNORE_PORT )
00830             {
00831                 return;
00832             }
00833 
00834             /* start calling the detection processes */
00835             Preprocess(&p);
00836             break;
00837         default:
00838             break;
00839     }
00840 
00841     ClearDumpBuf();
00842 
00843 }
00844 
00845 
00846 /*
00847  * Function: ShowUsage(char *)
00848  *
00849  * Purpose:  Display the program options and exit
00850  *
00851  * Arguments: progname => name of the program (argv[0])
00852  *
00853  * Returns: 0 => success
00854  */
00855 int ShowUsage(char *progname)
00856 {
00857     fprintf(stdout, "USAGE: %s [-options] <filter options>\n", progname);
00858 #if defined(WIN32) && defined(ENABLE_WIN32_SERVICE)
00859     fprintf(stdout, "       %s %s %s [-options] <filter options>\n", progname
00860                                                                    , SERVICE_CMDLINE_PARAM
00861                                                                    , SERVICE_INSTALL_CMDLINE_PARAM);
00862     fprintf(stdout, "       %s %s %s\n", progname
00863                                        , SERVICE_CMDLINE_PARAM
00864                                        , SERVICE_UNINSTALL_CMDLINE_PARAM);
00865     fprintf(stdout, "       %s %s %s\n", progname
00866                                        , SERVICE_CMDLINE_PARAM
00867                                        , SERVICE_SHOW_CMDLINE_PARAM);
00868 #endif
00869 
00870 #ifdef WIN32
00871     #define FPUTS_WIN32(msg) fputs(msg,stdout)
00872     #define FPUTS_UNIX(msg)  NULL
00873     #define FPUTS_BOTH(msg)  fputs(msg,stdout)
00874 #else
00875     #define FPUTS_WIN32(msg) 
00876     #define FPUTS_UNIX(msg)  fputs(msg,stdout)
00877     #define FPUTS_BOTH(msg)  fputs(msg,stdout)
00878 #endif
00879 
00880     FPUTS_BOTH ("Options:\n");
00881     FPUTS_BOTH ("        -A         Set alert mode: fast, full, console, or none "
00882                                   " (alert file alerts only)\n");
00883     FPUTS_UNIX ("                   \"unsock\" enables UNIX socket logging (experimental).\n");
00884     FPUTS_BOTH ("        -b         Log packets in tcpdump format (much faster!)\n");
00885     FPUTS_BOTH ("        -c <rules> Use Rules File <rules>\n");
00886     FPUTS_BOTH ("        -C         Print out payloads with character data only (no hex)\n");
00887     FPUTS_BOTH ("        -d         Dump the Application Layer\n");
00888     FPUTS_UNIX ("        -D         Run Snort in background (daemon) mode\n");
00889     FPUTS_BOTH ("        -e         Display the second layer header info\n");
00890     FPUTS_WIN32("        -E         Log alert messages to NT Eventlog. (Win32 only)\n");
00891     FPUTS_BOTH ("        -f         Turn off fflush() calls after binary log writes\n");
00892     FPUTS_BOTH ("        -F <bpf>   Read BPF filters from file <bpf>\n");
00893     FPUTS_UNIX ("        -g <gname> Run snort gid as <gname> group (or gid) after initialization\n");
00894     FPUTS_BOTH ("        -G <0xid>  Log Identifier (to uniquely id events for multiple snorts)\n");
00895     FPUTS_BOTH ("        -h <hn>    Home network = <hn>\n");
00896 #ifdef NFNETLINKQ
00897     FPUTS_UNIX ("        -H <q-num> NFNETLINK QUEUE this snort listens on (0-65535) - multiple snorts\n");
00898 #endif /* NFNETLINKQ */
00899     FPUTS_BOTH ("        -i <if>    Listen on interface <if>\n");
00900     FPUTS_BOTH ("        -I         Add Interface name to alert output\n");
00901 #ifdef GIDS
00902 #ifdef IPFW
00903     FPUTS_BOTH ("        -J <port>  ipfw divert socket <port> to listen on vice libpcap (FreeBSD only)\n");
00904 #endif
00905 #endif
00906     FPUTS_BOTH ("        -k <mode>  Checksum mode (all,noip,notcp,noudp,noicmp,none)\n");
00907     FPUTS_BOTH ("        -K <mode>  Logging mode (pcap[default],ascii,none)\n");
00908     FPUTS_BOTH ("        -l <ld>    Log to directory <ld>\n");
00909     FPUTS_BOTH ("        -L <file>  Log to this tcpdump file\n");
00910     FPUTS_UNIX ("        -m <umask> Set umask = <umask>\n");
00911     FPUTS_BOTH ("        -n <cnt>   Exit after receiving <cnt> packets\n");
00912     FPUTS_BOTH ("        -N         Turn off logging (alerts still work)\n");
00913     FPUTS_BOTH ("        -o         Change the rule testing order to Pass|Alert|Log\n");
00914     FPUTS_BOTH ("        -O         Obfuscate the logged IP addresses\n");
00915     FPUTS_BOTH ("        -p         Disable promiscuous mode sniffing\n");
00916     fprintf(stdout, "        -P <snap>  Set explicit snaplen of packet (default: %d)\n",
00917                                     SNAPLEN);
00918     FPUTS_BOTH ("        -q         Quiet. Don't show banner and status report\n");
00919 #ifdef GIDS
00920 #ifndef IPFW
00921     FPUTS_BOTH ("        -Q         Use ip_queue for input vice libpcap (iptables only)\n");
00922 #endif
00923 #endif
00924     FPUTS_BOTH ("        -r <tf>    Read and process tcpdump file <tf>\n");
00925     FPUTS_BOTH ("        -R <id>    Include 'id' in snort_intf<id>.pid file name\n");
00926     FPUTS_BOTH ("        -s         Log alert messages to syslog\n");
00927     FPUTS_BOTH ("        -S <n=v>   Set rules file variable n equal to value v\n");
00928     FPUTS_UNIX ("        -t <dir>   Chroots process to <dir> after initialization\n");
00929     FPUTS_BOTH ("        -T         Test and report on the current Snort configuration\n");
00930     FPUTS_UNIX ("        -u <uname> Run snort uid as <uname> user (or uid) after initialization\n");
00931     FPUTS_BOTH ("        -U         Use UTC for timestamps\n");
00932     FPUTS_BOTH ("        -v         Be verbose\n");
00933     FPUTS_BOTH ("        -V         Show version number\n");
00934     FPUTS_WIN32("        -W         Lists available interfaces. (Win32 only)\n");
00935 #ifdef DLT_IEEE802_11
00936     FPUTS_BOTH ("        -w         Dump 802.11 management and control frames\n");
00937 #endif
00938     FPUTS_BOTH ("        -X         Dump the raw packet data starting at the link layer\n");
00939     FPUTS_BOTH ("        -y         Include year in timestamp in the alert and log files\n");
00940     FPUTS_BOTH ("        -Z         Set the performonitor preprocessor file path and name\n");
00941     FPUTS_BOTH ("        -z         Set assurance mode, match on established sesions (for TCP)\n");
00942     FPUTS_BOTH ("        -?         Show this information\n");
00943     FPUTS_BOTH ("<Filter Options> are standard BPF options, as seen in TCPDump\n");
00944 
00945 #undef FPUTS_WIN32
00946 #undef FPUTS_UNIX
00947 #undef FPUTS_BOTH
00948 
00949     return 0;
00950 }
00951 
00952 
00953 
00954 /*
00955  * Function: ParseCmdLine(int, char *)
00956  *
00957  * Purpose:  Parse command line args
00958  *
00959  * Arguments: argc => count of arguments passed to the routine
00960  *            argv => 2-D character array, contains list of command line args
00961  *
00962  * Returns: 0 => success, 1 => exit on error
00963  */
00964 extern char *optarg;                /* for getopt */
00965 extern int   optind,opterr,optopt;  /* for getopt */
00966 
00967 int ParseCmdLine(int argc, char *argv[])
00968 {
00969     int ch;                         /* storage var for getopt info */
00970     int read_bpf = 0;
00971     char bpf_file[STD_BUF];
00972     char *eq_n;
00973     char *eq_p;
00974     char errorbuf[PCAP_ERRBUF_SIZE];
00975     int umaskchange = 1;
00976     int defumask = 0;
00977 #ifdef WIN32
00978     char *devicet;
00979     int adaplen;
00980 #endif
00981     char *valid_options;
00982 #ifndef WIN32
00983     int i;
00984 #endif
00985     int isName = 0;
00986 
00987     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Parsing command line...\n"););
00988     /* generally speaking, Snort works best when it's in promiscuous mode */
00989     pv.promisc_flag = 1;
00990 
00991     /* just to be sane.. */
00992     username = NULL;
00993     groupname = NULL;
00994     pv.pidfile_suffix[0] = 0;
00995 
00996     /*
00997     **  Set this so we know whether to return 1 on invalid input.
00998     **  Snort uses '?' for help and getopt uses '?' for telling us there
00999     **  was an invalid option, so we can't use that to tell invalid input.
01000     **  Instead, we check optopt and it will tell us.
01001     */
01002     optopt = 0;
01003 
01004 #ifndef WIN32
01005 #ifdef GIDS
01006 #ifndef IPFW
01007 #ifdef NFNETLINKQ
01008     valid_options = "?A:bB:c:CdDefF:g:G:h:H:i:Ik:K:l:L:m:n:NoOpP:qQr:R:sS:t:Tu:UvVwXyzZ:";
01009 #else
01010     valid_options = "?A:bB:c:CdDefF:g:G:h:i:Ik:K:l:L:m:n:NoOpP:qQr:R:sS:t:Tu:UvVwXyzZ:";
01011 #endif /* NFNETLINKQ */
01012 
01013 #else
01014     valid_options = "?A:bB:c:CdDefF:g:G:h:i:IJ:k:K:l:L:m:n:NoOpP:qr:R:sS:t:Tu:UvVwXyzZ:";
01015 #endif /* IPFW */
01016 #else
01017     /* Unix does not support an argument to -s <wink marty!> OR -E, -W */
01018     valid_options = "?A:bB:c:CdDefF:g:G:h:i:Ik:K:l:L:m:n:NoOpP:qQr:R:sS:t:Tu:UvVwXyzZ:";
01019 #endif /* GIDS */
01020 #else
01021     /* Win32 does not support:  -D, -g, -m, -t, -u */
01022     /* Win32 no longer supports an argument to -s, either! */
01023     valid_options = "?A:bB:c:CdeEfF:G:h:i:Ik:K:l:L:n:NoOpP:qr:R:sS:TUvVwWXyzZ:";
01024 #endif
01025 
01026     /* loop through each command line var and process it */
01027     while((ch = getopt(argc, argv, valid_options)) != -1)
01028     {
01029         DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Processing cmd line switch: %c\n", ch););
01030         switch(ch)
01031         {
01032             case 'A':                /* alert mode */
01033                 if(!strcasecmp(optarg, "none"))
01034                 {
01035                     pv.alert_mode = ALERT_NONE;
01036                 }
01037                 else if(!strcasecmp(optarg, "full"))
01038                 {
01039                     pv.alert_mode = ALERT_FULL;
01040                 }
01041                 else if(!strcasecmp(optarg, "fast"))
01042                 {
01043                     pv.alert_mode = ALERT_FAST;
01044                 }
01045                 else if(!strcasecmp(optarg, "console"))
01046                 {
01047                     pv.alert_mode = ALERT_STDOUT;
01048                 }
01049                 else if(!strcasecmp(optarg, "cmg"))
01050                 {
01051                     pv.alert_mode = ALERT_CMG;
01052                     /* turn off logging */
01053                     pv.log_mode = LOG_NONE;
01054                     pv.log_cmd_override = 1;
01055                     /* turn on layer2 headers */
01056                     pv.show2hdr_flag = 1;
01057                     /* turn on data dump */
01058                     pv.data_flag = 1;
01059                 }
01060                 else if(!strcasecmp(optarg, "unsock"))
01061                 {
01062                     pv.alert_mode = ALERT_UNSOCK;
01063                 }
01064                 else
01065                 {
01066                     FatalError("Unknown command line alert option: %s\n", optarg);
01067                 }
01068 
01069                 /* command line alert machanism has been specified, override 
01070                  * the config file options 
01071                  */ 
01072                 pv.alert_cmd_override = 1;
01073                 break;
01074 
01075             case 'b':                /* log packets in binary format for
01076                                       * post-processing */
01077                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Tcpdump logging mode "
01078                             "active\n"););
01079                 pv.log_mode = LOG_PCAP;
01080                 pv.log_cmd_override = 1;
01081                 break;
01082 
01083             case 'B': /* obfuscate with a substitution mask */
01084                 pv.obfuscation_flag = 1;
01085                 GenObfuscationMask(optarg);
01086                 break;
01087 
01088             case 'c':                /* use configuration file x */
01089                 if(!(pv.config_file = strdup(optarg)))
01090                     FatalError("Out of memory processing command line\n");
01091                 break;
01092 
01093             case 'C':  /* dump the application layer as text only */
01094                 pv.char_data_flag = 1;
01095                 break;
01096 
01097             case 'd':                /* dump the application layer data */
01098                 pv.data_flag = 1;
01099                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Data Flag active\n"););
01100                 break;
01101 
01102             case 'D':                /* daemon mode */
01103 #ifdef WIN32
01104                 FatalError("Setting the Daemon mode is not supported in the "
01105                            "WIN32 port of snort!  Use 'snort /SERVICE ...' "
01106                            "instead\n");
01107 #endif
01108                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Daemon mode flag set\n"););
01109                 pv.daemon_flag = 1;
01110                 flow_set_daemon();
01111                 pv.quiet_flag = 1;
01112                 if (pv.test_mode_flag)
01113                 {
01114                     FatalError("Cannot use test mode and daemon mode together."
01115                             "\nTo verify configuration run first in test "
01116                             "mode and then restart in daemon mode\n");
01117                 }
01118                 break;
01119 
01120             case 'e':                /* show second level header info */
01121                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Show 2nd level active\n"););
01122                 pv.show2hdr_flag = 1;
01123                 break;
01124 
01125 #ifdef WIN32
01126             case 'E':                /* log alerts to Event Log */
01127                 pv.alert_mode = ALERT_SYSLOG;
01128                 pv.syslog_remote_flag = 0;
01129                 pv.alert_cmd_override = 1;
01130                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Logging alerts to Event "
01131                             "Log\n"););
01132                 break;
01133 #endif
01134             case 'f':
01135                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Pcap linebuffering "
01136                             "activated\n"););
01137                 pv.line_buffer_flag = 1;
01138                 break;
01139 
01140             case 'F':                /* read BPF filter in from a file */
01141                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Tcpdump logging mode "
01142                             "active\n"););
01143                 strlcpy(bpf_file, optarg, STD_BUF);
01144                 read_bpf = 1;
01145                 break;
01146 
01147             case 'g':                /* setgid handler */
01148 #ifdef WIN32
01149                 FatalError("Setting the group id is not supported in the WIN32 port of snort!\n");
01150 #else
01151                 if(groupname != NULL)
01152                     free(groupname);
01153                 if((groupname = calloc(strlen(optarg) + 1, 1)) == NULL)
01154                     FatalPrintError("malloc");
01155 
01156                 bcopy(optarg, groupname, strlen(optarg));
01157 
01158                 isName = 0;
01159                 for (i=0;i<strlen(groupname);i++)
01160                 {
01161                     if (isdigit(groupname[i]) == 0)
01162                     {
01163                         isName = 1;
01164                         break;
01165                     }
01166                 }
01167                 if (((groupid = atoi(groupname)) == 0) || isName)
01168                 {
01169                     gr = getgrnam(groupname);
01170                     if(gr == NULL)
01171                         FatalError("Group \"%s\" unknown\n", groupname);
01172 
01173                     groupid = gr->gr_gid;
01174                 }
01175 #endif
01176                 break;
01177 
01178             case 'G':                /* snort loG identifier */
01179                 if (!strncmp(optarg, "0x", 2))
01180                 {
01181                     if (!sscanf(optarg, "0x%x", &pv.event_log_id))
01182                     {
01183                         pv.event_log_id = 0;
01184                     }
01185                 }
01186                 else
01187                 {
01188                     char *endPtr;
01189                     pv.event_log_id = strtoul(optarg, &endPtr, 0);
01190                     if (endPtr == optarg)
01191                     {
01192                         FatalError("Snort log identifier invalid: %s\n",
01193                                 optarg);
01194                     }
01195                 }
01196                 if (pv.event_log_id > 0xFFFF)
01197                 {
01198                     FatalError("Snort log identifier invalid: %d.  It must "
01199                                "be no larger than a 2 byte value\n",
01200                                pv.event_log_id);
01201                 }
01202                 else
01203                 {
01204                     u_int32_t id = pv.event_log_id;
01205                     pv.event_log_id = id << 16;
01206                 }
01207                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Log ID: 0x%x\n", pv.event_log_id););
01208                 break;
01209 
01210             case 'h':                /* set home network to x, this will help
01211                                       * determine what to set logging diectories
01212                                       * to */
01213                 GenHomenet(optarg);
01214                 break;
01215 
01216 #ifdef NFNETLINKQ
01217             case 'H':
01218                 nfqueue_num = 0;
01219                 nfqueue_num = atoi(optarg) % 65536;
01220                 break;
01221 #endif /* NFNETLINKQ */
01222 
01223             case 'i':
01224                 if(pv.interface)
01225                 {
01226                     FatalError("Cannot specify more than one network "
01227                                "interface on the command line.\n");
01228                 }
01229 #ifdef WIN32
01230                 /* first, try to handle the "-i1" case, where an interface
01231                  * is specified by number.  If this fails, then fall-through
01232                  * to the case outside the ifdef/endif, where an interface
01233                  * can be specified by its fully qualified name, like as is
01234                  * shown by running 'snort -W', ie.
01235                  * "\Device\Packet_{12345678-90AB-CDEF-1234567890AB}"
01236                  */
01237                 devicet = NULL;
01238                 adaplen = atoi(optarg);
01239                 if( adaplen > 0 )
01240                 {
01241                     devicet = pcap_lookupdev(errorbuf);
01242                     if ( devicet == NULL )
01243                     {
01244                         perror(errorbuf);
01245                         exit(1);
01246                     }
01247 
01248                     pv.interface = GetAdapterFromList(devicet, adaplen);
01249                     if ( pv.interface == NULL )
01250                     {
01251                         LogMessage("Invalid interface '%d'.\n", atoi(optarg));
01252                         exit(1);
01253                     }
01254 
01255 
01256                     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Interface = %s\n",
01257                                 PRINT_INTERFACE(pv.interface)));
01258                 }
01259                 else
01260 #endif  /* WIN32 */
01261                 /* this code handles the case in which the user specifies
01262                    the entire name of the interface and it is compiled
01263                    regardless of which OS you have */
01264                 {
01265                     pv.interface = (char *)malloc(strlen(optarg) + 1);
01266                     /* XXX OOM check */
01267                     strlcpy(pv.interface, optarg, strlen(optarg)+1);
01268                     DEBUG_WRAP(DebugMessage(DEBUG_INIT,
01269                         "Interface = %s\n",
01270                         PRINT_INTERFACE(pv.interface)););
01271                 }
01272                 break;
01273 
01274             case 'I':       /* add interface name to alert string */
01275                 pv.alert_interface_flag = 1;
01276                 break;
01277 
01278 #ifdef GIDS
01279 #ifdef IPFW
01280             case 'J':
01281                 LogMessage("Reading from ipfw divert socket\n");
01282                 pv.inline_flag = 1;
01283                 pv.divert_port = atoi(optarg);
01284                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Divert port set to: %d\n", pv.divert_port););
01285                 LogMessage("IPFW Divert port set to: %d\n", pv.divert_port);
01286                 pv.promisc_flag = 0;
01287                 pv.interface = NULL;
01288                 break;
01289 #endif
01290 #endif
01291 
01292 
01293             case 'k':  /* set checksum mode */
01294                 if(!strcasecmp(optarg, "all"))
01295                 {
01296                     pv.checksums_mode = DO_IP_CHECKSUMS | DO_TCP_CHECKSUMS |
01297                                         DO_UDP_CHECKSUMS | DO_ICMP_CHECKSUMS;
01298                 }
01299                 else if(!strcasecmp(optarg, "noip")) 
01300                 {
01301                     pv.checksums_mode ^= DO_IP_CHECKSUMS;
01302                 }
01303                 else if(!strcasecmp(optarg, "notcp"))
01304                 {
01305                     pv.checksums_mode ^= DO_TCP_CHECKSUMS;
01306                 }
01307                 else if(!strcasecmp(optarg, "noudp"))
01308                 {
01309                     pv.checksums_mode ^= DO_UDP_CHECKSUMS;
01310                 }
01311                 else if(!strcasecmp(optarg, "noicmp"))
01312                 {
01313                     pv.checksums_mode ^= DO_ICMP_CHECKSUMS;
01314                 }
01315                 if(!strcasecmp(optarg, "none"))
01316                 {
01317                     pv.checksums_mode = 0;
01318                 }
01319                 break;
01320 
01321             case 'K':                /* log mode */
01322                 if(!strcasecmp(optarg, "none"))
01323                 {
01324                     pv.log_mode = LOG_NONE;
01325                     pv.log_cmd_override = 1;
01326                 }
01327                 else if(!strcasecmp(optarg, "pcap"))
01328                 {
01329                     pv.log_mode = LOG_PCAP;
01330                     pv.log_cmd_override = 1;
01331                 }
01332                 else if(!strcasecmp(optarg, "ascii"))
01333                 {
01334                     pv.log_mode = LOG_ASCII;
01335                     pv.log_cmd_override = 1;
01336                 }
01337                 else
01338                 {
01339                     FatalError("Unknown command line log option: %s\n", optarg);
01340                 }
01341                 break;
01342 
01343             case 'l':                /* use log dir <X> */
01344                 if(!(pv.log_dir = strdup(optarg)))
01345                 {
01346                     FatalError("Out of memory processing command line\n");
01347                 }
01348 
01349                 if(access(pv.log_dir, 2) != 0)
01350                 {
01351                     FatalError("log directory '%s' does not exist\n", 
01352                             pv.log_dir);
01353                 }
01354                 break;
01355 
01356             case 'L':  /* set BinLogFile name */
01357                 /* implies tcpdump format logging */
01358                 if (strlen(optarg) < 256)
01359                 {
01360                     pv.log_mode = LOG_PCAP;
01361                     pv.binLogFile = strdup(optarg);
01362                     pv.log_cmd_override = 1;
01363                 }
01364                 else
01365                 {
01366                     FatalError("ParseCmdLine, log file: %s, > than 256 characters\n",
01367                                optarg);
01368                 }             
01369                 break;
01370 
01371             case 'm': /* set the umask for the output files */
01372 #ifdef WIN32
01373                 FatalError("Setting the umask is not supported in the "
01374                            "WIN32 port of snort!\n");
01375 #endif
01376                 {
01377                     char *p;
01378                     long val = 0;
01379 
01380                     umaskchange = 0;
01381 
01382                     val = strtol(optarg, &p, 8);
01383                     if (*p != '\0' || val < 0 || (val & ~FILEACCESSBITS))
01384                     {
01385                         FatalError("bad umask %s\n", optarg);
01386                     }
01387                     else
01388                     {
01389                         defumask = val;
01390                     }
01391                 }
01392                 break;
01393 
01394             case 'n':                /* grab x packets and exit */
01395                 pv.pkt_cnt = atoi(optarg);
01396                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Exiting after %d packets\n", pv.pkt_cnt););
01397                 break;
01398 
01399             case 'N':                /* no logging mode */
01400                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Logging deactivated\n"););
01401                 pv.log_mode = LOG_NONE;
01402                 pv.log_cmd_override = 1;
01403                 break;
01404 
01405             case 'o': /* change the rules processing order to
01406                        * passlist first */
01407                 pv.rules_order_flag = 1;
01408                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Rule application order changed to Pass->Alert->Log\n"););
01409                 break;
01410 
01411             case 'O':  /* obfuscate the logged IP addresses for
01412                         * privacy */
01413                 pv.obfuscation_flag = 1;
01414                 break;
01415 
01416             case 'p':  /* disable explicit promiscuous mode */
01417                 pv.promisc_flag = 0;
01418                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Promiscuous mode disabled!\n"););
01419                 break;
01420 
01421             case 'P':  /* explicitly define snaplength of packets */
01422                 pv.pkt_snaplen = atoi(optarg);
01423                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Snaplength of Packets set to: %d\n", pv.pkt_snaplen););
01424                 break;
01425 
01426             case 'q':  /* no stdout output mode */
01427                 pv.quiet_flag = 1;
01428                 break;
01429 
01430             case 'Q':
01431                 LogMessage("Reading from iptables\n");
01432                 pv.inline_flag = 1;
01433                 break;
01434 
01435             case 'r':  /* read packets from a TCPdump file instead
01436                         * of the net */
01437                 strlcpy(pv.readfile, optarg, STD_BUF);
01438                 pv.readmode_flag = 1;
01439                 if(argc == 3)
01440                 {
01441                     LogMessage("No run mode specified, defaulting to verbose mode\n");
01442                     pv.verbose_flag = 1;
01443                     pv.data_flag = 1;
01444                 }
01445                 break;
01446 
01447             case 'R': /* augment pid file name CPW*/
01448                 if (strlen(optarg) < MAX_PIDFILE_SUFFIX && strlen(optarg) > 0)
01449                 {
01450                     if (!strstr(optarg, "..") && !(strstr(optarg, "/")))
01451                     {
01452                         snprintf(pv.pidfile_suffix, MAX_PIDFILE_SUFFIX, "%s",
01453                                 optarg);
01454                     }
01455                     else
01456                     {
01457                         FatalError("ERROR: illegal pidfile suffix: %s\n",
01458                                 optarg);
01459                     }
01460                 }
01461                 else
01462                 {
01463                     FatalError("ERROR: pidfile suffix length problem: %d\n",
01464                             strlen(optarg) );
01465                 }
01466                 break;
01467 
01468             case 's':  /* log alerts to syslog */
01469                 pv.alert_mode = ALERT_SYSLOG;
01470 #ifndef WIN32
01471                 /* command line alerting option has been specified, 
01472                  * override the alert options in the config file
01473                  */ 
01474                 pv.alert_cmd_override = 1;
01475 #else
01476                 pv.alert_cmd_override = 0;
01477                 pv.syslog_remote_flag = 1;
01478 #endif
01479                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Logging alerts to "
01480                             "syslog\n"););
01481                 break;
01482 
01483             case 'S':  /* set a rules file variable */
01484                 if((eq_p = strchr(optarg, '=')) != NULL)
01485                 {
01486                     struct VarEntry *p;
01487                     int namesize = eq_p-optarg;
01488                     eq_n = calloc(namesize+2, sizeof(char));
01489                     strlcpy(eq_n, optarg, namesize+1);
01490                     p = VarDefine(eq_n, eq_p + 1);
01491                     p->flags |= VAR_STATIC;
01492                     free(eq_n);
01493                 }
01494                 else
01495                 {
01496                     FatalError("Format for command line variable definitions "
01497                                "is:\n -S var=value\n");
01498                 }
01499                 break;
01500 
01501             case 't':  /* chroot to the user specified directory */
01502 #ifdef WIN32
01503                 FatalError("Setting the chroot directory is not supported in "
01504                            "the WIN32 port of snort!\n");
01505 #endif  /* WIN32 */
01506                 if(!(pv.chroot_dir = strdup(optarg)))
01507                     FatalError("Out of memory processing command line\n");
01508                 break;
01509 
01510             case 'T': /* test mode, verify that the rules load properly */
01511                 pv.test_mode_flag = 1;
01512                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Snort starting in test mode...\n"););
01513                 if (pv.daemon_flag)
01514                 {
01515                     FatalError("Cannot use test mode and daemon mode together."
01516                             "\nTo verify configuration run first in test "
01517                             "mode and then restart in daemon mode\n");
01518                 }
01519                 break;    
01520 
01521             case 'u':  /* setuid */
01522 #ifdef WIN32
01523                 FatalError("Setting the user id is not "
01524                            "supported in the WIN32 port of snort!\n");
01525 #else
01526                 if((username = calloc(strlen(optarg) + 1, 1)) == NULL)
01527                     FatalPrintError("malloc");
01528 
01529                 bcopy(optarg, username, strlen(optarg));
01530 
01531                 isName = 0;
01532                 for (i=0;i<strlen(username);i++)
01533                 {
01534                     if (isdigit(username[i]) == 0)
01535                     {
01536                         isName = 1;
01537                         break;
01538                     }
01539                 }
01540 
01541                 if (((userid = atoi(username)) == 0) || isName)
01542                 {
01543                     pw = getpwnam(username);
01544                     if(pw == NULL)
01545                         FatalError("User \"%s\" unknown\n", username);
01546 
01547                     userid = pw->pw_uid;
01548                 }
01549                 else
01550                 {
01551                     pw = getpwuid(userid);
01552                     if(pw == NULL)
01553                         FatalError(
01554                                 "Can not obtain username for uid: %lu\n",
01555                                 (u_long) userid);
01556                 }
01557 
01558                 if(groupname == NULL)
01559                 {
01560                     char name[256];
01561 
01562                     snprintf(name, 255, "%lu", (u_long) pw->pw_gid);
01563 
01564                     if((groupname = calloc(strlen(name) + 1, 1)) == NULL)
01565                     {
01566                         FatalPrintError("malloc");
01567                     }
01568                     groupid = pw->pw_gid;
01569                 }
01570                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "UserID: %lu GroupID: %lu\n",
01571                     (unsigned long) userid, (unsigned long) groupid););
01572 #endif  /* !WIN32 */
01573                 break;
01574 
01575             case 'U': /* use UTC */
01576                 pv.use_utc = 1;
01577                 break;
01578 
01579             case 'v': /* be verbose */
01580                 pv.verbose_flag = 1;
01581                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Verbose Flag active\n"););
01582                 break;
01583 
01584             case 'V': /* prog ver already gets printed out, so we
01585                        * just exit */
01586                 DisplayBanner();
01587                 exit(0);
01588 
01589 #ifdef WIN32
01590             case 'W':
01591                 if ((pv.interface = pcap_lookupdev(errorbuf)) == NULL)
01592                     perror(errorbuf);
01593 
01594                 DisplayBanner();
01595                 PrintDeviceList(pv.interface);
01596                 exit(0);
01597                 break;
01598 #endif  /* WIN32 */
01599 
01600 #ifdef DLT_IEEE802_11
01601             case 'w':                /* show 802.11 all frames info */
01602                 pv.showwifimgmt_flag = 1;
01603                 break;
01604 #endif
01605 
01606             case 'X':  /* display verbose packet bytecode dumps */
01607                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Verbose packet bytecode dumps enabled\n"););
01608                 pv.verbose_bytedump_flag = 1;
01609                 break;
01610 
01611             case 'y':  /* Add year to timestamp in alert and log files */
01612                 pv.include_year = 1;
01613                 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Enabled year in timestamp\n"););
01614                 break;
01615 
01616             case 'z': /* set assurance mode (used with stream 4) */
01617                 LogMessage("WARNING: The -z option will be deprecated in the "
01618                            "next release of snort.\n  Use the 'stateful' "
01619                            "configuration option in snort.conf\n");
01620                 pv.assurance_mode = ASSURE_EST;
01621                 break;
01622 
01623             case 'Z': /* Set preprocessor performon file path/filename */
01624                 SetPerfmonitorFile(optarg);
01625                 break;
01626 
01627             case '?':  /* show help and exit with 1 */
01628                 DisplayBanner();
01629                 ShowUsage(progname);
01630 
01631                 if(optopt)
01632                     exit(1);
01633 
01634                 exit(0);
01635         }
01636     }
01637 
01638     /* TODO relocate all of this to later in startup process */
01639 
01640     /* if the umask arg happened, set umask */
01641     if (umaskchange)
01642     {
01643         umask(077);           /* set default to be sane */
01644     }
01645     else
01646     {
01647         umask(defumask);
01648     }
01649 
01650     /* if we're reading in BPF filters from a file */
01651     if(read_bpf)
01652     {
01653         /* suck 'em in */
01654         pv.pcap_cmd = read_infile(bpf_file);
01655     }
01656     else
01657     {
01658         /* set the BPF rules string (thanks Mike!) */
01659         pv.pcap_cmd = copy_argv(&argv[optind]);
01660     }
01661 
01662 #ifndef MUST_SPECIFY_DEVICE    
01663     if((pv.interface == NULL) && !pv.readmode_flag)
01664     {
01665 #ifdef GIDS
01666         if (!InlineMode())
01667         {
01668 #endif /* GIDS */
01669         pv.interface = pcap_lookupdev(errorbuf);
01670 
01671         if(pv.interface == NULL)
01672             FatalError( "Failed to lookup for interface: %s."
01673                     " Please specify one with -i switch\n", errorbuf);
01674         else
01675             LogMessage("***\n*** interface device lookup found: %s\n***\n",pv.interface);
01676 #ifdef GIDS
01677         }
01678 #endif /* GIDS */
01679     }
01680 #else
01681     if((pv.interface == NULL) && !pv.readmode_flag && !pv.test_mode_flag)
01682     {
01683             FatalError( "You must specify a network interface (-i), "
01684                         "a capture file (-r), or the test flag (-T)\n");
01685     }
01686 
01687 #endif    
01688     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "pcap_cmd is %s\n", 
01689                 pv.pcap_cmd !=NULL ? pv.pcap_cmd : "NULL"););
01690     return 0;
01691 }
01692 
01693 /*
01694  * Function: SetPktProcessor()
01695  *
01696  * Purpose:  Set which packet processing function we're going to use based on
01697  *           what type of datalink layer we're using
01698  *
01699  * Arguments: int num => number of interface
01700  *
01701  * Returns: 0 => success
01702  */
01703 int SetPktProcessor()
01704 {
01705 #ifdef GIDS
01706     if (InlineMode())
01707     {
01708 
01709 #ifndef IPFW
01710         if(!pv.quiet_flag)
01711             LogMessage("Setting the Packet Processor to decode packets "
01712                     "from iptables\n");
01713 
01714         grinder = DecodeIptablesPkt;
01715 #else
01716         if(!pv.quiet_flag)
01717             LogMessage("Setting the Packet Processor to decode packets "
01718                     "from ipfw divert\n");
01719 
01720         grinder = DecodeIpfwPkt;
01721 #endif /* IPFW */
01722 
01723         return 0;
01724 
01725     }
01726 #endif /* GIDS */
01727 
01728     switch(datalink)
01729     {
01730         case DLT_EN10MB:        /* Ethernet */
01731             if(!pv.readmode_flag)
01732             {
01733                 if(!pv.quiet_flag)
01734                     LogMessage("Decoding Ethernet on interface %s\n", 
01735                             PRINT_INTERFACE(pv.interface));
01736             }
01737 
01738             grinder = DecodeEthPkt;
01739             break;
01740 
01741 #ifdef DLT_IEEE802_11
01742         case DLT_IEEE802_11:
01743             if (!pv.readmode_flag)
01744             {
01745                 if (!pv.quiet_flag)
01746                     LogMessage("Decoding IEEE 802.11 on interface %s\n",
01747                             PRINT_INTERFACE(pv.interface));
01748             }
01749 
01750             grinder = DecodeIEEE80211Pkt;
01751             break;
01752 #endif
01753 #ifdef DLT_ENC
01754         case DLT_ENC:           /* Encapsulated data */
01755             if (!pv.readmode_flag)
01756             {
01757                 if (!pv.quiet_flag)
01758                     LogMessage("Decoding Encapsulated data on interface %s\n",
01759                            PRINT_INTERFACE(pv.interface));
01760             }
01761 
01762             grinder = DecodeEncPkt;
01763             break;
01764 
01765 #else
01766         case 13:
01767 #endif /* DLT_ENC */
01768         case DLT_IEEE802:                /* Token Ring */
01769             if(!pv.readmode_flag)
01770             {
01771                 if(!pv.quiet_flag)
01772                     LogMessage("Decoding Token Ring on interface %s\n", 
01773                             PRINT_INTERFACE(pv.interface));
01774             }
01775 
01776             grinder = DecodeTRPkt;
01777 
01778             break;
01779 
01780         case DLT_FDDI:                /* FDDI */
01781             if(!pv.readmode_flag)
01782             {
01783                 if(!pv.quiet_flag)
01784                     LogMessage("Decoding FDDI on interface %s\n", 
01785                             PRINT_INTERFACE(pv.interface));
01786             }
01787 
01788             grinder = DecodeFDDIPkt;
01789 
01790             break;
01791 
01792 #ifdef DLT_CHDLC
01793         case DLT_CHDLC:              /* Cisco HDLC */
01794             if (!pv.readmode_flag && !pv.quiet_flag)
01795                 LogMessage("Decoding Cisco HDLC on interface %s\n", 
01796                         PRINT_INTERFACE(pv.interface));
01797 
01798             grinder = DecodeChdlcPkt;
01799 
01800             break;
01801 #endif
01802 
01803         case DLT_SLIP:                /* Serial Line Internet Protocol */
01804             if(!pv.readmode_flag)
01805             {
01806                 if(!pv.quiet_flag)
01807                     LogMessage("Decoding Slip on interface %s\n", 
01808                             PRINT_INTERFACE(pv.interface));
01809             }
01810 
01811             if(pv.show2hdr_flag == 1)
01812             {
01813                 LogMessage("Second layer header parsing for this datalink "
01814                         "isn't implemented yet\n");
01815 
01816                 pv.show2hdr_flag = 0;
01817             }
01818 
01819             grinder = DecodeSlipPkt;
01820 
01821             break;
01822 
01823         case DLT_PPP:                /* point-to-point protocol */
01824             if(!pv.readmode_flag)
01825             {
01826                 if(!pv.quiet_flag)
01827                     LogMessage("Decoding PPP on interface %s\n", 
01828                             PRINT_INTERFACE(pv.interface));
01829             }
01830 
01831             if(pv.show2hdr_flag == 1)
01832             {
01833                 /* do we need ppp header showup? it's only 4 bytes anyway ;-) */
01834                 LogMessage("Second layer header parsing for this datalink "
01835                         "isn't implemented yet\n");
01836                 pv.show2hdr_flag = 0;
01837             }
01838 
01839             grinder = DecodePppPkt;
01840 
01841             break;
01842 
01843 #ifdef DLT_PPP_SERIAL
01844         case DLT_PPP_SERIAL:         /* PPP with full HDLC header*/
01845             if(!pv.readmode_flag)
01846             {
01847                 if(!pv.quiet_flag)
01848                     LogMessage("Decoding PPP on interface %s\n", 
01849                             PRINT_INTERFACE(pv.interface));
01850             }
01851 
01852             if(pv.show2hdr_flag == 1)
01853             {
01854                 /* do we need ppp header showup? it's only 4 bytes anyway ;-) */
01855                 LogMessage("Second layer header parsing for this datalink "
01856                         "isn't implemented yet\n");
01857                 pv.show2hdr_flag = 0;
01858             }
01859 
01860             grinder = DecodePppSerialPkt;
01861 
01862             break;
01863 #endif
01864 
01865 #ifdef DLT_LINUX_SLL
01866         case DLT_LINUX_SLL:
01867             if(!pv.readmode_flag)
01868             {
01869                 if(!pv.quiet_flag)
01870                     LogMessage("Decoding 'ANY' on interface %s\n", 
01871                             PRINT_INTERFACE(pv.interface));
01872             }
01873 
01874             grinder = DecodeLinuxSLLPkt;
01875 
01876             break;
01877 #endif
01878 
01879 #ifdef DLT_PFLOG
01880         case DLT_PFLOG:
01881             if(!pv.readmode_flag)
01882             {
01883                 if(!pv.quiet_flag)
01884                     LogMessage("Decoding OpenBSD PF log on interface %s\n",
01885                             PRINT_INTERFACE(pv.interface));
01886             }
01887 
01888             grinder = DecodePflog;
01889 
01890             break;
01891 #endif
01892 
01893 #ifdef DLT_OLDPFLOG
01894         case DLT_OLDPFLOG:
01895             if(!pv.readmode_flag)
01896             {
01897                 if(!pv.quiet_flag)
01898                     LogMessage("Decoding old OpenBSD PF log on interface %s\n",
01899                             PRINT_INTERFACE(pv.interface));
01900             }
01901 
01902             grinder = DecodeOldPflog;
01903 
01904             break;
01905 #endif
01906 
01907 #ifdef DLT_LOOP
01908         case DLT_LOOP:
01909 #endif
01910         case DLT_NULL:            /* loopback and stuff.. you wouldn't perform
01911                                    * intrusion detection on it, but it's ok for
01912                                    * testing. */
01913             if(!pv.readmode_flag)
01914             {
01915                 if(!pv.quiet_flag)
01916                 {
01917                     LogMessage("Decoding LoopBack on interface %s\n", 
01918                             PRINT_INTERFACE(pv.interface));
01919                 }
01920             }
01921 
01922             if(pv.show2hdr_flag == 1)
01923             {
01924                 LogMessage("Data link layer header parsing for this network "
01925                         " type isn't implemented yet\n");
01926                 pv.show2hdr_flag = 0;
01927             }
01928             grinder = DecodeNullPkt;
01929 
01930             break;
01931 
01932 #ifdef DLT_RAW /* Not supported in some arch or older pcap
01933                 * versions */
01934         case DLT_RAW:
01935             if(!pv.readmode_flag)
01936             {
01937                 if(!pv.quiet_flag)
01938                     LogMessage("Decoding raw data on interface %s\n", 
01939                             PRINT_INTERFACE(pv.interface));
01940             }
01941 
01942             if(pv.show2hdr_flag == 1)
01943             {
01944                 LogMessage("There's no second layer header available for "
01945                         "this datalink\n");
01946                 pv.show2hdr_flag = 0;
01947             }
01948             grinder = DecodeRawPkt;
01949 
01950             break;
01951 #endif
01952             /*
01953              * you need the I4L modified version of libpcap to get this stuff
01954              * working
01955              */
01956 #ifdef DLT_I4L_RAWIP
01957         case DLT_I4L_RAWIP:
01958             if (! pv.readmode_flag && !pv.quiet_flag)
01959                 LogMessage("Decoding I4L-rawip on interface %s\n", 
01960                         PRINT_INTERFACE(pv.interface));
01961 
01962             grinder = DecodeI4LRawIPPkt;
01963 
01964             break;
01965 #endif
01966 
01967 #ifdef DLT_I4L_IP
01968         case DLT_I4L_IP:
01969             if (! pv.readmode_flag && !pv.quiet_flag)
01970                 LogMessage("Decoding I4L-ip on interface %s\n", 
01971                         PRINT_INTERFACE(pv.interface));
01972 
01973             grinder = DecodeEthPkt;
01974 
01975             break;
01976 #endif
01977 
01978 #ifdef DLT_I4L_CISCOHDLC
01979         case DLT_I4L_CISCOHDLC:
01980             if (! pv.readmode_flag && !pv.quiet_flag)
01981                 LogMessage("Decoding I4L-cisco-h on interface %s\n", 
01982                         PRINT_INTERFACE(pv.interface));
01983 
01984             grinder = DecodeI4LCiscoIPPkt;
01985 
01986             break;
01987 #endif
01988 
01989         default:                        /* oops, don't know how to handle this one */
01990             ErrorMessage("\n%s cannot handle data link type %d\n",
01991                     progname, datalink);
01992             CleanExit(1);
01993     }
01994 
01995     return 0;
01996 }
01997 
01998 
01999 /*
02000  * Function: void *InterfaceThread(void *arg)
02001  *
02002  * Purpose: wrapper for pthread_create() to create a thread per interface
02003  */
02004 static struct timeval starttime;
02005 static struct timeval endtime;
02006 void *InterfaceThread(void *arg)
02007 {
02008     struct timezone tz;
02009 
02010     bzero((char *) &tz, sizeof(tz));
02011     gettimeofday(&starttime, &tz);
02012 
02013     /* Read all packets on the device.  Continue until cnt packets read */
02014     if(pcap_loop(pd, pv.pkt_cnt, (pcap_handler) PcapProcessPacket, NULL) < 0)
02015     {
02016         if(pv.daemon_flag)
02017             syslog(LOG_PID | LOG_CONS | LOG_DAEMON,
02018                     "pcap_loop: %s", pcap_geterr(pd));
02019         else
02020             ErrorMessage("pcap_loop: %s\n", pcap_geterr(pd));
02021 
02022         CleanExit(1);
02023     }
02024 
02025     pv.done_processing = 1;
02026 
02027     CleanExit(0);
02028 
02029     return NULL;                /* avoid warnings */
02030 }
02031 
02032 
02033 
02034 /****************************************************************************
02035  *
02036  * Function: OpenPcap(char *, int)
02037  *
02038  * Purpose:  Open the libpcap interface
02039  *
02040  * Arguments: intf => name of the interface to open
02041  *            num  => number of the interface (to fill-in datalink and pd)
02042  *
02043  * Returns: 0 => success, exits on problems
02044  *
02045  ****************************************************************************/
02046 int OpenPcap()
02047 {
02048     bpf_u_int32 localnet, netmask;        /* net addr holders */
02049     struct bpf_program fcode;        /* Finite state machine holder */
02050     char errorbuf[PCAP_ERRBUF_SIZE];        /* buffer to put error strings in */
02051     bpf_u_int32 defaultnet = 0xFFFFFF00;
02052 
02053     /* if we're not reading packets from a file */
02054     if(pv.interface == NULL)
02055     {
02056         if (!pv.readmode_flag)
02057         {
02058             DEBUG_WRAP(DebugMessage(DEBUG_INIT,
02059                     "pv.interface is NULL, looking up interface....   "););
02060             /* look up the device and get the handle */
02061             pv.interface = pcap_lookupdev(errorbuf);
02062     
02063             DEBUG_WRAP(DebugMessage(DEBUG_INIT,
02064                     "found interface %s\n", PRINT_INTERFACE(pv.interface)););
02065             /* uh oh, we couldn't find the interface name */
02066             if(pv.interface == NULL)
02067             {
02068                 FatalError("OpenPcap() interface lookup: \n\t%s\n",
02069                errorbuf);
02070             }
02071         }
02072         else
02073         {
02074             /* interface is null and we are in readmode */
02075             /* some routines would hate it to be NULL */
02076             pv.interface = "[reading from a file]"; 
02077         }
02078     }
02079 
02080     if(!pv.quiet_flag)
02081     {
02082         if (!pv.readmode_flag)
02083             LogMessage("\nInitializing Network Interface %s\n", 
02084                     PRINT_INTERFACE(pv.interface));
02085         else 
02086             LogMessage("TCPDUMP file reading mode.\n");
02087     }
02088 
02089     if (!pv.readmode_flag)
02090     {
02091         if(pv.pkt_snaplen)        /* if it's set let's try it... */
02092         {
02093             if(pv.pkt_snaplen < MIN_SNAPLEN)        /* if it's < MIN set it to
02094                                                      * MIN */
02095             {
02096                 /* XXX: Warning message, specidifed snaplen too small,
02097                  * snaplen set to X
02098                  */
02099                  snaplen = MIN_SNAPLEN;
02100             }
02101             else
02102             {
02103                  snaplen = pv.pkt_snaplen;
02104             }
02105          }
02106          else
02107          {
02108              snaplen = SNAPLEN;        /* otherwise let's put the compiled value in */
02109          }
02110         
02111         DEBUG_WRAP(DebugMessage(DEBUG_INIT,
02112                 "snaplength info: set=%d/compiled=%d/wanted=%d\n",
02113                 snaplen,  SNAPLEN, pv.pkt_snaplen););
02114     
02115         /* get the device file descriptor */
02116         pd = pcap_open_live(pv.interface, snaplen,
02117                 pv.promisc_flag ? PROMISC : 0, READ_TIMEOUT, errorbuf);
02118 
02119     }
02120     else
02121     {   /* reading packets from a file */
02122 
02123         if (!pv.quiet_flag)
02124         {
02125             LogMessage("Reading network traffic from \"%s\" file.\n", 
02126                     pv.readfile);
02127         }
02128         /* open the file */
02129         pd = pcap_open_offline(pv.readfile, errorbuf);
02130 
02131         /* the file didn't open correctly */
02132         if(pd == NULL)
02133         {
02134             FatalError("unable to open file \"%s\" for readback: %s\n",
02135                        pv.readfile, errorbuf);
02136         }
02137         /*
02138          * set the snaplen for the file (so we don't get a lot of extra crap
02139          * in the end of packets
02140          */
02141         snaplen = pcap_snapshot(pd);
02142 
02143         if(!pv.quiet_flag)
02144             LogMessage("snaplen = %d\n", snaplen);
02145     }
02146 
02147     /* something is wrong with the opened packet socket */
02148     if(pd == NULL)
02149     {
02150         if(strstr(errorbuf, "Permission denied"))
02151         {
02152             FatalError("You don't have permission to"
02153                        " sniff.\nTry doing this as root.\n");
02154         }
02155         else
02156         {
02157             FatalError("OpenPcap() device %s open: \n\t%s\n",
02158                        PRINT_INTERFACE(pv.interface), errorbuf);
02159         }
02160     }
02161     /* get local net and netmask */
02162     if(pcap_lookupnet(pv.interface, &localnet, &netmask, errorbuf) < 0)
02163     {
02164        if (!pv.readmode_flag)
02165        {
02166            ErrorMessage("OpenPcap() device %s network lookup: \n"
02167                         "\t%s\n",
02168                         PRINT_INTERFACE(pv.interface), errorbuf);
02169 
02170        }
02171         /*
02172          * set the default netmask to 255.255.255.0 (for stealthed
02173          * interfaces)
02174          */
02175         netmask = htonl(defaultnet);
02176     }
02177     else
02178     {
02179         DefineIfaceVar(PRINT_INTERFACE(pv.interface),
02180                        (u_char *) &localnet, 
02181                        (u_char *) &netmask);
02182     }
02183 
02184     /* compile BPF filter spec info fcode FSM */
02185     if(pcap_compile(pd, &fcode, pv.pcap_cmd, 1, netmask) < 0)
02186     {
02187         FatalError("OpenPcap() FSM compilation failed: \n\t%s\n"
02188                    "PCAP command: %s\n", pcap_geterr(pd), pv.pcap_cmd);
02189     }
02190     /* set the pcap filter */
02191     if(pcap_setfilter(pd, &fcode) < 0)
02192     {
02193         FatalError("OpenPcap() setfilter: \n\t%s\n",
02194                    pcap_geterr(pd));
02195     }
02196     
02197     /* get data link type */
02198     datalink = pcap_datalink(pd);
02199 
02200     if(datalink < 0)
02201     {
02202         FatalError("OpenPcap() datalink grab: \n\t%s\n",
02203                    pcap_geterr(pd));
02204     }
02205     return 0;
02206 }
02207 
02208 
02209 
02210 /* locate one of the possible default config files */
02211 /* allocates memory to hold filename */
02212 static char *ConfigFileSearch()
02213 {
02214     struct stat st;
02215     int i;
02216     char *conf_files[]={"/etc/snort.conf", "./snort.conf", NULL};
02217     char *fname = NULL;
02218     char *home_dir = NULL;
02219     char *rval = NULL;
02220 
02221     i = 0;
02222 
02223     /* search the default set of config files */
02224     while(conf_files[i])
02225     {
02226         fname = conf_files[i];
02227 
02228         if(stat(fname, &st) != -1)
02229         {
02230             if(!(rval = strdup(fname)))
02231                 FatalError("Out of memory searching for config file\n");
02232             break;
02233         }
02234         i++;
02235     }
02236 
02237     /* search for .snortrc in the HOMEDIR */
02238     if(!rval)
02239     {
02240         if((home_dir = getenv("HOME")))
02241         {
02242             /* create the full path */
02243             fname = (char *)malloc(strlen(home_dir) + strlen("/.snortrc") + 1);
02244             if(!fname)
02245                 FatalError("Out of memory searching for config file\n");
02246 
02247             if(stat(fname, &st) != -1)
02248                 rval = fname;
02249             else
02250                 free(fname);
02251         }
02252     }
02253 
02254     return rval;
02255 }
02256 
02257 static int ProcessAlertCommandLine()
02258 {
02259     
02260     if(!pv.alert_cmd_override)
02261     {
02262         /* Setup the default output plugin */
02263         ActivateOutputPlugin("alert_full", NULL);
02264     }
02265     else
02266     {
02267         switch(pv.alert_mode)
02268         {
02269             case ALERT_FAST:
02270                 ActivateOutputPlugin("alert_fast", NULL);
02271                 break;
02272 
02273             case ALERT_FULL:
02274                 ActivateOutputPlugin("alert_full", NULL);
02275                 break;
02276 
02277             case ALERT_NONE:
02278                 SetOutputList(NoAlert, NT_OUTPUT_ALERT, NULL);
02279                 break;
02280 
02281             case ALERT_UNSOCK:
02282                 ActivateOutputPlugin("alert_unixsock", NULL);
02283                 break;
02284 
02285             case ALERT_STDOUT:
02286                 ActivateOutputPlugin("alert_fast", "stdout");
02287                 break;
02288 
02289             case ALERT_CMG:
02290                 ActivateOutputPlugin("alert_fast", "stdout packet");
02291                 break;
02292 
02293             case ALERT_SYSLOG:
02294                 ActivateOutputPlugin("alert_syslog", NULL);
02295                 break;
02296 
02297             default:
02298                 FatalError("Unknown alert mode %u\n", pv.alert_mode);
02299                 break;
02300         }
02301     }
02302 
02303     return 0;
02304 }
02305 
02306 static int ProcessLogCommandLine()
02307 {
02308     if(!pv.log_cmd_override)
02309     {
02310         ActivateOutputPlugin("log_tcpdump", NULL);
02311     }
02312     else
02313     {
02314         switch(pv.log_mode)
02315         {
02316             case LOG_ASCII:
02317                 ActivateOutputPlugin("log_ascii", NULL);
02318                 break;
02319                 
02320             case LOG_PCAP:
02321                 if(pv.binLogFile)
02322                     ActivateOutputPlugin("log_tcpdump", pv.binLogFile);
02323                 else
02324                     ActivateOutputPlugin("log_tcpdump", NULL);
02325                 break;
02326                 
02327             case LOG_NONE:
02328                 SetOutputList(NoLog, NT_OUTPUT_LOG, NULL);
02329                 break;
02330                 
02331             default:
02332                 FatalError("Unknown log mode %u\n", pv.log_mode);
02333         }
02334     }
02335 
02336     return 0;
02337 }
02338 
02339 /* Signal Handlers ************************************************************/
02340 
02341 static void SigTermHandler(int signal)
02342 {
02343     CleanExit(0);
02344 }
02345 
02346 static void SigIntHandler(int signal)
02347 {
02348     CleanExit(0);
02349 }   
02350 
02351 static void SigQuitHandler(int signal)
02352 {
02353     CleanExit(0);
02354 }
02355 
02356 static void SigHupHandler(int signal)
02357 {
02358     Restart();
02359 }
02360 
02361 static void SigUsrHandler(int signal)
02362 {
02363     int quiet_flag;
02364 #ifndef WIN32
02365 #if defined(LINUX) || defined(FREEBSD) || defined(OPENBSD) || defined(SOLARIS)
02366     sigset_t set;
02367 
02368     /* XXX why do we unblock all signals here? */
02369     sigemptyset(&set);
02370     sigprocmask(SIG_SETMASK, &set, NULL);
02371 #else
02372     sigsetmask(0);
02373 #endif
02374 #endif  /* !WIN32 */
02375 
02376     quiet_flag = pv.quiet_flag;
02377     pv.quiet_flag = 0;
02378     
02379     if ( signal == SIGUSR1 )
02380     {
02381         DropStats(0);
02382     }
02383     
02384     else if ( signal == SIGNAL_SNORT_ROTATE_STATS )
02385     {
02386         pv.rotate_perf_file = 1;
02387     }
02388         
02389     pv.quiet_flag = quiet_flag;
02390 }
02391 
02392 /**
02393  * dummy signal handler for nonroot users or chroot.
02394  *
02395  * @param signal signal to exec
02396  */
02397 void SigCantHupHandler(int signal)
02398 {
02399         LogMessage("Reload via Signal HUP does not work if you aren't root or are chroot'ed\n");
02400 }
02401 
02402 /****************************************************************************
02403  *
02404  * Function: CleanExit()
02405  *
02406  * Purpose:  Clean up misc file handles and such and exit
02407  *
02408  * Arguments: exit value;
02409  *
02410  * Returns: void function
02411  *
02412  ****************************************************************************/
02413 extern PluginSignalFuncNode *PluginShutdownList;
02414 extern PluginSignalFuncNode *PluginCleanExitList;
02415 extern PluginSignalFuncNode *PluginRestartList;
02416 
02417 void CleanExit(int exit_val)
02418 {
02419     PluginSignalFuncNode *idx = NULL;
02420 
02421     /* This function can be called more than once.  For example,
02422      * once from the SIGINT signal handler, and once recursively
02423      * as a result of calling pcap_close() below.  We only need
02424      * to perform the cleanup once, however.  So the static
02425      * variable already_exiting will act as a flag to prevent
02426      * double-freeing any memory.  Not guaranteed to be
02427      * thread-safe, but it will prevent the simple cases.
02428      */
02429     static int already_exiting = 0;
02430     if( already_exiting != 0 )
02431     {
02432         return;
02433     }
02434     already_exiting = 1;
02435     /* Do some post processing on any incomplete Plugin Data */
02436     idx = PluginShutdownList;
02437     while(idx)
02438     {
02439         idx->func(SIGQUIT, idx->arg);
02440         idx = idx->next;
02441     }
02442 
02443     if (pv.done_processing)
02444     {
02445         struct timeval difftime;
02446         struct timezone tz;
02447 
02448         bzero((char *) &tz, sizeof(tz));
02449         gettimeofday(&endtime, &tz);
02450 
02451         TIMERSUB(&endtime, &starttime, &difftime);
02452 
02453         printf("Run time for packet processing was %lu.%lu seconds\n", 
02454                 (unsigned long)difftime.tv_sec, (unsigned long)difftime.tv_usec);
02455     }
02456 
02457 #ifdef TIMESTATS
02458     alarm(0);   /* cancel any existing alarm and disable alarm() function */
02459 #endif
02460 
02461     /* Print Statistics */
02462     if(!pv.test_mode_flag)
02463     {
02464         fpShowEventStats();
02465         DropStats(0);
02466     }
02467 
02468     /* Exit plugins */
02469     idx = PluginCleanExitList;
02470     //if(idx)
02471     //    LogMessage("WARNING: Deprecated Plugin API still in use\n");
02472 
02473 #ifdef GIDS
02474 #ifndef IPFW
02475     if (InlineMode())
02476     {
02477 
02478 #ifndef NFNETLINKQ
02479         if (ipqh)
02480         {
02481             ipq_destroy_handle(ipqh);
02482         }
02483 #else
02484         if(qhndl)
02485         {
02486             nfq_destroy_queue(qhndl);
02487             nfq_close(nfqh);
02488         }
02489 #endif /* NFNETLINKQ */
02490 
02491         RejectFuRestart();
02492 
02493         if(BaitAndSwitchIsRunning())
02494         {
02495             LogMessage("Going to try to restore iptables rules %s\n",restorecmd);
02496              
02497             if(system(restorecmd) !=0)
02498             {
02499                 LogMessage("iptables restore cmd failed restore manually\n");
02500             }
02501             else
02502             {
02503                LogMessage("iptables rules restored ok now oink oink exit\n");
02504             }
02505         }
02506 
02507 
02508     }
02509 #else
02510     if (divert_socket)
02511     {
02512         close(divert_socket);
02513     }
02514 
02515 #endif /* IPFW (may need cleanup code here) */
02516 #endif /* GIDS */
02517 
02518     while(idx)
02519     {
02520         idx->func(SIGQUIT, idx->arg);
02521         idx = idx->next;
02522     }
02523 
02524     /* free allocated memory */
02525 
02526     /* close pcap */
02527 #ifdef GIDS
02528     if (pd && !InlineMode())
02529 #else
02530     if (pd)
02531 #endif
02532         pcap_close(pd);
02533 
02534     LogMessage("Snort exiting\n");
02535 
02536     /* remove pid file */
02537     if(pv.pid_filename)
02538         unlink(pv.pid_filename);
02539 
02540     /* exit */
02541     exit(exit_val);
02542 }
02543 
02544 static void Restart()
02545 {
02546     PluginSignalFuncNode *idx = NULL;
02547 
02548     /* Print statistics */
02549     if(!pv.test_mode_flag)
02550     {
02551         fpShowEventStats();
02552         DropStats(0);
02553     }
02554 
02555     /* Exit plugins */
02556     /* legacy exit code */
02557     idx = PluginRestartList;
02558     //if(idx)
02559     //    LogMessage("WARNING: Deprecated Plugin API still in use\n");
02560 
02561 #ifdef GIDS
02562 #ifndef IPFW
02563     if (InlineMode())
02564     {
02565 
02566 #ifndef NFNETLINKQ
02567         if (ipqh)
02568         {
02569             ipq_destroy_handle(ipqh);
02570         }
02571 #else
02572     if(qhndl)
02573     {
02574         nfq_destroy_queue(qhndl);
02575         nfq_close(nfqh);
02576     }
02577 #endif /* NFNETLINKQ */
02578 
02579         RejectFuRestart();
02580 
02581         if(BaitAndSwitchIsRunning())
02582         {
02583             LogMessage("Going to try to restore iptables rules %s\n",restorecmd);
02584  
02585             if(system(restorecmd) !=0)
02586             {
02587                 LogMessage("iptables restore cmd failed restore manually\n");
02588             }
02589             else
02590             {
02591                LogMessage("iptables rules restored ok now oink oink exit\n");
02592             }
02593         }
02594 
02595 
02596     }
02597 #else
02598     if (divert_socket)
02599     {
02600         close(divert_socket);
02601     }
02602 
02603 #endif /* IPFW (may need cleanup code here) */
02604 #endif /* GIDS */
02605 
02606 
02607     while(idx)
02608     {
02609         idx->func(SIGHUP, idx->arg);
02610         idx = idx->next;
02611     }
02612 
02613     /* free allocated memory */
02614 
02615     /* close pcap */
02616     if(pd)
02617         pcap_close(pd);
02618 
02619     /* remove pid file */
02620 
02621     if(pv.pid_filename)
02622         unlink(pv.pid_filename);
02623     LogMessage("Restarting Snort\n");
02624 
02625     /* re-exec Snort */
02626 #ifdef PARANOID
02627     execv(progname, progargs);
02628 #else
02629     execvp(progname, progargs);
02630 #endif
02631 
02632     /* only get here if we failed to restart */
02633     LogMessage("Restarting %s failed: %s\n", progname, strerror(errno));
02634     exit(1);
02635 }
02636 

Generated on Sun May 14 14:51:18 2006 by  doxygen 1.4.2