📄 spp_frag3.c
字号:
#endif /* * Don't remove the tracker. * Remove all of the packets that are stored therein. * * If the existing tracker times out because of a delay * relative to the timeout */ //Frag3RemoveTracker(fkey, ft); Frag3DeleteTracker(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 - GET_IPH_HLEN(p) * 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->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 = GET_IPH_PROTO(p); /* * 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;}/** * Handle IP Options in fragmented packets. * * @param ft Current frag tracker for this packet * @param p Current packet to check for options * @param context In case we get an anomaly * * @return status * @retval 0 on an error * @retval 1 on success */static int Frag3HandleIPOptions(FragTracker *ft, Packet *p){ unsigned int i = 0; /* counter */ if(p->frag_offset == 0) { /* * This is the first packet. If it has IP options, * save them off, so we can set them on the reassembled packet. */ if (p->ip_options_len) { ft->ip_options_len = p->ip_options_len; ft->ip_option_count = p->ip_option_count; ft->ip_options_data = SnortAlloc(p->ip_options_len); memcpy(ft->ip_options_data, p->ip_options_data, p->ip_options_len); } } else { /* check that options match those from other non-offset 0 packets */ /* XXX: could check each individual option here, but that * would be performance ugly. So, we'll just check that the * option counts match. Alert if invalid, but still include in * reassembly. */ if (ft->copied_ip_option_count) { if (ft->copied_ip_option_count != p->ip_option_count) { EventAnomIpOpts(ft->context); } } else { ft->copied_ip_option_count = p->ip_option_count; for (i = 0;i< p->ip_option_count && i < IP_OPTMAX; i++) { /* Is the high bit set? If not, weird anomaly. */ if (!(p->ip_options[i].code & 0x80)) EventAnomIpOpts(ft->context); } } } return 1;}int FragGetPolicy(Packet *p, Frag3Context *f3context){#ifdef TARGET_BASED int frag_policy; /* Not caching this host_entry in the frag tracker so we can * swap the table out after processing this packet if we need * to. */ HostAttributeEntry *host_entry = SFAT_LookupHostEntryByDst(p); if (host_entry && (isFragPolicySet(host_entry) == POLICY_SET)) { frag_policy = getFragPolicy(host_entry); if (frag_policy != SFAT_UNKNOWN_FRAG_POLICY) { DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "FragGetPolicy: Policy Map Entry: %s %s %s %d(%s)\n", host_entry->hostInfo.vendor.value.s_value, host_entry->hostInfo.operatingSystem.value.s_value, host_entry->hostInfo.version.value.s_value, frag_policy, frag_policy_names[frag_policy]);); return frag_policy; } }#endif DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "FragGetPolicy: Using configured default %d(%s)\n", f3context->frag_policy, frag_policy_names[f3context->frag_policy]);); return f3context->frag_policy;}/** * Didn't find a FragTracker in the hash table, create a new one and put it * into the f_cache * * @param p Current packet to fill in FragTracker fields * @param fkey FragKey struct to use for table insertion * * @return status * @retval 0 on an error * @retval 1 on success */static int Frag3NewTracker(Packet *p, FRAGKEY *fkey, Frag3Context *f3context){ FragTracker *tmp; Frag3Frag *f = NULL; //int ret = 0; const u_int8_t *fragStart; u_int16_t fragLength; u_int16_t frag_end; SFXHASH_NODE *hnode; fragStart = (u_int8_t *)p->iph + GET_IPH_HLEN(p) * 4; /* 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 - GET_IPH_HLEN(p) * 4;#ifdef DEBUG if (p->actual_ip_len != ntohs(GET_IPH_LEN(p))) { DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "IP Actual Length (%d) != specified length (%d), " "truncated packet (%d)?\n", p->actual_ip_len, ntohs(GET_IPH_LEN(p)), snaplen);); }#endif /* Just to double check */ if (fragLength > snaplen) { DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Overly large fragment %d 0x%x 0x%x %d\n", fragLength, GET_IPH_LEN(p), GET_IPH_OFF(p), p->frag_offset << 3);); /* Ah, crap. Return that tracker. */ return 0; } /* Get a node from the hash table */ hnode = sfxhash_get_node(f_cache, fkey); if (!hnode) { DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Frag3NewTracker: sfxhash_get_node() failed\n");); return 0; } else { if (hnode->data) { tmp = hnode->data; memset(tmp, 0, sizeof(FragTracker)); } else { DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Frag3NewTracker: sfxhash_get_node() failed\n");); return 0; } } /* * setup the frag tracker */ tmp->sip = fkey->sip; tmp->dip = fkey->dip; tmp->id = fkey->id; tmp->protocol = fkey->proto; tmp->ttl = GET_IPH_TTL(p); /* store the first ttl we got */ tmp->calculated_size = 0; tmp->alerted = 0; tmp->frag_flags = 0; tmp->frag_bytes = 0; tmp->frag_pkts = 0; tmp->frag_time.tv_sec = p->pkth->ts.tv_sec; tmp->frag_time.tv_usec = p->pkth->ts.tv_usec; tmp->alert_count = 0; tmp->ip_options_len = 0; tmp->ip_option_count = 0; tmp->ip_options_data = NULL; tmp->copied_ip_options_len = 0; tmp->copied_ip_option_count = 0; tmp->context = f3context; tmp->ordinal = 0; tmp->frag_policy = FragGetPolicy(p, f3context); /* * get our first fragment storage struct */ if(!global_config.use_prealloc) { if(mem_in_use > global_config.memcap) { if (Frag3Prune(tmp) == 0) { DEBUG_WRAP(DebugMessage(DEBUG_FRAG, "Frag3NewTra
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -