summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Berger <stefanb@linux.vnet.ibm.com>2015-01-07 11:41:49 -0500
committerStefan Berger <stefanb@linux.vnet.ibm.com>2015-01-07 11:41:49 -0500
commit3a3b3691d145418dc6616e7ce8a5ca8ba857bc5b (patch)
treee95eeb5403baa3053adc2bb1f292178717bedccd
parentb073179085cb470e13e8e87e2a92cf2356c680eb (diff)
downloadlibvirt-3a3b3691d145418dc6616e7ce8a5ca8ba857bc5b.tar.gz
nwfilter: Add support for icmpv6 filtering
Make use of the ebtables functionality to be able to filter certain parameters of icmpv6 packets. Extend the XML parser for icmpv6 types, type ranges, codes, and code ranges. Extend the nwfilter documentation, schema, and test cases. Being able to filter icmpv6 types and codes helps extending the DHCP snooper for IPv6 and filtering at least some parameters of IPv6's NDP (Neighbor Discovery Protocol) packets. However, the filtering will not be as good as the filtering of ARP packets since we cannot check on IP addresses in the payload of the NDP packets. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
-rw-r--r--docs/formatnwfilter.html.in20
-rw-r--r--docs/schemas/nwfilter.rng26
-rw-r--r--src/conf/nwfilter_conf.c26
-rw-r--r--src/conf/nwfilter_conf.h4
-rw-r--r--src/nwfilter/nwfilter_ebiptables_driver.c80
-rw-r--r--tests/nwfilterxml2firewalldata/ipv6-linux.args16
-rw-r--r--tests/nwfilterxml2firewalldata/ipv6.xml38
-rw-r--r--tests/nwfilterxml2xmlin/ipv6-test.xml38
-rw-r--r--tests/nwfilterxml2xmlout/ipv6-test.xml12
9 files changed, 260 insertions, 0 deletions
diff --git a/docs/formatnwfilter.html.in b/docs/formatnwfilter.html.in
index 073b852abc..4a60e2ea9a 100644
--- a/docs/formatnwfilter.html.in
+++ b/docs/formatnwfilter.html.in
@@ -1197,6 +1197,26 @@
<td>End of range of valid destination ports; requires <code>protocol</code></td>
</tr>
<tr>
+ <td>type<span class="since">(Since 1.2.12)</span></td>
+ <td>UINT8</td>
+ <td>ICMPv6 type; requires <code>protocol</code> to be set to <code>icmpv6</code></td>
+ </tr>
+ <tr>
+ <td>typeend<span class="since">(Since 1.2.12)</span></td>
+ <td>UINT8</td>
+ <td>ICMPv6 type end of range; requires <code>protocol</code> to be set to <code>icmpv6</code></td>
+ </tr>
+ <tr>
+ <td>code<span class="since">(Since 1.2.12)</span></td>
+ <td>UINT8</td>
+ <td>ICMPv6 code; requires <code>protocol</code> to be set to <code>icmpv6</code></td>
+ </tr>
+ <tr>
+ <td>code<span class="since">(Since 1.2.12)</span></td>
+ <td>UINT8</td>
+ <td>ICMPv6 code end of range; requires <code>protocol</code> to be set to <code>icmpv6</code></td>
+ </tr>
+ <tr>
<td>comment <span class="since">(Since 0.8.5)</span></td>
<td>STRING</td>
<td>text with max. 256 characters</td>
diff --git a/docs/schemas/nwfilter.rng b/docs/schemas/nwfilter.rng
index 2b54fd54a0..9df39c0a64 100644
--- a/docs/schemas/nwfilter.rng
+++ b/docs/schemas/nwfilter.rng
@@ -90,6 +90,7 @@
<ref name="common-ipv6-attributes-p1"/>
<ref name="common-port-attributes"/>
<ref name="ip-attributes"/>
+ <ref name="icmp-attribute-ranges"/>
<ref name="comment-attribute"/>
</element>
</zeroOrMore>
@@ -588,6 +589,31 @@
</interleave>
</define>
+ <define name="icmp-attribute-ranges">
+ <interleave>
+ <optional>
+ <attribute name="type">
+ <ref name="uint8range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="typeend">
+ <ref name="uint8range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="code">
+ <ref name="uint8range"/>
+ </attribute>
+ </optional>
+ <optional>
+ <attribute name="codeend">
+ <ref name="uint8range"/>
+ </attribute>
+ </optional>
+ </interleave>
+ </define>
+
<define name="mac-attributes">
<interleave>
<optional>
diff --git a/src/conf/nwfilter_conf.c b/src/conf/nwfilter_conf.c
index 317792eb50..aed82ad288 100644
--- a/src/conf/nwfilter_conf.c
+++ b/src/conf/nwfilter_conf.c
@@ -1445,6 +1445,26 @@ static const virXMLAttr2Struct ipv6Attributes[] = {
.datatype = DATATYPE_UINT16 | DATATYPE_UINT16_HEX,
.dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.portData.dataDstPortEnd),
},
+ {
+ .name = "type",
+ .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.dataICMPTypeStart),
+ },
+ {
+ .name = "typeend",
+ .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.dataICMPTypeEnd),
+ },
+ {
+ .name = "code",
+ .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.dataICMPCodeStart),
+ },
+ {
+ .name = "codeend",
+ .datatype = DATATYPE_UINT8 | DATATYPE_UINT8_HEX,
+ .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.dataICMPCodeEnd),
+ },
COMMENT_PROP_IPHDR(ipv6HdrFilter),
{
.name = NULL,
@@ -2219,6 +2239,12 @@ virNWFilterRuleDefFixup(virNWFilterRuleDefPtr rule)
rule->p.ipv6HdrFilter.ipHdr.dataSrcIPAddr);
COPY_NEG_SIGN(rule->p.ipv6HdrFilter.ipHdr.dataDstIPMask,
rule->p.ipv6HdrFilter.ipHdr.dataDstIPAddr);
+ COPY_NEG_SIGN(rule->p.ipv6HdrFilter.dataICMPTypeEnd,
+ rule->p.ipv6HdrFilter.dataICMPTypeStart);
+ COPY_NEG_SIGN(rule->p.ipv6HdrFilter.dataICMPCodeStart,
+ rule->p.ipv6HdrFilter.dataICMPTypeStart);
+ COPY_NEG_SIGN(rule->p.ipv6HdrFilter.dataICMPCodeEnd,
+ rule->p.ipv6HdrFilter.dataICMPTypeStart);
virNWFilterRuleDefFixupIPSet(&rule->p.ipv6HdrFilter.ipHdr);
break;
diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
index f81df60dc3..6e68ecc857 100644
--- a/src/conf/nwfilter_conf.h
+++ b/src/conf/nwfilter_conf.h
@@ -265,6 +265,10 @@ struct _ipv6HdrFilterDef {
ethHdrDataDef ethHdr;
ipHdrDataDef ipHdr;
portDataDef portData;
+ nwItemDesc dataICMPTypeStart;
+ nwItemDesc dataICMPTypeEnd;
+ nwItemDesc dataICMPCodeStart;
+ nwItemDesc dataICMPCodeEnd;
};
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c
index 377b59bcaa..423d069e1b 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -1826,6 +1826,7 @@ ebtablesCreateRuleInstance(virFirewallPtr fw,
bool hasMask = false;
virFirewallRulePtr fwrule;
int ret = -1;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
if (STREQ(chainSuffix,
virNWFilterChainSuffixTypeToString(
@@ -2342,6 +2343,83 @@ ebtablesCreateRuleInstance(virFirewallPtr fw,
virFirewallRuleAddArg(fw, fwrule, number);
}
}
+
+ if (HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.dataICMPTypeStart) ||
+ HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.dataICMPTypeEnd) ||
+ HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.dataICMPCodeStart) ||
+ HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.dataICMPCodeEnd)) {
+ bool lo = false;
+ char *r;
+
+ virFirewallRuleAddArg(fw, fwrule,
+ "--ip6-icmp-type");
+
+ if (HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.dataICMPTypeStart)) {
+ if (printDataType(vars,
+ number, sizeof(number),
+ &rule->p.ipv6HdrFilter.dataICMPTypeStart) < 0)
+ goto cleanup;
+ lo = true;
+ } else {
+ ignore_value(virStrcpyStatic(number, "0"));
+ }
+
+ virBufferStrcat(&buf, number, ":", NULL);
+
+ if (HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.dataICMPTypeEnd)) {
+ if (printDataType(vars,
+ numberalt, sizeof(numberalt),
+ &rule->p.ipv6HdrFilter.dataICMPTypeEnd) < 0)
+ goto cleanup;
+ } else {
+ if (lo)
+ ignore_value(virStrcpyStatic(numberalt, number));
+ else
+ ignore_value(virStrcpyStatic(numberalt, "255"));
+ }
+
+ virBufferStrcat(&buf, numberalt, "/", NULL);
+
+ lo = false;
+
+ if (HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.dataICMPCodeStart)) {
+ if (printDataType(vars,
+ number, sizeof(number),
+ &rule->p.ipv6HdrFilter.dataICMPCodeStart) < 0)
+ goto cleanup;
+ lo = true;
+ } else {
+ ignore_value(virStrcpyStatic(number, "0"));
+ }
+
+ virBufferStrcat(&buf, number, ":", NULL);
+
+ if (HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.dataICMPCodeEnd)) {
+ if (printDataType(vars,
+ numberalt, sizeof(numberalt),
+ &rule->p.ipv6HdrFilter.dataICMPCodeEnd) < 0)
+ goto cleanup;
+ } else {
+ if (lo)
+ ignore_value(virStrcpyStatic(numberalt, number));
+ else
+ ignore_value(virStrcpyStatic(numberalt, "255"));
+ }
+
+ virBufferStrcat(&buf, numberalt, NULL);
+
+ if (ENTRY_WANT_NEG_SIGN(&rule->p.ipv6HdrFilter.dataICMPTypeStart))
+ virFirewallRuleAddArg(fw, fwrule, "!");
+
+ if (virBufferCheckError(&buf) < 0)
+ goto cleanup;
+
+ r = virBufferContentAndReset(&buf);
+
+ virFirewallRuleAddArg(fw, fwrule, r);
+
+ VIR_FREE(r);
+ }
break;
case VIR_NWFILTER_RULE_PROTOCOL_NONE:
@@ -2376,6 +2454,8 @@ ebtablesCreateRuleInstance(virFirewallPtr fw,
ret = 0;
cleanup:
+ virBufferFreeAndReset(&buf);
+
return ret;
}
diff --git a/tests/nwfilterxml2firewalldata/ipv6-linux.args b/tests/nwfilterxml2firewalldata/ipv6-linux.args
index a42566ca70..735f663716 100644
--- a/tests/nwfilterxml2firewalldata/ipv6-linux.args
+++ b/tests/nwfilterxml2firewalldata/ipv6-linux.args
@@ -18,3 +18,19 @@ ebtables -t nat -A libvirt-J-vnet0 -p ipv6 --ip6-destination 1::2/128 \
--ip6-source a:b:c::/65 --ip6-protocol 18 -j ACCEPT
ebtables -t nat -A libvirt-P-vnet0 -p ipv6 --ip6-source 1::2/128 \
--ip6-destination a:b:c::/65 --ip6-protocol 18 -j ACCEPT
+ebtables -t nat -A libvirt-J-vnet0 -p ipv6 --ip6-destination 1::2/128 \
+--ip6-source a:b:c::/65 --ip6-protocol 58 --ip6-icmp-type 1:11/10:11 -j ACCEPT
+ebtables -t nat -A libvirt-P-vnet0 -p ipv6 --ip6-source 1::2/128 \
+--ip6-destination a:b:c::/65 --ip6-protocol 58 --ip6-icmp-type 1:11/10:11 -j ACCEPT
+ebtables -t nat -A libvirt-J-vnet0 -p ipv6 --ip6-destination 1::2/128 \
+--ip6-source a:b:c::/65 --ip6-protocol 58 --ip6-icmp-type 1:1/10:10 -j ACCEPT
+ebtables -t nat -A libvirt-P-vnet0 -p ipv6 --ip6-source 1::2/128 \
+--ip6-destination a:b:c::/65 --ip6-protocol 58 --ip6-icmp-type 1:1/10:10 -j ACCEPT
+ebtables -t nat -A libvirt-J-vnet0 -p ipv6 --ip6-destination 1::2/128 \
+--ip6-source a:b:c::/65 --ip6-protocol 58 --ip6-icmp-type 0:255/10:10 -j ACCEPT
+ebtables -t nat -A libvirt-P-vnet0 -p ipv6 --ip6-source 1::2/128 \
+--ip6-destination a:b:c::/65 --ip6-protocol 58 --ip6-icmp-type 0:255/10:10 -j ACCEPT
+ebtables -t nat -A libvirt-J-vnet0 -p ipv6 --ip6-destination 1::2/128 \
+--ip6-source a:b:c::/65 --ip6-protocol 58 --ip6-icmp-type 1:1/0:255 -j ACCEPT
+ebtables -t nat -A libvirt-P-vnet0 -p ipv6 --ip6-source 1::2/128 \
+--ip6-destination a:b:c::/65 --ip6-protocol 58 --ip6-icmp-type 1:1/0:255 -j ACCEPT
diff --git a/tests/nwfilterxml2firewalldata/ipv6.xml b/tests/nwfilterxml2firewalldata/ipv6.xml
index 9f67bea737..2400958030 100644
--- a/tests/nwfilterxml2firewalldata/ipv6.xml
+++ b/tests/nwfilterxml2firewalldata/ipv6.xml
@@ -40,4 +40,42 @@
/>
</rule>
+ <rule action='accept' direction='inout'>
+ <ipv6 srcipaddr='1::2' srcipmask='128'
+ dstipaddr='a:b:c::'
+ dstipmask='ffff:ffff:ffff:ffff:8000::'
+ protocol='icmpv6'
+ type='1' typeend='11'
+ code='10' codeend='11'
+ />
+ </rule>
+
+ <rule action='accept' direction='inout'>
+ <ipv6 srcipaddr='1::2' srcipmask='128'
+ dstipaddr='a:b:c::'
+ dstipmask='ffff:ffff:ffff:ffff:8000::'
+ protocol='icmpv6'
+ type='1'
+ code='10'
+ />
+ </rule>
+
+ <rule action='accept' direction='inout'>
+ <ipv6 srcipaddr='1::2' srcipmask='128'
+ dstipaddr='a:b:c::'
+ dstipmask='ffff:ffff:ffff:ffff:8000::'
+ protocol='icmpv6'
+ code='10'
+ />
+ </rule>
+
+ <rule action='accept' direction='inout'>
+ <ipv6 srcipaddr='1::2' srcipmask='128'
+ dstipaddr='a:b:c::'
+ dstipmask='ffff:ffff:ffff:ffff:8000::'
+ protocol='icmpv6'
+ type='1'
+ />
+ </rule>
+
</filter>
diff --git a/tests/nwfilterxml2xmlin/ipv6-test.xml b/tests/nwfilterxml2xmlin/ipv6-test.xml
index 556796fa01..2daa3b96dd 100644
--- a/tests/nwfilterxml2xmlin/ipv6-test.xml
+++ b/tests/nwfilterxml2xmlin/ipv6-test.xml
@@ -40,4 +40,42 @@
/>
</rule>
+ <rule action='accept' direction='inout'>
+ <ipv6 srcipaddr='1::2' srcipmask='128'
+ dstipaddr='a:b:c::'
+ dstipmask='ffff:ffff:ffff:ffff:8000::'
+ protocol='icmpv6'
+ type='1' typeend='11'
+ code='10' codeend='11'
+ />
+ </rule>
+
+ <rule action='accept' direction='inout'>
+ <ipv6 srcipaddr='1::2' srcipmask='128'
+ dstipaddr='a:b:c::'
+ dstipmask='ffff:ffff:ffff:ffff:8000::'
+ protocol='icmpv6'
+ type='1'
+ code='10'
+ />
+ </rule>
+
+ <rule action='accept' direction='inout'>
+ <ipv6 srcipaddr='1::2' srcipmask='128'
+ dstipaddr='a:b:c::'
+ dstipmask='ffff:ffff:ffff:ffff:8000::'
+ protocol='icmpv6'
+ code='10'
+ />
+ </rule>
+
+ <rule action='accept' direction='inout'>
+ <ipv6 srcipaddr='1::2' srcipmask='128'
+ dstipaddr='a:b:c::'
+ dstipmask='ffff:ffff:ffff:ffff:8000::'
+ protocol='icmpv6'
+ type='1'
+ />
+ </rule>
+
</filter>
diff --git a/tests/nwfilterxml2xmlout/ipv6-test.xml b/tests/nwfilterxml2xmlout/ipv6-test.xml
index fcc5c0da26..ce9dd06233 100644
--- a/tests/nwfilterxml2xmlout/ipv6-test.xml
+++ b/tests/nwfilterxml2xmlout/ipv6-test.xml
@@ -12,4 +12,16 @@
<rule action='accept' direction='inout' priority='500'>
<ipv6 srcipaddr='1::2' srcipmask='128' dstipaddr='a:b:c::' dstipmask='65' protocol='18'/>
</rule>
+ <rule action='accept' direction='inout'>
+ <ipv6 srcipaddr='1::2' srcipmask='128' dstipaddr='a:b:c::' dstipmask='65' protocol='icmpv6' type='1' typeend='11' code='10' codeend='11'/>
+ </rule>
+ <rule action='accept' direction='inout'>
+ <ipv6 srcipaddr='1::2' srcipmask='128' dstipaddr='a:b:c::' dstipmask='65' protocol='icmpv6' type='1' code='10'/>
+ </rule>
+ <rule action='accept' direction='inout'>
+ <ipv6 srcipaddr='1::2' srcipmask='128' dstipaddr='a:b:c::' dstipmask='65' protocol='icmpv6' code='10'/>
+ </rule>
+ <rule action='accept' direction='inout'>
+ <ipv6 srcipaddr='1::2' srcipmask='128' dstipaddr='a:b:c::' dstipmask='65' protocol='icmpv6' type='1'/>
+ </rule>
</filter>