[libvirt] [PATCH] nwfilter: Some fixes to XML parser

While writing a couple of test cases for the nwfilter's XML parser I found some cases where the output ended up not looking as expected. So the following changes are in the patch below: - if the protocol ID in the MAC header is an integer, just write it into the datastructure without trying to find a corresponding string for it and if none is found failing - when writing the protocol ID as string, simply write it as integer if no corresponding string can be found - same changes for arpOpcode parsing and printing - same changes for protocol ID in an IP packet - DSCP value needs to be written into the data structure - IP protocol version number is redundant at this level, so remove it - parse the protocol ID found inside an IP packet not only as string but also as uint8 - arrange the display of the src and destination masks to be shown after the src and destination ip address respectively in the XML - the existing libvirt IP address parser accepts for example '25' as an IP address. I want this to be parsed as a CIDR type netmask. So try to parse it as an integer first (CIDR netmask) and if that doesn't work as a dotted IP address style netmask. - instantiation of rules with MAC masks didn't work because they weren't printed into a buffer, yet. Signed-off-by: Stefan Berger <stefanb@us.ibm.com> --- src/conf/nwfilter_conf.c | 128 ++++++++++++++---------------- src/nwfilter/nwfilter_ebiptables_driver.c | 1 2 files changed, 61 insertions(+), 68 deletions(-) Index: libvirt-acl/src/conf/nwfilter_conf.c =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.c +++ libvirt-acl/src/conf/nwfilter_conf.c @@ -403,15 +403,12 @@ checkMacProtocolID(enum attrDatatype dat virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED) { int32_t res = -1; - const char *str; if (datatype == DATATYPE_STRING) { if (intMapGetByString(macProtoMap, (char *)value, 1, &res) == 0) res = -1; } else if (datatype == DATATYPE_UINT16) { - if (intMapGetByInt(macProtoMap, - (int32_t)*(uint16_t *)value, &str) == 0) - res = -1; + res = (uint32_t)*(uint16_t *)value; } if (res != -1) { @@ -433,9 +430,10 @@ macProtocolIDFormatter(virBufferPtr buf, nwf->p.ethHdrFilter.dataProtocolID.u.u16, &str)) { virBufferVSprintf(buf, "%s", str); - return 1; + } else { + virBufferVSprintf(buf, "%d", nwf->p.ethHdrFilter.dataProtocolID.u.u16); } - return 0; + return 1; } @@ -500,15 +498,12 @@ arpOpcodeValidator(enum attrDatatype dat virNWFilterRuleDefPtr nwf) { int32_t res = -1; - const char *str; if (datatype == DATATYPE_STRING) { if (intMapGetByString(arpOpcodeMap, (char *)value, 1, &res) == 0) res = -1; } else if (datatype == DATATYPE_UINT16) { - if (intMapGetByInt(arpOpcodeMap, - (uint32_t)*(uint16_t *)value, &str) == 0) - res = -1; + res = (uint32_t)*(uint16_t *)value; } if (res != -1) { @@ -530,9 +525,10 @@ arpOpcodeFormatter(virBufferPtr buf, nwf->p.arpHdrFilter.dataOpcode.u.u16, &str)) { virBufferVSprintf(buf, "%s", str); - return 1; + } else { + virBufferVSprintf(buf, "%d", nwf->p.arpHdrFilter.dataOpcode.u.u16); } - return 0; + return 1; } @@ -560,16 +556,12 @@ static bool checkIPProtocolID(enum attrD virNWFilterRuleDefPtr nwf) { int32_t res = -1; - const char *str; if (datatype == DATATYPE_STRING) { if (intMapGetByString(ipProtoMap, (char *)value, 1, &res) == 0) res = -1; } else if (datatype == DATATYPE_UINT8) { - // may just accept what user provides and not test... - if (intMapGetByInt(ipProtoMap, - (uint32_t)*(uint16_t *)value, &str) == 0) - res = -1; + res = (uint32_t)*(uint16_t *)value; } if (res != -1) { @@ -591,19 +583,24 @@ formatIPProtocolID(virBufferPtr buf, nwf->p.ipHdrFilter.ipHdr.dataProtocolID.u.u8, &str)) { virBufferVSprintf(buf, "%s", str); - return 1; + } else { + virBufferVSprintf(buf, "%d", + nwf->p.ipHdrFilter.ipHdr.dataProtocolID.u.u8); } - return 0; + return 1; } static bool dscpValidator(enum attrDatatype datatype ATTRIBUTE_UNUSED, void *val, - virNWFilterRuleDefPtr nwf ATTRIBUTE_UNUSED) + virNWFilterRuleDefPtr nwf) { uint8_t dscp = *(uint16_t *)val; if (dscp > 63) return 0; + + nwf->p.ipHdrFilter.ipHdr.dataDSCP.u.u8 = dscp; + return 1; } @@ -685,11 +682,6 @@ static const virXMLAttr2Struct arpAttrib static const virXMLAttr2Struct ipAttributes[] = { COMMON_MAC_PROPS(ipHdrFilter), { - .name = "version", - .datatype = DATATYPE_UINT8, - .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataIPVersion), - }, - { .name = SRCIPADDR, .datatype = DATATYPE_IPADDR, .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataSrcIPAddr), @@ -711,7 +703,7 @@ static const virXMLAttr2Struct ipAttribu }, { .name = "protocol", - .datatype = DATATYPE_STRING, + .datatype = DATATYPE_STRING | DATATYPE_UINT8, .dataIdx = offsetof(virNWFilterRuleDef, p.ipHdrFilter.ipHdr.dataProtocolID), .validator= checkIPProtocolID, .formatter= formatIPProtocolID, @@ -756,16 +748,16 @@ static const virXMLAttr2Struct ipv6Attri .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataSrcIPAddr), }, { - .name = DSTIPADDR, - .datatype = DATATYPE_IPV6ADDR, - .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataDstIPAddr), - }, - { .name = SRCIPMASK, .datatype = DATATYPE_IPV6MASK, .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataSrcIPMask), }, { + .name = DSTIPADDR, + .datatype = DATATYPE_IPV6ADDR, + .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataDstIPAddr), + }, + { .name = DSTIPMASK, .datatype = DATATYPE_IPV6MASK, .dataIdx = offsetof(virNWFilterRuleDef, p.ipv6HdrFilter.ipHdr.dataDstIPMask), @@ -818,16 +810,16 @@ static const virXMLAttr2Struct ipv6Attri .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPAddr),\ },\ {\ - .name = DSTIPADDR,\ - .datatype = ADDRTYPE,\ - .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPAddr),\ - },\ - {\ .name = SRCIPMASK,\ .datatype = MASKTYPE,\ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPMask),\ },\ {\ + .name = DSTIPADDR,\ + .datatype = ADDRTYPE,\ + .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPAddr),\ + },\ + {\ .name = DSTIPMASK,\ .datatype = MASKTYPE,\ .dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPMask),\ @@ -1276,26 +1268,26 @@ virNWFilterRuleDetailsParse(virConnectPt case DATATYPE_IPMASK: storage_ptr = &item->u.u8; - if (!virNWIPv4AddressParser(prop, &ipaddr)) { - if (sscanf(prop, "%d", &int_val) == 1) { - if (int_val >= 0 && int_val <= 32) { - if (!validator) - *(uint8_t *)storage_ptr = - (uint8_t)int_val; - found = 1; - data_ptr = &int_val; - } else - rc = -1; + if (virStrToLong_i(prop, NULL, 10, &int_val) == 0) { + if (int_val >= 0 && int_val <= 32) { + if (!validator) + *(uint8_t *)storage_ptr = + (uint8_t)int_val; + found = 1; + data_ptr = &int_val; } else rc = -1; } else { - int_val = virSocketGetNumNetmaskBits( + if (virNWIPv4AddressParser(prop, &ipaddr)) { + int_val = virSocketGetNumNetmaskBits( &ipaddr.addr); - if (int_val >= 0) - *(uint8_t *)storage_ptr = int_val; - else + if (int_val >= 0) + *(uint8_t *)storage_ptr = int_val; + else + rc = -1; + found = 1; + } else rc = -1; - found = 1; } break; @@ -1330,26 +1322,26 @@ virNWFilterRuleDetailsParse(virConnectPt case DATATYPE_IPV6MASK: storage_ptr = &item->u.u8; - if (!virNWIPv6AddressParser(prop, &ipaddr)) { - if (sscanf(prop, "%d", &int_val) == 1) { - if (int_val >= 0 && int_val <= 128) { - if (!validator) - *(uint8_t *)storage_ptr = - (uint8_t)int_val; - found = 1; - data_ptr = &int_val; - } else - rc = -1; + if (virStrToLong_i(prop, NULL, 10, &int_val) == 0) { + if (int_val >= 0 && int_val <= 128) { + if (!validator) + *(uint8_t *)storage_ptr = + (uint8_t)int_val; + found = 1; + data_ptr = &int_val; } else rc = -1; } else { - int_val = virSocketGetNumNetmaskBits( - &ipaddr.addr); - if (int_val >= 0) - *(uint8_t *)storage_ptr = int_val; - else - rc = -1; - found = 1; + if (virNWIPv6AddressParser(prop, &ipaddr)) { + int_val = virSocketGetNumNetmaskBits( + &ipaddr.addr); + if (int_val >= 0) + *(uint8_t *)storage_ptr = int_val; + else + rc = -1; + found = 1; + } else + rc = -1; } break; 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 @@ -189,6 +189,7 @@ printDataType(virConnectPtr conn, break; case DATATYPE_MACADDR: + case DATATYPE_MACMASK: if (bufsize < VIR_MAC_STRING_BUFLEN) { virNWFilterReportError(conn, VIR_ERR_INVALID_NWFILTER, _("Buffer too small for MAC address"));

On Wed, Mar 31, 2010 at 04:45:04PM -0400, Stefan Berger wrote:
While writing a couple of test cases for the nwfilter's XML parser I found some cases where the output ended up not looking as expected. So the following changes are in the patch below:
- if the protocol ID in the MAC header is an integer, just write it into the datastructure without trying to find a corresponding string for it and if none is found failing - when writing the protocol ID as string, simply write it as integer if no corresponding string can be found - same changes for arpOpcode parsing and printing - same changes for protocol ID in an IP packet - DSCP value needs to be written into the data structure - IP protocol version number is redundant at this level, so remove it - parse the protocol ID found inside an IP packet not only as string but also as uint8 - arrange the display of the src and destination masks to be shown after the src and destination ip address respectively in the XML - the existing libvirt IP address parser accepts for example '25' as an IP address. I want this to be parsed as a CIDR type netmask. So try to parse it as an integer first (CIDR netmask) and if that doesn't work as a dotted IP address style netmask. - instantiation of rules with MAC masks didn't work because they weren't printed into a buffer, yet.
Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
ACK Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On 03/31/2010 02:45 PM, Stefan Berger wrote:
@@ -433,9 +430,10 @@ macProtocolIDFormatter(virBufferPtr buf, nwf->p.ethHdrFilter.dataProtocolID.u.u16, &str)) { virBufferVSprintf(buf, "%s", str); - return 1; + } else { + virBufferVSprintf(buf, "%d", nwf->p.ethHdrFilter.dataProtocolID.u.u16);
This would look a bit better as %u than %d, to match the fact that we know it is unsigned, but at least I don't see any problems with sign extension biting us if we leave the line alone.
+ if (virStrToLong_i(prop, NULL, 10, &int_val) == 0) { + if (int_val >= 0 && int_val <= 32) {
Is it any more efficient to use virStrToLong_ui, so that you can drop the int_val>=0 half of the test by virtue of the fact that you parsed an unsigned int to begin with? -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

Eric Blake <eblake@redhat.com> wrote on 04/01/2010 01:20:30 PM:
On 03/31/2010 02:45 PM, Stefan Berger wrote:
@@ -433,9 +430,10 @@ macProtocolIDFormatter(virBufferPtr buf, nwf->p.ethHdrFilter.dataProtocolID.u.u16, &str)) { virBufferVSprintf(buf, "%s", str); - return 1; + } else { + virBufferVSprintf(buf, "%d", nwf->p.ethHdrFilter.dataProtocolID.u.u16);
This would look a bit better as %u than %d, to match the fact that we know it is unsigned, but at least I don't see any problems with sign extension biting us if we leave the line alone.
+ if (virStrToLong_i(prop, NULL, 10, &int_val) == 0) { + if (int_val >= 0 && int_val <= 32) {
Is it any more efficient to use virStrToLong_ui, so that you can drop the int_val>=0 half of the test by virtue of the fact that you parsed an unsigned int to begin with?
Well, I could introduce a uint_val variable. I actually had tried that _ui function yesterday but then the signed problem came up with the int_val and thought that this probably boils down to 2 more assembly instructions and left it as it is... Also it's not in a critical path where this test was going to be done permanently. But yes, we can fix it along with the strcpn() = strlen() I added... Stefan
participants (3)
-
Daniel Veillard
-
Eric Blake
-
Stefan Berger