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@redhat.com wrote on 05/26/2011 10:08:43 PM:
> Chip Vincent <cvincent@linux.vnet.ibm.com>
> Sent by: libvirt-cim-bounces@redhat.com
>
> 05/26/11 10:08 PM
>
> Please respond to
> List for discussion and development of libvirt CIM <libvirt-cim@redhat.com>
>
> To
>
> libvirt-cim@redhat.com
>
> cc
>
> Subject
>
> [Libvirt-cim] [PATCH] (#2) Add DCN ACL classes & providers
>
> # HG changeset patch
> # User Chip Vincent <cvincent@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@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@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@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@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@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@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@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@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@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@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@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@redhat.com
> https://www.redhat.com/mailman/listinfo/libvirt-cim