+
+
+bool
+fw3_pr_rulespec(int table, int family, uint32_t *flags, uint32_t mask,
+ const struct fw3_rule_spec *r, const char *fmt, ...)
+{
+ char buf[256];
+ bool rv = false;
+
+ va_list ap;
+ uint32_t f = flags ? flags[family == FW3_FAMILY_V6] : 0;
+
+ if (mask)
+ f &= mask;
+
+ for (; r->format; r++)
+ {
+ if (!fw3_is_family(r, family))
+ continue;
+
+ if (r->table != table)
+ continue;
+
+ if ((r->flag != 0) && !hasbit(f, r->flag))
+ continue;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), r->format, ap);
+ va_end(ap);
+
+ fw3_pr(fmt, buf);
+
+ rv = true;
+ }
+
+ 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;
+}