Jelajahi Sumber

ncd: modules: net_iptables: add ebtables commands

ambrop7 13 tahun lalu
induk
melakukan
8df35491bd
1 mengubah file dengan 121 tambahan dan 76 penghapusan
  1. 121 76
      ncd/modules/net_iptables.c

+ 121 - 76
ncd/modules/net_iptables.c

@@ -28,13 +28,14 @@
  * 
  * @section DESCRIPTION
  * 
- * iptables module.
+ * iptables and ebtables module.
  * 
- * Note that all iptables commands (in general) must be issued synchronously, or
- * the kernel may randomly report errors if there is another iptables command in progress.
- * To solve this, the NCD process contains a single "iptables lock". All iptables commands
- * exposed here go through that lock.
- * In case you wish to call iptables directly, the lock is exposed via net.iptables.lock().
+ * Note that all iptables/ebtables commands (in general) must be issued synchronously, or
+ * the kernel may randomly report errors if there is another iptables/ebtables command in
+ * progress. To solve this, the NCD process contains a single "iptables lock". All
+ * iptables/ebtables commands exposed here go through that lock.
+ * In case you wish to call iptables/ebtables directly, the lock is exposed via
+ * net.iptables.lock().
  * 
  * Synopsis:
  *   net.iptables.append(string table, string chain, string arg1  ...)
@@ -49,27 +50,46 @@
  *   deinit: iptables -t table -P chain revert_target
  * 
  * Synopsis:
- *   net.iptables.newchain(string chain)
+ *   net.iptables.newchain(string table, string chain)
+ *   net.iptables.newchain(string chain) // DEPRECATED, defaults to table="filter"
  * Description:
- *   init:   iptables -N chain
- *   deinit: iptables -X chain
+ *   init:   iptables -t table -N chain
+ *   deinit: iptables -t table -X chain
+ * 
+ * Synopsis:
+ *   net.ebtables.append(string table, string chain, string arg1 ...)
+ * Description:
+ *   init:   ebtables -t table -A chain arg1 ...
+ *   deinit: ebtables -t table -D chain arg1 ...
+ * 
+ * Synopsis:
+ *   net.ebtables.policy(string table, string chain, string target, string revert_target)
+ * Description:
+ *   init:   ebtables -t table -P chain target
+ *   deinit: ebtables -t table -P chain revert_target
+ * 
+ * Synopsis:
+ *   net.ebtables.newchain(string table, string chain)
+ * Description:
+ *   init:   ebtables -t table -N chain
+ *   deinit: ebtables -t table -X chain
  * 
  * Synopsis:
  *   net.iptables.lock()
  * Description:
- *   Use at the beginning of a block of custom iptables commands to make sure
- *   they do not interfere with other iptables commands.
+ *   Use at the beginning of a block of custom iptables/ebtables commands to make sure
+ *   they do not interfere with other iptables/ebtables commands.
  *   WARNING: improper usage of the lock can lead to deadlock. In particular:
- *   - Do not call any of the iptables wrappers above from a lock section; those
- *     will attempt to aquire the lock themselves.
+ *   - Do not call any of the iptables/ebtables wrappers above from a lock section;
+ *     those will attempt to aquire the lock themselves.
  *   - Do not enter another lock section from a lock section.
  *   - Do not perform any potentially long wait from a lock section.
  * 
  * Synopsis:
  *   net.iptables.lock::unlock()
  * Description:
- *   Use at the end of a block of custom iptables commands to make sure
- *   they do not interfere with other iptables commands.
+ *   Use at the end of a block of custom iptables/ebtables commands to make sure
+ *   they do not interfere with other iptables/ebtables commands.
  */
 
 #include <stdlib.h>
@@ -77,6 +97,7 @@
 #include <unistd.h>
 
 #include <misc/debug.h>
+#include <misc/find_program.h>
 #include <ncd/BEventLock.h>
 
 #include <ncd/modules/command_template.h>
@@ -85,9 +106,6 @@
 
 #define ModuleLog(i, ...) NCDModuleInst_Backend_Log((i), BLOG_CURRENT_CHANNEL, __VA_ARGS__)
 
-#define IPTABLES_PATH "/sbin/iptables"
-#define IPTABLES_PATH2 "/usr/sbin/iptables"
-
 static void template_free_func (void *vo, int is_error);
 
 BEventLock iptables_lock;
