/*
 * Copyright (C) 2024 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: Mohd Husaam Mehdi <husaam.mehdi@genexis.eu>
 */

#include "syslog.h"

struct action_data {
	struct uci_section *file_section;
	struct uci_section *remote_section;
};

/*************************************************************
* UTILITY METHODS
**************************************************************/
struct uci_section *get_child_section_from_action_section(struct uci_section *action_section, char *child_section_type)
{
	if (!action_section || !child_section_type || *child_section_type == '\0') {
		return NULL;
	}

	char *action_name = NULL;
	action_name = bbf_uci_get_value_by_section_fallback_def(action_section, "name", "");

	if (DM_STRLEN(action_name) == 0) {
		return NULL;
	}

	struct uci_section *s = NULL;

	uci_foreach_sections("logmngr", child_section_type, s) {
		char *action = NULL;
		bbf_uci_get_value_by_section(s, "action", &action);

		if (action && *action != '\0' && !DM_STRCMP(action, action_name)) {
			return s;
		}
	}

	return NULL;
}

static void init_action_data(struct uci_section *action_section, struct action_data *ad)
{
	if (!ad) {
		return;
	}

	ad->file_section = NULL;
	ad->remote_section = NULL;

	// cppcheck-suppress cert-EXP05-C
	ad->file_section = get_child_section_from_action_section(action_section, "log_file");
	// cppcheck-suppress cert-EXP05-C
	ad->remote_section = get_child_section_from_action_section(action_section, "log_remote");
}

static void remove_action_child_sections(struct uci_section *action_section)
{
	char *action_name = NULL;

	dmuci_get_value_by_section_string(action_section, "name", &action_name);
	if (!action_name || action_name[0] == '\0') {
		return;
	}

	struct uci_section *s = NULL;

	// delete log_file sections that have option action equal to this action_name
	uci_foreach_sections("logmngr", "log_file", s) {
		char *action = NULL;
		dmuci_get_value_by_section_string(s, "action", &action);
		// if action is not empty and action is equal to action_name, then delete this section
		if (!DM_STRCMP(action, action_name)) {
			dmuci_delete_by_section(s, NULL, NULL);
			break;
		}
	}

	// delete log_remote sections that have option action equal to this action_name
	uci_foreach_sections("logmngr", "log_remote", s) {
		char *action = NULL;
		dmuci_get_value_by_section_string(s, "action", &action);
		// if action is not empty and action is equal to action_name, then delete this section
		if (!DM_STRCMP(action, action_name)) {
			dmuci_delete_by_section(s, NULL, NULL);
			break;
		}
	}
}

static void remove_option_from_action_sections(struct uci_section *section, const char *option_name, bool is_list)
{
	char *name = NULL;

	dmuci_get_value_by_section_string(section, "name", &name);
	if (!name || name[0] == '\0') {
		return;
	}

	struct uci_section *s = NULL;

	uci_foreach_sections("logmngr", "action", s) {
		if (is_list) {
			dmuci_del_list_value_by_section(s, option_name, name);
		} else {
			dmuci_set_value_by_section(s, option_name, "");
		}
	}
}

/*************************************************************
* ENTRY METHOD
**************************************************************/
static int browseSyslogSourceInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	char *inst = NULL;
	struct uci_section *s = NULL;

	// using UCI section only, no dmmap section as UCI maps to data model already
	uci_foreach_sections("logmngr", "source", s) {
		struct dm_data curr_data = {};
		curr_data.config_section = s;

		inst = handle_instance(dmctx, parent_node, curr_data.config_section, "bbf_source_inst", "name");

		if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)(&curr_data), inst) == DM_STOP)
			break;
	}

	return 0;
}

static int browseSyslogTemplateInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	char *inst = NULL;
	struct uci_section *s = NULL;

	// using UCI section only, no dmmap section as UCI maps to data model already
	uci_foreach_sections("logmngr", "template", s) {
		struct dm_data curr_data = {};
		curr_data.config_section = s;

		inst = handle_instance(dmctx, parent_node, curr_data.config_section, "bbf_template_inst", "name");

		if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)(&curr_data), inst) == DM_STOP)
			break;
	}

	return 0;
}

static int browseSyslogFilterInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	struct dm_data *curr_data = NULL;
	LIST_HEAD(dup_list);

	char *inst = NULL;

	synchronize_specific_config_sections_with_dmmap("logmngr", "filter", "dmmap_logmngr", &dup_list);
	list_for_each_entry(curr_data, &dup_list, list) {

		inst = handle_instance(dmctx, parent_node, curr_data->dmmap_section, "filter_instance", "filter_alias");

		if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)curr_data, inst) == DM_STOP)
			break;
	}

	free_dmmap_config_dup_list(&dup_list);
	return 0;
}

static int browseSyslogActionInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
{
	struct dm_data *curr_data = NULL;
	LIST_HEAD(dup_list);

	char *inst = NULL;

	synchronize_specific_config_sections_with_dmmap("logmngr", "action", "dmmap_logmngr", &dup_list);
	list_for_each_entry(curr_data, &dup_list, list) {
		struct action_data ad = {0};

		init_action_data(curr_data->config_section, &ad);

		curr_data->additional_data = (void *)(&ad);

		inst = handle_instance(dmctx, parent_node, curr_data->dmmap_section, "action_instance", "action_alias");

		if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)curr_data, inst) == DM_STOP)
			break;
	}

	free_dmmap_config_dup_list(&dup_list);
	return 0;
}

