From bd07a43337c25fc37f5dc29a650943ff095a4988 Mon Sep 17 00:00:00 2001 From: Amin Ben Romdhane Date: Sun, 7 May 2023 22:08:52 +0200 Subject: [PATCH] bbfdm: Add support to expose DotSO and JSON plugins --- bbfdmd/README.md | 3 +- bbfdmd/src/CMakeLists.txt | 3 +- bbfdmd/src/bbfdmd.c | 88 +++++++++--- bbfdmd/src/cli.c | 73 ++++++++-- bbfdmd/src/common.h | 13 +- bbfdmd/src/events.c | 7 + bbfdmd/src/get_helper.c | 15 +- bbfdmd/src/plugin.c | 165 ++++++++++++++++++++++ bbfdmd/src/plugin.h | 35 +++++ gitlab-ci/bbfdmd-functional-test.sh | 6 +- json/input.json | 9 +- libbbfdm-api/dm_plugin/dmdynamicjson.c | 36 +++-- libbbfdm-api/dm_plugin/dmdynamicjson.h | 6 + libbbfdm-api/dm_plugin/dmdynamiclibrary.c | 17 +-- libbbfdm-api/dm_plugin/dmdynamiclibrary.h | 4 +- libbbfdm-api/dm_plugin/dmdynamicvendor.c | 2 +- libbbfdm-api/dmapi.h | 1 + libbbfdm-api/dmbbf.c | 2 +- libbbfdm-api/dmcommon.c | 2 +- libbbfdm-api/dmentry.c | 5 +- libbbfdm-api/dmentry.h | 2 - libbbfdm/dmtree/tr181/device.c | 6 + libbbfdm/dmtree/tr181/device.h | 2 + test/cmocka/functional_api_test_bbfd.c | 2 + test/cmocka/functional_test_bbfd.c | 4 + test/cmocka/unit_test_bbfd.c | 16 +++ 26 files changed, 435 insertions(+), 89 deletions(-) create mode 100644 bbfdmd/src/plugin.c create mode 100644 bbfdmd/src/plugin.h diff --git a/bbfdmd/README.md b/bbfdmd/README.md index 922d0ed8..b051aab9 100644 --- a/bbfdmd/README.md +++ b/bbfdmd/README.md @@ -83,8 +83,9 @@ Below is an example of json file: } } ``` +> NOTE1: `bbfdmd` CLI mode is an experimentation feature and it can be updated later. -> NOTE: If `-I` option is not passed when starting `bbfdmd`, so configuration options will be loaded from the default [INPUT.JSON](../../json/input.json) located in '/etc/bbfdm/input.json'. +> NOTE2: If `-I` option is not passed when starting `bbfdmd`, so configuration options will be loaded from the default [INPUT.JSON](../../json/input.json) located in '/etc/bbfdm/input.json'. * To see a list of arguments supported by `bbfdmd` use: diff --git a/bbfdmd/src/CMakeLists.txt b/bbfdmd/src/CMakeLists.txt index 9612b892..3cc8cddb 100644 --- a/bbfdmd/src/CMakeLists.txt +++ b/bbfdmd/src/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.0) PROJECT(bbfdmd) ADD_DEFINITIONS(-fstrict-aliasing -Wall -Wextra -Werror -Wformat -Wformat-signedness -fPIC -D_GNU_SOURCE) +ADD_DEFINITIONS(-DBBF_VENDOR_PREFIX="${BBF_VENDOR_PREFIX}") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SOURCE_DIR}") @@ -12,6 +13,6 @@ ENDIF() FILE(GLOB BBF_SOURCES *.c) ADD_EXECUTABLE(bbfdmd ${BBF_SOURCES}) -TARGET_LINK_LIBRARIES(bbfdmd ubus ubox blobmsg_json bbfdm-api bbfdm) +TARGET_LINK_LIBRARIES(bbfdmd ubus ubox blobmsg_json dl bbfdm-api) INSTALL(TARGETS bbfdmd DESTINATION usr/sbin) INSTALL(FILES ../../json/input.json DESTINATION etc/bbfdm) diff --git a/bbfdmd/src/bbfdmd.c b/bbfdmd/src/bbfdmd.c index 6525e1a5..d1646669 100644 --- a/bbfdmd/src/bbfdmd.c +++ b/bbfdmd/src/bbfdmd.c @@ -39,10 +39,15 @@ #include "events.h" #include "pretty_print.h" #include "get_helper.h" +#include "plugin.h" #include "cli.h" #include "libbbfdm-api/dmentry.h" #include "libbbfdm-api/dmjson.h" +extern struct list_head loaded_json_files; +extern struct list_head json_list; +extern struct list_head json_memhead; + #define USP_SUBPROCESS_DEPTH (2) #define BBF_SCHEMA_UPDATE_TIMEOUT (60 * 1000) #define BBF_INSTANCES_UPDATE_TIMEOUT (25 * 1000) @@ -52,6 +57,10 @@ // Global variables static unsigned int g_refresh_time = BBF_INSTANCES_UPDATE_TIMEOUT; static int g_subprocess_level = USP_SUBPROCESS_DEPTH; +static void *deamon_lib_handle = NULL; + +char UBUS_METHOD_NAME[32] = "bbfdm"; +bool enable_plugins = true; static void sig_handler(int sig) { @@ -84,7 +93,8 @@ static void usp_cleanup(struct usp_context *u) { free_path_list(&u->instances); free_path_list(&u->old_instances); - bbf_global_clean(DM_ROOT_OBJ); + bbf_global_clean(DEAMON_DM_ROOT_OBJ); + free_dotso_plugin(deamon_lib_handle); } static bool is_sync_operate_cmd(usp_data_t *data __attribute__((unused))) @@ -134,6 +144,8 @@ static void fill_optional_data(usp_data_t *data, struct blob_attr *msg) data->is_raw = is_str_eq(blobmsg_get_string(attr), "raw") ? true : false; } + data->bbf_ctx.enable_plugins = enable_plugins; + DEBUG("Proto:|%s|, Inst Mode:|%s|, Tran-id:|%d|, Format:|%s|", (data->bbf_ctx.dm_type == BBFDM_BOTH) ? "both" : (data->bbf_ctx.dm_type == BBFDM_CWMP) ? "cwmp" : "usp", (data->bbf_ctx.instance_mode == 0) ? "Number" : "Alias", @@ -919,7 +931,11 @@ static int usp_notify_event(struct ubus_context *ctx, struct ubus_object *obj, INFO("ubus method|%s|, name|%s|", method, obj->name); event_name = blobmsg_get_string(tb[BBF_NOTIFY_NAME]); if (is_registered_event(event_name)) { - ubus_send_event(ctx, BBF_EVENT, msg); + char method_name[40] = {0}; + + snprintf(method_name, sizeof(method_name), "%s.%s", UBUS_METHOD_NAME, BBF_EVENT); + + ubus_send_event(ctx, method_name, msg); } else { WARNING("Event %s not registered", event_name); } @@ -939,10 +955,10 @@ static struct ubus_method bbf_methods[] = { UBUS_METHOD("notify_event", usp_notify_event, dm_notify_event_policy), }; -static struct ubus_object_type bbf_type = UBUS_OBJECT_TYPE(METHOD_NAME, bbf_methods); +static struct ubus_object_type bbf_type = UBUS_OBJECT_TYPE(UBUS_METHOD_NAME, bbf_methods); static struct ubus_object bbf_object = { - .name = METHOD_NAME, + .name = UBUS_METHOD_NAME, .type = &bbf_type, .methods = bbf_methods, .n_methods = ARRAY_SIZE(bbf_methods) @@ -974,7 +990,7 @@ static void periodic_schema_updater(struct uloop_timeout *t) INFO("Schema update available"); blob_buf_init(&bb, 0); blobmsg_add_string(&bb, "action", "schema_update_available"); - ubus_notify(&u->ubus_ctx, &bbf_object, METHOD_NAME, bb.head, 1000); + ubus_notify(&u->ubus_ctx, &bbf_object, UBUS_METHOD_NAME, bb.head, 1000); blob_buf_free(&bb); } @@ -988,6 +1004,7 @@ static void broadcast_add_del_event(struct list_head *inst, bool is_add) struct ubus_context ctx; struct blob_buf bb; struct pathNode *ptr; + char method_name[40]; void *a; int ret; @@ -1011,10 +1028,12 @@ static void broadcast_add_del_event(struct list_head *inst, bool is_add) } blobmsg_close_array(&bb, a); + snprintf(method_name, sizeof(method_name), "%s.%s", UBUS_METHOD_NAME, is_add ? BBF_ADD_EVENT : BBF_DEL_EVENT); + if (is_add) - ubus_send_event(&ctx, BBF_ADD_EVENT, bb.head); + ubus_send_event(&ctx, method_name, bb.head); else - ubus_send_event(&ctx, BBF_DEL_EVENT, bb.head); + ubus_send_event(&ctx, method_name, bb.head); blob_buf_free(&bb); ubus_shutdown(&ctx); @@ -1025,6 +1044,7 @@ static void update_instances_list(struct list_head *inst) struct dmctx bbf_ctx = { .in_param = ROOT_NODE, .nextlevel = false, + .enable_plugins = enable_plugins, .instance_mode = INSTANCE_MODE_NUMBER, .dm_type = BBFDM_USP }; @@ -1165,43 +1185,79 @@ static void periodic_instance_updater(struct uloop_timeout *t) fork_instance_checker(u); } -static int bbfdm_load_config(const char *json_path) +static int bbfdm_load_deamon_config(const char *json_path) { - json_object *json_obj = NULL; char *opt_val = NULL; + int err = 0; if (!json_path || !strlen(json_path)) return -1; - json_obj = json_object_from_file(json_path); + json_object *json_obj = json_object_from_file(json_path); if (!json_obj) return -1; - opt_val = dmjson_get_value(json_obj, 3, "daemon", "config", "loglevel"); + json_object *deamon_obj = dmjson_get_obj(json_obj, 1, "daemon"); + if (!deamon_obj) { + err = -1; + goto exit; + } + + opt_val = dmjson_get_value(deamon_obj, 2, "config", "loglevel"); if (opt_val && strlen(opt_val)) { uint8_t log_level = (uint8_t) strtoul(opt_val, NULL, 10); set_debug_level(log_level); } - opt_val = dmjson_get_value(json_obj, 3, "daemon", "config", "refresh_time"); + opt_val = dmjson_get_value(deamon_obj, 2, "config", "refresh_time"); if (opt_val && strlen(opt_val)) { unsigned int refresh_time = (unsigned int) strtoul(opt_val, NULL, 10); g_refresh_time = refresh_time * 1000; } - opt_val = dmjson_get_value(json_obj, 3, "daemon", "config", "transaction_timeout"); + opt_val = dmjson_get_value(deamon_obj, 2, "config", "transaction_timeout"); if (opt_val && strlen(opt_val)) { int trans_timeout = (int) strtol(opt_val, NULL, 10); configure_transaction_timeout(trans_timeout); } - opt_val = dmjson_get_value(json_obj, 3, "daemon", "config", "subprocess_level"); + opt_val = dmjson_get_value(deamon_obj, 2, "config", "subprocess_level"); if (opt_val && strlen(opt_val)) { g_subprocess_level = (unsigned int) strtoul(opt_val, NULL, 10); } + opt_val = dmjson_get_value(deamon_obj, 2, "config", "enable_plugins"); + if (opt_val && strlen(opt_val)) { + enable_plugins = (unsigned int) strtoul(opt_val, NULL, 10); + } + + opt_val = dmjson_get_value(deamon_obj, 2, "output", "name"); + if (opt_val && strlen(opt_val)) { + strncpyt(UBUS_METHOD_NAME, opt_val, sizeof(UBUS_METHOD_NAME)); + } + + opt_val = dmjson_get_value(deamon_obj, 2, "input", "type"); + if (opt_val && strlen(opt_val)) { + char *file_path = dmjson_get_value(deamon_obj, 2, "input", "name"); + + if (strcasecmp(opt_val, "JSON") == 0) + err= load_json_plugin(&loaded_json_files, &json_list, &json_memhead, file_path, + &DEAMON_DM_ROOT_OBJ); + else if (strcasecmp(opt_val, "DotSo") == 0) + err = load_dotso_plugin(&deamon_lib_handle, file_path, + &DEAMON_DM_ROOT_OBJ, + DEAMON_DM_VENDOR_EXTENSION, + &DEAMON_DM_VENDOR_EXTENSION_EXCLUDE); + else + err = -1; + } else { + err = -1; + } + +exit: json_object_put(json_obj); - return 0; + + return err; } static int usp_init(struct usp_context *u) @@ -1236,7 +1292,7 @@ int main(int argc, char **argv) } } - err = bbfdm_load_config(input_json); + err = bbfdm_load_deamon_config(input_json); if (err != UBUS_STATUS_OK) { fprintf(stderr, "Failed to load bbfdm config from json file '%s'\n", input_json); return -1; diff --git a/bbfdmd/src/cli.c b/bbfdmd/src/cli.c index ef17497e..f6031c79 100644 --- a/bbfdmd/src/cli.c +++ b/bbfdmd/src/cli.c @@ -24,21 +24,33 @@ #include #include "common.h" +#include "plugin.h" #include "libbbfdm-api/dmapi.h" #include "libbbfdm-api/dmjson.h" #include "libbbfdm-api/dmentry.h" +extern struct list_head loaded_json_files; +extern struct list_head json_list; +extern struct list_head json_memhead; + #define UNUSED __attribute__((unused)) +static DMOBJ *CLIENT_DM_ROOT_OBJ = NULL; +static DM_MAP_VENDOR *CLIENT_DM_VENDOR_EXTENSION[2] = {0}; +static DM_MAP_VENDOR_EXCLUDE *CLIENT_DM_VENDOR_EXTENSION_EXCLUDE = NULL; + +static void *client_lib_handle = NULL; + typedef struct { struct dmctx bbf_ctx; unsigned int instance_mode; unsigned int proto; - char in_type[128]; char in_name[128]; - char out_type[128]; + char in_type[8]; + char out_type[8]; char *cmd; bool ubus_status; + bool enable_plugins; } client_data_t; typedef struct { @@ -284,6 +296,13 @@ static int bbfdm_load_client_config(const char *json_path, client_data_t *client client_data->instance_mode = INSTANCE_MODE_NUMBER; } + opt_val = dmjson_get_value(json_obj, 3, "client", "config", "enable_plugins"); + if (opt_val && strlen(opt_val)) { + client_data->enable_plugins = (unsigned int) strtoul(opt_val, NULL, 10); + } else { + client_data->enable_plugins = false; + } + opt_val = dmjson_get_value(json_obj, 3, "client", "input", "type"); if (opt_val && strlen(opt_val)) { snprintf(client_data->in_type, sizeof(client_data->in_type), "%s", opt_val); @@ -357,7 +376,7 @@ static int cli_exec_get(client_data_t *client_data, char *argv[]) { int err = EXIT_SUCCESS; - if (strcasecmp(client_data->in_type, "DotSO") == 0) + if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) err = in_dotso_out_cli_exec_get(client_data, argv); else if (strcasecmp(client_data->in_type, "UBUS") == 0) err = in_ubus_out_cli_exec_get(client_data, argv); @@ -396,7 +415,7 @@ static int cli_exec_set(client_data_t *client_data, char *argv[]) { int err = EXIT_SUCCESS; - if (strcasecmp(client_data->in_type, "DotSO") == 0) + if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) err = in_dotso_out_cli_exec_set(client_data, argv); else if (strcasecmp(client_data->in_type, "UBUS") == 0) err = in_ubus_out_cli_exec_set(client_data, argv); @@ -434,7 +453,7 @@ static int cli_exec_add(client_data_t *client_data, char *argv[]) { int err = EXIT_SUCCESS; - if (strcasecmp(client_data->in_type, "DotSO") == 0) + if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) err = in_dotso_out_cli_exec_add(client_data, argv); else if (strcasecmp(client_data->in_type, "UBUS") == 0) err = in_ubus_out_cli_exec_add(client_data, argv); @@ -472,7 +491,7 @@ static int cli_exec_del(client_data_t *client_data, char *argv[]) { int err = EXIT_SUCCESS; - if (strcasecmp(client_data->in_type, "DotSO") == 0) + if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) err = in_dotso_out_cli_exec_del(client_data, argv); else if (strcasecmp(client_data->in_type, "UBUS") == 0) err = in_ubus_out_cli_exec_del(client_data, argv); @@ -513,7 +532,7 @@ static int cli_exec_instances(client_data_t *client_data, char *argv[]) { int err = EXIT_SUCCESS; - if (strcasecmp(client_data->in_type, "DotSO") == 0) + if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) err = in_dotso_out_cli_exec_instances(client_data, argv); else if (strcasecmp(client_data->in_type, "UBUS") == 0) err = in_ubus_out_cli_exec_instances(client_data, argv); @@ -595,7 +614,7 @@ static int cli_exec_schema(client_data_t *client_data, char *argv[]) { int err = EXIT_SUCCESS; - if (strcasecmp(client_data->in_type, "DotSO") == 0) + if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) err = in_dotso_out_cli_exec_schema(client_data, argv); else if (strcasecmp(client_data->in_type, "UBUS") == 0) err = in_ubus_out_cli_exec_schema(client_data, argv); @@ -615,18 +634,42 @@ static int cli_exec_command(client_data_t *client_data, int argc, char *argv[]) if (!client_data->cmd || strlen(client_data->cmd) == 0) return EXIT_FAILURE; - if (strcasecmp(client_data->in_type, "DotSO") == 0) { + if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) { - bbf_ctx_init(&client_data->bbf_ctx, DM_ROOT_OBJ, DM_VENDOR_EXTENSION, DM_VENDOR_EXTENSION_EXCLUDE); + if (strcasecmp(client_data->in_type, "DotSO") == 0) { + if (load_dotso_plugin(&client_lib_handle, client_data->in_name, + &CLIENT_DM_ROOT_OBJ, + CLIENT_DM_VENDOR_EXTENSION, + &CLIENT_DM_VENDOR_EXTENSION_EXCLUDE) != 0) { + err = EXIT_FAILURE; + goto end; + } + } else { + if (load_json_plugin(&loaded_json_files, &json_list, &json_memhead, client_data->in_name, + &CLIENT_DM_ROOT_OBJ) != 0) { + err = EXIT_FAILURE; + goto end; + } + } + + if (CLIENT_DM_ROOT_OBJ == NULL) { + err = EXIT_FAILURE; + goto end; + } + + bbf_ctx_init(&client_data->bbf_ctx, CLIENT_DM_ROOT_OBJ, CLIENT_DM_VENDOR_EXTENSION, CLIENT_DM_VENDOR_EXTENSION_EXCLUDE); client_data->bbf_ctx.dm_type = client_data->proto; client_data->bbf_ctx.instance_mode = client_data->instance_mode; + client_data->bbf_ctx.enable_plugins = client_data->enable_plugins; + } else if (strcasecmp(client_data->in_type, "UBUS") != 0) { + return -1; } for (size_t i = 0; i < ARRAY_SIZE(cli_commands); i++) { cli_cmd = &cli_commands[i]; - if (strcmp(client_data->cmd, cli_cmd->name)==0) { + if (strcmp(client_data->cmd, cli_cmd->name) == 0) { if (argc-1 < cli_cmd->num_args) { printf("ERROR: Number of arguments for %s method is wrong(%d), it should be %d\n", cli_cmd->name, argc-1, cli_cmd->num_args); @@ -644,13 +687,17 @@ static int cli_exec_command(client_data_t *client_data, int argc, char *argv[]) if (!registred_command) { printf("ERROR: Unknown command: %s\n", client_data->cmd); cli_commands[0].exec_cmd(client_data, NULL); - return EXIT_FAILURE; + err = EXIT_FAILURE; } end: if (strcasecmp(client_data->in_type, "DotSO") == 0) { bbf_ctx_clean(&client_data->bbf_ctx); - bbf_global_clean(DM_ROOT_OBJ); + bbf_global_clean(CLIENT_DM_ROOT_OBJ); + free_dotso_plugin(client_lib_handle); + } else if (strcasecmp(client_data->in_type, "JSON") == 0) { + bbf_ctx_clean(&client_data->bbf_ctx); + free_json_plugin(); } return err; diff --git a/bbfdmd/src/common.h b/bbfdmd/src/common.h index 0403aadf..214a8058 100644 --- a/bbfdmd/src/common.h +++ b/bbfdmd/src/common.h @@ -17,10 +17,9 @@ #include "bbfdmd.h" #define ROOT_NODE "Device." -#define METHOD_NAME "bbfdm" -#define BBF_ADD_EVENT METHOD_NAME".AddObj" -#define BBF_DEL_EVENT METHOD_NAME".DelObj" -#define BBF_EVENT METHOD_NAME".event" +#define BBF_ADD_EVENT "AddObj" +#define BBF_DEL_EVENT "DelObj" +#define BBF_EVENT "event" #define MAX_DM_KEY_LEN 256 #define MAX_DM_PATH 1024 @@ -34,9 +33,9 @@ #define USP_ERR_OK 0 -extern DMOBJ *DM_ROOT_OBJ; -extern DM_MAP_VENDOR *DM_VENDOR_EXTENSION[2]; -extern DM_MAP_VENDOR_EXCLUDE *DM_VENDOR_EXTENSION_EXCLUDE; +extern DMOBJ *DEAMON_DM_ROOT_OBJ; +extern DM_MAP_VENDOR *DEAMON_DM_VENDOR_EXTENSION[2]; +extern DM_MAP_VENDOR_EXCLUDE *DEAMON_DM_VENDOR_EXTENSION_EXCLUDE; bool match(const char *string, const char *pattern); bool is_str_eq(const char *s1, const char *s2); diff --git a/bbfdmd/src/events.c b/bbfdmd/src/events.c index 3c798a0d..11f69902 100644 --- a/bbfdmd/src/events.c +++ b/bbfdmd/src/events.c @@ -26,6 +26,9 @@ #include "get_helper.h" #include +extern char UBUS_METHOD_NAME[32]; +extern bool enable_plugins; + static struct event_map_list ev_map_list[] = { /* { event name, DM Path, .arguments[] = { event_args, dm_args } } */ { "wifi.dataelements.Associated", "Device.WiFi.DataElements.AssociationEvent.Associated!", @@ -171,6 +174,7 @@ static void uspd_event_handler(struct ubus_context *ctx, struct ubus_event_handl serialize_blob_msg(msg, "", &pv_list); struct blob_buf b, bb; + char method_name[40] = {0}; memset(&b, 0, sizeof(struct blob_buf)); memset(&bb, 0, sizeof(struct blob_buf)); @@ -178,6 +182,8 @@ static void uspd_event_handler(struct ubus_context *ctx, struct ubus_event_handl blob_buf_init(&b, 0); blob_buf_init(&bb, 0); + snprintf(method_name, sizeof(method_name), "%s.%s", UBUS_METHOD_NAME, BBF_EVENT); + blobmsg_add_string(&b, "name", dm_path); generate_blob_input(&bb, type, &pv_list); blobmsg_add_field(&b, BLOBMSG_TYPE_TABLE, "input", blob_data(bb.head), blob_len(bb.head)); @@ -269,6 +275,7 @@ bool is_registered_event(char *name) .iscommand = false, .isevent = true, .isinfo = false, + .enable_plugins = enable_plugins, .instance_mode = INSTANCE_MODE_NUMBER, .dm_type = BBFDM_USP }; diff --git a/bbfdmd/src/get_helper.c b/bbfdmd/src/get_helper.c index 160a17b3..7e3f04f2 100644 --- a/bbfdmd/src/get_helper.c +++ b/bbfdmd/src/get_helper.c @@ -31,15 +31,10 @@ #include "pretty_print.h" #include "libbbfdm-api/dmentry.h" -#include "libbbfdm/dmtree/tr181/device.h" -#include "libbbfdm/dmtree/vendor/vendor.h" -DMOBJ *DM_ROOT_OBJ = tEntryRoot; -DM_MAP_VENDOR *DM_VENDOR_EXTENSION[2] = { - tVendorExtension, - tVendorExtensionOverwrite -}; -DM_MAP_VENDOR_EXCLUDE *DM_VENDOR_EXTENSION_EXCLUDE = tVendorExtensionExclude; +DMOBJ *DEAMON_DM_ROOT_OBJ = NULL; +DM_MAP_VENDOR *DEAMON_DM_VENDOR_EXTENSION[2] = {0}; +DM_MAP_VENDOR_EXCLUDE *DEAMON_DM_VENDOR_EXTENSION_EXCLUDE = NULL; // uloop.h does not have versions, below line is to use // deprecated uloop_timeout_remaining for the time being @@ -79,7 +74,7 @@ void bb_add_string(struct blob_buf *bb, const char *name, const char *value) void bbf_init(struct dmctx *dm_ctx) { - bbf_ctx_init(dm_ctx, DM_ROOT_OBJ, DM_VENDOR_EXTENSION, DM_VENDOR_EXTENSION_EXCLUDE); + bbf_ctx_init(dm_ctx, DEAMON_DM_ROOT_OBJ, DEAMON_DM_VENDOR_EXTENSION, DEAMON_DM_VENDOR_EXTENSION_EXCLUDE); } void bbf_cleanup(struct dmctx *dm_ctx) @@ -89,7 +84,7 @@ void bbf_cleanup(struct dmctx *dm_ctx) void bbf_sub_init(struct dmctx *dm_ctx) { - bbf_ctx_init_sub(dm_ctx, DM_ROOT_OBJ, DM_VENDOR_EXTENSION, DM_VENDOR_EXTENSION_EXCLUDE); + bbf_ctx_init_sub(dm_ctx, DEAMON_DM_ROOT_OBJ, DEAMON_DM_VENDOR_EXTENSION, DEAMON_DM_VENDOR_EXTENSION_EXCLUDE); } void bbf_sub_cleanup(struct dmctx *dm_ctx) diff --git a/bbfdmd/src/plugin.c b/bbfdmd/src/plugin.c new file mode 100644 index 00000000..7b0f5def --- /dev/null +++ b/bbfdmd/src/plugin.c @@ -0,0 +1,165 @@ +/* + * plugin.c: Plugin file bbfdmd + * + * Copyright (C) 2023 iopsys Software Solutions AB. All rights reserved. + * + * Author: Amin Ben Romdhane + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include + +#include "common.h" +#include "libbbfdm-api/dmapi.h" +#include "libbbfdm-api/dm_plugin/dmdynamicjson.h" + +extern struct list_head global_memhead; + +int load_dotso_plugin(void **lib_handle, const char *file_path, + DMOBJ **main_entry, + DM_MAP_VENDOR *main_Extension[], + DM_MAP_VENDOR_EXCLUDE **main_Extension_exclude) +{ + if (!lib_handle || !file_path || !strlen(file_path) || !main_entry || !main_Extension || !main_Extension_exclude) + return -1; + + void *handle = dlopen(file_path, RTLD_NOW|RTLD_LOCAL); + if (!handle) { + fprintf(stderr, "ERROR: Plugin failed [%s]\n", dlerror()); + return -1; + } + + *lib_handle = handle; + + //Dynamic Object + DM_MAP_OBJ *dynamic_obj = NULL; + *(void **) (&dynamic_obj) = dlsym(handle, "tDynamicObj"); + if (dynamic_obj) { + char *node_obj = dm_dynamic_strdup(&global_memhead, dynamic_obj[0].path); + unsigned int len = strlen(node_obj); + + if (strncmp(node_obj, ROOT_NODE, strlen(ROOT_NODE)) != 0 || node_obj[len-1] != '.') { + fprintf(stderr, "ERROR: Object (%s) not valid\n", node_obj); + return -1; + } + + DMOBJ *dm_entryobj = (DMOBJ *)dm_dynamic_calloc(&global_memhead, 2, sizeof(DMOBJ)); + if (dm_entryobj == NULL) { + fprintf(stderr, "ERROR: No Memory exists\n"); + return -1; + } + + node_obj[len-1] = 0; + + dm_entryobj[0].obj = node_obj; + dm_entryobj[0].permission = &DMREAD; + dm_entryobj[0].nextobj = dynamic_obj[0].root_obj; + dm_entryobj[0].leaf = dynamic_obj[0].root_leaf; + dm_entryobj[0].bbfdm_type = BBFDM_BOTH; + + *main_entry = dm_entryobj; + } else { + fprintf(stderr, "ERROR: Main entry not available"); + return -1; + } + + //Vendor Extension + DM_MAP_VENDOR *vendor_extension = NULL; + *(void **) (&vendor_extension) = dlsym(handle, "tVendorExtension"); + if (vendor_extension) main_Extension[0] = vendor_extension; + + //Vendor Extension Overwrite + DM_MAP_VENDOR *vendor_extension_overwrite = NULL; + *(void **) (&vendor_extension_overwrite) = dlsym(handle, "tVendorExtensionOverwrite"); + if (vendor_extension_overwrite) main_Extension[1] = vendor_extension_overwrite; + + //Vendor Extension Exclude + DM_MAP_VENDOR_EXCLUDE *vendor_extension_exclude = NULL; + *(void **) (&vendor_extension_exclude) = dlsym(handle, "tVendorExtensionExclude"); + if (vendor_extension_exclude) *main_Extension_exclude = vendor_extension_exclude; + + return 0; +} + +int free_dotso_plugin(void *lib_handle) +{ + if (lib_handle) + dlclose(lib_handle); + + return 0; +} + +int load_json_plugin(struct list_head *json_plugin, struct list_head *json_list, struct list_head *json_memhead, const char *file_path, + DMOBJ **main_entry) +{ + int json_plugin_version = 0; + + if (!file_path || !strlen(file_path) || !main_entry) + return -1; + + json_object *json_obj = json_object_from_file(file_path); + if (!json_obj) + return -1; + + save_loaded_json_files(json_plugin, json_obj); + + json_object_object_foreach(json_obj, key, jobj) { + + if (strcmp(key, "json_plugin_version") == 0) { + json_plugin_version = json_object_get_int(jobj); + continue; + } + + char *node_obj = replace_str(key, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX); + unsigned int len = strlen(node_obj); + + if (strncmp(node_obj, ROOT_NODE, strlen(ROOT_NODE)) != 0 || node_obj[len-1] != '.') { + fprintf(stderr, "ERROR: Object (%s) not valid\n", node_obj); + return -1; + } + + char obj_prefix[512] = {0}; + find_prefix_obj(node_obj, obj_prefix, sizeof(obj_prefix)); + obj_prefix[strlen(obj_prefix)-1] = 0; + + DMOBJ *dm_entryobj = (DMOBJ *)dm_dynamic_calloc(json_memhead, 2, sizeof(DMOBJ)); + if (dm_entryobj == NULL) { + fprintf(stderr, "ERROR: No Memory exists\n"); + return -1; + } + + *main_entry = dm_entryobj; + + dm_entryobj[0].obj = dm_dynamic_strdup(json_memhead, obj_prefix); + dm_entryobj[0].permission = &DMREAD; + dm_entryobj[0].nextobj = (DMOBJ *)dm_dynamic_calloc(json_memhead, 2, sizeof(DMOBJ)); + dm_entryobj[0].leaf = NULL; + dm_entryobj[0].bbfdm_type = BBFDM_BOTH; + + parse_obj(node_obj, jobj, dm_entryobj[0].nextobj, 0, json_plugin_version, json_list); + FREE(node_obj); + break; + } + + return 0; +} + +int free_json_plugin(void) +{ + return free_json_loaded_object(); +} diff --git a/bbfdmd/src/plugin.h b/bbfdmd/src/plugin.h new file mode 100644 index 00000000..acb4ed3b --- /dev/null +++ b/bbfdmd/src/plugin.h @@ -0,0 +1,35 @@ +/* + * plugin.h: Plugin file bbfdmd + * + * Copyright (C) 2023 iopsys Software Solutions AB. All rights reserved. + * + * Author: Amin Ben Romdhane + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef PLUGIN_H + +int load_dotso_plugin(void **lib_handle, const char *file_path, + DMOBJ **main_entry, + DM_MAP_VENDOR *tVendorExtension[], + DM_MAP_VENDOR_EXCLUDE **tVendorExtensionExclude); +int free_dotso_plugin(void *lib_handle); + +int load_json_plugin(struct list_head *json_plugin, struct list_head *json_list, struct list_head *json_memhead, const char *file_path, + DMOBJ **main_entry); +int free_json_plugin(void); + +#endif /* PLUGIN_H */ diff --git a/gitlab-ci/bbfdmd-functional-test.sh b/gitlab-ci/bbfdmd-functional-test.sh index f0be3fb4..27d284f7 100755 --- a/gitlab-ci/bbfdmd-functional-test.sh +++ b/gitlab-ci/bbfdmd-functional-test.sh @@ -43,14 +43,10 @@ done echo "1..${num}" >> ./funl-result.log generate_report python_test ./funl-result.log -# run functional on bbf object validation -rm /usr/share/rpcd/schemas/bbf.json -fault=0 - # run functional on bbf object validation cp -r ./schemas/ubus/bbfdm.json /usr/share/rpcd/schemas/bbf.json ubus-api-validator -t 5 -f ./test/funl/validation/bbf.validation.json > ./funl-result.log -fault=$(( $fault + $? )) +fault=$? generate_report bbf_positive ./funl-result.log supervisorctl stop all diff --git a/json/input.json b/json/input.json index 6cd60d83..e8c369f0 100755 --- a/json/input.json +++ b/json/input.json @@ -1,10 +1,12 @@ { "daemon": { "config": { + "refresh_time": 10, + "enable_plugins": 1 }, "input": { - "type": "DotSO", - "name": "/usr/lib/libbbfdm.so" + "type": "DotSo", + "name": "/lib/libbbfdm.so" }, "output": { "type": "UBUS", @@ -14,7 +16,8 @@ "client": { "config": { "proto": "usp", - "instance_mode": 0 + "instance_mode": 0, + "enable_plugins": 0 }, "input": { "type": "UBUS", diff --git a/libbbfdm-api/dm_plugin/dmdynamicjson.c b/libbbfdm-api/dm_plugin/dmdynamicjson.c index 8ddf4f83..cd0c9c4b 100644 --- a/libbbfdm-api/dm_plugin/dmdynamicjson.c +++ b/libbbfdm-api/dm_plugin/dmdynamicjson.c @@ -14,9 +14,9 @@ #define MAX_DM_LENGTH (1024) #define json_object_get_string(x) (char *)json_object_get_string(x) -static LIST_HEAD(loaded_json_files); -static LIST_HEAD(json_list); -static LIST_HEAD(json_memhead); +LIST_HEAD(loaded_json_files); +LIST_HEAD(json_list); +LIST_HEAD(json_memhead); static operation_args empty_cmd = { .in = (const char**)NULL, @@ -89,7 +89,7 @@ static void free_json_data(struct list_head *json_list) } } -static void save_loaded_json_files(struct list_head *json_list, json_object *data) +void save_loaded_json_files(struct list_head *json_list, json_object *data) { struct loaded_json_file *json_file = calloc(1, sizeof(struct loaded_json_file)); list_add_tail(&json_file->list, json_list); @@ -145,7 +145,15 @@ int free_json_dynamic_arrays(DMOBJ *dm_entryobj) return 0; } -static void find_prefix_obj(char *full_obj, char *prefix_obj, size_t len) +int free_json_loaded_object(void) +{ + free_loaded_json_files(&loaded_json_files); + free_json_data(&json_list); + dm_dynamic_cleanmem(&json_memhead); + return 0; +} + +void find_prefix_obj(char *full_obj, char *prefix_obj, size_t len) { int last_occurent = 0, occur = 0; @@ -160,7 +168,7 @@ static void find_prefix_obj(char *full_obj, char *prefix_obj, size_t len) *(full_object + last_occurent + 1) = 0; snprintf(prefix_obj, len, "%s", full_object); - dmfree(full_object); + FREE(full_object); } static void find_current_obj(char *full_obj, char *curr_obj, size_t len) @@ -178,7 +186,7 @@ static void find_current_obj(char *full_obj, char *curr_obj, size_t len) full_object[occur] = 0; snprintf(curr_obj, len, "%s", full_object + last_occurent + 1); - dmfree(full_object); + FREE(full_object); } static void generate_path_without_instance(char *full_obj, bool is_obj, char *obj_path, size_t len) @@ -763,6 +771,7 @@ static char *uci_get_value(json_object *mapping_obj, int json_version, char *ref dmasprintf(&value, "cpe-%s", instance); end: + FREE(linker); return value; } @@ -1782,6 +1791,7 @@ static void parse_param(char *object, char *param, json_object *jobj, DMLEAF *pl pleaf[i].bbfdm_type = BBFDM_BOTH; snprintf(full_param, sizeof(full_param), "%s%s", object, param_ext); + FREE(param_ext); save_json_data(list, full_param, jobj, json_version, (const char**)in_p, (const char**)out_p, (const char**)ev_arg); } @@ -1802,7 +1812,7 @@ static void count_obj_param_under_jsonobj(json_object *jsonobj, int *obj_number, } } -static void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, int json_version, struct list_head *list) +void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, int json_version, struct list_head *list) { /* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys(13)*/ @@ -1816,7 +1826,7 @@ static void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, i char *obj_path = replace_str(object, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX); char *full_obj = replace_str(obj_path, ".{i}.", "."); find_current_obj(full_obj, curr_obj, sizeof(curr_obj)); - dmfree(obj_path); + FREE(obj_path); if (!pobj) return; @@ -1913,6 +1923,8 @@ static void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, i i++; } } + + FREE(full_obj); } int load_json_dynamic_arrays(struct dmctx *ctx) @@ -1950,8 +1962,10 @@ int load_json_dynamic_arrays(struct dmctx *ctx) find_prefix_obj(obj_path, obj_prefix, MAX_DM_LENGTH); bool obj_exists = find_root_entry(ctx, obj_prefix, &dm_entryobj); - if (obj_exists == 0 || !dm_entryobj) + if (obj_exists == 0 || !dm_entryobj) { + FREE(obj_path); continue; + } if (dm_entryobj->nextdynamicobj == NULL) { dm_entryobj->nextdynamicobj = calloc(__INDX_DYNAMIC_MAX, sizeof(struct dm_dynamic_obj)); @@ -1973,6 +1987,8 @@ int load_json_dynamic_arrays(struct dmctx *ctx) memset(dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0] + (idx + 1), 0, sizeof(struct dm_obj_s)); parse_obj(obj_path, jobj, dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].nextobj[0], idx, json_plugin_version, &json_list); } + + FREE(obj_path); } save_loaded_json_files(&loaded_json_files, json); } diff --git a/libbbfdm-api/dm_plugin/dmdynamicjson.h b/libbbfdm-api/dm_plugin/dmdynamicjson.h index 76710fc7..b63daad1 100644 --- a/libbbfdm-api/dm_plugin/dmdynamicjson.h +++ b/libbbfdm-api/dm_plugin/dmdynamicjson.h @@ -16,6 +16,12 @@ #define JSON_FOLDER_PATH "/etc/bbfdm/json" +void save_loaded_json_files(struct list_head *json_list, json_object *data); +void parse_obj(char *object, json_object *jobj, DMOBJ *pobj, int index, int json_version, struct list_head *list); +void find_prefix_obj(char *full_obj, char *prefix_obj, size_t len); +int free_json_loaded_object(void); + + int load_json_dynamic_arrays(struct dmctx *ctx); int free_json_dynamic_arrays(DMOBJ *dm_entryobj); diff --git a/libbbfdm-api/dm_plugin/dmdynamiclibrary.c b/libbbfdm-api/dm_plugin/dmdynamiclibrary.c index a9292ce2..5438631c 100644 --- a/libbbfdm-api/dm_plugin/dmdynamiclibrary.c +++ b/libbbfdm-api/dm_plugin/dmdynamiclibrary.c @@ -1,18 +1,17 @@ /* - * Copyright (C) 2021 iopsys Software Solutions AB + * Copyright (C) 2023 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 Ramdhane + * Author Amin Ben Romdhane * */ #include "dmdynamiclibrary.h" LIST_HEAD(loaded_library_list); -LIST_HEAD(library_memhead); struct loaded_library { @@ -20,14 +19,6 @@ struct loaded_library void *library; }; -struct dynamic_operate -{ - struct list_head list; - char *operate_path; - void *operate; - void *operate_args; -}; - static void add_list_loaded_libraries(struct list_head *library_list, void *library) { struct loaded_library *lib = calloc(1, sizeof(struct loaded_library)); @@ -79,7 +70,6 @@ void free_library_dynamic_arrays(DMOBJ *dm_entryobj) DMNODE node = {.current_object = ""}; free_all_list_open_library(&loaded_library_list); - dm_dynamic_cleanmem(&library_memhead); dm_browse_node_dynamic_object_tree(&node, root); } @@ -99,11 +89,10 @@ int load_library_dynamic_arrays(struct dmctx *ctx) void *handle = dlopen(buf, RTLD_NOW|RTLD_LOCAL); if (!handle) { - fprintf(stderr, "Plugin failed [%s]", dlerror()); + fprintf(stderr, "Plugin failed [%s]\n", dlerror()); continue; } - //Dynamic Object DM_MAP_OBJ *dynamic_obj = NULL; *(void **) (&dynamic_obj) = dlsym(handle, "tDynamicObj"); diff --git a/libbbfdm-api/dm_plugin/dmdynamiclibrary.h b/libbbfdm-api/dm_plugin/dmdynamiclibrary.h index 9dfa47ff..d6af7893 100644 --- a/libbbfdm-api/dm_plugin/dmdynamiclibrary.h +++ b/libbbfdm-api/dm_plugin/dmdynamiclibrary.h @@ -1,11 +1,11 @@ /* - * Copyright (C) 2021 iopsys Software Solutions AB + * Copyright (C) 2023 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 Ramdhane + * Author Amin Ben Romdhane * */ diff --git a/libbbfdm-api/dm_plugin/dmdynamicvendor.c b/libbbfdm-api/dm_plugin/dmdynamicvendor.c index 0a6a5018..9f9c44f5 100644 --- a/libbbfdm-api/dm_plugin/dmdynamicvendor.c +++ b/libbbfdm-api/dm_plugin/dmdynamicvendor.c @@ -225,7 +225,7 @@ static void exclude_obj(struct dmctx *ctx, char *in_obj) char *obj_path = replace_str(in_obj, ".{i}.", "."); dm_exclude_obj(ctx, &node, root, obj_path); - dmfree(obj_path); + FREE(obj_path); } static void exclude_param(struct dmctx *ctx, char *in_param) diff --git a/libbbfdm-api/dmapi.h b/libbbfdm-api/dmapi.h index 2fb4df8a..1c03896b 100644 --- a/libbbfdm-api/dmapi.h +++ b/libbbfdm-api/dmapi.h @@ -197,6 +197,7 @@ struct dmctx { bool iscommand; bool isevent; bool isinfo; + bool enable_plugins; }; typedef struct dmnode { diff --git a/libbbfdm-api/dmbbf.c b/libbbfdm-api/dmbbf.c index d6e75f42..90aac121 100644 --- a/libbbfdm-api/dmbbf.c +++ b/libbbfdm-api/dmbbf.c @@ -686,7 +686,7 @@ bool find_root_entry(struct dmctx *ctx, char *in_param, DMOBJ **root_entry) char *old_in_param = ctx->in_param; dm_check_dynamic_obj(ctx, &node, root, obj_path, obj_path, root_entry, &obj_found); ctx->in_param = old_in_param; - dmfree(obj_path); + FREE(obj_path); return (obj_found && *root_entry) ? true : false; } diff --git a/libbbfdm-api/dmcommon.c b/libbbfdm-api/dmcommon.c index f5569949..c81158fe 100644 --- a/libbbfdm-api/dmcommon.c +++ b/libbbfdm-api/dmcommon.c @@ -1847,7 +1847,7 @@ char *replace_str(const char *str, const char *substr, const char *replacement) } size_t new_str_len = i + cnt * (replacement_len - substr_len) + 1; - char *value = (char *)dmmalloc(new_str_len * sizeof(char)); + char *value = (char *)malloc(new_str_len * sizeof(char)); i = 0; while (*str) { diff --git a/libbbfdm-api/dmentry.c b/libbbfdm-api/dmentry.c index 25713310..2f6ad8bb 100644 --- a/libbbfdm-api/dmentry.c +++ b/libbbfdm-api/dmentry.c @@ -295,7 +295,8 @@ int bbf_entry_method(struct dmctx *ctx, int cmd) return bbf_fault_map(ctx->dm_type, USP_FAULT_INVALID_PATH); // Load dynamic objects and parameters - load_dynamic_arrays(ctx); + if (ctx->enable_plugins) + load_dynamic_arrays(ctx); dmentry_instance_lookup_inparam(ctx); @@ -348,8 +349,8 @@ int bbf_entry_method(struct dmctx *ctx, int cmd) void bbf_global_clean(DMOBJ *dm_entryobj) { - dm_dynamic_cleanmem(&global_memhead); free_dynamic_arrays(dm_entryobj); + dm_dynamic_cleanmem(&global_memhead); } int dm_entry_validate_allowed_objects(struct dmctx *ctx, char *value, char *objects[]) diff --git a/libbbfdm-api/dmentry.h b/libbbfdm-api/dmentry.h index 402832d4..f7baa6ad 100644 --- a/libbbfdm-api/dmentry.h +++ b/libbbfdm-api/dmentry.h @@ -15,8 +15,6 @@ #ifndef __DMENTRY_H__ #define __DMENTRY_H__ -extern struct list_head global_memhead; - void bbf_ctx_init(struct dmctx *ctx, DMOBJ *tEntryObj, DM_MAP_VENDOR *tVendorExtension[], DM_MAP_VENDOR_EXCLUDE *tVendorExtensionExclude); diff --git a/libbbfdm/dmtree/tr181/device.c b/libbbfdm/dmtree/tr181/device.c index 81539fcd..d4f71814 100644 --- a/libbbfdm/dmtree/tr181/device.c +++ b/libbbfdm/dmtree/tr181/device.c @@ -80,6 +80,12 @@ static int operate_Device_FactoryReset(char *refparam, struct dmctx *ctx, void * * OBJ & LEAF DEFINITION ***********************************************************************************************************************************/ /* *** BBFDM *** */ +DM_MAP_OBJ tDynamicObj[] = { +/* parentobj, nextobject, parameter */ +{"Device.", tDeviceObj, tDeviceParams}, +{0} +}; + DMOBJ tEntryRoot[] = { /* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/ {"Device", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceObj, tDeviceParams, NULL, BBFDM_BOTH}, diff --git a/libbbfdm/dmtree/tr181/device.h b/libbbfdm/dmtree/tr181/device.h index 8a6a511a..297d55a5 100644 --- a/libbbfdm/dmtree/tr181/device.h +++ b/libbbfdm/dmtree/tr181/device.h @@ -15,6 +15,8 @@ #include "libbbfdm-api/dmcommon.h" +extern DM_MAP_OBJ tDynamicObj[]; + extern DMOBJ tEntryRoot[]; extern DMOBJ tDeviceObj[]; extern DMLEAF tDeviceParams[]; diff --git a/test/cmocka/functional_api_test_bbfd.c b/test/cmocka/functional_api_test_bbfd.c index ca822ade..69fa7d83 100644 --- a/test/cmocka/functional_api_test_bbfd.c +++ b/test/cmocka/functional_api_test_bbfd.c @@ -965,11 +965,13 @@ static void test_bbf_api_common(void **state) DM_STRNCPY(buf, "Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.{i}.IPv4Address.{i}.", sizeof(buf)); value = replace_str(buf, ".{i}.", "."); assert_string_equal(value, "Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.IPv4Address."); + FREE(value); // replace_str: test DM_STRNCPY(buf, "Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.{i}.IPv4Address.{i}.", sizeof(buf)); value = replace_str(buf, ".{i}.", ".*."); assert_string_equal(value, "Device.IEEE1905.AL.NetworkTopology.IEEE1905Device.*.IPv4Address.*."); + FREE(value); /* diff --git a/test/cmocka/functional_test_bbfd.c b/test/cmocka/functional_test_bbfd.c index 02e69e9f..4ebe643c 100644 --- a/test/cmocka/functional_test_bbfd.c +++ b/test/cmocka/functional_test_bbfd.c @@ -6,6 +6,7 @@ #include #include #include + #include #include @@ -24,6 +25,9 @@ static int setup(void **state) bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE); + // Enable Plugins + ctx->enable_plugins = true; + *state = ctx; return 0; diff --git a/test/cmocka/unit_test_bbfd.c b/test/cmocka/unit_test_bbfd.c index 16f92ec7..bd3c1730 100644 --- a/test/cmocka/unit_test_bbfd.c +++ b/test/cmocka/unit_test_bbfd.c @@ -6,6 +6,7 @@ #include #include #include + #include #include @@ -29,6 +30,9 @@ static int setup(void **state) bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE); + // Enable Plugins + ctx->enable_plugins = true; + *state = ctx; return 0; @@ -592,6 +596,9 @@ static void test_api_bbfdm_json_get_value(void **state) bbf_ctx_clean_sub(ctx); bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE); + // Enable Plugins + ctx->enable_plugins = true; + /* * Test of JSON Parameter Path */ @@ -605,6 +612,9 @@ static void test_api_bbfdm_json_get_value(void **state) bbf_ctx_clean_sub(ctx); bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE); + // Enable Plugins + ctx->enable_plugins = true; + remove(DROPBEAR_JSON_PATH); ctx->in_param = "Device.X_IOPSYS_EU_Dropbear."; @@ -682,6 +692,9 @@ static void test_api_bbfdm_library_get_value(void **state) bbf_ctx_clean_sub(ctx); bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE); + // Enable Plugins + ctx->enable_plugins = true; + ctx->in_param = "Device.WiFi.SSID.1.Enable"; fault = bbf_entry_method(ctx, BBF_GET_VALUE); @@ -693,6 +706,9 @@ static void test_api_bbfdm_library_get_value(void **state) bbf_ctx_clean_sub(ctx); bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE); + // Enable Plugins + ctx->enable_plugins = true; + remove(LIBBBF_TEST_BBFDM_PATH); ctx->in_param = "Device.X_IOPSYS_EU_Syslog.";