From 74bf316022b20b9b2928224031490259273a8006 Mon Sep 17 00:00:00 2001 From: Amin Ben Romdhane Date: Thu, 7 Sep 2023 12:19:28 +0200 Subject: [PATCH] bbfdm: Add support for external linker in micro-services --- bbfdmd/ubus/bbfdmd.c | 2 - bbfdmd/ubus/cli.c | 3 - bbfdmd/ubus/common.c | 18 +- bbfdmd/ubus/common.h | 3 +- bbfdmd/ubus/get.c | 3 +- bbfdmd/ubus/get_helper.c | 2 - bbfdmd/ubus/get_helper.h | 1 - bbfdmd/ubus/operate.h | 2 - bbfdmd/ubus/plugin.c | 2 +- bbfdmd/ubus/pretty_print.c | 27 ++- bbfdmd/ubus/set.h | 2 - libbbfdm-api/dmapi.c | 27 +++ libbbfdm-api/dmapi.h | 14 +- libbbfdm-api/dmbbf.c | 186 +++++++++++++++++++- libbbfdm-api/dmbbf.h | 1 + libbbfdm-api/dmcommon.c | 16 +- libbbfdm-api/dmcommon.h | 7 +- libbbfdm-api/dmentry.c | 42 ++++- libbbfdm-api/dmentry.h | 1 + libbbfdm-api/include/libbbfdm_api.h | 30 ++++ libbbfdm/CMakeLists.txt | 2 +- libbbfdm/dmtree/tr181/bridging.c | 2 +- libbbfdm/dmtree/tr181/ethernet.c | 2 +- libbbfdm/dmtree/vendor/iopsys/tr181/times.c | 15 +- 24 files changed, 344 insertions(+), 66 deletions(-) diff --git a/bbfdmd/ubus/bbfdmd.c b/bbfdmd/ubus/bbfdmd.c index a14ae9fa..596eb0ae 100644 --- a/bbfdmd/ubus/bbfdmd.c +++ b/bbfdmd/ubus/bbfdmd.c @@ -29,8 +29,6 @@ #include "get_helper.h" #include "plugin.h" #include "cli.h" -#include "libbbfdm-api/dmentry.h" -#include "libbbfdm-api/dmjson.h" extern struct list_head loaded_json_files; extern struct list_head json_list; diff --git a/bbfdmd/ubus/cli.c b/bbfdmd/ubus/cli.c index 234958f5..e96cf881 100644 --- a/bbfdmd/ubus/cli.c +++ b/bbfdmd/ubus/cli.c @@ -13,9 +13,6 @@ #include "common.h" #include "plugin.h" -#include "libbbfdm-api/dmapi.h" -#include "libbbfdm-api/dmjson.h" -#include "libbbfdm-api/dmentry.h" extern struct list_head loaded_json_files; extern struct list_head json_list; diff --git a/bbfdmd/ubus/common.c b/bbfdmd/ubus/common.c index f0689171..531c9ed7 100644 --- a/bbfdmd/ubus/common.c +++ b/bbfdmd/ubus/common.c @@ -110,7 +110,7 @@ bool is_node_instance(char *path) rb = strchr(path, ']'); shift = (size_t) labs(rb - path); strncpyt(temp_char, path, shift + 1); - if (!match(temp_char, GLOB_EXPR)) + if (!match(temp_char, GLOB_EXPR, 0, NULL)) ret = true; } else { if (strtol(path, NULL, 10)) @@ -120,22 +120,6 @@ bool is_node_instance(char *path) } // RE utilities -bool match(const char *string, const char *pattern) -{ - int status; - regex_t re; - - if (regcomp(&re, pattern, REG_EXTENDED) != 0) - return 0; - - status = regexec(&re, string, 0, NULL, 0); - regfree(&re); - if (status != 0) - return false; - - return true; -} - int count_delim(const char *path) { int count = 0; diff --git a/bbfdmd/ubus/common.h b/bbfdmd/ubus/common.h index 2dc5b905..e2f10d3c 100644 --- a/bbfdmd/ubus/common.h +++ b/bbfdmd/ubus/common.h @@ -14,6 +14,8 @@ #include #include +#include "libbbfdm-api/dmcommon.h" + #include "bbfdmd.h" #define ROOT_NODE "Device." @@ -43,7 +45,6 @@ extern DMOBJ *DEAMON_DM_ROOT_OBJ; extern DM_MAP_VENDOR *DEAMON_DM_VENDOR_EXTENSION[2]; extern DM_MAP_VENDOR_EXCLUDE *DEAMON_DM_VENDOR_EXTENSION_EXCLUDE; -bool match(const char *string, const char *pattern); bool is_str_eq(const char *s1, const char *s2); bool is_node_instance(char *path); int count_delim(const char *path); diff --git a/bbfdmd/ubus/get.c b/bbfdmd/ubus/get.c index 06056bbb..03003038 100644 --- a/bbfdmd/ubus/get.c +++ b/bbfdmd/ubus/get.c @@ -12,7 +12,6 @@ #include "get.h" #include "get_helper.h" #include "pretty_print.h" -#include "libbbfdm-api/dmentry.h" #include @@ -680,7 +679,7 @@ static int solve_all_filters(struct dmctx *bbf_ctx, char *bPath, char *param, st INFO("Filter Para(%s), oper(%d), Val(%s)", para, oper, value); - if (match(para, "[*]+")) + if (match(para, "[*]+", 0, NULL)) ret = USP_FAULT_INVALID_TYPE; else ret = search_n_apply(bPath, para, oper, value, &pv_local, &plist_local); diff --git a/bbfdmd/ubus/get_helper.c b/bbfdmd/ubus/get_helper.c index a7c9843a..a37c3e52 100644 --- a/bbfdmd/ubus/get_helper.c +++ b/bbfdmd/ubus/get_helper.c @@ -18,8 +18,6 @@ #include "common.h" #include "pretty_print.h" -#include "libbbfdm-api/dmentry.h" - DMOBJ *DEAMON_DM_ROOT_OBJ = NULL; DM_MAP_VENDOR *DEAMON_DM_VENDOR_EXTENSION[2] = {0}; DM_MAP_VENDOR_EXCLUDE *DEAMON_DM_VENDOR_EXTENSION_EXCLUDE = NULL; diff --git a/bbfdmd/ubus/get_helper.h b/bbfdmd/ubus/get_helper.h index d27bc2f1..b2896c0a 100644 --- a/bbfdmd/ubus/get_helper.h +++ b/bbfdmd/ubus/get_helper.h @@ -3,7 +3,6 @@ #include "bbfdmd.h" #include "common.h" -#include "libbbfdm-api/dmbbf.h" #include diff --git a/bbfdmd/ubus/operate.h b/bbfdmd/ubus/operate.h index 90505a84..7041b037 100644 --- a/bbfdmd/ubus/operate.h +++ b/bbfdmd/ubus/operate.h @@ -4,8 +4,6 @@ #include "bbfdmd.h" #include "common.h" -#include "libbbfdm-api/dmbbf.h" - enum { DM_OPERATE_COMMAND, DM_OPERATE_COMMAND_KEY, diff --git a/bbfdmd/ubus/plugin.c b/bbfdmd/ubus/plugin.c index c7acac13..86dc7fda 100644 --- a/bbfdmd/ubus/plugin.c +++ b/bbfdmd/ubus/plugin.c @@ -13,7 +13,7 @@ #include #include "common.h" -#include "libbbfdm-api/dmapi.h" + #include "libbbfdm-api/plugin/json_plugin.h" extern struct list_head global_memhead; diff --git a/bbfdmd/ubus/pretty_print.c b/bbfdmd/ubus/pretty_print.c index ddcb185d..4e9a4038 100644 --- a/bbfdmd/ubus/pretty_print.c +++ b/bbfdmd/ubus/pretty_print.c @@ -22,7 +22,7 @@ struct resultstack { static bool is_search_by_reference(char *path) { DEBUG("Entry |%s|", path); - if (match(path, "[+]+")) { + if (match(path, "[+]+", 0, NULL)) { size_t pindex = 0, bindex = 0; char *last_plus, *last_bracket; @@ -47,7 +47,7 @@ static bool is_res_required(char *str, size_t *start, size_t *len) { DEBUG("Entry |%s|", str); - if (match(str, GLOB_CHAR)) { + if (match(str, GLOB_CHAR, 0, NULL)) { size_t s_len, b_len, p_len; char *star, *b_start, *b_end, *plus; char temp_char[MAX_DM_KEY_LEN] = {'\0'}; @@ -89,10 +89,10 @@ static bool is_res_required(char *str, size_t *start, size_t *len) // Check if naming with aliases used snprintf(temp_char, *len+1, "%s", str + *start); - if (match(temp_char, GLOB_EXPR)) + if (match(temp_char, GLOB_EXPR, 0, NULL)) return true; - if (match(temp_char, "[*+]+")) + if (match(temp_char, "[*+]+", 0, NULL)) return true; } *start = DM_STRLEN(str); @@ -335,6 +335,23 @@ static bool add_paths_to_stack(struct blob_buf *bb, char *path, size_t begin, return true; } +static void bb_add_flags_arr(struct blob_buf *bb, char *data) +{ + uint32_t *dm_falgs = (uint32_t *)data; + + if (!bb || !dm_falgs) + return; + + void *flags_arr = blobmsg_open_array(bb, "flags"); + + if (*dm_falgs & DM_FLAG_REFERENCE) + bb_add_string(bb, NULL, "Reference"); + else if (*dm_falgs & DM_FLAG_UNIQUE) + bb_add_string(bb, NULL, "Unique"); + + blobmsg_close_array(bb, flags_arr); +} + // public functions void prepare_result_blob(struct blob_buf *bb, struct list_head *pv_list) { @@ -419,6 +436,7 @@ void prepare_raw_result(struct blob_buf *bb, struct dmctx *bbf_ctx, struct list_ bb_add_string(bb, "path", n->name); bb_add_string(bb, "data", n->data); bb_add_string(bb, "type", n->type); + bb_add_flags_arr(bb, n->additional_data); blobmsg_close_table(bb, table); } } else { @@ -427,6 +445,7 @@ void prepare_raw_result(struct blob_buf *bb, struct dmctx *bbf_ctx, struct list_ bb_add_string(bb, "path", n->name); bb_add_string(bb, "data", n->data); bb_add_string(bb, "type", n->type); + bb_add_flags_arr(bb, n->additional_data); blobmsg_close_table(bb, table); } } diff --git a/bbfdmd/ubus/set.h b/bbfdmd/ubus/set.h index b2a90616..5a69fe5a 100644 --- a/bbfdmd/ubus/set.h +++ b/bbfdmd/ubus/set.h @@ -4,8 +4,6 @@ #include "bbfdmd.h" #include "common.h" -#include "libbbfdm-api/dmbbf.h" - enum { DM_SET_PATH, DM_SET_VALUE, diff --git a/libbbfdm-api/dmapi.c b/libbbfdm-api/dmapi.c index 1a60a31e..1d6550f8 100644 --- a/libbbfdm-api/dmapi.c +++ b/libbbfdm-api/dmapi.c @@ -218,6 +218,33 @@ int bbf_set_alias(struct dmctx *ctx, struct uci_section *s, char *option_name, c return 0; } +int bbf_get_reference_param(char *path, char *key_name, char *key_value, char **value) +{ + if (DM_STRLEN(path) == 0 || DM_STRLEN(key_name) == 0 || DM_STRLEN(key_value) == 0 || !value) + return -1; + + dmasprintf(value, "%s[%s==\"%s\"].", path, key_name, key_value); + return 0; +} + +int bbf_get_reference_args(char *value, struct dm_reference *reference_args) +{ + if (DM_STRLEN(value) == 0) + return -1; + + reference_args->path = value; + + char *seperator = strstr(value, "=>"); + if (!seperator) + return -1; + + *seperator = 0; + + reference_args->value = seperator + 2; + + return 0; +} + __attribute__ ((deprecated)) int bbf_validate_string(char *value, int min_length, int max_length, char *enumeration[], char *pattern[]) { struct dmctx ctx = {0}; diff --git a/libbbfdm-api/dmapi.h b/libbbfdm-api/dmapi.h index 3c41f773..84aee839 100644 --- a/libbbfdm-api/dmapi.h +++ b/libbbfdm-api/dmapi.h @@ -121,7 +121,8 @@ typedef struct dm_leaf_s { int (*getvalue)(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); int (*setvalue)(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action); int bbfdm_type; - char version[10] __attribute__((deprecated)); + uint32_t dm_falgs; + } DMLEAF; typedef struct dm_obj_s { @@ -139,7 +140,6 @@ typedef struct dm_obj_s { int (*get_linker)(char *refparam, struct dmctx *dmctx, void *data, char *instance, char **linker); int bbfdm_type; const char **unique_keys; - char version[10] __attribute__((deprecated)); } DMOBJ; struct dm_parameter { @@ -166,6 +166,11 @@ typedef struct dm_map_vendor_exclude { char **vendor_obj; } DM_MAP_VENDOR_EXCLUDE; +struct dm_reference { + char *path; + char *value; +}; + struct dmctx { bool stop; bool match; @@ -233,6 +238,11 @@ typedef struct { const char **param; } event_args; +enum dm_flags_enum { + DM_FLAG_REFERENCE = 1, + DM_FLAG_UNIQUE = 1<<1 +}; + enum set_value_action { VALUECHECK, VALUESET diff --git a/libbbfdm-api/dmbbf.c b/libbbfdm-api/dmbbf.c index 436e4f1d..c82bdfb1 100644 --- a/libbbfdm-api/dmbbf.c +++ b/libbbfdm-api/dmbbf.c @@ -840,6 +840,50 @@ static int is64digit(char c) return 0; } +static char *get_value_by_reference(struct dmctx *ctx, char *value) +{ + char *pch = NULL, *spch = NULL, *val = NULL; + char buf[MAX_DM_PATH * 4] = {0}; + + if (DM_STRLEN(value) == 0) + return value; + + DM_STRNCPY(buf, value, sizeof(buf)); + + for (pch = strtok_r(buf, ",", &spch); pch; pch = strtok_r(NULL, ",", &spch)) { + char path[MAX_DM_PATH] = {0}; + char key_name[256], key_value[256]; + regmatch_t pmatch[2]; + + bool res = match(pch, "\\[(.*?)\\]", 2, pmatch); + if (!res) + return value; + + snprintf(path, pmatch[0].rm_so + 1, "%s", pch); + int len = DM_STRLEN(path); + if (!len) + return value; + + + char *match_str = pch + pmatch[1].rm_so; + if (DM_STRLEN(match_str) == 0) + return value; + + int n = sscanf(match_str, "%[^=]==\"%[^\"]\"", key_name, key_value); + if (n != 2) + return value; + + snprintf(path + len, sizeof(path) - len, "*.%s", key_name); + + adm_entry_get_reference_param(ctx, path, key_value, &val); + + if (DM_STRLEN(val)) + return val; + } + + return value; +} + static char *check_value_by_type(char *value, int type) { int i = 0, len = DM_STRLEN(value); @@ -933,6 +977,7 @@ static int get_ubus_value(struct dmctx *dmctx, struct dmnode *node) { json_object *res = NULL, *res_obj = NULL; char *ubus_name = node->obj->checkdep; + uint32_t dm_falgs = 0; json_object *in_args = json_object_new_object(); json_object_object_add(in_args, "proto", json_object_new_string((dmctx->dm_type == BBFDM_BOTH) ? "both" : (dmctx->dm_type == BBFDM_CWMP) ? "cwmp" : "usp")); @@ -975,7 +1020,25 @@ static int get_ubus_value(struct dmctx *dmctx, struct dmnode *node) char *data = dmjson_get_value(res_obj, 1, "data"); char *type = dmjson_get_value(res_obj, 1, "type"); - add_list_parameter(dmctx, dmstrdup(path), dmstrdup(data), dmstrdup(type), NULL); + json_object *flags_array = dmjson_get_obj(res_obj, 1, "flags"); + if (flags_array) { + size_t nbre_falgs = json_object_array_length(flags_array); + + for (size_t j = 0; j < nbre_falgs; j++) { + json_object *flag_obj = json_object_array_get_idx(flags_array, j); + + const char *flag = json_object_get_string(flag_obj); + + if (DM_STRCMP(flag, "Reference") == 0) { + data = get_value_by_reference(dmctx, data); + dm_falgs |= DM_FLAG_REFERENCE; + } else if (DM_STRCMP(flag, "Unique") == 0) { + dm_falgs |= DM_FLAG_UNIQUE; + } + } + } + + add_list_parameter(dmctx, dmstrdup(path), dmstrdup(data), dmstrdup(type), flags_array ? (char *)&dm_falgs : NULL); } return 0; @@ -1236,20 +1299,58 @@ static int del_ubus_object(struct dmctx *dmctx, struct dmnode *node) return 0; } +static bool is_reference_parameter(char *ubus_name, char *param_name, json_object *in_args) +{ + json_object *res = NULL, *res_obj = NULL; + + dmubus_call(ubus_name, "get", + UBUS_ARGS{ + {"path", param_name, String}, + {"optional", json_object_to_json_string(in_args), Table} + }, + 2, &res); + + if (!res) + return false; + + json_object *res_array = dmjson_get_obj(res, 1, "results"); + if (!res_array) + return false; + + res_obj = json_object_array_get_idx(res_array, 0); + if (!res_obj) + return false; + + char *flags_list = dmjson_get_value_array_all(res_obj, ",", 1, "flags"); + + return DM_STRSTR(flags_list, "Reference") ? true : false; +} + static int set_ubus_value(struct dmctx *dmctx, struct dmnode *node) { json_object *res = NULL, *res_obj = NULL; char *ubus_name = node->obj->checkdep; + char param_value[512] = {0}; json_object *in_args = json_object_new_object(); json_object_object_add(in_args, "proto", json_object_new_string((dmctx->dm_type == BBFDM_BOTH) ? "both" : (dmctx->dm_type == BBFDM_CWMP) ? "cwmp" : "usp")); json_object_object_add(in_args, "instance_mode", json_object_new_string(dmctx->instance_mode ? "1" : "0")); json_object_object_add(in_args, "format", json_object_new_string("raw")); + if (is_reference_parameter(ubus_name, dmctx->in_param, in_args)) { + char *linker = NULL; + + adm_entry_get_linker_value(dmctx, dmctx->in_value, &linker); + + snprintf(param_value, sizeof(param_value), "%s=>%s", dmctx->in_value, linker ? linker : ""); + } else { + snprintf(param_value, sizeof(param_value), "%s", dmctx->in_value); + } + dmubus_call(ubus_name, "set", UBUS_ARGS{ {"path", dmctx->in_param, String}, - {"value", dmctx->in_value, String}, + {"value", param_value, String}, {"optional", json_object_to_json_string(in_args), Table} }, 3, &res); @@ -1417,12 +1518,15 @@ static int get_value_param(DMPARAM_ARGS) (leaf->getvalue)(full_param, dmctx, data, instance, &value); if (value && *value) { - value = check_value_by_type(value, leaf->type); + if (leaf->dm_falgs & DM_FLAG_REFERENCE) { + value = get_value_by_reference(dmctx, value); + } else + value = check_value_by_type(value, leaf->type); } else { value = get_default_value_by_type(leaf->type); } - add_list_parameter(dmctx, full_param, value, DMT_TYPE[leaf->type], NULL); + add_list_parameter(dmctx, full_param, value, DMT_TYPE[leaf->type], leaf->dm_falgs ? (char *)&leaf->dm_falgs : NULL); } return 0; @@ -1462,12 +1566,15 @@ static int mparam_get_value_in_param(DMPARAM_ARGS) (leaf->getvalue)(full_param, dmctx, data, instance, &value); if (value && *value) { - value = check_value_by_type(value, leaf->type); + if (leaf->dm_falgs & DM_FLAG_REFERENCE) { + value = get_value_by_reference(dmctx, value); + } else + value = check_value_by_type(value, leaf->type); } else { value = get_default_value_by_type(leaf->type); } - add_list_parameter(dmctx, full_param, value, DMT_TYPE[leaf->type], NULL); + add_list_parameter(dmctx, full_param, value, DMT_TYPE[leaf->type], leaf->dm_falgs ? (char *)&leaf->dm_falgs : NULL); dmctx->findparam = (dmctx->iswildcard) ? 1 : 0; dmctx->stop = (dmctx->iswildcard) ? false : true; @@ -1986,9 +2093,9 @@ static int mparam_set_value(DMPARAM_ARGS) if (node->is_ubus_service) { return set_ubus_value(dmctx, node); } else { - char refparam[MAX_DM_PATH]; + char refparam[MAX_DM_PATH] = {0}; + char param_value[512] = {0}; char *value = ""; - bool val = false; snprintf(refparam, MAX_DM_PATH, "%s%s", node->current_object, leaf->parameter); if (DM_STRCMP(refparam, dmctx->in_param) != 0) @@ -2006,6 +2113,8 @@ static int mparam_set_value(DMPARAM_ARGS) (leaf->getvalue)(refparam, dmctx, data, instance, &value); if (leaf->type == DMT_BOOL) { + bool val = false; + string_to_bool(dmctx->in_value, &val); if (dmuci_string_to_boolean(value) == val) { TRACE("Requested value (%s) is same as current value (%s)", dmctx->in_value, value); @@ -2018,7 +2127,17 @@ static int mparam_set_value(DMPARAM_ARGS) } } - return (leaf->setvalue)(refparam, dmctx, data, instance, dmctx->in_value, dmctx->setaction); + if ((leaf->dm_falgs & DM_FLAG_REFERENCE) && !DM_STRSTR(dmctx->in_value, "=>")) { + char *linker = NULL; + + adm_entry_get_linker_value(dmctx, dmctx->in_value, &linker); + + snprintf(param_value, sizeof(param_value), "%s=>%s", dmctx->in_value, linker ? linker : ""); + } else { + snprintf(param_value, sizeof(param_value), "%s", dmctx->in_value); + } + + return (leaf->setvalue)(refparam, dmctx, data, instance, param_value, dmctx->setaction); } } @@ -2044,6 +2163,55 @@ int dm_entry_set_value(struct dmctx *dmctx) return (dmctx->stop) ? err : FAULT_9005; } +/****************** + * get linker param + *****************/ +static int get_key_check_obj(DMOBJECT_ARGS) +{ + return FAULT_9005; +} + +static int get_key_check_param(DMPARAM_ARGS) +{ + char *full_param; + char *value = ""; + + dmastrcat(&full_param, node->current_object, leaf->parameter); + + if (dm_strcmp_wildcard(dmctx->in_param, full_param) != 0) { + dmfree(full_param); + return FAULT_9005; + } + + (leaf->getvalue)(full_param, dmctx, data, instance, &value); + + if (value && value[0] != '\0' && DM_STRCMP(value, dmctx->linker) == 0) { + if (node->current_object[DM_STRLEN(node->current_object) - 1] == '.') + node->current_object[DM_STRLEN(node->current_object) - 1] = 0; + dmctx->linker_param = dmstrdup(node->current_object); + dmctx->stop = true; + return 0; + } + + return FAULT_9005; +} + +int dm_entry_get_reference_param(struct dmctx *dmctx) +{ + int err = 0; + DMOBJ *root = dmctx->dm_entryobj; + DMNODE node = { .current_object = "" }; + + dmctx->checkobj = plugin_obj_wildcard_match; + dmctx->checkleaf = plugin_leaf_wildcard_match; + dmctx->method_obj = get_key_check_obj; + dmctx->method_param = get_key_check_param; + + err = dm_browse(dmctx, &node, root, NULL, NULL); + + return (dmctx->stop) ? err : FAULT_9005; +} + /****************** * get linker param *****************/ diff --git a/libbbfdm-api/dmbbf.h b/libbbfdm-api/dmbbf.h index c0cee82e..a9d1a1dc 100644 --- a/libbbfdm-api/dmbbf.h +++ b/libbbfdm-api/dmbbf.h @@ -43,6 +43,7 @@ int dm_entry_add_object(struct dmctx *dmctx); int dm_entry_delete_object(struct dmctx *dmctx); int dm_entry_set_value(struct dmctx *dmctx); int dm_entry_operate(struct dmctx *dmctx); +int dm_entry_get_reference_param(struct dmctx *dmctx); int dm_entry_get_linker(struct dmctx *dmctx); int dm_entry_get_linker_value(struct dmctx *dmctx); int dm_link_inst_obj(struct dmctx *dmctx, DMNODE *parent_node, void *data, char *instance); diff --git a/libbbfdm-api/dmcommon.c b/libbbfdm-api/dmcommon.c index cb335916..ededa430 100644 --- a/libbbfdm-api/dmcommon.c +++ b/libbbfdm-api/dmcommon.c @@ -1241,14 +1241,18 @@ void convert_hex_option_to_string(unsigned int tag, const char *hex, char *str, str[pos - 1] = 0; } -bool match(const char *string, const char *pattern) +bool match(const char *string, const char *pattern, size_t nmatch, regmatch_t pmatch[]) { regex_t re; - if (regcomp(&re, pattern, REG_EXTENDED) != 0) return 0; - int status = regexec(&re, string, 0, NULL, 0); + + if (regcomp(&re, pattern, REG_EXTENDED) != 0) + return 0; + + int status = regexec(&re, string, nmatch, pmatch, 0); + regfree(&re); - if (status != 0) return false; - return true; + + return (status != 0) ? false : true; } void bbfdm_set_fault_message(struct dmctx *ctx, const char *format, ...) @@ -1293,7 +1297,7 @@ static int bbfdm_validate_string_enumeration(struct dmctx *ctx, char *value, cha static int bbfdm_validate_string_pattern(struct dmctx *ctx, char *value, char *pattern[]) { for (; *pattern; pattern++) { - if (match(value, *pattern)) + if (match(value, *pattern, 0, NULL)) return 0; } diff --git a/libbbfdm-api/dmcommon.h b/libbbfdm-api/dmcommon.h index 686e8221..3763cb79 100644 --- a/libbbfdm-api/dmcommon.h +++ b/libbbfdm-api/dmcommon.h @@ -65,6 +65,7 @@ #include "dmuci.h" #include "dmubus.h" #include "dmjson.h" +#include "dmentry.h" extern char *Encapsulation[]; extern char *LinkType[]; @@ -224,9 +225,11 @@ void get_dmmap_section_of_config_section(char* dmmap_package, char* section_type void get_dmmap_section_of_config_section_eq(char* dmmap_package, char* section_type, char *opt, char* value, struct uci_section **dmmap_section); void get_dmmap_section_of_config_section_cont(char* dmmap_package, char* section_type, char *opt, char* value, struct uci_section **dmmap_section); void get_config_section_of_dmmap_section(char* package, char* section_type, char *section_name, struct uci_section **config_section); +int adm_entry_get_reference_param(struct dmctx *ctx, char *param, char *linker, char **value); int adm_entry_get_linker_param(struct dmctx *ctx, char *param, char *linker, char **value); int adm_entry_get_linker_value(struct dmctx *ctx, char *param, char **value); int dm_entry_validate_allowed_objects(struct dmctx *ctx, char *value, char *objects[]); +int dm_entry_validate_external_linker_allowed_objects(struct dmctx *ctx, char *value, char *objects[]); char *check_create_dmmap_package(const char *dmmap_package); unsigned int count_occurrences(char *str, char c); unsigned char isdigit_str(char *str); @@ -266,7 +269,7 @@ void convert_string_to_hex(const char *str, char *hex, size_t size); void convert_hex_to_string(const char *hex, char *str, size_t size); void convert_str_option_to_hex(unsigned int tag, const char *str, char *hex, size_t size); void convert_hex_option_to_string(unsigned int tag, const char *hex, char *str, size_t size); -bool match(const char *string, const char *pattern); +bool match(const char *string, const char *pattern, size_t nmatch, regmatch_t pmatch[]); void bbfdm_set_fault_message(struct dmctx *ctx, const char *format, ...); int bbfdm_validate_boolean(struct dmctx *ctx, char *value); int bbfdm_validate_unsignedInt(struct dmctx *ctx, char *value, struct range_args r_args[], int r_args_size); @@ -284,6 +287,8 @@ int bbfdm_validate_string_list(struct dmctx *ctx, char *value, int min_item, int int bbfdm_validate_hexBinary_list(struct dmctx *ctx, char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size); int bbf_get_alias(struct dmctx *ctx, struct uci_section *s, char *option_name, char *instance, char **value); int bbf_set_alias(struct dmctx *ctx, struct uci_section *s, char *option_name, char *instance, char *value); +int bbf_get_reference_param(char *path, char *key_name, char *key_value, char **value); +int bbf_get_reference_args(char *value, struct dm_reference *reference_args); char *base64_decode(const char *src); void string_to_mac(const char *str, size_t str_len, char *out, size_t out_len); bool folder_exists(const char *path); diff --git a/libbbfdm-api/dmentry.c b/libbbfdm-api/dmentry.c index 742ed369..50383eea 100644 --- a/libbbfdm-api/dmentry.c +++ b/libbbfdm-api/dmentry.c @@ -280,7 +280,7 @@ int dm_entry_validate_allowed_objects(struct dmctx *ctx, char *value, char *obje for (; *objects; objects++) { - if (match(value, *objects)) { + if (match(value, *objects, 0, NULL)) { char *linker = NULL; adm_entry_get_linker_value(ctx, value, &linker); @@ -293,6 +293,46 @@ int dm_entry_validate_allowed_objects(struct dmctx *ctx, char *value, char *obje return -1; } +int dm_entry_validate_external_linker_allowed_objects(struct dmctx *ctx, char *value, char *objects[]) +{ + if (!value || !objects) + return -1; + + if (*value == '\0') + return 0; + + for (; *objects; objects++) { + + if (match(value, *objects, 0, NULL)) + return 0; + } + + bbfdm_set_fault_message(ctx, "'%s' value is not allowed.", value); + return -1; +} + +int adm_entry_get_reference_param(struct dmctx *ctx, char *param, char *linker, char **value) +{ + struct dmctx dmctx = {0}; + *value = ""; + + if (!param || !linker || *linker == 0) + return 0; + + bbf_ctx_init_sub(&dmctx, ctx->dm_entryobj, ctx->dm_vendor_extension, ctx->dm_vendor_extension_exclude); + + dmctx.iswildcard = 1; + dmctx.inparam_isparam = 1; + dmctx.in_param = param; + dmctx.linker = linker; + + dm_entry_get_reference_param(&dmctx); + *value = dmctx.linker_param; + + bbf_ctx_clean_sub(&dmctx); + return 0; +} + int adm_entry_get_linker_param(struct dmctx *ctx, char *param, char *linker, char **value) { struct dmctx dmctx = {0}; diff --git a/libbbfdm-api/dmentry.h b/libbbfdm-api/dmentry.h index 74660be2..164411f1 100644 --- a/libbbfdm-api/dmentry.h +++ b/libbbfdm-api/dmentry.h @@ -33,6 +33,7 @@ void bbf_global_init(DMOBJ *dm_entryobj, DM_MAP_VENDOR *dm_VendorExtension[], DM void bbf_global_clean(DMOBJ *dm_entryobj, DM_MAP_VENDOR *dm_VendorExtension[], DM_MAP_VENDOR_EXCLUDE *dm_VendorExtensionExclude, bool enable_plugins); int dm_entry_validate_allowed_objects(struct dmctx *ctx, char *value, char *objects[]); +int dm_entry_validate_external_linker_allowed_objects(struct dmctx *ctx, char *value, char *objects[]); int adm_entry_get_linker_param(struct dmctx *ctx, char *param, char *linker, char **value); int adm_entry_get_linker_value(struct dmctx *ctx, char *param, char **value); diff --git a/libbbfdm-api/include/libbbfdm_api.h b/libbbfdm-api/include/libbbfdm_api.h index bfe5b1e8..c7bdc3a1 100644 --- a/libbbfdm-api/include/libbbfdm_api.h +++ b/libbbfdm-api/include/libbbfdm_api.h @@ -584,6 +584,36 @@ int bbf_get_alias(struct dmctx *ctx, struct uci_section *s, char *option_name, c **************************************************************************/ int bbf_set_alias(struct dmctx *ctx, struct uci_section *s, char *option_name, char *instance, char *value); +/*********************************************************************//** +** +** bbf_get_reference_param +** +** This API is used to get the reference parameter value +** +** \param path - parent path object +** \param key_name - parameter name used to identify the object +** \param key_value - value of parameter name used to identify the object +** \param value - the value to be set +** +** \return 0 if operation is successful, -1 otherwise +** +**************************************************************************/ +int bbf_get_reference_param(char *path, char *key_name, char *key_value, char **value); + +/*********************************************************************//** +** +** bbf_get_reference_args +** +** This API is used to get the reference arguments in order to set eexternal linker +** +** \param value - +** \param reference - +** +** \return 0 if operation is successful, -1 otherwise +** +**************************************************************************/ +int bbf_get_reference_args(char *value, struct dm_reference *reference_args); + /*********************************************************************//** ** ** bbfdm_validate_string diff --git a/libbbfdm/CMakeLists.txt b/libbbfdm/CMakeLists.txt index d47d2da9..21c101a9 100644 --- a/libbbfdm/CMakeLists.txt +++ b/libbbfdm/CMakeLists.txt @@ -86,7 +86,7 @@ ENDIF(BBF_VENDOR_EXTENSION) ADD_LIBRARY(bbfdm SHARED ${BBF_DM_SOURCES} ${BBF_TR181_SOURCES} ${BBF_TR143_SOURCES} ${BBF_TR471_SOURCES} ${BBF_VENDOR_EXTENSION_SOURCES}) -TARGET_LINK_LIBRARIES(bbfdm uci ubus ubox json-c blobmsg_json curl bbfdm-api ${SSL_LIBS} ${CRYPTO_LIBS}) +TARGET_LINK_LIBRARIES(bbfdm uci ubus ubox json-c blobmsg_json curl m bbfdm-api ${SSL_LIBS} ${CRYPTO_LIBS}) INSTALL(TARGETS bbfdm LIBRARY DESTINATION usr/lib) diff --git a/libbbfdm/dmtree/tr181/bridging.c b/libbbfdm/dmtree/tr181/bridging.c index 69e1f2a7..3170bbf1 100644 --- a/libbbfdm/dmtree/tr181/bridging.c +++ b/libbbfdm/dmtree/tr181/bridging.c @@ -2097,7 +2097,7 @@ static int set_BridgingBridgePort_LowerLayers(char *refparam, struct dmctx *ctx, } else dmuci_set_value_by_section(args->bridge_port_dmmap_sec, "config", "network"); - if (match(value, "Device.Bridging.Bridge.*.Port.")) { + if (match(value, "Device.Bridging.Bridge.*.Port.", 0, NULL)) { struct uci_section *s = get_origin_section_from_dmmap("dmmap_bridge_port", "bridge_port", linker); dmuci_get_value_by_section_string(s, "port", &linker); diff --git a/libbbfdm/dmtree/tr181/ethernet.c b/libbbfdm/dmtree/tr181/ethernet.c index 80d06dd5..876e8cde 100644 --- a/libbbfdm/dmtree/tr181/ethernet.c +++ b/libbbfdm/dmtree/tr181/ethernet.c @@ -1008,7 +1008,7 @@ static int set_EthernetLink_LowerLayers(char *refparam, struct dmctx *ctx, void dmuci_set_value_by_section((struct uci_section *)data, "is_eth", !DM_STRNCMP(value, "Device.Ethernet.", strlen("Device.Ethernet.")) ? "1" : "0"); - if (match(value, "Device.Bridging.Bridge.*.Port.")) { + if (match(value, "Device.Bridging.Bridge.*.Port.", 0, NULL)) { dmuci_set_value_by_section((struct uci_section *)data, "is_eth", "1"); // Remove unused Interface section created by Bridge Object if it exists diff --git a/libbbfdm/dmtree/vendor/iopsys/tr181/times.c b/libbbfdm/dmtree/vendor/iopsys/tr181/times.c index f3399f5c..fae6d76d 100644 --- a/libbbfdm/dmtree/vendor/iopsys/tr181/times.c +++ b/libbbfdm/dmtree/vendor/iopsys/tr181/times.c @@ -24,23 +24,24 @@ static int get_time_source_interface(char *refparam, struct dmctx *ctx, void *da char *iface = NULL; dmuci_get_option_value_string("system", "ntp", "interface", &iface); - adm_entry_get_linker_param(ctx, "Device.IP.Interface.", iface, value); - return 0; + + return bbf_get_reference_param("Device.IP.Interface.", "Name", iface, value); } static int set_time_source_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) { char *allowed_objects[] = {"Device.IP.Interface.", NULL}; - char *iface = NULL; + struct dm_reference reference = {0}; + + bbf_get_reference_args(value, &reference); switch (action) { case VALUECHECK: - if (dm_entry_validate_allowed_objects(ctx, value, allowed_objects)) + if (dm_entry_validate_allowed_objects(ctx, reference.path, allowed_objects)) return FAULT_9007; break; case VALUESET: - adm_entry_get_linker_value(ctx, value, &iface); - dmuci_set_value("system", "ntp", "interface", iface ? iface : ""); + dmuci_set_value("system", "ntp", "interface", reference.value); return 0; } return 0; @@ -52,6 +53,6 @@ static int set_time_source_interface(char *refparam, struct dmctx *ctx, void *da DMLEAF tIOPSYS_TimeParams[] = { /* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/ {BBF_VENDOR_PREFIX"LocalTimeZoneName", &DMREAD, DMT_STRING, get_local_time_zone_name, NULL, BBFDM_BOTH}, -{BBF_VENDOR_PREFIX"SourceInterface", &DMWRITE, DMT_STRING, get_time_source_interface, set_time_source_interface, BBFDM_BOTH}, +{BBF_VENDOR_PREFIX"SourceInterface", &DMWRITE, DMT_STRING, get_time_source_interface, set_time_source_interface, BBFDM_BOTH, DM_FLAG_REFERENCE}, {0} };