]> xenbits.xensource.com Git - libvirt.git/commitdiff
Add support for integrating our iptables support with Fedora's
authorMark McLoughlin <markmc@redhat.com>
Thu, 10 Jan 2008 13:54:02 +0000 (13:54 +0000)
committerMark McLoughlin <markmc@redhat.com>
Thu, 10 Jan 2008 13:54:02 +0000 (13:54 +0000)
iptables configuration using the lokkit --custom-rules command.

Basically, we write out our rules to /var/lib/libvirt/iptables
and run lokkit --custom-rules so that if e.g. iptables is
restarted or the user edits their firewall configuration, then
libvirt's rules get reloaded.

ChangeLog
configure.in
src/iptables.c

index 3add06a58efe7ca90e0e4c5fa00b4c39bb269822..b0cda86679c6e60693525d191df82d34e0febe69 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Thu Jan 10 13:52:05 GMT 2008 Mark McLoughlin <markmc@redhat.com>
+
+       Add support for integrating our iptables support with
+       Fedora's iptables configuration using the lokkit --custom-rules
+       command.
+
+       Basically, we write out our rules to /var/lib/libvirt/iptables
+       and run lokkit --custom-rules so that if e.g. iptables is
+       restarted or the user edits their firewall configuration,
+       then libvirt's rules get reloaded.
+
+       * configure.in: Add --enable-iptables-lokkit
+
+       * src/iptables.c: Add support for lokkit
+
 Thu Jan 10 13:51:00 GMT 2008 Mark McLoughlin <markmc@redhat.com>
 
        * src/iptables.c: Include the iptables command and chain
index bc56c2c3053bb95545e5cbed83c3621fd6f6305c..fe36718fb03911d4dd90b1996ae7522bdb4cf131 100644 (file)
@@ -204,6 +204,27 @@ if test x"$IPTABLES_DIR" != "x"; then
    AC_DEFINE_UNQUOTED(IPTABLES_DIR, "$IPTABLES_DIR", [directory used for saving iptables chains])
 fi
 
