Increase upload curl timeout to 30 seconds and improve the code to prevent crashes

This commit is contained in:
Amin Ben Romdhane 2023-12-26 04:37:09 +00:00 committed by Vivek Kumar Dutta
parent f9a7bb027a
commit a1df16afca
4 changed files with 80 additions and 54 deletions

View file

@ -72,6 +72,7 @@
#define BUF_SIZE_256 (256 + 1) #define BUF_SIZE_256 (256 + 1)
#define BUF_SIZE_2048 (2048 + 1) #define BUF_SIZE_2048 (2048 + 1)
#define ICWMP_TMP_PATH "/tmp/icwmp"
#define FIREWALL_CWMP "/etc/firewall.cwmp" #define FIREWALL_CWMP "/etc/firewall.cwmp"
#define CWMP_VARSTATE_UCI_PACKAGE "/var/state/icwmp" #define CWMP_VARSTATE_UCI_PACKAGE "/var/state/icwmp"
#define DM_PPP_INTERFACE_PATH "Device\\.PPP\\.Interface\\." #define DM_PPP_INTERFACE_PATH "Device\\.PPP\\.Interface\\."

View file

@ -120,6 +120,7 @@ int download_file_in_subprocess(const char *file_path, const char *url, const ch
CWMP_LOG(ERROR, "download %s: url is null"); CWMP_LOG(ERROR, "download %s: url is null");
return 500; return 500;
} }
struct blob_buf bbuf; struct blob_buf bbuf;
CWMP_MEMSET(&bbuf, 0, sizeof(struct blob_buf)); CWMP_MEMSET(&bbuf, 0, sizeof(struct blob_buf));
blob_buf_init(&bbuf, 0); blob_buf_init(&bbuf, 0);
@ -133,8 +134,9 @@ int download_file_in_subprocess(const char *file_path, const char *url, const ch
if (download_task != NULL) { if (download_task != NULL) {
char *ret = execute_task_in_subprocess(download_task); char *ret = execute_task_in_subprocess(download_task);
return atoi(ret); return ret ? atoi(ret) : 500;
} }
return 500; return 500;
} }
/* /*
@ -412,7 +414,7 @@ int cwmp_apply_multiple_firmware_in_subprocess()
{ {
subprocess_start(apply_multiple_firmware_task_function); subprocess_start(apply_multiple_firmware_task_function);
char *ret = execute_task_in_subprocess("{}"); //empty json object char *ret = execute_task_in_subprocess("{}"); //empty json object
return atoi(ret); return ret ? atoi(ret) : 500;
} }
int cwmp_launch_download(struct download *pdownload, char *download_file_name, enum load_type ltype, struct transfer_complete **ptransfer_complete) int cwmp_launch_download(struct download *pdownload, char *download_file_name, enum load_type ltype, struct transfer_complete **ptransfer_complete)

View file

@ -68,14 +68,17 @@ int subprocess_start(task_function task_fun)
return CWMP_GEN_ERR; return CWMP_GEN_ERR;
pid_t p; pid_t p;
if (pipe(pipefd1) == -1) { if (pipe(pipefd1) == -1) {
CWMP_LOG(ERROR, "pipefd1 failed\n"); CWMP_LOG(ERROR, "pipefd1 failed\n");
return CWMP_GEN_ERR; return CWMP_GEN_ERR;
} }
if (pipe(pipefd2) == -1) { if (pipe(pipefd2) == -1) {
CWMP_LOG(ERROR, "pipefd2 failed\n"); CWMP_LOG(ERROR, "pipefd2 failed\n");
return CWMP_GEN_ERR; return CWMP_GEN_ERR;
} }
p = fork(); p = fork();
if (p == 0) { if (p == 0) {
while(1) { while(1) {
@ -85,12 +88,13 @@ int subprocess_start(task_function task_fun)
read(pipefd1[0], from_parent, 512); //The received string should has the form {"task":"TaskName", "arg1_name":"xxx", "arg2_name":"xxxx"} 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) if (strlen(from_parent) == 0)
continue; continue;
//get the task name
//if the task name is end //get the task name if the task name is end
if (check_task_is_end(from_parent)) { if (check_task_is_end(from_parent)) {
exit((write(pipefd2[1], EXIT_TASK, strlen(EXIT_TASK)+1) == -1) exit((write(pipefd2[1], EXIT_TASK, strlen(EXIT_TASK)+1) == -1)
? EXIT_FAILURE : EXIT_SUCCESS); ? EXIT_FAILURE : EXIT_SUCCESS);
} }
char *to_child = task_fun(from_parent); char *to_child = task_fun(from_parent);
struct blob_buf bbuf; struct blob_buf bbuf;

View file

@ -22,13 +22,13 @@
#include "subprocess.h" #include "subprocess.h"
#include "session.h" #include "session.h"
#define CURL_TIMEOUT 20 #define CURL_TIMEOUT 30
int count_upload_queue = 0; int count_upload_queue = 0;
LIST_HEAD(list_upload); LIST_HEAD(list_upload);
int lookup_vcf_name(int instance, char **value) static int lookup_vcf_name(int instance, char **value)
{ {
char vcf_name_parameter[256]; char vcf_name_parameter[256];
LIST_HEAD(vcf_parameters); LIST_HEAD(vcf_parameters);
@ -46,7 +46,7 @@ int lookup_vcf_name(int instance, char **value)
return 0; return 0;
} }
int lookup_vlf_name(int instance, char **value) static int lookup_vlf_name(int instance, char **value)
{ {
char vlf_name_parameter[256]; char vlf_name_parameter[256];
LIST_HEAD(vlf_parameters); LIST_HEAD(vlf_parameters);
@ -67,9 +67,9 @@ int lookup_vlf_name(int instance, char **value)
/* /*
* Upload file * Upload file
*/ */
int upload_file(const char *file_path, const char *url, const char *username, const char *password) static long upload_file(const char *file_path, const char *url, const char *username, const char *password)
{ {
int res_code = 0; long res_code = 0;
CURL *curl; CURL *curl;
CURLcode res; CURLcode res;
FILE *fd_upload; FILE *fd_upload;
@ -77,24 +77,31 @@ int upload_file(const char *file_path, const char *url, const char *username, co
if (url == NULL) { if (url == NULL) {
CWMP_LOG(ERROR, "upload %s: url is null", __FUNCTION__); CWMP_LOG(ERROR, "upload %s: url is null", __FUNCTION__);
return -1; return FAULT_CPE_INTERNAL_ERROR;
} }
if (file_path == NULL) { if (file_path == NULL) {
CWMP_LOG(ERROR, "upload file name unknown"); CWMP_LOG(ERROR, "upload file name unknown");
return -1; return FAULT_CPE_INTERNAL_ERROR;
} }
if (0 != stat(file_path, &file_info)) { if (!file_exists(file_path)) {
CWMP_LOG(ERROR, "upload file %s not exists", file_path); CWMP_LOG(ERROR, "upload_file %s does not exist", file_path);
return -1; return FAULT_CPE_INTERNAL_ERROR;
} }
fd_upload = fopen(file_path, "rb"); fd_upload = fopen(file_path, "rb");
if (fd_upload == NULL) { if (fd_upload == NULL) {
CWMP_LOG(ERROR, "Failed to open url[%s] for upload", file_path); CWMP_LOG(ERROR, "Failed to open file[%s] for upload", file_path);
return FAULT_CPE_INTERNAL_ERROR; return FAULT_CPE_INTERNAL_ERROR;
} }
if (fstat(fileno(fd_upload), &file_info) != 0) {
CWMP_LOG(ERROR, "Failed to get file info for %s\n", file_path);
fclose(fd_upload);
return FAULT_CPE_INTERNAL_ERROR;
}
curl_global_init(CURL_GLOBAL_ALL); curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init(); curl = curl_easy_init();
@ -104,18 +111,20 @@ int upload_file(const char *file_path, const char *url, const char *username, co
snprintf(userpass, sizeof(userpass), "%s:%s", username, password ? password : ""); snprintf(userpass, sizeof(userpass), "%s:%s", username, password ? password : "");
curl_easy_setopt(curl, CURLOPT_USERPWD, userpass); curl_easy_setopt(curl, CURLOPT_USERPWD, userpass);
} }
if (CWMP_STRNCMP(url, "https://", 8) == 0) if (CWMP_STRNCMP(url, "https://", 8) == 0)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, CURL_TIMEOUT); curl_easy_setopt(curl, CURLOPT_TIMEOUT, CURL_TIMEOUT);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L); curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
//curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY); curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY);
curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_READDATA, fd_upload); curl_easy_setopt(curl, CURLOPT_READDATA, fd_upload);
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size); curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
if(res != CURLE_OK) { if (res != CURLE_OK) {
CWMP_LOG(ERROR, "## curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); CWMP_LOG(ERROR, "## curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
} }
@ -130,13 +139,13 @@ int upload_file(const char *file_path, const char *url, const char *username, co
char *upload_file_task_function(char *task) char *upload_file_task_function(char *task)
{ {
struct blob_buf bbuf; struct blob_buf bbuf;
if (task == NULL) { if (task == NULL) {
CWMP_LOG(ERROR, "upload %s: task is null", __FUNCTION__); CWMP_LOG(ERROR, "upload %s: task is null", __FUNCTION__);
return NULL; return NULL;
} }
CWMP_MEMSET(&bbuf, 0, sizeof(struct blob_buf)); CWMP_MEMSET(&bbuf, 0, sizeof(struct blob_buf));
blob_buf_init(&bbuf, 0); blob_buf_init(&bbuf, 0);
@ -156,10 +165,13 @@ char *upload_file_task_function(char *task)
char *username = blobmsg_get_string(tb[3]); char *username = blobmsg_get_string(tb[3]);
char *password = blobmsg_get_string(tb[4]); char *password = blobmsg_get_string(tb[4]);
int http_code = upload_file(file_path, url, username, password); long http_code = upload_file(file_path, url, username, password);
char *http_ret = (char *)malloc(4 * sizeof(char)); char *http_ret = (char *)malloc(16 * sizeof(char));
snprintf(http_ret, 4, "%d", http_code); if (http_ret == NULL)
http_ret[3] = 0; return NULL;
snprintf(http_ret, 16, "%ld", http_code);
return http_ret; return http_ret;
} }
@ -184,7 +196,7 @@ int upload_file_in_subprocess(const char *file_path, const char *url, const char
if (upload_task != NULL) { if (upload_task != NULL) {
char *ret = execute_task_in_subprocess(upload_task); char *ret = execute_task_in_subprocess(upload_task);
return atoi(ret); return ret ? atoi(ret) : 500;
} }
return 500; return 500;
} }
@ -201,16 +213,23 @@ int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptrans
bkp_session_save(); bkp_session_save();
char err_msg[256] = {0}; char err_msg[256] = {0};
if (!folder_exists(ICWMP_TMP_PATH)) {
int status = mkdir(ICWMP_TMP_PATH, S_IRWXU);
if (status != 0) {
snprintf(err_msg, sizeof(err_msg), "Failed to create (%s) folder", ICWMP_TMP_PATH);
goto end_upload;
}
}
if (pupload->file_type[0] == '1') { if (pupload->file_type[0] == '1') {
snprintf(file_path, sizeof(file_path), "/tmp/all_configs"); snprintf(file_path, sizeof(file_path), "%s/all_configs", ICWMP_TMP_PATH);
cwmp_uci_init(); cwmp_uci_init();
cwmp_uci_export(file_path, UCI_STANDARD_CONFIG); cwmp_uci_export(file_path, UCI_STANDARD_CONFIG);
cwmp_uci_exit(); cwmp_uci_exit();
} else if (pupload->file_type[0] == '2') { } else if (pupload->file_type[0] == '2') {
lookup_vlf_name(1, &name); lookup_vlf_name(1, &name);
if (name && strlen(name) > 0) { if (name && strlen(name) > 0) {
snprintf(file_path, sizeof(file_path), "/tmp/messages"); snprintf(file_path, sizeof(file_path), "%s/messages", ICWMP_TMP_PATH);
// cppcheck-suppress uninitvar
if (copy(name, file_path) != 0) { if (copy(name, file_path) != 0) {
error = FAULT_CPE_UPLOAD_FAILURE; error = FAULT_CPE_UPLOAD_FAILURE;
snprintf(err_msg, sizeof(err_msg), "Failed to copy the file content from %s to %s", file_path, name); snprintf(err_msg, sizeof(err_msg), "Failed to copy the file content from %s to %s", file_path, name);
@ -223,7 +242,7 @@ int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptrans
} else if (pupload->file_type[0] == '3') { } else if (pupload->file_type[0] == '3') {
lookup_vcf_name(pupload->f_instance, &name); lookup_vcf_name(pupload->f_instance, &name);
if (name && strlen(name) > 0) { if (name && strlen(name) > 0) {
snprintf(file_path, sizeof(file_path), "/tmp/%s", name); snprintf(file_path, sizeof(file_path), "%s/%s", ICWMP_TMP_PATH, name);
cwmp_uci_init(); cwmp_uci_init();
cwmp_uci_export_package(name, file_path, UCI_STANDARD_CONFIG); cwmp_uci_export_package(name, file_path, UCI_STANDARD_CONFIG);
cwmp_uci_exit(); cwmp_uci_exit();
@ -236,7 +255,7 @@ int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptrans
} else { //file_type is 4 } else { //file_type is 4
lookup_vlf_name(pupload->f_instance, &name); lookup_vlf_name(pupload->f_instance, &name);
if (name && strlen(name) > 0) { if (name && strlen(name) > 0) {
snprintf(file_path, sizeof(file_path), "/tmp/.cwmp_upload"); snprintf(file_path, sizeof(file_path), "%s/.cwmp_upload", ICWMP_TMP_PATH);
if (copy(name, file_path) != 0) { if (copy(name, file_path) != 0) {
error = FAULT_CPE_UPLOAD_FAILURE; error = FAULT_CPE_UPLOAD_FAILURE;
snprintf(err_msg, sizeof(err_msg), "Failed to copy the file content from %s to %s", file_path, name); snprintf(err_msg, sizeof(err_msg), "Failed to copy the file content from %s to %s", file_path, name);