.option_offset = 0,
.program_version = "4",
.orig_opts = base_opts,
+#if XTABLES_VERSION_CODE > 10
+ .compat_rev = xtables_compatible_revision,
+#endif
};
static struct xtables_globals xtg6 = {
.option_offset = 0,
.program_version = "6",
.orig_opts = base_opts,
+#if XTABLES_VERSION_CODE > 10
+ .compat_rev = xtables_compatible_revision,
+#endif
};
+static struct {
+ bool retain;
+ int mcount, tcount;
+ struct xtables_match **matches;
+ struct xtables_target **targets;
+ void (*register_match)(struct xtables_match *);
+ void (*register_target)(struct xtables_target *);
+} xext;
+
+
/* Required by certain extensions like SNAT and DNAT */
int kernel_version = 0;
struct fw3_ipt_handle *
fw3_ipt_open(enum fw3_family family, enum fw3_table table)
{
+ int i;
struct fw3_ipt_handle *h;
h = fw3_alloc(sizeof(*h));
fw3_xt_reset();
fw3_init_extensions();
+ if (xext.register_match)
+ for (i = 0; i < xext.mcount; i++)
+ xext.register_match(xext.matches[i]);
+
+ if (xext.register_target)
+ for (i = 0; i < xext.tcount; i++)
+ xext.register_target(xext.targets[i]);
+
return h;
}
void
fw3_ipt_close(struct fw3_ipt_handle *h)
{
- if (h->libv)
- {
- while (h->libc > 0)
- {
- h->libc--;
- dlclose(h->libv[h->libc]);
- }
-
- free(h->libv);
- }
-
free(h);
}
return NULL;
}
-static bool
-load_extension(struct fw3_ipt_handle *h, const char *name)
-{
- char path[256];
- void *lib, **tmp;
- const char *pfx = (h->family == FW3_FAMILY_V6) ? "libip6t" : "libipt";
-
- snprintf(path, sizeof(path), "/usr/lib/iptables/libxt_%s.so", name);
- if (!(lib = dlopen(path, RTLD_NOW)))
- {
- snprintf(path, sizeof(path), "/usr/lib/iptables/%s_%s.so", pfx, name);
- lib = dlopen(path, RTLD_NOW);
- }
-
- if (!lib)
- return false;
-
- tmp = realloc(h->libv, sizeof(lib) * (h->libc + 1));
-
- if (!tmp)
- return false;
-
- h->libv = tmp;
- h->libv[h->libc++] = lib;
-
- return true;
-}
-
static struct xtables_match *
find_match(struct fw3_ipt_rule *r, const char *name)
{
struct xtables_match *m;
- m = xtables_find_match(name, XTF_DONT_LOAD, &r->matches);
-
- if (!m && load_extension(r->h, name))
- m = xtables_find_match(name, XTF_DONT_LOAD, &r->matches);
+ xext.retain = true;
+ m = xtables_find_match(name, XTF_TRY_LOAD, &r->matches);
+ xext.retain = false;
return m;
}
{
struct xtables_target *t;
- if (is_chain(r->h, name))
- return xtables_find_target(XT_STANDARD_TARGET, XTF_LOAD_MUST_SUCCEED);
+ xext.retain = true;
- t = xtables_find_target(name, XTF_DONT_LOAD);
+ if (is_chain(r->h, name))
+ t = xtables_find_target(XT_STANDARD_TARGET, XTF_TRY_LOAD);
+ else
+ t = xtables_find_target(name, XTF_TRY_LOAD);
- if (!t && load_extension(r->h, name))
- t = xtables_find_target(name, XTF_DONT_LOAD);
+ xext.retain = false;
return t;
}
return r;
}
+
+void
+xtables_register_match(struct xtables_match *me)
+{
+ int i;
+ static struct xtables_match **tmp;
+
+ if (!xext.register_match)
+ xext.register_match = dlsym(RTLD_NEXT, "xtables_register_match");
+
+ if (!xext.register_match)
+ return;
+
+ xext.register_match(me);
+
+ if (xext.retain)
+ {
+ for (i = 0; i < xext.mcount; i++)
+ if (xext.matches[i] == me)
+ return;
+
+ tmp = realloc(xext.matches, sizeof(me) * (xext.mcount + 1));
+
+ if (!tmp)
+ return;
+
+ xext.matches = tmp;
+ xext.matches[xext.mcount++] = me;
+ }
+}
+
+void
+xtables_register_target(struct xtables_target *me)
+{
+ int i;
+ static struct xtables_target **tmp;
+
+ if (!xext.register_target)
+ xext.register_target = dlsym(RTLD_NEXT, "xtables_register_target");
+
+ if (!xext.register_target)
+ return;
+
+ xext.register_target(me);
+
+ if (xext.retain)
+ {
+ for (i = 0; i < xext.tcount; i++)
+ if (xext.targets[i] == me)
+ return;
+
+ tmp = realloc(xext.targets, sizeof(me) * (xext.tcount + 1));
+
+ if (!tmp)
+ return;
+
+ xext.targets = tmp;
+ xext.targets[xext.tcount++] = me;
+ }
+}