/*************************************************************
* ADD & DEL OBJ
**************************************************************/
static int addObjSyslogSource(char *refparam, struct dmctx *ctx, void *data, char **instance)
{
	struct uci_section *s = NULL;
	char s_name[16] = {0};

	snprintf(s_name, sizeof(s_name), "bbf_source_%s", *instance);

	dmuci_add_section("logmngr", "source", &s);
	dmuci_rename_section_by_section(s, s_name);
	dmuci_set_value_by_section(s, "name", s_name);
	dmuci_set_value_by_section(s, "system_messages", "1");
	dmuci_set_value_by_section(s, "kernel_messages", "1");

	return 0;
}

static int addObjSyslogTemplate(char *refparam, struct dmctx *ctx, void *data, char **instance)
{
	struct uci_section *s = NULL;
	char s_name[16] = {0};

	snprintf(s_name, sizeof(s_name), "bbf_tmplt_%s", *instance);

	dmuci_add_section("logmngr", "template", &s);
	dmuci_rename_section_by_section(s, s_name);
	dmuci_set_value_by_section(s, "name", s_name);

	return 0;
}

static int addObjSyslogFilter(char *refparam, struct dmctx *ctx, void *data, char **instance)
{
	struct uci_section *s = NULL;
	char s_name[16] = {0};

	snprintf(s_name, sizeof(s_name), "bbf_filter_%s", *instance);

	dmuci_add_section("logmngr", "filter", &s);
	dmuci_rename_section_by_section(s, s_name);
	dmuci_set_value_by_section(s, "name", s_name);

	return 0;
}

static int del_obj_common(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action, const char *type, bool list)
{
	struct uci_section *s = NULL, *stmp = NULL;

	switch (del_action) {
		case DEL_INST:
			// remove this from all action sections
			remove_option_from_action_sections(((struct dm_data *)data)->config_section, type, list);
			dmuci_delete_by_section(((struct dm_data *)data)->config_section, NULL, NULL);

			break;
		case DEL_ALL:
			// remove option altogether from all action sections
			uci_foreach_sections("logmngr", "action", s) {
				dmuci_set_value_by_section(s, type, "");
			}

			// delete all such sections
			s = NULL;
			uci_foreach_sections_safe("logmngr", type, stmp, s) {
				dmuci_delete_by_section(s, NULL, NULL);
			}

			break;
	}

	return 0;
}

static int delObjSyslogFilter(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
{
	del_obj_common(refparam, ctx, data, instance, del_action, "filter", true);
	return 0;
}

static int delObjSyslogSource(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
{
	del_obj_common(refparam, ctx, data, instance, del_action, "source", false);
	return 0;
}

static int delObjSyslogTemplate(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
{
	del_obj_common(refparam, ctx, data, instance, del_action, "template", false);
	return 0;
}

static int addObjSyslogAction(char *refparam, struct dmctx *ctx, void *data, char **instance)
{
	struct uci_section *s = NULL;
	char a_name[16] = {0};
	char lf_name[16] = {0};
	char lr_name[16] = {0};

	snprintf(a_name, sizeof(a_name), "bbf_action_%s", *instance);

	dmuci_add_section("logmngr", "action", &s);
	dmuci_rename_section_by_section(s, a_name);
	dmuci_set_value_by_section(s, "name", a_name);

	// add log_file section because there object cannot be added independently
	s = NULL;
	snprintf(lf_name, sizeof(lf_name), "bbf_lf_%s", *instance);
	dmuci_add_section("logmngr", "log_file", &s);
	dmuci_rename_section_by_section(s, lf_name);
	dmuci_set_value_by_section(s, "action", a_name);

	// add log_remote section because there object cannot be added independently
	s = NULL;
	snprintf(lr_name, sizeof(lr_name), "bbf_lr_%s", *instance);
	dmuci_add_section("logmngr", "log_remote", &s);
	dmuci_rename_section_by_section(s, lr_name);
	dmuci_set_value_by_section(s, "action", a_name);

	return 0;
}

static int delObjSyslogAction(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
{
	struct uci_section *s = NULL;
	struct uci_section *stmp = NULL;

	switch (del_action) {
		case DEL_INST:
			// remove this from all action sections
			remove_action_child_sections(((struct dm_data *)data)->config_section);
			dmuci_delete_by_section(((struct dm_data *)data)->config_section, NULL, NULL);

			break;
		case DEL_ALL:
			// delete all action sections
			uci_foreach_sections_safe("logmngr", "action", stmp, s) {
				dmuci_delete_by_section(s, NULL, NULL);
			}

			// delete all log_file sections
			s = NULL, stmp = NULL;
			uci_foreach_sections_safe("logmngr", "log_file", stmp, s) {
				dmuci_delete_by_section(s, NULL, NULL);
			}

			// delete all log_remote sections
			s = NULL, stmp = NULL;
			uci_foreach_sections_safe("logmngr", "log_remote", stmp, s) {
				dmuci_delete_by_section(s, NULL, NULL);
			}

			break;
	}
	return 0;
}

/*************************************************************
* GET & SET PARAM
**************************************************************/
static int get_Syslog_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *v;

	dmuci_get_option_value_string("logmngr", "globals", "enable", &v);
	*value = (*v == '0') ? "0" : "1";
	return 0;
}

static int set_Syslog_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	bool b = true;

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_boolean(ctx, value))
				return FAULT_9007;
			break;
		case VALUESET:
			string_to_bool(value, &b);

			dmuci_set_value("logmngr", "globals", "enable", b ? "1": "0");
			break;
	}

	return 0;
}

