Ticket refs #6554: newly created IP.Interface.{i}. can not be used by Firewall rules

This commit is contained in:
Amin Ben Ramdhane 2022-01-12 22:24:24 +01:00
parent 52e6a80306
commit 41c3384262
3 changed files with 190 additions and 32 deletions

View file

@ -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}
};

View file

@ -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);

View file

@ -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;
}