[libvirt] [PATCH 13/13] Extension for iptables rules

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds support for L3/L4 filtering using iptables. This adds
support for 'tcp', 'udp', 'icmp', 'igmp', 'sctp' etc. filtering.

As mentioned in the introduction, a .c file provided by this patch
is #include'd into a .c file. This will need work, but should be alright
for review.

Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx>






---
 configure.ac                              |    7 
 src/conf/nwfilter_conf.c                  |  320 +++++++++++
 src/conf/nwfilter_conf.h                  |   62 ++
 src/libvirt_private.syms                  |    3 
 src/nwfilter/nwfilter_ebiptables_driver.c |  112 +++-
 src/nwfilter/nwfilter_ebiptables_driver.h |    1 
 src/nwfilter/nwfilter_iptables.c          |  839 ++++++++++++++++++++++++++++++
 7 files changed, 1332 insertions(+), 12 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
@@ -75,6 +75,9 @@
     snprintf(buf, sizeof(buf), "%c-%s-%s", prefix, ifname, suffix)
 
 
+//FIXME: only temporary
+#include "nwfilter_iptables.c"
+
 static const char *supported_protocols[] = {
     "ipv4",
     "arp",
@@ -186,7 +189,8 @@ ebiptablesAddRuleInst(virConnectPtr conn
                       char *commandTemplate,
                       enum virNWFilterChainSuffixType neededChain,
                       char chainprefix,
-                      unsigned int priority)
+                      unsigned int priority,
+                      int isIptablesRule)
 {
     ebiptablesRuleInstPtr inst;
 
@@ -199,6 +203,7 @@ ebiptablesAddRuleInst(virConnectPtr conn
     inst->neededProtocolChain = neededChain;
     inst->chainprefix = chainprefix;
     inst->priority = priority;
+    inst->isIptablesRule = isIptablesRule;
 
     return virNWFilterRuleInstAddData(conn, res, inst);
 }
@@ -524,6 +529,9 @@ ebtablesCreateRuleInstance(virConnectPtr
                           CMD_DEF_PRE EBTABLES_CMD " -t %s -%%c %s %%s",
                           EBTABLES_DEFAULT_TABLE, chain);
     break;
+
+    default:
+        return -1;
     }
 
     virBufferVSprintf(&buf,
@@ -542,7 +550,8 @@ ebtablesCreateRuleInstance(virConnectPtr
                                  virBufferContentAndReset(&buf),
                                  nwfilter->chainsuffix,
                                  chainPrefix,
-                                 rule->priority);
+                                 rule->priority,
+                                 0);
 
 err_exit:
     virBufferFreeAndReset(&buf);
@@ -568,7 +577,7 @@ err_exit:
  */
 static int
 ebiptablesCreateRuleInstance(virConnectPtr conn,
-                             enum virDomainNetType nettype ATTRIBUTE_UNUSED,
+                             enum virDomainNetType nettype,
                              virNWFilterDefPtr nwfilter,
                              virNWFilterRuleDefPtr rule,
                              const char *ifname,
@@ -607,6 +616,33 @@ ebiptablesCreateRuleInstance(virConnectP
                                             res);
         }
     break;
+
+    case VIR_NWFILTER_RULE_PROTOCOL_TCP:
+    case VIR_NWFILTER_RULE_PROTOCOL_UDP:
+    case VIR_NWFILTER_RULE_PROTOCOL_SCP:
+    case VIR_NWFILTER_RULE_PROTOCOL_ICMP:
+    case VIR_NWFILTER_RULE_PROTOCOL_IGMP:
+    case VIR_NWFILTER_RULE_PROTOCOL_ALL:
+        if (nettype == VIR_DOMAIN_NET_TYPE_DIRECT) {
+            virNWFilterReportError(conn, VIR_ERR_INVALID_NWFILTER,
+                          _("'%s' protocol not support for net type '%s'"),
+                          virNWFilterRuleProtocolTypeToString(rule->prtclType),
+                          virDomainNetTypeToString(nettype));
+            return 1;
+        }
+        rc = iptablesCreateRuleInstance(conn,
+                                        nwfilter,
+                                        rule,
+                                        ifname,
+                                        vars,
+                                        res);
+    break;
+
+    case VIR_NWFILTER_RULE_PROTOCOL_LAST:
+        virNWFilterReportError(conn, VIR_ERR_INVALID_NWFILTER,
+                               "%s", _("illegal protocol type"));
+        rc = 1;
+    break;
     }
 
     return rc;
