icwmp: code cleanup

This commit is contained in:
Amin Ben Ramdhane 2022-04-27 11:39:30 +01:00
parent f7c42eaba6
commit bd7f6deb93
33 changed files with 770 additions and 1449 deletions

View file

@ -6,17 +6,14 @@ bin_PROGRAMS = icwmpd
icwmpd_SOURCES = \ icwmpd_SOURCES = \
./common.c \ ./common.c \
./cwmp_time.c \
./log.c \ ./log.c \
./cwmp_uci.c \ ./cwmp_uci.c \
./config.c \ ./config.c \
./session.c \ ./session.c \
./backupSession.c \ ./backupSession.c \
./md5.c \
./digestauth.c \ ./digestauth.c \
./event.c \ ./event.c \
./http.c \ ./cwmp_http.c \
./netlink.c \
./ubus.c \ ./ubus.c \
./datamodel_interface.c \ ./datamodel_interface.c \
./cwmp_cli.c \ ./cwmp_cli.c \

View file

@ -213,7 +213,7 @@ mxml_node_t *bkp_session_node_found(mxml_node_t *tree, char *name, struct search
if (mxmlGetType(c) == MXML_ELEMENT && strcmp(keys[i].name, (char *) mxmlGetElement(c)) == 0) { if (mxmlGetType(c) == MXML_ELEMENT && strcmp(keys[i].name, (char *) mxmlGetElement(c)) == 0) {
d = c; d = c;
d = mxmlWalkNext(d, c, MXML_DESCEND); d = mxmlWalkNext(d, c, MXML_DESCEND);
if ((keys[i].value == NULL) || (d && mxmlGetType(d) == MXML_OPAQUE && STRCMP(keys[i].value, mxmlGetOpaque(d)) == 0)) if ((keys[i].value == NULL) || (d && mxmlGetType(d) == MXML_OPAQUE && CWMP_STRCMP(keys[i].value, mxmlGetOpaque(d)) == 0))
i++; i++;
} }
c = mxmlWalkNext(c, b, MXML_NO_DESCEND); c = mxmlWalkNext(c, b, MXML_NO_DESCEND);

View file

@ -22,7 +22,6 @@
#include "ubus.h" #include "ubus.h"
#include "log.h" #include "log.h"
#ifndef CWMP_REVISION #ifndef CWMP_REVISION
#define CWMP_REVISION "8.2.10" #define CWMP_REVISION "8.2.10"
#endif #endif
@ -43,64 +42,49 @@ struct cwmp_mem {
char mem[0]; char mem[0];
}; };
char *Obj_Excluded[] = { static char *Obj_Excluded[] = {
"Device.DeviceInfo.ProcessStatus.Process.", "Device.DeviceInfo.ProcessStatus.Process.",
"Device.Hosts.Host." "Device.Hosts.Host."
}; };
struct option cwmp_long_options[] = { struct option cwmp_long_options[] = {
{ "boot-event", no_argument, NULL, 'b' }, { "get-rpc-methods", no_argument, NULL, 'g' }, { "boot-event", no_argument, NULL, 'b' },
{ "command-input", no_argument, NULL, 'c' }, { "help", no_argument, NULL, 'h' }, { "get-rpc-methods", no_argument, NULL, 'g' },
{ "version", no_argument, NULL, 'v' }, { NULL, 0, NULL, 0 } { "command-input", no_argument, NULL, 'c' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 }
}; };
struct FAULT_CPE FAULT_CPE_ARRAY[] = { struct FAULT_CPE FAULT_CPE_ARRAY[] = {
[FAULT_CPE_METHOD_NOT_SUPPORTED] = { "9000", FAULT_9000, FAULT_CPE_TYPE_SERVER, "Method not supported" }, [FAULT_CPE_METHOD_NOT_SUPPORTED] = { "9000", FAULT_9000, FAULT_CPE_TYPE_SERVER, "Method not supported" },
[FAULT_CPE_REQUEST_DENIED] = { "9001", FAULT_9001, FAULT_CPE_TYPE_SERVER, [FAULT_CPE_REQUEST_DENIED] = { "9001", FAULT_9001, FAULT_CPE_TYPE_SERVER, "Request denied (no reason specified)" },
"Request denied (no reason specified)" },
[FAULT_CPE_INTERNAL_ERROR] = { "9002", FAULT_9002, FAULT_CPE_TYPE_SERVER, "Internal error" }, [FAULT_CPE_INTERNAL_ERROR] = { "9002", FAULT_9002, FAULT_CPE_TYPE_SERVER, "Internal error" },
[FAULT_CPE_INVALID_ARGUMENTS] = { "9003", FAULT_9003, FAULT_CPE_TYPE_CLIENT, "Invalid arguments" }, [FAULT_CPE_INVALID_ARGUMENTS] = { "9003", FAULT_9003, FAULT_CPE_TYPE_CLIENT, "Invalid arguments" },
[FAULT_CPE_RESOURCES_EXCEEDED] = { "9004", FAULT_9004, FAULT_CPE_TYPE_SERVER, "Resources exceeded" }, [FAULT_CPE_RESOURCES_EXCEEDED] = { "9004", FAULT_9004, FAULT_CPE_TYPE_SERVER, "Resources exceeded" },
[FAULT_CPE_INVALID_PARAMETER_NAME] = { "9005", FAULT_9005, FAULT_CPE_TYPE_CLIENT, "Invalid parameter name" }, [FAULT_CPE_INVALID_PARAMETER_NAME] = { "9005", FAULT_9005, FAULT_CPE_TYPE_CLIENT, "Invalid parameter name" },
[FAULT_CPE_INVALID_PARAMETER_TYPE] = { "9006", FAULT_9006, FAULT_CPE_TYPE_CLIENT, "Invalid parameter type" }, [FAULT_CPE_INVALID_PARAMETER_TYPE] = { "9006", FAULT_9006, FAULT_CPE_TYPE_CLIENT, "Invalid parameter type" },
[FAULT_CPE_INVALID_PARAMETER_VALUE] = { "9007", FAULT_9007, FAULT_CPE_TYPE_CLIENT, "Invalid parameter value" }, [FAULT_CPE_INVALID_PARAMETER_VALUE] = { "9007", FAULT_9007, FAULT_CPE_TYPE_CLIENT, "Invalid parameter value" },
[FAULT_CPE_NON_WRITABLE_PARAMETER] = { "9008", FAULT_9008, FAULT_CPE_TYPE_CLIENT, [FAULT_CPE_NON_WRITABLE_PARAMETER] = { "9008", FAULT_9008, FAULT_CPE_TYPE_CLIENT, "Attempt to set a non-writable parameter" },
"Attempt to set a non-writable parameter" }, [FAULT_CPE_NOTIFICATION_REJECTED] = { "9009", FAULT_9009, FAULT_CPE_TYPE_SERVER, "Notification request rejected" },
[FAULT_CPE_NOTIFICATION_REJECTED] = { "9009", FAULT_9009, FAULT_CPE_TYPE_SERVER,
"Notification request rejected" },
[FAULT_CPE_DOWNLOAD_FAILURE] = { "9010", FAULT_9010, FAULT_CPE_TYPE_SERVER, "Download failure" }, [FAULT_CPE_DOWNLOAD_FAILURE] = { "9010", FAULT_9010, FAULT_CPE_TYPE_SERVER, "Download failure" },
[FAULT_CPE_UPLOAD_FAILURE] = { "9011", FAULT_9011, FAULT_CPE_TYPE_SERVER, "Upload failure" }, [FAULT_CPE_UPLOAD_FAILURE] = { "9011", FAULT_9011, FAULT_CPE_TYPE_SERVER, "Upload failure" },
[FAULT_CPE_FILE_TRANSFER_AUTHENTICATION_FAILURE] = { "9012", FAULT_9012, FAULT_CPE_TYPE_SERVER, [FAULT_CPE_FILE_TRANSFER_AUTHENTICATION_FAILURE] = { "9012", FAULT_9012, FAULT_CPE_TYPE_SERVER, "File transfer server authentication failure" },
"File transfer server authentication failure" }, [FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL] = { "9013", FAULT_9013, FAULT_CPE_TYPE_SERVER, "Unsupported protocol for file transfer" },
[FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL] = { "9013", FAULT_9013, FAULT_CPE_TYPE_SERVER, [FAULT_CPE_DOWNLOAD_FAIL_MULTICAST_GROUP] = { "9014", FAULT_9014, FAULT_CPE_TYPE_SERVER, "Download failure: unable to join multicast group" },
"Unsupported protocol for file transfer" }, [FAULT_CPE_DOWNLOAD_FAIL_CONTACT_SERVER] = { "9015", FAULT_9015, FAULT_CPE_TYPE_SERVER, "Download failure: unable to contact file server" },
[FAULT_CPE_DOWNLOAD_FAIL_MULTICAST_GROUP] = { "9014", FAULT_9014, FAULT_CPE_TYPE_SERVER, [FAULT_CPE_DOWNLOAD_FAIL_ACCESS_FILE] = { "9016", FAULT_9016, FAULT_CPE_TYPE_SERVER, "Download failure: unable to access file" },
"Download failure: unable to join multicast group" }, [FAULT_CPE_DOWNLOAD_FAIL_COMPLETE_DOWNLOAD] = { "9017", FAULT_9017, FAULT_CPE_TYPE_SERVER, "Download failure: unable to complete download" },
[FAULT_CPE_DOWNLOAD_FAIL_CONTACT_SERVER] = { "9015", FAULT_9015, FAULT_CPE_TYPE_SERVER, [FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED] = { "9018", FAULT_9018, FAULT_CPE_TYPE_SERVER, "Download failure: file corrupted" },
"Download failure: unable to contact file server" }, [FAULT_CPE_DOWNLOAD_FAIL_FILE_AUTHENTICATION] = { "9019", FAULT_9019, FAULT_CPE_TYPE_SERVER, "Download failure: file authentication failure" },
[FAULT_CPE_DOWNLOAD_FAIL_ACCESS_FILE] = { "9016", FAULT_9016, FAULT_CPE_TYPE_SERVER, [FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW] = { "9020", FAULT_9020, FAULT_CPE_TYPE_SERVER, "Download failure: unable to complete download" },
"Download failure: unable to access file" }, [FAULT_CPE_DUPLICATE_DEPLOYMENT_UNIT] = { "9026", FAULT_9026, FAULT_CPE_TYPE_SERVER, "Duplicate deployment unit" },
[FAULT_CPE_DOWNLOAD_FAIL_COMPLETE_DOWNLOAD] = { "9017", FAULT_9017, FAULT_CPE_TYPE_SERVER, [FAULT_CPE_SYSTEM_RESOURCES_EXCEEDED] = { "9027", FAULT_9027, FAULT_CPE_TYPE_SERVER, "System ressources exceeded" },
"Download failure: unable to complete download" },
[FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED] = { "9018", FAULT_9018, FAULT_CPE_TYPE_SERVER,
"Download failure: file corrupted" },
[FAULT_CPE_DOWNLOAD_FAIL_FILE_AUTHENTICATION] = { "9019", FAULT_9019, FAULT_CPE_TYPE_SERVER,
"Download failure: file authentication failure" },
[FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW] = { "9020", FAULT_9020, FAULT_CPE_TYPE_SERVER,
"Download failure: unable to complete download" },
[FAULT_CPE_DUPLICATE_DEPLOYMENT_UNIT] = { "9026", FAULT_9026, FAULT_CPE_TYPE_SERVER,
"Duplicate deployment unit" },
[FAULT_CPE_SYSTEM_RESOURCES_EXCEEDED] = { "9027", FAULT_9027, FAULT_CPE_TYPE_SERVER,
"System ressources exceeded" },
[FAULT_CPE_UNKNOWN_DEPLOYMENT_UNIT] = { "9028", FAULT_9028, FAULT_CPE_TYPE_SERVER, "Unknown deployment unit" }, [FAULT_CPE_UNKNOWN_DEPLOYMENT_UNIT] = { "9028", FAULT_9028, FAULT_CPE_TYPE_SERVER, "Unknown deployment unit" },
[FAULT_CPE_INVALID_DEPLOYMENT_UNIT_STATE] = { "9029", FAULT_9029, FAULT_CPE_TYPE_SERVER, [FAULT_CPE_INVALID_DEPLOYMENT_UNIT_STATE] = { "9029", FAULT_9029, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit state" },
"Invalid deployment unit state" }, [FAULT_CPE_INVALID_DOWNGRADE_REJECTED] = { "9030", FAULT_9030, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit Update: Downgrade not permitted" },
[FAULT_CPE_INVALID_DOWNGRADE_REJECTED] = { "9030", FAULT_9030, FAULT_CPE_TYPE_SERVER, [FAULT_CPE_INVALID_UPDATE_VERSION_UNSPECIFIED] = { "9031", FAULT_9031, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit Update: Version not specified" },
"Invalid deployment unit Update: Downgrade not permitted" }, [FAULT_CPE_INVALID_UPDATE_VERSION_EXIST] = { "9031", FAULT_9032, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit Update: Version already exist" }
[FAULT_CPE_INVALID_UPDATE_VERSION_UNSPECIFIED] = { "9031", FAULT_9031, FAULT_CPE_TYPE_SERVER,
"Invalid deployment unit Update: Version not specified" },
[FAULT_CPE_INVALID_UPDATE_VERSION_EXIST] = { "9031", FAULT_9032, FAULT_CPE_TYPE_SERVER,
"Invalid deployment unit Update: Version already exist" }
}; };
static void show_help(void) static void show_help(void)
@ -724,7 +708,27 @@ int get_connection_interface()
return CWMP_OK; return CWMP_OK;
} }
bool is_obj_excluded(char *object_name) char *get_time(time_t t_time)
{
static char local_time[32] = {0};
struct tm *t_tm;
t_tm = localtime(&t_time);
if (t_tm == NULL)
return NULL;
if (strftime(local_time, sizeof(local_time), "%FT%T%z", t_tm) == 0)
return NULL;
local_time[25] = local_time[24];
local_time[24] = local_time[23];
local_time[22] = ':';
local_time[26] = '\0';
return local_time;
}
bool is_obj_excluded(const char *object_name)
{ {
unsigned int i = 0; unsigned int i = 0;

View file

@ -16,9 +16,6 @@ AS_IF([test "x$enable_acs" = "xmulti"], [AC_DEFINE(ACS_MULTI)])
AS_IF([test "x$enable_acs" = "xyes"], [AC_DEFINE(ACS_MULTI)]) AS_IF([test "x$enable_acs" = "xyes"], [AC_DEFINE(ACS_MULTI)])
AS_IF([test "x$enable_acs" = "xno"], [AC_DEFINE(ACS_MULTI)]) AS_IF([test "x$enable_acs" = "xno"], [AC_DEFINE(ACS_MULTI)])
AC_ARG_ENABLE(debug, [AS_HELP_STRING([--enable-debug], [enable debugging messages])], AC_DEFINE(WITH_CWMP_DEBUG),)
AC_ARG_ENABLE(devel, [AS_HELP_STRING([--enable-devel], [enable development messages])], AC_DEFINE(WITH_DEV_DEBUG),)
AC_ARG_ENABLE(libopenssl, [AS_HELP_STRING([--enable-libopenssl], [enable libopenssl feature])], AC_DEFINE(LOPENSSL)) AC_ARG_ENABLE(libopenssl, [AS_HELP_STRING([--enable-libopenssl], [enable libopenssl feature])], AC_DEFINE(LOPENSSL))
AM_CONDITIONAL([LOPENSSL],[test "x$enable_libopenssl" = "xyes"]) AM_CONDITIONAL([LOPENSSL],[test "x$enable_libopenssl" = "xyes"])

18
cwmp.c
View file

@ -25,7 +25,7 @@
#include "log.h" #include "log.h"
#include "session.h" #include "session.h"
#include "diagnostic.h" #include "diagnostic.h"
#include "http.h" #include "cwmp_http.h"
#include "rpc_soap.h" #include "rpc_soap.h"
#include "config.h" #include "config.h"
#include "backupSession.h" #include "backupSession.h"
@ -148,7 +148,7 @@ static int cwmp_schedule_rpc(struct cwmp *cwmp, struct session *session)
struct list_head *ilist; struct list_head *ilist;
struct rpc *rpc_acs, *rpc_cpe; struct rpc *rpc_acs, *rpc_cpe;
if (http_client_init(cwmp) || thread_end) { if (cwmp_http_client_init(cwmp) || thread_end) {
CWMP_LOG(INFO, "Initializing http client failed"); CWMP_LOG(INFO, "Initializing http client failed");
goto retry; goto retry;
} }
@ -175,11 +175,6 @@ static int cwmp_schedule_rpc(struct cwmp *cwmp, struct session *session)
goto retry; goto retry;
CWMP_LOG(INFO, "Get the %sResponse message from the ACS", rpc_acs_methods[rpc_acs->type].name); CWMP_LOG(INFO, "Get the %sResponse message from the ACS", rpc_acs_methods[rpc_acs->type].name);
/*
* This condition is not always false.
* while the value of thread_end can be changed to true in the exit of icwmp.
*/
// cppcheck-suppress knownConditionTrueFalse
if (rpc_acs_methods[rpc_acs->type].parse_response || thread_end) if (rpc_acs_methods[rpc_acs->type].parse_response || thread_end)
if (rpc_acs_methods[rpc_acs->type].parse_response(cwmp, session, rpc_acs)) if (rpc_acs_methods[rpc_acs->type].parse_response(cwmp, session, rpc_acs))
goto retry; goto retry;
@ -250,7 +245,7 @@ retry:
end: end:
MXML_DELETE(session->tree_in); MXML_DELETE(session->tree_in);
MXML_DELETE(session->tree_out); MXML_DELETE(session->tree_out);
http_client_exit(); cwmp_http_client_exit();
xml_exit(); xml_exit();
return session->error; return session->error;
} }
@ -396,8 +391,7 @@ static void cwmp_schedule_session(struct cwmp *cwmp)
cwmp->session_status.last_status = SESSION_RUNNING; cwmp->session_status.last_status = SESSION_RUNNING;
cwmp->session_status.next_retry = 0; cwmp->session_status.next_retry = 0;
if (file_exists(fc_cookies)) cwmp_http_remove_cookies_file();
remove(fc_cookies);
CWMP_LOG(INFO, "Start session"); CWMP_LOG(INFO, "Start session");
uci_get_value(UCI_CPE_EXEC_DOWNLOAD, &exec_download); uci_get_value(UCI_CPE_EXEC_DOWNLOAD, &exec_download);
@ -452,7 +446,7 @@ static void *thread_uloop_run(void *v __attribute__((unused)))
static void *thread_http_cr_server_listen(void *v __attribute__((unused))) static void *thread_http_cr_server_listen(void *v __attribute__((unused)))
{ {
http_server_listen(); cwmp_http_server_listen();
return NULL; return NULL;
} }
@ -828,7 +822,7 @@ int main(int argc, char **argv)
return error; return error;
configure_var_state(cwmp); configure_var_state(cwmp);
http_server_init(); cwmp_http_server_init();
sigemptyset(&set); sigemptyset(&set);
sigaddset(&set, SIGINT); sigaddset(&set, SIGINT);

View file

@ -16,7 +16,6 @@
#include "ubus.h" #include "ubus.h"
#include "log.h" #include "log.h"
#include "datamodel_interface.h" #include "datamodel_interface.h"
#include "cwmp_time.h"
#include "backupSession.h" #include "backupSession.h"
#include "event.h" #include "event.h"
@ -202,7 +201,7 @@ static int cwmp_launch_du_install(char *url, char *uuid, char *user, char *pass,
int error = FAULT_CPE_NO_FAULT; int error = FAULT_CPE_NO_FAULT;
char *fault_code; char *fault_code;
(*pchange_du_state_complete)->start_time = strdup(mix_get_time()); (*pchange_du_state_complete)->start_time = strdup(get_time(time(NULL)));
cwmp_du_install(url, uuid, user, pass, env_name, env_id, &fault_code); cwmp_du_install(url, uuid, user, pass, env_name, env_id, &fault_code);
if (fault_code != NULL) { if (fault_code != NULL) {
@ -225,7 +224,7 @@ static int cwmp_launch_du_update(char *uuid, char *url, char *user, char *pass,
int error = FAULT_CPE_NO_FAULT; int error = FAULT_CPE_NO_FAULT;
char *fault_code; char *fault_code;
(*pchange_du_state_complete)->start_time = strdup(mix_get_time()); (*pchange_du_state_complete)->start_time = strdup(get_time(time(NULL)));
cwmp_du_update(url, uuid, user, pass, env_name, env_id, &fault_code); cwmp_du_update(url, uuid, user, pass, env_name, env_id, &fault_code);
if (fault_code != NULL) { if (fault_code != NULL) {
@ -248,7 +247,7 @@ static int cwmp_launch_du_uninstall(char *package_name, char *env_name, int env_
int error = FAULT_CPE_NO_FAULT; int error = FAULT_CPE_NO_FAULT;
char *fault_code; char *fault_code;
(*pchange_du_state_complete)->start_time = strdup(mix_get_time()); (*pchange_du_state_complete)->start_time = strdup(get_time(time(NULL)));
cwmp_du_uninstall(package_name, env_name, env_id, &fault_code); cwmp_du_uninstall(package_name, env_name, env_id, &fault_code);
@ -326,7 +325,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v)
res->uuid = strdup(p->uuid); res->uuid = strdup(p->uuid);
res->version = strdup(p->version); res->version = strdup(p->version);
res->current_state = strdup("Failed"); res->current_state = strdup("Failed");
res->start_time = strdup(mix_get_time()); res->start_time = strdup(get_time(time(NULL)));
res->complete_time = strdup(res->start_time); res->complete_time = strdup(res->start_time);
res->fault = error; res->fault = error;
} }
@ -378,7 +377,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v)
res->resolved = 0; res->resolved = 0;
} }
res->complete_time = strdup(mix_get_time()); res->complete_time = strdup(get_time(time(NULL)));
res->fault = error; res->fault = error;
break; break;
@ -411,7 +410,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v)
get_du_version(du_ref, &package_version); get_du_version(du_ref, &package_version);
res->version = strdup(package_version ? package_version : ""); res->version = strdup(package_version ? package_version : "");
res->du_ref = strdup(du_ref ? du_ref : ""); res->du_ref = strdup(du_ref ? du_ref : "");
res->complete_time = strdup(mix_get_time()); res->complete_time = strdup(get_time(time(NULL)));
res->fault = error; res->fault = error;
FREE(du_ref); FREE(du_ref);
break; break;
@ -441,7 +440,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v)
res->du_ref = strdup(du_ref ? du_ref : ""); res->du_ref = strdup(du_ref ? du_ref : "");
res->uuid = strdup(p->uuid); res->uuid = strdup(p->uuid);
res->version = strdup(package_version); res->version = strdup(package_version);
res->complete_time = strdup(mix_get_time()); res->complete_time = strdup(get_time(time(NULL)));
res->fault = error; res->fault = error;
FREE(du_ref); FREE(du_ref);
FREE(package_name); FREE(package_name);

View file

@ -1,21 +1,32 @@
/* /*
* This program is free software: you can redistribute it and/or modify * cwmp_http.c: Utility functions for http server and client
* 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 * Copyright (C) 2022 iopsys Software Solutions AB. All rights reserved.
* Author Mohamed Kallel <mohamed.kallel@pivasoftware.com> *
* Author Ahmed Zribi <ahmed.zribi@pivasoftware.com> * Author: Mohamed Kallel <mohamed.kallel@pivasoftware.com>
* Author Omar Kallel <omar.kallel@pivasoftware.com> * Author: Ahmed Zribi <ahmed.zribi@pivasoftware.com>
* Copyright (C) 2011-2012 Luka Perkov <freecwmp@lukaperkov.net> * Author: Omar Kallel <omar.kallel@pivasoftware.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/ */
#include <curl/curl.h> #include <curl/curl.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include "http.h" #include "cwmp_http.h"
#include "cwmp_uci.h" #include "cwmp_uci.h"
#include "log.h" #include "log.h"
#include "event.h" #include "event.h"
@ -23,55 +34,39 @@
#include "config.h" #include "config.h"
#include "digestauth.h" #include "digestauth.h"
#define HTTP_TIMEOUT 30
#define REALM "authenticate@cwmp" #define REALM "authenticate@cwmp"
#define OPAQUE "11733b200778ce33060f31c9af70a870ba96ddd4" #define OPAQUE "11733b200778ce33060f31c9af70a870ba96ddd4"
static struct http_client http_c;
static CURL *curl = NULL; static CURL *curl = NULL;
static char *http_client_url = NULL;
static char *cookies_file = "/tmp/icwmp_cookies";
char *fc_cookies = "/tmp/icwmp_cookies"; int cwmp_http_client_init(struct cwmp *cwmp)
void http_set_timeout(void)
{
if (curl)
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1);
}
int http_client_init(struct cwmp *cwmp)
{ {
char *dhcp_dis = NULL; char *dhcp_dis = NULL;
char *acs_var_stat = NULL;
uci_get_value(UCI_DHCP_DISCOVERY_PATH, &dhcp_dis); uci_get_value(UCI_DHCP_DISCOVERY_PATH, &dhcp_dis);
if (dhcp_dis && cwmp->retry_count_session > 0 && strcmp(dhcp_dis, "enable") == 0) { if (dhcp_dis && cwmp->retry_count_session > 0 && strcmp(dhcp_dis, "enable") == 0) {
char *acs_var_stat = NULL;
uci_get_state_value(UCI_DHCP_ACS_URL, &acs_var_stat); uci_get_state_value(UCI_DHCP_ACS_URL, &acs_var_stat);
if (acs_var_stat) { if (icwmp_asprintf(&http_client_url, "%s", acs_var_stat ? acs_var_stat : cwmp->conf.acsurl) == -1) {
if (icwmp_asprintf(&http_c.url, "%s", acs_var_stat) == -1) { FREE(acs_var_stat);
free(acs_var_stat);
FREE(dhcp_dis); FREE(dhcp_dis);
return -1; return -1;
} }
} else { } else {
if (icwmp_asprintf(&http_c.url, "%s", cwmp->conf.acsurl) == -1) { if (icwmp_asprintf(&http_client_url, "%s", cwmp->conf.acsurl) == -1) {
FREE(dhcp_dis);
return -1;
}
}
} else {
if (icwmp_asprintf(&http_c.url, "%s", cwmp->conf.acsurl) == -1) {
FREE(dhcp_dis); FREE(dhcp_dis);
return -1; return -1;
} }
} }
if (dhcp_dis) FREE(dhcp_dis);
free(dhcp_dis);
CWMP_LOG(INFO, "ACS url: %s", http_c.url); CWMP_LOG(INFO, "ACS url: %s", http_client_url);
/* TODO debug ssl config from freecwmp*/
curl_global_init(CURL_GLOBAL_SSL); curl_global_init(CURL_GLOBAL_SSL);
curl = curl_easy_init(); curl = curl_easy_init();
@ -80,39 +75,24 @@ int http_client_init(struct cwmp *cwmp)
if (cwmp->conf.ipv6_enable) { if (cwmp->conf.ipv6_enable) {
unsigned char buf[sizeof(struct in6_addr)]; unsigned char buf[sizeof(struct in6_addr)];
char *ip = NULL; char *ip = NULL;
curl_easy_setopt(curl, CURLOPT_URL, http_c.url);
curl_easy_setopt(curl, CURLOPT_URL, http_client_url);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, HTTP_TIMEOUT); curl_easy_setopt(curl, CURLOPT_TIMEOUT, HTTP_TIMEOUT);
curl_easy_setopt(curl, CURLOPT_NOBODY, 1); curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
curl_easy_getinfo(curl, CURLINFO_PRIMARY_IP, &ip); curl_easy_getinfo(curl, CURLINFO_PRIMARY_IP, &ip);
curl_easy_perform(curl); curl_easy_perform(curl);
int tmp = inet_pton(AF_INET, ip, buf); int tmp = inet_pton(AF_INET, ip, buf);
cwmp_uci_set_value("cwmp", "acs", "ip_version", (tmp == 1) ? "4" : "6"); cwmp_uci_set_value("cwmp", "acs", "ip_version", (tmp == 1) ? "4" : "6");
cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG);
} }
return 0; return 0;
} }
void http_client_exit(void) static size_t cwmp_http_get_response(void *buffer, size_t size, size_t rxed, char **msg_in)
{
icwmp_free(http_c.url);
if (http_c.header_list) {
curl_slist_free_all(http_c.header_list);
http_c.header_list = NULL;
}
if (file_exists(fc_cookies))
remove(fc_cookies);
if (curl) {
curl_easy_cleanup(curl);
curl = NULL;
}
curl_global_cleanup();
}
static size_t http_get_response(void *buffer, size_t size, size_t rxed, char **msg_in)
{ {
char *c; char *c;
@ -130,7 +110,7 @@ static size_t http_get_response(void *buffer, size_t size, size_t rxed, char **m
return size * rxed; return size * rxed;
} }
int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **msg_in) int cwmp_http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **msg_in)
{ {
unsigned char buf[sizeof(struct in6_addr)]; unsigned char buf[sizeof(struct in6_addr)];
int tmp = 0; int tmp = 0;
@ -139,25 +119,29 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **
static char ip_acs[128] = { 0 }; static char ip_acs[128] = { 0 };
char *ip = NULL; char *ip = NULL;
char errbuf[CURL_ERROR_SIZE]; char errbuf[CURL_ERROR_SIZE];
struct curl_slist *header_list = NULL;
http_c.header_list = NULL; header_list = curl_slist_append(header_list, "User-Agent: iopsys-cwmp");
http_c.header_list = curl_slist_append(http_c.header_list, "User-Agent: iopsys-cwmp"); if (!header_list)
if (!http_c.header_list)
return -1; return -1;
http_c.header_list = curl_slist_append(http_c.header_list, "Content-Type: text/xml");
if (!http_c.header_list) header_list = curl_slist_append(header_list, "Content-Type: text/xml");
if (!header_list)
return -1; return -1;
#ifdef ACS_FUSION #ifdef ACS_FUSION
http_c.header_list = curl_slist_append(http_c.header_list, "Expect:"); header_list = curl_slist_append(header_list, "Expect:");
if (!http_c.header_list) if (!header_list)
return -1; return -1;
#endif /* ACS_FUSION */ #endif /* ACS_FUSION */
if (cwmp->conf.http_disable_100continue) { if (cwmp->conf.http_disable_100continue) {
http_c.header_list = curl_slist_append(http_c.header_list, "Expect:"); header_list = curl_slist_append(header_list, "Expect:");
if (!http_c.header_list) if (!header_list)
return -1; return -1;
} }
curl_easy_setopt(curl, CURLOPT_URL, http_c.url);
curl_easy_setopt(curl, CURLOPT_URL, http_client_url);
curl_easy_setopt(curl, CURLOPT_USERNAME, cwmp->conf.acs_userid); 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_PASSWORD, cwmp->conf.acs_passwd);
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC | CURLAUTH_DIGEST); curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC | CURLAUTH_DIGEST);
@ -166,26 +150,28 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL); curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
curl_easy_setopt(curl, CURLOPT_NOBODY, 0); curl_easy_setopt(curl, CURLOPT_NOBODY, 0);
switch (cwmp->conf.compression) { switch (cwmp->conf.compression) {
case COMP_NONE: case COMP_NONE:
break; break;
case COMP_GZIP: case COMP_GZIP:
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip"); curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip");
http_c.header_list = curl_slist_append(http_c.header_list, "Content-Encoding: gzip"); header_list = curl_slist_append(header_list, "Content-Encoding: gzip");
break; break;
case COMP_DEFLATE: case COMP_DEFLATE:
curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "deflate"); curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "deflate");
http_c.header_list = curl_slist_append(http_c.header_list, "Content-Encoding: deflate"); header_list = curl_slist_append(header_list, "Content-Encoding: deflate");
break; break;
} }
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_c.header_list);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg_out); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, msg_out);
if (msg_out) if (msg_out)
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)msg_out_len); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)msg_out_len);
else else
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_response); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cwmp_http_get_response);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, msg_in); curl_easy_setopt(curl, CURLOPT_WRITEDATA, msg_in);
#ifdef DEVEL #ifdef DEVEL
@ -193,8 +179,8 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **
#endif #endif
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, fc_cookies); curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookies_file);
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, fc_cookies); curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookies_file);
if (cwmp->conf.acs_ssl_capath) if (cwmp->conf.acs_ssl_capath)
curl_easy_setopt(curl, CURLOPT_CAPATH, cwmp->conf.acs_ssl_capath); curl_easy_setopt(curl, CURLOPT_CAPATH, cwmp->conf.acs_ssl_capath);
@ -252,11 +238,9 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **
if (http_code != 200 && http_code != 204) if (http_code != 200 && http_code != 204)
goto error; goto error;
/* TODO add check for 301, 302 and 307 HTTP Redirect*/ if (header_list) {
curl_slist_free_all(header_list);
if (http_c.header_list) { header_list = NULL;
curl_slist_free_all(http_c.header_list);
http_c.header_list = NULL;
} }
if (res) if (res)
@ -266,36 +250,48 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **
error: error:
FREE(*msg_in); FREE(*msg_in);
if (http_c.header_list) { if (header_list) {
curl_slist_free_all(http_c.header_list); curl_slist_free_all(header_list);
http_c.header_list = NULL; header_list = NULL;
} }
return -1; return -1;
} }
void http_success_cr(void) void cwmp_http_client_exit(void)
{
icwmp_free(http_client_url);
if (curl) {
curl_easy_cleanup(curl);
curl = NULL;
}
curl_global_cleanup();
cwmp_http_remove_cookies_file();
}
static void cwmp_http_success_cr(void)
{ {
CWMP_LOG(INFO, "Connection Request thread: add connection request event in the queue"); CWMP_LOG(INFO, "Connection Request thread: add connection request event in the queue");
pthread_mutex_lock(&(cwmp_main.mutex_session_queue)); pthread_mutex_lock(&(cwmp_main.mutex_session_queue));
cwmp_add_event_container(&cwmp_main, EVENT_IDX_6CONNECTION_REQUEST, ""); cwmp_add_event_container(&cwmp_main, EVENT_IDX_6CONNECTION_REQUEST, "");
pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); pthread_mutex_unlock(&(cwmp_main.mutex_session_queue));
pthread_cond_signal(&(cwmp_main.threshold_session_send)); pthread_cond_signal(&(cwmp_main.threshold_session_send));
} }
static void http_cr_new_client(int client, bool service_available) static void cwmp_http_cr_new_client(int client, bool service_available)
{ {
FILE *fp;
char buffer[BUFSIZ]; char buffer[BUFSIZ];
char auth_digest_buffer[BUFSIZ]; char auth_digest_buffer[BUFSIZ];
int8_t auth_status = 0; int8_t auth_status = 0;
bool auth_digest_checked = false; bool auth_digest_checked = false;
bool method_is_get = false; bool method_is_get = false;
bool internal_error = false; bool internal_error = false;
char cr_http_get_head[512]; char cr_http_get_head[512];
pthread_mutex_lock(&mutex_config_load); pthread_mutex_lock(&mutex_config_load);
fp = fdopen(client, "r+"); FILE *fp = fdopen(client, "r+");
char *username = cwmp_main.conf.cpe_userid; char *username = cwmp_main.conf.cpe_userid;
char *password = cwmp_main.conf.cpe_passwd; char *password = cwmp_main.conf.cpe_passwd;
@ -304,6 +300,7 @@ static void http_cr_new_client(int client, bool service_available)
service_available = false; service_available = false;
goto http_end; goto http_end;
} }
snprintf(cr_http_get_head, sizeof(cr_http_get_head), "GET %s HTTP/1.1", cwmp_main.conf.connection_request_path); snprintf(cr_http_get_head, sizeof(cr_http_get_head), "GET %s HTTP/1.1", cwmp_main.conf.connection_request_path);
while (fgets(buffer, sizeof(buffer), fp)) { while (fgets(buffer, sizeof(buffer), fp)) {
if (!strncasecmp(buffer, cr_http_get_head, strlen(cr_http_get_head))) if (!strncasecmp(buffer, cr_http_get_head, strlen(cr_http_get_head)))
@ -318,18 +315,22 @@ static void http_cr_new_client(int client, bool service_available)
break; break;
} }
} }
if (!service_available || !method_is_get) { if (!service_available || !method_is_get) {
goto http_end; goto http_end;
} }
int auth_check = http_digest_auth_check("GET", "/", auth_digest_buffer + strlen("Authorization: Digest "), REALM, username, password, 300); int auth_check = http_digest_auth_check("GET", "/", auth_digest_buffer + strlen("Authorization: Digest "), REALM, username, password, 300);
if (auth_check == MHD_INVALID_NONCE) { if (auth_check == MHD_INVALID_NONCE) {
internal_error = true; internal_error = true;
goto http_end; goto http_end;
} }
if (auth_digest_checked && auth_check == MHD_YES) if (auth_digest_checked && auth_check == MHD_YES)
auth_status = 1; auth_status = 1;
else else
auth_status = 0; auth_status = 0;
http_end: http_end:
if (!service_available || !method_is_get) { if (!service_available || !method_is_get) {
CWMP_LOG(INFO, "Receive Connection Request: Return 503 Service Unavailable"); CWMP_LOG(INFO, "Receive Connection Request: Return 503 Service Unavailable");
@ -341,7 +342,7 @@ http_end:
fputs("HTTP/1.1 200 OK\r\n", fp); fputs("HTTP/1.1 200 OK\r\n", fp);
fputs("Connection: close\r\n", fp); fputs("Connection: close\r\n", fp);
fputs("Content-Length: 0\r\n", fp); fputs("Content-Length: 0\r\n", fp);
http_success_cr(); cwmp_http_success_cr();
} else if (internal_error) { } else if (internal_error) {
CWMP_LOG(INFO, "Receive Connection Request: Return 500 Internal Error"); CWMP_LOG(INFO, "Receive Connection Request: Return 500 Internal Error");
fputs("HTTP/1.1 500 Internal Server Error\r\n", fp); fputs("HTTP/1.1 500 Internal Server Error\r\n", fp);
@ -361,7 +362,7 @@ http_end:
pthread_mutex_unlock(&mutex_config_load); pthread_mutex_unlock(&mutex_config_load);
} }
void http_server_init(void) void cwmp_http_server_init(void)
{ {
struct sockaddr_in6 server = { 0 }; struct sockaddr_in6 server = { 0 };
unsigned short cr_port; unsigned short cr_port;
@ -411,7 +412,7 @@ void http_server_init(void)
CWMP_LOG(INFO, "Connection Request server initiated with the port: %d", cr_port); CWMP_LOG(INFO, "Connection Request server initiated with the port: %d", cr_port);
} }
void http_server_listen(void) void cwmp_http_server_listen(void)
{ {
int client_sock, c; int client_sock, c;
int cr_request = 0; int cr_request = 0;
@ -442,7 +443,8 @@ void http_server_listen(void)
service_available = false; service_available = false;
} }
} }
http_cr_new_client(client_sock, service_available);
cwmp_http_cr_new_client(client_sock, service_available);
close(client_sock); close(client_sock);
} }
@ -451,3 +453,15 @@ void http_server_listen(void)
return; return;
} }
} }
void cwmp_http_set_timeout(void)
{
if (curl)
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1);
}
void cwmp_http_remove_cookies_file(void)
{
if (file_exists(cookies_file))
remove(cookies_file);
}

