Ticket refs #6914: icwmp: migrate from multithreading to uloop

This commit is contained in:
Omar Kallel 2022-03-10 13:47:52 +01:00
parent 8fe0cf54ea
commit 1fbefe8b45
78 changed files with 3197 additions and 3029 deletions

10
.gitignore vendored
View file

@ -2,10 +2,8 @@
*.swo
*.o
*.lo
*.log
*.xml
*.so
bin/*
/icwmpd
!bin/Makefile.am
.prepared*
.built*
@ -14,6 +12,7 @@ bin/*
ABOUT-NLS
INSTALL
Makefile.in
/Makefile
aclocal.m4
autom4te.cache/
compile
@ -35,5 +34,6 @@ missing
/ltmain.sh
*.gcno
*.gcda
/icwmpd
/Makefile
/*.log
/*.xml
/report

View file

@ -4,8 +4,8 @@ include:
variables:
DEBUG: 'TRUE'
COMMON_IMAGE: "iopsys/code-analysis:0.27"
RUN_CPPCHECK: "cppcheck --force --enable=all --error-exitcode=1 -D_GNU_SOURCE --include=/usr/include/libubox/list.h --include=/usr/include/uci.h -I ./inc --suppress=unusedFunction -i ./test/ --inline-suppr"
COMMON_IMAGE: "iopsys/code-analysis:0.25"
RUN_CPPCHECK: "cppcheck --enable=all --inline-suppr --include=/usr/include/uci.h --suppress=unusedFunction -i ./test/"
SOURCE_FOLDER: "."
CWMP_WORKER_PROCESSES: 1
NBI_WORKER_PROCESSES: 1
@ -69,4 +69,4 @@ run_functional_test:
- funl-test-coverage.xml
- funl-test-memory-report.xml
- funl-test-result.log
- funl-test-debug.log
- funl-test-debug.log

View file

@ -1,6 +1,6 @@
MAINTAINERCLEANFILES = Makefile.in
CWMP_VERSION = 3.0.1
CWMP_VERSION = 3.0.2
bin_PROGRAMS = icwmpd
@ -10,12 +10,15 @@ icwmpd_SOURCES = \
./log.c \
./cwmp_uci.c \
./config.c \
./cwmp_config.c \
./session.c \
./backupSession.c \
./md5.c \
./digestauth.c \
./event.c \
./cwmp_event.c \
./http.c \
./cwmp_http.c \
./netlink.c \
./ubus.c \
./datamodel_interface.c \
@ -23,15 +26,16 @@ icwmpd_SOURCES = \
./notifications.c \
./cwmp_zlib.c \
./cwmp_du_state.c \
./subprocess.c \
./download.c \
./upload.c \
./sched_inform.c \
./xml.c \
./rpc_soap.c \
./soap.c \
./diagnostic.c \
./reboot.c \
./cwmp.c \
./ssl_utils.c
./ssl_utils.c \
./cwmp.c
icwmpd_CFLAGS = \
$(AM_CFLAGS) \
@ -40,7 +44,7 @@ icwmpd_CFLAGS = \
$(LIBUBUS_CFLAGS) \
$(MICROXML_CFLAGS) \
$(LIBCURL_CFLAGS) \
-Wall -Wextra \
-g -Wall -Wextra \
-Wformat
icwmpd_LDFLAGS = \

View file

@ -11,16 +11,18 @@
*/
#include <unistd.h>
#include <fcntl.h>
#include "backupSession.h"
#include "log.h"
#include "event.h"
#include "sched_inform.h"
#include "download.h"
#include "upload.h"
#include "cwmp_du_state.h"
#include "notifications.h"
#include "xml.h"
#include "event.h"
#include "download.h"
#include "cwmp_du_state.h"
#include "soap.h"
#include "upload.h"
#include "sched_inform.h"
#include "cwmp_event.h"
static mxml_node_t *bkp_tree = NULL;
pthread_mutex_t mutex_backup_session = PTHREAD_MUTEX_INITIALIZER;
@ -445,82 +447,9 @@ void bkp_session_insert_schedule_download(struct download *pschedule_download)
pthread_mutex_unlock(&mutex_backup_session);
}
void bkp_session_insert_apply_schedule_download(struct apply_schedule_download *papply_schedule_download)
{
char delay[4][128];
int i;
char maxretrie[2][128];
mxml_node_t *b;
pthread_mutex_lock(&mutex_backup_session);
for (i = 0; i < 2; i++) {
snprintf(delay[2 * i], sizeof(delay[i]), "%lld", (long long int)papply_schedule_download->timeintervals[i].windowstart);
snprintf(delay[2 * i + 1], sizeof(delay[i]), "%lld", (long long int)papply_schedule_download->timeintervals[i].windowend);
snprintf(maxretrie[i], sizeof(maxretrie[i]), "%d", papply_schedule_download->timeintervals[i].maxretries);
}
struct search_keywords sched_download_insert_app_keys[9] = { { "command_key", papply_schedule_download->command_key },
{ "file_type", papply_schedule_download->file_type },
{ "start_time", papply_schedule_download->start_time },
{ "windowstart1", delay[0] },
{ "windowend1", delay[1] },
{ "maxretrie1", maxretrie[0] },
{ "windowstart2", delay[2] },
{ "windowend2", delay[3] },
{ "maxretrie2", maxretrie[1] } };
b = bkp_session_node_found(bkp_tree, "apply_schedule_download", sched_download_insert_app_keys, 9);
if (!b) {
CWMP_LOG(INFO, "New schedule download key %s file", papply_schedule_download->command_key);
b = bkp_session_insert(bkp_tree, "apply_schedule_download", NULL);
bkp_session_insert(b, "start_time", papply_schedule_download->start_time);
bkp_session_insert(b, "command_key", papply_schedule_download->command_key);
bkp_session_insert(b, "file_type", papply_schedule_download->file_type);
bkp_session_insert(b, "windowstart1", delay[0]);
bkp_session_insert(b, "windowend1", delay[1]);
bkp_session_insert(b, "maxretrie1", maxretrie[0]);
bkp_session_insert(b, "windowstart2", delay[2]);
bkp_session_insert(b, "windowend2", delay[3]);
bkp_session_insert(b, "maxretrie2", maxretrie[1]);
}
pthread_mutex_unlock(&mutex_backup_session);
}
void bkp_session_delete_apply_schedule_download(struct apply_schedule_download *ps_download) //TODO
{
char delay[4][128];
char maxretrie[2][128];
int i;
mxml_node_t *b;
pthread_mutex_lock(&mutex_backup_session);
for (i = 0; i < 2; i++) {
snprintf(delay[2 * i], sizeof(delay[i]), "%lld", (long long int)ps_download->timeintervals[i].windowstart);
snprintf(delay[2 * i + 1], sizeof(delay[i]), "%lld", (long long int)ps_download->timeintervals[i].windowend);
snprintf(maxretrie[i], sizeof(maxretrie[i]), "%d", ps_download->timeintervals[i].maxretries);
}
struct search_keywords sched_download_del_app_keys[9] = { { "start_time", ps_download->start_time },
{ "command_key", ps_download->command_key },
{ "file_type", ps_download->file_type },
{ "windowstart1", delay[0] },
{ "windowend1", delay[1] },
{ "maxretrie1", maxretrie[0] },
{ "windowstart2", delay[2] },
{ "windowend2", delay[3] },
{ "maxretrie2", maxretrie[1] } };
b = bkp_session_node_found(bkp_tree, "apply_schedule_download", sched_download_del_app_keys, 9);
if (b)
mxmlDelete(b);
pthread_mutex_unlock(&mutex_backup_session);
}
void bkp_session_insert_change_du_state(struct change_du_state *pchange_du_state)
{
struct operations *p;
struct operations *p = NULL;
char schedule_time[128];
mxml_node_t *b, *n;
@ -529,6 +458,7 @@ void bkp_session_insert_change_du_state(struct change_du_state *pchange_du_state
b = bkp_session_insert(bkp_tree, "change_du_state", NULL);
bkp_session_insert(b, "command_key", pchange_du_state->command_key);
bkp_session_insert(b, "time", schedule_time);
list_for_each_entry (p, &(pchange_du_state->list_operation), list) {
if (p->type == DU_INSTALL) {
n = bkp_session_insert(b, "install", NULL);
@ -661,7 +591,7 @@ void bkp_session_delete_upload(struct upload *pupload)
void bkp_session_insert_du_state_change_complete(struct du_state_change_complete *pdu_state_change_complete)
{
char schedule_time[128], resolved[8], fault_code[8];
struct opresult *p;
struct opresult *p = NULL;
mxml_node_t *b;
pthread_mutex_lock(&mutex_backup_session);
@ -751,11 +681,9 @@ void bkp_session_delete_transfer_complete(struct transfer_complete *ptransfer_co
pthread_mutex_unlock(&mutex_backup_session);
}
int save_acs_bkp_config(struct cwmp *cwmp)
int save_acs_bkp_config()
{
struct config *conf;
conf = &(cwmp->conf);
struct config *conf = &(cwmp_main->conf);
bkp_session_simple_insert("acs", "url", conf->acsurl);
bkp_session_save();
return CWMP_OK;
@ -783,11 +711,11 @@ char *load_child_value(mxml_node_t *tree, char *sub_name)
return value;
}
void load_queue_event(mxml_node_t *tree, struct cwmp *cwmp)
void load_queue_event(mxml_node_t *tree)
{
char *command_key = NULL;
mxml_node_t *b = tree, *c;
int idx = -1, id = -1;
int idx, id = -1;
struct event_container *event_container_save = NULL;
struct backup_attributes bkp_attrs = { .index = &idx, .id = &id, .command_key = &command_key };
@ -798,14 +726,10 @@ void load_queue_event(mxml_node_t *tree, struct cwmp *cwmp)
while (b) {
if (b->type == MXML_ELEMENT) {
if (strcmp(b->value.element.name, "command_key") == 0) {
/*
* This condition is not always false.
* while the value of idx can be changed while call of load_specific_backup_attributes.
*/
// cppcheck-suppress knownConditionTrueFalse
if (idx != -1) {
if (EVENT_CONST[idx].RETRY & EVENT_RETRY_AFTER_REBOOT) {
event_container_save = cwmp_add_event_container(cwmp, idx, ((command_key != NULL) ? command_key : ""));
event_container_save = cwmp_add_event_container(idx, ((command_key != NULL) ? command_key : ""));
if (event_container_save != NULL) {
event_container_save->id = id;
}
@ -832,7 +756,7 @@ void load_schedule_inform(mxml_node_t *tree)
char *command_key = NULL;
time_t scheduled_time = 0;
struct schedule_inform *schedule_inform = NULL;
struct list_head *ilist;
struct list_head *ilist = NULL;
struct backup_attributes bkp_attrs = { .command_key = &command_key, .time = &scheduled_time };
load_specific_backup_attributes(tree, &bkp_attrs);
@ -867,6 +791,7 @@ void load_download(mxml_node_t *tree)
.file_size = &download_request->file_size,
.time = &download_request->scheduled_time };
load_specific_backup_attributes(tree, &bkp_attrs);
download_request->handler_timer.cb = cwmp_start_download;
list_for_each (ilist, &(list_download)) {
idownload_request = list_entry(ilist, struct download, list);
@ -877,6 +802,7 @@ void load_download(mxml_node_t *tree)
list_add(&(download_request->list), ilist->prev);
if (download_request->scheduled_time != 0)
count_download_queue++;
cwmp_set_end_session(END_SESSION_DOWNLOAD);
}
void load_schedule_download(mxml_node_t *tree)
@ -918,30 +844,6 @@ void load_schedule_download(mxml_node_t *tree)
count_download_queue++;
}
void load_apply_schedule_download(mxml_node_t *tree)
{
struct apply_schedule_download *download_request = NULL;
download_request = calloc(1, sizeof(struct apply_schedule_download));
struct backup_attributes bkp_attrs = {
.command_key = &download_request->command_key,
.file_type = &download_request->file_type,
.start_time = &download_request->start_time,
.windowstart1 = &download_request->timeintervals[0].windowstart,
.windowend1 = &download_request->timeintervals[0].windowend,
.maxretrie1 = &download_request->timeintervals[0].maxretries,
.windowstart2 = &download_request->timeintervals[1].windowstart,
.windowend2 = &download_request->timeintervals[1].windowend,
.maxretrie2 = &download_request->timeintervals[1].maxretries,
};
load_specific_backup_attributes(tree, &bkp_attrs);
list_add_tail(&(download_request->list), &(list_apply_schedule_download));
if (download_request->timeintervals[0].windowstart != 0)
count_download_queue++;
}
void load_upload(mxml_node_t *tree)
{
struct upload *upload_request = NULL;
@ -1006,7 +908,7 @@ void load_change_du_state(mxml_node_t *tree)
list_add_tail(&(change_du_state_request->list_operation), &(list_change_du_state));
}
void load_du_state_change_complete(mxml_node_t *tree, struct cwmp *cwmp)
void load_du_state_change_complete(mxml_node_t *tree)
{
mxml_node_t *b = tree;
struct du_state_change_complete *du_state_change_complete_request = NULL;
@ -1040,10 +942,10 @@ void load_du_state_change_complete(mxml_node_t *tree, struct cwmp *cwmp)
}
b = mxmlWalkNext(b, tree, MXML_NO_DESCEND);
}
cwmp_root_cause_changedustate_complete(cwmp, du_state_change_complete_request);
cwmp_root_cause_changedustate_complete(du_state_change_complete_request);
}
void load_transfer_complete(mxml_node_t *tree, struct cwmp *cwmp)
void load_transfer_complete(mxml_node_t *tree)
{
struct transfer_complete *ptransfer_complete;
@ -1057,8 +959,8 @@ void load_transfer_complete(mxml_node_t *tree, struct cwmp *cwmp)
.type = &ptransfer_complete->type };
load_specific_backup_attributes(tree, &bkp_attrs);
cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete);
sotfware_version_value_change(cwmp, ptransfer_complete);
cwmp_root_cause_transfer_complete(ptransfer_complete);
sotfware_version_value_change(ptransfer_complete);
}
void bkp_session_create_file()
@ -1103,16 +1005,16 @@ int bkp_session_check_file()
return 0;
}
int cwmp_init_backup_session(struct cwmp *cwmp, char **ret, enum backup_loading load)
int cwmp_init_backup_session(char **ret, enum backup_loading load)
{
int error;
if (bkp_session_check_file())
return 0;
error = cwmp_load_saved_session(cwmp, ret, load);
error = cwmp_load_saved_session(ret, load);
return error;
}
int cwmp_load_saved_session(struct cwmp *cwmp, char **ret, enum backup_loading load)
int cwmp_load_saved_session(char **ret, enum backup_loading load)
{
mxml_node_t *b;
@ -1145,23 +1047,21 @@ int cwmp_load_saved_session(struct cwmp *cwmp, char **ret, enum backup_loading l
}
if (load == ALL) {
if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "queue_event") == 0) {
load_queue_event(b, cwmp);
load_queue_event(b);
} else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "download") == 0) {
load_download(b);
} else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "upload") == 0) {
load_upload(b);
} else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "transfer_complete") == 0) {
load_transfer_complete(b, cwmp);
load_transfer_complete(b);
} else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "schedule_inform") == 0) {
load_schedule_inform(b);
} else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "change_du_state") == 0) {
load_change_du_state(b);
} else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "du_state_change_complete") == 0) {
load_du_state_change_complete(b, cwmp);
load_du_state_change_complete(b);
} else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "schedule_download") == 0) {
load_schedule_download(b);
} else if (b->type == MXML_ELEMENT && strcmp(b->value.element.name, "apply_schedule_download") == 0) {
load_apply_schedule_download(b);
}
}
b = mxmlWalkNext(b, bkp_tree, MXML_NO_DESCEND);

149
common.c
View file

@ -8,35 +8,38 @@
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*
*/
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <getopt.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <curl/curl.h>
#include <unistd.h>
#include <sys/reboot.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/file.h>
#include <regex.h>
#include "common.h"
#include "cwmp_cli.h"
#include "cwmp_uci.h"
#include "ubus.h"
#include "log.h"
#include "cwmp_cli.h"
#include "cwmp_du_state.h"
#include "ssl_utils.h"
#ifndef CWMP_REVISION
#define CWMP_REVISION "8.2.10"
#endif
char *commandKey = NULL;
bool thread_end = false;
bool signal_exit = false;
bool cwmp_stop = false;
bool ubus_exit = false;
long int flashsize = 256000000;
struct cwmp cwmp_main = { 0 };
struct cwmp *cwmp_main = NULL;
static int nbre_services = 0;
static char *list_services[MAX_NBRE_SERVICES] = { 0 };
bool g_firewall_restart = false;
LIST_HEAD(cwmp_memory_list);
extern bool g_firewall_restart;
struct cwmp_mem {
struct list_head list;
@ -51,51 +54,33 @@ struct option cwmp_long_options[] = {
struct FAULT_CPE FAULT_CPE_ARRAY[] = {
[FAULT_CPE_METHOD_NOT_SUPPORTED] = { "9000", FAULT_9000, FAULT_CPE_TYPE_SERVER, "Method not supported" },
[FAULT_CPE_REQUEST_DENIED] = { "9001", FAULT_9001, FAULT_CPE_TYPE_SERVER,
"Request denied (no reason specified)" },
[FAULT_CPE_REQUEST_DENIED] = { "9001", FAULT_9001, FAULT_CPE_TYPE_SERVER, "Request denied (no reason specified)" },
[FAULT_CPE_INTERNAL_ERROR] = { "9002", FAULT_9002, FAULT_CPE_TYPE_SERVER, "Internal error" },
[FAULT_CPE_INVALID_ARGUMENTS] = { "9003", FAULT_9003, FAULT_CPE_TYPE_CLIENT, "Invalid arguments" },
[FAULT_CPE_RESOURCES_EXCEEDED] = { "9004", FAULT_9004, FAULT_CPE_TYPE_SERVER, "Resources exceeded" },
[FAULT_CPE_INVALID_PARAMETER_NAME] = { "9005", FAULT_9005, FAULT_CPE_TYPE_CLIENT, "Invalid parameter name" },
[FAULT_CPE_INVALID_PARAMETER_TYPE] = { "9006", FAULT_9006, FAULT_CPE_TYPE_CLIENT, "Invalid parameter type" },
[FAULT_CPE_INVALID_PARAMETER_VALUE] = { "9007", FAULT_9007, FAULT_CPE_TYPE_CLIENT, "Invalid parameter value" },
[FAULT_CPE_NON_WRITABLE_PARAMETER] = { "9008", FAULT_9008, FAULT_CPE_TYPE_CLIENT,
"Attempt to set a non-writable parameter" },
[FAULT_CPE_NOTIFICATION_REJECTED] = { "9009", FAULT_9009, FAULT_CPE_TYPE_SERVER,
"Notification request rejected" },
[FAULT_CPE_NON_WRITABLE_PARAMETER] = { "9008", FAULT_9008, FAULT_CPE_TYPE_CLIENT, "Attempt to set a non-writable parameter" },
[FAULT_CPE_NOTIFICATION_REJECTED] = { "9009", FAULT_9009, FAULT_CPE_TYPE_SERVER, "Notification request rejected" },
[FAULT_CPE_DOWNLOAD_FAILURE] = { "9010", FAULT_9010, FAULT_CPE_TYPE_SERVER, "Download failure" },
[FAULT_CPE_UPLOAD_FAILURE] = { "9011", FAULT_9011, FAULT_CPE_TYPE_SERVER, "Upload failure" },
[FAULT_CPE_FILE_TRANSFER_AUTHENTICATION_FAILURE] = { "9012", FAULT_9012, FAULT_CPE_TYPE_SERVER,
"File transfer server authentication failure" },
[FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL] = { "9013", FAULT_9013, FAULT_CPE_TYPE_SERVER,
"Unsupported protocol for file transfer" },
[FAULT_CPE_DOWNLOAD_FAIL_MULTICAST_GROUP] = { "9014", FAULT_9014, FAULT_CPE_TYPE_SERVER,
"Download failure: unable to join multicast group" },
[FAULT_CPE_DOWNLOAD_FAIL_CONTACT_SERVER] = { "9015", FAULT_9015, FAULT_CPE_TYPE_SERVER,
"Download failure: unable to contact file server" },
[FAULT_CPE_DOWNLOAD_FAIL_ACCESS_FILE] = { "9016", FAULT_9016, FAULT_CPE_TYPE_SERVER,
"Download failure: unable to access file" },
[FAULT_CPE_DOWNLOAD_FAIL_COMPLETE_DOWNLOAD] = { "9017", FAULT_9017, FAULT_CPE_TYPE_SERVER,
"Download failure: unable to complete download" },
[FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED] = { "9018", FAULT_9018, FAULT_CPE_TYPE_SERVER,
"Download failure: file corrupted" },
[FAULT_CPE_DOWNLOAD_FAIL_FILE_AUTHENTICATION] = { "9019", FAULT_9019, FAULT_CPE_TYPE_SERVER,
"Download failure: file authentication failure" },
[FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW] = { "9020", FAULT_9020, FAULT_CPE_TYPE_SERVER,
"Download failure: unable to complete download" },
[FAULT_CPE_DUPLICATE_DEPLOYMENT_UNIT] = { "9026", FAULT_9026, FAULT_CPE_TYPE_SERVER,
"Duplicate deployment unit" },
[FAULT_CPE_SYSTEM_RESOURCES_EXCEEDED] = { "9027", FAULT_9027, FAULT_CPE_TYPE_SERVER,
"System ressources exceeded" },
[FAULT_CPE_FILE_TRANSFER_AUTHENTICATION_FAILURE] = { "9012", FAULT_9012, FAULT_CPE_TYPE_SERVER, "File transfer server authentication failure" },
[FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL] = { "9013", FAULT_9013, FAULT_CPE_TYPE_SERVER, "Unsupported protocol for file transfer" },
[FAULT_CPE_DOWNLOAD_FAIL_MULTICAST_GROUP] = { "9014", FAULT_9014, FAULT_CPE_TYPE_SERVER, "Download failure: unable to join multicast group" },
[FAULT_CPE_DOWNLOAD_FAIL_CONTACT_SERVER] = { "9015", FAULT_9015, FAULT_CPE_TYPE_SERVER, "Download failure: unable to contact file server" },
[FAULT_CPE_DOWNLOAD_FAIL_ACCESS_FILE] = { "9016", FAULT_9016, FAULT_CPE_TYPE_SERVER, "Download failure: unable to access file" },
[FAULT_CPE_DOWNLOAD_FAIL_COMPLETE_DOWNLOAD] = { "9017", FAULT_9017, FAULT_CPE_TYPE_SERVER, "Download failure: unable to complete download" },
[FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED] = { "9018", FAULT_9018, FAULT_CPE_TYPE_SERVER, "Download failure: file corrupted" },
[FAULT_CPE_DOWNLOAD_FAIL_FILE_AUTHENTICATION] = { "9019", FAULT_9019, FAULT_CPE_TYPE_SERVER, "Download failure: file authentication failure" },
[FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW] = { "9020", FAULT_9020, FAULT_CPE_TYPE_SERVER, "Download failure: unable to complete download" },
[FAULT_CPE_DUPLICATE_DEPLOYMENT_UNIT] = { "9026", FAULT_9026, FAULT_CPE_TYPE_SERVER, "Duplicate deployment unit" },
[FAULT_CPE_SYSTEM_RESOURCES_EXCEEDED] = { "9027", FAULT_9027, FAULT_CPE_TYPE_SERVER, "System ressources exceeded" },
[FAULT_CPE_UNKNOWN_DEPLOYMENT_UNIT] = { "9028", FAULT_9028, FAULT_CPE_TYPE_SERVER, "Unknown deployment unit" },
[FAULT_CPE_INVALID_DEPLOYMENT_UNIT_STATE] = { "9029", FAULT_9029, FAULT_CPE_TYPE_SERVER,
"Invalid deployment unit state" },
[FAULT_CPE_INVALID_DOWNGRADE_REJECTED] = { "9030", FAULT_9030, FAULT_CPE_TYPE_SERVER,
"Invalid deployment unit Update: Downgrade not permitted" },
[FAULT_CPE_INVALID_UPDATE_VERSION_UNSPECIFIED] = { "9031", FAULT_9031, FAULT_CPE_TYPE_SERVER,
"Invalid deployment unit Update: Version not specified" },
[FAULT_CPE_INVALID_UPDATE_VERSION_EXIST] = { "9031", FAULT_9032, FAULT_CPE_TYPE_SERVER,
"Invalid deployment unit Update: Version already exist" }
[FAULT_CPE_INVALID_DEPLOYMENT_UNIT_STATE] = { "9029", FAULT_9029, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit state" },
[FAULT_CPE_INVALID_DOWNGRADE_REJECTED] = { "9030", FAULT_9030, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit Update: Downgrade not permitted" },
[FAULT_CPE_INVALID_UPDATE_VERSION_UNSPECIFIED] = { "9031", FAULT_9031, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit Update: Version not specified" },
[FAULT_CPE_INVALID_UPDATE_VERSION_EXIST] = { "9031", FAULT_9032, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit Update: Version already exist" }
};
static void show_help(void)
@ -289,6 +274,44 @@ void get_firewall_zone_name_by_wan_iface(char *if_wan, char **zone_name)
}
}
int get_firewall_restart_state(char **state)
{
cwmp_uci_reinit();
return uci_get_state_value(UCI_CPE_FIREWALL_RESTART_STATE, state);
}
// wait till firewall restart is not complete or 5 sec, whichever is less
void check_firewall_restart_state()
{
int count = 0;
bool init = false;
do {
char *state = NULL;
if (get_firewall_restart_state(&state) != CWMP_OK)
break;
if (state != NULL && strcmp(state, "init") == 0) {
init = true;
FREE(state);
break;
}
usleep(500 * 1000);
FREE(state);
count++;
} while(count < 10);
// mark the firewall restart as done
g_firewall_restart = false;
if (init == false) { // In case of timeout reset the firewall_restart flag
CWMP_LOG(ERROR, "Firewall restart took longer than usual");
cwmp_uci_set_varstate_value("cwmp", "cpe", "firewall_restart", "init");
cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG);
}
}
/*
* Reboot
*/
@ -688,33 +711,3 @@ int copy_file(char *source_file, char *target_file)
fclose(target);
return 0;
}
void ubus_network_interface_callback(struct ubus_request *req __attribute__((unused)), int type __attribute__((unused)), struct blob_attr *msg)
{
const struct blobmsg_policy p[1] = { { "device", BLOBMSG_TYPE_STRING } };
struct blob_attr *tb[1] = { NULL };
blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg));
if (!tb[0]) {
cwmp_main.conf.interface = NULL;
CWMP_LOG(DEBUG, "CWMP IFACE - interface: NOT FOUND");
return;
}
FREE(cwmp_main.conf.interface);
cwmp_main.conf.interface = strdup(blobmsg_get_string(tb[0]));
CWMP_LOG(DEBUG, "CWMP IFACE - interface: %s", cwmp_main.conf.interface);
}
int get_connection_interface()
{
int e = cwmp_ubus_call("network.interface", "status", CWMP_UBUS_ARGS{ { "interface", { .str_val = cwmp_main.conf.default_wan_iface }, UBUS_String } }, 1, ubus_network_interface_callback, NULL);
if (e != 0) {
CWMP_LOG(INFO, "Get network interface from network.interface ubus method failed. Ubus err code: %d", e);
return -1;
}
if (cwmp_main.conf.interface == NULL) {
CWMP_LOG(INFO, "Not able to get the network interface from network.interface ubus method.");
return -1;
}
return CWMP_OK;
}

View file

