From bd7f6deb93168b1e91c27da4c40ea3b6d27b522a Mon Sep 17 00:00:00 2001 From: Amin Ben Ramdhane Date: Wed, 27 Apr 2022 11:39:30 +0100 Subject: [PATCH] icwmp: code cleanup --- Makefile.am | 5 +- backupSession.c | 2 +- common.c | 88 +++--- configure.ac | 3 - cwmp.c | 18 +- cwmp_du_state.c | 15 +- http.c => cwmp_http.c | 202 +++++++------- cwmp_time.c | 39 --- cwmp_uci.c | 251 ++++++++--------- digestauth.c | 163 ++++++----- download.c | 9 +- inc/common.h | 90 +++--- inc/cwmp_http.h | 40 +++ inc/cwmp_time.h | 18 -- inc/cwmp_uci.h | 17 +- inc/digestauth.h | 30 +- inc/http.h | 34 --- inc/log.h | 50 +--- inc/md5.h | 41 --- inc/messages.h | 70 ----- inc/netlink.h | 19 -- inc/ubus.h | 9 +- inc/xml.h | 13 + kcwmp.c | 168 ----------- log.c | 2 +- md5.c | 252 ----------------- netlink.c | 279 ------------------- rpc_soap.c | 41 ++- test/cmocka/icwmp_backup_session_unit_test.c | 5 +- test/cmocka/icwmp_cli_unit_test.c | 1 - ubus.c | 209 +++++++++++++- upload.c | 7 +- xml.c | 29 +- 33 files changed, 770 insertions(+), 1449 deletions(-) rename http.c => cwmp_http.c (75%) delete mode 100644 cwmp_time.c create mode 100644 inc/cwmp_http.h delete mode 100644 inc/cwmp_time.h delete mode 100644 inc/http.h delete mode 100644 inc/md5.h delete mode 100644 inc/messages.h delete mode 100755 inc/netlink.h delete mode 100644 kcwmp.c delete mode 100644 md5.c delete mode 100644 netlink.c diff --git a/Makefile.am b/Makefile.am index aebd334..e271d24 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,17 +6,14 @@ bin_PROGRAMS = icwmpd icwmpd_SOURCES = \ ./common.c \ - ./cwmp_time.c \ ./log.c \ ./cwmp_uci.c \ ./config.c \ ./session.c \ ./backupSession.c \ - ./md5.c \ ./digestauth.c \ ./event.c \ - ./http.c \ - ./netlink.c \ + ./cwmp_http.c \ ./ubus.c \ ./datamodel_interface.c \ ./cwmp_cli.c \ diff --git a/backupSession.c b/backupSession.c index 64c3cd2..670473e 100644 --- a/backupSession.c +++ b/backupSession.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) { d = c; 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++; } c = mxmlWalkNext(c, b, MXML_NO_DESCEND); diff --git a/common.c b/common.c index 6fc899c..e026e46 100755 --- a/common.c +++ b/common.c @@ -22,7 +22,6 @@ #include "ubus.h" #include "log.h" - #ifndef CWMP_REVISION #define CWMP_REVISION "8.2.10" #endif @@ -43,64 +42,49 @@ struct cwmp_mem { char mem[0]; }; -char *Obj_Excluded[] = { +static char *Obj_Excluded[] = { "Device.DeviceInfo.ProcessStatus.Process.", "Device.Hosts.Host." }; struct option cwmp_long_options[] = { - { "boot-event", no_argument, NULL, 'b' }, { "get-rpc-methods", no_argument, NULL, 'g' }, - { "command-input", no_argument, NULL, 'c' }, { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'v' }, { NULL, 0, NULL, 0 } + { "boot-event", no_argument, NULL, 'b' }, + { "get-rpc-methods", no_argument, NULL, 'g' }, + { "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[] = { [FAULT_CPE_METHOD_NOT_SUPPORTED] = { "9000", FAULT_9000, FAULT_CPE_TYPE_SERVER, "Method not supported" }, - [FAULT_CPE_REQUEST_DENIED] = { "9001", FAULT_9001, FAULT_CPE_TYPE_SERVER, - "Request denied (no reason specified)" }, + [FAULT_CPE_REQUEST_DENIED] = { "9001", FAULT_9001, FAULT_CPE_TYPE_SERVER, "Request denied (no reason specified)" }, [FAULT_CPE_INTERNAL_ERROR] = { "9002", FAULT_9002, FAULT_CPE_TYPE_SERVER, "Internal error" }, [FAULT_CPE_INVALID_ARGUMENTS] = { "9003", FAULT_9003, FAULT_CPE_TYPE_CLIENT, "Invalid arguments" }, [FAULT_CPE_RESOURCES_EXCEEDED] = { "9004", FAULT_9004, FAULT_CPE_TYPE_SERVER, "Resources exceeded" }, [FAULT_CPE_INVALID_PARAMETER_NAME] = { "9005", FAULT_9005, FAULT_CPE_TYPE_CLIENT, "Invalid parameter name" }, [FAULT_CPE_INVALID_PARAMETER_TYPE] = { "9006", FAULT_9006, FAULT_CPE_TYPE_CLIENT, "Invalid parameter type" }, [FAULT_CPE_INVALID_PARAMETER_VALUE] = { "9007", FAULT_9007, FAULT_CPE_TYPE_CLIENT, "Invalid parameter value" }, - [FAULT_CPE_NON_WRITABLE_PARAMETER] = { "9008", FAULT_9008, FAULT_CPE_TYPE_CLIENT, - "Attempt to set a non-writable parameter" }, - [FAULT_CPE_NOTIFICATION_REJECTED] = { "9009", FAULT_9009, FAULT_CPE_TYPE_SERVER, - "Notification request rejected" }, + [FAULT_CPE_NON_WRITABLE_PARAMETER] = { "9008", FAULT_9008, FAULT_CPE_TYPE_CLIENT, "Attempt to set a non-writable parameter" }, + [FAULT_CPE_NOTIFICATION_REJECTED] = { "9009", FAULT_9009, FAULT_CPE_TYPE_SERVER, "Notification request rejected" }, [FAULT_CPE_DOWNLOAD_FAILURE] = { "9010", FAULT_9010, FAULT_CPE_TYPE_SERVER, "Download failure" }, [FAULT_CPE_UPLOAD_FAILURE] = { "9011", FAULT_9011, FAULT_CPE_TYPE_SERVER, "Upload failure" }, - [FAULT_CPE_FILE_TRANSFER_AUTHENTICATION_FAILURE] = { "9012", FAULT_9012, FAULT_CPE_TYPE_SERVER, - "File transfer server authentication failure" }, - [FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL] = { "9013", FAULT_9013, FAULT_CPE_TYPE_SERVER, - "Unsupported protocol for file transfer" }, - [FAULT_CPE_DOWNLOAD_FAIL_MULTICAST_GROUP] = { "9014", FAULT_9014, FAULT_CPE_TYPE_SERVER, - "Download failure: unable to join multicast group" }, - [FAULT_CPE_DOWNLOAD_FAIL_CONTACT_SERVER] = { "9015", FAULT_9015, FAULT_CPE_TYPE_SERVER, - "Download failure: unable to contact file server" }, - [FAULT_CPE_DOWNLOAD_FAIL_ACCESS_FILE] = { "9016", FAULT_9016, FAULT_CPE_TYPE_SERVER, - "Download failure: unable to access file" }, - [FAULT_CPE_DOWNLOAD_FAIL_COMPLETE_DOWNLOAD] = { "9017", FAULT_9017, FAULT_CPE_TYPE_SERVER, - "Download failure: unable to complete download" }, - [FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED] = { "9018", FAULT_9018, FAULT_CPE_TYPE_SERVER, - "Download failure: file corrupted" }, - [FAULT_CPE_DOWNLOAD_FAIL_FILE_AUTHENTICATION] = { "9019", FAULT_9019, FAULT_CPE_TYPE_SERVER, - "Download failure: file authentication failure" }, - [FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW] = { "9020", FAULT_9020, FAULT_CPE_TYPE_SERVER, - "Download failure: unable to complete download" }, - [FAULT_CPE_DUPLICATE_DEPLOYMENT_UNIT] = { "9026", FAULT_9026, FAULT_CPE_TYPE_SERVER, - "Duplicate deployment unit" }, - [FAULT_CPE_SYSTEM_RESOURCES_EXCEEDED] = { "9027", FAULT_9027, FAULT_CPE_TYPE_SERVER, - "System ressources exceeded" }, + [FAULT_CPE_FILE_TRANSFER_AUTHENTICATION_FAILURE] = { "9012", FAULT_9012, FAULT_CPE_TYPE_SERVER, "File transfer server authentication failure" }, + [FAULT_CPE_FILE_TRANSFER_UNSUPPORTED_PROTOCOL] = { "9013", FAULT_9013, FAULT_CPE_TYPE_SERVER, "Unsupported protocol for file transfer" }, + [FAULT_CPE_DOWNLOAD_FAIL_MULTICAST_GROUP] = { "9014", FAULT_9014, FAULT_CPE_TYPE_SERVER, "Download failure: unable to join multicast group" }, + [FAULT_CPE_DOWNLOAD_FAIL_CONTACT_SERVER] = { "9015", FAULT_9015, FAULT_CPE_TYPE_SERVER, "Download failure: unable to contact file server" }, + [FAULT_CPE_DOWNLOAD_FAIL_ACCESS_FILE] = { "9016", FAULT_9016, FAULT_CPE_TYPE_SERVER, "Download failure: unable to access file" }, + [FAULT_CPE_DOWNLOAD_FAIL_COMPLETE_DOWNLOAD] = { "9017", FAULT_9017, FAULT_CPE_TYPE_SERVER, "Download failure: unable to complete download" }, + [FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED] = { "9018", FAULT_9018, FAULT_CPE_TYPE_SERVER, "Download failure: file corrupted" }, + [FAULT_CPE_DOWNLOAD_FAIL_FILE_AUTHENTICATION] = { "9019", FAULT_9019, FAULT_CPE_TYPE_SERVER, "Download failure: file authentication failure" }, + [FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW] = { "9020", FAULT_9020, FAULT_CPE_TYPE_SERVER, "Download failure: unable to complete download" }, + [FAULT_CPE_DUPLICATE_DEPLOYMENT_UNIT] = { "9026", FAULT_9026, FAULT_CPE_TYPE_SERVER, "Duplicate deployment unit" }, + [FAULT_CPE_SYSTEM_RESOURCES_EXCEEDED] = { "9027", FAULT_9027, FAULT_CPE_TYPE_SERVER, "System ressources exceeded" }, [FAULT_CPE_UNKNOWN_DEPLOYMENT_UNIT] = { "9028", FAULT_9028, FAULT_CPE_TYPE_SERVER, "Unknown deployment unit" }, - [FAULT_CPE_INVALID_DEPLOYMENT_UNIT_STATE] = { "9029", FAULT_9029, FAULT_CPE_TYPE_SERVER, - "Invalid deployment unit state" }, - [FAULT_CPE_INVALID_DOWNGRADE_REJECTED] = { "9030", FAULT_9030, FAULT_CPE_TYPE_SERVER, - "Invalid deployment unit Update: Downgrade not permitted" }, - [FAULT_CPE_INVALID_UPDATE_VERSION_UNSPECIFIED] = { "9031", FAULT_9031, FAULT_CPE_TYPE_SERVER, - "Invalid deployment unit Update: Version not specified" }, - [FAULT_CPE_INVALID_UPDATE_VERSION_EXIST] = { "9031", FAULT_9032, FAULT_CPE_TYPE_SERVER, - "Invalid deployment unit Update: Version already exist" } + [FAULT_CPE_INVALID_DEPLOYMENT_UNIT_STATE] = { "9029", FAULT_9029, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit state" }, + [FAULT_CPE_INVALID_DOWNGRADE_REJECTED] = { "9030", FAULT_9030, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit Update: Downgrade not permitted" }, + [FAULT_CPE_INVALID_UPDATE_VERSION_UNSPECIFIED] = { "9031", FAULT_9031, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit Update: Version not specified" }, + [FAULT_CPE_INVALID_UPDATE_VERSION_EXIST] = { "9031", FAULT_9032, FAULT_CPE_TYPE_SERVER, "Invalid deployment unit Update: Version already exist" } }; static void show_help(void) @@ -724,7 +708,27 @@ int get_connection_interface() 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; diff --git a/configure.ac b/configure.ac index 7eaf339..583ee0d 100644 --- a/configure.ac +++ b/configure.ac @@ -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" = "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)) AM_CONDITIONAL([LOPENSSL],[test "x$enable_libopenssl" = "xyes"]) diff --git a/cwmp.c b/cwmp.c index c94b4ee..42dd290 100644 --- a/cwmp.c +++ b/cwmp.c @@ -25,7 +25,7 @@ #include "log.h" #include "session.h" #include "diagnostic.h" -#include "http.h" +#include "cwmp_http.h" #include "rpc_soap.h" #include "config.h" #include "backupSession.h" @@ -148,7 +148,7 @@ static int cwmp_schedule_rpc(struct cwmp *cwmp, struct session *session) struct list_head *ilist; struct rpc *rpc_acs, *rpc_cpe; - if (http_client_init(cwmp) || thread_end) { + if (cwmp_http_client_init(cwmp) || thread_end) { CWMP_LOG(INFO, "Initializing http client failed"); goto retry; } @@ -175,11 +175,6 @@ static int cwmp_schedule_rpc(struct cwmp *cwmp, struct session *session) goto retry; CWMP_LOG(INFO, "Get the %sResponse message from the ACS", rpc_acs_methods[rpc_acs->type].name); - /* - * This condition is not always false. - * while the value of 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(cwmp, session, rpc_acs)) goto retry; @@ -250,7 +245,7 @@ retry: end: MXML_DELETE(session->tree_in); MXML_DELETE(session->tree_out); - http_client_exit(); + cwmp_http_client_exit(); xml_exit(); 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.next_retry = 0; - if (file_exists(fc_cookies)) - remove(fc_cookies); + cwmp_http_remove_cookies_file(); CWMP_LOG(INFO, "Start session"); 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))) { - http_server_listen(); + cwmp_http_server_listen(); return NULL; } @@ -828,7 +822,7 @@ int main(int argc, char **argv) return error; configure_var_state(cwmp); - http_server_init(); + cwmp_http_server_init(); sigemptyset(&set); sigaddset(&set, SIGINT); diff --git a/cwmp_du_state.c b/cwmp_du_state.c index e2ce415..d810cc9 100644 --- a/cwmp_du_state.c +++ b/cwmp_du_state.c @@ -16,7 +16,6 @@ #include "ubus.h" #include "log.h" #include "datamodel_interface.h" -#include "cwmp_time.h" #include "backupSession.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; 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); 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; 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); 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; 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); @@ -326,7 +325,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v) res->uuid = strdup(p->uuid); res->version = strdup(p->version); 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->fault = error; } @@ -378,7 +377,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v) res->resolved = 0; } - res->complete_time = strdup(mix_get_time()); + res->complete_time = strdup(get_time(time(NULL))); res->fault = error; break; @@ -411,7 +410,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v) get_du_version(du_ref, &package_version); res->version = strdup(package_version ? package_version : ""); 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; FREE(du_ref); break; @@ -441,7 +440,7 @@ void *thread_cwmp_rpc_cpe_change_du_state(void *v) res->du_ref = strdup(du_ref ? du_ref : ""); res->uuid = strdup(p->uuid); res->version = strdup(package_version); - res->complete_time = strdup(mix_get_time()); + res->complete_time = strdup(get_time(time(NULL))); res->fault = error; FREE(du_ref); FREE(package_name); diff --git a/http.c b/cwmp_http.c similarity index 75% rename from http.c rename to cwmp_http.c index bc5e32c..01e3f0d 100644 --- a/http.c +++ b/cwmp_http.c @@ -1,21 +1,32 @@ /* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. + * cwmp_http.c: Utility functions for http server and client * - * Copyright (C) 2013-2021 iopsys Software Solutions AB - * Author Mohamed Kallel - * Author Ahmed Zribi - * Author Omar Kallel - * Copyright (C) 2011-2012 Luka Perkov + * Copyright (C) 2022 iopsys Software Solutions AB. All rights reserved. + * + * Author: Mohamed Kallel + * Author: Ahmed Zribi + * Author: Omar Kallel + * + * 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 #include -#include #include -#include "http.h" +#include "cwmp_http.h" #include "cwmp_uci.h" #include "log.h" #include "event.h" @@ -23,55 +34,39 @@ #include "config.h" #include "digestauth.h" +#define HTTP_TIMEOUT 30 #define REALM "authenticate@cwmp" #define OPAQUE "11733b200778ce33060f31c9af70a870ba96ddd4" -static struct http_client http_c; - static CURL *curl = NULL; +static char *http_client_url = NULL; +static char *cookies_file = "/tmp/icwmp_cookies"; -char *fc_cookies = "/tmp/icwmp_cookies"; - -void http_set_timeout(void) -{ - if (curl) - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1); -} - -int http_client_init(struct cwmp *cwmp) +int cwmp_http_client_init(struct cwmp *cwmp) { char *dhcp_dis = NULL; - char *acs_var_stat = NULL; uci_get_value(UCI_DHCP_DISCOVERY_PATH, &dhcp_dis); if (dhcp_dis && cwmp->retry_count_session > 0 && strcmp(dhcp_dis, "enable") == 0) { + char *acs_var_stat = NULL; + uci_get_state_value(UCI_DHCP_ACS_URL, &acs_var_stat); - if (acs_var_stat) { - if (icwmp_asprintf(&http_c.url, "%s", acs_var_stat) == -1) { - free(acs_var_stat); - FREE(dhcp_dis); - return -1; - } - } else { - if (icwmp_asprintf(&http_c.url, "%s", cwmp->conf.acsurl) == -1) { - FREE(dhcp_dis); - return -1; - } + if (icwmp_asprintf(&http_client_url, "%s", acs_var_stat ? acs_var_stat : cwmp->conf.acsurl) == -1) { + FREE(acs_var_stat); + FREE(dhcp_dis); + return -1; } } else { - if (icwmp_asprintf(&http_c.url, "%s", cwmp->conf.acsurl) == -1) { + if (icwmp_asprintf(&http_client_url, "%s", cwmp->conf.acsurl) == -1) { FREE(dhcp_dis); return -1; } } - if (dhcp_dis) - free(dhcp_dis); + FREE(dhcp_dis); - CWMP_LOG(INFO, "ACS url: %s", http_c.url); - - /* TODO debug ssl config from freecwmp*/ + CWMP_LOG(INFO, "ACS url: %s", http_client_url); curl_global_init(CURL_GLOBAL_SSL); curl = curl_easy_init(); @@ -80,39 +75,24 @@ int http_client_init(struct cwmp *cwmp) if (cwmp->conf.ipv6_enable) { unsigned char buf[sizeof(struct in6_addr)]; - 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_NOBODY, 1); curl_easy_getinfo(curl, CURLINFO_PRIMARY_IP, &ip); curl_easy_perform(curl); + int tmp = inet_pton(AF_INET, ip, buf); cwmp_uci_set_value("cwmp", "acs", "ip_version", (tmp == 1) ? "4" : "6"); cwmp_commit_package("cwmp", UCI_STANDARD_CONFIG); } + return 0; } -void http_client_exit(void) -{ - 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) +static size_t cwmp_http_get_response(void *buffer, size_t size, size_t rxed, char **msg_in) { 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; } -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)]; 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 }; char *ip = NULL; char errbuf[CURL_ERROR_SIZE]; + struct curl_slist *header_list = NULL; - http_c.header_list = NULL; - http_c.header_list = curl_slist_append(http_c.header_list, "User-Agent: iopsys-cwmp"); - if (!http_c.header_list) + header_list = curl_slist_append(header_list, "User-Agent: iopsys-cwmp"); + if (!header_list) 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; + #ifdef ACS_FUSION - http_c.header_list = curl_slist_append(http_c.header_list, "Expect:"); - if (!http_c.header_list) + header_list = curl_slist_append(header_list, "Expect:"); + if (!header_list) return -1; #endif /* ACS_FUSION */ + if (cwmp->conf.http_disable_100continue) { - http_c.header_list = curl_slist_append(http_c.header_list, "Expect:"); - if (!http_c.header_list) + header_list = curl_slist_append(header_list, "Expect:"); + if (!header_list) 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_PASSWORD, cwmp->conf.acs_passwd); 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_POSTREDIR, CURL_REDIR_POST_ALL); curl_easy_setopt(curl, CURLOPT_NOBODY, 0); + switch (cwmp->conf.compression) { case COMP_NONE: break; case COMP_GZIP: curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "gzip"); - http_c.header_list = curl_slist_append(http_c.header_list, "Content-Encoding: gzip"); + header_list = curl_slist_append(header_list, "Content-Encoding: gzip"); break; case COMP_DEFLATE: curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "deflate"); - http_c.header_list = curl_slist_append(http_c.header_list, "Content-Encoding: deflate"); + header_list = curl_slist_append(header_list, "Content-Encoding: deflate"); 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); if (msg_out) curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)msg_out_len); else curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, 0); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_response); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cwmp_http_get_response); curl_easy_setopt(curl, CURLOPT_WRITEDATA, msg_in); #ifdef DEVEL @@ -193,8 +179,8 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char ** #endif curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf); - curl_easy_setopt(curl, CURLOPT_COOKIEFILE, fc_cookies); - curl_easy_setopt(curl, CURLOPT_COOKIEJAR, fc_cookies); + curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookies_file); + curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookies_file); if (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) goto error; - /* TODO add check for 301, 302 and 307 HTTP Redirect*/ - - if (http_c.header_list) { - curl_slist_free_all(http_c.header_list); - http_c.header_list = NULL; + if (header_list) { + curl_slist_free_all(header_list); + header_list = NULL; } if (res) @@ -266,36 +250,48 @@ int http_send_message(struct cwmp *cwmp, char *msg_out, int msg_out_len, char ** error: FREE(*msg_in); - if (http_c.header_list) { - curl_slist_free_all(http_c.header_list); - http_c.header_list = NULL; + if (header_list) { + curl_slist_free_all(header_list); + header_list = NULL; } 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"); + pthread_mutex_lock(&(cwmp_main.mutex_session_queue)); cwmp_add_event_container(&cwmp_main, EVENT_IDX_6CONNECTION_REQUEST, ""); pthread_mutex_unlock(&(cwmp_main.mutex_session_queue)); pthread_cond_signal(&(cwmp_main.threshold_session_send)); } -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 auth_digest_buffer[BUFSIZ]; int8_t auth_status = 0; bool auth_digest_checked = false; bool method_is_get = false; bool internal_error = false; - char cr_http_get_head[512]; pthread_mutex_lock(&mutex_config_load); - fp = fdopen(client, "r+"); + FILE *fp = fdopen(client, "r+"); char *username = cwmp_main.conf.cpe_userid; 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; goto http_end; } + 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)) { 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; } } + if (!service_available || !method_is_get) { goto http_end; } + int auth_check = http_digest_auth_check("GET", "/", auth_digest_buffer + strlen("Authorization: Digest "), REALM, username, password, 300); if (auth_check == MHD_INVALID_NONCE) { internal_error = true; goto http_end; } + if (auth_digest_checked && auth_check == MHD_YES) auth_status = 1; else auth_status = 0; + http_end: if (!service_available || !method_is_get) { 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("Connection: close\r\n", fp); fputs("Content-Length: 0\r\n", fp); - http_success_cr(); + cwmp_http_success_cr(); } else if (internal_error) { CWMP_LOG(INFO, "Receive Connection Request: Return 500 Internal Error"); fputs("HTTP/1.1 500 Internal Server Error\r\n", fp); @@ -361,7 +362,7 @@ http_end: pthread_mutex_unlock(&mutex_config_load); } -void http_server_init(void) +void cwmp_http_server_init(void) { struct sockaddr_in6 server = { 0 }; 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); } -void http_server_listen(void) +void cwmp_http_server_listen(void) { int client_sock, c; int cr_request = 0; @@ -442,7 +443,8 @@ void http_server_listen(void) service_available = false; } } - http_cr_new_client(client_sock, service_available); + + cwmp_http_cr_new_client(client_sock, service_available); close(client_sock); } @@ -451,3 +453,15 @@ void http_server_listen(void) 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); +} diff --git a/cwmp_time.c b/cwmp_time.c deleted file mode 100644 index 33e30a1..0000000 --- a/cwmp_time.c +++ /dev/null @@ -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 - */ - -#include - -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; -} diff --git a/cwmp_uci.c b/cwmp_uci.c index 5b33521..882a1b6 100644 --- a/cwmp_uci.c +++ b/cwmp_uci.c @@ -4,7 +4,7 @@ * 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) 2013-2022 iopsys Software Solutions AB * Author Omar Kallel */ #include @@ -15,7 +15,7 @@ #include "cwmp_uci.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_VARSTATE_CONFIG] = { "/var/state", NULL, NULL } }; @@ -37,10 +37,11 @@ static inline bool cwmp_check_section_name(const char *str, bool name) 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*/ ptr->value = value; + /*package*/ if (!package) 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; 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_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; goto lookup; } + ptr->target = UCI_TYPE_OPTION; ptr->option = option; ptr->flags |= UCI_LOOKUP_EXTENDED; + lookup: if (uci_lookup_ptr(ctx, ptr, NULL, false) != UCI_OK || !UCI_LOOKUP_COMPLETE) return -1; @@ -105,19 +108,21 @@ lookup: * 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) return; + uci_save_conf_paths[config].uci_ctx = uci_alloc_context(); if ( uci_save_conf_paths[config].uci_ctx == NULL) return; + 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_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) { 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; - int uci_nbre_conf_paths = (int)(sizeof(uci_save_conf_paths) / sizeof(struct uci_paths)); - for (i = 0; i < uci_nbre_conf_paths; i++) { + unsigned int i = 0; + + for (i = 0; i < ARRAY_SIZE(uci_save_conf_paths); i++) { cwmp_uci_init_by_config(i); } return 0; @@ -137,9 +142,9 @@ int cwmp_uci_init() void cwmp_uci_exit(void) { - int i; - int uci_nbre_conf_paths = (int)(sizeof(uci_save_conf_paths) / sizeof(struct uci_paths)); - for (i = 0; i < uci_nbre_conf_paths; i++) { + unsigned int i = 0; + + for (i = 0; i < ARRAY_SIZE(uci_save_conf_paths); 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; } -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; - char *s; + struct uci_ptr ptr = {0}; + char uci_path[256] = {0}; *value = NULL; - s = strdup(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); - free(s); + CWMP_STRNCPY(uci_path, path, sizeof(uci_path)); + + if (uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, uci_path, true) != UCI_OK) { + CWMP_LOG(ERROR, "Error occurred in uci get %s", uci_path); return UCI_ERR_PARSE; } - free(s); + if (ptr.flags & UCI_LOOKUP_COMPLETE) { 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; } *value = strdup(ptr.o->v.string); } + return UCI_OK; } int uci_get_state_value(char *path, char **value) { - int error; - error = cwmp_uci_get_value_by_path(path, UCI_VARSTATE_CONFIG, value); - return error; + return cwmp_uci_get_value_by_path(path, UCI_VARSTATE_CONFIG, value); } int uci_get_value(char *path, char **value) { - int error; - error = cwmp_uci_get_value_by_path(path, UCI_STANDARD_CONFIG, value); - return error; + return cwmp_uci_get_value_by_path(path, UCI_STANDARD_CONFIG, value); } int cwmp_uci_get_value_by_section_string(struct uci_section *s, char *option, char **value) { - struct uci_element *e; - struct uci_option *o; + struct uci_element *e = NULL; + struct uci_option *o = NULL; - *value = NULL; if (s == NULL || &s->options == NULL || option == NULL) goto not_found; - uci_foreach_element(&s->options, e) - { + uci_foreach_element(&s->options, e) { o = (uci_to_option(e)); if (!strcmp(o->e.name, option)) { if (o->type == UCI_TYPE_LIST) { @@ -237,11 +237,43 @@ not_found: 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; - struct uci_option *o; - struct uci_list *list; + ptr->prev = ptr; + ptr->next = ptr; +} + +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 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) return -1; - uci_foreach_element(&s->options, e) - { + uci_foreach_element(&s->options, e) { o = (uci_to_option(e)); if (strcmp(o->e.name, option) == 0) { switch (o->type) { @@ -278,22 +309,26 @@ int cwmp_uci_get_value_by_section_list(struct uci_section *s, char *option, stru } } } + return -1; } /* * 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}; if (cwmp_uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, package, section, option, value)) return UCI_ERR_PARSE; + if (uci_set(uci_save_conf_paths[uci_type].uci_ctx, &ptr) != UCI_OK) return UCI_ERR_NOTFOUND; + if (ptr.o) return UCI_OK; + 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); } -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; - char cmd[256]; 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; - } ret = uci_set(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 UCI_ERR_NOTFOUND; + CWMP_LOG(ERROR, "UCI Set not succeed %s", path); + ret = UCI_ERR_NOTFOUND; } + return ret; } @@ -342,43 +378,13 @@ int cwmp_uci_set_varstate_value_by_path(char *path, char *value) /* * 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) { struct uci_element *e = NULL, *tmp = NULL; + if (list == NULL) return; + uci_foreach_element_safe(list, e, tmp) 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) return NULL; + if (list && !uci_list_empty(list)) { struct uci_element *e = NULL; char list_val[512] = { 0 }; unsigned pos = 0; list_val[0] = 0; - uci_foreach_element(list, e) - { + + uci_foreach_element(list, e) { if (e->name) 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 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_ptr ptr = {0}; - struct uci_list *list; + struct uci_list *list = NULL; char *pch = NULL, *spch = NULL, *dup = NULL; int option_type; *value = NULL; @@ -489,25 +497,6 @@ int cwmp_uci_del_list_value(char *package, char *section, char *option, char *va 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 */ @@ -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) { struct uci_ptr ptr = {0}; - char fname[128]; + char fname[128] = {0}; *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 *s; + struct uci_section *s = NULL; + cwmp_uci_foreach_sections(package, stype, uci_type, s) { if (strcmp(section_name(s), sname) == 0) 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}; if (cwmp_uci_lookup_ptr_by_section(uci_save_conf_paths[uci_type].uci_ctx, &up, s, NULL, value) == -1) return UCI_ERR_PARSE; + if (uci_rename(uci_save_conf_paths[uci_type].uci_ctx, &up) != UCI_OK) 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) return UCI_ERR_DUPLICATE; + if (cwmp_uci_add_section(package, stype, uci_type, &s) != UCI_OK) return UCI_ERR_UNKNOWN; 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) { struct uci_ptr ptr = {0}; + if (cwmp_uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, package, section, NULL, NULL)) { *value = ""; return -1; } + if (ptr.s) { *value = icwmp_strdup(ptr.s->type); } else { *value = ""; } + return UCI_OK; } @@ -685,14 +658,14 @@ end: int cwmp_commit_package(char *package, uci_config_paths uci_type) { - struct uci_ptr ptr = { 0 }; - if (uci_lookup_ptr(uci_save_conf_paths[uci_type].uci_ctx, &ptr, package, true) != UCI_OK) { - return -1; - } + struct uci_ptr ptr = {0}; - 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; - } + + if (uci_commit(uci_save_conf_paths[uci_type].uci_ctx, &ptr.p, false) != UCI_OK) + return -1; + 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_element *e = NULL; int ret = CWMP_OK; + FILE *input = fopen(input_path, "r"); if (!input) return -1; @@ -714,8 +688,8 @@ int cwmp_uci_import(char *package_name, const char *input_path, uci_config_paths ret = -1; 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); if (uci_commit(uci_save_conf_paths[uci_type].uci_ctx, &p, true) != UCI_OK) 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) { - struct uci_ptr ptr = { 0 }; + struct uci_ptr ptr = {0}; int ret = 0; + FILE *out = fopen(output_path, "a"); if (!out) return -1; @@ -750,7 +725,7 @@ end: int cwmp_uci_export(const char *output_path, uci_config_paths uci_type) { char **configs = NULL; - char **p; + char **p = NULL; if (uci_list_configs(uci_save_conf_paths[uci_type].uci_ctx, &configs) != UCI_OK) return -1; diff --git a/digestauth.c b/digestauth.c index 7133ef1..9b102d6 100644 --- a/digestauth.c +++ b/digestauth.c @@ -3,23 +3,40 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * HTTP digest auth functions: originally imported from libmicrohttpd - * - * Copyright (C) 2013 Oussama Ghorbel - * Omar Kallel * + * Copyright (C) 2013-2022 iopsys Software Solutions AB + * Author Oussama Ghorbel + * Author Omar Kallel */ +#ifdef LMBEDTLS +#include +#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 +#define MD5_CTX MD5_CTX +#define MD5_INIT MD5_Init +#define MD5_UPDATE MD5_Update +#define MD5_FINAL MD5_Final +#endif + #include #include #include #include +#include #include "log.h" #include "common.h" #include "digestauth.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) @@ -38,11 +55,14 @@ */ #define MAX_AUTH_RESPONSE_LENGTH 1024 +/** + * Maximum length of the nonce in digest authentication. + */ #define MAX_NONCE_LENGTH 1024 char *nonce_privacy_key = NULL; -int generate_nonce_priv_key() +int generate_nonce_priv_key(void) { nonce_privacy_key = generate_random_string(28); 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) { - struct MD5Context md5; + MD5_CTX md5; unsigned char timestamp[4]; unsigned char tmpnonce[MD5_DIGEST_SIZE]; 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); - md5_init(&md5); + MD5_INIT(&md5); timestamp[0] = (nonce_time & 0xff000000) >> 0x18; timestamp[1] = (nonce_time & 0x00ff0000) >> 0x10; timestamp[2] = (nonce_time & 0x0000ff00) >> 0x08; timestamp[3] = (nonce_time & 0x000000ff); - md5_update(&md5, timestamp, 4); - md5_update(&md5, ":", 1); - md5_update(&md5, method, strlen(method)); - md5_update(&md5, ":", 1); + MD5_UPDATE(&md5, timestamp, 4); + MD5_UPDATE(&md5, ":", 1); + MD5_UPDATE(&md5, method, strlen(method)); + MD5_UPDATE(&md5, ":", 1); if (rnd_size > 0) - md5_update(&md5, rnd, rnd_size); - md5_update(&md5, ":", 1); - md5_update(&md5, uri, strlen(uri)); - md5_update(&md5, ":", 1); - md5_update(&md5, realm, strlen(realm)); - md5_final(tmpnonce, &md5); + MD5_UPDATE(&md5, rnd, rnd_size); + MD5_UPDATE(&md5, ":", 1); + MD5_UPDATE(&md5, uri, strlen(uri)); + MD5_UPDATE(&md5, ":", 1); + MD5_UPDATE(&md5, realm, strlen(realm)); + MD5_FINAL(tmpnonce, &md5); cvthex(tmpnonce, sizeof(tmpnonce), nonce); cvthex(timestamp, 4, timestamphex); 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) { - struct MD5Context md5; + MD5_CTX md5; unsigned char ha1[MD5_DIGEST_SIZE]; - md5_init(&md5); - md5_update(&md5, username, strlen(username)); - md5_update(&md5, ":", 1); - md5_update(&md5, realm, strlen(realm)); - md5_update(&md5, ":", 1); - md5_update(&md5, password, strlen(password)); - md5_final(ha1, &md5); + MD5_INIT(&md5); + MD5_UPDATE(&md5, username, strlen(username)); + MD5_UPDATE(&md5, ":", 1); + MD5_UPDATE(&md5, realm, strlen(realm)); + MD5_UPDATE(&md5, ":", 1); + MD5_UPDATE(&md5, password, strlen(password)); + MD5_FINAL(ha1, &md5); if (0 == strcasecmp(alg, "md5-sess")) { - md5_init(&md5); - md5_update(&md5, ha1, sizeof(ha1)); - md5_update(&md5, ":", 1); - md5_update(&md5, nonce, strlen(nonce)); - md5_update(&md5, ":", 1); - md5_update(&md5, cnonce, strlen(cnonce)); - md5_final(ha1, &md5); + MD5_INIT(&md5); + MD5_UPDATE(&md5, ha1, sizeof(ha1)); + MD5_UPDATE(&md5, ":", 1); + MD5_UPDATE(&md5, nonce, strlen(nonce)); + MD5_UPDATE(&md5, ":", 1); + MD5_UPDATE(&md5, cnonce, strlen(cnonce)); + MD5_FINAL(ha1, &md5); } 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) { - struct MD5Context md5; + MD5_CTX md5; unsigned char ha2[MD5_DIGEST_SIZE]; unsigned char resphash[MD5_DIGEST_SIZE]; char ha2hex[HASH_MD5_HEX_LEN + 1]; - md5_init(&md5); - md5_update(&md5, method, strlen(method)); - md5_update(&md5, ":", 1); - md5_update(&md5, uri, strlen(uri)); - md5_final(ha2, &md5); + MD5_INIT(&md5); + MD5_UPDATE(&md5, method, strlen(method)); + MD5_UPDATE(&md5, ":", 1); + MD5_UPDATE(&md5, uri, strlen(uri)); + MD5_FINAL(ha2, &md5); cvthex(ha2, MD5_DIGEST_SIZE, ha2hex); - md5_init(&md5); + MD5_INIT(&md5); /* calculate response */ - md5_update(&md5, ha1, HASH_MD5_HEX_LEN); - md5_update(&md5, ":", 1); - md5_update(&md5, nonce, strlen(nonce)); - md5_update(&md5, ":", 1); + MD5_UPDATE(&md5, ha1, HASH_MD5_HEX_LEN); + MD5_UPDATE(&md5, ":", 1); + MD5_UPDATE(&md5, nonce, strlen(nonce)); + MD5_UPDATE(&md5, ":", 1); if ('\0' != *qop) { - md5_update(&md5, noncecount, strlen(noncecount)); - md5_update(&md5, ":", 1); - md5_update(&md5, cnonce, strlen(cnonce)); - md5_update(&md5, ":", 1); - md5_update(&md5, qop, strlen(qop)); - md5_update(&md5, ":", 1); + MD5_UPDATE(&md5, noncecount, strlen(noncecount)); + MD5_UPDATE(&md5, ":", 1); + MD5_UPDATE(&md5, cnonce, strlen(cnonce)); + MD5_UPDATE(&md5, ":", 1); + MD5_UPDATE(&md5, qop, strlen(qop)); + MD5_UPDATE(&md5, ":", 1); } - md5_update(&md5, ha2hex, HASH_MD5_HEX_LEN); - md5_final(resphash, &md5); + MD5_UPDATE(&md5, ha2hex, HASH_MD5_HEX_LEN); + MD5_FINAL(resphash, &md5); 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) { 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); - DD(DEBUG, "%s: header: %s", __FUNCTION__, header); - fputs("WWW-Authenticate: ", fp); fputs(header, fp); return MHD_YES; @@ -313,20 +320,6 @@ int http_digest_auth_fail_response(FILE *fp, const char *http_method, const char 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) { 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]; size_t left; /* number of characters left in 'header' for 'uri' */ - DD(DEBUG, "%s: header: %s", __FUNCTION__, 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))) { - DD(DEBUG, "Authentication failed: URI does not match."); + CWMP_LOG(ERROR, "Authentication failed: URI does not match."); return MHD_NO; } + if (nonce_privacy_key == NULL) { if (generate_nonce_priv_key() != CWMP_OK) return MHD_INVALID_NONCE; } + nonce_key_len = strlen(nonce_privacy_key); 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")) || (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; } + nci = strtoul(nc, &end, 16); 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 */ } @@ -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_response(ha1, nonce, nc, cnonce, qop, http_method, uri, respexp); + return (0 == strcmp(response, respexp)) ? MHD_YES : MHD_NO; } } diff --git a/download.c b/download.c index d6fccb9..c670ed9 100644 --- a/download.c +++ b/download.c @@ -16,7 +16,6 @@ #include "ubus.h" #include "cwmp_uci.h" #include "backupSession.h" -#include "cwmp_time.h" #include "log.h" #include "event.h" @@ -175,7 +174,7 @@ int cwmp_launch_download(struct download *pdownload, char *download_file_name, e char *download_startTime; 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); bkp_session_save(); @@ -246,7 +245,7 @@ end_download: p->command_key = pdownload->command_key ? strdup(pdownload->command_key) : strdup(""); p->start_time = strdup(download_startTime); - p->complete_time = strdup(mix_get_time()); + p->complete_time = strdup(get_time(time(NULL))); p->type = ltype; if (error != FAULT_CPE_NO_FAULT) { 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)); if (ptransfer_complete != NULL) { 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->fault_code = ltype == TYPE_DOWNLOAD ? FAULT_CPE_DOWNLOAD_FAILURE : FAULT_CPE_DOWNLOAD_FAIL_WITHIN_TIME_WINDOW; 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->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->type = TYPE_SCHEDULE_DOWNLOAD; bkp_session_insert_transfer_complete(ptransfer_complete); diff --git a/inc/common.h b/inc/common.h index db62468..4cf4724 100644 --- a/inc/common.h +++ b/inc/common.h @@ -4,12 +4,12 @@ * 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 + * Copyright (C) 2013-2022 iopsys Software Solutions AB * Author Omar Kallel * */ -#ifndef __CCOMMON_H -#define __CCOMMON_H +#ifndef CWMP_COMMON_H +#define CWMP_COMMON_H #include #include @@ -21,9 +21,21 @@ #define CWMP_VERSION "3.0.0" #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 MAX_EVENTS 64 @@ -49,7 +61,6 @@ #define FIREWALL_CWMP "/etc/firewall.cwmp" #define CWMP_VARSTATE_UCI_PACKAGE "/var/state/cwmp" -#define STRCMP(S1, S2) ((S1 != NULL && S2 != NULL) ? strcmp(S1, S2) : -1) extern char *commandKey; extern bool thread_end; extern bool signal_exit; @@ -156,7 +167,10 @@ enum action { 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 { CWMP_XML_ERR = -1, @@ -167,9 +181,16 @@ enum cwmp_ret_err { 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 { struct list_head list; @@ -202,7 +223,10 @@ enum amd_version_enum { AMD_5, }; -enum instance_mode { INSTANCE_MODE_NUMBER, INSTANCE_MODE_ALIAS }; +enum instance_mode { + INSTANCE_MODE_NUMBER, + INSTANCE_MODE_ALIAS +}; struct cwmp_namespaces { char *soap_env; @@ -248,9 +272,17 @@ enum acs_support_idx { 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 { FAULT_CPE_NO_FAULT, @@ -322,7 +354,10 @@ enum fault_code_enum { __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 { const char *name; @@ -452,8 +487,7 @@ extern long int flashsize; extern struct FAULT_CPE FAULT_CPE_ARRAY[]; extern struct cwmp_namespaces ns; -void add_dm_parameter_to_list(struct list_head *head, char *param_name, char *param_data, char *param_type, - int notification, bool writable); +void add_dm_parameter_to_list(struct list_head *head, char *param_name, char *param_data, char *param_type, int notification, bool writable); void delete_dm_parameter_from_list(struct cwmp_dm_parameter *dm_parameter); void cwmp_free_all_dm_parameter_list(struct list_head *list); 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); int copy_file(char *source_file, char *target_file); 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 -#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 +#endif /* CWMP_COMMON_H */ diff --git a/inc/cwmp_http.h b/inc/cwmp_http.h new file mode 100644 index 0000000..bff4ea0 --- /dev/null +++ b/inc/cwmp_http.h @@ -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 + * Author: Ahmed Zribi + * Author: Omar Kallel + * + * 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__ */ diff --git a/inc/cwmp_time.h b/inc/cwmp_time.h deleted file mode 100644 index afc43ac..0000000 --- a/inc/cwmp_time.h +++ /dev/null @@ -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 - * - */ - -#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_ */ diff --git a/inc/cwmp_uci.h b/inc/cwmp_uci.h index c3bc0a3..8664f74 100644 --- a/inc/cwmp_uci.h +++ b/inc/cwmp_uci.h @@ -4,19 +4,18 @@ * 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 + * Copyright (C) 2013-2022 iopsys Software Solutions AB * Author Omar Kallel * */ -#ifndef __CWMPUCI_H -#define __CWMPUCI_H +#ifndef CWMP_UCI_H +#define CWMP_UCI_H #include #include "common.h" -//struct uci_context *cwmp_uci_ctx = ((void *)0); #define UCI_DHCP_DISCOVERY_PATH "cwmp.acs.dhcp_discovery" #define UCI_ACS_URL_PATH "cwmp.acs.url" #define UCI_PERIODIC_INFORM_TIME_PATH "cwmp.acs.periodic_inform_time" @@ -118,15 +117,12 @@ struct uci_paths { struct uci_context *uci_ctx; }; -extern struct uci_paths uci_save_conf_paths[]; -int cwmp_uci_init(); +int cwmp_uci_init(void); void cwmp_uci_exit(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_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_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_varstate_value_by_path(char *path, 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_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); -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); #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) \ 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 */ diff --git a/inc/digestauth.h b/inc/digestauth.h index bdd5b10..d29559f 100644 --- a/inc/digestauth.h +++ b/inc/digestauth.h @@ -3,10 +3,10 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * HTTP digest auth functions: originally imported from libmicrohttpd - * - * Copyright (C) 2013 Oussama Ghorbel * + * Copyright (C) 2013-2022 iopsys Software Solutions AB + * Author Oussama Ghorbel + * Author Omar Kallel */ #ifndef DIGESTAUTH_H_ @@ -29,10 +29,32 @@ 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); +/** + * 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 generate_nonce_priv_key(); +int generate_nonce_priv_key(void); #endif /* DIGESTAUTH_H_ */ diff --git a/inc/http.h b/inc/http.h deleted file mode 100644 index 3b79a31..0000000 --- a/inc/http.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Copyright (C) 2011 Luka Perkov - */ - -#ifndef _FREECWMP_HTTP_H__ -#define _FREECWMP_HTTP_H__ - -#include "common.h" - -extern char *fc_cookies; - -#define HTTP_TIMEOUT 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 diff --git a/inc/log.h b/inc/log.h index 01797aa..049b770 100644 --- a/inc/log.h +++ b/inc/log.h @@ -4,7 +4,7 @@ * 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 + * Copyright (C) 2013-2022 iopsys Software Solutions AB * Author Mohamed Kallel * Author Ahmed Zribi * @@ -39,58 +39,12 @@ int log_set_on_console(char *value); int log_set_on_file(char *value); int log_set_on_syslog(char *value); int log_set_severity_idx(char *value); + #define DEFAULT_LOG_FILE_SIZE 10240 #define DEFAULT_LOG_FILE_NAME "/var/log/icwmpd.log" #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_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_ */ diff --git a/inc/md5.h b/inc/md5.h deleted file mode 100644 index b3670fe..0000000 --- a/inc/md5.h +++ /dev/null @@ -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 - -#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 */ diff --git a/inc/messages.h b/inc/messages.h deleted file mode 100644 index 542676c..0000000 --- a/inc/messages.h +++ /dev/null @@ -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 - */ - -#ifndef _FREECWMP_MESSAGES_H__ -#define _FREECWMP_MESSAGES_H__ - -#define CWMP_LWNOTIFICATION_MESSAGE \ -"" \ -"" \ - "" \ - "" \ - "" \ - "" \ - "" \ - "" \ -"" -#define CWMP_INFORM_MESSAGE \ -"" \ -"" \ - "" \ - "" \ - "" \ - "" \ - "" \ - "" \ - "" \ - "" \ - "" \ - "" \ - "" \ - "" \ - "1" \ - "" \ - "" \ - "" \ - "" \ -"" \ -"" - - -#define CWMP_RESPONSE_MESSAGE \ -"" \ -"" \ - "" \ - "" \ - "" \ - "" \ -"" - -#endif - diff --git a/inc/netlink.h b/inc/netlink.h deleted file mode 100755 index 1aaddaf..0000000 --- a/inc/netlink.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Copyright (C) 2013-2019 iopsys Software Solutions AB - * Author Mohamed Kallel - * Author Anis Ellouze - * - */ - -#ifndef _NETLINK_H__ -#define _NETLINK_H__ - -int netlink_init(void); -int netlink_init_v6(void); - -#endif diff --git a/inc/ubus.h b/inc/ubus.h index f9b395f..67d5aa6 100644 --- a/inc/ubus.h +++ b/inc/ubus.h @@ -9,15 +9,12 @@ * * Copyright (C) 2012 Luka Perkov */ + #ifndef _FREECWMP_UBUS_H__ #define _FREECWMP_UBUS_H__ -#include -/* -#include -#include -#include "common.h" -*/ +#include + #include "common.h" #define ARRAY_MAX 8 diff --git a/inc/xml.h b/inc/xml.h index 5df4dbe..7f48fc9 100644 --- a/inc/xml.h +++ b/inc/xml.h @@ -16,6 +16,19 @@ } \ } while (0) +#define CWMP_RESPONSE_MESSAGE \ +"" \ +"" \ + "" \ + "" \ + "" \ + "" \ +"" + extern const char *cwmp_urls[]; int xml_prepare_msg_out(struct session *session); int xml_prepare_lwnotification_message(char **msg_out); diff --git a/kcwmp.c b/kcwmp.c deleted file mode 100644 index 712fb77..0000000 --- a/kcwmp.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#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); diff --git a/log.c b/log.c index 9d62b67..11381cd 100644 --- a/log.c +++ b/log.c @@ -4,7 +4,7 @@ * 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) 2013-2022 iopsys Software Solutions AB * Author Mohamed Kallel * Author Ahmed Zribi * diff --git a/md5.c b/md5.c deleted file mode 100644 index 12a6834..0000000 --- a/md5.c +++ /dev/null @@ -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 - -#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 */ diff --git a/netlink.c b/netlink.c deleted file mode 100644 index ca5641d..0000000 --- a/netlink.c +++ /dev/null @@ -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 - * Author Ahmed Zribi - * Copyright (C) 2011-2012 Luka Perkov - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "netlink.h" -#include "cwmp_uci.h" -#include "log.h" -#include "event.h" - -static int itfcmp(char *itf1, char *itf2); -static void netlink_new_msg(struct uloop_fd *ufd, unsigned events); -static struct uloop_fd netlink_event = {.cb = netlink_new_msg }; -static struct uloop_fd netlink_event_v6 = {.cb = netlink_new_msg }; - -static int itfcmp(char *itf1, char *itf2) -{ - int index = 0; - int status = 1; - char *str = NULL; - char *buf1 = NULL; - char *buf2 = NULL; - - if (itf1[0] == '\0') - goto end; - str = strchr(itf1, '.'); - if (str == NULL) - goto end; - index = (int)(str - itf1); - if (!index) - goto end; - - buf1 = malloc(index); - if (!buf1) - goto end; - - strncpy(buf1, itf1, index); - buf1[index] = '\0'; - if (itf2[0] == '\0') - goto end; - - str = strchr(itf2, '.'); - if (str == NULL) - goto end; - - index = (int)(str - itf2); - if (!index) - goto end; - - buf2 = malloc(index); - if (!buf2) - goto end; - - strncpy(buf2, itf1, index); - buf2[index] = '\0'; - - if (strcmp(buf1, buf2) == 0) - status = 0; -end: - if (buf1) - free(buf1); - if (buf2) - free(buf2); - return status; -} - -static void freecwmp_netlink_interface(struct nlmsghdr *nlh) -{ - struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA(nlh); - struct rtattr *rth = IFA_RTA(ifa); - int rtl = IFA_PAYLOAD(nlh); - char if_name[IFNAMSIZ], if_addr[INET_ADDRSTRLEN]; - - memset(&if_name, 0, sizeof(if_name)); - memset(&if_addr, 0, sizeof(if_addr)); - - if (ifa->ifa_family == AF_INET) { //CASE IPv4 - while (rtl && RTA_OK(rth, rtl)) { - if (rth->rta_type != IFA_LOCAL) { - rth = RTA_NEXT(rth, rtl); - continue; - } - - uint32_t addr = htonl(*(uint32_t *)RTA_DATA(rth)); - if (htonl(13) == 13) { - // running on big endian system - } else { - // running on little endian system - addr = __builtin_bswap32(addr); - } - - if_indextoname(ifa->ifa_index, if_name); - if (itfcmp(cwmp_main.conf.interface, if_name)) { - rth = RTA_NEXT(rth, rtl); - continue; - } - - inet_ntop(AF_INET, &(addr), if_addr, INET_ADDRSTRLEN); - - FREE(cwmp_main.conf.ip); - cwmp_main.conf.ip = strdup(if_addr); - cwmp_uci_set_varstate_value("cwmp", "cpe", "ip", cwmp_main.conf.ip); - cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); - connection_request_ip_value_change(&cwmp_main, IPv4); - break; - } - } else { //CASE IPv6 - while (rtl && RTA_OK(rth, rtl)) { - char pradd_v6[128]; - if (rth->rta_type != IFA_ADDRESS || ifa->ifa_scope == RT_SCOPE_LINK) { - rth = RTA_NEXT(rth, rtl); - continue; - } - inet_ntop(AF_INET6, RTA_DATA(rth), pradd_v6, sizeof(pradd_v6)); - if_indextoname(ifa->ifa_index, if_name); - if (strncmp(cwmp_main.conf.interface, if_name, IFNAMSIZ)) { - rth = RTA_NEXT(rth, rtl); - continue; - } - - FREE(cwmp_main.conf.ipv6); - cwmp_main.conf.ipv6 = strdup(pradd_v6); - cwmp_uci_set_varstate_value("cwmp", "cpe", "ipv6", cwmp_main.conf.ip); - cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); - connection_request_ip_value_change(&cwmp_main, IPv6); - break; - } - } -} - -static void netlink_new_msg(struct uloop_fd *ufd, unsigned events __attribute__((unused))) -{ - struct nlmsghdr *nlh; - char buffer[BUFSIZ]; - size_t msg_size; - - memset(&buffer, 0, sizeof(buffer)); - - nlh = (struct nlmsghdr *)buffer; - if ((int)(msg_size = recv(ufd->fd, nlh, BUFSIZ, 0)) == -1) { - CWMP_LOG(ERROR, "error receiving netlink message"); - return; - } - - while ((size_t)msg_size > sizeof(*nlh)) { - int len = nlh->nlmsg_len; - int req_len = len - sizeof(*nlh); - - if (req_len < 0 || (size_t)len > msg_size) { - CWMP_LOG(ERROR, "error reading netlink message"); - return; - } - - if (!NLMSG_OK(nlh, msg_size)) { - CWMP_LOG(ERROR, "netlink message is not NLMSG_OK"); - return; - } - - if (nlh->nlmsg_type == RTM_NEWADDR) - freecwmp_netlink_interface(nlh); - - msg_size -= NLMSG_ALIGN(len); - nlh = (struct nlmsghdr *)((char *)nlh + NLMSG_ALIGN(len)); - } -} - -int netlink_init_v6(void) -{ - struct { - struct nlmsghdr hdr; - struct ifaddrmsg msg; - } req; - struct sockaddr_nl addr; - int sock[2]; - - memset(&addr, 0, sizeof(addr)); - memset(&req, 0, sizeof(req)); - - if ((sock[0] = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) { - CWMP_LOG(ERROR, "couldn't open NETLINK_ROUTE socket"); - return -1; - } - - addr.nl_family = AF_NETLINK; - addr.nl_groups = RTMGRP_IPV6_IFADDR; - if ((bind(sock[0], (struct sockaddr *)&addr, sizeof(addr))) == -1) { - CWMP_LOG(ERROR, "couldn't bind netlink socket"); - return -1; - } - - netlink_event_v6.fd = sock[0]; - uloop_fd_add(&netlink_event_v6, ULOOP_READ | ULOOP_EDGE_TRIGGER); - - if ((sock[1] = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) == -1) { - CWMP_LOG(ERROR, "couldn't open NETLINK_ROUTE socket"); - return -1; - } - - req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); - req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; - req.hdr.nlmsg_type = RTM_GETADDR; - req.msg.ifa_family = AF_INET6; - - if ((send(sock[1], &req, req.hdr.nlmsg_len, 0)) == -1) { - CWMP_LOG(ERROR, "couldn't send netlink socket"); - return -1; - } - - struct uloop_fd dummy_event = {.fd = sock[1] }; - netlink_new_msg(&dummy_event, 0); - - return 0; -} - -int netlink_init(void) -{ - struct { - struct nlmsghdr hdr; - struct ifaddrmsg msg; - } req; - struct sockaddr_nl addr; - int sock[2]; - - memset(&addr, 0, sizeof(addr)); - memset(&req, 0, sizeof(req)); - - if ((sock[0] = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) { - CWMP_LOG(ERROR, "couldn't open NETLINK_ROUTE socket"); - return -1; - } - - addr.nl_family = AF_NETLINK; - addr.nl_groups = RTMGRP_IPV4_IFADDR; - if ((bind(sock[0], (struct sockaddr *)&addr, sizeof(addr))) == -1) { - CWMP_LOG(ERROR, "couldn't bind netlink socket"); - return -1; - } - - netlink_event.fd = sock[0]; - uloop_fd_add(&netlink_event, ULOOP_READ | ULOOP_EDGE_TRIGGER); - - if ((sock[1] = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) == -1) { - CWMP_LOG(ERROR, "couldn't open NETLINK_ROUTE socket"); - return -1; - } - - req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); - req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; - req.hdr.nlmsg_type = RTM_GETADDR; - req.msg.ifa_family = AF_INET; - - if ((send(sock[1], &req, req.hdr.nlmsg_len, 0)) == -1) { - CWMP_LOG(ERROR, "couldn't send netlink socket"); - return -1; - } - - struct uloop_fd dummy_event = {.fd = sock[1] }; - netlink_new_msg(&dummy_event, 0); - - return 0; -} diff --git a/rpc_soap.c b/rpc_soap.c index 9a4f4d2..dd8da2a 100755 --- a/rpc_soap.c +++ b/rpc_soap.c @@ -18,9 +18,7 @@ #include "cwmp_du_state.h" #include "log.h" #include "event.h" -#include "cwmp_time.h" #include "datamodel_interface.h" -#include "messages.h" #include "event.h" #include "xml.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 #define DM_CONN_REQ_URL "Device.ManagementServer.ConnectionRequestURL" +#define CWMP_INFORM_MESSAGE \ +"" \ +"" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "1" \ + "" \ + "" \ + "" \ + "" \ +"" \ +"" + struct cwmp_namespaces ns; const struct rpc_cpe_method rpc_cpe_methods[] = { [RPC_CPE_GET_RPC_METHODS] = { "GetRPCMethods", cwmp_handle_rpc_cpe_get_rpc_methods, AMD_1 }, [RPC_CPE_SET_PARAMETER_VALUES] = { "SetParameterValues", cwmp_handle_rpc_cpe_set_parameter_values, AMD_1 }, @@ -64,7 +89,13 @@ char *boot_inform_parameters[MAX_NBRE_CUSTOM_INFORM] = { 0 }; int nbre_custom_inform = 0; int nbre_boot_inform = 0; char *forced_inform_parameters[] = { - "Device.RootDataModelVersion", "Device.DeviceInfo.HardwareVersion", "Device.DeviceInfo.SoftwareVersion", "Device.DeviceInfo.ProvisioningCode", "Device.ManagementServer.ParameterKey", DM_CONN_REQ_URL, "Device.ManagementServer.AliasBasedAddressing" + "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) @@ -307,7 +338,7 @@ int cwmp_rpc_acs_prepare_message_inform(struct cwmp *cwmp, struct session *sessi if (!b) goto error; - b = mxmlNewOpaque(b, mix_get_time()); + b = mxmlNewOpaque(b, get_time(time(NULL))); if (!b) goto error; @@ -603,7 +634,7 @@ int cwmp_rpc_acs_prepare_transfer_complete(struct cwmp *cwmp, struct session *se if (!n) goto error; - n = mxmlNewOpaque(n, mix_get_time()); + n = mxmlNewOpaque(n, get_time(time(NULL))); if (!n) goto error; diff --git a/test/cmocka/icwmp_backup_session_unit_test.c b/test/cmocka/icwmp_backup_session_unit_test.c index 241e9c6..6d57ac0 100644 --- a/test/cmocka/icwmp_backup_session_unit_test.c +++ b/test/cmocka/icwmp_backup_session_unit_test.c @@ -19,7 +19,6 @@ #include "backupSession.h" #include "xml.h" #include "config.h" -#include "cwmp_time.h" #include "event.h" static struct cwmp cwmp_main_test = { 0 }; @@ -220,8 +219,8 @@ static void cwmp_backup_session_unit_test(void **state) struct transfer_complete *p; p = icwmp_calloc(1, sizeof(struct transfer_complete)); p->command_key = icwmp_strdup("transfer_complete_key"); - p->start_time = icwmp_strdup(mix_get_time()); - p->complete_time = icwmp_strdup(mix_get_time()); + p->start_time = icwmp_strdup(get_time(time(NULL))); + p->complete_time = icwmp_strdup(get_time(time(NULL))); p->old_software_version = icwmp_strdup("iopsys_img_old"); p->type = TYPE_DOWNLOAD; p->fault_code = FAULT_CPE_NO_FAULT; diff --git a/test/cmocka/icwmp_cli_unit_test.c b/test/cmocka/icwmp_cli_unit_test.c index e15e7d1..3e8713b 100644 --- a/test/cmocka/icwmp_cli_unit_test.c +++ b/test/cmocka/icwmp_cli_unit_test.c @@ -21,7 +21,6 @@ #include "backupSession.h" #include "xml.h" #include "config.h" -#include "cwmp_time.h" #include "event.h" #include "cwmp_uci.h" #include "cwmp_cli.h" diff --git a/ubus.c b/ubus.c index c549088..fbe6bff 100755 --- a/ubus.c +++ b/ubus.c @@ -15,18 +15,20 @@ #include #include #include +#include +#include +#include #include "ubus.h" #include "session.h" #include "log.h" #include "sched_inform.h" -#include "http.h" +#include "cwmp_http.h" #include "download.h" #include "upload.h" #include "cwmp_du_state.h" -#include "netlink.h" +#include "cwmp_uci.h" #include "event.h" -#include "cwmp_time.h" 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_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]) 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; 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_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() { time_t ntime = 0; + if (list_schedule_inform.next != &(list_schedule_inform)) { struct schedule_inform *schedule_inform; schedule_inform = list_entry(list_schedule_inform.next, struct schedule_inform, list); ntime = schedule_inform->scheduled_time; } + if (!ntime || (cwmp_main.session_status.next_retry && ntime > cwmp_main.session_status.next_retry)) { ntime = cwmp_main.session_status.next_retry; } + if (!ntime || (cwmp_main.session_status.next_periodic && ntime > cwmp_main.session_status.next_periodic)) { ntime = cwmp_main.session_status.next_periodic; } + 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"); 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_close_table(&blob_status, c); c = blobmsg_open_table(&blob_status, "last_session"); blobmsg_add_string(&blob_status, "status", cwmp_main.session_status.last_start_time ? arr_session_status[cwmp_main.session_status.last_status] : "N/A"); - blobmsg_add_string(&blob_status, "start_time", cwmp_main.session_status.last_start_time ? mix_get_time_of(cwmp_main.session_status.last_start_time) : "N/A"); - blobmsg_add_string(&blob_status, "end_time", cwmp_main.session_status.last_end_time ? mix_get_time_of(cwmp_main.session_status.last_end_time) : "N/A"); + blobmsg_add_string(&blob_status, "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 ? get_time(cwmp_main.session_status.last_end_time) : "N/A"); blobmsg_close_table(&blob_status, c); c = blobmsg_open_table(&blob_status, "next_session"); blobmsg_add_string(&blob_status, "status", arr_session_status[SESSION_WAITING]); 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_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)); 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]) { grm = blobmsg_data(tb[INFORM_GET_RPC_METHODS]); @@ -274,22 +280,199 @@ static struct ubus_object main_object = { .name = "tr069", .type = &main_object_type, .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) { uloop_init(); - if (netlink_init()) { + if (netlink_init(false)) { CWMP_LOG(ERROR, "netlink initialization failed"); } if (cwmp->conf.ipv6_enable) { - if (netlink_init_v6()) { + if (netlink_init(true)) { CWMP_LOG(ERROR, "netlink initialization failed"); } } + ctx = ubus_connect(cwmp->conf.ubus_socket); if (!ctx) return -1; diff --git a/upload.c b/upload.c index 84d2f47..8c7153d 100644 --- a/upload.c +++ b/upload.c @@ -14,7 +14,6 @@ #include "upload.h" #include "download.h" -#include "cwmp_time.h" #include "datamodel_interface.h" #include "log.h" #include "backupSession.h" @@ -115,7 +114,7 @@ int cwmp_launch_upload(struct upload *pupload, struct transfer_complete **ptrans char *upload_startTime; struct transfer_complete *p; char *name = NULL; - upload_startTime = mix_get_time(); + upload_startTime = get_time(time(NULL)); char file_path[128] = {'\0'}; bkp_session_delete_upload(pupload); bkp_session_save(); @@ -172,7 +171,7 @@ end_upload: p->command_key = pupload->command_key ? strdup(pupload->command_key) : strdup(""); 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; if (error != FAULT_CPE_NO_FAULT) { p->fault_code = error; @@ -213,7 +212,7 @@ void *thread_cwmp_rpc_cpe_upload(void *v) error = FAULT_CPE_DOWNLOAD_FAILURE; 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->fault_code = error; ptransfer_complete->type = TYPE_UPLOAD; diff --git a/xml.c b/xml.c index cdb2327..f64961d 100644 --- a/xml.c +++ b/xml.c @@ -13,8 +13,7 @@ #include "xml.h" #include "log.h" #include "notifications.h" -#include "messages.h" -#include "http.h" +#include "cwmp_http.h" #include "cwmp_zlib.h" 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 *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 \ +"" \ +"" \ + "" \ + "" \ + "" \ + "" \ + "" \ + "" \ +"" + mxml_node_t * /* O - Element node or NULL */ mxmlFindElementOpaque(mxml_node_t *node, /* I - Current 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) { 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; } if (msg_in) {