engine/session.c

Go to the documentation of this file.
00001 #define DEBUG
00002 //#define DEBUG_TIME    // Debug the session timing out code
00003 #define DEBUG_DIRECTION // Debug the find session direction/state code
00004 
00005 // TODO: add a shutdown handler that frees all allocated memory for sessions
00006 #include "session.h"
00007 #include "hlbrlib.h"
00008 #include "main_loop.h"
00009 #include "../decoders/decode_ip.h"
00010 #include "../decoders/decode_tcp.h"
00011 #include "../packets/packet.h"
00012 #include <stdio.h>
00013 #include <string.h>
00014 #include <stdlib.h>
00015 #include <arpa/inet.h>
00016 #include <netinet/in.h>
00017 
00018 /*+++++++++++++++++++Globals+++++++++++++++++*/
00019 IPB*                    Sessions[65536+1]; 
00020 int                     TCPDecoderID;
00021 int                     IPDecoderID;
00022 unsigned int            SessionCount = 0;
00023 SFunc*                  CreateFuncs;
00024 SFunc*                  DestroyFuncs;
00025 extern  GlobalVars      Globals;
00026 
00027 PP*                     TimeHead;
00028 PP*                     TimeTail;
00029 
00030 #ifdef DEBUG_DIRECTION
00031 #define DBGDIR(a)       a
00032 #else
00033 #define DBGDIR(a)
00034 #endif
00035 
00036 
00037 int RemountTCPStream(int, PP*, TCPData*);
00038 int TCPStream_Unqueue(PP*);
00039 
00040 
00041 
00042 /****************************************
00043 * Add function that gets called whenever a
00044 * session is created
00045 *****************************************/
00046 int AddSessionCreateHandler(void (*Func) (PP* Port, void* Data), void* Data){
00047         SFunc*  F;
00048 
00049         DEBUGPATH;
00050 
00051         if (!CreateFuncs){
00052                 CreateFuncs=calloc(sizeof(SFunc),1);
00053                 CreateFuncs->Func=Func;
00054                 CreateFuncs->Data=Data;
00055                 
00056                 return TRUE;
00057         }
00058 
00059         F=CreateFuncs;
00060         while (F->Next) F=F->Next;
00061         
00062         F->Next=calloc(sizeof(SFunc),1);
00063         F=F->Next;
00064         F->Func=Func;
00065         F->Data=Data;
00066         
00067         return TRUE;
00068 }
00069 
00070 /****************************************
00071 * Add function that gets called whenever a
00072 * session is detroyed
00073 *****************************************/
00074 int AddSessionDestroyHandler(void (*Func) (PP* Port, void* Data), void* Data){
00075         SFunc*  F;
00076         
00077         DEBUGPATH;
00078 
00079         if (!DestroyFuncs){
00080                 DestroyFuncs=calloc(sizeof(SFunc),1);
00081                 DestroyFuncs->Func=Func;
00082                 DestroyFuncs->Data=Data;
00083                 
00084                 return TRUE;
00085         }
00086 
00087         F=DestroyFuncs;
00088         while (F->Next) F=F->Next;
00089         
00090         F->Next=calloc(sizeof(SFunc),1);
00091         F=F->Next;
00092         F->Func=Func;
00093         F->Data=Data;
00094         
00095         return TRUE;
00096 }
00097 
00103 void CallCreateFuncs(PP* Port)
00104 {
00105         SFunc*  F;
00106 
00107         DEBUGPATH;
00108 
00109         F = CreateFuncs;
00110         
00111         while (F) {
00112                 F->Func(Port, F->Data);
00113                 F = F->Next;
00114         }
00115 }
00116 
00117 /***************************************
00118 * Tell everyone a new session ended
00119 ***************************************/
00120 void CallDestroyFuncs(PP* Port){
00121         SFunc*  F;
00122 
00123         DEBUGPATH;
00124 
00125         F=DestroyFuncs;
00126         
00127         while (F){
00128                 F->Func(Port, F->Data);
00129                 F=F->Next;
00130         }
00131 }
00132 
00133 /***************************************
00134 * Find out what bin this goes in
00135 ***************************************/
00136 unsigned short GetHash(unsigned int ip1, unsigned int ip2){
00137         unsigned short  hash;
00138         unsigned short  v1;
00139         
00140         DEBUGPATH;
00141 
00142         hash=ip1/65536;
00143         v1=(ip1 & 0x0000FFFF);
00144         hash ^= v1;
00145         v1=ip2/65536;
00146         hash ^= v1;
00147         v1=(ip2 & 0x0000FFFF);
00148         hash ^= v1;
00149 
00150         //return 100;
00151         return hash;
00152 }
00153 
00154 /************************************
00155 * Find the IP Pair, if it doesn't 
00156 * exist, create it
00157 ************************************/
00158 IPP* FindIPPair(unsigned int IP1, unsigned int IP2)
00159 {
00160         unsigned short  Hash;
00161         IPB*            Bin;
00162         IPP*            Pair;
00163         int             i;
00164         unsigned int    Top, Bottom, Middle;
00165         
00166         DEBUGPATH;
00167 
00168 #ifdef DEBUG
00169         printf("%s-",inet_ntoa(*(struct in_addr*)&IP1));
00170         printf("%s\n",inet_ntoa(*(struct in_addr*)&IP2));
00171 #endif
00172 
00173         Hash=GetHash(IP1, IP2);
00174 
00175         if (!Sessions[Hash]){
00176 #ifdef DEBUG
00177                 printf("First IP Pair in this bin %u\n", Hash);
00178 #endif  
00179                 Sessions[Hash]=calloc(sizeof(IPB),1);
00180                 if (!Sessions[Hash]){
00181                         printf("Out of memory\n");
00182                         return NULL;
00183                 }
00184                 
00185                 Bin=Sessions[Hash];
00186                 Bin->NumAllocated=IP_START;
00187                 Bin->NumIPs=1;
00188                 Bin->Pairs=calloc(sizeof(IPP*),IP_START+1);
00189                 
00190                 Bin->Pairs[0]=calloc(sizeof(IPP),1);
00191                 Pair=Bin->Pairs[0];
00192                 
00193                 Pair->IP1=IP1;
00194                 Pair->IP2=IP2;
00195                 Pair->NumAllocated=0;
00196                 Pair->NumPorts=0;
00197                 Pair->RefuseFromThisIP = 0;
00198                 Pair->Parent=Bin;
00199                 
00200                 return Pair;
00201         }
00202         
00203         /*replace this with a binary search after stable*/
00204         Bin = Sessions[Hash];
00205         
00206         Top = Bin->NumIPs-1;
00207         Bottom = 0;
00208         Middle = Bottom + ((Top-Bottom)/2);
00209         
00210         do {
00211                 Pair=Bin->Pairs[Middle];
00212                 
00213                 if (!Pair) {
00214                         printf("Pair was NULL. Tree corrupt\n");
00215                         return NULL;
00216                 }
00217                 
00218                 if ((Pair->IP1==IP1) && (Pair->IP2==IP2)) {
00219                         //DBG( PRINT2("Found Pair in Bin %i Slot %i\n", Hash, Middle) );
00220                         return Pair;
00221                 }
00222                 
00223                 if ( (IP1<Pair->IP1) || ( (IP1==Pair->IP1) && (IP2<Pair->IP2)) ) {
00224                         if (Top == Bottom) break;
00225                         
00226                         Top = Middle;
00227                         Middle = Bottom + ((Top-Bottom)/2);
00228                 }else{
00229                         if (Top == Bottom) break;
00230                         
00231                         Bottom = Middle+1;
00232                         Middle = Bottom + ((Top-Bottom)/2);
00233                 }
00234         } while (1);
00235         
00236 
00237 #ifdef DEBUG
00238         printf("Creating new pair\n");
00239 #endif
00240         
00241         if (Bin->NumIPs == Bin->NumAllocated) {
00242                 /*Not found, create a new one*/
00243                 Bin->Pairs=realloc(Bin->Pairs, sizeof(IPP*)*(Bin->NumAllocated+IP_GROW+2));
00244                 if (!Bin->Pairs){
00245                         printf("realloc failed\n");
00246                         exit(1);
00247                 }
00248         
00249                 /*Null out the new pointers*/
00250                 for (i = Bin->NumIPs; i < (Bin->NumAllocated+IP_GROW+1); i++) {
00251                         Bin->Pairs[i]=NULL;
00252                 }
00253         
00254                 Bin->NumAllocated+=IP_GROW;
00255         }
00256 
00257         if ( (IP1>Pair->IP1) || ( (IP1==Pair->IP1) && (IP2>Pair->IP2)) )
00258                 Middle++;
00259         
00260         memmove(&Bin->Pairs[Middle+1], &Bin->Pairs[Middle], sizeof(IPP*)*(Bin->NumIPs-Middle));
00261         
00262         Bin->Pairs[Middle]=calloc(sizeof(IPP),1);
00263         Pair=Bin->Pairs[Middle];
00264         Bin->NumIPs++;
00265         
00266         Pair->IP1=IP1;
00267         Pair->IP2=IP2;
00268         Pair->NumAllocated=0;
00269         Pair->NumPorts=0;
00270         Pair->RefuseFromThisIP = 0;
00271         Pair->Parent=Bin;
00272         
00273         return Pair;
00274 }
00275 
00283 int AddToTime(PP* Port)
00284 {
00285         DEBUGPATH;
00286 
00287         if (!TimeHead) {
00288                 TimeHead = Port;
00289                 TimeTail = Port;
00290                 Port->TimeNext = NULL;
00291                 Port->TimePrev = NULL;
00292                 
00293                 return TRUE;
00294         }
00295         
00296         if (!TimeTail) {
00297                 PRINTERROR("TimeTail was NULL.  Time chain is corrupted!\n");
00298                 return FALSE;
00299         }
00300         
00301         if (TimeTail->TimeNext) {
00302                 PRINTERROR("TimeTail->Next was not NULL.  Time chain is corrupted!\n");
00303                 return FALSE;
00304         }
00305         
00306         TimeTail->TimeNext = Port;
00307         Port->TimePrev = TimeTail;
00308         Port->TimeNext = NULL;
00309         TimeTail = Port;
00310 
00311         return TRUE;
00312 }
00313 
00321 int UpdateTime(PP* Port)
00322 {
00323         DEBUGPATH;
00324 
00325         if (TimeTail == Port) {
00326                 /* already the last */
00327                 return TRUE;
00328         }
00329 
00330         if (TimeHead == Port) {
00331                 if (Port->TimeNext == NULL) {
00332                         /* only item in chain */
00333                         return TRUE;
00334                 }
00335                 
00336                 TimeHead = TimeHead->TimeNext;
00337                 TimeHead->TimePrev = NULL;
00338                 
00339                 TimeTail->TimeNext = Port;
00340                 Port->TimeNext = NULL;
00341                 Port->TimePrev = TimeTail;
00342                 TimeTail = Port;
00343                 
00344                 return TRUE;
00345         }
00346         
00347         Port->TimePrev->TimeNext = Port->TimeNext;
00348         Port->TimeNext->TimePrev = Port->TimePrev;
00349         Port->TimeNext = NULL;
00350         TimeTail->TimeNext = Port;
00351         Port->TimePrev = TimeTail;
00352         TimeTail = Port;
00353         
00354         return TRUE;
00355 }
00356 
00357 
00361 int RemovePort(PP* Port)
00362 {
00363         IPP*            Pair;
00364         IPB*            Bin;
00365         int             Top, Bottom, Middle;
00366         unsigned short  Hash;
00367         char            Message[1024];
00368         
00369         DEBUGPATH;
00370 
00371         DBG( PRINT1("Freeing port with SessionID %u\n", Port->SessionID) );
00372 
00373         /* tell everyone this is going away */
00374         CallDestroyFuncs(Port);
00375 
00376         /* logs session */
00377         if (Globals.logSession_StartEnd) {
00378                 snprintf(Message, 1024, 
00379                          "End:%4x %d.%d.%d.%d:%d->%d.%d.%d.%d:%d dir:%d pcount:%d\n",
00380                          Port->SessionID, IP_BYTES(Pair->IP1), Port->Port1,
00381                          IP_BYTES(Pair->IP2), Port->Port2,
00382                          Port->Direction, Port->TCPCount);
00383                 LogMessage(Message, &(Globals.logSessionFile));
00384         }
00385 
00386         /* get pointers to parents */
00387         Pair = Port->Parent;
00388         Bin = Pair->Parent;
00389 
00390         /* remove from the time linked list */
00391         if ( (Port == TimeHead) && (Port == TimeTail) ) {
00392                 /* only item in the list */
00393                 if (Port->TimeNext || Port->TimePrev) {
00394                         PRINTERROR("Error Time chain is corrupt!\n");
00395                         return FALSE;
00396                 }
00397                 
00398                 TimeHead = NULL;
00399                 TimeTail = NULL;
00400         } else if (Port == TimeHead) {
00401                 Port->TimeNext->TimePrev = NULL;
00402                 TimeHead = Port->TimeNext;
00403         } else if (Port == TimeTail) {
00404                 Port->TimePrev->TimeNext = NULL;
00405                 TimeTail = Port->TimePrev;
00406         } else {
00407                 Port->TimePrev->TimeNext = Port->TimeNext;
00408                 Port->TimeNext->TimePrev = Port->TimePrev;
00409         }
00410         Port->TimeNext = NULL;
00411         Port->TimePrev = NULL;
00412 
00413         /* find the entry in the ports list */
00414         Top = Pair->NumPorts-1;
00415         Bottom = 0;
00416         Middle = Bottom + ((Top-Bottom)/2);
00417         
00418         while (1) {     
00419                 if (Pair->Ports[Middle] == Port) {
00420                         break;
00421                 }
00422                 
00423                 if ( (Port->Port1 < Pair->Ports[Middle]->Port1) || ( (Port->Port1 == Pair->Ports[Middle]->Port1) && (Port->Port2 < Pair->Ports[Middle]->Port2)) ){
00424                         if (Top == Bottom) {
00425                                 PRINTERROR("Error: Port not found in parent\n");
00426                                 return FALSE;
00427                         }
00428                         
00429                         Top = Middle;
00430                         Middle = Bottom + ((Top-Bottom)/2);
00431                 } else {
00432                         if (Top == Bottom) {
00433                                 printf("Error: Port not found in parent\n");
00434                                 return FALSE;
00435                         }
00436                         
00437                         Bottom = Middle + 1;
00438                         Middle = Bottom + ((Top-Bottom)/2);
00439                 }
00440         }
00441         
00442         /* remove this port from the ports list */
00443         memmove(&Pair->Ports[Middle], &Pair->Ports[Middle+1], sizeof(PP*)*(Pair->NumPorts - Middle - 1));
00444         Pair->NumPorts--;
00445         Pair->Ports[Pair->NumPorts] = NULL;
00446         FREE(Port->Stream0);
00447         FREE(Port->Stream1);
00448         free(Port);
00449         Port = NULL;
00450         
00451         /* if the pair is empty, remove it as well */
00452         if (Pair->NumPorts > 0) return TRUE;
00453         
00454         /* find this pair in the pairs list */
00455         Top = Bin->NumIPs - 1;
00456         Bottom = 0;
00457         Middle = Bottom + ((Top-Bottom)/2);
00458         
00459         while (1) {
00460                 if (Bin->Pairs[Middle] == Pair) {
00461                         break;
00462                 }
00463                 
00464                 if ( (Pair->IP1 < Bin->Pairs[Middle]->IP1) || ( (Pair->IP1 == Bin->Pairs[Middle]->IP1) && (Pair->IP2 < Bin->Pairs[Middle]->IP2)) ) {
00465                         if (Top == Bottom) {
00466                                 PRINTERROR("Error: Pair not found in parent\n");
00467                                 return FALSE;
00468                         }
00469                         
00470                         Top = Middle;
00471                         Middle = Bottom + ((Top-Bottom)/2);
00472                 } else {
00473                         if (Top == Bottom) {
00474                                 PRINTERROR("Error: Pair not found in parent\n");
00475                                 return FALSE;
00476                         }
00477                         
00478                         Bottom = Middle + 1;
00479                         Middle = Bottom + ((Top-Bottom)/2);
00480                 }
00481         }
00482         
00483         /* remove this pair from the bin */
00484         memmove(&Bin->Pairs[Middle], &Bin->Pairs[Middle+1], sizeof(IPP*)*(Bin->NumIPs-Middle-1));
00485         Bin->NumIPs--;
00486         Bin->Pairs[Bin->NumIPs] = NULL;
00487         
00488         Hash = GetHash(Pair->IP1, Pair->IP2);
00489         
00490         free(Pair->Ports);
00491         Pair->Ports = NULL;
00492         free(Pair);
00493         Pair = NULL;    
00494         
00495         /* if the bin is empty, remove it */
00496         if (Bin->NumIPs>0) return TRUE;
00497         
00498         free(Bin->Pairs);
00499         Bin->Pairs = NULL;
00500         free(Sessions[Hash]);
00501         Sessions[Hash] = NULL;
00502         
00503         return TRUE;
00504 }
00505 
00506 
00510 PP* FindPortPair(unsigned short Port1, unsigned short Port2, IPP* Pair, long int Now)
00511 {
00512         int     i;
00513         PP*     Port;
00514         int     Top, Bottom, Middle;
00515         char    Message[1024];
00516         
00517         DEBUGPATH;
00518 
00519         if (!Pair->Ports) {
00520                 DBG( PRINTERROR1("First Port Pair in this bin with sessionID %u\n", SessionCount) );
00521                 Pair->Ports = calloc(sizeof(PP*), PORT_START+2);
00522                 if (!Pair->Ports) {
00523                         printf("Out of memory\n");
00524                         return NULL;
00525                 }
00526                 
00527                 Pair->NumAllocated = PORT_START;
00528                 Pair->NumPorts = 1;
00529                 Pair->Ports[0] = calloc(sizeof(PP), 1);
00530                 
00531                 Port = Pair->Ports[0];
00532 
00533                 Port->Port1 = Port1;
00534                 Port->Port2 = Port2;            
00535                 Port->Parent = Pair;
00536                 Port->LastTime = Now;
00537                 Port->FirstTime = Now;
00538                 if (Port->SessionID) {
00539                         printf("SessionID was not 0\n");
00540                 }
00541                 Port->SessionID = SessionCount;
00542                 //DBG( PRINTERROR1("Filling session %d's struct with 0s...\n", Port->SessionID) );
00543                 //bzero(&(Port->Seqs), sizeof(struct tcp_stream_buffer));
00544                                 
00545                 SessionCount++;
00546                 DBG( PRINT1("There are %i sessions\n", SessionCount) );
00547                 AddToTime(Port);
00548 
00549                 if (Globals.logSession_StartEnd || Globals.logSession_All) {
00550                         snprintf(Message, 1024, 
00551                                  "Start %4x %d.%d.%d.%d:%d->%d.%d.%d.%d:%d dir:%d pcount:%d\n",
00552                                  Port->SessionID, IP_BYTES(Pair->IP1), Port->Port1,
00553                                  IP_BYTES(Pair->IP2), Port->Port2,
00554                                  //(TData->Header->syn ? 's' : '.'), (TData->Header->ack ? 'a' : '.'),
00555                                  Port->Direction, Port->TCPCount);
00556                         LogMessage(Message, &(Globals.logSessionFile));
00557                 }
00558 
00559                 /* Tell everyone this session exists */
00560                 CallCreateFuncs(Port);
00561                 
00562                 return Port;
00563         }
00564         
00565         /* Binary search for the port */
00566         Top = Pair->NumPorts-1;
00567         Bottom = 0;
00568         Middle = Bottom + ((Top-Bottom)/2);
00569         
00570         do {
00571                 if (Middle>Pair->NumAllocated) {
00572                         PRINTERROR("Tree is corrupted\n");
00573                         exit(1);
00574                 }
00575                 
00576                 Port = Pair->Ports[Middle];
00577                 if (!Port) {
00578                         PRINTERROR1("Error: Pointer was NULL Port %i\n", Middle);
00579                         return NULL;
00580                 }
00581                 
00582                 if ( (Port->Port1 == Port1) && (Port->Port2 == Port2) ) {
00583                         //DBG( PRINTERROR1("Found Port in Slot %i\n", Middle) );
00584                         Port->LastTime = Now;
00585                         UpdateTime(Port);
00586                         return Port;
00587                 }
00588                 
00589                 if ( (Port1 < Port->Port1) || ( (Port1 == Port->Port1) && (Port2 < Port->Port2) ) ) {
00590                         if (Top == Bottom)
00591                                 break;
00592                         
00593                         Top = Middle;
00594                         Middle = Bottom + ((Top-Bottom)/2);
00595                 } else {
00596                         if (Top == Bottom)
00597                                 break;
00598                         
00599                         Bottom = Middle + 1;
00600                         Middle = Bottom + ((Top-Bottom)/2);
00601                 }
00602         } while(1);
00603         
00604         DBG( PRINTERROR1("Creating new port with sessionID %u\n", SessionCount) );
00605 
00606         if (Pair->NumPorts == Pair->NumAllocated) {
00607                 /* allocate some more ports */
00608                 Pair->Ports = realloc(Pair->Ports, sizeof(PP*)*(Pair->NumAllocated+PORT_GROW+2));
00609                 if (!Pair->Ports) {
00610                         PRINTERROR("realloc failed\n");
00611                         exit(1);
00612                 }
00613         
00614                 /* Null out the new pointers */
00615                 for (i = Pair->NumPorts; i < (Pair->NumAllocated+PORT_GROW+1); i++) {
00616                         Pair->Ports[i] = NULL;
00617                 }
00618         
00619                 Pair->NumAllocated += PORT_GROW;
00620         }
00621         
00622         if ((Port1 > Port->Port1) || ( (Port1 == Port->Port1) && (Port2 > Port->Port2) ) )
00623                 Middle++;
00624         
00625         memmove(&Pair->Ports[Middle+1], &Pair->Ports[Middle], sizeof(PP*)*(Pair->NumPorts-Middle));
00626         
00627         Pair->Ports[Middle] = calloc(sizeof(PP),1);
00628         Port = Pair->Ports[Middle];
00629         Pair->NumPorts++;
00630 
00631         Port->Port1 = Port1;
00632         Port->Port2 = Port2;    
00633         Port->Parent = Pair;
00634         Port->LastTime = Now;
00635         Port->FirstTime = Now;
00636         if (Port->SessionID) {
00637                 PRINTERROR("SessionID was not NULL\n");
00638         }
00639         Port->SessionID = SessionCount;
00640 
00641 
00642         if (Globals.logSession_StartEnd) {
00643                 printf(Message, 1024, 
00644                        "Start %4x %d.%d.%d.%d:%d->%d.%d.%d.%d:%d dir:%d pcount:%d\n", 
00645                        Port->SessionID,
00646 #ifdef HLBR_LITTLE_ENDIAN
00647                        (Pair->IP1 & 0x000000ff), (Pair->IP1 & 0x0000ff00)>>8, (Pair->IP1 & 0x00ff0000)>>16, Pair->IP1>>24, Port->Port1,
00648                        (Pair->IP2 & 0x000000ff), (Pair->IP2 & 0x0000ff00)>>8, (Pair->IP2 & 0x00ff0000)>>16, Pair->IP2>>24, Port->Port2,
00649 #else
00650                        Pair->IP1>>24, (Pair->IP1 & 0x00ff0000)>>16, (Pair->IP1 & 0x0000ff00)>>8, (Pair->IP1 & 0x000000ff), Port->Port1, 
00651                        Pair->IP2>>24, (Pair->IP2 & 0x00ff0000)>>16, (Pair->IP2 & 0x0000ff00)>>8, (Pair->IP2 & 0x000000ff), Port->Port2, 
00652 #endif
00653                        //(TData->Header->syn ? 's' : '.'), (TData->Header->ack ? 'a' : '.'),
00654                        Port->Direction, Port->TCPCount);
00655                 LogMessage(Message, &(Globals.logSessionFile));
00656         }
00657 
00658         AddToTime(Port);
00659         SessionCount++;
00660         DBG( PRINT1("There are %i sessions\n", SessionCount) );
00661 
00662         /* Tell everyone this session exists */
00663         CallCreateFuncs(Port);
00664         
00665         return Port;
00666 }
00667 
00668 
00677 int TimeoutSessions(long int Now)
00678 {
00679         PP*     TimeNext;
00680         
00681         DEBUGPATH;
00682 
00683         while (TimeHead && (TimeHead->LastTime + SESSION_FORCE_TIMEOUT < Now)) {
00684                 TimeNext = TimeHead->TimeNext;  
00685                 RemovePort(TimeHead);
00686                 TimeHead = TimeNext;
00687         }
00688         
00689 /* Checks if there are pending sessions with just one packet waiting;
00690    this probably is the last packet in a TCP session, so let it go */
00691         while (TimeHead && (TimeHead->LastTime + (SESSION_FORCE_TIMEOUT/10) < Now)) {
00692                 //TODO
00693                 //if (TimeHead->Stream0 != NULL) {
00694                 //      if (TimeHead->Stream0->NumPieces == 1)
00695                 //              TCPSessionUnblock(TimeHead->Stream0
00696                 TimeNext = TimeHead->TimeNext;  
00697                 RemovePort(TimeHead);
00698                 TimeHead = TimeNext;
00699         }
00700 
00701         return TRUE;
00702 }
00703 
00704 
00713 int AssignSessionTCP(int PacketSlot, void* Data)
00714 {
00715         IPData*         IData;
00716         TCPData*        TData;
00717         unsigned int    IP1,IP2;
00718         unsigned short  Port1, Port2;
00719         IPP*            Pair;
00720         PP*             Port;
00721         struct tcp_stream*      Stream;
00722         char            reassemble = 0; // try to remount this packet?
00723         char            outoforder = 0; // packet isn't in the expected order?
00724 
00725         DEBUGPATH;
00726 
00727         GetDataByID(PacketSlot, IPDecoderID, (void**)&IData);
00728         if (!IData) {
00729                 PRINTPKTERROR(PacketSlot, IData, NULL, FALSE);
00730                 PRINTERROR("This was supposed to be a TCP packet\n");
00731                 return FALSE;
00732         }
00733 
00734         TData = (TCPData*)Data;
00735         if (!TData) {
00736                 PRINTPKTERROR(PacketSlot, IData, TData, FALSE);
00737                 PRINTERROR("TCP Data was NULL\n");
00738                 return FALSE;
00739         }
00740 
00741         // Assigns IP1 & IP2: IP1 is the lesser of the src & dst IPs
00742         if (IData->Header->saddr < IData->Header->daddr) {
00743                 IP1 = IData->Header->saddr;
00744                 IP2 = IData->Header->daddr;
00745                 Port1 = ntohs(TData->Header->source);
00746                 Port2 = ntohs(TData->Header->dest);
00747         } else {
00748                 IP1 = IData->Header->daddr;
00749                 IP2 = IData->Header->saddr;
00750                 Port1 = ntohs(TData->Header->dest);
00751                 Port2 = ntohs(TData->Header->source);
00752         }
00753 
00754         /* Finds a pair of IPs in the IP Pair Bin */
00755         Pair = FindIPPair(IP1, IP2);
00756         if (!Pair) {
00757                 PRINTPKTERROR(PacketSlot, IData, TData, FALSE);
00758                 PRINTERROR4("Failed to assign session pair for %d.%d.%d.%d:%d <-> %d.%d.%d.%d:%d\n",
00759                            IP_BYTES(IP1), Port1, IP_BYTES(IP2), Port2);
00760                 return FALSE;
00761         }
00762         /* Finds a session (a pair of ports in the pair of IPs) in the Bin */
00763         Port = FindPortPair(Port1, Port2, Pair, Globals.Packets[PacketSlot].tv.tv_sec);
00764         if (!Port) {
00765                 PRINTPKTERROR(PacketSlot, IData, TData, FALSE);
00766                 PRINTSESERROR(Port, FALSE);
00767                 PRINTERROR4("Failed to assign session port for %d.%d.%d.%d:%d <-> %d.%d.%d.%d:%d\n",
00768                            IP_BYTES(IP1), Port1, IP_BYTES(IP2), Port2);
00769                 return FALSE;
00770         }
00771 
00772         /* Discover the direction and state of this session */
00773 
00774         if ( (Port->ServerState == TCP_STATE_NEW) && (Port->ClientState == TCP_STATE_NEW) ) {
00775                 /* We don't know what direction or state this is yet.
00776                  *
00777                  * If it starts with a SYN:
00778                  *   Sender is Client, State is SYN
00779                  * If it starts with a SYN|ACK:
00780                  *   Sender is Server, State is SYN|ACK
00781                  * If it starts with a FIN:
00782                  *   Sender is Client, State is DATA, FIN Set for Client
00783                  * If it starts with a RST:
00784                  *   Sender is Server, State is RESET
00785                  * If it starts with a normal ACK:
00786                  *   Sender is Client, State is DATA
00787                  */
00788                 
00789                 if (TData->Header->syn && !(TData->Header->ack || TData->Header->fin || TData->Header->rst) ) {
00790                         DBGDIR( printf("Started with a SYN\n") );
00791 
00792                         if (IP1 == IData->Header->saddr) {
00793                                 Port->Direction = SESSION_IP2_SERVER;
00794                         } else {
00795                                 Port->Direction = SESSION_IP1_SERVER;
00796                         }
00797                         
00798                         Port->ClientState = TCP_STATE_SYN;
00799                         Port->ClientSeq = ntohl(TData->Header->seq);
00800                         Port->ClientAck = ntohl(TData->Header->ack_seq);
00801                 } else if (TData->Header->syn && TData->Header->ack && !(TData->Header->fin || TData->Header->rst) ) {
00802                         DBGDIR( printf("Started with a SYN|ACK\n") );
00803 
00804                         if (IP1 == IData->Header->saddr) {
00805                                 Port->Direction = SESSION_IP1_SERVER;
00806                         } else {
00807                                 Port->Direction = SESSION_IP2_SERVER;
00808                         }
00809                         
00810                         Port->ServerState = TCP_STATE_SYNACK;
00811                         Port->ServerSeq = ntohl(TData->Header->seq);
00812                         Port->ServerAck = ntohl(TData->Header->ack_seq);
00813                 } else if (TData->Header->rst) {
00814                         DBGDIR( printf("Started with a RST\n") );
00815 
00816                         if (IP1 == IData->Header->saddr){
00817                                 Port->Direction = SESSION_IP1_SERVER;
00818                         }else{
00819                                 Port->Direction = SESSION_IP2_SERVER;
00820                         }
00821                         
00822                         Port->ServerState = TCP_STATE_RESET;
00823                         Port->ServerSeq = ntohl(TData->Header->seq);
00824                         Port->ServerAck = ntohl(TData->Header->ack_seq);
00825                 } else if (TData->Header->fin) {
00826                         DBGDIR( printf("Started with a FIN\n") );
00827 
00828                         if (IP1 == IData->Header->saddr) {
00829                                 Port->Direction = SESSION_IP2_SERVER;
00830                         } else {
00831                                 Port->Direction = SESSION_IP1_SERVER;
00832                         }
00833                         
00834                         Port->ClientState = TCP_STATE_DATA;
00835                         Port->ClientSeq = ntohl(TData->Header->seq);
00836                         Port->ClientAck = ntohl(TData->Header->ack_seq);
00837                 } else {
00838                         /* This would happen only when HLBR is started when 
00839                            there are already active TCP sessions ? */
00840 
00841                         DBGDIR( PRINT("Startup in the middle of a session\n") );
00842 
00843                         if (IP1 == IData->Header->saddr) {
00844                                 Port->Direction = SESSION_IP2_SERVER;
00845                         }else{
00846                                 Port->Direction = SESSION_IP1_SERVER;
00847                         }
00848                         
00849                         Port->ClientState = TCP_STATE_DATA;
00850                         Port->ServerState = TCP_STATE_DATA;
00851                         Port->ClientSeq = ntohl(TData->Header->seq);
00852                         Port->ClientAck = ntohl(TData->Header->ack_seq);
00853                         /* It's useless to try to remount anything if we're not
00854                            catching the initial data */
00855                         Port->noreassemble = 1;
00856                 }
00857 
00858         } else {
00859                 /* We already had a state for this session. Let's just see
00860                    if it changed. */
00861 
00862                 /* see if this came from the client or the server */
00863                 if (
00864                         ((Port->Direction == SESSION_IP1_SERVER) && (IData->Header->saddr == IP1)) ||
00865                         ((Port->Direction == SESSION_IP2_SERVER) && (IData->Header->saddr == IP2))
00866                         ) {
00867                         
00868                         DBGDIR( PRINT("This packet came from the server\n") );
00869                         
00870                         if ( (Port->ClientState == TCP_STATE_FIN) && (Port->ServerState == TCP_STATE_FIN) && !(TData->Header->fin || TData->Header->syn || TData->Header->rst) ) {
00871                                 DBGDIR( PRINT("Final ACK\n") );
00872 
00873                                 if ( (Port->ClientSeq + 1) != ntohl(TData->Header->ack_seq)) {
00874                                         //printf("Seq didn't match (final ACK after FIN from client)\n");
00875                                 }
00876                                 Port->ClientState = TCP_STATE_LATE;
00877                                 Port->ServerState = TCP_STATE_LATE;
00878                         } else if (TData->Header->syn && TData->Header->ack  && !(TData->Header->rst || TData->Header->fin) ) {
00879 
00880                                 /* syn|ack from the server */
00881 
00882                                 if ( (Port->ServerState == TCP_STATE_NEW) && (Port->ClientState == TCP_STATE_SYN)) {
00883                                         DBGDIR( PRINT("Normal SYN|ACK\n") );
00884 
00885                                         Port->ServerState = TCP_STATE_SYNACK;
00886                                         Port->ServerSeq = ntohl(TData->Header->seq);
00887                                         Port->ServerAck = ntohl(TData->Header->ack_seq);
00888                                         
00889                                         if (Port->ServerAck != (Port->ClientSeq+1) ){
00890                                                 DBG( PRINT("SYN|ACK didn't match\n") );
00891                                                 Port->Error = TRUE;
00892                                         }
00893                                 } else if (Port->ServerState == TCP_STATE_SYNACK) {
00894                                         DBGDIR( PRINT("Resend of the SYN|ACK\n") );
00895                                         if ( (Port->ServerSeq != ntohl(TData->Header->seq)) || (Port->ServerAck != ntohl(TData->Header->ack_seq)) ) {
00896                                                 DBG( PRINT("Reset SYN|ACK didn't match original\n") );
00897                                                 Port->Error = TRUE;
00898                                         }
00899                                 }
00900                         } else if (TData->Header->rst) {
00901                                 DBGDIR( PRINT("Server sent a RESET\n") );
00902 
00903                                 Port->ServerState = TCP_STATE_RESET;
00904                                 Port->ServerSeq = ntohl(TData->Header->seq);
00905                                 Port->ServerAck = ntohl(TData->Header->ack_seq);
00906                         } else if (TData->Header->fin) {
00907                                 DBGDIR( printf("Server sent a FIN\n") );
00908 
00909                                 Port->ServerState=TCP_STATE_FIN;
00910                                 Port->ServerSeq=ntohl(TData->Header->seq);
00911                                 Port->ServerAck=ntohl(TData->Header->ack_seq);
00912                                 Port->ServerFin=1;
00913                         } else {
00914                                 if ( (Port->ServerState == TCP_STATE_SYNACK) && (Port->ClientState = TCP_STATE_DATA) ){
00915                                         DBGDIR( PRINT("First Data packet from server\n") );
00916 
00917                                         Port->ServerState = TCP_STATE_DATA;
00918                                         Port->ServerSeq = ntohl(TData->Header->seq);
00919                                         Port->ServerAck = ntohl(TData->Header->ack_seq);
00920                                         reassemble = 1;
00921                                 } else if (Port->ServerState == TCP_STATE_DATA) {
00922                                         DBGDIR( printf("Normal Data from Server\n") );
00923 
00924                                         Port->ServerSeq = ntohl(TData->Header->seq);
00925                                         Port->ServerAck = ntohl(TData->Header->ack_seq);
00926                                 } else {
00927                                         DBGDIR( PRINT("Error: This packet was unexpected (1)\n") );
00928                                         Port->Error = TRUE;
00929                                 }
00930                         }
00931                 } else {
00932 
00933                         DBGDIR( PRINT("This packet came from the client - ") );
00934                         PrintPacketSummary(stdout, PacketSlot, IData, TData, TRUE);
00935                         
00936                         if ( (Port->ClientState == TCP_STATE_FIN) && (Port->ServerState == TCP_STATE_FIN) && !(TData->Header->fin || TData->Header->syn || TData->Header->rst) ) {
00937                                 DBGDIR( PRINT("Final ACK\n") );
00938 
00939                                 if ( (Port->ServerSeq+1) != ntohl(TData->Header->ack_seq)) {
00940                                         //printf("Seq didn't match (final ACK after FIN from server)\n");
00941                                 }
00942                                 Port->ClientState = TCP_STATE_LATE;
00943                                 Port->ServerState = TCP_STATE_LATE;
00944                         } else if (!(TData->Header->fin || TData->Header->rst) ) {
00945                                 if ( (Port->ClientState == TCP_STATE_SYN) && (Port->ServerState == TCP_STATE_SYNACK) ){
00946                                         /* Acking the SYN|ACK */
00947                                         DBGDIR( PRINT("Normal SYN|ACK ACK\n") );
00948 
00949                                         Port->ClientState = TCP_STATE_DATA;
00950                                         Port->ClientSeq = ntohl(TData->Header->seq);
00951                                         Port->ClientAck = ntohl(TData->Header->ack_seq);
00952                                         if (TData->DataLen > 0) {
00953                                                 DBG( PRINT("syn|ack ack has payload?\n") );
00954                                                 reassemble = 1;
00955                                         }
00956                                 } else if (Port->ClientState == TCP_STATE_DATA) {
00957                                         DBGDIR( PRINT("Normal Client Traffic\n") );
00958 
00959                                         Port->ClientSeq = ntohl(TData->Header->seq);
00960                                         Port->ClientAck = ntohl(TData->Header->ack_seq);
00961                                         reassemble = 1;
00962                                 } else {
00963                                         DBGDIR( PRINT2("Error:  This packet was unexpected (2) SrvState:%d CliState:%d\n", Port->ServerState, Port->ClientState) );
00964                                 }
00965                         } else if (TData->Header->rst) {
00966                                 DBGDIR( PRINT("Client sent a RST\n") );
00967 
00968                                 Port->ClientState = TCP_STATE_RESET;
00969                         }else if (TData->Header->fin) {
00970                                 DBGDIR( PRINT("Client sent a FIN\n") );
00971 
00972                                 Port->ClientState = TCP_STATE_FIN;
00973                         } else {
00974                                 DBGDIR( PRINT("Error:  This packet was unexpected (3)\n") );
00975                         }
00976                 }
00977         }
00978 
00979 
00980         //RemountTCPStream(PacketSlot, Port, TData);
00981                 
00982         /* update stats and pointers */
00983         Port->TCPCount++;
00984         Globals.Packets[PacketSlot].Stream = Port;
00985 
00986 
00987         /* Does the magic
00988          * Reassemblies the payload in the big buffer 
00989          *  & call tests upon it 
00990          */
00991 
00992         // Will this packet be reassembled in the TCP stream?
00993         DBG( PRINT2("Reassemble:%d noreassemble:%d\n", reassemble, Port->noreassemble) );
00994         if (reassemble && !(Port->noreassemble)) {
00995                 if ((Port->Direction == SESSION_IP1_SERVER && IData->Header->saddr == IP2) ||
00996                     (Port->Direction == SESSION_IP2_SERVER && IData->Header->saddr == IP1)) {
00997                         if (Port->Stream0 == NULL) {
00998                                 Port->Stream0 = MALLOC(sizeof(struct tcp_stream));
00999                                 bzero(Port->Stream0, sizeof(struct tcp_stream));
01000                         }
01001                         Stream = Port->Stream0;
01002                 } else {
01003                         if (Port->Stream1 == NULL) {
01004                                 Port->Stream1 = MALLOC(sizeof(struct tcp_stream));
01005                                 bzero(Port->Stream1, sizeof(struct tcp_stream));
01006                         }
01007                         Stream = Port->Stream1;
01008                 }
01009 
01010 #define PIECE_SIZE(p)           (p.piece_end - p.piece_start + 1)
01011 #define PAYLOADS_SIZE(s)        (s->LastSeq - s->TopSeq + 1)
01012                 /* This packet goes right after the others in the Payloads 
01013                    buffer, or must we queue it? */
01014                 if (TData->Header->seq == Stream->LastSeq + 1) { // Goes to Payloads
01015                         // First block in the buffer?
01016                         if (Stream->NumPieces == 0) {
01017                                 Stream->Pieces[0].piece_start = TData->Header->seq;
01018                                 Stream->Pieces[0].piece_end = TData->Header->seq + TData->DataLen - 1;
01019                                 Stream->Pieces[0].PacketSlot = PacketSlot;
01020                                 Stream->TopSeq = Stream->Pieces[0].piece_start;
01021                                 Stream->LastSeq = Stream->Pieces[0].piece_end;
01022                                 memcpy(&(Stream->Payloads[0]), TData->Data, TData->DataLen);
01023                                 BlockPacket(PacketSlot);
01024                                 Stream->NumPieces++;
01025                         } else {
01026                                 if (Stream->NumPieces == TCP_PAYLOAD_PIECES_SIZE) {
01027                                         // Pieces is full so make room to one more...
01028                                         UnblockPacket(Stream->Pieces[0].PacketSlot);
01029                                         memmove(&(Stream->Payloads[0]), 
01030                                                 &(Stream->Payloads[ PIECE_SIZE(Stream->Pieces[0]) ]),
01031                                                 PAYLOADS_SIZE(Stream) - PIECE_SIZE(Stream->Pieces[0]) );
01032                                         memmove(&(Stream->Pieces[0]), &(Stream->Pieces[1]),
01033                                                 (--Stream->NumPieces) * sizeof(struct tcp_stream_piece) );
01034                                         Stream->TopSeq = Stream->Pieces[0].piece_start;
01035                                 }
01036                                 // And now, put it in Payloads/Pieces, at the end
01037                                 memcpy(&(Stream->Payloads[PAYLOADS_SIZE(Stream)]),
01038                                        TData->Data, TData->DataLen);
01039                                 Stream->LastSeq = TData->Header->seq + TData->DataLen - 1;
01040                                 Stream->Pieces[Stream->NumPieces].piece_start = TData->Header->seq;
01041                                 Stream->Pieces[Stream->NumPieces].piece_end = Stream->LastSeq;
01042                                 Stream->Pieces[Stream->NumPieces].PacketSlot = PacketSlot;
01043                                 Stream->NumPieces++;
01044                                 
01045                         }
01046                 } else {
01047 // queue it... check for a place for it in the queue
01048 // (check the boundaries of each piece for teardrop attacks, of course)
01049 // and then queue and block it.
01050                 }
01051 
01052                 // Now try to unqueue as many packets as possible
01053 // now, finally, apply the test on Payloads
01054                 printf("O buffer tem:\n");
01055                 for (IP1=0; IP1<PAYLOADS_SIZE(Stream); IP1++)
01056                         if (Stream->Payloads[IP1] >= 32 && Stream->Payloads[IP1] <= 126)
01057                                 putchar(Stream->Payloads[IP1]);
01058                         else
01059                                 putchar(46);
01060                 putchar(10);
01061                 //PrintSessionBuffer(stdout, Port);
01062         }
01063         
01064 
01065         TimeoutSessions(Globals.Packets[PacketSlot].tv.tv_sec);
01066 
01067         return TRUE;
01068 }
01069 
01077 int InitSession()
01078 {
01079         DEBUGPATH;
01080 
01081         bzero(Sessions, sizeof(IPB*)*65536);
01082         TimeHead = NULL;
01083         CreateFuncs = NULL;
01084         DestroyFuncs = NULL;
01085 
01086         IPDecoderID = GetDecoderByName("IP");
01087         TCPDecoderID = GetDecoderByName("TCP");
01088 
01089         return TRUE;
01090 }
01091 
01092 
01093 
01094 #if 0
01095 
01100 int RemountTCPStream(int PacketSlot, PP* Port, TCPData* TData)
01101 {
01102 //      TCPData*        TData = 0;
01103         int             i;
01104 
01105         DEBUGPATH;
01106         DBG( PRINT4("RemountTCPStream: Session:%d TCPCount:%d [%d,%d]\n",
01107                         Port->SessionID, Port->TCPCount,
01108                         TData->Header->seq, TData->Header->ack_seq) );
01109 #ifdef DEBUG000
01110         // dumping contents of this session's buffers...
01111         PRINTERROR3("   --- TCP stream buffer ---\n     %d pieces, TopSeq: %d, LastSeq: %d\n",
01112                     Port->Seqs.num_pieces, Port->Seqs.TopSeq, Port->Seqs.LastSeq);
01113         for (i = 0; i < Port->Seqs.num_pieces; i++)
01114                 PRINTERROR4("   [%d] %d -> %d           PacketSlot:%d\n",
01115                            i, Port->Seqs.pieces[i].piece_start,
01116                            Port->Seqs.pieces[i].piece_end,
01117                            Port->Seqs.pieces[i].PacketSlot);
01118 #endif  /* DEBUG */
01119         
01120         if (Port->Seqs.num_pieces == TCP_QUEUE_SIZE)
01121                 return FALSE;
01122 
01123         /*if (!GetDataByID(PacketSlot, TCPDecoderID, (void**)&TData)) {
01124                 PrintPacketSummary(stderr, PacketSlot, NULL, TData, FALSE);
01125                 PRINTERROR("This was supposed to be a TCP packet\n");
01126                 return FALSE;
01127                 }*/
01128 
01129         // packets with no payload aren't queued
01130         if (TData->DataLen == 0)
01131                 return TRUE;
01132 
01133         // this is the very first packet of this session
01134         if (Port->Seqs.LastSeq == 0 && Port->Seqs.TopSeq == 0) {
01135                 DBG( PRINTERROR2("Very first packet of session %d with payload (# of packets: %d)\n", Port->SessionID, Port->TCPCount) );
01136                 Port->Seqs.TopSeq = TData->Header->seq - 1;
01137                 Port->Seqs.LastSeq = TData->Header->seq - 1;
01138         }
01139 
01140         // new packet fits right after first bunch of packets in buffer
01141         if (TData->Header->seq == Port->Seqs.LastSeq + 1) {
01142                 if (Globals.logSession_All)
01143                         PRINT2("Session %d: packet %d fits right at buffer's end\n", Port->SessionID, PacketSlot);
01144 
01145                 if (Port->Seqs.LastSeq - Port->Seqs.TopSeq + 1 >= TCP_CACHE_SIZE) {
01146                         PRINTPKTERROR(-1, NULL, TData, FALSE);
01147                         PRINTSESERROR(Port, FALSE);
01148                         PRINTERROR("out of space in TCP cache\n");
01149                         return FALSE;
01150                 }
01151                 memcpy(TData->Data, 
01152                        &(Port->Seqs.buffer) + (Port->Seqs.LastSeq - Port->Seqs.TopSeq), 
01153                        TData->DataLen);
01154 
01155                 // finds position for the packet in pieces[]
01156                 for (i = 0; Port->Seqs.pieces[i].piece_end < Port->Seqs.LastSeq && i < TCP_QUEUE_SIZE; i++);
01157                 if (i == TCP_QUEUE_SIZE) {
01158                         PRINTERROR("pieces[] out of space?\n");
01159                         return FALSE;
01160                 }
01161                 DBG( PRINTERROR1("\tUsing pieces[%d]...", i) );
01162 
01163                 // move other pieces[] forward, to make space
01164                 if (i < TCP_QUEUE_SIZE - 1) {
01165                         DBG( PRINTERROR("\n\tNeed to move other pieces[] forward, to make space\n") );
01166                         memmove(&(Port->Seqs.pieces[i+1]), &(Port->Seqs.pieces[i]), 
01167                                 sizeof(struct tcp_stream_piece)*(TCP_QUEUE_SIZE-i));
01168                 }
01169                 Port->Seqs.pieces[i].piece_start = TData->Header->seq;
01170                 Port->Seqs.pieces[i].piece_end = TData->Header->seq + TData->DataLen-1;
01171                 Port->Seqs.pieces[i].PacketSlot = PacketSlot;
01172                 Port->Seqs.num_pieces++;
01173                 Port->Seqs.LastSeq = TData->Header->seq + TData->DataLen - 1;
01174                 DBG( PRINTERROR6(" Used: %d->%d, ps:%d, num_pieces:%d, Top/Last:%d/%d\n",
01175                                 Port->Seqs.pieces[i].piece_start,
01176                                 Port->Seqs.pieces[i].piece_end,
01177                                 Port->Seqs.pieces[i].PacketSlot,
01178                                 Port->Seqs.num_pieces,
01179                                 Port->Seqs.TopSeq, Port->Seqs.LastSeq) );
01180 
01181                 // try to add queued packets to the buffer
01182                 // try multiple times, because after a packet is popped out,
01183                 // maybe there's room for another one
01184                 while (TCPStream_Unqueue(Port));
01185         } else {
01186                 // This packet doesn't follow the previous one. So we queue it
01187                 if (Globals.logSession_All)
01188                         PRINT2("Session %d: packet %d doesn't fits at buffer's end, queuing it\n", Port->SessionID, PacketSlot);
01189 
01190                 DBG( PRINTPKTERROR(-1, NULL, TData, FALSE) );
01191                 DBG( PRINTSESERROR(Port, FALSE) );
01192                 DBG( PRINTERROR2("packet doesn't follows previous one (LastSeq:%d this packet's seq:%d)\n", Port->Seqs.LastSeq, TData->Header->seq) );
01193                 if (Port->Seqs.queue_size < TCP_QUEUE_SIZE) 
01194                         Port->Seqs.queue[i++] = PacketSlot;
01195                 BlockPacket(PacketSlot);
01196         }
01197 
01198         return TRUE;
01199 }
01200 
01205 int TCPStream_Unqueue(PP* Port)
01206 {
01207         TCPData*        TData;
01208         int i;
01209 
01210         DEBUGPATH;
01211 
01212         // Nothing to unqueue
01213         if (!Port->Seqs.queue_size)
01214                 return FALSE;
01215 
01216         // Even if there's something to unqueue, pieces[] can't hold it
01217         if (Port->Seqs.queue_size == TCP_QUEUE_SIZE)
01218                 return FALSE;
01219 
01220         for (i = 0; i < Port->Seqs.queue_size; i++) {
01221                 GetDataByID(Port->Seqs.queue[i], TCPDecoderID, (void**)&TData);
01222                 if (!TData) {
01223                         PrintPacketSummary(stderr, Port->Seqs.queue[i], NULL, TData, FALSE);
01224                         PRINTERROR("This was supposed to be a TCP packet\n");
01225                         return FALSE;
01226                 }
01227 
01228                 // put this piece after the others
01229                 if (TData->Header->seq == Port->Seqs.LastSeq + 1) {
01230                         if (TData->DataLen > (TCP_CACHE_SIZE - Port->Seqs.LastSeq - Port->Seqs.TopSeq + 1))
01231                                 // buffer can't hold the packet!
01232                                 // then just wait for another time...
01233                                 return FALSE;
01234 
01235                         memcpy(&(Port->Seqs.buffer) + Port->Seqs.LastSeq - Port->Seqs.TopSeq + 1,
01236                                TData->Data, TData->DataLen);
01237 
01238                         // add to pieces (at the end)
01239                         Port->Seqs.pieces[Port->Seqs.num_pieces].piece_start = TData->Header->seq;
01240                         Port->Seqs.pieces[Port->Seqs.num_pieces].piece_end = TData->Header->seq + TData->DataLen - 1;
01241                         Port->Seqs.pieces[Port->Seqs.num_pieces].PacketSlot = Port->Seqs.queue[i];
01242 
01243                         // unqueue it (moving subsequent records up)
01244                         if (Port->Seqs.queue_size == TCP_QUEUE_SIZE)
01245                                 Port->Seqs.queue_size--;
01246                         else
01247                                 memmove(&(Port->Seqs.queue[i]), 
01248                                         &(Port->Seqs.queue[i+1]),
01249                                         (Port->Seqs.queue_size-- - i - 1) * sizeof(int));
01250 
01251                         return TRUE;
01252                         
01253                 // put this piece before the others
01254                 } else if (TData->Header->seq + TData->DataLen - 1 ==
01255                            Port->Seqs.TopSeq) {
01256                         if (TData->DataLen > (TCP_CACHE_SIZE - Port->Seqs.LastSeq - Port->Seqs.TopSeq + 1))
01257                                 // buffer can't hold the packet!
01258                                 // then just wait for another time...
01259                                 return FALSE;
01260 
01261                         // first, move down the buffer to make space...
01262                         memmove(&(Port->Seqs.buffer) + TData->DataLen,
01263                                 &(Port->Seqs.buffer),
01264                                 Port->Seqs.LastSeq - Port->Seqs.TopSeq + 1);
01265                         // ...then insert data at beginning of buffer
01266                         memcpy(&(Port->Seqs.buffer), TData->Data, TData->DataLen);
01267 
01268                         // add to pieces (at the beginning)
01269                         memmove(&(Port->Seqs.pieces[1]), &(Port->Seqs.pieces[0]),
01270                                 (Port->Seqs.num_pieces - 1) * sizeof(struct tcp_stream_buffer));
01271                         Port->Seqs.num_pieces++;
01272 
01273                         // unqueue it (moving subsequent records up)
01274                         if (Port->Seqs.queue_size == TCP_QUEUE_SIZE)
01275                                 Port->Seqs.queue_size--;
01276                         else
01277                                 memmove(&(Port->Seqs.queue[i]), 
01278                                         &(Port->Seqs.queue[i+1]),
01279                                         (Port->Seqs.queue_size-- - i - 1) * sizeof(int));
01280 
01281                         return TRUE;
01282                 } else if (
01283                         ((TData->Header->seq < Port->Seqs.LastSeq) &&
01284                          (TData->Header->seq > Port->Seqs.TopSeq)) ||
01285                         ((Port->Seqs.TopSeq > TData->Header->seq) &&
01286                          (Port->Seqs.TopSeq < TData->Header->seq + TData->DataLen - 1)) ) {
01287                         // packet boundaries overwrite! drop the packet
01288                         // (taken from action_drop.c)
01289                         Globals.Packets[Port->Seqs.queue[i]].PassRawPacket = FALSE;
01290                         if (Globals.Packets[Port->Seqs.queue[i]].Status == PACKET_STATUS_BLOCKED)
01291                                 TCPRemount_unblock(Port->Seqs.queue[i], TRUE);
01292                         return FALSE; // should really continue trying other packets in queue, but array can change after calling TCPStream_unblock
01293                 }
01294         }
01295 
01296         return FALSE;
01297 }
01298 #endif
01299 
01311 int UnblockPacket(int PacketSlot){}
01312 int TCPRemount_unblock(int PacketSlot, int thispacket)
01313 {
01314 /*
01315         PacketRec*                      p;
01316         struct tcp_stream_buffer*       seq;
01317         int                             nseq;
01318         signed char                     i, piece;
01319         int                             up;
01320         TCPData*                        TData;
01321 
01322         DEBUGPATH;
01323 
01324         p = &Globals.Packets[PacketSlot];
01325         up = PacketSlot;
01326         
01327         if (!(p->Stream)) {
01328                 DBG( PRINTERROR1("Packet %d's Stream pointer is null!\n", PacketSlot) );
01329                 return FALSE;
01330         }
01331         seq = &(p->Stream->Seqs);
01332         if (seq->num_pieces == 0) {
01333                 DBG( PRINTERROR1("Packet %d's stream doesn't have any pieces to be unblocked\n", PacketSlot) );
01334                 return FALSE;
01335         }
01336         // if there's only one piece in the buffer, it can be unblocked only
01337         // if it's the last packet in the TCP session
01338         if (seq->num_pieces == 1) {
01339                 GetDataByID(PacketSlot, TCPDecoderID, (void**)&TData);
01340                 if (TData)
01341                         if (!TData->Header->fin && !TData->Header->rst) {
01342                                 DBG( PRINTERROR1("TCP buffer for packet %d has only one packet and it isn't a FIN or RST one\n", PacketSlot) );
01343                                 return FALSE;
01344                         }
01345         }
01346         
01347         nseq = seq->pieces[0].piece_start + 1;
01348         piece = -1;
01349         for (i = 0; i < seq->num_pieces; i++)
01350                 if (seq->pieces[i].piece_start < nseq) {
01351                         nseq = seq->pieces[i].piece_start;
01352                         piece = i;
01353                 }
01354         if (piece > -1) {
01355                 up = seq->pieces[piece].PacketSlot;
01356                 // if this piece's PacketSlot is valid, finally route this poor packet
01357                 if (seq->pieces[piece].PacketSlot > -1) {
01358                         Globals.Packets[seq->pieces[piece].PacketSlot].Status = PACKET_STATUS_IDLE;
01359                         RouteAndSend(seq->pieces[piece].PacketSlot);
01360                         ReturnEmptyPacket(seq->pieces[piece].PacketSlot);
01361                 }
01362                 // remove piece from pieces array
01363                 if (piece < TCP_QUEUE_SIZE)
01364                         memmove(&(seq->pieces[piece]), 
01365                                 &(seq->pieces[piece+1]),
01366                                 (seq->num_pieces - piece - 1) * sizeof(struct tcp_stream_piece));
01367                 seq->num_pieces--;
01368         }
01369 
01370         if ((thispacket) && (PacketSlot != up)) {
01371                 for (i = 0; i < seq->num_pieces; i++)
01372                         if (seq->pieces[i].PacketSlot == PacketSlot)
01373                                 seq->pieces[i].PacketSlot = -1;
01374         }
01375 
01376         return TRUE;
01377 */
01378 }

Generated on Sat Jul 7 23:33:10 2007 for HLBR by  doxygen 1.5.2