Add support to filter micro-service ubus calls based on proto

This commit is contained in:
Vivek Kumar Dutta 2024-12-06 12:20:34 +00:00 committed by IOPSYS Dev
parent b591f3fa88
commit f08359f40d
No known key found for this signature in database
13 changed files with 113 additions and 134 deletions

View file

@ -1,3 +1,3 @@
[program:bbfdmd]
priority=15
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-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/bbfdmd"
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-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/bbfdmd -l 7"

View file

@ -376,10 +376,10 @@ enum dmt_type_enum {
};
enum bbfdm_type_enum {
BBFDM_BOTH,
BBFDM_CWMP,
BBFDM_USP,
BBFDM_NONE
BBFDM_NONE = 0,
BBFDM_CWMP = 1<<0,
BBFDM_USP = 1<<1,
BBFDM_BOTH = BBFDM_CWMP|BBFDM_USP,
};
enum {

View file

@ -1143,6 +1143,16 @@ 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);
@ -1150,7 +1160,7 @@ static int get_ubus_value(struct dmctx *dmctx, struct dmnode *node)
blobmsg_add_string(&blob, "path", in_path);
prepare_optional_table(dmctx, &blob);
int res = ubus_call_blob_msg(ubus_name, "get", &blob, 5000, __get_ubus_value, dmctx);
int res = ubus_call_blob_msg(ubus_name, "get", &blob, timeout, __get_ubus_value, dmctx);
blob_buf_free(&blob);
@ -1205,6 +1215,11 @@ static int get_ubus_supported_dm(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;
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);
@ -1267,6 +1282,11 @@ 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);
@ -1292,6 +1312,11 @@ 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"));
@ -1337,6 +1362,11 @@ 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"));
@ -1410,6 +1440,11 @@ static int set_ubus_value(struct dmctx *dmctx, struct dmnode *node)
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"));
@ -1529,6 +1564,16 @@ static int get_ubus_name(struct dmctx *dmctx, struct dmnode *node)
char *ubus_name = node->obj->checkdep;
dmctx->in_value = node->current_object;
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);
@ -1537,7 +1582,7 @@ static int get_ubus_name(struct dmctx *dmctx, struct dmnode *node)
blobmsg_add_u8(&blob, "first_level", dmctx->nextlevel);
prepare_optional_table(dmctx, &blob);
int res = ubus_call_blob_msg(ubus_name, "schema", &blob, 5000, __get_ubus_name, dmctx);
int res = ubus_call_blob_msg(ubus_name, "schema", &blob, timeout, __get_ubus_name, dmctx);
blob_buf_free(&blob);
@ -1611,6 +1656,11 @@ 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);

View file

@ -2189,3 +2189,28 @@ long upload_file(const char *file_path, const char *url, const char *username, c
return res_code;
}
int get_proto_type(const char *proto)
{
int type = BBFDM_BOTH;
if (proto) {
if (is_str_eq("cwmp", proto))
type = BBFDM_CWMP;
else if (is_str_eq("usp", proto))
type = BBFDM_USP;
else
type = BBFDM_BOTH;
}
return type;
}
bool is_str_eq(const char *s1, const char *s2)
{
if (strcmp(s1, s2) == 0)
return true;
return false;
}

View file

@ -236,5 +236,7 @@ void diagnostics_reset_state(const char *sec_name);
char *diagnostics_get_interface_name(struct dmctx *ctx, const char *value);
long download_file(char *file_path, const char *url, const char *username, const char *password);
long upload_file(const char *file_path, const char *url, const char *username, const char *password);
int get_proto_type(const char *proto);
bool is_str_eq(const char *s1, const char *s2);
#endif

View file

@ -35,7 +35,7 @@ bool adm_entry_object_exists(struct dmctx *ctx, const char *param); // To be rem
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);
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__

View file

