contrib/fwd: implement fwd_ipt_delif() and fwd_ipt_clear_ruleset()
authorJo-Philipp Wich <jow@openwrt.org>
Thu, 17 Dec 2009 01:07:44 +0000 (01:07 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Thu, 17 Dec 2009 01:07:44 +0000 (01:07 +0000)
contrib/fwd/src/fwd.c
contrib/fwd/src/fwd_rules.c
contrib/fwd/src/fwd_rules.h

index 9d925bc00a7baf519918bbb5cb5b8c130d2a0604..903834b10470111caab8334a613c81b8a277c753 100644 (file)
@@ -27,7 +27,6 @@
 int main(int argc, const char *argv[])
 {
        struct fwd_handle *h;
-       struct iptc_handle *ipt;
 
        if( getuid() > 0 )
                fwd_fatal("Need root permissions!");
@@ -49,6 +48,13 @@ int main(int argc, const char *argv[])
        fwd_ipt_addif(h, "lan");
        fwd_ipt_addif(h, "wan");
 
+       sleep(1);
+
+       fwd_ipt_delif(h, "wan");
+       fwd_ipt_delif(h, "lan");
+
+       fwd_ipt_clear_ruleset(h);
+
        close(h->rtnl_socket);
        fwd_free_config(h->conf);
        fwd_free_addrs(h->addrs);
index e6604911a73b6c59b03bc1189e5b1d35627cb65d..141ce8565c80335862b724a7ec18180554e3c1b5 100644 (file)
@@ -397,6 +397,27 @@ 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;
+
+       printf("CMP: %s %s %s\n", what, cmt, cmp);
+
+       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)
 {
@@ -775,3 +796,127 @@ void fwd_ipt_addif(struct fwd_handle *h, const char *net)
        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));
+
+       if( !iptc_commit(h_filter) )
+               fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));
+
+       iptc_free(h_nat);
+       iptc_free(h_filter);
+}
+
index 7074622e340f6cee98c3e00b714e9ad6f1d4f2f9..f3492c58019204e6d23cd2b2541de672bc473f86 100644 (file)
 
 #include "fwd.h"
 
-#define IPT "iptables"
-
-struct fwd_ipt_rulebuf {
-       char *buf;
-       size_t len;
-};
-
-
-#define fwd_ipt_add_format fwd_ipt_rule_append
-
-#define fwd_ipt_exec_format(t, ...) do {         \
-       struct fwd_ipt_rulebuf *r = fwd_ipt_init(t); \
-       fwd_ipt_add_format(r, __VA_ARGS__);          \
-       fwd_ipt_exec(r);                             \
-} while(0)
-
 void fwd_ipt_build_ruleset(struct fwd_handle *h);
+void fwd_ipt_clear_ruleset(struct fwd_handle *h);
+
 void fwd_ipt_addif(struct fwd_handle *h, const char *net);
+void fwd_ipt_delif(struct fwd_handle *h, const char *net);
 
 #endif