From 45a6d7e0c7d33c098bee53506a23e2bac1687564 Mon Sep 17 00:00:00 2001 From: Amin Ben Romdhane Date: Thu, 27 Mar 2025 13:40:53 +0100 Subject: [PATCH] Redesign the handling of references based on uci reference_translation --- bbfdmd/ubus/bbfdmd.c | 9 +- bbfdmd/ubus/common.c | 59 +------- bbfdmd/ubus/common.h | 2 - bbfdmd/ubus/get.c | 76 +++++++--- bbfdmd/ubus/get.h | 3 +- bbfdmd/ubus/service.c | 70 --------- libbbfdm-api/legacy/dmapi.c | 30 ++-- libbbfdm-api/legacy/dmapi.h | 1 + libbbfdm-api/legacy/dmbbf.c | 242 ++++++++++++++++++-------------- libbbfdm-api/legacy/dmbbf.h | 1 + libbbfdm-api/legacy/dmcommon.c | 16 +++ libbbfdm-api/legacy/dmcommon.h | 1 + libbbfdm-api/legacy/dmentry.c | 3 + libbbfdm-api/legacy/dmuci.c | 11 ++ libbbfdm-api/legacy/dmuci.h | 11 ++ libbbfdm-ubus/bbfdm-ubus.c | 187 +++++------------------- libbbfdm-ubus/bbfdm-ubus.h | 2 - libbbfdm-ubus/plugin.c | 13 -- test/files/etc/config/schedules | 26 ++++ 19 files changed, 315 insertions(+), 448 deletions(-) create mode 100644 test/files/etc/config/schedules diff --git a/bbfdmd/ubus/bbfdmd.c b/bbfdmd/ubus/bbfdmd.c index 7307dcca..789fb80d 100644 --- a/bbfdmd/ubus/bbfdmd.c +++ b/bbfdmd/ubus/bbfdmd.c @@ -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); diff --git a/bbfdmd/ubus/common.c b/bbfdmd/ubus/common.c index 17332f2a..d0fba17b 100644 --- a/bbfdmd/ubus/common.c +++ b/bbfdmd/ubus/common.c @@ -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) { diff --git a/bbfdmd/ubus/common.h b/bbfdmd/ubus/common.h index 55374b68..13add469 100644 --- a/bbfdmd/ubus/common.h +++ b/bbfdmd/ubus/common.h @@ -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 */ diff --git a/bbfdmd/ubus/get.c b/bbfdmd/ubus/get.c index 15be9e11..b0fb3840 100644 --- a/bbfdmd/ubus/get.c +++ b/bbfdmd/ubus/get.c @@ -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); -} - diff --git a/bbfdmd/ubus/get.h b/bbfdmd/ubus/get.h index 8fd9683e..a96aa008 100644 --- a/bbfdmd/ubus/get.h +++ b/bbfdmd/ubus/get.h @@ -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); diff --git a/bbfdmd/ubus/service.c b/bbfdmd/ubus/service.c index 3e4bdbeb..5a2754d1 100644 --- a/bbfdmd/ubus/service.c +++ b/bbfdmd/ubus/service.c @@ -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, ®istered_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; -} diff --git a/libbbfdm-api/legacy/dmapi.c b/libbbfdm-api/legacy/dmapi.c index 3da406e4..063d5e5b 100644 --- a/libbbfdm-api/legacy/dmapi.c +++ b/libbbfdm-api/legacy/dmapi.c @@ -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; diff --git a/libbbfdm-api/legacy/dmapi.h b/libbbfdm-api/legacy/dmapi.h index f2a4d7ea..de0cac01 100644 --- a/libbbfdm-api/legacy/dmapi.h +++ b/libbbfdm-api/legacy/dmapi.h @@ -273,6 +273,7 @@ enum { BBF_DEL_OBJECT, BBF_OPERATE, BBF_EVENT, + BBF_REFERENCES_DB }; enum { diff --git a/libbbfdm-api/legacy/dmbbf.c b/libbbfdm-api/legacy/dmbbf.c index 37ff504b..e3459505 100644 --- a/libbbfdm-api/legacy/dmbbf.c +++ b/libbbfdm-api/legacy/dmbbf.c @@ -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; +} diff --git a/libbbfdm-api/legacy/dmbbf.h b/libbbfdm-api/legacy/dmbbf.h index 25bf9e8f..1f1e3824 100644 --- a/libbbfdm-api/legacy/dmbbf.h +++ b/libbbfdm-api/legacy/dmbbf.h @@ -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); diff --git a/libbbfdm-api/legacy/dmcommon.c b/libbbfdm-api/legacy/dmcommon.c index b972cb17..29489aaa 100644 --- a/libbbfdm-api/legacy/dmcommon.c +++ b/libbbfdm-api/legacy/dmcommon.c @@ -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); +} diff --git a/libbbfdm-api/legacy/dmcommon.h b/libbbfdm-api/legacy/dmcommon.h index ea41ec39..8896c91d 100644 --- a/libbbfdm-api/legacy/dmcommon.h +++ b/libbbfdm-api/legacy/dmcommon.h @@ -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 diff --git a/libbbfdm-api/legacy/dmentry.c b/libbbfdm-api/legacy/dmentry.c index bb9e1964..1c4a0c0d 100644 --- a/libbbfdm-api/legacy/dmentry.c +++ b/libbbfdm-api/legacy/dmentry.c @@ -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); diff --git a/libbbfdm-api/legacy/dmuci.c b/libbbfdm-api/legacy/dmuci.c index bd49c868..5ab86dfa 100644 --- a/libbbfdm-api/legacy/dmuci.c +++ b/libbbfdm-api/legacy/dmuci.c @@ -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}; diff --git a/libbbfdm-api/legacy/dmuci.h b/libbbfdm-api/legacy/dmuci.h index 4fc87228..dbecedc3 100644 --- a/libbbfdm-api/legacy/dmuci.h +++ b/libbbfdm-api/legacy/dmuci.h @@ -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); diff --git a/libbbfdm-ubus/bbfdm-ubus.c b/libbbfdm-ubus/bbfdm-ubus.c index 3cfa5d04..a48008b4 100644 --- a/libbbfdm-ubus/bbfdm-ubus.c +++ b/libbbfdm-ubus/bbfdm-ubus.c @@ -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) diff --git a/libbbfdm-ubus/bbfdm-ubus.h b/libbbfdm-ubus/bbfdm-ubus.h index 3f82c0fb..dc27e46e 100644 --- a/libbbfdm-ubus/bbfdm-ubus.h +++ b/libbbfdm-ubus/bbfdm-ubus.h @@ -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 { diff --git a/libbbfdm-ubus/plugin.c b/libbbfdm-ubus/plugin.c index de380e39..d791a8ab 100644 --- a/libbbfdm-ubus/plugin.c +++ b/libbbfdm-ubus/plugin.c @@ -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; diff --git a/test/files/etc/config/schedules b/test/files/etc/config/schedules new file mode 100644 index 00000000..56f8064a --- /dev/null +++ b/test/files/etc/config/schedules @@ -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' +