
src/Virt_FilterEntry.c | 88 ++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 74 insertions(+), 14 deletions(-) # HG changeset patch # User Eduardo Lima (Etrunko) <eblima@br.ibm.com> # Date 1317914740 10800 # Node ID 1a08d8186f3064dfb0c38ecb5846ffc1e7d5de4d # Parent a323895be993b3807cc41348ba3b74c76fb42596 FilterEntry: Support for mask in CIDR notation The values for mask fields may have been written using the CIDR notation[1]. For instance, take the libvirt 'no-ip-multicast' builtin filter: <filter name='no-ip-multicast' chain='ipv4'> <uuid>47756f11-6057-1448-2cce-fda40fa23ba4</uuid> <rule action='drop' direction='out' priority='500'> <ip dstipaddr='224.0.0.0' dstipmask='4'/> </rule> </filter> As libvirt-cim expects an address like string, for the mask, in this case the conversion will fail and will output an array with only zero values [0,0,0,0], when it actually should be [240,0,0,0]. [1] http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing Signed-off-by: Eduardo Lima (Etrunko) <eblima@br.ibm.com> diff --git a/src/Virt_FilterEntry.c b/src/Virt_FilterEntry.c --- a/src/Virt_FilterEntry.c +++ b/src/Virt_FilterEntry.c @@ -115,6 +115,44 @@ return array; } +static char *cidr_to_str(const char *cidr) +{ + char *ret = NULL; + int val; + unsigned int o1, o2, o3, o4; + + if (cidr == NULL || strlen(cidr) == 0) + return NULL; + + CU_DEBUG("Enter %s(%s)", __FUNCTION__, cidr); + + /* String value to integer */ + val = atoi(cidr); + if (val < 0 || val > 32) + return NULL; + + if (val == 0) + return strdup("0.0.0.0"); + else if (val == 32) + return strdup("255.255.255.255"); + + /* CIDR to bits */ + val = (0xffffffff >> (32 - val)) << (32 - val); + + /* bits to octets */ + o1 = (val & 0xff000000) >> 24; + o2 = (val & 0x00ff0000) >> 16; + o3 = (val & 0x0000ff00) >> 8; + o4 = val & 0x000000ff; + + /* octets to address string */ + ret = calloc(1, sizeof(*ret) * 16); + snprintf(ret, 16, "%u.%u.%u.%u", o1, o2, o3, o4); + + CU_DEBUG("%s: returning '%s'", __FUNCTION__, ret); + return ret; +} + static int convert_direction(const char *s) { enum {NOT_APPLICABLE, INPUT, OUTPUT, BOTH} direction = NOT_APPLICABLE; @@ -246,14 +284,25 @@ CMSetProperty(inst, "HdrSrcAddress", (CMPIValue *)&array, CMPI_uint8A); - memset(bytes, 0, sizeof(bytes)); - size = octets_from_ip(rule->var.tcp.srcipmask, - bytes, sizeof(bytes)); + /* CIDR notation? */ + if (rule->var.tcp.srcipmask) { + char *netmask = strdup(rule->var.tcp.srcipmask); + if (strstr(netmask, ".") == NULL) { + char *tmp = cidr_to_str(netmask); + free(netmask); + netmask = tmp; + } - array = octets_to_cmpi(broker, bytes, size); - if (array != NULL) - CMSetProperty(inst, "HdrSrcMask", - (CMPIValue *)&array, CMPI_uint8A); + memset(bytes, 0, sizeof(bytes)); + size = octets_from_ip(netmask, bytes, sizeof(bytes)); + + array = octets_to_cmpi(broker, bytes, size); + if (array != NULL) + CMSetProperty(inst, "HdrSrcMask", + (CMPIValue *)&array, CMPI_uint8A); + + free(netmask); + } } if (rule->var.tcp.dstipfrom && rule->var.tcp.dstipto) { @@ -284,14 +333,25 @@ CMSetProperty(inst, "HdrDestAddress", (CMPIValue *)&array, CMPI_uint8A); - memset(bytes, 0, sizeof(bytes)); - size = octets_from_ip(rule->var.tcp.dstipmask, - bytes, sizeof(bytes)); + /* CIDR notation? */ + if (rule->var.tcp.dstipmask) { + char *netmask = strdup(rule->var.tcp.dstipmask); + if (strstr(netmask, ".") == NULL) { + char *tmp = cidr_to_str(netmask); + free(netmask); + netmask = tmp; + } - array = octets_to_cmpi(broker, bytes, size); - if (array != NULL) - CMSetProperty(inst, "HdrDestMask", - (CMPIValue *)&array, CMPI_uint8A); + memset(bytes, 0, sizeof(bytes)); + size = octets_from_ip(netmask, bytes, sizeof(bytes)); + + array = octets_to_cmpi(broker, bytes, size); + if (array != NULL) + CMSetProperty(inst, "HdrDestMask", + (CMPIValue *)&array, CMPI_uint8A); + + free(netmask); + } } if ((rule->type == IP_RULE) || (rule->type == TCP_RULE)) {