View file

@ -1,39 +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 <freecwmp@lukaperkov.net>
*/
#include <time.h>
char local_time[32] = { 0 };
char *mix_get_time_of(time_t t_time)
{
struct tm *t_tm;
t_tm = localtime(&t_time);
if (t_tm == NULL)
return NULL;
if (strftime(local_time, sizeof(local_time), "%FT%T%z", t_tm) == 0)
return NULL;
local_time[25] = local_time[24];
local_time[24] = local_time[23];
local_time[22] = ':';
local_time[26] = '\0';
return local_time;
}
char *mix_get_time(void)
{
time_t t_time;
t_time = time(NULL);
mix_get_time_of(t_time);
return local_time;
}

View file

@ -4,7 +4,7 @@
* the Free Software Foundation, either version 2 of the License, or * the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Copyright (C) 2013-2021 iopsys Software Solutions AB * Copyright (C) 2013-2022 iopsys Software Solutions AB
* Author Omar Kallel <omar.kallel@pivasoftware.com> * Author Omar Kallel <omar.kallel@pivasoftware.com>
*/ */
#include <ctype.h> #include <ctype.h>
@ -15,7 +15,7 @@
#include "cwmp_uci.h" #include "cwmp_uci.h"
#include "log.h" #include "log.h"
struct uci_paths uci_save_conf_paths[] = { static struct uci_paths uci_save_conf_paths[] = {
[UCI_STANDARD_CONFIG] = { "/etc/config", "/tmp/.uci", NULL }, [UCI_STANDARD_CONFIG] = { "/etc/config", "/tmp/.uci", NULL },
[UCI_VARSTATE_CONFIG] = { "/var/state", NULL, NULL } [UCI_VARSTATE_CONFIG] = { "/var/state", NULL, NULL }
}; };
@ -37,10 +37,11 @@ static inline bool cwmp_check_section_name(const char *str, bool name)
return true; return true;
} }
int cwmp_uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *package, char *section, char *option, char *value) static int cwmp_uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *package, char *section, char *option, char *value)
{ {
/*value*/ /*value*/
ptr->value = value; ptr->value = value;
/*package*/ /*package*/
if (!package) if (!package)
return UCI_ERR_IO; return UCI_ERR_IO;
@ -64,9 +65,9 @@ int cwmp_uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *pack
ptr->option = option; ptr->option = option;
lookup: lookup:
if (uci_lookup_ptr(ctx, ptr, NULL, true) != UCI_OK) { if (uci_lookup_ptr(ctx, ptr, NULL, true) != UCI_OK)
return UCI_ERR_PARSE; return UCI_ERR_PARSE;
}
return UCI_OK; return UCI_OK;
} }
@ -91,9 +92,11 @@ static int cwmp_uci_lookup_ptr_by_section(struct uci_context *ctx, struct uci_pt
ptr->target = UCI_TYPE_SECTION; ptr->target = UCI_TYPE_SECTION;
goto lookup; goto lookup;
} }
ptr->target = UCI_TYPE_OPTION; ptr->target = UCI_TYPE_OPTION;
ptr->option = option; ptr->option = option;
ptr->flags |= UCI_LOOKUP_EXTENDED; ptr->flags |= UCI_LOOKUP_EXTENDED;
lookup: lookup:
if (uci_lookup_ptr(ctx, ptr, NULL, false) != UCI_OK || !UCI_LOOKUP_COMPLETE) if (uci_lookup_ptr(ctx, ptr, NULL, false) != UCI_OK || !UCI_LOOKUP_COMPLETE)
return -1; return -1;
@ -105,19 +108,21 @@ lookup:
* UCI INIT EXIT * UCI INIT EXIT
*/ */
void cwmp_uci_init_by_config(int config) static void cwmp_uci_init_by_config(int config)
{ {
if(uci_save_conf_paths[config].uci_ctx != NULL) if(uci_save_conf_paths[config].uci_ctx != NULL)
return; return;
uci_save_conf_paths[config].uci_ctx = uci_alloc_context(); uci_save_conf_paths[config].uci_ctx = uci_alloc_context();
if ( uci_save_conf_paths[config].uci_ctx == NULL) if ( uci_save_conf_paths[config].uci_ctx == NULL)
return; return;
uci_add_delta_path(uci_save_conf_paths[config].uci_ctx, uci_save_conf_paths[config].uci_ctx->savedir); uci_add_delta_path(uci_save_conf_paths[config].uci_ctx, uci_save_conf_paths[config].uci_ctx->savedir);
uci_set_savedir(uci_save_conf_paths[config].uci_ctx, uci_save_conf_paths[config].save_dir); uci_set_savedir(uci_save_conf_paths[config].uci_ctx, uci_save_conf_paths[config].save_dir);
uci_set_confdir(uci_save_conf_paths[config].uci_ctx, uci_save_conf_paths[config].conf_dir); uci_set_confdir(uci_save_conf_paths[config].uci_ctx, uci_save_conf_paths[config].conf_dir);
} }
void cwmp_uci_exit_by_config(int config) static void cwmp_uci_exit_by_config(int config)
{ {
if (uci_save_conf_paths[config].uci_ctx) { if (uci_save_conf_paths[config].uci_ctx) {
uci_free_context(uci_save_conf_paths[config].uci_ctx); uci_free_context(uci_save_conf_paths[config].uci_ctx);
@ -125,11 +130,11 @@ void cwmp_uci_exit_by_config(int config)
} }
} }
int cwmp_uci_init() int cwmp_uci_init(void)
{ {
int i; unsigned int i = 0;
int uci_nbre_conf_paths = (int)(sizeof(uci_save_conf_paths) / sizeof(struct uci_paths));
for (i = 0; i < uci_nbre_conf_paths; i++) { for (i = 0; i < ARRAY_SIZE(uci_save_conf_paths); i++) {
cwmp_uci_init_by_config(i); cwmp_uci_init_by_config(i);
} }
return 0; return 0;
@ -137,9 +142,9 @@ int cwmp_uci_init()
void cwmp_uci_exit(void) void cwmp_uci_exit(void)
{ {
int i; unsigned int i = 0;
int uci_nbre_conf_paths = (int)(sizeof(uci_save_conf_paths) / sizeof(struct uci_paths));
for (i = 0; i < uci_nbre_conf_paths; i++) { for (i = 0; i < ARRAY_SIZE(uci_save_conf_paths); i++) {
cwmp_uci_exit_by_config(i); cwmp_uci_exit_by_config(i);
} }
} }
@ -172,55 +177,50 @@ int cwmp_uci_get_option_value_string(char *package, char *section, char *option,
return UCI_OK; return UCI_OK;
} }
int cwmp_uci_get_value_by_path(char *path, uci_config_paths uci_type, char **value) static int cwmp_uci_get_value_by_path(char *path, uci_config_paths uci_type, char **value)
{ {
struct uci_ptr ptr; struct uci_ptr ptr = {0};
char *s; char uci_path[256] = {0};
*value = NULL; *value = NULL;
s = strdup(path); CWMP_STRNCPY(uci_path, path, sizeof(uci_path));
if (uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, s, true) != UCI_OK) {
CWMP_LOG(ERROR, "Error occurred in uci get %s", path); if (uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, uci_path, true) != UCI_OK) {
free(s); CWMP_LOG(ERROR, "Error occurred in uci get %s", uci_path);
return UCI_ERR_PARSE; return UCI_ERR_PARSE;
} }
free(s);
if (ptr.flags & UCI_LOOKUP_COMPLETE) { if (ptr.flags & UCI_LOOKUP_COMPLETE) {
if (ptr.o == NULL || ptr.o->v.string == NULL) { if (ptr.o == NULL || ptr.o->v.string == NULL) {
CWMP_LOG(INFO, "%s not found or empty value", path); CWMP_LOG(INFO, "%s not found or empty value", uci_path);
return UCI_OK; return UCI_OK;
} }
*value = strdup(ptr.o->v.string); *value = strdup(ptr.o->v.string);
} }
return UCI_OK; return UCI_OK;
} }
int uci_get_state_value(char *path, char **value) int uci_get_state_value(char *path, char **value)
{ {
int error; return cwmp_uci_get_value_by_path(path, UCI_VARSTATE_CONFIG, value);
error = cwmp_uci_get_value_by_path(path, UCI_VARSTATE_CONFIG, value);
return error;
} }
int uci_get_value(char *path, char **value) int uci_get_value(char *path, char **value)
{ {
int error; return cwmp_uci_get_value_by_path(path, UCI_STANDARD_CONFIG, value);
error = cwmp_uci_get_value_by_path(path, UCI_STANDARD_CONFIG, value);
return error;
} }
int cwmp_uci_get_value_by_section_string(struct uci_section *s, char *option, char **value) int cwmp_uci_get_value_by_section_string(struct uci_section *s, char *option, char **value)
{ {
struct uci_element *e; struct uci_element *e = NULL;
struct uci_option *o; struct uci_option *o = NULL;
*value = NULL;
if (s == NULL || &s->options == NULL || option == NULL) if (s == NULL || &s->options == NULL || option == NULL)
goto not_found; goto not_found;
uci_foreach_element(&s->options, e) uci_foreach_element(&s->options, e) {
{
o = (uci_to_option(e)); o = (uci_to_option(e));
if (!strcmp(o->e.name, option)) { if (!strcmp(o->e.name, option)) {
if (o->type == UCI_TYPE_LIST) { if (o->type == UCI_TYPE_LIST) {
@ -237,11 +237,43 @@ not_found:
return UCI_ERR_NOTFOUND; return UCI_ERR_NOTFOUND;
} }
int cwmp_uci_get_value_by_section_list(struct uci_section *s, char *option, struct uci_list **value) static void cwmp_uci_list_init(struct uci_list *ptr)
{ {
struct uci_element *e; ptr->prev = ptr;
struct uci_option *o; ptr->next = ptr;
struct uci_list *list; }
static void cwmp_uci_list_insert(struct uci_list *list, struct uci_list *ptr)
{
list->next->prev = ptr;
ptr->prev = list;
ptr->next = list->next;
list->next = ptr;
}
static void cwmp_uci_list_add(struct uci_list *head, struct uci_list *ptr)
{
cwmp_uci_list_insert(head->prev, ptr);
}
static void cwmp_uci_list_del(struct uci_element *e)
{
struct uci_list *ptr = e->list.prev;
ptr->next = e->list.next;
}
static void cwmp_delete_uci_element_from_list(struct uci_element *e)
{
cwmp_uci_list_del(e);
free(e->name);
free(e);
}
static int cwmp_uci_get_value_by_section_list(struct uci_section *s, char *option, struct uci_list **value)
{
struct uci_element *e = NULL;
struct uci_option *o = NULL;
struct uci_list *list = NULL;
char *pch = NULL, *spch = NULL; char *pch = NULL, *spch = NULL;
char dup[256]; char dup[256];
@ -250,8 +282,7 @@ int cwmp_uci_get_value_by_section_list(struct uci_section *s, char *option, stru
if (s == NULL || option == NULL) if (s == NULL || option == NULL)
return -1; return -1;
uci_foreach_element(&s->options, e) uci_foreach_element(&s->options, e) {
{
o = (uci_to_option(e)); o = (uci_to_option(e));
if (strcmp(o->e.name, option) == 0) { if (strcmp(o->e.name, option) == 0) {
switch (o->type) { switch (o->type) {
@ -278,22 +309,26 @@ int cwmp_uci_get_value_by_section_list(struct uci_section *s, char *option, stru
} }
} }
} }
return -1; return -1;
} }
/* /*
* UCI Set option value * UCI Set option value
*/ */
int cwmp_uci_set_value_string(char *package, char *section, char *option, char *value, uci_config_paths uci_type) static int cwmp_uci_set_value_string(char *package, char *section, char *option, char *value, uci_config_paths uci_type)
{ {
struct uci_ptr ptr = {0}; struct uci_ptr ptr = {0};
if (cwmp_uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, package, section, option, value)) if (cwmp_uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, package, section, option, value))
return UCI_ERR_PARSE; return UCI_ERR_PARSE;
if (uci_set(uci_save_conf_paths[uci_type].uci_ctx, &ptr) != UCI_OK) if (uci_set(uci_save_conf_paths[uci_type].uci_ctx, &ptr) != UCI_OK)
return UCI_ERR_NOTFOUND; return UCI_ERR_NOTFOUND;
if (ptr.o) if (ptr.o)
return UCI_OK; return UCI_OK;
return UCI_ERR_NOTFOUND; return UCI_ERR_NOTFOUND;
} }
@ -307,25 +342,26 @@ int cwmp_uci_set_varstate_value(char *package, char*section, char *option, char
return cwmp_uci_set_value_string(package, section, option, value, UCI_VARSTATE_CONFIG); return cwmp_uci_set_value_string(package, section, option, value, UCI_VARSTATE_CONFIG);
} }
int uci_set_value_by_path(char *path, char *value, uci_config_paths uci_type) static int uci_set_value_by_path(char *path, char *value, uci_config_paths uci_type)
{ {
struct uci_ptr ptr; struct uci_ptr ptr = {0};
char cmd[256] = {0};
int ret = UCI_OK; int ret = UCI_OK;
char cmd[256];
snprintf(cmd, sizeof(cmd), "%s=%s", path, value); snprintf(cmd, sizeof(cmd), "%s=%s", path, value);
if (uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, cmd, true) != UCI_OK) {
if (uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, cmd, true) != UCI_OK)
return UCI_ERR_PARSE; return UCI_ERR_PARSE;
}
ret = uci_set(uci_save_conf_paths[uci_type].uci_ctx, &ptr); ret = uci_set(uci_save_conf_paths[uci_type].uci_ctx, &ptr);
if (ret == UCI_OK) { if (ret == UCI_OK) {
ret = uci_save(uci_save_conf_paths[uci_type].uci_ctx, ptr.p); ret = uci_save(uci_save_conf_paths[uci_type].uci_ctx, ptr.p);
} else { } else {
CWMP_LOG(ERROR, "UCI delete not succeed %s", path); CWMP_LOG(ERROR, "UCI Set not succeed %s", path);
return UCI_ERR_NOTFOUND; ret = UCI_ERR_NOTFOUND;
} }
return ret; return ret;
} }
@ -342,43 +378,13 @@ int cwmp_uci_set_varstate_value_by_path(char *path, char *value)
/* /*
* UCI Lists * UCI Lists
*/ */
void cwmp_uci_list_init(struct uci_list *ptr)
{
ptr->prev = ptr;
ptr->next = ptr;
}
void cwmp_uci_list_insert(struct uci_list *list, struct uci_list *ptr)
{
list->next->prev = ptr;
ptr->prev = list;
ptr->next = list->next;
list->next = ptr;
}
void cwmp_uci_list_add(struct uci_list *head, struct uci_list *ptr)
{
cwmp_uci_list_insert(head->prev, ptr);
}
void cwmp_uci_list_del(struct uci_element *e)
{
struct uci_list *ptr = e->list.prev;
ptr->next = e->list.next;
}
void cwmp_delete_uci_element_from_list(struct uci_element *e)
{
cwmp_uci_list_del(e);
free(e->name);
free(e);
}
void cwmp_free_uci_list(struct uci_list *list) void cwmp_free_uci_list(struct uci_list *list)
{ {
struct uci_element *e = NULL, *tmp = NULL; struct uci_element *e = NULL, *tmp = NULL;
if (list == NULL) if (list == NULL)
return; return;
uci_foreach_element_safe(list, e, tmp) uci_foreach_element_safe(list, e, tmp)
cwmp_delete_uci_element_from_list(e); cwmp_delete_uci_element_from_list(e);
} }
@ -387,14 +393,15 @@ char *cwmp_uci_list_to_string(struct uci_list *list, char *delimitor)
{ {
if (delimitor == NULL) if (delimitor == NULL)
return NULL; return NULL;
if (list && !uci_list_empty(list)) { if (list && !uci_list_empty(list)) {
struct uci_element *e = NULL; struct uci_element *e = NULL;
char list_val[512] = { 0 }; char list_val[512] = { 0 };
unsigned pos = 0; unsigned pos = 0;
list_val[0] = 0; list_val[0] = 0;
uci_foreach_element(list, e)
{ uci_foreach_element(list, e) {
if (e->name) if (e->name)
pos += snprintf(&list_val[pos], sizeof(list_val) - pos, "%s%s", e->name, delimitor); pos += snprintf(&list_val[pos], sizeof(list_val) - pos, "%s%s", e->name, delimitor);
} }
@ -404,6 +411,7 @@ char *cwmp_uci_list_to_string(struct uci_list *list, char *delimitor)
return icwmp_strdup(list_val); return icwmp_strdup(list_val);
} }
return NULL; return NULL;
} }
@ -411,7 +419,7 @@ int cwmp_uci_get_option_value_list(char *package, char *section, char *option, u
{ {
struct uci_element *e = NULL; struct uci_element *e = NULL;
struct uci_ptr ptr = {0}; struct uci_ptr ptr = {0};
struct uci_list *list; struct uci_list *list = NULL;
char *pch = NULL, *spch = NULL, *dup = NULL; char *pch = NULL, *spch = NULL, *dup = NULL;
int option_type; int option_type;
*value = NULL; *value = NULL;
@ -489,25 +497,6 @@ int cwmp_uci_del_list_value(char *package, char *section, char *option, char *va
return 0; return 0;
} }
int uci_add_list_value(char *cmd, uci_config_paths uci_type)
{
struct uci_ptr ptr;
int ret = UCI_OK;
if (uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, cmd, true) != UCI_OK) {
return UCI_ERR_PARSE;
}
ret = uci_add_list(uci_save_conf_paths[uci_type].uci_ctx, &ptr);
if (ret == UCI_OK) {
ret = uci_save(uci_save_conf_paths[uci_type].uci_ctx, ptr.p);
} else {
CWMP_LOG(ERROR, "UCI delete not succeed %s", cmd);
return UCI_ERR_NOTFOUND;
}
return ret;
}
/* /*
* UCI ADD Section * UCI ADD Section
*/ */
@ -515,7 +504,7 @@ int uci_add_list_value(char *cmd, uci_config_paths uci_type)
int cwmp_uci_add_section(char *package, char *stype, uci_config_paths uci_type , struct uci_section **s) int cwmp_uci_add_section(char *package, char *stype, uci_config_paths uci_type , struct uci_section **s)
{ {
struct uci_ptr ptr = {0}; struct uci_ptr ptr = {0};
char fname[128]; char fname[128] = {0};
*s = NULL; *s = NULL;
@ -541,21 +530,23 @@ int cwmp_uci_add_section(char *package, char *stype, uci_config_paths uci_type ,
struct uci_section* get_section_by_section_name(char *package, char *stype, char* sname, uci_config_paths uci_type) struct uci_section* get_section_by_section_name(char *package, char *stype, char* sname, uci_config_paths uci_type)
{ {
struct uci_section *s; struct uci_section *s = NULL;
cwmp_uci_foreach_sections(package, stype, uci_type, s) { cwmp_uci_foreach_sections(package, stype, uci_type, s) {
if (strcmp(section_name(s), sname) == 0) if (strcmp(section_name(s), sname) == 0)
return s; return s;
} }
return NULL;
return NULL;
} }
int cwmp_uci_rename_section_by_section(struct uci_section *s, char *value, uci_config_paths uci_type) static int cwmp_uci_rename_section_by_section(struct uci_section *s, char *value, uci_config_paths uci_type)
{ {
struct uci_ptr up = {0}; struct uci_ptr up = {0};
if (cwmp_uci_lookup_ptr_by_section(uci_save_conf_paths[uci_type].uci_ctx, &up, s, NULL, value) == -1) if (cwmp_uci_lookup_ptr_by_section(uci_save_conf_paths[uci_type].uci_ctx, &up, s, NULL, value) == -1)
return UCI_ERR_PARSE; return UCI_ERR_PARSE;
if (uci_rename(uci_save_conf_paths[uci_type].uci_ctx, &up) != UCI_OK) if (uci_rename(uci_save_conf_paths[uci_type].uci_ctx, &up) != UCI_OK)
return UCI_ERR_NOTFOUND; return UCI_ERR_NOTFOUND;
@ -568,46 +559,28 @@ int cwmp_uci_add_section_with_specific_name(char *package, char *stype, char *se
if (get_section_by_section_name(package, stype, section_name, uci_type) != NULL) if (get_section_by_section_name(package, stype, section_name, uci_type) != NULL)
return UCI_ERR_DUPLICATE; return UCI_ERR_DUPLICATE;
if (cwmp_uci_add_section(package, stype, uci_type, &s) != UCI_OK) if (cwmp_uci_add_section(package, stype, uci_type, &s) != UCI_OK)
return UCI_ERR_UNKNOWN; return UCI_ERR_UNKNOWN;
return cwmp_uci_rename_section_by_section(s, section_name, uci_type); return cwmp_uci_rename_section_by_section(s, section_name, uci_type);
} }
/*
* UCI Delete Value
*/
int uci_delete_value(char *path, int uci_type)
{
struct uci_ptr ptr;
int ret = UCI_OK;
if (uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, path, true) != UCI_OK)
return CWMP_GEN_ERR;
ret = uci_delete(uci_save_conf_paths[uci_type].uci_ctx, &ptr);
if (ret == UCI_OK) {
ret = uci_save(uci_save_conf_paths[uci_type].uci_ctx, ptr.p);
} else {
CWMP_LOG(ERROR, "UCI delete not succeed %s", path);
return CWMP_GEN_ERR;
}
return ret;
}
int cwmp_uci_get_section_type(char *package, char *section, uci_config_paths uci_type, char **value) int cwmp_uci_get_section_type(char *package, char *section, uci_config_paths uci_type, char **value)
{ {
struct uci_ptr ptr = {0}; struct uci_ptr ptr = {0};
if (cwmp_uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, package, section, NULL, NULL)) { if (cwmp_uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, package, section, NULL, NULL)) {
*value = ""; *value = "";
return -1; return -1;
} }
if (ptr.s) { if (ptr.s) {
*value = icwmp_strdup(ptr.s->type); *value = icwmp_strdup(ptr.s->type);
} else { } else {
*value = ""; *value = "";
} }
return UCI_OK; return UCI_OK;
} }
@ -685,14 +658,14 @@ end:
int cwmp_commit_package(char *package, uci_config_paths uci_type) int cwmp_commit_package(char *package, uci_config_paths uci_type)
{ {
struct uci_ptr ptr = { 0 }; struct uci_ptr ptr = {0};
if (uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, package, true) != UCI_OK) {
return -1;
}
if (uci_commit(uci_save_conf_paths[uci_type].uci_ctx, &ptr.p, false) != UCI_OK) { if (uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, package, true) != UCI_OK)
return -1; return -1;
}
if (uci_commit(uci_save_conf_paths[uci_type].uci_ctx, &ptr.p, false) != UCI_OK)
return -1;
return 0; return 0;
} }
@ -701,6 +674,7 @@ int cwmp_uci_import(char *package_name, const char *input_path, uci_config_paths
struct uci_package *package = NULL; struct uci_package *package = NULL;
struct uci_element *e = NULL; struct uci_element *e = NULL;
int ret = CWMP_OK; int ret = CWMP_OK;
FILE *input = fopen(input_path, "r"); FILE *input = fopen(input_path, "r");
if (!input) if (!input)
return -1; return -1;
@ -714,8 +688,8 @@ int cwmp_uci_import(char *package_name, const char *input_path, uci_config_paths
ret = -1; ret = -1;
goto end; goto end;
} }
uci_foreach_element(&uci_save_conf_paths[uci_type].uci_ctx->root, e)
{ uci_foreach_element(&uci_save_conf_paths[uci_type].uci_ctx->root, e) {
struct uci_package *p = uci_to_package(e); struct uci_package *p = uci_to_package(e);
if (uci_commit(uci_save_conf_paths[uci_type].uci_ctx, &p, true) != UCI_OK) if (uci_commit(uci_save_conf_paths[uci_type].uci_ctx, &p, true) != UCI_OK)
ret = CWMP_GEN_ERR; ret = CWMP_GEN_ERR;
@ -728,8 +702,9 @@ end:
int cwmp_uci_export_package(char *package, const char *output_path, uci_config_paths uci_type) int cwmp_uci_export_package(char *package, const char *output_path, uci_config_paths uci_type)
{ {
struct uci_ptr ptr = { 0 }; struct uci_ptr ptr = {0};
int ret = 0; int ret = 0;
FILE *out = fopen(output_path, "a"); FILE *out = fopen(output_path, "a");
if (!out) if (!out)
return -1; return -1;
@ -750,7 +725,7 @@ end:
int cwmp_uci_export(const char *output_path, uci_config_paths uci_type) int cwmp_uci_export(const char *output_path, uci_config_paths uci_type)
{ {
char **configs = NULL; char **configs = NULL;
char **p; char **p = NULL;
if (uci_list_configs(uci_save_conf_paths[uci_type].uci_ctx, &configs) != UCI_OK) if (uci_list_configs(uci_save_conf_paths[uci_type].uci_ctx, &configs) != UCI_OK)
return -1; return -1;

View file

@ -3,23 +3,40 @@
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or * the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* HTTP digest auth functions: originally imported from libmicrohttpd
*
* Copyright (C) 2013 Oussama Ghorbel <oussama.ghorbel@pivasoftware.com>
* Omar Kallel <omar.kallel@pivasoftware.com>
* *
* Copyright (C) 2013-2022 iopsys Software Solutions AB
* Author Oussama Ghorbel <oussama.ghorbel@pivasoftware.com>
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*/ */
#ifdef LMBEDTLS
#include <mbedtls/md5.h>
#define MD5_CTX mbedtls_md5_context
#define MD5_INIT(X) { mbedtls_md5_init(X); mbedtls_md5_starts_ret(X); }
#define MD5_UPDATE(X, Y, Z) mbedtls_md5_update_ret(X, (unsigned char *)Y, Z)
#define MD5_FINAL(X, Y) mbedtls_md5_finish_ret(Y, X)
#else
#include <openssl/md5.h>
#define MD5_CTX MD5_CTX
#define MD5_INIT MD5_Init
#define MD5_UPDATE MD5_Update
#define MD5_FINAL MD5_Final
#endif
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <limits.h> #include <limits.h>
#include <stdint.h>
#include "log.h" #include "log.h"
#include "common.h" #include "common.h"
#include "digestauth.h" #include "digestauth.h"
#include "ssl_utils.h" #include "ssl_utils.h"
#include "md5.h"
#ifndef MD5_DIGEST_SIZE
#define MD5_DIGEST_SIZE 16
#endif
#define HASH_MD5_HEX_LEN (2 * MD5_DIGEST_SIZE) #define HASH_MD5_HEX_LEN (2 * MD5_DIGEST_SIZE)
@ -38,11 +55,14 @@
*/ */
#define MAX_AUTH_RESPONSE_LENGTH 1024 #define MAX_AUTH_RESPONSE_LENGTH 1024
/**
* Maximum length of the nonce in digest authentication.
*/
#define MAX_NONCE_LENGTH 1024 #define MAX_NONCE_LENGTH 1024
char *nonce_privacy_key = NULL; char *nonce_privacy_key = NULL;
int generate_nonce_priv_key() int generate_nonce_priv_key(void)
{ {
nonce_privacy_key = generate_random_string(28); nonce_privacy_key = generate_random_string(28);
if (nonce_privacy_key == NULL) if (nonce_privacy_key == NULL)
@ -94,7 +114,7 @@ static void cvthex(const unsigned char *bin, size_t len, char *hex)
*/ */
static void calculate_nonce(uint32_t nonce_time, const char *method, const char *rnd, unsigned int rnd_size, const char *uri, const char *realm, char *nonce, size_t size) static void calculate_nonce(uint32_t nonce_time, const char *method, const char *rnd, unsigned int rnd_size, const char *uri, const char *realm, char *nonce, size_t size)
{ {
struct MD5Context md5; MD5_CTX md5;
unsigned char timestamp[4]; unsigned char timestamp[4];
unsigned char tmpnonce[MD5_DIGEST_SIZE]; unsigned char tmpnonce[MD5_DIGEST_SIZE];
char timestamphex[sizeof(timestamp) * 2 + 1]; char timestamphex[sizeof(timestamp) * 2 + 1];
@ -104,22 +124,22 @@ static void calculate_nonce(uint32_t nonce_time, const char *method, const char
memset(nonce, 0, size); memset(nonce, 0, size);
md5_init(&md5); MD5_INIT(&md5);
timestamp[0] = (nonce_time & 0xff000000) >> 0x18; timestamp[0] = (nonce_time & 0xff000000) >> 0x18;
timestamp[1] = (nonce_time & 0x00ff0000) >> 0x10; timestamp[1] = (nonce_time & 0x00ff0000) >> 0x10;
timestamp[2] = (nonce_time & 0x0000ff00) >> 0x08; timestamp[2] = (nonce_time & 0x0000ff00) >> 0x08;
timestamp[3] = (nonce_time & 0x000000ff); timestamp[3] = (nonce_time & 0x000000ff);
md5_update(&md5, timestamp, 4); MD5_UPDATE(&md5, timestamp, 4);
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
md5_update(&md5, method, strlen(method)); MD5_UPDATE(&md5, method, strlen(method));
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
if (rnd_size > 0) if (rnd_size > 0)
md5_update(&md5, rnd, rnd_size); MD5_UPDATE(&md5, rnd, rnd_size);
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
md5_update(&md5, uri, strlen(uri)); MD5_UPDATE(&md5, uri, strlen(uri));
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
md5_update(&md5, realm, strlen(realm)); MD5_UPDATE(&md5, realm, strlen(realm));
md5_final(tmpnonce, &md5); MD5_FINAL(tmpnonce, &md5);
cvthex(tmpnonce, sizeof(tmpnonce), nonce); cvthex(tmpnonce, sizeof(tmpnonce), nonce);
cvthex(timestamp, 4, timestamphex); cvthex(timestamp, 4, timestamphex);
size_t len = size - strlen(nonce) - 1; size_t len = size - strlen(nonce) - 1;
@ -210,24 +230,24 @@ static int lookup_sub_value(char *dest, size_t size, const char *data, const cha
*/ */
static void digest_calc_ha1(const char *alg, const char *username, const char *realm, const char *password, const char *nonce, const char *cnonce, char *sessionkey) static void digest_calc_ha1(const char *alg, const char *username, const char *realm, const char *password, const char *nonce, const char *cnonce, char *sessionkey)
{ {
struct MD5Context md5; MD5_CTX md5;
unsigned char ha1[MD5_DIGEST_SIZE]; unsigned char ha1[MD5_DIGEST_SIZE];
md5_init(&md5); MD5_INIT(&md5);
md5_update(&md5, username, strlen(username)); MD5_UPDATE(&md5, username, strlen(username));
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
md5_update(&md5, realm, strlen(realm)); MD5_UPDATE(&md5, realm, strlen(realm));
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
md5_update(&md5, password, strlen(password)); MD5_UPDATE(&md5, password, strlen(password));
md5_final(ha1, &md5); MD5_FINAL(ha1, &md5);
if (0 == strcasecmp(alg, "md5-sess")) { if (0 == strcasecmp(alg, "md5-sess")) {
md5_init(&md5); MD5_INIT(&md5);
md5_update(&md5, ha1, sizeof(ha1)); MD5_UPDATE(&md5, ha1, sizeof(ha1));
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
md5_update(&md5, nonce, strlen(nonce)); MD5_UPDATE(&md5, nonce, strlen(nonce));
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
md5_update(&md5, cnonce, strlen(cnonce)); MD5_UPDATE(&md5, cnonce, strlen(cnonce));
md5_final(ha1, &md5); MD5_FINAL(ha1, &md5);
} }
cvthex(ha1, sizeof(ha1), sessionkey); cvthex(ha1, sizeof(ha1), sessionkey);
} }
@ -247,47 +267,36 @@ static void digest_calc_ha1(const char *alg, const char *username, const char *r
*/ */
static void digest_calc_response(const char *ha1, const char *nonce, const char *noncecount, const char *cnonce, const char *qop, const char *method, const char *uri, char *response) static void digest_calc_response(const char *ha1, const char *nonce, const char *noncecount, const char *cnonce, const char *qop, const char *method, const char *uri, char *response)
{ {
struct MD5Context md5; MD5_CTX md5;
unsigned char ha2[MD5_DIGEST_SIZE]; unsigned char ha2[MD5_DIGEST_SIZE];
unsigned char resphash[MD5_DIGEST_SIZE]; unsigned char resphash[MD5_DIGEST_SIZE];
char ha2hex[HASH_MD5_HEX_LEN + 1]; char ha2hex[HASH_MD5_HEX_LEN + 1];
md5_init(&md5); MD5_INIT(&md5);
md5_update(&md5, method, strlen(method)); MD5_UPDATE(&md5, method, strlen(method));
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
md5_update(&md5, uri, strlen(uri)); MD5_UPDATE(&md5, uri, strlen(uri));
md5_final(ha2, &md5); MD5_FINAL(ha2, &md5);
cvthex(ha2, MD5_DIGEST_SIZE, ha2hex); cvthex(ha2, MD5_DIGEST_SIZE, ha2hex);
md5_init(&md5); MD5_INIT(&md5);
/* calculate response */ /* calculate response */
md5_update(&md5, ha1, HASH_MD5_HEX_LEN); MD5_UPDATE(&md5, ha1, HASH_MD5_HEX_LEN);
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
md5_update(&md5, nonce, strlen(nonce)); MD5_UPDATE(&md5, nonce, strlen(nonce));
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
if ('\0' != *qop) { if ('\0' != *qop) {
md5_update(&md5, noncecount, strlen(noncecount)); MD5_UPDATE(&md5, noncecount, strlen(noncecount));
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
md5_update(&md5, cnonce, strlen(cnonce)); MD5_UPDATE(&md5, cnonce, strlen(cnonce));
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
md5_update(&md5, qop, strlen(qop)); MD5_UPDATE(&md5, qop, strlen(qop));
md5_update(&md5, ":", 1); MD5_UPDATE(&md5, ":", 1);
} }
md5_update(&md5, ha2hex, HASH_MD5_HEX_LEN); MD5_UPDATE(&md5, ha2hex, HASH_MD5_HEX_LEN);
md5_final(resphash, &md5); MD5_FINAL(resphash, &md5);
cvthex(resphash, sizeof(resphash), response); cvthex(resphash, sizeof(resphash), response);
} }
/**
* make response to request authentication from the client
*
* @param fp
* @param http_method
* @param url
* @param realm the realm presented to the client
* @param opaque string to user for opaque value
* @return MHD_YES on success, MHD_NO otherwise
*/
int http_digest_auth_fail_response(FILE *fp, const char *http_method, const char *url, const char *realm, const char *opaque) int http_digest_auth_fail_response(FILE *fp, const char *http_method, const char *url, const char *realm, const char *opaque)
{ {
size_t hlen, nonce_key_len = 0; size_t hlen, nonce_key_len = 0;
@ -304,8 +313,6 @@ int http_digest_auth_fail_response(FILE *fp, const char *http_method, const char
snprintf(header, sizeof(header), "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"", realm, nonce, opaque); snprintf(header, sizeof(header), "Digest realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"", realm, nonce, opaque);
DD(DEBUG, "%s: header: %s", __FUNCTION__, header);
fputs("WWW-Authenticate: ", fp); fputs("WWW-Authenticate: ", fp);
fputs(header, fp); fputs(header, fp);
return MHD_YES; return MHD_YES;
@ -313,20 +320,6 @@ int http_digest_auth_fail_response(FILE *fp, const char *http_method, const char
return MHD_NO; return MHD_NO;
} }
/**
* Authenticates the authorization header sent by the client
*
* @param http_method
* @param url
* @param header: pointer to the position just after the string "Authorization: Digest "
* @param realm The realm presented to the client
* @param username The username needs to be authenticated
* @param password The password used in the authentication
* @param nonce_timeout The amount of time for a nonce to be
* invalid in seconds
* @return MHD_YES if authenticated, MHD_NO if not,
* MHD_INVALID_NONCE if nonce is invalid
*/
int http_digest_auth_check(const char *http_method, const char *url, const char *header, const char *realm, const char *username, const char *password, unsigned int nonce_timeout) int http_digest_auth_check(const char *http_method, const char *url, const char *header, const char *realm, const char *username, const char *password, unsigned int nonce_timeout)
{ {
size_t len; size_t len;
@ -334,8 +327,6 @@ int http_digest_auth_check(const char *http_method, const char *url, const char
char nonce[MAX_NONCE_LENGTH]; char nonce[MAX_NONCE_LENGTH];
size_t left; /* number of characters left in 'header' for 'uri' */ size_t left; /* number of characters left in 'header' for 'uri' */
DD(DEBUG, "%s: header: %s", __FUNCTION__, header);
left = strlen(header); left = strlen(header);
{ {
@ -392,13 +383,15 @@ int http_digest_auth_check(const char *http_method, const char *url, const char
} }
if (0 != strncmp(uri, url, strlen(url))) { if (0 != strncmp(uri, url, strlen(url))) {
DD(DEBUG, "Authentication failed: URI does not match."); CWMP_LOG(ERROR, "Authentication failed: URI does not match.");
return MHD_NO; return MHD_NO;
} }
if (nonce_privacy_key == NULL) { if (nonce_privacy_key == NULL) {
if (generate_nonce_priv_key() != CWMP_OK) if (generate_nonce_priv_key() != CWMP_OK)
return MHD_INVALID_NONCE; return MHD_INVALID_NONCE;
} }
nonce_key_len = strlen(nonce_privacy_key); nonce_key_len = strlen(nonce_privacy_key);
calculate_nonce(nonce_time, http_method, nonce_privacy_key, nonce_key_len, url, realm, noncehashexp, sizeof(noncehashexp)); calculate_nonce(nonce_time, http_method, nonce_privacy_key, nonce_key_len, url, realm, noncehashexp, sizeof(noncehashexp));
@ -419,12 +412,13 @@ int http_digest_auth_check(const char *http_method, const char *url, const char
if ((0 == lookup_sub_value(cnonce, sizeof(cnonce), header, "cnonce")) || (0 == lookup_sub_value(qop, sizeof(qop), header, "qop")) || ((0 != strcmp(qop, "auth")) && (0 != strcmp(qop, ""))) || (0 == lookup_sub_value(nc, sizeof(nc), header, "nc")) || if ((0 == lookup_sub_value(cnonce, sizeof(cnonce), header, "cnonce")) || (0 == lookup_sub_value(qop, sizeof(qop), header, "qop")) || ((0 != strcmp(qop, "auth")) && (0 != strcmp(qop, ""))) || (0 == lookup_sub_value(nc, sizeof(nc), header, "nc")) ||
(0 == lookup_sub_value(response, sizeof(response), header, "response"))) { (0 == lookup_sub_value(response, sizeof(response), header, "response"))) {
DD(DEBUG, "Authentication failed, invalid format."); CWMP_LOG(ERROR, "Authentication failed, invalid format.");
return MHD_NO; return MHD_NO;
} }
nci = strtoul(nc, &end, 16); nci = strtoul(nc, &end, 16);
if (('\0' != *end) || ((LONG_MAX == nci) && (ERANGE == errno))) { if (('\0' != *end) || ((LONG_MAX == nci) && (ERANGE == errno))) {
DD(DEBUG, "Authentication failed, invalid format."); CWMP_LOG(ERROR, "Authentication failed, invalid format.");
return MHD_NO; /* invalid nonce format */ return MHD_NO; /* invalid nonce format */
} }
@ -436,6 +430,7 @@ int http_digest_auth_check(const char *http_method, const char *url, const char
digest_calc_ha1("md5", username, realm, password, nonce, cnonce, ha1); digest_calc_ha1("md5", username, realm, password, nonce, cnonce, ha1);
digest_calc_response(ha1, nonce, nc, cnonce, qop, http_method, uri, respexp); digest_calc_response(ha1, nonce, nc, cnonce, qop, http_method, uri, respexp);
return (0 == strcmp(response, respexp)) ? MHD_YES : MHD_NO; return (0 == strcmp(response, respexp)) ? MHD_YES : MHD_NO;
} }
} }

View file

@ -16,7 +16,6 @@
#include "ubus.h" #include "ubus.h"
#include "cwmp_uci.h" #include "cwmp_uci.h"
#include "backupSession.h" #include "backupSession.h"
#include "cwmp_time.h"
#include "log.h" #include "log.h"
#include "event.h" #include "event.h"
@ -175,7 +174,7 @@ int cwmp_launch_download(struct download *pdownload, char *download_file_name, e
char *download_startTime; char *download_startTime;
struct transfer_complete *p; struct transfer_complete *p;
download_startTime = mix_get_time(); download_startTime = get_time(time(NULL));
ltype == TYPE_DOWNLOAD ? bkp_session_delete_download(pdownload) : bkp_session_delete_schedule_download(pdownload); ltype == TYPE_DOWNLOAD ? bkp_session_delete_download(pdownload) : bkp_session_delete_schedule_download(pdownload);
bkp_session_save(); bkp_session_save();
@ -246,7 +245,7 @@ end_download:
p->command_key = pdownload->command_key ? strdup(pdownload->command_key) : strdup(""); p->command_key = pdownload->command_key ? strdup(pdownload->command_key) : strdup("");
p->start_time = strdup(download_startTime); p->start_time = strdup(download_startTime);
p->complete_time = strdup(mix_get_time()); p->complete_time = strdup(get_time(time(NULL)));
p->type = ltype; p->type = ltype;
if (error != FAULT_CPE_NO_FAULT) { if (error != FAULT_CPE_NO_FAULT) {
p->fault_code = error; p->fault_code = error;
@ -348,7 +347,7 @@ struct transfer_complete *set_download_error_transfer_complete(struct cwmp *cwmp
ptransfer_complete = calloc(1, sizeof(struct transfer_complete)); ptransfer_complete = calloc(1, sizeof(struct transfer_complete));
if (ptransfer_complete != NULL) { if (ptransfer_complete != NULL) {
ptransfer_complete->command_key = strdup(pdownload->command_key); ptransfer_complete->command_key = strdup(pdownload->command_key);
ptransfer_complete->start_time = strdup(mix_get_time()); ptransfer_complete->start_time = strdup(get_time(time(NULL)));
ptransfer_complete->complete_time = strdup(ptransfer_complete->start_time); ptransfer_complete->complete_time = strdup(ptransfer_complete->start_time);
ptransfer_complete->fault_code = ltype == TYPE_DOWNLOAD ? FAULT_CPE_DOWNLOAD_FAILURE : FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW; ptransfer_complete->fault_code = ltype == TYPE_DOWNLOAD ? FAULT_CPE_DOWNLOAD_FAILURE : FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW;
ptransfer_complete->type = ltype; ptransfer_complete->type = ltype;
@ -701,7 +700,7 @@ void *thread_cwmp_rpc_cpe_apply_schedule_download(void *v)
} }
ptransfer_complete->command_key = strdup(apply_download->command_key); ptransfer_complete->command_key = strdup(apply_download->command_key);
ptransfer_complete->start_time = strdup(apply_download->start_time); ptransfer_complete->start_time = strdup(apply_download->start_time);
ptransfer_complete->complete_time = strdup(mix_get_time()); ptransfer_complete->complete_time = strdup(get_time(time(NULL)));
ptransfer_complete->fault_code = error; ptransfer_complete->fault_code = error;
ptransfer_complete->type = TYPE_SCHEDULE_DOWNLOAD; ptransfer_complete->type = TYPE_SCHEDULE_DOWNLOAD;
bkp_session_insert_transfer_complete(ptransfer_complete); bkp_session_insert_transfer_complete(ptransfer_complete);

View file

@ -4,12 +4,12 @@
* the Free Software Foundation, either version 2 of the License, or * the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Copyright (C) 2013-2020 iopsys Software Solutions AB * Copyright (C) 2013-2022 iopsys Software Solutions AB
* Author Omar Kallel <omar.kallel@pivasoftware.com> * Author Omar Kallel <omar.kallel@pivasoftware.com>
* *
*/ */
#ifndef __CCOMMON_H #ifndef CWMP_COMMON_H
#define __CCOMMON_H #define CWMP_COMMON_H
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
@ -21,9 +21,21 @@
#define CWMP_VERSION "3.0.0" #define CWMP_VERSION "3.0.0"
#endif #endif
#define __offsetof__(x) (x) #ifndef FREE
#define FREE(x) do { if(x) {free(x); x = NULL;} } while (0)
#endif
#define ARRAYSIZEOF(a) (sizeof(a) / sizeof((a)[0])) #ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#endif
#define CWMP_STRCMP(S1, S2) ((S1 != NULL && S2 != NULL) ? strcmp(S1, S2) : -1)
#define CWMP_STRNCPY(DST, SRC, SIZE) \
do { \
strncpy(DST, SRC, SIZE - 1); \
DST[SIZE - 1] = '\0'; \
} while (0)
#define USP_OBJECT_NAME "usp.raw" #define USP_OBJECT_NAME "usp.raw"
#define MAX_EVENTS 64 #define MAX_EVENTS 64
@ -49,7 +61,6 @@
#define FIREWALL_CWMP "/etc/firewall.cwmp" #define FIREWALL_CWMP "/etc/firewall.cwmp"
#define CWMP_VARSTATE_UCI_PACKAGE "/var/state/cwmp" #define CWMP_VARSTATE_UCI_PACKAGE "/var/state/cwmp"
#define STRCMP(S1, S2) ((S1 != NULL && S2 != NULL) ? strcmp(S1, S2) : -1)
extern char *commandKey; extern char *commandKey;
extern bool thread_end; extern bool thread_end;
extern bool signal_exit; extern bool signal_exit;
@ -156,7 +167,10 @@ enum action {
RESTART, RESTART,
}; };
enum cwmp_start { CWMP_START_BOOT = 1, CWMP_START_PERIODIC = 2 }; enum cwmp_start {
CWMP_START_BOOT = 1,
CWMP_START_PERIODIC = 2
};
enum cwmp_ret_err { enum cwmp_ret_err {
CWMP_XML_ERR = -1, CWMP_XML_ERR = -1,
@ -167,9 +181,16 @@ enum cwmp_ret_err {
CWMP_RETRY_SESSION CWMP_RETRY_SESSION
}; };
enum http_compression { COMP_NONE, COMP_GZIP, COMP_DEFLATE }; enum http_compression {
COMP_NONE,
COMP_GZIP,
COMP_DEFLATE
};
enum enum_ip_version { IPv4 = 4, IPv6 = 6 }; enum enum_ip_version {
IPv4 = 4,
IPv6 = 6
};
typedef struct rpc { typedef struct rpc {
struct list_head list; struct list_head list;
@ -202,7 +223,10 @@ enum amd_version_enum {
AMD_5, AMD_5,
}; };
enum instance_mode { INSTANCE_MODE_NUMBER, INSTANCE_MODE_ALIAS }; enum instance_mode {
INSTANCE_MODE_NUMBER,
INSTANCE_MODE_ALIAS
};
struct cwmp_namespaces { struct cwmp_namespaces {
char *soap_env; char *soap_env;
@ -248,9 +272,17 @@ enum acs_support_idx {
RPC_ACS_NOT_SUPPORT RPC_ACS_NOT_SUPPORT
}; };
enum load_type { TYPE_DOWNLOAD = 0, TYPE_SCHEDULE_DOWNLOAD, TYPE_UPLOAD }; enum load_type {
TYPE_DOWNLOAD = 0,
TYPE_SCHEDULE_DOWNLOAD,
TYPE_UPLOAD
};
enum dustate_type { DU_INSTALL = 1, DU_UPDATE, DU_UNINSTALL }; enum dustate_type {
DU_INSTALL = 1,
DU_UPDATE,
DU_UNINSTALL
};
enum fault_cpe_idx { enum fault_cpe_idx {
FAULT_CPE_NO_FAULT, FAULT_CPE_NO_FAULT,
@ -322,7 +354,10 @@ enum fault_code_enum {
__FAULT_MAX __FAULT_MAX
}; };
enum client_server_faults { FAULT_CPE_TYPE_CLIENT, FAULT_CPE_TYPE_SERVER }; enum client_server_faults {
FAULT_CPE_TYPE_CLIENT,
FAULT_CPE_TYPE_SERVER
};
struct rpc_cpe_method { struct rpc_cpe_method {
const char *name; const char *name;
@ -452,8 +487,7 @@ extern long int flashsize;
extern struct FAULT_CPE FAULT_CPE_ARRAY[]; extern struct FAULT_CPE FAULT_CPE_ARRAY[];
extern struct cwmp_namespaces ns; extern struct cwmp_namespaces ns;
void add_dm_parameter_to_list(struct list_head *head, char *param_name, char *param_data, char *param_type, void add_dm_parameter_to_list(struct list_head *head, char *param_name, char *param_data, char *param_type, int notification, bool writable);
int notification, bool writable);
void delete_dm_parameter_from_list(struct cwmp_dm_parameter *dm_parameter); void delete_dm_parameter_from_list(struct cwmp_dm_parameter *dm_parameter);
void cwmp_free_all_dm_parameter_list(struct list_head *list); void cwmp_free_all_dm_parameter_list(struct list_head *list);
int global_env_init(int argc, char **argv, struct env *env); int global_env_init(int argc, char **argv, struct env *env);
@ -494,27 +528,7 @@ void clean_custom_inform_parameters();
char *string_to_hex(const unsigned char *str, size_t size); char *string_to_hex(const unsigned char *str, size_t size);
int copy_file(char *source_file, char *target_file); int copy_file(char *source_file, char *target_file);
int get_connection_interface(); int get_connection_interface();
bool is_obj_excluded(char *object_name); char *get_time(time_t t_time);
bool is_obj_excluded(const char *object_name);
#ifndef FREE #endif /* CWMP_COMMON_H */
#define FREE(x) \
do { \
if (x) { \
free(x); \
x = NULL; \
} \
} while (0)
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#endif
#define CWMP_STRNCPY(DST, SRC, SIZE) \
do { \
strncpy(DST, SRC, SIZE - 1); \
DST[SIZE - 1] = '\0'; \
} while (0)
#endif

40
inc/cwmp_http.h Normal file
View file

@ -0,0 +1,40 @@
/*
* cwmp_http.c: Utility functions for http server and client
*
* Copyright (C) 2022 iopsys Software Solutions AB. All rights reserved.
*
* Author: Mohamed Kallel <mohamed.kallel@pivasoftware.com>
* Author: Ahmed Zribi <ahmed.zribi@pivasoftware.com>
* Author: Omar Kallel <omar.kallel@pivasoftware.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifndef CWMP_HTTP_H__
#define CWMP_HTTP_H__
#include "common.h"
void cwmp_http_server_init(void);
void cwmp_http_server_listen(void);
int cwmp_http_client_init(struct cwmp *cwmp);
int cwmp_http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char **msg_in);
void cwmp_http_client_exit(void);
void cwmp_http_remove_cookies_file(void);
void cwmp_http_set_timeout(void);
#endif /* CWMP_HTTP_H__ */

View file

@ -1,18 +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 <omar.kallel@pivasoftware.com>
*
*/
#ifndef CWMP_TIME_H_
#define CWMP_TIME_H_
char *mix_get_time(void);
char *mix_get_time_of(time_t t_time);
#endif /* SRC_INC_CWMP_TIME_H_ */

View file

@ -4,19 +4,18 @@
* the Free Software Foundation, either version 2 of the License, or * the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Copyright (C) 2013-2020 iopsys Software Solutions AB * Copyright (C) 2013-2022 iopsys Software Solutions AB
* Author Omar Kallel <omar.kallel@pivasoftware.com> * Author Omar Kallel <omar.kallel@pivasoftware.com>
* *
*/ */
#ifndef __CWMPUCI_H #ifndef CWMP_UCI_H
#define __CWMPUCI_H #define CWMP_UCI_H
#include <uci.h> #include <uci.h>
#include "common.h" #include "common.h"
//struct uci_context *cwmp_uci_ctx = ((void *)0);
#define UCI_DHCP_DISCOVERY_PATH "cwmp.acs.dhcp_discovery" #define UCI_DHCP_DISCOVERY_PATH "cwmp.acs.dhcp_discovery"
#define UCI_ACS_URL_PATH "cwmp.acs.url" #define UCI_ACS_URL_PATH "cwmp.acs.url"
#define UCI_PERIODIC_INFORM_TIME_PATH "cwmp.acs.periodic_inform_time" #define UCI_PERIODIC_INFORM_TIME_PATH "cwmp.acs.periodic_inform_time"
@ -118,15 +117,12 @@ struct uci_paths {
struct uci_context *uci_ctx; struct uci_context *uci_ctx;
}; };
extern struct uci_paths uci_save_conf_paths[]; int cwmp_uci_init(void);
int cwmp_uci_init();
void cwmp_uci_exit(void); void cwmp_uci_exit(void);
void cwmp_uci_reinit(void); void cwmp_uci_reinit(void);
int cwmp_uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *package, char *section, char *option, char *value);
int cwmp_uci_get_cwmp_standard_option_value_list(char *package, char *section, char *option, struct uci_list **value); int cwmp_uci_get_cwmp_standard_option_value_list(char *package, char *section, char *option, struct uci_list **value);
int cwmp_uci_get_cwmp_varstate_option_value_list(char *package, char *section, char *option, struct uci_list **value); int cwmp_uci_get_cwmp_varstate_option_value_list(char *package, char *section, char *option, struct uci_list **value);
int uci_get_state_value(char *cmd, char **value); int uci_get_state_value(char *cmd, char **value);
int uci_set_value_by_path(char *cmd, char *value, uci_config_paths uci_type);
int cwmp_uci_set_value_by_path(char *path, char *value); int cwmp_uci_set_value_by_path(char *path, char *value);
int cwmp_uci_set_varstate_value_by_path(char *path, char *value); int cwmp_uci_set_varstate_value_by_path(char *path, char *value);
int uci_get_value(char *cmd, char **value); int uci_get_value(char *cmd, char **value);
@ -146,8 +142,6 @@ int cwmp_uci_set_value(char *package, char *section, char *option, char *value);
int cwmp_uci_set_varstate_value(char *package, char*section, char *option, char *value); int cwmp_uci_set_varstate_value(char *package, char*section, char *option, char *value);
int cwmp_uci_add_section_with_specific_name(char *package, char *stype, char *section, uci_config_paths uci_type); int cwmp_uci_add_section_with_specific_name(char *package, char *stype, char *section, uci_config_paths uci_type);
char *cwmp_uci_list_to_string(struct uci_list *list, char *delimitor); char *cwmp_uci_list_to_string(struct uci_list *list, char *delimitor);
void cwmp_uci_list_init(struct uci_list *ptr);
void cwmp_uci_list_add(struct uci_list *head, struct uci_list *ptr);
struct uci_section* get_section_by_section_name(char *package, char *stype, char* sname, uci_config_paths uci_type); struct uci_section* get_section_by_section_name(char *package, char *stype, char* sname, uci_config_paths uci_type);
#define cwmp_uci_path_foreach_option_eq(package, stype, option, val, section) \ #define cwmp_uci_path_foreach_option_eq(package, stype, option, val, section) \
@ -158,4 +152,5 @@ struct uci_section* get_section_by_section_name(char *package, char *stype, char
#define cwmp_uci_foreach_varstate_sections(package, stype, section) \ #define cwmp_uci_foreach_varstate_sections(package, stype, section) \
for (section = cwmp_uci_walk_section(package, stype, NULL, NULL, CWMP_CMP_SECTION, NULL, NULL, UCI_VARSTATE_CONFIG, CWMP_GET_FIRST_SECTION); section != NULL; section = cwmp_uci_walk_section(package, stype, NULL, NULL, CWMP_CMP_SECTION, NULL, section, UCI_VARSTATE_CONFIG, CWMP_GET_NEXT_SECTION)) for (section = cwmp_uci_walk_section(package, stype, NULL, NULL, CWMP_CMP_SECTION, NULL, NULL, UCI_VARSTATE_CONFIG, CWMP_GET_FIRST_SECTION); section != NULL; section = cwmp_uci_walk_section(package, stype, NULL, NULL, CWMP_CMP_SECTION, NULL, section, UCI_VARSTATE_CONFIG, CWMP_GET_NEXT_SECTION))
#endif
#endif /* CWMP_UCI_H */

View file

@ -3,10 +3,10 @@
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or * the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* HTTP digest auth functions: originally imported from libmicrohttpd
*
* Copyright (C) 2013 Oussama Ghorbel <oussama.ghorbel@pivasoftware.com>
* *
* Copyright (C) 2013-2022 iopsys Software Solutions AB
* Author Oussama Ghorbel <oussama.ghorbel@pivasoftware.com>
* Author Omar Kallel <omar.kallel@pivasoftware.com>
*/ */
#ifndef DIGESTAUTH_H_ #ifndef DIGESTAUTH_H_
@ -29,10 +29,32 @@
extern char *nonce_privacy_key; extern char *nonce_privacy_key;
/**
* make response to request authentication from the client
*
* @param fp
* @param http_method
* @param url
* @param realm the realm presented to the client
* @param opaque string to user for opaque value
* @return 'MHD_YES' on success, otherwise 'MHD_NO'
*/
int http_digest_auth_fail_response(FILE *fp, const char *http_method, const char *url, const char *realm, const char *opaque); int http_digest_auth_fail_response(FILE *fp, const char *http_method, const char *url, const char *realm, const char *opaque);
/**
* Authenticates the authorization header sent by the client
*
* @param http_method
* @param url
* @param header: pointer to the position just after the string "Authorization: Digest "
* @param realm The realm presented to the client
* @param username The username needs to be authenticated
* @param password The password used in the authentication
* @param nonce_timeout The amount of time for a nonce to be invalid in seconds
* @return 'MHD_YES' if authenticated, 'MHD_NO' if not, 'MHD_INVALID_NONCE' if nonce is invalid
*/
int http_digest_auth_check(const char *http_method, const char *url, const char *header, const char *realm, const char *username, const char *password, unsigned int nonce_timeout); int http_digest_auth_check(const char *http_method, const char *url, const char *header, const char *realm, const char *username, const char *password, unsigned int nonce_timeout);
int generate_nonce_priv_key(); int generate_nonce_priv_key(void);
#endif /* DIGESTAUTH_H_ */ #endif /* DIGESTAUTH_H_ */

View file

@ -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 <freecwmp@lukaperkov.net>
*/
#ifndef _FREECWMP_HTTP_H__
#define _FREECWMP_HTTP_H__
#include "common.h"
extern char *fc_cookies;
#define HTTP_TIMEOUT 30
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

View file

@ -4,7 +4,7 @@
* the Free Software Foundation, either version 2 of the License, or * the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Copyright (C) 2013-2019 iopsys Software Solutions AB * Copyright (C) 2013-2022 iopsys Software Solutions AB
* Author Mohamed Kallel <mohamed.kallel@pivasoftware.com> * Author Mohamed Kallel <mohamed.kallel@pivasoftware.com>
* Author Ahmed Zribi <ahmed.zribi@pivasoftware.com> * Author Ahmed Zribi <ahmed.zribi@pivasoftware.com>
* *
@ -39,58 +39,12 @@ int log_set_on_console(char *value);
int log_set_on_file(char *value); int log_set_on_file(char *value);
int log_set_on_syslog(char *value); int log_set_on_syslog(char *value);
int log_set_severity_idx(char *value); int log_set_severity_idx(char *value);
#define DEFAULT_LOG_FILE_SIZE 10240 #define DEFAULT_LOG_FILE_SIZE 10240
#define DEFAULT_LOG_FILE_NAME "/var/log/icwmpd.log" #define DEFAULT_LOG_FILE_NAME "/var/log/icwmpd.log"
#define DEFAULT_LOG_SEVERITY INFO #define DEFAULT_LOG_SEVERITY INFO
#ifdef WITH_CWMP_DEBUG
#ifndef CWMP_LOG
#define CWMP_LOG(SEV, MESSAGE, args...) puts_log(SEV, MESSAGE, ##args); #define CWMP_LOG(SEV, MESSAGE, args...) puts_log(SEV, MESSAGE, ##args);
#define CWMP_LOG_XML_MSG puts_log_xmlmsg #define CWMP_LOG_XML_MSG puts_log_xmlmsg
#endif
#else
#define CWMP_LOG(SEV, MESSAGE, args...)
#define CWMP_LOG_XML_MSG(X, Y, Z)
#endif
#ifdef WITH_DEV_DEBUG
#ifndef DD
#define DD(SEV, MESSAGE, args...) puts_log(SEV, MESSAGE, ##args);
#endif
#else
#define DD(SEV, MESSAGE, args...)
#endif
#ifndef DETECT_CRASH
#define DETECT_CRASH(MESSAGE, args...) \
{ \
const char *A[] = { MESSAGE }; \
printf("DETECT_CRASH: %s %s %d\n", __FUNCTION__, __FILE__, __LINE__); \
fflush(stdout); \
if (sizeof(A) > 0) \
printf(*A, ##args); \
sleep(1); \
}
#endif
#ifndef TRACE
#define TRACE_TYPE 0
static inline void trace_empty_func() {}
#if TRACE_TYPE == 2
#define TRACE(MESSAGE, args...) \
do { \
const char *A[] = { MESSAGE }; \
fprintf(stderr, "TRACE: %s %s %d ", __FUNCTION__, __FILE__, __LINE__); \
if (sizeof(A) > 0) \
fprintf(stderr, *A, ##args); \
fprintf(stderr, "\n"); \
fflush(stderr); \
} while (0)
#elif TRACE_TYPE == 1
#define TRACE(MESSAGE, ...) printf(MESSAGE, ##__VA_ARGS__)
#else
#define TRACE(MESSAGE, ...) trace_empty_func()
#endif
#endif
#endif /* _LOG_H_ */ #endif /* _LOG_H_ */

View file

@ -1,41 +0,0 @@
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
#ifndef MD5_H
#define MD5_H
#ifdef WORDS_BIGENDIAN
#define HIGHFIRST
#endif
#include <stdint.h>
#define MD5_DIGEST_SIZE 16
struct MD5Context {
uint32_t buf[4];
uint32_t bits[2];
unsigned char in[64];
};
void md5_init(struct MD5Context *ctx);
void md5_update(struct MD5Context *ctx, const void *buf, unsigned len);
void md5_final(unsigned char digest[MD5_DIGEST_SIZE], struct MD5Context *ctx);
#endif /* !MD5_H */

View file

@ -1,70 +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 <freecwmp@lukaperkov.net>
*/
#ifndef _FREECWMP_MESSAGES_H__
#define _FREECWMP_MESSAGES_H__
#define CWMP_LWNOTIFICATION_MESSAGE \
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \
"<Notification " \
"xmlns=\"urn:broadband-forum-org:cwmp:lwnotif-1-0\" " \
"xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" " \
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \
"xsi:schemaLocation=\"urn:broadband-forum-org:cwmp:lwnotif-1-0 " \
"http://www.broadband-forum.org/cwmp/cwmp-UDPLightweightNotification-1-0.xsd\">" \
"<TS/>" \
"<UN/>" \
"<CN/>" \
"<OUI/>" \
"<ProductClass/>" \
"<SerialNumber/>" \
"</Notification>"
#define CWMP_INFORM_MESSAGE \
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" \
"<soap_env:Envelope " \
"xmlns:soap_env=\"http://schemas.xmlsoap.org/soap/envelope/\" " \
"xmlns:soap_enc=\"http://schemas.xmlsoap.org/soap/encoding/\" " \
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " \
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" >" \
"<soap_env:Header>" \
"<cwmp:ID soap_env:mustUnderstand=\"1\"/>" \
"</soap_env:Header>" \
"<soap_env:Body>" \
"<cwmp:Inform>" \
"<DeviceId>" \
"<Manufacturer/>" \
"<OUI/>" \
"<ProductClass/>" \
"<SerialNumber/>" \
"</DeviceId>" \
"<Event soap_enc:arrayType=\"cwmp:EventStruct[0]\" />" \
"<MaxEnvelopes>1</MaxEnvelopes>" \
"<CurrentTime/>" \
"<RetryCount/>" \
"<ParameterList soap_enc:arrayType=\"cwmp:ParameterValueStruct[0]\" />" \
"</cwmp:Inform>" \
"</soap_env:Body>" \
"</soap_env:Envelope>"
#define CWMP_RESPONSE_MESSAGE \
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" \
"<soap_env:Envelope " \
"xmlns:soap_env=\"http://schemas.xmlsoap.org/soap/envelope/\" " \
"xmlns:soap_enc=\"http://schemas.xmlsoap.org/soap/encoding/\" " \
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " \
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" \
"<soap_env:Header>" \
"<cwmp:ID soap_env:mustUnderstand=\"1\"/>" \
"</soap_env:Header>" \
"<soap_env:Body/>" \
"</soap_env:Envelope>"
#endif

View file

@ -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 <mohamed.kallel@pivasoftware.com>
* Author Anis Ellouze <anis.ellouze@pivasoftware.com>
*
*/
#ifndef _NETLINK_H__
#define _NETLINK_H__
int netlink_init(void);
int netlink_init_v6(void);
#endif

View file

@ -9,15 +9,12 @@
* *
* Copyright (C) 2012 Luka Perkov <freecwmp@lukaperkov.net> * Copyright (C) 2012 Luka Perkov <freecwmp@lukaperkov.net>
*/ */
#ifndef _FREECWMP_UBUS_H__ #ifndef _FREECWMP_UBUS_H__
#define _FREECWMP_UBUS_H__ #define _FREECWMP_UBUS_H__
#include <libubus.h>
/*
#include <json-c/json.h>
#include <libubox/blobmsg_json.h>
#include "common.h" #include <libubus.h>
*/
#include "common.h" #include "common.h"
#define ARRAY_MAX 8 #define ARRAY_MAX 8

View file

@ -16,6 +16,19 @@
} \ } \
} while (0) } while (0)
#define CWMP_RESPONSE_MESSAGE \
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" \
"<soap_env:Envelope " \
"xmlns:soap_env=\"http://schemas.xmlsoap.org/soap/envelope/\" " \
"xmlns:soap_enc=\"http://schemas.xmlsoap.org/soap/encoding/\" " \
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " \
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" \
"<soap_env:Header>" \
"<cwmp:ID soap_env:mustUnderstand=\"1\"/>" \
"</soap_env:Header>" \
"<soap_env:Body/>" \
"</soap_env:Envelope>"
extern const char *cwmp_urls[]; extern const char *cwmp_urls[];
int xml_prepare_msg_out(struct session *session); int xml_prepare_msg_out(struct session *session);
int xml_prepare_lwnotification_message(char **msg_out); int xml_prepare_lwnotification_message(char **msg_out);

168
kcwmp.c
View file

@ -1,168 +0,0 @@
/*
* Copyright (C) 2019 iopsys Software Solutions AB. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <net/sock.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>
#include <linux/mutex.h>
#include <linux/wait.h>
#include <stdarg.h>
#include <linux/slab.h>
#include "cwmp_kernel.h"
typedef struct kernel_cwmp_input {
char **argv;
int argc;
int handler;
struct mutex mutex;
wait_queue_head_t thresholdq;
} KERNEL_CWMP_INPUT;
static struct sock *nl_sk = NULL;
static struct kernel_cwmp_input kernel_cwmp_input;
MODULE_LICENSE("IOPSYS");
static void kernel_api_cwmp_value_change_listener(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
int pid;
char *msg;
char *recv;
int i;
nlh = (struct nlmsghdr *)skb->data;
recv = (char *)nlmsg_data(nlh);
if (strcmp(recv, NETLINK_CWMP_ID) != 0) {
return;
}
pid = nlh->nlmsg_pid; /*pid of sending process */
while (kernel_cwmp_input.argc == 0) {
if (wait_event_interruptible(kernel_cwmp_input.thresholdq, kernel_cwmp_input.handler)) {
return;
}
}
kernel_cwmp_input.handler = 0;
mutex_lock(&(kernel_cwmp_input.mutex));
for (i = 0; i <= kernel_cwmp_input.argc; i++) {
struct sk_buff *skb_out;
int msg_size, res;
if (i < kernel_cwmp_input.argc) {
msg = kernel_cwmp_input.argv[i];
} else {
msg = NETLINK_END_DATA;
}
msg_size = strlen(msg);
skb_out = nlmsg_new(msg_size, 0);
if (!skb_out) {
printk(KERN_ERR "Failed to allocate new skb\n");
return;
}
nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0);
NETLINK_CB(skb_out).dst_group = 0; /* not in mcast group */
strncpy(nlmsg_data(nlh), msg, msg_size);
res = nlmsg_unicast(nl_sk, skb_out, pid);
if (i < kernel_cwmp_input.argc) {
kfree(kernel_cwmp_input.argv[i]);
}
}
if (kernel_cwmp_input.argv != NULL) {
kfree(kernel_cwmp_input.argv);
kernel_cwmp_input.argv = NULL;
}
kernel_cwmp_input.argc = 0;
mutex_unlock(&(kernel_cwmp_input.mutex));
}
static int /*__init*/ kernel_api_cwmp_value_change_init(void)
{
printk(KERN_INFO "Entering kernel cwmp module: %s\n", __FUNCTION__);
memset(&kernel_cwmp_input, 0, sizeof(struct kernel_cwmp_input));
init_waitqueue_head(&kernel_cwmp_input.thresholdq);
mutex_init(&kernel_cwmp_input.mutex);
nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, 0, kernel_api_cwmp_value_change_listener, NULL, THIS_MODULE);
if (!nl_sk) {
printk(KERN_ALERT "Error creating socket.\n");
return -10;
}
return 0;
}
static void /*__exit*/ kernel_api_cwmp_value_change_exit(void)
{
printk(KERN_INFO "Exiting kernel cwmp module: %s\n", __FUNCTION__);
netlink_kernel_release(nl_sk);
}
int kernel_api_cwmp_value_change_call(int count, ...)
{
int i;
va_list args;
char *s;
if (kernel_cwmp_input.argc > 0) {
kernel_cwmp_input.handler = 1;
wake_up_interruptible(&(kernel_cwmp_input.thresholdq));
return 1;
}
mutex_lock(&(kernel_cwmp_input.mutex));
kernel_cwmp_input.argv = kmalloc(count * sizeof(char *), GFP_KERNEL);
if (kernel_cwmp_input.argv == NULL) {
goto kernel_api_cwmp_error;
}
va_start(args, count);
for (i = 0; i < count; i++) {
s = (char *)va_arg(args, char *);
if (s == NULL) {
s = NETLINK_NULL;
}
kernel_cwmp_input.argv[i] = kmalloc(strlen(s), GFP_KERNEL);
if (kernel_cwmp_input.argv[i] == NULL) {
goto kernel_api_cwmp_error;
}
strncpy(kernel_cwmp_input.argv[i], s, sizeof(kernel_cwmp_input.argv[i]));
kernel_cwmp_input.argc++;
}
va_end(args);
mutex_unlock(&(kernel_cwmp_input.mutex));
kernel_cwmp_input.handler = 1;
wake_up_interruptible(&(kernel_cwmp_input.thresholdq));
return 1;
kernel_api_cwmp_error:
if (kernel_cwmp_input.argv != NULL) {
for (i = 0; i < kernel_cwmp_input.argc; i++) {
if (kernel_cwmp_input.argv[i] != NULL) {
kfree(kernel_cwmp_input.argv[i]);
}
}
kfree(kernel_cwmp_input.argv);
kernel_cwmp_input.argv = NULL;
}
kernel_cwmp_input.argc = 0;
mutex_unlock(&(kernel_cwmp_input.mutex));
return 1;
}
EXPORT_SYMBOL(kernel_api_cwmp_value_change_call);
module_init(kernel_api_cwmp_value_change_init);
module_exit(kernel_api_cwmp_value_change_exit);

2
log.c
View file

@ -4,7 +4,7 @@
* the Free Software Foundation, either version 2 of the License, or * the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Copyright (C) 2013-2021 iopsys Software Solutions AB * Copyright (C) 2013-2022 iopsys Software Solutions AB
* Author Mohamed Kallel <mohamed.kallel@pivasoftware.com> * Author Mohamed Kallel <mohamed.kallel@pivasoftware.com>
* Author Ahmed Zribi <ahmed.zribi@pivasoftware.com> * Author Ahmed Zribi <ahmed.zribi@pivasoftware.com>
* *

252
md5.c
View file

@ -1,252 +0,0 @@
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
#include <string.h>
#include "md5.h"
#if __BYTE_ORDER == __BIG_ENDIAN
#define HIGHFIRST
#endif
#ifndef HIGHFIRST
#define byteReverse(buf, len) /* Nothing */
#else
/*
* Note: this code is harmless on little-endian machines.
*/
static void byteReverse(unsigned char *buf, unsigned longs)
{
do {
uint32_t t;
t = (uint32_t)((unsigned)buf[3] << 8 | buf[2]) << 16 | ((unsigned)buf[1] << 8 | buf[0]);
*(uint32_t *)buf = t;
buf += 4;
} while (--longs);
}
#endif
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
static void md5_transform(uint32_t buf[4], const uint32_t in[16])
{
uint32_t a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void md5_init(struct MD5Context *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void md5_update(struct MD5Context *ctx, const void *data, unsigned len)
{
const unsigned char *buf = data;
uint32_t t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((uint32_t)len << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
unsigned char *p = (unsigned char *)ctx->in + t;
t = 64 - t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
byteReverse(ctx->in, 16);
md5_transform(ctx->buf, (uint32_t *)ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
md5_transform(ctx->buf, (uint32_t *)ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void md5_final(unsigned char digest[16], struct MD5Context *ctx)
{
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
md5_transform(ctx->buf, (uint32_t *)ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
byteReverse(ctx->in, 14);
/* Append length in bits and transform */
((uint32_t *)ctx->in)[14] = ctx->bits[0];
((uint32_t *)ctx->in)[15] = ctx->bits[1];
md5_transform(ctx->buf, (uint32_t *)ctx->in);
byteReverse((unsigned char *)ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(struct MD5Context)); /* In case it's sensitive */
}
/* end of md5.c */

279
netlink.c
View file

@ -1,279 +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 <mohamed.kallel@pivasoftware.com>
* Author Ahmed Zribi <ahmed.zribi@pivasoftware.com>
* Copyright (C) 2011-2012 Luka Perkov <freecwmp@lukaperkov.net>
*
*/
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <linux/rtnetlink.h>
#include <linux/netlink.h>
#include <stddef.h>
#include <libubox/uloop.h>
#include <string.h>
#include <stdlib.h>
#include "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[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;
}

View file

@ -18,9 +18,7 @@
#include "cwmp_du_state.h" #include "cwmp_du_state.h"
#include "log.h" #include "log.h"
#include "event.h" #include "event.h"
#include "cwmp_time.h"
#include "datamodel_interface.h" #include "datamodel_interface.h"
#include "messages.h"
#include "event.h" #include "event.h"
#include "xml.h" #include "xml.h"
#include "backupSession.h" #include "backupSession.h"
@ -33,6 +31,33 @@
// to start just before the time. This delay is to compensate the time lapsed during the message enqueue and response // 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" #define DM_CONN_REQ_URL "Device.ManagementServer.ConnectionRequestURL"
#define CWMP_INFORM_MESSAGE \
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" \
"<soap_env:Envelope " \
"xmlns:soap_env=\"http://schemas.xmlsoap.org/soap/envelope/\" " \
"xmlns:soap_enc=\"http://schemas.xmlsoap.org/soap/encoding/\" " \
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " \
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" >" \
"<soap_env:Header>" \
"<cwmp:ID soap_env:mustUnderstand=\"1\"/>" \
"</soap_env:Header>" \
"<soap_env:Body>" \
"<cwmp:Inform>" \
"<DeviceId>" \
"<Manufacturer/>" \
"<OUI/>" \
"<ProductClass/>" \
"<SerialNumber/>" \
"</DeviceId>" \
"<Event soap_enc:arrayType=\"cwmp:EventStruct[0]\" />" \
"<MaxEnvelopes>1</MaxEnvelopes>" \
"<CurrentTime/>" \
"<RetryCount/>" \
"<ParameterList soap_enc:arrayType=\"cwmp:ParameterValueStruct[0]\" />" \
"</cwmp:Inform>" \
"</soap_env:Body>" \
"</soap_env:Envelope>"
struct cwmp_namespaces ns; 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 }, 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_SET_PARAMETER_VALUES] = { "SetParameterValues", cwmp_handle_rpc_cpe_set_parameter_values, AMD_1 },
@ -64,7 +89,13 @@ char *boot_inform_parameters[MAX_NBRE_CUSTOM_INFORM] = { 0 };
int nbre_custom_inform = 0; int nbre_custom_inform = 0;
int nbre_boot_inform = 0; int nbre_boot_inform = 0;
char *forced_inform_parameters[] = { 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" "Device.RootDataModelVersion",
"Device.DeviceInfo.HardwareVersion",
"Device.DeviceInfo.SoftwareVersion",
"Device.DeviceInfo.ProvisioningCode",
"Device.ManagementServer.ParameterKey",
"Device.ManagementServer.AliasBasedAddressing",
DM_CONN_REQ_URL,
}; };
int xml_handle_message(struct session *session) int xml_handle_message(struct session *session)
@ -307,7 +338,7 @@ int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *sessi
if (!b) if (!b)
goto error; goto error;
b = mxmlNewOpaque(b, mix_get_time()); b = mxmlNewOpaque(b, get_time(time(NULL)));
if (!b) if (!b)
goto error; goto error;
@ -603,7 +634,7 @@ int cwmp_rpc_acs_prepare_transfer_complete(struct cwmp *cwmp, struct session *se
if (!n) if (!n)
goto error; goto error;
n = mxmlNewOpaque(n, mix_get_time()); n = mxmlNewOpaque(n, get_time(time(NULL)));
if (!n) if (!n)
goto error; goto error;

View file

@ -19,7 +19,6 @@
#include "backupSession.h" #include "backupSession.h"
#include "xml.h" #include "xml.h"
#include "config.h" #include "config.h"
#include "cwmp_time.h"
#include "event.h" #include "event.h"
static struct cwmp cwmp_main_test = { 0 }; static struct cwmp cwmp_main_test = { 0 };
@ -220,8 +219,8 @@ static void cwmp_backup_session_unit_test(void **state)
struct transfer_complete *p; struct transfer_complete *p;
p = icwmp_calloc(1, sizeof(struct transfer_complete)); p = icwmp_calloc(1, sizeof(struct transfer_complete));
p->command_key = icwmp_strdup("transfer_complete_key"); p->command_key = icwmp_strdup("transfer_complete_key");
p->start_time = icwmp_strdup(mix_get_time()); p->start_time = icwmp_strdup(get_time(time(NULL)));
p->complete_time = icwmp_strdup(mix_get_time()); p->complete_time = icwmp_strdup(get_time(time(NULL)));
p->old_software_version = icwmp_strdup("iopsys_img_old"); p->old_software_version = icwmp_strdup("iopsys_img_old");
p->type = TYPE_DOWNLOAD; p->type = TYPE_DOWNLOAD;
p->fault_code = FAULT_CPE_NO_FAULT; p->fault_code = FAULT_CPE_NO_FAULT;

View file

@ -21,7 +21,6 @@
#include "backupSession.h" #include "backupSession.h"
#include "xml.h" #include "xml.h"
#include "config.h" #include "config.h"
#include "cwmp_time.h"
#include "event.h" #include "event.h"
#include "cwmp_uci.h" #include "cwmp_uci.h"
#include "cwmp_cli.h" #include "cwmp_cli.h"

209
ubus.c
View file

@ -15,18 +15,20 @@
#include <pthread.h> #include <pthread.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <libubox/blobmsg_json.h> #include <libubox/blobmsg_json.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <linux/rtnetlink.h>
#include "ubus.h" #include "ubus.h"
#include "session.h" #include "session.h"
#include "log.h" #include "log.h"
#include "sched_inform.h" #include "sched_inform.h"
#include "http.h" #include "cwmp_http.h"
#include "download.h" #include "download.h"
#include "upload.h" #include "upload.h"
#include "cwmp_du_state.h" #include "cwmp_du_state.h"
#include "netlink.h" #include "cwmp_uci.h"
#include "event.h" #include "event.h"
#include "cwmp_time.h"
static struct ubus_context *ctx = NULL; static struct ubus_context *ctx = NULL;
@ -52,7 +54,7 @@ static int cwmp_handle_command(struct ubus_context *ctx, struct ubus_object *obj
struct blob_attr *tb[__COMMAND_MAX]; struct blob_attr *tb[__COMMAND_MAX];
struct blob_buf blob_command; struct blob_buf blob_command;
blobmsg_parse(command_policy, ARRAYSIZEOF(command_policy), tb, blob_data(msg), blob_len(msg)); blobmsg_parse(command_policy, ARRAY_SIZE(command_policy), tb, blob_data(msg), blob_len(msg));
if (!tb[COMMAND_NAME]) if (!tb[COMMAND_NAME])
return UBUS_STATUS_INVALID_ARGUMENT; return UBUS_STATUS_INVALID_ARGUMENT;
@ -101,7 +103,7 @@ static int cwmp_handle_command(struct ubus_context *ctx, struct ubus_object *obj
thread_end = true; thread_end = true;
if (cwmp_main.session_status.last_status == SESSION_RUNNING) if (cwmp_main.session_status.last_status == SESSION_RUNNING)
http_set_timeout(); cwmp_http_set_timeout();
pthread_cond_signal(&(cwmp_main.threshold_session_send)); pthread_cond_signal(&(cwmp_main.threshold_session_send));
pthread_cond_signal(&(cwmp_main.threshold_periodic)); pthread_cond_signal(&(cwmp_main.threshold_periodic));
@ -138,17 +140,21 @@ static int cwmp_handle_command(struct ubus_context *ctx, struct ubus_object *obj
static inline time_t get_session_status_next_time() static inline time_t get_session_status_next_time()
{ {
time_t ntime = 0; time_t ntime = 0;
if (list_schedule_inform.next != &(list_schedule_inform)) { if (list_schedule_inform.next != &(list_schedule_inform)) {
struct schedule_inform *schedule_inform; struct schedule_inform *schedule_inform;
schedule_inform = list_entry(list_schedule_inform.next, struct schedule_inform, list); schedule_inform = list_entry(list_schedule_inform.next, struct schedule_inform, list);
ntime = schedule_inform->scheduled_time; ntime = schedule_inform->scheduled_time;
} }
if (!ntime || (cwmp_main.session_status.next_retry && ntime > cwmp_main.session_status.next_retry)) { if (!ntime || (cwmp_main.session_status.next_retry && ntime > cwmp_main.session_status.next_retry)) {
ntime = cwmp_main.session_status.next_retry; ntime = cwmp_main.session_status.next_retry;
} }
if (!ntime || (cwmp_main.session_status.next_periodic && ntime > cwmp_main.session_status.next_periodic)) { if (!ntime || (cwmp_main.session_status.next_periodic && ntime > cwmp_main.session_status.next_periodic)) {
ntime = cwmp_main.session_status.next_periodic; ntime = cwmp_main.session_status.next_periodic;
} }
return ntime; return ntime;
} }
@ -163,20 +169,20 @@ static int cwmp_handle_status(struct ubus_context *ctx, struct ubus_object *obj
c = blobmsg_open_table(&blob_status, "cwmp"); c = blobmsg_open_table(&blob_status, "cwmp");
blobmsg_add_string(&blob_status, "status", "up"); blobmsg_add_string(&blob_status, "status", "up");
blobmsg_add_string(&blob_status, "start_time", mix_get_time_of(cwmp_main.start_time)); blobmsg_add_string(&blob_status, "start_time", get_time(cwmp_main.start_time));
blobmsg_add_string(&blob_status, "acs_url", cwmp_main.conf.acsurl); blobmsg_add_string(&blob_status, "acs_url", cwmp_main.conf.acsurl);
blobmsg_close_table(&blob_status, c); blobmsg_close_table(&blob_status, c);
c = blobmsg_open_table(&blob_status, "last_session"); c = blobmsg_open_table(&blob_status, "last_session");
blobmsg_add_string(&blob_status, "status", cwmp_main.session_status.last_start_time ? arr_session_status[cwmp_main.session_status.last_status] : "N/A"); blobmsg_add_string(&blob_status, "status", cwmp_main.session_status.last_start_time ? arr_session_status[cwmp_main.session_status.last_status] : "N/A");
blobmsg_add_string(&blob_status, "start_time", cwmp_main.session_status.last_start_time ? mix_get_time_of(cwmp_main.session_status.last_start_time) : "N/A"); blobmsg_add_string(&blob_status, "start_time", cwmp_main.session_status.last_start_time ? get_time(cwmp_main.session_status.last_start_time) : "N/A");
blobmsg_add_string(&blob_status, "end_time", cwmp_main.session_status.last_end_time ? mix_get_time_of(cwmp_main.session_status.last_end_time) : "N/A"); blobmsg_add_string(&blob_status, "end_time", cwmp_main.session_status.last_end_time ? get_time(cwmp_main.session_status.last_end_time) : "N/A");
blobmsg_close_table(&blob_status, c); blobmsg_close_table(&blob_status, c);
c = blobmsg_open_table(&blob_status, "next_session"); c = blobmsg_open_table(&blob_status, "next_session");
blobmsg_add_string(&blob_status, "status", arr_session_status[SESSION_WAITING]); blobmsg_add_string(&blob_status, "status", arr_session_status[SESSION_WAITING]);
ntime = get_session_status_next_time(); ntime = get_session_status_next_time();
blobmsg_add_string(&blob_status, "start_time", ntime ? mix_get_time_of(ntime) : "N/A"); blobmsg_add_string(&blob_status, "start_time", ntime ? get_time(ntime) : "N/A");
blobmsg_add_string(&blob_status, "end_time", "N/A"); blobmsg_add_string(&blob_status, "end_time", "N/A");
blobmsg_close_table(&blob_status, c); blobmsg_close_table(&blob_status, c);
@ -214,7 +220,7 @@ static int cwmp_handle_inform(struct ubus_context *ctx, struct ubus_object *obj
memset(&blob_inform, 0, sizeof(struct blob_buf)); memset(&blob_inform, 0, sizeof(struct blob_buf));
blob_buf_init(&blob_inform, 0); blob_buf_init(&blob_inform, 0);
blobmsg_parse(inform_policy, ARRAYSIZEOF(inform_policy), tb, blob_data(msg), blob_len(msg)); blobmsg_parse(inform_policy, ARRAY_SIZE(inform_policy), tb, blob_data(msg), blob_len(msg));
if (tb[INFORM_GET_RPC_METHODS]) { if (tb[INFORM_GET_RPC_METHODS]) {
grm = blobmsg_data(tb[INFORM_GET_RPC_METHODS]); grm = blobmsg_data(tb[INFORM_GET_RPC_METHODS]);
@ -274,22 +280,199 @@ static struct ubus_object main_object = {
.name = "tr069", .name = "tr069",
.type = &main_object_type, .type = &main_object_type,
.methods = freecwmp_methods, .methods = freecwmp_methods,
.n_methods = ARRAYSIZEOF(freecwmp_methods), .n_methods = ARRAY_SIZE(freecwmp_methods),
}; };
static int check_interfaces(char *itf1, char *itf2)
{
char itf1_buf[64] = {0};
char itf2_buf[64] = {0};
char *dot = NULL;
if (itf1[0] == '\0' || itf2[0] == '\0')
return -1;
CWMP_STRNCPY(itf1_buf, itf1, sizeof(itf1_buf));
CWMP_STRNCPY(itf2_buf, itf2, sizeof(itf2_buf));
dot = strchr(itf1_buf, '.');
if (dot)
*dot = 0;
dot = strchr(itf2_buf, '.');
if (dot)
*dot = 0;
return strcmp(itf1_buf, itf2_buf);
}
static void cwmp_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 (check_interfaces(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;
}
if_indextoname(ifa->ifa_index, if_name);
if (check_interfaces(cwmp_main.conf.interface, if_name)) {
rth = RTA_NEXT(rth, rtl);
continue;
}
inet_ntop(AF_INET6, RTA_DATA(rth), pradd_v6, sizeof(pradd_v6));
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)
cwmp_netlink_interface(nlh);
msg_size -= NLMSG_ALIGN(len);
nlh = (struct nlmsghdr *)((char *)nlh + NLMSG_ALIGN(len));
}
}
static struct uloop_fd netlink_event[2] = {{.cb = netlink_new_msg }, {.cb = netlink_new_msg }};
static int netlink_init(bool is_ipv6)
{
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 = is_ipv6 ? RTMGRP_IPV6_IFADDR : 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[is_ipv6 ? 1 : 0].fd = sock[0];
uloop_fd_add(&netlink_event[is_ipv6 ? 1 : 0], 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 = is_ipv6 ? AF_INET6 : 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;
}
int cwmp_ubus_init(struct cwmp *cwmp) int cwmp_ubus_init(struct cwmp *cwmp)
{ {
uloop_init(); uloop_init();
if (netlink_init()) { if (netlink_init(false)) {
CWMP_LOG(ERROR, "netlink initialization failed"); CWMP_LOG(ERROR, "netlink initialization failed");
} }
if (cwmp->conf.ipv6_enable) { if (cwmp->conf.ipv6_enable) {
if (netlink_init_v6()) { if (netlink_init(true)) {
CWMP_LOG(ERROR, "netlink initialization failed"); CWMP_LOG(ERROR, "netlink initialization failed");
} }
} }
ctx = ubus_connect(cwmp->conf.ubus_socket); ctx = ubus_connect(cwmp->conf.ubus_socket);
if (!ctx) if (!ctx)
return -1; return -1;

View file

@ -14,7 +14,6 @@
#include "upload.h" #include "upload.h"
#include "download.h" #include "download.h"
#include "cwmp_time.h"
#include "datamodel_interface.h" #include "datamodel_interface.h"
#include "log.h" #include "log.h"
#include "backupSession.h" #include "backupSession.h"
@ -115,7 +114,7 @@ int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptrans
char *upload_startTime; char *upload_startTime;
struct transfer_complete *p; struct transfer_complete *p;
char *name = NULL; char *name = NULL;
upload_startTime = mix_get_time(); upload_startTime = get_time(time(NULL));
char file_path[128] = {'\0'}; char file_path[128] = {'\0'};
bkp_session_delete_upload(pupload); bkp_session_delete_upload(pupload);
bkp_session_save(); bkp_session_save();
@ -172,7 +171,7 @@ end_upload:
p->command_key = pupload->command_key ? strdup(pupload->command_key) : strdup(""); p->command_key = pupload->command_key ? strdup(pupload->command_key) : strdup("");
p->start_time = strdup(upload_startTime); p->start_time = strdup(upload_startTime);
p->complete_time = strdup(mix_get_time()); p->complete_time = strdup(get_time(time(NULL)));
p->type = TYPE_UPLOAD; p->type = TYPE_UPLOAD;
if (error != FAULT_CPE_NO_FAULT) { if (error != FAULT_CPE_NO_FAULT) {
p->fault_code = error; p->fault_code = error;
@ -213,7 +212,7 @@ void *thread_cwmp_rpc_cpe_upload(void *v)
error = FAULT_CPE_DOWNLOAD_FAILURE; error = FAULT_CPE_DOWNLOAD_FAILURE;
ptransfer_complete->command_key = strdup(pupload->command_key); ptransfer_complete->command_key = strdup(pupload->command_key);
ptransfer_complete->start_time = strdup(mix_get_time()); ptransfer_complete->start_time = strdup(get_time(time(NULL)));
ptransfer_complete->complete_time = strdup(ptransfer_complete->start_time); ptransfer_complete->complete_time = strdup(ptransfer_complete->start_time);
ptransfer_complete->fault_code = error; ptransfer_complete->fault_code = error;
ptransfer_complete->type = TYPE_UPLOAD; ptransfer_complete->type = TYPE_UPLOAD;

29
xml.c
View file

@ -13,8 +13,7 @@
#include "xml.h" #include "xml.h"
#include "log.h" #include "log.h"
#include "notifications.h" #include "notifications.h"
#include "messages.h" #include "cwmp_http.h"
#include "http.h"
#include "cwmp_zlib.h" #include "cwmp_zlib.h"
static const char *soap_env_url = "http://schemas.xmlsoap.org/soap/envelope/"; static const char *soap_env_url = "http://schemas.xmlsoap.org/soap/envelope/";
@ -22,7 +21,29 @@ 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 *xsd_url = "http://www.w3.org/2001/XMLSchema";
static const char *xsi_url = "http://www.w3.org/2001/XMLSchema-instance"; 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", NULL }; 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",
NULL };
#define CWMP_LWNOTIFICATION_MESSAGE \
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" \
"<Notification " \
"xmlns=\"urn:broadband-forum-org:cwmp:lwnotif-1-0\" " \
"xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" " \
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \
"xsi:schemaLocation=\"urn:broadband-forum-org:cwmp:lwnotif-1-0 " \
"http://www.broadband-forum.org/cwmp/cwmp-UDPLightweightNotification-1-0.xsd\">" \
"<TS/>" \
"<UN/>" \
"<CN/>" \
"<OUI/>" \
"<ProductClass/>" \
"<SerialNumber/>" \
"</Notification>"
mxml_node_t * /* O - Element node or NULL */ mxml_node_t * /* O - Element node or NULL */
mxmlFindElementOpaque(mxml_node_t *node, /* I - Current node */ mxmlFindElementOpaque(mxml_node_t *node, /* I - Current node */
mxml_node_t *top, /* I - Top node */ mxml_node_t *top, /* I - Top node */
@ -153,7 +174,7 @@ int xml_send_message(struct cwmp *cwmp, struct session *session, struct rpc *rpc
} }
while (1) { while (1) {
f = 0; f = 0;
if (http_send_message(cwmp, msg_out, msg_out_len, &msg_in)) { if (cwmp_http_send_message(cwmp, msg_out, msg_out_len, &msg_in)) {
goto error; goto error;
} }
if (msg_in) { if (msg_in) {