00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdlib.h>
00029 #include <ctype.h>
00030 #include "plugbase.h"
00031 #include "mstring.h"
00032 #include "util.h"
00033 #include "debug.h"
00034 #include "parser.h"
00035
00036 #include "snort.h"
00037 #include "perf.h"
00038
00039
00040
00041
00042 static void PerfMonitorInit(u_char *args);
00043 static void ParsePerfMonitorArgs(char *args);
00044 static void ProcessPerfMonitor(Packet *p, void *);
00045 void PerfMonitorCleanExit(int, void *);
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 void SetupPerfMonitor()
00060 {
00061
00062
00063 RegisterPreprocessor("PerfMonitor", PerfMonitorInit);
00064
00065 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: PerfMonitor is setup...\n"););
00066 }
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 static void PerfMonitorInit(u_char *args)
00080 {
00081 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Preprocessor: PerfMonitor Initialized\n"););
00082
00083
00084 ParsePerfMonitorArgs((char*)args);
00085
00086
00087 AddFuncToPreprocList(ProcessPerfMonitor);
00088 }
00089
00090
00091
00092
00093 static char perf_file[1025]={""};
00094 void SetPerfmonitorFile( char * s )
00095 {
00096 if( strlen(s) < sizeof(perf_file)-1 )
00097 {
00098 strcpy(perf_file,s);
00099 }
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 static void ParsePerfMonitorArgs( char *args)
00119 {
00120 char **Tokens=NULL;
00121 int iTokenNum=0;
00122 int i, iTime=60, iFlow=0, iEvents=0, iMaxPerfStats=0;
00123 int iFile=0, iSnortFile=0, iConsole=0, iPkts=10000, iReset=0;
00124 int iStatsExit=0;
00125 char file[1025];
00126 char snortfile[1025];
00127 int iRet;
00128 char *pcEnd;
00129
00130 if( args )
00131 {
00132 Tokens = mSplit(args, " \t", 50, &iTokenNum, '\\');
00133 }
00134
00135 for( i = 0; i < iTokenNum; i++ )
00136 {
00137
00138 if( strcmp( Tokens[i],"time")==0 )
00139 {
00140
00141 if( i == (iTokenNum-1) )
00142 {
00143 FatalError("%s(%d) => Missing Time. The value must be a "
00144 "positive integer number.\n", file_name, file_line);
00145 }
00146
00147 iTime = strtol(Tokens[++i], &pcEnd, 10);
00148 if(iTime <= 0 || *pcEnd)
00149 FatalError("%s(%d) => Invalid Time. The value must be a "
00150 "positive integer number.\n", file_name, file_line);
00151 }
00152 else if( strcmp( Tokens[i],"flow")==0 )
00153 {
00154
00155
00156
00157
00158
00159
00160 iFlow = 1;
00161 }
00162 else if( strcmp( Tokens[i],"accumulate")==0)
00163 {
00164 iReset=0;
00165 }
00166 else if( strcmp( Tokens[i],"reset")==0 )
00167 {
00168 iReset=1;
00169 }
00170 else if( strcmp( Tokens[i],"events")==0 )
00171 {
00172
00173
00174
00175
00176
00177
00178
00179 iEvents = 1;
00180 }
00181 else if(!strcmp(Tokens[i], "max"))
00182 {
00183 iMaxPerfStats = 1;
00184 }
00185 else if(!strcmp(Tokens[i], "console"))
00186 {
00187 iConsole = 1;
00188 }
00189 else if(!strcmp(Tokens[i], "file"))
00190 {
00191 if( i == (iTokenNum-1) )
00192 {
00193 FatalError("%s(%d) => Missing 'file' argument. This value "
00194 "is the file that save stats.\n",
00195 file_name, file_line);
00196 }
00197
00198 iFile = 1;
00199
00200 strncpy( file, Tokens[++i], sizeof(file)-1 );
00201 file[sizeof(file)-1] = 0x00;
00202 }
00203 else if(!strcmp(Tokens[i], "snortfile"))
00204 {
00205 if( i == (iTokenNum-1) )
00206 {
00207 FatalError("%s(%d) => Missing 'snortfile' argument. This "
00208 "value is the file that save stats.\n",
00209 file_name, file_line);
00210 }
00211
00212 iSnortFile = 1;
00213
00214 if(pv.log_dir[strlen(pv.log_dir)-1] == '/')
00215 {
00216 iRet = snprintf(snortfile, sizeof(snortfile),
00217 "%s%s", pv.log_dir, Tokens[++i]);
00218 }
00219 else
00220 {
00221 iRet = snprintf(snortfile, sizeof(snortfile),
00222 "%s/%s", pv.log_dir, Tokens[++i]);
00223 }
00224
00225 if(iRet < 0)
00226 {
00227 FatalError("%s(%d) => 'snortfile' argument path is too long.\n",
00228 file_name, file_line);
00229 }
00230 }
00231 else if(!strcmp(Tokens[i], "pktcnt"))
00232 {
00233 if( i == (iTokenNum-1) )
00234 {
00235 FatalError("%s(%d) => Missing 'pktcnt' argument. This value "
00236 "should be a positive integer or zero.\n",
00237 file_name, file_line);
00238 }
00239
00240 iPkts = atoi(Tokens[++i]);
00241 if( iPkts < 0 )
00242 iPkts = 1000;
00243 }
00244 else if (!strcmp(Tokens[i], "atexitonly"))
00245 {
00246 iStatsExit = 1;
00247 }
00248 else
00249 {
00250 FatalError("%s(%d)=> Invalid parameter '%s' to preprocessor"
00251 " PerfMonitor.\n", file_name, file_line, Tokens[i]);
00252 }
00253 }
00254
00255 mSplitFree(&Tokens, iTokenNum);
00256
00257
00258
00259
00260 sfInitPerformanceStatistics(&sfPerf);
00261
00262 sfSetPerformanceSampleTime( &sfPerf, iTime );
00263
00264 sfSetPerformanceStatistics( &sfPerf, SFPERF_BASE );
00265
00266 sfSetPerformanceAccounting( &sfPerf, iReset );
00267
00268 if( iFlow ) sfSetPerformanceStatistics( &sfPerf, SFPERF_FLOW );
00269
00270 if( iEvents) sfSetPerformanceStatistics( &sfPerf, SFPERF_EVENT );
00271
00272 if( iMaxPerfStats ) sfSetPerformanceStatistics(&sfPerf, SFPERF_BASE_MAX);
00273
00274 if( iConsole ) sfSetPerformanceStatistics( &sfPerf, SFPERF_CONSOLE );
00275
00276 if( iFile && iSnortFile )
00277 {
00278 FatalError("%s(%d)=> Cannot log to both 'file' and 'snortfile'.\n",
00279 file_name, file_line);
00280 }
00281
00282 if( iFile || iSnortFile || strlen(perf_file) )
00283 {
00284
00285 if( strlen(perf_file) )
00286 {
00287 iFile=1;
00288 if( sfSetPerformanceStatisticsEx( &sfPerf, SFPERF_FILE, perf_file ) )
00289 {
00290 FatalError("Cannot open performance log file '%s'\n",perf_file);
00291 }
00292 }
00293 else
00294 {
00295 if(iFile)
00296 {
00297 if( sfSetPerformanceStatisticsEx( &sfPerf, SFPERF_FILE, file ) )
00298 {
00299 FatalError("Cannot open performance log file '%s'\n",file);
00300 }
00301 }
00302 else if(iSnortFile)
00303 {
00304 if( sfSetPerformanceStatisticsEx(&sfPerf, SFPERF_FILE, snortfile) )
00305 {
00306 FatalError("Cannot open performance log file '%s'\n",snortfile);
00307 }
00308 }
00309 }
00310 }
00311
00312 if( iPkts) sfSetPerformanceStatisticsEx( &sfPerf, SFPERF_PKTCNT, &iPkts );
00313 if( iStatsExit) sfSetPerformanceStatisticsEx( &sfPerf, SFPERF_SUMMARY, &iStatsExit );
00314
00315 LogMessage("PerfMonitor config:\n");
00316 LogMessage(" Time: %d seconds\n", iTime);
00317 LogMessage(" Flow Stats: %s\n", iFlow ? "ACTIVE" : "INACTIVE");
00318 LogMessage(" Event Stats: %s\n", iEvents ? "ACTIVE" : "INACTIVE");
00319 LogMessage(" Max Perf Stats: %s\n",
00320 iMaxPerfStats ? "ACTIVE" : "INACTIVE");
00321 LogMessage(" Console Mode: %s\n", iConsole ? "ACTIVE" : "INACTIVE");
00322 LogMessage(" File Mode: %s\n",
00323 iFile ? file : "INACTIVE");
00324 LogMessage(" SnortFile Mode: %s\n",
00325 iSnortFile ? snortfile : "INACTIVE");
00326 LogMessage(" Packet Count: %d\n", iPkts);
00327 LogMessage(" Dump Summary: %s\n", sfPerf.iPerfFlags & SFPERF_SUMMARY ?
00328 "Yes" : "No");
00329
00330 if (sfPerf.iPerfFlags & SFPERF_SUMMARY)
00331 {
00332 AddFuncToCleanExitList(PerfMonitorCleanExit, NULL);
00333 CheckSampleInterval(time(NULL), &sfPerf);
00334 }
00335
00336 return;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 static void ProcessPerfMonitor(Packet *p, void *context)
00354 {
00355
00356
00357
00358 if (!(p->preprocessors & PP_PERFMONITOR))
00359 return;
00360
00361 if (pv.rotate_perf_file)
00362 {
00363 sfRotatePerformanceStatisticsFile(&sfPerf);
00364 pv.rotate_perf_file = 0;
00365 }
00366
00367 if(sfPerf.sample_interval > 0)
00368 {
00369 if(p->pkth)
00370 {
00371 sfPerformanceStats(&sfPerf, p->pkt, p->pkth->caplen,
00372 p->packet_flags & PKT_REBUILT_STREAM);
00373 }
00374 }
00375
00376 if( p->tcph )
00377 {
00378 if((p->tcph->th_flags & TH_SYN) && !(p->tcph->th_flags & TH_ACK))
00379 {
00380
00381 sfPerf.sfBase.iSyns++;
00382 }
00383 else if((p->tcph->th_flags & TH_SYN) && (p->tcph->th_flags & TH_ACK ))
00384 {
00385
00386 sfPerf.sfBase.iSynAcks++;
00387 }
00388 }
00389
00390
00391
00392
00393 if(sfPerf.iPerfFlags & SFPERF_FLOW)
00394 {
00395
00396
00397
00398 if( p->tcph )
00399 {
00400 UpdateTCPFlowStatsEx(p->sp, p->dp, p->pkth->caplen);
00401 }
00402
00403
00404
00405 else if( p->udph )
00406 UpdateUDPFlowStatsEx(p->sp, p->dp, p->pkth->caplen);
00407
00408
00409
00410
00411 else if( p->icmph )
00412 UpdateICMPFlowStatsEx(p->icmph->type, p->pkth->caplen);
00413 }
00414
00415 return;
00416 }
00417
00418
00419
00420
00421 void PerfMonitorCleanExit(int signal, void *foo)
00422 {
00423 sfProcessPerfStats(&sfPerf);
00424 return;
00425 }
00426