contrib: remove abandonned projects
[project/luci.git] / contrib / fwd / src / fwd_config.c
diff --git a/contrib/fwd/src/fwd_config.c b/contrib/fwd/src/fwd_config.c
deleted file mode 100644 (file)
index 320e9ff..0000000
+++ /dev/null
@@ -1,987 +0,0 @@
-/*
- * fwd - OpenWrt firewall daemon - config parsing
- *
- *   Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
- *
- * The fwd program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * The fwd program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with the fwd program. If not, see http://www.gnu.org/licenses/.
- */
-
-
-#include "fwd.h"
-#include "fwd_addr.h"
-#include "fwd_config.h"
-#include "fwd_utils.h"
-
-#include "ucix.h"
-
-
-#define fwd_read_error(...) do { \
-       fwd_log_err(__VA_ARGS__);    \
-       return;                      \
-} while(0)
-
-
-/*
- * Parse helpers
- */
-static int
-fwd_read_policy(struct uci_context *uci, const char *s, const char *o)
-{
-       const char *val = ucix_get_option(uci, "firewall", s, o);
-
-       if( val != NULL )
-       {
-               switch( val[0] )
-               {
-                       case 'D':
-                       case 'd':
-                               return FWD_P_DROP;
-
-                       case 'R':
-                       case 'r':
-                               return FWD_P_REJECT;
-
-                       case 'A':
-                       case 'a':
-                               return FWD_P_ACCEPT;
-               }
-       }
-
-       return FWD_P_UNSPEC;
-}
-
-static int
-fwd_read_bool(struct uci_context *uci, const char *s, const char *o, int d)
-{
-       const char *val = ucix_get_option(uci, "firewall", s, o);
-
-       if( val != NULL )
-       {
-               if( !strcmp(val, "yes") || !strcmp(val, "true") || !strcmp(val, "1") )
-                       return 1;
-               else
-                       return 0;
-       }
-
-       return d;
-}
-
-static unsigned int
-fwd_read_uint(struct uci_context *uci, const char *s, const char *o, unsigned int d)
-{
-       const char *val = ucix_get_option(uci, "firewall", s, o);
-
-       if( val != NULL )
-       {
-               return atoi(val);
-       }
-
-       return d;
-}
-
-static int
-fwd_read_cidr(struct uci_context *uci, const char *s, const char *o, struct fwd_cidr **c)
-{
-       const char *val = ucix_get_option(uci, "firewall", s, o);
-       char ip[32], prefix[32];
-       struct in_addr ina;
-
-       memset(ip, 0, 32);
-       memset(prefix, 0, 32);
-
-       if( val == NULL )
-       {
-               return 0;
-       }
-       else if( (strlen(val) < 32) && (sscanf(val, "%[^/]/%s", ip, prefix) > 0) )
-       {
-               if( !(*c = fwd_alloc_ptr(struct fwd_cidr)) )
-                       goto inval;
-
-               if( inet_aton(ip, &ina) )
-               {
-                       (*c)->addr.s_addr = ina.s_addr;
-
-                       if( strchr(prefix, '.') )
-                       {
-                               if( inet_aton(prefix, &ina) )
-                               {
-                                       (*c)->prefix = 32;
-                                       ina.s_addr = ntohl(ina.s_addr);
-
-                                       while( !(ina.s_addr & 1) )
-                                       {
-                                               ina.s_addr >>= 1;
-                                               (*c)->prefix--;
-                                       }
-                               }
-                               else
-                               {
-                                       goto inval;
-                               }
-                       }
-                       else
-                       {
-                               (*c)->prefix = prefix[0] ? atoi(prefix) : 32;
-
-                               if( ((*c)->prefix < 0) || ((*c)->prefix > 32) )
-                               {
-                                       goto inval;
-                               }
-                       }
-
-                       return 0;
-               }
-       }
-
-       inval:
-       fwd_free_ptr(*c);
-       return -1;
-}
-
-static int
-fwd_read_mac(struct uci_context *uci, const char *s, const char *o, struct fwd_mac **m)
-{
-       const char *val = ucix_get_option(uci, "firewall", s, o);
-
-       if( val == NULL )
-       {
-               return 0;
-       }
-       else
-       {
-               if( (*m = fwd_alloc_ptr(struct fwd_mac)) != NULL )
-               {
-                       unsigned int i1, i2, i3, i4, i5, i6;
-
-                       if( sscanf(val, "%2x:%2x:%2x:%2x:%2x:%2x",
-                               &i1, &i2, &i3, &i4, &i5, &i6) == 6
-                       ) {
-                               (*m)->mac[0] = (unsigned char)i1;
-                               (*m)->mac[1] = (unsigned char)i2;
-                               (*m)->mac[2] = (unsigned char)i3;
-                               (*m)->mac[3] = (unsigned char)i4;
-                               (*m)->mac[4] = (unsigned char)i5;
-                               (*m)->mac[5] = (unsigned char)i6;
-                               return 0;
-                       }
-               }
-       }
-
-       fwd_free_ptr(*m);
-       return -1;
-}
-
-static int
-fwd_read_portrange(struct uci_context *uci, const char *s, const char *o, struct fwd_portrange **p)
-{
-       const char *val = ucix_get_option(uci, "firewall", s, o);
-       int min = -1;
-       int max = -1;
-       unsigned int tmp;
-
-       if( val == NULL )
-       {
-               return 0;
-       }
-       else if( sscanf(val, "%u%*[:-]%u", &min, &max) > 0 )
-       {
-               if( max == -1 )
-               {
-                       max = min;
-               }
-               else if( min > max )
-               {
-                       tmp = max;
-                       max = min;
-                       min = tmp;
-               }
-
-               if( (min >= 0) && (min <= 65535) && (max >= 0) && (max <= 65535) )
-               {
-                       if( (*p = fwd_alloc_ptr(struct fwd_portrange)) != NULL )
-                       {
-                               (*p)->min = min;
-                               (*p)->max = max;
-                               return 0;
-                       }
-               }
-       }
-
-       fwd_free_ptr(*p);
-       return -1;
-}
-
-static int
-fwd_read_proto(struct uci_context *uci, const char *s, const char *o, struct fwd_proto **p)
-{
-       const char *val = ucix_get_option(uci, "firewall", s, o);
-       int proto;
-
-       if( val == NULL )
-       {
-               return 0;
-       }
-       else
-       {
-               if( (*p = fwd_alloc_ptr(struct fwd_proto)) != NULL )
-               {
-                       proto = atoi(val);
-
-                       if( !strcasecmp(val, "all") )
-                       {
-                               (*p)->type  = FWD_PR_ALL;
-                               (*p)->proto = 0;
-                       }
-                       else if( !strcasecmp(val, "icmp") )
-                       {
-                               (*p)->type  = FWD_PR_ICMP;
-                               (*p)->proto = 0;
-                       }
-                       else if( !strcasecmp(val, "udp") )
-                       {
-                               (*p)->type  = FWD_PR_UDP;
-                               (*p)->proto = 0;
-                       }
-                       else if( !strcasecmp(val, "tcp") )
-                       {
-                               (*p)->type  = FWD_PR_TCP;
-                               (*p)->proto = 0;
-                       }
-                       else if( !strcasecmp(val, "tcpudp") )
-                       {
-                               (*p)->type  = FWD_PR_TCPUDP;
-                               (*p)->proto = 0;
-                       }
-                       else if( proto > 0 )
-                       {
-                               (*p)->type  = FWD_PR_CUSTOM;
-                               (*p)->proto = proto;
-                       }
-                       else
-                       {
-                               goto inval;
-                       }
-
-                       return 0;
-               }
-       }
-
-       inval:
-       fwd_free_ptr(*p);
-       return -1;
-}
-
-static int
-fwd_read_icmptype(struct uci_context *uci, const char *s, const char *o, struct fwd_icmptype **i)
-{
-       const char *val = ucix_get_option(uci, "firewall", s, o);
-       unsigned int type, code;
-
-       if( val == NULL )
-       {
-               return 0;
-       }
-       else
-       {
-               if( (*i = fwd_alloc_ptr(struct fwd_icmptype)) != NULL )
-               {
-                       if( sscanf(val, "%u/%u", &type, &code) == 2 )
-                       {
-                               if( (type > 255) || (code > 255) )
-                                       goto inval;
-
-                               (*i)->type = type;
-                               (*i)->code = code;
-
-                               return 0;
-                       }
-
-                       else if( sscanf(val, "%u", &type) == 1 )
-                       {
-                               if( type > 255 )
-                                       goto inval;
-
-                               (*i)->type = type;
-                               (*i)->code = -1;
-
-                               return 0;
-                       }
-
-                       /* XXX: no validity check here but I do not want to
-                               duplicate libipt_icmp.c ... */
-                       else if( sscanf(val, "%31s", (*i)->name) == 1 )
-                       {
-                               return 0;
-                       }
-               }
-       }
-
-       inval:
-       fwd_free_ptr(*i);
-       return -1;
-}
-
-static const char *
-fwd_read_string(struct uci_context *uci, const char *s, const char *o)
-{
-       return ucix_get_option(uci, "firewall", s, o);
-}
-
-
-static void
-fwd_append_config(struct fwd_data *h, struct fwd_data *a)
-{
-       while( h->next )
-               h = h->next;
-
-       h->next = a;
-}
-
-
-/*
- * config defaults
- */
-static void fwd_read_defaults_cb(
-       struct uci_context *uci,
-       const char *s, struct fwd_defaults *d
-) {
-       d->input        = fwd_read_policy(uci, s, "input");
-       d->forward      = fwd_read_policy(uci, s, "forward");
-       d->output       = fwd_read_policy(uci, s, "output");
-       d->syn_flood    = fwd_read_bool(uci, s, "syn_flood", 1);
-       d->syn_rate     = fwd_read_uint(uci, s, "syn_rate", 25);
-       d->syn_burst    = fwd_read_uint(uci, s, "syn_burst", 50);
-       d->drop_invalid = fwd_read_bool(uci, s, "drop_invalid", 1);
-}
-
-static struct fwd_data *
-fwd_read_defaults(struct uci_context *uci)
-{
-       struct fwd_data *dt;
-       struct fwd_defaults d;
-
-       if( (dt = fwd_alloc_ptr(struct fwd_data)) != NULL )
-       {
-               memset(&d, 0, sizeof(d));
-
-               ucix_for_each_section_type(uci, "firewall", "defaults",
-                       (void *)fwd_read_defaults_cb, &d);
-
-               memcpy(&dt->section.defaults, &d, sizeof(d));
-
-               dt->type = FWD_S_DEFAULTS;
-               dt->next = NULL;
-
-               return dt;
-       }
-
-       return NULL;
-}
-
-
-/*
- * config zone
- */
-static void fwd_read_zone_networks_cb(
-       const char *net, struct fwd_network **np
-) {
-       struct fwd_network *nn;
-
-       if( (nn = fwd_alloc_ptr(struct fwd_network)) != NULL )
-       {
-               nn->name = strdup(net);
-               nn->next = *np;
-               *np = nn;
-       }
-}
-
-static void fwd_read_zones_cb(
-       struct uci_context *uci,
-       const char *s, struct fwd_data_conveyor *cv
-) {
-       struct fwd_data *dtn;
-       struct fwd_network *net = NULL;
-       const char *name;
-
-       if( !(name = fwd_read_string(uci, s, "name")) )
-               fwd_read_error("section '%s' is missing 'name' option!", s);
-
-       if( (dtn = fwd_alloc_ptr(struct fwd_data)) != NULL )
-       {
-               dtn->section.zone.name      = strdup(name);
-               dtn->section.zone.masq      = fwd_read_bool(uci, s, "masq", 0);
-               dtn->section.zone.mtu_fix   = fwd_read_bool(uci, s, "mtu_fix", 0);
-               dtn->section.zone.conntrack = fwd_read_bool(uci, s, "conntrack", 0);
-
-               dtn->section.zone.input     = fwd_read_policy(uci, s, "input")
-                       ?: cv->head->section.defaults.input   ?: FWD_P_DROP;
-
-               dtn->section.zone.forward   = fwd_read_policy(uci, s, "forward")
-                       ?: cv->head->section.defaults.forward ?: FWD_P_DROP;
-
-               dtn->section.zone.output    = fwd_read_policy(uci, s, "output")
-                       ?: cv->head->section.defaults.output  ?: FWD_P_DROP;
-
-               /* try to parse option/list network ... */
-               if( ucix_for_each_list(uci, "firewall", s, "network",
-                       (void *)&fwd_read_zone_networks_cb, &net) < 0 )
-               {
-                       /* ... didn't work, fallback to option name */
-                       fwd_read_zone_networks_cb(name, &net);
-               }
-
-               dtn->section.zone.networks = net;
-               dtn->type = FWD_S_ZONE;
-               dtn->next = cv->cursor;
-               cv->cursor = dtn;
-       }
-}
-
-static struct fwd_data *
-fwd_read_zones(struct uci_context *uci, struct fwd_data *def)
-{
-       struct fwd_data_conveyor cv;
-
-       cv.cursor = NULL;
-       cv.head = def;
-
-       ucix_for_each_section_type(uci, "firewall", "zone",
-               (void *)fwd_read_zones_cb, &cv);
-
-       return cv.cursor;
-}
-
-
-/*
- * config forwarding
- */
-static void fwd_read_forwards_cb(
-       struct uci_context *uci,
-       const char *s, struct fwd_data_conveyor *cv
-) {
-       const char *src, *dest;
-       struct fwd_data *dtn;
-       struct fwd_zone *zsrc  = NULL;
-       struct fwd_zone *zdest = NULL;
-
-       if( !(src = fwd_read_string(uci, s, "src")) )
-               fwd_read_error("section '%s' is missing 'src' option!", s);
-       else if( !(zsrc = fwd_lookup_zone(cv->head, src)) )
-               fwd_read_error("section '%s' references unknown src zone '%s'!", s, src);
-       else if( !(dest = fwd_read_string(uci, s, "dest")) )
-               fwd_read_error("section '%s' is missing 'dest' option!", s);
-       else if( !(zdest = fwd_lookup_zone(cv->head, dest)) )
-               fwd_read_error("section '%s' references unknown dest zone '%s'!", s, dest);
-       
-       if( (dtn = fwd_alloc_ptr(struct fwd_data)) != NULL )
-       {
-               dtn->section.forwarding.src = zsrc;
-               dtn->section.forwarding.dest = zdest;
-               dtn->section.forwarding.mtu_fix = fwd_read_bool(uci, s, "mtu_fix", 0);
-               dtn->section.forwarding.masq = fwd_read_bool(uci, s, "masq", 0);
-
-               dtn->type = FWD_S_FORWARD;
-
-               if( zsrc )
-               {
-                       dtn->next = zsrc->forwardings;
-                       zsrc->forwardings = dtn;
-               }
-               else
-               {
-                       dtn->next = cv->cursor;
-                       cv->cursor = dtn;
-               }
-       }
-       else
-       {
-               fwd_read_error("out of memory while parsing config!");
-       }
-}
-
-static struct fwd_data *
-fwd_read_forwards(struct uci_context *uci, struct fwd_data *zones)
-{
-       struct fwd_data_conveyor cv;
-
-       cv.cursor = NULL;
-       cv.head = zones;
-
-       ucix_for_each_section_type(uci, "firewall", "forwarding",
-               (void *)fwd_read_forwards_cb, &cv);
-
-       return cv.cursor;
-}
-
-
-/*
- * config redirect
- */
-static void fwd_read_redirects_cb(
-       struct uci_context *uci,
-       const char *s, struct fwd_data_conveyor *cv
-) {
-       const char *src;
-       struct fwd_data *dtn  = NULL;
-       struct fwd_data *dtn2 = NULL;
-       struct fwd_zone *zsrc = NULL;
-
-       /* check zone */
-       if( !(src = fwd_read_string(uci, s, "src")) )
-               fwd_read_error(
-                       "section '%s' is missing 'src' option!",
-                       s
-               );
-
-       else if( !(zsrc = fwd_lookup_zone(cv->head, src)) )
-               fwd_read_error(
-                       "section '%s' references unknown src zone '%s'!",
-                       s, src
-               );
-
-       /* uci context, section, name, type */
-       fwd_check_option(uci, s, src_ip, cidr);
-       fwd_check_option(uci, s, src_mac, mac);
-       fwd_check_option(uci, s, src_port, portrange);
-       fwd_check_option(uci, s, src_dport, portrange);
-       fwd_check_option(uci, s, dest_ip, cidr);
-       fwd_check_option(uci, s, dest_port, portrange);
-       fwd_check_option(uci, s, proto, proto);
-       
-       if( (dtn = fwd_alloc_ptr(struct fwd_data)) != NULL )
-       {
-               dtn->section.redirect.proto     = proto;
-               dtn->section.redirect.src       = zsrc;
-               dtn->section.redirect.src_ip    = src_ip;
-               dtn->section.redirect.src_mac   = src_mac;
-               dtn->section.redirect.src_port  = src_port;
-               dtn->section.redirect.src_dport = src_dport;
-               dtn->section.redirect.dest_ip   = dest_ip;
-               dtn->section.redirect.dest_port = dest_port;
-
-               dtn->type = FWD_S_REDIRECT;
-               dtn->next = zsrc->redirects;
-               zsrc->redirects = dtn;
-
-               if( (proto != NULL) && (proto->type == FWD_PR_TCPUDP) )
-               {
-                       if( !(dtn2 = fwd_alloc_ptr(struct fwd_data)) ||
-                           !(dtn2->section.redirect.proto = fwd_alloc_ptr(struct fwd_proto))
-                       ) {
-                               fwd_free_ptr(dtn2);
-                               fwd_read_error("out of memory while parsing config!");
-                       }
-
-                       dtn->section.redirect.proto->type = FWD_PR_UDP;
-                       dtn2->section.redirect.proto->type = FWD_PR_TCP;
-
-                       dtn2->section.redirect.src       = zsrc;
-                       dtn2->section.redirect.src_ip    = src_ip;
-                       dtn2->section.redirect.src_mac   = src_mac;
-                       dtn2->section.redirect.src_port  = src_port;
-                       dtn2->section.redirect.src_dport = src_dport;
-                       dtn2->section.redirect.dest_ip   = dest_ip;
-                       dtn2->section.redirect.dest_port = dest_port;
-                       dtn2->section.redirect.clone     = 1;
-
-                       dtn2->type = FWD_S_REDIRECT;
-                       dtn2->next = zsrc->redirects;
-                       zsrc->redirects = dtn2;
-               }
-       }
-       else
-       {
-               fwd_read_error("out of memory while parsing config!");
-       }
-}
-
-static struct fwd_data *
-fwd_read_redirects(struct uci_context *uci, struct fwd_data *zones)
-{
-       struct fwd_data_conveyor cv;
-
-       cv.cursor = NULL;
-       cv.head = zones;
-
-       ucix_for_each_section_type(uci, "firewall", "redirect",
-               (void *)fwd_read_redirects_cb, &cv);
-
-       return cv.cursor;
-}
-
-
-/*
- * config rule
- */
-static void fwd_read_rules_cb(
-       struct uci_context *uci,
-       const char *s, struct fwd_data_conveyor *cv
-) {
-       const char *src, *dest;
-       struct fwd_data *dtn   = NULL;
-       struct fwd_data *dtn2  = NULL;
-       struct fwd_zone *zsrc  = NULL;
-       struct fwd_zone *zdest = NULL;
-
-       /* check zones */
-       if( !(src = fwd_read_string(uci, s, "src")) )
-               fwd_read_error(
-                       "section '%s' is missing 'src' option!",
-                       s
-               );
-
-       else if( !(zsrc = fwd_lookup_zone(cv->head, src)) )
-               fwd_read_error(
-                       "section '%s' references unknown src zone '%s'!",
-                       s, src
-               );
-
-       if( (dest = fwd_read_string(uci, s, "dest")) != NULL )
-               if( !(zdest = fwd_lookup_zone(cv->head, dest)) )
-                       fwd_read_error(
-                               "section '%s' references unknown dest zone '%s'!",
-                               s, dest
-                       );
-
-       /* uci context, section, name, type */
-       fwd_check_option(uci, s, src_ip, cidr);
-       fwd_check_option(uci, s, src_mac, mac);
-       fwd_check_option(uci, s, src_port, portrange);
-       fwd_check_option(uci, s, dest_ip, cidr);
-       fwd_check_option(uci, s, dest_port, portrange);
-       fwd_check_option(uci, s, proto, proto);
-       fwd_check_option(uci, s, icmptype, icmptype);
-       
-       if( (dtn = fwd_alloc_ptr(struct fwd_data)) != NULL )
-       {
-               dtn->section.rule.proto     = proto;
-               dtn->section.rule.icmp_type = icmptype;
-               dtn->section.rule.src       = zsrc;
-               dtn->section.rule.src_ip    = src_ip;
-               dtn->section.rule.src_mac   = src_mac;
-               dtn->section.rule.src_port  = src_port;
-               dtn->section.rule.dest      = zdest;
-               dtn->section.rule.dest_ip   = dest_ip;
-               dtn->section.rule.dest_port = dest_port;
-               dtn->section.rule.target    = fwd_read_policy(uci, s, "target");
-
-               dtn->type = FWD_S_RULE;
-               dtn->next = zsrc->rules;
-               zsrc->rules = dtn;
-
-               if( (proto != NULL) && (proto->type == FWD_PR_TCPUDP) )
-               {
-                       if( !(dtn2 = fwd_alloc_ptr(struct fwd_data)) ||
-                           !(dtn2->section.rule.proto = fwd_alloc_ptr(struct fwd_proto))
-                       ) {
-                               fwd_free_ptr(dtn2);
-                               fwd_read_error("out of memory while parsing config!");
-                       }
-
-                       dtn->section.rule.proto->type = FWD_PR_UDP;
-                       dtn2->section.rule.proto->type = FWD_PR_TCP;
-
-                       dtn2->section.rule.src       = zsrc;
-                       dtn2->section.rule.src_ip    = src_ip;
-                       dtn2->section.rule.src_mac   = src_mac;
-                       dtn2->section.rule.src_port  = src_port;
-                       dtn2->section.rule.dest      = zdest;
-                       dtn2->section.rule.dest_ip   = dest_ip;
-                       dtn2->section.rule.dest_port = dest_port;
-                       dtn2->section.rule.target    = dtn->section.rule.target;
-                       dtn2->section.rule.clone     = 1;
-
-                       dtn2->type = FWD_S_RULE;
-                       dtn2->next = zsrc->rules;
-                       zsrc->rules = dtn2;
-               }
-       }
-       else
-       {
-               fwd_read_error("out of memory while parsing config!");
-       }
-}
-
-static struct fwd_data *
-fwd_read_rules(struct uci_context *uci, struct fwd_data *zones)
-{
-       struct fwd_data_conveyor cv;
-
-       cv.cursor = NULL;
-       cv.head = zones;
-
-       ucix_for_each_section_type(uci, "firewall", "rule",
-               (void *)fwd_read_rules_cb, &cv);
-
-       return cv.cursor;
-}
-
-
-/*
- * config include
- */
-static void fwd_read_includes_cb(
-       struct uci_context *uci,
-       const char *s, struct fwd_data_conveyor *cv
-) {
-       const char *path = fwd_read_string(uci, s, "path");
-       struct fwd_data *dtn = NULL;
-
-       if( path != NULL )
-       {
-               if( (dtn = fwd_alloc_ptr(struct fwd_data)) != NULL )
-               {
-                       dtn->section.include.path = strdup(path);
-
-                       dtn->type = FWD_S_INCLUDE;
-                       dtn->next = cv->cursor;
-                       cv->cursor = dtn;
-               }
-               else
-               {
-                       fwd_read_error("out of memory while parsing config!");
-               }
-       }
-}
-
-static struct fwd_data *
-fwd_read_includes(struct uci_context *uci)
-{
-       struct fwd_data_conveyor cv;
-
-       cv.cursor = NULL;
-       cv.head   = NULL;
-
-       ucix_for_each_section_type(uci, "firewall", "include",
-               (void *)fwd_read_includes_cb, &cv);
-
-       return cv.cursor;
-}
-
-
-/*
- * config interface
- */
-static void fwd_read_network_data(
-       struct uci_context *uci, struct fwd_network *net
-) {
-       struct fwd_network *e;
-       const char *type, *ifname;
-
-       for( e = net; e; e = e->next )
-       {
-               if( (type = ucix_get_option(uci, "network", e->name, NULL)) != NULL )
-               {
-                       if( !(ifname = ucix_get_option(uci, "network", e->name, "ifname")) )
-                               fwd_read_error(
-                                       "section '%s' is missing 'ifname' option!",
-                                       e->name
-                               );
-
-                       e->isalias = (strcmp(type, "alias") ? 0 : 1);
-                       e->ifname  = strdup(ifname);
-               }
-       }
-}
-
-static void fwd_read_networks(
-       struct uci_context *uci, struct fwd_data *zones
-) {
-       struct fwd_data *e;
-
-       for( e = zones; e; e = e->next )
-               if( e->type == FWD_S_ZONE )
-                       fwd_read_network_data(uci, e->section.zone.networks);
-}
-
-static void fwd_free_networks(struct fwd_network *h)
-{
-       struct fwd_network *e = h;
-
-       while( h != NULL )
-       {
-               e = h->next;
-
-               fwd_free_ptr(h->name);
-               fwd_free_ptr(h->ifname);
-               fwd_free_ptr(h->addr);
-
-               free(h);
-               h = e;
-       }
-
-       e = h = NULL;
-}
-
-static struct fwd_cidr * fwd_alloc_cidr(struct fwd_cidr *addr)
-{
-       struct fwd_cidr *cidr;
-
-       if( (cidr = fwd_alloc_ptr(struct fwd_cidr)) != NULL )
-       {
-               if( addr != NULL )
-               {
-                       cidr->addr.s_addr = addr->addr.s_addr;
-                       cidr->prefix = addr->prefix;
-               }
-
-               return cidr;
-       }
-
-       return NULL;
-}
-
-
-
-struct fwd_data * fwd_read_config(struct fwd_handle *h)
-{
-       struct uci_context *ctx;
-       struct fwd_data *defaults, *zones, *e;
-       struct fwd_addr *addrs;
-       struct fwd_network *net;
-       struct fwd_zone *zone;
-
-       if( (ctx = ucix_init("firewall")) != NULL )
-       {
-               if( !(defaults = fwd_read_defaults(ctx)) )
-                       goto error;
-
-               if( !(zones = fwd_read_zones(ctx, defaults)) )
-                       goto error;
-
-               fwd_append_config(defaults, zones);
-               fwd_append_config(defaults, fwd_read_forwards(ctx, zones));
-               fwd_append_config(defaults, fwd_read_redirects(ctx, zones));
-               fwd_append_config(defaults, fwd_read_rules(ctx, zones));
-               fwd_append_config(defaults, fwd_read_includes(ctx));
-
-               ucix_cleanup(ctx);
-
-               if( (ctx = ucix_init("network")) != NULL )
-               {
-                       fwd_read_networks(ctx, zones);
-                       ucix_cleanup(ctx);
-
-                       if( !(addrs = fwd_get_addrs(h->rtnl_socket, AF_INET)) )
-                               goto error;
-
-                       for( e = zones; e && (zone = &e->section.zone); e = e->next )
-                       {
-                               if( e->type != FWD_S_ZONE )
-                                       break;
-
-                               for( net = zone->networks; net; net = net->next )
-                               {
-                                       net->addr = fwd_alloc_cidr(
-                                               fwd_lookup_addr(addrs, net->ifname)
-                                       );
-                               }
-                       }
-
-                       fwd_free_addrs(addrs);
-                       return defaults;
-               }
-       }
-
-       error:
-       if( ctx ) ucix_cleanup(ctx);
-       fwd_free_config(defaults);
-       fwd_free_config(zones);
-       return NULL;    
-}
-
-
-void fwd_free_config(struct fwd_data *h)
-{
-       struct fwd_data *e = h;
-
-       while( h != NULL )
-       {
-               e = h->next;
-
-               switch(h->type)
-               {
-                       case FWD_S_INCLUDE:
-                               fwd_free_ptr(h->section.include.path);
-                               break;
-
-                       case FWD_S_ZONE:
-                               fwd_free_ptr(h->section.zone.name);
-                               fwd_free_networks(h->section.zone.networks);
-                               fwd_free_config(h->section.zone.rules);
-                               fwd_free_config(h->section.zone.redirects);
-                               fwd_free_config(h->section.zone.forwardings);
-                               break;
-
-                       case FWD_S_REDIRECT:
-                               /* Clone rules share all pointers except proto.
-                   Prevent a double-free here */          
-                               if( ! h->section.redirect.clone )
-                               {
-                                       fwd_free_ptr(h->section.redirect.src_ip);
-                                       fwd_free_ptr(h->section.redirect.src_mac);
-                                       fwd_free_ptr(h->section.redirect.src_port);
-                                       fwd_free_ptr(h->section.redirect.src_dport);
-                                       fwd_free_ptr(h->section.redirect.dest_ip);
-                                       fwd_free_ptr(h->section.redirect.dest_port);
-                               }
-                               fwd_free_ptr(h->section.redirect.proto);
-                               break;
-
-                       case FWD_S_RULE:
-                               /* Clone rules share all pointers except proto.
-                   Prevent a double-free here */          
-                               if( ! h->section.rule.clone )
-                               {
-                                       fwd_free_ptr(h->section.rule.src_ip);
-                                       fwd_free_ptr(h->section.rule.src_mac);
-                                       fwd_free_ptr(h->section.rule.src_port);
-                                       fwd_free_ptr(h->section.rule.dest_ip);
-                                       fwd_free_ptr(h->section.rule.dest_port);
-                                       fwd_free_ptr(h->section.rule.icmp_type);
-                               }
-                               fwd_free_ptr(h->section.rule.proto);
-                               break;
-
-                       case FWD_S_DEFAULTS:
-                       case FWD_S_FORWARD:
-                               /* Make gcc happy */
-                               break;
-               }
-
-               fwd_free_ptr(h);
-               h = e;
-       }
-
-       e = h = NULL;
-}
-
-
-struct fwd_zone *
-fwd_lookup_zone(struct fwd_data *h, const char *n)
-{
-       struct fwd_data *e;
-
-       if( n != NULL )
-       {
-               for( e = h; e; e = e->next )
-               {
-                       if( (e->type = FWD_S_ZONE) && !strcmp(e->section.zone.name, n) )
-                               return &e->section.zone;
-               }
-       }
-
-       return NULL;
-}
-