@ -9,18 +9,19 @@
* Author Ahmed Zribi <ahmed.zribi@pivasoftware.com>
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include <string.h>
#include <stdlib.h>
#include "config.h"
#include "cwmp_uci.h"
#include "log.h"
#include "reboot.h"
#include "datamodel_interface.h"
#include "ubus.h"
pthread_mutex_t mutex_config_load = PTHREAD_MUTEX_INITIALIZER;
static int check_global_config(struct config *conf)
static int check_global_config()
{
struct config *conf = &(cwmp_main->conf);
if (conf->acsurl == NULL) {
conf->acsurl = strdup(DEFAULT_ACSURL);
}
@ -43,11 +44,13 @@ static time_t convert_datetime_to_timestamp(char *value)
return mktime(&tm);
}
int get_global_config(struct config *conf)
int get_global_config()
{
struct config *conf = &(cwmp_main->conf);
int error, error2, error3;
char *value = NULL, *value2 = NULL, *value3 = NULL;
//cwmp_main->conf.cr_auth_type = AUTH_DIGEST;
if ((error = uci_get_value(UCI_CPE_LOG_FILE_NAME, &value)) == CWMP_OK) {
if (value != NULL) {
log_set_log_file_name(value);
@ -592,46 +595,75 @@ int get_global_config(struct config *conf)
return CWMP_OK;
}
void ubus_network_interface_callback(struct ubus_request *req __attribute__((unused)), int type __attribute__((unused)), struct blob_attr *msg)
{
const struct blobmsg_policy p[1] = { { "device", BLOBMSG_TYPE_STRING } };
struct blob_attr *tb[1] = { NULL };
blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg));
if (!tb[0]) {
cwmp_main->conf.interface = NULL;
CWMP_LOG(DEBUG, "CWMP IFACE - interface: NOT FOUND");
return;
}
FREE(cwmp_main->conf.interface);
cwmp_main->conf.interface = strdup(blobmsg_get_string(tb[0]));
CWMP_LOG(DEBUG, "CWMP IFACE - interface: %s", cwmp_main->conf.interface);
}
int get_connection_interface()
{
int e = cwmp_ubus_call("network.interface", "status", CWMP_UBUS_ARGS{ { "interface", { .str_val = cwmp_main->conf.default_wan_iface }, UBUS_String } }, 1, ubus_network_interface_callback, NULL);
if (e != 0) {
CWMP_LOG(INFO, "Get network interface from network.interface ubus method failed. Ubus err code: %d", e);
return -1;
}
if (cwmp_main->conf.interface == NULL) {
CWMP_LOG(INFO, "Not able to get the network interface from network.interface ubus method.");
return -1;
}
return CWMP_OK;
}
int reload_networking_config()
{
int error;
char *value = NULL;
if ((error = uci_get_value(UCI_CPE_DEFAULT_WAN_IFACE, &value)) == CWMP_OK) {
FREE(cwmp_main.conf.default_wan_iface);
FREE(cwmp_main->conf.default_wan_iface);
if (value != NULL) {
cwmp_main.conf.default_wan_iface = strdup(value);
cwmp_main->conf.default_wan_iface = strdup(value);
FREE(value);
} else {
cwmp_main.conf.default_wan_iface = strdup("wan");
cwmp_main->conf.default_wan_iface = strdup("wan");
}
CWMP_LOG(DEBUG, "CWMP CONFIG - default wan interface: %s", cwmp_main.conf.default_wan_iface ? cwmp_main.conf.default_wan_iface : "");
CWMP_LOG(DEBUG, "CWMP CONFIG - default wan interface: %s", cwmp_main->conf.default_wan_iface ? cwmp_main->conf.default_wan_iface : "");
} else {
return error;
}
if (get_connection_interface() == -1)
if ((error = get_connection_interface()))
return -1;
return CWMP_OK;
}
int global_conf_init(struct cwmp *cwmp)
int global_conf_init()
{
int error = CWMP_OK;
pthread_mutex_lock(&mutex_config_load);
if ((error = get_global_config(&(cwmp->conf))))
if ((error = get_global_config(&(cwmp_main->conf))))
goto end;
if ((error = check_global_config(&(cwmp->conf))))
if ((error = check_global_config(&(cwmp_main->conf))))
goto end;
if ((error = get_connection_interface()))
return -1;
/* Launch reboot methods if needed */
launch_reboot_methods(cwmp);
launch_reboot_methods();
end:
pthread_mutex_unlock(&mutex_config_load);
@ -639,20 +671,11 @@ end:
return error;
}
int cwmp_get_deviceid(struct cwmp *cwmp)
int cwmp_config_reload()
{
cwmp_get_leaf_value("Device.DeviceInfo.Manufacturer", &cwmp->deviceid.manufacturer);
cwmp_get_leaf_value("Device.DeviceInfo.SerialNumber", &cwmp->deviceid.serialnumber);
cwmp_get_leaf_value("Device.DeviceInfo.ProductClass", &cwmp->deviceid.productclass);
cwmp_get_leaf_value("Device.DeviceInfo.ManufacturerOUI", &cwmp->deviceid.oui);
cwmp_get_leaf_value("Device.DeviceInfo.SoftwareVersion", &cwmp->deviceid.softwareversion);
return CWMP_OK;
}
memset(&cwmp_main->env, 0, sizeof(struct env));
int cwmp_config_reload(struct cwmp *cwmp)
{
memset(&cwmp->env, 0, sizeof(struct env));
int err = global_conf_init(cwmp);
int err = global_conf_init();
if (err != CWMP_OK)
return err;

View file

@ -1,4 +1,4 @@
AC_INIT([icwmp], [1.0], [dev@iopsys.eu])
AC_INIT([icwmp], [1.1], [dev@iopsys.eu])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([cwmp.c])
@ -96,9 +96,6 @@ AM_COND_IF([LWOLFSSL], [
AM_COND_IF([LOPENSSL], [
LSSL_LIBS='-lssl'
AC_SUBST([LSSL_LIBS])
], [
LSSL_LIBS='-lwolfssl'
AC_SUBST([LSSL_LIBS])
])
PKG_CHECK_MODULES(LIBCURL, [libcurl])

779
cwmp.c
View file

@ -10,463 +10,51 @@
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include <math.h>
#include <stdlib.h>
#include <pthread.h>
#include <libubox/uloop.h>
#include <sys/file.h>
#include <unistd.h>
#include <fcntl.h>
#include <syslog.h>
#include <sys/file.h>
#include <libubox/uloop.h>
#include "common.h"
#include "ssl_utils.h"
#include "xml.h"
#include "notifications.h"
#include "event.h"
#include "cwmp_uci.h"
#include "log.h"
#include "session.h"
#include "diagnostic.h"
#include "http.h"
#include "rpc_soap.h"
#include "config.h"
#include "backupSession.h"
#include "http.h"
#include "cwmp_http.h"
#include "diagnostic.h"
#include "config.h"
#include "ubus.h"
#include "digestauth.h"
#include "upload.h"
#include "download.h"
#include "sched_inform.h"
#include "datamodel_interface.h"
#include "log.h"
#include "notifications.h"
#include "cwmp_uci.h"
#include "cwmp_du_state.h"
#include "download.h"
#include "upload.h"
#include "sched_inform.h"
#include "digestauth.h"
#include "soap.h"
#include "netlink.h"
#include "cwmp_http.h"
#include "cwmp_config.h"
#include "cwmp_http.h"
static pthread_t periodic_event_thread;
static pthread_t scheduleInform_thread;
static pthread_t change_du_state_thread;
static pthread_t download_thread;
static pthread_t schedule_download_thread;
static pthread_t apply_schedule_download_thread;
static pthread_t upload_thread;
static pthread_t ubus_thread;
static pthread_t http_cr_server_thread;
static pthread_t periodic_check_notify;
static pthread_t signal_handler_thread;
bool g_firewall_restart = false;
static int cwmp_get_retry_interval(struct cwmp *cwmp)
{
unsigned int retry_count = 0;
double min = 0;
double max = 0;
int m = cwmp->conf.retry_min_wait_interval;
int k = cwmp->conf.retry_interval_multiplier;
int exp = cwmp->retry_count_session;
if (exp == 0)
return MAX_INT32;
if (exp > 10)
exp = 10;
min = pow(((double)k / 1000), (double)(exp - 1)) * m;
max = pow(((double)k / 1000), (double)exp) * m;
char *rand = generate_random_string(4);
if (rand) {
unsigned int dividend = (unsigned int)strtoul(rand, NULL, 16);
retry_count = dividend % ((unsigned int)max + 1 - (unsigned int)min) + (unsigned int)min;
free(rand);
}
return (retry_count);
}
static int cwmp_rpc_cpe_handle_message(struct session *session, struct rpc *rpc_cpe)
{
if (xml_prepare_msg_out(session))
return -1;
if (rpc_cpe_methods[rpc_cpe->type].handler(session, rpc_cpe))
return -1;
if (xml_set_cwmp_id_rpc_cpe(session))
return -1;
return 0;
}
static void cwmp_prepare_value_change(struct cwmp *cwmp)
{
struct event_container *event_container;
if (list_value_change.next == &(list_value_change))
return;
pthread_mutex_lock(&(cwmp->mutex_session_queue));
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, "");
if (!event_container)
goto end;
pthread_mutex_lock(&(mutex_value_change));
list_splice_init(&(list_value_change), &(event_container->head_dm_parameter));
pthread_mutex_unlock(&(mutex_value_change));
cwmp_save_event_container(event_container);
end:
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
}
int get_firewall_restart_state(char **state)
{
cwmp_uci_reinit();
return uci_get_state_value(UCI_CPE_FIREWALL_RESTART_STATE, state);
}
// wait till firewall restart is not complete or 5 sec, whichever is less
void check_firewall_restart_state()
{
int count = 0;
bool init = false;
do {
char *state = NULL;
if (get_firewall_restart_state(&state) != CWMP_OK)
break;
if (state != NULL && strcmp(state, "init") == 0) {
init = true;
FREE(state);
break;
}
usleep(500 * 1000);
FREE(state);
count++;
} while(count < 10);
// mark the firewall restart as done
g_firewall_restart = false;
if (init == false) { // In case of timeout reset the firewall_restart flag
CWMP_LOG(ERROR, "Firewall restart took longer than usual");
cwmp_uci_set_varstate_value("cwmp", "cpe", "firewall_restart", "init");
cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG);
}
}
static int cwmp_schedule_rpc(struct cwmp *cwmp, struct session *session)
{
struct list_head *ilist;
struct rpc *rpc_acs, *rpc_cpe;
if (http_client_init(cwmp) || thread_end) {
CWMP_LOG(INFO, "Initializing http client failed");
goto retry;
}
while (1) {
list_for_each (ilist, &(session->head_rpc_acs)) {
rpc_acs = list_entry(ilist, struct rpc, list);
if (!rpc_acs->type || thread_end)
goto retry;
CWMP_LOG(INFO, "Preparing the %s RPC message to send to the ACS", rpc_acs_methods[rpc_acs->type].name);
if (rpc_acs_methods[rpc_acs->type].prepare_message(cwmp, session, rpc_acs) || thread_end)
goto retry;
if (xml_set_cwmp_id(session) || thread_end)
goto retry;
CWMP_LOG(INFO, "Send the %s RPC message to the ACS", rpc_acs_methods[rpc_acs->type].name);
if (xml_send_message(cwmp, session, rpc_acs) || thread_end)
goto retry;
CWMP_LOG(INFO, "Get the %sResponse message from the ACS", rpc_acs_methods[rpc_acs->type].name);
/*
* This condition is not always false.
* while the value of idx can be changed to true in the exit of icwmp.
*/
// cppcheck-suppress knownConditionTrueFalse
if (rpc_acs_methods[rpc_acs->type].parse_response || thread_end)
if (rpc_acs_methods[rpc_acs->type].parse_response(cwmp, session, rpc_acs))
goto retry;
ilist = ilist->prev;
if (rpc_acs_methods[rpc_acs->type].extra_clean != NULL)
rpc_acs_methods[rpc_acs->type].extra_clean(session, rpc_acs);
cwmp_session_rpc_destructor(rpc_acs);
MXML_DELETE(session->tree_in);
MXML_DELETE(session->tree_out);
if (session->hold_request || thread_end)
break;
}
// If restart service caused firewall restart, wait for firewall restart to complete
if (g_firewall_restart == true)
check_firewall_restart_state();
CWMP_LOG(INFO, "Send empty message to the ACS");
if (xml_send_message(cwmp, session, NULL) || thread_end)
goto retry;
if (!session->tree_in || thread_end)
goto next;
CWMP_LOG(INFO, "Receive request from the ACS");
if (xml_handle_message(session) || thread_end)
goto retry;
while (session->head_rpc_cpe.next != &(session->head_rpc_cpe)) {
rpc_cpe = list_entry(session->head_rpc_cpe.next, struct rpc, list);
if (!rpc_cpe->type || thread_end)
goto retry;
CWMP_LOG(INFO, "Preparing the %s%s message", rpc_cpe_methods[rpc_cpe->type].name, (rpc_cpe->type != RPC_CPE_FAULT) ? "Response" : "");
if (cwmp_rpc_cpe_handle_message(session, rpc_cpe) || thread_end)
goto retry;
MXML_DELETE(session->tree_in);
CWMP_LOG(INFO, "Send the %s%s message to the ACS", rpc_cpe_methods[rpc_cpe->type].name, (rpc_cpe->type != RPC_CPE_FAULT) ? "Response" : "");
if (xml_send_message(cwmp, session, rpc_cpe) || thread_end)
goto retry;
MXML_DELETE(session->tree_out);
cwmp_session_rpc_destructor(rpc_cpe);
if (!session->tree_in || thread_end)
break;
CWMP_LOG(INFO, "Receive request from the ACS");
if (xml_handle_message(session) || thread_end)
goto retry;
}
next:
if (session->head_rpc_acs.next == &(session->head_rpc_acs))
break;
MXML_DELETE(session->tree_in);
MXML_DELETE(session->tree_out);
}
session->error = CWMP_OK;
goto end;
retry:
CWMP_LOG(INFO, "Failed");
session->error = CWMP_RETRY_SESSION;
event_remove_noretry_event_container(session, cwmp);
end:
MXML_DELETE(session->tree_in);
MXML_DELETE(session->tree_out);
http_client_exit();
xml_exit();
return session->error;
}
int run_session_end_func(void)
{
if (end_session_flag & END_SESSION_RESTART_SERVICES) {
CWMP_LOG(INFO, "Restart modified services");
icwmp_restart_services();
}
if (end_session_flag & END_SESSION_RELOAD) {
CWMP_LOG(INFO, "Config reload: end session request");
cwmp_uci_reinit();
cwmp_apply_acs_changes();
}
if (end_session_flag & END_SESSION_INIT_NOTIFY) {
CWMP_LOG(INFO, "SetParameterAttributes end session: reinit list notify");
reinit_list_param_notify();
}
if (end_session_flag & END_SESSION_SET_NOTIFICATION_UPDATE) {
CWMP_LOG(INFO, "SetParameterAttributes/Values end session: update enabled notify file");
cwmp_update_enabled_notify_file();
}
if (end_session_flag & END_SESSION_NSLOOKUP_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing nslookupdiagnostic: end session request");
cwmp_nslookup_diagnostics();
}
if (end_session_flag & END_SESSION_TRACEROUTE_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing traceroutediagnostic: end session request");
cwmp_traceroute_diagnostics();
}
if (end_session_flag & END_SESSION_UDPECHO_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing udpechodiagnostic: end session request");
cwmp_udp_echo_diagnostics();
}
if (end_session_flag & END_SESSION_SERVERSELECTION_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing serverselectiondiagnostic: end session request");
cwmp_serverselection_diagnostics();
}
if (end_session_flag & END_SESSION_IPPING_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing ippingdiagnostic: end session request");
cwmp_ip_ping_diagnostics();
}
if (end_session_flag & END_SESSION_DOWNLOAD_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing download diagnostic: end session request");
cwmp_download_diagnostics();
}
if (end_session_flag & END_SESSION_UPLOAD_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing upload diagnostic: end session request");
cwmp_upload_diagnostics();
}
if (end_session_flag & END_SESSION_REBOOT) {
CWMP_LOG(INFO, "Executing Reboot: end session request");
cwmp_reboot(commandKey);
exit(EXIT_SUCCESS);
}
if (end_session_flag & END_SESSION_FACTORY_RESET) {
CWMP_LOG(INFO, "Executing factory reset: end session request");
cwmp_factory_reset();
exit(EXIT_SUCCESS);
}
if (end_session_flag & END_SESSION_X_FACTORY_RESET_SOFT) {
CWMP_LOG(INFO, "Executing factory reset soft: end session request");
cwmp_factory_reset();
exit(EXIT_SUCCESS);
}
cwmp_uci_exit();
icwmp_cleanmem();
end_session_flag = 0;
return CWMP_OK;
}
static void cwmp_schedule_session(struct cwmp *cwmp)
{
int t;
struct timespec time_to_wait = { 0, 0 };
bool retry = false;
char *exec_download = NULL;
int is_notify = 0;
cwmp->cwmp_cr_event = 0;
while (1) {
struct list_head *ilist;
struct session *session;
int error;
pthread_mutex_lock(&(cwmp->mutex_session_send));
ilist = (&(cwmp->head_session_queue))->next;
while ((ilist == &(cwmp->head_session_queue)) || retry) {
t = cwmp_get_retry_interval(cwmp);
time_to_wait.tv_sec = time(NULL) + t;
CWMP_LOG(INFO, "Waiting the next session");
if (thread_end) {
pthread_mutex_unlock(&(cwmp->mutex_session_send));
return;
}
pthread_cond_timedwait(&(cwmp->threshold_session_send), &(cwmp->mutex_session_send), &time_to_wait);
if (thread_end) {
pthread_mutex_unlock(&(cwmp->mutex_session_send));
return;
}
ilist = (&(cwmp->head_session_queue))->next;
retry = false;
}
cwmp_uci_init();
if (cwmp->session_status.last_status == SESSION_FAILURE)
reload_networking_config();
session = list_entry(ilist, struct session, list);
if (file_exists(DM_ENABLED_NOTIFY)) {
if (!event_exist_in_list(cwmp, EVENT_IDX_4VALUE_CHANGE))
is_notify = check_value_change();
}
if (is_notify > 0 || !file_exists(DM_ENABLED_NOTIFY) || cwmp->custom_notify_active) {
cwmp->custom_notify_active = false;
cwmp_update_enabled_notify_file();
}
cwmp_prepare_value_change(cwmp);
clean_list_value_change();
if ((error = cwmp_move_session_to_session_send(cwmp, session))) {
CWMP_LOG(EMERG, "FATAL error in the mutex process in the session scheduler!");
exit(EXIT_FAILURE);
}
cwmp->session_status.last_end_time = 0;
cwmp->session_status.last_start_time = time(NULL);
cwmp->session_status.last_status = SESSION_RUNNING;
cwmp->session_status.next_retry = 0;
if (file_exists(fc_cookies))
remove(fc_cookies);
CWMP_LOG(INFO, "Start session");
uci_get_value(UCI_CPE_EXEC_DOWNLOAD, &exec_download);
if (exec_download && strcmp(exec_download, "1") == 0) {
CWMP_LOG(INFO, "Firmware downloaded and applied successfully");
cwmp_uci_set_value("cwmp", "cpe", "exec_download", "0");
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
}
FREE(exec_download);
error = cwmp_schedule_rpc(cwmp, session);
CWMP_LOG(INFO, "End session");
if (thread_end) {
event_remove_all_event_container(session, RPC_SEND);
run_session_end_func();
cwmp_session_destructor(session);
pthread_mutex_unlock(&(cwmp->mutex_session_send));
return;
}
if (session->error == CWMP_RETRY_SESSION && (!list_empty(&(session->head_event_container)) || (list_empty(&(session->head_event_container)) && cwmp->cwmp_cr_event == 0))) {
reload_networking_config();
run_session_end_func();
error = cwmp_move_session_to_session_queue(cwmp, session);
CWMP_LOG(INFO, "Retry session, retry count = %d, retry in %ds", cwmp->retry_count_session, cwmp_get_retry_interval(cwmp));
retry = true;
cwmp->session_status.last_end_time = time(NULL);
cwmp->session_status.last_status = SESSION_FAILURE;
cwmp->session_status.next_retry = time(NULL) + cwmp_get_retry_interval(cwmp);
cwmp->session_status.failure_session++;
pthread_mutex_unlock(&(cwmp->mutex_session_send));
continue;
}
event_remove_all_event_container(session, RPC_SEND);
run_session_end_func();
cwmp_session_destructor(session);
cwmp->session_send = NULL;
cwmp->retry_count_session = 0;
cwmp->session_status.last_end_time = time(NULL);
cwmp->session_status.last_status = SESSION_SUCCESS;
cwmp->session_status.next_retry = 0;
cwmp->session_status.success_session++;
pthread_mutex_unlock(&(cwmp->mutex_session_send));
}
}
static void *thread_uloop_run(void *v __attribute__((unused)))
{
cwmp_ubus_init(&cwmp_main);
return NULL;
}
static void *thread_http_cr_server_listen(void *v __attribute__((unused)))
{
http_server_listen();
return NULL;
}
void load_forced_inform_json_file(struct cwmp *cwmp)
void load_forced_inform_json_file()
{
struct blob_buf bbuf;
struct blob_attr *cur;
struct blob_attr *custom_forced_inform_list = NULL;
int rem;
if (cwmp->conf.forced_inform_json_file == NULL || !file_exists(cwmp->conf.forced_inform_json_file))
if (cwmp_main->conf.forced_inform_json_file == NULL || !file_exists(cwmp_main->conf.forced_inform_json_file))
return;
memset(&bbuf, 0, sizeof(struct blob_buf));
blob_buf_init(&bbuf, 0);
if (blobmsg_add_json_from_file(&bbuf, cwmp->conf.forced_inform_json_file) == false) {
CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp->conf.forced_inform_json_file);
if (blobmsg_add_json_from_file(&bbuf, cwmp_main->conf.forced_inform_json_file) == false) {
CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp_main->conf.forced_inform_json_file);
blob_buf_free(&bbuf);
return;
}
@ -474,13 +62,13 @@ void load_forced_inform_json_file(struct cwmp *cwmp)
struct blob_attr *tb[1] = { NULL };
blobmsg_parse(p, 1, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head));
if (tb[0] == NULL) {
CWMP_LOG(WARNING, "The JSON file %s doesn't contain a forced inform parameters list", cwmp->conf.custom_notify_json);
CWMP_LOG(WARNING, "The JSON file %s doesn't contain a forced inform parameters list", cwmp_main->conf.custom_notify_json);
blob_buf_free(&bbuf);
return;
}
custom_forced_inform_list = tb[0];
blobmsg_for_each_attr(cur, custom_forced_inform_list, rem)
{
char parameter_path[128];
@ -502,37 +90,51 @@ void load_forced_inform_json_file(struct cwmp *cwmp)
}
void load_boot_inform_json_file(struct cwmp *cwmp)
void clean_custom_inform_parameters()
{
int i;
for (i=0; i < nbre_custom_inform; i++) {
free(custom_forced_inform_parameters[i]);
custom_forced_inform_parameters[i] = NULL;
}
nbre_custom_inform = 0;
for (i=0; i < nbre_boot_inform; i++) {
free(boot_inform_parameters[i]);
boot_inform_parameters[i] = NULL;
}
nbre_boot_inform = 0;
}
void load_boot_inform_json_file()
{
struct blob_buf bbuf;
struct blob_attr *cur;
struct blob_attr *custom_boot_inform_list = NULL;
int rem;
if (cwmp->conf.boot_inform_json_file == NULL || !file_exists(cwmp->conf.boot_inform_json_file))
if (cwmp_main->conf.boot_inform_json_file == NULL || !file_exists(cwmp_main->conf.boot_inform_json_file))
return;
memset(&bbuf, 0, sizeof(struct blob_buf));
blob_buf_init(&bbuf, 0);
if (blobmsg_add_json_from_file(&bbuf, cwmp->conf.boot_inform_json_file) == false) {
CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp->conf.boot_inform_json_file);
if (blobmsg_add_json_from_file(&bbuf, cwmp_main->conf.boot_inform_json_file) == false) {
CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp_main->conf.boot_inform_json_file);
blob_buf_free(&bbuf);
return;
}
const struct blobmsg_policy p[1] = { { "boot_inform", BLOBMSG_TYPE_ARRAY } };
struct blob_attr *tb[1] = { NULL };
blobmsg_parse(p, 1, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head));
if (tb[0] == NULL) {
CWMP_LOG(WARNING, "The JSON file %s doesn't contain a boot inform parameters list", cwmp->conf.custom_notify_json);
CWMP_LOG(WARNING, "The JSON file %s doesn't contain a boot inform parameters list", cwmp_main->conf.custom_notify_json);
blob_buf_free(&bbuf);
return;
}
custom_boot_inform_list = tb[0];
blobmsg_for_each_attr(cur, custom_boot_inform_list, rem)
{
char parameter_path[128];
@ -554,21 +156,6 @@ void load_boot_inform_json_file(struct cwmp *cwmp)
blob_buf_free(&bbuf);
}
void clean_custom_inform_parameters()
{
int i;
for (i=0; i < nbre_custom_inform; i++) {
free(custom_forced_inform_parameters[i]);
custom_forced_inform_parameters[i] = NULL;
}
nbre_custom_inform = 0;
for (i=0; i < nbre_boot_inform; i++) {
free(boot_inform_parameters[i]);
boot_inform_parameters[i] = NULL;
}
nbre_boot_inform = 0;
}
int create_cwmp_var_state_files()
{
/*
@ -672,11 +259,48 @@ end:
return 0;
}
static int cwmp_init(int argc, char **argv, struct cwmp *cwmp)
int cwmp_apply_acs_changes(void)
{
int error;
if ((error = cwmp_config_reload()))
return error;
if ((error = cwmp_root_cause_events()))
return error;
return CWMP_OK;
}
static void configure_var_state()
{
char *zone_name = NULL;
cwmp_uci_init();
if (!file_exists(VARSTATE_CONFIG"/cwmp"))
creat(VARSTATE_CONFIG"/cwmp", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
cwmp_uci_add_section_with_specific_name("cwmp", "acs", "acs", UCI_VARSTATE_CONFIG);
cwmp_uci_add_section_with_specific_name("cwmp", "cpe", "cpe", UCI_VARSTATE_CONFIG);
get_firewall_zone_name_by_wan_iface(cwmp_main->conf.default_wan_iface, &zone_name);
cwmp_uci_set_varstate_value("cwmp", "acs", "zonename", zone_name ? zone_name : "wan");
cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG);
cwmp_uci_exit();
}
static int cwmp_init(int argc, char **argv)
{
int error;
struct env env;
openlog("cwmp", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
CWMP_LOG(INFO, "STARTING ICWMP with PID :%d", getpid());
cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp));
memset(&env, 0, sizeof(struct env));
if ((error = global_env_init(argc, argv, &env)))
return error;
@ -684,16 +308,12 @@ static int cwmp_init(int argc, char **argv, struct cwmp *cwmp)
error = wait_for_usp_raw_object();
if (error)
return error;
icwmp_init_list_services();
cwmp->event_id = 0;
cwmp->cwmp_period = 0;
cwmp->cwmp_periodic_time = 0;
cwmp->cwmp_periodic_enable = false;
/* Only One instance should run*/
cwmp->pid_file = fopen("/var/run/icwmpd.pid", "w+");
fcntl(fileno(cwmp->pid_file), F_SETFD, fcntl(fileno(cwmp->pid_file), F_GETFD) | FD_CLOEXEC);
int rc = flock(fileno(cwmp->pid_file), LOCK_EX | LOCK_NB);
cwmp_main->pid_file = fopen("/var/run/icwmpd.pid", "w+");
fcntl(fileno(cwmp_main->pid_file), F_SETFD, fcntl(fileno(cwmp_main->pid_file), F_GETFD) | FD_CLOEXEC);
int rc = flock(fileno(cwmp_main->pid_file), LOCK_EX | LOCK_NB);
if (rc) {
if (EWOULDBLOCK != errno) {
char *piderr = "PID file creation failed: Quit the daemon!";
@ -703,207 +323,114 @@ static int cwmp_init(int argc, char **argv, struct cwmp *cwmp)
} else
exit(EXIT_SUCCESS);
}
if (cwmp->pid_file)
fclose(cwmp->pid_file);
if (cwmp_main->pid_file)
fclose(cwmp_main->pid_file);
pthread_mutex_init(&cwmp->mutex_periodic, NULL);
pthread_mutex_init(&cwmp->mutex_session_queue, NULL);
pthread_mutex_init(&cwmp->mutex_session_send, NULL);
memcpy(&(cwmp->env), &env, sizeof(struct env));
INIT_LIST_HEAD(&(cwmp->head_session_queue));
memcpy(&(cwmp_main->env), &env, sizeof(struct env));
if ((error = create_cwmp_var_state_files()))
return error;
cwmp_uci_init();
if ((error = global_conf_init(cwmp)))
if ((error = global_conf_init()))
return error;
cwmp_get_deviceid(cwmp);
load_forced_inform_json_file(cwmp);
load_boot_inform_json_file(cwmp);
load_custom_notify_json(cwmp);
cwmp_get_deviceid();
load_forced_inform_json_file();
load_boot_inform_json_file();
load_custom_notify_json();
init_list_param_notify();
//http_server_init();
create_cwmp_session_structure();
cwmp_uci_exit();
generate_nonce_priv_key();
cwmp_main->start_time = time(NULL);
cwmp_main->start_diagnostics = false;
cwmp_main->event_id = 0;
cwmp_main->cwmp_period = 0;
cwmp_main->cwmp_periodic_time = 0;
cwmp_main->cwmp_periodic_enable = false;
return CWMP_OK;
}
static void cwmp_free(struct cwmp *cwmp)
static void cwmp_exit()
{
FREE(cwmp->deviceid.manufacturer);
FREE(cwmp->deviceid.serialnumber);
FREE(cwmp->deviceid.productclass);
FREE(cwmp->deviceid.oui);
FREE(cwmp->deviceid.softwareversion);
FREE(cwmp->conf.lw_notification_hostname);
FREE(cwmp->conf.ip);
FREE(cwmp->conf.ipv6);
FREE(cwmp->conf.acsurl);
FREE(cwmp->conf.acs_userid);
FREE(cwmp->conf.acs_passwd);
FREE(cwmp->conf.interface);
FREE(cwmp->conf.cpe_userid);
FREE(cwmp->conf.cpe_passwd);
FREE(cwmp->conf.ubus_socket);
FREE(cwmp->conf.connection_request_path);
FREE(cwmp->conf.default_wan_iface);
FREE(cwmp->conf.forced_inform_json_file);
FREE(cwmp->conf.custom_notify_json);
FREE(cwmp->conf.boot_inform_json_file);
pthread_join(http_cr_server_thread, NULL);
FREE(cwmp_main->deviceid.manufacturer);
FREE(cwmp_main->deviceid.serialnumber);
FREE(cwmp_main->deviceid.productclass);
FREE(cwmp_main->deviceid.oui);
FREE(cwmp_main->deviceid.softwareversion);
FREE(cwmp_main->conf.lw_notification_hostname);
FREE(cwmp_main->conf.ip);
FREE(cwmp_main->conf.ipv6);
FREE(cwmp_main->conf.acsurl);
FREE(cwmp_main->conf.acs_userid);
FREE(cwmp_main->conf.acs_passwd);
FREE(cwmp_main->conf.interface);
FREE(cwmp_main->conf.cpe_userid);
FREE(cwmp_main->conf.cpe_passwd);
FREE(cwmp_main->conf.ubus_socket);
FREE(cwmp_main->conf.connection_request_path);
FREE(cwmp_main->conf.default_wan_iface);
FREE(cwmp_main->conf.forced_inform_json_file);
FREE(cwmp_main->conf.custom_notify_json);
FREE(cwmp_main->conf.boot_inform_json_file);
FREE(nonce_privacy_key);
clean_list_param_notify();
bkp_tree_clean();
cwmp_ubus_exit();
clean_custom_inform_parameters();
icwmp_cleanmem();
cwmp_uci_exit();
CWMP_LOG(INFO, "EXIT ICWMP");
closelog();
clean_cwmp_session_structure();
FREE(cwmp_main);
}
static void *thread_cwmp_signal_handler_thread(void *arg)
void cwmp_end_handler(int signal_num __attribute__((unused)))
{
sigset_t *set = (sigset_t *)arg;
for (;;) {
int s, signal_num;
s = sigwait(set, &signal_num);
if (s == -1) {
CWMP_LOG(ERROR, "Error in sigwait");
} else {
CWMP_LOG(INFO, "Catch of Signal(%d)", signal_num);
if (signal_num == SIGINT || signal_num == SIGTERM) {
signal_exit = true;
if (!ubus_exit)
cwmp_ubus_call("tr069", "command", CWMP_UBUS_ARGS{ { "command", { .str_val = "exit" }, UBUS_String } }, 1, NULL, NULL);
break;
}
}
}
return NULL;
}
static void configure_var_state(struct cwmp *cwmp)
{
char *zone_name = NULL;
if (!file_exists(VARSTATE_CONFIG"/cwmp"))
creat(VARSTATE_CONFIG"/cwmp", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
cwmp_uci_reinit();
cwmp_uci_add_section_with_specific_name("cwmp", "acs", "acs", UCI_VARSTATE_CONFIG);
cwmp_uci_add_section_with_specific_name("cwmp", "cpe", "cpe", UCI_VARSTATE_CONFIG);
get_firewall_zone_name_by_wan_iface(cwmp->conf.default_wan_iface, &zone_name);
cwmp_uci_set_varstate_value("cwmp", "acs", "zonename", zone_name ? zone_name : "wan");
cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG);
cwmp_ubus_call("tr069", "exit", CWMP_UBUS_ARGS{ {} }, 0, NULL, NULL);
}
int main(int argc, char **argv)
{
struct cwmp *cwmp = &cwmp_main;
sigset_t set;
int error;
openlog("cwmp", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
if ((error = cwmp_init(argc, argv, cwmp)))
if ((error = cwmp_init(argc, argv)))
return error;
CWMP_LOG(INFO, "STARTING ICWMP with PID :%d", getpid());
cwmp->start_time = time(NULL);
if ((error = cwmp_init_backup_session(cwmp, NULL, ALL)))
if ((error = cwmp_init_backup_session(NULL, ALL)))
return error;
if ((error = cwmp_root_cause_events(cwmp)))
if ((error = cwmp_root_cause_events()))
return error;
configure_var_state(cwmp);
signal(SIGINT, cwmp_end_handler);
signal(SIGTERM, cwmp_end_handler);
configure_var_state();
http_server_init();
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigaddset(&set, SIGTERM);
sigprocmask(SIG_BLOCK, &set, NULL);
uloop_init();
error = pthread_create(&http_cr_server_thread, NULL, &thread_http_cr_server_listen, NULL);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the http connection request server thread!");
}
cwmp_netlink_init();
error = pthread_create(&ubus_thread, NULL, &thread_uloop_run, NULL);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the ubus thread!");
}
cwmp_ubus_init();
error = pthread_create(&periodic_event_thread, NULL, &thread_event_periodic, (void *)cwmp);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the periodic event thread!");
}
trigger_cwmp_session_timer();
error = pthread_create(&periodic_check_notify, NULL, &thread_periodic_check_notify, (void *)cwmp);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the periodic check notify thread!");
}
error = pthread_create(&scheduleInform_thread, NULL, &thread_cwmp_rpc_cpe_scheduleInform, (void *)cwmp);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the scheduled inform thread!");
}
initiate_cwmp_periodic_session_feature();
error = pthread_create(&download_thread, NULL, &thread_cwmp_rpc_cpe_download, (void *)cwmp);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the download thread!");
}
http_server_start();
error = pthread_create(&change_du_state_thread, NULL, &thread_cwmp_rpc_cpe_change_du_state, (void *)cwmp);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the state change thread!");
}
uloop_run();
uloop_done();
error = pthread_create(&schedule_download_thread, NULL, &thread_cwmp_rpc_cpe_schedule_download, (void *)cwmp);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the schedule download thread!");
}
cwmp_exit();
error = pthread_create(&apply_schedule_download_thread, NULL, &thread_cwmp_rpc_cpe_apply_schedule_download, (void *)cwmp);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the schedule download thread!");
}
error = pthread_create(&upload_thread, NULL, &thread_cwmp_rpc_cpe_upload, (void *)cwmp);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the download thread!");
}
error = pthread_create(&signal_handler_thread, NULL, &thread_cwmp_signal_handler_thread, (void *)&set);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the signal handler thread!");
}
cwmp_schedule_session(cwmp);
/* Join all threads */
pthread_join(periodic_event_thread, NULL);
pthread_join(periodic_check_notify, NULL);
pthread_join(scheduleInform_thread, NULL);
pthread_join(download_thread, NULL);
pthread_join(upload_thread, NULL);
pthread_join(schedule_download_thread, NULL);
pthread_join(apply_schedule_download_thread, NULL);
pthread_join(change_du_state_thread, NULL);
pthread_join(http_cr_server_thread, NULL);
pthread_join(ubus_thread, NULL);
pthread_join(signal_handler_thread, NULL);
/* Free all memory allocation */
cwmp_free(cwmp);
CWMP_LOG(INFO, "EXIT ICWMP");
closelog();
return CWMP_OK;
}

View file

