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

Stefan Berger stefanb at linux.vnet.ibm.com
Mon May 23 23:32:18 UTC 2011


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 at 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>




More information about the libvir-list mailing list