[netcf-devel] [PATCH 4/4] Only read/modify iptables config if bridge packets pass through it

David Lutterkort lutter at redhat.com
Thu Sep 10 19:28:46 UTC 2009


When /proc/sys/net/bridge/bridge-nf-call-iptables is 0, there is no need to
go anywhere near the iptables config. We make sure we do not even try to
read iptables-related files in that case.

Fixes part of BZ 517617
---
 src/drv_initscripts.c |   30 ++++++++++++++++++++++--------
 src/dutil_linux.c     |   26 ++++++++++++++++++++++++++
 src/dutil_linux.h     |    4 ++++
 src/netcf.c           |    3 ++-
 src/netcf.h           |    3 ++-
 5 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/src/drv_initscripts.c b/src/drv_initscripts.c
index 6436bcc..e17d834 100644
--- a/src/drv_initscripts.c
+++ b/src/drv_initscripts.c
@@ -65,9 +65,6 @@ static const struct augeas_pv augeas_xfm_common_pv[] = {
     { "/augeas/load/Ifcfg/excl[6]", "*.rpmsave" },
     { "/augeas/load/Ifcfg/excl[7]", "*.augnew" },
     { "/augeas/load/Ifcfg/excl[8]", "*.augsave" },
-    /* iptables config */
-    { "/augeas/load/Iptables/lens", "Iptables.lns" },
-    { "/augeas/load/Iptables/incl", "/etc/sysconfig/iptables" },
     /* modprobe config */
     { "/augeas/load/Modprobe/lens", "Modprobe.lns" },
     { "/augeas/load/Modprobe/incl[1]", "/etc/modprobe.d/*" },
@@ -77,9 +74,6 @@ static const struct augeas_pv augeas_xfm_common_pv[] = {
     { "/augeas/load/Modprobe/excl[3]", "*.rpmsave" },
     { "/augeas/load/Modprobe/excl[4]", "*.rpmnew" },
     { "/augeas/load/Modprobe/excl[5]", "*~" },
-    /* lokkit */
-    { "/augeas/load/Lokkit/lens", "Lokkit.lns" },
-    { "/augeas/load/Lokkit/incl", "/etc/sysconfig/system-config-firewall" },
     /* sysfs (choice entries from /class/net) */
     { "/augeas/load/Sysfs/lens", "Netcf.id" },
     { "/augeas/load/Sysfs/incl", "/sys/class/net/*/address" }
@@ -89,6 +83,19 @@ static const struct augeas_xfm_table augeas_xfm_common =
     { .size = ARRAY_CARDINALITY(augeas_xfm_common_pv),
       .pv = augeas_xfm_common_pv };
 
+static const struct augeas_pv augeas_xfm_iptables_pv[] = {
+    /* iptables config */
+    { "/augeas/load/Iptables/lens", "Iptables.lns" },
+    { "/augeas/load/Iptables/incl", "/etc/sysconfig/iptables" },
+    /* lokkit */
+    { "/augeas/load/Lokkit/lens", "Lokkit.lns" },
+    { "/augeas/load/Lokkit/incl", "/etc/sysconfig/system-config-firewall" },
+};
+
+static const struct augeas_xfm_table augeas_xfm_iptables =
+    { .size = ARRAY_CARDINALITY(augeas_xfm_iptables_pv),
+      .pv = augeas_xfm_iptables_pv };
+
 static const char *const prog_lokkit = "/usr/sbin/lokkit";
 static const char *const lokkit_custom_rules =
     "--custom-rules=ipv4:filter:" DATADIR "/netcf/iptables-forward-bridged";
@@ -347,8 +354,15 @@ static void bridge_physdevs(struct netcf *ncf) {
     int have_lokkit, use_lokkit;
     int r, nmatches;
 
+    /* If bridge packets never hit iptables, nothing to worry about */
+    if (! bridge_nf_call_iptables(ncf))
+        return;
+    ERR_BAIL(ncf);
+
     MEMZERO(argv, ARRAY_CARDINALITY(argv));
 
+    add_augeas_xfm_table(ncf, &augeas_xfm_iptables);
+
     aug = get_augeas(ncf);
     ERR_BAIL(ncf);
 
@@ -359,7 +373,7 @@ static void bridge_physdevs(struct netcf *ncf) {
       "$iptables/table[ . = 'filter']/*[. = 'FORWARD'][match = 'physdev']", NULL);
     ERR_THROW(nmatches < 0, ncf, EOTHER, "failed to look for bridge");
     if (nmatches > 0)
-        return;
+        goto error;
 
     have_lokkit = access(prog_lokkit, X_OK) == 0;
     use_lokkit = aug_match(aug,
@@ -445,6 +459,7 @@ static void bridge_physdevs(struct netcf *ncf) {
         ERR_BAIL(ncf);
     }
  error:
+    remove_augeas_xfm_table(ncf, &augeas_xfm_iptables);
     free(path);
     free(p);
     return;
@@ -467,7 +482,6 @@ int drv_init(struct netcf *ncf) {
     ncf->driver->get = parse_stylesheet(ncf, "initscripts-get.xsl");
     ncf->driver->put = parse_stylesheet(ncf, "initscripts-put.xsl");
     ncf->driver->rng = rng_parse(ncf, "interface.rng");
-    /* We undconditionally bridge physdevs; could be more discriminating */
     bridge_physdevs(ncf);
 
     /* open a socket for interface ioctls */
diff --git a/src/dutil_linux.c b/src/dutil_linux.c
index 154a8b1..47e6717 100644
--- a/src/dutil_linux.c
+++ b/src/dutil_linux.c
@@ -32,6 +32,7 @@
 #include <unistd.h>
 #include <ctype.h>
 #include <c-ctype.h>
+#include <errno.h>
 
 #include "safe-alloc.h"
 #include "ref.h"
@@ -151,6 +152,31 @@ void modprobed_unalias_bond(struct netcf *ncf, const char *name) {
     FREE(path);
 }
 
+bool bridge_nf_call_iptables(struct netcf *ncf) {
+    static const char *const proc_bridge_nf_call_iptables =
+        "proc/sys/net/bridge/bridge-nf-call-iptables";
+    char *path = NULL;
+    FILE *proc = NULL;
+    int r, c;
+
+    r = xasprintf(&path, "%s%s", ncf->root, proc_bridge_nf_call_iptables);
+    ERR_NOMEM(r < 0, ncf);
+
+    proc = fopen(path, "r");
+    ERR_THROW(proc == NULL, ncf, EFILE, "can not open %s: %s",
+              path, strerror(errno));
+    c = fgetc(proc);
+    ERR_THROW(c == EOF, ncf, EFILE, "nothing to read from %s: %s",
+              path, strerror(errno));
+    fclose(proc);
+    return c == '1';
+ error:
+    FREE(path);
+    if (proc != NULL)
+        fclose(proc);
+    return false;
+}
+
 /*
  * Local variables:
  *  indent-tabs-mode: nil
diff --git a/src/dutil_linux.h b/src/dutil_linux.h
index af76c3e..315820e 100644
--- a/src/dutil_linux.h
+++ b/src/dutil_linux.h
@@ -45,6 +45,10 @@ void modprobed_alias_bond(struct netcf *ncf, const char *name);
 /* Remove an 'alias NAME bonding' as created by modprobed_alias_bond */
 void modprobed_unalias_bond(struct netcf *ncf, const char *name);
 
+/* Look at /proc/sys/net/bridge/bridge-nf-call-iptables and return TRUE
+ * if bridge packets pass through iptables, FALSE otherwise
+ */
+bool bridge_nf_call_iptables(struct netcf *ncf);
 #endif
 
 /*
diff --git a/src/netcf.c b/src/netcf.c
index 8073af5..2907349 100644
--- a/src/netcf.c
+++ b/src/netcf.c
@@ -53,7 +53,8 @@ static const char *const errmsgs[] = {
     "required entry missing",             /* ENOENT */
     "failed to execute external program", /* EEXEC */
     "instance still in use",              /* EINUSE */
-    "XSLT transformation failed"          /* EXSLTFAILED */
+    "XSLT transformation failed",         /* EXSLTFAILED */
+    "File operation failed"               /* EFILE */
 };
 
 static void free_netcf(struct netcf *ncf) {
diff --git a/src/netcf.h b/src/netcf.h
index e08e94b..482b6d0 100644
--- a/src/netcf.h
+++ b/src/netcf.h
@@ -50,7 +50,8 @@ typedef enum {
                           * non-0 */
     NETCF_EINUSE,        /* attempt to close a netcf instance that is still
                           * used by other data structures */
-    NETCF_EXSLTFAILED    /* XSLT transformation failed */
+    NETCF_EXSLTFAILED,   /* XSLT transformation failed */
+    NETCF_EFILE          /* Some file access failed */
 } netcf_errcode_t;
 
 
-- 
1.6.2.5



More information about the netcf-devel mailing list