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

util.c

Go to the documentation of this file.
00001 /* $Id$ */
00002 /*
00003 ** Copyright (C) 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 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024 
00025 #include <sys/types.h>
00026 #ifndef WIN32
00027 #include <sys/socket.h>
00028 #include <netinet/in.h>
00029 #include <arpa/inet.h>
00030 #endif /* !WIN32 */
00031 #include <stdarg.h>
00032 #include <syslog.h>
00033 #include <errno.h>
00034 #include <sys/stat.h>
00035 #include <time.h>
00036 #include <signal.h>
00037 #include <unistd.h>
00038 #ifndef WIN32
00039 #include <grp.h>
00040 #include <pwd.h>
00041 #include <netdb.h>
00042 #include <limits.h>
00043 #endif /* !WIN32 */
00044 #include <fcntl.h>
00045 
00046 #ifdef HAVE_STRINGS_H
00047 #include <strings.h>
00048 #endif
00049 
00050 #include "snort.h"
00051 #include "mstring.h"
00052 #include "debug.h"
00053 #include "util.h"
00054 #include "parser.h"
00055 #include "inline.h"
00056 
00057 #ifdef WIN32
00058 #include "win32/WIN32-Code/name.h"
00059 #endif
00060 
00061 #ifdef PATH_MAX
00062 #define PATH_MAX_UTIL PATH_MAX
00063 #else
00064 #define PATH_MAX_UTIL 1024
00065 #endif /* PATH_MAX */
00066 
00067 #ifdef TIMESTATS
00068 extern long start_time;   /* used for processing run time and packets per second stats */
00069 extern float prev_pkts;
00070 #endif
00071 
00072 /*
00073  * Function: GenHomenet(char *)
00074  *
00075  * Purpose: Translate the command line character string into its equivalent
00076  *          32-bit network byte ordered value (with netmask)
00077  *
00078  * Arguments: netdata => The address/CIDR block
00079  *
00080  * Returns: void function
00081  */
00082 void GenHomenet(char *netdata)
00083 {
00084     struct in_addr net;    /* place to stick the local network data */
00085     char **toks;           /* dbl ptr to store mSplit return data in */
00086     int num_toks;          /* number of tokens mSplit returns */
00087     int nmask;             /* temporary netmask storage */
00088 
00089     /* break out the CIDR notation from the IP address */
00090     toks = mSplit(netdata, "/", 2, &num_toks, 0);
00091 
00092     if(num_toks > 1)
00093     {
00094         /* convert the CIDR notation into a real live netmask */
00095         nmask = atoi(toks[1]);
00096 
00097         if((nmask > 0) && (nmask < 33))
00098         {
00099             pv.netmask = netmasks[nmask];
00100         }
00101         else
00102         {
00103             FatalError("Bad CIDR block [%s:%d], 1 to 32 please!\n",
00104                        toks[1], nmask);
00105         }
00106     }
00107     else
00108     {
00109         FatalError("No netmask specified for home network!\n");
00110     }
00111 
00112     pv.netmask = htonl(pv.netmask);
00113 
00114     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "homenet netmask = %#8lX\n", pv.netmask););
00115 
00116     /* convert the IP addr into its 32-bit value */
00117     if((net.s_addr = inet_addr(toks[0])) == -1)
00118     {
00119         FatalError("Homenet (%s) didn't translate\n",
00120                    toks[0]);
00121     }
00122     else
00123     {
00124 #ifdef DEBUG
00125         struct in_addr sin;
00126 
00127         DebugMessage(DEBUG_INIT, "Net = %s (%X)\n", inet_ntoa(net), net.s_addr);
00128 #endif
00129         /* set the final homenet address up */
00130         pv.homenet = ((u_long) net.s_addr & pv.netmask);
00131 
00132 #ifdef DEBUG
00133         sin.s_addr = pv.homenet;
00134         DebugMessage(DEBUG_INIT, "Homenet = %s (%X)\n", inet_ntoa(sin), sin.s_addr);
00135 #endif
00136     }
00137 
00138     mSplitFree(&toks, num_toks);
00139 }
00140 
00141 
00142 
00143 void GenObfuscationMask(char *netdata)
00144 {
00145     struct in_addr net;       /* place to stick the local network data */
00146     char **toks;              /* dbl ptr to store mSplit return data in */
00147     int num_toks;             /* number of tokens mSplit returns */
00148     int nmask;                /* temporary netmask storage */
00149 
00150     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Got obfus data: %s\n", netdata););
00151 
00152     /* break out the CIDR notation from the IP address */
00153     toks = mSplit(netdata, "/", 2, &num_toks, 0);
00154 
00155     if(num_toks > 1)
00156     {
00157         /* convert the CIDR notation into a real live netmask */
00158         nmask = atoi(toks[1]);
00159 
00160         if((nmask > 0) && (nmask < 33))
00161         {
00162             pv.obfuscation_mask = netmasks[nmask];
00163         }
00164         else
00165         {
00166             FatalError("Bad CIDR block in obfuscation mask [%s:%d], "
00167                        "1 to 32 please!\n", toks[1], pv.obfuscation_mask);
00168         }
00169     }
00170     else
00171     {
00172         FatalError("No netmask specified for obsucation mask!\n");
00173     }
00174 
00175     pv.obfuscation_mask = htonl(pv.obfuscation_mask);
00176 
00177     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "obfuscation netmask = %#8lX\n", 
00178                 pv.obfuscation_mask););
00179 
00180     /* convert the IP addr into its 32-bit value */
00181     if((net.s_addr = inet_addr(toks[0])) == -1)
00182     {
00183         FatalError("Obfuscation mask (%s) didn't translate\n",
00184                    toks[0]);
00185     }
00186     else
00187     {
00188         struct in_addr sin;
00189 
00190         DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Obfuscation Net = %s (%X)\n", 
00191                 inet_ntoa(net), net.s_addr););
00192 
00193         /* set the final homenet address up */
00194         pv.obfuscation_net = ((u_long) net.s_addr & pv.obfuscation_mask);
00195 
00196         sin.s_addr = pv.obfuscation_net;
00197         DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Obfuscation Net = %s (%X)\n", 
00198                 inet_ntoa(sin), sin.s_addr););
00199         pv.obfuscation_mask = ~pv.obfuscation_mask;
00200     }
00201 
00202     mSplitFree(&toks, num_toks);
00203 }
00204 
00205 /****************************************************************************
00206  *
00207  * Function  : DefineIfaceVar()
00208  * Purpose   : Assign network address and network mast to IFACE_ADDR_VARNAME
00209  *             variable.
00210  * Arguments : interface name (string) netaddress and netmask (4 octets each)
00211  * Returns   : void function
00212  *
00213  ****************************************************************************/
00214 void DefineIfaceVar(char *iname, u_char * network, u_char * netmask)
00215 {
00216     char valbuf[32];
00217     char varbuf[BUFSIZ];
00218 
00219     snprintf(varbuf, BUFSIZ, "%s_ADDRESS", iname);
00220 
00221     snprintf(valbuf, 32, "%d.%d.%d.%d/%d.%d.%d.%d",
00222             network[0] & 0xff, network[1] & 0xff, network[2] & 0xff, 
00223             network[3] & 0xff, netmask[0] & 0xff, netmask[1] & 0xff, 
00224             netmask[2] & 0xff, netmask[3] & 0xff);
00225 
00226     VarDefine(varbuf, valbuf);
00227 }
00228 
00229 
00230 /****************************************************************************
00231  *
00232  * Function: CalcPct(float, float)
00233  *
00234  * Purpose:  Calculate the percentage of a value compared to a total
00235  *
00236  * Arguments: cnt => the numerator in the equation
00237  *            total => the denominator in the calculation
00238  *
00239  * Returns: pct -> the percentage of cnt to value
00240  *
00241  ****************************************************************************/
00242 float CalcPct(float cnt, float total)
00243 {
00244     float pct;
00245 
00246     if(cnt > 0.0)
00247         pct = cnt / total;
00248     else
00249         return 0.0;
00250 
00251     pct *= 100.0;
00252 
00253     return pct;
00254 }
00255 
00256 
00257 /****************************************************************************
00258  *
00259  * Function: DisplayBanner()
00260  *
00261  * Purpose:  Show valuable proggie info
00262  *
00263  * Arguments: None.
00264  *
00265  * Returns: 0 all the time
00266  *
00267  ****************************************************************************/
00268 int DisplayBanner()
00269 {
00270     char * info;
00271 
00272     info = getenv("HOSTTYPE");
00273     if( !info )
00274     {
00275         info="";
00276     }
00277 
00278     fprintf(stderr, "\n"
00279         "   ,,_     -*> Snort_Inline! <*-\n"
00280         "  o\"  )~   Version %s (Build %s) %s\n"
00281         "   ''''    By Martin Roesch & The Snort Team: http://www.snort.org/team.html\n"
00282         "           (C) Copyright 1998-2005 Sourcefire Inc., et al.\n"   
00283         "           Snort_Inline Mod by William Metcalf, Victor Julien, Nick Rogness,\n"
00284         "           Dave Remien, Rob McMillen and Jed Haile\n"
00285         " NOTE: Snort's default output has changed in version 2.4.1!\n"
00286         "       The default logging mode is now PCAP, use \"-K ascii\" to activate\n"
00287         "       the old default logging mode.\n"
00288         "\n"
00289         , VERSION, BUILD, info);
00290 
00291     return 0;
00292 }
00293 
00294 
00295 
00296 /****************************************************************************
00297  *
00298  * Function: ts_print(register const struct, char *)
00299  *
00300  * Purpose: Generate a time stamp and stuff it in a buffer.  This one has
00301  *          millisecond precision.  Oh yeah, I ripped this code off from
00302  *          TCPdump, props to those guys.
00303  *
00304  * Arguments: timeval => clock struct coming out of libpcap
00305  *            timebuf => buffer to stuff timestamp into
00306  *
00307  * Returns: void function
00308  *
00309  ****************************************************************************/
00310 void ts_print(register const struct timeval *tvp, char *timebuf)
00311 {
00312     register int s;
00313     int    localzone;
00314     time_t Time;
00315     struct timeval tv;
00316     struct timezone tz;
00317     struct tm *lt;    /* place to stick the adjusted clock data */
00318 
00319     /* if null was passed, we use current time */
00320     if(!tvp)
00321     {
00322         /* manual page (for linux) says tz is never used, so.. */
00323         bzero((char *) &tz, sizeof(tz));
00324         gettimeofday(&tv, &tz);
00325         tvp = &tv;
00326     }
00327 
00328     localzone = thiszone;
00329    
00330     /*
00331     **  If we're doing UTC, then make sure that the timezone is correct.
00332     */
00333     if(pv.use_utc)
00334         localzone = 0;
00335         
00336     s = (tvp->tv_sec + localzone) % 86400;
00337     Time = (tvp->tv_sec + localzone) - s;
00338 
00339     lt = gmtime(&Time);
00340 
00341     if(pv.include_year)
00342     {
00343         (void) snprintf(timebuf, TIMEBUF_SIZE, 
00344                         "%02d/%02d/%02d-%02d:%02d:%02d.%06u ", 
00345                         lt->tm_mon + 1, lt->tm_mday, lt->tm_year - 100, 
00346                         s / 3600, (s % 3600) / 60, s % 60, 
00347                         (u_int) tvp->tv_usec);
00348     } 
00349     else 
00350     {
00351         (void) snprintf(timebuf, TIMEBUF_SIZE,
00352                         "%02d/%02d-%02d:%02d:%02d.%06u ", lt->tm_mon + 1,
00353                         lt->tm_mday, s / 3600, (s % 3600) / 60, s % 60,
00354                         (u_int) tvp->tv_usec);
00355     }
00356 }
00357 
00358 
00359 
00360 /****************************************************************************
00361  *
00362  * Function: gmt2local(time_t)
00363  *
00364  * Purpose: Figures out how to adjust the current clock reading based on the
00365  *          timezone you're in.  Ripped off from TCPdump.
00366  *
00367  * Arguments: time_t => offset from GMT
00368  *
00369  * Returns: offset seconds from GMT
00370  *
00371  ****************************************************************************/
00372 int gmt2local(time_t t)
00373 {
00374     register int dt, dir;
00375     register struct tm *gmt, *loc;
00376     struct tm sgmt;
00377 
00378     if(t == 0)
00379         t = time(NULL);
00380 
00381     gmt = &sgmt;
00382     *gmt = *gmtime(&t);
00383     loc = localtime(&t);
00384 
00385     dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
00386         (loc->tm_min - gmt->tm_min) * 60;
00387 
00388     dir = loc->tm_year - gmt->tm_year;
00389 
00390     if(dir == 0)
00391         dir = loc->tm_yday - gmt->tm_yday;
00392 
00393     dt += dir * 24 * 60 * 60;
00394 
00395     return(dt);
00396 }
00397 
00398 
00399 
00400 
00401 /****************************************************************************
00402  *
00403  * Function: copy_argv(u_char **)
00404  *
00405  * Purpose: Copies a 2D array (like argv) into a flat string.  Stolen from
00406  *          TCPDump.
00407  *
00408  * Arguments: argv => 2D array to flatten
00409  *
00410  * Returns: Pointer to the flat string
00411  *
00412  ****************************************************************************/
00413 char *copy_argv(char **argv)
00414 {
00415     char **p;
00416     u_int len = 0;
00417     char *buf;
00418     char *src, *dst;
00419     void ftlerr(char *,...);
00420 
00421     p = argv;
00422     if(*p == 0)
00423         return 0;
00424 
00425     while(*p)
00426         len += strlen(*p++) + 1;
00427 
00428     buf = (char *) malloc(len);
00429 
00430     if(buf == NULL)
00431     {
00432         FatalError("malloc() failed: %s\n", strerror(errno));
00433     }
00434     p = argv;
00435     dst = buf;
00436 
00437     while((src = *p++) != NULL)
00438     {
00439         while((*dst++ = *src++) != '\0');
00440         dst[-1] = ' ';
00441     }
00442 
00443     dst[-1] = '\0';
00444 
00445     return buf;
00446 }
00447 
00448 
00449 /****************************************************************************
00450  *
00451  * Function: strip(char *)
00452  *
00453  * Purpose: Strips a data buffer of CR/LF/TABs.  Replaces CR/LF's with
00454  *          NULL and TABs with spaces.
00455  *
00456  * Arguments: data => ptr to the data buf to be stripped
00457  *
00458  * Returns: size of the newly stripped string
00459  *
00460  ****************************************************************************/
00461 int strip(char *data)
00462 {
00463     int size;
00464     char *end;
00465     char *idx;
00466 
00467     idx = data;
00468     end = data + strlen(data);
00469     size = end - idx;
00470 
00471     while(idx != end)
00472     {
00473         if((*idx == '\n') ||
00474                 (*idx == '\r'))
00475         {
00476             *idx = 0;
00477             size--;
00478         }
00479         if(*idx == '\t')
00480         {
00481             *idx = ' ';
00482         }
00483         idx++;
00484     }
00485 
00486     return size;
00487 }
00488 
00489 
00490 /****************************************************************************
00491  *
00492  * Function: InitNetMasks()
00493  *
00494  * Purpose: Loads the netmask struct in network order.  Yes, I know I could
00495  *          just load the array when I define it, but this is what occurred
00496  *          to me when I wrote this at 3:00 AM.
00497  *
00498  * Arguments: None.
00499  *
00500  * Returns: void function
00501  *
00502  ****************************************************************************/
00503 extern u_long netmasks[33]; /* defined in snort.c */
00504 
00505 void InitNetmasks()
00506 {
00507     netmasks[0] = 0x0;
00508     netmasks[1] = 0x80000000;
00509     netmasks[2] = 0xC0000000;
00510     netmasks[3] = 0xE0000000;
00511     netmasks[4] = 0xF0000000;
00512     netmasks[5] = 0xF8000000;
00513     netmasks[6] = 0xFC000000;
00514     netmasks[7] = 0xFE000000;
00515     netmasks[8] = 0xFF000000;
00516     netmasks[9] = 0xFF800000;
00517     netmasks[10] = 0xFFC00000;
00518     netmasks[11] = 0xFFE00000;
00519     netmasks[12] = 0xFFF00000;
00520     netmasks[13] = 0xFFF80000;
00521     netmasks[14] = 0xFFFC0000;
00522     netmasks[15] = 0xFFFE0000;
00523     netmasks[16] = 0xFFFF0000;
00524     netmasks[17] = 0xFFFF8000;
00525     netmasks[18] = 0xFFFFC000;
00526     netmasks[19] = 0xFFFFE000;
00527     netmasks[20] = 0xFFFFF000;
00528     netmasks[21] = 0xFFFFF800;
00529     netmasks[22] = 0xFFFFFC00;
00530     netmasks[23] = 0xFFFFFE00;
00531     netmasks[24] = 0xFFFFFF00;
00532     netmasks[25] = 0xFFFFFF80;
00533     netmasks[26] = 0xFFFFFFC0;
00534     netmasks[27] = 0xFFFFFFE0;
00535     netmasks[28] = 0xFFFFFFF0;
00536     netmasks[29] = 0xFFFFFFF8;
00537     netmasks[30] = 0xFFFFFFFC;
00538     netmasks[31] = 0xFFFFFFFE;
00539     netmasks[32] = 0xFFFFFFFF;
00540 }
00541 
00542 /*
00543  * error message printing routines. in daemon mode these would go into
00544  * syslog.
00545  *
00546  * first would allow to print formatted error messages (similar to printf) and
00547  * the second is similar to perror.
00548  *
00549  */
00550 
00551 void PrintError(char *str)
00552 {
00553     if(pv.daemon_flag)
00554         syslog(LOG_CONS | LOG_DAEMON | LOG_ERR, "%s:%m", str);
00555     else
00556         perror(str);
00557 }
00558 
00559 
00560 /*
00561  * Function: ErrorMessage(const char *, ...)
00562  *
00563  * Purpose: Print a message to stderr.
00564  *
00565  * Arguments: format => the formatted error string to print out
00566  *            ... => format commands/fillers
00567  *
00568  * Returns: void function
00569  */
00570 void ErrorMessage(const char *format,...)
00571 {
00572     char buf[STD_BUF+1];
00573     va_list ap;
00574 
00575     va_start(ap, format);
00576 
00577     if(pv.daemon_flag)
00578     {
00579         vsnprintf(buf, STD_BUF, format, ap);
00580         syslog(LOG_CONS | LOG_DAEMON | LOG_ERR, "%s", buf);
00581     }
00582     else
00583     {
00584         vfprintf(stderr, format, ap);
00585     }
00586     va_end(ap);
00587 }
00588 
00589 /*
00590  * Function: LogMessage(const char *, ...)
00591  *
00592  * Purpose: Print a message to stdout or with logfacility.
00593  *
00594  * Arguments: format => the formatted error string to print out
00595  *            ... => format commands/fillers
00596  *
00597  * Returns: void function
00598  */
00599 void LogMessage(const char *format,...)
00600 {
00601     char buf[STD_BUF+1];
00602     va_list ap;
00603 
00604     if(pv.quiet_flag && !pv.daemon_flag)
00605         return;
00606 
00607     va_start(ap, format);
00608 
00609     if(pv.daemon_flag)
00610     {
00611         vsnprintf(buf, STD_BUF, format, ap);
00612         syslog(LOG_DAEMON | LOG_NOTICE, "%s", buf);
00613     }
00614     else
00615     {
00616         vfprintf(stderr, format, ap);
00617     }
00618     va_end(ap);
00619 }
00620 
00621 
00622 /*
00623  * Function: CreateApplicationEventLogEntry(const char *)
00624  *
00625  * Purpose: Add an entry to the Win32 "Application" EventLog
00626  *
00627  * Arguments: szMessage => the formatted error string to print out
00628  *
00629  * Returns: void function
00630  */
00631 #if defined(WIN32) && defined(ENABLE_WIN32_SERVICE)
00632 void CreateApplicationEventLogEntry(const char *msg)
00633 {
00634     HANDLE hEventLog; 
00635     char*  pEventSourceName = "SnortService";
00636 
00637     /* prepare to write to Application log on local host
00638       * with Event Source of SnortService
00639       */
00640     AddEventSource(pEventSourceName);
00641     hEventLog = RegisterEventSource(NULL, pEventSourceName);
00642     if (hEventLog == NULL)
00643     {
00644         /* Could not register the event source. */
00645         return;
00646     }
00647  
00648     if (!ReportEvent(hEventLog,   /* event log handle               */
00649             EVENTLOG_ERROR_TYPE,  /* event type                     */
00650             0,                    /* category zero                  */
00651             EVMSG_SIMPLE,         /* event identifier               */
00652             NULL,                 /* no user security identifier    */
00653             1,                    /* one substitution string        */
00654             0,                    /* no data                        */
00655             &msg,                 /* pointer to array of strings    */
00656             NULL))                /* pointer to data                */
00657     {
00658         /* Could not report the event. */
00659     }
00660  
00661     DeregisterEventSource(hEventLog); 
00662 } 
00663 #endif  /* WIN32 && ENABLE_WIN32_SERVICE */
00664 
00665 
00666 /*
00667  * Function: FatalError(const char *, ...)
00668  *
00669  * Purpose: When a fatal error occurs, this function prints the error message
00670  *          and cleanly shuts down the program
00671  *
00672  * Arguments: format => the formatted error string to print out
00673  *            ... => format commands/fillers
00674  *
00675  * Returns: void function
00676  */
00677 void FatalError(const char *format,...)
00678 {
00679     char buf[STD_BUF+1];
00680     va_list ap;
00681 
00682     va_start(ap, format);
00683 
00684     vsnprintf(buf, STD_BUF, format, ap);
00685 
00686     if(pv.daemon_flag)
00687     {
00688         syslog(LOG_CONS | LOG_DAEMON | LOG_ERR, "FATAL ERROR: %s", buf);
00689     }
00690     else
00691     {
00692         fprintf(stderr, "ERROR: %s", buf);
00693         fprintf(stderr,"Fatal Error, Quitting..\n");
00694 #if defined(WIN32) && defined(ENABLE_WIN32_SERVICE)
00695         CreateApplicationEventLogEntry(buf);
00696 #endif
00697     }
00698 
00699     exit(1);
00700 }
00701 
00702 void FatalPrintError(char *msg)
00703 {
00704     PrintError(msg);
00705     exit(1);
00706 }
00707 
00708 /****************************************************************************
00709  *
00710  * Function: CreatePidFile(char *)
00711  *
00712  * Purpose:  Creates a PID file
00713  *
00714  * Arguments: Interface opened.
00715  *
00716  * Returns: void function
00717  *
00718  ****************************************************************************/
00719 void CreatePidFile(char *intf)
00720 {
00721     FILE *pid_file;
00722     struct stat pt;
00723 #ifdef WIN32
00724     char dir[STD_BUF + 1];
00725 #endif
00726 
00727     if (!pv.readmode_flag) 
00728     {
00729         if(!pv.quiet_flag)
00730         {
00731             LogMessage("Checking PID path...\n");
00732         }
00733 #ifndef _PATH_VARRUN
00734 #ifndef WIN32
00735         strlcpy(_PATH_VARRUN, "/var/run/", 10);
00736 #else
00737         if (GetCurrentDirectory(sizeof (dir)-1, dir))
00738             strncpy (_PATH_VARRUN, dir, sizeof(dir)-1);
00739 #endif  /* WIN32 */
00740 #else
00741         if(!pv.quiet_flag)
00742         {
00743             LogMessage("PATH_VARRUN is set to %s on this operating system\n", 
00744                     _PATH_VARRUN);
00745         }
00746 #endif  /* _PATH_VARRUN */
00747 
00748         stat(_PATH_VARRUN, &pt);
00749 
00750         if(!S_ISDIR(pt.st_mode) || access(_PATH_VARRUN, W_OK) == -1)
00751         {
00752             LogMessage("WARNING: _PATH_VARRUN is invalid, trying "
00753                     "/var/log...\n");
00754             strncpy(pv.pid_path, "/var/log/", strlen("/var/log/"));
00755             stat(pv.pid_path, &pt);
00756 
00757             if(!S_ISDIR(pt.st_mode) || access(pv.pid_path, W_OK) == -1)
00758             {
00759                 LogMessage("WARNING: %s is invalid, logging Snort "
00760                         "PID path to log directory (%s)\n", pv.pid_path,
00761                         pv.log_dir);
00762                 CheckLogDir();
00763                 snprintf(pv.pid_path, STD_BUF, "%s/", pv.log_dir);
00764             }
00765         }
00766         else
00767         {
00768             LogMessage("PID path stat checked out ok, PID path set to %s\n", _PATH_VARRUN);
00769             strlcpy(pv.pid_path, _PATH_VARRUN, STD_BUF);
00770         }
00771     }
00772 
00773     if(intf == NULL || pv.pid_path == NULL)
00774     {
00775         /* pv.pid_path should have some value by now
00776          *          * so let us just be sane.
00777          *                   */
00778         FatalError("CreatePidFile() failed to lookup interface or pid_path is unknown!\n");
00779     }
00780 
00781     snprintf(pv.pid_filename, STD_BUF,  "%s/snort_%s%s.pid", pv.pid_path, intf,
00782             pv.pidfile_suffix);
00783 
00784     pid_file = fopen(pv.pid_filename, "w");
00785 
00786     if(pid_file)
00787     {
00788         int pid = (int) getpid();
00789 
00790         LogMessage("Writing PID \"%d\" to file \"%s\"\n", pid, pv.pid_filename);
00791         fprintf(pid_file, "%d\n", pid);
00792         fclose(pid_file);
00793     }
00794     else
00795     {
00796         ErrorMessage("Failed to create pid file %s", pv.pid_filename);
00797         pv.pid_filename[0] = 0;
00798     }
00799 }
00800 
00801 
00802 /****************************************************************************
00803  *
00804  * Function: SetUidGid(char *)
00805  *
00806  * Purpose:  Sets safe UserID and GroupID if needed
00807  *
00808  * Arguments: none
00809  *
00810  * Returns: void function
00811  *
00812  ****************************************************************************/
00813 void SetUidGid(void)
00814 {
00815 #ifndef WIN32
00816 
00817     if(groupname != NULL)
00818     {
00819         if(InlineMode())
00820         {
00821             ErrorMessage("Cannot set uid and gid when running Snort in "
00822                 "inline mode.\n");
00823 
00824             return;
00825         }
00826 
00827         if(setgid(groupid) < 0)
00828             FatalError("Can not set gid: %lu\n", (u_long) groupid);
00829 
00830         DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Set gid to %lu\n", groupid););
00831     }
00832     if(username != NULL)
00833     {
00834         if(InlineMode())
00835         {
00836             ErrorMessage("Cannot set uid and gid when running Snort in "
00837                 "inline mode.\n");
00838 
00839             return;
00840         }
00841 
00842         if(getuid() == 0 && initgroups(username, groupid) < 0)
00843             FatalError("Can not initgroups(%s,%lu)",
00844                     username, (u_long) groupid);
00845 
00846         /** just to be on a safe side... **/
00847         endgrent();
00848         endpwent();
00849 
00850         if(setuid(userid) < 0)
00851             FatalError("Can not set uid: %lu\n", (u_long) userid);
00852         DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Set gid to %lu\n", groupid););
00853     }
00854 #endif  /* WIN32 */
00855 
00856     return;
00857 }
00858 
00859 #ifdef TIMESTATS
00860 /* Print out a message once an hour */
00861 void DropHourlyStats(int trap)
00862 {
00863    struct pcap_stat ps;      /* structure to hold packet statistics */
00864 
00865    const int secs_per_min = 60;             /* 60 seconds in a minute */
00866    const int secs_per_hr  = 3600;           /* 3600 seconds in a hour */
00867 
00868    unsigned int dhs_ppm = 0, dhs_pps = 0;
00869    unsigned int curr_pkts = 0;
00870    unsigned int curr_drop_pkts = 0;
00871 
00872    if (pcap_stats(pd, &ps))  /* get some packet statistics */
00873    {
00874       pcap_perror(pd, "pcap_stats");  /* an error has happened */
00875    }
00876    else                      /* prepare to figure out hourly stats */
00877    {
00878       static unsigned int prev_pkts;       /* used to remember the number of  */
00879       static unsigned int prev_drop_pkts;  /* packets processed from the last */
00880                                            /* time this function was called   */
00881 
00882       curr_pkts = ps.ps_recv - prev_pkts;
00883       curr_drop_pkts = ps.ps_drop - prev_drop_pkts;
00884 
00885       LogMessage("\n");
00886       LogMessage("Hourly Statistics Report\n");
00887       LogMessage("\n");
00888 
00889       dhs_ppm = curr_pkts / secs_per_min; /* how many packets per minute? */
00890       dhs_pps = curr_pkts / secs_per_hr;  /* how many packets per second? */
00891 
00892       LogMessage("Packet analysis time averages:\n");
00893       LogMessage("\n");
00894       LogMessage("Packets Received per hour is:     %10u\n", curr_pkts);
00895       LogMessage("Packets Received per minute is:   %10u\n", dhs_ppm);
00896       LogMessage("Packets Received per second is:   %10u\n", dhs_pps);
00897       LogMessage("Packets Dropped in the last hour: %10u\n", curr_drop_pkts);
00898       LogMessage("\n");
00899 
00900       prev_pkts = ps.ps_recv;       /* save current number of packets for use */
00901       prev_drop_pkts = ps.ps_drop;  /* next time this function is called... */
00902 
00903    }  /* end if pcap_stats(ps, &ps) */
00904    
00905    alarm(secs_per_hr);   /* reset the alarm to go off in a hour */
00906 
00907 }
00908 
00909 /* print out stats on how long snort ran */
00910 void TimeStats(struct pcap_stat *ps)
00911 {
00912 
00913 /*
00914  *  variable definitions for improved statistics handling
00915  *
00916  *  end_time = time which snort finished running (unix epoch)
00917  *  total_secs = total amount of time snort ran
00918  *  int_total_secs = used to eliminate casts from this function (temp. var)
00919  *  SECONDS_PER_DAY = the number of seconds in a day, 86400 (not counting leap seconds)
00920  *  SECONDS_PER_HOUR = the number of seconds in a hour, 3600
00921  *  SECONDS_PER_MIN = the number of seconds in a minute, 60
00922  *  days = number of days snort ran
00923  *  hrs  = number of hrs snort ran
00924  *  mins = number of minutes snort ran
00925  *  secs = number of seconds snort ran
00926  *
00927  *  ival = temp. variable for integer/modulus math
00928  *  ppd  = packets per day processed
00929  *  pph  = packets per hour processed
00930  *  ppm  = packets per minute processed
00931  *  pps  = packets per second processed
00932  *
00933  *  hflag = used to flag when hrs = zero, but days > 0
00934  *  mflag = used to flag when min = zero, but hrs > 0
00935  *
00936  */
00937 
00938     long end_time = 0L, total_secs = 0L;
00939 
00940     const int SECONDS_PER_DAY = 86400; /* number of seconds in a day  */
00941     const int SECONDS_PER_HOUR = 3600; /* number of seconds in a hour */
00942     const int SECONDS_PER_MIN = 60;    /* number of seconds in a minute */
00943 
00944     int days = 0, hrs = 0, mins = 0, secs = 0, ival = 0;
00945     int pps = 0, ppm = 0, pph = 0, ppd = 0;
00946     int int_total_secs = 0;
00947 
00948     int hflag = 0, mflag = 0;
00949 
00950     end_time = time(&end_time);         /* grab epoch for end time value (in seconds) */
00951     total_secs = end_time - start_time; /* total_secs is how many seconds snort ran for */
00952 
00953     ival = total_secs;                  /* convert total_secs from type 'long' to type 'int' */
00954     int_total_secs = ival;              /* used for cast elimination */
00955 
00956     days = ival / SECONDS_PER_DAY;      /* 86400 is number of seconds in a day */
00957     ival = ival % SECONDS_PER_DAY;      /* grab remainder to process hours */
00958     hrs  = ival / SECONDS_PER_HOUR;     /* 3600 is number of seconds in a(n) hour */
00959     ival = ival % SECONDS_PER_HOUR;     /* grab remainder to process minutes */
00960     mins = ival / SECONDS_PER_MIN;      /* 60 is number of seconds in a minute */
00961     secs = ival % SECONDS_PER_MIN;      /* grab remainder to process seconds */
00962 
00963     if (total_secs)
00964         pps = (ps->ps_recv / int_total_secs);  /* packets per second is received pkts divided by */
00965     else                                        /* total number of seconds (cast as type 'int') */
00966         pps = ps->ps_recv;                      /* guard against division by zero */
00967 
00968     LogMessage("Snort ran for %d Days %d Hours %d Minutes %d Seconds\n", days, hrs, mins, secs);
00969 
00970     if (days + hrs + mins + secs > 0) {
00971         LogMessage("Packet analysis time averages:\n\n");
00972     }
00973 
00974     if (days > 0) {
00975         ppd = (ps->ps_recv / (int_total_secs / SECONDS_PER_DAY));
00976         LogMessage("Snort Analyzed %d Packets Per Day\n", ppd);
00977         hflag = 1;
00978     }
00979 
00980     if (hrs > 0 || hflag == 1) {
00981         pph = (ps->ps_recv / (int_total_secs / SECONDS_PER_HOUR));
00982         LogMessage("Snort Analyzed %d Packets Per Hour\n", pph);
00983         mflag = 1;
00984     }
00985 
00986     if (mins > 0 || mflag == 1) {
00987         ppm = (ps->ps_recv / (int_total_secs / SECONDS_PER_MIN));
00988         LogMessage("Snort Analyzed %d Packets Per Minute\n", ppm);
00989     }
00990 
00991     LogMessage("Snort Analyzed %d Packets Per Second\n", pps);
00992     LogMessage(" \n");
00993 
00994 }
00995 #endif /* TIMESTATS */
00996 
00997 /* need int parameter here because of function declaration of signal(2) */
00998 void DropStats(int iParamIgnored)
00999 {
01000     struct pcap_stat ps;
01001     float drop = 0.0;
01002     float recv = 0.0;
01003 
01004 #ifndef TIMESTATS
01005     if(pv.quiet_flag)
01006         return;
01007 #endif
01008 
01009     puts("\n\n===============================================================================\n");
01010 
01011     /*
01012      * you will hardly run snort in daemon mode and read from file i that is
01013      * why no `LogMessage()' here
01014      */
01015     if(pv.readmode_flag || InlineMode())
01016     {
01017 
01018         /* this wildass line adjusts for the fragment reassembly packet injector */
01019         recv = (float) (pc.tcp
01020                 + pc.udp 
01021                 + pc.icmp
01022                 + pc.arp
01023                 + pc.ipx
01024                 + pc.eapol
01025                 + pc.ipv6
01026                 + pc.ethloopback
01027                 + pc.other
01028                 + pc.discards
01029                 + pc.frags
01030                 + pc.rebuild_element
01031                 - pc.rebuilt_frags
01032                 - pc.frag_timeout);
01033 
01034         printf("Snort processed %u packets.\n", (unsigned int) recv);
01035     }
01036     else
01037     {
01038         /* collect the packet stats */
01039         if(pcap_stats(pd, &ps))
01040         {
01041             pcap_perror(pd, "pcap_stats");
01042         }
01043         else
01044         {
01045             recv = (float) ps.ps_recv;
01046             drop = (float) ps.ps_drop;
01047 
01048 #ifdef TIMESTATS
01049             {
01050                 int oldQFlag = pv.quiet_flag;
01051                 pv.quiet_flag = 0;
01052                 TimeStats(&ps);     /* how long did snort run? */
01053                 pv.quiet_flag = oldQFlag;
01054             }
01055 #endif
01056 
01057             LogMessage("Snort received %u packets\n", ps.ps_recv);
01058             LogMessage("    Analyzed: %u(%.3f%%)\n", ps.ps_recv - ps.ps_drop, 
01059                     ps.ps_recv?CalcPct((float)(ps.ps_recv-ps.ps_drop), 
01060                         (float) ps.ps_recv):0);
01061             LogMessage("    Dropped: %u(%.3f%%)\n", ps.ps_drop, 
01062                     ps.ps_recv?CalcPct((float)ps.ps_drop, (float) ps.ps_recv):0);
01063         }
01064     }
01065 
01066     LogMessage("================================================"
01067             "===============================\n");
01068 
01069     LogMessage("Breakdown by protocol:\n");
01070     LogMessage("    TCP: %-10lu (%.3f%%)%-*s\n", 
01071             pc.tcp, CalcPct((float) pc.tcp, recv), 
01072             CalcPct((float)pc.tcp,recv + drop)<10?10:9 , " ");
01073     LogMessage("    UDP: %-10lu (%.3f%%)%-*s\n", 
01074             pc.udp, CalcPct((float) pc.udp, recv),  
01075             CalcPct((float)pc.udp,recv + drop)<10?10:9, " ");
01076     LogMessage("   ICMP: %-10lu (%.3f%%)%-*s\n", 
01077             pc.icmp, CalcPct((float) pc.icmp, recv), 
01078             CalcPct((float)pc.icmp,recv + drop)<10?10:9, " ");
01079     LogMessage("    ARP: %-10lu (%.3f%%)\n", 
01080             pc.arp, CalcPct((float) pc.arp, recv));
01081     LogMessage("  EAPOL: %-10lu (%.3f%%)\n", 
01082             pc.eapol, CalcPct((float) pc.eapol, recv));
01083     LogMessage("   IPv6: %-10lu (%.3f%%)\n", 
01084             pc.ipv6, CalcPct((float) pc.ipv6, recv));
01085     LogMessage("ETHLOOP: %-10lu (%.3f%%)\n", 
01086             pc.ethloopback, CalcPct((float) pc.ethloopback, recv));
01087     LogMessage("    IPX: %-10lu (%.3f%%)\n", 
01088             pc.ipx, CalcPct((float) pc.ipx, recv));
01089     LogMessage("   FRAG: %-10lu (%.3f%%)%-*s\n", 
01090             pc.frags, CalcPct((float) pc.frags, recv),  
01091             CalcPct((float)pc.udp,recv + drop)<10?10:9, " ");
01092     LogMessage("  OTHER: %-10lu (%.3f%%)\n", 
01093             pc.other, CalcPct((float) pc.other, recv));
01094     LogMessage("DISCARD: %-10lu (%.3f%%)\n", 
01095             pc.discards, CalcPct((float) pc.discards, recv));
01096 
01097     LogMessage("================================================"
01098             "===============================\n");
01099     LogMessage("Action Stats:\n");
01100     LogMessage("ALERTS: %u\n", pc.alert_pkts);
01101     LogMessage("LOGGED: %u\n", pc.log_pkts);
01102     LogMessage("PASSED: %u\n", pc.pass_pkts);
01103 
01104 #ifdef DLT_IEEE802_11
01105     if(datalink == DLT_IEEE802_11)
01106     {
01107         LogMessage("================================================"
01108                 "===============================\n");
01109         LogMessage("Wireless Stats:\n");
01110         LogMessage("Breakdown by type:\n");
01111         LogMessage("    Management Packets: %-10lu (%.3f%%)\n", 
01112                 pc.wifi_mgmt, CalcPct((float) pc.wifi_mgmt, recv));
01113         LogMessage("    Control Packets:    %-10lu (%.3f%%)\n", 
01114                 pc.wifi_control, CalcPct((float) pc.wifi_control, recv));
01115         LogMessage("    Data Packets:       %-10lu (%.3f%%)\n", 
01116                 pc.wifi_data, CalcPct((float) pc.wifi_data, recv));
01117     }
01118 #endif
01119 
01120     if(pc.frags > 0)
01121     {
01122         LogMessage("================================================"
01123                 "===============================\n");
01124         LogMessage("Fragmentation Stats:\n");
01125         LogMessage("Fragmented IP Packets: %-10lu (%.3f%%)\n", 
01126                 pc.frags, CalcPct((float) pc.frags, recv));
01127         LogMessage("    Fragment Trackers: %-10lu\n", 
01128                 pc.frag_trackers);
01129         LogMessage("   Rebuilt IP Packets: %-10lu\n", 
01130                 pc.rebuilt_frags);
01131         LogMessage("   Frag elements used: %-10lu\n", 
01132                 pc.rebuild_element);
01133         LogMessage("Discarded(incomplete): %-10lu\n", 
01134                 pc.frag_incomp);
01135         LogMessage("   Discarded(timeout): %-10lu\n", 
01136                 pc.frag_timeout);
01137         LogMessage("  Frag2 memory faults: %-10lu\n", 
01138                 pc.frag_mem_faults);
01139     }
01140 
01141     if(pc.tcp_stream_pkts > 0)
01142     {
01143         LogMessage("=============================================="
01144                 "=================================\n");
01145         LogMessage("TCP Stream Reassembly Stats:\n");
01146         LogMessage("    TCP Packets Used: %-10lu (%-3.3f%%)\n", 
01147                 pc.tcp_stream_pkts, 
01148                 CalcPct((float) pc.tcp_stream_pkts, recv));
01149         LogMessage("    Stream Trackers: %-10lu\n", pc.tcp_streams);
01150         LogMessage("    Stream flushes: %-10lu\n", pc.rebuilt_tcp);
01151         LogMessage("    Segments used: %-10lu\n", pc.rebuilt_segs);
01152         LogMessage("    Stream4 Memory Faults: %-10lu\n", 
01153                 pc.str_mem_faults);
01154     }
01155 
01156     LogMessage("=============================================="
01157             "=================================\n");
01158 
01159     return;
01160 }
01161 
01162 
01163 /****************************************************************************
01164  *
01165  * Function: InitProtoNames()
01166  *
01167  * Purpose: Initializes the protocol names
01168  *
01169  * Arguments: None.
01170  *
01171  * Returns: void function
01172  *
01173  ****************************************************************************/
01174 void InitProtoNames()
01175 {
01176     int i;
01177     struct protoent *pt;
01178     unsigned char *tmp;
01179     u_char protoname[11];
01180 
01181     for(i = 0; i < 256; i++)
01182     {
01183         pt = getprotobynumber(i);
01184 
01185         if(pt)
01186         {
01187             protocol_names[i] = strdup(pt->p_name);
01188 
01189             tmp = protocol_names[i];
01190 
01191             for(tmp = protocol_names[i]; *tmp != 0; tmp++)
01192                 *tmp = (unsigned char) toupper(*tmp);
01193         }
01194         else
01195         {
01196             snprintf(protoname, 10, "PROTO%03d", i);
01197             protocol_names[i] = strdup(protoname);
01198         }
01199     }
01200 }
01201 
01202 /****************************************************************************
01203  *
01204  * Function: CleanupProtoNames()
01205  *
01206  * Purpose: Frees the protocol names
01207  *
01208  * Arguments: None.
01209  *
01210  * Returns: void function
01211  *
01212  ****************************************************************************/
01213 void CleanupProtoNames()
01214 {
01215     int i;
01216 
01217     for(i = 0; i < 256; i++)
01218     {
01219         if( protocol_names[i] != NULL )
01220         {
01221             free( protocol_names[i] );
01222             protocol_names[i] = NULL;
01223         }
01224     }
01225 }
01226 
01227 /****************************************************************************
01228  *
01229  * Function: read_infile(char *)
01230  *
01231  * Purpose: Reads the BPF filters in from a file.  Ripped from tcpdump.
01232  *
01233  * Arguments: fname => the name of the file containing the BPF filters
01234  *
01235  * Returns: the processed BPF string
01236  *
01237  ****************************************************************************/
01238 char *read_infile(char *fname)
01239 {
01240     register int fd, cc;
01241     register char *cp, *cmt;
01242     struct stat buf;
01243 
01244     fd = open(fname, O_RDONLY);
01245 
01246     if(fd < 0)
01247         FatalError("can't open %s: %s\n", fname, pcap_strerror(errno));
01248 
01249     if(fstat(fd, &buf) < 0)
01250         FatalError("can't stat %s: %s\n", fname, pcap_strerror(errno));
01251 
01252     cp = malloc((u_int) buf.st_size + 1);
01253 
01254     cc = read(fd, cp, (int) buf.st_size);
01255 
01256     if(cc < 0)
01257         FatalError("read %s: %s\n", fname, pcap_strerror(errno));
01258 
01259     if(cc != buf.st_size)
01260         FatalError("short read %s (%d != %d)\n", fname, cc, (int) buf.st_size);
01261 
01262     cp[(int) buf.st_size] = '\0';
01263 
01264     close(fd);
01265 
01266     /* Treat everything upto the end of the line as a space
01267      *  so that we can put comments in our BPF filters
01268      */
01269     
01270     while((cmt = strchr(cp, '#')) != NULL)
01271     {
01272         while (*cmt != '\r' && *cmt != '\n' && *cmt != '\0')
01273         {
01274             *cmt++ = ' ';
01275         }
01276     }
01277 
01278     
01279     return(cp);
01280 }
01281 
01282 
01283  /****************************************************************************
01284   *
01285   * Function: CheckLogDir()
01286   *
01287   * Purpose: CyberPsychotic sez: basically we only check if logdir exist and
01288   *          writable, since it might screw the whole thing in the middle. Any
01289   *          other checks could be performed here as well.
01290   *
01291   * Arguments: None.
01292   *
01293   * Returns: void function
01294   *
01295   ****************************************************************************/
01296 void CheckLogDir(void)
01297 {
01298     struct stat st;
01299     char log_dir[STD_BUF];
01300 
01301     snprintf(log_dir, STD_BUF, "%s", pv.log_dir);
01302     stat(log_dir, &st);
01303 
01304     if(!S_ISDIR(st.st_mode) || access(log_dir, W_OK) == -1)
01305     {
01306         FatalError("\n[!] ERROR: "
01307                 "Can not get write access to logging directory \"%s\".\n"
01308                 "(directory doesn't exist or permissions are set incorrectly\n"
01309                 /*
01310                  * let us add this comment. Too many people seem to
01311                  * confuse it otherwise :-)
01312                  */
01313             "or it is not a directory at all)\n\n",
01314         log_dir);
01315     }
01316 }
01317 
01318 
01319 /****************************************************************************
01320  *
01321  * Function: GoDaemon()
01322  *
01323  * Purpose: Puts the program into daemon mode, nice and quiet like....
01324  *
01325  * Arguments: None.
01326  *
01327  * Returns: void function
01328  *
01329  ****************************************************************************/
01330 void GoDaemon(void)
01331 {
01332 #ifndef WIN32
01333     pid_t fs;
01334 
01335     LogMessage("Initializing daemon mode\n");
01336 
01337     if(getppid() != 1)
01338     {
01339         fs = fork();
01340 
01341         if(fs > 0)
01342             exit(0);                /* parent */
01343 
01344         if(fs < 0)
01345         {
01346             perror("fork");
01347             exit(1);
01348         }
01349         setsid();
01350     }
01351     /* redirect stdin/stdout/stderr to /dev/null */
01352     close(0);
01353     close(1);
01354     close(2);
01355 
01356 #ifdef DEBUG
01357     open("/tmp/snort.debug", O_CREAT | O_RDWR);
01358 #else
01359     open("/dev/null", O_RDWR);
01360 #endif
01361 
01362     dup(0);
01363     dup(0);
01364 #endif /* ! WIN32 */
01365     return;
01366 }
01367 
01368 
01369 /* This function has been moved into mstring.c, since that
01370 *  is where the allocation actually occurs.  It has been
01371 *  renamed to mSplitFree().
01372 *
01373 void FreeToks(char **toks, int num_toks)
01374 {
01375     if (toks)
01376     {
01377         if (num_toks > 0)
01378         {
01379             do
01380             {
01381                 num_toks--;
01382                 free(toks[num_toks]);
01383             } while(num_toks);
01384         }
01385         free(toks);
01386     }
01387 }
01388 */
01389 
01390 
01391 /* Self preserving memory allocator */
01392 void *SPAlloc(unsigned long size, struct _SPMemControl *spmc)
01393 {
01394     void *tmp;
01395 
01396     spmc->mem_usage += size;
01397 
01398     if(spmc->mem_usage > spmc->memcap)
01399     {
01400         spmc->sp_func(spmc);
01401     }
01402 
01403     tmp = (void *) calloc(size, sizeof(char));
01404 
01405     if(tmp == NULL)
01406     {
01407         FatalError("Unable to allocate memory!  (%lu requested, %lu in use)\n",
01408                 size, spmc->mem_usage);
01409     }
01410 
01411     return tmp;
01412 }
01413 
01414 
01415 void *SnortAlloc(unsigned long size)
01416 {
01417     void *tmp;
01418 
01419     tmp = (void *) calloc(size, sizeof(char));
01420 
01421     if(tmp == NULL)
01422     {
01423         FatalError("Unable to allocate memory!  (%lu requested)\n", size);
01424     }
01425 
01426     return tmp;
01427 }
01428 
01429 /** 
01430  * Chroot and adjust the pv.log_dir reference 
01431  * 
01432  * @param directory directory to chroot to
01433  * @param logdir ptr to pv.log_dir
01434  */
01435 void SetChroot(char *directory, char **logstore)
01436 {
01437 #ifdef WIN32
01438     FatalError("SetChroot() should not be called under Win32!\n");
01439 #else
01440     char *absdir;
01441     int abslen;
01442     char *logdir;
01443     
01444     if(!directory || !logstore)
01445     {
01446         FatalError("Null parameter passed\n");
01447     }
01448 
01449     logdir = *logstore;
01450 
01451     if(logdir == NULL || *logdir == '\0')
01452     {
01453         FatalError("Null log directory\n");
01454     }    
01455 
01456     DEBUG_WRAP(DebugMessage(DEBUG_INIT,"SetChroot: %s\n",
01457                                        CurrentWorkingDir()););
01458     
01459     logdir = GetAbsolutePath(logdir);
01460 
01461     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "SetChroot: %s\n",
01462                                        CurrentWorkingDir()));
01463     
01464     logdir = strdup(logdir);
01465 
01466     if(logdir == NULL)
01467     {
01468         FatalError("SetChroot: Out of memory");
01469     }
01470     
01471     /* change to the directory */
01472     if(chdir(directory) != 0)
01473     {
01474         FatalError("SetChroot: Can not chdir to \"%s\": %s\n", directory, 
01475                    strerror(errno));
01476     }
01477 
01478     /* always returns an absolute pathname */
01479     absdir = CurrentWorkingDir();
01480 
01481     if(absdir == NULL)                          
01482     {
01483         FatalError("NULL Chroot found\n");
01484     }
01485     
01486     abslen = strlen(absdir);
01487 
01488     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "ABS: %s %d\n", absdir, abslen););
01489     
01490     /* make the chroot call */
01491     if(chroot(absdir) < 0)
01492     {
01493         FatalError("Can not chroot to \"%s\": absolute: %s: %s\n",
01494                    directory, absdir, strerror(errno));
01495     }
01496 
01497     DEBUG_WRAP(DebugMessage(DEBUG_INIT,"chroot success (%s ->", absdir););
01498     DEBUG_WRAP(DebugMessage(DEBUG_INIT,"%s)\n ", CurrentWorkingDir()););
01499     
01500     /* change to "/" in the new directory */
01501     if(chdir("/") < 0)
01502     {
01503         FatalError("Can not chdir to \"/\" after chroot: %s\n", 
01504                    strerror(errno));
01505     }    
01506 
01507     DEBUG_WRAP(DebugMessage(DEBUG_INIT,"chdir success (%s)\n",
01508                             CurrentWorkingDir()););
01509 
01510 
01511     if(strncmp(absdir, logdir, strlen(absdir)))
01512     {
01513         FatalError("Absdir is not a subset of the logdir");
01514     }
01515     
01516     if(abslen >= strlen(logdir))
01517     {
01518         *logstore = "/";
01519     }
01520     else
01521     {
01522         *logstore = logdir + abslen;
01523     }
01524 
01525     DEBUG_WRAP(DebugMessage(DEBUG_INIT,"new logdir from %s to %s\n",
01526                             logdir, *logstore));
01527 
01528     /* install the I can't do this signal handler */
01529     signal(SIGHUP, SigCantHupHandler);
01530 #endif /* !WIN32 */
01531 }
01532 
01533 
01534 /**
01535  * Return a ptr to the absolute pathname of snort.  This memory must
01536  * be copied to another region if you wish to save it for later use.
01537  */
01538 char *CurrentWorkingDir(void)
01539 {
01540     static char buf[PATH_MAX_UTIL + 1];
01541     
01542     if(getcwd((char *) buf, PATH_MAX_UTIL) == NULL)
01543     {
01544         return NULL;
01545     }
01546 
01547     buf[PATH_MAX_UTIL] = '\0';
01548 
01549     return (char *) buf;
01550 }
01551 
01552 /**
01553  * Given a directory name, return a ptr to a static 
01554  */
01555 char *GetAbsolutePath(char *dir)
01556 {
01557     char *savedir, *dirp;
01558     static char buf[PATH_MAX_UTIL + 1];
01559 
01560     if(dir == NULL)
01561     {
01562         return NULL;
01563     }
01564 
01565     savedir = strdup(CurrentWorkingDir());
01566 
01567     if(savedir == NULL)
01568     {
01569         return NULL;
01570     }
01571 
01572     if(chdir(dir) < 0)
01573     {
01574         LogMessage("Can't change to directory: %s\n", dir);
01575         free(savedir);
01576         return NULL;
01577     }
01578 
01579     dirp = CurrentWorkingDir();
01580 
01581     if(dirp == NULL)
01582     {
01583         LogMessage("Unable to access current directory\n");
01584         free(savedir);
01585         return NULL;
01586     }
01587     else
01588     {
01589         strncpy(buf, dirp, PATH_MAX_UTIL);
01590         buf[PATH_MAX_UTIL] = '\0';
01591     }
01592 
01593     if(chdir(savedir) < 0)
01594     {
01595         LogMessage("Can't change back to directory: %s\n", dir);
01596         free(savedir);                
01597         return NULL;
01598     }
01599 
01600     free(savedir);
01601     return (char *) buf;
01602 }
01603 

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