X-Git-Url: http://git.archive.openwrt.org/?p=project%2Ffirewall3.git;a=blobdiff_plain;f=ipsets.c;h=eb37d0a82e6a831462ca19bf4825640b07c2b02a;hp=5e0d61f9c3f956c23c542b533fdda8884e31b70f;hb=b64f6ca3d43dabc651b829fc7c71d95ed791aee2;hpb=bb6873d86322a66bc01fc4195512ba5d2c78bddb diff --git a/ipsets.c b/ipsets.c index 5e0d61f..eb37d0a 100644 --- a/ipsets.c +++ b/ipsets.c @@ -19,14 +19,16 @@ #include "ipsets.h" -static struct fw3_option ipset_opts[] = { +const struct fw3_option fw3_ipset_opts[] = { + FW3_OPT("enabled", bool, ipset, enabled), + FW3_OPT("name", string, ipset, name), FW3_OPT("family", family, ipset, family), FW3_OPT("storage", ipset_method, ipset, method), FW3_LIST("match", ipset_datatype, ipset, datatypes), - FW3_LIST("iprange", address, ipset, iprange), + FW3_OPT("iprange", address, ipset, iprange), FW3_OPT("portrange", port, ipset, portrange), FW3_OPT("netmask", int, ipset, netmask), @@ -35,6 +37,8 @@ static struct fw3_option ipset_opts[] = { FW3_OPT("timeout", int, ipset, timeout), FW3_OPT("external", string, ipset, external), + + { } }; #define T(m, t1, t2, t3, r, o) \ @@ -42,27 +46,41 @@ static struct fw3_option ipset_opts[] = { FW3_IPSET_TYPE_##t1 | (FW3_IPSET_TYPE_##t2 << 8) | (FW3_IPSET_TYPE_##t3 << 16), \ r, o } -static struct fw3_ipset_settype ipset_types[] = { - T(BITMAP, IP, UNSPEC, UNSPEC, FW3_IPSET_OPT_IPRANGE, - FW3_IPSET_OPT_NETMASK), - T(BITMAP, IP, MAC, UNSPEC, FW3_IPSET_OPT_IPRANGE, 0), - T(BITMAP, PORT, UNSPEC, UNSPEC, FW3_IPSET_OPT_PORTRANGE, 0), +enum ipset_optflag { + OPT_IPRANGE = (1 << 0), + OPT_PORTRANGE = (1 << 1), + OPT_NETMASK = (1 << 2), + OPT_HASHSIZE = (1 << 3), + OPT_MAXELEM = (1 << 4), + OPT_FAMILY = (1 << 5), +}; + +struct ipset_type { + enum fw3_ipset_method method; + uint32_t types; + uint8_t required; + uint8_t optional; +}; + +static struct ipset_type ipset_types[] = { + T(BITMAP, IP, UNSPEC, UNSPEC, OPT_IPRANGE, OPT_NETMASK), + T(BITMAP, IP, MAC, UNSPEC, OPT_IPRANGE, 0), + T(BITMAP, PORT, UNSPEC, UNSPEC, OPT_PORTRANGE, 0), T(HASH, IP, UNSPEC, UNSPEC, 0, - FW3_IPSET_OPT_FAMILY | FW3_IPSET_OPT_HASHSIZE | FW3_IPSET_OPT_MAXELEM | - FW3_IPSET_OPT_NETMASK), + OPT_FAMILY | OPT_HASHSIZE | OPT_MAXELEM | OPT_NETMASK), T(HASH, NET, UNSPEC, UNSPEC, 0, - FW3_IPSET_OPT_FAMILY | FW3_IPSET_OPT_HASHSIZE | FW3_IPSET_OPT_MAXELEM), + OPT_FAMILY | OPT_HASHSIZE | OPT_MAXELEM), T(HASH, IP, PORT, UNSPEC, 0, - FW3_IPSET_OPT_FAMILY | FW3_IPSET_OPT_HASHSIZE | FW3_IPSET_OPT_MAXELEM), + OPT_FAMILY | OPT_HASHSIZE | OPT_MAXELEM), T(HASH, NET, PORT, UNSPEC, 0, - FW3_IPSET_OPT_FAMILY | FW3_IPSET_OPT_HASHSIZE | FW3_IPSET_OPT_MAXELEM), + OPT_FAMILY | OPT_HASHSIZE | OPT_MAXELEM), T(HASH, IP, PORT, IP, 0, - FW3_IPSET_OPT_FAMILY | FW3_IPSET_OPT_HASHSIZE | FW3_IPSET_OPT_MAXELEM), + OPT_FAMILY | OPT_HASHSIZE | OPT_MAXELEM), T(HASH, IP, PORT, NET, 0, - FW3_IPSET_OPT_FAMILY | FW3_IPSET_OPT_HASHSIZE | FW3_IPSET_OPT_MAXELEM), + OPT_FAMILY | OPT_HASHSIZE | OPT_MAXELEM), - T(LIST, SET, UNSPEC, UNSPEC, 0, FW3_IPSET_OPT_MAXELEM), + T(LIST, SET, UNSPEC, UNSPEC, 0, OPT_MAXELEM), }; @@ -119,56 +137,56 @@ check_types(struct uci_element *e, struct fw3_ipset *ipset) { if (!ipset->external || !*ipset->external) { - if ((ipset_types[i].required & FW3_IPSET_OPT_IPRANGE) && - list_empty(&ipset->iprange)) + if ((ipset_types[i].required & OPT_IPRANGE) && + !ipset->iprange.set) { warn_elem(e, "requires an ip range"); return false; } - if ((ipset_types[i].required & FW3_IPSET_OPT_PORTRANGE) && + if ((ipset_types[i].required & OPT_PORTRANGE) && !ipset->portrange.set) { warn_elem(e, "requires a port range"); return false; } - if (!(ipset_types[i].required & FW3_IPSET_OPT_IPRANGE) && - !list_empty(&ipset->iprange)) + if (!(ipset_types[i].required & OPT_IPRANGE) && + ipset->iprange.set) { warn_elem(e, "iprange ignored"); - fw3_free_list(&ipset->iprange); + ipset->iprange.set = false; } - if (!(ipset_types[i].required & FW3_IPSET_OPT_PORTRANGE) && + if (!(ipset_types[i].required & OPT_PORTRANGE) && ipset->portrange.set) { warn_elem(e, "portrange ignored"); - memset(&ipset->portrange, 0, sizeof(ipset->portrange)); + ipset->portrange.set = false; } - if (!(ipset_types[i].optional & FW3_IPSET_OPT_NETMASK) && + if (!(ipset_types[i].optional & OPT_NETMASK) && ipset->netmask > 0) { warn_elem(e, "netmask ignored"); ipset->netmask = 0; } - if (!(ipset_types[i].optional & FW3_IPSET_OPT_HASHSIZE) && + if (!(ipset_types[i].optional & OPT_HASHSIZE) && ipset->hashsize > 0) { warn_elem(e, "hashsize ignored"); ipset->hashsize = 0; } - if (!(ipset_types[i].optional & FW3_IPSET_OPT_MAXELEM) && + if (!(ipset_types[i].optional & OPT_MAXELEM) && ipset->maxelem > 0) { warn_elem(e, "maxelem ignored"); ipset->maxelem = 0; } - if (!(ipset_types[i].optional & FW3_IPSET_OPT_FAMILY) && + if (!(ipset_types[i].optional & OPT_FAMILY) && ipset->family != FW3_FAMILY_ANY) { warn_elem(e, "family ignored"); @@ -184,6 +202,25 @@ check_types(struct uci_element *e, struct fw3_ipset *ipset) return false; } +struct fw3_ipset * +fw3_alloc_ipset(void) +{ + struct fw3_ipset *ipset; + + ipset = malloc(sizeof(*ipset)); + + if (!ipset) + return NULL; + + memset(ipset, 0, sizeof(*ipset)); + + INIT_LIST_HEAD(&ipset->datatypes); + + ipset->enabled = true; + + return ipset; +} + void fw3_load_ipsets(struct fw3_state *state, struct uci_package *p) { @@ -203,17 +240,12 @@ fw3_load_ipsets(struct fw3_state *state, struct uci_package *p) if (strcmp(s->type, "ipset")) continue; - ipset = malloc(sizeof(*ipset)); + ipset = fw3_alloc_ipset(); if (!ipset) continue; - memset(ipset, 0, sizeof(*ipset)); - - INIT_LIST_HEAD(&ipset->datatypes); - INIT_LIST_HEAD(&ipset->iprange); - - fw3_parse_options(ipset, ipset_opts, ARRAY_SIZE(ipset_opts), s); + fw3_parse_options(ipset, fw3_ipset_opts, s); if (!ipset->name || !*ipset->name) { @@ -239,13 +271,11 @@ fw3_load_ipsets(struct fw3_state *state, struct uci_package *p) static void -create_ipset(struct fw3_ipset *ipset) +create_ipset(struct fw3_ipset *ipset, struct fw3_state *state) { bool first = true; - char s[INET6_ADDRSTRLEN]; struct fw3_ipset_datatype *type; - struct fw3_address *a1, *a2; const char *methods[] = { "(bug)", @@ -266,7 +296,7 @@ create_ipset(struct fw3_ipset *ipset) if (ipset->external && *ipset->external) return; - info("Creating ipset %s", ipset->name); + info(" * Creating ipset %s", ipset->name); first = true; fw3_pr("create %s %s", ipset->name, methods[ipset->method]); @@ -277,32 +307,9 @@ create_ipset(struct fw3_ipset *ipset) first = false; } - if (!list_empty(&ipset->iprange)) + if (ipset->iprange.set) { - a1 = list_first_entry(&ipset->iprange, struct fw3_address, list); - a2 = list_last_entry(&ipset->iprange, struct fw3_address, list); - - if (a1 == a2) - { - inet_ntop(a1->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, - &a1->address.v6, s, sizeof(s)); - - fw3_pr(" range %s/%u", s, a1->mask); - } - else if (a1->family == a2->family && - fw3_is_family(ipset, a1->family) && - fw3_is_family(ipset, a2->family)) - { - inet_ntop(a1->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, - &a1->address.v6, s, sizeof(s)); - - fw3_pr(" range %s", s); - - inet_ntop(a2->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, - &a2->address.v6, s, sizeof(s)); - - fw3_pr("-%s", s); - } + fw3_pr(" range %s", fw3_address_to_string(&ipset->iprange, false)); } else if (ipset->portrange.set) { @@ -328,29 +335,8 @@ create_ipset(struct fw3_ipset *ipset) fw3_pr("\n"); } -static bool -ipset_loaded(struct list_head *statefile, const char *name) -{ - struct fw3_statefile_entry *e; - int mask = (1 << FW3_FAMILY_V4) | (1 << FW3_FAMILY_V6); - - if (!statefile) - return false; - - list_for_each_entry(e, statefile, list) - { - if (e->type != FW3_TYPE_IPSET) - continue; - - if (!strcmp(e->name, name) && (e->flags[0] & mask)) - return true; - } - - return false; -} - void -fw3_create_ipsets(struct fw3_state *state, struct list_head *statefile) +fw3_create_ipsets(struct fw3_state *state) { struct fw3_ipset *ipset; @@ -358,66 +344,42 @@ fw3_create_ipsets(struct fw3_state *state, struct list_head *statefile) return; list_for_each_entry(ipset, &state->ipsets, list) - if (!ipset_loaded(statefile, ipset->name)) - create_ipset(ipset); + create_ipset(ipset, state); fw3_pr("quit\n"); } void -fw3_destroy_ipsets(struct fw3_state *state, struct list_head *statefile) +fw3_destroy_ipsets(struct fw3_state *state) { struct fw3_ipset *s; - struct fw3_statefile_entry *e; - int mask = (1 << FW3_FAMILY_V4) | (1 << FW3_FAMILY_V6); - - if (!statefile) - return; - list_for_each_entry(e, statefile, list) + list_for_each_entry(s, &state->ipsets, list) { - if (e->type != FW3_TYPE_IPSET) - continue; - - if (!hasbit(state->defaults.flags, FW3_FAMILY_V4)) - delbit(e->flags[0], FW3_FAMILY_V4); - - if (!hasbit(state->defaults.flags, FW3_FAMILY_V6)) - delbit(e->flags[0], FW3_FAMILY_V6); - - if ((s = fw3_lookup_ipset(state, e->name)) != NULL) - s->flags = e->flags[0]; + info(" * Deleting ipset %s", s->name); - if (!(e->flags[0] & mask)) - { - info("Deleting ipset %s", e->name); - - fw3_pr("flush %s\n", e->name); - fw3_pr("destroy %s\n", e->name); - } + fw3_pr("flush %s\n", s->name); + fw3_pr("destroy %s\n", s->name); } -} -void -fw3_free_ipset(struct fw3_ipset *ipset) -{ - fw3_free_list(&ipset->datatypes); - fw3_free_list(&ipset->iprange); - - free(ipset); + fw3_pr("quit\n"); } struct fw3_ipset * fw3_lookup_ipset(struct fw3_state *state, const char *name) { - struct fw3_ipset *ipset; + struct fw3_ipset *s; if (list_empty(&state->ipsets)) return NULL; - list_for_each_entry(ipset, &state->ipsets, list) - if (!strcmp(ipset->name, name)) - return ipset; + list_for_each_entry(s, &state->ipsets, list) + { + if (strcmp(s->name, name)) + continue; + + return s; + } return NULL; }