Line data Source code
1 : /*
2 : * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 :
7 : #include <sstream>
8 : #include <boost/make_shared.hpp>
9 : #include <boost/asio.hpp>
10 : #include <analytics/analytics_types.h>
11 : #include "base/regex.h"
12 : #include "analytics_types.h"
13 : #include "structured_syslog_config.h"
14 : #include "options.h"
15 : #include <base/logging.h>
16 : #include <boost/bind/bind.hpp>
17 : #include "rapidjson/document.h"
18 : #include "rapidjson/writer.h"
19 : #include "rapidjson/stringbuffer.h"
20 :
21 : using boost::regex_error;
22 : using contrail::regex;
23 : using contrail::regex_match;
24 : using contrail::regex_search;
25 : using namespace boost::placeholders;
26 :
27 11 : StructuredSyslogConfig::StructuredSyslogConfig(ConfigClientCollector *config_client, uint64_t structured_syslog_active_session_map_limit) {
28 11 : activeSessionConfigMapLIMIT = structured_syslog_active_session_map_limit;
29 11 : LOG(INFO, "StructuredSyslogConfig:Num of active session LIMIT in session config map: " << activeSessionConfigMapLIMIT);
30 11 : if (config_client) {
31 0 : config_client->RegisterConfigReceive("structured-systemlog", boost::bind(
32 : &StructuredSyslogConfig::ReceiveConfig, this, _1, _2));
33 : }
34 11 : }
35 :
36 11 : StructuredSyslogConfig::~StructuredSyslogConfig() {
37 11 : hostname_records_.erase(hostname_records_.begin(),
38 11 : hostname_records_.end());
39 11 : tenant_records_.erase(tenant_records_.begin(),
40 11 : tenant_records_.end());
41 11 : application_records_.erase(application_records_.begin(),
42 11 : application_records_.end());
43 11 : tenant_application_records_.erase(tenant_application_records_.begin(),
44 11 : tenant_application_records_.end());
45 11 : networks_map_.erase(networks_map_.begin(), networks_map_.end());
46 11 : session_config_map_.erase(session_config_map_.begin(),
47 11 : session_config_map_.end());
48 11 : }
49 :
50 :
51 : bool
52 0 : StructuredSyslogConfig::AddSyslogSessionCounter(const std::string session_unique_key,
53 : std::map<std::string, uint64_t> session_traffic_counters) {
54 : try {
55 0 : SyslogSessionConfig::iterator it = session_config_map_.find(session_unique_key);
56 0 : if (it != session_config_map_.end()) {
57 0 : LOG(DEBUG, "Session key found in session counter map.");
58 : }
59 : else {
60 0 : LOG(DEBUG, "Session key NOT found in session counter map.");
61 : //Put a Limit to num of session entries in the map.
62 0 : if(session_config_map_.size() >= activeSessionConfigMapLIMIT) {
63 0 : LOG(ERROR, "active sessions Config Map LIMIT reached. Current active session count: "<< session_config_map_.size());
64 0 : return false;
65 : }
66 : }
67 0 : LOG(DEBUG, "Adding/Replacing session traffic counters for session key " << session_unique_key);
68 0 : session_config_map_[session_unique_key] = session_traffic_counters;
69 0 : return true;
70 : }
71 0 : catch (std::exception &e) {
72 0 : LOG(ERROR, "Adding session traffic counters failed for session key: " << session_unique_key);
73 0 : return false;
74 0 : }
75 : }
76 :
77 : int
78 0 : StructuredSyslogConfig::RemoveSyslogSessionCounter(const std::string &session_unique_key) {
79 : try {
80 0 : LOG(DEBUG, "Removing Syslog Session Counter for " << session_unique_key);
81 0 : return session_config_map_.erase(session_unique_key);
82 : }
83 0 : catch (std::exception &e) {
84 0 : LOG(ERROR, "Removing session traffic counters failed for session key: " << session_unique_key);
85 0 : return 0;
86 0 : }
87 : }
88 :
89 : bool
90 0 : StructuredSyslogConfig::FetchSyslogSessionCounters(const std::string &session_unique_key,
91 : std::map<std::string, uint64_t> &session_traffic_counters) {
92 : try {
93 0 : SyslogSessionConfig::iterator itr = session_config_map_.find(session_unique_key);
94 0 : if (itr != session_config_map_.end()) {
95 0 : session_traffic_counters = itr->second;
96 0 : return true;
97 : }
98 : else{
99 0 : LOG(DEBUG, "Session counters not found for session key: " << session_unique_key);
100 0 : return false;
101 : }
102 : }
103 0 : catch (std::exception &e) {
104 0 : LOG(ERROR, "ERROR in fetching Session traffic counters for session key: " << session_unique_key);
105 0 : return false;
106 0 : }
107 : }
108 :
109 : /* Return int 4 when IP belongs to protocol IPv4 or
110 : Return int 6 when IP belongs to protocol IPv6, otherwise
111 : Return int -1 if IP is not valid */
112 : int
113 0 : StructuredSyslogConfig::get_ip_version (const std::string ip) {
114 0 : int version = -1;
115 : try {
116 0 : boost::asio::ip::address addr = boost::asio::ip::address::from_string(ip);
117 0 : if (addr.is_v4())
118 0 : version = 4;
119 0 : else if (addr.is_v6())
120 0 : version = 6;
121 : }
122 0 : catch (std::exception &e){
123 0 : LOG(ERROR, "IP : "<< ip <<" found while checking IP protocol is invalid. ERROR: " << e.what());
124 0 : }
125 0 : return version;
126 : }
127 :
128 : uint32_t
129 0 : StructuredSyslogConfig::IPToUInt(std::string ip) {
130 : int a, b, c, d;
131 0 : uint32_t addr = 0;
132 :
133 0 : if (sscanf(ip.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) != 4)
134 0 : return 0;
135 :
136 0 : addr = a << 24;
137 0 : addr |= b << 16;
138 0 : addr |= c << 8;
139 0 : addr |= d;
140 0 : return addr;
141 : }
142 :
143 : std::vector<std::string>
144 0 : StructuredSyslogConfig::split_into_vector(std::string str, char delimiter) {
145 0 : std::vector<std::string> list;
146 0 : std::stringstream ss(str);
147 0 : std::string s;
148 0 : while(getline(ss, s, delimiter)){
149 0 : list.push_back(s);
150 : }
151 0 : return list;
152 0 : }
153 :
154 :
155 :
156 : bool
157 0 : StructuredSyslogConfig::AddNetwork(const std::string& key, const std::string& network, const std::string& mask, const std::string& location)
158 : {
159 0 : uint32_t network_addr = IPToUInt(network);
160 0 : uint32_t mask_addr = IPToUInt(mask);
161 :
162 0 : uint32_t net_lower = (network_addr & mask_addr);
163 0 : uint32_t net_upper = (net_lower | (~mask_addr));
164 :
165 0 : std::string id = location;
166 0 : IPNetwork net(net_lower, net_upper, id);
167 0 : std::scoped_lock lock(networks_map_refresh_mutex);
168 :
169 0 : IPNetworks_map::iterator it = networks_map_.find(key);
170 0 : if (it != networks_map_.end()) {
171 0 : LOG(DEBUG, "VPN name found in Networks MAP while adding network. Appending to existing values of VPN key... ");
172 : //sorted insertion into vector
173 0 : it->second.insert(std::upper_bound(it->second.begin(), it->second.end(), net), net);
174 0 : LOG(DEBUG, "IPNetwork with destination address " << network_addr << " added in networks_map with VPN key " << key);
175 : } else {
176 0 : LOG(DEBUG, "VPN name NOT found in Networks MAP while adding network. Creating a new entry in Networks MAP ...");
177 0 : IPNetworks new_network;
178 0 : new_network.push_back(net);
179 0 : networks_map_.insert(std::make_pair(key, new_network) );
180 0 : LOG(DEBUG, "IPNetwork with destination address " << network_addr << " added in networks_map with VPN key " << key);
181 0 : }
182 0 : return true;
183 0 : }
184 :
185 :
186 : bool
187 0 : StructuredSyslogConfig::RefreshNetworksMap(const std::string location){
188 :
189 0 : std::scoped_lock lock(networks_map_refresh_mutex);
190 0 : for(IPNetworks_map::iterator it = networks_map_.begin(); it != networks_map_.end(); it++){
191 0 : std::vector<int> indexes_to_be_deleted;
192 0 : for(IPNetworks::iterator i = it->second.begin(); i != it->second.end(); i++) {
193 0 : if (location == i->id){
194 0 : LOG(DEBUG, "Location " << i->id << " to be deleted from Networks MAP with VPN " << it->first );
195 0 : indexes_to_be_deleted.push_back(i - it->second.begin());
196 : }
197 : }
198 0 : for(std::vector<int>::reverse_iterator v = indexes_to_be_deleted.rbegin(); v != indexes_to_be_deleted.rend(); ++v) {
199 0 : IPNetworks::iterator i = it->second.begin();
200 0 : it->second.erase(*v + i);
201 : }
202 0 : }
203 0 : LOG(INFO, "Networks MAP Refreshed!" );
204 0 : return true;
205 0 : }
206 :
207 : std::string
208 0 : StructuredSyslogConfig::FindNetwork(std::string ip, std::string key, std::string src_location)
209 : {
210 0 : uint32_t network_addr = IPToUInt(ip);
211 0 : IPNetwork ip_network(network_addr, 0, ip);
212 0 : std::string unknown_location;
213 :
214 0 : IPNetworks_map::iterator it = networks_map_.find(key);
215 0 : if (it != networks_map_.end()) {
216 0 : IPNetworks::iterator upper = std::upper_bound(it->second.begin(), it->second.end(), ip_network);
217 :
218 0 : uint32_t idx = upper - it->second.begin();
219 0 : if (idx <= it->second.size() && idx != 0){
220 0 : IPNetwork found_network_obj(0, 0, unknown_location);
221 0 : uint32_t min_range = UINT32_MAX;
222 : //check for last idx (idx-1) before upper_bound idx.
223 : //check for overlapping IP ranges in loop.
224 : //network with min. range should take priority.
225 0 : for (int i = idx - 1; i >= 0; i--) {
226 0 : IPNetwork possible_network_obj = it->second[i];
227 0 : LOG(DEBUG, "Checking for possible network-range match location " << possible_network_obj.id);
228 0 : uint32_t possible_network_range = possible_network_obj.address_end - possible_network_obj.address_begin;
229 0 : if ((network_addr >= possible_network_obj.address_begin)
230 0 : && (network_addr <= possible_network_obj.address_end)) {
231 0 : if (possible_network_range < min_range) {
232 0 : if (possible_network_obj.id != src_location) {
233 0 : found_network_obj = possible_network_obj;
234 0 : min_range = possible_network_range;
235 0 : LOG(DEBUG, "Possible Network found for " << ip << " from Tenant::VPN " << key <<
236 : " in Site : " << found_network_obj.id << " with range : " << possible_network_range);
237 : }
238 : }
239 : }
240 :
241 0 : }
242 0 : if (!(found_network_obj.id.empty())) {
243 0 : LOG(DEBUG, "Network found for " << ip << " from Tenant::VPN " << key <<
244 : " in Site : " << found_network_obj.id );
245 0 : return found_network_obj.id;
246 : }
247 : else {
248 0 : LOG(DEBUG,"Network address "<< ip <<" doesnt not belong to the found range "
249 : << found_network_obj.address_begin << " - " << found_network_obj.address_end << " in Tenant::VPN " << key);
250 : }
251 0 : }
252 : else{
253 0 : LOG(DEBUG,"Network range not found for " << ip << " in Tenant::VPN " << key );
254 : }
255 : }
256 : else {
257 0 : LOG(DEBUG, "Tenant::VPN "<< key << " NOT found in Network MAP!");
258 : }
259 0 : return unknown_location;
260 0 : }
261 :
262 : void
263 0 : StructuredSyslogConfig::HostnameRecordsHandler(const contrail_rapidjson::Document &jdoc,
264 : bool add_update) {
265 0 : if (jdoc.IsObject() && jdoc.HasMember("structured_syslog_hostname_record")) {
266 0 : const contrail_rapidjson::Value& hr = jdoc["structured_syslog_hostname_record"];
267 0 : std::string name, hostaddr, tenant, location, device, tags;
268 0 : std::map< std::string, std::string > linkmap;
269 0 : bool location_exists = false;
270 :
271 0 : if (hr.HasMember("fq_name")) {
272 0 : const contrail_rapidjson::Value& fq_name = hr["fq_name"];
273 0 : contrail_rapidjson::SizeType sz = fq_name.Size();
274 0 : name = fq_name[sz-1].GetString();
275 0 : LOG(DEBUG, "NAME got from fq_name: " << name);
276 : }
277 0 : if (hr.HasMember("structured_syslog_hostaddr")) {
278 0 : hostaddr = hr["structured_syslog_hostaddr"].GetString();
279 : }
280 0 : if (hr.HasMember("structured_syslog_tenant")) {
281 0 : tenant = hr["structured_syslog_tenant"].GetString();
282 : }
283 0 : if (hr.HasMember("structured_syslog_location")) {
284 0 : location = hr["structured_syslog_location"].GetString();
285 : }
286 0 : if (hr.HasMember("structured_syslog_device")) {
287 0 : device = hr["structured_syslog_device"].GetString();
288 : }
289 0 : if (hr.HasMember("structured_syslog_hostname_tags")) {
290 0 : tags = hr["structured_syslog_hostname_tags"].GetString();
291 : }
292 0 : if (hr.HasMember("structured_syslog_linkmap")) {
293 0 : const contrail_rapidjson::Value& linkmap_fields = hr["structured_syslog_linkmap"];
294 0 : const contrail_rapidjson::Value& links_array = linkmap_fields["links"];
295 0 : assert(links_array.IsArray());
296 0 : for (contrail_rapidjson::SizeType i = 0; i < links_array.Size(); i++) {
297 0 : std::string underlay = links_array[i]["underlay"].GetString();
298 0 : std::string link_type = links_array[i]["link_type"].GetString() ;
299 0 : std::string traffic_destination = links_array[i]["traffic_destination"].GetString() ;
300 0 : std::string link_metadata = links_array[i]["metadata"].GetString() ;
301 0 : std::string overlay_link_data = underlay + "@" + link_type + "@" + traffic_destination + "@" + link_metadata ;
302 0 : linkmap.insert(std::make_pair(links_array[i]["overlay"].GetString(),
303 : overlay_link_data));
304 0 : LOG(DEBUG, "Adding HostnameRecord: " << name << " linkmap: "
305 : << links_array[i]["overlay"].GetString() << " : "
306 : << overlay_link_data);
307 0 : }
308 : }
309 0 : if (hr.HasMember("structured_syslog_lan_segment_list")) {
310 0 : const contrail_rapidjson::Value& LANSegmentList_fields = hr["structured_syslog_lan_segment_list"];
311 0 : const contrail_rapidjson::Value& LANSegmentList_array = LANSegmentList_fields["LANSegmentList"];
312 0 : assert(LANSegmentList_array.IsArray());
313 0 : for (Chr_t::iterator it = hostname_records_.begin();it != hostname_records_.end(); it++){
314 0 : if (location == (it->second->location())) {
315 0 : LOG(DEBUG,"location already exists in hostname_records !!");
316 0 : location_exists = true;
317 0 : break;
318 : }
319 : }
320 0 : if (location_exists) {
321 0 : LOG(DEBUG, "Refresh LAN MAP for location : "<<location);
322 0 : RefreshNetworksMap(location);
323 : }
324 0 : for (contrail_rapidjson::SizeType i = 0; i < LANSegmentList_array.Size(); i++) {
325 0 : std::string vpn = LANSegmentList_array[i]["vpn"].GetString();
326 0 : std::string network_ranges = LANSegmentList_array[i]["network_ranges"].GetString();
327 0 : LOG(DEBUG, "Adding networks map with VPN: " << LANSegmentList_array[i]["vpn"].GetString()
328 : << " LANSegmentList: " << LANSegmentList_array[i]["network_ranges"].GetString());
329 :
330 0 : std::vector<std::string> network_range_list = split_into_vector(network_ranges,',');
331 0 : for (std::vector<std::string>::iterator iter = network_range_list.begin();
332 0 : iter != network_range_list.end(); iter++){
333 0 : std::vector<std::string> ip_and_subnet = split_into_vector(*iter,'/');
334 0 : std::string network_key = tenant + "::" + vpn;
335 0 : AddNetwork (network_key, ip_and_subnet[0], ip_and_subnet[1], location);
336 0 : }
337 0 : }
338 : }
339 0 : if (add_update) {
340 0 : LOG(DEBUG, "Adding HostnameRecord: " << name);
341 0 : AddHostnameRecord(name, hostaddr, tenant,
342 : location, device, tags, linkmap);
343 : } else {
344 0 : Chr_t::iterator cit = hostname_records_.find(name);
345 0 : if (cit != hostname_records_.end()) {
346 0 : LOG(DEBUG, "Erasing LAN MAP for location : "<< cit->second->location());
347 0 : if (!cit->second->location().empty()){
348 0 : RefreshNetworksMap(location);
349 : }
350 0 : LOG(DEBUG, "Erasing HostnameRecord: " << cit->second->name());
351 0 : hostname_records_.erase(cit);
352 : }
353 : }
354 0 : return;
355 0 : }
356 : }
357 :
358 : void
359 0 : StructuredSyslogConfig::TenantRecordsHandler(const contrail_rapidjson::Document &jdoc,
360 : bool add_update) {
361 0 : if (jdoc.IsObject() && jdoc.HasMember("structured_syslog_tenant_record")) {
362 0 : const contrail_rapidjson::Value& hr = jdoc["structured_syslog_tenant_record"];
363 0 : std::string name, tenantaddr, tenant, tags;
364 0 : std::map< std::string, std::string > dscpmap_ipv4;
365 0 : std::map< std::string, std::string > dscpmap_ipv6;
366 :
367 0 : if (hr.HasMember("fq_name")) {
368 0 : const contrail_rapidjson::Value& fq_name = hr["fq_name"];
369 0 : contrail_rapidjson::SizeType sz = fq_name.Size();
370 0 : name = fq_name[sz-1].GetString();
371 0 : LOG(DEBUG, "NAME got from fq_name: " << name);
372 : }
373 0 : if (hr.HasMember("structured_syslog_tenantaddr")) {
374 0 : tenantaddr = hr["structured_syslog_tenantaddr"].GetString();
375 : }
376 0 : if (hr.HasMember("structured_syslog_tenant")) {
377 0 : tenant = hr["structured_syslog_tenant"].GetString();
378 : }
379 0 : if (hr.HasMember("structured_syslog_tenant_tags")) {
380 0 : tags = hr["structured_syslog_tenant_tags"].GetString();
381 : }
382 0 : if (hr.HasMember("structured_syslog_dscpmap")) {
383 0 : const contrail_rapidjson::Value& dscpmap_fields = hr["structured_syslog_dscpmap"];
384 0 : const contrail_rapidjson::Value& dscpmapipv4_array = dscpmap_fields["dscpListIPv4"];
385 0 : const contrail_rapidjson::Value& dscpmapipv6_array = dscpmap_fields["dscpListIPv6"];
386 0 : assert(dscpmapipv6_array.IsArray());
387 0 : assert(dscpmapipv4_array.IsArray());
388 0 : for (contrail_rapidjson::SizeType i = 0; i < dscpmapipv4_array.Size(); i++) {
389 0 : dscpmap_ipv4.insert(std::make_pair<std::string,
390 0 : std::string >(dscpmapipv4_array[i]["dscp_value"].GetString(),
391 0 : dscpmapipv4_array[i]["alias_code"].GetString()));
392 0 : LOG(DEBUG, "Adding TenantRecord: " << name << " dscpmap ipv4: "
393 : << dscpmapipv4_array[i]["dscp_value"].GetString() << " : "
394 : << dscpmapipv4_array[i]["alias_code"].GetString());
395 : }
396 0 : for (contrail_rapidjson::SizeType i = 0; i < dscpmapipv6_array.Size(); i++) {
397 0 : dscpmap_ipv6.insert(std::make_pair<std::string,
398 0 : std::string >(dscpmapipv6_array[i]["dscp_value"].GetString(),
399 0 : dscpmapipv6_array[i]["alias_code"].GetString()));
400 0 : LOG(DEBUG, "Adding TenantRecord: " << name << " dscpmap ipv6: "
401 : << dscpmapipv6_array[i]["dscp_value"].GetString() << " : "
402 : << dscpmapipv6_array[i]["alias_code"].GetString());
403 : }
404 : }
405 0 : if (add_update) {
406 0 : LOG(DEBUG, "Adding TenantRecord: " << name);
407 0 : AddTenantRecord(name, tenantaddr, tenant,
408 : tags, dscpmap_ipv4, dscpmap_ipv6);
409 : } else {
410 0 : Ctr_t::iterator cit = tenant_records_.find(name);
411 0 : if (cit != tenant_records_.end()) {
412 0 : LOG(DEBUG, "Erasing TenantRecord: " << cit->second->name());
413 0 : tenant_records_.erase(cit);
414 : }
415 : }
416 0 : return;
417 0 : }
418 : }
419 :
420 :
421 : void
422 0 : StructuredSyslogConfig::ApplicationRecordsHandler(const contrail_rapidjson::Document &jdoc,
423 : bool add_update) {
424 0 : if (jdoc.IsObject() && jdoc.HasMember("structured_syslog_application_record")) {
425 0 : const contrail_rapidjson::Value& ar = jdoc["structured_syslog_application_record"];
426 0 : std::string name, app_category, app_subcategory,
427 0 : app_groups, app_risk, app_service_tags;
428 :
429 0 : if (ar.HasMember("fq_name")) {
430 0 : const contrail_rapidjson::Value& fq_name = ar["fq_name"];
431 0 : contrail_rapidjson::SizeType sz = fq_name.Size();
432 0 : name = fq_name[sz-1].GetString();
433 0 : LOG(DEBUG, "NAME got from fq_name: " << name);
434 : }
435 :
436 0 : if (ar.HasMember("structured_syslog_app_category")) {
437 0 : app_category = ar["structured_syslog_app_category"].GetString();
438 : }
439 0 : if (ar.HasMember("structured_syslog_app_subcategory")) {
440 0 : app_subcategory = ar["structured_syslog_app_subcategory"].GetString();
441 : }
442 0 : if (ar.HasMember("structured_syslog_app_groups")) {
443 0 : app_groups = ar["structured_syslog_app_groups"].GetString();
444 : }
445 0 : if (ar.HasMember("structured_syslog_app_risk")) {
446 0 : app_risk = ar["structured_syslog_app_risk"].GetString();
447 : }
448 0 : if (ar.HasMember("structured_syslog_app_service_tags")) {
449 0 : app_service_tags = ar["structured_syslog_app_service_tags"].GetString();
450 : }
451 :
452 0 : const contrail_rapidjson::Value& fq_name = ar["fq_name"];
453 0 : std::string tenant_name = fq_name[1].GetString();
454 0 : if (tenant_name.compare("default-global-analytics-config") == 0) {
455 0 : if (add_update) {
456 0 : LOG(DEBUG, "Adding ApplicationRecord: " << name);
457 0 : AddApplicationRecord(name, app_category, app_subcategory,
458 : app_groups, app_risk, app_service_tags);
459 : } else {
460 0 : Car_t::iterator cit = application_records_.find(name);
461 0 : if (cit != application_records_.end()) {
462 0 : LOG(DEBUG, "Erasing ApplicationRecord: " << cit->second->name());
463 0 : application_records_.erase(cit);
464 : }
465 : }
466 : }
467 : else {
468 0 : std::string apprec_name;
469 0 : apprec_name = tenant_name + '/' + name;
470 0 : if (add_update) {
471 0 : LOG(DEBUG, "Adding TenantApplicationRecord: " << apprec_name);
472 0 : AddTenantApplicationRecord(apprec_name, app_category, app_subcategory,
473 : app_groups, app_risk, app_service_tags);
474 : } else {
475 0 : Ctar_t::iterator ctit = tenant_application_records_.find(apprec_name);
476 0 : if (ctit != tenant_application_records_.end()) {
477 0 : LOG(DEBUG, "Erasing TenantApplicationRecord: " << ctit->second->name());
478 0 : tenant_application_records_.erase(ctit);
479 : }
480 : }
481 0 : }
482 :
483 0 : return;
484 0 : }
485 : }
486 :
487 : void
488 0 : StructuredSyslogConfig::MessageConfigsHandler(const contrail_rapidjson::Document &jdoc,
489 : bool add_update) {
490 0 : if (jdoc.IsObject() && jdoc.HasMember("structured_syslog_message")) {
491 0 : const contrail_rapidjson::Value& hr = jdoc["structured_syslog_message"];
492 0 : std::vector< std::string > ints;
493 0 : std::vector< std::string > tags;
494 0 : std::string name, forward;
495 0 : bool process_and_store = false;
496 0 : bool process_and_summarize = false;
497 0 : bool process_and_summarize_user = false;
498 :
499 0 : if (hr.HasMember("fq_name")) {
500 0 : const contrail_rapidjson::Value& fq_name = hr["fq_name"];
501 0 : contrail_rapidjson::SizeType sz = fq_name.Size();
502 0 : name = fq_name[sz-1].GetString();
503 0 : LOG(DEBUG, "NAME got from fq_name: " << name);
504 : }
505 :
506 0 : if (hr.HasMember("structured_syslog_message_tagged_fields")) {
507 0 : const contrail_rapidjson::Value& tagged_fields = hr["structured_syslog_message_tagged_fields"];
508 0 : const contrail_rapidjson::Value& tag_array = tagged_fields["field_names"];
509 0 : assert(tag_array.IsArray());
510 0 : for (contrail_rapidjson::SizeType i = 0; i < tag_array.Size(); i++)
511 0 : tags.push_back(tag_array[i].GetString());
512 : }
513 0 : if (hr.HasMember("structured_syslog_message_integer_fields")) {
514 0 : const contrail_rapidjson::Value& integer_fields = hr["structured_syslog_message_integer_fields"];
515 0 : const contrail_rapidjson::Value& int_array = integer_fields["field_names"];
516 0 : assert(int_array.IsArray());
517 0 : for (contrail_rapidjson::SizeType i = 0; i < int_array.Size(); i++)
518 0 : ints.push_back(int_array[i].GetString());
519 : }
520 0 : if (hr.HasMember("structured_syslog_message_forward")) {
521 0 : forward = hr["structured_syslog_message_forward"].GetString();
522 : }
523 0 : if (hr.HasMember("structured_syslog_message_process_and_store")) {
524 0 : process_and_store = hr["structured_syslog_message_process_and_store"].GetBool();
525 : }
526 0 : if (hr.HasMember("structured_syslog_message_process_and_summarize")) {
527 0 : process_and_summarize = hr["structured_syslog_message_process_and_summarize"].GetBool();
528 : }
529 0 : if (hr.HasMember("structured_syslog_message_process_and_summarize_user")) {
530 0 : process_and_summarize_user = hr["structured_syslog_message_process_and_summarize_user"].GetBool();
531 : }
532 0 : if (add_update) {
533 0 : LOG(DEBUG, "Adding MessageConfig: " << name);
534 0 : AddMessageConfig(name, tags, ints, process_and_store, forward, process_and_summarize, process_and_summarize_user);
535 : } else {
536 0 : Cmc_t::iterator cit = message_configs_.find(name);
537 0 : if (cit != message_configs_.end()) {
538 0 : LOG(DEBUG, "Erasing MessageConfig: " << cit->second->name());
539 0 : message_configs_.erase(cit);
540 : }
541 : }
542 0 : return;
543 0 : }
544 :
545 : }
546 :
547 : void
548 0 : StructuredSyslogConfig::SlaProfileRecordsHandler(const contrail_rapidjson::Document &jdoc,
549 : bool add_update) {
550 0 : if (jdoc.IsObject() && jdoc.HasMember("structured_syslog_sla_profile")) {
551 0 : const contrail_rapidjson::Value& slar = jdoc["structured_syslog_sla_profile"];
552 0 : std::string name, sla_params, tenant_name, slarec_name;
553 :
554 0 : if (slar.HasMember("fq_name")) {
555 0 : const contrail_rapidjson::Value& fq_name = slar["fq_name"];
556 0 : contrail_rapidjson::SizeType sz = fq_name.Size();
557 0 : name = fq_name[sz-1].GetString();
558 0 : tenant_name = fq_name[1].GetString();
559 0 : slarec_name = tenant_name + '/' + name;
560 0 : LOG(DEBUG, "NAME got from fq_name: " << name);
561 : }
562 0 : if (slar.HasMember("structured_syslog_sla_params")) {
563 0 : sla_params = slar["structured_syslog_sla_params"].GetString();
564 : }
565 0 : if (add_update) {
566 0 : LOG(DEBUG, "Adding SlaProfileRecord: " << slarec_name);
567 0 : AddSlaProfileRecord(slarec_name, sla_params);
568 : } else {
569 0 : Csr_t::iterator cit = sla_profile_records_.find(slarec_name);
570 0 : if (cit != sla_profile_records_.end()) {
571 0 : LOG(DEBUG, "Erasing SlaProfileRecord: " << cit->second->name());
572 0 : sla_profile_records_.erase(cit);
573 : }
574 : }
575 0 : return;
576 0 : }
577 : }
578 :
579 : void
580 0 : StructuredSyslogConfig::ReceiveConfig(const contrail_rapidjson::Document &jdoc, bool add_change) {
581 0 : HostnameRecordsHandler(jdoc, add_change);
582 0 : TenantRecordsHandler(jdoc, add_change);
583 0 : ApplicationRecordsHandler(jdoc, add_change);
584 0 : MessageConfigsHandler(jdoc, add_change);
585 0 : SlaProfileRecordsHandler(jdoc, add_change);
586 0 : }
587 :
588 : boost::shared_ptr<HostnameRecord>
589 0 : StructuredSyslogConfig::GetHostnameRecord(const std::string &name) {
590 0 : Chr_t::iterator it = hostname_records_.find(name);
591 0 : if (it != hostname_records_.end()) {
592 0 : return it->second;
593 : }
594 0 : return boost::shared_ptr<HostnameRecord>();
595 : }
596 :
597 : void
598 0 : StructuredSyslogConfig::AddHostnameRecord(const std::string &name,
599 : const std::string &hostaddr, const std::string &tenant,
600 : const std::string &location, const std::string &device,
601 : const std::string &tags, const std::map< std::string, std::string > &linkmap) {
602 0 : Chr_t::iterator it = hostname_records_.find(name);
603 0 : if (it != hostname_records_.end()) {
604 0 : it->second->Refresh(name, hostaddr, tenant, location,
605 : device, tags, linkmap);
606 : } else {
607 : boost::shared_ptr<HostnameRecord> c(new HostnameRecord(
608 0 : name, hostaddr, tenant, location, device, tags, linkmap));
609 0 : hostname_records_.insert(std::make_pair(name, c));
610 0 : }
611 0 : }
612 :
613 : boost::shared_ptr<TenantRecord>
614 0 : StructuredSyslogConfig::GetTenantRecord(const std::string &name) {
615 0 : Ctr_t::iterator it = tenant_records_.find(name);
616 0 : if (it != tenant_records_.end()) {
617 0 : return it->second;
618 : }
619 0 : return boost::shared_ptr<TenantRecord>();
620 : }
621 :
622 : void
623 0 : StructuredSyslogConfig::AddTenantRecord(const std::string &name,
624 : const std::string &tenantaddr, const std::string &tenant,
625 : const std::string &tags, const std::map< std::string, std::string > &dscpmap_ipv4,
626 : const std::map< std::string, std::string > &dscpmap_ipv6) {
627 0 : Ctr_t::iterator it = tenant_records_.find(name);
628 0 : if (it != tenant_records_.end()) {
629 0 : it->second->Refresh(name, tenantaddr, tenant, tags, dscpmap_ipv4, dscpmap_ipv6);
630 : } else {
631 : boost::shared_ptr<TenantRecord> c(new TenantRecord(
632 0 : name, tenantaddr, tenant, tags, dscpmap_ipv4, dscpmap_ipv6));
633 0 : tenant_records_.insert(std::make_pair(name, c));
634 0 : }
635 0 : }
636 :
637 : boost::shared_ptr<ApplicationRecord>
638 0 : StructuredSyslogConfig::GetApplicationRecord(const std::string &name) {
639 0 : Car_t::iterator it = application_records_.find(name);
640 0 : if (it != application_records_.end()) {
641 0 : return it->second;
642 : }
643 0 : return boost::shared_ptr<ApplicationRecord>();
644 : }
645 :
646 : void
647 0 : StructuredSyslogConfig::AddApplicationRecord(const std::string &name,
648 : const std::string &app_category, const std::string &app_subcategory,
649 : const std::string &app_groups, const std::string &app_risk,
650 : const std::string &app_service_tags) {
651 0 : Car_t::iterator it = application_records_.find(name);
652 0 : if (it != application_records_.end()) {
653 0 : it->second->Refresh(name, app_category, app_subcategory, app_groups,
654 : app_risk, app_service_tags);
655 : } else {
656 : boost::shared_ptr<ApplicationRecord> c(new ApplicationRecord(
657 : name, app_category, app_subcategory, app_groups,
658 0 : app_risk, app_service_tags));
659 0 : application_records_.insert(std::make_pair(name, c));
660 0 : }
661 0 : }
662 :
663 : boost::shared_ptr<TenantApplicationRecord>
664 0 : StructuredSyslogConfig::GetTenantApplicationRecord(const std::string &name) {
665 0 : Ctar_t::iterator it = tenant_application_records_.find(name);
666 0 : if (it != tenant_application_records_.end()) {
667 0 : return it->second;
668 : }
669 0 : return boost::shared_ptr<TenantApplicationRecord>();
670 : }
671 :
672 : void
673 0 : StructuredSyslogConfig::AddTenantApplicationRecord(const std::string &name,
674 : const std::string &tenant_app_category, const std::string &tenant_app_subcategory,
675 : const std::string &tenant_app_groups, const std::string &tenant_app_risk,
676 : const std::string &tenant_app_service_tags) {
677 0 : Ctar_t::iterator it = tenant_application_records_.find(name);
678 0 : if (it != tenant_application_records_.end()) {
679 0 : it->second->Refresh(name, tenant_app_category, tenant_app_subcategory,
680 : tenant_app_groups, tenant_app_risk, tenant_app_service_tags);
681 : } else {
682 : boost::shared_ptr<TenantApplicationRecord> c(new TenantApplicationRecord(
683 : name, tenant_app_category, tenant_app_subcategory,
684 0 : tenant_app_groups, tenant_app_risk, tenant_app_service_tags));
685 0 : tenant_application_records_.insert(std::make_pair(name, c));
686 0 : }
687 0 : }
688 :
689 : boost::shared_ptr<SlaProfileRecord>
690 0 : StructuredSyslogConfig::GetSlaProfileRecord(const std::string &name) {
691 0 : Csr_t::iterator it = sla_profile_records_.find(name);
692 0 : if (it != sla_profile_records_.end()) {
693 0 : return it->second;
694 : }
695 0 : return boost::shared_ptr<SlaProfileRecord>();
696 : }
697 :
698 : void
699 0 : StructuredSyslogConfig::AddSlaProfileRecord(const std::string &name,
700 : const std::string &sla_params) {
701 0 : Csr_t::iterator it = sla_profile_records_.find(name);
702 0 : if (it != sla_profile_records_.end()) {
703 0 : it->second->Refresh(name, sla_params);
704 : } else {
705 : boost::shared_ptr<SlaProfileRecord> c(new SlaProfileRecord(
706 0 : name, sla_params));
707 0 : sla_profile_records_.insert(std::make_pair(name, c));
708 0 : }
709 0 : }
710 :
711 : boost::shared_ptr<MessageConfig>
712 30 : StructuredSyslogConfig::GetMessageConfig(const std::string &name) {
713 30 : Cmc_t::iterator it = message_configs_.find(name);
714 30 : if (it != message_configs_.end()) {
715 : /* exact match */
716 0 : return it->second;
717 : }
718 : /* no exact match, look for match based on regex */
719 30 : Cmc_t::iterator cit = message_configs_.begin();
720 30 : Cmc_t::iterator end = message_configs_.end();
721 30 : Cmc_t::iterator match = end;
722 30 : while (cit != end) {
723 0 : regex pattern;
724 0 : Cmc_t::iterator dit = cit++;
725 0 : boost::match_results<std::string::const_iterator> what;
726 0 : boost::match_flag_type flags = boost::match_default;
727 0 : std::string::const_iterator name_start = name.begin(), name_end = name.end();
728 : try {
729 0 : pattern = regex(dit->second->name());
730 : }
731 0 : catch (regex_error &e) {
732 0 : LOG(DEBUG, "skipping invalid regex pattern: " << dit->second->name());
733 0 : continue;
734 0 : }
735 0 : if(regex_search(name_start, name_end, what, pattern, flags)) {
736 0 : if ((match == end) || (match->second->name().length() < dit->second->name().length())) {
737 0 : match = dit;
738 : }
739 : }
740 0 : }
741 30 : if (match != end) {
742 0 : return match->second;
743 : }
744 : /* no match */
745 30 : return boost::shared_ptr<MessageConfig>();
746 : }
747 :
748 : void
749 0 : StructuredSyslogConfig::AddMessageConfig(const std::string &name,
750 : const std::vector< std::string > &tags, const std::vector< std::string > &ints,
751 : bool process_and_store, const std::string &forward_action, bool process_and_summarize,
752 : bool process_and_summarize_user) {
753 0 : bool forward = false, process_before_forward = false;
754 0 : if (forward_action == "forward-unprocessed") {
755 0 : forward = true;
756 : }
757 0 : if (forward_action == "forward-processed") {
758 0 : forward = true;
759 0 : process_before_forward = true;
760 : }
761 0 : Cmc_t::iterator it = message_configs_.find(name);
762 0 : if (it != message_configs_.end()) {
763 0 : it->second->Refresh(name, tags, ints, process_and_store, forward, process_before_forward,
764 : process_and_summarize, process_and_summarize_user);
765 : } else {
766 : boost::shared_ptr<MessageConfig> c(new MessageConfig(
767 : name, tags, ints, process_and_store, forward, process_before_forward,
768 0 : process_and_summarize, process_and_summarize_user));
769 0 : message_configs_.insert(std::make_pair(name, c));
770 0 : }
771 0 : }
|