From e99dc2027940d699ed125fe2e182d94f619e7671 Mon Sep 17 00:00:00 2001 From: Omar Kallel Date: Thu, 30 Mar 2023 14:07:47 +0100 Subject: [PATCH] Ticket #10024: CWMP dual stack --- .gitlab-ci.yml | 2 + docs/api/uci/cwmp.md | 14 --- docs/guide/dual_stack_ip.md | 28 ++++++ gitlab-ci/install-dependencies.sh | 2 +- schemas/uci/cwmp.json | 37 +++---- src/common.c | 98 +++++++++++++++++-- src/common.h | 22 ++++- src/config.c | 25 +++-- src/cwmp.c | 17 +++- src/cwmp_dm/datamodel.c | 6 +- src/cwmp_http.c | 55 +++++++++++ src/http.c | 49 +--------- src/http.h | 2 + src/notifications.c | 4 +- src/session.c | 9 ++ test/cmocka/Makefile | 2 +- .../icwmp_datamodel_interface_unit_test.c | 2 +- test/cmocka/icwmp_soap_msg_unit_test.c | 2 +- test/files/etc/config/cwmp | 3 +- 19 files changed, 257 insertions(+), 122 deletions(-) create mode 100644 docs/guide/dual_stack_ip.md diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a8d1f66..207a500 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,6 +3,8 @@ include: file: '/static-code-analysis.yml' - project: 'docs/portal2/pipeline-template' file: 'MkDocs.gitlab-ci.yml' + rules: + - if: $CI_COMMIT_BRANCH == "devel" variables: DEBUG: 'TRUE' diff --git a/docs/api/uci/cwmp.md b/docs/api/uci/cwmp.md index 555dc18..3b5b4de 100644 --- a/docs/api/uci/cwmp.md +++ b/docs/api/uci/cwmp.md @@ -102,13 +102,6 @@
2000
The retry interval multiplier for session retry session as described in the standard.
- -
ipv6_enable
-
boolean
-
no
-
-
Enables IPv6 in cwmp
-
ssl_capath
string
@@ -231,13 +224,6 @@
Overwrite DeviceId parameter
- -
default_wan_interface
-
string
-
no
-
-
Configure the default wan interface of the device.
-
default_lan_interface
string
diff --git a/docs/guide/dual_stack_ip.md b/docs/guide/dual_stack_ip.md new file mode 100644 index 0000000..b2bf979 --- /dev/null +++ b/docs/guide/dual_stack_ip.md @@ -0,0 +1,28 @@ +# Dual Stack IP in icwmp: + +IPv4/IPv6 switch is done automatically in icwmp client. The CPE checks what's the suitable IP protocol (IPv4 or IPv6) to communicate with the ACS respecting those conditions: + +- IPv6 has the priority in the connection +- if IPv6 is disabled in the CPE side, so the CPE will automatically switch to IPv4 as IP protocol for the communication with the ACS side. +- If the CPE is not able to communicate with the ACS using IPv6, so it switches automatically to IPv4 as an IP protocol. + +This check is done in the beginng of the CWMP session respecting the following algorithm: + +```mermaid +flowchart TD + A[check if IPv6 is enabled in the CPE device] --> B{is enabled?} + B -- no -->C[Select IPv4] + B -- yes -->D[send an empty HTTP Request to the ACS side] + D -->E{get response} + E -- succes response -->F[Select IPv6] + E -- fail response -->C +``` + +While the CPE must prioritize the IPv6, so it starts by checking if IPv6 is working in the CPE, then sends a HTTP message to the ACS side through IPv6 before making the same test in IPv4. + +### Dual Stack configuration + +Two uci options are present to configure dual stack: + +- cwmp.cpe.default_wan_interface: that is the network interface that is used to check the connection with IPv4. +- cwmp.cpe.default_wan6_interface: that is the network interface that is used to check the connection with IPv6. \ No newline at end of file diff --git a/gitlab-ci/install-dependencies.sh b/gitlab-ci/install-dependencies.sh index f696169..08db90a 100755 --- a/gitlab-ci/install-dependencies.sh +++ b/gitlab-ci/install-dependencies.sh @@ -11,7 +11,7 @@ exec_cmd apt install -y mongodb jq uuid-dev exec_cmd apt-get install -y libmxml-dev # install genieacs -exec_cmd npm install -g genieacs@1.2.9 +exec_cmd npm install -g genieacs@1.2.5 ln -sf /root/.nvm/versions/node/v14.16.1/bin/genieacs-cwmp /usr/sbin/genieacs-cwmp ln -sf /root/.nvm/versions/node/v14.16.1/bin/genieacs-fs /usr/sbin/genieacs-fs ln -sf /root/.nvm/versions/node/v14.16.1/bin/genieacs-ui /usr/sbin/genieacs-ui diff --git a/schemas/uci/cwmp.json b/schemas/uci/cwmp.json index 7010c9a..eb94c7f 100644 --- a/schemas/uci/cwmp.json +++ b/schemas/uci/cwmp.json @@ -75,13 +75,6 @@ "default": "2000", "description": "The retry interval multiplier for session retry session as described in the standard." }, - { - "name": "ipv6_enable", - "type": "boolean", - "required": "no", - "default": "", - "description": "Enables IPv6 in cwmp" - }, { "name": "ssl_capath", "type": "string", @@ -110,13 +103,6 @@ "default": "", "description": "the **url** of ACS server received from the DHCP server via Option 43. This parameter is automatically updated by daemon, When **'dhcp_discovery'** option is enabled." }, - { - "name": "ip_version", - "type": "string", - "required": "no", - "default": "", - "description": "ip_version of ConnectionRequestURL" - }, { "name": "get_rpc_methods", "type": "boolean", @@ -187,20 +173,27 @@ "default": "", "description": "Overwrite DeviceId parameter" }, - { - "name": "default_wan_interface", - "type": "string", - "required": "no", - "default": "", - "description": "Configure the default wan interface of the device." - }, { "name": "default_lan_interface", "type": "string", "required": "no", - "default": "", + "default": "lan", "description": "Configure the default lan interface of the device." }, + { + "name": "default_wan_interface", + "type": "string", + "required": "no", + "default": "wan", + "description": "Configure the default wan interface that will be used for IPv4 connection." + }, + { + "name": "default_wan6_interface", + "type": "string", + "required": "no", + "default": "wan6", + "description": "Configure the default wan interface that will be used for IPv6 connection." + }, { "name": "log_to_console", "type": "string", diff --git a/src/common.c b/src/common.c index 0f08130..8bb7e9e 100755 --- a/src/common.c +++ b/src/common.c @@ -755,25 +755,35 @@ void ubus_network_interface_callback(struct ubus_request *req __attribute__((unu // Only update the interface if its not empty if (CWMP_STRLEN(l3_device)) { - cwmp_main->conf.interface = strdup(l3_device); + cwmp_main->net.interface = strdup(l3_device); } - CWMP_LOG(DEBUG, "CWMP IFACE - interface: %s", cwmp_main->conf.interface); + CWMP_LOG(DEBUG, "CWMP IFACE - interface: %s", cwmp_main->net.interface); } -int get_connection_interface(char *iface) +void set_uci_connection_interface(char* interface) { - if (iface == NULL) - return -1; + if (interface == NULL) { + CWMP_LOG(WARNING, "%s interface is NULL", __FUNCTION__); + return; + } + cwmp_uci_set_varstate_value("cwmp", "cpe", "interface", interface); + cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); +} +int get_connection_interface() +{ struct blob_buf b = { 0 }; memset(&b, 0, sizeof(struct blob_buf)); blob_buf_init(&b, 0); char ubus_obj[100] = {0}; - snprintf(ubus_obj, sizeof(ubus_obj), "network.interface.%s", iface); + if (cwmp_main->net.ipv6_status) + snprintf(ubus_obj, sizeof(ubus_obj), "network.interface.%s", cwmp_main->conf.default_wan6_iface); + else + snprintf(ubus_obj, sizeof(ubus_obj), "network.interface.%s", cwmp_main->conf.default_wan_iface); - FREE(cwmp_main->conf.interface); + FREE(cwmp_main->net.interface); int e = icwmp_ubus_invoke(ubus_obj, "status", b.head, ubus_network_interface_callback, NULL); blob_buf_free(&b); @@ -781,12 +791,84 @@ int get_connection_interface(char *iface) if (e != 0) { return -1; } - if (cwmp_main->conf.interface == NULL) { + if (cwmp_main->net.interface == NULL) { return -1; } + set_uci_connection_interface(cwmp_main->net.interface); return CWMP_OK; } +int get_connection_parameters() +{ + int error = get_connection_interface(); + if (error != CWMP_OK) { + CWMP_LOG(DEBUG, "Failed to get interface [%s] details", cwmp_main->net.connection_wan_iface); + return error; + } + + error = icwmp_check_http_connection(); + if (error != CWMP_OK || !cwmp_main->net.connection_wan_iface) { + CWMP_LOG(DEBUG, "Failed to check http connection"); + return error; + } + return CWMP_OK; +} + +void ubus_network_interface_status_callback(struct ubus_request *req __attribute__((unused)), int type __attribute__((unused)), struct blob_attr *msg) +{ + bool *up = (bool *)req->priv; + + const struct blobmsg_policy p[1] = { { "up", BLOBMSG_TYPE_BOOL } }; + struct blob_attr *tb[1] = { NULL }; + blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg)); + if (tb[0] != NULL) + *up = blobmsg_get_bool(tb[0]); +} + +bool check_ipv6_enabled() +{ + bool up=false; + struct blob_buf b = { 0 }; + memset(&b, 0, sizeof(struct blob_buf)); + blob_buf_init(&b, 0); + + char ubus_network_interface[512]; + snprintf(ubus_network_interface, sizeof(ubus_network_interface), "network.interface.%s", cwmp_main->conf.default_wan6_iface); + icwmp_ubus_invoke(ubus_network_interface, "status", b.head, ubus_network_interface_status_callback, &up); + + blob_buf_free(&b); + + return up; +} + +bool check_connection_attributes_change() +{ + cwmp_uci_reinit(); + + char *actual_wan_interface = NULL, *actual_wan6_interface = NULL; + uci_get_value("cwmp.cpe.default_wan_interface", &actual_wan_interface); + uci_get_value("cwmp.cpe.default_wan6_interface", &actual_wan6_interface); + bool wan_interface_changed = CWMP_STRCMP(actual_wan_interface, cwmp_main->conf.default_wan_iface); + bool wan6_interface_changed = CWMP_STRCMP(actual_wan6_interface, cwmp_main->conf.default_wan_iface); + + if (wan_interface_changed) + { + FREE(cwmp_main->conf.default_wan_iface); + cwmp_main->conf.default_wan_iface = strdup(actual_wan_interface); + } + if (wan6_interface_changed) + { + FREE(cwmp_main->conf.default_wan6_iface); + cwmp_main->conf.default_wan6_iface = strdup(actual_wan6_interface); + } + FREE(actual_wan_interface); + FREE(actual_wan6_interface); + bool actual_ipv6_status = check_ipv6_enabled(); + bool ipv6_status_changed = (actual_ipv6_status != cwmp_main->net.ipv6_status); + cwmp_main->net.ipv6_status = actual_ipv6_status; + return ipv6_status_changed || wan_interface_changed || wan6_interface_changed; +} + char *get_time(time_t t_time) { static char local_time[32] = {0}; diff --git a/src/common.h b/src/common.h index 885498f..ebb1c2a 100644 --- a/src/common.h +++ b/src/common.h @@ -22,6 +22,8 @@ #include #include #include +#include +#include #ifndef FREE #define FREE(x) do { if(x) {free(x); x = NULL;} } while (0) @@ -31,7 +33,7 @@ #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_STRCMP(S1, S2) ((S1 != NULL && S2 != NULL) ? strcmp(S1, S2) : (S1 == S2)) #define CWMP_STRDUP(S1) ((S1 != NULL) ? strdup(S1) : NULL) #define CWMP_STRLEN(S1) ((S1 != NULL) ? strlen(S1) : 0) @@ -87,6 +89,13 @@ typedef struct env { long int max_firmware_size; } env; +struct connection { + char *connection_wan_iface; + char *interface; + int ip_resolve; + bool ipv6_status; +}; + typedef struct config { char *acsurl; char *acs_userid; @@ -97,17 +106,16 @@ typedef struct config { char *custom_notify_json; char *ip; char *ipv6; - char *interface; char *ubus_socket; - char *default_wan_iface; char *connection_request_path; char *auto_tc_transfer_type; char *auto_tc_result_type; char *auto_tc_file_type; - char *auto_cdu_oprt_type; char *auto_cdu_result_type; char *auto_cdu_fault_code; + char *default_wan_iface; + char *default_wan6_iface; int connection_request_port; int period; int periodic_notify_interval; @@ -124,7 +132,6 @@ typedef struct config { bool periodic_enable; bool periodic_notify_enable; bool insecure_enable; - bool ipv6_enable; bool heart_beat_enable; bool acs_getrpc; bool auto_tc_enable; @@ -153,6 +160,7 @@ typedef struct cwmp { struct env env; struct config conf; struct deviceid deviceid; + struct connection net; struct session *session; bool cwmp_cr_event; bool init_complete; @@ -606,6 +614,10 @@ bool icwmp_validate_int_in_range(char *arg, int min, int max); char *string_to_hex(const unsigned char *str, size_t size); int copy_file(char *source_file, char *target_file); int get_connection_interface(); +int get_connection_parameters(); +int icwmp_check_http_connection(); +bool check_ipv6_enabled(); +bool check_connection_attributes_change(); char *get_time(time_t t_time); bool is_obj_excluded(const char *object_name); bool is_reload_parameter(const char *object_name); diff --git a/src/config.c b/src/config.c index 84e807e..cd58d77 100755 --- a/src/config.c +++ b/src/config.c @@ -48,6 +48,7 @@ static void config_get_cpe_elements(struct uci_section *s) UCI_CPE_ENABLE_SYSLOG, UCI_CPE_AMD_VERSION, UCI_CPE_DEFAULT_WAN_IFACE, + UCI_CPE_DEFAULT_WAN6_IFACE, __MAX_NUM_UCI_CPE_ATTRS, }; @@ -61,6 +62,7 @@ static void config_get_cpe_elements(struct uci_section *s) { .name = "log_to_syslog", .type = UCI_TYPE_STRING }, { .name = "amd_version", .type = UCI_TYPE_STRING }, { .name = "default_wan_interface", .type = UCI_TYPE_STRING }, + { .name = "default_wan6_interface", .type = UCI_TYPE_STRING }, }; struct uci_option *cpe_tb[__MAX_NUM_UCI_CPE_ATTRS] = {0}; @@ -91,18 +93,23 @@ static void config_get_cpe_elements(struct uci_section *s) } cwmp_main->conf.supported_amd_version = cwmp_main->conf.amd_version; CWMP_LOG(DEBUG, "CWMP CONFIG - amendement version: %d", cwmp_main->conf.amd_version); - if (cpe_tb[UCI_CPE_DEFAULT_WAN_IFACE]) { + + if (cpe_tb[UCI_CPE_DEFAULT_WAN_IFACE]) cwmp_main->conf.default_wan_iface = strdup(get_value_from_uci_option(cpe_tb[UCI_CPE_DEFAULT_WAN_IFACE])); - } else { + else cwmp_main->conf.default_wan_iface = strdup("wan"); - } CWMP_LOG(DEBUG, "CWMP CONFIG - default wan interface: %s", cwmp_main->conf.default_wan_iface); + + if (cpe_tb[UCI_CPE_DEFAULT_WAN6_IFACE]) + cwmp_main->conf.default_wan6_iface = strdup(get_value_from_uci_option(cpe_tb[UCI_CPE_DEFAULT_WAN6_IFACE])); + else + cwmp_main->conf.default_wan6_iface = strdup("wan6"); + CWMP_LOG(DEBUG, "CWMP CONFIG - default wan ipv6 interface: %s", cwmp_main->conf.default_wan6_iface); } static void config_get_acs_elements(struct uci_section *s) { enum { - UCI_ACS_IPV6_ENABLE, UCI_ACS_SSL_CAPATH, HTTP_DISABLE_100CONTINUE, UCI_ACS_INSECURE_ENABLE, @@ -110,7 +117,6 @@ static void config_get_acs_elements(struct uci_section *s) }; const struct uci_parse_option acs_opts[] = { - { .name = "ipv6_enable", .type = UCI_TYPE_STRING }, { .name = "ssl_capath", .type = UCI_TYPE_STRING }, { .name = "http_disable_100continue", .type = UCI_TYPE_STRING }, { .name = "insecure_enable", .type = UCI_TYPE_STRING }, @@ -120,9 +126,6 @@ static void config_get_acs_elements(struct uci_section *s) memset(acs_tb, 0, sizeof(acs_tb)); uci_parse_section(s, acs_opts, __MAX_NUM_UCI_ACS_ATTRS, acs_tb); - cwmp_main->conf.ipv6_enable = uci_str_to_bool(get_value_from_uci_option(acs_tb[UCI_ACS_IPV6_ENABLE])); - CWMP_LOG(DEBUG, "CWMP CONFIG - ipv6 enable: %d", cwmp_main->conf.ipv6_enable); - cwmp_main->conf.acs_ssl_capath = CWMP_STRDUP(get_value_from_uci_option(acs_tb[UCI_ACS_SSL_CAPATH])); CWMP_LOG(DEBUG, "CWMP CONFIG - acs ssl cpath: %s", cwmp_main->conf.acs_ssl_capath ? cwmp_main->conf.acs_ssl_capath : ""); @@ -188,12 +191,6 @@ int get_global_config() } FREE(value); - error = get_connection_interface(cwmp_main->conf.default_wan_iface); - if (error != CWMP_OK) { - CWMP_LOG(DEBUG, "Failed to get interface [%s] details", cwmp_main->conf.default_wan_iface); - return error; - } - bool discovery_enable = false; error = uci_get_value(UCI_DHCP_DISCOVERY_PATH, &value); if (error == CWMP_OK && value != NULL) { diff --git a/src/cwmp.c b/src/cwmp.c index 6073fb5..fdd43ce 100644 --- a/src/cwmp.c +++ b/src/cwmp.c @@ -205,6 +205,8 @@ static int cwmp_init() cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp)); cwmp_main->init_complete = false; + cwmp_main->net.interface = NULL; + cwmp_main->net.connection_wan_iface = NULL; error = get_preinit_config(); if (error) { return error; @@ -276,6 +278,13 @@ static int cwmp_init() cwmp_main->cwmp_period = 0; cwmp_main->cwmp_periodic_time = 0; cwmp_main->cwmp_periodic_enable = false; + sleep(15); + cwmp_main->net.ipv6_status = check_ipv6_enabled(); + error = get_connection_parameters(); + if (error != CWMP_OK) { + CWMP_LOG(DEBUG, "Failed to get connection parameters"); + return error; + } return CWMP_OK; } @@ -293,12 +302,12 @@ static void cwmp_free() FREE(cwmp_main->conf.acsurl); FREE(cwmp_main->conf.acs_userid); FREE(cwmp_main->conf.acs_passwd); - FREE(cwmp_main->conf.interface); + FREE(cwmp_main->net.interface); FREE(cwmp_main->conf.cpe_userid); FREE(cwmp_main->conf.cpe_passwd); FREE(cwmp_main->conf.ubus_socket); FREE(cwmp_main->conf.connection_request_path); - FREE(cwmp_main->conf.default_wan_iface); + FREE(cwmp_main->net.connection_wan_iface); FREE(cwmp_main->conf.custom_notify_json); FREE(cwmp_main->conf.auto_cdu_fault_code); FREE(cwmp_main->conf.auto_cdu_oprt_type); @@ -306,6 +315,8 @@ static void cwmp_free() FREE(cwmp_main->conf.auto_tc_file_type); FREE(cwmp_main->conf.auto_tc_result_type); FREE(cwmp_main->conf.auto_tc_transfer_type); + FREE(cwmp_main->conf.default_wan_iface); + FREE(cwmp_main->conf.default_wan6_iface); FREE(nonce_key); clean_list_param_notify(); bkp_tree_clean(); @@ -352,7 +363,7 @@ static void configure_var_state() cwmp_uci_add_section_with_specific_name("cwmp", "acs", "acs", UCI_VARSTATE_CONFIG); cwmp_uci_add_section_with_specific_name("cwmp", "cpe", "cpe", UCI_VARSTATE_CONFIG); - get_firewall_zone_name_by_wan_iface(cwmp_main->conf.default_wan_iface, &zone_name); + get_firewall_zone_name_by_wan_iface(cwmp_main->net.connection_wan_iface, &zone_name); cwmp_uci_set_varstate_value("cwmp", "acs", "zonename", zone_name ? zone_name : "wan"); cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); diff --git a/src/cwmp_dm/datamodel.c b/src/cwmp_dm/datamodel.c index ff63ee2..8949d95 100644 --- a/src/cwmp_dm/datamodel.c +++ b/src/cwmp_dm/datamodel.c @@ -457,10 +457,10 @@ static void get_management_ip_port(char **listen_addr) { char *ip = NULL, *port = NULL, *interface = NULL, *if_name = NULL, *version = NULL; - dmuci_get_option_value_string("cwmp", "cpe", "default_wan_interface", &interface); - dmuci_get_option_value_string("cwmp", "cpe", "interface", &if_name); - dmuci_get_option_value_string("cwmp", "acs", "ip_version", &version); + dmuci_get_option_value_string_varstate("cwmp", "cpe", "interface", &if_name); + dmuci_get_option_value_string_varstate("cwmp", "acs", "ip_version", &version); dmuci_get_option_value_string("cwmp", "cpe", "port", &port); + dmuci_get_option_value_string("cwmp", "cpe", *version == '6' ? "default_wan6_interface" : "default_wan_interface", &interface); if (network_get_ipaddr(interface, *version == '6' ? 6 : 4, &ip) == -1) { if (if_name[0] == '\0') diff --git a/src/cwmp_http.c b/src/cwmp_http.c index 94a5c67..0e947c7 100644 --- a/src/cwmp_http.c +++ b/src/cwmp_http.c @@ -13,6 +13,7 @@ #include "cwmp_http.h" #include "http.h" #include "log.h" +#include "cwmp_uci.h" struct uloop_fd http_event6; @@ -49,3 +50,57 @@ void http_server_stop(void) { pthread_join(http_cr_server_thread, NULL); } + +void set_http_ip_resolve(int resolve) +{ + cwmp_uci_set_varstate_value("cwmp", "acs", "ip_version", (resolve == CURL_IPRESOLVE_V6) ? "6" : "4"); + cwmp_commit_package("cwmp", UCI_VARSTATE_CONFIG); + FREE(cwmp_main->net.connection_wan_iface); + cwmp_main->net.connection_wan_iface = strdup((resolve == CURL_IPRESOLVE_V6) ? cwmp_main->conf.default_wan6_iface : cwmp_main->conf.default_wan_iface); + cwmp_main->net.ip_resolve = resolve; +} + +int icwmp_check_http_connection() +{ + if (!cwmp_main->net.ipv6_status) { + set_http_ip_resolve(CURL_IPRESOLVE_V4); + return CWMP_OK; + } + long resolve = CURL_IPRESOLVE_V6; + while(1) { + CURL *c = curl_easy_init(); + if(c) { + CURLcode ret; + curl_easy_setopt(c, CURLOPT_FAILONERROR, true); + curl_easy_setopt(c, CURLOPT_URL, cwmp_main->conf.acsurl); + curl_easy_setopt(c, CURLOPT_CONNECT_ONLY, 1L); + curl_easy_setopt(c, CURLOPT_IPRESOLVE, resolve); + curl_easy_setopt(c, CURLOPT_INTERFACE, cwmp_main->net.interface); + ret = curl_easy_perform(c); + if(ret == CURLE_OK) { + int tmp = 1; + char *ip = NULL; + curl_easy_getinfo(c, CURLINFO_PRIMARY_IP, &ip); + if (ip) { + unsigned char buf[sizeof(struct in6_addr)]; + tmp = inet_pton(AF_INET, ip, buf); + } + + if (tmp) + set_http_ip_resolve(CURL_IPRESOLVE_V4); + else + set_http_ip_resolve(CURL_IPRESOLVE_V6); + curl_easy_cleanup(c); + return CWMP_OK; + } + curl_easy_cleanup(c); + } + if (resolve == CURL_IPRESOLVE_V6) + resolve = CURL_IPRESOLVE_V4; + else if (resolve == CURL_IPRESOLVE_V4) + resolve = CURL_IPRESOLVE_WHATEVER; + else + break; + } + return -1; +} diff --git a/src/http.c b/src/http.c index 0536ef0..0c04df6 100644 --- a/src/http.c +++ b/src/http.c @@ -10,7 +10,6 @@ * See LICENSE file for license related information. * */ -#include #include #include #include @@ -42,58 +41,17 @@ void http_set_timeout(void) int icwmp_http_client_init() { - char *dhcp_dis = NULL; - char *acs_var_stat = NULL; - - uci_get_value(UCI_DHCP_DISCOVERY_PATH, &dhcp_dis); - - if (dhcp_dis && cwmp_main->retry_count_session > 0 && strcmp(dhcp_dis, "enable") == 0) { - uci_get_state_value(UCI_DHCP_ACS_URL, &acs_var_stat); - if (acs_var_stat) { - if (icwmp_asprintf(&http_c.url, "%s", acs_var_stat) == -1) { - free(acs_var_stat); - FREE(dhcp_dis); - return -1; - } - } else { - if (cwmp_main->conf.acsurl == NULL || icwmp_asprintf(&http_c.url, "%s", cwmp_main->conf.acsurl) == -1) { - FREE(dhcp_dis); - return -1; - } - } - } else { - if (cwmp_main->conf.acsurl == NULL || icwmp_asprintf(&http_c.url, "%s", cwmp_main->conf.acsurl) == -1) { - FREE(dhcp_dis); - return -1; - } + if (cwmp_main->conf.acsurl == NULL || icwmp_asprintf(&http_c.url, "%s", cwmp_main->conf.acsurl) == -1) { + return -1; } - if (dhcp_dis) - free(dhcp_dis); - CWMP_LOG(INFO, "ACS url: %s", http_c.url); - /* TODO debug ssl config from freecwmp*/ - curl_global_init(CURL_GLOBAL_SSL); curl = curl_easy_init(); if (!curl) return -1; - if (cwmp_main->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_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; } @@ -159,6 +117,7 @@ static void http_set_connection_options() curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5L); curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL); curl_easy_setopt(curl, CURLOPT_NOBODY, 0); + curl_easy_setopt(curl, CURLOPT_IPRESOLVE, cwmp_main->net.ip_resolve); #ifdef DEVEL curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); #endif @@ -166,7 +125,7 @@ static void http_set_connection_options() curl_easy_setopt(curl, CURLOPT_COOKIEFILE, fc_cookies); curl_easy_setopt(curl, CURLOPT_COOKIEJAR, fc_cookies); - curl_easy_setopt(curl, CURLOPT_INTERFACE, cwmp_main->conf.interface); + curl_easy_setopt(curl, CURLOPT_INTERFACE, cwmp_main->net.interface); } static void http_set_header_list_options() diff --git a/src/http.h b/src/http.h index 09fc7f9..3b5b430 100644 --- a/src/http.h +++ b/src/http.h @@ -13,6 +13,8 @@ #ifndef _FREECWMP_HTTP_H__ #define _FREECWMP_HTTP_H__ +#include + #include "common.h" extern char *fc_cookies; diff --git a/src/notifications.c b/src/notifications.c index adadcbd..b31e666 100644 --- a/src/notifications.c +++ b/src/notifications.c @@ -42,8 +42,8 @@ char *default_active_notifications_parameters[] = { }; char *forced_notifications_parameters[] = { - "Device.DeviceInfo.SoftwareVersion", - "Device.DeviceInfo.ProvisioningCode" + "Device.DeviceInfo.SoftwareVersion", + "Device.DeviceInfo.ProvisioningCode" }; /* diff --git a/src/session.c b/src/session.c index 4eeef26..e616735 100644 --- a/src/session.c +++ b/src/session.c @@ -32,6 +32,7 @@ #include "heartbeat.h" #include "sched_inform.h" #include "cwmp_du_state.h" +#include "cwmp_http.h" pthread_mutex_t cwmp_session_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -335,6 +336,14 @@ void start_cwmp_session() if (cwmp_main->session->session_status.last_status == SESSION_FAILURE) cwmp_config_load(); + + if (check_connection_attributes_change()) { + if (get_connection_parameters() != CWMP_OK || cwmp_stop) { + CWMP_LOG(INFO, "cwmp fails to get connection parameters"); + return; + } + } + /* * Value changes */ diff --git a/test/cmocka/Makefile b/test/cmocka/Makefile index 30869d6..09f75f8 100644 --- a/test/cmocka/Makefile +++ b/test/cmocka/Makefile @@ -33,4 +33,4 @@ all: libunit ${UNIT_TESTS} clean: rm -fv *.o libicwmp.so ${UNIT_TESTS} -.PHONY: clean unit-test \ No newline at end of file +.PHONY: clean unit-test diff --git a/test/cmocka/icwmp_datamodel_interface_unit_test.c b/test/cmocka/icwmp_datamodel_interface_unit_test.c index d43d286..4749258 100644 --- a/test/cmocka/icwmp_datamodel_interface_unit_test.c +++ b/test/cmocka/icwmp_datamodel_interface_unit_test.c @@ -50,12 +50,12 @@ static int dm_iface_unit_tests_clean(void **state) FREE(cwmp_main->conf.acsurl); FREE(cwmp_main->conf.acs_userid); FREE(cwmp_main->conf.acs_passwd); - FREE(cwmp_main->conf.interface); FREE(cwmp_main->conf.cpe_userid); FREE(cwmp_main->conf.cpe_passwd); FREE(cwmp_main->conf.ubus_socket); FREE(cwmp_main->conf.connection_request_path); FREE(cwmp_main->conf.default_wan_iface); + FREE(cwmp_main->conf.default_wan6_iface); FREE(cwmp_main->conf.custom_notify_json); cwmp_free_all_list_param_fault(&faults_array); cwmp_free_all_dm_parameter_list(&list_set_param_value); diff --git a/test/cmocka/icwmp_soap_msg_unit_test.c b/test/cmocka/icwmp_soap_msg_unit_test.c index bd12819..25f731e 100644 --- a/test/cmocka/icwmp_soap_msg_unit_test.c +++ b/test/cmocka/icwmp_soap_msg_unit_test.c @@ -50,12 +50,12 @@ static void clean_config() FREE(cwmp_main->conf.acsurl); FREE(cwmp_main->conf.acs_userid); FREE(cwmp_main->conf.acs_passwd); - FREE(cwmp_main->conf.interface); FREE(cwmp_main->conf.cpe_userid); FREE(cwmp_main->conf.cpe_passwd); FREE(cwmp_main->conf.ubus_socket); FREE(cwmp_main->conf.connection_request_path); FREE(cwmp_main->conf.default_wan_iface); + FREE(cwmp_main->conf.default_wan6_iface); } static void clean_name_space() diff --git a/test/files/etc/config/cwmp b/test/files/etc/config/cwmp index 7ef4ab4..515da45 100644 --- a/test/files/etc/config/cwmp +++ b/test/files/etc/config/cwmp @@ -11,14 +11,13 @@ config acs 'acs' option retry_min_wait_interval '5' #­ possible configs interval :[1000:65535] option retry_interval_multiplier '2000' - option ipv6_enable '0' - option ip_version '4' config cpe 'cpe' option enable '1' option interface 'eth0' option default_wan_interface 'wan' + option default_wan6_interface 'wan6' option log_to_console 'disable' option log_to_syslog 'disable' option log_to_file 'enable'