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
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #ifdef HAVE_CONFIG_H
00053 #include "config.h"
00054 #endif
00055
00056
00057 #include <sys/types.h>
00058 #include <stdlib.h>
00059 #include <ctype.h>
00060 #include <rpc/types.h>
00061
00062 #include "bounds.h"
00063 #include "generators.h"
00064 #include "log.h"
00065 #include "detect.h"
00066 #include "decode.h"
00067 #include "event.h"
00068 #include "util.h"
00069 #include "debug.h"
00070 #include "plugbase.h"
00071 #include "parser.h"
00072 #include "mstring.h"
00073 #include "checksum.h"
00074 #include "perf.h"
00075 #include "event_queue.h"
00076
00077 #include "ubi_BinTree.h"
00078 #include "ubi_SplayTree.h"
00079
00080 #include "snort.h"
00081
00082 void Frag2Init(u_char *args);
00083
00084
00085 #define FRAG_GOT_FIRST 0x00000001
00086 #define FRAG_GOT_LAST 0x00000002
00087 #define FRAG_REBUILT 0x00000004
00088 #define FRAG_OUTOFORDER 0x00000008
00089
00090
00091 #define FRAG_PRUNE_QUANTA 60
00092 #define FRAG_MEMCAP 4194304
00093
00094 #define FRAG2_TTL_LIMIT 5
00095 #define FRAG2_MIN_TTL 0
00096
00097 #if defined (SOLARIS) || defined (SUNOS) || defined (__sparc__) || defined(__sparc64__) || defined (HPUX)
00098 #define SPARC_TWIDDLE 2
00099 #else
00100 #define SPARC_TWIDDLE 0
00101 #endif
00102
00103 #define DATASIZE (ETHERNET_HEADER_LEN+65536)
00104
00105
00106 #define SELF_PRES_THRESHOLD 500
00107 #define SELF_PRES_PERIOD 90
00108
00109 #define SUSPEND_THRESHOLD 1000
00110 #define SUSPEND_PERIOD 30
00111
00112 #define OPS_NORMAL 0
00113 #define OPS_SELF_PRESERVATION 1
00114 #define OPS_SUSPEND 2
00115
00116
00117
00118 typedef struct _Frag2Data
00119 {
00120 u_int8_t os_flags;
00121 u_int32_t memcap;
00122 u_int32_t frag_timeout;
00123 u_int32_t last_prune_time;
00124 u_int8_t stop_traverse;
00125
00126 u_int8_t min_ttl;
00127 u_int8_t ttl_limit;
00128 char frag2_alerts;
00129
00130 u_int32_t sp_threshold;
00131 u_int32_t sp_period;
00132
00133 u_int32_t suspend_threshold;
00134 u_int32_t suspend_period;
00135
00136 char state_protection;
00137
00138 SPMemControl frag_sp_data;
00139 } Frag2Data;
00140
00141
00142 typedef struct _Frag2Frag
00143 {
00144 ubi_trNode Node;
00145
00146 u_int8_t *data;
00147 u_int16_t size;
00148 u_int16_t offset;
00149 } Frag2Frag;
00150
00151 typedef struct _FragTracker
00152 {
00153 ubi_trNode Node;
00154
00155 u_int32_t sip;
00156 u_int32_t dip;
00157 u_int16_t id;
00158 u_int8_t protocol;
00159
00160 u_int8_t ttl;
00161 u_int8_t alerted;
00162
00163 u_int32_t frag_flags;
00164 u_int32_t last_frag_time;
00165
00166 u_int32_t frag_bytes;
00167 u_int32_t calculated_size;
00168 u_int32_t frag_pkts;
00169
00170 ubi_trRoot fraglist;
00171 ubi_trRootPtr fraglistPtr;
00172 } FragTracker;
00173
00174 typedef struct _CompletionData
00175 {
00176 u_int8_t complete;
00177 u_int8_t teardrop;
00178 u_int8_t outoforder;
00179 } CompletionData;
00180
00181 typedef struct _F2Emergency
00182 {
00183 long end_time;
00184 unsigned long new_frag_count;
00185 int status;
00186 } F2Emergency;
00187
00188
00189 typedef struct _F2SPControl
00190 {
00191 FragTracker *ft;
00192 time_t cur_time;
00193
00194 } F2SPControl;
00195
00196
00197 static ubi_trRoot f_cache;
00198 static ubi_trRootPtr FragRootPtr = &f_cache;
00199
00200 extern char *file_name;
00201 extern int file_line;
00202
00203 static int frag_mem_usage;
00204
00205 static u_int16_t next_offset;
00206 static u_int32_t frag2_alloc_faults;
00207
00208 static Frag2Data f2data;
00209 static Packet *defrag_pkt;
00210
00211 F2Emergency f2_emergency;
00212
00213
00214 void ParseFrag2Args(u_char *);
00215 void Frag2Defrag(Packet *, void *);
00216 FragTracker *GetFragTracker(Packet *);
00217 FragTracker *NewFragTracker(Packet *);
00218 int InsertFrag(Packet *, FragTracker *);
00219 int FragIsComplete(FragTracker *, CompletionData *);
00220 void RebuildFrag(FragTracker *, Packet *);
00221 void Frag2DeleteFrag(FragTracker *);
00222 int Frag2SelfPreserve(struct _SPMemControl *);
00223 int PruneFragCache(FragTracker *, u_int32_t, u_int32_t);
00224 void ZapFrag(FragTracker *);
00225 void Frag2InitPkt();
00226 void Frag2CleanExit(int, void *);
00227 void Frag2Restart(int, void *);
00228
00229 int Frag2SelfPreserve(struct _SPMemControl *spmc)
00230 {
00231 F2SPControl *ctrl = (F2SPControl *)spmc->control;
00232
00233 frag2_alloc_faults++;
00234 pc.frag_mem_faults++;
00235 sfPerf.sfBase.iFragFaults++;
00236
00237 if(!PruneFragCache(ctrl->ft, (u_int32_t)ctrl->cur_time, 0))
00238 {
00239
00240 PruneFragCache(ctrl->ft, 0, 5);
00241 }
00242
00243 return 0;
00244 }
00245
00246 void *Frag2Alloc(FragTracker *cft, int tv_sec, u_int32_t size)
00247 {
00248 void *tmp;
00249
00250 frag_mem_usage += size;
00251
00252
00253 if( (u_int32_t)frag_mem_usage > f2data.memcap)
00254 {
00255
00256 frag2_alloc_faults++;
00257 pc.frag_mem_faults++;
00258 sfPerf.sfBase.iFragFaults++;
00259
00260
00261 if(!PruneFragCache(cft, (u_int32_t)tv_sec, 0))
00262 {
00263
00264 PruneFragCache(cft, 0, 5);
00265 }
00266 }
00267
00268 tmp = (void *) calloc(size, sizeof(char));
00269
00270 if(tmp == NULL)
00271 {
00272 FatalError("spp_defrag: Unable to allocate memory! "
00273 "(%u bytes in use)\n", frag_mem_usage);
00274 }
00275
00276 return tmp;
00277 }
00278
00279
00280 static int Frag2CompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr)
00281 {
00282 FragTracker *nFt;
00283 FragTracker *iFt;
00284
00285 nFt = (FragTracker *) NodePtr;
00286 iFt = (FragTracker *) ItemPtr;
00287
00288 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,"NodePtr: sip: 0x%X dip: 0x%X ip: 0x%X "
00289 "proto: 0x%X\n", nFt->sip, nFt->dip, nFt->id, nFt->protocol);
00290 DebugMessage(DEBUG_FRAG,"ItemPtr: sip: 0x%X dip: 0x%X ip: 0x%X "
00291 "proto: 0x%X\n", iFt->sip, iFt->dip, iFt->id, iFt->protocol););
00292
00293 if(nFt->sip < iFt->sip) return 1;
00294 if(nFt->sip > iFt->sip) return -1;
00295 if(nFt->dip < iFt->dip) return 1;
00296 if(nFt->dip > iFt->dip) return -1;
00297 if(nFt->id < iFt->id) return 1;
00298 if(nFt->id > iFt->id) return -1;
00299 if(nFt->protocol < iFt->protocol) return 1;
00300 if(nFt->protocol > iFt->protocol) return -1;
00301
00302 return 0;
00303 }
00304
00305
00306 static int Frag2FragCompare(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr)
00307 {
00308 Frag2Frag *nFrag;
00309 Frag2Frag *iFrag;
00310
00311 nFrag = (Frag2Frag *) NodePtr;
00312 iFrag = (Frag2Frag *) ItemPtr;
00313
00314 if(nFrag->offset < iFrag->offset) return 1;
00315 if(nFrag->offset > iFrag->offset) return -1;
00316
00317 return 0;
00318 }
00319
00320
00321
00322 static void CompletionTraverse(ubi_trNodePtr NodePtr, void *complete)
00323 {
00324 Frag2Frag *frag;
00325 CompletionData *comp = (CompletionData *) complete;
00326
00327 frag = (Frag2Frag *) NodePtr;
00328
00329 if(frag->offset == next_offset)
00330 {
00331 next_offset = frag->offset + frag->size;
00332 }
00333 else if(frag->offset < next_offset)
00334 {
00335
00336 comp->teardrop = 1;
00337
00338 if(frag->size + frag->offset > next_offset)
00339 {
00340 next_offset = frag->offset + frag->size;
00341 }
00342 }
00343 else if(frag->offset > next_offset)
00344 {
00345 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Holes in completion check... (%u > %u)\n",
00346 frag->offset, next_offset););
00347 comp->complete = 0;
00348 }
00349
00350 return;
00351 }
00352
00353 static void RebuildTraverse(ubi_trNodePtr NodePtr, void *buffer)
00354 {
00355 Frag2Frag *frag;
00356 u_int8_t *buf = (u_int8_t *)buffer;
00357
00358 if(f2data.stop_traverse)
00359 return;
00360
00361 frag = (Frag2Frag *)NodePtr;
00362
00363 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "frag offset: 0x%X size: %lu pointer: %p\n",
00364 (unsigned int) frag->offset, (unsigned long) frag->size,
00365 (buf+frag->offset)););
00366
00367 if((frag->offset + frag->size) < 65516)
00368 {
00369 SafeMemcpy(buf+frag->offset, frag->data, frag->size,
00370 defrag_pkt->pkt, defrag_pkt->pkt + DATASIZE);
00371 pc.rebuild_element++;
00372 }
00373 else
00374 {
00375 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "frag2: pkt rebuild size violation\n"););
00376 f2data.stop_traverse = 1;
00377 }
00378
00379 return;
00380 }
00381
00382 static void KillFrag(ubi_trNodePtr NodePtr)
00383 {
00384 Frag2Frag *frag;
00385
00386 frag = (Frag2Frag *) NodePtr;
00387
00388
00389 f2data.frag_sp_data.mem_usage -= frag->size;
00390 free(frag->data);
00391
00392
00393 f2data.frag_sp_data.mem_usage -= sizeof(Frag2Frag);
00394 free(frag);
00395
00396 }
00397
00398
00399 void SetupFrag2()
00400 {
00401 RegisterPreprocessor("frag2", Frag2Init);
00402 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Preprocessor: frag2 is setup...\n"););
00403 }
00404
00405
00406 void Frag2Init(u_char *args)
00407 {
00408
00409 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Initializing frag2\n"););
00410
00411 f2data.last_prune_time = 0;
00412 f2data.frag2_alerts = 0;
00413 f2data.min_ttl = FRAG2_MIN_TTL;
00414 f2data.ttl_limit = FRAG2_TTL_LIMIT;
00415
00416
00417 f2data.sp_threshold = SELF_PRES_THRESHOLD;
00418 f2data.sp_period = SELF_PRES_PERIOD;
00419 f2data.suspend_threshold = SUSPEND_THRESHOLD;
00420 f2data.suspend_period = SUSPEND_PERIOD;
00421 f2data.state_protection = 0;
00422
00423
00424 f2_emergency.end_time = 0;
00425 f2_emergency.new_frag_count = 0;
00426 f2_emergency.status = OPS_NORMAL;
00427
00428
00429 ParseFrag2Args(args);
00430
00431 (void)ubi_trInitTree(FragRootPtr,
00432 Frag2CompareFunc,
00433 0);
00434
00435 defrag_pkt = (Packet *)calloc(sizeof(Packet), sizeof(char));
00436
00437 if(!defrag_pkt)
00438 {
00439 FatalError("Unable to allocate defrag packet!\n");
00440 }
00441
00442 Frag2InitPkt();
00443
00444 AddFuncToPreprocList(Frag2Defrag);
00445 AddFuncToCleanExitList(Frag2CleanExit, NULL);
00446 AddFuncToRestartList(Frag2Restart, NULL);
00447 }
00448
00449
00450 void ParseFrag2Args(u_char *args)
00451 {
00452 char **toks;
00453 int num_toks;
00454 int i;
00455 char *index;
00456 char **stoks = NULL;
00457 int s_toks;
00458
00459 if(args == NULL || strlen(args) == 0)
00460 {
00461 f2data.memcap = FRAG_MEMCAP;
00462 f2data.frag_timeout = FRAG_PRUNE_QUANTA;
00463 f2data.ttl_limit = FRAG2_TTL_LIMIT;
00464 f2data.min_ttl = FRAG2_MIN_TTL;
00465 f2data.frag2_alerts = 0;
00466
00467 f2data.frag_sp_data.memcap = FRAG_MEMCAP;
00468 f2data.frag_sp_data.mem_usage = 0;
00469 f2data.frag_sp_data.fault_count = 0;
00470 f2data.frag_sp_data.sp_func = Frag2SelfPreserve;
00471
00472 if(!pv.quiet_flag)
00473 {
00474 LogMessage("No arguments to frag2 directive, "
00475 "setting defaults to:\n");
00476 LogMessage(" Fragment timeout: %d seconds\n",
00477 f2data.frag_timeout);
00478 LogMessage(" Fragment memory cap: %lu bytes\n", (unsigned long)f2data.memcap);
00479 LogMessage(" Fragment min_ttl: %d\n", f2data.min_ttl);
00480 LogMessage(" Fragment ttl_limit: %d\n", f2data.ttl_limit);
00481 LogMessage(" Fragment Problems: %d\n", f2data.frag2_alerts);
00482 LogMessage(" Self preservation threshold: %d\n", f2data.sp_threshold);
00483 LogMessage(" Self preservation period: %d\n", f2data.sp_period);
00484 LogMessage(" Suspend threshold: %d\n", f2data.suspend_threshold);
00485 LogMessage(" Suspend period: %d\n", f2data.suspend_period);
00486
00487 }
00488
00489 return;
00490 }
00491 else
00492 {
00493 f2data.memcap = FRAG_MEMCAP;
00494 f2data.frag_timeout = FRAG_PRUNE_QUANTA;
00495
00496 toks = mSplit(args, ",", 12, &num_toks, 0);
00497
00498 i=0;
00499
00500 while(i < num_toks)
00501 {
00502 index = toks[i];
00503
00504 while(isspace((int)*index)) index++;
00505
00506 stoks = mSplit(index, " ", 4, &s_toks, 0);
00507
00508 if(!strncasecmp(stoks[0], "timeout", 7))
00509 {
00510 if(stoks[1] && isdigit((int)stoks[1][0]))
00511 {
00512 f2data.frag_timeout = atoi(stoks[1]);
00513 }
00514 else
00515 {
00516 LogMessage("WARNING %s(%d) => Bad timeout in config file, "
00517 "defaulting to %d seconds\n", file_name, file_line, FRAG_PRUNE_QUANTA);
00518
00519 f2data.frag_timeout = FRAG_PRUNE_QUANTA;
00520 }
00521 }
00522 else if(!strncasecmp(stoks[0], "memcap", 6))
00523 {
00524 if(stoks[1] && isdigit((int)stoks[1][0]))
00525 {
00526 f2data.memcap = atoi(stoks[1]);
00527
00528 if(f2data.memcap < 16384)
00529 {
00530 LogMessage("WARNING %s(%d) => Ludicrous (<16k) memcap "
00531 "size, setting to default (%d bytes)\n",
00532 file_name, file_line, FRAG_MEMCAP);
00533
00534 f2data.memcap = FRAG_MEMCAP;
00535 }
00536 }
00537 else
00538 {
00539 LogMessage("WARNING %s(%d) => Bad memcap in config file, "
00540 "defaulting to %u bytes\n", file_name, file_line,
00541 FRAG_MEMCAP);
00542
00543 f2data.memcap = FRAG_MEMCAP;
00544 }
00545 }
00546 else if(!strcasecmp(stoks[0], "ttl_limit"))
00547 {
00548 if(s_toks > 1)
00549 {
00550 if(stoks[1] == NULL || stoks[1][0] == '\0')
00551 {
00552 FatalError("%s(%d) => ttl_limit requires an integer "
00553 "argument\n", file_name,file_line);
00554 }
00555
00556 if(isdigit((int)stoks[1][0]))
00557 {
00558 f2data.ttl_limit = atoi(stoks[1]);
00559 }
00560 else
00561 {
00562 LogMessage("WARNING %s(%d) => Bad TTL Limit"
00563 "size, setting to default (%d\n", file_name,
00564 file_line, FRAG2_TTL_LIMIT);
00565
00566 f2data.ttl_limit = FRAG2_TTL_LIMIT;
00567 }
00568 }
00569 else
00570 {
00571 FatalError("%s(%d) => ttl_limit requires an integer "
00572 "argument\n", file_name,file_line);
00573 }
00574 }
00575 else if(!strcasecmp(stoks[0], "min_ttl"))
00576 {
00577 if(isdigit((int)stoks[1][0]))
00578 {
00579 f2data.min_ttl = atoi(stoks[1]);
00580 }
00581 else
00582 {
00583 LogMessage("WARNING %s(%d) => Bad TTL Limit"
00584 "size, setting to default (%d\n", file_name,
00585 file_line, FRAG2_MIN_TTL);
00586
00587 f2data.min_ttl = FRAG2_MIN_TTL;
00588 }
00589 }
00590 else if(!strcasecmp(stoks[0], "detect_state_problems"))
00591 {
00592 f2data.frag2_alerts = 1;
00593 }
00594 else if(!strcasecmp(stoks[0], "self_preservation_threshold"))
00595 {
00596 if(isdigit((int)stoks[1][0]))
00597 {
00598 f2data.sp_threshold = atoi(stoks[1]);
00599 }
00600 else
00601 {
00602 LogMessage("WARNING %s(%d) => Bad sp_threshold in config file, "
00603 "defaulting to %d new sessions/second\n", file_name, file_line,
00604 SELF_PRES_THRESHOLD);
00605
00606 f2data.sp_threshold = SELF_PRES_THRESHOLD;
00607 }
00608 }
00609 else if(!strcasecmp(stoks[0], "self_preservation_period"))
00610 {
00611 if(isdigit((int)stoks[1][0]))
00612 {
00613 f2data.sp_period = atoi(stoks[1]);
00614 }
00615 else
00616 {
00617 LogMessage("WARNING %s(%d) => Bad sp_period in config file, "
00618 "defaulting to %d seconds\n", file_name, file_line,
00619 SELF_PRES_PERIOD);
00620
00621 f2data.sp_period = SELF_PRES_PERIOD;
00622 }
00623 }
00624 else if(!strcasecmp(stoks[0], "suspend_threshold"))
00625 {
00626 if(isdigit((int)stoks[1][0]))
00627 {
00628 f2data.suspend_threshold = atoi(stoks[1]);
00629 }
00630 else
00631 {
00632 LogMessage("WARNING %s(%d) => Bad suspend_threshold in config file, "
00633 "defaulting to %d new sessions/second\n", file_name, file_line,
00634 SUSPEND_THRESHOLD);
00635
00636 f2data.suspend_threshold = SUSPEND_THRESHOLD;
00637 }
00638 }
00639 else if(!strcasecmp(stoks[0], "suspend_period"))
00640 {
00641 if(isdigit((int)stoks[1][0]))
00642 {
00643 f2data.suspend_period = atoi(stoks[1]);
00644 }
00645 else
00646 {
00647 LogMessage("WARNING %s(%d) => Bad suspend_period in config file, "
00648 "defaulting to %d seconds\n", file_name, file_line,
00649 SUSPEND_PERIOD);
00650
00651 f2data.suspend_period = SUSPEND_PERIOD;
00652 }
00653 }
00654 else if(!strcasecmp(stoks[0], "state_protection"))
00655 {
00656 f2data.state_protection = 1;
00657 }
00658
00659
00660 mSplitFree(&stoks, s_toks);
00661
00662 i++;
00663 }
00664
00665 f2data.frag_sp_data.memcap = f2data.memcap;
00666 f2data.frag_sp_data.mem_usage = 0;
00667 f2data.frag_sp_data.fault_count = 0;
00668 f2data.frag_sp_data.sp_func = Frag2SelfPreserve;
00669
00670 mSplitFree(&toks, num_toks);
00671
00672 LogMessage("[*] Frag2 config:\n");
00673 LogMessage(" Fragment timeout: %d seconds\n",
00674 f2data.frag_timeout);
00675 LogMessage(" Fragment memory cap: %lu bytes\n", (unsigned long)f2data.memcap);
00676 LogMessage(" Fragment min_ttl: %d\n", f2data.min_ttl);
00677 LogMessage(" Fragment ttl_limit: %d\n", f2data.ttl_limit);
00678 LogMessage(" Fragment Problems: %d\n", f2data.frag2_alerts);
00679 LogMessage(" State Protection: %d\n", f2data.state_protection);
00680
00681 LogMessage(" Self preservation threshold: %d\n", f2data.sp_threshold);
00682 LogMessage(" Self preservation period: %d\n", f2data.sp_period);
00683 LogMessage(" Suspend threshold: %d\n", f2data.suspend_threshold);
00684 LogMessage(" Suspend period: %d\n", f2data.suspend_period);
00685
00686 }
00687 }
00688
00689 void Frag2Defrag(Packet *p, void *context)
00690 {
00691 FragTracker *ft;
00692 static int alert_once_emerg = 0;
00693 static int alert_once_suspend = 0;
00694
00695 if(!(p->preprocessors & PP_FRAG2))
00696 {
00697 return;
00698 }
00699
00700 if(f2_emergency.status != OPS_NORMAL)
00701 {
00702
00703
00704
00705
00706 if(p->pkth->ts.tv_sec >= f2_emergency.end_time)
00707 {
00708 f2_emergency.status = OPS_NORMAL;
00709 f2_emergency.end_time = 0;
00710 f2_emergency.new_frag_count = 0;
00711 }
00712
00713 if(f2_emergency.status == OPS_SUSPEND)
00714 {
00715 return;
00716 }
00717 }
00718
00719
00720 if(p == NULL || p->iph == NULL || !p->frag_flag)
00721 {
00722 return;
00723 }
00724
00725 if(p->csum_flags & CSE_IP)
00726 {
00727 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Discarding invalid IP checksum\n"););
00728 return;
00729 }
00730
00731 if(p->packet_flags & PKT_REBUILT_FRAG)
00732 {
00733 return;
00734 }
00735
00736 if(p->ip_options_len)
00737 {
00738 if(f2data.frag2_alerts)
00739 {
00740 SnortEventqAdd(GENERATOR_SPP_FRAG2, FRAG2_IPOPTIONS,
00741 1, 0, 5, FRAG2_IPOPTIONS_STR, 0);
00742 return;
00743 }
00744 }
00745
00746 if(p->iph->ip_ttl < f2data.min_ttl)
00747 {
00748 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Got frag packet (mem use: %u frag "
00749 "trackers: %d p->pkt_flags: 0x%X)\n", f2data.frag_sp_data.mem_usage,
00750 ubi_trCount(FragRootPtr), p->packet_flags););
00751 return;
00752 }
00753
00754
00755 if (!f2data.last_prune_time)
00756 f2data.last_prune_time = p->pkth->ts.tv_sec;
00757
00758 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Got frag packet (mem use: %lu frag "
00759 "trackers: %d p->pkt_flags: 0x%X)\n", f2data.frag_sp_data.mem_usage,
00760 ubi_trCount(FragRootPtr), p->packet_flags););
00761
00762 ft = GetFragTracker(p);
00763
00764 if(ft == NULL)
00765 {
00766 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Didn't find frag packet\n"););
00767 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Adding New FragTracker...\n"););
00768
00769
00770
00771
00772
00773
00774
00775
00776 if((f2_emergency.status == OPS_NORMAL) || (p->mf && p->frag_offset == 0))
00777 {
00778 ft = NewFragTracker(p);
00779
00780
00781
00782
00783
00784
00785 if(f2data.state_protection)
00786 ++f2_emergency.new_frag_count;
00787
00788 } else {
00789 ft = NULL;
00790 }
00791
00792 if(f2data.state_protection)
00793 {
00794 if(f2_emergency.new_frag_count >= f2data.suspend_threshold)
00795 {
00796 f2_emergency.status = OPS_SUSPEND;
00797 f2_emergency.end_time = p->pkth->ts.tv_sec + f2data.suspend_period;
00798
00799 if(alert_once_suspend == 0)
00800 {
00801 SnortEventqAdd(GENERATOR_SPP_FRAG2, FRAG2_SUSPEND,
00802 1, 0, 5, FRAG2_SUSPEND_STR, 0);
00803
00804 alert_once_suspend = 1;
00805 }
00806
00807 }
00808 else if (f2_emergency.new_frag_count >= f2data.sp_threshold)
00809 {
00810 f2_emergency.status = OPS_SELF_PRESERVATION;
00811 f2_emergency.end_time = p->pkth->ts.tv_sec + f2data.sp_period;
00812
00813 if(alert_once_emerg == 0)
00814 {
00815 SnortEventqAdd(GENERATOR_SPP_FRAG2, FRAG2_EMERGENCY,
00816 1, 0, 5, FRAG2_EMERGENCY_STR, 0);
00817
00818 alert_once_emerg = 1;
00819 }
00820 }
00821 }
00822
00823
00824 if(ft == NULL)
00825 {
00826 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
00827 "Discarding fragment, Disabling Detection\n"););
00828
00829
00830
00831
00832
00833
00834 DisableDetect(p);
00835 }
00836
00837 UpdateIPFragStats(&(sfPerf.sfBase), p->pkth->caplen);
00838 return;
00839 }
00840
00841
00842 if(ft->alerted == 1)
00843 {
00844
00845 return;
00846 }
00847
00848 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Found frag packet\n"););
00849
00850
00851 if(f2data.ttl_limit)
00852 {
00853
00854 if(abs(ft->ttl - p->iph->ip_ttl) >= f2data.ttl_limit)
00855 {
00856 SnortEventqAdd(GENERATOR_SPP_FRAG2, FRAG2_TTL_EVASION,
00857 1, 0, 5, FRAG2_TTL_EVASION_STR, 0);
00858
00859
00860 return;
00861 }
00862 }
00863
00864 if(InsertFrag(p, ft) == -1)
00865 {
00866 if(pv.verbose_flag)
00867 {
00868 LogMessage("WARNING: Insert into Fraglist failed"
00869 ", probably duplicate fragment (offset: %u)\n",
00870 p->frag_offset);
00871 }
00872
00873 return;
00874 }
00875 else
00876 {
00877 CompletionData compdata;
00878
00879 compdata.complete = 0;
00880 compdata.teardrop = 0;
00881 compdata.outoforder = 0;
00882
00883 if(FragIsComplete(ft, &compdata))
00884 {
00885 if(compdata.teardrop)
00886 {
00887 SnortEventqAdd(GENERATOR_SPP_FRAG2, FRAG2_TEARDROP,
00888 1, 0, 5, FRAG2_TEARDROP_STR, 0);
00889
00890 ft->alerted = 1;
00891 DisableDetect(p);
00892 return;
00893 }
00894 else if(f2data.frag2_alerts &&
00895 compdata.outoforder &&
00896 !(p->packet_flags & PKT_FRAG_ALERTED))
00897 {
00898 SnortEventqAdd(GENERATOR_SPP_FRAG2, FRAG2_OUTOFORDER,
00899 1, 0, 5, FRAG2_OUTOFORDER_STR, 0);
00900
00901 DisableDetect(p);
00902 p->packet_flags |= PKT_FRAG_ALERTED;
00903 return;
00904 }
00905
00906 RebuildFrag(ft, p);
00907
00908 } else {
00909 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Fragment not complete\n"););
00910 }
00911
00912 UpdateIPFragStats(&(sfPerf.sfBase), p->pkth->caplen);
00913 }
00914
00915 if( (u_int32_t)(p->pkth->ts.tv_sec) >
00916 (f2data.last_prune_time + f2data.frag_timeout))
00917 {
00918 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Prune time quanta for defrag code hit, "
00919 "pruning frag tree...\n"););
00920 PruneFragCache(ft, p->pkth->ts.tv_sec, 0);
00921 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Finished pruning, %lu frag trackers "
00922 "active, %lu alloc faults\n", ubi_trCount(FragRootPtr),
00923 (unsigned long) frag2_alloc_faults););
00924
00925 f2data.last_prune_time = p->pkth->ts.tv_sec;
00926 }
00927
00928 return;
00929 }
00930
00931
00932
00933 FragTracker *GetFragTracker(Packet *p)
00934 {
00935 FragTracker ft;
00936 FragTracker *returned;
00937
00938 if(ubi_trCount(FragRootPtr) == 0)
00939 return NULL;
00940
00941 if(f2data.frag_sp_data.mem_usage == 0)
00942 {
00943 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "trCount says nodes exist but "
00944 "f2data.frag_sp_data.mem_usage = 0\n"););
00945 return NULL;
00946 }
00947
00948 ft.sip = p->iph->ip_src.s_addr;
00949 ft.dip = p->iph->ip_dst.s_addr;
00950 ft.id = p->iph->ip_id;
00951 ft.protocol = p->iph->ip_proto;
00952
00953 returned = (FragTracker *) ubi_sptFind(FragRootPtr, (ubi_btItemPtr)&ft);
00954 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "returning %p\n", returned););
00955
00956 return returned;
00957 }
00958
00959
00960 FragTracker *NewFragTracker(Packet *p)
00961 {
00962 FragTracker *tmp;
00963 F2SPControl sp;
00964
00965
00966 sp.ft = NULL;
00967 sp.cur_time = p->pkth->ts.tv_sec;
00968
00969
00970 f2data.frag_sp_data.control = &sp;
00971
00972
00973
00974
00975 tmp = SPAlloc(sizeof(FragTracker), &(f2data.frag_sp_data));
00976
00977
00978 tmp->sip = p->iph->ip_src.s_addr;
00979 tmp->dip = p->iph->ip_dst.s_addr;
00980 tmp->id = p->iph->ip_id;
00981 tmp->protocol = p->iph->ip_proto;
00982
00983 tmp->fraglistPtr = &tmp->fraglist;
00984
00985 tmp->ttl = p->iph->ip_ttl;
00986
00987
00988 (void)ubi_trInitTree(tmp->fraglistPtr,
00989 Frag2FragCompare,
00990 0);
00991
00992
00993 if(InsertFrag(p, tmp) != -1)
00994 {
00995
00996 if(ubi_sptInsert(FragRootPtr, (ubi_btNodePtr)tmp,
00997 (ubi_btNodePtr)tmp, NULL) == FALSE)
00998 {
00999 LogMessage("NewFragTracker: sptInsert() failed\n");
01000 Frag2DeleteFrag(tmp);
01001 return NULL;
01002 }
01003 }
01004 else
01005 {
01006 f2data.frag_sp_data.mem_usage -= sizeof(FragTracker);
01007 free(tmp);
01008 return NULL;
01009 }
01010
01011 pc.frag_trackers++;
01012
01013 return tmp;
01014 }
01015
01016
01017 int InsertFrag(Packet *p, FragTracker *ft)
01018 {
01019 Frag2Frag *returned;
01020 Frag2Frag *newfrag;
01021 F2SPControl sp;
01022
01023 sfPerf.sfBase.iFragInserts++;
01024
01025 if(ft->frag_bytes + p->dsize > 70000)
01026 {
01027
01028 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01029 "Exiting out because of memusage %d, %d",
01030 ft->frag_bytes, p->dsize););
01031
01032 SnortEventqAdd(GENERATOR_SPP_FRAG2, FRAG2_OVERSIZE_FRAG,
01033 1, 0, 5, FRAG2_OVERSIZE_FRAG_STR, 0);
01034
01035 DisableDetect(p);
01036 ft->alerted = 1;
01037 return -1;
01038 }
01039
01040
01041
01042 if(p->mf && p->frag_offset == 0)
01043 {
01044 if(ft->frag_flags & FRAG_GOT_FIRST)
01045 {
01046 if(f2data.frag2_alerts)
01047 {
01048 SnortEventqAdd(GENERATOR_SPP_FRAG2, FRAG2_DUPFIRST,
01049 1, 0, 5, FRAG2_DUPFIRST_STR, 0);
01050
01051 p->packet_flags |= PKT_FRAG_ALERTED;
01052 }
01053 return -1;
01054 }
01055 else
01056 {
01057 ft->frag_flags |= FRAG_GOT_FIRST;
01058 }
01059 }
01060 else if(!p->mf && p->frag_offset > 0)
01061 {
01062 ft->frag_flags |= FRAG_GOT_LAST;
01063 ft->calculated_size = (p->frag_offset << 3) + p->dsize;
01064 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Bytes: %d, Calculated size: %d\n",
01065 ft->frag_bytes,
01066 ft->calculated_size););
01067
01068 if(ft->calculated_size > 65516)
01069 {
01070 SnortEventqAdd(GENERATOR_SPP_FRAG2, FRAG2_OVERSIZE_FRAG,
01071 1, 0, 5, FRAG2_OVERSIZE_FRAG_STR, 0);
01072
01073 return -1;
01074 }
01075
01076 }
01077
01078 if(!(ft->frag_flags & FRAG_GOT_FIRST))
01079 {
01080 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "setting out of order!"););
01081 ft->frag_flags |= FRAG_OUTOFORDER;
01082 }
01083
01084 ft->last_frag_time = p->pkth->ts.tv_sec;
01085 ft->frag_pkts++;
01086 ft->frag_bytes += p->dsize;
01087 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "ft->frag_bytes: %u %u!\n", ft->frag_bytes, f2data.frag_sp_data.mem_usage););
01088
01089
01090 sp.ft = ft;
01091 sp.cur_time = p->pkth->ts.tv_sec;
01092 f2data.frag_sp_data.control = &sp;
01093
01094
01095
01096
01097 newfrag = (Frag2Frag *) SPAlloc(sizeof(Frag2Frag), &(f2data.frag_sp_data));
01098
01099
01100 newfrag->data = (u_int8_t *) SPAlloc(p->dsize, &(f2data.frag_sp_data));
01101
01102 memcpy(newfrag->data, p->data, p->dsize);
01103
01104 newfrag->offset = p->frag_offset << 3;
01105 newfrag->size = p->dsize;
01106
01107 returned = (Frag2Frag *) ubi_sptFind(ft->fraglistPtr,
01108 (ubi_btItemPtr)newfrag);
01109
01110 if(returned != NULL)
01111 {
01112 if(f2data.frag2_alerts && !(p->packet_flags & PKT_FRAG_ALERTED))
01113 {
01114 SnortEventqAdd(GENERATOR_SPP_FRAG2, FRAG2_OVERLAP,
01115 1, 0, 5, FRAG2_OVERLAP_STR, 0);
01116
01117 p->packet_flags |= PKT_FRAG_ALERTED;
01118 DisableDetect(p);
01119 }
01120
01121
01122 f2data.frag_sp_data.mem_usage -= newfrag->size;
01123 free(newfrag->data);
01124
01125 f2data.frag_sp_data.mem_usage -= sizeof(Frag2Frag);
01126 free(newfrag);
01127 return 0;
01128 }
01129
01130 if(ubi_sptInsert(ft->fraglistPtr, (ubi_btNodePtr)newfrag,
01131 (ubi_btNodePtr)newfrag, NULL) == ubi_trFALSE)
01132 {
01133 LogMessage("InsertFrag: sptInsert failed\n");
01134
01135
01136
01137
01138
01139 f2data.frag_sp_data.mem_usage -= newfrag->size;
01140 free(newfrag->data);
01141 f2data.frag_sp_data.mem_usage -= sizeof(Frag2Frag);
01142 free(newfrag);
01143 return -1;
01144 }
01145
01146 return 0;
01147 }
01148
01149
01150
01151 int FragIsComplete(FragTracker *ft, CompletionData *compdata)
01152 {
01153 compdata->complete = 1;
01154
01155 sfPerf.sfBase.iFragCompletes++;
01156
01157 if(ft->frag_flags & FRAG_REBUILT)
01158 {
01159
01160
01161 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01162 "my frag is already rebuilt! %d\n",
01163 (ft->frag_flags & FRAG_OUTOFORDER)););
01164 compdata->outoforder = 1;
01165 }
01166
01167 if((ft->frag_flags & (FRAG_GOT_FIRST|FRAG_GOT_LAST)) ==
01168 (FRAG_GOT_FIRST|FRAG_GOT_LAST))
01169 {
01170
01171 next_offset = 0;
01172
01173
01174 (void)ubi_trTraverse(ft->fraglistPtr, CompletionTraverse, compdata);
01175
01176 return compdata->complete;
01177 }
01178 else
01179 {
01180 return 0;
01181 }
01182 }
01183
01184
01185 void RebuildFrag(FragTracker *ft, Packet *p)
01186 {
01187 u_int8_t *rebuild_ptr;
01188
01189 sfPerf.sfBase.iFragFlushes++;
01190
01191 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Rebuilding pkt [0x%X:%d 0x%X:%d]\n",
01192 p->iph->ip_src.s_addr, p->sp, p->iph->ip_dst.s_addr, p->dp);
01193 DebugMessage(DEBUG_FRAG, "Calculated size: %d\n", ft->calculated_size);
01194 DebugMessage(DEBUG_FRAG, "Frag Bytes: %d\n", ft->frag_bytes);
01195 );
01196
01197 if(ft->calculated_size > 65516)
01198 {
01199 LogMessage("WARNING: Dumping oversized fragment\n");
01200 ZapFrag(ft);
01201 }
01202
01203
01204 defrag_pkt->pkth->ts.tv_sec = p->pkth->ts.tv_sec;
01205 defrag_pkt->pkth->ts.tv_usec = p->pkth->ts.tv_usec;
01206
01207
01208 SafeMemcpy(defrag_pkt->pkt, p->pkt, ETHERNET_HEADER_LEN + sizeof(IPHdr),
01209 defrag_pkt->pkt, defrag_pkt->pkt + DATASIZE);
01210
01211
01212
01213
01214 rebuild_ptr = defrag_pkt->pkt + ETHERNET_HEADER_LEN + sizeof(IPHdr);
01215
01216
01217 defrag_pkt->iph = (IPHdr *) (defrag_pkt->pkt + ETHERNET_HEADER_LEN);
01218
01219
01220 defrag_pkt->iph->ip_off = 0x0000;
01221 defrag_pkt->frag_flag = 0;
01222
01223
01224 f2data.stop_traverse = 0;
01225 (void)ubi_trTraverse(ft->fraglistPtr, RebuildTraverse, rebuild_ptr);
01226 f2data.stop_traverse = 0;
01227
01228
01229 if((ETHERNET_HEADER_LEN + ft->calculated_size + sizeof(IPHdr)) > 65535)
01230 {
01231
01232
01233
01234
01235 #ifdef DONT_TRUNCATE
01236 defrag_pkt->pkth->caplen = 65535;
01237 #else
01238 defrag_pkt->pkth->caplen = ETHERNET_HEADER_LEN +
01239 ft->calculated_size + sizeof(IPHdr);
01240 #endif
01241
01242 }
01243 else
01244 {
01245 defrag_pkt->pkth->caplen = ETHERNET_HEADER_LEN +
01246 ft->calculated_size + sizeof(IPHdr);
01247 }
01248
01249 defrag_pkt->pkth->len = defrag_pkt->pkth->caplen;
01250
01251
01252 defrag_pkt->iph->ip_len = htons((u_short)(defrag_pkt->pkth->len - ETHERNET_HEADER_LEN));
01253
01254
01255 defrag_pkt->packet_flags = PKT_REBUILT_FRAG;
01256 defrag_pkt->frag_flag = 0;
01257
01258 defrag_pkt->iph->ip_csum = 0;
01259
01260
01261 defrag_pkt->iph->ip_csum = in_chksum_ip((u_int16_t *)defrag_pkt->iph, sizeof(IPHdr));
01262
01263 pc.rebuilt_frags++;
01264
01265 #ifdef DEBUG
01266 ClearDumpBuf();
01267
01268 ClearDumpBuf();
01269 #endif
01270
01271
01272 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Processing rebuilt packet:\n"););
01273 UpdateIPReassStats(&(sfPerf.sfBase), defrag_pkt->pkth->caplen);
01274 ProcessPacket(NULL, defrag_pkt->pkth, defrag_pkt->pkt, NULL);
01275 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Done with rebuilt packet, marking rebuilt...\n"););
01276
01277 ft->frag_flags = ft->frag_flags | FRAG_REBUILT;
01278
01279
01280
01281
01282
01283
01284
01285
01286 }
01287
01288
01289 void Frag2DeleteFrag(FragTracker *ft)
01290 {
01291 if(ft == NULL)
01292 {
01293 return;
01294 }
01295
01296 sfPerf.sfBase.iFragDeletes++;
01297
01298 (void)ubi_trKillTree(ft->fraglistPtr, KillFrag);
01299
01300 f2data.frag_sp_data.mem_usage -= sizeof(FragTracker);
01301 free(ft);
01302 }
01303
01304
01305
01306 int PruneFragCache(FragTracker *cft, u_int32_t time, u_int32_t mustdie)
01307 {
01308 FragTracker *ft;
01309 u_int32_t pruned = 0;
01310
01311 if(ubi_trCount(FragRootPtr) == 0)
01312 return 0;
01313
01314 ft = (FragTracker *) ubi_btFirst((ubi_btNodePtr)FragRootPtr);
01315
01316 if(ft == NULL)
01317 return 0;
01318
01319 if(time)
01320 {
01321 do
01322 {
01323 if((ft->frag_flags & FRAG_REBUILT) ||
01324 ft->last_frag_time + f2data.frag_timeout < time)
01325 {
01326 FragTracker *savft = ft;
01327
01328 sfPerf.sfBase.iFragTimeouts++;
01329
01330 ft = (FragTracker *) ubi_btNext((ubi_btNodePtr)ft);
01331
01332 if (savft != cft && ubi_trCount(FragRootPtr) > 1)
01333 {
01334 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Pruning stale fragment\n"););
01335 ZapFrag(savft);
01336 pc.frag_timeout++;
01337 pruned++;
01338 }
01339 }
01340 else
01341 {
01342 if(ft !=NULL && ubi_trCount(FragRootPtr)) {
01343 ft = (FragTracker *) ubi_btNext((ubi_btNodePtr)ft);
01344 } else {
01345 return pruned;
01346 }
01347 }
01348 } while(ft != NULL);
01349
01350 return pruned;
01351 }
01352 else
01353 {
01354
01355 while(mustdie-- && ubi_trCount(FragRootPtr) > 1)
01356 {
01357
01358
01359
01360
01361
01362 ft = (FragTracker *) ubi_btLeafNode((ubi_btNodePtr) FragRootPtr);
01363 if(ft != cft)
01364 {
01365 ZapFrag(ft);
01366 pc.frag_incomp++;
01367 }
01368 }
01369
01370 return mustdie;
01371 }
01372
01373 return 0;
01374 }
01375
01376
01377
01378
01379
01380
01381
01382
01383 void ZapFrag(FragTracker *ft)
01384 {
01385 FragTracker *killme;
01386
01387 if(ft != NULL && FragRootPtr->count != 0)
01388 {
01389 killme = (FragTracker *) ubi_sptRemove(FragRootPtr,
01390 (ubi_btNodePtr) ft);
01391
01392 if(killme != NULL)
01393 Frag2DeleteFrag(killme);
01394 }
01395 }
01396
01397
01398
01399 void Frag2Restart(int signal, void *foo)
01400 {
01401 return;
01402 }
01403
01404
01405
01406 void Frag2CleanExit(int signal, void *foo)
01407 {
01408 return;
01409 }
01410
01411
01412 void Frag2InitPkt()
01413 {
01414 defrag_pkt->pkth = calloc(sizeof(SnortPktHeader), sizeof(char));
01415 defrag_pkt->pkt = (u_int8_t *) calloc(DATASIZE + SPARC_TWIDDLE, sizeof(char));
01416
01417
01418 defrag_pkt->pkt += SPARC_TWIDDLE;
01419
01420 if(defrag_pkt->pkth == NULL || defrag_pkt->pkt == NULL)
01421 {
01422 FatalError("Out of memory on Frag2InitPkt()\n");
01423 }
01424 }