static int get_Syslog_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *v;

	dmuci_get_option_value_string("logmngr", "globals", "enable", &v);
	*value = (*v == '0') ? "Disabled" : "Enabled";
	return 0;
}

static int get_Syslog_FilterNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseSyslogFilterInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_Syslog_SourceNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseSyslogSourceInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_Syslog_TemplateNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseSyslogTemplateInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_Syslog_ActionNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	int cnt = get_number_of_entries(ctx, data, instance, browseSyslogActionInst);
	dmasprintf(value, "%d", cnt);
	return 0;
}

static int get_SyslogTemplate_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	return bbf_get_alias(ctx, ((struct dm_data *)data)->config_section, "name", instance, value);
}

static int set_SyslogTemplate_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	return bbf_set_alias(ctx, ((struct dm_data *)data)->config_section, "name", instance, value);
}

static int get_SyslogTemplate_Expression(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = bbf_uci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "expression", "");
	return 0;
}

static int set_SyslogTemplate_Expression(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, NULL, NULL))
				return FAULT_9007;
			break;
		case VALUESET:
			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "expression", value);
			break;
	}
	return 0;
}

static int get_SyslogSource_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	return bbf_get_alias(ctx, ((struct dm_data *)data)->config_section, "name", instance, value);
}

static int set_SyslogSource_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	return bbf_set_alias(ctx, ((struct dm_data *)data)->config_section, "name", instance, value);
}

static int get_SyslogSource_KernelMessages(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = bbf_uci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "kernel_messages", "1");
	return 0;
}

static int set_SyslogSource_KernelMessages(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	bool b = true;

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_boolean(ctx, value))
				return FAULT_9007;
			break;
		case VALUESET:
			bbf_convert_string_to_bool(value, &b);
			bbf_uci_set_value_by_section(((struct dm_data *)data)->config_section, "kernel_messages", b ? "1" : "0");

			break;
	}
	return 0;
}

static int get_SyslogSource_SystemMessages(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	*value = bbf_uci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "system_messages", "1");
	return 0;
}

static int set_SyslogSource_SystemMessages(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	bool b = true;

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_boolean(ctx, value))
				return FAULT_9007;
			break;
		case VALUESET:
			bbf_convert_string_to_bool(value, &b);
			bbf_uci_set_value_by_section(((struct dm_data *)data)->config_section, "system_messages", b ? "1" : "0");

			break;
	}
	return 0;
}

static int get_SyslogFilter_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	return bbf_get_alias(ctx, ((struct dm_data *)data)->dmmap_section, "filter_alias", instance, value);
}

static int set_SyslogFilter_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	return bbf_set_alias(ctx, ((struct dm_data *)data)->dmmap_section, "filter_alias", instance, value);
}

static int get_SyslogFilter_FacilityLevel(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct uci_list *uci_list = NULL;

	dmuci_get_value_by_section_list(((struct dm_data *)data)->config_section, "facility_level", &uci_list);

	if (uci_list != NULL) {
		struct uci_element *e = NULL;
		char buf[1024] = {0};
		unsigned pos = 0;

		uci_foreach_element(uci_list, e) {
			unsigned long facility_idx = DM_STRTOUL(e->name);

			if (facility_idx < FacilityMax) {
				*value = FacilityLevel[facility_idx];
				if (DM_STRLEN(buf) == 0)
					pos += snprintf(&buf[pos], sizeof(buf) - pos, "%s", FacilityLevel[facility_idx]);
				else
					pos += snprintf(&buf[pos], sizeof(buf) - pos, ",%s", FacilityLevel[facility_idx]);
			}
		}

		*value = dmstrdup(buf);

		return 0;
	}

	*value = "";
	return 0;
}

static int set_SyslogFilter_FacilityLevel(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_string_list(ctx, value, -1, -1, -1, -1, -1, FacilityLevel, NULL))
				return FAULT_9007;
			break;
		case VALUESET:
			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "facility_level", "");

			char *pch = NULL, *pchr = NULL;
			for (pch = strtok_r(value, ",", &pchr); pch != NULL; pch = strtok_r(NULL, ",", &pchr)) {
				size_t i = 0;
				for (; i < FacilityMax; i++) {
					if (!DM_STRCMP(FacilityLevel[i], pch)) {
						if (i < FacilityMax) {
							char fl_buf[8];
							snprintf(fl_buf, sizeof(fl_buf), "%zu", i);
							dmuci_add_list_value_by_section(((struct dm_data *)data)->config_section, "facility_level", fl_buf);
						}

						break;
					}
				}
			}

			break;
	}
	return 0;
}

static int get_SyslogFilter_Severity(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *level = NULL;

	level = bbf_uci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "severity_level", "");

	if (DM_STRLEN(level)) {
		unsigned long severity_idx = DM_STRTOUL(level);

		if (severity_idx < SeverityMax) {
			*value = dmstrdup(Severity[severity_idx]);
			return 0;
		}
	}

	*value = "";
	return 0;
}

static int set_SyslogFilter_Severity(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	size_t i = 0;

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, Severity, NULL))
				return FAULT_9007;
			break;
		case VALUESET:
			for (; i < SeverityMax; i++) {
				if (!DM_STRCMP(Severity[i], value)) {
					char buf[8];
					snprintf(buf, sizeof(buf), "%zu", i);
					dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "severity_level", buf);

					break;
				}
			}
			break;
	}
	return 0;
}

