contrib/fwd: generic drop target belongs into the drop chain
[project/luci.git] / contrib / fwd / src / fwd_rules.c
index e660491..6708e55 100644 (file)
@@ -45,7 +45,7 @@ static void fwd_r_jump_chain(
        if( (r = fwd_xt_init_rule(h)) != NULL )
        {
                fwd_xt_get_target(r, chain2);
-               fwd_xt_exec_rule(r, chain1);
+               fwd_xt_append_rule(r, chain1);
        }
 }
 
@@ -61,7 +61,7 @@ static void fwd_r_drop_invalid(struct iptc_handle *h, const char *chain)
                {
                        fwd_xt_parse_match(r, m, "--state", "INVALID");
                        fwd_xt_get_target(r, "DROP");
-                       fwd_xt_exec_rule(r, chain);
+                       fwd_xt_append_rule(r, chain);
                }
        }
 }
@@ -78,7 +78,7 @@ static void fwd_r_accept_related(struct iptc_handle *h, const char *chain)
                {
                        fwd_xt_parse_match(r, m, "--state", "RELATED,ESTABLISHED");
                        fwd_xt_get_target(r, "ACCEPT");
-                       fwd_xt_exec_rule(r, chain);
+                       fwd_xt_append_rule(r, chain);
                }
        }
 }
@@ -95,14 +95,14 @@ static void fwd_r_accept_lo(struct iptc_handle *h)
        {
                fwd_xt_parse_in(r, &n, 0);
                fwd_xt_get_target(r, "ACCEPT");
-               fwd_xt_exec_rule(r, "INPUT");
+               fwd_xt_append_rule(r, "INPUT");
        }
 
        if( (r = fwd_xt_init_rule(h)) != NULL )
        {
                fwd_xt_parse_out(r, &n, 0);
                fwd_xt_get_target(r, "ACCEPT");
-               fwd_xt_exec_rule(r, "OUTPUT");
+               fwd_xt_append_rule(r, "OUTPUT");
        }
 }
 
@@ -142,7 +142,7 @@ static void fwd_r_add_synflood(struct iptc_handle *h, struct fwd_defaults *def)
 
                /* -j RETURN; -A syn_flood */
                fwd_xt_get_target(r, "RETURN");
-               fwd_xt_exec_rule(r, "syn_flood");
+               fwd_xt_append_rule(r, "syn_flood");
        }
 
        /* drop rule */
@@ -150,7 +150,7 @@ static void fwd_r_add_synflood(struct iptc_handle *h, struct fwd_defaults *def)
        {       
                /* -j DROP; -A syn_flood */
                fwd_xt_get_target(r, "DROP");
-               fwd_xt_exec_rule(r, "syn_flood");
+               fwd_xt_append_rule(r, "syn_flood");
        }
 
        /* jump to syn_flood rule */
@@ -168,7 +168,7 @@ static void fwd_r_add_synflood(struct iptc_handle *h, struct fwd_defaults *def)
 
                /* -j syn_flood; -A INPUT */
                fwd_xt_get_target(r, "syn_flood");
-               fwd_xt_exec_rule(r, "INPUT");
+               fwd_xt_append_rule(r, "INPUT");
        }
 }
 
@@ -196,7 +196,7 @@ static void fwd_r_handle_reject(struct iptc_handle *h)
                }
 
                /* -A handle_reject */
-               fwd_xt_exec_rule(r, "handle_reject");
+               fwd_xt_append_rule(r, "handle_reject");
        }
 
        /* common reject rule */
@@ -210,7 +210,7 @@ static void fwd_r_handle_reject(struct iptc_handle *h)
                }
 
                /* -A handle_reject */
-               fwd_xt_exec_rule(r, "handle_reject");
+               fwd_xt_append_rule(r, "handle_reject");
        }
 }
 
@@ -225,9 +225,9 @@ static void fwd_r_handle_drop(struct iptc_handle *h)
        /* common drop rule */
        if( (r = fwd_xt_init_rule(h)) != NULL )
        {
-               /* -j DROP; -A handle_reject */
+               /* -j DROP; -A handle_drop */
                fwd_xt_get_target(r, "DROP");
-               fwd_xt_exec_rule(r, "handle_reject");
+               fwd_xt_append_rule(r, "handle_drop");
        }
 }
 
@@ -244,7 +244,7 @@ static void fwd_r_handle_accept(struct iptc_handle *h)
        {
                /* -j ACCEPT; -A handle_accept */
                fwd_xt_get_target(r, "ACCEPT");
-               fwd_xt_exec_rule(r, "handle_accept");
+               fwd_xt_append_rule(r, "handle_accept");
        }
 }
 
