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

spp_frag2.c

Go to the documentation of this file.
00001 /* $Id$ */
00002 /*
00003 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
00004 **
00005 ** This program is free software; you can redistribute it and/or modify
00006 ** it under the terms of the GNU General Public License as published by
00007 ** the Free Software Foundation; either version 2 of the License, or
00008 ** (at your option) any later version.
00009 **
00010 ** This program is distributed in the hope that it will be useful,
00011 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 ** GNU General Public License for more details.
00014 **
00015 ** You should have received a copy of the GNU General Public License
00016 ** along with this program; if not, write to the Free Software
00017 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018 */
00019 /*
00020  * Bugfixes;
00021  *
00022  *  Aug  1 15:28:36 MDT 2001, cpw: changed to use packet time for all time
00023  *  comparisons.  Modified calling sequence on a number subroutines to
00024  *  pass down current FragTracker and time to PruneFragCache.  The
00025  *  current FragTracker was getting released early by PruneFragCache
00026  *  which led to a segmentation fault.  I'd suggest a look see at
00027  *  PruneFragCache to see that is doing things in the right order.  Not
00028  *  knowing how it all works, I assumed that the loop was from oldest to
00029  *  newest.
00030  *  Using snort compiled with this version I was able to successfully
00031  *  process a gaggle of frags (GOF).  An individual packet looked like this:
00032  *  14:11:21.020324 a.11071 > b.11070: udp 8000 (frag 62829:1480@0+)
00033  *  14:11:21.020327 a > b: frag 1480 (frag 62829:1480@1480+)
00034  *  14:11:21.020329 a > b: frag 1480 (frag 62829:1480@2960+)
00035  *  14:11:21.020412 a > b: frag 1480 (frag 62829:1480@4440+)
00036  *  14:11:21.020416 a > b: frag 1480 (frag 62829:1480@5920+)
00037  *  14:11:21.020418 a > 134.253.164.21: frag 608 (frag 62829:608@7400)
00038  *  There were about 301066 full packets read from a 821947618 byte file.
00039  *
00040  *  Prior to this patch, I got the following seg fault:
00041  *  #0  ubi_btInsert (RootPtr=0x48, NewNode=0x8a94f10, ItemPtr=0x8a94f10,
00042  *      OldNode=0xbfffee7c) at ubi_BinTree.c:637
00043  *  #1  0x8077825 in ubi_sptInsert (RootPtr=0x48, NewNode=0x8a94f10,
00044  *      ItemPtr=0x8a94f10, OldNode=0x0) at ubi_SplayTree.c:317
00045  *  #2  0x807c08e in InsertFrag (p=0xbfffef5c, ft=0x874bdc8) at spp_frag2.c:534
00046  *  #3  0x807be82 in Frag2Defrag (p=0xbfffef5c) at spp_frag2.c:430
00047  *  #4  0x8058416 in Preprocess (p=0xbfffef5c) at rules.c:3427
00048  *  ...
00049  */
00050 
00051 /*  I N C L U D E S  ************************************************/
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 /*  D E F I N E S  **************************************************/
00085 #define FRAG_GOT_FIRST      0x00000001
00086 #define FRAG_GOT_LAST       0x00000002
00087 #define FRAG_REBUILT        0x00000004
00088 #define FRAG_OUTOFORDER     0x00000008 /* did we get other frags than
00089                                           MF Offset 0 first? */
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 /* values for the smartbits detector/self perservation */
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 /*  D A T A   S T R U C T U R E S  **********************************/
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; /* Minimum TTL to accept */
00127     u_int8_t ttl_limit; /* Size of ttls to avoid detection on */
00128     char frag2_alerts; /* Wether or not frag2 alerts are enabled */
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; /* self preservation 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;          /* src IP */
00156     u_int32_t dip;          /* dst IP */
00157     u_int16_t id;           /* IP ID */
00158     u_int8_t protocol;      /* IP protocol */
00159 
00160     u_int8_t ttl;  /* ttl used to detect evasions */
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 /*  G L O B A L S  **************************************************/
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 /*  P R O T O T Y P E S  ********************************************/
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         /* if we can't prune due to time, just nuke 5 random sessions */
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     /* if we use up all of our RAM, try to free up some stale frags */
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             /* if we can't prune due to time, just nuke 5 random sessions */
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         /* flag a teardrop attack detection */
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     //frag_mem_usage -= frag->size;
00389     f2data.frag_sp_data.mem_usage -= frag->size;
00390     free(frag->data);
00391 
00392     //frag_mem_usage -= sizeof(Frag2Frag);
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     /* initialize the f2 Emergency stuff */
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,        /* ptr to the tree head */
00432                          Frag2CompareFunc,   /* comparison function */
00433                          0);                 /* no dups */
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;  /* 4MB */
00462         f2data.frag_timeout = FRAG_PRUNE_QUANTA; /* 60 seconds */
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         /* Check to see if we should return to our non-emergency mode.
00703          * If we happen to stay in SUSPSEND mode, exit out
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     /* make sure we're interested in this packet */
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          * Much like keeping track of stream sessions, if someone
00771          * starts blasting us with fragments without an initial fragment,
00772          * the IDS will suffer.
00773          *
00774          * Here we will mitigate this with another two stage approach.
00775          */
00776         if((f2_emergency.status == OPS_NORMAL) || (p->mf && p->frag_offset == 0))
00777         {
00778             ft = NewFragTracker(p);            
00779 
00780             /* 
00781              * keep track of how many sessions per second we're creating vs. the number
00782              * of data packets per second we get on those sessions
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              * Mark that this packet isn't worth doing IDS on.  This
00831              * is self preservation because either our system is under
00832              * session trashing attacks.
00833              */
00834             DisableDetect(p);
00835         }
00836 
00837         UpdateIPFragStats(&(sfPerf.sfBase), p->pkth->caplen);
00838         return;
00839     }
00840 
00841     /* ft is not NULL at this point */
00842     if(ft->alerted == 1)
00843     {
00844         /* one alert per fragment is good enough */
00845         return;
00846     }
00847 
00848     DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Found frag packet\n"););
00849 
00850     /* detect ttl based evasion techniques */
00851     if(f2data.ttl_limit) 
00852     {
00853         /* ft->ttl is already set in the ft a few lines above */
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             /* lets just go look at real events from now on. */
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;  /* self preservation control data */
00964 
00965     /* set the current frag tracker (none needed here) */
00966     sp.ft = NULL;
00967     sp.cur_time = p->pkth->ts.tv_sec; /* self pres funcs need to know what time it is */
00968 
00969     /* link the control data to the self pres data struct */
00970     f2data.frag_sp_data.control = &sp;
00971 
00972     /* allocate space for a frag tracker */
00973     //tmp = Frag2Alloc(NULL, p->pkth->ts.tv_sec, sizeof(FragTracker));
00974 
00975     tmp = SPAlloc(sizeof(FragTracker), &(f2data.frag_sp_data));
00976 
00977     /* set the frag tracker data fields */
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; /* store the first ttl we got */
00986     
00987     /* initialize the fragment list */
00988     (void)ubi_trInitTree(tmp->fraglistPtr,    /* ptr to the tree head */
00989                          Frag2FragCompare,    /* comparison function */
00990                          0);                  /* dups ok */
00991 
00992     /* insert the fragment into the frag list */
00993     if(InsertFrag(p, tmp) != -1)
00994     {
00995         /* insert the frag tracker into the fragment tree */
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         /* only allow a minimum of overlap in the fragment system */
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     /* set the frag flag if this is the first fragment */
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     //newfrag = (Frag2Frag *) Frag2Alloc(ft, p->pkth->ts.tv_sec, 
01095     //        sizeof(Frag2Frag));
01096 
01097     newfrag = (Frag2Frag *) SPAlloc(sizeof(Frag2Frag), &(f2data.frag_sp_data));
01098 
01099     //newfrag->data = (u_int8_t *) Frag2Alloc(ft, p->pkth->ts.tv_sec, p->dsize);
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         /* we favor old data */
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          * if there was a problem inserting the fragment into the fraglist
01137          * nuke it
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         /* we probably put the frag together wrong. lets atleast tell
01160            people that */
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         /* global data for CompletionTraverse */
01171         next_offset = 0;
01172 
01173         /* traverse the frag tree and see if they're all there.... */
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     /* set the timestamps on the rebuild packet from the last packet of the frag */
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     /* copy the packet data from the last packet of the frag */
01208     SafeMemcpy(defrag_pkt->pkt, p->pkt, ETHERNET_HEADER_LEN + sizeof(IPHdr),
01209                defrag_pkt->pkt, defrag_pkt->pkt + DATASIZE);
01210     /* set the pointer to the beginning of the transport layer of the rebuilt
01211      * packet
01212      */
01213     
01214     rebuild_ptr = defrag_pkt->pkt + ETHERNET_HEADER_LEN + sizeof(IPHdr);
01215 
01216     /* reset the ip header pointer */
01217     defrag_pkt->iph = (IPHdr *) (defrag_pkt->pkt + ETHERNET_HEADER_LEN);
01218     
01219     /* clear the packet fragment fields */ 
01220     defrag_pkt->iph->ip_off = 0x0000;
01221     defrag_pkt->frag_flag = 0;
01222 
01223     /* walk the fragment list and rebuild the packet */
01224     f2data.stop_traverse = 0;
01225     (void)ubi_trTraverse(ft->fraglistPtr, RebuildTraverse, rebuild_ptr);
01226     f2data.stop_traverse = 0;
01227 
01228     /* set the new packet's capture length */
01229     if((ETHERNET_HEADER_LEN + ft->calculated_size + sizeof(IPHdr)) > 65535)
01230     {
01231         /* don't let other pcap apps die when they process this file
01232          * -- yes this opens us up for 14 bytes at the end of the
01233          * giant packet.
01234          */
01235 #ifdef DONT_TRUNCATE
01236         defrag_pkt->pkth->caplen = 65535;
01237 #else /* DONT_TRUNCATE */
01238         defrag_pkt->pkth->caplen = ETHERNET_HEADER_LEN +
01239             ft->calculated_size + sizeof(IPHdr);
01240 #endif /* DONT_TRUNCATE */
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     /* set the ip dgm length */
01252     defrag_pkt->iph->ip_len = htons((u_short)(defrag_pkt->pkth->len - ETHERNET_HEADER_LEN));
01253 
01254     /* tell the rest of the system that this is a rebuilt fragment */
01255     defrag_pkt->packet_flags = PKT_REBUILT_FRAG;
01256     defrag_pkt->frag_flag = 0;
01257 
01258     defrag_pkt->iph->ip_csum = 0;
01259         
01260     /* calculate the ip checksum for the packet */
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     //PrintNetData(stdout, defrag_pkt->pkt, defrag_pkt->pkth->caplen);
01268     ClearDumpBuf();
01269 #endif
01270 
01271     /* process the packet through the detection engine */
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     /* dump the packet frags */
01281     /* ZapFrag(ft);
01282 
01283     Now always done asynchronously because of the problem of detecting
01284     a full out frag assault after the fact ( fragroute t4 )
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         /* Make sure we don't free the root. */
01355         while(mustdie-- && ubi_trCount(FragRootPtr) > 1)
01356         {
01357             /* 
01358              * this code pulls a random leaf node from the frag tree for
01359              * deletion, allowing us to unpredicatably zap nodes which are
01360              * pretty stale anyway
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  * Remove a fragment tracker from the Fragment Tree
01380  * 
01381  * @param ft fragment tracker to whack
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     /* kludge for alignment */
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 }

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