static int get_SyslogFilter_SeverityCompare(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *compare = NULL;

	compare = bbf_uci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "severity_compare", "");

	if (DM_STRLEN(compare)) {
		unsigned long severity_idx = DM_STRTOUL(compare);

		if (severity_idx < CompareMax) {
			*value = dmstrdup(SeverityCompare[severity_idx]);
			return 0;
		}
	}

	*value = "";
	return 0;
}

static int set_SyslogFilter_SeverityCompare(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	size_t i = 0;

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, SeverityCompare, NULL))
				return FAULT_9007;
			break;
		case VALUESET:
			for (; i < CompareMax; i++) {
				if (!DM_STRCMP(SeverityCompare[i], value)) {
					char buf[8];
					snprintf(buf, sizeof(buf), "%zu", i);
					dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "severity_compare", buf);

					break;
				}
			}
			break;
	}

	return 0;
}

static int get_SyslogFilter_SeverityCompareAction(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *compare_action = NULL;

	compare_action = bbf_uci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "severity_action", "");

	if (DM_STRLEN(compare_action)) {
		unsigned long severity_idx = DM_STRTOUL(compare_action);

		if (severity_idx < ActionMax) {
			*value = dmstrdup(SeverityCompareAction[severity_idx]);
			return 0;
		}
	}

	*value = "";
	return 0;
}

static int set_SyslogFilter_SeverityCompareAction(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	size_t i = 0;

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, SeverityCompareAction, NULL))
				return FAULT_9007;
			break;
		case VALUESET:
			for (; i < ActionMax; i++) {
				if (!DM_STRCMP(SeverityCompareAction[i], value)) {
					char buf[8];
					snprintf(buf, sizeof(buf), "%zu", i);
					dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "severity_action", buf);

					break;
				}
			}
			break;
	}

	return 0;
}

static int get_SyslogFilter_PatternMatch(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *pattern_match = NULL;

	pattern_match = bbf_uci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "pattern_match", "");

	if (DM_STRLEN(pattern_match))
		*value = pattern_match;
	else
		*value = "";

	return 0;
}

static int set_SyslogFilter_PatternMatch(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, NULL, NULL))
				return FAULT_9007;
			break;
		case VALUESET:
			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "pattern_match", value);
			break;
	}
	return 0;
}

static int get_SyslogAction_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	return bbf_get_alias(ctx, ((struct dm_data *)data)->dmmap_section, "action_alias", instance, value);
}

static int set_SyslogAction_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	return bbf_set_alias(ctx, ((struct dm_data *)data)->dmmap_section, "action_alias", instance, value);
}

static int get_SyslogAction_SourceRef(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct uci_list *source = NULL;
	dmuci_get_value_by_section_list(((struct dm_data *)data)->config_section, "source", &source);

	if (source != NULL) {
		char buf[2056] = {0};
		struct uci_element *e = NULL;

		uci_foreach_element(source, e) {
			bbfdm_get_references(ctx, MATCH_ALL, "Device.Syslog.Source.", "Alias", e->name, buf, sizeof(buf));
		}

		*value = dmstrdup(buf);
	} else {
		*value = "";
	}

	return 0;
}

static int set_SyslogAction_SourceRef(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char **arr;
	size_t length = 0;
	int i;

	char *allowed_objects[] = {
		"Device.Syslog.Source.",
		NULL
	};

	struct dm_reference reference = {0};

	switch (action)	{
		case VALUECHECK:
			if (DM_STRLEN(value) == 0)
				break;

			// split cs into tokens
			arr = strsplit(value, ",", &length);
			for (i = 0; i < length; i++) {
				memset(&reference, 0 , sizeof(struct dm_reference));
				// resolve datamodel path
				bbfdm_get_reference_linker(ctx, arr[i], &reference);

				if (DM_STRLEN(reference.path) == 0)
					continue;

				if (dm_validate_allowed_objects(ctx, &reference, allowed_objects)) {
					return FAULT_9007;
				}
			}

			break;
		case VALUESET:
			bbf_uci_set_value_by_section(((struct dm_data *)data)->config_section, "source", "");

			if (DM_STRLEN(value) == 0) {
				break;
			}

			arr = strsplit(value, ",", &length);
			for (i = 0; i < length; i++) {
				memset(&reference, 0 , sizeof(struct dm_reference));
				bbfdm_get_reference_linker(ctx, arr[i], &reference);

				if (DM_STRLEN(reference.path) == 0 || DM_STRLEN(reference.value) == 0)
					continue;

				// set it in action section
				dmuci_add_list_value_by_section(((struct dm_data *)data)->config_section, "source", reference.value);
			}

			break;
	}
	return 0;
}

static int get_SyslogAction_TemplateRef(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	char *template = bbf_uci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "template", "");

	if (DM_STRLEN(template)) {
		// get the template path
		_bbfdm_get_references(ctx, "Device.Syslog.Template.", "Alias", template, value);
	}

	return 0;
}

static int set_SyslogAction_TemplateRef(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	struct dm_reference reference = {0};
	char *allowed_obj[] = {
		"Device.Syslog.Template.",
		NULL
	};

	bbfdm_get_reference_linker(ctx, value, &reference);

	switch (action) {
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, reference.path, -1, -1, NULL, NULL))
				return FAULT_9007;

			if (dm_validate_allowed_objects(ctx, &reference, allowed_obj))
				return FAULT_9007;
			break;
		case VALUESET:
			bbf_uci_set_value_by_section(((struct dm_data *)data)->config_section, "template", reference.value);

			break;
	}

	return 0;
}

