decoders/decode_ip_defrag.c

Go to the documentation of this file.
00001 #include "decode_ip_defrag.h"
00002 #include "../packets/packet.h"
00003 #include "../engine/cache.h"
00004 #include <stdio.h>
00005 #include <stdlib.h>
00006 #include <netinet/in.h>
00007 #include <arpa/inet.h>
00008 #include <string.h>
00009 
00010 //#define DEBUG
00011 
00012 /**********************************************
00013 * Pretty much this whole thing needs to get
00014 * rewritten. I was using it as a test 
00015 * harness for the packet caching system.
00016 ***********************************************/
00017 
00018 extern GlobalVars       Globals;
00019 
00020 int                             IPDecoderID;
00021 Cache*                  FragCache;
00022 pthread_mutex_t FragMutex;
00023 int                             FragLockID;
00024 
00025 struct defrag_item{
00026         int                             begin;
00027         int                             end;
00028         int                             PacketSlot;
00029         IPData*                 idata;
00030         int                             more;
00031         char                    done;
00032 };
00033 
00034 /************************************************************************
00035 * We have to recalc the IP header checksum
00036 * taken from snort
00037 * TODO: replace with the one from the RFC
00038 *************************************************************************/
00039 unsigned short checksum(unsigned short *b1, unsigned int len1, unsigned short *b2, unsigned int len2)
00040 {
00041     unsigned int sum = 0;
00042 
00043     if(b1 != (unsigned short *)NULL) 
00044     {
00045         while(len1 > 1) 
00046         {
00047             sum += *((unsigned short *)b1 ++);
00048 
00049             if(sum & 0x80000000)
00050             {
00051                 sum = (sum & 0xffff) + (sum >> 16);
00052             }
00053 
00054             len1 -= 2;
00055         }
00056     
00057         /* we'll have problems if b2 exists and len1 is odd */
00058         if(len1)
00059         {
00060            sum += (unsigned short) * (unsigned char*) b1;
00061         }
00062     }
00063 
00064     if(b2 != (unsigned short*)NULL) 
00065     {
00066         while(len2 > 1) 
00067         {
00068             sum += *((unsigned short*)b2 ++);
00069 
00070             if(sum & 0x80000000)
00071             {
00072                 sum = (sum & 0xffff) + (sum >> 16);
00073             }
00074 
00075             len2 -= 2;
00076         }
00077 
00078         if(len2)
00079         {
00080             sum += (unsigned short) * (unsigned char*) b2;
00081         }
00082     }
00083 
00084     while(sum >> 16)
00085         sum = (sum & 0xffff) + (sum >> 16);
00086 
00087     return (unsigned short) ~sum;
00088 }
00089 
00090 
00091 /*************************************************************
00092 * Build the packet back together and push it on the pending queue
00093 * TODO: Don't assume ethernet
00094 *************************************************************/
00095 int RebuildPacket(struct defrag_item* Frags, int NumFrags){
00096         PacketRec*      newp;
00097         IPData*         idata;
00098         int                     i;
00099         int                     flags;
00100         int                     offset;
00101         int                     first_header_len;
00102         int                     offset_to_ip;
00103         int                     PacketSlot;
00104         
00105         /*stick together the packet and put it on the pending queue*/
00106         PacketSlot=GetEmptyPacket();
00107         
00108         newp=&Globals.Packets[PacketSlot];
00109         
00110         /*allocate enough to hold the packet*/
00111         newp->LargePacket=TRUE;
00112         newp->RawPacket=calloc(MAX_PACKET_SIZE,1);
00113         
00114         /*create the headers*/
00115         newp->InterfaceNum=Globals.Packets[Frags[0].PacketSlot].InterfaceNum;
00116         newp->tv=Globals.Packets[Frags[0].PacketSlot].tv;
00117         
00118         for (i=0;i<NumFrags;i++){
00119                 if (!GetDataByID(Frags[i].PacketSlot, IPDecoderID, (void**)&idata)){
00120                         printf("Failed to get IP data in slot %i\n",PacketSlot);
00121                         return FALSE;
00122                 }
00123         
00124                 flags=ntohs(idata->Header->frag_off) / 8192;
00125                 offset=ntohs(idata->Header->frag_off) & 0x1FFF;
00126                 
00127                 if (offset==0){
00128                         offset_to_ip=((int)idata->Header) - ((int)Globals.Packets[Frags[i].PacketSlot].RawPacket);
00129                         first_header_len=idata->Header->ihl*4;
00130                         newp->PacketLen=Globals.Packets[Frags[i].PacketSlot].PacketLen;
00131                         memcpy(newp->RawPacket, Globals.Packets[Frags[i].PacketSlot].RawPacket, newp->PacketLen);
00132                 }
00133         }
00134         
00135         for (i=0;i<NumFrags;i++){
00136                 if (!GetDataByID(Frags[i].PacketSlot, IPDecoderID, (void**)&idata)){
00137                         printf("2Failed to get IP data\n");
00138                         return FALSE;
00139                 }
00140         
00141                 flags=ntohs(idata->Header->frag_off) / 8192;
00142                 offset=ntohs(idata->Header->frag_off) & 0x1FFF;
00143                 
00144                 if (offset!=0){
00145                         memcpy(newp->RawPacket+(offset*8)+offset_to_ip+first_header_len,
00146                                 Globals.Packets[Frags[i].PacketSlot].RawPacket+(idata->Header->ihl*4)+offset_to_ip,
00147                                 ntohs(idata->Header->tot_len)-(idata->Header->ihl*4));
00148 #ifdef DEBUG                            
00149                         printf("This fragment has %i bytes\n",  ntohs(idata->Header->tot_len)-(idata->Header->ihl*4));
00150 #endif                  
00151                         newp->PacketLen+=ntohs(idata->Header->tot_len)-(idata->Header->ihl*4);
00152                 }
00153         }
00154 
00155         for (i=0;i<NumFrags;i++){
00156                 if (!GetDataByID(Frags[i].PacketSlot, IPDecoderID, (void**)&idata)){
00157                         printf("3Failed to get IP data\n");
00158                         return FALSE;
00159                 }
00160         
00161                 flags=ntohs(idata->Header->frag_off) / 8192;
00162                 offset=ntohs(idata->Header->frag_off) & 0x1FFF;
00163                 
00164                 if (offset==0){
00165                         ((struct ip_header*)(newp->RawPacket+offset_to_ip))->frag_off=0;
00166                         ((struct ip_header*)(newp->RawPacket+offset_to_ip))->tot_len=htons(newp->PacketLen-14);
00167                         ((struct ip_header*)(newp->RawPacket+offset_to_ip))->check=0;
00168                         ((struct ip_header*)(newp->RawPacket+offset_to_ip))->check=checksum(
00169                                 (unsigned short*)(newp->RawPacket+offset_to_ip),
00170                                 ((struct ip_header*)(newp->RawPacket+offset_to_ip))->ihl*4,
00171                                 NULL,
00172                                 0
00173                                 );
00174                 }
00175         }
00176 
00177 #ifdef DEBUG    
00178         for (i=0;i<10;i++){
00179                 printf("Slot %i is in state %i\n",i, Globals.Packets[i].Status);
00180         }
00181 #endif  
00182                 
00183         return AddPacketToPending(PacketSlot);
00184 }
00185 
00186 /*************************************************************
00187 * Sort the Frag Array. Return TRUE if all pieces are present
00188 * TODO: Do an alert on overlapping fragments;
00189 *************************************************************/
00190 int SortFragArray(struct defrag_item* Frags, int NumFrags){
00191         int             i;
00192         int                     next;
00193         int                     all_done;
00194         int                     found;
00195         int                     last;
00196         
00197         DEBUGPATH;
00198 
00199         next=0;
00200         last=FALSE;
00201         while (1){
00202                 all_done=TRUE;
00203                 found=FALSE;
00204                 for (i=0;i<NumFrags;i++){
00205                         if (!Frags[i].done){
00206                                 if (Frags[i].begin < next){
00207                                         printf("ERROR! Overlapping Fragements\n");
00208 //                                      return FALSE;
00209                                 }
00210                                 if (Frags[i].begin==next){
00211                                         Frags[i].done=TRUE;
00212                                         next=Frags[i].end;
00213                                         all_done=FALSE;
00214                                         found=TRUE;
00215 #ifdef DEBUG                                    
00216                                         printf("More is %i\n",Frags[i].more);
00217 #endif                                  
00218                                         if (!Frags[i].more) last=TRUE;
00219                                 }
00220                         }
00221                 }
00222                 if (last) break;
00223                 if (all_done) break;
00224                 if (!found) return FALSE;
00225         }
00226         
00227         if (!last) return FALSE;
00228 
00229 #ifdef DEBUG    
00230         printf("We have all the parts\n");
00231 #endif  
00232         
00233         return TRUE;
00234 }
00235 
00236 /***************************************
00237 * Reassemble fragmented ip packets
00238 ****************************************/
00239 void* DecodeIPDefrag(int PacketSlot){
00240         struct defrag_key{
00241                 unsigned short  IPID;
00242                 unsigned int    saddr;
00243                 unsigned int    daddr;
00244                 unsigned char   proto;
00245         };
00246 
00247         CacheItems*                     CI;     
00248         IPDefragData*           data=NULL;
00249         IPData*                         idata;
00250         int                                     flags;
00251         int                                     offset;
00252         struct defrag_key       Key;
00253         
00254         PacketRec*                      ThisPacket;
00255         struct defrag_item      Frags[128];
00256         int                                     NumFrags;
00257         int                                     i;
00258         
00259         PacketRec*                      p;
00260         
00261         DEBUGPATH;
00262 
00263 #ifdef DEBUG
00264         printf("----------------------------\n");
00265         printf("Defragmenting IP\n");
00266 #endif
00267 
00268         p=&Globals.Packets[PacketSlot];
00269 
00270         if (!GetDataByID(PacketSlot, IPDecoderID, (void**)&idata)){
00271                 printf("Failed to get ip header data\n");
00272                 return NULL;
00273         }
00274         
00275         flags=ntohs(idata->Header->frag_off) / 8192;
00276         offset=ntohs(idata->Header->frag_off) & 0x1FFF;
00277         
00278         if ( (offset>0) || (flags & FRAG_FLAG_MORE) ){
00279 #ifdef DEBUG    
00280                 printf("This is a fragment\n");
00281 #endif   
00282                 p->PassRawPacket=FALSE;
00283 #ifdef DEBUG            
00284                 if (offset==0){
00285                         printf("This is the first Fragment\n");
00286                 }else{
00287                         printf("Fragment at offset %i\n",offset * 8);
00288                         if (flags & FRAG_FLAG_MORE){ 
00289                                 printf("More Fragments\n");
00290                         }else{
00291                                 printf("No More Fragments\n");
00292                         }
00293                 }
00294 #endif
00295 
00296                 Key.IPID=ntohs(idata->Header->id);
00297                 Key.saddr=idata->Header->saddr;
00298                 Key.daddr=idata->Header->daddr;
00299                 Key.proto=idata->Header->protocol;
00300                 
00301                 printf("ID is %u\n",ntohs(idata->Header->id));
00302                 printf("Proto is %u\n",idata->Header->protocol);
00303                 
00304                 /*check to see if we have all the pieces*/
00305                 hlbr_mutex_lock(&FragMutex, FRAG_LOCK_1, &FragLockID);
00306                 CI=CacheGet(FragCache, (unsigned char*)&Key, sizeof(Key), p->tv.tv_sec);
00307                 NumFrags=0;
00308                 if (CI){
00309                         Frags[0].begin=(ntohs(idata->Header->frag_off) & 0x1FFF)*8;
00310                         Frags[0].end=Frags[0].begin+ntohs(idata->Header->tot_len)-(idata->Header->ihl*4);
00311                         Frags[0].PacketSlot=PacketSlot;
00312                         Frags[0].done=FALSE;
00313                         Frags[0].more=ntohs(idata->Header->frag_off) / 8192;
00314                         /*do it this way so the compiler optimization doesn't kill it*/
00315                         if (Frags[0].more & FRAG_FLAG_MORE){
00316                                 Frags[0].more=TRUE;
00317                         }else{
00318                                 Frags[0].more=FALSE;
00319                         }                               
00320                         NumFrags=1;
00321 #ifdef DEBUG                    
00322                         printf("This frag %i-%i\n",Frags[0].begin, Frags[0].end);
00323 #endif                  
00324                 
00325                         for (i=0;i<CI->NumItems;i++){
00326                                 ThisPacket=&Globals.Packets[*(int*)CI->Items[i].Data];
00327                                 if (!GetDataByID(ThisPacket->PacketSlot, IPDecoderID, (void**)&Frags[NumFrags].idata)){
00328                                         printf("7Failed to get ip header data for the fragment\n");
00329                                         break;
00330                                 }
00331                                 Frags[NumFrags].begin=(ntohs(Frags[NumFrags].idata->Header->frag_off) & 0x1FFF)*8;
00332                                 Frags[NumFrags].end=Frags[NumFrags].begin+ntohs(Frags[NumFrags].idata->Header->tot_len)-(Frags[NumFrags].idata->Header->ihl*4);
00333                                 Frags[NumFrags].PacketSlot=ThisPacket->PacketSlot;
00334                                 Frags[NumFrags].done=FALSE;
00335                                 Frags[NumFrags].more=ntohs(Frags[NumFrags].idata->Header->frag_off) / 8192;
00336                                 /*do it this way so the compiler optimization doesn't kill it*/
00337                                 if (Frags[NumFrags].more & FRAG_FLAG_MORE){
00338                                         Frags[NumFrags].more=TRUE;
00339                                 }else{
00340                                         Frags[NumFrags].more=FALSE;
00341                                 }                               
00342                                 NumFrags++;
00343                         }
00344                 
00345                         if (!SortFragArray(Frags, NumFrags)){
00346                                 /*send this packet off to the cache*/
00347                                 /*to wait for the rest of the pieces*/
00348                                 printf("Adding slot %i\n",PacketSlot);                          
00349                                 CacheAdd(FragCache, (unsigned char*)&Key, sizeof(struct defrag_key), (unsigned char*)&PacketSlot, sizeof(int), Globals.Packets[PacketSlot].tv.tv_sec);
00350                                 Globals.Packets[PacketSlot].SaveCount++;
00351 #ifdef DEBUG
00352                                 printf("Still more packets\n");
00353 #endif                                                          
00354                         }else{
00355                                 /*tell the engine we're done with these packets*/
00356                                 RebuildPacket(Frags, NumFrags);
00357                                 for (i=0;i<CI->NumItems;i++){
00358                                         printf("Returning slot %i\n",*(int*)CI->Items[i].Data);
00359                                         Globals.Packets[*(int*)CI->Items[i].Data].SaveCount--;
00360                                         printf("SaveCount is now %i\n",Globals.Packets[*(int*)CI->Items[i].Data].SaveCount);
00361                                         ReturnEmptyPacket(*(int*)CI->Items[i].Data);
00362                                 }
00363                                 CacheDelKey(FragCache, (unsigned char*)&Key, sizeof(struct defrag_key), Globals.Packets[PacketSlot].tv.tv_sec);
00364 #ifdef DEBUG
00365                                 printf("Packet was rebuilt\n");
00366 #endif                          
00367                         }
00368                 }else{  
00369                         printf("Adding slot %i\n",PacketSlot);          
00370                         CacheAdd(FragCache, (unsigned char*)&Key, sizeof(struct defrag_key), (unsigned char*)&PacketSlot, sizeof(int), Globals.Packets[PacketSlot].tv.tv_sec);
00371                         Globals.Packets[PacketSlot].SaveCount++;
00372 #ifdef DEBUG
00373                         printf("First piece\n");
00374 #endif                                                                                  
00375                 }
00376                 hlbr_mutex_unlock(&FragMutex);
00377         }else{
00378                 data=calloc(sizeof(IPDefragData),1);
00379                 data->IsRebuilt=FALSE;
00380         }
00381                         
00382         return data;
00383 }
00384 
00385 /*************************************
00386 * Set up the decoder
00387 *************************************/
00388 int InitDecoderIPDefrag(){
00389         int DecoderID;
00390 
00391         DEBUGPATH;
00392 
00393         if ((DecoderID=CreateDecoder("IPDefrag"))==DECODER_NONE){
00394 #ifdef DEBUG
00395                 printf("Couldn't Allocate IP Defrag Decoder\n");
00396 #endif  
00397                 return FALSE;
00398         }
00399         
00400         Globals.Decoders[DecoderID].DecodeFunc=DecodeIPDefrag;
00401         if (!DecoderAddDecoder(GetDecoderByName("IP"), DecoderID)){
00402                 printf("Failed to Bind IP Defrag Decoder to IP Decoder\n");
00403                 return FALSE;
00404         }
00405 
00406         IPDecoderID=GetDecoderByName("IP");
00407         
00408         FragCache=InitCache(FRAG_TIMEOUT);
00409 
00410         return TRUE;
00411 }

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