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
00029
00030
00031
00032
00033 #include <time.h>
00034
00035 #include "snort.h"
00036 #include "decode.h"
00037 #include "debug.h"
00038 #include "plugbase.h"
00039 #include "util.h"
00040 #include "parser.h"
00041
00042 #include "spp_flow.h"
00043 #include "flow/flow.h"
00044 #include "flow/flow_cache.h"
00045 #include "flow/flow_callback.h"
00046 #include "flow/flow_class.h"
00047 #include "flow/flow_print.h"
00048 #include "flow/portscan/flowps_snort.h"
00049
00050 #define DEFAULT_MEMCAP (1024 * 1024 * 10)
00051 #define DEFAULT_ROWS (1024 * 4)
00052 #define DEFAULT_STAT_INTERVAL 0
00053
00054 typedef struct _SPPFLOW_CONFIG
00055 {
00056 int stats_interval;
00057 int memcap;
00058 int rows;
00059 FLOWHASHID hashid;
00060 } SPPFLOW_CONFIG;
00061
00062 static int s_flow_running = 0;
00063 static FLOWCACHE s_fcache;
00064 static SPPFLOW_CONFIG s_config;
00065
00066 static int FlowParseArgs(SPPFLOW_CONFIG *config, char *args);
00067 static INLINE int FlowPacket(Packet *p);
00068 static void FlowPreprocessor(Packet *p, void *);
00069 static void FlowInit(u_char *args);
00070 static void FlowCleanExit(int signal, void *data);
00071 static void FlowRestart(int signal, void *data);
00072 static void FlowParseOption(SPPFLOW_CONFIG *config,
00073 char *fname, int lineno,
00074 char *key, char *value);
00075 static void DisplayFlowConfig(void);
00076
00077 static int s_debug = 0;
00078 unsigned int giFlowbitSize = 64;
00079
00080
00081
00082
00083
00084
00085 void SetupFlow(void)
00086 {
00087
00088
00089
00090 RegisterPreprocessor("flow", FlowInit);
00091
00092
00093 SetupFlowPS();
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 static INLINE int FlowPacket(Packet *p)
00107 {
00108 if(!p->iph)
00109 return 0;
00110
00111 if(p->frag_flag)
00112 return 0;
00113
00114
00115
00116
00117
00118
00119 return 1;
00120 }
00121
00122
00123
00124
00125
00126
00127 static void FlowInit(u_char *args)
00128 {
00129 static int init_once = 0;
00130 int ret;
00131 static SPPFLOW_CONFIG *config = &s_config;
00132
00133 if(init_once)
00134 FatalError("%s(%d) Unable to reinitialize flow!\n", file_name, file_line);
00135 else
00136 init_once = 1;
00137
00138
00139 config->stats_interval = DEFAULT_STAT_INTERVAL;
00140 config->memcap = DEFAULT_MEMCAP;
00141 config->rows = DEFAULT_ROWS;
00142 config->hashid = HASH2;
00143 FlowParseArgs(config, args);
00144
00145 if((ret = flowcache_init(&s_fcache, config->rows, config->memcap,
00146 giFlowbitSize, config->hashid)) != FLOW_SUCCESS)
00147 {
00148 FatalError("Unable to initialize the flow cache!"
00149 "-- try more memory (current memcap is %d)\n", config->memcap);
00150 }
00151
00152 DisplayFlowConfig();
00153
00154 s_flow_running = 1;
00155
00156 AddFuncToPreprocList(FlowPreprocessor);
00157 AddFuncToCleanExitList(FlowCleanExit, NULL);
00158 AddFuncToRestartList(FlowRestart, NULL);
00159 }
00160
00161 static void FlowRestart(int signal, void *data)
00162 {
00163 return;
00164 }
00165
00166 static void FlowCleanExit(int signal, void *data)
00167 {
00168 fflush(stdout);
00169 LogMessage("Final Flow Statistics\n");
00170 if(!pv.quiet_flag)
00171 flowcache_stats(stdout, &s_fcache);
00172 fflush(stdout);
00173 flowcache_destroy(&s_fcache);
00174 return;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 static void FlowPreprocessor(Packet *p, void *context)
00186 {
00187 int flow_class;
00188 int direction;
00189 static time_t last_output = 0;
00190 FLOWKEY search_key;
00191 FLOW *fp;
00192 FLOWCACHE *fcache = &s_fcache;
00193 FLOWPACKET *pkt = (FLOWPACKET *) p;
00194
00195 if(!FlowPacket(p))
00196 {
00197 return;
00198 }
00199
00200
00201 if(flow_classifier(pkt, &flow_class) != FLOW_SUCCESS)
00202 {
00203
00204 return;
00205 }
00206
00207 switch(flow_class)
00208 {
00209 case FLOW_IPV4:
00210 if(flowkey_make(&search_key, pkt) != FLOW_SUCCESS)
00211 {
00212 ErrorMessage("Unable to make a search key\n");
00213 return;
00214 }
00215 break;
00216 default:
00217 ErrorMessage("Unknown Flow Type: %d\n", flow_class);
00218 return;
00219 }
00220
00221
00222
00223
00224 if(flowcache_find(fcache, &search_key, &fp, &direction) == FLOW_SUCCESS)
00225 {
00226
00227
00228
00229
00230 if(p->packet_flags & PKT_REBUILT_STREAM)
00231 {
00232 p->flow = fp;
00233 return;
00234 }
00235
00236 if(direction == FROM_RESPONDER && fp->stats.packets_recv == 0)
00237 {
00238
00239 flow_callbacks(FLOW_FIRST_BIDIRECTIONAL, fp, direction, p);
00240 }
00241
00242 flow_callbacks(FLOW_ADDITIONAL, fp, direction, pkt);
00243 }
00244 else
00245 {
00246
00247
00248
00249
00250 if(p->packet_flags & PKT_REBUILT_STREAM)
00251 {
00252 return;
00253 }
00254
00255 if(flowcache_newflow(fcache, &search_key, &fp) != FLOW_SUCCESS)
00256 {
00257 flow_printf("***ERROR: "); flowkey_print(&search_key); flow_printf("\n");
00258 }
00259
00260 direction = FROM_INITIATOR;
00261
00262 flow_callbacks(FLOW_NEW, fp, FROM_INITIATOR, pkt);
00263 }
00264
00265 fp->stats.direction = direction;
00266
00267
00268 if(s_config.stats_interval &&
00269 ((last_output + s_config.stats_interval) <= p->pkth->ts.tv_sec))
00270 {
00271 last_output = p->pkth->ts.tv_sec;
00272
00273 if(!pv.quiet_flag)
00274 flowcache_stats(stdout, fcache);
00275 }
00276
00277 p->flow = fp;
00278
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 int CheckFlowShutdown(Packet *p)
00291 {
00292 FLOWCACHE *fcache = &s_fcache;
00293
00294 FLOW *flowp = (FLOW *) p->flow;
00295
00296 if(flowp != NULL)
00297 {
00298 if(flow_checkflag(flowp, FLOW_CLOSEME))
00299 {
00300
00301 flow_callbacks(FLOW_SHUTDOWN, flowp, FROM_INITIATOR, p);
00302
00303 if(flowcache_releaseflow(fcache, &flowp) != FLOW_SUCCESS)
00304 {
00305 flow_printf("Can't release flow %p\n", p->flow);
00306 return FLOW_BADJUJU;
00307 }
00308 }
00309 }
00310
00311 p->flow = NULL;
00312
00313 return FLOW_SUCCESS;
00314 }
00315
00316
00317 static int FlowParseArgs(SPPFLOW_CONFIG *config, char *args)
00318 {
00319 char *key, *value;
00320 char *myargs = NULL;
00321 const char *delim = " \t";
00322
00323 if(args)
00324 {
00325 if(s_debug > 5)
00326 flow_printf("I'm parsing %s!\n", args);
00327
00328 myargs = strdup(args);
00329
00330 if(myargs == NULL)
00331 FatalError("Out of memory parsing flow arguments\n");
00332 }
00333 else
00334 {
00335 if(s_debug > 5)
00336 flow_printf("nothing to parse for this flow!\n");
00337
00338 return 0;
00339 }
00340
00341 key = strtok(myargs, delim);
00342
00343 while(key != NULL)
00344 {
00345 value = strtok(NULL, delim);
00346
00347 if(!value)
00348 {
00349 FatalError("%s(%d) key %s has no value", file_name, file_line);
00350 }
00351
00352 FlowParseOption(config, file_name, file_line, key, value);
00353 key = strtok(NULL, delim);
00354 }
00355
00356 if(myargs)
00357 free(myargs);
00358
00359 return 0;
00360 }
00361
00362 static void FlowParseOption(SPPFLOW_CONFIG *config,
00363 char *fname, int lineno,
00364 char *key, char *value)
00365 {
00366 if(!strcasecmp(key, "memcap"))
00367 {
00368 config->memcap = atoi(value);
00369 }
00370 else if(!strcasecmp(key, "rows"))
00371 {
00372 config->rows = atoi(value);
00373 }
00374 else if(!strcasecmp(key, "stats_interval"))
00375 {
00376 config->stats_interval = atoi(value);
00377 }
00378 else if(!strcasecmp(key, "hash"))
00379 {
00380 switch(atoi(value))
00381 {
00382 case 1:
00383 config->hashid = HASH1;
00384 break;
00385 case 2:
00386 config->hashid = HASH2;
00387 break;
00388 default:
00389 FatalError("%s(%d) Unknown Hash Type: key(%s) value(%s)\n",
00390 fname, lineno, key, value);
00391 }
00392 }
00393
00394 else
00395 {
00396 FatalError("%s(%d) Unknown Arguments: key(%s) value(%s)\n",
00397 fname, lineno, key, value);
00398 }
00399
00400 }
00401
00402
00403
00404
00405
00406
00407 static void DisplayFlowConfig(void)
00408 {
00409 SPPFLOW_CONFIG *cp = &s_config;
00410 FLOWCACHE *fcp = &s_fcache;
00411
00412 LogMessage(",-----------[Flow Config]----------------------\n");
00413 LogMessage("| Stats Interval: %d\n", cp->stats_interval);
00414 LogMessage("| Hash Method: %d\n", cp->hashid);
00415 LogMessage("| Memcap: %d\n", cp->memcap);
00416 LogMessage("| Rows : %d\n", flowcache_row_count(fcp));
00417 LogMessage("| Overhead Bytes: %d(%%%.2lf)\n",
00418 flowcache_overhead_bytes(fcp),
00419 calc_percent(flowcache_overhead_bytes(fcp),cp->memcap));
00420 LogMessage("`----------------------------------------------\n");
00421
00422 }
00423
00424
00425
00426
00427
00428
00429
00430 int SppFlowIsRunning(void)
00431 {
00432 return s_flow_running;
00433 }