X-Git-Url: http://git.archive.openwrt.org/?p=project%2Ffirewall3.git;a=blobdiff_plain;f=utils.c;h=dbc713cd36e8ff675813b6d0a5f0f7117bd293c4;hp=4314f91411d3b2af9027ffcb7f2a74d58d2f4111;hb=ff9d5e13c9150c62fe698e4bc5541e6f92b241d0;hpb=a2a689ed85420a4acf47835c9d6438e06e75ec82 diff --git a/utils.c b/utils.c index 4314f91..dbc713c 100644 --- 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; +}