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"
27 #include <cjson/cJSON.h>
29 static char *fault_process_vars(const char *template, const fault_details_t *details);
30 static char *fault_process_function(const char *function);
32 fault_settings_t *faults_settings_read(const char *json_plain) {
37 fault_settings_t *ret = (fault_settings_t *)malloc(sizeof(fault_settings_t));
39 log_error("malloc failed\n");
40 goto faults_settings_read_failed_cleanup;
43 ret->yang_notif_template = 0;
44 ret->choosing_method = 0;
48 cJSON *json = cJSON_Parse(json_plain);
50 log_error("json parsing error: %s\n", cJSON_GetErrorPtr());
51 goto faults_settings_read_failed_cleanup;
54 cJSON *main_node = cJSON_GetObjectItem(json, "fault-rules");
56 goto faults_settings_read_failed_cleanup;
59 cJSON *node = cJSON_GetObjectItem(main_node, "yang-notif-template");
60 if(node && cJSON_IsString(node)) {
61 ret->yang_notif_template = strdup(node->valuestring);
64 log_error("could not find yang-notif-template\n");
65 goto faults_settings_read_failed_cleanup;
68 node = cJSON_GetObjectItem(main_node, "choosing-method");
69 if(node && cJSON_IsString(node)) {
70 ret->choosing_method = strdup(node->valuestring);
73 log_error("could not find choosing-method\n");
74 goto faults_settings_read_failed_cleanup;
77 node = cJSON_GetObjectItem(main_node, "faults");
78 if(node && cJSON_IsArray(node)) {
80 cJSON_ArrayForEach(fault_detail, node) {
83 ret->fault = (fault_details_t *)realloc(ret->fault, sizeof(fault_details_t)*ret->fault_count);
86 log_error("realloc failed\n");
87 goto faults_settings_read_failed_cleanup;
90 ret->fault[ret->fault_count - 1].condition = 0;
91 ret->fault[ret->fault_count - 1].object = 0;
92 ret->fault[ret->fault_count - 1].severity = 0;
93 ret->fault[ret->fault_count - 1].date_time = 0;
94 ret->fault[ret->fault_count - 1].specific_problem = 0;
95 ret->fault[ret->fault_count - 1].field_name = 0;
96 ret->fault[ret->fault_count - 1].field_value = 0;
97 ret->fault[ret->fault_count - 1].field_count = 0;
98 ret->fault[ret->fault_count - 1].yang_notif_processed = 0;
100 cJSON_ArrayForEach(object, fault_detail) {
101 ret->fault[ret->fault_count - 1].field_count++;
102 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);
103 if(ret->fault[ret->fault_count - 1].field_name == 0) {
104 ret->fault[ret->fault_count - 1].field_count--;
105 log_error("realloc failed\n");
106 goto faults_settings_read_failed_cleanup;
109 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);
110 if(ret->fault[ret->fault_count - 1].field_value == 0) {
111 ret->fault[ret->fault_count - 1].field_count--;
112 log_error("realloc failed\n");
113 goto faults_settings_read_failed_cleanup;
116 asprintf(&ret->fault[ret->fault_count - 1].field_name[ret->fault[ret->fault_count - 1].field_count - 1], "%%%%%s%%%%", object->string);
117 ret->fault[ret->fault_count - 1].field_value[ret->fault[ret->fault_count - 1].field_count - 1] = strdup(object->valuestring);
122 log_error("could not find faults list\n");
123 goto faults_settings_read_failed_cleanup;
129 faults_settings_read_failed_cleanup:
130 faults_settings_free(ret);
135 void faults_settings_free(fault_settings_t *faults) {
137 free(faults->yang_notif_template);
138 free(faults->choosing_method);
140 for(int i = 0; i < faults->fault_count; i++) {
141 free(faults->fault[i].condition);
142 free(faults->fault[i].object);
143 free(faults->fault[i].severity);
144 free(faults->fault[i].date_time);
145 free(faults->fault[i].specific_problem);
147 for(int j = 0; j < faults->fault[i].field_count; j++) {
148 free(faults->fault[i].field_name[j]);
149 free(faults->fault[i].field_value[j]);
151 free(faults->fault[i].field_name);
152 free(faults->fault[i].field_value);
154 free(faults->fault[i].yang_notif_processed);
159 int faults_settings_process(fault_settings_t *faults, int fault_no) {
161 assert(fault_no < faults->fault_count);
163 free(faults->fault[fault_no].condition);
164 free(faults->fault[fault_no].object);
165 free(faults->fault[fault_no].severity);
166 free(faults->fault[fault_no].date_time);
167 free(faults->fault[fault_no].specific_problem);
168 free(faults->fault[fault_no].yang_notif_processed);
170 faults->fault[fault_no].condition = 0;
171 faults->fault[fault_no].object = 0;
172 faults->fault[fault_no].severity = 0;
173 faults->fault[fault_no].date_time = 0;
174 faults->fault[fault_no].specific_problem = 0;
175 faults->fault[fault_no].yang_notif_processed = 0;
177 for(int j = 0; j < faults->fault[fault_no].field_count; j++) {
178 if(strcmp(faults->fault[fault_no].field_name[j], "%%condition%%") == 0) {
179 faults->fault[fault_no].condition = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
181 else if(strcmp(faults->fault[fault_no].field_name[j], "%%object%%") == 0) {
182 faults->fault[fault_no].object = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
184 else if(strcmp(faults->fault[fault_no].field_name[j], "%%severity%%") == 0) {
185 faults->fault[fault_no].severity = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
187 else if(strcmp(faults->fault[fault_no].field_name[j], "%%date-time%%") == 0) {
188 faults->fault[fault_no].date_time = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
190 else if(strcmp(faults->fault[fault_no].field_name[j], "%%specific-problem%%") == 0) {
191 faults->fault[fault_no].specific_problem = fault_process_vars(faults->fault[fault_no].field_value[j], &faults->fault[fault_no]);
195 faults->fault[fault_no].yang_notif_processed = fault_process_vars(faults->yang_notif_template, &faults->fault[fault_no]);
197 if(faults->fault[fault_no].condition == 0) {
198 log_error("could not find condition in fault\n");
199 return NTS_ERR_FAILED;
202 if(faults->fault[fault_no].object == 0) {
203 log_error("could not find object in fault\n");
204 return NTS_ERR_FAILED;
207 if(faults->fault[fault_no].severity == 0) {
208 log_error("could not find severity in fault\n");
209 return NTS_ERR_FAILED;
212 if(faults->fault[fault_no].date_time == 0) {
213 log_error("could not find date_time in fault\n");
214 return NTS_ERR_FAILED;
217 if(faults->fault[fault_no].specific_problem == 0) {
218 log_error("could not find specific_problem in fault\n");
219 return NTS_ERR_FAILED;
222 if(faults->fault[fault_no].yang_notif_processed == 0) {
223 log_error("could not find yang_notif_processed in fault\n");
224 return NTS_ERR_FAILED;
230 static char *fault_process_vars(const char *template, const fault_details_t *details) {
234 char *ret = strdup(template);
236 log_error("strdup error\n");
240 //if template is blank, do not process anything, means nc notif disabled
254 //do replacements until no replacement is done
269 pos_start = strstr(ret, "%%");
271 char *pos_end = strstr(pos_start + 2, "%%");
272 int var_size = pos_end - pos_start + 2;
273 var = (char *)malloc(sizeof(char) * (var_size + 1));
275 log_error("bad malloc\n");
276 goto fault_process_vars_failed;
279 for(int i = 0; i < var_size; i++) {
280 var[i] = pos_start[i];
286 vars = (char **)realloc(vars, sizeof(char *) * vars_count);
289 log_error("bad malloc\n");
290 goto fault_process_vars_failed;
293 vars[vars_count - 1] = strdup(var);
294 if(!vars[vars_count - 1]) {
296 log_error("bad malloc\n");
297 goto fault_process_vars_failed;
302 pos_start = strstr(pos_end + 2, "%%");
306 pos_start = strstr(ret, "$$");
308 char *pos_end = strstr(pos_start + 2, "$$");
309 int func_size = pos_end - pos_start + 2;
310 func = (char *)malloc(sizeof(char) * (func_size + 1));
312 log_error("bad malloc\n");
313 goto fault_process_vars_failed;
316 for(int i = 0; i < func_size; i++) {
317 func[i] = pos_start[i];
323 funcs = (char **)realloc(funcs, sizeof(char *) * funcs_count);
326 log_error("bad malloc\n");
327 goto fault_process_vars_failed;
330 funcs[funcs_count - 1] = strdup(func);
331 if(!funcs[funcs_count - 1]) {
333 log_error("bad malloc\n");
334 goto fault_process_vars_failed;
339 pos_start = strstr(pos_end + 2, "$$");
343 for(int i = 0; i < vars_count; i++) {
345 for(int j = 0; j < details->field_count; j++) {
346 if(strcmp(details->field_name[j], vars[i]) == 0) {
347 var_value = strdup(details->field_value[j]);
352 log_error("value %s not found\n", vars[i]);
353 goto fault_process_vars_failed;
356 ret = str_replace(ret, vars[i], var_value);
360 goto fault_process_vars_failed;
369 for(int i = 0; i < funcs_count; i++) {
370 char *func_value = fault_process_function(funcs[i]);
371 if(func_value == 0) {
372 log_error("function %s not found\n", vars[i]);
373 goto fault_process_vars_failed;
376 ret = str_replace(ret, funcs[i], func_value);
379 goto fault_process_vars_failed;
387 for(int i = 0; i < vars_count; i++) {
394 for(int i = 0; i < funcs_count; i++) {
405 for(int i = 0; i < vars_count; i++) {
410 for(int i = 0; i < funcs_count; i++) {
416 fault_process_vars_failed:
420 for(int i = 0; i < vars_count; i++) {
425 for(int i = 0; i < funcs_count; i++) {
432 static char *fault_process_function(const char *function) {
435 static uint8_t uint8_counter = 0;
436 static uint16_t uint16_counter = 0;
437 static uint32_t uint32_counter = 0;
439 if(strcmp(function, "$$time$$") == 0) {
440 return get_current_date_and_time();
442 else if(strcmp(function, "$$uint8_counter$$") == 0) {
444 asprintf(&ret, "%d", uint8_counter);
448 else if(strcmp(function, "$$uint16_counter$$") == 0) {
450 asprintf(&ret, "%d", uint16_counter);
454 else if(strcmp(function, "$$uint32_counter$$") == 0) {
456 asprintf(&ret, "%d", uint32_counter);