icwmp/src/datamodel_interface.c
2025-08-29 16:47:10 +05:30

1008 lines
25 KiB
C
Executable file

/*
* datamodel_interface.c - API to call BBF datamodel functions (set, get, add, delete, setattributes, getattributes, getnames, ...)
*
* Copyright (C) 2021-2023, IOPSYS Software Solutions AB.
*
* Author Omar Kallel <omar.kallel@pivasoftware.com>
* Author Amin Ben Romdhane <amin.benromdhane@iopsys.eu>
*
* See LICENSE file for license related information.
*
*/
#include <libubox/blobmsg_json.h>
#include "datamodel_interface.h"
#include "ubus_utils.h"
#include "log.h"
struct list_params_result {
struct list_head *parameters_list;
struct list_head *alias_list;
int error;
char *err_param;
const char *error_msg;
};
struct setm_values_res {
const char *q_path;
bool status;
struct list_head *faults_list;
};
/*
* Common functions
*/
static struct blob_attr *get_results_array(struct blob_attr *msg)
{
struct blob_attr *tb[1] = {0};
const struct blobmsg_policy p[1] = {
{ "results", BLOBMSG_TYPE_ARRAY }
};
if (msg == NULL)
return NULL;
blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg));
return tb[0];
}
static struct blob_attr *get_modified_uci_array(struct blob_attr *msg)
{
struct blob_attr *tb[1] = {0};
const struct blobmsg_policy p[1] = {
{ "modified_uci", BLOBMSG_TYPE_ARRAY }
};
if (msg == NULL)
return NULL;
blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg));
return tb[0];
}
static void prepare_optional_table(struct blob_buf *b)
{
void *table = blobmsg_open_table(b, "optional");
bb_add_string(b, "proto", "cwmp");
bb_add_string(b, "format", "raw");
blobmsg_close_table(b, table);
}
static int get_instance_mode(void)
{
int mode = INSTANCE_MODE_NUMBER;
if (cwmp_ctx.conf.amd_version >= 5)
mode = cwmp_ctx.conf.instance_mode;
return mode;
}
/*
* Get parameter value
*/
static void ubus_get_single_parameter_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg)
{
struct blob_attr *cur = NULL;
int rem = 0;
if (msg == NULL || req == NULL)
return;
struct cwmp_dm_parameter *result = (struct cwmp_dm_parameter *)req->priv;
struct blob_attr *parameters = get_results_array(msg);
if (parameters == NULL) {
result->notification = FAULT_CPE_INTERNAL_ERROR;
return;
}
blobmsg_for_each_attr(cur, parameters, rem) {
struct blob_attr *tb[4] = {0};
const struct blobmsg_policy p[4] = {
{ "path", BLOBMSG_TYPE_STRING },
{ "data", BLOBMSG_TYPE_STRING },
{ "type", BLOBMSG_TYPE_STRING },
{ "fault", BLOBMSG_TYPE_INT32 }
};
blobmsg_parse(p, 4, tb, blobmsg_data(cur), blobmsg_len(cur));
if (tb[3]) {
result->notification = blobmsg_get_u32(tb[3]);
return;
}
result->name = icwmp_strdup(tb[0] ? blobmsg_get_string(tb[0]) : "");
result->value = icwmp_strdup(tb[1] ? blobmsg_get_string(tb[1]) : "");
result->type = icwmp_strdup(tb[2] ? blobmsg_get_string(tb[2]) : "");
break;
}
}
bool cwmp_get_parameter_value(const char *parameter_name, struct cwmp_dm_parameter *dm_parameter)
{
struct blob_buf b = {0};
int len = CWMP_STRLEN(parameter_name);
if (len == 0 || parameter_name[len - 1] == '.')
return false;
CWMP_MEMSET(&b, 0, sizeof(struct blob_buf));
blob_buf_init(&b, 0);
bb_add_string(&b, "path", parameter_name);
prepare_optional_table(&b);
int e = icwmp_ubus_invoke(BBFDM_OBJECT_NAME, "get", b.head, ubus_get_single_parameter_callback, dm_parameter);
blob_buf_free(&b);
if (e < 0) {
CWMP_LOG(INFO, "get ubus method failed: Ubus err code: %d", e);
return false;
}
if (dm_parameter->notification) {
CWMP_LOG(INFO, "Get parameter value of %s failed, fault_code: %d", parameter_name, dm_parameter->notification);
return false;
}
return true;
}
static size_t blob_attr_length(struct blob_attr *array)
{
struct blob_attr *cur = NULL;
size_t count = 0, rem = 0;
if (!array)
return 0;
blobmsg_for_each_attr(cur, array, rem) {
count++;
}
return count;
}
/*
* Get parameter Values/Names
*/
static void ubus_get_parameter_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg)
{
struct blob_attr *cur = NULL;
int rem = 0;
const struct blobmsg_policy p[5] = {
{ "path", BLOBMSG_TYPE_STRING },
{ "data", BLOBMSG_TYPE_STRING },
{ "type", BLOBMSG_TYPE_STRING },
{ "fault", BLOBMSG_TYPE_INT32 },
{ "output", BLOBMSG_TYPE_ARRAY }
};
if (msg == NULL || req == NULL)
return;
struct list_params_result *result = (struct list_params_result *)req->priv;
struct blob_attr *parameters = get_results_array(msg);
if (parameters == NULL) {
result->error = FAULT_CPE_INTERNAL_ERROR;
result->error_msg = "JSON message output is not correctly created";
return;
}
char *last_path = NULL;
char *last_transform = NULL;
int inst_mode = get_instance_mode();
size_t blob_len = blob_attr_length(parameters);
blobmsg_for_each_attr(cur, parameters, rem) {
struct blob_attr *tb[5] = {0};
blobmsg_parse(p, 5, tb, blobmsg_data(cur), blobmsg_len(cur));
if (tb[3]) {
if (blob_len == 1) {
result->error = blobmsg_get_u32(tb[3]);
if (tb[0]) {
result->err_param = strdup(blobmsg_get_string(tb[0]));
}
return;
} else {
continue;
}
}
if (!tb[0]) continue;
char *param_name = blobmsg_get_string(tb[0]);
char *param_value = tb[1] ? blobmsg_get_string(tb[1]) : "";
char *param_type = tb[2] ? blobmsg_get_string(tb[2]) : "";
bool writable = strcmp(param_value, "1") == 0 ? true : false;
add_dm_parameter_to_list(result->parameters_list, param_name, param_value, param_type, 0, writable);
if (inst_mode == INSTANCE_MODE_ALIAS) {
/* in GPN alias values comes in tb[4] i.e the output field */
if (tb[4]) {
struct blob_attr *_cur = NULL;
int _rem = 0;
const struct blobmsg_policy _p[1] = {
{ "data", BLOBMSG_TYPE_STRING }
};
blobmsg_for_each_attr(_cur, tb[4], _rem) {
struct blob_attr *_tb[1] = {0};
blobmsg_parse(_p, 1, _tb, blobmsg_data(_cur), blobmsg_len(_cur));
char *value = _tb[0] ? blobmsg_get_string(_tb[0]) : param_value;
add_dm_alias_to_list(result->alias_list, param_name, value, &last_path, &last_transform);
break;
}
}
}
}
FREE(last_path);
FREE(last_transform);
}
static void format_alias_instance(struct list_head *parameters_list, struct list_head *alias_list,
const char *q_path)
{
struct cwmp_dm_parameter *param1 = NULL;
struct cwmp_dm_alias *alias = NULL;
char *l_param = NULL;
char *l_trans = NULL;
int dot_count = 0;
char *tmp = NULL;
int inst_mode = get_instance_mode();
if ((inst_mode == INSTANCE_MODE_NUMBER && CWMP_STRSTR(q_path, "[") == NULL) ||
CWMP_STRSTR(q_path, ".*.") != NULL)
return;
// query path intact
char q_string[1024];
snprintf(q_string, sizeof(q_string), "%s", q_path);
tmp = strrchr(q_string, '.');
if (tmp) {
*(tmp+1) = '\0';
tmp = strchr(q_string, '.');
while (tmp) {
dot_count += 1;
tmp = strchr(tmp+1, '.');
}
}
list_for_each_entry (param1, parameters_list, list) {
char p_name[1024];
char leaf[128];
char res[2048];
if (!param1->name)
continue;
snprintf(p_name, sizeof(p_name), "%s", param1->name);
tmp = strrchr(p_name, '.');
if (!tmp)
continue;
snprintf(leaf, sizeof(leaf), "%s", tmp+1);
*(tmp+1) = '\0';
if (CWMP_STRCMP(p_name, l_param) == 0) {
snprintf(res, sizeof(res), "%s%s", l_trans, leaf);
FREE(param1->name);
param1->name = strdup(res);
continue;
}
list_for_each_entry (alias, alias_list, list) {
if (CWMP_STRCMP(p_name, alias->org_name) == 0) {
snprintf(res, sizeof(res), "%s%s", alias->trs_name, leaf);
FREE(param1->name);
FREE(l_param);
FREE(l_trans);
param1->name = strdup(res);
l_param = strdup(alias->org_name);
l_trans = strdup(alias->trs_name);
break;
}
}
if (CWMP_STRNCMP(param1->name, q_string, CWMP_STRLEN(q_string)) == 0 || dot_count == 0)
continue;
// replace the base query string
tmp = strchr(param1->name, '.');
if (!tmp)
continue;
int count = dot_count - 1;
while (count && tmp) {
count -= 1;
tmp = strchr(tmp+1, '.');
}
if (count == 0 && tmp) {
snprintf(res, sizeof(res), "%s%s", q_string, tmp+1);
FREE(l_param);
*(tmp+1) = '\0';
l_param = CWMP_STRDUP(param1->name);
FREE(param1->name);
param1->name = CWMP_STRDUP(res);
FREE(l_trans);
tmp = strrchr(res, '.');
if (tmp) {
*(tmp+1) = '\0';
}
l_trans = CWMP_STRDUP(res);
}
}
FREE(l_param);
FREE(l_trans);
}
int instantiate_param_name(const char *param, char **inst_path)
{
char orig_path[2048] = {0};
char *tmp = NULL;
bool valid = true;
if (!inst_path)
return CWMP_GEN_ERR;
*inst_path = NULL;
if (CWMP_STRLEN(param) == 0)
return CWMP_OK;
/* Alias mode not supported */
if (cwmp_ctx.conf.amd_version < 5 && CWMP_STRSTR(param, "[") != NULL)
return CWMP_GEN_ERR;
snprintf(orig_path, sizeof(orig_path), "%s", param);
tmp = strchr(orig_path, '[');
while (tmp) {
valid = false;
char prev_path[1024] = {0};
char query_path[1024] = {0};
char alias[66] = {0};
*tmp = '\0';
snprintf(prev_path, sizeof(prev_path), "%.1023s", orig_path);
snprintf(query_path, sizeof(query_path), "%.1016s*.Alias", orig_path);
tmp++;
char *pos = strchr(tmp, ']');
if (!pos)
break;
*pos = '\0';
snprintf(alias, sizeof(alias), "%s", tmp);
pos++;
LIST_HEAD(params_list);
struct blob_buf b = {0};
struct list_params_result get_result = {
.parameters_list = &params_list,
.error = FAULT_CPE_NO_FAULT,
.err_param = NULL
};
CWMP_MEMSET(&b, 0, sizeof(struct blob_buf));
blob_buf_init(&b, 0);
bb_add_string(&b, "path", query_path);
prepare_optional_table(&b);
int e = icwmp_ubus_invoke(BBFDM_OBJECT_NAME, "get", b.head, ubus_get_parameter_callback, &get_result);
blob_buf_free(&b);
if (e < 0) {
cwmp_free_all_dm_parameter_list(&params_list);
break;
}
if (get_result.error) {
cwmp_free_all_dm_parameter_list(&params_list);
FREE(get_result.err_param);
break;
}
struct cwmp_dm_parameter *p = NULL;
list_for_each_entry (p, &params_list, list) {
if (!p->name)
continue;
char *pos_dot = strrchr(p->name, '.');
if (!pos_dot)
continue;
if (CWMP_STRCMP(pos_dot, ".Alias") == 0 && CWMP_STRCMP(p->value, alias) == 0) {
*pos_dot = '\0';
char *instance = strrchr(p->name, '.');
if (!instance)
continue;
instance += 1;
valid = true;
snprintf(orig_path, sizeof(orig_path), "%s%s%s", prev_path, instance, pos);
break;
}
}
cwmp_free_all_dm_parameter_list(&params_list);
if (!valid) {
break;
}
tmp = strchr(orig_path, '[');
}
if (valid) {
*inst_path = strdup(orig_path);
return CWMP_OK;
}
return CWMP_GEN_ERR;
}
char *cwmp_get_parameter_values(const char *parameter_name, struct list_head *parameters_list)
{
char *inst_path = NULL;
LIST_HEAD(alias_list);
struct blob_buf b = {0};
struct list_params_result get_result = {
.parameters_list = parameters_list,
.alias_list = &alias_list,
.error = FAULT_CPE_NO_FAULT,
.err_param = NULL
};
unsigned int len = CWMP_STRLEN(parameter_name);
if (len > 2 && parameter_name[len - 1] == '.' && parameter_name[len - 2] == '*')
return "9005";
if (CWMP_OK != instantiate_param_name(parameter_name, &inst_path))
return "9005";
const char *param = CWMP_STRLEN(inst_path) ? inst_path : "";
CWMP_MEMSET(&b, 0, sizeof(struct blob_buf));
blob_buf_init(&b, 0);
bb_add_string(&b, "path", param);
prepare_optional_table(&b);
int e = icwmp_ubus_invoke(BBFDM_OBJECT_NAME, "get", b.head, ubus_get_parameter_callback, &get_result);
blob_buf_free(&b);
if (e < 0) {
CWMP_LOG(WARNING, "Get failed (%s) Ubus err code: %d", param, e);
FREE(inst_path);
cwmp_free_all_dm_parameter_list(&alias_list);
return "9002";
}
if (get_result.error) {
char buf[8] = {0};
CWMP_LOG(WARNING, "Get parameter values (%s) failed: fault_code: %d", param, get_result.error);
if (get_result.err_param && cwmp_ctx.session != NULL) {
snprintf(cwmp_ctx.session->fault_msg, sizeof(cwmp_ctx.session->fault_msg),
"GetParameterValues failed for %s", get_result.err_param);
}
FREE(get_result.err_param);
FREE(inst_path);
cwmp_free_all_dm_parameter_list(&alias_list);
snprintf(buf, sizeof(buf), "%d", get_result.error);
return icwmp_strdup(buf);
}
format_alias_instance(parameters_list, &alias_list, parameter_name);
FREE(inst_path);
cwmp_free_all_dm_alias_list(&alias_list);
return NULL;
}
char *cwmp_get_parameter_names(const char *parameter_name, bool next_level, struct list_head *parameters_list, const char **err_msg)
{
char *inst_path = NULL;
LIST_HEAD(alias_list);
struct blob_buf b = {0};
struct list_params_result get_result = {
.parameters_list = parameters_list,
.alias_list = &alias_list,
.error = FAULT_CPE_NO_FAULT,
.error_msg = NULL,
.err_param = NULL
};
unsigned int len = CWMP_STRLEN(parameter_name);
if (len > 2 && parameter_name[len - 1] == '.' && parameter_name[len - 2] == '*') {
if (err_msg) *err_msg = "Parameter name should not finished with instance wildcard(.*.)";
return "9005";
}
if (CWMP_OK != instantiate_param_name(parameter_name, &inst_path))
return "9005";
const char *object = CWMP_STRLEN(inst_path) ? inst_path : "";
CWMP_MEMSET(&b, 0, sizeof(struct blob_buf));
blob_buf_init(&b, 0);
bb_add_string(&b, "path", object);
blobmsg_add_u8(&b, "first_level", next_level);
prepare_optional_table(&b);
int e = icwmp_ubus_invoke(BBFDM_OBJECT_NAME, "schema", b.head, ubus_get_parameter_callback, &get_result);
blob_buf_free(&b);
if (e < 0) {
CWMP_LOG(INFO, "object_names ubus method failed: Ubus err code: %d", e);
FREE(inst_path);
cwmp_free_all_dm_alias_list(&alias_list);
if (err_msg) *err_msg = "Internal error in ubus method bbfdm schema";
return "9002";
}
if (get_result.error) {
char buf[8] = {0};
CWMP_LOG(WARNING, "Get parameter Names (%s) failed: fault_code: %d", object, get_result.error);
FREE(get_result.err_param);
FREE(inst_path);
cwmp_free_all_dm_alias_list(&alias_list);
snprintf(buf, sizeof(buf), "%d", get_result.error);
return icwmp_strdup(buf);
}
format_alias_instance(parameters_list, &alias_list, parameter_name);
FREE(inst_path);
cwmp_free_all_dm_alias_list(&alias_list);
return NULL;
}
char *cwmp_validate_multi_instance_path(const char *object, struct list_head *parameters_list)
{
struct blob_buf b = {0};
struct list_params_result get_result = {
.parameters_list = parameters_list,
.alias_list = NULL,
.error = FAULT_CPE_NO_FAULT,
.error_msg = NULL,
.err_param = NULL
};
CWMP_MEMSET(&b, 0, sizeof(struct blob_buf));
blob_buf_init(&b, 0);
bb_add_string(&b, "path", object);
blobmsg_add_u8(&b, "first_level", false);
void *table = blobmsg_open_table(&b, "optional");
bb_add_string(&b, "proto", "usp");
bb_add_string(&b, "format", "raw");
blobmsg_close_table(&b, table);
int e = icwmp_ubus_invoke(BBFDM_OBJECT_NAME, "schema", b.head, ubus_get_parameter_callback, &get_result);
blob_buf_free(&b);
if (e < 0) {
CWMP_LOG(INFO, "object_names ubus method failed: Ubus err code: %d", e);
return "9002";
}
if (get_result.error) {
char buf[8] = {0};
snprintf(buf, sizeof(buf), "%d", get_result.error);
CWMP_LOG(WARNING, "Get parameter Names (%s) failed: fault_code: %d", object, get_result.error);
FREE(get_result.err_param);
return icwmp_strdup(buf);
}
return NULL;
}
char *cwmp_validate_parameter_name(const char *param_name, bool next_level, struct list_head *param_list)
{
struct blob_buf buf = {0};
struct list_params_result get_result = {
.parameters_list = param_list,
.alias_list = NULL,
.error = FAULT_CPE_NO_FAULT,
.err_param = NULL
};
unsigned int len = CWMP_STRLEN(param_name);
if (len > 2 && param_name[len - 1] == '.' && param_name[len - 2] == '*')
return "9005";
if (CWMP_STRSTR(param_name, "[") != NULL) {
/* this method is invoked for notifications and alias instance is not
* supported for notification parameter name */
CWMP_LOG(DEBUG, "Instance mode Alias not supported for notification parameter");
return "9005";
}
const char *object = len ? param_name : "";
CWMP_MEMSET(&buf, 0, sizeof(struct blob_buf));
blob_buf_init(&buf, 0);
bb_add_string(&buf, "path", object);
blobmsg_add_u8(&buf, "first_level", next_level);
prepare_optional_table(&buf);
int e = icwmp_ubus_invoke(BBFDM_OBJECT_NAME, "schema", buf.head, ubus_get_parameter_callback, &get_result);
blob_buf_free(&buf);
if (e < 0)
return "9002";
if (get_result.error) {
char err[8] = {0};
FREE(get_result.err_param);
snprintf(err, sizeof(err), "%d", get_result.error);
return icwmp_strdup(err);
}
return NULL;
}
/*
* Set multiple parameter values
*/
static void ubus_set_value_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg)
{
struct blob_attr *cur = NULL;
int rem = 0;
const struct blobmsg_policy p[4] = {
{ "path", BLOBMSG_TYPE_STRING },
{ "data", BLOBMSG_TYPE_STRING },
{ "fault", BLOBMSG_TYPE_INT32 },
{ "fault_msg", BLOBMSG_TYPE_STRING },
};
if (msg == NULL || req == NULL)
return;
struct setm_values_res *result = (struct setm_values_res *)req->priv;
struct blob_attr *modified_uci = get_modified_uci_array(msg);
if (modified_uci) {
blobmsg_for_each_attr(cur, modified_uci, rem) {
char *config_name = blobmsg_get_string(cur);
cwmp_add_modified_uci_list(config_name);
}
}
struct blob_attr *parameters = get_results_array(msg);
if (parameters == NULL) {
result->status = false;
return;
}
cur = NULL;
rem = 0;
blobmsg_for_each_attr(cur, parameters, rem) {
struct blob_attr *tb[4] = {0};
blobmsg_parse(p, 4, tb, blobmsg_data(cur), blobmsg_len(cur));
if (!tb[0]) {
result->status = false;
continue;
}
if (tb[1]) continue;
result->status = false;
if (!tb[2]) continue;
/* Param path should have the query path same as received */
char param_path[1024] = {0};
char *r_path = blobmsg_get_string(tb[0]);
if (r_path) {
if (CWMP_STRSTR(result->q_path, ".*.") != NULL || CWMP_STRSTR(result->q_path, "[") == NULL) {
snprintf(param_path, sizeof(param_path), "%s", r_path);
} else {
snprintf(param_path, sizeof(param_path), "%s", result->q_path);
}
}
cwmp_add_list_fault_param(param_path, blobmsg_get_string(tb[3]), blobmsg_get_u32(tb[2]), result->faults_list);
}
}
int cwmp_set_parameter_value(const char *parameter_name, const char *parameter_value, const char *type, struct list_head *faults_list)
{
char *inst_path = NULL;
struct blob_buf b = {0};
int param_len = CWMP_STRLEN(parameter_name);
struct setm_values_res set_result = {
.q_path = parameter_name,
.faults_list = faults_list,
.status = true
};
if (param_len == 0 || parameter_name[param_len - 1] == '.' || parameter_value == NULL)
return FAULT_CPE_INVALID_ARGUMENTS;
if (CWMP_OK != instantiate_param_name(parameter_name, &inst_path))
return FAULT_CPE_INVALID_ARGUMENTS;
CWMP_MEMSET(&b, 0, sizeof(struct blob_buf));
blob_buf_init(&b, 0);
bb_add_string(&b, "path", inst_path);
bb_add_string(&b, "value", parameter_value);
if (cwmp_ctx.conf.cpe_disable_datatype_check == false) {
bb_add_string(&b, "datatype", type ? type : "");
}
prepare_optional_table(&b);
int e = icwmp_ubus_invoke(BBFDM_OBJECT_NAME, "set", b.head, ubus_set_value_callback, &set_result);
blob_buf_free(&b);
if (e < 0) {
CWMP_LOG(INFO, "set ubus method failed: Ubus err code: %d", e);
FREE(inst_path);
return FAULT_CPE_INTERNAL_ERROR;
}
if (set_result.status == false) {
CWMP_LOG(INFO, "Set parameter value of %s with %s value is failed", parameter_name, parameter_value);
FREE(inst_path);
return FAULT_CPE_INVALID_ARGUMENTS;
}
FREE(inst_path);
return FAULT_CPE_NO_FAULT;
}
int cwmp_set_multi_parameters_value(struct list_head *parameters_values_list, struct list_head *faults_list)
{
struct cwmp_dm_parameter *param_value = NULL;
bool fault_occured = false;
list_for_each_entry (param_value, parameters_values_list, list) {
if (CWMP_STRLEN(param_value->name) == 0)
continue;
int res = cwmp_set_parameter_value(param_value->name, param_value->value, param_value->type, faults_list);
if (res != FAULT_CPE_NO_FAULT)
fault_occured = true;
}
return fault_occured ? FAULT_CPE_INVALID_ARGUMENTS : FAULT_CPE_NO_FAULT;
}
/*
* Add Delete object
*/
static void ubus_objects_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg)
{
struct blob_attr *cur = NULL;
int rem = 0;
const struct blobmsg_policy p[4] = {
{ "data", BLOBMSG_TYPE_STRING },
{ "fault", BLOBMSG_TYPE_INT32 },
{ "fault_msg", BLOBMSG_TYPE_STRING },
{ "path", BLOBMSG_TYPE_STRING }
};
if (msg == NULL || req == NULL)
return;
struct object_result *result = (struct object_result *)req->priv;
struct blob_attr *modified_uci = get_modified_uci_array(msg);
if (modified_uci) {
blobmsg_for_each_attr(cur, modified_uci, rem) {
char *config_name = blobmsg_get_string(cur);
cwmp_add_modified_uci_list(config_name);
}
}
struct blob_attr *objects = get_results_array(msg);
if (objects == NULL) {
result->fault_code = FAULT_9002;
return;
}
cur = NULL;
rem = 0;
blobmsg_for_each_attr(cur, objects, rem) {
struct blob_attr *tb[4] = {0};
blobmsg_parse(p, 4, tb, blobmsg_data(cur), blobmsg_len(cur));
if (tb[1]) {
result->fault_code = blobmsg_get_u32(tb[1]);
snprintf(result->fault_msg, sizeof(result->fault_msg), "%s: %s",
tb[2] ? blobmsg_get_string(tb[2]) : "Request failed for",
tb[3] ? blobmsg_get_string(tb[3]) : "");
return;
}
if (tb[0])
result->instance = CWMP_STRDUP(blobmsg_get_string(tb[0]));
}
}
bool cwmp_add_object(const char *object_name, struct object_result *res)
{
struct blob_buf b = {0};
char alias_val[66] = {0};
char ob_path[1024] = {0};
int len = 0;
char *inst_path = NULL;
len = CWMP_STRLEN(object_name);
if (!len) {
res->fault_code = FAULT_9005;
snprintf(res->fault_msg, sizeof(res->fault_msg), "Object name should not be empty");
return false;
}
snprintf(ob_path, sizeof(ob_path), "%s", object_name);
if (ob_path[len - 1] != '.') {
res->fault_code = FAULT_9005;
snprintf(res->fault_msg, sizeof(res->fault_msg), "Object name must end with \'.\'");
return false;
}
if (ob_path[len - 2] == ']') {
/* Top.Group.Object.[a]. */
ob_path[len - 2] = '\0';
char *tmp = strrchr(ob_path, '[');
if (!tmp) {
res->fault_code = FAULT_9005;
snprintf(res->fault_msg, sizeof(res->fault_msg), "Invalid Object Name %s", object_name);
return false;
}
*tmp = '\0';
tmp += 1;
snprintf(alias_val, sizeof(alias_val), "%s", tmp);
}
if (CWMP_OK != instantiate_param_name(ob_path, &inst_path)) {
res->fault_code = FAULT_9005;
snprintf(res->fault_msg, sizeof(res->fault_msg), "Invalid Object Name %s", object_name);
return false;
}
if (CWMP_STRLEN(inst_path) == 0) {
res->fault_code = FAULT_9005;
snprintf(res->fault_msg, sizeof(res->fault_msg), "Invalid Object Name %s", object_name);
return false;
}
CWMP_MEMSET(&b, 0, sizeof(struct blob_buf));
blob_buf_init(&b, 0);
bb_add_string(&b, "path", inst_path);
prepare_optional_table(&b);
int e = icwmp_ubus_invoke(BBFDM_OBJECT_NAME, "add", b.head, ubus_objects_callback, res);
blob_buf_free(&b);
if (e < 0) {
CWMP_LOG(INFO, "add_object ubus method failed: Ubus err code: %d", e);
FREE(inst_path);
return false;
}
if (res->fault_code) {
CWMP_LOG(WARNING, "Add Object (%s) failed: fault_code: %d", object_name, res->fault_code);
FREE(inst_path);
return false;
}
/* Set the alias if needed */
if (CWMP_STRLEN(alias_val) && CWMP_STRLEN(res->instance)) {
char set_path[2048] = {0};
snprintf(set_path, sizeof(set_path), "%s%s.Alias", inst_path, res->instance);
CWMP_MEMSET(&b, 0, sizeof(struct blob_buf));
blob_buf_init(&b, 0);
bb_add_string(&b, "path", set_path);
bb_add_string(&b, "value", alias_val);
prepare_optional_table(&b);
icwmp_ubus_invoke(BBFDM_OBJECT_NAME, "set", b.head, NULL, NULL);
blob_buf_free(&b);
}
FREE(inst_path);
return true;
}
bool cwmp_delete_object(const char *object_name, struct object_result *res)
{
char *inst_path = NULL;
struct blob_buf b = {0};
int len = 0;
len = CWMP_STRLEN(object_name);
if (!len) {
res->fault_code = FAULT_9005;
snprintf(res->fault_msg, sizeof(res->fault_msg), "Object name should not be empty");
return false;
}
if (CWMP_OK != instantiate_param_name(object_name, &inst_path)) {
res->fault_code = FAULT_9005;
snprintf(res->fault_msg, sizeof(res->fault_msg), "Invalid Object Name %s", object_name);
return false;
}
if (CWMP_STRLEN(inst_path) == 0) {
res->fault_code = FAULT_9005;
snprintf(res->fault_msg, sizeof(res->fault_msg), "Invalid Object Name %s", object_name);
return false;
}
CWMP_MEMSET(&b, 0, sizeof(struct blob_buf));
blob_buf_init(&b, 0);
bb_add_string(&b, "path", inst_path);
prepare_optional_table(&b);
int e = icwmp_ubus_invoke(BBFDM_OBJECT_NAME, "del", b.head, ubus_objects_callback, res);
blob_buf_free(&b);
if (e < 0) {
CWMP_LOG(INFO, "delete object ubus method failed: Ubus err code: %d", e);
FREE(inst_path);
return false;
}
if (res->fault_code) {
CWMP_LOG(WARNING, "Delete Object (%s) failed: fault_code: %d", object_name, res->fault_code);
FREE(inst_path);
return false;
}
FREE(inst_path);
return true;
}