1 /****************************************************************************
2  *
3  * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
4  * Copyright (C) 2006-2013 Sourcefire, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License Version 2 as
8  * published by the Free Software Foundation.  You may not use, modify or
9  * distribute this program under any other version of the GNU General
10  * Public License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  *
21  ****************************************************************************/
22 
23 /*
24 **  $Id$
25 **
26 **  ppm.c
27 **
28 **  Packet Performance Monitor
29 **
30 **  Author: Marc Norton <mnorton@sourcefire.com>
31 **  Date: 10/2006
32 **
33 **  Usage:
34 *
35 *   config ppm: max-pkt-time usecs
36 *   config ppm: max-rule-time usecs
37 *   config ppm: max-suspend-time secs
38 *   config ppm: threshold count
39 *   config ppm: suspend-expensive-rules
40 *   config ppm: fastpath-expensive-packets
41 *   config ppm: pkt-events  syslog|console
42 *   config ppm: rule-events alert|syslog|console
43 *   config ppm: debug-rules
44 *   config ppm: debug-pkts
45 *
46 */
47 
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <syslog.h>
53 #include <time.h>
54 
55 #ifdef HAVE_CONFIG_H
56 #include "config.h"
57 #endif
58 
59 #include "snort.h"
60 #include "rules.h"
61 #include "treenodes.h"
62 #include "treenodes.h"
63 #include "decode.h"
64 #include "parser.h"
65 #include "plugin_enum.h"
66 #include "util.h"
67 #include "rules.h"
68 #include "treenodes.h"
69 #include "treenodes.h"
70 #include "fpcreate.h"
71 #include "event_queue.h"
72 #include "event_wrapper.h"
73 #include "log.h"
74 #include "ppm.h"
75 #include "sf_types.h"
76 #include "generators.h"
77 
78 #ifdef PPM_MGR
79 
80 #define PPM_BASE_SUSPEND_RULE_GID 1000
81 #define PPM_BASE_CLEAR_RULE_GID   2000
82 
83 #define PPM_DEFAULT_MAX_PKT_TICKS    0
84 #define PPM_DEFAULT_MAX_RULE_TICKS   0
85 #define PPM_DEFAULT_MAX_SUSP_SECS   60
86 #define PPM_DEFAULT_RULE_THRESHOLD   5
87 
88 PPM_TICKS ppm_tpu = 0; /* ticks per usec */
89 
90 ppm_pkt_timer_t   ppm_pkt_times[PPM_MAX_TIMERS];
91 ppm_pkt_timer_t  *ppm_pt = NULL;
92 unsigned int      ppm_pkt_index = 0;
93 ppm_rule_timer_t  ppm_rule_times[PPM_MAX_TIMERS];
94 ppm_rule_timer_t *ppm_rt = NULL;
95 unsigned int      ppm_rule_times_index = 0;
96 uint64_t            ppm_cur_time = 0;
97 
98 /* temporary flags */
99 int ppm_abort_this_pkt = 0;
100 int ppm_suspend_this_rule = 0;
101 
102 /* debug-pkts  data */
103 #define MAX_DP_NRULES 1000
104 typedef struct
105 {
106     uint64_t   pkt;
107     detection_option_tree_root_t * tree;
108     PPM_TICKS ticks;
109 
110 } ppm_rules_t;
111 
112 /* suspended rules */
113 static ppm_rules_t ppm_rules[MAX_DP_NRULES];
114 static int ppm_n_rules;
115 
116 /* cleared rules - re-enabled */
117 static detection_option_tree_root_t * ppm_crules[MAX_DP_NRULES];
118 static int ppm_n_crules;
119 
ppm_init_rules(void)120 void ppm_init_rules(void)
121 {
122     ppm_n_rules = 0;
123     ppm_n_crules = 0;
124 }
125 
ppm_set_rule(detection_option_tree_root_t * root,PPM_TICKS ticks)126 void ppm_set_rule(detection_option_tree_root_t * root,PPM_TICKS ticks)
127 {
128     if( ppm_n_rules < MAX_DP_NRULES )
129     {
130         ppm_rules[ppm_n_rules].tree=root;
131         ppm_rules[ppm_n_rules].ticks=ticks;
132         ppm_n_rules++;
133     }
134 }
135 
ppm_clear_rule(detection_option_tree_root_t * root)136 void ppm_clear_rule(detection_option_tree_root_t *root)
137 {
138     if( ppm_n_crules < MAX_DP_NRULES )
139     {
140         ppm_crules[ppm_n_crules++]=root;
141     }
142 }
143 
144 /*
145  * calc ticks per micro-secs in integer units
146  */
ppm_calc_ticks(void)147 static int ppm_calc_ticks(void)
148 {
149     ppm_tpu = (PPM_TICKS)get_ticks_per_usec();
150 
151     if( ppm_tpu == 0 )
152     {
153         return -1;
154     }
155 
156     return 0;
157 }
ppm_print_cfg(ppm_cfg_t * ppm_cfg)158 void ppm_print_cfg(ppm_cfg_t *ppm_cfg)
159 {
160     if (ppm_cfg == NULL)
161         return;
162 
163     if (!ppm_cfg->enabled)
164         return ;
165 
166     if( ppm_cfg->max_pkt_ticks )
167     {
168         LogMessage("\n");
169         LogMessage("Packet Performance Monitor Config:\n");
170         LogMessage("  ticks per usec  : %lu ticks\n",(unsigned long)ppm_tpu);
171 
172         LogMessage("  max packet time : %lu usecs\n",(unsigned long)(ppm_cfg->max_pkt_ticks/ppm_tpu));
173         LogMessage("  packet action   : ");
174         if( ppm_cfg->pkt_action )
175             LogMessage("fastpath-expensive-packets\n");
176         else
177             LogMessage("none\n");
178         LogMessage("  packet logging  : ");
179         if(ppm_cfg->pkt_log&PPM_LOG_ALERT) LogMessage("alert " );
180         if(ppm_cfg->pkt_log&PPM_LOG_MESSAGE) LogMessage("log ");
181         if(!ppm_cfg->pkt_log) LogMessage("none ");
182         LogMessage("\n");
183 #ifdef DEBUG
184         LogMessage("  debug-pkts      : %s\n",(ppm_cfg->debug_pkts)? "enabled":"disabled");
185 #endif
186     }
187 
188     if( ppm_cfg->max_rule_ticks)
189     {
190         LogMessage("\n");
191         LogMessage("Rule Performance Monitor Config:\n");
192         LogMessage("  ticks per usec  : %lu ticks\n",(unsigned long)ppm_tpu);
193 
194         LogMessage("  max rule time   : %lu usecs\n",(unsigned long)(ppm_cfg->max_rule_ticks/ppm_tpu));
195         LogMessage("  rule action     : ");
196         if( ppm_cfg->rule_action )
197         {
198             LogMessage("suspend-expensive-rules\n");
199             LogMessage("  rule threshold  : %u \n",(unsigned int)ppm_cfg->rule_threshold);
200         }
201         else
202             LogMessage("none\n");
203 
204 #ifdef PPM_TEST
205         /* use usecs instead of ticks for rule suspension during pcap playback */
206         LogMessage("  suspend timeout : %lu secs\n", (unsigned long)(ppm_cfg->max_suspend_ticks/((uint64_t)1000000)) );
207 #else
208         LogMessage("  suspend timeout : %lu secs\n", (unsigned long)(ppm_cfg->max_suspend_ticks/((uint64_t)ppm_tpu*1000000)) );
209 #endif
210         LogMessage("  rule logging    : ");
211         if(ppm_cfg->rule_log&PPM_LOG_ALERT) LogMessage("alert " );
212         if(ppm_cfg->rule_log&PPM_LOG_MESSAGE) LogMessage("log ");
213         if(!ppm_cfg->rule_log) LogMessage("none ");
214         LogMessage("\n");
215 #ifdef DEBUG
216         /*LogMessage("  debug-rules     : %s\n",(ppm_cfg->debug_rules)?"enabled":"disabled"); unsupported */
217 #endif
218     }
219 }
220 
221 static
print_rule(int proto,RuleTreeNode * r,OptTreeNode * o)222 int print_rule( int proto, RuleTreeNode * r, OptTreeNode * o )
223 {
224     if( o->rule_state != RULE_STATE_ENABLED )
225     {
226         //if( o->sigInfo.generator==1 || o->sigInfo.generator==3 )
227         LogMessage("   disabled gid=%u, sid=%u\n",o->sigInfo.generator,o->sigInfo.id);
228     }
229 
230     return 0;
231 }
232 
ppm_print_summary(ppm_cfg_t * ppm_cfg)233 void ppm_print_summary(ppm_cfg_t *ppm_cfg)
234 {
235     if (ppm_cfg == NULL)
236         return;
237 
238     if (!ppm_cfg->enabled)
239         return;
240 
241     LogMessage("===============================================================================\n");
242     if(ppm_cfg->max_pkt_ticks)
243     {
244         LogMessage("Packet Performance Summary:\n");
245 
246         LogMessage("   max packet time       : %g usecs\n",
247             ppm_ticks_to_usecs(ppm_cfg->max_pkt_ticks));
248 
249         LogMessage("   packet events         : %u\n",
250             (unsigned int)ppm_cfg->pkt_event_cnt);
251 
252         if( ppm_cfg->tot_pkts )
253             LogMessage("   avg pkt time          : %g usecs\n",
254                 ppm_ticks_to_usecs((PPM_TICKS)(ppm_cfg->tot_pkt_time/
255                     ppm_cfg->tot_pkts)));
256     }
257 
258     if(ppm_cfg->max_rule_ticks)
259     {
260         LogMessage("Rule Performance Summary:\n");
261 
262         LogMessage("   max rule time         : %lu usecs\n",
263             (unsigned long)(ppm_cfg->max_rule_ticks/ppm_tpu));
264 
265         LogMessage("   rule events           : %u\n",
266             (unsigned int)ppm_cfg->rule_event_cnt);
267 
268         if( ppm_cfg->tot_rules )
269             LogMessage("   avg rule time         : %g usecs\n",
270                 ppm_ticks_to_usecs((PPM_TICKS)(ppm_cfg->tot_rule_time/
271                     ppm_cfg->tot_rules)));
272 
273         if( ppm_cfg->tot_nc_rules )
274             LogMessage("   avg nc-rule time      : %g usecs\n",
275                 ppm_ticks_to_usecs((PPM_TICKS)(ppm_cfg->tot_nc_rule_time/
276                     ppm_cfg->tot_nc_rules)));
277 
278         if( ppm_cfg->tot_pcre_rules )
279             LogMessage("   avg nc-pcre-rule time : %g usecs\n",
280                 ppm_ticks_to_usecs((PPM_TICKS)(ppm_cfg->tot_pcre_rule_time/
281                     ppm_cfg->tot_pcre_rules)));
282 
283         fpWalkOtns( 0, print_rule );
284     }
285 }
286 
ppm_ticks_to_usecs(PPM_TICKS ticks)287 double ppm_ticks_to_usecs(PPM_TICKS ticks)
288 {
289     if (ppm_tpu > 0)
290         return (double)ticks / ppm_tpu;
291 
292     return 0.0;
293 }
294 
295 /*
296  *  Initialization
297  */
ppm_init(ppm_cfg_t * ppm_cfg)298 void ppm_init(ppm_cfg_t *ppm_cfg)
299 {
300     /* calc ticks per usec */
301     if (ppm_calc_ticks() == -1)
302         return;
303 
304     ppm_cfg->enabled = 1;
305 
306     ppm_cfg->max_pkt_ticks = PPM_DEFAULT_MAX_PKT_TICKS;
307     ppm_cfg->max_rule_ticks = PPM_DEFAULT_MAX_RULE_TICKS;
308 
309     /* use usecs instead of ticks for rule suspension during pcap playback */
310     ppm_cfg->max_suspend_ticks = (uint64_t)PPM_DEFAULT_MAX_SUSP_SECS * 1000000;
311 #ifndef PPM_TEST
312     ppm_cfg->max_suspend_ticks *= ppm_tpu;
313 #endif
314     ppm_cfg->rule_threshold = PPM_DEFAULT_RULE_THRESHOLD;
315 }
316 
317 /*
318  *  Logging functions - syslog and/or events
319  */
320 #define PPM_FMT_FASTPATH "PPM: Pkt-Event Pkt[" STDi64 "] used=%g usecs, %u rules, %u nc-rules tested, packet fastpathed (%s:%d -> %s:%d).\n"
321 #define PPM_FMT_PACKET   "PPM: Pkt-Event Pkt[" STDi64 "] used=%g usecs, %u rules, %u nc-rules tested (%s:%d -> %s:%d).\n"
322 
ppm_pkt_log(ppm_cfg_t * ppm_cfg,Packet * p)323 void ppm_pkt_log(ppm_cfg_t *ppm_cfg, Packet* p)
324 {
325     int filterEvent = 0;
326     if (!ppm_cfg->max_pkt_ticks)
327         return;
328 
329     ppm_cfg->pkt_event_cnt++;
330 
331     if (ppm_cfg->pkt_log & PPM_LOG_ALERT)
332     {
333         OptTreeNode* potn;
334         Event ev;
335 
336         /* make sure we have an otn already in our table for this event */
337         potn = OtnLookup(snort_conf->otn_map, GENERATOR_PPM, PPM_EVENT_PACKET_ABORTED);
338         if (potn == NULL)
339         {
340             /* have to make one */
341             potn = GenerateSnortEventOtn(GENERATOR_PPM, /* GID */
342                                          PPM_EVENT_PACKET_ABORTED, /* SID */
343                                          1, /* Rev */
344                                          0, /* classification */
345                                          3, /* priority (low) */
346                                          PPM_EVENT_PACKET_ABORTED_STR /* msg string */);
347 
348             if (potn == NULL)
349                 return;
350 
351             OtnLookupAdd(snort_conf->otn_map, potn);
352         }
353 
354         SetEvent(&ev,
355                  potn->sigInfo.generator, /* GID */
356                  potn->sigInfo.id, /* SID */
357                  potn->sigInfo.rev, /* Rev */
358                  potn->sigInfo.class_id, /* classification */
359                  potn->sigInfo.priority, /* priority (low) */
360 #if !defined(FEAT_OPEN_APPID)
361                  0);
362 #else /* defined(FEAT_OPEN_APPID) */
363                  0, NULL);
364 #endif /* defined(FEAT_OPEN_APPID) */
365 
366         if ( IPH_IS_VALID(p) )
367         {
368             filterEvent = sfthreshold_test(
369                         potn->event_data.sig_generator,
370                         potn->event_data.sig_id,
371                         GET_SRC_IP(p), GET_DST_IP(p),
372                         p->pkth->ts.tv_sec);
373         }
374         else
375         {
376             sfaddr_t cleared;
377             IP_CLEAR(cleared);
378 
379             filterEvent = sfthreshold_test(
380                         potn->event_data.sig_generator,
381                         potn->event_data.sig_id,
382                         IP_ARG(cleared), IP_ARG(cleared),
383                         p->pkth->ts.tv_sec);
384         }
385 
386         if(filterEvent < 0)
387             filterEvent = 0;
388         else
389             AlertAction(p, potn, NULL, &ev);
390     }
391 
392     if (ppm_cfg->pkt_log & PPM_LOG_MESSAGE)
393     {
394         char src[INET6_ADDRSTRLEN];
395         char dst[INET6_ADDRSTRLEN];
396 
397         sfaddr_t* addr = GET_SRC_IP(p);
398         sfip_ntop(addr, src, sizeof(src));
399 
400         addr = GET_DST_IP(p);
401         sfip_ntop(addr, dst, sizeof(dst));
402 
403         if (ppm_abort_this_pkt)
404         {
405             LogMessage(PPM_FMT_FASTPATH,
406                        ppm_pt->pktcnt,
407                        ppm_ticks_to_usecs((PPM_TICKS)ppm_pt->tot),
408                        ppm_pt->rule_tests, ppm_pt->nc_rule_tests,
409                        src, p->sp, dst, p->dp);
410         }
411         else
412         {
413             LogMessage(PPM_FMT_PACKET,
414                        ppm_pt->pktcnt,
415                        ppm_ticks_to_usecs((PPM_TICKS)ppm_pt->tot),
416                        ppm_pt->rule_tests, ppm_pt->nc_rule_tests,
417                        src, p->sp, dst, p->dp);
418         }
419     }
420 }
421 
422 #define PPM_FMT_SUS_PKT   "PPM: Rule-Event Pkt[" STDi64 "] suspended (%s:%d -> %s:%d).\n"
423 #define PPM_FMT_SUSPENDED "PPM: Rule-Event Pkt[" STDi64 "] address=0x%p used=%g usecs suspended %s\n"
424 #define PPM_FMT_REENABLED "PPM: Rule-Event Pkt[" STDi64 "] address=0x%p re-enabled %s\n"
425 
PPMGetOTN(uint32_t sid,const char * msg)426 static inline OptTreeNode * PPMGetOTN(uint32_t sid, const char *msg)
427 {
428     OptTreeNode *otn = OtnLookup(snort_conf->otn_map, GENERATOR_PPM, sid);
429 
430     if (otn == NULL)
431     {
432         otn = GenerateSnortEventOtn(GENERATOR_PPM, sid, 1, 0, 3, msg);
433         if (otn == NULL)
434             return NULL;
435 
436         OtnLookupAdd(snort_conf->otn_map, otn);
437     }
438     else
439     {
440         tSfPolicyId policy_id = getIpsRuntimePolicy();
441 
442         if ((getRtnFromOtn(otn, policy_id) == NULL)
443                 && (GenerateSnortEventRtn(otn, policy_id) == NULL))
444             return NULL;
445     }
446 
447     return otn;
448 }
449 
ppm_rule_log(ppm_cfg_t * ppm_cfg,uint64_t pktcnt,Packet * p)450 void ppm_rule_log(ppm_cfg_t *ppm_cfg, uint64_t pktcnt, Packet *p)
451 {
452     detection_option_tree_root_t *proot;
453     OptTreeNode *otn;
454     char timestamp[TIMEBUF_SIZE];
455     int filterEvent = 0;
456     *timestamp = '\0';
457 
458     if (!ppm_cfg->max_rule_ticks)
459         return ;
460 
461     if (ppm_n_crules)
462     {
463         if (ppm_cfg->rule_log & PPM_LOG_ALERT)
464         {
465             Event ev;
466 
467             otn = PPMGetOTN(PPM_EVENT_RULE_TREE_ENABLED,
468                     PPM_EVENT_RULE_TREE_ENABLED_STR);
469 
470             if (otn != NULL)
471             {
472                 const char *tmp = otn->sigInfo.message;
473 
474                 SetEvent(&ev,
475                         otn->sigInfo.generator, /* GID */
476                         otn->sigInfo.id, /* SID */
477                         otn->sigInfo.rev, /* Rev */
478                         otn->sigInfo.class_id, /* classification */
479                         otn->sigInfo.priority, /* priority (low) */
480 #if !defined(FEAT_OPEN_APPID)
481                         0);
482 #else /* defined(FEAT_OPEN_APPID) */
483                         0, NULL);
484 #endif /* defined(FEAT_OPEN_APPID) */
485 
486                 otn->sigInfo.message = PPM_EVENT_RULE_TREE_ENABLED_STR;
487                 if ( IPH_IS_VALID(p) )
488                 {
489                     filterEvent = sfthreshold_test(
490                                 otn->event_data.sig_generator,
491                                 otn->event_data.sig_id,
492                                 GET_SRC_IP(p), GET_DST_IP(p),
493                                 p->pkth->ts.tv_sec);
494                 }
495                 else
496                 {
497                     sfaddr_t cleared;
498                     IP_CLEAR(cleared);
499 
500                     filterEvent = sfthreshold_test(
501                                 otn->event_data.sig_generator,
502                                 otn->event_data.sig_id,
503                                 IP_ARG(cleared), IP_ARG(cleared),
504                                 p->pkth->ts.tv_sec);
505                 }
506 
507                 if(filterEvent < 0)
508                     filterEvent = 0;
509                 else
510                     AlertAction(p, otn, NULL, &ev);
511 
512                 otn->sigInfo.message = tmp;
513             }
514         }
515 
516         if (ppm_cfg->rule_log & PPM_LOG_MESSAGE)
517         {
518             int i;
519 
520             if(!*timestamp)
521                 ts_print((struct timeval*)&p->pkth->ts, timestamp);
522 
523             for (i=0; i< ppm_n_crules; i++)
524             {
525                 proot = ppm_crules[i];
526 
527                 LogMessage(PPM_FMT_REENABLED,
528                            pktcnt, (void*)proot, timestamp);
529             }
530         }
531 
532         ppm_n_crules = 0;
533     }
534 
535     if (ppm_n_rules)
536     {
537         if (ppm_cfg->rule_log & PPM_LOG_ALERT)
538         {
539             Event ev;
540 
541             otn = PPMGetOTN(PPM_EVENT_RULE_TREE_DISABLED,
542                     PPM_EVENT_RULE_TREE_DISABLED_STR);
543 
544             if (otn != NULL)
545             {
546                 const char *tmp = otn->sigInfo.message;
547 
548                 SetEvent(&ev,
549                         otn->sigInfo.generator, /* GID */
550                         otn->sigInfo.id, /* SID */
551                         otn->sigInfo.rev, /* Rev */
552                         otn->sigInfo.class_id, /* classification */
553                         otn->sigInfo.priority, /* priority (low) */
554 #if !defined(FEAT_OPEN_APPID)
555                         0);
556 #else /* defined(FEAT_OPEN_APPID) */
557                         0, NULL);
558 #endif /* defined(FEAT_OPEN_APPID) */
559 
560                 otn->sigInfo.message = PPM_EVENT_RULE_TREE_DISABLED_STR;
561                 if ( IPH_IS_VALID(p) )
562                 {
563                     filterEvent = sfthreshold_test(
564                                 otn->event_data.sig_generator,
565                                 otn->event_data.sig_id,
566                                 GET_SRC_IP(p), GET_DST_IP(p),
567                                 p->pkth->ts.tv_sec);
568                 }
569                 else
570                 {
571                     sfaddr_t cleared;
572                     IP_CLEAR(cleared);
573 
574                     filterEvent = sfthreshold_test(
575                                 otn->event_data.sig_generator,
576                                 otn->event_data.sig_id,
577                                 IP_ARG(cleared), IP_ARG(cleared),
578                                 p->pkth->ts.tv_sec);
579                 }
580 
581                 if(filterEvent < 0)
582                     filterEvent = 0;
583                 else
584                     AlertAction(p, otn, NULL, &ev);
585                 otn->sigInfo.message = tmp;
586             }
587         }
588 
589         if (ppm_cfg->rule_log & PPM_LOG_MESSAGE)
590         {
591             int i;
592             char src[INET6_ADDRSTRLEN];
593             char dst[INET6_ADDRSTRLEN];
594 
595             sfaddr_t* addr = GET_SRC_IP(p);
596             sfip_ntop(addr, src, sizeof(src));
597 
598             addr = GET_DST_IP(p);
599             sfip_ntop(addr, dst, sizeof(dst));
600 
601             LogMessage(PPM_FMT_SUS_PKT, pktcnt, src, p->sp, dst, p->dp);
602 
603             if(!*timestamp)
604                 ts_print((struct timeval*)&p->pkth->ts, timestamp);
605 
606             for (i=0; i< ppm_n_rules; i++)
607             {
608                 proot = ppm_rules[i].tree;
609 
610                 LogMessage(PPM_FMT_SUSPENDED,
611                            pktcnt, (void*)proot,
612                            ppm_ticks_to_usecs((PPM_TICKS)ppm_rules[i].ticks),
613                            timestamp);
614             }
615         }
616 
617         ppm_n_rules = 0;
618     }
619 }
620 
ppm_set_rule_event(ppm_cfg_t * ppm_cfg,detection_option_tree_root_t * root)621 void ppm_set_rule_event(ppm_cfg_t *ppm_cfg, detection_option_tree_root_t *root)
622 {
623     if (!ppm_cfg->max_rule_ticks)
624         return;
625 
626     ppm_cfg->rule_event_cnt++;
627 
628     if (ppm_cfg->rule_log && ppm_rt)
629         ppm_set_rule(root, ppm_rt->tot);
630 }
631 
ppm_clear_rule_event(ppm_cfg_t * ppm_cfg,detection_option_tree_root_t * root)632 void ppm_clear_rule_event(ppm_cfg_t *ppm_cfg, detection_option_tree_root_t *root)
633 {
634     if (!ppm_cfg->max_rule_ticks)
635         return;
636 
637     ppm_cfg->rule_event_cnt++;
638 
639     if (ppm_cfg->rule_log)
640         ppm_clear_rule(root);
641 }
642 
643 
644 /*
645  * Config functions
646  */
647 
ppm_set_pkt_action(ppm_cfg_t * ppm_cfg,int flag)648 void ppm_set_pkt_action(ppm_cfg_t *ppm_cfg, int flag)
649 {
650     ppm_cfg->pkt_action = flag;
651 }
652 
ppm_set_pkt_log(ppm_cfg_t * ppm_cfg,int flag)653 void ppm_set_pkt_log(ppm_cfg_t *ppm_cfg, int flag)
654 {
655     ppm_cfg->pkt_log |= flag;
656 }
657 
ppm_set_rule_action(ppm_cfg_t * ppm_cfg,int flag)658 void ppm_set_rule_action(ppm_cfg_t *ppm_cfg, int flag)
659 {
660     ppm_cfg->rule_action = flag;
661 }
662 
ppm_set_rule_log(ppm_cfg_t * ppm_cfg,int flag)663 void ppm_set_rule_log(ppm_cfg_t *ppm_cfg, int flag)
664 {
665     ppm_cfg->rule_log |= flag;
666 }
667 
ppm_set_max_pkt_time(ppm_cfg_t * ppm_cfg,PPM_USECS usecs)668 void ppm_set_max_pkt_time(ppm_cfg_t *ppm_cfg, PPM_USECS usecs)
669 {
670     ppm_cfg->max_pkt_ticks = usecs * ppm_tpu;
671 }
672 
ppm_set_max_rule_time(ppm_cfg_t * ppm_cfg,PPM_USECS usecs)673 void ppm_set_max_rule_time(ppm_cfg_t *ppm_cfg, PPM_USECS usecs)
674 {
675     ppm_cfg->max_rule_ticks = usecs * ppm_tpu;
676 }
677 
ppm_set_max_suspend_time(ppm_cfg_t * ppm_cfg,PPM_SECS secs)678 void ppm_set_max_suspend_time(ppm_cfg_t *ppm_cfg, PPM_SECS secs)
679 {
680     /* use usecs instead of ticks for rule suspension during pcap playback */
681     ppm_cfg->max_suspend_ticks = (uint64_t)secs * 1000000;
682 #ifndef PPM_TEST
683     ppm_cfg->max_suspend_ticks *= ppm_tpu;
684 #endif
685 }
686 
ppm_set_rule_threshold(ppm_cfg_t * ppm_cfg,unsigned int cnt)687 void ppm_set_rule_threshold(ppm_cfg_t *ppm_cfg, unsigned int cnt)
688 {
689     ppm_cfg->rule_threshold = cnt;
690 }
691 
692 #ifdef DEBUG
ppm_set_debug_rules(ppm_cfg_t * ppm_cfg,int flag)693 void ppm_set_debug_rules(ppm_cfg_t *ppm_cfg, int flag)
694 {
695     ppm_cfg->debug_rules = flag;
696 }
697 
ppm_set_debug_pkts(ppm_cfg_t * ppm_cfg,int flag)698 void ppm_set_debug_pkts(ppm_cfg_t *ppm_cfg, int flag)
699 {
700     ppm_cfg->debug_pkts = flag;
701 }
702 #endif
703 
704 #endif
705 
706