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

spo_log_ascii.c

Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
00003 **           (C) 2002 Sourcefire, Inc.
00004 **
00005 ** Author(s):   Martin Roesch <roesch@sourcefire.com>
00006 **              Andrew R. Baker <andrewb@sourcefire.com>
00007 **
00008 ** This program is free software; you can redistribute it and/or modify
00009 ** it under the terms of the GNU General Public License as published by
00010 ** the Free Software Foundation; either version 2 of the License, or
00011 ** (at your option) any later version.
00012 **
00013 ** This program is distributed in the hope that it will be useful,
00014 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 ** GNU General Public License for more details.
00017 **
00018 ** You should have received a copy of the GNU General Public License
00019 ** along with this program; if not, write to the Free Software
00020 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00021 */
00022 /* $Id$ */
00023 
00024 /* spo_log_ascii
00025  * 
00026  * Purpose:
00027  *
00028  * This output module provides the default packet logging funtionality
00029  *
00030  * Arguments:
00031  *   
00032  * None.
00033  *
00034  * Effect:
00035  *
00036  * None.
00037  *
00038  * Comments:
00039  *
00040  */
00041 
00042 #ifdef HAVE_CONFIG_H
00043 #include "config.h"
00044 #endif
00045 #include <sys/types.h>
00046 #include <string.h>
00047 #include <errno.h>
00048 #include <sys/stat.h>
00049 
00050 #ifdef HAVE_STRINGS_H
00051 #include <strings.h>
00052 #endif
00053 
00054 #ifndef WIN32
00055 #include <sys/socket.h>
00056 #include <netinet/in.h>
00057 #include <arpa/inet.h>
00058 #endif /* ! WIN32 */
00059 
00060 #include "plugbase.h"
00061 #include "spo_plugbase.h"
00062 #include "parser.h"
00063 #include "debug.h"
00064 #include "decode.h"
00065 #include "event.h"
00066 #include "log.h"
00067 #include "util.h"
00068 
00069 #include "snort.h"
00070 
00071 /* external globals from rules.c */
00072 extern OptTreeNode *otn_tmp;
00073 
00074 /* internal functions */
00075 void LogAsciiInit(u_char *args);
00076 void LogAscii(Packet *p, char *msg, void *arg, Event *event);
00077 void LogAsciiCleanExit(int signal, void *arg);
00078 void LogAsciiRestart(int signal, void *arg);
00079 char *IcmpFileName(Packet * p);
00080 static FILE *OpenLogFile(int mode, Packet * p);
00081 
00082 
00083 #define DUMP              1
00084 #define BOGUS             2
00085 #define NON_IP            3
00086 #define ARP               4
00087 #define GENERIC_LOG   5
00088 
00089 void LogAsciiSetup()
00090 {
00091     /* link the preprocessor keyword to the init function in 
00092        the preproc list */
00093     RegisterOutputPlugin("log_ascii", NT_OUTPUT_LOG, LogAsciiInit);
00094 
00095     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Output: LogAscii is setup\n"););
00096 }
00097 
00098 void LogAsciiInit(u_char *args)
00099 {
00100     DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Output: Ascii logging initialized\n"););
00101 
00102     pv.log_plugin_active = 1;
00103 
00104     /* Set the preprocessor function into the function list */
00105     AddFuncToOutputList(LogAscii, NT_OUTPUT_LOG, NULL);
00106     AddFuncToCleanExitList(LogAsciiCleanExit, NULL);
00107     AddFuncToRestartList(LogAsciiRestart, NULL);
00108 }
00109 
00110 
00111 
00112 void LogAscii(Packet *p, char *msg, void *arg, Event *event)
00113 {
00114     FILE *log_ptr = NULL;
00115     DEBUG_WRAP(DebugMessage(DEBUG_LOG, "LogPkt started\n"););
00116     if(p)
00117     { 
00118         if(p->iph)
00119             log_ptr = OpenLogFile(0, p);
00120         else if(p->ah)
00121             log_ptr = OpenLogFile(ARP, p);
00122         else
00123             log_ptr = OpenLogFile(NON_IP, p);
00124     }
00125     else
00126         log_ptr = OpenLogFile(GENERIC_LOG, p);
00127 
00128     if(!log_ptr)
00129         FatalError("Unable to open packet log file\n");
00130     
00131     if(msg)
00132     {
00133         fwrite("[**] ", 5, 1, log_ptr);
00134         fwrite(msg, strlen(msg), 1, log_ptr);
00135         fwrite(" [**]\n", 6, 1, log_ptr);
00136     }
00137     if(p)
00138     {
00139         if(p->iph)
00140             PrintIPPkt(log_ptr, p->iph->ip_proto, p);
00141         else if(p->ah)
00142             PrintArpHeader(log_ptr, p);
00143     }
00144     if(log_ptr)
00145         fclose(log_ptr);
00146 }
00147 
00148 
00149 void LogAsciiCleanExit(int signal, void *arg)
00150 {
00151     return;
00152 }
00153 
00154 void LogAsciiRestart(int signal, void *arg)
00155 {
00156     return;
00157 }
00158 
00159 static char *logfile[] =
00160         { "", "PACKET_FRAG", "PACKET_BOGUS", "PACKET_NONIP", "ARP", "log" };
00161 
00162 /*
00163  * Function: OpenLogFile()
00164  *
00165  * Purpose: Create the log directory and file to put the packet log into.
00166  *          This function sucks, I've got to find a better way to do this
00167  *          this stuff.
00168  *
00169  * Arguments: None.
00170  *
00171  * Returns: FILE pointer on success, else NULL
00172  */
00173 FILE *OpenLogFile(int mode, Packet * p)
00174 {
00175     char log_path[STD_BUF+1]; /* path to log file */
00176     char log_file[STD_BUF+1]; /* name of log file */
00177     char proto[5];      /* logged packet protocol */
00178     char suffix[5];     /* filename suffix */
00179     FILE *log_ptr = NULL;
00180 #ifdef WIN32
00181     strcpy(suffix,".ids");
00182 #else
00183     suffix[0] = '\0';
00184 #endif
00185 
00186     /* zero out our buffers */
00187     bzero((char *) log_path, STD_BUF + 1);
00188     bzero((char *) log_file, STD_BUF + 1);
00189     bzero((char *) proto, 5);
00190 
00191     if(mode == GENERIC_LOG || mode == DUMP || mode == BOGUS ||
00192             mode == NON_IP || mode == ARP)
00193     {
00194         snprintf(log_file, STD_BUF, "%s/%s", pv.log_dir, logfile[mode]);
00195 
00196         if(!(log_ptr = fopen(log_file, "a")))
00197         {
00198             FatalError("OpenLogFile() => fopen(%s) log file: %s\n",
00199                        log_file, strerror(errno));
00200         }
00201         return log_ptr;
00202     }
00203 
00204     if(otn_tmp != NULL)
00205     {
00206         if(otn_tmp->logto != NULL)
00207         {
00208             snprintf(log_file, STD_BUF, "%s/%s", pv.log_dir, otn_tmp->logto);
00209 
00210             if(!(log_ptr = fopen(log_file, "a")))
00211             {
00212                 FatalError("OpenLogFile() => fopen(%s) log file: %s\n", 
00213                            log_file, strerror(errno));
00214             }
00215             return log_ptr;
00216         }
00217     }
00218     /* figure out which way this packet is headed in relation to the homenet */
00219     if((p->iph->ip_dst.s_addr & pv.netmask) == pv.homenet)
00220     {
00221         if((p->iph->ip_src.s_addr & pv.netmask) != pv.homenet)
00222         {
00223             snprintf(log_path, STD_BUF, "%s/%s", pv.log_dir, 
00224                     inet_ntoa(p->iph->ip_src));
00225         }
00226         else
00227         {
00228             if(p->sp >= p->dp)
00229             {
00230                 snprintf(log_path, STD_BUF, "%s/%s", pv.log_dir, 
00231                         inet_ntoa(p->iph->ip_src));
00232             }
00233             else
00234             {
00235                 snprintf(log_path, STD_BUF, "%s/%s", pv.log_dir, 
00236                         inet_ntoa(p->iph->ip_dst));
00237             }
00238         }
00239     }
00240     else
00241     {
00242         if((p->iph->ip_src.s_addr & pv.netmask) == pv.homenet)
00243         {
00244             snprintf(log_path, STD_BUF, "%s/%s", pv.log_dir, 
00245                     inet_ntoa(p->iph->ip_dst));
00246         }
00247         else
00248         {
00249             if(p->sp >= p->dp)
00250             {
00251                 snprintf(log_path, STD_BUF, "%s/%s", pv.log_dir, 
00252                         inet_ntoa(p->iph->ip_src));
00253             }
00254             else
00255             {
00256                 snprintf(log_path, STD_BUF, "%s/%s", pv.log_dir, 
00257                         inet_ntoa(p->iph->ip_dst));
00258             }
00259         }
00260     }
00261 
00262     DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "Creating directory: %s\n", log_path););
00263 
00264     /* build the log directory */
00265     if(mkdir(log_path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))
00266     {
00267 
00268         if(errno != EEXIST)
00269         {
00270             FatalError("OpenLogFile() => mkdir(%s) log directory: %s\n",
00271                        log_path, strerror(errno));
00272         }
00273     }
00274 
00275     DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "Directory Created!\n"););
00276 
00277     /* build the log filename */
00278     if(p->iph->ip_proto == IPPROTO_TCP ||
00279             p->iph->ip_proto == IPPROTO_UDP)
00280     {
00281         if(p->frag_flag)
00282         {
00283             snprintf(log_file, STD_BUF, "%s/IP_FRAG%s", log_path, suffix);
00284         }
00285         else
00286         {
00287             if(p->sp >= p->dp)
00288             {
00289 #ifdef WIN32
00290                 snprintf(log_file, STD_BUF, "%s/%s_%d-%d%s", log_path,
00291                         protocol_names[p->iph->ip_proto], p->sp, p->dp, suffix);
00292 #else
00293                 snprintf(log_file, STD_BUF, "%s/%s:%d-%d%s", log_path,
00294                         protocol_names[p->iph->ip_proto], p->sp, p->dp, suffix);
00295 #endif
00296             }
00297             else
00298             {
00299 #ifdef WIN32
00300                 snprintf(log_file, STD_BUF, "%s/%s_%d-%d%s", log_path,
00301                         protocol_names[p->iph->ip_proto], p->dp, p->sp, suffix);
00302 #else
00303                 snprintf(log_file, STD_BUF, "%s/%s:%d-%d%s", log_path,
00304                         protocol_names[p->iph->ip_proto], p->dp, p->sp, suffix);
00305 #endif
00306             }
00307         }
00308     }
00309     else
00310     {
00311         if(p->frag_flag)
00312         {
00313             snprintf(log_file, STD_BUF, "%s/IP_FRAG%s", log_path, suffix);
00314         }
00315         else
00316         {
00317             if(p->iph->ip_proto == IPPROTO_ICMP)
00318             {
00319                 snprintf(log_file, STD_BUF, "%s/%s_%s%s", log_path, "ICMP",
00320                          IcmpFileName(p), suffix);
00321             }
00322             else
00323             {
00324                 snprintf(log_file, STD_BUF, "%s/PROTO%d%s", log_path,
00325                          p->iph->ip_proto, suffix);
00326             }
00327         }
00328     }
00329 
00330     DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "Opening file: %s\n", log_file););
00331 
00332     /* finally open the log file */
00333     if(!(log_ptr = fopen(log_file, "a")))
00334     {
00335         FatalError("OpenLogFile() => fopen(%s) log file: %s\n",
00336                    log_file, strerror(errno));
00337     }
00338 
00339     DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "File opened...\n"););
00340     return log_ptr;
00341 }
00342 
00343 
00344 
00345 /****************************************************************************
00346  *
00347  * Function: IcmpFileName(Packet *p)
00348  *
00349  * Purpose: Set the filename of an ICMP output log according to its type
00350  *
00351  * Arguments: p => Packet data struct
00352  *
00353  * Returns: the name of the file to set
00354  *
00355  ***************************************************************************/
00356 char *IcmpFileName(Packet * p)
00357 {
00358     if(p->icmph == NULL)
00359     {
00360         return "ICMP_TRUNC";
00361     }
00362 
00363     switch(p->icmph->type)
00364     {
00365         case ICMP_ECHOREPLY:
00366             return "ECHO_REPLY";
00367 
00368         case ICMP_DEST_UNREACH:
00369             switch(p->icmph->code)
00370             {
00371                 case ICMP_NET_UNREACH:
00372                     return "NET_UNRCH";
00373 
00374                 case ICMP_HOST_UNREACH:
00375                     return "HST_UNRCH";
00376 
00377                 case ICMP_PROT_UNREACH:
00378                     return "PROTO_UNRCH";
00379 
00380                 case ICMP_PORT_UNREACH:
00381                     return "PORT_UNRCH";
00382 
00383                 case ICMP_FRAG_NEEDED:
00384                     return "UNRCH_FRAG_NEEDED";
00385 
00386                 case ICMP_SR_FAILED:
00387                     return "UNRCH_SOURCE_ROUTE_FAILED";
00388 
00389                 case ICMP_NET_UNKNOWN:
00390                     return "UNRCH_NETWORK_UNKNOWN";
00391 
00392                 case ICMP_HOST_UNKNOWN:
00393                     return "UNRCH_HOST_UNKNOWN";
00394 
00395                 case ICMP_HOST_ISOLATED:
00396                     return "UNRCH_HOST_ISOLATED";
00397 
00398                 case ICMP_PKT_FILTERED_NET:
00399                     return "UNRCH_PKT_FILTERED_NET";
00400 
00401                 case ICMP_PKT_FILTERED_HOST:
00402                     return "UNRCH_PKT_FILTERED_HOST";
00403 
00404                 case ICMP_NET_UNR_TOS:
00405                     return "UNRCH_NET_UNR_TOS";
00406 
00407                 case ICMP_HOST_UNR_TOS:
00408                     return "UNRCH_HOST_UNR_TOS";
00409 
00410                 case ICMP_PKT_FILTERED:
00411                     return "UNRCH_PACKET_FILT";
00412 
00413                 case ICMP_PREC_VIOLATION:
00414                     return "UNRCH_PREC_VIOL";
00415 
00416                 case ICMP_PREC_CUTOFF:
00417                     return "UNRCH_PREC_CUTOFF";
00418 
00419                 default:
00420                     return "UNKNOWN";
00421 
00422             }
00423 
00424         case ICMP_SOURCE_QUENCH:
00425             return "SRC_QUENCH";
00426 
00427         case ICMP_REDIRECT:
00428             return "REDIRECT";
00429 
00430         case ICMP_ECHO:
00431             return "ECHO";
00432 
00433         case ICMP_TIME_EXCEEDED:
00434             return "TTL_EXCEED";
00435 
00436         case ICMP_PARAMETERPROB:
00437             return "PARAM_PROB";
00438 
00439         case ICMP_TIMESTAMP:
00440             return "TIMESTAMP";
00441 
00442         case ICMP_TIMESTAMPREPLY:
00443             return "TIMESTAMP_RPL";
00444 
00445         case ICMP_INFO_REQUEST:
00446             return "INFO_REQ";
00447 
00448         case ICMP_INFO_REPLY:
00449             return "INFO_RPL";
00450 
00451         case ICMP_ADDRESS:
00452             return "ADDR";
00453 
00454         case ICMP_ADDRESSREPLY:
00455             return "ADDR_RPL";
00456 
00457         default:
00458             return "UNKNOWN";
00459     }
00460 }
00461 
00462 

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