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