From 62cdbebd7039840575d32f5a5389fc2265fe5cd7 Mon Sep 17 00:00:00 2001 From: Omar Kallel Date: Thu, 25 Mar 2021 23:22:16 +0100 Subject: [PATCH] Enhance notification functions update_notify_file and check_value_change & add the function cwmp_get_single_parameter_value to call Inform parameters instead --- datamodel_interface.c | 78 ++++++++++++++++++++++++---- inc/datamodel_interface.h | 6 ++- inc/notifications.h | 8 +-- notifications.c | 106 ++++++++++++++++++++++---------------- xml.c | 23 +++------ 5 files changed, 147 insertions(+), 74 deletions(-) diff --git a/datamodel_interface.c b/datamodel_interface.c index 607b303..df11e61 100644 --- a/datamodel_interface.c +++ b/datamodel_interface.c @@ -11,6 +11,7 @@ #include "datamodel_interface.h" #include "log.h" #include "ubus.h" +#include "notifications.h" bool transaction_started = false; int transaction_id = 0; @@ -201,6 +202,52 @@ bool cwmp_transaction_status() CWMP_LOG(INFO, "Transaction with id: %d is not available anymore\n", transaction_id); return status; } +/* + * Get single _parameter value + */ + +void ubus_get_single_parameter_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg) +{ + struct blob_attr *parameters = get_parameters_array(msg); + struct cwmp_dm_parameter *result = (struct cwmp_dm_parameter *)req->priv; + if (parameters == NULL) { + int fault_code = get_fault(msg); + result->name = NULL; + result->type = NULL; + cwmp_asprintf(&result->value, "%d", fault_code); + return; + } + const struct blobmsg_policy p[3] = { { "parameter", BLOBMSG_TYPE_STRING }, { "value", BLOBMSG_TYPE_STRING }, { "type", BLOBMSG_TYPE_STRING } }; + struct blob_attr *cur; + int rem; + blobmsg_for_each_attr(cur, parameters, rem) + { + struct blob_attr *tb[3] = { NULL, NULL, NULL }; + blobmsg_parse(p, 3, tb, blobmsg_data(cur), blobmsg_len(cur)); + if (!tb[0]) + continue; + result->name = strdup(blobmsg_get_string(tb[0])); + result->value = strdup(tb[1] ? blobmsg_get_string(tb[1]) : ""); + result->type = strdup(tb[2] ? blobmsg_get_string(tb[2]) : ""); + break; + } +} + +char *cwmp_get_single_parameter_value(char *parameter_name, struct cwmp_dm_parameter *dm_parameter) +{ + int e; + e = cwmp_ubus_call("usp.raw", "get", CWMP_UBUS_ARGS{ { "path", {.str_val = !parameter_name || parameter_name[0] == '\0' ? DM_ROOT_OBJ : parameter_name }, UBUS_String } }, 1, ubus_get_single_parameter_callback, dm_parameter); + if (e < 0) { + CWMP_LOG(INFO, "get ubus method failed: Ubus err code: %d", e); + return strdup("9002"); + } + + if (dm_parameter->name == NULL) { + CWMP_LOG(INFO, "Get parameter_values failed: fault_code: %s", dm_parameter->value); // the value is the fault + return dm_parameter->value; + } + return NULL; +} /* * Get parameter Values/Names/Notify @@ -252,16 +299,6 @@ char *cwmp_get_parameter_names(char *object_name, bool next_level, struct list_h return NULL; } -int cwmp_update_enabled_list_notify(int instance_mode, struct list_head *parameters_list) -{ - int e; - struct list_params_result list_notify_result = {.parameters_list = parameters_list }; - e = cwmp_ubus_call("usp.raw", "list_notify", CWMP_UBUS_ARGS{ { "instance_mode", {.int_val = instance_mode }, UBUS_Integer } }, 1, ubus_get_parameter_callback, &list_notify_result); - if (e < 0) - CWMP_LOG(INFO, "list_notify ubus method failed: Ubus err code: %d", e); - return e; -} - /* * Set multiple parameter values */ @@ -438,3 +475,24 @@ char *cwmp_set_parameter_attributes(char *parameter_name, char *notification) return NULL; } + +/* + * Notifications functions + */ +int cwmp_update_enabled_notify_file(void) +{ + int e, fault; + struct cwmp *cwmp = &cwmp_main; + e = cwmp_ubus_call("usp.raw", "list_notify", CWMP_UBUS_ARGS{ { "instance_mode", {.int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 1, cwmp_update_enabled_notify_file_callback, &fault); + if (e || fault) + return 0; + return 1; +} + +int check_value_change(void) +{ + struct cwmp *cwmp = &cwmp_main; + int ret = 0; + cwmp_ubus_call("usp.raw", "list_notify", CWMP_UBUS_ARGS{ { "instance_mode", {.int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 1, ubus_check_value_change_callback, &ret); + return ret; +} diff --git a/inc/datamodel_interface.h b/inc/datamodel_interface.h index 6ad78ef..bef280b 100644 --- a/inc/datamodel_interface.h +++ b/inc/datamodel_interface.h @@ -7,17 +7,21 @@ extern bool transaction_started; extern int transaction_id; +struct blob_attr *get_parameters_array(struct blob_attr *msg); +int get_fault(struct blob_attr *msg); bool cwmp_transaction_start(char *app); bool cwmp_transaction_commit(); bool cwmp_transaction_abort(); bool cwmp_transaction_status(); char *cwmp_get_parameter_values(char *parameter_name, struct list_head *parameters_list); +char *cwmp_get_single_parameter_value(char *parameter_name, struct cwmp_dm_parameter *dm_parameter); int cwmp_set_multiple_parameters_values(struct list_head parameters_values_list, char *parameter_key, int *flag, struct list_head *faults_list); char *cwmp_add_object(char *object_name, char *key, char **instance); char *cwmp_delete_object(char *object_name, char *key); char *cwmp_get_parameter_names(char *object_name, bool next_level, struct list_head *parameters_list); char *cwmp_get_parameter_attributes(char *parameter_name, struct list_head *parameters_list); char *cwmp_set_parameter_attributes(char *parameter_name, char *notification); -int cwmp_update_enabled_list_notify(int instance_moden, struct list_head *parameters_list); +int cwmp_update_enabled_notify_file(); +int check_value_change(void); #endif /* SRC_DATAMODELIFACE_H_ */ diff --git a/inc/notifications.h b/inc/notifications.h index fae337b..142f1e5 100644 --- a/inc/notifications.h +++ b/inc/notifications.h @@ -13,6 +13,9 @@ #define NOTIFICATIONS_H_ #include #include +#include +#include + #include "common.h" #include "event.h" #include "datamodel_interface.h" @@ -32,9 +35,8 @@ extern struct list_head list_value_change; extern pthread_mutex_t mutex_value_change; #define DM_ENABLED_NOTIFY "/etc/icwmpd/.dm_enabled_notify" - -int cwmp_update_enabled_notify_file(); -int check_value_change(void); +void ubus_check_value_change_callback(struct ubus_request *req, int type, struct blob_attr *msg); +void cwmp_update_enabled_notify_file_callback(struct ubus_request *req, int type, struct blob_attr *msg); void sotfware_version_value_change(struct cwmp *cwmp, struct transfer_complete *p); void *thread_periodic_check_notify(void *v); void send_active_value_change(void); diff --git a/notifications.c b/notifications.c index 2fa4b57..74c8a60 100644 --- a/notifications.c +++ b/notifications.c @@ -13,98 +13,114 @@ #include #include #include + #include "notifications.h" +#include "ubus.h" LIST_HEAD(list_value_change); LIST_HEAD(list_lw_value_change); pthread_mutex_t mutex_value_change = PTHREAD_MUTEX_INITIALIZER; -int cwmp_update_enabled_notify_file() +void cwmp_update_enabled_notify_file_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg) { - struct cwmp *cwmp = &cwmp_main; FILE *fp; - LIST_HEAD(list_notify); - int e = cwmp_update_enabled_list_notify(cwmp->conf.instance_mode, &list_notify); - if (e) - return 0; - remove(DM_ENABLED_NOTIFY); + int *int_ret = (int *)req->priv; + *int_ret = get_fault(msg); + if (*int_ret) { + *int_ret = 0; + return; + } + remove(DM_ENABLED_NOTIFY); fp = fopen(DM_ENABLED_NOTIFY, "a"); if (fp == NULL) { - cwmp_free_all_dm_parameter_list(&list_notify); - return 0; + *int_ret = 0; + return; } - struct cwmp_dm_parameter *param_value = NULL; - list_for_each_entry (param_value, &list_notify, list) { + struct blob_attr *parameters = get_parameters_array(msg); + const struct blobmsg_policy p[5] = { { "parameter", BLOBMSG_TYPE_STRING }, { "value", BLOBMSG_TYPE_STRING }, { "type", BLOBMSG_TYPE_STRING }, { "notification", BLOBMSG_TYPE_STRING } }; + struct blob_attr *cur; + int rem; + blobmsg_for_each_attr(cur, parameters, rem) + { + struct blob_attr *tb[4] = { NULL, NULL, NULL, NULL }; + blobmsg_parse(p, 4, tb, blobmsg_data(cur), blobmsg_len(cur)); + if (!tb[0]) + continue; char *notif_line = NULL; - cwmp_asprintf(¬if_line, "parameter:%s notifcation:%d type:%s value:%s", param_value->name, param_value->notification, param_value->type, param_value->value); + cwmp_asprintf(¬if_line, "parameter:%s notifcation:%s type:%s value:%s", blobmsg_get_string(tb[0]), tb[3] ? blobmsg_get_string(tb[3]) : "", tb[2] ? blobmsg_get_string(tb[2]) : "", tb[1] ? blobmsg_get_string(tb[1]) : ""); fprintf(fp, "%s\n", notif_line); FREE(notif_line); } fclose(fp); - cwmp_free_all_dm_parameter_list(&list_notify); - return 1; } -void get_parameter_value_from_parameters_list(struct list_head *list_notif, char *parameter_name, struct cwmp_dm_parameter **ret_dm_param) +void get_parameter_value_from_parameters_list(struct blob_attr *list_notif, char *parameter_name, char **value, char **type) { - struct cwmp_dm_parameter *param_value = NULL; - list_for_each_entry (param_value, list_notif, list) { - if (param_value->name && strcmp(param_value->name, parameter_name) != 0) { + const struct blobmsg_policy p[5] = { { "parameter", BLOBMSG_TYPE_STRING }, { "value", BLOBMSG_TYPE_STRING }, { "type", BLOBMSG_TYPE_STRING } }; + struct blob_attr *cur; + int rem; + blobmsg_for_each_attr(cur, list_notif, rem) + { + struct blob_attr *tb[3] = { NULL, NULL, NULL }; + blobmsg_parse(p, 3, tb, blobmsg_data(cur), blobmsg_len(cur)); + if (!tb[0]) continue; - } - *ret_dm_param = (struct cwmp_dm_parameter *)calloc(1, sizeof(struct cwmp_dm_parameter)); - (*ret_dm_param)->name = strdup(param_value->name); - (*ret_dm_param)->value = strdup(param_value->value); - (*ret_dm_param)->type = strdup(param_value->type); + if (strcmp(parameter_name, blobmsg_get_string(tb[0])) != 0) + continue; + *value = strdup(tb[1] ? blobmsg_get_string(tb[1]) : ""); + *type = strdup(tb[2] ? blobmsg_get_string(tb[2]) : ""); break; } } -int check_value_change(void) +void ubus_check_value_change_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg) { FILE *fp; char buf[1280]; + char *dm_value = NULL, *dm_type = NULL; + int *int_ret = (int *)req->priv; + + *int_ret = get_fault(msg); + if (*int_ret) { + *int_ret = 0; + return; + } - struct cwmp *cwmp = &cwmp_main; - struct cwmp_dm_parameter *dm_parameter = NULL; - int is_notify = 0; fp = fopen(DM_ENABLED_NOTIFY, "r"); - if (fp == NULL) - return false; - LIST_HEAD(list_notify); - cwmp_update_enabled_list_notify(cwmp->conf.instance_mode, &list_notify); + if (fp == NULL) { + *int_ret = 0; + return; + } + + struct blob_attr *list_notify = get_parameters_array(msg); while (fgets(buf, 1280, fp) != NULL) { int len = strlen(buf); if (len) buf[len - 1] = '\0'; char parameter[128] = { 0 }, notification[2] = { 0 }, value[1024] = { 0 }, type[32] = { 0 }; sscanf(buf, "parameter:%s notifcation:%s type:%s value:%s\n", parameter, notification, type, value); - get_parameter_value_from_parameters_list(&list_notify, parameter, &dm_parameter); - if (dm_parameter == NULL) + get_parameter_value_from_parameters_list(list_notify, parameter, &dm_value, &dm_type); + if (dm_value == NULL && dm_type == NULL) continue; - if ((strlen(notification) > 0) && (notification[0] >= '1') && (dm_parameter->value != NULL) && (strcmp(dm_parameter->value, value) != 0)) { + if ((strlen(notification) > 0) && (notification[0] >= '1') && (dm_value != NULL) && (strcmp(dm_value, value) != 0)) { if (notification[0] == '1' || notification[0] == '2') - add_list_value_change(parameter, dm_parameter->value, dm_parameter->type); + add_list_value_change(parameter, dm_value, dm_type); if (notification[0] >= '3') - add_lw_list_value_change(parameter, dm_parameter->value, dm_parameter->type); + add_lw_list_value_change(parameter, dm_value, dm_type); if (notification[0] == '1') - is_notify |= NOTIF_PASSIVE; + *int_ret |= NOTIF_PASSIVE; if (notification[0] == '2') - is_notify |= NOTIF_ACTIVE; + *int_ret |= NOTIF_ACTIVE; if (notification[0] == '5' || notification[0] == '6') - is_notify |= NOTIF_LW_ACTIVE; + *int_ret |= NOTIF_LW_ACTIVE; } - FREE(dm_parameter->name); - FREE(dm_parameter->value); - FREE(dm_parameter->type); - FREE(dm_parameter); + FREE(dm_value); + FREE(dm_type); } fclose(fp); - cwmp_free_all_dm_parameter_list(&list_notify); - return is_notify; } void sotfware_version_value_change(struct cwmp *cwmp, struct transfer_complete *p) diff --git a/xml.c b/xml.c index 5ed8e33..da86ec1 100644 --- a/xml.c +++ b/xml.c @@ -561,15 +561,8 @@ static int xml_prepare_parameters_inform(struct cwmp_dm_parameter *dm_parameter, (*size)--; goto create_value; - } else if (b && dm_parameter->value == NULL) { + } else if (dm_parameter->value == NULL) return 0; - } else if (!b && dm_parameter->value == NULL) { - LIST_HEAD(list_specific_inform); - char *err = cwmp_get_parameter_values(dm_parameter->name, &list_specific_inform); - cwmp_free_all_dm_parameter_list(&list_specific_inform); - FREE(err); - return 0; - } node = mxmlNewElement(parameter_list, "ParameterValueStruct"); if (!node) return -1; @@ -841,19 +834,19 @@ int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *sessi size_t inform_parameters_nbre = sizeof(forced_inform_parameters) / sizeof(forced_inform_parameters[0]); size_t i; - struct cwmp_dm_parameter *cwmp_dm_param = NULL; + struct cwmp_dm_parameter cwmp_dm_param = { 0 }; LIST_HEAD(list_inform); for (i = 0; i < inform_parameters_nbre; i++) { - char *fault = cwmp_get_parameter_values(forced_inform_parameters[i], &list_inform); + char *fault = cwmp_get_single_parameter_value(forced_inform_parameters[i], &cwmp_dm_param); if (fault != NULL) { FREE(fault); continue; } - list_for_each_entry (cwmp_dm_param, &list_inform, list) { - if (xml_prepare_parameters_inform(cwmp_dm_param, parameter_list, &size)) - goto error; - } - cwmp_free_all_dm_parameter_list(&list_inform); + if (xml_prepare_parameters_inform(&cwmp_dm_param, parameter_list, &size)) + goto error; + FREE(cwmp_dm_param.name); + FREE(cwmp_dm_param.value); + FREE(cwmp_dm_param.type); } if (cwmp_asprintf(&c, "cwmp:ParameterValueStruct[%d]", size) == -1) goto error;