@@ -1134,16 +1170,19 @@ ebiptablesApplyRules(virConnectPtr conn,
     ebiptablesRuleInstPtr *inst = (ebiptablesRuleInstPtr *)_inst;
     int chains_in = 0, chains_out = 0;
     virBuffer buf = VIR_BUFFER_INITIALIZER;
+    int haveIptables = 0;
 
     if (inst)
         qsort(inst, nruleInstances, sizeof(inst[0]),
               ebiptablesRuleOrderSort);
 
     for (i = 0; i < nruleInstances; i++) {
-        if (inst[i]->chainprefix == CHAINPREFIX_HOST_IN_TEMP)
-            chains_in  |= (1 << inst[i]->neededProtocolChain);
-        else
-            chains_out |= (1 << inst[i]->neededProtocolChain);
+        if (!inst[i]->isIptablesRule) {
+            if (inst[i]->chainprefix == CHAINPREFIX_HOST_IN_TEMP)
+                chains_in  |= (1 << inst[i]->neededProtocolChain);
+            else
+                chains_out |= (1 << inst[i]->neededProtocolChain);
+        }
     }
 
     ebtablesUnlinkTmpRootChain(conn, &buf, 1, ifname);
@@ -1151,6 +1190,7 @@ ebiptablesApplyRules(virConnectPtr conn,
     ebtablesRemoveTmpSubChains(conn, &buf, ifname);
     ebtablesRemoveTmpRootChain(conn, &buf, 1, ifname);
     ebtablesRemoveTmpRootChain(conn, &buf, 0, ifname);
+    ebiptablesExecCLI(conn, &buf, &cli_status);
 
     if (chains_in != 0)
         ebtablesCreateTmpRootChain(conn, &buf, 1, ifname, 1);
@@ -1172,15 +1212,49 @@ ebiptablesApplyRules(virConnectPtr conn,
         goto tear_down_tmpebchains;
 
     for (i = 0; i < nruleInstances; i++)
-        ebiptablesInstCommand(conn, &buf,
-                              inst[i]->commandTemplate,
-                              'A', -1, 1);
+        if (!inst[i]->isIptablesRule)
+            ebiptablesInstCommand(conn, &buf,
+                                  inst[i]->commandTemplate,
+                                  'A', -1, 1);
+        else
+            haveIptables = 1;
 
     if (ebiptablesExecCLI(conn, &buf, &cli_status) || cli_status != 0)
         goto tear_down_tmpebchains;
 
     // FIXME: establishment of iptables user define table tree goes here
 
+    if (haveIptables) {
+        iptablesUnlinkTmpRootChains(conn, &buf, ifname);
+        iptablesRemoveTmpRootChains(conn, &buf, ifname);
+
+        iptablesCreateBaseChains(conn, &buf);
+
+        if (ebiptablesExecCLI(conn, &buf, &cli_status) || cli_status != 0)
+            goto tear_down_tmpebchains;
+
+        iptablesCreateTmpRootChains(conn, &buf, ifname);
+
+        if (ebiptablesExecCLI(conn, &buf, &cli_status) || cli_status != 0)
+           goto tear_down_tmpiptchains;
+
+        iptablesLinkTmpRootChains(conn, &buf, ifname);
+        iptablesSetupVirtInPost(conn, &buf, ifname);
+        if (ebiptablesExecCLI(conn, &buf, &cli_status) || cli_status != 0)
+           goto tear_down_tmpiptchains;
+
+        for (i = 0; i < nruleInstances; i++) {
+            if (inst[i]->isIptablesRule)
+                iptablesInstCommand(conn, &buf,
+                                    inst[i]->commandTemplate,
+                                    'A', -1, 1);
+        }
+
+        if (ebiptablesExecCLI(conn, &buf, &cli_status) || cli_status != 0)
+           goto tear_down_tmpiptchains;
+    }
+
+
     // END IPTABLES stuff
 
     if (chains_in != 0)
@@ -1191,6 +1265,15 @@ ebiptablesApplyRules(virConnectPtr conn,
     if (ebiptablesExecCLI(conn, &buf, &cli_status) || cli_status != 0)
         goto tear_down_ebsubchains_and_unlink;
 
+    // clean up IPtables in any case
+    iptablesUnlinkRootChains(conn, &buf, ifname);
+    iptablesRemoveRootChains(conn, &buf, ifname);
+
+    if (haveIptables) {
+        iptablesRenameTmpRootChains(conn, &buf, ifname);
+        ebiptablesExecCLI(conn, &buf, &cli_status);
+    }
+
     ebtablesUnlinkRootChain(conn, &buf, 1, ifname);
     ebtablesUnlinkRootChain(conn, &buf, 0, ifname);
 
@@ -1207,10 +1290,15 @@ ebiptablesApplyRules(virConnectPtr conn,
 
     return 0;
 
+
 tear_down_ebsubchains_and_unlink:
     ebtablesUnlinkTmpRootChain(conn, &buf, 1, ifname);
     ebtablesUnlinkTmpRootChain(conn, &buf, 0, ifname);
 
+tear_down_tmpiptchains:
+    if (haveIptables)
+        iptablesRemoveTmpRootChains(conn, &buf, ifname);
+
 tear_down_tmpebchains:
     ebtablesRemoveTmpSubChains(conn, &buf, ifname);
     ebtablesRemoveTmpRootChain(conn, &buf, 1, ifname);
@@ -1287,6 +1375,10 @@ ebiptablesAllTeardown(const char *ifname
     int cli_status;
     virConnectPtr conn = NULL;
 
+    iptablesUnlinkRootChains(conn, &buf, ifname);
+    iptablesClearVirtInPost(conn, &buf, ifname);
+    iptablesRemoveRootChains(conn, &buf, ifname);
+
     ebtablesUnlinkRootChain(conn, &buf, 1, ifname);
     ebtablesUnlinkRootChain(conn, &buf, 0, ifname);
 
Index: libvirt-acl/src/nwfilter/nwfilter_iptables.c
===================================================================
--- /dev/null
+++ libvirt-acl/src/nwfilter/nwfilter_iptables.c
@@ -0,0 +1,839 @@
+// all content of this file will be copied into nwfilter_ebiptables_driver.c
+
+#define IPTABLES_CMD IPTABLES_PATH
+#define GREP_CMD     GREP_PATH
+#define GAWK_CMD     GAWK_PATH
+
+#define VIRT_IN_CHAIN      "virt-in"
+#define VIRT_OUT_CHAIN     "virt-out"
+#define VIRT_IN_POST_CHAIN "virt-in-post"
+#define HOST_IN_CHAIN      "host-in"
+
+#define PRINT_IPT_ROOT_CHAIN(buf, prefix, ifname) \
+    snprintf(buf, sizeof(buf), "%c%c-%s", prefix[0], prefix[1], ifname)
+
+#define PHYSDEV_IN  "--physdev-in"
+#define PHYSDEV_OUT "--physdev-out"
+
+static const char *m_state_out_str   = "-m state --state NEW,ESTABLISHED";
+static const char *m_state_in_str    = "-m state --state ESTABLISHED";
+static const char *m_physdev_in_str  = "-m physdev " PHYSDEV_IN;
+static const char *m_physdev_out_str = "-m physdev " PHYSDEV_OUT;
+
+#define MATCH_STATE_OUT    m_state_out_str
+#define MATCH_STATE_IN     m_state_in_str
+#define MATCH_PHYSDEV_IN   m_physdev_in_str
+#define MATCH_PHYSDEV_OUT  m_physdev_out_str
+
+
+/* temporary local function declaration */
+static int
+printDataType(virConnectPtr conn,
+              virNWFilterHashTablePtr vars,
+              char *buf, int bufsize,
+              nwItemDescPtr item);
+
+static int
+ebiptablesAddRuleInst(virConnectPtr conn,
+                      virNWFilterRuleInstPtr res,
+                      char *commandTemplate,
+                      enum virNWFilterChainSuffixType neededChain,
+                      char chainprefix,
+                      unsigned int priority,
+                      int isIptablesRule);
+
+
+
+static int iptablesLinkIPTablesBaseChain(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                         virBufferPtr buf,
+                                         const char *udchain,
+                                         const char *syschain,
+                                         unsigned int pos,
+                                         int stopOnError)
+{
+    virBufferVSprintf(buf,
+                      "res=$("
+                        IPTABLES_CMD " -L %s -n --line-number | "
+                          GREP_CMD " \" %s \")\n"
+                      "if [ $? -ne 0 ]; then\n"
+                      "  " IPTABLES_CMD " -I %s %d -j %s\n"
+                      "else\n"
+                      "  r=$(echo $res | " GAWK_CMD " '{print $1}')\n"
+                      "  if [ \"${r}\" != \"%d\" ]; then\n"
+                      "    " CMD_DEF(IPTABLES_CMD " -I %s %d -j %s") CMD_SEPARATOR
+                      "    " CMD_EXEC
+                      "    %s"
+                      "    let r=r+1\n"
+                      "    " CMD_DEF(IPTABLES_CMD " -D %s ${r}") CMD_SEPARATOR
+                      "    " CMD_EXEC
+                      "    %s"
+                      "  fi\n"
+                      "fi\n",
+
+                      syschain, udchain,
+
+                      syschain, pos, udchain,
+
+                      pos,
+
+                      syschain, pos, udchain,
+                      CMD_STOPONERR(stopOnError),
+
+                      syschain,
+                      CMD_STOPONERR(stopOnError));
+    return 0;
+}
+
+
+static int iptablesCreateBaseChains(virConnectPtr conn,
+                                    virBufferPtr buf)
+{
+    virBufferAddLit(buf, IPTABLES_CMD " -N " VIRT_IN_CHAIN      CMD_SEPARATOR
+                         IPTABLES_CMD " -N " VIRT_OUT_CHAIN     CMD_SEPARATOR
+                         IPTABLES_CMD " -N " VIRT_IN_POST_CHAIN CMD_SEPARATOR
+                         IPTABLES_CMD " -N " HOST_IN_CHAIN      CMD_SEPARATOR);
+    iptablesLinkIPTablesBaseChain(conn, buf,
+                                  VIRT_IN_CHAIN     , "FORWARD", 1, 1);
+    iptablesLinkIPTablesBaseChain(conn, buf,
+                                  VIRT_OUT_CHAIN    , "FORWARD", 2, 1);
+    iptablesLinkIPTablesBaseChain(conn, buf,
+                                  VIRT_IN_POST_CHAIN, "FORWARD", 3, 1);
+    iptablesLinkIPTablesBaseChain(conn, buf,
+                                  HOST_IN_CHAIN     , "INPUT"  , 1, 1);
+
+    return 0;
+}
+
+
+static int
+iptablesCreateTmpRootChain(virConnectPtr conn ATTRIBUTE_UNUSED,
+                           virBufferPtr buf,
+                           char prefix,
+                           int incoming, const char *ifname,
+                           int stopOnError)
+{
+    char chain[MAX_CHAINNAME_LENGTH];
+    char chainPrefix[2] = {
+       prefix,
+       (incoming) ? CHAINPREFIX_HOST_IN_TEMP
+                  : CHAINPREFIX_HOST_OUT_TEMP
+    };
+
+    PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname);
+
+    virBufferVSprintf(buf,
+                      CMD_DEF(IPTABLES_CMD " -N %s") CMD_SEPARATOR
+                      CMD_EXEC
+                      "%s",
+                      chain,
+                      CMD_STOPONERR(stopOnError));
+
+    return 0;
+}
+
+
+static int
+iptablesCreateTmpRootChains(virConnectPtr conn,
+                            virBufferPtr buf,
+                            const char *ifname)
+{
+    iptablesCreateTmpRootChain(conn, buf, 'F', 0, ifname, 1);
+    iptablesCreateTmpRootChain(conn, buf, 'F', 1, ifname, 1);
+    iptablesCreateTmpRootChain(conn, buf, 'H', 1, ifname, 1);
+    return 0;
+}
+
+
+static int
+_iptablesRemoveRootChain(virConnectPtr conn ATTRIBUTE_UNUSED,
+                         virBufferPtr buf,
+                         char prefix,
+                         int incoming, const char *ifname,
+                         int isTempChain)
+{
+    char chain[MAX_CHAINNAME_LENGTH];
+    char chainPrefix[2] = {
+        prefix,
+    };
+
+    if (isTempChain)
+        chainPrefix[1] = (incoming) ? CHAINPREFIX_HOST_IN_TEMP
+                                    : CHAINPREFIX_HOST_OUT_TEMP;
+    else
+        chainPrefix[1] = (incoming) ? CHAINPREFIX_HOST_IN
+                                    : CHAINPREFIX_HOST_OUT;
+
+    PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname);
+
+    virBufferVSprintf(buf,
+                      IPTABLES_CMD " -F %s" CMD_SEPARATOR
+                      IPTABLES_CMD " -X %s" CMD_SEPARATOR,
+                      chain,
+                      chain);
+
+    return 0;
+}
+
+
+static int
+iptablesRemoveRootChain(virConnectPtr conn ATTRIBUTE_UNUSED,
+                        virBufferPtr buf,
+                        char prefix,
+                        int incoming,
+                        const char *ifname)
+{
+    return _iptablesRemoveRootChain(conn, buf, prefix, incoming, ifname, 0);
+}
+
+
+static int
+iptablesRemoveTmpRootChain(virConnectPtr conn ATTRIBUTE_UNUSED,
+                           virBufferPtr buf,
+                           char prefix,
+                           int incoming,
+                           const char *ifname)
+{
+    return _iptablesRemoveRootChain(conn, buf, prefix, incoming, ifname, 1);
+}
+
+
+static int
+iptablesRemoveTmpRootChains(virConnectPtr conn,
+                            virBufferPtr buf,
+                            const char *ifname)
+{
+    iptablesRemoveTmpRootChain(conn, buf, 'F', 0, ifname);
+    iptablesRemoveTmpRootChain(conn, buf, 'F', 1, ifname);
+    iptablesRemoveTmpRootChain(conn, buf, 'H', 1, ifname);
+    return 0;
+}
+
+
+static int
+iptablesRemoveRootChains(virConnectPtr conn,
+                         virBufferPtr buf,
+                         const char *ifname)
+{
+    iptablesRemoveRootChain(conn, buf, 'F', 0, ifname);
+    iptablesRemoveRootChain(conn, buf, 'F', 1, ifname);
+    iptablesRemoveRootChain(conn, buf, 'H', 1, ifname);
+    return 0;
+}
+
+
+static int
+iptablesLinkTmpRootChain(virConnectPtr conn ATTRIBUTE_UNUSED,
+                         virBufferPtr buf,
+                         const char *basechain,
+                         char prefix,
+                         int incoming, const char *ifname,
+                         int stopOnError)
+{
+    char chain[MAX_CHAINNAME_LENGTH];
+    char chainPrefix[2] = {
+        prefix,
+        (incoming) ? CHAINPREFIX_HOST_IN_TEMP
+                   : CHAINPREFIX_HOST_OUT_TEMP
+    };
+    const char *match = (incoming) ? MATCH_PHYSDEV_IN
+                                   : MATCH_PHYSDEV_OUT;
+
+    PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname);
+
+    virBufferVSprintf(buf,
+                      CMD_DEF(IPTABLES_CMD " -A %s "
+                              "%s %s -g %s") CMD_SEPARATOR
+                      CMD_EXEC
+                      "%s",
+                      basechain,
+                      match, ifname, chain,
+
+                      CMD_STOPONERR(stopOnError));
+
+    return 0;
+}
+
+
+static int
+iptablesLinkTmpRootChains(virConnectPtr conn,
+                          virBufferPtr buf,
+                          const char *ifname)
+{
+    iptablesLinkTmpRootChain(conn, buf, VIRT_OUT_CHAIN, 'F', 0, ifname, 1);
+    iptablesLinkTmpRootChain(conn, buf, VIRT_IN_CHAIN , 'F', 1, ifname, 1);
+    iptablesLinkTmpRootChain(conn, buf, HOST_IN_CHAIN , 'H', 1, ifname, 1);
+
+    return 0;
+}
+
+
+static int
+iptablesSetupVirtInPost(virConnectPtr conn ATTRIBUTE_UNUSED,
+                        virBufferPtr buf,
+                        const char *ifname)
+{
+    const char *match = MATCH_PHYSDEV_IN;
+    virBufferVSprintf(buf,
+                      "res=$(" IPTABLES_CMD " -L " VIRT_IN_POST_CHAIN
+                      " | grep \"\\%s %s\")\n"
+                      "if [ \"${res}\" == \"\" ]; then "
+                        CMD_DEF(IPTABLES_CMD
+                        " -A " VIRT_IN_POST_CHAIN
+                        " %s %s -j ACCEPT") CMD_SEPARATOR
+                        CMD_EXEC
+                        "%s"
+                      "fi\n",
+                      PHYSDEV_IN, ifname,
+                      match, ifname,
+                      CMD_STOPONERR(1));
+    return 0;
+}
+
+
+static int
+iptablesClearVirtInPost(virConnectPtr conn ATTRIBUTE_UNUSED,
+                        virBufferPtr buf,
+                        const char *ifname)
+{
+    const char *match = MATCH_PHYSDEV_IN;
+    virBufferVSprintf(buf,
+                      IPTABLES_CMD
+                      " -D " VIRT_IN_POST_CHAIN
+                      " %s %s -j ACCEPT" CMD_SEPARATOR,
+                      match, ifname);
+    return 0;
+}
+
+static int
+_iptablesUnlinkRootChain(virConnectPtr conn ATTRIBUTE_UNUSED,
+                        virBufferPtr buf,
+                        const char *basechain,
+                        char prefix,
+                        int incoming, const char *ifname,
+                        int isTempChain)
+{
+    char chain[MAX_CHAINNAME_LENGTH];
+    char chainPrefix[2] = {
+        prefix,
+    };
+    if (isTempChain)
+        chainPrefix[1] = (incoming) ? CHAINPREFIX_HOST_IN_TEMP
+                                    : CHAINPREFIX_HOST_OUT_TEMP;
+    else
+        chainPrefix[1] = (incoming) ? CHAINPREFIX_HOST_IN
+                                    : CHAINPREFIX_HOST_OUT;
+    const char *match = (incoming) ? MATCH_PHYSDEV_IN
+                                   : MATCH_PHYSDEV_OUT;
+
+    PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname);
+
+    virBufferVSprintf(buf,
+                      IPTABLES_CMD " -D %s "
+                      "%s %s -g %s" CMD_SEPARATOR,
+                      basechain,
+                      match, ifname, chain);
+
+    return 0;
+}
+
+
+static int
+iptablesUnlinkRootChain(virConnectPtr conn ATTRIBUTE_UNUSED,
+                        virBufferPtr buf,
+                        const char *basechain,
+                        char prefix,
+                        int incoming, const char *ifname)
+{
+    return _iptablesUnlinkRootChain(conn, buf,
+                                    basechain, prefix, incoming, ifname, 0);
+}
+
+
+static int
+iptablesUnlinkTmpRootChain(virConnectPtr conn ATTRIBUTE_UNUSED,
+                           virBufferPtr buf,
+                           const char *basechain,
+                           char prefix,
+                           int incoming, const char *ifname)
+{
+    return _iptablesUnlinkRootChain(conn, buf,
+                                    basechain, prefix, incoming, ifname, 1);
+}
+
+
+static int
+iptablesUnlinkRootChains(virConnectPtr conn,
+                         virBufferPtr buf,
+                         const char *ifname)
+{
+    iptablesUnlinkRootChain(conn, buf, VIRT_OUT_CHAIN, 'F', 0, ifname);
+    iptablesUnlinkRootChain(conn, buf, VIRT_IN_CHAIN , 'F', 1, ifname);
+    iptablesUnlinkRootChain(conn, buf, HOST_IN_CHAIN , 'H', 1, ifname);
+
+    return 0;
+}
+
+
+static int
+iptablesUnlinkTmpRootChains(virConnectPtr conn,
+                            virBufferPtr buf,
+                            const char *ifname)
+{
+    iptablesUnlinkTmpRootChain(conn, buf, VIRT_OUT_CHAIN, 'F', 0, ifname);
+    iptablesUnlinkTmpRootChain(conn, buf, VIRT_IN_CHAIN , 'F', 1, ifname);
+    iptablesUnlinkTmpRootChain(conn, buf, HOST_IN_CHAIN , 'H', 1, ifname);
+    return 0;
+}
+
+
+static int
+iptablesRenameTmpRootChain(virConnectPtr conn ATTRIBUTE_UNUSED,
+                           virBufferPtr buf,
+                           char prefix,
+                           int incoming,
+                           const char *ifname)
+{
+    char tmpchain[MAX_CHAINNAME_LENGTH], chain[MAX_CHAINNAME_LENGTH];
+    char tmpChainPrefix[2] = {
+        prefix,
+        (incoming) ? CHAINPREFIX_HOST_IN_TEMP
+                   : CHAINPREFIX_HOST_OUT_TEMP
+    };
+    char chainPrefix[2] = {
+        prefix,
+        (incoming) ? CHAINPREFIX_HOST_IN
+                   : CHAINPREFIX_HOST_OUT
+    };
+
+    PRINT_IPT_ROOT_CHAIN(tmpchain, tmpChainPrefix, ifname);
+    PRINT_IPT_ROOT_CHAIN(   chain,    chainPrefix, ifname);
+
+    virBufferVSprintf(buf,
+                      IPTABLES_CMD " -E %s %s" CMD_SEPARATOR,
+                      tmpchain,
+                      chain);
+    return 0;
+}
+
+
+static int
+iptablesRenameTmpRootChains(virConnectPtr conn,
+                            virBufferPtr buf,
+                            const char *ifname)
+{
+    iptablesRenameTmpRootChain(conn, buf, 'F', 0, ifname);
+    iptablesRenameTmpRootChain(conn, buf, 'F', 1, ifname);
+    iptablesRenameTmpRootChain(conn, buf, 'H', 1, ifname);
+    return 0;
+}
+
+
+static void
+iptablesInstCommand(virConnectPtr conn ATTRIBUTE_UNUSED,
+                    virBufferPtr buf,
+                    const char *templ, char cmd, int pos,
+                    int stopOnError)
+{
+    char position[10] = { 0 };
+    if (pos >= 0)
+        snprintf(position, sizeof(position), "%d", pos);
+
+    // FIXME: need error handling
+    virBufferVSprintf(buf, templ, cmd, position);
+    virBufferVSprintf(buf, CMD_SEPARATOR "%s",
+                      CMD_STOPONERR(stopOnError));
+}
+
+
+static int
+iptablesHandleIpHdr(virConnectPtr conn ATTRIBUTE_UNUSED,
+                    virBufferPtr buf,
+                    virNWFilterHashTablePtr vars,
+                    ipHdrDataDefPtr ipHdr,
+                    int directionIn)
+{
+    char ipaddr[INET_ADDRSTRLEN];
+    const char *src = "--source";
+    const char *dst = "--destination";
+    if (directionIn) {
+        src = "--destination";
+        dst = "--source";
+    }
+
+    if (HAS_ENTRY_ITEM(&ipHdr->dataSrcAddr)) {
+        if (printDataType(conn,
+                          vars,
+                          ipaddr, sizeof(ipaddr),
+                          &ipHdr->dataSrcAddr))
+            goto err_exit;
+
+        virBufferVSprintf(buf,
+                          " %s %s %s",
+                          ENTRY_GET_NEG_SIGN(&ipHdr->dataSrcAddr),
+                          src,
+                          ipaddr);
+
+        if (HAS_ENTRY_ITEM(&ipHdr->dataSrcMask)) {
+             virBufferVSprintf(buf,
+                              "/%d",
+                              ipHdr->dataSrcMask.u.u8);
+        }
+    }
+
+    if (HAS_ENTRY_ITEM(&ipHdr->dataDstAddr)) {
+
+        if (printDataType(conn,
+                          vars,
+                          ipaddr, sizeof(ipaddr),
+                          &ipHdr->dataDstAddr))
+           goto err_exit;
+
+        virBufferVSprintf(buf,
+                          " %s %s %s",
+                          ENTRY_GET_NEG_SIGN(&ipHdr->dataDstAddr),
+                          dst,
+                          ipaddr);
+
+        if (HAS_ENTRY_ITEM(&ipHdr->dataDstMask)) {
+            virBufferVSprintf(buf,
+                              "/%d",
+                              ipHdr->dataDstMask.u.u8);
+        }
+    }
+
+    return 0;
+
+err_exit:
+    virBufferFreeAndReset(buf);
+
+    return -1;
+}
+
+
+static int
+iptablesHandlePortData(virConnectPtr conn ATTRIBUTE_UNUSED,
+                       virBufferPtr buf,
+                       virNWFilterHashTablePtr vars,
+                       portDataDefPtr portData,
+                       int directionIn)
+{
+    char portstr[20];
+    const char *sport = "--sport";
+    const char *dport = "--dport";
+    if (directionIn) {
+        sport = "--dport";
+        dport = "--sport";
+    }
+
+    if (HAS_ENTRY_ITEM(&portData->dataSrcPortStart)) {
+        if (printDataType(conn,
+                          vars,
+                          portstr, sizeof(portstr),
+                          &portData->dataSrcPortStart))
+            goto err_exit;
+
+        virBufferVSprintf(buf,
+                          " %s %s %s",
+                          ENTRY_GET_NEG_SIGN(&portData->dataSrcPortStart),
+                          sport,
+                          portstr);
+
+        if (HAS_ENTRY_ITEM(&portData->dataSrcPortEnd)) {
+            if (printDataType(conn,
+                              vars,
+                              portstr, sizeof(portstr),
+                              &portData->dataSrcPortEnd))
+                goto err_exit;
+
+             virBufferVSprintf(buf,
+                               ":%s",
+                               portstr);
+        }
+    }
+
+    if (HAS_ENTRY_ITEM(&portData->dataDstPortStart)) {
+        if (printDataType(conn,
+                          vars,
+                          portstr, sizeof(portstr),
+                          &portData->dataDstPortStart))
+            goto err_exit;
+
+        virBufferVSprintf(buf,
+                          " %s %s %s",
+                          ENTRY_GET_NEG_SIGN(&portData->dataDstPortStart),
+                          dport,
+                          portstr);
+
+        if (HAS_ENTRY_ITEM(&portData->dataDstPortEnd)) {
+            if (printDataType(conn,
+                              vars,
+                              portstr, sizeof(portstr),
+                              &portData->dataDstPortEnd))
+                goto err_exit;
+
+             virBufferVSprintf(buf,
+                               ":%s",
+                               portstr);
+        }
+    }
+
+    return 0;
+
+err_exit:
+    return 1;
+}
+
+/*
+ * _iptablesCreateRuleInstance:
+ * @conn : Pointer to a virConnect object
+ * @chainPrefix : The prefix to put in front of the name of the chain
+ * @nwfilter : The filter
+ * @rule: The rule of the filter to convert
+ * @ifname : The name of the interface to apply the rule to
+ * @vars : A map containing the variables to resolve
+ * @res : The data structure to store the result(s) into
+ *
+ * Convert a single rule into its representation for later instantiation
+ *
+ * Returns 0 in case of success with the result stored in the data structure
+ * pointed to by res, != 0 otherwise with the error message stored in the
+ * virConnect object.
+ */
+static int
+_iptablesCreateRuleInstance(virConnectPtr conn,
+                            int directionIn,
+                            const char *chainPrefix,
+                            virNWFilterDefPtr nwfilter,
+                            virNWFilterRuleDefPtr rule,
+                            const char *ifname,
+                            virNWFilterHashTablePtr vars,
+                            virNWFilterRuleInstPtr res,
+                            const char *match,
+                            const char *accept_target)
+{
+    char chain[MAX_CHAINNAME_LENGTH];
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    const char *target;
+
+    PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname);
+
+    switch (rule->prtclType) {
+    case VIR_NWFILTER_RULE_PROTOCOL_TCP:
+        virBufferVSprintf(&buf,
+                          CMD_DEF_PRE IPTABLES_CMD " -%%c %s %%s",
+                          chain);
+
+        virBufferAddLit(&buf, " -p tcp");
+
+        if (iptablesHandleIpHdr(conn,
+                                &buf,
+                                vars,
+                                &rule->p.tcpHdrFilter.ipHdr,
+                                directionIn))
+            goto err_exit;
+
+        if (iptablesHandlePortData(conn,
+                                   &buf,
+                                   vars,
+                                   &rule->p.tcpHdrFilter.portData,
+                                   directionIn))
+            goto err_exit;
+
+    break;
+
+    case VIR_NWFILTER_RULE_PROTOCOL_UDP:
+        virBufferVSprintf(&buf,
+                          CMD_DEF_PRE IPTABLES_CMD " -%%c %s %%s",
+                          chain);
+
+        virBufferAddLit(&buf, " -p udp");
+
+        if (iptablesHandleIpHdr(conn,
+                                &buf,
+                                vars,
+                                &rule->p.udpHdrFilter.ipHdr,
+                                directionIn))
+            goto err_exit;
+
+        if (iptablesHandlePortData(conn,
+                                   &buf,
+                                   vars,
+                                   &rule->p.udpHdrFilter.portData,
+                                   directionIn))
+            goto err_exit;
+    break;
+
+    case VIR_NWFILTER_RULE_PROTOCOL_SCP:
+        virBufferVSprintf(&buf,
+                          CMD_DEF_PRE IPTABLES_CMD " -%%c %s %%s",
+                          chain);
+
+        virBufferAddLit(&buf, " -p scp");
+
+        if (iptablesHandleIpHdr(conn,
+                                &buf,
+                                vars,
+                                &rule->p.sctpHdrFilter.ipHdr,
+                                directionIn))
+            goto err_exit;
+
+        if (iptablesHandlePortData(conn,
+                                   &buf,
+                                   vars,
+                                   &rule->p.sctpHdrFilter.portData,
+                                   directionIn))
+            goto err_exit;
+    break;
+
+    case VIR_NWFILTER_RULE_PROTOCOL_ICMP:
+        virBufferVSprintf(&buf,
+                          CMD_DEF_PRE IPTABLES_CMD " -%%c %s %%s",
+                          chain);
+
+        virBufferAddLit(&buf, " -p icmp");
+
+        if (iptablesHandleIpHdr(conn,
+                                &buf,
+                                vars,
+                                &rule->p.icmpHdrFilter.ipHdr,
+                                directionIn))
+            goto err_exit;
+
+        if (HAS_ENTRY_ITEM(&rule->p.icmpHdrFilter.dataICMPType)) {
+            virBufferVSprintf(&buf,
+                              " %s --icmp-type %d",
+                              ENTRY_GET_NEG_SIGN(&rule->p.icmpHdrFilter.dataICMPType),
+                              rule->p.icmpHdrFilter.dataICMPType.u.u8);
+
+            if (HAS_ENTRY_ITEM(&rule->p.icmpHdrFilter.dataICMPCode)) {
+                 virBufferVSprintf(&buf,
+                                   "/%d",
+                                   rule->p.icmpHdrFilter.dataICMPCode.u.u8);
+            }
+        }
+    break;
+
+    case VIR_NWFILTER_RULE_PROTOCOL_ALL:
+        virBufferVSprintf(&buf,
+                          CMD_DEF_PRE IPTABLES_CMD " -%%c %s %%s",
+                          chain);
+
+        virBufferAddLit(&buf, " -p all");
+
+        if (iptablesHandleIpHdr(conn,
+                                &buf,
+                                vars,
+                                &rule->p.allHdrFilter.ipHdr,
+                                directionIn))
+            goto err_exit;
+
+    break;
+
+    default:
+        return -1;
+    }
+
+    if (match)
+        virBufferVSprintf(&buf, " %s", match);
+
+    if (rule->action == VIR_NWFILTER_RULE_ACTION_ACCEPT)
+        target = accept_target;
+    else
+        target = "DROP";
+
+    virBufferVSprintf(&buf,
+                      " -j %s" CMD_DEF_POST CMD_SEPARATOR
+                      CMD_EXEC,
+                      target);
+
+    if (virBufferError(&buf)) {
+        virBufferFreeAndReset(&buf);
+        virReportOOMError();
+        return -1;
+    }
+
+    return ebiptablesAddRuleInst(conn,
+                                 res,
+                                 virBufferContentAndReset(&buf),
+                                 nwfilter->chainsuffix,
+                                 '\0',
+                                 rule->priority,
+                                 1);
+
+
+err_exit:
+    virBufferFreeAndReset(&buf);
+
+    return -1;
+
+}
+
+
+static int
+iptablesCreateRuleInstance(virConnectPtr conn,
+                           virNWFilterDefPtr nwfilter,
+                           virNWFilterRuleDefPtr rule,
+                           const char *ifname,
+                           virNWFilterHashTablePtr vars,
+                           virNWFilterRuleInstPtr res)
+{
+    int rc;
+    int directionIn = 0;
+    char chainPrefix[2];
+    int needState = 1;
+
+    if ((rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN) ||
+        (rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT)) {
+        directionIn = 1;
+        needState = 0;
+    }
+
+    chainPrefix[0] = 'F';
+
+    chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+    rc = _iptablesCreateRuleInstance(conn,
+                                     directionIn,
+                                     chainPrefix,
+                                     nwfilter,
+                                     rule,
+                                     ifname,
+                                     vars,
+                                     res,
+                                     needState ? MATCH_STATE_OUT
+                                               : NULL,
+                                     "RETURN");
+    if (rc)
+        return rc;
+
+    chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP;
+    rc = _iptablesCreateRuleInstance(conn,
+                                     !directionIn,
+                                     chainPrefix,
+                                     nwfilter,
+                                     rule,
+                                     ifname,
+                                     vars,
+                                     res,
+                                     needState ? MATCH_STATE_IN
+                                               : NULL,
+                                     "ACCEPT");
+    if (rc)
+        return rc;
+
+    chainPrefix[0] = 'H';
+    chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+    rc = _iptablesCreateRuleInstance(conn,
+                                     directionIn,
+                                     chainPrefix,
+                                     nwfilter,
+                                     rule,
+                                     ifname,
+                                     vars,
+                                     res,
+                                     NULL,
+                                     "ACCEPT");
+    if (rc)
+        return rc;
+
+    return rc;
+}
Index: libvirt-acl/src/conf/nwfilter_conf.h
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_conf.h
+++ libvirt-acl/src/conf/nwfilter_conf.h
@@ -164,6 +164,54 @@ struct _ipHdrFilterDef {
 };
 
 
+typedef struct _icmpHdrFilterDef  icmpHdrFilterDef;
+typedef icmpHdrFilterDef *icmpHdrFilterDefPtr;
+struct _icmpHdrFilterDef {
+    ipHdrDataDef ipHdr;
+    nwItemDesc dataICMPType;
+    nwItemDesc dataICMPCode;
+    nwItemDesc dataStateFlags;
+};
+
+
+typedef struct _allHdrFilterDef  allHdrFilterDef;
+typedef allHdrFilterDef *allHdrFilterDefPtr;
+struct _allHdrFilterDef {
+    ipHdrDataDef ipHdr;
+};
+
+
+typedef struct _igmpHdrFilterDef  igmpHdrFilterDef;
+typedef igmpHdrFilterDef *igmpHdrFilterDefPtr;
+struct _igmpHdrFilterDef {
+    ipHdrDataDef ipHdr;
+};
+
+
+typedef struct _tcpHdrFilterDef  tcpHdrFilterDef;
+typedef tcpHdrFilterDef *tcpHdrFilterDefPtr;
+struct _tcpHdrFilterDef {
+    ipHdrDataDef ipHdr;
+    portDataDef  portData;
+};
+
+
+typedef struct _udpHdrFilterDef  udpHdrFilterDef;
+typedef udpHdrFilterDef *udpHdrFilterDefPtr;
+struct _udpHdrFilterDef {
+    ipHdrDataDef ipHdr;
+    portDataDef  portData;
+};
+
+
+typedef struct _sctpHdrFilterDef  sctpHdrFilterDef;
+typedef sctpHdrFilterDef *sctpHdrFilterDefPtr;
+struct _sctpHdrFilterDef {
+    ipHdrDataDef ipHdr;
+    portDataDef  portData;
+};
+
+
 enum virNWFilterRuleActionType {
     VIR_NWFILTER_RULE_ACTION_DROP = 0,
     VIR_NWFILTER_RULE_ACTION_ACCEPT,
@@ -191,6 +239,14 @@ enum virNWFilterRuleProtocolType {
     VIR_NWFILTER_RULE_PROTOCOL_MAC,
     VIR_NWFILTER_RULE_PROTOCOL_ARP,
     VIR_NWFILTER_RULE_PROTOCOL_IP,
+    VIR_NWFILTER_RULE_PROTOCOL_TCP,
+    VIR_NWFILTER_RULE_PROTOCOL_ICMP,
+    VIR_NWFILTER_RULE_PROTOCOL_IGMP,
+    VIR_NWFILTER_RULE_PROTOCOL_UDP,
+    VIR_NWFILTER_RULE_PROTOCOL_SCP,
+    VIR_NWFILTER_RULE_PROTOCOL_ALL,
+
+    VIR_NWFILTER_RULE_PROTOCOL_LAST
 };
 
 enum virNWFilterEbtablesTableType {
@@ -216,6 +272,12 @@ struct _virNWFilterRuleDef {
         ethHdrFilterDef  ethHdrFilter;
         arpHdrFilterDef  arpHdrFilter;
         ipHdrFilterDef   ipHdrFilter;
+        tcpHdrFilterDef  tcpHdrFilter;
+        icmpHdrFilterDef icmpHdrFilter;
+        udpHdrFilterDef  udpHdrFilter;
+        allHdrFilterDef  allHdrFilter;
+        igmpHdrFilterDef igmpHdrFilter;
+        sctpHdrFilterDef sctpHdrFilter;
     } p;
 
     int nvars;
Index: libvirt-acl/src/conf/nwfilter_conf.c
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_conf.c
+++ libvirt-acl/src/conf/nwfilter_conf.c
@@ -84,6 +84,18 @@ VIR_ENUM_IMPL(virNWFilterChainSuffix, VI
               "arp",
               "ipv4");
 
+VIR_ENUM_IMPL(virNWFilterRuleProtocol, VIR_NWFILTER_RULE_PROTOCOL_LAST,
+              "none",
+              "mac",
+              "arp",
+              "ip",
+              "tcp",
+              "icmp",
+              "igmp",
+              "udp",
+              "scp",
+              "all");
+
 
 /*
  * a map entry for a simple static int-to-string map
@@ -790,6 +802,236 @@ static const virXMLAttr2Struct ipAttribu
     }
 };
 
+static const virXMLAttr2Struct tcpAttributes[] = {
+    {
+        .name = SRCIPADDR,
+        .datatype = DATATYPE_IPADDR,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.ipHdr.dataSrcAddr),
+    },
+    {
+        .name = DSTIPADDR,
+        .datatype = DATATYPE_IPADDR,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.ipHdr.dataDstAddr),
+    },
+    {
+        .name = SRCIPMASK,
+        .datatype = DATATYPE_IPMASK,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.ipHdr.dataSrcMask),
+    },
+    {
+        .name = DSTIPMASK,
+        .datatype = DATATYPE_IPMASK,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.ipHdr.dataDstMask),
+    },
+    {
+        .name = SRCPORTSTART,
+        .datatype = DATATYPE_UINT16,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.portData.dataSrcPortStart),
+    },
+    {
+        .name = SRCPORTEND,
+        .datatype = DATATYPE_UINT16,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.portData.dataSrcPortEnd),
+    },
+    {
+        .name = DSTPORTSTART,
+        .datatype = DATATYPE_UINT16,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.portData.dataDstPortStart),
+    },
+    {
+        .name = DSTPORTEND,
+        .datatype = DATATYPE_UINT16,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.portData.dataDstPortEnd),
+    },
+    {
+        .name = NULL,
+    }
+};
+
+static const virXMLAttr2Struct udpAttributes[] = {
+    {
+        .name = SRCIPADDR,
+        .datatype = DATATYPE_IPADDR,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.udpHdrFilter.ipHdr.dataSrcAddr),
+    },
+    {
+        .name = DSTIPADDR,
+        .datatype = DATATYPE_IPADDR,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.udpHdrFilter.ipHdr.dataDstAddr),
+    },
+    {
+        .name = SRCIPMASK,
+        .datatype = DATATYPE_IPMASK,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.udpHdrFilter.ipHdr.dataSrcMask),
+    },
+    {
+        .name = DSTIPMASK,
+        .datatype = DATATYPE_IPMASK,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.udpHdrFilter.ipHdr.dataDstMask),
+    },
+    {
+        .name = SRCPORTSTART,
+        .datatype = DATATYPE_UINT16,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.udpHdrFilter.portData.dataSrcPortStart),
+    },
+    {
+        .name = SRCPORTEND,
+        .datatype = DATATYPE_UINT16,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.udpHdrFilter.portData.dataSrcPortEnd),
+    },
+    {
+        .name = DSTPORTSTART,
+        .datatype = DATATYPE_UINT16,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.udpHdrFilter.portData.dataDstPortStart),
+    },
+    {
+        .name = DSTPORTEND,
+        .datatype = DATATYPE_UINT16,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.udpHdrFilter.portData.dataDstPortEnd),
+    },
+    {
+        .name = NULL,
+    }
+};
+
+
+static const virXMLAttr2Struct sctpAttributes[] = {
+    {
+        .name = SRCIPADDR,
+        .datatype = DATATYPE_IPADDR,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.sctpHdrFilter.ipHdr.dataSrcAddr),
+    },
+    {
+        .name = DSTIPADDR,
+        .datatype = DATATYPE_IPADDR,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.sctpHdrFilter.ipHdr.dataDstAddr),
+    },
+    {
+        .name = SRCIPMASK,
+        .datatype = DATATYPE_IPMASK,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.sctpHdrFilter.ipHdr.dataSrcMask),
+    },
+    {
+        .name = DSTIPMASK,
+        .datatype = DATATYPE_IPMASK,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.sctpHdrFilter.ipHdr.dataDstMask),
+    },
+    {
+        .name = SRCPORTSTART,
+        .datatype = DATATYPE_UINT16,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.sctpHdrFilter.portData.dataSrcPortStart),
+    },
+    {
+        .name = SRCPORTEND,
+        .datatype = DATATYPE_UINT16,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.sctpHdrFilter.portData.dataSrcPortEnd),
+    },
+    {
+        .name = DSTPORTSTART,
+        .datatype = DATATYPE_UINT16,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.sctpHdrFilter.portData.dataDstPortStart),
+    },
+    {
+        .name = DSTPORTEND,
+        .datatype = DATATYPE_UINT16,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.sctpHdrFilter.portData.dataDstPortEnd),
+    },
+    {
+        .name = NULL,
+    }
+};
+
+
+static const virXMLAttr2Struct icmpAttributes[] = {
+    {
+        .name = SRCIPADDR,
+        .datatype = DATATYPE_IPADDR,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.ipHdr.dataSrcAddr),
+    },
+    {
+        .name = DSTIPADDR,
+        .datatype = DATATYPE_IPADDR,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.ipHdr.dataDstAddr),
+    },
+    {
+        .name = SRCIPMASK,
+        .datatype = DATATYPE_IPMASK,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.ipHdr.dataSrcMask),
+    },
+    {
+        .name = DSTIPMASK,
+        .datatype = DATATYPE_IPMASK,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.ipHdr.dataDstMask),
+    },
+    {
+        .name = "type",
+        .datatype = DATATYPE_UINT8,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPType),
+    },
+    {
+        .name = "code",
+        .datatype = DATATYPE_UINT8,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPCode),
+    },
+    {
+        .name = NULL,
+    }
+};
+
+
+static const virXMLAttr2Struct allAttributes[] = {
+    {
+        .name = SRCIPADDR,
+        .datatype = DATATYPE_IPADDR,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.allHdrFilter.ipHdr.dataSrcAddr),
+    },
+    {
+        .name = DSTIPADDR,
+        .datatype = DATATYPE_IPADDR,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.allHdrFilter.ipHdr.dataDstAddr),
+    },
+    {
+        .name = SRCIPMASK,
+        .datatype = DATATYPE_IPMASK,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.allHdrFilter.ipHdr.dataSrcMask),
+    },
+    {
+        .name = DSTIPMASK,
+        .datatype = DATATYPE_IPMASK,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.allHdrFilter.ipHdr.dataDstMask),
+    },
+    {
+        .name = NULL,
+    }
+};
+
+
+static const virXMLAttr2Struct igmpAttributes[] = {
+    {
+        .name = SRCIPADDR,
+        .datatype = DATATYPE_IPADDR,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.igmpHdrFilter.ipHdr.dataSrcAddr),
+    },
+    {
+        .name = DSTIPADDR,
+        .datatype = DATATYPE_IPADDR,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.igmpHdrFilter.ipHdr.dataDstAddr),
+    },
+    {
+        .name = SRCIPMASK,
+        .datatype = DATATYPE_IPMASK,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.igmpHdrFilter.ipHdr.dataSrcMask),
+    },
+    {
+        .name = DSTIPMASK,
+        .datatype = DATATYPE_IPMASK,
+        .dataIdx = offsetof(virNWFilterRuleDef, p.igmpHdrFilter.ipHdr.dataDstMask),
+    },
+    {
+        .name = NULL,
+    }
+};
+
 
 typedef struct _virAttributes virAttributes;
 struct _virAttributes {
@@ -813,6 +1055,30 @@ static const virAttributes virAttr[] = {
         .att = ipAttributes,
         .prtclType = VIR_NWFILTER_RULE_PROTOCOL_IP,
     }, {
+        .id = "tcp",
+        .att = tcpAttributes,
+        .prtclType = VIR_NWFILTER_RULE_PROTOCOL_TCP,
+    }, {
+        .id = "udp",
+        .att = udpAttributes,
+        .prtclType = VIR_NWFILTER_RULE_PROTOCOL_UDP,
+    }, {
+        .id = "sctp",
+        .att = sctpAttributes,
+        .prtclType = VIR_NWFILTER_RULE_PROTOCOL_SCP,
+    }, {
+        .id = "icmp",
+        .att = icmpAttributes,
+        .prtclType = VIR_NWFILTER_RULE_PROTOCOL_ICMP,
+    }, {
+        .id = "all", // = 'any'
+        .att = allAttributes,
+        .prtclType = VIR_NWFILTER_RULE_PROTOCOL_ALL,
+    }, {
+        .id = "igmp",
+        .att = igmpAttributes,
+        .prtclType = VIR_NWFILTER_RULE_PROTOCOL_IGMP,
+    }, {
         .id = NULL,
     }
 };
@@ -1356,8 +1622,60 @@ virNWFilterRuleDefFixup(virNWFilterRuleD
     case VIR_NWFILTER_RULE_PROTOCOL_ARP:
     case VIR_NWFILTER_RULE_PROTOCOL_NONE:
     break;
-    }
 
+    case VIR_NWFILTER_RULE_PROTOCOL_TCP:
+        COPY_NEG_SIGN(rule->p.tcpHdrFilter.ipHdr.dataSrcMask,
+                      rule->p.tcpHdrFilter.ipHdr.dataSrcAddr);
+        COPY_NEG_SIGN(rule->p.tcpHdrFilter.ipHdr.dataDstMask,
+                      rule->p.tcpHdrFilter.ipHdr.dataDstAddr);
+        COPY_NEG_SIGN(rule->p.tcpHdrFilter.portData.dataSrcPortEnd,
+                      rule->p.tcpHdrFilter.portData.dataSrcPortStart);
+        COPY_NEG_SIGN(rule->p.tcpHdrFilter.portData.dataDstPortStart,
+                      rule->p.tcpHdrFilter.portData.dataSrcPortStart);
+        COPY_NEG_SIGN(rule->p.tcpHdrFilter.portData.dataDstPortEnd,
+                      rule->p.tcpHdrFilter.portData.dataSrcPortStart);
+    break;
+
+    case VIR_NWFILTER_RULE_PROTOCOL_UDP:
+        COPY_NEG_SIGN(rule->p.udpHdrFilter.ipHdr.dataSrcMask,
+                      rule->p.udpHdrFilter.ipHdr.dataSrcAddr);
+        COPY_NEG_SIGN(rule->p.udpHdrFilter.ipHdr.dataDstMask,
+                      rule->p.udpHdrFilter.ipHdr.dataDstAddr);
+        COPY_NEG_SIGN(rule->p.udpHdrFilter.portData.dataSrcPortEnd,
+                      rule->p.udpHdrFilter.portData.dataSrcPortStart);
+        COPY_NEG_SIGN(rule->p.udpHdrFilter.portData.dataDstPortStart,
+                      rule->p.udpHdrFilter.portData.dataSrcPortStart);
+        COPY_NEG_SIGN(rule->p.udpHdrFilter.portData.dataDstPortEnd,
+                      rule->p.udpHdrFilter.portData.dataSrcPortStart);
+    break;
+
+    case VIR_NWFILTER_RULE_PROTOCOL_SCP:
+        COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataSrcMask,
+                      rule->p.sctpHdrFilter.ipHdr.dataSrcAddr);
+        COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataDstMask,
+                      rule->p.sctpHdrFilter.ipHdr.dataDstAddr);
+        COPY_NEG_SIGN(rule->p.sctpHdrFilter.portData.dataSrcPortEnd,
+                      rule->p.sctpHdrFilter.portData.dataSrcPortStart);
+        COPY_NEG_SIGN(rule->p.sctpHdrFilter.portData.dataDstPortStart,
+                      rule->p.sctpHdrFilter.portData.dataSrcPortStart);
+        COPY_NEG_SIGN(rule->p.sctpHdrFilter.portData.dataDstPortEnd,
+                      rule->p.sctpHdrFilter.portData.dataSrcPortStart);
+    break;
+
+    case VIR_NWFILTER_RULE_PROTOCOL_ICMP:
+        COPY_NEG_SIGN(rule->p.icmpHdrFilter.ipHdr.dataSrcMask,
+                      rule->p.icmpHdrFilter.ipHdr.dataSrcAddr);
+        COPY_NEG_SIGN(rule->p.icmpHdrFilter.ipHdr.dataDstMask,
+                      rule->p.icmpHdrFilter.ipHdr.dataDstAddr);
+        COPY_NEG_SIGN(rule->p.icmpHdrFilter.dataICMPCode,
+                      rule->p.icmpHdrFilter.dataICMPType);
+    break;
+
+    case VIR_NWFILTER_RULE_PROTOCOL_ALL:
+    case VIR_NWFILTER_RULE_PROTOCOL_IGMP:
+    case VIR_NWFILTER_RULE_PROTOCOL_LAST:
+    break;
+    }
 #undef COPY_NEG_SIGN
 }
 
Index: libvirt-acl/src/libvirt_private.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_private.syms
+++ libvirt-acl/src/libvirt_private.syms
@@ -457,6 +457,7 @@ virNWFilterPoolObjListFree;
 virNWFilterDefFormat;
 virNWFilterChainSuffixTypeToString;
 virNWFilterRuleActionTypeToString;
+virNWFilterRuleProtocolTypeToString;
 virNWFilterJumpTargetTypeToString;
 virNWFilterHashTableCreate;
 virNWFilterHashTableFree;
Index: libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.h
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_ebiptables_driver.h
+++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.h
@@ -32,6 +32,7 @@ struct _ebiptablesRuleInst {
     enum virNWFilterChainSuffixType neededProtocolChain;
     char chainprefix;    // I for incoming, O for outgoing
     unsigned int priority;
+    int isIptablesRule;
 };
 
 extern virNWFilterTechDriver ebiptables_driver;
Index: libvirt-acl/configure.ac
===================================================================
--- libvirt-acl.orig/configure.ac
+++ libvirt-acl/configure.ac
@@ -300,6 +300,13 @@ AC_DEFINE_UNQUOTED([IPTABLES_PATH], "$IP
 AC_PATH_PROG([EBTABLES_PATH], [ebtables], /sbin/ebtables, [/usr/sbin:$PATH])
 AC_DEFINE_UNQUOTED([EBTABLES_PATH], "$EBTABLES_PATH", [path to ebtables binary])
 
+AC_PATH_PROG([GREP_PATH], [grep], /bin/grep, [/bin:$PATH])
+AC_DEFINE_UNQUOTED([GREP_PATH], "$GREP_PATH", [path to grep binary])
+
+AC_PATH_PROG([GAWK_PATH], [gawk], /bin/gawk, [/bin:$PATH])
+AC_DEFINE_UNQUOTED([GAWK_PATH], "$GAWK_PATH", [path to gawk binary])
+
+
 if test "$with_openvz" = "yes"; then
     AC_DEFINE_UNQUOTED([WITH_OPENVZ], 1, [whether OpenVZ driver is enabled])
 fi
--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list

[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]