+dnl
+dnl ensure that Fedora's system-config-firewall knows
+dnl about libvirt's iptables rules
+dnl
+AC_ARG_ENABLE(iptables-lokkit,
+              AC_HELP_STRING([--enable-iptables-lokkit=no/yes/check],
+                             [enable registering libvirt's iptables rules with Fedora's lokkit]),
+                             [],[enable_iptables_lokkit=check])
+if test x"$enable_iptables_lokkit" != x"no"; then
+   AC_PATH_PROG(LOKKIT_PATH, lokkit, [], [/usr/sbin:$PATH])
+fi
+
+if test x"$enable_iptables_lokkit" = x"yes" -a x"$LOKKIT_PATH" = x; then
+   AC_MSG_ERROR([Cannot find lokkit and --enable-iptables-lokkit specified])
+fi
+
+if test x"$LOKKIT_PATH" != x; then
+   AC_DEFINE(ENABLE_IPTABLES_LOKKIT, [], [whether support for Fedora's lokkit is enabled])
+   AC_DEFINE_UNQUOTED(LOKKIT_PATH, "$LOKKIT_PATH", [path to lokkit binary])
+fi
+
 AC_PATH_PROG(IPTABLES_PATH, iptables, /sbin/iptables)
 AC_DEFINE_UNQUOTED(IPTABLES_PATH, "$IPTABLES_PATH", [path to iptables binary])
 
index e66bc6495a2a61c95d63c989f831f0c9ccd47971..21363ba1a6908fb9db95c1b08e926f7f1aeac7ba 100644 (file)
 
 #define qemudLog(level, msg...) fprintf(stderr, msg)
 
+#ifdef ENABLE_IPTABLES_LOKKIT
+#undef IPTABLES_DIR
+#define IPTABLES_DIR LOCAL_STATE_DIR "/lib/libvirt/iptables"
+#endif
+
 enum {
     ADD = 0,
     REMOVE
@@ -85,6 +90,107 @@ struct _iptablesContext
 };
 
 #ifdef IPTABLES_DIR
+#ifdef ENABLE_IPTABLES_LOKKIT
+static void
+notifyRulesUpdated(const char *table,
+                   const char *path)
+{
+    char arg[PATH_MAX];
+    char *argv[4];
+
+    snprintf(arg, sizeof(arg), "--custom-rules=ipv4:%s:%s", table, path);
+
+    argv[0] = (char *) LOKKIT_PATH;
+    argv[1] = (char *) "--nostart";
+    argv[2] = arg;
+    argv[3] = NULL;
+
+    if (virRun(NULL, argv, NULL) < 0)
+        qemudLog(QEMUD_WARN, "Failed to run '" LOKKIT_PATH " %s' : %s",
+                 arg, strerror(errno));
+}
+
+static int
+stripLine(char *str, int len, const char *line)
+{
+    char *s, *p;
+    int changed;
+
+    changed = 0;
+    s = str;
+
+    while ((p = strchr(s, '\n'))) {
+        if (p == s || strncmp(s, line, p - s) != 0) {
+            s = ++p;
+            continue;
+        }
+
+        ++p;
+        memmove(s, p, len - (p - str) + 1);
+        len -= p - s;
+        changed = 1;
+    }
+
+    if (strcmp(s, line) == 0) {
+        *s = '\0';
+        changed = 1;
+    }
+
+    return changed;
+}
+
+static void
+notifyRulesRemoved(const char *table,
+                   const char *path)
+{
+/* 10 MB limit on config file size as a sanity check */
+#define MAX_FILE_LEN (1024*1024*10)
+
+    char arg[PATH_MAX];
+    char *content;
+    int len;
+    FILE *f = NULL;
+
+    len = virFileReadAll(SYSCONF_DIR "/sysconfig/system-config-firewall",
+                         MAX_FILE_LEN, &content);
+    if (len < 0) {
+        qemudLog(QEMUD_WARN, "Failed to read " SYSCONF_DIR "/sysconfig/system-config-firewall");
+        return;
+    }
+
+    snprintf(arg, sizeof(arg), "--custom-rules=ipv4:%s:%s", table, path);
+
+    if (!stripLine(content, len, arg)) {
+        free(content);
+        return;
+    }
+
+    if (!(f = fopen(SYSCONF_DIR "/sysconfig/system-config-firewall", "w")))
+        goto write_error;
+
+    if (fputs(content, f) == EOF)
+        goto write_error;
+
+    if (fclose(f) == EOF) {
+        f = NULL;
+        goto write_error;
+    }
+
+    free(content);
+
+    return;
+
+ write_error:
+    qemudLog(QEMUD_WARN, "Failed to write to " SYSCONF_DIR "/sysconfig/system-config-firewall : %s",
+             strerror(errno));
+    if (f)
+        fclose(f);
+    free(content);
+
+#undef MAX_FILE_LEN
+}
+#endif /* ENABLE_IPTABLES_LOKKIT */
+
 static int
 writeRules(const char *path,
            const iptRule *rules,
@@ -183,6 +289,11 @@ iptRulesAppend(iptRules *rules,
         if ((err = writeRules(rules->path, rules->rules, rules->nrules)))
             return err;
     }
+
+#ifdef ENABLE_IPTABLES_LOKKIT
+    notifyRulesUpdated(rules->table, rules->path);
+#endif /* ENABLE_IPTABLES_LOKKIT */
+
 #endif /* IPTABLES_DIR */
 
     return 0;
@@ -216,6 +327,14 @@ iptRulesRemove(iptRules *rules,
         if ((err = writeRules(rules->path, rules->rules, rules->nrules)))
             return err;
     }
+
+#ifdef ENABLE_IPTABLES_LOKKIT
+    if (rules->nrules > 0)
+        notifyRulesUpdated(rules->table, rules->path);
+    else
+        notifyRulesRemoved(rules->table, rules->path);
+#endif /* ENABLE_IPTABLES_LOKKIT */
+
 #endif /* IPTABLES_DIR */
 
     return 0;