Fix custom force inform parameters

This commit is contained in:
suvendhu 2023-11-07 18:43:19 +05:30
parent 9e6f10391e
commit 62566e4e81
7 changed files with 154 additions and 8 deletions

View file

@ -35,9 +35,31 @@ config inform_parameter
```
Apart from the above, user can configure a parameter as forced inform parameter by using a JSON file. Users can include this json file in their firmware to add custom forced inform parameters (other than standard force inform parameters specified in datamodel).
Then user just need to set the file path in 'forced_inform_json' option under 'cpe' section of the cwmp UCI file.
Below is the schema/format of the JSON file:
```bash
root@iopsys:~# cat /etc/icwmpd/force_inform.json
{
"forced_inform": [
"Device.DeviceInfo.UpTime",
"Device.WiFi.SSID.1.SSID"
]
}
root@iopsys:~#
root@iopsys:~# uci -q get cwmp.cpe.forced_inform_json
/etc/icwmpd/force_inform.json
root@iopsys:~#
```
Forced inform parameters defined in JSON should be leaf elements.
> Note:
> 1. To configure a parameter as forced inform parameter, set the events_list to an empty string, or to include the parameter for specific event, set the event_list accordingly.
> 2. Factory default inform_parameters can be added from standard cwmp uci file
> 1. Factory default inform_parameters can be added from standard cwmp uci file.
> 2. To configure a parameter for specific event set the event_list accordingly.
## Notification management
`icwmpd` support below notification types, which can be configured from an ACS on the datamodel parameters

View file

@ -91,6 +91,7 @@ extern struct uloop_timeout periodic_session_timer;
extern struct uloop_timeout retry_session_timer;
extern bool g_firewall_restart;
extern struct list_head intf_reset_list;
extern struct list_head force_inform_list;
typedef struct env {
unsigned short boot;
@ -111,6 +112,7 @@ typedef struct config {
char cpe_userid[BUF_SIZE_256];
char cpe_passwd[BUF_SIZE_256];
char custom_notify_json[BUF_SIZE_256];
char forced_inform_json[BUF_SIZE_256];
char connection_request_path[BUF_SIZE_256];
char auto_tc_transfer_type[BUF_SIZE_16];
char auto_tc_result_type[BUF_SIZE_16];
@ -594,6 +596,11 @@ typedef struct bin_list {
struct list_head list;
} bin_list_t;
typedef struct force_inform_node {
char path[1024];
struct list_head list;
} force_inform_node;
extern struct cwmp *cwmp_main;
extern long int flashsize;
extern struct FAULT_CPE FAULT_CPE_ARRAY[];

View file

@ -66,6 +66,7 @@ static void config_get_cpe_elements(struct uci_section *s)
UCI_CPE_SESSION_TIMEOUT,
UCI_CPE_INSTANCE_MODE,
UCI_CPE_JSON_CUSTOM_NOTIFY_FILE,
UCI_CPE_JSON_FORCED_INFORM_FILE,
UCI_CPE_FORCE_IPV4,
__MAX_NUM_UCI_CPE_ATTRS,
};
@ -84,6 +85,7 @@ static void config_get_cpe_elements(struct uci_section *s)
[UCI_CPE_SESSION_TIMEOUT] = { .name = "session_timeout", .type = UCI_TYPE_STRING },
[UCI_CPE_INSTANCE_MODE] = { .name = "instance_mode", .type = UCI_TYPE_STRING },
[UCI_CPE_JSON_CUSTOM_NOTIFY_FILE] = { .name = "custom_notify_json", .type = UCI_TYPE_STRING },
[UCI_CPE_JSON_FORCED_INFORM_FILE] = { .name = "forced_inform_json", .type = UCI_TYPE_STRING },
[UCI_CPE_CON_REQ_TIMEOUT] = { .name = "cr_timeout", .type = UCI_TYPE_STRING },
[UCI_CPE_FORCE_IPV4] = { .name = "force_ipv4", .type = UCI_TYPE_STRING }
};
@ -179,6 +181,9 @@ static void config_get_cpe_elements(struct uci_section *s)
snprintf(cwmp_main->conf.custom_notify_json, sizeof(cwmp_main->conf.custom_notify_json), "%s", get_value_from_uci_option(cpe_tb[UCI_CPE_JSON_CUSTOM_NOTIFY_FILE]));
CWMP_LOG(DEBUG, "CWMP CONFIG - cpe custom notify json path: %s", cwmp_main->conf.custom_notify_json);
snprintf(cwmp_main->conf.forced_inform_json, sizeof(cwmp_main->conf.forced_inform_json), "%s", get_value_from_uci_option(cpe_tb[UCI_CPE_JSON_FORCED_INFORM_FILE]));
CWMP_LOG(DEBUG, "CWMP CONFIG - cpe forced inform json path: %s", cwmp_main->conf.forced_inform_json);
cwmp_main->conf.force_ipv4 = uci_str_to_bool(get_value_from_uci_option(cpe_tb[UCI_CPE_FORCE_IPV4]));
CWMP_LOG(DEBUG, "CWMP CONFIG - cpe force ipv4 enable: %d", cwmp_main->conf.force_ipv4);

View file

@ -44,6 +44,7 @@
bool g_firewall_restart = false;
struct list_head intf_reset_list;
struct list_head du_uuid_list;
struct list_head force_inform_list;
static bool interface_reset_req(char *param_name, char *value)
{
@ -254,6 +255,14 @@ static int cwmp_init(void)
cwmp_get_deviceid();
cwmp_uci_init();
/* Load default force inform parameters */
CWMP_MEMSET(&force_inform_list, 0, sizeof(struct list_head));
INIT_LIST_HEAD(&force_inform_list);
load_default_forced_inform();
/* Load custom notify and force inform parameters */
load_forced_inform_json();
load_custom_notify_json();
set_default_forced_active_parameters_notifications();
init_list_param_notify();
@ -303,6 +312,7 @@ void cwmp_exit()
clean_autonomous_complpolicy();
clean_interface_update();
clean_du_uuid_list();
clean_force_inform_list();
FREE(cwmp_main->ev);
FREE(cwmp_main->intf_ev);
uloop_end();

104
src/rpc.c
View file

@ -338,14 +338,16 @@ static void load_inform_xml_schema(mxml_node_t **tree)
}
struct cwmp_dm_parameter cwmp_dm_param = {0};
for (size_t i = 0; i < ARRAY_SIZE(forced_inform_parameters); i++) {
if (!cwmp_get_parameter_value(forced_inform_parameters[i], &cwmp_dm_param))
force_inform_node *iter = NULL, *node = NULL;
list_for_each_entry_safe(iter, node, &force_inform_list, list) {
if (!cwmp_get_parameter_value(iter->path, &cwmp_dm_param))
continue;
// An empty connection url cause CDR test to break
if (strcmp(forced_inform_parameters[i], "Device.ManagementServer.ConnectionRequestURL") == 0 &&
if (strcmp(iter->path, "Device.ManagementServer.ConnectionRequestURL") == 0 &&
CWMP_STRLEN(cwmp_dm_param.value) == 0) {
CWMP_LOG(ERROR, "# Empty CR URL[%s] value", forced_inform_parameters[i]);
CWMP_LOG(ERROR, "# Empty CR URL[%s] value", iter->path);
MXML_DELETE(xml);
return;
}
@ -425,8 +427,9 @@ static int validate_inform_parameter_name(struct list_head *parameters_values_li
if (match_reg_exp(reg_exp, param_value->name) == false)
continue;
for (size_t i = 0; i < ARRAY_SIZE(forced_inform_parameters); i++) {
if (strcmp(forced_inform_parameters[i], param_value->value) == 0)
force_inform_node *iter = NULL, *node = NULL;
list_for_each_entry_safe(iter, node, &force_inform_list, list) {
if (strcmp(iter->path, param_value->value) == 0)
return FAULT_CPE_INVALID_PARAMETER_VALUE;
}
}
@ -2091,3 +2094,92 @@ int cwmp_create_fault_message(struct rpc *rpc_cpe, int fault_code, char *fault_m
return 0;
}
void load_default_forced_inform(void)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(forced_inform_parameters); i++) {
force_inform_node *node = (force_inform_node *)malloc(sizeof(force_inform_node));
if (node == NULL) {
CWMP_LOG(ERROR, "Out of memory");
break;
}
CWMP_MEMSET(node, 0, sizeof(force_inform_node));
snprintf(node->path, sizeof(node->path), "%s", forced_inform_parameters[i]);
INIT_LIST_HEAD(&node->list);
list_add_tail(&node->list, &force_inform_list);
}
}
void clean_force_inform_list(void)
{
force_inform_node *iter = NULL, *node = NULL;
list_for_each_entry_safe(iter, node, &force_inform_list, list) {
list_del(&iter->list);
free(iter);
}
}
void load_forced_inform_json(void)
{
struct blob_buf bbuf = {0};
struct blob_attr *cur = NULL;
struct blob_attr *forced_inform_list = NULL;
int rem = 0;
if (!file_exists(cwmp_main->conf.forced_inform_json))
return;
CWMP_MEMSET(&bbuf, 0, sizeof(struct blob_buf));
blob_buf_init(&bbuf, 0);
if (blobmsg_add_json_from_file(&bbuf, cwmp_main->conf.forced_inform_json) == false) {
CWMP_LOG(WARNING, "The file %s is not a valid JSON file", cwmp_main->conf.forced_inform_json);
blob_buf_free(&bbuf);
return;
}
struct blob_attr *tb[1] = { NULL };
const struct blobmsg_policy p[1] = { { "forced_inform", BLOBMSG_TYPE_ARRAY } };
blobmsg_parse(p, 1, tb, blobmsg_data(bbuf.head), blobmsg_len(bbuf.head));
if (tb[0] == NULL) {
CWMP_LOG(WARNING, "The JSON file %s doesn't contain a forced inform parameters list", cwmp_main->conf.forced_inform_json);
blob_buf_free(&bbuf);
return;
}
forced_inform_list = tb[0];
blobmsg_for_each_attr(cur, forced_inform_list, rem)
{
char parameter_path[1024];
struct cwmp_dm_parameter cwmp_dm_param = {0};
snprintf(parameter_path, sizeof(parameter_path), "%s", blobmsg_get_string(cur));
if (parameter_path[strlen(parameter_path)-1] == '.') {
CWMP_LOG(WARNING, "%s is rejected as inform parameter. Only leaf parameters are allowed.", parameter_path);
continue;
}
if (!cwmp_get_parameter_value(parameter_path, &cwmp_dm_param)) {
CWMP_LOG(WARNING, "%s is rejected as inform parameter. Wrong parameter path.", parameter_path);
continue;
}
/* Add in forced inform list */
force_inform_node *node = (force_inform_node *)malloc(sizeof(force_inform_node));
if (node == NULL) {
CWMP_LOG(ERROR, "Out of memory");
break;
}
CWMP_MEMSET(node, 0, sizeof(force_inform_node));
snprintf(node->path, sizeof(node->path), "%s", parameter_path);
INIT_LIST_HEAD(&node->list);
list_add_tail(&node->list, &force_inform_list);
}
blob_buf_free(&bbuf);
}

View file

@ -51,5 +51,8 @@ int cwmp_rpc_acs_prepare_autonomous_transfer_complete(struct rpc *rpc);
int xml_handle_message();
int cwmp_create_fault_message(struct rpc *rpc_cpe, int fault_code, char *fault_msg);
void load_default_forced_inform(void);
void clean_force_inform_list(void);
void load_forced_inform_json(void);
#endif

View file

@ -30,6 +30,7 @@
#include "cwmp_event.h"
static int instance = 0;
struct list_head force_inform_list;
#define INVALID_PARAM_KEY "ParameterKeyParameterKeyParameter"
#define INVALID_USER "useruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruseruser1"
@ -69,6 +70,11 @@ static void unit_test_end_test_destruction()
*/
static int soap_unit_tests_init(void **state)
{
CWMP_MEMSET(&force_inform_list, 0, sizeof(struct list_head));
INIT_LIST_HEAD(&force_inform_list);
load_default_forced_inform();
load_forced_inform_json();
cwmp_main = (struct cwmp*)calloc(1, sizeof(struct cwmp));
create_cwmp_session_structure();
memcpy(&(cwmp_main->env), &cwmp_main, sizeof(struct env));
@ -82,6 +88,7 @@ static int soap_unit_tests_clean(void **state)
icwmp_free_list_services();
clean_name_space();
cwmp_session_exit();
clean_force_inform_list();
FREE(cwmp_main->session);
FREE(cwmp_main);
return 0;