diff --git a/docs/guide/libbbfdm_DeviceInfo_FirmwareImage.md b/docs/guide/libbbfdm_DeviceInfo_FirmwareImage.md deleted file mode 100644 index 3d101bf0..00000000 --- a/docs/guide/libbbfdm_DeviceInfo_FirmwareImage.md +++ /dev/null @@ -1,141 +0,0 @@ -# Design For Firmware Activation - -According to the TR181 data model, the Activate() command is an operation to activate the firmware image immediately or schedule it in another time. - -In fact, the Linux system already provides us a cron to schedule some jobs. And since Openwrt is one of the Linux systems, so we can use a cron job as solution to handle the firmware activation. - -The Activate() command has as arguments the TimeWindow object which is used to activate the required firmware in a specified time. For that, foreach TimeWindow instance a cron job will be created. - -> Note: As per TR181 data model, max 5 instances of TimeWindow is supported. - -Below is an example of an 'Activate()' command call with three TimeWindow instances. As a result, three jobs are created according to the defined TimeWindow.{i}.Start: - -```bash -root@iopsys-44d43771aff0:~# ubus call bbfdm operate '{"path":"Device.DeviceInfo.FirmwareImage.2.", "action":"Activate()", "input":{"TimeWindow.1 -.Start":"1800", "TimeWindow.1.End":"3600", "TimeWindow.1.Mode":"WhenIdle", "TimeWindow.2.Start":"5400", "TimeWindow.2.End":"9000", "TimeWindow -.2.Mode":"WhenIdle", "TimeWindow.3.Start":"86400", "TimeWindow.3.End":"172800", "TimeWindow.3.Mode":"Immediately"}}' -{ - "Results": [ - { - "path": "Device.DeviceInfo.FirmwareImage.2.Activate()", - "result": [ - { - - } - ] - } - ] -} -root@iopsys-44d43771aff0:~# crontab -l -52 22 21 2 * sh /usr/share/bbfdm/scripts/bbf_activate_handler.sh 'WhenIdle' '2' '1800' '0' '' '' -52 23 21 2 * sh /usr/share/bbfdm/scripts/bbf_activate_handler.sh 'WhenIdle' '2' '3600' '0' '' '' -22 22 22 2 * sh /usr/share/bbfdm/scripts/bbf_activate_handler.sh 'Immediately' '2' '86400' '1' '' '' -root@iopsys-44d43771aff0:~# - -``` - -For those cron jobs it is required to give the handler script to be executed which is in our case [bbf_activate_handler.sh](../../libbbfdm/scripts/bbf_activate_handler.sh). And, it is located under '/usr/share/bbfdm/' in the device. - - -## Cron job specification - -For each cron job related to the activated firmware, it is needed to define it as below: - -```bash -* * * * * command to execute * * * * * * -- - - - - - - - - - - - -| | | | | | | | | | | | -| | | | | | | | | | | --- Message that informs the user of a new activation request -| | | | | | | | | | ----- Maximum number of retries -| | | | | | | | | ------- Force firmware activation when it's not idle (0 - 1) -| | | | | | | | --------- End of the time window -| | | | | | | ----------- Firmware Bank id to be activated -| | | | | | ------------- Mode (AnyTime, Immediately, WhenIdle, ConfirmationNeeded) -| | | | | -------------------------------- Activate firmware script 'bbf_activate_handler.sh' -| | | | ---------------------------------- Day of week (0 - 6) (Sunday =0) -| | | ------------------------------------ Month (1 - 12) -| | -------------------------------------- Day (1 - 31) -| ---------------------------------------- Hour (0 - 23) ------------------------------------------- Minute (0 - 59) -``` - - -## Activate Handler script - -As described, we create a cron job for each TimeWindow in order to activate the required firmware within a specified time by running the [bbf_activate_handler.sh](../../libbbfdm/scripts/bbf_activate_handler.sh) handler script. - -In fact, the aim of this script is to manage firmware images based on the **mode** and the other passed arguments. - - -### 1. Mode 'AnyTime' and 'Immediately': - -For these modes and based on the firmware bank id, the required firmware image will be immediately activated at start time. The TimeWindow.{i}.End is ignored. - -### 2. How to handle 'WhenIdle' mode: - -Definition of WhenIdle may vary for each deployment and customer, to make it customizable [bbf_check_idle.sh](../../libbbfdm/scripts/bbf_check_idle.sh) script is used. It is assumed that customer shall overwrite this file using customer-config to match with there requirement. - -In this mode, [bbf_activate_handler.sh](../../libbbfdm/scripts/bbf_activate_handler.sh) script calls this script [bbf_check_idle.sh](../../libbbfdm/scripts/bbf_check_idle.sh) to determine the idle state of the device. [bbf_activate_handler.sh](../../libbbfdm/scripts/bbf_activate_handler.sh) assumes the device as idle if the exit status of the above script is 0, or if the [bbf_check_idle.sh](../../libbbfdm/scripts/bbf_check_idle.sh) is not present in the predefined path "ACTIVATE_HANDLER_FILE@dmcommon.h". - - -If the exit code from the idle script is zero then firmware image can be activated. Otherwise, it has to wait for next time slot which is defined by 'RETRY_TIME' variable. - -> Note1: The time slot is set through 'RETRY_TIME' variable which is defined under '/usr/share/bbfdm/scripts/bbf_activate_handler.sh' script. - -> Note2: The exit status of the script [bbf_check_idle.sh](../../libbbfdm/scripts/bbf_check_idle.sh) is important because based on it, the '[bbf_activate_handler.sh](../../libbbfdm/scripts/bbf_activate_handler.sh) script will decide whether the image can be activated or not. - -> Note3: Algorithm/Logic to determine the Idle state of device is out of scope of this document and it is expected that users overwrite this script with the logic to determine the same in actual deployment. - -> Note4: If 1 or more TimeWindow.{i}.Mode is set to 'WhenIdle' and all of them fails to get the idle state. The latest TimeWindow instance will force the device to activate the firmware image. - -> Note5: If the idle script [bbf_check_idle.sh](../../libbbfdm/scripts/bbf_check_idle.sh) not present in the pre-defined path "ACTIVATE_HANDLER_FILE@dmcommon.h", then the device is assumed to be in ideal state and the firmware shall be activated instantly. - -> Note6: It is very likely that TimeWindow with 'WhenIdle' mode might not find any suitable Idle state, in that case firmware shall not be activated. If users/operators want to make sure that firmware gets activated at the end, then they can add a TimeWindow with 'AnyTime/Immediate' mode at the end, to activate the firmware. - - -## Good to know - -* TimeWindow instance arguments are optional. - -* TimeWindow instances attributes must not overlap. - -* If TimeWindow.{i}.Start is set, TimeWindow.{i}.End and TimeWindow.{i}.Mode become mondatory. - -* The firmware activation is done by [bbf_activate_handler.sh](../../libbbfdm/scripts/bbf_activate_handler.sh) script as per the defined Mode in TimeWindow, but if the TimeWindow is not defined, it will activate the requested FirmwareImage instance immediately. - -* If the customer wants to be sure that the required firmware is getting activated at the end then they can define the TimeWindow.{i}.Mode as 'AnyTime' or 'Immediately' in the last TimeWindow instance. - -* This document is only target for Firmware management using USP. - -* TimeWindow.{i}.Mode = 'ConfirmationNeeded' is not supported. - - -## Vendor extension option to keep config while firmware download - -It deployments for some customers, its required to do a factory reset after doing a firmware upgrade to start the CPE from clean state and then provision it from ACS/Controller. - -As per standard datamodel, it's at-least 2 step time consuming process: -- Download the Firmware using 'Device.DeviceInfo.FirmwareImage.{i}.Download()' operate command with AutoActivate=1 -- Wait for the 'Device.Boot!' event -- Factory reset the CPE using 'Device.FactoryReset()' -- Wait for the Boot event and then start provisioning. - -We added an addition vendor specific input option which can be used by USP controller to factoryReset the CPE along with Firmware Upgrade, with this customer can save the cost of one additional reboot, which result into faster provisioning of the CPE. - -Below are the current input options defined for Download operate command -```bash -Device.DeviceInfo.FirmwareImage.{i}.Download() -Device.DeviceInfo.FirmwareImage.{i}.Download() input:AutoActivate -Device.DeviceInfo.FirmwareImage.{i}.Download() input:CheckSum -Device.DeviceInfo.FirmwareImage.{i}.Download() input:CheckSumAlgorithm -Device.DeviceInfo.FirmwareImage.{i}.Download() input:CommandKey -Device.DeviceInfo.FirmwareImage.{i}.Download() input:FileSize -Device.DeviceInfo.FirmwareImage.{i}.Download() input:Password -Device.DeviceInfo.FirmwareImage.{i}.Download() input:URL -Device.DeviceInfo.FirmwareImage.{i}.Download() input:Username -Device.DeviceInfo.FirmwareImage.{i}.Download() input:X_IOPSYS_EU_KeepConfig -``` - -Customer can use X_IOPSYS_EU_KeepConfig=0, to do factory reset(not copy the current config to next firmware) while doing the download. - -> Note: Default value of X_IOPSYS_EU_KeepConfig is 1, so in case this option not used, it keeps the config(as the default behavior of the CPE). diff --git a/docs/guide/libbbfdm_DeviceInfo_Reboots.md b/docs/guide/libbbfdm_DeviceInfo_Reboots.md deleted file mode 100644 index d86662f3..00000000 --- a/docs/guide/libbbfdm_DeviceInfo_Reboots.md +++ /dev/null @@ -1,74 +0,0 @@ -# Design for Reboot Data Model - -In TR-181 version 2.18, a new object, Device.DeviceInfo.Reboots, was introduced to track and monitor reboot operations. This object provides details such as reboot reasons, counts, timestamps, and more, offering a comprehensive view of the device's state. It simplifies diagnostics and troubleshooting for applications and processes running on the device. - -Currently, there is no standard configuration mapping to this object. However, we propose introducing a custom config called `deviceinfo` to manage this information effectively. - -The idea is to maintain a 1-to-1 mapping between the parameters and UCI config. To achieve this, we need to create an `init.d` service script that generates a UCI section each time the boot() function is called. Essentially, when the boot() function is executed, it will check the `/tmp/reset_reason` file for specific markers, such as (reset reason) and (reset triggered), to identify the cause of the last boot. And based on these markers, it will calculate the required counter for data model parameters and commit the changes in `deviceinfo.globals` section. Furthermore, if necessary, it will create a UCI reboot section by checking `deviceinfo.globals.max_reboot_entries` and adjusting the config accordingly. - -This approach ensures that the data model maps directly to UCI config as closely as possible, eliminating the need for any adjustments at the data model layer. - -## Parameter Mapping Details - -- Device.DeviceInfo.Reboots.BootCount: Maps to deviceinfo.globals.boot_count. This value is determined based on the marker (reset triggered: defaultreset) defined in `/tmp/reset_reason` file. -- Device.DeviceInfo.Reboots.CurrentVersionBootCount: Maps to deviceinfo.globals.curr_version_boot_count. This value is determined based on the marker (reset triggered: upgrade) defined in `/tmp/reset_reason` file. -- Device.DeviceInfo.Reboots.WatchdogBootCount: Maps to deviceinfo.globals.watchdog_boot_count. This value is determined based on the marker (reset reason: WATCHDOG) defined in `/tmp/reset_reason` file. -- Device.DeviceInfo.Reboots.ColdBootCount: -- Device.DeviceInfo.Reboots.WarmBootCount: -- Device.DeviceInfo.Reboots.MaxRebootEntries: Maps to deviceinfo.globals.max_reboot_entries. Possible values include {-1, 0, etc..}. Each case will be handled internally by bbfdm and default value is 3 and maximum reboot entry supported is 255. -- Device.DeviceInfo.Reboots.RebootNumberOfEntries: This is an internal bbfdm mechanism used to count the number of reboot entries. -- Device.DeviceInfo.Reboots.RemoveAllReboots(): An internal bbfdm API to remove all reboot sections. -- Device.DeviceInfo.Reboots.Reboot.{i}.: Each reboot entry is stored in a 'reboot' section. -- Device.DeviceInfo.Reboots.Reboot.{i}.Alias: Maps to deviceinfo.reboot[i].alias. This is managed internally by bbfdm. -- Device.DeviceInfo.Reboots.Reboot.{i}.TimeStamp: Maps to deviceinfo.reboot[i].time_stamp. This value is based on system uptime. -- Device.DeviceInfo.Reboots.Reboot.{i}.FirmwareUpdated: Maps to deviceinfo.reboot[i].firmware_updated. -- Device.DeviceInfo.Reboots.Reboot.{i}.Cause: Maps to deviceinfo.reboot[i].cause. Possible values include {LocalReboot, RemoteReboot, FactoryReset, LocalFactoryReset, RemoteFactoryReset}. -- Device.DeviceInfo.Reboots.Reboot.{i}.Reason: Maps to deviceinfo.reboot[i].reason. This value is determined based on the marker (reset reason) defined in `/tmp/reset_reason` file. -- Device.DeviceInfo.Reboots.Reboot.{i}.Remove(): An internal bbfdm API to remove the current 'reboot' section. - - -## Example Configuration - -Below is an example of the configuration file: - -```bash -cat /etc/config/deviceinfo - -config globals 'globals' - option boot_count '2' - option curr_version_boot_count '4' - option watchdog_boot_count '3' - option cold_boot_count '2' - option warm_boot_count '2' - option max_reboot_entries '3' - -config reboot 'reboot_1' - option alias 'cpe-1' - option time_stamp '2024-09-22T20:34:45Z' - option firmware_updated '0' - option cause 'RemoteReboot' - option reason 'REBOOT' - -config reboot 'reboot_2' - option alias 'cpe-2' - option time_stamp '2024-09-22T21:55:09Z' - option firmware_updated '0' - option cause 'LocalReboot' - option reason 'POR_RESET' - -config reboot 'reboot_3' - option alias 'cpe-3' - option time_stamp '2024-09-23T04:11:24Z' - option firmware_updated '1' - option cause 'LocalReboot' - option reason 'upgrade' - -config reboot 'reboot_4' - option alias 'cpe-4' - option time_stamp '2024-09-23T04:15:53Z' - option firmware_updated '0' - option cause 'RemoteFactoryReset' - option reason 'REBOOT' - -``` - diff --git a/gitlab-ci/bbfdmd-functional-test.sh b/gitlab-ci/bbfdmd-functional-test.sh index 1dfa9e61..5dff478f 100755 --- a/gitlab-ci/bbfdmd-functional-test.sh +++ b/gitlab-ci/bbfdmd-functional-test.sh @@ -24,6 +24,15 @@ echo "Checking system resources" free -h df -h +# Check if the specified log file exists, which indicates errors during plugin loading +if [ -f ${BBFDM_LOG_FILE} ]; then + echo "Some plugins failed to load! Please check the errors below" + echo "*****************************************************" + cat "${BBFDM_LOG_FILE}" + echo "*****************************************************" + exit 1 +fi + echo "## Running python based verification of functionalities ##" echo > ./funl-result.log num=0 diff --git a/gitlab-ci/install-dependencies.sh b/gitlab-ci/install-dependencies.sh index fa29642b..1cb9730e 100755 --- a/gitlab-ci/install-dependencies.sh +++ b/gitlab-ci/install-dependencies.sh @@ -1,6 +1,6 @@ #!/bin/bash -echo "install dependencies of bbf" +echo "install dependencies of bbfdm" source ./gitlab-ci/shared.sh @@ -12,6 +12,7 @@ exec_cmd pip3 install pexpect ubus xlwt ValgrindCI # Make sure that all plugins are removed [ ! -d "${BBFDM_PLUGIN_DIR}" ] && mkdir -p "${BBFDM_PLUGIN_DIR}" rm -f ${BBFDM_PLUGIN_DIR}/* +rm -f ${BBFDM_LOG_FILE} # compile and install libbbf install_libbbf ${1} diff --git a/gitlab-ci/shared.sh b/gitlab-ci/shared.sh index 17cddaaa..99e00f8a 100755 --- a/gitlab-ci/shared.sh +++ b/gitlab-ci/shared.sh @@ -2,6 +2,7 @@ BBFDM_PLUGIN_DIR="/usr/share/bbfdm/plugins" BBFDM_MS_DIR="/usr/share/bbfdm/micro_services" +BBFDM_LOG_FILE="/tmp/bbfdm.log" if [ -z "${CI_PROJECT_PATH}" ]; then CI_PROJECT_PATH=${PWD} @@ -64,7 +65,7 @@ function install_libbbf() mkdir -p build cd build - cmake ../ -DCMAKE_C_FLAGS="$COV_CFLAGS " -DCMAKE_EXE_LINKER_FLAGS="$COV_LDFLAGS -lm" -DBBF_VENDOR_PREFIX="$VENDOR_PREFIX" -DBBF_MAX_OBJECT_INSTANCES=255 -DBBFDMD_MAX_MSG_LEN=1048576 -DCMAKE_INSTALL_PREFIX=/ + cmake ../ -DCMAKE_C_FLAGS="$COV_CFLAGS " -DCMAKE_EXE_LINKER_FLAGS="$COV_LDFLAGS -lm" -DBBF_VENDOR_PREFIX="$VENDOR_PREFIX" -DBBF_MAX_OBJECT_INSTANCES=255 -DBBF_SCHEMA_FULL_TREE=ON -DBBFDMD_MAX_MSG_LEN=1048576 -DCMAKE_INSTALL_PREFIX=/ exec_cmd_verbose make echo "installing libbbf" diff --git a/libbbfdm-api/dmapi.h b/libbbfdm-api/dmapi.h index 1ea4358d..055b74d1 100644 --- a/libbbfdm-api/dmapi.h +++ b/libbbfdm-api/dmapi.h @@ -153,7 +153,7 @@ struct dm_parameter { }; typedef struct dm_map_obj { - char *path; + const char *path; struct dm_obj_s *root_obj; struct dm_leaf_s *root_leaf; int (*init_module)(void *data); diff --git a/libbbfdm-api/dmbbf.h b/libbbfdm-api/dmbbf.h index b5a53b7c..ff4639ec 100644 --- a/libbbfdm-api/dmbbf.h +++ b/libbbfdm-api/dmbbf.h @@ -69,6 +69,17 @@ static inline int DM_LINK_INST_OBJ(struct dmctx *dmctx, DMNODE *parent_node, voi } while(0) #endif + +#ifndef TRACE_FILE +#define TRACE_FILE(MESSAGE, ...) do { \ + FILE *log_file = fopen("/tmp/bbfdm.log", "a"); \ + if (log_file) { \ + fprintf(log_file, "[%s:%d] " MESSAGE "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + fclose(log_file); \ + } \ +} while(0) +#endif + // Macros for different log levels #define BBF_ERR(MESSAGE, ...) do { \ syslog(LOG_ERR, "[%s:%d] " MESSAGE, __FUNCTION__, __LINE__, ##__VA_ARGS__); /* Flawfinder: ignore */ \ diff --git a/libbbfdm-api/dmcommon.c b/libbbfdm-api/dmcommon.c index d79271f3..36c0133c 100644 --- a/libbbfdm-api/dmcommon.c +++ b/libbbfdm-api/dmcommon.c @@ -15,7 +15,6 @@ #include "dmcommon.h" - char *DiagnosticsState[] = {"None", "Requested", "Canceled", "Complete", "Error", NULL}; char *IPv4Address[] = {"^$", "^((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])$", NULL}; @@ -1704,6 +1703,23 @@ bool is_regular_file(const char *path) return stat(path, &buffer) == 0 && S_ISREG(buffer.st_mode); } +int create_empty_file(const char *file_name) +{ + if (!file_name) + return -1; + + // Skip creating the file if it already exists + if (file_exists(file_name)) + return 0; + + FILE *fp = fopen(file_name, "w"); + if (fp == NULL) + return -1; + + fclose(fp); + return 0; +} + unsigned long file_system_size(const char *path, const enum fs_size_type_enum type) { struct statvfs vfs; diff --git a/libbbfdm-api/dmcommon.h b/libbbfdm-api/dmcommon.h index c7ab6b19..93cf204e 100644 --- a/libbbfdm-api/dmcommon.h +++ b/libbbfdm-api/dmcommon.h @@ -217,6 +217,7 @@ void string_to_mac(const char *str, size_t str_len, char *out, size_t out_len); bool folder_exists(const char *path); bool file_exists(const char *path); bool is_regular_file(const char *path); +int create_empty_file(const char *file_name); unsigned long file_system_size(const char *path, const enum fs_size_type_enum type); void remove_char(char *str, const char c); char *replace_char(char *str, char find, char replace); diff --git a/libbbfdm-api/dmuci.c b/libbbfdm-api/dmuci.c index 56a1aae0..9a8da8ae 100644 --- a/libbbfdm-api/dmuci.c +++ b/libbbfdm-api/dmuci.c @@ -502,13 +502,9 @@ int dmuci_add_section(const char *package, const char *stype, struct uci_section *s = NULL; snprintf(fname, sizeof(fname), "%s/%s", uci_ctx->confdir, package); - if (!file_exists(fname)) { - FILE *fptr = fopen(fname, "w"); - if (fptr) - fclose(fptr); - else - return -1; - } + + if (create_empty_file(fname)) + return -1; if (dmuci_lookup_ptr(uci_ctx, &ptr, package, NULL, NULL, NULL)) return -1; diff --git a/libbbfdm-api/plugin/dotso_plugin.c b/libbbfdm-api/plugin/dotso_plugin.c index 686c95a9..9620975b 100644 --- a/libbbfdm-api/plugin/dotso_plugin.c +++ b/libbbfdm-api/plugin/dotso_plugin.c @@ -68,7 +68,11 @@ int load_dotso_plugins(DMOBJ *entryobj, const char *plugin_path) void *handle = dlopen(plugin_path, RTLD_LAZY); #endif if (!handle) { - BBF_ERR("Failed to add DotSo plugin '%s', [%s]\n", plugin_path, dlerror()); + char *err_msg = dlerror(); +#ifdef BBF_SCHEMA_FULL_TREE + TRACE_FILE("Failed to add DotSo plugin '%s', [%s]\n", plugin_path, err_msg); +#endif + BBF_ERR("Failed to add DotSo plugin '%s', [%s]\n", plugin_path, err_msg); return 0; } @@ -86,7 +90,10 @@ int load_dotso_plugins(DMOBJ *entryobj, const char *plugin_path) DMOBJ *dm_entryobj = find_entry_obj(entryobj, dynamic_obj[i].path); if (!dm_entryobj) { - BBF_ERR("Failed to add DotSo plugin '%s' to main tree with parent DM '%s'.", plugin_path, dynamic_obj[i].path); +#ifdef BBF_SCHEMA_FULL_TREE + TRACE_FILE("Failed to add DotSo plugin '%s' to main tree with parent DM index '%d' => '%s'", plugin_path, i, dynamic_obj[i].path); +#endif + BBF_ERR("Failed to add DotSo plugin '%s' to main tree with parent DM index '%d' => '%s'", plugin_path, i, dynamic_obj[i].path); continue; } diff --git a/libbbfdm/CMakeLists.txt b/libbbfdm/CMakeLists.txt index c7d5f32b..fcd27b53 100644 --- a/libbbfdm/CMakeLists.txt +++ b/libbbfdm/CMakeLists.txt @@ -2,8 +2,6 @@ cmake_minimum_required(VERSION 3.0) PROJECT(libbbfdm) -OPTION(BBF_VENDOR_EXTENSION "build with vendor extension" ON) - ADD_DEFINITIONS(-Wall -Werror -g -D_GNU_SOURCE -DBBF_VENDOR_PREFIX="${BBF_VENDOR_PREFIX}") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SOURCE_DIR} -I${CMAKE_CURRENT_SOURCE_DIR}") @@ -25,8 +23,3 @@ INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/plugins) INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/micro_services) INSTALL(DIRECTORY DESTINATION usr/libexec/rpcd) -IF(BBF_VENDOR_EXTENSION) - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/vendor.json - DESTINATION usr/share/bbfdm/plugins - ) -ENDIF(BBF_VENDOR_EXTENSION) diff --git a/libbbfdm/device.c b/libbbfdm/device.c index cea21fe2..1ca33cc9 100644 --- a/libbbfdm/device.c +++ b/libbbfdm/device.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 iopsys Software Solutions AB + * Copyright (C) 2019-2024 iopsys Software Solutions AB * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 @@ -7,23 +7,39 @@ * * Author: Imen Bhiri * Author: Anis Ellouze - * Author: Amin Ben Ramdhane + * Author: Amin Ben Romdhane */ #include "device.h" -#include "deviceinfo.h" #include "lanconfigsecurity.h" #include "security.h" #include "gatewayinfo.h" #include "schedules.h" /************************************************************* -* GET & SET PARAM +* COMMON FUNCTIONS **************************************************************/ -static int get_Device_RootDataModelVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +static void _exec_reboot(const void *arg1, void *arg2) { - *value = dmstrdup("2.18"); - return 0; + char config_name[16] = {0}; + + snprintf(config_name, sizeof(config_name), "%s", "sysmngr"); + + // Set last_reboot_cause to 'RemoteReboot' because the upcoming reboot will be initiated by USP Operate + dmuci_set_value(config_name, "reboots", "last_reboot_cause", "RemoteReboot"); + dmuci_commit_package(config_name); + + sleep(3); + dmubus_call_set("rpc-sys", "reboot", UBUS_ARGS{0}, 0); + sleep(5); // Wait for reboot to happen + BBF_ERR("Reboot call failed with rpc-sys, trying again with system"); + dmubus_call_set("system", "reboot", UBUS_ARGS{0}, 0); + sleep(5); // Wait for reboot + BBF_ERR("Reboot call failed!!!"); + + // Set last_reboot_cause to empty because there is a problem in the system reboot + dmuci_set_value(config_name, "reboots", "last_reboot_cause", ""); + dmuci_commit_package(config_name); } static void _exec_factoryreset(const void *arg1, void *arg2) @@ -37,6 +53,15 @@ static void _exec_factoryreset(const void *arg1, void *arg2) BBF_ERR("FactoryReset call failed!!!"); } +/************************************************************* +* GET & SET PARAM +**************************************************************/ +static int get_Device_RootDataModelVersion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + *value = dmstrdup("2.18"); + return 0; +} + /************************************************************* * OPERATE COMMANDS *************************************************************/ @@ -67,7 +92,6 @@ DM_MAP_OBJ tDynamicObj[] = { /* *** Device. *** */ DMOBJ tDMRootObj[] = { /* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/ -{"DeviceInfo", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoObj, tDeviceInfoParams, NULL, BBFDM_BOTH, NULL}, {"LANConfigSecurity", &DMREAD, NULL, NULL, "file:/etc/config/users", NULL, NULL, NULL, NULL, tLANConfigSecurityParams, NULL, BBFDM_BOTH, NULL}, {"Schedules", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tSchedulesObj, tSchedulesParams, NULL, BBFDM_BOTH, NULL}, {"Security", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tSecurityObj, tSecurityParams, NULL, BBFDM_BOTH, NULL}, diff --git a/libbbfdm/deviceinfo.c b/libbbfdm/deviceinfo.c deleted file mode 100644 index c5bb7832..00000000 --- a/libbbfdm/deviceinfo.c +++ /dev/null @@ -1,2066 +0,0 @@ -/* - * Copyright (C) 2019 iopsys Software Solutions AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * Author: Imen Bhiri - * Author: Feten Besbes - * Author: Amin Ben Ramdhane - */ - -#include "sys/statvfs.h" -#include -#include -#include - -#include "deviceinfo.h" - -extern struct list_head global_memhead; - -LIST_HEAD(process_list); -static int process_count = 0; - -#define PROCPS_BUFSIZE 1024 -#define CONFIG_BACKUP "/tmp/bbf_config_backup" -#define MAX_TIME_WINDOW 5 - -struct process_entry { - struct list_head list; - - char command[256]; - char state[16]; - char pid[8]; - char size[8]; - char priority[8]; - char cputime[8]; -}; - -typedef struct jiffy_counts_t { - unsigned long long usr, nic, sys, idle; - unsigned long long iowait, irq, softirq, steal; - unsigned long long total; - unsigned long long busy; -} jiffy_counts_t; - -struct Supported_Data_Models -{ - char url[128]; - char urn[128]; - char features[128]; -}; - -struct Supported_Data_Models Data_Models[] = { -{"http://www.broadband-forum.org/cwmp/tr-181-2-14-1.xml","urn:broadband-forum-org:tr-181-2-14-1","IP,Wireless,Firewall,NAT,DHCP,QoS,DNS,GRE,UPnP"}, -{"http://www.broadband-forum.org/cwmp/tr-104-2-0-2.xml","urn:broadband-forum-org:tr-104-2-0-2", "VoiceService"}, -{"http://www.broadband-forum.org/cwmp/tr-143-1-1-0.xml","urn:broadband-forum-org:tr-143-1-1-0", "Ping,TraceRoute,Download,Upload,UDPecho,ServerSelectionDiag"}, -{"http://www.broadband-forum.org/cwmp/tr-157-1-3-0.xml","urn:broadband-forum-org:tr-157-1-3-0", "Bulkdata,SoftwareModules"}, -}; - -/************************************************************* -* COMMON FUNCTIONS -**************************************************************/ -static void get_jif_val(jiffy_counts_t *p_jif) -{ - FILE *file = NULL; - char line[128]; - int ret; - - if ((file = fopen("/proc/stat", "r"))) { - while(fgets(line, sizeof(line), file) != NULL) - { - remove_new_line(line); - ret = sscanf(line, "cpu %llu %llu %llu %llu %llu %llu %llu %llu", &p_jif->usr, &p_jif->nic, &p_jif->sys, &p_jif->idle, - &p_jif->iowait, &p_jif->irq, &p_jif->softirq, &p_jif->steal); - - if (ret >= 4) { - p_jif->total = p_jif->usr + p_jif->nic + p_jif->sys + p_jif->idle - + p_jif->iowait + p_jif->irq + p_jif->softirq + p_jif->steal; - - p_jif->busy = p_jif->total - p_jif->idle - p_jif->iowait; - break; - } - } - fclose(file); - } -} - -static unsigned int get_cpu_load(jiffy_counts_t *prev_jif, jiffy_counts_t *cur_jif) -{ - unsigned total_diff, cpu; - - total_diff = (unsigned)(cur_jif->total - prev_jif->total); - - if (total_diff == 0) - total_diff = 1; - - cpu = 100 * (unsigned)(cur_jif->busy - prev_jif->busy) / total_diff; - - return cpu; -} - -static unsigned int get_cpu_usage(void) -{ - jiffy_counts_t prev_jif = {0}; - jiffy_counts_t cur_jif = {0}; - - get_jif_val(&prev_jif); - usleep(100000); - get_jif_val(&cur_jif); - - return get_cpu_load(&prev_jif, &cur_jif); -} - -static bool is_update_process_allowed(void) -{ - char *tr069_status = NULL; - - if (dmubus_object_method_exists("tr069")) { - struct uci_section *s = NULL, *stmp = NULL; - uci_path_foreach_sections_safe(varstate, "icwmp", "sess_status", stmp, s) { - dmuci_get_value_by_section_string(s, "current_status", &tr069_status); - } - } - - if (tr069_status == NULL) - goto end; - - if (strcmp(tr069_status, "running") == 0) { - return false; - } - -end: - return true; -} - -static char *get_proc_state(char state) -{ - switch(state) { - case 'R': - return "Running"; - case 'S': - return "Sleeping"; - case 'T': - return "Stopped"; - case 'D': - return "Uninterruptible"; - case 'Z': - return "Zombie"; - case 'I': - return "Idle"; - }; - - return "Idle"; -} - -static struct process_entry *check_entry_exists(const char *pid) -{ - struct process_entry *entry = NULL; - - list_for_each_entry(entry, &process_list, list) { - if (DM_STRCMP(entry->pid, pid) == 0) - return entry; - } - - return NULL; -} - -static void check_killed_process(void) -{ - struct process_entry *entry = NULL; - struct process_entry *entry_tmp = NULL; - char fstat[32]; - - list_for_each_entry_safe(entry, entry_tmp, &process_list, list) { - - snprintf(fstat, sizeof(fstat), "/proc/%s/stat", entry->pid); - if (file_exists(fstat)) - continue; - - list_del(&entry->list); - dmfree(entry); - } -} - -static void procps_get_cmdline(char *buf, int bufsz, const char *pid, const char *comm) -{ - int sz; - char filename[270]; - - snprintf(filename, sizeof(filename), "/proc/%s/cmdline", pid); - sz = dm_file_to_buf(filename, buf, bufsz); - if (sz > 0) { - const char *base; - int comm_len; - - while (--sz >= 0 && buf[sz] == '\0') - continue; - /* Prevent basename("process foo/bar") = "bar" */ - strchrnul(buf, ' ')[0] = '\0'; - base = basename(buf); /* before we replace argv0's NUL with space */ - while (sz >= 0) { - if ((unsigned char)(buf[sz]) < ' ') - buf[sz] = ' '; - sz--; - } - if (base[0] == '-') /* "-sh" (login shell)? */ - base++; - - /* If comm differs from argv0, prepend "{comm} ". - * It allows to see thread names set by prctl(PR_SET_NAME). - */ - if (!comm) - return; - comm_len = strlen(comm); - /* Why compare up to comm_len? - * Well, some processes rewrite argv, and use _spaces_ there - * while rewriting. (KDE is observed to do it). - * I prefer to still treat argv0 "process foo bar" - * as 'equal' to comm "process". - */ - if (strncmp(base, comm, comm_len) != 0) { - comm_len += 3; - if (bufsz > comm_len) - memmove(buf + comm_len, buf, bufsz - comm_len); - snprintf(buf, bufsz, "{%s}", comm); - if (bufsz <= comm_len) - return; - buf[comm_len - 1] = ' '; - buf[bufsz - 1] = '\0'; - } - } else { - snprintf(buf, bufsz, "[%s]", comm ? comm : "?"); - } -} - -static void init_processes(void) -{ - DIR *dir = NULL; - struct dirent *entry = NULL; - struct stat stats = {0}; - char buf[PROCPS_BUFSIZE]; - char fstat[288]; - char command[256]; - char comm[32]; - char bsize[32]; - char cputime[32]; - char priori[32]; - char *comm1 = NULL; - char *comm2 = NULL; - char state; - unsigned long stime; - unsigned long utime; - unsigned long vsize; - int priority, n; - int curr_process_idx = 0; - - if (!is_update_process_allowed()) - return; - - check_killed_process(); - - dir = opendir("/proc"); - if (dir == NULL) - return; - - while ((entry = readdir(dir)) != NULL) { - struct process_entry *pentry = NULL; - struct process_entry *pentry_exits = NULL; - - int digit = entry->d_name[0] - '0'; - if (digit < 0 || digit > 9) - continue; - - snprintf(fstat, sizeof(fstat), "/proc/%s/stat", entry->d_name); - if (stat(fstat, &stats)) - continue; - - n = dm_file_to_buf(fstat, buf, PROCPS_BUFSIZE); - if (n < 0) - continue; - - comm2 = strrchr(buf, ')'); /* split into "PID (cmd" and "" */ - if (!comm2) /* sanity check */ - continue; - - comm2[0] = '\0'; - comm1 = strchr(buf, '('); - if (!comm1) /* sanity check */ - continue; - - DM_STRNCPY(comm, comm1 + 1, sizeof(comm)); - - n = sscanf(comm2 + 2, /* Flawfinder: ignore */ \ - "%c %*u " /* state, ppid */ - "%*u %*u %*d %*s " /* pgid, sid, tty, tpgid */ - "%*s %*s %*s %*s %*s " /* flags, min_flt, cmin_flt, maj_flt, cmaj_flt */ - "%lu %lu " /* utime, stime */ - "%*u %*u %d " /* cutime, cstime, priority */ - "%*d " /* niceness */ - "%*s %*s " /* timeout, it_real_value */ - "%*s " /* start_time */ - "%lu " /* vsize */ - , - &state, - &utime, &stime, - &priority, - &vsize - ); - - if (n != 5) - continue; - - procps_get_cmdline(command, sizeof(command), entry->d_name, comm); - curr_process_idx++; - - snprintf(cputime, sizeof(cputime), "%lu", ((stime / sysconf(_SC_CLK_TCK)) + (utime / sysconf(_SC_CLK_TCK))) * 1000); - snprintf(bsize, sizeof(bsize), "%lu", vsize >> 10); - snprintf(priori, sizeof(priori), "%u", (unsigned)round((priority + 100) * 99 / 139)); - - if (process_count == 0 || !(pentry_exits = check_entry_exists(entry->d_name))) { - - pentry = dm_dynamic_calloc(&global_memhead, 1, sizeof(struct process_entry)); - if (!pentry) - return; - - list_add_tail(&pentry->list, &process_list); - } - - if (pentry_exits) - pentry = pentry_exits; - - DM_STRNCPY(pentry->pid, entry->d_name, sizeof(pentry->pid)); - DM_STRNCPY(pentry->command, command, sizeof(pentry->command)); - DM_STRNCPY(pentry->size, bsize, sizeof(pentry->size)); - DM_STRNCPY(pentry->priority, priori, sizeof(pentry->priority)); - DM_STRNCPY(pentry->cputime, cputime, sizeof(pentry->cputime)); - DM_STRNCPY(pentry->state, get_proc_state(state), sizeof(pentry->state)); - } - - closedir(dir); - process_count = curr_process_idx; -} - -static bool check_file_dir(char *name) -{ - DIR *dir = NULL; - struct dirent *d_file = NULL; - - if ((dir = opendir (DEFAULT_CONFIG_DIR)) != NULL) { - while ((d_file = readdir (dir)) != NULL) { - if (DM_STRCMP(name, d_file->d_name) == 0) { - closedir(dir); - return true; - } - } - closedir(dir); - } - return false; -} - -static bool get_response_code_status(const char *url, int response_code) -{ - 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; - } - - return true; -} - -static void send_transfer_complete_event(const char *command, const char *obj_path, const char *transfer_url, - char *fault_string, time_t start_t, time_t complete_t,const char *commandKey, const char *transfer_type) -{ - char start_time[32] = {0}; - char complete_time[32] = {0}; - struct blob_buf bb; - - strftime(start_time, sizeof(start_time), "%Y-%m-%dT%H:%M:%SZ", gmtime(&start_t)); - strftime(complete_time, sizeof(complete_time), "%Y-%m-%dT%H:%M:%SZ", gmtime(&complete_t)); - - memset(&bb, 0, sizeof(struct blob_buf)); - blob_buf_init(&bb, 0); - - blobmsg_add_string(&bb, "name", "Device.LocalAgent.TransferComplete!"); - void *arr = blobmsg_open_array(&bb, "input"); - - fill_blob_param(&bb, "Command", command, DMT_TYPE[DMT_STRING], 0); - if(commandKey) - fill_blob_param(&bb, "CommandKey", commandKey, DMT_TYPE[DMT_STRING], 0); - else - fill_blob_param(&bb, "CommandKey", "", DMT_TYPE[DMT_STRING], 0); - - fill_blob_param(&bb, "Requestor", "", DMT_TYPE[DMT_STRING], 0); - fill_blob_param(&bb, "TransferType", transfer_type, DMT_TYPE[DMT_STRING], 0); - fill_blob_param(&bb, "Affected", obj_path, DMT_TYPE[DMT_STRING], 0); - fill_blob_param(&bb, "TransferURL", transfer_url, DMT_TYPE[DMT_STRING], 0); - fill_blob_param(&bb, "StartTime", start_time, DMT_TYPE[DMT_STRING], 0); - fill_blob_param(&bb, "CompleteTime", complete_time, DMT_TYPE[DMT_STRING], 0); - - if (DM_STRLEN(fault_string) == 0) { - fill_blob_param(&bb, "FaultCode", "0", DMT_TYPE[DMT_STRING], 0); - } else { - fill_blob_param(&bb, "FaultCode", "7000", DMT_TYPE[DMT_STRING], 0); - } - - fill_blob_param(&bb, "FaultString", fault_string, DMT_TYPE[DMT_STRING], 0); - blobmsg_close_array(&bb, arr); - - dmubus_call_blob_msg_set("bbfdm", "notify_event", &bb); - - blob_buf_free(&bb); -} - -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_hash_value(const char *algo, const char *file_path, const char *checksum) -{ - unsigned char buffer[1024 * 16] = {0}; - char hash[BUFSIZ] = {0}; - bool res = false; - unsigned int bytes = 0; - FILE *file; - - EVP_MD_CTX *mdctx; - const EVP_MD *md; - unsigned char md_value[EVP_MAX_MD_SIZE]; - - file = fopen(file_path, "rb"); - if (!file) - return false; - - md = EVP_get_digestbyname(algo); - mdctx = EVP_MD_CTX_create(); - EVP_DigestInit_ex(mdctx, md, NULL); - - if (md == NULL) - goto end; - - while ((bytes = fread (buffer, 1, sizeof(buffer), file))) { - EVP_DigestUpdate(mdctx, buffer, bytes); - } - - bytes = 0; - EVP_DigestFinal_ex(mdctx, md_value, &bytes); - - for (int i = 0; i < bytes; i++) - snprintf(&hash[i * 2], sizeof(hash) - (i * 2), "%02x", md_value[i]); - - if (DM_STRCMP(hash, checksum) == 0) - res = true; - -end: - EVP_MD_CTX_destroy(mdctx); - EVP_cleanup(); - - 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_hash_value("SHA1", file_path, checksum); - else if (strcmp(checksum_algorithm, "SHA-224") == 0) - return validate_hash_value("SHA224", file_path, checksum); - else if (strcmp(checksum_algorithm, "SHA-256") == 0) - return validate_hash_value("SHA256", file_path, checksum); - else if (strcmp(checksum_algorithm, "SHA-384") == 0) - return validate_hash_value("SHA384", file_path, checksum); - else if (strcmp(checksum_algorithm, "SHA-512") == 0) - return validate_hash_value("SHA512", 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; - char fault_msg[128] = {0}; - time_t complete_time = 0; - time_t start_time = time(NULL); - - // Export config file to backup file - if (dmuci_export_package(config_name, CONFIG_BACKUP)) { - snprintf(fault_msg, sizeof(fault_msg), "Failed to export the configurations"); - res = -1; - goto end; - } - - // Upload the config file - long res_code = upload_file(CONFIG_BACKUP, url, username, password); - complete_time = time(NULL); - - // Check if the upload operation was successful - if (!get_response_code_status(url, res_code)) { - res = -1; - snprintf(fault_msg, sizeof(fault_msg), "Upload operation is failed, fault code (%ld)", res_code); - } - -end: - // Send the transfer complete event - send_transfer_complete_event(command, obj_path, url, fault_msg, start_time, complete_time, NULL, "Upload"); - - // Remove temporary file - 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 *file_size, const char *checksum_algorithm, const char *checksum, - const char *command, const char *obj_path) -{ - char config_restore[256] = {0}; - int res = 0; - char fault_msg[128] = {0}; - time_t complete_time = 0; - time_t start_time = time(NULL); - - DM_STRNCPY(config_restore, "/tmp/bbf_config_restore", sizeof(config_restore)); - - // Check the file system size if there is sufficient space for downloading the config file - if (!validate_file_system_size(file_size)) { - snprintf(fault_msg, sizeof(fault_msg), "Available memory space is less than required for the operation"); - res = -1; - goto end; - } - - // Download the firmware image - long res_code = download_file(config_restore, url, username, password); - complete_time = time(NULL); - - // Check if the download operation was successful - if (!get_response_code_status(url, res_code)) { - snprintf(fault_msg, sizeof(fault_msg), "Upload operation is failed, fault code (%ld)", res_code); - res = -1; - goto end; - } - - // Validate the CheckSum value according to its algorithm - if (!validate_checksum_value(config_restore, checksum_algorithm, checksum)) { - snprintf(fault_msg, sizeof(fault_msg), "Checksum of the downloaded file is mismatched"); - res = -1; - goto end; - } - - // Apply config file - if (dmuci_import(NULL, config_restore)) { - snprintf(fault_msg, sizeof(fault_msg), "Failed to import the configurations"); - res = -1; - } - -end: - // Send the transfer complete event - send_transfer_complete_event(command, obj_path, url, fault_msg, start_time, complete_time, NULL, "Download"); - - // Remove temporary file - if (file_exists(config_restore) && strncmp(url, FILE_URI, strlen(FILE_URI)) && remove(config_restore)) - res = -1; - - return res; -} - -struct sysupgrade_ev_data { - const char *bank_id; - bool status; -}; - -static void dmubus_receive_sysupgrade(struct ubus_context *ctx, struct ubus_event_handler *ev, - const char *type, struct blob_attr *msg) -{ - struct dmubus_event_data *data; - struct blob_attr *msg_attr; - - if (!msg || !ev) - return; - - data = container_of(ev, struct dmubus_event_data, ev); - if (data == NULL) - return; - - struct sysupgrade_ev_data *ev_data = (struct sysupgrade_ev_data *)data->ev_data; - if (ev_data == NULL) - return; - - size_t msg_len = (size_t)blobmsg_data_len(msg); - __blob_for_each_attr(msg_attr, blobmsg_data(msg), msg_len) { - if (DM_STRCMP("bank_id", blobmsg_name(msg_attr)) == 0) { - char *attr_val = (char *)blobmsg_data(msg_attr); - if (DM_STRCMP(attr_val, ev_data->bank_id) != 0) - return; - } - - if (DM_STRCMP("status", blobmsg_name(msg_attr)) == 0) { - char *attr_val = (char *)blobmsg_data(msg_attr); - if (DM_STRCMP(attr_val, "Downloading") == 0) - return; - else if (DM_STRCMP(attr_val, "Available") == 0) - ev_data->status = true; - else - ev_data->status = false; - - } - } - - uloop_end(); - return; -} - -static 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, const char *commandKey, char *keep) -{ - char fw_image_path[256] = {0}; - json_object *json_obj = NULL; - bool activate = false, valid = false; - int res = 0; - char fault_msg[128] = {0}; - time_t complete_time = 0; - time_t start_time = time(NULL); - - DM_STRNCPY(fw_image_path, "/tmp/firmware-XXXXXX", sizeof(fw_image_path)); - - // Check the file system size if there is sufficient space for downloading the firmware image - if (!validate_file_system_size(file_size)) { - res = -1; - snprintf(fault_msg, sizeof(fault_msg), "Available memory space is lower than required for downloading"); - goto end; - } - - res = mkstemp(fw_image_path); - if (res == -1) { - snprintf(fault_msg, sizeof(fault_msg), "Operation failed due to some internal failure"); - goto end; - } else { - close(res); // close the fd, as only filename required - res = 0; - } - - // Download the firmware image - long res_code = download_file(fw_image_path, url, username, password); - complete_time = time(NULL); - - // Check if the download operation was successful - if (!get_response_code_status(url, res_code)) { - snprintf(fault_msg, sizeof(fault_msg), "Download operation is failed, fault code (%ld)", 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; - snprintf(fault_msg, sizeof(fault_msg), "Checksum of the file is not matched with the specified value"); - goto end; - } - - string_to_bool(auto_activate, &activate); - char *act = (activate) ? "1" : "0"; - - dmubus_call_blocking("system", "validate_firmware_image", UBUS_ARGS{{"path", fw_image_path, String}}, 1, &json_obj); - if (json_obj == NULL) { - res = -1; - snprintf(fault_msg, sizeof(fault_msg), "Failed in validation of the file"); - goto end; - } - - char *val = dmjson_get_value(json_obj, 1, "valid"); - string_to_bool(val, &valid); - json_object_put(json_obj); - json_obj = NULL; - if (valid == false) { - snprintf(fault_msg, sizeof(fault_msg), "File is not a valid firmware image"); - res = -1; - goto end; - } - - // default state is to preserve the config over firmware upgrades - char *keep_config = DM_STRLEN((char *)keep) ? keep : "1"; - - // Apply Firmware Image - dmubus_call_blocking("fwbank", "upgrade", UBUS_ARGS{{"path", fw_image_path, String}, {"auto_activate", act, Boolean}, {"bank", bank_id, Integer}, {"keep_settings", keep_config, Boolean}}, 4, &json_obj); - if (json_obj == NULL) { - res = 1; - snprintf(fault_msg, sizeof(fault_msg), "Internal error occurred when applying the firmware"); - goto end; - } - - struct sysupgrade_ev_data ev_data = { - .bank_id = bank_id, - .status = false, - }; - - dmubus_wait_for_event("sysupgrade", 120, &ev_data, dmubus_receive_sysupgrade, NULL); - - if (ev_data.status == false) { - res = 1; - snprintf(fault_msg, sizeof(fault_msg), "Failed to apply the downloaded image file"); - goto end; - } - - // Schedule a device Reboot, if auto activation is true - if (activate) { - bbfdm_task_fork(_exec_reboot, NULL, NULL, NULL); - } - -end: - // Send the transfer complete event - send_transfer_complete_event(command, obj_path, url, fault_msg, start_time, complete_time, commandKey, "Download"); - - // Remove temporary file if ubus upgrade failed and file exists - if (!json_obj && file_exists(fw_image_path) && strncmp(url, FILE_URI, strlen(FILE_URI))) { - remove(fw_image_path); - res = -1; - } - - if (json_obj != NULL) - json_object_put(json_obj); - - return res; -} - -static int dmmap_synchronizeVcfInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) -{ - struct uci_section *s = NULL, *stmp = NULL; - DIR *dir; - struct dirent *d_file; - - sysfs_foreach_file(DEFAULT_CONFIG_DIR, dir, d_file) { - - if(d_file->d_name[0] == '.') - continue; - - if (!is_dmmap_section_exist_eq("dmmap", "vcf", "name", d_file->d_name)) { - dmuci_add_section_bbfdm("dmmap", "vcf", &s); - dmuci_set_value_by_section(s, "name", d_file->d_name); - dmuci_set_value_by_section(s, "backup_restore", "1"); - } - } - - if (dir) - closedir (dir); - - uci_path_foreach_sections_safe(bbfdm, "dmmap", "vcf", stmp, s) { - char *name; - - dmuci_get_value_by_section_string(s, "name", &name); - if (check_file_dir(name) == 0) - dmuci_delete_by_section_bbfdm(s, NULL, NULL); - } - - return 0; -} - -/************************************************************* -* ENTRY METHOD -**************************************************************/ -static int browseVcfInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) -{ - struct dm_data curr_data = {0}; - struct uci_section *s = NULL; - char *inst = NULL; - - dmmap_synchronizeVcfInst(dmctx, parent_node, prev_data, prev_instance); - uci_path_foreach_sections(bbfdm, "dmmap", "vcf", s) { - - curr_data.config_section = s; - - inst = handle_instance(dmctx, parent_node, s, "vcf_instance", "vcf_alias"); - - if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_data, inst) == DM_STOP) - break; - } - return 0; -} - -static int browseDeviceInfoSupportedDataModelInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) -{ - char *inst = NULL; - int i; - - for (i = 0; i < ARRAY_SIZE(Data_Models); i++) { - inst = handle_instance_without_section(dmctx, parent_node, i+1); - if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&Data_Models[i], inst) == DM_STOP) - break; - } - return 0; -} - -static int browseDeviceInfoFirmwareImageInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) -{ - json_object *res = NULL, *bank_obj = NULL, *arrobj = NULL; - struct dm_data curr_data = {0}; - char *inst = NULL; - int id = 0, i = 0; - - dmubus_call("fwbank", "dump", UBUS_ARGS{0}, 0, &res); - - dmjson_foreach_obj_in_array(res, arrobj, bank_obj, i, 1, "bank") { - - curr_data.json_object = bank_obj; - - inst = handle_instance_without_section(dmctx, parent_node, ++id); - - if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_data, inst) == DM_STOP) - break; - } - return 0; -} - -static int browseProcessEntriesInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) -{ - struct process_entry *entry = NULL; - struct dm_data curr_data = {0}; - char *inst = NULL; - int id = 0; - - init_processes(); - list_for_each_entry(entry, &process_list, list) { - - curr_data.additional_data = entry; - - inst = handle_instance_without_section(dmctx, parent_node, ++id); - - if (DM_LINK_INST_OBJ(dmctx, parent_node, &curr_data, inst) == DM_STOP) - break; - } - return 0; -} - -static int browseDeviceInfoRebootsRebootInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) -{ - struct dm_data *p = NULL; - char *inst = NULL; - LIST_HEAD(dup_list); - - synchronize_specific_config_sections_with_dmmap("deviceinfo", "reboot", "dmmap_deviceinfo", &dup_list); - list_for_each_entry(p, &dup_list, list) { - - inst = handle_instance(dmctx, parent_node, p->dmmap_section, "reboot_instance", "reboot_alias"); - - if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p, inst) == DM_STOP) - break; - } - free_dmmap_config_dup_list(&dup_list); - return 0; -} - -/************************************************************* -* GET & SET PARAM -**************************************************************/ -/*#Device.DeviceInfo.Manufacturer!UCI:cwmp/cpe,cpe/manufacturer*/ -static int get_device_manufacturer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("cwmp","cpe","manufacturer", value); - if (*value[0] == '\0') - db_get_value_string("device", "deviceinfo", "Manufacturer", value); - - return 0; -} - -/*#Device.DeviceInfo.ManufacturerOUI!UCI:cwmp/cpe,cpe/manufacturer_oui*/ -static int get_device_manufactureroui(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("cwmp", "cpe", "manufacturer_oui", value); - if (*value[0] == '\0') - db_get_value_string("device", "deviceinfo", "ManufacturerOUI", value); - - return 0; -} - -/*#Device.DeviceInfo.ProductClass!UCI:cwmp/cpe,cpe/product_class*/ -static int get_device_productclass(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("cwmp", "cpe", "product_class", value); - if (*value[0] == '\0') - db_get_value_string("device", "deviceinfo", "ProductClass", value); - - return 0; -} - -static int get_device_serialnumber(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("cwmp", "cpe", "serial_number", value); - if (*value[0] == '\0') - db_get_value_string("device", "deviceinfo", "SerialNumber", value); - - return 0; -} - -static int get_device_softwareversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("cwmp", "cpe", "software_version", value); - if (*value[0] == '\0') - db_get_value_string("device", "deviceinfo", "SoftwareVersion", value); - - return 0; -} - -static int get_device_active_fwimage(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - json_object *res = NULL, *bank_obj = NULL, *arrobj = NULL; - char linker[16] = {0}, *id = NULL; - int i = 0; - - dmubus_call("fwbank", "dump", UBUS_ARGS{0}, 0, &res); - dmjson_foreach_obj_in_array(res, arrobj, bank_obj, i, 1, "bank") { - char *active = dmjson_get_value(bank_obj, 1, "active"); - if (active && DM_LSTRCMP(active, "true") == 0) { - id = dmjson_get_value(bank_obj, 1, "id"); - break; - } - } - - if (DM_STRLEN(id) == 0) { - *value = dmstrdup(""); - return 0; - } - - snprintf(linker, sizeof(linker), "cpe-%s", id); - _bbfdm_get_references(ctx, "Device.DeviceInfo.FirmwareImage.", "Alias", linker, value); - return 0; -} - -static int get_device_boot_fwimage(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - json_object *res = NULL, *bank_obj = NULL, *arrobj = NULL; - char linker[16] = {0}, *id = NULL; - int i = 0; - - dmubus_call("fwbank", "dump", UBUS_ARGS{0}, 0, &res); - dmjson_foreach_obj_in_array(res, arrobj, bank_obj, i, 1, "bank") { - char *boot = dmjson_get_value(bank_obj, 1, "boot"); - if (boot && DM_LSTRCMP(boot, "true") == 0) { - id = dmjson_get_value(bank_obj, 1, "id"); - break; - } - } - - if (DM_STRLEN(id) == 0) { - *value = dmstrdup(""); - return 0; - } - - snprintf(linker, sizeof(linker), "cpe-%s", id); - _bbfdm_get_references(ctx, "Device.DeviceInfo.FirmwareImage.", "Alias", linker, value); - return 0; -} - -static int set_device_boot_fwimage(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - char *allowed_objects[] = {"Device.DeviceInfo.FirmwareImage.", NULL}; - struct dm_reference reference = {0}; - - bbfdm_get_reference_linker(ctx, value, &reference); - - switch (action) { - case VALUECHECK: - if (bbfdm_validate_string(ctx, reference.path, -1, -1, NULL, NULL)) - return FAULT_9007; - - if (dm_validate_allowed_objects(ctx, &reference, allowed_objects)) - return FAULT_9007; - - break; - case VALUESET: - if (DM_STRLEN(reference.value)) { - struct uci_section *dmmap_s = NULL; - json_object *res = NULL; - char *available = NULL; - - char *bank_id = DM_STRCHR(reference.value, '-'); // Get bank id 'X' which is linker from Alias prefix 'cpe-X' - if (!bank_id) - return FAULT_9001; - - get_dmmap_section_of_config_section_cont("dmmap_fw_image", "fw_image", "id", bank_id + 1, &dmmap_s); - dmuci_get_value_by_section_string(dmmap_s, "available", &available); - if (DM_LSTRCMP(available, "false") == 0) - return FAULT_9001; - - dmubus_call("fwbank", "set_bootbank", UBUS_ARGS{{"bank", bank_id + 1, Integer}}, 1, &res); - char *success = dmjson_get_value(res, 1, "success"); - if (DM_LSTRCMP(success, "true") != 0) - return FAULT_9001; - - } - break; - } - return 0; -} - -static int get_device_hardwareversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - db_get_value_string("device", "deviceinfo", "HardwareVersion", value); - return 0; -} - -static int get_device_devicecategory(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - db_get_value_string("device", "deviceinfo", "DeviceCategory", value); - return 0; -} - -static int get_device_additionalhardwareversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - db_get_value_string("device", "deviceinfo", "AdditionalHardwareVersion", value); - return 0; -} - -static int get_device_additionalsoftwareversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - db_get_value_string("device", "deviceinfo", "AdditionalSoftwareVersion", value); - return 0; -} - -/*#Device.DeviceInfo.ModelName!UCI:cwmp/cpe,cpe/model_name*/ -static int get_device_modelname(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("cwmp", "cpe", "model_name", value); - if (*value[0] == '\0') - db_get_value_string("device", "deviceinfo", "ModelName", value); - return 0; -} - -/*#Device.DeviceInfo.Description!UCI:cwmp/cpe,cpe/description*/ -static int get_device_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("cwmp", "cpe", "description", value); - if (*value[0] == '\0') - db_get_value_string("device", "deviceinfo", "Description", value); - return 0; -} - -/*#Device.DeviceInfo.UpTime!PROCFS:/proc/uptime*/ -static int get_device_info_uptime(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = get_uptime(); - return 0; -} - -static int get_device_info_firstusedate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("time", "global", "first_use_date", value); - return 0; -} - -/*#Device.DeviceInfo.ProvisioningCode!UCI:cwmp/cpe,cpe/provisioning_code*/ -static int get_device_provisioningcode(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - char *dhcp = NULL, *provisioning_code = NULL, *dhcp_provisioning_code = NULL; - bool discovery = false; - - dmuci_get_option_value_string("cwmp", "acs", "dhcp_discovery", &dhcp); - dmuci_get_option_value_string("cwmp", "cpe", "provisioning_code", &provisioning_code); - dmuci_get_option_value_string("cwmp", "cpe", "dhcp_provisioning_code", &dhcp_provisioning_code); - - discovery = dmuci_string_to_boolean(dhcp); - - if ((discovery == true) && (DM_STRLEN(dhcp_provisioning_code) != 0)) - *value = dhcp_provisioning_code; - else - *value = provisioning_code; - - return 0; -} - -static int set_device_provisioningcode(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - switch (action) { - case VALUECHECK: - if (bbfdm_validate_string(ctx, value, -1, 64, NULL, NULL)) - return FAULT_9007; - return 0; - case VALUESET: - dmuci_set_value("cwmp", "cpe", "provisioning_code", value); - return 0; - } - return 0; -} - -static int get_DeviceInfo_VendorConfigFileNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - int cnt = get_number_of_entries(ctx, data, instance, browseVcfInst); - dmasprintf(value, "%d", cnt); - return 0; -} - -static int get_DeviceInfo_SupportedDataModelNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmasprintf(value, "%d", ARRAY_SIZE(Data_Models)); - return 0; -} - -static int get_DeviceInfo_FirmwareImageNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - int cnt = get_number_of_entries(ctx, data, instance, browseDeviceInfoFirmwareImageInst); - dmasprintf(value, "%d", cnt); - return 0; -} - -static int get_deviceinfo_cid (char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - db_get_value_string("device", "deviceinfo", "CID", value); - return 0; -} - -static int get_deviceinfo_friendlyname(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - db_get_value_string("device", "deviceinfo", "FriendlyName", value); - return 0; -} - -static int get_deviceinfo_pen (char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - db_get_value_string("device", "deviceinfo", "PEN", value); - return 0; -} - -static int get_deviceinfo_modelnumber (char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - db_get_value_string("device", "deviceinfo", "ModelNumber", value); - return 0; -} - -static int get_DeviceInfo_HostName(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("system", "@system[0]", "hostname", value); - return 0; -} - -static int get_DeviceInfo_MaxNumberOfActivateTimeWindows(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmasprintf(value, "%d", MAX_TIME_WINDOW); - return 0; -} - -static int set_DeviceInfo_HostName(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - switch (action) { - case VALUECHECK: - if (bbfdm_validate_string(ctx, value, -1, 255, NULL, NULL)) - return FAULT_9007; - break; - case VALUESET: - dmuci_set_value("system", "@system[0]", "hostname", value); - break; - } - return 0; -} - -static int get_vcf_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "name", value); - return 0; -} - -static int get_vcf_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "version", value); - return 0; -} - -static int get_vcf_date(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - DIR *dir = NULL; - struct dirent *d_file = NULL; - char *config_name = NULL; - - *value = dmstrdup("0001-01-01T00:00:00Z"); - dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "name", &config_name); - if ((dir = opendir (DEFAULT_CONFIG_DIR)) != NULL) { - while ((d_file = readdir (dir)) != NULL) { - if (config_name && DM_STRCMP(config_name, d_file->d_name) == 0) { - char date[sizeof("AAAA-MM-JJTHH:MM:SSZ")], path[280] = {0}; - struct stat attr; - - snprintf(path, sizeof(path), "%s%s", DEFAULT_CONFIG_DIR, d_file->d_name); - stat(path, &attr); - strftime(date, sizeof(date), "%Y-%m-%dT%H:%M:%SZ", gmtime(&attr.st_mtime)); - *value = dmstrdup(date); - } - } - closedir (dir); - } - return 0; -} - -static int get_vcf_backup_restore(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "backup_restore", value); - return 0; -} - -static int get_vcf_desc(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "description", value); - return 0; -} - -static int get_vcf_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - return bbf_get_alias(ctx, ((struct dm_data *)data)->config_section, "vcf_alias", instance, value); -} - -static int set_vcf_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - return bbf_set_alias(ctx, ((struct dm_data *)data)->config_section, "vcf_alias", instance, value); -} - - -static int get_DeviceInfoSupportedDataModel_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct uci_section *s = NULL; - - uci_path_foreach_option_eq(bbfdm, "dmmap", "data_model", "data_model_inst", instance, s) { - dmuci_get_value_by_section_string(s, "alias", value); - break; - } - if ((*value)[0] == '\0') - dmasprintf(value, "cpe-%s", instance); - return 0; -} - -static int set_DeviceInfoSupportedDataModel_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct uci_section *s = NULL, *dmmap = NULL; - - switch (action) { - case VALUECHECK: - if (bbfdm_validate_string(ctx, value, -1, 64, NULL, NULL)) - return FAULT_9007; - break; - case VALUESET: - uci_path_foreach_option_eq(bbfdm, "dmmap", "data_model", "data_model_inst", instance, s) { - dmuci_set_value_by_section_bbfdm(s, "alias", value); - return 0; - } - dmuci_add_section_bbfdm("dmmap", "data_model", &dmmap); - dmuci_set_value_by_section(dmmap, "data_model_inst", instance); - dmuci_set_value_by_section(dmmap, "alias", value); - break; - } - return 0; -} - -static int get_DeviceInfoSupportedDataModel_URL(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = dmstrdup(((struct Supported_Data_Models *)data)->url); - return 0; -} - -static int get_DeviceInfoSupportedDataModel_URN(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = dmstrdup(((struct Supported_Data_Models *)data)->urn); - return 0; -} - -static int get_DeviceInfoSupportedDataModel_Features(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = dmstrdup(((struct Supported_Data_Models *)data)->features); - return 0; -} - -static int get_DeviceInfoFirmwareImage_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - char *id = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "id"); - dmasprintf(value, "cpe-%s", id ? id : instance); - return 0; -} - -static int set_DeviceInfoFirmwareImage_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - switch (action) { - case VALUECHECK: - if (bbfdm_validate_string(ctx, value, -1, 64, NULL, NULL)) - return FAULT_9007; - break; - case VALUESET: - bbfdm_set_fault_message(ctx, "Internal designated unique identifier, not allowed to update"); - return FAULT_9007; - } - return 0; -} - -static int get_DeviceInfoFirmwareImage_Name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - char *name; - - name = dmstrdup(dmjson_get_value(((struct dm_data *)data)->json_object, 1, "fwver")); - if (DM_STRLEN(name) > 64 ) { - name[64] = '\0'; - } - - *value = name; - return 0; -} - -static int get_DeviceInfoFirmwareImage_Version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "swver"); - return 0; -} - -static int get_DeviceInfoFirmwareImage_Available(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct uci_section *s = NULL; - - char *id = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "id"); - - uci_path_foreach_option_eq(bbfdm, "dmmap_fw_image", "fw_image", "id", id, s) { - dmuci_get_value_by_section_string(s, "available", value); - break; - } - - if ((*value)[0] == '\0') - *value = dmstrdup("true"); - return 0; -} - -static int set_DeviceInfoFirmwareImage_Available(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct uci_section *s = NULL, *dmmap = NULL; - char *id = NULL; - bool b; - - switch (action) { - case VALUECHECK: - if (bbfdm_validate_boolean(ctx, value)) - return FAULT_9007; - break; - case VALUESET: - string_to_bool(value, &b); - - if (!b) { - char *boot = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "boot"); - char *active = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "active"); - if (DM_LSTRCMP(boot, "true") == 0 || DM_LSTRCMP(active, "true") == 0) - return FAULT_9001; - } - - id = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "id"); - - uci_path_foreach_option_eq(bbfdm, "dmmap_fw_image", "fw_image", "id", id, s) { - dmuci_set_value_by_section_bbfdm(s, "available", b ? "true" : "false"); - return 0; - } - - dmuci_add_section_bbfdm("dmmap_fw_image", "fw_image", &dmmap); - dmuci_set_value_by_section(dmmap, "id", id); - dmuci_set_value_by_section(dmmap, "available", b ? "true" : "false"); - break; - } - return 0; -} - -static int get_DeviceInfoFirmwareImage_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "status"); - return 0; -} - -static int get_memory_status_total(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - json_object *res = NULL; - dmubus_call("system", "info", UBUS_ARGS{{}}, 0, &res); - DM_ASSERT(res, *value = dmstrdup("0")); - char *total = dmjson_get_value(res, 2, "memory", "total"); - dmasprintf(value, "%lu", DM_STRTOUL(total) / 1024); - return 0; -} - -static int get_memory_status_free(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - json_object *res = NULL; - dmubus_call("system", "info", UBUS_ARGS{{}}, 0, &res); - DM_ASSERT(res, *value = dmstrdup("0")); - char *free = dmjson_get_value(res, 2, "memory", "free"); - dmasprintf(value, "%lu", DM_STRTOUL(free) / 1024); - return 0; -} - -static int get_memory_status_total_persistent(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct statvfs dinfo; - if (statvfs("/overlay/", &dinfo) == 0) { - unsigned int total = (dinfo.f_bsize * dinfo.f_blocks) / 1024; - dmasprintf(value, "%u", total); - } else { - *value = dmstrdup("0"); - } - - return 0; -} - -static int get_memory_status_free_persistent(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct statvfs dinfo; - if (statvfs("/overlay/", &dinfo) == 0) { - unsigned int free = (dinfo.f_bsize * dinfo.f_bavail) / 1024; - dmasprintf(value, "%u", free); - } else { - *value = dmstrdup("0"); - } - - return 0; -} - -static int get_process_cpu_usage(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmasprintf(value, "%u", get_cpu_usage()); - return 0; -} - -static int get_process_number_of_entries(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - int cnt = get_number_of_entries(ctx, data, instance, browseProcessEntriesInst); - dmasprintf(value, "%d", cnt); - return 0; -} - -static int get_process_pid(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = data ? ((struct process_entry *)((struct dm_data *)data)->additional_data)->pid : ""; - return 0; -} - -static int get_process_command(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = data ? ((struct process_entry *)((struct dm_data *)data)->additional_data)->command : ""; - return 0; -} - -static int get_process_size(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = data ? ((struct process_entry *)((struct dm_data *)data)->additional_data)->size : ""; - return 0; -} - -static int get_process_priority(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = data ? ((struct process_entry *)((struct dm_data *)data)->additional_data)->priority : ""; - return 0; -} - -static int get_process_cpu_time(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = data ? ((struct process_entry *)((struct dm_data *)data)->additional_data)->cputime : ""; - return 0; -} - -static int get_process_state(char* refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = data ? ((struct process_entry *)((struct dm_data *)data)->additional_data)->state : ""; - return 0; -} - -static int get_DeviceInfoReboots_BootCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("deviceinfo", "globals", "boot_count", value); - return 0; -} - -static int get_DeviceInfoReboots_CurrentVersionBootCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("deviceinfo", "globals", "curr_version_boot_count", value); - return 0; -} - -static int get_DeviceInfoReboots_WatchdogBootCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("deviceinfo", "globals", "watchdog_boot_count", value); - return 0; -} - -static int get_DeviceInfoReboots_ColdBootCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("deviceinfo", "globals", "cold_boot_count", value); - return 0; -} - -static int get_DeviceInfoReboots_WarmBootCount(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_option_value_string("deviceinfo", "globals", "warm_boot_count", value); - return 0; -} - -static int get_DeviceInfoReboots_MaxRebootEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = dmuci_get_option_value_fallback_def("deviceinfo", "globals", "max_reboot_entries", "3"); - return 0; -} - -static int set_DeviceInfoReboots_MaxRebootEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct uci_section *s = NULL, *tmp_s = NULL; - int max_entries = DM_STRTOL(value); - - switch (action) { - case VALUECHECK: - if (bbfdm_validate_int(ctx, value, RANGE_ARGS{{"-1",NULL}}, 1)) - return FAULT_9007; - break; - case VALUESET: - if (max_entries == 0) { - // Delete all sections if value is "0" - uci_foreach_sections_safe("deviceinfo", "reboot", tmp_s, s) { - dmuci_delete_by_section(s, NULL, NULL); - } - } else if (max_entries > 0) { - // Step 1: Count total sections - int total_sections = 0; - - uci_foreach_sections_safe("deviceinfo", "reboot", tmp_s, s) { - total_sections++; - } - - // Step 2: Calculate how many sections to delete (earliest sections) - int to_delete = total_sections - max_entries; - - // Step 3: Delete the earliest sections that exceed max_entries - if (to_delete > 0) { - int idx = 0; - uci_foreach_sections_safe("deviceinfo", "reboot", tmp_s, s) { - if (idx++ < to_delete) { - dmuci_delete_by_section(s, NULL, NULL); - } - } - } - } - - dmuci_set_value("deviceinfo", "globals", "max_reboot_entries", value); - break; - } - return 0; -} - -static int get_DeviceInfoReboots_RebootNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - int cnt = get_number_of_entries(ctx, data, instance, browseDeviceInfoRebootsRebootInst); - dmasprintf(value, "%d", cnt); - return 0; -} - -static int get_DeviceInfoRebootsReboot_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - return bbf_get_alias(ctx, ((struct dm_data *)data)->dmmap_section, "reboot_alias", instance, value); -} - -static int set_DeviceInfoRebootsReboot_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - return bbf_set_alias(ctx, ((struct dm_data *)data)->dmmap_section, "reboot_alias", instance, value); -} - -static int get_DeviceInfoRebootsReboot_TimeStamp(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "time_stamp", value); - return 0; -} - -static int get_DeviceInfoRebootsReboot_FirmwareUpdated(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "firmware_updated", value); - return 0; -} - -static int get_DeviceInfoRebootsReboot_Cause(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "cause", value); - return 0; -} - -static int get_DeviceInfoRebootsReboot_Reason(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "reason", value); - return 0; -} - -/************************************************************* - * OPERATE COMMANDS - *************************************************************/ -static operation_args vendor_config_file_backup_args = { - .in = (const char *[]) { - "URL", - "Username", - "Password", - NULL - } -}; - -static int get_operate_args_DeviceInfoVendorConfigFile_Backup(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = (char *)&vendor_config_file_backup_args; - return 0; -} - -static int operate_DeviceInfoVendorConfigFile_Backup(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - const char *backup_command = "Backup()"; - char backup_path[256] = {'\0'}; - char *vcf_name = NULL; - - char *ret = DM_STRRCHR(refparam, '.'); - if (!ret) - return USP_FAULT_INVALID_ARGUMENT; - - if ((ret - refparam + 2) < sizeof(backup_path)) - snprintf(backup_path, ret - refparam + 2, "%s", refparam); - - char *url = dmjson_get_value((json_object *)value, 1, "URL"); - if (url[0] == '\0') - return USP_FAULT_INVALID_ARGUMENT; - - char *user = dmjson_get_value((json_object *)value, 1, "Username"); - char *pass = dmjson_get_value((json_object *)value, 1, "Password"); - - dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "name", &vcf_name); - - int res = bbf_config_backup(url, user, pass, vcf_name, backup_command, backup_path); - - return res ? USP_FAULT_COMMAND_FAILURE : 0; -} - -static operation_args vendor_config_file_restore_args = { - .in = (const char *[]) { - "URL", - "Username", - "Password", - "FileSize", - "TargetFileName", - "CheckSumAlgorithm", - "CheckSum", - NULL - } -}; - -static int get_operate_args_DeviceInfoVendorConfigFile_Restore(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = (char *)&vendor_config_file_restore_args; - return 0; -} - -static int operate_DeviceInfoVendorConfigFile_Restore(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - const char *restore_command = "Restore()"; - char restore_path[256] = {'\0'}; - - char *ret = DM_STRRCHR(refparam, '.'); - if (!ret) - return USP_FAULT_INVALID_ARGUMENT; - - if ((ret - refparam + 2) < sizeof(restore_path)) - snprintf(restore_path, ret - refparam + 2, "%s", refparam); - - char *url = dmjson_get_value((json_object *)value, 1, "URL"); - if (url[0] == '\0') - return USP_FAULT_INVALID_ARGUMENT; - - char *user = dmjson_get_value((json_object *)value, 1, "Username"); - char *pass = dmjson_get_value((json_object *)value, 1, "Password"); - char *file_size = dmjson_get_value((json_object *)value, 1, "FileSize"); - char *checksum_algorithm = dmjson_get_value((json_object *)value, 1, "CheckSumAlgorithm"); - char *checksum = dmjson_get_value((json_object *)value, 1, "CheckSum"); - - int res = bbf_config_restore(url, user, pass, file_size, checksum_algorithm, checksum, restore_command, restore_path); - - return res ? USP_FAULT_COMMAND_FAILURE : 0; -} - -static operation_args firmware_image_download_args = { - .in = (const char *[]) { - "URL", - "AutoActivate", - "Username", - "Password", - "FileSize", - "CheckSumAlgorithm", - "CheckSum", - "CommandKey", - BBF_VENDOR_PREFIX"KeepConfig", - NULL - } -}; - -static int get_operate_args_DeviceInfoFirmwareImage_Download(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = (char *)&firmware_image_download_args; - return 0; -} - -static int operate_DeviceInfoFirmwareImage_Download(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - const char *command = "Download()"; - char obj_path[256] = {0}; - - char *ret = DM_STRRCHR(refparam, '.'); - if (!ret) - return USP_FAULT_INVALID_ARGUMENT; - - if ((ret - refparam + 2) < sizeof(obj_path)) - snprintf(obj_path, ret - refparam + 2, "%s", refparam); - - char *url = dmjson_get_value((json_object *)value, 1, "URL"); - char *auto_activate = dmjson_get_value((json_object *)value, 1, "AutoActivate"); - if (url[0] == '\0') - return USP_FAULT_INVALID_ARGUMENT; - - // Assuming auto activate as false, if not provided by controller, in case of strict validation, - // this should result into a fault - if (DM_STRLEN(auto_activate) == 0) - auto_activate = dmstrdup("0"); - - char *username = dmjson_get_value((json_object *)value, 1, "Username"); - char *password = dmjson_get_value((json_object *)value, 1, "Password"); - char *file_size = dmjson_get_value((json_object *)value, 1, "FileSize"); - char *checksum_algorithm = dmjson_get_value((json_object *)value, 1, "CheckSumAlgorithm"); - char *checksum = dmjson_get_value((json_object *)value, 1, "CheckSum"); - char *commandKey = dmjson_get_value((json_object *)value, 1, "CommandKey"); - char *keep_config = dmjson_get_value((json_object *)value, 1, BBF_VENDOR_PREFIX"KeepConfig"); - - char *bank_id = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "id"); - - int res = bbf_fw_image_download(url, auto_activate, username, password, file_size, checksum_algorithm, checksum, bank_id, command, obj_path, commandKey, keep_config); - - if (res == 1) { - bbfdm_set_fault_message(ctx, "Firmware validation failed"); - } - - return res ? USP_FAULT_COMMAND_FAILURE : 0; -} - -static operation_args firmware_image_activate_args = { - .in = (const char *[]) { - - "TimeWindow.{i}.Start", - "TimeWindow.{i}.End", - "TimeWindow.{i}.Mode", - "TimeWindow.{i}.UserMessage", - "TimeWindow.{i}.MaxRetries", - NULL - } -}; - -static int get_operate_args_DeviceInfoFirmwareImage_Activate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = (char *)&firmware_image_activate_args; - return 0; -} - -void _exec_reboot(const void *arg1, void *arg2) -{ - char config_name[16] = {0}; - - snprintf(config_name, sizeof(config_name), "%s", "deviceinfo"); - - // Set last_reboot_cause to 'RemoteReboot' because the upcoming reboot will be initiated by USP Operate - dmuci_set_value(config_name, "globals", "last_reboot_cause", "RemoteReboot"); - dmuci_commit_package(config_name); - - sleep(3); - dmubus_call_set("rpc-sys", "reboot", UBUS_ARGS{0}, 0); - sleep(5); // Wait for reboot to happen - BBF_ERR("Reboot call failed with rpc-sys, trying again with system"); - dmubus_call_set("system", "reboot", UBUS_ARGS{0}, 0); - sleep(5); // Wait for reboot - BBF_ERR("Reboot call failed!!!"); - - // Set last_reboot_cause to empty because there is a problem in the system reboot - dmuci_set_value(config_name, "globals", "last_reboot_cause", ""); - dmuci_commit_package(config_name); -} - -static int operate_DeviceInfoFirmwareImage_Activate(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ -#define CRONTABS_ROOT "/etc/crontabs/root" -#define ACTIVATE_HANDLER_FILE "/usr/share/bbfdm/scripts/bbf_activate_handler.sh" - - char *FW_Mode[] = {"AnyTime", "Immediately", "WhenIdle", "ConfirmationNeeded", NULL}; - char *start_time[MAX_TIME_WINDOW] = {0}; - char *end_time[MAX_TIME_WINDOW] = {0}; - char *mode[MAX_TIME_WINDOW] = {0}; - char *user_message[MAX_TIME_WINDOW] = {0}; - char *max_retries[MAX_TIME_WINDOW] = {0}; - int res = 0, last_idx = -1; - - for (int i = 0; i < MAX_TIME_WINDOW; i++) { - char buf[32] = {0}; - - snprintf(buf, sizeof(buf), "TimeWindow.%d.Start", i + 1); - start_time[i] = dmjson_get_value((json_object *)value, 1, buf); - - snprintf(buf, sizeof(buf), "TimeWindow.%d.End", i + 1); - end_time[i] = dmjson_get_value((json_object *)value, 1, buf); - - snprintf(buf, sizeof(buf), "TimeWindow.%d.Mode", i + 1); - mode[i] = dmjson_get_value((json_object *)value, 1, buf); - - snprintf(buf, sizeof(buf), "TimeWindow.%d.UserMessage", i + 1); - user_message[i] = dmjson_get_value((json_object *)value, 1, buf); - - snprintf(buf, sizeof(buf), "TimeWindow.%d.MaxRetries", i + 1); - max_retries[i] = dmjson_get_value((json_object *)value, 1, buf); - - if (!DM_STRLEN(start_time[i])) - break; - - if (!DM_STRLEN(end_time[i]) || !DM_STRLEN(mode[i])) - return USP_FAULT_INVALID_ARGUMENT; - - if (bbfdm_validate_unsignedInt(ctx, start_time[i], RANGE_ARGS{{NULL,NULL}}, 1)) - return USP_FAULT_INVALID_ARGUMENT; - - if (bbfdm_validate_unsignedInt(ctx, end_time[i], RANGE_ARGS{{NULL,NULL}}, 1)) - return USP_FAULT_INVALID_ARGUMENT; - - if (DM_STRLEN(max_retries[i]) && bbfdm_validate_int(ctx, max_retries[i], RANGE_ARGS{{"-1","10"}}, 1)) - return USP_FAULT_INVALID_ARGUMENT; - - if (bbfdm_validate_string(ctx, mode[i], -1, -1, FW_Mode, NULL)) - return USP_FAULT_INVALID_ARGUMENT; - - if (DM_STRTOL(start_time[i]) > DM_STRTOL(end_time[i])) - return USP_FAULT_INVALID_ARGUMENT; - - if (i != 0 && DM_STRTOL(end_time[i - 1]) > DM_STRTOL(start_time[i])) - return USP_FAULT_INVALID_ARGUMENT; - - last_idx++; - } - - char *bank_id = dmjson_get_value(((struct dm_data *)data)->json_object, 1, "id"); - if (!DM_STRLEN(bank_id)) - return USP_FAULT_COMMAND_FAILURE; - - if (DM_STRLEN(start_time[0])) { - FILE *file = fopen(CRONTABS_ROOT, "a"); - if (!file) - return USP_FAULT_COMMAND_FAILURE; - - for (int i = 0; i < MAX_TIME_WINDOW && DM_STRLEN(start_time[i]); i++) { - char buffer[512] = {0}; - time_t t_time = time(NULL); - long int start_t = (DM_STRTOL(start_time[i]) > 60) ? DM_STRTOL(start_time[i]) : 60; - t_time += start_t; - struct tm *tm_local = localtime(&t_time); - - snprintf(buffer, sizeof(buffer), "%d %d %d %d * sh %s '%s' '%s' '%ld' '%d' '%s' '%s'\n", - tm_local->tm_min, - tm_local->tm_hour, - tm_local->tm_mday, - tm_local->tm_mon + 1, - ACTIVATE_HANDLER_FILE, - mode[i], - bank_id, - (DM_STRTOL(end_time[i]) - DM_STRTOL(start_time[i])), - (i == last_idx), - user_message[i], - max_retries[i]); - - fprintf(file, "%s", buffer); - } - - fclose(file); - - res = dmcmd_no_wait("/etc/init.d/cron", 1, "restart"); - } else { - 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 (strcasecmp(status, "true") != 0) - return USP_FAULT_COMMAND_FAILURE; - - bbfdm_task_fork(_exec_reboot, NULL, NULL, NULL); - } - - return res ? USP_FAULT_COMMAND_FAILURE : 0; -} - -static int operate_DeviceInfoReboots_RemoveAllReboots(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct uci_section *s = NULL, *tmp_s = NULL; - - uci_foreach_sections_safe("deviceinfo", "reboot", tmp_s, s) { - dmuci_delete_by_section(s, NULL, NULL); - } - return 0; -} - -static int operate_DeviceInfoRebootsReboot_Remove(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - dmuci_delete_by_section(((struct dm_data *)data)->config_section, NULL, NULL); - return 0; -} - -/********************************************************************************************************************************** -* OBJ & LEAF DEFINITION -***********************************************************************************************************************************/ -/* *** Device.DeviceInfo. *** */ -DMOBJ tDeviceInfoObj[] = { -/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/ -{"VendorConfigFile", &DMREAD, NULL, NULL, NULL, browseVcfInst, NULL, NULL, NULL, tDeviceInfoVendorConfigFileParams, NULL, BBFDM_BOTH, NULL}, -{"MemoryStatus", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoMemoryStatusParams, NULL, BBFDM_BOTH, NULL}, -{"ProcessStatus", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoProcessStatusObj, tDeviceInfoProcessStatusParams, NULL, BBFDM_BOTH, NULL}, -{"SupportedDataModel", &DMREAD, NULL, NULL, NULL, browseDeviceInfoSupportedDataModelInst, NULL, NULL, NULL, tDeviceInfoSupportedDataModelParams, NULL, BBFDM_CWMP, NULL}, -{"FirmwareImage", &DMREAD, NULL, NULL, "file:/usr/libexec/rpcd/fwbank", browseDeviceInfoFirmwareImageInst, NULL, NULL, NULL, tDeviceInfoFirmwareImageParams, NULL, BBFDM_BOTH, NULL}, -{"Reboots", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoRebootsObj, tDeviceInfoRebootsParams, NULL, BBFDM_USP, NULL}, -{0} -}; - -DMLEAF tDeviceInfoParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/ -{"DeviceCategory", &DMREAD, DMT_STRING, get_device_devicecategory, NULL, BBFDM_BOTH}, -{"Manufacturer", &DMREAD, DMT_STRING, get_device_manufacturer, NULL, BBFDM_BOTH}, -{"ManufacturerOUI", &DMREAD, DMT_STRING, get_device_manufactureroui, NULL, BBFDM_BOTH}, -{"ModelName", &DMREAD, DMT_STRING, get_device_modelname, NULL, BBFDM_BOTH}, -{"Description", &DMREAD, DMT_STRING, get_device_description, NULL, BBFDM_BOTH}, -{"ProductClass", &DMREAD, DMT_STRING, get_device_productclass, NULL, BBFDM_BOTH}, -{"SerialNumber", &DMREAD, DMT_STRING, get_device_serialnumber, NULL, BBFDM_BOTH}, -{"HardwareVersion", &DMREAD, DMT_STRING, get_device_hardwareversion, NULL, BBFDM_BOTH}, -{"SoftwareVersion", &DMREAD, DMT_STRING, get_device_softwareversion, NULL, BBFDM_BOTH}, -{"ActiveFirmwareImage", &DMREAD, DMT_STRING, get_device_active_fwimage, NULL, BBFDM_BOTH, DM_FLAG_REFERENCE}, -{"BootFirmwareImage", &DMWRITE, DMT_STRING, get_device_boot_fwimage, set_device_boot_fwimage, BBFDM_BOTH, DM_FLAG_REFERENCE}, -{"AdditionalHardwareVersion", &DMREAD, DMT_STRING, get_device_additionalhardwareversion, NULL, BBFDM_BOTH}, -{"AdditionalSoftwareVersion", &DMREAD, DMT_STRING, get_device_additionalsoftwareversion, NULL, BBFDM_BOTH}, -{"ProvisioningCode", &DMWRITE, DMT_STRING, get_device_provisioningcode, set_device_provisioningcode, BBFDM_BOTH}, -{"UpTime", &DMREAD, DMT_UNINT, get_device_info_uptime, NULL, BBFDM_BOTH}, -{"FirstUseDate", &DMREAD, DMT_TIME, get_device_info_firstusedate, NULL, BBFDM_BOTH}, -{"VendorConfigFileNumberOfEntries", &DMREAD, DMT_UNINT, get_DeviceInfo_VendorConfigFileNumberOfEntries, NULL, BBFDM_BOTH}, -{"SupportedDataModelNumberOfEntries", &DMREAD, DMT_UNINT, get_DeviceInfo_SupportedDataModelNumberOfEntries, NULL, BBFDM_CWMP}, -{"FirmwareImageNumberOfEntries", &DMREAD, DMT_UNINT, get_DeviceInfo_FirmwareImageNumberOfEntries, NULL, BBFDM_BOTH}, -{"CID", &DMREAD, DMT_STRING, get_deviceinfo_cid, NULL, BBFDM_USP}, -{"FriendlyName", &DMREAD, DMT_STRING, get_deviceinfo_friendlyname, NULL, BBFDM_USP}, -{"PEN", &DMREAD, DMT_STRING, get_deviceinfo_pen, NULL, BBFDM_USP}, -{"ModelNumber", &DMREAD, DMT_STRING, get_deviceinfo_modelnumber, NULL, BBFDM_BOTH}, -{"HostName", &DMWRITE, DMT_STRING, get_DeviceInfo_HostName, set_DeviceInfo_HostName, BBFDM_BOTH}, -{"MaxNumberOfActivateTimeWindows", &DMREAD, DMT_UNINT, get_DeviceInfo_MaxNumberOfActivateTimeWindows, NULL, BBFDM_USP}, -{0} -}; - -/* *** Device.DeviceInfo.VendorConfigFile.{i}. *** */ -DMLEAF tDeviceInfoVendorConfigFileParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/ -{"Alias", &DMWRITE, DMT_STRING, get_vcf_alias, set_vcf_alias, BBFDM_BOTH, DM_FLAG_UNIQUE}, -{"Name", &DMREAD, DMT_STRING, get_vcf_name, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE}, -{"Version", &DMREAD, DMT_STRING, get_vcf_version, NULL, BBFDM_BOTH}, -{"Date", &DMREAD, DMT_TIME, get_vcf_date, NULL, BBFDM_BOTH}, -{"Description", &DMREAD, DMT_STRING, get_vcf_desc, NULL, BBFDM_BOTH}, -{"UseForBackupRestore", &DMREAD, DMT_BOOL, get_vcf_backup_restore, NULL, BBFDM_BOTH}, -{"Backup()", &DMASYNC, DMT_COMMAND, get_operate_args_DeviceInfoVendorConfigFile_Backup, operate_DeviceInfoVendorConfigFile_Backup, BBFDM_USP}, -{"Restore()", &DMASYNC, DMT_COMMAND, get_operate_args_DeviceInfoVendorConfigFile_Restore, operate_DeviceInfoVendorConfigFile_Restore, BBFDM_USP}, -{0} -}; - -/* *** Device.DeviceInfo.MemoryStatus. *** */ -DMLEAF tDeviceInfoMemoryStatusParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/ -{"Total", &DMREAD, DMT_UNINT, get_memory_status_total, NULL, BBFDM_BOTH}, -{"Free", &DMREAD, DMT_UNINT, get_memory_status_free, NULL, BBFDM_BOTH}, -{"TotalPersistent", &DMREAD, DMT_UNINT, get_memory_status_total_persistent, NULL, BBFDM_BOTH}, -{"FreePersistent", &DMREAD, DMT_UNINT, get_memory_status_free_persistent, NULL, BBFDM_BOTH}, -{0} -}; -/* *** Device.DeviceInfo.ProcessStatus. *** */ -DMOBJ tDeviceInfoProcessStatusObj[] = { -/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/ -{"Process", &DMREAD, NULL, NULL, NULL, browseProcessEntriesInst, NULL, NULL, NULL, tDeviceInfoProcessStatusProcessParams, NULL, BBFDM_BOTH, NULL}, -{0} -}; - -DMLEAF tDeviceInfoProcessStatusParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/ -{"CPUUsage", &DMREAD, DMT_UNINT, get_process_cpu_usage, NULL, BBFDM_BOTH}, -{"ProcessNumberOfEntries", &DMREAD, DMT_UNINT, get_process_number_of_entries, NULL, BBFDM_BOTH}, -{0} -}; - -/* *** Device.DeviceInfo.ProcessStatus.Process.{i}. *** */ -DMLEAF tDeviceInfoProcessStatusProcessParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/ -{"PID", &DMREAD, DMT_UNINT, get_process_pid, NULL, BBFDM_BOTH, DM_FLAG_UNIQUE}, -{"Command", &DMREAD, DMT_STRING, get_process_command, NULL, BBFDM_BOTH}, -{"Size", &DMREAD, DMT_UNINT, get_process_size, NULL, BBFDM_BOTH}, -{"Priority", &DMREAD, DMT_UNINT, get_process_priority, NULL, BBFDM_BOTH}, -{"CPUTime", &DMREAD, DMT_UNINT, get_process_cpu_time, NULL, BBFDM_BOTH}, -{"State", &DMREAD, DMT_STRING, get_process_state, NULL, BBFDM_BOTH}, -{0} -}; - -/* *** Device.DeviceInfo.SupportedDataModel.{i}. *** */ -DMLEAF tDeviceInfoSupportedDataModelParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/ -{"Alias", &DMWRITE, DMT_STRING, get_DeviceInfoSupportedDataModel_Alias, set_DeviceInfoSupportedDataModel_Alias, BBFDM_CWMP, DM_FLAG_UNIQUE}, -{"URL", &DMREAD, DMT_STRING, get_DeviceInfoSupportedDataModel_URL, NULL, BBFDM_CWMP, DM_FLAG_UNIQUE}, -{"URN", &DMREAD, DMT_STRING, get_DeviceInfoSupportedDataModel_URN, NULL, BBFDM_CWMP}, -{"Features", &DMREAD, DMT_STRING, get_DeviceInfoSupportedDataModel_Features, NULL, BBFDM_CWMP}, -{0} -}; - -/* *** Device.DeviceInfo.FirmwareImage.{i}. *** */ -DMLEAF tDeviceInfoFirmwareImageParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/ -{"Alias", &DMWRITE, DMT_STRING, get_DeviceInfoFirmwareImage_Alias, set_DeviceInfoFirmwareImage_Alias, BBFDM_BOTH, DM_FLAG_UNIQUE|DM_FLAG_LINKER}, -{"Name", &DMREAD, DMT_STRING, get_DeviceInfoFirmwareImage_Name, NULL, BBFDM_BOTH}, -{"Version", &DMREAD, DMT_STRING, get_DeviceInfoFirmwareImage_Version, NULL, BBFDM_BOTH}, -{"Available", &DMWRITE, DMT_BOOL, get_DeviceInfoFirmwareImage_Available, set_DeviceInfoFirmwareImage_Available, BBFDM_BOTH}, -{"Status", &DMREAD, DMT_STRING, get_DeviceInfoFirmwareImage_Status, NULL, BBFDM_BOTH}, -{"BootFailureLog", &DMREAD, DMT_STRING, get_empty, NULL, BBFDM_BOTH}, -{"Download()", &DMASYNC, DMT_COMMAND, get_operate_args_DeviceInfoFirmwareImage_Download, operate_DeviceInfoFirmwareImage_Download, BBFDM_USP}, -{"Activate()", &DMASYNC, DMT_COMMAND, get_operate_args_DeviceInfoFirmwareImage_Activate, operate_DeviceInfoFirmwareImage_Activate, BBFDM_USP}, -{0} -}; - -/* *** Device.DeviceInfo.Reboots. *** */ -DMOBJ tDeviceInfoRebootsObj[] = { -/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys */ -{"Reboot", &DMREAD, NULL, NULL, NULL, browseDeviceInfoRebootsRebootInst, NULL, NULL, NULL, tDeviceInfoRebootsRebootParams, NULL, BBFDM_USP, NULL}, -{0} -}; - -DMLEAF tDeviceInfoRebootsParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */ -{"BootCount", &DMREAD, DMT_UNINT, get_DeviceInfoReboots_BootCount, NULL, BBFDM_USP}, -{"CurrentVersionBootCount", &DMREAD, DMT_UNINT, get_DeviceInfoReboots_CurrentVersionBootCount, NULL, BBFDM_USP}, -{"WatchdogBootCount", &DMREAD, DMT_UNINT, get_DeviceInfoReboots_WatchdogBootCount, NULL, BBFDM_USP}, -{"ColdBootCount", &DMREAD, DMT_UNINT, get_DeviceInfoReboots_ColdBootCount, NULL, BBFDM_USP}, -{"WarmBootCount", &DMREAD, DMT_UNINT, get_DeviceInfoReboots_WarmBootCount, NULL, BBFDM_USP}, -{"MaxRebootEntries", &DMWRITE, DMT_INT, get_DeviceInfoReboots_MaxRebootEntries, set_DeviceInfoReboots_MaxRebootEntries, BBFDM_USP}, -{"RebootNumberOfEntries", &DMREAD, DMT_UNINT, get_DeviceInfoReboots_RebootNumberOfEntries, NULL, BBFDM_USP}, -{"RemoveAllReboots()", &DMASYNC, DMT_COMMAND, NULL, operate_DeviceInfoReboots_RemoveAllReboots, BBFDM_USP}, -{0} -}; - -/* *** Device.DeviceInfo.Reboots.Reboot.{i}. *** */ -DMLEAF tDeviceInfoRebootsRebootParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */ -{"Alias", &DMWRITE, DMT_STRING, get_DeviceInfoRebootsReboot_Alias, set_DeviceInfoRebootsReboot_Alias, BBFDM_USP}, -{"TimeStamp", &DMREAD, DMT_TIME, get_DeviceInfoRebootsReboot_TimeStamp, NULL, BBFDM_USP}, -{"FirmwareUpdated", &DMREAD, DMT_BOOL, get_DeviceInfoRebootsReboot_FirmwareUpdated, NULL, BBFDM_USP}, -{"Cause", &DMREAD, DMT_STRING, get_DeviceInfoRebootsReboot_Cause, NULL, BBFDM_USP}, -{"Reason", &DMREAD, DMT_STRING, get_DeviceInfoRebootsReboot_Reason, NULL, BBFDM_USP}, -{"Remove()", &DMASYNC, DMT_COMMAND, NULL, operate_DeviceInfoRebootsReboot_Remove, BBFDM_USP}, -{0} -}; diff --git a/libbbfdm/deviceinfo.h b/libbbfdm/deviceinfo.h deleted file mode 100644 index 50d3a845..00000000 --- a/libbbfdm/deviceinfo.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2019 iopsys Software Solutions AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * Author: Imen Bhiri - * Author: Feten Besbes - * Author: Anis Ellouze - */ - -#ifndef __DEVICE_INFO_H -#define __DEVICE_INFO_H - -#include "libbbfdm-api/dmcommon.h" - -extern DMLEAF tDeviceInfoParams[]; -extern DMLEAF tDeviceInfoVendorConfigFileParams[]; -extern DMLEAF tDeviceInfoMemoryStatusParams[]; -extern DMOBJ tDeviceInfoProcessStatusObj[]; -extern DMLEAF tDeviceInfoProcessStatusParams[]; -extern DMOBJ tDeviceInfoObj[]; -extern DMLEAF tDeviceInfoProcessStatusProcessParams[]; -extern DMLEAF tDeviceInfoSupportedDataModelParams[]; -extern DMLEAF tDeviceInfoFirmwareImageParams[]; -extern DMOBJ tDeviceInfoRebootsObj[]; -extern DMLEAF tDeviceInfoRebootsParams[]; -extern DMLEAF tDeviceInfoRebootsRebootParams[]; - -void _exec_reboot(const void *arg1, void *arg2); -#endif diff --git a/libbbfdm/vendor/vendor.json b/libbbfdm/vendor/vendor.json deleted file mode 100644 index 1ae730c4..00000000 --- a/libbbfdm/vendor/vendor.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "json_plugin_version": 2, - "Device.DeviceInfo.": { - "type": "object", - "protocols": [ - "cwmp", - "usp" - ], - "description": "This object contains general device information.", - "access": false, - "array": false, - "{BBF_VENDOR_PREFIX}BaseMACAddress": { - "type": "string", - "read": true, - "write": false, - "protocols": [ - "cwmp", - "usp" - ], - "description": "The MAC Address of the device.", - "datatype": "MACAddress", - "range": [ - { - "max": 17 - } - ], - "pattern": [ - "", - "([0-9A-Fa-f][0-9A-Fa-f]:){5}([0-9A-Fa-f][0-9A-Fa-f])" - ], - "mapping": [ - { - "type": "uci", - "uci": { - "file": "/etc/board-db/config/device", - "section": { - "name": "deviceinfo" - }, - "option": { - "name":"BaseMACAddress" - } - } - } - ] - } - } -} \ No newline at end of file diff --git a/test/files/etc/config/deviceinfo b/test/files/etc/config/sysmngr similarity index 82% rename from test/files/etc/config/deviceinfo rename to test/files/etc/config/sysmngr index ceb1a577..ae63ff09 100644 --- a/test/files/etc/config/deviceinfo +++ b/test/files/etc/config/sysmngr @@ -1,5 +1,5 @@ -config globals 'globals' +config reboots 'reboots' option boot_count '2' option curr_version_boot_count '4' option watchdog_boot_count '3' @@ -7,28 +7,28 @@ config globals 'globals' option warm_boot_count '2' option max_reboot_entries '3' -config reboot +config reboot 'reboot_1730818192' option alias 'cpe-1' option time_stamp '2024-09-22T20:34:45Z' option firmware_updated '0' option cause 'RemoteReboot' option reason 'REBOOT' -config reboot +config reboot 'reboot_2541818178' option alias 'cpe-2' option time_stamp '2024-09-22T21:55:09Z' option firmware_updated '0' option cause 'LocalReboot' option reason 'POR_RESET' -config reboot +config reboot 'reboot_4512818130' option alias 'cpe-3' option time_stamp '2024-09-23T04:11:24Z' option firmware_updated '1' option cause 'LocalReboot' option reason 'upgrade' -config reboot +config reboot 'reboot_9874811423' option alias 'cpe-4' option time_stamp '2024-09-23T04:15:53Z' option firmware_updated '0' diff --git a/tools/bbf_common.py b/tools/bbf_common.py index 5890e3e8..b868a78b 100755 --- a/tools/bbf_common.py +++ b/tools/bbf_common.py @@ -411,7 +411,7 @@ def download_and_build_plugins(plugins, vendor_prefix): BBF_ERROR_CODE += 1 if len(LIST_FILES) > 0: - if not generate_shared_library(f"{name}{plugin_index}.so", LIST_FILES, vendor_prefix, extra_dependencies, is_microservice): + if not generate_shared_library(f"{plugin_index}_{name}.so", LIST_FILES, vendor_prefix, extra_dependencies, is_microservice): BBF_ERROR_CODE += 1 clear_list(LIST_FILES) diff --git a/tools/tools_input.json b/tools/tools_input.json index 52289d5e..e6bd896b 100644 --- a/tools/tools_input.json +++ b/tools/tools_input.json @@ -6,11 +6,37 @@ "model_name": "DG400PRIME-A", "software_version": "1.2.3.4", "dm_json_files": [ - "tools/datamodel.json", - "libbbfdm/vendor/vendor.json" + "tools/datamodel.json" ], "vendor_prefix": "X_IOPSYS_EU_", "plugins": [ + { + "repo": "https://dev.iopsys.eu/system/sysmngr.git", + "proto": "git", + "version": "devel", + "dm_info_file": "src/datamodel_description.json", + "extra_dependencies": [ + "-DSYSMNGR_VENDOR_CONFIG_FILE", + "-DSYSMNGR_MEMORY_STATUS", + "-DSYSMNGR_PROCESS_STATUS", + "-DSYSMNGR_SUPPORTED_DATA_MODEL", + "-DSYSMNGR_FIRMWARE_IMAGE", + "-DSYSMNGR_REBOOTS", + "-DSYSMNGR_NETWORK_PROPERTIES", + "-DSYSMNGR_VENDOR_EXTENSIONS" + ], + "dm_files": [ + "src/deviceinfo.c", + "src/configs.c", + "src/fw_images.c", + "src/memory.c", + "src/processes.c", + "src/reboots.c", + "src/supported_dm.c", + "src/network.c", + "src/utils.c" + ] + }, { "repo": "https://dev.iopsys.eu/bbf/icwmp.git", "proto": "git", @@ -23,6 +49,9 @@ "repo": "https://dev.iopsys.eu/bbf/bulkdata.git", "proto": "git", "version": "devel", + "extra_dependencies": [ + "-D_GNU_SOURCE" + ], "dm_files": [ "src/datamodel.c", "src/utils.c" @@ -330,7 +359,8 @@ "dm_files": [ "bbf_plugin/mcast_bbf.c", "bbf_plugin/x_iopsys_eu_igmp.c", - "bbf_plugin/x_iopsys_eu_mld.c" + "bbf_plugin/x_iopsys_eu_mld.c", + "bbf_plugin/x_iopsys_eu_common.c" ] }, { @@ -382,7 +412,7 @@ "libdm/tr104/*.c" ], "extra_dependencies": [ - "-I libdmtree", + "-I /builds/bbf/bbfdm/libbbfdm-api", "-I libdm/common" ] }, @@ -421,7 +451,7 @@ "libdm/extensions/iowrt/*.c" ], "extra_dependencies": [ - "-I libdmtree", + "-I /builds/bbf/bbfdm/libbbfdm-api", "-I libdm/common" ] } diff --git a/utilities/files/usr/share/bbfdm/scripts/bbf_activate_handler.sh b/utilities/files/usr/share/bbfdm/scripts/bbf_activate_handler.sh deleted file mode 100755 index 86193101..00000000 --- a/utilities/files/usr/share/bbfdm/scripts/bbf_activate_handler.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/sh - -# Script to activate image in specified time. -# -# Copyright © 2022 IOPSYS Software Solutions AB -# Author: Amin Ben Romdhane -# - -ROOT="$(dirname "${0}")" - -CHECK_IDLE_FILE="${ROOT}/bbf_check_idle.sh" -RETRY_TIME=300 -START_TIME=$(date +%s) -MODE="${1}" - -log() { - echo "${@}"|logger -t bbf.activate_firmware -p info -} - -activate_and_reboot_device() { - local bank_id="${1}" - local success - - success=$(ubus call fwbank set_bootbank "{'bank':${bank_id}}" | jsonfilter -e @.success) - if [ "${success}" != "true" ]; then - log "Can't activate the bank id ${bank_id}" - exit 1 - fi - - log "The device will restart after a few seconds" - ubus call rpc-sys reboot - exit 0 -} - -handle_whenidle_mode() { - local bank_id="${1}" - local end_time="${2}" - local force_activation="${3}" - local diff=0 - - [ ! -x "${CHECK_IDLE_FILE}" ] && { - activate_and_reboot_device "${bank_id}" - } - - sh "${CHECK_IDLE_FILE}" - if [ "$?" = "0" ]; then - activate_and_reboot_device "${bank_id}" - else - [ "${end_time}" -gt "$((diff + RETRY_TIME))" ] && { - sleep "${RETRY_TIME}" - } - - diff=$(($(date +%s) - START_TIME)) - fi - - while [ "${end_time}" -gt "${diff}" ]; do - sh "${CHECK_IDLE_FILE}" - if [ "$?" = "0" ]; then - activate_and_reboot_device "${bank_id}" - else - - if [ "${end_time}" -gt "$((diff + RETRY_TIME))" ]; then - sleep "${RETRY_TIME}" - else - break - fi - - diff=$(($(date +%s) - START_TIME)) - fi - - done - - [ "${force_activation}" = "1" ] && { - activate_and_reboot_device "${bank_id}" - } -} - -handle_confirmation_needed_mode() { - - log "[ConfirmationNeeded] mode is not implemented" - exit 0 -} - -######################## main ######################## -if [ "${MODE}" = "Immediately" ] || [ "${MODE}" = "AnyTime" ]; then - activate_and_reboot_device "${2}" -elif [ "${MODE}" = "WhenIdle" ]; then - handle_whenidle_mode "${2}" "${3}" "${4}" -elif [ "${MODE}" = "ConfirmationNeeded" ]; then - handle_confirmation_needed_mode "${2}" "${3}" "${4}" "${5}" "${6}" -else - log "[${MODE}] mode is not supported" - exit 1 -fi diff --git a/utilities/files/usr/share/bbfdm/scripts/bbf_check_idle.sh b/utilities/files/usr/share/bbfdm/scripts/bbf_check_idle.sh deleted file mode 100755 index 076e22ec..00000000 --- a/utilities/files/usr/share/bbfdm/scripts/bbf_check_idle.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -# Script to check idle state -# -# This script is used to determine if the device is in idle state or not -# And any idle state checking should be implemented here -# The value returned by this script is more important because based on it, will decide whether the image can be activated or not -# If (returned idle state == '0'), device is in idle state and can be activated. Otherwise, '1' - - -exit 0 \ No newline at end of file diff --git a/utilities/files/usr/share/bbfdm/scripts/bbf_reboot_handler.sh b/utilities/files/usr/share/bbfdm/scripts/bbf_reboot_handler.sh deleted file mode 100755 index c2eb7bc4..00000000 --- a/utilities/files/usr/share/bbfdm/scripts/bbf_reboot_handler.sh +++ /dev/null @@ -1,206 +0,0 @@ -#!/bin/sh - -# Script to handle Reboots Object -# -# Copyright © 2024 IOPSYS Software Solutions AB -# Author: Amin Ben Romdhane -# - -. /lib/functions.sh - -RESET_REASON_PATH="/tmp/reset_reason" -MAX_RETRIES=3 -RETRY_DELAY=1 - -log() { - echo "$@" | logger -t bbf_reboot -p info -} - -reset_option_counter() { - local option_name=$1 - local option_value=$2 - uci_set "deviceinfo" "globals" "${option_name}" "${option_value}" -} - -increment_option_counter() { - local option_name=$1 - local option_value=$(uci_get "deviceinfo" "globals" "${option_name}" "0") - local counter=$((option_value + 1)) - uci_set "deviceinfo" "globals" "${option_name}" "$counter" -} - -get_boot_trigger() { - local trigger - trigger=$(grep "triggered" ${RESET_REASON_PATH} | cut -d ':' -f2 | xargs) - echo "${trigger}" -} - -get_boot_reason() { - local reason - reason=$(grep "reason" ${RESET_REASON_PATH} | cut -d ':' -f2 | xargs) - echo "${reason}" -} - -calculate_boot_time() { - # Get current time and uptime in seconds - local current_time uptime_seconds boot_time boot_time_formatted - - current_time=$(date +%s) - uptime_seconds=$(awk '{print $1}' /proc/uptime | cut -d. -f1) - - # Calculate the boot time by subtracting the uptime from the current time - boot_time=$((current_time - uptime_seconds)) - - # Convert the boot time to a human-readable format - boot_time_formatted=$(date -d "@$boot_time" +"%Y-%m-%dT%H:%M:%SZ") - - echo "${boot_time_formatted}" -} - -boot_reason_message() { - # Generate a human-readable message based on the boot reason and trigger - local trigger reason - - trigger=$(get_boot_trigger) - - if [ -n "${trigger}" ]; then - case "${trigger}" in - "defaultreset") - echo "FACTORY RESET" - ;; - "upgrade") - echo "FIRMWARE UPGRADE" - ;; - *) - echo "${trigger}" - ;; - esac - else - reason=$(get_boot_reason) - case "${reason}" in - "POR_RESET") - echo "POWER ON RESET" - ;; - *) - echo "${reason}" - ;; - esac - fi -} - -create_reboot_section() { - local trigger=$1 - local reboot_sec - - reboot_sec="reboot_$(date +%Y%m%d%H%M%S)" - uci_add "deviceinfo" "reboot" "${reboot_sec}" - uci_set "deviceinfo" "${reboot_sec}" "time_stamp" "$(calculate_boot_time)" - - if [ "${trigger}" = "upgrade" ]; then - uci_set "deviceinfo" "${reboot_sec}" "firmware_updated" "1" - else - uci_set "deviceinfo" "${reboot_sec}" "firmware_updated" "0" - fi - - if [ "${trigger}" = "defaultreset" ]; then - uci_set "deviceinfo" "${reboot_sec}" "cause" "FactoryReset" - else - local last_reboot_cause - last_reboot_cause=$(uci_get "deviceinfo" "globals" "last_reboot_cause" "LocalReboot") - uci_set "deviceinfo" "${reboot_sec}" "cause" "${last_reboot_cause}" - uci_set "deviceinfo" "globals" "last_reboot_cause" "" - fi - - uci_set "deviceinfo" "${reboot_sec}" "reason" "$(boot_reason_message)" -} - -handle_reboot_action() { - local trigger reason max_reboot_entries retry_count reboot_sec_num - - retry_count=0 - - # Retry fetching the reset reason file - while [ ! -f "${RESET_REASON_PATH}" ] && [ $retry_count -lt $MAX_RETRIES ]; do - log "Warning: '${RESET_REASON_PATH}' not found. Attempt $((retry_count + 1)) of ${MAX_RETRIES}" - sleep $RETRY_DELAY - retry_count=$((retry_count + 1)) - done - - if [ ! -f "${RESET_REASON_PATH}" ]; then - log "Error: '${RESET_REASON_PATH}' is not generated after ${MAX_RETRIES} attempts!!!" - return 1 - fi - - uci_load "deviceinfo" - - trigger=$(get_boot_trigger) - reason=$(get_boot_reason) - - # Reset or increment boot counter based on trigger - if [ "${trigger}" = "defaultreset" ]; then - ## Reset all counters ## - reset_option_counter "boot_count" "1" - reset_option_counter "curr_version_boot_count" "0" - reset_option_counter "watchdog_boot_count" "0" - reset_option_counter "cold_boot_count" "0" - reset_option_counter "warm_boot_count" "0" - else - # Incrementing boot counter - increment_option_counter "boot_count" - fi - - # Reset or increment current version boot counter based on trigger - if [ "${trigger}" = "upgrade" ]; then - # Resetting current version boot counter - reset_option_counter "curr_version_boot_count" "1" - else - # Incrementing current version boot counter - increment_option_counter "curr_version_boot_count" - fi - - # Increment watchdog boot counter if the reason indicates a watchdog reset - if echo "${reason}" | grep -qi "watchdog"; then - # Incrementing watchdog boot counter - increment_option_counter "watchdog_boot_count" - fi - - # Increment cold or warm boot counter based on the reason - if [ "${reason}" = "POR_RESET" ]; then - increment_option_counter "cold_boot_count" - else - increment_option_counter "warm_boot_count" - fi - - # Get the max reboot entries - max_reboot_entries=$(uci_get "deviceinfo" "globals" "max_reboot_entries" "3") - - if [ "${max_reboot_entries}" -eq 0 ]; then - # Commit the UCI changes to persist the configuration - uci_commit "deviceinfo" - return 0 - fi - - if [ $max_reboot_entries -gt 0 ]; then - # Calculate the number of reboot sections in the config - reboot_sec_num=$(uci -q show deviceinfo | grep "=reboot" | wc -l) - - # Delete excess reboot sections if they exceed the max reboot entries - if [ "${reboot_sec_num}" -ge "${max_reboot_entries}" ]; then - local diff=$((reboot_sec_num - max_reboot_entries + 1)) - - for i in $(seq 1 $diff); do - uci_remove "deviceinfo" "@reboot[0]" - done - fi - fi - - # Create a new reboot section with the current boot information - create_reboot_section "${trigger}" - - # Commit the UCI changes to persist the configuration - uci_commit "deviceinfo" -} - -# Run the main function -handle_reboot_action -exit 0