Restore iptables-save include functionality
[project/firewall3.git] / utils.c
diff --git a/utils.c b/utils.c
index 9f57e9f..ea40974 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -132,6 +132,32 @@ info(const char* format, ...)
        fprintf(stderr, "\n");
 }
 
        fprintf(stderr, "\n");
 }
 
+void *
+fw3_alloc(size_t size)
+{
+       void *mem;
+
+       mem = calloc(1, size);
+
+       if (!mem)
+               error("Out of memory while allocating %d bytes", size);
+
+       return mem;
+}
+
+char *
+fw3_strdup(const char *s)
+{
+       char *ns;
+
+       ns = strdup(s);
+
+       if (!ns)
+               error("Out of memory while duplicating string '%s'", s);
+
+       return ns;
+}
+
 const char *
 fw3_find_command(const char *cmd)
 {
 const char *
 fw3_find_command(const char *cmd)
 {
@@ -352,18 +378,33 @@ static void
 write_defaults_uci(struct uci_context *ctx, struct fw3_defaults *d,
                    struct uci_package *dest)
 {
 write_defaults_uci(struct uci_context *ctx, struct fw3_defaults *d,
                    struct uci_package *dest)
 {
-       char buf[8];
+       char buf[sizeof("0xffffffff\0")];
        struct uci_ptr ptr = { .p = dest };
 
        uci_add_section(ctx, dest, "defaults", &ptr.s);
 
        struct uci_ptr ptr = { .p = dest };
 
        uci_add_section(ctx, dest, "defaults", &ptr.s);
 
-       sprintf(buf, "%u", d->flags[0]);
+       ptr.o      = NULL;
+       ptr.option = "input";
+       ptr.value  = fw3_flag_names[d->policy_input];
+       uci_set(ctx, &ptr);
+
+       ptr.o      = NULL;
+       ptr.option = "output";
+       ptr.value  = fw3_flag_names[d->policy_output];
+       uci_set(ctx, &ptr);
+
+       ptr.o      = NULL;
+       ptr.option = "forward";
+       ptr.value  = fw3_flag_names[d->policy_forward];
+       uci_set(ctx, &ptr);
+
+       sprintf(buf, "0x%x", d->flags[0]);
        ptr.o      = NULL;
        ptr.option = "__flags_v4";
        ptr.value  = buf;
        uci_set(ctx, &ptr);
 
        ptr.o      = NULL;
        ptr.option = "__flags_v4";
        ptr.value  = buf;
        uci_set(ctx, &ptr);
 
-       sprintf(buf, "%u", d->flags[1]);
+       sprintf(buf, "0x%x", d->flags[1]);
        ptr.o      = NULL;
        ptr.option = "__flags_v6";
        ptr.value  = buf;
        ptr.o      = NULL;
        ptr.option = "__flags_v6";
        ptr.value  = buf;
@@ -378,9 +419,7 @@ write_zone_uci(struct uci_context *ctx, struct fw3_zone *z,
        struct fw3_address *sub;
        enum fw3_family fam = FW3_FAMILY_ANY;
 
        struct fw3_address *sub;
        enum fw3_family fam = FW3_FAMILY_ANY;
 
-       char addr[INET6_ADDRSTRLEN];
-       char buf[INET6_ADDRSTRLEN * 2 + 2];
-       char *p;
+       char *p, buf[34];
 
        struct uci_ptr ptr = { .p = dest };
 
 
        struct uci_ptr ptr = { .p = dest };
 
@@ -457,7 +496,10 @@ write_zone_uci(struct uci_context *ctx, struct fw3_zone *z,
                if (dev->invert)
                        p += sprintf(p, "!");
 
                if (dev->invert)
                        p += sprintf(p, "!");
 
-               p += sprintf(p, "%s", dev->name);
+               if (*dev->network)
+                       p += sprintf(p, "%s@%s", dev->name, dev->network);
+               else
+                       p += sprintf(p, "%s", dev->name);
 
                ptr.value = buf;
                uci_add_list(ctx, &ptr);
 
                ptr.value = buf;
                uci_add_list(ctx, &ptr);
@@ -471,51 +513,84 @@ write_zone_uci(struct uci_context *ctx, struct fw3_zone *z,
                if (!sub)
                        continue;
 
                if (!sub)
                        continue;
 
-               p = buf;
-
-               if (sub->invert)
-                       p += sprintf(p, "!");
-
-               inet_ntop(sub->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6,
-                                 &sub->address.v4, addr, sizeof(addr));
-
-               p += sprintf(p, "%s", addr);
-
-               if (sub->range)
-               {
-                       inet_ntop(sub->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6,
-                                 &sub->address2.v4, addr, sizeof(addr));
-
-                       p += sprintf(p, "-%s", addr);
-               }
-               else
-               {
-                       p += sprintf(p, "/%u", sub->mask);
-               }
-
-               ptr.value = buf;
+               ptr.value = fw3_address_to_string(sub, true);
                uci_add_list(ctx, &ptr);
        }
 
                uci_add_list(ctx, &ptr);
        }
 
-       sprintf(buf, "%u", z->flags[0]);
+       sprintf(buf, "0x%x", z->flags[0]);
        ptr.o      = NULL;
        ptr.option = "__flags_v4";
        ptr.value  = buf;
        uci_set(ctx, &ptr);
 
        ptr.o      = NULL;
        ptr.option = "__flags_v4";
        ptr.value  = buf;
        uci_set(ctx, &ptr);
 
-       sprintf(buf, "%u", z->flags[1]);
+       sprintf(buf, "0x%x", z->flags[1]);
        ptr.o      = NULL;
        ptr.option = "__flags_v6";
        ptr.value  = buf;
        uci_set(ctx, &ptr);
 }
 
        ptr.o      = NULL;
        ptr.option = "__flags_v6";
        ptr.value  = buf;
        uci_set(ctx, &ptr);
 }
 
+static void
+write_ipset_uci(struct uci_context *ctx, struct fw3_ipset *s,
+                struct uci_package *dest)
+{
+       struct fw3_ipset_datatype *type;
+
+       char buf[sizeof("65535-65535\0")];
+
+       struct uci_ptr ptr = { .p = dest };
+
+       if (!s->enabled || s->external)
+               return;
+
+       uci_add_section(ctx, dest, "ipset", &ptr.s);
+
+       ptr.o      = NULL;
+       ptr.option = "name";
+       ptr.value  = s->name;
+       uci_set(ctx, &ptr);
+
+       ptr.o      = NULL;
+       ptr.option = "storage";
+       ptr.value  = fw3_ipset_method_names[s->method];
+       uci_set(ctx, &ptr);
+
+       list_for_each_entry(type, &s->datatypes, list)
+       {
+               sprintf(buf, "%s_%s", type->dest ? "dst" : "src",
+                                     fw3_ipset_type_names[type->type]);
+
+               ptr.o      = NULL;
+               ptr.option = "match";
+               ptr.value  = buf;
+               uci_add_list(ctx, &ptr);
+       }
+
+       if (s->iprange.set)
+       {
+               ptr.o      = NULL;
+               ptr.option = "iprange";
+               ptr.value  = fw3_address_to_string(&s->iprange, false);
+               uci_set(ctx, &ptr);
+       }
+
+       if (s->portrange.set)
+       {
+               sprintf(buf, "%u-%u", s->portrange.port_min, s->portrange.port_max);
+               ptr.o      = NULL;
+               ptr.option = "portrange";
+               ptr.value  = buf;
+               uci_set(ctx, &ptr);
+       }
+}
+
 void
 fw3_write_statefile(void *state)
 {
        FILE *sf;
        struct fw3_state *s = state;
        struct fw3_zone *z;
 void
 fw3_write_statefile(void *state)
 {
        FILE *sf;
        struct fw3_state *s = state;
        struct fw3_zone *z;
+       struct fw3_ipset *i;
 
        struct uci_package *p;
 
 
        struct uci_package *p;
 
@@ -546,10 +621,14 @@ fw3_write_statefile(void *state)
                        list_for_each_entry(z, &s->zones, list)
                                write_zone_uci(s->uci, z, p);
 
                        list_for_each_entry(z, &s->zones, list)
                                write_zone_uci(s->uci, z, p);
 
+                       list_for_each_entry(i, &s->ipsets, list)
+                               write_ipset_uci(s->uci, i, p);
+
                        uci_export(s->uci, sf, p, true);
                        uci_unload(s->uci, p);
                }
 
                        uci_export(s->uci, sf, p, true);
                        uci_unload(s->uci, p);
                }
 
+               fsync(fileno(sf));
                fclose(sf);
        }
 }
                fclose(sf);
        }
 }