static int get_SyslogAction_FilterRef(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct uci_list *filter = NULL;
	dmuci_get_value_by_section_list(((struct dm_data *)data)->config_section, "filter", &filter);

	if (filter != NULL) {
		char buf[2056] = {0};
		struct uci_element *e = NULL;

		uci_foreach_element(filter, e) {
			struct uci_section *cs = NULL;
			char *alias = NULL;
			// get our filter section and then its alias
			uci_foreach_sections("logmngr", "filter", cs) {
				char *filter_name = NULL;
				struct uci_section *ds = NULL;

				get_dmmap_section_of_config_section("dmmap_logmngr", "filter", section_name(cs), &ds);

				if (ds == NULL)
					continue;

				filter_name = bbf_uci_get_value_by_section_fallback_def(cs, "name", "");

				if (DM_STRLEN(filter_name) && !DM_STRCMP(filter_name, e->name)) {
					alias = bbf_uci_get_value_by_section_fallback_def(ds, "filter_alias", "");

					if (alias != NULL && *alias != '\0')
						break;
				}
			}

			bbfdm_get_references(ctx, MATCH_ALL, "Device.Syslog.Filter.", "Alias", alias, buf, sizeof(buf));
		}

		*value = dmstrdup(buf);
	} else {
		*value = "";
	}

	return 0;
}

static int set_SyslogAction_FilterRef(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	char **arr;
	size_t length = 0;
	int i;

	char *allowed_objects[] = {
		"Device.Syslog.Filter.",
		NULL
	};

	struct dm_reference reference = {0};

	switch (action)	{
		case VALUECHECK:
			if (DM_STRLEN(value) == 0)
				break;

			// split cs into tokens
			arr = strsplit(value, ",", &length);
			for (i = 0; i < length; i++) {
				memset(&reference, 0 , sizeof(struct dm_reference));
				// resolve datamodel path
				bbfdm_get_reference_linker(ctx, arr[i], &reference);

				if (DM_STRLEN(reference.path) == 0)
					continue;


				if (dm_validate_allowed_objects(ctx, &reference, allowed_objects)) {
					return FAULT_9007;
				}
			}

			break;
		case VALUESET:
			bbf_uci_set_value_by_section(((struct dm_data *)data)->config_section, "filter", "");

			if (DM_STRLEN(value) == 0) {
				break;
			}

			arr = strsplit(value, ",", &length);
			for (i = 0; i < length; i++) {
				memset(&reference, 0 , sizeof(struct dm_reference));
				bbfdm_get_reference_linker(ctx, arr[i], &reference);

				if (DM_STRLEN(reference.path) == 0 || DM_STRLEN(reference.value) == 0)
					continue;

				// get the bbf section for this alias
				struct uci_section *ds = NULL;
				uci_path_foreach_sections(bbfdm, "dmmap_logmngr", "filter", ds) {
					char *alias = NULL;
					alias = bbf_uci_get_value_by_section_fallback_def(ds, "filter_alias", "");

					// alias matched
					if (DM_STRLEN(alias) && !DM_STRCMP(alias, reference.value)) {
						// get the config section name
						char *section_name = NULL;
						section_name = bbf_uci_get_value_by_section_fallback_def(ds, "section_name", "");

						// get the config section
						struct uci_section *cs = NULL;
						get_config_section_of_dmmap_section("logmngr", "filter", section_name, &cs);

						// if we got config section
						if (cs) {
							// get the value for option name
							char *filter_name = NULL;
							filter_name = bbf_uci_get_value_by_section_fallback_def(cs, "name", "");

							// if we got name
							if (DM_STRLEN(filter_name)) {
								// set it in action section
								dmuci_add_list_value_by_section(((struct dm_data *)data)->config_section, "filter", filter_name);
							}
						}
					}
				}
			}

			break;
	}
	return 0;
}

static int get_SyslogActionLogFile_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct uci_section *s = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->file_section);

	if (s != NULL)
		*value = bbf_uci_get_value_by_section_fallback_def(s, "enable", "1");
	else
		*value = "";

	return 0;
}

static int set_SyslogActionLogFile_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	struct uci_section *f = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->file_section);
	bool b = true;

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_boolean(ctx, value))
				return FAULT_9007;
			break;
		case VALUESET:
			if (f == NULL)
				return FAULT_9002;

			bbf_convert_string_to_bool(value, &b);
			bbf_uci_set_value_by_section(f, "enable", b ? "1" : "0");

			break;
	}
	return 0;
}

static int get_SyslogActionLogFile_VendorLogFileRef(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	// check if option file is set in config_section
	struct uci_section *s = NULL;
	s = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->file_section);

	// not storing the value for future use so that if UCI is updated manually,
	// we still show fresh data
	if (s != NULL) {
		char *file = bbf_uci_get_value_by_section_fallback_def(s, "file", "");

		if (DM_STRLEN(file)) {
			char file_uri[5010] = {0};

			// if there is a path, then prepend file:// to it to comply with bbf requirement of file URI
			snprintf(file_uri, sizeof(file_uri), "file://%s", file);

			// get the vendor file path
			_bbfdm_get_references(ctx, "Device.DeviceInfo.VendorLogFile.", "Name", file_uri, value);
		}
	}

	return 0;
}

