[Libvirt-cim] [PATCH] (#2) Add DCN ACL classes & providers

Sharad Mishra snmishra at us.ibm.com
Tue Jun 7 01:29:46 UTC 2011


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 at redhat.com wrote on 05/26/2011 10:08:43 PM:

> Chip Vincent <cvincent at linux.vnet.ibm.com>
> Sent by: libvirt-cim-bounces at redhat.com
>
> 05/26/11 10:08 PM
>
> Please respond to
> List for discussion and development of libvirt CIM
<libvirt-cim at redhat.com>
>
> To
>
> libvirt-cim at redhat.com
>
> cc
>
> Subject
>
> [Libvirt-cim] [PATCH] (#2) Add DCN ACL classes & providers

>
> # HG changeset patch
> # User Chip Vincent <cvincent at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at redhat.com
> https://www.redhat.com/mailman/listinfo/libvirt-cim
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/libvirt-cim/attachments/20110606/a75ba13f/attachment.htm>


More information about the Libvirt-cim mailing list