@@ -579,49 +658,12 @@ fw3_free_object(void *obj, const void *opts)
 
 
 bool
 
 
 bool
-fw3_pr_rulespec(int table, int family, uint32_t *flags, uint32_t mask,
-                const struct fw3_rule_spec *r, const char *fmt, ...)
-{
-       char buf[256];
-       bool rv = false;
-
-       va_list ap;
-       uint32_t f = flags ? flags[family == FW3_FAMILY_V6] : 0;
-
-       if (mask)
-               f &= mask;
-
-       for (; r->format; r++)
-       {
-               if (!fw3_is_family(r, family))
-                       continue;
-
-               if (r->table != table)
-                       continue;
-
-               if ((r->flag != 0) && !hasbit(f, r->flag))
-                       continue;
-
-               va_start(ap, fmt);
-               vsnprintf(buf, sizeof(buf), r->format, ap);
-               va_end(ap);
-
-               fw3_pr(fmt, buf);
-
-               rv = true;
-       }
-
-       return rv;
-}
-
-
-bool
 fw3_hotplug(bool add, void *zone, void *device)
 {
        struct fw3_zone *z = zone;
        struct fw3_device *d = device;
 
 fw3_hotplug(bool add, void *zone, void *device)
 {
        struct fw3_zone *z = zone;
        struct fw3_device *d = device;
 
-       if (!d->network)
+       if (!*d->network)
                return false;
 
        switch (fork())
                return false;
 
        switch (fork())
@@ -645,7 +687,7 @@ fw3_hotplug(bool add, void *zone, void *device)
        clearenv();
        setenv("ACTION",    add ? "add" : "remove", 1);
        setenv("ZONE",      z->name,                1);
        clearenv();
        setenv("ACTION",    add ? "add" : "remove", 1);
        setenv("ZONE",      z->name,                1);
-       setenv("INTERFACE", d->network->name,       1);
+       setenv("INTERFACE", d->network,             1);
        setenv("DEVICE",    d->name,                1);
 
        execl(FW3_HOTPLUG, FW3_HOTPLUG, "firewall", NULL);
        setenv("DEVICE",    d->name,                1);
 
        execl(FW3_HOTPLUG, FW3_HOTPLUG, "firewall", NULL);