@ -8,13 +8,13 @@
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include <string.h>
#include <stdio.h>
#include "common.h"
#include "cwmp_cli.h"
#include "datamodel_interface.h"
#include "cwmp_uci.h"
#include "notifications.h"
#include "cwmp_cli.h"
#include "cwmp_uci.h"
LIST_HEAD(parameters_list);
@ -64,7 +64,7 @@ void display_get_cmd_result(struct cmd_input in __attribute__((unused)), union c
fprintf(stderr, "Fault %s: %s\n", fault, get_fault_message_by_fault_code(fault));
return;
}
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
list_for_each_entry (param_value, res.param_list, list) {
fprintf(stdout, "%s => %s\n", param_value->name, param_value->value);
}
@ -89,7 +89,7 @@ char *cmd_set_exec_func(struct cmd_input in, union cmd_result *res __attribute__
int fault_idx = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_key", &flag, &faults_list);
cwmp_free_all_dm_parameter_list(&list_set_param_value);
if (fault_idx != FAULT_CPE_NO_FAULT) {
struct cwmp_param_fault *param_fault;
struct cwmp_param_fault *param_fault = NULL;
char fault[5] = {0};
list_for_each_entry (param_fault, &faults_list, list) {
snprintf(fault, sizeof(fault), "%d", param_fault->fault);
@ -204,7 +204,7 @@ void display_get_notif_cmd_result(struct cmd_input in __attribute__((unused)), u
fprintf(stderr, "Fault %s: %s\n", fault, get_fault_message_by_fault_code(fault));
return;
}
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
list_for_each_entry (param_value, res.param_list, list) {
fprintf(stdout, "%s => %s\n", param_value->name, param_value->notification == 2 ? "active" : param_value->notification == 1 ? "passive" : "off");
}
@ -266,7 +266,7 @@ void display_get_names_cmd_result(struct cmd_input in __attribute__((unused)), u
fprintf(stderr, "Fault %s: %s\n", fault, get_fault_message_by_fault_code(fault));
return;
}
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
list_for_each_entry (param_value, res.param_list, list) {
fprintf(stdout, "%s => %s\n", param_value->name, param_value->writable ? "writable" : "not-writable");
}

22
cwmp_config.c Normal file
View file

@ -0,0 +1,22 @@
/*
* 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) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*
*/
#include "cwmp_config.h"
#include "datamodel_interface.h"
int cwmp_get_deviceid()
{
cwmp_get_leaf_value("Device.DeviceInfo.Manufacturer", &cwmp_main->deviceid.manufacturer);
cwmp_get_leaf_value("Device.DeviceInfo.SerialNumber", &cwmp_main->deviceid.serialnumber);
cwmp_get_leaf_value("Device.DeviceInfo.ProductClass", &cwmp_main->deviceid.productclass);
cwmp_get_leaf_value("Device.DeviceInfo.ManufacturerOUI", &cwmp_main->deviceid.oui);
cwmp_get_leaf_value("Device.DeviceInfo.SoftwareVersion", &cwmp_main->deviceid.softwareversion);
return CWMP_OK;
}

View file

@ -8,15 +8,16 @@
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include <stdio.h>
#include <libubox/blobmsg_json.h>
#include <stdlib.h>
#include "cwmp_du_state.h"
#include "common.h"
#include "ubus.h"
#include "cwmp_du_state.h"
#include "log.h"
#include "datamodel_interface.h"
#include "cwmp_time.h"
#include "backupSession.h"
#include "cwmp_time.h"
#include "datamodel_interface.h"
#include "event.h"
LIST_HEAD(list_change_du_state);
@ -116,7 +117,7 @@ static char *get_software_module_object_eq(char *param1, char *val1, char *param
if (err)
return NULL;
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
char instance[8];
list_for_each_entry (param_value, sw_parameters, list) {
snprintf(instance, (size_t)(strchr(param_value->name + strlen("Device.SoftwareModules.DeploymentUnit."), '.') - param_value->name - strlen("Device.SoftwareModules.DeploymentUnit.") + 1), "%s", (char *)(param_value->name + strlen("Device.SoftwareModules.DeploymentUnit.")));
@ -137,7 +138,7 @@ static int get_deployment_unit_name_version(char *uuid, char **name, char **vers
snprintf(version_param, sizeof(version_param), "Device.SoftwareModules.DeploymentUnit.%s.Version", sw_by_uuid_instance);
snprintf(environment_param, sizeof(environment_param), "Device.SoftwareModules.DeploymentUnit.%s.ExecutionEnvRef", sw_by_uuid_instance);
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
list_for_each_entry (param_value, &sw_parameters, list) {
if (strcmp(param_value->name, name_param) == 0) {
*name = strdup(param_value->value);
@ -168,7 +169,7 @@ static char *get_softwaremodules_uuid(char *url)
snprintf(uuid_param, sizeof(uuid_param), "Device.SoftwareModules.DeploymentUnit.%s.UUID", sw_by_url_instance);
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
list_for_each_entry (param_value, &sw_parameters, list) {
if (strcmp(param_value->name, uuid_param) == 0) {
uuid = strdup(param_value->value);
@ -190,7 +191,7 @@ static char *get_softwaremodules_url(char *uuid)
snprintf(url_param, sizeof(url_param), "Device.SoftwareModules.DeploymentUnit.%s.URL", sw_by_uuid_instance);
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
list_for_each_entry (param_value, &sw_parameters, list) {
if (strcmp(param_value->name, url_param) == 0) {
url = strdup(param_value->value);
@ -234,7 +235,7 @@ static char *get_exec_env_name(char *environment_path)
if (err)
return strdup("");
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
snprintf(env_param, sizeof(env_param), "%sName", environment_path);
list_for_each_entry (param_value, &environment_list, list) {
if (strcmp(param_value->name, env_param) == 0) {
@ -317,9 +318,8 @@ static int cwmp_launch_du_uninstall(char *package_name, char *package_env, struc
return error;
}
void *thread_cwmp_rpc_cpe_change_du_state(void *v)
void *thread_cwmp_rpc_cpe_change_du_state(void *v __attribute__((unused)))
{
struct cwmp *cwmp = (struct cwmp *)v;
struct timespec change_du_state_timeout = { 50, 0 };
int error = FAULT_CPE_NO_FAULT;
struct du_state_change_complete *pdu_state_change_complete;
@ -336,7 +336,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v)
for (;;) {
if (thread_end)
if (cwmp_stop)
break;
if (list_change_du_state.next != &(list_change_du_state)) {
@ -364,7 +364,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v)
}
bkp_session_insert_du_state_change_complete(pdu_state_change_complete);
bkp_session_save();
cwmp_root_cause_changedustate_complete(cwmp, pdu_state_change_complete);
cwmp_root_cause_changedustate_complete(pdu_state_change_complete);
}
list_del(&(pchange_du_state->list));
cwmp_free_change_du_state_request(pchange_du_state);
@ -373,7 +373,6 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v)
}
if ((timeout >= 0) && (timeout <= time_of_grace)) {
pthread_mutex_lock(&(cwmp->mutex_session_send));
pdu_state_change_complete = calloc(1, sizeof(struct du_state_change_complete));
if (pdu_state_change_complete != NULL) {
error = FAULT_CPE_NO_FAULT;
@ -501,17 +500,13 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v)
bkp_session_save();
bkp_session_insert_du_state_change_complete(pdu_state_change_complete);
bkp_session_save();
cwmp_root_cause_changedustate_complete(cwmp, pdu_state_change_complete);
cwmp_root_cause_changedustate_complete(pdu_state_change_complete);
}
}
pthread_mutex_lock(&mutex_change_du_state);
pthread_cond_timedwait(&threshold_change_du_state, &mutex_change_du_state, &change_du_state_timeout);
pthread_mutex_unlock(&mutex_change_du_state);
pthread_mutex_unlock(&(cwmp->mutex_session_send));
pthread_cond_signal(&(cwmp->threshold_session_send));
pthread_mutex_lock(&mutex_change_du_state);
list_del(&(pchange_du_state->list));
cwmp_free_change_du_state_request(pchange_du_state);
@ -526,7 +521,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v)
return NULL;
}
int cwmp_rpc_acs_destroy_data_du_state_change_complete(struct session *session __attribute__((unused)), struct rpc *rpc)
int cwmp_rpc_acs_destroy_data_du_state_change_complete(struct rpc *rpc)
{
if (rpc->extra_data != NULL) {
struct du_state_change_complete *p;

48
cwmp_event.c Normal file
View file

@ -0,0 +1,48 @@
/*
* 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) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include "cwmp_event.h"
#include "common.h"
#include "session.h"
struct event_container *__cwmp_add_event_container(int event_code, char *command_key)
{
struct event_container *event_container;
list_for_each_entry(event_container, &cwmp_main->session->events, list) {
if (event_container->code == event_code && EVENT_CONST[event_code].TYPE == EVENT_TYPE_SINGLE) {
return event_container;
}
if (event_container->code > event_code) {
break;
}
}
event_container = calloc(1, sizeof(struct event_container));
if (event_container == NULL) {
return NULL;
}
INIT_LIST_HEAD(&(event_container->head_dm_parameter));
list_add_tail(&(event_container->list), &(cwmp_main->session->events));
event_container->code = event_code;
event_container->command_key = command_key ? strdup(command_key) : strdup("");
if ((cwmp_main->event_id < 0) || (cwmp_main->event_id >= MAX_INT_ID)) {
cwmp_main->event_id = 0;
}
cwmp_main->event_id++;
event_container->id = cwmp_main->event_id;
return event_container;
}
struct event_container *cwmp_add_event_container(int event_code, char *command_key)
{
pthread_mutex_lock(&add_event_mutext);
struct event_container *event = __cwmp_add_event_container(event_code, command_key);
pthread_mutex_unlock(&add_event_mutext);
return event;
}

46
cwmp_http.c Normal file
View file

@ -0,0 +1,46 @@
/*
* 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) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include <pthread.h>
#include "common.h"
#include "cwmp_http.h"
#include "http.h"
#include "log.h"
struct uloop_fd http_event6;
pthread_t http_cr_server_thread;
void http_server_listen_uloop(struct uloop_fd *ufd __attribute__((unused)), unsigned events __attribute__((unused)))
{
http_server_listen();
}
void http_server_start_uloop(void)
{
http_server_init();
http_event6.fd = cwmp_main->cr_socket_desc;
http_event6.cb = http_server_listen_uloop;
uloop_fd_add(&http_event6, ULOOP_READ | ULOOP_EDGE_TRIGGER);
}
static void *thread_http_cr_server_listen(void *v __attribute__((unused)))
{
http_server_listen();
return NULL;
}
void http_server_start(void)
{
int error = pthread_create(&http_cr_server_thread, NULL, &thread_http_cr_server_listen, NULL);
if (error < 0) {
CWMP_LOG(ERROR, "Error when creating the http connection request server thread!");
}
}

View file

@ -8,12 +8,9 @@
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "common.h"
#include "cwmp_uci.h"
#include "log.h"
#include "cwmp_uci.h"
struct uci_paths uci_save_conf_paths[] = {
[UCI_STANDARD_CONFIG] = { "/etc/config", "/tmp/.uci", NULL },
@ -216,7 +213,7 @@ int cwmp_uci_get_value_by_section_string(struct uci_section *s, char *option, ch
struct uci_option *o;
*value = NULL;
if (s == NULL || &s->options == NULL || option == NULL)
if (s == NULL || option == NULL)
goto not_found;
uci_foreach_element(&s->options, e)
@ -377,16 +374,14 @@ void cwmp_delete_uci_element_from_list(struct uci_element *e)
void cwmp_free_uci_list(struct uci_list *list)
{
struct uci_element *e = NULL, *tmp = NULL;
if (list == NULL)
return;
uci_foreach_element_safe(list, e, tmp)
uci_foreach_element_safe(list, e, tmp) {
cwmp_delete_uci_element_from_list(e);
}
}
char *cwmp_uci_list_to_string(struct uci_list *list, char *delimitor)
{
if (delimitor == NULL)
return NULL;
if (list && !uci_list_empty(list)) {
struct uci_element *e = NULL;
char list_val[512] = { 0 };
@ -470,10 +465,8 @@ int cwmp_uci_add_list_value(char *package, char *section, char *option, char *va
return UCI_ERR_PARSE;
error = uci_add_list(uci_save_conf_paths[uci_type].uci_ctx, &ptr);
if (error != UCI_OK)
return error;
return UCI_OK;
return error;
}
int cwmp_uci_del_list_value(char *package, char *section, char *option, char *value, uci_config_paths uci_type)
@ -700,7 +693,7 @@ int cwmp_uci_import(char *package_name, const char *input_path, uci_config_paths
{
struct uci_package *package = NULL;
struct uci_element *e = NULL;
int ret = CWMP_OK;
int ret = UCI_OK;
FILE *input = fopen(input_path, "r");
if (!input)
return -1;
@ -710,10 +703,6 @@ int cwmp_uci_import(char *package_name, const char *input_path, uci_config_paths
goto end;
}
if (uci_save_conf_paths[uci_type].uci_ctx == NULL) {
ret = -1;
goto end;
}
uci_foreach_element(&uci_save_conf_paths[uci_type].uci_ctx->root, e)
{
struct uci_package *p = uci_to_package(e);
@ -752,7 +741,7 @@ int cwmp_uci_export(const char *output_path, uci_config_paths uci_type)
char **configs = NULL;
char **p;
if (uci_list_configs(uci_save_conf_paths[uci_type].uci_ctx, &configs) != UCI_OK)
if ((uci_list_configs(uci_save_conf_paths[uci_type].uci_ctx, &configs) != UCI_OK))
return -1;
if (configs == NULL)

View file

@ -9,9 +9,6 @@
*/
#include <zlib.h>
#include <string.h>
#include <stdlib.h>
#include "common.h"
#include "log.h"

View file

@ -8,11 +8,10 @@
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include <libubox/blobmsg_json.h>
#include "datamodel_interface.h"
#include "ubus.h"
#include "log.h"
#include "ubus.h"
#include "notifications.h"
int transaction_id = 0;
@ -292,8 +291,7 @@ void ubus_get_single_parameter_callback(struct ubus_request *req, int type __att
char *cwmp_get_single_parameter_value(char *parameter_name, struct cwmp_dm_parameter *dm_parameter)
{
int e;
struct cwmp *cwmp = &cwmp_main;
e = cwmp_ubus_call(USP_OBJECT_NAME, "get", CWMP_UBUS_ARGS{ { "path", { .str_val = !parameter_name || parameter_name[0] == '\0' ? DM_ROOT_OBJ : parameter_name }, UBUS_String }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 3, ubus_get_single_parameter_callback, dm_parameter);
e = cwmp_ubus_call(USP_OBJECT_NAME, "get", CWMP_UBUS_ARGS{ { "path", { .str_val = !parameter_name || parameter_name[0] == '\0' ? DM_ROOT_OBJ : parameter_name }, UBUS_String }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 3, ubus_get_single_parameter_callback, dm_parameter);
if (e < 0) {
CWMP_LOG(INFO, "get ubus method failed: Ubus err code: %d", e);
return "9002";
@ -368,9 +366,8 @@ void ubus_get_parameter_callback(struct ubus_request *req, int type __attribute_
char *cwmp_get_parameter_values(char *parameter_name, struct list_head *parameters_list)
{
int e;
struct cwmp *cwmp = &cwmp_main;
struct list_params_result get_result = { .parameters_list = parameters_list };
e = cwmp_ubus_call(USP_OBJECT_NAME, "get", CWMP_UBUS_ARGS{ { "path", { .str_val = !parameter_name || parameter_name[0] == '\0' ? DM_ROOT_OBJ : parameter_name }, UBUS_String }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 3, ubus_get_parameter_callback, &get_result);
e = cwmp_ubus_call(USP_OBJECT_NAME, "get", CWMP_UBUS_ARGS{ { "path", { .str_val = !parameter_name || parameter_name[0] == '\0' ? DM_ROOT_OBJ : parameter_name }, UBUS_String }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 3, ubus_get_parameter_callback, &get_result);
if (e < 0) {
CWMP_LOG(INFO, "get ubus method failed: Ubus err code: %d", e);
return "9002";
@ -386,9 +383,8 @@ char *cwmp_get_parameter_values(char *parameter_name, struct list_head *paramete
char *cwmp_get_multiple_parameters_values(struct list_head *arg_params_list, struct list_head *parameters_list)
{
int e;
struct cwmp *cwmp = &cwmp_main;
struct list_params_result get_result = { .parameters_list = parameters_list };
e = cwmp_ubus_call(USP_OBJECT_NAME, "getm_values", CWMP_UBUS_ARGS{ { "paths", { .param_value_list = arg_params_list }, UBUS_List_Param_Get }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 2, ubus_get_parameter_callback, &get_result );
e = cwmp_ubus_call(USP_OBJECT_NAME, "getm_values", CWMP_UBUS_ARGS{ { "paths", { .param_value_list = arg_params_list }, UBUS_List_Param_Get }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 2, ubus_get_parameter_callback, &get_result );
if (e < 0) {
CWMP_LOG(INFO, "getm_values ubus method failed: Ubus err code: %d", e);
return "9002";
@ -405,8 +401,7 @@ char *cwmp_get_parameter_names(char *object_name, bool next_level, struct list_h
{
int e;
struct list_params_result get_result = { .parameters_list = parameters_list };
struct cwmp *cwmp = &cwmp_main;
e = cwmp_ubus_call(USP_OBJECT_NAME, "object_names", CWMP_UBUS_ARGS{ { "path", { .str_val = object_name }, UBUS_String }, { "next-level", { .bool_val = next_level }, UBUS_Bool }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 4, ubus_get_parameter_callback, &get_result);
e = cwmp_ubus_call(USP_OBJECT_NAME, "object_names", CWMP_UBUS_ARGS{ { "path", { .str_val = object_name }, UBUS_String }, { "next-level", { .bool_val = next_level }, UBUS_Bool }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 4, ubus_get_parameter_callback, &get_result);
if (e < 0) {
CWMP_LOG(INFO, "object_names ubus method failed: Ubus err code: %d", e);
return "9002";
@ -457,9 +452,8 @@ int cwmp_set_multiple_parameters_values(struct list_head *parameters_values_list
{
int e;
struct setm_values_res set_result = { .flag = flag, .faults_list = faults_list };
struct cwmp *cwmp = &cwmp_main;
e = cwmp_ubus_call(USP_OBJECT_NAME, "setm_values",
CWMP_UBUS_ARGS{ { "pv_tuple", { .param_value_list = parameters_values_list }, UBUS_List_Param_Set }, { "key", { .str_val = parameter_key }, UBUS_String }, { "transaction_id", { .int_val = transaction_id }, UBUS_Integer }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 5,
CWMP_UBUS_ARGS{ { "pv_tuple", { .param_value_list = parameters_values_list }, UBUS_List_Param_Set }, { "key", { .str_val = parameter_key }, UBUS_String }, { "transaction_id", { .int_val = transaction_id }, UBUS_Integer }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 5,
ubus_setm_values_callback, &set_result);
if (e < 0) {
@ -509,9 +503,8 @@ void ubus_objects_callback(struct ubus_request *req, int type __attribute__((unu
char *cwmp_add_object(char *object_name, char *key, char **instance)
{
int e;
struct cwmp *cwmp = &cwmp_main;
struct object_result add_result = { .instance = instance };
e = cwmp_ubus_call(USP_OBJECT_NAME, "add_object", CWMP_UBUS_ARGS{ { "path", { .str_val = object_name }, UBUS_String }, { "key", { .str_val = key }, UBUS_String }, { "transaction_id", { .int_val = transaction_id }, UBUS_Integer }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 5,
e = cwmp_ubus_call(USP_OBJECT_NAME, "add_object", CWMP_UBUS_ARGS{ { "path", { .str_val = object_name }, UBUS_String }, { "key", { .str_val = key }, UBUS_String }, { "transaction_id", { .int_val = transaction_id }, UBUS_Integer }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 5,
ubus_objects_callback, &add_result);
if (e < 0) {
@ -529,8 +522,7 @@ char *cwmp_delete_object(char *object_name, char *key)
{
int e;
struct object_result add_result = { .instance = NULL };
struct cwmp *cwmp = &cwmp_main;
e = cwmp_ubus_call(USP_OBJECT_NAME, "del_object", CWMP_UBUS_ARGS{ { "path", { .str_val = object_name }, UBUS_String }, { "key", { .str_val = key }, UBUS_String }, { "transaction_id", { .int_val = transaction_id }, UBUS_Integer }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp->conf.instance_mode }, UBUS_Integer } }, 5,
e = cwmp_ubus_call(USP_OBJECT_NAME, "del_object", CWMP_UBUS_ARGS{ { "path", { .str_val = object_name }, UBUS_String }, { "key", { .str_val = key }, UBUS_String }, { "transaction_id", { .int_val = transaction_id }, UBUS_Integer }, { "proto", { .str_val = "cwmp" }, UBUS_String }, { "instance_mode", { .int_val = cwmp_main->conf.instance_mode }, UBUS_Integer } }, 5,
ubus_objects_callback, &add_result);
if (e < 0) {
CWMP_LOG(INFO, "del_object ubus method failed: Ubus err code: %d", e);

View file

@ -9,13 +9,17 @@
* Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
* Author: Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include "common.h"
#include "diagnostic.h"
#include "config.h"
#include "datamodel_interface.h"
#include "ubus.h"
#include "log.h"
#include "cwmp_uci.h"
#include "event.h"
#include "soap.h"
#include "log.h"
struct diagnostic_input {
char *input_name;
@ -165,7 +169,7 @@ int cwmp_download_diagnostics()
return -1;
CWMP_LOG(INFO, "Download diagnostic is successfully executed");
cwmp_root_cause_event_ipdiagnostic();
cwmp_root_cause_event_diagnostic();
return 0;
}
@ -175,7 +179,7 @@ int cwmp_upload_diagnostics()
return -1;
CWMP_LOG(INFO, "Upload diagnostic is successfully executed");
cwmp_root_cause_event_ipdiagnostic();
cwmp_root_cause_event_diagnostic();
return 0;
}
@ -185,7 +189,7 @@ int cwmp_ip_ping_diagnostics()
return -1;
CWMP_LOG(INFO, "IPPing diagnostic is successfully executed");
cwmp_root_cause_event_ipdiagnostic();
cwmp_root_cause_event_diagnostic();
return 0;
}
@ -195,7 +199,7 @@ int cwmp_nslookup_diagnostics()
return -1;
CWMP_LOG(INFO, "Nslookup diagnostic is successfully executed");
cwmp_root_cause_event_ipdiagnostic();
cwmp_root_cause_event_diagnostic();
return 0;
}
@ -205,7 +209,7 @@ int cwmp_traceroute_diagnostics()
return -1;
CWMP_LOG(INFO, "Trace Route diagnostic is successfully executed");
cwmp_root_cause_event_ipdiagnostic();
cwmp_root_cause_event_diagnostic();
return 0;
}
@ -215,7 +219,7 @@ int cwmp_udp_echo_diagnostics()
return -1;
CWMP_LOG(INFO, "UDPEcho diagnostic is successfully executed");
cwmp_root_cause_event_ipdiagnostic();
cwmp_root_cause_event_diagnostic();
return 0;
}
@ -225,6 +229,6 @@ int cwmp_serverselection_diagnostics()
return -1;
CWMP_LOG(INFO, "Server Selection diagnostic is successfully executed");
cwmp_root_cause_event_ipdiagnostic();
cwmp_root_cause_event_diagnostic();
return 0;
}

View file

@ -10,16 +10,16 @@
*
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>
#include "log.h"
#include "common.h"
#include "digestauth.h"
#include "ssl_utils.h"
#include "md5.h"
#include "log.h"
#include "ssl_utils.h"
#define HASH_MD5_HEX_LEN (2 * MD5_DIGEST_SIZE)
@ -329,9 +329,9 @@ int http_digest_auth_fail_response(FILE *fp, const char *http_method, const char
*/
int http_digest_auth_check(const char *http_method, const char *url, const char *header, const char *realm, const char *username, const char *password, unsigned int nonce_timeout)
{
size_t len;
size_t len = 0;
char *end;
char nonce[MAX_NONCE_LENGTH];
char nonce[MAX_NONCE_LENGTH] = {0};
size_t left; /* number of characters left in 'header' for 'uri' */
DD(DEBUG, "%s: header: %s", __FUNCTION__, header);
@ -339,7 +339,7 @@ int http_digest_auth_check(const char *http_method, const char *url, const char
left = strlen(header);
{
char un[MAX_USERNAME_LENGTH];
char un[MAX_USERNAME_LENGTH] = {0};
len = lookup_sub_value(un, sizeof(un), header, "username");
if (0 != strcmp(username, un))
@ -348,7 +348,7 @@ int http_digest_auth_check(const char *http_method, const char *url, const char
}
{
char r[MAX_REALM_LENGTH];
char r[MAX_REALM_LENGTH] = {0};
len = lookup_sub_value(r, sizeof(r), header, "realm");
if ((0 == len) || (0 != strcmp(realm, r)))
@ -362,13 +362,14 @@ int http_digest_auth_check(const char *http_method, const char *url, const char
{
char uri[left];
char cnonce[MAX_NONCE_LENGTH];
char qop[15]; /* auth,auth-int */
char nc[20];
char response[MAX_AUTH_RESPONSE_LENGTH];
char ha1[HASH_MD5_HEX_LEN + 1];
char respexp[HASH_MD5_HEX_LEN + 1];
char noncehashexp[HASH_MD5_HEX_LEN + 9];
memset( uri, 0, sizeof(uri) );
char cnonce[MAX_NONCE_LENGTH] = {0};
char qop[15] = {0}; /* auth,auth-int */
char nc[20] = {0};
char response[MAX_AUTH_RESPONSE_LENGTH] = {0};
char ha1[HASH_MD5_HEX_LEN + 1] = {0};
char respexp[HASH_MD5_HEX_LEN + 1] = {0};
char noncehashexp[HASH_MD5_HEX_LEN + 9] = {0};
uint32_t nonce_time;
unsigned long int nci;
uint32_t t;

View file

@ -9,27 +9,24 @@
*/
#include <curl/curl.h>
#include <string.h>
#include <libubox/blobmsg_json.h>
#include "common.h"
#include "download.h"
#include "ubus.h"
#include "cwmp_uci.h"
#include "backupSession.h"
#include "cwmp_time.h"
#include "ubus.h"
#include "log.h"
#include "cwmp_time.h"
#include "event.h"
#include "cwmp_uci.h"
#include "session.h"
#include "subprocess.h"
LIST_HEAD(list_download);
LIST_HEAD(list_schedule_download);
LIST_HEAD(list_apply_schedule_download);
pthread_mutex_t mutex_download = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t threshold_download;
pthread_mutex_t mutex_schedule_download = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t threshold_schedule_download;
pthread_mutex_t mutex_apply_schedule_download = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t threshold_apply_schedule_download;
int count_download_queue = 0;
@ -70,6 +67,57 @@ int download_file(const char *file_path, const char *url, const char *username,
return res_code;
}
char *download_file_task_function(char *task)
{
struct blob_buf bbuf;
memset(&bbuf, 0, sizeof(struct blob_buf));
blob_buf_init(&bbuf, 0);
if (blobmsg_add_json_from_string(&bbuf, task) == false) {
blob_buf_free(&bbuf);
return NULL;
}
const struct blobmsg_policy p[5] = { { "task", BLOBMSG_TYPE_STRING }, { "file_path", BLOBMSG_TYPE_STRING }, { "url", BLOBMSG_TYPE_STRING }, { "username", BLOBMSG_TYPE_STRING }, { "password", BLOBMSG_TYPE_STRING } };
struct blob_attr *tb[5] = { NULL, NULL, NULL, NULL, NULL};
blobmsg_parse(p, 5, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head));
char *task_name = blobmsg_get_string(tb[0]);
if (!task_name || strcmp(task_name, "download") != 0)
return NULL;
char *file_path = blobmsg_get_string(tb[1]);
char *url = blobmsg_get_string(tb[2]);
char *username = blobmsg_get_string(tb[3]);
char *password = blobmsg_get_string(tb[4]);
int http_code = download_file(file_path, url, username, password);
char *http_ret = (char *)malloc(4 * sizeof(char));
snprintf(http_ret, 4, "%d", http_code);
http_ret[3] = 0;
return http_ret;
}
int download_file_in_subprocess(const char *file_path, const char *url, const char *username, const char *password)
{
subprocess_start(download_file_task_function);
struct blob_buf bbuf;
memset(&bbuf, 0, sizeof(struct blob_buf));
blob_buf_init(&bbuf, 0);
blobmsg_add_string(&bbuf, "task", "download");
blobmsg_add_string(&bbuf, "file_path", file_path ? file_path : "");
blobmsg_add_string(&bbuf, "url", url ? url : "");
blobmsg_add_string(&bbuf, "username", username ? username : "");
blobmsg_add_string(&bbuf, "password", password ? password : "");
char *download_task = blobmsg_format_json(bbuf.head, true);
blob_buf_free(&bbuf);
if (download_task != NULL) {
char *ret = execute_task_in_subprocess(download_task);
return atoi(ret);
}
return 500;
}
/*
* Check if the downloaded image can be applied
*/
@ -140,6 +188,58 @@ int get_available_bank_id()
return bank_id;
}
/*
* Get Bank Status
*/
void ubus_get_bank_status_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg)
{
int *bank_id = (int *)req->priv;
int *status = bank_id;
bool bank_found = false;
struct blob_attr *banks = NULL;
struct blob_attr *cur;
int rem;
blobmsg_for_each_attr(cur, msg, rem)
{
if (blobmsg_type(cur) == BLOBMSG_TYPE_ARRAY) {
banks = cur;
break;
}
}
const struct blobmsg_policy p[8] = { { "name", BLOBMSG_TYPE_STRING }, { "id", BLOBMSG_TYPE_INT32 }, { "active", BLOBMSG_TYPE_BOOL }, { "upgrade", BLOBMSG_TYPE_BOOL },
{ "fwver", BLOBMSG_TYPE_STRING }, { "swver", BLOBMSG_TYPE_STRING }, { "fwver", BLOBMSG_TYPE_STRING }, { "status", BLOBMSG_TYPE_STRING } };
blobmsg_for_each_attr(cur, banks, rem)
{
struct blob_attr *tb[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
blobmsg_parse(p, 8, tb, blobmsg_data(cur), blobmsg_len(cur));
if (!tb[0])
continue;
if (blobmsg_get_u32(tb[1]) == (uint32_t)*bank_id) {
bank_found = true;
if (strcmp(blobmsg_get_string(tb[7]), "Available") == 0 || strcmp(blobmsg_get_string(tb[7]), "Active"))
*status = 1;
else
*status = 0;
}
}
if (bank_found == false)
*status = 0;
}
int get_applied_firmware_status(int *bank_id_status)
{
int e;
e = cwmp_ubus_call("fwbank", "dump", CWMP_UBUS_ARGS{ {} }, 0, ubus_get_bank_status_callback, &bank_id_status);
if (e != 0) {
CWMP_LOG(INFO, "fwbank dump ubus method failed: Ubus err code: %d", e);
}
return e;
}
/*
* Apply the new firmware
*/
@ -154,6 +254,24 @@ int cwmp_apply_firmware()
return e;
}
void wait_firmware_to_be_applied(int bank_id)
{
int count = 0;
do {
int bank_id_status = bank_id;
if (get_applied_firmware_status(&bank_id_status) != CWMP_OK)
break;
if (bank_id_status == 1)
break;
usleep(1000 * 1000);
count++;
} while(count < 15);
}
int cwmp_apply_multiple_firmware()
{
int e;
@ -166,9 +284,28 @@ int cwmp_apply_multiple_firmware()
CWMP_LOG(INFO, "fwbank upgrade ubus method failed: Ubus err code: %d", e);
return -1;
}
//wait until the apply completes
wait_firmware_to_be_applied(bank_id);
return CWMP_OK;
}
char *apply_multiple_firmware_task_function(char *task __attribute__((unused)))
{
int ret = cwmp_apply_multiple_firmware();
char *ret_str = (char *)malloc(2 * sizeof(char));
snprintf(ret_str, 2, "%d", ret);
ret_str[1] = 0;
return ret_str;
}
int cwmp_apply_multiple_firmware_in_subprocess()
{
subprocess_start(apply_multiple_firmware_task_function);
char *ret = execute_task_in_subprocess("{}"); //empty json object
return atoi(ret);
}
int cwmp_launch_download(struct download *pdownload, char *download_file_name, enum load_type ltype, struct transfer_complete **ptransfer_complete)
{
int error = FAULT_CPE_NO_FAULT;
@ -185,7 +322,7 @@ int cwmp_launch_download(struct download *pdownload, char *download_file_name, e
goto end_download;
}
int http_code = download_file(ICWMP_DOWNLOAD_FILE, pdownload->url, pdownload->username, pdownload->password);
int http_code = download_file_in_subprocess(ICWMP_DOWNLOAD_FILE, pdownload->url, pdownload->username, pdownload->password);
if (http_code == 404)
error = FAULT_CPE_DOWNLOAD_FAIL_CONTACT_SERVER;
else if (http_code == 401)
@ -264,11 +401,11 @@ char *get_file_name_by_download_url(char *url)
return slash+1;
}
int apply_downloaded_file(struct cwmp *cwmp, struct download *pdownload, char *download_file_name, struct transfer_complete *ptransfer_complete)
int apply_downloaded_file(struct download *pdownload, char *download_file_name, struct transfer_complete *ptransfer_complete)
{
int error = FAULT_CPE_NO_FAULT;
if (pdownload->file_type[0] == '1') {
ptransfer_complete->old_software_version = cwmp->deviceid.softwareversion;
ptransfer_complete->old_software_version = cwmp_main->deviceid.softwareversion;
}
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
@ -314,7 +451,7 @@ int apply_downloaded_file(struct cwmp *cwmp, struct download *pdownload, char *d
error = FAULT_CPE_NO_FAULT;
} else if (strcmp(pdownload->file_type, STORED_FIRMWARE_IMAGE_FILE_TYPE) == 0) {
int err = cwmp_apply_multiple_firmware();
int err = cwmp_apply_multiple_firmware_in_subprocess();
if (err == CWMP_OK)
error = FAULT_CPE_NO_FAULT;
else
@ -330,17 +467,19 @@ int apply_downloaded_file(struct cwmp *cwmp, struct download *pdownload, char *d
}
return FAULT_CPE_NO_FAULT;
}
if (error != FAULT_CPE_NO_FAULT) {
bkp_session_delete_transfer_complete(ptransfer_complete);
ptransfer_complete->fault_code = error;
}
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete);
cwmp_root_cause_transfer_complete(ptransfer_complete);
return error;
}
struct transfer_complete *set_download_error_transfer_complete(struct cwmp *cwmp, struct download *pdownload, enum load_type ltype)
struct transfer_complete *set_download_error_transfer_complete(struct download *pdownload, enum load_type ltype)
{
struct transfer_complete *ptransfer_complete;
ptransfer_complete = calloc(1, sizeof(struct transfer_complete));
@ -351,422 +490,11 @@ struct transfer_complete *set_download_error_transfer_complete(struct cwmp *cwmp
ptransfer_complete->fault_code = ltype == TYPE_DOWNLOAD ? FAULT_CPE_DOWNLOAD_FAILURE : FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW;
ptransfer_complete->type = ltype;
bkp_session_insert_transfer_complete(ptransfer_complete);
cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete);
cwmp_root_cause_transfer_complete(ptransfer_complete);
}
return ptransfer_complete;
}
void *thread_cwmp_rpc_cpe_download(void *v)
{
struct cwmp *cwmp = (struct cwmp *)v;
struct download *pdownload;
struct timespec download_timeout = { 0, 0 };
time_t current_time, stime;
int error;
struct transfer_complete *ptransfer_complete;
long int time_of_grace = 3600, timeout;
sleep(3);
for (;;) {
if (thread_end)
break;
if (list_download.next != &(list_download)) {
pdownload = list_entry(list_download.next, struct download, list);
stime = pdownload->scheduled_time;
current_time = time(NULL);
if (pdownload->scheduled_time != 0)
timeout = current_time - pdownload->scheduled_time;
else
timeout = 0;
if ((timeout >= 0) && (timeout > time_of_grace)) {
pthread_mutex_lock(&mutex_download);
bkp_session_delete_download(pdownload);
error = FAULT_CPE_DOWNLOAD_FAILURE;
ptransfer_complete = set_download_error_transfer_complete(cwmp, pdownload, TYPE_DOWNLOAD);
list_del(&(pdownload->list));
if (pdownload->scheduled_time != 0)
count_download_queue--;
cwmp_free_download_request(pdownload);
pthread_mutex_unlock(&mutex_download);
continue;
}
if ((timeout >= 0) && (timeout <= time_of_grace)) {
pthread_mutex_lock(&(cwmp->mutex_session_send));
char *download_file_name = get_file_name_by_download_url(pdownload->url);
CWMP_LOG(INFO, "Launch download file %s", pdownload->url);
error = cwmp_launch_download(pdownload, download_file_name, TYPE_DOWNLOAD, &ptransfer_complete);
sleep(3);
if (error != FAULT_CPE_NO_FAULT) {
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete);
bkp_session_delete_transfer_complete(ptransfer_complete);
} else {
error = apply_downloaded_file(cwmp, pdownload, download_file_name, ptransfer_complete);
if (error || pdownload->file_type[0] == '6')
bkp_session_delete_transfer_complete(ptransfer_complete);
}
if (pdownload->file_type[0] == '6')
sleep(30);
pthread_mutex_unlock(&(cwmp->mutex_session_send));
pthread_cond_signal(&(cwmp->threshold_session_send));
pthread_mutex_lock(&mutex_download);
list_del(&(pdownload->list));
if (pdownload->scheduled_time != 0)
count_download_queue--;
cwmp_free_download_request(pdownload);
pthread_mutex_unlock(&mutex_download);
continue;
}
pthread_mutex_lock(&mutex_download);
download_timeout.tv_sec = stime;
pthread_cond_timedwait(&threshold_download, &mutex_download, &download_timeout);
pthread_mutex_unlock(&mutex_download);
} else {
pthread_mutex_lock(&mutex_download);
pthread_cond_wait(&threshold_download, &mutex_download);
pthread_mutex_unlock(&mutex_download);
}
}
return NULL;
}
int cwmp_add_apply_schedule_download(struct download *schedule_download, char *start_time)
{
int i = 0;
int error = FAULT_CPE_NO_FAULT;
struct apply_schedule_download *apply_schedule_download;
apply_schedule_download = calloc(1, sizeof(struct apply_schedule_download));
if (apply_schedule_download == NULL) {
error = FAULT_CPE_INTERNAL_ERROR;
goto end;
}
if (error == FAULT_CPE_NO_FAULT) {
pthread_mutex_lock(&mutex_apply_schedule_download);
apply_schedule_download->command_key = strdup(schedule_download->command_key);
apply_schedule_download->file_type = strdup(schedule_download->file_type);
apply_schedule_download->start_time = strdup(start_time);
for (i = 0; i < 2; i++) {
apply_schedule_download->timeintervals[i].windowstart = schedule_download->timewindowstruct[i].windowstart;
apply_schedule_download->timeintervals[i].windowend = schedule_download->timewindowstruct[i].windowend;
apply_schedule_download->timeintervals[i].maxretries = schedule_download->timewindowstruct[i].maxretries;
}
list_add_tail(&(apply_schedule_download->list), &(list_apply_schedule_download));
bkp_session_insert_apply_schedule_download(apply_schedule_download);
bkp_session_save();
pthread_mutex_unlock(&mutex_apply_schedule_download);
pthread_cond_signal(&threshold_apply_schedule_download);
}
end:
cwmp_free_apply_schedule_download_request(apply_schedule_download);
return 0;
}
void *thread_cwmp_rpc_cpe_schedule_download(void *v)
{
struct cwmp *cwmp = (struct cwmp *)v;
struct timespec download_timeout = { 0, 0 };
int error = FAULT_CPE_NO_FAULT;
struct transfer_complete *ptransfer_complete;
int min_time = 0;
struct download *current_download = NULL;
struct download *p, *_p;
for (;;) {
time_t current_time;
if (thread_end)
break;
current_time = time(NULL);
if (list_schedule_download.next != &(list_schedule_download)) {
list_for_each_entry_safe (p, _p, &(list_schedule_download), list) {
if (min_time == 0) {
if (p->timewindowstruct[0].windowend >= current_time) {
min_time = p->timewindowstruct[0].windowstart;
current_download = p;
} else if (p->timewindowstruct[1].windowend >= current_time) {
min_time = p->timewindowstruct[1].windowstart;
current_download = p;
} else {
pthread_mutex_lock(&mutex_schedule_download);
bkp_session_delete_schedule_download(p);
error = FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW;
ptransfer_complete = set_download_error_transfer_complete(cwmp, p, TYPE_SCHEDULE_DOWNLOAD);
list_del(&(p->list));
if (p->timewindowstruct[0].windowstart != 0)
count_download_queue--;
cwmp_free_schedule_download_request(p);
pthread_mutex_unlock(&mutex_schedule_download);
continue;
}
} else {
if (p->timewindowstruct[0].windowend >= current_time) {
if (p->timewindowstruct[0].windowstart < min_time) {
min_time = p->timewindowstruct[0].windowstart;
current_download = p;
}
} else if (p->timewindowstruct[1].windowend >= current_time) {
if (p->timewindowstruct[1].windowstart < min_time) {
min_time = p->timewindowstruct[1].windowstart;
current_download = p;
}
} else {
pthread_mutex_lock(&mutex_schedule_download);
bkp_session_delete_schedule_download(p);
error = FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW;
ptransfer_complete = set_download_error_transfer_complete(cwmp, p, TYPE_SCHEDULE_DOWNLOAD);
list_del(&(p->list));
if (p->timewindowstruct[0].windowstart != 0)
count_download_queue--;
cwmp_free_schedule_download_request(p);
pthread_mutex_unlock(&mutex_schedule_download);
continue;
}
}
}
} else {
pthread_mutex_lock(&mutex_schedule_download);
pthread_cond_wait(&threshold_schedule_download, &mutex_schedule_download);
pthread_mutex_unlock(&mutex_schedule_download);
}
if (min_time == 0) {
continue;
} else if (min_time <= current_time) {
char *download_file_name = get_file_name_by_download_url(current_download->url);
if ((min_time == current_download->timewindowstruct[0].windowstart && (current_download->timewindowstruct[0].windowmode)[0] == '2') || (min_time == current_download->timewindowstruct[1].windowstart && (current_download->timewindowstruct[1].windowmode)[0] == '2')) {
pthread_mutex_lock(&mutex_schedule_download);
ptransfer_complete = calloc(1, sizeof(struct transfer_complete));
ptransfer_complete->type = TYPE_SCHEDULE_DOWNLOAD;
error = cwmp_launch_download(current_download, download_file_name, TYPE_SCHEDULE_DOWNLOAD, &ptransfer_complete);
if (error != FAULT_CPE_NO_FAULT) {
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete);
bkp_session_delete_transfer_complete(ptransfer_complete);
} else {
pthread_mutex_unlock(&mutex_schedule_download);
if (pthread_mutex_trylock(&(cwmp->mutex_session_send)) == 0) {
pthread_mutex_lock(&mutex_apply_schedule_download);
pthread_mutex_lock(&mutex_schedule_download);
error = apply_downloaded_file(cwmp, current_download, download_file_name, ptransfer_complete);
if (error == FAULT_CPE_NO_FAULT)
exit(EXIT_SUCCESS);
pthread_mutex_unlock(&mutex_schedule_download);
pthread_mutex_unlock(&mutex_apply_schedule_download);
pthread_mutex_unlock(&(cwmp->mutex_session_send));
pthread_cond_signal(&(cwmp->threshold_session_send));
} else {
cwmp_add_apply_schedule_download(current_download, ptransfer_complete->start_time);
}
}
pthread_mutex_lock(&mutex_schedule_download);
bkp_session_delete_schedule_download(current_download);
bkp_session_save();
list_del(&(current_download->list));
cwmp_free_schedule_download_request(current_download);
pthread_mutex_unlock(&mutex_schedule_download);
min_time = 0;
current_download = NULL;
continue;
} //AT ANY TIME OR WHEN IDLE
else {
pthread_mutex_lock(&(cwmp->mutex_session_send));
CWMP_LOG(INFO, "Launch download file %s", current_download->url);
error = cwmp_launch_download(current_download, download_file_name, TYPE_SCHEDULE_DOWNLOAD, &ptransfer_complete);
if (error != FAULT_CPE_NO_FAULT) {
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete);
bkp_session_delete_transfer_complete(ptransfer_complete);
} else {
error = apply_downloaded_file(cwmp, current_download, download_file_name, ptransfer_complete);
if (error == FAULT_CPE_NO_FAULT)
exit(EXIT_SUCCESS);
}
pthread_mutex_unlock(&(cwmp->mutex_session_send));
pthread_cond_signal(&(cwmp->threshold_session_send));
pthread_mutex_lock(&mutex_schedule_download);
list_del(&(current_download->list));
if (current_download->timewindowstruct[0].windowstart != 0)
count_download_queue--;
cwmp_free_schedule_download_request(current_download);
pthread_mutex_unlock(&mutex_schedule_download);
continue;
}
} else {
if (min_time == current_download->timewindowstruct[0].windowstart) {
pthread_mutex_lock(&mutex_schedule_download);
download_timeout.tv_sec = min_time;
pthread_cond_timedwait(&threshold_schedule_download, &mutex_schedule_download, &download_timeout);
pthread_mutex_unlock(&mutex_schedule_download);
} else if (min_time == current_download->timewindowstruct[1].windowstart) {
pthread_mutex_lock(&mutex_schedule_download);
download_timeout.tv_sec = min_time;
pthread_cond_timedwait(&threshold_schedule_download, &mutex_schedule_download, &download_timeout);
pthread_mutex_unlock(&mutex_schedule_download);
}
}
}
return NULL;
}
void *thread_cwmp_rpc_cpe_apply_schedule_download(void *v)
{
struct cwmp *cwmp = (struct cwmp *)v;
struct timespec apply_timeout = { 0, 0 };
int error = FAULT_CPE_NO_FAULT;
struct transfer_complete *ptransfer_complete;
int min_time = 0;
struct apply_schedule_download *apply_download = NULL;
struct apply_schedule_download *p, *_p;
for (;;) {
time_t current_time;
if (thread_end)
break;
current_time = time(NULL);
if (list_apply_schedule_download.next != &(list_apply_schedule_download)) {
list_for_each_entry_safe (p, _p, &(list_apply_schedule_download), list) {
if (min_time == 0) {
if (p->timeintervals[0].windowend >= current_time) {
min_time = p->timeintervals[0].windowstart;
apply_download = p;
} else if (p->timeintervals[1].windowend >= current_time) {
min_time = p->timeintervals[1].windowstart;
apply_download = p;
} else {
pthread_mutex_lock(&mutex_apply_schedule_download);
bkp_session_delete_apply_schedule_download(p);
error = FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW;
ptransfer_complete = set_download_error_transfer_complete(cwmp, (struct download *)p, TYPE_SCHEDULE_DOWNLOAD);
list_del(&(p->list));
if (p->timeintervals[0].windowstart != 0)
count_download_queue--;
cwmp_free_apply_schedule_download_request(p);
pthread_mutex_unlock(&mutex_apply_schedule_download);
continue;
}
} else {
if (p->timeintervals[0].windowend >= current_time) {
if (p->timeintervals[0].windowstart < min_time) {
min_time = p->timeintervals[0].windowstart;
apply_download = p;
}
} else if (p->timeintervals[1].windowend >= current_time) {
if (p->timeintervals[1].windowstart < min_time) {
min_time = p->timeintervals[1].windowstart;
apply_download = p;
}
} else {
pthread_mutex_lock(&mutex_apply_schedule_download);
bkp_session_delete_apply_schedule_download(p);
error = FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW;
ptransfer_complete = set_download_error_transfer_complete(cwmp, (struct download *)p, TYPE_SCHEDULE_DOWNLOAD);
list_del(&(p->list));
/*if(p->timewindowintervals[0].windowstart != 0)
count_download_queue--;*/
cwmp_free_apply_schedule_download_request(p);
pthread_mutex_unlock(&mutex_apply_schedule_download);
continue;
}
}
}
} else {
pthread_mutex_lock(&mutex_apply_schedule_download);
pthread_cond_wait(&threshold_apply_schedule_download, &mutex_apply_schedule_download);
pthread_mutex_unlock(&mutex_apply_schedule_download);
}
if (min_time == 0) {
continue;
} else if (min_time <= current_time) {
pthread_mutex_lock(&(cwmp->mutex_session_send));
pthread_mutex_lock(&mutex_schedule_download);
bkp_session_delete_apply_schedule_download(apply_download);
bkp_session_save();
ptransfer_complete = calloc(1, sizeof(struct transfer_complete));
if (apply_download->file_type[0] == '1') {
ptransfer_complete->old_software_version = cwmp->deviceid.softwareversion;
}
ptransfer_complete->command_key = strdup(apply_download->command_key);
ptransfer_complete->start_time = strdup(apply_download->start_time);
ptransfer_complete->complete_time = strdup(mix_get_time());
ptransfer_complete->fault_code = error;
ptransfer_complete->type = TYPE_SCHEDULE_DOWNLOAD;
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
if (strcmp(apply_download->file_type, FIRMWARE_UPGRADE_IMAGE_FILE_TYPE) == 0) {
cwmp_uci_set_value("cwmp", "cpe", "exec_download", "1");
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
cwmp_apply_firmware();
sleep(70);
error = FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED;
} else if (strcmp(apply_download->file_type, WEB_CONTENT_FILE_TYPE) == 0) {
//TODO Not Supported
error = FAULT_CPE_NO_FAULT;
} else if (strcmp(apply_download->file_type, VENDOR_CONFIG_FILE_TYPE) == 0) {
cwmp_uci_init();
int err = cwmp_uci_import(NULL, VENDOR_CONFIG_FILE, UCI_STANDARD_CONFIG);
cwmp_uci_exit();
if (err == CWMP_OK)
error = FAULT_CPE_NO_FAULT;
else if (err == CWMP_GEN_ERR)
error = FAULT_CPE_INTERNAL_ERROR;
else if (err == -1)
error = FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED;
}
if ((error == FAULT_CPE_NO_FAULT) && (apply_download->file_type[0] == '1' || apply_download->file_type[0] == '3')) {
if (apply_download->file_type[0] == '3') {
CWMP_LOG(INFO, "Download and apply new vendor config file is done successfully");
}
exit(EXIT_SUCCESS);
}
if (error != FAULT_CPE_NO_FAULT) {
bkp_session_delete_transfer_complete(ptransfer_complete);
ptransfer_complete->fault_code = error;
}
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete);
pthread_mutex_unlock(&mutex_schedule_download);
pthread_mutex_unlock(&(cwmp->mutex_session_send));
pthread_cond_signal(&(cwmp->threshold_session_send));
pthread_mutex_lock(&mutex_apply_schedule_download);
list_del(&(apply_download->list));
/*if(pdownload->timeintervals[0].windowstart != 0)
count_download_queue--;*/
cwmp_free_apply_schedule_download_request(apply_download);
pthread_mutex_unlock(&mutex_apply_schedule_download);
continue;
} else {
if (min_time == apply_download->timeintervals[0].windowstart) {
pthread_mutex_lock(&mutex_apply_schedule_download);
apply_timeout.tv_sec = min_time;
pthread_cond_timedwait(&threshold_apply_schedule_download, &mutex_schedule_download, &apply_timeout);
pthread_mutex_unlock(&mutex_apply_schedule_download);
} else if (min_time == apply_download->timeintervals[1].windowstart) {
pthread_mutex_lock(&mutex_apply_schedule_download);
apply_timeout.tv_sec = min_time;
pthread_cond_timedwait(&threshold_schedule_download, &mutex_schedule_download, &apply_timeout);
pthread_mutex_unlock(&mutex_schedule_download);
}
}
}
return NULL;
}
int cwmp_free_download_request(struct download *download)
{
if (download != NULL) {
@ -856,7 +584,6 @@ int cwmp_scheduledDownload_remove_all()
int cwmp_scheduled_Download_remove_all()
{
pthread_mutex_lock(&mutex_schedule_download);
while (list_schedule_download.next != &(list_schedule_download)) {
struct download *schedule_download;
schedule_download = list_entry(list_schedule_download.next, struct download, list);
@ -866,29 +593,11 @@ int cwmp_scheduled_Download_remove_all()
count_download_queue--;
cwmp_free_schedule_download_request(schedule_download);
}
pthread_mutex_unlock(&mutex_schedule_download);
return CWMP_OK;
}
int cwmp_apply_scheduled_Download_remove_all()
{
pthread_mutex_lock(&mutex_apply_schedule_download);
while (list_apply_schedule_download.next != &(list_apply_schedule_download)) {
struct apply_schedule_download *apply_schedule_download;
apply_schedule_download = list_entry(list_apply_schedule_download.next, struct apply_schedule_download, list);
list_del(&(apply_schedule_download->list));
bkp_session_delete_apply_schedule_download(apply_schedule_download);
/*if(apply_schedule_download->timetimeintervals[0].windowstart != 0)
count_download_queue--;*/ //TOCK
cwmp_free_apply_schedule_download_request(apply_schedule_download);
}
pthread_mutex_unlock(&mutex_apply_schedule_download);
return CWMP_OK;
}
int cwmp_rpc_acs_destroy_data_transfer_complete(struct session *session __attribute__((unused)), struct rpc *rpc)
int cwmp_rpc_acs_destroy_data_transfer_complete(struct rpc *rpc)
{
if (rpc->extra_data != NULL) {
struct transfer_complete *p = (struct transfer_complete *)rpc->extra_data;
@ -902,3 +611,138 @@ int cwmp_rpc_acs_destroy_data_transfer_complete(struct session *session __attrib
FREE(rpc->extra_data);
return 0;
}
void cwmp_start_download(struct uloop_timeout *timeout)
{
struct download *pdownload;
int error = FAULT_CPE_NO_FAULT;
struct transfer_complete *ptransfer_complete;
pdownload = container_of(timeout, struct download, handler_timer);
char *download_file_name = get_file_name_by_download_url(pdownload->url);
CWMP_LOG(INFO, "Launch download file %s", pdownload->url);
error = cwmp_launch_download(pdownload, download_file_name, TYPE_DOWNLOAD, &ptransfer_complete);
sleep(3);
if (error != FAULT_CPE_NO_FAULT) {
CWMP_LOG(ERROR, "Error while downloading the file: %s", pdownload->url);
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
cwmp_root_cause_transfer_complete(ptransfer_complete);
bkp_session_delete_transfer_complete(ptransfer_complete);
} else {
error = apply_downloaded_file(pdownload, download_file_name, ptransfer_complete);
if (error != FAULT_CPE_NO_FAULT) {
CWMP_LOG(ERROR, "Error while applying the downloaded file: %s", download_file_name);
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
cwmp_root_cause_transfer_complete(ptransfer_complete);
bkp_session_delete_transfer_complete(ptransfer_complete);
}
}
if (error == FAULT_CPE_NO_FAULT && pdownload->file_type[0] == '3') {
cwmp_root_cause_transfer_complete(ptransfer_complete);
bkp_session_delete_download(pdownload);
bkp_session_delete_transfer_complete(ptransfer_complete);
bkp_session_save();
}
pthread_mutex_lock(&mutex_download);
list_del(&(pdownload->list));
if (pdownload->scheduled_time != 0)
count_download_queue--;
cwmp_free_download_request(pdownload);
pthread_mutex_unlock(&mutex_download);
trigger_cwmp_session_timer();
}
void cwmp_start_schedule_download(struct uloop_timeout *timeout)
{
struct download *sched_download;
int error = FAULT_CPE_NO_FAULT;
struct transfer_complete *ptransfer_complete;
sched_download = container_of(timeout, struct download, handler_timer);
bool outdate = false;
int delay;
int window_index;
time_t now = time(NULL);
if (sched_download->timewindowstruct[0].windowstart > now) {
delay = sched_download->timewindowstruct[0].windowstart - now;
uloop_timeout_set(&sched_download->handler_timer, 1000 * delay);
return;
} else if (sched_download->timewindowstruct[0].windowend >= now) {
outdate = false;
window_index = 0;
} else if (sched_download->timewindowstruct[1].windowstart > now) {
delay = sched_download->timewindowstruct[1].windowstart - now;
uloop_timeout_set(&sched_download->handler_timer, 1000 * delay);
return;
} else if (sched_download->timewindowstruct[1].windowend >= now) {
outdate = false;
window_index = 1;
} else {
outdate = true;
}
if (!outdate) {
char *download_file_name = get_file_name_by_download_url(sched_download->url);
CWMP_LOG(INFO, "Launch download file %s", sched_download->url);
error = cwmp_launch_download(sched_download, download_file_name, TYPE_DOWNLOAD, &ptransfer_complete);
sleep(3);
if (error != FAULT_CPE_NO_FAULT) {
CWMP_LOG(ERROR, "Error while downloading the file: %s", sched_download->url);
goto retry;
} else {
error = apply_downloaded_file(sched_download, download_file_name, ptransfer_complete);
if (error != FAULT_CPE_NO_FAULT) {
CWMP_LOG(ERROR, "Error while applying the downloaded file: %s", download_file_name);
goto retry;
}
}
if (error == FAULT_CPE_NO_FAULT && sched_download->file_type[0] == '3') {
cwmp_root_cause_transfer_complete(ptransfer_complete);
bkp_session_delete_download(sched_download);
bkp_session_delete_transfer_complete(ptransfer_complete);
bkp_session_save();
}
} else {
error = FAULT_CPE_INTERNAL_ERROR;
CWMP_LOG(ERROR, "Schedule Download out of date");
ptransfer_complete = calloc(1, sizeof(struct transfer_complete));
if (ptransfer_complete == NULL) {
// error = FAULT_CPE_INTERNAL_ERROR;
return;
}
ptransfer_complete->command_key = sched_download->command_key ? strdup(sched_download->command_key) : strdup("");
ptransfer_complete->start_time = strdup(mix_get_time_of(now));
ptransfer_complete->complete_time = strdup(mix_get_time());
ptransfer_complete->type = TYPE_DOWNLOAD;
if (error != FAULT_CPE_NO_FAULT) {
ptransfer_complete->fault_code = error;
}
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
cwmp_root_cause_transfer_complete(ptransfer_complete);
bkp_session_delete_transfer_complete(ptransfer_complete);
}
return;
retry:
if (sched_download->timewindowstruct[window_index].maxretries > 0) {
uloop_timeout_set(&sched_download->handler_timer, 10);
sched_download->timewindowstruct[window_index].maxretries--;
return;
} else {
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
cwmp_root_cause_transfer_complete(ptransfer_complete);
bkp_session_delete_transfer_complete(ptransfer_complete);
bkp_session_save();
}
list_del(&(sched_download->list));
if (sched_download->scheduled_time != 0)
count_download_queue--;
cwmp_free_schedule_download_request(sched_download);
trigger_cwmp_session_timer();
}

287
event.c
View file

@ -11,12 +11,21 @@
*
*/
#include <pthread.h>
#include "backupSession.h"
#include "event.h"
#include "sched_inform.h"
#include "download.h"
#include "upload.h"
#include "log.h"
#include "event.h"
#include "session.h"
#include "cwmp_du_state.h"
#include "download.h"
#include "soap.h"
#include "upload.h"
#include "sched_inform.h"
#include "ubus.h"
#include "cwmp_event.h"
pthread_mutex_t add_event_mutext = PTHREAD_MUTEX_INITIALIZER;
const struct EVENT_CONST_STRUCT EVENT_CONST[] = {[EVENT_IDX_0BOOTSTRAP] = { "0 BOOTSTRAP", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL | EVENT_RETRY_AFTER_REBOOT },
[EVENT_IDX_1BOOT] = { "1 BOOT", EVENT_TYPE_SINGLE, EVENT_RETRY_AFTER_TRANSMIT_FAIL },
@ -54,84 +63,38 @@ void cwmp_save_event_container(struct event_container *event_container) //to be
}
}
struct event_container *cwmp_add_event_container(struct cwmp *cwmp, int event_code, char *command_key)
void cwmp_root_cause_event_diagnostic(void)
{
struct event_container *event_container;
struct list_head *ilist;
if (cwmp->head_event_container == NULL) {
struct session *session;
session = cwmp_add_queue_session(cwmp);
if (session == NULL) {
return NULL;
}
cwmp->head_event_container = &(session->head_event_container);
}
//session = list_entry(cwmp->head_event_container, struct session, head_event_container);
list_for_each (ilist, cwmp->head_event_container) {
event_container = list_entry(ilist, struct event_container, list);
if (event_container->code == event_code && EVENT_CONST[event_code].TYPE == EVENT_TYPE_SINGLE) {
return event_container;
}
if (event_container->code > event_code) {
break;
}
}
event_container = calloc(1, sizeof(struct event_container));
event_container = cwmp_add_event_container(EVENT_IDX_8DIAGNOSTICS_COMPLETE, "");
if (event_container == NULL) {
return NULL;
}
INIT_LIST_HEAD(&(event_container->head_dm_parameter));
list_add(&(event_container->list), ilist->prev);
event_container->code = event_code;
event_container->command_key = command_key ? strdup(command_key) : strdup("");
if ((cwmp->event_id < 0) || (cwmp->event_id >= MAX_INT_ID)) {
cwmp->event_id = 0;
}
cwmp->event_id++;
event_container->id = cwmp->event_id;
return event_container;
}
void cwmp_root_cause_event_ipdiagnostic(void)
{
struct cwmp *cwmp = &cwmp_main;
struct event_container *event_container;
pthread_mutex_lock(&(cwmp->mutex_session_queue));
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_8DIAGNOSTICS_COMPLETE, "");
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return;
}
cwmp_save_event_container(event_container);
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
pthread_cond_signal(&(cwmp->threshold_session_send));
cwmp_main->start_diagnostics = true;
return;
}
int cwmp_root_cause_event_boot(struct cwmp *cwmp)
int cwmp_root_cause_event_boot()
{
if (cwmp->env.boot == CWMP_START_BOOT) {
if (cwmp_main->env.boot == CWMP_START_BOOT) {
struct event_container *event_container;
pthread_mutex_lock(&(cwmp->mutex_session_queue));
cwmp->env.boot = 0;
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_1BOOT, "");
cwmp_main->env.boot = 0;
event_container = cwmp_add_event_container(EVENT_IDX_1BOOT, "");
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
cwmp_save_event_container(event_container);
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
}
return CWMP_OK;
}
int event_remove_all_event_container(struct session *session, int rem_from)
int event_remove_all_event_container(int rem_from)
{
while (session->head_event_container.next != &(session->head_event_container)) {
while (cwmp_main->session->events.next != &cwmp_main->session->events) {
struct event_container *event_container;
event_container = list_entry(session->head_event_container.next, struct event_container, list);
event_container = list_entry(cwmp_main->session->events.next, struct event_container, list);
bkp_session_delete_event(event_container->id, rem_from ? "send" : "queue");
free(event_container->command_key);
cwmp_free_all_dm_parameter_list(&(event_container->head_dm_parameter));
@ -142,16 +105,16 @@ int event_remove_all_event_container(struct session *session, int rem_from)
return CWMP_OK;
}
int event_remove_noretry_event_container(struct session *session, struct cwmp *cwmp)
int event_remove_noretry_event_container()
{
struct list_head *ilist, *q;
list_for_each_safe (ilist, q, &(session->head_event_container)) {
list_for_each_safe (ilist, q, &cwmp_main->session->events) {
struct event_container *event_container;
event_container = list_entry(ilist, struct event_container, list);
if (EVENT_CONST[event_container->code].CODE[0] == '6')
cwmp->cwmp_cr_event = 1;
cwmp_main->cwmp_cr_event = 1;
if (EVENT_CONST[event_container->code].RETRY == 0) {
free(event_container->command_key);
@ -163,247 +126,153 @@ int event_remove_noretry_event_container(struct session *session, struct cwmp *c
return CWMP_OK;
}
int cwmp_root_cause_event_bootstrap(struct cwmp *cwmp)
int cwmp_root_cause_event_bootstrap()
{
struct event_container *event_container;
char *acsurl = NULL;
int cmp = 0;
cwmp_load_saved_session(cwmp, &acsurl, ACS);
cwmp_load_saved_session(&acsurl, ACS);
if (acsurl == NULL)
save_acs_bkp_config(cwmp);
save_acs_bkp_config();
if (acsurl == NULL || ((cmp = strcmp(cwmp->conf.acsurl, acsurl)) != 0)) {
pthread_mutex_lock(&(cwmp->mutex_session_queue));
if (cwmp->head_event_container != NULL && cwmp->head_session_queue.next != &(cwmp->head_session_queue)) {
struct session *session;
session = list_entry(cwmp->head_event_container, struct session, head_event_container);
event_remove_all_event_container(session, RPC_QUEUE);
}
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_0BOOTSTRAP, "");
if (acsurl == NULL || ((cmp = strcmp(cwmp_main->conf.acsurl, acsurl)) != 0)) {
event_container = cwmp_add_event_container(EVENT_IDX_0BOOTSTRAP, "");
FREE(acsurl);
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
cwmp_save_event_container(event_container);
cwmp_scheduleInform_remove_all();
cwmp_scheduledDownload_remove_all();
cwmp_scheduled_Download_remove_all();
cwmp_apply_scheduled_Download_remove_all();
cwmp_scheduledUpload_remove_all();
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
} else {
FREE(acsurl);
}
if (cmp) {
pthread_mutex_lock(&(cwmp->mutex_session_queue));
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, "");
event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, "");
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
char buf[64] = "Device.ManagementServer.URL";
add_dm_parameter_to_list(&(event_container->head_dm_parameter), buf, NULL, NULL, 0, false);
cwmp_save_event_container(event_container);
save_acs_bkp_config(cwmp);
save_acs_bkp_config(cwmp_main);
cwmp_scheduleInform_remove_all();
cwmp_scheduledDownload_remove_all();
cwmp_apply_scheduled_Download_remove_all();
cwmp_scheduled_Download_remove_all();
cwmp_scheduledUpload_remove_all();
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
}
return CWMP_OK;
}
int cwmp_root_cause_transfer_complete(struct cwmp *cwmp, struct transfer_complete *p)
int cwmp_root_cause_transfer_complete(struct transfer_complete *p)
{
struct event_container *event_container;
struct session *session;
struct rpc *rpc_acs;
pthread_mutex_lock(&(cwmp->mutex_session_queue));
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_7TRANSFER_COMPLETE, "");
event_container = cwmp_add_event_container(EVENT_IDX_7TRANSFER_COMPLETE, "");
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
if ((rpc_acs = cwmp_add_session_rpc_acs(RPC_ACS_TRANSFER_COMPLETE)) == NULL) {
return CWMP_MEM_ERR;
}
switch (p->type) {
case TYPE_DOWNLOAD:
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_Download, p->command_key ? p->command_key : "");
event_container = cwmp_add_event_container(EVENT_IDX_M_Download, p->command_key ? p->command_key : "");
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
break;
case TYPE_UPLOAD:
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_Upload, p->command_key ? p->command_key : "");
event_container = cwmp_add_event_container(EVENT_IDX_M_Upload, p->command_key ? p->command_key : "");
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
break;
case TYPE_SCHEDULE_DOWNLOAD:
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_Schedule_Download, p->command_key ? p->command_key : "");
event_container = cwmp_add_event_container(EVENT_IDX_M_Schedule_Download, p->command_key ? p->command_key : "");
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
break;
}
session = list_entry(cwmp->head_event_container, struct session, head_event_container);
if ((rpc_acs = cwmp_add_session_rpc_acs(session, RPC_ACS_TRANSFER_COMPLETE)) == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
rpc_acs->extra_data = (void *)p;
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_OK;
}
int cwmp_root_cause_changedustate_complete(struct cwmp *cwmp, struct du_state_change_complete *p)
int cwmp_root_cause_changedustate_complete(struct du_state_change_complete *p)
{
struct event_container *event_container;
struct session *session;
struct rpc *rpc_acs;
pthread_mutex_lock(&(cwmp->mutex_session_queue));
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_11DU_STATE_CHANGE_COMPLETE, "");
event_container = cwmp_add_event_container(EVENT_IDX_11DU_STATE_CHANGE_COMPLETE, "");
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_ChangeDUState, p->command_key ? p->command_key : "");
event_container = cwmp_add_event_container(EVENT_IDX_M_ChangeDUState, p->command_key ? p->command_key : "");
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
session = list_entry(cwmp->head_event_container, struct session, head_event_container);
if ((rpc_acs = cwmp_add_session_rpc_acs(session, RPC_ACS_DU_STATE_CHANGE_COMPLETE)) == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
if ((rpc_acs = cwmp_add_session_rpc_acs(RPC_ACS_DU_STATE_CHANGE_COMPLETE)) == NULL) {
return CWMP_MEM_ERR;
}
rpc_acs->extra_data = (void *)p;
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_OK;
}
int cwmp_root_cause_get_rpc_method(struct cwmp *cwmp)
int cwmp_root_cause_get_rpc_method()
{
if (cwmp->env.periodic == CWMP_START_PERIODIC) {
if (cwmp_main->env.periodic == CWMP_START_PERIODIC) {
struct event_container *event_container;
struct session *session;
pthread_mutex_lock(&(cwmp->mutex_session_queue));
cwmp->env.periodic = 0;
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_2PERIODIC, "");
cwmp_main->env.periodic = 0;
event_container = cwmp_add_event_container(EVENT_IDX_2PERIODIC, "");
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
cwmp_save_event_container(event_container);
session = list_entry(cwmp->head_event_container, struct session, head_event_container);
if (cwmp_add_session_rpc_acs(session, RPC_ACS_GET_RPC_METHODS) == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
if (cwmp_add_session_rpc_acs(RPC_ACS_GET_RPC_METHODS) == NULL) {
return CWMP_MEM_ERR;
}
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
}
return CWMP_OK;
}
void *thread_event_periodic(void *v)
bool event_exist_in_list(int event)
{
struct cwmp *cwmp = (struct cwmp *)v;
struct event_container *event_container;
int periodic_interval;
bool periodic_enable;
time_t periodic_time;
struct timespec periodic_timeout = { 0, 0 };
time_t current_time;
long int delta_time;
periodic_interval = cwmp->conf.period;
periodic_enable = cwmp->conf.periodic_enable;
periodic_time = cwmp->conf.time;
for (;;) {
pthread_mutex_lock(&(cwmp->mutex_periodic));
if (cwmp->conf.periodic_enable) {
current_time = time(NULL);
if (periodic_time != 0) {
delta_time = (current_time - periodic_time) % periodic_interval;
if (delta_time >= 0)
periodic_timeout.tv_sec = current_time + periodic_interval - delta_time;
else
periodic_timeout.tv_sec = current_time - delta_time;
} else {
periodic_timeout.tv_sec = current_time + periodic_interval;
}
cwmp->session_status.next_periodic = periodic_timeout.tv_sec;
pthread_cond_timedwait(&(cwmp->threshold_periodic), &(cwmp->mutex_periodic), &periodic_timeout);
} else {
cwmp->session_status.next_periodic = 0;
pthread_cond_wait(&(cwmp->threshold_periodic), &(cwmp->mutex_periodic));
}
pthread_mutex_unlock(&(cwmp->mutex_periodic));
if (thread_end)
break;
if (periodic_interval != cwmp->conf.period || periodic_enable != cwmp->conf.periodic_enable || periodic_time != cwmp->conf.time) {
periodic_enable = cwmp->conf.periodic_enable;
periodic_interval = cwmp->conf.period;
periodic_time = cwmp->conf.time;
continue;
}
CWMP_LOG(INFO, "Periodic thread: add periodic event in the queue");
pthread_mutex_lock(&(cwmp->mutex_session_queue));
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_2PERIODIC, "");
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
continue;
}
cwmp_save_event_container(event_container);
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
pthread_cond_signal(&(cwmp->threshold_session_send));
}
return NULL;
}
bool event_exist_in_list(struct cwmp *cwmp, int event)
{
struct event_container *event_container;
list_for_each_entry (event_container, cwmp->head_event_container, list) {
struct event_container *event_container = NULL;
list_for_each_entry (event_container, &cwmp_main->session->events, list) {
if (event_container->code == event)
return true;
}
return false;
}
int cwmp_root_cause_event_periodic(struct cwmp *cwmp)
int cwmp_root_cause_event_periodic()
{
char local_time[27] = { 0 };
struct tm *t_tm;
if (cwmp->cwmp_period == cwmp->conf.period && cwmp->cwmp_periodic_enable == cwmp->conf.periodic_enable && cwmp->cwmp_periodic_time == cwmp->conf.time)
if (cwmp_main->cwmp_period == cwmp_main->conf.period && cwmp_main->cwmp_periodic_enable == cwmp_main->conf.periodic_enable && cwmp_main->cwmp_periodic_time == cwmp_main->conf.time)
return CWMP_OK;
pthread_mutex_lock(&(cwmp->mutex_periodic));
cwmp->cwmp_period = cwmp->conf.period;
cwmp->cwmp_periodic_enable = cwmp->conf.periodic_enable;
cwmp->cwmp_periodic_time = cwmp->conf.time;
CWMP_LOG(INFO, cwmp->cwmp_periodic_enable ? "Periodic event is enabled. Interval period = %ds" : "Periodic event is disabled", cwmp->cwmp_period);
cwmp_main->cwmp_period = cwmp_main->conf.period;
cwmp_main->cwmp_periodic_enable = cwmp_main->conf.periodic_enable;
cwmp_main->cwmp_periodic_time = cwmp_main->conf.time;
CWMP_LOG(INFO, cwmp_main->cwmp_periodic_enable ? "Periodic event is enabled. Interval period = %ds" : "Periodic event is disabled", cwmp_main->cwmp_period);
t_tm = localtime(&cwmp->cwmp_periodic_time);
t_tm = localtime(&cwmp_main->cwmp_periodic_time);
if (t_tm == NULL)
return CWMP_GEN_ERR;
@ -415,22 +284,20 @@ int cwmp_root_cause_event_periodic(struct cwmp *cwmp)
local_time[22] = ':';
local_time[26] = '\0';
CWMP_LOG(INFO, cwmp->cwmp_periodic_time ? "Periodic time is %s" : "Periodic time is Unknown", local_time);
pthread_mutex_unlock(&(cwmp->mutex_periodic));
pthread_cond_signal(&(cwmp->threshold_periodic));
CWMP_LOG(INFO, cwmp_main->cwmp_periodic_time ? "Periodic time is %s" : "Periodic time is Unknown", local_time);
return CWMP_OK;
}
void connection_request_ip_value_change(struct cwmp *cwmp, int version)
void connection_request_ip_value_change(int version)
{
char *bip = NULL;
char *ip_version = (version == IPv6) ? "ipv6" : "ip";
char *ip_value = (version == IPv6) ? cwmp->conf.ipv6 : cwmp->conf.ip;
char *ip_value = (version == IPv6) ? cwmp_main->conf.ipv6 : cwmp_main->conf.ip;
if (version == IPv6)
cwmp_load_saved_session(cwmp, &bip, CR_IPv6);
cwmp_load_saved_session(&bip, CR_IPv6);
else
cwmp_load_saved_session(cwmp, &bip, CR_IP);
cwmp_load_saved_session(&bip, CR_IP);
if (bip == NULL) {
bkp_session_simple_insert_in_parent("connection_request", ip_version, ip_value);
@ -439,30 +306,26 @@ void connection_request_ip_value_change(struct cwmp *cwmp, int version)
}
if (strcmp(bip, ip_value) != 0) {
struct event_container *event_container;
pthread_mutex_lock(&(cwmp->mutex_session_queue));
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, "");
event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, "");
if (event_container == NULL) {
FREE(bip);
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return;
}
cwmp_save_event_container(event_container);
bkp_session_simple_insert_in_parent("connection_request", ip_version, ip_value);
bkp_session_save();
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
pthread_cond_signal(&(cwmp->threshold_session_send));
}
FREE(bip);
}
void connection_request_port_value_change(struct cwmp *cwmp, int port)
void connection_request_port_value_change(int port)
{
char *bport = NULL;
char bufport[16];
snprintf(bufport, sizeof(bufport), "%d", port);
cwmp_load_saved_session(cwmp, &bport, CR_PORT);
cwmp_load_saved_session(&bport, CR_PORT);
if (bport == NULL) {
bkp_session_simple_insert_in_parent("connection_request", "port", bufport);
@ -471,7 +334,7 @@ void connection_request_port_value_change(struct cwmp *cwmp, int port)
}
if (strcmp(bport, bufport) != 0) {
struct event_container *event_container;
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, "");
event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, "");
if (event_container == NULL) {
FREE(bport);
return;
@ -483,20 +346,20 @@ void connection_request_port_value_change(struct cwmp *cwmp, int port)
FREE(bport);
}
int cwmp_root_cause_events(struct cwmp *cwmp)
int cwmp_root_cause_events()
{
int error;
if ((error = cwmp_root_cause_event_bootstrap(cwmp)))
if ((error = cwmp_root_cause_event_bootstrap()))
return error;
if ((error = cwmp_root_cause_event_boot(cwmp)))
if ((error = cwmp_root_cause_event_boot()))
return error;
if ((error = cwmp_root_cause_get_rpc_method(cwmp)))
if ((error = cwmp_root_cause_get_rpc_method()))
return error;
if ((error = cwmp_root_cause_event_periodic(cwmp)))
if ((error = cwmp_root_cause_event_periodic()))
return error;
return CWMP_OK;

View file

@ -2,7 +2,7 @@
echo "preparation script"
pwd
. ./gitlab-ci/shared.sh
source ./gitlab-ci/shared.sh
trap cleanup EXIT
trap cleanup SIGINT
@ -24,7 +24,7 @@ ubus-api-validator -f ./test/api/json/tr069.validation.json > ./api-test-result.
check_ret $?
echo "Stop all services"
supervisorctl stop icwmpd
supervisorctl stop all
# Artefact
gcovr -r . 2> /dev/null --xml -o ./api-test-coverage.xml

View file

@ -2,7 +2,7 @@
echo "preparation script"
pwd
. ./gitlab-ci/shared.sh
source ./gitlab-ci/shared.sh
trap cleanup EXIT
trap cleanup SIGINT
@ -39,9 +39,10 @@ echo "## Running script verification of functionalities ##"
echo > ./funl-test-result.log
echo > ./funl-test-debug.log
test_num=0
for test in $(ls -I "common.sh" -I "verify_custom_notifications.sh" test/script/); do
for test in `cat test/script/test_seq.txt`; do
test_num=$(( test_num + 1 ))
if ./test/script/"${test}"; then
./test/script/${test}
if [ "$?" -eq 0 ]; then
echo "ok ${test_num} - ${test}" >> ./funl-test-result.log
else
echo "not ok ${test_num} - ${test}" >> ./funl-test-result.log
@ -49,19 +50,17 @@ for test in $(ls -I "common.sh" -I "verify_custom_notifications.sh" test/script/
done
echo "Stop all services"
supervisorctl stop icwmpd
supervisorctl stop all
cp test/files/etc/config/users /etc/config/
cp test/files/etc/config/wireless /etc/config/
echo "Verify Custom notifications"
if ./test/script/verify_custom_notifications.sh; then
echo "ok - verify_custom_notifications" >> ./funl-test-result.log
else
echo "not ok - verify_custom_notifications" >> ./funl-test-result.log
fi
test_num=$(( test_num + 1 ))
#echo "Verify Custom notifications"
#./test/script/verify_custom_notifications.sh
#if [ "$?" -eq 0 ]; then
# echo "ok - verify_custom_notifications" >> ./funl-test-result.log
#else
# echo "not ok - verify_custom_notifications" >> ./funl-test-result.log
#fi
#
#test_num=$(( test_num + 1 ))
echo "1..${test_num}" >> ./funl-test-result.log
# Artefact

View file

@ -3,7 +3,7 @@
echo "install dependencies for unit-test script"
pwd
. ./gitlab-ci/shared.sh
source ./gitlab-ci/shared.sh
# install required packages
exec_cmd apt update

View file

@ -38,7 +38,7 @@ function exec_cmd()
function configure_genieacs()
{
sleep 10
sleep 3
echo "create a new user"
curl -X POST 'http://localhost:3000/init' -H "Content-Type: application/json" --data '{"users": true, "presets": true, "filters": true, "device": true, "index": true, "overview": true}' >/dev/null 2>&1
check_ret $?
@ -76,7 +76,7 @@ function configure_download_firmware()
function configure_acs_url()
{
url="http://$(hostname -i):7547"
url="http://127.0.0.1:7547"
uci set cwmp.acs.url=$url
uci commit cwmp
echo "Current ACS URL=$url"
@ -85,7 +85,7 @@ function configure_acs_url()
function check_cwmp_status()
{
status=`ubus call tr069 status | jq -r ".cwmp.status"`
if [ $status != "up" ]; then
if [ "${status}" != "up" ]; then
echo "icwmpd is not started correctly, (the current status=$status)"
exit 1
fi
@ -101,7 +101,7 @@ function clean_icwmp()
find -name '*.gcov' -exec rm {} -fv \;
find -name '*.deps' -exec rm {} -rfv \;
find -name '*.so' -exec rm {} -fv \;
rm -f *.o *.log *.xml vgcore.* firmware_v1.0.bin
rm -f *.o *.log *.xml firmware_v1.0.bin
rm -rf report
fi
}
@ -114,9 +114,13 @@ function build_icwmp()
# clean icwmp
clean_icwmp
mkdir -p /var/state
mkdir -p /var/run
mkdir -p /var/run/icwmpd
# compile icwmp
autoreconf -i >/dev/null 2>&1
./configure CFLAGS="$COV_CFLAGS -DWC_NO_HARDEN" LDFLAGS="$COV_LDFLAGS" --enable-acs=multi --enable-debug --enable-libopenssl >/dev/null 2>&1
./configure CFLAGS="$COV_CFLAGS -DWC_NO_HARDEN" LDFLAGS="$COV_LDFLAGS" --enable-acs=multi --enable-debug >/dev/null 2>&1
make CFLAGS="$COV_CFLAGS -DWC_NO_HARDEN" LDFLAGS="$COV_LDFLAGS"
check_ret $?
}

View file

@ -2,7 +2,7 @@
echo "preparation script"
pwd
. ./gitlab-ci/shared.sh
source ./gitlab-ci/shared.sh
trap cleanup EXIT
trap cleanup SIGINT

112
http.c
View file

@ -10,18 +10,26 @@
* Author Omar Kallel <omar.kallel@pivasoftware.com>
* Copyright (C) 2011-2012 Luka Perkov <freecwmp@lukaperkov.net>
*/
#include <curl/curl.h>
#include <arpa/inet.h>
#include <string.h>
#include <fcntl.h>
#include "http.h"
#include "cwmp_uci.h"
#include <curl/curl.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "log.h"
#include "event.h"
#include "ubus.h"
#include "config.h"
#include "event.h"
#include "http.h"
#include "digestauth.h"
#include "cwmp_uci.h"
#include "ubus.h"
#include "session.h"
#define REALM "authenticate@cwmp"
#define OPAQUE "11733b200778ce33060f31c9af70a870ba96ddd4"
@ -38,14 +46,14 @@ void http_set_timeout(void)
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1);
}
int http_client_init(struct cwmp *cwmp)
int http_client_init()
{
char *dhcp_dis = NULL;
char *acs_var_stat = NULL;
uci_get_value(UCI_DHCP_DISCOVERY_PATH, &dhcp_dis);
if (dhcp_dis && cwmp->retry_count_session > 0 && strcmp(dhcp_dis, "enable") == 0) {
if (dhcp_dis && cwmp_main->retry_count_session > 0 && strcmp(dhcp_dis, "enable") == 0) {
uci_get_state_value(UCI_DHCP_ACS_URL, &acs_var_stat);
if (acs_var_stat) {
if (icwmp_asprintf(&http_c.url, "%s", acs_var_stat) == -1) {
@ -54,13 +62,13 @@ int http_client_init(struct cwmp *cwmp)
return -1;
}
} else {
if (icwmp_asprintf(&http_c.url, "%s", cwmp->conf.acsurl) == -1) {
if (icwmp_asprintf(&http_c.url, "%s", cwmp_main->conf.acsurl) == -1) {
FREE(dhcp_dis);
return -1;
}
}
} else {
if (icwmp_asprintf(&http_c.url, "%s", cwmp->conf.acsurl) == -1) {
if (icwmp_asprintf(&http_c.url, "%s", cwmp_main->conf.acsurl) == -1) {
FREE(dhcp_dis);
return -1;
}
@ -78,7 +86,7 @@ int http_client_init(struct cwmp *cwmp)
if (!curl)
return -1;
if (cwmp->conf.ipv6_enable) {
if (cwmp_main->conf.ipv6_enable) {
unsigned char buf[sizeof(struct in6_addr)];
char *ip = NULL;
@ -130,7 +138,7 @@ static size_t http_get_response(void *buffer, size_t size, size_t rxed, char **m
return size * rxed;
}
int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **msg_in)
int http_send_message(char *msg_out, int msg_out_len, char **msg_in)
{
unsigned char buf[sizeof(struct in6_addr)];
int tmp = 0;
@ -152,21 +160,21 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **
if (!http_c.header_list)
return -1;
#endif /* ACS_FUSION */
if (cwmp->conf.http_disable_100continue) {
if (cwmp_main->conf.http_disable_100continue) {
http_c.header_list = curl_slist_append(http_c.header_list, "Expect:");
if (!http_c.header_list)
return -1;
}
curl_easy_setopt(curl, CURLOPT_URL, http_c.url);
curl_easy_setopt(curl, CURLOPT_USERNAME, cwmp->conf.acs_userid);
curl_easy_setopt(curl, CURLOPT_PASSWORD, cwmp->conf.acs_passwd);
curl_easy_setopt(curl, CURLOPT_USERNAME, cwmp_main->conf.acs_userid);
curl_easy_setopt(curl, CURLOPT_PASSWORD, cwmp_main->conf.acs_passwd);
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC | CURLAUTH_DIGEST);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, HTTP_TIMEOUT);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, HTTP_TIMEOUT);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
switch (cwmp->conf.compression) {
switch (cwmp_main->conf.compression) {
case COMP_NONE:
break;
case COMP_GZIP:
@ -196,14 +204,14 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, fc_cookies);
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, fc_cookies);
if (cwmp->conf.acs_ssl_capath)
curl_easy_setopt(curl, CURLOPT_CAPATH, cwmp->conf.acs_ssl_capath);
if (cwmp->conf.insecure_enable) {
if (cwmp_main->conf.acs_ssl_capath)
curl_easy_setopt(curl, CURLOPT_CAPATH, cwmp_main->conf.acs_ssl_capath);
if (cwmp_main->conf.insecure_enable) {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
}
curl_easy_setopt(curl, CURLOPT_INTERFACE, cwmp->conf.interface);
curl_easy_setopt(curl, CURLOPT_INTERFACE, cwmp_main->conf.interface);
*msg_in = (char *)calloc(1, sizeof(char));
res = curl_easy_perform(curl);
@ -246,7 +254,7 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **
}
if (http_code == 415) {
cwmp->conf.compression = COMP_NONE;
cwmp_main->conf.compression = COMP_NONE;
goto error;
}
if (http_code != 200 && http_code != 204)
@ -276,35 +284,34 @@ error:
void http_success_cr(void)
{
CWMP_LOG(INFO, "Connection Request thread: add connection request event in the queue");
pthread_mutex_lock(&(cwmp_main.mutex_session_queue));
cwmp_add_event_container(&cwmp_main, EVENT_IDX_6CONNECTION_REQUEST, "");
pthread_mutex_unlock(&(cwmp_main.mutex_session_queue));
pthread_cond_signal(&(cwmp_main.threshold_session_send));
pthread_mutex_lock(&start_session_mutext);
cwmp_ubus_call("tr069", "inform", CWMP_UBUS_ARGS{ {} }, 0, NULL, NULL);
pthread_mutex_unlock(&start_session_mutext);
}
static void http_cr_new_client(int client, bool service_available)
{
FILE *fp;
char buffer[BUFSIZ];
char auth_digest_buffer[BUFSIZ];
char auth_digest_buffer[BUFSIZ] = {0};
int8_t auth_status = 0;
bool auth_digest_checked = false;
bool method_is_get = false;
bool internal_error = false;
char cr_http_get_head[512];
pthread_mutex_lock(&mutex_config_load);
fp = fdopen(client, "r+");
char *username = cwmp_main.conf.cpe_userid;
char *password = cwmp_main.conf.cpe_passwd;
char *username = cwmp_main->conf.cpe_userid;
char *password = cwmp_main->conf.cpe_passwd;
if (!username || !password) {
// if we dont have username or password configured proceed with connecting to ACS
service_available = false;
goto http_end;
}
snprintf(cr_http_get_head, sizeof(cr_http_get_head), "GET %s HTTP/1.1", cwmp_main.conf.connection_request_path);
snprintf(cr_http_get_head, sizeof(cr_http_get_head), "GET %s HTTP/1.1", cwmp_main->conf.connection_request_path);
pthread_mutex_unlock(&mutex_config_load);
while (fgets(buffer, sizeof(buffer), fp)) {
if (!strncasecmp(buffer, cr_http_get_head, strlen(cr_http_get_head)))
method_is_get = true;
@ -341,24 +348,28 @@ http_end:
fputs("HTTP/1.1 200 OK\r\n", fp);
fputs("Connection: close\r\n", fp);
fputs("Content-Length: 0\r\n", fp);
fputs("\r\n", fp);
fclose(fp);
close(client);
http_success_cr();
} else if (internal_error) {
CWMP_LOG(INFO, "Receive Connection Request: Return 500 Internal Error");
fputs("HTTP/1.1 500 Internal Server Error\r\n", fp);
fputs("Connection: close\r\n", fp);
fputs("Content-Length: 0\r\n", fp);
}
else {
fputs("\r\n", fp);
fclose(fp);
close(client);
} else {
CWMP_LOG(INFO, "Receive Connection Request: Return 401 Unauthorized");
fputs("HTTP/1.1 401 Unauthorized\r\n", fp);
fputs("Connection: close\r\n", fp);
http_digest_auth_fail_response(fp, "GET", "/", REALM, OPAQUE);
fputs("\r\n", fp);
fputs("\r\n", fp);
fclose(fp);
close(client);
}
fputs("\r\n", fp);
fclose(fp);
pthread_mutex_unlock(&mutex_config_load);
}
void http_server_init(void)
@ -367,20 +378,20 @@ void http_server_init(void)
unsigned short cr_port;
for (;;) {
cr_port = (unsigned short)(cwmp_main.conf.connection_request_port);
cr_port = (unsigned short)(cwmp_main->conf.connection_request_port);
unsigned short i = (DEFAULT_CONNECTION_REQUEST_PORT == cr_port) ? 1 : 0;
//Create socket
cwmp_main.cr_socket_desc = socket(AF_INET6, SOCK_STREAM, 0);
if (cwmp_main.cr_socket_desc == -1) {
cwmp_main->cr_socket_desc = socket(AF_INET6, SOCK_STREAM, 0);
if (cwmp_main->cr_socket_desc == -1) {
CWMP_LOG(ERROR, "Could not open server socket for Connection Requests, Error no is : %d, Error description is : %s", errno, strerror(errno));
sleep(1);
continue;
}
fcntl(cwmp_main.cr_socket_desc, F_SETFD, fcntl(cwmp_main.cr_socket_desc, F_GETFD) | FD_CLOEXEC);
fcntl(cwmp_main->cr_socket_desc, F_SETFD, fcntl(cwmp_main->cr_socket_desc, F_GETFD) | FD_CLOEXEC);
int reusaddr = 1;
if (setsockopt(cwmp_main.cr_socket_desc, SOL_SOCKET, SO_REUSEADDR, &reusaddr, sizeof(int)) < 0) {
if (setsockopt(cwmp_main->cr_socket_desc, SOL_SOCKET, SO_REUSEADDR, &reusaddr, sizeof(int)) < 0) {
CWMP_LOG(WARNING, "setsockopt(SO_REUSEADDR) failed");
}
@ -391,7 +402,7 @@ void http_server_init(void)
for (;; i++) {
server.sin6_port = htons(cr_port);
//Bind
if (bind(cwmp_main.cr_socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) {
if (bind(cwmp_main->cr_socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) {
//print the error message
CWMP_LOG(ERROR, "Could not bind server socket on the port %d, Error no is : %d, Error description is : %s", cr_port, errno, strerror(errno));
cr_port = DEFAULT_CONNECTION_REQUEST_PORT + i;
@ -405,9 +416,11 @@ void http_server_init(void)
char cr_port_str[6];
snprintf(cr_port_str, 6, "%hu", cr_port);
cr_port_str[5] = '\0';
cwmp_uci_init();
cwmp_uci_set_value("cwmp", "cpe", "port", cr_port_str);
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
connection_request_port_value_change(&cwmp_main, cr_port);
connection_request_port_value_change(cr_port);
cwmp_uci_exit();
CWMP_LOG(INFO, "Connection Request server initiated with the port: %d", cr_port);
}
@ -419,15 +432,15 @@ void http_server_listen(void)
struct sockaddr_in6 client;
//Listen
listen(cwmp_main.cr_socket_desc, 3);
listen(cwmp_main->cr_socket_desc, 3);
//Accept and incoming connection
c = sizeof(struct sockaddr_in);
while ((client_sock = accept(cwmp_main.cr_socket_desc, (struct sockaddr *)&client, (socklen_t *)&c))) {
while ((client_sock = accept(cwmp_main->cr_socket_desc, (struct sockaddr *)&client, (socklen_t *)&c))) {
bool service_available;
time_t current_time;
if (thread_end)
if (cwmp_stop)
return;
current_time = time(NULL);
@ -443,7 +456,6 @@ void http_server_listen(void)
}
}
http_cr_new_client(client_sock, service_available);
close(client_sock);
}
if (client_sock < 0) {

View file

@ -38,9 +38,9 @@ struct search_keywords {
extern pthread_mutex_t mutex_backup_session;
int cwmp_init_backup_session(struct cwmp *cwmp, char **ret, enum backup_loading load);
int cwmp_init_backup_session(char **ret, enum backup_loading load);
void bkp_session_save();
int cwmp_load_saved_session(struct cwmp *cwmp, char **acsurl, enum backup_loading load);
int cwmp_load_saved_session(char **acsurl, enum backup_loading load);
mxml_node_t *bkp_session_insert_event(int index, char *command_key, int id, char *status);
void bkp_session_delete_event(int id, char *status);
void bkp_session_simple_insert_in_parent(char *parent, char *child, char *value);
@ -58,7 +58,7 @@ void bkp_session_insert_change_du_state(struct change_du_state *pchange_du_state
void bkp_session_delete_change_du_state(struct change_du_state *pchange_du_state);
void bkp_session_insert_transfer_complete(struct transfer_complete *ptransfer_complete);
void bkp_session_delete_transfer_complete(struct transfer_complete *ptransfer_complete);
int save_acs_bkp_config(struct cwmp *cwmp);
int save_acs_bkp_config();
void bkp_session_insert_schedule_download(struct download *pschedule_download);
void bkp_session_insert_apply_schedule_download(struct apply_schedule_download *papply_schedule_download);

View file

@ -11,11 +11,17 @@
#ifndef __CCOMMON_H
#define __CCOMMON_H
#include <stdbool.h>
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdbool.h>
#include <math.h>
#include <libubox/list.h>
#include <sys/time.h>
#include <pthread.h>
#include <stdbool.h>
#include <libubox/uloop.h>
#ifndef CWMP_VERSION
#define CWMP_VERSION "3.0.0"
@ -48,12 +54,15 @@
#define MAX_NBRE_SERVICES 256
#define FIREWALL_CWMP "/etc/firewall.cwmp"
#define CWMP_VARSTATE_UCI_PACKAGE "/var/state/cwmp"
#define STRCMP(S1, S2) ((S1 != NULL && S2 != NULL) ? strcmp(S1, S2) : -1)
extern char *commandKey;
extern bool thread_end;
extern bool signal_exit;
extern bool cwmp_stop;
extern bool ubus_exit;
extern struct uloop_timeout session_timer;
extern struct uloop_timeout priodic_session_timer;
extern struct uloop_timeout retry_session_timer;
extern bool g_firewall_restart;
typedef struct env {
unsigned short boot;
@ -109,45 +118,25 @@ struct deviceid {
char *softwareversion;
};
typedef struct session_status {
time_t last_start_time;
time_t last_end_time;
int last_status;
time_t next_periodic;
time_t next_retry;
unsigned int success_session;
unsigned int failure_session;
} session_status;
typedef struct cwmp {
struct env env;
struct config conf;
struct deviceid deviceid;
struct list_head head_session_queue;
pthread_mutex_t mutex_session_queue;
struct session *session_send;
struct session *session;
bool cwmp_cr_event;
pthread_mutex_t mutex_session_send;
pthread_cond_t threshold_session_send;
pthread_mutex_t mutex_periodic;
pthread_mutex_t mutex_notify_periodic;
pthread_cond_t threshold_periodic;
pthread_cond_t threshold_notify_periodic;
pthread_cond_t threshold_handle_notify;
int count_handle_notify;
int retry_count_session;
struct list_head *head_event_container;
FILE *pid_file;
time_t start_time;
struct session_status session_status;
unsigned int cwmp_id;
int event_id;
int cr_socket_desc;
int event_id;
int cwmp_period;
time_t cwmp_periodic_time;
bool cwmp_periodic_enable;
bool is_boot;
bool custom_notify_active;
bool start_diagnostics;
} cwmp;
enum action {
@ -157,6 +146,11 @@ enum action {
RESTART,
};
enum auth_type_enum {
AUTH_BASIC,
AUTH_DIGEST
};
enum cwmp_start { CWMP_START_BOOT = 1, CWMP_START_PERIODIC = 2 };
enum cwmp_ret_err {
@ -321,15 +315,15 @@ enum client_server_faults { FAULT_CPE_TYPE_CLIENT, FAULT_CPE_TYPE_SERVER };
struct rpc_cpe_method {
const char *name;
int (*handler)(struct session *session, struct rpc *rpc);
int (*handler)(struct rpc *rpc);
int amd;
};
struct rpc_acs_method {
const char *name;
int (*prepare_message)(struct cwmp *cwmp, struct session *session, struct rpc *rpc);
int (*parse_response)(struct cwmp *cwmp, struct session *session, struct rpc *rpc);
int (*extra_clean)(struct session *session, struct rpc *rpc);
int (*prepare_message)(struct rpc *rpc);
int (*parse_response)(struct rpc *rpc);
int (*extra_clean)(struct rpc *rpc);
};
typedef struct FAULT_CPE {
@ -355,6 +349,7 @@ typedef struct timewindow {
typedef struct download {
struct list_head list;
struct uloop_timeout handler_timer ;
time_t scheduled_time;
int file_size;
char *command_key;
@ -399,6 +394,7 @@ typedef struct operations {
typedef struct upload {
struct list_head list;
struct uloop_timeout handler_timer ;
time_t scheduled_time;
char *command_key;
char *file_type;
@ -441,7 +437,7 @@ typedef struct opfault {
char *fault_string;
} opfault;
extern struct cwmp cwmp_main;
extern struct cwmp *cwmp_main;
extern long int flashsize;
extern struct FAULT_CPE FAULT_CPE_ARRAY[];
extern struct cwmp_namespaces ns;
@ -483,11 +479,15 @@ bool icwmp_validate_string_length(char *arg, int max_length);
bool icwmp_validate_boolean_value(char *arg);
bool icwmp_validate_unsignedint(char *arg);
bool icwmp_validate_int_in_range(char *arg, int min, int max);
void load_forced_inform_json_file(struct cwmp *cwmp);
void load_forced_inform_json_file();
void clean_custom_inform_parameters();
char *string_to_hex(const unsigned char *str, size_t size);
int copy_file(char *source_file, char *target_file);
int get_connection_interface();
int cwmp_get_session_retry_interval();
int cwmp_apply_acs_changes();
void check_firewall_restart_state();
void cwmp_end_handler(int signal_num __attribute__((unused)));
#ifndef FREE
#define FREE(x) \
do { \

View file

@ -13,13 +13,14 @@
#ifndef _CONFIG_H__
#define _CONFIG_H__
#include "cwmp_uci.h"
#include <pthread.h>
#include "common.h"
extern pthread_mutex_t mutex_config_load;
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);
int global_conf_init();
int get_global_config();
int cwmp_config_reload();
int reload_networking_config();
#endif

View file

@ -11,6 +11,7 @@ struct cmd_input {
char *second_input;
};
char *cmd_get_exec_func(struct cmd_input in, union cmd_result *res);
char *cmd_set_exec_func(struct cmd_input in, union cmd_result *res __attribute__((unused)));
char *cmd_add_exec_func(struct cmd_input in, union cmd_result *res);

6
inc/cwmp_config.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef CWMP_CONF_H
#define CWMP_CONF_H
int cwmp_get_deviceid();
#endif

View file

@ -11,8 +11,6 @@
#ifndef CWMP_DU_STATE_H
#define CWMP_DU_STATE_H
#include "common.h"
extern struct list_head list_change_du_state;
extern pthread_mutex_t mutex_change_du_state;
extern pthread_cond_t threshold_change_du_state;
@ -20,7 +18,7 @@ extern pthread_cond_t threshold_change_du_state;
int cwmp_du_install(char *url, char *uuid, char *user, char *pass, char *env, char **package_version, char **package_name, char **package_uuid, char **package_env, char **fault_code);
int cwmp_du_update(char *url, char *uuid, char *user, char *pass, char **package_version, char **package_name, char **package_uuid, char **package_env, char **fault_code);
int cwmp_du_uninstall(char *package_name, char *package_env, char **fault_code);
int cwmp_rpc_acs_destroy_data_du_state_change_complete(struct session *session, struct rpc *rpc);
int cwmp_rpc_acs_destroy_data_du_state_change_complete(struct rpc *rpc);
void *thread_cwmp_rpc_cpe_change_du_state(void *v);
int cwmp_free_change_du_state_request(struct change_du_state *change_du_state);
#endif

5
inc/cwmp_event.h Normal file
View file

@ -0,0 +1,5 @@
#ifndef CWMP_EVENT_H
#define CWMP_EVENT_H
#include "event.h"
struct event_container *cwmp_add_event_container(int event_code, char *command_key);
#endif

7
inc/cwmp_http.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef CWMP_HTTP_H
#define CWMP_HTTP_H
#include "http.h"
extern pthread_t http_cr_server_thread;
void http_server_start(void);
#endif

View file

@ -14,8 +14,6 @@
#include <uci.h>
#include "common.h"
//struct uci_context *cwmp_uci_ctx = ((void *)0);
#define UCI_DHCP_DISCOVERY_PATH "cwmp.acs.dhcp_discovery"
#define UCI_ACS_URL_PATH "cwmp.acs.url"

View file

@ -1,6 +1,5 @@
#ifndef SRC_DATAMODELIFACE_H_
#define SRC_DATAMODELIFACE_H_
#include "common.h"
#define DM_ROOT_OBJ "Device."

View file

@ -1,8 +1,6 @@
#ifndef CWMP_DOWNLOAD_H
#define CWMP_DOWNLOAD_H
#include "common.h"
#define DOWNLOAD_PROTOCOL_HTTP "http://"
#define DOWNLOAD_PROTOCOL_HTTPS "https://"
#define DOWNLOAD_PROTOCOL_FTP "ftp://"
@ -22,14 +20,8 @@
extern struct list_head list_download;
extern struct list_head list_schedule_download;
extern struct list_head list_apply_schedule_download;
extern pthread_mutex_t mutex_download;
extern pthread_cond_t threshold_download;
extern pthread_mutex_t mutex_schedule_download;
extern pthread_cond_t threshold_schedule_download;
extern pthread_mutex_t mutex_apply_schedule_download;
extern pthread_cond_t threshold_apply_schedule_download;
extern int count_download_queue;
@ -39,9 +31,10 @@ int cwmp_free_apply_schedule_download_request(struct apply_schedule_download *ap
int cwmp_scheduledDownload_remove_all();
int cwmp_scheduled_Download_remove_all();
int cwmp_apply_scheduled_Download_remove_all();
int cwmp_rpc_acs_destroy_data_transfer_complete(struct session *session, struct rpc *rpc);
void *thread_cwmp_rpc_cpe_download(void *v);
int cwmp_rpc_acs_destroy_data_transfer_complete(struct rpc *rpc);
void *thread_cwmp_rpc_cpe_schedule_download(void *v);
void *thread_cwmp_rpc_cpe_apply_schedule_download(void *v);
int cwmp_launch_download(struct download *pdownload, char *download_file_name, enum load_type ltype, struct transfer_complete **ptransfer_complete);
void cwmp_start_download(struct uloop_timeout *timeout);
void cwmp_start_schedule_download(struct uloop_timeout *timeout);
#endif

View file

@ -11,9 +11,8 @@
#ifndef EVENT_H_
#define EVENT_H_
#include "common.h"
#include "session.h"
#include "event.h"
typedef struct event_container {
struct list_head list;
@ -67,18 +66,17 @@ enum event_idx_enum
};
extern const struct EVENT_CONST_STRUCT EVENT_CONST[__EVENT_IDX_MAX];
extern pthread_mutex_t add_event_mutext;
struct event_container *cwmp_add_event_container(struct cwmp *cwmp, int event_idx, char *command_key);
int event_remove_all_event_container(struct session *session, int rem_from);
int event_remove_noretry_event_container(struct session *session, struct cwmp *cwmp);
int event_remove_all_event_container(int rem_from);
int event_remove_noretry_event_container();
void cwmp_save_event_container(struct event_container *event_container);
void *thread_event_periodic(void *v);
void connection_request_ip_value_change(struct cwmp *cwmp, int version);
void connection_request_port_value_change(struct cwmp *cwmp, int port);
void connection_request_ip_value_change(int version);
void connection_request_port_value_change(int port);
int cwmp_get_int_event_code(const char *code);
bool event_exist_in_list(struct cwmp *cwmp, int event);
int cwmp_root_cause_events(struct cwmp *cwmp);
int cwmp_root_cause_transfer_complete(struct cwmp *cwmp, struct transfer_complete *p);
int cwmp_root_cause_changedustate_complete(struct cwmp *cwmp, struct du_state_change_complete *p);
void cwmp_root_cause_event_ipdiagnostic(void);
bool event_exist_in_list(int event);
int cwmp_root_cause_events();
int cwmp_root_cause_transfer_complete(struct transfer_complete *p);
int cwmp_root_cause_changedustate_complete(struct du_state_change_complete *p);
void cwmp_root_cause_event_diagnostic(void);
#endif /* SRC_INC_EVENT_H_ */

View file

@ -11,7 +11,6 @@
#define _FREECWMP_HTTP_H__
#include "common.h"
extern char *fc_cookies;
#define HTTP_TIMEOUT 30
@ -23,12 +22,12 @@ struct http_client {
void http_set_timeout(void);
int http_client_init(struct cwmp *cwmp);
int http_client_init();
void http_client_exit(void);
int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **msg_in);
int http_send_message(char *msg_out, int msg_out_len, char **msg_in);
int http_cr_server_init(void);
void http_success_cr(void);
void http_server_init(void);
void http_server_listen(void);
void http_success_cr(void);
#endif

View file

@ -18,12 +18,15 @@
#ifndef MD5_H
#define MD5_H
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#ifdef WORDS_BIGENDIAN
#define HIGHFIRST
#endif
#include <stdint.h>
#define MD5_DIGEST_SIZE 16
struct MD5Context {

View file

@ -15,5 +15,6 @@
int netlink_init(void);
int netlink_init_v6(void);
void cwmp_netlink_init(void);
#endif

View file

@ -11,12 +11,15 @@
#ifndef NOTIFICATIONS_H_
#define NOTIFICATIONS_H_
#include <sys/socket.h>
#include <pthread.h>
#include <libubox/blobmsg_json.h>
#include <libubus.h>
#include "common.h"
#include "event.h"
#include "datamodel_interface.h"
#include "soap.h"
enum NOTIFICATION_STATUS
{
@ -32,6 +35,7 @@ extern struct list_head list_lw_value_change;
extern struct list_head list_value_change;
extern pthread_mutex_t mutex_value_change;
extern struct list_head list_param_obj_notify;
extern struct uloop_timeout check_notify_timer;
/*#define foreach_parameter_notification(function, parameter, notification) \
#ifndef NOTIF_VARIABLES_##function \
@ -52,18 +56,21 @@ void cwmp_update_enabled_notify_file(void);
int check_value_change(void);
void create_list_param_obj_notify();
void create_list_param_leaf_notify();
void sotfware_version_value_change(struct cwmp *cwmp, struct transfer_complete *p);
void sotfware_version_value_change(struct transfer_complete *p);
void *thread_periodic_check_notify(void *v);
void send_active_value_change(void);
void add_list_value_change(char *param_name, char *param_data, char *param_type);
void clean_list_value_change();
char *cwmp_set_parameter_attributes(char *parameter_name, int notification);
char *cwmp_get_parameter_attributes(char *parameter_name, struct list_head *parameters_list);
void load_custom_notify_json(struct cwmp *cwmp);
void load_custom_notify_json();
void add_lw_list_value_change(char *param_name, char *param_data, char *param_type);
char *calculate_lwnotification_cnonce();
void cwmp_lwnotification();
void clean_list_param_notify();
void init_list_param_notify();
void reinit_list_param_notify();
void cwmp_prepare_value_change();
void periodic_check_notifiy(struct uloop_timeout *timeout __attribute__((unused)));
void trigger_periodic_notify_check();
#endif /* SRC_INC_NOTIFICATIONS_H_ */

View file

@ -13,7 +13,7 @@
#include "common.h"
void launch_reboot_methods(struct cwmp *cwmp);
void launch_reboot_methods();
#endif //_REBOOT_H__

View file

@ -1,58 +0,0 @@
/*
* 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) 2013-2019 iopsys Software Solutions AB
* Author Mohamed Kallel <mohamed.kallel@pivasoftware.com>
* Author Ahmed Zribi <ahmed.zribi@pivasoftware.com>
* Copyright (C) 2011 Luka Perkov <freecwmp@lukaperkov.net>
*
*/
#ifndef __RPC__SOAP__H_
#define __RPC__SOAP__H_
#include "common.h"
#include "session.h"
#define MAX_NBRE_CUSTOM_INFORM 256
extern char *custom_forced_inform_parameters[MAX_NBRE_CUSTOM_INFORM];
extern char *boot_inform_parameters[MAX_NBRE_CUSTOM_INFORM];
extern int nbre_custom_inform;
extern int nbre_boot_inform;
extern const struct rpc_cpe_method rpc_cpe_methods[__RPC_CPE_MAX];
extern const struct rpc_acs_method rpc_acs_methods[__RPC_ACS_MAX];
int cwmp_handle_rpc_cpe_get_rpc_methods(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_set_parameter_attributes(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_add_object(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_delete_object(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_reboot(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_factory_reset(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct session *session, struct rpc *rpc);
int cancel_transfer(char *key);
int cwmp_handle_rpc_cpe_cancel_transfer(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_schedule_inform(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_change_du_state(struct session *session, struct rpc *rpc);
int cwmp_handle_rpc_cpe_fault(struct session *session, struct rpc *rpc);
int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *session, struct rpc *rpc);
int cwmp_rpc_acs_parse_response_inform(struct cwmp *cwmp, struct session *session, struct rpc *rpc);
int cwmp_rpc_acs_prepare_get_rpc_methods(struct cwmp *cwmp, struct session *session, struct rpc *rpc);
int cwmp_rpc_acs_prepare_transfer_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc);
int cwmp_rpc_acs_prepare_du_state_change_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc);
int cwmp_rpc_acs_destroy_data_inform(struct session *session, struct rpc *rpc);
int xml_handle_message(struct session *session);
int cwmp_create_fault_message(struct session *session, struct rpc *rpc_cpe, int fault_code);
#endif

View file

@ -11,8 +11,6 @@
#ifndef CWMP_SCHED_INFORM_H
#define CWMP_SCHED_INFORM_H
#include "common.h"
extern struct list_head list_schedule_inform;
extern pthread_mutex_t mutex_schedule_inform;
extern pthread_cond_t threshold_schedule_inform;

View file

@ -15,11 +15,24 @@
#include <microxml.h>
#include "common.h"
extern struct uloop_timeout retry_session_timer;
extern pthread_mutex_t start_session_mutext;
typedef struct session_status {
time_t last_start_time;
time_t last_end_time;
int last_status;
time_t next_periodic;
time_t next_retry;
unsigned int success_session;
unsigned int failure_session;
} session_status;
typedef struct session {
struct list_head list;
struct list_head head_event_container;
struct list_head head_rpc_cpe;
struct list_head head_rpc_acs;
struct list_head events;
struct session_status session_status;
mxml_node_t *tree_in;
mxml_node_t *tree_out;
mxml_node_t *body_in;
@ -45,7 +58,10 @@ enum end_session_enum
END_SESSION_SERVERSELECTION_DIAGNOSTIC = 1 << 11,
END_SESSION_SET_NOTIFICATION_UPDATE = 1 << 12,
END_SESSION_RESTART_SERVICES = 1 << 13,
END_SESSION_INIT_NOTIFY = 1 << 14
END_SESSION_INIT_NOTIFY = 1 << 14,
END_SESSION_DOWNLOAD = 1 << 15,
END_SESSION_SCHEDULE_DOWNLOAD = 1 << 16,
END_SESSION_UPLOAD = 1 << 17
};
enum enum_session_status
@ -59,13 +75,19 @@ enum enum_session_status
extern unsigned int end_session_flag;
void cwmp_set_end_session(unsigned int flag);
struct rpc *cwmp_add_session_rpc_cpe(struct session *session, int type);
struct session *cwmp_add_queue_session(struct cwmp *cwmp);
struct rpc *cwmp_add_session_rpc_acs(struct session *session, int type);
int cwmp_apply_acs_changes();
int cwmp_move_session_to_session_send(struct cwmp *cwmp, struct session *session);
struct rpc *cwmp_add_session_rpc_acs_head(struct session *session, int type);
struct rpc *cwmp_add_session_rpc_cpe(int type);
struct rpc *cwmp_add_session_rpc_acs(int type);
struct rpc *cwmp_add_session_rpc_acs_head(int type);
int cwmp_session_rpc_destructor(struct rpc *rpc);
int cwmp_session_destructor(struct session *session);
int cwmp_move_session_to_session_queue(struct cwmp *cwmp, struct session *session);
void trigger_cwmp_session_timer();
void trigger_session_by_ubus(char *event);
void initiate_cwmp_periodic_session_feature();
int run_session_end_func(void);
void cwmp_schedule_session(struct uloop_timeout *timeout);
void start_cwmp_session();
int create_cwmp_session_structure();
int clean_cwmp_session_structure();
void set_cwmp_session_status(int status, int retry_time);
int cwmp_session_init();
int cwmp_session_exit();
#endif /* SRC_INC_SESSION_H_ */

64
inc/soap.h Normal file
View file

@ -0,0 +1,64 @@
/*
* 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) 2013-2019 iopsys Software Solutions AB
* Author Mohamed Kallel <mohamed.kallel@pivasoftware.com>
* Author Ahmed Zribi <ahmed.zribi@pivasoftware.com>
* Copyright (C) 2011 Luka Perkov <freecwmp@lukaperkov.net>
*
*/
#ifndef __RPC__SOAP__H_
#define __RPC__SOAP__H_
#include <microxml.h>
#include "common.h"
#include "session.h"
#include "xml.h"
#define PROCESSING_DELAY (1) // In download/upload the message enqueued before sending the response, which cause the download/upload
// to start just before the time. This delay is to compensate the time lapsed during the message enqueue and response
#define MAX_NBRE_CUSTOM_INFORM 256
extern char *custom_forced_inform_parameters[MAX_NBRE_CUSTOM_INFORM];
extern char *boot_inform_parameters[MAX_NBRE_CUSTOM_INFORM];
extern int nbre_custom_inform;
extern int nbre_boot_inform;
extern const struct rpc_cpe_method rpc_cpe_methods[__RPC_CPE_MAX];
extern const struct rpc_acs_method rpc_acs_methods[__RPC_ACS_MAX];
int cwmp_handle_rpc_cpe_get_rpc_methods(struct rpc *rpc);
int cwmp_handle_rpc_cpe_set_parameter_values(struct rpc *rpc);
int cwmp_handle_rpc_cpe_get_parameter_values(struct rpc *rpc);
int cwmp_handle_rpc_cpe_get_parameter_names(struct rpc *rpc);
int cwmp_handle_rpc_cpe_set_parameter_attributes(struct rpc *rpc);
int cwmp_handle_rpc_cpe_get_parameter_attributes(struct rpc *rpc);
int cwmp_handle_rpc_cpe_add_object(struct rpc *rpc);
int cwmp_handle_rpc_cpe_delete_object(struct rpc *rpc);
int cwmp_handle_rpc_cpe_reboot(struct rpc *rpc);
int cwmp_handle_rpc_cpe_download(struct rpc *rpc);
int cwmp_handle_rpc_cpe_upload(struct rpc *rpc);
int cwmp_handle_rpc_cpe_factory_reset(struct rpc *rpc);
int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct rpc *rpc);
int cancel_transfer(char *key);
int cwmp_handle_rpc_cpe_cancel_transfer(struct rpc *rpc);
int cwmp_handle_rpc_cpe_schedule_inform(struct rpc *rpc);
int cwmp_handle_rpc_cpe_schedule_download(struct rpc *rpc);
int cwmp_handle_rpc_cpe_change_du_state(struct rpc *rpc);
int cwmp_handle_rpc_cpe_fault(struct rpc *rpc);
int cwmp_rpc_acs_prepare_message_inform(struct rpc *rpc);
int cwmp_rpc_acs_parse_response_inform(struct rpc *rpc);
int cwmp_rpc_acs_prepare_get_rpc_methods(struct rpc *rpc);
int cwmp_rpc_acs_prepare_transfer_complete(struct rpc *rpc);
int cwmp_rpc_acs_prepare_du_state_change_complete(struct rpc *rpc);
int cwmp_rpc_acs_destroy_data_inform(struct rpc *rpc);
int xml_handle_message();
int cwmp_create_fault_message(struct rpc *rpc_cpe, int fault_code);
#endif

7
inc/subprocess.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef SUB_PROC_H
#define SUB_PROC_H
typedef char* (*task_function)(char *task_arg);
int subprocess_start(task_function task_fun);
char *execute_task_in_subprocess(char *task);
#endif

View file

@ -11,18 +11,14 @@
*/
#ifndef _FREECWMP_UBUS_H__
#define _FREECWMP_UBUS_H__
#include <libubus.h>
/*
#include <json-c/json.h>
#include <libubox/blobmsg_json.h>
#include <libubus.h>
#include "common.h"
*/
#include "common.h"
#define ARRAY_MAX 8
int cwmp_ubus_init(struct cwmp *cwmp);
int cwmp_ubus_init();
void cwmp_ubus_exit(void);
enum cwmp_ubus_arg_type

View file

@ -11,14 +11,12 @@
#ifndef CWMP_UPLOAD_H
#define CWMP_UPLOAD_H
#include "common.h"
extern struct list_head list_upload;
extern pthread_mutex_t mutex_upload;
extern pthread_cond_t threshold_upload;
int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptransfer_complete);
void *thread_cwmp_rpc_cpe_upload(void *v);
int cwmp_scheduledUpload_remove_all();
int cwmp_free_upload_request(struct upload *upload);
void cwmp_start_upload(struct uloop_timeout *timeout);
#endif

View file

@ -2,8 +2,10 @@
#define __XML__H_
#include <microxml.h>
#include <stdio.h>
#include <stdlib.h>
#include "session.h"
#include "common.h"
#define CWMP_MXML_TAB_SPACE " "
#define MAX_SCHEDULE_INFORM_QUEUE 10
@ -17,13 +19,13 @@
} while (0)
extern const char *cwmp_urls[];
int xml_prepare_msg_out(struct session *session);
int xml_prepare_msg_out();
int xml_prepare_lwnotification_message(char **msg_out);
int xml_set_cwmp_id_rpc_cpe(struct session *session);
int xml_set_cwmp_id_rpc_cpe();
int xml_recreate_namespace(mxml_node_t *tree);
const char *whitespace_cb(mxml_node_t *node, int where);
int xml_set_cwmp_id(struct session *session);
int xml_send_message(struct cwmp *cwmp, struct session *session, struct rpc *rpc);
int xml_set_cwmp_id();
int xml_send_message(struct rpc *rpc);
mxml_node_t *mxmlFindElementOpaque(mxml_node_t *node, mxml_node_t *top, const char *text, int descend);
char *xml_get_cwmp_version(int version);
void xml_exit(void);

11
log.c
View file

@ -10,14 +10,13 @@
*
*/
#include <syslog.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/stat.h>
#include "log.h"
#include <stdarg.h>
#include <syslog.h>
#include <sys/types.h>
#include <unistd.h>
#include "common.h"
#include "log.h"
static char *SEVERITY_NAMES[8] = { "[EMERG] ", "[ALERT] ", "[CRITIC] ", "[ERROR] ", "[WARNING]", "[NOTICE] ", "[INFO] ", "[DEBUG] " };
static int log_severity = DEFAULT_LOG_SEVERITY;

3
md5.c
View file

@ -15,9 +15,6 @@
* will fill a supplied 16-byte array with the digest.
*/
#include <string.h>
#include "md5.h"
#if __BYTE_ORDER == __BIG_ENDIAN

View file

@ -11,20 +11,29 @@
*
*/
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <getopt.h>
#include <limits.h>
#include <locale.h>
#include <unistd.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <linux/rtnetlink.h>
#include <linux/netlink.h>
#include <stddef.h>
#include <libubox/uloop.h>
#include <string.h>
#include <stdlib.h>
#include <linux/rtnetlink.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "netlink.h"
#include "cwmp_uci.h"
#include <libubox/uloop.h>
#include <libubox/usock.h>
#include "http.h"
#include "log.h"
#include "config.h"
#include "event.h"
#include "cwmp_uci.h"
static int itfcmp(char *itf1, char *itf2);
static void netlink_new_msg(struct uloop_fd *ufd, unsigned events);
@ -108,18 +117,18 @@ static void freecwmp_netlink_interface(struct nlmsghdr *nlh)
}
if_indextoname(ifa->ifa_index, if_name);
if (itfcmp(cwmp_main.conf.interface, if_name)) {
if (itfcmp(cwmp_main->conf.interface, if_name)) {
rth = RTA_NEXT(rth, rtl);
continue;
}
inet_ntop(AF_INET, &(addr), if_addr, INET_ADDRSTRLEN);
FREE(cwmp_main.conf.ip);
cwmp_main.conf.ip = strdup(if_addr);
cwmp_uci_set_varstate_value("cwmp", "cpe", "ip", cwmp_main.conf.ip);
FREE(cwmp_main->conf.ip);
cwmp_main->conf.ip = strdup(if_addr);
cwmp_uci_set_varstate_value("cwmp", "cpe", "ip", cwmp_main->conf.ip);
cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG);
connection_request_ip_value_change(&cwmp_main, IPv4);
connection_request_ip_value_change(IPv4);
break;
}
} else { //CASE IPv6
@ -131,16 +140,16 @@ static void freecwmp_netlink_interface(struct nlmsghdr *nlh)
}
inet_ntop(AF_INET6, RTA_DATA(rth), pradd_v6, sizeof(pradd_v6));
if_indextoname(ifa->ifa_index, if_name);
if (strncmp(cwmp_main.conf.interface, if_name, IFNAMSIZ)) {
if (strncmp(cwmp_main->conf.interface, if_name, IFNAMSIZ)) {
rth = RTA_NEXT(rth, rtl);
continue;
}
FREE(cwmp_main.conf.ipv6);
cwmp_main.conf.ipv6 = strdup(pradd_v6);
cwmp_uci_set_varstate_value("cwmp", "cpe", "ipv6", cwmp_main.conf.ip);
FREE(cwmp_main->conf.ipv6);
cwmp_main->conf.ipv6 = strdup(pradd_v6);
cwmp_uci_set_varstate_value("cwmp", "cpe", "ipv6", cwmp_main->conf.ip);
cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG);
connection_request_ip_value_change(&cwmp_main, IPv6);
connection_request_ip_value_change(IPv6);
break;
}
}
@ -277,3 +286,16 @@ int netlink_init(void)
return 0;
}
void cwmp_netlink_init(void)
{
if (netlink_init()) {
CWMP_LOG(ERROR, "netlink initialization failed");
}
if (cwmp_main->conf.ipv6_enable) {
if (netlink_init_v6()) {
CWMP_LOG(ERROR, "netlink initialization failed");
}
}
}

View file

@ -8,22 +8,24 @@
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*
*/
#include <unistd.h>
#include <netdb.h>
#include <libubox/list.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "notifications.h"
#include "ubus.h"
#include "cwmp_uci.h"
#include "datamodel_interface.h"
#include "ssl_utils.h"
#include "log.h"
#include "event.h"
#include "xml.h"
#include "cwmp_event.h"
#include "ssl_utils.h"
LIST_HEAD(list_value_change);
LIST_HEAD(list_lw_value_change);
LIST_HEAD(list_param_obj_notify);
pthread_mutex_t mutex_value_change = PTHREAD_MUTEX_INITIALIZER;
struct uloop_timeout check_notify_timer = { .cb = periodic_check_notifiy };
char *notifications[7] = {"disabled" , "passive", "active", "passive_lw", "passive_passive_lw", "active_lw", "passive_active_lw"};
@ -206,9 +208,7 @@ int get_parameter_leaf_notification_from_childs_list(char *parameter_name, struc
{
char *parent = NULL;
int ret_notif = -1;
struct cwmp_dm_parameter *param_value;
if (childs_list == NULL)
return -1;
struct cwmp_dm_parameter *param_value = NULL;
list_for_each_entry (param_value, childs_list, list) {
if (strcmp(param_value->name, parameter_name) == 0) {
ret_notif = param_value->notification;
@ -238,7 +238,7 @@ char *cwmp_get_parameter_attributes(char *parameter_name, struct list_head *para
cwmp_free_all_dm_parameter_list(&childs_notifs);
return error;
}
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
list_for_each_entry (param_value, &params_list, list) {
int notif_leaf;
notif_leaf = check_parameter_forced_notification(param_value->name);
@ -265,13 +265,11 @@ char *cwmp_get_parameter_attributes(char *parameter_name, struct list_head *para
bool parameter_is_other_notif_object_child(char *parent, char *parameter)
{
struct list_head list_iter, *list_ptr;
// cppcheck-suppress unreadVariable
list_iter.next = list_param_obj_notify.next;
list_iter.prev = list_param_obj_notify.prev;
struct cwmp_dm_parameter *dm_parameter = NULL;
while (list_iter.prev != &list_param_obj_notify) {
struct cwmp_dm_parameter *dm_parameter;
if (list_iter.prev == NULL)
continue;
dm_parameter = list_entry(list_iter.prev, struct cwmp_dm_parameter, list);
list_ptr = list_iter.prev;
list_iter.prev = list_ptr->prev;
@ -304,7 +302,7 @@ void create_list_param_obj_notify()
char* updated_list_param_leaf_notify_with_sub_parameter_list(struct list_head *list_param_leaf_notify, struct cwmp_dm_parameter parent_parameter, void (*update_notify_file_line_arg)(FILE *notify_file, char *param_name, char *param_type, char *param_value, int notification), FILE* notify_file_arg)
{
struct cwmp_dm_parameter *param_iter;
struct cwmp_dm_parameter *param_iter = NULL;
LIST_HEAD(params_list);
char *err = cwmp_get_parameter_values(parent_parameter.name, &params_list);
if (err)
@ -323,7 +321,7 @@ char* updated_list_param_leaf_notify_with_sub_parameter_list(struct list_head *l
void create_list_param_leaf_notify(struct list_head *list_param_leaf_notify, void (*update_notify_file_line_arg)(FILE *notify_file, char *param_name, char *param_type, char *param_value, int notification), FILE* notify_file_arg)
{
struct cwmp_dm_parameter *param_iter;
struct cwmp_dm_parameter *param_iter = NULL;;
int i;
for (i = 0; i < (int)ARRAY_SIZE(forced_notifications_parameters); i++)
@ -389,15 +387,15 @@ void cwmp_update_enabled_notify_file(void)
/*
* Load custom notify json file
*/
void load_custom_notify_json(struct cwmp *cwmp)
void load_custom_notify_json()
{
struct blob_buf bbuf;
struct blob_attr *cur;
struct blob_attr *custom_notify_list = NULL;
int rem;
cwmp->custom_notify_active = false;
if (cwmp->conf.custom_notify_json == NULL || !file_exists(cwmp->conf.custom_notify_json))
cwmp_main->custom_notify_active = false;
if (cwmp_main->conf.custom_notify_json == NULL || !file_exists(cwmp_main->conf.custom_notify_json))
return;
if (file_exists(NOTIFY_FILE))
@ -406,8 +404,8 @@ void load_custom_notify_json(struct cwmp *cwmp)
memset(&bbuf, 0, sizeof(struct blob_buf));
blob_buf_init(&bbuf, 0);
if (blobmsg_add_json_from_file(&bbuf, cwmp->conf.custom_notify_json) == false) {
CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp->conf.custom_notify_json);
if (blobmsg_add_json_from_file(&bbuf, cwmp_main->conf.custom_notify_json) == false) {
CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp_main->conf.custom_notify_json);
blob_buf_free(&bbuf);
creat(NOTIFY_FILE , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
return;
@ -416,12 +414,14 @@ void load_custom_notify_json(struct cwmp *cwmp)
const struct blobmsg_policy p_notif[1] = { { "custom_notification", BLOBMSG_TYPE_ARRAY } };
struct blob_attr *tb_notif[1] = { NULL};
blobmsg_parse(p_notif, 1, tb_notif, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head));
if (tb_notif[0] == NULL) {
CWMP_LOG(WARNING, "The JSON file %s doesn't contain a notify parameters list", cwmp->conf.custom_notify_json);
CWMP_LOG(WARNING, "The JSON file %s doesn't contain a notify parameters list", cwmp_main->conf.custom_notify_json);
blob_buf_free(&bbuf);
creat(NOTIFY_FILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
return;
}
custom_notify_list = tb_notif[0];
const struct blobmsg_policy p[2] = { { "parameter", BLOBMSG_TYPE_STRING }, { "notify_type", BLOBMSG_TYPE_STRING } };
@ -449,7 +449,7 @@ void load_custom_notify_json(struct cwmp *cwmp)
}
blob_buf_free(&bbuf);
creat(NOTIFY_FILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
cwmp->custom_notify_active = true;
cwmp_main->custom_notify_active = true;
}
/*
@ -457,7 +457,7 @@ void load_custom_notify_json(struct cwmp *cwmp)
*/
void get_parameter_value_from_parameters_list(struct list_head *params_list, char *parameter_name, char **value, char **type)
{
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
list_for_each_entry (param_value, params_list, list) {
if (param_value->name == NULL)
continue;
@ -540,61 +540,52 @@ int check_value_change(void)
return int_ret;
}
void sotfware_version_value_change(struct cwmp *cwmp, struct transfer_complete *p)
void cwmp_prepare_value_change()
{
struct event_container *event_container;
if (list_value_change.next == &(list_value_change))
return;
event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, "");
if (!event_container)
return;
pthread_mutex_lock(&(mutex_value_change));
list_splice_init(&(list_value_change), &(event_container->head_dm_parameter));
pthread_mutex_unlock(&(mutex_value_change));
cwmp_save_event_container(event_container);
}
void sotfware_version_value_change(struct transfer_complete *p)
{
char *current_software_version = NULL;
if (!p->old_software_version || p->old_software_version[0] == 0)
return;
current_software_version = cwmp->deviceid.softwareversion;
current_software_version = cwmp_main->deviceid.softwareversion;
if (p->old_software_version && current_software_version && strcmp(p->old_software_version, current_software_version) != 0) {
pthread_mutex_lock(&(cwmp->mutex_session_queue));
cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, "");
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, "");
}
}
void *thread_periodic_check_notify(void *v)
void periodic_check_notifiy(struct uloop_timeout *timeout __attribute__((unused)))
{
struct cwmp *cwmp = (struct cwmp *)v;
int periodic_interval;
bool periodic_enable;
struct timespec periodic_timeout = { 0, 0 };
time_t current_time;
int is_notify;
int is_notify = 0;
if (cwmp_stop)
return;
is_notify = check_value_change();
if (is_notify > 0)
cwmp_update_enabled_notify_file();
if (is_notify & NOTIF_ACTIVE)
send_active_value_change();
if (is_notify & NOTIF_LW_ACTIVE)
cwmp_lwnotification();
periodic_interval = cwmp->conf.periodic_notify_interval;
periodic_enable = cwmp->conf.periodic_notify_enable;
uloop_timeout_set(&check_notify_timer, cwmp_main->conf.periodic_notify_interval * 1000);
}
for (;;) {
if (periodic_enable) {
pthread_mutex_lock(&(cwmp->mutex_notify_periodic));
current_time = time(NULL);
periodic_timeout.tv_sec = current_time + periodic_interval;
if (thread_end)
break;
pthread_cond_timedwait(&(cwmp->threshold_notify_periodic), &(cwmp->mutex_notify_periodic), &periodic_timeout);
if (thread_end)
break;
pthread_mutex_lock(&(cwmp->mutex_session_send));
is_notify = check_value_change();
if (is_notify > 0)
cwmp_update_enabled_notify_file();
pthread_mutex_unlock(&(cwmp->mutex_session_send));
if (is_notify & NOTIF_ACTIVE)
send_active_value_change();
if (is_notify & NOTIF_LW_ACTIVE)
cwmp_lwnotification();
pthread_mutex_unlock(&(cwmp->mutex_notify_periodic));
} else
break;
}
return NULL;
void trigger_periodic_notify_check()
{
uloop_timeout_set(&check_notify_timer, 10);
}
void add_list_value_change(char *param_name, char *param_data, char *param_type)
@ -613,19 +604,14 @@ void clean_list_value_change()
void send_active_value_change(void)
{
struct cwmp *cwmp = &cwmp_main;
struct event_container *event_container;
pthread_mutex_lock(&(cwmp->mutex_session_queue));
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_4VALUE_CHANGE, "");
event_container = cwmp_add_event_container(EVENT_IDX_4VALUE_CHANGE, "");
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return;
}
cwmp_save_event_container(event_container);
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
pthread_cond_signal(&(cwmp->threshold_session_send));
return;
}
@ -636,10 +622,9 @@ void add_lw_list_value_change(char *param_name, char *param_data, char *param_ty
static void udplw_server_param(struct addrinfo **res)
{
struct addrinfo hints = { 0 };
struct cwmp *cwmp = &cwmp_main;
struct config *conf;
struct config *conf = &(cwmp_main->conf);
char port[32];
conf = &(cwmp->conf);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
snprintf(port, sizeof(port), "%d", conf->lw_notification_port);
@ -686,8 +671,6 @@ static void free_all_list_lw_notify()
{
while (list_lw_value_change.next != &list_lw_value_change) {
struct cwmp_dm_parameter *dm_parameter;
if (list_lw_value_change.next == NULL)
continue;
dm_parameter = list_entry(list_lw_value_change.next, struct cwmp_dm_parameter, list);
del_list_lw_notify(dm_parameter);
}
@ -698,9 +681,7 @@ void cwmp_lwnotification()
char msg[1024], *msg_out;
char signature[41];
struct addrinfo *servaddr;
struct cwmp *cwmp = &cwmp_main;
struct config *conf;
conf = &(cwmp->conf);
struct config *conf = &(cwmp_main->conf);
udplw_server_param(&servaddr);
xml_prepare_lwnotification_message(&msg_out);

124
reboot.c
View file

@ -5,116 +5,60 @@
* (at your option) any later version.
*
* Copyright (C) 2021 iopsys Software Solutions AB
* Author Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*
*/
#include <unistd.h>
#include "reboot.h"
#include "session.h"
#include "cwmp_uci.h"
#include "log.h"
#include "session.h"
#include "reboot.h"
static pthread_t delay_reboot_thread;
static pthread_t delay_schedule_thread;
static int g_curr_delay_reboot = -1;
static time_t g_curr_schedule_redoot = 0;
void cwmp_schedule_reboot(struct uloop_timeout *timeout __attribute__((unused)));
void cwmp_delay_reboot(struct uloop_timeout *timeout __attribute__((unused)));
static void *thread_delay_reboot(void *arg)
struct uloop_timeout schedule_reboot_timer = { .cb = cwmp_schedule_reboot };
struct uloop_timeout delay_reboot_timer = { .cb = cwmp_delay_reboot };
void cwmp_schedule_reboot(struct uloop_timeout *timeout __attribute__((unused)))
{
struct cwmp *cwmp = (struct cwmp *)arg;
cwmp_uci_set_value("cwmp", "cpe", "schedule_reboot", "0001-01-01T00:00:00Z");
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
if (time(NULL) > cwmp_main->conf.schedule_reboot)
return;
cwmp_reboot("schedule_reboot");
}
CWMP_LOG(INFO, "The device will reboot after %d seconds", cwmp->conf.delay_reboot);
sleep(cwmp->conf.delay_reboot);
void cwmp_delay_reboot(struct uloop_timeout *timeout __attribute__((unused)))
{
cwmp_uci_set_value("cwmp", "cpe", "delay_reboot", "-1");
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
/* 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) {
if (cwmp_main->session->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)
void launch_reboot_methods()
{
if (thread_exist) {
CWMP_LOG(INFO, "There is already a delay reboot thread!, Cancel the current thread");
static int curr_delay_reboot = -1;
static time_t curr_schedule_redoot = 0;
pthread_cancel(delay_reboot_thread);
create_delay_reboot_thread(cwmp, false);
} else {
CWMP_LOG(INFO, "Create a delay reboot thread");
if (cwmp_main->conf.delay_reboot != curr_delay_reboot && cwmp_main->conf.delay_reboot > 0) {
CWMP_LOG(INFO, "The device will reboot after %ld seconds", cwmp_main->conf.delay_reboot);
curr_delay_reboot = cwmp_main->conf.delay_reboot;
uloop_timeout_cancel(&delay_reboot_timer);
uloop_timeout_set(&delay_reboot_timer, cwmp_main->conf.delay_reboot * 1000);
}
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);
cwmp_uci_set_value("cwmp", "cpe", "schedule_reboot", "0001-01-01T00:00:00Z");
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
/* 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)
{
if (cwmp->conf.delay_reboot != g_curr_delay_reboot && cwmp->conf.delay_reboot > 0) {
create_delay_reboot_thread(cwmp, (g_curr_delay_reboot != -1));
g_curr_delay_reboot = cwmp->conf.delay_reboot;
}
if (cwmp->conf.schedule_reboot != g_curr_schedule_redoot && (cwmp->conf.schedule_reboot - time(NULL)) > 0) {
create_schedule_reboot_thread(cwmp, (g_curr_schedule_redoot != 0));
g_curr_schedule_redoot = cwmp->conf.schedule_reboot;
if (cwmp_main->conf.schedule_reboot != curr_schedule_redoot && (cwmp_main->conf.schedule_reboot - time(NULL)) > 0) {
curr_schedule_redoot = cwmp_main->conf.schedule_reboot;
time_t remaining_time = cwmp_main->conf.schedule_reboot - time(NULL);
CWMP_LOG(INFO, "The device will reboot after %ld seconds", remaining_time);
uloop_timeout_cancel(&schedule_reboot_timer);
uloop_timeout_set(&schedule_reboot_timer, remaining_time * 1000);
}
}

View file

@ -8,10 +8,12 @@
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include "common.h"
#include "sched_inform.h"
#include "log.h"
#include "backupSession.h"
#include "event.h"
#include "log.h"
#include "cwmp_event.h"
LIST_HEAD(list_schedule_inform);
pthread_mutex_t mutex_schedule_inform = PTHREAD_MUTEX_INITIALIZER;
@ -19,9 +21,8 @@ pthread_cond_t threshold_schedule_inform;
int count_schedule_inform_queue = 0;
void *thread_cwmp_rpc_cpe_scheduleInform(void *v)
void *thread_cwmp_rpc_cpe_scheduleInform(void *v __attribute__((unused)))
{
struct cwmp *cwmp = (struct cwmp *)v;
struct event_container *event_container;
struct schedule_inform *schedule_inform;
struct timespec si_timeout = { 0, 0 };
@ -30,7 +31,7 @@ void *thread_cwmp_rpc_cpe_scheduleInform(void *v)
for (;;) {
if (thread_end)
if (cwmp_stop)
break;
if (list_schedule_inform.next != &(list_schedule_inform)) {
@ -49,18 +50,15 @@ void *thread_cwmp_rpc_cpe_scheduleInform(void *v)
pthread_mutex_unlock(&mutex_schedule_inform);
continue;
}
pthread_mutex_lock(&(cwmp->mutex_session_queue));
CWMP_LOG(INFO, "Schedule Inform thread: add ScheduleInform event in the queue");
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_3SCHEDULED, "");
event_container = cwmp_add_event_container(EVENT_IDX_3SCHEDULED, "");
if (event_container != NULL) {
cwmp_save_event_container(event_container);
}
event_container = cwmp_add_event_container(cwmp, EVENT_IDX_M_ScheduleInform, schedule_inform->commandKey);
event_container = cwmp_add_event_container(EVENT_IDX_M_ScheduleInform, schedule_inform->commandKey);
if (event_container != NULL) {
cwmp_save_event_container(event_container);
}
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
pthread_cond_signal(&(cwmp->threshold_session_send));
pthread_mutex_lock(&mutex_schedule_inform);
list_del(&(schedule_inform->list));
if (schedule_inform->commandKey != NULL) {

680
session.c
View file

@ -9,109 +9,62 @@
*
*/
#include <stdlib.h>
#include "session.h"
#include "config.h"
#include "event.h"
#include "rpc_soap.h"
#include "backupSession.h"
#include "config.h"
#include "cwmp_uci.h"
#include "log.h"
#include "http.h"
#include "notifications.h"
#include "diagnostic.h"
#include "soap.h"
#include "ubus.h"
#include "download.h"
#include "upload.h"
#include "cwmp_event.h"
#include "ssl_utils.h"
pthread_mutex_t start_session_mutext = PTHREAD_MUTEX_INITIALIZER;
static void cwmp_priodic_session_timer(struct uloop_timeout *timeout);
struct uloop_timeout session_timer = { .cb = cwmp_schedule_session };
struct uloop_timeout priodic_session_timer = { .cb = cwmp_priodic_session_timer };
struct uloop_timeout retry_session_timer = { .cb = cwmp_schedule_session };
unsigned int end_session_flag = 0;
void cwmp_set_end_session(unsigned int flag)
int create_cwmp_session_structure()
{
end_session_flag |= flag;
}
struct rpc *cwmp_add_session_rpc_cpe(struct session *session, int type)
{
struct rpc *rpc_cpe;
rpc_cpe = calloc(1, sizeof(struct rpc));
if (rpc_cpe == NULL) {
return NULL;
}
rpc_cpe->type = type;
list_add_tail(&(rpc_cpe->list), &(session->head_rpc_cpe));
return rpc_cpe;
}
struct rpc *cwmp_add_session_rpc_acs(struct session *session, int type)
{
struct rpc *rpc_acs;
rpc_acs = calloc(1, sizeof(struct rpc));
if (rpc_acs == NULL) {
return NULL;
}
rpc_acs->type = type;
list_add_tail(&(rpc_acs->list), &(session->head_rpc_acs));
return rpc_acs;
}
int cwmp_apply_acs_changes(void)
{
int error;
if ((error = cwmp_config_reload(&cwmp_main)))
return error;
if ((error = cwmp_root_cause_events(&cwmp_main)))
return error;
cwmp_main->session = calloc(1, sizeof(struct session));
if (cwmp_main->session == NULL)
return CWMP_GEN_ERR;
INIT_LIST_HEAD(&(cwmp_main->session->events));
INIT_LIST_HEAD(&(cwmp_main->session->head_rpc_acs));
INIT_LIST_HEAD(&(cwmp_main->session->head_rpc_cpe));
return CWMP_OK;
}
int cwmp_move_session_to_session_send(struct cwmp *cwmp, struct session *session)
int cwmp_session_init()
{
pthread_mutex_lock(&(cwmp->mutex_session_queue));
if (cwmp->session_send != NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MUTEX_ERR;
}
list_del(&(session->list));
cwmp->session_send = session;
cwmp->head_event_container = NULL;
bkp_session_move_inform_to_inform_send();
bkp_session_save();
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
struct rpc *rpc_acs;
cwmp_main->cwmp_cr_event = 0;
cwmp_uci_init();
rpc_acs = cwmp_add_session_rpc_acs_head(RPC_ACS_INFORM);
if (rpc_acs == NULL)
return CWMP_GEN_ERR;
set_cwmp_session_status(SESSION_RUNNING, 0);
if (file_exists(fc_cookies))
remove(fc_cookies);
return CWMP_OK;
}
struct rpc *cwmp_add_session_rpc_acs_head(struct session *session, int type)
int clean_cwmp_session_structure()
{
struct rpc *rpc_acs;
rpc_acs = calloc(1, sizeof(struct rpc));
if (rpc_acs == NULL) {
return NULL;
}
rpc_acs->type = type;
list_add(&(rpc_acs->list), &(session->head_rpc_acs));
return rpc_acs;
}
struct session *cwmp_add_queue_session(struct cwmp *cwmp)
{
struct session *session = NULL;
struct rpc *rpc_acs;
session = calloc(1, sizeof(struct session));
if (session == NULL)
return NULL;
list_add_tail(&(session->list), &(cwmp->head_session_queue));
INIT_LIST_HEAD(&(session->head_event_container));
INIT_LIST_HEAD(&(session->head_rpc_acs));
INIT_LIST_HEAD(&(session->head_rpc_cpe));
rpc_acs = cwmp_add_session_rpc_acs_head(session, RPC_ACS_INFORM);
if (rpc_acs == NULL) {
FREE(session);
return NULL;
}
return session;
FREE(cwmp_main->session);
return 0;
}
int cwmp_session_rpc_destructor(struct rpc *rpc)
@ -121,101 +74,502 @@ int cwmp_session_rpc_destructor(struct rpc *rpc)
return CWMP_OK;
}
int cwmp_session_destructor(struct session *session)
int cwmp_session_exit()
{
cwmp_uci_exit();
icwmp_cleanmem();
return CWMP_OK;
}
static int cwmp_rpc_cpe_handle_message(struct rpc *rpc_cpe)
{
if (xml_prepare_msg_out())
return -1;
if (rpc_cpe_methods[rpc_cpe->type].handler(rpc_cpe))
return -1;
if (xml_set_cwmp_id_rpc_cpe())
return -1;
return 0;
}
static int cwmp_schedule_rpc()
{
struct list_head *ilist;
struct rpc *rpc_acs, *rpc_cpe;
if (http_client_init() || cwmp_stop) {
CWMP_LOG(INFO, "Initializing http client failed");
goto retry;
}
while (1) {
list_for_each (ilist, &(cwmp_main->session->head_rpc_acs)) {
rpc_acs = list_entry(ilist, struct rpc, list);
if (!rpc_acs->type || cwmp_stop)
goto retry;
CWMP_LOG(INFO, "Preparing the %s RPC message to send to the ACS", rpc_acs_methods[rpc_acs->type].name);
if (rpc_acs_methods[rpc_acs->type].prepare_message(rpc_acs) || cwmp_stop)
goto retry;
if (xml_set_cwmp_id() || cwmp_stop)
goto retry;
CWMP_LOG(INFO, "Send the %s RPC message to the ACS", rpc_acs_methods[rpc_acs->type].name);
if (xml_send_message(rpc_acs) || cwmp_stop)
goto retry;
CWMP_LOG(INFO, "Get the %sResponse message from the ACS", rpc_acs_methods[rpc_acs->type].name);
if (rpc_acs_methods[rpc_acs->type].parse_response || cwmp_stop)
if (rpc_acs_methods[rpc_acs->type].parse_response(rpc_acs))
goto retry;
ilist = ilist->prev;
if (rpc_acs_methods[rpc_acs->type].extra_clean != NULL)
rpc_acs_methods[rpc_acs->type].extra_clean(rpc_acs);
cwmp_session_rpc_destructor(rpc_acs);
MXML_DELETE(cwmp_main->session->tree_in);
MXML_DELETE(cwmp_main->session->tree_out);
if (cwmp_main->session->hold_request || cwmp_stop)
break;
}
// If restart service caused firewall restart, wait for firewall restart to complete
if (g_firewall_restart == true)
check_firewall_restart_state();
CWMP_LOG(INFO, "Send empty message to the ACS");
if (xml_send_message(NULL) || cwmp_stop)
goto retry;
if (!cwmp_main->session->tree_in || cwmp_stop)
goto next;
CWMP_LOG(INFO, "Receive request from the ACS");
if (xml_handle_message() || cwmp_stop)
goto retry;
while (cwmp_main->session->head_rpc_cpe.next != &(cwmp_main->session->head_rpc_cpe)) {
rpc_cpe = list_entry(cwmp_main->session->head_rpc_cpe.next, struct rpc, list);
if (!rpc_cpe->type || cwmp_stop)
goto retry;
CWMP_LOG(INFO, "Preparing the %s%s message", rpc_cpe_methods[rpc_cpe->type].name, (rpc_cpe->type != RPC_CPE_FAULT) ? "Response" : "");
if (cwmp_rpc_cpe_handle_message(rpc_cpe) || cwmp_stop)
goto retry;
MXML_DELETE(cwmp_main->session->tree_in);
CWMP_LOG(INFO, "Send the %s%s message to the ACS", rpc_cpe_methods[rpc_cpe->type].name, (rpc_cpe->type != RPC_CPE_FAULT) ? "Response" : "");
if (xml_send_message(rpc_cpe) || cwmp_stop)
goto retry;
MXML_DELETE(cwmp_main->session->tree_out);
cwmp_session_rpc_destructor(rpc_cpe);
if (!cwmp_main->session->tree_in || cwmp_stop)
break;
CWMP_LOG(INFO, "Receive request from the ACS");
if (xml_handle_message() || cwmp_stop)
goto retry;
}
next:
if (cwmp_main->session->head_rpc_acs.next == &(cwmp_main->session->head_rpc_acs))
break;
MXML_DELETE(cwmp_main->session->tree_in);
MXML_DELETE(cwmp_main->session->tree_out);
}
cwmp_main->session->error = CWMP_OK;
goto end;
retry:
CWMP_LOG(INFO, "Failed");
cwmp_main->session->error = CWMP_RETRY_SESSION;
event_remove_noretry_event_container();
end:
MXML_DELETE(cwmp_main->session->tree_in);
MXML_DELETE(cwmp_main->session->tree_out);
http_client_exit();
xml_exit();
return cwmp_main->session->error;
}
void set_cwmp_session_status(int status, int retry_time)
{
cwmp_main->session->session_status.last_status = status;
if (status == SESSION_SUCCESS) {
cwmp_main->session->session_status.last_end_time = time(NULL);
cwmp_main->session->session_status.next_retry = 0;
cwmp_main->session->session_status.success_session++;
} else if (status == SESSION_RUNNING) {
cwmp_main->session->session_status.last_end_time = 0;
cwmp_main->session->session_status.next_retry = 0;
cwmp_main->session->session_status.last_start_time = time(NULL);
} else {
cwmp_main->session->session_status.last_end_time = time(NULL);
cwmp_main->session->session_status.next_retry = time(NULL) + retry_time;
cwmp_main->session->session_status.failure_session++;
}
}
void rpc_exit()
{
struct rpc *rpc;
while (session->head_rpc_acs.next != &(session->head_rpc_acs)) {
rpc = list_entry(session->head_rpc_acs.next, struct rpc, list);
while (cwmp_main->session->head_rpc_acs.next != &(cwmp_main->session->head_rpc_acs)) {
rpc = list_entry(cwmp_main->session->head_rpc_acs.next, struct rpc, list);
if (!rpc)
break;
if (rpc_acs_methods[rpc->type].extra_clean != NULL)
rpc_acs_methods[rpc->type].extra_clean(session, rpc);
rpc_acs_methods[rpc->type].extra_clean(rpc);
cwmp_session_rpc_destructor(rpc);
}
while (session->head_rpc_cpe.next != &(session->head_rpc_cpe)) {
rpc = list_entry(session->head_rpc_cpe.next, struct rpc, list);
while (cwmp_main->session->head_rpc_cpe.next != &(cwmp_main->session->head_rpc_cpe)) {
rpc = list_entry(cwmp_main->session->head_rpc_cpe.next, struct rpc, list);
if (!rpc)
break;
cwmp_session_rpc_destructor(rpc);
}
if (session->list.next != NULL && session->list.prev != NULL)
list_del(&(session->list));
free(session);
return CWMP_OK;
}
int cwmp_move_session_to_session_queue(struct cwmp *cwmp, struct session *session)
void start_cwmp_session()
{
struct list_head *ilist, *jlist;
struct rpc *rpc_acs, *queue_rpc_acs;
struct session *session_queue;
int t, error;
char *exec_download = NULL;
int is_notify = 0;
pthread_mutex_lock(&(cwmp->mutex_session_queue));
cwmp->retry_count_session++;
cwmp->session_send = NULL;
if (cwmp->head_session_queue.next == &(cwmp->head_session_queue)) {
list_add_tail(&(session->list), &(cwmp->head_session_queue));
session->hold_request = 0;
session->digest_auth = 0;
cwmp->head_event_container = &(session->head_event_container);
if (session->head_rpc_acs.next != &(session->head_rpc_acs)) {
rpc_acs = list_entry(session->head_rpc_acs.next, struct rpc, list);
if (rpc_acs->type != RPC_ACS_INFORM) {
if (cwmp_add_session_rpc_acs_head(session, RPC_ACS_INFORM) == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
}
} else {
if (cwmp_add_session_rpc_acs_head(session, RPC_ACS_INFORM) == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
}
while (session->head_rpc_cpe.next != &(session->head_rpc_cpe)) {
struct rpc *rpc_cpe;
rpc_cpe = list_entry(session->head_rpc_cpe.next, struct rpc, list);
cwmp_session_rpc_destructor(rpc_cpe);
}
bkp_session_move_inform_to_inform_queue();
bkp_session_save();
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_OK;
uloop_timeout_cancel(&check_notify_timer);
if (cwmp_session_init() != CWMP_OK) {
CWMP_LOG(ERROR, "Not able to init a CWMP session");
t = cwmp_get_session_retry_interval();
CWMP_LOG(INFO, "Retry session, retry count = %d, retry in %ds", cwmp_main->retry_count_session, t);
set_cwmp_session_status(SESSION_FAILURE, t);
trigger_periodic_notify_check();
return;
}
list_for_each (ilist, &(session->head_event_container)) {
struct event_container *event_container_new, *event_container_old;
event_container_old = list_entry(ilist, struct event_container, list);
event_container_new = cwmp_add_event_container(cwmp, event_container_old->code, event_container_old->command_key);
if (event_container_new == NULL) {
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
return CWMP_MEM_ERR;
}
list_splice_init(&(event_container_old->head_dm_parameter), &(event_container_new->head_dm_parameter));
cwmp_save_event_container(event_container_new);
if (cwmp_main->session->session_status.last_status == SESSION_FAILURE)
reload_networking_config();
/*
* Value changes
*/
if (file_exists(DM_ENABLED_NOTIFY)) {
if (!event_exist_in_list(EVENT_IDX_4VALUE_CHANGE))
is_notify = check_value_change();
}
session_queue = list_entry(cwmp->head_event_container, struct session, head_event_container);
list_for_each (ilist, &(session->head_rpc_acs)) {
rpc_acs = list_entry(ilist, struct rpc, list);
bool dup;
dup = false;
list_for_each (jlist, &(session_queue->head_rpc_acs)) {
queue_rpc_acs = list_entry(jlist, struct rpc, list);
if (queue_rpc_acs->type == rpc_acs->type && (rpc_acs->type == RPC_ACS_INFORM || rpc_acs->type == RPC_ACS_GET_RPC_METHODS)) {
dup = true;
break;
if (is_notify > 0 || !file_exists(DM_ENABLED_NOTIFY) || cwmp_main->custom_notify_active) {
cwmp_main->custom_notify_active = false;
cwmp_update_enabled_notify_file();
}
cwmp_prepare_value_change(cwmp_main);
clean_list_value_change();
/*
* Start session
*/
CWMP_LOG(INFO, "Start session");
uci_get_value(UCI_CPE_EXEC_DOWNLOAD, &exec_download);
if (exec_download && strcmp(exec_download, "1") == 0) {
CWMP_LOG(INFO, "Firmware downloaded and applied successfully");
cwmp_uci_set_value("cwmp", "cpe", "exec_download", "0");
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
}
FREE(exec_download);
error = cwmp_schedule_rpc();
if (error != CWMP_OK)
CWMP_LOG(ERROR, "CWMP session error: %d", error);
/*
* End session
*/
CWMP_LOG(INFO, "End session");
if (cwmp_stop) {
event_remove_all_event_container(RPC_SEND);
event_remove_all_event_container(RPC_QUEUE);
run_session_end_func();
cwmp_session_exit();
rpc_exit();
return;
}
if (cwmp_main->session->error == CWMP_RETRY_SESSION && (!list_empty(&(cwmp_main->session->events)) || (list_empty(&(cwmp_main->session->events)) && cwmp_main->cwmp_cr_event == 0))) { //CWMP Retry session
reload_networking_config();
cwmp_main->retry_count_session++;
t = cwmp_get_session_retry_interval();
CWMP_LOG(INFO, "Retry session, retry count = %d, retry in %ds", cwmp_main->retry_count_session, t);
set_cwmp_session_status(SESSION_FAILURE, t);
uloop_timeout_set(&retry_session_timer, 1000 * t);
} else {
event_remove_all_event_container(RPC_SEND);
//event_remove_all_event_container(RPC_QUEUE);
cwmp_main->retry_count_session = 0;
set_cwmp_session_status(SESSION_SUCCESS, 0);
rpc_exit();
}
run_session_end_func();
cwmp_session_exit();
CWMP_LOG(INFO, "Waiting the next session");
trigger_periodic_notify_check();
}
void trigger_cwmp_session_timer()
{
uloop_timeout_cancel(&retry_session_timer);
uloop_timeout_set(&session_timer, 10);
}
void cwmp_schedule_session(struct uloop_timeout *timeout __attribute__((unused)))
{
pthread_mutex_lock(&start_session_mutext);
start_cwmp_session();
pthread_mutex_unlock(&start_session_mutext);
if (cwmp_main->start_diagnostics) {
cwmp_main->start_diagnostics = false;
trigger_cwmp_session_timer();
}
}
static void cwmp_priodic_session_timer(struct uloop_timeout *timeout __attribute__((unused)))
{
if (cwmp_main->conf.periodic_enable && cwmp_main->conf.period > 0) {
cwmp_main->session->session_status.next_periodic = time(NULL) + cwmp_main->conf.period;
uloop_timeout_set(&priodic_session_timer, cwmp_main->conf.period * 1000);
}
if (cwmp_main->conf.periodic_enable) {
cwmp_add_event_container(EVENT_IDX_2PERIODIC, "");
trigger_cwmp_session_timer();
}
}
long int cwmp_periodic_session_time(void)
{
long int delta_time;
long int periodic_time;
delta_time = time(NULL) - cwmp_main->conf.time;
if(delta_time > 0)
periodic_time = cwmp_main->conf.period - (delta_time % cwmp_main->conf.period);
else
periodic_time = (-delta_time) % cwmp_main->conf.period;
cwmp_main->session->session_status.next_periodic = time(NULL) + periodic_time;
return periodic_time;
}
void initiate_cwmp_periodic_session_feature()
{
uloop_timeout_cancel(&priodic_session_timer);
if (cwmp_main->conf.periodic_enable && cwmp_main->conf.period > 0) {
if (cwmp_main->conf.time >= 0){
CWMP_LOG(INFO, "Init periodic inform: periodic_inform time = %ld, interval = %d\n", cwmp_main->conf.time, cwmp_main->conf.period);
uloop_timeout_set(&priodic_session_timer, cwmp_periodic_session_time() * 1000);
}
else {
CWMP_LOG(INFO, "Init periodic inform: interval = %d\n", cwmp_main->conf.period);
cwmp_main->session->session_status.next_periodic = time(NULL) + cwmp_main->conf.period;
uloop_timeout_set(&priodic_session_timer, cwmp_main->conf.period * 1000);
}
}
}
struct rpc *cwmp_add_session_rpc_cpe(int type)
{
struct rpc *rpc_cpe;
rpc_cpe = calloc(1, sizeof(struct rpc));
if (rpc_cpe == NULL) {
return NULL;
}
rpc_cpe->type = type;
list_add_tail(&(rpc_cpe->list), &(cwmp_main->session->head_rpc_cpe));
return rpc_cpe;
}
struct rpc *cwmp_add_session_rpc_acs(int type)
{
struct rpc *rpc_acs;
rpc_acs = calloc(1, sizeof(struct rpc));
if (rpc_acs == NULL) {
return NULL;
}
rpc_acs->type = type;
list_add_tail(&(rpc_acs->list), &(cwmp_main->session->head_rpc_acs));
return rpc_acs;
}
int cwmp_get_session_retry_interval()
{
unsigned int retry_count = 0;
double min = 0;
double max = 0;
int m = cwmp_main->conf.retry_min_wait_interval;
int k = cwmp_main->conf.retry_interval_multiplier;
int exp = cwmp_main->retry_count_session;
if (exp == 0)
return MAX_INT32;
if (exp > 10)
exp = 10;
min = pow(((double)k / 1000), (double)(exp - 1)) * m;
max = pow(((double)k / 1000), (double)exp) * m;
char *rand = generate_random_string(4);
if (rand) {
unsigned int dividend = (unsigned int)strtoul(rand, NULL, 16);
retry_count = dividend % ((unsigned int)max + 1 - (unsigned int)min) + (unsigned int)min;
free(rand);
}
return (retry_count);
}
struct rpc *cwmp_add_session_rpc_acs_head(int type)
{
struct rpc *rpc_acs;
rpc_acs = calloc(1, sizeof(struct rpc));
if (rpc_acs == NULL) {
return NULL;
}
rpc_acs->type = type;
list_add(&(rpc_acs->list), &(cwmp_main->session->head_rpc_acs));
return rpc_acs;
}
void cwmp_set_end_session(unsigned int flag)
{
end_session_flag |= flag;
}
int run_session_end_func(void)
{
if (end_session_flag & END_SESSION_RESTART_SERVICES) {
CWMP_LOG(INFO, "Restart modified services");
icwmp_restart_services();
}
if (end_session_flag & END_SESSION_RELOAD) {
CWMP_LOG(INFO, "Config reload: end session request");
cwmp_uci_reinit();
cwmp_apply_acs_changes();
initiate_cwmp_periodic_session_feature();
}
if (end_session_flag & END_SESSION_INIT_NOTIFY) {
CWMP_LOG(INFO, "SetParameterAttributes end session: reinit list notify");
reinit_list_param_notify();
}
if (end_session_flag & END_SESSION_SET_NOTIFICATION_UPDATE) {
CWMP_LOG(INFO, "SetParameterAttributes/Values end session: update enabled notify file");
cwmp_update_enabled_notify_file();
}
if (end_session_flag & END_SESSION_NSLOOKUP_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing nslookupdiagnostic: end session request");
cwmp_nslookup_diagnostics();
}
if (end_session_flag & END_SESSION_TRACEROUTE_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing traceroutediagnostic: end session request");
cwmp_traceroute_diagnostics();
}
if (end_session_flag & END_SESSION_UDPECHO_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing udpechodiagnostic: end session request");
cwmp_udp_echo_diagnostics();
}
if (end_session_flag & END_SESSION_SERVERSELECTION_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing serverselectiondiagnostic: end session request");
cwmp_serverselection_diagnostics();
}
if (end_session_flag & END_SESSION_IPPING_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing ippingdiagnostic: end session request");
cwmp_ip_ping_diagnostics();
}
if (end_session_flag & END_SESSION_DOWNLOAD_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing download diagnostic: end session request");
cwmp_download_diagnostics();
}
if (end_session_flag & END_SESSION_UPLOAD_DIAGNOSTIC) {
CWMP_LOG(INFO, "Executing upload diagnostic: end session request");
cwmp_upload_diagnostics();
}
if (end_session_flag & END_SESSION_REBOOT) {
CWMP_LOG(INFO, "Executing Reboot: end session request");
cwmp_reboot(commandKey);
exit(EXIT_SUCCESS);
}
if (end_session_flag & END_SESSION_FACTORY_RESET) {
CWMP_LOG(INFO, "Executing factory reset: end session request");
cwmp_factory_reset();
exit(EXIT_SUCCESS);
}
if (end_session_flag & END_SESSION_X_FACTORY_RESET_SOFT) {
CWMP_LOG(INFO, "Executing factory reset soft: end session request");
cwmp_factory_reset();
exit(EXIT_SUCCESS);
}
if (end_session_flag & END_SESSION_DOWNLOAD) {
CWMP_LOG(INFO, "Trigger Uloop Downaload Calls");
struct list_head *ilist;
list_for_each (ilist, &(list_download)) {
struct download *download = list_entry(ilist, struct download, list);
int download_delay = 0;
if (download->scheduled_time > time(NULL)) {
download_delay = download->scheduled_time - time(NULL);
}
uloop_timeout_set(&download->handler_timer, 1000 * download_delay);
}
if (dup) {
continue;
}
ilist = ilist->prev;
list_del(&(rpc_acs->list));
list_add_tail(&(rpc_acs->list), &(session_queue->head_rpc_acs));
}
cwmp_session_destructor(session);
pthread_mutex_unlock(&(cwmp->mutex_session_queue));
if (end_session_flag & END_SESSION_SCHEDULE_DOWNLOAD) {
CWMP_LOG(INFO, "Trigger Uloop ScheduleDownaload Calls");
struct list_head *ilist;
list_for_each (ilist, &(list_schedule_download)) {
struct download *sched_download = list_entry(ilist, struct download, list);
time_t now = time(NULL);
int download_delay;
if (sched_download->timewindowstruct[0].windowstart > now)
download_delay = sched_download->timewindowstruct[0].windowstart - now;
else if (sched_download->timewindowstruct[0].windowend >= now)
download_delay = 1;
else if (now < sched_download->timewindowstruct[1].windowstart)
download_delay = sched_download->timewindowstruct[1].windowstart - now;
else if (sched_download->timewindowstruct[1].windowend >= now)
download_delay = 1;
else
download_delay = 1;
uloop_timeout_set(&sched_download->handler_timer, 1000 * download_delay);
}
}
if (end_session_flag & END_SESSION_UPLOAD) {
CWMP_LOG(INFO, "Trigger Uloop Upload Calls");
struct list_head *ilist;
list_for_each (ilist, &(list_upload)) {
struct download *upload = list_entry(ilist, struct download, list);
int upload_delay = 0;
if (upload->scheduled_time > time(NULL)) {
upload_delay = upload->scheduled_time - time(NULL);
}
uloop_timeout_set(&upload->handler_timer, 1000 * upload_delay);
}
}
end_session_flag = 0;
return CWMP_OK;
}

File diff suppressed because it is too large Load diff

View file

@ -21,7 +21,6 @@
#include <openssl/ssl.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <string.h>
#include "common.h"
#include "log.h"
@ -39,7 +38,7 @@ char *generate_random_string(size_t size)
int written = RAND_bytes(buf, size);
if (written != 1) {
CWMP_LOG(ERROR,"Failed to get random bytes");
printf("Failed to get random bytes");
goto end;
}
@ -59,9 +58,8 @@ void message_compute_signature(char *msg_out, char *signature, size_t len)
int i;
int result_len = 20;
unsigned char *result;
struct cwmp *cwmp = &cwmp_main;
struct config *conf;
conf = &(cwmp->conf);
conf = &(cwmp_main->conf);
/* unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
const unsigned char *d, size_t n, unsigned char *md,
unsigned int *md_len);*/
@ -74,4 +72,3 @@ void message_compute_signature(char *msg_out, char *signature, size_t len)
}
FREE(result);
}

147
subprocess.c Normal file
View file

@ -0,0 +1,147 @@
/*
* 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) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*
*/
#include <libubox/blobmsg_json.h>
#include <stdbool.h>
#include "common.h"
#include "subprocess.h"
#include "log.h"
#define END_TASK "{\"task\":\"end\"}"
#define EXIT_TASK "{\"task\":\"exit\"}"
static int pipefd1[2], pipefd2[2];
bool check_task_name(char *task, char *name)
{
struct blob_buf bbuf;
if (strcmp(task, "{}") == 0)
return false;
memset(&bbuf, 0, sizeof(struct blob_buf));
blob_buf_init(&bbuf, 0);
if (blobmsg_add_json_from_string(&bbuf, task) == false) {
blob_buf_free(&bbuf);
return false;
}
const struct blobmsg_policy p[1] = { { "task", BLOBMSG_TYPE_STRING } };
struct blob_attr *tb[1] = { NULL };
blobmsg_parse(p, 1, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head));
if (tb[0] == NULL)
return false;
char *task_name = blobmsg_get_string(tb[0]);
if (strcmp(task_name, name) == 0) {
blob_buf_free(&bbuf);
return true;
}
blob_buf_free(&bbuf);
return false;
}
bool check_task_is_end(char *task)
{
return check_task_name(task, "end");
}
bool check_task_is_exit(char *task)
{
return check_task_name(task, "exit");
}
int subprocess_start(task_function task_fun)
{
if(task_fun == NULL)
return CWMP_GEN_ERR;
pid_t p;
if (pipe(pipefd1) == -1) {
CWMP_LOG(ERROR, "pipefd1 failed\n");
return CWMP_GEN_ERR;
}
if (pipe(pipefd2) == -1) {
CWMP_LOG(ERROR, "pipefd2 failed\n");
return CWMP_GEN_ERR;
}
p = fork();
if (p == 0) {
while(1) {
char from_parent[512];
read(pipefd1[0], from_parent, 512); //The received string should has the form {"task":"TaskName", "arg1_name":"xxx", "arg2_name":"xxxx"}
if (strlen(from_parent) == 0)
continue;
//get the task name
//if the task name is end
if (check_task_is_end(from_parent)){
write(pipefd2[1], EXIT_TASK, strlen(EXIT_TASK)+1);
exit(EXIT_SUCCESS);
}
char *to_child = task_fun(from_parent);
struct blob_buf bbuf;
memset(&bbuf, 0, sizeof(struct blob_buf));
blob_buf_init(&bbuf, 0);
blobmsg_add_string(&bbuf, "ret", to_child);
char *to_child_json = blobmsg_format_json(bbuf.head, true);
write(pipefd2[1], to_child_json, strlen(to_child_json)+1);
blob_buf_free(&bbuf);
}
}
return CWMP_OK;
}
char *execute_task_in_subprocess(char *task)
{
char *ret = NULL;
write(pipefd1[1], task, strlen(task) + 1);
while(1) {
char from_child[512];
read(pipefd2[0], from_child, 512);
if(strlen(from_child) == 0)
continue;
//The received string from the child should has the format {"task":"exit"} or {"ret":"exit"}
if (check_task_is_exit(from_child)){
close(pipefd2[1]);
close(pipefd2[0]);
break;
}
struct blob_buf bbuf;
memset(&bbuf, 0, sizeof(struct blob_buf));
blob_buf_init(&bbuf, 0);
if (blobmsg_add_json_from_string(&bbuf, from_child) == false) {
blob_buf_free(&bbuf);
continue;
}
const struct blobmsg_policy p[1] = { { "ret", BLOBMSG_TYPE_STRING } };
struct blob_attr *tb[1] = { NULL };
blobmsg_parse(p, 1, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head));
if (tb[0] == NULL) {
blob_buf_free(&bbuf);
continue;
}
ret = blobmsg_get_string(tb[0]);
write(pipefd1[1], END_TASK, strlen(END_TASK) +1);
}
close(pipefd1[0]);
close(pipefd1[1]);
return ret;
}

View file

@ -1 +0,0 @@
icwmp_unit_testd

View file

@ -23,22 +23,30 @@
static struct cwmp cwmp_main_test = { 0 };
static int bkp_session_unit_tests_init(void **state)
{
cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp));
create_cwmp_session_structure();
return 0;
}
static int bkp_session_unit_tests_clean(void **state)
{
icwmp_cleanmem();
clean_cwmp_session_structure();
FREE(cwmp_main);
return 0;
}
static void cwmp_backup_session_unit_test(void **state)
{
remove(CWMP_BKP_FILE);
struct cwmp *cwmp_test = &cwmp_main_test;
mxml_node_t *backup_tree = NULL, *n = NULL;
/*
* Init backup session
*/
int error = cwmp_init_backup_session(cwmp_test, NULL, ALL);
int error = cwmp_init_backup_session(NULL, ALL);
assert_int_equal(error, 0);
bkp_session_save();
FILE *pFile;
@ -270,5 +278,5 @@ int icwmp_backup_session_test(void)
cmocka_unit_test(cwmp_backup_session_unit_test),
};
return cmocka_run_group_tests(tests, NULL, bkp_session_unit_tests_clean);
return cmocka_run_group_tests(tests, bkp_session_unit_tests_init, bkp_session_unit_tests_clean);
}

View file

@ -51,17 +51,20 @@ static void restore_output()
static int cwmp_cli_unit_tests_init(void **state)
{
cwmp_uci_init();
cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp));
create_cwmp_session_structure();
memcpy(&(cwmp_main->env), &cwmp_main, sizeof(struct env));
cwmp_session_init();
return 0;
}
static int cwmp_cli_unit_tests_clean(void **state)
{
icwmp_cleanmem();
FREE(add_instance);
icwmp_free_list_services();
cwmp_uci_exit();
cwmp_session_exit();
FREE(cwmp_main->session);
FREE(cwmp_main);
FREE(add_instance);
return 0;
}

View file

@ -18,9 +18,44 @@
#include "common.h"
#include "config.h"
#include "rpc_soap.h"
#include "soap.h"
static struct cwmp cwmp_main_test = { 0 };
static int custom_inform_unit_tests_init(void **state)
{
cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp));
get_global_config();
return 0;
}
static void clean_config()
{
FREE(cwmp_main->deviceid.manufacturer);
FREE(cwmp_main->deviceid.serialnumber);
FREE(cwmp_main->deviceid.productclass);
FREE(cwmp_main->deviceid.oui);
FREE(cwmp_main->deviceid.softwareversion);
FREE(cwmp_main->conf.lw_notification_hostname);
FREE(cwmp_main->conf.ip);
FREE(cwmp_main->conf.ipv6);
FREE(cwmp_main->conf.acsurl);
FREE(cwmp_main->conf.acs_userid);
FREE(cwmp_main->conf.acs_passwd);
FREE(cwmp_main->conf.interface);
FREE(cwmp_main->conf.cpe_userid);
FREE(cwmp_main->conf.cpe_passwd);
FREE(cwmp_main->conf.ubus_socket);
FREE(cwmp_main->conf.connection_request_path);
FREE(cwmp_main->conf.default_wan_iface);
FREE(cwmp_main->conf.interface);
}
static int custom_inform_unit_tests_clean(void **state)
{
clean_config();
icwmp_cleanmem();
FREE(cwmp_main);
return 0;
}
static int verify_inform_parameter_in_list(char *parameter)
{
@ -32,60 +67,32 @@ static int verify_inform_parameter_in_list(char *parameter)
return 0;
}
static void clean_config(struct cwmp *cwmp_test)
{
FREE(cwmp_test->deviceid.manufacturer);
FREE(cwmp_test->deviceid.serialnumber);
FREE(cwmp_test->deviceid.productclass);
FREE(cwmp_test->deviceid.oui);
FREE(cwmp_test->deviceid.softwareversion);
FREE(cwmp_test->conf.lw_notification_hostname);
FREE(cwmp_test->conf.ip);
FREE(cwmp_test->conf.ipv6);
FREE(cwmp_test->conf.acsurl);
FREE(cwmp_test->conf.acs_userid);
FREE(cwmp_test->conf.acs_passwd);
FREE(cwmp_test->conf.interface);
FREE(cwmp_test->conf.cpe_userid);
FREE(cwmp_test->conf.cpe_passwd);
FREE(cwmp_test->conf.ubus_socket);
FREE(cwmp_test->conf.connection_request_path);
FREE(cwmp_test->conf.default_wan_iface);
FREE(cwmp_test->conf.interface);
}
static void cwmp_custom_inform_unit_test(void **state)
{
struct cwmp *cwmp_test = &cwmp_main_test;
get_global_config(&(cwmp_test->conf));
cwmp_test->conf.forced_inform_json_file = strdup("/etc/icwmpd/forced_inform_valid.json");
load_forced_inform_json_file(cwmp_test);
cwmp_main->conf.forced_inform_json_file = strdup("/etc/icwmpd/forced_inform_valid.json");
load_forced_inform_json_file();
assert_int_equal(nbre_custom_inform, 2);
assert_int_equal(verify_inform_parameter_in_list("Device.DeviceInfo.X_IOPSYS_EU_BaseMACAddress"), 1);
assert_int_equal(verify_inform_parameter_in_list("Device.DeviceInfo.UpTime"), 1);
FREE(cwmp_test->conf.forced_inform_json_file);
FREE(cwmp_main->conf.forced_inform_json_file);
clean_custom_inform_parameters();
cwmp_test->conf.forced_inform_json_file = strdup("/etc/icwmpd/forced_inform_invalid_json.json");
load_forced_inform_json_file(cwmp_test);
cwmp_main->conf.forced_inform_json_file = strdup("/etc/icwmpd/forced_inform_invalid_json.json");
load_forced_inform_json_file();
assert_int_equal(nbre_custom_inform, 0);
assert_int_equal(verify_inform_parameter_in_list("Device.DeviceInfo.X_IOPSYS_EU_BaseMACAddress"), 0);
assert_int_equal(verify_inform_parameter_in_list("Device.DeviceInfo.UpTime"), 0);
FREE(cwmp_test->conf.forced_inform_json_file);
FREE(cwmp_main->conf.forced_inform_json_file);
clean_custom_inform_parameters();
cwmp_test->conf.forced_inform_json_file = strdup("/etc/icwmpd/forced_inform_invalid_parameter.json");
load_forced_inform_json_file(cwmp_test);
cwmp_main->conf.forced_inform_json_file = strdup("/etc/icwmpd/forced_inform_invalid_parameter.json");
load_forced_inform_json_file();
assert_int_equal(nbre_custom_inform, 1);
assert_int_equal(verify_inform_parameter_in_list("Devie.DeviceInfo.X_IOPSYS_EU_BaseMACAddress"), 0);
assert_int_equal(verify_inform_parameter_in_list("Device."), 0);
assert_int_equal(verify_inform_parameter_in_list("Device.DeviceInfo.UpTime"), 1);
FREE(cwmp_test->conf.forced_inform_json_file);
FREE(cwmp_main->conf.forced_inform_json_file);
clean_custom_inform_parameters();
clean_config(cwmp_test);
icwmp_cleanmem();
}
int icwmp_custom_inform_test(void)
@ -94,5 +101,5 @@ int icwmp_custom_inform_test(void)
cmocka_unit_test(cwmp_custom_inform_unit_test),
};
return cmocka_run_group_tests(tests, NULL, NULL);
return cmocka_run_group_tests(tests, custom_inform_unit_tests_init, custom_inform_unit_tests_clean);
}

74
test/cmocka/icwmp_datamodel_interface_unit_test.c Normal file → Executable file
View file

@ -19,13 +19,50 @@
#include "datamodel_interface.h"
#include "event.h"
#include "xml.h"
#include "rpc_soap.h"
#include "soap.h"
#include "session.h"
#include "log.h"
static LIST_HEAD(list_set_param_value);
static LIST_HEAD(faults_list);
static LIST_HEAD(parameters_list);
static int dm_iface_unit_tests_init(void **state)
{
cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp));
create_cwmp_session_structure();
global_conf_init();
return 0;
}
static int dm_iface_unit_tests_clean(void **state)
{
icwmp_free_list_services();
icwmp_cleanmem();
clean_cwmp_session_structure();
FREE(cwmp_main->deviceid.manufacturer);
FREE(cwmp_main->deviceid.serialnumber);
FREE(cwmp_main->deviceid.productclass);
FREE(cwmp_main->deviceid.oui);
FREE(cwmp_main->deviceid.softwareversion);
FREE(cwmp_main->conf.lw_notification_hostname);
FREE(cwmp_main->conf.ip);
FREE(cwmp_main->conf.ipv6);
FREE(cwmp_main->conf.acsurl);
FREE(cwmp_main->conf.acs_userid);
FREE(cwmp_main->conf.acs_passwd);
FREE(cwmp_main->conf.interface);
FREE(cwmp_main->conf.cpe_userid);
FREE(cwmp_main->conf.cpe_passwd);
FREE(cwmp_main->conf.ubus_socket);
FREE(cwmp_main->conf.connection_request_path);
FREE(cwmp_main->conf.default_wan_iface);
FREE(cwmp_main->conf.forced_inform_json_file);
FREE(cwmp_main->conf.custom_notify_json);
FREE(cwmp_main->conf.boot_inform_json_file);
FREE(cwmp_main);
cwmp_free_all_list_param_fault(&faults_list);
cwmp_free_all_dm_parameter_list(&list_set_param_value);
return 0;
}
@ -35,7 +72,7 @@ static int dm_iface_unit_tests_clean(void **state)
static void dm_get_parameter_values_test(void **state)
{
char *fault = NULL;
LIST_HEAD(parameters_list);
/*
* Test of valid parameter path
*/
@ -89,15 +126,13 @@ static void dm_set_multiple_parameter_values_test(void **state)
int fault_code = 0;
char *fault_name = NULL;
struct cwmp_param_fault *param_fault = NULL;
LIST_HEAD(list_set_param_value);
LIST_HEAD(faults_array);
/*
* Test of one valid parameter
*/
add_dm_parameter_to_list(&list_set_param_value, "Device.WiFi.SSID.1.Alias", "wifi_alias_1", NULL, 0, false);
cwmp_transaction_start("cwmp");
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssid_alias", &flag, &faults_array);
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssid_alias", &flag, &faults_list);
assert_int_equal(fault, 0);
assert_in_set(flag, flag_values, 15);
cwmp_transaction_commit();
@ -106,7 +141,7 @@ static void dm_set_multiple_parameter_values_test(void **state)
add_dm_parameter_to_list(&list_set_param_value, "Device.ManagementServer.Username", "iopsys_user", NULL, 0, false); //for other flag value
cwmp_transaction_start("cwmp");
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "mngt_server_user", &flag, &faults_array);
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "mngt_server_user", &flag, &faults_list);
assert_int_equal(fault, 0);
assert_in_set(flag, flag_values, 15);
cwmp_transaction_commit();
@ -119,9 +154,9 @@ static void dm_set_multiple_parameter_values_test(void **state)
*/
add_dm_parameter_to_list(&list_set_param_value, "Device.WiFi.SSID.1.Alis", "wifi_alias_1", NULL, 0, false);
cwmp_transaction_start("cwmp");
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssid_alias", &flag, &faults_array);
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssid_alias", &flag, &faults_list);
assert_non_null(fault);
list_for_each_entry (param_fault, &faults_array, list) {
list_for_each_entry (param_fault, &faults_list, list) {
fault_code = param_fault->fault;
fault_name = param_fault->name;
break;
@ -131,7 +166,7 @@ static void dm_set_multiple_parameter_values_test(void **state)
assert_non_null(fault_name);
cwmp_transaction_abort();
cwmp_free_all_dm_parameter_list(&list_set_param_value);
cwmp_free_all_list_param_fault(&faults_array);
cwmp_free_all_list_param_fault(&faults_list);
fault_code = 0;
fault_name = NULL;
param_fault = NULL;
@ -142,9 +177,9 @@ static void dm_set_multiple_parameter_values_test(void **state)
*/
add_dm_parameter_to_list(&list_set_param_value, "Device.ATM.Link.1.Status", "Up", NULL, 0, false);
cwmp_transaction_start("cwmp");
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_atm_link_status", &flag, &faults_array);
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_atm_link_status", &flag, &faults_list);
assert_int_not_equal(fault, 0);
list_for_each_entry (param_fault, &faults_array, list) {
list_for_each_entry (param_fault, &faults_list, list) {
fault_code = param_fault->fault;
fault_name = param_fault->name;
break;
@ -154,7 +189,7 @@ static void dm_set_multiple_parameter_values_test(void **state)
assert_non_null(fault_name);
cwmp_transaction_abort();
cwmp_free_all_dm_parameter_list(&list_set_param_value);
cwmp_free_all_list_param_fault(&faults_array);
cwmp_free_all_list_param_fault(&faults_list);
fault = 0;
fault_code = 0;
fault_name = NULL;
@ -165,9 +200,9 @@ static void dm_set_multiple_parameter_values_test(void **state)
*/
add_dm_parameter_to_list(&list_set_param_value, "Device.WiFi.SSID.1.Enable", "tre", NULL, 0, false);
cwmp_transaction_start("cwmp");
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssid_alias", &flag, &faults_array);
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssid_alias", &flag, &faults_list);
assert_non_null(fault);
list_for_each_entry (param_fault, &faults_array, list) {
list_for_each_entry (param_fault, &faults_list, list) {
fault_code = param_fault->fault;
fault_name = param_fault->name;
break;
@ -177,7 +212,7 @@ static void dm_set_multiple_parameter_values_test(void **state)
assert_non_null(fault_name);
cwmp_transaction_abort();
cwmp_free_all_dm_parameter_list(&list_set_param_value);
cwmp_free_all_list_param_fault(&faults_array);
cwmp_free_all_list_param_fault(&faults_list);
fault_code = 0;
fault_name = NULL;
param_fault = NULL;
@ -190,7 +225,7 @@ static void dm_set_multiple_parameter_values_test(void **state)
add_dm_parameter_to_list(&list_set_param_value, "Device.WiFi.SSID.1.SSID", "wifi_ssid_2", NULL, 0, false);
add_dm_parameter_to_list(&list_set_param_value, "Device.ManagementServer.Username", "iopsys_user_1", NULL, 0, false);
cwmp_transaction_start("cwmp");
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssids_aliases", &flag, &faults_array);
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wifi_ssids_aliases", &flag, &faults_list);
assert_int_equal(fault, 0);
assert_in_set(flag, flag_values, 15);
cwmp_transaction_commit();
@ -204,12 +239,13 @@ static void dm_set_multiple_parameter_values_test(void **state)
add_dm_parameter_to_list(&list_set_param_value, "Device.WiFi.SSID.2.Alis", "wifi_2", NULL, 0, false);
add_dm_parameter_to_list(&list_set_param_value, "Device.ATM.Link.1.Status", "Up", NULL, 0, false);
cwmp_transaction_start("cwmp");
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wrongs", &flag, &faults_array);
fault = cwmp_set_multiple_parameters_values(&list_set_param_value, "set_wrongs", &flag, &faults_list);
assert_int_not_equal(fault, 0);
list_for_each_entry (param_fault, &faults_array, list) {
list_for_each_entry (param_fault, &faults_list, list) {
assert_in_set(param_fault->fault, faults_values, 3);
}
cwmp_transaction_commit();
cwmp_free_all_list_param_fault(&faults_list);
cwmp_free_all_dm_parameter_list(&list_set_param_value);
}
@ -331,5 +367,5 @@ int icwmp_datamodel_interface_test(void)
cmocka_unit_test(dm_get_parameter_names_test),
};
return cmocka_run_group_tests(tests, NULL, dm_iface_unit_tests_clean);
return cmocka_run_group_tests(tests, dm_iface_unit_tests_init, dm_iface_unit_tests_clean);
}

View file

@ -23,9 +23,9 @@
#include "log.h"
#include "download.h"
static struct transfer_complete *transfer_complete_test = NULL;
struct transfer_complete *transfer_complete_test = NULL;
static void free_transfer_complete(struct transfer_complete *p)
void free_transfer_complete(struct transfer_complete *p)
{
FREE(p->command_key);
FREE(p->start_time);

View file

@ -20,25 +20,31 @@
/*
* Common functions
*/
static char *notifications_test[7] = {"disabled" , "passive", "active", "passive_lw", "passive_passive_lw", "active_lw", "passive_active_lw"};
char *notifications_test[7] = {"disabled" , "passive", "active", "passive_lw", "passive_passive_lw", "active_lw", "passive_active_lw"};
LIST_HEAD(parameters_list);
static LIST_HEAD(parameters_list);
static int cwmp_notifications_unit_tests_init(void **state)
{
cwmp_uci_init();
cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp));
create_cwmp_session_structure();
memcpy(&(cwmp_main->env), &cwmp_main, sizeof(struct env));
cwmp_session_init();
return 0;
}
static int cwmp_notifications_unit_tests_clean(void **state)
{
icwmp_cleanmem();
clean_list_param_notify();
clean_list_value_change();
cwmp_free_all_dm_parameter_list(&parameters_list);
cwmp_uci_exit();
cwmp_session_exit();
FREE(cwmp_main->session);
FREE(cwmp_main);
return 0;
}
static int check_notify_file(char *param, int *ret_notification)
int check_notify_file(char *param, int *ret_notification)
{
struct blob_buf bbuf;
char *parameter = NULL;
@ -80,7 +86,7 @@ static int check_notify_file(char *param, int *ret_notification)
return nbre_iterations;
}
static int get_parameter_notification_from_list_head(struct list_head *params_list, char *parameter_name)
int get_parameter_notification_from_list_head(struct list_head *params_list, char *parameter_name)
{
struct cwmp_dm_parameter *param_iter = NULL;
list_for_each_entry (param_iter, params_list, list) {
@ -90,7 +96,7 @@ static int get_parameter_notification_from_list_head(struct list_head *params_li
return 0;
}
static int get_parameter_notification_from_notifications_uci_list(char *parameter_name)
int get_parameter_notification_from_notifications_uci_list(char *parameter_name)
{
int i, notification = 0;
struct uci_list *list_notif;
@ -114,7 +120,7 @@ static int get_parameter_notification_from_notifications_uci_list(char *paramete
return notification;
}
static int get_parameter_in_list_value_change(char *parameter_name)
int get_parameter_in_list_value_change(char *parameter_name)
{
struct cwmp_dm_parameter *param_iter = NULL;
list_for_each_entry (param_iter, &list_value_change, list) {
@ -123,6 +129,7 @@ static int get_parameter_in_list_value_change(char *parameter_name)
}
return 0;
}
////////////////////////////////////////////
static void cwmp_init_list_param_notify_unit_test_default(void **state)
{
@ -264,6 +271,7 @@ static void cwmp_check_value_change_1_unit_test(void **state)
assert_int_equal((int)list_empty(&list_value_change), 0);
assert_int_equal((int)list_empty(&list_lw_value_change), 1);
assert_int_equal(get_parameter_in_list_value_change("Device.DeviceInfo.UpTime"), 1);
clean_list_value_change();
}
int icwmp_notifications_test(void)

File diff suppressed because it is too large Load diff

View file

@ -31,9 +31,9 @@ static int cwmp_uci_unit_tests_init(void **state)
static int cwmp_uci_unit_tests_clean(void **state)
{
icwmp_cleanmem();
cwmp_uci_exit();
if (list != NULL)
cwmp_free_uci_list(list);
cwmp_uci_exit();
return 0;
}
@ -81,7 +81,6 @@ static void cwmp_uci_get_tests(void **state)
error = cwmp_uci_get_value_by_section_string(s, "wrong_option", &value);
assert_null(value);
assert_int_equal(error, UCI_ERR_NOTFOUND);
}
static void cwmp_uci_set_tests(void **state)
@ -138,27 +137,24 @@ static void cwmp_uci_set_tests(void **state)
error = cwmp_uci_get_option_value_string("cwmp", "wront_section", "wrong_option", UCI_VARSTATE_CONFIG, &value);
assert_int_equal(error, UCI_ERR_NOTFOUND);
assert_null(value);
}
static void cwmp_uci_add_tests(void **state)
{
struct uci_section *s = NULL;
int error = UCI_OK;
int error = UCI_OK, cmp_cfg = 0;
error = cwmp_uci_add_section("cwmp", "acs", UCI_STANDARD_CONFIG, &s);
assert_non_null(s);
assert_int_equal(error, UCI_OK);
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
assert_int_equal(strncmp(section_name(s), "cfg", 3), 0);
s = NULL;
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
error = cwmp_uci_add_section("new_package", "new_section", UCI_STANDARD_CONFIG, &s);
assert_non_null(s);
assert_int_equal(error, UCI_OK);
cwmp_commit_package("new_package", UCI_STANDARD_CONFIG);
assert_int_equal(strncmp(section_name(s), "cfg", 3), 0);
s = NULL;
cwmp_commit_package("new_package", UCI_STANDARD_CONFIG);
error = cwmp_uci_add_section_with_specific_name("cwmp", "acs", "new_acs", UCI_STANDARD_CONFIG);
assert_int_equal(error, UCI_OK);
@ -179,29 +175,26 @@ static void cwmp_uci_list_tests(void **state)
assert_int_equal(error, UCI_OK);
error = cwmp_uci_add_list_value("cwmp", "cpe", "optionlist", "val2", UCI_STANDARD_CONFIG);
assert_int_equal(error, UCI_OK);
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
error = cwmp_uci_get_cwmp_standard_option_value_list("cwmp", "cpe", "optionlist", &list);
assert_int_equal(error, UCI_TYPE_LIST);
list_string = cwmp_uci_list_to_string(list, ",");
assert_non_null(list_string);
assert_string_equal(list_string, "val1,val2");
list_string = NULL;
if(list != NULL)
if(list != NULL) {
cwmp_free_uci_list(list);
list = NULL;
}
error = cwmp_uci_add_list_value("cwmp", "wrong_section", "optionlist", "val1", UCI_STANDARD_CONFIG);
assert_int_equal(error, UCI_ERR_INVAL);
error = cwmp_uci_add_list_value("cwmp", "wrong_section", "optionlist", "val2", UCI_STANDARD_CONFIG);
assert_int_equal(error, UCI_ERR_INVAL);
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
error = cwmp_uci_get_cwmp_standard_option_value_list("cwmp", "wrong_section", "optionlist", &list);
assert_int_equal(error, UCI_ERR_NOTFOUND);
assert_null(list);
list_string = cwmp_uci_list_to_string(list, ",");
assert_null(list_string);
if(list != NULL)
cwmp_free_uci_list(list);
}
int icwmp_uci_test(void)

View file

@ -1,11 +0,0 @@
config deviceinfo 'deviceinfo'
option Manufacturer 'iopsys'
option ProductClass 'FirstClass'
option SerialNumber '000000001'
option SoftwareVersion 'IOPSYS-CODE-ANALYSIS'
option HardwareVersion '1.0'
option DeviceCategory 'Gateway'
option ModelName 'ModelName'
option Description 'Iopsys code analysis test simulator'
option ManufacturerOUI 'XXX'
option BaseMACAddress 'feeddeadbeef'

View file

@ -14,12 +14,13 @@ config acs 'acs'
option https_ssl_capath ''
option ipv6_enable '0'
option ip_version '4'
option url 'http://127.0.0.1:7547'
config cpe 'cpe'
option interface 'eth0'
option interface 'lo'
option default_wan_interface 'wan'
option log_to_console 'disable'
option log_to_syslog 'disable'
option log_to_syslog 'enable'
option log_to_file 'enable'
# log_severity: INFO (Default)
# log_severity possible configs: EMERG, ALERT, CRITIC ,ERROR, WARNING, NOTICE, INFO, DEBUG

View file

@ -50,12 +50,7 @@ function check_session()
function remove_icwmp_log()
{
rm -f $icwmp_log_file
if [ -f "$icwmp_log_file" ]; then
echo "$icwmp_log_file exists" >> ./funl-test-debug.log
exit 1
fi
echo "" > $icwmp_log_file
}
function print_tag_value()

6
test/script/test_seq.txt Normal file
View file

@ -0,0 +1,6 @@
verify_add_method.sh
verify_delete_method.sh
verify_get_method.sh
verify_set_method.sh
verify_download_method.sh
verify_cmd_line.sh

View file

@ -19,11 +19,15 @@ if [ "$status" != "1" ]; then
exit 1
fi
rm /etc/icwmpd/dm_enabled_notify
rm /var/run/icwmpd/dm_enabled_notify
remove_icwmp_log
echo "Restarting icwmpd in order to apply the new firmware" >> ./funl-test-debug.log
supervisorctl restart icwmpd >> ./funl-test-debug.log
sleep 5
echo "Restarting icwmpd in order to apply the new firmware" >> ./funl-test-debug.log
#/builds/iopsys/icwmp/bin/icwmpd -b &
supervisorctl stop icwmpd
sleep 3
supervisorctl start icwmpd >> ./funl-test-debug.log
sleep 10
check_session "TransferComplete"
received_command_key=$(print_tag_value "cwmp:TransferComplete" "CommandKey")
if [ "$sent_command_key" != "$received_command_key" ]; then

132
ubus.c
View file

@ -11,22 +11,21 @@
* Copyright (C) 2012 Luka Perkov <freecwmp@lukaperkov.net>
*/
#include <json-c/json.h>
#include <pthread.h>
#include <sys/socket.h>
#include <libubox/blobmsg_json.h>
#include "ubus.h"
#include "session.h"
#include "log.h"
#include "cwmp_time.h"
#include "event.h"
#include "backupSession.h"
#include "sched_inform.h"
#include "http.h"
#include "cwmp_du_state.h"
#include "download.h"
#include "upload.h"
#include "cwmp_du_state.h"
#include "netlink.h"
#include "event.h"
#include "cwmp_time.h"
#include "http.h"
#include "soap.h"
#include "cwmp_event.h"
static struct ubus_context *ctx = NULL;
@ -50,7 +49,7 @@ static const struct blobmsg_policy command_policy[] = {
static int cwmp_handle_command(struct ubus_context *ctx, struct ubus_object *obj __attribute__((unused)), struct ubus_request_data *req, const char *method __attribute__((unused)), struct blob_attr *msg)
{
struct blob_attr *tb[__COMMAND_MAX];
struct blob_buf blob_command;
static struct blob_buf blob_command;
blobmsg_parse(command_policy, ARRAYSIZEOF(command_policy), tb, blob_data(msg), blob_len(msg));
@ -71,15 +70,13 @@ static int cwmp_handle_command(struct ubus_context *ctx, struct ubus_object *obj
return -1;
} else if (!strcmp("reload", cmd)) {
CWMP_LOG(INFO, "triggered ubus reload");
if (cwmp_main.session_status.last_status == SESSION_RUNNING) {
if (cwmp_main->session->session_status.last_status == SESSION_RUNNING) {
cwmp_set_end_session(END_SESSION_RELOAD);
blobmsg_add_u32(&blob_command, "status", 0);
if (snprintf(info, sizeof(info), "Session running, reload at the end of the session") == -1)
return -1;
} else {
pthread_mutex_lock(&(cwmp_main.mutex_session_queue));
cwmp_apply_acs_changes();
pthread_mutex_unlock(&(cwmp_main.mutex_session_queue));
blobmsg_add_u32(&blob_command, "status", 0);
if (snprintf(info, sizeof(info), "icwmpd config reloaded") == -1)
return -1;
@ -98,30 +95,21 @@ static int cwmp_handle_command(struct ubus_context *ctx, struct ubus_object *obj
return -1;
} else if (!strcmp("exit", cmd)) {
ubus_exit = true;
thread_end = true;
if (cwmp_main.session_status.last_status == SESSION_RUNNING)
if (snprintf(info, sizeof(info), "icwmpd daemon stopped") == -1)
return -1;
cwmp_stop = true;
if (cwmp_main->session->session_status.last_status == SESSION_RUNNING)
http_set_timeout();
pthread_cond_signal(&(cwmp_main.threshold_session_send));
pthread_cond_signal(&(cwmp_main.threshold_periodic));
pthread_cond_signal(&(cwmp_main.threshold_notify_periodic));
pthread_cond_signal(&threshold_schedule_inform);
pthread_cond_signal(&threshold_download);
pthread_cond_signal(&threshold_change_du_state);
pthread_cond_signal(&threshold_schedule_download);
pthread_cond_signal(&threshold_apply_schedule_download);
pthread_cond_signal(&threshold_upload);
uloop_timeout_cancel(&retry_session_timer);
uloop_timeout_cancel(&priodic_session_timer);
uloop_timeout_cancel(&session_timer);
uloop_end();
shutdown(cwmp_main->cr_socket_desc, SHUT_RDWR);
shutdown(cwmp_main.cr_socket_desc, SHUT_RDWR);
if (!signal_exit)
kill(getpid(), SIGTERM);
if (snprintf(info, sizeof(info), "icwmpd daemon stopped") == -1)
return -1;
} else {
blobmsg_add_u32(&blob_command, "status", -1);
if (snprintf(info, sizeof(info), "%s command is not supported", cmd) == -1)
@ -129,6 +117,7 @@ static int cwmp_handle_command(struct ubus_context *ctx, struct ubus_object *obj
}
blobmsg_add_string(&blob_command, "info", info);
ubus_send_reply(ctx, req, blob_command.head);
blob_buf_free(&blob_command);
@ -143,11 +132,11 @@ static inline time_t get_session_status_next_time()
schedule_inform = list_entry(list_schedule_inform.next, struct schedule_inform, list);
ntime = schedule_inform->scheduled_time;
}
if (!ntime || (cwmp_main.session_status.next_retry && ntime > cwmp_main.session_status.next_retry)) {
ntime = cwmp_main.session_status.next_retry;
if (!ntime || (cwmp_main->session->session_status.next_retry && ntime > cwmp_main->session->session_status.next_retry)) {
ntime = cwmp_main->session->session_status.next_retry;
}
if (!ntime || (cwmp_main.session_status.next_periodic && ntime > cwmp_main.session_status.next_periodic)) {
ntime = cwmp_main.session_status.next_periodic;
if (!ntime || (cwmp_main->session->session_status.next_periodic && ntime > cwmp_main->session->session_status.next_periodic)) {
ntime = cwmp_main->session->session_status.next_periodic;
}
return ntime;
}
@ -156,21 +145,20 @@ static int cwmp_handle_status(struct ubus_context *ctx, struct ubus_object *obj
{
void *c;
time_t ntime = 0;
struct blob_buf blob_status;
static struct blob_buf blob_status;
memset(&blob_status, 0, sizeof(struct blob_buf));
blob_buf_init(&blob_status, 0);
c = blobmsg_open_table(&blob_status, "cwmp");
blobmsg_add_string(&blob_status, "status", "up");
blobmsg_add_string(&blob_status, "start_time", mix_get_time_of(cwmp_main.start_time));
blobmsg_add_string(&blob_status, "acs_url", cwmp_main.conf.acsurl);
blobmsg_add_string(&blob_status, "start_time", mix_get_time_of(cwmp_main->start_time));
blobmsg_add_string(&blob_status, "acs_url", cwmp_main->conf.acsurl);
blobmsg_close_table(&blob_status, c);
c = blobmsg_open_table(&blob_status, "last_session");
blobmsg_add_string(&blob_status, "status", cwmp_main.session_status.last_start_time ? arr_session_status[cwmp_main.session_status.last_status] : "N/A");
blobmsg_add_string(&blob_status, "start_time", cwmp_main.session_status.last_start_time ? mix_get_time_of(cwmp_main.session_status.last_start_time) : "N/A");
blobmsg_add_string(&blob_status, "end_time", cwmp_main.session_status.last_end_time ? mix_get_time_of(cwmp_main.session_status.last_end_time) : "N/A");
blobmsg_add_string(&blob_status, "status", cwmp_main->session->session_status.last_start_time ? arr_session_status[cwmp_main->session->session_status.last_status] : "N/A");
blobmsg_add_string(&blob_status, "start_time", cwmp_main->session->session_status.last_start_time ? mix_get_time_of(cwmp_main->session->session_status.last_start_time) : "N/A");
blobmsg_add_string(&blob_status, "end_time", cwmp_main->session->session_status.last_end_time ? mix_get_time_of(cwmp_main->session->session_status.last_end_time) : "N/A");
blobmsg_close_table(&blob_status, c);
c = blobmsg_open_table(&blob_status, "next_session");
@ -181,9 +169,9 @@ static int cwmp_handle_status(struct ubus_context *ctx, struct ubus_object *obj
blobmsg_close_table(&blob_status, c);
c = blobmsg_open_table(&blob_status, "statistics");
blobmsg_add_u32(&blob_status, "success_sessions", cwmp_main.session_status.success_session);
blobmsg_add_u32(&blob_status, "failure_sessions", cwmp_main.session_status.failure_session);
blobmsg_add_u32(&blob_status, "total_sessions", cwmp_main.session_status.success_session + cwmp_main.session_status.failure_session);
blobmsg_add_u32(&blob_status, "success_sessions", cwmp_main->session->session_status.success_session);
blobmsg_add_u32(&blob_status, "failure_sessions", cwmp_main->session->session_status.failure_session);
blobmsg_add_u32(&blob_status, "total_sessions", cwmp_main->session->session_status.success_session + cwmp_main->session->session_status.failure_session);
blobmsg_close_table(&blob_status, c);
ubus_send_reply(ctx, req, blob_status.head);
@ -209,9 +197,8 @@ static int cwmp_handle_inform(struct ubus_context *ctx, struct ubus_object *obj
struct blob_attr *tb[__INFORM_MAX];
bool grm = false;
char *event = "";
struct blob_buf blob_inform;
static struct blob_buf blob_inform;
memset(&blob_inform, 0, sizeof(struct blob_buf));
blob_buf_init(&blob_inform, 0);
blobmsg_parse(inform_policy, ARRAYSIZEOF(inform_policy), tb, blob_data(msg), blob_len(msg));
@ -222,33 +209,25 @@ static int cwmp_handle_inform(struct ubus_context *ctx, struct ubus_object *obj
if (tb[INFORM_EVENT]) {
event = blobmsg_data(tb[INFORM_EVENT]);
}
if (grm) {
struct event_container *event_container;
struct session *session;
pthread_mutex_lock(&(cwmp_main.mutex_session_queue));
event_container = cwmp_add_event_container(&cwmp_main, EVENT_IDX_2PERIODIC, "");
if (event_container == NULL) {
pthread_mutex_unlock(&(cwmp_main.mutex_session_queue));
event_container = cwmp_add_event_container(EVENT_IDX_2PERIODIC, "");
if (event_container == NULL)
return 0;
}
cwmp_save_event_container(event_container);
session = list_entry(cwmp_main.head_event_container, struct session, head_event_container);
if (cwmp_add_session_rpc_acs(session, RPC_ACS_GET_RPC_METHODS) == NULL) {
pthread_mutex_unlock(&(cwmp_main.mutex_session_queue));
//session = list_entry(cwmp_main.head_event_container, struct session, head_event_container);
if (cwmp_add_session_rpc_acs(RPC_ACS_GET_RPC_METHODS) == NULL)
return 0;
}
pthread_mutex_unlock(&(cwmp_main.mutex_session_queue));
pthread_cond_signal(&(cwmp_main.threshold_session_send));
blobmsg_add_u32(&blob_inform, "status", 1);
blobmsg_add_string(&blob_inform, "info", "Session with GetRPCMethods will start");
} else {
int event_code = cwmp_get_int_event_code(event);
pthread_mutex_lock(&(cwmp_main.mutex_session_queue));
cwmp_add_event_container(&cwmp_main, event_code, "");
pthread_mutex_unlock(&(cwmp_main.mutex_session_queue));
pthread_cond_signal(&(cwmp_main.threshold_session_send));
if (cwmp_main.session_status.last_status == SESSION_RUNNING) {
cwmp_add_event_container(event_code, "");
if (cwmp_main->session->session_status.last_status == SESSION_RUNNING) {
blobmsg_add_u32(&blob_inform, "status", -1);
blobmsg_add_string(&blob_inform, "info", "Session already running, event will be sent at the end of the session");
} else {
@ -256,9 +235,9 @@ static int cwmp_handle_inform(struct ubus_context *ctx, struct ubus_object *obj
blobmsg_add_string(&blob_inform, "info", "Session started");
}
}
trigger_cwmp_session_timer();
ubus_send_reply(ctx, req, blob_inform.head);
blob_buf_free(&blob_inform);
return 0;
}
@ -277,20 +256,9 @@ static struct ubus_object main_object = {
.n_methods = ARRAYSIZEOF(freecwmp_methods),
};
int cwmp_ubus_init(struct cwmp *cwmp)
int cwmp_ubus_init()
{
uloop_init();
if (netlink_init()) {
CWMP_LOG(ERROR, "netlink initialization failed");
}
if (cwmp->conf.ipv6_enable) {
if (netlink_init_v6()) {
CWMP_LOG(ERROR, "netlink initialization failed");
}
}
ctx = ubus_connect(cwmp->conf.ubus_socket);
ctx = ubus_connect(cwmp_main->conf.ubus_socket);
if (!ctx)
return -1;
@ -299,8 +267,6 @@ int cwmp_ubus_init(struct cwmp *cwmp)
if (ubus_add_object(ctx, &main_object))
return -1;
uloop_run();
uloop_done();
return 0;
}
@ -355,7 +321,7 @@ int cwmp_ubus_call(const char *obj, const char *method, const struct cwmp_ubus_a
}
blobmsg_close_array(&b, a);
} else if (u_args[i].type == UBUS_List_Param_Set) {
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
void *a;
a = blobmsg_open_array(&b, u_args[i].key);
list_for_each_entry (param_value, u_args[i].val.param_value_list, list) {
@ -369,7 +335,7 @@ int cwmp_ubus_call(const char *obj, const char *method, const struct cwmp_ubus_a
}
blobmsg_close_array(&b, a);
} else if (u_args[i].type == UBUS_List_Param_Get) {
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
void *a;
a = blobmsg_open_array(&b, u_args[i].key);
list_for_each_entry (param_value, u_args[i].val.param_value_list, list) {
@ -379,7 +345,7 @@ int cwmp_ubus_call(const char *obj, const char *method, const struct cwmp_ubus_a
}
blobmsg_close_array(&b, a);
} else if (u_args[i].type == UBUS_Obj_Obj) {
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
json_object *input_json_obj = json_object_new_object();
list_for_each_entry (param_value, u_args[i].val.param_value_list, list) {
if (!param_value->name)

193
upload.c
View file

@ -8,23 +8,26 @@
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include <pthread.h>
#include <curl/curl.h>
#include <stdlib.h>
#include <libubox/blobmsg_json.h>
#include "common.h"
#include "upload.h"
#include "download.h"
#include "cwmp_time.h"
#include "datamodel_interface.h"
#include "download.h"
#include "log.h"
#include "cwmp_time.h"
#include "backupSession.h"
#include "event.h"
#include "cwmp_uci.h"
#include "event.h"
#include "subprocess.h"
#include "session.h"
#define CURL_TIMEOUT 20
LIST_HEAD(list_upload);
pthread_cond_t threshold_upload;
pthread_mutex_t mutex_upload = PTHREAD_MUTEX_INITIALIZER;
int lookup_vcf_name(char *instance, char **value)
@ -33,11 +36,9 @@ int lookup_vcf_name(char *instance, char **value)
char *err = NULL;
LIST_HEAD(vcf_parameters);
snprintf(vcf_name_parameter, sizeof(vcf_name_parameter), "Device.DeviceInfo.VendorConfigFile.%s.Name", instance);
if (cwmp_get_parameter_values(vcf_name_parameter, &vcf_parameters) != NULL) {
CWMP_LOG(ERROR, "Not able to get the value of the parameter %s : %s", vcf_name_parameter, err);
if ((err = cwmp_get_parameter_values(vcf_name_parameter, &vcf_parameters)) != NULL)
return -1;
}
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
list_for_each_entry (param_value, &vcf_parameters, list) {
*value = strdup(param_value->value);
break;
@ -52,11 +53,9 @@ int lookup_vlf_name(char *instance, char **value)
char *err = NULL;
LIST_HEAD(vlf_parameters);
snprintf(vlf_name_parameter, sizeof(vlf_name_parameter), "Device.DeviceInfo.VendorLogFile.%s.Name", instance);
if (cwmp_get_parameter_values(vlf_name_parameter, &vlf_parameters) != NULL) {
CWMP_LOG(ERROR, "Not able to get the value of the parameter %s : %s", vlf_name_parameter, err);
if ((err = cwmp_get_parameter_values(vlf_name_parameter, &vlf_parameters)) != NULL)
return -1;
}
struct cwmp_dm_parameter *param_value;
struct cwmp_dm_parameter *param_value = NULL;
list_for_each_entry (param_value, &vlf_parameters, list) {
*value = strdup(param_value->value);
break;
@ -65,6 +64,9 @@ int lookup_vlf_name(char *instance, char **value)
return 0;
}
/*
* Upload file
*/
int upload_file(const char *file_path, const char *url, const char *username, const char *password)
{
int res_code = 0;
@ -95,6 +97,58 @@ int upload_file(const char *file_path, const char *url, const char *username, co
return res_code;
}
char *upload_file_task_function(char *task)
{
struct blob_buf bbuf;
memset(&bbuf, 0, sizeof(struct blob_buf));
blob_buf_init(&bbuf, 0);
if (blobmsg_add_json_from_string(&bbuf, task) == false) {
blob_buf_free(&bbuf);
return NULL;
}
const struct blobmsg_policy p[5] = { { "task", BLOBMSG_TYPE_STRING }, { "file_path", BLOBMSG_TYPE_STRING }, { "url", BLOBMSG_TYPE_STRING }, { "username", BLOBMSG_TYPE_STRING }, { "password", BLOBMSG_TYPE_STRING } };
struct blob_attr *tb[5] = { NULL, NULL, NULL, NULL, NULL};
blobmsg_parse(p, 5, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head));
char *task_name = blobmsg_get_string(tb[0]);
if (!task_name || strcmp(task_name, "upload") != 0)
return NULL;
char *file_path = blobmsg_get_string(tb[1]);
char *url = blobmsg_get_string(tb[2]);
char *username = blobmsg_get_string(tb[3]);
char *password = blobmsg_get_string(tb[4]);
int http_code = upload_file(file_path, url, username, password);
char *http_ret = (char *)malloc(4 * sizeof(char));
snprintf(http_ret, 4, "%d", http_code);
http_ret[3] = 0;
return http_ret;
}
int upload_file_in_subprocess(const char *file_path, const char *url, const char *username, const char *password)
{
subprocess_start(upload_file_task_function);
struct blob_buf bbuf;
memset(&bbuf, 0, sizeof(struct blob_buf));
blob_buf_init(&bbuf, 0);
blobmsg_add_string(&bbuf, "task", "upload");
blobmsg_add_string(&bbuf, "file_path", file_path);
blobmsg_add_string(&bbuf, "url", url);
blobmsg_add_string(&bbuf, "username", username);
blobmsg_add_string(&bbuf, "password", password);
char *upload_task = blobmsg_format_json(bbuf.head, true);
blob_buf_free(&bbuf);
if (upload_task != NULL) {
char *ret = execute_task_in_subprocess(upload_task);
return atoi(ret);
}
return 500;
}
int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptransfer_complete)
{
int error = FAULT_CPE_NO_FAULT;
@ -108,10 +162,8 @@ int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptrans
if (pupload->file_type[0] == '1' || pupload->file_type[0] == '3') {
if (pupload->f_instance && isdigit(pupload->f_instance[0])) {
name = NULL;
lookup_vcf_name(pupload->f_instance, &name);
if (name && strlen(name) > 0) {
// cppcheck-suppress uninitvar
snprintf(file_path, sizeof(file_path), "/tmp/%s", name);
cwmp_uci_export_package(name, file_path, UCI_STANDARD_CONFIG);
FREE(name);
@ -165,90 +217,6 @@ end_upload:
return error;
}
void *thread_cwmp_rpc_cpe_upload(void *v)
{
struct cwmp *cwmp = (struct cwmp *)v;
struct upload *pupload;
struct timespec upload_timeout = { 0, 0 };
time_t current_time, stime;
int error = FAULT_CPE_NO_FAULT;
struct transfer_complete *ptransfer_complete;
long int time_of_grace = 3600, timeout;
for (;;) {
if (thread_end)
break;
if (list_upload.next != &(list_upload)) {
pupload = list_entry(list_upload.next, struct upload, list);
stime = pupload->scheduled_time;
current_time = time(NULL);
if (pupload->scheduled_time != 0)
timeout = current_time - pupload->scheduled_time;
else
timeout = 0;
if ((timeout >= 0) && (timeout > time_of_grace)) {
pthread_mutex_lock(&mutex_upload);
bkp_session_delete_upload(pupload);
ptransfer_complete = calloc(1, sizeof(struct transfer_complete));
if (ptransfer_complete != NULL) {
error = FAULT_CPE_DOWNLOAD_FAILURE;
ptransfer_complete->command_key = strdup(pupload->command_key);
ptransfer_complete->start_time = strdup(mix_get_time());
ptransfer_complete->complete_time = strdup(ptransfer_complete->start_time);
ptransfer_complete->fault_code = error;
ptransfer_complete->type = TYPE_UPLOAD;
bkp_session_insert_transfer_complete(ptransfer_complete);
cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete);
}
list_del(&(pupload->list));
if (pupload->scheduled_time != 0)
count_download_queue--;
cwmp_free_upload_request(pupload);
pthread_mutex_unlock(&mutex_download);
continue;
}
if ((timeout >= 0) && (timeout <= time_of_grace)) {
pthread_mutex_lock(&(cwmp->mutex_session_send));
CWMP_LOG(INFO, "Launch upload file %s", pupload->url);
error = cwmp_launch_upload(pupload, &ptransfer_complete);
if (error != FAULT_CPE_NO_FAULT) {
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete);
bkp_session_delete_transfer_complete(ptransfer_complete);
} else {
bkp_session_delete_transfer_complete(ptransfer_complete);
ptransfer_complete->fault_code = error;
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
cwmp_root_cause_transfer_complete(cwmp, ptransfer_complete);
}
pthread_mutex_unlock(&(cwmp->mutex_session_send));
pthread_cond_signal(&(cwmp->threshold_session_send));
pthread_mutex_lock(&mutex_upload);
list_del(&(pupload->list));
if (pupload->scheduled_time != 0)
count_download_queue--;
cwmp_free_upload_request(pupload);
pthread_mutex_unlock(&mutex_upload);
continue;
}
pthread_mutex_lock(&mutex_upload);
upload_timeout.tv_sec = stime;
pthread_cond_timedwait(&threshold_upload, &mutex_upload, &upload_timeout);
pthread_mutex_unlock(&mutex_upload);
} else {
pthread_mutex_lock(&mutex_upload);
pthread_cond_wait(&threshold_upload, &mutex_upload);
pthread_mutex_unlock(&mutex_upload);
}
}
return NULL;
}
int cwmp_free_upload_request(struct upload *upload)
{
if (upload != NULL) {
@ -291,3 +259,30 @@ int cwmp_scheduledUpload_remove_all()
return CWMP_OK;
}
void cwmp_start_upload(struct uloop_timeout *timeout)
{
struct upload *pupload;
int error = FAULT_CPE_NO_FAULT;
struct transfer_complete *ptransfer_complete;
pupload = container_of(timeout, struct upload, handler_timer);
CWMP_LOG(INFO, "Launch download file %s", pupload->url);
error = cwmp_launch_upload(pupload, &ptransfer_complete);
sleep(3);
if (error != FAULT_CPE_NO_FAULT) {
CWMP_LOG(ERROR, "Error while uploading the file: %s", pupload->url);
}
bkp_session_insert_transfer_complete(ptransfer_complete);
bkp_session_save();
cwmp_root_cause_transfer_complete(ptransfer_complete);
pthread_mutex_lock(&mutex_upload);
list_del(&(pupload->list));
if (pupload->scheduled_time != 0)
count_download_queue--;
cwmp_free_upload_request(pupload);
pthread_mutex_unlock(&mutex_upload);
trigger_cwmp_session_timer();
}

76
xml.c
View file

@ -9,13 +9,13 @@
* Author Ahmed Zribi <ahmed.zribi@pivasoftware.com>
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*/
#include "xml.h"
#include "common.h"
#include "log.h"
#include "cwmp_zlib.h"
#include "http.h"
#include "notifications.h"
#include "messages.h"
#include "http.h"
#include "cwmp_zlib.h"
static const char *soap_env_url = "http://schemas.xmlsoap.org/soap/envelope/";
static const char *soap_enc_url = "http://schemas.xmlsoap.org/soap/encoding/";
@ -116,19 +116,19 @@ void xml_exit(void)
FREE(ns.cwmp);
}
int xml_send_message(struct cwmp *cwmp, struct session *session, struct rpc *rpc)
int xml_send_message(struct rpc *rpc)
{
char *s, *msg_out = NULL, *msg_in = NULL;
char c[512];
int msg_out_len = 0, f, r = 0;
mxml_node_t *b;
if (session->tree_out) {
if (cwmp_main->session->tree_out) {
unsigned char *zmsg_out;
msg_out = mxmlSaveAllocString(session->tree_out, whitespace_cb);
msg_out = mxmlSaveAllocString(cwmp_main->session->tree_out, whitespace_cb);
CWMP_LOG_XML_MSG(DEBUG, msg_out, XML_MSG_OUT);
if (cwmp->conf.compression != COMP_NONE) {
if (zlib_compress(msg_out, &zmsg_out, &msg_out_len, cwmp->conf.compression)) {
if (cwmp_main->conf.compression != COMP_NONE) {
if (zlib_compress(msg_out, &zmsg_out, &msg_out_len, cwmp_main->conf.compression)) {
return -1;
}
FREE(msg_out);
@ -139,7 +139,7 @@ int xml_send_message(struct cwmp *cwmp, struct session *session, struct rpc *rpc
}
while (1) {
f = 0;
if (http_send_message(cwmp, msg_out, msg_out_len, &msg_in)) {
if (http_send_message(msg_out, msg_out_len, &msg_in)) {
goto error;
}
if (msg_in) {
@ -167,31 +167,31 @@ int xml_send_message(struct cwmp *cwmp, struct session *session, struct rpc *rpc
}
}
session->tree_in = mxmlLoadString(NULL, msg_in, MXML_OPAQUE_CALLBACK);
if (!session->tree_in)
cwmp_main->session->tree_in = mxmlLoadString(NULL, msg_in, MXML_OPAQUE_CALLBACK);
if (!cwmp_main->session->tree_in)
goto error;
xml_recreate_namespace(session->tree_in);
xml_recreate_namespace(cwmp_main->session->tree_in);
/* get NoMoreRequests or HolRequest*/
session->hold_request = false;
cwmp_main->session->hold_request = false;
if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "NoMoreRequests") == -1)
goto error;
b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
b = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND);
if (b) {
b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST);
b = mxmlWalkNext(b, cwmp_main->session->tree_in, MXML_DESCEND_FIRST);
if (b && b->type == MXML_OPAQUE && b->value.opaque)
session->hold_request = atoi(b->value.opaque);
cwmp_main->session->hold_request = (atoi(b->value.opaque)) ? true : false;
} else {
if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "HoldRequests") == -1)
goto error;
b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
b = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND);
if (b) {
b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST);
b = mxmlWalkNext(b, cwmp_main->session->tree_in, MXML_DESCEND_FIRST);
if (b && b->type == MXML_OPAQUE && b->value.opaque)
session->hold_request = atoi(b->value.opaque);
cwmp_main->session->hold_request = (atoi(b->value.opaque)) ? true : false;
}
}
@ -206,36 +206,34 @@ error:
return -1;
}
int xml_prepare_msg_out(struct session *session)
int xml_prepare_msg_out()
{
struct cwmp *cwmp = &cwmp_main;
struct config *conf;
conf = &(cwmp->conf);
struct config *conf = &(cwmp_main->conf);
mxml_node_t *n;
session->tree_out = mxmlLoadString(NULL, CWMP_RESPONSE_MESSAGE, MXML_OPAQUE_CALLBACK);
n = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND);
cwmp_main->session->tree_out = mxmlLoadString(NULL, CWMP_RESPONSE_MESSAGE, MXML_OPAQUE_CALLBACK);
n = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "soap_env:Envelope", NULL, NULL, MXML_DESCEND);
if (!n) {
return -1;
}
mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(conf->amd_version) - 1]);
if (!session->tree_out)
if (!cwmp_main->session->tree_out)
return -1;
return 0;
}
int xml_set_cwmp_id(struct session *session)
int xml_set_cwmp_id()
{
char c[32];
mxml_node_t *b;
/* define cwmp id */
if (snprintf(c, sizeof(c), "%u", ++(cwmp_main.cwmp_id)) == -1)
if (snprintf(c, sizeof(c), "%u", ++(cwmp_main->cwmp_id)) == -1)
return -1;
b = mxmlFindElement(session->tree_out, session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND);
b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND);
if (!b)
return -1;
@ -246,7 +244,7 @@ int xml_set_cwmp_id(struct session *session)
return 0;
}
int xml_set_cwmp_id_rpc_cpe(struct session *session)
int xml_set_cwmp_id_rpc_cpe()
{
char c[512];
mxml_node_t *b;
@ -255,16 +253,16 @@ int xml_set_cwmp_id_rpc_cpe(struct session *session)
if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "ID") == -1)
return -1;
b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
b = mxmlFindElement(cwmp_main->session->tree_in, cwmp_main->session->tree_in, c, NULL, NULL, MXML_DESCEND);
if (b) {
/* ACS send ID parameter */
b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST);
b = mxmlWalkNext(b, cwmp_main->session->tree_in, MXML_DESCEND_FIRST);
if (!b || b->type != MXML_OPAQUE || !b->value.opaque)
return 0;
snprintf(c, sizeof(c), "%s", b->value.opaque);
b = mxmlFindElement(session->tree_out, session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND);
b = mxmlFindElement(cwmp_main->session->tree_out, cwmp_main->session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND);
if (!b)
return -1;
@ -273,7 +271,7 @@ int xml_set_cwmp_id_rpc_cpe(struct session *session)
return -1;
} else {
/* ACS does not send ID parameter */
int r = xml_set_cwmp_id(session);
int r = xml_set_cwmp_id(cwmp_main->session);
return r;
}
return 0;
@ -370,9 +368,7 @@ error:
int xml_prepare_lwnotification_message(char **msg_out)
{
mxml_node_t *lw_tree, *b, *parameter_list;
struct cwmp *cwmp = &cwmp_main;
struct config *conf;
conf = &(cwmp->conf);
struct config *conf = &(cwmp_main->conf);
char *c = NULL;
lw_tree = mxmlLoadString(NULL, CWMP_LWNOTIFICATION_MESSAGE, MXML_OPAQUE_CALLBACK);
@ -414,7 +410,7 @@ int xml_prepare_lwnotification_message(char **msg_out)
if (!b)
goto error;
b = mxmlNewOpaque(b, cwmp->deviceid.oui);
b = mxmlNewOpaque(b, cwmp_main->deviceid.oui);
if (!b)
goto error;
@ -422,7 +418,7 @@ int xml_prepare_lwnotification_message(char **msg_out)
if (!b)
goto error;
b = mxmlNewOpaque(b, cwmp->deviceid.productclass ? cwmp->deviceid.productclass : "");
b = mxmlNewOpaque(b, cwmp_main->deviceid.productclass ? cwmp_main->deviceid.productclass : "");
if (!b)
goto error;
@ -430,7 +426,7 @@ int xml_prepare_lwnotification_message(char **msg_out)
if (!b)
goto error;
b = mxmlNewOpaque(b, cwmp->deviceid.serialnumber ? cwmp->deviceid.serialnumber : "");
b = mxmlNewOpaque(b, cwmp_main->deviceid.serialnumber ? cwmp_main->deviceid.serialnumber : "");
if (!b)
goto error;