00001 //--------------------------------------------------------------------------
00002 // Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
00003 // Copyright (C) 2013-2013 Sourcefire, Inc.
00004 //
00005 // This program is free software; you can redistribute it and/or modify it
00006 // under the terms of the GNU General Public License Version 2 as published
00007 // by the Free Software Foundation. You may not use, modify or distribute
00008 // this program under any other version of the GNU General Public License.
00009 //
00010 // This program is distributed in the hope that it will be useful, but
00011 // WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License along
00016 // with this program; if not, write to the Free Software Foundation, Inc.,
00017 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018 //--------------------------------------------------------------------------
00019
00020 #ifdef HAVE_CONFIG_H
00021 #include "config.h"
00022 #endif
00023
00024 #include "parser.h"
00025
00026 #include <pcap.h>
00027
00028 #include <cassert>
00029 #include <iostream>
00030
00031 #include "detection/fp_config.h"
00032 #include "detection/sfrim.h"
00033 #include "filters/detection_filter.h"
00034 #include "filters/rate_filter.h"
00035 #include "filters/sfthreshold.h"
00036 #include "hash/sfhashfcn.h"
00037 #include "hash/sfxhash.h"
00038 #include "log/messages.h"
00039 #include "main/shell.h"
00040 #include "main/snort_config.h"
00041 #include "managers/event_manager.h"
00042 #include "managers/module_manager.h"
00043 #include "ports/port_object.h"
00044 #include "ports/port_table.h"
00045 #include "ports/rule_port_tables.h"
00046 #include "sfip/sf_ipvar.h"
00047 #include "target_based/snort_protocols.h"
00048 #include "utils/util.h"
00049 #include "utils/util_cstring.h"
00050
00051 #include "config_file.h"
00052 #include "mstring.h"
00053 #include "parse_conf.h"
00054 #include "parse_rule.h"
00055 #include "parse_stream.h"
00056 #include "vars.h"
00057
00058 static struct rule_index_map_t* ruleIndexMap = nullptr;
00059
00060 static std::string s_aux_rules;
00061
00062 void parser_append_rules(const char* s)
00063 {
00064 s_aux_rules += s;
00065 s_aux_rules += "\n";
00066 }
00067
00068 //-------------------------------------------------------------------------
00069 // private / implementation methods
00070 //-------------------------------------------------------------------------
00071
00072 void parser_init()
00073 {
00074 parse_rule_init();
00075
00076 ruleIndexMap = RuleIndexMapCreate();
00077
00078 if ( !ruleIndexMap )
00079 ParseAbort("failed to create rule index map.");
00080 }
00081
00082 void parser_term(SnortConfig* sc)
00083 {
00084 parse_rule_term();
00085 RuleIndexMapFree(ruleIndexMap);
00086 ruleIndexMap = nullptr;
00087 sc->free_rule_state_list();
00088 }
00089
00090 static void CreateDefaultRules(SnortConfig* sc)
00091 {
00092 CreateRuleType(sc, ACTION_LOG, RULE_TYPE__LOG);
00093 CreateRuleType(sc, ACTION_PASS, RULE_TYPE__PASS);
00094 CreateRuleType(sc, ACTION_ALERT, RULE_TYPE__ALERT);
00095 CreateRuleType(sc, ACTION_DROP, RULE_TYPE__DROP);
00096 CreateRuleType(sc, ACTION_BLOCK, RULE_TYPE__BLOCK);
00097 CreateRuleType(sc, ACTION_RESET, RULE_TYPE__RESET);
00098 }
00099
00100 static void FreeRuleTreeNodes(SnortConfig* sc)
00101 {
00102 RuleTreeNode* rtn;
00103 OptTreeNode* otn;
00104 PolicyId policyId;
00105 SFGHASH_NODE* hashNode;
00106
00107 if (sc->otn_map == nullptr)
00108 return;
00109
00110 for (hashNode = sfghash_findfirst(sc->otn_map);
00111 hashNode;
00112 hashNode = sfghash_findnext(sc->otn_map))
00113 {
00114 otn = (OptTreeNode*)hashNode->data;
00115
00116 /* Autogenerated OTNs along with their respective pseudo RTN
00117 * will get cleaned up when the OTN is freed */
00118 if (otn->generated)
00119 continue;
00120
00121 for (policyId = 0;
00122 policyId < otn->proto_node_num;
00123 policyId++)
00124 {
00125 rtn = getRtnFromOtn(otn, policyId);
00126 DestroyRuleTreeNode(rtn);
00127
00128 otn->proto_nodes[policyId] = nullptr;
00129 }
00130 }
00131 }
00132
00133 static void FreeOutputLists(ListHead* list)
00134 {
00135 if ( list->AlertList )
00136 EventManager::release_outputs(list->AlertList);
00137
00138 if ( list->LogList )
00139 EventManager::release_outputs(list->LogList);
00140 }
00141
00142 /* Finish processing/setup Port Tables */
00143 static void finish_portlist_table(FastPatternConfig* fp, const char* s, PortTable* pt)
00144 {
00145 PortTableSortUniqRules(pt);
00146
00147 if ( fp->get_debug_print_rule_groups_uncompiled() )
00148 {
00149 LogMessage("***\n***Port-Table : %s Ports/Rules-UnCompiled\n",s);
00150 PortTablePrintInputEx(pt, rule_index_map_print_index);
00151 }
00152
00153 PortTableCompile(pt);
00154
00155 if ( fp->get_debug_print_rule_groups_compiled() )
00156 {
00157 LogMessage("***\n***Port-Table : %s Ports/Rules-Compiled\n",s);
00158 PortTablePrintCompiledEx(pt, rule_index_map_print_index);
00159 LogMessage("*** End of Compiled Group\n");
00160 }
00161 }
00162
00163 static void PortTablesFinish(RulePortTables* port_tables, FastPatternConfig* fp)
00164 {
00165 if ( fp->get_debug_print_rule_groups_compiled() )
00166 {
00167 LogMessage("IP-Any-Any Port List\n");
00168 PortObjectPrintEx(port_tables->ip.any, rule_index_map_print_index);
00169 }
00170
00171 finish_portlist_table(fp, "ip src", port_tables->ip.src);
00172 finish_portlist_table(fp, "ip dst", port_tables->ip.dst);
00173
00174 if ( fp->get_debug_print_rule_groups_compiled() )
00175 {
00176 LogMessage("*** ICMP-Any-Any Port List\n");
00177 PortObjectPrintEx(port_tables->icmp.any, rule_index_map_print_index);
00178 }
00179
00180 finish_portlist_table(fp, "icmp src", port_tables->icmp.src);
00181 finish_portlist_table(fp, "icmp dst", port_tables->icmp.dst);
00182
00183 if ( fp->get_debug_print_rule_groups_compiled() )
00184 {
00185 LogMessage("*** TCP-Any-Any Port List\n");
00186 PortObjectPrintEx(port_tables->tcp.any, rule_index_map_print_index);
00187 }
00188
00189 finish_portlist_table(fp, "tcp src", port_tables->tcp.src);
00190 finish_portlist_table(fp, "tcp dst", port_tables->tcp.dst);
00191
00192 if ( fp->get_debug_print_rule_groups_compiled() )
00193 {
00194 LogMessage("*** UDP-Any-Any Port List\n");
00195 PortObjectPrintEx(port_tables->udp.any, rule_index_map_print_index);
00196 }
00197
00198 finish_portlist_table(fp, "udp src", port_tables->udp.src);
00199 finish_portlist_table(fp, "udp dst", port_tables->udp.dst);
00200
00201 if ( fp->get_debug_print_rule_groups_compiled() )
00202 {
00203 LogMessage("*** SVC-Any-Any Port List\n");
00204 PortObjectPrintEx(port_tables->svc_any, rule_index_map_print_index);
00205 }
00206
00207 RuleListSortUniq(port_tables->ip.any->rule_list);
00208 RuleListSortUniq(port_tables->icmp.any->rule_list);
00209 RuleListSortUniq(port_tables->tcp.any->rule_list);
00210 RuleListSortUniq(port_tables->udp.any->rule_list);
00211 RuleListSortUniq(port_tables->svc_any->rule_list);
00212
00213 RuleListSortUniq(port_tables->ip.nfp->rule_list);
00214 RuleListSortUniq(port_tables->icmp.nfp->rule_list);
00215 RuleListSortUniq(port_tables->tcp.nfp->rule_list);
00216 RuleListSortUniq(port_tables->udp.nfp->rule_list);
00217 }
00218
00219 static void OtnInit(SnortConfig* sc)
00220 {
00221 if (sc == nullptr)
00222 return;
00223
00224 /* Don't initialize this more than once */
00225 if ( sc->otn_map != nullptr )
00226 return;
00227
00228 /* Init sid-gid -> otn map */
00229 sc->otn_map = OtnLookupNew();
00230 if (sc->otn_map == nullptr)
00231 ParseAbort("ParseRulesFile otn_map sfghash_new failed.");
00232 }
00233
00234 #define IFACE_VARS_MAX 128
00235 typedef struct iface_var
00236 {
00237 char name[128];
00238 uint32_t net;
00239 uint32_t netmask;
00240 } iface_var_t;
00241
00242 /****************************************************************************
00243 *
00244 * Function : DefineIfaceVar()
00245 * Purpose : Assign network address and network mask to IFACE_ADDR_VARNAME
00246 * variable.
00247 * Arguments : interface name (string) netaddress and netmask (4 octets each)
00248 * Returns : void function
00249 *
00250 ****************************************************************************/
00251 static void DefineIfaceVar(SnortConfig* sc, char* iname, const uint8_t* network, const uint8_t* netmask)
00252 {
00253 char valbuf[32];
00254 char varbuf[BUFSIZ];
00255
00256 if ((network == nullptr) || (*network == 0))
00257 return;
00258
00259 SnortSnprintf(varbuf, BUFSIZ, "%s_ADDRESS", iname);
00260
00261 SnortSnprintf(valbuf, 32, "%d.%d.%d.%d/%d.%d.%d.%d",
00262 network[0] & 0xff, network[1] & 0xff, network[2] & 0xff,
00263 network[3] & 0xff, netmask[0] & 0xff, netmask[1] & 0xff,
00264 netmask[2] & 0xff, netmask[3] & 0xff);
00265
00266 VarDefine(sc, varbuf, valbuf);
00267 }
00268
00269 /****************************************************************************
00270 *
00271 * Function : DefineAllIfaceVars()
00272 * Purpose : Find all up interfaces and define iface_ADDRESS vars for them
00273 * Arguments : none
00274 * Returns : void function
00275 *
00276 ****************************************************************************/
00277 static void DefineAllIfaceVars(SnortConfig* sc)
00278 {
00279
00280 // FIXIT-L don't come back here on reload unless we are going to find
00281 // new ifaces. Cache retrieved devs so if user is running with dropped
00282 // privs and does a reload, we can use previous values
00283 static int num_vars = 0;
00284
00285 // should be more than enough to cover the number of interfaces on a machine
00286 static iface_var_t iface_vars[IFACE_VARS_MAX];
00287
00288 if (num_vars > 0)
00289 {
00290 int i;
00291
00292 for (i = 0; i < num_vars; i++)
00293 {
00294 DefineIfaceVar(sc, iface_vars[i].name,
00295 (uint8_t*)&iface_vars[i].net,
00296 (uint8_t*)&iface_vars[i].netmask);
00297 }
00298 }
00299 else
00300 {
00301 char errbuf[PCAP_ERRBUF_SIZE];
00302 pcap_if_t* alldevs;
00303 pcap_if_t* dev;
00304 bpf_u_int32 net, netmask;
00305
00306 if (pcap_findalldevs(&alldevs, errbuf) == -1)
00307 return;
00308
00309 for (dev = alldevs; dev != nullptr; dev = dev->next)
00310 {
00311 if (pcap_lookupnet(dev->name, &net, &netmask, errbuf) == 0)
00312 {
00313 /* We've hit the maximum variables we can cache */
00314 if (num_vars >= IFACE_VARS_MAX)
00315 break;
00316
00317 SnortSnprintf(iface_vars[num_vars].name,
00318 sizeof(iface_vars[num_vars].name), "%s", dev->name);
00319
00320 DefineIfaceVar(sc, iface_vars[num_vars].name,
00321 (uint8_t*)&net,
00322 (uint8_t*)&netmask);
00323
00324 iface_vars[num_vars].net = net;
00325 iface_vars[num_vars].netmask = netmask;
00326 num_vars++;
00327 }
00328 }
00329
00330 pcap_freealldevs(alldevs);
00331 }
00332 }
00333
00334 static RuleListNode* addNodeToOrderedList(RuleListNode* ordered_list,
00335 RuleListNode* node, int evalIndex)
00336 {
00337 RuleListNode* prev;
00338
00339 prev = ordered_list;
00340
00341 /* set the eval order for this rule set */
00342 node->evalIndex = evalIndex;
00343
00344 if (!prev)
00345 {
00346 ordered_list = node;
00347 }
00348 else
00349 {
00350 while (prev->next)
00351 prev = prev->next;
00352 prev->next = node;
00353 }
00354
00355 node->next = nullptr;
00356
00357 return ordered_list;
00358 }
00359
00360 static void printRuleListOrder(RuleListNode* node)
00361 {
00362 char buf[STD_BUF];
00363 RuleListNode* first_node = node;
00364
00365 SnortSnprintf(buf, STD_BUF, "Rule application order: ");
00366
00367 while ( node != nullptr )
00368 {
00369 SnortSnprintfAppend(buf, STD_BUF, "%s%s",
00370 node == first_node ? "" : "->", node->name);
00371
00372 node = node->next;
00373 }
00374
00375 LogMessage("%s\n", buf);
00376 }
00377
00378 static void parse_file(SnortConfig* sc, Shell* sh)
00379 {
00380 const char* fname = sh->get_file();
00381
00382 if ( !fname || !*fname )
00383 return;
00384
00385 push_parse_location(fname, 0);
00386 sh->configure(sc);
00387 pop_parse_location();
00388 }
00389
00390 //-------------------------------------------------------------------------
00391 // public methods
00392 //-------------------------------------------------------------------------
00393
00394 /****************************************************************************
00395 * Function: ParseSnortConf()
00396 *
00397 * Read the rules file a line at a time and send each rule to the rule parser
00398 * This is the first pass of the configuration file. It parses everything
00399 * except the rules.
00400 *
00401 * Arguments: None
00402 *
00403 * Returns:
00404 * SnortConfig *
00405 * An initialized and configured snort configuration struct.
00406 * This struct should be passed on the second pass of the
00407 * configuration file to parse the rules.
00408 *
00409 ***************************************************************************/
00410 SnortConfig* ParseSnortConf(const SnortConfig* boot_conf, const char* fname)
00411 {
00412 SnortConfig* sc = new SnortConfig;
00413
00414 sc->logging_flags = boot_conf->logging_flags;
00415 VarNode* tmp = boot_conf->var_list;
00416
00417 if ( !fname )
00418 fname = get_snort_conf();
00419
00420 if ( !fname )
00421 fname = "";
00422
00423 CreateDefaultRules(sc);
00424
00425 sc->port_tables = PortTablesNew();
00426
00427 OtnInit(sc);
00428
00429 sc->fast_pattern_config = new FastPatternConfig();
00430 sc->event_queue_config = EventQueueConfigNew();
00431 sc->threshold_config = ThresholdConfigNew();
00432 sc->rate_filter_config = RateFilter_ConfigNew();
00433 sc->detection_filter_config = DetectionFilterConfigNew();
00434
00435 /* If snort is not run with root privileges, no interfaces will be defined,
00436 * so user beware if an iface_ADDRESS variable is used in snort.conf and
00437 * snort is not run as root (even if just in read mode) */
00438 DefineAllIfaceVars(sc);
00439
00440 /* Add command line defined variables - duplicates will already
00441 * have been resolved */
00442 while (tmp != nullptr)
00443 {
00444 AddVarToTable(sc, tmp->name, tmp->value);
00445 tmp = tmp->next;
00446 }
00447
00448 // get overrides from cmd line
00449 Shell* sh = boot_conf->policy_map->get_shell();
00450 sc->policy_map->get_shell()->set_overrides(sh);
00451
00452 if ( *fname )
00453 {
00454 sh = sc->policy_map->get_shell();
00455 sh->set_file(fname);
00456 }
00457
00458 for ( unsigned i = 0; true; i++ )
00459 {
00460 sh = sc->policy_map->get_shell(i);
00461
00462 if ( !sh )
00463 break;
00464
00465 set_policies(sc, sh);
00466 parse_file(sc, sh);
00467 }
00468 set_default_policy(sc);
00469 return sc;
00470 }
00471
00472 void FreeRuleTreeNode(RuleTreeNode* rtn)
00473 {
00474 RuleFpList* idx, * tmp;
00475 if (!rtn)
00476 return;
00477
00478 if (rtn->sip)
00479 {
00480 sfvar_free(rtn->sip);
00481 }
00482
00483 if (rtn->dip)
00484 {
00485 sfvar_free(rtn->dip);
00486 }
00487
00488 idx = rtn->rule_func;
00489 while (idx)
00490 {
00491 tmp = idx;
00492 idx = idx->next;
00493 snort_free(tmp);
00494 }
00495 }
00496
00497 void DestroyRuleTreeNode(RuleTreeNode* rtn)
00498 {
00499 if (!rtn)
00500 return;
00501
00502 rtn->otnRefCount--;
00503 if (rtn->otnRefCount != 0)
00504 return;
00505
00506 FreeRuleTreeNode(rtn);
00507
00508 snort_free(rtn);
00509 }
00510
00511 /****************************************************************************
00512 * Purpose: Adjust the information for a given rule
00513 * relative to the Rule State list
00514 *****************************************************************************/
00515 void SetRuleStates(SnortConfig* sc)
00516 {
00517 RuleState* rule_state;
00518
00519 if (sc == nullptr)
00520 return;
00521
00522 /* First, cycle through the rule state list and update the
00523 * rule state for each one we find. */
00524 for (rule_state = sc->rule_state_list; rule_state != nullptr; rule_state = rule_state->next)
00525 {
00526 /* Lookup the OTN by ruleState->sid, ruleState->gid */
00527 OptTreeNode* otn = OtnLookup(sc->otn_map, rule_state->gid, rule_state->sid);
00528
00529 if (otn == nullptr)
00530 {
00531 ParseError("Rule state specified for invalid SID: %u GID: %u",
00532 rule_state->sid, rule_state->gid);
00533 return;
00534 }
00535
00536 otn->enabled = rule_state->state;
00537 }
00538 }
00539
00540 void ParseRules(SnortConfig* sc)
00541 {
00542 for ( unsigned idx = 0; idx < sc->policy_map->ips_policy.size(); ++idx )
00543 {
00544 set_ips_policy(sc, idx);
00545 IpsPolicy* p = sc->policy_map->ips_policy[idx];
00546
00547 if ( p->enable_builtin_rules )
00548 ModuleManager::load_rules(sc);
00549
00550 const char* fname = p->include.c_str();
00551
00552 if ( fname && *fname )
00553 {
00554 push_parse_location(fname);
00555 ParseConfigFile(sc, fname);
00556 pop_parse_location();
00557 }
00558
00559 if ( !idx )
00560 p->rules += s_aux_rules;
00561
00562 if ( !p->rules.empty() )
00563 {
00564 push_parse_location("rules");
00565 ParseConfigString(sc, p->rules.c_str());
00566 pop_parse_location();
00567 }
00568 if ( !idx && sc->stdin_rules )
00569 {
00570 LogMessage("Reading rules until EOF or a line starting with END\n");
00571 push_parse_location("stdin");
00572 parse_stream(std::cin, sc);
00573 pop_parse_location();
00574 }
00575 }
00576
00577 /* Compile/Finish and Print the PortList Tables */
00578 PortTablesFinish(sc->port_tables, sc->fast_pattern_config);
00579
00580 parse_rule_print();
00581 }
00582
00583 /****************************************************************************
00584 *
00585 * Function: CreateRuleType
00586 *
00587 * Purpose: Creates a new type of rule and adds it to the end of the rule list
00588 *
00589 * Arguments: name = name of this rule type
00590 * mode = the mode for this rule type
00591 * rval = return value for this rule type (for detect events)
00592 *
00593 * Returns: the ListHead for the rule type
00594 *
00595 ***************************************************************************/
00596 ListHead* CreateRuleType(SnortConfig* sc, const char* name, RuleType mode)
00597 {
00598 RuleListNode* node;
00599 int evalIndex = 0;
00600
00601 if (sc == nullptr)
00602 return nullptr;
00603
00604 node = (RuleListNode*)snort_calloc(sizeof(RuleListNode));
00605
00606 /* If this is the first rule list node, then we need to
00607 * create a new list. */
00608 if (sc->rule_lists == nullptr)
00609 {
00610 sc->rule_lists = node;
00611 }
00612 else
00613 {
00614 RuleListNode* tmp = sc->rule_lists;
00615 RuleListNode* last;
00616
00617 do
00618 {
00619 /* We do not allow multiple rules types with the same name. */
00620 if (strcasecmp(tmp->name, name) == 0)
00621 {
00622 snort_free(node);
00623 return nullptr;
00624 }
00625
00626 evalIndex++;
00627 last = tmp;
00628 tmp = tmp->next;
00629 }
00630 while (tmp != nullptr);
00631
00632 last->next = node;
00633 }
00634
00635 node->RuleList = (ListHead*)snort_calloc(sizeof(ListHead));
00636 node->RuleList->ruleListNode = node;
00637 node->mode = mode;
00638 node->name = snort_strdup(name);
00639 node->evalIndex = evalIndex;
00640
00641 sc->evalOrder[node->mode] = evalIndex;
00642 sc->num_rule_types++;
00643
00644 return node->RuleList;
00645 }
00646
00647 void FreeRuleLists(SnortConfig* sc)
00648 {
00649 FreeRuleTreeNodes(sc);
00650
00651 RuleListNode* node = sc->rule_lists;
00652
00653 while (node != nullptr)
00654 {
00655 RuleListNode* tmp = node;
00656 node = node->next;
00657
00658 FreeOutputLists(tmp->RuleList);
00659 snort_free(tmp->RuleList);
00660
00661 if (tmp->name)
00662 snort_free(tmp->name);
00663
00664 snort_free(tmp);
00665 }
00666
00667 sc->rule_lists = nullptr;
00668 }
00669
00670 void PrintRuleOrder(RuleListNode* rule_lists)
00671 {
00672 printRuleListOrder(rule_lists);
00673 }
00674
00675 /****************************************************************************
00676 *
00677 * Function: OrderRuleLists
00678 *
00679 * Purpose: Orders the rule lists into the specified order.
00680 *
00681 * Returns: void function
00682 *
00683 ***************************************************************************/
00684 void OrderRuleLists(SnortConfig* sc, const char* order)
00685 {
00686 int i;
00687 int evalIndex = 0;
00688 RuleListNode* ordered_list = nullptr;
00689 RuleListNode* prev;
00690 RuleListNode* node;
00691 char** toks;
00692 int num_toks;
00693
00694 toks = mSplit(order, " \t", 0, &num_toks, 0);
00695
00696 for ( i = 0; i < num_toks; i++ )
00697 {
00698 prev = nullptr;
00699 node = sc->rule_lists;
00700
00701 while (node != nullptr)
00702 {
00703 if (strcmp(toks[i], node->name) == 0)
00704 {
00705 if (prev == nullptr)
00706 sc->rule_lists = node->next;
00707 else
00708 prev->next = node->next;
00709
00710 /* Add node to ordered list */
00711 ordered_list = addNodeToOrderedList(ordered_list, node, evalIndex++);
00712 sc->evalOrder[node->mode] = evalIndex;
00713
00714 break;
00715 }
00716 else
00717 {
00718 prev = node;
00719 node = node->next;
00720 }
00721 }
00722
00723 if ( node == nullptr )
00724 {
00725 ParseError("ruletype '%s' does not exist or "
00726 "has already been ordered.", toks[i]);
00727 return;
00728 }
00729 }
00730
00731 mSplitFree(&toks, num_toks);
00732
00733 /* anything left in the rule lists needs to be moved to the ordered lists */
00734 while (sc->rule_lists != nullptr)
00735 {
00736 node = sc->rule_lists;
00737 sc->rule_lists = node->next;
00738 /* Add node to ordered list */
00739 ordered_list = addNodeToOrderedList(ordered_list, node, evalIndex++);
00740 sc->evalOrder[node->mode] = evalIndex;
00741 }
00742
00743 /* set the rulelists to the ordered list */
00744 sc->rule_lists = ordered_list;
00745 }
00746
00747 /**Delete rtn from OTN.
00748 *
00749 * @param otn pointer to structure OptTreeNode.
00750 * @param policyId policy id
00751 *
00752 * @return pointer to deleted RTN, NULL otherwise.
00753 */
00754 RuleTreeNode* deleteRtnFromOtn(OptTreeNode* otn, PolicyId policyId, SnortConfig* sc, bool remove)
00755 {
00756 RuleTreeNode* rtn = nullptr;
00757
00758 if (otn->proto_nodes
00759 && (otn->proto_node_num >= (policyId+1)))
00760 {
00761 rtn = getRtnFromOtn(otn, policyId);
00762 otn->proto_nodes[policyId] = nullptr;
00763
00764 if ( remove && rtn )
00765 {
00766 RuleTreeNodeKey key{ rtn, policyId };
00767 if ( sc && sc->rtn_hash_table )
00768 sfxhash_remove(sc->rtn_hash_table, &key);
00769 }
00770
00771 return rtn;
00772 }
00773
00774 return nullptr;
00775 }
00776
00777 RuleTreeNode* deleteRtnFromOtn(OptTreeNode* otn, SnortConfig* sc)
00778 {
00779 return deleteRtnFromOtn(otn, get_ips_policy()->policy_id, sc);
00780 }
00781
00782 static uint32_t rtn_hash_func(SFHASHFCN*, const unsigned char *k, int)
00783 {
00784 uint32_t a,b,c;
00785 const RuleTreeNodeKey* rtnk = (const RuleTreeNodeKey*)k;
00786 RuleTreeNode* rtn = rtnk->rtn;
00787
00788 a = rtn->type;
00789 b = rtn->flags;
00790 c = (uint32_t)(uintptr_t)rtn->listhead;
00791
00792 mix(a,b,c);
00793
00794 a += (uint32_t)(uintptr_t)rtn->src_portobject;
00795 b += (uint32_t)(uintptr_t)rtn->dst_portobject;
00796 c += (uint32_t)(uintptr_t)rtnk->policyId;
00797
00798 finalize(a,b,c);
00799
00800 return c;
00801 }
00802
00803 static int rtn_compare_func(const void *k1, const void *k2, size_t)
00804 {
00805 const RuleTreeNodeKey* rtnk1 = (const RuleTreeNodeKey*)k1;
00806 const RuleTreeNodeKey* rtnk2 = (const RuleTreeNodeKey*)k2;
00807
00808 if (!rtnk1 || !rtnk2)
00809 return 1;
00810
00811 if (rtnk1->policyId != rtnk2->policyId)
00812 return 1;
00813
00814 if (same_headers(rtnk1->rtn, rtnk2->rtn))
00815 return 0;
00816
00817 return 1;
00818 }
00819
00820 /**Add RTN to OTN for a particular OTN.
00821 * @param otn pointer to structure OptTreeNode.
00822 * @param policyId policy id
00823 * @param rtn pointer to RuleTreeNode structure
00824 *
00825 * @return 0 if successful,
00826 * -ve otherwise
00827 */
00828 int addRtnToOtn(SnortConfig* sc, OptTreeNode* otn, RuleTreeNode* rtn, PolicyId policyId)
00829 {
00830 if (otn->proto_node_num <= policyId)
00831 {
00832 /* realloc the list, initialize missing elements to 0 and add
00833 * policyId */
00834 unsigned int numNodes = (policyId + 1);
00835 RuleTreeNode** tmpNodeArray =
00836 (RuleTreeNode**)snort_calloc(numNodes, sizeof(RuleTreeNode*));
00837
00838 /* copy original contents, the remaining elements are already
00839 * zeroed out by snort_calloc */
00840 if (otn->proto_nodes)
00841 {
00842 memcpy(tmpNodeArray, otn->proto_nodes,
00843 sizeof(RuleTreeNode*) * otn->proto_node_num);
00844 snort_free(otn->proto_nodes);
00845 }
00846
00847 otn->proto_node_num = numNodes;
00848 otn->proto_nodes = tmpNodeArray;
00849 }
00850
00851 //add policyId
00852 if (otn->proto_nodes[policyId])
00853 {
00854 DestroyRuleTreeNode(rtn);
00855 return -1;
00856 }
00857
00858 otn->proto_nodes[policyId] = rtn;
00859
00860 // Optimized for parsing only, this check avoids adding run time rtn
00861 if (!sc)
00862 return 0;
00863
00864 if (!sc->rtn_hash_table)
00865 {
00866 sc->rtn_hash_table = sfxhash_new(10000, sizeof(RuleTreeNodeKey), 0, 0, 0, nullptr, nullptr, 1);
00867
00868 if (sc->rtn_hash_table == nullptr)
00869 FatalError("Failed to create rule tree node hash table\n");
00870
00871 sfxhash_set_keyops(sc->rtn_hash_table, rtn_hash_func, rtn_compare_func);
00872 }
00873
00874 RuleTreeNodeKey key;
00875 memset(&key, 0, sizeof(key));
00876 key.rtn = rtn;
00877 key.policyId = policyId;
00878 sfxhash_add(sc->rtn_hash_table, &key, rtn);
00879
00880 return 0; //success
00881 }
00882
00883 int addRtnToOtn(SnortConfig*sc, OptTreeNode* otn, RuleTreeNode* rtn)
00884 {
00885 return addRtnToOtn(sc, otn, rtn, get_ips_policy()->policy_id);
00886 }
00887
00888 void rule_index_map_print_index(int index, char* buf, int bufsize)
00889 {
00890 unsigned gid, sid;
00891 parser_get_rule_ids(index, gid, sid);
00892 SnortSnprintfAppend(buf, bufsize, "%u:%u ", gid, sid);
00893 }
00894
00895 void parser_get_rule_ids(int idx, unsigned& gid, unsigned& sid)
00896 {
00897 assert(ruleIndexMap);
00898 RuleIndexMapGet(ruleIndexMap, idx, gid, sid);
00899 }
00900
00901 int parser_get_rule_index(unsigned gid, unsigned sid)
00902 {
00903 assert(ruleIndexMap);
00904 return RuleIndexMapAdd(ruleIndexMap, gid, sid);
00905 }
00906
END OF CODE