static int get_SyslogActionLogFile_FilePath(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct uci_section *f = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->file_section);

	if (f != NULL) {
		char *file_path = bbf_uci_get_value_by_section_fallback_def(f, "file", "");

		if (DM_STRLEN(file_path)) {
			// 4096 for path and 7 for file://
			char file_uri[5010] = {0};

			// if there is a path, then prepend file:// to it to comply with bbf requirement of file URI
			snprintf(file_uri, sizeof(file_uri), "file://%s", file_path);
			*value = dmstrdup(file_uri);

			return 0;
		}
	}

	*value = "";
	return 0;
}

static int set_SyslogActionLogFile_FilePath(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	struct uci_section *f = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->file_section);

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, NULL, NULL))
				return FAULT_9007;
			break;
		case VALUESET:
			if (f == NULL)
				return FAULT_9002;

			// remove file:// prefix from input
			if (!DM_STRNCMP(value, "file://", 7))
				value = value + 7;

			bbf_uci_set_value_by_section(f, "file", value);

			break;
	}
	return 0;
}

static int get_SyslogActionLogRemote_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct uci_section *r = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->remote_section);

	if (r != NULL)
		*value = bbf_uci_get_value_by_section_fallback_def(r, "enable", "1");
	else
		*value = "";

	return 0;
}

static int set_SyslogActionLogRemote_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	struct uci_section *r = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->remote_section);
	bool b = true;

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_boolean(ctx, value))
				return FAULT_9007;
			break;
		case VALUESET:
			if (r == NULL)
				return FAULT_9002;

			bbf_convert_string_to_bool(value, &b);
			bbf_uci_set_value_by_section(r, "enable", b ? "1" : "0");

			break;
	}

	return 0;
}

static int get_SyslogActionLogRemote_Address(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct uci_section *r = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->remote_section);

	if (r != NULL)
		*value = bbf_uci_get_value_by_section_fallback_def(r, "log_ip", "");
	else
		*value = "";

	return 0;
}

static int set_SyslogActionLogRemote_Address(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	struct uci_section *r = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->remote_section);

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, NULL, NULL))
				return FAULT_9007;
			break;
		case VALUESET:
			if (r == NULL)
				return FAULT_9002;

			bbf_uci_set_value_by_section(r, "log_ip", value);
			break;
	}

	return 0;
}

static int get_SyslogActionLogRemote_Protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct uci_section *r = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->remote_section);
	char *proto;

	dmuci_get_value_by_section_string(r, "proto", &proto);
	if (DM_STRCMP(proto, "tls") == 0) {
		*value = "TLS";
	} else if (DM_STRCMP(proto, "tcp") == 0) {
		*value = "TCP";
	} else {
		*value = "UDP";
	}

	return 0;
}

static int set_SyslogActionLogRemote_Protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	struct uci_section *r = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->remote_section);
	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, Protocol, NULL))
				return FAULT_9007;
			break;
		case VALUESET:
			if (strcmp("TCP", value) == 0)
				dmuci_set_value_by_section(r, "proto", "tcp");
			else if (strcmp("UDP", value) == 0)
				dmuci_set_value_by_section(r, "proto", "udp");
			else if (strcmp("TLS", value) == 0)
				dmuci_set_value_by_section(r, "proto", "tls");
			break;
	}

	return 0;
}

static int get_SyslogActionLogRemote_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct uci_section *r = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->remote_section);

	if (r != NULL)
		*value = bbf_uci_get_value_by_section_fallback_def(r, "port", "514");
	else
		*value = "514";

	return 0;
}

static int set_SyslogActionLogRemote_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	struct uci_section *r = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->remote_section);

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1","65535"}}, 1))
				return FAULT_9007;
			break;
		case VALUESET:
			if (r == NULL)
				return FAULT_9002;

			bbf_uci_set_value_by_section(r, "port", value);
			break;
	}

	return 0;
}

static int get_SyslogActionLogRemote_Certificate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct uci_section *r = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->remote_section);

	*value = "";

	if (r != NULL) {
		*value = bbf_uci_get_value_by_section_fallback_def(((struct dm_data *)data)->dmmap_section, "dm_certificate", "");

		// we did not find dm_certificate, so try to deduce it via path
		if (DM_STRLEN(*value) == 0) {
			char *cert_path = NULL;
			cert_path = bbf_uci_get_value_by_section_fallback_def(r, "cert", "");

			if (DM_STRLEN(cert_path) != 0) {
				// loop over security dmmap file, compare path and return instance
				uci_path_foreach_sections(bbfdm, "dmmap_security", "security_certificate", r) {
					char *path = NULL;
					path = bbf_uci_get_value_by_section_fallback_def(r, "path", "");

					if (DM_STRLEN(path) != 0) {
						if (!DM_STRCMP(path, cert_path)) {
							char bbf_path[256] = {0};
							char *inst_number = NULL;

							inst_number = bbf_uci_get_value_by_section_fallback_def(r, "security_certificate_instance", "");

							snprintf(bbf_path, sizeof(bbf_path), "Device.Security.Certificate.%s", inst_number);

							if (DM_STRLEN(inst_number) != 0) {
								// write it so that we don't have to do this processing next time
								bbf_uci_set_value_by_section(((struct dm_data *)data)->dmmap_section, "dm_certificate", bbf_path);
								*value = dmstrdup(bbf_path);
							}

							// exit the loop
							return 0;
						}
					}
				}
			}
		}
	}

	return 0;
}

