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 #include "sfxhash.h"
00038 #include "ubi_SplayTree.h"
00039 #include "decode.h"
00040 #include "debug.h"
00041 #include "stream.h"
00042 #include "log.h"
00043
00044
00045 static ubi_trRoot s_cache;
00046 static ubi_trRootPtr RootPtr = &s_cache;
00047
00048
00049 extern void DeleteSession(Session *, u_int32_t);
00050 extern Stream4Data s4data;
00051 extern u_int32_t stream4_memory_usage;
00052 #ifdef GIDS
00053
00054 extern void SegmentTruncTraverse(Stream *, u_int16_t);
00055 #endif
00056
00057 #ifdef USE_HASH_TABLE
00058 static SFXHASH *sessionHashTable = NULL;
00059 #endif
00060
00061 #ifndef WIN32
00062 #include <sys/socket.h>
00063 #include <netinet/in.h>
00064 #include <arpa/inet.h>
00065 #endif
00066
00067 #ifdef USE_HASH_TABLE
00068 int GetSessionCount()
00069 {
00070 if (sessionHashTable)
00071 return sessionHashTable->count;
00072 else
00073 return 0;
00074 }
00075
00076 int GetSessionKey(Packet *p, SessionHashKey *key)
00077 {
00078 if (!key)
00079 return 0;
00080
00081
00082
00083 if (p->iph->ip_src.s_addr < p->iph->ip_dst.s_addr)
00084 {
00085 key->lowIP = p->iph->ip_src.s_addr;
00086 key->port = p->tcph->th_sport;
00087 key->highIP = p->iph->ip_dst.s_addr;
00088 key->port2 = p->tcph->th_dport;
00089 }
00090 else if (p->iph->ip_src.s_addr == p->iph->ip_dst.s_addr)
00091 {
00092 key->lowIP = p->iph->ip_src.s_addr;
00093 key->highIP = p->iph->ip_dst.s_addr;
00094 if (p->tcph->th_sport < p->tcph->th_dport)
00095 {
00096 key->port = p->tcph->th_sport;
00097 key->port2 = p->tcph->th_dport;
00098 }
00099 else
00100 {
00101 key->port = p->tcph->th_sport;
00102 key->port2 = p->tcph->th_dport;
00103 }
00104 }
00105 else
00106 {
00107 key->lowIP = p->iph->ip_dst.s_addr;
00108 key->port = p->tcph->th_dport;
00109 key->highIP = p->iph->ip_src.s_addr;
00110 key->port2 = p->tcph->th_sport;
00111 }
00112
00113 #if defined(_LP64)
00114 key->pad1 = key->pad2 = 0;
00115 #endif
00116
00117
00118 return 1;
00119 }
00120
00121 Session *GetSessionFromHashTable(Packet *p)
00122 {
00123 Session *returned = NULL;
00124 SFXHASH_NODE *hnode;
00125 SessionHashKey sessionKey;
00126
00127
00128
00129
00130 if (!GetSessionKey(p, &sessionKey))
00131 return NULL;
00132
00133
00134
00135 hnode = sfxhash_find_node(sessionHashTable, &sessionKey);
00136
00137 if (hnode && hnode->data)
00138 {
00139
00140
00141
00142 returned = (Session *)hnode->data;
00143 }
00144
00145 return returned;
00146 }
00147
00148 int RemoveSessionFromHashTable(Session *ssn)
00149 {
00150 return sfxhash_remove(sessionHashTable, &(ssn->hashKey));
00151 }
00152
00153 int CleanHashTable(u_int32_t thetime, Session *save_me, int memCheck)
00154 {
00155 Session *idx;
00156 u_int32_t pruned = 0;
00157
00158 if (thetime != 0)
00159 {
00160 char got_one;
00161 idx = (Session *) sfxhash_lru(sessionHashTable);
00162
00163 if(idx == NULL)
00164 {
00165 return 0;
00166 }
00167
00168 do
00169 {
00170 got_one = 0;
00171 if(idx == save_me)
00172 {
00173 SFXHASH_NODE *lastNode = sfxhash_lru_node(sessionHashTable);
00174 sfxhash_gmovetofront(sessionHashTable, lastNode);
00175 lastNode = sfxhash_lru_node(sessionHashTable);
00176 if ((lastNode) && (lastNode->data != idx))
00177 {
00178 idx = (Session *)lastNode->data;
00179 continue;
00180 }
00181 else
00182 {
00183 return pruned;
00184 }
00185 }
00186
00187 if((idx->last_session_time+s4data.timeout) < thetime)
00188 {
00189 Session *savidx = idx;
00190
00191 if(sfxhash_count(sessionHashTable) > 1)
00192 {
00193 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "pruning stale session\n"););
00194 DeleteSession(savidx, thetime);
00195 idx = (Session *) sfxhash_lru(sessionHashTable);
00196 pruned++;
00197 got_one = 1;
00198 }
00199 else
00200 {
00201 DeleteSession(savidx, thetime);
00202 pruned++;
00203 return pruned;
00204 }
00205 }
00206 else
00207 {
00208 return pruned;
00209 }
00210 } while ((idx != NULL) && (got_one == 1));
00211
00212 return pruned;
00213 }
00214 else if (s4data.cache_clean_percent == 0)
00215 {
00216
00217
00218
00219
00220 while ( ((memCheck && (stream4_memory_usage > s4data.memcap)) ||
00221 (sessionHashTable->count >
00222 (s4data.max_sessions - s4data.cache_clean_sessions))) &&
00223 (sfxhash_count(sessionHashTable) > 1))
00224 {
00225 int i;
00226 idx = (Session *) sfxhash_lru(sessionHashTable);
00227 for (i=0;i<s4data.cache_clean_sessions &&
00228 (sfxhash_count(sessionHashTable) > 1); i++)
00229 {
00230 if(idx != save_me)
00231 {
00232 DeleteSession(idx, thetime);
00233 pruned++;
00234 idx = (Session *) sfxhash_lru(sessionHashTable);
00235 }
00236 else
00237 {
00238 SFXHASH_NODE *lastNode = sfxhash_lru_node(sessionHashTable);
00239 sfxhash_gmovetofront(sessionHashTable, lastNode);
00240 lastNode = sfxhash_lru_node(sessionHashTable);
00241 if ((lastNode) && (lastNode->data == idx))
00242 {
00243
00244 break;
00245 }
00246 idx = (Session *) sfxhash_lru(sessionHashTable);
00247 i--;
00248 }
00249 }
00250 }
00251 }
00252 else
00253 {
00254
00255 u_int32_t smallPercent = (u_int32_t)(s4data.max_sessions *
00256 s4data.cache_clean_percent);
00257 idx = (Session *) sfxhash_lru(sessionHashTable);
00258 while ((stream4_memory_usage > (s4data.memcap - smallPercent)) &&
00259 (sfxhash_count(sessionHashTable) > 1))
00260 {
00261 idx = (Session *) sfxhash_lru(sessionHashTable);
00262 if(idx != save_me)
00263 {
00264 DeleteSession(idx, thetime);
00265 pruned++;
00266 idx = (Session *) sfxhash_lru(sessionHashTable);
00267 }
00268 else
00269 {
00270 SFXHASH_NODE *lastNode = sfxhash_lru_node(sessionHashTable);
00271 sfxhash_gmovetofront(sessionHashTable, lastNode);
00272 lastNode = sfxhash_lru_node(sessionHashTable);
00273 if ((lastNode) && (lastNode->data == idx))
00274 {
00275
00276 break;
00277 }
00278 idx = (Session *) sfxhash_lru(sessionHashTable);
00279 }
00280 }
00281 }
00282 return pruned;
00283 }
00284
00285 Session *GetNewSession(Packet *p)
00286 {
00287 Session *retSsn = NULL;
00288 SessionHashKey sessionKey;
00289 SFXHASH_NODE *hnode;
00290
00291 if (!GetSessionKey(p, &sessionKey))
00292 return retSsn;
00293
00294 hnode = sfxhash_get_node(sessionHashTable, &sessionKey);
00295 if (!hnode)
00296 {
00297 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "HashTable full, clean it\n"););
00298 if (!CleanHashTable(p->pkth->ts.tv_sec, NULL, 0))
00299 {
00300 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "HashTable full, no timeouts, clean it\n"););
00301 CleanHashTable(0, NULL, 0);
00302 }
00303
00304
00305 hnode = sfxhash_get_node(sessionHashTable, &sessionKey);
00306 #ifdef DEBUG
00307 if (!hnode)
00308 {
00309 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Problem, no freed nodes\n"););
00310 }
00311 #endif
00312 }
00313 if (hnode && hnode->data)
00314 {
00315 retSsn = hnode->data;
00316
00317 memset(retSsn, 0, sizeof(Session));
00318
00319
00320 memcpy(&(retSsn->hashKey), &sessionKey,
00321 sizeof(SessionHashKey));
00322
00323 #if 0
00324 retSsn->ttl = 0;
00325 retSsn->alert_count = 0;
00326 retSsn->http_alert_flags = 0;
00327 retSsn->preproc_data = NULL;
00328 retSsn->preproc_free = NULL;
00329 retSsn->preproc_proto = 0;
00330 #endif
00331 }
00332 return retSsn;
00333 }
00334 #endif
00335
00336 Session *GetSessionFromSplayTree(Packet *p)
00337 {
00338 Session idx;
00339 Session *returned;
00340 #ifdef DEBUG
00341 char flagbuf[9];
00342 CreateTCPFlagString(p, flagbuf);
00343 #endif
00344
00345 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Trying to get session...\n"););
00346 idx.server.ip = p->iph->ip_src.s_addr;
00347 idx.client.ip = p->iph->ip_dst.s_addr;
00348 idx.server.port = p->sp;
00349 idx.client.port = p->dp;
00350
00351 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Looking for sip: 0x%X sp: %d cip: "
00352 "0x%X cp: %d flags: %s\n", idx.server.ip, idx.server.port,
00353 idx.client.ip, idx.client.port, flagbuf););
00354
00355 returned = (Session *) ubi_sptFind(RootPtr, (ubi_btItemPtr)&idx);
00356
00357 if(returned == NULL)
00358 {
00359 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "GetSession forward didn't work, "
00360 "trying backwards...\n"););
00361 idx.server.ip = p->iph->ip_dst.s_addr;
00362 idx.client.ip = p->iph->ip_src.s_addr;
00363 idx.server.port = p->dp;
00364 idx.client.port = p->sp;
00365 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Looking for sip: 0x%X sp: %d "
00366 "cip: 0x%X cp: %d flags: %s\n", idx.server.ip,
00367 idx.server.port, idx.client.ip, idx.client.port,
00368 flagbuf););
00369 returned = (Session *) ubi_sptFind(RootPtr, (ubi_btItemPtr)&idx);
00370 }
00371
00372 if(returned == NULL)
00373 {
00374 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Unable to find session\n"););
00375 }
00376 else
00377 {
00378 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "Found session\n"););
00379 }
00380
00381 return returned;
00382
00383 }
00384
00385 Session *RemoveSession(Session *ssn)
00386 {
00387 #ifdef USE_HASH_TABLE
00388 if (!RemoveSessionFromHashTable(ssn) )
00389 return ssn;
00390 else
00391 return NULL;
00392 #else
00393 Session *killme = NULL;
00394 if(ubi_trCount(RootPtr))
00395 {
00396 killme = (Session *) ubi_sptRemove(RootPtr, (ubi_btNodePtr) ssn);
00397 }
00398 return killme;
00399 #endif
00400 }
00401
00402 Session *GetSession(Packet *p)
00403 {
00404 #ifdef USE_HASH_TABLE
00405 return GetSessionFromHashTable(p);
00406 #else
00407 return GetSessionFromSplayTree(p);
00408 #endif
00409 }
00410
00411 #ifdef USE_HASH_TABLE
00412 #else
00413 static int CompareFunc(ubi_trItemPtr ItemPtr, ubi_trNodePtr NodePtr)
00414 {
00415 Session *nSession;
00416 Session *iSession;
00417
00418 nSession = ((Session *)NodePtr);
00419 iSession = (Session *)ItemPtr;
00420
00421 if(nSession->server.ip < iSession->server.ip) return 1;
00422 else if(nSession->server.ip > iSession->server.ip) return -1;
00423
00424 if(nSession->client.ip < iSession->client.ip) return 1;
00425 else if(nSession->client.ip > iSession->client.ip) return -1;
00426
00427 if(nSession->server.port < iSession->server.port) return 1;
00428 else if(nSession->server.port > iSession->server.port) return -1;
00429
00430 if(nSession->client.port < iSession->client.port) return 1;
00431 else if(nSession->client.port > iSession->client.port) return -1;
00432
00433 return 0;
00434 }
00435 #endif
00436
00437 void InitSessionCache()
00438 {
00439 #ifdef USE_HASH_TABLE
00440 if (!sessionHashTable)
00441 {
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 int hashTableSize = (int) (s4data.max_sessions * 1.4);
00456 int maxSessionMem = s4data.max_sessions * (
00457 sizeof(Session) +
00458 sizeof(SFXHASH_NODE) +
00459 sizeof(SessionHashKey) +
00460 sizeof (SFXHASH_NODE *));
00461 int tableMem = (hashTableSize +1) * sizeof(SFXHASH_NODE*);
00462 int maxMem = maxSessionMem + tableMem;
00463 sessionHashTable = sfxhash_new(hashTableSize,
00464 sizeof(SessionHashKey),
00465 sizeof(Session), maxMem, 0, NULL, NULL, 1);
00466
00467
00468 }
00469 #else
00470 (void)ubi_trInitTree(RootPtr,
00471 CompareFunc,
00472 0);
00473
00474 #endif
00475 }
00476
00477 void PurgeSessionCache()
00478 {
00479 Session *ssn = NULL;
00480 #ifdef USE_HASH_TABLE
00481 ssn = (Session *)sfxhash_mru(sessionHashTable);
00482 #else
00483 ssn = (Session *)ubi_trFirst(RootPtr);
00484 #endif
00485 while (ssn)
00486 {
00487 DeleteSession(ssn, 0);
00488 #ifdef USE_HASH_TABLE
00489 ssn = (Session *)sfxhash_mru(sessionHashTable);
00490 #else
00491 ssn = (Session *)ubi_trFirst(RootPtr);
00492 #endif
00493 }
00494 }
00495
00496 void PrintSessionCache()
00497 {
00498 #ifdef USE_HASH_TABLE
00499 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "%lu streams active, %u bytes in use\n",
00500 sfxhash_count(sessionHashTable), stream4_memory_usage););
00501 #else
00502 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "%lu streams active, %u bytes in use\n",
00503 ubi_trCount(RootPtr), stream4_memory_usage););
00504 #endif
00505 return;
00506 }
00507
00508 int PruneSessionCache(u_int32_t thetime, int mustdie, Session *save_me)
00509 {
00510 #ifdef USE_HASH_TABLE
00511 return CleanHashTable(thetime, save_me, 1);
00512 #else
00513 Session *idx;
00514 u_int32_t pruned = 0;
00515
00516 if(ubi_trCount(RootPtr) == 0)
00517 {
00518 return 0;
00519 }
00520
00521 {
00522 if (thetime != 0)
00523 {
00524 char got_one;
00525 idx = (Session *) ubi_btLast((ubi_btNodePtr)RootPtr->root);
00526
00527 if(idx == NULL)
00528 {
00529 return 0;
00530 }
00531
00532 do
00533 {
00534 got_one = 0;
00535 if(idx == save_me)
00536 {
00537 idx = (Session *) ubi_btPrev((ubi_btNodePtr)idx);
00538 continue;
00539 }
00540
00541 if((idx->last_session_time+s4data.timeout) < thetime)
00542 {
00543 Session *savidx = idx;
00544
00545 if(ubi_trCount(RootPtr) > 1)
00546 {
00547 idx = (Session *) ubi_btPrev((ubi_btNodePtr)idx);
00548 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "pruning stale session\n"););
00549 DeleteSession(savidx, thetime);
00550 pruned++;
00551 got_one = 1;
00552 }
00553 else
00554 {
00555 DeleteSession(savidx, thetime);
00556 pruned++;
00557 return pruned;
00558 }
00559 }
00560 else
00561 {
00562 if(idx != NULL && ubi_trCount(RootPtr))
00563 {
00564 idx = (Session *) ubi_btPrev((ubi_btNodePtr)idx);
00565 }
00566 else
00567 {
00568 return pruned;
00569 }
00570 }
00571 } while ((idx != NULL) && (got_one == 1));
00572
00573 return pruned;
00574 }
00575 else if (s4data.cache_clean_percent == 0)
00576 {
00577
00578
00579 while ((stream4_memory_usage > s4data.memcap) &&
00580 ubi_trCount(RootPtr) > 1)
00581 {
00582 int i;
00583 idx = (Session *) ubi_btLeafNode((ubi_btNodePtr)RootPtr);
00584 for (i=0;i<s4data.cache_clean_sessions &&
00585 ubi_trCount(RootPtr) > 1; i++)
00586 {
00587 if(idx != save_me)
00588 {
00589 DeleteSession(idx, thetime);
00590 pruned++;
00591 idx = (Session *) ubi_btLeafNode((ubi_btNodePtr)RootPtr);
00592 }
00593 else
00594 {
00595 Rotate((ubi_btNodePtr)idx);
00596 idx = (Session *) ubi_btLeafNode((ubi_btNodePtr)RootPtr);
00597 i--;
00598 }
00599 }
00600 }
00601 }
00602 else
00603 {
00604
00605 u_int32_t smallPercent = (u_int32_t)(s4data.memcap * s4data.cache_clean_percent);
00606 idx = (Session *) ubi_btLeafNode((ubi_btNodePtr)RootPtr);
00607 while ((stream4_memory_usage > (s4data.memcap - smallPercent)) &&
00608 ubi_trCount(RootPtr) > 1)
00609 {
00610 if(idx != save_me)
00611 {
00612 DeleteSession(idx, thetime);
00613 pruned++;
00614 idx = (Session *) ubi_btLeafNode((ubi_btNodePtr)RootPtr);
00615 }
00616 else
00617 {
00618 Rotate((ubi_btNodePtr)idx);
00619 idx = (Session *) ubi_btLeafNode((ubi_btNodePtr)RootPtr);
00620 }
00621 }
00622 }
00623 #ifdef DEBUG
00624 if(ubi_trCount(RootPtr) == 1) {
00625 DebugMessage(DEBUG_STREAM, "Emptied out the stream cache "
00626 "completely mustdie: %d, memusage: %u\n",
00627 mustdie,
00628 stream4_memory_usage);
00629 }
00630 #endif
00631 return pruned;
00632 }
00633 #endif
00634
00635 return 0;
00636 }
00637
00638
00639 #ifdef GIDS
00640 #ifdef USE_HASH_TABLE
00641 void TruncSession(Session *idx, u_int32_t thetime)
00642 {
00643 Stream *s;
00644 u_int16_t bytes_to_clear = 0;
00645
00646
00647 if(idx->client.last_trunc_time != thetime)
00648 {
00649
00650
00651
00652
00653 s = &idx->client;
00654
00655
00656
00657
00658 if(s->bytes_tracked > 0 && ubi_trCount(&s->data) > 1)
00659 {
00660
00661 bytes_to_clear = (s->bytes_tracked / 100) * s4data.truncate_cut_off_perc;
00662
00663
00664
00665
00666
00667 SegmentTruncTraverse(s, bytes_to_clear);
00668
00669
00670 }
00671
00672
00673 idx->client.last_trunc_time = thetime;
00674 }
00675
00676 if(idx->server.last_trunc_time != thetime)
00677 {
00678
00679
00680
00681
00682 s = &idx->server;
00683
00684
00685
00686
00687 if(s->bytes_tracked > 0 && ubi_trCount(&s->data) > 1)
00688 {
00689
00690 bytes_to_clear = (s->bytes_tracked / 100) * s4data.truncate_cut_off_perc;
00691
00692
00693
00694
00695
00696 SegmentTruncTraverse(s, bytes_to_clear);
00697
00698
00699 }
00700
00701
00702 idx->server.last_trunc_time = thetime;
00703 }
00704 }
00705
00706 int TruncHashTable(u_int32_t thetime, Session *save_me, int memCheck)
00707 {
00708 Session *idx = NULL, *savidx = NULL;
00709 u_int32_t pruned = 0;
00710 SFXHASH_NODE *lastNode = NULL;
00711
00712
00713
00714 if (thetime != 0)
00715 {
00716 char got_one;
00717 idx = (Session *) sfxhash_lru(sessionHashTable);
00718
00719 if(idx == NULL)
00720 {
00721 return 0;
00722 }
00723
00724 do
00725 {
00726 got_one = 0;
00727 if(idx == save_me)
00728 {
00729
00730
00731 lastNode = sfxhash_lru_node(sessionHashTable);
00732 sfxhash_gmovetofront(sessionHashTable, lastNode);
00733 lastNode = sfxhash_lru_node(sessionHashTable);
00734 if ((lastNode) && (lastNode->data != idx))
00735 {
00736 idx = (Session *)lastNode->data;
00737 continue;
00738 }
00739 else
00740 {
00741 return pruned;
00742 }
00743 }
00744
00745
00746 if((idx->last_session_time+s4data.timeout) < thetime)
00747 {
00748
00749
00750 savidx = idx;
00751
00752 if(sfxhash_count(sessionHashTable) > 1)
00753 {
00754 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "pruning stale session\n"););
00755 TruncSession(savidx, thetime);
00756 idx = (Session *) sfxhash_lru(sessionHashTable);
00757 pruned++;
00758 got_one = 1;
00759
00760 if ((lastNode) && (lastNode->data))
00761 {
00762 idx = (Session *)lastNode->data;
00763 continue;
00764 }
00765 else
00766 {
00767 return pruned;
00768 }
00769 }
00770 else
00771 {
00772 TruncSession(savidx, thetime);
00773 pruned++;
00774 return pruned;
00775 }
00776 }
00777
00778 else if( idx->server.last_trunc_time != thetime ||
00779 idx->client.last_trunc_time != thetime)
00780 {
00781 savidx = idx;
00782
00783 if(sfxhash_count(sessionHashTable) > 1)
00784 {
00785 DEBUG_WRAP(DebugMessage(DEBUG_STREAM, "pruning un-truncated session\n"););
00786 TruncSession(savidx, thetime);
00787 idx = (Session *) sfxhash_lru(sessionHashTable);
00788 pruned++;
00789 got_one = 1;
00790
00791
00792
00793
00794
00795 lastNode = sfxhash_lru_node(sessionHashTable);
00796 sfxhash_gmovetofront(sessionHashTable, lastNode);
00797 lastNode = sfxhash_lru_node(sessionHashTable);
00798 if ((lastNode) && (lastNode->data))
00799 {
00800 idx = (Session *)lastNode->data;
00801 continue;
00802 }
00803 else
00804 {
00805 return pruned;
00806 }
00807 }
00808 else
00809 {
00810 TruncSession(savidx, thetime);
00811 pruned++;
00812 return pruned;
00813 }
00814 }
00815 else
00816 {
00817 return pruned;
00818 }
00819 } while ((idx != NULL) && (got_one == 1));
00820
00821 return pruned;
00822 }
00823 return pruned;
00824 }
00825 #endif
00826 #endif
00827
00828
00829 #ifdef GIDS
00830
00831
00832 int TruncSessionCache(u_int32_t thetime, int must_trunc, Session *save_me)
00833 {
00834 #ifdef USE_HASH_TABLE
00835 u_int32_t cnt = 0;
00836
00837 cnt = TruncHashTable(thetime, save_me, 0);
00838
00839 #else
00840 Session *idx;
00841 Stream *s;
00842
00843 u_int16_t bytes_to_clear = 0;
00844
00845 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"TruncSessionCache starting... (%d sessions must be truncated, %lu sessions total)\n", must_trunc, ubi_trCount(RootPtr)););
00846
00847 if(ubi_trCount(RootPtr) == 0)
00848 {
00849 return 0;
00850 }
00851
00852 if(!must_trunc || !thetime)
00853 {
00854 return 0;
00855 }
00856
00857
00858 idx = (Session *) ubi_btLeafNode((ubi_btNodePtr)RootPtr);
00859
00860 while(must_trunc-- && ubi_trCount(RootPtr) > 1)
00861 {
00862 idx = (Session *) ubi_btNext((ubi_btNodePtr)idx);
00863
00864 if(idx == NULL)
00865 break;
00866
00867 if(idx != save_me)
00868 {
00869
00870
00871
00872 if(idx->client.last_trunc_time != thetime)
00873 {
00874 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"TruncSessionCache: client: %d (%p).\n", idx->client.bytes_tracked, idx););
00875
00876 s = &idx->client;
00877
00878
00879
00880
00881 if(s->bytes_tracked && ubi_trCount(&s->data) > 1)
00882 {
00883
00884 bytes_to_clear = s->bytes_tracked * (s4data.truncate_cut_off_perc / 100);
00885
00886 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"%5d -> %5d: stream_size: %5d: Going to try to truncate %d bytes\n", idx->client.port, idx->server.port, s->bytes_tracked, bytes_to_clear););
00887
00888
00889
00890 SegmentTruncTraverse(s, bytes_to_clear);
00891 }
00892
00893
00894 idx->client.last_trunc_time = thetime;
00895 }
00896
00897 if(idx->server.last_trunc_time != thetime)
00898 {
00899 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"TruncSessionCache: server: %d (%p).\n", idx->server.bytes_tracked, idx););
00900
00901 s = &idx->server;
00902
00903
00904
00905
00906 if(s->bytes_tracked && ubi_trCount(&s->data) > 1)
00907 {
00908
00909 bytes_to_clear = s->bytes_tracked * (s4data.truncate_cut_off_perc / 100);
00910
00911 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"%5d -> %5d: stream_size: %5d: Going to try to truncate %d bytes\n", idx->client.port, idx->server.port, s->bytes_tracked, bytes_to_clear););
00912
00913
00914
00915 SegmentTruncTraverse(s, bytes_to_clear);
00916 }
00917
00918
00919 idx->server.last_trunc_time = thetime;
00920 }
00921 }
00922 }
00923
00924 #ifdef DEBUG
00925 if(must_trunc)
00926 {
00927 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"Truncated all sessions in the cache completely: must_trunc: %d, memusage: %u\n",must_trunc,stream4_memory_usage););
00928 }
00929 #endif
00930
00931 #endif
00932 return 0;
00933 }
00934
00935
00936 #include "util.h"
00937 #include <errno.h>
00938
00939 int DumpStateTable(const char *path)
00940 {
00941 #ifdef USE_HASH_TABLE
00942 Session *idx;
00943 u_int8_t tag = rand();
00944 char got_one = 1;
00945 Stream *client = NULL;
00946 Stream *server = NULL;
00947 SFXHASH_NODE *lastNode = NULL;
00948 struct in_addr sip, cip;
00949 char sipstr[16] = "", cipstr[16] = "";
00950 u_int32_t dumpcnt = 0,
00951 skipcnt = 0;
00952 FILE *fp = NULL;
00953
00954 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"connections in hash: %u (path %s)\n", GetSessionCount(), path););
00955
00956 idx = (Session *) sfxhash_lru(sessionHashTable);
00957 if(idx == NULL)
00958 {
00959 return 0;
00960 }
00961
00962 if(path != NULL)
00963 {
00964 fp = fopen(path, "w+");
00965 if(fp == NULL)
00966 {
00967 FatalError("Opening '%s' failed: %s.\n", path, strerror(errno));
00968 return 0;
00969 }
00970
00971 fprintf(fp, "# state, start_time, last_session_time, client->ip, "
00972 "client->port, client->isn, client->base_seq, "
00973 "client->last_ack, client->win_size, client->pkts_sent, "
00974 "client->bytes_sent server->ip, server->port, server->isn, "
00975 "server->base_seq, server->last_ack, server->win_size, "
00976 "server->pkts_sent, server->bytes_sent\n");
00977 }
00978
00979 do
00980 {
00981 got_one = 0;
00982
00983
00984 if(idx->dumptag != tag)
00985 {
00986 got_one = 1;
00987
00988
00989 idx->dumptag = tag;
00990
00991 client = &idx->client;
00992 server = &idx->server;
00993
00994
00995 if(path == NULL)
00996 {
00997 cip.s_addr = client->ip;
00998 sip.s_addr = server->ip;
00999
01000 strlcpy(cipstr, inet_ntoa(cip), sizeof(cipstr));
01001 strlcpy(sipstr, inet_ntoa(sip), sizeof(sipstr));
01002
01003 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"connection %s:%u %s:%u\n",
01004 cipstr, client->port, sipstr, server->port););
01005 }
01006 else
01007 {
01008 if(idx->session_flags & SSNFLAG_ESTABLISHED ||
01009 idx->session_flags & SSNFLAG_MIDSTREAM)
01010 {
01011
01012 if(idx->session_flags & SSNFLAG_ESTABLISHED)
01013 fprintf(fp, "ESTABLISHED ");
01014 else if(idx->session_flags & SSNFLAG_MIDSTREAM)
01015 fprintf(fp, "MIDSTREAM ");
01016
01017
01018 fprintf(fp, "%u %u ", (u_int)idx->start_time,
01019 (u_int)idx->last_session_time);
01020
01021
01022 fprintf(fp, "%u %u %u %u %u %u %u %u ",
01023 client->ip, client->port,
01024 client->isn, client->base_seq, client->last_ack,
01025 client->win_size, client->pkts_sent, client->bytes_sent);
01026
01027
01028 fprintf(fp, "%u %u %u %u %u %u %u %u ",
01029 server->ip, server->port,
01030 server->isn, server->base_seq, server->last_ack,
01031 server->win_size, server->pkts_sent, server->bytes_sent);
01032
01033 fprintf(fp, "\n");
01034
01035 dumpcnt++;
01036 }
01037 else
01038 {
01039 skipcnt++;
01040 }
01041 }
01042
01043
01044
01045
01046
01047 lastNode = sfxhash_lru_node(sessionHashTable);
01048 sfxhash_gmovetofront(sessionHashTable, lastNode);
01049
01050 idx = (Session *) sfxhash_lru(sessionHashTable);
01051 }
01052 } while((idx != NULL) && (got_one == 1));
01053
01054 if(path != NULL)
01055 {
01056 fclose(fp);
01057
01058 LogMessage("Dumped %u connections to the state file.\n", dumpcnt);
01059 }
01060
01061 DEBUG_WRAP(DebugMessage(DEBUG_STREAM,"connections dumped: %u, skipped: %u, "
01062 "total: %u\n", dumpcnt, skipcnt, dumpcnt+skipcnt););
01063 return 0;
01064 #else
01065 printf("%s only works with USE_HASH_TABLE enabled.\n", __FUNCTION__);
01066 return 0;
01067 #endif
01068 }
01069
01070 #endif