Redesign dmmap to be portable and structured

This commit is contained in:
Amin Ben Romdhane 2025-07-25 23:34:41 +02:00
parent a4f6108138
commit d4bc6eea94
11 changed files with 360 additions and 66 deletions

View file

@ -351,7 +351,7 @@ static char *find_path_recursive(json_object *curr, char **parts, int index, int
return NULL; return NULL;
} }
char *bbfdm_resolve_external_reference(struct dmctx *ctx, const char *linker_path, const char *linker_value) char *bbfdm_resolve_external_reference_via_json(struct dmctx *ctx, const char *linker_path, const char *linker_value)
{ {
char file_path[256] = {0}; char file_path[256] = {0};
char *reference_path = NULL; char *reference_path = NULL;
@ -379,11 +379,50 @@ char *bbfdm_resolve_external_reference(struct dmctx *ctx, const char *linker_pat
return reference_path; return reference_path;
} }
static char *bbfdm_resolve_external_reference_via_dmmap(struct dmctx *ctx, const char *linker_path, const char *linker_name, const char *linker_value)
{
struct uci_section *dmmap_obj = NULL;
size_t count = 0;
if (DM_STRLEN(linker_path) == 0 || DM_STRLEN(linker_name) == 0 || DM_STRLEN(linker_value) == 0)
return NULL;
char **parts = strsplit(linker_path, ".", &count);
if (count < 2)
return NULL;
uci_path_foreach_sections(bbfdm, parts[1], parts[count - 1], dmmap_obj) {
char *curr_value = NULL;
dmuci_get_value_by_section_string(dmmap_obj, linker_name, &curr_value);
if (DM_STRCMP(curr_value, linker_value) == 0) {
char *linker_instance = NULL;
char *reference_path = NULL;
dmuci_get_value_by_section_string(dmmap_obj, "__instance__", &linker_instance);
dmasprintf(&reference_path, "%s%s", linker_path, linker_instance);
return reference_path;
}
}
return NULL;
}
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) 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}; char param_path[1024] = {0};
char *value = NULL; char *value = NULL;
if (!out || !out_len) {
BBF_ERR("Output buffer is NULL or has zero length. A valid buffer with sufficient size is required");
return -1;
}
size_t len = strlen(out);
if (match_action == MATCH_FIRST && len > 0) // Reference path is already resolved
return 0;
if (DM_STRLEN(base_path) == 0) { if (DM_STRLEN(base_path) == 0) {
BBF_ERR("Reference base path should not be empty!!!"); BBF_ERR("Reference base path should not be empty!!!");
return -1; return -1;
@ -399,16 +438,6 @@ int bbfdm_get_references(struct dmctx *ctx, int match_action, const char *base_p
return -1; return -1;
} }
if (!out || !out_len) {
BBF_ERR("Output buffer is NULL or has zero length. A valid buffer with sufficient size is required");
return -1;
}
size_t len = strlen(out);
if (match_action == MATCH_FIRST && len > 0) // Reference path is already resolved
return 0;
snprintf(param_path, sizeof(param_path), "%s*.%s", base_path, key_name); snprintf(param_path, sizeof(param_path), "%s*.%s", base_path, key_name);
adm_entry_get_reference_param(ctx, param_path, key_value, &value); adm_entry_get_reference_param(ctx, param_path, key_value, &value);
@ -424,7 +453,13 @@ int bbfdm_get_references(struct dmctx *ctx, int match_action, const char *base_p
return 0; return 0;
} }
char *external_reference = bbfdm_resolve_external_reference(ctx, param_path, key_value); char *external_reference = NULL;
if (ctx->bbfdm_api_version == BBFDM_API_V1)
external_reference = bbfdm_resolve_external_reference_via_dmmap(ctx, base_path, key_name, key_value);
else
external_reference = bbfdm_resolve_external_reference_via_json(ctx, param_path, key_value);
if (external_reference != NULL) { if (external_reference != NULL) {
if (out_len - len < strlen(external_reference)) { if (out_len - len < strlen(external_reference)) {

View file

@ -170,6 +170,11 @@ struct dm_reference {
bool is_valid_path; bool is_valid_path;
}; };
enum {
BBFDM_API_V0,
BBFDM_API_V1
};
struct dmctx { struct dmctx {
bool stop; bool stop;
bool match; bool match;
@ -188,6 +193,7 @@ struct dmctx {
int faultcode; int faultcode;
int setaction; int setaction;
unsigned int dm_type; unsigned int dm_type;
unsigned int bbfdm_api_version;
unsigned char inparam_isparam; unsigned char inparam_isparam;
unsigned char findparam; unsigned char findparam;
@ -207,7 +213,8 @@ struct dmctx {
struct ubus_context *ubus_ctx; struct ubus_context *ubus_ctx;
struct list_head *memhead; struct list_head *memhead;
char *inst_buf[16]; const char *obj_buf[16];
const char *inst_buf[16];
char fault_msg[256]; char fault_msg[256];
}; };
@ -215,6 +222,7 @@ typedef struct dmnode {
DMOBJ *obj; DMOBJ *obj;
struct dmnode *parent; struct dmnode *parent;
char *current_object; char *current_object;
char *current_object_file;
void *prev_data; void *prev_data;
char *prev_instance; char *prev_instance;
unsigned char instance_level; unsigned char instance_level;

View file

@ -431,6 +431,7 @@ static void dm_browse_entry(struct dmctx *dmctx, DMNODE *parent_node, DMOBJ *ent
node.matched = parent_node->matched; node.matched = parent_node->matched;
node.prev_data = data; node.prev_data = data;
node.prev_instance = instance; node.prev_instance = instance;
node.current_object_file = parent_node->current_object_file;
if (!bbfdatamodel_matches(dmctx->dm_type, entryobj->bbfdm_type)) { if (!bbfdatamodel_matches(dmctx->dm_type, entryobj->bbfdm_type)) {
*err = FAULT_9005; *err = FAULT_9005;
@ -447,6 +448,10 @@ static void dm_browse_entry(struct dmctx *dmctx, DMNODE *parent_node, DMOBJ *ent
else else
dmasprintf(&(node.current_object), "%s%s.", parent_obj, entryobj->obj); dmasprintf(&(node.current_object), "%s%s.", parent_obj, entryobj->obj);
if (DM_STRCMP(parent_obj, ROOT_NODE) == 0) {
node.current_object_file = entryobj->obj;
}
if (dmctx->checkobj) { if (dmctx->checkobj) {
*err = dmctx->checkobj(dmctx, &node, entryobj->permission, entryobj->addobj, entryobj->delobj, entryobj->get_linker, data, instance); *err = dmctx->checkobj(dmctx, &node, entryobj->permission, entryobj->addobj, entryobj->delobj, entryobj->get_linker, data, instance);
if (*err) if (*err)
@ -526,7 +531,7 @@ int dm_link_inst_obj(struct dmctx *dmctx, DMNODE *parent_node, void *data, char
char *parent_obj; char *parent_obj;
DMNODE node = {0}; DMNODE node = {0};
if (parent_node->browse_type == BROWSE_FIND_MAX_INST) { if (parent_node->browse_type == BROWSE_FIND_MAX_INST) { // To be removed later!!!!!!!!!!!!
int curr_inst = (instance && *instance != '\0') ? DM_STRTOL(instance) : 0; int curr_inst = (instance && *instance != '\0') ? DM_STRTOL(instance) : 0;
if (curr_inst > parent_node->max_instance) if (curr_inst > parent_node->max_instance)
parent_node->max_instance = curr_inst; parent_node->max_instance = curr_inst;
@ -534,7 +539,7 @@ int dm_link_inst_obj(struct dmctx *dmctx, DMNODE *parent_node, void *data, char
} }
parent_node->num_of_entries++; parent_node->num_of_entries++;
if (parent_node->browse_type == BROWSE_NUM_OF_ENTRIES) if (parent_node->browse_type == BROWSE_NUM_OF_ENTRIES) // To be removed later!!!!!!!!!!!!
return 0; return 0;
DMOBJ *prevobj = parent_node->obj; DMOBJ *prevobj = parent_node->obj;
@ -546,6 +551,7 @@ int dm_link_inst_obj(struct dmctx *dmctx, DMNODE *parent_node, void *data, char
node.instance_level = parent_node->instance_level + 1; node.instance_level = parent_node->instance_level + 1;
node.is_instanceobj = 1; node.is_instanceobj = 1;
node.matched = parent_node->matched; node.matched = parent_node->matched;
node.current_object_file = parent_node->current_object_file;
parent_obj = parent_node->current_object; parent_obj = parent_node->current_object;
if (instance == NULL) if (instance == NULL)
@ -595,8 +601,53 @@ int get_number_of_entries(struct dmctx *ctx, void *data, char *instance, int (*b
{ {
DMNODE node = {0}; DMNODE node = {0};
node.browse_type = BROWSE_NUM_OF_ENTRIES; if (browseinstobj == NULL) {
(browseinstobj)(ctx, &node, data, instance); int instance_level = 0;
size_t count = 0;
if (!ctx->addobj_instance)
return 0;
char **parts = strsplit(ctx->addobj_instance, ".", &count);
if (count < 2)
return -1;
for (int idx = 0; idx < count - 1; idx++) {
int i = 0;
bool is_instance = false;
while (parts[idx][i] != 0) {
if (isdigit(parts[idx][i]) != 0) {
is_instance = true;
break;
}
i++;
}
if (is_instance) instance_level++;
}
char *p = DM_STRSTR(parts[count - 1], "NumberOfEntries");
if (p) *p = 0;
node.obj = dmcalloc(1, sizeof(struct dm_obj_s));
if (node.obj == NULL) {
BBF_ERR("Failed to allocate memory");
return 0;
}
node.current_object_file = parts[1];
node.obj->obj = parts[count - 1];
node.instance_level = instance_level;
node.browse_type = BROWSE_NUM_OF_ENTRIES;
generic_browse(ctx,&node, data, instance);
} else {
node.browse_type = BROWSE_NUM_OF_ENTRIES;
(browseinstobj)(ctx, &node, data, instance);
}
node.browse_type = BROWSE_NORMAL;
return node.num_of_entries; return node.num_of_entries;
} }
@ -637,6 +688,100 @@ char *handle_instance(struct dmctx *dmctx, DMNODE *parent_node, struct uci_secti
return instance ? instance : ""; return instance ? instance : "";
} }
struct uci_section *create_dmmap_obj(struct dmctx *dmctx, unsigned char instance_level,
const char *obj_file, const char *obj_name, struct uci_section *config_sec,
char **instance)
{
struct uci_section *s = NULL, *dmmap_section = NULL;
char config_sec_name[128] = {0};
int max_instance = 0;
if (!dmctx || !obj_file || !obj_name || !instance)
return NULL;
if (config_sec != NULL) {
snprintf(config_sec_name, sizeof(config_sec_name), "%s.%s", section_config(config_sec), section_name(config_sec));
}
uci_path_foreach_sections(bbfdm, obj_file, obj_name, s) {
bool is_same_parent = true;
for (int i = 0; i < instance_level; i++) {
char *curr_obj_inst = NULL;
dmuci_get_value_by_section_string(s, dmctx->obj_buf[i], &curr_obj_inst);
if (DM_STRCMP(curr_obj_inst, dmctx->inst_buf[i]) != 0) {
is_same_parent = false;
break;
}
}
if (is_same_parent == false)
continue;
char *curr_instance = NULL;
dmuci_get_value_by_section_string(s, "__instance__", &curr_instance);
int curr_instance_int = (curr_instance && *curr_instance != '\0') ? DM_STRTOL(curr_instance) : 0;
if (curr_instance_int > max_instance)
max_instance = curr_instance_int;
if (config_sec != NULL) {
char *curr_sec_name = NULL;
dmuci_get_value_by_section_string(s, "__section_name__", &curr_sec_name);
if (DM_STRCMP(curr_sec_name, config_sec_name) == 0) {
dmctx->obj_buf[instance_level] = obj_name;
dmctx->inst_buf[instance_level] = curr_instance;
*instance = curr_instance;
return dmmap_section;
}
}
}
dmasprintf(instance, "%d", max_instance + 1);
if (dmmap_section == NULL) {
// Section not found -> create it
char s_name[64] = {0};
int pos = 0;
dmuci_add_section_bbfdm(obj_file, obj_name, &dmmap_section);
for (int i = 0; i < instance_level; i++) {
dmuci_set_value_by_section(dmmap_section, dmctx->obj_buf[i], dmctx->inst_buf[i]);
pos += snprintf(&s_name[pos], sizeof(s_name) - pos, "%s_%s", dmctx->obj_buf[i], dmctx->inst_buf[i]);
}
snprintf(&s_name[pos], sizeof(s_name) - pos, "%s_%s", obj_name, *instance);
dmuci_rename_section_by_section(dmmap_section, s_name);
dmuci_set_value_by_section(dmmap_section, "__section_name__", config_sec_name);
dmuci_set_value_by_section(dmmap_section, "__instance__", *instance);
}
dmctx->obj_buf[instance_level] = obj_name;
dmctx->inst_buf[instance_level] = *instance;
return dmmap_section;
}
char *uci_handle_instance(struct dmctx *dmctx, DMNODE *parent_node, struct dm_data *data)
{
char *instance = NULL;
switch(parent_node->browse_type) {
case BROWSE_NORMAL: // To be removed later!!!!!!!!!!!!
dmuci_get_value_by_section_string(data->dmmap_section, "__instance__", &instance);
dmctx->obj_buf[parent_node->instance_level] = parent_node->obj->obj;
dmctx->inst_buf[parent_node->instance_level] = instance ? instance : "";
break;
case BROWSE_FIND_MAX_INST: // To be removed later!!!!!!!!!!!!
case BROWSE_NUM_OF_ENTRIES: // To be removed later!!!!!!!!!!!!
break;
}
return instance ? instance : "";
}
char *handle_instance_without_section(struct dmctx *dmctx, DMNODE *parent_node, int inst_nbr) char *handle_instance_without_section(struct dmctx *dmctx, DMNODE *parent_node, int inst_nbr)
{ {
char *instance = NULL; char *instance = NULL;
@ -655,6 +800,42 @@ char *handle_instance_without_section(struct dmctx *dmctx, DMNODE *parent_node,
return instance ? instance : ""; return instance ? instance : "";
} }
int generic_browse(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
struct dm_data curr_data = {0};
char *instance = NULL;
// This check is added to prevent crashes if the object is updated to new design but forgot to update its NumberOfEntries parameter maps to it
if (parent_node->obj == NULL)
return 0;
uci_path_foreach_sections(bbfdm, parent_node->current_object_file, parent_node->obj->obj, curr_data.dmmap_section) {
char *config_sec_name = NULL;
bool is_same_parent = true;
for (int i = 0; i < parent_node->instance_level; i++) {
char *curr_obj_inst = NULL;
dmuci_get_value_by_section_string(curr_data.dmmap_section, dmctx->obj_buf[i], &curr_obj_inst);
if (DM_STRCMP(curr_obj_inst, dmctx->inst_buf[i]) != 0) {
is_same_parent = false;
break;
}
}
if (is_same_parent == false)
continue;
dmuci_get_value_by_section_string(curr_data.dmmap_section, "__section_name__", &config_sec_name);
curr_data.config_section = get_config_section_from_dmmap_section_name(config_sec_name);
instance = uci_handle_instance(dmctx, parent_node, &curr_data);
if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_data, instance) == DM_STOP)
break;
}
return 0;
}
int get_empty(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) int get_empty(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{ {
*value = dmstrdup(""); *value = dmstrdup("");
@ -901,10 +1082,12 @@ static int get_value_obj(DMOBJECT_ARGS)
static int get_value_param(DMPARAM_ARGS) static int get_value_param(DMPARAM_ARGS)
{ {
char full_param[MAX_DM_PATH] = {0}; char *full_param = NULL;
char *value = dmstrdup(""); char *value = dmstrdup("");
snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter); dmasprintf(&full_param, "%s%s", node->current_object, leaf->parameter);
dmctx->addobj_instance = full_param; // This assignment is needed to pass the refparam in order to calculate the NumberOfEntries param
(leaf->getvalue)(full_param, dmctx, data, instance, &value); (leaf->getvalue)(full_param, dmctx, data, instance, &value);
@ -926,10 +1109,10 @@ static int mobj_get_value_in_param(DMOBJECT_ARGS)
} }
static int mparam_get_value_in_param(DMPARAM_ARGS) static int mparam_get_value_in_param(DMPARAM_ARGS)
{ {
char full_param[MAX_DM_PATH] = {0}; char *full_param = NULL;
char *value = dmstrdup(""); char *value = dmstrdup("");
snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter); dmasprintf(&full_param, "%s%s", node->current_object, leaf->parameter);
if (dmctx->iswildcard) { if (dmctx->iswildcard) {
if (dm_strcmp_wildcard(dmctx->in_param, full_param) != 0) if (dm_strcmp_wildcard(dmctx->in_param, full_param) != 0)
@ -939,6 +1122,8 @@ static int mparam_get_value_in_param(DMPARAM_ARGS)
return FAULT_9005; return FAULT_9005;
} }
dmctx->addobj_instance = full_param; // This assignment is needed to pass the refparam in order to calculate the NumberOfEntries param
(leaf->getvalue)(full_param, dmctx, data, instance, &value); (leaf->getvalue)(full_param, dmctx, data, instance, &value);
if ((leaf->dm_flags & DM_FLAG_SECURE) && (dmctx->dm_type == BBFDM_CWMP)) { if ((leaf->dm_flags & DM_FLAG_SECURE) && (dmctx->dm_type == BBFDM_CWMP)) {
@ -1351,6 +1536,7 @@ static int mobj_add_object(DMOBJECT_ARGS)
char *refparam = node->current_object; char *refparam = node->current_object;
char *perm = permission->val; char *perm = permission->val;
char *new_instance = NULL; char *new_instance = NULL;
char file_path[64] = {0};
int fault = 0; int fault = 0;
if (DM_STRCMP(refparam, dmctx->in_param) != 0) if (DM_STRCMP(refparam, dmctx->in_param) != 0)
@ -1365,16 +1551,43 @@ static int mobj_add_object(DMOBJECT_ARGS)
if (perm[0] == '0' || addobj == NULL) if (perm[0] == '0' || addobj == NULL)
return FAULT_9005; return FAULT_9005;
int max_inst = find_max_instance(dmctx, node); snprintf(file_path, sizeof(file_path), "/etc/bbfdm/dmmap/%s", node->current_object_file);
fault = dmasprintf(&new_instance, "%d", max_inst);
if (fault)
return fault;
dmctx->stop = 1; if (file_exists(file_path)) {
struct dm_data curr_data = {0};
fault = (addobj)(refparam, dmctx, data, &new_instance); curr_data.dmmap_section = create_dmmap_obj(dmctx, node->instance_level, node->current_object_file, node->obj->obj, NULL, &new_instance);
if (fault) if (DM_STRLEN(new_instance) == 0 || curr_data.dmmap_section == NULL)
return fault; return FAULT_9005;
dmctx->stop = 1;
// cppcheck-suppress autoVariables
dmctx->addobj_instance = (char *)&curr_data;
fault = (addobj)(refparam, dmctx, data, &new_instance);
if (fault)
return fault;
if (curr_data.config_section != NULL) {
char sec_name[128] = {0};
snprintf(sec_name, sizeof(sec_name), "%s.%s", section_config(curr_data.config_section), section_name(curr_data.config_section));
dmuci_set_value_by_section(curr_data.dmmap_section, "__section_name__", sec_name);
}
} else {
int max_inst = find_max_instance(dmctx, node);
fault = dmasprintf(&new_instance, "%d", max_inst);
if (fault)
return fault;
dmctx->stop = 1;
fault = (addobj)(refparam, dmctx, data, &new_instance);
if (fault)
return fault;
}
dmctx->addobj_instance = new_instance; dmctx->addobj_instance = new_instance;
return 0; return 0;

View file

@ -27,9 +27,17 @@
#include "dmmem.h" #include "dmmem.h"
#include "dmapi.h" #include "dmapi.h"
int get_number_of_entries(struct dmctx *ctx, void *data, char *instance, int (*browseinstobj)(struct dmctx *ctx, struct dmnode *node, void *data, char *instance)); int get_number_of_entries(struct dmctx *ctx, void *data, char *instance, int (*browseinstobj)(struct dmctx *ctx, struct dmnode *node, void *data, char *instance)); // To be removed later!!!!!!!!!!!!
char *handle_instance(struct dmctx *dmctx, DMNODE *parent_node, struct uci_section *s, const char *inst_opt, const char *alias_opt); 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); char *handle_instance_without_section(struct dmctx *dmctx, DMNODE *parent_node, int inst_nbr);
struct uci_section *create_dmmap_obj(struct dmctx *dmctx, unsigned char instance_level,
const char *obj_file, const char *obj_name, struct uci_section *config_sec,
char **instance);
int generic_browse(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
char *uci_handle_instance(struct dmctx *dmctx, DMNODE *parent_node, struct dm_data *data);
int get_empty(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value); int get_empty(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
void fill_blob_param(struct blob_buf *bb, const char *path, const char *data, const char *type, uint32_t dm_flags); void fill_blob_param(struct blob_buf *bb, const char *path, const char *data, const char *type, uint32_t dm_flags);

View file

@ -314,6 +314,18 @@ void free_dmmap_config_dup_list(struct list_head *dup_list)
/* /*
* Function allows to synchronize config section with dmmap config * Function allows to synchronize config section with dmmap config
*/ */
struct uci_section *get_config_section_from_dmmap_section_name(const char *config_sec_name)
{
if (DM_STRLEN(config_sec_name) == 0)
return NULL;
char *p = strchr(config_sec_name, '.');
if (p) *p = 0;
return dmuci_get_section(config_sec_name, p ? p + 1 : "");
}
struct uci_section *get_origin_section_from_config(const char *package, const char *section_type, const char *orig_section_name) struct uci_section *get_origin_section_from_config(const char *package, const char *section_type, const char *orig_section_name)
{ {
struct uci_section *s = NULL; struct uci_section *s = NULL;

View file

@ -173,6 +173,7 @@ bool value_exists_in_uci_list(struct uci_list *list, const char *value);
bool value_exits_in_str_list(const char *str_list, const char *delimitor, const char *str); bool value_exits_in_str_list(const char *str_list, const char *delimitor, const char *str);
char *add_str_to_str_list(const char *str_list, const char *delimitor, const char *str); char *add_str_to_str_list(const char *str_list, const char *delimitor, const char *str);
char *remove_str_from_str_list(const char *str_list, const char *delimitor, const char *str); char *remove_str_from_str_list(const char *str_list, const char *delimitor, const char *str);
struct uci_section *get_config_section_from_dmmap_section_name(const char *config_sec_name);
struct uci_section *get_origin_section_from_config(const char *package, const char *section_type, const char *orig_section_name); struct uci_section *get_origin_section_from_config(const char *package, const char *section_type, const char *orig_section_name);
struct uci_section *get_origin_section_from_dmmap(const char *package, const char *section_type, const char *orig_section_name); struct uci_section *get_origin_section_from_dmmap(const char *package, const char *section_type, const char *orig_section_name);
struct uci_section *get_dup_section_in_dmmap(const char *dmmap_package, const char *section_type, const char *orig_section_name); struct uci_section *get_dup_section_in_dmmap(const char *dmmap_package, const char *section_type, const char *orig_section_name);
@ -212,7 +213,7 @@ int bbfdm_validate_string_list(struct dmctx *ctx, const char *value, int min_ite
int bbfdm_validate_hexBinary_list(struct dmctx *ctx, const char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size); int bbfdm_validate_hexBinary_list(struct dmctx *ctx, const char *value, int min_item, int max_item, int max_size, struct range_args r_args[], int r_args_size);
int bbf_get_alias(struct dmctx *ctx, struct uci_section *s, const char *option_name, const char *instance, char **value); int bbf_get_alias(struct dmctx *ctx, struct uci_section *s, const char *option_name, const char *instance, char **value);
int bbf_set_alias(struct dmctx *ctx, struct uci_section *s, const char *option_name, const char *instance, const char *value); int bbf_set_alias(struct dmctx *ctx, struct uci_section *s, const char *option_name, const char *instance, const char *value);
char *bbfdm_resolve_external_reference(struct dmctx *ctx, const char *linker_path, const char *linker_value); char *bbfdm_resolve_external_reference_via_json(struct dmctx *ctx, const char *linker_path, const char *linker_value);
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); 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);
int _bbfdm_get_references(struct dmctx *ctx, const char *base_path, const char *key_name, char *key_value, char **value); int _bbfdm_get_references(struct dmctx *ctx, const char *base_path, const char *key_name, char *key_value, char **value);
int bbfdm_get_reference_linker(struct dmctx *ctx, char *reference_path, struct dm_reference *reference_args); int bbfdm_get_reference_linker(struct dmctx *ctx, char *reference_path, struct dm_reference *reference_args);

View file

@ -128,6 +128,9 @@ int load_dotso_plugins(DMOBJ *entryobj, const char *plugin_path)
} }
} }
if (dynamic_obj[i].init_module)
dynamic_obj[i].init_module(NULL);
} }
add_list_loaded_libraries(&loaded_library_list, handle); add_list_loaded_libraries(&loaded_library_list, handle);

View file

@ -674,7 +674,7 @@ static char *handle_reference_value(struct dmctx *ctx, struct json_object *linke
if (DM_STRLEN(pref) != 0) if (DM_STRLEN(pref) != 0)
return pref; return pref;
pref = bbfdm_resolve_external_reference(ctx, linker_path, key_value); pref = bbfdm_resolve_external_reference_via_json(ctx, linker_path, key_value);
return pref ? pref : ""; return pref ? pref : "";
} }

View file

@ -78,13 +78,27 @@ static int operate_Device_FactoryReset(char *refparam, struct dmctx *ctx, void *
return !res ? 0 : USP_FAULT_COMMAND_FAILURE; return !res ? 0 : USP_FAULT_COMMAND_FAILURE;
} }
/*************************************************************
* Init & Clean Module
**************************************************************/
int init_core_module(void *data)
{
struct dmctx bbf_ctx = {0};
bbf_ctx_init(&bbf_ctx, NULL);
dmmap_synchronizeSchedulesSchedule(&bbf_ctx);
bbf_ctx_clean(&bbf_ctx);
return 0;
}
/********************************************************************************************************************************** /**********************************************************************************************************************************
* OBJ & LEAF DEFINITION * OBJ & LEAF DEFINITION
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
/* *** BBFDM *** */ /* *** BBFDM *** */
DM_MAP_OBJ tDynamicObj[] = { DM_MAP_OBJ tDynamicObj[] = {
/* parentobj, nextobject, parameter */ /* parentobj, nextobject, parameter */
{"Device.", tDMRootObj, tDMRootParams}, {"Device.", tDMRootObj, tDMRootParams, init_core_module, NULL},
{0} {0}
}; };

View file

@ -138,27 +138,24 @@ static char *get_status(char *start, char *period, char *day)
**************************************************************/ **************************************************************/
static int addSchedule(char *refparam, struct dmctx *ctx, void *data, char **instance) static int addSchedule(char *refparam, struct dmctx *ctx, void *data, char **instance)
{ {
struct uci_section *s = NULL, *dmmap_s = NULL; struct dm_data *curr_data = (struct dm_data *)ctx->addobj_instance;
char s_name[16] = {0}; char sec_name[32] = {0};
int i;
snprintf(s_name, sizeof(s_name), "schedule_%s", *instance); snprintf(sec_name, sizeof(sec_name), "schedule_%s", *instance);
dmuci_add_section("schedules", "schedule", &s); // Create and Set default config option
dmuci_rename_section_by_section(s, s_name); dmuci_add_section("schedules", "schedule", &curr_data->config_section);
dmuci_rename_section_by_section(curr_data->config_section, sec_name);
dmuci_set_value_by_section(s, "enable", "0"); dmuci_set_value_by_section(curr_data->config_section, "enable", "0");
dmuci_set_value_by_section(curr_data->config_section, "duration", "1");
for (i = 0; allowed_days[i] != NULL; i++) {
dmuci_add_list_value_by_section(s, "day", allowed_days[i]);
}
dmuci_set_value_by_section(s, "duration", "1"); for (int i = 0; allowed_days[i] != NULL; i++)
dmuci_add_list_value_by_section(curr_data->config_section, "day", allowed_days[i]);
// dmmap is already created by the core, Set default dmmap option if needed
dmuci_set_value_by_section(curr_data->dmmap_section, "Alias", sec_name);
dmuci_add_section_bbfdm("dmmap_schedules", "schedule", &dmmap_s);
dmuci_set_value_by_section(dmmap_s, "section_name", s_name);
dmuci_set_value_by_section(dmmap_s, "schedule_instance", *instance);
dmuci_set_value_by_section(dmmap_s, "schedule_alias", s_name);
return 0; return 0;
} }
@ -173,22 +170,22 @@ static int delSchedule(char *refparam, struct dmctx *ctx, void *data, char *inst
/************************************************************* /*************************************************************
* ENTRY METHODS * ENTRY METHODS
*************************************************************/ *************************************************************/
static int browseScheduleInstance(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) void dmmap_synchronizeSchedulesSchedule(struct dmctx *dmctx)
{ {
struct dm_data *p = NULL; struct uci_section *schedule_s = NULL;
char *inst = NULL; char object_name[16] = {0};
LIST_HEAD(dup_list); char *instance = NULL;
synchronize_specific_config_sections_with_dmmap("schedules", "schedule", "dmmap_schedules", &dup_list); bbfdm_create_empty_file("/etc/bbfdm/dmmap/Schedules");
list_for_each_entry(p, &dup_list, list) {
inst = handle_instance(dmctx, parent_node, p->dmmap_section, "schedule_instance", "schedule_alias"); snprintf(object_name, sizeof(object_name), "%s", "Schedules");
if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p, inst) == DM_STOP) // Device.Schedules.Schedule.{i}.
break; uci_foreach_sections("schedules", "schedule", schedule_s) {
create_dmmap_obj(dmctx, 0, "Schedules", "Schedule", schedule_s, &instance);
} }
free_dmmap_config_dup_list(&dup_list);
return 0; dmuci_commit_package_bbfdm(object_name);
} }
/************************************************************* /*************************************************************
@ -221,8 +218,8 @@ static int set_schedules_enable(char *refparam, struct dmctx *ctx, void *data, c
static int get_schedule_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) static int get_schedule_number(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{ {
unsigned int cnt = get_number_of_entries(ctx, data, instance, browseScheduleInstance); int cnt = get_number_of_entries(ctx, data, instance, NULL);
dmasprintf(value, "%u", cnt); dmasprintf(value, "%d", cnt);
return 0; return 0;
} }
@ -253,7 +250,7 @@ static int set_schedule_enable(char *refparam, struct dmctx *ctx, void *data, ch
static int get_schedule_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) static int get_schedule_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{ {
return bbf_get_alias(ctx, ((struct dm_data *)data)->dmmap_section, "schedule_alias", instance, value); return bbf_get_alias(ctx, ((struct dm_data *)data)->dmmap_section, "Alias", instance, value);
} }
static int set_schedule_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) static int set_schedule_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
@ -281,8 +278,8 @@ static int set_schedule_alias(char *refparam, struct dmctx *ctx, void *data, cha
break; break;
case VALUESET: case VALUESET:
dmuci_rename_section_by_section(((struct dm_data *)data)->config_section, value); dmuci_rename_section_by_section(((struct dm_data *)data)->config_section, value);
dmuci_set_value_by_section(((struct dm_data *)data)->dmmap_section, "section_name", value); dmuci_set_value_by_section(((struct dm_data *)data)->dmmap_section, "__section_name__", value);
dmuci_set_value_by_section(((struct dm_data *)data)->dmmap_section, "schedule_alias", value); dmuci_set_value_by_section(((struct dm_data *)data)->dmmap_section, "Alias", value);
break; break;
} }
@ -432,7 +429,7 @@ static int get_schedule_status(char *refparam, struct dmctx *ctx, void *data, ch
/* *** Device.Schedules. *** */ /* *** Device.Schedules. *** */
DMOBJ tSchedulesObj[] = { DMOBJ tSchedulesObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/ /* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
{"Schedule", &DMWRITE, addSchedule, delSchedule, NULL, browseScheduleInstance, NULL, NULL, NULL, tScheduleParams, NULL, BBFDM_BOTH, NULL}, {"Schedule", &DMWRITE, addSchedule, delSchedule, NULL, generic_browse, NULL, NULL, NULL, tScheduleParams, NULL, BBFDM_BOTH, NULL},
{0} {0}
}; };

View file

@ -16,5 +16,8 @@
extern DMOBJ tSchedulesObj[]; extern DMOBJ tSchedulesObj[];
extern DMLEAF tSchedulesParams[]; extern DMLEAF tSchedulesParams[];
extern DMLEAF tScheduleParams[]; extern DMLEAF tScheduleParams[];
void dmmap_synchronizeSchedulesSchedule(struct dmctx *dmctx);
#endif #endif