This is a big patch. I have visually reviewed the code and it looks good.
Ran cimtests which completed successfully, meaning that there is no
regression :-)
There are no automated tests to verify this feature at this time. I ran few
manual tests using wbemcli.
I Ack this patch but would like someone else to review and test it too
before pushing it upstream.
Thanks
Sharad Mishra
Open Virtualization
Linux Technology Center
IBM
libvirt-cim-bounces(a)redhat.com wrote on 05/26/2011 10:08:43 PM:
Chip Vincent <cvincent(a)linux.vnet.ibm.com>
Sent by: libvirt-cim-bounces(a)redhat.com
05/26/11 10:08 PM
Please respond to
List for discussion and development of libvirt CIM
<libvirt-cim(a)redhat.com>
To
libvirt-cim(a)redhat.com
cc
Subject
[Libvirt-cim] [PATCH] (#2) Add DCN ACL classes & providers
# HG changeset patch
# User Chip Vincent <cvincent(a)us.ibm.com>
# Date 1305221061 14400
# Node ID 68e37b55a0687ca55554ca84c79c3358c05aee90
# Parent 8e7c9a8ad1f9e5bf6765c89a36ccca43f0564934
(#2) Add DCN ACL classes & providers
Changes in this version:
#2 - Scoped code to primary use case: link network interfaces to
existing fitlers.
- Updated copyright year in a few places.
- Fixed octets_to_cmpi() to work when called from an associattion
provider
This patch adds several new classes and providers to add support for
filter
rules and filter lists.
The patch is rather large since all aspects are intertwined.
Here's an overview of the implementation:
libxkutil:
The instrumentation is implemented in acl_parsing.c/.h since this
function
is essentially independent of the device and/or pool parsing. ACLs
are
associated to devices (via filterref) so there are some minor changes in
device_parsing.c & xmlgen.c to support this.
+libxkutil/acl_parsing.h & .c
Adds several new structures to represent filters and rules. Since rules
can
only exist within the context of a filter, the main structure used in
the
APIs
is acl_fitler.
Also adds several new APIs to libxkutil to allow providers (see below) to
convert acl_filter and acl_rule structures to CIM objects, and to support
associations between themselves and existing resource (host system &
network
port).
schema & providers:
The ACL function does not map to an exiting profile so a subset of the
classes defined in the CIM Network schema are used.
+schema/FilterEntry.mof &.registration
+src/FilterEntry.h & .c
Adds two new classes to represent IP-level rules (IPHeadersFilter) and
MAC-level (Hdr8021Filter). These classes include two new properties to
surface libvirt features not defined by the schema (Direction &
Priority).
+schema/FilterList.mof & .registration
+src/FilterList.h & .c
Adds a class to represent ACL filters (FilterList)
NOTE: Read-write. Requires Name property only.
+schema/EntriesInFilterList.mof & .registration
+src/EntriesInFilterList.c
Adds a class to represent the relationship (association) between a filter
(FilterList) and the rules it contains (IPHeadersFilter or
Hdr8021Filter).
+schema/NestedFilterList.mof & .registration
+src/NestedFilterList.c
Adds a class to represent filters that have references (filterref) to
other pre-defined filters. This is not covered by the current schema so
a new class was introduced to a) allow filters to reference each other,
and
b) do it in a way that allows the client to determine if a filter
reference_s_ a filter or is reference_d_ by a filter.
+schema/HostedFilterList.mof & .registration
+src/HostedFilterList.c
Adds a class to represent the relationship (association) between a filter
and the computer system that hosts them. In the case of ACL filters,
which
are essentially defined once but available to all VMs, they are
always
linked
to the host system (hypervisor) rather than the individual computer
systems (VMs).
+schema/AppliedFilterList.mof & .registration
+src/AppliedFilterList.c
Adds a class to represent the relationship (association) between a filter
and a network port referencing it. This is not covered by the current
schema
so a new class was introduced.
NOTE: New associations are created via CIM intrinsic methods
(create/modify/
delete). It requires the client to provide fully qualified object
paths
to
the filter and network port so the providers can a) validate their
existance,
and b) apply the necessary links in the XML so new associations
appear
when
queried.
Signed-off-by: Chip Vincent <cvincent(a)us.ibm.com>
diff --git a/Makefile.am b/Makefile.am
--- a/Makefile.am
+++ b/Makefile.am
@@ -57,7 +57,13 @@
schema/InputPool.mof \
schema/HostedAccessPoint.mof \
schema/ServiceAccessBySAP.mof \
- schema/SAPAvailableForElement.mof
+ schema/SAPAvailableForElement.mof \
+ schema/FilterEntry.mof \
+ schema/FilterList.mof \
+ schema/EntriesInFilterList.mof \
+ schema/NestedFilterList.mof \
+ schema/AppliedFilterList.mof \
+ schema/HostedFilterList.mof
INTEROP_MOFS = \
schema/ComputerSystem.mof \
@@ -138,7 +144,13 @@
schema/InputPool.registration \
schema/HostedAccessPoint.registration \
schema/ServiceAccessBySAP.registration \
- schema/SAPAvailableForElement.registration
+ schema/SAPAvailableForElement.registration \
+ schema/FilterEntry.registration \
+ schema/FilterList.registration \
+ schema/EntriesInFilterList.registration \
+ schema/NestedFilterList.registration \
+ schema/AppliedFilterList.registration \
+ schema/HostedFilterList.registration
INTEROP_REGS = \
schema/RegisteredProfile.registration \
diff --git a/libxkutil/Makefile.am b/libxkutil/Makefile.am
--- a/libxkutil/Makefile.am
+++ b/libxkutil/Makefile.am
@@ -4,12 +4,12 @@
CFLAGS += $(CFLAGS_STRICT)
noinst_HEADERS = cs_util.h misc_util.h device_parsing.h xmlgen.h
infostore.h \
- pool_parsing.h
+ pool_parsing.h acl_parsing.h
lib_LTLIBRARIES = libxkutil.la
libxkutil_la_SOURCES = cs_util_instance.c misc_util.c device_parsing.c \
- xmlgen.c infostore.c pool_parsing.c
+ xmlgen.c infostore.c pool_parsing.c acl_parsing.c
libxkutil_la_LIBADD = @LIBVIRT_LIBS@ \
@LIBUUID_LIBS@
diff --git a/libxkutil/acl_parsing.c b/libxkutil/acl_parsing.c
new file mode 100644
--- /dev/null
+++ b/libxkutil/acl_parsing.c
@@ -0,0 +1,639 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+
+#include "acl_parsing.h"
+#include "device_parsing.h"
+#include "xmlgen.h"
+#include "../src/svpc_types.h"
+
+void cleanup_rule(struct acl_rule *rule)
+{
+ if(rule == NULL)
+ return;
+
+ free(rule->name);
+ free(rule->protocol_id);
+ free(rule->action);
+ free(rule->direction);
+ free(rule->priority);
+
+ switch(rule->type) {
+ case MAC_RULE:
+ free(rule->var.mac.srcmacaddr);
+ free(rule->var.mac.srcmacmask);
+ free(rule->var.mac.dstmacaddr);
+ free(rule->var.mac.dstmacmask);
+ free(rule->var.mac.protocol_id);
+ free(rule->var.mac.comment);
+ break;
+ case ARP_RULE:
+ free(rule->var.arp.srcmacaddr);
+ free(rule->var.arp.srcmacmask);
+ free(rule->var.arp.dstmacaddr);
+ free(rule->var.arp.dstmacmask);
+ free(rule->var.arp.hw_type);
+ free(rule->var.arp.protocol_type);
+ free(rule->var.arp.opcode);
+ free(rule->var.arp.arpsrcmacaddr);
+ free(rule->var.arp.arpdstmacaddr);
+ free(rule->var.arp.arpsrcipaddr);
+ free(rule->var.arp.arpdstipaddr);
+ free(rule->var.arp.comment);
+ break;
+ case IP_RULE:
+ free(rule->var.ip.srcmacaddr);
+ free(rule->var.ip.srcmacmask);
+ free(rule->var.ip.dstmacaddr);
+ free(rule->var.ip.dstmacmask);
+ free(rule->var.ip.srcipaddr);
+ free(rule->var.ip.srcipmask);
+ free(rule->var.ip.dstipaddr);
+ free(rule->var.ip.dstipmask);
+ free(rule->var.ip.srcportstart);
+ free(rule->var.ip.srcportend);
+ free(rule->var.ip.dstportstart);
+ free(rule->var.ip.dstportend);
+ free(rule->var.ip.comment);
+ break;
+ case TCP_RULE:
+ free(rule->var.tcp.srcmacaddr);
+ free(rule->var.tcp.srcipaddr);
+ free(rule->var.tcp.srcipmask);
+ free(rule->var.tcp.dstipaddr);
+ free(rule->var.tcp.srcipfrom);
+ free(rule->var.tcp.srcipto);
+ free(rule->var.tcp.dstipfrom);
+ free(rule->var.tcp.dstipto);
+ free(rule->var.tcp.srcportstart);
+ free(rule->var.tcp.srcportend);
+ free(rule->var.tcp.dstportstart);
+ free(rule->var.tcp.dstportend);
+ free(rule->var.tcp.comment);
+ free(rule->var.tcp.state);
+ break;
+ case IGMP_RULE:
+ free(rule->var.igmp.srcmacaddr);
+ free(rule->var.igmp.srcmacmask);
+ free(rule->var.igmp.dstmacaddr);
+ free(rule->var.igmp.dstmacmask);
+ free(rule->var.igmp.srcipaddr);
+ free(rule->var.igmp.srcipmask);
+ free(rule->var.igmp.dstipaddr);
+ free(rule->var.igmp.dstipmask);
+ free(rule->var.igmp.srcipfrom);
+ free(rule->var.igmp.srcipto);
+ free(rule->var.igmp.dstipfrom);
+ free(rule->var.igmp.dstipto);
+ free(rule->var.igmp.type);
+ free(rule->var.igmp.code);
+ free(rule->var.igmp.comment);
+ free(rule->var.igmp.state);
+ break;
+ case ICMP_RULE:
+ free(rule->var.icmp.srcmacaddr);
+ free(rule->var.icmp.srcmacmask);
+ free(rule->var.icmp.dstmacaddr);
+ free(rule->var.icmp.dstmacmask);
+ free(rule->var.icmp.srcipaddr);
+ free(rule->var.icmp.srcipmask);
+ free(rule->var.icmp.dstipaddr);
+ free(rule->var.icmp.dstipmask);
+ free(rule->var.icmp.srcipfrom);
+ free(rule->var.icmp.srcipto);
+ free(rule->var.icmp.dstipfrom);
+ free(rule->var.icmp.dstipto);
+ free(rule->var.icmp.type);
+ free(rule->var.icmp.code);
+ free(rule->var.icmp.comment);
+ free(rule->var.icmp.state);
+ break;
+ case UNKNOWN_RULE:
+ default:
+ break;
+ };
+
+ rule->type = UNKNOWN_RULE;
+}
+
+void cleanup_filter(struct acl_filter *filter)
+{
+ int i;
+
+ if(filter == NULL)
+ return;
+
+ free(filter->uuid);
+ free(filter->name);
+ free(filter->chain);
+
+ for (i = 0; i < filter->rule_ct; i++) {
+ cleanup_rule(filter->rules[i]);
+ free(filter->rules[i]);
+ }
+
+ free(filter->rules);
+ filter->rule_ct = 0;
+
+ for (i = 0; i < filter->ref_ct; i++)
+ free(filter->refs[i]);
+
+ free(filter->refs);
+ filter->ref_ct = 0;
+}
+
+void cleanup_filters(struct acl_filter **filters, int count)
+{
+ int i;
+ struct acl_filter *_filters = *filters;
+
+ if((filters == NULL) || (*filters == NULL) || (count == 0))
+ return;
+
+ for (i = 0; i < count; i++)
+ cleanup_filter(&_filters[i]);
+
+ free(_filters);
+ *filters = NULL;
+}
+
+
+static int parse_acl_mac_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL mac rule %s", rnode->name);
+
+ rule->type = MAC_RULE;
+ rule->var.mac.protocol_id = get_attr_value(rnode, "protocolid");
+ rule->var.mac.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.mac.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.mac.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.mac.dstmacmask = get_attr_value(rnode, "dstmacmask");
+ rule->var.mac.comment = get_attr_value(rnode, "comment");
+
+ return 1;
+}
+
+static int parse_acl_arp_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL arp rule %s", rnode->name);
+
+ rule->type = ARP_RULE;
+ rule->var.arp.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.arp.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.arp.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.arp.dstmacmask = get_attr_value(rnode, "dstmacmask");
+ rule->var.arp.hw_type = get_attr_value(rnode, "hwtype");
+ rule->var.arp.protocol_type = get_attr_value(rnode,
"protocoltype");
+ rule->var.arp.opcode = get_attr_value(rnode,
"opcode");
+ rule->var.arp.arpsrcmacaddr = get_attr_value(rnode,
"arpsrcmacaddr");
+ rule->var.arp.arpdstmacaddr = get_attr_value(rnode,
"arpdstmacaddr");
+ rule->var.arp.arpsrcipaddr = get_attr_value(rnode,
"arpsrcipaddr");
+ rule->var.arp.arpdstipaddr = get_attr_value(rnode,
"arpdstipaddr");
+ rule->var.arp.comment = get_attr_value(rnode,
"comment");
+
+ return 1;
+}
+
+static int parse_acl_ip_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACP ip rule %s", rnode->name);
+
+ rule->type = IP_RULE;
+ rule->var.ip.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.ip.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.ip.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.ip.dstmacmask = get_attr_value(rnode, "dstmacmaks");
+ rule->var.ip.srcipaddr = get_attr_value(rnode, "srcipaddr");
+ rule->var.ip.srcipmask = get_attr_value(rnode, "srcipmask");
+ rule->var.ip.dstipaddr = get_attr_value(rnode, "dstipaddr");
+ rule->var.ip.dstipmask = get_attr_value(rnode, "dstipmask");
+ rule->var.ip.protocol = get_attr_value(rnode, "protocol");
+ rule->var.ip.srcportstart = get_attr_value(rnode,
"srcportstart");
+ rule->var.ip.srcportend = get_attr_value(rnode,
"srcportend");
+ rule->var.ip.dstportstart = get_attr_value(rnode,
"dstportstart");
+ rule->var.ip.dstportend = get_attr_value(rnode,
"dstportend");
+ rule->var.ip.comment = get_attr_value(rnode, "comment");
+
+ return 1;
+}
+
+static int parse_acl_tcp_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL tcp rule %s", rnode->name);
+
+ rule->type = TCP_RULE;
+ rule->var.tcp.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.tcp.srcipaddr = get_attr_value(rnode, "srcipaddr");
+ rule->var.tcp.srcipmask = get_attr_value(rnode, "srcipmask");
+ rule->var.tcp.dstipaddr = get_attr_value(rnode, "dstipaddr");
+ rule->var.tcp.dstipmask = get_attr_value(rnode, "dstipmask");
+ rule->var.tcp.srcipfrom = get_attr_value(rnode, "srcipfrom");
+ rule->var.tcp.srcipto = get_attr_value(rnode, "srcipto");
+ rule->var.tcp.dstipfrom = get_attr_value(rnode, "dstipfrom");
+ rule->var.tcp.dstipto = get_attr_value(rnode, "dstipto");
+ rule->var.tcp.srcportstart = get_attr_value(rnode,
"srcportstart");
+ rule->var.tcp.srcportend = get_attr_value(rnode,
"srcportend");
+ rule->var.tcp.dstportstart = get_attr_value(rnode,
"dstportstart");
+ rule->var.tcp.dstportend = get_attr_value(rnode,
"dstportend");
+ rule->var.tcp.comment = get_attr_value(rnode, "comment");
+ rule->var.tcp.state = get_attr_value(rnode, "state");
+
+ return 1;
+}
+
+static int parse_acl_icmp_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL icmp rule %s", rnode->name);
+
+ rule->type = ICMP_RULE;
+ rule->var.icmp.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.icmp.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.icmp.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.icmp.dstmacmask = get_attr_value(rnode, "dstmacmask");
+ rule->var.icmp.srcipaddr = get_attr_value(rnode, "srcipaddr");
+ rule->var.icmp.srcipmask = get_attr_value(rnode, "srcipmask");
+ rule->var.icmp.dstipaddr = get_attr_value(rnode, "dstipaddr");
+ rule->var.icmp.dstipmask = get_attr_value(rnode, "dstipmask");
+ rule->var.icmp.srcipfrom = get_attr_value(rnode, "srcipfrom");
+ rule->var.icmp.srcipto = get_attr_value(rnode, "srcipto");
+ rule->var.icmp.dstipfrom = get_attr_value(rnode, "dstipfrom");
+ rule->var.icmp.dstipto = get_attr_value(rnode, "dstipto");
+ rule->var.icmp.comment = get_attr_value(rnode, "comment");
+ rule->var.icmp.state = get_attr_value(rnode, "state");
+
+ return 1;
+}
+
+static int parse_acl_igmp_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL igmp rule %s", rnode->name);
+
+ rule->type = IGMP_RULE;
+ rule->var.igmp.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.igmp.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.igmp.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.igmp.dstmacmask = get_attr_value(rnode, "dstmacmask");
+ rule->var.igmp.srcipaddr = get_attr_value(rnode, "srcipaddr");
+ rule->var.igmp.srcipmask = get_attr_value(rnode, "srcipmask");
+ rule->var.igmp.dstipaddr = get_attr_value(rnode, "dstipaddr");
+ rule->var.igmp.dstipmask = get_attr_value(rnode, "dstipmask");
+ rule->var.igmp.srcipfrom = get_attr_value(rnode, "srcipfrom");
+ rule->var.igmp.srcipto = get_attr_value(rnode, "srcipto");
+ rule->var.igmp.dstipfrom = get_attr_value(rnode, "dstipfrom");
+ rule->var.igmp.dstipto = get_attr_value(rnode, "dstipto");
+ rule->var.igmp.type = get_attr_value(rnode, "type");
+ rule->var.igmp.code = get_attr_value(rnode, "code");
+ rule->var.igmp.comment = get_attr_value(rnode, "comment");
+ rule->var.igmp.state = get_attr_value(rnode, "state");
+
+ return 1;
+}
+
+static int parse_acl_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ xmlNode *child = NULL;
+
+ memset(rule, 0, sizeof(*rule));
+
+ rule->action = get_attr_value(rnode, "action");
+ if (rule->action == NULL)
+ goto err;
+
+ rule->direction = get_attr_value(rnode, "direction");
+ if (rule->direction == NULL)
+ goto err;
+
+ rule->priority = get_attr_value(rnode, "priority");
+ rule->statematch = get_attr_value(rnode, "statematch");
+
+ for (child = rnode->children; child != NULL; child = child->
next)
{
+ if (XSTREQ(child->name, "mac")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_mac_rule(child, rule);
+ } else if (XSTREQ(child->name, "arp") ||
+ XSTREQ(child->name, "rarp")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_arp_rule(child, rule);
+ } else if (XSTREQ(child->name, "ip") ||
+ XSTREQ(child->name, "ipv6")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_ip_rule(child, rule);
+ } else if (XSTREQ(child->name, "tcp") ||
+ XSTREQ(child->name, "tcp-ipv6") ||
+ XSTREQ(child->name, "udp") ||
+ XSTREQ(child->name, "udp-ipv6") ||
+ XSTREQ(child->name, "sctp") ||
+ XSTREQ(child->name, "sctp-ipv6")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_tcp_rule(child, rule);
+ } else if (XSTREQ(child->name, "icmp") ||
+ XSTREQ(child->name, "icmpv6")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_icmp_rule(child, rule);
+ } else if (XSTREQ(child->name, "igmp") ||
+ XSTREQ(child->name, "igmp-ipv6") ||
+ XSTREQ(child->name, "esp") ||
+ XSTREQ(child->name, "esp-ipv6") ||
+ XSTREQ(child->name, "ah") ||
+ XSTREQ(child->name, "ah-ipv6") ||
+ XSTREQ(child->name, "udplite") ||
+ XSTREQ(child->name, "udplite-ipv6") ||
+ XSTREQ(child->name, "all") ||
+ XSTREQ(child->name, "all-ipv6")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_igmp_rule(child, rule);
+ }
+ }
+
+ return 1;
+
+ err:
+ cleanup_rule(rule);
+
+ return 0;
+}
+
+static int parse_acl_filter(xmlNode *fnode, struct acl_filter *filter)
+{
+ struct acl_rule *rule = NULL;
+ char *filter_ref = NULL;
+ xmlNode *child = NULL;
+
+ filter->name = get_attr_value(fnode, "name");
+ if (filter->name == NULL)
+ goto err;
+
+ filter->chain = get_attr_value(fnode, "chain");
+
+ for (child = fnode->children; child != NULL; child = child->
next)
{
+ if (XSTREQ(child->name, "uuid")) {
+ STRPROP(filter, uuid, child);
+ } else if (XSTREQ(child->name, "rule")) {
+ rule = malloc(sizeof(*rule));
+ if (rule == NULL)
+ goto err;
+
+ if (parse_acl_rule(child, rule) == 0)
+ goto err;
+
+ append_filter_rule(filter, rule);
+ }
+ else if (XSTREQ(child->name, "filterref")) {
+ filter_ref = get_attr_value(child, "filter");
+ if (filter_ref == NULL)
+ goto err;
+
+ append_filter_ref(filter, filter_ref);
+ }
+ }
+
+ return 1;
+
+ err:
+ cleanup_filter(filter);
+
+ return 0;
+}
+
+/* Dummy function to suppress error message from libxml2 */
+static void swallow_err_msg(void *ctx, const char *msg, ...)
+{
+ /* do nothing, just swallow the message. */
+}
+
+int get_filter_from_xml(const char *xml, struct acl_filter **filter)
+{
+ xmlDoc *xmldoc = NULL;
+
+ if (xml == NULL || filter == NULL)
+ return 0;
+
+ xmlSetGenericErrorFunc(NULL, swallow_err_msg);
+
+ xmldoc = xmlParseMemory(xml, strlen(xml) + 1);
+ if (xmldoc == NULL)
+ goto err;
+
+ *filter = malloc(sizeof(**filter));
+
+ memset(*filter, 0, sizeof(**filter));
+ parse_acl_filter(xmldoc->children, *filter);
+
+ err:
+ xmlSetGenericErrorFunc(NULL, NULL);
+ xmlFreeDoc(xmldoc);
+
+ return 1;
+}
+
+int get_filter_by_name(
+ virConnectPtr conn,
+ const char *name,
+ struct acl_filter **filter)
+{
+ virNWFilterPtr vfilter = NULL;
+ char *xml = NULL;
+
+ if (name == NULL || filter == NULL)
+ return 0;
+
+ vfilter = virNWFilterLookupByName(conn, name);
+
+ xml = virNWFilterGetXMLDesc(vfilter, 0);
+
+ virNWFilterFree(vfilter);
+
+ if (xml == NULL)
+ return 0;
+
+ get_filter_from_xml(xml, filter);
+
+ return 1;
+}
+
+int get_filter_by_uuid(
+ virConnectPtr conn,
+ const char *uuid,
+ struct acl_filter **filter)
+{
+ virNWFilterPtr vfilter = NULL;
+ char *xml = NULL;
+
+ if (uuid == NULL || filter == NULL)
+ return 0;
+
+ vfilter = virNWFilterLookupByUUIDString(conn, uuid);
+
+ xml = virNWFilterGetXMLDesc(vfilter, 0);
+
+ virNWFilterFree(vfilter);
+
+ if (xml == NULL)
+ return 0;
+
+ get_filter_from_xml(xml, filter);
+
+ return 1;
+}
+
+int get_filters(
+ virConnectPtr conn,
+ struct acl_filter **list)
+{
+ int count = 0;
+ char **names = NULL;
+ struct acl_filter *filters = NULL;
+ int i = 0;
+
+ count = virConnectNumOfNWFilters(conn);
+
+ names = calloc(count, sizeof(char *));
+ if (names == NULL)
+ goto err;
+
+ virConnectListNWFilters(conn, names, count);
+
+ filters = malloc(count * sizeof(struct acl_filter));
+ if (filters == NULL)
+ goto err;
+
+ for(i = 0; i < count; i++)
+ {
+ struct acl_filter *filter = NULL;
+
+ get_filter_by_name(conn, names[i], &filter);
+
+ memcpy(&filters[i], filter, sizeof(*filter));
+ }
+
+ *list = filters;
+
+ err:
+ free(names);
+
+ return i;
+}
+
+
+int append_filter_rule(struct acl_filter *filter, struct acl_rule *rule)
+{
+ struct acl_rule **old_rules = NULL;
+
+ if ((filter == NULL) || (rule == NULL))
+ return 0;
+
+ rule->name = make_rule_id(filter->name, filter->rule_ct);
+ if (rule->name == NULL)
+ return 0;
+
+ old_rules = filter->rules;
+
+ filter->rules =
+ malloc((filter->rule_ct + 1) * sizeof(struct acl_rule
*));
+
+ memcpy(filter->rules,
+ old_rules,
+ filter->rule_ct * sizeof(struct acl_rule *));
+
+ filter->rules[filter->rule_ct] = rule;
+ filter->rule_ct++;
+
+ free(old_rules);
+
+ return 1;
+}
+
+int append_filter_ref(struct acl_filter *filter, char *name)
+{
+ int i;
+ char **old_refs = NULL;
+
+ if ((filter == NULL) || (name == NULL))
+ return 0;
+
+ for (i = 0; i < filter->ref_ct; i++)
+ if (STREQC(filter->refs[i], name))
+ return 0; /* already exists */
+
+ old_refs = filter->refs;
+
+ filter->refs = malloc((filter->ref_ct + 1) * sizeof(char *));
+ memcpy(filter->refs, old_refs, filter->ref_ct * sizeof(char *));
+
+ filter->refs[filter->ref_ct] = name;
+ filter->ref_ct++;
+
+ free(old_refs);
+
+ return 1;
+}
+
+char *make_rule_id(const char *filter, int index)
+{
+ int ret;
+ char *rule_id = NULL;
+
+ if (filter == NULL)
+ return NULL;
+
+ ret = asprintf(&rule_id, "%s:%u", filter, index);
+ if (ret == -1) {
+ free(rule_id);
+ rule_id = NULL;
+ }
+
+
+ return rule_id;
+}
+
+int parse_rule_id(const char *rule_id, char **filter, int *index)
+{
+ int ret;
+
+ if ((filter == NULL) || (index == NULL))
+ return 0;
+ ret = sscanf(rule_id, "%as[^:]:%u", filter, index);
+ if (ret != 2) {
+ free(*filter);
+ *filter = NULL;
+
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/libxkutil/acl_parsing.h b/libxkutil/acl_parsing.h
new file mode 100644
--- /dev/null
+++ b/libxkutil/acl_parsing.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+#ifndef __ACL_PARSING_H
+#define __ACL_PARSING_H
+
+#include <libvirt/libvirt.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+
+struct acl_mac_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *protocol_id;
+ char *comment;
+};
+
+struct acl_arp_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *hw_type;
+ char *protocol_type;
+ char *opcode;
+ char *arpsrcmacaddr;
+ char *arpdstmacaddr;
+ char *arpsrcipaddr;
+ char *arpdstipaddr;
+ char *comment;
+};
+
+struct acl_ip_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *srcipaddr;
+ char *srcipmask;
+ char *dstipaddr;
+ char *dstipmask;
+
+ char *protocol;
+
+ char *srcportstart;
+ char *srcportend;
+ char *dstportstart;
+ char *dstportend;
+
+ char *comment;
+};
+
+struct acl_tcp_rule {
+ char *srcmacaddr;
+
+ char *srcipaddr;
+ char *srcipmask;
+ char *dstipaddr;
+ char *dstipmask;
+
+ char *srcipfrom;
+ char *srcipto;
+ char *dstipfrom;
+ char *dstipto;
+
+ char *srcportstart;
+ char *srcportend;
+ char *dstportstart;
+ char *dstportend;
+
+ char *comment;
+ char *state;
+};
+
+struct acl_igmp_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *srcipaddr;
+ char *srcipmask;
+ char *dstipaddr;
+ char *dstipmask;
+
+ char *srcipfrom;
+ char *srcipto;
+ char *dstipfrom;
+ char *dstipto;
+
+ char *type;
+ char *code;
+ char *comment;
+ char *state;
+};
+
+struct acl_icmp_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *srcipaddr;
+ char *srcipmask;
+ char *dstipaddr;
+ char *dstipmask;
+
+ char *srcipfrom;
+ char *srcipto;
+ char *dstipfrom;
+ char *dstipto;
+
+ char *type;
+ char *code;
+ char *comment;
+ char *state;
+};
+
+struct acl_rule {
+ char *name;
+ char *protocol_id;
+ char *action;
+ char *direction;
+ char *priority;
+ char *statematch;
+
+ enum {
+ UNKNOWN_RULE,
+ MAC_RULE,
+ ARP_RULE,
+ IP_RULE,
+ TCP_RULE,
+ ICMP_RULE,
+ IGMP_RULE
+ } type;
+
+ union {
+ struct acl_mac_rule mac;
+ struct acl_arp_rule arp;
+ struct acl_ip_rule ip;
+ struct acl_tcp_rule tcp;
+ struct acl_icmp_rule icmp;
+ struct acl_igmp_rule igmp;
+ } var;
+};
+
+struct acl_filter {
+ char *uuid;
+ char *name;
+ char *chain;
+
+ struct acl_rule **rules;
+ int rule_ct;
+
+ char **refs;
+ int ref_ct;
+};
+
+void cleanup_rule(struct acl_rule *rule);
+void cleanup_filter(struct acl_filter *filter);
+void cleanup_filters(struct acl_filter **filters, int count);
+
+int get_filters(virConnectPtr conn, struct acl_filter **list);
+
+int get_filter_from_xml(const char *xml, struct acl_filter **filter);
+int get_filter_by_uuid(virConnectPtr conn, const char *uuid,
+ struct acl_filter **filter);
+int get_filter_by_name(virConnectPtr conn, const char *name,
+ struct acl_filter **filter);
+
+char *make_rule_id(const char *filter, int index);
+int parse_rule_id(const char *rule_id, char **filter, int *index);
+
+/** NOTE: Both append functions take parameters allocated by caller and
+ * freed by cleanup_filter(s)
+ */
+int append_filter_rule(struct acl_filter *filter, struct acl_rule
*rule);
+int append_filter_ref(struct acl_filter *filter, char *name);
+#endif
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/libxkutil/device_parsing.c b/libxkutil/device_parsing.c
--- a/libxkutil/device_parsing.c
+++ b/libxkutil/device_parsing.c
@@ -80,6 +80,7 @@
free(dev->model);
free(dev->device);
free(dev->net_mode);
+ free(dev->filter_ref);
}
static void cleanup_emu_device(struct emu_device *dev)
@@ -386,9 +387,12 @@
ndev->model = get_attr_value(child, "type");
if (ndev->model == NULL)
goto err;
+ } else if (XSTREQ(child->name, "filterref")) {
+ ndev->filter_ref = get_attr_value(child,
"filter");
} else if (XSTREQ(child->name,
"virtualport")) {
parse_vsi_device(child, ndev);
}
+
}
if (ndev->source == NULL)
@@ -764,6 +768,7 @@
DUP_FIELD(dev, _dev, dev.net.model);
DUP_FIELD(dev, _dev, dev.net.device);
DUP_FIELD(dev, _dev, dev.net.net_mode);
+ DUP_FIELD(dev, _dev, dev.net.filter_ref);
DUP_FIELD(dev, _dev, dev.net.vsi.vsi_type);
DUP_FIELD(dev, _dev, dev.net.vsi.manager_id);
DUP_FIELD(dev, _dev, dev.net.vsi.type_id);
diff --git a/libxkutil/device_parsing.h b/libxkutil/device_parsing.h
--- a/libxkutil/device_parsing.h
+++ b/libxkutil/device_parsing.h
@@ -64,6 +64,7 @@
char *model;
char *device;
char *net_mode;
+ char *filter_ref;
struct vsi_device vsi;
};
diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c
--- a/libxkutil/xmlgen.c
+++ b/libxkutil/xmlgen.c
@@ -301,6 +301,15 @@
xmlNewProp(tmp, BAD_CAST "type", BAD_CAST
net->model);
}
+ if (net->filter_ref != NULL) {
+ tmp = xmlNewChild(nic, NULL,
+ BAD_CAST "filterref", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "filter",
+ BAD_CAST net->filter_ref);
+ }
+
if (STREQ(dev->dev.net.type, "network"))
msg = set_net_source(nic, net, "network");
else if (STREQ(dev->dev.net.type, "bridge"))
diff --git a/libxkutil/xmlgen.h b/libxkutil/xmlgen.h
--- a/libxkutil/xmlgen.h
+++ b/libxkutil/xmlgen.h
@@ -23,6 +23,7 @@
#include "device_parsing.h"
#include "pool_parsing.h"
+#include "acl_parsing.h"
#include "cmpidt.h"
@@ -38,4 +39,6 @@
char *res_to_xml(struct virt_pool_res *res);
+char *filter_to_xml(struct acl_filter *filter);
+
#endif
diff --git a/schema/AppliedFilterList.mof b/schema/AppliedFilterList.mof
new file mode 100644
--- /dev/null
+++ b/schema/AppliedFilterList.mof
@@ -0,0 +1,8 @@
+// Copyright IBM Corp. 2011
+[Association,
+ Provider("cmpi::Virt_AppliedFilterList")]
+class KVM_AppliedFilterList : CIM_ConcreteDependency
+{
+ CIM_NetworkPort ref Antecedent;
+ CIM_FilterList ref Dependent;
+};
diff --git a/schema/AppliedFilterList.registration b/schema/
AppliedFilterList.registration
new file mode 100644
--- /dev/null
+++ b/schema/AppliedFilterList.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+KVM_AppliedFilterList root/virt Virt_AppliedFilterList
Virt_AppliedFilterList association
diff --git a/schema/EntriesInFilterList.mof
b/schema/EntriesInFilterList.mof
new file mode 100644
--- /dev/null
+++ b/schema/EntriesInFilterList.mof
@@ -0,0 +1,6 @@
+// Copyright IBM Corp. 2011
+[Association,
+ Provider("cmpi::Virt_EntriesInFilterList")]
+class KVM_EntriesInFilterList : CIM_EntriesInFilterList
+{
+};
diff --git a/schema/EntriesInFilterList.registration b/schema/
EntriesInFilterList.registration
new file mode 100644
--- /dev/null
+++ b/schema/EntriesInFilterList.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+KVM_EntriesInFilterList root/virt Virt_EntriesInFilterList
Virt_EntriesInFilterList association
diff --git a/schema/FilterEntry.mof b/schema/FilterEntry.mof
new file mode 100644
--- /dev/null
+++ b/schema/FilterEntry.mof
@@ -0,0 +1,60 @@
+// Copyright IBM Corp. 2011
+[Provider("cmpi::Virt_FilterEntry")]
+class KVM_Hdr8021Filter : CIM_Hdr8021Filter
+{
+ [Description("This defines whether the Filter is used for input,
"
+ "output, or both input and output filtering. All
values are
"
+ "used with respect to the interface for which
the Filter
"
+ "applies. \"Not Applicable\" (0) is
used when there is
no "
+ "direction applicable to the Filter.
\"Input\" (1) is "
+ "used when the Filter applies to packets that are
inbound
"
+ "on the related interface. \"Output\"
(2) is used when
the "
+ "Filter applies to packets that are outbound on
the "
+ "related interface. \"Both\" (3) is used to indicate
that "
+ "the direction is immaterial, e.g., to filter
on a
source "
+ "subnet regardless of whether the flow is
inbound or "
+ "outbound."),
+ ValueMap { "0", "1", "2", "3",
"4" },
+ Values { "Not Applicable", "Input, Output",
"Both",
"Mirrored" }]
+ uint16 Direction;
+
+ [Description("The priority of the rule controls the order in
which
"
+ "the rule will be, instantiated relative to
other rules.
"
+ "Rules with lower value will be instantiated
and
therefore "
+ "evaluated before rules with higher value.
Valid values
are "
+ "in the range of 0 to 1000. If this attribute
is not "
+ "provided, the value 500 will automatically be
assigned."),
+ MinValue(0),
+ MaxValue(1000)]
+ uint16 Priority = 500;
+};
+
+[Provider("cmpi::Virt_FilterEntry")]
+class KVM_IPHeadersFilter : CIM_IPHeadersFilter
+{
+ [Description("This defines whether the Filter is used for input,
"
+ "output, or both input and output filtering. All
values are
"
+ "used with respect to the interface for which
the Filter
"
+ "applies. \"Not Applicable\" (0) is
used when there is
no "
+ "direction applicable to the Filter.
\"Input\" (1) is "
+ "used when the Filter applies to packets that are
inbound
"
+ "on the related interface. \"Output\"
(2) is used when
the "
+ "Filter applies to packets that are outbound on
the "
+ "related interface. \"Both\" (3) is used to indicate
that "
+ "the direction is immaterial, e.g., to filter
on a
source "
+ "subnet regardless of whether the flow is
inbound or "
+ "outbound."),
+ ValueMap { "0", "1", "2", "3",
"4" },
+ Values { "Not Applicable", "Input, Output",
"Both",
"Mirrored" }]
+ uint16 Direction;
+
+ [Description("The priority of the rule controls the order in
which
"
+ "the rule will be, instantiated relative to
other rules.
"
+ "Rules with lower value will be instantiated
and
therefore "
+ "evaluated before rules with higher value.
Valid values
are "
+ "in the range of 0 to 1000. If this attribute
is not "
+ "provided, the value 500 will automatically be
assigned."),
+ MinValue(0),
+ MaxValue(1000)]
+ uint16 Priority = 500;
+};
diff --git a/schema/FilterEntry.registration
b/schema/FilterEntry.registration
new file mode 100644
--- /dev/null
+++ b/schema/FilterEntry.registration
@@ -0,0 +1,4 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+KVM_Hdr8021Filter root/virt Virt_FilterEntry Virt_FilterEntry instance
+KVM_IPHeadersFilter root/virt Virt_FilterEntry Virt_FilterEntry instance
diff --git a/schema/FilterList.mof b/schema/FilterList.mof
new file mode 100644
--- /dev/null
+++ b/schema/FilterList.mof
@@ -0,0 +1,4 @@
+// Copyright IBM Corp. 2011
+class KVM_FilterList : CIM_FilterList
+{
+};
diff --git a/schema/FilterList.registration
b/schema/FilterList.registration
new file mode 100755
--- /dev/null
+++ b/schema/FilterList.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+KVM_FilterList root/virt Virt_FilterList Virt_FilterList instance
diff --git a/schema/HostedFilterList.mof b/schema/HostedFilterList.mof
new file mode 100644
--- /dev/null
+++ b/schema/HostedFilterList.mof
@@ -0,0 +1,6 @@
+// Copyright IBM Corp. 2011
+[Association,
+ Provider("cmpi::Virt_HostedFilterList")]
+class KVM_HostedFilterList : CIM_HostedFilterList
+{
+};
diff --git a/schema/HostedFilterList.registration b/schema/
HostedFilterList.registration
new file mode 100644
--- /dev/null
+++ b/schema/HostedFilterList.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+KVM_HostedFilterList root/virt Virt_HostedFilterList
Virt_HostedFilterList association
diff --git a/schema/NestedFilterList.mof b/schema/NestedFilterList.mof
new file mode 100644
--- /dev/null
+++ b/schema/NestedFilterList.mof
@@ -0,0 +1,8 @@
+// Copyright IBM Corp. 2011
+[Association,
+ Provider("cmpi::Virt_NestedFilterList")]
+class KVM_NestedFilterList : CIM_ConcreteDependency
+{
+ CIM_FilterList ref Antecedent;
+ CIM_FilterList ref Dependent;
+};
diff --git a/schema/NestedFilterList.registration b/schema/
NestedFilterList.registration
new file mode 100644
--- /dev/null
+++ b/schema/NestedFilterList.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+KVM_NestedFilterList root/virt Virt_NestedFilterList
Virt_NestedFilterList association
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,7 +23,9 @@
Virt_VSMigrationSettingData.h \
Virt_ConsoleRedirectionService.h \
Virt_ConsoleRedirectionServiceCapabilities.h \
- Virt_KVMRedirectionSAP.h
+ Virt_KVMRedirectionSAP.h \
+ Virt_FilterList.h \
+ Virt_FilterEntry.h
XKUADD = $(top_builddir)/libxkutil/libxkutil.la
@@ -77,7 +79,13 @@
libVirt_ServiceAffectsElement.la \
libVirt_HostedAccessPoint.la \
libVirt_ServiceAccessBySAP.la \
- libVirt_SAPAvailableForElement.la
+ libVirt_SAPAvailableForElement.la \
+ libVirt_FilterList.la \
+ libVirt_FilterEntry.la \
+ libVirt_EntriesInFilterList.la \
+ libVirt_NestedFilterList.la \
+ libVirt_HostedFilterList.la \
+ libVirt_AppliedFilterList.la
libVirt_ComputerSystem_la_SOURCES = Virt_ComputerSystem.c
libVirt_ComputerSystem_la_DEPENDENCIES =
libVirt_VirtualSystemSnapshotService.la
@@ -243,3 +251,26 @@
libVirt_SAPAvailableForElement_la_SOURCES =
Virt_SAPAvailableForElement.c
libVirt_SAPAvailableForElement_la_LIBADD = -lVirt_ComputerSystem -
lVirt_KVMRedirectionSAP
+libVirt_FilterEntry_la_DEPENDENCIES = libVirt_HostSystem.la
+libVirt_FilterEntry_la_SOURCES = Virt_FilterEntry.c
+libVirt_FilterEntry_la_LIBADD = -lVirt_HostSystem
+
+libVirt_FilterList_la_DEPENDENCIES = libVirt_HostSystem.la
+libVirt_FilterList_la_SOURCES = Virt_FilterList.c
+libVirt_FilterList_la_LIBADD = -lVirt_HostSystem
+
+libVirt_EntriesInFilterList_la_DEPENDENCIES =
libVirt_FilterEntry.la libVirt_FilterList.la
+libVirt_EntriesInFilterList_la_SOURCES = Virt_EntriesInFilterList.c
+libVirt_EntriesInFilterList_la_LIBADD = -lVirt_FilterEntry
-lVirt_FilterList
+
+libVirt_NestedFilterList_la_DEPENDENCIES = libVirt_FilterList.la
+libVirt_NestedFilterList_la_SOURCES = Virt_NestedFilterList.c
+libVirt_NestedFilterList_la_LIBADD = -lVirt_FilterList
+
+libVirt_HostedFilterList_la_DEPENDENCIES = libVirt_HostSystem.la
libVirt_FilterList.la
+libVirt_HostedFilterList_la_SOURCES = Virt_HostedFilterList.c
+libVirt_HostedFilterList_la_LIBADD = -lVirt_HostSystem -lVirt_FilterList
+
+libVirt_AppliedFilterList_la_DEPENDENCIES = libVirt_Device.la
libVirt_FilterList.la
+libVirt_AppliedFilterList_la_SOURCES = Virt_AppliedFilterList.c
+libVirt_AppliedFilterList_la_LIBADD = -lVirt_Device -lVirt_FilterList
diff --git a/src/Virt_AppliedFilterList.c b/src/Virt_AppliedFilterList.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_AppliedFilterList.c
@@ -0,0 +1,634 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_association.h>
+#include <libcmpiutil/std_instance.h>
+
+#include "device_parsing.h"
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "cs_util.h"
+
+#include "Virt_Device.h"
+#include "Virt_FilterList.h"
+
+static const CMPIBroker *_BROKER;
+
+/* TODO: Port to libcmpiutil/args_util.c */
+/**
+ * Get a reference property of an instance
+ *
+ * @param inst The instance
+ * @param prop The property name
+ * @param reference A pointer to a CMPIObjectPath* that will be set
+ * if successful
+ * @returns
+ * - CMPI_RC_OK on success
+ * - CMPI_RC_ERR_NO_SUCH_PROPERTY if prop is not present
+ * - CMPI_RC_ERR_TYPE_MISMATCH if prop is not a reference
+ * - CMPI_RC_OK otherwise
+ */
+static CMPIrc cu_get_ref_prop(const CMPIInstance *instance,
+ const char *prop,
+ CMPIObjectPath **reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIData value;
+
+ /* REQUIRE_PROPERY_DEFINED(instance, prop, value, &s); */
+ value = CMGetProperty(instance, prop, &s);
+ if ((s.rc != CMPI_RC_OK) || CMIsNullValue(value))
+ return CMPI_RC_ERR_NO_SUCH_PROPERTY;
+
+ if ((value.type != CMPI_ref) || CMIsNullObject
(value.value.ref))
+ return CMPI_RC_ERR_TYPE_MISMATCH;
+
+ *reference = value.value.ref;
+
+ return CMPI_RC_OK;
+}
+
+/* TODO: Port to libcmpiutil/args_util.c */
+/**
+ * Get a reference component of an object path
+ *
+ * @param _reference The reference
+ * @param key The key name
+ * @param reference A pointer to a CMPIObjectPath* that will be set
+ * if successful
+ * @returns
+ * - CMPI_RC_OK on success
+ * - CMPI_RC_ERR_NO_SUCH_PROPERTY if prop is not present
+ * - CMPI_RC_ERR_TYPE_MISMATCH if prop is not a reference
+ * - CMPI_RC_OK otherwise
+ */
+static CMPIrc cu_get_ref_path(const CMPIObjectPath *reference,
+ const char *key,
+ CMPIObjectPath **_reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIData value;
+
+ /* REQUIRE_PROPERY_DEFINED(instance, prop, value, &s); */
+ value = CMGetKey(reference, key, &s);
+ if ((s.rc != CMPI_RC_OK) || CMIsNullValue(value))
+ return CMPI_RC_ERR_NO_SUCH_PROPERTY;
+
+ /* how to parse and object path? */
+
+ return CMPI_RC_OK;
+}
+
+/* TODO: Port to libxkutil/device_parsing.c */
+static int update_device(virDomainPtr dom,
+ struct virt_device *dev)
+{
+ char *xml = NULL;
+ int flags = VIR_DOMAIN_DEVICE_MODIFY_CURRENT |
+ VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
+ int ret = 0;
+
+ /** device_to_xml() is not exported, so this function needs
+ * to be moved
+ */
+
+ /* xml = device_to_xml(dev); */
+
+ if (xml == NULL) {
+ CU_DEBUG("Failed to get XML for device '%s'",
dev->id);
+ goto out;
+ }
+
+ if (virDomainUpdateDeviceFlags(dom, xml, flags) != 0) {
+ CU_DEBUG("Failed to dynamically update device:");
+ CU_DEBUG("%s", xml);
+ goto out;
+ }
+
+ ret = 1;
+ out:
+ free(xml);
+
+ return ret;
+}
+
+/* TODO: Port to libxkutil/device_parsing.c */
+static int get_device_by_devid(virDomainPtr dom,
+ const char *devid,
+ int type,
+ struct virt_device **dev)
+{
+ int i, ret = 0;
+ struct virt_device *devices = NULL;
+ int count = get_devices(dom, &devices, type);
+
+ for (i = 0; i < count; i++) {
+ if (STREQC(devid, devices[i].id)) {
+ CU_DEBUG("Found '%s'", devices[i].id);
+
+ *dev = virt_device_dup(&devices[i]);
+ if (*dev != NULL)
+ ret = 1;
+
+ break;
+ }
+ }
+
+ cleanup_virt_devices(&devices, count);
+
+ return ret;
+}
+
+/**
+ * given a filter, get the network interface
+ */
+static CMPIStatus list_to_net(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ const char *name = NULL;
+ struct acl_filter *filter = NULL;
+ virDomainPtr *doms = NULL;
+ virConnectPtr conn = NULL;
+ int i, j, dcount, ncount;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ /* validate filter */
+ get_filter_by_name(conn, name, &filter);
+ if (filter == NULL)
+ goto out;
+
+ cleanup_filter(filter);
+
+ /* get domains */
+ dcount = get_domain_list(conn, &doms);
+ if (dcount < 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to get domain list");
+ goto out;
+ }
+
+ for (i = 0; i < dcount; i++) {
+ /* get domain's network devices */
+ struct virt_device *devices = NULL;
+ ncount = get_devices(doms[i], &devices,
CIM_RES_TYPE_NET);
+
+ CU_DEBUG("Found %u network devices", ncount);
+
+ for (j = 0; j < ncount; j++) {
+ struct net_device *ndev = &(devices[j].dev.net);
+
+ CU_DEBUG("filterref = %s", ndev->filter_ref);
+
+ if ((ndev->filter_ref != NULL) &&
+ STREQC(name, ndev->filter_ref)) {
+ CU_DEBUG("Getting network device
instance");
+
+ CMPIInstance *instance = NULL;
+ char *device_id =
+ get_fq_devid(
+ (char *)virDomainGetName(doms
[i]),
+ devices[j].id);
+
+ CU_DEBUG("Processing %s", device_id);
+
+ s = get_device_by_name(_BROKER,
+ reference,
+ device_id,
+
CIM_RES_TYPE_NET,
+
&instance);
+
+ if (instance != NULL) {
+ CU_DEBUG("adding instance to
list");
+ inst_list_add(list,
instance);
+ }
+ }
+ }
+
+ cleanup_virt_devices(&devices, ncount);
+ virDomainFree(doms[i]);
+ }
+
+ out:
+ virConnectClose(conn);
+
+ return s;
+}
+
+/**
+ * given a network interface, find the filter lists
+ */
+static CMPIStatus net_to_list(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+ const char *device_name = NULL;
+ char *domain_name = NULL;
+ char *net_name = NULL;
+ virConnectPtr conn = NULL;
+ virDomainPtr dom = NULL;
+ int i;
+ struct acl_filter *filter = NULL;
+
+ CU_DEBUG("Reference %s", REF2STR(reference));
+
+ /* validate device
+ * TODO: This may be redundant since it's necessary to get
+ * the device structure in order to determine the filter_ref
+ */
+ if (!STREQC(CLASSNAME(reference), "KVM_NetworkPort"))
+ goto out;
+
+ s = get_device_by_ref(_BROKER, reference, &instance);
+ if ((s.rc != CMPI_RC_OK) || (instance == NULL))
+ goto out;
+
+ if (cu_get_str_path(reference, "DeviceID",
+ &device_name) != CMPI_RC_OK) {
+ CU_DEBUG("Failed to get DeviceID");
+ goto out;
+ }
+
+ if (parse_fq_devid(device_name, &domain_name, &net_name) == 0) {
+ CU_DEBUG("Failed to parse devid");
+ goto out;
+ }
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ /* connect to domain */
+ dom = virDomainLookupByName(conn, domain_name);
+ if (dom == NULL) {
+ CU_DEBUG("Failed to connect to Domain '%s'",
domain_name);
+ goto out;
+ }
+
+ /* get domain's network devices */
+ struct virt_device *devices = NULL;
+ int count = get_devices(dom, &devices, CIM_RES_TYPE_NET);
+
+ CU_DEBUG("Found %u net devices on dom '%s'", count,
domain_name);
+
+ for (i = 0; i < count; i++) {
+ struct net_device *ndev = &(devices[i].dev.net);
+
+ CU_DEBUG("Checking net device '%s' for filterref",
+ devices[i].id);
+
+ if (STREQC(device_name, devices[i].id)) {
+ CMPIInstance *instance = NULL;
+
+ CU_DEBUG("Processing %s", ndev->filter_ref);
+
+ get_filter_by_name(conn, ndev->filter_ref,
&filter);
+ if (filter == NULL)
+ continue;
+
+ s = instance_from_filter(_BROKER,
+ info->context,
+ reference,
+ filter,
+ &instance);
+
+ if (instance != NULL)
+ inst_list_add(list, instance);
+
+ }
+
+ }
+
+ cleanup_virt_devices(&devices, count);
+ out:
+
+ free(domain_name);
+ free((char *)device_name);
+ free(net_name);
+
+ virDomainFree(dom);
+ virConnectClose(conn);
+
+ return s;
+}
+
+LIBVIRT_CIM_DEFAULT_MAKEREF()
+
+static char *antecedent[] = {
+ "KVM_FilterList",
+ NULL
+};
+
+static char *dependent[] = {
+ "KVM_NetworkPort",
+ NULL
+};
+
+static char *assoc_class_name[] = {
+ "KVM_AppliedFilterList",
+ NULL
+};
+
+static struct std_assoc _list_to_net = {
+ .source_class = (char **)&antecedent,
+ .source_prop = "Antecedent",
+
+ .target_class = (char **)&dependent,
+ .target_prop = "Dependent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = list_to_net,
+ .make_ref = make_ref
+};
+
+static struct std_assoc _net_to_list = {
+ .source_class = (char **)&dependent,
+ .source_prop = "Dependent",
+
+ .target_class = (char **)&antecedent,
+ .target_prop = "Antecedent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = net_to_list,
+ .make_ref = make_ref
+};
+
+static struct std_assoc *handlers[] = {
+ &_list_to_net,
+ &_net_to_list,
+ NULL
+};
+
+STDA_AssocMIStub(,
+ Virt_AppliedFilterList,
+ _BROKER,
+ libvirt_cim_init(),
+ handlers);
+
+DEFAULT_GI();
+DEFAULT_EIN();
+DEFAULT_EI();
+
+static CMPIStatus CreateInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIInstance *instance)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIObjectPath *antecedent = NULL;
+ const char *filter_name = NULL;
+ struct acl_filter *filter = NULL;
+ CMPIObjectPath *dependent = NULL;
+ char *domain_name = NULL;
+ const char *device_name = NULL;
+ char *net_name = NULL;
+ struct virt_device *device = NULL;
+ virConnectPtr conn = NULL;
+ virDomainPtr dom = NULL;
+
+ if (cu_get_ref_prop(instance, "Antecedent",
+ &antecedent) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Antecedent property");
+ goto out;
+ }
+
+ if (cu_get_str_path(reference, "Name", &filter_name) !=
CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Antecedent.Name property");
+ goto out;
+ }
+
+ get_filter_by_name(conn, filter_name, &filter);
+ if (filter == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Antecedent.Name object does not exist");
+ goto out;
+ }
+
+ if (cu_get_ref_prop(instance, "Dependent",
+ &dependent) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Dependent property");
+ goto out;
+ }
+
+ if (cu_get_str_path(reference, "DeviceID",
+ &device_name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Dependent.DeviceID property");
+ goto out;
+ }
+
+ if (parse_fq_devid(device_name, &domain_name, &net_name) == 0) {
+ CU_DEBUG("Failed to parse devid");
+ goto out;
+ }
+
+ dom = virDomainLookupByName(conn, domain_name);
+ if (dom == NULL) {
+ CU_DEBUG("Failed to connect to Domain '%s'",
domain_name);
+ goto out;
+ }
+
+ get_device_by_devid(dom, net_name, CIM_RES_TYPE_NET, &device);
+ if (device == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Dependent.Name object does not exist");
+ goto out;
+ }
+
+ free(device->dev.net.filter_ref);
+ device->dev.net.filter_ref = strdup(filter_name);
+
+ if (update_device(dom, device) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to update device");
+ goto out;
+ }
+
+ out:
+ free((char *)filter_name);
+ free(domain_name);
+ free((char *)device_name);
+ free(net_name);
+
+ cleanup_filter(filter);
+ cleanup_virt_device(device);
+
+ virDomainFree(dom);
+ virConnectClose(conn);
+
+ return s;
+}
+
+static CMPIStatus DeleteInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIObjectPath *antecedent = NULL;
+ const char *filter_name = NULL;
+ struct acl_filter *filter = NULL;
+ CMPIObjectPath *dependent = NULL;
+ char *domain_name = NULL;
+ const char *device_name = NULL;
+ char *net_name = NULL;
+ struct virt_device *device = NULL;
+ virConnectPtr conn = NULL;
+ virDomainPtr dom = NULL;
+
+ if (cu_get_ref_path(reference, "Antecedent",
+ &antecedent) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Antecedent property");
+ goto out;
+ }
+
+ if (cu_get_str_path(reference, "Name", &filter_name) !=
CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Antecedent.Name property");
+ goto out;
+ }
+
+ get_filter_by_name(conn, filter_name, &filter);
+ if (filter == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Antecedent.Name object does not exist");
+ goto out;
+ }
+
+ if (cu_get_ref_path(reference, "Dependent",
+ &dependent) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Dependent property");
+ goto out;
+ }
+
+ if (cu_get_str_path(reference, "DeviceID",
+ &device_name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Dependent.DeviceID property");
+ goto out;
+ }
+
+ if (parse_fq_devid(device_name, &domain_name, &net_name) == 0) {
+ CU_DEBUG("Failed to parse devid");
+ goto out;
+ }
+
+ dom = virDomainLookupByName(conn, domain_name);
+ if (dom == NULL) {
+ CU_DEBUG("Failed to connect to Domain '%s'",
domain_name);
+ goto out;
+ }
+
+ get_device_by_devid(dom, net_name, CIM_RES_TYPE_NET, &device);
+ if (device == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Dependent.Name object does not exist");
+ goto out;
+ }
+
+ free(device->dev.net.filter_ref);
+ device->dev.net.filter_ref = NULL;
+
+ if (update_device(dom, device) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to update device");
+ goto out;
+ }
+
+ out:
+ free((char *)filter_name);
+ free(domain_name);
+ free((char *)device_name);
+ free(net_name);
+
+ cleanup_filter(filter);
+ cleanup_virt_device(device);
+
+ virDomainFree(dom);
+ virConnectClose(conn);
+
+ return s;
+}
+
+DEFAULT_MI();
+DEFAULT_EQ();
+DEFAULT_INST_CLEANUP();
+
+STD_InstanceMIStub(,
+ Virt_AppliedFilterEntry,
+ _BROKER,
+ libvirt_cim_init());
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_EntriesInFilterList.c
b/src/Virt_EntriesInFilterList.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_EntriesInFilterList.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_association.h>
+
+#include <strings.h>
+
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "Virt_FilterList.h"
+#include "Virt_FilterEntry.h"
+
+static const CMPIBroker *_BROKER;
+
+/**
+ * given a filter, find all *direct* children
+ */
+static CMPIStatus list_to_rule(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+ struct acl_filter *filter = NULL;
+ const char *name = NULL;
+ virConnectPtr conn = NULL;
+ int i;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ get_filter_by_name(conn, name, &filter);
+ if (filter == NULL) {
+ CU_DEBUG("Filter '%s' does not exist", name);
+ goto out;
+ }
+
+ for (i = 0; i < filter->rule_ct; i++) {
+ CU_DEBUG("Processing %s", filter->rules[i]->name);
+
+ s = instance_from_rule(_BROKER,
+ info->context,
+ reference,
+ filter->rules[i],
+ &instance);
+
+ if (instance != NULL) {
+ inst_list_add(list, instance);
+ instance = NULL;
+ }
+ }
+
+ cleanup_filter(filter);
+
+ out:
+ virConnectClose(conn);
+
+ return s;
+}
+
+/**
+ * given a rule, fine the parent filter
+ */
+static CMPIStatus rule_to_list(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct acl_filter *filters = NULL;
+ CMPIInstance *instance = NULL;
+ const char *name = NULL;
+ virConnectPtr conn = NULL;
+ int count = 0;
+ int i, j = 0;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ count = get_filters(conn, &filters);
+ if (filters == NULL)
+ goto out;
+
+ /* return the filter that contains the rule */
+ for (i = 0; i < count; i++) {
+ for (j = 0; j < filters[i].rule_ct; j++) {
+ if (STREQC(name, filters[i].rules[j]->name)) {
+ CU_DEBUG("Processing %s,",filters
[i].name);
+
+ s = instance_from_filter(_BROKER,
+ info->context,
+ reference,
+ &filters[i],
+ &instance);
+
+ if (instance != NULL) {
+ inst_list_add(list, instance);
+ instance = NULL;
+ }
+
+ }
+ }
+ }
+
+ out:
+ cleanup_filters(&filters, count);
+ virConnectClose(conn);
+
+ return s;
+}
+
+LIBVIRT_CIM_DEFAULT_MAKEREF()
+
+static char *group_component[] = {
+ "KVM_FilterList",
+ NULL
+};
+
+static char *part_component[] = {
+ "KVM_Hdr8021Filter",
+ "KVM_IPHeadersFilter",
+ NULL
+};
+
+static char *assoc_class_name[] = {
+ "KVM_EntriesInFilterList",
+ NULL
+};
+
+static struct std_assoc _list_to_rule = {
+ .source_class = (char **)&group_component,
+ .source_prop = "GroupComponent",
+
+ .target_class = (char **)&part_component,
+ .target_prop = "PartComponent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = list_to_rule,
+ .make_ref = make_ref
+};
+
+static struct std_assoc _rule_to_list = {
+ .source_class = (char **)&part_component,
+ .source_prop = "PartComponent",
+
+ .target_class = (char **)&group_component,
+ .target_prop = "GroupComponent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = rule_to_list,
+ .make_ref = make_ref
+};
+
+static struct std_assoc *handlers[] = {
+ &_list_to_rule,
+ &_rule_to_list,
+ NULL
+};
+
+STDA_AssocMIStub(,
+ Virt_EntriesInFilterList,
+ _BROKER,
+ libvirt_cim_init(),
+ handlers);
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_FilterEntry.c b/src/Virt_FilterEntry.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_FilterEntry.c
@@ -0,0 +1,678 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_instance.h>
+
+#include <arpa/inet.h>
+
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "xmlgen.h"
+
+#include "Virt_FilterEntry.h"
+#include "Virt_HostSystem.h"
+
+const static CMPIBroker *_BROKER;
+
+static bool is_mac_rule(int type)
+{
+ if (type == MAC_RULE || type == ARP_RULE)
+ return 1;
+
+ return 0;
+}
+
+static bool is_ip_rule(int type)
+{
+ if (type == IP_RULE || type == TCP_RULE || type == ICMP_RULE ||
+ type == IGMP_RULE)
+ return 1;
+
+ return 0;
+}
+
+static int octets_from_mac(const char * s, unsigned int *buffer,
+ unsigned int size)
+{
+ unsigned int _buffer[6];
+ unsigned int i, n = 0;
+
+ if ((s == 0) || (s[0] == '\0') || (buffer == NULL) || (size <
6))
+ return 0;
+
+ if (s[0] == '$') {
+ for (i = 0; (s[i] != '\0') && (i < size); i++)
+ buffer[i] = s[i];
+
+ n = i;
+ }
+ else {
+ n = sscanf(s, "%x:%x:%x:%x:%x:%x",
+ &_buffer[0], &_buffer[1], &_buffer[2],
+ &_buffer[3], &_buffer[4], &_buffer[5]);
+
+ for (i = 0; (i < n) && (i < size); i++)
+ buffer[i] = _buffer[i];
+ }
+
+ return n;
+}
+
+static int octets_from_ip(const char * s, unsigned int *buffer,
+ unsigned int size)
+{
+ struct in6_addr addr;
+ unsigned int family = 0;
+ unsigned int i, n = 0;
+
+ if ((s == 0) || (s[0] == '\0') || (buffer == NULL) || (size <
4))
+ return 0;
+
+ if (s[0] == '$') {
+ for (i = 0; (s[i] != '\0') && (i < size); i++)
+ buffer[i] = s[i];
+
+ n = i;
+ }
+ else {
+ family = strstr(s, ":") ? AF_INET6 : AF_INET;
+ n = family == AF_INET6 ? 16 : 4;
+
+ if (size < n)
+ return 0;
+
+ if (inet_pton(family, s, &addr)) {
+ n = n <= size ? n : size;
+ for (i = 0; i < n; i++)
+ buffer[i] = addr.s6_addr[i];
+ }
+ }
+
+ return n;
+}
+
+static CMPIArray *octets_to_cmpi(const CMPIBroker *broker, unsigned
int *bytes, int size)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIArray *array = NULL;
+ int i;
+
+ if (bytes == 0 || size == 0)
+ return array;
+
+ array = CMNewArray(broker, size, CMPI_uint8, &s);
+
+ for (i = 0; i < size; i++) {
+ s = CMSetArrayElementAt(array, i,
+ (CMPIValue*)&bytes[i], CMPI_uint8);
+ }
+
+ return array;
+}
+
+static int convert_direction(const char *s)
+{
+ enum {NOT_APPLICABLE, INPUT, OUTPUT, BOTH} direction =
NOT_APPLICABLE;
+
+ if (s != NULL) {
+ if (STREQC(s, "in"))
+ direction = INPUT;
+ else if (STREQC(s, "out"))
+ direction = OUTPUT;
+ else if (STREQC(s, "inout"))
+ direction = BOTH;
+ }
+
+ return direction;
+}
+
+static int convert_priority(const char *s)
+{
+ int priority = 0;
+
+ if (s != NULL) {
+ priority = atoi(s);
+ }
+
+ return priority;
+}
+
+static CMPIInstance *convert_mac_rule_to_instance(
+ struct acl_rule *rule,
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIStatus *s)
+{
+ CMPIInstance *inst = NULL;
+ const char *sys_name = NULL;
+ const char *sys_ccname = NULL;
+ int direction, priority = 0;
+ unsigned int bytes[48];
+ unsigned int size = 0;
+ CMPIArray *array = NULL;
+
+ inst = get_typed_instance(broker,
+ CLASSNAME(reference),
+ "Hdr8021Filter",
+ NAMESPACE(reference));
+ if (inst == NULL) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get 8021 filter instance");
+
+ goto out;
+ }
+
+ *s = get_host_system_properties(&sys_name,
+ &sys_ccname,
+ reference,
+ broker,
+ context);
+
+ if (s->rc != CMPI_RC_OK) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get host attributes");
+ goto out;
+ }
+
+ CMSetProperty(inst, "SystemName", sys_name, CMPI_chars);
+ CMSetProperty(inst, "SystemCreationClassName", sys_ccname,
CMPI_chars);
+ CMSetProperty(inst, "Name", (CMPIValue *)rule->name,
CMPI_chars);
+
+ direction = convert_direction(rule->direction);
+ CMSetProperty(inst, "Direction", (CMPIValue *)&direction,
CMPI_uint16);
+
+ priority = convert_priority(rule->priority);
+ CMSetProperty(inst, "Priority", (CMPIValue *)&priority,
CMPI_uint16);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_mac(rule->var.mac.srcmacaddr,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcMACAddr8021",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_mac(rule->var.mac.srcmacmask,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcMACMask8021",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_mac(rule->var.mac.dstmacaddr,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestMACAddr8021", (CMPIValue *)
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_mac(rule->var.mac.dstmacmask,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestMACMask8021", (CMPIValue *)
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ out:
+ return inst;
+}
+
+static CMPIInstance *convert_ip_rule_to_instance(
+ struct acl_rule *rule,
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIStatus *s)
+{
+ CMPIInstance *inst = NULL;
+ const char *sys_name = NULL;
+ const char *sys_ccname = NULL;
+ int direction, priority = 0;
+ unsigned int bytes[48];
+ unsigned int size = 0;
+ unsigned int n = 0;
+ CMPIArray *array = NULL;
+
+ inst = get_typed_instance(broker,
+ CLASSNAME(reference),
+ "IPHeadersFilter",
+ NAMESPACE(reference));
+ if (inst == NULL) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get ip headers filter instance");
+ goto out;
+ }
+
+ *s = get_host_system_properties(&sys_name,
+ &sys_ccname,
+ reference,
+ broker,
+ context);
+
+ if (s->rc != CMPI_RC_OK) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get host attributes");
+ goto out;
+ }
+
+ CMSetProperty(inst, "SystemName", sys_name, CMPI_chars);
+ CMSetProperty(inst, "SystemCreationClassName", sys_ccname,
CMPI_chars);
+ CMSetProperty(inst, "Name", (CMPIValue *)rule->name,
CMPI_chars);
+
+ direction = convert_direction(rule->direction);
+ CMSetProperty(inst, "Direction", (CMPIValue *)&direction,
CMPI_uint16);
+
+ priority = convert_priority(rule->priority);
+ CMSetProperty(inst, "Priority", (CMPIValue *)&priority,
CMPI_uint16);
+
+ if (strstr(rule->protocol_id, "v6"))
+ n = 6;
+ else
+ n = 4;
+
+ CMSetProperty(inst, "HdrIPVersion",(CMPIValue *)&n, CMPI_uint8);
+
+ if (rule->var.tcp.srcipfrom && rule->var.tcp.srcipto) {
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.srcipfrom,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcAddress",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.srcipto,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcAddressEndOfRange",
+ (CMPIValue *)&array, CMPI_uint8A);
+ } else {
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.srcmacaddr,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcAddress",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.srcipmask,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcMask",
+ (CMPIValue *)&array, CMPI_uint8A);
+ }
+
+ if (rule->var.tcp.dstipfrom && rule->var.tcp.dstipto) {
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.dstipfrom,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestAddress",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.dstipto,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestAddressEndOfRange",
+ (CMPIValue *)&array, CMPI_uint8A);
+ } else {
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.dstipaddr,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestAddress",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.dstipmask,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestMask",
+ (CMPIValue *)&array, CMPI_uint8A);
+ }
+
+ if ((rule->type == IP_RULE) || (rule->type == TCP_RULE)) {
+ if (rule->var.tcp.srcportstart) {
+ n = atoi(rule->var.tcp.srcportstart);
+ CMSetProperty(inst, "HdrSrcPortStart",
+ (CMPIValue *)&n, CMPI_uint16);
+ }
+
+ if (rule->var.tcp.srcportend) {
+ n = atoi(rule->var.tcp.srcportend);
+ CMSetProperty(inst, "HdrSrcPortEnd",
+ (CMPIValue *)&n, CMPI_uint16);
+ }
+
+ if (rule->var.tcp.dstportstart) {
+ n = atoi(rule->var.tcp.dstportstart);
+ CMSetProperty(inst, "HdrDestPortStart",
+ (CMPIValue *)&n, CMPI_uint16);
+ }
+
+ if (rule->var.tcp.dstportend) {
+ n = atoi(rule->var.tcp.dstportend);
+ CMSetProperty(inst, "HdrDestPortEnd",
+ (CMPIValue *)&n, CMPI_uint16);
+ }
+ }
+
+ out:
+ return inst;
+}
+
+static CMPIInstance *convert_rule_to_instance(
+ struct acl_rule *rule,
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIStatus *s)
+{
+ CMPIInstance *instance = NULL;
+
+ if (rule == NULL)
+ return NULL;
+
+ if(is_mac_rule(rule->type)) {
+ instance = convert_mac_rule_to_instance(rule,
+ broker,
+ context,
+ reference,
+ s);
+ }
+ else if(is_ip_rule(rule->type)) {
+ instance = convert_ip_rule_to_instance(rule,
+ broker,
+ context,
+ reference,
+ s);
+ }
+
+ return instance;
+}
+
+CMPIStatus enum_filter_rules(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct inst_list *list)
+{
+ virConnectPtr conn = NULL;
+ struct acl_filter *filters = NULL;
+ int i, j, count = 0;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ enum {NONE, MAC, IP} class_type = NONE;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (STREQC(CLASSNAME(reference), "KVM_Hdr8021Filter"))
+ class_type = MAC;
+ else if (STREQC(CLASSNAME(reference), "KVM_IPHeadersFilter"))
+ class_type = IP;
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ count = get_filters(conn, &filters);
+
+ for (i = 0; i < count; i++) {
+ for (j = 0; j < filters[i].rule_ct; j++) {
+ CMPIInstance *instance = NULL;
+
+ if (((class_type == NONE) ||
+ (class_type == MAC)) &&
+ is_mac_rule(filters[i].rules[j]->type))
{
+ instance =
convert_mac_rule_to_instance(
+ filters[i].rules[j],
+ broker,
+ context,
+ reference,
+ &s);
+ }
+ else if (((class_type == NONE) ||
+ (class_type == IP)) &&
+ is_ip_rule(filters[i].rules[j]->type)) {
+ instance = convert_ip_rule_to_instance(
+ filters[i].rules[j],
+ broker,
+ context,
+ reference,
+ &s);
+ }
+ else
+ CU_DEBUG("Unrecognized rule type %u",
+ filters[i].rules[j]->type);
+
+ if (instance != NULL)
+ inst_list_add(list, instance);
+ }
+
+ }
+
+ out:
+ cleanup_filters(&filters, count);
+ virConnectClose(conn);
+
+ return s;
+}
+
+CMPIStatus get_rule_by_ref(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIInstance **instance)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct acl_filter *filter = NULL;
+ struct acl_rule *rule = NULL;
+ const char *name = NULL;
+ char *filter_name = NULL;
+ int rule_index;
+ virConnectPtr conn = NULL;
+ int i;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ if (parse_rule_id(name, &filter_name, &rule_index) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Could not parse filter name");
+ goto out;
+ }
+
+ CU_DEBUG("Filter name = %s, rule index = %u", filter_name,
rule_index);
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ get_filter_by_name(conn, filter_name, &filter);
+ if (filter == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Could not retrieve filter");
+ goto out;
+ }
+
+ for (i = 0; i < filter->rule_ct; i++) {
+ if (rule_index == i) {
+ rule = filter->rules[i];
+ break;
+ }
+ }
+
+ if (rule == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Could not retrieve rule");
+ goto out;
+ }
+
+ *instance = convert_rule_to_instance(rule,
+ broker,
+ context,
+ reference,
+ &s);
+ out:
+ free(filter_name);
+ cleanup_filter(filter);
+ virConnectClose(conn);
+
+ return s;
+}
+
+CMPIStatus instance_from_rule(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct acl_rule *rule,
+ CMPIInstance **instance)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+
+ *instance = convert_rule_to_instance(rule,
+ broker,
+ context,
+ reference,
+ &s);
+
+ return s;
+
+}
+
+static CMPIStatus GetInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const char **properties)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+
+ s = get_rule_by_ref(_BROKER, context, reference, &instance);
+
+ if (instance != NULL)
+ CMReturnInstance(results, instance);
+
+ return s;
+}
+
+static CMPIStatus EnumInstanceNames(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct inst_list list;
+
+ inst_list_init(&list);
+
+ s = enum_filter_rules(_BROKER, context, reference, &list);
+
+ cu_return_instance_names(results, &list);
+
+ inst_list_free(&list);
+
+ return s;
+}
+
+static CMPIStatus EnumInstances(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const char **properties)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct inst_list list;
+
+ inst_list_init(&list);
+
+ s = enum_filter_rules(_BROKER, context, reference, &list);
+
+ cu_return_instances(results, &list);
+
+ return s;
+}
+
+DEFAULT_CI();
+DEFAULT_MI();
+DEFAULT_DI();
+DEFAULT_EQ();
+DEFAULT_INST_CLEANUP();
+
+STD_InstanceMIStub(,
+ Virt_FilterEntry,
+ _BROKER,
+ libvirt_cim_init());
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_FilterEntry.h b/src/Virt_FilterEntry.h
new file mode 100644
--- /dev/null
+++ b/src/Virt_FilterEntry.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+#ifndef __VIRT_FILTERENTRY_H
+#define __VIRT_FILTERENTRY_H
+
+/**
+ * Return a list of filter instances
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class
name
+ * prefix), but can also be used to scope the results
by
+ * specifying the parent filter
+ * @param list A pointer to an array of CMPIInstance objects
+ * (called inits before and frees after)
+ */
+CMPIStatus enum_filter_rules(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct inst_list *list);
+
+/**
+ * Return a single filter instance by reference
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class
name
+ * prefix), but can also be used to scope the results
by
+ * specifying the parent filter
+ * @param list A pointer to a CMPIInstance *
+ */
+CMPIStatus get_rule_by_ref(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIInstance **instance);
+
+/**
+ * Get an instance representing a filter rule
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class
name
+ * prefix), but can also be used to scope the results
by
+ * specifying the parent filter
+ * @param rule A pointer to a filter rule
+ * @param instance A pointer to a CMPIInstance *
+ */
+CMPIStatus instance_from_rule(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct acl_rule *rule,
+ CMPIInstance **instance);
+
+#endif
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_FilterList.c b/src/Virt_FilterList.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_FilterList.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_instance.h>
+
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "xmlgen.h"
+
+#include "Virt_FilterList.h"
+#include "Virt_HostSystem.h"
+
+const static CMPIBroker *_BROKER;
+
+static CMPIInstance *convert_filter_to_instance(
+ struct acl_filter *filter,
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIStatus *s)
+{
+ CMPIInstance *inst = NULL;
+ const char *sys_name = NULL;
+ const char *sys_ccname = NULL;
+ int direction = 0;
+
+ inst = get_typed_instance(broker,
+ CLASSNAME(reference),
+ "FilterList",
+ NAMESPACE(reference));
+ if (inst == NULL) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get filter list instance");
+ goto out;
+ }
+
+ *s = get_host_system_properties(&sys_name,
+ &sys_ccname,
+ reference,
+ broker,
+ context);
+
+ if (s->rc != CMPI_RC_OK) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get host attributes");
+ goto out;
+ }
+
+ CMSetProperty(inst, "SystemName", sys_name, CMPI_chars);
+ CMSetProperty(inst, "SystemCreationClassName", sys_ccname,
CMPI_chars);
+ CMSetProperty(inst, "Name", (CMPIValue *)filter->name,
CMPI_chars);
+ CMSetProperty(inst, "InstanceID", (CMPIValue
*)filter->uuid,
+ CMPI_chars);
+ CMSetProperty(inst, "Direction", (CMPIValue *)&direction,
CMPI_uint16);
+
+ out:
+ return inst;
+}
+
+CMPIStatus enum_filter_lists(const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct inst_list *list)
+{
+ virConnectPtr conn = NULL;
+ struct acl_filter *filters = NULL;
+ int i, count = 0;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+
+ conn = connect_by_classname(broker, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ count = get_filters(conn, &filters);
+
+ CU_DEBUG("found %d filters", count);
+
+ for (i = 0; i < count; i++) {
+ instance = convert_filter_to_instance(&filters[i],
+ broker,
+ context,
+ reference,
+ &s);
+
+ if (instance != NULL)
+ inst_list_add(list, instance);
+ }
+
+ out:
+ cleanup_filters(&filters, count);
+ virConnectClose(conn);
+
+ return s;
+}
+
+CMPIStatus get_filter_by_ref(const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIInstance **instance)
+{
+ virConnectPtr conn = NULL;
+ struct acl_filter *filter = NULL;
+
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ const char *name = NULL;
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ conn = connect_by_classname(broker, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ get_filter_by_name(conn, name, &filter);
+ if (filter == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "No such instance (Name)");
+ goto out;
+ }
+
+ s = instance_from_filter(broker, context, reference,
filter, instance);
+
+ out:
+ cleanup_filter(filter);
+ virConnectClose(conn);
+
+ return s;
+}
+
+CMPIStatus instance_from_filter(const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct acl_filter *filter,
+ CMPIInstance **instance)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+
+ *instance = convert_filter_to_instance(filter, broker, context,
+ reference, &s);
+
+ return s;
+}
+
+static CMPIStatus GetInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const char **properties)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+
+ s = get_filter_by_ref(_BROKER, context, reference, &instance);
+
+ if (instance != NULL)
+ CMReturnInstance(results, instance);
+
+ return s;
+}
+
+static CMPIStatus EnumInstanceNames(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct inst_list list;
+
+ inst_list_init(&list);
+
+ s = enum_filter_lists(_BROKER, context, reference, &list);
+
+ cu_return_instance_names(results, &list);
+
+ inst_list_free(&list);
+
+ return s;
+}
+
+static CMPIStatus EnumInstances(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const char **properties)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct inst_list list;
+
+ inst_list_init(&list);
+
+ s = enum_filter_lists(_BROKER, context, reference, &list);
+
+ cu_return_instances(results, &list);
+
+ inst_list_free(&list);
+
+ return s;
+}
+
+DEFAULT_CI();
+DEFAULT_MI();
+DEFAULT_DI();
+DEFAULT_EQ();
+DEFAULT_INST_CLEANUP();
+
+STD_InstanceMIStub(,
+ Virt_FilterList,
+ _BROKER,
+ libvirt_cim_init());
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_FilterList.h b/src/Virt_FilterList.h
new file mode 100644
--- /dev/null
+++ b/src/Virt_FilterList.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+#ifndef __VIRT_FILTERLIST_H
+#define __VIRT_FILTERLIST_H
+
+#include "acl_parsing.h"
+
+/**
+ * Return a list of filter lists
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class
name
+ * prefix), but can also be used to scope the results
by
+ * specifying a specific filter
+ * @param list A pointer to an array of CMPIInstance objects
+ * (caller inits before and frees after)
+ */
+CMPIStatus enum_filter_lists(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct inst_list *list);
+
+/**
+ * Return a filter instance by reference
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class
name
+ * prefix), but can also be used to scope the results
by
+ * specifying a specific filter
+ * @param instance A pointer to a CMPIInstance * to place the new
instance
+ */
+CMPIStatus get_filter_by_ref(
+ const CMPIBroker *broker,
+ const CMPIContext *contest,
+ const CMPIObjectPath *reference,
+ CMPIInstance **instance);
+
+/**
+ * Return a list of filter lists
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class
name
+ * prefix), but can also be used to scope the results
by
+ * specifying a specific filter
+ * @param filter A pointer to a acl_filter
+ * @param instance A pointer to a CMPIInstance * to place the new
instance
+ */
+CMPIStatus instance_from_filter(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct acl_filter *filter,
+ CMPIInstance **instance);
+
+#endif
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_HostedFilterList.c b/src/Virt_HostedFilterList.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_HostedFilterList.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_association.h>
+
+#include "misc_util.h"
+#include "Virt_HostSystem.h"
+#include "Virt_FilterList.h"
+
+static const CMPIBroker *_BROKER;
+
+static CMPIStatus host_to_list(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+
+ /* validate host reference */
+ s = get_host(_BROKER, info->context, reference, &instance,
false);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ s = cu_validate_ref(_BROKER, reference, instance);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ s = enum_filter_lists(_BROKER, info->context, reference, list);
+
+ out:
+ return s;
+}
+
+static CMPIStatus list_to_host(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+
+ /* validate filter reference */
+ s = get_filter_by_ref(_BROKER, info->context, reference,
&instance);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ s = get_host(_BROKER, info->context, reference, &instance,
false);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ if (instance != NULL)
+ inst_list_add(list, instance);
+
+ out:
+ return s;
+}
+
+LIBVIRT_CIM_DEFAULT_MAKEREF()
+
+static char *antecedent[] = {
+ "KVM_HostSystem",
+ NULL
+};
+
+static char *dependent[] = {
+ "KVM_FilterList",
+ NULL
+};
+
+static char *assoc_class_name[] = {
+ "KVM_HostedFilterList",
+ NULL
+};
+
+static struct std_assoc _host_to_list = {
+ .source_class = (char **)&antecedent,
+ .source_prop = "Antecedent",
+
+ .target_class = (char **)&dependent,
+ .target_prop = "Dependent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = host_to_list,
+ .make_ref = make_ref
+};
+
+static struct std_assoc _list_to_host = {
+ .source_class = (char **)&dependent,
+ .source_prop = "Dependent",
+
+ .target_class = (char **)&antecedent,
+ .target_prop = "Antecedent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = list_to_host,
+ .make_ref = make_ref
+};
+
+static struct std_assoc *handlers[] = {
+ &_host_to_list,
+ &_list_to_host,
+ NULL
+};
+
+STDA_AssocMIStub(,
+ Virt_HostedFilterList,
+ _BROKER,
+ libvirt_cim_init(),
+ handlers);
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_NestedFilterList.c b/src/Virt_NestedFilterList.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_NestedFilterList.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_association.h>
+#include <libcmpiutil/std_instance.h>
+
+/* FIXME: This seems to be needed to compile STREQC, which suggests
+ * libcmpiutil.h needs to add the include since the marco is defined
there.
+ */
+#include <string.h>
+#include <strings.h>
+
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "Virt_FilterList.h"
+
+static const CMPIBroker *_BROKER;
+
+/**
+ * given a filter, find all *direct* filter_refs
+ */
+static CMPIStatus parent_to_child(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct acl_filter *parent_filter = NULL;
+ struct acl_filter *child_filter = NULL;
+ CMPIInstance *instance = NULL;
+ const char * name = NULL;
+ virConnectPtr conn = NULL;
+ int i;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ get_filter_by_name(conn, name, &parent_filter);
+ if (parent_filter == NULL)
+ goto out;
+
+ for (i = 0; i < parent_filter->ref_ct; i++) {
+ get_filter_by_name(conn, parent_filter->refs[i],
+ &child_filter);
+ if (child_filter == NULL)
+ continue;
+
+ CU_DEBUG("Processing %s,", child_filter->name);
+
+ s = instance_from_filter(_BROKER,
+ info->context,
+ reference,
+ child_filter,
+ &instance);
+
+ if (instance != NULL) {
+ CU_DEBUG("Adding instance to inst_list");
+ inst_list_add(list, instance);
+ }
+
+ cleanup_filter(child_filter);
+
+ child_filter = NULL;
+ instance = NULL;
+ }
+
+ cleanup_filter(parent_filter);
+
+ out:
+ virConnectClose(conn);
+
+ return s;
+}
+
+/**
+ * given a filter, find all the other filters that reference it
+ */
+static CMPIStatus child_to_parent(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct acl_filter *_list = NULL;
+ CMPIInstance *instance = NULL;
+ const char *name = NULL;
+ virConnectPtr conn = NULL;
+ int count, i, j;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ /* TODO: Ensure the referenced filter exists */
+
+ count = get_filters(conn, &_list);
+ if (_list == NULL)
+ goto out;
+
+ /* return any filter that has name in refs */
+ for (i = 0; i < count; i++) {
+ for (j = 0; j < _list[i].ref_ct; j++) {
+ if (STREQC(name, _list[i].refs[j])) {
+ CU_DEBUG("Processing %s,", _list
[i].name);
+
+ s = instance_from_filter(_BROKER,
+ info->context,
+ reference,
+ &_list[i],
+ &instance);
+
+ if (instance != NULL)
+ inst_list_add(list, instance);
+
+ instance = NULL;
+ }
+
+ }
+
+ cleanup_filter(&_list[i]);
+ }
+
+ free(_list);
+
+ out:
+ virConnectClose(conn);
+
+ return s;
+}
+
+LIBVIRT_CIM_DEFAULT_MAKEREF()
+
+static char *antecedent[] = {
+ "KVM_FilterList",
+ NULL
+};
+
+static char *dependent[] = {
+ "KVM_FilterList",
+ NULL
+};
+
+static char *assoc_class_name[] = {
+ "KVM_NestedFilterList",
+ NULL
+};
+
+static struct std_assoc _list_to_filter_ref = {
+ .source_class = (char **)&antecedent,
+ .source_prop = "Antecedent",
+
+ .target_class = (char **)&dependent,
+ .target_prop = "Dependent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = parent_to_child,
+ .make_ref = make_ref
+};
+
+static struct std_assoc _filter_ref_to_list = {
+ .source_class = (char **)&dependent,
+ .source_prop = "Dependent",
+
+ .target_class = (char **)&antecedent,
+ .target_prop = "Antecedent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = child_to_parent,
+ .make_ref = make_ref
+};
+
+static struct std_assoc *handlers[] = {
+ &_list_to_filter_ref,
+ &_filter_ref_to_list,
+ NULL
+};
+
+STDA_AssocMIStub(,
+ Virt_NestedFilterList,
+ _BROKER,
+ libvirt_cim_init(),
+ handlers);
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
_______________________________________________
Libvirt-cim mailing list
Libvirt-cim(a)redhat.com
https://www.redhat.com/mailman/listinfo/libvirt-cim