[libvirt] [PATCH] nwfilter: enable filtering of gratuitous ARP packets

This patch enables filtering of gratuitous ARP packets using the following XML: <rule action='accept' direction='in' priority='425'> <arp gratuitous='true'/> </rule> Signed-off-by: Stefan Berger <stefanb@us.ibm.com> --- docs/formatnwfilter.html.in | 6 ++++++ docs/schemas/nwfilter.rng | 16 ++++++++++++++++ examples/xml/nwfilter/no-arp-spoofing.xml | 6 +++++- src/conf/nwfilter_conf.c | 23 +++++++++++++++++++++++ src/conf/nwfilter_conf.h | 5 ++++- src/nwfilter/nwfilter_ebiptables_driver.c | 7 +++++++ tests/nwfilterxml2xmlin/arp-test.xml | 4 ++++ tests/nwfilterxml2xmlout/arp-test.xml | 3 +++ 8 files changed, 68 insertions(+), 2 deletions(-) Index: libvirt-acl/src/conf/nwfilter_conf.c =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.c +++ libvirt-acl/src/conf/nwfilter_conf.c @@ -970,6 +970,10 @@ static const virXMLAttr2Struct arpAttrib .name = ARPDSTIPADDR, .datatype = DATATYPE_IPADDR, .dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataARPDstIPAddr), + }, { + .name = "gratuitous", + .datatype = DATATYPE_BOOLEAN, + .dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataGratuitousARP), }, COMMENT_PROP(arpHdrFilter), { @@ -1611,6 +1615,18 @@ virNWFilterRuleDetailsParse(xmlNodePtr n found = 1; break; + case DATATYPE_BOOLEAN: + if (STREQ(prop, "true") || + STREQ(prop, "1") || + STREQ(prop, "yes")) + item->u.boolean = true; + else + item->u.boolean = false; + + data.ui = item->u.boolean; + found = 1; + break; + case DATATYPE_LAST: default: break; @@ -2744,6 +2760,13 @@ virNWFilterRuleDefDetailsFormat(virBuffe virBufferEscapeString(buf, "%s", item->u.string); break; + case DATATYPE_BOOLEAN: + if (item->u.boolean == true) + virBufferAddLit(buf, "true"); + else + virBufferAddLit(buf, "false"); + break; + case DATATYPE_STRING: default: virBufferAsprintf(buf, Index: libvirt-acl/src/conf/nwfilter_conf.h =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.h +++ libvirt-acl/src/conf/nwfilter_conf.h @@ -97,8 +97,9 @@ enum attrDatatype { DATATYPE_IPV6ADDR = (1 << 9), DATATYPE_IPV6MASK = (1 << 10), DATATYPE_STRINGCOPY = (1 << 11), + DATATYPE_BOOLEAN = (1 << 12), - DATATYPE_LAST = (1 << 12), + DATATYPE_LAST = (1 << 13), }; @@ -118,6 +119,7 @@ struct _nwItemDesc { union { nwMACAddress macaddr; virSocketAddr ipaddr; + bool boolean; uint8_t u8; uint16_t u16; char protocolID[10]; @@ -160,6 +162,7 @@ struct _arpHdrFilterDef { nwItemDesc dataARPSrcIPAddr; nwItemDesc dataARPDstMACAddr; nwItemDesc dataARPDstIPAddr; + nwItemDesc dataGratuitousARP; nwItemDesc dataComment; }; Index: libvirt-acl/docs/schemas/nwfilter.rng =================================================================== --- libvirt-acl.orig/docs/schemas/nwfilter.rng +++ libvirt-acl/docs/schemas/nwfilter.rng @@ -581,6 +581,11 @@ <ref name="uint16range"/> </attribute> </optional> + <optional> + <attribute name="gratuitous"> + <ref name="boolean"/> + </attribute> + </optional> </interleave> </define> @@ -784,6 +789,17 @@ </choice> </define> + <define name="boolean"> + <choice> + <value>yes</value> + <value>no</value> + <value>true</value> + <value>false</value> + <value>1</value> + <value>0</value> + </choice> + </define> + <define name="arpOpcodeType"> <choice> <!-- variable --> 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 @@ -2033,6 +2033,13 @@ ebtablesCreateRuleInstance(char chainPre ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataARPDstMACAddr), macaddr); } + + if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataGratuitousARP) && + rule->p.arpHdrFilter.dataGratuitousARP.u.boolean == true) { + virBufferAsprintf(&buf, + " %s --arp-gratuitous", + ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataGratuitousARP)); + } break; case VIR_NWFILTER_RULE_PROTOCOL_IP: Index: libvirt-acl/examples/xml/nwfilter/no-arp-spoofing.xml =================================================================== --- libvirt-acl.orig/examples/xml/nwfilter/no-arp-spoofing.xml +++ libvirt-acl/examples/xml/nwfilter/no-arp-spoofing.xml @@ -12,7 +12,11 @@ <rule action='drop' direction='out' priority='400' > <arp match='no' arpsrcipaddr='$IP' /> </rule> - <!-- drop if ipaddr or macaddr odes not belong to guest --> + <!-- allow gratuitous arp --> + <rule action='accept' direction='in' priority='425'> + <arp gratuitous='true'/> + </rule> + <!-- drop if ipaddr or macaddr does not belong to guest --> <rule action='drop' direction='in' priority='450' > <arp match='no' arpdstmacaddr='$MAC'/> <arp opcode='reply'/> Index: libvirt-acl/docs/formatnwfilter.html.in =================================================================== --- libvirt-acl.orig/docs/formatnwfilter.html.in +++ libvirt-acl/docs/formatnwfilter.html.in @@ -321,6 +321,7 @@ <li>IPV6_ADDR: IPv6 address in numbers format, i.e., FFFF::1</li> <li>IPV6_MASK: IPv6 mask in numbers format (FFFF:FFFF:FC00::) or CIDR mask (0-128)</li> <li>STRING: A string</li> + <li>BOOLEAN: 'true', 'yes', '1' or 'false', 'no', '0'</li> </ul> <p> <br/><br/> @@ -476,6 +477,11 @@ <td>STRING</td> <td>text with max. 256 characters</td> </tr> + <tr> + <td>gratuitous <span class="since">(Since 0.9.2)</span></td> + <td>BOOLEAN</td> + <td>boolean indicating whether to check for gratuitous ARP packet</td> + </tr> </table> <p> Valid strings for the <code>Opcode</code> field are: Index: libvirt-acl/tests/nwfilterxml2xmlin/arp-test.xml =================================================================== --- libvirt-acl.orig/tests/nwfilterxml2xmlin/arp-test.xml +++ libvirt-acl/tests/nwfilterxml2xmlin/arp-test.xml @@ -30,4 +30,8 @@ <arp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' opcode='65536' hwtype='65536' protocoltype='65536' /> </rule> + + <rule action='accept' direction='in'> + <arp gratuitous='true'/> + </rule> </filter> Index: libvirt-acl/tests/nwfilterxml2xmlout/arp-test.xml =================================================================== --- libvirt-acl.orig/tests/nwfilterxml2xmlout/arp-test.xml +++ libvirt-acl/tests/nwfilterxml2xmlout/arp-test.xml @@ -15,4 +15,7 @@ <rule action='accept' direction='out' priority='500'> <arp srcmacaddr='01:02:03:04:05:06' srcmacmask='ff:ff:ff:ff:ff:ff'/> </rule> + <rule action='accept' direction='in' priority='500'> + <arp gratuitous='true'/> + </rule> </filter>

On 05/23/2011 05:32 PM, Stefan Berger wrote:
This patch enables filtering of gratuitous ARP packets using the following XML:
<rule action='accept' direction='in' priority='425'> <arp gratuitous='true'/> </rule>
Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
+++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c @@ -2033,6 +2033,13 @@ ebtablesCreateRuleInstance(char chainPre
ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataARPDstMACAddr), macaddr); } + + if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataGratuitousARP) && + rule->p.arpHdrFilter.dataGratuitousARP.u.boolean == true) {
HACKING recommends against direct comparison to 'true', in part because of gnulib <stdbool.h> restrictions. Simplify this to: if (... && rule->p.arpHdrFilter.dataGratuitousARP.u.boolean) { Your mailer messed up indentation on all lines that started with < after an arbitrary amount of whitespace, but I trust that your original patch followed conventions. ACK with the nit fixed. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On 05/23/2011 07:38 PM, Eric Blake wrote:
On 05/23/2011 05:32 PM, Stefan Berger wrote:
This patch enables filtering of gratuitous ARP packets using the following XML:
<rule action='accept' direction='in' priority='425'> <arp gratuitous='true'/> </rule>
Signed-off-by: Stefan Berger<stefanb@us.ibm.com> +++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c @@ -2033,6 +2033,13 @@ ebtablesCreateRuleInstance(char chainPre
ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataARPDstMACAddr), macaddr); } + + if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataGratuitousARP)&& + rule->p.arpHdrFilter.dataGratuitousARP.u.boolean == true) { HACKING recommends against direct comparison to 'true', in part because of gnulib<stdbool.h> restrictions. Simplify this to:
if (...&& rule->p.arpHdrFilter.dataGratuitousARP.u.boolean) {
Your mailer messed up indentation on all lines that started with< after an arbitrary amount of whitespace, but I trust that your original patch followed conventions.
ACK with the nit fixed.
Fixed and pushed.
participants (2)
-
Eric Blake
-
Stefan Berger