mirror of
https://dev.iopsys.eu/bbf/icwmp.git
synced 2025-12-10 07:44:41 +01:00
icwmp: code cleanup
This commit is contained in:
parent
f7c42eaba6
commit
bd7f6deb93
33 changed files with 770 additions and 1449 deletions
|
|
@ -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 \
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
88
common.c
88
common.c
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
18
cwmp.c
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
|
||||||
if (icwmp_asprintf(&http_c.url, "%s", cwmp->conf.acsurl) == -1) {
|
|
||||||
FREE(dhcp_dis);
|
|
||||||
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);
|
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);
|
||||||
|
}
|
||||||
39
cwmp_time.c
39
cwmp_time.c
|
|
@ -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;
|
|
||||||
}
|
|
||||||
251
cwmp_uci.c
251
cwmp_uci.c
|
|
@ -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;
|
||||||
|
|
|
||||||
163
digestauth.c
163
digestauth.c
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
90
inc/common.h
90
inc/common.h
|
|
@ -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
40
inc/cwmp_http.h
Normal 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__ */
|
||||||
|
|
@ -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_ */
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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_ */
|
||||||
|
|
|
||||||
34
inc/http.h
34
inc/http.h
|
|
@ -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
|
|
||||||
50
inc/log.h
50
inc/log.h
|
|
@ -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_ */
|
||||||
|
|
|
||||||
41
inc/md5.h
41
inc/md5.h
|
|
@ -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 */
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
13
inc/xml.h
13
inc/xml.h
|
|
@ -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
168
kcwmp.c
|
|
@ -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
2
log.c
|
|
@ -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
252
md5.c
|
|
@ -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
279
netlink.c
|
|
@ -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;
|
|
||||||
}
|
|
||||||
41
rpc_soap.c
41
rpc_soap.c
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
209
ubus.c
|
|
@ -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;
|
||||||
|
|
|
||||||
7
upload.c
7
upload.c
|
|
@ -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
29
xml.c
|
|
@ -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) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue