contrib/fwd: remove debug prints, add syslog info
[project/luci.git] / contrib / fwd / src / fwd_config.c
index 11fd458..320e9ff 100644 (file)
 #include "fwd.h"
 #include "fwd_addr.h"
 #include "fwd_config.h"
+#include "fwd_utils.h"
 
 #include "ucix.h"
 
 
-#define fwd_read_error(...) do {  \
-       fprintf(stderr, "ERROR: ");   \
-       fprintf(stderr, __VA_ARGS__); \
-       fprintf(stderr, "\n");        \
-       return;                       \
+#define fwd_read_error(...) do { \
+       fwd_log_err(__VA_ARGS__);    \
+       return;                      \
 } while(0)
 
 
@@ -163,11 +162,17 @@ fwd_read_mac(struct uci_context *uci, const char *s, const char *o, struct fwd_m
        {
                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",
-                               (unsigned int *)&(*m)->mac[0], (unsigned int *)&(*m)->mac[1],
-                               (unsigned int *)&(*m)->mac[2], (unsigned int *)&(*m)->mac[3],
-                               (unsigned int *)&(*m)->mac[4], (unsigned int *)&(*m)->mac[5]) == 6
+                               &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;
                        }
                }
@@ -389,11 +394,11 @@ fwd_read_defaults(struct uci_context *uci)
  * config zone
  */
 static void fwd_read_zone_networks_cb(
-       const char *net, struct fwd_network_list **np
+       const char *net, struct fwd_network **np
 ) {
-       struct fwd_network_list *nn;
+       struct fwd_network *nn;
 
-       if( (nn = fwd_alloc_ptr(struct fwd_network_list)) != NULL )
+       if( (nn = fwd_alloc_ptr(struct fwd_network)) != NULL )
        {
                nn->name = strdup(net);
                nn->next = *np;
@@ -406,7 +411,7 @@ static void fwd_read_zones_cb(
        const char *s, struct fwd_data_conveyor *cv
 ) {
        struct fwd_data *dtn;
-       struct fwd_network_list *net = NULL;
+       struct fwd_network *net = NULL;
        const char *name;
 
        if( !(name = fwd_read_string(uci, s, "name")) )
@@ -470,17 +475,14 @@ static void fwd_read_forwards_cb(
        struct fwd_zone *zsrc  = NULL;
        struct fwd_zone *zdest = NULL;
 
-       if( (src = fwd_read_string(uci, s, "src")) != NULL )
-       {
-               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);
-       }
+       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 )
        {
@@ -490,8 +492,17 @@ static void fwd_read_forwards_cb(
                dtn->section.forwarding.masq = fwd_read_bool(uci, s, "masq", 0);
 
                dtn->type = FWD_S_FORWARD;
-               dtn->next = cv->cursor;
-               cv->cursor = dtn;
+
+               if( zsrc )
+               {
+                       dtn->next = zsrc->forwardings;
+                       zsrc->forwardings = dtn;
+               }
+               else
+               {
+                       dtn->next = cv->cursor;
+                       cv->cursor = dtn;
+               }
        }
        else
        {
@@ -560,8 +571,8 @@ static void fwd_read_redirects_cb(
                dtn->section.redirect.dest_port = dest_port;
 
                dtn->type = FWD_S_REDIRECT;
-               dtn->next = cv->cursor;
-               cv->cursor = dtn;
+               dtn->next = zsrc->redirects;
+               zsrc->redirects = dtn;
 
                if( (proto != NULL) && (proto->type == FWD_PR_TCPUDP) )
                {
@@ -582,10 +593,11 @@ static void fwd_read_redirects_cb(
                        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 = cv->cursor;
-                       cv->cursor = dtn2;
+                       dtn2->next = zsrc->redirects;
+                       zsrc->redirects = dtn2;
                }
        }
        else
@@ -665,8 +677,8 @@ static void fwd_read_rules_cb(
                dtn->section.rule.target    = fwd_read_policy(uci, s, "target");
 
                dtn->type = FWD_S_RULE;
-               dtn->next = cv->cursor;
-               cv->cursor = dtn;
+               dtn->next = zsrc->rules;
+               zsrc->rules = dtn;
 
                if( (proto != NULL) && (proto->type == FWD_PR_TCPUDP) )
                {
@@ -688,10 +700,11 @@ static void fwd_read_rules_cb(
                        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 = cv->cursor;
-                       cv->cursor = dtn2;
+                       dtn2->next = zsrc->rules;
+                       zsrc->rules = dtn2;
                }
        }
        else
@@ -761,9 +774,9 @@ fwd_read_includes(struct uci_context *uci)
  * config interface
  */
 static void fwd_read_network_data(
-       struct uci_context *uci, struct fwd_network_list *net
+       struct uci_context *uci, struct fwd_network *net
 ) {
-       struct fwd_network_list *e;
+       struct fwd_network *e;
        const char *type, *ifname;
 
        for( e = net; e; e = e->next )
@@ -792,9 +805,9 @@ static void fwd_read_networks(
                        fwd_read_network_data(uci, e->section.zone.networks);
 }
 
-static void fwd_free_networks(struct fwd_network_list *h)
+static void fwd_free_networks(struct fwd_network *h)
 {
-       struct fwd_network_list *e = h;
+       struct fwd_network *e = h;
 
        while( h != NULL )
        {
@@ -811,12 +824,33 @@ static void fwd_free_networks(struct fwd_network_list *h)
        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(void)
+struct fwd_data * fwd_read_config(struct fwd_handle *h)
 {
        struct uci_context *ctx;
-       struct fwd_data *defaults, *zones;
+       struct fwd_data *defaults, *zones, *e;
+       struct fwd_addr *addrs;
+       struct fwd_network *net;
+       struct fwd_zone *zone;
 
        if( (ctx = ucix_init("firewall")) != NULL )
        {
@@ -839,6 +873,23 @@ struct fwd_data * fwd_read_config(void)
                        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;
                }
        }
@@ -868,26 +919,39 @@ void fwd_free_config(struct fwd_data *h)
                        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:
-                               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);
+                               /* 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:
-                               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);
+                               /* 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);
-                               fwd_free_ptr(h->section.rule.icmp_type);
                                break;
 
                        case FWD_S_DEFAULTS:
@@ -896,7 +960,7 @@ void fwd_free_config(struct fwd_data *h)
                                break;
                }
 
-               free(h);
+               fwd_free_ptr(h);
                h = e;
        }