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(a)us.ibm.com>
---
configure.ac | 7
src/conf/nwfilter_conf.c | 278 ++++++
src/conf/nwfilter_conf.h | 73 +
src/libvirt_private.syms | 1
src/nwfilter/nwfilter_ebiptables_driver.c | 1231 ++++++++++++++++++++++++++++--
src/nwfilter/nwfilter_ebiptables_driver.h | 7
6 files changed, 1529 insertions(+), 68 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
@@ -63,7 +63,10 @@
#define EBTABLES_CMD EBTABLES_PATH
+#define IPTABLES_CMD IPTABLES_PATH
#define BASH_CMD BASH_PATH
+#define GREP_CMD GREP_PATH
+#define GAWK_CMD GAWK_PATH
#define PRINT_ROOT_CHAIN(buf, prefix, ifname) \
snprintf(buf, sizeof(buf), "libvirt-%c-%s", prefix, ifname)
@@ -71,6 +74,28 @@
snprintf(buf, sizeof(buf), "%c-%s-%s", prefix, ifname, suffix)
+#define VIRT_IN_CHAIN "libvirt-in"
+#define VIRT_OUT_CHAIN "libvirt-out"
+#define VIRT_IN_POST_CHAIN "libvirt-in-post"
+#define HOST_IN_CHAIN "libvirt-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
+
+
static const char *supported_protocols[] = {
"ipv4",
"ipv6",
@@ -195,108 +220,1087 @@ printDataType(virConnectPtr conn,
}
-static void
-ebiptablesRuleInstFree(ebiptablesRuleInstPtr inst)
-{
- if (!inst)
- return;
+static void
+ebiptablesRuleInstFree(ebiptablesRuleInstPtr inst)
+{
+ if (!inst)
+ return;
+
+ VIR_FREE(inst->commandTemplate);
+ VIR_FREE(inst);
+}
+
+
+static int
+ebiptablesAddRuleInst(virConnectPtr conn,
+ virNWFilterRuleInstPtr res,
+ char *commandTemplate,
+ enum virNWFilterChainSuffixType neededChain,
+ char chainprefix,
+ unsigned int priority,
+ enum RuleType ruleType)
+{
+ ebiptablesRuleInstPtr inst;
+
+ if (VIR_ALLOC(inst) < 0) {
+ virReportOOMError();
+ return 1;
+ }
+
+ inst->commandTemplate = commandTemplate;
+ inst->neededProtocolChain = neededChain;
+ inst->chainprefix = chainprefix;
+ inst->priority = priority;
+ inst->ruleType = ruleType;
+
+ return virNWFilterRuleInstAddData(conn, res, inst);
+}
+
+
+static int
+ebtablesHandleEthHdr(virConnectPtr conn,
+ virBufferPtr buf,
+ virNWFilterHashTablePtr vars,
+ ethHdrDataDefPtr ethHdr)
+{
+ char macaddr[VIR_MAC_STRING_BUFLEN];
+
+ if (HAS_ENTRY_ITEM(ðHdr->dataSrcMACAddr)) {
+ if (printDataType(conn,
+ vars,
+ macaddr, sizeof(macaddr),
+ ðHdr->dataSrcMACAddr))
+ goto err_exit;
+
+ virBufferVSprintf(buf,
+ " -s %s %s",
+ ENTRY_GET_NEG_SIGN(ðHdr->dataSrcMACAddr),
+ macaddr);
+
+ if (HAS_ENTRY_ITEM(ðHdr->dataSrcMACMask)) {
+ if (printDataType(conn,
+ vars,
+ macaddr, sizeof(macaddr),
+ ðHdr->dataSrcMACMask))
+ goto err_exit;
+
+ virBufferVSprintf(buf,
+ "/%s",
+ macaddr);
+ }
+ }
+
+ if (HAS_ENTRY_ITEM(ðHdr->dataDstMACAddr)) {
+ if (printDataType(conn,
+ vars,
+ macaddr, sizeof(macaddr),
+ ðHdr->dataDstMACAddr))
+ goto err_exit;
+
+ virBufferVSprintf(buf,
+ " -d %s %s",
+ ENTRY_GET_NEG_SIGN(ðHdr->dataDstMACAddr),
+ macaddr);
+
+ if (HAS_ENTRY_ITEM(ðHdr->dataDstMACMask)) {
+ if (printDataType(conn,
+ vars,
+ macaddr, sizeof(macaddr),
+ ðHdr->dataDstMACMask))
+ goto err_exit;
+
+ virBufferVSprintf(buf,
+ "/%s",
+ macaddr);
+ }
+ }
+
+ return 0;
+
+ err_exit:
+ virBufferFreeAndReset(buf);
+
+ return 1;
+}
+
+
+/************************ iptables support ************************/
+
+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);
+ virBufferVSprintf(buf, templ, cmd, position);
+ virBufferVSprintf(buf, CMD_SEPARATOR "%s",
+ CMD_STOPONERR(stopOnError));
+}
+
+
+static int
+iptablesHandleSrcMacAddr(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virBufferPtr buf,
+ virNWFilterHashTablePtr vars,
+ nwItemDescPtr srcMacAddr,
+ int directionIn ATTRIBUTE_UNUSED)
+{
+ char macaddr[VIR_MAC_STRING_BUFLEN];
+
+ if (HAS_ENTRY_ITEM(srcMacAddr)) {
+ if (printDataType(conn,
+ vars,
+ macaddr, sizeof(macaddr),
+ srcMacAddr))
+ goto err_exit;
+
+ virBufferVSprintf(buf,
+ " -m mac %s --mac-source %s",
+ ENTRY_GET_NEG_SIGN(srcMacAddr),
+ macaddr);
+ }
+
+ return 0;
+
+err_exit:
+ virBufferFreeAndReset(buf);
+
+ return 1;
+}
+
+
+static int
+iptablesHandleIpHdr(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virBufferPtr buf,
+ virNWFilterHashTablePtr vars,
+ ipHdrDataDefPtr ipHdr,
+ int directionIn)
+{
+ char ipaddr[INET_ADDRSTRLEN],
+ number[20];
+ const char *src = "--source";
+ const char *dst = "--destination";
+ const char *srcrange = "--src-range";
+ const char *dstrange = "--dst-range";
+ if (directionIn) {
+ src = "--destination";
+ dst = "--source";
+ srcrange = "--dst-range";
+ dstrange = "--src-range";
+ }
+
+ if (HAS_ENTRY_ITEM(&ipHdr->dataSrcIPAddr)) {
+
+ if (printDataType(conn,
+ vars,
+ ipaddr, sizeof(ipaddr),
+ &ipHdr->dataSrcIPAddr))
+ goto err_exit;
+
+ virBufferVSprintf(buf,
+ " %s %s %s",
+ ENTRY_GET_NEG_SIGN(&ipHdr->dataSrcIPAddr),
+ src,
+ ipaddr);
+
+ if (HAS_ENTRY_ITEM(&ipHdr->dataSrcIPMask)) {
+
+ if (printDataType(conn,
+ vars,
+ number, sizeof(number),
+ &ipHdr->dataSrcIPMask))
+ goto err_exit;
+
+ virBufferVSprintf(buf,
+ "/%s",
+ number);
+ }
+ } else if (HAS_ENTRY_ITEM(&ipHdr->dataSrcIPFrom)) {
+
+ if (printDataType(conn,
+ vars,
+ ipaddr, sizeof(ipaddr),
+ &ipHdr->dataSrcIPFrom))
+ goto err_exit;
+
+ virBufferVSprintf(buf,
+ " -m iprange %s %s %s",
+ ENTRY_GET_NEG_SIGN(&ipHdr->dataSrcIPFrom),
+ srcrange,
+ ipaddr);
+
+ if (HAS_ENTRY_ITEM(&ipHdr->dataSrcIPTo)) {
+
+ if (printDataType(conn,
+ vars,
+ ipaddr, sizeof(ipaddr),
+ &ipHdr->dataSrcIPTo))
+ goto err_exit;
+
+ virBufferVSprintf(buf,
+ "-%s",
+ ipaddr);
+ }
+ }
+
+ if (HAS_ENTRY_ITEM(&ipHdr->dataDstIPAddr)) {
+
+ if (printDataType(conn,
+ vars,
+ ipaddr, sizeof(ipaddr),
+ &ipHdr->dataDstIPAddr))
+ goto err_exit;
+
+ virBufferVSprintf(buf,
+ " %s %s %s",
+ ENTRY_GET_NEG_SIGN(&ipHdr->dataDstIPAddr),
+ dst,
+ ipaddr);
+
+ if (HAS_ENTRY_ITEM(&ipHdr->dataDstIPMask)) {
+
+ if (printDataType(conn,
+ vars,
+ number, sizeof(number),
+ &ipHdr->dataDstIPMask))
+ goto err_exit;
+
+ virBufferVSprintf(buf,
+ "/%s",
+ number);
+
+ }
+ } else if (HAS_ENTRY_ITEM(&ipHdr->dataDstIPFrom)) {
+
+ if (printDataType(conn,
+ vars,
+ ipaddr, sizeof(ipaddr),
+ &ipHdr->dataDstIPFrom))
+ goto err_exit;
+
+ virBufferVSprintf(buf,
+ " -m iprange %s %s %s",
+ ENTRY_GET_NEG_SIGN(&ipHdr->dataDstIPFrom),
+ dstrange,
+ ipaddr);
+
+ if (HAS_ENTRY_ITEM(&ipHdr->dataDstIPTo)) {
+
+ if (printDataType(conn,
+ vars,
+ ipaddr, sizeof(ipaddr),
+ &ipHdr->dataDstIPTo))
+ goto err_exit;
- VIR_FREE(inst->commandTemplate);
- VIR_FREE(inst);
-}
+ virBufferVSprintf(buf,
+ "-%s",
+ ipaddr);
+ }
+ }
+ if (HAS_ENTRY_ITEM(&ipHdr->dataDSCP)) {
-static int
-ebiptablesAddRuleInst(virConnectPtr conn,
- virNWFilterRuleInstPtr res,
- char *commandTemplate,
- enum virNWFilterChainSuffixType neededChain,
- char chainprefix,
- unsigned int priority)
-{
- ebiptablesRuleInstPtr inst;
+ if (printDataType(conn,
+ vars,
+ number, sizeof(number),
+ &ipHdr->dataDSCP))
+ goto err_exit;
- if (VIR_ALLOC(inst) < 0) {
- virReportOOMError();
- return 1;
+ virBufferVSprintf(buf,
+ " -m dscp %s --dscp %s",
+ ENTRY_GET_NEG_SIGN(&ipHdr->dataDSCP),
+ number);
}
- inst->commandTemplate = commandTemplate;
- inst->neededProtocolChain = neededChain;
- inst->chainprefix = chainprefix;
- inst->priority = priority;
+ return 0;
- return virNWFilterRuleInstAddData(conn, res, inst);
+err_exit:
+ virBufferFreeAndReset(buf);
+
+ return 1;
}
static int
-ebtablesHandleEthHdr(virConnectPtr conn,
- virBufferPtr buf,
- virNWFilterHashTablePtr vars,
- ethHdrDataDefPtr ethHdr)
-{
- char macaddr[VIR_MAC_STRING_BUFLEN];
+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(ðHdr->dataSrcMACAddr)) {
+ if (HAS_ENTRY_ITEM(&portData->dataSrcPortStart)) {
if (printDataType(conn,
vars,
- macaddr, sizeof(macaddr),
- ðHdr->dataSrcMACAddr))
+ portstr, sizeof(portstr),
+ &portData->dataSrcPortStart))
goto err_exit;
virBufferVSprintf(buf,
- " -s %s %s",
- ENTRY_GET_NEG_SIGN(ðHdr->dataSrcMACAddr),
- macaddr);
+ " %s %s %s",
+ ENTRY_GET_NEG_SIGN(&portData->dataSrcPortStart),
+ sport,
+ portstr);
- if (HAS_ENTRY_ITEM(ðHdr->dataSrcMACMask)) {
+ if (HAS_ENTRY_ITEM(&portData->dataSrcPortEnd)) {
if (printDataType(conn,
vars,
- macaddr, sizeof(macaddr),
- ðHdr->dataSrcMACMask))
+ portstr, sizeof(portstr),
+ &portData->dataSrcPortEnd))
goto err_exit;
- virBufferVSprintf(buf,
- "/%s",
- macaddr);
+ virBufferVSprintf(buf,
+ ":%s",
+ portstr);
}
}
- if (HAS_ENTRY_ITEM(ðHdr->dataDstMACAddr)) {
+ if (HAS_ENTRY_ITEM(&portData->dataDstPortStart)) {
if (printDataType(conn,
vars,
- macaddr, sizeof(macaddr),
- ðHdr->dataDstMACAddr))
+ portstr, sizeof(portstr),
+ &portData->dataDstPortStart))
goto err_exit;
virBufferVSprintf(buf,
- " -d %s %s",
- ENTRY_GET_NEG_SIGN(ðHdr->dataDstMACAddr),
- macaddr);
+ " %s %s %s",
+ ENTRY_GET_NEG_SIGN(&portData->dataDstPortStart),
+ dport,
+ portstr);
- if (HAS_ENTRY_ITEM(ðHdr->dataDstMACMask)) {
+ if (HAS_ENTRY_ITEM(&portData->dataDstPortEnd)) {
if (printDataType(conn,
vars,
- macaddr, sizeof(macaddr),
- ðHdr->dataDstMACMask))
+ portstr, sizeof(portstr),
+ &portData->dataDstPortEnd))
goto err_exit;
- virBufferVSprintf(buf,
- "/%s",
- macaddr);
+ virBufferVSprintf(buf,
+ ":%s",
+ portstr);
}
}
return 0;
- err_exit:
- virBufferFreeAndReset(buf);
-
+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];
+ char number[20];
+ 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 (iptablesHandleSrcMacAddr(conn,
+ &buf,
+ vars,
+ &rule->p.tcpHdrFilter.dataSrcMACAddr,
+ directionIn))
+ goto err_exit;
+
+ 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;
+
+ if (HAS_ENTRY_ITEM(&rule->p.tcpHdrFilter.dataTCPOption)) {
+ if (printDataType(conn,
+ vars,
+ number, sizeof(number),
+ &rule->p.tcpHdrFilter.dataTCPOption))
+ goto err_exit;
+
+ virBufferVSprintf(&buf,
+ " %s --tcp-option %s",
+
ENTRY_GET_NEG_SIGN(&rule->p.tcpHdrFilter.dataTCPOption),
+ number);
+ }
+
+ break;
+
+ case VIR_NWFILTER_RULE_PROTOCOL_UDP:
+ virBufferVSprintf(&buf,
+ CMD_DEF_PRE IPTABLES_CMD " -%%c %s %%s",
+ chain);
+
+ virBufferAddLit(&buf, " -p udp");
+
+ if (iptablesHandleSrcMacAddr(conn,
+ &buf,
+ vars,
+ &rule->p.udpHdrFilter.dataSrcMACAddr,
+ directionIn))
+ goto err_exit;
+
+ 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_SCTP:
+ virBufferVSprintf(&buf,
+ CMD_DEF_PRE IPTABLES_CMD " -%%c %s %%s",
+ chain);
+
+ virBufferAddLit(&buf, " -p sctp");
+
+ if (iptablesHandleSrcMacAddr(conn,
+ &buf,
+ vars,
+ &rule->p.sctpHdrFilter.dataSrcMACAddr,
+ directionIn))
+ goto err_exit;
+
+ 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 (iptablesHandleSrcMacAddr(conn,
+ &buf,
+ vars,
+ &rule->p.icmpHdrFilter.dataSrcMACAddr,
+ directionIn))
+ goto err_exit;
+
+ if (iptablesHandleIpHdr(conn,
+ &buf,
+ vars,
+ &rule->p.icmpHdrFilter.ipHdr,
+ directionIn))
+ goto err_exit;
+
+ if (HAS_ENTRY_ITEM(&rule->p.icmpHdrFilter.dataICMPType)) {
+ if (printDataType(conn,
+ vars,
+ number, sizeof(number),
+ &rule->p.icmpHdrFilter.dataICMPType))
+ goto err_exit;
+
+ virBufferVSprintf(&buf,
+ " %s --icmp-type %s",
+ ENTRY_GET_NEG_SIGN(&rule->p.icmpHdrFilter.dataICMPType),
+ number);
+
+ if (HAS_ENTRY_ITEM(&rule->p.icmpHdrFilter.dataICMPCode)) {
+ if (printDataType(conn,
+ vars,
+ number, sizeof(number),
+ &rule->p.icmpHdrFilter.dataICMPCode))
+ goto err_exit;
+
+ virBufferVSprintf(&buf,
+ "/%s",
+ number);
+ }
+ }
+ break;
+
+ case VIR_NWFILTER_RULE_PROTOCOL_ALL:
+ virBufferVSprintf(&buf,
+ CMD_DEF_PRE IPTABLES_CMD " -%%c %s %%s",
+ chain);
+
+ virBufferAddLit(&buf, " -p all");
+
+ if (iptablesHandleSrcMacAddr(conn,
+ &buf,
+ vars,
+ &rule->p.allHdrFilter.dataSrcMACAddr,
+ directionIn))
+ goto err_exit;
+
+ 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;
+}
+
+
+
+
+/*
* ebtablesCreateRuleInstance:
* @conn : Pointer to a virConnect object
* @chainPrefix : The prefix to put in front of the name of the chain
@@ -741,6 +1745,9 @@ ebtablesCreateRuleInstance(virConnectPtr
CMD_DEF_PRE EBTABLES_CMD " -t %s -%%c %s %%s",
EBTABLES_DEFAULT_TABLE, chain);
break;
+
+ default:
+ return -1;
}
virBufferVSprintf(&buf,
@@ -759,7 +1766,8 @@ ebtablesCreateRuleInstance(virConnectPtr
virBufferContentAndReset(&buf),
nwfilter->chainsuffix,
chainPrefix,
- rule->priority);
+ rule->priority,
+ RT_EBTABLES);
err_exit:
virBufferFreeAndReset(&buf);
@@ -785,7 +1793,7 @@ err_exit:
*/
static int
ebiptablesCreateRuleInstance(virConnectPtr conn,
- enum virDomainNetType nettype ATTRIBUTE_UNUSED,
+ enum virDomainNetType nettype,
virNWFilterDefPtr nwfilter,
virNWFilterRuleDefPtr rule,
const char *ifname,
@@ -825,6 +1833,33 @@ ebiptablesCreateRuleInstance(virConnectP
res);
}
break;
+
+ case VIR_NWFILTER_RULE_PROTOCOL_TCP:
+ case VIR_NWFILTER_RULE_PROTOCOL_UDP:
+ case VIR_NWFILTER_RULE_PROTOCOL_SCTP:
+ 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;
@@ -1352,16 +2387,19 @@ ebiptablesApplyNewRules(virConnectPtr co
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]->ruleType == RT_EBTABLES) {
+ 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);
@@ -1369,6 +2407,7 @@ ebiptablesApplyNewRules(virConnectPtr co
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);
@@ -1395,15 +2434,53 @@ ebiptablesApplyNewRules(virConnectPtr co
goto tear_down_tmpebchains;
for (i = 0; i < nruleInstances; i++)
- ebiptablesInstCommand(conn, &buf,
- inst[i]->commandTemplate,
- 'A', -1, 1);
+ switch (inst[i]->ruleType) {
+ case RT_EBTABLES:
+ ebiptablesInstCommand(conn, &buf,
+ inst[i]->commandTemplate,
+ 'A', -1, 1);
+ break;
+ case RT_IPTABLES:
+ haveIptables = 1;
+ break;
+ }
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]->ruleType == RT_IPTABLES)
+ 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)
@@ -1420,6 +2497,12 @@ tear_down_ebsubchains_and_unlink:
ebtablesUnlinkTmpRootChain(conn, &buf, 1, ifname);
ebtablesUnlinkTmpRootChain(conn, &buf, 0, ifname);
+tear_down_tmpiptchains:
+ if (haveIptables) {
+ iptablesUnlinkTmpRootChains(conn, &buf, ifname);
+ iptablesRemoveTmpRootChains(conn, &buf, ifname);
+ }
+
tear_down_tmpebchains:
ebtablesRemoveTmpSubChains(conn, &buf, ifname);
ebtablesRemoveTmpRootChain(conn, &buf, 1, ifname);
@@ -1442,6 +2525,9 @@ ebiptablesTearNewRules(virConnectPtr con
int cli_status;
virBuffer buf = VIR_BUFFER_INITIALIZER;
+ iptablesUnlinkTmpRootChains(conn, &buf, ifname);
+ iptablesRemoveTmpRootChains(conn, &buf, ifname);
+
ebtablesUnlinkTmpRootChain(conn, &buf, 1, ifname);
ebtablesUnlinkTmpRootChain(conn, &buf, 0, ifname);
@@ -1462,6 +2548,13 @@ ebiptablesTearOldRules(virConnectPtr con
int cli_status;
virBuffer buf = VIR_BUFFER_INITIALIZER;
+ // switch to new iptables user defined chains
+ iptablesUnlinkRootChains(conn, &buf, ifname);
+ iptablesRemoveRootChains(conn, &buf, ifname);
+
+ iptablesRenameTmpRootChains(conn, &buf, ifname);
+ ebiptablesExecCLI(conn, &buf, &cli_status);
+
ebtablesUnlinkRootChain(conn, &buf, 1, ifname);
ebtablesUnlinkRootChain(conn, &buf, 0, ifname);
@@ -1541,6 +2634,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/conf/nwfilter_conf.h
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_conf.h
+++ libvirt-acl/src/conf/nwfilter_conf.h
@@ -150,6 +150,10 @@ struct _ipHdrDataDef {
nwItemDesc dataDstIPAddr;
nwItemDesc dataDstIPMask;
nwItemDesc dataProtocolID;
+ nwItemDesc dataSrcIPFrom;
+ nwItemDesc dataSrcIPTo;
+ nwItemDesc dataDstIPFrom;
+ nwItemDesc dataDstIPTo;
nwItemDesc dataDSCP;
};
@@ -182,6 +186,61 @@ struct _ipv6HdrFilterDef {
};
+typedef struct _icmpHdrFilterDef icmpHdrFilterDef;
+typedef icmpHdrFilterDef *icmpHdrFilterDefPtr;
+struct _icmpHdrFilterDef {
+ nwItemDesc dataSrcMACAddr;
+ ipHdrDataDef ipHdr;
+ nwItemDesc dataICMPType;
+ nwItemDesc dataICMPCode;
+ nwItemDesc dataStateFlags;
+};
+
+
+typedef struct _allHdrFilterDef allHdrFilterDef;
+typedef allHdrFilterDef *allHdrFilterDefPtr;
+struct _allHdrFilterDef {
+ nwItemDesc dataSrcMACAddr;
+ ipHdrDataDef ipHdr;
+};
+
+
+typedef struct _igmpHdrFilterDef igmpHdrFilterDef;
+typedef igmpHdrFilterDef *igmpHdrFilterDefPtr;
+struct _igmpHdrFilterDef {
+ nwItemDesc dataSrcMACAddr;
+ ipHdrDataDef ipHdr;
+};
+
+
+typedef struct _tcpHdrFilterDef tcpHdrFilterDef;
+typedef tcpHdrFilterDef *tcpHdrFilterDefPtr;
+struct _tcpHdrFilterDef {
+ nwItemDesc dataSrcMACAddr;
+ ipHdrDataDef ipHdr;
+ portDataDef portData;
+ nwItemDesc dataTCPOption;
+};
+
+
+typedef struct _udpHdrFilterDef udpHdrFilterDef;
+typedef udpHdrFilterDef *udpHdrFilterDefPtr;
+struct _udpHdrFilterDef {
+ nwItemDesc dataSrcMACAddr;
+ ipHdrDataDef ipHdr;
+ portDataDef portData;
+};
+
+
+typedef struct _sctpHdrFilterDef sctpHdrFilterDef;
+typedef sctpHdrFilterDef *sctpHdrFilterDefPtr;
+struct _sctpHdrFilterDef {
+ nwItemDesc dataSrcMACAddr;
+ ipHdrDataDef ipHdr;
+ portDataDef portData;
+};
+
+
enum virNWFilterRuleActionType {
VIR_NWFILTER_RULE_ACTION_DROP = 0,
VIR_NWFILTER_RULE_ACTION_ACCEPT,
@@ -210,6 +269,14 @@ enum virNWFilterRuleProtocolType {
VIR_NWFILTER_RULE_PROTOCOL_ARP,
VIR_NWFILTER_RULE_PROTOCOL_IP,
VIR_NWFILTER_RULE_PROTOCOL_IPV6,
+ VIR_NWFILTER_RULE_PROTOCOL_TCP,
+ VIR_NWFILTER_RULE_PROTOCOL_ICMP,
+ VIR_NWFILTER_RULE_PROTOCOL_IGMP,
+ VIR_NWFILTER_RULE_PROTOCOL_UDP,
+ VIR_NWFILTER_RULE_PROTOCOL_SCTP,
+ VIR_NWFILTER_RULE_PROTOCOL_ALL,
+
+ VIR_NWFILTER_RULE_PROTOCOL_LAST
};
enum virNWFilterEbtablesTableType {
@@ -236,6 +303,12 @@ struct _virNWFilterRuleDef {
arpHdrFilterDef arpHdrFilter;
ipHdrFilterDef ipHdrFilter;
ipv6HdrFilterDef ipv6HdrFilter;
+ 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
@@ -76,6 +76,19 @@ VIR_ENUM_IMPL(virNWFilterChainSuffix, VI
"ipv4",
"ipv6");
+VIR_ENUM_IMPL(virNWFilterRuleProtocol, VIR_NWFILTER_RULE_PROTOCOL_LAST,
+ "none",
+ "mac",
+ "arp",
+ "ip",
+ "ipv6",
+ "tcp",
+ "icmp",
+ "igmp",
+ "udp",
+ "sctp",
+ "all");
+
/*
* a map entry for a simple static int-to-string map
@@ -117,6 +130,10 @@ static const char srcipaddr_str[] = "
static const char srcipmask_str[] = "srcipmask";
static const char dstipaddr_str[] = "dstipaddr";
static const char dstipmask_str[] = "dstipmask";
+static const char srcipfrom_str[] = "srcipfrom";
+static const char srcipto_str[] = "srcipto";
+static const char dstipfrom_str[] = "dstipfrom";
+static const char dstipto_str[] = "dstipto";
static const char srcportstart_str[] = "srcportstart";
static const char srcportend_str[] = "srcportend";
static const char dstportstart_str[] = "dstportstart";
@@ -135,6 +152,10 @@ static const char dscp_str[] = "
#define SRCIPMASK srcipmask_str
#define DSTIPADDR dstipaddr_str
#define DSTIPMASK dstipmask_str
+#define SRCIPFROM srcipfrom_str
+#define SRCIPTO srcipto_str
+#define DSTIPFROM dstipfrom_str
+#define DSTIPTO dstipto_str
#define SRCPORTSTART srcportstart_str
#define SRCPORTEND srcportend_str
#define DSTPORTSTART dstportstart_str
@@ -831,6 +852,149 @@ static const virXMLAttr2Struct ipv6Attri
};
+#define COMMON_L3_MAC_PROPS(STRUCT) \
+ {\
+ .name = SRCMACADDR,\
+ .datatype = DATATYPE_MACADDR,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.dataSrcMACAddr),\
+ }
+
+#define COMMON_IP_PROPS(STRUCT) \
+ COMMON_L3_MAC_PROPS(STRUCT),\
+ {\
+ .name = SRCIPADDR,\
+ .datatype = DATATYPE_IPADDR,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPAddr),\
+ },\
+ {\
+ .name = DSTIPADDR,\
+ .datatype = DATATYPE_IPADDR,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPAddr),\
+ },\
+ {\
+ .name = SRCIPMASK,\
+ .datatype = DATATYPE_IPMASK,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPMask),\
+ },\
+ {\
+ .name = DSTIPMASK,\
+ .datatype = DATATYPE_IPMASK,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPMask),\
+ },\
+ {\
+ .name = SRCIPFROM,\
+ .datatype = DATATYPE_IPADDR,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPFrom),\
+ },\
+ {\
+ .name = SRCIPTO,\
+ .datatype = DATATYPE_IPADDR,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPTo),\
+ },\
+ {\
+ .name = DSTIPFROM,\
+ .datatype = DATATYPE_IPADDR,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPFrom),\
+ },\
+ {\
+ .name = DSTIPTO,\
+ .datatype = DATATYPE_IPADDR,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPTo),\
+ },\
+ {\
+ .name = DSCP,\
+ .datatype = DATATYPE_UINT8,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDSCP),\
+ .validator = dscpValidator,\
+ }
+
+#define COMMON_PORT_PROPS(STRUCT) \
+ {\
+ .name = SRCPORTSTART,\
+ .datatype = DATATYPE_UINT16,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataSrcPortStart),\
+ },\
+ {\
+ .name = SRCPORTEND,\
+ .datatype = DATATYPE_UINT16,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataSrcPortEnd),\
+ },\
+ {\
+ .name = DSTPORTSTART,\
+ .datatype = DATATYPE_UINT16,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataDstPortStart),\
+ },\
+ {\
+ .name = DSTPORTEND,\
+ .datatype = DATATYPE_UINT16,\
+ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataDstPortEnd),\
+ }
+
+static const virXMLAttr2Struct tcpAttributes[] = {
+ COMMON_IP_PROPS(tcpHdrFilter),
+ COMMON_PORT_PROPS(tcpHdrFilter),
+ {
+ .name = "option",
+ .datatype = DATATYPE_UINT8,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.dataTCPOption),
+ },
+ {
+ .name = NULL,
+ }
+};
+
+static const virXMLAttr2Struct udpAttributes[] = {
+ COMMON_IP_PROPS(udpHdrFilter),
+ COMMON_PORT_PROPS(udpHdrFilter),
+ {
+ .name = NULL,
+ }
+};
+
+
+static const virXMLAttr2Struct sctpAttributes[] = {
+ COMMON_IP_PROPS(sctpHdrFilter),
+ COMMON_PORT_PROPS(sctpHdrFilter),
+ {
+ .name = NULL,
+ }
+};
+
+
+static const virXMLAttr2Struct icmpAttributes[] = {
+ COMMON_IP_PROPS(icmpHdrFilter),
+ {
+ .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[] = {
+ COMMON_IP_PROPS(allHdrFilter),
+ {
+ .name = NULL,
+ }
+};
+
+
+static const virXMLAttr2Struct igmpAttributes[] = {
+ COMMON_IP_PROPS(igmpHdrFilter),
+ {
+ .name = NULL,
+ }
+};
+
+
typedef struct _virAttributes virAttributes;
struct _virAttributes {
const char *id;
@@ -857,6 +1021,30 @@ static const virAttributes virAttr[] = {
.att = ipv6Attributes,
.prtclType = VIR_NWFILTER_RULE_PROTOCOL_IPV6,
}, {
+ .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_SCTP,
+ }, {
+ .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,
}
};
@@ -1274,8 +1462,96 @@ 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.dataSrcIPMask,
+ rule->p.tcpHdrFilter.ipHdr.dataSrcIPAddr);
+ COPY_NEG_SIGN(rule->p.tcpHdrFilter.ipHdr.dataDstIPMask,
+ rule->p.tcpHdrFilter.ipHdr.dataDstIPAddr);
+ COPY_NEG_SIGN(rule->p.tcpHdrFilter.ipHdr.dataSrcIPTo,
+ rule->p.tcpHdrFilter.ipHdr.dataSrcIPFrom);
+ COPY_NEG_SIGN(rule->p.tcpHdrFilter.ipHdr.dataDstIPTo,
+ rule->p.tcpHdrFilter.ipHdr.dataDstIPFrom);
+ 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.dataSrcIPMask,
+ rule->p.udpHdrFilter.ipHdr.dataSrcIPAddr);
+ COPY_NEG_SIGN(rule->p.udpHdrFilter.ipHdr.dataDstIPMask,
+ rule->p.udpHdrFilter.ipHdr.dataDstIPAddr);
+ COPY_NEG_SIGN(rule->p.udpHdrFilter.ipHdr.dataSrcIPTo,
+ rule->p.udpHdrFilter.ipHdr.dataSrcIPFrom);
+ COPY_NEG_SIGN(rule->p.udpHdrFilter.ipHdr.dataDstIPTo,
+ rule->p.udpHdrFilter.ipHdr.dataDstIPFrom);
+ 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_SCTP:
+ COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataSrcIPMask,
+ rule->p.sctpHdrFilter.ipHdr.dataSrcIPAddr);
+ COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataDstIPMask,
+ rule->p.sctpHdrFilter.ipHdr.dataDstIPAddr);
+ COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataSrcIPTo,
+ rule->p.sctpHdrFilter.ipHdr.dataSrcIPFrom);
+ COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataDstIPTo,
+ rule->p.sctpHdrFilter.ipHdr.dataDstIPFrom);
+ 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.dataSrcIPMask,
+ rule->p.icmpHdrFilter.ipHdr.dataSrcIPAddr);
+ COPY_NEG_SIGN(rule->p.icmpHdrFilter.ipHdr.dataDstIPMask,
+ rule->p.icmpHdrFilter.ipHdr.dataDstIPAddr);
+ COPY_NEG_SIGN(rule->p.icmpHdrFilter.ipHdr.dataSrcIPTo,
+ rule->p.icmpHdrFilter.ipHdr.dataSrcIPFrom);
+ COPY_NEG_SIGN(rule->p.icmpHdrFilter.ipHdr.dataDstIPTo,
+ rule->p.icmpHdrFilter.ipHdr.dataDstIPFrom);
+ COPY_NEG_SIGN(rule->p.icmpHdrFilter.dataICMPCode,
+ rule->p.icmpHdrFilter.dataICMPType);
+ break;
+
+ case VIR_NWFILTER_RULE_PROTOCOL_ALL:
+ COPY_NEG_SIGN(rule->p.allHdrFilter.ipHdr.dataSrcIPMask,
+ rule->p.allHdrFilter.ipHdr.dataSrcIPAddr);
+ COPY_NEG_SIGN(rule->p.allHdrFilter.ipHdr.dataDstIPMask,
+ rule->p.allHdrFilter.ipHdr.dataDstIPAddr);
+ COPY_NEG_SIGN(rule->p.allHdrFilter.ipHdr.dataSrcIPTo,
+ rule->p.allHdrFilter.ipHdr.dataSrcIPFrom);
+ COPY_NEG_SIGN(rule->p.allHdrFilter.ipHdr.dataDstIPTo,
+ rule->p.allHdrFilter.ipHdr.dataDstIPFrom);
+ break;
+
+ case VIR_NWFILTER_RULE_PROTOCOL_IGMP:
+ COPY_NEG_SIGN(rule->p.igmpHdrFilter.ipHdr.dataSrcIPMask,
+ rule->p.igmpHdrFilter.ipHdr.dataSrcIPAddr);
+ COPY_NEG_SIGN(rule->p.igmpHdrFilter.ipHdr.dataDstIPMask,
+ rule->p.igmpHdrFilter.ipHdr.dataDstIPAddr);
+ COPY_NEG_SIGN(rule->p.igmpHdrFilter.ipHdr.dataSrcIPTo,
+ rule->p.igmpHdrFilter.ipHdr.dataSrcIPFrom);
+ COPY_NEG_SIGN(rule->p.igmpHdrFilter.ipHdr.dataDstIPTo,
+ rule->p.igmpHdrFilter.ipHdr.dataDstIPFrom);
+ break;
+
+ 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
@@ -448,6 +448,7 @@ virNWFilterPoolObjListFree;
virNWFilterDefFormat;
virNWFilterChainSuffixTypeToString;
virNWFilterRuleActionTypeToString;
+virNWFilterRuleProtocolTypeToString;
virNWFilterJumpTargetTypeToString;
virNWFilterRegisterCallbackDriver;
virNWFilterTestUnassignDef;
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
@@ -25,6 +25,12 @@
#define MAX_CHAINNAME_LENGTH 32 /* see linux/netfilter_bridge/ebtables.h */
+enum RuleType {
+ RT_EBTABLES,
+ RT_IPTABLES,
+/* RT_IP6TABLES, for future use */
+};
+
typedef struct _ebiptablesRuleInst ebiptablesRuleInst;
typedef ebiptablesRuleInst *ebiptablesRuleInstPtr;
struct _ebiptablesRuleInst {
@@ -32,6 +38,7 @@ struct _ebiptablesRuleInst {
enum virNWFilterChainSuffixType neededProtocolChain;
char chainprefix; // I for incoming, O for outgoing
unsigned int priority;
+ enum RuleType ruleType;
};
extern virNWFilterTechDriver ebiptables_driver;
Index: libvirt-acl/configure.ac
===================================================================
--- libvirt-acl.orig/configure.ac
+++ libvirt-acl/configure.ac
@@ -303,6 +303,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