@@ -397,6 +397,25 @@ static void fwd_r_add_dnattarget(
        }
 }
 
+/* parse comment string and look for match */
+static int fwd_r_cmp(const char *what, const char *cmt, const char *cmp)
+{
+       char *match;
+
+       if( (match = strstr(cmt, what)) == NULL )
+               return 0;
+
+       match += strlen(what);
+
+       if( strncmp(match, cmp, strlen(cmp)) != 0 )
+               return 0;
+
+       if( (match[strlen(cmp)] != ' ') && (match[strlen(cmp)] != '\0') )
+               return 0;
+
+       return 1;
+}
+
 
 static void fwd_ipt_defaults_create(struct fwd_data *d)
 {
@@ -584,7 +603,7 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
                        fwd_xt_parse_out(x, n, 0);                                      /* -o ... */
                        fwd_xt_get_target(x, "MASQUERADE");                     /* -j MASQUERADE */
                        fwd_r_add_comment(x, "masq", z, NULL, n);       /* -m comment ... */
-                       fwd_xt_exec_rule(x, "zonemasq");                        /* -A zonemasq */
+                       fwd_xt_append_rule(x, "zonemasq");                      /* -A zonemasq */
                }
        }
 
@@ -611,7 +630,7 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
                        fwd_r_add_comment(x, "mssfix", z, NULL, n);
 
                        /* -A mssfix */
-                       fwd_xt_exec_rule(x, "mssfix");
+                       fwd_xt_append_rule(x, "mssfix");
                }
        }
 
@@ -631,7 +650,7 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
                                fwd_xt_parse_out(x, n2, 0);                             /* -o ... */
                                fwd_r_add_policytarget(x, z->forward);  /* -j handle_... */
                                fwd_r_add_comment(x, "zone", z, n, n2); /* -m comment ... */
-                               fwd_xt_exec_rule(x, "zones");                   /* -A zones */
+                               fwd_xt_append_rule(x, "zones");                 /* -A zones */
                        }
                }
        }
@@ -653,7 +672,7 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
                                fwd_xt_parse_out(x, n2, 0);                                     /* -o ... */
                                fwd_r_add_policytarget(x, FWD_P_ACCEPT);        /* -j handle_... */
                                fwd_r_add_comment(x, "forward", z, n, n2);      /* -m comment ... */
-                               fwd_xt_exec_rule(x, "forwardings");                     /* -A forwardings */
+                               fwd_xt_append_rule(x, "forwardings");                   /* -A forwardings */
                        }
                }
        }
@@ -676,7 +695,7 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
                        fwd_r_add_srcmac(x, r->src_mac);                        /* -m mac --mac-source ... */
                        fwd_r_add_dnattarget(x, r->dest_ip, r->dest_port);      /* -j DNAT ... */
                        fwd_r_add_comment(x, "redir", z, n, NULL);      /* -m comment ... */
-                       fwd_xt_exec_rule(x, "redirects");                       /* -A redirects */
+                       fwd_xt_append_rule(x, "redirects");                     /* -A redirects */
                }
 
                /* Forward */
@@ -691,7 +710,7 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
                        fwd_r_add_dport(x, r->dest_port);                       /* --dport ... */
                        fwd_r_add_policytarget(x, FWD_P_ACCEPT);        /* -j handle_accept */
                        fwd_r_add_comment(x, "redir", z, n, NULL);      /* -m comment ... */
-                       fwd_xt_exec_rule(x, "redirects");                       /* -A redirects */
+                       fwd_xt_append_rule(x, "redirects");                     /* -A redirects */
                }
 
                /* Add loopback rule if neither src_ip nor src_mac are defined */
@@ -706,7 +725,7 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
                                fwd_r_add_dport(x, r->src_dport);                       /* --dport ... */
                                fwd_xt_get_target(x, "MASQUERADE");                     /* -j MASQUERADE */
                                fwd_r_add_comment(x, "redir", z, n, NULL);      /* -m comment ... */
-                               fwd_xt_exec_rule(x, "loopback");                        /* -A loopback */
+                               fwd_xt_append_rule(x, "loopback");                      /* -A loopback */
                        }
                }
        }
@@ -737,7 +756,7 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
                                        fwd_r_add_dport(x, c->dest_port);               /* --dport ... */
                                        fwd_r_add_policytarget(x, c->target);   /* -j handle_... */
                                        fwd_r_add_comment(x, "rule", z, n, n2); /* -m comment ... */
