From ff9dbb2688b637def0f8de7e38d43b56aedb7182 Mon Sep 17 00:00:00 2001 From: Amin Ben Ramdhane Date: Mon, 31 May 2021 09:33:17 +0100 Subject: [PATCH] Ticket refs #5325: Add support for Device.ManagementServer.ScheduleReboot and DelayReboot --- bin/Makefile.am | 4 +- config.c | 485 +++++++++++++++++++++++++++--------------------- cwmp.c | 13 +- inc/common.h | 2 + inc/config.h | 8 +- inc/cwmp_uci.h | 2 + inc/reboot.h | 19 ++ reboot.c | 120 ++++++++++++ session.c | 2 +- 9 files changed, 428 insertions(+), 227 deletions(-) create mode 100644 inc/reboot.h create mode 100644 reboot.c diff --git a/bin/Makefile.am b/bin/Makefile.am index c17a683..476ce5e 100755 --- a/bin/Makefile.am +++ b/bin/Makefile.am @@ -27,6 +27,7 @@ icwmpd_SOURCES = \ ../sched_inform.c \ ../xml.c \ ../diagnostic.c \ + ../reboot.c \ ../cwmp.c icwmpd_CFLAGS = \ @@ -94,7 +95,8 @@ libicwmp_la_SOURCES = \ ../upload.c \ ../sched_inform.c \ ../xml.c \ - ../diagnostic.c + ../diagnostic.c \ + ../reboot.c libicwmp_la_CFLAGS=-I../inc libicwmp_la_LDFLAGS= $(AM_LIBS) -luci -lubox -lubus $(MICROXML_LIBS) $(LIBCURL_LIBS) -lpthread -lcrypto -lssl -ljson-c -lblobmsg_json -lz -lm diff --git a/config.c b/config.c index 3cb54f3..460c252 100755 --- a/config.c +++ b/config.c @@ -13,10 +13,11 @@ #include "config.h" #include "cwmp_uci.h" #include "log.h" +#include "reboot.h" pthread_mutex_t mutex_config_load = PTHREAD_MUTEX_INITIALIZER; -int check_global_config(struct config *conf) +static int check_global_config(struct config *conf) { if (conf->acsurl == NULL) { conf->acsurl = strdup(DEFAULT_ACSURL); @@ -24,6 +25,22 @@ int check_global_config(struct config *conf) return CWMP_OK; } +static time_t convert_datetime_to_timestamp(char *value) +{ + struct tm tm = { 0 }; + int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0; + + sscanf(value, "%4d-%2d-%2dT%2d:%2d:%2d", &year, &month, &day, &hour, &min, &sec); + tm.tm_year = year - 1900; /* years since 1900 */ + tm.tm_mon = month - 1; + tm.tm_mday = day; + tm.tm_hour = hour; + tm.tm_min = min; + tm.tm_sec = sec; + + return mktime(&tm); +} + int get_global_config(struct config *conf) { int error, error2, error3; @@ -32,33 +49,55 @@ int get_global_config(struct config *conf) if ((error = uci_get_value(UCI_CPE_LOG_FILE_NAME, &value)) == CWMP_OK) { if (value != NULL) { log_set_log_file_name(value); - free(value); - value = NULL; + FREE(value); } + } else { + return error; } if ((error = uci_get_value(UCI_CPE_LOG_MAX_SIZE, &value)) == CWMP_OK) { if (value != NULL) { log_set_file_max_size(value); - free(value); - value = NULL; + FREE(value); } + } else { + return error; } if ((error = uci_get_value(UCI_CPE_ENABLE_STDOUT_LOG, &value)) == CWMP_OK) { if (value != NULL) { log_set_on_console(value); - free(value); - value = NULL; + FREE(value); } + } else { + return error; } if ((error = uci_get_value(UCI_CPE_ENABLE_FILE_LOG, &value)) == CWMP_OK) { if (value != NULL) { log_set_on_file(value); - free(value); - value = NULL; + FREE(value); } + } else { + return error; + } + + if ((error = uci_get_value(UCI_LOG_SEVERITY_PATH, &value)) == CWMP_OK) { + if (value != NULL) { + log_set_severity_idx(value); + FREE(value); + } + } else { + return error; + } + + if ((error = uci_get_value(UCI_CPE_ENABLE_SYSLOG, &value)) == CWMP_OK) { + if (value != NULL) { + log_set_on_syslog(value); + FREE(value); + } + } else { + return error; } error = uci_get_value(UCI_DHCP_DISCOVERY_PATH, &value); @@ -66,56 +105,61 @@ int get_global_config(struct config *conf) error3 = uci_get_state_value(UCI_DHCP_ACS_URL, &value3); if ((((error == CWMP_OK) && (value != NULL) && (strcmp(value, "enable") == 0)) || ((error2 == CWMP_OK) && ((value2 == NULL) || (value2[0] == 0)))) && ((error3 == CWMP_OK) && (value3 != NULL) && (value3[0] != 0))) { - if (conf->acsurl != NULL) { - free(conf->acsurl); - } + FREE(conf->acsurl); conf->acsurl = value3; value3 = NULL; } else if ((error2 == CWMP_OK) && (value2 != NULL) && (value2[0] != 0)) { - if (conf->acsurl != NULL) { - free(conf->acsurl); - } + FREE(conf->acsurl); conf->acsurl = value2; value2 = NULL; } - if (value != NULL) { - free(value); - value = NULL; - } - if (value2 != NULL) { - free(value2); - value2 = NULL; - } - if (value3 != NULL) { - free(value3); - value3 = NULL; - } + + FREE(value); + FREE(value2); + FREE(value3); if ((error = uci_get_value(UCI_ACS_USERID_PATH, &value)) == CWMP_OK) { if (value != NULL) { - if (conf->acs_userid != NULL) { - free(conf->acs_userid); - } + FREE(conf->acs_userid); conf->acs_userid = value; value = NULL; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - acs username: %s", conf->acs_userid ? conf->acs_userid : ""); } else { return error; } + if ((error = uci_get_value(UCI_ACS_PASSWD_PATH, &value)) == CWMP_OK) { if (value != NULL) { - if (conf->acs_passwd != NULL) { - free(conf->acs_passwd); - } + FREE(conf->acs_passwd); conf->acs_passwd = value; value = NULL; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - acs password: %s", conf->acs_passwd ? conf->acs_passwd : ""); } else { return error; } - if ((error = get_amd_version_config()) != CWMP_OK) { + + if ((error = uci_get_value(UCI_CPE_AMD_VERSION, &value)) == CWMP_OK) { + int a = 0; + + conf->amd_version = DEFAULT_AMD_VERSION; + if (value != NULL) { + a = atoi(value); + if (a >= 1) { + conf->amd_version = a; + } + FREE(value); + } + conf->supported_amd_version = conf->amd_version; + + CWMP_LOG(DEBUG, "CWMP CONFIG - amendement version: %d", conf->amd_version); + } else { return error; } + if ((error = uci_get_value(UCI_ACS_COMPRESSION, &value)) == CWMP_OK) { conf->compression = COMP_NONE; if (conf->amd_version >= AMD_5 && value != NULL) { @@ -127,11 +171,13 @@ int get_global_config(struct config *conf) conf->compression = COMP_NONE; } } - free(value); - value = NULL; + FREE(value); + + CWMP_LOG(DEBUG, "CWMP CONFIG - acs compression: %d", conf->compression); } else { return error; } + if ((error = uci_get_value(UCI_ACS_RETRY_MIN_WAIT_INTERVAL, &value)) == CWMP_OK) { conf->retry_min_wait_interval = DEFAULT_RETRY_MINIMUM_WAIT_INTERVAL; if (conf->amd_version >= AMD_3 && value != NULL) { @@ -140,12 +186,13 @@ int get_global_config(struct config *conf) conf->retry_min_wait_interval = a; } } - free(value); - value = NULL; + FREE(value); + CWMP_LOG(DEBUG, "CWMP CONFIG - acs retry minimum wait interval: %d", conf->retry_min_wait_interval); } else { return error; } + if ((error = uci_get_value(UCI_ACS_RETRY_INTERVAL_MULTIPLIER, &value)) == CWMP_OK) { conf->retry_interval_multiplier = DEFAULT_RETRY_INTERVAL_MULTIPLIER; if (conf->amd_version >= AMD_3 && value != NULL) { @@ -154,171 +201,175 @@ int get_global_config(struct config *conf) conf->retry_interval_multiplier = a; } } - free(value); - value = NULL; + FREE(value); + + CWMP_LOG(DEBUG, "CWMP CONFIG - acs retry interval: %d", conf->retry_interval_multiplier); } else { return error; } + if ((error = uci_get_value(UCI_ACS_SSL_CAPATH, &value)) == CWMP_OK) { if (value != NULL) { - if (conf->acs_ssl_capath != NULL) { - free(conf->acs_ssl_capath); - } + FREE(conf->acs_ssl_capath); conf->acs_ssl_capath = value; value = NULL; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - acs ssl cpath: %s", conf->acs_ssl_capath ? conf->acs_ssl_capath : ""); } else { - FREE(conf->acs_ssl_capath); + return error; } + if ((error = uci_get_value(UCI_HTTPS_SSL_CAPATH, &value)) == CWMP_OK) { if (value != NULL) { - if (conf->https_ssl_capath != NULL) { - free(conf->https_ssl_capath); - } + FREE(conf->https_ssl_capath); conf->https_ssl_capath = value; value = NULL; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - https ssl cpath: %s", conf->https_ssl_capath ? conf->https_ssl_capath : ""); } else { - FREE(conf->https_ssl_capath); + return error; } + if ((error = uci_get_value(HTTP_DISABLE_100CONTINUE, &value)) == CWMP_OK) { if (value != NULL) { if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) conf->http_disable_100continue = true; - free(value); - value = NULL; + FREE(value); } + + CWMP_LOG(DEBUG, "CWMP CONFIG - http disable 100continue: %d", conf->http_disable_100continue); + } else { + return error; } + if ((error = uci_get_value(UCI_ACS_INSECURE_ENABLE, &value)) == CWMP_OK) { if (value != NULL) { if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) { conf->insecure_enable = true; } - free(value); - value = NULL; + FREE(value); } + + CWMP_LOG(DEBUG, "CWMP CONFIG - acs insecure enable: %d", conf->insecure_enable); + } else { + return error; } + if ((error = uci_get_value(UCI_ACS_IPV6_ENABLE, &value)) == CWMP_OK) { if (value != NULL) { if ((strcasecmp(value, "true") == 0) || (strcmp(value, "1") == 0)) { conf->ipv6_enable = true; } - free(value); - value = NULL; + FREE(value); } + + CWMP_LOG(DEBUG, "CWMP CONFIG - ipv6 enable: %d", conf->ipv6_enable); + } else { + return error; } + if ((error = uci_get_value(UCI_ACS_SSL_VERSION, &value)) == CWMP_OK) { if (value != NULL) { - if (conf->acs_ssl_version != NULL) { - free(conf->acs_ssl_version); - } + FREE(conf->acs_ssl_version); conf->acs_ssl_version = value; value = NULL; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - acs ssl version: %s", conf->acs_ssl_version ? conf->acs_ssl_version : ""); } else { - FREE(conf->acs_ssl_version); + return error; } + if ((error = uci_get_value(UCI_CPE_INTERFACE_PATH, &value)) == CWMP_OK) { if (value != NULL) { - if (conf->interface != NULL) { - free(conf->interface); - } + FREE(conf->interface); conf->interface = value; value = NULL; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - cpe interface: %s", conf->interface ? conf->interface : ""); } else { return error; } + if ((error = uci_get_value(UCI_CPE_USERID_PATH, &value)) == CWMP_OK) { + FREE(conf->cpe_userid); if (value != NULL) { - if (conf->cpe_userid != NULL) { - free(conf->cpe_userid); - } conf->cpe_userid = value; value = NULL; } else { - if (conf->cpe_userid != NULL) { - free(conf->cpe_userid); - } conf->cpe_userid = strdup(""); } + + CWMP_LOG(DEBUG, "CWMP CONFIG - cpe username: %s", conf->cpe_userid ? conf->cpe_userid : ""); } else { return error; } + if ((error = uci_get_value(UCI_CPE_PASSWD_PATH, &value)) == CWMP_OK) { + FREE(conf->cpe_passwd); if (value != NULL) { - if (conf->cpe_passwd != NULL) { - free(conf->cpe_passwd); - } conf->cpe_passwd = value; value = NULL; } else { - if (conf->cpe_passwd != NULL) { - free(conf->cpe_passwd); - } conf->cpe_passwd = strdup(""); } + + CWMP_LOG(DEBUG, "CWMP CONFIG - cpe password: %s", conf->cpe_passwd ? conf->cpe_passwd : ""); } else { return error; } if ((error = uci_get_value(UCI_CPE_UBUS_SOCKET_PATH, &value)) == CWMP_OK) { if (value != NULL) { - if (conf->ubus_socket != NULL) { - free(conf->ubus_socket); - } + FREE(conf->ubus_socket); conf->ubus_socket = value; value = NULL; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - ubus socket: %s", conf->ubus_socket ? conf->ubus_socket : ""); } else { return error; } - if ((error = uci_get_value(UCI_LOG_SEVERITY_PATH, &value)) == CWMP_OK) { - if (value != NULL) { - log_set_severity_idx(value); - free(value); - value = NULL; - } - } else { - return error; - } - if ((error = uci_get_value(UCI_CPE_ENABLE_SYSLOG, &value)) == CWMP_OK) { - if (value != NULL) { - log_set_on_syslog(value); - free(value); - value = NULL; - } - } if ((error = uci_get_value(UCI_CPE_PORT_PATH, &value)) == CWMP_OK) { int a = 0; if (value != NULL) { a = atoi(value); - free(value); - value = NULL; + FREE(value); } + if (a == 0) { CWMP_LOG(INFO, "Set the connection request port to the default value: %d", DEFAULT_CONNECTION_REQUEST_PORT); conf->connection_request_port = DEFAULT_CONNECTION_REQUEST_PORT; } else { conf->connection_request_port = a; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - connection request port: %d", conf->connection_request_port); } else { return error; } + if ((error = uci_get_value(UCI_CPE_DEFAULT_WAN_IFACE, &value)) == CWMP_OK) { - if (value != NULL) + FREE(conf->default_wan_iface); + if (value != NULL) { conf->default_wan_iface = strdup(value); - else + FREE(value); + } else { conf->default_wan_iface = strdup("wan"); + } + + CWMP_LOG(DEBUG, "CWMP CONFIG - default wan interface: %s", conf->default_wan_iface ? conf->default_wan_iface : ""); } else { return error; } + if ((error = uci_get_value(UCI_CPE_CRPATH_PATH, &value)) == CWMP_OK) { - if (conf->connection_request_path != NULL) { - free(conf->connection_request_path); - } + FREE(conf->connection_request_path); if (value == NULL) conf->connection_request_path = strdup("/"); else { @@ -329,10 +380,14 @@ int get_global_config(struct config *conf) snprintf(cr_path, sizeof(cr_path), "/%s", value); conf->connection_request_path = strdup(cr_path); } + FREE(value); } + + CWMP_LOG(DEBUG, "CWMP CONFIG - connection request: %s", conf->connection_request_path ? conf->connection_request_path : ""); } else { return error; } + if ((error = uci_get_value(UCI_CPE_NOTIFY_PERIODIC_ENABLE, &value)) == CWMP_OK) { bool a = true; if (value != NULL) { @@ -341,64 +396,68 @@ int get_global_config(struct config *conf) } else { a = true; } - free(value); - value = NULL; + FREE(value); } conf->periodic_notify_enable = a; + + CWMP_LOG(DEBUG, "CWMP CONFIG - periodic notifiy enable: %d", conf->periodic_notify_enable); } else { return error; } + if ((error = uci_get_value(UCI_CPE_NOTIFY_PERIOD, &value)) == CWMP_OK) { int a = 0; if (value != NULL) { a = atoi(value); - free(value); - value = NULL; + FREE(value); } + if (a == 0) { CWMP_LOG(INFO, "Set notify period to the default value: %d", DEFAULT_NOTIFY_PERIOD); conf->periodic_notify_interval = DEFAULT_NOTIFY_PERIOD; } else { conf->periodic_notify_interval = a; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - periodic notifiy interval: %d", conf->periodic_notify_interval); } else { return error; } + if ((error = uci_get_value(UCI_PERIODIC_INFORM_TIME_PATH, &value)) == CWMP_OK) { if (value != NULL) { - struct tm tm = { 0 }; - int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0; - sscanf(value, "%4d-%2d-%2dT%2d:%2d:%2d", &year, &month, &day, &hour, &min, &sec); - tm.tm_year = year - 1900; /* years since 1900 */ - tm.tm_mon = month - 1; - tm.tm_mday = day; - tm.tm_hour = hour; - tm.tm_min = min; - tm.tm_sec = sec; - conf->time = mktime(&tm); - } else + conf->time = convert_datetime_to_timestamp(value); + FREE(value); + } else { conf->time = 0; + } + + CWMP_LOG(DEBUG, "CWMP CONFIG - periodic inform time: %ld", conf->time); } else { return error; } + if ((error = uci_get_value(UCI_PERIODIC_INFORM_INTERVAL_PATH, &value)) == CWMP_OK) { int a = 0; if (value != NULL) { a = atoi(value); - free(value); - value = NULL; + FREE(value); } + if (a >= PERIOD_INFORM_MIN) { conf->period = a; } else { CWMP_LOG(ERROR, "Period interval of periodic inform should be > %ds. Set to default: %ds", PERIOD_INFORM_MIN, PERIOD_INFORM_DEFAULT); conf->period = PERIOD_INFORM_DEFAULT; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - periodic inform interval: %d", conf->period); } else { return error; } + if ((error = uci_get_value(UCI_PERIODIC_INFORM_ENABLE_PATH, &value)) == CWMP_OK) { if (value != NULL) { if ((strcasecmp(value, "TRUE") == 0) || (strcmp(value, "1") == 0)) { @@ -406,95 +465,50 @@ int get_global_config(struct config *conf) } else { conf->periodic_enable = false; } - free(value); - value = NULL; + FREE(value); } else { conf->periodic_enable = false; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - periodic inform enable: %d", conf->periodic_enable); } else { return error; } - if ((error = get_instance_mode_config()) != CWMP_OK) { - return error; - } - if ((error = get_session_timeout_config()) != CWMP_OK) { - return error; - } - return CWMP_OK; -} -int get_amd_version_config() -{ - int error; - int a = 0; - char *value = NULL; - struct cwmp *cwmp = &cwmp_main; - if ((error = uci_get_value(UCI_CPE_AMD_VERSION, &value)) == CWMP_OK) { - cwmp->conf.amd_version = DEFAULT_AMD_VERSION; - if (value != NULL) { - a = atoi(value); - if (a >= 1) { - cwmp->conf.amd_version = a; - } - free(value); - value = NULL; - } - cwmp->conf.supported_amd_version = cwmp->conf.amd_version; - } else { - return error; - } - return CWMP_OK; -} - -int get_session_timeout_config() -{ - int error; - int a = 0; - char *value = NULL; - struct cwmp *cwmp = &cwmp_main; - if ((error = uci_get_value(UCI_CPE_SESSION_TIMEOUT, &value)) == CWMP_OK) { - cwmp->conf.session_timeout = DEFAULT_SESSION_TIMEOUT; - if (value != NULL) { - a = atoi(value); - if (a >= 1) { - cwmp->conf.session_timeout = a; - } - free(value); - value = NULL; - } - } else { - return error; - } - return CWMP_OK; -} - -int get_instance_mode_config() -{ - int error; - char *value = NULL; - struct cwmp *cwmp = &cwmp_main; if ((error = uci_get_value(UCI_CPE_INSTANCE_MODE, &value)) == CWMP_OK) { - cwmp->conf.instance_mode = DEFAULT_INSTANCE_MODE; if (value != NULL) { if (0 == strcmp(value, "InstanceNumber")) { - cwmp->conf.instance_mode = INSTANCE_MODE_NUMBER; + conf->instance_mode = INSTANCE_MODE_NUMBER; } else { - cwmp->conf.instance_mode = INSTANCE_MODE_ALIAS; + conf->instance_mode = INSTANCE_MODE_ALIAS; } - free(value); - value = NULL; + FREE(value); + } else { + conf->instance_mode = DEFAULT_INSTANCE_MODE; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - instance mode: %d (InstanceNumber=0, InstanceAlias=1)", conf->instance_mode); + } else { + return error; + } + + if ((error = uci_get_value(UCI_CPE_SESSION_TIMEOUT, &value)) == CWMP_OK) { + int a = 0; + + conf->session_timeout = DEFAULT_SESSION_TIMEOUT; + if (value != NULL) { + a = atoi(value); + if (a >= 1) { + conf->session_timeout = a; + } + FREE(value); + } + + CWMP_LOG(DEBUG, "CWMP CONFIG - session timeout: %d", conf->session_timeout); } else { return error; } - return CWMP_OK; -} -int get_lwn_config(struct config *conf) -{ - int error; - int a = 0; - char *value = NULL; if ((error = uci_get_value(LW_NOTIFICATION_ENABLE, &value)) == CWMP_OK) { if (value != NULL) { if ((strcasecmp(value, "TRUE") == 0) || (strcmp(value, "1") == 0)) { @@ -502,48 +516,96 @@ int get_lwn_config(struct config *conf) } else { conf->lw_notification_enable = false; } - free(value); - value = NULL; + FREE(value); + } else { + conf->lw_notification_enable = false; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - lightweight notification enable: %d", conf->lw_notification_enable); + } else { + return error; } + if ((error = uci_get_value(LW_NOTIFICATION_HOSTNAME, &value)) == CWMP_OK) { + FREE(conf->lw_notification_hostname); if (value != NULL) { conf->lw_notification_hostname = strdup(value); - free(value); - value = NULL; + FREE(value); } else { - conf->lw_notification_hostname = strdup(conf->acsurl); + conf->lw_notification_hostname = strdup(conf->acsurl ? conf->acsurl : ""); } + + CWMP_LOG(DEBUG, "CWMP CONFIG - lightweight notification hostname: %s", conf->lw_notification_hostname ? conf->lw_notification_hostname : ""); + } else { + return error; } + if ((error = uci_get_value(LW_NOTIFICATION_PORT, &value)) == CWMP_OK) { + int a = 0; + if (value != NULL) { a = atoi(value); conf->lw_notification_port = a; - free(value); - value = NULL; + FREE(value); } else { conf->lw_notification_port = DEFAULT_LWN_PORT; } + + CWMP_LOG(DEBUG, "CWMP CONFIG - lightweight notification port: %d", conf->lw_notification_port); + } else { + return error; } + + if (uci_get_value(UCI_CPE_SCHEDULE_REBOOT, &value) == CWMP_OK) { + if (value != NULL) { + conf->schedule_reboot = convert_datetime_to_timestamp(value); + FREE(value); + } else { + conf->schedule_reboot = 0; + } + + CWMP_LOG(DEBUG, "CWMP CONFIG - schedule reboot: %ld", conf->schedule_reboot); + } else { + return error; + } + + if (uci_get_value(UCI_CPE_DELAY_REBOOT, &value) == CWMP_OK) { + int delay = -1; + + if (value != NULL) { + delay = atoi(value); + FREE(value); + } + + conf->delay_reboot = delay; + + CWMP_LOG(DEBUG, "CWMP CONFIG - delay reboot: %d", conf->delay_reboot); + } else { + return error; + } + return CWMP_OK; } -int global_conf_init(struct config *conf) +int global_conf_init(struct cwmp *cwmp) { - int error; + int error = CWMP_OK; pthread_mutex_lock(&mutex_config_load); - if ((error = get_global_config(conf))) { - pthread_mutex_unlock(&mutex_config_load); - return error; - } - if ((error = check_global_config(conf))) { - pthread_mutex_unlock(&mutex_config_load); - return error; - } - get_lwn_config(conf); + + if ((error = get_global_config(&(cwmp->conf)))) + goto end; + + if ((error = check_global_config(&(cwmp->conf)))) + goto end; + + /* Launch reboot methods if needed */ + launch_reboot_methods(cwmp); + +end: pthread_mutex_unlock(&mutex_config_load); - return CWMP_OK; + + return error; } int cwmp_get_deviceid(struct cwmp *cwmp) @@ -552,7 +614,7 @@ int cwmp_get_deviceid(struct cwmp *cwmp) cwmp_uci_init(UCI_DB_CONFIG); else cwmp_uci_init(UCI_BOARD_DB_CONFIG); - cwmp->deviceid.manufacturer = strdup(cwmp_db_get_value_string("device", "deviceinfo", "Manufacturer")); //TODO free + cwmp->deviceid.manufacturer = strdup(cwmp_db_get_value_string("device", "deviceinfo", "Manufacturer")); cwmp->deviceid.serialnumber = strdup(cwmp_db_get_value_string("device", "deviceinfo", "SerialNumber")); cwmp->deviceid.productclass = strdup(cwmp_db_get_value_string("device", "deviceinfo", "ProductClass")); cwmp->deviceid.oui = strdup(cwmp_db_get_value_string("device", "deviceinfo", "ManufacturerOUI")); @@ -563,13 +625,8 @@ int cwmp_get_deviceid(struct cwmp *cwmp) int cwmp_config_reload(struct cwmp *cwmp) { - int error; - memset(&cwmp->env, 0, sizeof(struct env)); memset(&cwmp->conf, 0, sizeof(struct config)); - if ((error = global_conf_init(&(cwmp->conf)))) - return error; - - return CWMP_OK; + return global_conf_init(cwmp); } diff --git a/cwmp.c b/cwmp.c index 5624731..88e88b3 100644 --- a/cwmp.c +++ b/cwmp.c @@ -147,8 +147,13 @@ end: return session->error; } -int run_session_end_func() +int run_session_end_func(void) { + if (end_session_flag & END_SESSION_TRANSACTION_COMMIT) { + cwmp_transaction_commit(); + transaction_started = false; + } + if (end_session_flag & END_SESSION_RELOAD) { CWMP_LOG(INFO, "Config reload: end session request"); cwmp_apply_acs_changes(); @@ -158,10 +163,6 @@ int run_session_end_func() CWMP_LOG(INFO, "SetParameterAttributes end session: update enabled notify file"); cwmp_update_enabled_notify_file(); } - if (end_session_flag & END_SESSION_TRANSACTION_COMMIT) { - cwmp_transaction_commit(); - transaction_started = false; - } if (end_session_flag & END_SESSION_NSLOOKUP_DIAGNOSTIC) { CWMP_LOG(INFO, "Executing nslookupdiagnostic: end session request"); @@ -359,7 +360,7 @@ int cwmp_init(int argc, char **argv, struct cwmp *cwmp) memcpy(&(cwmp->env), &env, sizeof(struct env)); INIT_LIST_HEAD(&(cwmp->head_session_queue)); - if ((error = global_conf_init(&(cwmp->conf)))) + if ((error = global_conf_init(cwmp))) return error; cwmp_get_deviceid(cwmp); diff --git a/inc/common.h b/inc/common.h index 05dacfc..6bfcf49 100644 --- a/inc/common.h +++ b/inc/common.h @@ -79,6 +79,8 @@ typedef struct config { int period; int periodic_notify_interval; int compression; + int delay_reboot; + time_t schedule_reboot; time_t time; bool periodic_enable; bool periodic_notify_enable; diff --git a/inc/config.h b/inc/config.h index 69bb80c..1a9a244 100755 --- a/inc/config.h +++ b/inc/config.h @@ -18,11 +18,9 @@ extern pthread_mutex_t mutex_config_load; -int get_amd_version_config(); -int get_instance_mode_config(); -int get_session_timeout_config(); -int cwmp_config_reload(struct cwmp *cwmp); -int global_conf_init(struct config *conf); +int global_conf_init(struct cwmp *cwmp); int get_global_config(struct config *conf); int cwmp_get_deviceid(struct cwmp *cwmp); +int cwmp_config_reload(struct cwmp *cwmp); + #endif diff --git a/inc/cwmp_uci.h b/inc/cwmp_uci.h index 9c8021e..60602d1 100644 --- a/inc/cwmp_uci.h +++ b/inc/cwmp_uci.h @@ -54,6 +54,8 @@ #define UCI_CPE_NOTIFY_PERIOD "cwmp.cpe.periodic_notify_interval" #define UCI_CPE_IP "cwmp.cpe.ip" #define UCI_CPE_IPV6 "cwmp.cpe.ipv6" +#define UCI_CPE_SCHEDULE_REBOOT "cwmp.cpe.schedule_reboot" +#define UCI_CPE_DELAY_REBOOT "cwmp.cpe.delay_reboot" #define LW_NOTIFICATION_ENABLE "cwmp.lwn.enable" #define LW_NOTIFICATION_HOSTNAME "cwmp.lwn.hostname" #define LW_NOTIFICATION_PORT "cwmp.lwn.port" diff --git a/inc/reboot.h b/inc/reboot.h new file mode 100644 index 0000000..276eacf --- /dev/null +++ b/inc/reboot.h @@ -0,0 +1,19 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Copyright (C) 2021 iopsys Software Solutions AB + * Author Amin Ben Ramdhane + */ + +#ifndef _REBOOT_H__ +#define _REBOOT_H__ + +#include "common.h" + +void launch_reboot_methods(struct cwmp *cwmp); + +#endif //_REBOOT_H__ + diff --git a/reboot.c b/reboot.c new file mode 100644 index 0000000..58d4616 --- /dev/null +++ b/reboot.c @@ -0,0 +1,120 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Copyright (C) 2021 iopsys Software Solutions AB + * Author Amin Ben Ramdhane + */ + +#include +#include +#include "session.h" +#include "cwmp_uci.h" +#include "log.h" +#include "reboot.h" + +static pthread_t delay_reboot_thread; +static pthread_t delay_schedule_thread; + +static void *thread_delay_reboot(void *arg) +{ + struct cwmp *cwmp = (struct cwmp *)arg; + + CWMP_LOG(INFO, "The device will reboot after %d seconds", cwmp->conf.delay_reboot); + sleep(cwmp->conf.delay_reboot); + uci_set_value(UCI_CPE_DELAY_REBOOT, "-1", CWMP_CMD_SET); + + /* check if the session is running before calling reboot method */ + /* if the session is in progress, wait until the end of the session */ + /* else calling reboot method */ + if (cwmp->session_status.last_status == SESSION_RUNNING) { + cwmp_set_end_session(END_SESSION_REBOOT); + } else { + cwmp_reboot("delay_reboot"); + exit(EXIT_SUCCESS); + } + + return NULL; +} + +static void create_delay_reboot_thread(struct cwmp *cwmp, bool thread_exist) +{ + if (thread_exist) { + CWMP_LOG(INFO, "There is already a delay reboot thread!, Cancel the current thread"); + + pthread_cancel(delay_reboot_thread); + create_delay_reboot_thread(cwmp, false); + } else { + CWMP_LOG(INFO, "Create a delay reboot thread"); + + if (pthread_create(&delay_reboot_thread, NULL, &thread_delay_reboot, (void *)cwmp)) { + CWMP_LOG(ERROR, "Error when creating the delay reboot thread!"); + } + + if (pthread_detach(delay_reboot_thread)) { + CWMP_LOG(ERROR, "Error when creating the delay reboot thread!"); + } + } +} + +static void *thread_schedule_reboot(void *arg) +{ + struct cwmp *cwmp = (struct cwmp *)arg; + time_t remaining_time = cwmp->conf.schedule_reboot - time(NULL); + + CWMP_LOG(INFO, "The device will reboot after %ld seconds", remaining_time); + sleep(remaining_time); + uci_set_value(UCI_CPE_SCHEDULE_REBOOT, "0001-01-01T00:00:00Z", CWMP_CMD_SET); + + /* check if the session is running before calling reboot method */ + /* if the session is in progress, wait until the end of the session */ + /* else calling reboot method */ + if (cwmp->session_status.last_status == SESSION_RUNNING) { + cwmp_set_end_session(END_SESSION_REBOOT); + } else { + cwmp_reboot("schedule_reboot"); + exit(EXIT_SUCCESS); + } + + return NULL; +} + +static void create_schedule_reboot_thread(struct cwmp *cwmp, bool thread_exist) +{ + if (thread_exist) { + CWMP_LOG(INFO, "There is already a schedule reboot thread!, Cancel the current thread"); + + pthread_cancel(delay_schedule_thread); + create_schedule_reboot_thread(cwmp, false); + } else { + CWMP_LOG(INFO, "Create a schedule reboot thread"); + + if (pthread_create(&delay_schedule_thread, NULL, &thread_schedule_reboot, (void *)cwmp)) { + CWMP_LOG(ERROR, "Error when creating the schedule reboot thread!"); + } + + if (pthread_detach(delay_schedule_thread)) { + CWMP_LOG(ERROR, "Error when detaching the schedule reboot thread!"); + } + } +} + +void launch_reboot_methods(struct cwmp *cwmp) +{ + static int curr_delay_reboot = -1; + static time_t curr_schedule_redoot = 0; + + if (cwmp->conf.delay_reboot != curr_delay_reboot && cwmp->conf.delay_reboot > 0) { + + create_delay_reboot_thread(cwmp, (curr_delay_reboot != -1)); + curr_delay_reboot = cwmp->conf.delay_reboot; + } + + if (cwmp->conf.schedule_reboot != curr_schedule_redoot && (cwmp->conf.schedule_reboot - time(NULL)) > 0) { + + create_schedule_reboot_thread(cwmp, (curr_schedule_redoot != 0)); + curr_schedule_redoot = cwmp->conf.schedule_reboot; + } +} diff --git a/session.c b/session.c index 6826cda..75c5581 100644 --- a/session.c +++ b/session.c @@ -18,7 +18,7 @@ unsigned int end_session_flag = 0; void cwmp_set_end_session(unsigned int flag) -{ // +{ end_session_flag |= flag; }