diff --git a/gitlab-ci/setup.sh b/gitlab-ci/setup.sh index 0240c5c..927f1d1 100755 --- a/gitlab-ci/setup.sh +++ b/gitlab-ci/setup.sh @@ -6,6 +6,8 @@ pwd [ -d "/opt/dev/bbfdm" ] && cd /opt/dev/bbfdm && ./gitlab-ci/setup.sh && cp -f ./gitlab-ci/bbfdm_services.conf /etc/supervisor/conf.d/ && cd - cp -rf ./test/files/* / +cp ./test/dummy/sysupgrade /sbin/ +chmod 777 /sbin/sysupgrade echo "set ACS url in cwmp uci" url="http://acs:7547" diff --git a/src/backupSession.h b/src/backupSession.h index d8375e2..fb975b0 100644 --- a/src/backupSession.h +++ b/src/backupSession.h @@ -22,11 +22,6 @@ #define RPC_SEND 1 #define CWMP_BACKUP_SESSION "" -#define CWMP_BKP_FILE "/var/run/icwmpd/icwmpd_backup_session.xml" - -#ifdef PERSIST_BACKUP_SESSION_EVENTS -#define CWMP_BKP_FILE_PERSISTENT "/etc/icwmpd/icwmpd_backup_session.xml" -#endif typedef enum backup_loading { diff --git a/src/common.c b/src/common.c index 1b30672..773a12e 100755 --- a/src/common.c +++ b/src/common.c @@ -93,6 +93,20 @@ struct FAULT_CPE FAULT_CPE_ARRAY[] = { [FAULT_CPE_INVALID_UPDATE_VERSION_EXIST] = { "9031", FAULT_9032, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit Update: Version already exist" } }; +const char *g_download_file_types[__MAX_DOWNLOAD_FILETYPE] = { + [DOWNLOAD_FILETYPE_FIRMWARE_UPGRADE_IMAGE] = "1 Firmware Upgrade Image", + [DOWNLOAD_FILETYPE_WEB_CONTENT] = "2 Web Content", + [DOWNLOAD_FILETYPE_VENDOR_CONFIG] = "3 Vendor Configuration File", + [DOWNLOAD_FILETYPE_TONE_FILE] = "4 Tone File", + [DOWNLOAD_FILETYPE_RINGER] = "5 Ringer File", + [DOWNLOAD_FILETYPE_STORED_FIRMWARE_IMAGE] = "6 Stored Firmware Image", +#ifdef ICWMP_ENABLE_VENDOR_EXTN + [DOWNLOAD_FILETYPE_UPGRADE_WITH_NOCONF] = "X GENEXIS-EU UPGRADE-WITH-NOCONF", + [DOWNLOAD_FILETYPE_UPGRADE_WITH_USERCONF] = "X GENEXIS-EU UPGRADE-WITH-USERCONF", + [DOWNLOAD_FILETYPE_UPGRADE_WITH_FULLCONF] = "X GENEXIS-EU UPGRADE-WITH-FULLCONF", +#endif +}; + static void show_help(void) { printf("Usage: icwmpd [OPTIONS]\n"); @@ -402,31 +416,94 @@ void set_rpc_parameter_key(const char *param_key) set_uci_path_value(NULL, "cwmp.cpe.ParameterKey", param_key ? param_key : ""); } +int run_cmd(const char *cmd, char *output, size_t out_len) +{ + int ret = -1, status; + FILE *pp; + + if (cmd == NULL) { + return 0; + } + + pp = popen(cmd, "r"); // flawfinder: ignore + if (pp == NULL) { + CWMP_LOG(ERROR, "Failed to run [%s]", cmd); + return -1; + } + + if (output != NULL && out_len != 0) { + memset(output, 0, out_len); + if (fgets(output, out_len, pp) == NULL) { + if (ferror(pp) != 0) { + CWMP_LOG(ERROR, "Failed to read output of cmd[%s]", cmd); + } + } + } + + status = pclose(pp); + if (status == -1) { + CWMP_LOG(WARNING, "cmd[%s], status[%d], err[%d=>%s]", cmd, status, errno, strerror(errno)); + return -1; + } + + if (WIFEXITED(status)) { + ret = WEXITSTATUS(status); + } + + return ret; +} + /* * Reboot */ void cwmp_reboot(const char *command_key) { + struct blob_buf b = {0}; + set_rpc_parameter_key(command_key); + // backup session files before reboot + CWMP_LOG(DEBUG, "Creating backup of session info"); + if (file_exists(CWMP_BKP_FILE)) { + copy_file(CWMP_BKP_FILE, CWMP_BKP_FILE_PERSISTENT); + if (file_exists(CWMP_BKP_FILE_OPCONF)) { + copy_file(CWMP_BKP_FILE, CWMP_BKP_FILE_OPCONF); + } + } + + if (file_exists(CWMP_DM_NOTIFY)) { + copy_file(CWMP_BKP_FILE, CWMP_DM_NOTIFY_PERSISTENT); + } + + if (file_exists(CWMP_DM_NOTIFY_MARKER)) { + copy_file(CWMP_BKP_FILE, CWMP_DM_NOTIFY_MARKER_PERSISTENT); + } + // Set last_reboot_cause to 'RemoteReboot' because the upcoming reboot will be initiated by CWMP Reboot RPC set_uci_path_value(NULL, "sysmngr.reboots.last_reboot_cause", "RemoteReboot"); + sleep(3); - struct blob_buf b = { 0 }; - CWMP_MEMSET(&b, 0, sizeof(struct blob_buf)); blob_buf_init(&b, 0); + icwmp_ubus_invoke("system", "reboot", b.head, NULL, NULL); + sleep(15); // Wait for reboot + CWMP_LOG(INFO, "Reboot call failed with system, trying again with reboot rpc-sys..."); icwmp_ubus_invoke("rpc-sys", "reboot", b.head, NULL, NULL); + sleep(15); // Wait for reboot to happen - blob_buf_free(&b); + CWMP_LOG(WARNING, "Reboot call failed with rpc-sys, trying again with reboot cmd ..."); + run_cmd("reboot", NULL, 0); + sleep(15); // Wait for reboot - // Wait before exit to avoid getting restarted by procd - sleep(300); + CWMP_LOG(ERROR, "Reboot calls failed, trying hard reboot!!!"); + run_cmd("reboot -f", NULL, 0); + sleep(15); // Wait for reboot // Set last_reboot_cause to empty because there is a problem in the system reboot set_uci_path_value(NULL, "sysmngr.reboots.last_reboot_cause", ""); - CWMP_LOG(ERROR, "# Problem in system restart #"); + CWMP_LOG(ERROR, "## Tried all reboot methods, nothing worked ....."); + blob_buf_free(&b); } /* @@ -434,16 +511,15 @@ void cwmp_reboot(const char *command_key) */ void cwmp_factory_reset() //use the ubus rpc-sys factory { - struct blob_buf b = { 0 }; - CWMP_MEMSET(&b, 0, sizeof(struct blob_buf)); - blob_buf_init(&b, 0); + int code = 3; - icwmp_ubus_invoke("rpc-sys", "factory", b.head, NULL, NULL); + // Flawfinder: ignore + code = run_cmd("defaultreset", NULL, 0); + if (code == 0) { + // Wait before exit to avoid getting restarted by procd + sleep(300); + } - blob_buf_free(&b); - - // Wait before exit to avoid getting restarted by procd - sleep(300); CWMP_LOG(ERROR, "# Problem in system factory reset #"); } @@ -465,59 +541,6 @@ unsigned int get_file_size(const char *file_name) return res; } -int copy(const char *from, const char *to) -{ - int fd_to, fd_from; - char buf[4096]; - ssize_t nread; - int saved_errno; - - fd_from = open(from, O_RDONLY); - if (fd_from < 0) - return -1; - - fd_to = open(to, O_WRONLY | O_CREAT | O_EXCL | O_SYNC, 0666); - if (fd_to < 0) - goto out_error; - - while ((nread = read(fd_from, buf, sizeof buf)) > 0) { - char *out_ptr = buf; - ssize_t nwritten; - - do { - nwritten = write(fd_to, out_ptr, nread); - - if (nwritten >= 0) { - nread -= nwritten; - out_ptr += nwritten; - } else if (errno != EINTR) { - goto out_error; - } - } while (nread > 0); - } - - if (nread == 0) { - if (close(fd_to) < 0) { - fd_to = -1; - goto out_error; - } - close(fd_from); - - /* Success! */ - return 0; - } - -out_error: - saved_errno = errno; - - close(fd_from); - if (fd_to >= 0) - close(fd_to); - - errno = saved_errno; - return -1; -} - bool file_exists(const char *path) { struct stat buffer; @@ -878,16 +901,21 @@ char *string_to_hex(const unsigned char *str, size_t size) return hex; } -int copy_file(char *source_file, char *target_file) +int copy_file(const char *source_file, const char *target_file) { int ch; FILE *source, *target; size_t len = 0; + if (source_file == NULL || target_file == NULL) { + CWMP_LOG(WARNING, "Source[%s] or target[%s] file is NULL", source_file, target_file); + return -1; + } + // cppcheck-suppress cert-MSC24-C source = fopen(source_file, "rb"); if (source == NULL) { - CWMP_LOG(ERROR, "Not able to open the source file: %s\n", source_file); + CWMP_LOG(ERROR, "Not able to open the source file: %s", source_file); return -1; } @@ -895,7 +923,7 @@ int copy_file(char *source_file, char *target_file) target = fopen(target_file, "wb"); if (target == NULL) { fclose(source); - CWMP_LOG(ERROR, "Not able to open the target file: %s\n", target_file); + CWMP_LOG(ERROR, "Not able to open the target file: %s", target_file); return -1; } @@ -904,7 +932,7 @@ int copy_file(char *source_file, char *target_file) len++; } - CWMP_LOG(ERROR, "File copied successfully, len %zd", len); + CWMP_LOG(DEBUG, "File copied successfully, len %zd", len); fclose(source); fclose(target); return 0; @@ -1208,20 +1236,26 @@ void free_binlist(struct list_head *blist) int cwmp_strcmp(const char *s1, const char *s2, const char *origin, int pos) { - if (s1 != NULL && s2 != NULL) + if (s1 != NULL && s2 != NULL) { return strcmp(s1, s2); - else { - CWMP_LOG(DEBUG, "%s:%d NULL argument found", origin, pos); + } else if (s1 == NULL) { + CWMP_LOG(DEBUG, "%s:%s:%d First argument is Null", __func__, origin, pos); + return -1; + } else { + CWMP_LOG(DEBUG, "%s:%s:%d Second argument is Null", __func__, origin, pos); return -1; } } int cwmp_strncmp(const char *s1, const char *s2, int len, const char *origin, int pos) { - if (s1 != NULL && s2 != NULL && len > 0) + if (s1 != NULL && s2 != NULL && len > 0) { return strncmp(s1, s2, len); - else { - CWMP_LOG(DEBUG, "%s:%d NULL argument found", origin, pos); + } else if (s1 == NULL) { + CWMP_LOG(DEBUG, "%s:%s:%d First argument is Null", __func__, origin, pos); + return -1; + } else { + CWMP_LOG(DEBUG, "%s:%s:%d Second argument is Null", __func__, origin, pos); return -1; } } @@ -1231,27 +1265,33 @@ int cwmp_strlen(const char *s1, const char *origin, int pos) if (s1 != NULL) return strlen(s1); else { - CWMP_LOG(DEBUG, "%s:%d NULL argument found", origin, pos); + CWMP_LOG(DEBUG, "%s:%s:%d NULL argument found", __func__, origin, pos); return 0; } } int cwmp_strcasecmp(const char *s1, const char *s2, const char *origin, int pos) { - if (s1 != NULL && s2 != NULL) + if (s1 != NULL && s2 != NULL) { return strcasecmp(s1, s2); - else { - CWMP_LOG(DEBUG, "%s:%d NULL argument found", origin, pos); + } else if (s1 == NULL) { + CWMP_LOG(DEBUG, "%s:%s:%d First argument is Null", __func__, origin, pos); + return -1; + } else { + CWMP_LOG(DEBUG, "%s:%s:%d Second argument is Null", __func__, origin, pos); return -1; } } char *cwmp_strstr(const char *s1, const char *s2, const char *origin, int pos) { - if (s1 != NULL && s2 != NULL) + if (s1 != NULL && s2 != NULL) { return strstr(s1, s2); - else { - CWMP_LOG(DEBUG, "%s:%d NULL argument found", origin, pos); + } else if (s1 == NULL) { + CWMP_LOG(DEBUG, "%s:%s:%d First argument is Null", __func__, origin, pos); + return NULL; + } else { + CWMP_LOG(DEBUG, "%s:%s:%d Second argument is Null", __func__, origin, pos); return NULL; } } @@ -1264,8 +1304,12 @@ char *cwmp_strncpy(char *dst, const char *src, int size, const char *origin, int if (dst != NULL && src != NULL) { strncpy(dst, src, size - 1); dst[size - 1] = '\0'; + } else if (dst == NULL) { + CWMP_LOG(DEBUG, "%s:%s:%d First argument is Null", __func__, origin, pos); + return NULL; } else { - CWMP_LOG(DEBUG, "%s:%d NULL argument found", origin, pos); + CWMP_LOG(DEBUG, "%s:%s:%d Second argument is Null", __func__, origin, pos); + return NULL; } return dst; @@ -1276,7 +1320,7 @@ char *cwmp_strdup(const char *s1, const char *origin, int pos) if (s1) return strdup(s1); else { - CWMP_LOG(DEBUG, "%s:%d NULL argument found", origin, pos); + CWMP_LOG(DEBUG, "%s:%s:%d NULL argument found", __func__, origin, pos); return NULL; } } @@ -1286,18 +1330,21 @@ void *cwmp_memset(void *src, int val, size_t size, const char *origin, int pos) if (src) return memset(src, val, size); else { - CWMP_LOG(DEBUG, "%s:%d NULL argument found", origin, pos); + CWMP_LOG(DEBUG, "%s:%s:%d NULL argument found", __func__, origin, pos); return NULL; } } void *cwmp_memcpy(void *dst, const void *src, size_t size, const char *origin, int pos) { - if (dst != NULL && src != NULL) + if (dst != NULL && src != NULL) { return memcpy(dst, src, size); - else { - CWMP_LOG(DEBUG, "%s:%d NULL argument found", origin, pos); - return dst; + } else if (dst == NULL) { + CWMP_LOG(DEBUG, "%s:%s:%d First argument is Null", __func__, origin, pos); + return NULL; + } else { + CWMP_LOG(DEBUG, "%s:%s:%d Second argument is Null", __func__, origin, pos); + return NULL; } } @@ -1370,9 +1417,5 @@ void stop_service(void) void apply_allowed_cr_ip_port(void) { - // Flawfinder: ignore - FILE *pp = popen(FIREWALL_CWMP, "r"); - if (pp) { - pclose(pp); - } + run_cmd(FIREWALL_CWMP, NULL, 0); } diff --git a/src/common.h b/src/common.h index 0e0c910..82ea4ed 100644 --- a/src/common.h +++ b/src/common.h @@ -81,6 +81,19 @@ #define DM_IP_INTERFACE_PATH "Device\\.IP\\.Interface\\." #define DEFAULT_CR_TIMEOUT 5 /* In Seconds */ +// Session specific files +#define CWMP_BKP_FILE "/var/run/icwmpd/icwmpd_backup_session.xml" +#define CWMP_BKP_FILE_PERSISTENT "/etc/icwmpd/icwmpd_backup_session.xml" +#define CWMP_BKP_FILE_OPCONF "/usr_data/userconf/keep.d/tmp/run/icwmpd/icwmpd_backup_session.xml" + +#define CWMP_DM_NOTIFY "/var/run/icwmpd/dm_enabled_notify" +#define CWMP_DM_NOTIFY_MARKER "/var/run/icwmpd/icwmpd_notify_import_marker" + +#define CWMP_DM_NOTIFY_PERSISTENT "/etc/icwmpd/dm_enabled_notify" +#define CWMP_DM_NOTIFY_MARKER_PERSISTENT "/etc/icwmpd/icwmpd_notify_import_marker" + +#define CWMP_BOOT_MARKER "/etc/icwmpd/icwmpd_boot_marker" + #define foreach_elt_in_strlist(elt, str, delim) \ char *tmpchr; \ char buffer_str[strlen(str) + 1]; \ @@ -339,7 +352,6 @@ enum rpc_cpe_methods_idx { RPC_CPE_CHANGE_DU_STATE, #endif RPC_CPE_CANCEL_TRANSFER, - RPC_CPE_X_FACTORY_RESET_SOFT, RPC_CPE_FAULT, __RPC_CPE_MAX }; @@ -450,6 +462,21 @@ enum client_server_faults { FAULT_CPE_TYPE_SERVER }; +enum download_filetypes { + DOWNLOAD_FILETYPE_FIRMWARE_UPGRADE_IMAGE = 1, + DOWNLOAD_FILETYPE_WEB_CONTENT = 2, + DOWNLOAD_FILETYPE_VENDOR_CONFIG = 3, + DOWNLOAD_FILETYPE_TONE_FILE = 4, + DOWNLOAD_FILETYPE_RINGER = 5, + DOWNLOAD_FILETYPE_STORED_FIRMWARE_IMAGE = 6, +#ifdef ICWMP_ENABLE_VENDOR_EXTN + DOWNLOAD_FILETYPE_UPGRADE_WITH_NOCONF = 7, + DOWNLOAD_FILETYPE_UPGRADE_WITH_USERCONF = 8, + DOWNLOAD_FILETYPE_UPGRADE_WITH_FULLCONF = 9, +#endif + __MAX_DOWNLOAD_FILETYPE +}; + struct rpc_cpe_method { const char *name; int (*handler)(struct rpc *rpc); @@ -492,6 +519,7 @@ typedef struct download { struct uloop_timeout handler_timer; time_t scheduled_time; unsigned int file_size; + enum download_filetypes filetype; int id; char *command_key; char *file_type; @@ -634,6 +662,7 @@ typedef struct { char path[1024]; } path_list_t; +extern const char *g_download_file_types[__MAX_DOWNLOAD_FILETYPE]; extern struct cwmp cwmp_ctx; extern unsigned int flashsize; extern struct FAULT_CPE FAULT_CPE_ARRAY[]; @@ -656,10 +685,9 @@ void cwmp_reboot(const char *command_key); void cwmp_factory_reset(); int download_file(const char *file_path, const char *url, const char *username, const char *password, const char *interface); unsigned int get_file_size(const char *file_name); -int cwmp_check_image(); +int cwmp_check_image(const char *fw_path); int cwmp_apply_firmware(); bool cwmp_apply_web_content(char *filepath); -int copy(const char *from, const char *to); int cwmp_get_fault_code(int fault_code); int cwmp_get_fault_code_by_string(char *fault_code); void *icwmp_malloc(size_t size); @@ -675,7 +703,7 @@ bool icwmp_validate_boolean_value(char *arg); bool icwmp_validate_unsignedint(char *arg); bool icwmp_validate_int_in_range(const char *arg, int min, int max); char *string_to_hex(const unsigned char *str, size_t size); -int copy_file(char *source_file, char *target_file); +int copy_file(const char *source_file, const char *target_file); int icwmp_check_http_connection(void); bool is_ipv6_enabled(void); bool is_ipv6_status_changed(void); @@ -710,4 +738,5 @@ bool end_session_reload_pending(void); void add_path_list(struct list_head *list, char *str); void free_path_list(struct list_head *list); void apply_allowed_cr_ip_port(void); +int run_cmd(const char *cmd, char *output, size_t out_len); #endif diff --git a/src/download.c b/src/download.c index f2b43f7..36a29ef 100644 --- a/src/download.c +++ b/src/download.c @@ -51,7 +51,7 @@ int download_file(const char *file_path, const char *url, const char *username, curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); - if (CWMP_STRLEN(username) > 0) { + if (username && CWMP_STRLEN(username) > 0) { char userpass[1024]; snprintf(userpass, sizeof(userpass), "%s:%s", username, password); curl_easy_setopt(curl, CURLOPT_USERPWD, userpass); @@ -65,7 +65,7 @@ int download_file(const char *file_path, const char *url, const char *username, curl_easy_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP, 1L); // Use l3 interface name - if (CWMP_STRLEN(interface)) + if (interface && CWMP_STRLEN(interface)) curl_easy_setopt(curl, CURLOPT_INTERFACE, interface); if (file_path == NULL) @@ -74,8 +74,13 @@ int download_file(const char *file_path, const char *url, const char *username, // cppcheck-suppress cert-MSC24-C FILE *fp = fopen(file_path, "wb"); if (fp) { + CURLcode res; + curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); - curl_easy_perform(curl); + res = curl_easy_perform(curl); + if (res != CURLE_OK) { + CWMP_LOG(WARNING, "Curl failed [%s], file[%s]", curl_easy_strerror(res), url); + } fclose(fp); } curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &res_code); @@ -118,6 +123,7 @@ char *download_file_task_function(char *task) char *http_ret = (char *)malloc(4 * sizeof(char)); snprintf(http_ret, 4, "%d", http_code); http_ret[3] = 0; + CWMP_LOG(DEBUG, "download return code [%d=>%s]", http_code, http_ret) return http_ret; } @@ -187,20 +193,25 @@ void ubus_check_image_callback(struct ubus_request *req, int type __attribute__( *code = tb[0] ? blobmsg_get_u32(tb[0]) : 4; } -int cwmp_check_image() +int cwmp_check_image(const char *fw_path) { - int code = 0, e; - struct blob_buf b = { 0 }; + int code = 3; + char cmd[128] = {0}; - blob_buf_init(&b, 0); + CWMP_LOG(INFO, "Check downloaded image [%s] ...", fw_path); - CWMP_LOG(INFO, "Check downloaded image ..."); - e = icwmp_ubus_invoke("rpc-sys", "upgrade_test", b.head, ubus_check_image_callback, &code); - if (e != 0) { - CWMP_LOG(INFO, "rpc-sys upgrade_test ubus method failed: Ubus err code: %d", e); - code = 5; + if (CWMP_STRLEN(fw_path) == 0) { + CWMP_LOG(INFO, "Firmware path is empty"); + return code; } - blob_buf_free(&b); + + snprintf(cmd, sizeof(cmd), "sysupgrade -T %s", fw_path); + + code = run_cmd(cmd, NULL, 0); + if (code != 0) { + CWMP_LOG(INFO, "Firmware verification failed with err: %d", code); + } + return code; } @@ -259,6 +270,45 @@ int get_available_bank_id() return bank_id; } +static void ubus_set_bootbank_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg) +{ + struct blob_attr *tb[1] = { NULL }; + const struct blobmsg_policy p[1] = {{ "success", BLOBMSG_TYPE_BOOL }}; + int *status = (req) ? (int *)req->priv : NULL; + + if (msg == NULL) { + CWMP_LOG(ERROR, "%s: msg is null", __func__); + return; + } + + blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg)); + if (tb[0]) { + if (status) { + *status = blobmsg_get_bool(tb[0]); + } + } +} + +static bool set_fwbank_bootbank(int id) +{ + struct blob_buf b = { 0 }; + int e; + bool status = false; + + CWMP_MEMSET(&b, 0, sizeof(struct blob_buf)); + blob_buf_init(&b, 0); + blobmsg_add_u32(&b, "bank", id); + + e = icwmp_ubus_invoke("fwbank", "set_bootbank", b.head, ubus_set_bootbank_callback, &status); + if (e != 0) { + CWMP_LOG(INFO, "fwbank dump ubus method failed: Ubus err code: %d", e); + status = false; + } + + blob_buf_free(&b); + return status; +} + /* * Get Bank Status */ @@ -338,7 +388,7 @@ bool cwmp_apply_web_content(char *filepath) CWMP_MEMSET(&b, 0, sizeof(struct blob_buf)); blob_buf_init(&b, 0); blobmsg_add_string(&b, "url", filepath ? filepath: ""); - blobmsg_add_string(&b, "filetype", WEB_CONTENT_FILE_TYPE); + blobmsg_add_string(&b, "filetype", "2 Web Content"); CWMP_LOG(INFO, "Apply downloaded web content ..."); e = icwmp_ubus_invoke("cwmp.rpc", "download", b.head, ubus_get_download_status, &status); @@ -446,13 +496,15 @@ void fw_upgrade_callback(struct ubus_request *req, int type __attribute__((unuse } } -static int cwmp_apply_multiple_firmware(bool auto_activate) +static int cwmp_apply_multiple_firmware(enum download_filetypes filetype, bool auto_activate) { char *fault_code = NULL; int e; struct blob_buf b = { 0 }; int bank_id = get_available_bank_id(); char buffer[32] = {0}; + int keep_opconf = -1, keep_userconf = -1; + char *config_scope = NULL; if (bank_id <= 0) return -1; @@ -467,21 +519,40 @@ static int cwmp_apply_multiple_firmware(bool auto_activate) bb_add_string(&b, "path", path); void *tbl = blobmsg_open_table(&b, "input"); bb_add_string(&b, "URL", url); - blobmsg_add_u8(&b, "AutoActivate", auto_activate); + //blobmsg_add_u8(&b, "AutoActivate", auto_activate); - if (cwmp_ctx.conf.cpe_keep_config != -1) { - snprintf(buffer, sizeof(buffer), "%s%s", BBF_VENDOR_PREFIX, "KeepConfig"); - blobmsg_add_u8(&b, buffer, cwmp_ctx.conf.cpe_keep_config); - } + if (filetype == DOWNLOAD_FILETYPE_FIRMWARE_UPGRADE_IMAGE || filetype == DOWNLOAD_FILETYPE_STORED_FIRMWARE_IMAGE) { + if (cwmp_ctx.conf.cpe_keep_config != -1) { + snprintf(buffer, sizeof(buffer), "%s%s", BBF_VENDOR_PREFIX, "KeepConfig"); + blobmsg_add_u8(&b, buffer, cwmp_ctx.conf.cpe_keep_config); + keep_userconf = (int)cwmp_ctx.conf.cpe_keep_config; + } - if (cwmp_ctx.conf.cpe_keep_opconf != -1) { - snprintf(buffer, sizeof(buffer), "%s%s", BBF_VENDOR_PREFIX, "KeepOpConf"); - blobmsg_add_u8(&b, buffer, cwmp_ctx.conf.cpe_keep_opconf); - } + if (cwmp_ctx.conf.cpe_keep_opconf != -1) { + snprintf(buffer, sizeof(buffer), "%s%s", BBF_VENDOR_PREFIX, "KeepOpConf"); + blobmsg_add_u8(&b, buffer, cwmp_ctx.conf.cpe_keep_opconf); + keep_opconf = cwmp_ctx.conf.cpe_keep_opconf; + } - if (strlen(cwmp_ctx.conf.cpe_config_scope) != 0) { + if (strlen(cwmp_ctx.conf.cpe_config_scope) != 0) { + snprintf(buffer, sizeof(buffer), "%s%s", BBF_VENDOR_PREFIX, "ConfigScope"); + bb_add_string(&b, buffer, cwmp_ctx.conf.cpe_config_scope); + config_scope = cwmp_ctx.conf.cpe_config_scope; + } +#ifdef ICWMP_ENABLE_VENDOR_EXTN + } else if (filetype == DOWNLOAD_FILETYPE_UPGRADE_WITH_USERCONF) { snprintf(buffer, sizeof(buffer), "%s%s", BBF_VENDOR_PREFIX, "ConfigScope"); - bb_add_string(&b, buffer, cwmp_ctx.conf.cpe_config_scope); + bb_add_string(&b, buffer, "UserOnly"); + config_scope = "UserOnly"; + } else if (filetype == DOWNLOAD_FILETYPE_UPGRADE_WITH_FULLCONF) { + snprintf(buffer, sizeof(buffer), "%s%s", BBF_VENDOR_PREFIX, "ConfigScope"); + bb_add_string(&b, buffer, "All"); + config_scope = "All"; + } else if (filetype == DOWNLOAD_FILETYPE_UPGRADE_WITH_NOCONF) { + snprintf(buffer, sizeof(buffer), "%s%s", BBF_VENDOR_PREFIX, "KeepConfig"); + blobmsg_add_u8(&b, buffer, false); + keep_userconf = 0; +#endif } blobmsg_close_table(&b, tbl); @@ -495,7 +566,29 @@ static int cwmp_apply_multiple_firmware(bool auto_activate) //set /var/state 'switch_bank' option set_uci_path_value(VARSTATE_CONFIG, "icwmp.cpe.switch_bank", "1"); +#ifdef ICWMP_ENABLE_VENDOR_EXTN + if (keep_opconf != -1) { + snprintf(buffer, sizeof(buffer), "%d", keep_opconf); + set_uci_path_value(VARSTATE_CONFIG, "icwmp.cpe.KeepOpConf", buffer); + } + + if (keep_userconf != -1) { + snprintf(buffer, sizeof(buffer), "%d", keep_userconf); + set_uci_path_value(VARSTATE_CONFIG, "icwmp.cpe.KeepConfig", buffer); + } + + if (CWMP_STRLEN(config_scope)) { + set_uci_path_value(VARSTATE_CONFIG, "icwmp.cpe.ConfigScope", config_scope); + } +#endif blob_buf_free(&b); + if (auto_activate == true) { + bool status = set_fwbank_bootbank(bank_id); + if (status == false) { + CWMP_LOG(ERROR, "Failed to activate bank %d", bank_id); + return -1; + } + } return CWMP_OK; } @@ -535,12 +628,22 @@ int cwmp_launch_download(struct download *pdownload, char *download_file_name, e if (pdownload->file_type == NULL) { error = FAULT_CPE_INVALID_ARGUMENTS; - snprintf(err_msg, sizeof(err_msg), "File type: null is not a valid value"); + snprintf(err_msg, sizeof(err_msg), "[%s:%d] File type [%d] is not a valid value", __func__, __LINE__, pdownload->filetype); goto end_download; + } else { + pdownload->filetype = get_download_filetype(pdownload->file_type); } - if (CWMP_STRCMP(pdownload->file_type, FIRMWARE_UPGRADE_IMAGE_FILE_TYPE) == 0 || CWMP_STRCMP(pdownload->file_type, STORED_FIRMWARE_IMAGE_FILE_TYPE) == 0) { + + if ((pdownload->filetype == DOWNLOAD_FILETYPE_FIRMWARE_UPGRADE_IMAGE) + || (pdownload->filetype == DOWNLOAD_FILETYPE_STORED_FIRMWARE_IMAGE) +#ifdef ICWMP_ENABLE_VENDOR_EXTN + || (pdownload->filetype == DOWNLOAD_FILETYPE_UPGRADE_WITH_NOCONF) + || (pdownload->filetype == DOWNLOAD_FILETYPE_UPGRADE_WITH_USERCONF) + || (pdownload->filetype == DOWNLOAD_FILETYPE_UPGRADE_WITH_FULLCONF) +#endif + ) { rename(ICWMP_DOWNLOAD_FILE, FIRMWARE_UPGRADE_IMAGE); - int ret = cwmp_check_image(); + int ret = cwmp_check_image(FIRMWARE_UPGRADE_IMAGE); if (ret == 0) { unsigned int file_size = get_file_size(FIRMWARE_UPGRADE_IMAGE); @@ -558,7 +661,7 @@ int cwmp_launch_download(struct download *pdownload, char *download_file_name, e snprintf(err_msg, sizeof(err_msg), "Failed validation with %d of Downloaded file", ret); remove(FIRMWARE_UPGRADE_IMAGE); } - } else if (CWMP_STRCMP(pdownload->file_type, WEB_CONTENT_FILE_TYPE) == 0) { + } else if (pdownload->filetype == DOWNLOAD_FILETYPE_WEB_CONTENT) { if (download_file_name != NULL) { char file_path[512]; snprintf(file_path, sizeof(file_path), "/tmp/%s", download_file_name); @@ -568,7 +671,7 @@ int cwmp_launch_download(struct download *pdownload, char *download_file_name, e error = FAULT_CPE_NO_FAULT; goto end_download; - } else if (CWMP_STRCMP(pdownload->file_type, VENDOR_CONFIG_FILE_TYPE) == 0) { + } else if (pdownload->filetype == DOWNLOAD_FILETYPE_VENDOR_CONFIG) { if (download_file_name != NULL) { char file_path[512]; snprintf(file_path, sizeof(file_path), "/tmp/%s", download_file_name); @@ -577,10 +680,10 @@ int cwmp_launch_download(struct download *pdownload, char *download_file_name, e rename(ICWMP_DOWNLOAD_FILE, VENDOR_CONFIG_FILE); error = FAULT_CPE_NO_FAULT; - } else if (CWMP_STRCMP(pdownload->file_type, TONE_FILE_TYPE) == 0) { + } else if (pdownload->filetype == DOWNLOAD_FILETYPE_TONE_FILE) { //TODO Not Supported error = FAULT_CPE_NO_FAULT; - } else if (CWMP_STRCMP(pdownload->file_type, RINGER_FILE_TYPE) == 0) { + } else if (pdownload->filetype == DOWNLOAD_FILETYPE_RINGER) { //TODO Not Supported error = FAULT_CPE_NO_FAULT; @@ -627,12 +730,12 @@ char *get_file_name_by_download_url(char *url) return slash+1; } -int apply_downloaded_file(struct download *pdownload, char *download_file_name, struct transfer_complete *ptransfer_complete) +int apply_downloaded_file(struct download *pdownload, char *download_file_name, enum load_type ltype, struct transfer_complete *ptransfer_complete) { int error = FAULT_CPE_NO_FAULT; char err_msg[256] = {0}; - if (pdownload->file_type[0] == '1') { + if (pdownload->filetype == DOWNLOAD_FILETYPE_FIRMWARE_UPGRADE_IMAGE) { ptransfer_complete->old_software_version = cwmp_ctx.deviceid.softwareversion; } if (ptransfer_complete->id <= 0) { @@ -644,21 +747,28 @@ int apply_downloaded_file(struct download *pdownload, char *download_file_name, } bkp_session_insert_transfer_complete(ptransfer_complete); bkp_session_save(); - if (CWMP_STRCMP(pdownload->file_type, FIRMWARE_UPGRADE_IMAGE_FILE_TYPE) == 0) { - set_uci_path_value(NULL, "cwmp.cpe.exec_download", "1"); - if (cwmp_apply_multiple_firmware(true) != 0) { + if (pdownload->filetype == DOWNLOAD_FILETYPE_FIRMWARE_UPGRADE_IMAGE +#ifdef ICWMP_ENABLE_VENDOR_EXTN + || pdownload->filetype == DOWNLOAD_FILETYPE_UPGRADE_WITH_NOCONF + || pdownload->filetype == DOWNLOAD_FILETYPE_UPGRADE_WITH_USERCONF + || pdownload->filetype == DOWNLOAD_FILETYPE_UPGRADE_WITH_FULLCONF +#endif + ) { + if (cwmp_apply_multiple_firmware(pdownload->filetype, true) == 0) { + cwmp_reboot("FirmwareUpgrade"); + if (error == FAULT_CPE_NO_FAULT) { + sleep(70); + error = FAULT_CPE_DOWNLOAD_FAIL_COMPLETE_DOWNLOAD; + snprintf(err_msg, sizeof(err_msg), "Failed to reboot after upgrade"); + CWMP_LOG(ERROR, "## Failed to reboot after upgrade"); + } + } else { error = FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED; snprintf(err_msg, sizeof(err_msg), "Failed in applying the downloaded firmware image, may be corrupted file"); + CWMP_LOG(ERROR, "Failed in applying the downloaded firmware image, may be corrupted file"); } - cwmp_reboot("FirmwareUpgrade"); - if (error == FAULT_CPE_NO_FAULT) { - sleep(70); - error = FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED; - snprintf(err_msg, sizeof(err_msg), "Downloaded firmware could not applied or reboot has not been taken after upgrade"); - } - - } else if (CWMP_STRCMP(pdownload->file_type, WEB_CONTENT_FILE_TYPE) == 0) { + } else if (pdownload->filetype == DOWNLOAD_FILETYPE_WEB_CONTENT) { // apply web content file char file_path[512] = {0}; if (download_file_name != NULL) { @@ -674,7 +784,7 @@ int apply_downloaded_file(struct download *pdownload, char *download_file_name, error = FAULT_CPE_NO_FAULT; remove(file_path); - } else if (CWMP_STRCMP(pdownload->file_type, VENDOR_CONFIG_FILE_TYPE) == 0) { + } else if (pdownload->filetype == DOWNLOAD_FILETYPE_VENDOR_CONFIG) { int err = CWMP_OK; if (download_file_name != NULL) { char file_path[512]; @@ -697,24 +807,30 @@ int apply_downloaded_file(struct download *pdownload, char *download_file_name, remove(VENDOR_CONFIG_FILE); } - if (err == CWMP_OK) - error = FAULT_CPE_NO_FAULT; - else if (err == CWMP_GEN_ERR) { + if (err == CWMP_OK) { + cwmp_reboot("VendorConfigApply"); + if (error == FAULT_CPE_NO_FAULT) { + sleep(70); + error = FAULT_CPE_DOWNLOAD_FAIL_COMPLETE_DOWNLOAD; + snprintf(err_msg, sizeof(err_msg), "Failed to reboot after config apply"); + CWMP_LOG(ERROR, "## Failed to reboot after config apply"); + } + } else if (err == CWMP_GEN_ERR) { error = FAULT_CPE_INTERNAL_ERROR; snprintf(err_msg, sizeof(err_msg), "Failed to commit the config file changes"); } else if (err == -1) { error = FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED; snprintf(err_msg, sizeof(err_msg), "UCI operation failed, could not import config file"); } - } else if (CWMP_STRCMP(pdownload->file_type, TONE_FILE_TYPE) == 0) { + } else if (pdownload->filetype == DOWNLOAD_FILETYPE_TONE_FILE) { //TODO Not Supported error = FAULT_CPE_NO_FAULT; - } else if (CWMP_STRCMP(pdownload->file_type, RINGER_FILE_TYPE) == 0) { + } else if (pdownload->filetype == DOWNLOAD_FILETYPE_RINGER) { //TODO Not Supported error = FAULT_CPE_NO_FAULT; - } else if (CWMP_STRCMP(pdownload->file_type, STORED_FIRMWARE_IMAGE_FILE_TYPE) == 0) { - int err = cwmp_apply_multiple_firmware(false); + } else if (pdownload->filetype == DOWNLOAD_FILETYPE_STORED_FIRMWARE_IMAGE) { + int err = cwmp_apply_multiple_firmware(pdownload->filetype, false); if (err == CWMP_OK) error = FAULT_CPE_NO_FAULT; else { @@ -729,20 +845,22 @@ int apply_downloaded_file(struct download *pdownload, char *download_file_name, snprintf(err_msg, sizeof(err_msg), "Invalid file type argument (%s)", pdownload->file_type); } - if ((error == FAULT_CPE_NO_FAULT) && - (pdownload->file_type[0] == '1' || pdownload->file_type[0] == '3' || pdownload->file_type[0] == '2')) { + if (error == FAULT_CPE_NO_FAULT) { set_rpc_parameter_key(pdownload->command_key); - if (pdownload->file_type[0] == '3' || pdownload->file_type[0] == '2') { - CWMP_LOG(INFO, "Download and apply new file type \"%s\" is done successfully", pdownload->file_type); - //cwmp_root_cause_transfer_complete(ptransfer_complete); + if (pdownload->filetype == DOWNLOAD_FILETYPE_WEB_CONTENT || + pdownload->filetype == DOWNLOAD_FILETYPE_STORED_FIRMWARE_IMAGE) { + + bkp_session_delete_element((ltype == TYPE_DOWNLOAD) ? "download" : "schedule_download", pdownload->id); bkp_session_delete_element_by_key("transfer_complete", "start_time", ptransfer_complete->start_time); + bkp_session_save(); } + CWMP_LOG(DEBUG, "Download and apply new filetype [%d=>%s] is done successfully", pdownload->filetype, pdownload->file_type); return FAULT_CPE_NO_FAULT; } - if (error != FAULT_CPE_NO_FAULT) { - bkp_session_delete_element_by_key("transfer_complete", "start_time", ptransfer_complete->start_time); - ptransfer_complete->fault_code = error; - } + + // In case of failure, save transfer complete failures report + bkp_session_delete_element_by_key("transfer_complete", "start_time", ptransfer_complete->start_time); + ptransfer_complete->fault_code = error; if (ptransfer_complete->id <= 0) { if ((cwmp_ctx.tc_id < 0) || (cwmp_ctx.tc_id >= MAX_INT_ID)) { cwmp_ctx.tc_id = 0; @@ -910,31 +1028,16 @@ void cwmp_start_download(struct uloop_timeout *timeout) //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); + error = apply_downloaded_file(pdownload, download_file_name, TYPE_DOWNLOAD, ptransfer_complete); if (error != FAULT_CPE_NO_FAULT) { CWMP_LOG(ERROR, "Error while applying the downloaded file: %s", download_file_name); - if (ptransfer_complete->id <= 0) { - if ((cwmp_ctx.tc_id < 0) || (cwmp_ctx.tc_id >= MAX_INT_ID)) { - cwmp_ctx.tc_id = 0; - } - cwmp_ctx.tc_id++; - ptransfer_complete->id = cwmp_ctx.tc_id; - } - 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_element_by_key("transfer_complete", "start_time", ptransfer_complete->start_time); - bkp_session_delete_element("download", pdownload->id); - bkp_session_save(); - } + list_del(&(pdownload->list)); - if (pdownload->scheduled_time != 0) + if (pdownload->scheduled_time != 0) { count_download_queue--; + } cwmp_free_download_request(pdownload); struct session_timer_event *download_inform_event = calloc(1, sizeof(struct session_timer_event)); @@ -990,24 +1093,18 @@ void cwmp_start_schedule_download(struct uloop_timeout *timeout) int error; 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); + error = cwmp_launch_download(sched_download, download_file_name, TYPE_SCHEDULE_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); + error = apply_downloaded_file(sched_download, download_file_name, TYPE_SCHEDULE_DOWNLOAD, ptransfer_complete); if (error != FAULT_CPE_NO_FAULT) { - CWMP_LOG(ERROR, "Error while applying the downloaded file: %s", download_file_name); + CWMP_LOG(ERROR, "[%s:%d]Error while applying the downloaded file: %s", __func__, __LINE__, 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_element("schedule_download", sched_download->id); - bkp_session_delete_element_by_key("transfer_complete", "start_time", ptransfer_complete->start_time); - bkp_session_save(); - } } else { CWMP_LOG(ERROR, "Schedule Download out of date"); ptransfer_complete = calloc(1, sizeof(struct transfer_complete)); @@ -1092,3 +1189,23 @@ void apply_schedule_downloads() uloop_timeout_set(&sched_download->handler_timer, 1000 * download_delay); } } + +enum download_filetypes get_download_filetype(const char *file_type) +{ + int i; + enum download_filetypes filetype = __MAX_DOWNLOAD_FILETYPE; + + if (CWMP_STRLEN(file_type) == 0) { + CWMP_LOG(WARNING, "empty file_type, can't process"); + return __MAX_DOWNLOAD_FILETYPE; + } + + for (i = DOWNLOAD_FILETYPE_FIRMWARE_UPGRADE_IMAGE; i < __MAX_DOWNLOAD_FILETYPE; i++) { + if (CWMP_STRCMP(g_download_file_types[i], file_type) == 0) { + filetype = i; + break; + } + } + + return filetype; +} diff --git a/src/download.h b/src/download.h index 56abcef..2c06c28 100644 --- a/src/download.h +++ b/src/download.h @@ -20,13 +20,6 @@ #define WEB_CONTENT_FILE "/tmp/web_content.ipk" #define VENDOR_CONFIG_FILE "/tmp/vendor_conf_file" -#define FIRMWARE_UPGRADE_IMAGE_FILE_TYPE "1 Firmware Upgrade Image" -#define WEB_CONTENT_FILE_TYPE "2 Web Content" -#define VENDOR_CONFIG_FILE_TYPE "3 Vendor Configuration File" -#define TONE_FILE_TYPE "4 Tone File" -#define RINGER_FILE_TYPE "5 Ringer File" -#define STORED_FIRMWARE_IMAGE_FILE_TYPE "6 Stored Firmware Image" - #define MAX_DOWNLOAD_QUEUE 10 extern struct list_head list_download; @@ -44,4 +37,5 @@ void cwmp_start_download(struct uloop_timeout *timeout); void apply_downloads(); void apply_schedule_downloads(); void cwmp_start_schedule_download(struct uloop_timeout *timeout); +enum download_filetypes get_download_filetype(const char *file_type); #endif diff --git a/src/event.c b/src/event.c index ba1843f..5212138 100644 --- a/src/event.c +++ b/src/event.c @@ -115,10 +115,19 @@ int event_remove_noretry_event_container() static int cwmp_root_cause_event_bootstrap(void) { char *acsurl = NULL; + bool force_event = false; + + if (file_exists(CWMP_BOOT_MARKER) == true) { + CWMP_LOG(DEBUG, "Skipping '0 BOOTSTRAP', boot marker %s exists", CWMP_BOOT_MARKER); + return CWMP_OK; + } else { + // Force '0 Bootstrap', in case of marker not present, usually the case with noconf upgrade + force_event = true; + } cwmp_load_saved_session(&acsurl, ACS); - if (acsurl == NULL || CWMP_STRCMP(cwmp_ctx.conf.acs_url, acsurl) != 0) { + if (acsurl == NULL || (CWMP_STRCMP(cwmp_ctx.conf.acs_url, acsurl) != 0) || (force_event == true)) { struct event_container *event_container; event_container = cwmp_add_event_container(EVENT_IDX_0BOOTSTRAP, ""); if (event_container == NULL) { diff --git a/src/http.c b/src/http.c index 78de059..f5314a6 100644 --- a/src/http.c +++ b/src/http.c @@ -724,7 +724,10 @@ void icwmp_http_server_listen(void) int client_sock = accept(cwmp_ctx.cr_socket_desc, (struct sockaddr *)&client, (socklen_t *)&c); if (client_sock < 0) { - CWMP_LOG(ERROR, "Could not accept connections for Connection Request!"); + if (errno == EINTR) + continue; + + CWMP_LOG(ERROR, "# Accept failure sock[%d], err [%s]", client_sock, strerror(errno)); shutdown(cwmp_ctx.cr_socket_desc, SHUT_RDWR); icwmp_http_server_init(); listen(cwmp_ctx.cr_socket_desc, 5); diff --git a/src/rpc.c b/src/rpc.c index 4158919..779be2d 100755 --- a/src/rpc.c +++ b/src/rpc.c @@ -1865,6 +1865,31 @@ error: } #endif +static bool check_valid_download_filetypes(enum download_filetypes filetype) +{ + bool res = false; + + switch(filetype) { + case DOWNLOAD_FILETYPE_FIRMWARE_UPGRADE_IMAGE: + case DOWNLOAD_FILETYPE_WEB_CONTENT: + case DOWNLOAD_FILETYPE_VENDOR_CONFIG: + case DOWNLOAD_FILETYPE_TONE_FILE: + case DOWNLOAD_FILETYPE_RINGER: + case DOWNLOAD_FILETYPE_STORED_FIRMWARE_IMAGE: +#ifdef ICWMP_ENABLE_VENDOR_EXTN + case DOWNLOAD_FILETYPE_UPGRADE_WITH_NOCONF: + case DOWNLOAD_FILETYPE_UPGRADE_WITH_USERCONF: + case DOWNLOAD_FILETYPE_UPGRADE_WITH_FULLCONF: +#endif + res = true; + break; + default: + res = false; + } + + return res; +} + /* * [RPC CPE]: Download */ @@ -1923,7 +1948,10 @@ int cwmp_handle_rpc_cpe_download(struct rpc *rpc) goto fault; } - if (CWMP_STRCMP(download->file_type, FIRMWARE_UPGRADE_IMAGE_FILE_TYPE) && CWMP_STRCMP(download->file_type, WEB_CONTENT_FILE_TYPE) && CWMP_STRCMP(download->file_type, VENDOR_CONFIG_FILE_TYPE) && CWMP_STRCMP(download->file_type, TONE_FILE_TYPE) && CWMP_STRCMP(download->file_type, RINGER_FILE_TYPE) && CWMP_STRCMP(download->file_type, STORED_FIRMWARE_IMAGE_FILE_TYPE)) { + // Get download filetype + download->filetype = get_download_filetype(download->file_type); + CWMP_LOG(DEBUG, "Failetype in download [%s], enum[%d]", download->file_type, download->filetype); + if (check_valid_download_filetypes(download->filetype) == false) { error = FAULT_CPE_INVALID_ARGUMENTS; snprintf(err_msg, sizeof(err_msg), "(%s) is an invalid file type in download request", download->file_type ? download->file_type : ""); } else if (count_download_queue >= MAX_DOWNLOAD_QUEUE) { @@ -2090,7 +2118,8 @@ int cwmp_handle_rpc_cpe_schedule_download(struct rpc *rpc) } } - if (CWMP_STRCMP(schedule_download->file_type, FIRMWARE_UPGRADE_IMAGE_FILE_TYPE) && CWMP_STRCMP(schedule_download->file_type, WEB_CONTENT_FILE_TYPE) && CWMP_STRCMP(schedule_download->file_type, VENDOR_CONFIG_FILE_TYPE) && CWMP_STRCMP(schedule_download->file_type, TONE_FILE_TYPE) && CWMP_STRCMP(schedule_download->file_type, RINGER_FILE_TYPE) && CWMP_STRCMP(schedule_download->file_type, STORED_FIRMWARE_IMAGE_FILE_TYPE)) { + schedule_download->filetype = get_download_filetype(schedule_download->file_type); + if (check_valid_download_filetypes(schedule_download->filetype) == false) { error = FAULT_CPE_INVALID_ARGUMENTS; snprintf(err_msg, sizeof(err_msg), "Invalid file type: (%s)", schedule_download->file_type ? schedule_download->file_type : ""); } else if ((CWMP_STRCMP(schedule_download->timewindowstruct[0].windowmode, "1 At Any Time") && CWMP_STRCMP(schedule_download->timewindowstruct[0].windowmode, "2 Immediately") && CWMP_STRCMP(schedule_download->timewindowstruct[0].windowmode, "3 When Idle")) || (CWMP_STRCMP(schedule_download->timewindowstruct[1].windowmode, "1 At Any Time") && CWMP_STRCMP(schedule_download->timewindowstruct[1].windowmode, "2 Immediately") && CWMP_STRCMP(schedule_download->timewindowstruct[1].windowmode, "3 When Idle"))) { diff --git a/src/session.c b/src/session.c index 04aa884..de873ec 100644 --- a/src/session.c +++ b/src/session.c @@ -347,7 +347,6 @@ static void schedule_session_retry(void) void start_cwmp_session(void) { int error; - char exec_download[BUF_SIZE_256] = {0}; uloop_timeout_cancel(&check_notify_timer); if (cwmp_session_init() != CWMP_OK) { @@ -401,12 +400,6 @@ void start_cwmp_session(void) CWMP_LOG(INFO, "Start session"); - get_uci_path_value(NULL, "cwmp.cpe.exec_download", exec_download, BUF_SIZE_256); - if (CWMP_STRCMP(exec_download, "1") == 0) { - CWMP_LOG(INFO, "Firmware downloaded and applied successfully"); - set_uci_path_value(NULL, "cwmp.cpe.exec_download", "0"); - } - error = cwmp_schedule_rpc(); if (error != CWMP_OK) { CWMP_LOG(ERROR, "CWMP session error: %d", error); @@ -448,9 +441,17 @@ void start_cwmp_session(void) // storage to avoid loss of events over power cycle if (file_exists(CWMP_BKP_FILE)) { CWMP_LOG(DEBUG, "Copied events backup file to persistent storage"); - copy(CWMP_BKP_FILE, CWMP_BKP_FILE_PERSISTENT); + copy_file(CWMP_BKP_FILE, CWMP_BKP_FILE_PERSISTENT); } #endif + if (file_exists(CWMP_BOOT_MARKER) == false) { + CWMP_LOG(DEBUG, "Create boot marker file"); + // cppcheck-suppress cert-MSC24-C + FILE *marker_fp = fopen(CWMP_BOOT_MARKER, "w"); + if (marker_fp) { + fclose(marker_fp); + } + } if (cwmp_ctx.throttle_session_triggered == true) { cwmp_ctx.throttle_session_triggered = false; diff --git a/src/subprocess.c b/src/subprocess.c index d49ee14..629353a 100644 --- a/src/subprocess.c +++ b/src/subprocess.c @@ -71,15 +71,15 @@ int subprocess_start(task_function task_fun) pid_t p; - if (pipe(pipefd1) == -1) { - CWMP_LOG(ERROR, "pipefd1 failed\n"); - return CWMP_GEN_ERR; - } + 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; - } + if (pipe(pipefd2) == -1) { + CWMP_LOG(ERROR, "pipefd2 failed\n"); + return CWMP_GEN_ERR; + } p = fork(); if (p == 0) { @@ -116,7 +116,9 @@ int subprocess_start(task_function task_fun) } } } - return CWMP_OK; + + CWMP_LOG(INFO, "Subprocess started with PID [%d]", p); + return CWMP_OK; } char *execute_task_in_subprocess(const char *task) diff --git a/src/uci_utils.c b/src/uci_utils.c index 079cf50..c3d4c6c 100644 --- a/src/uci_utils.c +++ b/src/uci_utils.c @@ -726,6 +726,12 @@ end: } fclose(input); pthread_mutex_unlock(&mutex_config_load); + + if (ret == CWMP_OK) { + // Need to remove dmmap + set_uci_path_value(VARSTATE_CONFIG, "dmmap.dmmap.cleanup", "1"); + } + return ret; } diff --git a/src/xml.c b/src/xml.c index 14ab01e..328a186 100644 --- a/src/xml.c +++ b/src/xml.c @@ -327,10 +327,13 @@ void cwmp_free_all_xml_data_list(struct list_head *list) int load_backup_event_command_key(mxml_node_t *b __attribute__((unused)), struct xml_data_struct *xml_attrs) { + const char *command_key = NULL; + mxml_node_t *c = mxmlWalkNext(b, b, MXML_DESCEND); - if (!c || mxmlGetType(c) != MXML_OPAQUE) - return FAULT_CPE_INVALID_ARGUMENTS; - const char *command_key = mxmlGetOpaque(c); + if (c && mxmlGetType(c) == MXML_OPAQUE) { + command_key = mxmlGetOpaque(c); + } + if (xml_attrs->index && *(xml_attrs->index) > -1) { if (EVENT_CONST[*(xml_attrs->index)].RETRY & EVENT_RETRY_AFTER_REBOOT) { xml_attrs->event_save = cwmp_add_event_container(*(xml_attrs->index), ((command_key != NULL) ? command_key : "")); diff --git a/test/cmocka/icwmp_download_unit_test.c b/test/cmocka/icwmp_download_unit_test.c index 62d9427..56ef5f4 100644 --- a/test/cmocka/icwmp_download_unit_test.c +++ b/test/cmocka/icwmp_download_unit_test.c @@ -94,7 +94,8 @@ static void cwmp_launch_download_unit_test(void **state) pdownload = icwmp_calloc(1, sizeof(struct download)); pdownload->command_key = icwmp_strdup("download_key"); pdownload->file_size = 0; - pdownload->file_type = icwmp_strdup(FIRMWARE_UPGRADE_IMAGE_FILE_TYPE); + pdownload->filetype = DOWNLOAD_FILETYPE_FIRMWARE_UPGRADE_IMAGE; + pdownload->file_type = icwmp_strdup("1 Firmware Upgrade Image"); pdownload->username = icwmp_strdup("iopsys"); pdownload->password = icwmp_strdup("iopsys"); pdownload->url = icwmp_strdup("http://127.0.0.1/firmware_v1.0.bin"); @@ -119,7 +120,8 @@ static void cwmp_launch_download_unit_test(void **state) pdownload = icwmp_calloc(1, sizeof(struct download)); pdownload->command_key = icwmp_strdup("download_key"); pdownload->file_size = 0; - pdownload->file_type = icwmp_strdup(FIRMWARE_UPGRADE_IMAGE_FILE_TYPE); + pdownload->filetype = DOWNLOAD_FILETYPE_FIRMWARE_UPGRADE_IMAGE; + pdownload->file_type = icwmp_strdup("1 Firmware Upgrade Image"); pdownload->username = icwmp_strdup("iopsys"); pdownload->password = icwmp_strdup("iopsys"); pdownload->url = icwmp_strdup("http://127.0.0.1/firmware.bin"); @@ -143,6 +145,7 @@ static void cwmp_launch_download_unit_test(void **state) pdownload = icwmp_calloc(1, sizeof(struct download)); pdownload->command_key = icwmp_strdup("download_key"); pdownload->file_size = 0; + pdownload->filetype = 255; pdownload->file_type = icwmp_strdup("7 New File Type"); pdownload->username = icwmp_strdup("iopsys"); pdownload->password = icwmp_strdup("iopsys"); @@ -167,7 +170,8 @@ static void cwmp_launch_download_unit_test(void **state) pdownload = icwmp_calloc(1, sizeof(struct download)); pdownload->command_key = icwmp_strdup("download_key"); pdownload->file_size = 0; - pdownload->file_type = icwmp_strdup(FIRMWARE_UPGRADE_IMAGE_FILE_TYPE); + pdownload->filetype = DOWNLOAD_FILETYPE_FIRMWARE_UPGRADE_IMAGE; + pdownload->file_type = icwmp_strdup("1 Firmware Upgrade Image"); pdownload->username = icwmp_strdup("iopsys"); pdownload->password = icwmp_strdup("iopsys"); pdownload->url = icwmp_strdup("http://127.0.0.1/invalid_firmware_v1.0.bin"); diff --git a/test/dummy/sysupgrade b/test/dummy/sysupgrade new file mode 100644 index 0000000..571ff5a --- /dev/null +++ b/test/dummy/sysupgrade @@ -0,0 +1,12 @@ +#!/bin/sh + +if [ -z "${2}" ]; then + exit 1 +fi + +invalid="$(cat ${2})" +if [ "${invalid}" = "Invalid" ]; then + exit 1 +fi + +exit 0