The patch below extends the XML parser and generator so that every l3 protocol
now can have a state attribute.

Signed-off-by: Stefan Berger <stef...@us.ibm.com>

---
 src/conf/nwfilter_conf.c |  166 +++++++++++++++++++++++++++++++++++++++++++----
 src/conf/nwfilter_conf.h |   21 +++++
 src/libvirt_private.syms |    1 
 3 files changed, 175 insertions(+), 13 deletions(-)

Index: libvirt-acl/src/conf/nwfilter_conf.c
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_conf.c
+++ libvirt-acl/src/conf/nwfilter_conf.c
@@ -44,6 +44,7 @@
 #include "nwfilter_params.h"
 #include "nwfilter_conf.h"
 #include "domain_conf.h"
+#include "c-ctype.h"
 
 
 #define VIR_FROM_THIS VIR_FROM_NWFILTER
@@ -157,6 +158,7 @@ static const char srcportend_str[]   = "
 static const char dstportstart_str[] = "dstportstart";
 static const char dstportend_str[]   = "dstportend";
 static const char dscp_str[]         = "dscp";
+static const char state_str[]        = "state";
 
 #define SRCMACADDR    srcmacaddr_str
 #define SRCMACMASK    srcmacmask_str
@@ -179,6 +181,7 @@ static const char dscp_str[]         = "
 #define DSTPORTSTART  dstportstart_str
 #define DSTPORTEND    dstportend_str
 #define DSCP          dscp_str
