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.

The slightly nasty bit is that rather than running something
like lokkit --remove-custom-rules, we have to grub around
in /etc/sysconfig/system-config-firewall to remove our
rules files.

Signed-off-by: Mark McLoughlin <[EMAIL PROTECTED]>

Index: libvirt/configure.in
===================================================================
--- libvirt.orig/configure.in   2008-01-04 14:48:49.000000000 +0000
+++ libvirt.orig/configure.in   2008-01-04 14:48:49.000000000 +0000
@@ -204,6 +204,20 @@ 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],
+                             [enable registering libvirt's iptables rules with 
Fedora's lokkit]),
+                             [],[enable_iptables_lokkit=no])
+if test x"$enable_iptables_lokkit" = x"yes"; then
+   AC_DEFINE(ENABLE_IPTABLES_LOKKIT, [], [whether support for Fedora's lokkit 
is enabled])
+   AC_PATH_PROG(LOKKIT_PATH, lokkit, /usr/sbin/lokkit)
+   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: libvirt/src/iptables.c
===================================================================
--- libvirt.orig/src/iptables.c 2008-01-04 14:51:29.000000000 +0000
+++ libvirt.orig/src/iptables.c 2008-01-04 14:51:29.000000000 +0000
@@ -48,6 +48,11 @@
 
 #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
@@ -133,6 +138,108 @@ iptablesSpawn(int errors, char * const *
 }
 
 #ifdef IPTABLES_DIR
+#ifdef ENABLE_IPTABLES_LOKKIT
+static void
+notifyRulesUpdated(const char *table,
+                   const char *path)
+{
+    char arg[PATH_MAX];
+    char *argv[4];
+    int retval;
+
+    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 ((retval = iptablesSpawn(WITH_ERRORS, argv)))
+        qemudLog(QEMUD_WARN, "Failed to run '" LOKKIT_PATH " %s' : %s",
+                 arg, strerror(retval));
+}
+
+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,
@@ -231,6 +338,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;
@@ -264,6 +376,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;

-- 

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to