@ -19,13 +19,14 @@ 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)
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)
@ -49,12 +50,14 @@ static bool add_service_to_main_tree(DMOBJ *main_dm, const char *srv_name, const
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;
@ -74,7 +77,7 @@ static bool is_service_registered(struct list_head *srvlist, const char *srv_nam
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, bool is_unified)
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;
@ -85,6 +88,7 @@ static void add_service_to_list(struct list_head *srvlist, const char *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)
@ -100,7 +104,7 @@ void free_services_from_list(struct list_head *clist)
}
}
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)
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.");
@ -113,13 +117,13 @@ bool load_service(DMOBJ *main_dm, struct list_head *srv_list, const char *srv_na
return false;
}
if (!add_service_to_main_tree(main_dm, srv_name, srv_parent_dm, srv_obj)) {
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, is_unified);
add_service_to_list(srv_list, srv_name, srv_parent_dm, srv_obj, proto, is_unified);
return true;
}
@ -133,6 +137,13 @@ void get_list_of_registered_service(struct list_head *srvlist, struct blob_buf *
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);
}

View file

@ -35,7 +35,6 @@
LIST_HEAD(head_registered_service);
static void run_schema_updater(struct bbfdm_context *u);
static void periodic_instance_updater(struct uloop_timeout *t);
static void bbfdm_register_instance_refresh_timer(struct ubus_context *ctx, int start_in);
static void bbfdm_cancel_instance_refresh_timer(struct ubus_context *ctx);
@ -76,6 +75,7 @@ static void fill_optional_data(bbfdm_data_t *data, struct blob_attr *msg)
if (!data || !msg)
return;
data->bbf_ctx.dm_type = BBFDM_BOTH;
blobmsg_for_each_attr(attr, msg, rem) {
if (is_str_eq(blobmsg_name(attr), "proto")) {
@ -196,47 +196,6 @@ err_out:
return UBUS_STATUS_UNKNOWN_ERROR;
}
static bool is_object_schema_update_available(struct bbfdm_context *u)
{
bool ret = false;
LIST_HEAD(paths_list);
bbfdm_data_t data = {
.ctx = 0,
.req = 0,
.is_raw = true,
.plist = &paths_list,
.bbf_ctx.nextlevel = false,
.bbf_ctx.iscommand = true,
.bbf_ctx.isevent = true,
.bbf_ctx.isinfo = true,
.bbf_ctx.dm_type = BBFDM_USP
};
int old_schema_len = u->schema_len;
// If new parameter gets added it would be a minimum tuple of three params
int min_len = 100;
add_path_list(ROOT_NODE, &paths_list);
int new_schema_len = bbfdm_get_supported_dm(&data);
if (new_schema_len == 0) {
BBF_WARNING("Failed to get schema");
free_path_list(&paths_list);
return ret;
}
if (new_schema_len - old_schema_len > min_len) {
BBF_DEBUG("DM Schema update available old:new[%d:%d]", old_schema_len, new_schema_len);
if (old_schema_len != 0) {
ret = true;
}
}
free_path_list(&paths_list);
return ret;
}
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 },
@ -710,46 +669,20 @@ int bbfdm_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
return 0;
}
static void service_list(struct blob_buf *bb)
{
void *array;
array = blobmsg_open_array(bb, "supported_cmd");
blobmsg_add_string(bb, NULL, "register");
blobmsg_add_string(bb, NULL, "list");
blobmsg_close_array(bb, array);
array = blobmsg_open_array(bb, "registered_service");
get_list_of_registered_service(&head_registered_service, bb);
blobmsg_close_array(bb, array);
}
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)
{
struct blob_buf bb;
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 0;
}
void *array = NULL;
memset(&bb, 0, sizeof(struct blob_buf));
blob_buf_init(&bb, 0);
BBF_INFO("ubus method|%s|, name|%s|", method, obj->name);
array = blobmsg_open_array(&bb, "registered_service");
get_list_of_registered_service(&head_registered_service, &bb);
blobmsg_close_array(&bb, array);
if (dm_is_micro_service() == true) { // It's a micro-service instance
blobmsg_add_string(&bb, "error", "Its not allowed to register a micro-service for another micro-service!!");
goto end;
}
service_list(&bb);
end:
ubus_send_reply(ctx, req, bb.head);
blob_buf_free(&bb);
@ -817,24 +750,6 @@ static struct ubus_object bbf_object = {
.n_methods = ARRAY_SIZE(bbf_methods)
};
static void run_schema_updater(struct bbfdm_context *u)
{
bool ret = false;
char method_name[256] = {0};
ret = is_object_schema_update_available(u);
if (ret && (dm_is_micro_service() == false)) {
struct blob_buf bb;
memset(&bb, 0, sizeof(struct blob_buf));
BBF_INFO("Schema update available");
snprintf(method_name, sizeof(method_name), "%s.%s", u->config.out_name, BBF_UPDATE_SCHEMA_EVENT);
blob_buf_init(&bb, 0);
ubus_send_event(&u->ubus_ctx, method_name, bb.head);
blob_buf_free(&bb);
}
}
static void broadcast_add_del_event(struct ubus_context *ctx, const char *method, struct list_head *inst, bool is_add)
{
struct blob_buf bb;
@ -1135,8 +1050,9 @@ static int daemon_load_services(const char *name, const char *json_path)
continue;
}
BBF_INFO("Registering [%s :: %s :: %s :: %d]", service_name, parent, obj, is_unified);
load_service(DEAMON_DM_ROOT_OBJ, &head_registered_service, service_name, parent, obj, is_unified);
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:
@ -1353,9 +1269,7 @@ int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx)
if (err != UBUS_STATUS_OK)
return -1;
run_schema_updater(bbfdm_ctx);
bbfdm_register_instance_refresh_timer(&bbfdm_ctx->ubus_ctx, 1);
err = register_events_to_ubus(&bbfdm_ctx->ubus_ctx, &bbfdm_ctx->event_handlers);
if (err != 0)
return err;

