diff --git a/.gitignore b/.gitignore index b0d3365..04bb3dc 100644 --- a/.gitignore +++ b/.gitignore @@ -2,10 +2,8 @@ *.swo *.o *.lo -*.log -*.xml -*.so bin/* +/icwmpd !bin/Makefile.am .prepared* .built* @@ -14,6 +12,7 @@ bin/* ABOUT-NLS INSTALL Makefile.in +/Makefile aclocal.m4 autom4te.cache/ compile @@ -35,5 +34,6 @@ missing /ltmain.sh *.gcno *.gcda -/icwmpd -/Makefile +/*.log +/*.xml +/report diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7960585..0fe1220 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,8 +4,8 @@ include: variables: DEBUG: 'TRUE' - COMMON_IMAGE: "iopsys/code-analysis:0.27" - RUN_CPPCHECK: "cppcheck --force --enable=all --error-exitcode=1 -D_GNU_SOURCE --include=/usr/include/libubox/list.h --include=/usr/include/uci.h -I ./inc --suppress=unusedFunction -i ./test/ --inline-suppr" + COMMON_IMAGE: "iopsys/code-analysis:0.25" + RUN_CPPCHECK: "cppcheck --enable=all --inline-suppr --include=/usr/include/uci.h --suppress=unusedFunction -i ./test/" SOURCE_FOLDER: "." CWMP_WORKER_PROCESSES: 1 NBI_WORKER_PROCESSES: 1 @@ -69,4 +69,4 @@ run_functional_test: - funl-test-coverage.xml - funl-test-memory-report.xml - funl-test-result.log - - funl-test-debug.log + - funl-test-debug.log \ No newline at end of file diff --git a/Makefile.am b/Makefile.am index 9f5379d..ff20fdf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ MAINTAINERCLEANFILES = Makefile.in -CWMP_VERSION = 3.0.1 +CWMP_VERSION = 3.0.2 bin_PROGRAMS = icwmpd @@ -10,12 +10,15 @@ icwmpd_SOURCES = \ ./log.c \ ./cwmp_uci.c \ ./config.c \ + ./cwmp_config.c \ ./session.c \ ./backupSession.c \ ./md5.c \ ./digestauth.c \ ./event.c \ + ./cwmp_event.c \ ./http.c \ + ./cwmp_http.c \ ./netlink.c \ ./ubus.c \ ./datamodel_interface.c \ @@ -23,15 +26,16 @@ icwmpd_SOURCES = \ ./notifications.c \ ./cwmp_zlib.c \ ./cwmp_du_state.c \ + ./subprocess.c \ ./download.c \ ./upload.c \ ./sched_inform.c \ ./xml.c \ - ./rpc_soap.c \ + ./soap.c \ ./diagnostic.c \ ./reboot.c \ - ./cwmp.c \ - ./ssl_utils.c + ./ssl_utils.c \ + ./cwmp.c icwmpd_CFLAGS = \ $(AM_CFLAGS) \ @@ -40,7 +44,7 @@ icwmpd_CFLAGS = \ $(LIBUBUS_CFLAGS) \ $(MICROXML_CFLAGS) \ $(LIBCURL_CFLAGS) \ - -Wall -Wextra \ + -g -Wall -Wextra \ -Wformat icwmpd_LDFLAGS = \ diff --git a/backupSession.c b/backupSession.c index 3cbecd7..d96a3df 100644 --- a/backupSession.c +++ b/backupSession.c @@ -11,16 +11,18 @@ */ #include +#include #include "backupSession.h" #include "log.h" -#include "event.h" -#include "sched_inform.h" -#include "download.h" -#include "upload.h" -#include "cwmp_du_state.h" #include "notifications.h" -#include "xml.h" +#include "event.h" +#include "download.h" +#include "cwmp_du_state.h" +#include "soap.h" +#include "upload.h" +#include "sched_inform.h" +#include "cwmp_event.h" static mxml_node_t *bkp_tree = NULL; pthread_mutex_t mutex_backup_session = PTHREAD_MUTEX_INITIALIZER; @@ -445,82 +447,9 @@ void bkp_session_insert_schedule_download(struct download *pschedule_download) pthread_mutex_unlock(&mutex_backup_session); } -void bkp_session_insert_apply_schedule_download(struct apply_schedule_download *papply_schedule_download) -{ - char delay[4][128]; - int i; - char maxretrie[2][128]; - mxml_node_t *b; - - pthread_mutex_lock(&mutex_backup_session); - - for (i = 0; i < 2; i++) { - snprintf(delay[2 * i], sizeof(delay[i]), "%lld", (long long int)papply_schedule_download->timeintervals[i].windowstart); - snprintf(delay[2 * i + 1], sizeof(delay[i]), "%lld", (long long int)papply_schedule_download->timeintervals[i].windowend); - snprintf(maxretrie[i], sizeof(maxretrie[i]), "%d", papply_schedule_download->timeintervals[i].maxretries); - } - - struct search_keywords sched_download_insert_app_keys[9] = { { "command_key", papply_schedule_download->command_key }, - { "file_type", papply_schedule_download->file_type }, - { "start_time", papply_schedule_download->start_time }, - { "windowstart1", delay[0] }, - { "windowend1", delay[1] }, - { "maxretrie1", maxretrie[0] }, - { "windowstart2", delay[2] }, - { "windowend2", delay[3] }, - { "maxretrie2", maxretrie[1] } }; - - b = bkp_session_node_found(bkp_tree, "apply_schedule_download", sched_download_insert_app_keys, 9); - if (!b) { - CWMP_LOG(INFO, "New schedule download key %s file", papply_schedule_download->command_key); - b = bkp_session_insert(bkp_tree, "apply_schedule_download", NULL); - bkp_session_insert(b, "start_time", papply_schedule_download->start_time); - bkp_session_insert(b, "command_key", papply_schedule_download->command_key); - bkp_session_insert(b, "file_type", papply_schedule_download->file_type); - bkp_session_insert(b, "windowstart1", delay[0]); - bkp_session_insert(b, "windowend1", delay[1]); - bkp_session_insert(b, "maxretrie1", maxretrie[0]); - - bkp_session_insert(b, "windowstart2", delay[2]); - bkp_session_insert(b, "windowend2", delay[3]); - bkp_session_insert(b, "maxretrie2", maxretrie[1]); - } - pthread_mutex_unlock(&mutex_backup_session); -} - -void bkp_session_delete_apply_schedule_download(struct apply_schedule_download *ps_download) //TODO -{ - char delay[4][128]; - char maxretrie[2][128]; - int i; - mxml_node_t *b; - - pthread_mutex_lock(&mutex_backup_session); - for (i = 0; i < 2; i++) { - snprintf(delay[2 * i], sizeof(delay[i]), "%lld", (long long int)ps_download->timeintervals[i].windowstart); - snprintf(delay[2 * i + 1], sizeof(delay[i]), "%lld", (long long int)ps_download->timeintervals[i].windowend); - snprintf(maxretrie[i], sizeof(maxretrie[i]), "%d", ps_download->timeintervals[i].maxretries); - } - struct search_keywords sched_download_del_app_keys[9] = { { "start_time", ps_download->start_time }, - { "command_key", ps_download->command_key }, - { "file_type", ps_download->file_type }, - { "windowstart1", delay[0] }, - { "windowend1", delay[1] }, - { "maxretrie1", maxretrie[0] }, - { "windowstart2", delay[2] }, - { "windowend2", delay[3] }, - { "maxretrie2", maxretrie[1] } }; - - b = bkp_session_node_found(bkp_tree, "apply_schedule_download", sched_download_del_app_keys, 9); - - if (b) - mxmlDelete(b); - pthread_mutex_unlock(&mutex_backup_session); -} - void bkp_session_insert_change_du_state(struct change_du_state *pchange_du_state) { - struct operations *p; + struct operations *p = NULL; char schedule_time[128]; mxml_node_t *b, *n; @@ -529,6 +458,7 @@ void bkp_session_insert_change_du_state(struct change_du_state *pchange_du_state b = bkp_session_insert(bkp_tree, "change_du_state", NULL); bkp_session_insert(b, "command_key", pchange_du_state->command_key); bkp_session_insert(b, "time", schedule_time); + list_for_each_entry (p, &(pchange_du_state->list_operation), list) { if (p->type == DU_INSTALL) { n = bkp_session_insert(b, "install", NULL); @@ -661,7 +591,7 @@ void bkp_session_delete_upload(struct upload *pupload) void bkp_session_insert_du_state_change_complete(struct du_state_change_complete *pdu_state_change_complete) { char schedule_time[128], resolved[8], fault_code[8]; - struct opresult *p; + struct opresult *p = NULL; mxml_node_t *b; pthread_mutex_lock(&mutex_backup_session); @@ -751,11 +681,9 @@ void bkp_session_delete_transfer_complete(struct transfer_complete *ptransfer_co pthread_mutex_unlock(&mutex_backup_session); } -int save_acs_bkp_config(struct cwmp *cwmp) +int save_acs_bkp_config() { - struct config *conf; - - conf = &(cwmp->conf); + struct config *conf = &(cwmp_main->conf); bkp_session_simple_insert("acs", "url", conf->acsurl); bkp_session_save(); return CWMP_OK; @@ -783,11 +711,11 @@ char *load_child_value(mxml_node_t *tree, char *sub_name) return value; } -void load_queue_event(mxml_node_t *tree, struct cwmp *cwmp) +void load_queue_event(mxml_node_t *tree) { char *command_key = NULL; mxml_node_t *b = tree, *c; - int idx = -1, id = -1; + int idx, id = -1; struct event_container *event_container_save = NULL; struct backup_attributes bkp_attrs = { .index = &idx, .id = &id, .command_key = &command_key }; @@ -798,14 +726,10 @@ void load_queue_event(mxml_node_t *tree, struct cwmp *cwmp) while (b) { if (b->type == MXML_ELEMENT) { if (strcmp(b->value.element.name, "command_key") == 0) { - /* - * This condition is not always false. - * while the value of idx can be changed while call of load_specific_backup_attributes. - */ // cppcheck-suppress knownConditionTrueFalse if (idx != -1) { if (EVENT_CONST[idx].RETRY & EVENT_RETRY_AFTER_REBOOT) { - event_container_save = cwmp_add_event_container(cwmp, idx, ((command_key != NULL) ? command_key : "")); + event_container_save = cwmp_add_event_container(idx, ((command_key != NULL) ? command_key : "")); if (event_container_save != NULL) { event_container_save->id = id; } @@ -832,7 +756,7 @@ void load_schedule_inform(mxml_node_t *tree) char *command_key = NULL; time_t scheduled_time = 0; struct schedule_inform *schedule_inform = NULL; - struct list_head *ilist; + struct list_head *ilist = NULL; struct backup_attributes bkp_attrs = { .command_key = &command_key, .time = &scheduled_time }; load_specific_backup_attributes(tree, &bkp_attrs); @@ -867,6 +791,7 @@ void load_download(mxml_node_t *tree) .file_size = &download_request->file_size, .time = &download_request->scheduled_time }; load_specific_backup_attributes(tree, &bkp_attrs); + download_request->handler_timer.cb = cwmp_start_download; list_for_each (ilist, &(list_download)) { idownload_request = list_entry(ilist, struct download, list); @@ -877,6 +802,7 @@ void load_download(mxml_node_t *tree) list_add(&(download_request->list), ilist->prev); if (download_request->scheduled_time != 0) count_download_queue++; + cwmp_set_end_session(END_SESSION_DOWNLOAD); } void load_schedule_download(mxml_node_t *tree) @@ -918,30 +844,6 @@ void load_schedule_download(mxml_node_t *tree) count_download_queue++; } -void load_apply_schedule_download(mxml_node_t *tree) -{ - struct apply_schedule_download *download_request = NULL; - - download_request = calloc(1, sizeof(struct apply_schedule_download)); - - struct backup_attributes bkp_attrs = { - .command_key = &download_request->command_key, - .file_type = &download_request->file_type, - .start_time = &download_request->start_time, - .windowstart1 = &download_request->timeintervals[0].windowstart, - .windowend1 = &download_request->timeintervals[0].windowend, - .maxretrie1 = &download_request->timeintervals[0].maxretries, - .windowstart2 = &download_request->timeintervals[1].windowstart, - .windowend2 = &download_request->timeintervals[1].windowend, - .maxretrie2 = &download_request->timeintervals[1].maxretries, - }; - load_specific_backup_attributes(tree, &bkp_attrs); - - list_add_tail(&(download_request->list), &(list_apply_schedule_download)); - if (download_request->timeintervals[0].windowstart != 0) - count_download_queue++; -} - void load_upload(mxml_node_t *tree) { struct upload *upload_request = NULL; @@ -1006,7 +908,7 @@ void load_change_du_state(mxml_node_t *tree) list_add_tail(&(change_du_state_request->list_operation), &(list_change_du_state)); } -void load_du_state_change_complete(mxml_node_t *tree, struct cwmp *cwmp) +void load_du_state_change_complete(mxml_node_t *tree) { mxml_node_t *b = tree; struct du_state_change_complete *du_state_change_complete_request = NULL; @@ -1040,10 +942,10 @@ void load_du_state_change_complete(mxml_node_t *tree, struct cwmp *cwmp) } b = mxmlWalkNext(b, tree, MXML_NO_DESCEND); } - cwmp_root_cause_changedustate_complete(cwmp, du_state_change_complete_request); + cwmp_root_cause_changedustate_complete(du_state_change_complete_request); } -void load_transfer_complete(mxml_node_t *tree, struct cwmp *cwmp) +void load_transfer_complete(mxml_node_t *tree) { struct transfer_complete *ptransfer_complete; @@ -1057,8 +959,8 @@ void load_transfer_complete(mxml_node_t *tree, struct cwmp *cwmp) .type = &ptransfer_complete->type }; load_specific_backup_attributes(tree, &bkp_attrs); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - sotfware_version_value_change(cwmp, ptransfer_complete); + cwmp_root_cause_transfer_complete(ptransfer_complete); + sotfware_version_value_change(ptransfer_complete); } void bkp_session_create_file() @@ -1103,16 +1005,16 @@ int bkp_session_check_file() return 0; } -int cwmp_init_backup_session(struct cwmp *cwmp, char **ret, enum backup_loading load) +int cwmp_init_backup_session(char **ret, enum backup_loading load) { int error; if (bkp_session_check_file()) return 0; - error = cwmp_load_saved_session(cwmp, ret, load); + error = cwmp_load_saved_session(ret, load); return error; } -int cwmp_load_saved_session(struct cwmp *cwmp, char **ret, enum backup_loading load) +int cwmp_load_saved_session(char **ret, enum backup_loading load) { mxml_node_t *b; @@ -1145,23 +1047,21 @@ int cwmp_load_saved_session(struct cwmp *cwmp, char **ret, enum backup_loading l } if (load == ALL) { if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "queue_event") == 0) { - load_queue_event(b, cwmp); + load_queue_event(b); } else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "download") == 0) { load_download(b); } else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "upload") == 0) { load_upload(b); } else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "transfer_complete") == 0) { - load_transfer_complete(b, cwmp); + load_transfer_complete(b); } else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "schedule_inform") == 0) { load_schedule_inform(b); } else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "change_du_state") == 0) { load_change_du_state(b); } else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "du_state_change_complete") == 0) { - load_du_state_change_complete(b, cwmp); + load_du_state_change_complete(b); } else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "schedule_download") == 0) { load_schedule_download(b); - } else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "apply_schedule_download") == 0) { - load_apply_schedule_download(b); } } b = mxmlWalkNext(b, bkp_tree, MXML_NO_DESCEND); diff --git a/common.c b/common.c index 7a510c3..d7a2371 100755 --- a/common.c +++ b/common.c @@ -8,35 +8,38 @@ * Author Omar Kallel * */ - -#include -#include -#include -#include +#include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include "common.h" -#include "cwmp_cli.h" #include "cwmp_uci.h" #include "ubus.h" #include "log.h" - +#include "cwmp_cli.h" +#include "cwmp_du_state.h" +#include "ssl_utils.h" #ifndef CWMP_REVISION #define CWMP_REVISION "8.2.10" #endif char *commandKey = NULL; -bool thread_end = false; -bool signal_exit = false; +bool cwmp_stop = false; bool ubus_exit = false; long int flashsize = 256000000; -struct cwmp cwmp_main = { 0 }; +struct cwmp *cwmp_main = NULL; static int nbre_services = 0; static char *list_services[MAX_NBRE_SERVICES] = { 0 }; +bool g_firewall_restart = false; LIST_HEAD(cwmp_memory_list); -extern bool g_firewall_restart; struct cwmp_mem { struct list_head list; @@ -51,51 +54,33 @@ struct option cwmp_long_options[] = { struct FAULT_CPE FAULT_CPE_ARRAY[] = { [FAULT_CPE_METHOD_NOT_SUPPORTED] = { "9000", FAULT_9000, FAULT_CPE_TYPE_SERVER, "Method not supported" }, - [FAULT_CPE_REQUEST_DENIED] = { "9001", FAULT_9001, FAULT_CPE_TYPE_SERVER, - "Request denied (no reason specified)" }, + [FAULT_CPE_REQUEST_DENIED] = { "9001", FAULT_9001, FAULT_CPE_TYPE_SERVER, "Request denied (no reason specified)" }, [FAULT_CPE_INTERNAL_ERROR] = { "9002", FAULT_9002, FAULT_CPE_TYPE_SERVER, "Internal error" }, [FAULT_CPE_INVALID_ARGUMENTS] = { "9003", FAULT_9003, FAULT_CPE_TYPE_CLIENT, "Invalid arguments" }, [FAULT_CPE_RESOURCES_EXCEEDED] = { "9004", FAULT_9004, FAULT_CPE_TYPE_SERVER, "Resources exceeded" }, [FAULT_CPE_INVALID_PARAMETER_NAME] = { "9005", FAULT_9005, FAULT_CPE_TYPE_CLIENT, "Invalid parameter name" }, [FAULT_CPE_INVALID_PARAMETER_TYPE] = { "9006", FAULT_9006, FAULT_CPE_TYPE_CLIENT, "Invalid parameter type" }, [FAULT_CPE_INVALID_PARAMETER_VALUE] = { "9007", FAULT_9007, FAULT_CPE_TYPE_CLIENT, "Invalid parameter value" }, - [FAULT_CPE_NON_WRITABLE_PARAMETER] = { "9008", FAULT_9008, FAULT_CPE_TYPE_CLIENT, - "Attempt to set a non-writable parameter" }, - [FAULT_CPE_NOTIFICATION_REJECTED] = { "9009", FAULT_9009, FAULT_CPE_TYPE_SERVER, - "Notification request rejected" }, + [FAULT_CPE_NON_WRITABLE_PARAMETER] = { "9008", FAULT_9008, FAULT_CPE_TYPE_CLIENT, "Attempt to set a non-writable parameter" }, + [FAULT_CPE_NOTIFICATION_REJECTED] = { "9009", FAULT_9009, FAULT_CPE_TYPE_SERVER, "Notification request rejected" }, [FAULT_CPE_DOWNLOAD_FAILURE] = { "9010", FAULT_9010, FAULT_CPE_TYPE_SERVER, "Download failure" }, [FAULT_CPE_UPLOAD_FAILURE] = { "9011", FAULT_9011, FAULT_CPE_TYPE_SERVER, "Upload failure" }, - [FAULT_CPE_FILE_TRANSFER_AUTHENTICATION_FAILURE] = { "9012", FAULT_9012, FAULT_CPE_TYPE_SERVER, - "File transfer server authentication failure" }, - [FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL] = { "9013", FAULT_9013, FAULT_CPE_TYPE_SERVER, - "Unsupported protocol for file transfer" }, - [FAULT_CPE_DOWNLOAD_FAIL_MULTICAST_GROUP] = { "9014", FAULT_9014, FAULT_CPE_TYPE_SERVER, - "Download failure: unable to join multicast group" }, - [FAULT_CPE_DOWNLOAD_FAIL_CONTACT_SERVER] = { "9015", FAULT_9015, FAULT_CPE_TYPE_SERVER, - "Download failure: unable to contact file server" }, - [FAULT_CPE_DOWNLOAD_FAIL_ACCESS_FILE] = { "9016", FAULT_9016, FAULT_CPE_TYPE_SERVER, - "Download failure: unable to access file" }, - [FAULT_CPE_DOWNLOAD_FAIL_COMPLETE_DOWNLOAD] = { "9017", FAULT_9017, FAULT_CPE_TYPE_SERVER, - "Download failure: unable to complete download" }, - [FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED] = { "9018", FAULT_9018, FAULT_CPE_TYPE_SERVER, - "Download failure: file corrupted" }, - [FAULT_CPE_DOWNLOAD_FAIL_FILE_AUTHENTICATION] = { "9019", FAULT_9019, FAULT_CPE_TYPE_SERVER, - "Download failure: file authentication failure" }, - [FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW] = { "9020", FAULT_9020, FAULT_CPE_TYPE_SERVER, - "Download failure: unable to complete download" }, - [FAULT_CPE_DUPLICATE_DEPLOYMENT_UNIT] = { "9026", FAULT_9026, FAULT_CPE_TYPE_SERVER, - "Duplicate deployment unit" }, - [FAULT_CPE_SYSTEM_RESOURCES_EXCEEDED] = { "9027", FAULT_9027, FAULT_CPE_TYPE_SERVER, - "System ressources exceeded" }, + [FAULT_CPE_FILE_TRANSFER_AUTHENTICATION_FAILURE] = { "9012", FAULT_9012, FAULT_CPE_TYPE_SERVER, "File transfer server authentication failure" }, + [FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL] = { "9013", FAULT_9013, FAULT_CPE_TYPE_SERVER, "Unsupported protocol for file transfer" }, + [FAULT_CPE_DOWNLOAD_FAIL_MULTICAST_GROUP] = { "9014", FAULT_9014, FAULT_CPE_TYPE_SERVER, "Download failure: unable to join multicast group" }, + [FAULT_CPE_DOWNLOAD_FAIL_CONTACT_SERVER] = { "9015", FAULT_9015, FAULT_CPE_TYPE_SERVER, "Download failure: unable to contact file server" }, + [FAULT_CPE_DOWNLOAD_FAIL_ACCESS_FILE] = { "9016", FAULT_9016, FAULT_CPE_TYPE_SERVER, "Download failure: unable to access file" }, + [FAULT_CPE_DOWNLOAD_FAIL_COMPLETE_DOWNLOAD] = { "9017", FAULT_9017, FAULT_CPE_TYPE_SERVER, "Download failure: unable to complete download" }, + [FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED] = { "9018", FAULT_9018, FAULT_CPE_TYPE_SERVER, "Download failure: file corrupted" }, + [FAULT_CPE_DOWNLOAD_FAIL_FILE_AUTHENTICATION] = { "9019", FAULT_9019, FAULT_CPE_TYPE_SERVER, "Download failure: file authentication failure" }, + [FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW] = { "9020", FAULT_9020, FAULT_CPE_TYPE_SERVER, "Download failure: unable to complete download" }, + [FAULT_CPE_DUPLICATE_DEPLOYMENT_UNIT] = { "9026", FAULT_9026, FAULT_CPE_TYPE_SERVER, "Duplicate deployment unit" }, + [FAULT_CPE_SYSTEM_RESOURCES_EXCEEDED] = { "9027", FAULT_9027, FAULT_CPE_TYPE_SERVER, "System ressources exceeded" }, [FAULT_CPE_UNKNOWN_DEPLOYMENT_UNIT] = { "9028", FAULT_9028, FAULT_CPE_TYPE_SERVER, "Unknown deployment unit" }, - [FAULT_CPE_INVALID_DEPLOYMENT_UNIT_STATE] = { "9029", FAULT_9029, FAULT_CPE_TYPE_SERVER, - "Invalid deployment unit state" }, - [FAULT_CPE_INVALID_DOWNGRADE_REJECTED] = { "9030", FAULT_9030, FAULT_CPE_TYPE_SERVER, - "Invalid deployment unit Update: Downgrade not permitted" }, - [FAULT_CPE_INVALID_UPDATE_VERSION_UNSPECIFIED] = { "9031", FAULT_9031, FAULT_CPE_TYPE_SERVER, - "Invalid deployment unit Update: Version not specified" }, - [FAULT_CPE_INVALID_UPDATE_VERSION_EXIST] = { "9031", FAULT_9032, FAULT_CPE_TYPE_SERVER, - "Invalid deployment unit Update: Version already exist" } + [FAULT_CPE_INVALID_DEPLOYMENT_UNIT_STATE] = { "9029", FAULT_9029, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit state" }, + [FAULT_CPE_INVALID_DOWNGRADE_REJECTED] = { "9030", FAULT_9030, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit Update: Downgrade not permitted" }, + [FAULT_CPE_INVALID_UPDATE_VERSION_UNSPECIFIED] = { "9031", FAULT_9031, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit Update: Version not specified" }, + [FAULT_CPE_INVALID_UPDATE_VERSION_EXIST] = { "9031", FAULT_9032, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit Update: Version already exist" } }; static void show_help(void) @@ -289,6 +274,44 @@ void get_firewall_zone_name_by_wan_iface(char *if_wan, char **zone_name) } } +int get_firewall_restart_state(char **state) +{ + cwmp_uci_reinit(); + return uci_get_state_value(UCI_CPE_FIREWALL_RESTART_STATE, state); +} + +// wait till firewall restart is not complete or 5 sec, whichever is less +void check_firewall_restart_state() +{ + int count = 0; + bool init = false; + + do { + char *state = NULL; + + if (get_firewall_restart_state(&state) != CWMP_OK) + break; + + if (state != NULL && strcmp(state, "init") == 0) { + init = true; + FREE(state); + break; + } + + usleep(500 * 1000); + FREE(state); + count++; + } while(count < 10); + + // mark the firewall restart as done + g_firewall_restart = false; + if (init == false) { // In case of timeout reset the firewall_restart flag + CWMP_LOG(ERROR, "Firewall restart took longer than usual"); + cwmp_uci_set_varstate_value("cwmp", "cpe", "firewall_restart", "init"); + cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); + } +} + /* * Reboot */ @@ -688,33 +711,3 @@ int copy_file(char *source_file, char *target_file) fclose(target); return 0; } - -void ubus_network_interface_callback(struct ubus_request *req __attribute__((unused)), int type __attribute__((unused)), struct blob_attr *msg) -{ - const struct blobmsg_policy p[1] = { { "device", BLOBMSG_TYPE_STRING } }; - struct blob_attr *tb[1] = { NULL }; - blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg)); - if (!tb[0]) { - cwmp_main.conf.interface = NULL; - CWMP_LOG(DEBUG, "CWMP IFACE - interface: NOT FOUND"); - return; - } - - FREE(cwmp_main.conf.interface); - cwmp_main.conf.interface = strdup(blobmsg_get_string(tb[0])); - CWMP_LOG(DEBUG, "CWMP IFACE - interface: %s", cwmp_main.conf.interface); -} - -int get_connection_interface() -{ - int e = cwmp_ubus_call("network.interface", "status", CWMP_UBUS_ARGS{ { "interface", { .str_val = cwmp_main.conf.default_wan_iface }, UBUS_String } }, 1, ubus_network_interface_callback, NULL); - if (e != 0) { - CWMP_LOG(INFO, "Get network interface from network.interface ubus method failed. Ubus err code: %d", e); - return -1; - } - if (cwmp_main.conf.interface == NULL) { - CWMP_LOG(INFO, "Not able to get the network interface from network.interface ubus method."); - return -1; - } - return CWMP_OK; -} diff --git a/config.c b/config.c index f00e1a4..ec717c6 100755 --- a/config.c +++ b/config.c @@ -9,18 +9,19 @@ * Author Ahmed Zribi * Author Omar Kallel */ -#include -#include #include "config.h" +#include "cwmp_uci.h" #include "log.h" #include "reboot.h" #include "datamodel_interface.h" +#include "ubus.h" pthread_mutex_t mutex_config_load = PTHREAD_MUTEX_INITIALIZER; -static int check_global_config(struct config *conf) +static int check_global_config() { + struct config *conf = &(cwmp_main->conf); if (conf->acsurl == NULL) { conf->acsurl = strdup(DEFAULT_ACSURL); } @@ -43,11 +44,13 @@ static time_t convert_datetime_to_timestamp(char *value) return mktime(&tm); } -int get_global_config(struct config *conf) +int get_global_config() { + struct config *conf = &(cwmp_main->conf); int error, error2, error3; char *value = NULL, *value2 = NULL, *value3 = NULL; + //cwmp_main->conf.cr_auth_type = AUTH_DIGEST; if ((error = uci_get_value(UCI_CPE_LOG_FILE_NAME, &value)) == CWMP_OK) { if (value != NULL) { log_set_log_file_name(value); @@ -592,46 +595,75 @@ int get_global_config(struct config *conf) return CWMP_OK; } +void ubus_network_interface_callback(struct ubus_request *req __attribute__((unused)), int type __attribute__((unused)), struct blob_attr *msg) +{ + const struct blobmsg_policy p[1] = { { "device", BLOBMSG_TYPE_STRING } }; + struct blob_attr *tb[1] = { NULL }; + blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg)); + if (!tb[0]) { + cwmp_main->conf.interface = NULL; + CWMP_LOG(DEBUG, "CWMP IFACE - interface: NOT FOUND"); + return; + } + + FREE(cwmp_main->conf.interface); + cwmp_main->conf.interface = strdup(blobmsg_get_string(tb[0])); + CWMP_LOG(DEBUG, "CWMP IFACE - interface: %s", cwmp_main->conf.interface); +} + +int get_connection_interface() +{ + int e = cwmp_ubus_call("network.interface", "status", CWMP_UBUS_ARGS{ { "interface", { .str_val = cwmp_main->conf.default_wan_iface }, UBUS_String } }, 1, ubus_network_interface_callback, NULL); + if (e != 0) { + CWMP_LOG(INFO, "Get network interface from network.interface ubus method failed. Ubus err code: %d", e); + return -1; + } + if (cwmp_main->conf.interface == NULL) { + CWMP_LOG(INFO, "Not able to get the network interface from network.interface ubus method."); + return -1; + } + return CWMP_OK; +} + int reload_networking_config() { int error; char *value = NULL; if ((error = uci_get_value(UCI_CPE_DEFAULT_WAN_IFACE, &value)) == CWMP_OK) { - FREE(cwmp_main.conf.default_wan_iface); + FREE(cwmp_main->conf.default_wan_iface); if (value != NULL) { - cwmp_main.conf.default_wan_iface = strdup(value); + cwmp_main->conf.default_wan_iface = strdup(value); FREE(value); } else { - cwmp_main.conf.default_wan_iface = strdup("wan"); + cwmp_main->conf.default_wan_iface = strdup("wan"); } - CWMP_LOG(DEBUG, "CWMP CONFIG - default wan interface: %s", cwmp_main.conf.default_wan_iface ? cwmp_main.conf.default_wan_iface : ""); + CWMP_LOG(DEBUG, "CWMP CONFIG - default wan interface: %s", cwmp_main->conf.default_wan_iface ? cwmp_main->conf.default_wan_iface : ""); } else { return error; } - if (get_connection_interface() == -1) + if ((error = get_connection_interface())) return -1; return CWMP_OK; } -int global_conf_init(struct cwmp *cwmp) +int global_conf_init() { int error = CWMP_OK; pthread_mutex_lock(&mutex_config_load); - - if ((error = get_global_config(&(cwmp->conf)))) + if ((error = get_global_config(&(cwmp_main->conf)))) goto end; - if ((error = check_global_config(&(cwmp->conf)))) + if ((error = check_global_config(&(cwmp_main->conf)))) goto end; if ((error = get_connection_interface())) return -1; /* Launch reboot methods if needed */ - launch_reboot_methods(cwmp); + launch_reboot_methods(); end: pthread_mutex_unlock(&mutex_config_load); @@ -639,20 +671,11 @@ end: return error; } -int cwmp_get_deviceid(struct cwmp *cwmp) +int cwmp_config_reload() { - cwmp_get_leaf_value("Device.DeviceInfo.Manufacturer", &cwmp->deviceid.manufacturer); - cwmp_get_leaf_value("Device.DeviceInfo.SerialNumber", &cwmp->deviceid.serialnumber); - cwmp_get_leaf_value("Device.DeviceInfo.ProductClass", &cwmp->deviceid.productclass); - cwmp_get_leaf_value("Device.DeviceInfo.ManufacturerOUI", &cwmp->deviceid.oui); - cwmp_get_leaf_value("Device.DeviceInfo.SoftwareVersion", &cwmp->deviceid.softwareversion); - return CWMP_OK; -} + memset(&cwmp_main->env, 0, sizeof(struct env)); -int cwmp_config_reload(struct cwmp *cwmp) -{ - memset(&cwmp->env, 0, sizeof(struct env)); - int err = global_conf_init(cwmp); + int err = global_conf_init(); if (err != CWMP_OK) return err; diff --git a/configure.ac b/configure.ac index 4d6cbaf..843890c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([icwmp], [1.0], [dev@iopsys.eu]) +AC_INIT([icwmp], [1.1], [dev@iopsys.eu]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([cwmp.c]) @@ -96,9 +96,6 @@ AM_COND_IF([LWOLFSSL], [ AM_COND_IF([LOPENSSL], [ LSSL_LIBS='-lssl' AC_SUBST([LSSL_LIBS]) -], [ - LSSL_LIBS='-lwolfssl' - AC_SUBST([LSSL_LIBS]) ]) PKG_CHECK_MODULES(LIBCURL, [libcurl]) diff --git a/cwmp.c b/cwmp.c index b08c008..17d237d 100644 --- a/cwmp.c +++ b/cwmp.c @@ -10,463 +10,51 @@ * Author Omar Kallel */ -#include -#include +#include +#include +#include +#include #include #include -#include +#include #include "common.h" -#include "ssl_utils.h" -#include "xml.h" -#include "notifications.h" -#include "event.h" -#include "cwmp_uci.h" -#include "log.h" #include "session.h" -#include "diagnostic.h" -#include "http.h" -#include "rpc_soap.h" -#include "config.h" #include "backupSession.h" +#include "http.h" +#include "cwmp_http.h" +#include "diagnostic.h" +#include "config.h" #include "ubus.h" -#include "digestauth.h" -#include "upload.h" -#include "download.h" -#include "sched_inform.h" -#include "datamodel_interface.h" +#include "log.h" +#include "notifications.h" +#include "cwmp_uci.h" #include "cwmp_du_state.h" +#include "download.h" +#include "upload.h" +#include "sched_inform.h" +#include "digestauth.h" +#include "soap.h" +#include "netlink.h" +#include "cwmp_http.h" +#include "cwmp_config.h" +#include "cwmp_http.h" -static pthread_t periodic_event_thread; -static pthread_t scheduleInform_thread; -static pthread_t change_du_state_thread; -static pthread_t download_thread; -static pthread_t schedule_download_thread; -static pthread_t apply_schedule_download_thread; -static pthread_t upload_thread; -static pthread_t ubus_thread; -static pthread_t http_cr_server_thread; -static pthread_t periodic_check_notify; -static pthread_t signal_handler_thread; -bool g_firewall_restart = false; - -static int cwmp_get_retry_interval(struct cwmp *cwmp) -{ - unsigned int retry_count = 0; - double min = 0; - double max = 0; - int m = cwmp->conf.retry_min_wait_interval; - int k = cwmp->conf.retry_interval_multiplier; - int exp = cwmp->retry_count_session; - if (exp == 0) - return MAX_INT32; - if (exp > 10) - exp = 10; - min = pow(((double)k / 1000), (double)(exp - 1)) * m; - max = pow(((double)k / 1000), (double)exp) * m; - char *rand = generate_random_string(4); - if (rand) { - unsigned int dividend = (unsigned int)strtoul(rand, NULL, 16); - retry_count = dividend % ((unsigned int)max + 1 - (unsigned int)min) + (unsigned int)min; - free(rand); - } - return (retry_count); -} - -static int cwmp_rpc_cpe_handle_message(struct session *session, struct rpc *rpc_cpe) -{ - if (xml_prepare_msg_out(session)) - return -1; - - if (rpc_cpe_methods[rpc_cpe->type].handler(session, rpc_cpe)) - return -1; - - if (xml_set_cwmp_id_rpc_cpe(session)) - return -1; - - return 0; -} - -static void cwmp_prepare_value_change(struct cwmp *cwmp) -{ - struct event_container *event_container; - if (list_value_change.next == &(list_value_change)) - return; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, ""); - if (!event_container) - goto end; - pthread_mutex_lock(&(mutex_value_change)); - list_splice_init(&(list_value_change), &(event_container->head_dm_parameter)); - pthread_mutex_unlock(&(mutex_value_change)); - cwmp_save_event_container(event_container); - -end: - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); -} - -int get_firewall_restart_state(char **state) -{ - cwmp_uci_reinit(); - return uci_get_state_value(UCI_CPE_FIREWALL_RESTART_STATE, state); -} - -// wait till firewall restart is not complete or 5 sec, whichever is less -void check_firewall_restart_state() -{ - int count = 0; - bool init = false; - - do { - char *state = NULL; - - if (get_firewall_restart_state(&state) != CWMP_OK) - break; - - if (state != NULL && strcmp(state, "init") == 0) { - init = true; - FREE(state); - break; - } - - usleep(500 * 1000); - FREE(state); - count++; - } while(count < 10); - - // mark the firewall restart as done - g_firewall_restart = false; - if (init == false) { // In case of timeout reset the firewall_restart flag - CWMP_LOG(ERROR, "Firewall restart took longer than usual"); - cwmp_uci_set_varstate_value("cwmp", "cpe", "firewall_restart", "init"); - cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); - } -} - -static int cwmp_schedule_rpc(struct cwmp *cwmp, struct session *session) -{ - struct list_head *ilist; - struct rpc *rpc_acs, *rpc_cpe; - - if (http_client_init(cwmp) || thread_end) { - CWMP_LOG(INFO, "Initializing http client failed"); - goto retry; - } - - while (1) { - list_for_each (ilist, &(session->head_rpc_acs)) { - rpc_acs = list_entry(ilist, struct rpc, list); - if (!rpc_acs->type || thread_end) - goto retry; - - CWMP_LOG(INFO, "Preparing the %s RPC message to send to the ACS", rpc_acs_methods[rpc_acs->type].name); - if (rpc_acs_methods[rpc_acs->type].prepare_message(cwmp, session, rpc_acs) || thread_end) - goto retry; - - if (xml_set_cwmp_id(session) || thread_end) - goto retry; - - CWMP_LOG(INFO, "Send the %s RPC message to the ACS", rpc_acs_methods[rpc_acs->type].name); - if (xml_send_message(cwmp, session, rpc_acs) || thread_end) - goto retry; - - CWMP_LOG(INFO, "Get the %sResponse message from the ACS", rpc_acs_methods[rpc_acs->type].name); - /* - * This condition is not always false. - * while the value of idx can be changed to true in the exit of icwmp. - */ - // cppcheck-suppress knownConditionTrueFalse - if (rpc_acs_methods[rpc_acs->type].parse_response || thread_end) - if (rpc_acs_methods[rpc_acs->type].parse_response(cwmp, session, rpc_acs)) - goto retry; - - ilist = ilist->prev; - if (rpc_acs_methods[rpc_acs->type].extra_clean != NULL) - rpc_acs_methods[rpc_acs->type].extra_clean(session, rpc_acs); - cwmp_session_rpc_destructor(rpc_acs); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); - if (session->hold_request || thread_end) - break; - } - - // If restart service caused firewall restart, wait for firewall restart to complete - if (g_firewall_restart == true) - check_firewall_restart_state(); - - CWMP_LOG(INFO, "Send empty message to the ACS"); - if (xml_send_message(cwmp, session, NULL) || thread_end) - goto retry; - if (!session->tree_in || thread_end) - goto next; - - CWMP_LOG(INFO, "Receive request from the ACS"); - if (xml_handle_message(session) || thread_end) - goto retry; - - while (session->head_rpc_cpe.next != &(session->head_rpc_cpe)) { - rpc_cpe = list_entry(session->head_rpc_cpe.next, struct rpc, list); - if (!rpc_cpe->type || thread_end) - goto retry; - - CWMP_LOG(INFO, "Preparing the %s%s message", rpc_cpe_methods[rpc_cpe->type].name, (rpc_cpe->type != RPC_CPE_FAULT) ? "Response" : ""); - if (cwmp_rpc_cpe_handle_message(session, rpc_cpe) || thread_end) - goto retry; - MXML_DELETE(session->tree_in); - - CWMP_LOG(INFO, "Send the %s%s message to the ACS", rpc_cpe_methods[rpc_cpe->type].name, (rpc_cpe->type != RPC_CPE_FAULT) ? "Response" : ""); - if (xml_send_message(cwmp, session, rpc_cpe) || thread_end) - goto retry; - MXML_DELETE(session->tree_out); - - cwmp_session_rpc_destructor(rpc_cpe); - if (!session->tree_in || thread_end) - break; - - CWMP_LOG(INFO, "Receive request from the ACS"); - if (xml_handle_message(session) || thread_end) - goto retry; - } - - next: - if (session->head_rpc_acs.next == &(session->head_rpc_acs)) - break; - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); - } - - session->error = CWMP_OK; - goto end; - -retry: - CWMP_LOG(INFO, "Failed"); - session->error = CWMP_RETRY_SESSION; - event_remove_noretry_event_container(session, cwmp); - -end: - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); - http_client_exit(); - xml_exit(); - return session->error; -} - -int run_session_end_func(void) -{ - if (end_session_flag & END_SESSION_RESTART_SERVICES) { - CWMP_LOG(INFO, "Restart modified services"); - icwmp_restart_services(); - } - - if (end_session_flag & END_SESSION_RELOAD) { - CWMP_LOG(INFO, "Config reload: end session request"); - cwmp_uci_reinit(); - cwmp_apply_acs_changes(); - } - - if (end_session_flag & END_SESSION_INIT_NOTIFY) { - CWMP_LOG(INFO, "SetParameterAttributes end session: reinit list notify"); - reinit_list_param_notify(); - } - - if (end_session_flag & END_SESSION_SET_NOTIFICATION_UPDATE) { - CWMP_LOG(INFO, "SetParameterAttributes/Values end session: update enabled notify file"); - cwmp_update_enabled_notify_file(); - } - - if (end_session_flag & END_SESSION_NSLOOKUP_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing nslookupdiagnostic: end session request"); - cwmp_nslookup_diagnostics(); - } - - if (end_session_flag & END_SESSION_TRACEROUTE_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing traceroutediagnostic: end session request"); - cwmp_traceroute_diagnostics(); - } - - if (end_session_flag & END_SESSION_UDPECHO_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing udpechodiagnostic: end session request"); - cwmp_udp_echo_diagnostics(); - } - - if (end_session_flag & END_SESSION_SERVERSELECTION_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing serverselectiondiagnostic: end session request"); - cwmp_serverselection_diagnostics(); - } - - if (end_session_flag & END_SESSION_IPPING_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing ippingdiagnostic: end session request"); - cwmp_ip_ping_diagnostics(); - } - - if (end_session_flag & END_SESSION_DOWNLOAD_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing download diagnostic: end session request"); - cwmp_download_diagnostics(); - } - - if (end_session_flag & END_SESSION_UPLOAD_DIAGNOSTIC) { - CWMP_LOG(INFO, "Executing upload diagnostic: end session request"); - cwmp_upload_diagnostics(); - } - - if (end_session_flag & END_SESSION_REBOOT) { - CWMP_LOG(INFO, "Executing Reboot: end session request"); - cwmp_reboot(commandKey); - exit(EXIT_SUCCESS); - } - - if (end_session_flag & END_SESSION_FACTORY_RESET) { - CWMP_LOG(INFO, "Executing factory reset: end session request"); - cwmp_factory_reset(); - exit(EXIT_SUCCESS); - } - - if (end_session_flag & END_SESSION_X_FACTORY_RESET_SOFT) { - CWMP_LOG(INFO, "Executing factory reset soft: end session request"); - cwmp_factory_reset(); - exit(EXIT_SUCCESS); - } - cwmp_uci_exit(); - icwmp_cleanmem(); - end_session_flag = 0; - return CWMP_OK; -} - -static void cwmp_schedule_session(struct cwmp *cwmp) -{ - int t; - struct timespec time_to_wait = { 0, 0 }; - bool retry = false; - char *exec_download = NULL; - int is_notify = 0; - - cwmp->cwmp_cr_event = 0; - while (1) { - struct list_head *ilist; - struct session *session; - int error; - - pthread_mutex_lock(&(cwmp->mutex_session_send)); - ilist = (&(cwmp->head_session_queue))->next; - while ((ilist == &(cwmp->head_session_queue)) || retry) { - t = cwmp_get_retry_interval(cwmp); - time_to_wait.tv_sec = time(NULL) + t; - CWMP_LOG(INFO, "Waiting the next session"); - - if (thread_end) { - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - return; - } - - pthread_cond_timedwait(&(cwmp->threshold_session_send), &(cwmp->mutex_session_send), &time_to_wait); - - if (thread_end) { - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - return; - } - - ilist = (&(cwmp->head_session_queue))->next; - retry = false; - } - cwmp_uci_init(); - if (cwmp->session_status.last_status == SESSION_FAILURE) - reload_networking_config(); - session = list_entry(ilist, struct session, list); - if (file_exists(DM_ENABLED_NOTIFY)) { - if (!event_exist_in_list(cwmp, EVENT_IDX_4VALUE_CHANGE)) - is_notify = check_value_change(); - } - if (is_notify > 0 || !file_exists(DM_ENABLED_NOTIFY) || cwmp->custom_notify_active) { - cwmp->custom_notify_active = false; - cwmp_update_enabled_notify_file(); - } - cwmp_prepare_value_change(cwmp); - clean_list_value_change(); - if ((error = cwmp_move_session_to_session_send(cwmp, session))) { - CWMP_LOG(EMERG, "FATAL error in the mutex process in the session scheduler!"); - exit(EXIT_FAILURE); - } - - cwmp->session_status.last_end_time = 0; - cwmp->session_status.last_start_time = time(NULL); - cwmp->session_status.last_status = SESSION_RUNNING; - cwmp->session_status.next_retry = 0; - - if (file_exists(fc_cookies)) - remove(fc_cookies); - CWMP_LOG(INFO, "Start session"); - - uci_get_value(UCI_CPE_EXEC_DOWNLOAD, &exec_download); - if (exec_download && strcmp(exec_download, "1") == 0) { - CWMP_LOG(INFO, "Firmware downloaded and applied successfully"); - cwmp_uci_set_value("cwmp", "cpe", "exec_download", "0"); - cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); - } - FREE(exec_download); - error = cwmp_schedule_rpc(cwmp, session); - CWMP_LOG(INFO, "End session"); - - if (thread_end) { - event_remove_all_event_container(session, RPC_SEND); - run_session_end_func(); - cwmp_session_destructor(session); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - return; - } - - if (session->error == CWMP_RETRY_SESSION && (!list_empty(&(session->head_event_container)) || (list_empty(&(session->head_event_container)) && cwmp->cwmp_cr_event == 0))) { - reload_networking_config(); - run_session_end_func(); - error = cwmp_move_session_to_session_queue(cwmp, session); - CWMP_LOG(INFO, "Retry session, retry count = %d, retry in %ds", cwmp->retry_count_session, cwmp_get_retry_interval(cwmp)); - retry = true; - cwmp->session_status.last_end_time = time(NULL); - cwmp->session_status.last_status = SESSION_FAILURE; - cwmp->session_status.next_retry = time(NULL) + cwmp_get_retry_interval(cwmp); - cwmp->session_status.failure_session++; - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - continue; - } - event_remove_all_event_container(session, RPC_SEND); - run_session_end_func(); - cwmp_session_destructor(session); - cwmp->session_send = NULL; - cwmp->retry_count_session = 0; - cwmp->session_status.last_end_time = time(NULL); - cwmp->session_status.last_status = SESSION_SUCCESS; - cwmp->session_status.next_retry = 0; - cwmp->session_status.success_session++; - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - } -} - -static void *thread_uloop_run(void *v __attribute__((unused))) -{ - cwmp_ubus_init(&cwmp_main); - return NULL; -} - -static void *thread_http_cr_server_listen(void *v __attribute__((unused))) -{ - http_server_listen(); - return NULL; -} - -void load_forced_inform_json_file(struct cwmp *cwmp) +void load_forced_inform_json_file() { struct blob_buf bbuf; struct blob_attr *cur; struct blob_attr *custom_forced_inform_list = NULL; int rem; - if (cwmp->conf.forced_inform_json_file == NULL || !file_exists(cwmp->conf.forced_inform_json_file)) + if (cwmp_main->conf.forced_inform_json_file == NULL || !file_exists(cwmp_main->conf.forced_inform_json_file)) return; memset(&bbuf, 0, sizeof(struct blob_buf)); blob_buf_init(&bbuf, 0); - if (blobmsg_add_json_from_file(&bbuf, cwmp->conf.forced_inform_json_file) == false) { - CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp->conf.forced_inform_json_file); + if (blobmsg_add_json_from_file(&bbuf, cwmp_main->conf.forced_inform_json_file) == false) { + CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp_main->conf.forced_inform_json_file); blob_buf_free(&bbuf); return; } @@ -474,13 +62,13 @@ void load_forced_inform_json_file(struct cwmp *cwmp) struct blob_attr *tb[1] = { NULL }; blobmsg_parse(p, 1, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head)); if (tb[0] == NULL) { - CWMP_LOG(WARNING, "The JSON file %s doesn't contain a forced inform parameters list", cwmp->conf.custom_notify_json); + CWMP_LOG(WARNING, "The JSON file %s doesn't contain a forced inform parameters list", cwmp_main->conf.custom_notify_json); blob_buf_free(&bbuf); return; } - custom_forced_inform_list = tb[0]; + blobmsg_for_each_attr(cur, custom_forced_inform_list, rem) { char parameter_path[128]; @@ -502,37 +90,51 @@ void load_forced_inform_json_file(struct cwmp *cwmp) } -void load_boot_inform_json_file(struct cwmp *cwmp) +void clean_custom_inform_parameters() +{ + int i; + for (i=0; i < nbre_custom_inform; i++) { + free(custom_forced_inform_parameters[i]); + custom_forced_inform_parameters[i] = NULL; + } + nbre_custom_inform = 0; + for (i=0; i < nbre_boot_inform; i++) { + free(boot_inform_parameters[i]); + boot_inform_parameters[i] = NULL; + } + nbre_boot_inform = 0; +} + +void load_boot_inform_json_file() { struct blob_buf bbuf; struct blob_attr *cur; struct blob_attr *custom_boot_inform_list = NULL; int rem; - if (cwmp->conf.boot_inform_json_file == NULL || !file_exists(cwmp->conf.boot_inform_json_file)) + if (cwmp_main->conf.boot_inform_json_file == NULL || !file_exists(cwmp_main->conf.boot_inform_json_file)) return; memset(&bbuf, 0, sizeof(struct blob_buf)); blob_buf_init(&bbuf, 0); - if (blobmsg_add_json_from_file(&bbuf, cwmp->conf.boot_inform_json_file) == false) { - CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp->conf.boot_inform_json_file); + if (blobmsg_add_json_from_file(&bbuf, cwmp_main->conf.boot_inform_json_file) == false) { + CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp_main->conf.boot_inform_json_file); blob_buf_free(&bbuf); return; } - const struct blobmsg_policy p[1] = { { "boot_inform", BLOBMSG_TYPE_ARRAY } }; struct blob_attr *tb[1] = { NULL }; blobmsg_parse(p, 1, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head)); - if (tb[0] == NULL) { - CWMP_LOG(WARNING, "The JSON file %s doesn't contain a boot inform parameters list", cwmp->conf.custom_notify_json); + CWMP_LOG(WARNING, "The JSON file %s doesn't contain a boot inform parameters list", cwmp_main->conf.custom_notify_json); blob_buf_free(&bbuf); return; } - custom_boot_inform_list = tb[0]; + + blobmsg_for_each_attr(cur, custom_boot_inform_list, rem) { char parameter_path[128]; @@ -554,21 +156,6 @@ void load_boot_inform_json_file(struct cwmp *cwmp) blob_buf_free(&bbuf); } -void clean_custom_inform_parameters() -{ - int i; - for (i=0; i < nbre_custom_inform; i++) { - free(custom_forced_inform_parameters[i]); - custom_forced_inform_parameters[i] = NULL; - } - nbre_custom_inform = 0; - for (i=0; i < nbre_boot_inform; i++) { - free(boot_inform_parameters[i]); - boot_inform_parameters[i] = NULL; - } - nbre_boot_inform = 0; -} - int create_cwmp_var_state_files() { /* @@ -672,11 +259,48 @@ end: return 0; } -static int cwmp_init(int argc, char **argv, struct cwmp *cwmp) +int cwmp_apply_acs_changes(void) +{ + int error; + + if ((error = cwmp_config_reload())) + return error; + + if ((error = cwmp_root_cause_events())) + return error; + + return CWMP_OK; +} + +static void configure_var_state() +{ + char *zone_name = NULL; + + cwmp_uci_init(); + if (!file_exists(VARSTATE_CONFIG"/cwmp")) + creat(VARSTATE_CONFIG"/cwmp", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + + cwmp_uci_add_section_with_specific_name("cwmp", "acs", "acs", UCI_VARSTATE_CONFIG); + cwmp_uci_add_section_with_specific_name("cwmp", "cpe", "cpe", UCI_VARSTATE_CONFIG); + + get_firewall_zone_name_by_wan_iface(cwmp_main->conf.default_wan_iface, &zone_name); + cwmp_uci_set_varstate_value("cwmp", "acs", "zonename", zone_name ? zone_name : "wan"); + + cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); + cwmp_uci_exit(); +} + +static int cwmp_init(int argc, char **argv) { int error; struct env env; + openlog("cwmp", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); + + CWMP_LOG(INFO, "STARTING ICWMP with PID :%d", getpid()); + + cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); + memset(&env, 0, sizeof(struct env)); if ((error = global_env_init(argc, argv, &env))) return error; @@ -684,16 +308,12 @@ static int cwmp_init(int argc, char **argv, struct cwmp *cwmp) error = wait_for_usp_raw_object(); if (error) return error; - icwmp_init_list_services(); - cwmp->event_id = 0; - cwmp->cwmp_period = 0; - cwmp->cwmp_periodic_time = 0; - cwmp->cwmp_periodic_enable = false; + /* Only One instance should run*/ - cwmp->pid_file = fopen("/var/run/icwmpd.pid", "w+"); - fcntl(fileno(cwmp->pid_file), F_SETFD, fcntl(fileno(cwmp->pid_file), F_GETFD) | FD_CLOEXEC); - int rc = flock(fileno(cwmp->pid_file), LOCK_EX | LOCK_NB); + cwmp_main->pid_file = fopen("/var/run/icwmpd.pid", "w+"); + fcntl(fileno(cwmp_main->pid_file), F_SETFD, fcntl(fileno(cwmp_main->pid_file), F_GETFD) | FD_CLOEXEC); + int rc = flock(fileno(cwmp_main->pid_file), LOCK_EX | LOCK_NB); if (rc) { if (EWOULDBLOCK != errno) { char *piderr = "PID file creation failed: Quit the daemon!"; @@ -703,207 +323,114 @@ static int cwmp_init(int argc, char **argv, struct cwmp *cwmp) } else exit(EXIT_SUCCESS); } - if (cwmp->pid_file) - fclose(cwmp->pid_file); + if (cwmp_main->pid_file) + fclose(cwmp_main->pid_file); - pthread_mutex_init(&cwmp->mutex_periodic, NULL); - pthread_mutex_init(&cwmp->mutex_session_queue, NULL); - pthread_mutex_init(&cwmp->mutex_session_send, NULL); - memcpy(&(cwmp->env), &env, sizeof(struct env)); - INIT_LIST_HEAD(&(cwmp->head_session_queue)); + memcpy(&(cwmp_main->env), &env, sizeof(struct env)); if ((error = create_cwmp_var_state_files())) return error; cwmp_uci_init(); - if ((error = global_conf_init(cwmp))) + if ((error = global_conf_init())) return error; - cwmp_get_deviceid(cwmp); - load_forced_inform_json_file(cwmp); - load_boot_inform_json_file(cwmp); - load_custom_notify_json(cwmp); + cwmp_get_deviceid(); + load_forced_inform_json_file(); + load_boot_inform_json_file(); + load_custom_notify_json(); init_list_param_notify(); + //http_server_init(); + create_cwmp_session_structure(); cwmp_uci_exit(); generate_nonce_priv_key(); + cwmp_main->start_time = time(NULL); + cwmp_main->start_diagnostics = false; + cwmp_main->event_id = 0; + cwmp_main->cwmp_period = 0; + cwmp_main->cwmp_periodic_time = 0; + cwmp_main->cwmp_periodic_enable = false; return CWMP_OK; } -static void cwmp_free(struct cwmp *cwmp) +static void cwmp_exit() { - FREE(cwmp->deviceid.manufacturer); - FREE(cwmp->deviceid.serialnumber); - FREE(cwmp->deviceid.productclass); - FREE(cwmp->deviceid.oui); - FREE(cwmp->deviceid.softwareversion); - FREE(cwmp->conf.lw_notification_hostname); - FREE(cwmp->conf.ip); - FREE(cwmp->conf.ipv6); - FREE(cwmp->conf.acsurl); - FREE(cwmp->conf.acs_userid); - FREE(cwmp->conf.acs_passwd); - FREE(cwmp->conf.interface); - FREE(cwmp->conf.cpe_userid); - FREE(cwmp->conf.cpe_passwd); - FREE(cwmp->conf.ubus_socket); - FREE(cwmp->conf.connection_request_path); - FREE(cwmp->conf.default_wan_iface); - FREE(cwmp->conf.forced_inform_json_file); - FREE(cwmp->conf.custom_notify_json); - FREE(cwmp->conf.boot_inform_json_file); + pthread_join(http_cr_server_thread, NULL); + + FREE(cwmp_main->deviceid.manufacturer); + FREE(cwmp_main->deviceid.serialnumber); + FREE(cwmp_main->deviceid.productclass); + FREE(cwmp_main->deviceid.oui); + FREE(cwmp_main->deviceid.softwareversion); + FREE(cwmp_main->conf.lw_notification_hostname); + FREE(cwmp_main->conf.ip); + FREE(cwmp_main->conf.ipv6); + FREE(cwmp_main->conf.acsurl); + FREE(cwmp_main->conf.acs_userid); + FREE(cwmp_main->conf.acs_passwd); + FREE(cwmp_main->conf.interface); + FREE(cwmp_main->conf.cpe_userid); + FREE(cwmp_main->conf.cpe_passwd); + FREE(cwmp_main->conf.ubus_socket); + FREE(cwmp_main->conf.connection_request_path); + FREE(cwmp_main->conf.default_wan_iface); + FREE(cwmp_main->conf.forced_inform_json_file); + FREE(cwmp_main->conf.custom_notify_json); + FREE(cwmp_main->conf.boot_inform_json_file); FREE(nonce_privacy_key); + clean_list_param_notify(); bkp_tree_clean(); cwmp_ubus_exit(); clean_custom_inform_parameters(); icwmp_cleanmem(); cwmp_uci_exit(); + CWMP_LOG(INFO, "EXIT ICWMP"); + closelog(); + clean_cwmp_session_structure(); + FREE(cwmp_main); } -static void *thread_cwmp_signal_handler_thread(void *arg) +void cwmp_end_handler(int signal_num __attribute__((unused))) { - sigset_t *set = (sigset_t *)arg; - - for (;;) { - int s, signal_num; - s = sigwait(set, &signal_num); - if (s == -1) { - CWMP_LOG(ERROR, "Error in sigwait"); - } else { - CWMP_LOG(INFO, "Catch of Signal(%d)", signal_num); - - if (signal_num == SIGINT || signal_num == SIGTERM) { - signal_exit = true; - - if (!ubus_exit) - cwmp_ubus_call("tr069", "command", CWMP_UBUS_ARGS{ { "command", { .str_val = "exit" }, UBUS_String } }, 1, NULL, NULL); - - break; - } - } - } - - return NULL; -} - -static void configure_var_state(struct cwmp *cwmp) -{ - char *zone_name = NULL; - - if (!file_exists(VARSTATE_CONFIG"/cwmp")) - creat(VARSTATE_CONFIG"/cwmp", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - - cwmp_uci_reinit(); - cwmp_uci_add_section_with_specific_name("cwmp", "acs", "acs", UCI_VARSTATE_CONFIG); - cwmp_uci_add_section_with_specific_name("cwmp", "cpe", "cpe", UCI_VARSTATE_CONFIG); - - get_firewall_zone_name_by_wan_iface(cwmp->conf.default_wan_iface, &zone_name); - cwmp_uci_set_varstate_value("cwmp", "acs", "zonename", zone_name ? zone_name : "wan"); - - cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); + cwmp_ubus_call("tr069", "exit", CWMP_UBUS_ARGS{ {} }, 0, NULL, NULL); } int main(int argc, char **argv) { - struct cwmp *cwmp = &cwmp_main; - sigset_t set; int error; - openlog("cwmp", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); - - if ((error = cwmp_init(argc, argv, cwmp))) + if ((error = cwmp_init(argc, argv))) return error; - CWMP_LOG(INFO, "STARTING ICWMP with PID :%d", getpid()); - cwmp->start_time = time(NULL); - - if ((error = cwmp_init_backup_session(cwmp, NULL, ALL))) + if ((error = cwmp_init_backup_session(NULL, ALL))) return error; - if ((error = cwmp_root_cause_events(cwmp))) + if ((error = cwmp_root_cause_events())) return error; - configure_var_state(cwmp); + signal(SIGINT, cwmp_end_handler); + signal(SIGTERM, cwmp_end_handler); + + configure_var_state(); http_server_init(); - sigemptyset(&set); - sigaddset(&set, SIGINT); - sigaddset(&set, SIGTERM); - sigprocmask(SIG_BLOCK, &set, NULL); + uloop_init(); - error = pthread_create(&http_cr_server_thread, NULL, &thread_http_cr_server_listen, NULL); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the http connection request server thread!"); - } + cwmp_netlink_init(); - error = pthread_create(&ubus_thread, NULL, &thread_uloop_run, NULL); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the ubus thread!"); - } + cwmp_ubus_init(); - error = pthread_create(&periodic_event_thread, NULL, &thread_event_periodic, (void *)cwmp); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the periodic event thread!"); - } + trigger_cwmp_session_timer(); - error = pthread_create(&periodic_check_notify, NULL, &thread_periodic_check_notify, (void *)cwmp); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the periodic check notify thread!"); - } - error = pthread_create(&scheduleInform_thread, NULL, &thread_cwmp_rpc_cpe_scheduleInform, (void *)cwmp); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the scheduled inform thread!"); - } + initiate_cwmp_periodic_session_feature(); - error = pthread_create(&download_thread, NULL, &thread_cwmp_rpc_cpe_download, (void *)cwmp); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the download thread!"); - } + http_server_start(); - error = pthread_create(&change_du_state_thread, NULL, &thread_cwmp_rpc_cpe_change_du_state, (void *)cwmp); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the state change thread!"); - } + uloop_run(); + uloop_done(); - error = pthread_create(&schedule_download_thread, NULL, &thread_cwmp_rpc_cpe_schedule_download, (void *)cwmp); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the schedule download thread!"); - } + cwmp_exit(); - error = pthread_create(&apply_schedule_download_thread, NULL, &thread_cwmp_rpc_cpe_apply_schedule_download, (void *)cwmp); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the schedule download thread!"); - } - - error = pthread_create(&upload_thread, NULL, &thread_cwmp_rpc_cpe_upload, (void *)cwmp); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the download thread!"); - } - - error = pthread_create(&signal_handler_thread, NULL, &thread_cwmp_signal_handler_thread, (void *)&set); - if (error < 0) { - CWMP_LOG(ERROR, "Error when creating the signal handler thread!"); - } - - cwmp_schedule_session(cwmp); - - /* Join all threads */ - pthread_join(periodic_event_thread, NULL); - pthread_join(periodic_check_notify, NULL); - pthread_join(scheduleInform_thread, NULL); - pthread_join(download_thread, NULL); - pthread_join(upload_thread, NULL); - pthread_join(schedule_download_thread, NULL); - pthread_join(apply_schedule_download_thread, NULL); - pthread_join(change_du_state_thread, NULL); - pthread_join(http_cr_server_thread, NULL); - pthread_join(ubus_thread, NULL); - pthread_join(signal_handler_thread, NULL); - - /* Free all memory allocation */ - cwmp_free(cwmp); - - CWMP_LOG(INFO, "EXIT ICWMP"); - closelog(); return CWMP_OK; } diff --git a/cwmp_cli.c b/cwmp_cli.c index f566275..1dc6bb2 100644 --- a/cwmp_cli.c +++ b/cwmp_cli.c @@ -8,13 +8,13 @@ * Author Omar Kallel */ -#include +#include #include "common.h" -#include "cwmp_cli.h" #include "datamodel_interface.h" -#include "cwmp_uci.h" #include "notifications.h" +#include "cwmp_cli.h" +#include "cwmp_uci.h" LIST_HEAD(parameters_list); @@ -64,7 +64,7 @@ void display_get_cmd_result(struct cmd_input in __attribute__((unused)), union c fprintf(stderr, "Fault %s: %s\n", fault, get_fault_message_by_fault_code(fault)); return; } - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, res.param_list, list) { fprintf(stdout, "%s => %s\n", param_value->name, param_value->value); } @@ -89,7 +89,7 @@ char *cmd_set_exec_func(struct cmd_input in, union cmd_result *res __attribute__ int fault_idx = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_key", &flag, &faults_list); cwmp_free_all_dm_parameter_list(&list_set_param_value); if (fault_idx != FAULT_CPE_NO_FAULT) { - struct cwmp_param_fault *param_fault; + struct cwmp_param_fault *param_fault = NULL; char fault[5] = {0}; list_for_each_entry (param_fault, &faults_list, list) { snprintf(fault, sizeof(fault), "%d", param_fault->fault); @@ -204,7 +204,7 @@ void display_get_notif_cmd_result(struct cmd_input in __attribute__((unused)), u fprintf(stderr, "Fault %s: %s\n", fault, get_fault_message_by_fault_code(fault)); return; } - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, res.param_list, list) { fprintf(stdout, "%s => %s\n", param_value->name, param_value->notification == 2 ? "active" : param_value->notification == 1 ? "passive" : "off"); } @@ -266,7 +266,7 @@ void display_get_names_cmd_result(struct cmd_input in __attribute__((unused)), u fprintf(stderr, "Fault %s: %s\n", fault, get_fault_message_by_fault_code(fault)); return; } - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, res.param_list, list) { fprintf(stdout, "%s => %s\n", param_value->name, param_value->writable ? "writable" : "not-writable"); } diff --git a/cwmp_config.c b/cwmp_config.c new file mode 100644 index 0000000..07a381f --- /dev/null +++ b/cwmp_config.c @@ -0,0 +1,22 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Copyright (C) 2013-2021 iopsys Software Solutions AB + * Author Omar Kallel + * + */ +#include "cwmp_config.h" +#include "datamodel_interface.h" + +int cwmp_get_deviceid() +{ + cwmp_get_leaf_value("Device.DeviceInfo.Manufacturer", &cwmp_main->deviceid.manufacturer); + cwmp_get_leaf_value("Device.DeviceInfo.SerialNumber", &cwmp_main->deviceid.serialnumber); + cwmp_get_leaf_value("Device.DeviceInfo.ProductClass", &cwmp_main->deviceid.productclass); + cwmp_get_leaf_value("Device.DeviceInfo.ManufacturerOUI", &cwmp_main->deviceid.oui); + cwmp_get_leaf_value("Device.DeviceInfo.SoftwareVersion", &cwmp_main->deviceid.softwareversion); + return CWMP_OK; +} diff --git a/cwmp_du_state.c b/cwmp_du_state.c index 6f8f5e0..d4047e3 100644 --- a/cwmp_du_state.c +++ b/cwmp_du_state.c @@ -8,15 +8,16 @@ * Author Omar Kallel */ +#include #include -#include -#include "cwmp_du_state.h" +#include "common.h" #include "ubus.h" +#include "cwmp_du_state.h" #include "log.h" -#include "datamodel_interface.h" -#include "cwmp_time.h" #include "backupSession.h" +#include "cwmp_time.h" +#include "datamodel_interface.h" #include "event.h" LIST_HEAD(list_change_du_state); @@ -116,7 +117,7 @@ static char *get_software_module_object_eq(char *param1, char *val1, char *param if (err) return NULL; - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; char instance[8]; list_for_each_entry (param_value, sw_parameters, list) { snprintf(instance, (size_t)(strchr(param_value->name + strlen("Device.SoftwareModules.DeploymentUnit."), '.') - param_value->name - strlen("Device.SoftwareModules.DeploymentUnit.") + 1), "%s", (char *)(param_value->name + strlen("Device.SoftwareModules.DeploymentUnit."))); @@ -137,7 +138,7 @@ static int get_deployment_unit_name_version(char *uuid, char **name, char **vers snprintf(version_param, sizeof(version_param), "Device.SoftwareModules.DeploymentUnit.%s.Version", sw_by_uuid_instance); snprintf(environment_param, sizeof(environment_param), "Device.SoftwareModules.DeploymentUnit.%s.ExecutionEnvRef", sw_by_uuid_instance); - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, &sw_parameters, list) { if (strcmp(param_value->name, name_param) == 0) { *name = strdup(param_value->value); @@ -168,7 +169,7 @@ static char *get_softwaremodules_uuid(char *url) snprintf(uuid_param, sizeof(uuid_param), "Device.SoftwareModules.DeploymentUnit.%s.UUID", sw_by_url_instance); - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, &sw_parameters, list) { if (strcmp(param_value->name, uuid_param) == 0) { uuid = strdup(param_value->value); @@ -190,7 +191,7 @@ static char *get_softwaremodules_url(char *uuid) snprintf(url_param, sizeof(url_param), "Device.SoftwareModules.DeploymentUnit.%s.URL", sw_by_uuid_instance); - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, &sw_parameters, list) { if (strcmp(param_value->name, url_param) == 0) { url = strdup(param_value->value); @@ -234,7 +235,7 @@ static char *get_exec_env_name(char *environment_path) if (err) return strdup(""); - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; snprintf(env_param, sizeof(env_param), "%sName", environment_path); list_for_each_entry (param_value, &environment_list, list) { if (strcmp(param_value->name, env_param) == 0) { @@ -317,9 +318,8 @@ static int cwmp_launch_du_uninstall(char *package_name, char *package_env, struc return error; } -void *thread_cwmp_rpc_cpe_change_du_state(void *v) +void *thread_cwmp_rpc_cpe_change_du_state(void *v __attribute__((unused))) { - struct cwmp *cwmp = (struct cwmp *)v; struct timespec change_du_state_timeout = { 50, 0 }; int error = FAULT_CPE_NO_FAULT; struct du_state_change_complete *pdu_state_change_complete; @@ -336,7 +336,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v) for (;;) { - if (thread_end) + if (cwmp_stop) break; if (list_change_du_state.next != &(list_change_du_state)) { @@ -364,7 +364,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v) } bkp_session_insert_du_state_change_complete(pdu_state_change_complete); bkp_session_save(); - cwmp_root_cause_changedustate_complete(cwmp, pdu_state_change_complete); + cwmp_root_cause_changedustate_complete(pdu_state_change_complete); } list_del(&(pchange_du_state->list)); cwmp_free_change_du_state_request(pchange_du_state); @@ -373,7 +373,6 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v) } if ((timeout >= 0) && (timeout <= time_of_grace)) { - pthread_mutex_lock(&(cwmp->mutex_session_send)); pdu_state_change_complete = calloc(1, sizeof(struct du_state_change_complete)); if (pdu_state_change_complete != NULL) { error = FAULT_CPE_NO_FAULT; @@ -501,17 +500,13 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v) bkp_session_save(); bkp_session_insert_du_state_change_complete(pdu_state_change_complete); bkp_session_save(); - cwmp_root_cause_changedustate_complete(cwmp, pdu_state_change_complete); + cwmp_root_cause_changedustate_complete(pdu_state_change_complete); } } pthread_mutex_lock(&mutex_change_du_state); pthread_cond_timedwait(&threshold_change_du_state, &mutex_change_du_state, &change_du_state_timeout); pthread_mutex_unlock(&mutex_change_du_state); - - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - pthread_mutex_lock(&mutex_change_du_state); list_del(&(pchange_du_state->list)); cwmp_free_change_du_state_request(pchange_du_state); @@ -526,7 +521,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v) return NULL; } -int cwmp_rpc_acs_destroy_data_du_state_change_complete(struct session *session __attribute__((unused)), struct rpc *rpc) +int cwmp_rpc_acs_destroy_data_du_state_change_complete(struct rpc *rpc) { if (rpc->extra_data != NULL) { struct du_state_change_complete *p; diff --git a/cwmp_event.c b/cwmp_event.c new file mode 100644 index 0000000..47856fd --- /dev/null +++ b/cwmp_event.c @@ -0,0 +1,48 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Copyright (C) 2013-2021 iopsys Software Solutions AB + * Author Omar Kallel + */ + +#include "cwmp_event.h" +#include "common.h" +#include "session.h" + +struct event_container *__cwmp_add_event_container(int event_code, char *command_key) +{ + struct event_container *event_container; + list_for_each_entry(event_container, &cwmp_main->session->events, list) { + if (event_container->code == event_code && EVENT_CONST[event_code].TYPE == EVENT_TYPE_SINGLE) { + return event_container; + } + if (event_container->code > event_code) { + break; + } + } + event_container = calloc(1, sizeof(struct event_container)); + if (event_container == NULL) { + return NULL; + } + INIT_LIST_HEAD(&(event_container->head_dm_parameter)); + list_add_tail(&(event_container->list), &(cwmp_main->session->events)); + event_container->code = event_code; + event_container->command_key = command_key ? strdup(command_key) : strdup(""); + if ((cwmp_main->event_id < 0) || (cwmp_main->event_id >= MAX_INT_ID)) { + cwmp_main->event_id = 0; + } + cwmp_main->event_id++; + event_container->id = cwmp_main->event_id; + return event_container; +} + +struct event_container *cwmp_add_event_container(int event_code, char *command_key) +{ + pthread_mutex_lock(&add_event_mutext); + struct event_container *event = __cwmp_add_event_container(event_code, command_key); + pthread_mutex_unlock(&add_event_mutext); + return event; +} diff --git a/cwmp_http.c b/cwmp_http.c new file mode 100644 index 0000000..2becbea --- /dev/null +++ b/cwmp_http.c @@ -0,0 +1,46 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Copyright (C) 2013-2021 iopsys Software Solutions AB + * Author Omar Kallel + */ + +#include +#include "common.h" +#include "cwmp_http.h" +#include "http.h" +#include "log.h" + +struct uloop_fd http_event6; + +pthread_t http_cr_server_thread; + +void http_server_listen_uloop(struct uloop_fd *ufd __attribute__((unused)), unsigned events __attribute__((unused))) +{ + http_server_listen(); +} + +void http_server_start_uloop(void) +{ + http_server_init(); + http_event6.fd = cwmp_main->cr_socket_desc; + http_event6.cb = http_server_listen_uloop; + uloop_fd_add(&http_event6, ULOOP_READ | ULOOP_EDGE_TRIGGER); +} + +static void *thread_http_cr_server_listen(void *v __attribute__((unused))) +{ + http_server_listen(); + return NULL; +} + +void http_server_start(void) +{ + int error = pthread_create(&http_cr_server_thread, NULL, &thread_http_cr_server_listen, NULL); + if (error < 0) { + CWMP_LOG(ERROR, "Error when creating the http connection request server thread!"); + } +} diff --git a/cwmp_uci.c b/cwmp_uci.c index 5b33521..c2cac49 100644 --- a/cwmp_uci.c +++ b/cwmp_uci.c @@ -8,12 +8,9 @@ * Author Omar Kallel */ #include -#include -#include - #include "common.h" -#include "cwmp_uci.h" #include "log.h" +#include "cwmp_uci.h" struct uci_paths uci_save_conf_paths[] = { [UCI_STANDARD_CONFIG] = { "/etc/config", "/tmp/.uci", NULL }, @@ -216,7 +213,7 @@ int cwmp_uci_get_value_by_section_string(struct uci_section *s, char *option, ch struct uci_option *o; *value = NULL; - if (s == NULL || &s->options == NULL || option == NULL) + if (s == NULL || option == NULL) goto not_found; uci_foreach_element(&s->options, e) @@ -377,16 +374,14 @@ void cwmp_delete_uci_element_from_list(struct uci_element *e) void cwmp_free_uci_list(struct uci_list *list) { struct uci_element *e = NULL, *tmp = NULL; - if (list == NULL) - return; - uci_foreach_element_safe(list, e, tmp) + + uci_foreach_element_safe(list, e, tmp) { cwmp_delete_uci_element_from_list(e); + } } char *cwmp_uci_list_to_string(struct uci_list *list, char *delimitor) { - if (delimitor == NULL) - return NULL; if (list && !uci_list_empty(list)) { struct uci_element *e = NULL; char list_val[512] = { 0 }; @@ -470,10 +465,8 @@ int cwmp_uci_add_list_value(char *package, char *section, char *option, char *va return UCI_ERR_PARSE; error = uci_add_list(uci_save_conf_paths[uci_type].uci_ctx, &ptr); - if (error != UCI_OK) - return error; - return UCI_OK; + return error; } int cwmp_uci_del_list_value(char *package, char *section, char *option, char *value, uci_config_paths uci_type) @@ -700,7 +693,7 @@ int cwmp_uci_import(char *package_name, const char *input_path, uci_config_paths { struct uci_package *package = NULL; struct uci_element *e = NULL; - int ret = CWMP_OK; + int ret = UCI_OK; FILE *input = fopen(input_path, "r"); if (!input) return -1; @@ -710,10 +703,6 @@ int cwmp_uci_import(char *package_name, const char *input_path, uci_config_paths goto end; } - if (uci_save_conf_paths[uci_type].uci_ctx == NULL) { - ret = -1; - goto end; - } uci_foreach_element(&uci_save_conf_paths[uci_type].uci_ctx->root, e) { struct uci_package *p = uci_to_package(e); @@ -752,7 +741,7 @@ int cwmp_uci_export(const char *output_path, uci_config_paths uci_type) char **configs = NULL; char **p; - if (uci_list_configs(uci_save_conf_paths[uci_type].uci_ctx, &configs) != UCI_OK) + if ((uci_list_configs(uci_save_conf_paths[uci_type].uci_ctx, &configs) != UCI_OK)) return -1; if (configs == NULL) diff --git a/cwmp_zlib.c b/cwmp_zlib.c index 7495fa5..68be8ea 100644 --- a/cwmp_zlib.c +++ b/cwmp_zlib.c @@ -9,9 +9,6 @@ */ #include -#include -#include - #include "common.h" #include "log.h" diff --git a/datamodel_interface.c b/datamodel_interface.c index 9c48222..4d084a7 100755 --- a/datamodel_interface.c +++ b/datamodel_interface.c @@ -8,11 +8,10 @@ * Author Omar Kallel */ -#include - #include "datamodel_interface.h" -#include "ubus.h" #include "log.h" +#include "ubus.h" +#include "notifications.h" int transaction_id = 0; @@ -292,8 +291,7 @@ void ubus_get_single_parameter_callback(struct ubus_request *req, int type __att char *cwmp_get_single_parameter_value(char *parameter_name, struct cwmp_dm_parameter *dm_parameter) { int e; - struct cwmp *cwmp = &cwmp_main; - e = cwmp_ubus_call(USP_OBJECT_NAME, "get", CWMP_UBUS_ARGS{ { "path", { .str_val = !parameter_name || parameter_name[0] == '\0' ? DM_ROOT_OBJ : parameter_name }, UBUS_String }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 3, ubus_get_single_parameter_callback, dm_parameter); + e = cwmp_ubus_call(USP_OBJECT_NAME, "get", CWMP_UBUS_ARGS{ { "path", { .str_val = !parameter_name || parameter_name[0] == '\0' ? DM_ROOT_OBJ : parameter_name }, UBUS_String }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 3, ubus_get_single_parameter_callback, dm_parameter); if (e < 0) { CWMP_LOG(INFO, "get ubus method failed: Ubus err code: %d", e); return "9002"; @@ -368,9 +366,8 @@ void ubus_get_parameter_callback(struct ubus_request *req, int type __attribute_ char *cwmp_get_parameter_values(char *parameter_name, struct list_head *parameters_list) { int e; - struct cwmp *cwmp = &cwmp_main; struct list_params_result get_result = { .parameters_list = parameters_list }; - e = cwmp_ubus_call(USP_OBJECT_NAME, "get", CWMP_UBUS_ARGS{ { "path", { .str_val = !parameter_name || parameter_name[0] == '\0' ? DM_ROOT_OBJ : parameter_name }, UBUS_String }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 3, ubus_get_parameter_callback, &get_result); + e = cwmp_ubus_call(USP_OBJECT_NAME, "get", CWMP_UBUS_ARGS{ { "path", { .str_val = !parameter_name || parameter_name[0] == '\0' ? DM_ROOT_OBJ : parameter_name }, UBUS_String }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 3, ubus_get_parameter_callback, &get_result); if (e < 0) { CWMP_LOG(INFO, "get ubus method failed: Ubus err code: %d", e); return "9002"; @@ -386,9 +383,8 @@ char *cwmp_get_parameter_values(char *parameter_name, struct list_head *paramete char *cwmp_get_multiple_parameters_values(struct list_head *arg_params_list, struct list_head *parameters_list) { int e; - struct cwmp *cwmp = &cwmp_main; struct list_params_result get_result = { .parameters_list = parameters_list }; - e = cwmp_ubus_call(USP_OBJECT_NAME, "getm_values", CWMP_UBUS_ARGS{ { "paths", { .param_value_list = arg_params_list }, UBUS_List_Param_Get }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 2, ubus_get_parameter_callback, &get_result ); + e = cwmp_ubus_call(USP_OBJECT_NAME, "getm_values", CWMP_UBUS_ARGS{ { "paths", { .param_value_list = arg_params_list }, UBUS_List_Param_Get }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 2, ubus_get_parameter_callback, &get_result ); if (e < 0) { CWMP_LOG(INFO, "getm_values ubus method failed: Ubus err code: %d", e); return "9002"; @@ -405,8 +401,7 @@ char *cwmp_get_parameter_names(char *object_name, bool next_level, struct list_h { int e; struct list_params_result get_result = { .parameters_list = parameters_list }; - struct cwmp *cwmp = &cwmp_main; - e = cwmp_ubus_call(USP_OBJECT_NAME, "object_names", CWMP_UBUS_ARGS{ { "path", { .str_val = object_name }, UBUS_String }, { "next-level", { .bool_val = next_level }, UBUS_Bool }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 4, ubus_get_parameter_callback, &get_result); + e = cwmp_ubus_call(USP_OBJECT_NAME, "object_names", CWMP_UBUS_ARGS{ { "path", { .str_val = object_name }, UBUS_String }, { "next-level", { .bool_val = next_level }, UBUS_Bool }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 4, ubus_get_parameter_callback, &get_result); if (e < 0) { CWMP_LOG(INFO, "object_names ubus method failed: Ubus err code: %d", e); return "9002"; @@ -457,9 +452,8 @@ int cwmp_set_multiple_parameters_values(struct list_head *parameters_values_list { int e; struct setm_values_res set_result = { .flag = flag, .faults_list = faults_list }; - struct cwmp *cwmp = &cwmp_main; e = cwmp_ubus_call(USP_OBJECT_NAME, "setm_values", - CWMP_UBUS_ARGS{ { "pv_tuple", { .param_value_list = parameters_values_list }, UBUS_List_Param_Set }, { "key", { .str_val = parameter_key }, UBUS_String }, { "transaction_id", { .int_val = transaction_id }, UBUS_Integer }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 5, + CWMP_UBUS_ARGS{ { "pv_tuple", { .param_value_list = parameters_values_list }, UBUS_List_Param_Set }, { "key", { .str_val = parameter_key }, UBUS_String }, { "transaction_id", { .int_val = transaction_id }, UBUS_Integer }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 5, ubus_setm_values_callback, &set_result); if (e < 0) { @@ -509,9 +503,8 @@ void ubus_objects_callback(struct ubus_request *req, int type __attribute__((unu char *cwmp_add_object(char *object_name, char *key, char **instance) { int e; - struct cwmp *cwmp = &cwmp_main; struct object_result add_result = { .instance = instance }; - e = cwmp_ubus_call(USP_OBJECT_NAME, "add_object", CWMP_UBUS_ARGS{ { "path", { .str_val = object_name }, UBUS_String }, { "key", { .str_val = key }, UBUS_String }, { "transaction_id", { .int_val = transaction_id }, UBUS_Integer }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 5, + e = cwmp_ubus_call(USP_OBJECT_NAME, "add_object", CWMP_UBUS_ARGS{ { "path", { .str_val = object_name }, UBUS_String }, { "key", { .str_val = key }, UBUS_String }, { "transaction_id", { .int_val = transaction_id }, UBUS_Integer }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 5, ubus_objects_callback, &add_result); if (e < 0) { @@ -529,8 +522,7 @@ char *cwmp_delete_object(char *object_name, char *key) { int e; struct object_result add_result = { .instance = NULL }; - struct cwmp *cwmp = &cwmp_main; - e = cwmp_ubus_call(USP_OBJECT_NAME, "del_object", CWMP_UBUS_ARGS{ { "path", { .str_val = object_name }, UBUS_String }, { "key", { .str_val = key }, UBUS_String }, { "transaction_id", { .int_val = transaction_id }, UBUS_Integer }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 5, + e = cwmp_ubus_call(USP_OBJECT_NAME, "del_object", CWMP_UBUS_ARGS{ { "path", { .str_val = object_name }, UBUS_String }, { "key", { .str_val = key }, UBUS_String }, { "transaction_id", { .int_val = transaction_id }, UBUS_Integer }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 5, ubus_objects_callback, &add_result); if (e < 0) { CWMP_LOG(INFO, "del_object ubus method failed: Ubus err code: %d", e); diff --git a/diagnostic.c b/diagnostic.c index 08c355b..88c1d5d 100644 --- a/diagnostic.c +++ b/diagnostic.c @@ -9,13 +9,17 @@ * Author: Amin Ben Ramdhane * Author: Omar Kallel */ -#include - +#include +#include #include "common.h" #include "diagnostic.h" +#include "config.h" +#include "datamodel_interface.h" #include "ubus.h" -#include "log.h" +#include "cwmp_uci.h" #include "event.h" +#include "soap.h" +#include "log.h" struct diagnostic_input { char *input_name; @@ -165,7 +169,7 @@ int cwmp_download_diagnostics() return -1; CWMP_LOG(INFO, "Download diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_root_cause_event_diagnostic(); return 0; } @@ -175,7 +179,7 @@ int cwmp_upload_diagnostics() return -1; CWMP_LOG(INFO, "Upload diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_root_cause_event_diagnostic(); return 0; } @@ -185,7 +189,7 @@ int cwmp_ip_ping_diagnostics() return -1; CWMP_LOG(INFO, "IPPing diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_root_cause_event_diagnostic(); return 0; } @@ -195,7 +199,7 @@ int cwmp_nslookup_diagnostics() return -1; CWMP_LOG(INFO, "Nslookup diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_root_cause_event_diagnostic(); return 0; } @@ -205,7 +209,7 @@ int cwmp_traceroute_diagnostics() return -1; CWMP_LOG(INFO, "Trace Route diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_root_cause_event_diagnostic(); return 0; } @@ -215,7 +219,7 @@ int cwmp_udp_echo_diagnostics() return -1; CWMP_LOG(INFO, "UDPEcho diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_root_cause_event_diagnostic(); return 0; } @@ -225,6 +229,6 @@ int cwmp_serverselection_diagnostics() return -1; CWMP_LOG(INFO, "Server Selection diagnostic is successfully executed"); - cwmp_root_cause_event_ipdiagnostic(); + cwmp_root_cause_event_diagnostic(); return 0; } diff --git a/digestauth.c b/digestauth.c index 7133ef1..7c45c3e 100644 --- a/digestauth.c +++ b/digestauth.c @@ -10,16 +10,16 @@ * */ +#include #include -#include -#include +#include #include -#include "log.h" #include "common.h" #include "digestauth.h" -#include "ssl_utils.h" #include "md5.h" +#include "log.h" +#include "ssl_utils.h" #define HASH_MD5_HEX_LEN (2 * MD5_DIGEST_SIZE) @@ -329,9 +329,9 @@ int http_digest_auth_fail_response(FILE *fp, const char *http_method, const char */ int http_digest_auth_check(const char *http_method, const char *url, const char *header, const char *realm, const char *username, const char *password, unsigned int nonce_timeout) { - size_t len; + size_t len = 0; char *end; - char nonce[MAX_NONCE_LENGTH]; + char nonce[MAX_NONCE_LENGTH] = {0}; size_t left; /* number of characters left in 'header' for 'uri' */ DD(DEBUG, "%s: header: %s", __FUNCTION__, header); @@ -339,7 +339,7 @@ int http_digest_auth_check(const char *http_method, const char *url, const char left = strlen(header); { - char un[MAX_USERNAME_LENGTH]; + char un[MAX_USERNAME_LENGTH] = {0}; len = lookup_sub_value(un, sizeof(un), header, "username"); if (0 != strcmp(username, un)) @@ -348,7 +348,7 @@ int http_digest_auth_check(const char *http_method, const char *url, const char } { - char r[MAX_REALM_LENGTH]; + char r[MAX_REALM_LENGTH] = {0}; len = lookup_sub_value(r, sizeof(r), header, "realm"); if ((0 == len) || (0 != strcmp(realm, r))) @@ -362,13 +362,14 @@ int http_digest_auth_check(const char *http_method, const char *url, const char { char uri[left]; - char cnonce[MAX_NONCE_LENGTH]; - char qop[15]; /* auth,auth-int */ - char nc[20]; - char response[MAX_AUTH_RESPONSE_LENGTH]; - char ha1[HASH_MD5_HEX_LEN + 1]; - char respexp[HASH_MD5_HEX_LEN + 1]; - char noncehashexp[HASH_MD5_HEX_LEN + 9]; + memset( uri, 0, sizeof(uri) ); + char cnonce[MAX_NONCE_LENGTH] = {0}; + char qop[15] = {0}; /* auth,auth-int */ + char nc[20] = {0}; + char response[MAX_AUTH_RESPONSE_LENGTH] = {0}; + char ha1[HASH_MD5_HEX_LEN + 1] = {0}; + char respexp[HASH_MD5_HEX_LEN + 1] = {0}; + char noncehashexp[HASH_MD5_HEX_LEN + 9] = {0}; uint32_t nonce_time; unsigned long int nci; uint32_t t; diff --git a/download.c b/download.c index da645f6..21712d4 100644 --- a/download.c +++ b/download.c @@ -9,27 +9,24 @@ */ #include -#include #include +#include "common.h" #include "download.h" -#include "ubus.h" #include "cwmp_uci.h" #include "backupSession.h" -#include "cwmp_time.h" +#include "ubus.h" #include "log.h" +#include "cwmp_time.h" #include "event.h" +#include "cwmp_uci.h" +#include "session.h" +#include "subprocess.h" LIST_HEAD(list_download); LIST_HEAD(list_schedule_download); -LIST_HEAD(list_apply_schedule_download); pthread_mutex_t mutex_download = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t threshold_download; -pthread_mutex_t mutex_schedule_download = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t threshold_schedule_download; -pthread_mutex_t mutex_apply_schedule_download = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t threshold_apply_schedule_download; int count_download_queue = 0; @@ -70,6 +67,57 @@ int download_file(const char *file_path, const char *url, const char *username, return res_code; } +char *download_file_task_function(char *task) +{ + + struct blob_buf bbuf; + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + + if (blobmsg_add_json_from_string(&bbuf, task) == false) { + blob_buf_free(&bbuf); + return NULL; + } + const struct blobmsg_policy p[5] = { { "task", BLOBMSG_TYPE_STRING }, { "file_path", BLOBMSG_TYPE_STRING }, { "url", BLOBMSG_TYPE_STRING }, { "username", BLOBMSG_TYPE_STRING }, { "password", BLOBMSG_TYPE_STRING } }; + + struct blob_attr *tb[5] = { NULL, NULL, NULL, NULL, NULL}; + blobmsg_parse(p, 5, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head)); + char *task_name = blobmsg_get_string(tb[0]); + if (!task_name || strcmp(task_name, "download") != 0) + return NULL; + char *file_path = blobmsg_get_string(tb[1]); + char *url = blobmsg_get_string(tb[2]); + char *username = blobmsg_get_string(tb[3]); + char *password = blobmsg_get_string(tb[4]); + + int http_code = download_file(file_path, url, username, password); + char *http_ret = (char *)malloc(4 * sizeof(char)); + snprintf(http_ret, 4, "%d", http_code); + http_ret[3] = 0; + return http_ret; +} + +int download_file_in_subprocess(const char *file_path, const char *url, const char *username, const char *password) +{ + subprocess_start(download_file_task_function); + + struct blob_buf bbuf; + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + blobmsg_add_string(&bbuf, "task", "download"); + blobmsg_add_string(&bbuf, "file_path", file_path ? file_path : ""); + blobmsg_add_string(&bbuf, "url", url ? url : ""); + blobmsg_add_string(&bbuf, "username", username ? username : ""); + blobmsg_add_string(&bbuf, "password", password ? password : ""); + char *download_task = blobmsg_format_json(bbuf.head, true); + blob_buf_free(&bbuf); + + if (download_task != NULL) { + char *ret = execute_task_in_subprocess(download_task); + return atoi(ret); + } + return 500; +} /* * Check if the downloaded image can be applied */ @@ -140,6 +188,58 @@ int get_available_bank_id() return bank_id; } +/* + * Get Bank Status + */ +void ubus_get_bank_status_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg) +{ + int *bank_id = (int *)req->priv; + int *status = bank_id; + bool bank_found = false; + struct blob_attr *banks = NULL; + struct blob_attr *cur; + int rem; + + blobmsg_for_each_attr(cur, msg, rem) + { + if (blobmsg_type(cur) == BLOBMSG_TYPE_ARRAY) { + banks = cur; + break; + } + } + + const struct blobmsg_policy p[8] = { { "name", BLOBMSG_TYPE_STRING }, { "id", BLOBMSG_TYPE_INT32 }, { "active", BLOBMSG_TYPE_BOOL }, { "upgrade", BLOBMSG_TYPE_BOOL }, + { "fwver", BLOBMSG_TYPE_STRING }, { "swver", BLOBMSG_TYPE_STRING }, { "fwver", BLOBMSG_TYPE_STRING }, { "status", BLOBMSG_TYPE_STRING } }; + + blobmsg_for_each_attr(cur, banks, rem) + { + struct blob_attr *tb[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + blobmsg_parse(p, 8, tb, blobmsg_data(cur), blobmsg_len(cur)); + if (!tb[0]) + continue; + + if (blobmsg_get_u32(tb[1]) == (uint32_t)*bank_id) { + bank_found = true; + if (strcmp(blobmsg_get_string(tb[7]), "Available") == 0 || strcmp(blobmsg_get_string(tb[7]), "Active")) + *status = 1; + else + *status = 0; + } + } + if (bank_found == false) + *status = 0; +} + +int get_applied_firmware_status(int *bank_id_status) +{ + int e; + e = cwmp_ubus_call("fwbank", "dump", CWMP_UBUS_ARGS{ {} }, 0, ubus_get_bank_status_callback, &bank_id_status); + if (e != 0) { + CWMP_LOG(INFO, "fwbank dump ubus method failed: Ubus err code: %d", e); + } + return e; +} + /* * Apply the new firmware */ @@ -154,6 +254,24 @@ int cwmp_apply_firmware() return e; } +void wait_firmware_to_be_applied(int bank_id) +{ + int count = 0; + + do { + int bank_id_status = bank_id; + + if (get_applied_firmware_status(&bank_id_status) != CWMP_OK) + break; + + if (bank_id_status == 1) + break; + + usleep(1000 * 1000); + count++; + } while(count < 15); +} + int cwmp_apply_multiple_firmware() { int e; @@ -166,9 +284,28 @@ int cwmp_apply_multiple_firmware() CWMP_LOG(INFO, "fwbank upgrade ubus method failed: Ubus err code: %d", e); return -1; } + //wait until the apply completes + wait_firmware_to_be_applied(bank_id); return CWMP_OK; } +char *apply_multiple_firmware_task_function(char *task __attribute__((unused))) +{ + int ret = cwmp_apply_multiple_firmware(); + + char *ret_str = (char *)malloc(2 * sizeof(char)); + snprintf(ret_str, 2, "%d", ret); + ret_str[1] = 0; + return ret_str; +} + +int cwmp_apply_multiple_firmware_in_subprocess() +{ + subprocess_start(apply_multiple_firmware_task_function); + char *ret = execute_task_in_subprocess("{}"); //empty json object + return atoi(ret); +} + int cwmp_launch_download(struct download *pdownload, char *download_file_name, enum load_type ltype, struct transfer_complete **ptransfer_complete) { int error = FAULT_CPE_NO_FAULT; @@ -185,7 +322,7 @@ int cwmp_launch_download(struct download *pdownload, char *download_file_name, e goto end_download; } - int http_code = download_file(ICWMP_DOWNLOAD_FILE, pdownload->url, pdownload->username, pdownload->password); + int http_code = download_file_in_subprocess(ICWMP_DOWNLOAD_FILE, pdownload->url, pdownload->username, pdownload->password); if (http_code == 404) error = FAULT_CPE_DOWNLOAD_FAIL_CONTACT_SERVER; else if (http_code == 401) @@ -264,11 +401,11 @@ char *get_file_name_by_download_url(char *url) return slash+1; } -int apply_downloaded_file(struct cwmp *cwmp, struct download *pdownload, char *download_file_name, struct transfer_complete *ptransfer_complete) +int apply_downloaded_file(struct download *pdownload, char *download_file_name, struct transfer_complete *ptransfer_complete) { int error = FAULT_CPE_NO_FAULT; if (pdownload->file_type[0] == '1') { - ptransfer_complete->old_software_version = cwmp->deviceid.softwareversion; + ptransfer_complete->old_software_version = cwmp_main->deviceid.softwareversion; } bkp_session_insert_transfer_complete(ptransfer_complete); bkp_session_save(); @@ -314,7 +451,7 @@ int apply_downloaded_file(struct cwmp *cwmp, struct download *pdownload, char *d error = FAULT_CPE_NO_FAULT; } else if (strcmp(pdownload->file_type, STORED_FIRMWARE_IMAGE_FILE_TYPE) == 0) { - int err = cwmp_apply_multiple_firmware(); + int err = cwmp_apply_multiple_firmware_in_subprocess(); if (err == CWMP_OK) error = FAULT_CPE_NO_FAULT; else @@ -330,17 +467,19 @@ int apply_downloaded_file(struct cwmp *cwmp, struct download *pdownload, char *d } return FAULT_CPE_NO_FAULT; } + if (error != FAULT_CPE_NO_FAULT) { bkp_session_delete_transfer_complete(ptransfer_complete); ptransfer_complete->fault_code = error; } + bkp_session_insert_transfer_complete(ptransfer_complete); bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); + cwmp_root_cause_transfer_complete(ptransfer_complete); return error; } -struct transfer_complete *set_download_error_transfer_complete(struct cwmp *cwmp, struct download *pdownload, enum load_type ltype) +struct transfer_complete *set_download_error_transfer_complete(struct download *pdownload, enum load_type ltype) { struct transfer_complete *ptransfer_complete; ptransfer_complete = calloc(1, sizeof(struct transfer_complete)); @@ -351,422 +490,11 @@ struct transfer_complete *set_download_error_transfer_complete(struct cwmp *cwmp ptransfer_complete->fault_code = ltype == TYPE_DOWNLOAD ? FAULT_CPE_DOWNLOAD_FAILURE : FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW; ptransfer_complete->type = ltype; bkp_session_insert_transfer_complete(ptransfer_complete); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); + cwmp_root_cause_transfer_complete(ptransfer_complete); } return ptransfer_complete; } -void *thread_cwmp_rpc_cpe_download(void *v) -{ - struct cwmp *cwmp = (struct cwmp *)v; - struct download *pdownload; - struct timespec download_timeout = { 0, 0 }; - time_t current_time, stime; - int error; - struct transfer_complete *ptransfer_complete; - long int time_of_grace = 3600, timeout; - - sleep(3); - for (;;) { - - if (thread_end) - break; - - if (list_download.next != &(list_download)) { - pdownload = list_entry(list_download.next, struct download, list); - stime = pdownload->scheduled_time; - current_time = time(NULL); - if (pdownload->scheduled_time != 0) - timeout = current_time - pdownload->scheduled_time; - else - timeout = 0; - if ((timeout >= 0) && (timeout > time_of_grace)) { - pthread_mutex_lock(&mutex_download); - bkp_session_delete_download(pdownload); - error = FAULT_CPE_DOWNLOAD_FAILURE; - ptransfer_complete = set_download_error_transfer_complete(cwmp, pdownload, TYPE_DOWNLOAD); - list_del(&(pdownload->list)); - if (pdownload->scheduled_time != 0) - count_download_queue--; - cwmp_free_download_request(pdownload); - pthread_mutex_unlock(&mutex_download); - continue; - } - if ((timeout >= 0) && (timeout <= time_of_grace)) { - pthread_mutex_lock(&(cwmp->mutex_session_send)); - char *download_file_name = get_file_name_by_download_url(pdownload->url); - CWMP_LOG(INFO, "Launch download file %s", pdownload->url); - error = cwmp_launch_download(pdownload, download_file_name, TYPE_DOWNLOAD, &ptransfer_complete); - sleep(3); - if (error != FAULT_CPE_NO_FAULT) { - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - bkp_session_delete_transfer_complete(ptransfer_complete); - } else { - error = apply_downloaded_file(cwmp, pdownload, download_file_name, ptransfer_complete); - if (error || pdownload->file_type[0] == '6') - bkp_session_delete_transfer_complete(ptransfer_complete); - } - if (pdownload->file_type[0] == '6') - sleep(30); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - pthread_mutex_lock(&mutex_download); - list_del(&(pdownload->list)); - if (pdownload->scheduled_time != 0) - count_download_queue--; - cwmp_free_download_request(pdownload); - pthread_mutex_unlock(&mutex_download); - continue; - } - pthread_mutex_lock(&mutex_download); - download_timeout.tv_sec = stime; - pthread_cond_timedwait(&threshold_download, &mutex_download, &download_timeout); - pthread_mutex_unlock(&mutex_download); - } else { - pthread_mutex_lock(&mutex_download); - pthread_cond_wait(&threshold_download, &mutex_download); - pthread_mutex_unlock(&mutex_download); - } - } - return NULL; -} - -int cwmp_add_apply_schedule_download(struct download *schedule_download, char *start_time) -{ - int i = 0; - int error = FAULT_CPE_NO_FAULT; - struct apply_schedule_download *apply_schedule_download; - - apply_schedule_download = calloc(1, sizeof(struct apply_schedule_download)); - if (apply_schedule_download == NULL) { - error = FAULT_CPE_INTERNAL_ERROR; - goto end; - } - if (error == FAULT_CPE_NO_FAULT) { - pthread_mutex_lock(&mutex_apply_schedule_download); - apply_schedule_download->command_key = strdup(schedule_download->command_key); - apply_schedule_download->file_type = strdup(schedule_download->file_type); - apply_schedule_download->start_time = strdup(start_time); - for (i = 0; i < 2; i++) { - apply_schedule_download->timeintervals[i].windowstart = schedule_download->timewindowstruct[i].windowstart; - apply_schedule_download->timeintervals[i].windowend = schedule_download->timewindowstruct[i].windowend; - apply_schedule_download->timeintervals[i].maxretries = schedule_download->timewindowstruct[i].maxretries; - } - list_add_tail(&(apply_schedule_download->list), &(list_apply_schedule_download)); - - bkp_session_insert_apply_schedule_download(apply_schedule_download); - bkp_session_save(); - pthread_mutex_unlock(&mutex_apply_schedule_download); - pthread_cond_signal(&threshold_apply_schedule_download); - } -end: - cwmp_free_apply_schedule_download_request(apply_schedule_download); - return 0; -} - -void *thread_cwmp_rpc_cpe_schedule_download(void *v) -{ - struct cwmp *cwmp = (struct cwmp *)v; - struct timespec download_timeout = { 0, 0 }; - int error = FAULT_CPE_NO_FAULT; - struct transfer_complete *ptransfer_complete; - int min_time = 0; - struct download *current_download = NULL; - struct download *p, *_p; - - for (;;) { - time_t current_time; - - if (thread_end) - break; - - current_time = time(NULL); - if (list_schedule_download.next != &(list_schedule_download)) { - list_for_each_entry_safe (p, _p, &(list_schedule_download), list) { - if (min_time == 0) { - if (p->timewindowstruct[0].windowend >= current_time) { - min_time = p->timewindowstruct[0].windowstart; - current_download = p; - } else if (p->timewindowstruct[1].windowend >= current_time) { - min_time = p->timewindowstruct[1].windowstart; - current_download = p; - } else { - pthread_mutex_lock(&mutex_schedule_download); - bkp_session_delete_schedule_download(p); - error = FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW; - ptransfer_complete = set_download_error_transfer_complete(cwmp, p, TYPE_SCHEDULE_DOWNLOAD); - list_del(&(p->list)); - if (p->timewindowstruct[0].windowstart != 0) - count_download_queue--; - cwmp_free_schedule_download_request(p); - pthread_mutex_unlock(&mutex_schedule_download); - continue; - } - } else { - if (p->timewindowstruct[0].windowend >= current_time) { - if (p->timewindowstruct[0].windowstart < min_time) { - min_time = p->timewindowstruct[0].windowstart; - current_download = p; - } - - } else if (p->timewindowstruct[1].windowend >= current_time) { - if (p->timewindowstruct[1].windowstart < min_time) { - min_time = p->timewindowstruct[1].windowstart; - current_download = p; - } - } else { - pthread_mutex_lock(&mutex_schedule_download); - bkp_session_delete_schedule_download(p); - error = FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW; - ptransfer_complete = set_download_error_transfer_complete(cwmp, p, TYPE_SCHEDULE_DOWNLOAD); - list_del(&(p->list)); - if (p->timewindowstruct[0].windowstart != 0) - count_download_queue--; - cwmp_free_schedule_download_request(p); - pthread_mutex_unlock(&mutex_schedule_download); - continue; - } - } - } - } else { - pthread_mutex_lock(&mutex_schedule_download); - pthread_cond_wait(&threshold_schedule_download, &mutex_schedule_download); - pthread_mutex_unlock(&mutex_schedule_download); - } - if (min_time == 0) { - continue; - } else if (min_time <= current_time) { - char *download_file_name = get_file_name_by_download_url(current_download->url); - if ((min_time == current_download->timewindowstruct[0].windowstart && (current_download->timewindowstruct[0].windowmode)[0] == '2') || (min_time == current_download->timewindowstruct[1].windowstart && (current_download->timewindowstruct[1].windowmode)[0] == '2')) { - pthread_mutex_lock(&mutex_schedule_download); - ptransfer_complete = calloc(1, sizeof(struct transfer_complete)); - ptransfer_complete->type = TYPE_SCHEDULE_DOWNLOAD; - error = cwmp_launch_download(current_download, download_file_name, TYPE_SCHEDULE_DOWNLOAD, &ptransfer_complete); - if (error != FAULT_CPE_NO_FAULT) { - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - bkp_session_delete_transfer_complete(ptransfer_complete); - } else { - pthread_mutex_unlock(&mutex_schedule_download); - if (pthread_mutex_trylock(&(cwmp->mutex_session_send)) == 0) { - pthread_mutex_lock(&mutex_apply_schedule_download); - pthread_mutex_lock(&mutex_schedule_download); - error = apply_downloaded_file(cwmp, current_download, download_file_name, ptransfer_complete); - if (error == FAULT_CPE_NO_FAULT) - exit(EXIT_SUCCESS); - - pthread_mutex_unlock(&mutex_schedule_download); - pthread_mutex_unlock(&mutex_apply_schedule_download); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - } else { - cwmp_add_apply_schedule_download(current_download, ptransfer_complete->start_time); - } - } - pthread_mutex_lock(&mutex_schedule_download); - bkp_session_delete_schedule_download(current_download); - bkp_session_save(); - list_del(&(current_download->list)); - cwmp_free_schedule_download_request(current_download); - pthread_mutex_unlock(&mutex_schedule_download); - min_time = 0; - current_download = NULL; - continue; - } //AT ANY TIME OR WHEN IDLE - else { - pthread_mutex_lock(&(cwmp->mutex_session_send)); - CWMP_LOG(INFO, "Launch download file %s", current_download->url); - error = cwmp_launch_download(current_download, download_file_name, TYPE_SCHEDULE_DOWNLOAD, &ptransfer_complete); - if (error != FAULT_CPE_NO_FAULT) { - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - bkp_session_delete_transfer_complete(ptransfer_complete); - } else { - error = apply_downloaded_file(cwmp, current_download, download_file_name, ptransfer_complete); - if (error == FAULT_CPE_NO_FAULT) - exit(EXIT_SUCCESS); - } - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - pthread_mutex_lock(&mutex_schedule_download); - list_del(&(current_download->list)); - if (current_download->timewindowstruct[0].windowstart != 0) - count_download_queue--; - cwmp_free_schedule_download_request(current_download); - pthread_mutex_unlock(&mutex_schedule_download); - continue; - } - } else { - if (min_time == current_download->timewindowstruct[0].windowstart) { - pthread_mutex_lock(&mutex_schedule_download); - download_timeout.tv_sec = min_time; - pthread_cond_timedwait(&threshold_schedule_download, &mutex_schedule_download, &download_timeout); - pthread_mutex_unlock(&mutex_schedule_download); - } else if (min_time == current_download->timewindowstruct[1].windowstart) { - pthread_mutex_lock(&mutex_schedule_download); - download_timeout.tv_sec = min_time; - pthread_cond_timedwait(&threshold_schedule_download, &mutex_schedule_download, &download_timeout); - pthread_mutex_unlock(&mutex_schedule_download); - } - } - } - return NULL; -} - -void *thread_cwmp_rpc_cpe_apply_schedule_download(void *v) -{ - struct cwmp *cwmp = (struct cwmp *)v; - struct timespec apply_timeout = { 0, 0 }; - int error = FAULT_CPE_NO_FAULT; - struct transfer_complete *ptransfer_complete; - int min_time = 0; - struct apply_schedule_download *apply_download = NULL; - struct apply_schedule_download *p, *_p; - - for (;;) { - time_t current_time; - - if (thread_end) - break; - - current_time = time(NULL); - if (list_apply_schedule_download.next != &(list_apply_schedule_download)) { - list_for_each_entry_safe (p, _p, &(list_apply_schedule_download), list) { - if (min_time == 0) { - if (p->timeintervals[0].windowend >= current_time) { - min_time = p->timeintervals[0].windowstart; - apply_download = p; - } else if (p->timeintervals[1].windowend >= current_time) { - min_time = p->timeintervals[1].windowstart; - apply_download = p; - } else { - pthread_mutex_lock(&mutex_apply_schedule_download); - bkp_session_delete_apply_schedule_download(p); - error = FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW; - ptransfer_complete = set_download_error_transfer_complete(cwmp, (struct download *)p, TYPE_SCHEDULE_DOWNLOAD); - list_del(&(p->list)); - if (p->timeintervals[0].windowstart != 0) - count_download_queue--; - cwmp_free_apply_schedule_download_request(p); - pthread_mutex_unlock(&mutex_apply_schedule_download); - continue; - } - } else { - if (p->timeintervals[0].windowend >= current_time) { - if (p->timeintervals[0].windowstart < min_time) { - min_time = p->timeintervals[0].windowstart; - apply_download = p; - } - - } else if (p->timeintervals[1].windowend >= current_time) { - if (p->timeintervals[1].windowstart < min_time) { - min_time = p->timeintervals[1].windowstart; - apply_download = p; - } - } else { - pthread_mutex_lock(&mutex_apply_schedule_download); - bkp_session_delete_apply_schedule_download(p); - error = FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW; - ptransfer_complete = set_download_error_transfer_complete(cwmp, (struct download *)p, TYPE_SCHEDULE_DOWNLOAD); - list_del(&(p->list)); - /*if(p->timewindowintervals[0].windowstart != 0) - count_download_queue--;*/ - cwmp_free_apply_schedule_download_request(p); - pthread_mutex_unlock(&mutex_apply_schedule_download); - continue; - } - } - } - } else { - pthread_mutex_lock(&mutex_apply_schedule_download); - pthread_cond_wait(&threshold_apply_schedule_download, &mutex_apply_schedule_download); - pthread_mutex_unlock(&mutex_apply_schedule_download); - } - if (min_time == 0) { - continue; - } else if (min_time <= current_time) { - pthread_mutex_lock(&(cwmp->mutex_session_send)); - pthread_mutex_lock(&mutex_schedule_download); - bkp_session_delete_apply_schedule_download(apply_download); - bkp_session_save(); - ptransfer_complete = calloc(1, sizeof(struct transfer_complete)); - if (apply_download->file_type[0] == '1') { - ptransfer_complete->old_software_version = cwmp->deviceid.softwareversion; - } - ptransfer_complete->command_key = strdup(apply_download->command_key); - ptransfer_complete->start_time = strdup(apply_download->start_time); - ptransfer_complete->complete_time = strdup(mix_get_time()); - ptransfer_complete->fault_code = error; - ptransfer_complete->type = TYPE_SCHEDULE_DOWNLOAD; - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - - if (strcmp(apply_download->file_type, FIRMWARE_UPGRADE_IMAGE_FILE_TYPE) == 0) { - cwmp_uci_set_value("cwmp", "cpe", "exec_download", "1"); - cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); - cwmp_apply_firmware(); - sleep(70); - error = FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED; - } else if (strcmp(apply_download->file_type, WEB_CONTENT_FILE_TYPE) == 0) { - //TODO Not Supported - error = FAULT_CPE_NO_FAULT; - } else if (strcmp(apply_download->file_type, VENDOR_CONFIG_FILE_TYPE) == 0) { - cwmp_uci_init(); - int err = cwmp_uci_import(NULL, VENDOR_CONFIG_FILE, UCI_STANDARD_CONFIG); - cwmp_uci_exit(); - if (err == CWMP_OK) - error = FAULT_CPE_NO_FAULT; - else if (err == CWMP_GEN_ERR) - error = FAULT_CPE_INTERNAL_ERROR; - else if (err == -1) - error = FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED; - } - - if ((error == FAULT_CPE_NO_FAULT) && (apply_download->file_type[0] == '1' || apply_download->file_type[0] == '3')) { - if (apply_download->file_type[0] == '3') { - CWMP_LOG(INFO, "Download and apply new vendor config file is done successfully"); - } - exit(EXIT_SUCCESS); - } - if (error != FAULT_CPE_NO_FAULT) { - bkp_session_delete_transfer_complete(ptransfer_complete); - ptransfer_complete->fault_code = error; - } - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - - pthread_mutex_unlock(&mutex_schedule_download); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - pthread_mutex_lock(&mutex_apply_schedule_download); - list_del(&(apply_download->list)); - /*if(pdownload->timeintervals[0].windowstart != 0) - count_download_queue--;*/ - cwmp_free_apply_schedule_download_request(apply_download); - pthread_mutex_unlock(&mutex_apply_schedule_download); - continue; - } else { - if (min_time == apply_download->timeintervals[0].windowstart) { - pthread_mutex_lock(&mutex_apply_schedule_download); - apply_timeout.tv_sec = min_time; - pthread_cond_timedwait(&threshold_apply_schedule_download, &mutex_schedule_download, &apply_timeout); - pthread_mutex_unlock(&mutex_apply_schedule_download); - } else if (min_time == apply_download->timeintervals[1].windowstart) { - pthread_mutex_lock(&mutex_apply_schedule_download); - apply_timeout.tv_sec = min_time; - pthread_cond_timedwait(&threshold_schedule_download, &mutex_schedule_download, &apply_timeout); - pthread_mutex_unlock(&mutex_schedule_download); - } - } - } - return NULL; -} - int cwmp_free_download_request(struct download *download) { if (download != NULL) { @@ -856,7 +584,6 @@ int cwmp_scheduledDownload_remove_all() int cwmp_scheduled_Download_remove_all() { - pthread_mutex_lock(&mutex_schedule_download); while (list_schedule_download.next != &(list_schedule_download)) { struct download *schedule_download; schedule_download = list_entry(list_schedule_download.next, struct download, list); @@ -866,29 +593,11 @@ int cwmp_scheduled_Download_remove_all() count_download_queue--; cwmp_free_schedule_download_request(schedule_download); } - pthread_mutex_unlock(&mutex_schedule_download); return CWMP_OK; } -int cwmp_apply_scheduled_Download_remove_all() -{ - pthread_mutex_lock(&mutex_apply_schedule_download); - while (list_apply_schedule_download.next != &(list_apply_schedule_download)) { - struct apply_schedule_download *apply_schedule_download; - apply_schedule_download = list_entry(list_apply_schedule_download.next, struct apply_schedule_download, list); - list_del(&(apply_schedule_download->list)); - bkp_session_delete_apply_schedule_download(apply_schedule_download); - /*if(apply_schedule_download->timetimeintervals[0].windowstart != 0) - count_download_queue--;*/ //TOCK - cwmp_free_apply_schedule_download_request(apply_schedule_download); - } - pthread_mutex_unlock(&mutex_apply_schedule_download); - - return CWMP_OK; -} - -int cwmp_rpc_acs_destroy_data_transfer_complete(struct session *session __attribute__((unused)), struct rpc *rpc) +int cwmp_rpc_acs_destroy_data_transfer_complete(struct rpc *rpc) { if (rpc->extra_data != NULL) { struct transfer_complete *p = (struct transfer_complete *)rpc->extra_data; @@ -902,3 +611,138 @@ int cwmp_rpc_acs_destroy_data_transfer_complete(struct session *session __attrib FREE(rpc->extra_data); return 0; } + +void cwmp_start_download(struct uloop_timeout *timeout) +{ + struct download *pdownload; + int error = FAULT_CPE_NO_FAULT; + struct transfer_complete *ptransfer_complete; + pdownload = container_of(timeout, struct download, handler_timer); + + char *download_file_name = get_file_name_by_download_url(pdownload->url); + CWMP_LOG(INFO, "Launch download file %s", pdownload->url); + error = cwmp_launch_download(pdownload, download_file_name, TYPE_DOWNLOAD, &ptransfer_complete); + sleep(3); + if (error != FAULT_CPE_NO_FAULT) { + CWMP_LOG(ERROR, "Error while downloading the file: %s", pdownload->url); + bkp_session_insert_transfer_complete(ptransfer_complete); + bkp_session_save(); + cwmp_root_cause_transfer_complete(ptransfer_complete); + bkp_session_delete_transfer_complete(ptransfer_complete); + } else { + error = apply_downloaded_file(pdownload, download_file_name, ptransfer_complete); + if (error != FAULT_CPE_NO_FAULT) { + CWMP_LOG(ERROR, "Error while applying the downloaded file: %s", download_file_name); + bkp_session_insert_transfer_complete(ptransfer_complete); + bkp_session_save(); + cwmp_root_cause_transfer_complete(ptransfer_complete); + bkp_session_delete_transfer_complete(ptransfer_complete); + } + } + if (error == FAULT_CPE_NO_FAULT && pdownload->file_type[0] == '3') { + cwmp_root_cause_transfer_complete(ptransfer_complete); + bkp_session_delete_download(pdownload); + bkp_session_delete_transfer_complete(ptransfer_complete); + bkp_session_save(); + } + pthread_mutex_lock(&mutex_download); + list_del(&(pdownload->list)); + if (pdownload->scheduled_time != 0) + count_download_queue--; + cwmp_free_download_request(pdownload); + pthread_mutex_unlock(&mutex_download); + trigger_cwmp_session_timer(); +} + +void cwmp_start_schedule_download(struct uloop_timeout *timeout) +{ + struct download *sched_download; + int error = FAULT_CPE_NO_FAULT; + struct transfer_complete *ptransfer_complete; + sched_download = container_of(timeout, struct download, handler_timer); + bool outdate = false; + int delay; + int window_index; + + time_t now = time(NULL); + if (sched_download->timewindowstruct[0].windowstart > now) { + delay = sched_download->timewindowstruct[0].windowstart - now; + uloop_timeout_set(&sched_download->handler_timer, 1000 * delay); + return; + } else if (sched_download->timewindowstruct[0].windowend >= now) { + outdate = false; + window_index = 0; + } else if (sched_download->timewindowstruct[1].windowstart > now) { + delay = sched_download->timewindowstruct[1].windowstart - now; + uloop_timeout_set(&sched_download->handler_timer, 1000 * delay); + return; + } else if (sched_download->timewindowstruct[1].windowend >= now) { + outdate = false; + window_index = 1; + } else { + outdate = true; + } + + if (!outdate) { + char *download_file_name = get_file_name_by_download_url(sched_download->url); + CWMP_LOG(INFO, "Launch download file %s", sched_download->url); + error = cwmp_launch_download(sched_download, download_file_name, TYPE_DOWNLOAD, &ptransfer_complete); + sleep(3); + if (error != FAULT_CPE_NO_FAULT) { + CWMP_LOG(ERROR, "Error while downloading the file: %s", sched_download->url); + goto retry; + } else { + error = apply_downloaded_file(sched_download, download_file_name, ptransfer_complete); + if (error != FAULT_CPE_NO_FAULT) { + CWMP_LOG(ERROR, "Error while applying the downloaded file: %s", download_file_name); + goto retry; + } + } + if (error == FAULT_CPE_NO_FAULT && sched_download->file_type[0] == '3') { + cwmp_root_cause_transfer_complete(ptransfer_complete); + bkp_session_delete_download(sched_download); + bkp_session_delete_transfer_complete(ptransfer_complete); + bkp_session_save(); + } + } else { + error = FAULT_CPE_INTERNAL_ERROR; + CWMP_LOG(ERROR, "Schedule Download out of date"); + ptransfer_complete = calloc(1, sizeof(struct transfer_complete)); + if (ptransfer_complete == NULL) { + // error = FAULT_CPE_INTERNAL_ERROR; + return; + } + + ptransfer_complete->command_key = sched_download->command_key ? strdup(sched_download->command_key) : strdup(""); + ptransfer_complete->start_time = strdup(mix_get_time_of(now)); + ptransfer_complete->complete_time = strdup(mix_get_time()); + ptransfer_complete->type = TYPE_DOWNLOAD; + if (error != FAULT_CPE_NO_FAULT) { + ptransfer_complete->fault_code = error; + } + bkp_session_insert_transfer_complete(ptransfer_complete); + bkp_session_save(); + cwmp_root_cause_transfer_complete(ptransfer_complete); + bkp_session_delete_transfer_complete(ptransfer_complete); + } + + return; + +retry: + if (sched_download->timewindowstruct[window_index].maxretries > 0) { + uloop_timeout_set(&sched_download->handler_timer, 10); + sched_download->timewindowstruct[window_index].maxretries--; + return; + } else { + bkp_session_insert_transfer_complete(ptransfer_complete); + bkp_session_save(); + cwmp_root_cause_transfer_complete(ptransfer_complete); + bkp_session_delete_transfer_complete(ptransfer_complete); + bkp_session_save(); + } + list_del(&(sched_download->list)); + if (sched_download->scheduled_time != 0) + count_download_queue--; + cwmp_free_schedule_download_request(sched_download); + trigger_cwmp_session_timer(); +} diff --git a/event.c b/event.c index 5990f3a..3b95644 100644 --- a/event.c +++ b/event.c @@ -11,12 +11,21 @@ * */ +#include + #include "backupSession.h" -#include "event.h" -#include "sched_inform.h" -#include "download.h" -#include "upload.h" #include "log.h" +#include "event.h" +#include "session.h" +#include "cwmp_du_state.h" +#include "download.h" +#include "soap.h" +#include "upload.h" +#include "sched_inform.h" +#include "ubus.h" +#include "cwmp_event.h" + +pthread_mutex_t add_event_mutext = PTHREAD_MUTEX_INITIALIZER; const struct EVENT_CONST_STRUCT EVENT_CONST[] = {[EVENT_IDX_0BOOTSTRAP] = { "0 BOOTSTRAP", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT }, [EVENT_IDX_1BOOT] = { "1 BOOT", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL }, @@ -54,84 +63,38 @@ void cwmp_save_event_container(struct event_container *event_container) //to be } } -struct event_container *cwmp_add_event_container(struct cwmp *cwmp, int event_code, char *command_key) +void cwmp_root_cause_event_diagnostic(void) { struct event_container *event_container; - struct list_head *ilist; - if (cwmp->head_event_container == NULL) { - struct session *session; - session = cwmp_add_queue_session(cwmp); - if (session == NULL) { - return NULL; - } - cwmp->head_event_container = &(session->head_event_container); - } - //session = list_entry(cwmp->head_event_container, struct session, head_event_container); - list_for_each (ilist, cwmp->head_event_container) { - event_container = list_entry(ilist, struct event_container, list); - if (event_container->code == event_code && EVENT_CONST[event_code].TYPE == EVENT_TYPE_SINGLE) { - return event_container; - } - if (event_container->code > event_code) { - break; - } - } - event_container = calloc(1, sizeof(struct event_container)); + event_container = cwmp_add_event_container(EVENT_IDX_8DIAGNOSTICS_COMPLETE, ""); if (event_container == NULL) { - return NULL; - } - INIT_LIST_HEAD(&(event_container->head_dm_parameter)); - list_add(&(event_container->list), ilist->prev); - event_container->code = event_code; - event_container->command_key = command_key ? strdup(command_key) : strdup(""); - if ((cwmp->event_id < 0) || (cwmp->event_id >= MAX_INT_ID)) { - cwmp->event_id = 0; - } - cwmp->event_id++; - event_container->id = cwmp->event_id; - return event_container; -} - -void cwmp_root_cause_event_ipdiagnostic(void) -{ - struct cwmp *cwmp = &cwmp_main; - struct event_container *event_container; - - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_8DIAGNOSTICS_COMPLETE, ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return; } cwmp_save_event_container(event_container); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - pthread_cond_signal(&(cwmp->threshold_session_send)); + cwmp_main->start_diagnostics = true; return; } -int cwmp_root_cause_event_boot(struct cwmp *cwmp) +int cwmp_root_cause_event_boot() { - if (cwmp->env.boot == CWMP_START_BOOT) { + if (cwmp_main->env.boot == CWMP_START_BOOT) { struct event_container *event_container; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - cwmp->env.boot = 0; - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_1BOOT, ""); + cwmp_main->env.boot = 0; + event_container = cwmp_add_event_container(EVENT_IDX_1BOOT, ""); if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return CWMP_MEM_ERR; } cwmp_save_event_container(event_container); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); } return CWMP_OK; } -int event_remove_all_event_container(struct session *session, int rem_from) +int event_remove_all_event_container(int rem_from) { - while (session->head_event_container.next != &(session->head_event_container)) { + while (cwmp_main->session->events.next != &cwmp_main->session->events) { struct event_container *event_container; - event_container = list_entry(session->head_event_container.next, struct event_container, list); + event_container = list_entry(cwmp_main->session->events.next, struct event_container, list); bkp_session_delete_event(event_container->id, rem_from ? "send" : "queue"); free(event_container->command_key); cwmp_free_all_dm_parameter_list(&(event_container->head_dm_parameter)); @@ -142,16 +105,16 @@ int event_remove_all_event_container(struct session *session, int rem_from) return CWMP_OK; } -int event_remove_noretry_event_container(struct session *session, struct cwmp *cwmp) +int event_remove_noretry_event_container() { struct list_head *ilist, *q; - list_for_each_safe (ilist, q, &(session->head_event_container)) { + list_for_each_safe (ilist, q, &cwmp_main->session->events) { struct event_container *event_container; event_container = list_entry(ilist, struct event_container, list); if (EVENT_CONST[event_container->code].CODE[0] == '6') - cwmp->cwmp_cr_event = 1; + cwmp_main->cwmp_cr_event = 1; if (EVENT_CONST[event_container->code].RETRY == 0) { free(event_container->command_key); @@ -163,247 +126,153 @@ int event_remove_noretry_event_container(struct session *session, struct cwmp *c return CWMP_OK; } -int cwmp_root_cause_event_bootstrap(struct cwmp *cwmp) +int cwmp_root_cause_event_bootstrap() { struct event_container *event_container; char *acsurl = NULL; int cmp = 0; - cwmp_load_saved_session(cwmp, &acsurl, ACS); + cwmp_load_saved_session(&acsurl, ACS); if (acsurl == NULL) - save_acs_bkp_config(cwmp); + save_acs_bkp_config(); - if (acsurl == NULL || ((cmp = strcmp(cwmp->conf.acsurl, acsurl)) != 0)) { - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - if (cwmp->head_event_container != NULL && cwmp->head_session_queue.next != &(cwmp->head_session_queue)) { - struct session *session; - session = list_entry(cwmp->head_event_container, struct session, head_event_container); - event_remove_all_event_container(session, RPC_QUEUE); - } - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_0BOOTSTRAP, ""); + if (acsurl == NULL || ((cmp = strcmp(cwmp_main->conf.acsurl, acsurl)) != 0)) { + event_container = cwmp_add_event_container(EVENT_IDX_0BOOTSTRAP, ""); FREE(acsurl); if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return CWMP_MEM_ERR; } cwmp_save_event_container(event_container); cwmp_scheduleInform_remove_all(); cwmp_scheduledDownload_remove_all(); cwmp_scheduled_Download_remove_all(); - cwmp_apply_scheduled_Download_remove_all(); cwmp_scheduledUpload_remove_all(); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); } else { FREE(acsurl); } if (cmp) { - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, ""); + event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, ""); if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return CWMP_MEM_ERR; } char buf[64] = "Device.ManagementServer.URL"; add_dm_parameter_to_list(&(event_container->head_dm_parameter), buf, NULL, NULL, 0, false); cwmp_save_event_container(event_container); - save_acs_bkp_config(cwmp); + save_acs_bkp_config(cwmp_main); cwmp_scheduleInform_remove_all(); cwmp_scheduledDownload_remove_all(); - cwmp_apply_scheduled_Download_remove_all(); cwmp_scheduled_Download_remove_all(); cwmp_scheduledUpload_remove_all(); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); } return CWMP_OK; } -int cwmp_root_cause_transfer_complete(struct cwmp *cwmp, struct transfer_complete *p) +int cwmp_root_cause_transfer_complete(struct transfer_complete *p) { struct event_container *event_container; - struct session *session; struct rpc *rpc_acs; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_7TRANSFER_COMPLETE, ""); + event_container = cwmp_add_event_container(EVENT_IDX_7TRANSFER_COMPLETE, ""); if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + return CWMP_MEM_ERR; + } + if ((rpc_acs = cwmp_add_session_rpc_acs(RPC_ACS_TRANSFER_COMPLETE)) == NULL) { return CWMP_MEM_ERR; } switch (p->type) { case TYPE_DOWNLOAD: - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_Download, p->command_key ? p->command_key : ""); + event_container = cwmp_add_event_container(EVENT_IDX_M_Download, p->command_key ? p->command_key : ""); if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return CWMP_MEM_ERR; } break; case TYPE_UPLOAD: - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_Upload, p->command_key ? p->command_key : ""); + event_container = cwmp_add_event_container(EVENT_IDX_M_Upload, p->command_key ? p->command_key : ""); if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return CWMP_MEM_ERR; } break; case TYPE_SCHEDULE_DOWNLOAD: - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_Schedule_Download, p->command_key ? p->command_key : ""); + event_container = cwmp_add_event_container(EVENT_IDX_M_Schedule_Download, p->command_key ? p->command_key : ""); if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return CWMP_MEM_ERR; } break; } - session = list_entry(cwmp->head_event_container, struct session, head_event_container); - if ((rpc_acs = cwmp_add_session_rpc_acs(session, RPC_ACS_TRANSFER_COMPLETE)) == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MEM_ERR; - } + rpc_acs->extra_data = (void *)p; - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return CWMP_OK; } -int cwmp_root_cause_changedustate_complete(struct cwmp *cwmp, struct du_state_change_complete *p) +int cwmp_root_cause_changedustate_complete(struct du_state_change_complete *p) { struct event_container *event_container; - struct session *session; struct rpc *rpc_acs; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_11DU_STATE_CHANGE_COMPLETE, ""); + event_container = cwmp_add_event_container(EVENT_IDX_11DU_STATE_CHANGE_COMPLETE, ""); if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return CWMP_MEM_ERR; } - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_ChangeDUState, p->command_key ? p->command_key : ""); + event_container = cwmp_add_event_container(EVENT_IDX_M_ChangeDUState, p->command_key ? p->command_key : ""); if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return CWMP_MEM_ERR; } - session = list_entry(cwmp->head_event_container, struct session, head_event_container); - if ((rpc_acs = cwmp_add_session_rpc_acs(session, RPC_ACS_DU_STATE_CHANGE_COMPLETE)) == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + if ((rpc_acs = cwmp_add_session_rpc_acs(RPC_ACS_DU_STATE_CHANGE_COMPLETE)) == NULL) { return CWMP_MEM_ERR; } rpc_acs->extra_data = (void *)p; - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return CWMP_OK; } -int cwmp_root_cause_get_rpc_method(struct cwmp *cwmp) +int cwmp_root_cause_get_rpc_method() { - if (cwmp->env.periodic == CWMP_START_PERIODIC) { + if (cwmp_main->env.periodic == CWMP_START_PERIODIC) { struct event_container *event_container; - struct session *session; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - cwmp->env.periodic = 0; - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_2PERIODIC, ""); + cwmp_main->env.periodic = 0; + event_container = cwmp_add_event_container(EVENT_IDX_2PERIODIC, ""); if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return CWMP_MEM_ERR; } cwmp_save_event_container(event_container); - session = list_entry(cwmp->head_event_container, struct session, head_event_container); - if (cwmp_add_session_rpc_acs(session, RPC_ACS_GET_RPC_METHODS) == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + if (cwmp_add_session_rpc_acs(RPC_ACS_GET_RPC_METHODS) == NULL) { return CWMP_MEM_ERR; } - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); } return CWMP_OK; } -void *thread_event_periodic(void *v) +bool event_exist_in_list(int event) { - struct cwmp *cwmp = (struct cwmp *)v; - struct event_container *event_container; - int periodic_interval; - bool periodic_enable; - time_t periodic_time; - struct timespec periodic_timeout = { 0, 0 }; - time_t current_time; - long int delta_time; - - periodic_interval = cwmp->conf.period; - periodic_enable = cwmp->conf.periodic_enable; - periodic_time = cwmp->conf.time; - - for (;;) { - pthread_mutex_lock(&(cwmp->mutex_periodic)); - if (cwmp->conf.periodic_enable) { - current_time = time(NULL); - if (periodic_time != 0) { - delta_time = (current_time - periodic_time) % periodic_interval; - if (delta_time >= 0) - periodic_timeout.tv_sec = current_time + periodic_interval - delta_time; - else - periodic_timeout.tv_sec = current_time - delta_time; - } else { - periodic_timeout.tv_sec = current_time + periodic_interval; - } - cwmp->session_status.next_periodic = periodic_timeout.tv_sec; - pthread_cond_timedwait(&(cwmp->threshold_periodic), &(cwmp->mutex_periodic), &periodic_timeout); - } else { - cwmp->session_status.next_periodic = 0; - pthread_cond_wait(&(cwmp->threshold_periodic), &(cwmp->mutex_periodic)); - } - pthread_mutex_unlock(&(cwmp->mutex_periodic)); - - if (thread_end) - break; - - if (periodic_interval != cwmp->conf.period || periodic_enable != cwmp->conf.periodic_enable || periodic_time != cwmp->conf.time) { - periodic_enable = cwmp->conf.periodic_enable; - periodic_interval = cwmp->conf.period; - periodic_time = cwmp->conf.time; - continue; - } - CWMP_LOG(INFO, "Periodic thread: add periodic event in the queue"); - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_2PERIODIC, ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - continue; - } - cwmp_save_event_container(event_container); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - } - return NULL; -} - -bool event_exist_in_list(struct cwmp *cwmp, int event) -{ - struct event_container *event_container; - list_for_each_entry (event_container, cwmp->head_event_container, list) { + struct event_container *event_container = NULL; + list_for_each_entry (event_container, &cwmp_main->session->events, list) { if (event_container->code == event) return true; } return false; } -int cwmp_root_cause_event_periodic(struct cwmp *cwmp) +int cwmp_root_cause_event_periodic() { char local_time[27] = { 0 }; struct tm *t_tm; - if (cwmp->cwmp_period == cwmp->conf.period && cwmp->cwmp_periodic_enable == cwmp->conf.periodic_enable && cwmp->cwmp_periodic_time == cwmp->conf.time) + if (cwmp_main->cwmp_period == cwmp_main->conf.period && cwmp_main->cwmp_periodic_enable == cwmp_main->conf.periodic_enable && cwmp_main->cwmp_periodic_time == cwmp_main->conf.time) return CWMP_OK; - pthread_mutex_lock(&(cwmp->mutex_periodic)); - cwmp->cwmp_period = cwmp->conf.period; - cwmp->cwmp_periodic_enable = cwmp->conf.periodic_enable; - cwmp->cwmp_periodic_time = cwmp->conf.time; - CWMP_LOG(INFO, cwmp->cwmp_periodic_enable ? "Periodic event is enabled. Interval period = %ds" : "Periodic event is disabled", cwmp->cwmp_period); + cwmp_main->cwmp_period = cwmp_main->conf.period; + cwmp_main->cwmp_periodic_enable = cwmp_main->conf.periodic_enable; + cwmp_main->cwmp_periodic_time = cwmp_main->conf.time; + CWMP_LOG(INFO, cwmp_main->cwmp_periodic_enable ? "Periodic event is enabled. Interval period = %ds" : "Periodic event is disabled", cwmp_main->cwmp_period); - t_tm = localtime(&cwmp->cwmp_periodic_time); + t_tm = localtime(&cwmp_main->cwmp_periodic_time); if (t_tm == NULL) return CWMP_GEN_ERR; @@ -415,22 +284,20 @@ int cwmp_root_cause_event_periodic(struct cwmp *cwmp) local_time[22] = ':'; local_time[26] = '\0'; - CWMP_LOG(INFO, cwmp->cwmp_periodic_time ? "Periodic time is %s" : "Periodic time is Unknown", local_time); - pthread_mutex_unlock(&(cwmp->mutex_periodic)); - pthread_cond_signal(&(cwmp->threshold_periodic)); + CWMP_LOG(INFO, cwmp_main->cwmp_periodic_time ? "Periodic time is %s" : "Periodic time is Unknown", local_time); return CWMP_OK; } -void connection_request_ip_value_change(struct cwmp *cwmp, int version) +void connection_request_ip_value_change(int version) { char *bip = NULL; char *ip_version = (version == IPv6) ? "ipv6" : "ip"; - char *ip_value = (version == IPv6) ? cwmp->conf.ipv6 : cwmp->conf.ip; + char *ip_value = (version == IPv6) ? cwmp_main->conf.ipv6 : cwmp_main->conf.ip; if (version == IPv6) - cwmp_load_saved_session(cwmp, &bip, CR_IPv6); + cwmp_load_saved_session(&bip, CR_IPv6); else - cwmp_load_saved_session(cwmp, &bip, CR_IP); + cwmp_load_saved_session(&bip, CR_IP); if (bip == NULL) { bkp_session_simple_insert_in_parent("connection_request", ip_version, ip_value); @@ -439,30 +306,26 @@ void connection_request_ip_value_change(struct cwmp *cwmp, int version) } if (strcmp(bip, ip_value) != 0) { struct event_container *event_container; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, ""); + event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, ""); if (event_container == NULL) { FREE(bip); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return; } cwmp_save_event_container(event_container); bkp_session_simple_insert_in_parent("connection_request", ip_version, ip_value); bkp_session_save(); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - pthread_cond_signal(&(cwmp->threshold_session_send)); } FREE(bip); } -void connection_request_port_value_change(struct cwmp *cwmp, int port) +void connection_request_port_value_change(int port) { char *bport = NULL; char bufport[16]; snprintf(bufport, sizeof(bufport), "%d", port); - cwmp_load_saved_session(cwmp, &bport, CR_PORT); + cwmp_load_saved_session(&bport, CR_PORT); if (bport == NULL) { bkp_session_simple_insert_in_parent("connection_request", "port", bufport); @@ -471,7 +334,7 @@ void connection_request_port_value_change(struct cwmp *cwmp, int port) } if (strcmp(bport, bufport) != 0) { struct event_container *event_container; - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, ""); + event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, ""); if (event_container == NULL) { FREE(bport); return; @@ -483,20 +346,20 @@ void connection_request_port_value_change(struct cwmp *cwmp, int port) FREE(bport); } -int cwmp_root_cause_events(struct cwmp *cwmp) +int cwmp_root_cause_events() { int error; - if ((error = cwmp_root_cause_event_bootstrap(cwmp))) + if ((error = cwmp_root_cause_event_bootstrap())) return error; - if ((error = cwmp_root_cause_event_boot(cwmp))) + if ((error = cwmp_root_cause_event_boot())) return error; - if ((error = cwmp_root_cause_get_rpc_method(cwmp))) + if ((error = cwmp_root_cause_get_rpc_method())) return error; - if ((error = cwmp_root_cause_event_periodic(cwmp))) + if ((error = cwmp_root_cause_event_periodic())) return error; return CWMP_OK; diff --git a/gitlab-ci/functional-api-test.sh b/gitlab-ci/functional-api-test.sh index c443962..37794a7 100755 --- a/gitlab-ci/functional-api-test.sh +++ b/gitlab-ci/functional-api-test.sh @@ -2,7 +2,7 @@ echo "preparation script" pwd -. ./gitlab-ci/shared.sh +source ./gitlab-ci/shared.sh trap cleanup EXIT trap cleanup SIGINT @@ -24,7 +24,7 @@ ubus-api-validator -f ./test/api/json/tr069.validation.json > ./api-test-result. check_ret $? echo "Stop all services" -supervisorctl stop icwmpd +supervisorctl stop all # Artefact gcovr -r . 2> /dev/null --xml -o ./api-test-coverage.xml diff --git a/gitlab-ci/functional-test.sh b/gitlab-ci/functional-test.sh index 8738c44..fb44003 100755 --- a/gitlab-ci/functional-test.sh +++ b/gitlab-ci/functional-test.sh @@ -2,7 +2,7 @@ echo "preparation script" pwd -. ./gitlab-ci/shared.sh +source ./gitlab-ci/shared.sh trap cleanup EXIT trap cleanup SIGINT @@ -39,9 +39,10 @@ echo "## Running script verification of functionalities ##" echo > ./funl-test-result.log echo > ./funl-test-debug.log test_num=0 -for test in $(ls -I "common.sh" -I "verify_custom_notifications.sh" test/script/); do +for test in `cat test/script/test_seq.txt`; do test_num=$(( test_num + 1 )) - if ./test/script/"${test}"; then + ./test/script/${test} + if [ "$?" -eq 0 ]; then echo "ok ${test_num} - ${test}" >> ./funl-test-result.log else echo "not ok ${test_num} - ${test}" >> ./funl-test-result.log @@ -49,19 +50,17 @@ for test in $(ls -I "common.sh" -I "verify_custom_notifications.sh" test/script/ done echo "Stop all services" -supervisorctl stop icwmpd +supervisorctl stop all -cp test/files/etc/config/users /etc/config/ -cp test/files/etc/config/wireless /etc/config/ - -echo "Verify Custom notifications" -if ./test/script/verify_custom_notifications.sh; then - echo "ok - verify_custom_notifications" >> ./funl-test-result.log -else - echo "not ok - verify_custom_notifications" >> ./funl-test-result.log -fi - -test_num=$(( test_num + 1 )) +#echo "Verify Custom notifications" +#./test/script/verify_custom_notifications.sh +#if [ "$?" -eq 0 ]; then +# echo "ok - verify_custom_notifications" >> ./funl-test-result.log +#else +# echo "not ok - verify_custom_notifications" >> ./funl-test-result.log +#fi +# +#test_num=$(( test_num + 1 )) echo "1..${test_num}" >> ./funl-test-result.log # Artefact diff --git a/gitlab-ci/install-dependencies.sh b/gitlab-ci/install-dependencies.sh index c2e52f9..f9b2bd9 100755 --- a/gitlab-ci/install-dependencies.sh +++ b/gitlab-ci/install-dependencies.sh @@ -3,7 +3,7 @@ echo "install dependencies for unit-test script" pwd -. ./gitlab-ci/shared.sh +source ./gitlab-ci/shared.sh # install required packages exec_cmd apt update diff --git a/gitlab-ci/shared.sh b/gitlab-ci/shared.sh index cf34d05..fc6fd6e 100644 --- a/gitlab-ci/shared.sh +++ b/gitlab-ci/shared.sh @@ -38,7 +38,7 @@ function exec_cmd() function configure_genieacs() { - sleep 10 + sleep 3 echo "create a new user" curl -X POST 'http://localhost:3000/init' -H "Content-Type: application/json" --data '{"users": true, "presets": true, "filters": true, "device": true, "index": true, "overview": true}' >/dev/null 2>&1 check_ret $? @@ -76,7 +76,7 @@ function configure_download_firmware() function configure_acs_url() { - url="http://$(hostname -i):7547" + url="http://127.0.0.1:7547" uci set cwmp.acs.url=$url uci commit cwmp echo "Current ACS URL=$url" @@ -85,7 +85,7 @@ function configure_acs_url() function check_cwmp_status() { status=`ubus call tr069 status | jq -r ".cwmp.status"` - if [ $status != "up" ]; then + if [ "${status}" != "up" ]; then echo "icwmpd is not started correctly, (the current status=$status)" exit 1 fi @@ -101,7 +101,7 @@ function clean_icwmp() find -name '*.gcov' -exec rm {} -fv \; find -name '*.deps' -exec rm {} -rfv \; find -name '*.so' -exec rm {} -fv \; - rm -f *.o *.log *.xml vgcore.* firmware_v1.0.bin + rm -f *.o *.log *.xml firmware_v1.0.bin rm -rf report fi } @@ -114,9 +114,13 @@ function build_icwmp() # clean icwmp clean_icwmp + mkdir -p /var/state + mkdir -p /var/run + mkdir -p /var/run/icwmpd + # compile icwmp autoreconf -i >/dev/null 2>&1 - ./configure CFLAGS="$COV_CFLAGS -DWC_NO_HARDEN" LDFLAGS="$COV_LDFLAGS" --enable-acs=multi --enable-debug --enable-libopenssl >/dev/null 2>&1 + ./configure CFLAGS="$COV_CFLAGS -DWC_NO_HARDEN" LDFLAGS="$COV_LDFLAGS" --enable-acs=multi --enable-debug >/dev/null 2>&1 make CFLAGS="$COV_CFLAGS -DWC_NO_HARDEN" LDFLAGS="$COV_LDFLAGS" check_ret $? } diff --git a/gitlab-ci/unit-test.sh b/gitlab-ci/unit-test.sh index 084a4b0..e059322 100755 --- a/gitlab-ci/unit-test.sh +++ b/gitlab-ci/unit-test.sh @@ -2,7 +2,7 @@ echo "preparation script" pwd -. ./gitlab-ci/shared.sh +source ./gitlab-ci/shared.sh trap cleanup EXIT trap cleanup SIGINT diff --git a/http.c b/http.c index bc5e32c..1d99eac 100644 --- a/http.c +++ b/http.c @@ -10,18 +10,26 @@ * Author Omar Kallel * Copyright (C) 2011-2012 Luka Perkov */ -#include -#include -#include -#include -#include "http.h" -#include "cwmp_uci.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "log.h" -#include "event.h" -#include "ubus.h" #include "config.h" +#include "event.h" +#include "http.h" #include "digestauth.h" +#include "cwmp_uci.h" +#include "ubus.h" +#include "session.h" #define REALM "authenticate@cwmp" #define OPAQUE "11733b200778ce33060f31c9af70a870ba96ddd4" @@ -38,14 +46,14 @@ void http_set_timeout(void) curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1); } -int http_client_init(struct cwmp *cwmp) +int http_client_init() { char *dhcp_dis = NULL; char *acs_var_stat = NULL; uci_get_value(UCI_DHCP_DISCOVERY_PATH, &dhcp_dis); - if (dhcp_dis && cwmp->retry_count_session > 0 && strcmp(dhcp_dis, "enable") == 0) { + if (dhcp_dis && cwmp_main->retry_count_session > 0 && strcmp(dhcp_dis, "enable") == 0) { uci_get_state_value(UCI_DHCP_ACS_URL, &acs_var_stat); if (acs_var_stat) { if (icwmp_asprintf(&http_c.url, "%s", acs_var_stat) == -1) { @@ -54,13 +62,13 @@ int http_client_init(struct cwmp *cwmp) return -1; } } else { - if (icwmp_asprintf(&http_c.url, "%s", cwmp->conf.acsurl) == -1) { + if (icwmp_asprintf(&http_c.url, "%s", cwmp_main->conf.acsurl) == -1) { FREE(dhcp_dis); return -1; } } } else { - if (icwmp_asprintf(&http_c.url, "%s", cwmp->conf.acsurl) == -1) { + if (icwmp_asprintf(&http_c.url, "%s", cwmp_main->conf.acsurl) == -1) { FREE(dhcp_dis); return -1; } @@ -78,7 +86,7 @@ int http_client_init(struct cwmp *cwmp) if (!curl) return -1; - if (cwmp->conf.ipv6_enable) { + if (cwmp_main->conf.ipv6_enable) { unsigned char buf[sizeof(struct in6_addr)]; char *ip = NULL; @@ -130,7 +138,7 @@ static size_t http_get_response(void *buffer, size_t size, size_t rxed, char **m return size * rxed; } -int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **msg_in) +int http_send_message(char *msg_out, int msg_out_len, char **msg_in) { unsigned char buf[sizeof(struct in6_addr)]; int tmp = 0; @@ -152,21 +160,21 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char ** if (!http_c.header_list) return -1; #endif /* ACS_FUSION */ - if (cwmp->conf.http_disable_100continue) { + if (cwmp_main->conf.http_disable_100continue) { http_c.header_list = curl_slist_append(http_c.header_list, "Expect:"); if (!http_c.header_list) return -1; } curl_easy_setopt(curl, CURLOPT_URL, http_c.url); - curl_easy_setopt(curl, CURLOPT_USERNAME, cwmp->conf.acs_userid); - curl_easy_setopt(curl, CURLOPT_PASSWORD, cwmp->conf.acs_passwd); + curl_easy_setopt(curl, CURLOPT_USERNAME, cwmp_main->conf.acs_userid); + curl_easy_setopt(curl, CURLOPT_PASSWORD, cwmp_main->conf.acs_passwd); curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC | CURLAUTH_DIGEST); curl_easy_setopt(curl, CURLOPT_TIMEOUT, HTTP_TIMEOUT); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, HTTP_TIMEOUT); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL); curl_easy_setopt(curl, CURLOPT_NOBODY, 0); - switch (cwmp->conf.compression) { + switch (cwmp_main->conf.compression) { case COMP_NONE: break; case COMP_GZIP: @@ -196,14 +204,14 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char ** curl_easy_setopt(curl, CURLOPT_COOKIEFILE, fc_cookies); curl_easy_setopt(curl, CURLOPT_COOKIEJAR, fc_cookies); - if (cwmp->conf.acs_ssl_capath) - curl_easy_setopt(curl, CURLOPT_CAPATH, cwmp->conf.acs_ssl_capath); - if (cwmp->conf.insecure_enable) { + if (cwmp_main->conf.acs_ssl_capath) + curl_easy_setopt(curl, CURLOPT_CAPATH, cwmp_main->conf.acs_ssl_capath); + if (cwmp_main->conf.insecure_enable) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); } - curl_easy_setopt(curl, CURLOPT_INTERFACE, cwmp->conf.interface); + curl_easy_setopt(curl, CURLOPT_INTERFACE, cwmp_main->conf.interface); *msg_in = (char *)calloc(1, sizeof(char)); res = curl_easy_perform(curl); @@ -246,7 +254,7 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char ** } if (http_code == 415) { - cwmp->conf.compression = COMP_NONE; + cwmp_main->conf.compression = COMP_NONE; goto error; } if (http_code != 200 && http_code != 204) @@ -276,35 +284,34 @@ error: void http_success_cr(void) { CWMP_LOG(INFO, "Connection Request thread: add connection request event in the queue"); - pthread_mutex_lock(&(cwmp_main.mutex_session_queue)); - cwmp_add_event_container(&cwmp_main, EVENT_IDX_6CONNECTION_REQUEST, ""); - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); - pthread_cond_signal(&(cwmp_main.threshold_session_send)); + pthread_mutex_lock(&start_session_mutext); + cwmp_ubus_call("tr069", "inform", CWMP_UBUS_ARGS{ {} }, 0, NULL, NULL); + pthread_mutex_unlock(&start_session_mutext); } static void http_cr_new_client(int client, bool service_available) { FILE *fp; char buffer[BUFSIZ]; - char auth_digest_buffer[BUFSIZ]; + char auth_digest_buffer[BUFSIZ] = {0}; int8_t auth_status = 0; bool auth_digest_checked = false; bool method_is_get = false; bool internal_error = false; char cr_http_get_head[512]; - pthread_mutex_lock(&mutex_config_load); fp = fdopen(client, "r+"); - char *username = cwmp_main.conf.cpe_userid; - char *password = cwmp_main.conf.cpe_passwd; + char *username = cwmp_main->conf.cpe_userid; + char *password = cwmp_main->conf.cpe_passwd; if (!username || !password) { // if we dont have username or password configured proceed with connecting to ACS service_available = false; goto http_end; } - snprintf(cr_http_get_head, sizeof(cr_http_get_head), "GET %s HTTP/1.1", cwmp_main.conf.connection_request_path); + snprintf(cr_http_get_head, sizeof(cr_http_get_head), "GET %s HTTP/1.1", cwmp_main->conf.connection_request_path); + pthread_mutex_unlock(&mutex_config_load); while (fgets(buffer, sizeof(buffer), fp)) { if (!strncasecmp(buffer, cr_http_get_head, strlen(cr_http_get_head))) method_is_get = true; @@ -341,24 +348,28 @@ http_end: fputs("HTTP/1.1 200 OK\r\n", fp); fputs("Connection: close\r\n", fp); fputs("Content-Length: 0\r\n", fp); + fputs("\r\n", fp); + fclose(fp); + close(client); http_success_cr(); } else if (internal_error) { CWMP_LOG(INFO, "Receive Connection Request: Return 500 Internal Error"); fputs("HTTP/1.1 500 Internal Server Error\r\n", fp); fputs("Connection: close\r\n", fp); fputs("Content-Length: 0\r\n", fp); - } - else { + fputs("\r\n", fp); + fclose(fp); + close(client); + } else { CWMP_LOG(INFO, "Receive Connection Request: Return 401 Unauthorized"); fputs("HTTP/1.1 401 Unauthorized\r\n", fp); fputs("Connection: close\r\n", fp); http_digest_auth_fail_response(fp, "GET", "/", REALM, OPAQUE); fputs("\r\n", fp); + fputs("\r\n", fp); + fclose(fp); + close(client); } - fputs("\r\n", fp); - - fclose(fp); - pthread_mutex_unlock(&mutex_config_load); } void http_server_init(void) @@ -367,20 +378,20 @@ void http_server_init(void) unsigned short cr_port; for (;;) { - cr_port = (unsigned short)(cwmp_main.conf.connection_request_port); + cr_port = (unsigned short)(cwmp_main->conf.connection_request_port); unsigned short i = (DEFAULT_CONNECTION_REQUEST_PORT == cr_port) ? 1 : 0; //Create socket - cwmp_main.cr_socket_desc = socket(AF_INET6, SOCK_STREAM, 0); - if (cwmp_main.cr_socket_desc == -1) { + cwmp_main->cr_socket_desc = socket(AF_INET6, SOCK_STREAM, 0); + if (cwmp_main->cr_socket_desc == -1) { CWMP_LOG(ERROR, "Could not open server socket for Connection Requests, Error no is : %d, Error description is : %s", errno, strerror(errno)); sleep(1); continue; } - fcntl(cwmp_main.cr_socket_desc, F_SETFD, fcntl(cwmp_main.cr_socket_desc, F_GETFD) | FD_CLOEXEC); + fcntl(cwmp_main->cr_socket_desc, F_SETFD, fcntl(cwmp_main->cr_socket_desc, F_GETFD) | FD_CLOEXEC); int reusaddr = 1; - if (setsockopt(cwmp_main.cr_socket_desc, SOL_SOCKET, SO_REUSEADDR, &reusaddr, sizeof(int)) < 0) { + if (setsockopt(cwmp_main->cr_socket_desc, SOL_SOCKET, SO_REUSEADDR, &reusaddr, sizeof(int)) < 0) { CWMP_LOG(WARNING, "setsockopt(SO_REUSEADDR) failed"); } @@ -391,7 +402,7 @@ void http_server_init(void) for (;; i++) { server.sin6_port = htons(cr_port); //Bind - if (bind(cwmp_main.cr_socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) { + if (bind(cwmp_main->cr_socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) { //print the error message CWMP_LOG(ERROR, "Could not bind server socket on the port %d, Error no is : %d, Error description is : %s", cr_port, errno, strerror(errno)); cr_port = DEFAULT_CONNECTION_REQUEST_PORT + i; @@ -405,9 +416,11 @@ void http_server_init(void) char cr_port_str[6]; snprintf(cr_port_str, 6, "%hu", cr_port); cr_port_str[5] = '\0'; + cwmp_uci_init(); cwmp_uci_set_value("cwmp", "cpe", "port", cr_port_str); cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); - connection_request_port_value_change(&cwmp_main, cr_port); + connection_request_port_value_change(cr_port); + cwmp_uci_exit(); CWMP_LOG(INFO, "Connection Request server initiated with the port: %d", cr_port); } @@ -419,15 +432,15 @@ void http_server_listen(void) struct sockaddr_in6 client; //Listen - listen(cwmp_main.cr_socket_desc, 3); + listen(cwmp_main->cr_socket_desc, 3); //Accept and incoming connection c = sizeof(struct sockaddr_in); - while ((client_sock = accept(cwmp_main.cr_socket_desc, (struct sockaddr *)&client, (socklen_t *)&c))) { + while ((client_sock = accept(cwmp_main->cr_socket_desc, (struct sockaddr *)&client, (socklen_t *)&c))) { bool service_available; time_t current_time; - - if (thread_end) + + if (cwmp_stop) return; current_time = time(NULL); @@ -443,7 +456,6 @@ void http_server_listen(void) } } http_cr_new_client(client_sock, service_available); - close(client_sock); } if (client_sock < 0) { diff --git a/inc/backupSession.h b/inc/backupSession.h index 82c2661..1122580 100644 --- a/inc/backupSession.h +++ b/inc/backupSession.h @@ -38,9 +38,9 @@ struct search_keywords { extern pthread_mutex_t mutex_backup_session; -int cwmp_init_backup_session(struct cwmp *cwmp, char **ret, enum backup_loading load); +int cwmp_init_backup_session(char **ret, enum backup_loading load); void bkp_session_save(); -int cwmp_load_saved_session(struct cwmp *cwmp, char **acsurl, enum backup_loading load); +int cwmp_load_saved_session(char **acsurl, enum backup_loading load); mxml_node_t *bkp_session_insert_event(int index, char *command_key, int id, char *status); void bkp_session_delete_event(int id, char *status); void bkp_session_simple_insert_in_parent(char *parent, char *child, char *value); @@ -58,7 +58,7 @@ void bkp_session_insert_change_du_state(struct change_du_state *pchange_du_state void bkp_session_delete_change_du_state(struct change_du_state *pchange_du_state); void bkp_session_insert_transfer_complete(struct transfer_complete *ptransfer_complete); void bkp_session_delete_transfer_complete(struct transfer_complete *ptransfer_complete); -int save_acs_bkp_config(struct cwmp *cwmp); +int save_acs_bkp_config(); void bkp_session_insert_schedule_download(struct download *pschedule_download); void bkp_session_insert_apply_schedule_download(struct apply_schedule_download *papply_schedule_download); diff --git a/inc/common.h b/inc/common.h index f64434d..bb4e69d 100644 --- a/inc/common.h +++ b/inc/common.h @@ -11,11 +11,17 @@ #ifndef __CCOMMON_H #define __CCOMMON_H -#include #include -#include +#include +#include +#include +#include +#include #include +#include #include +#include +#include #ifndef CWMP_VERSION #define CWMP_VERSION "3.0.0" @@ -48,12 +54,15 @@ #define MAX_NBRE_SERVICES 256 #define FIREWALL_CWMP "/etc/firewall.cwmp" #define CWMP_VARSTATE_UCI_PACKAGE "/var/state/cwmp" - #define STRCMP(S1, S2) ((S1 != NULL && S2 != NULL) ? strcmp(S1, S2) : -1) + extern char *commandKey; -extern bool thread_end; -extern bool signal_exit; +extern bool cwmp_stop; extern bool ubus_exit; +extern struct uloop_timeout session_timer; +extern struct uloop_timeout priodic_session_timer; +extern struct uloop_timeout retry_session_timer; +extern bool g_firewall_restart; typedef struct env { unsigned short boot; @@ -109,45 +118,25 @@ struct deviceid { char *softwareversion; }; -typedef struct session_status { - time_t last_start_time; - time_t last_end_time; - int last_status; - time_t next_periodic; - time_t next_retry; - unsigned int success_session; - unsigned int failure_session; -} session_status; - typedef struct cwmp { struct env env; struct config conf; struct deviceid deviceid; - struct list_head head_session_queue; - pthread_mutex_t mutex_session_queue; - struct session *session_send; + struct session *session; bool cwmp_cr_event; - pthread_mutex_t mutex_session_send; - pthread_cond_t threshold_session_send; - pthread_mutex_t mutex_periodic; - pthread_mutex_t mutex_notify_periodic; - pthread_cond_t threshold_periodic; - pthread_cond_t threshold_notify_periodic; - pthread_cond_t threshold_handle_notify; int count_handle_notify; int retry_count_session; - struct list_head *head_event_container; FILE *pid_file; time_t start_time; - struct session_status session_status; unsigned int cwmp_id; - int event_id; int cr_socket_desc; + int event_id; int cwmp_period; time_t cwmp_periodic_time; bool cwmp_periodic_enable; bool is_boot; bool custom_notify_active; + bool start_diagnostics; } cwmp; enum action { @@ -157,6 +146,11 @@ enum action { RESTART, }; +enum auth_type_enum { + AUTH_BASIC, + AUTH_DIGEST +}; + enum cwmp_start { CWMP_START_BOOT = 1, CWMP_START_PERIODIC = 2 }; enum cwmp_ret_err { @@ -321,15 +315,15 @@ enum client_server_faults { FAULT_CPE_TYPE_CLIENT, FAULT_CPE_TYPE_SERVER }; struct rpc_cpe_method { const char *name; - int (*handler)(struct session *session, struct rpc *rpc); + int (*handler)(struct rpc *rpc); int amd; }; struct rpc_acs_method { const char *name; - int (*prepare_message)(struct cwmp *cwmp, struct session *session, struct rpc *rpc); - int (*parse_response)(struct cwmp *cwmp, struct session *session, struct rpc *rpc); - int (*extra_clean)(struct session *session, struct rpc *rpc); + int (*prepare_message)(struct rpc *rpc); + int (*parse_response)(struct rpc *rpc); + int (*extra_clean)(struct rpc *rpc); }; typedef struct FAULT_CPE { @@ -355,6 +349,7 @@ typedef struct timewindow { typedef struct download { struct list_head list; + struct uloop_timeout handler_timer ; time_t scheduled_time; int file_size; char *command_key; @@ -399,6 +394,7 @@ typedef struct operations { typedef struct upload { struct list_head list; + struct uloop_timeout handler_timer ; time_t scheduled_time; char *command_key; char *file_type; @@ -441,7 +437,7 @@ typedef struct opfault { char *fault_string; } opfault; -extern struct cwmp cwmp_main; +extern struct cwmp *cwmp_main; extern long int flashsize; extern struct FAULT_CPE FAULT_CPE_ARRAY[]; extern struct cwmp_namespaces ns; @@ -483,11 +479,15 @@ bool icwmp_validate_string_length(char *arg, int max_length); bool icwmp_validate_boolean_value(char *arg); bool icwmp_validate_unsignedint(char *arg); bool icwmp_validate_int_in_range(char *arg, int min, int max); -void load_forced_inform_json_file(struct cwmp *cwmp); +void load_forced_inform_json_file(); void clean_custom_inform_parameters(); char *string_to_hex(const unsigned char *str, size_t size); int copy_file(char *source_file, char *target_file); -int get_connection_interface(); +int cwmp_get_session_retry_interval(); +int cwmp_apply_acs_changes(); +void check_firewall_restart_state(); +void cwmp_end_handler(int signal_num __attribute__((unused))); + #ifndef FREE #define FREE(x) \ do { \ diff --git a/inc/config.h b/inc/config.h index 034e537..2be36c1 100755 --- a/inc/config.h +++ b/inc/config.h @@ -13,13 +13,14 @@ #ifndef _CONFIG_H__ #define _CONFIG_H__ -#include "cwmp_uci.h" +#include +#include "common.h" extern pthread_mutex_t mutex_config_load; -int global_conf_init(struct cwmp *cwmp); -int get_global_config(struct config *conf); -int cwmp_get_deviceid(struct cwmp *cwmp); -int cwmp_config_reload(struct cwmp *cwmp); +int global_conf_init(); +int get_global_config(); +int cwmp_config_reload(); int reload_networking_config(); + #endif diff --git a/inc/cwmp_cli.h b/inc/cwmp_cli.h index d6fde40..556abd8 100644 --- a/inc/cwmp_cli.h +++ b/inc/cwmp_cli.h @@ -11,6 +11,7 @@ struct cmd_input { char *second_input; }; + char *cmd_get_exec_func(struct cmd_input in, union cmd_result *res); char *cmd_set_exec_func(struct cmd_input in, union cmd_result *res __attribute__((unused))); char *cmd_add_exec_func(struct cmd_input in, union cmd_result *res); diff --git a/inc/cwmp_config.h b/inc/cwmp_config.h new file mode 100644 index 0000000..e730c3f --- /dev/null +++ b/inc/cwmp_config.h @@ -0,0 +1,6 @@ +#ifndef CWMP_CONF_H +#define CWMP_CONF_H + +int cwmp_get_deviceid(); + +#endif diff --git a/inc/cwmp_du_state.h b/inc/cwmp_du_state.h index 66526f0..018ee3a 100644 --- a/inc/cwmp_du_state.h +++ b/inc/cwmp_du_state.h @@ -11,8 +11,6 @@ #ifndef CWMP_DU_STATE_H #define CWMP_DU_STATE_H -#include "common.h" - extern struct list_head list_change_du_state; extern pthread_mutex_t mutex_change_du_state; extern pthread_cond_t threshold_change_du_state; @@ -20,7 +18,7 @@ extern pthread_cond_t threshold_change_du_state; int cwmp_du_install(char *url, char *uuid, char *user, char *pass, char *env, char **package_version, char **package_name, char **package_uuid, char **package_env, char **fault_code); int cwmp_du_update(char *url, char *uuid, char *user, char *pass, char **package_version, char **package_name, char **package_uuid, char **package_env, char **fault_code); int cwmp_du_uninstall(char *package_name, char *package_env, char **fault_code); -int cwmp_rpc_acs_destroy_data_du_state_change_complete(struct session *session, struct rpc *rpc); +int cwmp_rpc_acs_destroy_data_du_state_change_complete(struct rpc *rpc); void *thread_cwmp_rpc_cpe_change_du_state(void *v); int cwmp_free_change_du_state_request(struct change_du_state *change_du_state); #endif diff --git a/inc/cwmp_event.h b/inc/cwmp_event.h new file mode 100644 index 0000000..b4cc8d8 --- /dev/null +++ b/inc/cwmp_event.h @@ -0,0 +1,5 @@ +#ifndef CWMP_EVENT_H +#define CWMP_EVENT_H +#include "event.h" +struct event_container *cwmp_add_event_container(int event_code, char *command_key); +#endif diff --git a/inc/cwmp_http.h b/inc/cwmp_http.h new file mode 100644 index 0000000..df75df7 --- /dev/null +++ b/inc/cwmp_http.h @@ -0,0 +1,7 @@ +#ifndef CWMP_HTTP_H +#define CWMP_HTTP_H +#include "http.h" +extern pthread_t http_cr_server_thread; + +void http_server_start(void); +#endif diff --git a/inc/cwmp_uci.h b/inc/cwmp_uci.h index 358b2fd..c7b423b 100644 --- a/inc/cwmp_uci.h +++ b/inc/cwmp_uci.h @@ -14,8 +14,6 @@ #include -#include "common.h" - //struct uci_context *cwmp_uci_ctx = ((void *)0); #define UCI_DHCP_DISCOVERY_PATH "cwmp.acs.dhcp_discovery" #define UCI_ACS_URL_PATH "cwmp.acs.url" diff --git a/inc/datamodel_interface.h b/inc/datamodel_interface.h index 6d76b6e..417f589 100644 --- a/inc/datamodel_interface.h +++ b/inc/datamodel_interface.h @@ -1,6 +1,5 @@ #ifndef SRC_DATAMODELIFACE_H_ #define SRC_DATAMODELIFACE_H_ - #include "common.h" #define DM_ROOT_OBJ "Device." diff --git a/inc/download.h b/inc/download.h index 241b66e..483c77e 100644 --- a/inc/download.h +++ b/inc/download.h @@ -1,8 +1,6 @@ #ifndef CWMP_DOWNLOAD_H #define CWMP_DOWNLOAD_H -#include "common.h" - #define DOWNLOAD_PROTOCOL_HTTP "http://" #define DOWNLOAD_PROTOCOL_HTTPS "https://" #define DOWNLOAD_PROTOCOL_FTP "ftp://" @@ -22,14 +20,8 @@ extern struct list_head list_download; extern struct list_head list_schedule_download; -extern struct list_head list_apply_schedule_download; extern pthread_mutex_t mutex_download; -extern pthread_cond_t threshold_download; -extern pthread_mutex_t mutex_schedule_download; -extern pthread_cond_t threshold_schedule_download; -extern pthread_mutex_t mutex_apply_schedule_download; -extern pthread_cond_t threshold_apply_schedule_download; extern int count_download_queue; @@ -39,9 +31,10 @@ int cwmp_free_apply_schedule_download_request(struct apply_schedule_download *ap int cwmp_scheduledDownload_remove_all(); int cwmp_scheduled_Download_remove_all(); int cwmp_apply_scheduled_Download_remove_all(); -int cwmp_rpc_acs_destroy_data_transfer_complete(struct session *session, struct rpc *rpc); -void *thread_cwmp_rpc_cpe_download(void *v); +int cwmp_rpc_acs_destroy_data_transfer_complete(struct rpc *rpc); void *thread_cwmp_rpc_cpe_schedule_download(void *v); void *thread_cwmp_rpc_cpe_apply_schedule_download(void *v); int cwmp_launch_download(struct download *pdownload, char *download_file_name, enum load_type ltype, struct transfer_complete **ptransfer_complete); +void cwmp_start_download(struct uloop_timeout *timeout); +void cwmp_start_schedule_download(struct uloop_timeout *timeout); #endif diff --git a/inc/event.h b/inc/event.h index 3e90f36..bf81766 100644 --- a/inc/event.h +++ b/inc/event.h @@ -11,9 +11,8 @@ #ifndef EVENT_H_ #define EVENT_H_ - #include "common.h" -#include "session.h" +#include "event.h" typedef struct event_container { struct list_head list; @@ -67,18 +66,17 @@ enum event_idx_enum }; extern const struct EVENT_CONST_STRUCT EVENT_CONST[__EVENT_IDX_MAX]; +extern pthread_mutex_t add_event_mutext; -struct event_container *cwmp_add_event_container(struct cwmp *cwmp, int event_idx, char *command_key); -int event_remove_all_event_container(struct session *session, int rem_from); -int event_remove_noretry_event_container(struct session *session, struct cwmp *cwmp); +int event_remove_all_event_container(int rem_from); +int event_remove_noretry_event_container(); void cwmp_save_event_container(struct event_container *event_container); -void *thread_event_periodic(void *v); -void connection_request_ip_value_change(struct cwmp *cwmp, int version); -void connection_request_port_value_change(struct cwmp *cwmp, int port); +void connection_request_ip_value_change(int version); +void connection_request_port_value_change(int port); int cwmp_get_int_event_code(const char *code); -bool event_exist_in_list(struct cwmp *cwmp, int event); -int cwmp_root_cause_events(struct cwmp *cwmp); -int cwmp_root_cause_transfer_complete(struct cwmp *cwmp, struct transfer_complete *p); -int cwmp_root_cause_changedustate_complete(struct cwmp *cwmp, struct du_state_change_complete *p); -void cwmp_root_cause_event_ipdiagnostic(void); +bool event_exist_in_list(int event); +int cwmp_root_cause_events(); +int cwmp_root_cause_transfer_complete(struct transfer_complete *p); +int cwmp_root_cause_changedustate_complete(struct du_state_change_complete *p); +void cwmp_root_cause_event_diagnostic(void); #endif /* SRC_INC_EVENT_H_ */ diff --git a/inc/http.h b/inc/http.h index 3b79a31..93fe576 100644 --- a/inc/http.h +++ b/inc/http.h @@ -11,7 +11,6 @@ #define _FREECWMP_HTTP_H__ #include "common.h" - extern char *fc_cookies; #define HTTP_TIMEOUT 30 @@ -23,12 +22,12 @@ struct http_client { void http_set_timeout(void); -int http_client_init(struct cwmp *cwmp); +int http_client_init(); void http_client_exit(void); -int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **msg_in); +int http_send_message(char *msg_out, int msg_out_len, char **msg_in); +int http_cr_server_init(void); +void http_success_cr(void); void http_server_init(void); void http_server_listen(void); -void http_success_cr(void); - #endif diff --git a/inc/md5.h b/inc/md5.h index b3670fe..a0132bd 100644 --- a/inc/md5.h +++ b/inc/md5.h @@ -18,12 +18,15 @@ #ifndef MD5_H #define MD5_H +#include +#include +#include +#include + #ifdef WORDS_BIGENDIAN #define HIGHFIRST #endif -#include - #define MD5_DIGEST_SIZE 16 struct MD5Context { diff --git a/inc/netlink.h b/inc/netlink.h index 1aaddaf..3b4b0a2 100755 --- a/inc/netlink.h +++ b/inc/netlink.h @@ -15,5 +15,6 @@ int netlink_init(void); int netlink_init_v6(void); +void cwmp_netlink_init(void); #endif diff --git a/inc/notifications.h b/inc/notifications.h index a07cb7e..fb2d815 100644 --- a/inc/notifications.h +++ b/inc/notifications.h @@ -11,12 +11,15 @@ #ifndef NOTIFICATIONS_H_ #define NOTIFICATIONS_H_ - +#include #include #include #include #include "common.h" +#include "event.h" +#include "datamodel_interface.h" +#include "soap.h" enum NOTIFICATION_STATUS { @@ -32,6 +35,7 @@ extern struct list_head list_lw_value_change; extern struct list_head list_value_change; extern pthread_mutex_t mutex_value_change; extern struct list_head list_param_obj_notify; +extern struct uloop_timeout check_notify_timer; /*#define foreach_parameter_notification(function, parameter, notification) \ #ifndef NOTIF_VARIABLES_##function \ @@ -52,18 +56,21 @@ void cwmp_update_enabled_notify_file(void); int check_value_change(void); void create_list_param_obj_notify(); void create_list_param_leaf_notify(); -void sotfware_version_value_change(struct cwmp *cwmp, struct transfer_complete *p); +void sotfware_version_value_change(struct transfer_complete *p); void *thread_periodic_check_notify(void *v); void send_active_value_change(void); void add_list_value_change(char *param_name, char *param_data, char *param_type); void clean_list_value_change(); char *cwmp_set_parameter_attributes(char *parameter_name, int notification); char *cwmp_get_parameter_attributes(char *parameter_name, struct list_head *parameters_list); -void load_custom_notify_json(struct cwmp *cwmp); +void load_custom_notify_json(); void add_lw_list_value_change(char *param_name, char *param_data, char *param_type); char *calculate_lwnotification_cnonce(); void cwmp_lwnotification(); void clean_list_param_notify(); void init_list_param_notify(); void reinit_list_param_notify(); +void cwmp_prepare_value_change(); +void periodic_check_notifiy(struct uloop_timeout *timeout __attribute__((unused))); +void trigger_periodic_notify_check(); #endif /* SRC_INC_NOTIFICATIONS_H_ */ diff --git a/inc/reboot.h b/inc/reboot.h index 276eacf..fc33241 100644 --- a/inc/reboot.h +++ b/inc/reboot.h @@ -13,7 +13,7 @@ #include "common.h" -void launch_reboot_methods(struct cwmp *cwmp); +void launch_reboot_methods(); #endif //_REBOOT_H__ diff --git a/inc/rpc_soap.h b/inc/rpc_soap.h deleted file mode 100644 index b7a66ae..0000000 --- a/inc/rpc_soap.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Copyright (C) 2013-2019 iopsys Software Solutions AB - * Author Mohamed Kallel - * Author Ahmed Zribi - * Copyright (C) 2011 Luka Perkov - * - */ - -#ifndef __RPC__SOAP__H_ -#define __RPC__SOAP__H_ - -#include "common.h" -#include "session.h" - -#define MAX_NBRE_CUSTOM_INFORM 256 -extern char *custom_forced_inform_parameters[MAX_NBRE_CUSTOM_INFORM]; -extern char *boot_inform_parameters[MAX_NBRE_CUSTOM_INFORM]; -extern int nbre_custom_inform; -extern int nbre_boot_inform; -extern const struct rpc_cpe_method rpc_cpe_methods[__RPC_CPE_MAX]; -extern const struct rpc_acs_method rpc_acs_methods[__RPC_ACS_MAX]; - -int cwmp_handle_rpc_cpe_get_rpc_methods(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_set_parameter_attributes(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_add_object(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_delete_object(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_reboot(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_factory_reset(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct session *session, struct rpc *rpc); -int cancel_transfer(char *key); -int cwmp_handle_rpc_cpe_cancel_transfer(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_schedule_inform(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_change_du_state(struct session *session, struct rpc *rpc); -int cwmp_handle_rpc_cpe_fault(struct session *session, struct rpc *rpc); - -int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *session, struct rpc *rpc); -int cwmp_rpc_acs_parse_response_inform(struct cwmp *cwmp, struct session *session, struct rpc *rpc); -int cwmp_rpc_acs_prepare_get_rpc_methods(struct cwmp *cwmp, struct session *session, struct rpc *rpc); -int cwmp_rpc_acs_prepare_transfer_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc); -int cwmp_rpc_acs_prepare_du_state_change_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc); -int cwmp_rpc_acs_destroy_data_inform(struct session *session, struct rpc *rpc); - -int xml_handle_message(struct session *session); -int cwmp_create_fault_message(struct session *session, struct rpc *rpc_cpe, int fault_code); - -#endif diff --git a/inc/sched_inform.h b/inc/sched_inform.h index dad0c0e..269448e 100644 --- a/inc/sched_inform.h +++ b/inc/sched_inform.h @@ -11,8 +11,6 @@ #ifndef CWMP_SCHED_INFORM_H #define CWMP_SCHED_INFORM_H -#include "common.h" - extern struct list_head list_schedule_inform; extern pthread_mutex_t mutex_schedule_inform; extern pthread_cond_t threshold_schedule_inform; diff --git a/inc/session.h b/inc/session.h index 6ef2743..f3e7803 100644 --- a/inc/session.h +++ b/inc/session.h @@ -15,11 +15,24 @@ #include #include "common.h" +extern struct uloop_timeout retry_session_timer; +extern pthread_mutex_t start_session_mutext; + +typedef struct session_status { + time_t last_start_time; + time_t last_end_time; + int last_status; + time_t next_periodic; + time_t next_retry; + unsigned int success_session; + unsigned int failure_session; +} session_status; + typedef struct session { - struct list_head list; - struct list_head head_event_container; struct list_head head_rpc_cpe; struct list_head head_rpc_acs; + struct list_head events; + struct session_status session_status; mxml_node_t *tree_in; mxml_node_t *tree_out; mxml_node_t *body_in; @@ -45,7 +58,10 @@ enum end_session_enum END_SESSION_SERVERSELECTION_DIAGNOSTIC = 1 << 11, END_SESSION_SET_NOTIFICATION_UPDATE = 1 << 12, END_SESSION_RESTART_SERVICES = 1 << 13, - END_SESSION_INIT_NOTIFY = 1 << 14 + END_SESSION_INIT_NOTIFY = 1 << 14, + END_SESSION_DOWNLOAD = 1 << 15, + END_SESSION_SCHEDULE_DOWNLOAD = 1 << 16, + END_SESSION_UPLOAD = 1 << 17 }; enum enum_session_status @@ -59,13 +75,19 @@ enum enum_session_status extern unsigned int end_session_flag; void cwmp_set_end_session(unsigned int flag); -struct rpc *cwmp_add_session_rpc_cpe(struct session *session, int type); -struct session *cwmp_add_queue_session(struct cwmp *cwmp); -struct rpc *cwmp_add_session_rpc_acs(struct session *session, int type); -int cwmp_apply_acs_changes(); -int cwmp_move_session_to_session_send(struct cwmp *cwmp, struct session *session); -struct rpc *cwmp_add_session_rpc_acs_head(struct session *session, int type); +struct rpc *cwmp_add_session_rpc_cpe(int type); +struct rpc *cwmp_add_session_rpc_acs(int type); +struct rpc *cwmp_add_session_rpc_acs_head(int type); int cwmp_session_rpc_destructor(struct rpc *rpc); -int cwmp_session_destructor(struct session *session); -int cwmp_move_session_to_session_queue(struct cwmp *cwmp, struct session *session); +void trigger_cwmp_session_timer(); +void trigger_session_by_ubus(char *event); +void initiate_cwmp_periodic_session_feature(); +int run_session_end_func(void); +void cwmp_schedule_session(struct uloop_timeout *timeout); +void start_cwmp_session(); +int create_cwmp_session_structure(); +int clean_cwmp_session_structure(); +void set_cwmp_session_status(int status, int retry_time); +int cwmp_session_init(); +int cwmp_session_exit(); #endif /* SRC_INC_SESSION_H_ */ diff --git a/inc/soap.h b/inc/soap.h new file mode 100644 index 0000000..78f213d --- /dev/null +++ b/inc/soap.h @@ -0,0 +1,64 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Copyright (C) 2013-2019 iopsys Software Solutions AB + * Author Mohamed Kallel + * Author Ahmed Zribi + * Copyright (C) 2011 Luka Perkov + * + */ + +#ifndef __RPC__SOAP__H_ +#define __RPC__SOAP__H_ + +#include +#include "common.h" +#include "session.h" +#include "xml.h" + + +#define PROCESSING_DELAY (1) // In download/upload the message enqueued before sending the response, which cause the download/upload + // to start just before the time. This delay is to compensate the time lapsed during the message enqueue and response + +#define MAX_NBRE_CUSTOM_INFORM 256 +extern char *custom_forced_inform_parameters[MAX_NBRE_CUSTOM_INFORM]; +extern char *boot_inform_parameters[MAX_NBRE_CUSTOM_INFORM]; +extern int nbre_custom_inform; +extern int nbre_boot_inform; +extern const struct rpc_cpe_method rpc_cpe_methods[__RPC_CPE_MAX]; +extern const struct rpc_acs_method rpc_acs_methods[__RPC_ACS_MAX]; + +int cwmp_handle_rpc_cpe_get_rpc_methods(struct rpc *rpc); +int cwmp_handle_rpc_cpe_set_parameter_values(struct rpc *rpc); +int cwmp_handle_rpc_cpe_get_parameter_values(struct rpc *rpc); +int cwmp_handle_rpc_cpe_get_parameter_names(struct rpc *rpc); +int cwmp_handle_rpc_cpe_set_parameter_attributes(struct rpc *rpc); +int cwmp_handle_rpc_cpe_get_parameter_attributes(struct rpc *rpc); +int cwmp_handle_rpc_cpe_add_object(struct rpc *rpc); +int cwmp_handle_rpc_cpe_delete_object(struct rpc *rpc); +int cwmp_handle_rpc_cpe_reboot(struct rpc *rpc); +int cwmp_handle_rpc_cpe_download(struct rpc *rpc); +int cwmp_handle_rpc_cpe_upload(struct rpc *rpc); +int cwmp_handle_rpc_cpe_factory_reset(struct rpc *rpc); +int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct rpc *rpc); +int cancel_transfer(char *key); +int cwmp_handle_rpc_cpe_cancel_transfer(struct rpc *rpc); +int cwmp_handle_rpc_cpe_schedule_inform(struct rpc *rpc); +int cwmp_handle_rpc_cpe_schedule_download(struct rpc *rpc); +int cwmp_handle_rpc_cpe_change_du_state(struct rpc *rpc); +int cwmp_handle_rpc_cpe_fault(struct rpc *rpc); + +int cwmp_rpc_acs_prepare_message_inform(struct rpc *rpc); +int cwmp_rpc_acs_parse_response_inform(struct rpc *rpc); +int cwmp_rpc_acs_prepare_get_rpc_methods(struct rpc *rpc); +int cwmp_rpc_acs_prepare_transfer_complete(struct rpc *rpc); +int cwmp_rpc_acs_prepare_du_state_change_complete(struct rpc *rpc); +int cwmp_rpc_acs_destroy_data_inform(struct rpc *rpc); + +int xml_handle_message(); +int cwmp_create_fault_message(struct rpc *rpc_cpe, int fault_code); + +#endif diff --git a/inc/subprocess.h b/inc/subprocess.h new file mode 100644 index 0000000..4df3ced --- /dev/null +++ b/inc/subprocess.h @@ -0,0 +1,7 @@ +#ifndef SUB_PROC_H +#define SUB_PROC_H + +typedef char* (*task_function)(char *task_arg); +int subprocess_start(task_function task_fun); +char *execute_task_in_subprocess(char *task); +#endif diff --git a/inc/ubus.h b/inc/ubus.h index f9b395f..9396308 100644 --- a/inc/ubus.h +++ b/inc/ubus.h @@ -11,18 +11,14 @@ */ #ifndef _FREECWMP_UBUS_H__ #define _FREECWMP_UBUS_H__ -#include -/* #include #include +#include #include "common.h" -*/ -#include "common.h" - #define ARRAY_MAX 8 -int cwmp_ubus_init(struct cwmp *cwmp); +int cwmp_ubus_init(); void cwmp_ubus_exit(void); enum cwmp_ubus_arg_type diff --git a/inc/upload.h b/inc/upload.h index e061b78..c56aab1 100644 --- a/inc/upload.h +++ b/inc/upload.h @@ -11,14 +11,12 @@ #ifndef CWMP_UPLOAD_H #define CWMP_UPLOAD_H -#include "common.h" - extern struct list_head list_upload; extern pthread_mutex_t mutex_upload; -extern pthread_cond_t threshold_upload; int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptransfer_complete); void *thread_cwmp_rpc_cpe_upload(void *v); int cwmp_scheduledUpload_remove_all(); int cwmp_free_upload_request(struct upload *upload); +void cwmp_start_upload(struct uloop_timeout *timeout); #endif diff --git a/inc/xml.h b/inc/xml.h index 264bd51..d0f1148 100644 --- a/inc/xml.h +++ b/inc/xml.h @@ -2,8 +2,10 @@ #define __XML__H_ #include +#include +#include + #include "session.h" -#include "common.h" #define CWMP_MXML_TAB_SPACE " " #define MAX_SCHEDULE_INFORM_QUEUE 10 @@ -17,13 +19,13 @@ } while (0) extern const char *cwmp_urls[]; -int xml_prepare_msg_out(struct session *session); +int xml_prepare_msg_out(); int xml_prepare_lwnotification_message(char **msg_out); -int xml_set_cwmp_id_rpc_cpe(struct session *session); +int xml_set_cwmp_id_rpc_cpe(); int xml_recreate_namespace(mxml_node_t *tree); const char *whitespace_cb(mxml_node_t *node, int where); -int xml_set_cwmp_id(struct session *session); -int xml_send_message(struct cwmp *cwmp, struct session *session, struct rpc *rpc); +int xml_set_cwmp_id(); +int xml_send_message(struct rpc *rpc); mxml_node_t *mxmlFindElementOpaque(mxml_node_t *node, mxml_node_t *top, const char *text, int descend); char *xml_get_cwmp_version(int version); void xml_exit(void); diff --git a/log.c b/log.c index 9d62b67..1947312 100644 --- a/log.c +++ b/log.c @@ -10,14 +10,13 @@ * */ -#include -#include -#include -#include #include - -#include "log.h" +#include +#include +#include +#include #include "common.h" +#include "log.h" static char *SEVERITY_NAMES[8] = { "[EMERG] ", "[ALERT] ", "[CRITIC] ", "[ERROR] ", "[WARNING]", "[NOTICE] ", "[INFO] ", "[DEBUG] " }; static int log_severity = DEFAULT_LOG_SEVERITY; diff --git a/md5.c b/md5.c index 12a6834..d101666 100644 --- a/md5.c +++ b/md5.c @@ -15,9 +15,6 @@ * will fill a supplied 16-byte array with the digest. */ - -#include - #include "md5.h" #if __BYTE_ORDER == __BIG_ENDIAN diff --git a/netlink.c b/netlink.c index ca5641d..094e028 100644 --- a/netlink.c +++ b/netlink.c @@ -11,20 +11,29 @@ * */ -#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include -#include "netlink.h" -#include "cwmp_uci.h" +#include +#include +#include "http.h" #include "log.h" +#include "config.h" #include "event.h" +#include "cwmp_uci.h" static int itfcmp(char *itf1, char *itf2); static void netlink_new_msg(struct uloop_fd *ufd, unsigned events); @@ -108,18 +117,18 @@ static void freecwmp_netlink_interface(struct nlmsghdr *nlh) } if_indextoname(ifa->ifa_index, if_name); - if (itfcmp(cwmp_main.conf.interface, if_name)) { + if (itfcmp(cwmp_main->conf.interface, if_name)) { rth = RTA_NEXT(rth, rtl); continue; } inet_ntop(AF_INET, &(addr), if_addr, INET_ADDRSTRLEN); - FREE(cwmp_main.conf.ip); - cwmp_main.conf.ip = strdup(if_addr); - cwmp_uci_set_varstate_value("cwmp", "cpe", "ip", cwmp_main.conf.ip); + FREE(cwmp_main->conf.ip); + cwmp_main->conf.ip = strdup(if_addr); + cwmp_uci_set_varstate_value("cwmp", "cpe", "ip", cwmp_main->conf.ip); cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); - connection_request_ip_value_change(&cwmp_main, IPv4); + connection_request_ip_value_change(IPv4); break; } } else { //CASE IPv6 @@ -131,16 +140,16 @@ static void freecwmp_netlink_interface(struct nlmsghdr *nlh) } inet_ntop(AF_INET6, RTA_DATA(rth), pradd_v6, sizeof(pradd_v6)); if_indextoname(ifa->ifa_index, if_name); - if (strncmp(cwmp_main.conf.interface, if_name, IFNAMSIZ)) { + if (strncmp(cwmp_main->conf.interface, if_name, IFNAMSIZ)) { rth = RTA_NEXT(rth, rtl); continue; } - FREE(cwmp_main.conf.ipv6); - cwmp_main.conf.ipv6 = strdup(pradd_v6); - cwmp_uci_set_varstate_value("cwmp", "cpe", "ipv6", cwmp_main.conf.ip); + FREE(cwmp_main->conf.ipv6); + cwmp_main->conf.ipv6 = strdup(pradd_v6); + cwmp_uci_set_varstate_value("cwmp", "cpe", "ipv6", cwmp_main->conf.ip); cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); - connection_request_ip_value_change(&cwmp_main, IPv6); + connection_request_ip_value_change(IPv6); break; } } @@ -277,3 +286,16 @@ int netlink_init(void) return 0; } + +void cwmp_netlink_init(void) +{ + if (netlink_init()) { + CWMP_LOG(ERROR, "netlink initialization failed"); + } + + if (cwmp_main->conf.ipv6_enable) { + if (netlink_init_v6()) { + CWMP_LOG(ERROR, "netlink initialization failed"); + } + } +} diff --git a/notifications.c b/notifications.c index 1d1d3b0..328f44e 100644 --- a/notifications.c +++ b/notifications.c @@ -8,22 +8,24 @@ * Author Omar Kallel * */ - +#include #include +#include +#include #include #include "notifications.h" +#include "ubus.h" #include "cwmp_uci.h" -#include "datamodel_interface.h" -#include "ssl_utils.h" #include "log.h" -#include "event.h" -#include "xml.h" +#include "cwmp_event.h" +#include "ssl_utils.h" LIST_HEAD(list_value_change); LIST_HEAD(list_lw_value_change); LIST_HEAD(list_param_obj_notify); pthread_mutex_t mutex_value_change = PTHREAD_MUTEX_INITIALIZER; +struct uloop_timeout check_notify_timer = { .cb = periodic_check_notifiy }; char *notifications[7] = {"disabled" , "passive", "active", "passive_lw", "passive_passive_lw", "active_lw", "passive_active_lw"}; @@ -206,9 +208,7 @@ int get_parameter_leaf_notification_from_childs_list(char *parameter_name, struc { char *parent = NULL; int ret_notif = -1; - struct cwmp_dm_parameter *param_value; - if (childs_list == NULL) - return -1; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, childs_list, list) { if (strcmp(param_value->name, parameter_name) == 0) { ret_notif = param_value->notification; @@ -238,7 +238,7 @@ char *cwmp_get_parameter_attributes(char *parameter_name, struct list_head *para cwmp_free_all_dm_parameter_list(&childs_notifs); return error; } - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, ¶ms_list, list) { int notif_leaf; notif_leaf = check_parameter_forced_notification(param_value->name); @@ -265,13 +265,11 @@ char *cwmp_get_parameter_attributes(char *parameter_name, struct list_head *para bool parameter_is_other_notif_object_child(char *parent, char *parameter) { struct list_head list_iter, *list_ptr; + // cppcheck-suppress unreadVariable list_iter.next = list_param_obj_notify.next; list_iter.prev = list_param_obj_notify.prev; + struct cwmp_dm_parameter *dm_parameter = NULL; while (list_iter.prev != &list_param_obj_notify) { - struct cwmp_dm_parameter *dm_parameter; - if (list_iter.prev == NULL) - continue; - dm_parameter = list_entry(list_iter.prev, struct cwmp_dm_parameter, list); list_ptr = list_iter.prev; list_iter.prev = list_ptr->prev; @@ -304,7 +302,7 @@ void create_list_param_obj_notify() char* updated_list_param_leaf_notify_with_sub_parameter_list(struct list_head *list_param_leaf_notify, struct cwmp_dm_parameter parent_parameter, void (*update_notify_file_line_arg)(FILE *notify_file, char *param_name, char *param_type, char *param_value, int notification), FILE* notify_file_arg) { - struct cwmp_dm_parameter *param_iter; + struct cwmp_dm_parameter *param_iter = NULL; LIST_HEAD(params_list); char *err = cwmp_get_parameter_values(parent_parameter.name, ¶ms_list); if (err) @@ -323,7 +321,7 @@ char* updated_list_param_leaf_notify_with_sub_parameter_list(struct list_head *l void create_list_param_leaf_notify(struct list_head *list_param_leaf_notify, void (*update_notify_file_line_arg)(FILE *notify_file, char *param_name, char *param_type, char *param_value, int notification), FILE* notify_file_arg) { - struct cwmp_dm_parameter *param_iter; + struct cwmp_dm_parameter *param_iter = NULL;; int i; for (i = 0; i < (int)ARRAY_SIZE(forced_notifications_parameters); i++) @@ -389,15 +387,15 @@ void cwmp_update_enabled_notify_file(void) /* * Load custom notify json file */ -void load_custom_notify_json(struct cwmp *cwmp) +void load_custom_notify_json() { struct blob_buf bbuf; struct blob_attr *cur; struct blob_attr *custom_notify_list = NULL; int rem; - cwmp->custom_notify_active = false; - if (cwmp->conf.custom_notify_json == NULL || !file_exists(cwmp->conf.custom_notify_json)) + cwmp_main->custom_notify_active = false; + if (cwmp_main->conf.custom_notify_json == NULL || !file_exists(cwmp_main->conf.custom_notify_json)) return; if (file_exists(NOTIFY_FILE)) @@ -406,8 +404,8 @@ void load_custom_notify_json(struct cwmp *cwmp) memset(&bbuf, 0, sizeof(struct blob_buf)); blob_buf_init(&bbuf, 0); - if (blobmsg_add_json_from_file(&bbuf, cwmp->conf.custom_notify_json) == false) { - CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp->conf.custom_notify_json); + if (blobmsg_add_json_from_file(&bbuf, cwmp_main->conf.custom_notify_json) == false) { + CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp_main->conf.custom_notify_json); blob_buf_free(&bbuf); creat(NOTIFY_FILE , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); return; @@ -416,12 +414,14 @@ void load_custom_notify_json(struct cwmp *cwmp) const struct blobmsg_policy p_notif[1] = { { "custom_notification", BLOBMSG_TYPE_ARRAY } }; struct blob_attr *tb_notif[1] = { NULL}; blobmsg_parse(p_notif, 1, tb_notif, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head)); + if (tb_notif[0] == NULL) { - CWMP_LOG(WARNING, "The JSON file %s doesn't contain a notify parameters list", cwmp->conf.custom_notify_json); + CWMP_LOG(WARNING, "The JSON file %s doesn't contain a notify parameters list", cwmp_main->conf.custom_notify_json); blob_buf_free(&bbuf); creat(NOTIFY_FILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); return; } + custom_notify_list = tb_notif[0]; const struct blobmsg_policy p[2] = { { "parameter", BLOBMSG_TYPE_STRING }, { "notify_type", BLOBMSG_TYPE_STRING } }; @@ -449,7 +449,7 @@ void load_custom_notify_json(struct cwmp *cwmp) } blob_buf_free(&bbuf); creat(NOTIFY_FILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - cwmp->custom_notify_active = true; + cwmp_main->custom_notify_active = true; } /* @@ -457,7 +457,7 @@ void load_custom_notify_json(struct cwmp *cwmp) */ void get_parameter_value_from_parameters_list(struct list_head *params_list, char *parameter_name, char **value, char **type) { - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, params_list, list) { if (param_value->name == NULL) continue; @@ -540,61 +540,52 @@ int check_value_change(void) return int_ret; } -void sotfware_version_value_change(struct cwmp *cwmp, struct transfer_complete *p) +void cwmp_prepare_value_change() +{ + struct event_container *event_container; + if (list_value_change.next == &(list_value_change)) + return; + event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, ""); + if (!event_container) + return; + pthread_mutex_lock(&(mutex_value_change)); + list_splice_init(&(list_value_change), &(event_container->head_dm_parameter)); + pthread_mutex_unlock(&(mutex_value_change)); + cwmp_save_event_container(event_container); +} + +void sotfware_version_value_change(struct transfer_complete *p) { char *current_software_version = NULL; if (!p->old_software_version || p->old_software_version[0] == 0) return; - current_software_version = cwmp->deviceid.softwareversion; + current_software_version = cwmp_main->deviceid.softwareversion; if (p->old_software_version && current_software_version && strcmp(p->old_software_version, current_software_version) != 0) { - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, ""); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, ""); } } -void *thread_periodic_check_notify(void *v) +void periodic_check_notifiy(struct uloop_timeout *timeout __attribute__((unused))) { - struct cwmp *cwmp = (struct cwmp *)v; - int periodic_interval; - bool periodic_enable; - struct timespec periodic_timeout = { 0, 0 }; - time_t current_time; - int is_notify; + int is_notify = 0; + if (cwmp_stop) + return; + is_notify = check_value_change(); + if (is_notify > 0) + cwmp_update_enabled_notify_file(); + if (is_notify & NOTIF_ACTIVE) + send_active_value_change(); + if (is_notify & NOTIF_LW_ACTIVE) + cwmp_lwnotification(); - periodic_interval = cwmp->conf.periodic_notify_interval; - periodic_enable = cwmp->conf.periodic_notify_enable; + uloop_timeout_set(&check_notify_timer, cwmp_main->conf.periodic_notify_interval * 1000); +} - for (;;) { - if (periodic_enable) { - pthread_mutex_lock(&(cwmp->mutex_notify_periodic)); - current_time = time(NULL); - periodic_timeout.tv_sec = current_time + periodic_interval; - - if (thread_end) - break; - - pthread_cond_timedwait(&(cwmp->threshold_notify_periodic), &(cwmp->mutex_notify_periodic), &periodic_timeout); - - if (thread_end) - break; - - pthread_mutex_lock(&(cwmp->mutex_session_send)); - is_notify = check_value_change(); - if (is_notify > 0) - cwmp_update_enabled_notify_file(); - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - if (is_notify & NOTIF_ACTIVE) - send_active_value_change(); - if (is_notify & NOTIF_LW_ACTIVE) - cwmp_lwnotification(); - pthread_mutex_unlock(&(cwmp->mutex_notify_periodic)); - } else - break; - } - return NULL; +void trigger_periodic_notify_check() +{ + uloop_timeout_set(&check_notify_timer, 10); } void add_list_value_change(char *param_name, char *param_data, char *param_type) @@ -613,19 +604,14 @@ void clean_list_value_change() void send_active_value_change(void) { - struct cwmp *cwmp = &cwmp_main; struct event_container *event_container; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, ""); + event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, ""); if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); return; } cwmp_save_event_container(event_container); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - pthread_cond_signal(&(cwmp->threshold_session_send)); return; } @@ -636,10 +622,9 @@ void add_lw_list_value_change(char *param_name, char *param_data, char *param_ty static void udplw_server_param(struct addrinfo **res) { struct addrinfo hints = { 0 }; - struct cwmp *cwmp = &cwmp_main; - struct config *conf; + struct config *conf = &(cwmp_main->conf); char port[32]; - conf = &(cwmp->conf); + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; snprintf(port, sizeof(port), "%d", conf->lw_notification_port); @@ -686,8 +671,6 @@ static void free_all_list_lw_notify() { while (list_lw_value_change.next != &list_lw_value_change) { struct cwmp_dm_parameter *dm_parameter; - if (list_lw_value_change.next == NULL) - continue; dm_parameter = list_entry(list_lw_value_change.next, struct cwmp_dm_parameter, list); del_list_lw_notify(dm_parameter); } @@ -698,9 +681,7 @@ void cwmp_lwnotification() char msg[1024], *msg_out; char signature[41]; struct addrinfo *servaddr; - struct cwmp *cwmp = &cwmp_main; - struct config *conf; - conf = &(cwmp->conf); + struct config *conf = &(cwmp_main->conf); udplw_server_param(&servaddr); xml_prepare_lwnotification_message(&msg_out); diff --git a/reboot.c b/reboot.c index 837fd82..b397175 100644 --- a/reboot.c +++ b/reboot.c @@ -5,116 +5,60 @@ * (at your option) any later version. * * Copyright (C) 2021 iopsys Software Solutions AB - * Author Amin Ben Ramdhane + * Author Omar Kallel + * */ #include -#include "reboot.h" +#include "session.h" #include "cwmp_uci.h" #include "log.h" -#include "session.h" +#include "reboot.h" -static pthread_t delay_reboot_thread; -static pthread_t delay_schedule_thread; -static int g_curr_delay_reboot = -1; -static time_t g_curr_schedule_redoot = 0; +void cwmp_schedule_reboot(struct uloop_timeout *timeout __attribute__((unused))); +void cwmp_delay_reboot(struct uloop_timeout *timeout __attribute__((unused))); -static void *thread_delay_reboot(void *arg) +struct uloop_timeout schedule_reboot_timer = { .cb = cwmp_schedule_reboot }; +struct uloop_timeout delay_reboot_timer = { .cb = cwmp_delay_reboot }; + +void cwmp_schedule_reboot(struct uloop_timeout *timeout __attribute__((unused))) { - struct cwmp *cwmp = (struct cwmp *)arg; + cwmp_uci_set_value("cwmp", "cpe", "schedule_reboot", "0001-01-01T00:00:00Z"); + cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); + if (time(NULL) > cwmp_main->conf.schedule_reboot) + return; + cwmp_reboot("schedule_reboot"); +} - CWMP_LOG(INFO, "The device will reboot after %d seconds", cwmp->conf.delay_reboot); - sleep(cwmp->conf.delay_reboot); +void cwmp_delay_reboot(struct uloop_timeout *timeout __attribute__((unused))) +{ cwmp_uci_set_value("cwmp", "cpe", "delay_reboot", "-1"); cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); - /* check if the session is running before calling reboot method */ - /* if the session is in progress, wait until the end of the session */ - /* else calling reboot method */ - if (cwmp->session_status.last_status == SESSION_RUNNING) { + if (cwmp_main->session->session_status.last_status == SESSION_RUNNING) { cwmp_set_end_session(END_SESSION_REBOOT); } else { cwmp_reboot("delay_reboot"); exit(EXIT_SUCCESS); } - - return NULL; } -static void create_delay_reboot_thread(struct cwmp *cwmp, bool thread_exist) +void launch_reboot_methods() { - if (thread_exist) { - CWMP_LOG(INFO, "There is already a delay reboot thread!, Cancel the current thread"); + static int curr_delay_reboot = -1; + static time_t curr_schedule_redoot = 0; - pthread_cancel(delay_reboot_thread); - create_delay_reboot_thread(cwmp, false); - } else { - CWMP_LOG(INFO, "Create a delay reboot thread"); + if (cwmp_main->conf.delay_reboot != curr_delay_reboot && cwmp_main->conf.delay_reboot > 0) { + CWMP_LOG(INFO, "The device will reboot after %ld seconds", cwmp_main->conf.delay_reboot); + curr_delay_reboot = cwmp_main->conf.delay_reboot; + uloop_timeout_cancel(&delay_reboot_timer); + uloop_timeout_set(&delay_reboot_timer, cwmp_main->conf.delay_reboot * 1000); + } - if (pthread_create(&delay_reboot_thread, NULL, &thread_delay_reboot, (void *)cwmp)) { - CWMP_LOG(ERROR, "Error when creating the delay reboot thread!"); - } - - if (pthread_detach(delay_reboot_thread)) { - CWMP_LOG(ERROR, "Error when creating the delay reboot thread!"); - } - } -} - -static void *thread_schedule_reboot(void *arg) -{ - struct cwmp *cwmp = (struct cwmp *)arg; - time_t remaining_time = cwmp->conf.schedule_reboot - time(NULL); - - CWMP_LOG(INFO, "The device will reboot after %ld seconds", remaining_time); - sleep(remaining_time); - cwmp_uci_set_value("cwmp", "cpe", "schedule_reboot", "0001-01-01T00:00:00Z"); - cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); - - /* check if the session is running before calling reboot method */ - /* if the session is in progress, wait until the end of the session */ - /* else calling reboot method */ - if (cwmp->session_status.last_status == SESSION_RUNNING) { - cwmp_set_end_session(END_SESSION_REBOOT); - } else { - cwmp_reboot("schedule_reboot"); - exit(EXIT_SUCCESS); - } - - return NULL; -} - -static void create_schedule_reboot_thread(struct cwmp *cwmp, bool thread_exist) -{ - if (thread_exist) { - CWMP_LOG(INFO, "There is already a schedule reboot thread!, Cancel the current thread"); - - pthread_cancel(delay_schedule_thread); - create_schedule_reboot_thread(cwmp, false); - } else { - CWMP_LOG(INFO, "Create a schedule reboot thread"); - - if (pthread_create(&delay_schedule_thread, NULL, &thread_schedule_reboot, (void *)cwmp)) { - CWMP_LOG(ERROR, "Error when creating the schedule reboot thread!"); - } - - if (pthread_detach(delay_schedule_thread)) { - CWMP_LOG(ERROR, "Error when detaching the schedule reboot thread!"); - } - } -} - -void launch_reboot_methods(struct cwmp *cwmp) -{ - - if (cwmp->conf.delay_reboot != g_curr_delay_reboot && cwmp->conf.delay_reboot > 0) { - - create_delay_reboot_thread(cwmp, (g_curr_delay_reboot != -1)); - g_curr_delay_reboot = cwmp->conf.delay_reboot; - } - - if (cwmp->conf.schedule_reboot != g_curr_schedule_redoot && (cwmp->conf.schedule_reboot - time(NULL)) > 0) { - - create_schedule_reboot_thread(cwmp, (g_curr_schedule_redoot != 0)); - g_curr_schedule_redoot = cwmp->conf.schedule_reboot; + if (cwmp_main->conf.schedule_reboot != curr_schedule_redoot && (cwmp_main->conf.schedule_reboot - time(NULL)) > 0) { + curr_schedule_redoot = cwmp_main->conf.schedule_reboot; + time_t remaining_time = cwmp_main->conf.schedule_reboot - time(NULL); + CWMP_LOG(INFO, "The device will reboot after %ld seconds", remaining_time); + uloop_timeout_cancel(&schedule_reboot_timer); + uloop_timeout_set(&schedule_reboot_timer, remaining_time * 1000); } } diff --git a/sched_inform.c b/sched_inform.c index a3b9033..60c3358 100644 --- a/sched_inform.c +++ b/sched_inform.c @@ -8,10 +8,12 @@ * Author Omar Kallel */ +#include "common.h" #include "sched_inform.h" +#include "log.h" #include "backupSession.h" #include "event.h" -#include "log.h" +#include "cwmp_event.h" LIST_HEAD(list_schedule_inform); pthread_mutex_t mutex_schedule_inform = PTHREAD_MUTEX_INITIALIZER; @@ -19,9 +21,8 @@ pthread_cond_t threshold_schedule_inform; int count_schedule_inform_queue = 0; -void *thread_cwmp_rpc_cpe_scheduleInform(void *v) +void *thread_cwmp_rpc_cpe_scheduleInform(void *v __attribute__((unused))) { - struct cwmp *cwmp = (struct cwmp *)v; struct event_container *event_container; struct schedule_inform *schedule_inform; struct timespec si_timeout = { 0, 0 }; @@ -30,7 +31,7 @@ void *thread_cwmp_rpc_cpe_scheduleInform(void *v) for (;;) { - if (thread_end) + if (cwmp_stop) break; if (list_schedule_inform.next != &(list_schedule_inform)) { @@ -49,18 +50,15 @@ void *thread_cwmp_rpc_cpe_scheduleInform(void *v) pthread_mutex_unlock(&mutex_schedule_inform); continue; } - pthread_mutex_lock(&(cwmp->mutex_session_queue)); CWMP_LOG(INFO, "Schedule Inform thread: add ScheduleInform event in the queue"); - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_3SCHEDULED, ""); + event_container = cwmp_add_event_container(EVENT_IDX_3SCHEDULED, ""); if (event_container != NULL) { cwmp_save_event_container(event_container); } - event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_ScheduleInform, schedule_inform->commandKey); + event_container = cwmp_add_event_container(EVENT_IDX_M_ScheduleInform, schedule_inform->commandKey); if (event_container != NULL) { cwmp_save_event_container(event_container); } - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - pthread_cond_signal(&(cwmp->threshold_session_send)); pthread_mutex_lock(&mutex_schedule_inform); list_del(&(schedule_inform->list)); if (schedule_inform->commandKey != NULL) { diff --git a/session.c b/session.c index c12b498..3ecc76b 100644 --- a/session.c +++ b/session.c @@ -9,109 +9,62 @@ * */ -#include - #include "session.h" -#include "config.h" #include "event.h" -#include "rpc_soap.h" #include "backupSession.h" +#include "config.h" +#include "cwmp_uci.h" +#include "log.h" +#include "http.h" +#include "notifications.h" +#include "diagnostic.h" +#include "soap.h" +#include "ubus.h" +#include "download.h" +#include "upload.h" +#include "cwmp_event.h" +#include "ssl_utils.h" + +pthread_mutex_t start_session_mutext = PTHREAD_MUTEX_INITIALIZER; +static void cwmp_priodic_session_timer(struct uloop_timeout *timeout); +struct uloop_timeout session_timer = { .cb = cwmp_schedule_session }; +struct uloop_timeout priodic_session_timer = { .cb = cwmp_priodic_session_timer }; +struct uloop_timeout retry_session_timer = { .cb = cwmp_schedule_session }; unsigned int end_session_flag = 0; -void cwmp_set_end_session(unsigned int flag) +int create_cwmp_session_structure() { - end_session_flag |= flag; -} - -struct rpc *cwmp_add_session_rpc_cpe(struct session *session, int type) -{ - struct rpc *rpc_cpe; - - rpc_cpe = calloc(1, sizeof(struct rpc)); - if (rpc_cpe == NULL) { - return NULL; - } - rpc_cpe->type = type; - list_add_tail(&(rpc_cpe->list), &(session->head_rpc_cpe)); - return rpc_cpe; -} - -struct rpc *cwmp_add_session_rpc_acs(struct session *session, int type) -{ - struct rpc *rpc_acs; - - rpc_acs = calloc(1, sizeof(struct rpc)); - if (rpc_acs == NULL) { - return NULL; - } - rpc_acs->type = type; - list_add_tail(&(rpc_acs->list), &(session->head_rpc_acs)); - return rpc_acs; -} - -int cwmp_apply_acs_changes(void) -{ - int error; - - if ((error = cwmp_config_reload(&cwmp_main))) - return error; - - if ((error = cwmp_root_cause_events(&cwmp_main))) - return error; - + cwmp_main->session = calloc(1, sizeof(struct session)); + if (cwmp_main->session == NULL) + return CWMP_GEN_ERR; + INIT_LIST_HEAD(&(cwmp_main->session->events)); + INIT_LIST_HEAD(&(cwmp_main->session->head_rpc_acs)); + INIT_LIST_HEAD(&(cwmp_main->session->head_rpc_cpe)); return CWMP_OK; } -int cwmp_move_session_to_session_send(struct cwmp *cwmp, struct session *session) +int cwmp_session_init() { - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - if (cwmp->session_send != NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MUTEX_ERR; - } - list_del(&(session->list)); - cwmp->session_send = session; - cwmp->head_event_container = NULL; - bkp_session_move_inform_to_inform_send(); - bkp_session_save(); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + struct rpc *rpc_acs; + + cwmp_main->cwmp_cr_event = 0; + + cwmp_uci_init(); + rpc_acs = cwmp_add_session_rpc_acs_head(RPC_ACS_INFORM); + if (rpc_acs == NULL) + return CWMP_GEN_ERR; + + set_cwmp_session_status(SESSION_RUNNING, 0); + if (file_exists(fc_cookies)) + remove(fc_cookies); return CWMP_OK; } -struct rpc *cwmp_add_session_rpc_acs_head(struct session *session, int type) +int clean_cwmp_session_structure() { - struct rpc *rpc_acs; - - rpc_acs = calloc(1, sizeof(struct rpc)); - if (rpc_acs == NULL) { - return NULL; - } - rpc_acs->type = type; - list_add(&(rpc_acs->list), &(session->head_rpc_acs)); - return rpc_acs; -} - -struct session *cwmp_add_queue_session(struct cwmp *cwmp) -{ - struct session *session = NULL; - struct rpc *rpc_acs; - - session = calloc(1, sizeof(struct session)); - if (session == NULL) - return NULL; - - list_add_tail(&(session->list), &(cwmp->head_session_queue)); - INIT_LIST_HEAD(&(session->head_event_container)); - INIT_LIST_HEAD(&(session->head_rpc_acs)); - INIT_LIST_HEAD(&(session->head_rpc_cpe)); - rpc_acs = cwmp_add_session_rpc_acs_head(session, RPC_ACS_INFORM); - if (rpc_acs == NULL) { - FREE(session); - return NULL; - } - - return session; + FREE(cwmp_main->session); + return 0; } int cwmp_session_rpc_destructor(struct rpc *rpc) @@ -121,101 +74,502 @@ int cwmp_session_rpc_destructor(struct rpc *rpc) return CWMP_OK; } -int cwmp_session_destructor(struct session *session) +int cwmp_session_exit() +{ + cwmp_uci_exit(); + icwmp_cleanmem(); + return CWMP_OK; +} + +static int cwmp_rpc_cpe_handle_message(struct rpc *rpc_cpe) +{ + if (xml_prepare_msg_out()) + return -1; + if (rpc_cpe_methods[rpc_cpe->type].handler(rpc_cpe)) + return -1; + if (xml_set_cwmp_id_rpc_cpe()) + return -1; + + return 0; +} + +static int cwmp_schedule_rpc() +{ + struct list_head *ilist; + struct rpc *rpc_acs, *rpc_cpe; + + if (http_client_init() || cwmp_stop) { + CWMP_LOG(INFO, "Initializing http client failed"); + goto retry; + } + + while (1) { + list_for_each (ilist, &(cwmp_main->session->head_rpc_acs)) { + + rpc_acs = list_entry(ilist, struct rpc, list); + if (!rpc_acs->type || cwmp_stop) + goto retry; + + CWMP_LOG(INFO, "Preparing the %s RPC message to send to the ACS", rpc_acs_methods[rpc_acs->type].name); + if (rpc_acs_methods[rpc_acs->type].prepare_message(rpc_acs) || cwmp_stop) + goto retry; + + if (xml_set_cwmp_id() || cwmp_stop) + goto retry; + + CWMP_LOG(INFO, "Send the %s RPC message to the ACS", rpc_acs_methods[rpc_acs->type].name); + if (xml_send_message(rpc_acs) || cwmp_stop) + goto retry; + + CWMP_LOG(INFO, "Get the %sResponse message from the ACS", rpc_acs_methods[rpc_acs->type].name); + if (rpc_acs_methods[rpc_acs->type].parse_response || cwmp_stop) + if (rpc_acs_methods[rpc_acs->type].parse_response(rpc_acs)) + goto retry; + + ilist = ilist->prev; + if (rpc_acs_methods[rpc_acs->type].extra_clean != NULL) + rpc_acs_methods[rpc_acs->type].extra_clean(rpc_acs); + cwmp_session_rpc_destructor(rpc_acs); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + if (cwmp_main->session->hold_request || cwmp_stop) + break; + } + + // If restart service caused firewall restart, wait for firewall restart to complete + if (g_firewall_restart == true) + check_firewall_restart_state(); + + CWMP_LOG(INFO, "Send empty message to the ACS"); + if (xml_send_message(NULL) || cwmp_stop) + goto retry; + if (!cwmp_main->session->tree_in || cwmp_stop) + goto next; + + CWMP_LOG(INFO, "Receive request from the ACS"); + if (xml_handle_message() || cwmp_stop) + goto retry; + + while (cwmp_main->session->head_rpc_cpe.next != &(cwmp_main->session->head_rpc_cpe)) { + + rpc_cpe = list_entry(cwmp_main->session->head_rpc_cpe.next, struct rpc, list); + if (!rpc_cpe->type || cwmp_stop) + goto retry; + + CWMP_LOG(INFO, "Preparing the %s%s message", rpc_cpe_methods[rpc_cpe->type].name, (rpc_cpe->type != RPC_CPE_FAULT) ? "Response" : ""); + if (cwmp_rpc_cpe_handle_message(rpc_cpe) || cwmp_stop) + goto retry; + MXML_DELETE(cwmp_main->session->tree_in); + + CWMP_LOG(INFO, "Send the %s%s message to the ACS", rpc_cpe_methods[rpc_cpe->type].name, (rpc_cpe->type != RPC_CPE_FAULT) ? "Response" : ""); + if (xml_send_message(rpc_cpe) || cwmp_stop) + goto retry; + MXML_DELETE(cwmp_main->session->tree_out); + + cwmp_session_rpc_destructor(rpc_cpe); + if (!cwmp_main->session->tree_in || cwmp_stop) + break; + + CWMP_LOG(INFO, "Receive request from the ACS"); + if (xml_handle_message() || cwmp_stop) + goto retry; + } + + next: + if (cwmp_main->session->head_rpc_acs.next == &(cwmp_main->session->head_rpc_acs)) + break; + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + } + + cwmp_main->session->error = CWMP_OK; + goto end; + +retry: + CWMP_LOG(INFO, "Failed"); + cwmp_main->session->error = CWMP_RETRY_SESSION; + event_remove_noretry_event_container(); + +end: + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + http_client_exit(); + xml_exit(); + return cwmp_main->session->error; +} + +void set_cwmp_session_status(int status, int retry_time) +{ + cwmp_main->session->session_status.last_status = status; + if (status == SESSION_SUCCESS) { + cwmp_main->session->session_status.last_end_time = time(NULL); + cwmp_main->session->session_status.next_retry = 0; + cwmp_main->session->session_status.success_session++; + } else if (status == SESSION_RUNNING) { + cwmp_main->session->session_status.last_end_time = 0; + cwmp_main->session->session_status.next_retry = 0; + cwmp_main->session->session_status.last_start_time = time(NULL); + } else { + cwmp_main->session->session_status.last_end_time = time(NULL); + cwmp_main->session->session_status.next_retry = time(NULL) + retry_time; + cwmp_main->session->session_status.failure_session++; + } +} + +void rpc_exit() { struct rpc *rpc; - while (session->head_rpc_acs.next != &(session->head_rpc_acs)) { - rpc = list_entry(session->head_rpc_acs.next, struct rpc, list); + while (cwmp_main->session->head_rpc_acs.next != &(cwmp_main->session->head_rpc_acs)) { + rpc = list_entry(cwmp_main->session->head_rpc_acs.next, struct rpc, list); if (!rpc) break; if (rpc_acs_methods[rpc->type].extra_clean != NULL) - rpc_acs_methods[rpc->type].extra_clean(session, rpc); + rpc_acs_methods[rpc->type].extra_clean(rpc); cwmp_session_rpc_destructor(rpc); } - while (session->head_rpc_cpe.next != &(session->head_rpc_cpe)) { - rpc = list_entry(session->head_rpc_cpe.next, struct rpc, list); + while (cwmp_main->session->head_rpc_cpe.next != &(cwmp_main->session->head_rpc_cpe)) { + rpc = list_entry(cwmp_main->session->head_rpc_cpe.next, struct rpc, list); if (!rpc) break; cwmp_session_rpc_destructor(rpc); } - - if (session->list.next != NULL && session->list.prev != NULL) - list_del(&(session->list)); - free(session); - - return CWMP_OK; } -int cwmp_move_session_to_session_queue(struct cwmp *cwmp, struct session *session) +void start_cwmp_session() { - struct list_head *ilist, *jlist; - struct rpc *rpc_acs, *queue_rpc_acs; - struct session *session_queue; + int t, error; + char *exec_download = NULL; + int is_notify = 0; - pthread_mutex_lock(&(cwmp->mutex_session_queue)); - cwmp->retry_count_session++; - cwmp->session_send = NULL; - if (cwmp->head_session_queue.next == &(cwmp->head_session_queue)) { - list_add_tail(&(session->list), &(cwmp->head_session_queue)); - session->hold_request = 0; - session->digest_auth = 0; - cwmp->head_event_container = &(session->head_event_container); - if (session->head_rpc_acs.next != &(session->head_rpc_acs)) { - rpc_acs = list_entry(session->head_rpc_acs.next, struct rpc, list); - if (rpc_acs->type != RPC_ACS_INFORM) { - if (cwmp_add_session_rpc_acs_head(session, RPC_ACS_INFORM) == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MEM_ERR; - } - } - } else { - if (cwmp_add_session_rpc_acs_head(session, RPC_ACS_INFORM) == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MEM_ERR; - } - } - while (session->head_rpc_cpe.next != &(session->head_rpc_cpe)) { - struct rpc *rpc_cpe; - rpc_cpe = list_entry(session->head_rpc_cpe.next, struct rpc, list); - cwmp_session_rpc_destructor(rpc_cpe); - } - bkp_session_move_inform_to_inform_queue(); - bkp_session_save(); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_OK; + uloop_timeout_cancel(&check_notify_timer); + if (cwmp_session_init() != CWMP_OK) { + CWMP_LOG(ERROR, "Not able to init a CWMP session"); + t = cwmp_get_session_retry_interval(); + CWMP_LOG(INFO, "Retry session, retry count = %d, retry in %ds", cwmp_main->retry_count_session, t); + set_cwmp_session_status(SESSION_FAILURE, t); + trigger_periodic_notify_check(); + return; } - list_for_each (ilist, &(session->head_event_container)) { - struct event_container *event_container_new, *event_container_old; - event_container_old = list_entry(ilist, struct event_container, list); - event_container_new = cwmp_add_event_container(cwmp, event_container_old->code, event_container_old->command_key); - if (event_container_new == NULL) { - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); - return CWMP_MEM_ERR; - } - list_splice_init(&(event_container_old->head_dm_parameter), &(event_container_new->head_dm_parameter)); - cwmp_save_event_container(event_container_new); + + if (cwmp_main->session->session_status.last_status == SESSION_FAILURE) + reload_networking_config(); + /* + * Value changes + */ + if (file_exists(DM_ENABLED_NOTIFY)) { + if (!event_exist_in_list(EVENT_IDX_4VALUE_CHANGE)) + is_notify = check_value_change(); } - session_queue = list_entry(cwmp->head_event_container, struct session, head_event_container); - list_for_each (ilist, &(session->head_rpc_acs)) { - rpc_acs = list_entry(ilist, struct rpc, list); - bool dup; - dup = false; - list_for_each (jlist, &(session_queue->head_rpc_acs)) { - queue_rpc_acs = list_entry(jlist, struct rpc, list); - if (queue_rpc_acs->type == rpc_acs->type && (rpc_acs->type == RPC_ACS_INFORM || rpc_acs->type == RPC_ACS_GET_RPC_METHODS)) { - dup = true; - break; + if (is_notify > 0 || !file_exists(DM_ENABLED_NOTIFY) || cwmp_main->custom_notify_active) { + cwmp_main->custom_notify_active = false; + cwmp_update_enabled_notify_file(); + } + cwmp_prepare_value_change(cwmp_main); + clean_list_value_change(); + + /* + * Start session + */ + + CWMP_LOG(INFO, "Start session"); + + uci_get_value(UCI_CPE_EXEC_DOWNLOAD, &exec_download); + if (exec_download && strcmp(exec_download, "1") == 0) { + CWMP_LOG(INFO, "Firmware downloaded and applied successfully"); + cwmp_uci_set_value("cwmp", "cpe", "exec_download", "0"); + cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); + } + FREE(exec_download); + error = cwmp_schedule_rpc(); + if (error != CWMP_OK) + CWMP_LOG(ERROR, "CWMP session error: %d", error); + /* + * End session + */ + CWMP_LOG(INFO, "End session"); + + if (cwmp_stop) { + event_remove_all_event_container(RPC_SEND); + event_remove_all_event_container(RPC_QUEUE); + run_session_end_func(); + cwmp_session_exit(); + rpc_exit(); + return; + } + + if (cwmp_main->session->error == CWMP_RETRY_SESSION && (!list_empty(&(cwmp_main->session->events)) || (list_empty(&(cwmp_main->session->events)) && cwmp_main->cwmp_cr_event == 0))) { //CWMP Retry session + reload_networking_config(); + cwmp_main->retry_count_session++; + t = cwmp_get_session_retry_interval(); + CWMP_LOG(INFO, "Retry session, retry count = %d, retry in %ds", cwmp_main->retry_count_session, t); + set_cwmp_session_status(SESSION_FAILURE, t); + uloop_timeout_set(&retry_session_timer, 1000 * t); + } else { + event_remove_all_event_container(RPC_SEND); + //event_remove_all_event_container(RPC_QUEUE); + cwmp_main->retry_count_session = 0; + set_cwmp_session_status(SESSION_SUCCESS, 0); + rpc_exit(); + } + run_session_end_func(); + cwmp_session_exit(); + CWMP_LOG(INFO, "Waiting the next session"); + trigger_periodic_notify_check(); +} + +void trigger_cwmp_session_timer() +{ + uloop_timeout_cancel(&retry_session_timer); + uloop_timeout_set(&session_timer, 10); +} + +void cwmp_schedule_session(struct uloop_timeout *timeout __attribute__((unused))) +{ + pthread_mutex_lock(&start_session_mutext); + start_cwmp_session(); + pthread_mutex_unlock(&start_session_mutext); + if (cwmp_main->start_diagnostics) { + cwmp_main->start_diagnostics = false; + trigger_cwmp_session_timer(); + } +} + +static void cwmp_priodic_session_timer(struct uloop_timeout *timeout __attribute__((unused))) +{ + if (cwmp_main->conf.periodic_enable && cwmp_main->conf.period > 0) { + cwmp_main->session->session_status.next_periodic = time(NULL) + cwmp_main->conf.period; + uloop_timeout_set(&priodic_session_timer, cwmp_main->conf.period * 1000); + } + if (cwmp_main->conf.periodic_enable) { + cwmp_add_event_container(EVENT_IDX_2PERIODIC, ""); + trigger_cwmp_session_timer(); + } +} + +long int cwmp_periodic_session_time(void) +{ + long int delta_time; + long int periodic_time; + + delta_time = time(NULL) - cwmp_main->conf.time; + if(delta_time > 0) + periodic_time = cwmp_main->conf.period - (delta_time % cwmp_main->conf.period); + else + periodic_time = (-delta_time) % cwmp_main->conf.period; + + cwmp_main->session->session_status.next_periodic = time(NULL) + periodic_time; + return periodic_time; +} + +void initiate_cwmp_periodic_session_feature() +{ + uloop_timeout_cancel(&priodic_session_timer); + if (cwmp_main->conf.periodic_enable && cwmp_main->conf.period > 0) { + if (cwmp_main->conf.time >= 0){ + CWMP_LOG(INFO, "Init periodic inform: periodic_inform time = %ld, interval = %d\n", cwmp_main->conf.time, cwmp_main->conf.period); + uloop_timeout_set(&priodic_session_timer, cwmp_periodic_session_time() * 1000); + } + else { + CWMP_LOG(INFO, "Init periodic inform: interval = %d\n", cwmp_main->conf.period); + cwmp_main->session->session_status.next_periodic = time(NULL) + cwmp_main->conf.period; + uloop_timeout_set(&priodic_session_timer, cwmp_main->conf.period * 1000); + } + } +} + +struct rpc *cwmp_add_session_rpc_cpe(int type) +{ + struct rpc *rpc_cpe; + + rpc_cpe = calloc(1, sizeof(struct rpc)); + if (rpc_cpe == NULL) { + return NULL; + } + rpc_cpe->type = type; + list_add_tail(&(rpc_cpe->list), &(cwmp_main->session->head_rpc_cpe)); + return rpc_cpe; +} + +struct rpc *cwmp_add_session_rpc_acs(int type) +{ + struct rpc *rpc_acs; + + rpc_acs = calloc(1, sizeof(struct rpc)); + if (rpc_acs == NULL) { + return NULL; + } + rpc_acs->type = type; + list_add_tail(&(rpc_acs->list), &(cwmp_main->session->head_rpc_acs)); + return rpc_acs; +} + +int cwmp_get_session_retry_interval() +{ + unsigned int retry_count = 0; + double min = 0; + double max = 0; + int m = cwmp_main->conf.retry_min_wait_interval; + int k = cwmp_main->conf.retry_interval_multiplier; + int exp = cwmp_main->retry_count_session; + if (exp == 0) + return MAX_INT32; + if (exp > 10) + exp = 10; + min = pow(((double)k / 1000), (double)(exp - 1)) * m; + max = pow(((double)k / 1000), (double)exp) * m; + char *rand = generate_random_string(4); + if (rand) { + unsigned int dividend = (unsigned int)strtoul(rand, NULL, 16); + retry_count = dividend % ((unsigned int)max + 1 - (unsigned int)min) + (unsigned int)min; + free(rand); + } + return (retry_count); +} + +struct rpc *cwmp_add_session_rpc_acs_head(int type) +{ + struct rpc *rpc_acs; + + rpc_acs = calloc(1, sizeof(struct rpc)); + if (rpc_acs == NULL) { + return NULL; + } + rpc_acs->type = type; + list_add(&(rpc_acs->list), &(cwmp_main->session->head_rpc_acs)); + return rpc_acs; +} + +void cwmp_set_end_session(unsigned int flag) +{ + end_session_flag |= flag; +} + +int run_session_end_func(void) +{ + if (end_session_flag & END_SESSION_RESTART_SERVICES) { + CWMP_LOG(INFO, "Restart modified services"); + icwmp_restart_services(); + } + + if (end_session_flag & END_SESSION_RELOAD) { + CWMP_LOG(INFO, "Config reload: end session request"); + cwmp_uci_reinit(); + cwmp_apply_acs_changes(); + initiate_cwmp_periodic_session_feature(); + } + + if (end_session_flag & END_SESSION_INIT_NOTIFY) { + CWMP_LOG(INFO, "SetParameterAttributes end session: reinit list notify"); + reinit_list_param_notify(); + } + + if (end_session_flag & END_SESSION_SET_NOTIFICATION_UPDATE) { + CWMP_LOG(INFO, "SetParameterAttributes/Values end session: update enabled notify file"); + cwmp_update_enabled_notify_file(); + } + + if (end_session_flag & END_SESSION_NSLOOKUP_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing nslookupdiagnostic: end session request"); + cwmp_nslookup_diagnostics(); + } + + if (end_session_flag & END_SESSION_TRACEROUTE_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing traceroutediagnostic: end session request"); + cwmp_traceroute_diagnostics(); + } + + if (end_session_flag & END_SESSION_UDPECHO_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing udpechodiagnostic: end session request"); + cwmp_udp_echo_diagnostics(); + } + + if (end_session_flag & END_SESSION_SERVERSELECTION_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing serverselectiondiagnostic: end session request"); + cwmp_serverselection_diagnostics(); + } + + if (end_session_flag & END_SESSION_IPPING_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing ippingdiagnostic: end session request"); + cwmp_ip_ping_diagnostics(); + } + + if (end_session_flag & END_SESSION_DOWNLOAD_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing download diagnostic: end session request"); + cwmp_download_diagnostics(); + } + + if (end_session_flag & END_SESSION_UPLOAD_DIAGNOSTIC) { + CWMP_LOG(INFO, "Executing upload diagnostic: end session request"); + cwmp_upload_diagnostics(); + } + + if (end_session_flag & END_SESSION_REBOOT) { + CWMP_LOG(INFO, "Executing Reboot: end session request"); + cwmp_reboot(commandKey); + exit(EXIT_SUCCESS); + } + + if (end_session_flag & END_SESSION_FACTORY_RESET) { + CWMP_LOG(INFO, "Executing factory reset: end session request"); + cwmp_factory_reset(); + exit(EXIT_SUCCESS); + } + + if (end_session_flag & END_SESSION_X_FACTORY_RESET_SOFT) { + CWMP_LOG(INFO, "Executing factory reset soft: end session request"); + cwmp_factory_reset(); + exit(EXIT_SUCCESS); + } + + if (end_session_flag & END_SESSION_DOWNLOAD) { + CWMP_LOG(INFO, "Trigger Uloop Downaload Calls"); + struct list_head *ilist; + list_for_each (ilist, &(list_download)) { + struct download *download = list_entry(ilist, struct download, list); + int download_delay = 0; + if (download->scheduled_time > time(NULL)) { + download_delay = download->scheduled_time - time(NULL); } + uloop_timeout_set(&download->handler_timer, 1000 * download_delay); } - if (dup) { - continue; - } - ilist = ilist->prev; - list_del(&(rpc_acs->list)); - list_add_tail(&(rpc_acs->list), &(session_queue->head_rpc_acs)); } - cwmp_session_destructor(session); - pthread_mutex_unlock(&(cwmp->mutex_session_queue)); + + if (end_session_flag & END_SESSION_SCHEDULE_DOWNLOAD) { + CWMP_LOG(INFO, "Trigger Uloop ScheduleDownaload Calls"); + struct list_head *ilist; + list_for_each (ilist, &(list_schedule_download)) { + struct download *sched_download = list_entry(ilist, struct download, list); + time_t now = time(NULL); + int download_delay; + if (sched_download->timewindowstruct[0].windowstart > now) + download_delay = sched_download->timewindowstruct[0].windowstart - now; + else if (sched_download->timewindowstruct[0].windowend >= now) + download_delay = 1; + else if (now < sched_download->timewindowstruct[1].windowstart) + download_delay = sched_download->timewindowstruct[1].windowstart - now; + else if (sched_download->timewindowstruct[1].windowend >= now) + download_delay = 1; + else + download_delay = 1; + + uloop_timeout_set(&sched_download->handler_timer, 1000 * download_delay); + } + } + + if (end_session_flag & END_SESSION_UPLOAD) { + CWMP_LOG(INFO, "Trigger Uloop Upload Calls"); + struct list_head *ilist; + list_for_each (ilist, &(list_upload)) { + struct download *upload = list_entry(ilist, struct download, list); + int upload_delay = 0; + if (upload->scheduled_time > time(NULL)) { + upload_delay = upload->scheduled_time - time(NULL); + } + uloop_timeout_set(&upload->handler_timer, 1000 * upload_delay); + } + } + + end_session_flag = 0; return CWMP_OK; } diff --git a/rpc_soap.c b/soap.c similarity index 81% rename from rpc_soap.c rename to soap.c index c561770..7cb3585 100755 --- a/rpc_soap.c +++ b/soap.c @@ -12,25 +12,27 @@ * Copyright (C) 2011-2012 Luka Perkov * Copyright (C) 2012 Jonas Gorski */ +#include "soap.h" -#include "rpc_soap.h" -#include "download.h" -#include "cwmp_du_state.h" -#include "log.h" -#include "event.h" +#include + +#include "http.h" #include "cwmp_time.h" -#include "datamodel_interface.h" -#include "messages.h" -#include "event.h" -#include "xml.h" -#include "backupSession.h" +#include "cwmp_zlib.h" #include "notifications.h" +#include "messages.h" +#include "backupSession.h" +#include "log.h" +#include "datamodel_interface.h" +#include "cwmp_uci.h" +#include "diagnostic.h" +#include "ubus.h" +#include "cwmp_du_state.h" +#include "download.h" #include "upload.h" #include "sched_inform.h" -#include "diagnostic.h" +#include "cwmp_event.h" -#define PROCESSING_DELAY (1) // In download/upload the message enqueued before sending the response, which cause the download/upload - // to start just before the time. This delay is to compensate the time lapsed during the message enqueue and response #define DM_CONN_REQ_URL "Device.ManagementServer.ConnectionRequestURL" struct cwmp_namespaces ns; @@ -68,35 +70,33 @@ char *forced_inform_parameters[] = { "Device.RootDataModelVersion", "Device.DeviceInfo.HardwareVersion", "Device.DeviceInfo.SoftwareVersion", "Device.DeviceInfo.ProvisioningCode", "Device.ManagementServer.ParameterKey", DM_CONN_REQ_URL, "Device.ManagementServer.AliasBasedAddressing" }; -int xml_handle_message(struct session *session) +int xml_handle_message() { struct rpc *rpc_cpe; char *c; int i; mxml_node_t *b; - struct cwmp *cwmp = &cwmp_main; - struct config *conf; - conf = &(cwmp->conf); + struct config *conf = &(cwmp_main->conf); /* get method */ if (icwmp_asprintf(&c, "%s:%s", ns.soap_env, "Body") == -1) { CWMP_LOG(INFO, "Internal error"); - session->fault_code = FAULT_CPE_INTERNAL_ERROR; + cwmp_main->session->fault_code = FAULT_CPE_INTERNAL_ERROR; goto fault; } - b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (!b) { CWMP_LOG(INFO, "Invalid received message"); - session->fault_code = FAULT_CPE_REQUEST_DENIED; + cwmp_main->session->fault_code = FAULT_CPE_REQUEST_DENIED; goto fault; } - session->body_in = b; + cwmp_main->session->body_in = b; while (1) { - b = mxmlWalkNext(b, session->body_in, MXML_DESCEND_FIRST); + b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND_FIRST); if (!b) goto error; if (b->type == MXML_ELEMENT) @@ -111,20 +111,20 @@ int xml_handle_message(struct session *session) if (strlen(ns.cwmp) != ns_len) { CWMP_LOG(INFO, "Invalid received message"); - session->fault_code = FAULT_CPE_REQUEST_DENIED; + cwmp_main->session->fault_code = FAULT_CPE_REQUEST_DENIED; goto fault; } if (strncmp(ns.cwmp, c, ns_len)) { CWMP_LOG(INFO, "Invalid received message"); - session->fault_code = FAULT_CPE_REQUEST_DENIED; + cwmp_main->session->fault_code = FAULT_CPE_REQUEST_DENIED; goto fault; } c = tmp + 1; } else { CWMP_LOG(INFO, "Invalid received message"); - session->fault_code = FAULT_CPE_REQUEST_DENIED; + cwmp_main->session->fault_code = FAULT_CPE_REQUEST_DENIED; goto fault; } CWMP_LOG(INFO, "SOAP RPC message: %s", c); @@ -132,7 +132,7 @@ int xml_handle_message(struct session *session) for (i = 1; i < __RPC_CPE_MAX; i++) { if (i != RPC_CPE_FAULT && strcmp(c, rpc_cpe_methods[i].name) == 0 && rpc_cpe_methods[i].amd <= conf->amd_version) { CWMP_LOG(INFO, "%s RPC is supported", c); - rpc_cpe = cwmp_add_session_rpc_cpe(session, i); + rpc_cpe = cwmp_add_session_rpc_cpe(i); if (rpc_cpe == NULL) goto error; break; @@ -140,12 +140,12 @@ int xml_handle_message(struct session *session) } if (!rpc_cpe) { CWMP_LOG(INFO, "%s RPC is not supported", c); - session->fault_code = FAULT_CPE_METHOD_NOT_SUPPORTED; + cwmp_main->session->fault_code = FAULT_CPE_METHOD_NOT_SUPPORTED; goto fault; } return 0; fault: - rpc_cpe = cwmp_add_session_rpc_cpe(session, RPC_CPE_FAULT); + rpc_cpe = cwmp_add_session_rpc_cpe(RPC_CPE_FAULT); if (rpc_cpe == NULL) goto error; return 0; @@ -157,20 +157,19 @@ error: * [RPC ACS]: Inform */ -static int xml_prepare_events_inform(struct session *session, mxml_node_t *tree) +static int xml_prepare_events_inform(mxml_node_t *tree) { mxml_node_t *node, *b1, *b2; char c[128]; unsigned int n = 0; struct list_head *ilist; struct event_container *event_container; - struct cwmp *cwmp = &cwmp_main; b1 = mxmlFindElement(tree, tree, "Event", NULL, NULL, MXML_DESCEND); if (!b1) return -1; - list_for_each (ilist, &(session->head_event_container)) { + list_for_each (ilist, &(cwmp_main->session->events)) { event_container = list_entry(ilist, struct event_container, list); node = mxmlNewElement(b1, "EventStruct"); if (!node) @@ -179,7 +178,7 @@ static int xml_prepare_events_inform(struct session *session, mxml_node_t *tree) if (!b2) goto error; if (event_container->code == EVENT_IDX_0BOOTSTRAP || event_container->code == EVENT_IDX_1BOOT) - cwmp->is_boot = true; + cwmp_main->is_boot = true; b2 = mxmlNewOpaque(b2, EVENT_CONST[event_container->code].CODE); if (!b2) goto error; @@ -251,8 +250,7 @@ create_value: return 0; } -// cppcheck-suppress constParameter -int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *session, struct rpc *this) +int cwmp_rpc_acs_prepare_message_inform(struct rpc *this) { struct cwmp_dm_parameter *dm_parameter; struct event_container *event_container; @@ -261,7 +259,7 @@ int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *sessi int size = 0; struct list_head *ilist, *jlist; - if (session == NULL || this == NULL) + if (cwmp_main->session == NULL || this == NULL) return -1; tree = mxmlLoadString(NULL, CWMP_INFORM_MESSAGE, MXML_OPAQUE_CALLBACK); @@ -271,8 +269,8 @@ int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *sessi b = mxmlFindElement(tree, tree, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); if (!b) goto error; - mxmlElementSetAttr(b, "xmlns:cwmp", cwmp_urls[(cwmp->conf.supported_amd_version) - 1]); - if (cwmp->conf.supported_amd_version >= 4) { + mxmlElementSetAttr(b, "xmlns:cwmp", cwmp_urls[(cwmp_main->conf.supported_amd_version) - 1]); + if (cwmp_main->conf.supported_amd_version >= 4) { b = mxmlFindElement(tree, tree, "soap_env:Header", NULL, NULL, MXML_DESCEND); if (!b) goto error; @@ -280,16 +278,16 @@ int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *sessi if (!node) goto error; mxmlElementSetAttr(node, "soap_env:mustUnderstand", "0"); - node = mxmlNewInteger(node, cwmp->conf.session_timeout); + node = mxmlNewInteger(node, cwmp_main->conf.session_timeout); if (!node) goto error; } - if (cwmp->conf.supported_amd_version >= 5) { + if (cwmp_main->conf.supported_amd_version >= 5) { node = mxmlNewElement(b, "cwmp:SupportedCWMPVersions"); if (!node) goto error; mxmlElementSetAttr(node, "soap_env:mustUnderstand", "0"); - node = mxmlNewOpaque(node, xml_get_cwmp_version(cwmp->conf.supported_amd_version)); + node = mxmlNewOpaque(node, xml_get_cwmp_version(cwmp_main->conf.supported_amd_version)); if (!node) goto error; } @@ -297,12 +295,12 @@ int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *sessi if (!b) goto error; - b = mxmlNewInteger(b, cwmp->retry_count_session); + b = mxmlNewInteger(b, cwmp_main->retry_count_session); if (!b) goto error; - cwmp->is_boot = false; - if (xml_prepare_events_inform(session, tree)) + cwmp_main->is_boot = false; + if (xml_prepare_events_inform(tree)) goto error; b = mxmlFindElement(tree, tree, "CurrentTime", NULL, NULL, MXML_DESCEND); @@ -317,7 +315,7 @@ int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *sessi if (!parameter_list) goto error; - list_for_each (ilist, &(session->head_event_container)) { + list_for_each (ilist, &(cwmp_main->session->events)) { event_container = list_entry(ilist, struct event_container, list); list_for_each (jlist, &(event_container->head_dm_parameter)) { dm_parameter = list_entry(jlist, struct cwmp_dm_parameter, list); @@ -329,28 +327,28 @@ int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *sessi b = mxmlFindElement(tree, tree, "OUI", NULL, NULL, MXML_DESCEND); if (!b) goto error; - b = mxmlNewOpaque(b, cwmp->deviceid.oui ? cwmp->deviceid.oui : ""); + b = mxmlNewOpaque(b, cwmp_main->deviceid.oui ? cwmp_main->deviceid.oui : ""); if (!b) goto error; b = mxmlFindElement(tree, tree, "Manufacturer", NULL, NULL, MXML_DESCEND); if (!b) goto error; - b = mxmlNewOpaque(b, cwmp->deviceid.manufacturer ? cwmp->deviceid.manufacturer : ""); + b = mxmlNewOpaque(b, cwmp_main->deviceid.manufacturer ? cwmp_main->deviceid.manufacturer : ""); if (!b) goto error; b = mxmlFindElement(tree, tree, "ProductClass", NULL, NULL, MXML_DESCEND); if (!b) goto error; - b = mxmlNewOpaque(b, cwmp->deviceid.productclass ? cwmp->deviceid.productclass : ""); + b = mxmlNewOpaque(b, cwmp_main->deviceid.productclass ? cwmp_main->deviceid.productclass : ""); if (!b) goto error; b = mxmlFindElement(tree, tree, "SerialNumber", NULL, NULL, MXML_DESCEND); if (!b) goto error; - b = mxmlNewOpaque(b, cwmp->deviceid.serialnumber ? cwmp->deviceid.serialnumber : ""); + b = mxmlNewOpaque(b, cwmp_main->deviceid.serialnumber ? cwmp_main->deviceid.serialnumber : ""); if (!b) goto error; @@ -380,7 +378,7 @@ int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *sessi if (xml_prepare_parameters_inform(&cwmp_dm_param, parameter_list, &size)) goto error; } - if (cwmp->is_boot == true) { + if (cwmp_main->is_boot == true) { for (j = 0; j < nbre_boot_inform; j++) { char *fault = cwmp_get_single_parameter_value(boot_inform_parameters[j], &cwmp_dm_param); if (fault != NULL) @@ -395,7 +393,7 @@ int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *sessi mxmlElementSetAttr(parameter_list, "xsi:type", "soap_enc:Array"); mxmlElementSetAttr(parameter_list, "soap_enc:arrayType", c); - session->tree_out = tree; + cwmp_main->session->tree_out = tree; return 0; @@ -404,14 +402,14 @@ error: return -1; } -int cwmp_rpc_acs_parse_response_inform(struct cwmp *cwmp, struct session *session, struct rpc *this __attribute__((unused))) +int cwmp_rpc_acs_parse_response_inform(struct rpc *this __attribute__((unused))) { mxml_node_t *tree, *b; int i = -1; char *c; const char *cwmp_urn; - tree = session->tree_in; + tree = cwmp_main->session->tree_in; if (!tree) goto error; b = mxmlFindElement(tree, tree, "MaxEnvelopes", NULL, NULL, MXML_DESCEND); @@ -420,19 +418,19 @@ int cwmp_rpc_acs_parse_response_inform(struct cwmp *cwmp, struct session *sessio b = mxmlWalkNext(b, tree, MXML_DESCEND_FIRST); if (!b || b->type != MXML_OPAQUE || !b->value.opaque) goto error; - if (cwmp->conf.supported_amd_version == 1) { - cwmp->conf.amd_version = 1; + if (cwmp_main->conf.supported_amd_version == 1) { + cwmp_main->conf.amd_version = 1; return 0; } b = mxmlFindElement(tree, tree, "UseCWMPVersion", NULL, NULL, MXML_DESCEND); - if (b && cwmp->conf.supported_amd_version >= 5) { //IF supported version !=5 acs response dosen't contain UseCWMPVersion + if (b && cwmp_main->conf.supported_amd_version >= 5) { //IF supported version !=5 acs response dosen't contain UseCWMPVersion b = mxmlWalkNext(b, tree, MXML_DESCEND_FIRST); if (!b || b->type != MXML_OPAQUE || !b->value.opaque) goto error; c = (char *)(b->value.opaque); if (c && *(c + 1) == '.') { c += 2; - cwmp->conf.amd_version = atoi(c) + 1; + cwmp_main->conf.amd_version = atoi(c) + 1; return 0; } goto error; @@ -445,28 +443,28 @@ int cwmp_rpc_acs_parse_response_inform(struct cwmp *cwmp, struct session *sessio } } if (i == 0) { - cwmp->conf.amd_version = i + 1; + cwmp_main->conf.amd_version = i + 1; } else if (i >= 1 && i <= 3) { - switch (cwmp->conf.supported_amd_version) { + switch (cwmp_main->conf.supported_amd_version) { case 1: - cwmp->conf.amd_version = 1; //Already done + cwmp_main->conf.amd_version = 1; //Already done break; case 2: case 3: case 4: //MIN ACS CPE - if (cwmp->conf.supported_amd_version <= i + 1) - cwmp->conf.amd_version = cwmp->conf.supported_amd_version; + if (cwmp_main->conf.supported_amd_version <= i + 1) + cwmp_main->conf.amd_version = cwmp_main->conf.supported_amd_version; else - cwmp->conf.amd_version = i + 1; + cwmp_main->conf.amd_version = i + 1; break; - //(cwmp->supported_conf.amd_version < i+1) ?"cwmp->conf.amd_version":"i+1"; + //(cwmp_main->supported_conf.amd_version < i+1) ?"cwmp_main->conf.amd_version":"i+1"; case 5: - cwmp->conf.amd_version = i + 1; + cwmp_main->conf.amd_version = i + 1; break; } } else if (i >= 4) { - cwmp->conf.amd_version = cwmp->conf.supported_amd_version; + cwmp_main->conf.amd_version = cwmp_main->conf.supported_amd_version; } return 0; @@ -474,9 +472,9 @@ error: return -1; } -int cwmp_rpc_acs_destroy_data_inform(struct session *session __attribute__((unused)), struct rpc *rpc __attribute__((unused))) +int cwmp_rpc_acs_destroy_data_inform(struct rpc *rpc __attribute__((unused))) { - //event_remove_all_event_container(session,RPC_SEND); + //event_remove_all_event_container(RPC_SEND); return 0; } @@ -484,7 +482,7 @@ int cwmp_rpc_acs_destroy_data_inform(struct session *session __attribute__((unus * [RPC ACS]: GetRPCMethods */ -int cwmp_rpc_acs_prepare_get_rpc_methods(struct cwmp *cwmp, struct session *session, struct rpc *rpc __attribute__((unused))) +int cwmp_rpc_acs_prepare_get_rpc_methods(struct rpc *rpc __attribute__((unused))) { mxml_node_t *tree, *n; @@ -493,7 +491,7 @@ int cwmp_rpc_acs_prepare_get_rpc_methods(struct cwmp *cwmp, struct session *sess n = mxmlFindElement(tree, tree, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); if (!n) return -1; - mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp->conf.amd_version) - 1]); + mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp_main->conf.amd_version) - 1]); n = mxmlFindElement(tree, tree, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!n) return -1; @@ -502,16 +500,16 @@ int cwmp_rpc_acs_prepare_get_rpc_methods(struct cwmp *cwmp, struct session *sess if (!n) return -1; - session->tree_out = tree; + cwmp_main->session->tree_out = tree; return 0; } -int cwmp_rpc_acs_parse_response_get_rpc_methods(struct session *session) +int cwmp_rpc_acs_parse_response_get_rpc_methods() { mxml_node_t *tree, *b; - tree = session->tree_in; + tree = cwmp_main->session->tree_in; if (!tree) goto error; b = mxmlFindElement(tree, tree, "MethodList", NULL, NULL, MXML_DESCEND); @@ -530,17 +528,16 @@ error: * [RPC ACS]: TransferComplete */ -int cwmp_rpc_acs_prepare_transfer_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc) +int cwmp_rpc_acs_prepare_transfer_complete(struct rpc *rpc) { mxml_node_t *tree, *n; struct transfer_complete *p; - p = (struct transfer_complete *)rpc->extra_data; tree = mxmlLoadString(NULL, CWMP_RESPONSE_MESSAGE, MXML_OPAQUE_CALLBACK); n = mxmlFindElement(tree, tree, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); if (!n) goto error; - mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp->conf.amd_version) - 1]); + mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp_main->conf.amd_version) - 1]); n = mxmlFindElement(tree, tree, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!n) @@ -598,7 +595,7 @@ int cwmp_rpc_acs_prepare_transfer_complete(struct cwmp *cwmp, struct session *se if (!n) goto error; - session->tree_out = tree; + cwmp_main->session->tree_out = tree; return 0; @@ -610,7 +607,7 @@ error: * [RPC ACS]: DUStateChangeComplete */ -int cwmp_rpc_acs_prepare_du_state_change_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc) +int cwmp_rpc_acs_prepare_du_state_change_complete(struct rpc *rpc) { mxml_node_t *tree, *n, *b, *t; struct du_state_change_complete *p; @@ -623,7 +620,7 @@ int cwmp_rpc_acs_prepare_du_state_change_complete(struct cwmp *cwmp, struct sess if (!n) goto error; - mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp->conf.amd_version) - 1]); + mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp_main->conf.amd_version) - 1]); n = mxmlFindElement(tree, tree, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!n) goto error; @@ -730,7 +727,7 @@ int cwmp_rpc_acs_prepare_du_state_change_complete(struct cwmp *cwmp, struct sess if (!b) goto error; } - session->tree_out = tree; + cwmp_main->session->tree_out = tree; return 0; error: @@ -741,7 +738,7 @@ error: * [RPC CPE]: GetParameterValues */ -int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_get_parameter_values(struct rpc *rpc) { mxml_node_t *n, *parameter_list, *b; char *parameter_name = NULL; @@ -750,8 +747,8 @@ int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc char c[256]; #endif - b = session->body_in; - n = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + b = cwmp_main->session->body_in; + n = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!n) goto fault; @@ -780,7 +777,7 @@ int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc fault_code = cwmp_get_fault_code_by_string(err); goto fault; } - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, ¶meters_list, list) { n = mxmlNewElement(parameter_list, "ParameterValueStruct"); if (!n) @@ -811,12 +808,12 @@ int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc } cwmp_free_all_dm_parameter_list(¶meters_list); } - b = mxmlWalkNext(b, session->body_in, MXML_DESCEND); + b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND); parameter_name = NULL; } #ifdef ACS_MULTI - b = mxmlFindElement(session->tree_out, session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -830,7 +827,7 @@ int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc fault: cwmp_free_all_dm_parameter_list(¶meters_list); - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) goto error; return 0; @@ -841,9 +838,9 @@ error: /* * [RPC CPE]: GetParameterNames */ -int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_get_parameter_names(struct rpc *rpc) { - mxml_node_t *n, *parameter_list, *b = session->body_in; + mxml_node_t *n, *parameter_list, *b = cwmp_main->session->body_in; char *parameter_name = NULL; char *NextLevel = NULL; int counter = 0, fault_code = FAULT_CPE_INTERNAL_ERROR; @@ -851,7 +848,7 @@ int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc #ifdef ACS_MULTI char c[256]; #endif - n = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!n) goto fault; @@ -877,7 +874,7 @@ int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "NextLevel")) { NextLevel = b->value.opaque; } - b = mxmlWalkNext(b, session->body_in, MXML_DESCEND); + b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND); } if (!icwmp_validate_boolean_value(NextLevel)) { @@ -892,7 +889,7 @@ int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc goto fault; } } - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, ¶meters_list, list) { n = mxmlNewElement(parameter_list, "ParameterInfoStruct"); if (!n) @@ -919,7 +916,7 @@ int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc } cwmp_free_all_dm_parameter_list(¶meters_list); #ifdef ACS_MULTI - b = mxmlFindElement(session->tree_out, session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -932,7 +929,7 @@ int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc fault: cwmp_free_all_dm_parameter_list(¶meters_list); - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) goto error; return 0; @@ -944,7 +941,7 @@ error: * [RPC CPE]: GetParameterAttributes */ -int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_get_parameter_attributes(struct rpc *rpc) { mxml_node_t *n, *parameter_list, *b; char *parameter_name = NULL; @@ -953,8 +950,8 @@ int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct #ifdef ACS_MULTI char c[256]; #endif - b = session->body_in; - n = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + b = cwmp_main->session->body_in; + n = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!n) goto fault; @@ -983,7 +980,7 @@ int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct fault_code = cwmp_get_fault_code_by_string(err); goto fault; } - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, ¶meters_list, list) { n = mxmlNewElement(parameter_list, "ParameterAttributeStruct"); if (!n) @@ -1003,7 +1000,8 @@ int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct goto fault; char notification[2]; - snprintf(notification, sizeof(notification), "%d", param_value->notification); + sprintf(notification, "%d", param_value->notification); + notification[1] = '\0'; n = mxmlNewOpaque(n, notification); if (!n) goto fault; @@ -1021,11 +1019,11 @@ int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct } cwmp_free_all_dm_parameter_list(¶meters_list); } - b = mxmlWalkNext(b, session->body_in, MXML_DESCEND); + b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND); parameter_name = NULL; } #ifdef ACS_MULTI - b = mxmlFindElement(session->tree_out, session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -1038,7 +1036,7 @@ int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct fault: cwmp_free_all_dm_parameter_list(¶meters_list); - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) goto error; return 0; @@ -1050,10 +1048,10 @@ error: * [RPC CPE]: SetParameterValues */ -static int is_duplicated_parameter(mxml_node_t *param_node, struct session *session) +static int is_duplicated_parameter(mxml_node_t *param_node) { mxml_node_t *b = param_node; - while ((b = mxmlWalkNext(b, session->body_in, MXML_DESCEND))) { + while ((b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND))) { if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "Name")) { if (strcmp(b->value.opaque, param_node->value.opaque) == 0) return -1; @@ -1062,7 +1060,7 @@ static int is_duplicated_parameter(mxml_node_t *param_node, struct session *sess return 0; } -int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_set_parameter_values(struct rpc *rpc) { mxml_node_t *b, *n; char *parameter_name = NULL; @@ -1071,30 +1069,29 @@ int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc char *v, *c = NULL; int fault_code = FAULT_CPE_INTERNAL_ERROR, ret = 0; - b = mxmlFindElement(session->body_in, session->body_in, "ParameterList", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->body_in, cwmp_main->session->body_in, "ParameterList", NULL, NULL, MXML_DESCEND); if (!b) { fault_code = FAULT_CPE_REQUEST_DENIED; goto fault; } LIST_HEAD(list_fault_param); - // cppcheck-suppress autoVariables rpc->list_set_value_fault = &list_fault_param; LIST_HEAD(list_set_param_value); while (b) { if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "Name")) { parameter_name = icwmp_strdup(b->value.opaque); - if (is_duplicated_parameter(b, session)) { + if (is_duplicated_parameter(b)) { fault_code = FAULT_CPE_INVALID_ARGUMENTS; goto fault; } } - if (b->type == MXML_ELEMENT && !strcmp(b->value.element.name, "Name") && !b->child) { + if (b && b->type == MXML_ELEMENT && !strcmp(b->value.element.name, "Name") && !b->child) { parameter_name = icwmp_strdup(""); } - if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "Value")) { + if (b && b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "Value")) { parameter_value = icwmp_strdup((char *)mxmlGetOpaque(b)); n = b->parent; while ((b = mxmlWalkNext(b, n, MXML_DESCEND))) { @@ -1104,21 +1101,21 @@ int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc } b = n->last_child; } - if (b->type == MXML_ELEMENT && !strcmp(b->value.element.name, "Value") && !b->child) { + if (b && b->type == MXML_ELEMENT && !strcmp(b->value.element.name, "Value") && !b->child) { parameter_value = icwmp_strdup(""); } if (parameter_name && parameter_value) { add_dm_parameter_to_list(&list_set_param_value, parameter_name, parameter_value, NULL, 0, false); } - b = mxmlWalkNext(b, session->body_in, MXML_DESCEND); + b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND); } - b = mxmlFindElement(session->body_in, session->body_in, "ParameterKey", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->body_in, cwmp_main->session->body_in, "ParameterKey", NULL, NULL, MXML_DESCEND); if (!b) { fault_code = FAULT_CPE_REQUEST_DENIED; goto fault; } - b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST); + b = mxmlWalkNext(b, cwmp_main->session->tree_in, MXML_DESCEND_FIRST); if (b && b->type == MXML_OPAQUE && b->value.opaque) parameter_key = b->value.opaque; @@ -1137,12 +1134,13 @@ int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc goto fault; struct cwmp_dm_parameter *param_value; - list_for_each_entry (param_value, &list_set_param_value, list) + list_for_each_entry (param_value, &list_set_param_value, list) { set_diagnostic_parameter_structure_value(param_value->name, param_value->value); + } cwmp_free_all_dm_parameter_list(&list_set_param_value); - b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -1166,7 +1164,7 @@ int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc fault: cwmp_free_all_dm_parameter_list(&list_set_param_value); - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) ret = CWMP_XML_ERR; cwmp_free_all_list_param_fault(rpc->list_set_value_fault); @@ -1181,9 +1179,9 @@ fault: * [RPC CPE]: SetParameterAttributes */ -int cwmp_handle_rpc_cpe_set_parameter_attributes(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_set_parameter_attributes(struct rpc *rpc) { - mxml_node_t *n, *b = session->body_in; + mxml_node_t *n, *b = cwmp_main->session->body_in; char *parameter_name = NULL, *parameter_notification = NULL; int fault_code = FAULT_CPE_INTERNAL_ERROR, ret = 0; char *notification_change = NULL; @@ -1193,7 +1191,7 @@ int cwmp_handle_rpc_cpe_set_parameter_attributes(struct session *session, struct if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "SetParameterAttributes") == -1) goto fault; - n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (!n) goto fault; @@ -1243,7 +1241,7 @@ int cwmp_handle_rpc_cpe_set_parameter_attributes(struct session *session, struct b = mxmlWalkNext(b, n, MXML_DESCEND); } - b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -1255,7 +1253,7 @@ int cwmp_handle_rpc_cpe_set_parameter_attributes(struct session *session, struct return 0; fault: - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) ret = CWMP_XML_ERR; return ret; @@ -1265,7 +1263,7 @@ fault: * [RPC CPE]: AddObject */ -int cwmp_handle_rpc_cpe_add_object(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_add_object(struct rpc *rpc) { mxml_node_t *b; char *object_name = NULL; @@ -1273,7 +1271,7 @@ int cwmp_handle_rpc_cpe_add_object(struct session *session, struct rpc *rpc) int fault_code = FAULT_CPE_INTERNAL_ERROR, ret = 0; char *instance = NULL; - b = session->body_in; + b = cwmp_main->session->body_in; while (b) { if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "ParameterKey")) { parameter_key = b->value.opaque; @@ -1281,7 +1279,7 @@ int cwmp_handle_rpc_cpe_add_object(struct session *session, struct rpc *rpc) if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "ObjectName")) { object_name = b->value.opaque; } - b = mxmlWalkNext(b, session->body_in, MXML_DESCEND); + b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND); } if (!icwmp_validate_string_length(parameter_key, 32)) { @@ -1304,7 +1302,7 @@ int cwmp_handle_rpc_cpe_add_object(struct session *session, struct rpc *rpc) goto fault; } - b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -1341,7 +1339,7 @@ int cwmp_handle_rpc_cpe_add_object(struct session *session, struct rpc *rpc) fault: FREE(instance); - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) ret = CWMP_XML_ERR; if (transaction_id) { cwmp_transaction_abort(); @@ -1354,14 +1352,14 @@ fault: * [RPC CPE]: DeleteObject */ -int cwmp_handle_rpc_cpe_delete_object(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_delete_object(struct rpc *rpc) { mxml_node_t *b; char *object_name = NULL; char *parameter_key = NULL; int fault_code = FAULT_CPE_INTERNAL_ERROR, ret = 0; - b = session->body_in; + b = cwmp_main->session->body_in; while (b) { if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "ObjectName")) { object_name = b->value.opaque; @@ -1369,7 +1367,7 @@ int cwmp_handle_rpc_cpe_delete_object(struct session *session, struct rpc *rpc) if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "ParameterKey")) { parameter_key = b->value.opaque; } - b = mxmlWalkNext(b, session->body_in, MXML_DESCEND); + b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND); } if (!icwmp_validate_string_length(parameter_key, 32)) { fault_code = FAULT_CPE_INVALID_ARGUMENTS; @@ -1390,7 +1388,7 @@ int cwmp_handle_rpc_cpe_delete_object(struct session *session, struct rpc *rpc) goto fault; } - b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -1413,7 +1411,7 @@ int cwmp_handle_rpc_cpe_delete_object(struct session *session, struct rpc *rpc) return 0; fault: - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) ret = CWMP_XML_ERR; if (transaction_id) { cwmp_transaction_abort(); @@ -1426,16 +1424,16 @@ fault: * [RPC CPE]: GetRPCMethods */ -int cwmp_handle_rpc_cpe_get_rpc_methods(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_get_rpc_methods(struct rpc *rpc) { mxml_node_t *n, *method_list; int i, counter = 0; #ifdef ACS_MULTI - mxml_node_t *b = session->body_in; + mxml_node_t *b = cwmp_main->session->body_in; char c[128]; #endif - n = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!n) goto fault; @@ -1461,7 +1459,7 @@ int cwmp_handle_rpc_cpe_get_rpc_methods(struct session *session, struct rpc *rpc } } #ifdef ACS_MULTI - b = mxmlFindElement(session->tree_out, session->tree_out, "MethodList", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "MethodList", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -1475,7 +1473,7 @@ int cwmp_handle_rpc_cpe_get_rpc_methods(struct session *session, struct rpc *rpc return 0; fault: - if (cwmp_create_fault_message(session, rpc, FAULT_CPE_INTERNAL_ERROR)) + if (cwmp_create_fault_message(rpc, FAULT_CPE_INTERNAL_ERROR)) goto error; return 0; @@ -1487,11 +1485,11 @@ error: * [RPC CPE]: FactoryReset */ -int cwmp_handle_rpc_cpe_factory_reset(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_factory_reset(struct rpc *rpc) { mxml_node_t *b; - b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -1504,7 +1502,7 @@ int cwmp_handle_rpc_cpe_factory_reset(struct session *session, struct rpc *rpc) return 0; fault: - if (cwmp_create_fault_message(session, rpc, FAULT_CPE_INTERNAL_ERROR)) + if (cwmp_create_fault_message(rpc, FAULT_CPE_INTERNAL_ERROR)) goto error; return 0; @@ -1516,11 +1514,11 @@ error: * [RPC CPE]: X_FactoryResetSoft */ -int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct rpc *rpc) { mxml_node_t *b; - b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -1533,7 +1531,7 @@ int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct session *session, struct rpc return 0; fault: - if (cwmp_create_fault_message(session, rpc, FAULT_CPE_INTERNAL_ERROR)) + if (cwmp_create_fault_message(rpc, FAULT_CPE_INTERNAL_ERROR)) goto error; return 0; @@ -1545,18 +1543,18 @@ error: * [RPC CPE]: CancelTransfer */ -int cwmp_handle_rpc_cpe_cancel_transfer(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_cancel_transfer(struct rpc *rpc) { mxml_node_t *b; char *command_key = NULL; int fault_code = FAULT_CPE_INTERNAL_ERROR; - b = session->body_in; + b = cwmp_main->session->body_in; while (b) { if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "CommandKey")) { command_key = b->value.opaque; } - b = mxmlWalkNext(b, session->body_in, MXML_DESCEND); + b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND); } if (!icwmp_validate_string_length(command_key, 32)) { fault_code = FAULT_CPE_INVALID_ARGUMENTS; @@ -1565,7 +1563,7 @@ int cwmp_handle_rpc_cpe_cancel_transfer(struct session *session, struct rpc *rpc if (command_key) { cancel_transfer(command_key); } - b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -1574,7 +1572,7 @@ int cwmp_handle_rpc_cpe_cancel_transfer(struct session *session, struct rpc *rpc goto fault; return 0; fault: - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) goto error; return 0; @@ -1607,7 +1605,7 @@ int cancel_transfer(char *key) if (strcmp(pupload->command_key, key) == 0) { pthread_mutex_lock(&mutex_upload); bkp_session_delete_upload(pupload); - bkp_session_save(); + bkp_session_save(); //is it needed list_del(&(pupload->list)); if (pupload->scheduled_time != 0) count_download_queue--; @@ -1624,35 +1622,32 @@ int cancel_transfer(char *key) * [RPC CPE]: Reboot */ -int cwmp_handle_rpc_cpe_reboot(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_reboot(struct rpc *rpc) { mxml_node_t *b; struct event_container *event_container; char *command_key = NULL; int fault_code = FAULT_CPE_INTERNAL_ERROR; - b = session->body_in; + b = cwmp_main->session->body_in; while (b) { if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "CommandKey")) { command_key = b->value.opaque; commandKey = icwmp_strdup(b->value.opaque); } - b = mxmlWalkNext(b, session->body_in, MXML_DESCEND); + b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND); } if (!icwmp_validate_string_length(commandKey, 32)) { fault_code = FAULT_CPE_INVALID_ARGUMENTS; goto fault; } - pthread_mutex_lock(&(cwmp_main.mutex_session_queue)); - event_container = cwmp_add_event_container(&cwmp_main, EVENT_IDX_M_Reboot, command_key); + event_container = cwmp_add_event_container(EVENT_IDX_M_Reboot, command_key); if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); goto fault; } cwmp_save_event_container(event_container); - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); - b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!b) goto fault; @@ -1665,7 +1660,7 @@ int cwmp_handle_rpc_cpe_reboot(struct session *session, struct rpc *rpc) return 0; fault: - if (cwmp_create_fault_message(session, rpc, fault_code)) + if (cwmp_create_fault_message(rpc, fault_code)) goto error; return 0; @@ -1677,9 +1672,9 @@ error: * [RPC CPE]: ScheduleInform */ -int cwmp_handle_rpc_cpe_schedule_inform(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_schedule_inform(struct rpc *rpc) { - mxml_node_t *n, *b = session->body_in; + mxml_node_t *n, *b = cwmp_main->session->body_in; char *command_key = NULL; struct schedule_inform *schedule_inform; time_t scheduled_time; @@ -1697,7 +1692,7 @@ int cwmp_handle_rpc_cpe_schedule_inform(struct session *session, struct rpc *rpc if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "DelaySeconds")) { delay_seconds = atoi(b->value.opaque); } - b = mxmlWalkNext(b, session->body_in, MXML_DESCEND); + b = mxmlWalkNext(b, cwmp_main->session->body_in, MXML_DESCEND); } if (!icwmp_validate_string_length(command_key, 32)) { fault = FAULT_CPE_INVALID_ARGUMENTS; @@ -1725,7 +1720,7 @@ int cwmp_handle_rpc_cpe_schedule_inform(struct session *session, struct rpc *rpc } } - n = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!n) goto fault; @@ -1751,7 +1746,7 @@ success: return 0; fault: - if (cwmp_create_fault_message(session, rpc, fault ? fault : FAULT_CPE_INTERNAL_ERROR)) + if (cwmp_create_fault_message(rpc, fault ? fault : FAULT_CPE_INTERNAL_ERROR)) goto error; goto success; @@ -1762,9 +1757,9 @@ error: /* * [RPC CPE]: ChangeDuState */ -int cwmp_handle_rpc_cpe_change_du_state(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_change_du_state(struct rpc *rpc) { - mxml_node_t *n, *t, *b = session->body_in; + mxml_node_t *n, *t, *b = cwmp_main->session->body_in; struct change_du_state *change_du_state = NULL; struct operations *elem = NULL; int error = FAULT_CPE_NO_FAULT; @@ -1775,7 +1770,7 @@ int cwmp_handle_rpc_cpe_change_du_state(struct session *session, struct rpc *rpc goto fault; } - n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (!n) return -1; @@ -1861,7 +1856,7 @@ int cwmp_handle_rpc_cpe_change_du_state(struct session *session, struct rpc *rpc } } } - if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "CommandKey")) { + if (b && b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "CommandKey")) { change_du_state->command_key = strdup(b->value.opaque); } b = mxmlWalkNext(b, n, MXML_DESCEND); @@ -1870,7 +1865,7 @@ int cwmp_handle_rpc_cpe_change_du_state(struct session *session, struct rpc *rpc error = FAULT_CPE_INVALID_ARGUMENTS; goto fault; } - t = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + t = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!t) goto fault; @@ -1890,7 +1885,7 @@ int cwmp_handle_rpc_cpe_change_du_state(struct session *session, struct rpc *rpc fault: cwmp_free_change_du_state_request(change_du_state); - if (cwmp_create_fault_message(session, rpc, error)) + if (cwmp_create_fault_message(rpc, error)) goto error; return 0; @@ -1941,9 +1936,9 @@ int create_download_upload_response(mxml_node_t *tree_out, enum load_type ltype) /* * [RPC CPE]: Download */ -int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_download(struct rpc *rpc) { - mxml_node_t *n, *b = session->body_in; + mxml_node_t *n, *b = cwmp_main->session->body_in; char c[256], *tmp, *file_type = NULL; int error = FAULT_CPE_NO_FAULT; struct download *download = NULL, *idownload; @@ -1957,7 +1952,7 @@ int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc) goto fault; } - n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (!n) return -1; @@ -2047,7 +2042,7 @@ int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc) if (error != FAULT_CPE_NO_FAULT) goto fault; - if (create_download_upload_response(session->tree_out, TYPE_DOWNLOAD) != FAULT_CPE_NO_FAULT) { + if (create_download_upload_response(cwmp_main->session->tree_out, TYPE_DOWNLOAD) != FAULT_CPE_NO_FAULT) { error = FAULT_CPE_INTERNAL_ERROR; goto fault; } @@ -2068,6 +2063,7 @@ int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc) count_download_queue++; download->scheduled_time = scheduled_time; } + download->handler_timer.cb = cwmp_start_download; bkp_session_insert_download(download); bkp_session_save(); if (download_delay != 0) { @@ -2075,16 +2071,16 @@ int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc) } else { CWMP_LOG(INFO, "Download will start at the end of session"); } - + cwmp_set_end_session(END_SESSION_DOWNLOAD); pthread_mutex_unlock(&mutex_download); - pthread_cond_signal(&threshold_download); + } return 0; fault: cwmp_free_download_request(download); - if (cwmp_create_fault_message(session, rpc, error)) + if (cwmp_create_fault_message(rpc, error)) return -1; return 0; } @@ -2092,9 +2088,9 @@ fault: /* * [RPC CPE]: ScheduleDownload */ -int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_schedule_download(struct rpc *rpc) { - mxml_node_t *n, *t, *b = session->body_in; + mxml_node_t *n, *t, *b = cwmp_main->session->body_in; char c[256], *tmp, *file_type = NULL; char *windowmode0 = NULL, *windowmode1 = NULL, *str_file_size = NULL; int i = 0, j = 0; @@ -2107,7 +2103,7 @@ int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *r goto fault; } - n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (!n) return -1; @@ -2243,7 +2239,7 @@ int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *r if (error != FAULT_CPE_NO_FAULT) goto fault; - t = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + t = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); if (!t) goto fault; @@ -2251,31 +2247,37 @@ int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *r if (!t) goto fault; - pthread_mutex_lock(&mutex_schedule_download); - list_add_tail(&(schedule_download->list), &(list_schedule_download)); - if (schedule_download_delay[0] != 0) { - count_download_queue++; + if (error == FAULT_CPE_NO_FAULT) { + list_add_tail(&(schedule_download->list), &(list_schedule_download)); + if (schedule_download_delay[0] != 0) { + count_download_queue++; + } + while (i > 0) { + i--; + schedule_download->timewindowstruct[i].windowstart = time(NULL) + schedule_download_delay[i * 2]; + schedule_download->timewindowstruct[i].windowend = time(NULL) + schedule_download_delay[i * 2 + 1]; + } + schedule_download->handler_timer.cb = cwmp_start_schedule_download; + bkp_session_insert_schedule_download(schedule_download); + bkp_session_save(); + if (schedule_download_delay[0] != 0) { + CWMP_LOG(INFO, "Schedule download will start in %us", schedule_download_delay[0]); + } else { + CWMP_LOG(INFO, "Schedule Download will start at the end of session"); + } + time_t now = time(NULL); + if ((schedule_download->timewindowstruct[0].windowstart < now) ||(schedule_download->timewindowstruct[0].windowend < now && (now < schedule_download->timewindowstruct[1].windowstart || schedule_download->timewindowstruct[1].windowend < now) )) { + error = FAULT_CPE_INTERNAL_ERROR; + goto fault; + } + cwmp_set_end_session(END_SESSION_SCHEDULE_DOWNLOAD); } - while (i > 0) { - i--; - schedule_download->timewindowstruct[i].windowstart = time(NULL) + schedule_download_delay[i * 2]; - schedule_download->timewindowstruct[i].windowend = time(NULL) + schedule_download_delay[i * 2 + 1]; - } - bkp_session_insert_schedule_download(schedule_download); - bkp_session_save(); - if (schedule_download_delay[0] != 0) { - CWMP_LOG(INFO, "Schedule download will start in %us", schedule_download_delay[0]); - } else { - CWMP_LOG(INFO, "Schedule Download will start at the end of session"); - } - pthread_mutex_unlock(&mutex_schedule_download); - pthread_cond_signal(&threshold_schedule_download); return 0; fault: cwmp_free_schedule_download_request(schedule_download); - if (cwmp_create_fault_message(session, rpc, error)) + if (cwmp_create_fault_message(rpc, error)) goto error; return 0; @@ -2286,9 +2288,9 @@ error: /* * [RPC CPE]: Upload */ -int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_upload(struct rpc *rpc) { - mxml_node_t *n, *b = session->body_in; + mxml_node_t *n, *b = cwmp_main->session->body_in; char *tmp, *file_type = NULL; int error = FAULT_CPE_NO_FAULT; struct upload *upload = NULL, *iupload; @@ -2303,7 +2305,7 @@ int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc) goto fault; } - n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (!n) return -1; @@ -2334,16 +2336,16 @@ int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc) } } } - if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "URL")) { + if (b && b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "URL")) { upload->url = strdup(b->value.opaque); } - if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "Username")) { + if (b && b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "Username")) { upload->username = strdup(b->value.opaque); } - if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "Password")) { + if (b && b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "Password")) { upload->password = strdup(b->value.opaque); } - if (b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "DelaySeconds")) { + if (b && b->type == MXML_OPAQUE && b->value.opaque && b->parent->type == MXML_ELEMENT && !strcmp(b->parent->value.element.name, "DelaySeconds")) { str_upload_delay = strdup(b->value.opaque); upload_delay = atol(b->value.opaque); } @@ -2390,7 +2392,7 @@ int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc) goto fault; } - if (create_download_upload_response(session->tree_out, TYPE_UPLOAD) != FAULT_CPE_NO_FAULT) { + if (create_download_upload_response(cwmp_main->session->tree_out, TYPE_UPLOAD) != FAULT_CPE_NO_FAULT) { error = FAULT_CPE_INTERNAL_ERROR; goto fault; } @@ -2411,21 +2413,23 @@ int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc) count_download_queue++; upload->scheduled_time = scheduled_time; } - bkp_session_insert_upload(upload); + upload->handler_timer.cb = cwmp_start_upload; + bkp_session_save(upload); bkp_session_save(); if (upload_delay != 0) { - CWMP_LOG(INFO, "Upload will start in %us", upload_delay); + CWMP_LOG(INFO, "Download will start in %us", upload_delay); } else { - CWMP_LOG(INFO, "Upload will start at the end of session"); + CWMP_LOG(INFO, "Download will start at the end of session"); } + cwmp_set_end_session(END_SESSION_UPLOAD); pthread_mutex_unlock(&mutex_upload); - pthread_cond_signal(&threshold_upload); + } return 0; fault: cwmp_free_upload_request(upload); - if (cwmp_create_fault_message(session, rpc, error)) + if (cwmp_create_fault_message(rpc, error)) return -1; return 0; } @@ -2434,11 +2438,11 @@ fault: * [FAULT]: Fault */ -int cwmp_handle_rpc_cpe_fault(struct session *session, struct rpc *rpc) +int cwmp_handle_rpc_cpe_fault(struct rpc *rpc) { mxml_node_t *b, *t, *u, *body; - body = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); + body = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND); b = mxmlNewElement(body, "soap_env:Fault"); if (!b) @@ -2448,7 +2452,7 @@ int cwmp_handle_rpc_cpe_fault(struct session *session, struct rpc *rpc) if (!t) return -1; - u = mxmlNewOpaque(t, (FAULT_CPE_ARRAY[session->fault_code].TYPE == FAULT_CPE_TYPE_CLIENT) ? "Client" : "Server"); + u = mxmlNewOpaque(t, (FAULT_CPE_ARRAY[cwmp_main->session->fault_code].TYPE == FAULT_CPE_TYPE_CLIENT) ? "Client" : "Server"); if (!u) return -1; @@ -2472,7 +2476,7 @@ int cwmp_handle_rpc_cpe_fault(struct session *session, struct rpc *rpc) if (!t) return -1; - u = mxmlNewOpaque(t, FAULT_CPE_ARRAY[session->fault_code].CODE); + u = mxmlNewOpaque(t, FAULT_CPE_ARRAY[cwmp_main->session->fault_code].CODE); if (!u) return -1; @@ -2480,7 +2484,7 @@ int cwmp_handle_rpc_cpe_fault(struct session *session, struct rpc *rpc) if (!b) return -1; - u = mxmlNewOpaque(t, FAULT_CPE_ARRAY[session->fault_code].DESCRIPTION); + u = mxmlNewOpaque(t, FAULT_CPE_ARRAY[cwmp_main->session->fault_code].DESCRIPTION); if (!u) return -1; @@ -2529,18 +2533,18 @@ int cwmp_handle_rpc_cpe_fault(struct session *session, struct rpc *rpc) return 0; } -int cwmp_create_fault_message(struct session *session, struct rpc *rpc_cpe, int fault_code) +int cwmp_create_fault_message(struct rpc *rpc_cpe, int fault_code) { CWMP_LOG(INFO, "Fault detected"); - session->fault_code = fault_code; + cwmp_main->session->fault_code = fault_code; - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_out); - if (xml_prepare_msg_out(session)) + if (xml_prepare_msg_out()) return -1; CWMP_LOG(INFO, "Preparing the Fault message"); - if (rpc_cpe_methods[RPC_CPE_FAULT].handler(session, rpc_cpe)) + if (rpc_cpe_methods[RPC_CPE_FAULT].handler(rpc_cpe)) return -1; rpc_cpe->type = RPC_CPE_FAULT; diff --git a/ssl_utils.c b/ssl_utils.c index c9aa9d5..bfe6b7d 100644 --- a/ssl_utils.c +++ b/ssl_utils.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "common.h" #include "log.h" @@ -39,7 +38,7 @@ char *generate_random_string(size_t size) int written = RAND_bytes(buf, size); if (written != 1) { - CWMP_LOG(ERROR,"Failed to get random bytes"); + printf("Failed to get random bytes"); goto end; } @@ -59,9 +58,8 @@ void message_compute_signature(char *msg_out, char *signature, size_t len) int i; int result_len = 20; unsigned char *result; - struct cwmp *cwmp = &cwmp_main; struct config *conf; - conf = &(cwmp->conf); + conf = &(cwmp_main->conf); /* unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, const unsigned char *d, size_t n, unsigned char *md, unsigned int *md_len);*/ @@ -74,4 +72,3 @@ void message_compute_signature(char *msg_out, char *signature, size_t len) } FREE(result); } - diff --git a/subprocess.c b/subprocess.c new file mode 100644 index 0000000..101ac66 --- /dev/null +++ b/subprocess.c @@ -0,0 +1,147 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Copyright (C) 2013-2021 iopsys Software Solutions AB + * Author Omar Kallel + * + */ + +#include +#include + +#include "common.h" +#include "subprocess.h" +#include "log.h" + +#define END_TASK "{\"task\":\"end\"}" +#define EXIT_TASK "{\"task\":\"exit\"}" + +static int pipefd1[2], pipefd2[2]; + +bool check_task_name(char *task, char *name) +{ + struct blob_buf bbuf; + + if (strcmp(task, "{}") == 0) + return false; + + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + + if (blobmsg_add_json_from_string(&bbuf, task) == false) { + blob_buf_free(&bbuf); + return false; + } + + const struct blobmsg_policy p[1] = { { "task", BLOBMSG_TYPE_STRING } }; + + struct blob_attr *tb[1] = { NULL }; + blobmsg_parse(p, 1, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head)); + if (tb[0] == NULL) + return false; + + char *task_name = blobmsg_get_string(tb[0]); + + if (strcmp(task_name, name) == 0) { + blob_buf_free(&bbuf); + return true; + } + blob_buf_free(&bbuf); + return false; +} + +bool check_task_is_end(char *task) +{ + return check_task_name(task, "end"); +} + +bool check_task_is_exit(char *task) +{ + return check_task_name(task, "exit"); +} + +int subprocess_start(task_function task_fun) +{ + if(task_fun == NULL) + return CWMP_GEN_ERR; + + pid_t p; + if (pipe(pipefd1) == -1) { + CWMP_LOG(ERROR, "pipefd1 failed\n"); + return CWMP_GEN_ERR; + } + if (pipe(pipefd2) == -1) { + CWMP_LOG(ERROR, "pipefd2 failed\n"); + return CWMP_GEN_ERR; + } + p = fork(); + + if (p == 0) { + while(1) { + char from_parent[512]; + read(pipefd1[0], from_parent, 512); //The received string should has the form {"task":"TaskName", "arg1_name":"xxx", "arg2_name":"xxxx"} + if (strlen(from_parent) == 0) + continue; + //get the task name + //if the task name is end + if (check_task_is_end(from_parent)){ + write(pipefd2[1], EXIT_TASK, strlen(EXIT_TASK)+1); + exit(EXIT_SUCCESS); + } + char *to_child = task_fun(from_parent); + + struct blob_buf bbuf; + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + blobmsg_add_string(&bbuf, "ret", to_child); + char *to_child_json = blobmsg_format_json(bbuf.head, true); + write(pipefd2[1], to_child_json, strlen(to_child_json)+1); + blob_buf_free(&bbuf); + } + } + return CWMP_OK; +} + +char *execute_task_in_subprocess(char *task) +{ + char *ret = NULL; + + write(pipefd1[1], task, strlen(task) + 1); + + while(1) { + char from_child[512]; + read(pipefd2[0], from_child, 512); + if(strlen(from_child) == 0) + continue; + //The received string from the child should has the format {"task":"exit"} or {"ret":"exit"} + if (check_task_is_exit(from_child)){ + close(pipefd2[1]); + close(pipefd2[0]); + break; + } + + struct blob_buf bbuf; + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + if (blobmsg_add_json_from_string(&bbuf, from_child) == false) { + blob_buf_free(&bbuf); + continue; + } + const struct blobmsg_policy p[1] = { { "ret", BLOBMSG_TYPE_STRING } }; + struct blob_attr *tb[1] = { NULL }; + blobmsg_parse(p, 1, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head)); + if (tb[0] == NULL) { + blob_buf_free(&bbuf); + continue; + } + ret = blobmsg_get_string(tb[0]); + write(pipefd1[1], END_TASK, strlen(END_TASK) +1); + } + close(pipefd1[0]); + close(pipefd1[1]); + return ret; +} + diff --git a/test/cmocka/.gitignore b/test/cmocka/.gitignore deleted file mode 100644 index 4c858af..0000000 --- a/test/cmocka/.gitignore +++ /dev/null @@ -1 +0,0 @@ -icwmp_unit_testd diff --git a/test/cmocka/icwmp_backup_session_unit_test.c b/test/cmocka/icwmp_backup_session_unit_test.c index f0ec7bc..8eeb0cc 100644 --- a/test/cmocka/icwmp_backup_session_unit_test.c +++ b/test/cmocka/icwmp_backup_session_unit_test.c @@ -23,22 +23,30 @@ static struct cwmp cwmp_main_test = { 0 }; +static int bkp_session_unit_tests_init(void **state) +{ + cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); + create_cwmp_session_structure(); + return 0; +} + static int bkp_session_unit_tests_clean(void **state) { icwmp_cleanmem(); + clean_cwmp_session_structure(); + FREE(cwmp_main); return 0; } static void cwmp_backup_session_unit_test(void **state) { remove(CWMP_BKP_FILE); - struct cwmp *cwmp_test = &cwmp_main_test; mxml_node_t *backup_tree = NULL, *n = NULL; /* * Init backup session */ - int error = cwmp_init_backup_session(cwmp_test, NULL, ALL); + int error = cwmp_init_backup_session(NULL, ALL); assert_int_equal(error, 0); bkp_session_save(); FILE *pFile; @@ -270,5 +278,5 @@ int icwmp_backup_session_test(void) cmocka_unit_test(cwmp_backup_session_unit_test), }; - return cmocka_run_group_tests(tests, NULL, bkp_session_unit_tests_clean); + return cmocka_run_group_tests(tests, bkp_session_unit_tests_init, bkp_session_unit_tests_clean); } diff --git a/test/cmocka/icwmp_cli_unit_test.c b/test/cmocka/icwmp_cli_unit_test.c index e15e7d1..e3f1cbe 100644 --- a/test/cmocka/icwmp_cli_unit_test.c +++ b/test/cmocka/icwmp_cli_unit_test.c @@ -51,17 +51,20 @@ static void restore_output() static int cwmp_cli_unit_tests_init(void **state) { - cwmp_uci_init(); + cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); + create_cwmp_session_structure(); + memcpy(&(cwmp_main->env), &cwmp_main, sizeof(struct env)); + cwmp_session_init(); return 0; } static int cwmp_cli_unit_tests_clean(void **state) { - icwmp_cleanmem(); - FREE(add_instance); icwmp_free_list_services(); - cwmp_uci_exit(); - + cwmp_session_exit(); + FREE(cwmp_main->session); + FREE(cwmp_main); + FREE(add_instance); return 0; } diff --git a/test/cmocka/icwmp_custom_inform_parameters_unit_test.c b/test/cmocka/icwmp_custom_inform_parameters_unit_test.c index 8293eda..af5cce5 100644 --- a/test/cmocka/icwmp_custom_inform_parameters_unit_test.c +++ b/test/cmocka/icwmp_custom_inform_parameters_unit_test.c @@ -18,9 +18,44 @@ #include "common.h" #include "config.h" -#include "rpc_soap.h" +#include "soap.h" -static struct cwmp cwmp_main_test = { 0 }; +static int custom_inform_unit_tests_init(void **state) +{ + cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); + get_global_config(); + return 0; +} + +static void clean_config() +{ + FREE(cwmp_main->deviceid.manufacturer); + FREE(cwmp_main->deviceid.serialnumber); + FREE(cwmp_main->deviceid.productclass); + FREE(cwmp_main->deviceid.oui); + FREE(cwmp_main->deviceid.softwareversion); + FREE(cwmp_main->conf.lw_notification_hostname); + FREE(cwmp_main->conf.ip); + FREE(cwmp_main->conf.ipv6); + FREE(cwmp_main->conf.acsurl); + FREE(cwmp_main->conf.acs_userid); + FREE(cwmp_main->conf.acs_passwd); + FREE(cwmp_main->conf.interface); + FREE(cwmp_main->conf.cpe_userid); + FREE(cwmp_main->conf.cpe_passwd); + FREE(cwmp_main->conf.ubus_socket); + FREE(cwmp_main->conf.connection_request_path); + FREE(cwmp_main->conf.default_wan_iface); + FREE(cwmp_main->conf.interface); +} + +static int custom_inform_unit_tests_clean(void **state) +{ + clean_config(); + icwmp_cleanmem(); + FREE(cwmp_main); + return 0; +} static int verify_inform_parameter_in_list(char *parameter) { @@ -32,60 +67,32 @@ static int verify_inform_parameter_in_list(char *parameter) return 0; } -static void clean_config(struct cwmp *cwmp_test) -{ - FREE(cwmp_test->deviceid.manufacturer); - FREE(cwmp_test->deviceid.serialnumber); - FREE(cwmp_test->deviceid.productclass); - FREE(cwmp_test->deviceid.oui); - FREE(cwmp_test->deviceid.softwareversion); - FREE(cwmp_test->conf.lw_notification_hostname); - FREE(cwmp_test->conf.ip); - FREE(cwmp_test->conf.ipv6); - FREE(cwmp_test->conf.acsurl); - FREE(cwmp_test->conf.acs_userid); - FREE(cwmp_test->conf.acs_passwd); - FREE(cwmp_test->conf.interface); - FREE(cwmp_test->conf.cpe_userid); - FREE(cwmp_test->conf.cpe_passwd); - FREE(cwmp_test->conf.ubus_socket); - FREE(cwmp_test->conf.connection_request_path); - FREE(cwmp_test->conf.default_wan_iface); - FREE(cwmp_test->conf.interface); -} - static void cwmp_custom_inform_unit_test(void **state) { - struct cwmp *cwmp_test = &cwmp_main_test; - get_global_config(&(cwmp_test->conf)); - - cwmp_test->conf.forced_inform_json_file = strdup("/etc/icwmpd/forced_inform_valid.json"); - load_forced_inform_json_file(cwmp_test); + cwmp_main->conf.forced_inform_json_file = strdup("/etc/icwmpd/forced_inform_valid.json"); + load_forced_inform_json_file(); assert_int_equal(nbre_custom_inform, 2); assert_int_equal(verify_inform_parameter_in_list("Device.DeviceInfo.X_IOPSYS_EU_BaseMACAddress"), 1); assert_int_equal(verify_inform_parameter_in_list("Device.DeviceInfo.UpTime"), 1); - FREE(cwmp_test->conf.forced_inform_json_file); + FREE(cwmp_main->conf.forced_inform_json_file); clean_custom_inform_parameters(); - cwmp_test->conf.forced_inform_json_file = strdup("/etc/icwmpd/forced_inform_invalid_json.json"); - load_forced_inform_json_file(cwmp_test); + cwmp_main->conf.forced_inform_json_file = strdup("/etc/icwmpd/forced_inform_invalid_json.json"); + load_forced_inform_json_file(); assert_int_equal(nbre_custom_inform, 0); assert_int_equal(verify_inform_parameter_in_list("Device.DeviceInfo.X_IOPSYS_EU_BaseMACAddress"), 0); assert_int_equal(verify_inform_parameter_in_list("Device.DeviceInfo.UpTime"), 0); - FREE(cwmp_test->conf.forced_inform_json_file); + FREE(cwmp_main->conf.forced_inform_json_file); clean_custom_inform_parameters(); - cwmp_test->conf.forced_inform_json_file = strdup("/etc/icwmpd/forced_inform_invalid_parameter.json"); - load_forced_inform_json_file(cwmp_test); + cwmp_main->conf.forced_inform_json_file = strdup("/etc/icwmpd/forced_inform_invalid_parameter.json"); + load_forced_inform_json_file(); assert_int_equal(nbre_custom_inform, 1); assert_int_equal(verify_inform_parameter_in_list("Devie.DeviceInfo.X_IOPSYS_EU_BaseMACAddress"), 0); assert_int_equal(verify_inform_parameter_in_list("Device."), 0); assert_int_equal(verify_inform_parameter_in_list("Device.DeviceInfo.UpTime"), 1); - FREE(cwmp_test->conf.forced_inform_json_file); + FREE(cwmp_main->conf.forced_inform_json_file); clean_custom_inform_parameters(); - - clean_config(cwmp_test); - icwmp_cleanmem(); } int icwmp_custom_inform_test(void) @@ -94,5 +101,5 @@ int icwmp_custom_inform_test(void) cmocka_unit_test(cwmp_custom_inform_unit_test), }; - return cmocka_run_group_tests(tests, NULL, NULL); + return cmocka_run_group_tests(tests, custom_inform_unit_tests_init, custom_inform_unit_tests_clean); } diff --git a/test/cmocka/icwmp_datamodel_interface_unit_test.c b/test/cmocka/icwmp_datamodel_interface_unit_test.c old mode 100644 new mode 100755 index 057fc68..683ae0a --- a/test/cmocka/icwmp_datamodel_interface_unit_test.c +++ b/test/cmocka/icwmp_datamodel_interface_unit_test.c @@ -19,13 +19,50 @@ #include "datamodel_interface.h" #include "event.h" #include "xml.h" -#include "rpc_soap.h" +#include "soap.h" #include "session.h" #include "log.h" +static LIST_HEAD(list_set_param_value); +static LIST_HEAD(faults_list); +static LIST_HEAD(parameters_list); + +static int dm_iface_unit_tests_init(void **state) +{ + cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); + create_cwmp_session_structure(); + global_conf_init(); + return 0; +} + static int dm_iface_unit_tests_clean(void **state) { + icwmp_free_list_services(); icwmp_cleanmem(); + clean_cwmp_session_structure(); + FREE(cwmp_main->deviceid.manufacturer); + FREE(cwmp_main->deviceid.serialnumber); + FREE(cwmp_main->deviceid.productclass); + FREE(cwmp_main->deviceid.oui); + FREE(cwmp_main->deviceid.softwareversion); + FREE(cwmp_main->conf.lw_notification_hostname); + FREE(cwmp_main->conf.ip); + FREE(cwmp_main->conf.ipv6); + FREE(cwmp_main->conf.acsurl); + FREE(cwmp_main->conf.acs_userid); + FREE(cwmp_main->conf.acs_passwd); + FREE(cwmp_main->conf.interface); + FREE(cwmp_main->conf.cpe_userid); + FREE(cwmp_main->conf.cpe_passwd); + FREE(cwmp_main->conf.ubus_socket); + FREE(cwmp_main->conf.connection_request_path); + FREE(cwmp_main->conf.default_wan_iface); + FREE(cwmp_main->conf.forced_inform_json_file); + FREE(cwmp_main->conf.custom_notify_json); + FREE(cwmp_main->conf.boot_inform_json_file); + FREE(cwmp_main); + cwmp_free_all_list_param_fault(&faults_list); + cwmp_free_all_dm_parameter_list(&list_set_param_value); return 0; } @@ -35,7 +72,7 @@ static int dm_iface_unit_tests_clean(void **state) static void dm_get_parameter_values_test(void **state) { char *fault = NULL; - LIST_HEAD(parameters_list); + /* * Test of valid parameter path */ @@ -89,15 +126,13 @@ static void dm_set_multiple_parameter_values_test(void **state) int fault_code = 0; char *fault_name = NULL; struct cwmp_param_fault *param_fault = NULL; - LIST_HEAD(list_set_param_value); - LIST_HEAD(faults_array); /* * Test of one valid parameter */ add_dm_parameter_to_list(&list_set_param_value, "Device.WiFi.SSID.1.Alias", "wifi_alias_1", NULL, 0, false); cwmp_transaction_start("cwmp"); - fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssid_alias", &flag, &faults_array); + fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssid_alias", &flag, &faults_list); assert_int_equal(fault, 0); assert_in_set(flag, flag_values, 15); cwmp_transaction_commit(); @@ -106,7 +141,7 @@ static void dm_set_multiple_parameter_values_test(void **state) add_dm_parameter_to_list(&list_set_param_value, "Device.ManagementServer.Username", "iopsys_user", NULL, 0, false); //for other flag value cwmp_transaction_start("cwmp"); - fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "mngt_server_user", &flag, &faults_array); + fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "mngt_server_user", &flag, &faults_list); assert_int_equal(fault, 0); assert_in_set(flag, flag_values, 15); cwmp_transaction_commit(); @@ -119,9 +154,9 @@ static void dm_set_multiple_parameter_values_test(void **state) */ add_dm_parameter_to_list(&list_set_param_value, "Device.WiFi.SSID.1.Alis", "wifi_alias_1", NULL, 0, false); cwmp_transaction_start("cwmp"); - fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssid_alias", &flag, &faults_array); + fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssid_alias", &flag, &faults_list); assert_non_null(fault); - list_for_each_entry (param_fault, &faults_array, list) { + list_for_each_entry (param_fault, &faults_list, list) { fault_code = param_fault->fault; fault_name = param_fault->name; break; @@ -131,7 +166,7 @@ static void dm_set_multiple_parameter_values_test(void **state) assert_non_null(fault_name); cwmp_transaction_abort(); cwmp_free_all_dm_parameter_list(&list_set_param_value); - cwmp_free_all_list_param_fault(&faults_array); + cwmp_free_all_list_param_fault(&faults_list); fault_code = 0; fault_name = NULL; param_fault = NULL; @@ -142,9 +177,9 @@ static void dm_set_multiple_parameter_values_test(void **state) */ add_dm_parameter_to_list(&list_set_param_value, "Device.ATM.Link.1.Status", "Up", NULL, 0, false); cwmp_transaction_start("cwmp"); - fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_atm_link_status", &flag, &faults_array); + fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_atm_link_status", &flag, &faults_list); assert_int_not_equal(fault, 0); - list_for_each_entry (param_fault, &faults_array, list) { + list_for_each_entry (param_fault, &faults_list, list) { fault_code = param_fault->fault; fault_name = param_fault->name; break; @@ -154,7 +189,7 @@ static void dm_set_multiple_parameter_values_test(void **state) assert_non_null(fault_name); cwmp_transaction_abort(); cwmp_free_all_dm_parameter_list(&list_set_param_value); - cwmp_free_all_list_param_fault(&faults_array); + cwmp_free_all_list_param_fault(&faults_list); fault = 0; fault_code = 0; fault_name = NULL; @@ -165,9 +200,9 @@ static void dm_set_multiple_parameter_values_test(void **state) */ add_dm_parameter_to_list(&list_set_param_value, "Device.WiFi.SSID.1.Enable", "tre", NULL, 0, false); cwmp_transaction_start("cwmp"); - fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssid_alias", &flag, &faults_array); + fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssid_alias", &flag, &faults_list); assert_non_null(fault); - list_for_each_entry (param_fault, &faults_array, list) { + list_for_each_entry (param_fault, &faults_list, list) { fault_code = param_fault->fault; fault_name = param_fault->name; break; @@ -177,7 +212,7 @@ static void dm_set_multiple_parameter_values_test(void **state) assert_non_null(fault_name); cwmp_transaction_abort(); cwmp_free_all_dm_parameter_list(&list_set_param_value); - cwmp_free_all_list_param_fault(&faults_array); + cwmp_free_all_list_param_fault(&faults_list); fault_code = 0; fault_name = NULL; param_fault = NULL; @@ -190,7 +225,7 @@ static void dm_set_multiple_parameter_values_test(void **state) add_dm_parameter_to_list(&list_set_param_value, "Device.WiFi.SSID.1.SSID", "wifi_ssid_2", NULL, 0, false); add_dm_parameter_to_list(&list_set_param_value, "Device.ManagementServer.Username", "iopsys_user_1", NULL, 0, false); cwmp_transaction_start("cwmp"); - fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssids_aliases", &flag, &faults_array); + fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssids_aliases", &flag, &faults_list); assert_int_equal(fault, 0); assert_in_set(flag, flag_values, 15); cwmp_transaction_commit(); @@ -204,12 +239,13 @@ static void dm_set_multiple_parameter_values_test(void **state) add_dm_parameter_to_list(&list_set_param_value, "Device.WiFi.SSID.2.Alis", "wifi_2", NULL, 0, false); add_dm_parameter_to_list(&list_set_param_value, "Device.ATM.Link.1.Status", "Up", NULL, 0, false); cwmp_transaction_start("cwmp"); - fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wrongs", &flag, &faults_array); + fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wrongs", &flag, &faults_list); assert_int_not_equal(fault, 0); - list_for_each_entry (param_fault, &faults_array, list) { + list_for_each_entry (param_fault, &faults_list, list) { assert_in_set(param_fault->fault, faults_values, 3); } cwmp_transaction_commit(); + cwmp_free_all_list_param_fault(&faults_list); cwmp_free_all_dm_parameter_list(&list_set_param_value); } @@ -331,5 +367,5 @@ int icwmp_datamodel_interface_test(void) cmocka_unit_test(dm_get_parameter_names_test), }; - return cmocka_run_group_tests(tests, NULL, dm_iface_unit_tests_clean); + return cmocka_run_group_tests(tests, dm_iface_unit_tests_init, dm_iface_unit_tests_clean); } diff --git a/test/cmocka/icwmp_download_unit_test.c b/test/cmocka/icwmp_download_unit_test.c index 3401012..7f2f08e 100644 --- a/test/cmocka/icwmp_download_unit_test.c +++ b/test/cmocka/icwmp_download_unit_test.c @@ -23,9 +23,9 @@ #include "log.h" #include "download.h" -static struct transfer_complete *transfer_complete_test = NULL; +struct transfer_complete *transfer_complete_test = NULL; -static void free_transfer_complete(struct transfer_complete *p) +void free_transfer_complete(struct transfer_complete *p) { FREE(p->command_key); FREE(p->start_time); diff --git a/test/cmocka/icwmp_notifications_unit_test.c b/test/cmocka/icwmp_notifications_unit_test.c index 0064f95..234e356 100644 --- a/test/cmocka/icwmp_notifications_unit_test.c +++ b/test/cmocka/icwmp_notifications_unit_test.c @@ -20,25 +20,31 @@ /* * Common functions */ -static char *notifications_test[7] = {"disabled" , "passive", "active", "passive_lw", "passive_passive_lw", "active_lw", "passive_active_lw"}; +char *notifications_test[7] = {"disabled" , "passive", "active", "passive_lw", "passive_passive_lw", "active_lw", "passive_active_lw"}; -LIST_HEAD(parameters_list); +static LIST_HEAD(parameters_list); static int cwmp_notifications_unit_tests_init(void **state) { - cwmp_uci_init(); + cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); + create_cwmp_session_structure(); + memcpy(&(cwmp_main->env), &cwmp_main, sizeof(struct env)); + cwmp_session_init(); return 0; } static int cwmp_notifications_unit_tests_clean(void **state) { - icwmp_cleanmem(); + clean_list_param_notify(); + clean_list_value_change(); cwmp_free_all_dm_parameter_list(¶meters_list); - cwmp_uci_exit(); + cwmp_session_exit(); + FREE(cwmp_main->session); + FREE(cwmp_main); return 0; } -static int check_notify_file(char *param, int *ret_notification) +int check_notify_file(char *param, int *ret_notification) { struct blob_buf bbuf; char *parameter = NULL; @@ -80,7 +86,7 @@ static int check_notify_file(char *param, int *ret_notification) return nbre_iterations; } -static int get_parameter_notification_from_list_head(struct list_head *params_list, char *parameter_name) +int get_parameter_notification_from_list_head(struct list_head *params_list, char *parameter_name) { struct cwmp_dm_parameter *param_iter = NULL; list_for_each_entry (param_iter, params_list, list) { @@ -90,7 +96,7 @@ static int get_parameter_notification_from_list_head(struct list_head *params_li return 0; } -static int get_parameter_notification_from_notifications_uci_list(char *parameter_name) +int get_parameter_notification_from_notifications_uci_list(char *parameter_name) { int i, notification = 0; struct uci_list *list_notif; @@ -114,7 +120,7 @@ static int get_parameter_notification_from_notifications_uci_list(char *paramete return notification; } -static int get_parameter_in_list_value_change(char *parameter_name) +int get_parameter_in_list_value_change(char *parameter_name) { struct cwmp_dm_parameter *param_iter = NULL; list_for_each_entry (param_iter, &list_value_change, list) { @@ -123,6 +129,7 @@ static int get_parameter_in_list_value_change(char *parameter_name) } return 0; } +//////////////////////////////////////////// static void cwmp_init_list_param_notify_unit_test_default(void **state) { @@ -264,6 +271,7 @@ static void cwmp_check_value_change_1_unit_test(void **state) assert_int_equal((int)list_empty(&list_value_change), 0); assert_int_equal((int)list_empty(&list_lw_value_change), 1); assert_int_equal(get_parameter_in_list_value_change("Device.DeviceInfo.UpTime"), 1); + clean_list_value_change(); } int icwmp_notifications_test(void) diff --git a/test/cmocka/icwmp_soap_msg_unit_test.c b/test/cmocka/icwmp_soap_msg_unit_test.c index 0f9466e..e99528e 100644 --- a/test/cmocka/icwmp_soap_msg_unit_test.c +++ b/test/cmocka/icwmp_soap_msg_unit_test.c @@ -13,9 +13,8 @@ #include #include #include -#include -#include "rpc_soap.h" +#include "soap.h" #include "event.h" #include "session.h" #include "config.h" @@ -23,14 +22,13 @@ #include "log.h" #include "download.h" #include "cwmp_uci.h" -#include "xml.h" + +#include "cwmp_config.h" +#include "cwmp_event.h" #include "icwmp_soap_msg_unit_test.h" -static struct cwmp cwmp_main_test = { 0 }; -static struct cwmp *cwmp_test; -static struct session *session_test = NULL; -static int instance = 0; +int instance = 0; #define INVALID_PARAM_KEY "ParameterKeyParameterKeyParameter" #define INVALID_USER "useruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruser1" @@ -40,26 +38,26 @@ static int instance = 0; */ static void clean_config() { - FREE(cwmp_test->deviceid.manufacturer); - FREE(cwmp_test->deviceid.serialnumber); - FREE(cwmp_test->deviceid.productclass); - FREE(cwmp_test->deviceid.oui); - FREE(cwmp_test->deviceid.softwareversion); - FREE(cwmp_test->conf.lw_notification_hostname); - FREE(cwmp_test->conf.ip); - FREE(cwmp_test->conf.ipv6); - FREE(cwmp_test->conf.acsurl); - FREE(cwmp_test->conf.acs_userid); - FREE(cwmp_test->conf.acs_passwd); - FREE(cwmp_test->conf.interface); - FREE(cwmp_test->conf.cpe_userid); - FREE(cwmp_test->conf.cpe_passwd); - FREE(cwmp_test->conf.ubus_socket); - FREE(cwmp_test->conf.connection_request_path); - FREE(cwmp_test->conf.default_wan_iface); + FREE(cwmp_main->deviceid.manufacturer); + FREE(cwmp_main->deviceid.serialnumber); + FREE(cwmp_main->deviceid.productclass); + FREE(cwmp_main->deviceid.oui); + FREE(cwmp_main->deviceid.softwareversion); + FREE(cwmp_main->conf.lw_notification_hostname); + FREE(cwmp_main->conf.ip); + FREE(cwmp_main->conf.ipv6); + FREE(cwmp_main->conf.acsurl); + FREE(cwmp_main->conf.acs_userid); + FREE(cwmp_main->conf.acs_passwd); + FREE(cwmp_main->conf.interface); + FREE(cwmp_main->conf.cpe_userid); + FREE(cwmp_main->conf.cpe_passwd); + FREE(cwmp_main->conf.ubus_socket); + FREE(cwmp_main->conf.connection_request_path); + FREE(cwmp_main->conf.default_wan_iface); } -static void clean_name_space() +void clean_name_space() { FREE(ns.soap_env); FREE(ns.soap_enc); @@ -68,11 +66,11 @@ static void clean_name_space() FREE(ns.cwmp); } -static void unit_test_remove_all_events_by_session(struct session *session) +void unit_test_remove_all_session_events() { - while (session->head_event_container.next != &(session->head_event_container)) { + while (cwmp_main->session->events.next != &cwmp_main->session->events) { struct event_container *event_container; - event_container = list_entry(session->head_event_container.next, struct event_container, list); + event_container = list_entry(cwmp_main->session->events.next, struct event_container, list); free(event_container->command_key); cwmp_free_all_dm_parameter_list(&(event_container->head_dm_parameter)); list_del(&(event_container->list)); @@ -80,14 +78,9 @@ static void unit_test_remove_all_events_by_session(struct session *session) } } -static void unit_test_end_test_destruction() +void unit_test_end_test_destruction() { - struct session *session = NULL; - while (cwmp_test->head_session_queue.next != &(cwmp_test->head_session_queue)) { - session = list_entry(cwmp_test->head_session_queue.next, struct session, list); - unit_test_remove_all_events_by_session(session); - cwmp_session_destructor(session); - } + unit_test_remove_all_session_events(); } /* @@ -95,27 +88,21 @@ static void unit_test_end_test_destruction() */ static int soap_unit_tests_init(void **state) { - cwmp_test = &cwmp_main_test; - INIT_LIST_HEAD(&(cwmp_test->head_session_queue)); - memcpy(&(cwmp_test->env), &cwmp_test, sizeof(struct env)); - cwmp_uci_init(); + cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); + create_cwmp_session_structure(); + memcpy(&(cwmp_main->env), &cwmp_main, sizeof(struct env)); + cwmp_session_init(); return 0; } static int soap_unit_tests_clean(void **state) { - icwmp_cleanmem(); - if (session_test != NULL) { - MXML_DELETE(session_test->tree_in); - MXML_DELETE(session_test->tree_out); - session_test->head_rpc_acs.next = NULL; - session_test->head_rpc_cpe.next = NULL; - cwmp_session_destructor(session_test); - } icwmp_free_list_services(); clean_name_space(); clean_config(); - cwmp_uci_exit(); + cwmp_session_exit(); + FREE(cwmp_main->session); + FREE(cwmp_main); return 0; } @@ -124,51 +111,37 @@ static int soap_unit_tests_clean(void **state) */ static void get_config_test(void **state) { - int error = get_global_config(&(cwmp_test->conf)); + int error = get_global_config(); assert_int_equal(error, CWMP_OK); log_set_severity_idx("INFO"); } static void get_deviceid_test(void **state) { - int error = cwmp_get_deviceid(cwmp_test); + int error = cwmp_get_deviceid(); assert_int_equal(error, CWMP_OK); } static void add_event_test(void **state) { struct event_container *event_container; - event_container = cwmp_add_event_container(cwmp_test, EVENT_IDX_1BOOT, ""); + event_container = cwmp_add_event_container(EVENT_IDX_1BOOT, ""); assert_non_null(event_container); assert_string_equal(EVENT_CONST[event_container->code].CODE, "1 BOOT"); } -static int create_session(struct session **session) -{ - *session = calloc(1, sizeof(struct session)); - if (*session == NULL) - return 0; - - list_add_tail(&((*session)->list), &(cwmp_test->head_session_queue)); - - INIT_LIST_HEAD(&((*session)->head_event_container)); - *session = list_entry((&(cwmp_test->head_session_queue))->next, struct session, list); - return 1; -} - static void soap_inform_message_test(void **state) { mxml_node_t *env = NULL, *n = NULL, *device_id = NULL, *cwmp_inform = NULL; - struct session *session = NULL; struct rpc *rpc_acs; - create_session(&session); - session_test = session; - rpc_acs = list_entry(&(session->head_rpc_acs), struct rpc, list); - cwmp_rpc_acs_prepare_message_inform(cwmp_test, session, rpc_acs); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + rpc_acs = list_entry(&(cwmp_main->session->head_rpc_acs), struct rpc, list); + + cwmp_rpc_acs_prepare_message_inform(rpc_acs); + + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -198,33 +171,33 @@ static void soap_inform_message_test(void **state) n = mxmlFindElement(cwmp_inform, cwmp_inform, "ParameterList", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); unit_test_end_test_destruction(); clean_config(); - session_test = NULL; + } -static void prepare_session_for_rpc_method_call(struct session *session) +static void prepare_session_for_rpc_method_call() { mxml_node_t *b; char *c; icwmp_asprintf(&c, "%s:%s", ns.soap_env, "Body"); - b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); - session->body_in = b; - xml_prepare_msg_out(session); + b = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); + cwmp_main->session->body_in = b; + xml_prepare_msg_out(cwmp_main->session); } -static void prepare_gpv_soap_request(struct session *session, char *parameters[], int len) +static void prepare_gpv_soap_request(char *parameters[], int len) { mxml_node_t *params = NULL, *n = NULL; int i; - session->tree_in = mxmlLoadString(NULL, CWMP_GETPARAMETERVALUES_REQ, MXML_OPAQUE_CALLBACK); - xml_recreate_namespace(session->tree_in); - params = mxmlFindElement(session->tree_in, session->tree_in, "ParameterNames", NULL, NULL, MXML_DESCEND); + cwmp_main->session->tree_in = mxmlLoadString(NULL, CWMP_GETPARAMETERVALUES_REQ, MXML_OPAQUE_CALLBACK); + xml_recreate_namespace(cwmp_main->session->tree_in); + params = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, "ParameterNames", NULL, NULL, MXML_DESCEND); for (i = 0; i < len; i++) { n = mxmlNewElement(params, "string"); n = mxmlNewOpaque(n, parameters[i]); @@ -233,27 +206,25 @@ static void prepare_gpv_soap_request(struct session *session, char *parameters[] static void soap_get_param_value_message_test(void **state) { - struct session *session = NULL; mxml_node_t *env = NULL, *n = NULL, *name = NULL, *value = NULL; struct rpc *rpc_cpe; - create_session(&session); - session_test = session; - rpc_cpe = list_entry(&(session->head_rpc_cpe), struct rpc, list); + + rpc_cpe = list_entry(&(cwmp_main->session->head_rpc_cpe), struct rpc, list); /* * Valid parameter path */ char *valid_parameters[1] = { "Device.ManagementServer.PeriodicInformEnable" }; - prepare_gpv_soap_request(session, valid_parameters, 1); + prepare_gpv_soap_request(valid_parameters, 1); - prepare_session_for_rpc_method_call(session); + prepare_session_for_rpc_method_call(); - int ret = cwmp_handle_rpc_cpe_get_parameter_values(session, rpc_cpe); + int ret = cwmp_handle_rpc_cpe_get_parameter_values(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -274,8 +245,8 @@ static void soap_get_param_value_message_test(void **state) value = mxmlFindElement(n, n, "Value", NULL, NULL, MXML_DESCEND); assert_non_null(value); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Wrong parameter path @@ -283,14 +254,14 @@ static void soap_get_param_value_message_test(void **state) mxml_node_t *fault_code = NULL, *fault_string = NULL, *detail = NULL, *detail_code = NULL, *detail_string = NULL; char *invalid_parameter[1] = { "Device.ManagementServereriodicInformEnable" }; - prepare_gpv_soap_request(session, invalid_parameter, 1); + prepare_gpv_soap_request(invalid_parameter, 1); - prepare_session_for_rpc_method_call(session); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_get_parameter_values(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_get_parameter_values(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -314,22 +285,209 @@ static void soap_get_param_value_message_test(void **state) detail_string = mxmlFindElement(detail, detail, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(detail_string); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); - session->head_rpc_acs.next = NULL; + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + cwmp_main->session->head_rpc_acs.next = NULL; unit_test_end_test_destruction(); clean_name_space(); - session_test = NULL; + } -static void prepare_addobj_soap_request(struct session *session, char *object, char *parameter_key) +static void prepare_spv_soap_request(char *parameter, char *value, char *parameter_key) +{ + mxml_node_t *params = NULL, *n = NULL; + + cwmp_main->session->tree_in = mxmlLoadString(NULL, CWMP_SETPARAMETERVALUES_REQ, MXML_OPAQUE_CALLBACK); + xml_recreate_namespace(cwmp_main->session->tree_in); + params = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, "ParameterValueStruct", NULL, NULL, MXML_DESCEND); + n = mxmlNewElement(params, "Name"); + n = mxmlNewOpaque(n, parameter); + n = mxmlNewElement(params, "Value"); + mxmlElementSetAttr(n, "xsi:type", "xsd:string"); + n = mxmlNewOpaque(n, value); + n = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, "ParameterKey", NULL, NULL, MXML_DESCEND); + n = mxmlNewOpaque(n, parameter_key); +} + +static void soap_set_param_value_message_test(void **state) +{ + mxml_node_t *env = NULL, *n = NULL; + struct rpc *rpc_cpe; + + + + rpc_cpe = list_entry(&(cwmp_main->session->head_rpc_cpe), struct rpc, list); + + /* + * Valid path & writable parameter + */ + rpc_cpe->type = RPC_CPE_SET_PARAMETER_VALUES; + prepare_spv_soap_request("Device.ManagementServer.PeriodicInformEnable", "true", "set_value_test"); + prepare_session_for_rpc_method_call(); + + int ret = cwmp_handle_rpc_cpe_set_parameter_values(rpc_cpe); + assert_int_equal(ret, 0); + + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + assert_non_null(env); + n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "cwmp:ID", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(env, env, "soap_env:Body", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "cwmp:SetParameterValuesResponse", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "Status", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "1"); + + rpc_cpe->list_set_value_fault = NULL; + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + cwmp_main->session->tree_out = NULL; + + /* + * Wrong parameter path + */ + rpc_cpe->type = RPC_CPE_SET_PARAMETER_VALUES; + mxml_node_t *cwmp_fault = NULL, *set_val_fault = NULL; + + prepare_spv_soap_request("Device.ManagementServeriodicInformEnable", "mngmt_enable", "set_value_test"); + prepare_session_for_rpc_method_call(); + + ret = cwmp_handle_rpc_cpe_set_parameter_values(rpc_cpe); + assert_int_equal(ret, 0); + + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + assert_non_null(env); + n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "cwmp:ID", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(env, env, "soap_env:Body", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(env, env, "soap_env:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "detail", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + cwmp_fault = mxmlFindElement(n, n, "cwmp:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(cwmp_fault); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultCode", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "9003"); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + set_val_fault = mxmlFindElement(cwmp_fault, cwmp_fault, "SetParameterValuesFault", NULL, NULL, MXML_DESCEND); + assert_non_null(set_val_fault); + n = mxmlFindElement(set_val_fault, set_val_fault, "ParameterName", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "Device.ManagementServeriodicInformEnable"); + n = mxmlFindElement(set_val_fault, set_val_fault, "FaultCode", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "9005"); + n = mxmlFindElement(set_val_fault, set_val_fault, "FaultString", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + rpc_cpe->list_set_value_fault = NULL; + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + cwmp_main->session->tree_in = NULL; + cwmp_main->session->tree_out = NULL; + + /* + * Not writable & Valid parameter path + */ + rpc_cpe->type = RPC_CPE_SET_PARAMETER_VALUES; + prepare_spv_soap_request("Device.ManagementServer.AliasBasedAddressing", "true", "set_value_test"); + prepare_session_for_rpc_method_call(); + + ret = cwmp_handle_rpc_cpe_set_parameter_values(rpc_cpe); + assert_int_equal(ret, 0); + + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + assert_non_null(env); + n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "cwmp:ID", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(env, env, "soap_env:Body", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(env, env, "soap_env:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "detail", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + cwmp_fault = mxmlFindElement(n, n, "cwmp:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(cwmp_fault); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultCode", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "9003"); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + set_val_fault = mxmlFindElement(cwmp_fault, cwmp_fault, "SetParameterValuesFault", NULL, NULL, MXML_DESCEND); + assert_non_null(set_val_fault); + n = mxmlFindElement(set_val_fault, set_val_fault, "ParameterName", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "Device.ManagementServer.AliasBasedAddressing"); + n = mxmlFindElement(set_val_fault, set_val_fault, "FaultCode", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "9008"); + n = mxmlFindElement(set_val_fault, set_val_fault, "FaultString", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + rpc_cpe->list_set_value_fault = NULL; + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + + cwmp_main->session->head_rpc_acs.next = NULL; + unit_test_end_test_destruction(); + clean_name_space(); + + /* + * Invalide parameteKey + */ + rpc_cpe->type = RPC_CPE_SET_PARAMETER_VALUES; + + prepare_spv_soap_request("Device.ManagementServer.PeriodicInformEnable", "false", INVALID_PARAM_KEY); + prepare_session_for_rpc_method_call(); + + ret = cwmp_handle_rpc_cpe_set_parameter_values(rpc_cpe); + assert_int_equal(ret, 0); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + assert_non_null(env); + n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "cwmp:ID", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(env, env, "soap_env:Body", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(env, env, "soap_env:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "detail", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + cwmp_fault = mxmlFindElement(n, n, "cwmp:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(cwmp_fault); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultCode", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "9003"); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + set_val_fault = mxmlFindElement(cwmp_fault, cwmp_fault, "SetParameterValuesFault", NULL, NULL, MXML_DESCEND); + assert_null(set_val_fault); + rpc_cpe->list_set_value_fault = NULL; + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + cwmp_main->session->tree_in = NULL; + cwmp_main->session->tree_out = NULL; + +} + +static void prepare_addobj_soap_request(char *object, char *parameter_key) { mxml_node_t *add_node = NULL, *n = NULL; - session->tree_in = mxmlLoadString(NULL, CWMP_ADDOBJECT_REQ, MXML_OPAQUE_CALLBACK); - xml_recreate_namespace(session->tree_in); - add_node = mxmlFindElement(session->tree_in, session->tree_in, "cwmp:AddObject", NULL, NULL, MXML_DESCEND); + cwmp_main->session->tree_in = mxmlLoadString(NULL, CWMP_ADDOBJECT_REQ, MXML_OPAQUE_CALLBACK); + xml_recreate_namespace(cwmp_main->session->tree_in); + add_node = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, "cwmp:AddObject", NULL, NULL, MXML_DESCEND); n = mxmlFindElement(add_node, add_node, "ObjectName", NULL, NULL, MXML_DESCEND); n = mxmlNewOpaque(n, object); n = mxmlFindElement(add_node, add_node, "ParameterKey", NULL, NULL, MXML_DESCEND); @@ -338,23 +496,20 @@ static void prepare_addobj_soap_request(struct session *session, char *object, c static void soap_add_object_message_test(void **state) { - struct session *session = NULL; mxml_node_t *env = NULL, *n = NULL, *add_resp = NULL; struct rpc *rpc_cpe; - create_session(&session); - session_test = session; - rpc_cpe = list_entry(&(session->head_rpc_cpe), struct rpc, list); + rpc_cpe = list_entry(&(cwmp_main->session->head_rpc_cpe), struct rpc, list); /* * Valid path & writable object */ - prepare_addobj_soap_request(session, "Device.WiFi.SSID.", "add_object_test"); - prepare_session_for_rpc_method_call(session); + prepare_addobj_soap_request("Device.WiFi.SSID.", "add_object_test"); + prepare_session_for_rpc_method_call(); - int ret = cwmp_handle_rpc_cpe_add_object(session, rpc_cpe); + int ret = cwmp_handle_rpc_cpe_add_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -370,21 +525,21 @@ static void soap_add_object_message_test(void **state) n = mxmlFindElement(add_resp, add_resp, "Status", NULL, NULL, MXML_DESCEND); assert_non_null(n); assert_string_equal(n->child->value.opaque, "1"); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Wrong object path */ mxml_node_t *cwmp_fault = NULL; - prepare_addobj_soap_request(session, "Device.WiFi.SSI.", "add_object_test"); - prepare_session_for_rpc_method_call(session); + prepare_addobj_soap_request("Device.WiFi.SSI.", "add_object_test"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_add_object(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_add_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -403,20 +558,20 @@ static void soap_add_object_message_test(void **state) assert_string_equal(n->child->value.opaque, "9005"); n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Not writable & Valid object path */ cwmp_fault = NULL; - prepare_addobj_soap_request(session, "Device.DeviceInfo.Processor.", "add_object_test"); - prepare_session_for_rpc_method_call(session); + prepare_addobj_soap_request("Device.DeviceInfo.Processor.", "add_object_test"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_add_object(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_add_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -435,20 +590,20 @@ static void soap_add_object_message_test(void **state) assert_string_equal(n->child->value.opaque, "9005"); n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Invalid parameterkey */ cwmp_fault = NULL; - prepare_addobj_soap_request(session, "Device.WiFi.SSID.", INVALID_PARAM_KEY); - prepare_session_for_rpc_method_call(session); + prepare_addobj_soap_request("Device.WiFi.SSID.", INVALID_PARAM_KEY); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_add_object(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_add_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -467,22 +622,23 @@ static void soap_add_object_message_test(void **state) assert_string_equal(n->child->value.opaque, "9003"); n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); - session->head_rpc_acs.next = NULL; + cwmp_main->session->head_rpc_acs.next = NULL; unit_test_end_test_destruction(); clean_name_space(); - session_test = NULL; + + } -static void prepare_delobj_soap_request(struct session *session, char *object, char *parameter_key) +static void prepare_delobj_soap_request(char *object, char *parameter_key) { mxml_node_t *del_node = NULL, *n = NULL; - session->tree_in = mxmlLoadString(NULL, CWMP_DELOBJECT_REQ, MXML_OPAQUE_CALLBACK); - xml_recreate_namespace(session->tree_in); - del_node = mxmlFindElement(session->tree_in, session->tree_in, "cwmp:DeleteObject", NULL, NULL, MXML_DESCEND); + cwmp_main->session->tree_in = mxmlLoadString(NULL, CWMP_DELOBJECT_REQ, MXML_OPAQUE_CALLBACK); + xml_recreate_namespace(cwmp_main->session->tree_in); + del_node = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, "cwmp:DeleteObject", NULL, NULL, MXML_DESCEND); n = mxmlFindElement(del_node, del_node, "ObjectName", NULL, NULL, MXML_DESCEND); n = mxmlNewOpaque(n, object); n = mxmlFindElement(del_node, del_node, "ParameterKey", NULL, NULL, MXML_DESCEND); @@ -491,26 +647,24 @@ static void prepare_delobj_soap_request(struct session *session, char *object, c static void soap_delete_object_message_test(void **state) { - struct session *session = NULL; mxml_node_t *env = NULL, *n = NULL, *add_resp = NULL; struct rpc *rpc_cpe; - create_session(&session); - session_test = session; - rpc_cpe = list_entry(&(session->head_rpc_cpe), struct rpc, list); + + rpc_cpe = list_entry(&(cwmp_main->session->head_rpc_cpe), struct rpc, list); /* * Valid path & writable object */ char del_obj[32]; snprintf(del_obj, sizeof(del_obj), "Device.WiFi.SSID.%d.", instance); - prepare_delobj_soap_request(session, del_obj, "del_object_test"); - prepare_session_for_rpc_method_call(session); + prepare_delobj_soap_request(del_obj, "del_object_test"); + prepare_session_for_rpc_method_call(); - int ret = cwmp_handle_rpc_cpe_delete_object(session, rpc_cpe); + int ret = cwmp_handle_rpc_cpe_delete_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -523,21 +677,21 @@ static void soap_delete_object_message_test(void **state) n = mxmlFindElement(add_resp, add_resp, "Status", NULL, NULL, MXML_DESCEND); assert_non_null(n); assert_string_equal(n->child->value.opaque, "1"); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Wrong object path */ mxml_node_t *cwmp_fault = NULL; - prepare_delobj_soap_request(session, "Device.WiFi.SID.1", "del_object_test"); - prepare_session_for_rpc_method_call(session); + prepare_delobj_soap_request("Device.WiFi.SID.1", "del_object_test"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_delete_object(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_delete_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -556,20 +710,20 @@ static void soap_delete_object_message_test(void **state) assert_string_equal(n->child->value.opaque, "9005"); n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Not writable & Valid object path */ cwmp_fault = NULL; - prepare_delobj_soap_request(session, "Device.DeviceInfo.Processor.2.", "del_object_test"); - prepare_session_for_rpc_method_call(session); + prepare_delobj_soap_request("Device.DeviceInfo.Processor.2.", "del_object_test"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_delete_object(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_delete_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -588,20 +742,20 @@ static void soap_delete_object_message_test(void **state) assert_string_equal(n->child->value.opaque, "9005"); n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Invalid parameterkey */ cwmp_fault = NULL; - prepare_delobj_soap_request(session, "Device.WiFi.SSID.1.", INVALID_PARAM_KEY); - prepare_session_for_rpc_method_call(session); + prepare_delobj_soap_request("Device.WiFi.SSID.1.", INVALID_PARAM_KEY); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_delete_object(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_delete_object(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -620,22 +774,23 @@ static void soap_delete_object_message_test(void **state) assert_string_equal(n->child->value.opaque, "9003"); n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); - session->head_rpc_acs.next = NULL; + cwmp_main->session->head_rpc_acs.next = NULL; unit_test_end_test_destruction(); clean_name_space(); - session_test = NULL; + + } -static void prepare_gpa_soap_request(struct session *session, char *parameter) +static void prepare_gpa_soap_request(char *parameter) { mxml_node_t *n = NULL; - session->tree_in = mxmlLoadString(NULL, CWMP_GETATTRIBUTES_REQ, MXML_OPAQUE_CALLBACK); - xml_recreate_namespace(session->tree_in); - n = mxmlFindElement(session->tree_in, session->tree_in, "cwmp:GetParameterAttributes", NULL, NULL, MXML_DESCEND); + cwmp_main->session->tree_in = mxmlLoadString(NULL, CWMP_GETATTRIBUTES_REQ, MXML_OPAQUE_CALLBACK); + xml_recreate_namespace(cwmp_main->session->tree_in); + n = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, "cwmp:GetParameterAttributes", NULL, NULL, MXML_DESCEND); n = mxmlFindElement(n, n, "ParameterNames", NULL, NULL, MXML_DESCEND); n = mxmlNewElement(n, "string"); n = mxmlNewOpaque(n, parameter); @@ -643,25 +798,23 @@ static void prepare_gpa_soap_request(struct session *session, char *parameter) static void soap_get_parameter_attributes_message_test(void **state) { - struct session *session = NULL; mxml_node_t *env = NULL, *n = NULL, *param_attr = NULL; struct rpc *rpc_cpe; - create_session(&session); - session_test = session; - rpc_cpe = list_entry(&(session->head_rpc_cpe), struct rpc, list); + + rpc_cpe = list_entry(&(cwmp_main->session->head_rpc_cpe), struct rpc, list); /* * Valid path */ - prepare_gpa_soap_request(session, "Device.DeviceInfo.UpTime"); - prepare_session_for_rpc_method_call(session); + prepare_gpa_soap_request("Device.DeviceInfo.UpTime"); + prepare_session_for_rpc_method_call(); - int ret = cwmp_handle_rpc_cpe_get_parameter_attributes(session, rpc_cpe); + int ret = cwmp_handle_rpc_cpe_get_parameter_attributes(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -683,8 +836,8 @@ static void soap_get_parameter_attributes_message_test(void **state) n = mxmlFindElement(param_attr, param_attr, "AccessList", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Not Valid path @@ -692,14 +845,14 @@ static void soap_get_parameter_attributes_message_test(void **state) mxml_node_t *fault_code = NULL, *fault_string = NULL, *detail = NULL, *detail_code = NULL, *detail_string = NULL; char *invalid_parameter[1] = { "Device.DeviceInfo.pTime" }; - prepare_gpv_soap_request(session, invalid_parameter, 1); + prepare_gpv_soap_request(invalid_parameter, 1); - prepare_session_for_rpc_method_call(session); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_get_parameter_values(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_get_parameter_values(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -722,22 +875,23 @@ static void soap_get_parameter_attributes_message_test(void **state) assert_string_equal(detail_code->child->value.opaque, "9005"); detail_string = mxmlFindElement(detail, detail, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(detail_string); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); - session->head_rpc_acs.next = NULL; + cwmp_main->session->head_rpc_acs.next = NULL; unit_test_end_test_destruction(); clean_name_space(); - session_test = NULL; + + } -static void prepare_spa_soap_request(struct session *session, char *parameter, char *notification, char *notification_change) +static void prepare_spa_soap_request(char *parameter, char *notification, char *notification_change) { mxml_node_t *n = NULL, *set_attr = NULL; - session->tree_in = mxmlLoadString(NULL, CWMP_SETATTRIBUTES_REQ, MXML_OPAQUE_CALLBACK); - xml_recreate_namespace(session->tree_in); - set_attr = mxmlFindElement(session->tree_in, session->tree_in, "SetParameterAttributesStruct", NULL, NULL, MXML_DESCEND); + cwmp_main->session->tree_in = mxmlLoadString(NULL, CWMP_SETATTRIBUTES_REQ, MXML_OPAQUE_CALLBACK); + xml_recreate_namespace(cwmp_main->session->tree_in); + set_attr = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, "SetParameterAttributesStruct", NULL, NULL, MXML_DESCEND); n = mxmlFindElement(set_attr, set_attr, "Name", NULL, NULL, MXML_DESCEND); n = mxmlNewOpaque(n, parameter); n = mxmlFindElement(set_attr, set_attr, "Notification", NULL, NULL, MXML_DESCEND); @@ -748,25 +902,23 @@ static void prepare_spa_soap_request(struct session *session, char *parameter, c static void soap_set_parameter_attributes_message_test(void **state) { - struct session *session = NULL; mxml_node_t *env = NULL, *n = NULL; struct rpc *rpc_cpe; - create_session(&session); - session_test = session; - rpc_cpe = list_entry(&(session->head_rpc_cpe), struct rpc, list); + + rpc_cpe = list_entry(&(cwmp_main->session->head_rpc_cpe), struct rpc, list); /* * Valid path */ - prepare_spa_soap_request(session, "Device.DeviceInfo.UpTime", "1", "true"); - prepare_session_for_rpc_method_call(session); + prepare_spa_soap_request("Device.DeviceInfo.UpTime", "1", "true"); + prepare_session_for_rpc_method_call(); - int ret = cwmp_handle_rpc_cpe_set_parameter_attributes(session, rpc_cpe); + int ret = cwmp_handle_rpc_cpe_set_parameter_attributes(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -777,20 +929,20 @@ static void soap_set_parameter_attributes_message_test(void **state) n = mxmlFindElement(n, n, "cwmp:SetParameterAttributesResponse", NULL, NULL, MXML_DESCEND); assert_non_null(n); assert_null(n->child); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Not Valid path */ mxml_node_t *cwmp_fault = NULL; - prepare_spa_soap_request(session, "Device.DeviceInfo.pTime", "1", "true"); - prepare_session_for_rpc_method_call(session); + prepare_spa_soap_request("Device.DeviceInfo.pTime", "1", "true"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_set_parameter_attributes(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_set_parameter_attributes(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -810,19 +962,19 @@ static void soap_set_parameter_attributes_message_test(void **state) n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Not Valid Notification value */ - prepare_spa_soap_request(session, "Device.DeviceInfo.UpTime", "8", "true"); - prepare_session_for_rpc_method_call(session); + prepare_spa_soap_request("Device.DeviceInfo.UpTime", "8", "true"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_set_parameter_attributes(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_set_parameter_attributes(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -842,20 +994,20 @@ static void soap_set_parameter_attributes_message_test(void **state) n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Invalid Notification String */ - prepare_spa_soap_request(session, "Device.DeviceInfo.UpTime", "balabala", "true"); - prepare_session_for_rpc_method_call(session); + prepare_spa_soap_request("Device.DeviceInfo.UpTime", "balabala", "true"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_set_parameter_attributes(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_set_parameter_attributes(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -875,20 +1027,20 @@ static void soap_set_parameter_attributes_message_test(void **state) n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); /* * Invalid NotificationChange */ - prepare_spa_soap_request(session, "Device.DeviceInfo.UpTime", "2", "5"); - prepare_session_for_rpc_method_call(session); + prepare_spa_soap_request( "Device.DeviceInfo.UpTime", "2", "5"); + prepare_session_for_rpc_method_call(); - ret = cwmp_handle_rpc_cpe_set_parameter_attributes(session, rpc_cpe); + ret = cwmp_handle_rpc_cpe_set_parameter_attributes(rpc_cpe); assert_int_equal(ret, 0); - env = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); assert_non_null(env); n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); assert_non_null(n); @@ -908,13 +1060,273 @@ static void soap_set_parameter_attributes_message_test(void **state) n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); assert_non_null(n); - MXML_DELETE(session->tree_in); - MXML_DELETE(session->tree_out); + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); - session->head_rpc_acs.next = NULL; + cwmp_main->session->head_rpc_acs.next = NULL; + unit_test_end_test_destruction(); + clean_name_space(); + + +} + +static void prepare_download_soap_request(char *url, char *file_type, char *username, char *password, char *file_size, char *delay_second) +{ + mxml_node_t *n = NULL, *download = NULL; + cwmp_main->session->tree_in = mxmlLoadString(NULL, CWMP_DOWNLOAD_REQ, MXML_OPAQUE_CALLBACK); + xml_recreate_namespace(cwmp_main->session->tree_in); + download = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, "cwmp:Download", NULL, NULL, MXML_DESCEND); + n = mxmlFindElement(download, download, "URL", NULL, NULL, MXML_DESCEND); + n = mxmlNewOpaque(n, url); + n = mxmlFindElement(download, download, "FileType", NULL, NULL, MXML_DESCEND); + n = mxmlNewOpaque(n, file_type); + n = mxmlFindElement(download, download, "Username", NULL, NULL, MXML_DESCEND); + n = mxmlNewOpaque(n, username); + n = mxmlFindElement(download, download, "Password", NULL, NULL, MXML_DESCEND); + n = mxmlNewOpaque(n, password); + n = mxmlFindElement(download, download, "FileSize", NULL, NULL, MXML_DESCEND); + n = mxmlNewOpaque(n, file_size); + n = mxmlFindElement(download, download, "DelaySeconds", NULL, NULL, MXML_DESCEND); + n = mxmlNewOpaque(n, delay_second); +} + +static void free_download() +{ + if (list_download.next != &(list_download)) { + struct list_head *ilist, *q; + list_for_each_safe (ilist, q, &(list_download)) { + struct download *download; + download = list_entry(ilist, struct download, list); + bkp_session_delete_download(download); + cwmp_free_download_request(download); + } + } +} + +static void soap_download_message_test(void **state) //TODO will be properly done with Download unit tests +{ + mxml_node_t *env = NULL, *n = NULL, *download_node = NULL; + struct rpc *rpc_cpe; + + + + rpc_cpe = list_entry(&(cwmp_main->session->head_rpc_cpe), struct rpc, list); + + /* + * Valid Arguments + */ + prepare_download_soap_request("http://192.168.1.160/tr069/DG400PRIME-A-IOPSYS-6.2.0BETA1-210530_2348_nand_squashfs_update.pkgtb", "6 Stored Firmware Image", "iopsys", "iopsys", "0", "0"); + prepare_session_for_rpc_method_call(); + int ret = cwmp_handle_rpc_cpe_download(rpc_cpe); + assert_int_equal(ret, 0); + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + assert_non_null(env); + n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "cwmp:ID", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(env, env, "soap_env:Body", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + download_node = mxmlFindElement(n, n, "cwmp:DownloadResponse", NULL, NULL, MXML_DESCEND); + assert_non_null(download_node); + n = mxmlFindElement(download_node, download_node, "Status", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "1"); + n = mxmlFindElement(download_node, download_node, "StartTime", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(download_node, download_node, "CompleteTime", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + free_download(); + bkp_tree_clean(); + + /* + * wrong FileType + */ + + mxml_node_t *cwmp_fault = NULL; + prepare_download_soap_request("http://192.168.1.160/tr069/DG400PRIME-A-IOPSYS-6.2.0BETA1-210530_2348_nand_squashfs_update.pkgtb", "7 New FileType", "iopsys", "iopsys", "0", "0"); + prepare_session_for_rpc_method_call(); + ret = cwmp_handle_rpc_cpe_download(rpc_cpe); + assert_int_equal(ret, 0); + + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + assert_non_null(env); + n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "cwmp:ID", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(env, env, "soap_env:Body", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + + + n = mxmlFindElement(n, n, "soap_env:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "detail", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + cwmp_fault = mxmlFindElement(n, n, "cwmp:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(cwmp_fault); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultCode", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "9003"); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + free_download(); + bkp_tree_clean(); + + /* + * Wrong FileSize + */ + prepare_download_soap_request("http://192.168.1.160/tr069/DG400PRIME-A-IOPSYS-6.2.0BETA1-210530_2348_nand_squashfs_update.pkgtb", "6 Stored Firmware Image", "iopsys", "iopsys", "-15", "0"); + prepare_session_for_rpc_method_call(); + ret = cwmp_handle_rpc_cpe_download(rpc_cpe); + assert_int_equal(ret, 0); + + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + assert_non_null(env); + n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "cwmp:ID", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(env, env, "soap_env:Body", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + + + n = mxmlFindElement(n, n, "soap_env:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "detail", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + cwmp_fault = mxmlFindElement(n, n, "cwmp:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(cwmp_fault); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultCode", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "9003"); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + free_download(); + bkp_tree_clean(); + + cwmp_main->session->head_rpc_acs.next = NULL; + unit_test_end_test_destruction(); + clean_name_space(); + + /* + * Wrong DelaySeconds + */ + + prepare_download_soap_request("http://192.168.1.160/tr069/DG400PRIME-A-IOPSYS-6.2.0BETA1-210530_2348_nand_squashfs_update.pkgtb", "6 Stored Firmware Image", "iopsys", "iopsys", "0", "jjjk"); + prepare_session_for_rpc_method_call(); + ret = cwmp_handle_rpc_cpe_download( rpc_cpe); + assert_int_equal(ret, 0); + + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + assert_non_null(env); + n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "cwmp:ID", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(env, env, "soap_env:Body", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + + + n = mxmlFindElement(n, n, "soap_env:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "detail", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + cwmp_fault = mxmlFindElement(n, n, "cwmp:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(cwmp_fault); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultCode", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "9003"); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + free_download(); + bkp_tree_clean(); + + /* + * Invalid username + */ + prepare_download_soap_request("http://192.168.1.160/tr069/DG400PRIME-A-IOPSYS-6.2.0BETA1-210530_2348_nand_squashfs_update.pkgtb", "6 Stored Firmware Image", INVALID_USER, "iopsys", "0", "0"); + prepare_session_for_rpc_method_call(); + ret = cwmp_handle_rpc_cpe_download(rpc_cpe); + assert_int_equal(ret, 0); + + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + assert_non_null(env); + n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "cwmp:ID", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(env, env, "soap_env:Body", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + + + n = mxmlFindElement(n, n, "soap_env:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "detail", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + cwmp_fault = mxmlFindElement(n, n, "cwmp:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(cwmp_fault); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultCode", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "9003"); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + free_download(); + bkp_tree_clean(); + + /* + * Invalid password + */ + prepare_download_soap_request("http://192.168.1.160/tr069/DG400PRIME-A-IOPSYS-6.2.0BETA1-210530_2348_nand_squashfs_update.pkgtb", "6 Stored Firmware Image", "iopsys", INVALID_PASS, "0", "0"); + prepare_session_for_rpc_method_call(); + ret = cwmp_handle_rpc_cpe_download(rpc_cpe); + assert_int_equal(ret, 0); + + env = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + assert_non_null(env); + n = mxmlFindElement(env, env, "soap_env:Header", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "cwmp:ID", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(env, env, "soap_env:Body", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + + + n = mxmlFindElement(n, n, "soap_env:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + n = mxmlFindElement(n, n, "detail", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + cwmp_fault = mxmlFindElement(n, n, "cwmp:Fault", NULL, NULL, MXML_DESCEND); + assert_non_null(cwmp_fault); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultCode", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + assert_string_equal(n->child->value.opaque, "9003"); + n = mxmlFindElement(cwmp_fault, cwmp_fault, "FaultString", NULL, NULL, MXML_DESCEND); + assert_non_null(n); + + MXML_DELETE(cwmp_main->session->tree_in); + MXML_DELETE(cwmp_main->session->tree_out); + free_download(); + bkp_tree_clean(); + + cwmp_main->session->head_rpc_acs.next = NULL; unit_test_end_test_destruction(); clean_name_space(); - session_test = NULL; } int icwmp_soap_msg_test(void) @@ -924,10 +1336,12 @@ int icwmp_soap_msg_test(void) cmocka_unit_test(add_event_test), cmocka_unit_test(soap_inform_message_test), cmocka_unit_test(soap_get_param_value_message_test), + //cmocka_unit_test(soap_set_param_value_message_test), cmocka_unit_test(soap_add_object_message_test), cmocka_unit_test(soap_delete_object_message_test), cmocka_unit_test(soap_get_parameter_attributes_message_test), cmocka_unit_test(soap_set_parameter_attributes_message_test), + //cmocka_unit_test(soap_download_message_test) //TODO will be properly done with Download unit tests }; return cmocka_run_group_tests(tests, soap_unit_tests_init, soap_unit_tests_clean); diff --git a/test/cmocka/icwmp_uci_unit_test.c b/test/cmocka/icwmp_uci_unit_test.c index 4c948f1..87efe1b 100644 --- a/test/cmocka/icwmp_uci_unit_test.c +++ b/test/cmocka/icwmp_uci_unit_test.c @@ -31,9 +31,9 @@ static int cwmp_uci_unit_tests_init(void **state) static int cwmp_uci_unit_tests_clean(void **state) { icwmp_cleanmem(); - cwmp_uci_exit(); if (list != NULL) cwmp_free_uci_list(list); + cwmp_uci_exit(); return 0; } @@ -81,7 +81,6 @@ static void cwmp_uci_get_tests(void **state) error = cwmp_uci_get_value_by_section_string(s, "wrong_option", &value); assert_null(value); assert_int_equal(error, UCI_ERR_NOTFOUND); - } static void cwmp_uci_set_tests(void **state) @@ -138,27 +137,24 @@ static void cwmp_uci_set_tests(void **state) error = cwmp_uci_get_option_value_string("cwmp", "wront_section", "wrong_option", UCI_VARSTATE_CONFIG, &value); assert_int_equal(error, UCI_ERR_NOTFOUND); assert_null(value); - } static void cwmp_uci_add_tests(void **state) { struct uci_section *s = NULL; - int error = UCI_OK; + int error = UCI_OK, cmp_cfg = 0; error = cwmp_uci_add_section("cwmp", "acs", UCI_STANDARD_CONFIG, &s); assert_non_null(s); assert_int_equal(error, UCI_OK); - cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); assert_int_equal(strncmp(section_name(s), "cfg", 3), 0); - s = NULL; + cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); error = cwmp_uci_add_section("new_package", "new_section", UCI_STANDARD_CONFIG, &s); assert_non_null(s); assert_int_equal(error, UCI_OK); - cwmp_commit_package("new_package", UCI_STANDARD_CONFIG); assert_int_equal(strncmp(section_name(s), "cfg", 3), 0); - s = NULL; + cwmp_commit_package("new_package", UCI_STANDARD_CONFIG); error = cwmp_uci_add_section_with_specific_name("cwmp", "acs", "new_acs", UCI_STANDARD_CONFIG); assert_int_equal(error, UCI_OK); @@ -179,29 +175,26 @@ static void cwmp_uci_list_tests(void **state) assert_int_equal(error, UCI_OK); error = cwmp_uci_add_list_value("cwmp", "cpe", "optionlist", "val2", UCI_STANDARD_CONFIG); assert_int_equal(error, UCI_OK); - cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); error = cwmp_uci_get_cwmp_standard_option_value_list("cwmp", "cpe", "optionlist", &list); assert_int_equal(error, UCI_TYPE_LIST); list_string = cwmp_uci_list_to_string(list, ","); assert_non_null(list_string); assert_string_equal(list_string, "val1,val2"); list_string = NULL; - if(list != NULL) + if(list != NULL) { cwmp_free_uci_list(list); + list = NULL; + } error = cwmp_uci_add_list_value("cwmp", "wrong_section", "optionlist", "val1", UCI_STANDARD_CONFIG); assert_int_equal(error, UCI_ERR_INVAL); error = cwmp_uci_add_list_value("cwmp", "wrong_section", "optionlist", "val2", UCI_STANDARD_CONFIG); assert_int_equal(error, UCI_ERR_INVAL); - cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); error = cwmp_uci_get_cwmp_standard_option_value_list("cwmp", "wrong_section", "optionlist", &list); assert_int_equal(error, UCI_ERR_NOTFOUND); assert_null(list); list_string = cwmp_uci_list_to_string(list, ","); assert_null(list_string); - if(list != NULL) - cwmp_free_uci_list(list); - } int icwmp_uci_test(void) diff --git a/test/files/etc/board-db/config/device b/test/files/etc/board-db/config/device deleted file mode 100644 index 5c60ca1..0000000 --- a/test/files/etc/board-db/config/device +++ /dev/null @@ -1,11 +0,0 @@ -config deviceinfo 'deviceinfo' - option Manufacturer 'iopsys' - option ProductClass 'FirstClass' - option SerialNumber '000000001' - option SoftwareVersion 'IOPSYS-CODE-ANALYSIS' - option HardwareVersion '1.0' - option DeviceCategory 'Gateway' - option ModelName 'ModelName' - option Description 'Iopsys code analysis test simulator' - option ManufacturerOUI 'XXX' - option BaseMACAddress 'feeddeadbeef' diff --git a/test/files/etc/config/cwmp b/test/files/etc/config/cwmp index e284351..34ba23c 100644 --- a/test/files/etc/config/cwmp +++ b/test/files/etc/config/cwmp @@ -14,12 +14,13 @@ config acs 'acs' option https_ssl_capath '' option ipv6_enable '0' option ip_version '4' + option url 'http://127.0.0.1:7547' config cpe 'cpe' - option interface 'eth0' + option interface 'lo' option default_wan_interface 'wan' option log_to_console 'disable' - option log_to_syslog 'disable' + option log_to_syslog 'enable' option log_to_file 'enable' # log_severity: INFO (Default) # log_severity possible configs: EMERG, ALERT, CRITIC ,ERROR, WARNING, NOTICE, INFO, DEBUG diff --git a/test/script/common.sh b/test/script/common.sh index c0226c7..ff4e113 100644 --- a/test/script/common.sh +++ b/test/script/common.sh @@ -50,12 +50,7 @@ function check_session() function remove_icwmp_log() { - rm -f $icwmp_log_file - - if [ -f "$icwmp_log_file" ]; then - echo "$icwmp_log_file exists" >> ./funl-test-debug.log - exit 1 - fi + echo "" > $icwmp_log_file } function print_tag_value() diff --git a/test/script/test_seq.txt b/test/script/test_seq.txt new file mode 100644 index 0000000..d690461 --- /dev/null +++ b/test/script/test_seq.txt @@ -0,0 +1,6 @@ +verify_add_method.sh +verify_delete_method.sh +verify_get_method.sh +verify_set_method.sh +verify_download_method.sh +verify_cmd_line.sh diff --git a/test/script/verify_download_method.sh b/test/script/verify_download_method.sh index 8583e71..ea650a5 100755 --- a/test/script/verify_download_method.sh +++ b/test/script/verify_download_method.sh @@ -19,11 +19,15 @@ if [ "$status" != "1" ]; then exit 1 fi -rm /etc/icwmpd/dm_enabled_notify +rm /var/run/icwmpd/dm_enabled_notify remove_icwmp_log -echo "Restarting icwmpd in order to apply the new firmware" >> ./funl-test-debug.log -supervisorctl restart icwmpd >> ./funl-test-debug.log sleep 5 +echo "Restarting icwmpd in order to apply the new firmware" >> ./funl-test-debug.log +#/builds/iopsys/icwmp/bin/icwmpd -b & +supervisorctl stop icwmpd +sleep 3 +supervisorctl start icwmpd >> ./funl-test-debug.log +sleep 10 check_session "TransferComplete" received_command_key=$(print_tag_value "cwmp:TransferComplete" "CommandKey") if [ "$sent_command_key" != "$received_command_key" ]; then diff --git a/ubus.c b/ubus.c index c549088..6b159d3 100755 --- a/ubus.c +++ b/ubus.c @@ -11,22 +11,21 @@ * Copyright (C) 2012 Luka Perkov */ -#include -#include #include -#include #include "ubus.h" #include "session.h" #include "log.h" +#include "cwmp_time.h" +#include "event.h" +#include "backupSession.h" #include "sched_inform.h" -#include "http.h" +#include "cwmp_du_state.h" #include "download.h" #include "upload.h" -#include "cwmp_du_state.h" -#include "netlink.h" -#include "event.h" -#include "cwmp_time.h" +#include "http.h" +#include "soap.h" +#include "cwmp_event.h" static struct ubus_context *ctx = NULL; @@ -50,7 +49,7 @@ static const struct blobmsg_policy command_policy[] = { static int cwmp_handle_command(struct ubus_context *ctx, struct ubus_object *obj __attribute__((unused)), struct ubus_request_data *req, const char *method __attribute__((unused)), struct blob_attr *msg) { struct blob_attr *tb[__COMMAND_MAX]; - struct blob_buf blob_command; + static struct blob_buf blob_command; blobmsg_parse(command_policy, ARRAYSIZEOF(command_policy), tb, blob_data(msg), blob_len(msg)); @@ -71,15 +70,13 @@ static int cwmp_handle_command(struct ubus_context *ctx, struct ubus_object *obj return -1; } else if (!strcmp("reload", cmd)) { CWMP_LOG(INFO, "triggered ubus reload"); - if (cwmp_main.session_status.last_status == SESSION_RUNNING) { + if (cwmp_main->session->session_status.last_status == SESSION_RUNNING) { cwmp_set_end_session(END_SESSION_RELOAD); blobmsg_add_u32(&blob_command, "status", 0); if (snprintf(info, sizeof(info), "Session running, reload at the end of the session") == -1) return -1; } else { - pthread_mutex_lock(&(cwmp_main.mutex_session_queue)); cwmp_apply_acs_changes(); - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); blobmsg_add_u32(&blob_command, "status", 0); if (snprintf(info, sizeof(info), "icwmpd config reloaded") == -1) return -1; @@ -98,30 +95,21 @@ static int cwmp_handle_command(struct ubus_context *ctx, struct ubus_object *obj return -1; } else if (!strcmp("exit", cmd)) { ubus_exit = true; - thread_end = true; - if (cwmp_main.session_status.last_status == SESSION_RUNNING) + if (snprintf(info, sizeof(info), "icwmpd daemon stopped") == -1) + return -1; + + cwmp_stop = true; + + if (cwmp_main->session->session_status.last_status == SESSION_RUNNING) http_set_timeout(); - pthread_cond_signal(&(cwmp_main.threshold_session_send)); - pthread_cond_signal(&(cwmp_main.threshold_periodic)); - pthread_cond_signal(&(cwmp_main.threshold_notify_periodic)); - pthread_cond_signal(&threshold_schedule_inform); - pthread_cond_signal(&threshold_download); - pthread_cond_signal(&threshold_change_du_state); - pthread_cond_signal(&threshold_schedule_download); - pthread_cond_signal(&threshold_apply_schedule_download); - pthread_cond_signal(&threshold_upload); - + uloop_timeout_cancel(&retry_session_timer); + uloop_timeout_cancel(&priodic_session_timer); + uloop_timeout_cancel(&session_timer); uloop_end(); + shutdown(cwmp_main->cr_socket_desc, SHUT_RDWR); - shutdown(cwmp_main.cr_socket_desc, SHUT_RDWR); - - if (!signal_exit) - kill(getpid(), SIGTERM); - - if (snprintf(info, sizeof(info), "icwmpd daemon stopped") == -1) - return -1; } else { blobmsg_add_u32(&blob_command, "status", -1); if (snprintf(info, sizeof(info), "%s command is not supported", cmd) == -1) @@ -129,6 +117,7 @@ static int cwmp_handle_command(struct ubus_context *ctx, struct ubus_object *obj } blobmsg_add_string(&blob_command, "info", info); + ubus_send_reply(ctx, req, blob_command.head); blob_buf_free(&blob_command); @@ -143,11 +132,11 @@ static inline time_t get_session_status_next_time() schedule_inform = list_entry(list_schedule_inform.next, struct schedule_inform, list); ntime = schedule_inform->scheduled_time; } - if (!ntime || (cwmp_main.session_status.next_retry && ntime > cwmp_main.session_status.next_retry)) { - ntime = cwmp_main.session_status.next_retry; + if (!ntime || (cwmp_main->session->session_status.next_retry && ntime > cwmp_main->session->session_status.next_retry)) { + ntime = cwmp_main->session->session_status.next_retry; } - if (!ntime || (cwmp_main.session_status.next_periodic && ntime > cwmp_main.session_status.next_periodic)) { - ntime = cwmp_main.session_status.next_periodic; + if (!ntime || (cwmp_main->session->session_status.next_periodic && ntime > cwmp_main->session->session_status.next_periodic)) { + ntime = cwmp_main->session->session_status.next_periodic; } return ntime; } @@ -156,21 +145,20 @@ static int cwmp_handle_status(struct ubus_context *ctx, struct ubus_object *obj { void *c; time_t ntime = 0; - struct blob_buf blob_status; + static struct blob_buf blob_status; - memset(&blob_status, 0, sizeof(struct blob_buf)); blob_buf_init(&blob_status, 0); c = blobmsg_open_table(&blob_status, "cwmp"); blobmsg_add_string(&blob_status, "status", "up"); - blobmsg_add_string(&blob_status, "start_time", mix_get_time_of(cwmp_main.start_time)); - blobmsg_add_string(&blob_status, "acs_url", cwmp_main.conf.acsurl); + blobmsg_add_string(&blob_status, "start_time", mix_get_time_of(cwmp_main->start_time)); + blobmsg_add_string(&blob_status, "acs_url", cwmp_main->conf.acsurl); blobmsg_close_table(&blob_status, c); c = blobmsg_open_table(&blob_status, "last_session"); - blobmsg_add_string(&blob_status, "status", cwmp_main.session_status.last_start_time ? arr_session_status[cwmp_main.session_status.last_status] : "N/A"); - blobmsg_add_string(&blob_status, "start_time", cwmp_main.session_status.last_start_time ? mix_get_time_of(cwmp_main.session_status.last_start_time) : "N/A"); - blobmsg_add_string(&blob_status, "end_time", cwmp_main.session_status.last_end_time ? mix_get_time_of(cwmp_main.session_status.last_end_time) : "N/A"); + blobmsg_add_string(&blob_status, "status", cwmp_main->session->session_status.last_start_time ? arr_session_status[cwmp_main->session->session_status.last_status] : "N/A"); + blobmsg_add_string(&blob_status, "start_time", cwmp_main->session->session_status.last_start_time ? mix_get_time_of(cwmp_main->session->session_status.last_start_time) : "N/A"); + blobmsg_add_string(&blob_status, "end_time", cwmp_main->session->session_status.last_end_time ? mix_get_time_of(cwmp_main->session->session_status.last_end_time) : "N/A"); blobmsg_close_table(&blob_status, c); c = blobmsg_open_table(&blob_status, "next_session"); @@ -181,9 +169,9 @@ static int cwmp_handle_status(struct ubus_context *ctx, struct ubus_object *obj blobmsg_close_table(&blob_status, c); c = blobmsg_open_table(&blob_status, "statistics"); - blobmsg_add_u32(&blob_status, "success_sessions", cwmp_main.session_status.success_session); - blobmsg_add_u32(&blob_status, "failure_sessions", cwmp_main.session_status.failure_session); - blobmsg_add_u32(&blob_status, "total_sessions", cwmp_main.session_status.success_session + cwmp_main.session_status.failure_session); + blobmsg_add_u32(&blob_status, "success_sessions", cwmp_main->session->session_status.success_session); + blobmsg_add_u32(&blob_status, "failure_sessions", cwmp_main->session->session_status.failure_session); + blobmsg_add_u32(&blob_status, "total_sessions", cwmp_main->session->session_status.success_session + cwmp_main->session->session_status.failure_session); blobmsg_close_table(&blob_status, c); ubus_send_reply(ctx, req, blob_status.head); @@ -209,9 +197,8 @@ static int cwmp_handle_inform(struct ubus_context *ctx, struct ubus_object *obj struct blob_attr *tb[__INFORM_MAX]; bool grm = false; char *event = ""; - struct blob_buf blob_inform; + static struct blob_buf blob_inform; - memset(&blob_inform, 0, sizeof(struct blob_buf)); blob_buf_init(&blob_inform, 0); blobmsg_parse(inform_policy, ARRAYSIZEOF(inform_policy), tb, blob_data(msg), blob_len(msg)); @@ -222,33 +209,25 @@ static int cwmp_handle_inform(struct ubus_context *ctx, struct ubus_object *obj if (tb[INFORM_EVENT]) { event = blobmsg_data(tb[INFORM_EVENT]); } + if (grm) { struct event_container *event_container; - struct session *session; - pthread_mutex_lock(&(cwmp_main.mutex_session_queue)); - event_container = cwmp_add_event_container(&cwmp_main, EVENT_IDX_2PERIODIC, ""); - if (event_container == NULL) { - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); + event_container = cwmp_add_event_container(EVENT_IDX_2PERIODIC, ""); + if (event_container == NULL) return 0; - } + cwmp_save_event_container(event_container); - session = list_entry(cwmp_main.head_event_container, struct session, head_event_container); - if (cwmp_add_session_rpc_acs(session, RPC_ACS_GET_RPC_METHODS) == NULL) { - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); + //session = list_entry(cwmp_main.head_event_container, struct session, head_event_container); + if (cwmp_add_session_rpc_acs(RPC_ACS_GET_RPC_METHODS) == NULL) return 0; - } - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); - pthread_cond_signal(&(cwmp_main.threshold_session_send)); + blobmsg_add_u32(&blob_inform, "status", 1); blobmsg_add_string(&blob_inform, "info", "Session with GetRPCMethods will start"); } else { int event_code = cwmp_get_int_event_code(event); - pthread_mutex_lock(&(cwmp_main.mutex_session_queue)); - cwmp_add_event_container(&cwmp_main, event_code, ""); - pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); - pthread_cond_signal(&(cwmp_main.threshold_session_send)); - if (cwmp_main.session_status.last_status == SESSION_RUNNING) { + cwmp_add_event_container(event_code, ""); + if (cwmp_main->session->session_status.last_status == SESSION_RUNNING) { blobmsg_add_u32(&blob_inform, "status", -1); blobmsg_add_string(&blob_inform, "info", "Session already running, event will be sent at the end of the session"); } else { @@ -256,9 +235,9 @@ static int cwmp_handle_inform(struct ubus_context *ctx, struct ubus_object *obj blobmsg_add_string(&blob_inform, "info", "Session started"); } } + trigger_cwmp_session_timer(); ubus_send_reply(ctx, req, blob_inform.head); blob_buf_free(&blob_inform); - return 0; } @@ -277,20 +256,9 @@ static struct ubus_object main_object = { .n_methods = ARRAYSIZEOF(freecwmp_methods), }; -int cwmp_ubus_init(struct cwmp *cwmp) +int cwmp_ubus_init() { - uloop_init(); - - if (netlink_init()) { - CWMP_LOG(ERROR, "netlink initialization failed"); - } - - if (cwmp->conf.ipv6_enable) { - if (netlink_init_v6()) { - CWMP_LOG(ERROR, "netlink initialization failed"); - } - } - ctx = ubus_connect(cwmp->conf.ubus_socket); + ctx = ubus_connect(cwmp_main->conf.ubus_socket); if (!ctx) return -1; @@ -299,8 +267,6 @@ int cwmp_ubus_init(struct cwmp *cwmp) if (ubus_add_object(ctx, &main_object)) return -1; - uloop_run(); - uloop_done(); return 0; } @@ -355,7 +321,7 @@ int cwmp_ubus_call(const char *obj, const char *method, const struct cwmp_ubus_a } blobmsg_close_array(&b, a); } else if (u_args[i].type == UBUS_List_Param_Set) { - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; void *a; a = blobmsg_open_array(&b, u_args[i].key); list_for_each_entry (param_value, u_args[i].val.param_value_list, list) { @@ -369,7 +335,7 @@ int cwmp_ubus_call(const char *obj, const char *method, const struct cwmp_ubus_a } blobmsg_close_array(&b, a); } else if (u_args[i].type == UBUS_List_Param_Get) { - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; void *a; a = blobmsg_open_array(&b, u_args[i].key); list_for_each_entry (param_value, u_args[i].val.param_value_list, list) { @@ -379,7 +345,7 @@ int cwmp_ubus_call(const char *obj, const char *method, const struct cwmp_ubus_a } blobmsg_close_array(&b, a); } else if (u_args[i].type == UBUS_Obj_Obj) { - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; json_object *input_json_obj = json_object_new_object(); list_for_each_entry (param_value, u_args[i].val.param_value_list, list) { if (!param_value->name) diff --git a/upload.c b/upload.c index be32575..f5fff05 100644 --- a/upload.c +++ b/upload.c @@ -8,23 +8,26 @@ * Author Omar Kallel */ +#include #include -#include +#include +#include "common.h" #include "upload.h" -#include "download.h" -#include "cwmp_time.h" #include "datamodel_interface.h" +#include "download.h" #include "log.h" +#include "cwmp_time.h" #include "backupSession.h" -#include "event.h" #include "cwmp_uci.h" +#include "event.h" +#include "subprocess.h" +#include "session.h" #define CURL_TIMEOUT 20 LIST_HEAD(list_upload); -pthread_cond_t threshold_upload; pthread_mutex_t mutex_upload = PTHREAD_MUTEX_INITIALIZER; int lookup_vcf_name(char *instance, char **value) @@ -33,11 +36,9 @@ int lookup_vcf_name(char *instance, char **value) char *err = NULL; LIST_HEAD(vcf_parameters); snprintf(vcf_name_parameter, sizeof(vcf_name_parameter), "Device.DeviceInfo.VendorConfigFile.%s.Name", instance); - if (cwmp_get_parameter_values(vcf_name_parameter, &vcf_parameters) != NULL) { - CWMP_LOG(ERROR, "Not able to get the value of the parameter %s : %s", vcf_name_parameter, err); + if ((err = cwmp_get_parameter_values(vcf_name_parameter, &vcf_parameters)) != NULL) return -1; - } - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, &vcf_parameters, list) { *value = strdup(param_value->value); break; @@ -52,11 +53,9 @@ int lookup_vlf_name(char *instance, char **value) char *err = NULL; LIST_HEAD(vlf_parameters); snprintf(vlf_name_parameter, sizeof(vlf_name_parameter), "Device.DeviceInfo.VendorLogFile.%s.Name", instance); - if (cwmp_get_parameter_values(vlf_name_parameter, &vlf_parameters) != NULL) { - CWMP_LOG(ERROR, "Not able to get the value of the parameter %s : %s", vlf_name_parameter, err); + if ((err = cwmp_get_parameter_values(vlf_name_parameter, &vlf_parameters)) != NULL) return -1; - } - struct cwmp_dm_parameter *param_value; + struct cwmp_dm_parameter *param_value = NULL; list_for_each_entry (param_value, &vlf_parameters, list) { *value = strdup(param_value->value); break; @@ -65,6 +64,9 @@ int lookup_vlf_name(char *instance, char **value) return 0; } +/* + * Upload file + */ int upload_file(const char *file_path, const char *url, const char *username, const char *password) { int res_code = 0; @@ -95,6 +97,58 @@ int upload_file(const char *file_path, const char *url, const char *username, co return res_code; } +char *upload_file_task_function(char *task) +{ + + struct blob_buf bbuf; + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + + if (blobmsg_add_json_from_string(&bbuf, task) == false) { + blob_buf_free(&bbuf); + return NULL; + } + const struct blobmsg_policy p[5] = { { "task", BLOBMSG_TYPE_STRING }, { "file_path", BLOBMSG_TYPE_STRING }, { "url", BLOBMSG_TYPE_STRING }, { "username", BLOBMSG_TYPE_STRING }, { "password", BLOBMSG_TYPE_STRING } }; + + struct blob_attr *tb[5] = { NULL, NULL, NULL, NULL, NULL}; + blobmsg_parse(p, 5, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head)); + char *task_name = blobmsg_get_string(tb[0]); + if (!task_name || strcmp(task_name, "upload") != 0) + return NULL; + char *file_path = blobmsg_get_string(tb[1]); + char *url = blobmsg_get_string(tb[2]); + char *username = blobmsg_get_string(tb[3]); + char *password = blobmsg_get_string(tb[4]); + + int http_code = upload_file(file_path, url, username, password); + char *http_ret = (char *)malloc(4 * sizeof(char)); + snprintf(http_ret, 4, "%d", http_code); + http_ret[3] = 0; + return http_ret; +} + +int upload_file_in_subprocess(const char *file_path, const char *url, const char *username, const char *password) +{ + subprocess_start(upload_file_task_function); + + struct blob_buf bbuf; + memset(&bbuf, 0, sizeof(struct blob_buf)); + blob_buf_init(&bbuf, 0); + blobmsg_add_string(&bbuf, "task", "upload"); + blobmsg_add_string(&bbuf, "file_path", file_path); + blobmsg_add_string(&bbuf, "url", url); + blobmsg_add_string(&bbuf, "username", username); + blobmsg_add_string(&bbuf, "password", password); + char *upload_task = blobmsg_format_json(bbuf.head, true); + blob_buf_free(&bbuf); + + if (upload_task != NULL) { + char *ret = execute_task_in_subprocess(upload_task); + return atoi(ret); + } + return 500; +} + int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptransfer_complete) { int error = FAULT_CPE_NO_FAULT; @@ -108,10 +162,8 @@ int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptrans if (pupload->file_type[0] == '1' || pupload->file_type[0] == '3') { if (pupload->f_instance && isdigit(pupload->f_instance[0])) { - name = NULL; lookup_vcf_name(pupload->f_instance, &name); if (name && strlen(name) > 0) { - // cppcheck-suppress uninitvar snprintf(file_path, sizeof(file_path), "/tmp/%s", name); cwmp_uci_export_package(name, file_path, UCI_STANDARD_CONFIG); FREE(name); @@ -165,90 +217,6 @@ end_upload: return error; } -void *thread_cwmp_rpc_cpe_upload(void *v) -{ - struct cwmp *cwmp = (struct cwmp *)v; - struct upload *pupload; - struct timespec upload_timeout = { 0, 0 }; - time_t current_time, stime; - int error = FAULT_CPE_NO_FAULT; - struct transfer_complete *ptransfer_complete; - long int time_of_grace = 3600, timeout; - - for (;;) { - - if (thread_end) - break; - - if (list_upload.next != &(list_upload)) { - pupload = list_entry(list_upload.next, struct upload, list); - stime = pupload->scheduled_time; - current_time = time(NULL); - if (pupload->scheduled_time != 0) - timeout = current_time - pupload->scheduled_time; - else - timeout = 0; - if ((timeout >= 0) && (timeout > time_of_grace)) { - pthread_mutex_lock(&mutex_upload); - bkp_session_delete_upload(pupload); - ptransfer_complete = calloc(1, sizeof(struct transfer_complete)); - if (ptransfer_complete != NULL) { - error = FAULT_CPE_DOWNLOAD_FAILURE; - - ptransfer_complete->command_key = strdup(pupload->command_key); - ptransfer_complete->start_time = strdup(mix_get_time()); - ptransfer_complete->complete_time = strdup(ptransfer_complete->start_time); - ptransfer_complete->fault_code = error; - ptransfer_complete->type = TYPE_UPLOAD; - bkp_session_insert_transfer_complete(ptransfer_complete); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - } - list_del(&(pupload->list)); - if (pupload->scheduled_time != 0) - count_download_queue--; - cwmp_free_upload_request(pupload); - pthread_mutex_unlock(&mutex_download); - continue; - } - if ((timeout >= 0) && (timeout <= time_of_grace)) { - pthread_mutex_lock(&(cwmp->mutex_session_send)); - CWMP_LOG(INFO, "Launch upload file %s", pupload->url); - error = cwmp_launch_upload(pupload, &ptransfer_complete); - if (error != FAULT_CPE_NO_FAULT) { - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - bkp_session_delete_transfer_complete(ptransfer_complete); - } else { - bkp_session_delete_transfer_complete(ptransfer_complete); - ptransfer_complete->fault_code = error; - bkp_session_insert_transfer_complete(ptransfer_complete); - bkp_session_save(); - cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete); - } - pthread_mutex_unlock(&(cwmp->mutex_session_send)); - pthread_cond_signal(&(cwmp->threshold_session_send)); - pthread_mutex_lock(&mutex_upload); - list_del(&(pupload->list)); - if (pupload->scheduled_time != 0) - count_download_queue--; - cwmp_free_upload_request(pupload); - pthread_mutex_unlock(&mutex_upload); - continue; - } - pthread_mutex_lock(&mutex_upload); - upload_timeout.tv_sec = stime; - pthread_cond_timedwait(&threshold_upload, &mutex_upload, &upload_timeout); - pthread_mutex_unlock(&mutex_upload); - } else { - pthread_mutex_lock(&mutex_upload); - pthread_cond_wait(&threshold_upload, &mutex_upload); - pthread_mutex_unlock(&mutex_upload); - } - } - return NULL; -} - int cwmp_free_upload_request(struct upload *upload) { if (upload != NULL) { @@ -291,3 +259,30 @@ int cwmp_scheduledUpload_remove_all() return CWMP_OK; } + +void cwmp_start_upload(struct uloop_timeout *timeout) +{ + struct upload *pupload; + int error = FAULT_CPE_NO_FAULT; + struct transfer_complete *ptransfer_complete; + + pupload = container_of(timeout, struct upload, handler_timer); + + CWMP_LOG(INFO, "Launch download file %s", pupload->url); + error = cwmp_launch_upload(pupload, &ptransfer_complete); + sleep(3); + if (error != FAULT_CPE_NO_FAULT) { + CWMP_LOG(ERROR, "Error while uploading the file: %s", pupload->url); + } + + bkp_session_insert_transfer_complete(ptransfer_complete); + bkp_session_save(); + cwmp_root_cause_transfer_complete(ptransfer_complete); + pthread_mutex_lock(&mutex_upload); + list_del(&(pupload->list)); + if (pupload->scheduled_time != 0) + count_download_queue--; + cwmp_free_upload_request(pupload); + pthread_mutex_unlock(&mutex_upload); + trigger_cwmp_session_timer(); +} diff --git a/xml.c b/xml.c index 6b326a5..24bc129 100644 --- a/xml.c +++ b/xml.c @@ -9,13 +9,13 @@ * Author Ahmed Zribi * Author Omar Kallel */ - #include "xml.h" +#include "common.h" #include "log.h" +#include "cwmp_zlib.h" +#include "http.h" #include "notifications.h" #include "messages.h" -#include "http.h" -#include "cwmp_zlib.h" static const char *soap_env_url = "http://schemas.xmlsoap.org/soap/envelope/"; static const char *soap_enc_url = "http://schemas.xmlsoap.org/soap/encoding/"; @@ -116,19 +116,19 @@ void xml_exit(void) FREE(ns.cwmp); } -int xml_send_message(struct cwmp *cwmp, struct session *session, struct rpc *rpc) +int xml_send_message(struct rpc *rpc) { char *s, *msg_out = NULL, *msg_in = NULL; char c[512]; int msg_out_len = 0, f, r = 0; mxml_node_t *b; - if (session->tree_out) { + if (cwmp_main->session->tree_out) { unsigned char *zmsg_out; - msg_out = mxmlSaveAllocString(session->tree_out, whitespace_cb); + msg_out = mxmlSaveAllocString(cwmp_main->session->tree_out, whitespace_cb); CWMP_LOG_XML_MSG(DEBUG, msg_out, XML_MSG_OUT); - if (cwmp->conf.compression != COMP_NONE) { - if (zlib_compress(msg_out, &zmsg_out, &msg_out_len, cwmp->conf.compression)) { + if (cwmp_main->conf.compression != COMP_NONE) { + if (zlib_compress(msg_out, &zmsg_out, &msg_out_len, cwmp_main->conf.compression)) { return -1; } FREE(msg_out); @@ -139,7 +139,7 @@ int xml_send_message(struct cwmp *cwmp, struct session *session, struct rpc *rpc } while (1) { f = 0; - if (http_send_message(cwmp, msg_out, msg_out_len, &msg_in)) { + if (http_send_message(msg_out, msg_out_len, &msg_in)) { goto error; } if (msg_in) { @@ -167,31 +167,31 @@ int xml_send_message(struct cwmp *cwmp, struct session *session, struct rpc *rpc } } - session->tree_in = mxmlLoadString(NULL, msg_in, MXML_OPAQUE_CALLBACK); - if (!session->tree_in) + cwmp_main->session->tree_in = mxmlLoadString(NULL, msg_in, MXML_OPAQUE_CALLBACK); + if (!cwmp_main->session->tree_in) goto error; - xml_recreate_namespace(session->tree_in); + xml_recreate_namespace(cwmp_main->session->tree_in); /* get NoMoreRequests or HolRequest*/ - session->hold_request = false; + cwmp_main->session->hold_request = false; if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "NoMoreRequests") == -1) goto error; - b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (b) { - b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST); + b = mxmlWalkNext(b, cwmp_main->session->tree_in, MXML_DESCEND_FIRST); if (b && b->type == MXML_OPAQUE && b->value.opaque) - session->hold_request = atoi(b->value.opaque); + cwmp_main->session->hold_request = (atoi(b->value.opaque)) ? true : false; } else { if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "HoldRequests") == -1) goto error; - b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (b) { - b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST); + b = mxmlWalkNext(b, cwmp_main->session->tree_in, MXML_DESCEND_FIRST); if (b && b->type == MXML_OPAQUE && b->value.opaque) - session->hold_request = atoi(b->value.opaque); + cwmp_main->session->hold_request = (atoi(b->value.opaque)) ? true : false; } } @@ -206,36 +206,34 @@ error: return -1; } -int xml_prepare_msg_out(struct session *session) +int xml_prepare_msg_out() { - struct cwmp *cwmp = &cwmp_main; - struct config *conf; - conf = &(cwmp->conf); + struct config *conf = &(cwmp_main->conf); mxml_node_t *n; - session->tree_out = mxmlLoadString(NULL, CWMP_RESPONSE_MESSAGE, MXML_OPAQUE_CALLBACK); - n = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); + cwmp_main->session->tree_out = mxmlLoadString(NULL, CWMP_RESPONSE_MESSAGE, MXML_OPAQUE_CALLBACK); + n = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND); if (!n) { return -1; } mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(conf->amd_version) - 1]); - if (!session->tree_out) + if (!cwmp_main->session->tree_out) return -1; return 0; } -int xml_set_cwmp_id(struct session *session) +int xml_set_cwmp_id() { char c[32]; mxml_node_t *b; /* define cwmp id */ - if (snprintf(c, sizeof(c), "%u", ++(cwmp_main.cwmp_id)) == -1) + if (snprintf(c, sizeof(c), "%u", ++(cwmp_main->cwmp_id)) == -1) return -1; - b = mxmlFindElement(session->tree_out, session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND); if (!b) return -1; @@ -246,7 +244,7 @@ int xml_set_cwmp_id(struct session *session) return 0; } -int xml_set_cwmp_id_rpc_cpe(struct session *session) +int xml_set_cwmp_id_rpc_cpe() { char c[512]; mxml_node_t *b; @@ -255,16 +253,16 @@ int xml_set_cwmp_id_rpc_cpe(struct session *session) if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "ID") == -1) return -1; - b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND); if (b) { /* ACS send ID parameter */ - b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST); + b = mxmlWalkNext(b, cwmp_main->session->tree_in, MXML_DESCEND_FIRST); if (!b || b->type != MXML_OPAQUE || !b->value.opaque) return 0; snprintf(c, sizeof(c), "%s", b->value.opaque); - b = mxmlFindElement(session->tree_out, session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND); + b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND); if (!b) return -1; @@ -273,7 +271,7 @@ int xml_set_cwmp_id_rpc_cpe(struct session *session) return -1; } else { /* ACS does not send ID parameter */ - int r = xml_set_cwmp_id(session); + int r = xml_set_cwmp_id(cwmp_main->session); return r; } return 0; @@ -370,9 +368,7 @@ error: int xml_prepare_lwnotification_message(char **msg_out) { mxml_node_t *lw_tree, *b, *parameter_list; - struct cwmp *cwmp = &cwmp_main; - struct config *conf; - conf = &(cwmp->conf); + struct config *conf = &(cwmp_main->conf); char *c = NULL; lw_tree = mxmlLoadString(NULL, CWMP_LWNOTIFICATION_MESSAGE, MXML_OPAQUE_CALLBACK); @@ -414,7 +410,7 @@ int xml_prepare_lwnotification_message(char **msg_out) if (!b) goto error; - b = mxmlNewOpaque(b, cwmp->deviceid.oui); + b = mxmlNewOpaque(b, cwmp_main->deviceid.oui); if (!b) goto error; @@ -422,7 +418,7 @@ int xml_prepare_lwnotification_message(char **msg_out) if (!b) goto error; - b = mxmlNewOpaque(b, cwmp->deviceid.productclass ? cwmp->deviceid.productclass : ""); + b = mxmlNewOpaque(b, cwmp_main->deviceid.productclass ? cwmp_main->deviceid.productclass : ""); if (!b) goto error; @@ -430,7 +426,7 @@ int xml_prepare_lwnotification_message(char **msg_out) if (!b) goto error; - b = mxmlNewOpaque(b, cwmp->deviceid.serialnumber ? cwmp->deviceid.serialnumber : ""); + b = mxmlNewOpaque(b, cwmp_main->deviceid.serialnumber ? cwmp_main->deviceid.serialnumber : ""); if (!b) goto error;