diff --git a/README.md b/README.md
index 26ea3e3..28f1c4a 100644
--- a/README.md
+++ b/README.md
@@ -30,6 +30,8 @@ config cpe 'cpe'
option default_wan_interface 'wan'
option userid 'iopsys'
option exec_download '0'
+ list allowed_cr_ip '10.5.3.14/32'
+ list allowed_cr_ip '20.2.1.0/24'
config lwn 'lwn'
option enable '1'
diff --git a/bbf_plugin/CMakeLists.txt b/bbf_plugin/CMakeLists.txt
index 9ee56f1..42c01b0 100644
--- a/bbf_plugin/CMakeLists.txt
+++ b/bbf_plugin/CMakeLists.txt
@@ -4,6 +4,7 @@ PROJECT(libcwmpdm.so)
ADD_DEFINITIONS(-Wall -Werror -Wformat -g)
ADD_DEFINITIONS(-D_GNU_SOURCE)
+ADD_DEFINITIONS(-DBBF_VENDOR_PREFIX="${BBF_VENDOR_PREFIX}")
# Compile and install libcwmpdm.so
ADD_LIBRARY(cwmpdm SHARED datamodel.c)
diff --git a/bbf_plugin/datamodel.c b/bbf_plugin/datamodel.c
index 0281fc5..cc9a79a 100644
--- a/bbf_plugin/datamodel.c
+++ b/bbf_plugin/datamodel.c
@@ -939,6 +939,40 @@ static int set_manageable_device_notification_limit(char *refparam, struct dmctx
return 0;
}
+#ifdef ICWMP_ENABLE_VENDOR_EXTN
+static int get_allowed_cr_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+ struct uci_list *uci_opt_list = NULL;
+
+ dmuci_get_option_value_list("cwmp", "cpe", "allowed_cr_ip", &uci_opt_list);
+ *value = dmuci_list_to_string(uci_opt_list, ",");
+ return 0;
+}
+
+static int set_allowed_cr_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+ size_t length, i;
+ int ret = 0;
+ char **arr;
+
+ switch (action) {
+ case VALUECHECK:
+ if (bbfdm_validate_string(ctx, value, -1, -1, NULL, NULL))
+ ret = FAULT_9007;
+ break;
+ case VALUESET:
+ dmuci_delete("cwmp", "cpe", "allowed_cr_ip", NULL);
+ arr = strsplit(value, ",", &length);
+
+ for (i = 0; i < length; i++) {
+ dmuci_add_list_value("cwmp", "cpe", "allowed_cr_ip", arr[i]);
+ }
+ break;
+ }
+ return ret;
+}
+#endif
+
static int get_heart_beat_policy_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
*value = dmuci_get_option_value_fallback_def("cwmp", "acs", "heartbeat_enable", "0");
@@ -1419,6 +1453,9 @@ DMLEAF tManagementServerParams[] = {
{"ManageableDeviceNumberOfEntries", &DMREAD, DMT_UNINT, get_manageable_device_number_of_entries, NULL, BBFDM_CWMP},
{"DefaultActiveNotificationThrottle", &DMWRITE, DMT_UNINT, get_default_active_notification_throttle, set_default_active_notification_throttle, BBFDM_CWMP},
{"ManageableDeviceNotificationLimit", &DMWRITE, DMT_UNINT, get_manageable_device_notification_limit, set_manageable_device_notification_limit, BBFDM_CWMP},
+#ifdef ICWMP_ENABLE_VENDOR_EXTN
+{BBF_VENDOR_PREFIX"AllowedConnectionRequestIP", &DMWRITE, DMT_STRING, get_allowed_cr_ip, set_allowed_cr_ip, BBFDM_CWMP},
+#endif
{0}
};
diff --git a/docs/api/uci/cwmp.md b/docs/api/uci/cwmp.md
index bf00ff8..c632af7 100644
--- a/docs/api/uci/cwmp.md
+++ b/docs/api/uci/cwmp.md
@@ -917,10 +917,10 @@
|
- incoming_rule
+ allowed_cr_ip
|
- string
+ list
|
no
@@ -929,7 +929,7 @@
|
- This configure firewall rules. Allowed values <IP_Only/Port_Only/IP_Port>. IP_Only means only acs ip as source ip used for firewall input rule, Port_Only means only destination port will be used and IP_Port or empty value meaning both ip and port will be used for firewall input rule.
+ List of subnets or ips from where incoming connection requests are allowed e.g 10.2.1.0/24 or 10.2.1.5/32. So connection requests are allowed with src IP in range of <10.2.1.1 - 10.2.1.254> or from 10.2.1.5 and with dest-port same as <port> Empty value means only destination port will be used and connection requests on the valid port will be accepted irrespective of any src IP.
|
diff --git a/gitlab-ci/shared.sh b/gitlab-ci/shared.sh
index fb4d7a8..13d01c0 100644
--- a/gitlab-ci/shared.sh
+++ b/gitlab-ci/shared.sh
@@ -109,6 +109,7 @@ function build_icwmp()
{
COV_CFLAGS='-g -O0 -fprofile-arcs -ftest-coverage'
COV_LDFLAGS='--coverage'
+ VENDOR_PREFIX='X_IOWRT_EU_'
BINP="${PWD}"
# clean icwmp
@@ -117,7 +118,7 @@ function build_icwmp()
# compile icwmp
mkdir -p build
cd build
- cmake ../ -DCMAKE_C_FLAGS="$COV_CFLAGS " -DCMAKE_EXE_LINKER_FLAGS="$COV_LDFLAGS" -DCMAKE_INSTALL_PREFIX=/
+ cmake ../ -DCMAKE_C_FLAGS="$COV_CFLAGS -DICWMP_ENABLE_VENDOR_EXTN" -DCMAKE_EXE_LINKER_FLAGS="$COV_LDFLAGS" -DCMAKE_INSTALL_PREFIX=/ -DBBF_VENDOR_PREFIX="$VENDOR_PREFIX"
exec_cmd make
echo "installing icwmpd binary and libcwmpdm.so library"
diff --git a/schemas/uci/cwmp.json b/schemas/uci/cwmp.json
index 5abeafd..fb38700 100644
--- a/schemas/uci/cwmp.json
+++ b/schemas/uci/cwmp.json
@@ -276,7 +276,14 @@
"type": "uinteger",
"required": "no",
"default": "7547",
- "description": "The port used for connection request."
+ "description": "The port allowed for incoming connection request."
+ },
+ {
+ "name": "allowed_cr_ip",
+ "type": "list",
+ "required": "no",
+ "default": null,
+ "description": "List of subnets or ips from where incoming connection requests are allowed e.g 10.2.1.0/24 or 10.2.1.5/32. So connection requests are allowed with SRC IP in range of '10.2.1.1 - 10.2.1.254' or from 10.2.1.5 and with dest port same as port. Empty value means only destination port will be used and connection requests on the valid port will be accepted irrespective of any src IP."
},
{
"name": "path",
@@ -285,6 +292,13 @@
"default": "/",
"description": "CPE Connection request URI path"
},
+ {
+ "name": "instance_mode",
+ "type": "string",
+ "required": "no",
+ "default": "InstanceNumber",
+ "description": "Configure the instance mode to use. Supported instance modes are : InstanceNumber and InstanceAlias."
+ },
{
"name": "provisioning_code",
"type": "string",
@@ -299,13 +313,6 @@
"default": "5",
"description": "Configure the amendment version to use."
},
- {
- "name": "instance_mode",
- "type": "string",
- "required": "no",
- "default": "InstanceNumber",
- "description": "Configure the instance mode to use. Supported instance modes are : InstanceNumber and InstanceNumber."
- },
{
"name": "session_timeout",
"type": "uinteger",
@@ -355,13 +362,6 @@
"default": "",
"description": "Define absolute path of the JSON containing parameters on which notification get enabled as per the definition. See readme for examples."
},
- {
- "name": "incoming_rule",
- "type": "string",
- "required": "no",
- "default": "",
- "description": "This configure firewall rules. Allowed values . IP_Only means only acs ip as source ip used for firewall input rule, Port_Only means only destination port will be used and IP_Port or empty value meaning both ip and port will be used for firewall input rule."
- },
{
"name": "force_ipv4",
"type": "boolean",
diff --git a/src/common.c b/src/common.c
index 7a9b640..2680bf6 100755
--- a/src/common.c
+++ b/src/common.c
@@ -1364,3 +1364,12 @@ void stop_service(void)
icwmp_ubus_invoke("service", "state", bb.head, NULL, NULL);
blob_buf_free(&bb);
}
+
+void apply_allowed_cr_ip_port(void)
+{
+ // Flawfinder: ignore
+ FILE *pp = popen(FIREWALL_CWMP, "r");
+ if (pp) {
+ pclose(pp);
+ }
+}
diff --git a/src/common.h b/src/common.h
index 8bb702b..e9252d6 100644
--- a/src/common.h
+++ b/src/common.h
@@ -75,7 +75,7 @@
#define ICWMP_TMP_PATH "/tmp/icwmp"
#define VENDOR_LOG_SCRIPT "/etc/icwmpd/vendor_log.sh"
-#define FIREWALL_CWMP "/etc/icwmpd/firewall.cwmp"
+#define FIREWALL_CWMP "/etc/icwmpd/firewall.cwmp cwmp"
#define DM_PPP_INTERFACE_PATH "Device\\.PPP\\.Interface\\."
#define DM_IP_INTERFACE_PATH "Device\\.IP\\.Interface\\."
#define DEFAULT_CR_TIMEOUT 5 /* In Seconds */
@@ -135,6 +135,7 @@ typedef struct config {
bool acs_getrpc;
bool auto_tc_enable;
bool auto_cdu_enable;
+ bool cr_ip_port_change;
int retry_min_wait_interval;
int retry_interval_multiplier;
@@ -172,6 +173,7 @@ typedef struct config {
char default_wan_iface[BUF_SIZE_32];
char cpe_client_cert[BUF_SIZE_256];
char cpe_client_key[BUF_SIZE_256];
+ char valid_cr_ip[BUF_SIZE_2048];
} config;
struct deviceid {
@@ -182,12 +184,6 @@ struct deviceid {
char softwareversion[BUF_SIZE_64];
};
-enum firewall_cr_policy {
- CR_POLICY_Port_Only = 0,
- CR_POLICY_IP_Only,
- CR_POLICY_BOTH,
-};
-
typedef struct cwmp {
struct env env;
struct config conf;
@@ -227,7 +223,6 @@ typedef struct cwmp {
struct ubus_event_handler *ev;
struct ubus_event_handler *intf_ev;
bool throttle_session_triggered;
- enum firewall_cr_policy cr_policy;
bool acs_changed;
int curr_delay_reboot;
time_t curr_schedule_reboot;
@@ -650,7 +645,6 @@ bool folder_exists(const char *path);
bool file_exists(const char *path);
void cwmp_reboot(const char *command_key);
void cwmp_factory_reset();
-void get_firewall_zone_name_by_wan_iface(char *if_wan, char **zone_name);
int download_file(const char *file_path, const char *url, const char *username, const char *password, const char *interface);
unsigned int get_file_size(const char *file_name);
int cwmp_check_image();
@@ -706,4 +700,5 @@ bool end_session_reload_service(const char *service);
bool end_session_reload_pending(void);
void add_path_list(struct list_head *list, char *str);
void free_path_list(struct list_head *list);
+void apply_allowed_cr_ip_port(void);
#endif
diff --git a/src/config.c b/src/config.c
index 0a9d028..65c15bc 100755
--- a/src/config.c
+++ b/src/config.c
@@ -26,17 +26,6 @@
#include "heartbeat.h"
#include "cwmp_http.h"
-static void set_cr_incoming_rule(const char *rule)
-{
- if (CWMP_LSTRCASECMP(rule, "ip_only") == 0) {
- cwmp_ctx.cr_policy = CR_POLICY_IP_Only;
- } else if (CWMP_LSTRCASECMP(rule, "ip_port") == 0) {
- cwmp_ctx.cr_policy = CR_POLICY_BOTH;
- } else {
- cwmp_ctx.cr_policy = CR_POLICY_Port_Only; // Default case
- }
-}
-
int get_preinit_config()
{
char value[BUF_SIZE_256] = {0};
@@ -64,9 +53,6 @@ int get_preinit_config()
CWMP_STRNCMP(cwmp_ctx.conf.default_wan_iface, "wan", sizeof(cwmp_ctx.conf.default_wan_iface));
}
- get_uci_path_value(NULL, UCI_CPE_INCOMING_RULE, value, BUF_SIZE_256);
- set_cr_incoming_rule(value);
-
cwmp_ctx.conf.amd_version = DEFAULT_AMD_VERSION;
get_uci_path_value(NULL, UCI_CPE_AMD_VERSION, value, BUF_SIZE_256);
if (CWMP_STRLEN(value) != 0) {
diff --git a/src/config.h b/src/config.h
index 1764404..c9ff85c 100755
--- a/src/config.h
+++ b/src/config.h
@@ -20,7 +20,6 @@
#define UCI_LOG_SEVERITY_PATH "cwmp.cpe.log_severity"
#define UCI_CPE_ENABLE_SYSLOG "cwmp.cpe.log_to_syslog"
#define UCI_CPE_DEFAULT_WAN_IFACE "cwmp.cpe.default_wan_interface"
-#define UCI_CPE_INCOMING_RULE "cwmp.cpe.incoming_rule"
#define UCI_CPE_AMD_VERSION "cwmp.cpe.amd_version"
#define UCI_CPE_CERT_PATH "cwmp.cpe.client_cert_path"
#define UCI_CPE_KEY_PATH "cwmp.cpe.client_key_path"
diff --git a/src/cwmp.c b/src/cwmp.c
index 84aaab1..b581354 100644
--- a/src/cwmp.c
+++ b/src/cwmp.c
@@ -352,6 +352,9 @@ int main(int argc, char **argv)
http_server_start();
+ apply_allowed_cr_ip_port();
+ cwmp_ctx.conf.cr_ip_port_change = false;
+
uloop_run();
uloop_done();
diff --git a/src/http.c b/src/http.c
index 22f1905..9d57352 100644
--- a/src/http.c
+++ b/src/http.c
@@ -331,15 +331,6 @@ int icwmp_http_send_message(char *msg_out, int msg_out_len, char **msg_in)
} else {
set_uci_path_value(VARSTATE_CONFIG, "icwmp.acs.ip", cwmp_ctx.ip_acs);
}
-
- // Trigger firewall to reload firewall.cwmp
- if (cwmp_ctx.cr_policy != CR_POLICY_Port_Only) {
- // Flawfinder: ignore
- FILE *pp = popen(FIREWALL_CWMP, "r");
- if (pp) {
- pclose(pp);
- }
- }
}
}
@@ -693,13 +684,8 @@ void icwmp_http_server_init(void)
snprintf(cr_port_str, 6, "%hu", cr_port);
cr_port_str[5] = '\0';
set_uci_path_value(NULL, "cwmp.cpe.port", cr_port_str);
- // Flawfinder: ignore
- FILE *pp = popen(FIREWALL_CWMP, "r");
- if (pp) {
- pclose(pp);
- }
-
connection_request_port_value_change(cr_port);
+ cwmp_ctx.conf.cr_ip_port_change = true;
}
CWMP_LOG(INFO, "Connection Request server initiated with the port: %d", cr_port);
diff --git a/src/session.c b/src/session.c
index f2c65b9..9e956dc 100644
--- a/src/session.c
+++ b/src/session.c
@@ -697,6 +697,12 @@ int run_session_end_func(void)
CWMP_LOG(ERROR, "config reload failed at session end");
}
+ if (cwmp_ctx.conf.cr_ip_port_change == true) {
+ CWMP_LOG(INFO, "Allowed CR IPs are changed");
+ apply_allowed_cr_ip_port();
+ cwmp_ctx.conf.cr_ip_port_change = false;
+ }
+
reinit_cwmp_periodic_session_feature();
reinit_heartbeat_procedures();
diff --git a/src/uci_utils.c b/src/uci_utils.c
index ea7a2e8..8ee5f63 100644
--- a/src/uci_utils.c
+++ b/src/uci_utils.c
@@ -52,6 +52,45 @@ static char *get_value_from_uci_option(struct uci_option *tb)
return "";
}
+static int get_value_from_uci_list(struct uci_option *tb, char *value, size_t size)
+{
+ if (value == NULL)
+ return -1;
+
+ memset(value, 0, size);
+
+ if (tb == NULL)
+ return -1;
+
+ if (tb->type == UCI_TYPE_LIST) {
+ struct uci_element *e;
+ bool sep = false;
+ char *tmp = value;
+ size_t left = 0;
+
+ uci_foreach_element(&tb->v.list, e) {
+ if (sep) {
+ left = size - strlen(value);
+ if (left < 2)
+ break;
+
+ int rc = snprintf(tmp, left, "%s", ",");
+ tmp = tmp + rc;
+ }
+
+ left = size - strlen(value);
+ if (left <= strlen(e->name))
+ break;
+
+ int rc = snprintf(tmp, left, "%s", e->name);
+ tmp = tmp + rc;
+ sep = true;
+ }
+ }
+
+ return 0;
+}
+
static void config_get_acs_elements(struct uci_section *s)
{
enum {
@@ -243,6 +282,7 @@ static void config_get_cpe_elements(struct uci_section *s)
UCI_CPE_ENABLE,
UCI_CPE_USE_CURL_IFNAME,
UCI_CPE_DISABLE_DATATYPE_CHECK,
+ UCI_CPE_ALLOWED_CR_IP,
__MAX_NUM_UCI_CPE_ATTRS,
};
@@ -269,7 +309,8 @@ static void config_get_cpe_elements(struct uci_section *s)
[UCI_CPE_CLOCK_SYNC_TIMEOUT] = { .name = "clock_sync_timeout", .type = UCI_TYPE_STRING },
[UCI_CPE_ENABLE] = { .name = "enable", .type = UCI_TYPE_STRING },
[UCI_CPE_USE_CURL_IFNAME] = { .name = "use_curl_ifname", .type = UCI_TYPE_STRING },
- [UCI_CPE_DISABLE_DATATYPE_CHECK] = { .name = "disable_datatype_check", .type = UCI_TYPE_STRING }
+ [UCI_CPE_DISABLE_DATATYPE_CHECK] = { .name = "disable_datatype_check", .type = UCI_TYPE_STRING },
+ [UCI_CPE_ALLOWED_CR_IP] = { .name = "allowed_cr_ip", .type = UCI_TYPE_LIST },
};
struct uci_option *cpe_tb[__MAX_NUM_UCI_CPE_ATTRS];
@@ -417,6 +458,16 @@ static void config_get_cpe_elements(struct uci_section *s)
cwmp_ctx.conf.cpe_disable_datatype_check = str_to_bool(get_value_from_uci_option(cpe_tb[UCI_CPE_DISABLE_DATATYPE_CHECK]));
CWMP_LOG(DEBUG, "CWMP CONFIG - cpe datatype validation: %d", cwmp_ctx.conf.cpe_disable_datatype_check);
+
+ char allowed_cr_ip[BUF_SIZE_2048] = {0};
+ get_value_from_uci_list(cpe_tb[UCI_CPE_ALLOWED_CR_IP], allowed_cr_ip, sizeof(allowed_cr_ip));
+
+ if (CWMP_STRCMP(cwmp_ctx.conf.valid_cr_ip, allowed_cr_ip) != 0) {
+ snprintf(cwmp_ctx.conf.valid_cr_ip, sizeof(cwmp_ctx.conf.valid_cr_ip), "%s", allowed_cr_ip);
+ cwmp_ctx.conf.cr_ip_port_change = true;
+ }
+
+ CWMP_LOG(DEBUG, "CWMP CONFIG - cpe allowed_cr_ip: %s", cwmp_ctx.conf.valid_cr_ip);
}
static void config_get_lwn_elements(struct uci_section *s)