Device.DeviceInfo.FirmwareImage: add support for Download() and Activate() commands

This commit is contained in:
Amin Ben Ramdhane 2021-05-25 10:49:17 +01:00
parent d1b7bab383
commit a82500080a
8 changed files with 577 additions and 75 deletions

View file

@ -159,6 +159,8 @@ libbbfdm_la_LIBADD = \
$(LBLOBMSG_LIBS) \
$(LIBDLOPEN_LIBS) \
$(LIBCURL_LIBS) \
$(LIBOPENSSL_LIBS) \
$(LIBCRYPTO_LIBS) \
-lbbf_api
libbbfdm_la_CFLAGS+=-I../

View file

@ -100,6 +100,9 @@ AC_SUBST([LIBDLOPEN_LIBS])
LIBCURL_LIBS='-lcurl'
AC_SUBST([LIBCURL_LIBS])
LIBCRYPTO_LIBS='-lcrypto'
AC_SUBST([LIBCRYPTO_LIBS])
AM_COND_IF([LOPENSSL], [
LIBOPENSSL_LIBS='-lssl'
AC_SUBST([LIBOPENSSL_LIBS])

View file

@ -9,6 +9,7 @@
*
*/
#include <openssl/sha.h>
#include <curl/curl.h>
#include <libtrace.h>
#include "dmentry.h"
@ -16,6 +17,7 @@
static int read_next;
static struct diagnostic_stats diag_stats = {0};
static const int READ_BUF_SIZE = { 1024 * 16 };
char *get_diagnostics_option(char *sec_name, char *option)
{
@ -68,34 +70,91 @@ void set_diagnostics_interface_option(struct dmctx *ctx, char *sec_name, char *v
}
}
static int download_file(const char *file_path, const char *url, const char *username, const char *password)
static bool get_response_code_status(const char *url, int response_code)
{
int res_code = 0;
if ((strncmp(url, HTTP_URI, strlen(HTTP_URI)) == 0 && response_code != 200) ||
(strncmp(url, FTP_URI, strlen(FTP_URI)) == 0 && response_code != 226) ||
(strncmp(url, FILE_URI, strlen(FILE_URI)) == 0 && response_code != 0) ||
(strncmp(url, HTTP_URI, strlen(HTTP_URI)) && strncmp(url, FTP_URI, strlen(FTP_URI)) && strncmp(url, FILE_URI, strlen(FILE_URI)))) {
return false;
}
CURL *curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_USERNAME, username);
curl_easy_setopt(curl, CURLOPT_PASSWORD, password);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, CURL_TIMEOUT);
return true;
}
FILE *fp = fopen(file_path, "wb");
if (fp) {
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_perform(curl);
fclose(fp);
static void send_transfer_complete_event(const char *command, const char *obj_path, const char *transfer_url,
long res_code, time_t start_t, time_t complete_t, const char *transfer_type)
{
char start_time[32] = {0};
char complete_time[32] = {0};
char fault_string[128] = {0};
unsigned fault_code = 0;
strftime(start_time, sizeof(start_time), "%Y-%m-%dT%H:%M:%SZ", localtime(&start_t));
strftime(complete_time, sizeof(complete_time), "%Y-%m-%dT%H:%M:%SZ", localtime(&complete_t));
if (!get_response_code_status(transfer_url, res_code)) {
fault_code = USP_FAULT_GENERAL_FAILURE;
snprintf(fault_string, sizeof(fault_string), "%s operation is failed, fault code (%ld)", transfer_type, res_code);
}
struct json_object *obj = json_object_new_object();
json_object_object_add(obj, "Command", json_object_new_string(command));
json_object_object_add(obj, "CommandKey", json_object_new_string(""));
json_object_object_add(obj, "Requestor", json_object_new_string(""));
json_object_object_add(obj, "TransferType", json_object_new_string(transfer_type));
json_object_object_add(obj, "Affected", json_object_new_string(obj_path));
json_object_object_add(obj, "TransferURL", json_object_new_string(transfer_url));
json_object_object_add(obj, "StartTime", json_object_new_string(start_time));
json_object_object_add(obj, "CompleteTime", json_object_new_string(complete_time));
json_object_object_add(obj, "FaultCode", json_object_new_uint64(fault_code));
json_object_object_add(obj, "FaultString", json_object_new_string(fault_string));
dmubus_call_set("usp.raw", "notify_event", UBUS_ARGS{{"name", "Device.LocalAgent.TransferComplete!", String}, {"input", json_object_to_json_string(obj), Table}}, 2);
json_object_put(obj);
}
static long download_file(char *file_path, const char *url, const char *username, const char *password)
{
long res_code = 0;
if (strncmp(url, FILE_URI, strlen(FILE_URI)) == 0) {
const char *curr_path = (!strncmp(url, FILE_LOCALHOST_URI, strlen(FILE_LOCALHOST_URI))) ? url + strlen(FILE_LOCALHOST_URI) : url + strlen(FILE_URI);
if (!file_exists(curr_path))
return -1;
DM_STRNCPY(file_path, curr_path, 256);
} else {
CURL *curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_USERNAME, username);
curl_easy_setopt(curl, CURLOPT_PASSWORD, password);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, CURL_TIMEOUT);
FILE *fp = fopen(file_path, "wb");
if (fp) {
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_perform(curl);
fclose(fp);
}
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &res_code);
curl_easy_cleanup(curl);
}
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &res_code);
curl_easy_cleanup(curl);
}
return res_code;
}
static 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_easy_init();
if (curl) {
@ -119,7 +178,222 @@ static int upload_file(const char *file_path, const char *url, const char *usern
return res_code;
}
int bbf_config_backup(const char *url, const char *username, const char *password, char *config_name)
const bool validate_file_system_size(const char *file_size)
{
if (file_size && *file_size) {
unsigned long f_size = strtoul(file_size, NULL, 10);
unsigned long fs_available_size = file_system_size("/tmp", FS_SIZE_AVAILABLE);
if (fs_available_size < f_size)
return false;
}
return true;
}
const bool validate_sha1sum_value(const char *file_path, const char *checksum)
{
unsigned char hash[SHA_DIGEST_LENGTH];
unsigned char buffer[READ_BUF_SIZE];
char sha1_res[1 + SHA_DIGEST_LENGTH * 2];
bool res = false;
int bytes = 0;
SHA_CTX ctx;
FILE *file = fopen(file_path, "rb");
if (!file)
return false;
if (!SHA1_Init(&ctx))
goto end;
while ((bytes = fread (buffer, 1, sizeof(buffer), file))) {
if (!SHA1_Update(&ctx, buffer, bytes))
goto end;
}
if (!SHA1_Final(hash, &ctx))
goto end;
for (int i = 0; i < SHA_DIGEST_LENGTH; i++)
snprintf(&sha1_res[i * 2], sizeof(sha1_res) - (i * 2), "%02x", hash[i]);
if (strcmp(sha1_res, checksum) == 0)
res = true;
end:
fclose(file);
return res;
}
const bool validate_sha224sum_value(const char *file_path, const char *checksum)
{
unsigned char hash[SHA224_DIGEST_LENGTH];
unsigned char buffer[READ_BUF_SIZE];
char sha224_res[1 + SHA224_DIGEST_LENGTH * 2];
bool res = false;
int bytes = 0;
SHA256_CTX ctx;
FILE *file = fopen(file_path, "rb");
if (!file)
return false;
if (!SHA224_Init(&ctx))
goto end;
while ((bytes = fread (buffer, 1, sizeof(buffer), file))) {
if (!SHA224_Update(&ctx, buffer, bytes))
goto end;
}
if (!SHA224_Final(hash, &ctx))
goto end;
for (int i = 0; i < SHA224_DIGEST_LENGTH; i++)
snprintf(&sha224_res[i * 2], sizeof(sha224_res) - (i * 2), "%02x", hash[i]);
if (strcmp(sha224_res, checksum) == 0)
res = true;
end:
fclose(file);
return res;
}
const bool validate_sha256sum_value(const char *file_path, const char *checksum)
{
unsigned char hash[SHA256_DIGEST_LENGTH];
unsigned char buffer[READ_BUF_SIZE];
char sha256_res[1 + SHA256_DIGEST_LENGTH * 2];
bool res = false;
int bytes = 0;
SHA256_CTX ctx;
FILE *file = fopen(file_path, "rb");
if (!file)
return false;
if (!SHA256_Init(&ctx))
goto end;
while ((bytes = fread (buffer, 1, sizeof(buffer), file))) {
if (!SHA256_Update(&ctx, buffer, bytes))
goto end;
}
if (!SHA256_Final(hash, &ctx))
goto end;
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
snprintf(&sha256_res[i * 2], sizeof(sha256_res) - (i * 2), "%02x", hash[i]);
if (strcmp(sha256_res, checksum) == 0)
res = true;
end:
fclose(file);
return res;
}
const bool validate_sha384sum_value(const char *file_path, const char *checksum)
{
unsigned char hash[SHA384_DIGEST_LENGTH];
unsigned char buffer[READ_BUF_SIZE];
char sha384_res[1 + SHA384_DIGEST_LENGTH * 2];
bool res = false;
int bytes = 0;
SHA512_CTX ctx;
FILE *file = fopen(file_path, "rb");
if (!file)
return false;
if (!SHA384_Init(&ctx))
goto end;
while ((bytes = fread (buffer, 1, sizeof(buffer), file))) {
if (!SHA384_Update(&ctx, buffer, bytes))
goto end;
}
if (!SHA384_Final(hash, &ctx))
goto end;
for (int i = 0; i < SHA384_DIGEST_LENGTH; i++)
snprintf(&sha384_res[i * 2], sizeof(sha384_res) - (i * 2), "%02x", hash[i]);
if (strcmp(sha384_res, checksum) == 0)
res = true;
end:
fclose(file);
return res;
}
const bool validate_sha512sum_value(const char *file_path, const char *checksum)
{
unsigned char hash[SHA512_DIGEST_LENGTH];
unsigned char buffer[READ_BUF_SIZE];
char sha512_res[1 + SHA512_DIGEST_LENGTH * 2];
bool res = false;
int bytes = 0;
SHA512_CTX ctx;
FILE *file = fopen(file_path, "rb");
if (!file)
return false;
if (!SHA512_Init(&ctx))
goto end;
while ((bytes = fread (buffer, 1, sizeof(buffer), file))) {
if (!SHA512_Update(&ctx, buffer, bytes))
goto end;
}
if (!SHA512_Final(hash, &ctx))
goto end;
for (int i = 0; i < SHA512_DIGEST_LENGTH; i++)
snprintf(&sha512_res[i * 2], sizeof(sha512_res) - (i * 2), "%02x", hash[i]);
if (strcmp(sha512_res, checksum) == 0)
res = true;
end:
fclose(file);
return res;
}
const bool validate_checksum_value(const char *file_path, const char *checksum_algorithm, const char *checksum)
{
if (checksum && *checksum) {
if (strcmp(checksum_algorithm, "SHA-1") == 0)
return validate_sha1sum_value(file_path, checksum);
else if (strcmp(checksum_algorithm, "SHA-224") == 0)
return validate_sha224sum_value(file_path, checksum);
else if (strcmp(checksum_algorithm, "SHA-256") == 0)
return validate_sha256sum_value(file_path, checksum);
else if (strcmp(checksum_algorithm, "SHA-384") == 0)
return validate_sha384sum_value(file_path, checksum);
else if (strcmp(checksum_algorithm, "SHA-512") == 0)
return validate_sha512sum_value(file_path, checksum);
else
return false;
}
return true;
}
int bbf_config_backup(const char *url, const char *username, const char *password,
char *config_name, const char *command, const char *obj_path)
{
int res = 0;
@ -129,57 +403,166 @@ int bbf_config_backup(const char *url, const char *username, const char *passwor
goto end;
}
// Upload config file
int res_code = upload_file(CONFIG_BACKUP, url, username, password);
if ((strncmp(url, HTTP_PROTO, strlen(HTTP_PROTO)) == 0 && res_code != 200) ||
(strncmp(url, FTP_PROTO, strlen(FTP_PROTO)) == 0 && res_code != 226) ||
(strncmp(url, HTTP_PROTO, strlen(HTTP_PROTO)) && strncmp(url, FTP_PROTO, strlen(FTP_PROTO))))
// Upload the config file
time_t start_time = time(NULL);
long res_code = upload_file(CONFIG_BACKUP, url, username, password);
time_t complete_time = time(NULL);
// Send Transfer Complete Event
send_transfer_complete_event(command, obj_path, url, res_code, start_time, complete_time, "Upload");
// Check if the upload operation was successful
if (!get_response_code_status(url, res_code)) {
res = -1;
goto end;
}
end:
// Remove temporary file
if (remove(CONFIG_BACKUP))
if (file_exists(CONFIG_BACKUP) && remove(CONFIG_BACKUP))
res = -1;
return res;
}
int bbf_config_restore(const char *url, const char *username, const char *password, const char *size)
int bbf_config_restore(const char *url, const char *username, const char *password,
const char *file_size, const char *checksum_algorithm, const char *checksum,
const char *command, const char *obj_path)
{
char config_restore[256] = "/tmp/bbf_config_restore";
int res = 0;
// Check file size
if (size && *size) {
unsigned long file_size = strtoul(size, NULL, 10);
unsigned long fs_available_size = file_system_size("/tmp", FS_SIZE_AVAILABLE);
if (fs_available_size < file_size) {
res = -1;
goto end;
}
// Check the file system size if there is sufficient space for downloading the config file
if (!validate_file_system_size(file_size)) {
res = -1;
goto end;
}
// Download config file
int res_code = download_file(CONFIG_RESTORE, url, username, password);
if ((strncmp(url, HTTP_PROTO, strlen(HTTP_PROTO)) == 0 && res_code != 200) ||
(strncmp(url, FTP_PROTO, strlen(FTP_PROTO)) == 0 && res_code != 226) ||
(strncmp(url, HTTP_PROTO, strlen(HTTP_PROTO)) && strncmp(url, FTP_PROTO, strlen(FTP_PROTO)))) {
// Download the firmware image
time_t start_time = time(NULL);
long res_code = download_file(config_restore, url, username, password);
time_t complete_time = time(NULL);
// Send Transfer Complete Event
send_transfer_complete_event(command, obj_path, url, res_code, start_time, complete_time, "Download");
// Check if the download operation was successful
if (!get_response_code_status(url, res_code)) {
res = -1;
goto end;
}
// Validate the CheckSum value according to its algorithm
if (!validate_checksum_value(config_restore, checksum_algorithm, checksum)) {
res = -1;
goto end;
}
// Apply config file
if (dmuci_import(NULL, CONFIG_RESTORE))
if (dmuci_import(NULL, config_restore))
res = -1;
end:
// Remove temporary file
if (remove(CONFIG_RESTORE))
if (file_exists(config_restore) && strncmp(url, FILE_URI, strlen(FILE_URI)) && remove(config_restore))
res = -1;
return res;
}
int bbf_fw_image_download(const char *url, const char *auto_activate, const char *username, const char *password,
const char *file_size, const char *checksum_algorithm, const char *checksum,
const char *bank_id, const char *command, const char *obj_path)
{
char fw_image_path[256] = "/tmp/firmware.bin";
json_object *json_obj = NULL;
bool activate = false;
int res = 0;
// Check the file system size if there is sufficient space for downloading the firmware image
if (!validate_file_system_size(file_size)) {
res = -1;
goto end;
}
// Download the firmware image
time_t start_time = time(NULL);
long res_code = download_file(fw_image_path, url, username, password);
time_t complete_time = time(NULL);
// Send Transfer Complete Event
send_transfer_complete_event(command, obj_path, url, res_code, start_time, complete_time, "Download");
// Check if the download operation was successful
if (!get_response_code_status(url, res_code)) {
res = -1;
goto end;
}
// Validate the CheckSum value according to its algorithm
if (!validate_checksum_value(fw_image_path, checksum_algorithm, checksum)) {
res = -1;
goto end;
}
// Apply Firmware Image
dmubus_call("fwbank", "upgrade", UBUS_ARGS{{"path", fw_image_path, String}, {"auto_activate", auto_activate, Boolean}, {"bank", bank_id, Integer}}, 3, &json_obj);
if (!json_obj) {
res = -1;
goto end;
}
// Reboot the device if auto activation is true
string_to_bool((char *)auto_activate, &activate);
if (activate) {
sleep(30); // Wait for the image to become available
if (dmubus_call_set("system", "reboot", UBUS_ARGS{}, 0) != 0)
res = -1;
}
end:
// Remove temporary file
if (!json_obj && file_exists(fw_image_path) && strncmp(url, FILE_URI, strlen(FILE_URI)) && remove(fw_image_path))
res = -1;
return res;
}
static void launch_activate_iamge_cb(struct uloop_timeout *t)
{
dmubus_call_set("system", "reboot", UBUS_ARGS{}, 0);
}
static void activate_fw_images(struct activate_image *active_img)
{
int i = 0;
for (i = 0; i < MAX_TIME_WINDOW && *active_img->start_time; i++, active_img++) {
active_img->activate_timer.cb = launch_activate_iamge_cb;
uloop_timeout_set(&active_img->activate_timer, atoi(active_img->start_time) * 1000);
}
}
int bbf_fw_image_activate(const char *bank_id, struct activate_image *active_img)
{
json_object *json_obj = NULL;
dmubus_call("fwbank", "set_bootbank", UBUS_ARGS{{"bank", bank_id, Integer}}, 1, &json_obj);
char *status = dmjson_get_value(json_obj, 1, "success");
if (strcmp(status, "true") != 0)
return -1;
if (*active_img->start_time) {
activate_fw_images(active_img);
} else {
if (dmubus_call_set("system", "reboot", UBUS_ARGS{}, 0) != 0)
return -1;
}
return 0;
}
static void libtrace_cleanup(libtrace_t *trace, libtrace_packet_t *packet)
{
if (trace)
@ -578,8 +961,8 @@ int start_upload_download_diagnostic(int diagnostic_type)
}
if ((url[0] == '\0') ||
(strncmp(url, HTTP_PROTO, strlen(HTTP_PROTO)) != 0 &&
strncmp(url, FTP_PROTO, strlen(FTP_PROTO)) != 0 &&
(strncmp(url, HTTP_URI, strlen(HTTP_URI)) != 0 &&
strncmp(url, FTP_URI, strlen(FTP_URI)) != 0 &&
strstr(url,"@") != NULL))
return -1;
@ -600,9 +983,9 @@ int start_upload_download_diagnostic(int diagnostic_type)
status = get_diagnostics_option("download", "DiagnosticState");
if (status && strcmp(status, "Complete") == 0) {
memset(&diag_stats, 0, sizeof(diag_stats));
if (strncmp(url, HTTP_PROTO, strlen(HTTP_PROTO)) == 0)
if (strncmp(url, HTTP_URI, strlen(HTTP_URI)) == 0)
extract_stats(DOWNLOAD_DUMP_FILE, DIAGNOSTIC_HTTP, DOWNLOAD_DIAGNOSTIC);
if (strncmp(url, FTP_PROTO, strlen(FTP_PROTO)) == 0)
if (strncmp(url, FTP_URI, strlen(FTP_URI)) == 0)
extract_stats(DOWNLOAD_DUMP_FILE, DIAGNOSTIC_FTP, DOWNLOAD_DIAGNOSTIC);
} else if (status && strncmp(status, "Error_", strlen("Error_")) == 0)
return -1;
@ -619,9 +1002,9 @@ int start_upload_download_diagnostic(int diagnostic_type)
status = get_diagnostics_option("upload", "DiagnosticState");
if (status && strcmp(status, "Complete") == 0) {
memset(&diag_stats, 0, sizeof(diag_stats));
if (strncmp(url, HTTP_PROTO, strlen(HTTP_PROTO)) == 0)
if (strncmp(url, HTTP_URI, strlen(HTTP_URI)) == 0)
extract_stats(UPLOAD_DUMP_FILE, DIAGNOSTIC_HTTP, UPLOAD_DIAGNOSTIC);
if (strncmp(url, FTP_PROTO, strlen(FTP_PROTO)) == 0)
if (strncmp(url, FTP_URI, strlen(FTP_URI)) == 0)
extract_stats(UPLOAD_DUMP_FILE, DIAGNOSTIC_FTP, UPLOAD_DIAGNOSTIC);
} else if (status && strncmp(status, "Error_", strlen("Error_")) == 0)
return -1;

View file

@ -13,9 +13,12 @@
#define __DMDIAGNOSTICS_H__
#include <libbbf_api/dmcommon.h>
#include <libubox/uloop.h>
#define HTTP_PROTO "http://"
#define FTP_PROTO "ftp://"
#define HTTP_URI "http"
#define FTP_URI "ftp"
#define FILE_URI "file://"
#define FILE_LOCALHOST_URI "file://localhost"
#define default_date_format "AAAA-MM-JJTHH:MM:SS.000000Z"
#define default_date_size sizeof(default_date_format) + 1
#define FTP_SIZE_RESPONSE "213"
@ -23,10 +26,10 @@
#define FTP_TRANSFERT_COMPLETE "226 Transfer"
#define FTP_RETR_REQUEST "RETR"
#define FTP_STOR_REQUEST "STOR"
#define CURL_TIMEOUT 10
#define CURL_TIMEOUT 100
#define DMMAP_DIAGNOSTIGS "dmmap_diagnostics"
#define CONFIG_RESTORE "/tmp/bbf_config_restore"
#define CONFIG_BACKUP "/tmp/bbf_config_backup"
#define MAX_TIME_WINDOW 5
struct diagnostic_stats
{
@ -45,6 +48,12 @@ struct diagnostic_stats
uint32_t ftp_syn;
};
struct activate_image
{
struct uloop_timeout activate_timer;
char *start_time;
};
enum diagnostic_protocol {
DIAGNOSTIC_HTTP = 1,
DIAGNOSTIC_FTP
@ -61,7 +70,14 @@ void set_diagnostics_option(char *sec_name, char *option, char *value);
void init_diagnostics_operation(char *sec_name, char *operation_path);
void set_diagnostics_interface_option(struct dmctx *ctx, char *sec_name, char *value);
int start_upload_download_diagnostic(int diagnostic_type);
int bbf_config_backup(const char *url, const char *username, const char *password, char *config_name);
int bbf_config_restore(const char *url, const char *username, const char *password, const char *size);
int bbf_config_backup(const char *url, const char *username, const char *password,
char *config_name, const char *command, const char *obj_path);
int bbf_config_restore(const char *url, const char *username, const char *password,
const char *file_size, const char *checksum_algorithm, const char *checksum,
const char *command, const char *obj_path);
int bbf_fw_image_download(const char *url, const char *auto_activate, const char *username, const char *password,
const char *file_size, const char *checksum_algorithm, const char *checksum,
const char *bank_id, const char *command, const char *obj_path);
int bbf_fw_image_activate(const char *bank_id, struct activate_image *active_img);
#endif

View file

@ -20,6 +20,14 @@
static uint8_t wifi_neighbor_count = 0;
struct op_cmd *dynamic_operate = NULL;
static const char *fw_image_activate_in[] = {
"TimeWindow.1.Start",
"TimeWindow.2.Start",
"TimeWindow.3.Start",
"TimeWindow.4.Start",
"TimeWindow.5.Start",
};
static void bbf_init(struct dmctx *dm_ctx, char *path)
{
unsigned int instance = INSTANCE_MODE_NUMBER;
@ -219,6 +227,12 @@ static opr_ret_t dhcp_client_renew(struct dmctx *dmctx, char *path, json_object
static opr_ret_t vendor_conf_backup(struct dmctx *dmctx, char *path, json_object *input)
{
struct file_server fserver = {0};
char obj_path[256] = {'\0'};
char command[32] = {'\0'};
char *ret = strrchr(path, '.');
strncpy(obj_path, path, ret - path +1);
DM_STRNCPY(command, ret+1, sizeof(command));
char *vcf_name = get_param_val_from_op_cmd(path, "Name");
if (!vcf_name)
@ -231,7 +245,7 @@ static opr_ret_t vendor_conf_backup(struct dmctx *dmctx, char *path, json_object
fserver.user = dmjson_get_value(input, 1, "Username");
fserver.pass = dmjson_get_value(input, 1, "Password");
int res = bbf_config_backup(fserver.url, fserver.user, fserver.pass, vcf_name);
int res = bbf_config_backup(fserver.url, fserver.user, fserver.pass, vcf_name, command, obj_path);
dmfree(vcf_name);
return res ? FAIL : SUCCESS;
@ -240,7 +254,12 @@ static opr_ret_t vendor_conf_backup(struct dmctx *dmctx, char *path, json_object
static opr_ret_t vendor_conf_restore(struct dmctx *dmctx, char *path, json_object *input)
{
struct file_server fserver = {0};
char *file_size = NULL;
char obj_path[256] = {'\0'};
char command[32] = {'\0'};
char *ret = strrchr(path, '.');
strncpy(obj_path, path, ret - path +1);
DM_STRNCPY(command, ret+1, sizeof(command));
fserver.url = dmjson_get_value(input, 1, "URL");
if (fserver.url[0] == '\0')
@ -248,9 +267,11 @@ static opr_ret_t vendor_conf_restore(struct dmctx *dmctx, char *path, json_objec
fserver.user = dmjson_get_value(input, 1, "Username");
fserver.pass = dmjson_get_value(input, 1, "Password");
file_size = dmjson_get_value(input, 1, "FileSize");
fserver.file_size = dmjson_get_value(input, 1, "FileSize");
fserver.checksum_algorithm = dmjson_get_value(input, 1, "CheckSumAlgorithm");
fserver.checksum = dmjson_get_value(input, 1, "CheckSum");
int res = bbf_config_restore(fserver.url, fserver.user, fserver.pass, file_size);
int res = bbf_config_restore(fserver.url, fserver.user, fserver.pass, fserver.file_size, fserver.checksum_algorithm, fserver.checksum, command, obj_path);
return res ? FAIL : SUCCESS;
}
@ -744,11 +765,11 @@ static opr_ret_t swmodules_install_du(struct dmctx *dmctx, char *path, json_obje
return FAIL;
dmubus_call("swmodules", "du_install", UBUS_ARGS{
{"url", du_install.url},
{"uuid", du_install.uuid},
{"username", du_install.username},
{"password", du_install.password},
{"environment", exec_env}},
{"url", du_install.url, String},
{"uuid", du_install.uuid, String},
{"username", du_install.username, String},
{"password", du_install.password, String},
{"environment", exec_env, String}},
5,
&res);
@ -776,10 +797,10 @@ static opr_ret_t swmodules_update_du(struct dmctx *dmctx, char *path, json_objec
return FAIL;
dmubus_call("swmodules", "du_update", UBUS_ARGS{
{"uuid", du_uuid},
{"url", du_update.url},
{"username", du_update.username},
{"password", du_update.password}},
{"uuid", du_uuid, String},
{"url", du_update.url, String},
{"username", du_update.username, String},
{"password", du_update.password, String}},
4,
&res);
@ -810,8 +831,8 @@ static opr_ret_t swmodules_uninstall_du(struct dmctx *dmctx, char *path, json_ob
return FAIL;
dmubus_call("swmodules", "du_uninstall", UBUS_ARGS{
{"name", du_name},
{"environment", env}},
{"name", du_name, String},
{"environment", env, String}},
2,
&res);
@ -826,12 +847,65 @@ static opr_ret_t swmodules_uninstall_du(struct dmctx *dmctx, char *path, json_ob
static opr_ret_t firmware_image_download(struct dmctx *dmctx, char *path, json_object *input)
{
return SUCCESS;
char obj_path[256] = {'\0'};
char command[32] = {'\0'};
char *bank_id = NULL;
char *linker = NULL;
char *ret = strrchr(path, '.');
strncpy(obj_path, path, ret - path +1);
DM_STRNCPY(command, ret+1, sizeof(command));
adm_entry_get_linker_value(dmctx, obj_path, &linker);
if (linker && *linker) {
bank_id = strchr(linker, ':');
if (!bank_id)
return FAIL;
} else {
return FAIL;
}
char *url = dmjson_get_value(input, 1, "URL");
char *auto_activate = dmjson_get_value(input, 1, "AutoActivate");
if (url[0] == '\0' || auto_activate[0] == '\0')
return UBUS_INVALID_ARGUMENTS;
char *username = dmjson_get_value(input, 1, "Username");
char *password = dmjson_get_value(input, 1, "Password");
char *file_size = dmjson_get_value(input, 1, "FileSize");
char *checksum_algorithm = dmjson_get_value(input, 1, "CheckSumAlgorithm");
char *checksum = dmjson_get_value(input, 1, "CheckSum");
int res = bbf_fw_image_download(url, auto_activate, username, password, file_size, checksum_algorithm, checksum, bank_id+1, command, obj_path);
return res ? FAIL : SUCCESS;
}
static opr_ret_t firmware_image_activate(struct dmctx *dmctx, char *path, json_object *input)
{
return SUCCESS;
struct activate_image active_images[MAX_TIME_WINDOW] = {0};
char fwimage_path[256] = {'\0'};
char *bank_id = NULL;
char *linker = NULL;
char *ret = strrchr(path, '.');
strncpy(fwimage_path, path, ret - path +1);
adm_entry_get_linker_value(dmctx, fwimage_path, &linker);
if (linker && *linker) {
bank_id = strchr(linker, ':');
if (!bank_id)
return FAIL;
} else {
return FAIL;
}
for (int i = 0; i < ARRAY_SIZE(fw_image_activate_in); i++)
active_images[i].start_time = dmjson_get_value(input, 1, fw_image_activate_in[i]);
int res = bbf_fw_image_activate(bank_id+1, active_images);
return res ? FAIL : SUCCESS;
}
static int get_index_of_available_dynamic_operate(struct op_cmd *operate)
@ -934,7 +1008,17 @@ static const struct op_cmd operate_helper[] = {
}
},
{
"Device.DeviceInfo.FirmwareImage.*.Activate", firmware_image_activate, "async"
"Device.DeviceInfo.FirmwareImage.*.Activate", firmware_image_activate, "async",
{
.in = (const char *[]) {
"TimeWindow.{i}.Start",
"TimeWindow.{i}.End",
"TimeWindow.{i}.Mode",
"TimeWindow.{i}.UserMessage",
"TimeWindow.{i}.MaxRetries",
NULL
}
}
},
{
"Device.WiFi.NeighboringWiFiDiagnostic", fetch_neighboring_wifi_diagnostic, "async",

View file

@ -34,6 +34,9 @@ struct file_server {
char *url;
char *user;
char *pass;
char *file_size;
char *checksum_algorithm;
char *checksum;
};
struct neighboring_wiFi_diagnostic {

View file

@ -88,10 +88,19 @@ static int __dm_ubus_call(const char *obj, const char *method, const struct ubus
blob_buf_init(&b, 0);
for (i = 0; i < u_args_size; i++) {
if (u_args[i].type != Integer)
blobmsg_add_string(&b, u_args[i].key, u_args[i].val);
else
if (u_args[i].type == Integer) {
blobmsg_add_u32(&b, u_args[i].key, atoi(u_args[i].val));
} else if (u_args[i].type == Boolean) {
bool val = false;
string_to_bool((char *)u_args[i].val, &val);
blobmsg_add_u8(&b, u_args[i].key, val);
} else if (u_args[i].type == Table) {
json_object *obj = json_tokener_parse(u_args[i].val);
blobmsg_add_json_element(&b, u_args[i].key, obj);
json_object_put(obj);
} else {
blobmsg_add_string(&b, u_args[i].key, u_args[i].val);
}
}
if (!ubus_lookup_id(ubus_ctx, obj, &id))

View file

@ -19,6 +19,8 @@
enum ubus_arg_type {
String,
Integer,
Boolean,
Table
};
struct ubus_arg {