diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c
index 54f76562ad..d8123c4446 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/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 \
       : ""
@@ -2710,6 +2710,10 @@ ebiptablesDisplayRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
  *        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
@@ -2721,17 +2725,24 @@ ebiptablesDisplayRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
  */
 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);
 
@@ -3142,7 +3153,6 @@ ebtablesApplyBasicRules(const char *ifname,
                         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];
@@ -3197,7 +3207,7 @@ ebtablesApplyBasicRules(const char *ifname,
     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;
@@ -3233,7 +3243,6 @@ ebtablesApplyDHCPOnlyRules(const char *ifname,
                            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];
@@ -3313,7 +3322,7 @@ ebtablesApplyDHCPOnlyRules(const char *ifname,
     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);
@@ -3346,7 +3355,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];
 
@@ -3386,7 +3394,7 @@ ebtablesApplyDropAllRules(const char *ifname)
     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;
@@ -3429,7 +3437,7 @@ static int ebtablesCleanAll(const char *ifname)
     ebtablesRemoveTmpRootChain(&buf, 1, ifname);
     ebtablesRemoveTmpRootChain(&buf, 0, ifname);
 
-    ebiptablesExecCLI(&buf, &cli_status);
+    ebiptablesExecCLI(&buf, &cli_status, NULL);
     return 0;
 }
 
@@ -3586,6 +3594,7 @@ ebiptablesApplyNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
     bool haveIp6tables = false;
     ebiptablesRuleInstPtr ebtChains = NULL;
     int nEbtChains = 0;
+    char *errmsg = NULL;
 
     if (!chains_in_set || !chains_out_set) {
         virReportOOMError();
@@ -3624,7 +3633,7 @@ ebiptablesApplyNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
         ebtablesRemoveTmpSubChains(&buf, ifname);
         ebtablesRemoveTmpRootChain(&buf, 1, ifname);
         ebtablesRemoveTmpRootChain(&buf, 0, ifname);
-        ebiptablesExecCLI(&buf, &cli_status);
+        ebiptablesExecCLI(&buf, &cli_status, NULL);
     }
 
     /* create needed chains */
@@ -3639,7 +3648,7 @@ ebiptablesApplyNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
         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
@@ -3673,7 +3682,7 @@ ebiptablesApplyNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
                               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) {
@@ -3682,17 +3691,17 @@ ebiptablesApplyNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
 
         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++) {
@@ -3703,7 +3712,7 @@ ebiptablesApplyNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
                                     'A', -1, 1);
         }
 
-        if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0)
+        if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0)
            goto tear_down_tmpiptchains;
 
         iptablesCheckBridgeNFCallEnabled(false);
@@ -3715,17 +3724,17 @@ ebiptablesApplyNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
 
         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++) {
@@ -3735,7 +3744,7 @@ ebiptablesApplyNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
                                     'A', -1, 1);
         }
 
-        if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0)
+        if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0)
            goto tear_down_tmpip6tchains;
 
         iptablesCheckBridgeNFCallEnabled(true);
@@ -3746,7 +3755,7 @@ ebiptablesApplyNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
     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);
@@ -3756,6 +3765,8 @@ ebiptablesApplyNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
         VIR_FREE(ebtChains[i].commandTemplate);
     VIR_FREE(ebtChains);
 
+    VIR_FREE(errmsg);
+
     return 0;
 
 tear_down_ebsubchains_and_unlink:
@@ -3783,12 +3794,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);
@@ -3798,6 +3811,8 @@ exit_free_sets:
         VIR_FREE(ebtChains[i].commandTemplate);
     VIR_FREE(ebtChains);
 
+    VIR_FREE(errmsg);
+
     return 1;
 }
 
@@ -3828,7 +3843,7 @@ ebiptablesTearNewRules(virConnectPtr conn ATTRIBUTE_UNUSED,
         ebtablesRemoveTmpRootChain(&buf, 0, ifname);
     }
 
-    ebiptablesExecCLI(&buf, &cli_status);
+    ebiptablesExecCLI(&buf, &cli_status, NULL);
 
     return 0;
 }
@@ -3847,7 +3862,7 @@ ebiptablesTearOldRules(virConnectPtr conn ATTRIBUTE_UNUSED,
         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) {
@@ -3855,7 +3870,7 @@ ebiptablesTearOldRules(virConnectPtr conn ATTRIBUTE_UNUSED,
         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) {
@@ -3869,7 +3884,7 @@ ebiptablesTearOldRules(virConnectPtr conn ATTRIBUTE_UNUSED,
 
         ebtablesRenameTmpSubAndRootChains(&buf, ifname);
 
-        ebiptablesExecCLI(&buf, &cli_status);
+        ebiptablesExecCLI(&buf, &cli_status, NULL);
     }
 
     return 0;
@@ -3906,7 +3921,7 @@ ebiptablesRemoveRules(virConnectPtr conn ATTRIBUTE_UNUSED,
                               'D', -1,
                               0);
 
-    if (ebiptablesExecCLI(&buf, &cli_status))
+    if (ebiptablesExecCLI(&buf, &cli_status, NULL))
         goto err_exit;
 
     if (cli_status) {
@@ -3957,7 +3972,7 @@ ebiptablesAllTeardown(const char *ifname)
         ebtablesRemoveRootChain(&buf, 1, ifname);
         ebtablesRemoveRootChain(&buf, 0, ifname);
     }
-    ebiptablesExecCLI(&buf, &cli_status);
+    ebiptablesExecCLI(&buf, &cli_status, NULL);
 
     return 0;
 }
@@ -3991,7 +4006,6 @@ static int
 ebiptablesDriverInit(bool privileged)
 {
     virBuffer buf = VIR_BUFFER_INITIALIZER;
-    int cli_status;
 
     if (!privileged)
         return 0;
@@ -4012,7 +4026,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);
     }
 
@@ -4025,7 +4039,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);
     }
 
@@ -4038,7 +4052,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);
     }