📄 spp_frag3.c
字号:
p->packet_flags, prealloc_nodes_in_use, global_config.static_frags);); /* zero the frag key */ memset(&fkey, 0, sizeof(FRAGKEY));#if 0 /* * Check the memcap and clear some space if we're over the memcap */ if(mem_in_use > global_config.memcap) { DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "memcap exceeded (%ld bytes in use), " "calling Frag3Prune()\n", mem_in_use);); Frag3Prune(); }#endif pkttime = (struct timeval *) &p->pkth->ts; /* * try to get the tracker that this frag should go with */ if((ft = Frag3GetTracker(p, &fkey)) == NULL) { DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Adding New FragTracker...\n");); /* * first frag for this packet, start a new tracker */ Frag3NewTracker(p, &fkey, f3context); DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "[FRAG3] mem use: %ld frag " "trackers: %d prealloc " "nodes in use: %lu/%lu\n", mem_in_use, sfxhash_count(f_cache), prealloc_nodes_in_use, global_config.static_frags);); /* * all done, return control to Snort */ return; } DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Found frag tracker\n");); /* * insert the fragment into the FragTracker */ if((insert_return = Frag3Insert(p, ft, &fkey, f3context)) != FRAG_INSERT_OK) { /* * we can pad this switch out for a variety of entertaining behaviors * later if we're so inclined */ switch(insert_return) { case FRAG_INSERT_FAILED: if(!pv.quiet_flag) { LogMessage("WARNING: Insert into Fraglist failed, " "(offset: %u)\n", p->frag_offset); } return; case FRAG_INSERT_TTL: LogMessage( "[FRAG3] Fragment discarded due to large TTL Delta " "[0x%X->0x%X], TTL: %d orig TTL: %d " "Offset: %d Length: %d\n", ntohl(p->iph->ip_src.s_addr), ntohl(p->iph->ip_dst.s_addr), p->iph->ip_ttl, ft->ttl, p->frag_offset, p->dsize); f3stats.discards++; return; case FRAG_INSERT_ATTACK: case FRAG_INSERT_ANOMALY: f3stats.discards++; return; case FRAG_INSERT_TIMEOUT:#ifdef DEBUG if(!pv.quiet_flag) { LogMessage("WARNING: Insert into Fraglist failed due to timeout, " "(offset: %u)\n", p->frag_offset); }#endif return; default: break; } } p->fragtracker = (void *)ft; /* * check to see if it's reassembly time */ if(Frag3IsComplete(ft)) { DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "[*] Fragment is complete, rebuilding!\n");); /* * if the frag completes but it's bad we're just going to drop it * instead of wasting time on putting it back together */ if(!(ft->frag_flags & FRAG_BAD)) { Frag3Rebuild(ft, p); if ((p->frag_offset != 0) || (p->iph->ip_proto != IPPROTO_UDP)) { /* Need to reset some things here because the * rebuilt packet will have reset the do_detect * flag when it hits Preprocess. */ do_detect = 0; otn_tmp = NULL; /* And unset the frag tracker for this packet since * we're going to blow it away in a few usecs... */ p->fragtracker = NULL; } } Frag3RemoveTracker(&fkey, ft); } DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "[FRAG3] Dumped fragtracker (mem use: %ld frag " "trackers: %d prealloc " "nodes in use: %lu/%lu)\n", mem_in_use, sfxhash_count(f_cache), prealloc_nodes_in_use, global_config.static_frags);); return;}/** * Check to see if a FragTracker has timed out * * @param current_time Time at this moment * @param start_time Time to compare current_time to * @param f3context Engine context * * @return status * @retval FRAG_TIMEOUT Current time diff is greater than the current * context's timeout value * @retval FRAG_TIME_OK Current time diff is within the context's prune * window */static INLINE int CheckTimeout(struct timeval *current_time, struct timeval *start_time, Frag3Context *f3context){ struct timeval tv_diff; /* storage struct for the difference between current_time and start_time */ TIMERSUB(current_time, start_time, &tv_diff); if(tv_diff.tv_sec >= f3context->frag_timeout) { return FRAG_TIMEOUT; } return FRAG_TIME_OK;}/** * Time-related expiration of fragments from the system. Checks the current * FragTracker for timeout, then walks up the LRU list looking to see if * anyone should have timed out. * * @param p Current packet (contains pointer to the current timestamp) * @param ft FragTracker to check for a timeout * @param fkey FragKey of the current FragTracker for sfxhash lookup * @param f3context Context of the defrag engine, contains the timeout value * * @return status * @retval FRAG_TRACKER_TIMEOUT The current FragTracker has timed out * @retval FRAG_OK The current FragTracker has not timed out */static int Frag3Expire( Packet *p, FragTracker *ft, FRAGKEY *fkey, Frag3Context *f3context){#if 0 struct timeval *fttime; /* FragTracker timestamp */ struct timeval *pkttime; /* packet timestamp */ FragTracker *tmpft; /* temp pointer for moving thru the LRU queue */#endif /* * Check the FragTracker that was passed in first */ if(CheckTimeout( pkttime, &(ft)->frag_time, f3context) == FRAG_TIMEOUT) { /* * Oops, we've timed out, whack the FragTracker */#ifdef DEBUG_FRAG3 if (DEBUG_FRAG & GetDebugLevel()) LogMessage("(spp_frag3) Current Fragment dropped due to timeout! " "[0x%08X->0x%08X ID: %d]\n", ft->sip, ft->dip, ft->id);#endif Frag3RemoveTracker(fkey, ft); f3stats.timeouts++; sfPerf.sfBase.iFragTimeouts++; return FRAG_TRACKER_TIMEOUT; }#if 0 /* * This doesn't really need to be done here!!! * We'll blow them away when we prune for memory reasons. */ /* * The current FragTracker hasn't timed out, check the LRU FragTrackers to * see if any of them need to go. */ if((tmpft = (FragTracker*)sfxhash_lru(f_cache))) { fttime = &tmpft->frag_time; pkttime = (struct timeval *) &p->pkth->ts; while(tmpft && CheckTimeout(pkttime,fttime,f3context)==FRAG_TIMEOUT) { LogMessage("(spp_frag3) Fragment dropped due to timeout! " "[0x%08X->0x%08X ID: %d]\n", tmpft->sip, tmpft->dip, tmpft->id); sfxhash_free_node(f_cache, sfxhash_lru_node(f_cache)); f3stats.timeouts++; sfPerf.sfBase.iFragTimeouts++; if((tmpft = (FragTracker*)(sfxhash_lru(f_cache)))) { fttime = &tmpft->frag_time; } } }#endif /* * set the current FragTracker's timeout on our way out the door... */ /* XXX Uh, I shouldn't be doing this should I???? */ //ft->frag_time.tv_sec = p->pkth->ts.tv_sec; //ft->frag_time.tv_usec = p->pkth->ts.tv_usec; return FRAG_OK;}/** * Check to see if we've got the first or last fragment on a FragTracker and * set the appropriate frag_flags * * @param p Packet to get the info from * @param ft FragTracker to set the flags on * * @return none */static int INLINE Frag3CheckFirstLast(Packet *p, FragTracker *ft){ u_int16_t fragLength; int retVal = FRAG_FIRSTLAST_OK; u_int16_t endOfThisFrag; /* set the frag flag if this is the first fragment */ if(p->mf && p->frag_offset == 0) { ft->frag_flags |= FRAG_GOT_FIRST; DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Got first frag\n");); } else if((!p->mf) && (p->frag_offset > 0)) /* set for last frag too */ { /* Use the actual length here, because packet may have been * truncated. Don't want to try to copy more than we actually * captured. */ fragLength = p->actual_ip_len - IP_HLEN(p->iph) * 4; endOfThisFrag = (p->frag_offset << 3) + fragLength; if (ft->frag_flags & FRAG_GOT_LAST) { DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Got last frag again!\n");); switch (ft->context->frag_policy) { case FRAG_POLICY_BSD: case FRAG_POLICY_LINUX: case FRAG_POLICY_BSD_RIGHT: case FRAG_POLICY_LAST: case FRAG_POLICY_WINDOWS: case FRAG_POLICY_FIRST: if (ft->calculated_size > endOfThisFrag) { /* Already have a 'last frag' with a higher * end point. Leave it as is. * * Some OS's do not respond at all -- we'll * still try to rebuild anyway in that case, * because there is really something wrong * and we should look at it. */ retVal = FRAG_LAST_DUPLICATE; } break; case FRAG_POLICY_SOLARIS: if (ft->calculated_size > endOfThisFrag) { /* Already have a 'last frag' with a higher * end point. Leave it as is. * * Some OS's do not respond at all -- we'll * still try to rebuild anyway in that case, * because there is really something wrong * and we should look at it. */ retVal = FRAG_LAST_DUPLICATE; } else { /* Solaris does some weird stuff here... */ /* Usually, Solaris takes the higher end point. * But in one strange case (when it hasn't seen * any frags beyond the existing last frag), it * actually appends that new last frag to the * end of the previous last frag, regardless of * the offset. Effectively, it adjusts the * offset of the new last frag to immediately * after the existing last frag. */ /* XXX: how to handle that case? punt? */ retVal = FRAG_LAST_OFFSET_ADJUST; } break; } } ft->frag_flags |= FRAG_GOT_LAST; /* * If this is the last frag (and we don't have a frag that already * extends beyond this one), set the size that we're expecting. */ if ((ft->calculated_size < endOfThisFrag) && (retVal != FRAG_LAST_OFFSET_ADJUST)) { ft->calculated_size = endOfThisFrag; DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Got last frag, Bytes: %d, " "Calculated size: %d\n", ft->frag_bytes, ft->calculated_size);); } } DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Frag Status: %s:%s\n", ft->frag_flags&FRAG_GOT_FIRST?"FIRST":"No FIRST", ft->frag_flags&FRAG_GOT_LAST?"LAST":"No LAST");); return retVal; }/** * Lookup a FragTracker in the f_cache sfxhash table based on an input key * * @param p The current packet to get the key info from * @param fkey Pointer to a container for the FragKey * * @return Pointer to the FragTracker in the hash bucket or NULL if there is * no fragment in the hash bucket */static FragTracker *Frag3GetTracker(Packet *p, FRAGKEY *fkey){ FragTracker *returned; /* FragTracker ptr returned by the lookup */ /* * we have to setup the key first, downstream functions depend on * it being setup here */ fkey->sip = p->iph->ip_src.s_addr; fkey->dip = p->iph->ip_dst.s_addr; fkey->id = p->iph->ip_id; fkey->proto = p->iph->ip_proto; /* * if the hash table is empty we're done */ if(sfxhash_count(f_cache) == 0) return NULL; DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "[*] Looking up FragTracker using key:\n"););#ifdef DEBUG_FRAG3 PrintFragKey(fkey);#endif returned = (FragTracker *) sfxhash_find(f_cache, fkey); DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Frag3GetTracker returning %p for\n", returned);); return returned;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -