1 /*************************************************************************
3 * Copyright 2020 highstreet technologies GmbH and others
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
21 #include "utils/log_utils.h"
22 #include "utils/sys_utils.h"
23 #include "core/framework.h"
28 #include <cjson/cJSON.h>
30 static char *fault_process_vars(const char *template, const fault_details_t *details);
31 static char *fault_process_function(const char *function);
33 fault_settings_t *faults_settings_read(const char *json_plain) {
38 fault_settings_t *ret = (fault_settings_t *)malloc(sizeof(fault_settings_t));
40 log_error("malloc failed\n");
41 goto faults_settings_read_failed_cleanup;
44 ret->yang_notif_template = 0;
45 ret->choosing_method = 0;
49 cJSON *json = cJSON_Parse(json_plain);
51 log_error("json parsing error: %s\n", cJSON_GetErrorPtr());
52 goto faults_settings_read_failed_cleanup;
55 cJSON *main_node = cJSON_GetObjectItem(json, "fault-rules");
57 goto faults_settings_read_failed_cleanup;
60 cJSON *node = cJSON_GetObjectItem(main_node, "yang-notif-template");
61 if(node && cJSON_IsString(node)) {
62 ret->yang_notif_template = strdup(node->valuestring);
65 log_error("could not find yang-notif-template\n");
66 goto faults_settings_read_failed_cleanup;
69 node = cJSON_GetObjectItem(main_node, "choosing-method");
70 if(node && cJSON_IsString(node)) {
71 ret->choosing_method = strdup(node->valuestring);
74 log_error("could not find choosing-method\n");
75 goto faults_settings_read_failed_cleanup;
78 node = cJSON_GetObjectItem(main_node, "faults");
79 if(node && cJSON_IsArray(node)) {
81 cJSON_ArrayForEach(fault_detail, node) {
84 ret->fault = (fault_details_t *)realloc(ret->fault, sizeof(fault_details_t)*ret->fault_count);
87 log_error("realloc failed\n");
88 goto faults_settings_read_failed_cleanup;
91 ret->fault[ret->fault_count - 1].condition = 0;
92 ret->fault[ret->fault_count - 1].object = 0;
93 ret->fault[ret->fault_count - 1].severity = 0;
94 ret->fault[ret->fault_count - 1].date_time = 0;
95 ret->fault[ret->fault_count - 1].specific_problem = 0;
96 ret->fault[ret->fault_count - 1].field_name = 0;
97 ret->fault[ret->fault_count - 1].field_value = 0;
98 ret->fault[ret->fault_count - 1].field_count = 0;
99 ret->fault[ret->fault_count - 1].yang_notif_processed = 0;
101 cJSON_ArrayForEach(object, fault_detail) {
102 ret->fault[ret->fault_count - 1].field_count++;
103 ret->fault[ret->fault_count - 1].field_name = (char **)realloc(ret->fault[ret->fault_count - 1].field_name, sizeof(char*) * ret->fault[ret->fault_count - 1].field_count);
104 if(ret->fault[ret->fault_count - 1].field_name == 0) {
105 ret->fault[ret->fault_count - 1].field_count--;
106 log_error("realloc failed\n");
107 goto faults_settings_read_failed_cleanup;
110 ret->fault[ret->fault_count - 1].field_value = (char **)realloc(ret->fault[ret->fault_count - 1].field_value, sizeof(char*) * ret->fault[ret->fault_count - 1].field_count);
111 if(ret->fault[ret->fault_count - 1].field_value == 0) {
112 ret->fault[ret->fault_count - 1].field_count--;
113 log_error("realloc failed\n");
114 goto faults_settings_read_failed_cleanup;
117 asprintf(&ret->fault[ret->fault_count - 1].field_name[ret->fault[ret->fault_count - 1].field_count - 1], "%%%%%s%%%%", object->string);
118 ret->fault[ret->fault_count - 1].field_value[ret->fault[ret->fault_count - 1].field_count - 1] = strdup(object->valuestring);
123 log_error("could not find faults list\n");
124 goto faults_settings_read_failed_cleanup;
130 faults_settings_read_failed_cleanup:
131 faults_settings_free(ret);
136 void faults_settings_free(fault_settings_t *faults) {
138 free(faults->yang_notif_template);
139 free(faults->choosing_method);
141 for(int i = 0; i < faults->fault_count; i++) {
142 free(faults->fault[i].condition);
143 free(faults->fault[i].object);
144 free(faults->fault[i].severity);
145 free(faults->fault[i].date_time);
146 free(faults->fault[i].specific_problem);
148 for(int j = 0; j < faults->fault[i].field_count; j++) {
149 free(faults->fault[i].field_name[j]);
150 free(faults->fault[i].field_value[j]);
152 free(faults->fault[i].field_name);
153 free(faults->fault[i].field_value);
155 free(faults->fault[i].yang_notif_processed);
160 int faults_settings_process(fault_settings_t *faults, int fault_no) {
162 assert(fault_no < faults->fault_count);
164 free(faults->fault[fault_no].condition);
165 free(faults->fault[fault_no].object);
166 free(faults->fault[fault_no].severity);
167 free(faults->fault[fault_no].date_time);
168 free(faults->fault[fault_no].specific_problem);
169 free(faults->fault[fault_no].yang_notif_processed);
171 faults->fault[fault_no].condition = 0;
172 faults->fault[fault_no].object = 0;
173 faults->fault[fault_no].severity = 0;
174 faults->fault[fault_no].date_time = 0;
175 faults->fault[fault_no].specific_problem = 0;
176 faults->fault[fault_no].yang_notif_processed = 0;
178 for(int j = 0; j < faults->fault[fault_no].field_count; j++) {
179 if(strcmp(faults->fault[fault_no].field_name[j], "%%condition%%") == 0) {
180 faults->fault[fault_no].condition = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
182 else if(strcmp(faults->fault[fault_no].field_name[j], "%%object%%") == 0) {
183 faults->fault[fault_no].object = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
185 else if(strcmp(faults->fault[fault_no].field_name[j], "%%severity%%") == 0) {
186 faults->fault[fault_no].severity = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
188 else if(strcmp(faults->fault[fault_no].field_name[j], "%%date-time%%") == 0) {
189 faults->fault[fault_no].date_time = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
191 else if(strcmp(faults->fault[fault_no].field_name[j], "%%specific-problem%%") == 0) {
192 faults->fault[fault_no].specific_problem = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
196 faults->fault[fault_no].yang_notif_processed = fault_process_vars(faults->yang_notif_template, &faults->fault[fault_no]);
198 if(faults->fault[fault_no].condition == 0) {
199 log_error("could not find condition in fault\n");
200 return NTS_ERR_FAILED;
203 if(faults->fault[fault_no].object == 0) {
204 log_error("could not find object in fault\n");
205 return NTS_ERR_FAILED;
208 if(faults->fault[fault_no].severity == 0) {
209 log_error("could not find severity in fault\n");
210 return NTS_ERR_FAILED;
213 if(faults->fault[fault_no].date_time == 0) {
214 log_error("could not find date_time in fault\n");
215 return NTS_ERR_FAILED;
218 if(faults->fault[fault_no].specific_problem == 0) {
219 log_error("could not find specific_problem in fault\n");
220 return NTS_ERR_FAILED;
223 if(faults->fault[fault_no].yang_notif_processed == 0) {
224 log_error("could not find yang_notif_processed in fault\n");
225 return NTS_ERR_FAILED;
231 static char *fault_process_vars(const char *template, const fault_details_t *details) {
235 char *ret = strdup(template);
237 log_error("strdup error\n");
241 //if template is blank, do not process anything, means nc notif disabled
255 //do replacements until no replacement is done
270 pos_start = strstr(ret, "%%");
272 char *pos_end = strstr(pos_start + 2, "%%");
273 int var_size = pos_end - pos_start + 2;
274 var = (char *)malloc(sizeof(char) * (var_size + 1));
276 log_error("bad malloc\n");
277 goto fault_process_vars_failed;
280 for(int i = 0; i < var_size; i++) {
281 var[i] = pos_start[i];
287 vars = (char **)realloc(vars, sizeof(char *) * vars_count);
290 log_error("bad malloc\n");
291 goto fault_process_vars_failed;
294 vars[vars_count - 1] = strdup(var);
295 if(!vars[vars_count - 1]) {
297 log_error("bad malloc\n");
298 goto fault_process_vars_failed;
303 pos_start = strstr(pos_end + 2, "%%");
307 pos_start = strstr(ret, "$$");
309 char *pos_end = strstr(pos_start + 2, "$$");
310 int func_size = pos_end - pos_start + 2;
311 func = (char *)malloc(sizeof(char) * (func_size + 1));
313 log_error("bad malloc\n");
314 goto fault_process_vars_failed;
317 for(int i = 0; i < func_size; i++) {
318 func[i] = pos_start[i];
324 funcs = (char **)realloc(funcs, sizeof(char *) * funcs_count);
327 log_error("bad malloc\n");
328 goto fault_process_vars_failed;
331 funcs[funcs_count - 1] = strdup(func);
332 if(!funcs[funcs_count - 1]) {
334 log_error("bad malloc\n");
335 goto fault_process_vars_failed;
340 pos_start = strstr(pos_end + 2, "$$");
344 for(int i = 0; i < vars_count; i++) {
346 for(int j = 0; j < details->field_count; j++) {
347 if(strcmp(details->field_name[j], vars[i]) == 0) {
348 var_value = strdup(details->field_value[j]);
353 log_error("value %s not found\n", vars[i]);
354 goto fault_process_vars_failed;
357 ret = str_replace(ret, vars[i], var_value);
361 goto fault_process_vars_failed;
370 for(int i = 0; i < funcs_count; i++) {
371 char *func_value = fault_process_function(funcs[i]);
372 if(func_value == 0) {
373 log_error("function %s not found\n", vars[i]);
374 goto fault_process_vars_failed;
377 ret = str_replace(ret, funcs[i], func_value);
380 goto fault_process_vars_failed;
388 for(int i = 0; i < vars_count; i++) {
395 for(int i = 0; i < funcs_count; i++) {
406 for(int i = 0; i < vars_count; i++) {
411 for(int i = 0; i < funcs_count; i++) {
417 fault_process_vars_failed:
421 for(int i = 0; i < vars_count; i++) {
426 for(int i = 0; i < funcs_count; i++) {
433 static char *fault_process_function(const char *function) {
436 static uint8_t uint8_counter = 0;
437 static uint16_t uint16_counter = 0;
438 static uint32_t uint32_counter = 0;
440 if(strcmp(function, "$$time$$") == 0) {
441 return get_current_date_and_time();
443 else if(strcmp(function, "$$uint8_counter$$") == 0) {
445 asprintf(&ret, "%d", uint8_counter);
449 else if(strcmp(function, "$$uint16_counter$$") == 0) {
451 asprintf(&ret, "%d", uint16_counter);
455 else if(strcmp(function, "$$uint32_counter$$") == 0) {
457 asprintf(&ret, "%d", uint32_counter);
461 else if(strcmp(function, "$$hostname$$") == 0) {
463 asprintf(&ret, "%s", framework_environment.settings.hostname);