src/Virt_FilterEntry.c | 88 ++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 74 insertions(+), 14 deletions(-)
# HG changeset patch
# User Eduardo Lima (Etrunko) <eblima(a)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(a)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)) {