zones: make forward policy destination bound
[project/firewall3.git] / utils.c
diff --git a/utils.c b/utils.c
index fc8c201..fa4a73f 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -16,6 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#define _GNU_SOURCE
 #include "utils.h"
 #include "options.h"
 
@@ -132,6 +133,32 @@ info(const char* format, ...)
        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)
 {
@@ -198,7 +225,7 @@ __fw3_command_pipe(bool silent, const char *command, ...)
                return false;
 
        argn = 2;
-       args = malloc(argn * sizeof(arg));
+       args = calloc(argn, sizeof(arg));
 
        if (!args)
                return false;
@@ -487,7 +514,7 @@ write_zone_uci(struct uci_context *ctx, struct fw3_zone *z,
                if (!sub)
                        continue;
 
-               ptr.value = fw3_address_to_string(sub, true);
+               ptr.value = fw3_address_to_string(sub, true, false);
                uci_add_list(ctx, &ptr);
        }
 
@@ -531,9 +558,7 @@ write_ipset_uci(struct uci_context *ctx, struct fw3_ipset *s,
 
        list_for_each_entry(type, &s->datatypes, list)
        {
-               sprintf(buf, "%s_%s", type->dest ? "dst" : "src",
-                                     fw3_ipset_type_names[type->type]);
-
+               sprintf(buf, "%s_%s", type->dir, fw3_ipset_type_names[type->type]);
                ptr.o      = NULL;
                ptr.option = "match";
                ptr.value  = buf;
@@ -544,7 +569,7 @@ write_ipset_uci(struct uci_context *ctx, struct fw3_ipset *s,
        {
                ptr.o      = NULL;
                ptr.option = "iprange";
-               ptr.value  = fw3_address_to_string(&s->iprange, false);
+               ptr.value  = fw3_address_to_string(&s->iprange, false, false);
                uci_set(ctx, &ptr);
        }
 
@@ -630,44 +655,23 @@ fw3_free_object(void *obj, const void *opts)
        free(obj);
 }
 
-
-bool
-fw3_pr_rulespec(int table, int family, uint32_t *flags, uint32_t mask,
-                const struct fw3_rule_spec *r, const char *fmt, ...)
+void
+fw3_free_list(struct list_head *head)
 {
-       char buf[256];
-       bool rv = false;
+       struct list_head *entry, *tmp;
 
-       va_list ap;
-       uint32_t f = flags ? flags[family == FW3_FAMILY_V6] : 0;
-
-       if (mask)
-               f &= mask;
+       if (!head)
+               return;
 
-       for (; r->format; r++)
+       list_for_each_safe(entry, tmp, head)
        {
-               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;
+               list_del(entry);
+               free(entry);
        }
 
-       return rv;
+       free(head);
 }
 
-
 bool
 fw3_hotplug(bool add, void *zone, void *device)
 {
@@ -693,7 +697,7 @@ fw3_hotplug(bool add, void *zone, void *device)
        close(0);
        close(1);
        close(2);
-       chdir("/");
+       if (chdir("/")) {};
 
        clearenv();
        setenv("ACTION",    add ? "add" : "remove", 1);
@@ -706,3 +710,60 @@ fw3_hotplug(bool add, void *zone, void *device)
        /* unreached */
        return false;
 }
+
+int
+fw3_netmask2bitlen(int family, void *mask)
+{
+       int bits;
+       struct in_addr *v4;
+       struct in6_addr *v6;
+
+       if (family == FW3_FAMILY_V6)
+               for (bits = 0, v6 = mask;
+                    bits < 128 && (v6->s6_addr[bits / 8] << (bits % 8)) & 128;
+                    bits++);
+       else
+               for (bits = 0, v4 = mask;
+                    bits < 32 && (ntohl(v4->s_addr) << bits) & 0x80000000;
+                    bits++);
+
+       return bits;
+}
+
+bool
+fw3_bitlen2netmask(int family, int bits, void *mask)
+{
+       int i;
+       struct in_addr *v4;
+       struct in6_addr *v6;
+
+       if (family == FW3_FAMILY_V6)
+       {
+               if (bits < -128 || bits > 128)
+                       return false;
+
+               v6 = mask;
+               i = abs(bits);
+
+               memset(v6->s6_addr, 0xff, i / 8);
+               memset(v6->s6_addr + (i / 8) + 1, 0, (128 - i) / 8);
+               v6->s6_addr[i / 8] = 0xff << (8 - (i & 7));
+
+               if (bits < 0)
+                       for (i = 0; i < 16; i++)
+                               v6->s6_addr[i] = ~v6->s6_addr[i];
+       }
+       else
+       {
+               if (bits < -32 || bits > 32)
+                       return false;
+
+               v4 = mask;
+               v4->s_addr = htonl(~((1 << (32 - abs(bits))) - 1));
+
+               if (bits < 0)
+                       v4->s_addr = ~v4->s_addr;
+       }
+
+       return true;
+}