+#define STATE         state_str
 
 
 /**
@@ -414,9 +417,11 @@ union data {
 };
 
 typedef bool (*valueValidator)(enum attrDatatype datatype, union data *valptr,
-                               virNWFilterRuleDefPtr nwf);
+                               virNWFilterRuleDefPtr nwf,
+                               nwItemDesc *item);
 typedef bool (*valueFormatter)(virBufferPtr buf,
-                               virNWFilterRuleDefPtr nwf);
+                               virNWFilterRuleDefPtr nwf,
+                               nwItemDesc *item);
 
 typedef struct _virXMLAttr2Struct virXMLAttr2Struct;
 struct _virXMLAttr2Struct
@@ -441,7 +446,8 @@ static const struct int_map macProtoMap[
 
 static bool
 checkMacProtocolID(enum attrDatatype datatype, union data *value,
-                   virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED)
+                   virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED,
+                   nwItemDesc *item ATTRIBUTE_UNUSED)
 {
     int32_t res = -1;
 
@@ -468,7 +474,8 @@ checkMacProtocolID(enum attrDatatype dat
 
 static bool
 macProtocolIDFormatter(virBufferPtr buf,
-                       virNWFilterRuleDefPtr nwf)
+                       virNWFilterRuleDefPtr nwf,
+                       nwItemDesc *item ATTRIBUTE_UNUSED)
 {
     const char *str = NULL;
     bool asHex = true;
@@ -519,7 +526,8 @@ checkValidMask(unsigned char *data, int 
 static bool
 checkMACMask(enum attrDatatype datatype ATTRIBUTE_UNUSED,
              union data *macMask,
-             virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED)
+             virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED,
+             nwItemDesc *item ATTRIBUTE_UNUSED)
 {
     return checkValidMask(macMask->uc, 6);
 }
@@ -545,7 +553,8 @@ static const struct int_map arpOpcodeMap
 static bool
 arpOpcodeValidator(enum attrDatatype datatype,
                    union data *value,
-                   virNWFilterRuleDefPtr nwf)
+                   virNWFilterRuleDefPtr nwf,
+                   nwItemDesc *item ATTRIBUTE_UNUSED)
 {
     int32_t res = -1;
 
@@ -569,7 +578,8 @@ arpOpcodeValidator(enum attrDatatype dat
 
 static bool
 arpOpcodeFormatter(virBufferPtr buf,
-                   virNWFilterRuleDefPtr nwf)
+                   virNWFilterRuleDefPtr nwf,
+                   nwItemDesc *item ATTRIBUTE_UNUSED)
 {
     const char *str = NULL;
 
@@ -604,7 +614,8 @@ static const struct int_map ipProtoMap[]
 
 static bool checkIPProtocolID(enum attrDatatype datatype,
                               union data *value,
-                              virNWFilterRuleDefPtr nwf)
+                              virNWFilterRuleDefPtr nwf,
+                              nwItemDesc *item ATTRIBUTE_UNUSED)
 {
     int32_t res = -1;
 
@@ -628,7 +639,8 @@ static bool checkIPProtocolID(enum attrD
 
 static bool
 formatIPProtocolID(virBufferPtr buf,
-                   virNWFilterRuleDefPtr nwf)
+                   virNWFilterRuleDefPtr nwf,
+                   nwItemDesc *item ATTRIBUTE_UNUSED)
 {
     const char *str = NULL;
     bool asHex = true;
@@ -649,7 +661,8 @@ formatIPProtocolID(virBufferPtr buf,
 
 static bool
 dscpValidator(enum attrDatatype datatype, union data *val,
-              virNWFilterRuleDefPtr nwf)
+              virNWFilterRuleDefPtr nwf,
+              nwItemDesc *item ATTRIBUTE_UNUSED)
 {
     uint8_t dscp = val->ui;
     if (dscp > 63)
@@ -660,6 +673,128 @@ dscpValidator(enum attrDatatype datatype
     return 1;
 }
 
+
+static const struct int_map stateMatchMap[] = {
+    INTMAP_ENTRY(RULE_FLAG_STATE_NEW          , "NEW"),
+    INTMAP_ENTRY(RULE_FLAG_STATE_ESTABLISHED  , "ESTABLISHED"),
+    INTMAP_ENTRY(RULE_FLAG_STATE_RELATED      , "RELATED"),
+    INTMAP_ENTRY(RULE_FLAG_STATE_INVALID      , "INVALID"),
+    INTMAP_ENTRY(RULE_FLAG_STATE_NONE         , "NONE"),
+    INTMAP_ENTRY_LAST,
+};
+
+
+static int
+parseStringItems(const struct int_map *int_map,
+                 const char *input, int32_t *flags, char sep)
+{
+    int rc = 0;
+    unsigned int i, j;
+    bool found;
+
+    i = 0;
+    while (input[i]) {
+        found = false;
+        while (c_isspace(input[i]) || input[i] == sep)
+            i++;
+        if (!input[i])
+            break;
+        for (j = 0; int_map[j].val; j++) {
+            if (STRCASEEQLEN(&input[i], int_map[j].val,
+                             strlen(int_map[j].val))) {
+                *flags |= int_map[j].attr;
+                i += strlen(int_map[j].val);
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            rc = 1;
+            break;
+        }
+    }
+    return rc;
+}
+
+
+static int
+printStringItems(virBufferPtr buf, const struct int_map *int_map,
+                 int32_t flags, const char *sep)
+{
+    unsigned int i, c = 0;
+    int32_t last_attr = 0;
+
+    for (i = 0; int_map[i].val; i++) {
+        if (last_attr != int_map[i].attr &&
+            flags & int_map[i].attr) {
+            if (c >= 1)
+                virBufferVSprintf(buf, "%s", sep);
+            virBufferVSprintf(buf, "%s", int_map[i].val);
+            c++;
+        }
+        last_attr = int_map[i].attr;
+    }
+
+    return 0;
+}
+
+
+static int
+parseStateMatch(const char *statematch, int32_t *flags)
+{
+    int rc = parseStringItems(stateMatchMap, statematch, flags, ',');
+
+    if ((*flags & RULE_FLAG_STATE_NONE))
+        *flags = RULE_FLAG_STATE_NONE;
+
+    return rc;
+}
+
+
+void
+virNWFilterPrintStateMatchFlags(virBufferPtr buf, const char *prefix,
+                                int32_t flags, bool disp_none)
+{
+    if (!disp_none && (flags & RULE_FLAG_STATE_NONE))
+        return;
+
+    virBufferVSprintf(buf, "%s", prefix);
+
+    printStringItems(buf, stateMatchMap, flags, ",");
+}
+
+
+static bool
+stateValidator(enum attrDatatype datatype ATTRIBUTE_UNUSED, union data *val,
+               virNWFilterRuleDefPtr nwf,
+               nwItemDesc *item)
+{
+    char *input = val->c;
+    int32_t flags = 0;
+
+    if (parseStateMatch(input, &flags))
+        return 0;
+
+    item->u.u16 = flags;
+    nwf->flags |= flags;
+
+    item->datatype = DATATYPE_UINT16;
+
+    return 1;
+}
+
+
+static bool
+stateFormatter(virBufferPtr buf,
+               virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED,
+               nwItemDesc *item)
+{
+    virNWFilterPrintStateMatchFlags(buf, "", item->u.u16, true);
+
+    return true;
+}
+
+
 #define COMMON_MAC_PROPS(STRUCT) \
     {\
         .name = SRCMACADDR,\
@@ -926,6 +1061,13 @@ static const virXMLAttr2Struct ipv6Attri
         .name = "connlimit-above",\
         .datatype = DATATYPE_UINT16,\
         .dataIdx = offsetof(virNWFilterRuleDef, 
p.STRUCT.ipHdr.dataConnlimitAbove),\
+    },\
+    {\
+        .name = STATE,\
+        .datatype = DATATYPE_STRING,\
+        .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataState),\
+        .validator = stateValidator,\
+        .formatter = stateFormatter,\
     }
 
 #define COMMON_PORT_PROPS(STRUCT) \
@@ -1422,7 +1564,7 @@ virNWFilterRuleDetailsParse(xmlNodePtr n
                 *flags = NWFILTER_ENTRY_ITEM_FLAG_EXISTS | flags_set;
                 item->datatype = datatype >> 1;
                 if (validator) {
-                    if (!validator(datatype >> 1, &data, nwf)) {
+                    if (!validator(datatype >> 1, &data, nwf, item)) {
                         rc = -1;
                         *flags = 0;
                     }
@@ -2533,7 +2675,7 @@ virNWFilterRuleDefDetailsFormat(virBuffe
             virBufferVSprintf(buf, " %s='",
                               att[i].name);
             if (att[i].formatter) {
-               if (!att[i].formatter(buf, def)) {
+               if (!att[i].formatter(buf, def, item)) {
                   virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
                                          _("formatter for %s %s reported 
error"),
                                          type,
Index: libvirt-acl/src/conf/nwfilter_conf.h
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_conf.h
+++ libvirt-acl/src/conf/nwfilter_conf.h
@@ -28,11 +28,14 @@
 
 # include <stdint.h>
 # include <stddef.h>
+# include <stdbool.h>
 
 # include "internal.h"
+
 # include "util.h"
 # include "hash.h"
 # include "xml.h"
+# include "buf.h"
 # include "network.h"
 
 /* XXX
@@ -179,6 +182,7 @@ struct _ipHdrDataDef {
     nwItemDesc dataDstIPFrom;
     nwItemDesc dataDstIPTo;
     nwItemDesc dataDSCP;
+    nwItemDesc dataState;
     nwItemDesc dataConnlimitAbove;
     nwItemDesc dataComment;
 };
@@ -353,10 +357,25 @@ enum virNWFilterEbtablesTableType {
 # define MAX_RULE_PRIORITY  1000
 
 enum virNWFilterRuleFlags {
-    RULE_FLAG_NO_STATEMATCH = (1 << 0),
+    RULE_FLAG_NO_STATEMATCH      = (1 << 0),
+    RULE_FLAG_STATE_NEW          = (1 << 1),
+    RULE_FLAG_STATE_ESTABLISHED  = (1 << 2),
+    RULE_FLAG_STATE_RELATED      = (1 << 3),
+    RULE_FLAG_STATE_INVALID      = (1 << 4),
+    RULE_FLAG_STATE_NONE         = (1 << 5),
 };
 
 
+# define IPTABLES_STATE_FLAGS \
+  (RULE_FLAG_STATE_NEW | \
+   RULE_FLAG_STATE_ESTABLISHED | \
+   RULE_FLAG_STATE_RELATED | \
+   RULE_FLAG_STATE_INVALID | \
+   RULE_FLAG_STATE_NONE)
+
+void virNWFilterPrintStateMatchFlags(virBufferPtr buf, const char *prefix,
+                                     int32_t flags, bool disp_none);
+
 typedef struct _virNWFilterRuleDef  virNWFilterRuleDef;
 typedef virNWFilterRuleDef *virNWFilterRuleDefPtr;
 struct _virNWFilterRuleDef {
Index: libvirt-acl/src/libvirt_private.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_private.syms
+++ libvirt-acl/src/libvirt_private.syms
@@ -534,6 +534,7 @@ virNWFilterConfLayerInit;
 virNWFilterConfLayerShutdown;
 virNWFilterLockFilterUpdates;
 virNWFilterUnlockFilterUpdates;
+virNWFilterPrintStateMatchFlags;
 
 
 # nwfilter_params.h

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to