firewall3: check the return value of fw3_parse_options()
[project/firewall3.git] / snats.c
diff --git a/snats.c b/snats.c
index 1e01192..fad6008 100644 (file)
--- a/snats.c
+++ b/snats.c
@@ -1,7 +1,7 @@
 /*
  * firewall3 - 3rd OpenWrt UCI firewall implementation
  *
- *   Copyright (C) 2014 Jo-Philipp Wich <jow@openwrt.org>
+ *   Copyright (C) 2014 Jo-Philipp Wich <jo@mein.io>
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -104,32 +104,65 @@ check_families(struct uci_element *e, struct fw3_snat *r)
        return true;
 }
 
+
+static struct fw3_snat*
+alloc_snat(struct fw3_state *state)
+{
+       struct fw3_snat *snat = calloc(1, sizeof(*snat));
+
+       if (snat) {
+               INIT_LIST_HEAD(&snat->proto);
+               list_add_tail(&snat->list, &state->snats);
+               snat->enabled = true;
+       }
+
+       return snat;
+}
+
+
 void
-fw3_load_snats(struct fw3_state *state, struct uci_package *p)
+fw3_load_snats(struct fw3_state *state, struct uci_package *p, struct blob_attr *a)
 {
        struct uci_section *s;
        struct uci_element *e;
-       struct fw3_snat *snat;
+       struct fw3_snat *snat, *n;
+       struct blob_attr *rule, *opt;
+       unsigned rem, orem;
 
        INIT_LIST_HEAD(&state->snats);
 
-       uci_foreach_element(&p->sections, e)
-       {
-               s = uci_to_section(e);
+       blob_for_each_attr(rule, a, rem) {
+               const char *type = NULL;
+               const char *name = "ubus rule";
+               blobmsg_for_each_attr(opt, rule, orem)
+                       if (!strcmp(blobmsg_name(opt), "type"))
+                               type = blobmsg_get_string(opt);
+                       else if (!strcmp(blobmsg_name(opt), "name"))
+                               name = blobmsg_get_string(opt);
 
-               if (strcmp(s->type, "nat"))
+               if (!type || strcmp(type, "nat"))
                        continue;
 
-               snat = malloc(sizeof(*snat));
+               if (!(snat = alloc_snat(state)))
+                       continue;
 
-               if (!snat)
+               if (!fw3_parse_blob_options(snat, fw3_snat_opts, rule, name))
+               {
+                       fprintf(stderr, "%s skipped due to invalid options\n", name);
+                       fw3_free_snat(snat);
                        continue;
+               }
+       }
 
-               memset(snat, 0, sizeof(*snat));
+       uci_foreach_element(&p->sections, e)
+       {
+               s = uci_to_section(e);
 
-               INIT_LIST_HEAD(&snat->proto);
+               if (strcmp(s->type, "nat"))
+                       continue;
 
-               snat->enabled = true;
+               if (!(snat = alloc_snat(state)))
+                       continue;
 
                if (!fw3_parse_options(snat, fw3_snat_opts, s))
                {
@@ -137,7 +170,10 @@ fw3_load_snats(struct fw3_state *state, struct uci_package *p)
                        fw3_free_snat(snat);
                        continue;
                }
+       }
 
+       list_for_each_entry_safe(snat, n, &state->snats, list)
+       {
                if (!snat->enabled)
                {
                        fw3_free_snat(snat);
@@ -216,12 +252,7 @@ fw3_load_snats(struct fw3_state *state, struct uci_package *p)
                }
 
                if (snat->_src)
-               {
                        set(snat->_src->flags, FW3_FAMILY_V4, FW3_FLAG_SNAT);
-                       snat->_src->conntrack = true;
-               }
-
-               list_add_tail(&snat->list, &state->snats);
        }
 }
 
@@ -231,7 +262,7 @@ append_chain(struct fw3_ipt_rule *r, struct fw3_snat *snat)
        if (snat->_src)
                fw3_ipt_rule_append(r, "zone_%s_postrouting", snat->src.name);
        else
-               fw3_ipt_rule_append(r, "delegate_postrouting");
+               fw3_ipt_rule_append(r, "POSTROUTING");
 }
 
 static void