]> xenbits.xensource.com Git - libvirt.git/commitdiff
Enable chains with names having a known prefix
authorStefan Berger <stefanb@linux.vnet.ibm.com>
Fri, 18 Nov 2011 16:58:18 +0000 (11:58 -0500)
committerStefan Berger <stefanb@us.ibm.com>
Fri, 18 Nov 2011 16:58:18 +0000 (11:58 -0500)
This patch enables chains that have a known prefix in their name.
Known prefixes are: 'ipv4', 'ipv6', 'arp', 'rarp'. All prefixes
are also protocols that can be evaluated on the ebtables level.

Following the prefix they will be automatically connected to an interface's
'root' chain and jumped into following the protocol they evaluate, i.e.,
a table 'arp-xyz' will be accessed from the root table using

ebtables -t nat -A <iface root table> -p arp -j I-<ifname>-arp-xyz

thus generating a 'root' chain like this one here:

Bridge chain: libvirt-O-vnet0, entries: 5, policy: ACCEPT
-p IPv4 -j O-vnet0-ipv4
-p ARP -j O-vnet0-arp
-p 0x8035 -j O-vnet0-rarp
-p ARP -j O-vnet0-arp-xyz
-j DROP

where the chain 'arp-xyz' is accessed for filtering of ARP packets.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
docs/schemas/nwfilter.rng
src/conf/nwfilter_conf.c
src/conf/nwfilter_conf.h

index e679766323eb380cd9182f0b664834db976fbf51..b9d72760afb0558331889251e951ceca132494ef 100644 (file)
       <attribute name="chain">
         <choice>
           <value>root</value>
-          <value>arp</value>
-          <value>rarp</value>
-          <value>ipv4</value>
-          <value>ipv6</value>
+          <data type="string">
+            <param name="pattern">arp[a-zA-Z0-9_\.:-]{0,9}</param>
+          </data>
+          <data type="string">
+            <param name="pattern">rarp[a-zA-Z0-9_\.:-]{0,8}</param>
+          </data>
+          <data type="string">
+            <param name="pattern">ipv4[a-zA-Z0-9_\.:-]{0,8}</param>
+          </data>
+          <data type="string">
+            <param name="pattern">ipv6[a-zA-Z0-9_\.:-]{0,8}</param>
+          </data>
         </choice>
       </attribute>
     </optional>
index 4b7c823070166c5634e392658f6405f2f5f58138..ea9111deeba2b81ff97edc6a22e6da87e6ff014b 100644 (file)
@@ -2007,6 +2007,84 @@ err_exit:
     goto cleanup;
 }
 
+static bool
+virNWFilterIsValidChainName(const char *chainname)
+{
+    if (strlen(chainname) > MAX_CHAIN_SUFFIX_SIZE) {
+        virNWFilterReportError(VIR_ERR_INVALID_ARG,
+                               _("Name of chain is longer than "
+                                 "%u characters"),
+                               MAX_CHAIN_SUFFIX_SIZE);
+        return false;
+    }
+
+    if (chainname[strspn(chainname, VALID_CHAINNAME)] != 0) {
+        virNWFilterReportError(VIR_ERR_INVALID_ARG,
+                               _("Chain name contains invalid characters"));
+        return false;
+    }
+
+    return true;
+}
+
+/*
+ * Test whether the name of the chain is supported.
+ * It current has to have a prefix of either one of the strings found in
+ * virNWFilterChainSuffixTypeToString().
+ */
+static const char *
+virNWFilterIsAllowedChain(const char *chainname)
+{
+    enum virNWFilterChainSuffixType i;
+    const char *name, *msg;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    bool printed = false;
+
+    if (!virNWFilterIsValidChainName(chainname))
+        return NULL;
+
+    for (i = 0; i < VIR_NWFILTER_CHAINSUFFIX_LAST; i++) {
+        name = virNWFilterChainSuffixTypeToString(i);
+        if (i == VIR_NWFILTER_CHAINSUFFIX_ROOT) {
+            /* allow 'root' as a complete name but not as a prefix */
+            if (STREQ(chainname, name))
+                return name;
+            if (STRPREFIX(chainname, name))
+                return NULL;
+        }
+        if (STRPREFIX(chainname, name))
+            return name;
+    }
+
+    virBufferAsprintf(&buf,
+                      _("Invalid chain name '%s'. Please use a chain name "
+                      "called '%s' or any of the following prefixes: "),
+                      chainname,
+                      virNWFilterChainSuffixTypeToString(
+                          VIR_NWFILTER_CHAINSUFFIX_ROOT));
+    for (i = 0; i < VIR_NWFILTER_CHAINSUFFIX_LAST; i++) {
+        if (i == VIR_NWFILTER_CHAINSUFFIX_ROOT)
+            continue;
+        if (printed)
+            virBufferAddLit(&buf, ", ");
+        virBufferAdd(&buf, virNWFilterChainSuffixTypeToString(i), -1);
+        printed = true;
+    }
+
+    if (virBufferError(&buf)) {
+        virReportOOMError();
+        virBufferFreeAndReset(&buf);
+        goto err_exit;
+    }
+
+    msg = virBufferContentAndReset(&buf);
+
+    virNWFilterReportError(VIR_ERR_INVALID_ARG, "%s", msg);
+    VIR_FREE(msg);
+
+err_exit:
+    return NULL;
+}
 
 static virNWFilterDefPtr
 virNWFilterDefParseXML(xmlXPathContextPtr ctxt) {
@@ -2017,6 +2095,7 @@ virNWFilterDefParseXML(xmlXPathContextPtr ctxt) {
     char *chain_pri_s = NULL;
     virNWFilterEntryPtr entry;
     int chain_priority;
+    const char *name_prefix;
 
     if (VIR_ALLOC(ret) < 0) {
         virReportOOMError();
@@ -2052,19 +2131,19 @@ virNWFilterDefParseXML(xmlXPathContextPtr ctxt) {
 
     chain = virXPathString("string(./@chain)", ctxt);
     if (chain) {
-        if (virNWFilterChainSuffixTypeFromString(chain) < 0) {
-            virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
-                                   _("unknown chain suffix '%s'"), chain);
+        name_prefix = virNWFilterIsAllowedChain(chain);
+        if (name_prefix == NULL)
             goto cleanup;
-        }
         ret->chainsuffix = chain;
 
         if (chain_pri_s) {
             ret->chainPriority = chain_priority;
         } else {
             /* assign default priority if none can be found via lookup */
-            if (!intMapGetByString(chain_priorities, chain, 0,
+            if (!name_prefix ||
+                !intMapGetByString(chain_priorities, name_prefix, 0,
                                    &ret->chainPriority)) {
+                /* assign default chain priority */
                 ret->chainPriority = (NWFILTER_MAX_FILTER_PRIORITY +
                                       NWFILTER_MIN_FILTER_PRIORITY) / 2;
             }
index 0ff14d143a2880812459ad59a1eabb61b1902b99..55b2aad35aab5125d0b077d5b4e2801aab731498 100644 (file)
@@ -446,6 +446,9 @@ enum virNWFilterChainSuffixType {
     VIR_NWFILTER_CHAINSUFFIX_LAST,
 };
 
+# define VALID_CHAINNAME \
+  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.:-"
+
 typedef int32_t virNWFilterChainPriority;
 
 typedef struct _virNWFilterDef virNWFilterDef;