uint32_t typelist = 0;
struct fw3_ipset_datatype *type;
- const char *methods[] = {
- "(bug)",
- "bitmap",
- "hash",
- "list",
- };
-
- typelist = 0;
-
list_for_each_entry(type, &ipset->datatypes, list)
{
if (i >= 3)
ipset->method = ipset_types[i].method;
warn_elem(e, "defines no storage method, assuming '%s'",
- methods[ipset->method]);
+ fw3_ipset_method_names[ipset->method]);
break;
}
if (ipset_types[i].method == ipset->method &&
ipset_types[i].types == typelist)
{
- if (!ipset->external || !*ipset->external)
+ if (!ipset->external)
{
if ((ipset_types[i].required & OPT_IPRANGE) &&
!ipset->iprange.set)
}
if (!(ipset_types[i].optional & OPT_FAMILY) &&
- ipset->family != FW3_FAMILY_ANY)
+ ipset->family != FW3_FAMILY_V4)
{
warn_elem(e, "family ignored");
- ipset->family = FW3_FAMILY_ANY;
+ ipset->family = FW3_FAMILY_V4;
}
}
INIT_LIST_HEAD(&ipset->datatypes);
+ ipset->enabled = true;
+ ipset->family = FW3_FAMILY_V4;
+
return ipset;
}
fw3_parse_options(ipset, fw3_ipset_opts, s);
+ if (ipset->external)
+ {
+ if (!*ipset->external)
+ ipset->external = NULL;
+ else if (!ipset->name)
+ ipset->name = ipset->external;
+ }
+
if (!ipset->name || !*ipset->name)
{
warn_elem(e, "must have a name assigned");
//{
// warn_elem(e, "has duplicated set name '%s'", ipset->name);
//}
+ else if (ipset->family == FW3_FAMILY_ANY)
+ {
+ warn_elem(e, "must not have family 'any'");
+ }
else if (list_empty(&ipset->datatypes))
{
warn_elem(e, "has no datatypes assigned");
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 *a;
-
- const char *methods[] = {
- "(bug)",
- "bitmap",
- "hash",
- "list",
- };
-
- const char *types[] = {
- "(bug)",
- "ip",
- "port",
- "mac",
- "net",
- "set",
- };
-
- if (ipset->external && *ipset->external)
- return;
info(" * Creating ipset %s", ipset->name);
first = true;
- fw3_pr("create %s %s", ipset->name, methods[ipset->method]);
+ fw3_pr("create %s %s", ipset->name, fw3_ipset_method_names[ipset->method]);
list_for_each_entry(type, &ipset->datatypes, list)
{
- fw3_pr("%c%s", first ? ':' : ',', types[type->type]);
+ fw3_pr("%c%s", first ? ':' : ',', fw3_ipset_type_names[type->type]);
first = false;
}
if (ipset->iprange.set)
{
- a = &ipset->iprange;
-
- if (!a->range)
- {
- inet_ntop(a->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6,
- &a->address.v6, s, sizeof(s));
-
- fw3_pr(" range %s/%u", s, a->mask);
- }
- else
- {
- inet_ntop(a->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6,
- &a->address.v6, s, sizeof(s));
-
- fw3_pr(" range %s", s);
-
- inet_ntop(a->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6,
- &a->address2.v6, s, sizeof(s));
-
- fw3_pr("-%s", s);
- }
+ fw3_pr(" range %s", fw3_address_to_string(&ipset->iprange, false));
}
else if (ipset->portrange.set)
{
ipset->portrange.port_min, ipset->portrange.port_max);
}
- if (ipset->family != FW3_FAMILY_ANY)
- fw3_pr(" family inet%s", (ipset->family == FW3_FAMILY_V4) ? "" : "6");
+ fw3_pr(" family inet%s", (ipset->family == FW3_FAMILY_V4) ? "" : "6");
if (ipset->timeout > 0)
fw3_pr(" timeout %u", ipset->timeout);
void
fw3_create_ipsets(struct fw3_state *state)
{
+ int tries;
+ bool exec = false;
struct fw3_ipset *ipset;
if (state->disable_ipsets)
return;
+ /* spawn ipsets */
+ list_for_each_entry(ipset, &state->ipsets, list)
+ {
+ if (ipset->external)
+ continue;
+
+ if (!exec)
+ {
+ exec = fw3_command_pipe(false, "ipset", "-exist", "-");
+
+ if (!exec)
+ return;
+ }
+
+ create_ipset(ipset, state);
+ }
+
+ if (exec)
+ {
+ fw3_pr("quit\n");
+ fw3_command_close();
+ }
+
+ /* wait for ipsets to appear */
list_for_each_entry(ipset, &state->ipsets, list)
- if (!hasbit(ipset->flags[0], FW3_FLAG_DELETED))
- create_ipset(ipset, state);
+ {
+ if (ipset->external)
+ continue;
- fw3_pr("quit\n");
+ for (tries = 0; !fw3_check_ipset(ipset) && tries < 10; tries++)
+ usleep(50000);
+ }
}
void
-fw3_destroy_ipsets(struct fw3_state *state, enum fw3_family family)
+fw3_destroy_ipsets(struct fw3_state *state)
{
- struct fw3_ipset *s, *tmp;
+ int tries;
+ bool exec = false;
+ struct fw3_ipset *ipset;
- list_for_each_entry_safe(s, tmp, &state->ipsets, list)
+ /* destroy ipsets */
+ list_for_each_entry(ipset, &state->ipsets, list)
{
- del(s->flags, family, family);
-
- if (fw3_no_family(s->flags[family == FW3_FAMILY_V6]))
+ if (!exec)
{
- info(" * Deleting ipset %s", s->name);
+ exec = fw3_command_pipe(false, "ipset", "-exist", "-");
- fw3_pr("flush %s\n", s->name);
- fw3_pr("destroy %s\n", s->name);
+ if (!exec)
+ return;
}
+
+ info(" * Deleting ipset %s", ipset->name);
+
+ fw3_pr("flush %s\n", ipset->name);
+ fw3_pr("destroy %s\n", ipset->name);
+ }
+
+ if (exec)
+ {
+ fw3_pr("quit\n");
+ fw3_command_close();
+ }
+
+ /* wait for ipsets to disappear */
+ list_for_each_entry(ipset, &state->ipsets, list)
+ {
+ if (ipset->external)
+ continue;
+
+ for (tries = 0; fw3_check_ipset(ipset) && tries < 10; tries++)
+ usleep(50000);
}
}
return NULL;
}
+
+bool
+fw3_check_ipset(struct fw3_ipset *set)
+{
+ bool rv = false;
+
+ socklen_t sz;
+ int s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+ struct ip_set_req_version req_ver;
+ struct ip_set_req_get_set req_name;
+
+ if (s < 0 || fcntl(s, F_SETFD, FD_CLOEXEC))
+ goto out;
+
+ sz = sizeof(req_ver);
+ req_ver.op = IP_SET_OP_VERSION;
+
+ if (getsockopt(s, SOL_IP, SO_IP_SET, &req_ver, &sz))
+ goto out;
+
+ sz = sizeof(req_name);
+ req_name.op = IP_SET_OP_GET_BYNAME;
+ req_name.version = req_ver.version;
+ snprintf(req_name.set.name, IPSET_MAXNAMELEN - 1, "%s",
+ set->external ? set->external : set->name);
+
+ if (getsockopt(s, SOL_IP, SO_IP_SET, &req_name, &sz))
+ goto out;
+
+ rv = ((sz == sizeof(req_name)) && (req_name.set.index != IPSET_INVALID_ID));
+
+out:
+ if (s >= 0)
+ close(s);
+
+ return rv;
+}