-                                       fwd_xt_exec_rule(x, "rules");                   /* -A rules */
+                                       fwd_xt_append_rule(x, "rules");                 /* -A rules */
                                }
                        }
                }
@@ -760,10 +779,134 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
                                fwd_r_add_dport(x, c->dest_port);                       /* --dport ... */
                                fwd_r_add_policytarget(x, c->target);           /* -j handle_... */
                                fwd_r_add_comment(x, "rule", z, n, NULL);       /* -m comment ... */
-                               fwd_xt_exec_rule(x, "rules");                           /* -A rules */
+                               fwd_xt_append_rule(x, "rules");                         /* -A rules */
+                       }
+               }
+       }
+
+       if( !iptc_commit(h_nat) )
+               fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));
+
+       if( !iptc_commit(h_filter) )
+               fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));
+
+       iptc_free(h_nat);
+       iptc_free(h_filter);
+}
+
+
+static void fwd_ipt_delif_table(struct iptc_handle *h, const char *net)
+{
+       struct xt_entry_match *m;
+       struct ipt_entry *e;
+       const char *chain, *comment;
+       size_t off = 0, num = 0;
+
+       /* iterate chains */
+       for( chain = iptc_first_chain(h); chain;
+            chain = iptc_next_chain(h)
+       ) {
+               /* iterate rules */
+               for( e = iptc_first_rule(chain, h), num = 0; e;
+                    e = iptc_next_rule(e, h), num++
+               ) {
+                       repeat_rule:
+
+                       /* skip entries w/o matches */
+                       if( ! e->target_offset )
+                               continue;
+
+                       /* iterate matches */
+                       for( off = sizeof(struct ipt_entry);
+                            off < e->target_offset;
+                            off += m->u.match_size
+                       ) {
+                               m = (void *)e + off;
+
+                               /* yay */
+                               if( ! strcmp(m->u.user.name, "comment") )
+                               {
+                                       /* better use struct_xt_comment_info but well... */
+                                       comment = (void *)m + sizeof(struct xt_entry_match);
+
+                                       if( fwd_r_cmp("src:", comment, net) )
+                                       {
+                                               e = iptc_next_rule(e, h);
+                                               iptc_delete_num_entry(chain, num, h);
+
+                                               if( e != NULL )
+                                                       goto repeat_rule;
+                                               else
+                                                       break;
+                                       }
+                               }
                        }
                }
        }
+}
+
+void fwd_ipt_delif(struct fwd_handle *h, const char *net)
+{
+       struct iptc_handle *h_filter, *h_nat;
+
+       if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
+               fwd_fatal("Unable to obtain libiptc handle");
+
+
+       printf("\n\n#\n# delif(%s)\n#\n", net);
+
+       /* delete network related rules */
+       fwd_ipt_delif_table(h_nat, net);
+       fwd_ipt_delif_table(h_filter, net);
+
+
+       if( !iptc_commit(h_nat) )
+               fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));
+
+       if( !iptc_commit(h_filter) )
+               fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));
+
+       iptc_free(h_nat);
+       iptc_free(h_filter);
+}
+
+
+static void fwd_ipt_clear_ruleset_table(struct iptc_handle *h)
+{
+       const char *chain;
+
+       /* pass 1: flush all chains */
+       for( chain = iptc_first_chain(h); chain;
+            chain = iptc_next_chain(h)
+       ) {
+               iptc_flush_entries(chain, h);
+       }
+
+       /* pass 2: remove user defined chains */
+       for( chain = iptc_first_chain(h); chain;
+            chain = iptc_next_chain(h)
+       ) {
+               if( ! iptc_builtin(chain, h) )
+                       iptc_delete_chain(chain, h);
+       }
+}
+
+void fwd_ipt_clear_ruleset(struct fwd_handle *h)
+{
+       struct iptc_handle *h_filter, *h_nat;
+
+       if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
+               fwd_fatal("Unable to obtain libiptc handle");
+
+       /* flush tables */
+       fwd_ipt_clear_ruleset_table(h_nat);
+       fwd_ipt_clear_ruleset_table(h_filter);
+
+       /* revert policies */
+       fwd_r_set_policy(h_filter, "INPUT", "ACCEPT");
+       fwd_r_set_policy(h_filter, "OUTPUT", "ACCEPT");
+       fwd_r_set_policy(h_filter, "FORWARD", "ACCEPT");        
+
 
        if( !iptc_commit(h_nat) )
                fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));