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

spo_log_tcpdump.c

Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 /* $Id$ */
00020 
00021 /* spo_log_tcpdump 
00022  * 
00023  * Purpose:
00024  *
00025  * This plugin generates tcpdump formatted binary log files
00026  *
00027  * Arguments:
00028  *   
00029  * filename of the output log (default: snort.log)
00030  *
00031  * Effect:
00032  *
00033  * Packet logs are written (quickly) to a tcpdump formatted output
00034  * file
00035  *
00036  * Comments:
00037  *
00038  * First logger...
00039  *
00040  */
00041 
00042 #ifdef HAVE_CONFIG_H
00043 #include "config.h"
00044 #endif
00045 
00046 #ifdef HAVE_STRINGS_H
00047 #include <strings.h>
00048 #endif
00049 
00050 #include <sys/types.h>
00051 #include <pcap.h>
00052 #include <ctype.h>
00053 #include <stdlib.h>
00054 #include <string.h>
00055 #include <errno.h>
00056 #include <unistd.h>
00057 #include <time.h>
00058 
00059 #include "decode.h"
00060 #include "event.h"
00061 #include "plugbase.h"
00062 #include "spo_plugbase.h"
00063 #include "parser.h"
00064 #include "debug.h"
00065 #include "util.h"
00066 
00067 #include "snort.h"
00068 
00069 typedef struct _LogTcpdumpData
00070 {
00071     char *filename;
00072     int log_written;
00073     pcap_dumper_t *dumpd;
00074 
00075 } LogTcpdumpData;
00076 
00077 /* list of function prototypes for this preprocessor */
00078 void LogTcpdumpInit(u_char *);
00079 LogTcpdumpData *ParseTcpdumpArgs(char *);
00080 void LogTcpdump(Packet *, char *, void *, Event *);
00081 void TcpdumpInitLogFile(LogTcpdumpData *);
00082 void SpoLogTcpdumpCleanExitFunc(int, void *);
00083 void SpoLogTcpdumpRestartFunc(int, void *);
00084 void DirectLogTcpdump(struct pcap_pkthdr *, u_int8_t *);
00085 void LogTcpdumpSingle(Packet *, char *, void *, Event *);
00086 void LogTcpdumpStream(Packet *, char *, void *, Event *);
00087 
00088 
00089 
00090 /* external globals from rules.c */
00091 extern pcap_dumper_t *dumpd;  /* ptr to pcap packet dump facility */
00092 extern PV pv;              /* program variables struct */
00093 
00094 /* If you need to instantiate the plugin's data structure, do it here */
00095 LogTcpdumpData *log_tcpdump_ptr;
00096 
00097 /*
00098  * Function: SetupLogTcpdump()
00099  *
00100  * Purpose: Registers the output plugin keyword and initialization 
00101  *          function into the output plugin list.  This is the function that
00102  *          gets called from InitOutputPlugins() in plugbase.c.
00103  *
00104  * Arguments: None.
00105  *
00106  * Returns: void function
00107  *
00108  */
00109 void LogTcpdumpSetup()
00110 {
00111     /* link the preprocessor keyword to the init function in 
00112        the preproc list */
00113     RegisterOutputPlugin("log_tcpdump", NT_OUTPUT_LOG, LogTcpdumpInit);
00114 
00115     DEBUG_WRAP(DebugMessage(DEBUG_INIT,"Output plugin: Log-Tcpdump is setup...\n"););
00116 }
00117 
00118 
00119 /*
00120  * Function: LogTcpdumpInit(u_char *)
00121  *
00122  * Purpose: Calls the argument parsing function, performs final setup on data
00123  *          structs, links the preproc function into the function list.
00124  *
00125  * Arguments: args => ptr to argument string
00126  *
00127  * Returns: void function
00128  *
00129  */
00130 void LogTcpdumpInit(u_char *args)
00131 {
00132     LogTcpdumpData *data;
00133     DEBUG_WRAP(DebugMessage(DEBUG_INIT,"Output: Log-Tcpdump Initialized\n"););
00134 
00135     /* tell command line loggers to go away */
00136     pv.log_plugin_active = 1;
00137 
00138     /* parse the argument list from the rules file */
00139     data = ParseTcpdumpArgs(args);
00140     log_tcpdump_ptr = data;
00141 
00142     TcpdumpInitLogFile(data);
00143 
00144     pv.log_bitmap |= LOG_TCPDUMP;
00145 
00146     /* Set the preprocessor function into the function list */
00147     AddFuncToOutputList(LogTcpdump, NT_OUTPUT_LOG, data);
00148     AddFuncToCleanExitList(SpoLogTcpdumpCleanExitFunc, data);
00149     AddFuncToRestartList(SpoLogTcpdumpRestartFunc, data);
00150 }
00151 
00152 
00153 
00154 /*
00155  * Function: ParseTcpdumpArgs(char *)
00156  *
00157  * Purpose: Process the preprocessor arguements from the rules file and 
00158  *          initialize the preprocessor's data struct.  This function doesn't
00159  *          have to exist if it makes sense to parse the args in the init 
00160  *          function.
00161  *
00162  * Arguments: args => argument list
00163  *
00164  * Returns: void function
00165  *
00166  */
00167 LogTcpdumpData *ParseTcpdumpArgs(char *args)
00168 {
00169     LogTcpdumpData *data;
00170 
00171     data = (LogTcpdumpData *) calloc(1, sizeof(LogTcpdumpData));
00172 
00173     DEBUG_WRAP(DebugMessage(DEBUG_INIT,"Args: %s<>\n", args););
00174 
00175     if(args != NULL)
00176     {
00177         while(isspace((int)*args)) args++;
00178         if(strcmp(args, "") != 0)
00179             data->filename = strdup(args);
00180         else
00181             data->filename = strdup("snort.log");
00182     }
00183     else
00184     {
00185         data->filename = strdup("snort.log");
00186     }
00187 
00188     return data;
00189 }
00190 
00191 
00192 /*
00193  * Function: PreprocFunction(Packet *)
00194  *
00195  * Purpose: Perform the preprocessor's intended function.  This can be
00196  *          simple (statistics collection) or complex (IP defragmentation)
00197  *          as you like.  Try not to destroy the performance of the whole
00198  *          system by trying to do too much....
00199  *
00200  * Arguments: p => pointer to the current packet data struct 
00201  *
00202  * Returns: void function
00203  */
00204 void LogTcpdump(Packet *p, char *msg, void *arg, Event *event)
00205 {
00206 
00207     if(p)
00208     {
00209         if(p->packet_flags & PKT_REBUILT_STREAM)
00210         {
00211             LogTcpdumpStream(p, msg, arg, event);
00212         }
00213         else
00214         {
00215             LogTcpdumpSingle(p, msg, arg, event);
00216         }
00217     }
00218 }
00219 
00220 void LogTcpdumpSingle(Packet *p, char *msg, void *arg, Event *event)
00221 {
00222     LogTcpdumpData *data = (LogTcpdumpData *)arg;
00223 
00224     data->log_written = 1;
00225 
00226     /* sizeof(struct pcap_pkthdr) = 16 bytes */
00227     pcap_dump((u_char *)data->dumpd,p->pkth,p->pkt);
00228 
00229     if(!pv.line_buffer_flag)
00230     { 
00231 #ifdef WIN32
00232         fflush( NULL );  /* flush all open output streams */
00233 #else
00234         /* we happen to know that pcap_dumper_t* is really just a FILE* */
00235         fflush( (FILE*) data->dumpd );
00236 #endif
00237     }
00238 }
00239 
00240 
00241 void LogTcpdumpStream(Packet *p, char *msg, void *arg, Event *event)
00242 {
00243     LogTcpdumpData *data = (LogTcpdumpData *)arg;
00244     Stream *s = NULL;
00245     StreamPacketData *spd;
00246 
00247     data->log_written = 1;
00248 
00249     s = (Stream *) p->streamptr;
00250 
00251     for(spd = (StreamPacketData *)ubi_btFirst((ubi_btNodePtr)&s->data);
00252         spd;
00253         spd = (StreamPacketData*)ubi_btNext((ubi_btNodePtr)spd))
00254     {
00255         if(spd->chuck != SEG_UNASSEMBLED)
00256         {
00257             pcap_dump((u_char *)data->dumpd, 
00258                       (struct pcap_pkthdr *) &spd->pkth, 
00259                       (u_char *) spd->pkt);
00260         }
00261     }
00262 
00263     if(!pv.line_buffer_flag)
00264     { 
00265 #ifdef WIN32
00266         fflush( NULL );  /* flush all open output streams */
00267 #else
00268         /* we happen to know that pcap_dumper_t* is really just a FILE* */
00269         fflush( (FILE*) data->dumpd );
00270 #endif
00271     }
00272 }
00273 
00274 
00275 /*
00276  * Function: TcpdumpInitLogFile()
00277  *
00278  * Purpose: Initialize the tcpdump log file header
00279  *
00280  * Arguments: data => pointer to the plugin's reference data struct 
00281  *
00282  * Returns: void function
00283  */
00284 void TcpdumpInitLogFile(LogTcpdumpData *data)
00285 {
00286     time_t curr_time;      /* place to stick the clock data */
00287     //struct tm *loc_time;   /* place to stick the adjusted clock data */
00288     //char timebuf[10];
00289     char logdir[STD_BUF];
00290     int value;
00291 
00292     bzero(logdir, STD_BUF);
00293     //bzero(timebuf, 10);
00294     curr_time = time(NULL);
00295     //loc_time = localtime(&curr_time);
00296     //strftime(timebuf,9,"%m%d@%H%M",loc_time);
00297 
00298     if(data->filename[0] == '/')
00299         value = snprintf(logdir, STD_BUF-1, "%s.%lu", data->filename, 
00300                 (unsigned long)curr_time);
00301     else
00302         value = snprintf(logdir, STD_BUF-1, "%s/%s.%lu", pv.log_dir, 
00303                 data->filename, (unsigned long)curr_time);
00304 
00305     if(value == -1)
00306         FatalError("log file logging path and file name are too long\n");
00307 
00308     DEBUG_WRAP(DebugMessage(DEBUG_LOG, "Opening %s\n", logdir););
00309 
00310     if(!pv.test_mode_flag)
00311     {
00312         data->dumpd = pcap_dump_open(pd,logdir);
00313         if(data->dumpd == NULL)
00314         {
00315             FatalError("log_tcpdump TcpdumpInitLogFile(): %s\n", strerror(errno));
00316         }
00317 
00318         /* keep a copy of the filename for later reference */
00319         if(data->filename != NULL)
00320         {
00321             bzero( data->filename, strlen(data->filename) );
00322             free(data->filename);
00323             data->filename = strdup(logdir);
00324         }
00325     }
00326 
00327     return;
00328 }
00329 
00330 
00331 
00332 /*
00333  * Function: SpoLogTcpdumpCleanExitFunc()
00334  *
00335  * Purpose: Cleanup at exit time
00336  *
00337  * Arguments: signal => signal that caused this event
00338  *            arg => data ptr to reference this plugin's data
00339  *
00340  * Returns: void function
00341  */
00342 void SpoLogTcpdumpCleanExitFunc(int signal, void *arg)
00343 {
00344     /* cast the arg pointer to the proper type */
00345     LogTcpdumpData *data = (LogTcpdumpData *) arg;
00346 
00347     DEBUG_WRAP(DebugMessage(DEBUG_LOG,"SpoLogTcpdumpCleanExitFunc\n"););
00348 
00349     /* close the output file */
00350     if( data->dumpd != NULL )
00351     {
00352         pcap_dump_close(data->dumpd);
00353         data->dumpd = NULL;
00354     }
00355 
00356     /* 
00357      * if we haven't written any data, dump the output file so there aren't
00358      * fragments all over the disk 
00359      */
00360     if(data->filename!=NULL && pc.alert_pkts==0 && pc.log_pkts==0)
00361     {
00362         unlink(data->filename);
00363     }
00364 
00365     /* free up initialized memory */
00366     if( data->filename != NULL )
00367     {
00368         bzero(data->filename, strlen(data->filename));
00369         free(data->filename);
00370     }
00371     bzero(data, sizeof(LogTcpdumpData));
00372     free(data);
00373 }
00374 
00375 
00376 
00377 /*
00378  * Function: SpoLogTcpdumpRestartFunc()
00379  *
00380  * Purpose: For restarts (SIGHUP usually) clean up structs that need it
00381  *
00382  * Arguments: signal => signal that caused this event
00383  *            arg => data ptr to reference this plugin's data
00384  *
00385  * Returns: void function
00386  */
00387 void SpoLogTcpdumpRestartFunc(int signal, void *arg)
00388 {
00389 
00390     LogTcpdumpData *data = (LogTcpdumpData *)arg;
00391 
00392     DEBUG_WRAP(DebugMessage(DEBUG_LOG,"SpoLogTcpdumpRestartFunc\n"););
00393 
00394     if( data->dumpd != NULL )
00395     {
00396         pcap_dump_close(data->dumpd); 
00397         data->dumpd = NULL;
00398     }
00399 
00400     /* 
00401      * if we haven't written any data, dump the output file so there aren't
00402      * fragments all over the disk 
00403      */
00404     if(data->filename!=NULL && pc.alert_pkts==0 && pc.log_pkts==0)
00405     {
00406         unlink(data->filename);
00407     }
00408 
00409     if( data->filename != NULL )
00410     {
00411         bzero(data->filename, strlen(data->filename));
00412         free(data->filename);
00413     }
00414     bzero(data, sizeof(LogTcpdumpData));
00415     free(data);
00416 }
00417 
00418 
00419 
00420 void DirectLogTcpdump(struct pcap_pkthdr *ph, u_int8_t *pkt)
00421 {
00422     pc.log_pkts++;
00423     pcap_dump((u_char *)log_tcpdump_ptr->dumpd, ph, pkt);
00424     return;
00425 }
00426         

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