diff --git a/dmtree/tr181/firewall.c b/dmtree/tr181/firewall.c index d5985c17..64d7467c 100644 --- a/dmtree/tr181/firewall.c +++ b/dmtree/tr181/firewall.c @@ -12,6 +12,9 @@ #include "dmentry.h" #include "firewall.h" +/************************************************************* +* COMMON FUNCTIONS +**************************************************************/ static int dmmap_synchronizeNATPortMappingEnable(const char *intf, bool value) { struct uci_section *s = NULL; @@ -35,6 +38,16 @@ static int dmmap_synchronizeNATPortMappingEnable(const char *intf, bool value) return 0; } +static char *get_rule_perm(char *refparam, struct dmctx *dmctx, void *data, char *instance) +{ + char *rule_perm = NULL; + + dmuci_get_value_by_section_string(((struct dmmap_dup *)data)->dmmap_section, "is_rule", &rule_perm); + return rule_perm; +} + +struct dm_permession_s DMRule = {"1", &get_rule_perm}; + /************************************************************* * ENTRY METHOD **************************************************************/ @@ -63,15 +76,33 @@ static int browseRuleInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_d struct dmmap_dup *p = NULL; LIST_HEAD(dup_list); - synchronize_specific_config_sections_with_dmmap("firewall", "rule", "dmmap_firewall", &dup_list); + // Forwarding sections + synchronize_specific_config_sections_with_dmmap("firewall", "forwarding", "dmmap_firewall", &dup_list); list_for_each_entry(p, &dup_list, list) { + dmuci_set_value_by_section(p->dmmap_section, "is_rule", "0"); + inst = handle_instance(dmctx, parent_node, p->dmmap_section, "firewall_chain_rule_instance", "firewall_chain_rule_alias"); if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p, inst) == DM_STOP) - break; + goto end; } free_dmmap_config_dup_list(&dup_list); + + // Rule sections + synchronize_specific_config_sections_with_dmmap("firewall", "rule", "dmmap_firewall", &dup_list); + list_for_each_entry(p, &dup_list, list) { + + dmuci_set_value_by_section(p->dmmap_section, "is_rule", "1"); + + inst = handle_instance(dmctx, parent_node, p->dmmap_section, "firewall_chain_rule_instance", "firewall_chain_rule_alias"); + + if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p, inst) == DM_STOP) + goto end; + } + free_dmmap_config_dup_list(&dup_list); + +end: return 0; } @@ -129,11 +160,7 @@ static int delete_firewall_rule(char *refparam, struct dmctx *ctx, void *data, c **************************************************************/ static int get_firewall_enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - char *path = "/etc/rc.d/*firewall"; - if (check_file(path)) - *value = "1"; - else - *value = "0"; + *value = dmuci_get_option_value_fallback_def("firewall", "globals", "enabled", "1"); return 0; } @@ -219,6 +246,20 @@ static int get_level_default_log_policy(char *refparam, struct dmctx *ctx, void 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"; @@ -665,7 +706,7 @@ static int set_firewall_enable(char *refparam, struct dmctx *ctx, void *data, ch break; case VALUESET: string_to_bool(value, &b); - dmcmd("/etc/init.d/firewall", 1, b ? "enable" : "disable"); + dmuci_set_value("firewall", "globals", "enabled", b ? "1" : "0"); break; } return 0; @@ -778,6 +819,31 @@ static int set_level_port_mapping_enabled(char *refparam, struct dmctx *ctx, voi 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 (dm_validate_string(value, -1, -1, DefaultPolicy, NULL)) + return FAULT_9007; + break; + case VALUESET: + if (strcmp(value, "Drop") == 0) { + dmuci_set_value("firewall", "@defaults[0]", "input", "DROP"); + dmuci_set_value("firewall", "@defaults[0]", "output", "DROP"); + } else if (strcmp(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; @@ -1326,6 +1392,7 @@ DMLEAF tFirewallLevelParams[] = { {"Description", &DMWRITE, DMT_STRING, get_level_description, set_level_description, BBFDM_BOTH, "2.2"}, {"Chain", &DMREAD, DMT_STRING, get_level_chain, NULL, BBFDM_BOTH, "2.2"}, {"PortMappingEnabled", &DMWRITE, DMT_BOOL, get_level_port_mapping_enabled, set_level_port_mapping_enabled, BBFDM_BOTH, "2.2"}, +{"DefaultPolicy", &DMWRITE, DMT_STRING, get_level_default_policy, set_level_default_policy, BBFDM_BOTH, "2.2"}, {"DefaultLogPolicy", &DMWRITE, DMT_BOOL, get_level_default_log_policy, set_level_default_log_policy, BBFDM_BOTH, "2.2"}, {0} }; @@ -1350,29 +1417,29 @@ DMLEAF tFirewallChainParams[] = { /* *** 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, "2.2"}, -{"Status", &DMREAD, DMT_STRING, get_rule_status, NULL, BBFDM_BOTH, "2.2"}, +{"Enable", &DMRule, DMT_BOOL, get_rule_enable, set_rule_enable, BBFDM_BOTH, "2.2"}, +{"Status", &DMRule, DMT_STRING, get_rule_status, NULL, BBFDM_BOTH, "2.2"}, {"Order", &DMWRITE, DMT_UNINT, get_rule_order, set_rule_order, BBFDM_BOTH, "2.2"}, {"Alias", &DMWRITE, DMT_STRING, get_rule_alias, set_rule_alias, BBFDM_BOTH, "2.2"}, -{"Description", &DMWRITE, DMT_STRING, get_rule_description, set_rule_description, BBFDM_BOTH, "2.2"}, -{"Target", &DMWRITE, DMT_STRING, get_rule_target, set_rule_target, BBFDM_BOTH, "2.2"}, -//{"TargetChain", &DMWRITE, DMT_STRING, get_rule_target_chain, set_rule_target_chain, BBFDM_BOTH, "2.2"}, -{"Log", &DMWRITE, DMT_BOOL, get_rule_log, set_rule_log, BBFDM_BOTH, "2.2"}, -{"CreationDate", &DMREAD, DMT_TIME, get_FirewallChainRule_CreationDate, NULL, BBFDM_BOTH, "2.2"}, -{"ExpiryDate", &DMWRITE, DMT_TIME, get_FirewallChainRule_ExpiryDate, set_FirewallChainRule_ExpiryDate, BBFDM_BOTH, "2.2"}, -{"SourceInterface", &DMWRITE, DMT_STRING, get_rule_source_interface, set_rule_source_interface, BBFDM_BOTH, "2.2"}, -{"SourceAllInterfaces", &DMWRITE, DMT_BOOL, get_rule_source_all_interfaces, set_rule_source_all_interfaces, BBFDM_BOTH, "2.2"}, -{"DestInterface", &DMWRITE, DMT_STRING, get_rule_dest_interface, set_rule_dest_interface, 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"}, +//{"TargetChain", &DMRule, DMT_STRING, get_rule_target_chain, set_rule_target_chain, BBFDM_BOTH, "2.2"}, +{"Log", &DMRule, DMT_BOOL, get_rule_log, set_rule_log, BBFDM_BOTH, "2.2"}, +{"CreationDate", &DMRule, DMT_TIME, get_FirewallChainRule_CreationDate, NULL, BBFDM_BOTH, "2.2"}, +{"ExpiryDate", &DMRule, DMT_TIME, get_FirewallChainRule_ExpiryDate, set_FirewallChainRule_ExpiryDate, BBFDM_BOTH, "2.2"}, +{"SourceInterface", &DMRule, DMT_STRING, get_rule_source_interface, set_rule_source_interface, BBFDM_BOTH, "2.2"}, +{"SourceAllInterfaces", &DMRule, DMT_BOOL, get_rule_source_all_interfaces, set_rule_source_all_interfaces, BBFDM_BOTH, "2.2"}, +{"DestInterface", &DMRule, DMT_STRING, get_rule_dest_interface, set_rule_dest_interface, BBFDM_BOTH, "2.2"}, {"DestAllInterfaces", &DMWRITE, DMT_BOOL, get_rule_dest_all_interfaces, set_rule_dest_all_interfaces, BBFDM_BOTH, "2.2"}, -{"IPVersion", &DMWRITE, DMT_INT, get_rule_i_p_version, set_rule_i_p_version, BBFDM_BOTH, "2.2"}, -{"DestIP", &DMWRITE, DMT_STRING, get_rule_dest_ip, set_rule_dest_ip, BBFDM_BOTH, "2.2"}, -{"DestMask", &DMWRITE, DMT_STRING, get_rule_dest_mask, set_rule_dest_mask, BBFDM_BOTH, "2.2"}, -{"SourceIP", &DMWRITE, DMT_STRING, get_rule_source_ip, set_rule_source_ip, BBFDM_BOTH, "2.2"}, -{"SourceMask", &DMWRITE, DMT_STRING, get_rule_source_mask, set_rule_source_mask, BBFDM_BOTH, "2.2"}, -{"Protocol", &DMWRITE, DMT_INT, get_rule_protocol, set_rule_protocol, BBFDM_BOTH, "2.2"}, -{"DestPort", &DMWRITE, DMT_INT, get_rule_dest_port, set_rule_dest_port, BBFDM_BOTH, "2.2"}, -{"DestPortRangeMax", &DMWRITE, DMT_INT, get_rule_dest_port_range_max, set_rule_dest_port_range_max, BBFDM_BOTH, "2.2"}, -{"SourcePort", &DMWRITE, DMT_INT, get_rule_source_port, set_rule_source_port, BBFDM_BOTH, "2.2"}, -{"SourcePortRangeMax", &DMWRITE, DMT_INT, get_rule_source_port_range_max, set_rule_source_port_range_max, BBFDM_BOTH, "2.2"}, +{"IPVersion", &DMRule, DMT_INT, get_rule_i_p_version, set_rule_i_p_version, BBFDM_BOTH, "2.2"}, +{"DestIP", &DMRule, DMT_STRING, get_rule_dest_ip, set_rule_dest_ip, BBFDM_BOTH, "2.2"}, +{"DestMask", &DMRule, DMT_STRING, get_rule_dest_mask, set_rule_dest_mask, BBFDM_BOTH, "2.2"}, +{"SourceIP", &DMRule, DMT_STRING, get_rule_source_ip, set_rule_source_ip, BBFDM_BOTH, "2.2"}, +{"SourceMask", &DMRule, DMT_STRING, get_rule_source_mask, set_rule_source_mask, BBFDM_BOTH, "2.2"}, +{"Protocol", &DMRule, DMT_INT, get_rule_protocol, set_rule_protocol, BBFDM_BOTH, "2.2"}, +{"DestPort", &DMRule, DMT_INT, get_rule_dest_port, set_rule_dest_port, BBFDM_BOTH, "2.2"}, +{"DestPortRangeMax", &DMRule, DMT_INT, get_rule_dest_port_range_max, set_rule_dest_port_range_max, BBFDM_BOTH, "2.2"}, +{"SourcePort", &DMRule, DMT_INT, get_rule_source_port, set_rule_source_port, BBFDM_BOTH, "2.2"}, +{"SourcePortRangeMax", &DMRule, DMT_INT, get_rule_source_port_range_max, set_rule_source_port_range_max, BBFDM_BOTH, "2.2"}, {0} }; diff --git a/dmtree/tr181/ip.c b/dmtree/tr181/ip.c index ff58529b..b0eff3d3 100644 --- a/dmtree/tr181/ip.c +++ b/dmtree/tr181/ip.c @@ -67,6 +67,70 @@ static int get_ip_iface_sysfs(const struct uci_section *data, const char *name, return get_net_iface_sysfs(section_name((struct uci_section *)data), name, value); } +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_firewall_zone_section(char *s_name) +{ + struct uci_section *s = NULL; + char zone_name[32] = {0}; + char *input = NULL; + char *output = NULL; + char *forward = NULL; + + snprintf(zone_name, sizeof(zone_name), "zone_%s", s_name); + + 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, zone_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 void remove_unused_firewall_zone_sections(void) +{ + struct uci_section *s = NULL, *stmp = NULL; + + uci_foreach_sections_safe("firewall", "zone", stmp, s) { + struct uci_section *dmmap_section = NULL; + char *zone_added = NULL; + char *name = NULL; + + get_dmmap_section_of_config_section("dmmap_firewall", "zone", section_name(s), &dmmap_section); + dmuci_get_value_by_section_string(dmmap_section, "added_by_controller", &zone_added); + if (zone_added && strcmp(zone_added, "1") == 0) + continue; + + dmuci_get_value_by_section_string(s, "name", &name); + if (!get_origin_section_from_config("network", "interface", name)) + dmuci_delete_by_section(s, NULL, NULL); + } +} + +static void add_network_to_firewall_zone_network_list(char *zone_name, char *interface_name) +{ + struct uci_section *s = NULL; + + uci_foreach_option_eq("firewall", "zone", "name", zone_name, s) { + dmuci_add_list_value_by_section(s, "network", interface_name); + break; + } +} + static bool proc_intf6_line_exists(char *parent_section, char *address) { struct uci_section *s = NULL; @@ -411,6 +475,11 @@ static int delete_ip_intertace_instance(struct uci_section *s) } } + /* Remove Firewall zone section related to this "IP.Interface." object */ + uci_foreach_option_eq_safe("firewall", "zone", "name", section_name(int_ss), stmp, ss) { + dmuci_delete_by_section(ss, NULL, NULL); + } + /* remove interface section */ dmuci_delete_by_section(int_ss, NULL, NULL); } @@ -547,12 +616,17 @@ static int browseIPInterfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void strchr(device, '@')) continue; + // check if firewall zone exists + if (!firewall_zone_exists(section_name(p->config_section))) + create_firewall_zone_section(section_name(p->config_section)); + inst = handle_instance(dmctx, parent_node, p->dmmap_section, "ip_int_instance", "ip_int_alias"); if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p->config_section, inst) == DM_STOP) break; } free_dmmap_config_dup_list(&dup_list); + remove_unused_firewall_zone_sections(); return 0; } @@ -778,10 +852,14 @@ static int addObjIPInterface(char *refparam, struct dmctx *ctx, void *data, char snprintf(ip_name, sizeof(ip_name), "iface%s", *instance); + // Network interface section dmuci_set_value("network", ip_name, "", "interface"); dmuci_set_value("network", ip_name, "proto", "none"); dmuci_set_value("network", ip_name, "disabled", "1"); + // Firewall zone section + create_firewall_zone_section(ip_name); + dmuci_add_section_bbfdm("dmmap_network", "interface", &dmmap_ip_interface); dmuci_set_value_by_section(dmmap_ip_interface, "section_name", ip_name); dmuci_set_value_by_section(dmmap_ip_interface, "ip_int_instance", *instance); @@ -831,6 +909,9 @@ static int addObjIPInterfaceIPv4Address(char *refparam, struct dmctx *ctx, void dmuci_set_value("network", ipv4_name, "", "interface"); dmuci_set_value("network", ipv4_name, "device", device_buf); dmuci_set_value("network", ipv4_name, "proto", "static"); + + // Firewall : add this new interface to zone->network list + add_network_to_firewall_zone_network_list(section_name((struct uci_section *)data), ipv4_name); } else { char *proto; @@ -914,6 +995,9 @@ static int addObjIPInterfaceIPv6Address(char *refparam, struct dmctx *ctx, void dmuci_set_value("network", ipv6_name, "proto", "static"); dmuci_set_value("network", ipv6_name, "ip6addr", "::"); + // Firewall : add this new interface to zone->network list + add_network_to_firewall_zone_network_list(section_name((struct uci_section *)data), ipv6_name); + dmuci_add_section_bbfdm("dmmap_network_ipv6", "intf_ipv6", &dmmap_ip_interface_ipv6); dmuci_set_value_by_section(dmmap_ip_interface_ipv6, "parent_section", section_name((struct uci_section *)data)); dmuci_set_value_by_section(dmmap_ip_interface_ipv6, "section_name", ipv6_name); @@ -943,6 +1027,9 @@ static int addObjIPInterfaceIPv6Prefix(char *refparam, struct dmctx *ctx, void * dmuci_set_value("network", ipv6_prefix_name, "proto", "static"); dmuci_set_value("network", ipv6_prefix_name, "ip6prefix", "::/64"); + // Firewall : add this new interface to zone->network list + add_network_to_firewall_zone_network_list(section_name((struct uci_section *)data), ipv6_prefix_name); + dmuci_add_section_bbfdm("dmmap_network_ipv6_prefix", "intf_ipv6_prefix", &dmmap_ip_interface_ipv6_prefix); dmuci_set_value_by_section(dmmap_ip_interface_ipv6_prefix, "parent_section", section_name((struct uci_section *)data)); dmuci_set_value_by_section(dmmap_ip_interface_ipv6_prefix, "section_name", ipv6_prefix_name); diff --git a/dmtree/tr181/nat.c b/dmtree/tr181/nat.c index a69cd719..9c65db0a 100644 --- a/dmtree/tr181/nat.c +++ b/dmtree/tr181/nat.c @@ -63,18 +63,22 @@ static int browsePortMappingInst(struct dmctx *dmctx, DMNODE *parent_node, void static int add_NAT_InterfaceSetting(char *refparam, struct dmctx *ctx, void *data, char **instance) { struct uci_section *s = NULL, *dmmap_firewall = NULL; - char name[32]; + char zone_name[16] = {0}; + char name[16] = {0}; - snprintf(name, sizeof(name), "iface_set_%s", *instance); + 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", section_name(s)); + dmuci_set_value_by_section(dmmap_firewall, "section_name", zone_name); + dmuci_set_value_by_section(dmmap_firewall, "added_by_controller", "1"); dmuci_set_value_by_section(dmmap_firewall, "interface_setting_instance", *instance); return 0; }