static int set_SyslogActionLogRemote_Certificate(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	struct uci_section *r = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->remote_section);

	struct dm_reference reference = {0};
	bbfdm_get_reference_linker(ctx, value, &reference);

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_string(ctx, value, -1, -1, NULL, NULL))
				return FAULT_9007;

			// TODO: linker flag is not set for the Device.Security.Certificate. as of now
			// so dm_validate_allowed_objects will fail, hence this remains to be done
			// for now just check prefix in the input value
			if (DM_STRNCMP(value, "Device.Security.Certificate.", DM_STRLEN("Device.Security.Certificate.")))
				return FAULT_9007;

			break;
		case VALUESET:
			reference.path = value;

			struct uci_section *s = NULL;
			if (!reference.path) {
				return FAULT_9002;
			}

			// find the last dot in path, so that we can get the instance number after that
			char *p = DM_STRRCHR(reference.path, '.');

			uci_path_foreach_sections(bbfdm, "dmmap_security", "security_certificate", s) {
				char *inst = NULL;
				inst = bbf_uci_get_value_by_section_fallback_def(s, "security_certificate_instance", "");

				if (DM_STRLEN(inst) != 0) {
					if (!DM_STRCMP(inst, p + 1)) {
						char *path = NULL;

						path = bbf_uci_get_value_by_section_fallback_def(s, "path", "");

						if (DM_STRLEN(path) != 0) {
							bbf_uci_set_value_by_section(r, "cert", path);
							bbf_uci_set_value_by_section(((struct dm_data *)data)->dmmap_section, "dm_certificate", reference.path);
						}

						return 0;
					}
				}
			}

			return FAULT_9002;
	}

	return 0;
}

static int get_SyslogActionLogRemote_PeerVerify(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
{
	struct uci_section *r = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->remote_section);

	if (r != NULL)
		*value = bbf_uci_get_value_by_section_fallback_def(r, "peer_verify", "");
	else
		*value = "";

	return 0;
}

static int set_SyslogActionLogRemote_PeerVerify(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
{
	struct uci_section *r = (struct uci_section *)(((struct action_data *)((struct dm_data *)data)->additional_data)->remote_section);

	switch (action)	{
		case VALUECHECK:
			if (bbfdm_validate_boolean(ctx, value))
				return FAULT_9007;
			break;
		case VALUESET:
			if (r == NULL)
				return FAULT_9002;

			bbf_uci_set_value_by_section(r, "peer_verify", value);

			break;
	}

	return 0;
}

/**********************************************************************************************************************************
*                                            OBJ & PARAM DEFINITION
***********************************************************************************************************************************/
/* *** Device.Syslog. *** */
DMOBJ tDeviceSyslogObj[] = {
{"Syslog", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tSyslogObj, tSyslogParams, NULL, BBFDM_BOTH, NULL},
{0}
};

DMOBJ tSyslogObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys */
{"Filter", &DMWRITE, addObjSyslogFilter, delObjSyslogFilter, NULL, browseSyslogFilterInst, NULL, NULL, NULL, tSyslogFilterParams, NULL, BBFDM_BOTH, NULL},
{"Source", &DMWRITE, addObjSyslogSource, delObjSyslogSource, NULL, browseSyslogSourceInst, NULL, NULL, NULL, tSyslogSourceParams, NULL, BBFDM_BOTH, NULL},
{"Template", &DMWRITE, addObjSyslogTemplate, delObjSyslogTemplate, NULL, browseSyslogTemplateInst, NULL, NULL, NULL, tSyslogTemplateParams, NULL, BBFDM_BOTH, NULL},
{"Action", &DMWRITE, addObjSyslogAction, delObjSyslogAction, NULL, browseSyslogActionInst, NULL, NULL, tSyslogActionObj, tSyslogActionParams, NULL, BBFDM_BOTH, NULL},
{0}
};

DMLEAF tSyslogParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"Enable", &DMWRITE, DMT_BOOL, get_Syslog_Enable, set_Syslog_Enable, BBFDM_BOTH},
{"Status", &DMREAD, DMT_STRING, get_Syslog_Status, NULL, BBFDM_BOTH},
{"FilterNumberOfEntries", &DMREAD, DMT_UNINT, get_Syslog_FilterNumberOfEntries, NULL, BBFDM_BOTH},
{"SourceNumberOfEntries", &DMREAD, DMT_UNINT, get_Syslog_SourceNumberOfEntries, NULL, BBFDM_BOTH},
{"TemplateNumberOfEntries", &DMREAD, DMT_UNINT, get_Syslog_TemplateNumberOfEntries, NULL, BBFDM_BOTH},
{"ActionNumberOfEntries", &DMREAD, DMT_UNINT, get_Syslog_ActionNumberOfEntries, NULL, BBFDM_BOTH},
{0}
};

