diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..03146ac7a439244d8057f6e9ae5d660f075b85e3
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,15 @@
+include:
+  - project: 'iopsys/gitlab-ci-pipeline'
+    file: '/static-code-analysis.yml'
+    ref: '0.31'
+
+stages:
+    - static_code_analysis
+
+variables:
+  DEBUG: 'TRUE'
+  SOURCE_FOLDER: "./src"
+  FLAWFINDER_OPTIONS: "-m 4 --error-level=5"
+  CPPCHECK_OPTIONS: "--enable=all --error-exitcode=1"
+  COMPILE: "./gitlab-ci/compile.sh"
+
diff --git a/README.md b/README.md
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..006380023c39af165ba025784a5e3f13a0add266 100644
--- a/README.md
+++ b/README.md
@@ -0,0 +1,7 @@
+# Firewall Manager
+
+This package contains code for the Device.Firewall. and Device.NAT. objects.
+
+## Dependencies
+
+- For both the Firewall and NAT objects, UCI file *firewall* is being used (package firewall).
diff --git a/docs/.pages b/docs/.pages
new file mode 100644
index 0000000000000000000000000000000000000000..077dd799babf86aacc95e0e769053205d3de3f38
--- /dev/null
+++ b/docs/.pages
@@ -0,0 +1,8 @@
+title: "FIREWALLMNGR"
+
+nav:
+    - "arch"
+    - "api"
+    - "spec"
+    - "guide"
+    - "..."
diff --git a/docs/api/.pages b/docs/api/.pages
new file mode 100644
index 0000000000000000000000000000000000000000..d24670492410f5b22dcd68c1b8dd93db7cdfda66
--- /dev/null
+++ b/docs/api/.pages
@@ -0,0 +1,6 @@
+title: "FIREWALLMNGR"
+
+nav:
+    - "ubus"
+    - "uci"
+    - "..."
diff --git a/docs/api/ubus/.pages b/docs/api/ubus/.pages
new file mode 100644
index 0000000000000000000000000000000000000000..0a9cd8d4b99049aa6636ce077e1464d129b2a057
--- /dev/null
+++ b/docs/api/ubus/.pages
@@ -0,0 +1,4 @@
+title: "FIREWALLMNGR"
+
+nav:
+    - "..."
diff --git a/docs/api/uci/.pages b/docs/api/uci/.pages
new file mode 100644
index 0000000000000000000000000000000000000000..0a9cd8d4b99049aa6636ce077e1464d129b2a057
--- /dev/null
+++ b/docs/api/uci/.pages
@@ -0,0 +1,4 @@
+title: "FIREWALLMNGR"
+
+nav:
+    - "..."
diff --git a/docs/arch/.pages b/docs/arch/.pages
new file mode 100644
index 0000000000000000000000000000000000000000..c399cd960c9dff2ecee901488c19434ca87a0749
--- /dev/null
+++ b/docs/arch/.pages
@@ -0,0 +1,2 @@
+title: "FIREWALLMNGR"
+hide: true
diff --git a/docs/guide/.pages b/docs/guide/.pages
new file mode 100644
index 0000000000000000000000000000000000000000..0a9cd8d4b99049aa6636ce077e1464d129b2a057
--- /dev/null
+++ b/docs/guide/.pages
@@ -0,0 +1,4 @@
+title: "FIREWALLMNGR"
+
+nav:
+    - "..."
diff --git a/docs/guide/libbbfdm_Firewall.md b/docs/guide/libbbfdm_Firewall.md
new file mode 100644
index 0000000000000000000000000000000000000000..b02d5288f25cc265004c825850844e72dc4d7822
--- /dev/null
+++ b/docs/guide/libbbfdm_Firewall.md
@@ -0,0 +1,54 @@
+# TR181 Firewall datamodel mapping
+
+Aim of this document is to explain the TR181 firewall datamodel parameter mappings with firewall and network uci.
+
+In TR-181 firewall definition, we have Device.Firewall.Level., Deivce.Firewall.Chain. and Firewall.Chain.{i}.Rules., which does not have one to one mapping with firewall uci sections.
+
+So for each new network interface created by libbbf, a new firewall uci zone will be created as follow:
+- Create a Network interface section
+- Create a Firewall zone section corresponding to the Interface section in the network uci file
+- Give it the same name as the interface section in the network uci file.
+- Set the default firewall zone value of input/output/forward to ACCEPT/ACCEPT/ACCEPT for all bridge interface and REJECT/ACCEPT/REJECT for all non bridge interfaces
+
+So basically, if the network uci has this section for an interface
+```bash
+config interface ‘iptv’
+    option device ‘ethx.y’
+    option proto ‘dhcp’
+```
+
+Then below zone gets created by libbbf in firewall uci:
+```bash
+config zone ‘iptv’
+    option network ‘iptv’
+    option input ‘REJECT’
+    option output ‘ACCEPT’
+    option forward ‘REJECT’
+```
+
+Further, Per interface default policy can be configured by adding a rule in chain for each direction. So, if its required to have ACCEPT policy for input direction, then specify a rule as Chain.1.Rule.x.SourceInterface = Device.IP.Interface.3 and Rule.x.Target = ACCEPT and this result into corresponding firewall uci which does the same.
+
+```bash
+config rule ‘x’
+    option src ‘iptv’
+    option target ‘ACCEPT’
+```
+
+> Note: when trying to define a rule as Chain.1.Rule.x.SourceInterface = Device.IP.Interface.x and the zone for this interface (Device.IP.Interface.x) doesn't exist in the firewall uci file so, a new firewall zone section corresponding to this interface section will be created.
+
+Similarly, to configure firewall rules for each interfaces, add rule objects in Device.Firewall.Chain.{i}.Rule.{i}. table to the existing Device.Firewall.Chain.{i}. in the order in which they should be applied.
+
+# Limitations
+- Multiple Device.Firewall.Level.{i}. objects are not supported
+- Multiple Device.Firewall.Chain.{i}. objects are not supported
+- Device.Firewall.Chain.{i}.Rule.{i}.TargetChain not supported
+- Device.Firewall.Chain.{i}.Rule.{i}.Order not supported, firewall rule applied in the order in which they are created, lower index rule has higher priority.
+- Device.Firewall.Config only supports 'Advanced' mode
+
+# How Device.Firewall.Chain.{i}.Rule.{i}. Object handles the Protocol parameter:
+
+For Firewall rule sections, if the protocol(proto option) is not defined or if there are multiple protocols defined in the rule like proto='tcp udp' then in those cases the 'Device.Firewall.Chain.{i}.Rule.{i}.Protocol' parameter will have as value '255' which is reserved in the protocol specification.
+
+# References
+1. [Firewall uci](https://openwrt.org/docs/guide-user/firewall/firewall_configuration)
+2. [Network uci](https://openwrt.org/docs/guide-user/base-system/basic-networking)
diff --git a/docs/spec/.pages b/docs/spec/.pages
new file mode 100644
index 0000000000000000000000000000000000000000..c399cd960c9dff2ecee901488c19434ca87a0749
--- /dev/null
+++ b/docs/spec/.pages
@@ -0,0 +1,2 @@
+title: "FIREWALLMNGR"
+hide: true
diff --git a/gitlab-ci/compile.sh b/gitlab-ci/compile.sh
new file mode 100755
index 0000000000000000000000000000000000000000..3a6962853ec1d9b0f7fbed73c821489e01b8c268
--- /dev/null
+++ b/gitlab-ci/compile.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+echo "Install dependencies"
+orig_dir=$(pwd)
+echo $orig_dir
+
+source ./gitlab-ci/shared.sh
+
+# install bbfdm
+install_bbfdm
+
+# compile
+set -e
+echo "build stage"
+cd $orig_dir/src/
+pwd
+# just the existence of macro INCLUDE_PORT_TRIGGER is checked in code
+make CFLAGS='-DINCLUDE_PORT_TRIGGER=\"yes\"'
diff --git a/gitlab-ci/shared.sh b/gitlab-ci/shared.sh
new file mode 100644
index 0000000000000000000000000000000000000000..f098751729cd67463d6d4912bc1bf7ffab42ee40
--- /dev/null
+++ b/gitlab-ci/shared.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+function exec_cmd()
+{
+	echo "executing $@"
+	$@ >/dev/null 2>&1
+
+	if [ $? -ne 0 ]; then
+		echo "Failed to execute $@"
+		exit 1
+	fi
+}
+
+function install_bbfdm()
+{
+	[ -d "/opt/dev/bbfdm" ] && rm -rf /opt/dev/bbfdm
+
+	if [ -n "${BBFDM_BRANCH}" ]; then
+		exec_cmd git clone -b ${BBFDM_BRANCH} https://dev.iopsys.eu/bbf/bbfdm.git /opt/dev/bbfdm
+	else
+		exec_cmd git clone https://dev.iopsys.eu/bbf/bbfdm.git /opt/dev/bbfdm
+	fi
+
+	cd /opt/dev/bbfdm
+	./gitlab-ci/install-dependencies.sh install
+	./gitlab-ci/setup.sh install
+}
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..2c38144e97a893a72a70ddfe600bae4e96f1666f
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,25 @@
+LIB = libfirewallmngr.so
+
+# if filter does not return empty when searching for -DINCLUDE_PORT_TRIGGER
+# then include nat_porttrigger.o
+# else
+# do not include nat_porttrigger.o
+ifneq (,$(filter -DINCLUDE_PORT_TRIGGER, $(CFLAGS)))
+LIB_OBJS = firewallmngr.o firewall.o nat.o nat_porttrigger.o
+else
+LIB_OBJS = firewallmngr.o firewall.o nat.o
+endif
+
+PROG_CFLAGS = $(CFLAGS) -Wall -Werror -fPIC
+LIB_LDFLAGS = $(LDFLAGS)
+
+%.o: %.c
+	$(CC) $(PROG_CFLAGS) -c -o $@ $<
+
+all: $(LIB)
+
+$(LIB): $(LIB_OBJS)
+	$(CC) $(PROG_CFLAGS) -shared -o $@ $^ $(LIB_LDFLAGS)
+
+clean:
+	rm -f *.o $(LIB)
diff --git a/src/firewall.c b/src/firewall.c
new file mode 100644
index 0000000000000000000000000000000000000000..51f858277db26008ee4afd84dd863b10d4ce0647
--- /dev/null
+++ b/src/firewall.c
@@ -0,0 +1,2554 @@
+/*
+ * 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: Omar Kallel <omar.kallel@pivasoftware.com>
+ *      Author: Amin Ben Romdhane <amin.benromdhane@iopsys.eu>
+ */
+
+#include "firewall.h"
+
+struct rule_sec
+{
+	struct list_head list;
+	struct uci_section *config_section;
+	struct uci_section *dmmap_section;
+	char **dynamic_rule;
+	char *creator;
+	bool is_dynamic_rule;
+};
+
+/*************************************************************
+* COMMON FUNCTIONS
+**************************************************************/
+static void firewall__create_zone_section(char *s_name)
+{
+	struct uci_section *s = NULL;
+	char *input = NULL;
+	char *output = NULL;
+	char *forward = NULL;
+
+	dmuci_get_option_value_string("firewall", "@defaults[0]", "input", &input);
+	dmuci_get_option_value_string("firewall", "@defaults[0]", "output", &output);
+	dmuci_get_option_value_string("firewall", "@defaults[0]", "forward", &forward);
+
+	dmuci_add_section("firewall", "zone", &s);
+	dmuci_rename_section_by_section(s, s_name);
+	dmuci_set_value_by_section(s, "name", s_name);
+	dmuci_set_value_by_section(s, "input", input);
+	dmuci_set_value_by_section(s, "output", output);
+	dmuci_set_value_by_section(s, "forward", forward);
+
+	dmuci_add_list_value_by_section(s, "network", s_name);
+}
+
+
+static bool firewall_zone_exists(char *s_name)
+{
+	struct uci_section *s = NULL;
+
+	uci_foreach_option_eq("firewall", "zone", "name", s_name, s) {
+		return true;
+	}
+
+	return false;
+}
+
+static void create_portmapping_section(bool b)
+{
+	struct uci_section *s = NULL;
+
+	dmuci_add_section("firewall", "include", &s);
+	dmuci_rename_section_by_section(s, "portmapping");
+	dmuci_set_value_by_section(s, "enabled", b ? "0" : "1");
+	dmuci_set_value_by_section(s, "path", "/etc/firewall.portmapping");
+	dmuci_set_value_by_section(s, "reload", "1");
+}
+
+static void add_firewall_config_dup_list(struct list_head *dup_list, struct uci_section *config_section, struct uci_section *dmmap_section, bool is_dynamic_rule)
+{
+	struct rule_sec *rule_args;
+
+	rule_args = dmcalloc(1, sizeof(struct rule_sec));
+	list_add_tail(&rule_args->list, dup_list);
+
+	rule_args->config_section = config_section;
+	rule_args->dmmap_section = dmmap_section;
+	rule_args->is_dynamic_rule = is_dynamic_rule;
+}
+
+static void free_firewall_config_dup_list(struct list_head *dup_list)
+{
+	struct rule_sec *rule_args = NULL, *tmp = NULL;
+
+	list_for_each_entry_safe(rule_args, tmp, dup_list, list) {
+		list_del(&rule_args->list);
+		dmfree(rule_args);
+	}
+}
+
+void synchronize_firewall_sections_with_dmmap(char *package, char *section_type, char *dmmap_package, bool is_dynamic_rule, struct list_head *dup_list)
+{
+	struct uci_section *s, *stmp, *dmmap_sect;
+	char *v;
+
+	uci_foreach_sections(package, section_type, s) {
+		/*
+		 * create/update corresponding dmmap section that have same config_section link and using param_value_array
+		 */
+		if ((dmmap_sect = get_dup_section_in_dmmap(dmmap_package, section_type, section_name(s))) == NULL) {
+			dmuci_add_section_bbfdm(dmmap_package, section_type, &dmmap_sect);
+			dmuci_set_value_by_section_bbfdm(dmmap_sect, "section_name", section_name(s));
+		}
+
+		/*
+		 * Add system and dmmap sections to the list
+		 */
+		add_firewall_config_dup_list(dup_list, s, dmmap_sect, is_dynamic_rule);
+	}
+
+	/*
+	 * Delete unused dmmap sections
+	 */
+	uci_path_foreach_sections_safe(bbfdm, dmmap_package, section_type, stmp, s) {
+		dmuci_get_value_by_section_string(s, "section_name", &v);
+		if (get_origin_section_from_config(package, section_type, v) == NULL)
+			dmuci_delete_by_section(s, NULL, NULL);
+	}
+}
+
+static void fill_rules_info(struct uci_section *s)
+{
+	struct uci_context *fw_ctx = NULL;
+	struct uci_package *fw_pkg = NULL;
+	struct uci_element *fw_elmnt = NULL;
+	char rule_start_pos[8], rules_num[8];
+	unsigned int pos = 0, num = 0, idx = 0;
+
+	fw_ctx = uci_alloc_context();
+	if (!fw_ctx)
+		return;
+
+	uci_load(fw_ctx, "firewall", &fw_pkg);
+	if (!fw_pkg)
+		goto end;
+
+
+	uci_foreach_element(&fw_pkg->sections, fw_elmnt) {
+		struct uci_section *uci_sec = uci_to_section(fw_elmnt);
+
+		if (DM_STRCMP(uci_sec->type, "forwarding") == 0) {
+			pos = idx;
+			num++;
+		}
+
+		if (DM_STRCMP(uci_sec->type, "rule") == 0)
+			num++;
+
+		idx++;
+	}
+
+	uci_unload(fw_ctx, fw_pkg);
+
+	snprintf(rule_start_pos, sizeof(rule_start_pos), "%u", pos);
+	snprintf(rules_num, sizeof(rules_num), "%u", num);
+
+	dmuci_set_value_by_section(s, "rule_start_pos", rule_start_pos);
+	dmuci_set_value_by_section(s, "rules_num", rules_num);
+
+end:
+	uci_free_context(fw_ctx);
+}
+
+static void update_rule_order(const char *start_order, const char *stop_order, bool incr)
+{
+	struct uci_section *s = NULL;
+	char *order = NULL;
+
+	uci_path_foreach_sections(bbfdm, "dmmap_firewall", "forwarding", s) {
+
+		dmuci_get_value_by_section_string(s, "order", &order);
+
+		if ((DM_STRTOUL(order) >= DM_STRTOUL(start_order)) && (DM_STRTOUL(order) <= DM_STRTOUL(stop_order))) {
+			char buf[8] = {0};
+
+			snprintf(buf, sizeof(buf), "%lu", incr ? (DM_STRTOUL(order) + 1) : (DM_STRTOUL(order) - 1));
+			dmuci_set_value_by_section(s, "order", buf);
+		}
+	}
+
+	uci_path_foreach_sections(bbfdm, "dmmap_firewall", "rule", s) {
+
+		dmuci_get_value_by_section_string(s, "order", &order);
+
+		if ((DM_STRTOUL(order) >= DM_STRTOUL(start_order)) && (DM_STRTOUL(order) <= DM_STRTOUL(stop_order))) {
+			char buf[8] = {0};
+
+			snprintf(buf, sizeof(buf), "%lu", incr ? (DM_STRTOUL(order) + 1) : (DM_STRTOUL(order) - 1));
+			dmuci_set_value_by_section(s, "order", buf);
+		}
+	}
+}
+
+/*************************************************************
+* ADD & DEL OBJ
+*************************************************************/
+static int addService(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+	struct uci_section *s = NULL, *dmmap_s = NULL;
+	char s_name[16];
+
+	snprintf(s_name, sizeof(s_name), "service_%s", *instance);
+
+	dmuci_add_section("firewall", "service", &s);
+	dmuci_rename_section_by_section(s, s_name);
+	dmuci_set_value_by_section(s, "enable", "0");
+	dmuci_set_value_by_section(s, "interface", "");
+	dmuci_add_list_value_by_section(s, "dest_port", "-1");
+	dmuci_set_value_by_section(s, "family", "-1");
+	dmuci_add_list_value_by_section(s, "proto", "-1");
+	dmuci_set_value_by_section(s, "icmp_type", "-1");
+	dmuci_set_value_by_section(s, "target", "Accept");
+
+	dmuci_add_section_bbfdm("dmmap_firewall", "service", &dmmap_s);
+	dmuci_set_value_by_section(dmmap_s, "section_name", section_name(s));
+	dmuci_set_value_by_section(dmmap_s, "service_instance", *instance);
+
+	return 0;
+}
+
+static int delService(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+	struct uci_section *s = NULL, *stmp = NULL;
+
+	switch (del_action) {
+		case DEL_INST:
+			dmuci_delete_by_section(((struct dm_data *)data)->config_section, NULL, NULL);
+			dmuci_delete_by_section(((struct dm_data *)data)->dmmap_section, NULL, NULL);
+			break;
+		case DEL_ALL:
+			uci_foreach_sections_safe("firewall", "service", stmp, s) {
+				struct uci_section *dmmap_section = NULL;
+
+				get_dmmap_section_of_config_section("dmmap_firewall", "service", section_name(s), &dmmap_section);
+				dmuci_delete_by_section(dmmap_section, NULL, NULL);
+
+				dmuci_delete_by_section(s, NULL, NULL);
+			}
+			break;
+	}
+	return 0;
+}
+
+/*************************************************************
+* ENTRY METHOD
+**************************************************************/
+static int browseLevelInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+	struct uci_section *s = is_dmmap_section_exist("dmmap_firewall", "level");
+	if (!s) dmuci_add_section_bbfdm("dmmap_firewall", "level", &s);
+	handle_instance(dmctx, parent_node, s, "firewall_level_instance", "firewall_level_alias");
+	DM_LINK_INST_OBJ(dmctx, parent_node, s, "1");
+	return 0;
+}
+
+static int browseChainInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+	struct uci_section *s = NULL;
+	char *inst = NULL;
+
+	s = is_dmmap_section_exist_eq("dmmap_firewall", "chain", "creator", "Defaults");
+	if (!s) {
+		dmuci_add_section_bbfdm("dmmap_firewall", "chain", &s);
+		dmuci_set_value_by_section(s, "name", "Defaults Configuration");
+		dmuci_set_value_by_section(s, "creator", "Defaults");
+		fill_rules_info(s);
+	}
+
+	inst = handle_instance(dmctx, parent_node, s, "firewall_chain_instance", "firewall_chain_alias");
+	if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, inst) == DM_STOP)
+		return 0;
+
+	if (file_exists("/etc/config/upnpd")) {
+		s = is_dmmap_section_exist_eq("dmmap_firewall", "chain", "creator", "PortMapping");
+		if (!s) {
+			dmuci_add_section_bbfdm("dmmap_firewall", "chain", &s);
+			dmuci_set_value_by_section(s, "name", "UPnP Port Mapping (dynamic rules)");
+			dmuci_set_value_by_section(s, "creator", "PortMapping");
+		}
+
+		inst = handle_instance(dmctx, parent_node, s, "firewall_chain_instance", "firewall_chain_alias");
+		if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)s, inst) == DM_STOP)
+			return 0;
+	}
+
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.!UCI:firewall/rule/dmmap_firewall*/
+static int browseRuleInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+	struct uci_section *chain_args = (struct uci_section *)prev_data;
+	struct rule_sec *p = NULL;
+	LIST_HEAD(dup_list);
+	char *creator = NULL;
+	char *order = NULL;
+	char *inst = NULL;
+
+	dmuci_get_value_by_section_string(chain_args, "creator", &creator);
+
+	if (DM_STRCMP(creator, "Defaults") == 0) {
+
+		// Forwarding sections
+		synchronize_firewall_sections_with_dmmap("firewall", "forwarding", "dmmap_firewall", true, &dup_list);
+		list_for_each_entry(p, &dup_list, list) {
+
+			inst = handle_instance(dmctx, parent_node, p->dmmap_section, "firewall_chain_rule_instance", "firewall_chain_rule_alias");
+
+			dmuci_get_value_by_section_string(p->dmmap_section, "order", &order);
+			if (DM_STRLEN(order) == 0) {
+				// Fill order only first time
+				dmuci_set_value_by_section(p->dmmap_section, "order", inst);
+			}
+
+			p->creator = creator;
+
+			if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p, inst) == DM_STOP) {
+				free_firewall_config_dup_list(&dup_list);
+				return 0;
+			}
+		}
+		free_firewall_config_dup_list(&dup_list);
+
+		// Rule sections
+		synchronize_firewall_sections_with_dmmap("firewall", "rule", "dmmap_firewall", false, &dup_list);
+		list_for_each_entry(p, &dup_list, list) {
+
+			inst = handle_instance(dmctx, parent_node, p->dmmap_section, "firewall_chain_rule_instance", "firewall_chain_rule_alias");
+
+			dmuci_get_value_by_section_string(p->dmmap_section, "order", &order);
+			if (DM_STRLEN(order) == 0) {
+				// Fill order only first time
+				dmuci_set_value_by_section(p->dmmap_section, "order", inst);
+			}
+
+			p->creator = creator;
+
+			if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p, inst) == DM_STOP)
+				break;
+		}
+		free_firewall_config_dup_list(&dup_list);
+	} else if (DM_STRCMP(creator, "PortMapping") == 0) {
+#define UPNP_LEASE_FILE "/var/run/miniupnpd.leases"
+#define UPNP_RULE_ARG_NUMBER 6
+		char *pch = NULL, *spch = NULL;
+		char *upnp_lease_file = NULL;
+		char line[2048];
+		int i = 0, idx = 0;
+
+		dmuci_get_option_value_string("upnpd", "config", "upnp_lease_file", &upnp_lease_file);
+
+		upnp_lease_file = DM_STRLEN(upnp_lease_file) ? upnp_lease_file : UPNP_LEASE_FILE;
+
+		FILE *fp = fopen(upnp_lease_file, "r");
+		if (fp == NULL)
+			return 0;
+
+		while (fgets(line, sizeof(line), fp) != NULL) {
+			remove_new_line(line);
+
+			if (DM_STRLEN(line) == 0)
+				continue;
+
+			// This is an example of rule:
+			// TCP:45678:X.X.X.X:3000:1678270810:forward_test
+			// Proto:external_port:internal_ip:internal_port:expiry_date:description
+			// Number of arguments: 6
+			char **dynamic_rule = dmcalloc(UPNP_RULE_ARG_NUMBER, sizeof(char *));
+
+			for (idx = 0, pch = strtok_r(line, ":", &spch);
+				 idx < UPNP_RULE_ARG_NUMBER && pch != NULL;
+				 idx++, pch = strtok_r(NULL, ":", &spch)) {
+				dynamic_rule[idx] = dmstrdup(pch);
+			}
+
+			p = dmcalloc(1, sizeof(struct rule_sec));
+			list_add_tail(&p->list, &dup_list);
+
+			p->is_dynamic_rule = true;
+			p->dynamic_rule = dynamic_rule;
+			p->creator = creator;
+
+			inst = handle_instance_without_section(dmctx, parent_node, ++i);
+
+			if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p, inst) == DM_STOP)
+				break;
+		}
+
+		free_firewall_config_dup_list(&dup_list);
+		fclose(fp);
+	}
+
+	return 0;
+}
+
+/*#Device.Firewall.DMZ.{i}.!UCI:firewall/dmz/dmmap_dmz*/
+static int browseFirewallDMZInst(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("firewall", "dmz", "dmmap_dmz", &dup_list);
+	list_for_each_entry(curr_data, &dup_list, list) {
+
+		inst = handle_instance(dmctx, parent_node, curr_data->dmmap_section, "dmz_instance", "dmz_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 browseServiceInst(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("firewall", "service", "dmmap_firewall", &dup_list);
+	list_for_each_entry(curr_data, &dup_list, list) {
+		inst = handle_instance(dmctx, parent_node, curr_data->dmmap_section, "service_instance", "service_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 add_firewall_rule(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+	struct uci_section *chain_args = (struct uci_section *)data;
+	struct uci_section *s = NULL, *dmmap_firewall_rule = NULL;
+	char creation_date[32] = {0};
+	char s_name[16] = {0};
+	char buf[8] = {0};
+	char *creator = NULL;
+	char *rule_start_pos = NULL, *rules_num = NULL;
+	time_t now = time(NULL);
+
+	dmuci_get_value_by_section_string(chain_args, "creator", &creator);
+	if (DM_STRCMP(creator, "PortMapping") == 0) {
+		bbfdm_set_fault_message(ctx, "This is a dynamic 'Chain' instance which is created by 'Port Mapping', so it's not permitted to add a static 'Rule'.");
+		return FAULT_9003;
+	}
+
+	dmuci_get_value_by_section_string(chain_args, "rule_start_pos", &rule_start_pos);
+	dmuci_get_value_by_section_string(chain_args, "rules_num", &rules_num);
+
+	strftime(creation_date, sizeof(creation_date), "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
+
+	snprintf(s_name, sizeof(s_name), "rule_%s", *instance);
+
+	dmuci_add_section("firewall", "rule", &s);
+	dmuci_rename_section_by_section(s, s_name);
+	dmuci_set_value_by_section(s, "enabled", "0");
+	dmuci_set_value_by_section(s, "target", "DROP");
+	dmuci_set_value_by_section(s, "proto", "0");
+
+	// Update rule section order
+	snprintf(buf, sizeof(buf), "%lu", DM_STRTOUL(rule_start_pos) + DM_STRTOUL(rules_num));
+	dmuci_reoder_section_by_section(s, buf);
+
+	// Update rules number
+	snprintf(buf, sizeof(buf), "%lu", DM_STRTOUL(rules_num) + 1);
+	dmuci_set_value_by_section(chain_args, "rules_num", buf);
+
+	dmuci_add_section_bbfdm("dmmap_firewall", "rule", &dmmap_firewall_rule);
+	dmuci_set_value_by_section(dmmap_firewall_rule, "section_name", s_name);
+	dmuci_set_value_by_section(dmmap_firewall_rule, "creation_date", creation_date);
+	dmuci_set_value_by_section(dmmap_firewall_rule, "firewall_chain_rule_instance", *instance);
+	return 0;
+}
+
+static int delete_firewall_rule(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+	struct uci_section *s = NULL;
+	char *order = NULL, *rules_num = NULL;
+	char buf[8] = {0};
+
+	switch (del_action) {
+		case DEL_INST:
+			if (((struct rule_sec *)data)->is_dynamic_rule) {
+				bbfdm_set_fault_message(ctx, "This is a dynamic 'Rule' instance, therefore it's not permitted to delete it.");
+				return FAULT_9003;
+			}
+
+			s = get_dup_section_in_dmmap_opt("dmmap_firewall", "chain", "creator", "Defaults");
+			dmuci_get_value_by_section_string(s, "rules_num", &rules_num);
+
+			dmuci_get_value_by_section_string(((struct rule_sec *)data)->dmmap_section, "order", &order);
+			update_rule_order(order, rules_num, false);
+
+			// Update rules number
+			snprintf(buf, sizeof(buf), "%lu", DM_STRTOUL(rules_num) - 1);
+			dmuci_set_value_by_section(s, "rules_num", buf);
+
+			dmuci_delete_by_section(((struct rule_sec *)data)->config_section, NULL, NULL);
+			dmuci_delete_by_section(((struct rule_sec *)data)->dmmap_section, NULL, NULL);
+			break;
+		case DEL_ALL:
+			break;
+	}
+	return 0;
+}
+
+static int addObjFirewallDMZ(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+	struct uci_section *s = NULL, *dmmap = NULL;
+	char s_name[16] = {0};
+
+	snprintf(s_name, sizeof(s_name), "dmz_%s", *instance);
+
+	dmuci_add_section("firewall", "dmz", &s);
+	dmuci_rename_section_by_section(s, s_name);
+	dmuci_set_value_by_section(s, "enabled", "0");
+
+	dmuci_add_section_bbfdm("dmmap_dmz", "dmz", &dmmap);
+	dmuci_set_value_by_section(dmmap, "section_name", section_name(s));
+	dmuci_set_value_by_section(dmmap, "dmz_instance", *instance);
+	return 0;
+}
+
+static int delObjFirewallDMZ(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+	struct uci_section *s = NULL, *stmp = NULL;
+
+	switch (del_action) {
+		case DEL_INST:
+			dmuci_delete_by_section(((struct dm_data *)data)->config_section, NULL, NULL);
+			dmuci_delete_by_section(((struct dm_data *)data)->dmmap_section, NULL, NULL);
+			break;
+		case DEL_ALL:
+			uci_foreach_sections_safe("firewall", "dmz", stmp, s) {
+				struct uci_section *dmmap_section = NULL;
+
+				get_dmmap_section_of_config_section("dmmap_dmz", "dmz", section_name(s), &dmmap_section);
+				dmuci_delete_by_section(dmmap_section, NULL, NULL);
+
+				dmuci_delete_by_section(s, NULL, NULL);
+			}
+			break;
+	}
+	return 0;
+}
+
+/*************************************************************
+* GET & SET PARAM
+**************************************************************/
+static int get_firewall_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_option_value_fallback_def("firewall", "globals", "enabled", "1");
+	return 0;
+}
+
+static int get_firewall_config(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = "Advanced";
+    return 0;
+}
+
+static int get_firewall_advanced_level(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = "Device.Firewall.Level.1";
+    return 0;
+}
+
+static int get_firewall_level_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = "1";
+	return 0;
+}
+
+static int get_firewall_chain_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = "1";
+    return 0;
+}
+
+static int get_firewall_service_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	int cnt = get_number_of_entries(ctx, data, instance, browseServiceInst);
+	dmasprintf(value, "%d", cnt);
+	return 0;
+}
+
+static int get_level_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	return bbf_get_alias(ctx, (struct uci_section *)data, "firewall_level_alias", instance, value);
+}
+
+static int get_level_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string((struct uci_section *)data, "name", value);
+	return 0;
+}
+
+static int get_level_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+    dmuci_get_value_by_section_string((struct uci_section *)data, "description", value);
+    return 0;
+}
+
+static int get_level_chain(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = "Device.Firewall.Chain.1";
+    return 0;
+}
+
+static int get_level_port_mapping_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct uci_section *s = NULL;
+	bool portmapping_sec_exists = false;
+	char *enable = NULL;
+
+	uci_foreach_sections("firewall", "include", s) {
+		if (strncmp(section_name(s), "portmapping", 11) == 0) {
+			portmapping_sec_exists = true ;
+
+			dmuci_get_value_by_section_string(s, "enabled", &enable);
+			if (*enable == '0') {
+				*value = "1";
+				break;
+			}
+		}
+	}
+
+	if (portmapping_sec_exists == false)
+		*value = "1";
+
+	return 0;
+}
+
+static int get_level_default_log_policy(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct uci_section *s = NULL;
+	char *v;
+
+	uci_foreach_sections("firewall", "zone", s) {
+		dmuci_get_value_by_section_string(s, "log", &v);
+		if (*v == '1') {
+			*value = "1";
+			return 0;
+		}
+	}
+	*value = "0";
+	return 0;
+}
+
+static int get_level_default_policy(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	char *input = NULL;
+
+	dmuci_get_option_value_string("firewall", "@defaults[0]", "input", &input);
+	if (!input || *input == 0) {
+		*value = "Drop";
+		return 0;
+	}
+
+	*value = (*input == 'A') ? "Accept" : (*input == 'R') ? "Reject" : "Drop";
+	return 0;
+}
+
+static int get_chain_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = "1";
+	return 0;
+}
+
+static int get_chain_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	return bbf_get_alias(ctx, (struct uci_section *)data, "firewall_chain_alias", instance, value);
+}
+
+static int get_chain_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string((struct uci_section *)data, "name", value);
+	return 0;
+}
+
+static int get_chain_creator(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string((struct uci_section *)data, "creator", value);
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.RuleNumberOfEntries!UCI:firewall/rule/*/
+static int get_chain_rule_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	int cnt = get_number_of_entries(ctx, data, instance, browseRuleInst);
+	dmasprintf(value, "%d", cnt);
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.Enable!UCI:firewall/rule,@i-1/enabled*/
+static int get_rule_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = "1";
+	} else {
+		char *v;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "enabled", &v);
+		*value = (*v == 'n' || *v == '0' ) ? "0" : "1";
+	}
+
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.Status!UCI:firewall/rule,@i-1/enabled*/
+static int get_rule_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = "Enabled";
+	} else {
+		char *v;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "enabled", &v);
+		*value = (*v == 'n' || *v == '0') ? "Disabled" : "Enabled";
+	}
+
+	return 0;
+}
+
+static int get_rule_order(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (rule_args->is_dynamic_rule && DM_STRCMP(rule_args->creator, "Defaults") != 0) {
+		*value = instance;
+	} else {
+		dmuci_get_value_by_section_string(rule_args->dmmap_section, "order", value);
+	}
+
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.Alias!UCI:dmmap_firewall/rule,@i-1/firewall_chain_rule_alias*/
+static int get_rule_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (!rule_args->is_dynamic_rule)
+		dmuci_get_value_by_section_string(rule_args->dmmap_section, "firewall_chain_rule_alias", value);
+
+	if ((*value)[0] == '\0')
+		dmasprintf(value, "cpe-%s", instance);
+    return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.Description!UCI:firewall/rule,@i-1/name*/
+static int get_rule_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = (rule_args->dynamic_rule && rule_args->dynamic_rule[5]) ? rule_args->dynamic_rule[5] : "";
+	} else {
+		dmuci_get_value_by_section_string(rule_args->config_section, "name", value);
+	}
+
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.Target!UCI:firewall/rule,@i-1/target*/
+static int get_rule_target(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = "Accept";
+	} else {
+		char *target;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "target", &target);
+		if (DM_STRLEN(target) == 0) {
+			*value = "Accept";
+		} else {
+			if (strcasecmp(target, "Accept") == 0)
+				*value = "Accept";
+			else if (strcasecmp(target, "Reject") == 0)
+				*value = "Reject";
+			else if (strcasecmp(target, "Drop") == 0)
+				*value = "Drop";
+			else if (strcasecmp(target, "MARK") == 0)
+				*value = "Return";
+			else
+				*value = target;
+		}
+	}
+
+    return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.Log!UCI:firewall/rule,@i-1/log*/
+static int get_rule_log(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = "0";
+	} else {
+		char *v;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "log", &v);
+		*value = (*v == '1' ) ? "1" : "0";
+	}
+
+	return 0;
+}
+
+static int get_FirewallChainRule_CreationDate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = "0001-01-01T00:00:00Z";
+	} else {
+		*value = dmuci_get_value_by_section_fallback_def(rule_args->dmmap_section, "creation_date", "0001-01-01T00:00:00Z");
+	}
+
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.ExpiryDate!UCI:firewall/rule,@i-1/expiry*/
+static int get_FirewallChainRule_ExpiryDate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+	char *expiry_date = NULL;
+
+	if (rule_args->is_dynamic_rule) {
+		expiry_date = (rule_args->dynamic_rule && rule_args->dynamic_rule[4]) ? rule_args->dynamic_rule[4] : "";
+	} else {
+		dmuci_get_value_by_section_string(rule_args->config_section, "expiry", &expiry_date);
+	}
+
+	if (DM_STRLEN(expiry_date) != 0 && DM_STRTOL(expiry_date) > 0) {
+		char expiry[sizeof "AAAA-MM-JJTHH:MM:SSZ"];
+		time_t time_value = DM_STRTOL(expiry_date);
+
+		strftime(expiry, sizeof expiry, "%Y-%m-%dT%H:%M:%SZ", gmtime(&time_value));
+		*value = dmstrdup(expiry);
+	} else {
+		*value = "9999-12-31T23:59:59Z";
+	}
+
+	return 0;
+}
+
+static int set_FirewallChainRule_ExpiryDate(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+	char expiry_date[16];
+	struct tm tm;
+
+	switch (action)	{
+		case VALUECHECK:
+			if (bbfdm_validate_dateTime(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			strptime(value, "%Y-%m-%dT%H:%M:%SZ", &tm);
+			snprintf(expiry_date, sizeof(expiry_date), "%lld", (long long)timegm(&tm));
+			dmuci_set_value_by_section(rule_args->config_section, "expiry", expiry_date);
+			break;
+	}
+	return 0;
+}
+
+static int get_rule_source_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+	char *src = NULL;
+
+	if (rule_args->is_dynamic_rule) {
+		dmuci_get_option_value_string("upnpd", "config", "internal_iface", &src);
+	} else {
+		char *ifaceobj = NULL, src_iface[256] = {0};
+		struct uci_list *net_list = NULL;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "src", &src);
+		if (src == NULL || *src == '\0')
+			return 0;
+
+		if (DM_LSTRCMP(src, "*") == 0) {
+			dmuci_get_value_by_section_string(rule_args->dmmap_section, "src", &src);
+		} else {
+			struct uci_section *s = NULL;
+			char *zone_name = NULL;
+
+			uci_foreach_sections("firewall", "zone", s) {
+				dmuci_get_value_by_section_string(s, "name", &zone_name);
+				if (zone_name && DM_STRCMP(zone_name, src) == 0) {
+					dmuci_get_value_by_section_list(s, "network", &net_list);
+					break;
+				}
+			}
+		}
+
+		if (net_list != NULL) {
+			struct uci_element *e = NULL;
+			unsigned pos = 0;
+
+			src_iface[0] = 0;
+			uci_foreach_element(net_list, e) {
+				bbf_get_reference_param("Device.IP.Interface.", "Name", e->name, &ifaceobj);
+				if (DM_STRLEN(ifaceobj))
+					pos += snprintf(&src_iface[pos], sizeof(src_iface) - pos, "%s,", ifaceobj);
+			}
+
+			if (pos)
+				src_iface[pos - 1] = 0;
+
+			*value = dmstrdup(src_iface);
+			return 0;
+		}
+	}
+
+	bbf_get_reference_param("Device.IP.Interface.", "Name", src, value);
+	return 0;
+}
+
+static int get_rule_source_all_interfaces(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = "0";
+	} else {
+		char *v;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "src", &v);
+		*value = (*v == '*') ? "1" : "0";
+	}
+
+	return 0;
+}
+
+static int get_rule_dest_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+	char *dest = NULL;
+
+	if (rule_args->is_dynamic_rule) {
+		dmuci_get_option_value_string("upnpd", "config", "external_iface", &dest);
+	} else {
+		char *ifaceobj = NULL, dst_iface[256] = {0};
+		struct uci_list *net_list = NULL;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "dest", &dest);
+		if (dest == NULL || *dest == '\0')
+			return 0;
+
+		if (DM_LSTRCMP(dest, "*") == 0) {
+			dmuci_get_value_by_section_string(rule_args->dmmap_section, "dest", &dest);
+		} else {
+			struct uci_section *s = NULL;
+			char *zone_name = NULL;
+
+			uci_foreach_sections("firewall", "zone", s) {
+				dmuci_get_value_by_section_string(s, "name", &zone_name);
+				if (zone_name && DM_STRCMP(zone_name, dest) == 0) {
+					dmuci_get_value_by_section_list(s, "network", &net_list);
+					break;
+				}
+			}
+		}
+
+		if (net_list != NULL) {
+			struct uci_element *e = NULL;
+			unsigned pos = 0;
+
+			dst_iface[0] = 0;
+			uci_foreach_element(net_list, e) {
+				bbf_get_reference_param("Device.IP.Interface.", "Name", e->name, &ifaceobj);
+				if (DM_STRLEN(ifaceobj))
+					pos += snprintf(&dst_iface[pos], sizeof(dst_iface) - pos, "%s,", ifaceobj);
+			}
+
+			if (pos)
+				dst_iface[pos - 1] = 0;
+
+			*value = dmstrdup(dst_iface);
+			return 0;
+		}
+	}
+
+	bbf_get_reference_param("Device.IP.Interface.", "Name", dest, value);
+	return 0;
+}
+
+static int get_rule_dest_all_interfaces(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = "0";
+	} else {
+		char *v;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "dest", &v);
+		*value = (*v == '*') ? "1" : "0";
+	}
+
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.IPVersion!UCI:firewall/rule,@i-1/family*/
+static int get_rule_i_p_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = "-1";
+	} else {
+		char *ipversion;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "family", &ipversion);
+		if (strcasecmp(ipversion, "ipv4") == 0) {
+			*value = "4";
+		} else if (strcasecmp(ipversion, "ipv6") == 0) {
+			*value = "6";
+		} else {
+			*value = "-1";
+		}
+	}
+
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.DestIp!UCI:firewall/rule,@i-1/dest_ip*/
+static int get_rule_dest_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = (rule_args->dynamic_rule && rule_args->dynamic_rule[2]) ? rule_args->dynamic_rule[2] : "";
+	} else {
+		char buf[64], *pch, *destip;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "dest_ip", &destip);
+		DM_STRNCPY(buf, destip, sizeof(buf));
+		pch = DM_STRCHR(buf, '/');
+		if (pch) *pch = '\0';
+		*value = dmstrdup(buf);
+	}
+
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.DestMask!UCI:firewall/rule,@i-1/dest_ip*/
+static int get_rule_dest_mask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+	char *pch, *destip;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = "";
+		return 0;
+	}
+
+	dmuci_get_value_by_section_string(rule_args->config_section, "dest_ip", &destip);
+	if (*destip == '\0')
+		return 0;
+
+	pch = DM_STRCHR(destip, '/');
+	if (pch) {
+		*value = destip;
+	} else {
+		char *family;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "family", &family);
+		dmasprintf(value, "%s/%s", destip, DM_LSTRCMP(family, "ipv6") == 0 ? "128" : "32");
+	}
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.SourceIp!UCI:firewall/rule,@i-1/src_ip*/
+static int get_rule_source_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+	char buf[64], *pch, *srcip;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = "";
+		return 0;
+	}
+
+	dmuci_get_value_by_section_string(rule_args->config_section, "src_ip", &srcip);
+	DM_STRNCPY(buf, srcip, sizeof(buf));
+	pch = DM_STRCHR(buf, '/');
+	if (pch)
+		*pch = '\0';
+	*value = dmstrdup(buf);
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.SourceMask!UCI:firewall/rule,@i-1/src_ip*/
+static int get_rule_source_mask(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+	char *pch, *srcip;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = "";
+		return 0;
+	}
+
+	dmuci_get_value_by_section_string(rule_args->config_section, "src_ip", &srcip);
+	if (*srcip == '\0')
+		return 0;
+
+	pch = DM_STRCHR(srcip, '/');
+	if (pch) {
+		*value = srcip;
+	} else {
+		char *family;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "family", &family);
+		dmasprintf(value, "%s/%s", srcip, DM_LSTRCMP(family, "ipv6") == 0 ? "128" : "32");
+	}
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.Protocol!UCI:firewall/rule,@i-1/proto*/
+static int get_rule_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+	char *proto = NULL, buf[256], protocol[32], protocol_nbr[16];
+
+	if (rule_args->is_dynamic_rule) {
+		proto = (rule_args->dynamic_rule && rule_args->dynamic_rule[0]) ? rule_args->dynamic_rule[0] : "255";
+	} else {
+		dmuci_get_value_by_section_string(rule_args->config_section, "proto", &proto);
+
+		if (DM_STRLEN(proto) == 0 || strchr(proto, ' ')) {
+			*value = "255";
+			return 0;
+		}
+
+		if (*proto == '0' || strcmp(proto, "all") == 0) {
+			*value = "-1";
+			return 0;
+		}
+	}
+
+	if (isdigit_str(proto)) {
+		*value = proto;
+		return 0;
+	}
+
+	FILE *fp = fopen("/etc/protocols", "r");
+	if (fp == NULL)
+		return 0;
+
+	while (fgets (buf , 256 , fp) != NULL) {
+		sscanf(buf, "%31s %15s", protocol, protocol_nbr);
+		if (DM_STRCASECMP(protocol, proto) == 0) {
+			*value = dmstrdup(protocol_nbr);
+			fclose(fp);
+			return 0;
+		}
+	}
+	fclose(fp);
+
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.DestPort!UCI:firewall/rule,@i-1/dest_port*/
+static int get_rule_dest_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = (rule_args->dynamic_rule && rule_args->dynamic_rule[1]) ? rule_args->dynamic_rule[1] : "-1";
+	} else {
+		char *tmp, *v;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "dest_port", &v);
+		v = dmstrdup(v);
+		tmp = DM_STRCHR(v, ':');
+		if (tmp == NULL)
+			tmp = DM_STRCHR(v, '-');
+		if (tmp)
+			*tmp = '\0';
+		if (*v == '\0') {
+			*value = "-1";
+			return 0;
+		}
+		*value = v;
+	}
+
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.DestPortRangeMax!UCI:firewall/rule,@i-1/dest_port*/
+static int get_rule_dest_port_range_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+	char *tmp, *v;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = "-1";
+		return 0;
+	}
+
+	dmuci_get_value_by_section_string(rule_args->config_section, "dest_port", &v);
+	tmp = DM_STRCHR(v, ':');
+	if (tmp == NULL)
+		tmp = DM_STRCHR(v, '-');
+	*value = (tmp) ? tmp+1 : "-1";
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.SourcePort!UCI:firewall/rule,@i-1/src_port*/
+static int get_rule_source_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = (rule_args->dynamic_rule && rule_args->dynamic_rule[3]) ? rule_args->dynamic_rule[3] : "-1";
+	} else {
+		char *tmp, *v;
+
+		dmuci_get_value_by_section_string(rule_args->config_section, "src_port", &v);
+		v = dmstrdup(v);
+		tmp = DM_STRCHR(v, ':');
+		if (tmp == NULL)
+			tmp = DM_STRCHR(v, '-');
+		if (tmp)
+			*tmp = '\0';
+		if (*v == '\0') {
+			*value = "-1";
+			return 0;
+		}
+		*value = v;
+	}
+
+	return 0;
+}
+
+/*#Device.Firewall.Chain.{i}.Rule.{i}.SourcePortRangeMax!UCI:firewall/rule,@i-1/src_port*/
+static int get_rule_source_port_range_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct rule_sec *rule_args = (struct rule_sec *)data;
+	char *tmp, *v;
+
+	if (rule_args->is_dynamic_rule) {
+		*value = "-1";
+		return 0;
+	}
+
+	dmuci_get_value_by_section_string(rule_args->config_section, "src_port", &v);
+	tmp = DM_STRCHR(v, ':');
+	if (tmp == NULL)
+		tmp = DM_STRCHR(v, '-');
+	*value = (tmp) ? tmp+1 : "-1";
+	return 0;
+}
+
+static int set_firewall_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	bool b;
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			string_to_bool(value, &b);
+			dmuci_set_value("firewall", "globals", "enabled", b ? "1" : "0");
+			break;
+	}
+        return 0;
+}
+
+static int set_firewall_config(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *config[] = {"High", "Low", "Off", "Advanced", NULL};
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, -1, config, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (strcasecmp(value, "Advanced") != 0) {
+				bbfdm_set_fault_message(ctx, "The current Firewall implementation supports only 'Advanced' config.");
+				return FAULT_9007;
+			}
+			break;
+	}
+        return 0;
+}
+
+static int set_firewall_advanced_level(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:
+			if (strcasecmp(value, "Device.Firewall.Level.1.") != 0) {
+				bbfdm_set_fault_message(ctx, "The current Firewall implementation supports only one Level. So the value should be 'Device.Firewall.Level.1'.");
+				return FAULT_9007;
+			}
+			break;
+	}
+        return 0;
+}
+
+static int set_level_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	return bbf_set_alias(ctx, (struct uci_section *)data, "firewall_level_alias", instance, value);
+}
+
+static int set_level_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 64, NULL, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section_bbfdm((struct uci_section *)data, "name", value);
+			break;
+	}
+        return 0;
+}
+
+static int set_level_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section_bbfdm((struct uci_section *)data, "description", value);
+			break;
+	}
+        return 0;
+}
+
+static int set_level_port_mapping_enabled(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	bool b, portmapping_sec_exists = false;
+	struct uci_section *s = NULL;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			string_to_bool(value, &b);
+			uci_foreach_sections("firewall", "include", s) {
+				if (strncmp(section_name(s), "portmapping", 11) == 0) {
+					portmapping_sec_exists = true;
+					break;
+				}
+			}
+
+			if (portmapping_sec_exists == true) {
+				dmuci_set_value_by_section(s, "enabled", b ? "0" : "1");
+			} else {
+				create_portmapping_section(b);
+			}
+			break;
+	}
+	return 0;
+}
+
+static int set_level_default_policy(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *DefaultPolicy[] = {"Drop", "Accept", "Reject", NULL};
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, -1, DefaultPolicy, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (DM_LSTRCMP(value, "Drop") == 0) {
+				dmuci_set_value("firewall", "@defaults[0]", "input", "DROP");
+				dmuci_set_value("firewall", "@defaults[0]", "output", "DROP");
+			} else if (DM_LSTRCMP(value, "Accept") == 0) {
+				dmuci_set_value("firewall", "@defaults[0]", "input", "ACCEPT");
+				dmuci_set_value("firewall", "@defaults[0]", "output", "ACCEPT");
+			} else {
+				dmuci_set_value("firewall", "@defaults[0]", "input", "REJECT");
+				dmuci_set_value("firewall", "@defaults[0]", "output", "REJECT");
+			}
+			break;
+	}
+	return 0;
+}
+
+static int set_level_default_log_policy(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	bool b;
+	struct uci_section *s = NULL;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			string_to_bool(value, &b);
+			if (b) {
+				uci_foreach_sections("firewall", "zone", s) {
+					dmuci_set_value_by_section(s, "log", "1");
+				}
+			} else {
+				uci_foreach_sections("firewall", "zone", s) {
+					dmuci_set_value_by_section(s, "log", "");
+				}
+			}
+			break;
+	}
+	return 0;
+}
+
+static int set_chain_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			break;
+	}
+	return 0;
+}
+
+static int set_chain_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	return bbf_set_alias(ctx, (struct uci_section *)data, "firewall_chain_alias", instance, value);
+}
+
+static int set_chain_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 64, NULL, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section_bbfdm((struct uci_section *)data, "name", value);
+			break;
+	}
+        return 0;
+}
+
+static int set_rule_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	bool b;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			string_to_bool(value, &b);
+			dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "enabled", b ? "1" : "0");
+			break;
+	}
+	return 0;
+}
+
+static int set_rule_order(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	struct uci_section *s = NULL;
+	char *rule_start_pos = NULL;
+	char *rules_num = NULL;
+	char *curr_order = NULL;
+	char buf[8] = {0};
+
+	s = get_dup_section_in_dmmap_opt("dmmap_firewall", "chain", "creator", "Defaults");
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"1",NULL}}, 1))
+				return FAULT_9007;
+
+			dmuci_get_value_by_section_string(s, "rules_num", &rules_num);
+			if (DM_STRTOUL(value) > DM_STRTOUL(rules_num)) {
+				bbfdm_set_fault_message(ctx, "The order value '%s' should be lower than the greater order value '%s'.", value, rules_num);
+				return FAULT_9007;
+			}
+
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			dmuci_get_value_by_section_string(((struct rule_sec *)data)->dmmap_section, "order", &curr_order);
+			if (DM_STRTOUL(curr_order) > DM_STRTOUL(value))
+				update_rule_order(value, curr_order, true);
+			else
+				update_rule_order(curr_order, value, false);
+
+			dmuci_get_value_by_section_string(s, "rule_start_pos", &rule_start_pos);
+			snprintf(buf, sizeof(buf), "%lu", DM_STRTOUL(rule_start_pos) + DM_STRTOUL(value) - 1);
+
+			dmuci_reoder_section_by_section(((struct rule_sec *)data)->config_section, buf);
+			dmuci_set_value_by_section(((struct rule_sec *)data)->dmmap_section, "order", value);
+			break;
+	}
+	return 0;
+}
+
+static int set_rule_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	return bbf_set_alias(ctx, ((struct rule_sec *)data)->dmmap_section, "firewall_chain_rule_alias", instance, value);
+}
+
+static int set_rule_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "name", value);
+			break;
+	}
+	return 0;
+}
+
+static int set_rule_target(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *Target[] = {"Drop", "Accept", "Reject", "Return", "TargetChain", NULL};
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, -1, Target, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			if (strcasecmp(value, "Accept") == 0)
+				dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "target", "ACCEPT");
+			else if (strcasecmp(value, "Reject") == 0)
+				dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "target", "REJECT");
+			else if (strcasecmp(value, "Drop") == 0)
+				dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "target", "DROP");
+			else if (strcasecmp(value, "Return") == 0)
+				dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "target", "MARK");
+			break;
+	}
+        return 0;
+}
+
+static int set_rule_log(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	bool b;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			string_to_bool(value, &b);
+			dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "log", b ? "1" : "");
+			break;
+	}
+        return 0;
+}
+
+static int set_rule_interface(struct dmctx *ctx, void *data, char *type, char *value, int action)
+{
+	char *allowed_objects[] = {"Device.IP.Interface.", NULL};
+	struct dm_reference reference = {0};
+	char *option = NULL;
+
+	bbf_get_reference_args(value, &reference);
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, reference.path, -1, 256, NULL, NULL))
+				return FAULT_9007;
+
+			if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
+				return FAULT_9007;
+
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			dmuci_get_value_by_section_string(((struct rule_sec *)data)->config_section, type, &option);
+
+			if (DM_STRLEN(reference.path) == 0) {
+				dmuci_set_value_by_section((option && DM_LSTRCMP(option, "*") == 0) ? ((struct rule_sec *)data)->dmmap_section : ((struct rule_sec *)data)->config_section, type, "");
+			} else {
+				if (DM_STRLEN(reference.value)) {
+
+					// check if firewall zone exists
+					if (!firewall_zone_exists(reference.value))
+						firewall__create_zone_section(reference.value);
+
+					dmuci_set_value_by_section((option && DM_LSTRCMP(option, "*") == 0) ? ((struct rule_sec *)data)->dmmap_section : ((struct rule_sec *)data)->config_section, type, reference.value);
+				}
+			}
+			break;
+	}
+	return 0;
+}
+
+static int set_rule_source_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	return set_rule_interface(ctx, data, "src", value, action);
+}
+
+static int set_rule_source_all_interfaces(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *src;
+	bool b;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			string_to_bool(value, &b);
+			if (b) {
+				// Get the current 'src' option
+				dmuci_get_value_by_section_string(((struct rule_sec *)data)->config_section, "src", &src);
+
+				// Save 'src' option in the associated dmmap rule section
+				dmuci_set_value_by_section(((struct rule_sec *)data)->dmmap_section, "src", src);
+
+				// Set the current 'src' option
+				dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "src", "*");
+			} else {
+				// Get 'src' option from the associated dmmap rule section
+				dmuci_get_value_by_section_string(((struct rule_sec *)data)->dmmap_section, "src", &src);
+
+				// Set the current 'src' option
+				dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "src", src);
+			}
+			break;
+	}
+	return 0;
+}
+
+static int set_rule_dest_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	return set_rule_interface(ctx, data, "dest", value, action);
+}
+
+static int set_rule_dest_all_interfaces(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *dest;
+	bool b;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			string_to_bool(value, &b);
+			if (b) {
+				// Get the current 'dest' option
+				dmuci_get_value_by_section_string(((struct rule_sec *)data)->config_section, "dest", &dest);
+
+				// Save 'dest' option in the associated dmmap rule section
+				dmuci_set_value_by_section(((struct rule_sec *)data)->dmmap_section, "dest", dest);
+
+				// Set the current 'dest' option
+				dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "dest", "*");
+			} else {
+				// Get 'dest' option from the associated dmmap rule section
+				dmuci_get_value_by_section_string(((struct rule_sec *)data)->dmmap_section, "dest", &dest);
+
+				// Set the current 'dest' option
+				dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "dest", dest);
+			}
+			break;
+	}
+	return 0;
+}
+
+static int set_rule_i_p_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_int(ctx, value, RANGE_ARGS{{"-1","15"}}, 1))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			if (DM_LSTRCMP(value, "4") == 0)
+				dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "family", "ipv4");
+			else if (DM_LSTRCMP(value, "6") == 0)
+				dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "family", "ipv6");
+			else if (DM_LSTRCMP(value, "-1") == 0)
+				dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "family", "");
+			break;
+	}
+        return 0;
+}
+
+static int set_rule_dest_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char buf[64], new[64], *pch, *destip;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 45, NULL, IPAddress))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			dmuci_get_value_by_section_string(((struct rule_sec *)data)->config_section, "dest_ip", &destip);
+			DM_STRNCPY(buf, destip, sizeof(buf));
+			pch = DM_STRCHR(buf, '/');
+			if (pch)
+				snprintf(new, sizeof(new), "%s%s", value, pch);
+			else
+				DM_STRNCPY(new, value, sizeof(new));
+			dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "dest_ip", new);
+			break;
+	}
+    return 0;
+}
+
+static int set_rule_dest_mask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char new[64], *pch, *destip;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 49, NULL, IPPrefix))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			dmuci_get_value_by_section_string(((struct rule_sec *)data)->config_section, "dest_ip", &destip);
+			pch = DM_STRCHR(destip, '/');
+			if (pch)
+				*pch = '\0';
+
+			pch = DM_STRCHR(value, '/');
+			if (pch == NULL)
+				return 0;
+
+			snprintf(new, sizeof(new), "%s%s", destip, pch);
+			dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "dest_ip", new);
+			break;
+	}
+        return 0;
+}
+
+static int set_rule_source_ip(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char buf[64], new[64], *pch, *srcip;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 45, NULL, IPAddress))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			dmuci_get_value_by_section_string(((struct rule_sec *)data)->config_section, "src_ip", &srcip);
+			DM_STRNCPY(buf, srcip, sizeof(buf));
+			pch = DM_STRCHR(buf, '/');
+			if (pch)
+				snprintf(new, sizeof(new), "%s%s", value, pch);
+			else
+				DM_STRNCPY(new, value, sizeof(new));
+			dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "src_ip", new);
+			break;
+	}
+        return 0;
+}
+
+static int set_rule_source_mask(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char new[64], *pch, *srcip;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 49, NULL, IPPrefix))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			dmuci_get_value_by_section_string(((struct rule_sec *)data)->config_section, "src_ip", &srcip);
+			pch = DM_STRCHR(srcip, '/');
+			if (pch)
+				*pch = '\0';
+
+			pch = DM_STRCHR(value, '/');
+			if (pch == NULL)
+				return 0;
+
+			snprintf(new, sizeof(new), "%s%s", srcip, pch);
+			dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "src_ip", new);
+			break;
+	}
+        return 0;
+}
+
+static int set_rule_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_int(ctx, value, RANGE_ARGS{{"-1","255"}}, 1))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "proto", (*value == '-') ? "0" : value);
+			break;
+	}
+        return 0;
+}
+
+static int set_rule_dest_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char buffer[64], *v, *tmp = NULL;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_int(ctx, value, RANGE_ARGS{{"-1","65535"}}, 1))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			if (*value == '-')
+				value = "";
+			dmuci_get_value_by_section_string(((struct rule_sec *)data)->config_section, "dest_port", &v);
+			tmp = DM_STRCHR(v, ':');
+			if (tmp == NULL)
+				tmp = DM_STRCHR(v, '-');
+			if (tmp == NULL)
+				snprintf(buffer, sizeof(buffer), "%s", value);
+			else
+				snprintf(buffer, sizeof(buffer), "%s%s", value, tmp);
+			dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "dest_port", buffer);
+			break;
+	}
+        return 0;
+}
+
+static int set_rule_dest_port_range_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *v, *tmp, *buf, buffer[64];
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_int(ctx, value, RANGE_ARGS{{"-1","65535"}}, 1))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			dmuci_get_value_by_section_string(((struct rule_sec *)data)->config_section, "dest_port", &v);
+			buf = dmstrdup(v);
+			v = buf;
+			tmp = DM_STRCHR(buf, ':');
+			if (tmp == NULL)
+				tmp = DM_STRCHR(v, '-');
+			if (tmp)
+				*tmp = '\0';
+			if (*value == '-')
+				snprintf(buffer, sizeof(buffer), "%s", v);
+			else
+				snprintf(buffer, sizeof(buffer), "%s:%s", v, value);
+			dmfree(buf);
+			dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "dest_port", buffer);
+			break;
+	}
+	return 0;
+}
+
+static int set_rule_source_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char buffer[64], *v, *tmp = NULL;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_int(ctx, value, RANGE_ARGS{{"-1","65535"}}, 1))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			if (*value == '-')
+				value = "";
+			dmuci_get_value_by_section_string(((struct rule_sec *)data)->config_section, "src_port", &v);
+			tmp = DM_STRCHR(v, ':');
+			if (tmp == NULL)
+				tmp = DM_STRCHR(v, '-');
+			if (tmp == NULL)
+				snprintf(buffer, sizeof(buffer), "%s", value);
+			else
+				snprintf(buffer, sizeof(buffer), "%s%s", value, tmp);
+			dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "src_port", buffer);
+			break;
+	}
+    return 0;
+}
+
+static int set_rule_source_port_range_max(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *v, *tmp, *buf, buffer[64];
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_int(ctx, value, RANGE_ARGS{{"-1","65535"}}, 1))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (((struct rule_sec *)data)->is_dynamic_rule)
+				break;
+
+			dmuci_get_value_by_section_string(((struct rule_sec *)data)->config_section, "src_port", &v);
+			buf = dmstrdup(v);
+			v = buf;
+			tmp = DM_STRCHR(buf, ':');
+			if (tmp == NULL)
+				tmp = DM_STRCHR(buf, '-');
+			if (tmp)
+				*tmp = '\0';
+			if (*value == '-')
+				snprintf(buffer, sizeof(buffer), "%s", v);
+			else
+				snprintf(buffer, sizeof(buffer), "%s:%s", v, value);
+			dmfree(buf);
+			dmuci_set_value_by_section(((struct rule_sec *)data)->config_section, "src_port", buffer);
+			break;
+	}
+	return 0;
+}
+
+static int get_firewall_dmz_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	int cnt = get_number_of_entries(ctx, data, instance, browseFirewallDMZInst);
+	dmasprintf(value, "%d", cnt);
+	return 0;
+}
+
+/*#Device.Firewall.DMZ.{i}.Alias!UCI:dmmap_dmz/DMZ,@i-1/alias*/
+static int get_FirewallDMZ_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	return bbf_get_alias(ctx, ((struct dm_data *)data)->dmmap_section, "dmz_alias", instance, value);
+}
+
+static int set_FirewallDMZ_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, "dmz_alias", instance, value);
+}
+
+/*#Device.Firewall.DMZ.{i}.Enable!UCI:firewall/dmz,@i-1/enabled*/
+static int get_FirewallDMZ_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "enabled", "0");
+	return 0;
+}
+
+static int set_FirewallDMZ_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	bool b = 0;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			string_to_bool(value, &b);
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "enabled", b ? "1" : "0");
+			break;
+	}
+	return 0;
+}
+
+/*#Device.Firewall.DMZ.{i}.Status!UCI:firewall/dmz,@i-1/status*/
+static int get_FirewallDMZ_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct dm_data *dmz_args = (struct dm_data *)data;
+	char *v, *destip, *interface;
+
+	dmuci_get_value_by_section_string(dmz_args->config_section, "interface", &interface);
+	dmuci_get_value_by_section_string(dmz_args->config_section, "dest_ip", &destip);
+	if (DM_STRLEN(destip) == 0 || DM_STRLEN(interface) == 0) {
+		*value = "Error_Misconfigured";
+		return 0;
+	}
+
+	dmuci_get_value_by_section_string(dmz_args->config_section, "enabled", &v);
+	*value = (dmuci_string_to_boolean(v)) ? "Enabled" : "Disabled";
+	return 0;
+}
+
+/*#Device.Firewall.DMZ.{i}.Origin!UCI:firewall/dmz,@i-1/origin*/
+static int get_FirewallDMZ_Origin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "origin", "Controller");
+	return 0;
+}
+
+static int set_FirewallDMZ_Origin(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *Origin[] = {"User", "System", "Controller", NULL};
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, -1, Origin, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "origin", value);
+			break;
+	}
+	return 0;
+}
+
+/*#Device.Firewall.DMZ.{i}.Description!UCI:firewall/dmz,@i-1/description*/
+static int get_FirewallDMZ_Description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "description", value);
+	return 0;
+}
+
+static int set_FirewallDMZ_Description(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "description", value);
+			break;
+	}
+	return 0;
+}
+
+/*#Device.Firewall.DMZ.{i}.Interface!UCI:firewall/dmz,@i-1/interface*/
+static int get_FirewallDMZ_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	char *interf = NULL;
+
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "interface", &interf);
+
+	bbf_get_reference_param("Device.IP.Interface.", "Name", interf, value);
+	return 0;
+}
+
+static int set_FirewallDMZ_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *allowed_objects[] = {"Device.IP.Interface.", NULL};
+	struct dm_reference reference = {0};
+
+	bbf_get_reference_args(value, &reference);
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL))
+				return FAULT_9007;
+
+			if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
+				return FAULT_9007;
+
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "interface", reference.value);
+			break;
+	}
+	return 0;
+}
+
+/*#Device.Firewall.DMZ.{i}.DestIP!UCI:firewall/dmz,@i-1/dest_ip*/
+static int get_FirewallDMZ_DestIP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "dest_ip", value);
+	return 0;
+}
+
+static int set_FirewallDMZ_DestIP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 15, NULL, IPv4Address))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "dest_ip", value);
+			break;
+	}
+	return 0;
+}
+
+/*#Device.Firewall.DMZ.{i}.SourcePrefix!UCI:firewall/dmz,@i-1/source_prefix*/
+static int get_FirewallDMZ_SourcePrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "source_prefix", value);
+	return 0;
+}
+
+static int set_FirewallDMZ_SourcePrefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 18, NULL, IPv4Prefix))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "source_prefix", value);
+			break;
+	}
+	return 0;
+}
+
+static int get_service_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	return bbf_get_alias(ctx, ((struct dm_data *)data)->dmmap_section, "service_alias", instance, value);
+}
+
+static int set_service_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, "service_alias", instance, value);
+}
+
+static int get_service_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "enable", "0");
+	return 0;
+}
+
+static int set_service_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	bool b;
+
+	switch (action)	{
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			string_to_bool(value, &b);
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "enable", b ? "1" : "0");
+			break;
+	}
+
+	return 0;
+}
+
+static int get_service_intf(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	char *intf = NULL;
+
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "interface", &intf);
+
+	if (intf == NULL || *intf == '\0')
+		return 0;
+
+	bbf_get_reference_param("Device.IP.Interface.", "Name", intf, value);
+
+	return 0;
+}
+
+static int set_service_intf(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *allowed_objects[] = {"Device.IP.Interface.", NULL};
+	struct dm_reference reference = {0};
+
+	bbf_get_reference_args(value, &reference);
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL))
+				return FAULT_9007;
+
+			if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
+				return FAULT_9007;
+
+			break;
+		case VALUESET:
+			if (DM_STRLEN(reference.value)) {
+				// check if firewall zone exists
+				if (!firewall_zone_exists(reference.value))
+					firewall__create_zone_section(reference.value);
+
+				dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "interface", reference.value);
+			}
+			break;
+	}
+
+	return 0;
+}
+
+static int get_service_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct uci_list *val = NULL;
+	dmuci_get_value_by_section_list(((struct dm_data *)data)->config_section, "dest_port", &val);
+	*value = dmuci_list_to_string(val, ",");
+	return 0;
+}
+
+static int set_service_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	size_t length, i;
+	char **arr;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_int_list(ctx, value, 1, 65537, 0, RANGE_ARGS{{"-1", "65535"}},1))
+				return FAULT_9007;
+
+			break;
+		case VALUESET:
+			arr = strsplit(value, ",", &length);
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "dest_port", "");
+			for (i = 0; i < length; i++)
+				dmuci_add_list_value_by_section(((struct dm_data *)data)->config_section, "dest_port", arr[i]);
+			break;
+	}
+
+	return 0;
+}
+
+static int get_service_ipver(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	char *ipversion;
+
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "family", &ipversion);
+	if (strcasecmp(ipversion, "ipv4") == 0) {
+		*value = "4";
+	} else if (strcasecmp(ipversion, "ipv6") == 0) {
+		*value = "6";
+	} else {
+		*value = "-1";
+	}
+
+	return 0;
+}
+
+static int set_service_ipver(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_int(ctx, value, RANGE_ARGS{{"-1","15"}}, 1))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (DM_LSTRCMP(value, "4") == 0)
+				dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "family", "ipv4");
+			else if (DM_LSTRCMP(value, "6") == 0)
+				dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "family", "ipv6");
+			else if (DM_LSTRCMP(value, "-1") == 0)
+				dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "family", "");
+			break;
+	}
+        return 0;
+}
+
+static int get_service_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct uci_list *val = NULL;
+	dmuci_get_value_by_section_list(((struct dm_data *)data)->config_section, "proto", &val);
+	*value = dmuci_list_to_string(val, ",");
+	return 0;
+}
+
+static int set_service_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	size_t length, i;
+	char **arr;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_int_list(ctx, value, 1, 257, 0, RANGE_ARGS{{"-1", "255"}},1))
+				return FAULT_9007;
+
+			break;
+		case VALUESET:
+			arr = strsplit(value, ",", &length);
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "proto", "");
+			for (i = 0; i < length; i++)
+				dmuci_add_list_value_by_section(((struct dm_data *)data)->config_section, "proto", arr[i]);
+			break;
+	}
+
+	return 0;
+}
+
+static int get_service_icmp(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "icmp_type", value);
+	return 0;
+}
+
+static int set_service_icmp(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_int(ctx, value, RANGE_ARGS{{"-1","255"}}, 1))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "icmp_type", value);
+			break;
+	}
+        return 0;
+}
+
+static int get_service_src_prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct uci_list *val = NULL;
+	dmuci_get_value_by_section_list(((struct dm_data *)data)->config_section, "src_prefix", &val);
+	*value = dmuci_list_to_string(val, ",");
+	return 0;
+}
+
+static int set_service_src_prefix(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	size_t length, i;
+	char **arr = NULL;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string_list(ctx, value, -1, -1, -1, -1, 49, NULL, IPPrefix))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			arr = strsplit(value, ",", &length);
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "src_prefix", "");
+			for (i = 0; i < length; i++)
+				dmuci_add_list_value_by_section(((struct dm_data *)data)->config_section, "src_prefix", arr[i]);
+			break;
+	}
+        return 0;
+}
+
+static int get_service_action(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "target", value);
+	return 0;
+}
+
+static int set_service_action(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *allowed_params[] = {"Drop", "Accept", "Reject", NULL};
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, -1, allowed_params, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "target", value);
+			break;
+	}
+        return 0;
+}
+
+static int get_service_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	char *enable = NULL, *intf = NULL;
+
+	get_service_enable(refparam, ctx, data, instance, &enable);
+
+	if (DM_STRCMP(enable, "1") != 0) {
+		*value = "Disabled";
+		return 0;
+	}
+
+	get_service_intf(refparam, ctx, data, instance, &intf);
+
+	if (DM_STRLEN(intf) == 0) {
+		*value = "Error_Misconfigured";
+		return 0;
+	}
+
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "status", "Enabled");
+
+	return 0;
+}
+
+/**********************************************************************************************************************************
+*                                            OBJ & PARAM DEFINITION
+***********************************************************************************************************************************/
+/* *** Device.Firewall. *** */
+DMOBJ tFirewallObj[] = {
+/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
+{"Level", &DMREAD, NULL, NULL, NULL, browseLevelInst, NULL, NULL, NULL, tFirewallLevelParams, NULL, BBFDM_BOTH, NULL},
+{"Chain", &DMREAD, NULL, NULL, NULL, browseChainInst, NULL, NULL, tFirewallChainObj, tFirewallChainParams, NULL, BBFDM_BOTH, NULL},
+{"DMZ", &DMWRITE, addObjFirewallDMZ, delObjFirewallDMZ, NULL, browseFirewallDMZInst, NULL, NULL, NULL, tFirewallDMZParams, NULL, BBFDM_BOTH, NULL},
+{"Service", &DMWRITE, addService, delService, NULL, browseServiceInst, NULL, NULL, NULL, tFirewallServiceParams, NULL, BBFDM_BOTH, NULL},
+{0}
+};
+
+DMLEAF tFirewallParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
+{"Enable", &DMWRITE, DMT_BOOL, get_firewall_enable, set_firewall_enable, BBFDM_BOTH},
+{"Config", &DMWRITE, DMT_STRING, get_firewall_config, set_firewall_config, BBFDM_BOTH},
+{"AdvancedLevel", &DMWRITE, DMT_STRING, get_firewall_advanced_level, set_firewall_advanced_level, BBFDM_BOTH},
+{"LevelNumberOfEntries", &DMREAD, DMT_UNINT, get_firewall_level_number_of_entries, NULL, BBFDM_BOTH},
+{"ChainNumberOfEntries", &DMREAD, DMT_UNINT, get_firewall_chain_number_of_entries, NULL, BBFDM_BOTH},
+{"DMZNumberOfEntries", &DMREAD, DMT_UNINT, get_firewall_dmz_number_of_entries, NULL, BBFDM_BOTH},
+{"ServiceNumberOfEntries", &DMREAD, DMT_UNINT, get_firewall_service_number_of_entries, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Firewall.Level.{i}. *** */
+DMLEAF tFirewallLevelParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
+{"Alias", &DMWRITE, DMT_STRING, get_level_alias, set_level_alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
+{"Name", &DMWRITE, DMT_STRING, get_level_name, set_level_name, BBFDM_BOTH, DM_FLAG_UNIQUE},
+{"Description", &DMWRITE, DMT_STRING, get_level_description, set_level_description, BBFDM_BOTH},
+{"Chain", &DMREAD, DMT_STRING, get_level_chain, NULL, BBFDM_BOTH},
+{"PortMappingEnabled", &DMWRITE, DMT_BOOL, get_level_port_mapping_enabled, set_level_port_mapping_enabled, BBFDM_BOTH},
+{"DefaultPolicy", &DMWRITE, DMT_STRING, get_level_default_policy, set_level_default_policy, BBFDM_BOTH},
+{"DefaultLogPolicy", &DMWRITE, DMT_BOOL, get_level_default_log_policy, set_level_default_log_policy, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Firewall.Chain.{i}. *** */
+DMOBJ tFirewallChainObj[] = {
+/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
+{"Rule", &DMWRITE, add_firewall_rule, delete_firewall_rule, NULL, browseRuleInst, NULL, NULL, NULL, tFirewallChainRuleParams, NULL, BBFDM_BOTH, NULL},
+{0}
+};
+
+DMLEAF tFirewallChainParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
+{"Enable", &DMWRITE, DMT_BOOL, get_chain_enable, set_chain_enable, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_chain_alias, set_chain_alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
+{"Name", &DMWRITE, DMT_STRING, get_chain_name, set_chain_name, BBFDM_BOTH, DM_FLAG_UNIQUE},
+{"Creator", &DMREAD, DMT_STRING, get_chain_creator, NULL, BBFDM_BOTH},
+{"RuleNumberOfEntries", &DMREAD, DMT_UNINT, get_chain_rule_number_of_entries, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Firewall.Chain.{i}.Rule.{i}. *** */
+DMLEAF tFirewallChainRuleParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
+{"Enable", &DMWRITE, DMT_BOOL, get_rule_enable, set_rule_enable, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_rule_status, NULL, BBFDM_BOTH},
+{"Order", &DMWRITE, DMT_UNINT, get_rule_order, set_rule_order, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_rule_alias, set_rule_alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
+{"Description", &DMWRITE, DMT_STRING, get_rule_description, set_rule_description, BBFDM_BOTH},
+{"Target", &DMWRITE, DMT_STRING, get_rule_target, set_rule_target, BBFDM_BOTH},
+//{"TargetChain", &DMWRITE, DMT_STRING, get_rule_target_chain, set_rule_target_chain, BBFDM_BOTH},
+{"Log", &DMWRITE, DMT_BOOL, get_rule_log, set_rule_log, BBFDM_BOTH},
+{"CreationDate", &DMREAD, DMT_TIME, get_FirewallChainRule_CreationDate, NULL, BBFDM_BOTH},
+{"ExpiryDate", &DMWRITE, DMT_TIME, get_FirewallChainRule_ExpiryDate, set_FirewallChainRule_ExpiryDate, BBFDM_BOTH},
+{"SourceInterface", &DMWRITE, DMT_STRING, get_rule_source_interface, set_rule_source_interface, BBFDM_BOTH, DM_FLAG_REFERENCE},
+{"SourceAllInterfaces", &DMWRITE, DMT_BOOL, get_rule_source_all_interfaces, set_rule_source_all_interfaces, BBFDM_BOTH},
+{"DestInterface", &DMWRITE, DMT_STRING, get_rule_dest_interface, set_rule_dest_interface, BBFDM_BOTH, DM_FLAG_REFERENCE},
+{"DestAllInterfaces", &DMWRITE, DMT_BOOL, get_rule_dest_all_interfaces, set_rule_dest_all_interfaces, BBFDM_BOTH},
+{"IPVersion", &DMWRITE, DMT_INT, get_rule_i_p_version, set_rule_i_p_version, BBFDM_BOTH},
+{"DestIP", &DMWRITE, DMT_STRING, get_rule_dest_ip, set_rule_dest_ip, BBFDM_BOTH},
+{"DestMask", &DMWRITE, DMT_STRING, get_rule_dest_mask, set_rule_dest_mask, BBFDM_BOTH},
+{"SourceIP", &DMWRITE, DMT_STRING, get_rule_source_ip, set_rule_source_ip, BBFDM_BOTH},
+{"SourceMask", &DMWRITE, DMT_STRING, get_rule_source_mask, set_rule_source_mask, BBFDM_BOTH},
+{"Protocol", &DMWRITE, DMT_INT, get_rule_protocol, set_rule_protocol, BBFDM_BOTH},
+{"DestPort", &DMWRITE, DMT_INT, get_rule_dest_port, set_rule_dest_port, BBFDM_BOTH},
+{"DestPortRangeMax", &DMWRITE, DMT_INT, get_rule_dest_port_range_max, set_rule_dest_port_range_max, BBFDM_BOTH},
+{"SourcePort", &DMWRITE, DMT_INT, get_rule_source_port, set_rule_source_port, BBFDM_BOTH},
+{"SourcePortRangeMax", &DMWRITE, DMT_INT, get_rule_source_port_range_max, set_rule_source_port_range_max, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.Firewall.DMZ.{i}. *** */
+DMLEAF tFirewallDMZParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version */
+{"Alias", &DMWRITE, DMT_STRING, get_FirewallDMZ_Alias, set_FirewallDMZ_Alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
+{"Enable", &DMWRITE, DMT_BOOL, get_FirewallDMZ_Enable, set_FirewallDMZ_Enable, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_FirewallDMZ_Status, NULL, BBFDM_BOTH},
+{"Origin", &DMWRITE, DMT_STRING, get_FirewallDMZ_Origin, set_FirewallDMZ_Origin, BBFDM_BOTH},
+{"Description", &DMWRITE, DMT_STRING, get_FirewallDMZ_Description, set_FirewallDMZ_Description, BBFDM_BOTH},
+{"Interface", &DMWRITE, DMT_STRING, get_FirewallDMZ_Interface, set_FirewallDMZ_Interface, BBFDM_BOTH, DM_FLAG_REFERENCE},
+{"DestIP", &DMWRITE, DMT_STRING, get_FirewallDMZ_DestIP, set_FirewallDMZ_DestIP, BBFDM_BOTH},
+{"SourcePrefix", &DMWRITE, DMT_STRING, get_FirewallDMZ_SourcePrefix, set_FirewallDMZ_SourcePrefix, BBFDM_BOTH, DM_FLAG_UNIQUE},
+{0}
+};
+
+/* *** Device.Firewall.Service.{i}. *** */
+DMLEAF tFirewallServiceParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
+{"Alias", &DMWRITE, DMT_STRING, get_service_alias, set_service_alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
+{"Enable", &DMWRITE, DMT_BOOL, get_service_enable, set_service_enable, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_service_status, NULL, BBFDM_BOTH},
+{"Interface", &DMWRITE, DMT_STRING, get_service_intf, set_service_intf, BBFDM_BOTH, DM_FLAG_REFERENCE},
+{"DestPort", &DMWRITE, DMT_STRING, get_service_port, set_service_port, BBFDM_BOTH},
+{"IPVersion", &DMWRITE, DMT_INT, get_service_ipver, set_service_ipver, BBFDM_BOTH},
+{"Protocol", &DMWRITE, DMT_STRING, get_service_protocol, set_service_protocol, BBFDM_BOTH},
+{"ICMPType", &DMWRITE, DMT_INT, get_service_icmp, set_service_icmp, BBFDM_BOTH},
+{"SourcePrefixes", &DMWRITE, DMT_STRING, get_service_src_prefix, set_service_src_prefix, BBFDM_BOTH},
+{"Action", &DMWRITE, DMT_STRING, get_service_action, set_service_action, BBFDM_BOTH},
+{0}
+};
diff --git a/src/firewall.h b/src/firewall.h
new file mode 100644
index 0000000000000000000000000000000000000000..9137b8f5de298b461cdd32232ee8ede097f265f7
--- /dev/null
+++ b/src/firewall.h
@@ -0,0 +1,25 @@
+/*
+ * 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: Omar Kallel <omar.kallel@pivasoftware.com>
+ */
+
+#ifndef _FIREWALL_H
+#define _FIREWALL_H
+
+#include "libbbfdm-api/dmcommon.h"
+
+extern DMOBJ tFirewallObj[];
+extern DMLEAF tFirewallParams[];
+extern DMLEAF tFirewallLevelParams[];
+extern DMLEAF tFirewallChainParams[];
+extern DMOBJ tFirewallChainObj[];
+extern DMLEAF tFirewallChainRuleParams[];
+extern DMLEAF tFirewallDMZParams[];
+extern DMLEAF tFirewallServiceParams[];
+
+#endif
diff --git a/src/firewallmngr.c b/src/firewallmngr.c
new file mode 100644
index 0000000000000000000000000000000000000000..75b82b07d7a383976bbf0446ba603d7d89a0832a
--- /dev/null
+++ b/src/firewallmngr.c
@@ -0,0 +1,26 @@
+/*
+ * 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 Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
+ *
+ */
+
+#include "firewallmngr.h"
+
+DMOBJ tFirewallObjs[] = {
+/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/
+{"NAT", &DMREAD, NULL, NULL, "file:/etc/config/firewall", NULL, NULL, NULL, tNATObj, tNATParams, NULL, BBFDM_BOTH, NULL},
+{"Firewall", &DMREAD, NULL, NULL, "file:/etc/config/firewall", NULL, NULL, NULL, tFirewallObj, tFirewallParams, NULL, BBFDM_BOTH, NULL},
+{0}
+};
+
+/* ********** DynamicObj ********** */
+DM_MAP_OBJ tDynamicObj[] = {
+/* parentobj, nextobject, parameter */
+{"Device.", tFirewallObjs, NULL},
+{0}
+};
diff --git a/src/firewallmngr.h b/src/firewallmngr.h
new file mode 100644
index 0000000000000000000000000000000000000000..efef390bb08c6d22798f48ac5802ede4645cbd2b
--- /dev/null
+++ b/src/firewallmngr.h
@@ -0,0 +1,25 @@
+/*
+ * 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: Anis Ellouze <anis.ellouze@pivasoftware.com>
+ *		Author: Omar Kallel <omar.kallel@pivasoftware.com>
+ *		Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
+ *		Author: Imen BHIRI <imen.bhiri@pivasoftware.com>
+ *		Author: Amit Kumar <amit.kumar@iopsys.eu>
+ *
+ */
+
+#ifndef __FIREWALLMNGR_H
+#define __FIREWALLMNGR_H
+
+#include "libbbfdm-api/dmcommon.h"
+#include "firewall.h"
+#include "nat.h"
+
+extern DMOBJ tFirewallObjs[];
+
+#endif
diff --git a/src/nat.c b/src/nat.c
new file mode 100644
index 0000000000000000000000000000000000000000..a3a171bc7a0ad1ec15b992eb3717f78e3159fe4f
--- /dev/null
+++ b/src/nat.c
@@ -0,0 +1,746 @@
+/*
+ * 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: Anis Ellouze <anis.ellouze@pivasoftware.com>
+ *	Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
+ *
+ */
+
+#include "nat.h"
+#include "nat_porttrigger.h"
+
+static int get_nat_port_mapping_external_port_end_range(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+/*************************************************************
+* ENTRY METHOD
+**************************************************************/
+/*#Device.NAT.InterfaceSetting.{i}.!UCI:firewall/zone/dmmap_firewall*/
+static int browseInterfaceSettingInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+	char *inst = NULL;
+	struct dm_data *curr_data = NULL;
+	LIST_HEAD(dup_list);
+
+	synchronize_specific_config_sections_with_dmmap("firewall", "zone", "dmmap_firewall", &dup_list);
+	list_for_each_entry(curr_data, &dup_list, list) {
+
+		inst = handle_instance(dmctx, parent_node, curr_data->dmmap_section, "interface_setting_instance", "interface_setting_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;
+}
+
+/*#Device.NAT.PortMapping.{i}.!UCI:firewall/redirect/dmmap_firewall*/
+static int browsePortMappingInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+	char *inst = NULL, *target = NULL;
+	struct dm_data *curr_data = NULL;
+	LIST_HEAD(dup_list);
+
+	synchronize_specific_config_sections_with_dmmap("firewall", "redirect", "dmmap_firewall", &dup_list);
+
+	list_for_each_entry(curr_data, &dup_list, list) {
+		dmuci_get_value_by_section_string(curr_data->config_section, "target", &target);
+		if (*target != '\0' && DM_LSTRCMP(target, "DNAT") != 0)
+			continue;
+
+		/*
+		 * Add port range end in dmmap section if needed
+		 */
+		char *src_dport = NULL;
+		dmuci_get_value_by_section_string(curr_data->config_section, "src_dport", &src_dport);
+		if (DM_STRLEN(src_dport) != 0) {
+			char *tmp = DM_STRCHR(src_dport, '-');
+			if (tmp)
+				dmuci_set_value_by_section(curr_data->dmmap_section, "src_dport_end", tmp + 1);
+		}
+
+		inst = handle_instance(dmctx, parent_node, curr_data->dmmap_section, "port_mapping_instance", "port_mapping_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 add_NAT_InterfaceSetting(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+	struct uci_section *s = NULL, *dmmap_firewall = NULL;
+	char zone_name[16] = {0};
+	char name[16] = {0};
+
+	snprintf(zone_name, sizeof(zone_name), "zone_iface_%s", *instance);
+	snprintf(name, sizeof(name), "iface_%s", *instance);
+
+	dmuci_add_section("firewall", "zone", &s);
+	dmuci_rename_section_by_section(s, zone_name);
+	dmuci_set_value_by_section(s, "input", "REJECT");
+	dmuci_set_value_by_section(s, "output", "ACCEPT");
+	dmuci_set_value_by_section(s, "forward", "REJECT");
+	dmuci_set_value_by_section(s, "name", name);
+
+	dmuci_add_section_bbfdm("dmmap_firewall", "zone", &dmmap_firewall);
+	dmuci_set_value_by_section(dmmap_firewall, "section_name", zone_name);
+	dmuci_set_value_by_section(dmmap_firewall, "interface_setting_instance", *instance);
+	return 0;
+}
+
+static int delete_NAT_InterfaceSetting(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+	struct uci_section *s = NULL, *stmp = NULL;
+
+	switch (del_action) {
+		case DEL_INST:
+			dmuci_delete_by_section(((struct dm_data *)data)->config_section, NULL, NULL);
+			dmuci_delete_by_section(((struct dm_data *)data)->dmmap_section, NULL, NULL);
+			break;
+		case DEL_ALL:
+			uci_foreach_sections_safe("firewall", "zone", stmp, s) {
+				struct uci_section *dmmap_firewall = NULL;
+
+				get_dmmap_section_of_config_section("dmmap_firewall", "zone", section_name(s), &dmmap_firewall);
+				dmuci_delete_by_section(dmmap_firewall, NULL, NULL);
+
+				dmuci_delete_by_section(s, NULL, NULL);
+			}
+			break;
+	}
+	return 0;
+}
+
+static int add_NAT_PortMapping(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+	struct uci_section *s = NULL, *dmmap_firewall = NULL;
+	char s_name[32];
+
+	snprintf(s_name, sizeof(s_name), "port_map_%s", *instance);
+
+	dmuci_add_section("firewall", "redirect", &s);
+	dmuci_rename_section_by_section(s, s_name);
+	dmuci_set_value_by_section(s, "target", "DNAT");
+	dmuci_set_value_by_section(s, "enabled", "0");
+	dmuci_set_value_by_section(s, "proto", "tcp");
+
+	dmuci_add_section_bbfdm("dmmap_firewall", "redirect", &dmmap_firewall);
+	dmuci_set_value_by_section(dmmap_firewall, "section_name", s_name);
+	dmuci_set_value_by_section(dmmap_firewall, "port_mapping_instance", *instance);
+	dmuci_set_value_by_section(dmmap_firewall, "enabled", "0");
+	return 0;
+}
+
+static int delete_NAT_PortMapping(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+	struct uci_section *s = NULL, *stmp = NULL;
+
+	switch (del_action) {
+		case DEL_INST:
+			dmuci_delete_by_section(((struct dm_data *)data)->config_section, NULL, NULL);
+			dmuci_delete_by_section(((struct dm_data *)data)->dmmap_section, NULL, NULL);
+			break;
+		case DEL_ALL:
+			uci_foreach_sections_safe("firewall", "redirect", stmp, s) {
+				struct uci_section *dmmap_firewall = NULL;
+
+				get_dmmap_section_of_config_section("dmmap_firewall", "redirect", section_name(s), &dmmap_firewall);
+				dmuci_delete_by_section(dmmap_firewall, NULL, NULL);
+
+				dmuci_delete_by_section(s, NULL, NULL);
+			}
+			return 0;
+	}
+	return 0;
+}
+
+/**************************************************************************
+* SET & GET VALUE
+***************************************************************************/
+/*#Device.NAT.InterfaceSettingNumberOfEntries!UCI:firewall/zone/*/
+static int get_nat_interface_setting_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	int cnt = get_number_of_entries(ctx, data, instance, browseInterfaceSettingInst);
+	dmasprintf(value, "%d", cnt);
+	return 0;
+}
+
+/*#Device.NAT.PortMappingNumberOfEntries!UCI:firewall/redirect/*/
+static int get_nat_port_mapping_number_of_entries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	int cnt = get_number_of_entries(ctx, data, instance, browsePortMappingInst);
+	dmasprintf(value, "%d", cnt);
+	return 0;
+}
+
+/*#Device.NAT.InterfaceSetting.{i}.Enable!UCI:firewall/zone,@i-1/masq*/
+static int get_nat_interface_setting_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	char *val;
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "masq", &val);
+	*value = (*val == '1') ? "1" : "0";
+	return 0;
+}
+
+static int set_nat_interface_setting_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	bool b;
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			return 0;
+		case VALUESET:
+			string_to_bool(value, &b);
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "masq", b ? "1" : "0");
+			return 0;
+	}
+	return 0;
+}
+
+/*#Device.NAT.InterfaceSetting.{i}.Status!UCI:firewall/zone,@i-1/masq*/
+static int get_nat_interface_setting_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	char *val;
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "masq", &val);
+	*value = (*val == '1') ? "Enabled" : "Disabled";
+	return 0;
+}
+
+/*#Device.NAT.InterfaceSetting.{i}.Alias!UCI:dmmap_firewall/zone,@i-1/interface_setting_alias*/
+static int get_nat_interface_setting_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	return bbf_get_alias(ctx, ((struct dm_data *)data)->dmmap_section, "interface_setting_alias", instance, value);
+}
+
+static int set_nat_interface_setting_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, "interface_setting_alias", instance, value);
+}
+
+static int get_nat_interface_setting_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct uci_list *v = NULL;
+	char buf[256];
+	unsigned pos = 0;
+
+	buf[0] = 0;
+	dmuci_get_value_by_section_list(((struct dm_data *)data)->config_section, "network", &v);
+	if (v) {
+		struct uci_element *e = NULL;
+		char *ifaceobj = NULL;
+
+		uci_foreach_element(v, e) {
+			bbf_get_reference_param("Device.IP.Interface.", "Name", e->name, &ifaceobj);
+			if (DM_STRLEN(ifaceobj))
+				pos += snprintf(&buf[pos], sizeof(buf) - pos, "%s,", ifaceobj);
+		}
+	}
+
+	/* cut tailing ',' */
+	if (pos)
+		buf[pos - 1] = 0;
+
+	*value = dmstrdup(buf);
+	return 0;
+}
+
+static int set_nat_interface_setting_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *allowed_objects[] = {"Device.IP.Interface.", NULL};
+	struct dm_reference reference = {0};
+
+	bbf_get_reference_args(value, &reference);
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, reference.path, -1, 256, NULL, NULL))
+				return FAULT_9007;
+
+			if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
+				return FAULT_9007;
+
+			return 0;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "network", "");
+			dmuci_add_list_value_by_section(((struct dm_data *)data)->config_section, "network", reference.value);
+			return 0;
+	}
+	return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.Enable!UCI:firewall/redirect,@i-1/enabled*/
+static int get_nat_port_mapping_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->dmmap_section, "enabled", "1");
+	return 0;
+}
+
+static int set_nat_port_mapping_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	bool b;
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			return 0;
+		case VALUESET:
+			string_to_bool(value, &b);
+			dmuci_set_value_by_section(((struct dm_data *)data)->dmmap_section, "enabled", b ? "1" : "0");
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "enabled", b ? "1" : "0");
+	}
+	return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.Status!UCI:firewall/redirect,@i-1/enabled*/
+static int get_nat_port_mapping_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	get_nat_port_mapping_enable(refparam, ctx, data, instance, value);
+	*value = (DM_LSTRCMP(*value, "1") == 0) ? "Enabled" : "Disabled";
+	return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.Alias!UCI:dmmap_firewall/redirect,@i-1/port_mapping_alias*/
+static int get_nat_port_mapping_alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	return bbf_get_alias(ctx, ((struct dm_data *)data)->dmmap_section, "port_mapping_alias", instance, value);
+}
+
+static int set_nat_port_mapping_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, "port_mapping_alias", instance, value);
+}
+
+static int get_nat_port_mapping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	struct uci_section *s = NULL;
+	struct uci_list *v = NULL;
+	char *zone_name = NULL, *name = NULL, *src_dip = NULL, buf[256];
+	unsigned pos = 0;
+
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "src_dip", &src_dip);
+	if (src_dip && DM_LSTRCMP(src_dip, "*") == 0)
+		return 0;
+
+	buf[0] = 0;
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "src", &zone_name);
+	uci_foreach_sections("firewall", "zone", s) {
+		dmuci_get_value_by_section_string(s, "name", &name);
+		if (zone_name && name && DM_STRCMP(zone_name, name) == 0) {
+			dmuci_get_value_by_section_list(s, "network", &v);
+			break;
+		}
+	}
+
+	if (v) {
+		struct uci_element *e = NULL;
+		char *ifaceobj = NULL;
+
+		uci_foreach_element(v, e) {
+			bbf_get_reference_param("Device.IP.Interface.", "Name", e->name, &ifaceobj);
+			if (DM_STRLEN(ifaceobj))
+				pos += snprintf(&buf[pos], sizeof(buf) - pos, "%s,", ifaceobj);
+		}
+	}
+
+	/* cut tailing ',' */
+	if (pos)
+		buf[pos - 1] = 0;
+
+	*value = dmstrdup(buf);
+	return 0;
+}
+
+static int set_nat_port_mapping_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *allowed_objects[] = {"Device.IP.Interface.", NULL};
+	struct dm_reference reference = {0};
+
+	bbf_get_reference_args(value, &reference);
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, reference.path, -1, 256, NULL, NULL))
+				return FAULT_9007;
+
+			if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
+				return FAULT_9007;
+
+			break;
+		case VALUESET:
+			if (DM_STRLEN(reference.value)) {
+				struct uci_section *s = NULL;
+				bool zone_enable, sect_enable;
+
+				uci_foreach_sections("firewall", "zone", s) {
+					char *network = NULL;
+
+					dmuci_get_value_by_section_string(s, "network", &network);
+					if (is_strword_in_optionvalue(network, reference.value)) {
+						char *zone_name = NULL;
+						char *zone_masq = NULL;
+						char *val = NULL;
+
+						dmuci_get_value_by_section_string(s, "name", &zone_name);
+						dmuci_get_value_by_section_string(s, "masq", &zone_masq);
+						dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "src", zone_name);
+
+						// set this section enable parameter based on the configured zone masq value
+						dmuci_get_value_by_section_string(((struct dm_data *)data)->dmmap_section, "enabled", &val);
+						sect_enable = (*val == '1') ? true : false;
+						zone_enable = (*zone_masq == '1') ? true : false;
+
+						sect_enable = sect_enable && zone_enable;
+						dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "enabled", sect_enable ? "1" : "0");
+						break;
+					}
+				}
+			} else {
+				dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "src", "");
+			}
+			break;
+	}
+	return 0;
+}
+
+static int get_nat_port_mapping_all_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	char *src_dip = NULL;
+
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "src_dip", &src_dip);
+	*value = (src_dip && *src_dip == '*') ? "1" : "0";
+	return 0;
+}
+
+static int set_nat_port_mapping_all_interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *src = NULL;
+	bool b;
+
+	switch (action)	{
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			string_to_bool(value, &b);
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "src_dip", b ? "*" : "");
+			if (b) {
+				dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "src", &src);
+				if (src == NULL || *src == '\0')
+					dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "src", "wan");
+			}
+			break;
+	}
+	return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.LeaseDuration!UCI:firewall/redirect,@i-1/expiry*/
+static int get_nat_port_mapping_lease_duration(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	char *expiry_date = NULL;
+
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "expiry", &expiry_date);
+	if (expiry_date && *expiry_date != '\0' && DM_STRTOL(expiry_date) > 0) {
+		dmasprintf(value, "%lld", (long long)(DM_STRTOL(expiry_date) - time(NULL)));
+	} else {
+		*value = "0";
+	}
+	return 0;
+}
+
+static int set_nat_port_mapping_lease_duration(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char expiry_date[16];
+
+	switch (action)	{
+		case VALUECHECK:
+			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{NULL,NULL}}, 1))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			if (!value || DM_STRTOL(value) == 0)
+				break;
+
+			snprintf(expiry_date, sizeof(expiry_date), "%lld", (long long)(DM_STRTOL(value) + time(NULL)));
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "expiry", expiry_date);
+			break;
+	}
+	return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.RemoteHost!UCI:firewall/redirect,@i-1/src_dip*/
+static int get_nat_port_mapping_remote_host(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "src_ip", value);
+	return 0;
+}
+
+static int set_nat_port_mapping_remote_host(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;
+			return 0;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "src_ip", value);
+			return 0;
+	}
+	return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.ExternalPort!UCI:firewall/redirect,@i-1/src_dport*/
+static int get_nat_port_mapping_external_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	char *src_dport = NULL;
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "src_dport", &src_dport);
+	if (src_dport && *src_dport == '\0') {
+		*value = "0";
+		return 0;
+	}
+
+	char *tmp = src_dport ? DM_STRCHR(src_dport, '-') : NULL;
+	if (tmp)
+		*tmp = '\0';
+	*value = src_dport;
+	return 0;
+}
+
+static int set_nat_port_mapping_external_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *dport_end = NULL, buffer[64];
+	uint16_t start_port, end_port;
+
+	get_nat_port_mapping_external_port_end_range(refparam, ctx, data, instance, &dport_end);
+	end_port = DM_STRTOL(dport_end);
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","65535"}}, 1))
+				return FAULT_9007;
+
+			start_port = DM_STRTOL(value);
+			if (start_port && end_port && start_port > end_port) {
+				bbfdm_set_fault_message(ctx, "The start port value '%s' should be lower than the end port value '%s'.", value, dport_end);
+				return FAULT_9007;
+			}
+
+			return 0;
+		case VALUESET:
+			if (strcmp(value, "0") == 0) { /* 0 means no external port */
+				dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "src_dport", "");
+				return 0;
+			}
+
+			start_port = DM_STRTOL(value);
+			if (!end_port) // if end range is 0
+				snprintf(buffer, sizeof(buffer), "%d", start_port);
+			else
+				snprintf(buffer, sizeof(buffer), "%d-%d", start_port, end_port);
+
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "src_dport", buffer);
+			return 0;
+	}
+	return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.ExternalPortEndRange!UCI:firewall/redirect,@i-1/src_dport*/
+static int get_nat_port_mapping_external_port_end_range(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->dmmap_section, "src_dport_end", "0");
+	return 0;
+}
+
+static int set_nat_port_mapping_external_port_end_range(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *src_dport = NULL;
+	uint16_t sport, dport;
+
+	get_nat_port_mapping_external_port(refparam, ctx, data, instance, &src_dport);
+	sport = DM_STRTOL(src_dport);
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","65535"}}, 1))
+				return FAULT_9007;
+
+			dport = DM_STRTOL(value);
+
+			// Add check to check if the endrange > src_dport
+			if (dport != 0 && dport < sport) {
+				bbfdm_set_fault_message(ctx, "The end port value '%s' should be greater than the start port value '%s'.", value, src_dport);
+				return FAULT_9007;
+			}
+
+			return 0;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->dmmap_section, "src_dport_end", value);
+
+			dport = DM_STRTOL(value);
+
+			if (sport) { // if not 0
+				char buffer[64] = {0};
+
+				if (dport) // if not 0
+					snprintf(buffer, sizeof(buffer), "%d-%d", sport, dport);
+				else
+					snprintf(buffer, sizeof(buffer), "%d", sport);
+
+				dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "src_dport", buffer);
+			}
+
+			return 0;
+	}
+	return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.InternalPort!UCI:firewall/redirect,@i-1/dest_port*/
+static int get_nat_port_mapping_internal_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "dest_port", "0");
+	return 0;
+}
+
+static int set_nat_port_mapping_internal_port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","65535"}}, 1))
+				return FAULT_9007;
+			return 0;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "dest_port", value);
+			return 0;
+	}
+	return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.Protocol!UCI:firewall/redirect,@i-1/proto*/
+static int get_nat_port_mapping_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	char *proto = NULL;
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "proto", &proto);
+	*value = (proto && DM_LSTRCMP(proto, "udp") == 0) ? "UDP" : "TCP";
+	return 0;
+}
+
+static int set_nat_port_mapping_protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *NAT_Protocol[] = {"TCP", "UDP", NULL};
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, -1, NAT_Protocol, NULL))
+				return FAULT_9007;
+			return 0;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "proto", (DM_LSTRCMP(value, "UDP") == 0) ? "udp" : "tcp");
+			return 0;
+	}
+	return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.InternalClient!UCI:firewall/redirect,@i-1/dest_ip*/
+static int get_nat_port_mapping_internal_client(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "dest_ip", value);
+	return 0;
+}
+
+static int set_nat_port_mapping_internal_client(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL))
+				return FAULT_9007;
+			return 0;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "dest_ip", value);
+			return 0;
+	}
+	return 0;
+}
+
+/*#Device.NAT.PortMapping.{i}.Description!UCI:firewall/redirect,@i-1/name*/
+static int get_nat_port_mapping_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "name", value);
+	return 0;
+}
+
+static int set_nat_port_mapping_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL))
+				return FAULT_9007;
+			return 0;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "name", value);
+			return 0;
+	}
+	return 0;
+}
+
+/**********************************************************************************************************************************
+*                                            OBJ & PARAM DEFINITION
+***********************************************************************************************************************************/
+/* *** Device.NAT. *** */
+DMOBJ tNATObj[] = {
+/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/
+{"InterfaceSetting", &DMWRITE, add_NAT_InterfaceSetting, delete_NAT_InterfaceSetting, NULL, browseInterfaceSettingInst, NULL, NULL, NULL, tNATInterfaceSettingParams, NULL, BBFDM_BOTH, NULL},
+{"PortMapping", &DMWRITE, add_NAT_PortMapping, delete_NAT_PortMapping, NULL, browsePortMappingInst, NULL, NULL, NULL, tNATPortMappingParams, NULL, BBFDM_BOTH, NULL},
+#ifdef INCLUDE_PORT_TRIGGER
+{"PortTrigger", &DMWRITE, addObjNATPortTrigger, delObjNATPortTrigger, NULL, browseNATPortTriggerInst, NULL, NULL, tNATPortTriggerObj, tNATPortTriggerParams, NULL, BBFDM_BOTH},
+#endif
+{0}
+};
+
+DMLEAF tNATParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
+{"InterfaceSettingNumberOfEntries", &DMREAD, DMT_UNINT, get_nat_interface_setting_number_of_entries, NULL, BBFDM_BOTH},
+{"PortMappingNumberOfEntries", &DMREAD, DMT_UNINT, get_nat_port_mapping_number_of_entries, NULL, BBFDM_BOTH},
+#ifdef INCLUDE_PORT_TRIGGER
+{"PortTriggerNumberOfEntries", &DMREAD, DMT_UNINT, get_NAT_PortTriggerNumberOfEntries, NULL, BBFDM_BOTH},
+#endif
+{0}
+};
+
+/* *** Device.NAT.InterfaceSetting.{i}. *** */
+DMLEAF tNATInterfaceSettingParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
+{"Enable", &DMWRITE, DMT_BOOL, get_nat_interface_setting_enable, set_nat_interface_setting_enable, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_nat_interface_setting_status, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_nat_interface_setting_alias, set_nat_interface_setting_alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
+{"Interface", &DMWRITE, DMT_STRING, get_nat_interface_setting_interface, set_nat_interface_setting_interface, BBFDM_BOTH, DM_FLAG_UNIQUE|DM_FLAG_REFERENCE},
+{0}
+};
+
+/* *** Device.NAT.PortMapping.{i}. *** */
+DMLEAF tNATPortMappingParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/
+{"Enable", &DMWRITE, DMT_BOOL, get_nat_port_mapping_enable, set_nat_port_mapping_enable, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_nat_port_mapping_status, NULL, BBFDM_BOTH},
+{"Alias", &DMWRITE, DMT_STRING, get_nat_port_mapping_alias, set_nat_port_mapping_alias, BBFDM_BOTH, DM_FLAG_UNIQUE},
+{"Interface", &DMWRITE, DMT_STRING, get_nat_port_mapping_interface, set_nat_port_mapping_interface, BBFDM_BOTH, DM_FLAG_REFERENCE},
+{"AllInterfaces", &DMWRITE, DMT_BOOL, get_nat_port_mapping_all_interface, set_nat_port_mapping_all_interface, BBFDM_BOTH},
+{"LeaseDuration", &DMWRITE, DMT_UNINT, get_nat_port_mapping_lease_duration, set_nat_port_mapping_lease_duration, BBFDM_BOTH},
+{"RemoteHost", &DMWRITE, DMT_STRING, get_nat_port_mapping_remote_host, set_nat_port_mapping_remote_host, BBFDM_BOTH, DM_FLAG_UNIQUE},
+{"ExternalPort", &DMWRITE, DMT_UNINT, get_nat_port_mapping_external_port, set_nat_port_mapping_external_port, BBFDM_BOTH, DM_FLAG_UNIQUE},
+{"ExternalPortEndRange", &DMWRITE, DMT_UNINT, get_nat_port_mapping_external_port_end_range, set_nat_port_mapping_external_port_end_range, BBFDM_BOTH},
+{"InternalPort", &DMWRITE, DMT_UNINT, get_nat_port_mapping_internal_port, set_nat_port_mapping_internal_port, BBFDM_BOTH},
+{"Protocol", &DMWRITE, DMT_STRING, get_nat_port_mapping_protocol, set_nat_port_mapping_protocol, BBFDM_BOTH, DM_FLAG_UNIQUE},
+{"InternalClient", &DMWRITE, DMT_STRING, get_nat_port_mapping_internal_client, set_nat_port_mapping_internal_client, BBFDM_BOTH},
+{"Description", &DMWRITE, DMT_STRING, get_nat_port_mapping_description, set_nat_port_mapping_description, BBFDM_BOTH},
+{0}
+};
diff --git a/src/nat.h b/src/nat.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f882d7b66cf4b2462a4c23ad07db07b04b192c7
--- /dev/null
+++ b/src/nat.h
@@ -0,0 +1,23 @@
+/*
+ * 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: Imen BHIRI <imen.bhiri@pivasoftware.com>
+ *	Author: Amin Ben Ramdhane <amin.benramdhane@pivasoftware.com>
+ *
+ */
+
+#ifndef __NAT_H
+#define __NAT_H
+
+#include "libbbfdm-api/dmcommon.h"
+
+extern DMOBJ tNATObj[];
+extern DMLEAF tNATParams[];
+extern DMLEAF tNATInterfaceSettingParams[];
+extern DMLEAF tNATPortMappingParams[];
+
+#endif
diff --git a/src/nat_porttrigger.c b/src/nat_porttrigger.c
new file mode 100644
index 0000000000000000000000000000000000000000..d21fdc8758fc2ce699367b7e1d7b03f2d2b4c568
--- /dev/null
+++ b/src/nat_porttrigger.c
@@ -0,0 +1,518 @@
+/*
+ * 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: Amit Kumar <amit.kumar@iopsys.eu>
+ *
+ */
+
+#include "libbbfdm-api/dmcommon.h"
+
+/*************************************************************
+* ENTRY METHOD
+**************************************************************/
+
+/*#Device.NAT.PortTrigger.{i}.!UCI:port-trigger/port_trigger/dmmap_port_trigger*/
+int browseNATPortTriggerInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+	int inst = 0;
+	struct uci_section *p = NULL;
+	struct dm_data data = {0};
+	char *name = NULL;
+	char *buf = NULL;
+
+	uci_foreach_sections("port-trigger", "port_trigger", p) {
+		dmuci_get_section_name(section_name(p),&name);
+		if (name) {
+			sscanf(name, "port_trigger_%d",&inst);
+			if (inst == 0) {
+				continue;
+			}
+			dmasprintf(&buf, "%d", inst);
+			data.config_section = p;
+			if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&data, buf) == DM_STOP)
+				break;
+		}
+	}
+
+	return 0;
+}
+
+static int browseNATPortTriggerRuleInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance)
+{
+        struct uci_section *p = NULL;
+	struct dm_data data = {0};
+	int inst = 0;
+	int ptg_inst = 0;
+	char *name = NULL;
+	char *buf = NULL;
+	int parent_inst = 0;
+	parent_inst = atoi(prev_instance);
+
+	uci_foreach_sections("port-trigger", "rule", p) {
+		dmuci_get_section_name(section_name(p),&name);
+		if (name) {
+			sscanf(name, "port_trigger_%d_rule_%d",&ptg_inst,&inst);
+			if ((inst == 0) || (ptg_inst != parent_inst))
+				continue;
+			dmasprintf(&buf, "%d", inst);
+			data.config_section = p;
+			if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&data, buf) == DM_STOP)
+				break;
+		}
+	}
+        return 0;
+}
+
+/*************************************************************
+* ADD & DEL OBJ
+**************************************************************/
+int addObjNATPortTrigger(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+	struct uci_section *s = NULL;
+	char port_trigger_name[16] = {0};
+	char name[16] = {0};
+
+	snprintf(port_trigger_name, sizeof(port_trigger_name), "port_trigger_%s", *instance);
+	snprintf(name, sizeof(name), "trigger_%s", *instance);
+
+	dmuci_add_section("port-trigger", "port_trigger", &s);
+	dmuci_rename_section_by_section(s, port_trigger_name);
+	dmuci_set_value_by_section(s, "name", name);
+
+	return 0;
+}
+
+int delObjNATPortTrigger(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+	struct uci_section *s = NULL, *stmp = NULL;
+	char *name;
+
+	switch (del_action) {
+		case DEL_INST:
+			dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "name", &name);
+			uci_foreach_option_eq_safe("port-trigger", "rule", "port_trigger", name, stmp, s) {
+                                dmuci_delete_by_section(s, NULL, NULL);
+                        }
+
+			dmuci_delete_by_section(((struct dm_data *)data)->config_section, NULL, NULL);
+			break;
+		case DEL_ALL:
+			uci_foreach_sections_safe("port-trigger", "port_trigger", stmp, s) {
+
+				dmuci_delete_by_section(s, NULL, NULL);
+			}
+			uci_foreach_sections_safe("port-trigger", "rule", stmp, s) {
+
+				dmuci_delete_by_section(s, NULL, NULL);
+			}
+			break;
+	}
+	return 0;
+}
+
+static int addObjNATPortTriggerRule(char *refparam, struct dmctx *ctx, void *data, char **instance)
+{
+        struct uci_section *port_trigger = ((struct dm_data *)data)->config_section;
+        struct uci_section *s = NULL;
+        char s_name[50] = {0};
+	char *name = NULL;
+
+        snprintf(s_name, sizeof(s_name), "%s_rule_%s", section_name(port_trigger),*instance);
+
+	dmuci_add_section("port-trigger", "rule", &s);
+        dmuci_rename_section_by_section(s, s_name);
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "name", &name);
+	dmuci_set_value_by_section(s, "port_trigger", name);
+
+        return 0;
+}
+
+static int delObjNATPortTriggerRule(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action)
+{
+	struct uci_section *s = NULL, *stmp = NULL;
+	char *name;
+
+	switch (del_action) {
+		case DEL_INST:
+			dmuci_delete_by_section(((struct dm_data *)data)->config_section, NULL, NULL);
+			break;
+		case DEL_ALL:
+			dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "name", &name);
+                        uci_foreach_option_eq_safe("port-trigger", "rule", "port_trigger", name, stmp, s) {
+                                dmuci_delete_by_section(s, NULL, NULL);
+                        }
+			break;
+	}
+	return 0;
+}
+
+/*************************************************************
+* GET & SET PARAM
+**************************************************************/
+/*#Device.NAT.PortTriggerNumberOfEntries!UCI:port-trigger/port_trigger/*/
+int get_NAT_PortTriggerNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	int cnt = get_number_of_entries(ctx, data, instance, browseNATPortTriggerInst);
+	dmasprintf(value, "%d", cnt);
+	return 0;
+}
+
+static int get_NATPortTrigger_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_section_name(section_name(((struct dm_data *)data)->config_section),value);
+	return 0;
+}
+
+static int get_NATPortTrigger_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "enable", "0");
+	*value = (**value == 'n' || **value == '0' ) ? "0" : "1";
+	return 0;
+}
+
+static int set_NATPortTrigger_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	bool b;
+	time_t now = time(NULL);
+
+	switch (action)	{
+		case VALUECHECK:
+			if (bbfdm_validate_boolean(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			string_to_bool(value, &b);
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "enable", b ? "1" : "0");
+
+			if (b == 1) {
+				char activation_date[32] = {0};
+
+				strftime(activation_date, sizeof(activation_date), "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
+				dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "activation_date", activation_date);
+			}
+			break;
+	}
+	return 0;
+}
+
+static int get_NATPortTrigger_Status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	/*return the admin state of port trigger rule
+	* running status to be updated in later changes*/
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "enable", "0");
+	*value = (**value == 'n' || **value == '0' ) ? "Disabled" : "Enabled";
+	return 0;
+}
+
+static int get_NATPortTrigger_Origin(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "origin", "Controller");
+	return 0;
+}
+
+static int set_NATPortTrigger_Origin(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *Origin[] = {"User", "System", "Controller", NULL};
+
+	switch (action)	{
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, -1, Origin, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "origin", value);
+			break;
+	}
+	return 0;
+}
+
+static int get_NATPortTrigger_Description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "description", value);
+	return 0;
+}
+
+static int set_NATPortTrigger_Description(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action)	{
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, value, -1, 256, NULL, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "description", value);
+			break;
+	}
+	return 0;
+}
+
+static int get_NATPortTrigger_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	char *interf = NULL;
+
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "src", &interf);
+
+	bbf_get_reference_param("Device.IP.Interface.", "Name", interf, value);
+
+	return 0;
+}
+
+static int set_NATPortTrigger_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *allowed_objects[] = {"Device.IP.Interface.", NULL};
+	struct dm_reference reference = {0};
+
+	bbf_get_reference_args(value, &reference);
+
+	switch (action) {
+		case VALUECHECK:
+			if (bbfdm_validate_string(ctx, reference.path, -1, 256, NULL, NULL))
+				return FAULT_9007;
+
+			if (dm_validate_allowed_objects(ctx, &reference, allowed_objects))
+				return FAULT_9007;
+
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "src", reference.value);
+			break;
+	}
+	return 0;
+}
+
+static int get_NATPortTrigger_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "port", "0");
+	return 0;
+}
+
+static int set_NATPortTrigger_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action)	{
+		case VALUECHECK:
+			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","65535"}}, 1))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "port", value);
+			break;
+	}
+	return 0;
+}
+
+static int get_NATPortTrigger_PortEndRange(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "port_end_range", "0");
+	return 0;
+}
+
+static int set_NATPortTrigger_PortEndRange(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char *port;
+	uint16_t s_port, end_port;
+
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "port", &port);
+	s_port = DM_STRTOL(port);
+	switch (action)	{
+		case VALUECHECK:
+			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","65535"}}, 1))
+				return FAULT_9007;
+			end_port = DM_STRTOL(value);
+			if (s_port > end_port)
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "port_end_range", value);
+			break;
+	}
+	return 0;
+}
+
+static int get_NATPortTrigger_AutoDisableDuration(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "auto_disable_duration", value);
+	return 0;
+}
+
+static int set_NATPortTrigger_AutoDisableDuration(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action)	{
+		case VALUECHECK:
+			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{NULL,NULL}}, 1))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "auto_disable_duration", value);
+			break;
+	}
+	return 0;
+}
+
+static int get_NATPortTrigger_ActivationDate(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "activation_date", "0001-01-01T00:00:00Z");
+	return 0;
+}
+
+static int set_NATPortTrigger_ActivationDate(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	char activation_date[16] = {0};
+	struct tm tm;
+
+	switch (action)	{
+		case VALUECHECK:
+			if (bbfdm_validate_dateTime(ctx, value))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			strptime(value, "%Y-%m-%dT%H:%M:%SZ", &tm);
+			snprintf(activation_date, sizeof(activation_date), "%lld", (long long)timegm(&tm));
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "activation_date", activation_date);
+			break;
+	}
+	return 0;
+}
+
+static int get_NATPortTrigger_Protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "protocol", value);
+	return 0;
+}
+
+static int set_NATPortTrigger_Protocol(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, NATProtocol, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "protocol", value);
+			break;
+	}
+	return 0;
+}
+
+static int get_NATPortTrigger_RuleNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	int cnt = get_number_of_entries(ctx, data, instance, browseNATPortTriggerRuleInst);
+	dmasprintf(value, "%d", cnt);
+	return 0;
+}
+
+static int get_NATPortTriggerRule_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_section_name(section_name(((struct dm_data *)data)->config_section),value);
+	return 0;
+}
+
+static int get_NATPortTriggerRule_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "port", "0");
+	return 0;
+}
+
+static int set_NATPortTriggerRule_Port(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+	switch (action)	{
+		case VALUECHECK:
+			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","65535"}}, 1))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "port", value);
+			break;
+	}
+	return 0;
+}
+
+static int get_NATPortTriggerRule_PortEndRange(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	*value = dmuci_get_value_by_section_fallback_def(((struct dm_data *)data)->config_section, "port_end_range", "0");
+	return 0;
+}
+
+static int set_NATPortTriggerRule_PortEndRange(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action)
+{
+
+	char *port;
+	uint16_t s_port, end_port;
+
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "port", &port);
+	s_port = DM_STRTOL(port);
+	switch (action)	{
+		case VALUECHECK:
+			if (bbfdm_validate_unsignedInt(ctx, value, RANGE_ARGS{{"0","65535"}}, 1))
+				return FAULT_9007;
+			end_port = DM_STRTOL(value);
+			if (s_port > end_port)
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "port_end_range", value);
+			break;
+	}
+	return 0;
+}
+
+static int get_NATPortTriggerRule_Protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value)
+{
+	dmuci_get_value_by_section_string(((struct dm_data *)data)->config_section, "protocol", value);
+	return 0;
+}
+
+static int set_NATPortTriggerRule_Protocol(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, NATProtocol, NULL))
+				return FAULT_9007;
+			break;
+		case VALUESET:
+			dmuci_set_value_by_section(((struct dm_data *)data)->config_section, "protocol", value);
+			break;
+	}
+	return 0;
+}
+
+/**********************************************************************************************************************************
+*                                            OBJ & PARAM DEFINITION
+***********************************************************************************************************************************/
+
+DMLEAF tNATPortTriggerParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
+{"Alias", &DMREAD, DMT_STRING, get_NATPortTrigger_Alias, NULL, BBFDM_BOTH},
+{"Enable", &DMWRITE, DMT_BOOL, get_NATPortTrigger_Enable, set_NATPortTrigger_Enable, BBFDM_BOTH},
+{"Status", &DMREAD, DMT_STRING, get_NATPortTrigger_Status, NULL, BBFDM_BOTH},
+{"Origin", &DMWRITE, DMT_STRING, get_NATPortTrigger_Origin, set_NATPortTrigger_Origin, BBFDM_BOTH},
+{"Description", &DMWRITE, DMT_STRING, get_NATPortTrigger_Description, set_NATPortTrigger_Description, BBFDM_BOTH},
+{"Interface", &DMWRITE, DMT_STRING, get_NATPortTrigger_Interface, set_NATPortTrigger_Interface, BBFDM_BOTH, DM_FLAG_REFERENCE},
+{"Port", &DMWRITE, DMT_UNINT, get_NATPortTrigger_Port, set_NATPortTrigger_Port, BBFDM_BOTH},
+{"PortEndRange", &DMWRITE, DMT_UNINT, get_NATPortTrigger_PortEndRange, set_NATPortTrigger_PortEndRange, BBFDM_BOTH},
+{"AutoDisableDuration", &DMWRITE, DMT_UNINT, get_NATPortTrigger_AutoDisableDuration, set_NATPortTrigger_AutoDisableDuration, BBFDM_BOTH},
+{"ActivationDate", &DMWRITE, DMT_TIME, get_NATPortTrigger_ActivationDate, set_NATPortTrigger_ActivationDate, BBFDM_BOTH},
+{"Protocol", &DMWRITE, DMT_STRING, get_NATPortTrigger_Protocol, set_NATPortTrigger_Protocol, BBFDM_BOTH},
+{"RuleNumberOfEntries", &DMREAD, DMT_UNINT, get_NATPortTrigger_RuleNumberOfEntries, NULL, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.NAT.PortTrigger.{i}.Rule.{i}. *** */
+DMLEAF tNATPortTriggerRuleParams[] = {
+/* PARAM, permission, type, getvalue, setvalue, bbfdm_type */
+{"Alias", &DMREAD, DMT_STRING, get_NATPortTriggerRule_Alias, NULL, BBFDM_BOTH},
+{"Port", &DMWRITE, DMT_UNINT, get_NATPortTriggerRule_Port, set_NATPortTriggerRule_Port, BBFDM_BOTH},
+{"PortEndRange", &DMWRITE, DMT_UNINT, get_NATPortTriggerRule_PortEndRange, set_NATPortTriggerRule_PortEndRange, BBFDM_BOTH},
+{"Protocol", &DMWRITE, DMT_STRING, get_NATPortTriggerRule_Protocol, set_NATPortTriggerRule_Protocol, BBFDM_BOTH},
+{0}
+};
+
+/* *** Device.NAT.PortTrigger.{i}. *** */
+DMOBJ tNATPortTriggerObj[] = {
+/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys */
+{"Rule", &DMWRITE, addObjNATPortTriggerRule, delObjNATPortTriggerRule, NULL, browseNATPortTriggerRuleInst, NULL, NULL, NULL, tNATPortTriggerRuleParams, NULL, BBFDM_BOTH, NULL},
+{0}
+};
diff --git a/src/nat_porttrigger.h b/src/nat_porttrigger.h
new file mode 100644
index 0000000000000000000000000000000000000000..f3e770378f97863e9f5f88b5a42673fb853c3f58
--- /dev/null
+++ b/src/nat_porttrigger.h
@@ -0,0 +1,26 @@
+/*
+ * 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: Amit Kumar <amit.kumar@iopsys.eu>
+ *	Author: Mohd Husaam Mehdi <husaam.mehdi@iopsys.eu>
+ *
+ */
+
+#ifndef __NAT_PORTTRIGGER_H
+#define __NAT_PORTTRIGGER_H
+
+#include "libbbfdm-api/dmcommon.h"
+
+extern DMOBJ tNATPortTriggerObj[];
+extern DMLEAF tNATPortTriggerParams[];
+
+int browseNATPortTriggerInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance);
+int addObjNATPortTrigger(char *refparam, struct dmctx *ctx, void *data, char **instance);
+int delObjNATPortTrigger(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action);
+int get_NAT_PortTriggerNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value);
+
+#endif