diff --git a/.gitignore b/.gitignore
index ea3d7b8..9965252 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@
*.xml
*.so
*.txt
+*.orig
bin/*
!bin/Makefile.am
.prepared*
diff --git a/Makefile.am b/Makefile.am
index a2e3451..b411dde 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,32 +5,31 @@ CWMP_VERSION = 3.0.1
bin_PROGRAMS = icwmpd
icwmpd_SOURCES = \
- ./common.c \
- ./log.c \
- ./cwmp_uci.c \
- ./config.c \
- ./session.c \
- ./backupSession.c \
- ./digauth.c \
- ./event.c \
- ./http.c \
- ./netlink.c \
- ./ubus_utils.c \
- ./datamodel_interface.c \
- ./cwmp_cli.c \
- ./notifications.c \
- ./cwmp_zlib.c \
- ./cwmp_du_state.c \
- ./download.c \
- ./upload.c \
- ./sched_inform.c \
- ./xml.c \
- ./rpc_soap.c \
- ./diagnostic.c \
- ./reboot.c \
- ./heartbeat.c \
- ./cwmp.c \
- ./ssl_utils.c
+ ./src/common.c \
+ ./src/log.c \
+ ./src/cwmp_uci.c \
+ ./src/config.c \
+ ./src/session.c \
+ ./src/backupSession.c \
+ ./src/digauth.c \
+ ./src/event.c \
+ ./src/http.c \
+ ./src/ubus_utils.c \
+ ./src/datamodel_interface.c \
+ ./src/cwmp_cli.c \
+ ./src/notifications.c \
+ ./src/cwmp_zlib.c \
+ ./src/cwmp_du_state.c \
+ ./src/download.c \
+ ./src/upload.c \
+ ./src/sched_inform.c \
+ ./src/xml.c \
+ ./src/rpc.c \
+ ./src/diagnostic.c \
+ ./src/reboot.c \
+ ./src/heartbeat.c \
+ ./src/cwmp.c \
+ ./src/ssl_utils.c
icwmpd_CFLAGS = \
$(AM_CFLAGS) \
@@ -66,4 +65,4 @@ icwmpd_LDADD = \
icwmpd_CFLAGS+=-DCWMP_VERSION=\"$(CWMP_VERSION)\"
icwmpd_LDFLAGS+=-DCWMP_VERSION=\"$(CWMP_VERSION)\"
-icwmpd_CFLAGS+=-I./inc
+icwmpd_CFLAGS+=-I..
diff --git a/configure.ac b/configure.ac
index e6a636f..30bd834 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
AC_INIT([icwmp], [1.0], [dev@iopsys.eu])
AM_INIT_AUTOMAKE
-AC_CONFIG_SRCDIR([cwmp.c])
+AC_CONFIG_SRCDIR([src/cwmp.c])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
diff --git a/gitlab-ci/functional-test.sh b/gitlab-ci/functional-test.sh
index 84bd75e..a541391 100755
--- a/gitlab-ci/functional-test.sh
+++ b/gitlab-ci/functional-test.sh
@@ -8,6 +8,21 @@ pwd
trap cleanup EXIT
trap cleanup SIGINT
+function check_valgrind_xml() {
+ echo "Checking memory leaks..."
+ grep -q "UninitCondition" memory-report.xml
+ error_on_zero $?
+
+ grep -q "Leak_PossiblyLost" memory-report.xml
+ error_on_zero $?
+
+ grep -q "Leak_DefinitelyLost" memory-report.xml
+ error_on_zero $?
+
+ grep -q "Leak_StillReachable" memory-report.xml
+ error_on_zero $?
+}
+
date +%s > timestamp.log
echo "Compiling icmwp"
build_icwmp
@@ -59,6 +74,11 @@ done
echo "Stop all services"
supervisorctl stop icwmpd
+check_valgrind_xml
+
+cp test/files/etc/config/users /etc/config/
+cp test/files/etc/config/wireless /etc/config/
+
echo "Verify Custom notifications"
echo "#### Start custom_notifications ####" >> "$icwmp_master_log"
if ./test/script/verify_custom_notifications.sh; then
diff --git a/gitlab-ci/shared.sh b/gitlab-ci/shared.sh
index ad05f20..3b8b8c1 100644
--- a/gitlab-ci/shared.sh
+++ b/gitlab-ci/shared.sh
@@ -38,6 +38,7 @@ function exec_cmd()
function configure_genieacs()
{
+ start_acs
sleep 10
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
diff --git a/inc/cwmp_zlib.h b/inc/cwmp_zlib.h
deleted file mode 100644
index acafa16..0000000
--- a/inc/cwmp_zlib.h
+++ /dev/null
@@ -1,17 +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-2020 iopsys Software Solutions AB
- * Author Omar Kallel
- *
- */
-
-#ifndef __ZLIB_H
-#define __ZLIB_H
-
-int zlib_compress(char *message, unsigned char **zmsg, int *zlen, int type);
-
-#endif
diff --git a/inc/diagnostic.h b/inc/diagnostic.h
deleted file mode 100644
index fe2e1e9..0000000
--- a/inc/diagnostic.h
+++ /dev/null
@@ -1,25 +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) 2019 iopsys Software Solutions AB
- * Author: Imen Bhiri
- * Author: Amin Ben Ramdhane
- */
-
-#ifndef __DIAGNOSTIC__H
-#define __DIAGNOSTIC__H
-
-bool set_diagnostic_parameter_structure_value(char *parameter_name, char *value);
-
-int cwmp_download_diagnostics();
-int cwmp_upload_diagnostics();
-int cwmp_ip_ping_diagnostics();
-int cwmp_nslookup_diagnostics();
-int cwmp_traceroute_diagnostics();
-int cwmp_udp_echo_diagnostics();
-int cwmp_serverselection_diagnostics();
-
-#endif
diff --git a/inc/http.h b/inc/http.h
deleted file mode 100644
index 049367f..0000000
--- a/inc/http.h
+++ /dev/null
@@ -1,34 +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) 2011 Luka Perkov
- */
-
-#ifndef _FREECWMP_HTTP_H__
-#define _FREECWMP_HTTP_H__
-
-#include "common.h"
-
-extern char *fc_cookies;
-
-#define HTTP_TIMEOUT 60
-
-struct http_client {
- struct curl_slist *header_list;
- char *url;
-};
-
-void http_set_timeout(void);
-
-int http_client_init(struct cwmp *cwmp);
-void http_client_exit(void);
-int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **msg_in);
-
-void http_server_init(void);
-void http_server_listen(void);
-void http_success_cr(void);
-
-#endif
diff --git a/inc/netlink.h b/inc/netlink.h
deleted file mode 100755
index 1aaddaf..0000000
--- a/inc/netlink.h
+++ /dev/null
@@ -1,19 +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
- * Author Anis Ellouze
- *
- */
-
-#ifndef _NETLINK_H__
-#define _NETLINK_H__
-
-int netlink_init(void);
-int netlink_init_v6(void);
-
-#endif
diff --git a/inc/reboot.h b/inc/reboot.h
deleted file mode 100644
index 276eacf..0000000
--- a/inc/reboot.h
+++ /dev/null
@@ -1,19 +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) 2021 iopsys Software Solutions AB
- * Author Amin Ben Ramdhane
- */
-
-#ifndef _REBOOT_H__
-#define _REBOOT_H__
-
-#include "common.h"
-
-void launch_reboot_methods(struct cwmp *cwmp);
-
-#endif //_REBOOT_H__
-
diff --git a/inc/xml.h b/inc/xml.h
deleted file mode 100644
index d3d0e69..0000000
--- a/inc/xml.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __XML__H_
-#define __XML__H_
-
-#include
-#include "session.h"
-#include "common.h"
-
-#define CWMP_MXML_TAB_SPACE " "
-#define MAX_SCHEDULE_INFORM_QUEUE 10
-
-#define MXML_DELETE(X) \
- do { \
- if (X) { \
- mxmlDelete(X); \
- X = NULL; \
- } \
- } while (0)
-
-extern const char *cwmp_urls[];
-int xml_prepare_msg_out(struct session *session);
-int xml_prepare_lwnotification_message(char **msg_out);
-int xml_set_cwmp_id_rpc_cpe(struct session *session);
-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);
-mxml_node_t *mxmlFindElementOpaque(mxml_node_t *node, mxml_node_t *top, const char *text, int descend);
-char *xml__get_attribute_name_by_value(mxml_node_t *node, const char *value);
-char *xml_get_cwmp_version(int version);
-void xml_exit(void);
-void load_response_xml_schema(mxml_node_t **schema);
-void load_notification_xml_schema(mxml_node_t **tree);
-
-#endif
diff --git a/netlink.c b/netlink.c
deleted file mode 100644
index d7dfb5c..0000000
--- a/netlink.c
+++ /dev/null
@@ -1,282 +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-2021 iopsys Software Solutions AB
- * Author Mohamed Kallel
- * Author Ahmed Zribi
- * Copyright (C) 2011-2012 Luka Perkov
- *
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "netlink.h"
-#include "cwmp_uci.h"
-#include "log.h"
-#include "event.h"
-
-static int itfcmp(char *itf1, char *itf2);
-static void netlink_new_msg(struct uloop_fd *ufd, unsigned events);
-static struct uloop_fd netlink_event = {.cb = netlink_new_msg };
-static struct uloop_fd netlink_event_v6 = {.cb = netlink_new_msg };
-
-static int itfcmp(char *itf1, char *itf2)
-{
- int index = 0;
- int status = 1;
- char *str = NULL;
- char *buf1 = NULL;
- char *buf2 = NULL;
-
- if (itf1 == NULL || itf2 == NULL)
- return status;
-
- if (itf1[0] == '\0')
- goto end;
- str = strchr(itf1, '.');
- if (str == NULL)
- goto end;
- index = (int)(str - itf1);
- if (!index)
- goto end;
-
- buf1 = malloc(index);
- if (!buf1)
- goto end;
-
- strncpy(buf1, itf1, index);
- buf1[index] = '\0';
- if (itf2[0] == '\0')
- goto end;
-
- str = strchr(itf2, '.');
- if (str == NULL)
- goto end;
-
- index = (int)(str - itf2);
- if (!index)
- goto end;
-
- buf2 = malloc(index);
- if (!buf2)
- goto end;
-
- strncpy(buf2, itf1, index);
- buf2[index] = '\0';
-
- if (strcmp(buf1, buf2) == 0)
- status = 0;
-end:
- if (buf1)
- free(buf1);
- if (buf2)
- free(buf2);
- return status;
-}
-
-static void freecwmp_netlink_interface(struct nlmsghdr *nlh)
-{
- struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA(nlh);
- struct rtattr *rth = IFA_RTA(ifa);
- int rtl = IFA_PAYLOAD(nlh);
- char if_name[IFNAMSIZ], if_addr[INET_ADDRSTRLEN];
-
- memset(&if_name, 0, sizeof(if_name));
- memset(&if_addr, 0, sizeof(if_addr));
-
- if (ifa->ifa_family == AF_INET) { //CASE IPv4
- while (rtl && RTA_OK(rth, rtl)) {
- if (rth->rta_type != IFA_LOCAL) {
- rth = RTA_NEXT(rth, rtl);
- continue;
- }
-
- uint32_t addr = htonl(*(uint32_t *)RTA_DATA(rth));
- if (htonl(13) == 13) {
- // running on big endian system
- } else {
- // running on little endian system
- addr = __builtin_bswap32(addr);
- }
-
- if_indextoname(ifa->ifa_index, 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);
- cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG);
- connection_request_ip_value_change(&cwmp_main, IPv4);
- break;
- }
- } else { //CASE IPv6
- while (rtl && RTA_OK(rth, rtl)) {
- char pradd_v6[128];
- if (rth->rta_type != IFA_ADDRESS || ifa->ifa_scope == RT_SCOPE_LINK) {
- rth = RTA_NEXT(rth, rtl);
- continue;
- }
- 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)) {
- 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);
- cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG);
- connection_request_ip_value_change(&cwmp_main, IPv6);
- break;
- }
- }
-}
-
-static void netlink_new_msg(struct uloop_fd *ufd, unsigned events __attribute__((unused)))
-{
- struct nlmsghdr *nlh;
- char buffer[BUFSIZ];
- size_t msg_size;
-
- memset(&buffer, 0, sizeof(buffer));
-
- nlh = (struct nlmsghdr *)buffer;
- if ((int)(msg_size = recv(ufd->fd, nlh, BUFSIZ, 0)) == -1) {
- CWMP_LOG(ERROR, "error receiving netlink message");
- return;
- }
-
- while ((size_t)msg_size > sizeof(*nlh)) {
- int len = nlh->nlmsg_len;
- int req_len = len - sizeof(*nlh);
-
- if (req_len < 0 || (size_t)len > msg_size) {
- CWMP_LOG(ERROR, "error reading netlink message");
- return;
- }
-
- if (!NLMSG_OK(nlh, msg_size)) {
- CWMP_LOG(ERROR, "netlink message is not NLMSG_OK");
- return;
- }
-
- if (nlh->nlmsg_type == RTM_NEWADDR)
- freecwmp_netlink_interface(nlh);
-
- msg_size -= NLMSG_ALIGN(len);
- nlh = (struct nlmsghdr *)((char *)nlh + NLMSG_ALIGN(len));
- }
-}
-
-int netlink_init_v6(void)
-{
- struct {
- struct nlmsghdr hdr;
- struct ifaddrmsg msg;
- } req;
- struct sockaddr_nl addr;
- int sock[2];
-
- memset(&addr, 0, sizeof(addr));
- memset(&req, 0, sizeof(req));
-
- if ((sock[0] = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) {
- CWMP_LOG(ERROR, "couldn't open NETLINK_ROUTE socket");
- return -1;
- }
-
- addr.nl_family = AF_NETLINK;
- addr.nl_groups = RTMGRP_IPV6_IFADDR;
- if ((bind(sock[0], (struct sockaddr *)&addr, sizeof(addr))) == -1) {
- CWMP_LOG(ERROR, "couldn't bind netlink socket");
- return -1;
- }
-
- netlink_event_v6.fd = sock[0];
- uloop_fd_add(&netlink_event_v6, ULOOP_READ | ULOOP_EDGE_TRIGGER);
-
- if ((sock[1] = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) == -1) {
- CWMP_LOG(ERROR, "couldn't open NETLINK_ROUTE socket");
- return -1;
- }
-
- req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
- req.hdr.nlmsg_type = RTM_GETADDR;
- req.msg.ifa_family = AF_INET6;
-
- if ((send(sock[1], &req, req.hdr.nlmsg_len, 0)) == -1) {
- CWMP_LOG(ERROR, "couldn't send netlink socket");
- return -1;
- }
-
- struct uloop_fd dummy_event = {.fd = sock[1] };
- netlink_new_msg(&dummy_event, 0);
-
- return 0;
-}
-
-int netlink_init(void)
-{
- struct {
- struct nlmsghdr hdr;
- struct ifaddrmsg msg;
- } req;
- struct sockaddr_nl addr;
- int sock[2];
-
- memset(&addr, 0, sizeof(addr));
- memset(&req, 0, sizeof(req));
-
- if ((sock[0] = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) {
- CWMP_LOG(ERROR, "couldn't open NETLINK_ROUTE socket");
- return -1;
- }
-
- addr.nl_family = AF_NETLINK;
- addr.nl_groups = RTMGRP_IPV4_IFADDR;
- if ((bind(sock[0], (struct sockaddr *)&addr, sizeof(addr))) == -1) {
- CWMP_LOG(ERROR, "couldn't bind netlink socket");
- return -1;
- }
-
- netlink_event.fd = sock[0];
- uloop_fd_add(&netlink_event, ULOOP_READ | ULOOP_EDGE_TRIGGER);
-
- if ((sock[1] = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) == -1) {
- CWMP_LOG(ERROR, "couldn't open NETLINK_ROUTE socket");
- return -1;
- }
-
- req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
- req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
- req.hdr.nlmsg_type = RTM_GETADDR;
- req.msg.ifa_family = AF_INET;
-
- if ((send(sock[1], &req, req.hdr.nlmsg_len, 0)) == -1) {
- CWMP_LOG(ERROR, "couldn't send netlink socket");
- return -1;
- }
-
- struct uloop_fd dummy_event = {.fd = sock[1] };
- netlink_new_msg(&dummy_event, 0);
-
- return 0;
-}
diff --git a/rpc_soap.c b/rpc_soap.c
deleted file mode 100755
index d3cfaa2..0000000
--- a/rpc_soap.c
+++ /dev/null
@@ -1,2852 +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-2021 iopsys Software Solutions AB
- * Author Mohamed Kallel
- * Author Ahmed Zribi
- * Author Omar Kallel
- *
- * Copyright (C) 2011-2012 Luka Perkov
- * Copyright (C) 2012 Jonas Gorski
- */
-
-#include "rpc_soap.h"
-#include "download.h"
-#include "cwmp_du_state.h"
-#include "log.h"
-#include "event.h"
-#include "datamodel_interface.h"
-#include "event.h"
-#include "xml.h"
-#include "backupSession.h"
-#include "notifications.h"
-#include "upload.h"
-#include "sched_inform.h"
-#include "diagnostic.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 DM_CONN_REQ_URL "Device.ManagementServer.ConnectionRequestURL"
-
-struct cwmp_namespaces ns;
-const struct rpc_cpe_method rpc_cpe_methods[] = { [RPC_CPE_GET_RPC_METHODS] = { "GetRPCMethods", cwmp_handle_rpc_cpe_get_rpc_methods, AMD_1 },
- [RPC_CPE_SET_PARAMETER_VALUES] = { "SetParameterValues", cwmp_handle_rpc_cpe_set_parameter_values, AMD_1 },
- [RPC_CPE_GET_PARAMETER_VALUES] = { "GetParameterValues", cwmp_handle_rpc_cpe_get_parameter_values, AMD_1 },
- [RPC_CPE_GET_PARAMETER_NAMES] = { "GetParameterNames", cwmp_handle_rpc_cpe_get_parameter_names, AMD_1 },
- [RPC_CPE_SET_PARAMETER_ATTRIBUTES] = { "SetParameterAttributes", cwmp_handle_rpc_cpe_set_parameter_attributes, AMD_1 },
- [RPC_CPE_GET_PARAMETER_ATTRIBUTES] = { "GetParameterAttributes", cwmp_handle_rpc_cpe_get_parameter_attributes, AMD_1 },
- [RPC_CPE_ADD_OBJECT] = { "AddObject", cwmp_handle_rpc_cpe_add_object, AMD_1 },
- [RPC_CPE_DELETE_OBJECT] = { "DeleteObject", cwmp_handle_rpc_cpe_delete_object, AMD_1 },
- [RPC_CPE_REBOOT] = { "Reboot", cwmp_handle_rpc_cpe_reboot, AMD_1 },
- [RPC_CPE_DOWNLOAD] = { "Download", cwmp_handle_rpc_cpe_download, AMD_1 },
- [RPC_CPE_UPLOAD] = { "Upload", cwmp_handle_rpc_cpe_upload, AMD_1 },
- [RPC_CPE_FACTORY_RESET] = { "FactoryReset", cwmp_handle_rpc_cpe_factory_reset, AMD_1 },
- [RPC_CPE_CANCEL_TRANSFER] = { "CancelTransfer", cwmp_handle_rpc_cpe_cancel_transfer, AMD_3 },
- [RPC_CPE_SCHEDULE_INFORM] = { "ScheduleInform", cwmp_handle_rpc_cpe_schedule_inform, AMD_1 },
- [RPC_CPE_SCHEDULE_DOWNLOAD] = { "ScheduleDownload", cwmp_handle_rpc_cpe_schedule_download, AMD_3 },
- [RPC_CPE_CHANGE_DU_STATE] = { "ChangeDUState", cwmp_handle_rpc_cpe_change_du_state, AMD_3 },
- [RPC_CPE_X_FACTORY_RESET_SOFT] = { "X_FactoryResetSoft", cwmp_handle_rpc_cpe_x_factory_reset_soft, AMD_1 },
- [RPC_CPE_FAULT] = { "Fault", cwmp_handle_rpc_cpe_fault, AMD_1 } };
-
-struct rpc_acs_method rpc_acs_methods[] = { [RPC_ACS_INFORM] = { "Inform", cwmp_rpc_acs_prepare_message_inform, cwmp_rpc_acs_parse_response_inform, cwmp_rpc_acs_destroy_data_inform, NOT_KNOWN },
- [RPC_ACS_GET_RPC_METHODS] = { "GetRPCMethods", cwmp_rpc_acs_prepare_get_rpc_methods, cwmp_rpc_acs_parse_response_get_rpc_methods, NULL, NOT_KNOWN },
- [RPC_ACS_TRANSFER_COMPLETE] = { "TransferComplete", cwmp_rpc_acs_prepare_transfer_complete, NULL, cwmp_rpc_acs_destroy_data_transfer_complete, NOT_KNOWN },
- [RPC_ACS_DU_STATE_CHANGE_COMPLETE] = { "DUStateChangeComplete", cwmp_rpc_acs_prepare_du_state_change_complete, NULL, cwmp_rpc_acs_destroy_data_du_state_change_complete, NOT_KNOWN }
-};
-
-char *custom_forced_inform_parameters[MAX_NBRE_CUSTOM_INFORM] = { 0 };
-char *boot_inform_parameters[MAX_NBRE_CUSTOM_INFORM] = { 0 };
-int nbre_custom_inform = 0;
-int nbre_boot_inform = 0;
-char *forced_inform_parameters[] = {
- "Device.RootDataModelVersion",
- "Device.DeviceInfo.HardwareVersion",
- "Device.DeviceInfo.SoftwareVersion",
- "Device.DeviceInfo.ProvisioningCode",
- "Device.ManagementServer.ParameterKey",
- DM_CONN_REQ_URL,
- "Device.ManagementServer.AliasBasedAddressing"
-};
-
-int xml_handle_message(struct session *session)
-{
- struct rpc *rpc_cpe;
- char *c;
- int i;
- mxml_node_t *b;
- struct cwmp *cwmp = &cwmp_main;
- struct config *conf;
- conf = &(cwmp->conf);
-
- /* get method */
- if (icwmp_asprintf(&c, "%s:%s", ns.soap_env, "Body") == -1) {
- CWMP_LOG(INFO, "Internal error");
- session->fault_code = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
- b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
-
- if (!b) {
- CWMP_LOG(INFO, "Invalid received message");
- session->fault_code = FAULT_CPE_REQUEST_DENIED;
- goto fault;
- }
- session->body_in = b;
-
- while (1) {
- b = mxmlWalkNext(b, session->body_in, MXML_DESCEND_FIRST);
- if (!b)
- goto error;
- if (mxmlGetType(b) == MXML_ELEMENT)
- break;
- }
-
- c = (char *)mxmlGetElement(b);
- /* convert QName to localPart, check that ns is the expected one */
- if (strchr(c, ':')) {
- char *tmp = strchr(c, ':');
- size_t ns_len = tmp - c;
-
- if (strlen(ns.cwmp) != ns_len) {
- CWMP_LOG(INFO, "Invalid received message");
- session->fault_code = FAULT_CPE_REQUEST_DENIED;
- goto fault;
- }
-
- if (strncmp(ns.cwmp, c, ns_len)) {
- CWMP_LOG(INFO, "Invalid received message");
- session->fault_code = FAULT_CPE_REQUEST_DENIED;
- goto fault;
- }
-
- c = tmp + 1;
- } else {
- CWMP_LOG(INFO, "Invalid received message");
- session->fault_code = FAULT_CPE_REQUEST_DENIED;
- goto fault;
- }
- CWMP_LOG(INFO, "SOAP RPC message: %s", c);
- rpc_cpe = NULL;
- for (i = 1; i < __RPC_CPE_MAX; i++) {
- if (i != RPC_CPE_FAULT && strcmp(c, rpc_cpe_methods[i].name) == 0 && rpc_cpe_methods[i].amd <= conf->supported_amd_version) {
- CWMP_LOG(INFO, "%s RPC is supported", c);
- rpc_cpe = cwmp_add_session_rpc_cpe(session, i);
- if (rpc_cpe == NULL)
- goto error;
- break;
- }
- }
- if (!rpc_cpe) {
- CWMP_LOG(INFO, "%s RPC is not supported", c);
- session->fault_code = FAULT_CPE_METHOD_NOT_SUPPORTED;
- goto fault;
- }
- return 0;
-fault:
- rpc_cpe = cwmp_add_session_rpc_cpe(session, RPC_CPE_FAULT);
- if (rpc_cpe == NULL)
- goto error;
- return 0;
-error:
- return -1;
-}
-
-/*
- * [RPC ACS]: Inform
- */
-
-static int xml_prepare_events_inform(mxml_node_t *b1, struct session *session)
-{
- mxml_node_t *node, *b2;
- char c[128];
- unsigned int n = 0;
- struct list_head *ilist;
- struct event_container *event_container;
- struct cwmp *cwmp = &cwmp_main;
-
- if (!b1)
- return -1;
-
- list_for_each (ilist, &(session->head_event_container)) {
- event_container = list_entry(ilist, struct event_container, list);
- node = mxmlNewElement(b1, "EventStruct");
- if (!node)
- goto error;
- b2 = mxmlNewElement(node, "EventCode");
- if (!b2)
- goto error;
- if (event_container->code == EVENT_IDX_0BOOTSTRAP || event_container->code == EVENT_IDX_1BOOT)
- cwmp->is_boot = true;
- b2 = mxmlNewOpaque(b2, EVENT_CONST[event_container->code].CODE);
- if (!b2)
- goto error;
- b2 = mxmlNewElement(node, "CommandKey");
- if (!b2)
- goto error;
- if (event_container->command_key) {
- b2 = mxmlNewOpaque(b2, event_container->command_key);
- if (!b2)
- goto error;
- }
- mxmlAdd(b1, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
- n++;
- }
- if (n) {
- if (snprintf(c, sizeof(c), "cwmp:EventStruct[%u]", n) == -1)
- return -1;
- mxmlElementSetAttr(b1, "xsi:type", "soap_enc:Array");
- mxmlElementSetAttr(b1, "soap_enc:arrayType", c);
- }
- return 0;
-
-error:
- return -1;
-}
-
-static int xml_prepare_parameters_inform(struct cwmp_dm_parameter *dm_parameter, mxml_node_t *parameter_list, int *size)
-{
- mxml_node_t *node, *b;
- b = mxmlFindElementOpaque(parameter_list, parameter_list, dm_parameter->name, MXML_DESCEND);
- if (b && dm_parameter->value != NULL) {
- node = mxmlGetParent(b);
- b = mxmlFindElement(node, node, "Value", NULL, NULL, MXML_DESCEND_FIRST);
- if (!b)
- return 0;
- mxml_node_t *c = mxmlGetFirstChild(b);
- if (c && strcmp(dm_parameter->value, mxmlGetOpaque(c)) == 0)
- return 0;
- mxmlDelete(b);
- (*size)--;
-
- goto create_value;
- } else if (dm_parameter->value == NULL)
- return 0;
- node = mxmlNewElement(parameter_list, "ParameterValueStruct");
- if (!node)
- return -1;
-
- b = mxmlNewElement(node, "Name");
- if (!b)
- return -1;
-
- b = mxmlNewOpaque(b, dm_parameter->name);
- if (!b)
- return -1;
-
-create_value:
- b = mxmlNewElement(node, "Value");
- if (!b)
- return -1;
-
-#ifdef ACS_MULTI
- mxmlElementSetAttr(b, "xsi:type", (dm_parameter->type && dm_parameter->type[0] != '\0') ? dm_parameter->type : "xsd:string");
-#endif
- b = mxmlNewOpaque(b, dm_parameter->value);
- if (!b)
- return -1;
-
- (*size)++;
- return 0;
-}
-
-static void load_inform_xml_schema(mxml_node_t **tree, struct cwmp *cwmp, struct session *session)
-{
- char declaration[1024] = {0};
-
- if (tree == NULL)
- return;
-
- *tree = NULL;
-
- snprintf(declaration, sizeof(declaration), "?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?");
- mxml_node_t *xml = mxmlNewElement(NULL, declaration);
- if (xml == NULL)
- return;
-
- mxml_node_t *envelope = mxmlNewElement(xml, "soap_env:Envelope");
- if (envelope == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- mxmlElementSetAttr(envelope, "xmlns:soap_env", "http://schemas.xmlsoap.org/soap/envelope/");
- mxmlElementSetAttr(envelope, "xmlns:soap_enc", "http://schemas.xmlsoap.org/soap/encoding/");
- mxmlElementSetAttr(envelope, "xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
- mxmlElementSetAttr(envelope, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
- mxmlElementSetAttr(envelope, "xmlns:cwmp", cwmp_urls[(cwmp->conf.supported_amd_version) - 1]);
-
- mxml_node_t *header = mxmlNewElement(envelope, "soap_env:Header");
- if (header == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *id = mxmlNewElement(header, "cwmp:ID");
- if (id == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- mxmlElementSetAttr(id, "soap_env:mustUnderstand", "1");
-
- mxml_node_t *node = NULL;
- if (cwmp->conf.supported_amd_version >= 4) {
- node = mxmlNewElement(header, "cwmp:SessionTimeout");
- if (!node) {
- MXML_DELETE(xml);
- return;
- }
-
- mxmlElementSetAttr(node, "soap_env:mustUnderstand", "0");
- node = mxmlNewInteger(node, cwmp->conf.session_timeout);
- if (!node) {
- MXML_DELETE(xml);
- return;
- }
- }
-
- if (cwmp->conf.supported_amd_version >= 5) {
- node = mxmlNewElement(header, "cwmp:SupportedCWMPVersions");
- if (!node) {
- MXML_DELETE(xml);
- return;
- }
-
- mxmlElementSetAttr(node, "soap_env:mustUnderstand", "0");
- node = mxmlNewOpaque(node, xml_get_cwmp_version(cwmp->conf.supported_amd_version));
- if (!node) {
- MXML_DELETE(xml);
- return;
- }
- }
-
- mxml_node_t *body = mxmlNewElement(envelope, "soap_env:Body");
- if (body == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *inform = mxmlNewElement(body, "cwmp:Inform");
- if (inform == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *dev_id = mxmlNewElement(inform, "DeviceId");
- if (dev_id == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *manufac = mxmlNewElement(dev_id, "Manufacturer");
- if (manufac == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- if (NULL == mxmlNewOpaque(manufac, cwmp->deviceid.manufacturer ? cwmp->deviceid.manufacturer : "")) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *oui = mxmlNewElement(dev_id, "OUI");
- if (oui == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- if (NULL == mxmlNewOpaque(oui, cwmp->deviceid.oui ? cwmp->deviceid.oui : "")) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *prod_class = mxmlNewElement(dev_id, "ProductClass");
- if (prod_class == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- if (NULL == mxmlNewOpaque(prod_class, cwmp->deviceid.productclass ? cwmp->deviceid.productclass : "")) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *sl_no = mxmlNewElement(dev_id, "SerialNumber");
- if (sl_no == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- if (NULL == mxmlNewOpaque(sl_no, cwmp->deviceid.serialnumber ? cwmp->deviceid.serialnumber : "")) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *event = mxmlNewElement(inform, "Event");
- if (event == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- mxmlElementSetAttr(event, "soap_enc:arrayType", "cwmp:EventStruct[0]");
-
- cwmp->is_boot = false;
- if (xml_prepare_events_inform(event, session)) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *max_env = mxmlNewElement(inform, "MaxEnvelopes");
- if (max_env == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- mxmlNewInteger(max_env, 1);
-
- mxml_node_t *curr_time = mxmlNewElement(inform, "CurrentTime");
- if (curr_time == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- if (NULL == mxmlNewOpaque(curr_time, get_time(time(NULL)))) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *retry_count = mxmlNewElement(inform, "RetryCount");
- if (retry_count == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- if (NULL == mxmlNewInteger(retry_count, cwmp->retry_count_session)) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *param_list = mxmlNewElement(inform, "ParameterList");
- if (param_list == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- mxmlElementSetAttr(param_list, "soap_enc:arrayType", "cwmp:ParameterValueStruct[0]");
-
- struct list_head *ilist, *jlist;
- struct cwmp_dm_parameter *dm_parameter;
- int size = 0;
-
- list_for_each (ilist, &(session->head_event_container)) {
- struct event_container *event_container = list_entry(ilist, struct event_container, list);
- list_for_each (jlist, &(event_container->head_dm_parameter)) {
- dm_parameter = list_entry(jlist, struct cwmp_dm_parameter, list);
- if (xml_prepare_parameters_inform(dm_parameter, param_list, &size)) {
- MXML_DELETE(xml);
- return;
- }
- }
- }
-
- size_t inform_parameters_nbre = sizeof(forced_inform_parameters) / sizeof(forced_inform_parameters[0]);
- size_t i;
- int j;
- struct cwmp_dm_parameter cwmp_dm_param = { 0 };
- LIST_HEAD(list_inform);
- for (i = 0; i < inform_parameters_nbre; i++) {
- char *fault = cwmp_get_single_parameter_value(forced_inform_parameters[i], &cwmp_dm_param);
- if (fault != NULL)
- continue;
-
- // An empty connection url cause CDR test to break
- if (strcmp(forced_inform_parameters[i], DM_CONN_REQ_URL) == 0 && cwmp_dm_param.value != NULL && strlen(cwmp_dm_param.value) == 0) {
- CWMP_LOG(ERROR, "# Empty CR URL[%s] value", forced_inform_parameters[i]);
- MXML_DELETE(xml);
- return;
- }
-
- if (xml_prepare_parameters_inform(&cwmp_dm_param, param_list, &size)) {
- MXML_DELETE(xml);
- return;
- }
- }
-
- for (j = 0; j < nbre_custom_inform; j++) {
- char *fault = cwmp_get_single_parameter_value(custom_forced_inform_parameters[j], &cwmp_dm_param);
- if (fault != NULL)
- continue;
- if (xml_prepare_parameters_inform(&cwmp_dm_param, param_list, &size)) {
- MXML_DELETE(xml);
- return;
- }
- }
-
- if (cwmp->is_boot == true) {
- for (j = 0; j < nbre_boot_inform; j++) {
- char *fault = cwmp_get_single_parameter_value(boot_inform_parameters[j], &cwmp_dm_param);
- if (fault != NULL)
- continue;
- if (xml_prepare_parameters_inform(&cwmp_dm_param, param_list, &size)) {
- MXML_DELETE(xml);
- return;
- }
- }
- }
-
- char c[256] = {0};
- if (snprintf(c, sizeof(c), "cwmp:ParameterValueStruct[%d]", size) == -1) {
- MXML_DELETE(xml);
- return;
- }
-
- mxmlElementSetAttr(param_list, "xsi:type", "soap_enc:Array");
- mxmlElementSetAttr(param_list, "soap_enc:arrayType", c);
-
- *tree = xml;
-}
-
-int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *session, struct rpc *this __attribute__((unused)))
-{
- mxml_node_t *tree;
-
- if (session == NULL)
- return -1;
-
- load_inform_xml_schema(&tree, cwmp, session);
-
- if (!tree)
- goto error;
-
- session->tree_out = tree;
-
- return 0;
-
-error:
- CWMP_LOG(ERROR, "Unable Prepare Message Inform", CWMP_BKP_FILE);
- return -1;
-}
-
-int cwmp_rpc_acs_parse_response_inform(struct cwmp *cwmp, struct session *session, struct rpc *this __attribute__((unused)))
-{
- mxml_node_t *tree, *b;
- int i = -1;
- char *c;
- const char *cwmp_urn;
-
- tree = session->tree_in;
- if (!tree)
- goto error;
- b = mxmlFindElement(tree, tree, "MaxEnvelopes", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto error;
- b = mxmlWalkNext(b, tree, MXML_DESCEND_FIRST);
- if (!b || mxmlGetType(b) != MXML_OPAQUE || !mxmlGetOpaque(b))
- goto error;
- if (cwmp->conf.supported_amd_version == 1) {
- cwmp->conf.amd_version = 1;
- return 0;
- }
- b = mxmlFindElement(tree, tree, "UseCWMPVersion", NULL, NULL, MXML_DESCEND);
- if (b && cwmp->conf.supported_amd_version >= 5) { //IF supported version !=5 acs response dosen't contain UseCWMPVersion
- b = mxmlWalkNext(b, tree, MXML_DESCEND_FIRST);
- if (!b || mxmlGetType(b) != MXML_OPAQUE || !mxmlGetOpaque(b))
- goto error;
- c = (char *) mxmlGetOpaque(b);
- if (c && *(c + 1) == '.') {
- c += 2;
- cwmp->conf.amd_version = atoi(c) + 1;
- return 0;
- }
- goto error;
- }
- for (i = 0; cwmp_urls[i] != NULL; i++) {
- cwmp_urn = cwmp_urls[i];
- c = (char *)xml__get_attribute_name_by_value(tree, cwmp_urn);
- if (c && *(c + 5) == ':') {
- break;
- }
- }
- if (i == 0) {
- cwmp->conf.amd_version = i + 1;
- } else if (i >= 1 && i <= 3) {
- switch (cwmp->conf.supported_amd_version) {
- case 1:
- cwmp->conf.amd_version = 1; //Already done
- break;
- case 2:
- case 3:
- case 4:
- //MIN ACS CPE
- if (cwmp->conf.supported_amd_version <= i + 1)
- cwmp->conf.amd_version = cwmp->conf.supported_amd_version;
- else
- cwmp->conf.amd_version = i + 1;
- break;
- //(cwmp->supported_conf.amd_version < i+1) ?"cwmp->conf.amd_version":"i+1";
- case 5:
- cwmp->conf.amd_version = i + 1;
- break;
- }
- } else if (i >= 4) {
- cwmp->conf.amd_version = cwmp->conf.supported_amd_version;
- }
- return 0;
-
-error:
- return -1;
-}
-
-int set_rpc_acs_to_supported(char *rpc_name)
-{
- int i;
-
- for (i=1; i < __RPC_ACS_MAX; i++) {
- if (strcmp(rpc_acs_methods[i].name, rpc_name) == 0) {
- rpc_acs_methods[i].acs_support = RPC_ACS_SUPPORT;
- return i;
- }
- }
- return -1;
-}
-
-void set_not_known_acs_support()
-{
- int i;
- for (i=1; i < __RPC_ACS_MAX; i++) {
- if ((i != RPC_ACS_INFORM) && (rpc_acs_methods[i].acs_support == NOT_KNOWN))
- rpc_acs_methods[i].acs_support = RPC_ACS_NOT_SUPPORT;
- }
-}
-
-int cwmp_rpc_acs_parse_response_get_rpc_methods(struct cwmp *cwmp __attribute__((unused)), struct session *session, struct rpc *this __attribute__((unused)))
-{
- mxml_node_t *tree, *b;
- tree = session->tree_in;
- b = mxmlFindElement(tree, tree, "cwmp:GetRPCMethodsResponse", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto error;
-
- while (b) {
- const char *node_opaque = mxmlGetOpaque(b);
- mxml_node_t *parent_node = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
-
- if (node_type == MXML_OPAQUE && mxmlGetType(parent_node) == MXML_ELEMENT && node_opaque && strcmp((char *) mxmlGetElement(parent_node), "string") == 0)
- set_rpc_acs_to_supported((char*)node_opaque);
-
- b = mxmlWalkNext(b, session->body_in, MXML_DESCEND);
- }
- set_not_known_acs_support();
- return 0;
-error:
- return -1;
-}
-
-int cwmp_rpc_acs_destroy_data_inform(struct session *session __attribute__((unused)), struct rpc *rpc __attribute__((unused)))
-{
- //event_remove_all_event_container(session,RPC_SEND);
- return 0;
-}
-
-/*
- * [RPC ACS]: GetRPCMethods
- */
-
-int cwmp_rpc_acs_prepare_get_rpc_methods(struct cwmp *cwmp, struct session *session, struct rpc *rpc __attribute__((unused)))
-{
- mxml_node_t *tree, *n;
-
- load_response_xml_schema(&tree);
- if (!tree)
- return -1;
-
- n = mxmlFindElement(tree, tree, "soap_env:Envelope", NULL, NULL, MXML_DESCEND);
- if (!n)
- return -1;
- mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp->conf.amd_version) - 1]);
- n = mxmlFindElement(tree, tree, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!n)
- return -1;
-
- n = mxmlNewElement(n, "cwmp:GetRPCMethods");
- if (!n)
- return -1;
-
- session->tree_out = tree;
-
- return 0;
-}
-
-/*
- * [RPC ACS]: TransferComplete
- */
-
-int cwmp_rpc_acs_prepare_transfer_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc)
-{
- mxml_node_t *tree, *n;
- struct transfer_complete *p;
-
- p = (struct transfer_complete *)rpc->extra_data;
- load_response_xml_schema(&tree);
- if (!tree)
- goto error;
-
- n = mxmlFindElement(tree, tree, "soap_env:Envelope", NULL, NULL, MXML_DESCEND);
- if (!n)
- goto error;
- mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp->conf.amd_version) - 1]);
-
- n = mxmlFindElement(tree, tree, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!n)
- goto error;
-
- n = mxmlNewElement(n, "cwmp:TransferComplete");
- if (!n)
- goto error;
-
- n = mxmlNewElement(n, "CommandKey");
- if (!n)
- goto error;
-
- n = mxmlNewOpaque(n, p->command_key ? p->command_key : "");
- if (!n)
- goto error;
-
- n = mxmlGetParent(n);
- if (n)
- n = mxmlGetParent(n);
-
- n = mxmlNewElement(n, "StartTime");
- if (!n)
- goto error;
-
- n = mxmlNewOpaque(n, p->start_time);
- if (!n)
- goto error;
-
- //n = n->parent->parent;
- n = mxmlGetParent(n);
- if (n)
- n = mxmlGetParent(n);
- n = mxmlNewElement(n, "CompleteTime");
- if (!n)
- goto error;
-
- n = mxmlNewOpaque(n, get_time(time(NULL)));
- if (!n)
- goto error;
-
- // n = n->parent->parent;
- n = mxmlGetParent(n);
- if (n)
- n = mxmlGetParent(n);
- n = mxmlNewElement(n, "FaultStruct");
- if (!n)
- goto error;
-
- n = mxmlNewElement(n, "FaultCode");
- if (!n)
- goto error;
-
- n = mxmlNewOpaque(n, p->fault_code ? FAULT_CPE_ARRAY[p->fault_code].CODE : "0");
- if (!n)
- goto error;
-
- // n = n->parent->parent;
- n = mxmlGetParent(n);
- if (n)
- n = mxmlGetParent(n);
- n = mxmlNewElement(n, "FaultString");
- if (!n)
- goto error;
-
- n = mxmlNewOpaque(n, p->fault_code ? FAULT_CPE_ARRAY[p->fault_code].DESCRIPTION : "");
- if (!n)
- goto error;
-
- session->tree_out = tree;
-
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * [RPC ACS]: DUStateChangeComplete
- */
-
-int cwmp_rpc_acs_prepare_du_state_change_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc)
-{
- mxml_node_t *tree, *n, *b, *t;
- struct du_state_change_complete *p;
- struct opresult *q;
- char *c;
-
- p = (struct du_state_change_complete *)rpc->extra_data;
- load_response_xml_schema(&tree);
- if (!tree)
- goto error;
-
- n = mxmlFindElement(tree, tree, "soap_env:Envelope", NULL, NULL, MXML_DESCEND);
- if (!n)
- goto error;
-
- mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp->conf.amd_version) - 1]);
- n = mxmlFindElement(tree, tree, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!n)
- goto error;
-
- n = mxmlNewElement(n, "cwmp:DUStateChangeComplete");
- if (!n)
- goto error;
-
- n = mxmlNewElement(n, "CommandKey");
- if (!n)
- goto error;
-
- n = mxmlNewOpaque(n, p->command_key);
- if (!n)
- goto error;
- // n = n->parent->parent;
- n = mxmlGetParent(n);
- if (n)
- n = mxmlGetParent(n);
- n = mxmlGetParent(n);
- if (n)
- n = mxmlGetParent(n);
- n = mxmlNewElement(n, "Results");
- if (!n)
- goto error;
-
- list_for_each_entry (q, &(p->list_opresult), list) {
- t = mxmlNewElement(n, "OpResultStruct");
- if (!t)
- goto error;
-
- b = mxmlNewElement(t, "UUID");
- if (!b)
- goto error;
-
- c = q->uuid ? strdup(q->uuid) : strdup("");
- b = mxmlNewOpaque(b, c);
- FREE(c);
- if (!b)
- goto error;
-
- b = mxmlNewElement(t, "DeploymentUnitRef");
- if (!b)
- goto error;
-
- c = q->du_ref ? strdup(q->du_ref) : strdup("");
- b = mxmlNewOpaque(b, c);
- FREE(c);
- if (!b)
- goto error;
-
- b = mxmlNewElement(t, "Version");
- if (!b)
- goto error;
-
- c = q->version ? strdup(q->version) : strdup("");
- b = mxmlNewOpaque(b, c);
- FREE(c);
- if (!b)
- goto error;
-
- b = mxmlNewElement(t, "CurrentState");
- if (!b)
- goto error;
-
- c = q->current_state ? strdup(q->current_state) : strdup("");
- b = mxmlNewOpaque(b, c);
- FREE(c);
- if (!b)
- goto error;
-
- b = mxmlNewElement(t, "StartTime");
- if (!b)
- goto error;
-
- c = q->start_time ? strdup(q->start_time) : strdup("");
- b = mxmlNewOpaque(b, c);
- FREE(c);
- if (!b)
- goto error;
-
- b = mxmlNewElement(t, "CompleteTime");
- if (!b)
- goto error;
-
- c = q->complete_time ? strdup(q->complete_time) : strdup("");
- b = mxmlNewOpaque(b, c);
- FREE(c);
- if (!b)
- goto error;
-
- b = mxmlNewElement(t, "FaultStruct");
- if (!b)
- goto error;
-
- b = mxmlNewElement(b, "FaultCode");
- if (!b)
- goto error;
-
- b = mxmlNewOpaque(b, q->fault ? FAULT_CPE_ARRAY[q->fault].CODE : "0");
- if (!b)
- goto error;
-
- // b = b->parent->parent;
- b = mxmlGetParent(b);
- if (b)
- b = mxmlGetParent(b);
- b = mxmlNewElement(b, "FaultString");
- if (!b)
- goto error;
-
- b = mxmlNewOpaque(b, q->fault ? FAULT_CPE_ARRAY[q->fault].DESCRIPTION : "");
- if (!b)
- goto error;
- }
- session->tree_out = tree;
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * [RPC CPE]: GetParameterValues
- */
-
-int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *n, *parameter_list, *b;
- char *parameter_name = NULL;
- int counter = 0, fault_code = FAULT_CPE_INTERNAL_ERROR;
-#ifdef ACS_MULTI
- char c[256] = {0};
-#endif
- LIST_HEAD(parameters_list);
-
- b = session->body_in;
- if (session->tree_out == NULL)
- goto fault;
-
- n = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!n)
- goto fault;
-
- n = mxmlNewElement(n, "cwmp:GetParameterValuesResponse");
- if (!n)
- goto fault;
-
- parameter_list = mxmlNewElement(n, "ParameterList");
- if (!parameter_list)
- goto fault;
-#ifdef ACS_MULTI
- mxmlElementSetAttr(parameter_list, "xsi:type", "soap_enc:Array");
-#endif
- while (b) {
- const char *node_value = mxmlGetOpaque(b);
- const char *node_name = (char *) mxmlGetElement(b);
- mxml_node_t *parent_node = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
- mxml_node_t *firstchild = mxmlGetFirstChild(b);
- if (node_type == MXML_OPAQUE && mxmlGetType(parent_node) == MXML_ELEMENT && node_value && !strcmp((char *) mxmlGetElement(parent_node), "string")) {
- parameter_name = icwmp_strdup(node_value);
- }
- if (node_type == MXML_ELEMENT && /* added in order to support GetParameterValues with empty string*/
- node_name != NULL && !strcmp(node_name, "string") && !firstchild) {
- parameter_name = icwmp_strdup("");
- }
- if (parameter_name) {
- char *err = cwmp_get_parameter_values(parameter_name, ¶meters_list);
- if (err && !is_obj_excluded(parameter_name)) {
- fault_code = cwmp_get_fault_code_by_string(err);
- goto fault;
- }
- struct cwmp_dm_parameter *param_value;
- list_for_each_entry (param_value, ¶meters_list, list) {
- n = mxmlNewElement(parameter_list, "ParameterValueStruct");
- if (!n)
- goto fault;
-
- n = mxmlNewElement(n, "Name");
- if (!n)
- goto fault;
-
- n = mxmlNewOpaque(n, param_value->name ? param_value->name : "");
- if (!n)
- goto fault;
-
- n = mxmlGetParent(n);
- if (!n)
- goto fault;
-
- n = mxmlGetParent(n);
- if (!n)
- goto fault;
-
- n = mxmlNewElement(n, "Value");
- if (!n)
- goto fault;
-
-#ifdef ACS_MULTI
- mxmlElementSetAttr(n, "xsi:type", param_value->type ? param_value->type : "");
-#endif
-
- n = mxmlNewOpaque(n, param_value->value ? param_value->value : "");
- if (!n)
- goto fault;
-
- counter++;
- }
- cwmp_free_all_dm_parameter_list(¶meters_list);
- parameter_name = NULL;
- }
- b = mxmlWalkNext(b, session->body_in, MXML_DESCEND);
- }
-
-#ifdef ACS_MULTI
- b = mxmlFindElement(session->tree_out, session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto fault;
-
- if (snprintf(c, sizeof(c), "cwmp:ParameterValueStruct[%d]", counter) == -1)
- goto fault;
-
- mxmlElementSetAttr(b, "soap_enc:arrayType", c);
-#endif
-
- return 0;
-
-fault:
- cwmp_free_all_dm_parameter_list(¶meters_list);
- if (cwmp_create_fault_message(session, rpc, fault_code))
- return -1;
- return 0;
-}
-
-/*
- * [RPC CPE]: GetParameterNames
- */
-int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *n, *parameter_list, *b = session->body_in;
- char *parameter_name = NULL;
- char *NextLevel = NULL;
- int counter = 0, fault_code = FAULT_CPE_INTERNAL_ERROR;
- LIST_HEAD(parameters_list);
-#ifdef ACS_MULTI
- char c[256] = {0};
-#endif
- if (session->tree_out == NULL)
- goto fault;
-
- n = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!n)
- goto fault;
-
- n = mxmlNewElement(n, "cwmp:GetParameterNamesResponse");
- if (!n)
- goto fault;
-
- parameter_list = mxmlNewElement(n, "ParameterList");
- if (!parameter_list)
- goto fault;
-
-#ifdef ACS_MULTI
- mxmlElementSetAttr(parameter_list, "xsi:type", "soap_enc:Array");
-#endif
-
- while (b) {
- const char *node_value = mxmlGetOpaque(b);
- const char *node_name = (char *) mxmlGetElement(b);
- mxml_node_t *parent = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
- mxml_node_t *firstchild = mxmlGetFirstChild(b);
-
- if (node_type == MXML_OPAQUE && node_value && mxmlGetType(parent) == MXML_ELEMENT && !strcmp((char *) mxmlGetElement(parent), "ParameterPath")) {
- parameter_name = icwmp_strdup(node_value);
- }
- if (node_type == MXML_ELEMENT && node_name && !strcmp(node_name, "ParameterPath") && !firstchild) {
- parameter_name = icwmp_strdup("");
- }
- if (node_type == MXML_OPAQUE && node_value && mxmlGetType(parent) == MXML_ELEMENT && !strcmp((char *) mxmlGetElement(parent), "NextLevel")) {
- NextLevel = icwmp_strdup(node_value);
- }
- b = mxmlWalkNext(b, session->body_in, MXML_DESCEND);
- }
-
- if (!icwmp_validate_boolean_value(NextLevel)) {
- fault_code = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
-
- if (parameter_name && NextLevel) {
- char *err = cwmp_get_parameter_names(parameter_name, strcmp(NextLevel, "true") == 0 || strcmp(NextLevel, "1") == 0 ? true : false, ¶meters_list);
- if (err && !is_obj_excluded(parameter_name)) {
- fault_code = cwmp_get_fault_code_by_string(err);
- goto fault;
- }
- parameter_name = NULL;
- NextLevel = NULL;
- }
- struct cwmp_dm_parameter *param_value;
- list_for_each_entry (param_value, ¶meters_list, list) {
- n = mxmlNewElement(parameter_list, "ParameterInfoStruct");
- if (!n)
- goto fault;
-
- n = mxmlNewElement(n, "Name");
- if (!n)
- goto fault;
-
- n = mxmlNewOpaque(n, param_value->name);
- if (!n)
- goto fault;
-
- n = mxmlGetParent(n);
- if (!n)
- goto fault;
-
- n = mxmlGetParent(n);
- if (!n)
- goto fault;
-
- n = mxmlNewElement(n, "Writable");
- if (!n)
- goto fault;
-
- n = mxmlNewOpaque(n, param_value->writable ? "1" : "0");
- if (!n)
- goto fault;
-
- counter++;
- }
- cwmp_free_all_dm_parameter_list(¶meters_list);
-#ifdef ACS_MULTI
- b = mxmlFindElement(session->tree_out, session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto fault;
-
- if (snprintf(c, sizeof(c), "cwmp:ParameterInfoStruct[%d]", counter) == -1)
- goto fault;
-
- mxmlElementSetAttr(b, "soap_enc:arrayType", c);
-#endif
- return 0;
-
-fault:
- cwmp_free_all_dm_parameter_list(¶meters_list);
- if (cwmp_create_fault_message(session, rpc, fault_code))
- return -1;
- return 0;
-}
-
-/*
- * [RPC CPE]: GetParameterAttributes
- */
-
-int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *n, *parameter_list, *b;
- char *parameter_name = NULL;
- int counter = 0, fault_code = FAULT_CPE_INTERNAL_ERROR;
- LIST_HEAD(parameters_list);
-#ifdef ACS_MULTI
- char c[256];
-#endif
- b = session->body_in;
- n = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!n)
- goto fault;
-
- n = mxmlNewElement(n, "cwmp:GetParameterAttributesResponse");
- if (!n)
- goto fault;
-
- parameter_list = mxmlNewElement(n, "ParameterList");
- if (!parameter_list)
- goto fault;
-
-#ifdef ACS_MULTI
- mxmlElementSetAttr(parameter_list, "xsi:type", "soap_enc:Array");
-#endif
-
- while (b) {
- const char *node_opaque = mxmlGetOpaque(b);
- const char *node_name = (char *) mxmlGetElement(b);
- mxml_node_t *parent = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
- mxml_node_t *firstchild = mxmlGetFirstChild(b);
-
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "string")) {
- parameter_name = icwmp_strdup(node_opaque);
- }
- if (node_type == MXML_ELEMENT && !strcmp(node_name, "string") && !firstchild) {
- parameter_name = icwmp_strdup("");
- }
- if (parameter_name) {
- char *err = cwmp_get_parameter_attributes(parameter_name, ¶meters_list);
- if (err && !is_obj_excluded(parameter_name)) {
- fault_code = cwmp_get_fault_code_by_string(err);
- goto fault;
- }
- struct cwmp_dm_parameter *param_value;
- list_for_each_entry (param_value, ¶meters_list, list) {
- n = mxmlNewElement(parameter_list, "ParameterAttributeStruct");
- if (!n)
- goto fault;
-
- n = mxmlNewElement(n, "Name");
- if (!n)
- goto fault;
-
- n = mxmlNewOpaque(n, param_value->name);
- if (!n)
- goto fault;
-
- n = mxmlGetParent(n);
- if (n)
- n = mxmlGetParent(n);
- n = mxmlNewElement(n, "Notification");
- if (!n)
- goto fault;
-
- char notification[2];
- snprintf(notification, sizeof(notification), "%d", param_value->notification);
- n = mxmlNewOpaque(n, notification);
- if (!n)
- goto fault;
-
- n = mxmlGetParent(n);
- if (n)
- n = mxmlGetParent(n);
- n = mxmlNewElement(n, "AccessList");
- if (!n)
- goto fault;
-
- n = mxmlNewOpaque(n, "");
- if (!n)
- goto fault;
-
- counter++;
- }
- cwmp_free_all_dm_parameter_list(¶meters_list);
- parameter_name = NULL;
- }
- b = mxmlWalkNext(b, session->body_in, MXML_DESCEND);
- }
-#ifdef ACS_MULTI
- b = mxmlFindElement(session->tree_out, session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto fault;
-
- if (snprintf(c, sizeof(c), "cwmp:ParameterAttributeStruct[%d]", counter) == -1)
- goto fault;
-
- mxmlElementSetAttr(b, "soap_enc:arrayType", c);
-#endif
- return 0;
-
-fault:
- cwmp_free_all_dm_parameter_list(¶meters_list);
- if (cwmp_create_fault_message(session, rpc, fault_code))
- return -1;
- return 0;
-}
-
-/*
- * [RPC CPE]: SetParameterValues
- */
-
-static int is_duplicated_parameter(mxml_node_t *param_node, struct session *session)
-{
- mxml_node_t *b = param_node;
- while ((b = mxmlWalkNext(b, session->body_in, MXML_DESCEND))) {
- const char *node_opaque = mxmlGetOpaque(b);
- mxml_node_t *parent = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
-
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "Name")) {
- if (strcmp(node_opaque, mxmlGetOpaque(param_node)) == 0)
- return -1;
- }
- }
- return 0;
-}
-
-int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *b = NULL;
- char *parameter_name = NULL;
- char *parameter_value = NULL;
- char *parameter_key = NULL;
- char *v, *c = NULL;
- int fault_code = FAULT_CPE_INTERNAL_ERROR, ret = 0;
-
- b = mxmlFindElement(session->body_in, session->body_in, "ParameterList", NULL, NULL, MXML_DESCEND);
- if (!b) {
- fault_code = FAULT_CPE_REQUEST_DENIED;
- goto fault;
- }
-
- LIST_HEAD(list_fault_param);
- rpc->list_set_value_fault = &list_fault_param;
- LIST_HEAD(list_set_param_value);
- while (b) {
- const char *node_opaque = mxmlGetOpaque(b);
- const char *node_name = (char *) mxmlGetElement(b);
- mxml_node_t *parent = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
- mxml_node_t *child = mxmlGetFirstChild(b);
-
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "Name")) {
- parameter_name = icwmp_strdup(node_opaque);
- if (is_duplicated_parameter(b, session)) {
- fault_code = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- }
-
- if (node_type == MXML_ELEMENT && !strcmp(node_name, "Name") && !child) {
- parameter_name = icwmp_strdup("");
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "Value")) {
- parameter_value = icwmp_strdup((char *)mxmlGetOpaque(b));
- while ((b = mxmlWalkNext(b, parent, MXML_DESCEND))) {
- v = (char *)mxmlGetOpaque(b);
- icwmp_asprintf(&c, "%s %s", parameter_value, v);
- parameter_value = icwmp_strdup(c);
- }
- b = mxmlGetLastChild(parent);
- }
- if (node_type == MXML_ELEMENT && !strcmp(node_name, "Value") && !child) {
- parameter_value = icwmp_strdup("");
- }
- if (parameter_name && parameter_value) {
- add_dm_parameter_to_list(&list_set_param_value, parameter_name, parameter_value, NULL, 0, false);
- parameter_name = NULL;
- parameter_value = NULL;
- }
- b = mxmlWalkNext(b, session->body_in, MXML_DESCEND);
- }
-
- b = mxmlFindElement(session->body_in, session->body_in, "ParameterKey", NULL, NULL, MXML_DESCEND);
- if (!b) {
- fault_code = FAULT_CPE_REQUEST_DENIED;
- goto fault;
- }
- b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST);
- if (b && mxmlGetType(b) == MXML_OPAQUE && mxmlGetOpaque(b))
- parameter_key = icwmp_strdup(mxmlGetOpaque(b));
-
- if (!icwmp_validate_string_length(parameter_key, 32)) {
- fault_code = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
-
- int flag = 0;
- if (transaction_id == 0) {
- if (!cwmp_transaction_start("cwmp"))
- goto fault;
- }
- fault_code = cwmp_set_multiple_parameters_values(&list_set_param_value, parameter_key ? parameter_key : "", &flag, rpc->list_set_value_fault);
- if (fault_code != FAULT_CPE_NO_FAULT)
- goto fault;
-
- struct cwmp_dm_parameter *param_value;
- list_for_each_entry (param_value, &list_set_param_value, list) {
- set_interface_reset_request(param_value->name, param_value->value);
- set_diagnostic_parameter_structure_value(param_value->name, param_value->value);
- }
-
- cwmp_free_all_dm_parameter_list(&list_set_param_value);
-
- b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto fault;
-
- b = mxmlNewElement(b, "cwmp:SetParameterValuesResponse");
- if (!b)
- goto fault;
-
- b = mxmlNewElement(b, "Status");
- if (!b)
- goto fault;
-
- b = mxmlNewOpaque(b, "1");
- if (!b)
- goto fault;
-
- if (!cwmp_transaction_commit())
- goto fault;
-
- cwmp_set_end_session(flag | END_SESSION_RESTART_SERVICES | END_SESSION_SET_NOTIFICATION_UPDATE | END_SESSION_RELOAD);
- return 0;
-
-fault:
- cwmp_free_all_dm_parameter_list(&list_set_param_value);
- if (cwmp_create_fault_message(session, rpc, fault_code))
- ret = CWMP_XML_ERR;
-
- cwmp_free_all_list_param_fault(rpc->list_set_value_fault);
- if (transaction_id) {
- cwmp_transaction_abort();
- transaction_id = 0;
- }
- return ret;
-}
-
-/*
- * [RPC CPE]: SetParameterAttributes
- */
-
-int cwmp_handle_rpc_cpe_set_parameter_attributes(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *n, *b = session->body_in;
- char *parameter_name = NULL, *parameter_notification = NULL;
- int fault_code = FAULT_CPE_INTERNAL_ERROR, ret = 0;
- char *notification_change = NULL;
- char c[256];
-
- /* handle cwmp:SetParameterAttributes */
- if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "SetParameterAttributes") == -1)
- goto fault;
-
- n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
-
- if (!n)
- goto fault;
- b = n;
-
- while (b) {
- const char *node_opaque = mxmlGetOpaque(b);
- const char *node_name = (char *) mxmlGetElement(b);
- mxml_node_t *parent = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
- mxml_node_t *child = mxmlGetFirstChild(b);
-
- if (node_type == MXML_ELEMENT && !strcmp(node_name, "SetParameterAttributesStruct")) {
- parameter_name = NULL;
- parameter_notification = NULL;
- notification_change = NULL;
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "Name")) {
- parameter_name = icwmp_strdup(node_opaque);
- }
- if (node_type == MXML_ELEMENT && !strcmp(node_name, "Name") && !child) {
- parameter_name = icwmp_strdup("");
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "NotificationChange")) {
- notification_change = icwmp_strdup(node_opaque);
- }
- if (node_type == MXML_ELEMENT && !strcmp(node_name, "NotificationChange") && !child) {
- notification_change = icwmp_strdup("");
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "Notification")) {
- parameter_notification = icwmp_strdup(node_opaque);
- }
- if (node_type == MXML_ELEMENT && !strcmp(node_name, "Notification") && !child) {
- parameter_notification = icwmp_strdup("");
- }
- if (parameter_name && parameter_notification && notification_change) {
- if (!icwmp_validate_boolean_value(notification_change)) {
- fault_code = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (!icwmp_validate_int_in_range(parameter_notification, 0, 6)) {
- fault_code = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- char *err = cwmp_set_parameter_attributes(parameter_name, atoi(parameter_notification));
- if (err) {
- fault_code = cwmp_get_fault_code_by_string(err);
- goto fault;
- }
- parameter_name = NULL;
- parameter_notification = NULL;
- notification_change = NULL;
- }
- b = mxmlWalkNext(b, n, MXML_DESCEND);
- }
-
- b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto fault;
-
- b = mxmlNewElement(b, "cwmp:SetParameterAttributesResponse");
- if (!b)
- goto fault;
-
- cwmp_set_end_session(END_SESSION_SET_NOTIFICATION_UPDATE | END_SESSION_RESTART_SERVICES | END_SESSION_INIT_NOTIFY);
- return 0;
-
-fault:
- if (cwmp_create_fault_message(session, rpc, fault_code))
- ret = CWMP_XML_ERR;
-
- return ret;
-}
-
-/*
- * [RPC CPE]: AddObject
- */
-
-int cwmp_handle_rpc_cpe_add_object(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *b;
- char *object_name = NULL;
- char *parameter_key = NULL;
- int fault_code = FAULT_CPE_INTERNAL_ERROR, ret = 0;
- char *instance = NULL;
-
- b = session->body_in;
- while (b) {
- const char *node_opaque = mxmlGetOpaque(b);
- mxml_node_t *parent = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
-
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "ParameterKey")) {
- parameter_key = icwmp_strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "ObjectName")) {
- object_name = icwmp_strdup(node_opaque);
- }
- b = mxmlWalkNext(b, session->body_in, MXML_DESCEND);
- }
-
- if (!icwmp_validate_string_length(parameter_key, 32)) {
- fault_code = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (transaction_id == 0) {
- if (!cwmp_transaction_start("cwmp"))
- goto fault;
- }
-
- if (object_name) {
- char *err = cwmp_add_object(object_name, parameter_key ? parameter_key : "", &instance);
- if (err) {
- fault_code = cwmp_get_fault_code_by_string(err);
- goto fault;
- }
-
- if (instance == NULL) {
- fault_code = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
- } else {
- fault_code = FAULT_CPE_INVALID_PARAMETER_NAME;
- goto fault;
- }
-
- b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto fault;
-
- b = mxmlNewElement(b, "cwmp:AddObjectResponse");
- if (!b)
- goto fault;
-
- b = mxmlNewElement(b, "InstanceNumber");
- if (!b)
- goto fault;
-
- b = mxmlNewOpaque(b, instance);
- if (!b)
- goto fault;
-
- b = mxmlGetParent(b);
- if (!b)
- goto fault;
-
- b = mxmlGetParent(b);
- if (!b)
- goto fault;
-
- b = mxmlNewElement(b, "Status");
- if (!b)
- goto fault;
-
- b = mxmlNewOpaque(b, "1");
- if (!b)
- goto fault;
-
- if (!cwmp_transaction_commit())
- goto fault;
-
- char *object_path = NULL;
- icwmp_asprintf(&object_path, "%s%s.", object_name, instance);
- cwmp_set_parameter_attributes(object_path, 0);
- FREE(instance);
- cwmp_set_end_session(END_SESSION_RESTART_SERVICES);
- return 0;
-
-fault:
- FREE(instance);
- if (cwmp_create_fault_message(session, rpc, fault_code))
- ret = CWMP_XML_ERR;
- if (transaction_id) {
- cwmp_transaction_abort();
- transaction_id = 0;
- }
- return ret;
-}
-
-/*
- * [RPC CPE]: DeleteObject
- */
-
-int cwmp_handle_rpc_cpe_delete_object(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *b;
- char *object_name = NULL;
- char *parameter_key = NULL;
- int fault_code = FAULT_CPE_INTERNAL_ERROR, ret = 0;
-
- b = session->body_in;
- while (b) {
- const char *node_opaque = mxmlGetOpaque(b);
- mxml_node_t *parent = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
-
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "ObjectName")) {
- object_name = icwmp_strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "ParameterKey")) {
- parameter_key = icwmp_strdup(node_opaque);
- }
- b = mxmlWalkNext(b, session->body_in, MXML_DESCEND);
- }
- if (!icwmp_validate_string_length(parameter_key, 32)) {
- fault_code = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (transaction_id == 0) {
- if (!cwmp_transaction_start("cwmp"))
- goto fault;
- }
- if (object_name) {
- char *err = cwmp_delete_object(object_name, parameter_key ? parameter_key : "");
- if (err) {
- fault_code = cwmp_get_fault_code_by_string(err);
- goto fault;
- }
- } else {
- fault_code = FAULT_CPE_INVALID_PARAMETER_NAME;
- goto fault;
- }
-
- b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto fault;
-
- b = mxmlNewElement(b, "cwmp:DeleteObjectResponse");
- if (!b)
- goto fault;
-
- b = mxmlNewElement(b, "Status");
- if (!b)
- goto fault;
-
- b = mxmlNewOpaque(b, "1");
- if (!b)
- goto fault;
-
- if (!cwmp_transaction_commit())
- goto fault;
-
- cwmp_set_end_session(END_SESSION_RESTART_SERVICES);
- return 0;
-
-fault:
- if (cwmp_create_fault_message(session, rpc, fault_code))
- ret = CWMP_XML_ERR;
- if (transaction_id) {
- cwmp_transaction_abort();
- transaction_id = 0;
- }
- return ret;
-}
-
-/*
- * [RPC CPE]: GetRPCMethods
- */
-
-int cwmp_handle_rpc_cpe_get_rpc_methods(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *n, *method_list;
- int i, counter = 0;
-#ifdef ACS_MULTI
- mxml_node_t *b = session->body_in;
- char c[128];
-#endif
-
- n = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!n)
- goto fault;
-
- n = mxmlNewElement(n, "cwmp:GetRPCMethodsResponse");
- if (!n)
- goto fault;
-
- method_list = mxmlNewElement(n, "MethodList");
- if (!method_list)
- goto fault;
-
- for (i = 1; i < __RPC_CPE_MAX; i++) {
- if (i != RPC_CPE_FAULT) {
- n = mxmlNewElement(method_list, "string");
- if (!n)
- goto fault;
-
- n = mxmlNewOpaque(n, rpc_cpe_methods[i].name);
- if (!n)
- goto fault;
-
- counter++;
- }
- }
-#ifdef ACS_MULTI
- b = mxmlFindElement(session->tree_out, session->tree_out, "MethodList", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto fault;
-
- mxmlElementSetAttr(b, "xsi:type", "soap_enc:Array");
- if (snprintf(c, sizeof(c), "xsd:string[%d]", counter) == -1)
- goto fault;
-
- mxmlElementSetAttr(b, "soap_enc:arrayType", c);
-#endif
-
- return 0;
-
-fault:
- if (cwmp_create_fault_message(session, rpc, FAULT_CPE_INTERNAL_ERROR))
- goto error;
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * [RPC CPE]: FactoryReset
- */
-
-int cwmp_handle_rpc_cpe_factory_reset(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *b;
-
- b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto fault;
-
- b = mxmlNewElement(b, "cwmp:FactoryResetResponse");
- if (!b)
- goto fault;
-
- cwmp_set_end_session(END_SESSION_FACTORY_RESET);
-
- return 0;
-
-fault:
- if (cwmp_create_fault_message(session, rpc, FAULT_CPE_INTERNAL_ERROR))
- goto error;
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * [RPC CPE]: X_FactoryResetSoft
- */
-
-int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *b;
-
- b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto fault;
-
- b = mxmlNewElement(b, "cwmp:X_FactoryResetSoftResponse");
- if (!b)
- goto fault;
-
- cwmp_set_end_session(END_SESSION_X_FACTORY_RESET_SOFT);
-
- return 0;
-
-fault:
- if (cwmp_create_fault_message(session, rpc, FAULT_CPE_INTERNAL_ERROR))
- goto error;
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * [RPC CPE]: CancelTransfer
- */
-
-int cwmp_handle_rpc_cpe_cancel_transfer(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *b;
- char *command_key = NULL;
- int fault_code = FAULT_CPE_INTERNAL_ERROR;
-
- b = session->body_in;
- while (b) {
- const char *node_opaque = mxmlGetOpaque(b);
- mxml_node_t *parent = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
-
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "CommandKey")) {
- command_key = icwmp_strdup(node_opaque);
- }
- b = mxmlWalkNext(b, session->body_in, MXML_DESCEND);
- }
- if (!icwmp_validate_string_length(command_key, 32)) {
- fault_code = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (command_key) {
- cancel_transfer(command_key);
- }
- b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto fault;
-
- b = mxmlNewElement(b, "cwmp:CancelTransferResponse");
- if (!b)
- goto fault;
- return 0;
-fault:
- if (cwmp_create_fault_message(session, rpc, fault_code))
- goto error;
- return 0;
-
-error:
- return -1;
-}
-
-int cancel_transfer(char *key)
-{
- struct list_head *ilist, *q;
-
- if (list_download.next != &(list_download)) {
- list_for_each_safe (ilist, q, &(list_download)) {
- struct download *pdownload = list_entry(ilist, struct download, list);
- if (strcmp(pdownload->command_key, key) == 0) {
- pthread_mutex_lock(&mutex_download);
- bkp_session_delete_download(pdownload);
- bkp_session_save();
- list_del(&(pdownload->list));
- if (pdownload->scheduled_time != 0)
- count_download_queue--;
- cwmp_free_download_request(pdownload);
- pthread_mutex_unlock(&mutex_download);
- }
- }
- }
- if (list_upload.next != &(list_upload)) {
- list_for_each_safe (ilist, q, &(list_upload)) {
- struct upload *pupload = list_entry(ilist, struct upload, list);
- if (strcmp(pupload->command_key, key) == 0) {
- pthread_mutex_lock(&mutex_upload);
- bkp_session_delete_upload(pupload);
- bkp_session_save();
- list_del(&(pupload->list));
- if (pupload->scheduled_time != 0)
- count_download_queue--;
- cwmp_free_upload_request(pupload);
- pthread_mutex_unlock(&mutex_upload);
- }
- }
- }
- // Cancel schedule download
- return CWMP_OK;
-}
-
-/*
- * [RPC CPE]: Reboot
- */
-
-int cwmp_handle_rpc_cpe_reboot(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *b;
- struct event_container *event_container;
- char *command_key = NULL;
- int fault_code = FAULT_CPE_INTERNAL_ERROR;
- b = session->body_in;
-
- while (b) {
- const char *node_opaque = mxmlGetOpaque(b);
- mxml_node_t *parent = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
-
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "CommandKey")) {
- command_key = icwmp_strdup(node_opaque);
- commandKey = icwmp_strdup(node_opaque);
- }
- b = mxmlWalkNext(b, session->body_in, MXML_DESCEND);
- }
- if (!icwmp_validate_string_length(commandKey, 32)) {
- fault_code = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- pthread_mutex_lock(&(cwmp_main.mutex_session_queue));
- event_container = cwmp_add_event_container(&cwmp_main, EVENT_IDX_M_Reboot, command_key);
- if (event_container == NULL) {
- pthread_mutex_unlock(&(cwmp_main.mutex_session_queue));
- goto fault;
- }
- cwmp_save_event_container(event_container);
- pthread_mutex_unlock(&(cwmp_main.mutex_session_queue));
-
- b = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!b)
- goto fault;
-
- b = mxmlNewElement(b, "cwmp:RebootResponse");
- if (!b)
- goto fault;
-
- cwmp_set_end_session(END_SESSION_REBOOT);
-
- return 0;
-
-fault:
- if (cwmp_create_fault_message(session, rpc, fault_code))
- goto error;
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * [RPC CPE]: ScheduleInform
- */
-
-int cwmp_handle_rpc_cpe_schedule_inform(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *n, *b = session->body_in;
- char *command_key = NULL;
- struct schedule_inform *schedule_inform;
- time_t scheduled_time;
- struct list_head *ilist;
- int fault = FAULT_CPE_NO_FAULT;
- int delay_seconds = 0;
-
- pthread_mutex_lock(&mutex_schedule_inform);
-
- while (b) {
- const char *node_opaque = mxmlGetOpaque(b);
- mxml_node_t *parent = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
-
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "CommandKey")) {
- command_key = icwmp_strdup(node_opaque);
- }
-
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "DelaySeconds")) {
- delay_seconds = atoi(node_opaque);
- }
- b = mxmlWalkNext(b, session->body_in, MXML_DESCEND);
- }
- if (!icwmp_validate_string_length(command_key, 32)) {
- fault = FAULT_CPE_INVALID_ARGUMENTS;
- pthread_mutex_unlock(&mutex_schedule_inform);
- goto fault;
- }
- if (delay_seconds <= 0) {
- fault = FAULT_CPE_INVALID_ARGUMENTS;
- pthread_mutex_unlock(&mutex_schedule_inform);
- goto fault;
- }
-
- if (count_schedule_inform_queue >= MAX_SCHEDULE_INFORM_QUEUE) {
- fault = FAULT_CPE_RESOURCES_EXCEEDED;
- pthread_mutex_unlock(&mutex_schedule_inform);
- goto fault;
- }
- count_schedule_inform_queue++;
-
- scheduled_time = time(NULL) + delay_seconds;
- list_for_each (ilist, &(list_schedule_inform)) {
- schedule_inform = list_entry(ilist, struct schedule_inform, list);
- if (schedule_inform->scheduled_time >= scheduled_time) {
- break;
- }
- }
-
- n = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!n)
- goto fault;
-
- n = mxmlNewElement(n, "cwmp:ScheduleInformResponse");
- if (!n)
- goto fault;
-
- CWMP_LOG(INFO, "Schedule inform event will start in %us", delay_seconds);
- schedule_inform = calloc(1, sizeof(struct schedule_inform));
- if (schedule_inform == NULL) {
- pthread_mutex_unlock(&mutex_schedule_inform);
- goto fault;
- }
- schedule_inform->commandKey = strdup(command_key);
- schedule_inform->scheduled_time = scheduled_time;
- list_add(&(schedule_inform->list), ilist->prev);
- bkp_session_insert_schedule_inform(schedule_inform->scheduled_time, schedule_inform->commandKey);
- bkp_session_save();
- pthread_mutex_unlock(&mutex_schedule_inform);
- pthread_cond_signal(&threshold_schedule_inform);
-
-success:
- return 0;
-
-fault:
- if (cwmp_create_fault_message(session, rpc, fault ? fault : FAULT_CPE_INTERNAL_ERROR))
- goto error;
- goto success;
-
-error:
- return -1;
-}
-
-/*
- * [RPC CPE]: ChangeDuState
- */
-int cwmp_handle_rpc_cpe_change_du_state(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *n, *t, *b = session->body_in;
- struct change_du_state *change_du_state = NULL;
- struct operations *elem = NULL;
- int error = FAULT_CPE_NO_FAULT;
- char c[256];
-
- if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "ChangeDUState") == -1) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
-
- n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
-
- if (!n)
- return -1;
- b = n;
-
- change_du_state = calloc(1, sizeof(struct change_du_state));
- if (change_du_state == NULL) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
-
- INIT_LIST_HEAD(&(change_du_state->list_operation));
- change_du_state->timeout = time(NULL);
-
- while (b) {
- const char *node_opaque = mxmlGetOpaque(b);
- const char *node_name = (char *) mxmlGetElement(b);
- mxml_type_t node_type = mxmlGetType(b);
- mxml_node_t *parent = mxmlGetParent(b);
- t = b;
- if (node_type == MXML_ELEMENT && strcmp(node_name, "Operations") == 0) {
- char *operation = (char *)mxmlElementGetAttr(b, "xsi:type");
- if (!strcmp(operation, "cwmp:InstallOpStruct")) {
- elem = (operations *)calloc(1, sizeof(operations));
- elem->type = DU_INSTALL;
- list_add_tail(&(elem->list), &(change_du_state->list_operation));
- t = mxmlWalkNext(t, b, MXML_DESCEND);
- while (t) {
- const char *opaque = mxmlGetOpaque(t);
- mxml_node_t *prt = mxmlGetParent(t);
- mxml_type_t type = mxmlGetType(t);
-
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "URL")) {
- elem->url = strdup(opaque);
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "UUID")) {
- elem->uuid = strdup(opaque);
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "Username")) {
- elem->username = strdup(opaque);
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "Password")) {
- elem->password = strdup(opaque);
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "ExecutionEnvRef")) {
- elem->executionenvref = strdup(opaque);
- }
- t = mxmlWalkNext(t, b, MXML_DESCEND);
- }
- } else if (!strcmp(operation, "cwmp:UpdateOpStruct")) {
- elem = (operations *)calloc(1, sizeof(operations));
- elem->type = DU_UPDATE;
- list_add_tail(&(elem->list), &(change_du_state->list_operation));
- t = mxmlWalkNext(t, b, MXML_DESCEND);
- while (t) {
- const char *opaque = mxmlGetOpaque(t);
- mxml_node_t *prt = mxmlGetParent(t);
- mxml_type_t type = mxmlGetType(t);
-
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "Username")) {
- elem->url = strdup(opaque);
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "Version")) {
- elem->uuid = strdup(opaque);
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "URL")) {
- elem->username = strdup(opaque);
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "Password")) {
- elem->password = strdup(opaque);
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "UUID")) {
- elem->executionenvref = strdup(opaque);
- }
-
- t = mxmlWalkNext(t, b, MXML_DESCEND);
- }
- } else if (!strcmp(operation, "cwmp:UninstallOpStruct")) {
- elem = (operations *)calloc(1, sizeof(operations));
- elem->type = DU_UNINSTALL;
- list_add_tail(&(elem->list), &(change_du_state->list_operation));
- t = mxmlWalkNext(t, b, MXML_DESCEND);
- while (t) {
- const char *opaque = mxmlGetOpaque(t);
- mxml_node_t *prt = mxmlGetParent(t);
- mxml_type_t type = mxmlGetType(t);
-
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "Version")) {
- elem->url = strdup(opaque);
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "ExecutionEnvRef")) {
- elem->uuid = strdup(opaque);
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "URL")) {
- elem->username = strdup(opaque);
- }
-
- t = mxmlWalkNext(t, b, MXML_DESCEND);
- }
- }
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "CommandKey")) {
- change_du_state->command_key = strdup(node_opaque);
- }
- b = mxmlWalkNext(b, n, MXML_DESCEND);
- }
- if (!icwmp_validate_string_length(change_du_state->command_key, 32)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- t = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!t)
- goto fault;
-
- t = mxmlNewElement(t, "cwmp:ChangeDUStateResponse");
- if (!t)
- goto fault;
-
- if (error == FAULT_CPE_NO_FAULT) {
- pthread_mutex_lock(&mutex_change_du_state);
- list_add_tail(&(change_du_state->list), &(list_change_du_state));
- bkp_session_insert_change_du_state(change_du_state);
- bkp_session_save();
- pthread_mutex_unlock(&mutex_change_du_state);
- pthread_cond_signal(&threshold_change_du_state);
- }
- return 0;
-
-fault:
- cwmp_free_change_du_state_request(change_du_state);
- if (cwmp_create_fault_message(session, rpc, error))
- goto error;
- return 0;
-
-error:
- return -1;
-}
-
-int create_download_upload_response(mxml_node_t *tree_out, enum load_type ltype)
-{
- mxml_node_t *t, *b;
- t = mxmlFindElement(tree_out, tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!t)
- return -1;
-
- t = mxmlNewElement(t, ltype == TYPE_DOWNLOAD ? "cwmp:DownloadResponse" : "cwmp:UploadResponse");
- if (!t)
- return -1;
-
- b = mxmlNewElement(t, "Status");
- if (!b)
- return -1;
-
- b = mxmlNewOpaque(b, "1");
- if (!b)
- return -1;
-
- b = mxmlGetParent(b);
- if (b)
- b = mxmlGetParent(b);
-
- b = mxmlNewElement(t, "StartTime");
- if (!b)
- return -1;
-
- b = mxmlNewOpaque(b, "0001-01-01T00:00:00+00:00");
- if (!b)
- return -1;
-
- b = mxmlGetParent(mxmlGetParent(b));
- b = mxmlNewElement(t, "CompleteTime");
- if (!b)
- return -1;
-
- b = mxmlNewOpaque(b, "0001-01-01T00:00:00+00:00");
- if (!b)
- return -1;
-
- return FAULT_CPE_NO_FAULT;
-}
-
-/*
- * [RPC CPE]: Download
- */
-int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *n, *b = session->body_in;
- char c[256], *tmp, *file_type = NULL;
- int error = FAULT_CPE_NO_FAULT;
- struct download *download = NULL, *idownload;
- struct list_head *ilist;
- time_t scheduled_time = 0;
- time_t download_delay = 0;
- char *str_file_size = NULL, *str_download_delay = NULL;
-
- if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "Download") == -1) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
-
- n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
-
- if (!n)
- return -1;
- b = n;
-
- download = calloc(1, sizeof(struct download));
- if (download == NULL) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
-
- while (b != NULL) {
- const char *node_opaque = mxmlGetOpaque(b);
- mxml_node_t *parent = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
-
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "CommandKey")) {
- download->command_key = strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "FileType")) {
- if (download->file_type == NULL) {
- download->file_type = strdup(node_opaque);
- file_type = icwmp_strdup(node_opaque);
- } else {
- tmp = file_type;
- if (cwmp_asprintf(&file_type, "%s %s", tmp, node_opaque) == -1) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
- }
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "URL")) {
- download->url = strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "Username")) {
- download->username = strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "Password")) {
- download->password = strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "FileSize")) {
- str_file_size = strdup(node_opaque ? node_opaque: "0");
- download->file_size = atoi(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "DelaySeconds")) {
- str_download_delay = strdup(node_opaque ? node_opaque: "0");
- download_delay = atol(node_opaque);
- }
- b = mxmlWalkNext(b, n, MXML_DESCEND);
- }
- if (!icwmp_validate_string_length(download->command_key, 32)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (!icwmp_validate_string_length(download->url, 256)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (!icwmp_validate_string_length(download->username, 256)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (!icwmp_validate_string_length(download->password, 256)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (!icwmp_validate_unsignedint(str_file_size)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- FREE(str_file_size);
- goto fault;
- }
- FREE(str_file_size);
- if (!icwmp_validate_unsignedint(str_download_delay)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- FREE(str_download_delay);
- goto fault;
- }
- FREE(str_download_delay);
-
- if (strcmp(file_type, FIRMWARE_UPGRADE_IMAGE_FILE_TYPE) && strcmp(file_type, WEB_CONTENT_FILE_TYPE) && strcmp(file_type, VENDOR_CONFIG_FILE_TYPE) && strcmp(file_type, TONE_FILE_TYPE) && strcmp(file_type, RINGER_FILE_TYPE) && strcmp(file_type, STORED_FIRMWARE_IMAGE_FILE_TYPE)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- } else if (count_download_queue >= MAX_DOWNLOAD_QUEUE) {
- error = FAULT_CPE_RESOURCES_EXCEEDED;
- } else if (download->url == NULL || (strcmp(download->url, "") == 0)) {
- error = FAULT_CPE_REQUEST_DENIED;
- } else if (strstr(download->url, "@") != NULL) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- } else if (strncmp(download->url, DOWNLOAD_PROTOCOL_HTTP, strlen(DOWNLOAD_PROTOCOL_HTTP)) != 0 && strncmp(download->url, DOWNLOAD_PROTOCOL_HTTPS, strlen(DOWNLOAD_PROTOCOL_HTTPS)) != 0 && strncmp(download->url, DOWNLOAD_PROTOCOL_FTP, strlen(DOWNLOAD_PROTOCOL_FTP)) != 0) {
- error = FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL;
- }
- if (error != FAULT_CPE_NO_FAULT)
- goto fault;
-
- if (create_download_upload_response(session->tree_out, TYPE_DOWNLOAD) != FAULT_CPE_NO_FAULT) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
-
- if (error == FAULT_CPE_NO_FAULT) {
- pthread_mutex_lock(&mutex_download);
- if (download_delay != 0)
- scheduled_time = time(NULL) + download_delay + PROCESSING_DELAY;
-
- list_for_each (ilist, &(list_download)) {
- idownload = list_entry(ilist, struct download, list);
- if (idownload->scheduled_time >= scheduled_time) {
- break;
- }
- }
- list_add(&(download->list), ilist->prev);
- if (download_delay != 0) {
- count_download_queue++;
- download->scheduled_time = scheduled_time;
- }
- bkp_session_insert_download(download);
- bkp_session_save();
- if (download_delay != 0) {
- CWMP_LOG(INFO, "Download will start in %us", download_delay);
- } else {
- CWMP_LOG(INFO, "Download will start at the end of session");
- }
-
- pthread_mutex_unlock(&mutex_download);
- pthread_cond_signal(&threshold_download);
- }
-
- return 0;
-
-fault:
- cwmp_free_download_request(download);
- if (cwmp_create_fault_message(session, rpc, error))
- return -1;
- return 0;
-}
-
-/*
- * [RPC CPE]: ScheduleDownload
- */
-int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *n, *t, *b = session->body_in;
- char c[256], *tmp, *file_type = NULL;
- char *windowmode0 = NULL, *windowmode1 = NULL, *str_file_size = NULL;
- int i = 0, j = 0;
- int error = FAULT_CPE_NO_FAULT;
- struct download *schedule_download = NULL;
- time_t schedule_download_delay[4] = { 0, 0, 0, 0 };
-
- if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "ScheduleDownload") == -1) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
-
- n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
-
- if (!n)
- return -1;
- b = n;
-
- schedule_download = calloc(1, sizeof(struct download));
- if (schedule_download == NULL) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
-
- while (b != NULL) {
- const char *node_opaque = mxmlGetOpaque(b);
- mxml_node_t *parent = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
- t = b;
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "CommandKey")) {
- schedule_download->command_key = strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "FileType")) {
- if (schedule_download->file_type != NULL) {
- tmp = file_type;
- if (cwmp_asprintf(&file_type, "%s %s", tmp, node_opaque) == -1) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
- } else {
- schedule_download->file_type = strdup(node_opaque);
- file_type = icwmp_strdup(node_opaque);
- }
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "URL")) {
- schedule_download->url = strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "Username")) {
- schedule_download->username = strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "Password")) {
- schedule_download->password = strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "FileSize")) {
- str_file_size = strdup(node_opaque);
- schedule_download->file_size = atoi(node_opaque);
- }
- if (node_type== MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "TimeWindowList")) {
- if (!t)
- return -1; //TO CHECK*/
- t = mxmlWalkNext(t, b, MXML_DESCEND);
- while (t) {
- const char *opaque = mxmlGetOpaque(t);
- mxml_node_t *prt = mxmlGetParent(t);
- mxml_type_t type = mxmlGetType(t);
-
- if (type == MXML_OPAQUE && node_opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "WindowStart")) {
- schedule_download_delay[j] = atol(opaque);
- j++;
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "WindowEnd")) {
- schedule_download_delay[j] = atol(opaque);
- j++;
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "WindowMode")) {
- if (schedule_download->timewindowstruct[i].windowmode == NULL) {
- schedule_download->timewindowstruct[i].windowmode = strdup(opaque);
- if (i == 0)
- windowmode0 = icwmp_strdup(opaque);
- else
- windowmode1 = icwmp_strdup(opaque);
- } else if (i == 0) {
- tmp = windowmode0;
- if (cwmp_asprintf(&windowmode0, "%s %s", tmp, opaque) == -1) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
- } else if (i == 1) {
- tmp = windowmode1;
- if (cwmp_asprintf(&windowmode1, "%s %s", tmp, opaque) == -1) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
- }
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "UserMessage")) {
- schedule_download->timewindowstruct[i].usermessage = strdup(opaque);
- }
- if (type == MXML_OPAQUE && opaque && mxmlGetType(prt) == MXML_ELEMENT && !strcmp(mxmlGetElement(prt), "MaxRetries")) {
- schedule_download->timewindowstruct[i].maxretries = atoi(opaque);
- }
- t = mxmlWalkNext(t, b, MXML_DESCEND);
- }
- i++;
- }
- b = mxmlWalkNext(b, n, MXML_DESCEND);
- }
- if (!icwmp_validate_string_length(schedule_download->command_key, 32)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (!icwmp_validate_string_length(schedule_download->url, 256)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (!icwmp_validate_string_length(schedule_download->username, 256)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (!icwmp_validate_string_length(schedule_download->password, 256)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (!icwmp_validate_unsignedint(str_file_size)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- FREE(str_file_size);
- goto fault;
- }
- FREE(str_file_size);
- if (strcmp(file_type, FIRMWARE_UPGRADE_IMAGE_FILE_TYPE) && strcmp(file_type, WEB_CONTENT_FILE_TYPE) && strcmp(file_type, VENDOR_CONFIG_FILE_TYPE) && strcmp(file_type, TONE_FILE_TYPE) && strcmp(file_type, RINGER_FILE_TYPE) && strcmp(file_type, STORED_FIRMWARE_IMAGE_FILE_TYPE)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- } else if ((strcmp(windowmode0, "1 At Any Time") && strcmp(windowmode0, "2 Immediately") && strcmp(windowmode0, "3 When Idle")) || (strcmp(windowmode1, "1 At Any Time") && strcmp(windowmode1, "2 Immediately") && strcmp(windowmode1, "3 When Idle"))) {
- error = FAULT_CPE_REQUEST_DENIED;
- } else if (count_download_queue >= MAX_DOWNLOAD_QUEUE) {
- error = FAULT_CPE_RESOURCES_EXCEEDED;
- } else if (schedule_download->url == NULL || (strcmp(schedule_download->url, "") == 0)) {
- error = FAULT_CPE_REQUEST_DENIED;
- } else if (strstr(schedule_download->url, "@") != NULL) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- } else if (strncmp(schedule_download->url, DOWNLOAD_PROTOCOL_HTTP, strlen(DOWNLOAD_PROTOCOL_HTTP)) != 0 && strncmp(schedule_download->url, DOWNLOAD_PROTOCOL_FTP, strlen(DOWNLOAD_PROTOCOL_FTP)) != 0) {
- error = FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL;
- } else {
- for (j = 0; j < 3; j++) {
- if (schedule_download_delay[j] > schedule_download_delay[j + 1]) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- break;
- }
- }
- }
-
- if (error != FAULT_CPE_NO_FAULT)
- goto fault;
-
- t = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
- if (!t)
- goto fault;
-
- t = mxmlNewElement(t, "cwmp:ScheduleDownloadResponse"); // ScheduleDownloadResponse has no argument
- if (!t)
- goto fault;
-
- pthread_mutex_lock(&mutex_schedule_download);
- list_add_tail(&(schedule_download->list), &(list_schedule_download));
- if (schedule_download_delay[0] != 0) {
- count_download_queue++;
- }
- while (i > 0) {
- i--;
- schedule_download->timewindowstruct[i].windowstart = time(NULL) + schedule_download_delay[i * 2];
- schedule_download->timewindowstruct[i].windowend = time(NULL) + schedule_download_delay[i * 2 + 1];
- }
- bkp_session_insert_schedule_download(schedule_download);
- bkp_session_save();
- if (schedule_download_delay[0] != 0) {
- CWMP_LOG(INFO, "Schedule download will start in %us", schedule_download_delay[0]);
- } else {
- CWMP_LOG(INFO, "Schedule Download will start at the end of session");
- }
- pthread_mutex_unlock(&mutex_schedule_download);
- pthread_cond_signal(&threshold_schedule_download);
-
- return 0;
-
-fault:
- cwmp_free_schedule_download_request(schedule_download);
- if (cwmp_create_fault_message(session, rpc, error))
- goto error;
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * [RPC CPE]: Upload
- */
-int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *n, *b = session->body_in;
- //char *file_type = NULL;
- int error = FAULT_CPE_NO_FAULT;
- struct upload *upload = NULL, *iupload;
- struct list_head *ilist;
- time_t scheduled_time = 0;
- time_t upload_delay = 0;
- char *str_upload_delay = NULL;
- char c[256];
-
- if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "Upload") == -1) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
-
- n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
-
- if (!n)
- return -1;
- b = n;
-
- upload = calloc(1, sizeof(struct upload));
- if (upload == NULL) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
- upload->f_instance = 0;
- while (b != NULL) {
- const char *node_opaque = mxmlGetOpaque(b);
- mxml_node_t *parent = mxmlGetParent(b);
- mxml_type_t node_type = mxmlGetType(b);
-
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "CommandKey")) {
- upload->command_key = strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "FileType")) {
- char log_config[16]={0};
- int ftype, instance = 0;
- sscanf(node_opaque, "%1d Vendor %15s File %8d", &ftype, log_config, &instance);
- if (strcmp(log_config, "Configuration") != 0 && strcmp(log_config, "Log") != 0) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- } else if (strcmp(log_config, "Configuration") == 0 && ftype != 1 && ftype != 3) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- } else if (strcmp(log_config, "Log") == 0 && ftype != 2 && ftype != 4) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if ((ftype == 3 || ftype == 4) && (instance == 0)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (ftype !=1 && ftype != 2 && ftype != 3 && ftype != 4) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- upload->file_type = strdup(node_opaque);
- upload->f_instance = instance;
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "URL")) {
- upload->url = strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "Username")) {
- upload->username = strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "Password")) {
- upload->password = strdup(node_opaque);
- }
- if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "DelaySeconds")) {
- str_upload_delay = strdup(node_opaque);
- upload_delay = atol(node_opaque);
- }
- b = mxmlWalkNext(b, n, MXML_DESCEND);
- }
- if (!icwmp_validate_string_length(upload->command_key, 32)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (!icwmp_validate_string_length(upload->url, 256)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (!icwmp_validate_string_length(upload->username, 256)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (!icwmp_validate_string_length(upload->password, 256)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- goto fault;
- }
- if (!icwmp_validate_unsignedint(str_upload_delay)) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- FREE(str_upload_delay);
- goto fault;
- }
- FREE(str_upload_delay);
-
- if (count_download_queue >= MAX_DOWNLOAD_QUEUE) {
- error = FAULT_CPE_RESOURCES_EXCEEDED;
- } else if (upload->url == NULL || (strcmp(upload->url, "") == 0)) {
- error = FAULT_CPE_REQUEST_DENIED;
- } else if (strstr(upload->url, "@") != NULL) {
- error = FAULT_CPE_INVALID_ARGUMENTS;
- } else if (strncmp(upload->url, DOWNLOAD_PROTOCOL_HTTPS, strlen(DOWNLOAD_PROTOCOL_HTTPS)) != 0 && strncmp(upload->url, DOWNLOAD_PROTOCOL_HTTP, strlen(DOWNLOAD_PROTOCOL_HTTP)) != 0 && strncmp(upload->url, DOWNLOAD_PROTOCOL_FTP, strlen(DOWNLOAD_PROTOCOL_FTP)) != 0) {
- error = FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL;
- }
-
- if (error != FAULT_CPE_NO_FAULT) {
- goto fault;
- }
-
- if (create_download_upload_response(session->tree_out, TYPE_UPLOAD) != FAULT_CPE_NO_FAULT) {
- error = FAULT_CPE_INTERNAL_ERROR;
- goto fault;
- }
-
- if (error == FAULT_CPE_NO_FAULT) {
- pthread_mutex_lock(&mutex_upload);
- if (upload_delay != 0)
- scheduled_time = time(NULL) + upload_delay + PROCESSING_DELAY;
-
- list_for_each (ilist, &(list_upload)) {
- iupload = list_entry(ilist, struct upload, list);
- if (iupload->scheduled_time >= scheduled_time) {
- break;
- }
- }
- list_add(&(upload->list), ilist->prev);
- if (upload_delay != 0) {
- count_download_queue++;
- upload->scheduled_time = scheduled_time;
- }
- bkp_session_insert_upload(upload);
- bkp_session_save();
- if (upload_delay != 0) {
- CWMP_LOG(INFO, "Upload will start in %us", upload_delay);
- } else {
- CWMP_LOG(INFO, "Upload will start at the end of session");
- }
- pthread_mutex_unlock(&mutex_upload);
- pthread_cond_signal(&threshold_upload);
- }
- return 0;
-
-fault:
- cwmp_free_upload_request(upload);
- if (cwmp_create_fault_message(session, rpc, error))
- return -1;
- return 0;
-}
-
-/*
- * [FAULT]: Fault
- */
-
-int cwmp_handle_rpc_cpe_fault(struct session *session, struct rpc *rpc)
-{
- mxml_node_t *b, *t, *u, *body;
-
- body = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
-
- b = mxmlNewElement(body, "soap_env:Fault");
- if (!b)
- return -1;
-
- t = mxmlNewElement(b, "faultcode");
- if (!t)
- return -1;
-
- u = mxmlNewOpaque(t, (FAULT_CPE_ARRAY[session->fault_code].TYPE == FAULT_CPE_TYPE_CLIENT) ? "Client" : "Server");
- if (!u)
- return -1;
-
- t = mxmlNewElement(b, "faultstring");
- if (!t)
- return -1;
-
- u = mxmlNewOpaque(t, "CWMP fault");
- if (!u)
- return -1;
-
- b = mxmlNewElement(b, "detail");
- if (!b)
- return -1;
-
- b = mxmlNewElement(b, "cwmp:Fault");
- if (!b)
- return -1;
-
- t = mxmlNewElement(b, "FaultCode");
- if (!t)
- return -1;
-
- u = mxmlNewOpaque(t, FAULT_CPE_ARRAY[session->fault_code].CODE);
- if (!u)
- return -1;
-
- t = mxmlNewElement(b, "FaultString");
- if (!b)
- return -1;
-
- u = mxmlNewOpaque(t, FAULT_CPE_ARRAY[session->fault_code].DESCRIPTION);
- if (!u)
- return -1;
-
- if (rpc->type == RPC_CPE_SET_PARAMETER_VALUES) {
- while (rpc->list_set_value_fault->next != rpc->list_set_value_fault) {
- struct cwmp_param_fault *param_fault;
-
- param_fault = list_entry(rpc->list_set_value_fault->next, struct cwmp_param_fault, list);
-
- if (param_fault->fault) {
- int idx;
- idx = cwmp_get_fault_code(param_fault->fault);
-
- t = mxmlNewElement(b, "SetParameterValuesFault");
- if (!t)
- return -1;
-
- u = mxmlNewElement(t, "ParameterName");
- if (!u)
- return -1;
-
- u = mxmlNewOpaque(u, param_fault->name);
- if (!u)
- return -1;
-
- u = mxmlNewElement(t, "FaultCode");
- if (!u)
- return -1;
-
- u = mxmlNewOpaque(u, FAULT_CPE_ARRAY[idx].CODE);
- if (!u)
- return -1;
-
- u = mxmlNewElement(t, "FaultString");
- if (!u)
- return -1;
-
- u = mxmlNewOpaque(u, FAULT_CPE_ARRAY[idx].DESCRIPTION);
- if (!u)
- return -1;
- }
- cwmp_del_list_fault_param(param_fault);
- }
- }
-
- return 0;
-}
-
-int cwmp_create_fault_message(struct session *session, struct rpc *rpc_cpe, int fault_code)
-{
- CWMP_LOG(INFO, "Fault detected");
- session->fault_code = fault_code;
-
- MXML_DELETE(session->tree_out);
-
- if (xml_prepare_msg_out(session))
- return -1;
-
- CWMP_LOG(INFO, "Preparing the Fault message");
- if (rpc_cpe_methods[RPC_CPE_FAULT].handler(session, rpc_cpe))
- return -1;
- rpc_cpe->type = RPC_CPE_FAULT;
-
- return 0;
-}
diff --git a/backupSession.c b/src/backupSession.c
similarity index 98%
rename from backupSession.c
rename to src/backupSession.c
index 758922d..ff7dc41 100644
--- a/backupSession.c
+++ b/src/backupSession.c
@@ -1,13 +1,14 @@
/*
- * 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.
+ * backupSession.c - API to store/load CWMP session in/from backup XML files
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Mohamed Kallel
* Author Ahmed Zribi
* Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
*/
#include
@@ -521,7 +522,7 @@ void bkp_session_delete_apply_schedule_download(struct apply_schedule_download *
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;
@@ -662,7 +663,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);
@@ -802,6 +803,10 @@ void load_queue_event(mxml_node_t *tree, struct cwmp *cwmp)
const char *element = mxmlGetElement(b);
if (strcmp(element, "command_key") == 0) {
+ // cppcheck-suppress knownConditionTrueFalse
+ /*
+ * idx value can be modified when loading the backup with the function load_specific_backup_attributes
+ */
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 : ""));
diff --git a/inc/backupSession.h b/src/backupSession.h
similarity index 88%
rename from inc/backupSession.h
rename to src/backupSession.h
index b4e5b60..c55fb01 100644
--- a/inc/backupSession.h
+++ b/src/backupSession.h
@@ -1,19 +1,20 @@
/*
- * 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.
+ * backupSession.h - API to store/load CWMP session in/from backup XML files
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2020 iopsys Software Solutions AB
* Author Mohamed Kallel
* Author Ahmed Zribi
+ * Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
*
*/
#ifndef _BACKUPSESSION_H__
#define _BACKUPSESSION_H__
-#include
+#include "xml_utils.h"
#include "common.h"
#define RPC_NO_STATUS -1
diff --git a/common.c b/src/common.c
similarity index 98%
rename from common.c
rename to src/common.c
index 74df6ff..52f6473 100755
--- a/common.c
+++ b/src/common.c
@@ -1,12 +1,12 @@
/*
- * 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.
+ * common.c - Some commun functions used by the application
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel
*
+ * See LICENSE file for license related information.
+ *
*/
#include
@@ -165,6 +165,7 @@ void add_dm_parameter_to_list(struct list_head *head, char *param_name, char *pa
dm_parameter->value = strdup(param_val);
dm_parameter->type = strdup(param_type ? param_type : "xsd:string");
+ dm_parameter->access_list = strdup("");
dm_parameter->notification = notification;
dm_parameter->writable = writable;
}
@@ -175,6 +176,7 @@ void delete_dm_parameter_from_list(struct cwmp_dm_parameter *dm_parameter)
free(dm_parameter->name);
free(dm_parameter->value);
free(dm_parameter->type);
+ free(dm_parameter->access_list);
free(dm_parameter);
}
diff --git a/inc/common.h b/src/common.h
similarity index 97%
rename from inc/common.h
rename to src/common.h
index 503d8ca..5ed900b 100644
--- a/inc/common.h
+++ b/src/common.h
@@ -1,13 +1,14 @@
/*
- * 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.
+ * common.h - Some commun functions used by the application
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2020 iopsys Software Solutions AB
* Author Omar Kallel
*
+ * See LICENSE file for license related information.
+ *
*/
+
#ifndef __CCOMMON_H
#define __CCOMMON_H
@@ -216,6 +217,7 @@ struct cwmp_dm_parameter {
char *name;
char *value;
char *type;
+ char *access_list;
int notification;
bool writable;
bool forced_notification_param;
diff --git a/config.c b/src/config.c
similarity index 98%
rename from config.c
rename to src/config.c
index 0751795..08f0e38 100755
--- a/config.c
+++ b/src/config.c
@@ -1,14 +1,16 @@
/*
- * 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.
+ * config.c - load/store icwmp application configuration
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Mohamed Kallel
* Author Ahmed Zribi
* Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
*/
+
#include
#include
diff --git a/inc/config.h b/src/config.h
similarity index 54%
rename from inc/config.h
rename to src/config.h
index 41858bb..1336e4d 100755
--- a/inc/config.h
+++ b/src/config.h
@@ -1,13 +1,13 @@
/*
- * 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.
+ * config.h - load/store icwmp application configuration
*
- * Copyright (C) 2013-2019 iopsys Software Solutions AB
- * Author Mohamed Kallel
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
+ *
+ * Author Omar Kallel
* Author Anis Ellouze
*
+ * See LICENSE file for license related information.
+ *
*/
#ifndef _CONFIG_H__
diff --git a/cwmp.c b/src/cwmp.c
similarity index 97%
rename from cwmp.c
rename to src/cwmp.c
index c57464e..6dcdd05 100644
--- a/cwmp.c
+++ b/src/cwmp.c
@@ -1,13 +1,14 @@
/*
- * 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.
+ * cwmp.c - icwmp Main file
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Mohamed Kallel
* Author Ahmed Zribi
* Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
*/
#include
@@ -28,7 +29,7 @@
#include "session.h"
#include "diagnostic.h"
#include "http.h"
-#include "rpc_soap.h"
+#include "rpc.h"
#include "config.h"
#include "backupSession.h"
#include "ubus_utils.h"
@@ -39,7 +40,6 @@
#include "datamodel_interface.h"
#include "cwmp_du_state.h"
#include "heartbeat.h"
-#include "netlink.h"
static pthread_t periodic_event_thread;
static pthread_t scheduleInform_thread;
@@ -230,7 +230,7 @@ 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) {
+ if (icwmp_http_client_init(cwmp) || thread_end) {
CWMP_LOG(INFO, "Initializing http client failed");
goto retry;
}
@@ -327,7 +327,7 @@ retry:
end:
MXML_DELETE(session->tree_in);
MXML_DELETE(session->tree_out);
- http_client_exit();
+ icwmp_http_client_exit();
xml_exit();
return session->error;
}
@@ -571,16 +571,6 @@ static void *thread_uloop_run(void *v __attribute__((unused)))
{
uloop_init();
- 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");
- }
- }
-
ctx = ubus_connect(cwmp_main.conf.ubus_socket);
if (!ctx)
return NULL;
@@ -603,7 +593,7 @@ static void *thread_uloop_run(void *v __attribute__((unused)))
static void *thread_http_cr_server_listen(void *v __attribute__((unused)))
{
- http_server_listen();
+ icwmp_http_server_listen();
return NULL;
}
@@ -830,6 +820,7 @@ end:
static int cwmp_init(struct cwmp *cwmp)
{
int error;
+
icwmp_init_list_services();
cwmp->event_id = 0;
cwmp->cwmp_period = 0;
@@ -1011,7 +1002,7 @@ int main(int argc, char **argv)
return error;
configure_var_state(&cwmp_main);
- http_server_init();
+ icwmp_http_server_init();
memset(&act, 0, sizeof(act));
act.sa_handler = icwmp_signal_handler;
diff --git a/cwmp_cli.c b/src/cwmp_cli.c
similarity index 95%
rename from cwmp_cli.c
rename to src/cwmp_cli.c
index f566275..acb132e 100644
--- a/cwmp_cli.c
+++ b/src/cwmp_cli.c
@@ -1,11 +1,12 @@
/*
- * 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.
+ * cwmp_cli.c - icwmp CLI
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
*/
#include
@@ -64,7 +65,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 +90,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 +205,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 +267,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");
}
diff --git a/inc/cwmp_cli.h b/src/cwmp_cli.h
similarity index 79%
rename from inc/cwmp_cli.h
rename to src/cwmp_cli.h
index d6fde40..8d2b4a9 100644
--- a/inc/cwmp_cli.h
+++ b/src/cwmp_cli.h
@@ -1,3 +1,14 @@
+/*
+ * cwmp_cli.h - icwmp CLI
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
+ *
+ * Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
+ */
+
#ifndef CWMP_CLI
#define CWMP_CLI
diff --git a/cwmp_du_state.c b/src/cwmp_du_state.c
similarity index 97%
rename from cwmp_du_state.c
rename to src/cwmp_du_state.c
index 914811a..99d71c9 100644
--- a/cwmp_du_state.c
+++ b/src/cwmp_du_state.c
@@ -1,11 +1,12 @@
/*
- * 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.
+ * cwmp-du_state.c - ChangeDUState method corresponding functions
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
*/
#include
@@ -156,7 +157,7 @@ static int get_deployment_unit_name_version(char *uuid, char **name, char **vers
snprintf(name_param, sizeof(name_param), "Device.SoftwareModules.DeploymentUnit.%s.Name", sw_by_uuid_instance);
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);
@@ -218,7 +219,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) {
diff --git a/inc/cwmp_du_state.h b/src/cwmp_du_state.h
similarity index 73%
rename from inc/cwmp_du_state.h
rename to src/cwmp_du_state.h
index ed7c110..e356037 100644
--- a/inc/cwmp_du_state.h
+++ b/src/cwmp_du_state.h
@@ -1,11 +1,12 @@
/*
- * 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.
+ * cwmp-du_state.h - ChangeDUState method corresponding functions
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
*/
#ifndef CWMP_DU_STATE_H
diff --git a/cwmp_uci.c b/src/cwmp_uci.c
similarity index 98%
rename from cwmp_uci.c
rename to src/cwmp_uci.c
index ce77d75..fffd1b1 100644
--- a/cwmp_uci.c
+++ b/src/cwmp_uci.c
@@ -1,12 +1,14 @@
/*
- * 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.
+ * cwmp_uci.c - API to manage UCI packages/sections/options
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
*/
+
#include
#include
#include
diff --git a/inc/cwmp_uci.h b/src/cwmp_uci.h
similarity index 95%
rename from inc/cwmp_uci.h
rename to src/cwmp_uci.h
index 39d1b63..3b84c52 100644
--- a/inc/cwmp_uci.h
+++ b/src/cwmp_uci.h
@@ -1,14 +1,15 @@
/*
- * 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.
+ * cwmp_uci.h - API to manage UCI packages/sections/options
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2020 iopsys Software Solutions AB
* Author Omar Kallel
*
+ * See LICENSE file for license related information.
+ *
*/
+
#ifndef __CWMPUCI_H
#define __CWMPUCI_H
diff --git a/cwmp_zlib.c b/src/cwmp_zlib.c
similarity index 84%
rename from cwmp_zlib.c
rename to src/cwmp_zlib.c
index 7495fa5..bb0a9bd 100644
--- a/cwmp_zlib.c
+++ b/src/cwmp_zlib.c
@@ -1,11 +1,12 @@
/*
- * 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.
+ * cwmp_zlib.c - ZLIB compresssion of CWMP messages
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
+ *
+ * Author Mohamed Kallel
+ *
+ * See LICENSE file for license related information.
*
- * Copyright (C) 2014-2021 iopsys Software Solutions AB
- * Author Mohamed Kallel
*/
#include
diff --git a/src/cwmp_zlib.h b/src/cwmp_zlib.h
new file mode 100644
index 0000000..5f94b30
--- /dev/null
+++ b/src/cwmp_zlib.h
@@ -0,0 +1,17 @@
+/*
+ * cwmp_zlib.h - ZLIB compresssion of CWMP messages
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
+ *
+ * Author Mohamed Kallel
+ *
+ * See LICENSE file for license related information.
+ *
+ */
+
+#ifndef __ZLIB_H
+#define __ZLIB_H
+
+int zlib_compress(char *message, unsigned char **zmsg, int *zlen, int type);
+
+#endif
diff --git a/datamodel_interface.c b/src/datamodel_interface.c
similarity index 98%
rename from datamodel_interface.c
rename to src/datamodel_interface.c
index 304d4e2..bb11cba 100755
--- a/datamodel_interface.c
+++ b/src/datamodel_interface.c
@@ -1,11 +1,12 @@
/*
- * 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.
+ * datamodel_interface.c - API to call BBF datamodel functions (set, get, add, delete, setattributes, getattributes, getnames, ...)
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
*/
#include
@@ -440,7 +441,7 @@ char *cwmp_get_multiple_parameters_values(struct list_head *arg_params_list, str
{
int e;
struct cwmp *cwmp = &cwmp_main;
- struct cwmp_dm_parameter *param_value;
+ struct cwmp_dm_parameter *param_value = NULL;
struct list_params_result get_result = { .parameters_list = parameters_list };
struct blob_buf b = { 0 };
@@ -536,7 +537,7 @@ void ubus_setm_values_callback(struct ubus_request *req, int type __attribute__(
int cwmp_set_multiple_parameters_values(struct list_head *parameters_values_list, char *parameter_key, int *flag, struct list_head *faults_list)
{
int e;
- struct cwmp_dm_parameter *param_value;
+ struct cwmp_dm_parameter *param_value = NULL;
struct setm_values_res set_result = { .flag = flag, .faults_list = faults_list };
struct cwmp *cwmp = &cwmp_main;
struct blob_buf b = { 0 };
diff --git a/inc/datamodel_interface.h b/src/datamodel_interface.h
similarity index 78%
rename from inc/datamodel_interface.h
rename to src/datamodel_interface.h
index 6d76b6e..278123a 100644
--- a/inc/datamodel_interface.h
+++ b/src/datamodel_interface.h
@@ -1,3 +1,14 @@
+/*
+ * datamodel_interface.h - API to call BBF datamodel functions (set, get, add, delete, setattributes, getattributes, getnames, ...)
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
+ *
+ * Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
+ */
+
#ifndef SRC_DATAMODELIFACE_H_
#define SRC_DATAMODELIFACE_H_
diff --git a/diagnostic.c b/src/diagnostic.c
similarity index 97%
rename from diagnostic.c
rename to src/diagnostic.c
index eba05e3..5f119d6 100644
--- a/diagnostic.c
+++ b/src/diagnostic.c
@@ -1,14 +1,16 @@
/*
- * 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.
+ * diagnostic.c - Manage Diagnostics parameters from icwmp
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2021 iopsys Software Solutions AB
* Author Imen Bhiri
* Author: Amin Ben Ramdhane
* Author: Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
*/
+
#include
#include "common.h"
diff --git a/src/diagnostic.h b/src/diagnostic.h
new file mode 100644
index 0000000..0430f4c
--- /dev/null
+++ b/src/diagnostic.h
@@ -0,0 +1,27 @@
+/*
+ * diagnostic.h - Manage Diagnostics parameters from icwmp
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
+ *
+ * Author Imen Bhiri
+ * Author: Amin Ben Ramdhane
+ * Author: Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
+ */
+
+#ifndef __DIAGNOSTIC__H
+#define __DIAGNOSTIC__H
+
+bool set_diagnostic_parameter_structure_value(char *parameter_name, char *value);
+
+int cwmp_download_diagnostics();
+int cwmp_upload_diagnostics();
+int cwmp_ip_ping_diagnostics();
+int cwmp_nslookup_diagnostics();
+int cwmp_traceroute_diagnostics();
+int cwmp_udp_echo_diagnostics();
+int cwmp_serverselection_diagnostics();
+
+#endif
diff --git a/digauth.c b/src/digauth.c
similarity index 98%
rename from digauth.c
rename to src/digauth.c
index d12fa75..01faa6a 100644
--- a/digauth.c
+++ b/src/digauth.c
@@ -144,10 +144,10 @@ static void get_hexstring(unsigned const char *hash, int len, char *hexstr, int
static void get_value_from_header(const char *data)
{
- if (data == NULL)
+ if (CWMP_STRLEN(data) == 0)
return;
- int header_len = strlen(data) + 1;
+ int header_len = CWMP_STRLEN(data) + 1;
char header[header_len];
memset(header, 0, header_len);
strncpy(header, data, header_len);
@@ -167,7 +167,7 @@ static void get_value_from_header(const char *data)
strip_lead_trail_char(key, '\"');
eq = eq + 1;
- char *end = eq + strlen(eq) - 1;
+ char *end = eq + CWMP_STRLEN(eq) - 1;
len = end - eq + 2;
char val[len];
snprintf(val, len, "%s", eq);
diff --git a/inc/digauth.h b/src/digauth.h
similarity index 67%
rename from inc/digauth.h
rename to src/digauth.h
index 6846a27..3f74ab4 100644
--- a/inc/digauth.h
+++ b/src/digauth.h
@@ -1,3 +1,13 @@
+/*
+ * digauth.h - HTTP digest authentication utility
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
+ *
+ * Author: suvendhu.hansa@iopsys.eu
+ *
+ * See LICENSE file for license related information.
+ *
+ */
#ifndef DIGAUTH_H_
#define DIGAUTH_H_
diff --git a/download.c b/src/download.c
similarity index 98%
rename from download.c
rename to src/download.c
index 704551f..3954d42 100644
--- a/download.c
+++ b/src/download.c
@@ -1,13 +1,13 @@
/*
- * 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.
+ * download.c - Download method functions
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
+ *
+ * Author: Omar Kallel
+ *
+ * See LICENSE file for license related information.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
- * Author Omar Kallel
*/
-
#include
#include
#include
diff --git a/inc/download.h b/src/download.h
similarity index 89%
rename from inc/download.h
rename to src/download.h
index 241b66e..34a09c1 100644
--- a/inc/download.h
+++ b/src/download.h
@@ -1,3 +1,13 @@
+/*
+ * download.h - Download method functions
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
+ *
+ * Author: Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
+ */
#ifndef CWMP_DOWNLOAD_H
#define CWMP_DOWNLOAD_H
diff --git a/event.c b/src/event.c
similarity index 98%
rename from event.c
rename to src/event.c
index 3b1216b..7891746 100644
--- a/event.c
+++ b/src/event.c
@@ -1,14 +1,14 @@
/*
- * 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.
+ * event.c - Manage CWMP Events
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Mohamed Kallel
* Author Ahmed Zribi
* Author Omar Kallel
*
+ * See LICENSE file for license related information.
+ *
*/
#include "backupSession.h"
@@ -389,7 +389,7 @@ void *thread_event_periodic(void *v)
bool event_exist_in_list(struct cwmp *cwmp, int event)
{
- struct event_container *event_container;
+ struct event_container *event_container = NULL;
list_for_each_entry (event_container, cwmp->head_event_container, list) {
if (event_container->code == event)
return true;
diff --git a/inc/event.h b/src/event.h
similarity index 87%
rename from inc/event.h
rename to src/event.h
index 8803d6e..7c57085 100644
--- a/inc/event.h
+++ b/src/event.h
@@ -1,12 +1,12 @@
/*
- * 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.
+ * event.h - Manage CWMP Events
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2020 iopsys Software Solutions AB
* Author Omar Kallel
*
+ * See LICENSE file for license related information.
+ *
*/
#ifndef EVENT_H_
diff --git a/heartbeat.c b/src/heartbeat.c
similarity index 96%
rename from heartbeat.c
rename to src/heartbeat.c
index d831acd..401c131 100644
--- a/heartbeat.c
+++ b/src/heartbeat.c
@@ -1,3 +1,13 @@
+/*
+ * heartbeat.c - CWMP HeartBeat mechanism
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
+ *
+ * Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
+ */
#include
#include
diff --git a/inc/heartbeat.h b/src/heartbeat.h
similarity index 65%
rename from inc/heartbeat.h
rename to src/heartbeat.h
index cde6978..9102dce 100644
--- a/inc/heartbeat.h
+++ b/src/heartbeat.h
@@ -1,3 +1,13 @@
+/*
+ * heartbeat.h - CWMP HeartBeat mechanism
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
+ *
+ * Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
+ */
#ifndef HEARTBEAT_H
#define HEARTBEAT_H
diff --git a/http.c b/src/http.c
similarity index 92%
rename from http.c
rename to src/http.c
index 97944f2..e51b307 100644
--- a/http.c
+++ b/src/http.c
@@ -1,14 +1,14 @@
/*
- * 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.
+ * http.c - API for HTTP exchanges
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
- * Author Mohamed Kallel
- * Author Ahmed Zribi
* Author Omar Kallel
- * Copyright (C) 2011-2012 Luka Perkov
+ * Author Mohamed Kallel
+ * Author Ahmed Zribi
+ *
+ * See LICENSE file for license related information.
+ *
*/
#include
#include
@@ -39,7 +39,7 @@ void http_set_timeout(void)
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1);
}
-int http_client_init(struct cwmp *cwmp)
+int icwmp_http_client_init(struct cwmp *cwmp)
{
char *dhcp_dis = NULL;
char *acs_var_stat = NULL;
@@ -96,7 +96,7 @@ int http_client_init(struct cwmp *cwmp)
return 0;
}
-void http_client_exit(void)
+void icwmp_http_client_exit(void)
{
icwmp_free(http_c.url);
@@ -131,7 +131,69 @@ 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)
+static void http_set_security_options(struct cwmp *cwmp)
+{
+ 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_HTTPAUTH, CURLAUTH_BASIC | CURLAUTH_DIGEST);
+
+ if (cwmp->conf.acs_ssl_capath)
+ curl_easy_setopt(curl, CURLOPT_CAPATH, cwmp->conf.acs_ssl_capath);
+ if (cwmp->conf.insecure_enable) {
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
+ }
+}
+
+static void http_set_connection_options(struct cwmp *cwmp)
+{
+ curl_easy_setopt(curl, CURLOPT_URL, http_c.url);
+
+ 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);
+#ifdef DEVEL
+ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+#endif
+
+ curl_easy_setopt(curl, CURLOPT_COOKIEFILE, fc_cookies);
+ curl_easy_setopt(curl, CURLOPT_COOKIEJAR, fc_cookies);
+
+ curl_easy_setopt(curl, CURLOPT_INTERFACE, cwmp->conf.interface);
+}
+
+static void http_set_header_list_options(struct cwmp *cwmp)
+{
+ switch (cwmp->conf.compression) {
+ case COMP_NONE:
+ break;
+ case COMP_GZIP:
+ curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip");
+ http_c.header_list = curl_slist_append(http_c.header_list, "Content-Encoding: gzip");
+ break;
+ case COMP_DEFLATE:
+ curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "deflate");
+ http_c.header_list = curl_slist_append(http_c.header_list, "Content-Encoding: deflate");
+ break;
+ }
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_c.header_list);
+}
+
+static void http_set_inout_options(char *msg_out, int msg_out_len, char **msg_in)
+{
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg_out);
+ if (msg_out)
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)msg_out_len);
+ else
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0);
+
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_response);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, msg_in);
+}
+
+int icwmp_http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **msg_in)
{
unsigned char buf[sizeof(struct in6_addr)];
int tmp = 0;
@@ -158,53 +220,13 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **
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_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) {
- case COMP_NONE:
- break;
- case COMP_GZIP:
- curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip");
- http_c.header_list = curl_slist_append(http_c.header_list, "Content-Encoding: gzip");
- break;
- case COMP_DEFLATE:
- curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "deflate");
- http_c.header_list = curl_slist_append(http_c.header_list, "Content-Encoding: deflate");
- break;
- }
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_c.header_list);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg_out);
- if (msg_out)
- curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)msg_out_len);
- else
- curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0);
+ http_set_connection_options(cwmp);
+ http_set_security_options(cwmp);
+ http_set_header_list_options(cwmp);
+ http_set_inout_options(msg_out, msg_out_len, msg_in);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_response);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, msg_in);
-
-#ifdef DEVEL
- curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
-#endif
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
- 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) {
- 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);
*msg_in = (char *)calloc(1, sizeof(char));
res = curl_easy_perform(curl);
@@ -279,7 +301,7 @@ error:
return -1;
}
-void http_success_cr(void)
+static 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));
@@ -291,14 +313,14 @@ void http_success_cr(void)
static void http_cr_new_client(int client, bool service_available)
{
FILE *fp;
- char buffer[BUFSIZ];
- char auth_digest_buffer[BUFSIZ];
+ char buffer[BUFSIZ] = {0};
+ 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[HTTP_GET_HDR_LEN];
+ char cr_http_get_head[HTTP_GET_HDR_LEN] = {0};
pthread_mutex_lock(&mutex_config_load);
fp = fdopen(client, "r+");
@@ -388,7 +410,7 @@ http_end:
pthread_mutex_unlock(&mutex_config_load);
}
-void http_server_init(void)
+void icwmp_http_server_init(void)
{
struct sockaddr_in6 server = { 0 };
unsigned short cr_port;
@@ -438,7 +460,7 @@ void http_server_init(void)
CWMP_LOG(INFO, "Connection Request server initiated with the port: %d", cr_port);
}
-void http_server_listen(void)
+void icwmp_http_server_listen(void)
{
int client_sock, c;
int cr_request = 0;
diff --git a/src/http.h b/src/http.h
new file mode 100644
index 0000000..a6fb776
--- /dev/null
+++ b/src/http.h
@@ -0,0 +1,36 @@
+/*
+ * http.h - API for HTTP exchanges
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
+ *
+ * Author Omar Kallel
+ * Author Mohamed Kallel
+ * Author Ahmed Zribi
+ *
+ * See LICENSE file for license related information.
+ *
+ */
+#ifndef _FREECWMP_HTTP_H__
+#define _FREECWMP_HTTP_H__
+
+#include "common.h"
+
+extern char *fc_cookies;
+
+#define HTTP_TIMEOUT 60
+
+struct http_client {
+ struct curl_slist *header_list;
+ char *url;
+};
+
+void http_set_timeout(void);
+
+int icwmp_http_client_init(struct cwmp *cwmp);
+void icwmp_http_client_exit(void);
+int icwmp_http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **msg_in);
+
+void icwmp_http_server_init(void);
+void icwmp_http_server_listen(void);
+
+#endif
diff --git a/log.c b/src/log.c
similarity index 93%
rename from log.c
rename to src/log.c
index 7a0f1e1..2a1620e 100644
--- a/log.c
+++ b/src/log.c
@@ -1,12 +1,13 @@
/*
- * 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.
+ * log.c - CWMP Logs functions
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
- * Author Mohamed Kallel
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
+ *
+ * Author Mohamed Kallel
* Author Ahmed Zribi
+ * Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
*
*/
diff --git a/inc/log.h b/src/log.h
similarity index 69%
rename from inc/log.h
rename to src/log.h
index 5cb7ba5..f9a4eb2 100644
--- a/inc/log.h
+++ b/src/log.h
@@ -1,12 +1,13 @@
/*
- * 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.
+ * log.h - CWMP Logs functions
*
- * Copyright (C) 2013-2019 iopsys Software Solutions AB
- * Author Mohamed Kallel
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
+ *
+ * Author Mohamed Kallel
* Author Ahmed Zribi
+ * Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
*
*/
diff --git a/notifications.c b/src/notifications.c
similarity index 97%
rename from notifications.c
rename to src/notifications.c
index 04bcb58..186fffc 100644
--- a/notifications.c
+++ b/src/notifications.c
@@ -1,12 +1,12 @@
/*
- * 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.
+ * notifications.c - Manage CWMP Notifications
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel
*
+ * See LICENSE file for license related information.
+ *
*/
#include
@@ -207,7 +207,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;
+ struct cwmp_dm_parameter *param_value = NULL;
if (childs_list == NULL)
return -1;
list_for_each_entry (param_value, childs_list, list) {
@@ -239,7 +239,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, ¶ms_list, list) {
int notif_leaf;
notif_leaf = check_parameter_forced_notification(param_value->name);
@@ -307,7 +307,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, ¶ms_list);
if (err)
@@ -326,7 +326,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++)
@@ -462,7 +462,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;
diff --git a/inc/notifications.h b/src/notifications.h
similarity index 88%
rename from inc/notifications.h
rename to src/notifications.h
index b0415c1..ccbaa38 100644
--- a/inc/notifications.h
+++ b/src/notifications.h
@@ -1,12 +1,12 @@
/*
- * 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.
+ * notifications.h - Manage CWMP Notifications
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2020 iopsys Software Solutions AB
* Author Omar Kallel
*
+ * See LICENSE file for license related information.
+ *
*/
#ifndef NOTIFICATIONS_H_
diff --git a/reboot.c b/src/reboot.c
similarity index 92%
rename from reboot.c
rename to src/reboot.c
index 837fd82..c0d600f 100644
--- a/reboot.c
+++ b/src/reboot.c
@@ -1,11 +1,12 @@
/*
- * 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.
+ * reboot.c - Reboot method fuctions
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2021 iopsys Software Solutions AB
* Author Amin Ben Ramdhane
+ *
+ * See LICENSE file for license related information.
+ *
*/
#include
diff --git a/src/reboot.h b/src/reboot.h
new file mode 100644
index 0000000..98b2992
--- /dev/null
+++ b/src/reboot.h
@@ -0,0 +1,20 @@
+/*
+ * reboot.h - Reboot method fuctions
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
+ *
+ * Author Amin Ben Ramdhane
+ *
+ * See LICENSE file for license related information.
+ *
+ */
+
+#ifndef _REBOOT_H__
+#define _REBOOT_H__
+
+#include "common.h"
+
+void launch_reboot_methods(struct cwmp *cwmp);
+
+#endif //_REBOOT_H__
+
diff --git a/src/rpc.c b/src/rpc.c
new file mode 100755
index 0000000..bc1577b
--- /dev/null
+++ b/src/rpc.c
@@ -0,0 +1,1960 @@
+/*
+ * rpc.c - CWMP RPC methods
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
+ *
+ * Author Mohamed Kallel
+ * Author Ahmed Zribi
+ * Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
+ */
+
+#include "rpc.h"
+
+#include "download.h"
+#include "cwmp_du_state.h"
+#include "log.h"
+#include "event.h"
+#include "datamodel_interface.h"
+#include "event.h"
+#include "xml.h"
+#include "backupSession.h"
+#include "notifications.h"
+#include "upload.h"
+#include "sched_inform.h"
+#include "diagnostic.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 DM_CONN_REQ_URL "Device.ManagementServer.ConnectionRequestURL"
+
+struct cwmp_namespaces ns;
+const struct rpc_cpe_method rpc_cpe_methods[] = { [RPC_CPE_GET_RPC_METHODS] = { "GetRPCMethods", cwmp_handle_rpc_cpe_get_rpc_methods, AMD_1 },
+ [RPC_CPE_SET_PARAMETER_VALUES] = { "SetParameterValues", cwmp_handle_rpc_cpe_set_parameter_values, AMD_1 },
+ [RPC_CPE_GET_PARAMETER_VALUES] = { "GetParameterValues", cwmp_handle_rpc_cpe_get_parameter_values, AMD_1 },
+ [RPC_CPE_GET_PARAMETER_NAMES] = { "GetParameterNames", cwmp_handle_rpc_cpe_get_parameter_names, AMD_1 },
+ [RPC_CPE_SET_PARAMETER_ATTRIBUTES] = { "SetParameterAttributes", cwmp_handle_rpc_cpe_set_parameter_attributes, AMD_1 },
+ [RPC_CPE_GET_PARAMETER_ATTRIBUTES] = { "GetParameterAttributes", cwmp_handle_rpc_cpe_get_parameter_attributes, AMD_1 },
+ [RPC_CPE_ADD_OBJECT] = { "AddObject", cwmp_handle_rpc_cpe_add_object, AMD_1 },
+ [RPC_CPE_DELETE_OBJECT] = { "DeleteObject", cwmp_handle_rpc_cpe_delete_object, AMD_1 },
+ [RPC_CPE_REBOOT] = { "Reboot", cwmp_handle_rpc_cpe_reboot, AMD_1 },
+ [RPC_CPE_DOWNLOAD] = { "Download", cwmp_handle_rpc_cpe_download, AMD_1 },
+ [RPC_CPE_UPLOAD] = { "Upload", cwmp_handle_rpc_cpe_upload, AMD_1 },
+ [RPC_CPE_FACTORY_RESET] = { "FactoryReset", cwmp_handle_rpc_cpe_factory_reset, AMD_1 },
+ [RPC_CPE_CANCEL_TRANSFER] = { "CancelTransfer", cwmp_handle_rpc_cpe_cancel_transfer, AMD_3 },
+ [RPC_CPE_SCHEDULE_INFORM] = { "ScheduleInform", cwmp_handle_rpc_cpe_schedule_inform, AMD_1 },
+ [RPC_CPE_SCHEDULE_DOWNLOAD] = { "ScheduleDownload", cwmp_handle_rpc_cpe_schedule_download, AMD_3 },
+ [RPC_CPE_CHANGE_DU_STATE] = { "ChangeDUState", cwmp_handle_rpc_cpe_change_du_state, AMD_3 },
+ [RPC_CPE_X_FACTORY_RESET_SOFT] = { "X_FactoryResetSoft", cwmp_handle_rpc_cpe_x_factory_reset_soft, AMD_1 },
+ [RPC_CPE_FAULT] = { "Fault", cwmp_handle_rpc_cpe_fault, AMD_1 } };
+
+struct rpc_acs_method rpc_acs_methods[] = { [RPC_ACS_INFORM] = { "Inform", cwmp_rpc_acs_prepare_message_inform, cwmp_rpc_acs_parse_response_inform, NULL, NOT_KNOWN },
+ [RPC_ACS_GET_RPC_METHODS] = { "GetRPCMethods", cwmp_rpc_acs_prepare_get_rpc_methods, cwmp_rpc_acs_parse_response_get_rpc_methods, NULL, NOT_KNOWN },
+ [RPC_ACS_TRANSFER_COMPLETE] = { "TransferComplete", cwmp_rpc_acs_prepare_transfer_complete, NULL, cwmp_rpc_acs_destroy_data_transfer_complete, NOT_KNOWN },
+ [RPC_ACS_DU_STATE_CHANGE_COMPLETE] = { "DUStateChangeComplete", cwmp_rpc_acs_prepare_du_state_change_complete, NULL, cwmp_rpc_acs_destroy_data_du_state_change_complete, NOT_KNOWN }
+};
+
+char *custom_forced_inform_parameters[MAX_NBRE_CUSTOM_INFORM] = { 0 };
+char *boot_inform_parameters[MAX_NBRE_CUSTOM_INFORM] = { 0 };
+int nbre_custom_inform = 0;
+int nbre_boot_inform = 0;
+char *forced_inform_parameters[] = {
+ "Device.RootDataModelVersion",
+ "Device.DeviceInfo.HardwareVersion",
+ "Device.DeviceInfo.SoftwareVersion",
+ "Device.DeviceInfo.ProvisioningCode",
+ "Device.ManagementServer.ParameterKey",
+ DM_CONN_REQ_URL,
+ "Device.ManagementServer.AliasBasedAddressing"
+};
+
+int xml_handle_message(struct session *session)
+{
+ struct rpc *rpc_cpe;
+ char *c;
+ int i;
+ mxml_node_t *b;
+ struct cwmp *cwmp = &cwmp_main;
+ struct config *conf;
+ conf = &(cwmp->conf);
+
+ /* get method */
+ if (icwmp_asprintf(&c, "%s:%s", ns.soap_env, "Body") == -1) {
+ CWMP_LOG(INFO, "Internal error");
+ session->fault_code = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+ b = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
+
+ if (!b) {
+ CWMP_LOG(INFO, "Invalid received message");
+ session->fault_code = FAULT_CPE_REQUEST_DENIED;
+ goto fault;
+ }
+ session->body_in = b;
+
+ while (1) {
+ b = mxmlWalkNext(b, session->body_in, MXML_DESCEND_FIRST);
+ if (!b)
+ goto error;
+ if (mxmlGetType(b) == MXML_ELEMENT)
+ break;
+ }
+
+ c = (char *)mxmlGetElement(b);
+ /* convert QName to localPart, check that ns is the expected one */
+ if (strchr(c, ':')) {
+ char *tmp = strchr(c, ':');
+ size_t ns_len = tmp - c;
+
+ if (strlen(ns.cwmp) != ns_len) {
+ CWMP_LOG(INFO, "Invalid received message");
+ session->fault_code = FAULT_CPE_REQUEST_DENIED;
+ goto fault;
+ }
+
+ if (strncmp(ns.cwmp, c, ns_len)) {
+ CWMP_LOG(INFO, "Invalid received message");
+ session->fault_code = FAULT_CPE_REQUEST_DENIED;
+ goto fault;
+ }
+
+ c = tmp + 1;
+ } else {
+ CWMP_LOG(INFO, "Invalid received message");
+ session->fault_code = FAULT_CPE_REQUEST_DENIED;
+ goto fault;
+ }
+ CWMP_LOG(INFO, "SOAP RPC message: %s", c);
+ rpc_cpe = NULL;
+ for (i = 1; i < __RPC_CPE_MAX; i++) {
+ if (i != RPC_CPE_FAULT && strcmp(c, rpc_cpe_methods[i].name) == 0 && rpc_cpe_methods[i].amd <= conf->supported_amd_version) {
+ CWMP_LOG(INFO, "%s RPC is supported", c);
+ rpc_cpe = cwmp_add_session_rpc_cpe(session, i);
+ if (rpc_cpe == NULL)
+ goto error;
+ break;
+ }
+ }
+ if (!rpc_cpe) {
+ CWMP_LOG(INFO, "%s RPC is not supported", c);
+ session->fault_code = FAULT_CPE_METHOD_NOT_SUPPORTED;
+ goto fault;
+ }
+ return 0;
+fault:
+ rpc_cpe = cwmp_add_session_rpc_cpe(session, RPC_CPE_FAULT);
+ if (rpc_cpe == NULL)
+ goto error;
+ return 0;
+error:
+ return -1;
+}
+
+/*
+ * [RPC ACS]: Inform
+ */
+static int xml_prepare_parameters_inform(struct cwmp_dm_parameter *dm_parameter, mxml_node_t *parameter_list, int *size)
+{
+ mxml_node_t *node = NULL, *b;
+ b = mxmlFindElementOpaque(parameter_list, parameter_list, dm_parameter->name, MXML_DESCEND);
+ if (b && dm_parameter->value != NULL) {
+ node = mxmlGetParent(b);
+ b = mxmlFindElement(node, node, "Value", NULL, NULL, MXML_DESCEND_FIRST);
+ if (!b)
+ return 0;
+ mxml_node_t *c = mxmlGetFirstChild(b);
+ if (c && strcmp(dm_parameter->value, mxmlGetOpaque(c)) == 0)
+ return 0;
+ mxmlDelete(b);
+ (*size)--;
+ } else if (dm_parameter->value == NULL)
+ return 0;
+
+ char *type = (dm_parameter->type && dm_parameter->type[0] != '\0') ? dm_parameter->type : "xsd:string";
+ if (node == NULL) {
+ struct xml_data_struct inform_params_xml_attrs = {0};
+ struct xml_list_data *xml_data = calloc(1, sizeof(struct xml_list_data));
+ xml_data->param_name = strdup(dm_parameter->name);
+ xml_data->param_value = strdup(dm_parameter->value);
+ xml_data->param_type = strdup(type);
+ LIST_HEAD(prameters_xml_list);
+ list_add_tail(&xml_data->list, &prameters_xml_list);
+ inform_params_xml_attrs.data_list = &prameters_xml_list;
+ int fault = build_xml_node_data(SOAP_PARAM_STRUCT, parameter_list, &inform_params_xml_attrs);
+ if (fault != CWMP_OK)
+ return -1;
+
+ cwmp_free_all_xml_data_list(&prameters_xml_list);
+ } else {
+ struct xml_data_struct inform_param_value_xml_attrs = {0};
+ inform_param_value_xml_attrs.value = &dm_parameter->value;
+ inform_param_value_xml_attrs.xsi_type = &type;
+
+ int fault = build_xml_node_data(SOAP_VALUE_STRUCT, node, &inform_param_value_xml_attrs);
+ if (fault != CWMP_OK)
+ return -1;
+ }
+
+ (*size)++;
+ return 0;
+}
+
+static void load_inform_xml_schema(mxml_node_t **tree, struct cwmp *cwmp, struct session *session)
+{
+ char declaration[1024] = {0};
+ mxml_node_t *xml = NULL, *envelope = NULL;
+ if (tree == NULL)
+ return;
+
+ *tree = NULL;
+
+ snprintf(declaration, sizeof(declaration), "?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?");
+
+ xml= mxmlNewElement(NULL, declaration);
+ if (xml == NULL)
+ return;
+
+ struct xml_data_struct env_xml_attrs = {0};
+
+ env_xml_attrs.xml_env = &envelope;
+ env_xml_attrs.amd_version = &cwmp->conf.supported_amd_version;
+ env_xml_attrs.session_timeout = &cwmp->conf.session_timeout;
+
+ int fault = build_xml_node_data(SOAP_ENV, xml, &env_xml_attrs);
+
+ if (envelope == NULL || fault != CWMP_OK) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ mxml_node_t *inform = build_top_body_soap_request(envelope, "Inform");
+ if (inform == NULL) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ struct xml_data_struct inform_xml_attrs = {0};
+
+ char *manufacturer = cwmp->deviceid.manufacturer ? cwmp->deviceid.manufacturer : "";
+ char *oui = cwmp->deviceid.oui ? cwmp->deviceid.oui : "";
+ char *product_class = cwmp->deviceid.productclass ? cwmp->deviceid.productclass : "";
+ char *serial_number = cwmp->deviceid.serialnumber ? cwmp->deviceid.serialnumber : "";
+ int max_env = 1;
+ char *current_time = get_time(time(NULL));
+
+ inform_xml_attrs.manufacturer = &manufacturer;
+ inform_xml_attrs.oui = &oui;
+ inform_xml_attrs.product_class = &product_class;
+ inform_xml_attrs.serial_number = &serial_number;
+ inform_xml_attrs.max_envelopes = &max_env;
+ inform_xml_attrs.current_time = ¤t_time;
+ inform_xml_attrs.retry_count = &cwmp->retry_count_session;
+
+ LIST_HEAD(xml_events_list);
+ event_container_list_to_xml_data_list(&(session->head_event_container), &xml_events_list);
+ inform_xml_attrs.data_list = &xml_events_list;
+
+ fault = build_xml_node_data(SOAP_INFORM_CWMP, inform, &inform_xml_attrs);
+ if (fault != CWMP_OK) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ cwmp_free_all_xml_data_list(&xml_events_list);
+ mxml_node_t *param_list = mxmlNewElement(inform, "ParameterList");
+ if (param_list == NULL) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ mxmlElementSetAttr(param_list, "soap_enc:arrayType", "cwmp:ParameterValueStruct[0]");
+
+ struct list_head *ilist, *jlist;
+ struct cwmp_dm_parameter *dm_parameter;
+ int size = 0;
+
+ list_for_each (ilist, &(session->head_event_container)) {
+ struct event_container *event_container = list_entry(ilist, struct event_container, list);
+ list_for_each (jlist, &(event_container->head_dm_parameter)) {
+ dm_parameter = list_entry(jlist, struct cwmp_dm_parameter, list);
+ if (xml_prepare_parameters_inform(dm_parameter, param_list, &size)) {
+ MXML_DELETE(xml);
+ return;
+ }
+ }
+ }
+
+ size_t inform_parameters_nbre = sizeof(forced_inform_parameters) / sizeof(forced_inform_parameters[0]);
+ size_t i;
+ int j;
+ struct cwmp_dm_parameter cwmp_dm_param = { 0 };
+ LIST_HEAD(list_inform);
+ for (i = 0; i < inform_parameters_nbre; i++) {
+ char *fault = cwmp_get_single_parameter_value(forced_inform_parameters[i], &cwmp_dm_param);
+ if (fault != NULL)
+ continue;
+
+ // An empty connection url cause CDR test to break
+ if (strcmp(forced_inform_parameters[i], DM_CONN_REQ_URL) == 0 && cwmp_dm_param.value != NULL && strlen(cwmp_dm_param.value) == 0) {
+ CWMP_LOG(ERROR, "# Empty CR URL[%s] value", forced_inform_parameters[i]);
+ MXML_DELETE(xml);
+ return;
+ }
+
+ if (xml_prepare_parameters_inform(&cwmp_dm_param, param_list, &size)) {
+ MXML_DELETE(xml);
+ return;
+ }
+ }
+
+ for (j = 0; j < nbre_custom_inform; j++) {
+ char *fault = cwmp_get_single_parameter_value(custom_forced_inform_parameters[j], &cwmp_dm_param);
+ if (fault != NULL)
+ continue;
+ if (xml_prepare_parameters_inform(&cwmp_dm_param, param_list, &size)) {
+ MXML_DELETE(xml);
+ return;
+ }
+ }
+
+ if (cwmp->is_boot == true) {
+ for (j = 0; j < nbre_boot_inform; j++) {
+ char *fault = cwmp_get_single_parameter_value(boot_inform_parameters[j], &cwmp_dm_param);
+ if (fault != NULL)
+ continue;
+ if (xml_prepare_parameters_inform(&cwmp_dm_param, param_list, &size)) {
+ MXML_DELETE(xml);
+ return;
+ }
+ }
+ }
+
+ char c[256] = {0};
+ if (snprintf(c, sizeof(c), "cwmp:ParameterValueStruct[%d]", size) == -1) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ mxmlElementSetAttr(param_list, "xsi:type", "soap_enc:Array");
+ mxmlElementSetAttr(param_list, "soap_enc:arrayType", c);
+
+ *tree = xml;
+}
+
+int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *session, struct rpc *this)
+{
+ mxml_node_t *tree;
+
+ if (session == NULL || this == NULL)
+ return -1;
+
+ load_inform_xml_schema(&tree, cwmp, session);
+
+ if (!tree)
+ goto error;
+
+ session->tree_out = tree;
+
+ return 0;
+
+error:
+ CWMP_LOG(ERROR, "Unable Prepare Message Inform", CWMP_BKP_FILE);
+ return -1;
+}
+
+int cwmp_rpc_acs_parse_response_inform(struct cwmp *cwmp, struct session *session, struct rpc *this __attribute__((unused)))
+{
+ mxml_node_t *tree, *b;
+ int i = -1;
+ char *c;
+ const char *cwmp_urn;
+
+ tree = session->tree_in;
+ if (!tree)
+ goto error;
+ b = mxmlFindElement(tree, tree, "MaxEnvelopes", NULL, NULL, MXML_DESCEND);
+ if (!b)
+ goto error;
+ b = mxmlWalkNext(b, tree, MXML_DESCEND_FIRST);
+ if (!b || mxmlGetType(b) != MXML_OPAQUE || !mxmlGetOpaque(b))
+ goto error;
+ if (cwmp->conf.supported_amd_version == 1) {
+ cwmp->conf.amd_version = 1;
+ return 0;
+ }
+ b = mxmlFindElement(tree, tree, "UseCWMPVersion", NULL, NULL, MXML_DESCEND);
+ if (b && cwmp->conf.supported_amd_version >= 5) { //IF supported version !=5 acs response dosen't contain UseCWMPVersion
+ b = mxmlWalkNext(b, tree, MXML_DESCEND_FIRST);
+ if (!b || mxmlGetType(b) != MXML_OPAQUE || !mxmlGetOpaque(b))
+ goto error;
+ c = (char *) mxmlGetOpaque(b);
+ if (c && *(c + 1) == '.') {
+ c += 2;
+ cwmp->conf.amd_version = atoi(c) + 1;
+ return 0;
+ }
+ goto error;
+ }
+ for (i = 0; cwmp_urls[i] != NULL; i++) {
+ cwmp_urn = cwmp_urls[i];
+ c = (char *)xml__get_attribute_name_by_value(tree, cwmp_urn);
+ if (c && *(c + 5) == ':') {
+ break;
+ }
+ }
+ if (i == 0) {
+ cwmp->conf.amd_version = i + 1;
+ } else if (i >= 1 && i <= 3) {
+ switch (cwmp->conf.supported_amd_version) {
+ case 1:
+ cwmp->conf.amd_version = 1; //Already done
+ break;
+ case 2:
+ case 3:
+ case 4:
+ //MIN ACS CPE
+ if (cwmp->conf.supported_amd_version <= i + 1)
+ cwmp->conf.amd_version = cwmp->conf.supported_amd_version;
+ else
+ cwmp->conf.amd_version = i + 1;
+ break;
+ //(cwmp->supported_conf.amd_version < i+1) ?"cwmp->conf.amd_version":"i+1";
+ case 5:
+ cwmp->conf.amd_version = i + 1;
+ break;
+ }
+ } else if (i >= 4) {
+ cwmp->conf.amd_version = cwmp->conf.supported_amd_version;
+ }
+ return 0;
+
+error:
+ return -1;
+}
+
+int set_rpc_acs_to_supported(char *rpc_name)
+{
+ int i;
+
+ for (i=1; i < __RPC_ACS_MAX; i++) {
+ if (strcmp(rpc_acs_methods[i].name, rpc_name) == 0) {
+ rpc_acs_methods[i].acs_support = RPC_ACS_SUPPORT;
+ return i;
+ }
+ }
+ return -1;
+}
+
+void set_not_known_acs_support()
+{
+ int i;
+ for (i=1; i < __RPC_ACS_MAX; i++) {
+ if ((i != RPC_ACS_INFORM) && (rpc_acs_methods[i].acs_support == NOT_KNOWN))
+ rpc_acs_methods[i].acs_support = RPC_ACS_NOT_SUPPORT;
+ }
+}
+
+int cwmp_rpc_acs_parse_response_get_rpc_methods(struct cwmp *cwmp __attribute__((unused)), struct session *session, struct rpc *this __attribute__((unused)))
+{
+ mxml_node_t *tree, *b;
+ tree = session->tree_in;
+ b = mxmlFindElement(tree, tree, "cwmp:GetRPCMethodsResponse", NULL, NULL, MXML_DESCEND);
+ if (!b)
+ goto error;
+
+ while (b) {
+ const char *node_opaque = mxmlGetOpaque(b);
+ mxml_node_t *parent_node = mxmlGetParent(b);
+ mxml_type_t node_type = mxmlGetType(b);
+
+ if (node_type == MXML_OPAQUE && mxmlGetType(parent_node) == MXML_ELEMENT && node_opaque && strcmp((char *) mxmlGetElement(parent_node), "string") == 0)
+ set_rpc_acs_to_supported((char*)node_opaque);
+
+ b = mxmlWalkNext(b, session->body_in, MXML_DESCEND);
+ }
+ set_not_known_acs_support();
+ return 0;
+error:
+ return -1;
+}
+
+/*
+ * [RPC ACS]: GetRPCMethods
+ */
+int cwmp_rpc_acs_prepare_get_rpc_methods(struct cwmp *cwmp, struct session *session, struct rpc *rpc __attribute__((unused)))
+{
+ mxml_node_t *tree, *n;
+
+ load_response_xml_schema(&tree);
+ if (!tree)
+ return -1;
+
+ n = mxmlFindElement(tree, tree, "soap_env:Envelope", NULL, NULL, MXML_DESCEND);
+ if (!n)
+ return -1;
+ mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp->conf.amd_version) - 1]);
+
+ n = build_top_body_soap_request(tree, "GetRPCMethods");
+ if (!n)
+ return -1;
+
+ session->tree_out = tree;
+
+ return 0;
+}
+
+/*
+ * [RPC ACS]: TransferComplete
+ */
+int cwmp_rpc_acs_prepare_transfer_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *tree, *n;
+ struct transfer_complete *p;
+
+ p = (struct transfer_complete *)rpc->extra_data;
+ load_response_xml_schema(&tree);
+ if (!tree)
+ goto error;
+
+ n = mxmlFindElement(tree, tree, "soap_env:Envelope", NULL, NULL, MXML_DESCEND);
+ if (!n)
+ goto error;
+ mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp->conf.amd_version) - 1]);
+
+ n = build_top_body_soap_request(tree, "TransferComplete");
+ if (!n)
+ goto error;
+
+ struct xml_data_struct transfer_complete_xml_attrs = {0};
+
+ transfer_complete_xml_attrs.command_key = &p->command_key;
+ transfer_complete_xml_attrs.start_time = &p->start_time;
+ transfer_complete_xml_attrs.complete_time = &p->complete_time;
+ int faultcode = p->fault_code ? atoi(FAULT_CPE_ARRAY[p->fault_code].CODE) : 0;
+ transfer_complete_xml_attrs.fault_code = &faultcode;
+ char *faultstring = strdup(p->fault_code ? FAULT_CPE_ARRAY[p->fault_code].DESCRIPTION : "");
+ transfer_complete_xml_attrs.fault_string = &faultstring;
+
+ int fault = build_xml_node_data(SOAP_ACS_TRANSCOMPLETE, n, &transfer_complete_xml_attrs);
+ if (fault != CWMP_OK)
+ goto error;
+
+ FREE(faultstring);
+ session->tree_out = tree;
+
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * [RPC ACS]: DUStateChangeComplete
+ */
+int cwmp_rpc_acs_prepare_du_state_change_complete(struct cwmp *cwmp, struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *tree, *n;
+ struct du_state_change_complete *p;
+
+ p = (struct du_state_change_complete *)rpc->extra_data;
+ load_response_xml_schema(&tree);
+ if (!tree)
+ goto error;
+
+ n = mxmlFindElement(tree, tree, "soap_env:Envelope", NULL, NULL, MXML_DESCEND);
+ if (!n)
+ goto error;
+
+ mxmlElementSetAttr(n, "xmlns:cwmp", cwmp_urls[(cwmp->conf.amd_version) - 1]);
+
+ n = build_top_body_soap_request(tree, "DUStateChangeComplete");
+ if (!n)
+ goto error;
+
+ LIST_HEAD(opt_result_list);
+ cdu_operations_list_to_xml_data_list(&p->list_opresult, &opt_result_list);
+
+ struct xml_data_struct cdu_complete_xml_attrs = {0};
+
+ cdu_complete_xml_attrs.command_key = &p->command_key;
+ cdu_complete_xml_attrs.data_list = &opt_result_list;
+
+ int fault = build_xml_node_data(SOAP_DU_CHANGE_COMPLETE, n, &cdu_complete_xml_attrs);
+ if (fault != CWMP_OK) {
+ cwmp_free_all_xml_data_list(&opt_result_list);
+ goto error;
+ }
+
+ cwmp_free_all_xml_data_list(&opt_result_list);
+ session->tree_out = tree;
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * [RPC CPE]: GetParameterValues
+ */
+int cwmp_handle_rpc_cpe_get_parameter_values(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *b, *parameter_list = NULL;
+ int fault_code = FAULT_CPE_INTERNAL_ERROR;
+ int counter = 0;
+ char c[256];
+
+ if (session->tree_out == NULL)
+ goto fault;
+
+ b = build_top_body_soap_response(session->tree_out, "GetParameterValues");
+
+ struct xml_data_struct gpv_resp_xml_attrs = {0};
+
+ char *xsi_type = "soap_enc:Array";
+ gpv_resp_xml_attrs.xsi_type = &xsi_type;
+ gpv_resp_xml_attrs.parameter_list = ¶meter_list;
+
+ int fault = build_xml_node_data(SOAP_RESP_GPV, b, &gpv_resp_xml_attrs);
+ if (fault != CWMP_OK)
+ goto fault;
+
+ LIST_HEAD(gpv_xml_data_list);
+
+ struct xml_data_struct gpv_xml_attrs = {0};
+ gpv_xml_attrs.data_list = &gpv_xml_data_list;
+ struct xml_tag_validation gpv_validation[] = {{"string", VALIDATE_STR_SIZE, 0, 256}};
+ gpv_xml_attrs.validations = gpv_validation;
+ gpv_xml_attrs.nbre_validations = 1;
+
+ fault = load_xml_node_data(SOAP_REQ_GPV, session->body_in, &gpv_xml_attrs);
+ if (fault) {
+ fault_code = fault;
+ goto fault;
+ }
+
+ struct xml_list_data *p = NULL;
+ struct list_head *l = gpv_xml_data_list.next;
+ while (l != &gpv_xml_data_list) {
+ p = list_entry(l, struct xml_list_data, list);
+ LIST_HEAD(parameters_list);
+ char *err = cwmp_get_parameter_values(p->param_name, ¶meters_list);
+ if (err && !is_obj_excluded(p->param_name)) {
+ fault_code = cwmp_get_fault_code_by_string(err);
+ goto fault;
+ }
+ LIST_HEAD(prameters_xml_list);
+ dm_parameter_list_to_xml_data_list(¶meters_list, &prameters_xml_list);
+
+ struct xml_data_struct prmvalstrct_resp_xml_attrs = {0};
+ prmvalstrct_resp_xml_attrs.counter = &counter;
+ prmvalstrct_resp_xml_attrs.data_list = &prameters_xml_list;
+
+ fault = build_xml_node_data(SOAP_PARAM_STRUCT, parameter_list, &prmvalstrct_resp_xml_attrs);
+ if (fault != CWMP_OK)
+ goto fault;
+
+ cwmp_free_all_dm_parameter_list(¶meters_list);
+ cwmp_free_all_xml_data_list(&prameters_xml_list);
+ l = l->next;
+ }
+ cwmp_free_all_xml_data_list(&gpv_xml_data_list);
+ b = mxmlFindElement(session->tree_out, session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND);
+ if (!b)
+ goto fault;
+
+ if (snprintf(c, sizeof(c), "cwmp:ParameterValueStruct[%d]", counter) == -1)
+ goto fault;
+
+ mxmlElementSetAttr(b, "soap_enc:arrayType", c);
+
+ return 0;
+
+fault:
+ if (cwmp_create_fault_message(session, rpc, fault_code))
+ return -1;
+ return 0;
+}
+
+/*
+ * [RPC CPE]: GetParameterNames
+ */
+int cwmp_handle_rpc_cpe_get_parameter_names(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *n, *b, *parameter_list;
+ char *parameter_name = NULL;
+ bool next_level = true;
+ int counter = 0, fault_code = FAULT_CPE_INTERNAL_ERROR;
+ LIST_HEAD(parameters_list);
+ char c[256];
+
+ struct xml_data_struct gpn_xml_attrs = {0};
+
+ gpn_xml_attrs.next_level = &next_level;
+ gpn_xml_attrs.parameter_path = ¶meter_name;
+ struct xml_tag_validation gpn_validation[] = {{"ParameterPath", VALIDATE_STR_SIZE, 0, 256}, {"NextLevel", VALIDATE_BOOLEAN, 0, 0}};
+ gpn_xml_attrs.validations = gpn_validation;
+ gpn_xml_attrs.nbre_validations = 2;
+
+ int fault = load_xml_node_data(SOAP_REQ_GPN, session->body_in, &gpn_xml_attrs);
+ if (fault != CWMP_OK) {
+ fault_code = fault;
+ goto fault;
+ }
+ char *err = cwmp_get_parameter_names(parameter_name ? parameter_name : "", next_level, ¶meters_list);
+ if (err && !is_obj_excluded(parameter_name)) {
+ fault_code = cwmp_get_fault_code_by_string(err);
+ goto fault;
+ }
+ FREE(parameter_name);
+
+ if (session->tree_out == NULL)
+ goto fault;
+
+ n = build_top_body_soap_response(session->tree_out, "GetParameterNames");
+
+ if (!n){
+ fault_code = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ parameter_list = mxmlNewElement(n, "ParameterList");
+ if (!parameter_list){
+ fault_code = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ mxmlElementSetAttr(parameter_list, "xsi:type", "soap_enc:Array");
+
+ LIST_HEAD(prameters_xml_list);
+ dm_parameter_list_to_xml_data_list(¶meters_list, &prameters_xml_list);
+
+ struct xml_data_struct gpv_resp_xml_attrs = {0};
+ gpv_resp_xml_attrs.data_list = &prameters_xml_list;
+ gpv_resp_xml_attrs.counter = &counter;
+
+ fault = build_xml_node_data(SOAP_RESP_GPN, parameter_list, &gpv_resp_xml_attrs);
+ if (fault != CWMP_OK)
+ goto fault;
+
+ cwmp_free_all_dm_parameter_list(¶meters_list);
+ cwmp_free_all_xml_data_list(&prameters_xml_list);
+
+ b = mxmlFindElement(session->tree_out, session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND);
+ if (!b)
+ goto fault;
+
+ if (snprintf(c, sizeof(c), "cwmp:ParameterInfoStruct[%d]", counter) == -1)
+ goto fault;
+
+ mxmlElementSetAttr(b, "soap_enc:arrayType", c);
+ return 0;
+
+fault:
+ cwmp_free_all_dm_parameter_list(¶meters_list);
+ if (cwmp_create_fault_message(session, rpc, fault_code))
+ return -1;
+ return 0;
+}
+
+/*
+ * [RPC CPE]: GetParameterAttributes
+ */
+int cwmp_handle_rpc_cpe_get_parameter_attributes(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *n, *parameter_list, *b;
+ int counter = 0, fault_code = FAULT_CPE_INTERNAL_ERROR;
+ char c[256];
+ b = session->body_in;
+
+ n = build_top_body_soap_response(session->tree_out, "GetParameterAttributes");
+ if (!n)
+ goto fault;
+
+ parameter_list = mxmlNewElement(n, "ParameterList");
+ if (!parameter_list)
+ goto fault;
+
+ mxmlElementSetAttr(parameter_list, "xsi:type", "soap_enc:Array");
+
+ LIST_HEAD(gpa_xml_data_list);
+
+
+ struct xml_data_struct gpa_xml_attrs = {0};
+ gpa_xml_attrs.data_list = &gpa_xml_data_list;
+ struct xml_tag_validation gpa_validation[] = {{"string", VALIDATE_STR_SIZE, 0, 256}};
+ gpa_xml_attrs.validations = gpa_validation;
+ gpa_xml_attrs.nbre_validations = 1;
+
+ int fault = load_xml_node_data(SOAP_REQ_GPA, b, &gpa_xml_attrs);
+ if (fault) {
+ fault_code = fault;
+ goto fault;
+ }
+
+ struct xml_list_data *p = NULL;
+ struct list_head*l= gpa_xml_data_list.next;
+ while (l != &gpa_xml_data_list) {
+ p = list_entry(l, struct xml_list_data, list);
+ LIST_HEAD(parameters_list);
+ char *err = cwmp_get_parameter_attributes(p->param_name, ¶meters_list);
+ if (err && !is_obj_excluded(p->param_name)) {
+ fault_code = cwmp_get_fault_code_by_string(err);
+ cwmp_free_all_dm_parameter_list(¶meters_list);
+ cwmp_free_all_xml_data_list(&gpa_xml_data_list);
+ goto fault;
+ }
+ LIST_HEAD(parameters_xml_list);
+ dm_parameter_list_to_xml_data_list(¶meters_list, ¶meters_xml_list);
+
+ struct xml_data_struct gpv_resp_xml_attrs = {0};
+ gpv_resp_xml_attrs.counter = &counter;
+ gpv_resp_xml_attrs.data_list = ¶meters_xml_list;
+ fault = build_xml_node_data(SOAP_RESP_GPA, parameter_list, &gpv_resp_xml_attrs);
+ if (fault != CWMP_OK)
+ goto fault;
+
+ cwmp_free_all_xml_data_list(¶meters_xml_list);
+ l = l->next;
+ }
+ cwmp_free_all_xml_data_list(&gpa_xml_data_list);
+
+ b = mxmlFindElement(session->tree_out, session->tree_out, "ParameterList", NULL, NULL, MXML_DESCEND);
+ if (!b)
+ goto fault;
+
+ if (snprintf(c, sizeof(c), "cwmp:ParameterAttributeStruct[%d]", counter) == -1)
+ goto fault;
+
+ mxmlElementSetAttr(b, "soap_enc:arrayType", c);
+ return 0;
+
+fault:
+ if (cwmp_create_fault_message(session, rpc, fault_code))
+ return -1;
+ return 0;
+}
+
+/*
+ * [RPC CPE]: SetParameterValues
+ */
+int is_duplicated_parameter(mxml_node_t *param_node, struct session *session)
+{
+ mxml_node_t *b = param_node;
+ while ((b = mxmlWalkNext(b, session->body_in, MXML_DESCEND))) {
+ const char *node_opaque = mxmlGetOpaque(b);
+ mxml_node_t *parent = mxmlGetParent(b);
+ mxml_type_t node_type = mxmlGetType(b);
+
+ if (node_type == MXML_OPAQUE && node_opaque && mxmlGetType(parent) == MXML_ELEMENT && !strcmp(mxmlGetElement(parent), "Name")) {
+ if (strcmp(node_opaque, mxmlGetOpaque(param_node)) == 0)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int cwmp_handle_rpc_cpe_set_parameter_values(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *b = NULL;
+ char *parameter_key = NULL;
+ int fault_code = FAULT_CPE_INTERNAL_ERROR, ret = 0;
+
+ LIST_HEAD(xml_list_set_param_value);
+ LIST_HEAD(list_set_param_value);
+ LIST_HEAD(list_fault_param);
+
+ rpc->list_set_value_fault = &list_fault_param;
+ struct xml_tag_validation spv_validation[] = {{"ParameterKey", VALIDATE_STR_SIZE, 0, 32}, {"Name", VALIDATE_STR_SIZE, 0, 256}};
+ struct xml_data_struct spv_xml_attrs = {0};
+ spv_xml_attrs.parameter_key = ¶meter_key;
+ spv_xml_attrs.data_list = &xml_list_set_param_value;
+ spv_xml_attrs.validations = spv_validation;
+ spv_xml_attrs.nbre_validations = 2;
+
+ int fault = load_xml_node_data(SOAP_REQ_SPV, session->body_in, &spv_xml_attrs);
+ if (fault) {
+ fault_code = fault;
+ goto fault;
+ }
+
+ xml_data_list_to_dm_parameter_list(&xml_list_set_param_value, &list_set_param_value);
+
+ int flag = 0;
+ if (transaction_id == 0) {
+ if (!cwmp_transaction_start("cwmp")) {
+ fault_code = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+ }
+
+ fault_code = cwmp_set_multiple_parameters_values(&list_set_param_value, parameter_key ? parameter_key : "", &flag, rpc->list_set_value_fault);
+ if (fault_code != FAULT_CPE_NO_FAULT)
+ goto fault;
+
+ FREE(parameter_key);
+ struct cwmp_dm_parameter *param_value;
+ // cppcheck-suppress unknownMacro
+ list_for_each_entry (param_value, &list_set_param_value, list)
+ set_diagnostic_parameter_structure_value(param_value->name, param_value->value);
+
+ cwmp_free_all_xml_data_list(&xml_list_set_param_value);
+ cwmp_free_all_dm_parameter_list(&list_set_param_value);
+
+ b = build_top_body_soap_response(session->tree_out, "SetParameterValues");
+
+ if (!b) {
+ fault_code = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ int status = 1;
+
+ struct xml_data_struct spv_resp_xml_attrs = {.status = &status};
+ fault = build_xml_node_data(SOAP_RESP_SPV, b, &spv_resp_xml_attrs);
+ if (fault)
+ goto fault;
+
+ if (!cwmp_transaction_commit()) {
+ fault_code = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ cwmp_set_end_session(flag | END_SESSION_RESTART_SERVICES | END_SESSION_SET_NOTIFICATION_UPDATE | END_SESSION_RELOAD);
+ return 0;
+
+fault:
+ cwmp_free_all_dm_parameter_list(&list_set_param_value);
+ if (cwmp_create_fault_message(session, rpc, fault_code))
+ ret = CWMP_XML_ERR;
+
+ cwmp_free_all_list_param_fault(rpc->list_set_value_fault);
+ if (transaction_id) {
+ cwmp_transaction_abort();
+ transaction_id = 0;
+ }
+ return ret;
+}
+
+/*
+ * [RPC CPE]: SetParameterAttributes
+ */
+int cwmp_handle_rpc_cpe_set_parameter_attributes(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *n;
+ int fault_code = FAULT_CPE_INTERNAL_ERROR, ret = 0;
+ char c[256];
+
+ if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "SetParameterAttributes") == -1)
+ goto fault;
+
+ n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
+
+ if (!n)
+ goto fault;
+
+ LIST_HEAD(prameters_xml_list);
+ struct xml_data_struct spa_xml_attrs = {0};
+ spa_xml_attrs.data_list = &prameters_xml_list;
+ struct xml_tag_validation spa_validation[] = {{"Name", VALIDATE_STR_SIZE, 0, 256}, {"NotificationChange", VALIDATE_BOOLEAN, 0, 0}, {"Notification", VALIDATE_INT_RANGE, 0, 6}};
+ spa_xml_attrs.validations = spa_validation;
+ spa_xml_attrs.nbre_validations = 3;
+
+ fault_code = load_xml_node_data(SOAP_REQ_SPA, n, &spa_xml_attrs);
+ if (fault_code)
+ goto fault;
+ struct list_head *l = prameters_xml_list.next;
+ struct xml_list_data *p = NULL;
+ while (l != &prameters_xml_list) {
+ p = list_entry(l, struct xml_list_data, list);
+ if (p->param_name && p->notification_change) {
+ char *err = cwmp_set_parameter_attributes(p->param_name, p->notification);
+ if (err) {
+ fault_code = cwmp_get_fault_code_by_string(err);
+ goto fault;
+ }
+ }
+ l = l->next;
+ }
+ cwmp_free_all_xml_data_list(&prameters_xml_list);
+
+ mxml_node_t *resp = build_top_body_soap_response(session->tree_out, "SetParameterAttributes");
+ if (!resp)
+ goto fault;
+
+ cwmp_set_end_session(END_SESSION_SET_NOTIFICATION_UPDATE | END_SESSION_RESTART_SERVICES | END_SESSION_INIT_NOTIFY);
+ return 0;
+
+fault:
+ if (cwmp_create_fault_message(session, rpc, fault_code))
+ ret = CWMP_XML_ERR;
+
+ return ret;
+}
+
+/*
+ * [RPC CPE]: AddObject
+ */
+int cwmp_handle_rpc_cpe_add_object(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *b;
+ char *object_name = NULL;
+ char *parameter_key = NULL;
+ int fault_code = FAULT_CPE_INTERNAL_ERROR, ret = 0;
+ char *instance = NULL;
+
+ struct xml_data_struct add_obj_xml_attrs = {0};
+ add_obj_xml_attrs.object_name = &object_name;
+ add_obj_xml_attrs.parameter_key = ¶meter_key;
+ struct xml_tag_validation gpn_validation[] = {{"ParameterKey", VALIDATE_STR_SIZE, 0, 32}, {"ObjectName", VALIDATE_STR_SIZE, 0, 256}};
+ add_obj_xml_attrs.validations = gpn_validation;
+ add_obj_xml_attrs.nbre_validations = 2;
+
+ int fault = load_xml_node_data(SOAP_REQ_ADDOBJ, session->body_in, &add_obj_xml_attrs);
+
+ if (fault) {
+ fault_code = fault;
+ goto fault;
+ }
+
+ if (transaction_id == 0) {
+ if (!cwmp_transaction_start("cwmp")) {
+ fault_code = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+ }
+
+ if (object_name) {
+ char *err = cwmp_add_object(object_name, parameter_key ? parameter_key : "", &instance);
+ if (err) {
+ fault_code = cwmp_get_fault_code_by_string(err);
+ goto fault;
+ }
+ } else {
+ fault_code = FAULT_CPE_INVALID_PARAMETER_NAME;
+ goto fault;
+ }
+ if (instance == NULL) {
+ fault_code = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+ b = build_top_body_soap_response(session->tree_out, "AddObject");
+
+ if (!b) {
+ fault_code = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ int instance_int = atoi(instance);
+ int status = 1;
+ struct xml_data_struct add_resp_xml_attrs = {0};
+ add_resp_xml_attrs.instance = &instance_int;
+ add_resp_xml_attrs.status = &status;
+
+ fault = build_xml_node_data(SOAP_RESP_ADDOBJ, b, &add_resp_xml_attrs);
+ if (fault != CWMP_OK)
+ goto fault;
+
+ if (!cwmp_transaction_commit()) {
+ fault_code = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ char *object_path = NULL;
+ icwmp_asprintf(&object_path, "%s%s.", object_name, instance);
+ cwmp_set_parameter_attributes(object_path, 0);
+ FREE(object_name);
+ FREE(parameter_key);
+ FREE(instance);
+ cwmp_set_end_session(END_SESSION_RESTART_SERVICES);
+ return 0;
+
+fault:
+ FREE(object_name);
+ FREE(parameter_key);
+ FREE(instance);
+ if (cwmp_create_fault_message(session, rpc, fault_code))
+ ret = CWMP_XML_ERR;
+ if (transaction_id) {
+ cwmp_transaction_abort();
+ transaction_id = 0;
+ }
+ return ret;
+}
+
+/*
+ * [RPC CPE]: DeleteObject
+ */
+int cwmp_handle_rpc_cpe_delete_object(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *b;
+ char *object_name = NULL;
+ char *parameter_key = NULL;
+ int fault_code = FAULT_CPE_INTERNAL_ERROR, ret = 0;
+
+ struct xml_data_struct del_obj_xml_attrs = {0};
+ del_obj_xml_attrs.object_name = &object_name;
+ del_obj_xml_attrs.parameter_key = ¶meter_key;
+ struct xml_tag_validation gpn_validation[] = {{"ParameterKey", VALIDATE_STR_SIZE, 0, 32}, {"ObjectName", VALIDATE_STR_SIZE, 0, 256}};
+ del_obj_xml_attrs.validations = gpn_validation;
+ del_obj_xml_attrs.nbre_validations = 2;
+
+ int fault = load_xml_node_data(SOAP_REQ_DELOBJ, session->body_in, &del_obj_xml_attrs);
+
+ if (fault) {
+ fault_code = fault;
+ goto fault;
+ }
+
+ if (transaction_id == 0) {
+ if (!cwmp_transaction_start("cwmp"))
+ goto fault;
+ }
+ if (object_name) {
+ char *err = cwmp_delete_object(object_name, parameter_key ? parameter_key : "");
+ if (err) {
+ fault_code = cwmp_get_fault_code_by_string(err);
+ goto fault;
+ }
+ } else {
+ fault_code = FAULT_CPE_INVALID_PARAMETER_NAME;
+ goto fault;
+ }
+
+ b = build_top_body_soap_response(session->tree_out, "DeleteObject");
+
+ if (!b) {
+ fault_code = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ int status = 1;
+ struct xml_data_struct add_resp_xml_attrs = {0};
+ add_resp_xml_attrs.status = &status;
+
+ fault = build_xml_node_data(SOAP_RESP_DELOBJ, b, &add_resp_xml_attrs);
+ if (fault != CWMP_OK)
+ goto fault;
+
+ if (!cwmp_transaction_commit()) {
+ fault_code = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+ FREE(object_name);
+ FREE(parameter_key);
+ cwmp_set_end_session(END_SESSION_RESTART_SERVICES);
+ return 0;
+
+fault:
+ FREE(object_name);
+ FREE(parameter_key);
+ if (cwmp_create_fault_message(session, rpc, fault_code))
+ ret = CWMP_XML_ERR;
+ if (transaction_id) {
+ cwmp_transaction_abort();
+ transaction_id = 0;
+ }
+ return ret;
+}
+
+/*
+ * [RPC CPE]: GetRPCMethods
+ */
+int cwmp_handle_rpc_cpe_get_rpc_methods(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *n, *method_list;
+ int i, counter = 0;
+ mxml_node_t *b = session->body_in;
+ char c[128];
+
+ n = build_top_body_soap_response(session->tree_out, "GetRPCMethods");
+
+ if (!n)
+ goto fault;
+
+
+ LIST_HEAD(rpcs_list);
+
+ for (i = 1; i < __RPC_CPE_MAX; i++) {
+ if (i != RPC_CPE_FAULT) {
+ struct xml_list_data *xml_data = calloc(1, sizeof(struct xml_list_data));
+ xml_data->rpc_name = strdup(rpc_cpe_methods[i].name);
+ list_add(&(xml_data->list), &rpcs_list);
+ counter++;
+ }
+ }
+
+ method_list = mxmlNewElement(n, "MethodList");
+ if (!method_list)
+ goto fault;
+
+ struct xml_data_struct getrpc_resp_xml_attrs = {0};
+ getrpc_resp_xml_attrs.data_list = &rpcs_list;
+
+ int fault = build_xml_node_data(SOAP_RESP_GETRPC, method_list, &getrpc_resp_xml_attrs);
+ if (fault != CWMP_OK)
+ goto fault;
+
+ cwmp_free_all_xml_data_list(&rpcs_list);
+ b = mxmlFindElement(session->tree_out, session->tree_out, "MethodList", NULL, NULL, MXML_DESCEND);
+ if (!b)
+ goto fault;
+
+ mxmlElementSetAttr(b, "xsi:type", "soap_enc:Array");
+ if (snprintf(c, sizeof(c), "xsd:string[%d]", counter) == -1)
+ goto fault;
+
+ mxmlElementSetAttr(b, "soap_enc:arrayType", c);
+
+ return 0;
+
+fault:
+ if (cwmp_create_fault_message(session, rpc, FAULT_CPE_INTERNAL_ERROR))
+ goto error;
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * [RPC CPE]: FactoryReset
+ */
+int cwmp_handle_rpc_cpe_factory_reset(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *b;
+
+ b = build_top_body_soap_response(session->tree_out, "FactoryReset");
+
+ if (!b)
+ goto fault;
+
+ cwmp_set_end_session(END_SESSION_FACTORY_RESET);
+
+ return 0;
+
+fault:
+ if (cwmp_create_fault_message(session, rpc, FAULT_CPE_INTERNAL_ERROR))
+ goto error;
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * [RPC CPE]: X_FactoryResetSoft
+ */
+int cwmp_handle_rpc_cpe_x_factory_reset_soft(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *b;
+
+ b = build_top_body_soap_response(session->tree_out, "X_FactoryResetSoft");
+
+ if (!b)
+ goto fault;
+
+ cwmp_set_end_session(END_SESSION_X_FACTORY_RESET_SOFT);
+
+ return 0;
+
+fault:
+ if (cwmp_create_fault_message(session, rpc, FAULT_CPE_INTERNAL_ERROR))
+ goto error;
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * [RPC CPE]: CancelTransfer
+ */
+int cwmp_handle_rpc_cpe_cancel_transfer(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *b;
+ char *command_key = NULL;
+ int fault_code = FAULT_CPE_INTERNAL_ERROR;
+ b = session->body_in;
+
+ struct xml_data_struct canceltrancer_obj_xml_attrs = {0};
+ canceltrancer_obj_xml_attrs.command_key = &command_key;
+ struct xml_tag_validation canceltransfer_validation[] = {{"CommandKey", VALIDATE_STR_SIZE, 0, 32}};
+ canceltrancer_obj_xml_attrs.validations = canceltransfer_validation;
+ canceltrancer_obj_xml_attrs.nbre_validations = 1;
+
+ fault_code = load_xml_node_data(SOAP_REQ_CANCELTRANSFER, session->body_in, &canceltrancer_obj_xml_attrs);
+
+ if (command_key)
+ cancel_transfer(command_key);
+
+ if (fault_code)
+ goto fault;
+
+ b = build_top_body_soap_response(session->tree_out, "CancelTransfer");
+
+ if (!b) {
+ fault_code = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+ FREE(command_key);
+ return 0;
+
+fault:
+ FREE(command_key);
+ if (cwmp_create_fault_message(session, rpc, fault_code))
+ goto error;
+ return 0;
+
+error:
+ return -1;
+}
+
+int cancel_transfer(char *key)
+{
+ struct list_head *ilist, *q;
+
+ if (list_download.next != &(list_download)) {
+ list_for_each_safe (ilist, q, &(list_download)) {
+ struct download *pdownload = list_entry(ilist, struct download, list);
+ if (strcmp(pdownload->command_key, key) == 0) {
+ pthread_mutex_lock(&mutex_download);
+ bkp_session_delete_download(pdownload);
+ bkp_session_save();
+ list_del(&(pdownload->list));
+ if (pdownload->scheduled_time != 0)
+ count_download_queue--;
+ cwmp_free_download_request(pdownload);
+ pthread_mutex_unlock(&mutex_download);
+ }
+ }
+ }
+ if (list_upload.next != &(list_upload)) {
+ list_for_each_safe (ilist, q, &(list_upload)) {
+ struct upload *pupload = list_entry(ilist, struct upload, list);
+ if (strcmp(pupload->command_key, key) == 0) {
+ pthread_mutex_lock(&mutex_upload);
+ bkp_session_delete_upload(pupload);
+ bkp_session_save();
+ list_del(&(pupload->list));
+ if (pupload->scheduled_time != 0)
+ count_download_queue--;
+ cwmp_free_upload_request(pupload);
+ pthread_mutex_unlock(&mutex_upload);
+ }
+ }
+ }
+ // Cancel schedule download
+ return CWMP_OK;
+}
+
+/*
+ * [RPC CPE]: Reboot
+ */
+int cwmp_handle_rpc_cpe_reboot(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *b;
+ struct event_container *event_container;
+ char *command_key = NULL;
+ int fault_code = FAULT_CPE_INTERNAL_ERROR;
+ b = session->body_in;
+
+ struct xml_data_struct reboot_obj_xml_attrs = {0};
+ reboot_obj_xml_attrs.command_key = &command_key;
+ struct xml_tag_validation reboot_validation[] = {{"CommandKey", VALIDATE_STR_SIZE, 0, 32}};
+ reboot_obj_xml_attrs.validations = reboot_validation;
+ reboot_obj_xml_attrs.nbre_validations = 1;
+
+ fault_code = load_xml_node_data(SOAP_REQ_REBOOT, session->body_in, &reboot_obj_xml_attrs);
+
+ if (fault_code)
+ goto fault;
+
+ commandKey = icwmp_strdup(command_key);
+
+ pthread_mutex_lock(&(cwmp_main.mutex_session_queue));
+ event_container = cwmp_add_event_container(&cwmp_main, EVENT_IDX_M_Reboot, command_key);
+ if (event_container == NULL) {
+ pthread_mutex_unlock(&(cwmp_main.mutex_session_queue));
+ goto fault;
+ }
+ cwmp_save_event_container(event_container);
+ pthread_mutex_unlock(&(cwmp_main.mutex_session_queue));
+
+ b = build_top_body_soap_response(session->tree_out, "Reboot");
+
+ if (!b)
+ goto fault;
+
+ cwmp_set_end_session(END_SESSION_REBOOT);
+
+ FREE(command_key);
+ return 0;
+
+fault:
+FREE(command_key);
+ if (cwmp_create_fault_message(session, rpc, fault_code))
+ goto error;
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * [RPC CPE]: ScheduleInform
+ */
+int cwmp_handle_rpc_cpe_schedule_inform(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *n;
+ char *command_key = NULL;
+ struct schedule_inform *schedule_inform;
+ time_t scheduled_time;
+ struct list_head *ilist;
+ int fault = FAULT_CPE_NO_FAULT;
+ int delay_seconds = 0;
+
+
+ pthread_mutex_lock(&mutex_schedule_inform);
+
+ struct xml_data_struct schedinform_obj_xml_attrs = {0};
+ schedinform_obj_xml_attrs.command_key = &command_key;
+ schedinform_obj_xml_attrs.delay_seconds = (long int*)&delay_seconds;
+ struct xml_tag_validation schedinform_validation[] = {{"CommandKey", VALIDATE_STR_SIZE, 0, 32}, {"DelaySeconds", VALIDATE_UNINT, 0, 0}};
+ schedinform_obj_xml_attrs.validations = schedinform_validation;
+ schedinform_obj_xml_attrs.nbre_validations = 2;
+
+ fault = load_xml_node_data(SOAP_REQ_SCHEDINF, session->body_in, &schedinform_obj_xml_attrs);
+
+ FREE(command_key);
+ if (fault)
+ goto fault;
+
+ if (count_schedule_inform_queue >= MAX_SCHEDULE_INFORM_QUEUE) {
+ fault = FAULT_CPE_RESOURCES_EXCEEDED;
+ pthread_mutex_unlock(&mutex_schedule_inform);
+ goto fault;
+ }
+ count_schedule_inform_queue++;
+
+ scheduled_time = time(NULL) + delay_seconds;
+ list_for_each (ilist, &(list_schedule_inform)) {
+ schedule_inform = list_entry(ilist, struct schedule_inform, list);
+ if (schedule_inform->scheduled_time >= scheduled_time) {
+ break;
+ }
+ }
+
+ n = build_top_body_soap_response(session->tree_out, "ScheduleInform");
+
+ if (!n)
+ goto fault;
+
+ CWMP_LOG(INFO, "Schedule inform event will start in %us", delay_seconds);
+ schedule_inform = calloc(1, sizeof(struct schedule_inform));
+ if (schedule_inform == NULL) {
+ pthread_mutex_unlock(&mutex_schedule_inform);
+ goto fault;
+ }
+ schedule_inform->commandKey = strdup(command_key);
+ schedule_inform->scheduled_time = scheduled_time;
+ list_add(&(schedule_inform->list), ilist->prev);
+ bkp_session_insert_schedule_inform(schedule_inform->scheduled_time, schedule_inform->commandKey);
+ bkp_session_save();
+ pthread_mutex_unlock(&mutex_schedule_inform);
+ pthread_cond_signal(&threshold_schedule_inform);
+
+success:
+ return 0;
+
+fault:
+ if (cwmp_create_fault_message(session, rpc, fault ? fault : FAULT_CPE_INTERNAL_ERROR))
+ goto error;
+ goto success;
+
+error:
+ return -1;
+}
+
+/*
+ * [RPC CPE]: ChangeDuState
+ */
+int cwmp_handle_rpc_cpe_change_du_state(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *n, *t;
+ struct change_du_state *change_du_state = NULL;
+ int error = FAULT_CPE_NO_FAULT;
+ char c[256];
+
+ if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "ChangeDUState") == -1) {
+ error = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
+
+ if (!n)
+ return -1;
+
+ change_du_state = calloc(1, sizeof(struct change_du_state));
+ if (change_du_state == NULL) {
+ error = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ INIT_LIST_HEAD(&(change_du_state->list_operation));
+ change_du_state->timeout = time(NULL);
+
+ LIST_HEAD(xml_list_operations);
+ struct xml_data_struct cdu_xml_attrs = {0};
+ cdu_xml_attrs.command_key = &change_du_state->command_key;
+ cdu_xml_attrs.data_list = &xml_list_operations;
+ struct xml_tag_validation cdu_validation[] = {{"CommandKey", VALIDATE_STR_SIZE, 0, 32}, {"URL", VALIDATE_STR_SIZE, 0, 1024}, {"UUID", VALIDATE_STR_SIZE, 0, 36}, {"Username", VALIDATE_STR_SIZE, 0, 256}, {"Password", VALIDATE_STR_SIZE, 0, 256}, {"ExecutionEnvRef", VALIDATE_STR_SIZE, 0, 256}, {"Version", VALIDATE_STR_SIZE, 0, 32}};
+ cdu_xml_attrs.validations = cdu_validation;
+ cdu_xml_attrs.nbre_validations = 7;
+
+ error = load_xml_node_data(SOAP_REQ_CDU, n, &cdu_xml_attrs);
+
+ if (error)
+ goto fault;
+
+ xml_data_list_to_cdu_operations_list(&xml_list_operations, &change_du_state->list_operation);
+
+ t = build_top_body_soap_response(session->tree_out, "ChangeDUState");
+
+ if (!t)
+ goto fault;
+
+ if (error == FAULT_CPE_NO_FAULT) {
+ pthread_mutex_lock(&mutex_change_du_state);
+ list_add_tail(&(change_du_state->list), &(list_change_du_state));
+ bkp_session_insert_change_du_state(change_du_state);
+ bkp_session_save();
+ pthread_mutex_unlock(&mutex_change_du_state);
+ pthread_cond_signal(&threshold_change_du_state);
+ }
+ return 0;
+
+fault:
+ cwmp_free_change_du_state_request(change_du_state);
+ if (cwmp_create_fault_message(session, rpc, error))
+ goto error;
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * [RPC CPE]: Download
+ */
+int cwmp_handle_rpc_cpe_download(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *n;
+ char c[256];
+ int error = FAULT_CPE_NO_FAULT;
+ struct download *download = NULL, *idownload;
+ struct list_head *ilist;
+ time_t scheduled_time = 0;
+ time_t download_delay = 0;
+
+ if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "Download") == -1) {
+ error = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
+
+ if (!n)
+ return -1;
+
+ download = calloc(1, sizeof(struct download));
+ if (download == NULL) {
+ error = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ struct xml_data_struct download_xml_attrs = {0};
+ download_xml_attrs.command_key = &download->command_key;
+ download_xml_attrs.url = &download->url;
+ download_xml_attrs.username = &download->username;
+ download_xml_attrs.password = &download->password;
+ download_xml_attrs.delay_seconds = (long int*)&download_delay;
+ download_xml_attrs.file_type = &download->file_type;
+ download_xml_attrs.file_size = &download->file_size;
+
+ struct xml_tag_validation download_validation[] = {{"CommandKey", VALIDATE_STR_SIZE, 0, 32}, {"FileType", VALIDATE_STR_SIZE, 0, 64}, {"URL", VALIDATE_STR_SIZE, 0, 256}, {"Username", VALIDATE_STR_SIZE, 0, 256}, {"Password", VALIDATE_STR_SIZE, 0, 256}, {"FileSize", VALIDATE_UNINT, 0, 0}, {"DelaySeconds", VALIDATE_UNINT, 0, 0}};
+ download_xml_attrs.validations = download_validation;
+ download_xml_attrs.nbre_validations = 7;
+
+ int fault = load_xml_node_data(SOAP_REQ_DOWNLOAD, n, &download_xml_attrs);
+
+ if (fault) {
+ error = fault;
+ goto fault;
+ }
+
+ if (strcmp(download->file_type, FIRMWARE_UPGRADE_IMAGE_FILE_TYPE) && strcmp(download->file_type, WEB_CONTENT_FILE_TYPE) && strcmp(download->file_type, VENDOR_CONFIG_FILE_TYPE) && strcmp(download->file_type, TONE_FILE_TYPE) && strcmp(download->file_type, RINGER_FILE_TYPE) && strcmp(download->file_type, STORED_FIRMWARE_IMAGE_FILE_TYPE)) {
+ error = FAULT_CPE_INVALID_ARGUMENTS;
+ } else if (count_download_queue >= MAX_DOWNLOAD_QUEUE) {
+ error = FAULT_CPE_RESOURCES_EXCEEDED;
+ } else if (download->url == NULL || (strcmp(download->url, "") == 0)) {
+ error = FAULT_CPE_REQUEST_DENIED;
+ } else if (strstr(download->url, "@") != NULL) {
+ error = FAULT_CPE_INVALID_ARGUMENTS;
+ } else if (strncmp(download->url, DOWNLOAD_PROTOCOL_HTTP, strlen(DOWNLOAD_PROTOCOL_HTTP)) != 0 && strncmp(download->url, DOWNLOAD_PROTOCOL_HTTPS, strlen(DOWNLOAD_PROTOCOL_HTTPS)) != 0 && strncmp(download->url, DOWNLOAD_PROTOCOL_FTP, strlen(DOWNLOAD_PROTOCOL_FTP)) != 0) {
+ error = FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL;
+ }
+ if (error != FAULT_CPE_NO_FAULT)
+ goto fault;
+
+ mxml_node_t *t = build_top_body_soap_response(session->tree_out, "Download");
+ char *start_time = "0001-01-01T00:00:00+00:00";
+ char *complete_time = "0001-01-01T00:00:00+00:00";
+ int status = 1;
+
+ struct xml_data_struct download_resp_xml_attrs = {0};
+ download_resp_xml_attrs.status = &status;
+ download_resp_xml_attrs.start_time = &start_time;
+ download_resp_xml_attrs.complete_time = &complete_time;
+ fault = build_xml_node_data(SOAP_RESP_DOWNLOAD, t, &download_resp_xml_attrs);
+ if (fault != CWMP_OK) {
+ error = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ if (error == FAULT_CPE_NO_FAULT) {
+ pthread_mutex_lock(&mutex_download);
+ if (download_delay != 0)
+ scheduled_time = time(NULL) + download_delay + PROCESSING_DELAY;
+
+ list_for_each (ilist, &(list_download)) {
+ idownload = list_entry(ilist, struct download, list);
+ if (idownload->scheduled_time >= scheduled_time) {
+ break;
+ }
+ }
+ list_add(&(download->list), ilist->prev);
+ if (download_delay != 0) {
+ count_download_queue++;
+ download->scheduled_time = scheduled_time;
+ }
+ bkp_session_insert_download(download);
+ bkp_session_save();
+ if (download_delay != 0) {
+ CWMP_LOG(INFO, "Download will start in %us", download_delay);
+ } else {
+ CWMP_LOG(INFO, "Download will start at the end of session");
+ }
+
+ pthread_mutex_unlock(&mutex_download);
+ pthread_cond_signal(&threshold_download);
+ }
+
+ return 0;
+
+fault:
+ cwmp_free_download_request(download);
+ if (cwmp_create_fault_message(session, rpc, error))
+ return -1;
+ return 0;
+}
+
+/*
+ * [RPC CPE]: ScheduleDownload
+ */
+int cwmp_handle_rpc_cpe_schedule_download(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *n, *t;
+ char c[256];
+ int i = 0, j = 0;
+ int error = FAULT_CPE_NO_FAULT;
+ struct download *schedule_download = NULL;
+ time_t schedule_download_delay[4] = { 0, 0, 0, 0 };
+
+ if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "ScheduleDownload") == -1) {
+ error = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
+
+ if (!n)
+ return -1;
+
+ schedule_download = calloc(1, sizeof(struct download));
+ if (schedule_download == NULL) {
+ error = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ struct xml_data_struct sched_download_xml_attrs = {0};
+ sched_download_xml_attrs.command_key = &schedule_download->command_key;
+ sched_download_xml_attrs.url = &schedule_download->url;
+ sched_download_xml_attrs.username = &schedule_download->username;
+ sched_download_xml_attrs.password = &schedule_download->password;
+ sched_download_xml_attrs.file_type = &schedule_download->file_type;
+ sched_download_xml_attrs.file_size = &schedule_download->file_size;
+
+ struct xml_tag_validation scheddownload_validation[] = {{"CommandKey", VALIDATE_STR_SIZE, 0, 32}, {"FileType", VALIDATE_STR_SIZE, 0, 64}, {"URL", VALIDATE_STR_SIZE, 0, 256}, {"Username", VALIDATE_STR_SIZE, 0, 256}, {"Password", VALIDATE_STR_SIZE, 0, 256}, {"FileSize", VALIDATE_UNINT, 0, 0}};
+ sched_download_xml_attrs.validations = scheddownload_validation;
+ sched_download_xml_attrs.nbre_validations = 6;
+
+ LIST_HEAD(time_window_intervals);
+ sched_download_xml_attrs.data_list = &time_window_intervals;
+
+ error = load_xml_node_data(SOAP_REQ_SCHEDDOWN, n, &sched_download_xml_attrs);
+
+ if (error)
+ goto fault;
+
+ struct xml_list_data *list_data = NULL;
+ if (time_window_intervals.next) {
+ list_data = container_of(time_window_intervals.next, struct xml_list_data, list);
+ schedule_download->timewindowstruct[0].windowmode = list_data->windowmode;
+ schedule_download->timewindowstruct[0].usermessage = list_data->usermessage;
+ schedule_download->timewindowstruct[0].maxretries = list_data->max_retries;
+ schedule_download->timewindowstruct[0].windowstart = list_data->windowstart;
+ schedule_download->timewindowstruct[0].windowend = list_data->windowend;
+ if (time_window_intervals.next->next) {
+ list_data = container_of(time_window_intervals.next->next, struct xml_list_data, list);
+ schedule_download->timewindowstruct[1].windowmode = list_data->windowmode;
+ schedule_download->timewindowstruct[1].usermessage = list_data->usermessage;
+ schedule_download->timewindowstruct[1].maxretries = list_data->max_retries;
+ schedule_download->timewindowstruct[1].windowstart = list_data->windowstart;
+ schedule_download->timewindowstruct[1].windowend = list_data->windowend;
+ }
+ }
+
+ if (strcmp(schedule_download->file_type, FIRMWARE_UPGRADE_IMAGE_FILE_TYPE) && strcmp(schedule_download->file_type, WEB_CONTENT_FILE_TYPE) && strcmp(schedule_download->file_type, VENDOR_CONFIG_FILE_TYPE) && strcmp(schedule_download->file_type, TONE_FILE_TYPE) && strcmp(schedule_download->file_type, RINGER_FILE_TYPE) && strcmp(schedule_download->file_type, STORED_FIRMWARE_IMAGE_FILE_TYPE)) {
+ error = FAULT_CPE_INVALID_ARGUMENTS;
+ } else if ((strcmp(schedule_download->timewindowstruct[0].windowmode, "1 At Any Time") && strcmp(schedule_download->timewindowstruct[0].windowmode, "2 Immediately") && strcmp(schedule_download->timewindowstruct[0].windowmode, "3 When Idle")) || (strcmp(schedule_download->timewindowstruct[1].windowmode, "1 At Any Time") && strcmp(schedule_download->timewindowstruct[1].windowmode, "2 Immediately") && strcmp(schedule_download->timewindowstruct[1].windowmode, "3 When Idle"))) {
+ error = FAULT_CPE_REQUEST_DENIED;
+ } else if (count_download_queue >= MAX_DOWNLOAD_QUEUE) {
+ error = FAULT_CPE_RESOURCES_EXCEEDED;
+ } else if (schedule_download->url == NULL || (strcmp(schedule_download->url, "") == 0)) {
+ error = FAULT_CPE_REQUEST_DENIED;
+ } else if (strstr(schedule_download->url, "@") != NULL) {
+ error = FAULT_CPE_INVALID_ARGUMENTS;
+ } else if (strncmp(schedule_download->url, DOWNLOAD_PROTOCOL_HTTP, strlen(DOWNLOAD_PROTOCOL_HTTP)) != 0 && strncmp(schedule_download->url, DOWNLOAD_PROTOCOL_FTP, strlen(DOWNLOAD_PROTOCOL_FTP)) != 0) {
+ error = FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL;
+ } else {
+ for (j = 0; j < 3; j++) {
+ if (schedule_download_delay[j] > schedule_download_delay[j + 1]) {
+ error = FAULT_CPE_INVALID_ARGUMENTS;
+ break;
+ }
+ }
+ }
+
+ if (error != FAULT_CPE_NO_FAULT)
+ goto fault;
+
+ t = build_top_body_soap_response(session->tree_out, "ScheduleDownload");
+
+ if (!t)
+ goto fault;
+
+ pthread_mutex_lock(&mutex_schedule_download);
+ list_add_tail(&(schedule_download->list), &(list_schedule_download));
+ if (schedule_download_delay[0] != 0) {
+ count_download_queue++;
+ }
+ while (i > 0) {
+ i--;
+ schedule_download->timewindowstruct[i].windowstart = time(NULL) + schedule_download_delay[i * 2];
+ schedule_download->timewindowstruct[i].windowend = time(NULL) + schedule_download_delay[i * 2 + 1];
+ }
+ bkp_session_insert_schedule_download(schedule_download);
+ bkp_session_save();
+ if (schedule_download_delay[0] != 0) {
+ CWMP_LOG(INFO, "Schedule download will start in %us", schedule_download_delay[0]);
+ } else {
+ CWMP_LOG(INFO, "Schedule Download will start at the end of session");
+ }
+ pthread_mutex_unlock(&mutex_schedule_download);
+ pthread_cond_signal(&threshold_schedule_download);
+
+ return 0;
+
+fault:
+ cwmp_free_schedule_download_request(schedule_download);
+ if (cwmp_create_fault_message(session, rpc, error))
+ goto error;
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * [RPC CPE]: Upload
+ */
+int cwmp_handle_rpc_cpe_upload(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *n;
+ int error = FAULT_CPE_NO_FAULT;
+ struct upload *upload = NULL, *iupload;
+ struct list_head *ilist;
+ time_t scheduled_time = 0;
+ time_t upload_delay = 0;
+ char c[256];
+
+ if (snprintf(c, sizeof(c), "%s:%s", ns.cwmp, "Upload") == -1) {
+ error = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ n = mxmlFindElement(session->tree_in, session->tree_in, c, NULL, NULL, MXML_DESCEND);
+
+ if (!n)
+ return -1;
+
+ upload = calloc(1, sizeof(struct upload));
+ if (upload == NULL) {
+ error = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+ upload->f_instance = 0;
+
+ struct xml_data_struct upload_xml_attrs = {0};
+ upload_xml_attrs.command_key = &upload->command_key;
+ upload_xml_attrs.url = &upload->url;
+ upload_xml_attrs.username = &upload->username;
+ upload_xml_attrs.password = &upload->password;
+ upload_xml_attrs.delay_seconds = (long int*)&upload_delay;
+ upload_xml_attrs.file_type = &upload->file_type;
+ upload_xml_attrs.instance = &upload->f_instance;
+
+
+ struct xml_tag_validation upload_validation[] = {{"CommandKey", VALIDATE_STR_SIZE, 0, 32}, {"FileType", VALIDATE_STR_SIZE, 0, 64}, {"URL", VALIDATE_STR_SIZE, 0, 256}, {"Username", VALIDATE_STR_SIZE, 0, 256}, {"Password", VALIDATE_STR_SIZE, 0, 256}, {"DelaySeconds", VALIDATE_UNINT, 0, 0}};
+ upload_xml_attrs.validations = upload_validation;
+ upload_xml_attrs.nbre_validations = 6;
+
+ error = load_xml_node_data(SOAP_REQ_UPLOAD, n, &upload_xml_attrs);
+
+ if (error)
+ goto fault;
+
+ if (count_download_queue >= MAX_DOWNLOAD_QUEUE) {
+ error = FAULT_CPE_RESOURCES_EXCEEDED;
+ } else if (upload->url == NULL || (strcmp(upload->url, "") == 0)) {
+ error = FAULT_CPE_REQUEST_DENIED;
+ } else if (strstr(upload->url, "@") != NULL) {
+ error = FAULT_CPE_INVALID_ARGUMENTS;
+ } else if (strncmp(upload->url, DOWNLOAD_PROTOCOL_HTTPS, strlen(DOWNLOAD_PROTOCOL_HTTPS)) != 0 && strncmp(upload->url, DOWNLOAD_PROTOCOL_HTTP, strlen(DOWNLOAD_PROTOCOL_HTTP)) != 0 && strncmp(upload->url, DOWNLOAD_PROTOCOL_FTP, strlen(DOWNLOAD_PROTOCOL_FTP)) != 0) {
+ error = FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL;
+ }
+
+ if (error != FAULT_CPE_NO_FAULT) {
+ goto fault;
+ }
+
+ mxml_node_t *t = build_top_body_soap_response(session->tree_out, "Upload");
+ char *start_time = "0001-01-01T00:00:00+00:00";
+ char *complete_time = "0001-01-01T00:00:00+00:00";
+ int status = 1;
+
+ struct xml_data_struct upload_resp_xml_attrs = {0};
+ upload_resp_xml_attrs.status = &status;
+ upload_resp_xml_attrs.start_time = &start_time;
+ upload_resp_xml_attrs.complete_time = &complete_time;
+ int fault = build_xml_node_data(SOAP_RESP_UPLOAD, t, &upload_resp_xml_attrs);
+ if (fault != CWMP_OK) {
+ error = FAULT_CPE_INTERNAL_ERROR;
+ goto fault;
+ }
+
+ if (error == FAULT_CPE_NO_FAULT) {
+ pthread_mutex_lock(&mutex_upload);
+ if (upload_delay != 0)
+ scheduled_time = time(NULL) + upload_delay + PROCESSING_DELAY;
+
+ list_for_each (ilist, &(list_upload)) {
+ iupload = list_entry(ilist, struct upload, list);
+ if (iupload->scheduled_time >= scheduled_time) {
+ break;
+ }
+ }
+ list_add(&(upload->list), ilist->prev);
+ if (upload_delay != 0) {
+ count_download_queue++;
+ upload->scheduled_time = scheduled_time;
+ }
+ bkp_session_insert_upload(upload);
+ bkp_session_save();
+ if (upload_delay != 0) {
+ CWMP_LOG(INFO, "Upload will start in %us", upload_delay);
+ } else {
+ CWMP_LOG(INFO, "Upload will start at the end of session");
+ }
+ pthread_mutex_unlock(&mutex_upload);
+ pthread_cond_signal(&threshold_upload);
+ }
+ return 0;
+
+fault:
+ cwmp_free_upload_request(upload);
+ if (cwmp_create_fault_message(session, rpc, error))
+ return -1;
+ return 0;
+}
+
+/*
+ * [FAULT]: Fault
+ */
+
+int cwmp_handle_rpc_cpe_fault(struct session *session, struct rpc *rpc)
+{
+ mxml_node_t *body;
+
+ body = mxmlFindElement(session->tree_out, session->tree_out, "soap_env:Body", NULL, NULL, MXML_DESCEND);
+ struct xml_data_struct fault_xml_attrs = {0};
+ char *faultcode = (FAULT_CPE_ARRAY[session->fault_code].TYPE == FAULT_CPE_TYPE_CLIENT) ? "Client" : "Server";
+ char *faultstring = "CWMP fault";
+ int fault_code = atoi(session->fault_code ? FAULT_CPE_ARRAY[session->fault_code].CODE : "0");
+ char *fault_string = strdup(FAULT_CPE_ARRAY[session->fault_code].DESCRIPTION);
+ fault_xml_attrs.fault_code = &fault_code;
+ fault_xml_attrs.fault_string = &fault_string;
+ fault_xml_attrs.faultcode = &faultcode;
+ fault_xml_attrs.faultstring = &faultstring;
+
+ int fault = build_xml_node_data(SOAP_ROOT_FAULT, body, &fault_xml_attrs);
+ FREE(fault_string);
+ if (fault)
+ return -1;
+
+ if (rpc->type == RPC_CPE_SET_PARAMETER_VALUES) {
+ LIST_HEAD(spv_fault_xml_data_list);
+ cwmp_param_fault_list_to_xml_data_list(rpc->list_set_value_fault, &spv_fault_xml_data_list);
+ struct xml_data_struct spv_fault_xml_attrs = {0};
+ spv_fault_xml_attrs.data_list = &spv_fault_xml_data_list;
+ body = mxmlFindElement(session->tree_out, session->tree_out, "cwmp:Fault", NULL, NULL, MXML_DESCEND);
+ fault = build_xml_node_data(SOAP_SPV_FAULT, body, &spv_fault_xml_attrs);
+ if (fault)
+ return -1;
+ cwmp_free_all_xml_data_list(&spv_fault_xml_data_list);
+ }
+
+ return 0;
+}
+
+int cwmp_create_fault_message(struct session *session, struct rpc *rpc_cpe, int fault_code)
+{
+ CWMP_LOG(INFO, "Fault detected");
+ session->fault_code = fault_code;
+
+ MXML_DELETE(session->tree_out);
+
+ if (xml_prepare_msg_out(session))
+ return -1;
+
+ CWMP_LOG(INFO, "Preparing the Fault message");
+ if (rpc_cpe_methods[RPC_CPE_FAULT].handler(session, rpc_cpe))
+ return -1;
+ rpc_cpe->type = RPC_CPE_FAULT;
+
+ return 0;
+}
diff --git a/inc/rpc_soap.h b/src/rpc.h
similarity index 86%
rename from inc/rpc_soap.h
rename to src/rpc.h
index 25c4386..a63e301 100644
--- a/inc/rpc_soap.h
+++ b/src/rpc.h
@@ -1,13 +1,13 @@
/*
- * 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.
+ * rpc.h - CWMP RPC methods
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2019 iopsys Software Solutions AB
* Author Mohamed Kallel
* Author Ahmed Zribi
- * Copyright (C) 2011 Luka Perkov
+ * Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
*
*/
@@ -51,7 +51,6 @@ int cwmp_rpc_acs_parse_response_get_rpc_methods(struct cwmp *cwmp, struct sessio
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);
diff --git a/sched_inform.c b/src/sched_inform.c
similarity index 92%
rename from sched_inform.c
rename to src/sched_inform.c
index a3b9033..16ea76a 100644
--- a/sched_inform.c
+++ b/src/sched_inform.c
@@ -1,11 +1,12 @@
/*
- * 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.
+ * sched_inform.c - ScheduleInform method corresponding functions
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
*/
#include "sched_inform.h"
diff --git a/inc/sched_inform.h b/src/sched_inform.h
similarity index 57%
rename from inc/sched_inform.h
rename to src/sched_inform.h
index dad0c0e..7d587e3 100644
--- a/inc/sched_inform.h
+++ b/src/sched_inform.h
@@ -1,11 +1,12 @@
/*
- * 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.
+ * sched_inform.h - ScheduleInform method corresponding functions
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
*/
#ifndef CWMP_SCHED_INFORM_H
diff --git a/session.c b/src/session.c
similarity index 95%
rename from session.c
rename to src/session.c
index 6725a42..baf5fee 100644
--- a/session.c
+++ b/src/session.c
@@ -1,12 +1,12 @@
/*
- * 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.
+ * session.c - API for CWMP Session
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel
*
+ * See LICENSE file for license related information.
+ *
*/
#include
@@ -14,7 +14,7 @@
#include "session.h"
#include "config.h"
#include "event.h"
-#include "rpc_soap.h"
+#include "rpc.h"
#include "backupSession.h"
#include "heartbeat.h"
diff --git a/inc/session.h b/src/session.h
similarity index 84%
rename from inc/session.h
rename to src/session.h
index 2bd6237..d2090c0 100644
--- a/inc/session.h
+++ b/src/session.h
@@ -1,18 +1,18 @@
/*
- * 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.
+ * session.h - API for CWMP Session
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2020 iopsys Software Solutions AB
* Author Omar Kallel
*
+ * See LICENSE file for license related information.
+ *
*/
#ifndef SESSION_H_
#define SESSION_H_
-#include
+#include "xml_utils.h"
#include "common.h"
typedef struct session {
diff --git a/ssl_utils.c b/src/ssl_utils.c
similarity index 100%
rename from ssl_utils.c
rename to src/ssl_utils.c
diff --git a/inc/ssl_utils.h b/src/ssl_utils.h
similarity index 100%
rename from inc/ssl_utils.h
rename to src/ssl_utils.h
diff --git a/ubus_utils.c b/src/ubus_utils.c
similarity index 100%
rename from ubus_utils.c
rename to src/ubus_utils.c
diff --git a/inc/ubus_utils.h b/src/ubus_utils.h
similarity index 72%
rename from inc/ubus_utils.h
rename to src/ubus_utils.h
index eca1940..632b191 100644
--- a/inc/ubus_utils.h
+++ b/src/ubus_utils.h
@@ -1,3 +1,13 @@
+/*
+ * ubus_utils.h - ubus methods and utility functions
+ *
+ * Copyright (C) 2022, IOPSYS Software Solutions AB.
+ *
+ * Author: suvendhu.hansa@iopsys.eu
+ *
+ * See LICENSE file for license related information
+ *
+ */
#ifndef __ICWMP_UBUS_UTILS_H__
#define __ICWMP_UBUS_UTILS_H__
diff --git a/upload.c b/src/upload.c
similarity index 95%
rename from upload.c
rename to src/upload.c
index 8c7153d..9b40a05 100644
--- a/upload.c
+++ b/src/upload.c
@@ -1,11 +1,12 @@
/*
- * 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.
+ * upload.c - Upload method corresponding functions
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
*/
#include
@@ -36,7 +37,7 @@ int lookup_vcf_name(int instance, char **value)
CWMP_LOG(ERROR, "Not able to get the value of the parameter %s", vcf_name_parameter);
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 = param_value->value ? strdup(param_value->value) : NULL;
break;
@@ -54,7 +55,7 @@ int lookup_vlf_name(int instance, char **value)
CWMP_LOG(ERROR, "Not able to get the value of the parameter %s", vlf_name_parameter);
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 = param_value->value ? strdup(param_value->value) : NULL;
break;
diff --git a/inc/upload.h b/src/upload.h
similarity index 61%
rename from inc/upload.h
rename to src/upload.h
index e061b78..3f05215 100644
--- a/inc/upload.h
+++ b/src/upload.h
@@ -1,11 +1,12 @@
/*
- * 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.
+ * upload.h - Upload method corresponding functions
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
*
- * Copyright (C) 2013-2021 iopsys Software Solutions AB
* Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
*/
#ifndef CWMP_UPLOAD_H
diff --git a/src/xml.c b/src/xml.c
new file mode 100644
index 0000000..2623dd9
--- /dev/null
+++ b/src/xml.c
@@ -0,0 +1,1434 @@
+/*
+ * xml.c - XML and SOAP functions
+ *
+ * Copyright (C) 2021-2022, IOPSYS Software Solutions AB.
+ *
+ * Author Mohamed Kallel
+ * Author Ahmed Zribi
+ * Author Omar Kallel
+ *
+ * See LICENSE file for license related information.
+ *
+ */
+
+#include "xml.h"
+#include "log.h"
+#include "notifications.h"
+#include "http.h"
+#include "cwmp_zlib.h"
+#include "common.h"
+#include "event.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/";
+static const char *xsd_url = "http://www.w3.org/2001/XMLSchema";
+static const char *xsi_url = "http://www.w3.org/2001/XMLSchema-instance";
+
+const char *cwmp_urls[] = { "urn:dslforum-org:cwmp-1-0", "urn:dslforum-org:cwmp-1-1", "urn:dslforum-org:cwmp-1-2", "urn:dslforum-org:cwmp-1-2", "urn:dslforum-org:cwmp-1-2", "urn:dslforum-org:cwmp-1-2", NULL };
+
+struct xml_node_data xml_nodes_data[] = {
+ /*
+ * SOAP Requests
+ */
+ [SOAP_REQ_SPV] = {XML_SINGLE, 0, NULL, {{"ParameterList", XML_REC, SOAP_REQ_SPV_LIST, NULL}, {"ParameterKey", XML_STRING, 0, NULL}}},
+ [SOAP_REQ_GPV] = {XML_LIST, SOAP_REQ_GPV_REF, "string", {}},
+ [SOAP_REQ_GPN] = {XML_SINGLE, 0, NULL, {{"ParameterPath", XML_STRING, 0, NULL}, {"NextLevel", XML_BOOL, 0, NULL}}},
+ [SOAP_REQ_SPA] = {XML_LIST, SOAP_REQ_SPA_REF, "SetParameterAttributesStruct", {}},
+ [SOAP_REQ_GPA] = {XML_LIST, SOAP_REQ_GPA_REF, "string", {}},
+ [SOAP_REQ_ADDOBJ] = {XML_SINGLE, 0, NULL, {{"ObjectName", XML_STRING, 0, NULL}, {"ParameterKey", XML_STRING, 0, NULL}}},
+ [SOAP_REQ_DELOBJ] = {XML_SINGLE, 0, NULL, {{"ObjectName", XML_STRING, 0, NULL}, {"ParameterKey", XML_STRING, 0, NULL}}},
+ [SOAP_REQ_REBOOT] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}}},
+ [SOAP_REQ_DOWNLOAD] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"FileType", XML_FUNC, 0, load_download_filetype}, {"URL", XML_STRING, 0, NULL}, {"Username", XML_STRING, 0, NULL}, {"Password", XML_STRING, 0, NULL}, {"FileSize", XML_INTEGER, 0, NULL}, {"DelaySeconds", XML_INTEGER, 0, NULL}}},
+ [SOAP_REQ_UPLOAD] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"FileType", XML_FUNC, 0, load_upload_filetype}, {"URL", XML_STRING, 0, NULL}, {"Username", XML_STRING, 0, NULL}, {"Password", XML_STRING, 0, NULL}, {"DelaySeconds", XML_INTEGER, 0, NULL}}},
+ [SOAP_REQ_CANCELTRANSFER] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}}},
+ [SOAP_REQ_SCHEDINF] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"DelaySeconds", XML_INTEGER, 0, NULL}}},
+ [SOAP_REQ_SCHEDDOWN] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"FileType", XML_STRING, 0, NULL}, {"URL", XML_STRING, 0, NULL}, {"Username", XML_STRING, 0, NULL}, {"Password", XML_STRING, 0, NULL}, {"FileSize", XML_STRING, 0, NULL}, {"TimeWindowList", XML_REC, SOAP_TIMEWINDOW_REF, NULL}}},
+ [SOAP_REQ_CDU] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"Operations", XML_REC, SOAP_REQ_CDU_OPERATIONS, NULL}}},
+ [SOAP_REQ_SPV_LIST] = {XML_LIST, SOAP_REQ_SPV_LIST_REF, "ParameterValueStruct", {}},
+ [SOAP_REQ_SPV_LIST_REF] = {XML_SINGLE, 0, NULL, {{"Name", XML_STRING, 0, NULL}, {"Value", XML_STRING, 0, NULL}}},
+ [SOAP_REQ_GPV_REF] = {XML_SINGLE, 0, NULL, {{"string", XML_STRING, 0, NULL}}},
+ [SOAP_REQ_SPA_REF] = {XML_SINGLE, 0, NULL, {{"Name", XML_STRING, 0, NULL}, {"Notification", XML_INTEGER, 0, NULL}, {"NotificationChange", XML_BOOL, 0, NULL}}},
+ [SOAP_REQ_GPA_REF] = {XML_SINGLE, 0, NULL, {{"string", XML_STRING, 0, NULL}}},
+ [SOAP_TIMEWINDOW_REF] = {XML_LIST, SOAP_TIME_REF, NULL, {}},
+ [SOAP_TIME_REF] = {XML_SINGLE, 0, NULL, {{"WindowStart", XML_LINTEGER, 0, NULL}, {"WindowEnd", XML_LINTEGER, 0, NULL}, {"WindowMode", XML_STRING, 0, NULL}, {"WindowMode", XML_FUNC, 0, load_sched_download_window_mode}, {"MaxRetries", XML_INTEGER, 0, NULL}}},
+ [SOAP_REQ_CDU_OPERATIONS] = {XML_LIST, SOAP_REQ_CDU_OPS_REF, "Operations", {}},
+ [SOAP_REQ_CDU_OPS_REF] = {XML_SINGLE, 0, NULL, {{"Operations", XML_FUNC, 0, NULL}}},
+ [SOAP_REQ_DU_INSTALL] = {XML_SINGLE, 0, NULL, {{"URL", XML_STRING, 0, NULL}, {"UUID", XML_STRING, 0, NULL}, {"Username", XML_STRING, 0, NULL}, {"Password", XML_STRING, 0, NULL}, {"ExecutionEnvRef", XML_STRING, 0, NULL}}},
+ [SOAP_REQ_DU_UPDATE] = {XML_SINGLE, 0, NULL, {{"URL", XML_STRING, 0, NULL}, {"UUID", XML_STRING, 0, NULL}, {"Username", XML_STRING, 0, NULL}, {"Password", XML_STRING, 0, NULL}, {"Version", XML_STRING, 0, NULL}}},
+ [SOAP_REQ_DU_UNINSTALL] = {XML_SINGLE, 0, NULL, {{"Version", XML_STRING, 0, NULL}, {"ExecutionEnvRef", XML_STRING, 0, NULL}, {"URL", XML_STRING, 0, NULL}}},
+
+ /*
+ * SOAP Responses
+ */
+ [SOAP_RESP_GPV] = {XML_SINGLE, 0, NULL, {{"ParameterList", XML_NODE, ATTR_PARAM_STRUCT, NULL}}},
+ [SOAP_PARAM_STRUCT] = {XML_LIST, SOAP_PARAM_STRUCT_REF, "ParameterValueStruct", {}},
+ [SOAP_PARAM_STRUCT_REF] = {XML_SINGLE, 0, NULL, {{"Name", XML_STRING, 0, NULL}, {"Value", XML_STRING, ATTR_PARAM_STRUCT, NULL}}},
+ [SOAP_VALUE_STRUCT] = {XML_SINGLE, 0, NULL, {{"Value", XML_STRING, ATTR_PARAM_STRUCT, NULL}}},
+ [SOAP_RESP_SPV] = {XML_SINGLE, 0, NULL, {{"Status", XML_INTEGER, 0, NULL}}},
+ [SOAP_RESP_GPN] = {XML_LIST, SOAP_RESP_GPN_REF, "ParameterInfoStruct", {}},
+ [SOAP_RESP_GPN_REF] = {XML_SINGLE, 0, NULL, {{"Name", XML_STRING, 0, NULL}, {"Writable", XML_BOOL, 0, NULL}}},
+ [SOAP_RESP_GPA] = {XML_LIST, SOAP_RESP_GPA_REF, "ParameterAttributeStruct", {}},
+ [SOAP_RESP_GPA_REF] = {XML_SINGLE, 0, NULL, {{"Name", XML_STRING, 0, NULL}, {"Notification", XML_INTEGER, 0, NULL}, {"AccessList", XML_STRING, 0, NULL}}},
+ [SOAP_RESP_ADDOBJ] = {XML_SINGLE, 0, NULL, {{"InstanceNumber", XML_INTEGER, 0, NULL}, {"Status", XML_INTEGER, 0, NULL}}},
+ [SOAP_RESP_DELOBJ] = {XML_SINGLE, 0, NULL, {{"Status", XML_INTEGER, 0, NULL}}},
+ [SOAP_RESP_DOWNLOAD] = {XML_SINGLE, 0, NULL, {{"Status", XML_INTEGER, 0, NULL}, {"StartTime", XML_STRING, 0, NULL}, {"CompleteTime", XML_STRING, 0, NULL}}},
+ [SOAP_RESP_UPLOAD] = {XML_SINGLE, 0, NULL, {{"Status", XML_INTEGER, 0, NULL}, {"StartTime", XML_STRING, 0, NULL}, {"CompleteTime", XML_STRING, 0, NULL}}},
+ [SOAP_RESP_GETRPC] = {XML_LIST, SOAP_RESP_GETRPC_REF, NULL, {}},
+ [SOAP_RESP_GETRPC_REF] = {XML_SINGLE, 0, NULL, {{"string", XML_STRING, 0, NULL}}},
+ [SOAP_ACS_TRANSCOMPLETE] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"FaultStruct", XML_REC, SOAP_FAULT_STRCT_REF, NULL}, {"StartTime", XML_STRING, 0, NULL}, {"CompleteTime", XML_STRING, 0, NULL}}},
+ [SOAP_ROOT_FAULT] = {XML_SINGLE, 0, NULL, {{"soap_env:Fault", XML_REC, SOAP_RPC_FAULT, NULL}}},
+ [SOAP_RPC_FAULT] = {XML_SINGLE, 0, NULL, {{"faultcode", XML_STRING, 0, NULL}, {"faultstring", XML_STRING, 0, NULL}, {"detail", XML_REC, SOAP_FAULT_DETAIL, NULL}}},
+ [SOAP_FAULT_DETAIL] = {XML_SINGLE, 0, NULL, {{"cwmp:Fault", XML_REC, SOAP_CWMP_FAULT, NULL}}},
+ [SOAP_CWMP_FAULT] = {XML_SINGLE, 0, NULL, {{"FaultCode", XML_INTEGER, 0, NULL}, {"FaultString", XML_STRING, 0, NULL}}},
+ [SOAP_SPV_FAULT] = {XML_LIST, SOAP_SPV_FAULT_REF, "SetParameterValuesFault", {}},
+ [SOAP_SPV_FAULT_REF] = {XML_SINGLE, 0, NULL, {{"ParameterName", XML_STRING, 0, NULL}, {"FaultCode", XML_INTEGER, 0, NULL}, {"FaultString", XML_STRING, 0, NULL}}},
+ [SOAP_FAULT_STRCT_REF] = {XML_SINGLE, 0, NULL, {{"FaultCode", XML_INTEGER, 0, NULL}, {"FaultString", XML_STRING, 0, NULL}}},
+
+ [SOAP_ENV] = {XML_SINGLE, 0, NULL, {{"soap_env:Envelope", XML_FUNC, 0, build_inform_env_header}}},
+ [SOAP_INFORM_CWMP] = {XML_SINGLE, 0, NULL, {{"DeviceId", XML_REC, SOAP_DEVID, NULL}, {"Event", XML_FUNC, 0, build_inform_events}, {"MaxEnvelopes", XML_INTEGER, 0, NULL}, {"CurrentTime", XML_STRING, 0, NULL}, {"RetryCount", XML_INTEGER, 0, NULL}}},
+ [SOAP_DEVID] = {XML_SINGLE, 0, NULL, {{"Manufacturer", XML_STRING, 0, NULL}, {"OUI", XML_STRING, 0, NULL}, {"ProductClass", XML_STRING, 0, NULL}, {"SerialNumber", XML_STRING, 0, NULL}}},
+ [SOAP_DU_CHANGE_COMPLETE] = {XML_SINGLE, 0, NULL, {{"CommandKey", XML_STRING, 0, NULL}, {"Results", XML_REC, SOAP_CDU_RESULTS_REF, NULL}}},
+ [SOAP_CDU_RESULTS_REF] = {XML_LIST, 0, NULL, {{"OpResultStruct", XML_REC, SOAP_CDU_OPTS_REF, NULL}}},
+ [SOAP_CDU_OPTS_REF] = {XML_SINGLE, 0, NULL, {{"UUID", XML_STRING, 0, NULL}, {"DeploymentUnitRef", XML_STRING, 0, NULL}, {"Version", XML_STRING, 0, NULL}, {"CurrentState", XML_STRING, 0, NULL}, {"StartTime", XML_STRING, 0, NULL}, {"CompleteTime", XML_STRING, 0, NULL}, {"FaultStruct", XML_REC, SOAP_CWMP_FAULT, NULL}}},
+ [ATTR_PARAM_STRUCT] = {XML_SINGLE, 0, NULL, {{"xsi:type", XML_STRING, 0, NULL}}},
+ [ATTR_SOAP_ENV] = {XML_SINGLE, 0, NULL, {{"xmlns:soap_env", XML_STRING, 0, NULL}, {"xmlns:soap_enc", XML_STRING, 0, NULL}, {"xmlns:xsd", XML_STRING, 0, NULL}, {"xmlns:xsi", XML_STRING, 0, NULL}}}
+};
+
+char* xml_tags_names[] = {
+ "ParameterList",
+ "Name",
+ "Value",
+ "string",
+ "ParameterPath",
+ "ParameterName",
+ "ObjectName",
+ "ParameterKey",
+ "CommandKey",
+ "FileType",
+ "URL",
+ "Username",
+ "Password",
+ "UUID",
+ "ExecutionEnvRef",
+ "DeploymentUnitRef",
+ "CurrentState",
+ "Version",
+ "WindowMode",
+ "UserMessage",
+ "StartTime",
+ "CompleteTime",
+ "AccessList",
+ "FaultString",
+ "faultcode",
+ "faultstring",
+ "Manufacturer",
+ "OUI",
+ "SerialNumber",
+ "CurrentTime",
+ "ProductClass",
+ "xsi:type",
+ "FileSize",
+ "Notification",
+ "MaxRetries",
+ "Status",
+ "InstanceNumber",
+ "FaultCode",
+ "MaxEnvelopes",
+ "RetryCount",
+ "DelaySeconds",
+ "WindowStart",
+ "WindowEnd",
+ "NextLevel",
+ "NotificationChange",
+ "Writable",
+};
+
+void add_xml_data_list(struct list_head *data_list, struct xml_list_data *xml_data)
+{
+ list_add_tail(&xml_data->list, data_list);
+}
+
+void delete_xml_data_from_list(struct xml_list_data *xml_data)
+{
+ list_del(&xml_data->list);
+ FREE(xml_data->param_name);
+ FREE(xml_data->param_value);
+ FREE(xml_data->param_type);
+ FREE(xml_data->windowmode);
+ FREE(xml_data->usermessage);
+ FREE(xml_data->access_list);
+ FREE(xml_data->fault_string);
+ FREE(xml_data->command_key);
+ FREE(xml_data->complete_time);
+ FREE(xml_data->current_state);
+ FREE(xml_data->execution_env_ref);
+ FREE(xml_data->du_ref);
+ FREE(xml_data->password);
+ FREE(xml_data->rpc_name);
+ FREE(xml_data->url);
+ FREE(xml_data->uuid);
+ FREE(xml_data->start_time);
+ FREE(xml_data->version);
+ FREE(xml_data);
+}
+
+void cwmp_free_all_xml_data_list(struct list_head *list)
+{
+ while (list->next != list) {
+ struct xml_list_data *xml_data;
+ xml_data = list_entry(list->next, struct xml_list_data, list);
+ delete_xml_data_from_list(xml_data);
+ }
+}
+
+int load_upload_filetype(mxml_node_t *b, struct xml_data_struct *xml_attrs)
+{
+ mxml_node_t *t = mxmlWalkNext(b, b, MXML_DESCEND);
+ const char *node_opaque = mxmlGetOpaque(t);
+ int error = FAULT_CPE_NO_FAULT;
+ char log_config[16]={0};
+ int ftype, instance = 0;
+
+ sscanf(node_opaque, "%1d Vendor %15s File %8d", &ftype, log_config, &instance);
+ if (strcmp(log_config, "Configuration") != 0 && strcmp(log_config, "Log") != 0) {
+ error = FAULT_CPE_INVALID_ARGUMENTS;
+ return error;
+ } else if (strcmp(log_config, "Configuration") == 0 && ftype != 1 && ftype != 3) {
+ error = FAULT_CPE_INVALID_ARGUMENTS;
+ return error;
+ } else if (strcmp(log_config, "Log") == 0 && ftype != 2 && ftype != 4) {
+ error = FAULT_CPE_INVALID_ARGUMENTS;
+ return error;
+ }
+ if ((ftype == 3 || ftype == 4) && (instance == 0)) {
+ error = FAULT_CPE_INVALID_ARGUMENTS;
+ return error;
+ }
+ if (ftype !=1 && ftype != 2 && ftype != 3 && ftype != 4) {
+ error = FAULT_CPE_INVALID_ARGUMENTS;
+ return error;
+ }
+ *xml_attrs->file_type = strdup(node_opaque);
+ *xml_attrs->instance = instance;
+ return error;
+}
+
+int load_download_filetype(mxml_node_t *b, struct xml_data_struct *xml_attrs)
+{
+ int error = FAULT_CPE_NO_FAULT;
+ mxml_node_t *t = mxmlWalkNext(b, b, MXML_DESCEND);
+ const char *node_opaque = mxmlGetOpaque(t);
+ if (*(xml_attrs->file_type) == NULL) {
+ *(xml_attrs->file_type) = strdup(node_opaque);
+ } else {
+ char tmp[128];
+ snprintf(tmp, sizeof(tmp), "%s", *(xml_attrs->file_type));
+ FREE(*(xml_attrs->file_type));
+ if (cwmp_asprintf(xml_attrs->file_type, "%s %s", tmp, node_opaque) == -1) {
+ error = FAULT_CPE_INTERNAL_ERROR;
+ return error;
+ }
+ }
+ return error;
+}
+
+int load_sched_download_window_mode(mxml_node_t *b, struct xml_data_struct *xml_attrs)
+{
+ mxml_node_t *t = mxmlWalkNext(b, b, MXML_DESCEND);
+ const char *node_opaque = mxmlGetOpaque(t);
+ if (*(xml_attrs->window_mode) == NULL)
+ *(xml_attrs->window_mode) = strdup(node_opaque);
+ else {
+ static char *tmp = NULL;
+ tmp = *(xml_attrs->window_mode);
+ if (cwmp_asprintf(xml_attrs->window_mode, "%s %s", tmp, node_opaque) == -1)
+ return FAULT_CPE_INTERNAL_ERROR;
+ }
+ return FAULT_CPE_NO_FAULT;
+}
+
+int load_change_du_state_operation(mxml_node_t *b, struct xml_data_struct *xml_attrs)
+{
+ char *operation = (char *)mxmlElementGetAttr(b, "xsi:type");
+ int cdu_ref = 0;
+ int type = 0;
+
+ if (strcmp(operation, "cwmp:InstallOpStruct") == 0) {
+ cdu_ref = SOAP_REQ_DU_INSTALL;
+ type = DU_INSTALL;
+ }
+ else if (strcmp(operation, "cwmp:UpdateOpStruct") == 0) {
+ cdu_ref = SOAP_REQ_DU_INSTALL;
+ type = DU_UPDATE;
+ }
+ else if (strcmp(operation, "cwmp:UninstallOpStruct") == 0) {
+ cdu_ref = SOAP_REQ_DU_INSTALL;
+ type = DU_UNINSTALL;
+ }
+
+ // cppcheck-suppress autoVariables
+ xml_attrs->cdu_type = &type;
+
+ if (cdu_ref == 0)
+ return FAULT_CPE_INVALID_ARGUMENTS;
+
+ int fault = load_xml_node_data(cdu_ref, b, xml_attrs);
+ if (fault)
+ return fault;
+
+
+ return FAULT_CPE_NO_FAULT;
+}
+
+int build_inform_env_header(mxml_node_t *b __attribute__((unused)), struct xml_data_struct *xml_attrs)
+{
+ if (b == NULL)
+ return FAULT_CPE_INTERNAL_ERROR;
+ int amd_version = xml_attrs->amd_version ? *(xml_attrs->amd_version) : 2;
+ mxml_node_t **envelope = xml_attrs->xml_env;
+
+ *envelope = b;
+
+ mxmlElementSetAttr(*envelope, "xmlns:soap_env", "http://schemas.xmlsoap.org/soap/envelope/");
+ mxmlElementSetAttr(*envelope, "xmlns:soap_enc", "http://schemas.xmlsoap.org/soap/encoding/");
+ mxmlElementSetAttr(*envelope, "xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
+ mxmlElementSetAttr(*envelope, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+ mxmlElementSetAttr(*envelope, "xmlns:cwmp", cwmp_urls[amd_version - 1]);
+
+ mxml_node_t *header = mxmlNewElement(*envelope, "soap_env:Header");
+ if (header == NULL)
+ return FAULT_CPE_INTERNAL_ERROR;
+
+ mxml_node_t *id = mxmlNewElement(header, "cwmp:ID");
+ if (id == NULL)
+ return FAULT_CPE_INTERNAL_ERROR;
+
+ mxmlElementSetAttr(id, "soap_env:mustUnderstand", "1");
+
+ mxml_node_t *node = NULL;
+ if (amd_version >= 4) {
+ node = mxmlNewElement(header, "cwmp:SessionTimeout");
+ if (!node)
+ return FAULT_CPE_INTERNAL_ERROR;
+
+ mxmlElementSetAttr(node, "soap_env:mustUnderstand", "0");
+ node = mxmlNewInteger(node, *(xml_attrs->session_timeout));
+ if (!node)
+ return FAULT_CPE_INTERNAL_ERROR;
+ }
+
+ if (amd_version >= 5) {
+ node = mxmlNewElement(header, "cwmp:SupportedCWMPVersions");
+ if (!node)
+ return FAULT_CPE_INTERNAL_ERROR;
+
+ mxmlElementSetAttr(node, "soap_env:mustUnderstand", "0");
+ node = mxmlNewOpaque(node, xml_get_cwmp_version(amd_version));
+ if (!node)
+ return FAULT_CPE_INTERNAL_ERROR;
+ }
+
+ mxml_node_t *body = mxmlNewElement(*envelope, "soap_env:Body");
+ if (body == NULL)
+ return FAULT_CPE_INTERNAL_ERROR;
+
+ return FAULT_CPE_NO_FAULT;
+}
+
+int build_inform_events(mxml_node_t *event, struct xml_data_struct *xml_attrs)
+{
+ mxml_node_t *node, *b2;
+ char c[128];
+ unsigned int n = 0;
+ struct cwmp *cwmp = &cwmp_main;
+
+ cwmp->is_boot = false;
+
+ if (!event)
+ return -1;
+
+ mxmlElementSetAttr(event, "soap_enc:arrayType", "cwmp:EventStruct[0]");
+ struct xml_list_data *xml_data;
+
+ list_for_each_entry (xml_data, xml_attrs->data_list, list) {
+ node = mxmlNewElement(event, "EventStruct");
+ if (!node)
+ goto error;
+ b2 = mxmlNewElement(node, "EventCode");
+ if (!b2)
+ goto error;
+ if (xml_data->event_code == EVENT_IDX_0BOOTSTRAP || xml_data->event_code == EVENT_IDX_1BOOT)
+ cwmp->is_boot = true;
+ b2 = mxmlNewOpaque(b2, EVENT_CONST[xml_data->event_code].CODE);
+ if (!b2)
+ goto error;
+ b2 = mxmlNewElement(node, "CommandKey");
+ if (!b2)
+ goto error;
+ if (xml_data->command_key) {
+ b2 = mxmlNewOpaque(b2, xml_data->command_key);
+ if (!b2)
+ goto error;
+ }
+ mxmlAdd(event, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node);
+ n++;
+ }
+ if (n) {
+ if (snprintf(c, sizeof(c), "cwmp:EventStruct[%u]", n) == -1)
+ return -1;
+ mxmlElementSetAttr(event, "xsi:type", "soap_enc:Array");
+ mxmlElementSetAttr(event, "soap_enc:arrayType", c);
+ }
+ return 0;
+
+error:
+ return -1;
+}
+
+int get_xml_type(int node_ref, int soap_idx)
+{
+ return xml_nodes_data[node_ref].xml_tags[soap_idx].tag_type;
+}
+
+int get_xml_tag_index(const char *name)
+{
+ unsigned int i;
+ if (name == NULL)
+ return -1;
+
+ size_t total_size = sizeof(xml_tags_names) / sizeof(char*);
+ for (i = 0; i < total_size; i++) {
+ if (strcmp(name, xml_tags_names[i]) == 0)
+ return i;
+ }
+ return -1;
+}
+
+
+int get_xml_soap_tag_index(int soap_ref, const char *name)
+{
+ unsigned int i = 0;
+ if (name == NULL)
+ return -1;
+ while (xml_nodes_data[soap_ref].xml_tags[i].tag_name) {
+ if (strcmp(name, xml_nodes_data[soap_ref].xml_tags[i].tag_name) == 0)
+ return i;
+ i++;
+ }
+ return -1;
+}
+
+int load_xml_list_node_data(int node_ref, mxml_node_t *node, struct xml_data_struct *xml_attrs)
+{
+ mxml_node_t *b;
+
+ b = mxmlWalkNext(node, node, MXML_DESCEND);
+ while (b) {
+ if (mxmlGetType(b) == MXML_ELEMENT) {
+ if (strcmp(xml_nodes_data[node_ref].tag_list_name, mxmlGetElement(b)) == 0) {
+ struct xml_list_data *xml_data = calloc(1, sizeof(struct xml_list_data));
+
+ struct xml_data_struct xml_attrs_args = {0};
+ xml_attrs_args.name = &xml_data->param_name;
+ xml_attrs_args.string = &xml_data->param_name;
+ xml_attrs_args.parameter_path = &xml_data->param_name;
+ xml_attrs_args.value = &xml_data->param_value;
+ xml_attrs_args.window_mode = &xml_data->windowmode;
+ xml_attrs_args.user_message = &xml_data->usermessage;
+ xml_attrs_args.notification = &xml_data->notification;
+ xml_attrs_args.scheddown_max_retries = &xml_data->max_retries;
+ xml_attrs_args.window_start = &xml_data->windowstart;
+ xml_attrs_args.window_end = &xml_data->windowend;
+ xml_attrs_args.notification_change = &xml_data->notification_change;
+ xml_attrs_args.access_list = &xml_data->access_list;
+
+ xml_attrs_args.url = &xml_data->url;
+ xml_attrs_args.uuid = &xml_data->uuid;
+ xml_attrs_args.username = &xml_data->username;
+ xml_attrs_args.password = &xml_data->password;
+ xml_attrs_args.exec_env_ref = &xml_data->execution_env_ref;
+ xml_attrs_args.version = &xml_data->version;
+ xml_attrs_args.cdu_type = &xml_data->cdu_type;
+
+ xml_attrs_args.validations = xml_attrs->validations;
+ xml_attrs_args.nbre_validations = xml_attrs->nbre_validations;
+ xml_attrs_args.data_list = xml_attrs->data_list;
+
+ list_add(&(xml_data->list), xml_attrs->data_list);
+ int fault = load_xml_node_data(xml_nodes_data[node_ref].tag_node_ref, b, &xml_attrs_args);
+ if (fault)
+ return fault;
+ }
+ }
+ b = mxmlWalkNext(b, node, MXML_DESCEND);
+ }
+ return CWMP_OK;
+}
+
+bool validate_xml_node_opaque_value(char *node_name, char *opaque, struct xml_tag_validation *validations, int nbre_validations)
+{
+ int i;
+ for (i = 0; i < nbre_validations; i++) {
+ if (strcmp(node_name, validations[i].tag_name) == 0) {
+ if (validations[i].validation_type == VALIDATE_STR_SIZE) {
+ if (!icwmp_validate_string_length(opaque, validations[i].max))
+ return false;
+ }
+ if (validations[i].validation_type == VALIDATE_UNINT) {
+ if (!icwmp_validate_unsignedint(opaque))
+ return false;
+ }
+ if (validations[i].validation_type == VALIDATE_BOOLEAN) {
+ if (!icwmp_validate_boolean_value(opaque))
+ return false;
+ }
+ if (validations[i].validation_type == VALIDATE_INT_RANGE) {
+ if (!icwmp_validate_int_in_range(opaque, validations[i].min, validations[i].max)) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+int load_single_xml_node_data(int node_ref, mxml_node_t *node, struct xml_data_struct *xml_attrs)
+{
+ mxml_node_t *b = node;
+ int idx, xml_type = -1, soap_idx;
+ void **ptr = NULL;
+ int error = FAULT_CPE_NO_FAULT;
+ while (b) {
+ const char *node_name = mxmlGetElement(b);
+ mxml_type_t node_type = mxmlGetType(b);
+ mxml_node_t *firstchild = mxmlGetFirstChild(b);
+
+ if (node_type == MXML_ELEMENT) {
+ soap_idx = get_xml_soap_tag_index(node_ref, node_name);
+ if (soap_idx == -1) {
+ b = mxmlWalkNext(b, node, MXML_DESCEND);
+ continue;
+ }
+
+ xml_type = get_xml_type(node_ref, soap_idx);
+ if (xml_type == XML_FUNC) {
+ if ((error = xml_nodes_data[node_ref].xml_tags[soap_idx].xml_func(b, xml_attrs)) != FAULT_CPE_NO_FAULT)
+ return error;
+ b = mxmlWalkNext(b, node, MXML_DESCEND);
+ continue;
+ }
+
+ if (xml_type == XML_REC) {
+ if ((error = load_xml_node_data(xml_nodes_data[node_ref].xml_tags[soap_idx].rec_ref, node, xml_attrs)) != FAULT_CPE_NO_FAULT)
+ return error;
+ b = mxmlWalkNext(b, node, MXML_DESCEND);
+ continue;
+ }
+ idx = get_xml_tag_index(node_name);
+
+ // cppcheck-suppress knownConditionTrueFalse
+ /*
+ * xml_type value can be modified when calling the function get_xml_type
+ */
+ if ((idx == -1) && (xml_type != XML_FUNC) && (xml_type != XML_REC)) {
+ b = mxmlWalkNext(b, node, MXML_DESCEND);
+ continue;
+ }
+
+ char *opaque = NULL;
+ if (firstchild) {
+ opaque = (char*) mxmlGetOpaque(firstchild);
+ }
+
+ if (!validate_xml_node_opaque_value((char*)mxmlGetElement(b), opaque, xml_attrs->validations, xml_attrs->nbre_validations))
+ return FAULT_CPE_INVALID_ARGUMENTS;
+
+ if ((xml_type != XML_FUNC) && (xml_type != XML_REC))
+ ptr = (void **)((char *)xml_attrs + idx * sizeof(char *));
+
+ char **str;
+ int *intgr;
+ bool *bol;
+ long int *lint;
+ time_t *time;
+
+ switch (xml_type) {
+ case XML_STRING:
+ str = (char **)(*ptr);
+ *str = strdup(opaque ? opaque : "");
+ break;
+ case XML_INTEGER:
+ intgr = (int *)(*ptr);
+ *intgr = opaque ? atoi(opaque) : 0;
+ break;
+ case XML_BOOL:
+ bol = (bool *)(*ptr);
+ *bol = opaque && ((strcmp(opaque, "1") == 0) || (strcasecmp(opaque, "true") == 0));
+ break;
+ case XML_LINTEGER:
+ lint = (long int *)(*ptr);
+ *lint = opaque ? atol(opaque) : 0;
+ break;
+ case XML_TIME:
+ time = (time_t *)(*ptr);
+ *time = opaque ? atol(opaque) : 0;
+ break;
+ default:
+ break;
+ }
+
+ }
+ b = mxmlWalkNext(b, node, MXML_DESCEND);
+ }
+ return CWMP_OK;
+}
+
+int load_xml_node_data(int node_ref, mxml_node_t *node, struct xml_data_struct *xml_attrs)
+{
+ if (node_ref >= SOAP_MAX)
+ return CWMP_XML_ERR;
+ if (xml_nodes_data[node_ref].node_ms == XML_LIST) {
+ return load_xml_list_node_data(node_ref, node, xml_attrs);
+ } else {
+ return load_single_xml_node_data(node_ref, node, xml_attrs);
+ }
+ return CWMP_OK;
+}
+
+void cwmp_param_fault_list_to_xml_data_list(struct list_head *param_fault_list, struct list_head *xml_data_list)
+{
+ struct cwmp_param_fault *param_fault = NULL;
+ list_for_each_entry (param_fault, param_fault_list, list) {
+ if (!param_fault->fault)
+ continue;
+
+ struct xml_list_data *xml_data;
+
+ xml_data = calloc(1, sizeof(struct xml_list_data));
+ list_add_tail(&xml_data->list, xml_data_list);
+ int idx = cwmp_get_fault_code(param_fault->fault);
+ xml_data->param_name = strdup(param_fault->name);
+ xml_data->fault_code = atoi(FAULT_CPE_ARRAY[idx].CODE);
+ xml_data->fault_string = strdup(FAULT_CPE_ARRAY[idx].DESCRIPTION);
+ }
+}
+
+void dm_parameter_list_to_xml_data_list(struct list_head *dm_parameter_list, struct list_head *xml_data_list)
+{
+ struct cwmp_dm_parameter *param_value;
+ list_for_each_entry (param_value, dm_parameter_list, list) {
+ struct xml_list_data *xml_data;
+
+ xml_data = calloc(1, sizeof(struct xml_list_data));
+ list_add_tail(&xml_data->list, xml_data_list);
+ xml_data->param_name = strdup(param_value->name ? param_value->name : "");
+ xml_data->param_value = strdup(param_value->value ? param_value->value : "");
+ xml_data->param_type = strdup(param_value->type ? param_value->type : "");
+ xml_data->access_list = strdup(param_value->access_list ? param_value->access_list : "");
+ xml_data->notification = param_value->notification;
+ xml_data->writable = param_value->writable;
+ }
+}
+
+void xml_data_list_to_dm_parameter_list(struct list_head *xml_data_list, struct list_head *dm_parameter_list)
+{
+ struct xml_list_data *xml_data;
+ list_for_each_entry (xml_data, xml_data_list, list) {
+ struct cwmp_dm_parameter *dm_parameter;
+ dm_parameter = calloc(1, sizeof(struct cwmp_dm_parameter));
+ list_add_tail(&dm_parameter->list, dm_parameter_list);
+ dm_parameter->name = strdup(xml_data->param_name ? xml_data->param_name : "");
+ dm_parameter->value = strdup(xml_data->param_value ? xml_data->param_value : "");
+ dm_parameter->type = strdup(xml_data->param_type ? xml_data->param_type : "");
+ dm_parameter->access_list = strdup(xml_data->access_list ? xml_data->access_list : "");
+ dm_parameter->notification = xml_data->notification;
+ dm_parameter->writable =xml_data->notification;
+ }
+}
+
+void xml_data_list_to_cdu_operations_list(struct list_head *xml_data_list, struct list_head *cdu_operations_list)
+{
+ struct xml_list_data *xml_data;
+ list_for_each_entry (xml_data, xml_data_list, list) {
+ struct operations *operation;
+ operation = calloc(1, sizeof(struct operations));
+ list_add_tail(&operation->list, cdu_operations_list);
+ operation->url = strdup(xml_data->url ? xml_data->url : "");
+ operation->uuid = strdup(xml_data->uuid ? xml_data->uuid : "");
+ operation->username = strdup(xml_data->username ? xml_data->username : "");
+ operation->password = strdup(xml_data->password ? xml_data->password : "");
+ operation->executionenvref = strdup(xml_data->execution_env_ref ? xml_data->execution_env_ref : "");
+ operation->version = strdup(xml_data->version ? xml_data->version : "");
+ operation->type = xml_data->cdu_type;
+ }
+}
+
+void cdu_operations_list_to_xml_data_list(struct list_head *du_op_list, struct list_head *xml_data_list)
+{
+ struct opresult *du_opt_data = NULL;
+ list_for_each_entry (du_opt_data, du_op_list, list) {
+ struct xml_list_data *xml_data = calloc(1, sizeof(struct xml_list_data));
+ list_add_tail(&xml_data->list, xml_data_list);
+ xml_data->uuid = strdup(du_opt_data->uuid ? du_opt_data->uuid : "");
+ xml_data->du_ref = strdup(du_opt_data->du_ref ? du_opt_data->du_ref : "");
+ xml_data->version = strdup(du_opt_data->version ? du_opt_data->version : "");
+ xml_data->current_state = strdup(du_opt_data->current_state ? du_opt_data->current_state : "");
+ xml_data->start_time = strdup(du_opt_data->start_time ? du_opt_data->start_time : "");
+ xml_data->complete_time = strdup(du_opt_data->complete_time ? du_opt_data->complete_time : "");
+ xml_data->fault_code = du_opt_data->fault ? atoi(FAULT_CPE_ARRAY[du_opt_data->fault].CODE) : 0;
+ xml_data->fault_string = du_opt_data->fault ? strdup(FAULT_CPE_ARRAY[du_opt_data->fault].DESCRIPTION) : strdup("");
+ }
+}
+
+void event_container_list_to_xml_data_list(struct list_head *event_container_list, struct list_head *xml_data_list)
+{
+ struct event_container *event_container;
+
+ list_for_each_entry (event_container, event_container_list, list) {
+ struct xml_list_data *xml_data = calloc(1, sizeof(struct xml_list_data));
+ list_add_tail(&xml_data->list, xml_data_list);
+ xml_data->event_code = event_container->code;
+ xml_data->command_key = strdup(event_container->command_key);
+ }
+}
+
+void get_xml_data_value_by_name(int type, int idx, struct xml_data_struct *xml_attrs, char **data_value)
+{
+ char **str;
+ int *intgr;
+ bool *bol;
+ long int *lint;
+ time_t *time;
+
+ void **ptr = (void **)((char *)xml_attrs + idx * sizeof(char *));
+ switch(type) {
+ case XML_STRING:
+ str = (char **)(*ptr);
+ *data_value = icwmp_strdup(*str ? *str : "");
+ break;
+ case XML_INTEGER:
+ intgr = (int *)(*ptr);
+ icwmp_asprintf(data_value, "%d", *intgr);
+ break;
+ case XML_LINTEGER:
+ lint = (long int *)(*ptr);
+ icwmp_asprintf(data_value, "%ld", *lint);
+ break;
+ case XML_BOOL:
+ bol = (bool *)(*ptr);
+ *data_value = icwmp_strdup(bol ? "1" : "0");
+ break;
+ case XML_TIME:
+ time = (time_t *)(*ptr);
+ icwmp_asprintf(data_value, "%ld", *time);
+ break;
+ case XML_NODE:
+ *data_value = *ptr;
+ break;
+ default:
+ break;
+ }
+}
+
+void set_node_attributes(int attr_ref, mxml_node_t *node, struct xml_data_struct *xml_attrs)
+{
+ unsigned int i = 0;
+ size_t total_size = sizeof(xml_nodes_data[attr_ref].xml_tags) / sizeof(struct xml_tag);
+
+ for(i =0; i < total_size; i++) {
+ char *attr_value = NULL;
+ int idx = get_xml_tag_index(xml_nodes_data[attr_ref].xml_tags[i].tag_name);
+ if (idx == -1)
+ continue;
+ get_xml_data_value_by_name(xml_nodes_data[attr_ref].xml_tags[i].tag_type, idx, xml_attrs, &attr_value);
+ if (!attr_value)
+ continue;
+ mxmlElementSetAttr(node, xml_nodes_data[attr_ref].xml_tags[i].tag_name, attr_value);
+ }
+}
+
+int build_single_xml_node_data(int node_ref, mxml_node_t *node, struct xml_data_struct *xml_attrs)
+{
+ int i = 0, idx = 0;
+ mxml_node_t *n;
+ size_t total_size = sizeof(xml_nodes_data[node_ref].xml_tags) / sizeof(struct xml_tag);
+ for(i =0; i < (int)total_size; i++) {
+ if (xml_nodes_data[node_ref].xml_tags[i].tag_name == NULL)
+ continue;
+
+ n = mxmlNewElement(node, xml_nodes_data[node_ref].xml_tags[i].tag_name);
+ if (!n)
+ return CWMP_XML_ERR;
+
+ if (xml_nodes_data[node_ref].xml_tags[i].rec_ref >= ATTR_PARAM_STRUCT)
+ set_node_attributes(xml_nodes_data[node_ref].xml_tags[i].rec_ref, n, xml_attrs);
+
+ if (xml_nodes_data[node_ref].xml_tags[i].tag_type == XML_REC) {
+ if (xml_nodes_data[node_ref].xml_tags[i].rec_ref > 0)
+ build_xml_node_data(xml_nodes_data[node_ref].xml_tags[i].rec_ref, n, xml_attrs);
+ continue;
+ }
+
+ if (xml_nodes_data[node_ref].xml_tags[i].tag_type == XML_FUNC) {
+ if (xml_nodes_data[node_ref].xml_tags[i].xml_func) {
+ xml_nodes_data[node_ref].xml_tags[i].xml_func(n, xml_attrs);
+ }
+ continue;
+ }
+
+ idx = get_xml_tag_index(xml_nodes_data[node_ref].xml_tags[i].tag_name);
+ if (idx == -1)
+ continue;
+
+ if (xml_nodes_data[node_ref].xml_tags[i].tag_type == XML_NODE) {
+ mxml_node_t **t = NULL;
+ get_xml_data_value_by_name(xml_nodes_data[node_ref].xml_tags[i].tag_type, idx, xml_attrs, (char **)&t);
+ if (t != NULL)
+ *t = n;
+ continue;
+ }
+
+ char *opaque = NULL;
+ get_xml_data_value_by_name(xml_nodes_data[node_ref].xml_tags[i].tag_type, idx, xml_attrs, &opaque);
+
+ n = mxmlNewOpaque(n, opaque ? opaque : "");
+ if (!n)
+ return CWMP_XML_ERR;
+ }
+ return CWMP_OK;
+}
+
+int build_xml_list_node_data(int node_ref, mxml_node_t *node, struct xml_data_struct *xml_attrs)
+{
+ mxml_node_t *n;
+ struct xml_list_data *xml_data;
+ list_for_each_entry (xml_data, xml_attrs->data_list, list) {
+ if (xml_nodes_data[node_ref].tag_list_name) {
+ n = mxmlNewElement(node, xml_nodes_data[node_ref].tag_list_name);
+ if (!n)
+ return CWMP_XML_ERR;
+ } else {
+ n = node;
+ }
+ if (xml_nodes_data[node_ref].tag_node_ref > 0) {
+ struct xml_data_struct xml_ref_data = {0};
+ xml_ref_data.name = &xml_data->param_name;
+ xml_ref_data.parameter_name = &xml_data->param_name;
+ xml_ref_data.value = &xml_data->param_value;
+ xml_ref_data.string = &xml_data->rpc_name;
+ xml_ref_data.xsi_type = &xml_data->param_type;
+ xml_ref_data.notification = &xml_data->notification;
+ xml_ref_data.writable = &xml_data->writable;
+ xml_ref_data.access_list = &xml_data->access_list;
+ xml_ref_data.fault_string = &xml_data->fault_string;
+ xml_ref_data.fault_code = &xml_data->fault_code;
+ xml_ref_data.current_state = &xml_data->current_state;
+ xml_ref_data.du_ref = &xml_data->du_ref;
+
+ int fault = build_xml_node_data(xml_nodes_data[node_ref].tag_node_ref, n, &xml_ref_data);
+
+ if (fault != CWMP_OK)
+ return fault;
+ }
+ if (xml_attrs->counter != NULL)
+ *(xml_attrs->counter)+=1;
+ }
+ return 0;
+}
+
+int build_xml_node_data(int node_ref, mxml_node_t *node, struct xml_data_struct *xml_attrs)
+{
+ if (node_ref >= SOAP_MAX)
+ return CWMP_XML_ERR;
+
+ if (xml_nodes_data[node_ref].node_ms == XML_LIST ) {
+ return build_xml_list_node_data(node_ref, node, xml_attrs);
+ } else
+ return build_single_xml_node_data(node_ref, node, xml_attrs);
+ return CWMP_OK;
+}
+
+mxml_node_t * build_top_body_soap_response(mxml_node_t *node, char *method)
+{
+ mxml_node_t *n = mxmlFindElement(node, node, "soap_env:Body", NULL, NULL, MXML_DESCEND);
+
+ if (!n)
+ return NULL;
+
+ char method_resp[128];
+ snprintf(method_resp, sizeof(method_resp), "cwmp:%sResponse", method);
+ n = mxmlNewElement(n, method_resp);
+
+ if (!n)
+ return NULL;
+
+ return n;
+}
+
+mxml_node_t * build_top_body_soap_request(mxml_node_t *node, char *method)
+{
+ mxml_node_t *n = mxmlFindElement(node, node, "soap_env:Body", NULL, NULL, MXML_DESCEND);
+
+ if (!n)
+ return NULL;
+
+ char method_resp[128];
+ snprintf(method_resp, sizeof(method_resp), "cwmp:%s", method);
+ n = mxmlNewElement(n, method_resp);
+
+ if (!n)
+ return NULL;
+
+ return n;
+}
+
+mxml_node_t * /* O - Element node or NULL */
+mxmlFindElementOpaque(mxml_node_t *node, /* I - Current node */
+ mxml_node_t *top, /* I - Top node */
+ const char *text, /* I - Element text, if NULL return NULL */
+ int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
+{
+ if (!node || !top || !text)
+ return (NULL);
+
+ node = mxmlWalkNext(node, top, descend);
+
+ while (node != NULL) {
+ const char *op = mxmlGetOpaque(node);
+ if (mxmlGetType(node) == MXML_OPAQUE && op && (!strcmp(op, text))) {
+ return (node);
+ }
+
+ if (descend == MXML_DESCEND)
+ node = mxmlWalkNext(node, top, MXML_DESCEND);
+ else
+ node = mxmlGetNextSibling(node);
+ }
+ return (NULL);
+}
+
+char *xml__get_attribute_name_by_value(mxml_node_t *node, const char *value)
+{
+ int attributes_nbre = mxmlElementGetAttrCount(node);
+ int i;
+ for (i = 0; i < attributes_nbre; i++) {
+ char *attr_name = NULL;
+ const char *attr_value = mxmlElementGetAttrByIndex(node, i, (const char **)&attr_name);
+ if (strcmp(attr_value, value) == 0)
+ return attr_name;
+ }
+ return NULL;
+}
+
+int xml_recreate_namespace(mxml_node_t *tree)
+{
+ const char *cwmp_urn;
+ int i;
+ mxml_node_t *b = tree;
+
+ do {
+ char *c;
+ FREE(ns.soap_env);
+ FREE(ns.soap_enc);
+ FREE(ns.xsd);
+ FREE(ns.xsi);
+ FREE(ns.cwmp);
+
+ c = (char *)xml__get_attribute_name_by_value(b, soap_env_url);
+ if (c && *(c + 5) == ':') {
+ ns.soap_env = strdup((c + 6));
+ } else {
+ continue;
+ }
+
+ c = (char *)xml__get_attribute_name_by_value(b, soap_enc_url);
+ if (c && *(c + 5) == ':') {
+ ns.soap_enc = strdup((c + 6));
+ } else {
+ continue;
+ }
+
+ c = (char *)xml__get_attribute_name_by_value(b, xsd_url);
+ if (c && *(c + 5) == ':') {
+ ns.xsd = strdup((c + 6));
+ } else {
+ continue;
+ }
+
+ c = (char *)xml__get_attribute_name_by_value(b, xsi_url);
+ if (c && *(c + 5) == ':') {
+ ns.xsi = strdup((c + 6));
+ } else {
+ continue;
+ }
+
+ for (i = 0; cwmp_urls[i] != NULL; i++) {
+ cwmp_urn = cwmp_urls[i];
+ c = (char *)xml__get_attribute_name_by_value(b, cwmp_urn);
+ if (c && *(c + 5) == ':') {
+ ns.cwmp = strdup((c + 6));
+ break;
+ }
+ }
+
+ if (!ns.cwmp)
+ continue;
+
+ return 0;
+ } while ((b = mxmlWalkNext(b, tree, MXML_DESCEND)));
+
+ return -1;
+}
+
+void xml_exit(void)
+{
+ FREE(ns.soap_env);
+ FREE(ns.soap_enc);
+ FREE(ns.xsd);
+ FREE(ns.xsi);
+ FREE(ns.cwmp);
+}
+
+int xml_send_message(struct cwmp *cwmp, struct session *session, 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) {
+ unsigned char *zmsg_out;
+ msg_out = mxmlSaveAllocString(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)) {
+ return -1;
+ }
+ FREE(msg_out);
+ msg_out = (char *)zmsg_out;
+ } else {
+ msg_out_len = strlen(msg_out);
+ }
+ }
+ while (1) {
+ f = 0;
+ if (icwmp_http_send_message(cwmp, msg_out, msg_out_len, &msg_in)) {
+ goto error;
+ }
+ if (msg_in) {
+ CWMP_LOG_XML_MSG(DEBUG, msg_in, XML_MSG_IN);
+ if ((s = strstr(msg_in, "")))
+ sscanf(s, "%d", &f);
+ if (f) {
+ if (f == 8005) {
+ r++;
+ if (r < 5) {
+ FREE(msg_in);
+ continue;
+ }
+ goto error;
+ } else if (rpc && rpc->type != RPC_ACS_INFORM) {
+ break;
+ } else {
+ goto error;
+ }
+ } else {
+ break;
+ }
+ } else {
+ goto end;
+ }
+ }
+
+ session->tree_in = mxmlLoadString(NULL, msg_in, MXML_OPAQUE_CALLBACK);
+ if (!session->tree_in)
+ goto error;
+ xml_recreate_namespace(session->tree_in);
+ /* get NoMoreRequests or HolRequest*/
+ 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);
+ if (b) {
+ b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST);
+ if (b && mxmlGetType(b) == MXML_OPAQUE && mxmlGetOpaque(b))
+ session->hold_request = atoi(mxmlGetOpaque(b));
+ } 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);
+ if (b) {
+ b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST);
+ if (b && mxmlGetType(b) == MXML_OPAQUE && mxmlGetOpaque(b))
+ session->hold_request = atoi(mxmlGetOpaque(b));
+ }
+ }
+
+end:
+ FREE(msg_out);
+ FREE(msg_in);
+ return 0;
+
+error:
+ FREE(msg_out);
+ FREE(msg_in);
+ return -1;
+}
+
+int xml_prepare_msg_out(struct session *session)
+{
+ struct cwmp *cwmp = &cwmp_main;
+ struct config *conf;
+ conf = &(cwmp->conf);
+ mxml_node_t *n;
+
+ load_response_xml_schema(&session->tree_out);
+ if (!session->tree_out)
+ return -1;
+
+ n = mxmlFindElement(session->tree_out, 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)
+ return -1;
+
+ return 0;
+}
+
+int xml_set_cwmp_id(struct session *session)
+{
+ char c[32];
+ mxml_node_t *b;
+
+ /* define cwmp id */
+ 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);
+ if (!b)
+ return -1;
+
+ b = mxmlNewOpaque(b, c);
+ if (!b)
+ return -1;
+
+ return 0;
+}
+
+int xml_set_cwmp_id_rpc_cpe(struct session *session)
+{
+ char c[512];
+ mxml_node_t *b;
+
+ /* handle cwmp:ID */
+ 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);
+
+ if (b) {
+ /* ACS send ID parameter */
+ b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST);
+ if (!b || mxmlGetType(b) != MXML_OPAQUE || !mxmlGetOpaque(b))
+ return 0;
+ snprintf(c, sizeof(c), "%s", mxmlGetOpaque(b));
+
+ b = mxmlFindElement(session->tree_out, session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND);
+ if (!b)
+ return -1;
+
+ b = mxmlNewOpaque(b, c);
+ if (!b)
+ return -1;
+ } else {
+ /* ACS does not send ID parameter */
+ int r = xml_set_cwmp_id(session);
+ return r;
+ }
+ return 0;
+}
+
+const char *get_node_tab_space(mxml_node_t *node)
+{
+ static char tab_space[10 * sizeof(CWMP_MXML_TAB_SPACE) + 1];
+ int count = 0;
+
+ memset(tab_space, 0, sizeof(tab_space));
+ while ((node = mxmlGetParent(node))) {
+ count = count + 1;
+ }
+
+ if (count) {
+ snprintf(tab_space, sizeof(tab_space), "%*s", (int)(count * sizeof(CWMP_MXML_TAB_SPACE)), "");
+ }
+
+ return tab_space;
+}
+
+const char *whitespace_cb(mxml_node_t *node, int where __attribute__((unused)))
+{
+ if (mxmlGetType(node) != MXML_ELEMENT)
+ return NULL;
+
+ switch (where) {
+ case MXML_WS_BEFORE_CLOSE:
+ if (mxmlGetFirstChild(node) && mxmlGetType(mxmlGetFirstChild(node)) != MXML_ELEMENT)
+ return NULL;
+
+ return get_node_tab_space(node);
+ case MXML_WS_BEFORE_OPEN:
+ if (where == MXML_WS_BEFORE_CLOSE && mxmlGetFirstChild(node) && mxmlGetType(mxmlGetFirstChild(node)) != MXML_ELEMENT)
+ return NULL;
+
+ return get_node_tab_space(node);
+ case MXML_WS_AFTER_OPEN:
+ return ((mxmlGetFirstChild(node) == NULL || mxmlGetType(mxmlGetFirstChild(node)) == MXML_ELEMENT) ? "\n" : NULL);
+ case MXML_WS_AFTER_CLOSE:
+ return "\n";
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+char *xml_get_cwmp_version(int version)
+{
+ static char versions[60];
+ unsigned pos = 0;
+ int k;
+
+ versions[0] = '\0';
+ for (k = 0; k < version; k++) {
+ pos += snprintf(&versions[pos], sizeof(versions) - pos, "1.%d, ", k);
+ }
+
+ if (pos)
+ versions[pos - 2] = 0;
+
+ return versions;
+}
+
+static int xml_prepare_lwnotifications(mxml_node_t *parameter_list)
+{
+ mxml_node_t *b, *n;
+
+ struct list_head *p;
+ struct cwmp_dm_parameter *lw_notification;
+ list_for_each (p, &list_lw_value_change) {
+ lw_notification = list_entry(p, struct cwmp_dm_parameter, list);
+
+ n = mxmlNewElement(parameter_list, "Param");
+ if (!n)
+ goto error;
+
+ b = mxmlNewElement(n, "Name");
+ if (!b)
+ goto error;
+
+ b = mxmlNewOpaque(b, lw_notification->name);
+ if (!b)
+ goto error;
+
+ b = mxmlNewElement(n, "Value");
+ if (!b)
+ goto error;
+ mxmlElementSetAttr(b, "xsi:type", lw_notification->type);
+ b = mxmlNewOpaque(b, lw_notification->value);
+ if (!b)
+ goto error;
+ }
+ return 0;
+
+error:
+ return -1;
+}
+
+int xml_prepare_lwnotification_message(char **msg_out)
+{
+ mxml_node_t *lw_tree;
+
+ load_notification_xml_schema(&lw_tree);
+ if (!lw_tree)
+ goto error;
+
+ *msg_out = mxmlSaveAllocString(lw_tree, whitespace_cb);
+
+ mxmlDelete(lw_tree);
+ return 0;
+
+error:
+ return -1;
+}
+
+void load_notification_xml_schema(mxml_node_t **tree)
+{
+ char declaration[1024] = {0};
+ struct cwmp *cwmp = &cwmp_main;
+ struct config *conf;
+ conf = &(cwmp->conf);
+ char *c = NULL;
+
+ if (tree == NULL)
+ return;
+
+ *tree = NULL;
+
+ snprintf(declaration, sizeof(declaration), "?xml version=\"1.0\" encoding=\"UTF-8\"?");
+ mxml_node_t *xml = mxmlNewElement(NULL, declaration);
+ if (xml == NULL)
+ return;
+
+ mxml_node_t *notification = mxmlNewElement(xml, "Notification");
+ if (notification == NULL) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ mxmlElementSetAttr(notification, "xmlns", "urn:broadband-forum-org:cwmp:lwnotif-1-0");
+ mxmlElementSetAttr(notification, "xmlns:xs", xsd_url);
+ mxmlElementSetAttr(notification, "xmlns:xsi", xsi_url);
+ mxmlElementSetAttr(notification, "xsi:schemaLocation", "urn:broadband-forum-org:cwmp:lxnotif-1-0 http://www.broadband-forum.org/cwmp/cwmp-UDPLightweightNotification-1-0.xsd");
+
+ mxml_node_t *ts = mxmlNewElement(notification, "TS");
+ if (ts == NULL) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ if (cwmp_asprintf(&c, "%ld", time(NULL)) == -1) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ if (NULL == mxmlNewOpaque(ts, c)) {
+ FREE(c);
+ MXML_DELETE(xml);
+ return;
+ }
+
+ FREE(c);
+
+ mxml_node_t *un = mxmlNewElement(notification, "UN");
+ if (un == NULL) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ if (NULL == mxmlNewOpaque(un, conf->acs_userid)) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ mxml_node_t *cn = mxmlNewElement(notification, "CN");
+ if (cn == NULL) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ c = (char *)calculate_lwnotification_cnonce();
+ if (!c) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ if (NULL == mxmlNewOpaque(cn, c)) {
+ FREE(c);
+ MXML_DELETE(xml);
+ return;
+ }
+
+ FREE(c);
+
+ mxml_node_t *oui = mxmlNewElement(notification, "OUI");
+ if (oui == NULL) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ if (NULL == mxmlNewOpaque(oui, cwmp->deviceid.oui)) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ mxml_node_t *pclass = mxmlNewElement(notification, "ProductClass");
+ if (pclass == NULL) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ if (NULL == mxmlNewOpaque(pclass, cwmp->deviceid.productclass ? cwmp->deviceid.productclass : "")) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ mxml_node_t *slno = mxmlNewElement(notification, "SerialNumber");
+ if (slno == NULL) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ if (NULL == mxmlNewOpaque(slno, cwmp->deviceid.serialnumber ? cwmp->deviceid.serialnumber : "")) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ if (xml_prepare_lwnotifications(notification)) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ *tree = xml;
+}
+
+void load_response_xml_schema(mxml_node_t **schema)
+{
+ char declaration[1024] = {0};
+
+ if (schema == NULL)
+ return;
+
+ *schema = NULL;
+
+ snprintf(declaration, sizeof(declaration), "?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?");
+ mxml_node_t *xml = mxmlNewElement(NULL, declaration);
+ if (xml == NULL)
+ return;
+
+ mxml_node_t *envlp = mxmlNewElement(xml, "soap_env:Envelope");
+ if (envlp == NULL) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ mxmlElementSetAttr(envlp, "xmlns:soap_env", soap_env_url);
+ mxmlElementSetAttr(envlp, "xmlns:soap_enc", soap_enc_url);
+ mxmlElementSetAttr(envlp, "xmlns:xsd", xsd_url);
+ mxmlElementSetAttr(envlp, "xmlns:xsi", xsi_url);
+
+ mxml_node_t *header = mxmlNewElement(envlp, "soap_env:Header");
+ if (header == NULL) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ mxml_node_t *id = mxmlNewElement(header, "cwmp:ID");
+ if (id == NULL) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ mxmlElementSetAttr(id, "soap_env:mustUnderstand", "1");
+
+ if (NULL == mxmlNewElement(envlp, "soap_env:Body")) {
+ MXML_DELETE(xml);
+ return;
+ }
+
+ *schema = xml;
+}
diff --git a/src/xml.h b/src/xml.h
new file mode 100644
index 0000000..7d2c134
--- /dev/null
+++ b/src/xml.h
@@ -0,0 +1,255 @@
+#ifndef __XML__H_
+#define __XML__H_
+
+#include "xml_utils.h"
+#include "session.h"
+#include "common.h"
+
+#define CWMP_MXML_TAB_SPACE " "
+#define MAX_SCHEDULE_INFORM_QUEUE 10
+
+#define XML2(A,B) {A, B, 0, NULL}
+#define XML3(A,B,C) {A, B, C, NULL}
+#define XML4(A,B,D) {A, B, 0, D}
+enum soap_methods {
+ SOAP_REQ_SPV = 1,
+ SOAP_REQ_GPV,
+ SOAP_REQ_GPN,
+ SOAP_REQ_SPA,
+ SOAP_REQ_GPA,
+ SOAP_REQ_ADDOBJ,
+ SOAP_REQ_DELOBJ,
+ SOAP_REQ_REBOOT,
+ SOAP_REQ_DOWNLOAD,
+ SOAP_REQ_UPLOAD,
+ SOAP_REQ_CANCELTRANSFER,
+ SOAP_REQ_SCHEDINF,
+ SOAP_REQ_SCHEDDOWN,
+ SOAP_REQ_CDU,
+ SOAP_REQ_SPV_LIST,
+ SOAP_REQ_SPV_LIST_REF,
+ SOAP_REQ_GPV_REF,
+ SOAP_REQ_SPA_REF,
+ SOAP_REQ_GPA_REF,
+ SOAP_TIMEWINDOW_REF,
+ SOAP_TIME_REF,
+ SOAP_REQ_CDU_OPERATIONS,
+ SOAP_REQ_CDU_OPS_REF,
+ SOAP_REQ_DU_INSTALL,
+ SOAP_REQ_DU_UPDATE,
+ SOAP_REQ_DU_UNINSTALL,
+
+ SOAP_RESP_GPV,
+ SOAP_PARAM_STRUCT,
+ SOAP_PARAM_STRUCT_REF,
+ SOAP_VALUE_STRUCT,
+ SOAP_RESP_SPV,
+ SOAP_RESP_GPN,
+ SOAP_RESP_GPN_REF,
+ SOAP_RESP_GPA,
+ SOAP_RESP_GPA_REF,
+ SOAP_RESP_ADDOBJ,
+ SOAP_RESP_DELOBJ,
+ SOAP_RESP_DOWNLOAD,
+ SOAP_RESP_UPLOAD,
+ SOAP_RESP_GETRPC,
+ SOAP_RESP_GETRPC_REF,
+ SOAP_ACS_TRANSCOMPLETE,
+ SOAP_ROOT_FAULT,
+ SOAP_RPC_FAULT,
+ SOAP_FAULT_DETAIL,
+ SOAP_CWMP_FAULT,
+ SOAP_SPV_FAULT,
+ SOAP_SPV_FAULT_REF,
+ SOAP_FAULT_STRCT_REF,
+ SOAP_ENV,
+ SOAP_HEAD,
+ SOAP_BODY,
+ SOAP_INFORM_CWMP,
+ SOAP_DEVID,
+ SOAP_DU_CHANGE_COMPLETE,
+ SOAP_CDU_RESULTS_REF,
+ SOAP_CDU_OPTS_REF,
+ ATTR_PARAM_STRUCT,
+ ATTR_SOAP_ENV,
+ SOAP_MAX
+};
+
+enum xml_tag_types {
+ XML_STRING,
+ XML_BOOL,
+ XML_INTEGER,
+ XML_LINTEGER,
+ XML_TIME,
+ XML_FUNC,
+ XML_REC,
+ XML_NODE,
+ XML_ATTR
+};
+
+enum tag_multiple_single {
+ XML_SINGLE,
+ XML_LIST
+};
+
+enum validation_types {
+ VALIDATE_STR_SIZE,
+ VALIDATE_UNINT,
+ VALIDATE_BOOLEAN,
+ VALIDATE_INT_RANGE
+};
+
+struct xml_tag_validation {
+ char *tag_name;
+ int validation_type;
+ int min;
+ int max;
+};
+
+struct xml_data_struct {
+ mxml_node_t **parameter_list;
+ char **name;
+ char **value;
+ char **string;
+ char **parameter_path;
+ char **parameter_name;
+ char **object_name;
+ char **parameter_key;
+ char **command_key;
+ char **file_type;
+ char **url;
+ char **username;
+ char **password;
+ char **uuid;
+ char **exec_env_ref;
+ char **du_ref;
+ char **current_state;
+ char **version;
+ char **window_mode;
+ char **user_message;
+ char **start_time;
+ char **complete_time;
+ char **access_list;
+ char **fault_string;
+ char **faultcode;
+ char **faultstring;
+ char **manufacturer;
+ char **oui;
+ char **serial_number;
+ char **current_time;
+ char **product_class;
+ char **xsi_type;
+ int *file_size;
+ int *notification;
+ int *scheddown_max_retries;
+ int *status;
+ int *instance;
+ int *fault_code;
+ int *max_envelopes;
+ int *retry_count;
+ long int *delay_seconds;
+ long int *window_start;
+ long int *window_end;
+ bool *next_level;
+ bool *notification_change;
+ bool *writable;
+
+ mxml_node_t **xml_env;
+ struct list_head *data_list;
+ char **xcwmp;
+ int *amd_version;
+ unsigned int *session_timeout;
+ int *cdu_type;
+ int *counter;
+ struct xml_tag_validation *validations;
+ int nbre_validations;
+};
+
+struct xml_list_data {
+ struct list_head list;
+ char *param_name;
+ char *param_value;
+ char *param_type;
+ char *windowmode;
+ char *usermessage;
+ char *access_list;
+ char *rpc_name;
+ char *fault_string;
+ char *url;
+ char *uuid;
+ char *username;
+ char *password;
+ char *execution_env_ref;
+ char *version;
+ char *du_ref;
+ char *current_state;
+ char *start_time;
+ char *complete_time;
+ char *command_key;
+
+ long int windowstart;
+ long int windowend;
+ int max_retries;
+ int notification;
+ int fault_code;
+ int cdu_type;
+ int event_code;
+ bool notification_change;
+ bool writable;
+};
+
+struct xml_tag {
+ char *tag_name;
+ int tag_type;
+ int rec_ref;
+ int (*xml_func)(mxml_node_t *node, struct xml_data_struct *xml_attrs);
+};
+
+struct xml_node_data {
+ int node_ms;
+ int tag_node_ref;
+ char *tag_list_name;
+ struct xml_tag xml_tags[10];
+};
+
+#define MXML_DELETE(X) \
+ do { \
+ if (X) { \
+ mxmlDelete(X); \
+ X = NULL; \
+ } \
+ } while (0)
+
+extern const char *cwmp_urls[];
+int xml_prepare_msg_out(struct session *session);
+int xml_prepare_lwnotification_message(char **msg_out);
+int xml_set_cwmp_id_rpc_cpe(struct session *session);
+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);
+mxml_node_t *mxmlFindElementOpaque(mxml_node_t *node, mxml_node_t *top, const char *text, int descend);
+char *xml__get_attribute_name_by_value(mxml_node_t *node, const char *value);
+char *xml_get_cwmp_version(int version);
+void xml_exit(void);
+void load_response_xml_schema(mxml_node_t **schema);
+void load_notification_xml_schema(mxml_node_t **tree);
+int load_xml_node_data(int node_ref, mxml_node_t *node, struct xml_data_struct *xml_attrs);
+int build_xml_node_data(int node_ref, mxml_node_t *node, struct xml_data_struct *xml_attrs);
+void add_xml_data_list(struct list_head *data_list, struct xml_list_data *xml_data);
+mxml_node_t * build_top_body_soap_response(mxml_node_t *node, char *method);
+mxml_node_t * build_top_body_soap_request(mxml_node_t *node, char *method);
+void dm_parameter_list_to_xml_data_list(struct list_head *dm_parameter_list, struct list_head *xml_data_list);
+void xml_data_list_to_dm_parameter_list(struct list_head *xml_data_list, struct list_head *dm_parameter_list);
+void xml_data_list_to_cdu_operations_list(struct list_head *xml_data_list, struct list_head *du_op_list);
+void cdu_operations_list_to_xml_data_list(struct list_head *du_op_list, struct list_head *xml_data_list);
+void event_container_list_to_xml_data_list(struct list_head *event_container, struct list_head *xml_data_list);
+void cwmp_param_fault_list_to_xml_data_list(struct list_head *param_fault_list, struct list_head *xml_data_list);
+void cwmp_free_all_xml_data_list(struct list_head *list);
+int load_upload_filetype(mxml_node_t *b, struct xml_data_struct *xml_attrs);
+int load_download_filetype(mxml_node_t *b, struct xml_data_struct *xml_attrs);
+int load_sched_download_window_mode(mxml_node_t *b, struct xml_data_struct *xml_attrs);
+int load_change_du_state_operation(mxml_node_t *b, struct xml_data_struct *xml_attrs);
+int build_inform_events(mxml_node_t *b, struct xml_data_struct *xml_attrs);
+int build_inform_env_header(mxml_node_t *b, struct xml_data_struct *xml_attrs);
+#endif
diff --git a/inc/xml_utils.h b/src/xml_utils.h
similarity index 100%
rename from inc/xml_utils.h
rename to src/xml_utils.h
diff --git a/test/cmocka/Makefile b/test/cmocka/Makefile
index 2c4a809..2537146 100644
--- a/test/cmocka/Makefile
+++ b/test/cmocka/Makefile
@@ -4,20 +4,20 @@ LIB_LDFLAGS:= -luci -lblobmsg_json -lubox\
-ljson-c -lubus -lpthread -lcurl\
-lcrypto -lmxml
-LIB_CFLAGS:= -fPIC -I../../inc -DLOPENSSL -g -O0
+LIB_CFLAGS:= -fPIC -I../../src/ -DLOPENSSL -g -O0
UNIT_TESTS:= icwmp_unit_testd
VALGRIND = /usr/bin/valgrind --xml=yes --xml-file=memory-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all
-
-ICWMP_SOURCES=$(patsubst ./%.c, ../../%.c, $(icwmpd_SOURCES))
-ICWMP_OBJS=$(patsubst ../../%.c, %.o, $(ICWMP_SOURCES))
+
+ICWMP_SOURCES=$(patsubst ./src/%.c, ../../src/%.c, $(icwmpd_SOURCES))
+ICWMP_OBJS=$(patsubst ../../src/%.c, %.o, $(ICWMP_SOURCES))
TEST_SRCS = $(wildcard *.c)
TEST_OBJS = $(TEST_SRCS:=.o)
%.c.o: %.c
- $(CC) -g -O0 -I../../inc -c -o $@ $<
+ $(CC) -g -O0 -I../../src/ -c -o $@ $<
-%.o: ../../%.c
+%.o: ../../src/%.c
$(CC) ${LIB_CFLAGS} -c -o $@ $<
libunit: ${ICWMP_OBJS}
diff --git a/test/cmocka/icwmp_custom_inform_parameters_unit_test.c b/test/cmocka/icwmp_custom_inform_parameters_unit_test.c
index 8293eda..0d04503 100644
--- a/test/cmocka/icwmp_custom_inform_parameters_unit_test.c
+++ b/test/cmocka/icwmp_custom_inform_parameters_unit_test.c
@@ -18,7 +18,7 @@
#include "common.h"
#include "config.h"
-#include "rpc_soap.h"
+#include "rpc.h"
static struct cwmp cwmp_main_test = { 0 };
diff --git a/test/cmocka/icwmp_datamodel_interface_unit_test.c b/test/cmocka/icwmp_datamodel_interface_unit_test.c
index 057fc68..d4009f6 100644
--- a/test/cmocka/icwmp_datamodel_interface_unit_test.c
+++ b/test/cmocka/icwmp_datamodel_interface_unit_test.c
@@ -19,7 +19,7 @@
#include "datamodel_interface.h"
#include "event.h"
#include "xml.h"
-#include "rpc_soap.h"
+#include "rpc.h"
#include "session.h"
#include "log.h"
diff --git a/test/cmocka/icwmp_soap_msg_unit_test.c b/test/cmocka/icwmp_soap_msg_unit_test.c
index ec225b2..3e0faad 100644
--- a/test/cmocka/icwmp_soap_msg_unit_test.c
+++ b/test/cmocka/icwmp_soap_msg_unit_test.c
@@ -16,7 +16,7 @@
#include
#include
-#include "rpc_soap.h"
+#include "rpc.h"
#include "event.h"
#include "session.h"
#include "config.h"
diff --git a/xml.c b/xml.c
deleted file mode 100644
index 2091036..0000000
--- a/xml.c
+++ /dev/null
@@ -1,577 +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-2021 iopsys Software Solutions AB
- * Author Mohamed Kallel
- * Author Ahmed Zribi
- * Author Omar Kallel
- */
-
-#include "xml.h"
-#include "log.h"
-#include "notifications.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/";
-static const char *xsd_url = "http://www.w3.org/2001/XMLSchema";
-static const char *xsi_url = "http://www.w3.org/2001/XMLSchema-instance";
-
-const char *cwmp_urls[] = { "urn:dslforum-org:cwmp-1-0", "urn:dslforum-org:cwmp-1-1", "urn:dslforum-org:cwmp-1-2", "urn:dslforum-org:cwmp-1-2", "urn:dslforum-org:cwmp-1-2", "urn:dslforum-org:cwmp-1-2", NULL };
-
-mxml_node_t * /* O - Element node or NULL */
-mxmlFindElementOpaque(mxml_node_t *node, /* I - Current node */
- mxml_node_t *top, /* I - Top node */
- const char *text, /* I - Element text, if NULL return NULL */
- int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
-{
- if (!node || !top || !text)
- return (NULL);
-
- node = mxmlWalkNext(node, top, descend);
-
- while (node != NULL) {
- const char *op = mxmlGetOpaque(node);
- if (mxmlGetType(node) == MXML_OPAQUE && op && (!strcmp(op, text))) {
- return (node);
- }
-
- if (descend == MXML_DESCEND)
- node = mxmlWalkNext(node, top, MXML_DESCEND);
- else
- node = mxmlGetNextSibling(node);
- }
- return (NULL);
-}
-
-char *xml__get_attribute_name_by_value(mxml_node_t *node, const char *value)
-{
- int attributes_nbre = mxmlElementGetAttrCount(node);
- int i;
- for (i = 0; i < attributes_nbre; i++) {
- char *attr_name = NULL;
- const char *attr_value = mxmlElementGetAttrByIndex(node, i, (const char **)&attr_name);
- if (strcmp(attr_value, value) == 0)
- return attr_name;
- }
- return NULL;
-}
-
-int xml_recreate_namespace(mxml_node_t *tree)
-{
- const char *cwmp_urn;
- int i;
- mxml_node_t *b = tree;
-
- do {
- char *c;
- FREE(ns.soap_env);
- FREE(ns.soap_enc);
- FREE(ns.xsd);
- FREE(ns.xsi);
- FREE(ns.cwmp);
-
- c = (char *)xml__get_attribute_name_by_value(b, soap_env_url);
- if (c && *(c + 5) == ':') {
- ns.soap_env = strdup((c + 6));
- } else {
- continue;
- }
-
- c = (char *)xml__get_attribute_name_by_value(b, soap_enc_url);
- if (c && *(c + 5) == ':') {
- ns.soap_enc = strdup((c + 6));
- } else {
- continue;
- }
-
- c = (char *)xml__get_attribute_name_by_value(b, xsd_url);
- if (c && *(c + 5) == ':') {
- ns.xsd = strdup((c + 6));
- } else {
- continue;
- }
-
- c = (char *)xml__get_attribute_name_by_value(b, xsi_url);
- if (c && *(c + 5) == ':') {
- ns.xsi = strdup((c + 6));
- } else {
- continue;
- }
-
- for (i = 0; cwmp_urls[i] != NULL; i++) {
- cwmp_urn = cwmp_urls[i];
- c = (char *)xml__get_attribute_name_by_value(b, cwmp_urn);
- if (c && *(c + 5) == ':') {
- ns.cwmp = strdup((c + 6));
- break;
- }
- }
-
- if (!ns.cwmp)
- continue;
-
- return 0;
- } while ((b = mxmlWalkNext(b, tree, MXML_DESCEND)));
-
- return -1;
-}
-
-void xml_exit(void)
-{
- FREE(ns.soap_env);
- FREE(ns.soap_enc);
- FREE(ns.xsd);
- FREE(ns.xsi);
- FREE(ns.cwmp);
-}
-
-int xml_send_message(struct cwmp *cwmp, struct session *session, 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) {
- unsigned char *zmsg_out;
- msg_out = mxmlSaveAllocString(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)) {
- return -1;
- }
- FREE(msg_out);
- msg_out = (char *)zmsg_out;
- } else {
- msg_out_len = strlen(msg_out);
- }
- }
- while (1) {
- f = 0;
- if (http_send_message(cwmp, msg_out, msg_out_len, &msg_in)) {
- goto error;
- }
- if (msg_in) {
- CWMP_LOG_XML_MSG(DEBUG, msg_in, XML_MSG_IN);
- if ((s = strstr(msg_in, "")))
- sscanf(s, "%d", &f);
- if (f) {
- if (f == 8005) {
- r++;
- if (r < 5) {
- FREE(msg_in);
- continue;
- }
- goto error;
- } else if (rpc && rpc->type != RPC_ACS_INFORM) {
- break;
- } else {
- goto error;
- }
- } else {
- break;
- }
- } else {
- goto end;
- }
- }
-
- session->tree_in = mxmlLoadString(NULL, msg_in, MXML_OPAQUE_CALLBACK);
- if (!session->tree_in)
- goto error;
- xml_recreate_namespace(session->tree_in);
- /* get NoMoreRequests or HolRequest*/
- 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);
- if (b) {
- b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST);
- if (b && mxmlGetType(b) == MXML_OPAQUE && mxmlGetOpaque(b))
- session->hold_request = atoi(mxmlGetOpaque(b));
- } 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);
- if (b) {
- b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST);
- if (b && mxmlGetType(b) == MXML_OPAQUE && mxmlGetOpaque(b))
- session->hold_request = atoi(mxmlGetOpaque(b));
- }
- }
-
-end:
- FREE(msg_out);
- FREE(msg_in);
- return 0;
-
-error:
- FREE(msg_out);
- FREE(msg_in);
- return -1;
-}
-
-int xml_prepare_msg_out(struct session *session)
-{
- struct cwmp *cwmp = &cwmp_main;
- struct config *conf;
- conf = &(cwmp->conf);
- mxml_node_t *n;
-
- load_response_xml_schema(&session->tree_out);
- if (!session->tree_out)
- return -1;
-
- n = mxmlFindElement(session->tree_out, 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)
- return -1;
-
- return 0;
-}
-
-int xml_set_cwmp_id(struct session *session)
-{
- char c[32];
- mxml_node_t *b;
-
- /* define cwmp id */
- 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);
- if (!b)
- return -1;
-
- b = mxmlNewOpaque(b, c);
- if (!b)
- return -1;
-
- return 0;
-}
-
-int xml_set_cwmp_id_rpc_cpe(struct session *session)
-{
- char c[512];
- mxml_node_t *b;
-
- /* handle cwmp:ID */
- 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);
-
- if (b) {
- /* ACS send ID parameter */
- b = mxmlWalkNext(b, session->tree_in, MXML_DESCEND_FIRST);
- if (!b || mxmlGetType(b) != MXML_OPAQUE || !mxmlGetOpaque(b))
- return 0;
- snprintf(c, sizeof(c), "%s", mxmlGetOpaque(b));
-
- b = mxmlFindElement(session->tree_out, session->tree_out, "cwmp:ID", NULL, NULL, MXML_DESCEND);
- if (!b)
- return -1;
-
- b = mxmlNewOpaque(b, c);
- if (!b)
- return -1;
- } else {
- /* ACS does not send ID parameter */
- int r = xml_set_cwmp_id(session);
- return r;
- }
- return 0;
-}
-
-const char *get_node_tab_space(mxml_node_t *node)
-{
- static char tab_space[10 * sizeof(CWMP_MXML_TAB_SPACE) + 1];
- int count = 0;
-
- memset(tab_space, 0, sizeof(tab_space));
- while ((node = mxmlGetParent(node))) {
- count = count + 1;
- }
-
- if (count) {
- snprintf(tab_space, sizeof(tab_space), "%*s", (int)(count * sizeof(CWMP_MXML_TAB_SPACE)), "");
- }
-
- return tab_space;
-}
-
-const char *whitespace_cb(mxml_node_t *node, int where __attribute__((unused)))
-{
- if (mxmlGetType(node) != MXML_ELEMENT)
- return NULL;
-
- switch (where) {
- case MXML_WS_BEFORE_CLOSE:
- if (mxmlGetFirstChild(node) && mxmlGetType(mxmlGetFirstChild(node)) != MXML_ELEMENT)
- return NULL;
-
- return get_node_tab_space(node);
- case MXML_WS_BEFORE_OPEN:
- if (where == MXML_WS_BEFORE_CLOSE && mxmlGetFirstChild(node) && mxmlGetType(mxmlGetFirstChild(node)) != MXML_ELEMENT)
- return NULL;
-
- return get_node_tab_space(node);
- case MXML_WS_AFTER_OPEN:
- return ((mxmlGetFirstChild(node) == NULL || mxmlGetType(mxmlGetFirstChild(node)) == MXML_ELEMENT) ? "\n" : NULL);
- case MXML_WS_AFTER_CLOSE:
- return "\n";
- default:
- return NULL;
- }
-
- return NULL;
-}
-
-char *xml_get_cwmp_version(int version)
-{
- static char versions[60];
- unsigned pos = 0;
- int k;
-
- versions[0] = '\0';
- for (k = 0; k < version; k++) {
- pos += snprintf(&versions[pos], sizeof(versions) - pos, "1.%d, ", k);
- }
-
- if (pos)
- versions[pos - 2] = 0;
-
- return versions;
-}
-
-static int xml_prepare_lwnotifications(mxml_node_t *parameter_list)
-{
- mxml_node_t *b, *n;
-
- struct list_head *p;
- struct cwmp_dm_parameter *lw_notification;
- list_for_each (p, &list_lw_value_change) {
- lw_notification = list_entry(p, struct cwmp_dm_parameter, list);
-
- n = mxmlNewElement(parameter_list, "Param");
- if (!n)
- goto error;
-
- b = mxmlNewElement(n, "Name");
- if (!b)
- goto error;
-
- b = mxmlNewOpaque(b, lw_notification->name);
- if (!b)
- goto error;
-
- b = mxmlNewElement(n, "Value");
- if (!b)
- goto error;
-#ifdef ACS_MULTI
- mxmlElementSetAttr(b, "xsi:type", lw_notification->type);
-#endif
- b = mxmlNewOpaque(b, lw_notification->value);
- if (!b)
- goto error;
- }
- return 0;
-
-error:
- return -1;
-}
-
-int xml_prepare_lwnotification_message(char **msg_out)
-{
- mxml_node_t *lw_tree;
-
- load_notification_xml_schema(&lw_tree);
- if (!lw_tree)
- goto error;
-
- *msg_out = mxmlSaveAllocString(lw_tree, whitespace_cb);
-
- mxmlDelete(lw_tree);
- return 0;
-
-error:
- return -1;
-}
-
-void load_notification_xml_schema(mxml_node_t **tree)
-{
- char declaration[1024] = {0};
- struct cwmp *cwmp = &cwmp_main;
- struct config *conf;
- conf = &(cwmp->conf);
- char *c = NULL;
-
- if (tree == NULL)
- return;
-
- *tree = NULL;
-
- snprintf(declaration, sizeof(declaration), "?xml version=\"1.0\" encoding=\"UTF-8\"?");
- mxml_node_t *xml = mxmlNewElement(NULL, declaration);
- if (xml == NULL)
- return;
-
- mxml_node_t *notification = mxmlNewElement(xml, "Notification");
- if (notification == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- mxmlElementSetAttr(notification, "xmlns", "urn:broadband-forum-org:cwmp:lwnotif-1-0");
- mxmlElementSetAttr(notification, "xmlns:xs", xsd_url);
- mxmlElementSetAttr(notification, "xmlns:xsi", xsi_url);
- mxmlElementSetAttr(notification, "xsi:schemaLocation", "urn:broadband-forum-org:cwmp:lxnotif-1-0 http://www.broadband-forum.org/cwmp/cwmp-UDPLightweightNotification-1-0.xsd");
-
- mxml_node_t *ts = mxmlNewElement(notification, "TS");
- if (ts == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- if (cwmp_asprintf(&c, "%ld", time(NULL)) == -1) {
- MXML_DELETE(xml);
- return;
- }
-
- if (NULL == mxmlNewOpaque(ts, c)) {
- FREE(c);
- MXML_DELETE(xml);
- return;
- }
-
- FREE(c);
-
- mxml_node_t *un = mxmlNewElement(notification, "UN");
- if (un == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- if (NULL == mxmlNewOpaque(un, conf->acs_userid)) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *cn = mxmlNewElement(notification, "CN");
- if (cn == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- c = (char *)calculate_lwnotification_cnonce();
- if (!c) {
- MXML_DELETE(xml);
- return;
- }
-
- if (NULL == mxmlNewOpaque(cn, c)) {
- FREE(c);
- MXML_DELETE(xml);
- return;
- }
-
- FREE(c);
-
- mxml_node_t *oui = mxmlNewElement(notification, "OUI");
- if (oui == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- if (NULL == mxmlNewOpaque(oui, cwmp->deviceid.oui)) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *pclass = mxmlNewElement(notification, "ProductClass");
- if (pclass == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- if (NULL == mxmlNewOpaque(pclass, cwmp->deviceid.productclass ? cwmp->deviceid.productclass : "")) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *slno = mxmlNewElement(notification, "SerialNumber");
- if (slno == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- if (NULL == mxmlNewOpaque(slno, cwmp->deviceid.serialnumber ? cwmp->deviceid.serialnumber : "")) {
- MXML_DELETE(xml);
- return;
- }
-
- if (xml_prepare_lwnotifications(notification)) {
- MXML_DELETE(xml);
- return;
- }
-
- *tree = xml;
-}
-
-void load_response_xml_schema(mxml_node_t **schema)
-{
- char declaration[1024] = {0};
-
- if (schema == NULL)
- return;
-
- *schema = NULL;
-
- snprintf(declaration, sizeof(declaration), "?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?");
- mxml_node_t *xml = mxmlNewElement(NULL, declaration);
- if (xml == NULL)
- return;
-
- mxml_node_t *envlp = mxmlNewElement(xml, "soap_env:Envelope");
- if (envlp == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- mxmlElementSetAttr(envlp, "xmlns:soap_env", soap_env_url);
- mxmlElementSetAttr(envlp, "xmlns:soap_enc", soap_enc_url);
- mxmlElementSetAttr(envlp, "xmlns:xsd", xsd_url);
- mxmlElementSetAttr(envlp, "xmlns:xsi", xsi_url);
-
- mxml_node_t *header = mxmlNewElement(envlp, "soap_env:Header");
- if (header == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- mxml_node_t *id = mxmlNewElement(header, "cwmp:ID");
- if (id == NULL) {
- MXML_DELETE(xml);
- return;
- }
-
- mxmlElementSetAttr(id, "soap_env:mustUnderstand", "1");
-
- if (NULL == mxmlNewElement(envlp, "soap_env:Body")) {
- MXML_DELETE(xml);
- return;
- }
-
- *schema = xml;
-}