As suggested by danpb, make libvirt_qemud handle SIGHUP by re-loading
the iptables rules.
Signed-off-by: Mark McLoughlin <markmc(a)redhat.com>
Index: libvirt/qemud/iptables.c
===================================================================
--- libvirt.orig/qemud/iptables.c
+++ libvirt/qemud/iptables.c
@@ -36,6 +36,8 @@
#include <sys/stat.h>
#include <sys/wait.h>
+#include "internal.h"
+
enum {
ADD = 0,
REMOVE
@@ -48,11 +50,18 @@ enum {
typedef struct
{
+ char *rule;
+ char **argv;
+ int flipflop;
+} iptRule;
+
+typedef struct
+{
char *table;
char *chain;
- int nrules;
- char **rules;
+ int nrules;
+ iptRule *rules;
#ifdef IPTABLES_DIR
@@ -73,7 +82,7 @@ struct _iptablesContext
#ifdef IPTABLES_DIR
static int
writeRules(const char *path,
- char * const *rules,
+ const iptRules *rules,
int nrules)
{
char tmp[PATH_MAX];
@@ -96,7 +105,7 @@ writeRules(const char *path,
}
for (i = 0; i < nrules; i++) {
- if (fputs(rules[i], f) == EOF ||
+ if (fputs(rules[i].rule, f) == EOF ||
fputc('\n', f) == EOF) {
fclose(f);
if (istmp)
@@ -173,19 +182,43 @@ buildPath(const char *table,
}
#endif /* IPTABLES_DIR */
-static int
-iptRulesAppend(iptRules *rules,
- const char *rule)
+static void
+iptRuleFree(iptRule *rule)
{
- char **r;
+ if (rule->rule)
+ free(rule->rule);
+ rule->rule = NULL;
+
+ if (rule->argv) {
+ int i = 0;
+ while (rule->argv[i])
+ free(rule->argv[i++]);
+ free(rule->argv);
+ rule->argv = NULL;
+ }
+}
- if (!(r = (char **)realloc(rules->rules, sizeof(char *) * (rules->nrules+1))))
+static int
+iptRulesAppend(iptRules *rules,
+ char *rule,
+ char **argv,
+ int flipflop)
+{
+ iptRule *r;
+
+ if (!(r = (iptRule *)realloc(rules->rules, sizeof(iptRule) *
(rules->nrules+1)))) {
+ int i = 0;
+ while (argv[i])
+ free(argv[i++]);
+ free(argv);
return ENOMEM;
+ }
rules->rules = r;
- if (!(rules->rules[rules->nrules] = strdup(rule)))
- return ENOMEM;
+ rules->rules[rules->nrules].rule = rule;
+ rules->rules[rules->nrules].argv = argv;
+ rules->rules[rules->nrules].flipflop = flipflop;
rules->nrules++;
@@ -211,17 +244,17 @@ iptRulesRemove(iptRules *rules,
int i;
for (i = 0; i < rules->nrules; i++)
- if (!strcmp(rules->rules[i], strdup(rule)))
+ if (!strcmp(rules->rules[i].rule, strdup(rule)))
break;
if (i >= rules->nrules)
return EINVAL;
- free(rules->rules[i]);
+ iptRuleFree(&rules->rules[i]);
memmove(&rules->rules[i],
&rules->rules[i+1],
- (rules->nrules - i - 1) * sizeof (char *));
+ (rules->nrules - i - 1) * sizeof (iptRule));
rules->nrules--;
@@ -253,16 +286,14 @@ iptRulesFree(iptRules *rules)
}
- for (i = 0; i < rules->nrules; i++) {
- free(rules->rules[i]);
- rules->rules[i] = NULL;
- }
-
- rules->nrules = 0;
-
if (rules->rules) {
+ for (i = 0; i < rules->nrules; i++)
+ iptRuleFree(&rules->rules[i]);
+
free(rules->rules);
rules->rules = NULL;
+
+ rules->nrules = 0;
}
#ifdef IPTABLES_DIR
@@ -480,10 +511,13 @@ iptablesAddRemoveRule(iptRules *rules, i
(retval = iptablesAddRemoveChain(rules, action)))
goto error;
- if (action == ADD)
- retval = iptRulesAppend(rules, rule);
- else
+ if (action == ADD) {
+ retval = iptRulesAppend(rules, rule, argv, flipflop);
+ rule = NULL;
+ argv = NULL;
+ } else {
retval = iptRulesRemove(rules, rule);
+ }
error:
if (rule)
@@ -535,6 +569,45 @@ iptablesContextFree(iptablesContext *ctx
free(ctx);
}
+static void
+iptRulesReload(iptRules *rules)
+{
+ int i;
+ int retval;
+
+ for (i = 0; i < rules->nrules; i++) {
+ iptRule *rule = &rules->rules[i];
+ char *orig;
+
+ orig = rule->argv[rule->flipflop];
+ rule->argv[rule->flipflop] = (char *) "--delete";
+
+ if ((retval = iptablesSpawn(WITH_ERRORS, rule->argv)))
+ qemudLog(QEMUD_WARN, "Failed to remove iptables rule '%s' from
chain '%s' in table '%s': %s",
+ rule->rule, rules->chain, rules->table, strerror(errno));
+
+ rule->argv[rule->flipflop] = orig;
+ }
+
+ if ((retval = iptablesAddRemoveChain(rules, REMOVE)) ||
+ (retval = iptablesAddRemoveChain(rules, ADD)))
+ qemudLog(QEMUD_WARN, "Failed to re-create chain '%s' in table
'%s': %s",
+ rules->chain, rules->table, strerror(retval));
+
+ for (i = 0; i < rules->nrules; i++)
+ if ((retval = iptablesSpawn(WITH_ERRORS, rules->rules[i].argv)))
+ qemudLog(QEMUD_WARN, "Failed to add iptables rule '%s' to chain
'%s' in table '%s': %s",
+ rules->rules[i].rule, rules->chain, rules->table,
strerror(retval));
+}
+
+void
+iptablesReloadRules(iptablesContext *ctx)
+{
+ iptRulesReload(ctx->input_filter);
+ iptRulesReload(ctx->forward_filter);
+ iptRulesReload(ctx->nat_postrouting);
+}
+
static int
iptablesInput(iptablesContext *ctx,
const char *iface,
Index: libvirt/qemud/iptables.h
===================================================================
--- libvirt.orig/qemud/iptables.h
+++ libvirt/qemud/iptables.h
@@ -27,6 +27,8 @@ typedef struct _iptablesContext iptables
iptablesContext *iptablesContextNew (void);
void iptablesContextFree (iptablesContext *ctx);
+void iptablesReloadRules (iptablesContext *ctx);
+
int iptablesAddTcpInput (iptablesContext *ctx,
const char *iface,
int port);
Index: libvirt/qemud/qemud.c
===================================================================
--- libvirt.orig/qemud/qemud.c
+++ libvirt/qemud/qemud.c
@@ -88,6 +88,11 @@ static int qemudDispatchSignal(struct qe
case SIGHUP:
qemudLog(QEMUD_INFO, "Reloading configuration on SIGHUP");
ret = qemudScanConfigs(server);
+
+ if (server->iptables) {
+ qemudLog(QEMUD_INFO, "Reloading iptables rules");
+ iptablesReloadRules(server->iptables);
+ }
break;
case SIGINT:
--