Display the executed command and failure message if a command failed to execute. Signed-off-by: Stefan Berger --- v2: - addressing Eric Blake's comments --- src/nwfilter/nwfilter_ebiptables_driver.c | 86 +++++++++++++++++------------- 1 file changed, 50 insertions(+), 36 deletions(-) Index: libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_ebiptables_driver.c +++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c @@ -65,10 +65,10 @@ #define CMD_DEF_PRE "cmd='" #define CMD_DEF_POST "'" #define CMD_DEF(X) CMD_DEF_PRE X CMD_DEF_POST -#define CMD_EXEC "eval res=\\$\\(\"${cmd}\"\\)" CMD_SEPARATOR +#define CMD_EXEC "eval res=\\$\\(\"${cmd} 2>&1\"\\)" CMD_SEPARATOR #define CMD_STOPONERR(X) \ X ? "if [ $? -ne 0 ]; then" \ - " echo \"Failure to execute command '${cmd}'.\";" \ + " echo \"Failure to execute command '${cmd}' : '${res}'.\";" \ " exit 1;" \ "fi" CMD_SEPARATOR \ : "" @@ -2707,6 +2707,10 @@ ebiptablesDisplayRuleInstance(virConnect * execute. * @status: Pointer to an integer for returning the WEXITSTATUS of the * commands executed via the script the was run. + * @outbuf: Optional pointer to a string that will hold the buffer with + * output of the executed command. The actual buffer holding + * the message will be newly allocated by this function and + * any passed in buffer freed first. * * Returns 0 in case of success, < 0 in case of an error. The returned * value is NOT the result of running the commands inside the shell @@ -2718,17 +2722,24 @@ ebiptablesDisplayRuleInstance(virConnect */ static int ebiptablesExecCLI(virBufferPtr buf, - int *status) + int *status, char **outbuf) { int rc = -1; virCommandPtr cmd; - *status = 0; + if (status) + *status = 0; + if (!virBufferError(buf) && !virBufferUse(buf)) return 0; + if (outbuf) + VIR_FREE(*outbuf); + cmd = virCommandNewArgList("/bin/sh", "-c", NULL); virCommandAddArgBuffer(cmd, buf); + if (outbuf) + virCommandSetOutputBuffer(cmd, outbuf); virMutexLock(&execCLIMutex); @@ -3138,7 +3149,6 @@ ebtablesApplyBasicRules(const char *ifna const unsigned char *macaddr) { virBuffer buf = VIR_BUFFER_INITIALIZER; - int cli_status; char chain[MAX_CHAINNAME_LENGTH]; char chainPrefix = CHAINPREFIX_HOST_IN_TEMP; char macaddr_str[VIR_MAC_STRING_BUFLEN]; @@ -3193,7 +3203,7 @@ ebtablesApplyBasicRules(const char *ifna ebtablesLinkTmpRootChain(&buf, 1, ifname, 1); ebtablesRenameTmpRootChain(&buf, 1, ifname); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, NULL) < 0) goto tear_down_tmpebchains; return 0; @@ -3229,7 +3239,6 @@ ebtablesApplyDHCPOnlyRules(const char *i const char *dhcpserver) { virBuffer buf = VIR_BUFFER_INITIALIZER; - int cli_status; char chain_in [MAX_CHAINNAME_LENGTH], chain_out[MAX_CHAINNAME_LENGTH]; char macaddr_str[VIR_MAC_STRING_BUFLEN]; @@ -3309,7 +3318,7 @@ ebtablesApplyDHCPOnlyRules(const char *i ebtablesRenameTmpRootChain(&buf, 1, ifname); ebtablesRenameTmpRootChain(&buf, 0, ifname); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, NULL) < 0) goto tear_down_tmpebchains; VIR_FREE(srcIPParam); @@ -3342,7 +3351,6 @@ static int ebtablesApplyDropAllRules(const char *ifname) { virBuffer buf = VIR_BUFFER_INITIALIZER; - int cli_status; char chain_in [MAX_CHAINNAME_LENGTH], chain_out[MAX_CHAINNAME_LENGTH]; @@ -3382,7 +3390,7 @@ ebtablesApplyDropAllRules(const char *if ebtablesRenameTmpRootChain(&buf, 1, ifname); ebtablesRenameTmpRootChain(&buf, 0, ifname); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, NULL) < 0) goto tear_down_tmpebchains; return 0; @@ -3425,7 +3433,7 @@ static int ebtablesCleanAll(const char * ebtablesRemoveTmpRootChain(&buf, 1, ifname); ebtablesRemoveTmpRootChain(&buf, 0, ifname); - ebiptablesExecCLI(&buf, &cli_status); + ebiptablesExecCLI(&buf, &cli_status, NULL); return 0; } @@ -3582,6 +3590,7 @@ ebiptablesApplyNewRules(virConnectPtr co bool haveIp6tables = false; ebiptablesRuleInstPtr ebtChains = NULL; int nEbtChains = 0; + char *errmsg = NULL; if (!chains_in_set || !chains_out_set) { virReportOOMError(); @@ -3620,7 +3629,7 @@ ebiptablesApplyNewRules(virConnectPtr co ebtablesRemoveTmpSubChains(&buf, ifname); ebtablesRemoveTmpRootChain(&buf, 1, ifname); ebtablesRemoveTmpRootChain(&buf, 0, ifname); - ebiptablesExecCLI(&buf, &cli_status); + ebiptablesExecCLI(&buf, &cli_status, NULL); } /* create needed chains */ @@ -3635,7 +3644,7 @@ ebiptablesApplyNewRules(virConnectPtr co qsort(&ebtChains[0], nEbtChains, sizeof(ebtChains[0]), ebiptablesRuleOrderSort); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) goto tear_down_tmpebchains; /* process ebtables commands; interleave commands from filters with @@ -3669,7 +3678,7 @@ ebiptablesApplyNewRules(virConnectPtr co ebtChains[j++].commandTemplate, 'A', -1, 1); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) goto tear_down_tmpebchains; if (haveIptables) { @@ -3678,17 +3687,17 @@ ebiptablesApplyNewRules(virConnectPtr co iptablesCreateBaseChains(iptables_cmd_path, &buf); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) goto tear_down_tmpebchains; iptablesCreateTmpRootChains(iptables_cmd_path, &buf, ifname); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) goto tear_down_tmpiptchains; iptablesLinkTmpRootChains(iptables_cmd_path, &buf, ifname); iptablesSetupVirtInPost(iptables_cmd_path, &buf, ifname); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) goto tear_down_tmpiptchains; for (i = 0; i < nruleInstances; i++) { @@ -3699,7 +3708,7 @@ ebiptablesApplyNewRules(virConnectPtr co 'A', -1, 1); } - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) goto tear_down_tmpiptchains; iptablesCheckBridgeNFCallEnabled(false); @@ -3711,17 +3720,17 @@ ebiptablesApplyNewRules(virConnectPtr co iptablesCreateBaseChains(ip6tables_cmd_path, &buf); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) goto tear_down_tmpiptchains; iptablesCreateTmpRootChains(ip6tables_cmd_path, &buf, ifname); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) goto tear_down_tmpip6tchains; iptablesLinkTmpRootChains(ip6tables_cmd_path, &buf, ifname); iptablesSetupVirtInPost(ip6tables_cmd_path, &buf, ifname); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) goto tear_down_tmpip6tchains; for (i = 0; i < nruleInstances; i++) { @@ -3731,7 +3740,7 @@ ebiptablesApplyNewRules(virConnectPtr co 'A', -1, 1); } - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) goto tear_down_tmpip6tchains; iptablesCheckBridgeNFCallEnabled(true); @@ -3742,7 +3751,7 @@ ebiptablesApplyNewRules(virConnectPtr co if (virHashSize(chains_out_set) != 0) ebtablesLinkTmpRootChain(&buf, 0, ifname, 1); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) + if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) goto tear_down_ebsubchains_and_unlink; virHashFree(chains_in_set); @@ -3752,6 +3761,8 @@ ebiptablesApplyNewRules(virConnectPtr co VIR_FREE(ebtChains[i].commandTemplate); VIR_FREE(ebtChains); + VIR_FREE(errmsg); + return 0; tear_down_ebsubchains_and_unlink: @@ -3779,12 +3790,14 @@ tear_down_tmpebchains: ebtablesRemoveTmpRootChain(&buf, 0, ifname); } - ebiptablesExecCLI(&buf, &cli_status); + ebiptablesExecCLI(&buf, &cli_status, NULL); virNWFilterReportError(VIR_ERR_BUILD_FIREWALL, _("Some rules could not be created for " - "interface %s."), - ifname); + "interface %s%s%s"), + ifname, + errmsg ? ": " : "", + errmsg ? errmsg : ""); exit_free_sets: virHashFree(chains_in_set); @@ -3794,6 +3807,8 @@ exit_free_sets: VIR_FREE(ebtChains[i].commandTemplate); VIR_FREE(ebtChains); + VIR_FREE(errmsg); + return 1; } @@ -3824,7 +3839,7 @@ ebiptablesTearNewRules(virConnectPtr con ebtablesRemoveTmpRootChain(&buf, 0, ifname); } - ebiptablesExecCLI(&buf, &cli_status); + ebiptablesExecCLI(&buf, &cli_status, NULL); return 0; } @@ -3843,7 +3858,7 @@ ebiptablesTearOldRules(virConnectPtr con iptablesRemoveRootChains(iptables_cmd_path, &buf, ifname); iptablesRenameTmpRootChains(iptables_cmd_path, &buf, ifname); - ebiptablesExecCLI(&buf, &cli_status); + ebiptablesExecCLI(&buf, &cli_status, NULL); } if (ip6tables_cmd_path) { @@ -3851,7 +3866,7 @@ ebiptablesTearOldRules(virConnectPtr con iptablesRemoveRootChains(ip6tables_cmd_path, &buf, ifname); iptablesRenameTmpRootChains(ip6tables_cmd_path, &buf, ifname); - ebiptablesExecCLI(&buf, &cli_status); + ebiptablesExecCLI(&buf, &cli_status, NULL); } if (ebtables_cmd_path) { @@ -3865,7 +3880,7 @@ ebiptablesTearOldRules(virConnectPtr con ebtablesRenameTmpSubAndRootChains(&buf, ifname); - ebiptablesExecCLI(&buf, &cli_status); + ebiptablesExecCLI(&buf, &cli_status, NULL); } return 0; @@ -3902,7 +3917,7 @@ ebiptablesRemoveRules(virConnectPtr conn 'D', -1, 0); - if (ebiptablesExecCLI(&buf, &cli_status)) + if (ebiptablesExecCLI(&buf, &cli_status, NULL)) goto err_exit; if (cli_status) { @@ -3953,7 +3968,7 @@ ebiptablesAllTeardown(const char *ifname ebtablesRemoveRootChain(&buf, 1, ifname); ebtablesRemoveRootChain(&buf, 0, ifname); } - ebiptablesExecCLI(&buf, &cli_status); + ebiptablesExecCLI(&buf, &cli_status, NULL); return 0; } @@ -3987,7 +4002,6 @@ static int ebiptablesDriverInit(bool privileged) { virBuffer buf = VIR_BUFFER_INITIALIZER; - int cli_status; if (!privileged) return 0; @@ -4008,7 +4022,7 @@ ebiptablesDriverInit(bool privileged) ebtables_cmd_path, EBTABLES_DEFAULT_TABLE, CMD_STOPONERR(1)); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status) + if (ebiptablesExecCLI(&buf, NULL, NULL) < 0) VIR_FREE(ebtables_cmd_path); } @@ -4021,7 +4035,7 @@ ebiptablesDriverInit(bool privileged) iptables_cmd_path, CMD_STOPONERR(1)); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status) + if (ebiptablesExecCLI(&buf, NULL, NULL) < 0) VIR_FREE(iptables_cmd_path); } @@ -4034,7 +4048,7 @@ ebiptablesDriverInit(bool privileged) ip6tables_cmd_path, CMD_STOPONERR(1)); - if (ebiptablesExecCLI(&buf, &cli_status) || cli_status) + if (ebiptablesExecCLI(&buf, NULL, NULL) < 0) VIR_FREE(ip6tables_cmd_path); }