From d92ef77e289733fb825522a3f20bb27d3bbde6e3 Mon Sep 17 00:00:00 2001 From: Omar Kallel Date: Fri, 27 Jan 2023 15:55:28 +0100 Subject: [PATCH] Ticket refs #9642: CWMP SPAs not persistent --- gitlab-ci/unit-test.sh | 2 ++ src/common.c | 6 ++-- src/cwmp.c | 7 +++-- src/cwmp_uci.c | 3 +- src/cwmp_uci.h | 4 ++- src/datamodel.c | 2 +- src/download.c | 4 +-- src/notifications.c | 32 ++++++++++++++------- src/notifications.h | 3 ++ test/cmocka/icwmp_notifications_unit_test.c | 2 +- test/script/verify_custom_notifications.sh | 30 +++++++++---------- 11 files changed, 59 insertions(+), 36 deletions(-) diff --git a/gitlab-ci/unit-test.sh b/gitlab-ci/unit-test.sh index b58025b..0793c32 100755 --- a/gitlab-ci/unit-test.sh +++ b/gitlab-ci/unit-test.sh @@ -7,6 +7,8 @@ pwd trap cleanup EXIT trap cleanup SIGINT +if [ ! -f /etc/icwmpd/cwmp_notifications ]; then touch /etc/icwmpd/cwmp_notifications; fi + echo "Configure download server" configure_download_firmware diff --git a/src/common.c b/src/common.c index e257ae2..9fc6ada 100755 --- a/src/common.c +++ b/src/common.c @@ -314,8 +314,8 @@ void check_firewall_restart_state() */ void cwmp_reboot(char *command_key) { - cwmp_uci_set_varstate_value("cwmp", "cpe", "ParameterKey", command_key); - cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); + cwmp_uci_set_value("cwmp", "cpe", "ParameterKey", command_key); + cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); struct blob_buf b = { 0 }; memset(&b, 0, sizeof(struct blob_buf)); @@ -324,6 +324,8 @@ void cwmp_reboot(char *command_key) icwmp_ubus_invoke("rpc-sys", "reboot", b.head, NULL, NULL); blob_buf_free(&b); + + sleep(5); } /* diff --git a/src/cwmp.c b/src/cwmp.c index 83067e2..b3dc076 100644 --- a/src/cwmp.c +++ b/src/cwmp.c @@ -93,7 +93,7 @@ void set_interface_reset_request(char *param_name, char *value) list_add_tail(&node->list, &intf_reset_list); } -int create_cwmp_var_state_files() +int create_cwmp_temporary_files() { /* * Create Notifications empty uci package @@ -228,7 +228,10 @@ static int cwmp_init() if (cwmp_main->pid_file) fclose(cwmp_main->pid_file); - if ((error = create_cwmp_var_state_files())) + if ((error = create_cwmp_temporary_files())) + return error; + + if ((error = create_cwmp_notifications_package())) return error; CWMP_LOG(DEBUG, "Loading icwmpd configuration"); diff --git a/src/cwmp_uci.c b/src/cwmp_uci.c index d65feba..0b58031 100644 --- a/src/cwmp_uci.c +++ b/src/cwmp_uci.c @@ -19,7 +19,8 @@ struct uci_paths uci_save_conf_paths[] = { [UCI_STANDARD_CONFIG] = { "/etc/config", "/tmp/.uci", NULL }, - [UCI_VARSTATE_CONFIG] = { "/var/state", NULL, NULL } + [UCI_VARSTATE_CONFIG] = { "/var/state", NULL, NULL }, + [UCI_ETCICWMPD_CONFIG] = {"/etc/icwmpd", NULL, NULL} }; /* diff --git a/src/cwmp_uci.h b/src/cwmp_uci.h index c585430..ef7f395 100644 --- a/src/cwmp_uci.h +++ b/src/cwmp_uci.h @@ -77,7 +77,8 @@ typedef enum uci_config_paths { UCI_STANDARD_CONFIG, - UCI_VARSTATE_CONFIG + UCI_VARSTATE_CONFIG, + UCI_ETCICWMPD_CONFIG }uci_config_paths; enum uci_val_type @@ -130,6 +131,7 @@ int cwmp_uci_init(); void cwmp_uci_exit(void); void cwmp_uci_reinit(void); int cwmp_uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *package, char *section, char *option, char *value); +int cwmp_uci_get_option_value_list(char *package, char *section, char *option, uci_config_paths uci_type, struct uci_list **value); int cwmp_uci_get_cwmp_standard_option_value_list(char *package, char *section, char *option, struct uci_list **value); int cwmp_uci_get_cwmp_varstate_option_value_list(char *package, char *section, char *option, struct uci_list **value); int uci_get_state_value(char *cmd, char **value); diff --git a/src/datamodel.c b/src/datamodel.c index a3c76fd..6b4ba29 100644 --- a/src/datamodel.c +++ b/src/datamodel.c @@ -371,7 +371,7 @@ static int set_management_server_delay_reboot(char *refparam, struct dmctx *ctx, /*#Device.ManagementServer.ParameterKey!UCI:cwmp/acs,acs/ParameterKey*/ static int get_management_server_key(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - dmuci_get_option_value_string_varstate("cwmp", "cpe", "ParameterKey", value); + dmuci_get_option_value_string("cwmp", "cpe", "ParameterKey", value); return 0; } diff --git a/src/download.c b/src/download.c index bb3017f..7f1482a 100644 --- a/src/download.c +++ b/src/download.c @@ -537,8 +537,8 @@ int apply_downloaded_file(struct download *pdownload, char *download_file_name, error = FAULT_CPE_INVALID_ARGUMENTS; if ((error == FAULT_CPE_NO_FAULT) && (pdownload->file_type[0] == '1' || pdownload->file_type[0] == '3')) { - cwmp_uci_set_varstate_value("cwmp", "cpe", "ParameterKey", pdownload->command_key ? pdownload->command_key : ""); - cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); + cwmp_uci_set_value("cwmp", "cpe", "ParameterKey", pdownload->command_key ? pdownload->command_key : ""); + cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); if (pdownload->file_type[0] == '3') { CWMP_LOG(INFO, "Download and apply new vendor config file is done successfully"); //cwmp_root_cause_transfer_complete(ptransfer_complete); diff --git a/src/notifications.c b/src/notifications.c index 8fbab18..7789de8 100644 --- a/src/notifications.c +++ b/src/notifications.c @@ -48,6 +48,18 @@ char *forced_notifications_parameters[] = { /* * Common functions */ +int create_cwmp_notifications_package() +{ + if (!file_exists(CWMP_NOTIFICATIONS_PACKAGE)) { + FILE *fptr = fopen(CWMP_NOTIFICATIONS_PACKAGE, "w+"); + if (fptr) + fclose(fptr); + else + return CWMP_GEN_ERR; + } + return CWMP_OK; +} + static bool parameter_is_subobject_of_parameter(char *parent, char *child) { if (child == NULL) { @@ -105,18 +117,18 @@ int add_uci_option_notification(char *parameter_name, int notification) struct uci_section *s = NULL; int ret = 0; - ret = cwmp_uci_get_section_type("cwmp", "@notifications[0]", UCI_VARSTATE_CONFIG, ¬ification_type); + ret = cwmp_uci_get_section_type("cwmp_notifications", "@notifications[0]", UCI_ETCICWMPD_CONFIG, ¬ification_type); if (ret != UCI_OK) return -1; if (notification_type == NULL || notification_type[0] == '\0') { - cwmp_uci_add_section("cwmp", "notifications", UCI_VARSTATE_CONFIG, &s); + cwmp_uci_add_section("cwmp_notifications", "notifications", UCI_ETCICWMPD_CONFIG, &s); } - ret = cwmp_uci_add_list_value("cwmp", "@notifications[0]", notifications[notification], parameter_name, UCI_VARSTATE_CONFIG); + ret = cwmp_uci_add_list_value("cwmp_notifications", "@notifications[0]", notifications[notification], parameter_name, UCI_ETCICWMPD_CONFIG); if (ret != UCI_OK) return -1; - ret = cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); + ret = cwmp_commit_package("cwmp_notifications", UCI_ETCICWMPD_CONFIG); return ret; } @@ -130,7 +142,7 @@ bool check_parent_with_different_notification(char *parameter_name, int notifica if (i == notification) continue; - option_type = cwmp_uci_get_cwmp_varstate_option_value_list("cwmp", "@notifications[0]", notifications[i], &list_notif); + option_type = cwmp_uci_get_option_value_list("cwmp_notifications", "@notifications[0]", notifications[i], UCI_ETCICWMPD_CONFIG, &list_notif); if (list_notif) { uci_foreach_element(list_notif, e) { if (parameter_is_subobject_of_parameter(e->name, parameter_name)) @@ -155,19 +167,19 @@ bool update_notifications_list(char *parameter_name, int notification) parameter_name = "Device."; for (i = 0; i < 7; i++) { int option_type; - option_type = cwmp_uci_get_cwmp_varstate_option_value_list("cwmp", "@notifications[0]", notifications[i], &list_notif); + option_type = cwmp_uci_get_option_value_list("cwmp_notifications", "@notifications[0]", notifications[i], UCI_ETCICWMPD_CONFIG, &list_notif); if (list_notif) { uci_foreach_element_safe(list_notif, tmp, e) { if (e->name == NULL) continue; ename = strdup(e->name); if ((strcmp(parameter_name, e->name) == 0 && (i != notification)) || parameter_is_subobject_of_parameter(parameter_name, e->name)) - cwmp_uci_del_list_value("cwmp", "@notifications[0]", notifications[i], e->name, UCI_VARSTATE_CONFIG); + cwmp_uci_del_list_value("cwmp_notifications", "@notifications[0]", notifications[i], e->name, UCI_ETCICWMPD_CONFIG); if (ename && (strcmp(parameter_name, ename) == 0 || parameter_is_subobject_of_parameter(ename, parameter_name) ) && (i == notification)) update_ret = false; FREE(ename); } - cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); + cwmp_commit_package("cwmp_notifications", UCI_ETCICWMPD_CONFIG); } if (option_type == UCI_TYPE_STRING) cwmp_free_uci_list(list_notif); @@ -213,7 +225,7 @@ int get_parameter_family_notifications(char *parameter_name, struct list_head *c for (i = 0; i < 7; i++) { int option_type; - option_type = cwmp_uci_get_cwmp_varstate_option_value_list("cwmp", "@notifications[0]", notifications[i], &list_notif); + option_type = cwmp_uci_get_option_value_list("cwmp_notifications", "@notifications[0]", notifications[i], UCI_ETCICWMPD_CONFIG, &list_notif); if (list_notif) { uci_foreach_element(list_notif, e) { if (parameter_is_subobject_of_parameter(parameter_name, e->name)) { @@ -335,7 +347,7 @@ void create_list_param_obj_notify() cwmp_uci_reinit(); for (i = 0; i < 7; i++) { int option_type; - option_type = cwmp_uci_get_cwmp_varstate_option_value_list("cwmp", "@notifications[0]", notifications[i], &list_notif); + option_type = cwmp_uci_get_option_value_list("cwmp_notifications", "@notifications[0]", notifications[i], UCI_ETCICWMPD_CONFIG, &list_notif); if (list_notif) { uci_foreach_element(list_notif, e) { add_dm_parameter_to_list(&list_param_obj_notify, e->name, "", "", i, false); diff --git a/src/notifications.h b/src/notifications.h index 32433b3..ac91980 100644 --- a/src/notifications.h +++ b/src/notifications.h @@ -18,6 +18,8 @@ #include "common.h" +#define CWMP_NOTIFICATIONS_PACKAGE "/etc/icwmpd/cwmp_notifications" + enum NOTIFICATION_STATUS { NOTIF_NONE = 0, @@ -48,6 +50,7 @@ extern struct uloop_timeout check_notify_timer; #define DM_ENABLED_NOTIFY "/var/run/icwmpd/dm_enabled_notify" #define NOTIFY_MARKER "/etc/icwmpd/icwmpd_notify_import_marker" #define RUN_NOTIFY_MARKER "/var/run/icwmpd/icwmpd_notify_import_marker" +int create_cwmp_notifications_package(); void ubus_check_value_change_callback(struct ubus_request *req, int type, struct blob_attr *msg); void cwmp_update_enabled_notify_file(void); int check_value_change(void); diff --git a/test/cmocka/icwmp_notifications_unit_test.c b/test/cmocka/icwmp_notifications_unit_test.c index e891bae..26a94c0 100644 --- a/test/cmocka/icwmp_notifications_unit_test.c +++ b/test/cmocka/icwmp_notifications_unit_test.c @@ -105,7 +105,7 @@ static int get_parameter_notification_from_notifications_uci_list(char *paramete struct uci_element *e; for (i = 0; i < 7; i++) { int option_type; - option_type = cwmp_uci_get_cwmp_varstate_option_value_list("cwmp", "@notifications[0]", notifications_test[i], &list_notif); + option_type = cwmp_uci_get_option_value_list("cwmp_notifications", "@notifications[0]", notifications_test[i], UCI_ETCICWMPD_CONFIG, &list_notif); if (list_notif) { uci_foreach_element(list_notif, e) { if (strcmp(e->name, parameter_name) == 0) { diff --git a/test/script/verify_custom_notifications.sh b/test/script/verify_custom_notifications.sh index d13d43c..60b8c7b 100755 --- a/test/script/verify_custom_notifications.sh +++ b/test/script/verify_custom_notifications.sh @@ -15,8 +15,6 @@ exec_cmd cp test/files/etc/icwmpd/custom_notification* /etc/icwmpd # Test a valid custom notification json file # rm /var/log/icwmpd.log -uci -c /var/state delete cwmp.@notifications[0] -uci -c /var/state commit cwmp exec_cmd uci set cwmp.cpe.custom_notify_json="/etc/icwmpd/custom_notification_valid.json" uci commit cwmp @@ -29,12 +27,12 @@ supervisorctl stop icwmpd check_valgrind_xml -notif1=`uci -c /var/state get cwmp.@notifications[0].active | grep "Device.Users."` +notif1=`uci -c /etc/icwmpd get cwmp_notifications.@notifications[0].active | grep "Device.Users."` if [[ $notif1 != *"Device.Users."* ]]; then echo "FAIL: active notifications list doesn't contain Device.Users. parameter" exit 1 fi -notif2=`uci -c /var/state get cwmp.@notifications[0].passive | grep "Device.WiFi.SSID.1.SSID"` +notif2=`uci -c /etc/icwmpd get cwmp_notifications.@notifications[0].passive | grep "Device.WiFi.SSID.1.SSID"` if [[ $notif2 != *"Device.WiFi.SSID.1.SSID"* ]]; then echo "FAIL: active notifications list doesn't contain Device.WiFi.SSID.1.SSID parameter" exit 1 @@ -48,8 +46,8 @@ echo "PASS test valid custom notification json file" # Test custom notification invalid json file # rm /var/log/icwmpd.log -uci -c /var/state delete cwmp.@notifications[0] -uci -c /var/state commit cwmp +uci -c /etc/icwmpd delete cwmp_notifications.@notifications[0] +uci -c /etc/icwmpd commit cwmp_notifications exec_cmd uci set cwmp.cpe.custom_notify_json="/etc/icwmpd/custom_notification_invalid_json.json" uci commit cwmp @@ -62,12 +60,12 @@ supervisorctl stop icwmpd check_valgrind_xml -notif1=`uci -c /var/state get cwmp.@notifications[0].active | grep "Device.Users."` +notif1=`uci -c /etc/icwmpd get cwmp_notifications.@notifications[0].active | grep "Device.Users."` if [[ $notif1 == *"Device.Users."* ]]; then echo "FAIL: the json file is invalid, the active notifcation list shouldn't contain Device.Users. parameter" exit 1 fi -notif2=`uci -c /var/state get cwmp.@notifications[0].passive | grep "Device.WiFi.SSID.1.SSID"` +notif2=`uci -c /etc/icwmpd get cwmp_notifications.@notifications[0].passive | grep "Device.WiFi.SSID.1.SSID"` if [[ $notif2 == *"Device.WiFi.SSID.1.SSID"* ]]; then echo "FAIL: the json file is invalid, the active notifcation list shouldn't contain Device.WiFi.SSID.1.SSID parameter" exit 1 @@ -87,8 +85,8 @@ rm /etc/icwmpd/icwmpd_notify # Test custom notification json file containing forced active notification # rm /var/log/icwmpd.log -uci -c /var/state delete cwmp.@notifications[0] -uci -c /var/state commit cwmp +uci -c /etc/icwmpd delete cwmp_notifications.@notifications[0] +uci -c /etc/icwmpd commit cwmp_notifications exec_cmd uci set cwmp.cpe.custom_notify_json="/etc/icwmpd/custom_notification_forced.json" uci commit cwmp @@ -100,12 +98,12 @@ supervisorctl stop icwmpd check_valgrind_xml -notif1=`uci -c /var/state get cwmp.@notifications[0].active | grep "Device.Users."` +notif1=`uci -c /etc/icwmpd get cwmp_notifications.@notifications[0].active | grep "Device.Users."` if [[ $notif1 != *"Device.Users."* ]]; then echo "FAIL: active notifications list doesn't contain Device.Users. parameter" exit 1 fi -notif2=`uci -c /var/state get cwmp.@notifications[0].passive | grep "Device.DeviceInfo.ProvisioningCode"` +notif2=`uci -c /etc/icwmpd get cwmp_notifications.@notifications[0].passive | grep "Device.DeviceInfo.ProvisioningCode"` if [[ $notif2 == *"Device.DeviceInfo.ProvisioningCode"* ]]; then echo "FAIL: passive notifications list contains Device.DeviceInfo.ProvisioningCode while it's a forced active notification paramter" exit 1 @@ -125,8 +123,8 @@ rm /etc/icwmpd/icwmpd_notify # Test custom notification json file containing invalid parameter path # rm /var/log/icwmpd.log -uci -c /var/state delete cwmp.@notifications[0] -uci -c /var/state commit cwmp +uci -c /etc/icwmpd delete cwmp_notifications.@notifications[0] +uci -c /etc/icwmpd commit cwmp_notifications exec_cmd uci set cwmp.cpe.custom_notify_json="/etc/icwmpd/custom_notification_invalid_parameter.json" uci commit cwmp @@ -138,12 +136,12 @@ supervisorctl stop icwmpd check_valgrind_xml -notif1=`uci -c /var/state get cwmp.@notifications[0].active | grep "Device.Users."` +notif1=`uci -c /etc/icwmpd get cwmp_notifications.@notifications[0].active | grep "Device.Users."` if [[ $notif1 != *"Device.Users."* ]]; then echo "FAIL: active notifications list doesn't contain Device.Users. parameter" exit 1 fi -notif2=`uci -c /var/state get cwmp.@notifications[0].passive | grep "Device.WiFi.SSID.1.SD"` +notif2=`uci -c /etc/icwmpd get cwmp_notifications.@notifications[0].passive | grep "Device.WiFi.SSID.1.SD"` if [[ $notif2 == *"Device.WiFi.SSID.1.SD"* ]]; then echo "FAIL: passive notifications list contains Device.WiFi.SSID.1.SD while it's a wrong parameter path" exit 1