Dynamically create rules for available libext*.a libraries, clean up rules
[project/firewall3.git] / iptables.c
index 9c5f80a..a189745 100644 (file)
@@ -39,7 +39,7 @@ static struct xtables_globals xtg6 = {
 };
 
 /* Required by certain extensions like SNAT and DNAT */
-int kernel_version;
+int kernel_version = 0;
 
 void
 get_kernel_version(void)
@@ -51,7 +51,20 @@ get_kernel_version(void)
                sprintf(uts.release, "3.0.0");
 
        sscanf(uts.release, "%d.%d.%d", &x, &y, &z);
-       kernel_version = LINUX_VERSION(x, y, z);
+       kernel_version = 0x10000 * x + 0x100 * y + z;
+}
+
+#undef __ipt_module
+#define __ipt_module(x) libxt_##x##_init, libipt_##x##_init, libip6t_##x##_init,
+
+static void fw3_init_extensions(void)
+{
+       int i;
+       void (*initfuncs[])(void) = { FW3_IPT_MODULES };
+
+       for (i = 0; i < sizeof(initfuncs)/sizeof(initfuncs[0]); i++)
+               if (initfuncs[i])
+                       initfuncs[i]();
 }
 
 struct fw3_ipt_handle *
@@ -94,17 +107,31 @@ fw3_ipt_open(enum fw3_family family, enum fw3_table table)
        xtables_matches = NULL;
        xtables_targets = NULL;
 
-       init_extensions();
-       init_extensions4();
-       init_extensions6();
+       fw3_init_extensions();
 
        return h;
 }
 
