1 /*
2 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
3 ** Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
4 ** Copyright (C) 2002-2013 Sourcefire, Inc.
5 **               Chris Green <cmg@sourcefire.com>
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License Version 2 as
9 ** published by the Free Software Foundation.  You may not use, modify or
10 ** distribute this program under any other version of the GNU General
11 ** Public License.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with this program; if not, write to the Free Software
20 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 */
22 
23 /* $Id$ */
24 
25 /*  I N C L U D E S  ************************************************/
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 
30 #include <sys/types.h>
31 #include <stdlib.h>
32 #include <rpc/types.h>
33 #include <string.h>
34 #include <ctype.h>
35 
36 #include "decode.h"
37 #include "rules.h"
38 #include "treenodes.h"
39 #include "snort_debug.h"
40 #include "util.h"
41 #include "generators.h"
42 #include "log.h"
43 #include "parser.h"
44 #include "snort.h"
45 #include "tag.h"
46 
47 #include "sfxhash.h"
48 
49 #include "ipv6_port.h"
50 
51 /*  D E F I N E S  **************************************************/
52 #define MAX_TAG_NODES   256
53 
54 /* by default we'll set a 5 minute timeout if we see no activity
55  * on a tag with a 'count' metric so that we prune dead sessions
56  * periodically since we're not doing TCP state tracking
57  */
58 #define TAG_PRUNE_QUANTUM   300
59 #define TAG_MEMCAP          4194304  /* 4MB */
60 
61 /*  D A T A   S T R U C T U R E S  **********************************/
62 /**Key used for identifying a session or host.
63  */
64 typedef struct _tagSessionKey
65 {
66     struct in6_addr sip;  ///source IP address
67     struct in6_addr dip;  ///destination IP address
68 
69     /* ports */
70     uint16_t sp; ///source port
71     uint16_t dp; ///destination port
72 
73 } tTagSessionKey;
74 
75 /**Node identifying a session or host based tagging.
76  */
77 typedef struct _TagNode
78 {
79     /**key identifying a session or host. */
80     tTagSessionKey key;
81 
82     /** transport proto */
83     uint8_t proto;
84 
85     /** number of packets/seconds/bytes to tag for */
86     int seconds;
87     int packets;
88     int bytes;
89 
90     /** counters of number of packets tagged and max to
91      * prevent Eventing DOS */
92     int pkt_count;
93 
94     /** packets/seconds selector */
95     int metric;
96 
97     /** session or host mode */
98     int mode;
99 
100     /** last UNIX second that this node had a successful match */
101     uint32_t last_access;
102 
103     /** event id number for correlation with trigger events */
104     uint16_t event_id;
105     struct timeval event_time;
106 
107     void* log_list;  // retain custom logging if any from triggering alert
108 
109 } TagNode;
110 
111 /*  G L O B A L S  **************************************************/
112 /**host tag cache */
113 static SFXHASH *host_tag_cache_ptr;
114 
115 /**session tag cache */
116 static SFXHASH *ssn_tag_cache_ptr;
117 
118 static uint32_t last_prune_time;
119 static uint32_t tag_alloc_faults;
120 static uint32_t tag_memory_usage;
121 
122 static bool s_exclusive = false;
123 static unsigned s_sessions = 0;
124 
125 // TBD when tags leverage sessions, tag nodes can be freed at end
126 // of session.  then we can configure this to allow multiple
127 // (consecutive) sessions to be captured.
128 static const unsigned s_max_sessions = 1;
129 
130 /*  P R O T O T Y P E S  ********************************************/
131 static TagNode * TagAlloc(SFXHASH *);
132 static void TagFree(SFXHASH *, TagNode *);
133 static int TagFreeSessionNodeFunc(void *key, void *data);
134 static int TagFreeHostNodeFunc(void *key, void *data);
135 static int PruneTagCache(uint32_t, int);
136 static int PruneTime(SFXHASH* tree, uint32_t thetime);
137 static void TagSession(Packet *, TagData *, uint32_t, uint16_t, void*);
138 static void TagHost(Packet *, TagData *, uint32_t, uint16_t, void*);
139 static void AddTagNode(Packet *, TagData *, int, uint32_t, uint16_t, void*);
140 static inline void SwapTag(TagNode *);
141 
142 /**Calculated memory needed per node insertion into respective cache. Its includes
143  * memory needed for allocating TagNode, SFXHASH_NODE, and key size.
144  *
145  * @param hash - pointer to SFXHASH that should point to either ssn_tag_cache_ptr
146  * or host_tag_cache_ptr.
147  *
148  * @returns number of bytes needed
149  */
memory_per_node(SFXHASH * hash)150 static inline unsigned int memory_per_node(
151         SFXHASH *hash
152         )
153 {
154     if (hash == ssn_tag_cache_ptr)
155     {
156         return sizeof(tTagSessionKey)+sizeof(SFXHASH_NODE)+sizeof(TagNode);
157     }
158     else if (hash == host_tag_cache_ptr)
159     {
160         return sizeof(sfaddr_t)+sizeof(SFXHASH_NODE)+sizeof(TagNode);
161     }
162 
163     return 0;
164 }
165 
166 /** Allocate a TagNode
167  *
168  * Alocates a TagNode while guaranteeing that total memory usage remains within TAG_MEMCAP.
169  * Least used nodes may be deleted from ssn_tag_cache and host_tag_cache to make space if
170  * the limit is being exceeded.
171  *
172  * @param hash - pointer to SFXHASH that should point to either ssn_tag_cache_ptr
173  * or host_tag_cache_ptr.
174  *
175  * @returns a pointer to new TagNode or NULL if memory couldn't * be allocated
176  */
TagAlloc(SFXHASH * hash)177 static TagNode * TagAlloc(
178         SFXHASH *hash
179         )
180 {
181     TagNode *tag_node = NULL;
182 
183     if(tag_memory_usage + memory_per_node(hash) > TAG_MEMCAP)
184     {
185         /* aggressively prune */
186         struct timeval tv;
187         struct timezone tz;
188         int pruned_nodes = 0;
189 
190         tag_alloc_faults++;
191 
192         gettimeofday(&tv, &tz);
193 
194         pruned_nodes = PruneTagCache((uint32_t)tv.tv_sec, 0);
195 
196         if(pruned_nodes == 0)
197         {
198             /* if we can't prune due to time, just try to nuke
199              * 5 not so recently used nodes */
200             pruned_nodes = PruneTagCache(0, 5);
201 
202             /* unlikely to happen since memcap has been reached */
203             if (pruned_nodes == 0)
204                 return NULL;
205         }
206     }
207 
208     tag_node = (TagNode *)calloc(1, sizeof(TagNode));
209 
210     if (tag_node != NULL)
211         tag_memory_usage += memory_per_node(hash);
212 
213     return tag_node;
214 }
215 
216 /**Frees allocated TagNode.
217  *
218  * @param hash - pointer to SFXHASH that should point to either ssn_tag_cache_ptr
219  * or host_tag_cache_ptr.
220  * @param node - pointer to node to be freed
221  */
TagFree(SFXHASH * hash,TagNode * node)222 static void TagFree(
223         SFXHASH *hash,
224         TagNode *node
225         )
226 {
227     if (node == NULL)
228         return;
229 
230     if ( node->metric & TAG_METRIC_SESSION )
231         s_exclusive = false;
232 
233     free((void *)node);
234     tag_memory_usage -= memory_per_node(hash);
235 }
236 
237 /**Callback from session tag cache to free user data.
238  * @param key - pointer to key to session tag
239  * @param data - pointer to user data, to be freed.
240  * @returns 0
241  */
TagFreeSessionNodeFunc(void * key,void * data)242 static int TagFreeSessionNodeFunc(void *key, void *data)
243 {
244     TagFree(ssn_tag_cache_ptr, (TagNode *)data);
245     return 0;
246 }
247 
248 /**Callback from host tag cache to free user data.
249  * @param key - pointer to key to session tag
250  * @param data - pointer to user data, to be freed.
251  * @returns 0
252  */
TagFreeHostNodeFunc(void * key,void * data)253 static int TagFreeHostNodeFunc(void *key, void *data)
254 {
255     TagFree(host_tag_cache_ptr, (TagNode *)data);
256     return 0;
257 }
258 
259 /**Reset all data structures and free all memory.
260  */
TagCacheReset(void)261 void TagCacheReset(void)
262 {
263     sfxhash_make_empty(ssn_tag_cache_ptr);
264     sfxhash_make_empty(host_tag_cache_ptr);
265 }
266 
267 
268 #ifdef DEBUG_MSGS
269 
270 /**
271  * Print out a tag node IFF we are current in debug_flow
272  *
273  * @param np tagnode pointer to print
274  */
PrintTagNode(TagNode * np)275 static void PrintTagNode(TagNode *np)
276 {
277     char sipstr[INET6_ADDRSTRLEN];
278     char dipstr[INET6_ADDRSTRLEN];
279 
280     if(!DebugThis(DEBUG_FLOW))
281     {
282         return;
283     }
284 
285     sfip_raw_ntop(AF_INET6, &np->key.sip, sipstr, sizeof(sipstr));
286     sfip_raw_ntop(AF_INET6, &np->key.dip, dipstr, sizeof(dipstr));
287 
288     printf("+--------------------------------------------------------------\n");
289     printf("| Ssn Counts: %d, Host Counts: %d\n",
290            ssn_tag_cache_ptr->count,
291            host_tag_cache_ptr->count);
292 
293     printf("| (%u) %s:%d -> %s:%d Metric: %u "
294            "LastAccess: %u, event_id: %u mode: %u event_time.tv_sec: %"PRIu64"\n"
295            "| Packets: %d, Bytes: %d, Seconds: %d\n",
296            np->proto,
297            sipstr, np->key.sp,
298            dipstr, np->key.dp,
299            np->metric,
300            np->last_access,
301            np->event_id,
302            np->mode,
303            (uint64_t)np->event_time.tv_sec,
304            np->packets,
305            np->bytes,
306            np->seconds);
307 
308     printf("+--------------------------------------------------------------\n");
309 }
310 
311 #endif /* DEBUG */
312 
313 /**
314  * swap the sips and dips, dp's and sp's
315  *
316  * @param np TagNode ptr
317  */
SwapTag(TagNode * np)318 static inline void SwapTag(TagNode *np)
319 {
320     struct in6_addr tip;
321     uint16_t tport;
322 
323     tip = np->key.sip;
324     np->key.sip = np->key.dip;
325     np->key.dip = tip;
326 
327     tport = np->key.sp;
328     np->key.sp = np->key.dp;
329     np->key.dp = tport;
330 }
331 
InitTag(void)332 void InitTag(void)
333 {
334     unsigned int hashTableSize = TAG_MEMCAP/sizeof(TagNode);
335 
336     ssn_tag_cache_ptr = sfxhash_new(
337                 hashTableSize,              /* number of hash buckets */
338                 sizeof(tTagSessionKey),     /* size of the key we're going to use */
339                 0,                          /* size of the storage node */
340                 0,                          /* disable memcap*/
341                 0,                          /* use auto node recovery */
342                 NULL,                       /* anr free function */
343                 TagFreeSessionNodeFunc,     /* user free function */
344                 0);                         /* recycle node flag */
345 
346     host_tag_cache_ptr = sfxhash_new(
347                 hashTableSize,       /* number of hash buckets */
348                 sizeof(struct in6_addr), /* size of the key we're going to use */
349                 0,                   /* size of the storage node */
350                 0,                   /* disable memcap*/
351                 0,                   /* use auto node recovery */
352                 NULL,                /* anr free function */
353                 TagFreeHostNodeFunc, /* user free function */
354                 0);                  /* recycle node flag */
355 }
356 
CleanupTag(void)357 void CleanupTag(void)
358 {
359     if (ssn_tag_cache_ptr)
360     {
361         sfxhash_delete(ssn_tag_cache_ptr);
362     }
363 
364     if (host_tag_cache_ptr)
365     {
366         sfxhash_delete(host_tag_cache_ptr);
367     }
368 }
369 
TagSession(Packet * p,TagData * tag,uint32_t time,uint16_t event_id,void * log_list)370 static void TagSession(Packet *p, TagData *tag, uint32_t time, uint16_t event_id, void* log_list)
371 {
372     DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "TAGGING SESSION\n"););
373 
374     AddTagNode(p, tag, TAG_SESSION, time, event_id, log_list);
375 }
376 
TagHost(Packet * p,TagData * tag,uint32_t time,uint16_t event_id,void * log_list)377 static void TagHost(Packet *p, TagData *tag, uint32_t time, uint16_t event_id, void* log_list)
378 {
379     int mode;
380 
381     DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "TAGGING HOST\n"););
382 
383     switch(tag->tag_direction)
384     {
385         case TAG_HOST_DST:
386             mode = TAG_HOST_DST;
387             break;
388         case TAG_HOST_SRC:
389             mode = TAG_HOST_SRC;
390             break;
391         default:
392             mode = TAG_HOST_SRC;
393             break;
394     }
395 
396     AddTagNode(p, tag, mode, time, event_id, log_list);
397 }
398 
AddTagNode(Packet * p,TagData * tag,int mode,uint32_t now,uint16_t event_id,void * log_list)399 static void AddTagNode(Packet *p, TagData *tag, int mode, uint32_t now,
400                 uint16_t event_id, void* log_list)
401 {
402     TagNode *idx;  /* index pointer */
403     TagNode *returned;
404     SFXHASH *tag_cache_ptr = NULL;
405 
406     DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "Adding new Tag Head\n"););
407 
408     if ( tag->tag_metric & TAG_METRIC_SESSION )
409     {
410         if ( s_exclusive )
411             return;
412 
413         if ( s_sessions >= s_max_sessions )
414             return;
415 
416         s_exclusive = true;
417         ++s_sessions;
418     }
419     if(mode == TAG_SESSION)
420     {
421         DEBUG_WRAP(DebugMessage(DEBUG_FLOW,"Session Tag!\n"););
422         tag_cache_ptr = ssn_tag_cache_ptr;
423 
424     }
425     else
426     {
427         DEBUG_WRAP(DebugMessage(DEBUG_FLOW,"Host Tag!\n"););
428         tag_cache_ptr = host_tag_cache_ptr;
429     }
430     idx = TagAlloc(tag_cache_ptr);
431 
432     /* If a TagNode couldn't be allocated, just write an error message
433      * and return - won't be able to track this one. */
434     if (idx == NULL)
435     {
436         ErrorMessage("AddTagNode(): Unable to allocate %u bytes of memory for new TagNode\n",
437                      (unsigned)sizeof(TagNode));
438         return;
439     }
440 
441     sfaddr_copy_to_raw(&idx->key.sip, GET_SRC_IP(p));
442     sfaddr_copy_to_raw(&idx->key.dip, GET_DST_IP(p));
443     idx->key.sp = p->sp;
444     idx->key.dp = p->dp;
445     idx->proto = GET_IPH_PROTO(p);
446     idx->metric = tag->tag_metric;
447     idx->last_access = now;
448     idx->event_id = event_id;
449     idx->event_time.tv_sec = p->pkth->ts.tv_sec;
450     idx->event_time.tv_usec = p->pkth->ts.tv_usec;
451     idx->mode = mode;
452     idx->pkt_count = 0;
453     idx->log_list = log_list;
454 
455     if(idx->metric & TAG_METRIC_SECONDS)
456     {
457         /* set the expiration time for this tag */
458         idx->seconds = now + tag->tag_seconds;
459     }
460 
461     if(idx->metric & TAG_METRIC_BYTES)
462     {
463         /* set the expiration time for this tag */
464         idx->bytes = tag->tag_bytes;
465     }
466 
467     if(idx->metric & TAG_METRIC_PACKETS)
468     {
469         /* set the expiration time for this tag */
470         idx->packets = tag->tag_packets;
471     }
472 
473     DEBUG_WRAP(PrintTagNode(idx););
474 
475     /* check for duplicates */
476     returned = (TagNode *) sfxhash_find(tag_cache_ptr, idx);
477 
478     if(returned == NULL)
479     {
480         DEBUG_WRAP(DebugMessage(DEBUG_FLOW,"Looking the other way!!\n"););
481         SwapTag(idx);
482         returned = (TagNode *) sfxhash_find(tag_cache_ptr, idx);
483         SwapTag(idx);
484     }
485 
486     if(returned == NULL)
487     {
488         DEBUG_WRAP(DebugMessage(DEBUG_FLOW,"Inserting a New Tag!\n"););
489 
490         /* if we're supposed to be tagging the other side, swap it
491            around -- Lawrence Reed */
492         if(mode == TAG_HOST_DST)
493         {
494             SwapTag(idx);
495         }
496 
497         if(sfxhash_add(tag_cache_ptr, idx, idx) != SFXHASH_OK)
498         {
499             DEBUG_WRAP(DebugMessage(DEBUG_FLOW,
500                                     "sfxhash_add failed, that's going to "
501                                     "make life difficult\n"););
502             TagFree(tag_cache_ptr, idx);
503             return;
504         }
505 
506         DEBUG_WRAP(PrintTagNode(idx););
507     }
508     else
509     {
510         DEBUG_WRAP(DebugMessage(DEBUG_FLOW,"Existing Tag found!\n"););
511 
512         if(idx->metric & TAG_METRIC_SECONDS)
513             returned->seconds = idx->seconds;
514         else
515             returned->seconds += idx->seconds;
516 
517         /* get rid of the new tag since we are using an existing one */
518         TagFree(tag_cache_ptr, idx);
519 
520         DEBUG_WRAP(PrintTagNode(returned););
521     }
522 }
523 
524 
CheckTagList(Packet * p,Event * event,void ** log_list)525 int CheckTagList(Packet *p, Event *event, void** log_list)
526 {
527     TagNode idx;
528     TagNode *returned = NULL;
529     SFXHASH* taglist = NULL;
530     char create_event = 1;
531 
532     /* check for active tags */
533     if(!sfxhash_count(host_tag_cache_ptr) && !sfxhash_count(ssn_tag_cache_ptr))
534     {
535         return 0;
536     }
537 
538     if(p == NULL || !IPH_IS_VALID(p))
539     {
540         DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "bailing from CheckTagList, p->iph == NULL\n"););
541         return 0;
542     }
543 
544     DEBUG_WRAP(DebugMessage(DEBUG_FLOW,"Host Tags Active: %d   Session Tags Active: %d\n",
545 			    sfxhash_count(host_tag_cache_ptr), sfxhash_count(ssn_tag_cache_ptr)););
546 
547     DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "[*] Checking session tag list (forward)...\n"););
548 
549     sfaddr_copy_to_raw(&idx.key.sip, GET_SRC_IP(p));
550     sfaddr_copy_to_raw(&idx.key.dip, GET_DST_IP(p));
551     idx.key.sp = p->sp;
552     idx.key.dp = p->dp;
553 
554     /* check for session tags... */
555     returned = (TagNode *) sfxhash_find(ssn_tag_cache_ptr, &idx);
556 
557     if(returned == NULL)
558     {
559         sfaddr_copy_to_raw(&idx.key.dip, GET_SRC_IP(p));
560         sfaddr_copy_to_raw(&idx.key.sip, GET_DST_IP(p));
561         idx.key.dp = p->sp;
562         idx.key.sp = p->dp;
563 
564         DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "   Checking session tag list (reverse)...\n"););
565         returned = (TagNode *) sfxhash_find(ssn_tag_cache_ptr, &idx);
566 
567         if(returned == NULL)
568         {
569             DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "   Checking host tag list "
570 				    "(forward)...\n"););
571 
572             returned = (TagNode *) sfxhash_find(host_tag_cache_ptr, &idx);
573 
574             if(returned == NULL)
575             {
576                 /*
577                 **  Only switch sip, because that's all we check for
578                 **  the host tags.
579                 */
580                 sfaddr_copy_to_raw(&idx.key.sip, GET_SRC_IP(p));
581 
582                 returned = (TagNode *) sfxhash_find(host_tag_cache_ptr, &idx);
583             }
584 
585             if(returned != NULL)
586             {
587                 DEBUG_WRAP(DebugMessage(DEBUG_FLOW,"   [*!*] Found host node\n"););
588                 taglist = host_tag_cache_ptr;
589             }
590         }
591         else
592         {
593             DEBUG_WRAP(DebugMessage(DEBUG_FLOW,"   [*!*] Found session node\n"););
594             taglist = ssn_tag_cache_ptr;
595         }
596     }
597     else
598     {
599         DEBUG_WRAP(DebugMessage(DEBUG_FLOW,"   [*!*] Found session node\n"););
600         taglist = ssn_tag_cache_ptr;
601     }
602 
603     if(returned != NULL)
604     {
605         DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "    ! Found tag node !\n"););
606 
607         returned->last_access = p->pkth->ts.tv_sec;
608         returned->pkt_count++;
609 
610         if ( returned->metric & TAG_METRIC_SECONDS )
611         {
612             if(p->pkth->ts.tv_sec > returned->seconds)
613             {
614                 returned->metric = 0;
615                 create_event = 0;
616             }
617         }
618 
619         if ( returned->metric & TAG_METRIC_BYTES )
620         {
621             int n = p->pkth->caplen;
622 
623             if ( n < returned->bytes )
624                 returned->bytes -= n;
625             else
626                 returned->metric = 0;
627         }
628 
629         if ( returned->metric & TAG_METRIC_PACKETS )
630         {
631             if ( returned->packets > 1 )
632                 returned->packets--;
633             else
634                 returned->metric = 0;
635         }
636         if ( !(returned->metric & TAG_METRIC_UNLIMITED) )
637         {
638             /* Check whether or not to actually log an event.
639              * This is used to prevent a poorly written tag rule
640              * from DOSing a backend event processors on high
641              * bandwidth sensors. */
642             /* Use the global max. */
643             /* If its non-0, check count for this tag node */
644             if ( ScTaggedPacketLimit() &&
645                 returned->pkt_count >= ScTaggedPacketLimit() )
646             {
647                 returned->metric = 0;
648             }
649         }
650 
651         if ( create_event )
652         {
653             /* set the event info */
654             SetEvent(event, GENERATOR_TAG, TAG_LOG_PKT, 1, 1, 1,
655 #if !defined(FEAT_OPEN_APPID)
656                     returned->event_id);
657 #else /* defined(FEAT_OPEN_APPID) */
658                     returned->event_id, NULL);
659 #endif /* defined(FEAT_OPEN_APPID) */
660             /* set event reference details */
661             event->ref_time.tv_sec = returned->event_time.tv_sec;
662             event->ref_time.tv_usec = returned->event_time.tv_usec;
663             event->event_reference = returned->event_id | ScEventLogId();
664             *log_list = returned->log_list;
665         }
666 
667         if ( !returned->metric )
668         {
669             DEBUG_WRAP(DebugMessage(DEBUG_FLOW,
670                 "    Prune condition met for tag, removing from list\n"););
671 
672             if (sfxhash_remove(taglist, returned) != SFXHASH_OK)
673             {
674                 LogMessage("WARNING: failed to remove tagNode from hash.\n");
675             }
676         }
677     }
678 
679     if ( (u_int)(p->pkth->ts.tv_sec) > last_prune_time + TAG_PRUNE_QUANTUM )
680     {
681         DEBUG_WRAP(DebugMessage(DEBUG_FLOW,
682                                 "Exceeded Prune Quantum, pruning tag trees\n"););
683         PruneTagCache(p->pkth->ts.tv_sec, 0);
684         last_prune_time = p->pkth->ts.tv_sec;
685     }
686 
687     if ( returned && create_event )
688         return 1;
689 
690     return 0;
691 }
692 
PruneTagCache(uint32_t thetime,int mustdie)693 static int PruneTagCache(uint32_t thetime, int mustdie)
694 {
695     int pruned = 0;
696 
697     if (mustdie == 0)
698     {
699         if(sfxhash_count(ssn_tag_cache_ptr) != 0)
700         {
701             pruned = PruneTime(ssn_tag_cache_ptr, thetime);
702         }
703 
704         if(sfxhash_count(host_tag_cache_ptr) != 0)
705         {
706             pruned += PruneTime(host_tag_cache_ptr, thetime);
707         }
708     }
709     else
710     {
711         TagNode *lru_node = NULL;
712 
713         while (pruned < mustdie &&
714                (sfxhash_count(ssn_tag_cache_ptr) > 0 || sfxhash_count(host_tag_cache_ptr) > 0))
715         {
716             if ((lru_node = (TagNode *)sfxhash_lru(ssn_tag_cache_ptr)) != NULL)
717             {
718                 if (sfxhash_remove(ssn_tag_cache_ptr, lru_node) != SFXHASH_OK)
719                 {
720                     LogMessage("WARNING: failed to remove tagNode from hash.\n");
721                 }
722                 pruned++;
723             }
724             if ((lru_node = (TagNode *)sfxhash_lru(host_tag_cache_ptr)) != NULL)
725             {
726                 if (sfxhash_remove(host_tag_cache_ptr, lru_node) != SFXHASH_OK)
727                 {
728                     LogMessage("WARNING: failed to remove tagNode from hash.\n");
729                 }
730                 pruned++;
731             }
732         }
733     }
734 
735     return pruned;
736 }
737 
PruneTime(SFXHASH * tree,uint32_t thetime)738 static int PruneTime(SFXHASH* tree, uint32_t thetime)
739 {
740     int pruned = 0;
741     TagNode *lru_node = NULL;
742 
743     while ((lru_node = (TagNode *)sfxhash_lru(tree)) != NULL)
744     {
745         if ((lru_node->last_access + TAG_PRUNE_QUANTUM) < thetime)
746         {
747             if (sfxhash_remove(tree, lru_node) != SFXHASH_OK)
748             {
749                 LogMessage("WARNING: failed to remove tagNode from hash.\n");
750             }
751             pruned++;
752         }
753         else
754         {
755             break;
756         }
757     }
758 
759     return pruned;
760 }
761 
SetTags(Packet * p,OptTreeNode * otn,RuleTreeNode * rtn,uint16_t event_id)762 void SetTags(Packet *p, OptTreeNode *otn, RuleTreeNode *rtn, uint16_t event_id)
763 {
764    DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "Setting tags\n"););
765 
766     if(otn != NULL && otn->tag != NULL)
767     {
768         if (otn->tag->tag_type != 0)
769         {
770             void* log_list = rtn ? rtn->listhead : NULL;
771 
772             switch(otn->tag->tag_type)
773             {
774                 case TAG_SESSION:
775                     DEBUG_WRAP(DebugMessage(DEBUG_FLOW,"Setting session tag:\n");
776 			            DebugMessage(DEBUG_FLOW,"SIP: %s  SP: %d   ",
777                             sfip_ntoa(GET_SRC_IP(p)), p->sp);
778                         DebugMessage(DEBUG_FLOW,"DIP: %s  DP: %d\n",
779 					        sfip_ntoa(GET_DST_IP(p)),p->dp););
780                     TagSession(p, otn->tag, p->pkth->ts.tv_sec, event_id, log_list);
781                     break;
782                 case TAG_HOST:
783                     DEBUG_WRAP(DebugMessage(DEBUG_FLOW,"Setting host tag:\n");
784     			        DebugMessage(DEBUG_FLOW,"SIP: %s  SP: %d   ",
785 	    			        sfip_ntoa(GET_SRC_IP(p)),p->sp);
786                         DebugMessage(DEBUG_FLOW, "DIP: %s  DP: %d\n",
787                             sfip_ntoa(GET_DST_IP(p)),p->dp););
788                     TagHost(p, otn->tag, p->pkth->ts.tv_sec, event_id, log_list);
789                     break;
790 
791                 default:
792                     LogMessage("WARNING: Trying to tag with unknown "
793                             "tag type.\n");
794                     break;
795             }
796         }
797     }
798 
799     return;
800 }
801 
802