@@ -118,21 +136,7 @@ struct unlock_instance {
 
 static void unlock_free (struct unlock_instance *o);
 
-static const char *find_iptables (NCDModuleInst *i)
-{
-    if (access(IPTABLES_PATH, X_OK) == 0) {
-        return IPTABLES_PATH;
-    }
-    
-    if (access(IPTABLES_PATH2, X_OK) == 0) {
-        return IPTABLES_PATH2;
-    }
-    
-    ModuleLog(i, BLOG_ERROR, "failed to find iptables (tried "IPTABLES_PATH" and "IPTABLES_PATH2")");
-    return NULL;
-}
-
-static int build_append_cmdline (NCDModuleInst *i, int remove, char **exec, CmdLine *cl)
+static int build_append_cmdline (NCDModuleInst *i, const char *prog, int remove, char **exec, CmdLine *cl)
 {
     // read arguments
     NCDValue *table_arg;
@@ -148,15 +152,9 @@ static int build_append_cmdline (NCDModuleInst *i, int remove, char **exec, CmdL
     char *table = NCDValue_StringValue(table_arg);
     char *chain = NCDValue_StringValue(chain_arg);
     
-    // find iptables
-    const char *iptables_path = find_iptables(i);
-    if (!iptables_path) {
-        goto fail0;
-    }
-    
-    // alloc exec
-    if (!(*exec = strdup(iptables_path))) {
-        ModuleLog(i, BLOG_ERROR, "strdup failed");
+    // find program
+    if (!(*exec = badvpn_find_program(prog))) {
+        ModuleLog(i, BLOG_ERROR, "failed to find program: %s", prog);
         goto fail0;
     }
     
@@ -167,7 +165,7 @@ static int build_append_cmdline (NCDModuleInst *i, int remove, char **exec, CmdL
     }
     
     // add header
-    if (!CmdLine_Append(cl, iptables_path) || !CmdLine_Append(cl, "-t") || !CmdLine_Append(cl, table) || !CmdLine_Append(cl, (remove ? "-D" : "-A")) || !CmdLine_Append(cl, chain)) {
+    if (!CmdLine_Append(cl, *exec) || !CmdLine_Append(cl, "-t") || !CmdLine_Append(cl, table) || !CmdLine_Append(cl, (remove ? "-D" : "-A")) || !CmdLine_Append(cl, chain)) {
         ModuleLog(i, BLOG_ERROR, "CmdLine_Append failed");
         goto fail2;
     }
@@ -204,7 +202,7 @@ fail0:
     return 0;
 }
 
-static int build_policy_cmdline (NCDModuleInst *i, int remove, char **exec, CmdLine *cl)
+static int build_policy_cmdline (NCDModuleInst *i, const char *prog, int remove, char **exec, CmdLine *cl)
 {
     // read arguments
     NCDValue *table_arg;
@@ -226,15 +224,9 @@ static int build_policy_cmdline (NCDModuleInst *i, int remove, char **exec, CmdL
     char *target = NCDValue_StringValue(target_arg);
     char *revert_target = NCDValue_StringValue(revert_target_arg);
     
-    // find iptables
-    const char *iptables_path = find_iptables(i);
-    if (!iptables_path) {
-        goto fail0;
-    }
-    
-    // alloc exec
-    if (!(*exec = strdup(iptables_path))) {
-        ModuleLog(i, BLOG_ERROR, "strdup failed");
+    // find program
+    if (!(*exec = badvpn_find_program(prog))) {
+        ModuleLog(i, BLOG_ERROR, "failed to find program: %s", prog);
         goto fail0;
     }
     
@@ -245,7 +237,7 @@ static int build_policy_cmdline (NCDModuleInst *i, int remove, char **exec, CmdL
     }
     
     // add arguments
-    if (!CmdLine_Append(cl, iptables_path) || !CmdLine_Append(cl, "-t") || !CmdLine_Append(cl, table) ||
+    if (!CmdLine_Append(cl, *exec) || !CmdLine_Append(cl, "-t") || !CmdLine_Append(cl, table) ||
         !CmdLine_Append(cl, "-P") || !CmdLine_Append(cl, chain) || !CmdLine_Append(cl, (remove ? revert_target : target))) {
         ModuleLog(i, BLOG_ERROR, "CmdLine_Append failed");
         goto fail2;
@@ -267,29 +259,25 @@ fail0:
     return 0;
 }
 
-static int build_newchain_cmdline (NCDModuleInst *i, int remove, char **exec, CmdLine *cl)
+static int build_newchain_cmdline (NCDModuleInst *i, const char *prog, int remove, char **exec, CmdLine *cl)
 {
     // read arguments
+    NCDValue *table_arg = NULL;
     NCDValue *chain_arg;
-    if (!NCDValue_ListRead(i->args, 1, &chain_arg)) {
+    if (!NCDValue_ListRead(i->args, 1, &chain_arg) && !NCDValue_ListRead(i->args, 2, &table_arg, &chain_arg)) {
         ModuleLog(i, BLOG_ERROR, "wrong arity");
         goto fail0;
     }
-    if (!NCDValue_IsStringNoNulls(chain_arg)) {
+    if ((table_arg && !NCDValue_IsStringNoNulls(table_arg)) || !NCDValue_IsStringNoNulls(chain_arg)) {
         ModuleLog(i, BLOG_ERROR, "wrong type");
         goto fail0;
     }
+    char *table = (!table_arg ? "filter" : NCDValue_StringValue(table_arg));
     char *chain = NCDValue_StringValue(chain_arg);
     
-    // find iptables
-    const char *iptables_path = find_iptables(i);
-    if (!iptables_path) {
-        goto fail0;
-    }
-    
-    // alloc exec
-    if (!(*exec = strdup(iptables_path))) {
-        ModuleLog(i, BLOG_ERROR, "strdup failed");
+    // find program
+    if (!(*exec = badvpn_find_program(prog))) {
+        ModuleLog(i, BLOG_ERROR, "failed to find program: %s", prog);
         goto fail0;
     }
     
@@ -300,7 +288,7 @@ static int build_newchain_cmdline (NCDModuleInst *i, int remove, char **exec, Cm
     }
     
     // add arguments
-    if (!CmdLine_AppendMulti(cl, 3, iptables_path, (remove ? "-X" : "-N"), chain)) {
+    if (!CmdLine_AppendMulti(cl, 5, *exec, "-t", table, (remove ? "-X" : "-N"), chain)) {
         ModuleLog(i, BLOG_ERROR, "CmdLine_AppendMulti failed");
         goto fail2;
     }
@@ -321,6 +309,36 @@ fail0:
     return 0;
 }
 
+static int build_iptables_append_cmdline (NCDModuleInst *i, int remove, char **exec, CmdLine *cl)
+{
+    return build_append_cmdline(i, "iptables", remove, exec, cl);
+}
+
+static int build_iptables_policy_cmdline (NCDModuleInst *i, int remove, char **exec, CmdLine *cl)
+{
+    return build_policy_cmdline(i, "iptables", remove, exec, cl);
+}
+
+static int build_iptables_newchain_cmdline (NCDModuleInst *i, int remove, char **exec, CmdLine *cl)
+{
+    return build_newchain_cmdline(i, "iptables", remove, exec, cl);
+}
+
+static int build_ebtables_append_cmdline (NCDModuleInst *i, int remove, char **exec, CmdLine *cl)
+{
+    return build_append_cmdline(i, "ebtables", remove, exec, cl);
+}
+
+static int build_ebtables_policy_cmdline (NCDModuleInst *i, int remove, char **exec, CmdLine *cl)
+{
+    return build_policy_cmdline(i, "ebtables", remove, exec, cl);
+}
+
+static int build_ebtables_newchain_cmdline (NCDModuleInst *i, int remove, char **exec, CmdLine *cl)
+{
+    return build_newchain_cmdline(i, "ebtables", remove, exec, cl);
+}
+
 static void lock_job_handler (struct lock_instance *o)
 {
     ASSERT(o->state == LOCK_STATE_LOCKING || o->state == LOCK_STATE_RELOCKING)
@@ -396,19 +414,34 @@ void template_free_func (void *vo, int is_error)
     NCDModuleInst_Backend_Dead(i);
 }
 
-static void append_func_new (NCDModuleInst *i)
+static void append_iptables_func_new (NCDModuleInst *i)
 {
-    func_new(i, build_append_cmdline);
+    func_new(i, build_iptables_append_cmdline);
 }
 
-static void policy_func_new (NCDModuleInst *i)
+static void policy_iptables_func_new (NCDModuleInst *i)
 {
-    func_new(i, build_policy_cmdline);
+    func_new(i, build_iptables_policy_cmdline);
 }
 
-static void newchain_func_new (NCDModuleInst *i)
+static void newchain_iptables_func_new (NCDModuleInst *i)
 {
-    func_new(i, build_newchain_cmdline);
+    func_new(i, build_iptables_newchain_cmdline);
+}
+
+static void append_ebtables_func_new (NCDModuleInst *i)
+{
+    func_new(i, build_ebtables_append_cmdline);
+}
+
+static void policy_ebtables_func_new (NCDModuleInst *i)
+{
+    func_new(i, build_ebtables_policy_cmdline);
+}
+
+static void newchain_ebtables_func_new (NCDModuleInst *i)
+{
+    func_new(i, build_ebtables_newchain_cmdline);
 }
 
 static void func_die (void *vo)
@@ -561,15 +594,27 @@ static void unlock_free (struct unlock_instance *o)
 static const struct NCDModule modules[] = {
     {
         .type = "net.iptables.append",
-        .func_new = append_func_new,
+        .func_new = append_iptables_func_new,
         .func_die = func_die
     }, {
         .type = "net.iptables.policy",
-        .func_new = policy_func_new,
+        .func_new = policy_iptables_func_new,
         .func_die = func_die
     }, {
         .type = "net.iptables.newchain",
-        .func_new = newchain_func_new,
+        .func_new = newchain_iptables_func_new,
+        .func_die = func_die
+    }, {
+        .type = "net.ebtables.append",
+        .func_new = append_ebtables_func_new,
+        .func_die = func_die
+    }, {
+        .type = "net.ebtables.policy",
+        .func_new = policy_ebtables_func_new,
+        .func_die = func_die
+    }, {
+        .type = "net.ebtables.newchain",
+        .func_new = newchain_ebtables_func_new,
         .func_die = func_die
     }, {
         .type = "net.iptables.lock",