+static void
+debug(struct fw3_ipt_handle *h, const char *fmt, ...)
+{
+       va_list ap;
+
+       printf("%s -t %s ", (h->family == FW3_FAMILY_V6) ? "ip6tables" : "iptables",
+                           fw3_flag_names[h->table]);
+
+       va_start(ap, fmt);
+       vprintf(fmt, ap);
+       va_end(ap);
+}
+
 void
 fw3_ipt_set_policy(struct fw3_ipt_handle *h, const char *chain,
                    enum fw3_flag policy)
 {
+       if (fw3_pr_debug)
+               debug(h, "-P %s %s\n", chain, fw3_flag_names[policy]);
+
        if (h->family == FW3_FAMILY_V6)
                ip6tc_set_policy(chain, fw3_flag_names[policy], NULL, h->handle);
        else
@@ -116,8 +143,8 @@ fw3_ipt_delete_chain(struct fw3_ipt_handle *h, const char *chain)
 {
        if (fw3_pr_debug)
        {
-               printf("-F %s\n", chain);
-               printf("-X %s\n", chain);
+               debug(h, "-F %s\n", chain);
+               debug(h, "-X %s\n", chain);
        }
 
        if (h->family == FW3_FAMILY_V6)
@@ -160,7 +187,7 @@ fw3_ipt_delete_rules(struct fw3_ipt_handle *h, const char *target)
                                        if (*t && !strcmp(t, target))
                                        {
                                                if (fw3_pr_debug)
-                                                       printf("-D %s %u\n", chain, num + 1);
+                                                       debug(h, "-D %s %u\n", chain, num + 1);
 
                                                ip6tc_delete_num_entry(chain, num, h->handle);
                                                found = true;
@@ -188,7 +215,7 @@ fw3_ipt_delete_rules(struct fw3_ipt_handle *h, const char *target)
                                        if (*t && !strcmp(t, target))
                                        {
                                                if (fw3_pr_debug)
-                                                       printf("-D %s %u\n", chain, num + 1);
+                                                       debug(h, "-D %s %u\n", chain, num + 1);
 
                                                iptc_delete_num_entry(chain, num, h->handle);
                                                found = true;
@@ -201,6 +228,22 @@ fw3_ipt_delete_rules(struct fw3_ipt_handle *h, const char *target)
 }
 
 void
+fw3_ipt_create_chain(struct fw3_ipt_handle *h, const char *fmt, ...)
+{
+       char buf[32];
+       va_list ap;
+
+       va_start(ap, fmt);
+       vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
+       va_end(ap);
+
+       if (fw3_pr_debug)
+               debug(h, "-N %s\n", buf);
+
+       iptc_create_chain(buf, h->handle);
+}
+
+void
 fw3_ipt_flush(struct fw3_ipt_handle *h)
 {
        const char *chain;
@@ -315,16 +358,14 @@ init_match(struct fw3_ipt_rule *r, struct xtables_match *m, bool no_clone)
        s = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size;
 
        m->m = fw3_alloc(s);
-       strcpy(m->m->u.user.name, m->real_name ? m->real_name : m->name);
+
+       fw3_xt_set_match_name(m);
+
        m->m->u.user.revision = m->revision;
        m->m->u.match_size = s;
 
        /* free previous userspace data */
-       if (m->udata_size)
-       {
-               free(m->udata);
-               m->udata = fw3_alloc(m->udata_size);
-       }
+       fw3_xt_free_match_udata(m);
 
        if (m->init)
                m->init(m->m);
@@ -335,14 +376,7 @@ init_match(struct fw3_ipt_rule *r, struct xtables_match *m, bool no_clone)
 
        /* merge option table */
        g = (r->h->family == FW3_FAMILY_V6) ? &xtg6 : &xtg;
-
-       if (m->x6_options)
-               g->opts = xtables_options_xfrm(g->orig_opts, g->opts,
-                                                                          m->x6_options, &m->option_offset);
-
-       if (m->extra_opts)
-               g->opts = xtables_merge_options(g->orig_opts, g->opts,
-                                                                               m->extra_opts, &m->option_offset);
+       fw3_xt_merge_match_options(g, m);
 }
 
 static bool
@@ -388,32 +422,20 @@ get_target(struct fw3_ipt_rule *r, const char *name)
        s = XT_ALIGN(sizeof(struct xt_entry_target)) + t->size;
        t->t = fw3_alloc(s);
 
-       if (!t->real_name)
-               strcpy(t->t->u.user.name, name);
-       else
-               strcpy(t->t->u.user.name, t->real_name);
+       fw3_xt_set_target_name(t, name);
 
        t->t->u.user.revision = t->revision;
        t->t->u.target_size = s;
 
-       if (t->udata_size)
-       {
-               free(t->udata);
-               t->udata = fw3_alloc(t->udata_size);
-       }
+       /* free previous userspace data */
+       fw3_xt_free_target_udata(t);
 
        if (t->init)
                t->init(t->t);
 
        /* merge option table */
        g = (r->h->family == FW3_FAMILY_V6) ? &xtg6 : &xtg;
-
-       if (t->x6_options)
-               g->opts = xtables_options_xfrm(g->orig_opts, g->opts,
-                                              t->x6_options, &t->option_offset);
-       else
-               g->opts = xtables_merge_options(g->orig_opts, g->opts,
-                                               t->extra_opts, &t->option_offset);
+       fw3_xt_merge_target_options(g, t);
 
        r->target = t;
 
@@ -975,7 +997,7 @@ rule_print(struct fw3_ipt_rule *r, const char *chain)
        struct xtables_match *m;
        struct xtables_target *t;
 
-       printf("-A %s", chain);
+       debug(r->h, "-A %s", chain);
 
        if (r->h->family == FW3_FAMILY_V6)
                rule_print6(&r->e6);
@@ -985,7 +1007,7 @@ rule_print(struct fw3_ipt_rule *r, const char *chain)
        for (rm = r->matches; rm; rm = rm->next)
        {
                m = rm->match;
-               printf(" -m %s", m->alias ? m->alias(m->m) : m->m->u.user.name);
+               printf(" -m %s", fw3_xt_get_match_name(m));
 
                if (m->save)
                        m->save(&r->e.ip, m->m);
@@ -994,7 +1016,7 @@ rule_print(struct fw3_ipt_rule *r, const char *chain)
        if (r->target)
        {
                t = r->target;
-               printf(" -j %s", t->alias ? t->alias(t->t) : t->t->u.user.name);
+               printf(" -j %s", fw3_xt_get_target_name(t));
 
                if (t->save)
                        t->save(&r->e.ip, t->t);
@@ -1010,7 +1032,7 @@ parse_option(struct fw3_ipt_rule *r, int optc, bool inv)
        struct xtables_match *em;
 
        /* is a target option */
-       if (r->target && (r->target->parse || r->target->x6_parse) &&
+       if (r->target && fw3_xt_has_target_parse(r->target) &&
                optc >= r->target->option_offset &&
                optc < (r->target->option_offset + 256))
        {
@@ -1023,7 +1045,7 @@ parse_option(struct fw3_ipt_rule *r, int optc, bool inv)
        {
                em = m->match;
 
-               if (m->completed || (!em->parse && !em->x6_parse))
+               if (m->completed || !fw3_xt_has_match_parse(em))
                        continue;
 
                if (optc < em->option_offset ||
@@ -1119,7 +1141,7 @@ fw3_ipt_rule_append(struct fw3_ipt_rule *r, const char *fmt, ...)
                        if (!em)
                        {
                                fprintf(stderr, "fw3_ipt_rule_append(): Can't find match '%s'\n", optarg);
-                               return;
+                               goto free;
                        }
 
                        init_match(r, em, true);
@@ -1131,7 +1153,7 @@ fw3_ipt_rule_append(struct fw3_ipt_rule *r, const char *fmt, ...)
                        if (!et)
                        {
                                fprintf(stderr, "fw3_ipt_rule_append(): Can't find target '%s'\n", optarg);
-                               return;
+                               goto free;
                        }
 
                        break;
@@ -1220,6 +1242,7 @@ fw3_ipt_rule_append(struct fw3_ipt_rule *r, const char *fmt, ...)
                free(e);
        }
 
+free:
        for (i = 1; i < r->argc; i++)
                free(r->argv[i]);
 
@@ -1227,7 +1250,9 @@ fw3_ipt_rule_append(struct fw3_ipt_rule *r, const char *fmt, ...)
 
        xtables_rule_matches_free(&r->matches);
 
-       free(r->target->t);
+       if (r->target)
+               free(r->target->t);
+
        free(r);
 
        /* reset all targets and matches */