View file

@ -12,14 +12,6 @@
#include "common.h"
#include "get_helper.h"
bool is_str_eq(const char *s1, const char *s2)
{
if (strcmp(s1, s2) == 0)
return true;
return false;
}
bool get_boolean_string(char *value)
{
if (!value)
@ -126,22 +118,6 @@ int get_dm_type(char *dm_type)
return DMT_STRING;
}
int get_proto_type(const char *proto)
{
int type = BBFDM_BOTH;
if (proto) {
if (is_str_eq("cwmp", proto))
type = BBFDM_CWMP;
else if (is_str_eq("usp", proto))
type = BBFDM_USP;
else
type = BBFDM_BOTH;
}
return type;
}
// 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)

View file

@ -24,7 +24,6 @@
#define BBF_ADD_EVENT "AddObj"
#define BBF_DEL_EVENT "DelObj"
#define BBF_EVENT_NAME "event"
#define BBF_UPDATE_SCHEMA_EVENT "UpdateSchema"
#define MAX_DM_KEY_LEN 256
#define MAX_DM_PATH 1024
@ -44,7 +43,6 @@
extern DMOBJ *DEAMON_DM_ROOT_OBJ;
extern DM_MAP_OBJ *INTERNAL_ROOT_TREE;
bool is_str_eq(const char *s1, const char *s2);
bool is_node_instance(char *path);
int count_delim(const char *path);
@ -52,7 +50,6 @@ bool get_boolean_string(char *value);
bool validate_msglen(bbfdm_data_t *data);
int get_dm_type(char *dm_type);
int get_proto_type(const char *proto);
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);

View file

@ -12,6 +12,7 @@ static int setup_teardown(void **state)
{
bbfdm_init_mem(&bbf_ctx);
bbfdm_uci_init(&bbf_ctx);
bbf_ctx.dm_type = BBFDM_USP;
return 0;
}

View file

@ -22,6 +22,7 @@ static int setup(void **state)
return -1;
bbf_ctx_init(ctx, TR181_ROOT_TREE);
ctx->dm_type = BBFDM_BOTH;
*state = ctx;

View file

@ -369,6 +369,7 @@ static void test_api_bbfdm_valid_operate(void **state)
struct dmctx *ctx = (struct dmctx *) *state;
int fault = 0;
ctx->dm_type = BBFDM_USP;
ctx->in_param = "Device.X_IOPSYS_EU_Reboot()";
fault = bbf_entry_method(ctx, BBF_OPERATE);
@ -380,6 +381,7 @@ static void test_api_bbfdm_wrong_operate(void **state)
struct dmctx *ctx = (struct dmctx *) *state;
int fault = 0;
ctx->dm_type = BBFDM_USP;
ctx->in_param = "Device.IP.Diagnostics.IPing()";
fault = bbf_entry_method(ctx, BBF_OPERATE);