As suggested by danpb, make libvirt_qemud handle SIGHUP by re-loading the iptables rules. Signed-off-by: Mark McLoughlin Index: libvirt/qemud/iptables.c =================================================================== --- libvirt.orig/qemud/iptables.c +++ libvirt/qemud/iptables.c @@ -36,6 +36,8 @@ #include #include +#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: --