/* *** Device.Syslog.Filter.{i}. *** */
DMLEAF tSyslogFilterParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"Alias", &DMWRITE, DMT_STRING, get_SyslogFilter_Alias, set_SyslogFilter_Alias, BBFDM_BOTH, DM_FLAG_UNIQUE|DM_FLAG_LINKER},
{"FacilityLevel", &DMWRITE, DMT_STRING, get_SyslogFilter_FacilityLevel, set_SyslogFilter_FacilityLevel, BBFDM_BOTH},
{"Severity", &DMWRITE, DMT_STRING, get_SyslogFilter_Severity, set_SyslogFilter_Severity, BBFDM_BOTH},
{"SeverityCompare", &DMWRITE, DMT_STRING, get_SyslogFilter_SeverityCompare, set_SyslogFilter_SeverityCompare, BBFDM_BOTH},
{"SeverityCompareAction", &DMWRITE, DMT_STRING, get_SyslogFilter_SeverityCompareAction, set_SyslogFilter_SeverityCompareAction, BBFDM_BOTH},
{"PatternMatch", &DMWRITE, DMT_STRING, get_SyslogFilter_PatternMatch, set_SyslogFilter_PatternMatch, BBFDM_BOTH},
{0}
};

/* *** Device.Syslog.Template.{i}. *** */
DMLEAF tSyslogTemplateParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"Alias", &DMWRITE, DMT_STRING, get_SyslogTemplate_Alias, set_SyslogTemplate_Alias, BBFDM_BOTH, DM_FLAG_UNIQUE|DM_FLAG_LINKER},
{"Expression", &DMWRITE, DMT_STRING, get_SyslogTemplate_Expression, set_SyslogTemplate_Expression, BBFDM_BOTH},
{0}
};

/* *** Device.Syslog.Source.{i}. *** */
DMLEAF tSyslogSourceParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"Alias", &DMWRITE, DMT_STRING, get_SyslogSource_Alias, set_SyslogSource_Alias, BBFDM_BOTH, DM_FLAG_UNIQUE|DM_FLAG_LINKER},
{"KernelMessages", &DMWRITE, DMT_BOOL, get_SyslogSource_KernelMessages, set_SyslogSource_KernelMessages, BBFDM_BOTH},
{"SystemMessages", &DMWRITE, DMT_BOOL, get_SyslogSource_SystemMessages, set_SyslogSource_SystemMessages, BBFDM_BOTH},
{0}
};

/* *** Device.Syslog.Action.{i}. *** */
DMOBJ tSyslogActionObj[] = {
/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys */
{"LogFile", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tSyslogActionLogFileParams, NULL, BBFDM_BOTH, NULL},
{"LogRemote", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, tSyslogActionLogRemoteParams, NULL, BBFDM_BOTH, NULL},
{0}
};

DMLEAF tSyslogActionParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"Alias", &DMWRITE, DMT_STRING, get_SyslogAction_Alias, set_SyslogAction_Alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
{"SourceRef", &DMWRITE, DMT_STRING, get_SyslogAction_SourceRef, set_SyslogAction_SourceRef, BBFDM_BOTH, DM_FLAG_REFERENCE},
{"FilterRef", &DMWRITE, DMT_STRING, get_SyslogAction_FilterRef, set_SyslogAction_FilterRef, BBFDM_BOTH, DM_FLAG_REFERENCE},
{"TemplateRef", &DMWRITE, DMT_STRING, get_SyslogAction_TemplateRef, set_SyslogAction_TemplateRef, BBFDM_BOTH, DM_FLAG_REFERENCE},
//{"StructuredData", &DMWRITE, DMT_BOOL, get_SyslogAction_StructuredData, set_SyslogAction_StructuredData, BBFDM_BOTH},
//{"LogEvent!", &DMREAD, DMT_EVENT, NULL, NULL, BBFDM_USP},
{0}
};

/* *** Device.Syslog.Action.{i}.LogFile. *** */
DMLEAF tSyslogActionLogFileParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"Enable", &DMWRITE, DMT_BOOL, get_SyslogActionLogFile_Enable, set_SyslogActionLogFile_Enable, BBFDM_BOTH},
{"VendorLogFileRef", &DMREAD, DMT_STRING, get_SyslogActionLogFile_VendorLogFileRef, NULL, BBFDM_BOTH, DM_FLAG_REFERENCE},
{"FilePath", &DMWRITE, DMT_STRING, get_SyslogActionLogFile_FilePath, set_SyslogActionLogFile_FilePath, BBFDM_BOTH},
{0}
};

/* *** Device.Syslog.Action.{i}.LogRemote. *** */
DMLEAF tSyslogActionLogRemoteParams[] = {
/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
{"Enable", &DMWRITE, DMT_BOOL, get_SyslogActionLogRemote_Enable, set_SyslogActionLogRemote_Enable, BBFDM_BOTH},
{"Address", &DMWRITE, DMT_STRING, get_SyslogActionLogRemote_Address, set_SyslogActionLogRemote_Address, BBFDM_BOTH},
{"Protocol", &DMWRITE, DMT_STRING, get_SyslogActionLogRemote_Protocol, set_SyslogActionLogRemote_Protocol, BBFDM_BOTH},
{"Port", &DMWRITE, DMT_UNINT, get_SyslogActionLogRemote_Port, set_SyslogActionLogRemote_Port, BBFDM_BOTH},
{"Certificate", &DMWRITE, DMT_STRING, get_SyslogActionLogRemote_Certificate, set_SyslogActionLogRemote_Certificate, BBFDM_BOTH, DM_FLAG_REFERENCE},
{"PeerVerify", &DMWRITE, DMT_BOOL, get_SyslogActionLogRemote_PeerVerify, set_SyslogActionLogRemote_PeerVerify, BBFDM_BOTH},
{0}
};

/* ********** DynamicObj ********** */
DM_MAP_OBJ tDynamicObj[] = {
/* parentobj, nextobject, parameter */
{"Device.", tDeviceSyslogObj, NULL},
{0}
};
