diff --git a/libbbfdm-api/dmuci.c b/libbbfdm-api/dmuci.c index 11ed351f..59dc7cc1 100644 --- a/libbbfdm-api/dmuci.c +++ b/libbbfdm-api/dmuci.c @@ -790,6 +790,20 @@ int dmuci_rename_section_by_section(struct uci_section *s, char *value) return 0; } +/**** UCI REORDER SECTION by section pointer *****/ +int dmuci_reoder_section_by_section(struct uci_section *s, char *pos) +{ + struct uci_ptr up = {0}; + + if (dmuci_lookup_ptr_by_section(uci_ctx, &up, s, NULL, pos) == -1) + return -1; + + if (uci_reorder_section(uci_ctx, up.s, strtoul(up.value, NULL, 10)) != UCI_OK) + return -1; + + return 0; +} + /**** UCI WALK SECTIONS *****/ struct uci_section *dmuci_walk_section (char *package, char *stype, void *arg1, void *arg2, int cmp , int (*filter)(struct uci_section *s, void *value), struct uci_section *prev_section, int walk) { diff --git a/libbbfdm-api/dmuci.h b/libbbfdm-api/dmuci.h index 2e30ca1f..fc44c12b 100644 --- a/libbbfdm-api/dmuci.h +++ b/libbbfdm-api/dmuci.h @@ -359,6 +359,7 @@ int dmuci_delete_by_section_unnamed(struct uci_section *s, char *option, char *v int dmuci_add_list_value_by_section(struct uci_section *s, char *option, char *value); int dmuci_del_list_value_by_section(struct uci_section *s, char *option, char *value); int dmuci_rename_section_by_section(struct uci_section *s, char *value); +int dmuci_reoder_section_by_section(struct uci_section *s, char *pos); struct uci_section *dmuci_walk_section(char *package, char *stype, void *arg1, void *arg2, int cmp , int (*filter)(struct uci_section *s, void *value), struct uci_section *prev_section, int walk); struct uci_section *dmuci_walk_all_sections(char *package, struct uci_section *prev_section, int walk); diff --git a/libbbfdm/dmtree/tr181/firewall.c b/libbbfdm/dmtree/tr181/firewall.c index 08495e6f..e6e81146 100644 --- a/libbbfdm/dmtree/tr181/firewall.c +++ b/libbbfdm/dmtree/tr181/firewall.c @@ -17,6 +17,7 @@ struct rule_sec struct uci_section *config_section; struct uci_section *dmmap_section; char **dynamic_rule; + char *creator; bool is_dynamic_rule; }; @@ -127,6 +128,85 @@ void synchronize_firewall_sections_with_dmmap(char *package, char *section_type, } } +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)) { + 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); + } + + if (DM_STRTOUL(order) == DM_STRTOUL(stop_order)) + return; + } + + 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)) { + 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); + } + + if (DM_STRTOUL(order) == DM_STRTOUL(stop_order)) + return; + } +} + /************************************************************* * ENTRY METHOD **************************************************************/ @@ -149,6 +229,7 @@ static int browseChainInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_ 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"); @@ -178,17 +259,27 @@ static int browseRuleInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_d 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; @@ -202,6 +293,14 @@ static int browseRuleInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_d 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; } @@ -245,6 +344,7 @@ static int browseRuleInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_d p->is_dynamic_rule = true; p->dynamic_rule = dynamic_rule; + p->creator = creator; inst = handle_instance_without_section(dmctx, parent_node, ++i); @@ -268,13 +368,18 @@ static int add_firewall_rule(char *refparam, struct dmctx *ctx, void *data, char 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) 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); @@ -285,6 +390,14 @@ static int add_firewall_rule(char *refparam, struct dmctx *ctx, void *data, char 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); @@ -295,12 +408,16 @@ static int add_firewall_rule(char *refparam, struct dmctx *ctx, void *data, char static int delete_firewall_rule(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action) { struct uci_section *s = NULL, *stmp = NULL; + char *order = NULL; switch (del_action) { case DEL_INST: if (((struct rule_sec *)data)->is_dynamic_rule) return FAULT_9003; + dmuci_get_value_by_section_string(((struct rule_sec *)data)->dmmap_section, "order", &order); + update_rule_order(order, "0", false); + 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; @@ -501,7 +618,14 @@ static int get_rule_status(char *refparam, struct dmctx *ctx, void *data, char * static int get_rule_order(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - *value = instance; + 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; } @@ -1256,12 +1380,36 @@ static int set_rule_enable(char *refparam, struct dmctx *ctx, void *data, char * 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 (dm_validate_unsignedInt(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)) + return FAULT_9007; + break; case VALUESET: + 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; @@ -1742,7 +1890,7 @@ DMLEAF tFirewallChainRuleParams[] = { /* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/ {"Enable", &DMRule, DMT_BOOL, get_rule_enable, set_rule_enable, BBFDM_BOTH, "2.2"}, {"Status", &DMREAD, DMT_STRING, get_rule_status, NULL, BBFDM_BOTH, "2.2"}, -{"Order", &DMWRITE, DMT_UNINT, get_rule_order, set_rule_order, BBFDM_BOTH, "2.2"}, +{"Order", &DMRule, DMT_UNINT, get_rule_order, set_rule_order, BBFDM_BOTH, "2.2"}, {"Alias", &DMRule, DMT_STRING, get_rule_alias, set_rule_alias, BBFDM_BOTH, "2.2"}, {"Description", &DMRule, DMT_STRING, get_rule_description, set_rule_description, BBFDM_BOTH, "2.2"}, {"Target", &DMRule, DMT_STRING, get_rule_target, set_rule_target, BBFDM_BOTH, "2.2"}, diff --git a/test/files/etc/config/firewall b/test/files/etc/config/firewall index edf85cd9..86c6122a 100644 --- a/test/files/etc/config/firewall +++ b/test/files/etc/config/firewall @@ -8,14 +8,14 @@ config defaults option output 'ACCEPT' option forward 'REJECT' -config zone +config zone 'lan' option name 'lan' list network 'lan' option input 'ACCEPT' option output 'ACCEPT' option forward 'ACCEPT' -config zone +config zone 'wan' option name 'wan' list network 'wan' list network 'wan6' @@ -25,11 +25,11 @@ config zone option masq '1' option mtu_fix '1' -config forwarding +config forwarding 'default_fwd_1' option src 'lan' option dest 'wan' -config rule +config rule 'default_rule_1' option name 'Allow-DHCP-Renew' option src 'wan' option proto 'udp' @@ -37,7 +37,7 @@ config rule option target 'ACCEPT' option family 'ipv4' -config rule +config rule 'default_rule_2' option name 'Allow-Ping' option src 'wan' option proto 'icmp' @@ -45,14 +45,14 @@ config rule option family 'ipv4' option target 'ACCEPT' -config rule +config rule 'default_rule_3' option name 'Allow-IGMP' option src 'wan' option proto 'igmp' option family 'ipv4' option target 'ACCEPT' -config rule +config rule 'default_rule_4' option name 'Allow-DHCPv6' option src 'wan' option proto 'udp' @@ -62,7 +62,7 @@ config rule option family 'ipv6' option target 'ACCEPT' -config rule +config rule 'default_rule_5' option name 'Allow-MLD' option src 'wan' option proto 'icmp' @@ -74,7 +74,7 @@ config rule option family 'ipv6' option target 'ACCEPT' -config rule +config rule 'default_rule_6' option name 'Allow-ICMPv6-Input' option src 'wan' option proto 'icmp' @@ -93,7 +93,7 @@ config rule option family 'ipv6' option target 'ACCEPT' -config rule +config rule 'default_rule_7' option name 'Allow-ICMPv6-Forward' option src 'wan' option dest '*' @@ -109,14 +109,14 @@ config rule option family 'ipv6' option target 'ACCEPT' -config rule +config rule 'default_rule_8' option name 'Allow-IPSec-ESP' option src 'wan' option dest 'lan' option proto 'esp' option target 'ACCEPT' -config rule +config rule 'default_rule_9' option name 'Allow-ISAKMP' option src 'wan' option dest 'lan' @@ -124,7 +124,7 @@ config rule option proto 'udp' option target 'ACCEPT' -config rule +config rule 'default_rule_10' option name 'Support-UDP-Traceroute' option src 'wan' option dest_port '33434:33689'