From ca5227149c47c4dae96bc2613a038aecc7944819 Mon Sep 17 00:00:00 2001 From: Suvendhu Hansa Date: Mon, 22 Sep 2025 19:07:06 +0530 Subject: [PATCH] Added support to download opconf --- src/common.h | 1 + src/download.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++- src/rpc.c | 10 +++++--- src/xml.c | 6 ++--- 4 files changed, 75 insertions(+), 8 deletions(-) diff --git a/src/common.h b/src/common.h index 24b2f3c..a05efd6 100644 --- a/src/common.h +++ b/src/common.h @@ -498,6 +498,7 @@ typedef struct download { char *url; char *username; char *password; + char *target_file_name; struct timewindow timewindowstruct[2]; } download; diff --git a/src/download.c b/src/download.c index 61be219..f0f5538 100644 --- a/src/download.c +++ b/src/download.c @@ -368,6 +368,64 @@ bool cwmp_apply_web_content(char *filepath) return status; } +// Apply opconf +static void ubus_get_opconf_status(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg) +{ + if (msg == NULL) { + CWMP_LOG(ERROR, "received msg is null"); + return; + } + + char **status = (char **)req->priv; + if (status == NULL) + return; + + const struct blobmsg_policy p[1] = { { "Result", BLOBMSG_TYPE_STRING } }; + struct blob_attr *tb[1] = { NULL }; + blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg)); + if (tb[0] == NULL) { + CWMP_LOG(ERROR, "result not exists in received msg"); + return; + } + + *status = strdup(blobmsg_get_string(tb[0])); +} + +bool valid_opconf_file_name(char *download_file_name) +{ + char pattern[64] = {0}; + + snprintf(pattern, sizeof(pattern), "^opconf[^/]*\\.(json|tar\\.gz)$"); + + return match_reg_exp(pattern, download_file_name); +} + +int cwmp_apply_opconf(char *filepath) +{ + char file_url[520]; + char *status = NULL; + + if (CWMP_STRLEN(filepath) == 0) + return CWMP_GEN_ERR; + + snprintf(file_url, sizeof(file_url), "file://%s", filepath); + + struct blob_buf b = {0}; + CWMP_MEMSET(&b, 0, sizeof(struct blob_buf)); + blob_buf_init(&b, 0); + + blobmsg_add_string(&b, "url", file_url); + + int err = icwmp_ubus_invoke("opconf", "install", b.head, ubus_get_opconf_status, &status); + if (CWMP_STRCMP(status, "OK") != 0) + err = -1; + + blob_buf_free(&b); + FREE(status); + + return err; +} + void fw_upgrade_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg) { char **fault = (char **)req->priv; @@ -619,11 +677,17 @@ int apply_downloaded_file(struct download *pdownload, char *download_file_name, char file_path[512]; snprintf(file_path, sizeof(file_path), "/tmp/%s", download_file_name); - if (strstr(download_file_name, ".uci.conf") != NULL) { + + if (CWMP_STRSTR(download_file_name, ".uci.conf") != NULL || + CWMP_STRSTR(pdownload->target_file_name, ".uci.conf") != NULL) { err = import_uci_package(NULL, file_path); + } else if (valid_opconf_file_name(download_file_name) || + CWMP_STRCMP(pdownload->target_file_name, "opconf.json") == 0) { + err = cwmp_apply_opconf(file_path); } else { err = import_uci_package(download_file_name, file_path); } + remove(file_path); } else { err = import_uci_package("vendor_conf_file", VENDOR_CONFIG_FILE); diff --git a/src/rpc.c b/src/rpc.c index ccc8903..b97b011 100755 --- a/src/rpc.c +++ b/src/rpc.c @@ -1937,10 +1937,11 @@ int cwmp_handle_rpc_cpe_download(struct rpc *rpc) download_xml_attrs.delay_seconds = (long int*)&download_delay; download_xml_attrs.file_type = &download->file_type; download_xml_attrs.file_size = &download->file_size; + download_xml_attrs.target_file_name = &download->target_file_name; - struct xml_tag_validation download_validation[] = {{"CommandKey", VALIDATE_STR_SIZE, 0, 32}, {"FileType", VALIDATE_STR_SIZE, 0, 64}, {"URL", VALIDATE_STR_SIZE, 0, 256}, {"Username", VALIDATE_STR_SIZE, 0, 256}, {"Password", VALIDATE_STR_SIZE, 0, 256}, {"FileSize", VALIDATE_UNINT, 0, 0}, {"DelaySeconds", VALIDATE_UNINT, 0, 0}}; + struct xml_tag_validation download_validation[] = {{"CommandKey", VALIDATE_STR_SIZE, 0, 32}, {"FileType", VALIDATE_STR_SIZE, 0, 64}, {"URL", VALIDATE_STR_SIZE, 0, 256}, {"Username", VALIDATE_STR_SIZE, 0, 256}, {"Password", VALIDATE_STR_SIZE, 0, 256}, {"FileSize", VALIDATE_UNINT, 0, 0}, {"TargetFileName", VALIDATE_STR_SIZE, 0, 256}, {"DelaySeconds", VALIDATE_UNINT, 0, 0}}; download_xml_attrs.validations = download_validation; - download_xml_attrs.nbre_validations = 7; + download_xml_attrs.nbre_validations = 8; error = load_xml_node_data(SOAP_REQ_DOWNLOAD, n, &download_xml_attrs); @@ -2080,10 +2081,11 @@ int cwmp_handle_rpc_cpe_schedule_download(struct rpc *rpc) sched_download_xml_attrs.password = &schedule_download->password; sched_download_xml_attrs.file_type = &schedule_download->file_type; sched_download_xml_attrs.file_size = &schedule_download->file_size; + sched_download_xml_attrs.target_file_name = &schedule_download->target_file_name; - struct xml_tag_validation scheddownload_validation[] = {{"CommandKey", VALIDATE_STR_SIZE, 0, 32}, {"FileType", VALIDATE_STR_SIZE, 0, 64}, {"URL", VALIDATE_STR_SIZE, 0, 256}, {"Username", VALIDATE_STR_SIZE, 0, 256}, {"Password", VALIDATE_STR_SIZE, 0, 256}, {"FileSize", VALIDATE_UNINT, 0, 0}}; + struct xml_tag_validation scheddownload_validation[] = {{"CommandKey", VALIDATE_STR_SIZE, 0, 32}, {"FileType", VALIDATE_STR_SIZE, 0, 64}, {"URL", VALIDATE_STR_SIZE, 0, 256}, {"Username", VALIDATE_STR_SIZE, 0, 256}, {"Password", VALIDATE_STR_SIZE, 0, 256}, {"FileSize", VALIDATE_UNINT, 0, 0}, {"TargetFileName", VALIDATE_STR_SIZE, 0, 256}}; sched_download_xml_attrs.validations = scheddownload_validation; - sched_download_xml_attrs.nbre_validations = 6; + sched_download_xml_attrs.nbre_validations = 7; LIST_HEAD(time_window_intervals); sched_download_xml_attrs.data_list = &time_window_intervals; diff --git a/src/xml.c b/src/xml.c index bc90cda..14ab01e 100644 --- a/src/xml.c +++ b/src/xml.c @@ -63,11 +63,11 @@ struct xml_node_data xml_nodes_data[] = { [SOAP_REQ_ADDOBJ] = {XML_SINGLE, 0, NULL, {{"ObjectName", XML_STRING, 0, NULL}, {"ParameterKey", XML_STRING, 0, NULL}}}, [SOAP_REQ_DELOBJ] = {XML_SINGLE, 0, NULL, {{"ObjectName", XML_STRING, 0, NULL}, {"ParameterKey", XML_STRING, 0, NULL}}}, [SOAP_REQ_REBOOT] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}}}, - [SOAP_REQ_DOWNLOAD] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"FileType", XML_FUNC, 0, load_download_filetype}, {"URL", XML_STRING, 0, NULL}, {"Username", XML_STRING, 0, NULL}, {"Password", XML_STRING, 0, NULL}, {"FileSize", XML_INTEGER, 0, NULL}, {"DelaySeconds", XML_INTEGER, 0, NULL}}}, + [SOAP_REQ_DOWNLOAD] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"FileType", XML_FUNC, 0, load_download_filetype}, {"URL", XML_STRING, 0, NULL}, {"Username", XML_STRING, 0, NULL}, {"Password", XML_STRING, 0, NULL}, {"FileSize", XML_INTEGER, 0, NULL}, {"TargetFileName", XML_STRING, 0, NULL}, {"DelaySeconds", XML_INTEGER, 0, NULL}}}, [SOAP_REQ_UPLOAD] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"FileType", XML_FUNC, 0, load_upload_filetype}, {"URL", XML_STRING, 0, NULL}, {"Username", XML_STRING, 0, NULL}, {"Password", XML_STRING, 0, NULL}, {"DelaySeconds", XML_INTEGER, 0, NULL}}}, [SOAP_REQ_CANCELTRANSFER] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}}}, [SOAP_REQ_SCHEDINF] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"DelaySeconds", XML_INTEGER, 0, NULL}}}, - [SOAP_REQ_SCHEDDOWN] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"FileType", XML_STRING, 0, NULL}, {"URL", XML_STRING, 0, NULL}, {"Username", XML_STRING, 0, NULL}, {"Password", XML_STRING, 0, NULL}, {"FileSize", XML_STRING, 0, NULL}, {"TimeWindowList", XML_REC, SOAP_TIMEWINDOW_REF, NULL}}}, + [SOAP_REQ_SCHEDDOWN] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"FileType", XML_STRING, 0, NULL}, {"URL", XML_STRING, 0, NULL}, {"Username", XML_STRING, 0, NULL}, {"Password", XML_STRING, 0, NULL}, {"FileSize", XML_STRING, 0, NULL}, {"TargetFileName", XML_STRING, 0, NULL}, {"TimeWindowList", XML_REC, SOAP_TIMEWINDOW_REF, NULL}}}, [SOAP_REQ_CDU] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"Operations", XML_REC, SOAP_REQ_CDU_OPERATIONS, NULL}}}, [SOAP_REQ_SPV_LIST] = {XML_LIST, SOAP_REQ_SPV_LIST_REF, "ParameterValueStruct", {}}, [SOAP_REQ_SPV_LIST_REF] = {XML_SINGLE, 0, NULL, {{"Name", XML_STRING, 0, NULL}, {"Value", XML_STRING, 0, NULL}}}, @@ -173,7 +173,7 @@ struct xml_node_data xml_nodes_data[] = { [GET_RPC_ATTR] = {XML_SINGLE, 0, NULL, {{"xsi:type", XML_STRING, 0, NULL}, {"soap_enc:arrayType", XML_FUNC, 0, get_soap_enc_array_type}}} }; -struct xml_switch xml_nodes_names_switches[] = {{"URL", "url"}, {"UUID", "uuid"}, {"IsDownload", "isdownload"}, {"AnnounceURL", "announceurl"}, {"TransferURL", "transferurl"}, {"ExecutionEnvRef", "executionenvref"}, {"Resolved", "resolved"}, {"CurrentState", "uuid"}, {"FileType", "file_type"}, {"CommandKey", "command_key"}, {"Username", "username"}, {"Version", "version"}, {"Password", "password"}, {"StartTime", "start_time"}, {"CompleteTime", "complete_time"}, {"FileSize", "file_size"}, {"FaultCode", "fault_code"}, {"FaultString", "fault_string"}}; +struct xml_switch xml_nodes_names_switches[] = {{"URL", "url"}, {"UUID", "uuid"}, {"IsDownload", "isdownload"}, {"AnnounceURL", "announceurl"}, {"TransferURL", "transferurl"}, {"ExecutionEnvRef", "executionenvref"}, {"Resolved", "resolved"}, {"CurrentState", "uuid"}, {"FileType", "file_type"}, {"CommandKey", "command_key"}, {"Username", "username"}, {"Version", "version"}, {"Password", "password"}, {"StartTime", "start_time"}, {"CompleteTime", "complete_time"}, {"FileSize", "file_size"}, {"TargetFileName", "target_file"}, {"FaultCode", "fault_code"}, {"FaultString", "fault_string"}}; char* xml_tags_names[] = { "ParameterList",