#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 \
: ""
* 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
*/
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);
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];
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;
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];
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);
ebtablesApplyDropAllRules(const char *ifname)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
- int cli_status;
char chain_in [MAX_CHAINNAME_LENGTH],
chain_out[MAX_CHAINNAME_LENGTH];
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;
ebtablesRemoveTmpRootChain(&buf, 1, ifname);
ebtablesRemoveTmpRootChain(&buf, 0, ifname);
- ebiptablesExecCLI(&buf, &cli_status);
+ ebiptablesExecCLI(&buf, &cli_status, NULL);
return 0;
}
bool haveIp6tables = false;
ebiptablesRuleInstPtr ebtChains = NULL;
int nEbtChains = 0;
+ char *errmsg = NULL;
if (!chains_in_set || !chains_out_set) {
virReportOOMError();
ebtablesRemoveTmpSubChains(&buf, ifname);
ebtablesRemoveTmpRootChain(&buf, 1, ifname);
ebtablesRemoveTmpRootChain(&buf, 0, ifname);
- ebiptablesExecCLI(&buf, &cli_status);
+ ebiptablesExecCLI(&buf, &cli_status, NULL);
}
/* create needed chains */
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
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) {
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++) {
'A', -1, 1);
}
- if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0)
+ if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0)
goto tear_down_tmpiptchains;
iptablesCheckBridgeNFCallEnabled(false);
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++) {
'A', -1, 1);
}
- if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0)
+ if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0)
goto tear_down_tmpip6tchains;
iptablesCheckBridgeNFCallEnabled(true);
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);
VIR_FREE(ebtChains[i].commandTemplate);
VIR_FREE(ebtChains);
+ VIR_FREE(errmsg);
+
return 0;
tear_down_ebsubchains_and_unlink:
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);
VIR_FREE(ebtChains[i].commandTemplate);
VIR_FREE(ebtChains);
+ VIR_FREE(errmsg);
+
return 1;
}
ebtablesRemoveTmpRootChain(&buf, 0, ifname);
}
- ebiptablesExecCLI(&buf, &cli_status);
+ ebiptablesExecCLI(&buf, &cli_status, NULL);
return 0;
}
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) {
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) {
ebtablesRenameTmpSubAndRootChains(&buf, ifname);
- ebiptablesExecCLI(&buf, &cli_status);
+ ebiptablesExecCLI(&buf, &cli_status, NULL);
}
return 0;
'D', -1,
0);
- if (ebiptablesExecCLI(&buf, &cli_status))
+ if (ebiptablesExecCLI(&buf, &cli_status, NULL))
goto err_exit;
if (cli_status) {
ebtablesRemoveRootChain(&buf, 1, ifname);
ebtablesRemoveRootChain(&buf, 0, ifname);
}
- ebiptablesExecCLI(&buf, &cli_status);
+ ebiptablesExecCLI(&buf, &cli_status, NULL);
return 0;
}
ebiptablesDriverInit(bool privileged)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
- int cli_status;
if (!privileged)
return 0;
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);
}
iptables_cmd_path,
CMD_STOPONERR(1));
- if (ebiptablesExecCLI(&buf, &cli_status) || cli_status)
+ if (ebiptablesExecCLI(&buf, NULL, NULL) < 0)
VIR_FREE(iptables_cmd_path);
}
ip6tables_cmd_path,
CMD_STOPONERR(1));
- if (ebiptablesExecCLI(&buf, &cli_status) || cli_status)
+ if (ebiptablesExecCLI(&buf, NULL, NULL) < 0)
VIR_FREE(ip6tables_cmd_path);
}