Make nat reflection src address configurable by introducing a reflection_src paramete...
[project/firewall3.git] / utils.c
diff --git a/utils.c b/utils.c
index 4314f91..dbc713c 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -244,6 +244,7 @@ __fw3_command_pipe(bool silent, const char *command, ...)
                signal(SIGPIPE, SIG_IGN);
                pipe_pid = pid;
                close(pfds[0]);
+               fcntl(pfds[1], F_SETFD, fcntl(pfds[1], F_GETFD) | FD_CLOEXEC);
        }
 
        pipe_fd = fdopen(pfds[1], "w");
@@ -361,6 +362,7 @@ fw3_read_statefile(void *state)
        struct fw3_state *s = state;
        struct fw3_zone *zone;
        struct fw3_ipset *ipset;
+       struct fw3_device *net, *dev;
 
        sf = fopen(FW3_STATEFILE, "r");
 
@@ -430,6 +432,28 @@ fw3_read_statefile(void *state)
                        ipset->flags[1] = flags[1];
                        list_add_tail(&ipset->running_list, &s->running_ipsets);
                        break;
+
+               case FW3_TYPE_NETWORK:
+                       if (!(zone = fw3_lookup_zone(state, name, false)))
+                               continue;
+
+                       if (!(p = strtok(NULL, " \t\n")) || !(name = strtok(NULL, " \t\n")))
+                               continue;
+
+                       if (!(net = malloc(sizeof(*net))))
+                               continue;
+
+                       memset(net, 0, sizeof(*net));
+                       snprintf(net->name, sizeof(net->name), "%s", p);
+                       list_add_tail(&net->list, &zone->running_networks);
+
+                       if (!(dev = malloc(sizeof(*dev))))
+                               continue;
+
+                       memset(dev, 0, sizeof(*dev));
+                       dev->network = net;
+                       snprintf(dev->name, sizeof(dev->name), "%s", name);
+                       list_add_tail(&dev->list, &zone->running_devices);
                }
        }
 
@@ -443,11 +467,12 @@ fw3_write_statefile(void *state)
 {
        FILE *sf;
        struct fw3_state *s = state;
-       struct fw3_defaults *d = &s->defaults;
+       struct fw3_defaults *defs = &s->defaults;
        struct fw3_zone *z;
        struct fw3_ipset *i;
+       struct fw3_device *d;
 
-       if (fw3_no_table(d->flags[0]) && fw3_no_table(d->flags[1]))
+       if (fw3_no_table(defs->flags[0]) && fw3_no_table(defs->flags[1]))
        {
                if (unlink(FW3_STATEFILE))
                        warn("Unable to remove state %s: %s",
@@ -464,14 +489,24 @@ fw3_write_statefile(void *state)
                return;
        }
 
-       fprintf(sf, "%x - %x %x\n", FW3_TYPE_DEFAULTS, d->flags[0], d->flags[1]);
+       fprintf(sf, "%x - %x %x\n",
+               FW3_TYPE_DEFAULTS, defs->flags[0], defs->flags[1]);
 
        list_for_each_entry(z, &s->running_zones, running_list)
        {
-               if (!fw3_no_table(z->flags[0]) || !fw3_no_table(z->flags[1]))
+               if (fw3_no_table(z->flags[0]) && fw3_no_table(z->flags[1]))
+                       continue;
+
+               fprintf(sf, "%x %s %x %x\n",
+                       FW3_TYPE_ZONE, z->name, z->flags[0], z->flags[1]);
+
+               list_for_each_entry(d, &z->devices, list)
                {
-                       fprintf(sf, "%x %s %x %x\n",
-                                       FW3_TYPE_ZONE, z->name, z->flags[0], z->flags[1]);
+                       if (!d->network)
+                               continue;
+
+                       fprintf(sf, "%x %s 0 0 %s %s\n",
+                               FW3_TYPE_NETWORK, z->name, d->network->name, d->name);
                }
        }
 
@@ -563,3 +598,43 @@ fw3_pr_rulespec(int table, int family, uint32_t *flags, uint32_t mask,
 
        return rv;
 }
+
+
+bool
+fw3_hotplug(bool add, void *zone, void *device)
+{
+       struct fw3_zone *z = zone;
+       struct fw3_device *d = device;
+
+       if (!d->network)
+               return false;
+
+       switch (fork())
+       {
+       case -1:
+               warn("Unable to fork(): %s\n", strerror(errno));
+               return false;
+
+       case 0:
+               break;
+
+       default:
+               return true;
+       }
+
+       close(0);
+       close(1);
+       close(2);
+       chdir("/");
+
+       clearenv();
+       setenv("ACTION",    add ? "add" : "remove", 1);
+       setenv("ZONE",      z->name,                1);
+       setenv("INTERFACE", d->network->name,       1);
+       setenv("DEVICE",    d->name,                1);
+
+       execl(FW3_HOTPLUG, FW3_HOTPLUG, "firewall", NULL);
+
+       /* unreached */
+       return false;
+}