Redesign the handling of references based on uci reference_translation

This commit is contained in:
Amin Ben Romdhane 2025-03-27 13:40:53 +01:00
parent e3757b5f37
commit 45a6d7e0c7
19 changed files with 315 additions and 448 deletions

View file

@ -56,7 +56,7 @@ static int bbfdm_handler_async(struct ubus_context *ctx, struct ubus_object *obj
return UBUS_STATUS_UNKNOWN_ERROR;
}
BBFDM_INFO("ubus method|%s|, name|%s|", method, obj->name);
BBFDM_INFO("START: ubus method|%s|, name|%s|", method, obj->name);
snprintf(context->requested_path, sizeof(context->requested_path), "%s", blobmsg_get_string(tb[BBFDM_PATH]));
snprintf(context->ubus_method, sizeof(context->ubus_method), "%s", method);
@ -66,13 +66,6 @@ static int bbfdm_handler_async(struct ubus_context *ctx, struct ubus_object *obj
memset(&context->tmp_bb, 0, sizeof(struct blob_buf));
blob_buf_init(&context->tmp_bb, 0);
if (strcmp(method, "get") == 0) {
INIT_LIST_HEAD(&context->linker_list);
// Send linker cleanup event for all services
send_linker_cleanup_event(ctx);
}
fill_optional_input(tb[BBFDM_INPUT], &requested_proto, &context->raw_format);
ubus_defer_request(ctx, req, &context->request_data);

View file

@ -111,33 +111,6 @@ static void sync_callback(struct ubus_request *req, int type __attribute__((unus
}
}
static void generate_reference_to_set(const char *in_value, char *output_str, size_t output_str_len)
{
char token_buffer[MAX_VALUE_LENGTH] = {0};
char *token = NULL, *saveptr = NULL;
unsigned pos = 0;
if (!output_str || output_str_len == 0)
return;
output_str[0] = '\0'; // Ensure output buffer is initialized
if (!in_value || in_value[0] == '\0') // Empty value, nothing to make
return;
bbfdm_strncpy(token_buffer, in_value, sizeof(token_buffer));
for (token = strtok_r(token_buffer, ",", &saveptr); token; token = strtok_r(NULL, ",", &saveptr)) {
char *reference_value = get_reference_data(token, "reference_value");
pos += snprintf(&output_str[pos], output_str_len - pos, "%s=>%s##,", token, reference_value ? reference_value : "");
BBFDM_FREE(reference_value);
}
if (pos > 0) {
output_str[pos - 1] = 0; // Remove trailing comma
}
}
void run_sync_call(const char *ubus_obj, const char *ubus_method, struct blob_attr *msg, struct blob_buf *bb_response)
{
struct blob_buf req_buf = {0};
@ -151,37 +124,7 @@ void run_sync_call(const char *ubus_obj, const char *ubus_method, struct blob_at
blob_buf_init(&req_buf, 0);
blob_for_each_attr(attr, msg, remaining) {
if (strcmp(ubus_method, "set") == 0 &&
strcmp(blobmsg_name(attr), "value") == 0 &&
blobmsg_type(attr) == BLOBMSG_TYPE_STRING &&
strncmp(BBFDM_ROOT_OBJECT, blobmsg_get_string(attr), strlen(BBFDM_ROOT_OBJECT)) == 0) {
char reference_to_set[MAX_VALUE_LENGTH] = {0};
generate_reference_to_set(blobmsg_get_string(attr), reference_to_set, sizeof(reference_to_set));
blobmsg_add_string(&req_buf, blobmsg_name(attr), reference_to_set);
} if (strcmp(ubus_method, "set") == 0 &&
strcmp(blobmsg_name(attr), "obj_path") == 0 &&
blobmsg_type(attr) == BLOBMSG_TYPE_TABLE) {
struct blob_attr *__attr = NULL;
int rem = 0;
void *table = blobmsg_open_table(&req_buf, "obj_path");
blobmsg_for_each_attr(__attr, attr, rem) {
if (blobmsg_type(__attr) == BLOBMSG_TYPE_STRING && strncmp(BBFDM_ROOT_OBJECT, blobmsg_get_string(__attr), strlen(BBFDM_ROOT_OBJECT)) == 0) {
char reference_to_set[MAX_VALUE_LENGTH] = {0};
generate_reference_to_set(blobmsg_get_string(__attr), reference_to_set, sizeof(reference_to_set));
blobmsg_add_string(&req_buf, blobmsg_name(__attr), reference_to_set);
} else {
blobmsg_add_string(&req_buf, blobmsg_name(__attr), blobmsg_get_string(__attr));
}
}
blobmsg_close_table(&req_buf, table);
} else {
blobmsg_add_field(&req_buf, blobmsg_type(attr), blobmsg_name(attr), blobmsg_data(attr), blobmsg_len(attr));
}
blobmsg_add_field(&req_buf, blobmsg_type(attr), blobmsg_name(attr), blobmsg_data(attr), blobmsg_len(attr));
}
if (g_log_level == LOG_DEBUG) {

View file

@ -37,8 +37,6 @@ struct blob_attr *get_results_array(struct blob_attr *msg);
bool proto_matches(unsigned int dm_type, const enum bbfdmd_type_enum type);
char *get_reference_data(const char *path, const char *method_name);
void run_sync_call(const char *ubus_obj, const char *ubus_method, struct blob_attr *msg, struct blob_buf *bb_response);
#endif /* BBFDMD_COMMON_H */

View file

@ -82,6 +82,41 @@ static void fill_blob_param(struct blob_buf *bb, struct blob_attr *path, const c
blobmsg_close_table(bb, table);
}
// Function to calculate FNV-1 hash
static void calculate_hash(const char *input, char *output, size_t out_len)
{
#define FNV_OFFSET_BASIS 0x811C9DC5
#define FNV_PRIME 0x1000193
uint32_t hash = FNV_OFFSET_BASIS;
while (*input != '\0') {
hash *= FNV_PRIME; // Multiply hash by prime
hash ^= (uint8_t)(*input); // XOR with current character
input++;
}
snprintf(output, out_len, "%08X", hash);
}
static int _uci_get_option_str(struct uci_context *uci_ctx,
const char *package, const char *section, const char *option,
char *out, size_t out_len)
{
struct uci_ptr ptr = {0};
char buf[128] = {0};
snprintf(buf, sizeof(buf), "%s.%s.%s", package, section, option);
if (uci_lookup_ptr(uci_ctx, &ptr, buf, true) != UCI_OK)
return -1;
if (ptr.o && ptr.o->type == UCI_TYPE_STRING)
snprintf(out, out_len, "%s", ptr.o->v.string);
return 0;
}
static void resolve_reference_path(struct async_request_context *ctx, struct blob_attr *data, char *output, size_t output_len)
{
if (!ctx || !output || output_len == 0) {
@ -145,16 +180,19 @@ static void resolve_reference_path(struct async_request_context *ctx, struct blo
// If not found, attempt to resolve via micro-services
{
// Try to get reference value from micro-services directly
char *reference_path = get_reference_data(token, "reference_path");
char reference_path[1024] = {0};
char hash_str[9] = {0};
calculate_hash(token, hash_str, sizeof(hash_str));
_uci_get_option_str(ctx->uci_ctx, "reference_translation", "reference_path", hash_str, reference_path, sizeof(reference_path));
// Add path to list in order to be used by other parameters
add_linker_entry(ctx, token, reference_path ? reference_path : "");
add_linker_entry(ctx, token, reference_path);
// Reference value is found
if (reference_path != NULL) {
if (strlen(reference_path) != 0) {
pos += snprintf(&output[pos], output_len - pos, "%s,", reference_path);
BBFDM_FREE(reference_path);
if (!is_ref_list) break;
}
}
@ -189,7 +227,6 @@ static void prepare_and_send_response(struct async_request_context *ctx)
blobmsg_close_table(&bb_raw, table);
} else {
blobmsg_for_each_attr(attr, ctx->tmp_bb.head, remaining) {
if (strcmp(ctx->ubus_method, "get") == 0) {
struct blob_attr *fields[4];
const struct blobmsg_policy policy[4] = {
@ -235,15 +272,29 @@ static void prepare_and_send_response(struct async_request_context *ctx)
void send_response(struct async_request_context *ctx)
{
if (strcmp(ctx->ubus_method, "get") == 0) {
// Init linker list for only Get method
INIT_LIST_HEAD(&ctx->linker_list);
// Init uci context for only Get method
ctx->uci_ctx = uci_alloc_context();
if (ctx->uci_ctx) uci_set_confdir(ctx->uci_ctx, "/etc/bbfdm/dmmap/");
}
prepare_and_send_response(ctx);
if (strcmp(ctx->ubus_method, "get") == 0) {
send_linker_cleanup_event(ctx->ubus_ctx);
// Free uci context for only Get method
if (ctx->uci_ctx) uci_free_context(ctx->uci_ctx);
// Free linker list for only Get method
free_linker_entries(ctx);
}
ubus_complete_deferred_request(ctx->ubus_ctx, &ctx->request_data, UBUS_STATUS_OK);
blob_buf_free(&ctx->tmp_bb);
BBFDM_INFO("END: ubus method|%s|, name|bbfdm|", ctx->ubus_method);
BBFDM_FREE(ctx);
}
@ -363,14 +414,3 @@ void run_async_call(struct async_request_context *ctx, const char *ubus_obj, str
blob_buf_free(&req_buf);
}
void send_linker_cleanup_event(struct ubus_context *ctx)
{
struct blob_buf bb = {0};
memset(&bb, 0, sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
ubus_send_event(ctx, "bbfdm.linker.cleanup", bb.head);
blob_buf_free(&bb);
}

View file

@ -27,6 +27,7 @@ struct linker_args {
struct async_request_context {
struct ubus_context *ubus_ctx;
struct uci_context *uci_ctx;
struct ubus_request_data request_data;
struct list_head linker_list;
struct blob_buf tmp_bb;
@ -45,8 +46,6 @@ struct ubus_request_tracker {
char request_name[128];
};
void send_linker_cleanup_event(struct ubus_context *ctx);
void run_async_call(struct async_request_context *ctx, const char *ubus_obj, struct blob_attr *msg);
void send_response(struct async_request_context *ctx);

View file

@ -253,73 +253,3 @@ bool is_path_match(const char *requested_path, unsigned int requested_proto, ser
return false;
}
static char *get_ubus_object_name(const char *path)
{
service_entry_t *service = NULL;
list_for_each_entry(service, &registered_services, list) {
if (!is_path_match(path, BBFDMD_BOTH, service))
continue;
return service->name;
}
return NULL;
}
static void reference_data_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg)
{
struct blob_attr *fields[1];
const struct blobmsg_policy policy[1] = {
{ "data", BLOBMSG_TYPE_STRING },
};
if (!req || !msg)
return;
char *reference_data = (char *)req->priv;
if (!reference_data)
return;
blobmsg_parse(policy, 1, fields, blobmsg_data(msg), blobmsg_len(msg));
if (fields[0]) {
snprintf(reference_data, MAX_PATH_LENGTH - 1, "%s", blobmsg_get_string(fields[0]));
BBFDM_DEBUG("reference_data '%s'", reference_data);
}
}
char *get_reference_data(const char *path, const char *method_name)
{
struct blob_buf req_buf = {0};
char reference_value[MAX_PATH_LENGTH] = {0};
if (!path)
return NULL;
char *ubus_obj = get_ubus_object_name(path);
if (!ubus_obj)
return NULL;
reference_value[0] = 0;
memset(&req_buf, 0, sizeof(struct blob_buf));
blob_buf_init(&req_buf, 0);
blobmsg_add_string(&req_buf, "path", path);
if (g_log_level == LOG_DEBUG) {
char *json_str = blobmsg_format_json_indent(req_buf.head, true, -1);
BBFDM_DEBUG("### ubus call %s %s '%s' ###", ubus_obj, method_name, json_str);
BBFDM_FREE(json_str);
}
BBFDM_UBUS_INVOKE_SYNC(ubus_obj, method_name, req_buf.head, 2000, reference_data_callback, &reference_value);
blob_buf_free(&req_buf);
return (reference_value[0] != 0) ? strdup(reference_value) : NULL;
}

View file

@ -264,12 +264,12 @@ int bbfdm_get_references(struct dmctx *ctx, int match_action, const char *base_p
return 0;
}
if (out_len - len < strlen(base_path) + strlen(key_name) + strlen(key_value) + 9) { // 9 = 'path[key_name==\"key_value\"].'
if (out_len - len < strlen(base_path) + strlen(key_name) + strlen(key_value) + 7) { // 7 = 'path[key_name=="key_value"].'
BBF_ERR("Buffer overflow detected. The output buffer is not large enough to hold the additional data!!!");
return -1;
}
snprintf(param_path, sizeof(param_path), "%s[%s==\"%s\"].", base_path, key_name, key_value);
snprintf(param_path, sizeof(param_path), "%s[%s==%s].", base_path, key_name, key_value);
snprintf(&out[len], out_len - len, "%s%s", len ? (match_action == MATCH_FIRST ? "," : ";") : "", param_path);
@ -289,27 +289,27 @@ int _bbfdm_get_references(struct dmctx *ctx, const char *base_path, const char *
int bbfdm_get_reference_linker(struct dmctx *ctx, char *reference_path, struct dm_reference *reference_args)
{
if (DM_STRLEN(reference_path) == 0) {
bbfdm_set_fault_message(ctx, "%s: reference path should not be empty", __func__);
char hash_str[9] = {0};
char *uci_val = NULL;
if (!reference_path || !reference_args)
return -1;
}
reference_args->path = reference_path;
char *separator = strstr(reference_path, "=>");
if (!separator) {
bbfdm_set_fault_message(ctx, "%s: reference path must contain '=>' symbol to separate the path and value", __func__);
return -1;
}
if (DM_STRLEN(reference_args->path) == 0)
return 0;
*separator = 0;
calculate_hash(reference_path, hash_str, sizeof(hash_str));
reference_args->value = separator + 2;
int res = dmuci_get_option_value_string_bbfdm("reference_translation", "reference_value", hash_str, &uci_val);
char *valid_path = strstr(separator + 2, "##");
if (valid_path) {
if (uci_val && uci_val[0] == '#' && uci_val[1] == '\0') {
reference_args->value = uci_val;
reference_args->is_valid_path = true;
*valid_path = 0;
} else {
reference_args->value = uci_val;
reference_args->is_valid_path = (res == 0) ? true : false;
}
return 0;

View file

@ -273,6 +273,7 @@ enum {
BBF_DEL_OBJECT,
BBF_OPERATE,
BBF_EVENT,
BBF_REFERENCES_DB
};
enum {

View file

@ -887,125 +887,93 @@ static char *get_default_value_by_type(const char *param_name, int type)
}
}
static void convert_to_regex(const char *input, char *output)
{
int j = 0;
for (int i = 0; input[i] != '\0'; i++) {
if (input[i] == '.') {
output[j++] = '\\'; // Escape '.'
output[j++] = '.';
} else if (input[i] == '*') {
output[j++] = '['; // Replace '*' with '[^.]+'
output[j++] = '^';
output[j++] = '.';
output[j++] = ']';
output[j++] = '+';
} else {
output[j++] = input[i]; // Copy other characters
}
}
output[j++] = '.'; // Allow anything after the base match
output[j++] = '*';
output[j] = '\0'; // Null-terminate the string
}
static bool is_same_reference_path(const char *curr_value, const char *in_value, char *out, size_t out_len)
static bool is_same_reference_path(const char *curr_value, const char *in_value)
{
char *pch = NULL, *pchr = NULL;
char resolved_path[2048] = {0};
char buf[2048] = {0};
unsigned pos = 0;
if (!curr_value || !in_value || !out || !out_len)
if (!curr_value || !in_value)
return false;
if (strcmp(curr_value, in_value) == 0)
return true;
if (DM_STRLEN(in_value) == 0) {
DM_STRNCPY(out, "=>", sizeof(out_len));
return false;
}
char *in_value_list = strchr(in_value, ',');
if (in_value_list) {
char formatted_value[2048] = {0};
long int pos = 0;
DM_STRNCPY(buf, in_value, sizeof(buf));
formatted_value[0] = '\0';
for (pch = strtok_r(buf, ",", &pchr); pch != NULL; pch = strtok_r(NULL, ",", &pchr)) {
if (formatted_value[0] == '\0') {
pos += snprintf(formatted_value, sizeof(formatted_value), "%s", pch);
} else {
pos += snprintf(&formatted_value[pos], sizeof(formatted_value) - pos, ";%s", pch);
}
char *delimiter_pos = DM_STRSTR(formatted_value, "=>");
if (delimiter_pos) {
pos = labs(delimiter_pos - formatted_value);
*delimiter_pos = '\0';
}
}
if (strcmp(curr_value, formatted_value) == 0)
return true;
else
return false;
}
DM_STRNCPY(buf, curr_value, sizeof(buf));
for (pch = strtok_r(buf, ",", &pchr); pch != NULL; pch = strtok_r(NULL, ",", &pchr)) {
char *is_list = strchr(buf, ';');
for (pch = strtok_r(buf, is_list ? ";" : ",", &pchr);
pch != NULL;
pch = strtok_r(NULL, is_list ? ";" : ",", &pchr)) {
char *p = strchr(pch, '[');
if (p) {
char regex_pattern[MAX_DM_PATH * 2] = {0};
char path[MAX_DM_PATH] = {0};
char key_name[256], key_value[256];
regmatch_t pmatch[2];
regmatch_t p_match[1];
char hash_str[9] = {0};
char *uci_val = NULL;
if (!match(pch, "\\[(.*?)\\]", 2, pmatch))
continue;
calculate_hash(pch, hash_str, sizeof(hash_str));
snprintf(path, pmatch[0].rm_so + 1, "%s", pch);
int len = DM_STRLEN(path);
if (!len)
continue;
dmuci_get_option_value_string_bbfdm("reference_translation", "reference_path", hash_str, &uci_val);
char *match_str = pch + pmatch[1].rm_so;
if (DM_STRLEN(match_str) == 0)
continue;
int n = sscanf(match_str, "%255[^=]==\"%255[^\"]\"", key_name, key_value);
if (n != 2) {
n = sscanf(match_str, "%255[^=]==%255[^]]", key_name, key_value);
if (n != 2)
continue;
}
char *tag = strstr(in_value, "=>");
if (!tag)
continue;
convert_to_regex(path, regex_pattern);
if (match(in_value, regex_pattern, 1, p_match) && strncmp(key_value, tag + 2, strlen(key_value)) == 0) {
return true;
if (DM_STRLEN(uci_val)) {
pos += snprintf(&resolved_path[pos], sizeof(resolved_path) - pos, "%s,", uci_val);
}
} else {
if (strncmp(pch, in_value, strlen(pch)) == 0)
return true;
pos += snprintf(&resolved_path[pos], sizeof(resolved_path) - pos, "%s,", pch);
}
if (pos != 0 && is_list == false)
break;
}
if (pos > 0) {
resolved_path[pos - 1] = 0; // Remove trailing comma
}
if (strcmp(resolved_path, in_value) == 0)
return true;
return false;
}
static int convert_path_with_star(const char *full_obj, char *out_str, size_t out_len)
{
char str[1024] = {0};
char *pch, *pchr;
size_t pos = 0;
DM_STRNCPY(str, full_obj, sizeof(str));
for (pch = strtok_r(str, ".", &pchr); pch != NULL; pch = strtok_r(NULL, ".", &pchr)) {
const char *part = isdigit_str(pch) ? "*" : pch;
int written = snprintf(out_str + pos, out_len - pos, "%s.", part);
if (written < 0 || written >= (int)(out_len - pos)) {
return -1; // overflow
}
pos += written;
}
return 0;
}
static void set_references(const char *parent_path, const char *current_path, const char *key_name, const char *key_value, char *out_str, size_t out_len)
{
char linker[MAX_DM_PATH * 2] = {0};
char hash_str[9] = {0};
convert_path_with_star(parent_path, out_str, out_len);
snprintf(linker, sizeof(linker), "%s[%s==%s].", out_str, key_name, DM_STRLEN(key_value) ? key_value : "");
calculate_hash(linker, hash_str, sizeof(hash_str));
DM_STRNCPY(out_str, current_path, strlen(current_path));
dmuci_set_value_bbfdm("reference_translation", "reference_path", hash_str, out_str);
calculate_hash(out_str, hash_str, sizeof(hash_str));
dmuci_set_value_bbfdm("reference_translation", "reference_value", hash_str, DM_STRLEN(key_value) ? key_value : "#");
}
/* **********
* get value
* **********/
@ -1032,6 +1000,12 @@ static int get_value_param(DMPARAM_ARGS)
}
fill_blob_param(&dmctx->bb, full_param, value, DMT_TYPE[leaf->type], leaf->dm_flags);
if (leaf->dm_flags & DM_FLAG_LINKER) {
// Update reference path & value
set_references(node->parent->current_object, node->current_object, leaf->parameter, value, full_param, sizeof(full_param));
}
return 0;
}
@ -1066,6 +1040,11 @@ static int mparam_get_value_in_param(DMPARAM_ARGS)
fill_blob_param(&dmctx->bb, full_param, value, DMT_TYPE[leaf->type], leaf->dm_flags);
if (leaf->dm_flags & DM_FLAG_LINKER) {
// Update reference path & value
set_references(node->parent->current_object, node->current_object, leaf->parameter, value, full_param, sizeof(full_param));
}
dmctx->findparam = (dmctx->iswildcard) ? 1 : 0;
dmctx->stop = (dmctx->iswildcard) ? false : true;
return 0;
@ -1663,22 +1642,13 @@ static int mparam_set_value(DMPARAM_ARGS)
return 0;
}
} else if (leaf->dm_flags & DM_FLAG_REFERENCE) {
if (is_same_reference_path(value, dmctx->in_value, param_value, sizeof(param_value))) {
if (is_same_reference_path(value, dmctx->in_value)) {
BBF_DEBUG("Requested value (%s) is same as current value (%s)..", dmctx->in_value, value);
return 0;
}
} else {
int len = DM_STRLEN(param_value);
// Remove linker value from the provided value if it is not marked as reference value 'Device.XXX.=>XX##'
if (len > 7 && DM_STRNCMP(param_value, ROOT_NODE, strlen(ROOT_NODE)) == 0 &&
param_value[len - 1] == '#' && param_value[len - 2] == '#') {
char *p = DM_STRSTR(param_value, "=>");
if (p) *p = 0;
}
if (DM_STRCMP(value, param_value) == 0) {
BBF_DEBUG("Requested value (%s) is same as current value (%s)...", param_value, value);
if (DM_STRCMP(dmctx->in_value, value) == 0) {
BBF_DEBUG("Requested value (%s) is same as current value (%s)...", dmctx->in_value, value);
return 0;
}
}
@ -1972,3 +1942,63 @@ int dm_entry_event(struct dmctx *dmctx)
return (dmctx->stop) ? err : USP_FAULT_INVALID_PATH;
}
/* **********
* get instances data base
* **********/
static int mobj_get_references_db(DMOBJECT_ARGS)
{
struct uci_section *ref_s = NULL;
ref_s = dmuci_get_section_bbfdm("reference_translation", "reference_path");
if (ref_s == NULL) {
dmuci_add_section_bbfdm("reference_translation", "reference_path", &ref_s);
dmuci_rename_section_by_section(ref_s, "reference_path");
}
ref_s = dmuci_get_section_bbfdm("reference_translation", "reference_value");
if (ref_s == NULL) {
dmuci_add_section_bbfdm("reference_translation", "reference_value", &ref_s);
dmuci_rename_section_by_section(ref_s, "reference_value");
}
return 0;
}
static int mparam_get_references_db(DMPARAM_ARGS)
{
if (node->is_instanceobj == 0)
return 0;
if (leaf->dm_flags & DM_FLAG_LINKER) {
char full_param[MAX_DM_PATH] = {0};
char *value = dmstrdup("");
snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter);
(leaf->getvalue)(full_param, dmctx, data, instance, &value);
set_references(node->parent->current_object, node->current_object, leaf->parameter, value, full_param, sizeof(full_param));
}
return 0;
}
int dm_entry_references_db(struct dmctx *ctx)
{
DMOBJ *root = ctx->dm_entryobj;
DMNODE node = {.current_object = ""};
int err = 0;
ctx->inparam_isparam = 0;
ctx->findparam = 1;
ctx->stop = 0;
ctx->checkobj = NULL;
ctx->checkleaf = NULL;
ctx->method_obj = mobj_get_references_db;
ctx->method_param = mparam_get_references_db;
err = dm_browse(ctx, &node, root, NULL, NULL);
return (ctx->findparam == 0) ? err : 0;
}

View file

@ -47,6 +47,7 @@ int dm_entry_set_value(struct dmctx *dmctx);
int dm_entry_object_exists(struct dmctx *dmctx);
int dm_entry_operate(struct dmctx *dmctx);
int dm_entry_event(struct dmctx *dmctx);
int dm_entry_references_db(struct dmctx *ctx);
int dm_entry_get_reference_param(struct dmctx *dmctx);
int dm_entry_get_reference_value(struct dmctx *dmctx);
int dm_link_inst_obj(struct dmctx *dmctx, DMNODE *parent_node, void *data, char *instance);

View file

@ -2196,3 +2196,19 @@ bool is_str_eq(const char *s1, const char *s2)
return false;
}
// Function to calculate FNV-1 hash
void calculate_hash(const char *input, char *output, size_t out_len)
{
#define FNV_OFFSET_BASIS 0x811C9DC5
#define FNV_PRIME 0x1000193
uint32_t hash = FNV_OFFSET_BASIS;
while (*input != '\0') {
hash *= FNV_PRIME; // Multiply hash by prime
hash ^= (uint8_t)(*input); // XOR with current character
input++;
}
snprintf(output, out_len, "%08X", hash);
}

View file

@ -238,5 +238,6 @@ long download_file(char *file_path, const char *url, const char *username, const
long upload_file(const char *file_path, const char *url, const char *username, const char *password);
int get_proto_type(const char *proto);
bool is_str_eq(const char *s1, const char *s2);
void calculate_hash(const char *input, char *output, size_t out_len);
#endif

View file

@ -229,6 +229,9 @@ int bbf_entry_method(struct dmctx *ctx, int cmd)
case BBF_EVENT:
fault = dm_entry_event(ctx);
break;
case BBF_REFERENCES_DB:
fault = dm_entry_references_db(ctx);
break;
}
return bbf_fault_map(ctx, fault);

View file

@ -190,6 +190,17 @@ int dmuci_get_section_type(const char *package, const char *section, char **valu
return 0;
}
/**** UCI SECTION EXIST *****/
struct uci_section *dmuci_get_section(const char *package, const char *section)
{
struct uci_ptr ptr = {0};
if (dmuci_lookup_ptr(uci_ctx, &ptr, package, section, NULL, NULL))
return NULL;
return ptr.s;
}
int dmuci_get_option_value_string(const char *package, const char *section, const char *option, char **value)
{
struct uci_ptr ptr = {0};

View file

@ -156,6 +156,15 @@ int dmuci_get_section_type_##UCI_PATH(const char *package, const char *section,c
uci_ctx = save_uci_ctx; \
return res; \
}\
struct uci_section *dmuci_get_section_##UCI_PATH(const char *package, const char *section) \
{\
struct uci_context *save_uci_ctx; \
save_uci_ctx = uci_ctx; \
uci_ctx = uci_ctx_##UCI_PATH; \
struct uci_section *res = dmuci_get_section(package, section); \
uci_ctx = save_uci_ctx; \
return res; \
}\
int dmuci_get_option_value_string_##UCI_PATH(const char *package, const char *section, const char *option, char **value) \
{\
struct uci_context *save_uci_ctx; \
@ -306,6 +315,7 @@ int dmuci_add_list_value_by_section(struct uci_section *s, const char *option, c
int dmuci_del_list_value_by_section(struct uci_section *s, const char *option, const char *value);
int dmuci_rename_section_by_section(struct uci_section *s, const char *value);
int dmuci_reoder_section_by_section(struct uci_section *s, char *pos);
struct uci_section *dmuci_get_section(const char *package, const char *section);
struct uci_section *dmuci_walk_section(const char *package, const char *stype, const void *arg1, const void *arg2, int cmp , int (*filter)(struct uci_section *s, const void *value), struct uci_section *prev_section, int walk);
struct uci_section *dmuci_walk_all_sections(const char *package, struct uci_section *prev_section, int walk);
@ -318,6 +328,7 @@ int dmuci_delete_by_section_unnamed_bbfdm(struct uci_section *s, const char *opt
int dmuci_delete_by_section_bbfdm(struct uci_section *s, const char *option, const char *value);
int dmuci_commit_package_bbfdm(char *package);
int dmuci_commit_bbfdm(void);
struct uci_section *dmuci_get_section_bbfdm(const char *package, const char *section);
struct uci_section *dmuci_walk_section_bbfdm(const char *package, const char *stype, const void *arg1, const void *arg2, int cmp , int (*filter)(struct uci_section *s, const void *value), struct uci_section *prev_section, int walk);
struct uci_section *dmuci_walk_section_varstate(const char *package, const char *stype, const void *arg1, const void *arg2, int cmp , int (*filter)(struct uci_section *s, const void *value), struct uci_section *prev_section, int walk);

View file

@ -36,9 +36,6 @@ static void bbfdm_ctx_cleanup(struct bbfdm_context *u)
{
bbf_global_clean(DEAMON_DM_ROOT_OBJ);
free_path_list(&u->linker_list);
free_path_list(&u->obj_list);
/* DotSo Plugin */
bbfdm_free_dotso_plugin(u, &deamon_lib_handle);
@ -75,40 +72,24 @@ static void fill_optional_data(bbfdm_data_t *data, struct blob_attr *msg)
}
}
static char *get_value_by_reference_path(struct dmctx *ctx, char *reference_path)
static int refresh_references_db(unsigned int dm_type)
{
char path[MAX_DM_PATH] = {0};
char key_name[256], key_value[256];
char *reference_value = NULL;
regmatch_t pmatch[2];
struct dmctx bbf_ctx = {
.in_param = ROOT_NODE,
.dm_type = dm_type
};
if (!ctx || !reference_path)
return NULL;
bbf_init(&bbf_ctx);
int res = bbfdm_cmd_exec(&bbf_ctx, BBF_REFERENCES_DB);
if (!match(reference_path, "\\[(.*?)\\]", 2, pmatch))
return NULL;
snprintf(path, pmatch[0].rm_so + 1, "%s", reference_path);
int len = DM_STRLEN(path);
if (!len)
return NULL;
char *match_str = reference_path + pmatch[1].rm_so;
if (DM_STRLEN(match_str) == 0)
return NULL;
int n = sscanf(match_str, "%255[^=]==\"%255[^\"]\"", key_name, key_value);
if (n != 2) {
n = sscanf(match_str, "%255[^=]==%255[^]]", key_name, key_value);
if (n != 2)
return NULL;
if (!res) {
// Apply all bbfdm changes
dmuci_commit_bbfdm();
}
snprintf(path + len, sizeof(path) - len, "*.%s", key_name);
bbf_cleanup(&bbf_ctx);
adm_entry_get_reference_param(ctx, path, key_value, &reference_value);
return reference_value;
return res;
}
static void async_req_free(struct bbfdm_async_req *r)
@ -415,6 +396,10 @@ int bbfdm_set_handler(struct ubus_context *ctx, struct ubus_object *obj,
bbf_cleanup(&data.bbf_ctx);
if (!fault) {
refresh_references_db(data.bbf_ctx.dm_type);
}
end:
free_pv_list(&pv_list);
@ -546,6 +531,10 @@ end:
bbf_cleanup(&data.bbf_ctx);
if (!fault) {
refresh_references_db(data.bbf_ctx.dm_type);
}
ubus_send_reply(ctx, req, data.bb.head);
blob_buf_free(&data.bb);
@ -621,107 +610,20 @@ int bbfdm_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
return 0;
}
int bbfdm_ref_path_handler(struct ubus_context *ctx, struct ubus_object *obj,
int bbfdm_refresh_references_db(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct blob_attr *tb[__DM_GET_MAX];
struct bbfdm_context *u;
struct pvNode *node = NULL;
struct blob_buf bb;
bool reference_value_found = false;
struct blob_buf bb = {0};
if (blobmsg_parse(dm_get_policy, __DM_GET_MAX, tb, blob_data(msg), blob_len(msg))) {
BBF_ERR("Failed to parse blob");
return UBUS_STATUS_UNKNOWN_ERROR;
}
if (!tb[DM_GET_PATH])
return UBUS_STATUS_INVALID_ARGUMENT;
u = container_of(ctx, struct bbfdm_context, ubus_ctx);
if (u == NULL) {
BBF_ERR("failed to get the bbfdm context");
return UBUS_STATUS_UNKNOWN_ERROR;
}
BBFDM_INFO("ubus method|%s|, name|%s|", method, obj->name);
char *path = blobmsg_get_string(tb[DM_GET_PATH]);
if (!match_with_path_list(&u->obj_list, path))
return UBUS_STATUS_INVALID_ARGUMENT;
BBF_INFO("ubus method|%s|, name|%s|", method, obj->name);
memset(&bb, 0, sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
list_for_each_entry(node, &u->linker_list, list) {
if (strcmp(node->param, path) == 0) {
bb_add_string(&bb, "data", node->val);
reference_value_found = true;
break;
}
}
int res = refresh_references_db(BBFDM_BOTH);
if (!reference_value_found) {
struct dmctx bbf_ctx = {0};
bbf_init(&bbf_ctx);
char *reference_path = get_value_by_reference_path(&bbf_ctx, path);
add_pv_list(path, reference_path, NULL, &u->linker_list);
bb_add_string(&bb, "data", reference_path ? reference_path : "");
bbf_cleanup(&bbf_ctx);
}
ubus_send_reply(ctx, req, bb.head);
blob_buf_free(&bb);
return 0;
}
int bbfdm_ref_value_handler(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct blob_attr *tb[__DM_GET_MAX];
struct bbfdm_context *u;
struct dmctx bbf_ctx = {0};
char *reference_value = NULL;
struct blob_buf bb;
if (blobmsg_parse(dm_get_policy, __DM_GET_MAX, tb, blob_data(msg), blob_len(msg))) {
BBF_ERR("Failed to parse blob");
return UBUS_STATUS_UNKNOWN_ERROR;
}
if (!tb[DM_GET_PATH])
return UBUS_STATUS_INVALID_ARGUMENT;
u = container_of(ctx, struct bbfdm_context, ubus_ctx);
if (u == NULL) {
BBF_ERR("failed to get the bbfdm context");
return UBUS_STATUS_UNKNOWN_ERROR;
}
BBFDM_INFO("ubus method|%s|, name|%s|", method, obj->name);
char *reference_path = blobmsg_get_string(tb[DM_GET_PATH]);
if (!match_with_path_list(&u->obj_list, reference_path))
return UBUS_STATUS_INVALID_ARGUMENT;
memset(&bb, 0, sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
bbf_init(&bbf_ctx);
adm_entry_get_reference_value(&bbf_ctx, reference_path, &reference_value);
bb_add_string(&bb, "data", reference_value ? reference_value : "");
bbf_cleanup(&bbf_ctx);
blobmsg_add_u8(&bb, "status", !res ? true : false);
ubus_send_reply(ctx, req, bb.head);
blob_buf_free(&bb);
@ -737,8 +639,7 @@ static struct ubus_method bbf_methods[] = {
UBUS_METHOD("operate", bbfdm_operate_handler, dm_operate_policy),
UBUS_METHOD("add", bbfdm_add_handler, dm_add_policy),
UBUS_METHOD("del", bbfdm_del_handler, dm_del_policy),
UBUS_METHOD("reference_path", bbfdm_ref_path_handler, dm_get_policy),
UBUS_METHOD("reference_value", bbfdm_ref_value_handler, dm_get_policy),
UBUS_METHOD_NOARG("refresh_references_db", bbfdm_refresh_references_db)
};
static struct ubus_object_type bbf_type = UBUS_OBJECT_TYPE("", bbf_methods);
@ -766,30 +667,8 @@ static int regiter_ubus_object(struct ubus_context *ctx)
return ubus_add_object(ctx, &bbf_object);
}
static void bbfdm_linker_cb(struct ubus_context *ctx, struct ubus_event_handler *ev,
const char *type, struct blob_attr *msg)
{
if (!type || !msg)
return;
struct bbfdm_context *u;
u = container_of(ctx, struct bbfdm_context, ubus_ctx);
if (u == NULL) {
BBF_ERR("failed to get the bbfdm context");
return;
}
if (strcmp(type, "bbfdm.linker.cleanup") == 0) {
//BBF_ERR("bbfdm.linker.cleanup");
free_pv_list(&u->linker_list);
}
}
static void bbfdm_ctx_init(struct bbfdm_context *bbfdm_ctx)
{
INIT_LIST_HEAD(&bbfdm_ctx->linker_list);
INIT_LIST_HEAD(&bbfdm_ctx->obj_list);
INIT_LIST_HEAD(&bbfdm_ctx->event_handlers);
}
@ -852,8 +731,6 @@ static int load_micro_service_data_model(struct bbfdm_context *daemon_ctx)
return 0;
}
static struct ubus_event_handler bbfdm_linker_handler = { .cb = bbfdm_linker_cb };
int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx)
{
int err = 0;
@ -861,7 +738,7 @@ int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx)
err = ubus_connect_ctx(&bbfdm_ctx->ubus_ctx, NULL);
if (err != UBUS_STATUS_OK) {
BBF_ERR("Failed to connect to ubus");
return -5; // Error code -5 indicating that ubus_ctx is connected
return -5; // Error code -5 indicating that ubus_ctx is not connected
}
uloop_init();
@ -885,11 +762,13 @@ int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx)
if (err != UBUS_STATUS_OK)
return -1;
err = register_events_to_ubus(&bbfdm_ctx->ubus_ctx, &bbfdm_ctx->event_handlers);
if (err != 0)
return err;
err = refresh_references_db(BBFDM_BOTH);
if (err) {
BBF_ERR("Failed to refresh instance data base");
return -1;
}
return ubus_register_event_handler(&bbfdm_ctx->ubus_ctx, &bbfdm_linker_handler, "bbfdm.linker.cleanup");
return register_events_to_ubus(&bbfdm_ctx->ubus_ctx, &bbfdm_ctx->event_handlers);
}
int bbfdm_ubus_regiter_free(struct bbfdm_context *bbfdm_ctx)

View file

@ -27,8 +27,6 @@ struct bbfdm_context {
bbfdm_config_t config;
struct ubus_context ubus_ctx;
struct list_head event_handlers;
struct list_head linker_list;
struct list_head obj_list;
};
struct ev_handler_node {

View file

@ -66,15 +66,6 @@ int bbfdm_load_internal_plugin(struct bbfdm_context *bbfdm_ctx, DM_MAP_OBJ *dyna
return -1;
}
if (dynamic_obj[i].root_obj != NULL && bbfdm_ctx != NULL) {
struct dm_obj_s *entryobj = dynamic_obj[i].root_obj;
for (; (entryobj && entryobj->obj); entryobj++) {
char path[MAX_DM_PATH] = {0};
snprintf(path, sizeof(path), "%s%s.", node_obj, entryobj->obj);
add_path_list(path, &bbfdm_ctx->obj_list);
}
}
node_obj[len-1] = 0;
dm_entryobj[i].obj = node_obj;
@ -196,10 +187,6 @@ static int bbfdm_load_json_plugin(struct bbfdm_context *bbfdm_ctx, struct list_h
return -1;
}
char path[MAX_DM_PATH] = {0};
snprintf(path, sizeof(path), "%s%s.", obj_prefix, obj_name);
add_path_list(path, &bbfdm_ctx->obj_list);
// Remove '.' from object prefix
if (obj_prefix[obj_prefix_len - 1] == '.')
obj_prefix[obj_prefix_len - 1] = 0;

View file

@ -0,0 +1,26 @@
config global 'global'
option enable '1'
config schedule 'schedule_1'
option enable '0'
list day 'Monday'
list day 'Tuesday'
list day 'Wednesday'
list day 'Thursday'
list day 'Friday'
list day 'Saturday'
list day 'Sunday'
option duration '1'
config schedule 'schedule_2'
option enable '0'
list day 'Monday'
list day 'Tuesday'
list day 'Wednesday'
list day 'Thursday'
list day 'Friday'
list day 'Saturday'
list day 'Sunday'
option duration '1'