/* * 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 * Author Amin Ben Romdhane * * See LICENSE file for license related information. * */ #include #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 = ¶ms_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(¶ms_list); break; } if (get_result.error) { cwmp_free_all_dm_parameter_list(¶ms_list); FREE(get_result.err_param); break; } struct cwmp_dm_parameter *p = NULL; list_for_each_entry (p, ¶ms_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(¶ms_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; }