print a notification if forwards are skipped due to zone family mismatch
[project/firewall3.git] / utils.c
diff --git a/utils.c b/utils.c
index 9899d4d..9b62789 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -295,70 +295,166 @@ fw3_has_table(bool ipv6, const char *table)
        return seen;
 }
 
+
 bool
-fw3_check_statefile(bool test_exists)
+fw3_lock(void)
 {
-       struct stat s;
+       lock_fd = open(FW3_LOCKFILE, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
 
-       if (!stat(FW3_STATEFILE, &s))
+       if (lock_fd < 0)
        {
-               if (test_exists)
-                       return true;
-
-               warn("The firewall appears to be started already. "
-                        "If it is indeed empty, remove the %s file and retry.",
-                        FW3_STATEFILE);
-
+               warn("Cannot create lock file %s: %s", FW3_LOCKFILE, strerror(errno));
                return false;
        }
-       else if (test_exists)
+
+       if (flock(lock_fd, LOCK_EX))
        {
-               warn("The firewall appears to stopped already.");
+               warn("Cannot acquire exclusive lock: %s", strerror(errno));
                return false;
        }
 
-       lock_fd = open(FW3_STATEFILE, O_CREAT | O_RDWR);
+       return true;
+}
 
+void
+fw3_unlock(void)
+{
        if (lock_fd < 0)
+               return;
+
+       if (flock(lock_fd, LOCK_UN))
+               warn("Cannot release exclusive lock: %s", strerror(errno));
+
+       close(lock_fd);
+       unlink(FW3_LOCKFILE);
+
+       lock_fd = -1;
+}
+
+
+struct list_head *
+fw3_read_statefile(void)
+{
+       FILE *sf;
+
+       int n;
+       char line[128];
+       const char *p;
+
+       struct list_head *state;
+       struct fw3_statefile_entry *entry;
+
+       sf = fopen(FW3_STATEFILE, "r");
+
+       if (!sf)
+               return NULL;
+
+       state = malloc(sizeof(*state));
+
+       if (!state)
+               return NULL;
+
+       INIT_LIST_HEAD(state);
+
+       while (fgets(line, sizeof(line), sf))
        {
-               warn("Unable to create %s file", FW3_STATEFILE);
-               goto fail;
+               entry = malloc(sizeof(*entry));
+
+               if (!entry)
+                       continue;
+
+               memset(entry, 0, sizeof(*entry));
+
+               p = strtok(line, " \t\n");
+
+               if (!p)
+                       continue;
+
+               entry->type = strtoul(p, NULL, 10);
+
+               p = strtok(NULL, " \t\n");
+
+               if (!p)
+                       continue;
+
+               entry->name = strdup(p);
+
+               for (n = 0, p = strtok(NULL, " \t\n");
+                    n < ARRAY_SIZE(entry->flags) && p != NULL;
+                    n++, p = strtok(NULL, " \t\n"))
+               {
+                       entry->flags[n] = strtoul(p, NULL, 10);
+               }
+
+               list_add_tail(&entry->list, state);
        }
 
-       if (flock(lock_fd, LOCK_EX))
+       fclose(sf);
+
+       return state;
+}
+
+void
+fw3_write_statefile(void *state)
+{
+       FILE *sf;
+       struct fw3_state *s = state;
+       struct fw3_defaults *d = &s->defaults;
+       struct fw3_zone *z;
+       struct fw3_ipset *i;
+
+       int mask = (1 << FW3_FAMILY_V4) | (1 << FW3_FAMILY_V6);
+
+       if (!(d->flags & mask))
        {
-               warn("Unable to acquire exclusive lock on %s file", FW3_STATEFILE);
-               goto fail;
+               if (unlink(FW3_STATEFILE))
+                       warn("Unable to remove state %s: %s",
+                            FW3_STATEFILE, strerror(errno));
 
+               return;
        }
 
-       return true;
+       sf = fopen(FW3_STATEFILE, "w");
 
-fail:
-       if (lock_fd > -1)
+       if (!sf)
        {
-               close(lock_fd);
-               lock_fd = -1;
+               warn("Cannot create state %s: %s", FW3_STATEFILE, strerror(errno));
+               return;
        }
 
-       return false;
-}
+       fprintf(sf, "%u - %u\n", FW3_TYPE_DEFAULTS, d->flags);
 
-void
-fw3_remove_statefile(void)
-{
-       if (lock_fd > -1)
-               fw3_close_statefile();
+       list_for_each_entry(z, &s->zones, list)
+       {
+               fprintf(sf, "%u %s %u %u\n", FW3_TYPE_ZONE,
+                       z->name, z->src_flags, z->dst_flags);
+       }
+
+       list_for_each_entry(i, &s->ipsets, list)
+       {
+               if (i->external && *i->external)
+                       continue;
 
-       if (unlink(FW3_STATEFILE))
-               warn("Unable to delete %s file", FW3_STATEFILE);
+               fprintf(sf, "%u %s %u\n", FW3_TYPE_IPSET, i->name, i->flags);
+       }
+
+       fclose(sf);
 }
 
 void
-fw3_close_statefile(void)
+fw3_free_statefile(struct list_head *statefile)
 {
-       flock(lock_fd, LOCK_UN);
-       close(lock_fd);
+       struct fw3_statefile_entry *e, *tmp;
 
-       lock_fd = -1;
+       if (!statefile)
+               return;
+
+       list_for_each_entry_safe(e, tmp, statefile, list)
+       {
+               list_del(&e->list);
+               free(e->name);
+               free(e);
+       }
+
+       free(statefile);
 }