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
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #ifdef HAVE_CONFIG_H
00078 #include "config.h"
00079 #endif
00080
00081 #include <sys/types.h>
00082 #include <stdlib.h>
00083 #include <ctype.h>
00084 #include <rpc/types.h>
00085
00086 #include "bounds.h"
00087 #include "generators.h"
00088 #include "log.h"
00089 #include "detect.h"
00090 #include "decode.h"
00091 #include "event.h"
00092 #include "util.h"
00093 #include "debug.h"
00094 #include "plugbase.h"
00095 #include "parser.h"
00096 #include "mstring.h"
00097 #include "checksum.h"
00098 #include "perf.h"
00099 #include "event_queue.h"
00100 #include "timersub.h"
00101 #include "fpcreate.h"
00102
00103 #include "sfutil/sflsq.h"
00104 #include "sfutil/sfxhash.h"
00105
00106 #include "snort.h"
00107 extern OptTreeNode *otn_tmp;
00108
00109
00110
00111
00112 #define FRAG_GOT_FIRST 0x00000001
00113 #define FRAG_GOT_LAST 0x00000002
00114 #define FRAG_REBUILT 0x00000004
00115 #define FRAG_BAD 0x00000008
00116
00117 #define FRAG_PRUNE_QUANTA 60
00118
00119
00120
00121
00122 #define FRAG_MEMCAP 4194304
00123
00124 #define FRAG3_TTL_LIMIT 5
00125
00126 #define FRAG3_MIN_TTL 1
00127
00128
00129 #define FRAG_POLICY_FIRST 1
00130 #define FRAG_POLICY_LINUX 2
00131 #define FRAG_POLICY_BSD 3
00132 #define FRAG_POLICY_BSD_RIGHT 4
00133 #define FRAG_POLICY_LAST 5
00134 #define FRAG_POLICY_WINDOWS 6
00135
00136
00137 #define FRAG_POLICY_SOLARIS 7
00138
00139
00140
00141
00142
00143
00144 #if defined (SOLARIS) || defined (SUNOS) || defined (__sparc__) || defined(__sparc64__) || defined (HPUX)
00145 #define SPARC_TWIDDLE 2
00146 #else
00147 #define SPARC_TWIDDLE 0
00148 #endif
00149
00150
00151 #define DATASIZE (ETHERNET_HEADER_LEN+IP_MAXPACKET)
00152
00153
00154 #define DEFAULT_MAX_FRAGS 8192
00155
00156
00157 #define FRAG_TIME_OK 0
00158 #define FRAG_TIMEOUT 1
00159
00160
00161 #define FRAG_INSERT_OK 0
00162 #define FRAG_INSERT_FAILED 1
00163 #define FRAG_INSERT_REJECTED 2
00164 #define FRAG_INSERT_TIMEOUT 3
00165 #define FRAG_INSERT_ATTACK 4
00166 #define FRAG_INSERT_ANOMALY 5
00167 #define FRAG_INSERT_TTL 6
00168
00169
00170 #define FRAG_FIRSTLAST_OK 0
00171 #define FRAG_LAST_DUPLICATE 1
00172
00173
00174 #define FRAG_OK 0
00175 #define FRAG_TRACKER_TIMEOUT 1
00176 #define FRAG_LAST_OFFSET_ADJUST 2
00177
00178
00179 #define FRAG3_DETECT_ANOMALIES 0x01
00180
00181
00182
00183
00184 typedef struct
00185 {
00186 u_int32_t max_frags;
00187 u_int32_t memcap;
00188 u_int32_t static_frags;
00189 u_int8_t use_prealloc;
00190
00191 } Frag3GlobalConfig;
00192
00193
00194 typedef struct _Frag3Context
00195 {
00196 u_int16_t frag_policy;
00197 int32_t frag_timeout;
00198
00199 u_int8_t min_ttl;
00200 u_int8_t ttl_limit;
00201
00202 char frag3_alerts;
00203
00204 IpAddrSet *bound_addrs;
00205
00206 } Frag3Context;
00207
00208
00209 typedef struct _Frag3Frag
00210 {
00211 u_int8_t *data;
00212 u_int16_t size;
00213 u_int16_t offset;
00214
00215 u_int8_t *fptr;
00216 u_int16_t flen;
00217
00218 struct _Frag3Frag *prev;
00219 struct _Frag3Frag *next;
00220
00221 int ord;
00222 char last;
00223 } Frag3Frag;
00224
00225
00226 typedef struct _fragkey
00227 {
00228 u_int32_t sip;
00229 u_int32_t dip;
00230 u_int16_t id;
00231 u_int8_t proto;
00232 } FRAGKEY;
00233
00234
00235 #define MAX_FRAG_ALERTS 8
00236
00237
00238 typedef struct _FragTracker
00239 {
00240 u_int32_t sip;
00241 u_int32_t dip;
00242 u_int16_t id;
00243 u_int8_t protocol;
00244
00245 u_int8_t ttl;
00246 u_int8_t alerted;
00247 u_int32_t frag_flags;
00248
00249 u_int32_t frag_bytes;
00250
00251
00252
00253 u_int32_t calculated_size;
00254
00255
00256
00257 u_int32_t frag_pkts;
00258
00259 struct timeval frag_time;
00260
00261 Frag3Frag *fraglist;
00262 Frag3Frag *fraglist_tail;
00263 int fraglist_count;
00264
00265 u_int32_t alert_gid[MAX_FRAG_ALERTS];
00266 u_int32_t alert_sid[MAX_FRAG_ALERTS];
00267 u_int8_t alert_count;
00268
00269 u_int32_t ip_options_len;
00270 u_int32_t ip_option_count;
00271 u_int8_t *ip_options_data;
00272
00273 u_int32_t copied_ip_options_len;
00274 u_int32_t copied_ip_option_count;
00275
00276 Frag3Context *context;
00277
00278 int ordinal;
00279
00280 } FragTracker;
00281
00282
00283 typedef struct _Frag3Stats
00284 {
00285 u_int32_t total;
00286 u_int32_t overlaps;
00287 u_int32_t reassembles;
00288 u_int32_t prunes;
00289 u_int32_t timeouts;
00290 u_int32_t fragtrackers_created;
00291 u_int32_t fragtrackers_released;
00292 u_int32_t fragtrackers_autoreleased;
00293 u_int32_t fragnodes_created;
00294 u_int32_t fragnodes_released;
00295 u_int32_t discards;
00296 u_int32_t anomalies;
00297 u_int32_t alerts;
00298
00299 } Frag3Stats;
00300
00301
00302
00303 static Frag3GlobalConfig global_config;
00304 static SFXHASH *f_cache;
00305 static Frag3Frag *prealloc_frag_list;
00306
00307 static char global_init_complete;
00308
00309 static u_int32_t mem_in_use;
00310
00311 static u_int32_t prealloc_nodes_in_use;
00312 static int ten_percent;
00313
00314 static Frag3Stats f3stats;
00315 static u_int8_t stats_registered;
00316
00317
00318 static Packet *defrag_pkt;
00319
00320
00321 static char *policy_names[] = { "no policy!",
00322 "FIRST",
00323 "LINUX",
00324 "BSD",
00325 "BSD_RIGHT",
00326 "LAST",
00327 "WINDOWS",
00328 "SOLARIS"};
00329
00330
00331
00332
00333 extern char *file_name;
00334 extern int file_line;
00335 extern u_int snaplen;
00336 extern SFPERF sfPerf;
00337
00338
00339
00340 static void Frag3ParseGlobalArgs(u_char *);
00341 static void Frag3ParseArgs(u_char *, Frag3Context *);
00342 static FragTracker *Frag3GetTracker(Packet *, FRAGKEY *);
00343 static int Frag3NewTracker(Packet *p, FRAGKEY *fkey, Frag3Context *);
00344 static int Frag3Insert(Packet *, FragTracker *, FRAGKEY *, Frag3Context *);
00345 static void Frag3Rebuild(FragTracker *, Packet *);
00346 static int INLINE Frag3IsComplete(FragTracker *);
00347 static int Frag3HandleIPOptions(FragTracker *, Packet *);
00348 static void Frag3InitPkt();
00349
00350
00351 static int Frag3Prune(FragTracker *);
00352 static struct timeval *pkttime;
00353 static void Frag3DeleteFrag(Frag3Frag *);
00354 static void Frag3RemoveTracker(void *, void *);
00355 static void Frag3DeleteTracker(FragTracker *);
00356 static int Frag3AutoFree(void *, void *);
00357 static int Frag3UserFree(void *, void *);
00358
00359
00360 static INLINE void Frag3FraglistAddNode(FragTracker *, Frag3Frag *, Frag3Frag *);
00361 static INLINE void Frag3FraglistDeleteNode(FragTracker *, Frag3Frag *);
00362
00363
00364 static INLINE Frag3Frag *Frag3PreallocPop();
00365 static INLINE void Frag3PreallocPush(Frag3Frag *);
00366
00367
00368 void Frag3Defrag(Packet *, void *);
00369 void Frag3CleanExit(int, void *);
00370 void Frag3Restart(int, void *);
00371 void Frag3Init(u_char *);
00372 void Frag3GlobalInit(u_char *);
00373
00374 #ifdef DEBUG_FRAG3
00375
00376
00377
00378
00379
00380
00381
00382 static void PrintFragTracker(FragTracker *ft)
00383 {
00384 LogMessage("FragTracker %p\n", ft);
00385 if(ft)
00386 {
00387 LogMessage(" sip: 0x%08X\n", ft->sip);
00388 LogMessage(" dip: 0x%08X\n", ft->dip);
00389 LogMessage(" id: %d\n", ft->id);
00390 LogMessage(" proto: 0x%X\n", ft->protocol);
00391 LogMessage(" ttl: %d\n", ft->ttl);
00392 LogMessage(" alerted: %d\n", ft->alerted);
00393 LogMessage(" frag_flags: 0x%X\n", ft->frag_flags);
00394 LogMessage(" frag_bytes: %d\n", ft->frag_bytes);
00395 LogMessage(" calc_size: %d\n", ft->calculated_size);
00396 LogMessage(" frag_pkts: %d\n", ft->frag_pkts);
00397 LogMessage(" frag_time: %lu %lu\n", ft->frag_time.tv_sec,
00398 ft->frag_time.tv_usec);
00399 LogMessage(" fraglist: %p\n", ft->fraglist);
00400 LogMessage(" fl_tail: %p\n", ft->fraglist_tail);
00401 LogMessage("fraglst cnt: %d\n", ft->fraglist_count);
00402 }
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412 static void PrintFragKey(FRAGKEY *fkey)
00413 {
00414 LogMessage("FragKey %p\n", fkey);
00415
00416 if(fkey)
00417 {
00418 LogMessage(" sip: 0x%08X\n", fkey->sip);
00419 LogMessage(" dip: 0x%08X\n", fkey->dip);
00420 LogMessage(" id: %d\n", fkey->id);
00421 LogMessage(" proto: 0x%X\n", fkey->proto);
00422 }
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432 static void PrintFrag3Frag(Frag3Frag *f)
00433 {
00434 LogMessage("Frag3Frag: %p\n", f);
00435
00436 if(f)
00437 {
00438 LogMessage(" data: %p\n", f->data);
00439 LogMessage(" size: %d\n", f->size);
00440 LogMessage(" offset: %d\n", f->offset);
00441 LogMessage(" fptr: %p\n", f->fptr);
00442 LogMessage(" flen: %d\n", f->flen);
00443 LogMessage(" prev: %p\n", f->prev);
00444 LogMessage(" next: %p\n", f->next);
00445 }
00446 }
00447
00448 #endif
00449
00450
00451
00452
00453
00454
00455
00456
00457 static void Frag3PrintGlobalConfig()
00458 {
00459 LogMessage("Frag3 global config:\n");
00460 LogMessage(" Max frags: %d\n", global_config.max_frags);
00461 if(!global_config.use_prealloc)
00462 LogMessage(" Fragment memory cap: %lu bytes\n",
00463 (unsigned long)global_config.memcap);
00464 else
00465 LogMessage(" Preallocated frag nodes: %lu\n",
00466 global_config.static_frags);
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 static void Frag3PrintEngineConfig(Frag3Context *context)
00478 {
00479 LogMessage("Frag3 engine config:\n");
00480 LogMessage(" Target-based policy: %s\n",
00481 policy_names[context->frag_policy]);
00482 LogMessage(" Fragment timeout: %d seconds\n",
00483 context->frag_timeout);
00484 LogMessage(" Fragment min_ttl: %d\n", context->min_ttl);
00485 LogMessage(" Fragment ttl_limit: %d\n", context->ttl_limit);
00486 LogMessage(" Fragment Problems: %X\n", context->frag3_alerts);
00487
00488 IpAddrSetPrint(" Bound Addresses: ", context->bound_addrs);
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498 static INLINE void EventAnomIpOpts(Frag3Context *context)
00499 {
00500 if(!(context->frag3_alerts & FRAG3_DETECT_ANOMALIES))
00501 return;
00502
00503 SnortEventqAdd(GENERATOR_SPP_FRAG3,
00504 FRAG3_IPOPTIONS,
00505 1,
00506 0,
00507 3,
00508 FRAG3_IPOPTIONS_STR,
00509 NULL);
00510
00511 f3stats.alerts++;
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521 static INLINE void EventAttackTeardrop(Frag3Context *context)
00522 {
00523 if(!(context->frag3_alerts & FRAG3_DETECT_ANOMALIES))
00524 return;
00525
00526 SnortEventqAdd(GENERATOR_SPP_FRAG3,
00527 FRAG3_TEARDROP,
00528 1,
00529 0,
00530 3,
00531 FRAG3_TEARDROP_STR,
00532 NULL);
00533
00534 f3stats.alerts++;
00535 }
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545 static INLINE void EventAnomShortFrag(Frag3Context *context)
00546 {
00547 if(!(context->frag3_alerts & FRAG3_DETECT_ANOMALIES))
00548 return;
00549
00550 SnortEventqAdd(GENERATOR_SPP_FRAG3,
00551 FRAG3_SHORT_FRAG,
00552 1,
00553 0,
00554 3,
00555 FRAG3_SHORT_FRAG_STR,
00556 NULL);
00557
00558 f3stats.alerts++;
00559 f3stats.anomalies++;
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 static INLINE void EventAnomOversize(Frag3Context *context)
00571 {
00572 if(!(context->frag3_alerts & FRAG3_DETECT_ANOMALIES))
00573 return;
00574
00575 SnortEventqAdd(GENERATOR_SPP_FRAG3,
00576 FRAG3_ANOMALY_OVERSIZE,
00577 1,
00578 0,
00579 3,
00580 FRAG3_ANOM_OVERSIZE_STR,
00581 NULL);
00582
00583 f3stats.alerts++;
00584 f3stats.anomalies++;
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 static INLINE void EventAnomZeroFrag(Frag3Context *context)
00596 {
00597 if(!(context->frag3_alerts & FRAG3_DETECT_ANOMALIES))
00598 return;
00599
00600 SnortEventqAdd(GENERATOR_SPP_FRAG3,
00601 FRAG3_ANOMALY_ZERO,
00602 1,
00603 0,
00604 3,
00605 FRAG3_ANOM_ZERO_STR,
00606 NULL);
00607
00608 f3stats.alerts++;
00609 f3stats.anomalies++;
00610 }
00611
00612
00613
00614
00615
00616
00617
00618
00619 static INLINE void EventAnomBadsizeLg(Frag3Context *context)
00620 {
00621 if(!(context->frag3_alerts & FRAG3_DETECT_ANOMALIES))
00622 return;
00623
00624 SnortEventqAdd(GENERATOR_SPP_FRAG3,
00625 FRAG3_ANOMALY_BADSIZE_LG,
00626 1,
00627 0,
00628 3,
00629 FRAG3_ANOM_BADSIZE_LG_STR,
00630 NULL);
00631
00632 f3stats.alerts++;
00633 f3stats.anomalies++;
00634 }
00635
00636
00637
00638
00639
00640
00641
00642
00643 static INLINE void EventAnomBadsizeSm(Frag3Context *context)
00644 {
00645 if(!(context->frag3_alerts & FRAG3_DETECT_ANOMALIES))
00646 return;
00647
00648 SnortEventqAdd(GENERATOR_SPP_FRAG3,
00649 FRAG3_ANOMALY_BADSIZE_SM,
00650 1,
00651 0,
00652 3,
00653 FRAG3_ANOM_BADSIZE_SM_STR,
00654 NULL);
00655
00656 f3stats.alerts++;
00657 f3stats.anomalies++;
00658 }
00659
00660
00661
00662
00663
00664
00665
00666
00667 static INLINE void EventAnomOverlap(Frag3Context *context)
00668 {
00669 if(!(context->frag3_alerts & FRAG3_DETECT_ANOMALIES))
00670 return;
00671
00672 SnortEventqAdd(GENERATOR_SPP_FRAG3,
00673 FRAG3_ANOMALY_OVLP,
00674 1,
00675 0,
00676 3,
00677 FRAG3_ANOM_OVLP_STR,
00678 NULL);
00679
00680 f3stats.alerts++;
00681 f3stats.anomalies++;
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691 void SetupFrag3()
00692 {
00693 RegisterPreprocessor("frag3_global", Frag3GlobalInit);
00694 RegisterPreprocessor("frag3_engine", Frag3Init);
00695 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Preprocessor: frag3 is setup...\n"););
00696 }
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 void Frag3GlobalInit(u_char *args)
00707 {
00708 Frag3Frag *tmp;
00709 unsigned int i;
00710
00711
00712
00713
00714 global_config.max_frags = DEFAULT_MAX_FRAGS;
00715 global_config.memcap = FRAG_MEMCAP;
00716 global_config.static_frags = 0;
00717 global_config.use_prealloc = 0;
00718
00719 Frag3ParseGlobalArgs(args);
00720
00721
00722
00723
00724
00725 if(f_cache == NULL)
00726 {
00727
00728 int hashTableSize = (int) (global_config.max_frags * 1.4);
00729 int maxFragMem = global_config.max_frags * (
00730 sizeof(FragTracker) +
00731 sizeof(SFXHASH_NODE) +
00732 sizeof (FRAGKEY) +
00733 sizeof(SFXHASH_NODE *));
00734 int tableMem = (hashTableSize + 1) * sizeof(SFXHASH_NODE *);
00735 int maxMem = maxFragMem + tableMem;
00736 f_cache = sfxhash_new(
00737 hashTableSize,
00738 sizeof(FRAGKEY),
00739 sizeof(FragTracker),
00740 maxMem,
00741 1,
00742 Frag3AutoFree,
00743 Frag3UserFree,
00744 1);
00745 }
00746
00747
00748
00749
00750 if(!f_cache)
00751 {
00752 LogMessage("WARNING: Unable to generate new sfxhash for frag3, "
00753 "defragmentation disabled!\n");
00754 return;
00755 }
00756
00757
00758
00759
00760 if(global_config.static_frags)
00761 {
00762 for(i=0; i< global_config.static_frags; i++)
00763 {
00764 tmp = (Frag3Frag *) SnortAlloc(sizeof(Frag3Frag));
00765 tmp->fptr = (u_int8_t *) SnortAlloc(sizeof(u_int8_t) * snaplen);
00766 Frag3PreallocPush(tmp);
00767 }
00768
00769 prealloc_nodes_in_use = 0;
00770 }
00771
00772
00773
00774
00775 defrag_pkt = (Packet *)SnortAlloc(sizeof(Packet));
00776
00777
00778
00779
00780 Frag3InitPkt();
00781
00782
00783
00784
00785 global_init_complete = 1;
00786
00787
00788
00789
00790 Frag3PrintGlobalConfig();
00791
00792 return;
00793 }
00794
00795
00796
00797
00798
00799
00800
00801
00802 void Frag3Init(u_char *args)
00803 {
00804 PreprocessFuncNode *pfn;
00805 Frag3Context *context;
00806
00807 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Initializing frag3\n"););
00808
00809 context = (Frag3Context *) SnortAlloc(sizeof(Frag3Context));
00810
00811 if(!global_init_complete)
00812 {
00813 LogMessage("[!] WARNING: Unable to configure frag3 engine!\n"
00814 "Frag3 global config has not been established, "
00815 "please issue a \"preprocessor frag3_global\" directive\n");
00816 return;
00817 }
00818
00819
00820
00821
00822
00823
00824
00825 context->frag_policy = FRAG_POLICY_BSD;
00826 context->frag_timeout = FRAG_PRUNE_QUANTA;
00827 context->ttl_limit = FRAG3_TTL_LIMIT;
00828 context->min_ttl = FRAG3_MIN_TTL;
00829 context->frag3_alerts = 0;
00830
00831
00832
00833
00834 context->bound_addrs = NULL;
00835
00836
00837
00838
00839 Frag3ParseArgs(args, context);
00840
00841
00842
00843
00844 pfn = AddFuncToPreprocList(Frag3Defrag);
00845
00846 pfn->context = (void *) context;
00847
00848 if(!stats_registered)
00849 {
00850 AddFuncToCleanExitList(Frag3CleanExit, NULL);
00851 AddFuncToRestartList(Frag3Restart, NULL);
00852 stats_registered = 1;
00853 }
00854
00855
00856
00857
00858 Frag3PrintEngineConfig(context);
00859
00860 return;
00861 }
00862
00863
00864
00865
00866
00867
00868
00869
00870 static void Frag3ParseGlobalArgs(u_char *args)
00871 {
00872 char **toks;
00873 int num_toks;
00874 int i;
00875 char *index;
00876 char **stoks = NULL;
00877 int s_toks;
00878
00879 if(args != NULL && strlen(args) != 0)
00880 {
00881 toks = mSplit(args, ",", 12, &num_toks, 0);
00882
00883 i=0;
00884
00885 while(i < num_toks)
00886 {
00887 index = toks[i];
00888
00889 while(isspace((int)*index)) index++;
00890
00891 stoks = mSplit(index, " ", 4, &s_toks, 0);
00892
00893 if(!strcasecmp(stoks[0], "max_frags"))
00894 {
00895 if(isdigit((int)stoks[1][0]))
00896 {
00897 global_config.max_frags = atoi(stoks[1]);
00898 }
00899 else
00900 {
00901 LogMessage("WARNING %s(%d) => Bad max_frags in config "
00902 "file, defaulting to %d frags\n",
00903 file_name, file_line,
00904 DEFAULT_MAX_FRAGS);
00905
00906 global_config.max_frags = DEFAULT_MAX_FRAGS;
00907 }
00908
00909 }
00910 else if(!strcasecmp(stoks[0], "memcap"))
00911 {
00912 #ifdef FRAG3_USE_MEMCAP
00913 if(stoks[1] && isdigit((int)stoks[1][0]))
00914 {
00915 global_config.memcap = atoi(stoks[1]);
00916
00917 if(global_config.memcap < 16384)
00918 {
00919 LogMessage("WARNING %s(%d) => Ludicrous (<16k) memcap "
00920 "size, setting to default (%d bytes)\n",
00921 file_name, file_line, FRAG_MEMCAP);
00922
00923 global_config.memcap = FRAG_MEMCAP;
00924 }
00925 }
00926 else
00927 {
00928 LogMessage("WARNING %s(%d) => Bad memcap in config file, "
00929 "defaulting to %u bytes\n", file_name, file_line,
00930 FRAG_MEMCAP);
00931
00932 global_config.memcap = FRAG_MEMCAP;
00933 }
00934
00935
00936 ten_percent = ((global_config.memcap >> 5) +
00937 (global_config.memcap >> 6));
00938 #else
00939
00940 int memcap;
00941 if(stoks[1] && isdigit((int)stoks[1][0]))
00942 {
00943 memcap = atoi(stoks[1]);
00944
00945 if(memcap < 16384)
00946 {
00947 LogMessage("WARNING %s(%d) => Ludicrous (<16k) memcap "
00948 "size, setting to default (%d bytes)\n",
00949 file_name, file_line, FRAG_MEMCAP);
00950
00951 memcap = FRAG_MEMCAP;
00952 }
00953 }
00954 else
00955 {
00956 LogMessage("WARNING %s(%d) => Bad memcap in config file, "
00957 "defaulting to %u bytes\n", file_name, file_line,
00958 FRAG_MEMCAP);
00959
00960 memcap = FRAG_MEMCAP;
00961 }
00962
00963 global_config.static_frags = (u_int32_t)memcap /
00964 (sizeof(Frag3Frag) + sizeof(u_int8_t) * snaplen) + 1;
00965 global_config.use_prealloc = 1;
00966 ten_percent = global_config.static_frags >> 5;
00967 #endif
00968 }
00969 else if(!strcasecmp(stoks[0], "prealloc_frags"))
00970 {
00971 if(isdigit((int)stoks[1][0]))
00972 {
00973 global_config.static_frags = atoi(stoks[1]);
00974 global_config.use_prealloc = 1;
00975
00976
00977
00978 ten_percent = global_config.static_frags >> 5;
00979 }
00980 else
00981 {
00982 LogMessage("WARNING %s(%d) => Bad prealloc_frags in config "
00983 "file, defaulting to dynamic frag management\n",
00984 file_name, file_line);
00985
00986 global_config.static_frags = 0;
00987 }
00988 }
00989
00990 mSplitFree(&stoks, s_toks);
00991
00992 i++;
00993 }
00994 mSplitFree(&toks, num_toks);
00995 }
00996
00997 return;
00998 }
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009 static void Frag3ParseArgs(u_char *args, Frag3Context *context)
01010 {
01011 char **toks;
01012 int num_toks;
01013 int i;
01014 char *index;
01015
01016 if(args == NULL || strlen(args) == 0)
01017 {
01018 return;
01019 }
01020 else
01021 {
01022 int increment;
01023 toks = mSplit(args, " ", 13, &num_toks, 0);
01024
01025 i=0;
01026
01027 while(i < num_toks)
01028 {
01029 increment = 1;
01030 index = toks[i];
01031
01032 if(!strcasecmp(index, "timeout"))
01033 {
01034 if(i+1 < num_toks && isdigit((int)toks[i+1][0]))
01035 {
01036 context->frag_timeout = atoi(toks[i+1]);
01037 increment = 2;
01038 }
01039 else
01040 {
01041 LogMessage("WARNING %s(%d) => Bad timeout in config file, "
01042 "defaulting to %d seconds\n", file_name,
01043 file_line, FRAG_PRUNE_QUANTA);
01044
01045 context->frag_timeout = FRAG_PRUNE_QUANTA;
01046 }
01047 }
01048 else if(!strcasecmp(index, "ttl_limit"))
01049 {
01050 if(i+1 >= num_toks || toks[i+1][0] == '\0')
01051 {
01052 FatalError("%s(%d) => ttl_limit requires an integer "
01053 "argument\n", file_name,file_line);
01054 }
01055
01056 if(isdigit((int)toks[i+1][0]))
01057 {
01058 context->ttl_limit = atoi(toks[i+1]);
01059 increment = 2;
01060 }
01061 else
01062 {
01063 LogMessage("WARNING %s(%d) => Bad TTL Limit"
01064 "size, setting to default (%d\n", file_name,
01065 file_line, FRAG3_TTL_LIMIT);
01066
01067 context->ttl_limit = FRAG3_TTL_LIMIT;
01068 }
01069 }
01070 else if(!strcasecmp(index, "min_ttl"))
01071 {
01072 if(i+1 >= num_toks || toks[i+1][0] == '\0')
01073 {
01074 FatalError("%s(%d) => min_ttl requires an integer "
01075 "argument\n", file_name,file_line);
01076 }
01077
01078 if(isdigit((int)toks[i+1][0]))
01079 {
01080 context->min_ttl = atoi(toks[i+1]);
01081 increment = 2;
01082 }
01083 else
01084 {
01085 LogMessage("WARNING %s(%d) => Bad Min TTL "
01086 "size, setting to default (%d\n", file_name,
01087 file_line, FRAG3_MIN_TTL);
01088
01089 context->min_ttl = FRAG3_MIN_TTL;
01090 }
01091 }
01092 else if(!strcasecmp(index, "detect_anomalies"))
01093 {
01094 context->frag3_alerts |= FRAG3_DETECT_ANOMALIES;
01095 }
01096 else if(!strcasecmp(index, "policy"))
01097 {
01098 if (i+1 >= num_toks)
01099 FatalError("%s(%d) => policy requires a policy "
01100 "identifier argument\n", file_name, file_line);
01101
01102 if(!strcasecmp(toks[i+1], "bsd"))
01103 {
01104 context->frag_policy = FRAG_POLICY_BSD;
01105 }
01106 else if(!strcasecmp(toks[i+1], "bsd-right"))
01107 {
01108 context->frag_policy = FRAG_POLICY_BSD_RIGHT;
01109 }
01110 else if(!strcasecmp(toks[i+1], "linux"))
01111 {
01112 context->frag_policy = FRAG_POLICY_LINUX;
01113 }
01114 else if(!strcasecmp(toks[i+1], "first"))
01115 {
01116 context->frag_policy = FRAG_POLICY_FIRST;
01117 }
01118 else if(!strcasecmp(toks[i+1], "windows"))
01119 {
01120 context->frag_policy = FRAG_POLICY_WINDOWS;
01121 }
01122 else if(!strcasecmp(toks[i+1], "solaris"))
01123 {
01124 context->frag_policy = FRAG_POLICY_SOLARIS;
01125 }
01126 else if(!strcasecmp(toks[i+1], "last"))
01127 {
01128 context->frag_policy = FRAG_POLICY_LAST;
01129 }
01130 else
01131 {
01132 LogMessage("WARNING %s(%d) => Bad policy name \"%s\""
01133 "reverting to FRAG_POLICY_BSD\n",
01134 file_name, file_line, toks[i+1]);
01135 }
01136 increment = 2;
01137 }
01138 else if(!strcasecmp(index, "bind_to"))
01139 {
01140 if (i+1 < num_toks)
01141 {
01142 context->bound_addrs = IpAddrSetParse(toks[i+1]);
01143 increment = 2;
01144 }
01145 else
01146 {
01147 FatalError("%s(%d) => bind_to requires an IP list or "
01148 "CIDR block argument\n", file_name, file_line);
01149 }
01150 }
01151
01152 i += increment;
01153 }
01154
01155 mSplitFree(&toks, num_toks);
01156
01157 if(context->bound_addrs == NULL)
01158 {
01159
01160
01161
01162 context->bound_addrs = (IpAddrSet *) SnortAlloc(sizeof(IpAddrSet));
01163 }
01164 }
01165
01166 return;
01167 }
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178 void Frag3Defrag(Packet *p, void *context)
01179 {
01180 FRAGKEY fkey;
01181 FragTracker *ft;
01182 Frag3Context *f3context = (Frag3Context *) context;
01183 int insert_return = 0;
01184
01185
01186
01187
01188 if( (p == NULL) || !(p->preprocessors & PP_FRAG3) ||
01189 p->iph == NULL || !p->frag_flag ||
01190 (p->csum_flags & CSE_IP) ||
01191 (p->packet_flags & PKT_REBUILT_FRAG))
01192 {
01193 return;
01194 }
01195
01196
01197
01198
01199
01200
01201
01202 if ((p->frag_offset != 0) || (p->iph->ip_proto != IPPROTO_UDP))
01203 {
01204
01205
01206
01207
01208
01209 p->preprocessors = 0;
01210 p->preprocessors |= PP_PORTSCAN2;
01211 do_detect = 0;
01212 otn_tmp = NULL;
01213 }
01214
01215 #if 0
01216
01217
01218
01219 if(p->ip_options_len)
01220 {
01221 EventAnomIpOpts(f3context);
01222 f3stats.discards++;
01223 return;
01224 }
01225 #endif
01226
01227
01228
01229
01230 if(p->iph->ip_ttl < f3context->min_ttl)
01231 {
01232 LogMessage(
01233 "[FRAG3] Fragment discarded due to low TTL "
01234 "[0x%X->0x%X], TTL: %d " "Offset: %d Length: %d\n",
01235 ntohl(p->iph->ip_src.s_addr),
01236 ntohl(p->iph->ip_dst.s_addr),
01237 p->iph->ip_ttl, p->frag_offset,
01238 p->dsize);
01239
01240 f3stats.discards++;
01241 return;
01242 }
01243
01244
01245
01246
01247 if(!IpAddrSetContains(f3context->bound_addrs, p->iph->ip_dst))
01248 {
01249 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01250 "[FRAG3] Fragment ignored, not in IpAddrSet\n"););
01251 return;
01252 }
01253
01254 f3stats.total++;
01255 UpdateIPFragStats(&(sfPerf.sfBase), p->pkth->caplen);
01256
01257 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01258 "\n++++++++++++++++++++++++++++++++++++++++++++++\n"););
01259 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01260 "[**] [FRAG3] Inspecting fragment...\n"););
01261 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01262 "[FRAG3] Got frag packet (mem use: %ld frag "
01263 "trackers: %d p->pkt_flags: 0x%X "
01264 "prealloc nodes in use: %lu/%lu)\n",
01265 mem_in_use,
01266 sfxhash_count(f_cache),
01267 p->packet_flags, prealloc_nodes_in_use,
01268 global_config.static_frags););
01269
01270
01271 memset(&fkey, 0, sizeof(FRAGKEY));
01272
01273 #if 0
01274
01275
01276
01277 if(mem_in_use > global_config.memcap)
01278 {
01279 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01280 "memcap exceeded (%ld bytes in use), "
01281 "calling Frag3Prune()\n", mem_in_use););
01282 Frag3Prune();
01283 }
01284 #endif
01285 pkttime = (struct timeval *) &p->pkth->ts;
01286
01287
01288
01289
01290 if((ft = Frag3GetTracker(p, &fkey)) == NULL)
01291 {
01292 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Adding New FragTracker...\n"););
01293
01294
01295
01296
01297 Frag3NewTracker(p, &fkey, f3context);
01298
01299 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01300 "[FRAG3] mem use: %ld frag "
01301 "trackers: %d prealloc "
01302 "nodes in use: %lu/%lu\n",
01303 mem_in_use,
01304 sfxhash_count(f_cache),
01305 prealloc_nodes_in_use,
01306 global_config.static_frags););
01307
01308
01309
01310 return;
01311 }
01312
01313 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Found frag tracker\n"););
01314
01315
01316
01317
01318 if((insert_return = Frag3Insert(p, ft, &fkey, f3context)) != FRAG_INSERT_OK)
01319 {
01320
01321
01322
01323
01324 switch(insert_return)
01325 {
01326 case FRAG_INSERT_FAILED:
01327 if(!pv.quiet_flag)
01328 {
01329 LogMessage("WARNING: Insert into Fraglist failed, "
01330 "(offset: %u)\n", p->frag_offset);
01331 }
01332 return;
01333 case FRAG_INSERT_TTL:
01334 LogMessage(
01335 "[FRAG3] Fragment discarded due to large TTL Delta "
01336 "[0x%X->0x%X], TTL: %d orig TTL: %d "
01337 "Offset: %d Length: %d\n",
01338 ntohl(p->iph->ip_src.s_addr),
01339 ntohl(p->iph->ip_dst.s_addr),
01340 p->iph->ip_ttl, ft->ttl, p->frag_offset,
01341 p->dsize);
01342 f3stats.discards++;
01343 return;
01344 case FRAG_INSERT_ATTACK:
01345 case FRAG_INSERT_ANOMALY:
01346 f3stats.discards++;
01347 return;
01348 case FRAG_INSERT_TIMEOUT:
01349 #ifdef DEBUG
01350 if(!pv.quiet_flag)
01351 {
01352 LogMessage("WARNING: Insert into Fraglist failed due to timeout, "
01353 "(offset: %u)\n", p->frag_offset);
01354 }
01355 #endif
01356 return;
01357 default:
01358 break;
01359 }
01360 }
01361
01362 p->fragtracker = (void *)ft;
01363
01364
01365
01366
01367 if(Frag3IsComplete(ft))
01368 {
01369 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01370 "[*] Fragment is complete, rebuilding!\n"););
01371
01372
01373
01374
01375
01376 if(!(ft->frag_flags & FRAG_BAD))
01377 {
01378 Frag3Rebuild(ft, p);
01379
01380 if ((p->frag_offset != 0) || (p->iph->ip_proto != IPPROTO_UDP))
01381 {
01382
01383
01384
01385
01386 do_detect = 0;
01387 otn_tmp = NULL;
01388
01389
01390
01391 p->fragtracker = NULL;
01392 }
01393 }
01394
01395 Frag3RemoveTracker(&fkey, ft);
01396
01397 }
01398
01399 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01400 "[FRAG3] Dumped fragtracker (mem use: %ld frag "
01401 "trackers: %d prealloc "
01402 "nodes in use: %lu/%lu)\n",
01403 mem_in_use,
01404 sfxhash_count(f_cache),
01405 prealloc_nodes_in_use,
01406 global_config.static_frags););
01407
01408 return;
01409 }
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424 static INLINE int CheckTimeout(struct timeval *current_time,
01425 struct timeval *start_time,
01426 Frag3Context *f3context)
01427 {
01428 struct timeval tv_diff;
01429
01430
01431 TIMERSUB(current_time, start_time, &tv_diff);
01432
01433 if(tv_diff.tv_sec >= f3context->frag_timeout)
01434 {
01435 return FRAG_TIMEOUT;
01436 }
01437
01438 return FRAG_TIME_OK;
01439 }
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455 static int Frag3Expire(
01456 Packet *p,
01457 FragTracker *ft,
01458 FRAGKEY *fkey,
01459 Frag3Context *f3context)
01460 {
01461 #if 0
01462 struct timeval *fttime;
01463 struct timeval *pkttime;
01464 FragTracker *tmpft;
01465 #endif
01466
01467
01468
01469
01470 if(CheckTimeout(
01471 pkttime,
01472 &(ft)->frag_time,
01473 f3context) == FRAG_TIMEOUT)
01474 {
01475
01476
01477
01478 #ifdef DEBUG_FRAG3
01479 if (DEBUG_FRAG & GetDebugLevel())
01480 LogMessage("(spp_frag3) Current Fragment dropped due to timeout! "
01481 "[0x%08X->0x%08X ID: %d]\n", ft->sip, ft->dip, ft->id);
01482 #endif
01483
01484 Frag3RemoveTracker(fkey, ft);
01485
01486 f3stats.timeouts++;
01487 sfPerf.sfBase.iFragTimeouts++;
01488
01489 return FRAG_TRACKER_TIMEOUT;
01490 }
01491
01492 #if 0
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502 if((tmpft = (FragTracker*)sfxhash_lru(f_cache)))
01503 {
01504 fttime = &tmpft->frag_time;
01505 pkttime = (struct timeval *) &p->pkth->ts;
01506
01507 while(tmpft && CheckTimeout(pkttime,fttime,f3context)==FRAG_TIMEOUT)
01508 {
01509 LogMessage("(spp_frag3) Fragment dropped due to timeout! "
01510 "[0x%08X->0x%08X ID: %d]\n", tmpft->sip, tmpft->dip,
01511 tmpft->id);
01512
01513 sfxhash_free_node(f_cache, sfxhash_lru_node(f_cache));
01514
01515 f3stats.timeouts++;
01516 sfPerf.sfBase.iFragTimeouts++;
01517
01518 if((tmpft = (FragTracker*)(sfxhash_lru(f_cache))))
01519 {
01520 fttime = &tmpft->frag_time;
01521 }
01522 }
01523 }
01524 #endif
01525
01526
01527
01528
01529
01530
01531
01532
01533 return FRAG_OK;
01534 }
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545 static int INLINE Frag3CheckFirstLast(Packet *p, FragTracker *ft)
01546 {
01547 u_int16_t fragLength;
01548 int retVal = FRAG_FIRSTLAST_OK;
01549 u_int16_t endOfThisFrag;
01550
01551
01552
01553 if(p->mf && p->frag_offset == 0)
01554 {
01555 ft->frag_flags |= FRAG_GOT_FIRST;
01556
01557 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Got first frag\n"););
01558 }
01559 else if((!p->mf) && (p->frag_offset > 0))
01560 {
01561
01562
01563
01564 fragLength = p->actual_ip_len - IP_HLEN(p->iph) * 4;
01565 endOfThisFrag = (p->frag_offset << 3) + fragLength;
01566
01567 if (ft->frag_flags & FRAG_GOT_LAST)
01568 {
01569 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Got last frag again!\n"););
01570 switch (ft->context->frag_policy)
01571 {
01572 case FRAG_POLICY_BSD:
01573 case FRAG_POLICY_LINUX:
01574 case FRAG_POLICY_BSD_RIGHT:
01575 case FRAG_POLICY_LAST:
01576 case FRAG_POLICY_WINDOWS:
01577 case FRAG_POLICY_FIRST:
01578 if (ft->calculated_size > endOfThisFrag)
01579 {
01580
01581
01582
01583
01584
01585
01586
01587
01588 retVal = FRAG_LAST_DUPLICATE;
01589 }
01590 break;
01591 case FRAG_POLICY_SOLARIS:
01592 if (ft->calculated_size > endOfThisFrag)
01593 {
01594
01595
01596
01597
01598
01599
01600
01601
01602 retVal = FRAG_LAST_DUPLICATE;
01603 }
01604 else
01605 {
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617 retVal = FRAG_LAST_OFFSET_ADJUST;
01618 }
01619 break;
01620 }
01621 }
01622
01623 ft->frag_flags |= FRAG_GOT_LAST;
01624
01625
01626
01627
01628
01629 if ((ft->calculated_size < endOfThisFrag) &&
01630 (retVal != FRAG_LAST_OFFSET_ADJUST))
01631 {
01632 ft->calculated_size = endOfThisFrag;
01633
01634 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Got last frag, Bytes: %d, "
01635 "Calculated size: %d\n",
01636 ft->frag_bytes,
01637 ft->calculated_size););
01638 }
01639 }
01640
01641 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Frag Status: %s:%s\n",
01642 ft->frag_flags&FRAG_GOT_FIRST?"FIRST":"No FIRST",
01643 ft->frag_flags&FRAG_GOT_LAST?"LAST":"No LAST"););
01644 return retVal;
01645 }
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656 static FragTracker *Frag3GetTracker(Packet *p, FRAGKEY *fkey)
01657 {
01658 FragTracker *returned;
01659
01660
01661
01662
01663
01664 fkey->sip = p->iph->ip_src.s_addr;
01665 fkey->dip = p->iph->ip_dst.s_addr;
01666 fkey->id = p->iph->ip_id;
01667 fkey->proto = p->iph->ip_proto;
01668
01669
01670
01671
01672 if(sfxhash_count(f_cache) == 0)
01673 return NULL;
01674
01675 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01676 "[*] Looking up FragTracker using key:\n"););
01677
01678 #ifdef DEBUG_FRAG3
01679 PrintFragKey(fkey);
01680 #endif
01681
01682 returned = (FragTracker *) sfxhash_find(f_cache, fkey);
01683
01684 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01685 "Frag3GetTracker returning %p for\n", returned););
01686
01687 return returned;
01688 }
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701 static int Frag3HandleIPOptions(FragTracker *ft,
01702 Packet *p)
01703 {
01704 unsigned int i = 0;
01705 if(p->frag_offset == 0)
01706 {
01707
01708
01709
01710
01711 if (p->ip_options_len)
01712 {
01713 ft->ip_options_len = p->ip_options_len;
01714 ft->ip_option_count = p->ip_option_count;
01715 ft->ip_options_data = SnortAlloc(p->ip_options_len);
01716 memcpy(ft->ip_options_data, p->ip_options_data, p->ip_options_len);
01717 }
01718 }
01719 else
01720 {
01721
01722
01723
01724
01725
01726
01727
01728 if (ft->copied_ip_option_count)
01729 {
01730 if (ft->copied_ip_option_count != p->ip_option_count)
01731 {
01732 EventAnomIpOpts(ft->context);
01733 }
01734 }
01735 else
01736 {
01737 ft->copied_ip_option_count = p->ip_option_count;
01738 for (i = 0;i< p->ip_option_count && i < IP_OPTMAX; i++)
01739 {
01740
01741 if (!(p->ip_options[i].code & 0x80))
01742 EventAnomIpOpts(ft->context);
01743 }
01744 }
01745 }
01746 return 1;
01747 }
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760 static int Frag3NewTracker(Packet *p, FRAGKEY *fkey, Frag3Context *f3context)
01761 {
01762 FragTracker *tmp;
01763 Frag3Frag *f = NULL;
01764
01765 char *fragStart;
01766 u_int16_t fragLength;
01767 u_int16_t frag_end;
01768 SFXHASH_NODE *hnode;
01769
01770 fragStart = (u_int8_t *)p->iph + IP_HLEN(p->iph) * 4;
01771
01772
01773
01774 fragLength = p->actual_ip_len - IP_HLEN(p->iph) * 4;
01775 #ifdef DEBUG
01776 if (p->actual_ip_len != ntohs(p->iph->ip_len))
01777 {
01778 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01779 "IP Actual Length (%d) != specified length (%d), "
01780 "truncated packet (%d)?\n",
01781 p->actual_ip_len, ntohs(p->iph->ip_len), snaplen););
01782 }
01783 #endif
01784
01785
01786 if (fragLength > snaplen)
01787 {
01788 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01789 "Overly large fragment %d 0x%x 0x%x %d\n",
01790 fragLength, p->iph->ip_len, p->iph->ip_off,
01791 p->frag_offset << 3););
01792
01793
01794 return 0;
01795 }
01796
01797 hnode = sfxhash_get_node(f_cache, fkey);
01798 if (!hnode)
01799 {
01800 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01801 "Frag3NewTracker: sfxhash_get_node() failed\n"););
01802
01803 return 0;
01804 }
01805 else
01806 {
01807 if (hnode->data)
01808 {
01809 tmp = hnode->data;
01810 memset(tmp, 0, sizeof(FragTracker));
01811 }
01812 else
01813 {
01814 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01815 "Frag3NewTracker: sfxhash_get_node() failed\n"););
01816
01817 return 0;
01818 }
01819 }
01820
01821
01822
01823
01824 tmp->sip = fkey->sip;
01825 tmp->dip = fkey->dip;
01826 tmp->id = fkey->id;
01827 tmp->protocol = fkey->proto;
01828 tmp->ttl = p->iph->ip_ttl;
01829 tmp->calculated_size = 0;
01830 tmp->alerted = 0;
01831 tmp->frag_flags = 0;
01832 tmp->frag_bytes = 0;
01833 tmp->frag_pkts = 0;
01834 tmp->frag_time.tv_sec = p->pkth->ts.tv_sec;
01835 tmp->frag_time.tv_usec = p->pkth->ts.tv_usec;
01836 tmp->alert_count = 0;
01837 tmp->ip_options_len = 0;
01838 tmp->ip_option_count = 0;
01839 tmp->ip_options_data = NULL;
01840 tmp->copied_ip_options_len = 0;
01841 tmp->copied_ip_option_count = 0;
01842 tmp->context = f3context;
01843 tmp->ordinal = 0;
01844
01845
01846
01847
01848 if(!global_config.use_prealloc)
01849 {
01850 if(mem_in_use > global_config.memcap)
01851 {
01852 if (Frag3Prune(tmp) == 0)
01853 {
01854 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01855 "Frag3NewTracker: Pruning failed\n"););
01856
01857 return 0;
01858 }
01859 }
01860
01861 f = (Frag3Frag *) SnortAlloc(sizeof(Frag3Frag));
01862 mem_in_use += sizeof(Frag3Frag);
01863
01864 f->fptr = (u_int8_t *) SnortAlloc(fragLength);
01865 mem_in_use += fragLength;
01866
01867
01868 }
01869 else
01870 {
01871 while((f = Frag3PreallocPop()) == NULL)
01872 {
01873 if (Frag3Prune(tmp) == 0)
01874 {
01875 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01876 "Frag3NewTracker: Pruning failed\n"););
01877
01878 return 0;
01879 }
01880 }
01881 }
01882
01883 f3stats.fragnodes_created++;
01884 sfPerf.sfBase.iFragCreates++;
01885 sfPerf.sfBase.iCurrentFrags++;
01886 if (sfPerf.sfBase.iCurrentFrags > sfPerf.sfBase.iMaxFrags)
01887 sfPerf.sfBase.iMaxFrags = sfPerf.sfBase.iCurrentFrags;
01888
01889
01890 tmp->fraglist = NULL;
01891
01892
01893
01894
01895 memcpy(f->fptr, fragStart, fragLength);
01896
01897 f->size = f->flen = fragLength;
01898 f->offset = p->frag_offset << 3;
01899 frag_end = f->offset + fragLength;
01900 f->ord = tmp->ordinal++;
01901 f->data = f->fptr;
01902 if (!p->mf)
01903 {
01904 f->last = 1;
01905 }
01906 else
01907 {
01908
01909
01910
01911 if(frag_end & 7)
01912 {
01913
01914
01915
01916 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01917 "[..] Short frag (Bonk, etc) attack!\n"););
01918
01919 EventAnomShortFrag(f3context);
01920
01921
01922 }
01923
01924
01925 frag_end &= ~7;
01926
01927
01928 f->size = frag_end - f->offset;
01929 }
01930
01931
01932 tmp->fraglist = f;
01933 tmp->fraglist_tail = f;
01934 tmp->fraglist_count = 1;
01935 tmp->frag_pkts = 1;
01936
01937
01938
01939
01940 Frag3CheckFirstLast(p, tmp);
01941
01942 tmp->frag_bytes += fragLength;
01943
01944 Frag3HandleIPOptions(tmp, p);
01945
01946 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01947 "[#] accumulated bytes on FragTracker: %d\n",
01948 tmp->frag_bytes););
01949
01950 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01951 "Initial fragment for tracker, ptr %p, offset %d, "
01952 "size %d\n", f, f->offset, f->size););
01953
01954 #ifdef DEBUG_FRAG3
01955 PrintFragKey(fkey);
01956 #endif
01957
01958 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01959 "Calling sfxhash(add), overhead at %lu\n",
01960 f_cache->overhead_bytes););
01961
01962 #if 0
01963
01964
01965
01966 if((ret = sfxhash_add(f_cache, fkey, &tmp)) != SFXHASH_OK)
01967 {
01968 if(ret == SFXHASH_INTABLE)
01969 {
01970 LogMessage("Key collision in sfxhash!\n");
01971 }
01972
01973 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
01974 "Frag3NewTracker: sfxhash_add() failed\n"););
01975
01976 return 0;
01977 }
01978 #endif
01979
01980 f3stats.fragtrackers_created++;
01981 pc.frag_trackers++;
01982
01983 p->fragtracker = (void *)tmp;
01984
01985 return 1;
01986 }
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006 static int AddFragNode(FragTracker *ft,
02007 Packet *p,
02008 Frag3Context *f3context,
02009 u_int8_t *fragStart,
02010 int16_t fragLength,
02011 char lastfrag,
02012 int16_t len,
02013 u_int16_t slide,
02014 u_int16_t trunc,
02015 u_int16_t frag_offset,
02016 Frag3Frag *left,
02017 Frag3Frag **retFrag)
02018 {
02019 Frag3Frag *newfrag = NULL;
02020 int16_t newSize = len - slide - trunc;
02021
02022 if (newSize <= 0)
02023 {
02024
02025
02026
02027 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02028 "zero size frag after left & right trimming "
02029 "(len: %d slide: %d trunc: %d)\n",
02030 len, slide, trunc););
02031
02032 f3stats.discards++;
02033
02034 #ifdef DEBUG
02035 newfrag = ft->fraglist;
02036 while (newfrag)
02037 {
02038 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02039 "Size: %d, offset: %d, len %d, "
02040 "Prev: 0x%x, Next: 0x%x, This: 0x%x, Ord: %d, %s\n",
02041 newfrag->size, newfrag->offset,
02042 newfrag->flen, newfrag->prev,
02043 newfrag->next, newfrag, newfrag->ord,
02044 newfrag->last ? "Last":""););
02045 newfrag = newfrag->next;
02046 }
02047 #endif
02048
02049 return FRAG_INSERT_ANOMALY;
02050 }
02051
02052
02053
02054
02055 if(!global_config.use_prealloc)
02056 {
02057 if(mem_in_use > global_config.memcap)
02058 {
02059 if (Frag3Prune(ft) == 0)
02060 {
02061 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02062 "Frag3Insert: Pruning failed\n"););
02063
02064 return FRAG_INSERT_FAILED;
02065 }
02066 }
02067
02068
02069
02070
02071 newfrag = (Frag3Frag *) SnortAlloc(sizeof(Frag3Frag));
02072 mem_in_use += sizeof(Frag3Frag);
02073
02074
02075
02076
02077 newfrag->fptr = (u_int8_t*)SnortAlloc(fragLength);
02078 mem_in_use += fragLength;
02079 }
02080 else
02081 {
02082
02083
02084
02085 while((newfrag = Frag3PreallocPop()) == NULL)
02086 {
02087 if (Frag3Prune(ft) == 0)
02088 {
02089 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02090 "Frag3Insert: Pruning failed\n"););
02091
02092 return FRAG_INSERT_FAILED;
02093 }
02094 }
02095
02096 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02097 "got newfrag (%p) from prealloc\n", newfrag););
02098 }
02099
02100 f3stats.fragnodes_created++;
02101
02102 newfrag->flen = fragLength;
02103 memcpy(newfrag->fptr, fragStart, fragLength);
02104 newfrag->ord = ft->ordinal++;
02105
02106
02107
02108
02109 newfrag->data = newfrag->fptr + slide;
02110 newfrag->size = newSize;
02111 newfrag->offset = frag_offset;
02112 newfrag->last = lastfrag;
02113
02114 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02115 "[+] Adding new frag, offset %d, size %d\n"
02116 " nf->data = nf->fptr(%p) + slide (%d)\n"
02117 " nf->size = len(%d) - slide(%d) - trunc(%d)\n",
02118 newfrag->offset, newfrag->size, newfrag->fptr,
02119 slide, fragLength, slide, trunc););
02120
02121
02122
02123
02124 Frag3FraglistAddNode(ft, left, newfrag);
02125
02126 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02127 "[*] Inserted new frag %d@%d ptr %p data %p prv %p nxt %p\n",
02128 newfrag->size, newfrag->offset, newfrag, newfrag->data,
02129 newfrag->prev, newfrag->next););
02130
02131
02132
02133
02134 ft->frag_bytes += newfrag->size;
02135
02136 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02137 "[#] accumulated bytes on FragTracker %d, count"
02138 " %d\n", ft->frag_bytes, ft->fraglist_count););
02139
02140 *retFrag = newfrag;
02141 return FRAG_INSERT_OK;
02142 }
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155 static int DupFragNode(FragTracker *ft,
02156 Frag3Frag *left,
02157 Frag3Frag **retFrag)
02158 {
02159 Frag3Frag *newfrag = NULL;
02160
02161
02162
02163
02164 if(!global_config.use_prealloc)
02165 {
02166 if(mem_in_use > global_config.memcap)
02167 {
02168 if (Frag3Prune(ft) == 0)
02169 {
02170 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02171 "Frag3Insert: Pruning failed\n"););
02172
02173 return FRAG_INSERT_FAILED;
02174 }
02175 }
02176
02177
02178
02179
02180 newfrag = (Frag3Frag *) SnortAlloc(sizeof(Frag3Frag));
02181 mem_in_use += sizeof(Frag3Frag);
02182
02183
02184
02185
02186 newfrag->fptr = (u_int8_t*)SnortAlloc(left->flen);
02187 mem_in_use += left->flen;
02188 }
02189 else
02190 {
02191
02192
02193
02194 while((newfrag = Frag3PreallocPop()) == NULL)
02195 {
02196 if (Frag3Prune(ft) == 0)
02197 {
02198 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02199 "Frag3Insert: Pruning failed\n"););
02200
02201 return FRAG_INSERT_FAILED;
02202 }
02203 }
02204
02205 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02206 "got newfrag (%p) from prealloc\n", newfrag););
02207 }
02208
02209 f3stats.fragnodes_created++;
02210
02211 newfrag->ord = ft->ordinal++;
02212
02213
02214
02215 newfrag->flen = left->flen;
02216 memcpy(newfrag->fptr, left->fptr, newfrag->flen);
02217 newfrag->data = newfrag->fptr + (left->data - left->fptr);
02218 newfrag->size = left->size;
02219 newfrag->offset = left->offset;
02220 newfrag->last = left->last;
02221
02222
02223
02224
02225 Frag3FraglistAddNode(ft, left, newfrag);
02226
02227 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02228 "[*] Inserted new frag %d@%d ptr %p data %p prv %p nxt %p\n",
02229 newfrag->size, newfrag->offset, newfrag, newfrag->data,
02230 newfrag->prev, newfrag->next););
02231
02232
02233
02234
02235 ft->frag_bytes += newfrag->size;
02236
02237 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02238 "[#] accumulated bytes on FragTracker %d, count"
02239 " %d\n", ft->frag_bytes, ft->fraglist_count););
02240
02241 *retFrag = newfrag;
02242 return FRAG_INSERT_OK;
02243 }
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262 static int Frag3Insert(Packet *p, FragTracker *ft, FRAGKEY *fkey,
02263 Frag3Context *f3context)
02264 {
02265 u_int16_t frag_offset;
02266 u_int16_t frag_end;
02267 int16_t trunc = 0;
02268 int32_t overlap = 0;
02269 int16_t len = 0;
02270 int16_t slide = 0;
02271 int done = 0;
02272 int addthis = 1;
02273 int i = 0;
02274 int delta = 0;
02275 int firstLastOk;
02276 int ret = FRAG_INSERT_OK;
02277 char lastfrag = 0;
02278 Frag3Frag *right = NULL;
02279 Frag3Frag *newfrag = NULL;
02280 Frag3Frag *left = NULL;
02281 Frag3Frag *idx = NULL;
02282 Frag3Frag *dump_me = NULL;
02283
02284 u_int8_t *fragStart;
02285 int16_t fragLength;
02286
02287 sfPerf.sfBase.iFragInserts++;
02288
02289
02290
02291
02292
02293 if(Frag3Expire(p, ft, fkey, f3context) == FRAG_TRACKER_TIMEOUT)
02294 {
02295 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02296 "[..] Deleting fragtracker due to timeout!\n"););
02297
02298 return FRAG_INSERT_TIMEOUT;
02299 }
02300
02301 delta = abs(ft->ttl - p->iph->ip_ttl);
02302 if (delta > f3context->ttl_limit)
02303 {
02304 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02305 "[..] Large TTL delta!\n"););
02306
02307 return FRAG_INSERT_TTL;
02308 }
02309
02310
02311
02312
02313
02314 firstLastOk = Frag3CheckFirstLast(p, ft);
02315
02316 fragStart = (u_int8_t *)p->iph + IP_HLEN(p->iph) * 4;
02317
02318
02319
02320 len = fragLength = p->actual_ip_len - IP_HLEN(p->iph) * 4;
02321 #ifdef DEBUG
02322 if (p->actual_ip_len != ntohs(p->iph->ip_len))
02323 {
02324 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02325 "IP Actual Length (%d) != specified length (%d), "
02326 "truncated packet (%d)?\n",
02327 p->actual_ip_len, ntohs(p->iph->ip_len), snaplen););
02328 }
02329 #endif
02330
02331
02332
02333
02334 frag_offset = p->frag_offset << 3;
02335
02336 if (firstLastOk == FRAG_LAST_OFFSET_ADJUST)
02337 frag_offset = (u_int16_t)ft->calculated_size;
02338 frag_end = frag_offset + fragLength;
02339
02340
02341
02342
02343 if(!p->mf)
02344 {
02345 if ((frag_end > ft->calculated_size) &&
02346 (firstLastOk == FRAG_LAST_OFFSET_ADJUST))
02347 {
02348 ft->calculated_size = frag_end;
02349 }
02350
02351
02352
02353 lastfrag = 1;
02354 }
02355 else
02356 {
02357 u_int16_t oldfrag_end;
02358
02359
02360
02361 if(frag_end & 7)
02362 {
02363
02364
02365
02366 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02367 "[..] Short frag (Bonk, etc) attack!\n"););
02368
02369 EventAnomShortFrag(f3context);
02370
02371
02372 }
02373
02374
02375 oldfrag_end = frag_end;
02376 frag_end &= ~7;
02377
02378
02379 len -= (oldfrag_end - frag_end);
02380
02381
02382
02383
02384
02385 if(frag_end > ft->calculated_size)
02386 {
02387 if(ft->frag_flags & FRAG_GOT_LAST)
02388 {
02389
02390 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02391 "[..] Oversize frag pkt!\n"););
02392
02393 EventAnomOversize(f3context);
02394
02395 return FRAG_INSERT_ANOMALY;
02396 }
02397 ft->calculated_size = frag_end;
02398 }
02399 }
02400
02401 if(frag_end == frag_offset)
02402 {
02403
02404
02405
02406 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02407 "[..] Zero size frag!\n"););
02408
02409 if(f3context->frag3_alerts & FRAG3_DETECT_ANOMALIES)
02410 {
02411 EventAnomZeroFrag(f3context);
02412 }
02413
02414 return FRAG_INSERT_ANOMALY;
02415 }
02416
02417 if(ft->calculated_size > IP_MAXPACKET)
02418 {
02419
02420
02421
02422 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02423 "[..] Oversize frag!\n"););
02424
02425 EventAnomBadsizeLg(f3context);
02426
02427 ft->frag_flags |= FRAG_BAD;
02428
02429 return FRAG_INSERT_ANOMALY;
02430 }
02431
02432
02433
02434
02435
02436 Frag3HandleIPOptions(ft, p);
02437
02438 ft->frag_pkts++;
02439
02440 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02441 "Walking frag list (%d nodes), new frag %d@%d\n",
02442 ft->fraglist_count, fragLength, frag_offset););
02443
02444
02445
02446
02447
02448 for(idx = ft->fraglist; idx; idx = idx->next)
02449 {
02450 i++;
02451 right = idx;
02452
02453 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02454 "%d right o %d s %d ptr %p prv %p nxt %p\n",
02455 i, right->offset, right->size, right,
02456 right->prev, right->next););
02457
02458 if(right->offset >= frag_offset)
02459 {
02460 break;
02461 }
02462
02463 left = right;
02464 }
02465
02466
02467
02468
02469 if(idx == NULL) right = NULL;
02470
02471
02472
02473
02474 if(left)
02475 {
02476 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02477 "Dealing with previous (left) frag %d@%d\n",
02478 left->size, left->offset););
02479
02480
02481
02482
02483
02484
02485
02486
02487 overlap = left->offset + left->size - frag_offset;
02488
02489 if(overlap > 0)
02490 {
02491 if(frag_end < ft->calculated_size ||
02492 ((ft->frag_flags & FRAG_GOT_LAST) &&
02493 frag_end != ft->calculated_size))
02494 {
02495 if (!p->mf)
02496 {
02497
02498
02499
02500 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02501 "[..] Teardrop attack!\n"););
02502
02503 EventAttackTeardrop(f3context);
02504
02505 ft->frag_flags |= FRAG_BAD;
02506
02507 return FRAG_INSERT_ATTACK;
02508 }
02509 }
02510
02511 f3stats.overlaps++;
02512
02513
02514
02515
02516
02517
02518
02519 switch(f3context->frag_policy)
02520 {
02521
02522
02523
02524 case FRAG_POLICY_LINUX:
02525 case FRAG_POLICY_FIRST:
02526 case FRAG_POLICY_WINDOWS:
02527 case FRAG_POLICY_SOLARIS:
02528 case FRAG_POLICY_BSD:
02529 frag_offset += (int16_t)overlap;
02530 slide = (int16_t)overlap;
02531
02532 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02533 "left overlap, new frag moves: %d bytes, "
02534 "slide: %d\n", overlap, slide););
02535
02536 if(frag_end <= frag_offset)
02537 {
02538
02539
02540
02541 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02542 "zero size frag"););
02543
02544 EventAnomZeroFrag(f3context);
02545
02546 return FRAG_INSERT_ANOMALY;
02547 }
02548
02549 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "left overlap, "
02550 "truncating new pkt (slide: %d)\n", slide););
02551
02552 break;
02553
02554
02555
02556
02557
02558 case FRAG_POLICY_BSD_RIGHT:
02559 if ((f3context->frag_policy == FRAG_POLICY_BSD_RIGHT) &&
02560 (left->offset + left->size >= frag_offset + len))
02561 {
02562
02563
02564
02565
02566 frag_offset += (int16_t)overlap;
02567 slide = (int16_t)overlap;
02568 goto left_overlap_last;
02569 }
02570
02571 case FRAG_POLICY_LAST:
02572 if ((left->offset < frag_offset) && (left->offset + left->size > frag_offset + len))
02573 {
02574
02575
02576
02577
02578
02579
02580
02581
02582 ret = DupFragNode(ft, left, &right);
02583 if (ret != FRAG_INSERT_OK)
02584 {
02585
02586
02587 return ret;
02588 }
02589 left->size -= (int16_t)overlap;
02590 ft->frag_bytes -= (int16_t)overlap;
02591
02592 right->offset = frag_offset + len;
02593 right->size -= (frag_offset + len - left->offset);
02594 right->data += (frag_offset + len - left->offset);
02595 ft->frag_bytes -= (frag_offset + len - left->offset);
02596 }
02597 else
02598 {
02599 left->size -= (int16_t)overlap;
02600 ft->frag_bytes -= (int16_t)overlap;
02601 }
02602
02603 left_overlap_last:
02604 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "[!!] left overlap, "
02605 "truncating old pkt (offset: %d overlap: %d)\n",
02606 left->offset, overlap););
02607
02608 if (left->size <= 0)
02609 {
02610 dump_me = left;
02611
02612 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "retrans, "
02613 "dumping old frag (offset: %d overlap: %d)\n",
02614 dump_me->offset, overlap););
02615
02616 left = left->prev;
02617
02618 Frag3FraglistDeleteNode(ft, dump_me);
02619 }
02620
02621 break;
02622 }
02623
02624
02625
02626
02627 if(frag_end < frag_offset)
02628 {
02629 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02630 "frag_end < frag_offset!"););
02631
02632 if(f3context->frag3_alerts & FRAG3_DETECT_ANOMALIES)
02633 {
02634 EventAnomBadsizeSm(f3context);
02635 }
02636
02637 return FRAG_INSERT_ANOMALY;
02638 }
02639 }
02640 else
02641 {
02642 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "No left overlap!\n"););
02643 }
02644 }
02645
02646 if ((u_int16_t)fragLength > snaplen)
02647 {
02648 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02649 "Overly large fragment %d 0x%x 0x%x %d\n",
02650 fragLength, p->iph->ip_len, p->iph->ip_off,
02651 p->frag_offset << 3););
02652 return FRAG_INSERT_FAILED;
02653 }
02654
02655
02656
02657
02658
02659
02660
02661 while(right && (right->offset < frag_end) && !done)
02662 {
02663 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02664 "Next (right)fragment %d@%d\n",
02665 right->size, right->offset););
02666
02667 #ifdef DEBUG_FRAG3
02668 PrintFrag3Frag(right);
02669 #endif
02670 trunc = 0;
02671 overlap = frag_end - right->offset;
02672
02673 if (overlap)
02674 {
02675 if(frag_end < ft->calculated_size ||
02676 ((ft->frag_flags & FRAG_GOT_LAST) &&
02677 frag_end != ft->calculated_size))
02678 {
02679 if (!p->mf)
02680 {
02681
02682
02683
02684 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02685 "[..] Teardrop attack!\n"););
02686
02687 EventAttackTeardrop(f3context);
02688
02689 ft->frag_flags |= FRAG_BAD;
02690
02691 return FRAG_INSERT_ATTACK;
02692 }
02693 }
02694 }
02695
02696
02697
02698
02699 if(overlap < right->size)
02700 {
02701 f3stats.overlaps++;
02702
02703 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02704 "Right-side overlap %d bytes\n", overlap););
02705
02706
02707
02708
02709 switch(f3context->frag_policy)
02710 {
02711
02712
02713
02714 case FRAG_POLICY_LAST:
02715 case FRAG_POLICY_LINUX:
02716 case FRAG_POLICY_BSD:
02717 if ((f3context->frag_policy == FRAG_POLICY_BSD) &&
02718 (right->offset == frag_offset))
02719 {
02720 slide = (int16_t)(right->offset + right->size - frag_offset);
02721 frag_offset += (int16_t)slide;
02722 }
02723 else
02724 {
02725 right->offset += (int16_t)overlap;
02726 right->data += (int16_t)overlap;
02727 right->size -= (int16_t)overlap;
02728 ft->frag_bytes -= (int16_t)overlap;
02729 }
02730 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "[!!] right overlap, "
02731 "truncating old frag (offset: %d, "
02732 "overlap: %d)\n", right->offset, overlap);
02733 DebugMessage(DEBUG_FRAG,
02734 "Exiting right overlap loop...\n"););
02735 if (right->size <= 0)
02736 {
02737 dump_me = right;
02738
02739 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "retrans, "
02740 "dumping old frag (offset: %d overlap: %d)\n",
02741 dump_me->offset, overlap););
02742
02743 right = right->next;
02744
02745 Frag3FraglistDeleteNode(ft, dump_me);
02746 }
02747 break;
02748
02749
02750
02751
02752 case FRAG_POLICY_FIRST:
02753 case FRAG_POLICY_WINDOWS:
02754 case FRAG_POLICY_SOLARIS:
02755 case FRAG_POLICY_BSD_RIGHT:
02756 trunc = (int16_t)overlap;
02757 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "[!!] right overlap, "
02758 "truncating new frag (offset: %d "
02759 "overlap: %d)\n",
02760 right->offset, overlap);
02761 DebugMessage(DEBUG_FRAG,
02762 "Exiting right overlap loop...\n"););
02763 break;
02764 }
02765
02766
02767
02768
02769 done = 1;
02770 }
02771 else
02772 {
02773
02774
02775
02776 if(f3context->frag3_alerts & FRAG3_DETECT_ANOMALIES)
02777 {
02778
02779
02780
02781 EventAnomOverlap(f3context);
02782 f3stats.overlaps++;
02783 }
02784
02785
02786
02787
02788 switch(f3context->frag_policy)
02789 {
02790
02791
02792
02793
02794 case FRAG_POLICY_WINDOWS:
02795 case FRAG_POLICY_SOLARIS:
02796 case FRAG_POLICY_BSD:
02797
02798
02799
02800
02801
02802 if ((frag_end > right->offset + right->size) &&
02803 (frag_offset < right->offset))
02804 {
02805 dump_me = right;
02806 ft->frag_bytes -= right->size;
02807
02808 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "retrans, "
02809 "dumping old frag (offset: %d overlap: %d)\n",
02810 dump_me->offset, overlap););
02811
02812 right = right->next;
02813
02814 Frag3FraglistDeleteNode(ft, dump_me);
02815 break;
02816 }
02817 else
02818 {
02819 if ((f3context->frag_policy == FRAG_POLICY_SOLARIS) ||
02820 (f3context->frag_policy == FRAG_POLICY_BSD))
02821 {
02822
02823 if ((frag_end == right->offset + right->size) &&
02824 (frag_offset < right->offset))
02825 {
02826
02827
02828
02829
02830 goto right_overlap_last;
02831 }
02832 }
02833 }
02834
02835
02836
02837
02838
02839
02840
02841
02842 case FRAG_POLICY_FIRST:
02843
02844 if (right->offset == frag_offset)
02845 {
02846 slide = (int16_t)(right->offset + right->size - frag_offset);
02847 frag_offset += (int16_t)slide;
02848 left = right;
02849 right = right->next;
02850 }
02851 else
02852 {
02853 trunc = (int16_t)overlap;
02854 }
02855
02856 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "right overlap, "
02857 "rejecting new overlap data (overlap: %d, "
02858 "trunc: %d)\n", overlap, trunc););
02859
02860 if (frag_end - trunc <= frag_offset)
02861 {
02862
02863
02864
02865 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02866 "zero size frag (len: %d overlap: %d)\n",
02867 fragLength, overlap););
02868
02869 f3stats.discards++;
02870
02871 return FRAG_INSERT_ANOMALY;
02872 }
02873
02874 {
02875 u_int16_t curr_end;
02876
02877
02878
02879
02880
02881 ret = AddFragNode(ft, p, f3context, fragStart, fragLength, 0, len,
02882 slide, trunc, frag_offset, left, &newfrag);
02883 if (ret != FRAG_INSERT_OK)
02884 {
02885
02886
02887 return ret;
02888 }
02889
02890 curr_end = newfrag->offset + newfrag->size;
02891
02892
02893 while (right &&
02894 (curr_end <= right->offset) &&
02895 (right->offset < frag_end))
02896 {
02897 curr_end = right->offset + right->size;
02898 left = right;
02899 right = right->next;
02900 }
02901
02902 if (right && (right->offset < frag_end))
02903 {
02904
02905 frag_offset = right->offset + right->size;
02906
02907 slide = 0;
02908
02909
02910
02911 left = right;
02912
02913
02914
02915
02916
02917
02918 trunc = 0;
02919 if (right->next)
02920 continue;
02921 }
02922
02923 if (curr_end < frag_end)
02924 {
02925
02926
02927
02928
02929 slide = left->offset + left->size - frag_offset;
02930 frag_offset = curr_end;
02931 trunc = 0;
02932 }
02933 else
02934 {
02935 addthis = 0;
02936 }
02937 }
02938 break;
02939
02940
02941
02942
02943 right_overlap_last:
02944 case FRAG_POLICY_BSD_RIGHT:
02945 case FRAG_POLICY_LAST:
02946 case FRAG_POLICY_LINUX:
02947 dump_me = right;
02948 ft->frag_bytes -= right->size;
02949
02950 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "retrans, "
02951 "dumping old frag (offset: %d overlap: %d)\n",
02952 dump_me->offset, overlap););
02953
02954 right = right->next;
02955
02956 Frag3FraglistDeleteNode(ft, dump_me);
02957
02958 break;
02959 }
02960 }
02961 }
02962
02963 if (addthis)
02964 {
02965 ret = AddFragNode(ft, p, f3context, fragStart, fragLength, lastfrag, len,
02966 slide, trunc, frag_offset, left, &newfrag);
02967 }
02968 else
02969 {
02970 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02971 "Fully truncated right overlap\n"););
02972 }
02973
02974 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02975 "Frag3Insert(): returning normally\n"););
02976
02977 return ret;
02978 }
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989 static int INLINE Frag3IsComplete(FragTracker *ft)
02990 {
02991 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
02992 "[$] Checking completion criteria\n"););
02993
02994
02995
02996
02997 if((ft->frag_flags & FRAG_GOT_FIRST) &&
02998 (ft->frag_flags & FRAG_GOT_LAST))
02999 {
03000 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03001 " Got First and Last frags\n"););
03002
03003
03004
03005
03006
03007 if(ft->frag_bytes == ft->calculated_size)
03008 {
03009 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03010 " [!] frag_bytes = calculated_size!\n"););
03011
03012 sfPerf.sfBase.iFragCompletes++;
03013
03014 return 1;
03015 }
03016
03017 if (ft->frag_bytes > ft->calculated_size)
03018 {
03019 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03020 " [!] frag_bytes > calculated_size!\n"););
03021
03022 sfPerf.sfBase.iFragCompletes++;
03023
03024 return 1;
03025 }
03026
03027 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03028 " Calc size (%d) != frag bytes (%d)\n",
03029 ft->calculated_size, ft->frag_bytes););
03030
03031
03032
03033
03034 return 0;
03035 }
03036
03037 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03038 " Missing First or Last frags (frag_flags: 0x%X)\n",
03039 ft->frag_flags););
03040
03041 return 0;
03042 }
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053 static void Frag3Rebuild(FragTracker *ft, Packet *p)
03054 {
03055 u_int8_t *rebuild_ptr;
03056 u_int8_t *rebuild_end;
03057 Frag3Frag *frag;
03058 u_int8_t new_ip_hlen = 0;
03059 u_int8_t save_ip_hlen = 0;
03060
03061 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Rebuilding pkt [0x%X:%d 0x%X:%d]\n",
03062 p->iph->ip_src.s_addr, p->sp,
03063 p->iph->ip_dst.s_addr, p->dp);
03064 DebugMessage(DEBUG_FRAG, "Calculated size: %d\n",
03065 ft->calculated_size);
03066 DebugMessage(DEBUG_FRAG, "Frag Bytes: %d\n", ft->frag_bytes);
03067 );
03068
03069
03070
03071
03072
03073 defrag_pkt->pkth->ts.tv_sec = p->pkth->ts.tv_sec;
03074 defrag_pkt->pkth->ts.tv_usec = p->pkth->ts.tv_usec;
03075
03076
03077
03078
03079 rebuild_end = defrag_pkt->pkt + DATASIZE;
03080
03081
03082
03083
03084
03085
03086 if (ft->ip_options_data && ft->ip_options_len)
03087 {
03088 save_ip_hlen = new_ip_hlen = IP_HLEN(p->iph);
03089
03090
03091
03092
03093
03094
03095 new_ip_hlen += (u_int8_t)((ft->ip_options_len - p->ip_options_len) >> 2);
03096 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03097 "Adjusting IP Header from %d to %d bytes\n",
03098 save_ip_hlen, new_ip_hlen););
03099 SET_IP_HLEN(p->iph, new_ip_hlen);
03100 }
03101
03102
03103 SafeMemcpy(defrag_pkt->pkt, p->pkt, ETHERNET_HEADER_LEN + sizeof(IPHdr),
03104 defrag_pkt->pkt, rebuild_end);
03105
03106
03107
03108
03109
03110 rebuild_ptr = defrag_pkt->pkt + ETHERNET_HEADER_LEN + sizeof(IPHdr);
03111
03112
03113
03114
03115 if (ft->ip_options_data && ft->ip_options_len)
03116 {
03117 SafeMemcpy(rebuild_ptr, ft->ip_options_data, ft->ip_options_len,
03118 rebuild_ptr, rebuild_end);
03119
03120
03121
03122
03123
03124 rebuild_ptr += ft->ip_options_len;
03125
03126
03127
03128
03129 SET_IP_HLEN(p->iph, save_ip_hlen);
03130 }
03131 else if (ft->copied_ip_options_len)
03132 {
03133
03134
03135
03136 }
03137
03138
03139
03140
03141 defrag_pkt->iph = (IPHdr *) (defrag_pkt->pkt + ETHERNET_HEADER_LEN);
03142
03143
03144
03145
03146 defrag_pkt->iph->ip_off = 0x0000;
03147 defrag_pkt->frag_flag = 0;
03148
03149 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03150 "[^^] Walking fraglist:\n"););
03151
03152
03153
03154
03155 for(frag = ft->fraglist; frag; frag = frag->next)
03156 {
03157 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03158 " frag: %p\n"
03159 " frag->data: %p\n"
03160 " frag->offset: %d\n"
03161 " frag->size: %d\n"
03162 " frag->prev: %p\n"
03163 " frag->next: %p\n",
03164 frag, frag->data, frag->offset,
03165 frag->size, frag->prev, frag->next););
03166
03167
03168
03169
03170
03171 if ((frag->offset + frag->size) > (u_int16_t)ft->calculated_size)
03172 continue;
03173
03174
03175
03176
03177 if (frag->size)
03178 SafeMemcpy(rebuild_ptr+frag->offset, frag->data, frag->size,
03179 rebuild_ptr, rebuild_end);
03180
03181 }
03182
03183
03184
03185
03186 if((ETHERNET_HEADER_LEN + ft->calculated_size + sizeof(IPHdr)
03187 + ft->ip_options_len) >
03188 (IP_MAXPACKET-1))
03189 {
03190
03191
03192
03193
03194 #ifdef DONT_TRUNCATE
03195 defrag_pkt->pkth->caplen = IP_MAXPACKET - 1;
03196 #else
03197 defrag_pkt->pkth->caplen = ETHERNET_HEADER_LEN +
03198 ft->calculated_size + sizeof(IPHdr) + ft->ip_options_len ;
03199 #endif
03200 }
03201 else
03202 {
03203 defrag_pkt->pkth->caplen = ETHERNET_HEADER_LEN +
03204 ft->calculated_size + sizeof(IPHdr) + ft->ip_options_len;
03205 }
03206
03207 defrag_pkt->pkth->len = defrag_pkt->pkth->caplen;
03208
03209
03210
03211
03212 defrag_pkt->iph->ip_len = htons((short)(defrag_pkt->pkth->len-ETHERNET_HEADER_LEN));
03213 defrag_pkt->actual_ip_len = ntohs(defrag_pkt->iph->ip_len);
03214
03215
03216
03217
03218 defrag_pkt->packet_flags = PKT_REBUILT_FRAG;
03219 defrag_pkt->frag_flag = 0;
03220 defrag_pkt->iph->ip_csum = 0;
03221
03222
03223
03224
03225 defrag_pkt->iph->ip_csum =
03226 in_chksum_ip((u_int16_t *)defrag_pkt->iph, sizeof(IPHdr) + ft->ip_options_len);
03227
03228 pc.rebuilt_frags++;
03229 sfPerf.sfBase.iFragFlushes++;
03230
03231
03232
03233
03234 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03235 "Processing rebuilt packet:\n"););
03236
03237 f3stats.reassembles++;
03238
03239 UpdateIPReassStats(&(sfPerf.sfBase), defrag_pkt->pkth->caplen);
03240
03241 #ifdef DEBUG_FRAG3
03242
03243
03244
03245
03246 if (DEBUG_FRAG & GetDebugLevel())
03247 {
03248 ClearDumpBuf();
03249 printf("++++++++++++++++++Frag3 DEFRAG'd PACKET++++++++++++++\n");
03250 PrintIPPkt(stdout, defrag_pkt->iph->ip_proto, defrag_pkt);
03251 printf("++++++++++++++++++Frag3 DEFRAG'd PACKET++++++++++++++\n");
03252 ClearDumpBuf();
03253 }
03254 #endif
03255 ProcessPacket(NULL, defrag_pkt->pkth, defrag_pkt->pkt, ft);
03256
03257 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03258 "Done with rebuilt packet, marking rebuilt...\n"););
03259
03260 ft->frag_flags = ft->frag_flags | FRAG_REBUILT;
03261 }
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271 static void Frag3InitPkt()
03272 {
03273
03274
03275
03276 defrag_pkt->pkth = SnortAlloc(sizeof(SnortPktHeader));
03277 defrag_pkt->pkt = (u_int8_t *) SnortAlloc(DATASIZE + SPARC_TWIDDLE);
03278
03279
03280
03281
03282 defrag_pkt->pkt += SPARC_TWIDDLE;
03283
03284 if(defrag_pkt->pkth == NULL || defrag_pkt->pkt == NULL)
03285 {
03286 FatalError("Out of memory on Frag3InitPkt()\n");
03287 }
03288 }
03289
03290
03291
03292
03293
03294
03295
03296
03297 static void Frag3DeleteFrag(Frag3Frag *frag)
03298 {
03299
03300
03301
03302 if(!global_config.use_prealloc)
03303 {
03304 free(frag->fptr);
03305 mem_in_use -= frag->flen;
03306
03307 free(frag);
03308 mem_in_use -= sizeof(Frag3Frag);
03309 }
03310 else
03311 {
03312 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "o %d s %d ptr %p prv %p nxt %p\n",
03313 frag->offset, frag->size, frag, frag->prev, frag->next););
03314 Frag3PreallocPush(frag);
03315 }
03316
03317 f3stats.fragnodes_released++;
03318 }
03319
03320
03321
03322
03323
03324
03325
03326
03327
03328 static void Frag3DeleteTracker(FragTracker *ft)
03329 {
03330 Frag3Frag *idx = ft->fraglist;
03331 Frag3Frag *dump_me = NULL;
03332
03333 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03334 "Frag3DeleteTracker %d nodes to dump\n", ft->fraglist_count););
03335
03336
03337
03338
03339 while(idx)
03340 {
03341 dump_me = idx;
03342 idx = idx->next;
03343 Frag3DeleteFrag(dump_me);
03344 }
03345 if (ft->ip_options_data)
03346 {
03347 free(ft->ip_options_data);
03348 ft->ip_options_data = NULL;
03349 }
03350
03351 return;
03352 }
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362 static void Frag3RemoveTracker(void *key, void *data)
03363 {
03364
03365
03366
03367 if(sfxhash_remove(f_cache, key) != SFXHASH_OK)
03368 {
03369 ErrorMessage("sfxhash_remove() failed in frag3!\n");
03370 }
03371
03372 return;
03373 }
03374
03375
03376
03377
03378
03379
03380
03381
03382
03383
03384 static int Frag3AutoFree(void *key, void *data)
03385 {
03386 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03387 "Calling Frag3DeleteTracker()\n"););
03388
03389 Frag3DeleteTracker((FragTracker *) data);
03390
03391 sfPerf.sfBase.iFragDeletes++;
03392 sfPerf.sfBase.iFragAutoFrees++;
03393 sfPerf.sfBase.iCurrentFrags--;
03394 f3stats.fragtrackers_autoreleased++;
03395
03396 return 0;
03397 }
03398
03399
03400
03401
03402
03403
03404
03405
03406
03407
03408 static int Frag3UserFree(void *key, void *data)
03409 {
03410 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03411 "Calling Frag3DeleteTracker()\n"););
03412
03413 Frag3DeleteTracker((FragTracker *) data);
03414
03415 sfPerf.sfBase.iFragDeletes++;
03416 sfPerf.sfBase.iCurrentFrags--;
03417 f3stats.fragtrackers_released++;
03418
03419 return 0;
03420 }
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435 static int Frag3Prune(FragTracker *not_me)
03436 {
03437 SFXHASH_NODE *hnode;
03438 int found_this = 0;
03439 int pruned = 0;
03440 #ifdef DEBUG
03441
03442
03443
03444 FragTracker *ft;
03445 struct timeval *fttime;
03446 #endif
03447
03448 sfPerf.sfBase.iFragFaults++;
03449 f3stats.prunes++;
03450
03451 if(!global_config.use_prealloc)
03452 {
03453
03454 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03455 "(spp_frag3) Frag3Prune: Pruning by memcap! "););
03456 while((mem_in_use > global_config.memcap) ||
03457 (f_cache->count > (global_config.max_frags - 5)))
03458 {
03459 hnode = sfxhash_lru_node(f_cache);
03460 if (hnode && hnode->data == not_me)
03461 {
03462 if (found_this)
03463 {
03464
03465 LogMessage("(spp_frag3) Frag3Prune: Pruning by memcap - empty list! ");
03466 return pruned;
03467 }
03468 sfxhash_gmovetofront(f_cache, hnode);
03469 found_this = 1;
03470 continue;
03471 }
03472 #ifdef DEBUG
03473 ft = hnode->data;
03474 fttime = &(ft->frag_time);
03475
03476 if (CheckTimeout(pkttime,fttime,ft->context)==FRAG_TIMEOUT)
03477 {
03478 LogMessage("(spp_frag3) Frag3Prune: Fragment dropped (timeout)! "
03479 "[0x%08X->0x%08X ID: %d Count: %d]\n", ft->sip, ft->dip,
03480 ft->id, ft->fraglist_count);
03481 f3stats.timeouts++;
03482 sfPerf.sfBase.iFragTimeouts++;
03483 }
03484 else
03485 {
03486 LogMessage("(spp_frag3) Frag3Prune: Fragment dropped (memory)! "
03487 "[0x%08X->0x%08X ID: %d Count: %d]\n", ft->sip, ft->dip,
03488 ft->id, ft->fraglist_count);
03489 }
03490 #endif
03491 Frag3RemoveTracker(hnode->key, hnode->data);
03492
03493
03494 pruned++;
03495 }
03496 }
03497 else
03498 {
03499 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03500 "(spp_frag3) Frag3Prune: Pruning by prealloc! "););
03501 while(prealloc_nodes_in_use>(global_config.static_frags-ten_percent))
03502 {
03503 hnode = sfxhash_lru_node(f_cache);
03504 if (hnode && hnode->data == not_me)
03505 {
03506 if (found_this)
03507 {
03508
03509 LogMessage("(spp_frag3) Frag3Prune: Pruning by prealloc - empty list! ");
03510 return pruned;
03511 }
03512 sfxhash_gmovetofront(f_cache, hnode);
03513 found_this = 1;
03514 continue;
03515 }
03516
03517 #ifdef DEBUG
03518 ft = hnode->data;
03519 fttime = &(ft->frag_time);
03520
03521 if (CheckTimeout(pkttime,fttime,ft->context)==FRAG_TIMEOUT)
03522 {
03523 LogMessage("(spp_frag3) Frag3Prune: Fragment dropped (timeout)! "
03524 "[0x%08X->0x%08X ID: %d Count: %d]\n", ft->sip, ft->dip,
03525 ft->id, ft->fraglist_count);
03526 f3stats.timeouts++;
03527 sfPerf.sfBase.iFragTimeouts++;
03528 }
03529 else
03530 {
03531 LogMessage("(spp_frag3) Frag3Prune: Fragment dropped (memory)! "
03532 "[0x%08X->0x%08X ID: %d Count: %d]\n", ft->sip, ft->dip,
03533 ft->id, ft->fraglist_count);
03534 }
03535 #endif
03536
03537 Frag3RemoveTracker(hnode->key, hnode->data);
03538
03539
03540 pruned++;
03541 }
03542 }
03543
03544 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03545 "(spp_frag3) Frag3Prune: Pruned %d nodes\n", pruned););
03546 return pruned;
03547 }
03548
03549
03550
03551
03552
03553
03554
03555
03556 void Frag3PrintStats()
03557 {
03558 LogMessage("Frag3 statistics:\n");
03559 LogMessage(" Total Fragments: %lu\n", f3stats.total);
03560 LogMessage(" Frags Reassembled: %lu\n", f3stats.reassembles);
03561 LogMessage(" Discards: %lu\n", f3stats.discards);
03562 LogMessage(" Memory Faults: %lu\n", f3stats.prunes);
03563 LogMessage(" Timeouts: %lu\n", f3stats.timeouts);
03564 LogMessage(" Overlaps: %lu\n", f3stats.overlaps);
03565 LogMessage(" Anomalies: %lu\n", f3stats.anomalies);
03566 LogMessage(" Alerts: %lu\n", f3stats.alerts);
03567 LogMessage(" FragTrackers Added: %lu\n", f3stats.fragtrackers_created);
03568 LogMessage(" FragTrackers Dumped: %lu\n", f3stats.fragtrackers_released);
03569 LogMessage("FragTrackers Auto Freed: %lu\n", f3stats.fragtrackers_autoreleased);
03570 LogMessage(" Frag Nodes Inserted: %lu\n", f3stats.fragnodes_created);
03571 LogMessage(" Frag Nodes Deleted: %lu\n", f3stats.fragnodes_released);
03572
03573 LogMessage("===================================================="
03574 "===========================\n");
03575 }
03576
03577
03578
03579
03580 void Frag3Restart(int signal, void *foo)
03581 {
03582 Frag3PrintStats();
03583 return;
03584 }
03585
03586
03587
03588
03589 void Frag3CleanExit(int signal, void *foo)
03590 {
03591 Frag3PrintStats();
03592
03593
03594
03595
03596 return;
03597 }
03598
03599
03600
03601
03602
03603
03604
03605 static INLINE Frag3Frag *Frag3PreallocPop()
03606 {
03607 Frag3Frag *node;
03608
03609 if(prealloc_frag_list)
03610 {
03611 node = prealloc_frag_list;
03612 prealloc_frag_list = prealloc_frag_list->next;
03613 if (prealloc_frag_list)
03614 {
03615 prealloc_frag_list->prev = NULL;
03616 }
03617 else
03618 {
03619 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03620 "Using last prealloc frag node\n"););
03621 }
03622 node->next = NULL;
03623 node->prev = NULL;
03624 node->offset = 0;
03625 node->size = 0;
03626 node->flen = 0;
03627 node->last = 0;
03628 }
03629 else
03630 {
03631 return NULL;
03632 }
03633
03634 if (!node->fptr)
03635 {
03636 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03637 "Frag3Frag fptr is NULL!\n"););
03638 }
03639
03640 prealloc_nodes_in_use++;
03641 return node;
03642 }
03643
03644
03645
03646
03647
03648
03649
03650
03651 static INLINE void Frag3PreallocPush(Frag3Frag *node)
03652 {
03653 if (!prealloc_frag_list)
03654 {
03655 node->next = NULL;
03656 node->prev = NULL;
03657 }
03658 else
03659 {
03660 node->next = prealloc_frag_list;
03661 node->prev = NULL;
03662 prealloc_frag_list->prev = node;
03663 }
03664
03665 prealloc_frag_list = node;
03666 node->data = NULL;
03667 if (!node->fptr)
03668 {
03669 DEBUG_WRAP(DebugMessage(DEBUG_FRAG,
03670 "Frag3Frag fptr is NULL!\n"););
03671 }
03672
03673 prealloc_nodes_in_use--;
03674 return;
03675 }
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685
03686
03687 static INLINE void Frag3FraglistAddNode(FragTracker *ft, Frag3Frag *prev,
03688 Frag3Frag *node)
03689 {
03690 if(prev)
03691 {
03692 node->next = prev->next;
03693 node->prev = prev;
03694 prev->next = node;
03695 if (node->next)
03696 node->next->prev = node;
03697 else
03698 ft->fraglist_tail = node;
03699 }
03700 else
03701 {
03702 node->next = ft->fraglist;
03703 if (node->next)
03704 node->next->prev = node;
03705 else
03706 ft->fraglist_tail = node;
03707 ft->fraglist = node;
03708 }
03709
03710 ft->fraglist_count++;
03711 return;
03712 }
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722 static INLINE void Frag3FraglistDeleteNode(FragTracker *ft, Frag3Frag *node)
03723 {
03724 DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Deleting list node %p (p %p n %p)\n",
03725 node, node->prev, node->next););
03726
03727 if(node->prev)
03728 node->prev->next = node->next;
03729 else
03730 ft->fraglist = node->next;
03731
03732 if(node->next)
03733 node->next->prev = node->prev;
03734 else
03735 ft->fraglist_tail = node->prev;
03736
03737 Frag3DeleteFrag(node);
03738 ft->fraglist_count--;
03739 }
03740
03741
03742
03743
03744
03745
03746
03747
03748
03749
03750
03751
03752
03753
03754
03755
03756
03757
03758 int fpAddFragAlert(Packet *p, OTNX *otnx)
03759 {
03760 FragTracker *ft = p->fragtracker;
03761
03762 if ( !ft )
03763 return 0;
03764
03765 if ( !otnx )
03766 return 0;
03767
03768 if ( !otnx->otn )
03769 return 0;
03770
03771
03772 if ( ft->alert_count >= MAX_FRAG_ALERTS )
03773 return 0;
03774
03775 ft->alert_gid[ft->alert_count] = otnx->otn->sigInfo.generator;
03776 ft->alert_sid[ft->alert_count] = otnx->otn->sigInfo.id;
03777 ft->alert_count++;
03778
03779 return 1;
03780 }
03781
03782
03783
03784
03785
03786
03787
03788
03789
03790
03791
03792
03793
03794
03795
03796
03797
03798
03799
03800 int fpFragAlerted(Packet *p, OTNX *otnx)
03801 {
03802 FragTracker *ft = p->fragtracker;
03803 SigInfo *si = &otnx->otn->sigInfo;
03804 int i;
03805
03806 if ( !ft )
03807 return 0;
03808
03809 for ( i = 0; i < ft->alert_count; i++ )
03810 {
03811
03812
03813
03814 if ( (p->packet_flags & PKT_REBUILT_FRAG)
03815 && ft->alert_gid[i] == si->generator && ft->alert_sid[i] == si->id )
03816 {
03817 return 1;
03818 }
03819 }
03820
03821 return 0;
03822 }
03823