1 //--------------------------------------------------------------------------
2 // Copyright (C) 2015-2021 Cisco and/or its affiliates. All rights reserved.
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License Version 2 as published
6 // by the Free Software Foundation.  You may not use, modify or distribute
7 // this program under any other version of the GNU General Public License.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 //--------------------------------------------------------------------------
18 // connector_manager.cc author Ed Borgoyn <eborgoyn@cisco.com>
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include "connector_manager.h"
25 
26 #include <cassert>
27 #include <list>
28 #include <map>
29 #include <unordered_map>
30 
31 #include "framework/connector.h"
32 #include "log/messages.h"
33 #include "utils/util.h"
34 
35 using namespace snort;
36 
37 //  ConnectorManager Private Data
38 
39 // One ConnectorElem for each Connector within the ConnectorCommon configuration
40 struct ConnectorElem
41 {
42     ConnectorConfig* config;
43     std::unordered_map<pid_t, Connector*> thread_connectors;
44 };
45 
46 // One ConnectorCommonElem created for each ConnectorCommon configured
47 struct ConnectorCommonElem
48 {
49     const ConnectorApi* api;
50     ConnectorCommon* connector_common;
51     std::map<std::string, ConnectorElem*> connectors;
52 
ConnectorCommonElemConnectorCommonElem53     ConnectorCommonElem(const ConnectorApi* p)
54     {
55         api = p;
56         connector_common = nullptr;
57     }
58 };
59 
60 typedef std::list<ConnectorCommonElem> CList;
61 static CList s_connector_commons;
62 
63 //-------------------------------------------------------------------------
64 
add_plugin(const ConnectorApi * api)65 void ConnectorManager::add_plugin(const ConnectorApi* api)
66 {
67     if ( api->pinit )
68         api->pinit();
69 }
70 
dump_plugins()71 void ConnectorManager::dump_plugins()
72 {
73     Dumper d("Connectors");
74 
75     for ( auto& sc : s_connector_commons )
76         d.dump(sc.api->base.name, sc.api->base.version);
77 }
78 
release_plugins()79 void ConnectorManager::release_plugins()
80 {
81     for ( auto& sc : s_connector_commons )
82     {
83         if ( sc.api->dtor )
84             sc.api->dtor(sc.connector_common);
85 
86         for ( auto& conn : sc.connectors )
87             delete conn.second;
88 
89         sc.connectors.clear();
90 
91         if ( sc.api->pterm )
92             sc.api->pterm();
93     }
94 
95     s_connector_commons.clear();
96 }
97 
get_connector(const std::string & connector_name)98 Connector* ConnectorManager::get_connector(const std::string& connector_name)
99 {
100     for ( auto& sc : s_connector_commons )
101     {
102         pid_t tid = gettid();
103         if ( sc.connectors.count(connector_name) > 0 )
104         {
105             ConnectorElem* map = sc.connectors[connector_name];
106             if ( map->thread_connectors.count(tid) == 1 )
107                 return ( map->thread_connectors[tid] );
108         }
109     }
110     return ( nullptr );
111 }
112 
thread_init()113 void ConnectorManager::thread_init()
114 {
115     pid_t tid = gettid();
116 
117     for ( auto& sc : s_connector_commons )
118     {
119         if ( sc.api->tinit )
120         {
121             for ( auto& conn : sc.connectors )
122             {
123                 /* There must NOT be a connector for this thread present. */
124                 assert(conn.second->thread_connectors.count(tid) == 0);
125 
126                 Connector* connector = sc.api->tinit(conn.second->config);
127                 conn.second->thread_connectors.emplace(tid, std::move(connector));
128             }
129         }
130     }
131 }
132 
thread_term()133 void ConnectorManager::thread_term()
134 {
135     pid_t tid = gettid();
136 
137     for ( auto& sc : s_connector_commons )
138     {
139         if ( sc.api->tterm )
140         {
141             for ( auto& conn : sc.connectors )
142             {
143                 /* There must be a connector for this thread present. */
144                 assert(conn.second->thread_connectors.count(tid) != 0);
145 
146                 sc.api->tterm(conn.second->thread_connectors[tid]);
147 
148                 conn.second->thread_connectors.clear();
149             }
150         }
151     }
152 }
153 
instantiate(const ConnectorApi * api,Module * mod,SnortConfig *)154 void ConnectorManager::instantiate(const ConnectorApi* api, Module* mod, SnortConfig*)
155 {
156     assert(mod);
157     ConnectorCommonElem c(api);
158 
159     ConnectorCommon* connector_common = api->ctor(mod);
160     assert(connector_common);
161 
162     c.connector_common = connector_common;
163     ConnectorConfig::ConfigSet* config_set = connector_common->config_set;
164 
165     // iterate through the config_set and create the connector entries
166     for ( auto cfg : *config_set )
167     {
168         ConnectorElem* connector_elem = new ConnectorElem;
169         connector_elem->config = &*cfg;
170         c.connectors.emplace(cfg->connector_name, std::move(connector_elem));
171     }
172 
173     s_connector_commons.emplace_back(c);
174 }
175 
176