diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2ed9a570..c34f41cd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -15,8 +15,8 @@ include: - if: $CI_COMMIT_BRANCH == "devel" stages: - - unit_test - static_code_analysis + - unit_test - functional_test - deploy @@ -29,6 +29,7 @@ run_unit_test: - "./gitlab-ci/install-dependencies.sh ms" - "./gitlab-ci/setup.sh ms" - "./gitlab-ci/unit-test.sh" + artifacts: when: always paths: diff --git a/bbfdmd/ubus/CMakeLists.txt b/bbfdmd/ubus/CMakeLists.txt index 68f0a617..b1ef4fba 100644 --- a/bbfdmd/ubus/CMakeLists.txt +++ b/bbfdmd/ubus/CMakeLists.txt @@ -4,9 +4,9 @@ PROJECT(bbfdmd) ADD_DEFINITIONS(-fstrict-aliasing -Wall -Wextra -Werror -Wformat -Wformat-signedness -g3 -fPIC -D_GNU_SOURCE) -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SOURCE_DIR} -I${CMAKE_SOURCE_DIR}/libbbfdm-api/legacy -I${CMAKE_SOURCE_DIR}/libbbfdm-api/version-2 -I${CMAKE_SOURCE_DIR}/libbbfdm-ubus") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SOURCE_DIR}") FILE(GLOB BBF_SOURCES *.c) ADD_EXECUTABLE(bbfdmd ${BBF_SOURCES}) -TARGET_LINK_LIBRARIES(bbfdmd bbfdm-ubus bbfdm) +TARGET_LINK_LIBRARIES(bbfdmd ubus ubox blobmsg_json json-c bbfdm-api-v2) INSTALL(TARGETS bbfdmd DESTINATION usr/sbin) diff --git a/bbfdmd/ubus/bbfdmd.c b/bbfdmd/ubus/bbfdmd.c index 3cfe69f6..1d3b9037 100644 --- a/bbfdmd/ubus/bbfdmd.c +++ b/bbfdmd/ubus/bbfdmd.c @@ -1,21 +1,179 @@ /* - * bbfdmd.c: BBFDMD deamon + * Copyright (C) 2023-2025 iopsys Software Solutions AB * - * Copyright (C) 2023-2024 IOPSYS Software Solutions AB. All rights reserved. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation * - * Author: Vivek Dutta - * Author: Amin Ben Romdhane + * Author: Vivek Dutta + * Author: Amin Ben Romdhane * - * See LICENSE file for license related information. */ -#include +#include +#include +#include +#include +#include + +#include +#include #include "common.h" -#include "bbfdm-ubus.h" +#include "service.h" +#include "get.h" #include "cli.h" -#include "../../libbbfdm/device.h" +extern struct list_head registered_services; +extern int g_log_level; + +static const struct blobmsg_policy bbfdm_policy[] = { + [BBFDM_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING }, + [BBFDM_VALUE] = { .name = "value", .type = BLOBMSG_TYPE_STRING }, + [BBFDM_INPUT] = { .name = "optional", .type = BLOBMSG_TYPE_TABLE} +}; + +static int bbfdm_handler_async(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + struct blob_attr *tb[__BBFDM_MAX]; + service_entry_t *service = NULL; + + if (blobmsg_parse(bbfdm_policy, __BBFDM_MAX, tb, blob_data(msg), blob_len(msg))) { + BBFDM_ERR("Failed to parse input message"); + return UBUS_STATUS_UNKNOWN_ERROR; + } + + if (!tb[BBFDM_PATH]) { + BBFDM_ERR("%s: path must be defined", method); + return UBUS_STATUS_INVALID_ARGUMENT; + } + + struct async_request_context *context = calloc(1, sizeof(struct async_request_context)); + if (!context) { + BBFDM_ERR("Failed to allocate memory"); + return UBUS_STATUS_UNKNOWN_ERROR; + } + + BBFDM_INFO("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); + + context->ubus_ctx = ctx; + + 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); + + // Event handler to wait for linker response + context->linker_handler.cb = linker_response_callback; + ubus_register_event_handler(ctx, &context->linker_handler, "bbfdm.linker.response"); + } + + unsigned int requested_proto = get_proto_type_option_value(tb[BBFDM_INPUT]); + + ubus_defer_request(ctx, req, &context->request_data); + + list_for_each_entry(service, ®istered_services, list) { + + if (!is_path_match(context->requested_path, requested_proto, service)) + continue; + + run_async_call(context, service->name, msg); + } + + context->service_list_processed = true; + + if (context->path_matched == false) + send_response(context); + + return 0; +} + +static int bbfdm_handler_sync(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + struct blob_attr *tb[__BBFDM_MAX]; + service_entry_t *service = NULL; + char requested_path[MAX_PATH_LENGTH]; + struct blob_buf bb = {0}; + + if (blobmsg_parse(bbfdm_policy, __BBFDM_MAX, tb, blob_data(msg), blob_len(msg))) { + BBFDM_ERR("Failed to parse input message"); + return UBUS_STATUS_UNKNOWN_ERROR; + } + + if (!tb[BBFDM_PATH]) { + BBFDM_ERR("%s: path must be defined", method); + return UBUS_STATUS_INVALID_ARGUMENT; + } + + BBFDM_INFO("ubus method|%s|, name|%s|", method, obj->name); + + snprintf(requested_path, sizeof(requested_path), "%s", blobmsg_get_string(tb[BBFDM_PATH])); + + memset(&bb, 0, sizeof(struct blob_buf)); + blob_buf_init(&bb, 0); + + unsigned int requested_proto = get_proto_type_option_value(tb[BBFDM_INPUT]); + + list_for_each_entry(service, ®istered_services, list) { + + if (!is_path_match(requested_path, requested_proto, service)) + continue; + + run_sync_call(service->name, method, msg, &bb); + } + + ubus_send_reply(ctx, req, bb.head); + blob_buf_free(&bb); + + return 0; +} + +static int bbfdm_services_handler(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg __attribute__((unused))) +{ + struct blob_buf bb; + + BBFDM_INFO("ubus method|%s|, name|%s|", method, obj->name); + + memset(&bb, 0, sizeof(struct blob_buf)); + blob_buf_init(&bb, 0); + + list_registered_services(&bb); + + ubus_send_reply(ctx, req, bb.head); + blob_buf_free(&bb); + + return 0; +} + +static struct ubus_method bbfdm_methods[] = { + UBUS_METHOD("get", bbfdm_handler_async, bbfdm_policy), + UBUS_METHOD("schema", bbfdm_handler_async, bbfdm_policy), + UBUS_METHOD("instances", bbfdm_handler_async, bbfdm_policy), + UBUS_METHOD("operate", bbfdm_handler_async, bbfdm_policy), + UBUS_METHOD("set", bbfdm_handler_sync, bbfdm_policy), + UBUS_METHOD("add", bbfdm_handler_sync, bbfdm_policy), + UBUS_METHOD("del", bbfdm_handler_sync, bbfdm_policy), + UBUS_METHOD_NOARG("services", bbfdm_services_handler) +}; + +static struct ubus_object_type bbfdm_object_type = UBUS_OBJECT_TYPE(BBFDM_UBUS_OBJECT, bbfdm_methods); + +static struct ubus_object bbfdm_object = { + .name = BBFDM_UBUS_OBJECT, + .type = &bbfdm_object_type, + .methods = bbfdm_methods, + .n_methods = ARRAY_SIZE(bbfdm_methods) +}; static void usage(char *prog) { @@ -30,13 +188,10 @@ static void usage(char *prog) int main(int argc, char **argv) { - struct bbfdm_context bbfdm_ctx = {0}; + struct ubus_context ubus_ctx = {0}; char *cli_argv[4] = {0}; - int log_level = 3; // Default is LOG_ERR int err = 0, ch, cli_argc = 0, i; - memset(&bbfdm_ctx, 0, sizeof(struct bbfdm_context)); - while ((ch = getopt(argc, argv, "hc:l:")) != -1) { switch (ch) { case 'c': @@ -47,9 +202,9 @@ int main(int argc, char **argv) break; case 'l': if (optarg) { - log_level = (int)strtod(optarg, NULL); - if (log_level < 0 || log_level > 7) - log_level = 3; + g_log_level = (int)strtod(optarg, NULL); + if (g_log_level < 0 || g_log_level > 7) + g_log_level = 3; } break; case 'h': @@ -61,24 +216,42 @@ int main(int argc, char **argv) } if (cli_argc) { - return bbfdm_cli_exec_command(cli_argc, cli_argv); + return bbfdmd_cli_exec_command(cli_argc, cli_argv); } - bbfdm_ubus_set_log_level(log_level); - bbfdm_ubus_load_data_model(tDynamicObj); + openlog(BBFDM_UBUS_OBJECT, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); - openlog(BBFDM_DEFAULT_UBUS_OBJ, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); + setlogmask(LOG_UPTO(g_log_level)); - err = bbfdm_ubus_regiter_init(&bbfdm_ctx); - if (err != 0) - goto exit; + err = ubus_connect_ctx(&ubus_ctx, NULL); + if (err != UBUS_STATUS_OK) { + BBFDM_ERR("Failed to connect to ubus"); + return -1; + } - BBF_INFO("Waiting on uloop...."); + uloop_init(); + ubus_add_uloop(&ubus_ctx); + + err = register_services(&ubus_ctx); + if (err) { + BBFDM_ERR("Failed to load micro-services"); + goto end; + } + + err = ubus_add_object(&ubus_ctx, &bbfdm_object); + if (err != UBUS_STATUS_OK) { + BBFDM_ERR("Failed to add ubus object: %s", ubus_strerror(err)); + goto end; + } + + BBFDM_INFO("Waiting on uloop...."); uloop_run(); -exit: - if (err != -5) // Error code is not -5, indicating that ubus_ctx is connected, proceed with shutdown - bbfdm_ubus_regiter_free(&bbfdm_ctx); +end: + BBFDM_ERR("Free context"); + unregister_services(); + uloop_done(); + ubus_shutdown(&ubus_ctx); closelog(); diff --git a/bbfdmd/ubus/cli.c b/bbfdmd/ubus/cli.c index cbfde81a..8fad9ee2 100644 --- a/bbfdmd/ubus/cli.c +++ b/bbfdmd/ubus/cli.c @@ -1,20 +1,22 @@ /* - * cli.c: Cli command for bbfdmd + * Copyright (C) 2023-2025 iopsys Software Solutions AB * - * Copyright (C) 2023 IOPSYS Software Solutions AB. All rights reserved. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation * - * Author: Amin Ben Romdhane + * Author: Amin Ben Romdhane * - * See LICENSE file for license related information. */ #include #include +#include +#include +#include +#include #include "common.h" -#include "plugin.h" - -#define UNUSED __attribute__((unused)) typedef struct { char *cmd; @@ -28,7 +30,7 @@ typedef struct { char *usage; } cli_cmd_t; -static int cli_exec_help(cli_data_t *cli_data UNUSED, const char *path UNUSED, const char *value UNUSED); +static int cli_exec_help(cli_data_t *cli_data __attribute__((unused)), const char *path __attribute__((unused)), const char *value __attribute__((unused))); static int cli_exec_cmd(cli_data_t *cli_data, const char *path, const char *value); cli_cmd_t cli_commands[] = { @@ -138,10 +140,8 @@ static void __ubus_callback(struct ubus_request *req, int msgtype __attribute__( } else if (strcmp(cli_data->cmd, "instances") == 0) { printf("%s\n", name); } else if (strcmp(cli_data->cmd, "schema") == 0) { - char *type = tb[2] ? blobmsg_get_string(tb[2]) : ""; - int cmd = get_dm_type(type); - - printf("%s %s %s\n", name, type, (cmd != DMT_EVENT && cmd != DMT_COMMAND) ? data : "0"); + char *type = tb[2] ? blobmsg_get_string(tb[2]) : "xsd:string"; + printf("%s %s\n", name, type); } cli_data->ubus_status = true; @@ -151,7 +151,6 @@ static void __ubus_callback(struct ubus_request *req, int msgtype __attribute__( static int cli_exec_cmd(cli_data_t *cli_data, const char *path, const char *value) { struct blob_buf b = {0}; - void *table = NULL; int err = EXIT_SUCCESS; memset(&b, 0, sizeof(struct blob_buf)); @@ -159,21 +158,17 @@ static int cli_exec_cmd(cli_data_t *cli_data, const char *path, const char *valu blob_buf_init(&b, 0); blobmsg_add_string(&b, "path", path); - if (value) blobmsg_add_string(&b, "value", value); + blobmsg_add_string(&b, "value", value ? value : ""); - table = blobmsg_open_table(&b, "optional"); - blobmsg_add_string(&b, "format", "raw"); - blobmsg_close_table(&b, table); - - int e = bbfdm_ubus_invoke(BBFDM_DEFAULT_UBUS_OBJ, cli_data->cmd, b.head, __ubus_callback, cli_data); + int e = bbfdm_ubus_invoke(BBFDM_UBUS_OBJECT, cli_data->cmd, b.head, __ubus_callback, cli_data); if (e < 0) { - printf("ERROR: ubus invoke for [object:%s method:%s] exit with error(%d)\n", BBFDM_DEFAULT_UBUS_OBJ, cli_data->cmd, e); + printf("ERROR: ubus invoke for [object:%s method:%s] exit with error(%d)\n", BBFDM_UBUS_OBJECT, cli_data->cmd, e); err = EXIT_FAILURE; } if (cli_data->ubus_status == false) { - printf("ERROR: ubus call for [object:%s method:%s] exit with error\n", BBFDM_DEFAULT_UBUS_OBJ, cli_data->cmd); + printf("ERROR: ubus call for [object:%s method:%s] exit with error\n", BBFDM_UBUS_OBJECT, cli_data->cmd); err = EXIT_FAILURE; } @@ -182,7 +177,7 @@ static int cli_exec_cmd(cli_data_t *cli_data, const char *path, const char *valu return err; } -static int cli_exec_help(cli_data_t *cli_data UNUSED, const char *path UNUSED, const char *value UNUSED) +static int cli_exec_help(cli_data_t *cli_data __attribute__((unused)), const char *path __attribute__((unused)), const char *value __attribute__((unused))) { cli_cmd_t *cli_cmd; @@ -236,7 +231,7 @@ end: return err; } -int bbfdm_cli_exec_command(int argc, char *argv[]) +int bbfdmd_cli_exec_command(int argc, char *argv[]) { cli_data_t cli_data = {0}; diff --git a/bbfdmd/ubus/cli.h b/bbfdmd/ubus/cli.h index 8de5a907..56b3c935 100644 --- a/bbfdmd/ubus/cli.h +++ b/bbfdmd/ubus/cli.h @@ -1,11 +1,17 @@ /* - * cli.c: Cli command for bbfdmd + * Copyright (C) 2023-2025 iopsys Software Solutions AB * - * Copyright (C) 2023 IOPSYS Software Solutions AB. All rights reserved. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation * - * Author: Amin Ben Romdhane + * Author: Amin Ben Romdhane * - * See LICENSE file for license related information. */ -int bbfdm_cli_exec_command(int argc, char *argv[]); +#ifndef BBFDMD_CLI_H +#define BBFDMD_CLI_H + +int bbfdmd_cli_exec_command(int argc, char *argv[]); + +#endif /* BBFDMD_CLI_H */ diff --git a/bbfdmd/ubus/common.c b/bbfdmd/ubus/common.c new file mode 100644 index 00000000..deae68cd --- /dev/null +++ b/bbfdmd/ubus/common.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2025 iopsys Software Solutions AB + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * Author: Amin Ben Romdhane + * + */ + +#include +#include + +#include "common.h" + +int g_log_level = LOG_ERR; + +unsigned int get_proto_type(const char *proto) +{ + int type = BBFDMD_BOTH; + + if (proto) { + if (strcmp(proto, "cwmp") == 0) + type = BBFDMD_CWMP; + else if (strcmp(proto, "usp") == 0) + type = BBFDMD_USP; + else + type = BBFDMD_BOTH; + } + + return type; +} + +unsigned int get_proto_type_option_value(struct blob_attr *msg) +{ + struct blob_attr *tb[1] = {0}; + const struct blobmsg_policy p[1] = { + { "proto", BLOBMSG_TYPE_STRING } + }; + int proto = BBFDMD_BOTH; + + if (!msg) + return proto; + + blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg)); + + if (tb[0]) { + const char *val = blobmsg_get_string(tb[0]); + proto = get_proto_type(val); + } + + return proto; +} + +bool proto_matches(unsigned int dm_type, const enum bbfdmd_type_enum type) +{ + return (dm_type == BBFDMD_BOTH || type == BBFDMD_BOTH || dm_type == type) && type != BBFDMD_NONE; +} + +static void sync_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg) +{ + struct blob_attr *attr = NULL; + int remaining = 0; + + if (!req || !msg) + return; + + struct blob_buf *bb_response = (struct blob_buf *)req->priv; + + if (!bb_response) + return; + + blob_for_each_attr(attr, msg, remaining) { + blobmsg_add_field(bb_response, blobmsg_type(attr), blobmsg_name(attr), blobmsg_data(attr), blobmsg_len(attr)); + } +} + +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}; + struct blob_attr *attr = NULL; + int remaining = 0; + + if (!ubus_obj || !ubus_method || !msg || !bb_response) + return; + + memset(&req_buf, 0, sizeof(struct blob_buf)); + 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 value_in[MAX_PATH_LENGTH]; + + char *reference_value = get_reference_data(blobmsg_get_string(attr), "reference_value"); + snprintf(value_in, sizeof(value_in), "%s=>%s##", blobmsg_get_string(attr), reference_value ? reference_value : ""); + BBFDM_FREE(reference_value); + + blobmsg_add_string(&req_buf, blobmsg_name(attr), value_in); + } 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 value_in[MAX_PATH_LENGTH]; + + char *reference_value = get_reference_data(blobmsg_get_string(__attr), "reference_value"); + snprintf(value_in, sizeof(value_in), "%s=>%s##", blobmsg_get_string(__attr), reference_value ? reference_value : ""); + BBFDM_FREE(reference_value); + + blobmsg_add_string(&req_buf, blobmsg_name(__attr), value_in); + } 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)); + } + } + + 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, ubus_method, json_str); + BBFDM_FREE(json_str); + } + + BBFDM_UBUS_INVOKE_SYNC(ubus_obj, ubus_method, req_buf.head, 2000, sync_callback, bb_response); + + blob_buf_free(&req_buf); +} diff --git a/bbfdmd/ubus/common.h b/bbfdmd/ubus/common.h new file mode 100644 index 00000000..9d30a62b --- /dev/null +++ b/bbfdmd/ubus/common.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2025 iopsys Software Solutions AB + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * Author: Amin Ben Romdhane + * + */ + +#ifndef BBFDMD_COMMON_H +#define BBFDMD_COMMON_H + +#include "libbbfdm-api/version-2/bbfdm_api.h" + +#define BBFDM_ROOT_OBJECT "Device." +#define BBFDM_UBUS_OBJECT "bbfdm" +#define BBFDM_ADD_EVENT "AddObj" +#define BBFDM_DEL_EVENT "DelObj" +#define BBFDM_EVENT_NAME "event" +#define BBFDM_MICROSERVICE_INPUT_PATH "/etc/bbfdm/services" +#define MAX_PATH_LENGTH 1024 +#define SERVICE_CALL_TIMEOUT 5000 // 5 secs +#define SERVICE_CALL_OPERATE_TIMEOUT 1800000 // 30 mins + +enum bbfdmd_type_enum { + BBFDMD_NONE = 0, + BBFDMD_CWMP = 1<<0, + BBFDMD_USP = 1<<1, + BBFDMD_BOTH = BBFDMD_CWMP | BBFDMD_USP, +}; + +unsigned int get_proto_type(const char *proto); +unsigned int get_proto_type_option_value(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 new file mode 100644 index 00000000..00900ce3 --- /dev/null +++ b/bbfdmd/ubus/get.c @@ -0,0 +1,350 @@ +/* + * Copyright (C) 2025 iopsys Software Solutions AB + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * Author: Amin Ben Romdhane + * + */ + +#include +#include + +#include "common.h" +#include "service.h" +#include "get.h" + +extern int g_log_level; + +static void add_linker_entry(struct async_request_context *ctx, const char *linker_path, const char *linker_value) +{ + struct linker_args *linker = calloc(1, sizeof(struct linker_args)); + if (!linker) + return; + + list_add_tail(&linker->list, &ctx->linker_list); + linker->path = strdup(linker_path ? linker_path : ""); + linker->value = strdup(linker_value ? linker_value : ""); +} + +static void free_linker_entries(struct async_request_context *ctx) +{ + struct linker_args *linker = NULL, *tmp = NULL; + + list_for_each_entry_safe(linker, tmp, &ctx->linker_list, list) { + list_del(&linker->list); + BBFDM_FREE(linker->path); + BBFDM_FREE(linker->value); + BBFDM_FREE(linker); + } +} + +static void fill_blob_param(struct blob_buf *bb, const char *path, const char *data, const char *type) +{ + if (!bb || !path || !data || !type) + return; + + void *table = blobmsg_open_table(bb, NULL); + + blobmsg_add_string(bb, "path", path); + blobmsg_add_string(bb, "data", data); + blobmsg_add_string(bb, "type", type); + + blobmsg_close_table(bb, table); +} + +static void resolve_reference_path(struct async_request_context *ctx, char *ref_path, char *output, size_t output_len) +{ + char *token = NULL, *saveptr = NULL; + char buffer[MAX_PATH_LENGTH] = {0}; + + if (!ref_path || !output || !output_len) { + BBFDM_ERR("Invalid arguments"); + return; + } + + // Initialize output buffer + output[0] = 0; + + // Return if reference path is empty + if (strlen(ref_path) == 0) + return; + + snprintf(buffer, sizeof(buffer), "%s", ref_path); + + for (token = strtok_r(buffer, ",", &saveptr); token; token = strtok_r(NULL, ",", &saveptr)) { + + // Reference is found, don't need to parse the list + if (!strchr(token, '[')) { + snprintf(output, output_len, "%s", token); + return; + } + + struct linker_args *linker = NULL; + list_for_each_entry(linker, &ctx->linker_list, list) { + // Reference is found in the resolved list + if (strcmp(linker->path, token) == 0 && strlen(linker->value) != 0) { + snprintf(output, output_len, "%s", linker->value); + return; + } + } + + // Reference is not found in the resolved list + { + // Try to get reference value from micro-services directly + char *reference_path = get_reference_data(token, "reference_path"); + + // Add path to list in order to be used by other parameters + add_linker_entry(ctx, token, reference_path ? reference_path : ""); + + // Reference value is found + if (reference_path != NULL) { + snprintf(output, output_len, "%s", reference_path); + BBFDM_FREE(reference_path); + return; + } + } + } + + BBFDM_ERR("Can't resolve reference path '%s' -> Set its value to empty", ref_path); +} + +static void prepare_and_send_response(struct async_request_context *ctx) +{ + struct blob_attr *attr = NULL; + struct blob_buf bb = {0}; + int remaining = 0; + + if (!ctx) + return; + + memset(&bb, 0, sizeof(struct blob_buf)); + blob_buf_init(&bb, 0); + + void *array = blobmsg_open_array(&bb, "results"); + + if (ctx->path_matched == false) { + void *table = blobmsg_open_table(&bb, NULL); + blobmsg_add_string(&bb, "path", ctx->requested_path); + blobmsg_add_u32(&bb, "fault", 9005); + blobmsg_add_string(&bb, "fault_msg", "Invalid parameter name"); + blobmsg_close_table(&bb, 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] = { + { "path", BLOBMSG_TYPE_STRING }, + { "data", BLOBMSG_TYPE_STRING }, + { "type", BLOBMSG_TYPE_STRING }, + { "reference", BLOBMSG_TYPE_BOOL }, + }; + + blobmsg_parse(policy, 4, fields, blobmsg_data(attr), blobmsg_len(attr)); + + bool is_reference = fields[3] ? blobmsg_get_u8(fields[3]) : false; + + if (is_reference) { + char buffer[1024] = {0}; + + char *path = fields[0] ? blobmsg_get_string(fields[0]) : ""; + char *data = fields[1] ? blobmsg_get_string(fields[1]) : ""; + char *type = fields[2] ? blobmsg_get_string(fields[2]) : ""; + + resolve_reference_path(ctx, data, buffer, sizeof(buffer)); + fill_blob_param(&bb, path, buffer, type); + } else { + blobmsg_add_blob(&bb, attr); + } + } else { + blobmsg_add_blob(&bb, attr); + } + } + } + + blobmsg_close_array(&bb, array); + + ubus_send_reply(ctx->ubus_ctx, &ctx->request_data, bb.head); + blob_buf_free(&bb); +} + +void send_response(struct async_request_context *ctx) +{ + prepare_and_send_response(ctx); + + if (strcmp(ctx->ubus_method, "get") == 0) { + ubus_unregister_event_handler(ctx->ubus_ctx, &ctx->linker_handler); + send_linker_cleanup_event(ctx->ubus_ctx); + free_linker_entries(ctx); + } + + ubus_complete_deferred_request(ctx->ubus_ctx, &ctx->request_data, UBUS_STATUS_OK); + blob_buf_free(&ctx->tmp_bb); + BBFDM_FREE(ctx); +} + +static struct blob_attr *get_results_array(struct blob_attr *msg) +{ + struct blob_attr *tb[1] = {0}; + const struct blobmsg_policy p[1] = { + { "results", BLOBMSG_TYPE_ARRAY } + }; + + if (msg == NULL) + return NULL; + + blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg)); + + return tb[0]; +} + +static void append_response_data(struct ubus_request_tracker *tracker, struct blob_attr *msg) +{ + struct blob_attr *attr = NULL; + int remaining = 0; + + if (!tracker || !msg) + return; + + struct blob_attr *results = get_results_array(msg); + if (!results) + return; + + blobmsg_for_each_attr(attr, results, remaining) { + blobmsg_add_blob(&tracker->ctx->tmp_bb, attr); + } +} + +static void handle_request_timeout(struct uloop_timeout *timeout) +{ + struct ubus_request_tracker *tracker = container_of(timeout, struct ubus_request_tracker, timeout); + BBFDM_ERR("Timeout occurred for request: '%s'", tracker->request_name); + + ubus_abort_request(tracker->ctx->ubus_ctx, &tracker->async_request); + tracker->ctx->pending_requests--; + + if (tracker->ctx->pending_requests == 0 && tracker->ctx->service_list_processed) { + BBFDM_ERR("All requests completed after timeout"); + send_response(tracker->ctx); + } + + BBFDM_FREE(tracker); +} + +static void ubus_result_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg __attribute__((unused))) +{ + struct ubus_request_tracker *tracker = container_of(req, struct ubus_request_tracker, async_request); + + if (msg) { + BBFDM_DEBUG("Response from object '%s'", tracker->request_name); + append_response_data(tracker, msg); + } +} + +static void ubus_request_complete(struct ubus_request *req, int ret) +{ + struct ubus_request_tracker *tracker = container_of(req, struct ubus_request_tracker, async_request); + BBFDM_DEBUG("Request completed for '%s' with status: '%d'", tracker->request_name, ret); + + uloop_timeout_cancel(&tracker->timeout); + tracker->ctx->pending_requests--; + + if (tracker->ctx->pending_requests == 0 && tracker->ctx->service_list_processed) { + BBFDM_DEBUG("Result Callback: All requests completed"); + send_response(tracker->ctx); + } + + BBFDM_FREE(tracker); +} + +void run_async_call(struct async_request_context *ctx, const char *ubus_obj, struct blob_attr *msg) +{ + struct blob_buf req_buf = {0}; + struct blob_attr *attr = NULL; + int remaining = 0; + uint32_t id = 0; + + if (!ctx || !ubus_obj || !msg) { + BBFDM_ERR("Invalid arguments"); + return; + } + + if (ubus_lookup_id(ctx->ubus_ctx, ubus_obj, &id)) { + BBFDM_ERR("Failed to lookup object: %s", ubus_obj); + return; + } + + struct ubus_request_tracker *tracker = calloc(1, sizeof(struct ubus_request_tracker)); + if (!tracker) { + BBFDM_ERR("Failed to allocate memory for request tracker"); + return; + } + + tracker->ctx = ctx; + ctx->pending_requests++; + ctx->path_matched = true; + + memset(&req_buf, 0, sizeof(struct blob_buf)); + blob_buf_init(&req_buf, 0); + + blob_for_each_attr(attr, msg, remaining) { + blobmsg_add_field(&req_buf, blobmsg_type(attr), blobmsg_name(attr), blobmsg_data(attr), blobmsg_len(attr)); + } + + snprintf(tracker->request_name, sizeof(tracker->request_name), "%s->%s", ubus_obj, ctx->ubus_method); + + tracker->timeout.cb = handle_request_timeout; + uloop_timeout_set(&tracker->timeout, !strcmp(ctx->ubus_method, "operate") ? SERVICE_CALL_OPERATE_TIMEOUT : SERVICE_CALL_TIMEOUT); + + 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, ctx->ubus_method, json_str); + BBFDM_FREE(json_str); + } + + if (ubus_invoke_async(ctx->ubus_ctx, id, ctx->ubus_method, req_buf.head, &tracker->async_request)) { + BBFDM_ERR("Failed to invoke async method for object: %s", tracker->request_name); + uloop_timeout_cancel(&tracker->timeout); + BBFDM_FREE(tracker); + } else { + tracker->async_request.data_cb = ubus_result_callback; + tracker->async_request.complete_cb = ubus_request_complete; + ubus_complete_request_async(ctx->ubus_ctx, &tracker->async_request); + } + + 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); +} + +void linker_response_callback(struct ubus_context *ctx __attribute__((unused)), struct ubus_event_handler *ev, const char *type __attribute__((unused)), struct blob_attr *msg) +{ + struct async_request_context *context = NULL; + struct blob_attr *attr = NULL; + size_t rem = 0; + + if (!msg) + return; + + context = container_of(ev, struct async_request_context, linker_handler); + if (context == NULL) { + BBFDM_ERR("Failed to get the request context"); + return; + } + + blobmsg_for_each_attr(attr, msg, rem) { + BBFDM_DEBUG("LINKER RESPONSE: '%s' <=> '%s'", blobmsg_name(attr), blobmsg_get_string(attr)); + add_linker_entry(context, blobmsg_name(attr), blobmsg_get_string(attr)); + } +} diff --git a/bbfdmd/ubus/get.h b/bbfdmd/ubus/get.h new file mode 100644 index 00000000..4350d1a5 --- /dev/null +++ b/bbfdmd/ubus/get.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2025 iopsys Software Solutions AB + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * Author: Amin Ben Romdhane + * + */ + +#ifndef BBFDMD_GET_H +#define BBFDMD_GET_H + +enum { + BBFDM_PATH, + BBFDM_VALUE, + BBFDM_INPUT, + __BBFDM_MAX +}; + +struct linker_args { + struct list_head list; + char *path; + char *value; +}; + +struct async_request_context { + struct ubus_context *ubus_ctx; + struct ubus_request_data request_data; + struct ubus_event_handler linker_handler; + struct list_head linker_list; + struct blob_buf tmp_bb; + bool service_list_processed; + bool path_matched; + int pending_requests; + char requested_path[MAX_PATH_LENGTH]; + char ubus_method[32]; +}; + +struct ubus_request_tracker { + struct async_request_context *ctx; + struct ubus_request async_request; + struct uloop_timeout timeout; + char request_name[128]; +}; + +void send_linker_cleanup_event(struct ubus_context *ctx); +void linker_response_callback(struct ubus_context *ctx, struct ubus_event_handler *ev, const char *type, struct blob_attr *msg); + +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); + +#endif /* BBFDMD_GET_H */ diff --git a/bbfdmd/ubus/service.c b/bbfdmd/ubus/service.c new file mode 100644 index 00000000..2a2b5e7d --- /dev/null +++ b/bbfdmd/ubus/service.c @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2025 iopsys Software Solutions AB + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * Author: Amin Ben Romdhane + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "service.h" + +LIST_HEAD(registered_services); + +extern int g_log_level; + +static void add_service_to_list(const char *name, int service_proto, service_object_t *objects, size_t count, bool is_unified) +{ + service_entry_t *service = NULL; + + if (!name || !objects || count == 0) { + BBFDM_ERR("Invalid service registration parameters"); + return; + } + + service = calloc(1, sizeof(service_entry_t)); + list_add_tail(&service->list, ®istered_services); + + service->name = strdup(name); + service->protocol = service_proto; + service->objects = objects; + service->object_count = count; + service->is_unified = is_unified; +} + +static int load_service_from_file(struct ubus_context *ubus_ctx, const char *filename, const char *file_path) +{ + size_t num_objs = 0; + + if (!filename || !file_path) { + BBFDM_ERR("Invalid filename or file path"); + return -1; + } + + json_object *json_root = json_object_from_file(file_path); + if (!json_root) { + BBFDM_ERR("Failed to read JSON file: %s", file_path); + return -1; + } + + json_object *daemon_config = NULL; + json_object_object_get_ex(json_root, "daemon", &daemon_config); + if (!daemon_config) { + BBFDM_ERR("Failed to find daemon object"); + json_object_put(json_root); + return -1; + } + + json_object *enable_jobj = NULL; + json_object_object_get_ex(daemon_config, "enable", &enable_jobj); + bool enable = enable_jobj ? json_object_get_boolean(enable_jobj) : false; + if (!enable) { + BBFDM_INFO("Service is disabled, Skipping service"); + json_object_put(json_root); + return -1; + } + + char service_name[MAX_PATH_LENGTH] = {0}; + snprintf(service_name, sizeof(service_name), "%s.%.*s", BBFDM_UBUS_OBJECT, (int)(strlen(filename) - 5), filename); + + uint32_t ubus_id; + if (ubus_lookup_id(ubus_ctx, service_name, &ubus_id)) { + BBFDM_ERR("Failed to lookup UBUS object: %s", service_name); + } + + json_object *unified_daemon_jobj = NULL; + json_object_object_get_ex(daemon_config, "unified_daemon", &unified_daemon_jobj); + bool is_unified = unified_daemon_jobj ? json_object_get_boolean(unified_daemon_jobj) : false; + + json_object *proto_jobj = NULL; + json_object_object_get_ex(daemon_config, "proto", &proto_jobj); + int service_proto = get_proto_type(proto_jobj ? json_object_get_string(proto_jobj) : ""); + + json_object *services_array = NULL; + if (!json_object_object_get_ex(daemon_config, "services", &services_array) || json_object_get_type(services_array) != json_type_array) { + json_object_put(json_root); + return -1; + } + + size_t service_count = json_object_array_length(services_array); + if (service_count == 0) { + BBFDM_ERR("Skipping service '%s' due to no objects defined", service_name); + json_object_put(json_root); + return -1; + } + + service_object_t *objects = calloc(service_count, sizeof(service_object_t)); + + for (size_t i = 0; i < service_count; i++) { + json_object *service_obj = json_object_array_get_idx(services_array, i); + json_object *parent_dm = NULL, *object = NULL, *proto = NULL; + + json_object_object_get_ex(service_obj, "parent_dm", &parent_dm); + json_object_object_get_ex(service_obj, "object", &object); + json_object_object_get_ex(service_obj, "proto", &proto); + + snprintf(objects[num_objs].parent_path, sizeof(objects[num_objs].parent_path), "%s", parent_dm ? json_object_get_string(parent_dm) : ""); + snprintf(objects[num_objs].object_name, sizeof(objects[num_objs].object_name), "%s", object ? json_object_get_string(object) : ""); + + if (strlen(objects[num_objs].parent_path) == 0 || strlen(objects[num_objs].object_name) == 0) { + BBFDM_ERR("Skip empty registration parent_dm[%s] or object[%s]", objects[num_objs].parent_path, objects[num_objs].object_name); + continue; + } + + objects[num_objs].protocol = get_proto_type(proto ? json_object_get_string(proto) : ""); + num_objs++; + } + + BBFDM_INFO("Registering [%s :: %lu :: %d]", service_name, num_objs, is_unified); + add_service_to_list(service_name, service_proto, objects, num_objs, is_unified); + json_object_put(json_root); + return 0; +} + +static int filter(const struct dirent *entry) +{ + return entry->d_name[0] != '.'; +} + +static int compare(const struct dirent **a, const struct dirent **b) +{ + size_t len_a = strlen((*a)->d_name); + size_t len_b = strlen((*b)->d_name); + + if (len_a < len_b) // Sort by length (shorter first) + return -1; + + if (len_a > len_b) + return 1; + + return strcasecmp((*a)->d_name, (*b)->d_name); // If lengths are equal, sort alphabetically +} + +int register_services(struct ubus_context *ubus_ctx) +{ + struct dirent **namelist; + + int num_files = scandir(BBFDM_MICROSERVICE_INPUT_PATH, &namelist, filter, compare); + + for (int i = 0; i < num_files; i++) { + char file_path[512] = {0}; + + snprintf(file_path, sizeof(file_path), "%s/%s", BBFDM_MICROSERVICE_INPUT_PATH, namelist[i]->d_name); + + if (!bbfdm_file_exists(file_path) || !bbfdm_is_regular_file(file_path)) { + BBFDM_FREE(namelist[i]); + continue; + } + + if (load_service_from_file(ubus_ctx, namelist[i]->d_name, file_path)) { + BBFDM_ERR("Failed to load service: %s", namelist[i]->d_name); + } + + BBFDM_FREE(namelist[i]); + } + + BBFDM_FREE(namelist); + return 0; +} + +void unregister_services(void) +{ + service_entry_t *service = NULL, *tmp = NULL; + + list_for_each_entry_safe(service, tmp, ®istered_services, list) { + list_del(&service->list); + BBFDM_FREE(service->name); + BBFDM_FREE(service->objects); + BBFDM_FREE(service); + } +} + +void list_registered_services(struct blob_buf *bb) +{ + service_entry_t *service = NULL; + + if (!bb) + return; + + void *array = blobmsg_open_array(bb, "registered_services"); + + list_for_each_entry(service, ®istered_services, list) { + void *table = blobmsg_open_table(bb, NULL); + blobmsg_add_string(bb, "name", service->name ? service->name : ""); + blobmsg_add_string(bb, "proto", service->protocol == BBFDMD_USP ? "usp" : service->protocol == BBFDMD_CWMP ? "cwmp" : "both"); + blobmsg_add_u8(bb, "unified_daemon", service->is_unified); + void *objects_array = blobmsg_open_array(bb, "objects"); + for (size_t i = 0; i < service->object_count; i++) { + void *obj_table = blobmsg_open_table(bb, NULL); + blobmsg_add_string(bb, "parent_dm", service->objects[i].parent_path); + blobmsg_add_string(bb, "object", service->objects[i].object_name); + blobmsg_add_string(bb, "proto", service->objects[i].protocol == BBFDMD_USP ? "usp" : service->objects[i].protocol == BBFDMD_CWMP ? "cwmp" : "both"); + blobmsg_close_table(bb, obj_table); + } + blobmsg_close_array(bb, objects_array); + blobmsg_close_table(bb, table); + } + + blobmsg_close_array(bb, array); +} + +bool is_path_match(const char *requested_path, unsigned int requested_proto, service_entry_t *service) +{ + if (!proto_matches(requested_proto, service->protocol)) + return false; + + if (strlen(requested_path) == 0 || strcmp(requested_path, BBFDM_ROOT_OBJECT) == 0) + return true; + + if (strncmp(BBFDM_ROOT_OBJECT, requested_path, strlen(BBFDM_ROOT_OBJECT)) != 0) + return false; + + for (size_t idx = 0; idx < service->object_count; idx++) { + char current_obj[MAX_PATH_LENGTH] = {0}; + + if (!proto_matches(requested_proto, service->objects[idx].protocol)) + continue; + + snprintf(current_obj, sizeof(current_obj), "%s%s", service->objects[idx].parent_path, service->objects[idx].object_name); + + if (strncmp(current_obj, requested_path, strlen(current_obj)) == 0) + return true; + + if (strncmp(requested_path, current_obj, strlen(requested_path)) == 0) + return true; + } + + 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/bbfdmd/ubus/service.h b/bbfdmd/ubus/service.h new file mode 100644 index 00000000..426231b9 --- /dev/null +++ b/bbfdmd/ubus/service.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2025 iopsys Software Solutions AB + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * Author: Amin Ben Romdhane + * + */ + +#ifndef BBFDMD_SERVICE_H +#define BBFDMD_SERVICE_H + +typedef struct { + enum bbfdmd_type_enum protocol; + char parent_path[MAX_PATH_LENGTH - 256]; + char object_name[256]; +} service_object_t; + +typedef struct service_entry { + struct list_head list; + char *name; + enum bbfdmd_type_enum protocol; + bool is_unified; + size_t object_count; + service_object_t *objects; +} service_entry_t; + +int register_services(struct ubus_context *ctx); +void unregister_services(void); +void list_registered_services(struct blob_buf *bb); + +bool is_path_match(const char *requested_path, unsigned int requested_proto, service_entry_t *service); + +#endif /* BBFDMD_SERVICE_H */ diff --git a/dm-service/dm_service.c b/dm-service/dm_service.c index 16f175e3..edbfaa4e 100644 --- a/dm-service/dm_service.c +++ b/dm-service/dm_service.c @@ -1,7 +1,7 @@ /* * dm_service.c: dm-service deamon * - * Copyright (C) 2024 IOPSYS Software Solutions AB. All rights reserved. + * Copyright (C) 2024-2025 IOPSYS Software Solutions AB. All rights reserved. * * Author: Amin Ben Romdhane * @@ -28,7 +28,7 @@ int main(int argc, char **argv) { struct bbfdm_context bbfdm_ctx = {0}; char proc_name[64] = {0}; - int log_level = 3; // Default is LOG_ERR + int log_level = LOG_ERR; int err = 0, ch; memset(&bbfdm_ctx, 0, sizeof(struct bbfdm_context)); @@ -53,7 +53,7 @@ int main(int argc, char **argv) } } - if (dm_is_micro_service() == false) { + if (strlen(bbfdm_ctx.config.service_name) == 0) { fprintf(stderr, "Failed to start micro-service without providing the name using '-m' option\n"); exit(-1); } diff --git a/docs/api/ubus/bbfdm.json b/docs/api/ubus/bbfdm.json index 39f4c98d..c01498e1 100644 --- a/docs/api/ubus/bbfdm.json +++ b/docs/api/ubus/bbfdm.json @@ -742,31 +742,6 @@ } } } - }, - "notify_event": { - "title": "notify occurance of an event on ubus", - "type": "object", - "required": [ - "input" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - }, - "input": { - "type": "array", - "properties": {} - } - } - }, - "output": {} - } } } } diff --git a/gitlab-ci/generate_supported_dm.sh b/gitlab-ci/generate_supported_dm.sh index d70b0366..421177ac 100755 --- a/gitlab-ci/generate_supported_dm.sh +++ b/gitlab-ci/generate_supported_dm.sh @@ -19,12 +19,10 @@ install_cmph install_libeasy install_libethernet -# Make sure that all plugins are removed -[ ! -d "${BBFDM_PLUGIN_DIR}" ] && mkdir -p "${BBFDM_PLUGIN_DIR}" -rm -f ${BBFDM_PLUGIN_DIR}/* - [ ! -d "${BBFDM_MS_DIR}" ] && mkdir -p "${BBFDM_MS_DIR}" -rm -f ${BBFDM_MS_DIR}/* +rm -rf ${BBFDM_MS_DIR}/* + +mkdir -p ${BBFDM_MS_DIR}/core if [ -z "${1}" ]; then ./tools/generate_dm.py tools/tools_input.json diff --git a/gitlab-ci/install-dependencies.sh b/gitlab-ci/install-dependencies.sh index 69c0369b..2ae39d49 100755 --- a/gitlab-ci/install-dependencies.sh +++ b/gitlab-ci/install-dependencies.sh @@ -8,12 +8,17 @@ source ./gitlab-ci/shared.sh exec_cmd apt update exec_cmd pip3 install xlwt -# Make sure that all plugins are removed -[ ! -d "${BBFDM_PLUGIN_DIR}" ] && mkdir -p "${BBFDM_PLUGIN_DIR}" -rm -f ${BBFDM_PLUGIN_DIR}/* +# Create directories for micro-service configuration and shared files +[ ! -d "${BBFDM_MS_CONF}" ] && mkdir -p "${BBFDM_MS_CONF}" +[ ! -d "${BBFDM_MS_DIR}" ] && mkdir -p "${BBFDM_MS_DIR}" + +# Make sure that all generated files are removed +rm -rf ${BBFDM_MS_DIR}/* +rm -f ${BBFDM_MS_CONF}/* +rm -f ${BBFDM_DMMAP_DIR}/* rm -f ${BBFDM_LOG_FILE} -# compile and install libbbf +# compile and install Core Data Model as a micro-service install_libbbf ${1} #compile and install libbbf_test dynamic extension library @@ -23,10 +28,6 @@ install_libbbf_test ${1} if [ -z "${1}" ]; then echo "Skip installation of micro-services ...." else - # Create directories for micro-service configuration and shared files - mkdir -p /etc/bbfdm/services - mkdir -p /usr/share/bbfdm/micro_services - #install SYSMNGR Data Model as a micro-service echo "Installing System Manager (SYSMNGR) Data Model as a micro-service" install_sysmngr_as_micro_service @@ -39,5 +40,7 @@ else echo "Installing Network Data Model (netmngr) as a micro-service" install_netmngr_as_micro_service + #install Ethernet Data Model as a micro-service + echo "Installing Ethernet Data Model (ethmngr) as a micro-service" install_ethmngr_as_micro_service fi diff --git a/gitlab-ci/micro_service.conf b/gitlab-ci/micro_service.conf index 9d6bfede..24511b18 100644 --- a/gitlab-ci/micro_service.conf +++ b/gitlab-ci/micro_service.conf @@ -10,6 +10,10 @@ command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-netmngr priority=7 command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-wifidmd-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m wifidmd" +[program:core] +priority=8 +command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-core-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/dm-service -m core" + [program:ethmngr] priority=10 command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-ethmngr-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/ethmngr" diff --git a/gitlab-ci/setup.sh b/gitlab-ci/setup.sh index 8c577781..38473d51 100755 --- a/gitlab-ci/setup.sh +++ b/gitlab-ci/setup.sh @@ -5,6 +5,10 @@ echo "# Preparation script ..." # link '/bin/sh' to bash instead of dash ln -sf bash /bin/sh +#cleanup +rm -f /etc/config/* +rm -rf /tmp/bbfdm/.bbfdm/* /tmp/bbfdm/.cwmp/* /tmp/bbfdm/.usp/* + echo "Installing bbfdm rpcd utilities" cp -r ./test/files/etc/* /etc/ cp -r ./test/files/usr/* /usr/ diff --git a/gitlab-ci/shared.sh b/gitlab-ci/shared.sh index 899fa8b4..74252527 100755 --- a/gitlab-ci/shared.sh +++ b/gitlab-ci/shared.sh @@ -1,7 +1,8 @@ #!/bin/bash -BBFDM_PLUGIN_DIR="/usr/share/bbfdm/plugins" BBFDM_MS_DIR="/usr/share/bbfdm/micro_services" +BBFDM_MS_CONF="/etc/bbfdm/services" +BBFDM_DMMAP_DIR="etc/bbfdm/dmmap/" BBFDM_LOG_FILE="/tmp/bbfdm.log" if [ -z "${CI_PROJECT_PATH}" ]; then @@ -43,43 +44,15 @@ function exec_cmd_verbose() fi } -generate_input_schema() +function install_ms() { - service_name="$1" - schema='{ - "daemon": { - "enable": "1", - "service_name": "'"$service_name"'", - "config": { - "loglevel": "4" - } - } -}' - echo "$schema" + exec_cmd cp -f "${1}" ${BBFDM_MS_DIR}/${2}.so } -generate_input_schema_with_output_name() +function install_ms_plugin() { - service_name="$1" - output_name="$2" - schema='{ - "daemon": { - "enable": "1", - "service_name": "'"$service_name"'", - "config": { - "loglevel": "4" - }, - "output": { - "name": "'"$output_name"'" - } - } -}' - echo "$schema" -} - -function install_plugin() -{ - exec_cmd cp -f "${1}" ${BBFDM_PLUGIN_DIR}/ + exec_cmd mkdir -p ${BBFDM_MS_DIR}/${2} + exec_cmd cp -f "${1}" ${BBFDM_MS_DIR}/${2}/ } function install_libbbf() @@ -107,6 +80,7 @@ function install_libbbf() echo "371d530c95a17d1ca223a29b7a6cdc97e1135c1e0959b51106cca91a0b148b5e42742d372a359760742803f2a44bd88fca67ccdcfaeed26d02ce3b6049cb1e04" > /etc/bbfdm/.secure_hash cd .. exec_cmd cp utilities/bbf_configd /usr/sbin/ + install_ms /usr/lib/libcore.so core } function install_libbbf_test() @@ -117,21 +91,17 @@ function install_libbbf_test() exec_cmd_verbose make -C test/bbf_test/ echo "installing libbbf_test" - install_plugin ./test/bbf_test/libbbf_test.so + install_ms_plugin ./test/bbf_test/libbbf_test.so core } function install_wifidmd_as_micro_service() { [ -d "/opt/dev/wifidmd" ] && return 0 - exec_cmd git clone https://dev.iopsys.eu/bbf/wifidmd.git /opt/dev/wifidmd + exec_cmd git clone -b devel https://dev.iopsys.eu/bbf/wifidmd.git /opt/dev/wifidmd - exec_cmd make -C /opt/dev/wifidmd/src/ clean && make -C /opt/dev/wifidmd/src/ CFLAGS="-D'BBF_VENDOR_PREFIX=\"X_IOPSYS_EU_\"'" - exec_cmd cp -f /opt/dev/wifidmd/src/libwifi.so /usr/share/bbfdm/micro_services/wifidmd.so - exec_cmd mkdir -p /usr/share/bbfdm/micro_services/wifidmd - exec_cmd cp -f /opt/dev/wifidmd/src/libdataelements.so /usr/share/bbfdm/micro_services/wifidmd - - generate_input_schema_with_output_name "wifidmd" "WiFi" > /etc/bbfdm/services/wifidmd.json + exec_cmd make -C /opt/dev/wifidmd/src/ clean && make -C /opt/dev/wifidmd/src/ CFLAGS="-D'BBF_VENDOR_PREFIX=\"X_IOPSYS_EU_\"'" WIFIDMD_WIFI_DATAELEMENTS='y' + install_ms /opt/dev/wifidmd/src/libwifi.so wifidmd } function install_libeasy() @@ -172,45 +142,45 @@ function install_ethmngr_as_micro_service() exec_cmd git clone https://dev.iopsys.eu/hal/ethmngr.git /opt/dev/ethmngr exec_cmd make -C /opt/dev/ethmngr - exec_cmd cp /opt/dev/ethmngr/ethmngr /usr/sbin/ethmngr + exec_cmd cp -f /opt/dev/ethmngr/ethmngr /usr/sbin/ethmngr } function install_netmngr_as_micro_service() { [ -d "/opt/dev/netmngr" ] && return 0 - exec_cmd git clone https://dev.iopsys.eu/network/netmngr.git /opt/dev/netmngr + exec_cmd git clone -b devel https://dev.iopsys.eu/network/netmngr.git /opt/dev/netmngr + + exec_cmd apt install iproute2 -y exec_cmd make -C /opt/dev/netmngr/src/ clean exec_cmd make -C /opt/dev/netmngr/src/ NETMNGR_GRE_OBJ=y NETMNGR_IP_OBJ=y NETMNGR_ROUTING_OBJ=y NETMNGR_PPP_OBJ=y NETMNGR_ROUTER_ADVERTISEMENT_OBJ=y NETMNGR_IPV6RD_OBJ=y - exec_cmd cp -f /opt/dev/netmngr/src/libnetmngr.so /usr/share/bbfdm/micro_services/netmngr.so - exec_cmd cp -f /opt/dev/netmngr/src/libinterface_stack.so /usr/share/bbfdm/plugins - exec_cmd mkdir -p /usr/share/bbfdm/micro_services/netmngr - - generate_input_schema_with_output_name "netmngr" "Network" > /etc/bbfdm/services/netmngr.json + install_ms /opt/dev/netmngr/src/libnetmngr.so netmngr exec_cmd git clone https://dev.iopsys.eu/bbf/tr143d.git /opt/dev/tr143d exec_cmd make -C /opt/dev/tr143d/src/ clean && make -C /opt/dev/tr143d/src/ - exec_cmd cp -f /opt/dev/tr143d/src/libtr143d.so /usr/share/bbfdm/micro_services/netmngr + exec_cmd cp -f utilities/files/usr/share/bbfdm/scripts/bbf_api /usr/share/bbfdm/scripts/ + exec_cmd cp -rf /opt/dev/tr143d/scripts/* /usr/share/bbfdm/scripts/ + install_ms_plugin /opt/dev/tr143d/src/libtr143d.so netmngr exec_cmd git clone https://dev.iopsys.eu/bbf/tr471d.git /opt/dev/tr471d exec_cmd make -C /opt/dev/tr471d/src/ clean && make -C /opt/dev/tr471d/src/ - exec_cmd cp -f /opt/dev/tr471d/src/libtr471d.so /usr/share/bbfdm/micro_services/netmngr + install_ms_plugin /opt/dev/tr471d/src/libtr471d.so netmngr exec_cmd git clone https://dev.iopsys.eu/bbf/twamp-light.git /opt/dev/twamp exec_cmd make -C /opt/dev/twamp clean && make -C /opt/dev/twamp - exec_cmd cp -f /opt/dev/twamp/libtwamp.so /usr/share/bbfdm/micro_services/netmngr + install_ms_plugin /opt/dev/twamp/libtwamp.so netmngr exec_cmd git clone https://dev.iopsys.eu/bbf/udpecho.git /opt/dev/udpecho exec_cmd make -C /opt/dev/udpecho/src/ clean && make -C /opt/dev/udpecho/src/ - exec_cmd cp -f /opt/dev/udpecho/src/libudpechoserver.so /usr/share/bbfdm/micro_services/netmngr + install_ms_plugin /opt/dev/udpecho/src/libudpechoserver.so netmngr } function install_sysmngr_as_micro_service() { [ -d "/opt/dev/sysmngr" ] && return 0 - exec_cmd git clone https://dev.iopsys.eu/system/sysmngr.git /opt/dev/sysmngr + exec_cmd git clone -b devel https://dev.iopsys.eu/system/sysmngr.git /opt/dev/sysmngr exec_cmd make -C /opt/dev/sysmngr/src/ clean && \ exec_cmd make -C /opt/dev/sysmngr/src/ \ @@ -225,7 +195,7 @@ function install_sysmngr_as_micro_service() SYSMNGR_VENDOR_EXTENSIONS='y' \ SYSMNGR_FWBANK_UBUS_SUPPORT='y' - exec_cmd cp /opt/dev/sysmngr/src/sysmngr /usr/sbin/ + exec_cmd cp -f /opt/dev/sysmngr/src/sysmngr /usr/sbin/ exec_cmd mkdir /etc/sysmngr } diff --git a/gitlab-ci/tools-test.sh b/gitlab-ci/tools-test.sh index 6672bf94..8223cbbc 100755 --- a/gitlab-ci/tools-test.sh +++ b/gitlab-ci/tools-test.sh @@ -19,7 +19,7 @@ echo "Validate BBF Data Model JSON Plugin" check_ret $? echo "Validating plugins" -for plugin in $(ls -1 test/files/usr/share/bbfdm/plugins/*); do +for plugin in $(ls -1 test/files/usr/share/bbfdm/micro_services/core/*); do echo "Validating ${plugin} JSON Plugin" ./tools/validate_json_plugin.py ${plugin} check_ret $? diff --git a/libbbfdm-api/legacy/dmapi.c b/libbbfdm-api/legacy/dmapi.c index a419481d..3eeb4e45 100644 --- a/libbbfdm-api/legacy/dmapi.c +++ b/libbbfdm-api/legacy/dmapi.c @@ -222,6 +222,22 @@ int bbf_set_alias(struct dmctx *ctx, struct uci_section *s, const char *option_n return 0; } +static void send_linker_request_event(struct ubus_context *ctx, const char *path) +{ + struct blob_buf bb; + + if (DM_STRLEN(path) == 0) + return; + + memset(&bb, 0, sizeof(struct blob_buf)); + blob_buf_init(&bb, 0); + + blobmsg_add_string(&bb, "path", path); + + ubus_send_event(ctx, "bbfdm.linker.request", bb.head); + blob_buf_free(&bb); +} + int bbfdm_get_references(struct dmctx *ctx, int match_action, const char *base_path, const char *key_name, char *key_value, char *out, size_t out_len) { char param_path[1024] = {0}; @@ -261,20 +277,20 @@ int bbfdm_get_references(struct dmctx *ctx, int match_action, const char *base_p } snprintf(&out[len], out_len - len, "%s%s", len ? (match_action == MATCH_FIRST ? "," : ";") : "", value); - goto end; + return 0; } - if (dm_is_micro_service() == true) { // It's a micro-service instance - - if (out_len - len < strlen(base_path) + strlen(key_name) + strlen(key_value) + 9) { // 9 = '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(&out[len], out_len - len, "%s%s[%s==\"%s\"].", len ? (match_action == MATCH_FIRST ? "," : ";") : "", base_path, key_name, key_value); + if (out_len - len < strlen(base_path) + strlen(key_name) + strlen(key_value) + 9) { // 9 = 'path[key_name==\"key_value\"].' + BBF_ERR("Buffer overflow detected. The output buffer is not large enough to hold the additional data!!!"); + return -1; } -end: + snprintf(param_path, sizeof(param_path), "%s[%s==\"%s\"].", base_path, key_name, key_value); + + send_linker_request_event(ctx->ubus_ctx, param_path); + + snprintf(&out[len], out_len - len, "%s%s", len ? (match_action == MATCH_FIRST ? "," : ";") : "", param_path); + return 0; } @@ -317,68 +333,6 @@ int bbfdm_get_reference_linker(struct dmctx *ctx, char *reference_path, struct d return 0; } -static char *bbfdm_get_reference_value(const char *reference_path) -{ - unsigned int reference_path_dot_num = count_occurrences(reference_path, '.'); - json_object *res = NULL; - - json_object *in_args = json_object_new_object(); - json_object_object_add(in_args, "proto", json_object_new_string("usp")); - json_object_object_add(in_args, "format", json_object_new_string("raw")); - - dmubus_call("bbfdm", "get", - UBUS_ARGS{ - {"path", reference_path, String}, - {"optional", json_object_to_json_string(in_args), Table} - }, - 2, &res); - - json_object_put(in_args); - - if (!res) - return NULL; - - json_object *res_array = dmjson_get_obj(res, 1, "results"); - if (!res_array) - return NULL; - - size_t nbre_obj = json_object_array_length(res_array); - if (nbre_obj == 0) - return NULL; - - for (size_t i = 0; i < nbre_obj; i++) { - json_object *res_obj = json_object_array_get_idx(res_array, i); - - char *fault = dmjson_get_value(res_obj, 1, "fault"); - if (DM_STRLEN(fault)) - return NULL; - - char *path = dmjson_get_value(res_obj, 1, "path"); - - unsigned int path_dot_num = count_occurrences(path, '.'); - if (path_dot_num > reference_path_dot_num) - continue; - - 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_LSTRCMP(flag, "Linker") == 0) { - char *data = dmjson_get_value(res_obj, 1, "data"); - return data ? dmstrdup(data) : ""; - } - } - } - } - - return NULL; -} - int bbfdm_operate_reference_linker(struct dmctx *ctx, const char *reference_path, char **reference_value) { if (!ctx) { @@ -401,8 +355,5 @@ int bbfdm_operate_reference_linker(struct dmctx *ctx, const char *reference_path if (DM_STRLEN(*reference_value) != 0) return 0; - if (dm_is_micro_service() == true) // It's a micro-service instance - *reference_value = bbfdm_get_reference_value(reference_path); - return 0; } diff --git a/libbbfdm-api/legacy/dmapi.h b/libbbfdm-api/legacy/dmapi.h index 36c8e092..f2a4d7ea 100644 --- a/libbbfdm-api/legacy/dmapi.h +++ b/libbbfdm-api/legacy/dmapi.h @@ -28,6 +28,8 @@ #include "libbbfdm-api/version-2/bbfdm_api.h" +#define ROOT_NODE "Device." + extern struct dm_permession_s DMREAD; extern struct dm_permession_s DMWRITE; extern struct dm_permession_s DMSYNC; @@ -177,21 +179,12 @@ struct dmctx { bool iscommand; bool isevent; bool isinfo; - bool disable_mservice_browse; int (*method_param)(DMPARAM_ARGS); int (*method_obj)(DMOBJECT_ARGS); int (*checkobj)(DMOBJECT_ARGS); int (*checkleaf)(DMOBJECT_ARGS); - struct list_head *memhead; - struct blob_buf bb; - - DMOBJ *dm_entryobj; - struct uci_context *config_uci_ctx; - struct uci_context *dmmap_uci_ctx; - struct uci_context *varstate_uci_ctx; - int faultcode; int setaction; unsigned int dm_type; @@ -204,6 +197,16 @@ struct dmctx { char *addobj_instance; char *linker; char *linker_param; + + struct blob_buf bb; + + DMOBJ *dm_entryobj; + struct uci_context *config_uci_ctx; + struct uci_context *dmmap_uci_ctx; + struct uci_context *varstate_uci_ctx; + struct ubus_context *ubus_ctx; + struct list_head *memhead; + char *inst_buf[16]; char fault_msg[256]; }; @@ -220,7 +223,6 @@ typedef struct dmnode { unsigned char browse_type; int max_instance; int num_of_entries; - bool is_ubus_service; } DMNODE; typedef struct { @@ -387,7 +389,6 @@ enum bbfdm_type_enum { enum { INDX_JSON_MOUNT, INDX_LIBRARY_MOUNT, - INDX_SERVICE_MOUNT, __INDX_DYNAMIC_MAX }; diff --git a/libbbfdm-api/legacy/dmbbf.c b/libbbfdm-api/legacy/dmbbf.c index 15f1b736..7708e99e 100644 --- a/libbbfdm-api/legacy/dmbbf.c +++ b/libbbfdm-api/legacy/dmbbf.c @@ -18,9 +18,6 @@ #include "dmbbf.h" #define MAX_DM_PATH (1024) -#define SEPARATOR_LIST_VALUES ";" - -static bool is_micro_service = false; char *DMT_TYPE[] = { [DMT_STRING] = "xsd:string", @@ -41,16 +38,6 @@ struct dm_permession_s DMWRITE = {"1", NULL}; struct dm_permession_s DMSYNC = {"sync", NULL}; struct dm_permession_s DMASYNC = {"async", NULL}; -bool dm_is_micro_service(void) -{ - return is_micro_service; -} - -void dm_set_micro_service(void) -{ - is_micro_service = true; -} - static int dm_browse(struct dmctx *dmctx, DMNODE *parent_node, DMOBJ *entryobj, void *data, char *instance); static bool is_instance_number_alias(char **str) @@ -200,6 +187,15 @@ static int plugin_leaf_onlyobj_match(DMOBJECT_ARGS) static int plugin_obj_nextlevel_match(DMOBJECT_ARGS) { + if (DM_STRCMP(dmctx->in_param, "Device") == 0 && DM_STRCMP(dmctx->in_value, "core") != 0) + return FAULT_9005; + + unsigned int current_object_dot_num = count_occurrences(node->current_object, '.'); + unsigned int in_path_dot_num = count_occurrences(dmctx->in_param, '.'); + + if (current_object_dot_num > in_path_dot_num + 1) + return FAULT_9005; + if (node->matched > 1) return FAULT_9005; @@ -272,6 +268,15 @@ static int plugin_leaf_wildcard_match(DMOBJECT_ARGS) static int plugin_obj_wildcard_nextlevel_match(DMOBJECT_ARGS) { + if (DM_STRCMP(dmctx->in_param, "Device") == 0 && DM_STRCMP(dmctx->in_value, "core") != 0) + return FAULT_9005; + + unsigned int current_object_dot_num = count_occurrences(node->current_object, '.'); + unsigned int in_path_dot_num = count_occurrences(dmctx->in_param, '.'); + + if (current_object_dot_num > in_path_dot_num + 1) + return FAULT_9005; + if (node->matched > 1) return FAULT_9005; @@ -412,32 +417,6 @@ static int dm_browse_leaf(struct dmctx *dmctx, DMNODE *parent_node, DMLEAF *leaf return err; } -static void dm_browse_service(struct dmctx *dmctx, DMNODE *parent_node, DMOBJ *entryobj, void *data, char *instance, char *parent_obj, int *err) -{ - DMNODE node = {0}; - - node.obj = entryobj; - node.parent = parent_node; - node.is_ubus_service = true; - - if (dmctx->disable_mservice_browse == true) - return; - - dmasprintf(&(node.current_object), "%s%s.", parent_obj, entryobj->obj); - - if (dmctx->checkobj) { - *err = dmctx->checkobj(dmctx, &node, NULL, NULL, NULL, NULL, data, instance); - if (*err) - return; - } - - *err = dmctx->method_obj(dmctx, &node, NULL, NULL, NULL, NULL, data, instance); - if (dmctx->stop) - return; - - *err = dmctx->method_param(dmctx, &node, NULL, data, instance); -} - static void dm_browse_entry(struct dmctx *dmctx, DMNODE *parent_node, DMOBJ *entryobj, void *data, char *instance, char *parent_obj, int *err) { DMNODE node = {0}; @@ -524,10 +503,7 @@ static int dm_browse(struct dmctx *dmctx, DMNODE *parent_node, DMOBJ *entryobj, for (int j = 0; next_dyn_array->nextobj[j]; j++) { DMOBJ *jentryobj = next_dyn_array->nextobj[j]; for (; (jentryobj && jentryobj->obj); jentryobj++) { - if (i == INDX_SERVICE_MOUNT) - dm_browse_service(dmctx, parent_node, jentryobj, data, instance, parent_obj, &err); - else - dm_browse_entry(dmctx, parent_node, jentryobj, data, instance, parent_obj, &err); + dm_browse_entry(dmctx, parent_node, jentryobj, data, instance, parent_obj, &err); if (dmctx->stop) return err; } @@ -686,18 +662,18 @@ static void bb_add_flags_arr(struct blob_buf *bb, uint32_t dm_flags) if (!bb || !dm_flags) return; - void *flags_arr = blobmsg_open_array(bb, "flags"); + //void *flags_arr = blobmsg_open_array(bb, "flags"); if (dm_flags & DM_FLAG_REFERENCE) - blobmsg_add_string(bb, NULL, "Reference"); - if (dm_flags & DM_FLAG_UNIQUE) + blobmsg_add_u8(bb, "reference", true); + /*if (dm_flags & DM_FLAG_UNIQUE) blobmsg_add_string(bb, NULL, "Unique"); if (dm_flags & DM_FLAG_LINKER) blobmsg_add_string(bb, NULL, "Linker"); if (dm_flags & DM_FLAG_SECURE) - blobmsg_add_string(bb, NULL, "Secure"); + blobmsg_add_string(bb, NULL, "Secure");*/ - blobmsg_close_array(bb, flags_arr); + //blobmsg_close_array(bb, flags_arr); } void fill_blob_param(struct blob_buf *bb, const char *path, const char *data, const char *type, uint32_t dm_flags) @@ -827,78 +803,6 @@ static int is64digit(char c) return 0; } -char *get_value_by_reference(struct dmctx *ctx, char *value) -{ - if (dm_is_micro_service() == true) // It's a micro-service instance - return value; - - char *pch = NULL, *spch = NULL; - char buf[MAX_DM_PATH * 4] = {0}; - char buf_val[MAX_DM_PATH * 4] = {0}; - bool is_list = false; - int pos = 0; - - if (DM_STRLEN(value) == 0) - return value; - - DM_STRNCPY(buf, value, sizeof(buf)); - - if (DM_STRCHR(buf, ';')) - is_list = true; - - buf_val[0] = 0; - - for (pch = strtok_r(buf, is_list ? SEPARATOR_LIST_VALUES : ",", &spch); pch; pch = strtok_r(NULL, is_list ? SEPARATOR_LIST_VALUES : ",", &spch)) { - char *val = NULL; - - if (DM_LSTRSTR(pch, "==")) { - 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) - continue; - - snprintf(path, pmatch[0].rm_so + 1, "%s", pch); - int len = DM_STRLEN(path); - if (!len) - continue; - - 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; - } - - snprintf(path + len, sizeof(path) - len, "*.%s", key_name); - - adm_entry_get_reference_param(ctx, path, key_value, &val); - } else { - val = pch; - } - - if (DM_STRLEN(val)) { - pos += snprintf(&buf_val[pos], sizeof(buf_val) - pos, "%s,", val); - - if (!is_list) // Requested value is not list - break; - } - } - - if (DM_STRLEN(buf_val)) { - buf_val[pos - 1] = 0; - return dmstrdup(buf_val); - } - - return ""; -} - static char *check_value_by_type(const char *param_name, char *value, int type) { int i = 0, len = DM_STRLEN(value); @@ -983,788 +887,93 @@ static char *get_default_value_by_type(const char *param_name, int type) } } -static void get_reference_paramater_value(struct dmctx *dmctx, char *in_value, char *str, size_t size) +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) { char *pch = NULL, *pchr = NULL; char buf[2048] = {0}; - unsigned int pos = 0; - if (!in_value || !str || !size) - return; + if (!curr_value || !in_value || !out || !out_len) + return false; - memset(str, 0, size); + if (strcmp(curr_value, in_value) == 0) + return true; if (DM_STRLEN(in_value) == 0) { - DM_STRNCPY(str, "=>", size); - return; + DM_STRNCPY(out, "=>", sizeof(out_len)); + return false; } - DM_STRNCPY(buf, in_value, sizeof(buf)); + DM_STRNCPY(buf, curr_value, sizeof(buf)); for (pch = strtok_r(buf, ",", &pchr); pch != NULL; pch = strtok_r(NULL, ",", &pchr)) { - uint32_t len = DM_STRLEN(pch); - char *linker = NULL; - if (len && pch[len - 1] == '.') - pch[len - 1] = 0; + 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]; - adm_entry_get_reference_value(dmctx, pch, &linker); - - pos += snprintf((char *)str + pos, size - pos, "%s=>%s%s,", pch, linker ? linker : "", linker ? "##" : ""); - } - - if (pos) - str[pos - 1] = 0; -} - -static struct blob_attr *get_results_array(struct blob_attr *msg) -{ - struct blob_attr *tb[1] = {0}; - const struct blobmsg_policy p[1] = { - { "results", BLOBMSG_TYPE_ARRAY } - }; - - if (msg == NULL) - return NULL; - - blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg)); - - return tb[0]; -} - -static void prepare_optional_table(struct dmctx *dmctx, struct blob_buf *bb) -{ - void *table = blobmsg_open_table(bb, "optional"); - blobmsg_add_string(bb, "proto", (dmctx->dm_type == BBFDM_BOTH) ? "both" : (dmctx->dm_type == BBFDM_CWMP) ? "cwmp" : "usp"); - blobmsg_add_string(bb, "format", "raw"); - blobmsg_close_table(bb, table); -} - -typedef void (*ms_ubus_cb)(struct ubus_request *req, int type, struct blob_attr *msg); - -static int ubus_call_blob_msg(const char *obj, const char *method, struct blob_buf *blob, int timeout, ms_ubus_cb ms_callback, void *callback_arg) -{ - struct ubus_context *ubus_ctx = NULL; - uint32_t id; - int rc = -1; - - ubus_ctx = ubus_connect(NULL); - if (ubus_ctx == NULL) { - BBF_ERR("UBUS context is null"); - return -1; - } - - if (ubus_lookup_id(ubus_ctx, obj, &id)) { - BBF_ERR("Failed to lookup UBUS object ID for '%s' using method '%s'", obj, method); - ubus_free(ubus_ctx); - return -1; - } - - rc = ubus_invoke(ubus_ctx, id, method, blob->head, ms_callback, callback_arg, timeout); - - if (ubus_ctx) { - ubus_free(ubus_ctx); - ubus_ctx = NULL; - } - - return rc; -} - -static uint32_t get_dm_flags(struct blob_attr *flags_arr) -{ - struct blob_attr *flag = NULL; - uint32_t dm_flags = 0; - int rem = 0; - - if (!flags_arr) - return 0; - - blobmsg_for_each_attr(flag, flags_arr, rem) { - char *flag_str = blobmsg_get_string(flag); - if (DM_LSTRCMP(flag_str, "Reference") == 0) - dm_flags |= DM_FLAG_REFERENCE; - if (DM_LSTRCMP(flag_str, "Unique") == 0) - dm_flags |= DM_FLAG_UNIQUE; - if (DM_LSTRCMP(flag_str, "Linker") == 0) - dm_flags |= DM_FLAG_LINKER; - if (DM_LSTRCMP(flag_str, "Secure") == 0) - dm_flags |= DM_FLAG_SECURE; - } - - return dm_flags; -} - -static void __get_ubus_value(struct ubus_request *req, int type, struct blob_attr *msg) -{ - struct blob_attr *cur = NULL; - int rem = 0; - - if (!msg || !req) - return; - - struct dmctx *dmctx = (struct dmctx *)req->priv; - - struct blob_attr *parameters = get_results_array(msg); - if (parameters == NULL) { - dmctx->faultcode = FAULT_9005; - return; - } - - int array_len = blobmsg_len(parameters); - if (array_len == 0) { - dmctx->findparam = 1; - return; - } - - blobmsg_for_each_attr(cur, parameters, rem) { - struct blob_attr *tb[5] = {0}; - const struct blobmsg_policy p[5] = { - { "path", BLOBMSG_TYPE_STRING }, - { "data", BLOBMSG_TYPE_STRING }, - { "type", BLOBMSG_TYPE_STRING }, - { "flags", BLOBMSG_TYPE_ARRAY }, - { "fault", BLOBMSG_TYPE_INT32 } - }; - - blobmsg_parse(p, 5, tb, blobmsg_data(cur), blobmsg_len(cur)); - - if (tb[4]) { - int fault = blobmsg_get_u32(tb[4]); - dmctx->faultcode = fault; - return; - } else { - dmctx->faultcode = 0; - } - - dmctx->findparam = 1; - - uint32_t dm_flags = get_dm_flags(tb[3]); - - bool is_reference = dm_flags & DM_FLAG_REFERENCE; - - if (is_reference) { - char *dm_path = (tb[0]) ? blobmsg_get_string(tb[0]) : ""; - char *dm_data = (tb[1]) ? get_value_by_reference(dmctx, blobmsg_get_string(tb[1])) : ""; - char *dm_type = (tb[2]) ? blobmsg_get_string(tb[2]) : ""; - - fill_blob_param(&dmctx->bb, dm_path, dm_data, dm_type, dm_flags); - } else { - blobmsg_add_blob(&dmctx->bb, cur); - } - } -} - -static int get_ubus_value(struct dmctx *dmctx, struct dmnode *node) -{ - char *ubus_name = node->obj->checkdep; - char *in_path = (dmctx->in_param[0] == '\0' || rootcmp(dmctx->in_param, "Device") == 0) ? node->current_object : dmctx->in_param; - struct blob_buf blob = {0}; - int timeout = 5000; - - if ((dm_is_micro_service() == false) && ((dmctx->dm_type & node->obj->bbfdm_type) == false)) { - BBF_DEBUG("[%s] Ignore unsupported proto objects [%s], in[%d], datamodel[%d]", __func__, ubus_name, dmctx->dm_type, node->obj->bbfdm_type); - return 0; - } - - if (node->obj->bbfdm_type == BBFDM_CWMP) { - timeout = 10000; - } - - memset(&blob, 0, sizeof(struct blob_buf)); - blob_buf_init(&blob, 0); - - blobmsg_add_string(&blob, "path", in_path); - prepare_optional_table(dmctx, &blob); - - int res = ubus_call_blob_msg(ubus_name, "get", &blob, timeout, __get_ubus_value, dmctx); - - blob_buf_free(&blob); - - if (res) - return FAULT_9005; - - if (dmctx->faultcode) - return dmctx->faultcode; - - return 0; -} - -static void __get_ubus_supported_dm(struct ubus_request *req, int type, struct blob_attr *msg) -{ - struct blob_attr *cur = NULL; - int rem = 0; - - if (!msg || !req) - return; - - struct dmctx *dmctx = (struct dmctx *)req->priv; - - struct blob_attr *parameters = get_results_array(msg); - if (parameters == NULL) - return; - - int array_len = blobmsg_len(parameters); - if (array_len == 0) { - dmctx->findparam = 1; - return; - } - - blobmsg_for_each_attr(cur, parameters, rem) { - struct blob_attr *tb[1] = {0}; - const struct blobmsg_policy p[1] = { - { "fault", BLOBMSG_TYPE_INT32 } - }; - - blobmsg_parse(p, 1, tb, blobmsg_data(cur), blobmsg_len(cur)); - - if (tb[0]) - continue; - - dmctx->findparam = 1; - blobmsg_add_blob(&dmctx->bb, cur); - } -} - -static int get_ubus_supported_dm(struct dmctx *dmctx, struct dmnode *node) -{ - char *ubus_name = node->obj->checkdep; - char *in_path = (dmctx->in_param[0] == '\0' || rootcmp(dmctx->in_param, "Device") == 0) ? node->current_object : dmctx->in_param; - struct blob_buf blob = {0}; - - if ((dm_is_micro_service() == false) && ((dmctx->dm_type & node->obj->bbfdm_type) == false)) { - BBF_DEBUG("[%s] Ignore unsupported proto objects [%s], in[%d], datamodel[%d]", __func__, ubus_name, dmctx->dm_type, node->obj->bbfdm_type); - return 0; - } - - memset(&blob, 0, sizeof(struct blob_buf)); - blob_buf_init(&blob, 0); - - blobmsg_add_string(&blob, "path", in_path); - blobmsg_add_u8(&blob, "first_level", dmctx->nextlevel); - prepare_optional_table(dmctx, &blob); - - ubus_call_blob_msg(ubus_name, "schema", &blob, 5000, __get_ubus_supported_dm, dmctx); - - blob_buf_free(&blob); - - return 0; -} - -static void __get_ubus_instances(struct ubus_request *req, int type, struct blob_attr *msg) -{ - struct blob_attr *cur = NULL; - int rem = 0; - - if (!msg || !req) - return; - - struct dmctx *dmctx = (struct dmctx *)req->priv; - - struct blob_attr *parameters = get_results_array(msg); - if (parameters == NULL) { - dmctx->faultcode = FAULT_9005; - return; - } - - int array_len = blobmsg_len(parameters); - if (array_len == 0) { - dmctx->findparam = 1; - return; - } - - blobmsg_for_each_attr(cur, parameters, rem) { - struct blob_attr *tb[1] = {0}; - const struct blobmsg_policy p[1] = { - { "fault", BLOBMSG_TYPE_INT32 } - }; - - blobmsg_parse(p, 1, tb, blobmsg_data(cur), blobmsg_len(cur)); - - if (tb[0]) { - int fault = blobmsg_get_u32(tb[0]); - dmctx->faultcode = fault; - return; - } else { - dmctx->faultcode = 0; - } - - dmctx->findparam = 1; - blobmsg_add_blob(&dmctx->bb, cur); - } -} - -static int get_ubus_instances(struct dmctx *dmctx, struct dmnode *node) -{ - char *ubus_name = node->obj->checkdep; - struct blob_buf blob = {0}; - - if ((dm_is_micro_service() == false) && ((dmctx->dm_type & node->obj->bbfdm_type) == false)) { - BBF_DEBUG("[%s] Ignore unsupported proto objects [%s], in[%d], datamodel[%d]", __func__, ubus_name, dmctx->dm_type, node->obj->bbfdm_type); - return 0; - } - - memset(&blob, 0, sizeof(struct blob_buf)); - blob_buf_init(&blob, 0); - - blobmsg_add_string(&blob, "path", dmctx->in_param); - blobmsg_add_u8(&blob, "first_level", dmctx->nextlevel); - prepare_optional_table(dmctx, &blob); - - int res = ubus_call_blob_msg(ubus_name, "instances", &blob, 5000, __get_ubus_instances, dmctx); - - blob_buf_free(&blob); - - if (res) - return FAULT_9005; - - if (dmctx->faultcode) - return dmctx->faultcode; - - return 0; -} - -static int add_ubus_object(struct dmctx *dmctx, struct dmnode *node) -{ - json_object *res = NULL, *res_obj = NULL; - char *ubus_name = node->obj->checkdep; - - if ((dm_is_micro_service() == false) && ((dmctx->dm_type & node->obj->bbfdm_type) == false)) { - BBF_DEBUG("[%s] Ignore unsupported proto objects [%s], in[%d], datamodel[%d]", __func__, ubus_name, dmctx->dm_type, node->obj->bbfdm_type); - return 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, "format", json_object_new_string("raw")); - - dmubus_call(ubus_name, "add", - UBUS_ARGS{ - {"path", dmctx->in_param, String}, - {"optional", json_object_to_json_string(in_args), Table} - }, - 2, &res); - json_object_put(in_args); - - if (!res) - return FAULT_9005; - - json_object *res_array = dmjson_get_obj(res, 1, "results"); - if (!res_array) - return FAULT_9005; - - size_t nbre_obj = json_object_array_length(res_array); - - for (size_t i = 0; i < nbre_obj; i++) { - res_obj = json_object_array_get_idx(res_array, i); - - char *fault = dmjson_get_value(res_obj, 1, "fault"); - if (DM_STRLEN(fault)) { - char *fault_msg = dmjson_get_value(res_obj, 1, "fault_msg"); - bbfdm_set_fault_message(dmctx, "%s", fault_msg); - return DM_STRTOUL(fault); - } - - char *data = dmjson_get_value(res_obj, 1, "data"); - - dmctx->stop = 1; - dmctx->addobj_instance = dmstrdup(data); - } - - return 0; -} - -static int del_ubus_object(struct dmctx *dmctx, struct dmnode *node) -{ - json_object *res = NULL, *res_obj = NULL; - char *ubus_name = node->obj->checkdep; - - if ((dm_is_micro_service() == false) && ((dmctx->dm_type & node->obj->bbfdm_type) == false)) { - BBF_DEBUG("[%s] Ignore unsupported proto objects [%s], in[%d], datamodel[%d]", __func__, ubus_name, dmctx->dm_type, node->obj->bbfdm_type); - return 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, "format", json_object_new_string("raw")); - - dmubus_call(ubus_name, "del", - UBUS_ARGS{ - {"path", dmctx->in_param, String}, - {"optional", json_object_to_json_string(in_args), Table} - }, - 2, &res); - json_object_put(in_args); - - if (!res) - return FAULT_9005; - - json_object *res_array = dmjson_get_obj(res, 1, "results"); - if (!res_array) - return FAULT_9005; - - size_t nbre_obj = json_object_array_length(res_array); - - for (size_t i = 0; i < nbre_obj; i++) { - res_obj = json_object_array_get_idx(res_array, i); - - dmctx->stop = 1; - - char *fault = dmjson_get_value(res_obj, 1, "fault"); - if (DM_STRLEN(fault)) { - char *fault_msg = dmjson_get_value(res_obj, 1, "fault_msg"); - bbfdm_set_fault_message(dmctx, "%s", fault_msg); - return DM_STRTOUL(fault); - } - } - - return 0; -} - -static bool is_reference_parameter(char *ubus_name, char *param_name, json_object *in_args, char **value) -{ - 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; - - *value = dmjson_get_value(res_obj, 1, "data"); - - char *flags_list = dmjson_get_value_array_all(res_obj, ",", 1, "flags"); - - return DM_LSTRSTR(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[2048] = {0}; - char *ref_value = dmstrdup(""); - - if ((dm_is_micro_service() == false) && ((dmctx->dm_type & node->obj->bbfdm_type) == false)) { - BBF_DEBUG("[%s] Ignore unsupported proto objects [%s], in[%d], datamodel[%d]", __func__, ubus_name, dmctx->dm_type, node->obj->bbfdm_type); - return 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, "format", json_object_new_string("raw")); - - if (is_reference_parameter(ubus_name, dmctx->in_param, in_args, &ref_value)) { - ref_value = get_value_by_reference(dmctx, ref_value); - - if (DM_STRCMP(ref_value, dmctx->in_value) == 0) { - BBF_DEBUG("Requested reference value (%s) is same as current reference value (%s)", dmctx->in_value, ref_value); - dmctx->stop = 1; - return 0; - } - - get_reference_paramater_value(dmctx, dmctx->in_value, param_value, sizeof(param_value)); - } else { - snprintf(param_value, sizeof(param_value), "%s", dmctx->in_value); - } - - dmubus_call(ubus_name, "set", - UBUS_ARGS{ - {"path", dmctx->in_param, String}, - {"value", param_value, String}, - {"datatype", dmctx->in_type ? dmctx->in_type : "", String}, - {"optional", json_object_to_json_string(in_args), Table} - }, - 4, &res); - json_object_put(in_args); - - if (!res) - return FAULT_9005; - - json_object *res_array = dmjson_get_obj(res, 1, "results"); - if (!res_array) - return FAULT_9005; - - size_t nbre_obj = json_object_array_length(res_array); - - for (size_t i = 0; i < nbre_obj; i++) { - res_obj = json_object_array_get_idx(res_array, i); - - char *fault = dmjson_get_value(res_obj, 1, "fault"); - - if (DM_STRLEN(fault) == 0 || (DM_STRTOUL(fault) != FAULT_9005 && DM_STRTOUL(fault) != USP_FAULT_INVALID_PATH)) - dmctx->stop = 1; - - if (DM_STRLEN(fault)) { - char *fault_msg = dmjson_get_value(res_obj, 1, "fault_msg"); - bbfdm_set_fault_message(dmctx, "%s", fault_msg); - return DM_STRTOUL(fault); - } - } - - return 0; -} - -static void __get_ubus_name(struct ubus_request *req, int type, struct blob_attr *msg) -{ - struct blob_attr *cur = NULL; - int rem = 0, idx = 0; - - if (!msg || !req) - return; - - struct dmctx *dmctx = (struct dmctx *)req->priv; - unsigned int in_path_dot_num = count_occurrences(dmctx->in_param, '.'); - - struct blob_attr *parameters = get_results_array(msg); - if (parameters == NULL) - return; - - int array_len = blobmsg_len(parameters); - if (array_len == 0) { - dmctx->findparam = 1; - return; - } - - blobmsg_for_each_attr(cur, parameters, rem) { - struct blob_attr *tb[2] = {0}; - const struct blobmsg_policy p[2] = { - { "path", BLOBMSG_TYPE_STRING }, - { "fault", BLOBMSG_TYPE_INT32 } - }; - - blobmsg_parse(p, 2, tb, blobmsg_data(cur), blobmsg_len(cur)); - - if (tb[1]) { - dmctx->faultcode = blobmsg_get_u32(tb[1]); - return; - } else { - dmctx->faultcode = 0; - } - - dmctx->findparam = 1; - - if (idx == 0 && dmctx->nextlevel && (count_occurrences(dmctx->in_value, '.') == in_path_dot_num + 1)) { - fill_blob_param(&dmctx->bb, dmctx->in_value, "0", "xsd:object", 0); - idx++; - } - - if (dmctx->nextlevel) { - char *path = tb[0] ? blobmsg_get_string(tb[0]) : ""; - unsigned int path_dot_num = count_occurrences(path, '.'); - size_t len = DM_STRLEN(path); - - if ((path[len - 1] == '.' && path_dot_num > in_path_dot_num + 1) || - (path[len - 1] != '.' && path_dot_num > in_path_dot_num)) + if (!match(pch, "\\[(.*?)\\]", 2, pmatch)) continue; - } - blobmsg_add_blob(&dmctx->bb, cur); - } -} + snprintf(path, pmatch[0].rm_so + 1, "%s", pch); + int len = DM_STRLEN(path); + if (!len) + continue; -static int get_ubus_name(struct dmctx *dmctx, struct dmnode *node) -{ - char *in_path = (dmctx->in_param[0] == '\0' || rootcmp(dmctx->in_param, "Device") == 0) ? node->current_object : dmctx->in_param; - char *ubus_name = node->obj->checkdep; - dmctx->in_value = node->current_object; - struct blob_buf blob = {0}; - int timeout = 5000; + char *match_str = pch + pmatch[1].rm_so; + if (DM_STRLEN(match_str) == 0) + continue; - if ((dm_is_micro_service() == false) && ((dmctx->dm_type & node->obj->bbfdm_type) == false)) { - BBF_DEBUG("[%s] Ignore unsupported proto objects [%s], in[%d], datamodel[%d]", __func__, ubus_name, dmctx->dm_type, node->obj->bbfdm_type); - return 0; - } + 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; + } - if (node->obj->bbfdm_type == BBFDM_CWMP) { - timeout = 10000; - } + char *tag = strstr(in_value, "=>"); + if (!tag) + continue; - memset(&blob, 0, sizeof(struct blob_buf)); - blob_buf_init(&blob, 0); + convert_to_regex(path, regex_pattern); - blobmsg_add_string(&blob, "path", in_path); - blobmsg_add_u8(&blob, "first_level", dmctx->nextlevel); - prepare_optional_table(dmctx, &blob); - - int res = ubus_call_blob_msg(ubus_name, "schema", &blob, timeout, __get_ubus_name, dmctx); - - blob_buf_free(&blob); - - if (res) - return FAULT_9005; - - if (dmctx->faultcode) - return dmctx->faultcode; - - return 0; -} - -static void __operate_ubus(struct ubus_request *req, int type, struct blob_attr *msg) -{ - struct blob_attr *cur = NULL; - int rem = 0; - - if (!msg || !req) - return; - - struct dmctx *dmctx = (struct dmctx *)req->priv; - - struct blob_attr *parameters = get_results_array(msg); - if (parameters == NULL) { - dmctx->faultcode = USP_FAULT_INVALID_PATH; - return; - } - - int array_len = blobmsg_len(parameters); - if (array_len == 0) { - dmctx->findparam = 1; - return; - } - - blobmsg_for_each_attr(cur, parameters, rem) { - struct blob_attr *tb[3] = {0}; - const struct blobmsg_policy p[3] = { - { "fault", BLOBMSG_TYPE_INT32 }, - { "fault_msg", BLOBMSG_TYPE_STRING }, - { "output", BLOBMSG_TYPE_ARRAY } - }; - - blobmsg_parse(p, 3, tb, blobmsg_data(cur), blobmsg_len(cur)); - - uint32_t fault = tb[0] ? blobmsg_get_u32(tb[0]) : 0; - - if (fault == 0 || (fault != FAULT_9005 && fault != USP_FAULT_INVALID_PATH)) - dmctx->stop = 1; - - if (fault) { - bbfdm_set_fault_message(dmctx, "%s", tb[0] ? blobmsg_get_string(tb[0]) : ""); - dmctx->faultcode = fault; - return; + if (match(in_value, regex_pattern, 1, p_match) && strncmp(key_value, tag + 2, strlen(key_value)) == 0) { + return true; + } } else { - dmctx->faultcode = 0; - } - - if (tb[2]) { - struct blob_attr *output = NULL; - int _rem = 0; - - blobmsg_for_each_attr(output, tb[2], _rem) { - blobmsg_add_blob(&dmctx->bb, output); - } - } - } -} - -static int operate_ubus(struct dmctx *dmctx, struct dmnode *node) -{ - char *ubus_name = node->obj->checkdep; - struct blob_buf blob = {0}; - - if ((dm_is_micro_service() == false) && ((dmctx->dm_type & node->obj->bbfdm_type) == false)) { - BBF_DEBUG("[%s] Ignore unsupported proto objects [%s], in[%d], datamodel[%d]", __func__, ubus_name, dmctx->dm_type, node->obj->bbfdm_type); - return 0; - } - - memset(&blob, 0, sizeof(struct blob_buf)); - blob_buf_init(&blob, 0); - - blobmsg_add_string(&blob, "command", dmctx->in_param); - blobmsg_add_string(&blob, "command_key", dmctx->linker); - - json_object *jobj = json_tokener_parse(dmctx->in_value ? dmctx->in_value : "{}"); - blobmsg_add_json_element(&blob, "input", jobj); - json_object_put(jobj); - - prepare_optional_table(dmctx, &blob); - - int res = ubus_call_blob_msg(ubus_name, "operate", &blob, 120000, __operate_ubus, dmctx); - - blob_buf_free(&blob); - - if (res) - return USP_FAULT_INVALID_PATH; - - if (dmctx->faultcode) - return dmctx->faultcode; - - return 0; -} - -static int get_ubus_reference_value(struct dmctx *dmctx, struct dmnode *node) -{ - unsigned int in_path_dot_num = count_occurrences(dmctx->in_param, '.'); - char *ubus_name = node->obj->checkdep; - json_object *res = NULL; - - 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, "format", json_object_new_string("raw")); - - dmubus_call(ubus_name, "get", - UBUS_ARGS{ - {"path", dmctx->in_param, String}, - {"optional", json_object_to_json_string(in_args), Table} - }, - 2, &res); - - json_object_put(in_args); - - if (!res) - return FAULT_9005; - - json_object *res_array = dmjson_get_obj(res, 1, "results"); - if (!res_array) - return FAULT_9005; - - size_t nbre_obj = json_object_array_length(res_array); - if (nbre_obj == 0) - return FAULT_9005; - - for (size_t i = 0; i < nbre_obj; i++) { - json_object *res_obj = json_object_array_get_idx(res_array, i); - - char *fault = dmjson_get_value(res_obj, 1, "fault"); - if (DM_STRLEN(fault)) - return DM_STRTOUL(fault); - - char *path = dmjson_get_value(res_obj, 1, "path"); - - unsigned int path_dot_num = count_occurrences(path, '.'); - if (path_dot_num > in_path_dot_num) - continue; - - 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_LSTRCMP(flag, "Linker") == 0) { - char *data = dmjson_get_value(res_obj, 1, "data"); - dmctx->linker = data ? dmstrdup(data) : ""; - dmctx->stop = true; - return 0; - } - } + if (strncmp(pch, in_value, strlen(pch)) == 0) + return true; } } - return FAULT_9005; + return false; } /* ********** @@ -1777,31 +986,22 @@ static int get_value_obj(DMOBJECT_ARGS) static int get_value_param(DMPARAM_ARGS) { - if (node->is_ubus_service) { - return get_ubus_value(dmctx, node); + 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); + + if ((leaf->dm_flags & DM_FLAG_SECURE) && (dmctx->dm_type == BBFDM_CWMP)) { + value = dmstrdup(""); + } else if (value && *value) { + value = check_value_by_type(full_param, value, leaf->type); } else { - 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); - - if ((leaf->dm_flags & DM_FLAG_SECURE) && (dmctx->dm_type == BBFDM_CWMP)) { - value = dmstrdup(""); - } else if (value && *value) { - if (leaf->dm_flags & DM_FLAG_REFERENCE) { - value = get_value_by_reference(dmctx, value); - } else { - value = check_value_by_type(full_param, value, leaf->type); - } - } else { - value = get_default_value_by_type(full_param, leaf->type); - } - - fill_blob_param(&dmctx->bb, full_param, value, DMT_TYPE[leaf->type], leaf->dm_flags); + value = get_default_value_by_type(full_param, leaf->type); } + fill_blob_param(&dmctx->bb, full_param, value, DMT_TYPE[leaf->type], leaf->dm_flags); return 0; } @@ -1811,46 +1011,33 @@ static int mobj_get_value_in_param(DMOBJECT_ARGS) } static int mparam_get_value_in_param(DMPARAM_ARGS) { - if (node->is_ubus_service) { - int err = get_ubus_value(dmctx, node); - if (err) + char full_param[MAX_DM_PATH] = {0}; + char *value = dmstrdup(""); + + snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter); + + if (dmctx->iswildcard) { + if (dm_strcmp_wildcard(dmctx->in_param, full_param) != 0) return FAULT_9005; - - dmctx->findparam = (dmctx->iswildcard) ? 1 : 0; - dmctx->stop = (dmctx->iswildcard) ? false : true; } else { - char full_param[MAX_DM_PATH] = {0}; - char *value = dmstrdup(""); - - snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter); - - if (dmctx->iswildcard) { - if (dm_strcmp_wildcard(dmctx->in_param, full_param) != 0) - return FAULT_9005; - } else { - if (DM_STRCMP(dmctx->in_param, full_param) != 0) - return FAULT_9005; - } - - (leaf->getvalue)(full_param, dmctx, data, instance, &value); - - if ((leaf->dm_flags & DM_FLAG_SECURE) && (dmctx->dm_type == BBFDM_CWMP)) { - value = dmstrdup(""); - } else if (value && *value) { - if (leaf->dm_flags & DM_FLAG_REFERENCE) { - value = get_value_by_reference(dmctx, value); - } else - value = check_value_by_type(full_param, value, leaf->type); - } else { - value = get_default_value_by_type(full_param, leaf->type); - } - - fill_blob_param(&dmctx->bb, full_param, value, DMT_TYPE[leaf->type], leaf->dm_flags); - - dmctx->findparam = (dmctx->iswildcard) ? 1 : 0; - dmctx->stop = (dmctx->iswildcard) ? false : true; + if (DM_STRCMP(dmctx->in_param, full_param) != 0) + return FAULT_9005; } + (leaf->getvalue)(full_param, dmctx, data, instance, &value); + + if ((leaf->dm_flags & DM_FLAG_SECURE) && (dmctx->dm_type == BBFDM_CWMP)) { + value = dmstrdup(""); + } else if (value && *value) { + value = check_value_by_type(full_param, value, leaf->type); + } else { + value = get_default_value_by_type(full_param, leaf->type); + } + + fill_blob_param(&dmctx->bb, full_param, value, DMT_TYPE[leaf->type], leaf->dm_flags); + + dmctx->findparam = (dmctx->iswildcard) ? 1 : 0; + dmctx->stop = (dmctx->iswildcard) ? false : true; return 0; } @@ -1927,45 +1114,39 @@ static void fill_blob_alias_param(struct blob_buf *bb, const char *path, const c static int mobj_get_name(DMOBJECT_ARGS) { - if (node->is_ubus_service) { - return 0; - } else { - char *refparam = node->current_object; - char *perm = permission->val; + char *refparam = node->current_object; + char *perm = permission->val; - if (permission->get_permission != NULL) - perm = permission->get_permission(refparam, dmctx, data, instance); - - fill_blob_param(&dmctx->bb, refparam, perm, "xsd:object", 0); + if (DM_STRCMP(node->current_object, ROOT_NODE) == 0 && DM_STRCMP(dmctx->in_value, "core") != 0) return 0; - } + + if (permission->get_permission != NULL) + perm = permission->get_permission(refparam, dmctx, data, instance); + + fill_blob_param(&dmctx->bb, refparam, perm, "xsd:object", 0); + return 0; } static int mparam_get_name(DMPARAM_ARGS) { - if (node->is_ubus_service) { - get_ubus_name(dmctx, node); - return 0; + char *perm = leaf->permission->val; + char refparam[MAX_DM_PATH] = {0}; + + snprintf(refparam, sizeof(refparam), "%s%s", node->current_object, leaf->parameter); + + if (leaf->permission->get_permission != NULL) + perm = leaf->permission->get_permission(refparam, dmctx, data, instance); + + if (DM_LSTRCMP(leaf->parameter, "Alias") == 0) { + char *alias = dmstrdup(""); + + (leaf->getvalue)(refparam, dmctx, data, instance, &alias); + fill_blob_alias_param(&dmctx->bb, refparam, perm, DMT_TYPE[leaf->type], alias); } else { - char *perm = leaf->permission->val; - char refparam[MAX_DM_PATH] = {0}; - - snprintf(refparam, sizeof(refparam), "%s%s", node->current_object, leaf->parameter); - - if (leaf->permission->get_permission != NULL) - perm = leaf->permission->get_permission(refparam, dmctx, data, instance); - - if (DM_LSTRCMP(leaf->parameter, "Alias") == 0) { - char *alias = dmstrdup(""); - - (leaf->getvalue)(refparam, dmctx, data, instance, &alias); - fill_blob_alias_param(&dmctx->bb, refparam, perm, DMT_TYPE[leaf->type], alias); - } else { - fill_blob_param(&dmctx->bb, refparam, perm, DMT_TYPE[leaf->type], 0); - } - - return 0; + fill_blob_param(&dmctx->bb, refparam, perm, DMT_TYPE[leaf->type], 0); } + + return 0; } static int mobj_get_name_in_param(DMOBJECT_ARGS) @@ -1975,99 +1156,89 @@ static int mobj_get_name_in_param(DMOBJECT_ARGS) static int mparam_get_name_in_param(DMPARAM_ARGS) { - if (node->is_ubus_service) { - int err = get_ubus_name(dmctx, node); - dmctx->stop = true; - return err ? err : 0; + char *perm = leaf->permission->val; + char refparam[MAX_DM_PATH] = {0}; + + snprintf(refparam, sizeof(refparam), "%s%s", node->current_object, leaf->parameter); + + if (dmctx->iswildcard) { + if (dm_strcmp_wildcard(refparam, dmctx->in_param) != 0) + return FAULT_9005; } else { - char *perm = leaf->permission->val; - char refparam[MAX_DM_PATH] = {0}; - - snprintf(refparam, sizeof(refparam), "%s%s", node->current_object, leaf->parameter); - - if (dmctx->iswildcard) { - if (dm_strcmp_wildcard(refparam, dmctx->in_param) != 0) - return FAULT_9005; - } else { - if (DM_STRCMP(refparam, dmctx->in_param) != 0) - return FAULT_9005; - } - - dmctx->stop = (dmctx->iswildcard) ? 0 : 1; - - if (dmctx->nextlevel == 1) { - dmctx->stop = 1; - return FAULT_9003; - } - - if (leaf->permission->get_permission != NULL) - perm = leaf->permission->get_permission(refparam, dmctx, data, instance); - - if (DM_LSTRCMP(leaf->parameter, "Alias") == 0) { - char *alias = dmstrdup(""); - - (leaf->getvalue)(refparam, dmctx, data, instance, &alias); - fill_blob_alias_param(&dmctx->bb, refparam, perm, DMT_TYPE[leaf->type], alias); - } else { - fill_blob_param(&dmctx->bb, refparam, perm, DMT_TYPE[leaf->type], 0); - } - - dmctx->findparam = (dmctx->iswildcard) ? 1 : 0; - return 0; + if (DM_STRCMP(refparam, dmctx->in_param) != 0) + return FAULT_9005; } + + dmctx->stop = (dmctx->iswildcard) ? 0 : 1; + + if (dmctx->nextlevel == 1) { + dmctx->stop = 1; + return FAULT_9003; + } + + if (leaf->permission->get_permission != NULL) + perm = leaf->permission->get_permission(refparam, dmctx, data, instance); + + if (DM_LSTRCMP(leaf->parameter, "Alias") == 0) { + char *alias = dmstrdup(""); + + (leaf->getvalue)(refparam, dmctx, data, instance, &alias); + fill_blob_alias_param(&dmctx->bb, refparam, perm, DMT_TYPE[leaf->type], alias); + } else { + fill_blob_param(&dmctx->bb, refparam, perm, DMT_TYPE[leaf->type], 0); + } + + dmctx->findparam = (dmctx->iswildcard) ? 1 : 0; + return 0; + } static int mobj_get_name_in_obj(DMOBJECT_ARGS) { - if (node->is_ubus_service) { + char *refparam = node->current_object; + char *perm = permission->val; + + if (!node->matched) + return FAULT_9005; + + if (DM_STRCMP(node->current_object, ROOT_NODE) == 0 && DM_STRCMP(dmctx->in_value, "core") != 0) return 0; + + if (dmctx->iswildcard) { + if (dmctx->nextlevel && dm_strcmp_wildcard(node->current_object, dmctx->in_param) == 0) + return 0; } else { - char *refparam = node->current_object; - char *perm = permission->val; - - if (!node->matched) - return FAULT_9005; - - if (dmctx->iswildcard) { - if (dmctx->nextlevel && dm_strcmp_wildcard(node->current_object, dmctx->in_param) == 0) - return 0; - } else { - if (dmctx->nextlevel && DM_STRCMP(node->current_object, dmctx->in_param) == 0) - return 0; - } - - if (permission->get_permission != NULL) - perm = permission->get_permission(refparam, dmctx, data, instance); - - fill_blob_param(&dmctx->bb, refparam, perm, "xsd:object", 0); - return 0; + if (dmctx->nextlevel && DM_STRCMP(node->current_object, dmctx->in_param) == 0) + return 0; } + + if (permission->get_permission != NULL) + perm = permission->get_permission(refparam, dmctx, data, instance); + + fill_blob_param(&dmctx->bb, refparam, perm, "xsd:object", 0); + return 0; } static int mparam_get_name_in_obj(DMPARAM_ARGS) { - if (node->is_ubus_service) { - return get_ubus_name(dmctx, node); + char *perm = leaf->permission->val; + char refparam[MAX_DM_PATH] = {0}; + + snprintf(refparam, sizeof(refparam), "%s%s", node->current_object, leaf->parameter); + + if (leaf->permission->get_permission != NULL) + perm = leaf->permission->get_permission(refparam, dmctx, data, instance); + + if (DM_LSTRCMP(leaf->parameter, "Alias") == 0) { + char *alias = dmstrdup(""); + + (leaf->getvalue)(refparam, dmctx, data, instance, &alias); + fill_blob_alias_param(&dmctx->bb, refparam, perm, DMT_TYPE[leaf->type], alias); } else { - char *perm = leaf->permission->val; - char refparam[MAX_DM_PATH] = {0}; - - snprintf(refparam, sizeof(refparam), "%s%s", node->current_object, leaf->parameter); - - if (leaf->permission->get_permission != NULL) - perm = leaf->permission->get_permission(refparam, dmctx, data, instance); - - if (DM_LSTRCMP(leaf->parameter, "Alias") == 0) { - char *alias = dmstrdup(""); - - (leaf->getvalue)(refparam, dmctx, data, instance, &alias); - fill_blob_alias_param(&dmctx->bb, refparam, perm, DMT_TYPE[leaf->type], alias); - } else { - fill_blob_param(&dmctx->bb, refparam, perm, DMT_TYPE[leaf->type], 0); - } - - return 0; + fill_blob_param(&dmctx->bb, refparam, perm, DMT_TYPE[leaf->type], 0); } + + return 0; } int dm_entry_get_name(struct dmctx *ctx) @@ -2098,8 +1269,7 @@ int dm_entry_get_name(struct dmctx *ctx) ctx->checkleaf = plugin_leaf_nextlevel_match; ctx->method_obj = mobj_get_name; ctx->method_param = mparam_get_name; - ctx->in_param = root->obj; - ctx->disable_mservice_browse = true; + ctx->in_param = dmstrdup("Device"); node.matched = 1; findparam_check = 1; } else if (*(ctx->in_param + len - 1) == '.') { @@ -2137,15 +1307,11 @@ int dm_entry_get_name(struct dmctx *ctx) * ***********************/ static int mobj_get_supported_dm(DMOBJECT_ARGS) { - if (node->is_ubus_service) { - return 0; - } else { - char *perm = permission ? permission->val : "0"; - char *refparam = node->current_object; + char *perm = permission ? permission->val : "0"; + char *refparam = node->current_object; - if (node->matched && dmctx->isinfo) { - fill_blob_param(&dmctx->bb, refparam, perm, "xsd:object", 0); - } + if (node->matched && dmctx->isinfo) { + fill_blob_param(&dmctx->bb, refparam, perm, "xsd:object", 0); } return 0; @@ -2153,38 +1319,34 @@ static int mobj_get_supported_dm(DMOBJECT_ARGS) static int mparam_get_supported_dm(DMPARAM_ARGS) { - if (node->is_ubus_service) { - return get_ubus_supported_dm(dmctx, node); - } else { - char refparam[MAX_DM_PATH] = {0}; - char *value = NULL; + char refparam[MAX_DM_PATH] = {0}; + char *value = NULL; - snprintf(refparam, sizeof(refparam), "%s%s", node->current_object, leaf->parameter); + snprintf(refparam, sizeof(refparam), "%s%s", node->current_object, leaf->parameter); - if (node->matched) { - if (leaf->type == DMT_EVENT) { - if (dmctx->isevent) { - if (leaf->getvalue) - (leaf->getvalue)(refparam, dmctx, data, instance, &value); + if (node->matched) { + if (leaf->type == DMT_EVENT) { + if (dmctx->isevent) { + if (leaf->getvalue) + (leaf->getvalue)(refparam, dmctx, data, instance, &value); - fill_blob_event(&dmctx->bb, refparam, DMT_TYPE[leaf->type], value); - } - - } else if (leaf->type == DMT_COMMAND) { - if (dmctx->iscommand) { - - if (leaf->getvalue) - (leaf->getvalue)(refparam, dmctx, data, instance, &value); - - fill_blob_operate(&dmctx->bb, refparam, leaf->permission->val, DMT_TYPE[leaf->type], value); - } - } else { - fill_blob_param(&dmctx->bb, refparam, leaf->permission->val, DMT_TYPE[leaf->type], leaf->dm_flags); + fill_blob_event(&dmctx->bb, refparam, DMT_TYPE[leaf->type], value); } - } - return 0; + } else if (leaf->type == DMT_COMMAND) { + if (dmctx->iscommand) { + + if (leaf->getvalue) + (leaf->getvalue)(refparam, dmctx, data, instance, &value); + + fill_blob_operate(&dmctx->bb, refparam, leaf->permission->val, DMT_TYPE[leaf->type], value); + } + } else { + fill_blob_param(&dmctx->bb, refparam, leaf->permission->val, DMT_TYPE[leaf->type], leaf->dm_flags); + } } + + return 0; } int dm_entry_get_supported_dm(struct dmctx *ctx) @@ -2216,23 +1378,19 @@ int dm_entry_get_supported_dm(struct dmctx *ctx) * **************/ static int mobj_get_instances_in_obj(DMOBJECT_ARGS) { - if (node->is_ubus_service) { - return get_ubus_instances(dmctx, node); - } else { - if (node->matched && node->is_instanceobj) { - char path[MAX_DM_PATH] = {0}; + if (node->matched && node->is_instanceobj) { + char path[MAX_DM_PATH] = {0}; - snprintf(path, sizeof(path), "%s", node->current_object); + snprintf(path, sizeof(path), "%s", node->current_object); - int len = DM_STRLEN(path); + int len = DM_STRLEN(path); - if (len) { - path[len - 1] = 0; + if (len) { + path[len - 1] = 0; - void *table = blobmsg_open_table(&dmctx->bb, NULL); - blobmsg_add_string(&dmctx->bb, "path", path); - blobmsg_close_table(&dmctx->bb, table); - } + void *table = blobmsg_open_table(&dmctx->bb, NULL); + blobmsg_add_string(&dmctx->bb, "path", path); + blobmsg_close_table(&dmctx->bb, table); } } @@ -2260,14 +1418,8 @@ int dm_entry_get_instances(struct dmctx *ctx) ctx->inparam_isparam = 0; ctx->findparam = 0; ctx->stop = 0; - - if (ctx->iswildcard) { - ctx->checkobj = (ctx->nextlevel) ? plugin_obj_wildcard_nextlevel_match : plugin_obj_wildcard_match; - ctx->checkleaf = (ctx->nextlevel) ? plugin_leaf_wildcard_nextlevel_match : plugin_leaf_wildcard_match; - } else { - ctx->checkobj = (ctx->nextlevel) ? plugin_obj_nextlevel_match : plugin_obj_match; - ctx->checkleaf = (ctx->nextlevel) ? plugin_leaf_nextlevel_match : plugin_leaf_match; - } + ctx->checkobj = (ctx->iswildcard) ? plugin_obj_wildcard_match : plugin_obj_match; + ctx->checkleaf = (ctx->iswildcard) ? plugin_leaf_wildcard_match : plugin_leaf_match; ctx->method_obj = mobj_get_instances_in_obj; ctx->method_param = mparam_get_instances_in_obj; @@ -2281,40 +1433,36 @@ int dm_entry_get_instances(struct dmctx *ctx) * **************/ static int mobj_add_object(DMOBJECT_ARGS) { - if (node->is_ubus_service) { - return add_ubus_object(dmctx, node); - } else { - char *refparam = node->current_object; - char *perm = permission->val; - char *new_instance = NULL; - int fault = 0; + char *refparam = node->current_object; + char *perm = permission->val; + char *new_instance = NULL; + int fault = 0; - if (DM_STRCMP(refparam, dmctx->in_param) != 0) - return FAULT_9005; + if (DM_STRCMP(refparam, dmctx->in_param) != 0) + return FAULT_9005; - if (node->is_instanceobj) - return FAULT_9005; + if (node->is_instanceobj) + return FAULT_9005; - if (permission->get_permission != NULL) - perm = permission->get_permission(refparam, dmctx, data, instance); + if (permission->get_permission != NULL) + perm = permission->get_permission(refparam, dmctx, data, instance); - if (perm[0] == '0' || addobj == NULL) - return FAULT_9005; + if (perm[0] == '0' || addobj == NULL) + return FAULT_9005; - int max_inst = find_max_instance(dmctx, node); - fault = dmasprintf(&new_instance, "%d", max_inst); - if (fault) - return fault; + int max_inst = find_max_instance(dmctx, node); + fault = dmasprintf(&new_instance, "%d", max_inst); + if (fault) + return fault; - dmctx->stop = 1; + dmctx->stop = 1; - fault = (addobj)(refparam, dmctx, data, &new_instance); - if (fault) - return fault; + fault = (addobj)(refparam, dmctx, data, &new_instance); + if (fault) + return fault; - dmctx->addobj_instance = new_instance; - return 0; - } + dmctx->addobj_instance = new_instance; + return 0; } static int mparam_add_object(DMPARAM_ARGS) @@ -2349,30 +1497,24 @@ int dm_entry_add_object(struct dmctx *dmctx) * **************/ static int delete_object_obj(DMOBJECT_ARGS) { - if (node->is_ubus_service) { - return del_ubus_object(dmctx, node); - } else { - char *refparam = node->current_object; - char *perm = permission->val; + char *refparam = node->current_object; + char *perm = permission->val; - if (DM_STRCMP(refparam, dmctx->in_param) != 0) - return FAULT_9005; + if (DM_STRCMP(refparam, dmctx->in_param) != 0) + return FAULT_9005; - dmctx->stop = 1; + dmctx->stop = 1; - if (permission->get_permission != NULL) - perm = permission->get_permission(refparam, dmctx, data, instance); + if (permission->get_permission != NULL) + perm = permission->get_permission(refparam, dmctx, data, instance); - if (perm[0] == '0' || delobj == NULL) - return FAULT_9005; + if (perm[0] == '0' || delobj == NULL) + return FAULT_9005; - if (!node->is_instanceobj) - return FAULT_9005; + if (!node->is_instanceobj) + return FAULT_9005; - return (delobj)(refparam, dmctx, data, instance, DEL_INST); - } - - return 0; + return (delobj)(refparam, dmctx, data, instance, DEL_INST); } static int delete_object_param(DMPARAM_ARGS) @@ -2450,76 +1592,76 @@ static int get_datatype(char *type) static int mparam_set_value(DMPARAM_ARGS) { - if (node->is_ubus_service) { - return set_ubus_value(dmctx, node); - } else { - char refparam[MAX_DM_PATH] = {0}; - char param_value[2048] = {0}; - char *value = dmstrdup(""); + char refparam[MAX_DM_PATH] = {0}; + char param_value[2048] = {0}; + char *value = dmstrdup(""); - snprintf(refparam, MAX_DM_PATH, "%s%s", node->current_object, leaf->parameter); - if (DM_STRCMP(refparam, dmctx->in_param) != 0) - return FAULT_9005; + snprintf(refparam, MAX_DM_PATH, "%s%s", node->current_object, leaf->parameter); + if (DM_STRCMP(refparam, dmctx->in_param) != 0) + return FAULT_9005; - dmctx->stop = 1; - dmctx->setaction = VALUECHECK; + dmctx->stop = 1; + dmctx->setaction = VALUECHECK; - char *perm = leaf->permission->val; - if (leaf->permission->get_permission != NULL) - perm = leaf->permission->get_permission(refparam, dmctx, data, instance); + char *perm = leaf->permission->val; + if (leaf->permission->get_permission != NULL) + perm = leaf->permission->get_permission(refparam, dmctx, data, instance); - if (perm[0] == '0' || !leaf->setvalue) - return FAULT_9008; + if (perm[0] == '0' || !leaf->setvalue) + return FAULT_9008; - // If type is not defined then bypass this check - if (DM_STRLEN(dmctx->in_type) != 0) { - int type = get_datatype(dmctx->in_type); + // If type is not defined then bypass this check + if (DM_STRLEN(dmctx->in_type) != 0) { + int type = get_datatype(dmctx->in_type); - if (type != leaf->type) { - return FAULT_9006; - } + if (type != leaf->type) { + return FAULT_9006; } - - (leaf->getvalue)(refparam, dmctx, data, instance, &value); - - snprintf(param_value, sizeof(param_value), "%s", dmctx->in_value); - - if (leaf->type == DMT_BOOL) { - bool val = false; - int res = 0; - - res = string_to_bool(dmctx->in_value, &val); - if (res == 0 && dmuci_string_to_boolean(value) == val) { - BBF_DEBUG("Requested value (%s) is same as current value (%s).", dmctx->in_value, value); - return 0; - } - } else if (leaf->dm_flags & DM_FLAG_REFERENCE) { - value = get_value_by_reference(dmctx, value); - - if (DM_STRCMP(value, dmctx->in_value) == 0) { - BBF_DEBUG("Requested value (%s) is same as current value (%s)..", dmctx->in_value, value); - return 0; - } - - if (DM_LSTRSTR(dmctx->in_value, "=>") == NULL) - get_reference_paramater_value(dmctx, dmctx->in_value, param_value, sizeof(param_value)); - } else { - if (DM_STRCMP(value, dmctx->in_value) == 0) { - BBF_DEBUG("Requested value (%s) is same as current value (%s)...", dmctx->in_value, value); - return 0; - } - } - - char *param_val = dmstrdup(param_value); - - int fault = (leaf->setvalue)(refparam, dmctx, data, instance, param_value, dmctx->setaction); - if (fault) - return fault; - - dmctx->setaction = VALUESET; - - return (leaf->setvalue)(refparam, dmctx, data, instance, param_val, dmctx->setaction); } + + (leaf->getvalue)(refparam, dmctx, data, instance, &value); + + snprintf(param_value, sizeof(param_value), "%s", dmctx->in_value); + + if (leaf->type == DMT_BOOL) { + bool val = false; + int res = 0; + + res = string_to_bool(dmctx->in_value, &val); + if (res == 0 && dmuci_string_to_boolean(value) == val) { + BBF_DEBUG("Requested value (%s) is same as current value (%s).", dmctx->in_value, value); + return 0; + } + } else if (leaf->dm_flags & DM_FLAG_REFERENCE) { + if (is_same_reference_path(value, dmctx->in_value, param_value, sizeof(param_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, dmctx->in_value) == 0) { + BBF_DEBUG("Requested value (%s) is same as current value (%s)...", dmctx->in_value, value); + return 0; + } + } + + char *param_val = dmstrdup(param_value); + + int fault = (leaf->setvalue)(refparam, dmctx, data, instance, param_value, dmctx->setaction); + if (fault) + return fault; + + dmctx->setaction = VALUESET; + + return (leaf->setvalue)(refparam, dmctx, data, instance, param_val, dmctx->setaction); } int dm_entry_set_value(struct dmctx *dmctx) @@ -2547,57 +1689,6 @@ int dm_entry_set_value(struct dmctx *dmctx) /****************** * get reference param *****************/ -static int get_key_ubus_value(struct dmctx *dmctx, struct dmnode *node) -{ - json_object *res = NULL, *res_obj = NULL; - char *ubus_name = node->obj->checkdep; - - 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, "format", json_object_new_string("raw")); - - dmubus_call(ubus_name, "get", - UBUS_ARGS{ - {"path", dmctx->in_param, String}, - {"optional", json_object_to_json_string(in_args), Table} - }, - 2, &res); - - json_object_put(in_args); - - if (!res) - return FAULT_9005; - - json_object *res_array = dmjson_get_obj(res, 1, "results"); - if (!res_array) - return FAULT_9005; - - size_t nbre_obj = json_object_array_length(res_array); - - if (nbre_obj == 0) - return FAULT_9005; - - for (size_t i = 0; i < nbre_obj; i++) { - res_obj = json_object_array_get_idx(res_array, i); - - char *fault = dmjson_get_value(res_obj, 1, "fault"); - if (DM_STRLEN(fault)) - return DM_STRTOUL(fault); - - char *path = dmjson_get_value(res_obj, 1, "path"); - char *data = dmjson_get_value(res_obj, 1, "data"); - - if (data && DM_STRCMP(data, dmctx->linker) == 0) { - dmctx->linker_param = dmstrdup(path); - char *p = strrchr(dmctx->linker_param, '.'); - if (p) *p = 0; - return 0; - } - } - - return 0; -} - static int get_key_check_obj(DMOBJECT_ARGS) { return FAULT_9005; @@ -2605,28 +1696,22 @@ static int get_key_check_obj(DMOBJECT_ARGS) static int get_key_check_param(DMPARAM_ARGS) { - if (node->is_ubus_service) { - int err = get_key_ubus_value(dmctx, node); + char full_param[MAX_DM_PATH] = {0}; + char *value = dmstrdup(""); + + snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter); + + if (dm_strcmp_wildcard(dmctx->in_param, full_param) != 0) + return FAULT_9005; + + (leaf->getvalue)(full_param, dmctx, data, instance, &value); + + if (DM_STRLEN(value) && 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 err ? err : 0; - } else { - char full_param[MAX_DM_PATH] = {0}; - char *value = dmstrdup(""); - - snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter); - - if (dm_strcmp_wildcard(dmctx->in_param, full_param) != 0) - return FAULT_9005; - - (leaf->getvalue)(full_param, dmctx, data, instance, &value); - - if (DM_STRLEN(value) && 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 0; } return FAULT_9005; @@ -2653,32 +1738,28 @@ int dm_entry_get_reference_param(struct dmctx *dmctx) *****************/ static int get_reference_value_check_obj(DMOBJECT_ARGS) { - if (node->is_ubus_service) { - return get_ubus_reference_value(dmctx, node); - } else { - if (DM_STRCMP(node->current_object, dmctx->in_param) == 0) { + if (DM_STRCMP(node->current_object, dmctx->in_param) == 0) { - if (!data || !instance) - return FAULT_9005; + if (!data || !instance) + return FAULT_9005; - struct dm_leaf_s *leaf = node->obj->leaf; - if (!leaf) - return FAULT_9005; + struct dm_leaf_s *leaf = node->obj->leaf; + if (!leaf) + return FAULT_9005; - for (; (leaf && leaf->parameter); leaf++) { + for (; (leaf && leaf->parameter); leaf++) { - if (leaf->dm_flags & DM_FLAG_LINKER) { - char full_param[MAX_DM_PATH] = {0}; - char *link_val = NULL; + if (leaf->dm_flags & DM_FLAG_LINKER) { + char full_param[MAX_DM_PATH] = {0}; + char *link_val = NULL; - snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter); + snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter); - (leaf->getvalue)(full_param, dmctx, data, instance, &link_val); + (leaf->getvalue)(full_param, dmctx, data, instance, &link_val); - dmctx->linker = link_val ? dmstrdup(link_val) : ""; - dmctx->stop = true; - return 0; - } + dmctx->linker = link_val ? dmstrdup(link_val) : ""; + dmctx->stop = true; + return 0; } } } @@ -2712,22 +1793,13 @@ int dm_entry_get_reference_value(struct dmctx *dmctx) *****************/ static int object_exists_check_obj(DMOBJECT_ARGS) { - if (node->is_ubus_service) { - int fault = get_ubus_instances(dmctx, node); - if (fault) - return fault; - + if (DM_STRCMP(node->current_object, dmctx->in_param) == 0) { dmctx->match = true; dmctx->stop = true; return 0; - } else { - if (DM_STRCMP(node->current_object, dmctx->in_param) == 0) { - dmctx->match = true; - dmctx->stop = true; - return 0; - } - return FAULT_9005; } + + return FAULT_9005; } static int object_exists_check_param(DMPARAM_ARGS) @@ -2761,26 +1833,22 @@ static int mobj_operate(DMOBJECT_ARGS) static int mparam_operate(DMPARAM_ARGS) { - if (node->is_ubus_service) { - return operate_ubus(dmctx, node); - } else { - char full_param[MAX_DM_PATH]; + char full_param[MAX_DM_PATH]; - snprintf(full_param, MAX_DM_PATH, "%s%s", node->current_object, leaf->parameter); - if (DM_STRCMP(full_param, dmctx->in_param) != 0) - return USP_FAULT_INVALID_PATH; + snprintf(full_param, MAX_DM_PATH, "%s%s", node->current_object, leaf->parameter); + if (DM_STRCMP(full_param, dmctx->in_param) != 0) + return USP_FAULT_INVALID_PATH; - dmctx->stop = 1; + dmctx->stop = 1; - if (!leaf->setvalue) - return USP_FAULT_COMMAND_FAILURE; + if (!leaf->setvalue) + return USP_FAULT_COMMAND_FAILURE; - json_object *j_input = (dmctx->in_value) ? json_tokener_parse(dmctx->in_value) : NULL; - int fault = (leaf->setvalue)(full_param, dmctx, data, instance, (char *)j_input, 0); - json_object_put(j_input); + json_object *j_input = (dmctx->in_value) ? json_tokener_parse(dmctx->in_value) : NULL; + int fault = (leaf->setvalue)(full_param, dmctx, data, instance, (char *)j_input, 0); + json_object_put(j_input); - return fault; - } + return fault; } int dm_entry_operate(struct dmctx *dmctx) diff --git a/libbbfdm-api/legacy/dmbbf.h b/libbbfdm-api/legacy/dmbbf.h index 94eb1a14..829be868 100644 --- a/libbbfdm-api/legacy/dmbbf.h +++ b/libbbfdm-api/legacy/dmbbf.h @@ -27,9 +27,6 @@ #include "dmmem.h" #include "dmapi.h" -bool dm_is_micro_service(void); -void dm_set_micro_service(void); - int get_number_of_entries(struct dmctx *ctx, void *data, char *instance, int (*browseinstobj)(struct dmctx *ctx, struct dmnode *node, void *data, char *instance)); char *handle_instance(struct dmctx *dmctx, DMNODE *parent_node, struct uci_section *s, const char *inst_opt, const char *alias_opt); char *handle_instance_without_section(struct dmctx *dmctx, DMNODE *parent_node, int inst_nbr); @@ -40,7 +37,6 @@ void fill_blob_event(struct blob_buf *bb, const char *path, const char *type, vo void fill_blob_operate(struct blob_buf *bb, const char *path, const char *data, const char *type, void *in_out); int string_to_bool(const char *v, bool *b); -char *get_value_by_reference(struct dmctx *ctx, char *value); int dm_entry_get_value(struct dmctx *dmctx); int dm_entry_get_name(struct dmctx *ctx); int dm_entry_get_supported_dm(struct dmctx *ctx); diff --git a/libbbfdm-api/legacy/dmentry.c b/libbbfdm-api/legacy/dmentry.c index c73cdb9b..bb9e1964 100644 --- a/libbbfdm-api/legacy/dmentry.c +++ b/libbbfdm-api/legacy/dmentry.c @@ -49,6 +49,7 @@ void bbf_ctx_init(struct dmctx *ctx, DMOBJ *tEntryObj) ctx->dm_entryobj = tEntryObj; dm_init_mem(ctx); dm_uci_init(ctx); + dm_ubus_init(ctx); } void bbf_ctx_clean(struct dmctx *ctx) @@ -57,7 +58,7 @@ void bbf_ctx_clean(struct dmctx *ctx) dm_uci_exit(ctx); dm_clean_mem(ctx); - dmubus_free(); + dm_ubus_free(ctx); } void bbf_ctx_init_sub(struct dmctx *ctx, DMOBJ *tEntryObj) @@ -273,13 +274,10 @@ int adm_entry_get_reference_param(struct dmctx *ctx, char *param, char *linker, { struct dmctx dmctx = {0}; - *value = dmstrdup(""); - - if (!param || !linker || *linker == 0) + if (DM_STRLEN(param) == 0 || DM_STRLEN(linker) == 0) return 0; - bbf_ctx_init_sub(&dmctx, ctx->dm_entryobj); - + dmctx.dm_entryobj = ctx->dm_entryobj; dmctx.iswildcard = 1; dmctx.inparam_isparam = 1; dmctx.in_param = param; @@ -287,9 +285,8 @@ int adm_entry_get_reference_param(struct dmctx *ctx, char *param, char *linker, dm_entry_get_reference_param(&dmctx); - *value = dmctx.linker_param ? dmctx.linker_param : dmstrdup(""); + *value = dmctx.linker_param; - bbf_ctx_clean_sub(&dmctx); return 0; } @@ -317,7 +314,7 @@ int adm_entry_get_reference_value(struct dmctx *ctx, const char *param, char **v return 0; } -bool adm_entry_object_exists(struct dmctx *ctx, const char *param) // To be removed later!!!!!!!!!!!! (After moving all Objects outside bbfdm core) +bool adm_entry_object_exists(struct dmctx *ctx, const char *param) // To be removed later { struct dmctx dmctx = {0}; char linker[256] = {0}; diff --git a/libbbfdm-api/legacy/dmentry.h b/libbbfdm-api/legacy/dmentry.h index e93571bf..1d5756b7 100644 --- a/libbbfdm-api/legacy/dmentry.h +++ b/libbbfdm-api/legacy/dmentry.h @@ -30,12 +30,8 @@ void bbf_global_clean(DMOBJ *dm_entryobj); int dm_validate_allowed_objects(struct dmctx *ctx, struct dm_reference *reference, char *objects[]); -bool adm_entry_object_exists(struct dmctx *ctx, const char *param); // To be removed later!!!!!!!!!!!! (After moving all Objects outside bbfdm core) +bool adm_entry_object_exists(struct dmctx *ctx, const char *param); // To be removed later void bbf_entry_services(unsigned int proto, bool is_commit, bool reload_required); -void get_list_of_registered_service(struct list_head *srvlist, struct blob_buf *bb); -bool load_service(DMOBJ *main_dm, struct list_head *srv_list, const char *srv_name, const char *srv_parent_dm, const char *srv_obj, bool is_unified, uint8_t proto); -void free_services_from_list(struct list_head *clist); - #endif //__DMENTRY_H__ diff --git a/libbbfdm-api/legacy/dmplugin.c b/libbbfdm-api/legacy/dmplugin.c index 15b242c5..212eabb5 100644 --- a/libbbfdm-api/legacy/dmplugin.c +++ b/libbbfdm-api/legacy/dmplugin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 iopsys Software Solutions AB + * Copyright (C) 2023-2025 iopsys Software Solutions AB * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 @@ -14,141 +14,6 @@ #include "plugin/json_plugin.h" #include "plugin/dotso_plugin.h" -extern struct list_head global_memhead; - -struct service -{ - bool is_unified_daemon; - enum bbfdm_type_enum proto; - struct list_head list; - char *name; - char *parent_dm; - char *object; -}; - -static bool add_service_to_main_tree(DMOBJ *main_dm, const char *srv_name, const char *srv_parent_dm, const char *srv_obj, uint8_t proto) -{ - DMOBJ *dm_entryobj = find_entry_obj(main_dm, srv_parent_dm); - if (!dm_entryobj) - return false; - - // Disable service object if it already exists in the main tree - disable_entry_obj(dm_entryobj, srv_obj, srv_parent_dm, srv_name); - - if (dm_entryobj->nextdynamicobj == NULL) { - dm_entryobj->nextdynamicobj = calloc(__INDX_DYNAMIC_MAX, sizeof(struct dm_dynamic_obj)); - dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].idx_type = INDX_JSON_MOUNT; - dm_entryobj->nextdynamicobj[INDX_LIBRARY_MOUNT].idx_type = INDX_LIBRARY_MOUNT; - dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].idx_type = INDX_SERVICE_MOUNT; - } - - if (dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj == NULL) { - dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj = calloc(2, sizeof(DMOBJ *)); - } - - if (dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] == NULL) { - dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] = dm_dynamic_calloc(&global_memhead, 2, sizeof(struct dm_obj_s)); - ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[0]).obj = dm_dynamic_strdup(&global_memhead, srv_obj); - ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[0]).checkdep = dm_dynamic_strdup(&global_memhead, srv_name); - ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[0]).bbfdm_type = proto; - } else { - int idx = get_entry_obj_idx(dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0]); - dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] = dm_dynamic_realloc(&global_memhead, dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0], (idx + 2) * sizeof(struct dm_obj_s)); - memset(dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] + (idx + 1), 0, sizeof(struct dm_obj_s)); - ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[idx]).obj = dm_dynamic_strdup(&global_memhead, srv_obj); - ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[idx]).checkdep = dm_dynamic_strdup(&global_memhead, srv_name); - ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[idx]).bbfdm_type = proto; - } - - return true; -} - -static bool is_service_registered(struct list_head *srvlist, const char *srv_name, const char *srv_parent_dm, const char *srv_obj) -{ - struct service *srv = NULL; - - list_for_each_entry(srv, srvlist, list) { - if (DM_STRCMP(srv->name, srv_name) == 0 && - DM_STRCMP(srv->parent_dm, srv_parent_dm) == 0 && - DM_STRCMP(srv->object, srv_obj) == 0) - return true; - } - - return false; -} - -static void add_service_to_list(struct list_head *srvlist, const char *srv_name, const char *srv_parent_dm, const char *srv_object, uint8_t proto, bool is_unified) -{ - struct service *srv = NULL; - - srv = calloc(1, sizeof(struct service)); - list_add_tail(&srv->list, srvlist); - - srv->name = strdup(srv_name); - srv->parent_dm = strdup(srv_parent_dm); - srv->object = strdup(srv_object); - srv->is_unified_daemon = is_unified; - srv->proto = proto; -} - -void free_services_from_list(struct list_head *clist) -{ - struct service *srv = NULL, *tmp = NULL; - - list_for_each_entry_safe(srv, tmp, clist, list) { - list_del(&srv->list); - free(srv->name); - free(srv->parent_dm); - free(srv->object); - free(srv); - } -} - -bool load_service(DMOBJ *main_dm, struct list_head *srv_list, const char *srv_name, const char *srv_parent_dm, const char *srv_obj, bool is_unified, uint8_t proto) -{ - if (!main_dm || !srv_list || !srv_name || !srv_parent_dm || !srv_obj) { - BBF_ERR("Invalid arguments: main_dm, srv_list, srv_name, srv_parent_dm, and srv_obj must not be NULL."); - return false; - } - - if (is_service_registered(srv_list, srv_name, srv_parent_dm, srv_obj)) { - BBF_DEBUG("Service registration failed: Service '%s' with parent DM '%s' and object '%s' is already registered.", - srv_name, srv_parent_dm, srv_obj); - return false; - } - - if (!add_service_to_main_tree(main_dm, srv_name, srv_parent_dm, srv_obj, proto)) { - BBF_ERR("Failed to add service '%s' to main tree with parent DM '%s' and object '%s'.", - srv_name, srv_parent_dm, srv_obj); - return false; - } - - add_service_to_list(srv_list, srv_name, srv_parent_dm, srv_obj, proto, is_unified); - return true; -} - -void get_list_of_registered_service(struct list_head *srvlist, struct blob_buf *bb) -{ - struct service *srv = NULL; - void *table = NULL; - - list_for_each_entry(srv, srvlist, list) { - table = blobmsg_open_table(bb, NULL); - blobmsg_add_string(bb, "name", srv->name); - blobmsg_add_string(bb, "parent_dm", srv->parent_dm); - blobmsg_add_string(bb, "object", srv->object); - if (srv->proto == BBFDM_USP) { - blobmsg_add_string(bb, "proto", "usp"); - } else if (srv->proto == BBFDM_CWMP) { - blobmsg_add_string(bb, "proto", "cwmp"); - } else { - blobmsg_add_string(bb, "proto", "both"); - } - blobmsg_add_u8(bb, "unified_daemon", srv->is_unified_daemon); - blobmsg_close_table(bb, table); - } -} - static void free_all_dynamic_nodes(DMOBJ *entryobj) { for (; (entryobj && entryobj->obj); entryobj++) { @@ -356,47 +221,45 @@ int get_leaf_idx(DMLEAF **entryleaf) return idx; } +static int filter(const struct dirent *entry) +{ + return entry->d_name[0] != '.'; +} + +static int compare(const struct dirent **a, const struct dirent **b) +{ + return strcasecmp((*a)->d_name, (*b)->d_name); +} + void load_plugins(DMOBJ *dm_entryobj, const char *plugin_path) { + struct dirent **namelist; + if (DM_STRLEN(plugin_path) == 0) // If empty, return without further action return; if (!folder_exists(plugin_path)) { - BBF_ERR("(%s) doesn't exist", plugin_path); + BBF_ERR("Folder plugin (%s) doesn't exist", plugin_path); return; } - struct dirent *ent = NULL; - int num_files = 0; - char *files[256]; - - DIR *dir = opendir(plugin_path); - if (dir == NULL) { - BBF_ERR("Cannot open (%s) directory", plugin_path); - return; - } - - while ((ent = readdir(dir)) != NULL && num_files < 256) { - files[num_files++] = strdup(ent->d_name); - } - - closedir(dir); - - qsort(files, num_files, sizeof(char *), compare_strings); + int num_files = scandir(plugin_path, &namelist, filter, compare); for (int i = 0; i < num_files; i++) { - char buf[512] = {0}; + char file_path[512] = {0}; - snprintf(buf, sizeof(buf), "%s/%s", plugin_path, files[i]); + snprintf(file_path, sizeof(file_path), "%s/%s", plugin_path, namelist[i]->d_name); - if (DM_LSTRSTR(files[i], ".json")) { - load_json_plugins(dm_entryobj, buf); - } else if (DM_LSTRSTR(files[i], ".so")) { - load_dotso_plugins(dm_entryobj, buf); + if (DM_LSTRSTR(namelist[i]->d_name, ".json")) { + load_json_plugins(dm_entryobj, file_path); + } else if (DM_LSTRSTR(namelist[i]->d_name, ".so")) { + load_dotso_plugins(dm_entryobj, file_path); } - free(files[i]); + FREE(namelist[i]); } + + FREE(namelist); } void free_plugins(DMOBJ *dm_entryobj) diff --git a/libbbfdm-api/legacy/dmplugin.h b/libbbfdm-api/legacy/dmplugin.h index b4c6ef63..871a3378 100644 --- a/libbbfdm-api/legacy/dmplugin.h +++ b/libbbfdm-api/legacy/dmplugin.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 iopsys Software Solutions AB + * Copyright (C) 2023-2025 iopsys Software Solutions AB * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/libbbfdm-api/legacy/dmubus.c b/libbbfdm-api/legacy/dmubus.c index 746b2f29..47dfae1f 100644 --- a/libbbfdm-api/legacy/dmubus.c +++ b/libbbfdm-api/legacy/dmubus.c @@ -43,19 +43,6 @@ static json_object *json_res = NULL; static const struct dm_ubus_cache_entry * dm_ubus_cache_lookup(unsigned hash); -static struct ubus_context *dm_libubus_init() -{ - return ubus_connect(NULL); -} - -static void dm_libubus_free() -{ - if (ubus_ctx) { - ubus_free(ubus_ctx); - ubus_ctx = NULL; - } -} - static void prepare_blob_message(struct blob_buf *b, const struct ubus_arg u_args[], int u_args_size) { if (!b) @@ -103,11 +90,8 @@ static int __dm_ubus_call_internal(const char *obj, const char *method, int time json_res = NULL; if (ubus_ctx == NULL) { - ubus_ctx = dm_libubus_init(); - if (ubus_ctx == NULL) { - BBF_ERR("UBUS context is null"); - return -1; - } + BBF_ERR("UBUS context is null"); + return -1; } if (ubus_lookup_id(ubus_ctx, obj, &id)) { @@ -332,11 +316,8 @@ static int dmubus_call_blob_internal(const char *obj, const char *method, json_o if (resp) *resp = NULL; if (ubus_ctx == NULL) { - ubus_ctx = dm_libubus_init(); - if (ubus_ctx == NULL) { - printf("UBUS context is null\n\r"); - return -1; - } + BBF_ERR("UBUS context is null"); + return -1; } memset(&blob, 0, sizeof(struct blob_buf)); @@ -387,7 +368,7 @@ int dmubus_call_blob_set(const char *obj, const char *method, json_object *value static int dmubus_call_blob_msg_internal(const char *obj, const char *method, struct blob_buf *data, int timeout, json_object **resp) { uint32_t id = 0; - int rc = -1; + int rc; json_res = NULL; @@ -395,11 +376,8 @@ static int dmubus_call_blob_msg_internal(const char *obj, const char *method, st *resp = NULL; if (ubus_ctx == NULL) { - ubus_ctx = dm_libubus_init(); - if (ubus_ctx == NULL) { - BBF_ERR("UBUS context is null"); - return -1; - } + BBF_ERR("UBUS context is null"); + return -1; } if (ubus_lookup_id(ubus_ctx, obj, &id)) { @@ -533,8 +511,8 @@ int dmubus_call(const char *obj, const char *method, struct ubus_arg u_args[], i int dmubus_call_blocking(const char *obj, const char *method, struct ubus_arg u_args[], int u_args_size, json_object **req_res) { - int rc = 0; struct blob_buf bmsg; + int rc; memset(&bmsg, 0, sizeof(struct blob_buf)); prepare_blob_message(&bmsg, u_args, u_args_size); @@ -578,9 +556,8 @@ bool dmubus_object_method_exists(const char *object) return false; if (ubus_ctx == NULL) { - ubus_ctx = dm_libubus_init(); - if (ubus_ctx == NULL) - return false; + BBF_ERR("UBUS context is null"); + return false; } snprintf(ubus_object, sizeof(ubus_object), "%s", object); @@ -601,8 +578,17 @@ bool dmubus_object_method_exists(const char *object) return true; } -void dmubus_free() +void dm_ubus_init(struct dmctx *bbf_ctx) +{ + bbf_ctx->ubus_ctx = ubus_ctx = ubus_connect(NULL); +} + +void dm_ubus_free(struct dmctx *bbf_ctx) { dm_ubus_cache_entry_free(); - dm_libubus_free(); + + if (bbf_ctx->ubus_ctx) { + ubus_free(bbf_ctx->ubus_ctx); + bbf_ctx->ubus_ctx = ubus_ctx = NULL; + } } diff --git a/libbbfdm-api/legacy/dmubus.h b/libbbfdm-api/legacy/dmubus.h index cf5da981..7505eed6 100644 --- a/libbbfdm-api/legacy/dmubus.h +++ b/libbbfdm-api/legacy/dmubus.h @@ -62,7 +62,8 @@ int dmubus_call_blob_set(const char *obj, const char *method, json_object *value int dmubus_call_blob_msg_set(const char *obj, const char *method, struct blob_buf *blob_msg); -void dmubus_free(); +void dm_ubus_init(struct dmctx *bbf_ctx); +void dm_ubus_free(struct dmctx *bbf_ctx); bool dmubus_object_method_exists(const char *obj); diff --git a/libbbfdm-api/legacy/plugin/json_plugin.c b/libbbfdm-api/legacy/plugin/json_plugin.c index b5065126..c17b00b4 100644 --- a/libbbfdm-api/legacy/plugin/json_plugin.c +++ b/libbbfdm-api/legacy/plugin/json_plugin.c @@ -674,7 +674,7 @@ static char *handle_reference_value(struct dmctx *ctx, struct json_object *linke char *pref = NULL; adm_entry_get_reference_param(ctx, linker_path, key_value, &pref); - return pref; + return pref ? pref : dmstrdup(""); } else { char buf_ref[256 + 32] = {0}; @@ -2084,7 +2084,6 @@ static void create_parse_obj(DMOBJ *dm_entryobj, char *obj_path, json_object *jo dm_entryobj->nextdynamicobj = calloc(__INDX_DYNAMIC_MAX, sizeof(struct dm_dynamic_obj)); dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].idx_type = INDX_JSON_MOUNT; dm_entryobj->nextdynamicobj[INDX_LIBRARY_MOUNT].idx_type = INDX_LIBRARY_MOUNT; - dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].idx_type = INDX_SERVICE_MOUNT; } if (dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj == NULL) { @@ -2114,7 +2113,6 @@ static void create_parse_param(DMOBJ *dm_entryobj, char *obj_path, char *param, dm_entryobj->dynamicleaf = calloc(__INDX_DYNAMIC_MAX, sizeof(struct dm_dynamic_obj)); dm_entryobj->dynamicleaf[INDX_JSON_MOUNT].idx_type = INDX_JSON_MOUNT; dm_entryobj->dynamicleaf[INDX_LIBRARY_MOUNT].idx_type = INDX_LIBRARY_MOUNT; - dm_entryobj->dynamicleaf[INDX_SERVICE_MOUNT].idx_type = INDX_SERVICE_MOUNT; } if (dm_entryobj->dynamicleaf[INDX_JSON_MOUNT].nextleaf == NULL) { diff --git a/libbbfdm-api/version-2/CMakeLists.txt b/libbbfdm-api/version-2/CMakeLists.txt index 28442efd..d04c5520 100644 --- a/libbbfdm-api/version-2/CMakeLists.txt +++ b/libbbfdm-api/version-2/CMakeLists.txt @@ -8,7 +8,7 @@ FILE(GLOB BBFDM_API_SOURCES *.c) ADD_LIBRARY(bbfdm-api-v2 SHARED ${BBFDM_API_SOURCES}) -TARGET_LINK_LIBRARIES(bbfdm-api-v2 uci ubus) +TARGET_LINK_LIBRARIES(bbfdm-api-v2 uci ubus ubox) INSTALL(TARGETS bbfdm-api-v2 LIBRARY DESTINATION usr/lib) diff --git a/libbbfdm-api/version-2/bbfdm_ubus.c b/libbbfdm-api/version-2/bbfdm_ubus.c index aaf274c7..eff8b022 100644 --- a/libbbfdm-api/version-2/bbfdm_ubus.c +++ b/libbbfdm-api/version-2/bbfdm_ubus.c @@ -92,3 +92,19 @@ int bbfdm_ubus_invoke_async(struct ubus_context *ubus_ctx, const char *obj, cons ubus_complete_request_async(ubus_ctx, req); return 0; } + +int bbfdm_ubus_send_event(struct bbfdm_ctx *bbfdm_ctx, const char *obj, struct blob_attr *msg) +{ + if (!bbfdm_ctx || !bbfdm_ctx->ubus_ctx) { + BBFDM_ERR("Invalid context or UBUS context is NULL"); + return -1; + } + + int ret = ubus_send_event(bbfdm_ctx->ubus_ctx, obj, msg); + + if (ret != 0) { + BBFDM_ERR("UBUS send event failed for obj='%s', error code=%d", obj, ret); + } + + return ret; +} diff --git a/libbbfdm-api/version-2/bbfdm_ubus.h b/libbbfdm-api/version-2/bbfdm_ubus.h index 995c29ab..3e0f6ead 100644 --- a/libbbfdm-api/version-2/bbfdm_ubus.h +++ b/libbbfdm-api/version-2/bbfdm_ubus.h @@ -98,6 +98,38 @@ int bbfdm_ubus_invoke_async(struct ubus_context *ubus_ctx, const char *obj, cons bbfdm_free_ctx(&ctx); \ } while (0) +/** + * @brief Sends an event to a UBUS object. + * + * This function sends an event to the specified UBUS object with the provided + * message data. The event is transmitted using the UBUS system. + * + * @param[in] bbfdm_ctx Pointer to the BBFDM context. + * @param[in] obj Name of the UBUS object to send the event to. + * @param[in] msg Pointer to a `blob_attr` message containing event data. + * @return 0 on success, -1 on failure. + */ +int bbfdm_ubus_send_event(struct bbfdm_ctx *bbfdm_ctx, const char *obj, struct blob_attr *msg); + +/** + * @brief Sends an event to a UBUS object. + * + * This macro simplifies the process of initializing a context, sending an event, + * and cleaning up the context. + * + * @param obj The name of the UBUS object to send the event to. + * @param msg Pointer to a `blob_attr` message containing event data. + * @return Always returns 0. + */ +#define BBFDM_UBUS_SEND_EVENT(obj, msg) \ + do { \ + struct bbfdm_ctx ctx = {0}; \ + memset(&ctx, 0, sizeof(struct bbfdm_ctx)); \ + bbfdm_init_ctx(&ctx); \ + bbfdm_ubus_send_event(&ctx, obj, msg); \ + bbfdm_free_ctx(&ctx); \ + } while (0) + #ifdef __cplusplus } #endif diff --git a/libbbfdm-ubus/bbfdm-ubus.c b/libbbfdm-ubus/bbfdm-ubus.c index 03632877..e479609a 100644 --- a/libbbfdm-ubus/bbfdm-ubus.c +++ b/libbbfdm-ubus/bbfdm-ubus.c @@ -1,7 +1,7 @@ /* * bbfdm-ubus.c: bbfdm-ubus API to expose Data Model over ubus * - * Copyright (C) 2023-2024 IOPSYS Software Solutions AB. All rights reserved. + * Copyright (C) 2023-2025 IOPSYS Software Solutions AB. All rights reserved. * * Author: Vivek Dutta * Author: Amin Ben Romdhane @@ -24,16 +24,10 @@ #include "operate.h" #include "add_delete.h" #include "events.h" -#include "pretty_print.h" #include "get_helper.h" #include "plugin.h" -#define BBFDM_DEFAULT_MICROSERVICE_INPUT_PATH "/etc/bbfdm/services" -#define BBFDM_DEFAULT_MODULES_PATH "/usr/share/bbfdm" -#define BBFDM_DEFAULT_PLUGINS_PATH BBFDM_DEFAULT_MODULES_PATH"/plugins" -#define BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH BBFDM_DEFAULT_MODULES_PATH"/micro_services" - -LIST_HEAD(head_registered_service); +#define BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH "/usr/share/bbfdm/micro_services" // Global variables static void *deamon_lib_handle = NULL; @@ -42,12 +36,8 @@ static void bbfdm_ctx_cleanup(struct bbfdm_context *u) { bbf_global_clean(DEAMON_DM_ROOT_OBJ); - free_path_list(&u->config.list_objs); - - /* Main daemon */ - if (dm_is_micro_service() == false) { - free_services_from_list(&head_registered_service); - } + free_path_list(&u->linker_list); + free_path_list(&u->obj_list); /* DotSo Plugin */ bbfdm_free_dotso_plugin(u, &deamon_lib_handle); @@ -63,8 +53,10 @@ static bool is_sync_operate_cmd(bbfdm_data_t *data __attribute__((unused))) static void fill_optional_data(bbfdm_data_t *data, struct blob_attr *msg) { - struct blob_attr *attr; - size_t rem; + struct blob_attr *tb[1] = {0}; + const struct blobmsg_policy p[1] = { + { "proto", BLOBMSG_TYPE_STRING } + }; if (!data) return; @@ -74,19 +66,49 @@ static void fill_optional_data(bbfdm_data_t *data, struct blob_attr *msg) if (!msg) return; - blobmsg_for_each_attr(attr, msg, rem) { + blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg)); - if (is_str_eq(blobmsg_name(attr), "proto")) { - const char *val = blobmsg_get_string(attr); - data->bbf_ctx.dm_type = get_proto_type(val); - } + if (tb[0]) { + const char *val = blobmsg_get_string(tb[0]); + data->bbf_ctx.dm_type = get_proto_type(val); + BBF_DEBUG("Proto:|%s|", (data->bbf_ctx.dm_type == BBFDM_BOTH) ? "both" : (data->bbf_ctx.dm_type == BBFDM_CWMP) ? "cwmp" : "usp"); + } +} - if (is_str_eq(blobmsg_name(attr), "format")) - data->is_raw = is_str_eq(blobmsg_get_string(attr), "raw") ? true : false; +static char *get_value_by_reference_path(struct dmctx *ctx, char *reference_path) +{ + char path[MAX_DM_PATH] = {0}; + char key_name[256], key_value[256]; + char *reference_value = NULL; + regmatch_t pmatch[2]; + + if (!ctx || !reference_path) + return NULL; + + 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; } - char *proto = (data->bbf_ctx.dm_type == BBFDM_BOTH) ? "both" : (data->bbf_ctx.dm_type == BBFDM_CWMP) ? "cwmp" : "usp"; - BBF_DEBUG("Proto:|%s|, is_raw:|%d|", proto, data->is_raw); + snprintf(path + len, sizeof(path) - len, "*.%s", key_name); + + adm_entry_get_reference_param(ctx, path, key_value, &reference_value); + + return reference_value; } static void async_req_free(struct bbfdm_async_req *r) @@ -105,11 +127,9 @@ static void async_complete_cb(struct uloop_process *p, __attribute__((unused)) i ubus_send_reply(r->ctx, &r->req, bb->head); BBF_INFO("pid(%d) blob data sent raw(%zu)", r->process.pid, blob_raw_len(bb->head)); ubus_complete_deferred_request(r->ctx, &r->req, 0); - munmap(r->result, DEF_IPC_DATA_LEN); async_req_free(r); } - } static struct bbfdm_async_req *async_req_new(void) @@ -124,7 +144,7 @@ static struct bbfdm_async_req *async_req_new(void) return r; } -static int bbfdm_start_deferred(bbfdm_data_t *data, void (*EXEC_CB)(bbfdm_data_t *data, void *d), bool is_operate) +static int bbfdm_start_deferred(bbfdm_data_t *data, void (*EXEC_CB)(bbfdm_data_t *data, void *d)) { struct bbfdm_async_req *r = NULL; pid_t child; @@ -177,7 +197,6 @@ static int bbfdm_start_deferred(bbfdm_data_t *data, void (*EXEC_CB)(bbfdm_data_t r->ctx = data->ctx; r->process.pid = child; r->process.cb = async_complete_cb; - r->is_operate = is_operate; uloop_process_add(&r->process); ubus_defer_request(data->ctx, data->req, &r->req); return 0; @@ -194,26 +213,15 @@ err_out: static const struct blobmsg_policy dm_get_policy[] = { [DM_GET_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING }, - [DM_GET_PATHS] = { .name = "paths", .type = BLOBMSG_TYPE_ARRAY }, - [DM_GET_MAXDEPTH] = { .name = "maxdepth", .type = BLOBMSG_TYPE_INT32 }, [DM_GET_OPTIONAL] = { .name = "optional", .type = BLOBMSG_TYPE_TABLE}, }; -static int bbfdm_get_handler(struct ubus_context *ctx, struct ubus_object *obj __attribute__((unused)), - struct ubus_request_data *req, const char *method __attribute__((unused)), - struct blob_attr *msg) +static int bbfdm_get_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]; LIST_HEAD(paths_list); bbfdm_data_t data; - uint8_t maxdepth = 0; - 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 UBUS_STATUS_UNKNOWN_ERROR; - } memset(&data, 0, sizeof(bbfdm_data_t)); @@ -222,37 +230,20 @@ static int bbfdm_get_handler(struct ubus_context *ctx, struct ubus_object *obj _ return UBUS_STATUS_UNKNOWN_ERROR; } - if (!(tb[DM_GET_PATH]) && !(tb[DM_GET_PATHS])) + if (!tb[DM_GET_PATH]) return UBUS_STATUS_INVALID_ARGUMENT; - if (tb[DM_GET_PATH]) { - char *path = blobmsg_get_string(tb[DM_GET_PATH]); - add_path_list(path, &paths_list); - } - - if (tb[DM_GET_PATHS]) { - struct blob_attr *paths = tb[DM_GET_PATHS]; - struct blob_attr *path = NULL; - size_t rem; - - blobmsg_for_each_attr(path, paths, rem) { - char *path_str = blobmsg_get_string(path); - - add_path_list(path_str, &paths_list); - } - } - - if (tb[DM_GET_MAXDEPTH]) - maxdepth = blobmsg_get_u32(tb[DM_GET_MAXDEPTH]); + add_path_list(blobmsg_get_string(tb[DM_GET_PATH]), &paths_list); data.ctx = ctx; data.req = req; data.plist = &paths_list; - data.depth = maxdepth; fill_optional_data(&data, tb[DM_GET_OPTIONAL]); - bbfdm_get_value(&data, NULL); + BBF_INFO("ubus method|%s|, name|%s|", method, obj->name); + + bbfdm_get(&data, BBF_GET_VALUE); free_path_list(&paths_list); return 0; @@ -260,7 +251,6 @@ static int bbfdm_get_handler(struct ubus_context *ctx, struct ubus_object *obj _ static const struct blobmsg_policy dm_schema_policy[] = { [DM_SCHEMA_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING }, - [DM_SCHEMA_PATHS] = { .name = "paths", .type = BLOBMSG_TYPE_ARRAY }, [DM_SCHEMA_FIRST_LEVEL] = { .name = "first_level", .type = BLOBMSG_TYPE_BOOL}, [DM_SCHEMA_OPTIONAL] = { .name = "optional", .type = BLOBMSG_TYPE_TABLE}, }; @@ -274,39 +264,24 @@ static int bbfdm_schema_handler(struct ubus_context *ctx, struct ubus_object *ob bbfdm_data_t data; struct bbfdm_context *u; + memset(&data, 0, sizeof(bbfdm_data_t)); + 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; } - memset(&data, 0, sizeof(bbfdm_data_t)); - if (blobmsg_parse(dm_schema_policy, __DM_SCHEMA_MAX, tb, blob_data(msg), blob_len(msg))) { BBF_ERR("Failed to parse blob"); return UBUS_STATUS_UNKNOWN_ERROR; } - if (!(tb[DM_SCHEMA_PATH]) && !(tb[DM_SCHEMA_PATHS])) + if (!tb[DM_SCHEMA_PATH]) return UBUS_STATUS_INVALID_ARGUMENT; - if (tb[DM_SCHEMA_PATH]) { - char *path = blobmsg_get_string(tb[DM_SCHEMA_PATH]); - - add_path_list(path, &paths_list); - } - - if (tb[DM_SCHEMA_PATHS]) { - struct blob_attr *paths = tb[DM_GET_PATHS]; - struct blob_attr *path = NULL; - size_t rem; - - blobmsg_for_each_attr(path, paths, rem) { - char *path_str = blobmsg_get_string(path); - - add_path_list(path_str, &paths_list); - } - } + char *path = blobmsg_get_string(tb[DM_SCHEMA_PATH]); + add_path_list(path, &paths_list); fill_optional_data(&data, tb[DM_SCHEMA_OPTIONAL]); @@ -322,12 +297,16 @@ static int bbfdm_schema_handler(struct ubus_context *ctx, struct ubus_object *ob #ifdef BBF_SCHEMA_FULL_TREE data.bbf_ctx.isinfo = true; - bbfdm_get_supported_dm(&data); + bbfdm_get(&data, BBF_SCHEMA); #else - if (dm_type == BBFDM_CWMP) - bbfdm_get_names(&data); - else - bbfdm_get_supported_dm(&data); + if (dm_type == BBFDM_CWMP) { + char *service_name = strdup(u->config.service_name); + data.bbf_ctx.in_value = (dm_type == BBFDM_CWMP) ? service_name : NULL; + bbfdm_get(&data, BBF_GET_NAME); + FREE(service_name); + } else { + bbfdm_get(&data, BBF_SCHEMA); + } #endif free_path_list(&paths_list); @@ -336,8 +315,6 @@ static int bbfdm_schema_handler(struct ubus_context *ctx, struct ubus_object *ob static const struct blobmsg_policy dm_instances_policy[] = { [DM_INSTANCES_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING }, - [DM_INSTANCES_PATHS] = { .name = "paths", .type = BLOBMSG_TYPE_ARRAY }, - [DM_INSTANCES_FIRST_LEVEL] = { .name = "first_level", .type = BLOBMSG_TYPE_BOOL }, [DM_INSTANCES_OPTIONAL] = { .name = "optional", .type = BLOBMSG_TYPE_TABLE }, }; @@ -356,34 +333,19 @@ static int bbfdm_instances_handler(struct ubus_context *ctx, struct ubus_object return UBUS_STATUS_UNKNOWN_ERROR; } - if (!(tb[DM_INSTANCES_PATH]) && !(tb[DM_INSTANCES_PATHS])) + if (!tb[DM_INSTANCES_PATH]) return UBUS_STATUS_INVALID_ARGUMENT; - if (tb[DM_INSTANCES_PATH]) { - char *path = blobmsg_get_string(tb[DM_INSTANCES_PATH]); - add_path_list(path, &paths_list); - } - - if (tb[DM_INSTANCES_PATHS]) { - struct blob_attr *paths = tb[DM_INSTANCES_PATHS]; - struct blob_attr *path = NULL; - size_t rem; - - blobmsg_for_each_attr(path, paths, rem) { - char *path_str = blobmsg_get_string(path); - - add_path_list(path_str, &paths_list); - } - } + char *path = blobmsg_get_string(tb[DM_INSTANCES_PATH]); + add_path_list(path, &paths_list); data.ctx = ctx; data.req = req; - data.bbf_ctx.nextlevel = (tb[DM_INSTANCES_FIRST_LEVEL]) ? blobmsg_get_bool(tb[DM_INSTANCES_FIRST_LEVEL]) : false; data.plist = &paths_list; fill_optional_data(&data, tb[DM_INSTANCES_OPTIONAL]); - bbfdm_get_instances(&data); + bbfdm_get(&data, BBF_INSTANCES); free_path_list(&paths_list); return 0; @@ -402,7 +364,6 @@ int bbfdm_set_handler(struct ubus_context *ctx, struct ubus_object *obj, struct blob_attr *msg) { struct blob_attr *tb[__DM_SET_MAX] = {NULL}; - char path[PATH_MAX] = {'\0'}; bbfdm_data_t data; int fault = 0; LIST_HEAD(pv_list); @@ -420,22 +381,17 @@ int bbfdm_set_handler(struct ubus_context *ctx, struct ubus_object *obj, if (!tb[DM_SET_VALUE] && !tb[DM_SET_OBJ_PATH]) return UBUS_STATUS_INVALID_ARGUMENT; - snprintf(path, PATH_MAX, "%s", (char *)blobmsg_data(tb[DM_SET_PATH])); + char *path = blobmsg_get_string(tb[DM_SET_PATH]); + char *value = blobmsg_get_string(tb[DM_SET_VALUE]); + char *type = tb[DM_SET_TYPE] ? blobmsg_get_string(tb[DM_SET_TYPE]) : NULL; fill_optional_data(&data, tb[DM_SET_OPTIONAL]); BBF_INFO("ubus method|%s|, name|%s|, path(%s)", method, obj->name, path); blob_buf_init(&data.bb, 0); - bbf_init(&data.bbf_ctx); - data.ctx = ctx; - data.bbf_ctx.in_param = path; - - char *value = tb[DM_SET_VALUE] ? blobmsg_get_string(tb[DM_SET_VALUE]) : NULL; - char *type = tb[DM_SET_TYPE] ? blobmsg_get_string(tb[DM_SET_TYPE]) : NULL; - - fault = fill_pvlist_set(&data, path, value, type, tb[DM_SET_OBJ_PATH], &pv_list); + fault = fill_pvlist_set(path, value, type, tb[DM_SET_OBJ_PATH], &pv_list); if (fault) { BBF_ERR("Fault in fill pvlist set path |%s| : |%d|", data.bbf_ctx.in_param, fault); fill_err_code_array(&data, fault); @@ -445,20 +401,21 @@ int bbfdm_set_handler(struct ubus_context *ctx, struct ubus_object *obj, if (list_empty(&pv_list)) { BBF_ERR("Fault in fill pvlist set path |%s| : |list is empty|", data.bbf_ctx.in_param); fill_err_code_array(&data, USP_FAULT_INTERNAL_ERROR); - fault = USP_FAULT_INTERNAL_ERROR; goto end; } data.plist = &pv_list; + bbf_init(&data.bbf_ctx); fault = bbfdm_set_value(&data); -end: - if ((data.bbf_ctx.dm_type == BBFDM_BOTH) && (dm_is_micro_service() == false)) { + if (data.bbf_ctx.dm_type == BBFDM_BOTH) { bbf_entry_services(data.bbf_ctx.dm_type, (!fault) ? true : false, true); } bbf_cleanup(&data.bbf_ctx); + +end: free_pv_list(&pv_list); ubus_send_reply(ctx, req, data.bb.head); @@ -468,7 +425,7 @@ end: } static const struct blobmsg_policy dm_operate_policy[__DM_OPERATE_MAX] = { - [DM_OPERATE_COMMAND] = { .name = "command", .type = BLOBMSG_TYPE_STRING }, + [DM_OPERATE_COMMAND] = { .name = "path", .type = BLOBMSG_TYPE_STRING }, [DM_OPERATE_COMMAND_KEY] = { .name = "command_key", .type = BLOBMSG_TYPE_STRING }, [DM_OPERATE_INPUT] = { .name = "input", .type = BLOBMSG_TYPE_TABLE }, [DM_OPERATE_OPTIONAL] = { .name = "optional", .type = BLOBMSG_TYPE_TABLE }, @@ -512,7 +469,7 @@ static int bbfdm_operate_handler(struct ubus_context *ctx, struct ubus_object *o if (is_sync_operate_cmd(&data)) { bbfdm_operate_cmd(&data, NULL); } else { - bbfdm_start_deferred(&data, bbfdm_operate_cmd, true); + bbfdm_start_deferred(&data, bbfdm_operate_cmd); } FREE(str); @@ -567,7 +524,7 @@ int bbfdm_add_handler(struct ubus_context *ctx, struct ubus_object *obj, snprintf(path, PATH_MAX, "%s%s.", (char *)blobmsg_data(tb[DM_ADD_PATH]), data.bbf_ctx.addobj_instance); - fault = fill_pvlist_set(&data, path, NULL, NULL, tb[DM_ADD_OBJ_PATH], &pv_list); + fault = fill_pvlist_set(path, NULL, NULL, tb[DM_ADD_OBJ_PATH], &pv_list); if (fault) { BBF_ERR("Fault in fill pvlist set path |%s|", path); fill_err_code_array(&data, USP_FAULT_INTERNAL_ERROR); @@ -583,7 +540,7 @@ int bbfdm_add_handler(struct ubus_context *ctx, struct ubus_object *obj, } end: - if ((data.bbf_ctx.dm_type == BBFDM_BOTH) && (dm_is_micro_service() == false)) { + if (data.bbf_ctx.dm_type == BBFDM_BOTH) { bbf_entry_services(data.bbf_ctx.dm_type, (!fault) ? true : false, true); } @@ -651,7 +608,7 @@ int bbfdm_del_handler(struct ubus_context *ctx, struct ubus_object *obj, fault = create_del_response(&data); - if ((data.bbf_ctx.dm_type == BBFDM_BOTH) && (dm_is_micro_service() == false)) { + if (data.bbf_ctx.dm_type == BBFDM_BOTH) { bbf_entry_services(data.bbf_ctx.dm_type, (!fault) ? true : false, true); } @@ -664,44 +621,23 @@ int bbfdm_del_handler(struct ubus_context *ctx, struct ubus_object *obj, return 0; } -static int bbfdm_service_handler(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req __attribute__((unused)), const char *method, - struct blob_attr *msg) +int bbfdm_ref_path_handler(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) { - struct blob_buf bb; - void *array = NULL; - - memset(&bb, 0, sizeof(struct blob_buf)); - blob_buf_init(&bb, 0); - - array = blobmsg_open_array(&bb, "registered_service"); - get_list_of_registered_service(&head_registered_service, &bb); - blobmsg_close_array(&bb, array); - - ubus_send_reply(ctx, req, bb.head); - blob_buf_free(&bb); - - return 0; -} - -enum { - BBF_NOTIFY_NAME, - BBF_NOTIFY_PRAMS, - __BBF_NOTIFY_MAX, -}; - -static const struct blobmsg_policy dm_notify_event_policy[] = { - [BBF_NOTIFY_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING }, - [BBF_NOTIFY_PRAMS] = { .name = "input", .type = BLOBMSG_TYPE_ARRAY }, -}; - -static int bbfdm_notify_event(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req __attribute__((unused)), const char *method, - struct blob_attr *msg) -{ - struct blob_attr *tb[__BBF_NOTIFY_MAX] = {NULL}; - char method_name[256] = {0}; + struct blob_attr *tb[__DM_GET_MAX]; struct bbfdm_context *u; + struct pvNode *node = NULL; + struct blob_buf bb; + bool reference_value_found = false; + + 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) { @@ -709,17 +645,86 @@ static int bbfdm_notify_event(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_UNKNOWN_ERROR; } - if (blobmsg_parse(dm_notify_event_policy, __BBF_NOTIFY_MAX, tb, blob_data(msg), blob_len(msg))) { + 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; + + 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; + } + } + + 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[BBF_NOTIFY_NAME]) + if (!tb[DM_GET_PATH]) return UBUS_STATUS_INVALID_ARGUMENT; - BBF_INFO("ubus method|%s|, name|%s|", method, obj->name); - snprintf(method_name, sizeof(method_name), "%s.%s", DM_STRLEN(u->config.out_root_obj) ? u->config.out_root_obj : u->config.out_name, BBF_EVENT_NAME); - ubus_send_event(ctx, method_name, msg); + 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); + + ubus_send_reply(ctx, req, bb.head); + blob_buf_free(&bb); return 0; } @@ -732,8 +737,8 @@ 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("notify_event", bbfdm_notify_event, dm_notify_event_policy), - UBUS_METHOD_NOARG("service", bbfdm_service_handler), + UBUS_METHOD("reference_path", bbfdm_ref_path_handler, dm_get_policy), + UBUS_METHOD("reference_value", bbfdm_ref_value_handler, dm_get_policy), }; static struct ubus_object_type bbf_type = UBUS_OBJECT_TYPE("", bbf_methods); @@ -745,218 +750,8 @@ static struct ubus_object bbf_object = { .n_methods = ARRAY_SIZE(bbf_methods) }; -static int _fill_daemon_input_option(json_object *daemon_obj, bbfdm_config_t *config) -{ - char opt_val[MAX_DM_PATH] = {0}; - - if (!config || strlen(config->service_name) == 0) { - BBF_ERR("Invalid input options for service name \n"); - return -1; - } - - if (strchr(config->service_name, '/')) { // absolute path - char *srv_name = dmjson_get_value(daemon_obj, 1, "service_name"); - if (strlen(srv_name)) { - strncpyt(config->service_name, srv_name, sizeof(config->service_name)); - } - } - - // check if the service plugin is DotSO plugin - snprintf(opt_val, MAX_DM_PATH, "%s/%s.so", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); - if (!file_exists(opt_val)) { - snprintf(opt_val, MAX_DM_PATH, "%s/%s.json", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); - } - - if (!file_exists(opt_val)) { - BBF_ERR("Failed to load service plugin %s opt_val=%s\n", config->service_name, opt_val); - return -1; - } - - strncpyt(config->in_name, opt_val, sizeof(config->in_name)); - - snprintf(opt_val, MAX_DM_PATH, "%s/%s", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); - if (folder_exists(opt_val)) { - strncpyt(config->in_plugin_dir, opt_val, sizeof(config->in_plugin_dir)); - } - - return 0; -} - -static int _fill_daemon_output_options(json_object *daemon_obj, bbfdm_config_t *config) -{ - char *opt_val = NULL; - - if (!config || !daemon_obj) { - BBF_ERR("Invalid input options \n"); - return -1; - } - - opt_val = dmjson_get_value(daemon_obj, 2, "output", "root_obj"); - if (DM_STRLEN(opt_val)) { - strncpyt(config->out_root_obj, opt_val, sizeof(config->out_root_obj)); - } else { // for main process, there is no root obj - strncpyt(config->out_root_obj, BBFDM_DEFAULT_UBUS_OBJ, sizeof(config->out_root_obj)); - } - - opt_val = dmjson_get_value(daemon_obj, 2, "output", "name"); - if (strlen(opt_val)) { - snprintf(config->out_name, sizeof(config->out_name), "%s.%s", BBFDM_DEFAULT_UBUS_OBJ, opt_val); - } - - return 0; -} - -static int daemon_load_config_external_plugin(bbfdm_config_t *config) -{ - json_object *json_obj = NULL; - char json_path[MAX_DM_PATH] = {0}; - int err = 0; - - if (!config || !strlen(config->service_name)) - return -1; - - if (strchr(config->service_name, '/')) { // absolute path - strncpyt(json_path, config->service_name, MAX_DM_PATH); - } else { - snprintf(json_path, MAX_DM_PATH, "%s/%s.json", BBFDM_DEFAULT_MICROSERVICE_INPUT_PATH, config->service_name); - } - - json_obj = json_object_from_file(json_path); - if (!json_obj) { - BBF_ERR("Failed to read input %s file \n", json_path); - return -1; - } - - json_object *daemon_obj = dmjson_get_obj(json_obj, 1, "daemon"); - if (!daemon_obj) { - err = -1; - goto exit; - } - - err = _fill_daemon_input_option(daemon_obj, config); - if (err == -1) { - goto exit; - } - - err = _fill_daemon_output_options(daemon_obj, config); - -exit: - if (json_obj) { - json_object_put(json_obj); - } - - return err; -} - -static int daemon_load_config_internal_plugin(bbfdm_config_t *config) -{ - char opt_val[MAX_DM_PATH] = {0}; - - if (strlen(config->service_name) == 0 && dm_is_micro_service() == false) { // default value for main process - strncpyt(config->service_name, BBFDM_DEFAULT_UBUS_OBJ, sizeof(config->service_name)); - } - - if (!config || strlen(config->service_name) == 0) { - BBF_ERR("Invalid input options for service name \n"); - return -1; - } - - if(dm_is_micro_service() == false) { - strncpyt(config->in_plugin_dir, BBFDM_DEFAULT_PLUGINS_PATH, sizeof(config->in_plugin_dir)); - snprintf(config->out_name, sizeof(config->out_name), "%s", BBFDM_DEFAULT_UBUS_OBJ); - } else { - snprintf(opt_val, MAX_DM_PATH, "%s/%s", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); - if (folder_exists(opt_val)) { - strncpyt(config->in_plugin_dir, opt_val, sizeof(config->in_plugin_dir)); - } - - strncpyt(config->out_root_obj, BBFDM_DEFAULT_UBUS_OBJ, sizeof(config->out_root_obj)); - } - - return 0; -} - -static int daemon_load_services(const char *name, const char *json_path) -{ - json_object *json_obj = NULL; - json_object *jserv = NULL, *jservices = NULL; - int idx = 0, err = 0; - char buffer[MAX_DM_PATH/2] = {0}, service_name[MAX_DM_PATH] = {0}; - bool is_unified = false; - - if (!name || !json_path) { - BBF_ERR("Invalid service name or json file path"); - return -1; - } - - json_obj = json_object_from_file(json_path); - if (!json_obj) { - BBF_ERR("Failed to read input %s file for services", json_path); - return -1; - } - - json_object *daemon_obj = dmjson_get_obj(json_obj, 1, "daemon"); - if (!daemon_obj) { - err = -1; - goto exit; - } - - strncpyt(buffer, name, sizeof(buffer)); - // Remove .json from the end - size_t len = strlen(buffer) - strlen(".json"); - buffer[len] = '\0'; - - snprintf(service_name, sizeof(service_name), "%s.%s", BBFDM_DEFAULT_UBUS_OBJ, buffer); - string_to_bool(dmjson_get_value((daemon_obj), 1, "unified_daemon"), &is_unified); - - dmjson_foreach_obj_in_array(daemon_obj, jservices, jserv, idx, 1, "services") { - if (jserv) { - char parent[MAX_DM_PATH] = {0}, obj[MAX_DM_PATH] = {0}; - char *tmp; - - tmp = dmjson_get_value(jserv, 1, "parent_dm"); - replace_str(tmp, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX, parent, sizeof(parent)); - - tmp = dmjson_get_value(jserv, 1, "object"); - replace_str(tmp, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX, obj, sizeof(obj)); - - if ((DM_STRLEN(parent) == 0) || (DM_STRLEN(obj) == 0)) { - BBF_ERR("Skip empty registration parent_dm[%s] or object[%s]", parent, obj); - continue; - } - - tmp = dmjson_get_value(jserv, 1, "proto"); - BBF_INFO("Registering [%s :: %s :: %s :: %d :: %s]", service_name, parent, obj, is_unified, tmp); - load_service(DEAMON_DM_ROOT_OBJ, &head_registered_service, service_name, parent, obj, is_unified, get_proto_type(tmp)); - } - } -exit: - if (json_obj) { - json_object_put(json_obj); - } - - return err; -} - -static int daemon_load_config(bbfdm_config_t *config) -{ - int err = 0; - - if (INTERNAL_ROOT_TREE) { - err = daemon_load_config_internal_plugin(config); - BBF_INFO("Loading Config Internal plugin (%s)", config->service_name); - } else { - // This API will only be called with micro-services - err = daemon_load_config_external_plugin(config); - BBF_INFO("Loading Config External plugin (%s)", config->service_name); - } - - return err; -} - static int regiter_ubus_object(struct ubus_context *ctx) { - int ret; struct bbfdm_context *u; u = container_of(ctx, struct bbfdm_context, ubus_ctx); @@ -967,32 +762,123 @@ static int regiter_ubus_object(struct ubus_context *ctx) bbf_object.name = u->config.out_name; bbf_object.type->name = u->config.out_name; - if (dm_is_micro_service()) { - bbf_object.n_methods = bbf_object.n_methods - 2; - bbf_object.type->n_methods = bbf_object.n_methods; - ret = ubus_add_object(ctx, &bbf_object); - } else { - ret = ubus_add_object(ctx, &bbf_object); + + return ubus_add_object(ctx, &bbf_object); +} + +static void send_linker_response_event(struct ubus_context *ctx, const char *reference_path, const char *reference_value) +{ + struct blob_buf bb; + + memset(&bb, 0, sizeof(struct blob_buf)); + blob_buf_init(&bb, 0); + + bb_add_string(&bb, reference_path, reference_value ? reference_value : ""); + + ubus_send_event(ctx, "bbfdm.linker.response", bb.head); + blob_buf_free(&bb); +} + +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); + } else if (strcmp(type, "bbfdm.linker.request") == 0) { + //BBF_ERR("bbfdm.linker.request"); + + struct dmctx bbf_ctx = {0}; + struct blob_attr *tb[1] = {0}; + const struct blobmsg_policy p[1] = { + { "path", BLOBMSG_TYPE_STRING } + }; + + blobmsg_parse(p, 1, tb, blobmsg_data(msg), blobmsg_len(msg)); + + char *reference_path = tb[0] ? blobmsg_get_string(tb[0]) : ""; + + if (DM_STRLEN(reference_path) == 0) + return; + + if (!match_with_path_list(&u->obj_list, reference_path)) + return; + + if (present_in_pv_list(&u->linker_list, reference_path)) + return; + + bbf_init(&bbf_ctx); + + char *reference_value = get_value_by_reference_path(&bbf_ctx, reference_path); + + add_pv_list(reference_path, reference_value, NULL, &u->linker_list); + send_linker_response_event(ctx, reference_path, reference_value); + + bbf_cleanup(&bbf_ctx); } - return ret; } 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); - INIT_LIST_HEAD(&bbfdm_ctx->config.list_objs); } -static int daemon_load_data_model(struct bbfdm_context *daemon_ctx) +static int load_micro_service_config(bbfdm_config_t *config) +{ + char opt_val[MAX_DM_PATH] = {0}; + + if (!config || strlen(config->service_name) == 0) { + BBF_ERR("Invalid input options for service name"); + return -1; + } + + if (INTERNAL_ROOT_TREE == NULL) { + // This API will only be called with micro-services started with '-m' option + + snprintf(opt_val, MAX_DM_PATH, "%s/%s.so", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); + if (!file_exists(opt_val)) { + snprintf(opt_val, MAX_DM_PATH, "%s/%s.json", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); + } + + if (!file_exists(opt_val)) { + BBF_ERR("Failed to load service plugin %s opt_val=%s", config->service_name, opt_val); + return -1; + } + + strncpyt(config->in_name, opt_val, sizeof(config->in_name)); + } + + snprintf(opt_val, MAX_DM_PATH, "%s/%s", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); + if (folder_exists(opt_val)) { + strncpyt(config->in_plugin_dir, opt_val, sizeof(config->in_plugin_dir)); + } + + return 0; +} + +static int load_micro_service_data_model(struct bbfdm_context *daemon_ctx) { int err = 0; if (INTERNAL_ROOT_TREE) { BBF_INFO("Loading Data Model Internal plugin (%s)", daemon_ctx->config.service_name); - err = bbfdm_load_internal_plugin(daemon_ctx, INTERNAL_ROOT_TREE, &daemon_ctx->config, &DEAMON_DM_ROOT_OBJ); + err = bbfdm_load_internal_plugin(daemon_ctx, INTERNAL_ROOT_TREE, &DEAMON_DM_ROOT_OBJ); } else { BBF_INFO("Loading Data Model External plugin (%s)", daemon_ctx->config.service_name); - err = bbfdm_load_external_plugin(daemon_ctx, &deamon_lib_handle, &daemon_ctx->config, &DEAMON_DM_ROOT_OBJ); + err = bbfdm_load_external_plugin(daemon_ctx, &deamon_lib_handle, &DEAMON_DM_ROOT_OBJ); } if (err) @@ -1006,58 +892,10 @@ static int daemon_load_data_model(struct bbfdm_context *daemon_ctx) return -1; } - if (dm_is_micro_service()) { - if (DM_STRLEN(daemon_ctx->config.out_parent_dm) == 0) { - BBF_ERR("output parent dm not defined"); - return -1; - } - - if (list_empty(&daemon_ctx->config.list_objs)) { - BBF_ERR("output objects is not defined"); - return -1; - } - - if (DM_STRLEN(daemon_ctx->config.out_root_obj) == 0) { - BBF_ERR("output root obj not defined"); - return -1; - } - } - return 0; } -static int register_micro_services() -{ - DIR *dir_tmp = NULL; - struct dirent *d_file = NULL; - int err = 0; - - if (dm_is_micro_service() == true) { - return 0; - } - - sysfs_foreach_file(BBFDM_DEFAULT_MICROSERVICE_INPUT_PATH, dir_tmp, d_file) { - char config_name[512] = {0}; - - if (d_file->d_name[0] == '.') - continue; - - snprintf(config_name, sizeof(config_name), "%s/%s", BBFDM_DEFAULT_MICROSERVICE_INPUT_PATH, d_file->d_name); - - if (!file_exists(config_name) || !is_regular_file(config_name)) - continue; - - err = daemon_load_services(d_file->d_name, config_name); - if (err) { - BBF_ERR("Failed to load micro-services %s", d_file->d_name); - break; - } - } - if (dir_tmp) { - closedir (dir_tmp); - } - return err; -} +static struct ubus_event_handler bbfdm_linker_handler = { .cb = bbfdm_linker_cb }; int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx) { @@ -1074,22 +912,15 @@ int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx) bbfdm_ctx_init(bbfdm_ctx); - err = daemon_load_config(&bbfdm_ctx->config); + err = load_micro_service_config(&bbfdm_ctx->config); if (err) { - BBF_ERR("Failed to load config"); + BBF_ERR("Failed to load micro-service config"); return err; } - err = daemon_load_data_model(bbfdm_ctx); + err = load_micro_service_data_model(bbfdm_ctx); if (err) { - BBF_ERR("Failed to load data_model"); - return err; - } - - // Pre-load the services - err = register_micro_services(); - if (err) { - BBF_ERR("Failed to load micro-services"); + BBF_ERR("Failed to load micro-service data model"); return err; } @@ -1097,7 +928,11 @@ int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx) if (err != UBUS_STATUS_OK) return -1; - return register_events_to_ubus(&bbfdm_ctx->ubus_ctx, &bbfdm_ctx->event_handlers); + err = register_events_to_ubus(&bbfdm_ctx->ubus_ctx, &bbfdm_ctx->event_handlers); + if (err != 0) + return err; + + return ubus_register_event_handler(&bbfdm_ctx->ubus_ctx, &bbfdm_linker_handler, "bbfdm.linker.*"); } int bbfdm_ubus_regiter_free(struct bbfdm_context *bbfdm_ctx) @@ -1114,7 +949,6 @@ void bbfdm_ubus_set_service_name(struct bbfdm_context *bbfdm_ctx, const char *sr { strncpyt(bbfdm_ctx->config.service_name, srv_name, sizeof(bbfdm_ctx->config.service_name)); snprintf(bbfdm_ctx->config.out_name, sizeof(bbfdm_ctx->config.out_name), "%s.%s", BBFDM_DEFAULT_UBUS_OBJ, srv_name); - dm_set_micro_service(); } void bbfdm_ubus_set_log_level(int log_level) @@ -1126,6 +960,3 @@ void bbfdm_ubus_load_data_model(DM_MAP_OBJ *DynamicObj) { INTERNAL_ROOT_TREE = DynamicObj; } - -void bbfdm_schedule_instance_refresh_timer(struct ubus_context *ctx, int start_in_sec) {} // To be removed later - diff --git a/libbbfdm-ubus/bbfdm-ubus.h b/libbbfdm-ubus/bbfdm-ubus.h index 8fd1df59..3f82c0fb 100644 --- a/libbbfdm-ubus/bbfdm-ubus.h +++ b/libbbfdm-ubus/bbfdm-ubus.h @@ -13,25 +13,22 @@ struct bbfdm_async_req { struct ubus_context *ctx; struct ubus_request_data req; struct uloop_process process; - bool is_operate; void *result; }; typedef struct bbfdm_config { - struct list_head list_objs; // Micro-service list of objects to expose char service_name[32]; // Service name for micro-service identification - char in_type[32]; // Input type, Possible values: { 'JSON', 'DotSo' } - char in_name[128]; // plugin path - char in_plugin_dir[128]; // extra plugin directory path + char in_name[128]; // Service plugin path + char in_plugin_dir[128]; // Service extra/internal plugin directory path char out_name[128]; // Ubus name to use - char out_parent_dm[32]; // Parent device for micro-service - char out_root_obj[32]; // Ubus name to use as root data model } bbfdm_config_t; 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 { @@ -47,8 +44,6 @@ typedef struct bbfdm_data { struct list_head *plist; struct dmctx bbf_ctx; struct blob_buf bb; - uint8_t depth; - bool is_raw; } bbfdm_data_t; int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx); @@ -58,6 +53,4 @@ void bbfdm_ubus_set_service_name(struct bbfdm_context *bbfdm_ctx, const char *sr void bbfdm_ubus_set_log_level(int log_level); void bbfdm_ubus_load_data_model(DM_MAP_OBJ *DynamicObj); -void bbfdm_schedule_instance_refresh_timer(struct ubus_context *ctx, int start_in_sec); // To be removed later - #endif /* BBFDM_UBUS_H */ diff --git a/libbbfdm-ubus/common.c b/libbbfdm-ubus/common.c index 81df3e62..9666d5dc 100644 --- a/libbbfdm-ubus/common.c +++ b/libbbfdm-ubus/common.c @@ -12,64 +12,6 @@ #include "common.h" #include "get_helper.h" -bool get_boolean_string(char *value) -{ - if (!value) - return false; - - if (strncasecmp(value, "true", 4) == 0 || - value[0] == '1' || - strncasecmp(value, "on", 2) == 0 || - strncasecmp(value, "yes", 3) == 0 || - strncasecmp(value, "enabled", 7) == 0) - return true; - - return false; -} - -bool is_node_instance(char *path) -{ - bool ret = false; - char *rb = NULL; - - BBF_DEBUG("entry |%s|", path); - if (!path) - return false; - - if (path[0] == '[') { - char temp_char[MAX_DM_KEY_LEN] = {'\0'}; - size_t shift; - - rb = strchr(path, ']'); - shift = (size_t) labs(rb - path); - strncpyt(temp_char, path, shift + 1); - if (!match(temp_char, GLOB_EXPR, 0, NULL)) - ret = true; - } else { - if (strtol(path, NULL, 10)) - ret = true; - } - return ret; -} - -// RE utilities -int count_delim(const char *path) -{ - int count = 0; - char *token, *save; - char *pp = strdup(path); - - token = strtok_r(pp, ".", &save); - while (token) { - token = strtok_r(NULL, ".", &save); - count++; - } - free(pp); - - // count is the count of tokens - return (count - 1); -} - bool validate_msglen(bbfdm_data_t *data) { size_t data_len = blob_pad_len(data->bbf_ctx.bb.head); @@ -85,39 +27,6 @@ bool validate_msglen(bbfdm_data_t *data) return true; } -int get_dm_type(char *dm_type) -{ - if (dm_type == NULL) - return DMT_STRING; - - if (DM_STRCMP(dm_type, DMT_TYPE[DMT_STRING]) == 0) - return DMT_STRING; - else if (DM_STRCMP(dm_type, DMT_TYPE[DMT_UNINT]) == 0) - return DMT_UNINT; - else if (DM_STRCMP(dm_type, DMT_TYPE[DMT_INT]) == 0) - return DMT_INT; - else if (DM_STRCMP(dm_type, DMT_TYPE[DMT_UNLONG]) == 0) - return DMT_UNLONG; - else if (DM_STRCMP(dm_type, DMT_TYPE[DMT_LONG]) == 0) - return DMT_LONG; - else if (DM_STRCMP(dm_type, DMT_TYPE[DMT_BOOL]) == 0) - return DMT_BOOL; - else if (DM_STRCMP(dm_type, DMT_TYPE[DMT_TIME]) == 0) - return DMT_TIME; - else if (DM_STRCMP(dm_type, DMT_TYPE[DMT_HEXBIN]) == 0) - return DMT_HEXBIN; - else if (DM_STRCMP(dm_type, DMT_TYPE[DMT_BASE64]) == 0) - return DMT_BASE64; - else if (DM_STRCMP(dm_type, DMT_TYPE[DMT_COMMAND]) == 0) - return DMT_COMMAND; - else if (DM_STRCMP(dm_type, DMT_TYPE[DMT_EVENT]) == 0) - return DMT_EVENT; - else - return DMT_STRING; - - return DMT_STRING; -} - // glibc doesn't guarantee a 0 termianted string on strncpy // strncpy with always 0 terminated string void strncpyt(char *dst, const char *src, size_t n) diff --git a/libbbfdm-ubus/common.h b/libbbfdm-ubus/common.h index 472f9d51..5057f6b7 100644 --- a/libbbfdm-ubus/common.h +++ b/libbbfdm-ubus/common.h @@ -17,17 +17,8 @@ #include #include "bbfdm-ubus.h" -#define STRINGIFY(x) #x -#define TO_STR(x) STRINGIFY(x) - -#define ROOT_NODE "Device." -#define BBF_EVENT_NAME "event" - -#define MAX_DM_KEY_LEN 256 #define MAX_DM_PATH 1024 #define MAX_DM_VALUE 4096 -#define DM_VALUE_SEP "," -#define DELIM '.' #ifdef BBFDM_MAX_MSG_LEN #define DEF_IPC_DATA_LEN (BBFDM_MAX_MSG_LEN - 128) // Configured Len - 128 bytes @@ -35,21 +26,11 @@ #define DEF_IPC_DATA_LEN (10 * 1024 * 1024 - 128) // 10M - 128 bytes #endif -#define GLOB_CHAR "[[+*]+" -#define GLOB_EXPR "[=><]+" - extern DMOBJ *DEAMON_DM_ROOT_OBJ; extern DM_MAP_OBJ *INTERNAL_ROOT_TREE; -bool is_node_instance(char *path); -int count_delim(const char *path); - -bool get_boolean_string(char *value); bool validate_msglen(bbfdm_data_t *data); -int get_dm_type(char *dm_type); - -int get_resolved_paths(struct dmctx *bbf_ctx, char *qpath, struct list_head *resolved_paths); void strncpyt(char *dst, const char *src, size_t n); #endif /* COMMON_H */ diff --git a/libbbfdm-ubus/events.c b/libbbfdm-ubus/events.c index d6aee3c2..9163bcda 100644 --- a/libbbfdm-ubus/events.c +++ b/libbbfdm-ubus/events.c @@ -90,7 +90,6 @@ static void bbfdm_event_handler(struct ubus_context *ctx, struct ubus_event_hand .iscommand = false, .isevent = true, .isinfo = false, - .disable_mservice_browse = true, .dm_type = BBFDM_USP }; @@ -107,7 +106,7 @@ static void bbfdm_event_handler(struct ubus_context *ctx, struct ubus_event_hand if (!e_args) goto end; - snprintf(e_args->method_name, sizeof(e_args->method_name), "%s.%s", DM_STRLEN(u->config.out_root_obj) ? u->config.out_root_obj : u->config.out_name, BBF_EVENT_NAME); + snprintf(e_args->method_name, sizeof(e_args->method_name), "%s.event", BBFDM_DEFAULT_UBUS_OBJ); e_args->blob_data = (struct blob_attr *)calloc(1, blob_data_len); @@ -155,7 +154,6 @@ int register_events_to_ubus(struct ubus_context *ctx, struct list_head *ev_list) .iscommand = false, .isevent = true, .isinfo = false, - .disable_mservice_browse = true, .dm_type = BBFDM_USP }; diff --git a/libbbfdm-ubus/get.c b/libbbfdm-ubus/get.c index 57963c23..4d8ff690 100644 --- a/libbbfdm-ubus/get.c +++ b/libbbfdm-ubus/get.c @@ -10,988 +10,48 @@ */ #include "common.h" -#include "get.h" #include "get_helper.h" -#include "pretty_print.h" #include -enum operation { - OPER_EQUAL_EQUAL, - OPER_NOT_EQUAL, - OPER_LESS_THAN_EQUAL, - OPER_GREATER_THAN_EQUAL, - OPER_LESS_THAN, - OPER_GREATER_THAN, -}; - -static const char * const operations[] = { - [OPER_EQUAL_EQUAL] = "==", - [OPER_NOT_EQUAL] = "!=", - [OPER_LESS_THAN_EQUAL] = "<=", - [OPER_GREATER_THAN_EQUAL] = ">=", - [OPER_LESS_THAN] = "<", - [OPER_GREATER_THAN] = ">" -}; - -static bool get_base_path(const char *query_path, char *base_path) +void bbfdm_get(bbfdm_data_t *data, int method) { - size_t i, j, qlen; - bool found = false; - char ch; - - if (base_path == NULL) - return false; - - base_path[0] = '\0'; - - if (strncmp(query_path, ROOT_NODE, strlen(ROOT_NODE)) != 0) - return false; - - qlen = DM_STRLEN(query_path); - - for (i = 0; i < qlen; i++) { - switch (query_path[i]) { - case '[': - if (query_path[i - 1] != '.') - return false; - - for (j = i + 1; j < qlen; j++) { - ch = query_path[j]; - if ((ch == '>') || - (ch == '<') || - (ch == '=')) { - found = true; - break; - } - if (query_path[j] == ']') { - i = j; - break; - } - } - break; - } - - if (found) - break; - } - - strncpyt(base_path, query_path, i + 1); - return true; -} - -static bool get_next_param(char *qPath, size_t *pos, char *param) -{ - size_t qlen, i; - bool found; - - if (qPath == NULL || pos == NULL || param == NULL) - return false; - - qlen = DM_STRLEN(qPath); - if (*pos >= qlen || *pos >= MAX_DM_PATH || qlen >= MAX_DM_PATH) - return false; - - param[0] = '\0'; - found = false; - for (i = *pos; i < qlen; i++) { - switch (qPath[i]) { - case '[': - while (i < qlen) { - if (qPath[++i] == ']') - break; - } - if (qPath[++i] != '.') { - BBF_ERR("No dot after search parameters"); - return false; - } - // skip the dot - i++; - found = true; - break; - case '.': - i++; - found = true; - break; - } - - if (found) - break; - } - - if (i == qlen) - strncpyt(param, qPath + *pos, i - *pos + 1); - else - strncpyt(param, qPath + *pos, i - *pos); - - *pos = i; - - // removing last . from param - qlen = DM_STRLEN(param); - if (qlen > 0) { - if (param[qlen - 1] == '.') - param[qlen - 1] = '\0'; - } - - return true; -} - -static bool is_present_in_datamodel(struct dmctx *bbf_ctx, char *path) -{ - struct blob_attr *cur = NULL; - size_t plen = 0, rem = 0; - bool found = false; - - BBF_DEBUG("path(%s)", path); - plen = DM_STRLEN(path); - - blobmsg_for_each_attr(cur, bbf_ctx->bb.head, rem) { - struct blob_attr *tb[1] = {0}; - const struct blobmsg_policy p[1] = { - { "path", BLOBMSG_TYPE_STRING } - }; - - blobmsg_parse(p, 1, tb, blobmsg_data(cur), blobmsg_len(cur)); - - char *name = (tb[0]) ? blobmsg_get_string(tb[0]) : ""; - - if (strncmp(name, path, plen) == 0) { - found = true; - break; - } - } - - return found; -} - -static int seperator(char *token, char *para, enum operation *oper, char *value) -{ - char *ptr; - size_t plen; - bool found; - uint8_t i, op_count; - - // handle ==, !=, <=, >= - if (token == NULL || para == NULL || - oper == NULL || value == NULL) - return USP_FAULT_INTERNAL_ERROR; - - found = false; - op_count = ARRAY_SIZE(operations); - for (i = 0; i < op_count; i++) { - ptr = strstr(token, operations[i]); - if (ptr) { - *oper = i; - plen = (size_t)labs(ptr - token); - ptr += DM_STRLEN(operations[i]); - found = true; - break; - } - } - - if (found) { - strncpyt(para, token, plen + 1); - plen = DM_STRLEN(ptr); - strncpyt(value, ptr, plen + 1); - return 0; - } - - return USP_FAULT_INVALID_PATH_SYNTAX; -} - -static bool get_instance(char *path, size_t start, char *instance) -{ - char *ptr; - size_t plen, path_len; - - if (instance == NULL) - return false; - - path_len = DM_STRLEN(path); - if (path_len <= start) - return false; - - ptr = strchr(path + start, '.'); - - if (ptr == NULL) - return false; - - plen = (size_t)labs(ptr - path) - start; - if (plen > path_len) - return false; - - strncpyt(instance, path + start, plen + 1); - if (strtol(instance, NULL, 10) == 0) { - if (instance[0] != '[') - return false; - } - - return true; -} - -static void handle_special_escape_sequence(char *value, char *buff, size_t buff_len) -{ - size_t i, len, j; - - if (buff == NULL) - return; - - len = DM_STRLEN(value); - j = 0; - for (i = 0; i < len && j < buff_len-1; ++i) { - if (value[i] == '%' && len > i + 2) { - if (value[i + 1] == '2') { - if (value[i + 2] == '5') { - buff[j++] = '%'; - i += 2; - continue; - } else if (value[i + 2] == '2') { - buff[j++] = '"'; - i += 2; - continue; - } - } - } - buff[j++] = value[i]; - } - buff[j] = '\0'; - - BBF_DEBUG("value(%s), new_value(%s)", value, buff); -} - -static bool handle_string(char *v1, char *v2, enum operation op, int *fault) -{ - char temp[MAX_DM_VALUE]; - - if (!fault) - return false; - - if (v1 == NULL || v2 == NULL) { - return false; - } - - int v2_len = DM_STRLEN(v2); - if (v2_len == 0) { - *fault = USP_FAULT_INVALID_PATH_SYNTAX; - return false; - } - - if ((v2[0] == '"' && v2[v2_len - 1] != '"') || - (v2[0] != '"' && v2[v2_len - 1] == '"')) { - *fault = USP_FAULT_INVALID_PATH_SYNTAX; - return false; - } - - bool has_quote = v2[0] == '"'; - - // Check for %22 and %25 special escape sequences - char buff[MAX_DM_VALUE] = {0}; - handle_special_escape_sequence(v2, buff, MAX_DM_VALUE); - - snprintf(temp, MAX_DM_VALUE, "%s%s%s", has_quote ? "\"": "", v1, has_quote ? "\"": ""); - - switch (op) { - case OPER_EQUAL_EQUAL: - return !strcmp(temp, buff); - case OPER_NOT_EQUAL: - return !!strcmp(temp, buff); - case OPER_LESS_THAN: - case OPER_GREATER_THAN: - case OPER_LESS_THAN_EQUAL: - case OPER_GREATER_THAN_EQUAL: - *fault = USP_FAULT_INVALID_PATH_SYNTAX; - return false; - } - - return false; -} - -static bool handle_uint(char *v1, char *v2, enum operation op, int *fault) -{ - uint32_t ui1, ui2; - - if (!fault) - return false; - - if (v1 == NULL || v2 == NULL) - return false; - - ui1 = (uint32_t) strtoul(v1, NULL, 10); - ui2 = (uint32_t) strtoul(v2, NULL, 10); - - if ((ui1 == 0 && v1[0] != '0') || - (ui2 == 0 && v2[0] != '0')) { - *fault = USP_FAULT_INVALID_TYPE; - return false; - } - - switch (op) { - case OPER_EQUAL_EQUAL: - return (ui1 == ui2); - case OPER_NOT_EQUAL: - return (ui1 != ui2); - case OPER_LESS_THAN: - return (ui1 < ui2); - case OPER_GREATER_THAN: - return (ui1 > ui2); - case OPER_LESS_THAN_EQUAL: - return (ui1 <= ui2); - case OPER_GREATER_THAN_EQUAL: - return (ui1 >= ui2); - } - - return false; -} - -static bool handle_int(char *v1, char *v2, enum operation op, int *fault) -{ - int32_t i1, i2; - - if (!fault) - return false; - - if (v1 == NULL || v2 == NULL) - return false; - - i1 = (int32_t) strtol(v1, NULL, 10); - i2 = (int32_t) strtol(v2, NULL, 10); - - if ((i1 == 0 && v1[0] != '0') || - (i2 == 0 && v2[0] != '0')) { - *fault = USP_FAULT_INVALID_TYPE; - return false; - } - - switch (op) { - case OPER_EQUAL_EQUAL: - return (i1 == i2); - case OPER_NOT_EQUAL: - return (i1 != i2); - case OPER_LESS_THAN: - return (i1 < i2); - case OPER_GREATER_THAN: - return (i1 > i2); - case OPER_LESS_THAN_EQUAL: - return (i1 <= i2); - case OPER_GREATER_THAN_EQUAL: - return (i1 >= i2); - } - - return false; -} - -static bool handle_unlong(char *v1, char *v2, enum operation op, int *fault) -{ - uint64_t ul1, ul2; - - if (!fault) - return false; - - if (v1 == NULL || v2 == NULL) - return false; - - ul1 = (uint64_t) strtoll(v1, NULL, 10); - ul2 = (uint64_t) strtoll(v2, NULL, 10); - - if ((ul1 == 0 && v1[0] != '0') || - (ul2 == 0 && v2[0] != '0')) { - *fault = USP_FAULT_INVALID_TYPE; - return false; - } - - switch (op) { - case OPER_EQUAL_EQUAL: - return (ul1 == ul2); - case OPER_NOT_EQUAL: - return (ul1 != ul2); - case OPER_LESS_THAN: - return (ul1 < ul2); - case OPER_GREATER_THAN: - return (ul1 > ul2); - case OPER_LESS_THAN_EQUAL: - return (ul1 <= ul2); - case OPER_GREATER_THAN_EQUAL: - return (ul1 >= ul2); - } - - return false; -} - -static bool handle_long(char *v1, char *v2, enum operation op, int *fault) -{ - int64_t l1, l2; - - if (!fault) - return false; - - if (v1 == NULL || v2 == NULL) - return false; - - l1 = (int64_t) strtoll(v1, NULL, 10); - l2 = (int64_t) strtoll(v2, NULL, 10); - - if ((l1 == 0 && v1[0] != '0') || - (l2 == 0 && v2[0] != '0')) { - *fault = USP_FAULT_INVALID_TYPE; - return false; - } - - switch (op) { - case OPER_EQUAL_EQUAL: - return (l1 == l2); - case OPER_NOT_EQUAL: - return (l1 != l2); - case OPER_LESS_THAN: - return (l1 < l2); - case OPER_GREATER_THAN: - return (l1 > l2); - case OPER_LESS_THAN_EQUAL: - return (l1 <= l2); - case OPER_GREATER_THAN_EQUAL: - return (l1 >= l2); - } - - return false; -} - -static bool handle_bool(char *v1, char *v2, enum operation op, int *fault) -{ - bool vb1, vb2; - - if (!fault) - return false; - - if (v1 == NULL || v2 == NULL) - return false; - - vb1 = get_boolean_string(v1); - vb2 = get_boolean_string(v2); - - switch (op) { - case OPER_EQUAL_EQUAL: - return (vb1 == vb2); - case OPER_NOT_EQUAL: - return (vb1 != vb2); - case OPER_LESS_THAN: - case OPER_GREATER_THAN: - case OPER_LESS_THAN_EQUAL: - case OPER_GREATER_THAN_EQUAL: - *fault = USP_FAULT_INVALID_PATH_SYNTAX; - return false; - } - - return false; -} - -static bool handle_time(char *v1, char *v2, enum operation op, const int *fault) -{ - struct tm tm1, tm2; - char *tmp; - time_t t1, t2; - double sec; - - if (!fault) - return false; - - if (v1 == NULL || v2 == NULL) - return false; - - memset(&tm1, 0, sizeof(t1)); - memset(&tm2, 0, sizeof(t2)); - - tmp = strptime(v1, "%Y-%m-%dT%H:%M:%S", &tm1); - if (tmp == NULL) - return USP_FAULT_INVALID_TYPE; - - tmp = strptime(v2, "%Y-%m-%dT%H:%M:%S", &tm2); - if (tmp == NULL) - return USP_FAULT_INVALID_TYPE; - - t1 = timegm(&tm1); - t2 = timegm(&tm2); - - sec = difftime(t1, t2); - switch (op) { - case OPER_EQUAL_EQUAL: - return (sec == 0); - case OPER_NOT_EQUAL: - return (sec != 0); - case OPER_LESS_THAN: - return (sec < 0); - case OPER_GREATER_THAN: - return (sec > 0); - case OPER_LESS_THAN_EQUAL: - return (sec <= 0); - case OPER_GREATER_THAN_EQUAL: - return (sec >= 0); - } - - return false; -} - -static bool handle_hexbin(const char *v1, const char *v2, enum operation op __attribute__((unused)), - int *fault) -{ - if (v1 == NULL || v2 == NULL) - return false; - - *fault = USP_FAULT_INVALID_PATH_SYNTAX; - return false; -} - -static bool check_values(char *val_type, char *val1, char *val2, enum operation oper, int *fault) -{ - bool result = false; - - BBF_DEBUG("type(%s), val1(%s), Val2(%s), Oper(%d)", val_type, val1, val2, oper); - switch (get_dm_type(val_type)) { - case DMT_STRING: - result = handle_string(val1, val2, oper, fault); - break; - case DMT_UNINT: - result = handle_uint(val1, val2, oper, fault); - break; - case DMT_INT: - result = handle_int(val1, val2, oper, fault); - break; - case DMT_UNLONG: - result = handle_unlong(val1, val2, oper, fault); - break; - case DMT_LONG: - result = handle_long(val1, val2, oper, fault); - break; - case DMT_BOOL: - result = handle_bool(val1, val2, oper, fault); - break; - case DMT_TIME: - result = handle_time(val1, val2, oper, fault); - break; - case DMT_HEXBIN: - result = handle_hexbin(val1, val2, oper, fault); - break; - } - - return result; -} - -static int search_n_apply(char *bPath, char *para, enum operation oper, char *value, struct list_head *fltrd, struct list_head *resolved_plist) -{ - char temp[MAX_DM_PATH * 2] = {0}; - struct pvNode *pv = NULL; - size_t blen; + struct pathNode *pn = NULL; int fault = 0; - blen = DM_STRLEN(bPath); - - if (!list_empty(resolved_plist)) { - struct pathNode *iter, *node; - - list_for_each_entry_safe(iter, node, resolved_plist, list) { - bool is_present = false; - - snprintf(temp, sizeof(temp), "%s%s", iter->path, para); - - list_for_each_entry(pv, fltrd, list) { - if (strcmp(pv->param, temp) == 0) { - is_present = true; - break; - } - } - - if (!is_present) { - list_del(&iter->list); - free(iter); - continue; - } - - if (check_values(pv->type, pv->val, value, oper, &fault) == false) { - list_del(&iter->list); - free(iter); - if (fault != 0) - return fault; - } - } - } else { - list_for_each_entry(pv, fltrd, list) { - char inst[MAX_DM_KEY_LEN]; - - if (strncmp(pv->param, bPath, blen) != 0) - continue; - - if (get_instance(pv->param, blen, inst) == false) - continue; - - snprintf(temp, sizeof(temp), "%s%s.%s", bPath, inst, para); - - if (strcmp(pv->param, temp) != 0) - continue; - - if (check_values(pv->type, pv->val, value, oper, &fault)) { - snprintf(temp, sizeof(temp), "%s%s.", bPath, inst); - add_path_list(temp, resolved_plist); // Resolved List - } else { - if (fault) - return fault; - } - } - } - - return fault; -} - -static int solve_all_filters(struct dmctx *bbf_ctx, char *bPath, char *param, struct list_head *resolved_plist) -{ - struct blob_attr *cur = NULL; - char *token = NULL, *save = NULL; - size_t blen = 0, rem = 0; - int ret = 0; - - LIST_HEAD(pv_local); - LIST_HEAD(plist_local); - - BBF_INFO("## Basepath(%s), param(%s)", bPath, param); - - // Use shorter list for rest of the operation - blen = DM_STRLEN(bPath); - - blobmsg_for_each_attr(cur, bbf_ctx->bb.head, rem) { - struct blob_attr *tb[3] = {0}; - const struct blobmsg_policy p[3] = { - { "path", BLOBMSG_TYPE_STRING }, - { "data", BLOBMSG_TYPE_STRING }, - { "type", BLOBMSG_TYPE_STRING } - }; - - blobmsg_parse(p, 3, tb, blobmsg_data(cur), blobmsg_len(cur)); - - char *name = (tb[0]) ? blobmsg_get_string(tb[0]) : ""; - char *data = (tb[1]) ? blobmsg_get_string(tb[1]) : ""; - char *type = (tb[2]) ? blobmsg_get_string(tb[2]) : ""; - - if (strncmp(name, bPath, blen) == 0) { - add_pv_list(name, data, type, &pv_local); - } - } - - token = strtok_r(param, "&&", &save); - while (token) { - enum operation oper; - char para[MAX_DM_KEY_LEN] = {0}; - char value[MAX_DM_VALUE] = {0}; - - ret = seperator(token, para, &oper, value); - if (ret != 0) - break; - - BBF_INFO("Filter Para(%s), oper(%d), Val(%s)", para, oper, value); - - if (match(para, "[*]+", 0, NULL)) - ret = USP_FAULT_INVALID_TYPE; - else - ret = search_n_apply(bPath, para, oper, value, &pv_local, &plist_local); - - if (ret != 0) - break; - - if (list_empty(&plist_local)) - break; - - token = strtok_r(NULL, "&&", &save); - } - - if (ret == 0) { - struct pathNode *iter; - - list_for_each_entry(iter, &plist_local, list) { - add_path_list(iter->path, resolved_plist); - } - } - - free_path_list(&plist_local); - free_pv_list(&pv_local); - return ret; -} - -static void refresh_path_list(struct list_head *path_list, struct list_head *plist_local) -{ - struct pathNode *iter; - - free_path_list(path_list); - - list_for_each_entry(iter, plist_local, list) { - add_path_list(iter->path, path_list); - } -} - -static int resolve_path(struct dmctx *bbf_ctx, char *qPath, size_t pos, struct list_head *resolved_plist) -{ - char temp[MAX_DM_PATH + 5] = {0}; - char param[MAX_DM_PATH] = {0}; - size_t plen; - struct pathNode *ptr; - int fault; - bool check = true; - size_t start = 0; - bool non_leaf = false; - - LIST_HEAD(plist_local); - - start = pos; - size_t qPath_len = DM_STRLEN(qPath); - if (start >= qPath_len) - return 0; - - if (list_empty(resolved_plist)) - return 0; - - BBF_INFO("Entry Len :: %zu & qPath :: %s", start, qPath); - - if (strchr(qPath+start, '.') != NULL) - non_leaf = true; - - if (get_next_param(qPath, &start, param) == false) - return USP_FAULT_INVALID_PATH_SYNTAX; - - plen = DM_STRLEN(param); - BBF_DEBUG("PARAM ::(%s) pos ::(%zu)", param, start); - - fault = 0; - list_for_each_entry(ptr, resolved_plist, list) { - - size_t len = DM_STRLEN(ptr->path); - if (len == 0) - continue; - - snprintf(temp, sizeof(temp), "%s%s", ptr->path, (ptr->path[len - 1] != '.') ? "." : ""); - - if (param[0] == '[') { - param[plen-1] = 0; - fault = solve_all_filters(bbf_ctx, temp, param+1, &plist_local); - } else { - char buff[MAX_DM_VALUE] = {0}; - if (non_leaf) - snprintf(buff, sizeof(buff), "%s%s.", temp, param); - else - snprintf(buff, sizeof(buff), "%s%s", temp, param); - - check = is_present_in_datamodel(bbf_ctx, buff); - if (check) - add_path_list(buff, &plist_local); - } - - if (fault) { - free_path_list(&plist_local); - return fault; - } - } - - if (check == false && list_empty(&plist_local)) { - free_path_list(&plist_local); - return bbf_fault_map(bbf_ctx, FAULT_9005); - } - - refresh_path_list(resolved_plist, &plist_local); - free_path_list(&plist_local); - - return resolve_path(bbf_ctx, qPath, start, resolved_plist); -} - -int get_resolved_paths(struct dmctx *bbf_ctx, char *qpath, struct list_head *resolved_paths) -{ - char bpath[MAX_DM_PATH] = {0}; - int fault = 0; - - if (get_base_path(qpath, bpath)) { - size_t pos = 0; - - pos = strlen(bpath); - BBF_INFO("Base Path :: |%s| Pos :: |%zu|", bpath, pos); - - bbf_ctx->in_param = bpath; - - fault = bbfdm_cmd_exec(bbf_ctx, BBF_GET_VALUE); - - if (!fault) { - add_path_list(bpath, resolved_paths); - fault = resolve_path(bbf_ctx, qpath, pos, resolved_paths); - } - } else { - BBF_INFO("Not able to get base path"); - fault = bbf_fault_map(bbf_ctx, FAULT_9005); - } - - if (fault) - BBF_WARNING("qpath(%s), fault(%d)", qpath, fault); - - return fault; -} - -void bbfdm_get_value(bbfdm_data_t *data, void *output) -{ - struct pathNode *pn; - void *array = NULL; - int fault = 0; - - memset(&data->bb, 0, sizeof(struct blob_buf)); - bbf_init(&data->bbf_ctx); - blob_buf_init(&data->bb, 0); - if (data->is_raw) - array = blobmsg_open_array(&data->bb, "results"); + void *array = blobmsg_open_array(&data->bbf_ctx.bb, "results"); list_for_each_entry(pn, data->plist, list) { bbf_sub_init(&data->bbf_ctx); - LIST_HEAD(resolved_list); - if (DM_STRLEN(pn->path) == 0) - snprintf(pn->path, MAX_DM_PATH, "%s", ROOT_NODE); - - fault = get_resolved_paths(&data->bbf_ctx, pn->path, &resolved_list); + data->bbf_ctx.in_param = pn->path; + fault = bbfdm_cmd_exec(&data->bbf_ctx, method); if (fault) { - data->bbf_ctx.in_param = pn->path; - fill_err_code_table(data, fault); - } else { - BBF_INFO("Preparing result for(%s)", pn->path); - - data->bbf_ctx.in_param = pn->path; - - if (data->is_raw) { - prepare_raw_result(&data->bb, &data->bbf_ctx, &resolved_list); - } else { - prepare_pretty_result(data->depth, &data->bb, &data->bbf_ctx, &resolved_list); - } + void *table = blobmsg_open_table(&data->bbf_ctx.bb, NULL); + bb_add_string(&data->bbf_ctx.bb, "path", data->bbf_ctx.in_param); + blobmsg_add_u32(&data->bbf_ctx.bb, "fault", bbf_fault_map(&data->bbf_ctx, fault)); + bb_add_string(&data->bbf_ctx.bb, "fault_msg", data->bbf_ctx.fault_msg); + blobmsg_close_table(&data->bbf_ctx.bb, table); } - free_path_list(&resolved_list); bbf_sub_cleanup(&data->bbf_ctx); } - if (data->is_raw) - blobmsg_close_array(&data->bb, array); + blobmsg_close_array(&data->bbf_ctx.bb, array); - if (!validate_msglen(data)) + if (!validate_msglen(data)) { BBF_ERR("IPC failed for path(%s)", data->bbf_ctx.in_param); + } - if (output) - memcpy(output, data->bb.head, blob_pad_len(data->bb.head)); - else - ubus_send_reply(data->ctx, data->req, data->bb.head); - - // free - blob_buf_free(&data->bb); + if (data->ctx && data->req) { + ubus_send_reply(data->ctx, data->req, data->bbf_ctx.bb.head); + } // Apply all bbfdm changes dmuci_commit_bbfdm(); bbf_cleanup(&data->bbf_ctx); } - -void bbfdm_get_names(bbfdm_data_t *data) -{ - struct pathNode *pn = NULL; - int fault = 0; - - bbf_init(&data->bbf_ctx); - - void *array = blobmsg_open_array(&data->bbf_ctx.bb, "results"); - - list_for_each_entry(pn, data->plist, list) { - bbf_sub_init(&data->bbf_ctx); - - data->bbf_ctx.in_param = pn->path; - - fault = bbfdm_cmd_exec(&data->bbf_ctx, BBF_GET_NAME); - if (fault) { - void *table = blobmsg_open_table(&data->bbf_ctx.bb, NULL); - blobmsg_add_string(&data->bbf_ctx.bb, "path", data->bbf_ctx.in_param ? data->bbf_ctx.in_param : ""); - blobmsg_add_u32(&data->bbf_ctx.bb, "fault", bbf_fault_map(&data->bbf_ctx, fault)); - bb_add_string(&data->bbf_ctx.bb, "fault_msg", data->bbf_ctx.fault_msg); - blobmsg_close_table(&data->bbf_ctx.bb, table); - } - - bbf_sub_cleanup(&data->bbf_ctx); - } - - blobmsg_close_array(&data->bbf_ctx.bb, array); - - if (data->ctx && data->req) - ubus_send_reply(data->ctx, data->req, data->bbf_ctx.bb.head); - - // Apply all bbfdm changes - dmuci_commit_bbfdm(); - - bbf_cleanup(&data->bbf_ctx); -} - -void bbfdm_get_instances(bbfdm_data_t *data) -{ - struct pathNode *pn = NULL; - int fault = 0; - - bbf_init(&data->bbf_ctx); - - void *array = blobmsg_open_array(&data->bbf_ctx.bb, "results"); - - list_for_each_entry(pn, data->plist, list) { - bbf_sub_init(&data->bbf_ctx); - - data->bbf_ctx.in_param = pn->path; - - fault = bbfdm_cmd_exec(&data->bbf_ctx, BBF_INSTANCES); - if (fault) { - void *table = blobmsg_open_table(&data->bbf_ctx.bb, NULL); - blobmsg_add_string(&data->bbf_ctx.bb, "path", data->bbf_ctx.in_param ? data->bbf_ctx.in_param : ""); - blobmsg_add_u32(&data->bbf_ctx.bb, "fault", bbf_fault_map(&data->bbf_ctx, fault)); - bb_add_string(&data->bbf_ctx.bb, "fault_msg", data->bbf_ctx.fault_msg); - blobmsg_close_table(&data->bbf_ctx.bb, table); - } - - bbf_sub_cleanup(&data->bbf_ctx); - } - - blobmsg_close_array(&data->bbf_ctx.bb, array); - - if (data->ctx && data->req) - ubus_send_reply(data->ctx, data->req, data->bbf_ctx.bb.head); - - // Apply all bbfdm changes - dmuci_commit_bbfdm(); - - bbf_cleanup(&data->bbf_ctx); -} - -void bbfdm_get_supported_dm(bbfdm_data_t *data) -{ - struct pathNode *pn = NULL; - int fault = 0; - - bbf_init(&data->bbf_ctx); - - void *array = blobmsg_open_array(&data->bbf_ctx.bb, "results"); - - list_for_each_entry(pn, data->plist, list) { - bbf_sub_init(&data->bbf_ctx); - - data->bbf_ctx.in_param = pn->path; - - fault = bbfdm_cmd_exec(&data->bbf_ctx, BBF_SCHEMA); - if (fault) { - void *table = blobmsg_open_table(&data->bbf_ctx.bb, NULL); - blobmsg_add_string(&data->bbf_ctx.bb, "path", data->bbf_ctx.in_param ? data->bbf_ctx.in_param : ""); - blobmsg_add_u32(&data->bbf_ctx.bb, "fault", bbf_fault_map(&data->bbf_ctx, fault)); - bb_add_string(&data->bbf_ctx.bb, "fault_msg", data->bbf_ctx.fault_msg); - blobmsg_close_table(&data->bbf_ctx.bb, table); - } - - bbf_sub_cleanup(&data->bbf_ctx); - } - - blobmsg_close_array(&data->bbf_ctx.bb, array); - - if (data->ctx && data->req) - ubus_send_reply(data->ctx, data->req, data->bbf_ctx.bb.head); - - bbf_cleanup(&data->bbf_ctx); -} diff --git a/libbbfdm-ubus/get.h b/libbbfdm-ubus/get.h index 9faa5459..b423881d 100644 --- a/libbbfdm-ubus/get.h +++ b/libbbfdm-ubus/get.h @@ -3,34 +3,23 @@ enum { DM_GET_PATH, - DM_GET_PATHS, - DM_GET_MAXDEPTH, DM_GET_OPTIONAL, __DM_GET_MAX }; enum { DM_INSTANCES_PATH, - DM_INSTANCES_PATHS, - DM_INSTANCES_FIRST_LEVEL, DM_INSTANCES_OPTIONAL, __DM_INSTANCES_MAX }; enum { DM_SCHEMA_PATH, - DM_SCHEMA_PATHS, DM_SCHEMA_FIRST_LEVEL, DM_SCHEMA_OPTIONAL, __DM_SCHEMA_MAX }; -void bbfdm_get_value(bbfdm_data_t *data, void *output); - -void bbfdm_get_names(bbfdm_data_t *data); - -void bbfdm_get_instances(bbfdm_data_t *data); - -void bbfdm_get_supported_dm(bbfdm_data_t *data); +void bbfdm_get(bbfdm_data_t *data, int method); #endif /* GET_H */ diff --git a/libbbfdm-ubus/get_helper.c b/libbbfdm-ubus/get_helper.c index b34d7bf6..a0dab15f 100644 --- a/libbbfdm-ubus/get_helper.c +++ b/libbbfdm-ubus/get_helper.c @@ -16,7 +16,6 @@ #include "get_helper.h" #include "common.h" -#include "pretty_print.h" DMOBJ *DEAMON_DM_ROOT_OBJ = NULL; DM_MAP_OBJ *INTERNAL_ROOT_TREE = NULL; @@ -60,12 +59,36 @@ void bbf_sub_cleanup(struct dmctx *dm_ctx) bbf_ctx_clean_sub(dm_ctx); } +bool match_with_path_list(struct list_head *plist, char *entry) +{ + struct pathNode *node; + + list_for_each_entry(node, plist, list) { + if (strncmp(node->path, entry, strlen(node->path)) == 0) + return true; + } + + return false; +} + bool present_in_path_list(struct list_head *plist, char *entry) { - struct pathNode *pos; + struct pathNode *node; - list_for_each_entry(pos, plist, list) { - if (!strcmp(pos->path, entry)) + list_for_each_entry(node, plist, list) { + if (!strcmp(node->path, entry)) + return true; + } + + return false; +} + +bool present_in_pv_list(struct list_head *pv_list, char *entry) +{ + struct pvNode *node = NULL; + + list_for_each_entry(node, pv_list, list) { + if (!strcmp(node->param, entry)) return true; } @@ -138,7 +161,7 @@ void free_path_list(struct list_head *plist) void fill_err_code_table(bbfdm_data_t *data, int fault) { void *table = blobmsg_open_table(&data->bb, NULL); - blobmsg_add_string(&data->bb, "path", data->bbf_ctx.in_param ? data->bbf_ctx.in_param : ""); + bb_add_string(&data->bb, "path", data->bbf_ctx.in_param); blobmsg_add_u32(&data->bb, "fault", bbf_fault_map(&data->bbf_ctx, fault)); bb_add_string(&data->bb, "fault_msg", data->bbf_ctx.fault_msg); blobmsg_close_table(&data->bb, table); @@ -148,104 +171,9 @@ void fill_err_code_array(bbfdm_data_t *data, int fault) { void *array = blobmsg_open_array(&data->bb, "results"); void *table = blobmsg_open_table(&data->bb, NULL); - blobmsg_add_string(&data->bb, "path", data->bbf_ctx.in_param); + bb_add_string(&data->bb, "path", data->bbf_ctx.in_param); blobmsg_add_u32(&data->bb, "fault", bbf_fault_map(&data->bbf_ctx, fault)); bb_add_string(&data->bb, "fault_msg", data->bbf_ctx.fault_msg); blobmsg_close_table(&data->bb, table); blobmsg_close_array(&data->bb, array); } - -static int CountConsecutiveDigits(char *p) -{ - char c; - int num_digits; - - num_digits = 0; - c = *p++; - while ((c >= '0') && (c <= 9)) - { - num_digits++; - c = *p++; - } - - return num_digits; -} - -static int compare_path(const void *arg1, const void *arg2) -{ - const struct pvNode *pv1 = (const struct pvNode *)arg1; - const struct pvNode *pv2 = (const struct pvNode *)arg2; - - char *s1 = pv1->param; - char *s2 = pv2->param; - - char c1, c2; - int num_digits_s1; - int num_digits_s2; - int delta; - - // Skip all characters which are the same - while (true) { - c1 = *s1; - c2 = *s2; - - // Exit if reached the end of either string - if ((c1 == '\0') || (c2 == '\0')) { - // NOTE: The following comparision puts s1 before s2, if s1 terminates before s2 (and vice versa) - return (int)c1 - (int)c2; - } - - // Exit if the characters do not match - if (c1 != c2) { - break; - } - - // As characters match, move to next characters - s1++; - s2++; - } - - // If the code gets here, then we have reached a character which is different - // Determine the number of digits in the rest of the string (this may be 0 if the first character is not a digit) - num_digits_s1 = CountConsecutiveDigits(s1); - num_digits_s2 = CountConsecutiveDigits(s2); - - // Determine if the number of digits in s1 is greater than in s2 (if so, s1 comes after s2) - delta = num_digits_s1 - num_digits_s2; - if (delta != 0) { - return delta; - } - - // If the code gets here, then the strings contain either no digits, or the same number of digits, - // so just compare the characters (this also works if the characters are digits) - return (int)c1 - (int)c2; -} - -// Returns a pointer to the sorted array of PVs, memory need to be freed by caller -struct pvNode *sort_pv_path(struct list_head *pv_list, size_t pv_count) -{ - if (!pv_list) - return NULL; - - if (list_empty(pv_list) || pv_count == 0) - return NULL; - - struct pvNode *arr = (struct pvNode *)calloc(pv_count, sizeof(struct pvNode)); - if (arr == NULL) - return NULL; - - struct pvNode *pv = NULL; - size_t i = 0; - - list_for_each_entry(pv, pv_list, list) { - if (i == pv_count) - break; - - memcpy(&arr[i], pv, sizeof(struct pvNode)); - i++; - } - - qsort(arr, pv_count, sizeof(struct pvNode), compare_path); - - return arr; -} diff --git a/libbbfdm-ubus/get_helper.h b/libbbfdm-ubus/get_helper.h index e6837862..b317aad7 100644 --- a/libbbfdm-ubus/get_helper.h +++ b/libbbfdm-ubus/get_helper.h @@ -24,11 +24,12 @@ void bbf_cleanup(struct dmctx *dm_ctx); void bbf_sub_init(struct dmctx *dm_ctx); void bbf_sub_cleanup(struct dmctx *dm_ctx); -bool present_in_path_list(struct list_head *plist, char *entry); - +bool present_in_pv_list(struct list_head *pv_list, char *entry); void add_pv_list(const char *para, const char *val, const char *type, struct list_head *pv_list); void free_pv_list(struct list_head *pv_list); +bool match_with_path_list(struct list_head *plist, char *entry); +bool present_in_path_list(struct list_head *plist, char *entry); void add_path_list(const char *param, struct list_head *plist); void free_path_list(struct list_head *plist); @@ -37,6 +38,4 @@ void fill_err_code_array(bbfdm_data_t *data, int fault); void bb_add_string(struct blob_buf *bb, const char *name, const char *value); -struct pvNode *sort_pv_path(struct list_head *pv_list, size_t pv_count); - #endif /* GET_HELPER_H */ diff --git a/libbbfdm-ubus/operate.c b/libbbfdm-ubus/operate.c index 87f84ffc..f6ae63a2 100644 --- a/libbbfdm-ubus/operate.c +++ b/libbbfdm-ubus/operate.c @@ -10,9 +10,7 @@ */ #include "common.h" -#include "operate.h" #include "get_helper.h" -#include "pretty_print.h" #include @@ -20,71 +18,31 @@ void bbfdm_operate_cmd(bbfdm_data_t *data, void *output) { int fault = 0; - memset(&data->bb, 0, sizeof(struct blob_buf)); - bbf_init(&data->bbf_ctx); - blob_buf_init(&data->bb, 0); - void *global_array = blobmsg_open_array(&data->bb, "results"); + void *array = blobmsg_open_array(&data->bbf_ctx.bb, "results"); - void *global_table = blobmsg_open_table(&data->bb, NULL); - blobmsg_add_string(&data->bb, "path", data->bbf_ctx.in_param); - blobmsg_add_string(&data->bb, "data", data->bbf_ctx.linker); + void *table = blobmsg_open_table(&data->bbf_ctx.bb, NULL); + bb_add_string(&data->bbf_ctx.bb, "path", data->bbf_ctx.in_param); + bb_add_string(&data->bbf_ctx.bb, "data", data->bbf_ctx.linker); + void *output_array = blobmsg_open_array(&data->bbf_ctx.bb, "output"); fault = bbfdm_cmd_exec(&data->bbf_ctx, BBF_OPERATE); - if (fault == 0) { - void *table = NULL, *array = NULL; - struct blob_attr *cur = NULL; - size_t rem = 0; - - if (data->is_raw) { - array = blobmsg_open_array(&data->bb, "output"); - blobmsg_for_each_attr(cur, data->bbf_ctx.bb.head, rem) { - blobmsg_add_blob(&data->bb, cur); - } - blobmsg_close_array(&data->bb, array); - } else { - LIST_HEAD(pv_local); - - blobmsg_for_each_attr(cur, data->bbf_ctx.bb.head, rem) { - struct blob_attr *tb[3] = {0}; - const struct blobmsg_policy p[3] = { - { "path", BLOBMSG_TYPE_STRING }, - { "data", BLOBMSG_TYPE_STRING }, - { "type", BLOBMSG_TYPE_STRING } - }; - - blobmsg_parse(p, 3, tb, blobmsg_data(cur), blobmsg_len(cur)); - - char *op_name = (tb[0]) ? blobmsg_get_string(tb[0]) : ""; - char *op_data = (tb[1]) ? blobmsg_get_string(tb[1]) : ""; - char *op_type = (tb[2]) ? blobmsg_get_string(tb[2]) : ""; - - add_pv_list(op_name, op_data, op_type, &pv_local); - } - - array = blobmsg_open_array(&data->bb, "output"); - table = blobmsg_open_table(&data->bb, NULL); - prepare_result_blob(&data->bb, &pv_local); - blobmsg_close_table(&data->bb, table); - blobmsg_close_array(&data->bb, array); - - free_pv_list(&pv_local); - } - } else { - blobmsg_add_u32(&data->bb, "fault", fault); - bb_add_string(&data->bb, "fault_msg", data->bbf_ctx.fault_msg); + if (fault) { + blobmsg_add_u32(&data->bbf_ctx.bb, "fault", fault); + bb_add_string(&data->bbf_ctx.bb, "fault_msg", data->bbf_ctx.fault_msg); } - blobmsg_close_table(&data->bb, global_table); + blobmsg_close_array(&data->bbf_ctx.bb, output_array); + blobmsg_close_table(&data->bbf_ctx.bb, table); - blobmsg_close_array(&data->bb, global_array); + blobmsg_close_array(&data->bbf_ctx.bb, array); - if (output) - memcpy(output, data->bb.head, blob_pad_len(data->bb.head)); - else - ubus_send_reply(data->ctx, data->req, data->bb.head); + if (output) { + memcpy(output, data->bbf_ctx.bb.head, blob_pad_len(data->bbf_ctx.bb.head)); + } else if (data->ctx && data->req) { + ubus_send_reply(data->ctx, data->req, data->bbf_ctx.bb.head); + } - blob_buf_free(&data->bb); bbf_cleanup(&data->bbf_ctx); } diff --git a/libbbfdm-ubus/plugin.c b/libbbfdm-ubus/plugin.c index 455b336a..de380e39 100644 --- a/libbbfdm-ubus/plugin.c +++ b/libbbfdm-ubus/plugin.c @@ -1,7 +1,7 @@ /* * plugin.c: Plugin file bbfdmd * - * Copyright (C) 2023 IOPSYS Software Solutions AB. All rights reserved. + * Copyright (C) 2023-2025 IOPSYS Software Solutions AB. All rights reserved. * * Author: Amin Ben Romdhane * @@ -17,7 +17,6 @@ #include "libbbfdm-api/legacy/plugin/json_plugin.h" - extern struct list_head loaded_json_files; extern struct list_head json_list; extern struct list_head json_memhead; @@ -37,34 +36,9 @@ static uint8_t find_number_of_objects(DM_MAP_OBJ *dynamic_obj) return len; } -static void fill_dotso_micro_service_out_args(bbfdm_config_t *config, DMOBJ *entryobj, char *parent_dm) +int bbfdm_load_internal_plugin(struct bbfdm_context *bbfdm_ctx, DM_MAP_OBJ *dynamic_obj, DMOBJ **main_entry) { - char ms_name[128] = {0}; - - if (!config || !entryobj || !parent_dm) - return; - - strncpyt(config->out_parent_dm, parent_dm, sizeof(config->out_parent_dm)); - - for (; (entryobj && entryobj->obj); entryobj++) { - - add_path_list(entryobj->obj, &config->list_objs); - - int len = DM_STRLEN(ms_name); - if (len == 0) { - snprintf(ms_name, sizeof(ms_name), "%s.%s", config->out_root_obj, entryobj->obj); - } else { - snprintf(ms_name + len, sizeof(ms_name) - len, "_%s", entryobj->obj); - } - } - - if (DM_STRLEN(config->out_name) == 0) - strncpyt(config->out_name, ms_name, sizeof(config->out_name)); -} - -int bbfdm_load_internal_plugin(struct bbfdm_context *bbfdm_ctx, DM_MAP_OBJ *dynamic_obj, bbfdm_config_t *config, DMOBJ **main_entry) -{ - if (!dynamic_obj || !config || !main_entry) { + if (!dynamic_obj || !main_entry) { BBF_ERR("Input validation failed"); return -1; } @@ -92,9 +66,14 @@ int bbfdm_load_internal_plugin(struct bbfdm_context *bbfdm_ctx, DM_MAP_OBJ *dyna return -1; } - // Fill out arguments if it is running as micro-service - if (dm_is_micro_service() == true) - fill_dotso_micro_service_out_args(config, dynamic_obj[i].root_obj, node_obj); + 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; @@ -112,9 +91,9 @@ int bbfdm_load_internal_plugin(struct bbfdm_context *bbfdm_ctx, DM_MAP_OBJ *dyna return 0; } -int bbfdm_load_dotso_plugin(struct bbfdm_context *bbfdm_ctx, void **lib_handle, const char *file_path, bbfdm_config_t *config, DMOBJ **main_entry) +int bbfdm_load_dotso_plugin(struct bbfdm_context *bbfdm_ctx, void **lib_handle, const char *file_path, DMOBJ **main_entry) { - if (!lib_handle || !file_path || !strlen(file_path) || !config || !main_entry) { + if (!lib_handle || !file_path || !strlen(file_path) || !main_entry) { BBF_ERR("Input validation failed"); return -1; } @@ -132,7 +111,7 @@ int bbfdm_load_dotso_plugin(struct bbfdm_context *bbfdm_ctx, void **lib_handle, //Dynamic Object *(void **) (&dynamic_obj) = dlsym(handle, "tDynamicObj"); - return bbfdm_load_internal_plugin(bbfdm_ctx, dynamic_obj, config, main_entry); + return bbfdm_load_internal_plugin(bbfdm_ctx, dynamic_obj, main_entry); } int bbfdm_free_dotso_plugin(struct bbfdm_context *bbfdm_ctx, void **lib_handle) @@ -159,28 +138,11 @@ int bbfdm_free_dotso_plugin(struct bbfdm_context *bbfdm_ctx, void **lib_handle) return 0; } -static void fill_json_micro_service_out_args(bbfdm_config_t *config, char *parent_dm, char *obj, char *ms_name, size_t ms_name_len) -{ - if (!config || !obj) - return; - - strncpyt(config->out_parent_dm, parent_dm, sizeof(config->out_parent_dm)); - add_path_list(obj, &config->list_objs); - - int len = DM_STRLEN(ms_name); - if (len == 0) { - snprintf(ms_name, ms_name_len, "%s.%s", config->out_root_obj, obj); - } else { - snprintf(ms_name + len, ms_name_len - len, "_%s", obj); - } -} - -int bbfdm_load_json_plugin(struct list_head *json_plugin, struct list_head *json_list, struct list_head *json_memhead, - const char *file_path, bbfdm_config_t *config, DMOBJ **main_entry) +static int bbfdm_load_json_plugin(struct bbfdm_context *bbfdm_ctx, struct list_head *json_plugin, struct list_head *json_list, + struct list_head *json_memhead, const char *file_path, DMOBJ **main_entry) { DMOBJ *dm_entryobj = NULL; int json_plugin_version = JSON_VERSION_0; - char ms_name[128] = {0}; uint8_t idx = 0; if (!file_path || !strlen(file_path) || !main_entry) { @@ -218,7 +180,7 @@ int bbfdm_load_json_plugin(struct list_head *json_plugin, struct list_head *json return -1; } - char obj_prefix[1024] = {0}; + char obj_prefix[512] = {0}; json_plugin_find_prefix_obj(node_obj, obj_prefix, sizeof(obj_prefix)); int obj_prefix_len = strlen(obj_prefix); @@ -234,9 +196,9 @@ int bbfdm_load_json_plugin(struct list_head *json_plugin, struct list_head *json return -1; } - // Fill out arguments if it is running as micro-service - if (dm_is_micro_service() == true) - fill_json_micro_service_out_args(config, obj_prefix, obj_name, ms_name, sizeof(ms_name)); + 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] == '.') @@ -264,9 +226,6 @@ int bbfdm_load_json_plugin(struct list_head *json_plugin, struct list_head *json idx++; } - if (DM_STRLEN(config->out_name) == 0) - strncpyt(config->out_name, ms_name, sizeof(config->out_name)); - *main_entry = dm_entryobj; return 0; } @@ -276,7 +235,7 @@ int bbfdm_free_json_plugin(void) return free_json_plugins(); } -int bbfdm_load_external_plugin(struct bbfdm_context *bbfdm_ctx, void **lib_handle, bbfdm_config_t *config, DMOBJ **main_entry) +int bbfdm_load_external_plugin(struct bbfdm_context *bbfdm_ctx, void **lib_handle, DMOBJ **main_entry) { char file_path[128] = {0}; int err = -1; @@ -293,10 +252,10 @@ int bbfdm_load_external_plugin(struct bbfdm_context *bbfdm_ctx, void **lib_handl BBF_ERR("Input file without extension"); } else if (strcasecmp(ext, ".json") == 0) { BBF_INFO("Loading JSON plugin %s", file_path); - err = bbfdm_load_json_plugin(&loaded_json_files, &json_list, &json_memhead, file_path, config, main_entry); + err = bbfdm_load_json_plugin(bbfdm_ctx, &loaded_json_files, &json_list, &json_memhead, file_path, main_entry); } else if (strcasecmp(ext, ".so") == 0) { BBF_INFO("Loading DotSo plugin %s", file_path); - err = bbfdm_load_dotso_plugin(bbfdm_ctx, lib_handle, file_path, config, main_entry); + err = bbfdm_load_dotso_plugin(bbfdm_ctx, lib_handle, file_path, main_entry); } else { BBF_ERR("Input type %s not supported", ext); } diff --git a/libbbfdm-ubus/plugin.h b/libbbfdm-ubus/plugin.h index 6d39e463..f753a22d 100644 --- a/libbbfdm-ubus/plugin.h +++ b/libbbfdm-ubus/plugin.h @@ -10,14 +10,12 @@ #ifndef PLUGIN_H -int bbfdm_load_internal_plugin(struct bbfdm_context *bbfdm_ctx, DM_MAP_OBJ *Dynamic_Obj, bbfdm_config_t *config, DMOBJ **main_entry); -int bbfdm_load_external_plugin(struct bbfdm_context *bbfdm_ctx, void **lib_handle, bbfdm_config_t *config, DMOBJ **main_entry); +int bbfdm_load_internal_plugin(struct bbfdm_context *bbfdm_ctx, DM_MAP_OBJ *Dynamic_Obj, DMOBJ **main_entry); +int bbfdm_load_external_plugin(struct bbfdm_context *bbfdm_ctx, void **lib_handle, DMOBJ **main_entry); -int bbfdm_load_dotso_plugin(struct bbfdm_context *bbfdm_ctx, void **lib_handle, const char *file_path, bbfdm_config_t *config, DMOBJ **main_entry); +int bbfdm_load_dotso_plugin(struct bbfdm_context *bbfdm_ctx, void **lib_handle, const char *file_path, DMOBJ **main_entry); int bbfdm_free_dotso_plugin(struct bbfdm_context *bbfdm_ctx, void *lib_handle); -int bbfdm_load_json_plugin(struct list_head *json_plugin, struct list_head *json_list, struct list_head *json_memhead, - const char *file_path, bbfdm_config_t *config, DMOBJ **main_entry); int bbfdm_free_json_plugin(void); #endif /* PLUGIN_H */ diff --git a/libbbfdm-ubus/pretty_print.c b/libbbfdm-ubus/pretty_print.c deleted file mode 100644 index 5f16fbed..00000000 --- a/libbbfdm-ubus/pretty_print.c +++ /dev/null @@ -1,444 +0,0 @@ -/* - * pretty_print.c: utils for pretty printing of results - * - * Copyright (C) 2020-2023 IOPSYS Software Solutions AB. All rights reserved. - * - * Author: Vivek Dutta - * - * See LICENSE file for license related information. - */ - -#include "common.h" -#include "get_helper.h" -#include "pretty_print.h" - -// private function and structures -struct resultstack { - void *cookie; - char *key; - struct list_head list; -}; - -static bool is_search_by_reference(char *path) -{ - BBF_DEBUG("Entry |%s|", path); - if (match(path, "[+]+", 0, NULL)) { - size_t pindex = 0, bindex = 0; - char *last_plus, *last_bracket; - - last_bracket = strrchr(path, ']'); - if (!last_bracket) - return true; - - last_plus = strrchr(path, '+'); - - pindex = (size_t)labs(last_plus - path); - bindex = (size_t)labs(last_bracket - path); - - if (pindex > bindex) - return true; - } - - return false; -} - -//if matched start will have first match index, end will have end index -static bool is_res_required(char *str, size_t *start, size_t *len) -{ - - BBF_DEBUG("Entry |%s|", str); - if (match(str, GLOB_CHAR, 0, NULL)) { - size_t s_len = 0, b_len = 0, p_len = 0; - char *star, *b_start, *b_end, *plus; - char temp_char[MAX_DM_KEY_LEN] = {'\0'}; - - s_len = DM_STRLEN(str); - b_len = s_len; - p_len = s_len; - - star = strchr(str, '*'); - b_start = strchr(str, '['); - b_end = strchr(str, ']'); - plus = strchr(str, '+'); - - if (star) - s_len = (size_t)labs(star - str); - - if (b_start) - b_len = (size_t)labs(b_start - str); - - if (plus) - p_len = (size_t)labs(plus - str); - - *start = MIN(MIN(s_len, p_len), b_len); - if (*start == s_len) { - *len = 1; - } else if (*start == p_len) { - size_t i = 0, index = 0; - - while ((str+i) != plus) { - if (str[i] == DELIM) - index = i; - ++i; - } - *start = index+1; - *len = p_len - index; - } else { - *len = (size_t)labs(b_end - b_start); - } - - // Check if naming with aliases used - snprintf(temp_char, *len+1, "%s", str + *start); - if (match(temp_char, GLOB_EXPR, 0, NULL)) - return true; - - if (match(temp_char, "[*+]+", 0, NULL)) - return true; - } - *start = DM_STRLEN(str); - return false; -} - -static size_t get_glob_len(char *path) -{ - size_t m_index = 0, m_len = 0, ret = 0; - size_t plen = DM_STRLEN(path); - char temp_name[MAX_DM_KEY_LEN] = {'\0'}; - char *end = NULL; - - BBF_DEBUG("Entry"); - if (is_res_required(path, &m_index, &m_len)) { - if (m_index <= MAX_DM_KEY_LEN) - snprintf(temp_name, m_index, "%s", path); - end = strrchr(temp_name, DELIM); - if (end != NULL) - ret = m_index - DM_STRLEN(end); - } else { - char name[MAX_DM_KEY_LEN] = {'\0'}; - - if (plen == 0) - return ret; - - if (path[plen - 1] == DELIM) { - if (plen <= MAX_DM_KEY_LEN) - snprintf(name, plen, "%s", path); - } else { - ret = 1; - if (plen < MAX_DM_KEY_LEN) - snprintf(name, plen + 1, "%s", path); - } - end = strrchr(name, DELIM); - if (end == NULL) - return ret; - - ret = ret + DM_STRLEN(path) - DM_STRLEN(end); - if (is_node_instance(end+1)) { - int copy_len = plen - DM_STRLEN(end); - if (copy_len <= MAX_DM_KEY_LEN) - snprintf(temp_name, copy_len, "%s", path); - - end = strrchr(temp_name, DELIM); - if (end != NULL) - ret = ret - DM_STRLEN(end); - } - } - return(ret); -} - -static void resulting(uint8_t maxdepth, char *path, struct dmctx *bbf_ctx, struct list_head *pv_local) -{ - struct blob_attr *cur = NULL; - size_t rem = 0; - uint8_t count; - - size_t plen = get_glob_len(bbf_ctx->in_param); - size_t path_len = DM_STRLEN(path); - if (path_len == 0) - return; - - blobmsg_for_each_attr(cur, bbf_ctx->bb.head, rem) { - struct blob_attr *tb[3] = {0}; - const struct blobmsg_policy p[3] = { - { "path", BLOBMSG_TYPE_STRING }, - { "data", BLOBMSG_TYPE_STRING }, - { "type", BLOBMSG_TYPE_STRING } - }; - - blobmsg_parse(p, 3, tb, blobmsg_data(cur), blobmsg_len(cur)); - - char *name = (tb[0]) ? blobmsg_get_string(tb[0]) : ""; - char *data = (tb[1]) ? blobmsg_get_string(tb[1]) : ""; - char *type = (tb[2]) ? blobmsg_get_string(tb[2]) : ""; - - if (match(name, path, 0, NULL)) { - if (is_search_by_reference(bbf_ctx->in_param)) - plen = 0; - - if (maxdepth > 4 || maxdepth == 0) { - add_pv_list(name + plen, data, type, pv_local); - } else { - count = count_delim(name + path_len); - if (count < maxdepth) - add_pv_list(name + plen, data, type, pv_local); - } - } - } -} - -static void add_data_blob(struct blob_buf *bb, char *param, char *value, char *type) -{ - if (param == NULL || value == NULL || type == NULL) - return; - - BBF_DEBUG("# Adding BLOB (%s)::(%s)", param, value); - switch (get_dm_type(type)) { - case DMT_UNINT: - blobmsg_add_u64(bb, param, (uint32_t)strtoul(value, NULL, 10)); - break; - case DMT_INT: - blobmsg_add_u32(bb, param, (int)strtol(value, NULL, 10)); - break; - case DMT_LONG: - blobmsg_add_u64(bb, param, strtoll(value, NULL, 10)); - break; - case DMT_UNLONG: - blobmsg_add_u64(bb, param, (uint64_t)strtoull(value, NULL, 10)); - break; - case DMT_BOOL: - if (get_boolean_string(value)) - blobmsg_add_u8(bb, param, true); - else - blobmsg_add_u8(bb, param, false); - break; - default: //"xsd:hexbin" "xsd:dateTime" "xsd:string" - bb_add_string(bb, param, value); - break; - } -} - -static void free_result_list(struct list_head *head) -{ - struct resultstack *iter = NULL, *node = NULL; - - list_for_each_entry_safe(iter, node, head, list) { - free(iter->key); - list_del(&iter->list); - free(iter); - } -} - -static void free_result_node(struct resultstack *rnode) -{ - if (rnode) { - BBF_DEBUG("## ResStack DEL(%s)", rnode->key); - free(rnode->key); - list_del(&rnode->list); - free(rnode); - } -} - -static void add_result_node(struct list_head *rlist, char *key, char *cookie) -{ - struct resultstack *rnode = NULL; - - rnode = (struct resultstack *)calloc(1, sizeof(*rnode)); - if (!rnode) { - BBF_ERR("Out of memory!"); - return; - } - - INIT_LIST_HEAD(&rnode->list); - list_add(&rnode->list, rlist); - - rnode->key = (key) ? strdup(key) : strdup(""); - rnode->cookie = cookie; - BBF_DEBUG("## ResSTACK ADD (%s) ##", rnode->key); -} - -static bool is_leaf_element(char *path) -{ - char *ptr = NULL; - - if (!path) - return true; - - ptr = strchr(path, DELIM); - - return (ptr == NULL); -} - -static bool get_next_element(char *path, char *param) -{ - char *ptr; - size_t len; - - if (!path) - return false; - - len = DM_STRLEN(path); - ptr = strchr(path, DELIM); - if (ptr) - strncpyt(param, path, (size_t)labs(ptr - path) + 1); - else - strncpyt(param, path, len + 1); - - return true; -} - -static bool is_same_group(char *path, char *group) -{ - return (strncmp(path, group, DM_STRLEN(group)) == 0); -} - -static bool add_paths_to_stack(struct blob_buf *bb, char *path, size_t begin, - struct pvNode *pv, struct list_head *result_stack) -{ - char key[MAX_DM_KEY_LEN], param[MAX_DM_PATH], *ptr; - size_t parsed_len = 0; - void *c; - char *k; - - ptr = path + begin; - if (is_leaf_element(ptr)) { - add_data_blob(bb, ptr, pv->val, pv->type); - return true; - } - - while (get_next_element(ptr, key)) { - parsed_len += DM_STRLEN(key) + 1; - ptr += DM_STRLEN(key) + 1; - if (is_leaf_element(ptr)) { - strncpyt(param, path, begin + parsed_len + 1); - if (is_node_instance(key)) - c = blobmsg_open_table(bb, NULL); - else - c = blobmsg_open_table(bb, key); - - k = param; - add_result_node(result_stack, k, c); - add_data_blob(bb, ptr, pv->val, pv->type); - break; - } - strncpyt(param, pv->param, begin + parsed_len + 1); - if (is_node_instance(ptr)) - c = blobmsg_open_array(bb, key); - else - c = blobmsg_open_table(bb, key); - - k = param; - add_result_node(result_stack, k, c); - } - - return true; -} - -// public functions -void prepare_result_blob(struct blob_buf *bb, struct list_head *pv_list) -{ - char *ptr; - size_t len; - struct pvNode *pv; - struct resultstack *rnode; - - LIST_HEAD(result_stack); - - if (!bb || !pv_list) - return; - - if (list_empty(pv_list)) - return; - - size_t count = 0; - list_for_each_entry(pv, pv_list, list) { - count++; - } - - struct pvNode *sortedPV = sort_pv_path(pv_list, count); - if (sortedPV == NULL) - return; - - for (size_t i = 0; i < count; i++) { - pv = &sortedPV[i]; - ptr = pv->param; - if (list_empty(&result_stack)) { - BBF_DEBUG("stack empty Processing (%s)", ptr); - add_paths_to_stack(bb, pv->param, 0, pv, &result_stack); - } else { - bool is_done = false; - - while (is_done == false) { - rnode = list_entry(result_stack.next, struct resultstack, list); - if (is_same_group(ptr, rnode->key)) { - len = DM_STRLEN(rnode->key); - ptr = ptr + len; - - BBF_DEBUG("GROUP (%s), ptr(%s), len(%zu)", pv->param, ptr, len); - add_paths_to_stack(bb, pv->param, len, pv, &result_stack); - is_done = true; - } else { - // Get the latest entry before deleting it - BBF_DEBUG("DIFF GROUP pv(%s), param(%s)", pv->param, ptr); - blobmsg_close_table(bb, rnode->cookie); - free_result_node(rnode); - if (list_empty(&result_stack)) { - add_paths_to_stack(bb, pv->param, 0, pv, &result_stack); - is_done = true; - } - } - } - } - } - - free(sortedPV); - - // Close the stack entry if left - list_for_each_entry(rnode, &result_stack, list) { - blobmsg_close_table(bb, rnode->cookie); - } - free_result_list(&result_stack); -} - -void prepare_raw_result(struct blob_buf *bb, struct dmctx *bbf_ctx, struct list_head *rslvd) -{ - struct pathNode *iter = NULL; - struct blob_attr *cur = NULL; - size_t rem = 0; - - list_for_each_entry(iter, rslvd, list) { - if (DM_STRLEN(iter->path) == 0) - continue; - - blobmsg_for_each_attr(cur, bbf_ctx->bb.head, rem) { - struct blob_attr *tb[1] = {0}; - const struct blobmsg_policy p[1] = { - { "path", BLOBMSG_TYPE_STRING } - }; - - blobmsg_parse(p, 1, tb, blobmsg_data(cur), blobmsg_len(cur)); - - char *name = (tb[0]) ? blobmsg_get_string(tb[0]) : ""; - - if (match(name, iter->path, 0, NULL)) { - blobmsg_add_blob(bb, cur); - } - } - } -} - -void prepare_pretty_result(uint8_t maxdepth, struct blob_buf *bb, struct dmctx *bbf_ctx, struct list_head *rslvd) -{ - struct pathNode *iter = NULL; - - LIST_HEAD(pv_local); - - BBF_DEBUG("################### DATA to PROCESS ##################"); - list_for_each_entry(iter, rslvd, list) { - BBF_DEBUG("## %s ##", iter->path); - resulting(maxdepth, iter->path, bbf_ctx, &pv_local); - } - BBF_DEBUG("######################################################"); - - prepare_result_blob(bb, &pv_local); - - free_pv_list(&pv_local); -} diff --git a/libbbfdm-ubus/pretty_print.h b/libbbfdm-ubus/pretty_print.h deleted file mode 100644 index a2b15ea7..00000000 --- a/libbbfdm-ubus/pretty_print.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * pretty_print.h: utils for pretty printing of results - * - * Copyright (C) 2020-2023 IOPSYS Software Solutions AB. All rights reserved. - * - * Author: Vivek Dutta - * - * See LICENSE file for license related information. - */ - -#ifndef PRETTY_PRINT_H -#define PRETTY_PRINT_H - -void prepare_result_blob(struct blob_buf *bb, struct list_head *pv_list); -void prepare_raw_result(struct blob_buf *bb, struct dmctx *bbf_ctx, struct list_head *rslvd); -void prepare_pretty_result(uint8_t maxdepth, struct blob_buf *bb, struct dmctx *bbf_ctx, struct list_head *rslvd); - -#endif /* PRETTY_PRINT_H */ diff --git a/libbbfdm-ubus/set.c b/libbbfdm-ubus/set.c index 0d807f3a..4bade7bf 100644 --- a/libbbfdm-ubus/set.c +++ b/libbbfdm-ubus/set.c @@ -17,10 +17,9 @@ int bbfdm_set_value(bbfdm_data_t *data) { struct pvNode *pv = NULL; - void *array = NULL; int fault = 0; - array = blobmsg_open_array(&data->bb, "results"); + void *array = blobmsg_open_array(&data->bb, "results"); list_for_each_entry(pv, data->plist, list) { data->bbf_ctx.in_param = pv->param; @@ -43,39 +42,8 @@ int bbfdm_set_value(bbfdm_data_t *data) return fault; } -static int set_resolved_paths(bbfdm_data_t *data, char *path, char *value, char *type, struct list_head *pv_list) +int fill_pvlist_set(char *param_name, char *param_value, char *data_type, struct blob_attr *blob_table, struct list_head *pv_list) { - int fault = 0; - - if (!path || !value || !pv_list) - return -1; - - LIST_HEAD(resolved_paths); - bbf_sub_init(&data->bbf_ctx); - - fault = get_resolved_paths(&data->bbf_ctx, path, &resolved_paths); - - if (!fault) { - struct pathNode *p; - - list_for_each_entry(p, &resolved_paths, list) { - add_pv_list(p->path, value, type, pv_list); - } - } - - bbf_sub_cleanup(&data->bbf_ctx); - free_path_list(&resolved_paths); - - return fault; -} - -int fill_pvlist_set(bbfdm_data_t *data, char *param_name, char *param_value, char *type, struct blob_attr *blob_table, struct list_head *pv_list) -{ - struct blob_attr *attr; - struct blobmsg_hdr *hdr; - char path[MAX_DM_PATH], value[MAX_DM_VALUE]; - int fault = 0; - size_t plen = DM_STRLEN(param_name); if (plen == 0) return USP_FAULT_INVALID_PATH; @@ -86,18 +54,21 @@ int fill_pvlist_set(bbfdm_data_t *data, char *param_name, char *param_value, cha if (param_name[plen - 1] == '.') return USP_FAULT_INVALID_PATH; - fault = set_resolved_paths(data, param_name, param_value, type, pv_list); - if (fault) - return fault; + add_pv_list(param_name, param_value, data_type, pv_list); + return 0; blob__table: if (!blob_table) return 0; + struct blob_attr *attr; + struct blobmsg_hdr *hdr; + size_t tlen = (size_t)blobmsg_data_len(blob_table); __blob_for_each_attr(attr, blobmsg_data(blob_table), tlen) { + char path[MAX_DM_PATH] = {0}, value[MAX_DM_VALUE] = {0}; hdr = blob_data(attr); switch (blob_id(attr)) { @@ -122,9 +93,7 @@ blob__table: } snprintf(path, MAX_DM_PATH, "%s%s", param_name, (char *)hdr->name); - fault = set_resolved_paths(data, path, value, NULL, pv_list); - if (fault) - return fault; + add_pv_list(path, value, NULL, pv_list); } return 0; diff --git a/libbbfdm-ubus/set.h b/libbbfdm-ubus/set.h index 4543add4..ef65de82 100644 --- a/libbbfdm-ubus/set.h +++ b/libbbfdm-ubus/set.h @@ -10,7 +10,7 @@ enum { __DM_SET_MAX, }; -int fill_pvlist_set(bbfdm_data_t *data, char *param_name, char *param_value, char *type, struct blob_attr *blob_table, struct list_head *pv_list); +int fill_pvlist_set(char *param_name, char *param_value, char *data_type, struct blob_attr *blob_table, struct list_head *pv_list); int bbfdm_set_value(bbfdm_data_t *data); #endif /* SET_H */ diff --git a/libbbfdm/CMakeLists.txt b/libbbfdm/CMakeLists.txt index 303908f0..7a970f4d 100644 --- a/libbbfdm/CMakeLists.txt +++ b/libbbfdm/CMakeLists.txt @@ -7,11 +7,11 @@ ADD_DEFINITIONS(-Wall -Werror -g3 -D_GNU_SOURCE -DBBF_VENDOR_PREFIX="${BBF_VENDO SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SOURCE_DIR} -I${CMAKE_CURRENT_SOURCE_DIR} -I${CMAKE_SOURCE_DIR}/libbbfdm-api/version-2") FILE(GLOB BBF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.c) -ADD_LIBRARY(bbfdm STATIC ${BBF_SOURCES}) +ADD_LIBRARY(core SHARED ${BBF_SOURCES}) -TARGET_LINK_LIBRARIES(bbfdm uci ubus ubox json-c blobmsg_json m bbfdm-api ssl crypto) +TARGET_LINK_LIBRARIES(core uci ubus ubox json-c blobmsg_json m bbfdm-api ssl crypto) -INSTALL(TARGETS bbfdm +INSTALL(TARGETS core LIBRARY DESTINATION usr/lib ) @@ -19,7 +19,6 @@ INSTALL(DIRECTORY DESTINATION etc/bbfdm) INSTALL(DIRECTORY DESTINATION etc/bbfdm/dmmap) INSTALL(DIRECTORY DESTINATION usr/share/bbfdm) INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/scripts) -INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/plugins) INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/micro_services) INSTALL(DIRECTORY DESTINATION usr/libexec/rpcd) diff --git a/libbbfdm/device.c b/libbbfdm/device.c index 1ca33cc9..dcb980f3 100644 --- a/libbbfdm/device.c +++ b/libbbfdm/device.c @@ -91,12 +91,11 @@ DM_MAP_OBJ tDynamicObj[] = { /* *** Device. *** */ DMOBJ tDMRootObj[] = { -/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/ -{"LANConfigSecurity", &DMREAD, NULL, NULL, "file:/etc/config/users", NULL, NULL, NULL, NULL, tLANConfigSecurityParams, NULL, BBFDM_BOTH, NULL}, -{"Schedules", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tSchedulesObj, tSchedulesParams, NULL, BBFDM_BOTH, NULL}, -{"Security", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tSecurityObj, tSecurityParams, NULL, BBFDM_BOTH, NULL}, -{"Services", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, BBFDM_BOTH, NULL}, -{"GatewayInfo", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tGatewayInfoParams, NULL, BBFDM_CWMP, NULL}, +/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/ +{"LANConfigSecurity", &DMREAD, NULL, NULL, "file:/etc/config/users", NULL, NULL, NULL, NULL, tLANConfigSecurityParams, NULL, BBFDM_BOTH}, +{"Schedules", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tSchedulesObj, tSchedulesParams, NULL, BBFDM_BOTH}, +{"Security", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tSecurityObj, tSecurityParams, NULL, BBFDM_CWMP}, +{"GatewayInfo", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tGatewayInfoParams, NULL, BBFDM_CWMP}, {0} }; diff --git a/libbbfdm/security.c b/libbbfdm/security.c index 3a298be1..2e0484cf 100644 --- a/libbbfdm/security.c +++ b/libbbfdm/security.c @@ -299,20 +299,20 @@ static int get_SecurityCertificate_SignatureAlgorithm(char *refparam, struct dmc ***********************************************************************************************************************************/ /* *** Device.Security. *** */ DMOBJ tSecurityObj[] = { -/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/ -{"Certificate", &DMREAD, NULL, NULL, NULL, browseSecurityCertificateInst, NULL, NULL, NULL, tSecurityCertificateParams, NULL, BBFDM_CWMP, NULL}, +/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/ +{"Certificate", &DMREAD, NULL, NULL, NULL, browseSecurityCertificateInst, NULL, NULL, NULL, tSecurityCertificateParams, NULL, BBFDM_CWMP}, {0} }; DMLEAF tSecurityParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/ +/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/ {"CertificateNumberOfEntries", &DMREAD, DMT_UNINT, get_Security_CertificateNumberOfEntries, NULL, BBFDM_CWMP}, {0} }; /* *** Device.Security.Certificate.{i}. *** */ DMLEAF tSecurityCertificateParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/ +/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/ //{"Enable", &DMWRITE, DMT_BOOL, get_SecurityCertificate_Enable, set_SecurityCertificate_Enable, BBFDM_CWMP}, {"LastModif", &DMREAD, DMT_TIME, get_SecurityCertificate_LastModif, NULL, BBFDM_CWMP}, {"SerialNumber", &DMREAD, DMT_STRING, get_SecurityCertificate_SerialNumber, NULL, BBFDM_CWMP, DM_FLAG_UNIQUE}, diff --git a/test/cmocka/Makefile b/test/cmocka/Makefile index 35823e3f..9668d970 100644 --- a/test/cmocka/Makefile +++ b/test/cmocka/Makefile @@ -1,6 +1,6 @@ CC = gcc CFLAGS = -g -Wall -LDFLAGS = -lcmocka -lbbfdm-api -lbbfdm -lubox -lblobmsg_json -ljson-c -lssl -lcrypto --coverage +LDFLAGS = -lcmocka -lbbfdm-api -lcore -lubox -lblobmsg_json -ljson-c -lssl -lcrypto --coverage UNIT_TESTS = unit_test_bbfd FUNCTIONAL_TESTS = functional_test_bbfd FUNCTIONAL_API_TESTS = functional_api_test_bbfd diff --git a/test/cmocka/functional_api_test_bbfd.c b/test/cmocka/functional_api_test_bbfd.c index 6ad5c321..8cf284db 100644 --- a/test/cmocka/functional_api_test_bbfd.c +++ b/test/cmocka/functional_api_test_bbfd.c @@ -12,6 +12,7 @@ static int setup_teardown(void **state) { dm_init_mem(&bbf_ctx); dm_uci_init(&bbf_ctx); + dm_ubus_init(&bbf_ctx); bbf_ctx.dm_type = BBFDM_USP; return 0; } @@ -20,7 +21,7 @@ static int group_teardown(void **state) { dm_uci_exit(&bbf_ctx); dm_clean_mem(&bbf_ctx); - dmubus_free(); + dm_ubus_free(&bbf_ctx); return 0; } diff --git a/test/cmocka/functional_test_bbfd.c b/test/cmocka/functional_test_bbfd.c index 6b1aa4cd..8518c4b6 100644 --- a/test/cmocka/functional_test_bbfd.c +++ b/test/cmocka/functional_test_bbfd.c @@ -42,7 +42,7 @@ static int teardown_commit(void **state) static int group_init(void **state) { - bbf_global_init(TR181_ROOT_TREE, "/usr/share/bbfdm/plugins"); + bbf_global_init(TR181_ROOT_TREE, "/usr/share/bbfdm/micro_services/core"); return 0; } diff --git a/test/cmocka/unit_test_bbfd.c b/test/cmocka/unit_test_bbfd.c index d8dcb83c..cef3ad25 100644 --- a/test/cmocka/unit_test_bbfd.c +++ b/test/cmocka/unit_test_bbfd.c @@ -54,7 +54,7 @@ static int teardown_revert(void **state) static int group_init(void **state) { - bbf_global_init(TR181_ROOT_TREE, "/usr/share/bbfdm/plugins"); + bbf_global_init(TR181_ROOT_TREE, "/usr/share/bbfdm/micro_services/core"); return 0; } diff --git a/test/files/etc/bbfdm/services/core.json b/test/files/etc/bbfdm/services/core.json new file mode 100644 index 00000000..a719eadf --- /dev/null +++ b/test/files/etc/bbfdm/services/core.json @@ -0,0 +1,41 @@ +{ + "daemon": { + "enable": "1", + "service_name": "core", + "unified_daemon": false, + "services": [ + { + "parent_dm": "Device.", + "object": "LANConfigSecurity" + }, + { + "parent_dm": "Device.", + "object": "Schedules" + }, + { + "parent_dm": "Device.", + "object": "Security", + "proto": "cwmp" + }, + { + "parent_dm": "Device.", + "object": "GatewayInfo" + }, + { + "parent_dm": "Device.", + "object": "RootDataModelVersion" + }, + { + "parent_dm": "Device.", + "object": "Reboot()" + }, + { + "parent_dm": "Device.", + "object": "FactoryReset()" + } + ], + "config": { + "loglevel": "3" + } + } +} \ No newline at end of file diff --git a/test/files/etc/bbfdm/services/netmngr.json b/test/files/etc/bbfdm/services/netmngr.json index b41b6d2f..47c24f35 100644 --- a/test/files/etc/bbfdm/services/netmngr.json +++ b/test/files/etc/bbfdm/services/netmngr.json @@ -23,6 +23,14 @@ { "parent_dm": "Device.", "object": "RouterAdvertisement" + }, + { + "parent_dm": "Device.", + "object": "IPv6rd" + }, + { + "parent_dm": "Device.", + "object": "InterfaceStack" } ], "config": { diff --git a/test/files/usr/share/bbfdm/plugins/X_IOPSYS_EU_Dropbear.json b/test/files/usr/share/bbfdm/micro_services/core/X_IOPSYS_EU_Dropbear.json similarity index 100% rename from test/files/usr/share/bbfdm/plugins/X_IOPSYS_EU_Dropbear.json rename to test/files/usr/share/bbfdm/micro_services/core/X_IOPSYS_EU_Dropbear.json diff --git a/test/files/usr/share/bbfdm/plugins/X_IOPSYS_EU_JSON_TEST_V1.json b/test/files/usr/share/bbfdm/micro_services/core/X_IOPSYS_EU_JSON_TEST_V1.json similarity index 100% rename from test/files/usr/share/bbfdm/plugins/X_IOPSYS_EU_JSON_TEST_V1.json rename to test/files/usr/share/bbfdm/micro_services/core/X_IOPSYS_EU_JSON_TEST_V1.json diff --git a/test/files/usr/share/bbfdm/plugins/X_IOPSYS_EU_TEST.json b/test/files/usr/share/bbfdm/micro_services/core/X_IOPSYS_EU_TEST.json similarity index 100% rename from test/files/usr/share/bbfdm/plugins/X_IOPSYS_EU_TEST.json rename to test/files/usr/share/bbfdm/micro_services/core/X_IOPSYS_EU_TEST.json diff --git a/test/files/usr/share/bbfdm/plugins/X_IOPSYS_EU_WiFi.json b/test/files/usr/share/bbfdm/micro_services/core/X_IOPSYS_EU_WiFi.json similarity index 100% rename from test/files/usr/share/bbfdm/plugins/X_IOPSYS_EU_WiFi.json rename to test/files/usr/share/bbfdm/micro_services/core/X_IOPSYS_EU_WiFi.json diff --git a/test/files/usr/share/bbfdm/plugins/x_iopsys_wifi_extension.json b/test/files/usr/share/bbfdm/micro_services/wifidmd/x_iopsys_wifi_extension.json similarity index 100% rename from test/files/usr/share/bbfdm/plugins/x_iopsys_wifi_extension.json rename to test/files/usr/share/bbfdm/micro_services/wifidmd/x_iopsys_wifi_extension.json diff --git a/test/files/var/reset_reason b/test/files/var/reset_reason new file mode 100644 index 00000000..6f9e63ec --- /dev/null +++ b/test/files/var/reset_reason @@ -0,0 +1,2 @@ +reset reason: REBOOT +reset triggered: upgrade diff --git a/test/funl/validation/bbf.validation.json b/test/funl/validation/bbf.validation.json index 7ed2e54f..20fdfc86 100644 --- a/test/funl/validation/bbf.validation.json +++ b/test/funl/validation/bbf.validation.json @@ -5,7 +5,7 @@ "method": "get", "args": { "path": "Device.DeviceInfo.Manufacturer", - "optional": {"format":"raw", "proto":"usp"} + "optional": {"proto":"usp"} }, "rc": 0 }, @@ -13,7 +13,7 @@ "method": "get", "args": { "path": "Device.DeviceInfo.Manufacturer", - "optional": {"format":"raw", "proto":"cwmp"} + "optional": {"proto":"cwmp"} }, "rc": 0 }, @@ -21,7 +21,7 @@ "method": "get", "args": { "path":"Device.WiFi.SSID.*.Alias", - "optional": {"format":"raw", "proto":"cwmp"} + "optional": {"proto":"cwmp"} }, "rc": 0 }, @@ -29,7 +29,7 @@ "method": "get", "args": { "path": "Device.DeviceInfo.Manufacturer", - "optional": {"format":"raw", "proto":"both"} + "optional": {"proto":"both"} }, "rc": 0 }, @@ -40,15 +40,6 @@ }, "rc": 0 }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "optional": {"format":"raw", "proto":"usp"}, - "maxdepth": "1" - }, - "rc": 0 - }, { "method": "get", "args": { @@ -78,7 +69,7 @@ "method": "instances", "args": { "path": "Device.WiFi.SSID.", - "optional": {"format":"raw", "proto":"usp"} + "optional": {"proto":"usp"} }, "rc": 0 }, @@ -104,14 +95,6 @@ }, "rc": 0 }, - { - "method": "get", - "args": { - "paths": ["Device.WiFi.SSID.1.SSID","Device.WiFi.SSID.2.SSID"], - "proto": "usp" - }, - "rc": 0 - }, { "method": "set", "args": { diff --git a/test/python/validate_3536.py b/test/python/validate_3536.py deleted file mode 100755 index 02007a4b..00000000 --- a/test/python/validate_3536.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/python3 - -import subprocess -import json - -TEST_NAME = "BUG_3536" - -print("Running: " + TEST_NAME) - -def bbf_get(path, proto = ""): - path_arg = "{\"path\":\"" + path + "\", \"optional\":{\"format\":\"raw\", \"proto\":\"" + proto + "\"}}" - cmd = ['ubus', 'call', 'bbfdm', 'get', path_arg] - - out = subprocess.Popen(cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - - stdout,stderr = out.communicate() - return stdout - -# check fault code of invalid path -output = json.loads(bbf_get("Device", "usp")) -assert output["results"][0]["fault"] == 7026, "Wrong fault code" - -# check fault code of invalid path -output = json.loads(bbf_get("Device", "cwmp")) -assert output["results"][0]["fault"] == 9005, "Wrong fault code for cwmp" - -# check fault code of invalid path -output = json.loads(bbf_get("Device")) -assert output["results"][0]["fault"] == 9005, "Wrong fault code for default proto" - -print("PASS: " + TEST_NAME) diff --git a/test/python/validate_device.py b/test/python/validate_device.py index 0ce5ea4d..05056744 100755 --- a/test/python/validate_device.py +++ b/test/python/validate_device.py @@ -15,12 +15,11 @@ if sock.exists(): else: assert ubus.connect() -out = ubus.call('bbfdm', 'get', {"path":"Device.", "optional":{"format":"raw"}}) -assert isinstance(out[0]["results"][0], dict), "FAIL: get Device. on bbf with raw format" - -# Check get operation for Device. path succeed out = ubus.call('bbfdm', 'get', {"path":"Device."}) -assert isinstance(out[0]['Device'], dict), "FAIL: get Device. on bbf with pretty format" +assert isinstance(out[0]["results"][0], dict), "FAIL: get Device." + +out = ubus.call('bbfdm', 'get', {"path":"Device"}) +assert out[0]["results"][0]["fault"] == 9005, "FAIL: get Device" ubus.disconnect() print("PASS: " + TEST_NAME) diff --git a/test/python/validate_ubus_event.py b/test/python/validate_ubus_event.py deleted file mode 100755 index 87ce7162..00000000 --- a/test/python/validate_ubus_event.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/python3 - -import ubus -import json -import pathlib - -TEST_NAME = "Validate ubus event bbf" - -print("Running: " + TEST_NAME) - -def callback(event, data): - print("PASS: " + TEST_NAME) - ubus.disconnect() - exit(0) - -sock = pathlib.Path('/var/run/ubus/ubus.sock') -if sock.exists (): - assert ubus.connect('/var/run/ubus/ubus.sock') -else: - assert ubus.connect() - -ubus.listen(("bbfdm.event", callback)) - -ubus.call("bbfdm", "notify_event", {"name":"Device.LocalAgent.TransferComplete!", "input":[{"path":"Command","data":"Backup()","type":"xsd:string"},{"path":"CommandKey","data":"","type":"xsd:string"}]}) - -ubus.loop() - -ubus.disconnect() - -print("FAIL: " + TEST_NAME) diff --git a/test/tools/dm-cli.c b/test/tools/dm-cli.c index a0ea164f..d18ce756 100644 --- a/test/tools/dm-cli.c +++ b/test/tools/dm-cli.c @@ -54,7 +54,6 @@ int main(int argc, char **argv) DMOBJ *CLI_DM_ROOT_OBJ = NULL; void *cli_lib_handle = NULL; struct dmctx bbfdm_ctx = {0}; - bbfdm_config_t bbfdm_config = {0}; char *plugin_path = NULL, *plugin_dir = NULL, *dm_path = NULL; unsigned int proto = BBFDM_BOTH; int err = 0, ch; @@ -83,9 +82,9 @@ int main(int argc, char **argv) } if (plugin_path == NULL) { - err = bbfdm_load_internal_plugin(NULL, tDynamicObj, &bbfdm_config, &CLI_DM_ROOT_OBJ); + err = bbfdm_load_internal_plugin(NULL, tDynamicObj, &CLI_DM_ROOT_OBJ); } else { - err = bbfdm_load_dotso_plugin(NULL, &cli_lib_handle, plugin_path, &bbfdm_config, &CLI_DM_ROOT_OBJ); + err = bbfdm_load_dotso_plugin(NULL, &cli_lib_handle, plugin_path, &CLI_DM_ROOT_OBJ); } if (err || !CLI_DM_ROOT_OBJ) { diff --git a/test/vendor_test/Makefile b/test/vendor_test/Makefile index e02de4cf..9d567309 100644 --- a/test/vendor_test/Makefile +++ b/test/vendor_test/Makefile @@ -13,8 +13,8 @@ $(LIB): $(LIB_OBJS) $(CC) $(LIB_CFLAGS) $(LIB_LDFLAGS) -shared -o $@ $^ install: - cp -f $(LIB) /usr/share/bbfdm/plugins/ - cp -f *.json /usr/share/bbfdm/plugins + cp -f $(LIB) /usr/share/bbfdm/micro_services/core/ + cp -f *.json /usr/share/bbfdm/micro_services/core/ clean: rm -fv *.o $(LIB) diff --git a/tools/bbf_common.py b/tools/bbf_common.py index 058c1fee..7fc9e946 100755 --- a/tools/bbf_common.py +++ b/tools/bbf_common.py @@ -12,7 +12,7 @@ import glob # Constants BBF_ERROR_CODE = 0 CURRENT_PATH = os.getcwd() -BBF_PLUGIN_DIR = "/usr/share/bbfdm/plugins/" +BBF_MS_CORE_DIR = "/usr/share/bbfdm/micro_services/core/" BBF_MS_DIR = "/usr/share/bbfdm/micro_services/" DM_JSON_FILE = os.path.join(CURRENT_PATH, "tools", "datamodel.json") @@ -151,7 +151,7 @@ def generate_shared_library(dm_name, source_files, vendor_prefix, if is_microservice: outdir = BBF_MS_DIR else: - outdir = BBF_PLUGIN_DIR + outdir = BBF_MS_CORE_DIR output_library = outdir + dm_name @@ -233,7 +233,7 @@ def build_and_install_dmcli(): "-lbbfdm-ubus", "-lubox", "-lblobmsg_json", - "-lbbfdm", + "-lcore", "-ljson-c", "-lssl", "-lcrypto", @@ -257,7 +257,7 @@ def fill_list_dm(proto, dm_list, dm_name=None): if dm_name: command = f"dm-cli -l {dm_name}" else: - command = "dm-cli -p /usr/share/bbfdm/plugins" + command = "dm-cli -p /usr/share/bbfdm/micro_services/core" # Add the appropriate flag (-c or -u) based on the proto value if proto == "cwmp": @@ -411,7 +411,7 @@ def download_and_build_plugins(plugins, vendor_prefix): if filename.endswith('.c'): LIST_FILES.append(filename) elif filename.endswith('.json'): - install_json_plugin(filename, "/usr/share/bbfdm/plugins/"+f"{plugin_index}_{name}.json", prefix) + install_json_plugin(filename, "/usr/share/bbfdm/micro_services/core/"+f"{plugin_index}_{name}.json", prefix) else: BBF_ERROR_CODE += 1 print(f"# Unknown file format {filename} {BBF_ERROR_CODE}") diff --git a/tools/tools_input.json b/tools/tools_input.json index b7b8bcb6..aa3032f0 100644 --- a/tools/tools_input.json +++ b/tools/tools_input.json @@ -358,20 +358,13 @@ "proto": "git", "version": "devel", "dm_files": [ - "src/wifi.c" + "src/wifi.c", + "src/dataelements.c" ], "extra_dependencies": [ "-lm" ] }, - { - "repo": "https://dev.iopsys.eu/bbf/wifidmd.git", - "proto": "git", - "version": "devel", - "dm_files": [ - "src/dataelements.c" - ] - }, { "repo": "https://dev.iopsys.eu/hal/mcastmngr.git", "proto": "git", @@ -410,14 +403,6 @@ "test/obuspa_core_dm.json" ] }, - { - "repo": "https://dev.iopsys.eu/network/netmngr.git", - "proto": "git", - "version": "devel", - "dm_files": [ - "src/interfacestack.c" - ] - }, { "repo": "https://dev.iopsys.eu/network/netmngr.git", "proto": "git", @@ -438,7 +423,8 @@ "src/routeradvertisement.c", "src/routing.c", "src/ipv6rd.c", - "src/common.c" + "src/common.c", + "src/interfacestack.c" ] }, {