/* * 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 MOHAMED Kallel * Author Imen Bhiri * Author Feten Besbes * Author Amin Ben Romdhane * Author Omar Kallel */ #include "dmapi.h" #include "dmplugin.h" #include "dmcommon.h" #include "dmentry.h" LIST_HEAD(global_memhead); static struct dm_fault DM_FAULT_ARRAY[] = { { FAULT_9000, "Method not supported" }, { FAULT_9001, "Request denied (no reason specified)" }, { FAULT_9002, "Internal error" }, { FAULT_9003, "Invalid arguments" }, { FAULT_9004, "Resources exceeded" }, { FAULT_9005, "Invalid parameter name" }, { FAULT_9006, "Invalid parameter type" }, { FAULT_9007, "Invalid parameter value" }, { FAULT_9008, "Attempt to set a non-writable parameter" }, { USP_FAULT_GENERAL_FAILURE, "general failure"}, { USP_FAULT_MESSAGE_NOT_UNDERSTOOD, "message was not understood"}, { USP_FAULT_REQUEST_DENIED, "Cannot or will not process message"}, { USP_FAULT_INTERNAL_ERROR, "Message failed due to an internal error"}, { USP_FAULT_INVALID_ARGUMENT, "invalid values in the request elements"}, { USP_FAULT_RESOURCES_EXCEEDED, "Message failed due to memory or processing limitations"}, { USP_FAULT_INVALID_TYPE, "Unable to convert string value to correct data type"}, { USP_FAULT_INVALID_VALUE, "Out of range or invalid enumeration"}, { USP_FAULT_PARAM_READ_ONLY, "Attempted to write to a read only parameter"}, { USP_FAULT_INVALID_PATH, "Path is not present in the data model schema"}, }; void bbf_ctx_init(struct dmctx *ctx, DMOBJ *tEntryObj) { memset(&ctx->bb, 0, sizeof(struct blob_buf)); blob_buf_init(&ctx->bb, 0); ctx->dm_entryobj = tEntryObj; bbfdm_init_mem(ctx); bbfdm_uci_init(ctx); } void bbf_ctx_clean(struct dmctx *ctx) { blob_buf_free(&ctx->bb); bbfdm_uci_exit(ctx); bbfdm_clean_mem(ctx); dmubus_free(); } void bbf_ctx_init_sub(struct dmctx *ctx, DMOBJ *tEntryObj) { ctx->dm_entryobj = tEntryObj; } void bbf_ctx_clean_sub(struct dmctx *ctx) { } static char *get_fault_message(int fault_code) { for (int i = 0; i < ARRAY_SIZE(DM_FAULT_ARRAY); i++) if (DM_FAULT_ARRAY[i].code == fault_code) return DM_FAULT_ARRAY[i].description; return "BBFDM: Internal error"; } int bbf_fault_map(struct dmctx *ctx, int fault) { int out_fault; if (!fault) return 0; if (ctx->dm_type == BBFDM_USP) { switch(fault) { case FAULT_9000: bbfdm_set_fault_message(ctx, "%s", get_fault_message(USP_FAULT_MESSAGE_NOT_UNDERSTOOD)); out_fault = USP_FAULT_MESSAGE_NOT_UNDERSTOOD; break; case FAULT_9001: bbfdm_set_fault_message(ctx, "%s", get_fault_message(USP_FAULT_REQUEST_DENIED)); out_fault = USP_FAULT_REQUEST_DENIED; break; case FAULT_9002: bbfdm_set_fault_message(ctx, "%s", get_fault_message(USP_FAULT_INTERNAL_ERROR)); out_fault = USP_FAULT_INTERNAL_ERROR; break; case FAULT_9003: bbfdm_set_fault_message(ctx, "%s", get_fault_message(USP_FAULT_INVALID_ARGUMENT)); out_fault = USP_FAULT_INVALID_ARGUMENT; break; case FAULT_9004: bbfdm_set_fault_message(ctx, "%s", get_fault_message(USP_FAULT_RESOURCES_EXCEEDED)); out_fault = USP_FAULT_RESOURCES_EXCEEDED; break; case FAULT_9005: bbfdm_set_fault_message(ctx, "%s", get_fault_message(USP_FAULT_INVALID_PATH)); out_fault = USP_FAULT_INVALID_PATH; break; case FAULT_9006: bbfdm_set_fault_message(ctx, "%s", get_fault_message(USP_FAULT_INVALID_TYPE)); out_fault = USP_FAULT_INVALID_TYPE; break; case FAULT_9007: bbfdm_set_fault_message(ctx, "%s", get_fault_message(USP_FAULT_PARAM_READ_ONLY)); out_fault = USP_FAULT_INVALID_VALUE; break; case FAULT_9008: bbfdm_set_fault_message(ctx, "%s", get_fault_message(USP_FAULT_PARAM_READ_ONLY)); out_fault = USP_FAULT_PARAM_READ_ONLY; break; default: if (fault >= FAULT_9000) { bbfdm_set_fault_message(ctx, "%s", get_fault_message(USP_FAULT_GENERAL_FAILURE)); out_fault = USP_FAULT_GENERAL_FAILURE; } else { bbfdm_set_fault_message(ctx, "%s", get_fault_message(fault)); out_fault = fault; } } } else if (ctx->dm_type == BBFDM_CWMP) { switch(fault) { case USP_FAULT_MESSAGE_NOT_UNDERSTOOD: bbfdm_set_fault_message(ctx, "%s", get_fault_message(FAULT_9000)); out_fault = FAULT_9000; break; case USP_FAULT_REQUEST_DENIED: bbfdm_set_fault_message(ctx, "%s", get_fault_message(FAULT_9001)); out_fault = FAULT_9001; break; case USP_FAULT_GENERAL_FAILURE: case USP_FAULT_INTERNAL_ERROR: bbfdm_set_fault_message(ctx, "%s", get_fault_message(FAULT_9002)); out_fault = FAULT_9002; break; case USP_FAULT_INVALID_ARGUMENT: bbfdm_set_fault_message(ctx, "%s", get_fault_message(FAULT_9003)); out_fault = FAULT_9003; break; case USP_FAULT_RESOURCES_EXCEEDED: bbfdm_set_fault_message(ctx, "%s", get_fault_message(FAULT_9004)); out_fault = FAULT_9004; break; case USP_FAULT_INVALID_PATH: bbfdm_set_fault_message(ctx, "%s", get_fault_message(FAULT_9005)); out_fault = FAULT_9005; break; case USP_FAULT_INVALID_TYPE: bbfdm_set_fault_message(ctx, "%s", get_fault_message(FAULT_9006)); out_fault = FAULT_9006; break; case USP_FAULT_INVALID_VALUE: bbfdm_set_fault_message(ctx, "%s", get_fault_message(FAULT_9007)); out_fault = FAULT_9007; break; case USP_FAULT_PARAM_READ_ONLY: bbfdm_set_fault_message(ctx, "%s", get_fault_message(FAULT_9008)); out_fault = FAULT_9008; break; default: bbfdm_set_fault_message(ctx, "%s", get_fault_message(fault)); out_fault = fault; } } else { bbfdm_set_fault_message(ctx, "%s", get_fault_message(fault)); out_fault = fault; } return out_fault; } int bbf_entry_method(struct dmctx *ctx, int cmd) { int fault = 0; ctx->iswildcard = DM_STRCHR(ctx->in_param, '*') ? 1 : 0; ctx->fault_msg[0] = 0; ctx->stop = false; if (!ctx->dm_entryobj) { bbfdm_set_fault_message(ctx, "Root entry was not defined."); return bbf_fault_map(ctx, FAULT_9002); } if (!ctx->in_param) { bbfdm_set_fault_message(ctx, "Path should not be blank."); return bbf_fault_map(ctx, FAULT_9005); } switch(cmd) { case BBF_GET_VALUE: fault = dm_entry_get_value(ctx); break; case BBF_SCHEMA: fault = dm_entry_get_supported_dm(ctx); break; case BBF_INSTANCES: fault = dm_entry_get_instances(ctx); break; case BBF_GET_NAME: fault = dm_entry_get_name(ctx); break; case BBF_SET_VALUE: fault = dm_entry_set_value(ctx); break; case BBF_ADD_OBJECT: fault = dm_entry_add_object(ctx); break; case BBF_DEL_OBJECT: fault = dm_entry_delete_object(ctx); break; case BBF_OPERATE: fault = dm_entry_operate(ctx); break; case BBF_EVENT: fault = dm_entry_event(ctx); break; } dmuci_save(); return bbf_fault_map(ctx, fault); } void bbf_global_init(DMOBJ *dm_entryobj, const char *plugin_path) { dm_dynamic_initmem(&global_memhead); load_plugins(dm_entryobj, plugin_path); } void bbf_global_clean(DMOBJ *dm_entryobj) { free_plugins(dm_entryobj); dm_dynamic_cleanmem(&global_memhead); } int dm_validate_allowed_objects(struct dmctx *ctx, struct dm_reference *reference, char *objects[]) { if (!reference || !objects) return -1; if (DM_STRLEN(reference->path) == 0) return 0; for (; *objects; objects++) { if (match(reference->path, *objects, 0, NULL)) { if (dm_is_micro_service()) { if (DM_STRLEN(reference->value)) return 0; } else { if (adm_entry_object_exists(ctx, reference->path)) return 0; } } } bbfdm_set_fault_message(ctx, "'%s' value is not allowed.", reference->path); return -1; } int adm_entry_get_reference_param(struct dmctx *ctx, char *param, char *linker, char **value) { struct dmctx dmctx = {0}; *value = ""; if (!param || !linker || *linker == 0) return 0; bbf_ctx_init_sub(&dmctx, ctx->dm_entryobj); dmctx.iswildcard = 1; dmctx.inparam_isparam = 1; dmctx.in_param = param; dmctx.linker = linker; dm_entry_get_reference_param(&dmctx); *value = dmctx.linker_param ? dmctx.linker_param : ""; bbf_ctx_clean_sub(&dmctx); return 0; } int adm_entry_get_reference_value(struct dmctx *ctx, char *param, char **value) { struct dmctx dmctx = {0}; char linker[256] = {0}; *value = NULL; if (!param || param[0] == '\0') return 0; snprintf(linker, sizeof(linker), "%s%c", param, (param[DM_STRLEN(param) - 1] != '.') ? '.' : '\0'); bbf_ctx_init_sub(&dmctx, ctx->dm_entryobj); dmctx.in_param = linker; dm_entry_get_reference_value(&dmctx); *value = dmctx.linker; bbf_ctx_clean_sub(&dmctx); return 0; } bool adm_entry_object_exists(struct dmctx *ctx, char *param) // To be removed later!!!!!!!!!!!! (After moving all Objects outside bbfdm core) { struct dmctx dmctx = {0}; char linker[256] = {0}; if (!param || param[0] == '\0') return false; snprintf(linker, sizeof(linker), "%s%c", param, (param[DM_STRLEN(param) - 1] != '.') ? '.' : '\0'); bbf_ctx_init_sub(&dmctx, ctx->dm_entryobj); memset(&dmctx.bb, 0, sizeof(struct blob_buf)); blob_buf_init(&dmctx.bb, 0); dmctx.in_param = linker; dm_entry_object_exists(&dmctx); bbf_ctx_clean_sub(&dmctx); blob_buf_free(&dmctx.bb); return dmctx.match; } void bbf_entry_services(unsigned int proto, bool is_commit, bool reload_required) { struct blob_buf bb = {0}; memset(&bb, 0, sizeof(struct blob_buf)); blob_buf_init(&bb, 0); blobmsg_add_string(&bb, "proto", (proto == BBFDM_CWMP) ? "cwmp": (proto == BBFDM_USP) ? "usp" : "both"); blobmsg_add_u8(&bb, "monitor", false); blobmsg_add_u8(&bb, "reload", reload_required); dmubus_call_blob_msg_set("bbf.config", is_commit ? "commit" : "revert", &bb); blob_buf_free(&bb); }