[PATCH] Cimtest: Use python xml to parse virsh net-dumpxml output
by Eduardo Lima (Etrunko)
# HG changeset patch
# User Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
# Date 1306533151 10800
# Node ID 51bd999e881e96c8c2af698a7968d00b7009aaf2
# Parent 589512c8ddff8224f16fbaa4348cc17df4d0536a
Cimtest: Use python xml to parse virsh net-dumpxml output
Signed-off-by: Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
diff --git a/suites/libvirt-cim/lib/XenKvmLib/vxml.py b/suites/libvirt-cim/lib/XenKvmLib/vxml.py
--- a/suites/libvirt-cim/lib/XenKvmLib/vxml.py
+++ b/suites/libvirt-cim/lib/XenKvmLib/vxml.py
@@ -38,6 +38,12 @@
import pywbem
from xml.dom import minidom, Node
from xml import xpath
+
+try:
+ from xml.etree import cElementTree as ElementTree
+except:
+ from xml.etree import ElementTree
+
from VirtLib import utils, live
from XenKvmLib.xm_virt_util import get_bridge_from_network_xml, bootloader, \
net_list
@@ -210,6 +216,17 @@
else:
vbr = bridgename
return vbr
+ # get_valid_bridge_name
+
+ def _parse_net_dumpxml(_xml):
+ try:
+ root = ElementTree.fromstring(_xml)
+ ip_element = root.find("ip")
+ return ip_element.get("address")
+ except:
+ logger.error("Encounter error dump netxml")
+ return None
+ # _parse_net_dumpxml
self.vbr = get_valid_bridge_name(server)
if self.vbr is None:
@@ -223,7 +240,7 @@
self.server = server
if is_new_net is False:
- cmd = "virsh net-dumpxml %s 2>/dev/null" % self.net_name
+ cmd = "virsh -c %s net-dumpxml %s 2>/dev/null" % (self.vuri, self.net_name)
s, net_xml = utils.run_remote(server, cmd)
if s != 0:
logger.error("Encounter error dump netxml")
@@ -245,10 +262,13 @@
n_list = net_list(server, virt)
for _net_name in n_list:
- cmd = "virsh net-dumpxml %s 2>/dev/null | \
- awk '/ip address/ {print}' | \
- cut -d ' ' -f 4 | sed 's/address=//'" % _net_name
- s, in_use_addr = utils.run_remote(server, cmd)
+ cmd = "virsh -c %s net-dumpxml %s 2>/dev/null" % (self.vuri, _net_name)
+ s, xml = utils.run_remote(server, cmd)
+
+ in_use_addr = _parse_net_dumpxml(xml)
+ if in_use_addr is None:
+ logger.error("Unable to find IP address")
+ return None
sub_net_in_use = in_use_addr
sub_net_in_use = sub_net_in_use.rsplit('.', 1)[0].strip("'") + "."
@@ -310,7 +330,7 @@
self.server = server
if is_new_pool is False:
- cmd = "virsh pool-dumpxml %s 2>/dev/null" % self.pool_name
+ cmd = "virsh -c %s pool-dumpxml %s 2>/dev/null" % (self.vuri, self.pool_name)
s, disk_xml = utils.run_remote(server, cmd)
if s != 0:
logger.error("Encounter error dump netxml")
13 years, 5 months
[PATCH] #2 Cimtest: Handle keyboard interrupt
by Eduardo Lima (Etrunko)
# HG changeset patch
# User Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
# Date 1306522145 10800
# Node ID c8670eeacbb02db390825e4dda776a2a4cf67ff8
# Parent 01aa645a1e1269eb31d1fdd9de8d7e9120f5fa74
Cimtest: Handle keyboard interrupt
During my tests I have noticed that if the user interrupts the program
execution, by pressing Ctrl+C, the next time cimtest runs, it will fail
due to leftovers of previous execution, especially, a disk pool called
cimtest-diskpool and a network called cimtest-netpool.
With this patch, if a KeyboardInterrupt exception occurs, the
cleanup_env() function will be called before the program exit.
Changes from #1:
* Avoid NameError (ret) if another exception other than
KeyboardInterrupt occurs
Signed-off-by: Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
diff --git a/suites/libvirt-cim/main.py b/suites/libvirt-cim/main.py
--- a/suites/libvirt-cim/main.py
+++ b/suites/libvirt-cim/main.py
@@ -176,8 +176,7 @@
testsuite.debug("%s %sh | %smin | %ssec | %smsec" %
(prefix, h, m, s, msec))
-def main():
- (options, args) = parser.parse_args()
+def main(options, args):
to_addr = None
from_addr = None
relay = None
@@ -302,7 +301,21 @@
(from_addr, to_addr, relay)
send_report(to_addr, from_addr, relay, msg_body, heading)
+ return 0
+# main()
+
if __name__ == '__main__':
- sys.exit(main())
+ ret = -1
+ try:
+ options, args = parser.parse_args()
+ ret = main(options, args)
+ except (KeyboardInterrupt, SystemExit):
+ print "\nKeyboardInterrupt. Cleaning up..."
+ status = cleanup_env(options.ip, options.virt)
+ if status != PASS:
+ print "Unable to clean up. Please check your environment."
+ else:
+ print "Clean up successful"
+ sys.exit(ret)
13 years, 5 months
[PATCH] Update RPM spec file to match Fedora
by Eduardo Lima (Etrunko)
# HG changeset patch
# User Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
# Date 1306874177 10800
# Node ID da242202e48891c6003c21817ecf67844b91b1a6
# Parent f934d53d40ef2521b6b8242c06a58db84f85f71f
Update RPM spec file to match Fedora
Signed-off-by: Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
diff --git a/libvirt-cim.spec.in b/libvirt-cim.spec.in
--- a/libvirt-cim.spec.in
+++ b/libvirt-cim.spec.in
@@ -10,11 +10,13 @@
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
URL: http://libvirt.org/CIM/
Requires: libxml2 >= 2.6.0
-Requires: libvirt >= 0.6.3
+Requires: libvirt >= 0.6.4
Requires: unzip
+Requires: tog-pegasus
+BuildRequires: libcmpiutil >= 0.5.4
BuildRequires: tog-pegasus-devel
-BuildRequires: libvirt-devel >= 0.5.4
-BuildRequires: e2fsprogs-devel
+BuildRequires: libvirt-devel >= 0.6.4
+BuildRequires: libuuid-devel
BuildRequires: libxml2-devel
BuildRequires: libcmpiutil-devel
BuildConflicts: sblim-cmpi-devel
@@ -27,11 +29,11 @@
%prep
%setup -q
-chmod -x src/* libxkutil/* schema/* README doc/* base_schema/README*
-chmod +X src/* libxkutil/* schema/*
%build
%configure --disable-werror
+sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool
+sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool
make %{?_smp_mflags}
%install
@@ -43,6 +45,9 @@
rm -f $RPM_BUILD_ROOT%{_libdir}/cmpi/*.la
rm -f $RPM_BUILD_ROOT%{_libdir}/cmpi/*.a
rm -f $RPM_BUILD_ROOT%{_libdir}/libxkutil.so
+mkdir -p $RPM_BUILD_ROOT/etc/ld.so.conf.d
+echo %{_libdir}/cmpi > $RPM_BUILD_ROOT/etc/ld.so.conf.d/libvirt-cim.conf
+mkdir -p $RPM_BUILD_ROOT@INFO_STORE@
%clean
rm -fr $RPM_BUILD_ROOT
@@ -60,17 +65,19 @@
%define CIMV2_REG %{_datadir}/%{name}/{HostedResourcePool,ElementCapabilities,HostedService,HostedDependency,ElementConformsToProfile,HostedAccessPoint}.registration
%define CIMV2_MOF %{_datadir}/%{name}/{HostedResourcePool,ElementCapabilities,HostedService,HostedDependency,RegisteredProfile,ComputerSystem,ElementConformsToProfile,HostedAccessPoint}.mof
+# _If_ there is already a version of this installed, we must deregister
+# the classes we plan to install in post, otherwise we may corrupt
+# the pegasus repository. This is convention in other provider packages
%{_datadir}/%{name}/provider-register.sh -d -t pegasus \
-n @CIM_VIRT_NS@ \
-r %{REGISTRATION} -m %{SCHEMA} >/dev/null 2>&1 || true
%post
/sbin/ldconfig
-mkdir -p @INFO_STORE@
%{_datadir}/%{name}/install_base_schema.sh %{_datadir}/%{name}
-/etc/init.d/tog-pegasus restart
+/etc/init.d/tog-pegasus condrestart
%{_datadir}/%{name}/provider-register.sh -t pegasus \
-n @CIM_VIRT_NS@ \
@@ -93,25 +100,34 @@
-n @CIM_VIRT_NS@ \
-r %{REGISTRATION} -m %{SCHEMA} >/dev/null 2>&1 || true
%{_datadir}/%{name}/provider-register.sh -d -t pegasus \
- -n root/PG_InterOp \
- -r %{PGINTEROP_REG} -m %{PGINTEROP_MOF} >/dev/null 2>&1 || true
+ -n root/interop \
+ -r %{INTEROP_REG} -m %{INTEROP_MOF} >/dev/null 2>&1 || true
+%{_datadir}/%{name}/provider-register.sh -d -t pegasus \
+ -n root/PG_InterOp \
+ -r %{PGINTEROP_REG} -m %{PGINTEROP_MOF} >/dev/null 2>&1 || true
+%{_datadir}/%{name}/provider-register.sh -d -t pegasus \
+ -n root/cimv2 \
+ -r %{CIMV2_REG} -m %{CIMV2_MOF} >/dev/null 2>&1 || true
%postun -p /sbin/ldconfig
-%files
+%files
%defattr(-, root, root)
+%{_sysconfdir}/libvirt/cim
%doc README COPYING doc/CodingStyle doc/SubmittingPatches
%doc base_schema/README.DMTF
%doc doc/*.html
%{_libdir}/lib*.so*
%{_libdir}/cmpi/lib*.so*
+%{_datadir}/libvirt-cim
%{_datadir}/libvirt-cim/*.sh
%{_datadir}/libvirt-cim/*.mof
%{_datadir}/libvirt-cim/cimv*-interop_mof
%{_datadir}/libvirt-cim/cimv*-cimv2_mof
%{_datadir}/libvirt-cim/*.registration
%{_datadir}/libvirt-cim/cim_schema_*-MOFs.zip
+%{_sysconfdir}/ld.so.conf.d/libvirt-cim.conf
%changelog
* Wed Oct 28 2009 Richard Maciel <rmaciel(a)linux.vnet.ibm.com> - 0.1-1
13 years, 5 months
[PATCH] (#2) Add DCN ACL classes & providers
by Chip Vincent
# HG changeset patch
# User Chip Vincent <cvincent(a)us.ibm.com>
# Date 1305221061 14400
# Node ID 68e37b55a0687ca55554ca84c79c3358c05aee90
# Parent 8e7c9a8ad1f9e5bf6765c89a36ccca43f0564934
(#2) Add DCN ACL classes & providers
Changes in this version:
#2 - Scoped code to primary use case: link network interfaces to
existing fitlers.
- Updated copyright year in a few places.
- Fixed octets_to_cmpi() to work when called from an associattion provider
This patch adds several new classes and providers to add support for filter
rules and filter lists.
The patch is rather large since all aspects are intertwined.
Here's an overview of the implementation:
libxkutil:
The instrumentation is implemented in acl_parsing.c/.h since this function
is essentially independent of the device and/or pool parsing. ACLs are
associated to devices (via filterref) so there are some minor changes in
device_parsing.c & xmlgen.c to support this.
+libxkutil/acl_parsing.h & .c
Adds several new structures to represent filters and rules. Since rules can
only exist within the context of a filter, the main structure used in the APIs
is acl_fitler.
Also adds several new APIs to libxkutil to allow providers (see below) to
convert acl_filter and acl_rule structures to CIM objects, and to support
associations between themselves and existing resource (host system & network
port).
schema & providers:
The ACL function does not map to an exiting profile so a subset of the
classes defined in the CIM Network schema are used.
+schema/FilterEntry.mof &.registration
+src/FilterEntry.h & .c
Adds two new classes to represent IP-level rules (IPHeadersFilter) and
MAC-level (Hdr8021Filter). These classes include two new properties to
surface libvirt features not defined by the schema (Direction & Priority).
+schema/FilterList.mof & .registration
+src/FilterList.h & .c
Adds a class to represent ACL filters (FilterList)
NOTE: Read-write. Requires Name property only.
+schema/EntriesInFilterList.mof & .registration
+src/EntriesInFilterList.c
Adds a class to represent the relationship (association) between a filter
(FilterList) and the rules it contains (IPHeadersFilter or Hdr8021Filter).
+schema/NestedFilterList.mof & .registration
+src/NestedFilterList.c
Adds a class to represent filters that have references (filterref) to
other pre-defined filters. This is not covered by the current schema so
a new class was introduced to a) allow filters to reference each other, and
b) do it in a way that allows the client to determine if a filter
reference_s_ a filter or is reference_d_ by a filter.
+schema/HostedFilterList.mof & .registration
+src/HostedFilterList.c
Adds a class to represent the relationship (association) between a filter
and the computer system that hosts them. In the case of ACL filters, which
are essentially defined once but available to all VMs, they are always linked
to the host system (hypervisor) rather than the individual computer
systems (VMs).
+schema/AppliedFilterList.mof & .registration
+src/AppliedFilterList.c
Adds a class to represent the relationship (association) between a filter
and a network port referencing it. This is not covered by the current schema
so a new class was introduced.
NOTE: New associations are created via CIM intrinsic methods (create/modify/
delete). It requires the client to provide fully qualified object paths to
the filter and network port so the providers can a) validate their existance,
and b) apply the necessary links in the XML so new associations appear when
queried.
Signed-off-by: Chip Vincent <cvincent(a)us.ibm.com>
diff --git a/Makefile.am b/Makefile.am
--- a/Makefile.am
+++ b/Makefile.am
@@ -57,7 +57,13 @@
schema/InputPool.mof \
schema/HostedAccessPoint.mof \
schema/ServiceAccessBySAP.mof \
- schema/SAPAvailableForElement.mof
+ schema/SAPAvailableForElement.mof \
+ schema/FilterEntry.mof \
+ schema/FilterList.mof \
+ schema/EntriesInFilterList.mof \
+ schema/NestedFilterList.mof \
+ schema/AppliedFilterList.mof \
+ schema/HostedFilterList.mof
INTEROP_MOFS = \
schema/ComputerSystem.mof \
@@ -138,7 +144,13 @@
schema/InputPool.registration \
schema/HostedAccessPoint.registration \
schema/ServiceAccessBySAP.registration \
- schema/SAPAvailableForElement.registration
+ schema/SAPAvailableForElement.registration \
+ schema/FilterEntry.registration \
+ schema/FilterList.registration \
+ schema/EntriesInFilterList.registration \
+ schema/NestedFilterList.registration \
+ schema/AppliedFilterList.registration \
+ schema/HostedFilterList.registration
INTEROP_REGS = \
schema/RegisteredProfile.registration \
diff --git a/libxkutil/Makefile.am b/libxkutil/Makefile.am
--- a/libxkutil/Makefile.am
+++ b/libxkutil/Makefile.am
@@ -4,12 +4,12 @@
CFLAGS += $(CFLAGS_STRICT)
noinst_HEADERS = cs_util.h misc_util.h device_parsing.h xmlgen.h infostore.h \
- pool_parsing.h
+ pool_parsing.h acl_parsing.h
lib_LTLIBRARIES = libxkutil.la
libxkutil_la_SOURCES = cs_util_instance.c misc_util.c device_parsing.c \
- xmlgen.c infostore.c pool_parsing.c
+ xmlgen.c infostore.c pool_parsing.c acl_parsing.c
libxkutil_la_LIBADD = @LIBVIRT_LIBS@ \
@LIBUUID_LIBS@
diff --git a/libxkutil/acl_parsing.c b/libxkutil/acl_parsing.c
new file mode 100644
--- /dev/null
+++ b/libxkutil/acl_parsing.c
@@ -0,0 +1,639 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+
+#include "acl_parsing.h"
+#include "device_parsing.h"
+#include "xmlgen.h"
+#include "../src/svpc_types.h"
+
+void cleanup_rule(struct acl_rule *rule)
+{
+ if(rule == NULL)
+ return;
+
+ free(rule->name);
+ free(rule->protocol_id);
+ free(rule->action);
+ free(rule->direction);
+ free(rule->priority);
+
+ switch(rule->type) {
+ case MAC_RULE:
+ free(rule->var.mac.srcmacaddr);
+ free(rule->var.mac.srcmacmask);
+ free(rule->var.mac.dstmacaddr);
+ free(rule->var.mac.dstmacmask);
+ free(rule->var.mac.protocol_id);
+ free(rule->var.mac.comment);
+ break;
+ case ARP_RULE:
+ free(rule->var.arp.srcmacaddr);
+ free(rule->var.arp.srcmacmask);
+ free(rule->var.arp.dstmacaddr);
+ free(rule->var.arp.dstmacmask);
+ free(rule->var.arp.hw_type);
+ free(rule->var.arp.protocol_type);
+ free(rule->var.arp.opcode);
+ free(rule->var.arp.arpsrcmacaddr);
+ free(rule->var.arp.arpdstmacaddr);
+ free(rule->var.arp.arpsrcipaddr);
+ free(rule->var.arp.arpdstipaddr);
+ free(rule->var.arp.comment);
+ break;
+ case IP_RULE:
+ free(rule->var.ip.srcmacaddr);
+ free(rule->var.ip.srcmacmask);
+ free(rule->var.ip.dstmacaddr);
+ free(rule->var.ip.dstmacmask);
+ free(rule->var.ip.srcipaddr);
+ free(rule->var.ip.srcipmask);
+ free(rule->var.ip.dstipaddr);
+ free(rule->var.ip.dstipmask);
+ free(rule->var.ip.srcportstart);
+ free(rule->var.ip.srcportend);
+ free(rule->var.ip.dstportstart);
+ free(rule->var.ip.dstportend);
+ free(rule->var.ip.comment);
+ break;
+ case TCP_RULE:
+ free(rule->var.tcp.srcmacaddr);
+ free(rule->var.tcp.srcipaddr);
+ free(rule->var.tcp.srcipmask);
+ free(rule->var.tcp.dstipaddr);
+ free(rule->var.tcp.srcipfrom);
+ free(rule->var.tcp.srcipto);
+ free(rule->var.tcp.dstipfrom);
+ free(rule->var.tcp.dstipto);
+ free(rule->var.tcp.srcportstart);
+ free(rule->var.tcp.srcportend);
+ free(rule->var.tcp.dstportstart);
+ free(rule->var.tcp.dstportend);
+ free(rule->var.tcp.comment);
+ free(rule->var.tcp.state);
+ break;
+ case IGMP_RULE:
+ free(rule->var.igmp.srcmacaddr);
+ free(rule->var.igmp.srcmacmask);
+ free(rule->var.igmp.dstmacaddr);
+ free(rule->var.igmp.dstmacmask);
+ free(rule->var.igmp.srcipaddr);
+ free(rule->var.igmp.srcipmask);
+ free(rule->var.igmp.dstipaddr);
+ free(rule->var.igmp.dstipmask);
+ free(rule->var.igmp.srcipfrom);
+ free(rule->var.igmp.srcipto);
+ free(rule->var.igmp.dstipfrom);
+ free(rule->var.igmp.dstipto);
+ free(rule->var.igmp.type);
+ free(rule->var.igmp.code);
+ free(rule->var.igmp.comment);
+ free(rule->var.igmp.state);
+ break;
+ case ICMP_RULE:
+ free(rule->var.icmp.srcmacaddr);
+ free(rule->var.icmp.srcmacmask);
+ free(rule->var.icmp.dstmacaddr);
+ free(rule->var.icmp.dstmacmask);
+ free(rule->var.icmp.srcipaddr);
+ free(rule->var.icmp.srcipmask);
+ free(rule->var.icmp.dstipaddr);
+ free(rule->var.icmp.dstipmask);
+ free(rule->var.icmp.srcipfrom);
+ free(rule->var.icmp.srcipto);
+ free(rule->var.icmp.dstipfrom);
+ free(rule->var.icmp.dstipto);
+ free(rule->var.icmp.type);
+ free(rule->var.icmp.code);
+ free(rule->var.icmp.comment);
+ free(rule->var.icmp.state);
+ break;
+ case UNKNOWN_RULE:
+ default:
+ break;
+ };
+
+ rule->type = UNKNOWN_RULE;
+}
+
+void cleanup_filter(struct acl_filter *filter)
+{
+ int i;
+
+ if(filter == NULL)
+ return;
+
+ free(filter->uuid);
+ free(filter->name);
+ free(filter->chain);
+
+ for (i = 0; i < filter->rule_ct; i++) {
+ cleanup_rule(filter->rules[i]);
+ free(filter->rules[i]);
+ }
+
+ free(filter->rules);
+ filter->rule_ct = 0;
+
+ for (i = 0; i < filter->ref_ct; i++)
+ free(filter->refs[i]);
+
+ free(filter->refs);
+ filter->ref_ct = 0;
+}
+
+void cleanup_filters(struct acl_filter **filters, int count)
+{
+ int i;
+ struct acl_filter *_filters = *filters;
+
+ if((filters == NULL) || (*filters == NULL) || (count == 0))
+ return;
+
+ for (i = 0; i < count; i++)
+ cleanup_filter(&_filters[i]);
+
+ free(_filters);
+ *filters = NULL;
+}
+
+
+static int parse_acl_mac_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL mac rule %s", rnode->name);
+
+ rule->type = MAC_RULE;
+ rule->var.mac.protocol_id = get_attr_value(rnode, "protocolid");
+ rule->var.mac.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.mac.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.mac.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.mac.dstmacmask = get_attr_value(rnode, "dstmacmask");
+ rule->var.mac.comment = get_attr_value(rnode, "comment");
+
+ return 1;
+}
+
+static int parse_acl_arp_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL arp rule %s", rnode->name);
+
+ rule->type = ARP_RULE;
+ rule->var.arp.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.arp.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.arp.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.arp.dstmacmask = get_attr_value(rnode, "dstmacmask");
+ rule->var.arp.hw_type = get_attr_value(rnode, "hwtype");
+ rule->var.arp.protocol_type = get_attr_value(rnode, "protocoltype");
+ rule->var.arp.opcode = get_attr_value(rnode, "opcode");
+ rule->var.arp.arpsrcmacaddr = get_attr_value(rnode, "arpsrcmacaddr");
+ rule->var.arp.arpdstmacaddr = get_attr_value(rnode, "arpdstmacaddr");
+ rule->var.arp.arpsrcipaddr = get_attr_value(rnode, "arpsrcipaddr");
+ rule->var.arp.arpdstipaddr = get_attr_value(rnode, "arpdstipaddr");
+ rule->var.arp.comment = get_attr_value(rnode, "comment");
+
+ return 1;
+}
+
+static int parse_acl_ip_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACP ip rule %s", rnode->name);
+
+ rule->type = IP_RULE;
+ rule->var.ip.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.ip.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.ip.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.ip.dstmacmask = get_attr_value(rnode, "dstmacmaks");
+ rule->var.ip.srcipaddr = get_attr_value(rnode, "srcipaddr");
+ rule->var.ip.srcipmask = get_attr_value(rnode, "srcipmask");
+ rule->var.ip.dstipaddr = get_attr_value(rnode, "dstipaddr");
+ rule->var.ip.dstipmask = get_attr_value(rnode, "dstipmask");
+ rule->var.ip.protocol = get_attr_value(rnode, "protocol");
+ rule->var.ip.srcportstart = get_attr_value(rnode, "srcportstart");
+ rule->var.ip.srcportend = get_attr_value(rnode, "srcportend");
+ rule->var.ip.dstportstart = get_attr_value(rnode, "dstportstart");
+ rule->var.ip.dstportend = get_attr_value(rnode, "dstportend");
+ rule->var.ip.comment = get_attr_value(rnode, "comment");
+
+ return 1;
+}
+
+static int parse_acl_tcp_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL tcp rule %s", rnode->name);
+
+ rule->type = TCP_RULE;
+ rule->var.tcp.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.tcp.srcipaddr = get_attr_value(rnode, "srcipaddr");
+ rule->var.tcp.srcipmask = get_attr_value(rnode, "srcipmask");
+ rule->var.tcp.dstipaddr = get_attr_value(rnode, "dstipaddr");
+ rule->var.tcp.dstipmask = get_attr_value(rnode, "dstipmask");
+ rule->var.tcp.srcipfrom = get_attr_value(rnode, "srcipfrom");
+ rule->var.tcp.srcipto = get_attr_value(rnode, "srcipto");
+ rule->var.tcp.dstipfrom = get_attr_value(rnode, "dstipfrom");
+ rule->var.tcp.dstipto = get_attr_value(rnode, "dstipto");
+ rule->var.tcp.srcportstart = get_attr_value(rnode, "srcportstart");
+ rule->var.tcp.srcportend = get_attr_value(rnode, "srcportend");
+ rule->var.tcp.dstportstart = get_attr_value(rnode, "dstportstart");
+ rule->var.tcp.dstportend = get_attr_value(rnode, "dstportend");
+ rule->var.tcp.comment = get_attr_value(rnode, "comment");
+ rule->var.tcp.state = get_attr_value(rnode, "state");
+
+ return 1;
+}
+
+static int parse_acl_icmp_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL icmp rule %s", rnode->name);
+
+ rule->type = ICMP_RULE;
+ rule->var.icmp.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.icmp.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.icmp.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.icmp.dstmacmask = get_attr_value(rnode, "dstmacmask");
+ rule->var.icmp.srcipaddr = get_attr_value(rnode, "srcipaddr");
+ rule->var.icmp.srcipmask = get_attr_value(rnode, "srcipmask");
+ rule->var.icmp.dstipaddr = get_attr_value(rnode, "dstipaddr");
+ rule->var.icmp.dstipmask = get_attr_value(rnode, "dstipmask");
+ rule->var.icmp.srcipfrom = get_attr_value(rnode, "srcipfrom");
+ rule->var.icmp.srcipto = get_attr_value(rnode, "srcipto");
+ rule->var.icmp.dstipfrom = get_attr_value(rnode, "dstipfrom");
+ rule->var.icmp.dstipto = get_attr_value(rnode, "dstipto");
+ rule->var.icmp.comment = get_attr_value(rnode, "comment");
+ rule->var.icmp.state = get_attr_value(rnode, "state");
+
+ return 1;
+}
+
+static int parse_acl_igmp_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL igmp rule %s", rnode->name);
+
+ rule->type = IGMP_RULE;
+ rule->var.igmp.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.igmp.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.igmp.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.igmp.dstmacmask = get_attr_value(rnode, "dstmacmask");
+ rule->var.igmp.srcipaddr = get_attr_value(rnode, "srcipaddr");
+ rule->var.igmp.srcipmask = get_attr_value(rnode, "srcipmask");
+ rule->var.igmp.dstipaddr = get_attr_value(rnode, "dstipaddr");
+ rule->var.igmp.dstipmask = get_attr_value(rnode, "dstipmask");
+ rule->var.igmp.srcipfrom = get_attr_value(rnode, "srcipfrom");
+ rule->var.igmp.srcipto = get_attr_value(rnode, "srcipto");
+ rule->var.igmp.dstipfrom = get_attr_value(rnode, "dstipfrom");
+ rule->var.igmp.dstipto = get_attr_value(rnode, "dstipto");
+ rule->var.igmp.type = get_attr_value(rnode, "type");
+ rule->var.igmp.code = get_attr_value(rnode, "code");
+ rule->var.igmp.comment = get_attr_value(rnode, "comment");
+ rule->var.igmp.state = get_attr_value(rnode, "state");
+
+ return 1;
+}
+
+static int parse_acl_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ xmlNode *child = NULL;
+
+ memset(rule, 0, sizeof(*rule));
+
+ rule->action = get_attr_value(rnode, "action");
+ if (rule->action == NULL)
+ goto err;
+
+ rule->direction = get_attr_value(rnode, "direction");
+ if (rule->direction == NULL)
+ goto err;
+
+ rule->priority = get_attr_value(rnode, "priority");
+ rule->statematch = get_attr_value(rnode, "statematch");
+
+ for (child = rnode->children; child != NULL; child = child->next) {
+ if (XSTREQ(child->name, "mac")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_mac_rule(child, rule);
+ } else if (XSTREQ(child->name, "arp") ||
+ XSTREQ(child->name, "rarp")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_arp_rule(child, rule);
+ } else if (XSTREQ(child->name, "ip") ||
+ XSTREQ(child->name, "ipv6")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_ip_rule(child, rule);
+ } else if (XSTREQ(child->name, "tcp") ||
+ XSTREQ(child->name, "tcp-ipv6") ||
+ XSTREQ(child->name, "udp") ||
+ XSTREQ(child->name, "udp-ipv6") ||
+ XSTREQ(child->name, "sctp") ||
+ XSTREQ(child->name, "sctp-ipv6")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_tcp_rule(child, rule);
+ } else if (XSTREQ(child->name, "icmp") ||
+ XSTREQ(child->name, "icmpv6")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_icmp_rule(child, rule);
+ } else if (XSTREQ(child->name, "igmp") ||
+ XSTREQ(child->name, "igmp-ipv6") ||
+ XSTREQ(child->name, "esp") ||
+ XSTREQ(child->name, "esp-ipv6") ||
+ XSTREQ(child->name, "ah") ||
+ XSTREQ(child->name, "ah-ipv6") ||
+ XSTREQ(child->name, "udplite") ||
+ XSTREQ(child->name, "udplite-ipv6") ||
+ XSTREQ(child->name, "all") ||
+ XSTREQ(child->name, "all-ipv6")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_igmp_rule(child, rule);
+ }
+ }
+
+ return 1;
+
+ err:
+ cleanup_rule(rule);
+
+ return 0;
+}
+
+static int parse_acl_filter(xmlNode *fnode, struct acl_filter *filter)
+{
+ struct acl_rule *rule = NULL;
+ char *filter_ref = NULL;
+ xmlNode *child = NULL;
+
+ filter->name = get_attr_value(fnode, "name");
+ if (filter->name == NULL)
+ goto err;
+
+ filter->chain = get_attr_value(fnode, "chain");
+
+ for (child = fnode->children; child != NULL; child = child->next) {
+ if (XSTREQ(child->name, "uuid")) {
+ STRPROP(filter, uuid, child);
+ } else if (XSTREQ(child->name, "rule")) {
+ rule = malloc(sizeof(*rule));
+ if (rule == NULL)
+ goto err;
+
+ if (parse_acl_rule(child, rule) == 0)
+ goto err;
+
+ append_filter_rule(filter, rule);
+ }
+ else if (XSTREQ(child->name, "filterref")) {
+ filter_ref = get_attr_value(child, "filter");
+ if (filter_ref == NULL)
+ goto err;
+
+ append_filter_ref(filter, filter_ref);
+ }
+ }
+
+ return 1;
+
+ err:
+ cleanup_filter(filter);
+
+ return 0;
+}
+
+/* Dummy function to suppress error message from libxml2 */
+static void swallow_err_msg(void *ctx, const char *msg, ...)
+{
+ /* do nothing, just swallow the message. */
+}
+
+int get_filter_from_xml(const char *xml, struct acl_filter **filter)
+{
+ xmlDoc *xmldoc = NULL;
+
+ if (xml == NULL || filter == NULL)
+ return 0;
+
+ xmlSetGenericErrorFunc(NULL, swallow_err_msg);
+
+ xmldoc = xmlParseMemory(xml, strlen(xml) + 1);
+ if (xmldoc == NULL)
+ goto err;
+
+ *filter = malloc(sizeof(**filter));
+
+ memset(*filter, 0, sizeof(**filter));
+ parse_acl_filter(xmldoc->children, *filter);
+
+ err:
+ xmlSetGenericErrorFunc(NULL, NULL);
+ xmlFreeDoc(xmldoc);
+
+ return 1;
+}
+
+int get_filter_by_name(
+ virConnectPtr conn,
+ const char *name,
+ struct acl_filter **filter)
+{
+ virNWFilterPtr vfilter = NULL;
+ char *xml = NULL;
+
+ if (name == NULL || filter == NULL)
+ return 0;
+
+ vfilter = virNWFilterLookupByName(conn, name);
+
+ xml = virNWFilterGetXMLDesc(vfilter, 0);
+
+ virNWFilterFree(vfilter);
+
+ if (xml == NULL)
+ return 0;
+
+ get_filter_from_xml(xml, filter);
+
+ return 1;
+}
+
+int get_filter_by_uuid(
+ virConnectPtr conn,
+ const char *uuid,
+ struct acl_filter **filter)
+{
+ virNWFilterPtr vfilter = NULL;
+ char *xml = NULL;
+
+ if (uuid == NULL || filter == NULL)
+ return 0;
+
+ vfilter = virNWFilterLookupByUUIDString(conn, uuid);
+
+ xml = virNWFilterGetXMLDesc(vfilter, 0);
+
+ virNWFilterFree(vfilter);
+
+ if (xml == NULL)
+ return 0;
+
+ get_filter_from_xml(xml, filter);
+
+ return 1;
+}
+
+int get_filters(
+ virConnectPtr conn,
+ struct acl_filter **list)
+{
+ int count = 0;
+ char **names = NULL;
+ struct acl_filter *filters = NULL;
+ int i = 0;
+
+ count = virConnectNumOfNWFilters(conn);
+
+ names = calloc(count, sizeof(char *));
+ if (names == NULL)
+ goto err;
+
+ virConnectListNWFilters(conn, names, count);
+
+ filters = malloc(count * sizeof(struct acl_filter));
+ if (filters == NULL)
+ goto err;
+
+ for(i = 0; i < count; i++)
+ {
+ struct acl_filter *filter = NULL;
+
+ get_filter_by_name(conn, names[i], &filter);
+
+ memcpy(&filters[i], filter, sizeof(*filter));
+ }
+
+ *list = filters;
+
+ err:
+ free(names);
+
+ return i;
+}
+
+
+int append_filter_rule(struct acl_filter *filter, struct acl_rule *rule)
+{
+ struct acl_rule **old_rules = NULL;
+
+ if ((filter == NULL) || (rule == NULL))
+ return 0;
+
+ rule->name = make_rule_id(filter->name, filter->rule_ct);
+ if (rule->name == NULL)
+ return 0;
+
+ old_rules = filter->rules;
+
+ filter->rules =
+ malloc((filter->rule_ct + 1) * sizeof(struct acl_rule *));
+
+ memcpy(filter->rules,
+ old_rules,
+ filter->rule_ct * sizeof(struct acl_rule *));
+
+ filter->rules[filter->rule_ct] = rule;
+ filter->rule_ct++;
+
+ free(old_rules);
+
+ return 1;
+}
+
+int append_filter_ref(struct acl_filter *filter, char *name)
+{
+ int i;
+ char **old_refs = NULL;
+
+ if ((filter == NULL) || (name == NULL))
+ return 0;
+
+ for (i = 0; i < filter->ref_ct; i++)
+ if (STREQC(filter->refs[i], name))
+ return 0; /* already exists */
+
+ old_refs = filter->refs;
+
+ filter->refs = malloc((filter->ref_ct + 1) * sizeof(char *));
+ memcpy(filter->refs, old_refs, filter->ref_ct * sizeof(char *));
+
+ filter->refs[filter->ref_ct] = name;
+ filter->ref_ct++;
+
+ free(old_refs);
+
+ return 1;
+}
+
+char *make_rule_id(const char *filter, int index)
+{
+ int ret;
+ char *rule_id = NULL;
+
+ if (filter == NULL)
+ return NULL;
+
+ ret = asprintf(&rule_id, "%s:%u", filter, index);
+ if (ret == -1) {
+ free(rule_id);
+ rule_id = NULL;
+ }
+
+
+ return rule_id;
+}
+
+int parse_rule_id(const char *rule_id, char **filter, int *index)
+{
+ int ret;
+
+ if ((filter == NULL) || (index == NULL))
+ return 0;
+ ret = sscanf(rule_id, "%as[^:]:%u", filter, index);
+ if (ret != 2) {
+ free(*filter);
+ *filter = NULL;
+
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/libxkutil/acl_parsing.h b/libxkutil/acl_parsing.h
new file mode 100644
--- /dev/null
+++ b/libxkutil/acl_parsing.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ACL_PARSING_H
+#define __ACL_PARSING_H
+
+#include <libvirt/libvirt.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+
+struct acl_mac_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *protocol_id;
+ char *comment;
+};
+
+struct acl_arp_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *hw_type;
+ char *protocol_type;
+ char *opcode;
+ char *arpsrcmacaddr;
+ char *arpdstmacaddr;
+ char *arpsrcipaddr;
+ char *arpdstipaddr;
+ char *comment;
+};
+
+struct acl_ip_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *srcipaddr;
+ char *srcipmask;
+ char *dstipaddr;
+ char *dstipmask;
+
+ char *protocol;
+
+ char *srcportstart;
+ char *srcportend;
+ char *dstportstart;
+ char *dstportend;
+
+ char *comment;
+};
+
+struct acl_tcp_rule {
+ char *srcmacaddr;
+
+ char *srcipaddr;
+ char *srcipmask;
+ char *dstipaddr;
+ char *dstipmask;
+
+ char *srcipfrom;
+ char *srcipto;
+ char *dstipfrom;
+ char *dstipto;
+
+ char *srcportstart;
+ char *srcportend;
+ char *dstportstart;
+ char *dstportend;
+
+ char *comment;
+ char *state;
+};
+
+struct acl_igmp_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *srcipaddr;
+ char *srcipmask;
+ char *dstipaddr;
+ char *dstipmask;
+
+ char *srcipfrom;
+ char *srcipto;
+ char *dstipfrom;
+ char *dstipto;
+
+ char *type;
+ char *code;
+ char *comment;
+ char *state;
+};
+
+struct acl_icmp_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *srcipaddr;
+ char *srcipmask;
+ char *dstipaddr;
+ char *dstipmask;
+
+ char *srcipfrom;
+ char *srcipto;
+ char *dstipfrom;
+ char *dstipto;
+
+ char *type;
+ char *code;
+ char *comment;
+ char *state;
+};
+
+struct acl_rule {
+ char *name;
+ char *protocol_id;
+ char *action;
+ char *direction;
+ char *priority;
+ char *statematch;
+
+ enum {
+ UNKNOWN_RULE,
+ MAC_RULE,
+ ARP_RULE,
+ IP_RULE,
+ TCP_RULE,
+ ICMP_RULE,
+ IGMP_RULE
+ } type;
+
+ union {
+ struct acl_mac_rule mac;
+ struct acl_arp_rule arp;
+ struct acl_ip_rule ip;
+ struct acl_tcp_rule tcp;
+ struct acl_icmp_rule icmp;
+ struct acl_igmp_rule igmp;
+ } var;
+};
+
+struct acl_filter {
+ char *uuid;
+ char *name;
+ char *chain;
+
+ struct acl_rule **rules;
+ int rule_ct;
+
+ char **refs;
+ int ref_ct;
+};
+
+void cleanup_rule(struct acl_rule *rule);
+void cleanup_filter(struct acl_filter *filter);
+void cleanup_filters(struct acl_filter **filters, int count);
+
+int get_filters(virConnectPtr conn, struct acl_filter **list);
+
+int get_filter_from_xml(const char *xml, struct acl_filter **filter);
+int get_filter_by_uuid(virConnectPtr conn, const char *uuid,
+ struct acl_filter **filter);
+int get_filter_by_name(virConnectPtr conn, const char *name,
+ struct acl_filter **filter);
+
+char *make_rule_id(const char *filter, int index);
+int parse_rule_id(const char *rule_id, char **filter, int *index);
+
+/** NOTE: Both append functions take parameters allocated by caller and
+ * freed by cleanup_filter(s)
+ */
+int append_filter_rule(struct acl_filter *filter, struct acl_rule *rule);
+int append_filter_ref(struct acl_filter *filter, char *name);
+#endif
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/libxkutil/device_parsing.c b/libxkutil/device_parsing.c
--- a/libxkutil/device_parsing.c
+++ b/libxkutil/device_parsing.c
@@ -80,6 +80,7 @@
free(dev->model);
free(dev->device);
free(dev->net_mode);
+ free(dev->filter_ref);
}
static void cleanup_emu_device(struct emu_device *dev)
@@ -386,9 +387,12 @@
ndev->model = get_attr_value(child, "type");
if (ndev->model == NULL)
goto err;
+ } else if (XSTREQ(child->name, "filterref")) {
+ ndev->filter_ref = get_attr_value(child, "filter");
} else if (XSTREQ(child->name, "virtualport")) {
parse_vsi_device(child, ndev);
}
+
}
if (ndev->source == NULL)
@@ -764,6 +768,7 @@
DUP_FIELD(dev, _dev, dev.net.model);
DUP_FIELD(dev, _dev, dev.net.device);
DUP_FIELD(dev, _dev, dev.net.net_mode);
+ DUP_FIELD(dev, _dev, dev.net.filter_ref);
DUP_FIELD(dev, _dev, dev.net.vsi.vsi_type);
DUP_FIELD(dev, _dev, dev.net.vsi.manager_id);
DUP_FIELD(dev, _dev, dev.net.vsi.type_id);
diff --git a/libxkutil/device_parsing.h b/libxkutil/device_parsing.h
--- a/libxkutil/device_parsing.h
+++ b/libxkutil/device_parsing.h
@@ -64,6 +64,7 @@
char *model;
char *device;
char *net_mode;
+ char *filter_ref;
struct vsi_device vsi;
};
diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c
--- a/libxkutil/xmlgen.c
+++ b/libxkutil/xmlgen.c
@@ -301,6 +301,15 @@
xmlNewProp(tmp, BAD_CAST "type", BAD_CAST net->model);
}
+ if (net->filter_ref != NULL) {
+ tmp = xmlNewChild(nic, NULL,
+ BAD_CAST "filterref", NULL);
+ if (tmp == NULL)
+ return XML_ERROR;
+ xmlNewProp(tmp, BAD_CAST "filter",
+ BAD_CAST net->filter_ref);
+ }
+
if (STREQ(dev->dev.net.type, "network"))
msg = set_net_source(nic, net, "network");
else if (STREQ(dev->dev.net.type, "bridge"))
diff --git a/libxkutil/xmlgen.h b/libxkutil/xmlgen.h
--- a/libxkutil/xmlgen.h
+++ b/libxkutil/xmlgen.h
@@ -23,6 +23,7 @@
#include "device_parsing.h"
#include "pool_parsing.h"
+#include "acl_parsing.h"
#include "cmpidt.h"
@@ -38,4 +39,6 @@
char *res_to_xml(struct virt_pool_res *res);
+char *filter_to_xml(struct acl_filter *filter);
+
#endif
diff --git a/schema/AppliedFilterList.mof b/schema/AppliedFilterList.mof
new file mode 100644
--- /dev/null
+++ b/schema/AppliedFilterList.mof
@@ -0,0 +1,8 @@
+// Copyright IBM Corp. 2011
+[Association,
+ Provider("cmpi::Virt_AppliedFilterList")]
+class KVM_AppliedFilterList : CIM_ConcreteDependency
+{
+ CIM_NetworkPort ref Antecedent;
+ CIM_FilterList ref Dependent;
+};
diff --git a/schema/AppliedFilterList.registration b/schema/AppliedFilterList.registration
new file mode 100644
--- /dev/null
+++ b/schema/AppliedFilterList.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+KVM_AppliedFilterList root/virt Virt_AppliedFilterList Virt_AppliedFilterList association
diff --git a/schema/EntriesInFilterList.mof b/schema/EntriesInFilterList.mof
new file mode 100644
--- /dev/null
+++ b/schema/EntriesInFilterList.mof
@@ -0,0 +1,6 @@
+// Copyright IBM Corp. 2011
+[Association,
+ Provider("cmpi::Virt_EntriesInFilterList")]
+class KVM_EntriesInFilterList : CIM_EntriesInFilterList
+{
+};
diff --git a/schema/EntriesInFilterList.registration b/schema/EntriesInFilterList.registration
new file mode 100644
--- /dev/null
+++ b/schema/EntriesInFilterList.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+KVM_EntriesInFilterList root/virt Virt_EntriesInFilterList Virt_EntriesInFilterList association
diff --git a/schema/FilterEntry.mof b/schema/FilterEntry.mof
new file mode 100644
--- /dev/null
+++ b/schema/FilterEntry.mof
@@ -0,0 +1,60 @@
+// Copyright IBM Corp. 2011
+[Provider("cmpi::Virt_FilterEntry")]
+class KVM_Hdr8021Filter : CIM_Hdr8021Filter
+{
+ [Description("This defines whether the Filter is used for input, "
+ "output, or both input and output filtering. All values are "
+ "used with respect to the interface for which the Filter "
+ "applies. \"Not Applicable\" (0) is used when there is no "
+ "direction applicable to the Filter. \"Input\" (1) is "
+ "used when the Filter applies to packets that are inbound "
+ "on the related interface. \"Output\" (2) is used when the "
+ "Filter applies to packets that are outbound on the "
+ "related interface. \"Both\" (3) is used to indicate that "
+ "the direction is immaterial, e.g., to filter on a source "
+ "subnet regardless of whether the flow is inbound or "
+ "outbound."),
+ ValueMap { "0", "1", "2", "3", "4" },
+ Values { "Not Applicable", "Input, Output", "Both", "Mirrored" }]
+ uint16 Direction;
+
+ [Description("The priority of the rule controls the order in which "
+ "the rule will be, instantiated relative to other rules. "
+ "Rules with lower value will be instantiated and therefore "
+ "evaluated before rules with higher value. Valid values are "
+ "in the range of 0 to 1000. If this attribute is not "
+ "provided, the value 500 will automatically be assigned."),
+ MinValue(0),
+ MaxValue(1000)]
+ uint16 Priority = 500;
+};
+
+[Provider("cmpi::Virt_FilterEntry")]
+class KVM_IPHeadersFilter : CIM_IPHeadersFilter
+{
+ [Description("This defines whether the Filter is used for input, "
+ "output, or both input and output filtering. All values are "
+ "used with respect to the interface for which the Filter "
+ "applies. \"Not Applicable\" (0) is used when there is no "
+ "direction applicable to the Filter. \"Input\" (1) is "
+ "used when the Filter applies to packets that are inbound "
+ "on the related interface. \"Output\" (2) is used when the "
+ "Filter applies to packets that are outbound on the "
+ "related interface. \"Both\" (3) is used to indicate that "
+ "the direction is immaterial, e.g., to filter on a source "
+ "subnet regardless of whether the flow is inbound or "
+ "outbound."),
+ ValueMap { "0", "1", "2", "3", "4" },
+ Values { "Not Applicable", "Input, Output", "Both", "Mirrored" }]
+ uint16 Direction;
+
+ [Description("The priority of the rule controls the order in which "
+ "the rule will be, instantiated relative to other rules. "
+ "Rules with lower value will be instantiated and therefore "
+ "evaluated before rules with higher value. Valid values are "
+ "in the range of 0 to 1000. If this attribute is not "
+ "provided, the value 500 will automatically be assigned."),
+ MinValue(0),
+ MaxValue(1000)]
+ uint16 Priority = 500;
+};
diff --git a/schema/FilterEntry.registration b/schema/FilterEntry.registration
new file mode 100644
--- /dev/null
+++ b/schema/FilterEntry.registration
@@ -0,0 +1,4 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+KVM_Hdr8021Filter root/virt Virt_FilterEntry Virt_FilterEntry instance
+KVM_IPHeadersFilter root/virt Virt_FilterEntry Virt_FilterEntry instance
diff --git a/schema/FilterList.mof b/schema/FilterList.mof
new file mode 100644
--- /dev/null
+++ b/schema/FilterList.mof
@@ -0,0 +1,4 @@
+// Copyright IBM Corp. 2011
+class KVM_FilterList : CIM_FilterList
+{
+};
diff --git a/schema/FilterList.registration b/schema/FilterList.registration
new file mode 100755
--- /dev/null
+++ b/schema/FilterList.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+KVM_FilterList root/virt Virt_FilterList Virt_FilterList instance
diff --git a/schema/HostedFilterList.mof b/schema/HostedFilterList.mof
new file mode 100644
--- /dev/null
+++ b/schema/HostedFilterList.mof
@@ -0,0 +1,6 @@
+// Copyright IBM Corp. 2011
+[Association,
+ Provider("cmpi::Virt_HostedFilterList")]
+class KVM_HostedFilterList : CIM_HostedFilterList
+{
+};
diff --git a/schema/HostedFilterList.registration b/schema/HostedFilterList.registration
new file mode 100644
--- /dev/null
+++ b/schema/HostedFilterList.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+KVM_HostedFilterList root/virt Virt_HostedFilterList Virt_HostedFilterList association
diff --git a/schema/NestedFilterList.mof b/schema/NestedFilterList.mof
new file mode 100644
--- /dev/null
+++ b/schema/NestedFilterList.mof
@@ -0,0 +1,8 @@
+// Copyright IBM Corp. 2011
+[Association,
+ Provider("cmpi::Virt_NestedFilterList")]
+class KVM_NestedFilterList : CIM_ConcreteDependency
+{
+ CIM_FilterList ref Antecedent;
+ CIM_FilterList ref Dependent;
+};
diff --git a/schema/NestedFilterList.registration b/schema/NestedFilterList.registration
new file mode 100644
--- /dev/null
+++ b/schema/NestedFilterList.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2011
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+KVM_NestedFilterList root/virt Virt_NestedFilterList Virt_NestedFilterList association
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,7 +23,9 @@
Virt_VSMigrationSettingData.h \
Virt_ConsoleRedirectionService.h \
Virt_ConsoleRedirectionServiceCapabilities.h \
- Virt_KVMRedirectionSAP.h
+ Virt_KVMRedirectionSAP.h \
+ Virt_FilterList.h \
+ Virt_FilterEntry.h
XKUADD = $(top_builddir)/libxkutil/libxkutil.la
@@ -77,7 +79,13 @@
libVirt_ServiceAffectsElement.la \
libVirt_HostedAccessPoint.la \
libVirt_ServiceAccessBySAP.la \
- libVirt_SAPAvailableForElement.la
+ libVirt_SAPAvailableForElement.la \
+ libVirt_FilterList.la \
+ libVirt_FilterEntry.la \
+ libVirt_EntriesInFilterList.la \
+ libVirt_NestedFilterList.la \
+ libVirt_HostedFilterList.la \
+ libVirt_AppliedFilterList.la
libVirt_ComputerSystem_la_SOURCES = Virt_ComputerSystem.c
libVirt_ComputerSystem_la_DEPENDENCIES = libVirt_VirtualSystemSnapshotService.la
@@ -243,3 +251,26 @@
libVirt_SAPAvailableForElement_la_SOURCES = Virt_SAPAvailableForElement.c
libVirt_SAPAvailableForElement_la_LIBADD = -lVirt_ComputerSystem -lVirt_KVMRedirectionSAP
+libVirt_FilterEntry_la_DEPENDENCIES = libVirt_HostSystem.la
+libVirt_FilterEntry_la_SOURCES = Virt_FilterEntry.c
+libVirt_FilterEntry_la_LIBADD = -lVirt_HostSystem
+
+libVirt_FilterList_la_DEPENDENCIES = libVirt_HostSystem.la
+libVirt_FilterList_la_SOURCES = Virt_FilterList.c
+libVirt_FilterList_la_LIBADD = -lVirt_HostSystem
+
+libVirt_EntriesInFilterList_la_DEPENDENCIES = libVirt_FilterEntry.la libVirt_FilterList.la
+libVirt_EntriesInFilterList_la_SOURCES = Virt_EntriesInFilterList.c
+libVirt_EntriesInFilterList_la_LIBADD = -lVirt_FilterEntry -lVirt_FilterList
+
+libVirt_NestedFilterList_la_DEPENDENCIES = libVirt_FilterList.la
+libVirt_NestedFilterList_la_SOURCES = Virt_NestedFilterList.c
+libVirt_NestedFilterList_la_LIBADD = -lVirt_FilterList
+
+libVirt_HostedFilterList_la_DEPENDENCIES = libVirt_HostSystem.la libVirt_FilterList.la
+libVirt_HostedFilterList_la_SOURCES = Virt_HostedFilterList.c
+libVirt_HostedFilterList_la_LIBADD = -lVirt_HostSystem -lVirt_FilterList
+
+libVirt_AppliedFilterList_la_DEPENDENCIES = libVirt_Device.la libVirt_FilterList.la
+libVirt_AppliedFilterList_la_SOURCES = Virt_AppliedFilterList.c
+libVirt_AppliedFilterList_la_LIBADD = -lVirt_Device -lVirt_FilterList
diff --git a/src/Virt_AppliedFilterList.c b/src/Virt_AppliedFilterList.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_AppliedFilterList.c
@@ -0,0 +1,634 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_association.h>
+#include <libcmpiutil/std_instance.h>
+
+#include "device_parsing.h"
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "cs_util.h"
+
+#include "Virt_Device.h"
+#include "Virt_FilterList.h"
+
+static const CMPIBroker *_BROKER;
+
+/* TODO: Port to libcmpiutil/args_util.c */
+/**
+ * Get a reference property of an instance
+ *
+ * @param inst The instance
+ * @param prop The property name
+ * @param reference A pointer to a CMPIObjectPath* that will be set
+ * if successful
+ * @returns
+ * - CMPI_RC_OK on success
+ * - CMPI_RC_ERR_NO_SUCH_PROPERTY if prop is not present
+ * - CMPI_RC_ERR_TYPE_MISMATCH if prop is not a reference
+ * - CMPI_RC_OK otherwise
+ */
+static CMPIrc cu_get_ref_prop(const CMPIInstance *instance,
+ const char *prop,
+ CMPIObjectPath **reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIData value;
+
+ /* REQUIRE_PROPERY_DEFINED(instance, prop, value, &s); */
+ value = CMGetProperty(instance, prop, &s);
+ if ((s.rc != CMPI_RC_OK) || CMIsNullValue(value))
+ return CMPI_RC_ERR_NO_SUCH_PROPERTY;
+
+ if ((value.type != CMPI_ref) || CMIsNullObject(value.value.ref))
+ return CMPI_RC_ERR_TYPE_MISMATCH;
+
+ *reference = value.value.ref;
+
+ return CMPI_RC_OK;
+}
+
+/* TODO: Port to libcmpiutil/args_util.c */
+/**
+ * Get a reference component of an object path
+ *
+ * @param _reference The reference
+ * @param key The key name
+ * @param reference A pointer to a CMPIObjectPath* that will be set
+ * if successful
+ * @returns
+ * - CMPI_RC_OK on success
+ * - CMPI_RC_ERR_NO_SUCH_PROPERTY if prop is not present
+ * - CMPI_RC_ERR_TYPE_MISMATCH if prop is not a reference
+ * - CMPI_RC_OK otherwise
+ */
+static CMPIrc cu_get_ref_path(const CMPIObjectPath *reference,
+ const char *key,
+ CMPIObjectPath **_reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIData value;
+
+ /* REQUIRE_PROPERY_DEFINED(instance, prop, value, &s); */
+ value = CMGetKey(reference, key, &s);
+ if ((s.rc != CMPI_RC_OK) || CMIsNullValue(value))
+ return CMPI_RC_ERR_NO_SUCH_PROPERTY;
+
+ /* how to parse and object path? */
+
+ return CMPI_RC_OK;
+}
+
+/* TODO: Port to libxkutil/device_parsing.c */
+static int update_device(virDomainPtr dom,
+ struct virt_device *dev)
+{
+ char *xml = NULL;
+ int flags = VIR_DOMAIN_DEVICE_MODIFY_CURRENT |
+ VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
+ int ret = 0;
+
+ /** device_to_xml() is not exported, so this function needs
+ * to be moved
+ */
+
+ /* xml = device_to_xml(dev); */
+
+ if (xml == NULL) {
+ CU_DEBUG("Failed to get XML for device '%s'", dev->id);
+ goto out;
+ }
+
+ if (virDomainUpdateDeviceFlags(dom, xml, flags) != 0) {
+ CU_DEBUG("Failed to dynamically update device:");
+ CU_DEBUG("%s", xml);
+ goto out;
+ }
+
+ ret = 1;
+ out:
+ free(xml);
+
+ return ret;
+}
+
+/* TODO: Port to libxkutil/device_parsing.c */
+static int get_device_by_devid(virDomainPtr dom,
+ const char *devid,
+ int type,
+ struct virt_device **dev)
+{
+ int i, ret = 0;
+ struct virt_device *devices = NULL;
+ int count = get_devices(dom, &devices, type);
+
+ for (i = 0; i < count; i++) {
+ if (STREQC(devid, devices[i].id)) {
+ CU_DEBUG("Found '%s'", devices[i].id);
+
+ *dev = virt_device_dup(&devices[i]);
+ if (*dev != NULL)
+ ret = 1;
+
+ break;
+ }
+ }
+
+ cleanup_virt_devices(&devices, count);
+
+ return ret;
+}
+
+/**
+ * given a filter, get the network interface
+ */
+static CMPIStatus list_to_net(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ const char *name = NULL;
+ struct acl_filter *filter = NULL;
+ virDomainPtr *doms = NULL;
+ virConnectPtr conn = NULL;
+ int i, j, dcount, ncount;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ /* validate filter */
+ get_filter_by_name(conn, name, &filter);
+ if (filter == NULL)
+ goto out;
+
+ cleanup_filter(filter);
+
+ /* get domains */
+ dcount = get_domain_list(conn, &doms);
+ if (dcount < 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to get domain list");
+ goto out;
+ }
+
+ for (i = 0; i < dcount; i++) {
+ /* get domain's network devices */
+ struct virt_device *devices = NULL;
+ ncount = get_devices(doms[i], &devices, CIM_RES_TYPE_NET);
+
+ CU_DEBUG("Found %u network devices", ncount);
+
+ for (j = 0; j < ncount; j++) {
+ struct net_device *ndev = &(devices[j].dev.net);
+
+ CU_DEBUG("filterref = %s", ndev->filter_ref);
+
+ if ((ndev->filter_ref != NULL) &&
+ STREQC(name, ndev->filter_ref)) {
+ CU_DEBUG("Getting network device instance");
+
+ CMPIInstance *instance = NULL;
+ char *device_id =
+ get_fq_devid(
+ (char *)virDomainGetName(doms[i]),
+ devices[j].id);
+
+ CU_DEBUG("Processing %s", device_id);
+
+ s = get_device_by_name(_BROKER,
+ reference,
+ device_id,
+ CIM_RES_TYPE_NET,
+ &instance);
+
+ if (instance != NULL) {
+ CU_DEBUG("adding instance to list");
+ inst_list_add(list, instance);
+ }
+ }
+ }
+
+ cleanup_virt_devices(&devices, ncount);
+ virDomainFree(doms[i]);
+ }
+
+ out:
+ virConnectClose(conn);
+
+ return s;
+}
+
+/**
+ * given a network interface, find the filter lists
+ */
+static CMPIStatus net_to_list(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+ const char *device_name = NULL;
+ char *domain_name = NULL;
+ char *net_name = NULL;
+ virConnectPtr conn = NULL;
+ virDomainPtr dom = NULL;
+ int i;
+ struct acl_filter *filter = NULL;
+
+ CU_DEBUG("Reference %s", REF2STR(reference));
+
+ /* validate device
+ * TODO: This may be redundant since it's necessary to get
+ * the device structure in order to determine the filter_ref
+ */
+ if (!STREQC(CLASSNAME(reference), "KVM_NetworkPort"))
+ goto out;
+
+ s = get_device_by_ref(_BROKER, reference, &instance);
+ if ((s.rc != CMPI_RC_OK) || (instance == NULL))
+ goto out;
+
+ if (cu_get_str_path(reference, "DeviceID",
+ &device_name) != CMPI_RC_OK) {
+ CU_DEBUG("Failed to get DeviceID");
+ goto out;
+ }
+
+ if (parse_fq_devid(device_name, &domain_name, &net_name) == 0) {
+ CU_DEBUG("Failed to parse devid");
+ goto out;
+ }
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ /* connect to domain */
+ dom = virDomainLookupByName(conn, domain_name);
+ if (dom == NULL) {
+ CU_DEBUG("Failed to connect to Domain '%s'", domain_name);
+ goto out;
+ }
+
+ /* get domain's network devices */
+ struct virt_device *devices = NULL;
+ int count = get_devices(dom, &devices, CIM_RES_TYPE_NET);
+
+ CU_DEBUG("Found %u net devices on dom '%s'", count, domain_name);
+
+ for (i = 0; i < count; i++) {
+ struct net_device *ndev = &(devices[i].dev.net);
+
+ CU_DEBUG("Checking net device '%s' for filterref",
+ devices[i].id);
+
+ if (STREQC(device_name, devices[i].id)) {
+ CMPIInstance *instance = NULL;
+
+ CU_DEBUG("Processing %s", ndev->filter_ref);
+
+ get_filter_by_name(conn, ndev->filter_ref, &filter);
+ if (filter == NULL)
+ continue;
+
+ s = instance_from_filter(_BROKER,
+ info->context,
+ reference,
+ filter,
+ &instance);
+
+ if (instance != NULL)
+ inst_list_add(list, instance);
+
+ }
+
+ }
+
+ cleanup_virt_devices(&devices, count);
+ out:
+
+ free(domain_name);
+ free((char *)device_name);
+ free(net_name);
+
+ virDomainFree(dom);
+ virConnectClose(conn);
+
+ return s;
+}
+
+LIBVIRT_CIM_DEFAULT_MAKEREF()
+
+static char *antecedent[] = {
+ "KVM_FilterList",
+ NULL
+};
+
+static char *dependent[] = {
+ "KVM_NetworkPort",
+ NULL
+};
+
+static char *assoc_class_name[] = {
+ "KVM_AppliedFilterList",
+ NULL
+};
+
+static struct std_assoc _list_to_net = {
+ .source_class = (char **)&antecedent,
+ .source_prop = "Antecedent",
+
+ .target_class = (char **)&dependent,
+ .target_prop = "Dependent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = list_to_net,
+ .make_ref = make_ref
+};
+
+static struct std_assoc _net_to_list = {
+ .source_class = (char **)&dependent,
+ .source_prop = "Dependent",
+
+ .target_class = (char **)&antecedent,
+ .target_prop = "Antecedent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = net_to_list,
+ .make_ref = make_ref
+};
+
+static struct std_assoc *handlers[] = {
+ &_list_to_net,
+ &_net_to_list,
+ NULL
+};
+
+STDA_AssocMIStub(,
+ Virt_AppliedFilterList,
+ _BROKER,
+ libvirt_cim_init(),
+ handlers);
+
+DEFAULT_GI();
+DEFAULT_EIN();
+DEFAULT_EI();
+
+static CMPIStatus CreateInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIInstance *instance)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIObjectPath *antecedent = NULL;
+ const char *filter_name = NULL;
+ struct acl_filter *filter = NULL;
+ CMPIObjectPath *dependent = NULL;
+ char *domain_name = NULL;
+ const char *device_name = NULL;
+ char *net_name = NULL;
+ struct virt_device *device = NULL;
+ virConnectPtr conn = NULL;
+ virDomainPtr dom = NULL;
+
+ if (cu_get_ref_prop(instance, "Antecedent",
+ &antecedent) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Antecedent property");
+ goto out;
+ }
+
+ if (cu_get_str_path(reference, "Name", &filter_name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Antecedent.Name property");
+ goto out;
+ }
+
+ get_filter_by_name(conn, filter_name, &filter);
+ if (filter == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Antecedent.Name object does not exist");
+ goto out;
+ }
+
+ if (cu_get_ref_prop(instance, "Dependent",
+ &dependent) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Dependent property");
+ goto out;
+ }
+
+ if (cu_get_str_path(reference, "DeviceID",
+ &device_name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Dependent.DeviceID property");
+ goto out;
+ }
+
+ if (parse_fq_devid(device_name, &domain_name, &net_name) == 0) {
+ CU_DEBUG("Failed to parse devid");
+ goto out;
+ }
+
+ dom = virDomainLookupByName(conn, domain_name);
+ if (dom == NULL) {
+ CU_DEBUG("Failed to connect to Domain '%s'", domain_name);
+ goto out;
+ }
+
+ get_device_by_devid(dom, net_name, CIM_RES_TYPE_NET, &device);
+ if (device == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Dependent.Name object does not exist");
+ goto out;
+ }
+
+ free(device->dev.net.filter_ref);
+ device->dev.net.filter_ref = strdup(filter_name);
+
+ if (update_device(dom, device) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to update device");
+ goto out;
+ }
+
+ out:
+ free((char *)filter_name);
+ free(domain_name);
+ free((char *)device_name);
+ free(net_name);
+
+ cleanup_filter(filter);
+ cleanup_virt_device(device);
+
+ virDomainFree(dom);
+ virConnectClose(conn);
+
+ return s;
+}
+
+static CMPIStatus DeleteInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIObjectPath *antecedent = NULL;
+ const char *filter_name = NULL;
+ struct acl_filter *filter = NULL;
+ CMPIObjectPath *dependent = NULL;
+ char *domain_name = NULL;
+ const char *device_name = NULL;
+ char *net_name = NULL;
+ struct virt_device *device = NULL;
+ virConnectPtr conn = NULL;
+ virDomainPtr dom = NULL;
+
+ if (cu_get_ref_path(reference, "Antecedent",
+ &antecedent) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Antecedent property");
+ goto out;
+ }
+
+ if (cu_get_str_path(reference, "Name", &filter_name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Antecedent.Name property");
+ goto out;
+ }
+
+ get_filter_by_name(conn, filter_name, &filter);
+ if (filter == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Antecedent.Name object does not exist");
+ goto out;
+ }
+
+ if (cu_get_ref_path(reference, "Dependent",
+ &dependent) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Dependent property");
+ goto out;
+ }
+
+ if (cu_get_str_path(reference, "DeviceID",
+ &device_name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Dependent.DeviceID property");
+ goto out;
+ }
+
+ if (parse_fq_devid(device_name, &domain_name, &net_name) == 0) {
+ CU_DEBUG("Failed to parse devid");
+ goto out;
+ }
+
+ dom = virDomainLookupByName(conn, domain_name);
+ if (dom == NULL) {
+ CU_DEBUG("Failed to connect to Domain '%s'", domain_name);
+ goto out;
+ }
+
+ get_device_by_devid(dom, net_name, CIM_RES_TYPE_NET, &device);
+ if (device == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Dependent.Name object does not exist");
+ goto out;
+ }
+
+ free(device->dev.net.filter_ref);
+ device->dev.net.filter_ref = NULL;
+
+ if (update_device(dom, device) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to update device");
+ goto out;
+ }
+
+ out:
+ free((char *)filter_name);
+ free(domain_name);
+ free((char *)device_name);
+ free(net_name);
+
+ cleanup_filter(filter);
+ cleanup_virt_device(device);
+
+ virDomainFree(dom);
+ virConnectClose(conn);
+
+ return s;
+}
+
+DEFAULT_MI();
+DEFAULT_EQ();
+DEFAULT_INST_CLEANUP();
+
+STD_InstanceMIStub(,
+ Virt_AppliedFilterEntry,
+ _BROKER,
+ libvirt_cim_init());
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_EntriesInFilterList.c b/src/Virt_EntriesInFilterList.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_EntriesInFilterList.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_association.h>
+
+#include <strings.h>
+
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "Virt_FilterList.h"
+#include "Virt_FilterEntry.h"
+
+static const CMPIBroker *_BROKER;
+
+/**
+ * given a filter, find all *direct* children
+ */
+static CMPIStatus list_to_rule(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+ struct acl_filter *filter = NULL;
+ const char *name = NULL;
+ virConnectPtr conn = NULL;
+ int i;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ get_filter_by_name(conn, name, &filter);
+ if (filter == NULL) {
+ CU_DEBUG("Filter '%s' does not exist", name);
+ goto out;
+ }
+
+ for (i = 0; i < filter->rule_ct; i++) {
+ CU_DEBUG("Processing %s", filter->rules[i]->name);
+
+ s = instance_from_rule(_BROKER,
+ info->context,
+ reference,
+ filter->rules[i],
+ &instance);
+
+ if (instance != NULL) {
+ inst_list_add(list, instance);
+ instance = NULL;
+ }
+ }
+
+ cleanup_filter(filter);
+
+ out:
+ virConnectClose(conn);
+
+ return s;
+}
+
+/**
+ * given a rule, fine the parent filter
+ */
+static CMPIStatus rule_to_list(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct acl_filter *filters = NULL;
+ CMPIInstance *instance = NULL;
+ const char *name = NULL;
+ virConnectPtr conn = NULL;
+ int count = 0;
+ int i, j = 0;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ count = get_filters(conn, &filters);
+ if (filters == NULL)
+ goto out;
+
+ /* return the filter that contains the rule */
+ for (i = 0; i < count; i++) {
+ for (j = 0; j < filters[i].rule_ct; j++) {
+ if (STREQC(name, filters[i].rules[j]->name)) {
+ CU_DEBUG("Processing %s,",filters[i].name);
+
+ s = instance_from_filter(_BROKER,
+ info->context,
+ reference,
+ &filters[i],
+ &instance);
+
+ if (instance != NULL) {
+ inst_list_add(list, instance);
+ instance = NULL;
+ }
+
+ }
+ }
+ }
+
+ out:
+ cleanup_filters(&filters, count);
+ virConnectClose(conn);
+
+ return s;
+}
+
+LIBVIRT_CIM_DEFAULT_MAKEREF()
+
+static char *group_component[] = {
+ "KVM_FilterList",
+ NULL
+};
+
+static char *part_component[] = {
+ "KVM_Hdr8021Filter",
+ "KVM_IPHeadersFilter",
+ NULL
+};
+
+static char *assoc_class_name[] = {
+ "KVM_EntriesInFilterList",
+ NULL
+};
+
+static struct std_assoc _list_to_rule = {
+ .source_class = (char **)&group_component,
+ .source_prop = "GroupComponent",
+
+ .target_class = (char **)&part_component,
+ .target_prop = "PartComponent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = list_to_rule,
+ .make_ref = make_ref
+};
+
+static struct std_assoc _rule_to_list = {
+ .source_class = (char **)&part_component,
+ .source_prop = "PartComponent",
+
+ .target_class = (char **)&group_component,
+ .target_prop = "GroupComponent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = rule_to_list,
+ .make_ref = make_ref
+};
+
+static struct std_assoc *handlers[] = {
+ &_list_to_rule,
+ &_rule_to_list,
+ NULL
+};
+
+STDA_AssocMIStub(,
+ Virt_EntriesInFilterList,
+ _BROKER,
+ libvirt_cim_init(),
+ handlers);
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_FilterEntry.c b/src/Virt_FilterEntry.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_FilterEntry.c
@@ -0,0 +1,678 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_instance.h>
+
+#include <arpa/inet.h>
+
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "xmlgen.h"
+
+#include "Virt_FilterEntry.h"
+#include "Virt_HostSystem.h"
+
+const static CMPIBroker *_BROKER;
+
+static bool is_mac_rule(int type)
+{
+ if (type == MAC_RULE || type == ARP_RULE)
+ return 1;
+
+ return 0;
+}
+
+static bool is_ip_rule(int type)
+{
+ if (type == IP_RULE || type == TCP_RULE || type == ICMP_RULE ||
+ type == IGMP_RULE)
+ return 1;
+
+ return 0;
+}
+
+static int octets_from_mac(const char * s, unsigned int *buffer,
+ unsigned int size)
+{
+ unsigned int _buffer[6];
+ unsigned int i, n = 0;
+
+ if ((s == 0) || (s[0] == '\0') || (buffer == NULL) || (size < 6))
+ return 0;
+
+ if (s[0] == '$') {
+ for (i = 0; (s[i] != '\0') && (i < size); i++)
+ buffer[i] = s[i];
+
+ n = i;
+ }
+ else {
+ n = sscanf(s, "%x:%x:%x:%x:%x:%x",
+ &_buffer[0], &_buffer[1], &_buffer[2],
+ &_buffer[3], &_buffer[4], &_buffer[5]);
+
+ for (i = 0; (i < n) && (i < size); i++)
+ buffer[i] = _buffer[i];
+ }
+
+ return n;
+}
+
+static int octets_from_ip(const char * s, unsigned int *buffer,
+ unsigned int size)
+{
+ struct in6_addr addr;
+ unsigned int family = 0;
+ unsigned int i, n = 0;
+
+ if ((s == 0) || (s[0] == '\0') || (buffer == NULL) || (size < 4))
+ return 0;
+
+ if (s[0] == '$') {
+ for (i = 0; (s[i] != '\0') && (i < size); i++)
+ buffer[i] = s[i];
+
+ n = i;
+ }
+ else {
+ family = strstr(s, ":") ? AF_INET6 : AF_INET;
+ n = family == AF_INET6 ? 16 : 4;
+
+ if (size < n)
+ return 0;
+
+ if (inet_pton(family, s, &addr)) {
+ n = n <= size ? n : size;
+ for (i = 0; i < n; i++)
+ buffer[i] = addr.s6_addr[i];
+ }
+ }
+
+ return n;
+}
+
+static CMPIArray *octets_to_cmpi(const CMPIBroker *broker, unsigned int *bytes, int size)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIArray *array = NULL;
+ int i;
+
+ if (bytes == 0 || size == 0)
+ return array;
+
+ array = CMNewArray(broker, size, CMPI_uint8, &s);
+
+ for (i = 0; i < size; i++) {
+ s = CMSetArrayElementAt(array, i,
+ (CMPIValue*)&bytes[i], CMPI_uint8);
+ }
+
+ return array;
+}
+
+static int convert_direction(const char *s)
+{
+ enum {NOT_APPLICABLE, INPUT, OUTPUT, BOTH} direction = NOT_APPLICABLE;
+
+ if (s != NULL) {
+ if (STREQC(s, "in"))
+ direction = INPUT;
+ else if (STREQC(s, "out"))
+ direction = OUTPUT;
+ else if (STREQC(s, "inout"))
+ direction = BOTH;
+ }
+
+ return direction;
+}
+
+static int convert_priority(const char *s)
+{
+ int priority = 0;
+
+ if (s != NULL) {
+ priority = atoi(s);
+ }
+
+ return priority;
+}
+
+static CMPIInstance *convert_mac_rule_to_instance(
+ struct acl_rule *rule,
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIStatus *s)
+{
+ CMPIInstance *inst = NULL;
+ const char *sys_name = NULL;
+ const char *sys_ccname = NULL;
+ int direction, priority = 0;
+ unsigned int bytes[48];
+ unsigned int size = 0;
+ CMPIArray *array = NULL;
+
+ inst = get_typed_instance(broker,
+ CLASSNAME(reference),
+ "Hdr8021Filter",
+ NAMESPACE(reference));
+ if (inst == NULL) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get 8021 filter instance");
+
+ goto out;
+ }
+
+ *s = get_host_system_properties(&sys_name,
+ &sys_ccname,
+ reference,
+ broker,
+ context);
+
+ if (s->rc != CMPI_RC_OK) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get host attributes");
+ goto out;
+ }
+
+ CMSetProperty(inst, "SystemName", sys_name, CMPI_chars);
+ CMSetProperty(inst, "SystemCreationClassName", sys_ccname, CMPI_chars);
+ CMSetProperty(inst, "Name", (CMPIValue *)rule->name, CMPI_chars);
+
+ direction = convert_direction(rule->direction);
+ CMSetProperty(inst, "Direction", (CMPIValue *)&direction, CMPI_uint16);
+
+ priority = convert_priority(rule->priority);
+ CMSetProperty(inst, "Priority", (CMPIValue *)&priority, CMPI_uint16);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_mac(rule->var.mac.srcmacaddr,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcMACAddr8021",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_mac(rule->var.mac.srcmacmask,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcMACMask8021",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_mac(rule->var.mac.dstmacaddr,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestMACAddr8021", (CMPIValue *)
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_mac(rule->var.mac.dstmacmask,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestMACMask8021", (CMPIValue *)
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ out:
+ return inst;
+}
+
+static CMPIInstance *convert_ip_rule_to_instance(
+ struct acl_rule *rule,
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIStatus *s)
+{
+ CMPIInstance *inst = NULL;
+ const char *sys_name = NULL;
+ const char *sys_ccname = NULL;
+ int direction, priority = 0;
+ unsigned int bytes[48];
+ unsigned int size = 0;
+ unsigned int n = 0;
+ CMPIArray *array = NULL;
+
+ inst = get_typed_instance(broker,
+ CLASSNAME(reference),
+ "IPHeadersFilter",
+ NAMESPACE(reference));
+ if (inst == NULL) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get ip headers filter instance");
+ goto out;
+ }
+
+ *s = get_host_system_properties(&sys_name,
+ &sys_ccname,
+ reference,
+ broker,
+ context);
+
+ if (s->rc != CMPI_RC_OK) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get host attributes");
+ goto out;
+ }
+
+ CMSetProperty(inst, "SystemName", sys_name, CMPI_chars);
+ CMSetProperty(inst, "SystemCreationClassName", sys_ccname, CMPI_chars);
+ CMSetProperty(inst, "Name", (CMPIValue *)rule->name, CMPI_chars);
+
+ direction = convert_direction(rule->direction);
+ CMSetProperty(inst, "Direction", (CMPIValue *)&direction, CMPI_uint16);
+
+ priority = convert_priority(rule->priority);
+ CMSetProperty(inst, "Priority", (CMPIValue *)&priority, CMPI_uint16);
+
+ if (strstr(rule->protocol_id, "v6"))
+ n = 6;
+ else
+ n = 4;
+
+ CMSetProperty(inst, "HdrIPVersion",(CMPIValue *)&n, CMPI_uint8);
+
+ if (rule->var.tcp.srcipfrom && rule->var.tcp.srcipto) {
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.srcipfrom,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcAddress",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.srcipto,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcAddressEndOfRange",
+ (CMPIValue *)&array, CMPI_uint8A);
+ } else {
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.srcmacaddr,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcAddress",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.srcipmask,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcMask",
+ (CMPIValue *)&array, CMPI_uint8A);
+ }
+
+ if (rule->var.tcp.dstipfrom && rule->var.tcp.dstipto) {
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.dstipfrom,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestAddress",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.dstipto,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestAddressEndOfRange",
+ (CMPIValue *)&array, CMPI_uint8A);
+ } else {
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.dstipaddr,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestAddress",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ memset(bytes, 0, sizeof(bytes));
+ size = octets_from_ip(rule->var.tcp.dstipmask,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(broker, bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestMask",
+ (CMPIValue *)&array, CMPI_uint8A);
+ }
+
+ if ((rule->type == IP_RULE) || (rule->type == TCP_RULE)) {
+ if (rule->var.tcp.srcportstart) {
+ n = atoi(rule->var.tcp.srcportstart);
+ CMSetProperty(inst, "HdrSrcPortStart",
+ (CMPIValue *)&n, CMPI_uint16);
+ }
+
+ if (rule->var.tcp.srcportend) {
+ n = atoi(rule->var.tcp.srcportend);
+ CMSetProperty(inst, "HdrSrcPortEnd",
+ (CMPIValue *)&n, CMPI_uint16);
+ }
+
+ if (rule->var.tcp.dstportstart) {
+ n = atoi(rule->var.tcp.dstportstart);
+ CMSetProperty(inst, "HdrDestPortStart",
+ (CMPIValue *)&n, CMPI_uint16);
+ }
+
+ if (rule->var.tcp.dstportend) {
+ n = atoi(rule->var.tcp.dstportend);
+ CMSetProperty(inst, "HdrDestPortEnd",
+ (CMPIValue *)&n, CMPI_uint16);
+ }
+ }
+
+ out:
+ return inst;
+}
+
+static CMPIInstance *convert_rule_to_instance(
+ struct acl_rule *rule,
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIStatus *s)
+{
+ CMPIInstance *instance = NULL;
+
+ if (rule == NULL)
+ return NULL;
+
+ if(is_mac_rule(rule->type)) {
+ instance = convert_mac_rule_to_instance(rule,
+ broker,
+ context,
+ reference,
+ s);
+ }
+ else if(is_ip_rule(rule->type)) {
+ instance = convert_ip_rule_to_instance(rule,
+ broker,
+ context,
+ reference,
+ s);
+ }
+
+ return instance;
+}
+
+CMPIStatus enum_filter_rules(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct inst_list *list)
+{
+ virConnectPtr conn = NULL;
+ struct acl_filter *filters = NULL;
+ int i, j, count = 0;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ enum {NONE, MAC, IP} class_type = NONE;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (STREQC(CLASSNAME(reference), "KVM_Hdr8021Filter"))
+ class_type = MAC;
+ else if (STREQC(CLASSNAME(reference), "KVM_IPHeadersFilter"))
+ class_type = IP;
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ count = get_filters(conn, &filters);
+
+ for (i = 0; i < count; i++) {
+ for (j = 0; j < filters[i].rule_ct; j++) {
+ CMPIInstance *instance = NULL;
+
+ if (((class_type == NONE) ||
+ (class_type == MAC)) &&
+ is_mac_rule(filters[i].rules[j]->type)) {
+ instance = convert_mac_rule_to_instance(
+ filters[i].rules[j],
+ broker,
+ context,
+ reference,
+ &s);
+ }
+ else if (((class_type == NONE) ||
+ (class_type == IP)) &&
+ is_ip_rule(filters[i].rules[j]->type)) {
+ instance = convert_ip_rule_to_instance(
+ filters[i].rules[j],
+ broker,
+ context,
+ reference,
+ &s);
+ }
+ else
+ CU_DEBUG("Unrecognized rule type %u",
+ filters[i].rules[j]->type);
+
+ if (instance != NULL)
+ inst_list_add(list, instance);
+ }
+
+ }
+
+ out:
+ cleanup_filters(&filters, count);
+ virConnectClose(conn);
+
+ return s;
+}
+
+CMPIStatus get_rule_by_ref(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIInstance **instance)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct acl_filter *filter = NULL;
+ struct acl_rule *rule = NULL;
+ const char *name = NULL;
+ char *filter_name = NULL;
+ int rule_index;
+ virConnectPtr conn = NULL;
+ int i;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ if (parse_rule_id(name, &filter_name, &rule_index) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Could not parse filter name");
+ goto out;
+ }
+
+ CU_DEBUG("Filter name = %s, rule index = %u", filter_name, rule_index);
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ get_filter_by_name(conn, filter_name, &filter);
+ if (filter == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Could not retrieve filter");
+ goto out;
+ }
+
+ for (i = 0; i < filter->rule_ct; i++) {
+ if (rule_index == i) {
+ rule = filter->rules[i];
+ break;
+ }
+ }
+
+ if (rule == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Could not retrieve rule");
+ goto out;
+ }
+
+ *instance = convert_rule_to_instance(rule,
+ broker,
+ context,
+ reference,
+ &s);
+ out:
+ free(filter_name);
+ cleanup_filter(filter);
+ virConnectClose(conn);
+
+ return s;
+}
+
+CMPIStatus instance_from_rule(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct acl_rule *rule,
+ CMPIInstance **instance)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+
+ *instance = convert_rule_to_instance(rule,
+ broker,
+ context,
+ reference,
+ &s);
+
+ return s;
+
+}
+
+static CMPIStatus GetInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const char **properties)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+
+ s = get_rule_by_ref(_BROKER, context, reference, &instance);
+
+ if (instance != NULL)
+ CMReturnInstance(results, instance);
+
+ return s;
+}
+
+static CMPIStatus EnumInstanceNames(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct inst_list list;
+
+ inst_list_init(&list);
+
+ s = enum_filter_rules(_BROKER, context, reference, &list);
+
+ cu_return_instance_names(results, &list);
+
+ inst_list_free(&list);
+
+ return s;
+}
+
+static CMPIStatus EnumInstances(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const char **properties)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct inst_list list;
+
+ inst_list_init(&list);
+
+ s = enum_filter_rules(_BROKER, context, reference, &list);
+
+ cu_return_instances(results, &list);
+
+ return s;
+}
+
+DEFAULT_CI();
+DEFAULT_MI();
+DEFAULT_DI();
+DEFAULT_EQ();
+DEFAULT_INST_CLEANUP();
+
+STD_InstanceMIStub(,
+ Virt_FilterEntry,
+ _BROKER,
+ libvirt_cim_init());
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_FilterEntry.h b/src/Virt_FilterEntry.h
new file mode 100644
--- /dev/null
+++ b/src/Virt_FilterEntry.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __VIRT_FILTERENTRY_H
+#define __VIRT_FILTERENTRY_H
+
+/**
+ * Return a list of filter instances
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class name
+ * prefix), but can also be used to scope the results by
+ * specifying the parent filter
+ * @param list A pointer to an array of CMPIInstance objects
+ * (called inits before and frees after)
+ */
+CMPIStatus enum_filter_rules(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct inst_list *list);
+
+/**
+ * Return a single filter instance by reference
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class name
+ * prefix), but can also be used to scope the results by
+ * specifying the parent filter
+ * @param list A pointer to a CMPIInstance *
+ */
+CMPIStatus get_rule_by_ref(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIInstance **instance);
+
+/**
+ * Get an instance representing a filter rule
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class name
+ * prefix), but can also be used to scope the results by
+ * specifying the parent filter
+ * @param rule A pointer to a filter rule
+ * @param instance A pointer to a CMPIInstance *
+ */
+CMPIStatus instance_from_rule(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct acl_rule *rule,
+ CMPIInstance **instance);
+
+#endif
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_FilterList.c b/src/Virt_FilterList.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_FilterList.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_instance.h>
+
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "xmlgen.h"
+
+#include "Virt_FilterList.h"
+#include "Virt_HostSystem.h"
+
+const static CMPIBroker *_BROKER;
+
+static CMPIInstance *convert_filter_to_instance(
+ struct acl_filter *filter,
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIStatus *s)
+{
+ CMPIInstance *inst = NULL;
+ const char *sys_name = NULL;
+ const char *sys_ccname = NULL;
+ int direction = 0;
+
+ inst = get_typed_instance(broker,
+ CLASSNAME(reference),
+ "FilterList",
+ NAMESPACE(reference));
+ if (inst == NULL) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get filter list instance");
+ goto out;
+ }
+
+ *s = get_host_system_properties(&sys_name,
+ &sys_ccname,
+ reference,
+ broker,
+ context);
+
+ if (s->rc != CMPI_RC_OK) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get host attributes");
+ goto out;
+ }
+
+ CMSetProperty(inst, "SystemName", sys_name, CMPI_chars);
+ CMSetProperty(inst, "SystemCreationClassName", sys_ccname, CMPI_chars);
+ CMSetProperty(inst, "Name", (CMPIValue *)filter->name, CMPI_chars);
+ CMSetProperty(inst, "InstanceID", (CMPIValue *)filter->uuid,
+ CMPI_chars);
+ CMSetProperty(inst, "Direction", (CMPIValue *)&direction, CMPI_uint16);
+
+ out:
+ return inst;
+}
+
+CMPIStatus enum_filter_lists(const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct inst_list *list)
+{
+ virConnectPtr conn = NULL;
+ struct acl_filter *filters = NULL;
+ int i, count = 0;
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+
+ conn = connect_by_classname(broker, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ count = get_filters(conn, &filters);
+
+ CU_DEBUG("found %d filters", count);
+
+ for (i = 0; i < count; i++) {
+ instance = convert_filter_to_instance(&filters[i],
+ broker,
+ context,
+ reference,
+ &s);
+
+ if (instance != NULL)
+ inst_list_add(list, instance);
+ }
+
+ out:
+ cleanup_filters(&filters, count);
+ virConnectClose(conn);
+
+ return s;
+}
+
+CMPIStatus get_filter_by_ref(const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIInstance **instance)
+{
+ virConnectPtr conn = NULL;
+ struct acl_filter *filter = NULL;
+
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ const char *name = NULL;
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ conn = connect_by_classname(broker, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ get_filter_by_name(conn, name, &filter);
+ if (filter == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "No such instance (Name)");
+ goto out;
+ }
+
+ s = instance_from_filter(broker, context, reference, filter, instance);
+
+ out:
+ cleanup_filter(filter);
+ virConnectClose(conn);
+
+ return s;
+}
+
+CMPIStatus instance_from_filter(const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct acl_filter *filter,
+ CMPIInstance **instance)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+
+ *instance = convert_filter_to_instance(filter, broker, context,
+ reference, &s);
+
+ return s;
+}
+
+static CMPIStatus GetInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const char **properties)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+
+ s = get_filter_by_ref(_BROKER, context, reference, &instance);
+
+ if (instance != NULL)
+ CMReturnInstance(results, instance);
+
+ return s;
+}
+
+static CMPIStatus EnumInstanceNames(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct inst_list list;
+
+ inst_list_init(&list);
+
+ s = enum_filter_lists(_BROKER, context, reference, &list);
+
+ cu_return_instance_names(results, &list);
+
+ inst_list_free(&list);
+
+ return s;
+}
+
+static CMPIStatus EnumInstances(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const char **properties)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct inst_list list;
+
+ inst_list_init(&list);
+
+ s = enum_filter_lists(_BROKER, context, reference, &list);
+
+ cu_return_instances(results, &list);
+
+ inst_list_free(&list);
+
+ return s;
+}
+
+DEFAULT_CI();
+DEFAULT_MI();
+DEFAULT_DI();
+DEFAULT_EQ();
+DEFAULT_INST_CLEANUP();
+
+STD_InstanceMIStub(,
+ Virt_FilterList,
+ _BROKER,
+ libvirt_cim_init());
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_FilterList.h b/src/Virt_FilterList.h
new file mode 100644
--- /dev/null
+++ b/src/Virt_FilterList.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __VIRT_FILTERLIST_H
+#define __VIRT_FILTERLIST_H
+
+#include "acl_parsing.h"
+
+/**
+ * Return a list of filter lists
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class name
+ * prefix), but can also be used to scope the results by
+ * specifying a specific filter
+ * @param list A pointer to an array of CMPIInstance objects
+ * (caller inits before and frees after)
+ */
+CMPIStatus enum_filter_lists(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct inst_list *list);
+
+/**
+ * Return a filter instance by reference
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class name
+ * prefix), but can also be used to scope the results by
+ * specifying a specific filter
+ * @param instance A pointer to a CMPIInstance * to place the new instance
+ */
+CMPIStatus get_filter_by_ref(
+ const CMPIBroker *broker,
+ const CMPIContext *contest,
+ const CMPIObjectPath *reference,
+ CMPIInstance **instance);
+
+/**
+ * Return a list of filter lists
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class name
+ * prefix), but can also be used to scope the results by
+ * specifying a specific filter
+ * @param filter A pointer to a acl_filter
+ * @param instance A pointer to a CMPIInstance * to place the new instance
+ */
+CMPIStatus instance_from_filter(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct acl_filter *filter,
+ CMPIInstance **instance);
+
+#endif
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_HostedFilterList.c b/src/Virt_HostedFilterList.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_HostedFilterList.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_association.h>
+
+#include "misc_util.h"
+#include "Virt_HostSystem.h"
+#include "Virt_FilterList.h"
+
+static const CMPIBroker *_BROKER;
+
+static CMPIStatus host_to_list(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+
+ /* validate host reference */
+ s = get_host(_BROKER, info->context, reference, &instance, false);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ s = cu_validate_ref(_BROKER, reference, instance);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ s = enum_filter_lists(_BROKER, info->context, reference, list);
+
+ out:
+ return s;
+}
+
+static CMPIStatus list_to_host(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+
+ /* validate filter reference */
+ s = get_filter_by_ref(_BROKER, info->context, reference, &instance);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ s = get_host(_BROKER, info->context, reference, &instance, false);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ if (instance != NULL)
+ inst_list_add(list, instance);
+
+ out:
+ return s;
+}
+
+LIBVIRT_CIM_DEFAULT_MAKEREF()
+
+static char *antecedent[] = {
+ "KVM_HostSystem",
+ NULL
+};
+
+static char *dependent[] = {
+ "KVM_FilterList",
+ NULL
+};
+
+static char *assoc_class_name[] = {
+ "KVM_HostedFilterList",
+ NULL
+};
+
+static struct std_assoc _host_to_list = {
+ .source_class = (char **)&antecedent,
+ .source_prop = "Antecedent",
+
+ .target_class = (char **)&dependent,
+ .target_prop = "Dependent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = host_to_list,
+ .make_ref = make_ref
+};
+
+static struct std_assoc _list_to_host = {
+ .source_class = (char **)&dependent,
+ .source_prop = "Dependent",
+
+ .target_class = (char **)&antecedent,
+ .target_prop = "Antecedent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = list_to_host,
+ .make_ref = make_ref
+};
+
+static struct std_assoc *handlers[] = {
+ &_host_to_list,
+ &_list_to_host,
+ NULL
+};
+
+STDA_AssocMIStub(,
+ Virt_HostedFilterList,
+ _BROKER,
+ libvirt_cim_init(),
+ handlers);
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_NestedFilterList.c b/src/Virt_NestedFilterList.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_NestedFilterList.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_association.h>
+#include <libcmpiutil/std_instance.h>
+
+/* FIXME: This seems to be needed to compile STREQC, which suggests
+ * libcmpiutil.h needs to add the include since the marco is defined there.
+ */
+#include <string.h>
+#include <strings.h>
+
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "Virt_FilterList.h"
+
+static const CMPIBroker *_BROKER;
+
+/**
+ * given a filter, find all *direct* filter_refs
+ */
+static CMPIStatus parent_to_child(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct acl_filter *parent_filter = NULL;
+ struct acl_filter *child_filter = NULL;
+ CMPIInstance *instance = NULL;
+ const char * name = NULL;
+ virConnectPtr conn = NULL;
+ int i;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ get_filter_by_name(conn, name, &parent_filter);
+ if (parent_filter == NULL)
+ goto out;
+
+ for (i = 0; i < parent_filter->ref_ct; i++) {
+ get_filter_by_name(conn, parent_filter->refs[i],
+ &child_filter);
+ if (child_filter == NULL)
+ continue;
+
+ CU_DEBUG("Processing %s,", child_filter->name);
+
+ s = instance_from_filter(_BROKER,
+ info->context,
+ reference,
+ child_filter,
+ &instance);
+
+ if (instance != NULL) {
+ CU_DEBUG("Adding instance to inst_list");
+ inst_list_add(list, instance);
+ }
+
+ cleanup_filter(child_filter);
+
+ child_filter = NULL;
+ instance = NULL;
+ }
+
+ cleanup_filter(parent_filter);
+
+ out:
+ virConnectClose(conn);
+
+ return s;
+}
+
+/**
+ * given a filter, find all the other filters that reference it
+ */
+static CMPIStatus child_to_parent(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ struct acl_filter *_list = NULL;
+ CMPIInstance *instance = NULL;
+ const char *name = NULL;
+ virConnectPtr conn = NULL;
+ int count, i, j;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Unable to get Name from reference");
+ goto out;
+ }
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ /* TODO: Ensure the referenced filter exists */
+
+ count = get_filters(conn, &_list);
+ if (_list == NULL)
+ goto out;
+
+ /* return any filter that has name in refs */
+ for (i = 0; i < count; i++) {
+ for (j = 0; j < _list[i].ref_ct; j++) {
+ if (STREQC(name, _list[i].refs[j])) {
+ CU_DEBUG("Processing %s,", _list[i].name);
+
+ s = instance_from_filter(_BROKER,
+ info->context,
+ reference,
+ &_list[i],
+ &instance);
+
+ if (instance != NULL)
+ inst_list_add(list, instance);
+
+ instance = NULL;
+ }
+
+ }
+
+ cleanup_filter(&_list[i]);
+ }
+
+ free(_list);
+
+ out:
+ virConnectClose(conn);
+
+ return s;
+}
+
+LIBVIRT_CIM_DEFAULT_MAKEREF()
+
+static char *antecedent[] = {
+ "KVM_FilterList",
+ NULL
+};
+
+static char *dependent[] = {
+ "KVM_FilterList",
+ NULL
+};
+
+static char *assoc_class_name[] = {
+ "KVM_NestedFilterList",
+ NULL
+};
+
+static struct std_assoc _list_to_filter_ref = {
+ .source_class = (char **)&antecedent,
+ .source_prop = "Antecedent",
+
+ .target_class = (char **)&dependent,
+ .target_prop = "Dependent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = parent_to_child,
+ .make_ref = make_ref
+};
+
+static struct std_assoc _filter_ref_to_list = {
+ .source_class = (char **)&dependent,
+ .source_prop = "Dependent",
+
+ .target_class = (char **)&antecedent,
+ .target_prop = "Antecedent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = child_to_parent,
+ .make_ref = make_ref
+};
+
+static struct std_assoc *handlers[] = {
+ &_list_to_filter_ref,
+ &_filter_ref_to_list,
+ NULL
+};
+
+STDA_AssocMIStub(,
+ Virt_NestedFilterList,
+ _BROKER,
+ libvirt_cim_init(),
+ handlers);
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
13 years, 5 months
CIMTest run performance
by Eduardo Lima (Etrunko)
Hello all,
I had been trying to set up cimtest to work on my machine for a couple
of days without success. So yesterday I started to dig the code and
found that every command is sent via ssh, even if the test is supposed
to run locally.
The reason of cimtest not working was exactly that did not have the ssh
keys set up properly. By fixing that configuration, I was able to make
the test work as expected. :)
But I was still intrigued with the fact that every command is sent via
ssh, thus taking cimtest a very very long time to complete. So I hacked
a simple patch to try to workaround this issue:
=====
diff -r d6951b8799a8 lib/VirtLib/utils.py
--- a/lib/VirtLib/utils.py Wed May 18 13:49:05 2011 -0400
+++ b/lib/VirtLib/utils.py Fri May 27 07:42:23 2011 -0700
@@ -33,7 +33,8 @@
def run_remote(ip, cmd):
- cmd = 'ssh %s -i %s root@%s "%s"' % (SSH_PARMS, SSH_KEY, ip, cmd)
+ if ip not in ["localhost", "127.0.0.1"]:
+ cmd = 'ssh %s -i %s root@%s "%s"' % (SSH_PARMS, SSH_KEY, ip, cmd)
return commands.getstatusoutput(cmd)
def copy_remote(ip, local, remote='/tmp'):
=====
As you can see, it is a quick check if 'ip' is neither localhost nor
127.0.0.1, which only in that case the command is sent via ssh.
Note that this patch triggers some other issues, which I hope to be able
to fix soon. But there is already a *huge increase* in the performance.
I have used the most simpler and probably not the most correct measure:
$ time && cimtest && time
With the following results:
Without patch:
Fri May 27 06:46:28 PDT 2011
Fri May 27 07:16:17 PDT 2011
With patch:
Fri May 27 07:29:06 PDT 2011
Fri May 27 07:34:50 PDT 2011
From 30 minutes down to 6!
_BUT_, I can't really tell if it is actually intended that everything
runs with ssh. Taking a look on the test results, it is noticeable that
cimtest behaves in a different way, as follows.
Without path:
FAIL : 18
XFAIL : 5
SKIP : 6
PASS : 158
-----------------
Total : 187
=================================================
FAIL Test Summary:
ComputerSystem - 04_defineStartVS.py: FAIL
ComputerSystemMigrationJobIndication -
01_csmig_ind_for_offline_mig.py: FAIL
ElementSettingData - 01_forward.py: FAIL
HostSystem - 02_hostsystem_to_rasd.py: FAIL
HostSystem - 04_hs_to_EAPF.py: FAIL
KVMRedirectionSAP - 02_ipv6_support.py: FAIL
Profile - 02_profile_to_elec.py: FAIL
Profile - 04_verify_libvirt_cim_slp_profiles.py: FAIL
SystemDevice - 01_forward.py: FAIL
VirtualSystemManagementService - 13_refconfig_additional_devs.py: FAIL
VirtualSystemManagementService - 19_definenetwork_ers.py: FAIL
VirtualSystemManagementService - 20_verify_vnc_password.py: FAIL
VirtualSystemMigrationService - 06_remote_live_migration.py: FAIL
VirtualSystemMigrationService - 07_remote_offline_migration.py: FAIL
VirtualSystemMigrationService -
08_remote_restart_resume_migration.py: FAIL
VirtualSystemSettingDataComponent - 01_forward.py: FAIL
VirtualSystemSettingDataComponent - 02_reverse.py: FAIL
VSSD - 04_vssd_to_rasd.py: FAIL
=================================================
XFAIL Test Summary:
ComputerSystem - 32_start_reboot.py: XFAIL
SwitchService - 01_enum.py: XFAIL
VirtualSystemManagementService - 22_addmulti_brg_interface.py: XFAIL
VirtualSystemManagementService - 28_definesystem_with_vsi_profile.py:
XFAIL
VirtualSystemManagementService - 30_dynamic_disk_mod.py: XFAIL
=================================================
SKIP Test Summary:
ComputerSystem - 02_nosystems.py: SKIP
LogicalDisk - 02_nodevs.py: SKIP
VirtualSystemMigrationService - 01_migratable_host.py: SKIP
VirtualSystemMigrationService - 02_host_migrate_type.py: SKIP
VirtualSystemMigrationService - 05_migratable_host_errs.py: SKIP
VSSD - 02_bootldr.py: SKIP
With patch:
FAIL : 15
XFAIL : 5
SKIP : 10
PASS : 157
-----------------
Total : 187
=================================================
FAIL Test Summary:
ComputerSystem - 04_defineStartVS.py: FAIL
ComputerSystem - 41_cs_to_settingdefinestate.py: FAIL
ElementSettingData - 01_forward.py: FAIL
HostSystem - 02_hostsystem_to_rasd.py: FAIL
HostSystem - 04_hs_to_EAPF.py: FAIL
KVMRedirectionSAP - 02_ipv6_support.py: FAIL
Profile - 02_profile_to_elec.py: FAIL
Profile - 04_verify_libvirt_cim_slp_profiles.py: FAIL
SystemDevice - 01_forward.py: FAIL
VirtualSystemManagementService - 06_addresource.py: FAIL
VirtualSystemManagementService - 13_refconfig_additional_devs.py: FAIL
VirtualSystemManagementService - 20_verify_vnc_password.py: FAIL
VirtualSystemSettingDataComponent - 01_forward.py: FAIL
VirtualSystemSettingDataComponent - 02_reverse.py: FAIL
VSSD - 04_vssd_to_rasd.py: FAIL
=================================================
XFAIL Test Summary:
ComputerSystem - 32_start_reboot.py: XFAIL
SwitchService - 01_enum.py: XFAIL
VirtualSystemManagementService - 22_addmulti_brg_interface.py: XFAIL
VirtualSystemManagementService - 28_definesystem_with_vsi_profile.py: XFAIL
VirtualSystemManagementService - 30_dynamic_disk_mod.py: XFAIL
=================================================
SKIP Test Summary:
ComputerSystem - 02_nosystems.py: SKIP
ComputerSystemMigrationJobIndication - 01_csmig_ind_for_offline_mig.py: SKIP
LogicalDisk - 02_nodevs.py: SKIP
VirtualSystemMigrationService - 01_migratable_host.py: SKIP
VirtualSystemMigrationService - 02_host_migrate_type.py: SKIP
VirtualSystemMigrationService - 05_migratable_host_errs.py: SKIP
VirtualSystemMigrationService - 06_remote_live_migration.py: SKIP
VirtualSystemMigrationService - 07_remote_offline_migration.py: SKIP
VirtualSystemMigrationService - 08_remote_restart_resume_migration.py: SKIP
VSSD - 02_bootldr.py: SKIP
I would really appreciate comments from the experts on this issue. IMHO,
it is something really worthy and if there are any tests that are
required to run remotely, I could work on a proper fix to try to achieve
the same results.
Best regards, Etrunko
--
Eduardo de Barros Lima
Software Engineer, Open Virtualization
Linux Technology Center - IBM/Brazil
eblima(a)br.ibm.com
13 years, 5 months
[PATCH] Cimtest: Handle keyboard interrupt
by Eduardo Lima (Etrunko)
# HG changeset patch
# User Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
# Date 1306522145 10800
# Node ID c7ff1c6e7cb60b37ce6d2ce4fbf58535b3b3fc9e
# Parent 01aa645a1e1269eb31d1fdd9de8d7e9120f5fa74
Cimtest: Handle keyboard interrupt
During my tests I have noticed that if the user interrupts the program
execution, by pressing Ctrl+C, the next time cimtest runs, it will fail
due to leftovers of previous execution, especially, a disk pool called
cimtest-diskpool and a network called cimtest-netpool.
With this patch, if a KeyboardInterrupt exception occurs, the
cleanup_env() function will be called before the program exit.
Signed-off-by: Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
diff --git a/suites/libvirt-cim/main.py b/suites/libvirt-cim/main.py
--- a/suites/libvirt-cim/main.py
+++ b/suites/libvirt-cim/main.py
@@ -176,8 +176,7 @@
testsuite.debug("%s %sh | %smin | %ssec | %smsec" %
(prefix, h, m, s, msec))
-def main():
- (options, args) = parser.parse_args()
+def main(options, args):
to_addr = None
from_addr = None
relay = None
@@ -302,7 +301,21 @@
(from_addr, to_addr, relay)
send_report(to_addr, from_addr, relay, msg_body, heading)
+ return 0
+# main()
+
if __name__ == '__main__':
- sys.exit(main())
+ try:
+ options, args = parser.parse_args()
+ ret = main(options, args)
+ except (KeyboardInterrupt, SystemExit):
+ ret = -1
+ print "\nKeyboardInterrupt. Cleaning up..."
+ status = cleanup_env(options.ip, options.virt)
+ if status != PASS:
+ print "Unable to clean up. Please check your environment."
+ else:
+ print "Clean up successful"
+ sys.exit(ret)
13 years, 5 months
[PATCH] #2 Fix file permissions
by Eduardo Lima (Etrunko)
# HG changeset patch
# User Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
# Date 1306261772 10800
# Node ID 12538a8f8fee7574119b4b16411ea80e6cda0ec2
# Parent f51a1ccadbcce1c7f9ba6268267866f7721420c1
Fix file permissions
Removing exec flag from source code files.
Changes from #1
- Added .hgtags to the patch
Signed-off-by: Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
diff --git a/.hgtags b/.hgtags
old mode 100755
new mode 100644
diff --git a/Makefile.am b/Makefile.am
old mode 100755
new mode 100644
diff --git a/README b/README
old mode 100755
new mode 100644
diff --git a/acinclude.m4 b/acinclude.m4
old mode 100755
new mode 100644
diff --git a/base_schema/Makefile.am b/base_schema/Makefile.am
old mode 100755
new mode 100644
diff --git a/base_schema/install_base_schema.sh.in b/base_schema/install_base_schema.sh.in
old mode 100755
new mode 100644
diff --git a/configure.ac b/configure.ac
old mode 100755
new mode 100644
diff --git a/doc/CodingStyle b/doc/CodingStyle
old mode 100755
new mode 100644
diff --git a/doc/Makefile.am b/doc/Makefile.am
old mode 100755
new mode 100644
diff --git a/doc/libvirt-cim.html b/doc/libvirt-cim.html
old mode 100755
new mode 100644
diff --git a/libvirt-cim.spec.in b/libvirt-cim.spec.in
old mode 100755
new mode 100644
diff --git a/libxkutil/Makefile.am b/libxkutil/Makefile.am
old mode 100755
new mode 100644
diff --git a/libxkutil/device_parsing.c b/libxkutil/device_parsing.c
old mode 100755
new mode 100644
diff --git a/libxkutil/device_parsing.h b/libxkutil/device_parsing.h
old mode 100755
new mode 100644
diff --git a/libxkutil/infostore.c b/libxkutil/infostore.c
old mode 100755
new mode 100644
diff --git a/libxkutil/misc_util.c b/libxkutil/misc_util.c
old mode 100755
new mode 100644
diff --git a/libxkutil/misc_util.h b/libxkutil/misc_util.h
old mode 100755
new mode 100644
diff --git a/libxkutil/xml_parse_test.c b/libxkutil/xml_parse_test.c
old mode 100755
new mode 100644
diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c
old mode 100755
new mode 100644
diff --git a/schema/AllocationCapabilities.registration b/schema/AllocationCapabilities.registration
old mode 100755
new mode 100644
diff --git a/schema/ComputerSystem.registration b/schema/ComputerSystem.registration
old mode 100755
new mode 100644
diff --git a/schema/ComputerSystemIndication.registration b/schema/ComputerSystemIndication.registration
old mode 100755
new mode 100644
diff --git a/schema/ComputerSystemMigrationIndication.mof b/schema/ComputerSystemMigrationIndication.mof
old mode 100755
new mode 100644
diff --git a/schema/ComputerSystemMigrationIndication.registration b/schema/ComputerSystemMigrationIndication.registration
old mode 100755
new mode 100644
diff --git a/schema/ConcreteComponent.registration b/schema/ConcreteComponent.registration
old mode 100755
new mode 100644
diff --git a/schema/ConsoleRedirectionService.mof b/schema/ConsoleRedirectionService.mof
old mode 100755
new mode 100644
diff --git a/schema/ConsoleRedirectionService.registration b/schema/ConsoleRedirectionService.registration
old mode 100755
new mode 100644
diff --git a/schema/ConsoleRedirectionServiceCapabilities.registration b/schema/ConsoleRedirectionServiceCapabilities.registration
old mode 100755
new mode 100644
diff --git a/schema/DiskPool.registration b/schema/DiskPool.registration
old mode 100755
new mode 100644
diff --git a/schema/ElementAllocatedFromPool.registration b/schema/ElementAllocatedFromPool.registration
old mode 100755
new mode 100644
diff --git a/schema/ElementConformsToProfile.registration b/schema/ElementConformsToProfile.registration
old mode 100755
new mode 100644
diff --git a/schema/ElementSettingData.mof b/schema/ElementSettingData.mof
old mode 100755
new mode 100644
diff --git a/schema/ElementSettingData.registration b/schema/ElementSettingData.registration
old mode 100755
new mode 100644
diff --git a/schema/EnabledLogicalElementCapabilities.registration b/schema/EnabledLogicalElementCapabilities.registration
old mode 100755
new mode 100644
diff --git a/schema/GraphicsPool.mof b/schema/GraphicsPool.mof
old mode 100755
new mode 100644
diff --git a/schema/GraphicsPool.registration b/schema/GraphicsPool.registration
old mode 100755
new mode 100644
diff --git a/schema/HostSystem.registration b/schema/HostSystem.registration
old mode 100755
new mode 100644
diff --git a/schema/HostedAccessPoint.mof b/schema/HostedAccessPoint.mof
old mode 100755
new mode 100644
diff --git a/schema/HostedAccessPoint.registration b/schema/HostedAccessPoint.registration
old mode 100755
new mode 100644
diff --git a/schema/HostedDependency.mof b/schema/HostedDependency.mof
old mode 100755
new mode 100644
diff --git a/schema/HostedDependency.registration b/schema/HostedDependency.registration
old mode 100755
new mode 100644
diff --git a/schema/HostedResourcePool.registration b/schema/HostedResourcePool.registration
old mode 100755
new mode 100644
diff --git a/schema/HostedService.registration b/schema/HostedService.registration
old mode 100755
new mode 100644
diff --git a/schema/InputPool.mof b/schema/InputPool.mof
old mode 100755
new mode 100644
diff --git a/schema/InputPool.registration b/schema/InputPool.registration
old mode 100755
new mode 100644
diff --git a/schema/KVMRedirectionSAP.mof b/schema/KVMRedirectionSAP.mof
old mode 100755
new mode 100644
diff --git a/schema/KVMRedirectionSAP.registration b/schema/KVMRedirectionSAP.registration
old mode 100755
new mode 100644
diff --git a/schema/LogicalDisk.registration b/schema/LogicalDisk.registration
old mode 100755
new mode 100644
diff --git a/schema/Memory.registration b/schema/Memory.registration
old mode 100755
new mode 100644
diff --git a/schema/MemoryPool.registration b/schema/MemoryPool.registration
old mode 100755
new mode 100644
diff --git a/schema/NetPool.registration b/schema/NetPool.registration
old mode 100755
new mode 100644
diff --git a/schema/NetworkPort.registration b/schema/NetworkPort.registration
old mode 100755
new mode 100644
diff --git a/schema/Processor.registration b/schema/Processor.registration
old mode 100755
new mode 100644
diff --git a/schema/ProcessorPool.registration b/schema/ProcessorPool.registration
old mode 100755
new mode 100644
diff --git a/schema/ReferencedProfile.mof b/schema/ReferencedProfile.mof
old mode 100755
new mode 100644
diff --git a/schema/ReferencedProfile.registration b/schema/ReferencedProfile.registration
old mode 100755
new mode 100644
diff --git a/schema/ResourceAllocationFromPool.registration b/schema/ResourceAllocationFromPool.registration
old mode 100755
new mode 100644
diff --git a/schema/ResourceAllocationSettingData.mof b/schema/ResourceAllocationSettingData.mof
old mode 100755
new mode 100644
diff --git a/schema/ResourceAllocationSettingData.registration b/schema/ResourceAllocationSettingData.registration
old mode 100755
new mode 100644
diff --git a/schema/ResourcePoolConfigurationCapabilities.registration b/schema/ResourcePoolConfigurationCapabilities.registration
old mode 100755
new mode 100644
diff --git a/schema/ResourcePoolConfigurationService.registration b/schema/ResourcePoolConfigurationService.registration
old mode 100755
new mode 100644
diff --git a/schema/ServiceAccessBySAP.mof b/schema/ServiceAccessBySAP.mof
old mode 100755
new mode 100644
diff --git a/schema/ServiceAccessBySAP.registration b/schema/ServiceAccessBySAP.registration
old mode 100755
new mode 100644
diff --git a/schema/SettingsDefineCapabilities.registration b/schema/SettingsDefineCapabilities.registration
old mode 100755
new mode 100644
diff --git a/schema/SettingsDefineState.registration b/schema/SettingsDefineState.registration
old mode 100755
new mode 100644
diff --git a/schema/SystemDevice.registration b/schema/SystemDevice.registration
old mode 100755
new mode 100644
diff --git a/schema/VSMigrationCapabilities.mof b/schema/VSMigrationCapabilities.mof
old mode 100755
new mode 100644
diff --git a/schema/VSMigrationCapabilities.registration b/schema/VSMigrationCapabilities.registration
old mode 100755
new mode 100644
diff --git a/schema/VSMigrationService.mof b/schema/VSMigrationService.mof
old mode 100755
new mode 100644
diff --git a/schema/VSMigrationService.registration b/schema/VSMigrationService.registration
old mode 100755
new mode 100644
diff --git a/schema/VSMigrationSettingData.mof b/schema/VSMigrationSettingData.mof
old mode 100755
new mode 100644
diff --git a/schema/VSMigrationSettingData.registration b/schema/VSMigrationSettingData.registration
old mode 100755
new mode 100644
diff --git a/schema/VSSD.mof b/schema/VSSD.mof
old mode 100755
new mode 100644
diff --git a/schema/VSSD.registration b/schema/VSSD.registration
old mode 100755
new mode 100644
diff --git a/schema/VSSDComponent.mof b/schema/VSSDComponent.mof
old mode 100755
new mode 100644
diff --git a/schema/VSSDComponent.registration b/schema/VSSDComponent.registration
old mode 100755
new mode 100644
diff --git a/schema/Virt_ResourceAllocationSettingData.mof b/schema/Virt_ResourceAllocationSettingData.mof
old mode 100755
new mode 100644
diff --git a/schema/Virt_VSSD.mof b/schema/Virt_VSSD.mof
old mode 100755
new mode 100644
diff --git a/schema/VirtualSystemManagementCapabilities.registration b/schema/VirtualSystemManagementCapabilities.registration
old mode 100755
new mode 100644
diff --git a/schema/VirtualSystemManagementService.registration b/schema/VirtualSystemManagementService.registration
old mode 100755
new mode 100644
diff --git a/schema/VirtualSystemSnapshotService.mof b/schema/VirtualSystemSnapshotService.mof
old mode 100755
new mode 100644
diff --git a/src/Makefile.am b/src/Makefile.am
old mode 100755
new mode 100644
diff --git a/src/Virt_AllocationCapabilities.c b/src/Virt_AllocationCapabilities.c
old mode 100755
new mode 100644
diff --git a/src/Virt_AllocationCapabilities.h b/src/Virt_AllocationCapabilities.h
old mode 100755
new mode 100644
diff --git a/src/Virt_ComputerSystem.c b/src/Virt_ComputerSystem.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ComputerSystem.h b/src/Virt_ComputerSystem.h
old mode 100755
new mode 100644
diff --git a/src/Virt_ComputerSystemIndication.c b/src/Virt_ComputerSystemIndication.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ComputerSystemMigrationIndication.c b/src/Virt_ComputerSystemMigrationIndication.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ConcreteComponent.c b/src/Virt_ConcreteComponent.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ConsoleRedirectionService.c b/src/Virt_ConsoleRedirectionService.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ConsoleRedirectionServiceCapabilities.c b/src/Virt_ConsoleRedirectionServiceCapabilities.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ConsoleRedirectionServiceCapabilities.h b/src/Virt_ConsoleRedirectionServiceCapabilities.h
old mode 100755
new mode 100644
diff --git a/src/Virt_Device.c b/src/Virt_Device.c
old mode 100755
new mode 100644
diff --git a/src/Virt_DevicePool.c b/src/Virt_DevicePool.c
old mode 100755
new mode 100644
diff --git a/src/Virt_DevicePool.h b/src/Virt_DevicePool.h
old mode 100755
new mode 100644
diff --git a/src/Virt_ElementAllocatedFromPool.c b/src/Virt_ElementAllocatedFromPool.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ElementCapabilities.c b/src/Virt_ElementCapabilities.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ElementConformsToProfile.c b/src/Virt_ElementConformsToProfile.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ElementSettingData.c b/src/Virt_ElementSettingData.c
old mode 100755
new mode 100644
diff --git a/src/Virt_EnabledLogicalElementCapabilities.c b/src/Virt_EnabledLogicalElementCapabilities.c
old mode 100755
new mode 100644
diff --git a/src/Virt_HostSystem.c b/src/Virt_HostSystem.c
old mode 100755
new mode 100644
diff --git a/src/Virt_HostSystem.h b/src/Virt_HostSystem.h
old mode 100755
new mode 100644
diff --git a/src/Virt_HostedAccessPoint.c b/src/Virt_HostedAccessPoint.c
old mode 100755
new mode 100644
diff --git a/src/Virt_HostedDependency.c b/src/Virt_HostedDependency.c
old mode 100755
new mode 100644
diff --git a/src/Virt_HostedResourcePool.c b/src/Virt_HostedResourcePool.c
old mode 100755
new mode 100644
diff --git a/src/Virt_HostedService.c b/src/Virt_HostedService.c
old mode 100755
new mode 100644
diff --git a/src/Virt_KVMRedirectionSAP.c b/src/Virt_KVMRedirectionSAP.c
old mode 100755
new mode 100644
diff --git a/src/Virt_KVMRedirectionSAP.h b/src/Virt_KVMRedirectionSAP.h
old mode 100755
new mode 100644
diff --git a/src/Virt_RASD.c b/src/Virt_RASD.c
old mode 100755
new mode 100644
diff --git a/src/Virt_RASD.h b/src/Virt_RASD.h
old mode 100755
new mode 100644
diff --git a/src/Virt_ReferencedProfile.c b/src/Virt_ReferencedProfile.c
old mode 100755
new mode 100644
diff --git a/src/Virt_RegisteredProfile.c b/src/Virt_RegisteredProfile.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ResourceAllocationFromPool.c b/src/Virt_ResourceAllocationFromPool.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ResourcePoolConfigurationCapabilities.c b/src/Virt_ResourcePoolConfigurationCapabilities.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ResourcePoolConfigurationService.c b/src/Virt_ResourcePoolConfigurationService.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ResourcePoolConfigurationService.h b/src/Virt_ResourcePoolConfigurationService.h
old mode 100755
new mode 100644
diff --git a/src/Virt_ServiceAccessBySAP.c b/src/Virt_ServiceAccessBySAP.c
old mode 100755
new mode 100644
diff --git a/src/Virt_ServiceAffectsElement.c b/src/Virt_ServiceAffectsElement.c
old mode 100755
new mode 100644
diff --git a/src/Virt_SettingsDefineCapabilities.c b/src/Virt_SettingsDefineCapabilities.c
old mode 100755
new mode 100644
diff --git a/src/Virt_SettingsDefineCapabilities.h b/src/Virt_SettingsDefineCapabilities.h
old mode 100755
new mode 100644
diff --git a/src/Virt_SettingsDefineState.c b/src/Virt_SettingsDefineState.c
old mode 100755
new mode 100644
diff --git a/src/Virt_SystemDevice.c b/src/Virt_SystemDevice.c
old mode 100755
new mode 100644
diff --git a/src/Virt_VSMigrationCapabilities.c b/src/Virt_VSMigrationCapabilities.c
old mode 100755
new mode 100644
diff --git a/src/Virt_VSMigrationService.c b/src/Virt_VSMigrationService.c
old mode 100755
new mode 100644
diff --git a/src/Virt_VSMigrationService.h b/src/Virt_VSMigrationService.h
old mode 100755
new mode 100644
diff --git a/src/Virt_VSMigrationSettingData.c b/src/Virt_VSMigrationSettingData.c
old mode 100755
new mode 100644
diff --git a/src/Virt_VSSD.c b/src/Virt_VSSD.c
old mode 100755
new mode 100644
diff --git a/src/Virt_VSSDComponent.c b/src/Virt_VSSDComponent.c
old mode 100755
new mode 100644
diff --git a/src/Virt_VirtualSystemManagementCapabilities.c b/src/Virt_VirtualSystemManagementCapabilities.c
old mode 100755
new mode 100644
diff --git a/src/Virt_VirtualSystemManagementService.c b/src/Virt_VirtualSystemManagementService.c
old mode 100755
new mode 100644
diff --git a/src/Virt_VirtualSystemManagementService.h b/src/Virt_VirtualSystemManagementService.h
old mode 100755
new mode 100644
diff --git a/src/Virt_VirtualSystemSnapshotService.c b/src/Virt_VirtualSystemSnapshotService.c
old mode 100755
new mode 100644
diff --git a/src/Virt_VirtualSystemSnapshotService.h b/src/Virt_VirtualSystemSnapshotService.h
old mode 100755
new mode 100644
diff --git a/src/profiles.h b/src/profiles.h
old mode 100755
new mode 100644
diff --git a/src/svpc_types.h b/src/svpc_types.h
old mode 100755
new mode 100644
13 years, 5 months
[PATCH] Update .hgignore
by Eduardo Lima (Etrunko)
# HG changeset patch
# User Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
# Date 1306267369 10800
# Node ID a93bab93b304329e9f63d50a8d46cab427271c8d
# Parent 86998e0d6368e290e34ba61985b9d19cbeb7fef3
Update .hgignore
Signed-off-by: Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
diff -r 86998e0d6368 -r a93bab93b304 .hgignore
--- a/.hgignore Tue May 24 15:29:32 2011 -0300
+++ b/.hgignore Tue May 24 17:02:49 2011 -0300
@@ -7,6 +7,13 @@
*~
*.o
tests/*.err
+doc/*.html
+.changeset
+.revision
+*.spec
+xml_parse_test
+cim_schema_*.zip
+install_base_schema.sh
syntax: regexp
.*\#.*\#$
@@ -33,4 +40,4 @@
.*\.loT$
^acinclude.m4.orig$
^config.h.in$
-libcmpiutil/doc/html/.*%
\ No newline at end of file
+libcmpiutil/doc/html/.*%
13 years, 5 months
[PATCH] Add DCN ACL classes & providers to support libvirt NWFilters
by Chip Vincent
# HG changeset patch
# User Chip Vincent <cvincent(a)us.ibm.com>
# Date 1305221061 14400
# Node ID 51c1f55fa776f68ce794ea626b06b08691ff7a47
# Parent f51a1ccadbcce1c7f9ba6268267866f7721420c1
Add DCN ACL classes & providers to support libvirt NWFilters.
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. Since there's lots of rule types,
there's lots of new functions in xmlgen. A future patch should refactor
xmlgen to be more manageable like device/pool/acl_parsing.
+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).
NOTE: Read-write. Requires Name property to be in the form
<filter_name>:<index>, where <filter_name> is the name of an existing filter,
and <index> is an arbitrary number. Example: "clean-traffic:0". This allows
the provider to create the rule properly in the context of a pre-defined
filter. The <index> element will be changed as needed by the provider to
avoid conflict, and will be communicated to the client via the object path
returned during a CreateInstance operation.
+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).
NOTE: Read-only. Clients may not explicitly create associations between
filters and rules. Rather, the relationship is implicitly formed when the
rule is created (see above).
+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.
NOTE: New associations are created via CIM intrinsic methods (create/modify/
delete). It requires the client to provide fully qualified object paths to
the 'parent' filter and 'child' filter so the providers can a) validate their
existance, and b) apply the necessary links in the XML so new associations
will appear when queried.
+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).
NOTE: Read-only. Clients may not change the host associated to filters.
+schema/AppliedFilterList.mof & .registration
+src/AppliedFilterList.c
Adds a class to represent the relationship (association) between a filter
and a network port referencing it. This is not covered by the current schema
so a new class was introduced.
NOTE: New associations are created via CIM intrinsic methods (create/modify/
delete). It requires the client to provide fully qualified object paths to
the filter and network port so the providers can a) validate their existance,
and b) apply the necessary links in the XML so new associations appear when
queried.
Signed-off-by: Chip Vincent <cvincent(a)us.ibm.com>
diff --git a/Makefile.am b/Makefile.am
--- a/Makefile.am
+++ b/Makefile.am
@@ -57,7 +57,13 @@
schema/InputPool.mof \
schema/HostedAccessPoint.mof \
schema/ServiceAccessBySAP.mof \
- schema/SAPAvailableForElement.mof
+ schema/SAPAvailableForElement.mof \
+ schema/FilterEntry.mof \
+ schema/FilterList.mof \
+ schema/EntriesInFilterList.mof \
+ schema/NestedFilterList.mof \
+ schema/AppliedFilterList.mof \
+ schema/HostedFilterList.mof
INTEROP_MOFS = \
schema/ComputerSystem.mof \
@@ -138,7 +144,13 @@
schema/InputPool.registration \
schema/HostedAccessPoint.registration \
schema/ServiceAccessBySAP.registration \
- schema/SAPAvailableForElement.registration
+ schema/SAPAvailableForElement.registration \
+ schema/FilterEntry.registration \
+ schema/FilterList.registration \
+ schema/EntriesInFilterList.registration \
+ schema/NestedFilterList.registration \
+ schema/AppliedFilterList.registration \
+ schema/HostedFilterList.registration
INTEROP_REGS = \
schema/RegisteredProfile.registration \
diff --git a/libxkutil/Makefile.am b/libxkutil/Makefile.am
--- a/libxkutil/Makefile.am
+++ b/libxkutil/Makefile.am
@@ -4,12 +4,12 @@
CFLAGS += $(CFLAGS_STRICT)
noinst_HEADERS = cs_util.h misc_util.h device_parsing.h xmlgen.h infostore.h \
- pool_parsing.h
+ pool_parsing.h acl_parsing.h
lib_LTLIBRARIES = libxkutil.la
libxkutil_la_SOURCES = cs_util_instance.c misc_util.c device_parsing.c \
- xmlgen.c infostore.c pool_parsing.c
+ xmlgen.c infostore.c pool_parsing.c acl_parsing.c
libxkutil_la_LIBADD = @LIBVIRT_LIBS@ \
@LIBUUID_LIBS@
diff --git a/libxkutil/acl_parsing.c b/libxkutil/acl_parsing.c
new file mode 100644
--- /dev/null
+++ b/libxkutil/acl_parsing.c
@@ -0,0 +1,741 @@
+/*
+ * Copyright IBM Corp. 2010
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+
+#include "acl_parsing.h"
+#include "device_parsing.h"
+#include "xmlgen.h"
+#include "../src/svpc_types.h"
+
+void cleanup_rule(struct acl_rule *rule)
+{
+ if(rule == NULL)
+ return;
+
+ free(rule->name);
+ free(rule->protocol_id);
+ free(rule->action);
+ free(rule->direction);
+ free(rule->priority);
+
+ switch(rule->type) {
+ case MAC_RULE:
+ free(rule->var.mac.srcmacaddr);
+ free(rule->var.mac.srcmacmask);
+ free(rule->var.mac.dstmacaddr);
+ free(rule->var.mac.dstmacmask);
+ free(rule->var.mac.protocol_id);
+ free(rule->var.mac.comment);
+ break;
+ case ARP_RULE:
+ free(rule->var.arp.srcmacaddr);
+ free(rule->var.arp.srcmacmask);
+ free(rule->var.arp.dstmacaddr);
+ free(rule->var.arp.dstmacmask);
+ free(rule->var.arp.hw_type);
+ free(rule->var.arp.protocol_type);
+ free(rule->var.arp.opcode);
+ free(rule->var.arp.arpsrcmacaddr);
+ free(rule->var.arp.arpdstmacaddr);
+ free(rule->var.arp.arpsrcipaddr);
+ free(rule->var.arp.arpdstipaddr);
+ free(rule->var.arp.comment);
+ break;
+ case IP_RULE:
+ free(rule->var.ip.srcmacaddr);
+ free(rule->var.ip.srcmacmask);
+ free(rule->var.ip.dstmacaddr);
+ free(rule->var.ip.dstmacmask);
+ free(rule->var.ip.srcipaddr);
+ free(rule->var.ip.srcipmask);
+ free(rule->var.ip.dstipaddr);
+ free(rule->var.ip.dstipmask);
+ free(rule->var.ip.srcportstart);
+ free(rule->var.ip.srcportend);
+ free(rule->var.ip.dstportstart);
+ free(rule->var.ip.dstportend);
+ free(rule->var.ip.comment);
+ break;
+ case TCP_RULE:
+ free(rule->var.tcp.srcmacaddr);
+ free(rule->var.tcp.srcipaddr);
+ free(rule->var.tcp.srcipmask);
+ free(rule->var.tcp.dstipaddr);
+ free(rule->var.tcp.srcipfrom);
+ free(rule->var.tcp.srcipto);
+ free(rule->var.tcp.dstipfrom);
+ free(rule->var.tcp.dstipto);
+ free(rule->var.tcp.srcportstart);
+ free(rule->var.tcp.srcportend);
+ free(rule->var.tcp.dstportstart);
+ free(rule->var.tcp.dstportend);
+ free(rule->var.tcp.comment);
+ free(rule->var.tcp.state);
+ break;
+ case IGMP_RULE:
+ free(rule->var.igmp.srcmacaddr);
+ free(rule->var.igmp.srcmacmask);
+ free(rule->var.igmp.dstmacaddr);
+ free(rule->var.igmp.dstmacmask);
+ free(rule->var.igmp.srcipaddr);
+ free(rule->var.igmp.srcipmask);
+ free(rule->var.igmp.dstipaddr);
+ free(rule->var.igmp.dstipmask);
+ free(rule->var.igmp.srcipfrom);
+ free(rule->var.igmp.srcipto);
+ free(rule->var.igmp.dstipfrom);
+ free(rule->var.igmp.dstipto);
+ free(rule->var.igmp.type);
+ free(rule->var.igmp.code);
+ free(rule->var.igmp.comment);
+ free(rule->var.igmp.state);
+ break;
+ case ICMP_RULE:
+ free(rule->var.icmp.srcmacaddr);
+ free(rule->var.icmp.srcmacmask);
+ free(rule->var.icmp.dstmacaddr);
+ free(rule->var.icmp.dstmacmask);
+ free(rule->var.icmp.srcipaddr);
+ free(rule->var.icmp.srcipmask);
+ free(rule->var.icmp.dstipaddr);
+ free(rule->var.icmp.dstipmask);
+ free(rule->var.icmp.srcipfrom);
+ free(rule->var.icmp.srcipto);
+ free(rule->var.icmp.dstipfrom);
+ free(rule->var.icmp.dstipto);
+ free(rule->var.icmp.type);
+ free(rule->var.icmp.code);
+ free(rule->var.icmp.comment);
+ free(rule->var.icmp.state);
+ break;
+ case UNKNOWN_RULE:
+ default:
+ break;
+ };
+
+ rule->type = UNKNOWN_RULE;
+}
+
+void cleanup_filter(struct acl_filter *filter)
+{
+ int i;
+
+ if(filter == NULL)
+ return;
+
+ free(filter->uuid);
+ free(filter->name);
+ free(filter->chain);
+
+ for (i = 0; i < filter->rule_ct; i++) {
+ cleanup_rule(filter->rules[i]);
+ free(filter->rules[i]);
+ }
+
+ free(filter->rules);
+ filter->rule_ct = 0;
+
+ for (i = 0; i < filter->ref_ct; i++)
+ free(filter->refs[i]);
+
+ free(filter->refs);
+ filter->ref_ct = 0;
+}
+
+void cleanup_filters(struct acl_filter **filters, int count)
+{
+ int i;
+ struct acl_filter *_filters = *filters;
+
+ if((filters == NULL) || (*filters == NULL) || (count == 0))
+ return;
+
+ for (i = 0; i < count; i++)
+ cleanup_filter(&_filters[i]);
+
+ free(_filters);
+ *filters = NULL;
+}
+
+
+static int parse_acl_mac_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL mac rule %s", rnode->name);
+
+ rule->type = MAC_RULE;
+ rule->var.mac.protocol_id = get_attr_value(rnode, "protocolid");
+ rule->var.mac.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.mac.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.mac.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.mac.dstmacmask = get_attr_value(rnode, "dstmacmask");
+ rule->var.mac.comment = get_attr_value(rnode, "comment");
+
+ return 1;
+}
+
+static int parse_acl_arp_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL arp rule %s", rnode->name);
+
+ rule->type = ARP_RULE;
+ rule->var.arp.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.arp.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.arp.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.arp.dstmacmask = get_attr_value(rnode, "dstmacmask");
+ rule->var.arp.hw_type = get_attr_value(rnode, "hwtype");
+ rule->var.arp.protocol_type = get_attr_value(rnode, "protocoltype");
+ rule->var.arp.opcode = get_attr_value(rnode, "opcode");
+ rule->var.arp.arpsrcmacaddr = get_attr_value(rnode, "arpsrcmacaddr");
+ rule->var.arp.arpdstmacaddr = get_attr_value(rnode, "arpdstmacaddr");
+ rule->var.arp.arpsrcipaddr = get_attr_value(rnode, "arpsrcipaddr");
+ rule->var.arp.arpdstipaddr = get_attr_value(rnode, "arpdstipaddr");
+ rule->var.arp.comment = get_attr_value(rnode, "comment");
+
+ return 1;
+}
+
+static int parse_acl_ip_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACP ip rule %s", rnode->name);
+
+ rule->type = IP_RULE;
+ rule->var.ip.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.ip.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.ip.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.ip.dstmacmask = get_attr_value(rnode, "dstmacmaks");
+ rule->var.ip.srcipaddr = get_attr_value(rnode, "srcipaddr");
+ rule->var.ip.srcipmask = get_attr_value(rnode, "srcipmask");
+ rule->var.ip.dstipaddr = get_attr_value(rnode, "dstipaddr");
+ rule->var.ip.dstipmask = get_attr_value(rnode, "dstipmask");
+ rule->var.ip.protocol = get_attr_value(rnode, "protocol");
+ rule->var.ip.srcportstart = get_attr_value(rnode, "srcportstart");
+ rule->var.ip.srcportend = get_attr_value(rnode, "srcportend");
+ rule->var.ip.dstportstart = get_attr_value(rnode, "dstportstart");
+ rule->var.ip.dstportend = get_attr_value(rnode, "dstportend");
+ rule->var.ip.comment = get_attr_value(rnode, "comment");
+
+ return 1;
+}
+
+static int parse_acl_tcp_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL tcp rule %s", rnode->name);
+
+ rule->type = TCP_RULE;
+ rule->var.tcp.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.tcp.srcipaddr = get_attr_value(rnode, "srcipaddr");
+ rule->var.tcp.srcipmask = get_attr_value(rnode, "srcipmask");
+ rule->var.tcp.dstipaddr = get_attr_value(rnode, "dstipaddr");
+ rule->var.tcp.dstipmask = get_attr_value(rnode, "dstipmask");
+ rule->var.tcp.srcipfrom = get_attr_value(rnode, "srcipfrom");
+ rule->var.tcp.srcipto = get_attr_value(rnode, "srcipto");
+ rule->var.tcp.dstipfrom = get_attr_value(rnode, "dstipfrom");
+ rule->var.tcp.dstipto = get_attr_value(rnode, "dstipto");
+ rule->var.tcp.srcportstart = get_attr_value(rnode, "srcportstart");
+ rule->var.tcp.srcportend = get_attr_value(rnode, "srcportend");
+ rule->var.tcp.dstportstart = get_attr_value(rnode, "dstportstart");
+ rule->var.tcp.dstportend = get_attr_value(rnode, "dstportend");
+ rule->var.tcp.comment = get_attr_value(rnode, "comment");
+ rule->var.tcp.state = get_attr_value(rnode, "state");
+
+ return 1;
+}
+
+static int parse_acl_icmp_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL icmp rule %s", rnode->name);
+
+ rule->type = ICMP_RULE;
+ rule->var.icmp.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.icmp.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.icmp.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.icmp.dstmacmask = get_attr_value(rnode, "dstmacmask");
+ rule->var.icmp.srcipaddr = get_attr_value(rnode, "srcipaddr");
+ rule->var.icmp.srcipmask = get_attr_value(rnode, "srcipmask");
+ rule->var.icmp.dstipaddr = get_attr_value(rnode, "dstipaddr");
+ rule->var.icmp.dstipmask = get_attr_value(rnode, "dstipmask");
+ rule->var.icmp.srcipfrom = get_attr_value(rnode, "srcipfrom");
+ rule->var.icmp.srcipto = get_attr_value(rnode, "srcipto");
+ rule->var.icmp.dstipfrom = get_attr_value(rnode, "dstipfrom");
+ rule->var.icmp.dstipto = get_attr_value(rnode, "dstipto");
+ rule->var.icmp.comment = get_attr_value(rnode, "comment");
+ rule->var.icmp.state = get_attr_value(rnode, "state");
+
+ return 1;
+}
+
+static int parse_acl_igmp_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ CU_DEBUG("ACL igmp rule %s", rnode->name);
+
+ rule->type = IGMP_RULE;
+ rule->var.igmp.srcmacaddr = get_attr_value(rnode, "srcmacaddr");
+ rule->var.igmp.srcmacmask = get_attr_value(rnode, "srcmacmask");
+ rule->var.igmp.dstmacaddr = get_attr_value(rnode, "dstmacaddr");
+ rule->var.igmp.dstmacmask = get_attr_value(rnode, "dstmacmask");
+ rule->var.igmp.srcipaddr = get_attr_value(rnode, "srcipaddr");
+ rule->var.igmp.srcipmask = get_attr_value(rnode, "srcipmask");
+ rule->var.igmp.dstipaddr = get_attr_value(rnode, "dstipaddr");
+ rule->var.igmp.dstipmask = get_attr_value(rnode, "dstipmask");
+ rule->var.igmp.srcipfrom = get_attr_value(rnode, "srcipfrom");
+ rule->var.igmp.srcipto = get_attr_value(rnode, "srcipto");
+ rule->var.igmp.dstipfrom = get_attr_value(rnode, "dstipfrom");
+ rule->var.igmp.dstipto = get_attr_value(rnode, "dstipto");
+ rule->var.igmp.type = get_attr_value(rnode, "type");
+ rule->var.igmp.code = get_attr_value(rnode, "code");
+ rule->var.igmp.comment = get_attr_value(rnode, "comment");
+ rule->var.igmp.state = get_attr_value(rnode, "state");
+
+ return 1;
+}
+
+static int parse_acl_rule(xmlNode *rnode, struct acl_rule *rule)
+{
+ xmlNode *child = NULL;
+
+ memset(rule, 0, sizeof(*rule));
+
+ rule->action = get_attr_value(rnode, "action");
+ if (rule->action == NULL)
+ goto err;
+
+ rule->direction = get_attr_value(rnode, "direction");
+ if (rule->direction == NULL)
+ goto err;
+
+ rule->priority = get_attr_value(rnode, "priority");
+ rule->statematch = get_attr_value(rnode, "statematch");
+
+ for (child = rnode->children; child != NULL; child = child->next) {
+ if (XSTREQ(child->name, "mac")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_mac_rule(child, rule);
+ } else if (XSTREQ(child->name, "arp") ||
+ XSTREQ(child->name, "rarp")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_arp_rule(child, rule);
+ } else if (XSTREQ(child->name, "ip") ||
+ XSTREQ(child->name, "ipv6")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_ip_rule(child, rule);
+ } else if (XSTREQ(child->name, "tcp") ||
+ XSTREQ(child->name, "tcp-ipv6") ||
+ XSTREQ(child->name, "udp") ||
+ XSTREQ(child->name, "udp-ipv6") ||
+ XSTREQ(child->name, "sctp") ||
+ XSTREQ(child->name, "sctp-ipv6")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_tcp_rule(child, rule);
+ } else if (XSTREQ(child->name, "icmp") ||
+ XSTREQ(child->name, "icmpv6")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_icmp_rule(child, rule);
+ } else if (XSTREQ(child->name, "igmp") ||
+ XSTREQ(child->name, "igmp-ipv6") ||
+ XSTREQ(child->name, "esp") ||
+ XSTREQ(child->name, "esp-ipv6") ||
+ XSTREQ(child->name, "ah") ||
+ XSTREQ(child->name, "ah-ipv6") ||
+ XSTREQ(child->name, "udplite") ||
+ XSTREQ(child->name, "udplite-ipv6") ||
+ XSTREQ(child->name, "all") ||
+ XSTREQ(child->name, "all-ipv6")) {
+ rule->protocol_id = strdup((char *)child->name);
+ parse_acl_igmp_rule(child, rule);
+ }
+ }
+
+ return 1;
+
+ err:
+ cleanup_rule(rule);
+
+ return 0;
+}
+
+static int parse_acl_filter(xmlNode *fnode, struct acl_filter *filter)
+{
+ struct acl_rule *rule = NULL;
+ char *filter_ref = NULL;
+ xmlNode *child = NULL;
+
+ filter->name = get_attr_value(fnode, "name");
+ if (filter->name == NULL)
+ goto err;
+
+ filter->chain = get_attr_value(fnode, "chain");
+
+ for (child = fnode->children; child != NULL; child = child->next) {
+ if (XSTREQ(child->name, "uuid")) {
+ STRPROP(filter, uuid, child);
+ } else if (XSTREQ(child->name, "rule")) {
+ rule = malloc(sizeof(*rule));
+ if (rule == NULL)
+ goto err;
+
+ if (parse_acl_rule(child, rule) == 0)
+ goto err;
+
+ append_filter_rule(filter, rule);
+ }
+ else if (XSTREQ(child->name, "filterref")) {
+ filter_ref = get_attr_value(child, "filter");
+ if (filter_ref == NULL)
+ goto err;
+
+ append_filter_ref(filter, filter_ref);
+ }
+ }
+
+ return 1;
+
+ err:
+ cleanup_filter(filter);
+
+ return 0;
+}
+
+/* Dummy function to suppress error message from libxml2 */
+static void swallow_err_msg(void *ctx, const char *msg, ...)
+{
+ /* do nothing, just swallow the message. */
+}
+
+int get_filter_from_xml(const char *xml, struct acl_filter **filter)
+{
+ xmlDoc *xmldoc = NULL;
+
+ if (xml == NULL || filter == NULL)
+ return 0;
+
+ xmlSetGenericErrorFunc(NULL, swallow_err_msg);
+
+ xmldoc = xmlParseMemory(xml, strlen(xml) + 1);
+ if (xmldoc == NULL)
+ goto err;
+
+ *filter = malloc(sizeof(**filter));
+
+ memset(*filter, 0, sizeof(**filter));
+ parse_acl_filter(xmldoc->children, *filter);
+
+ err:
+ xmlSetGenericErrorFunc(NULL, NULL);
+ xmlFreeDoc(xmldoc);
+
+ return 1;
+}
+
+int get_filter_by_name(
+ virConnectPtr conn,
+ const char *name,
+ struct acl_filter **filter)
+{
+ virNWFilterPtr vfilter = NULL;
+ char *xml = NULL;
+
+ if (name == NULL || filter == NULL)
+ return 0;
+
+ vfilter = virNWFilterLookupByName(conn, name);
+
+ xml = virNWFilterGetXMLDesc(vfilter, 0);
+
+ virNWFilterFree(vfilter);
+
+ if (xml == NULL)
+ return 0;
+
+ get_filter_from_xml(xml, filter);
+
+ return 1;
+}
+
+int get_filter_by_uuid(
+ virConnectPtr conn,
+ const char *uuid,
+ struct acl_filter **filter)
+{
+ virNWFilterPtr vfilter = NULL;
+ char *xml = NULL;
+
+ if (uuid == NULL || filter == NULL)
+ return 0;
+
+ vfilter = virNWFilterLookupByUUIDString(conn, uuid);
+
+ xml = virNWFilterGetXMLDesc(vfilter, 0);
+
+ virNWFilterFree(vfilter);
+
+ if (xml == NULL)
+ return 0;
+
+ get_filter_from_xml(xml, filter);
+
+ return 1;
+}
+
+int get_filters(
+ virConnectPtr conn,
+ struct acl_filter **list)
+{
+ int count = 0;
+ char **names = NULL;
+ struct acl_filter *filters = NULL;
+ int i = 0;
+
+ count = virConnectNumOfNWFilters(conn);
+
+ names = calloc(count, sizeof(char *));
+ if (names == NULL)
+ goto err;
+
+ virConnectListNWFilters(conn, names, count);
+
+ filters = malloc(count * sizeof(struct acl_filter));
+ if (filters == NULL)
+ goto err;
+
+ for(i = 0; i < count; i++)
+ {
+ struct acl_filter *filter = NULL;
+
+ get_filter_by_name(conn, names[i], &filter);
+
+ memcpy(&filters[i], filter, sizeof(*filter));
+ }
+
+ *list = filters;
+
+ err:
+ free(names);
+
+ return i;
+}
+
+
+int append_filter_rule(struct acl_filter *filter, struct acl_rule *rule)
+{
+ struct acl_rule **old_rules = NULL;
+
+ if ((filter == NULL) || (rule == NULL))
+ return 0;
+
+ rule->name = make_rule_id(filter->name, filter->rule_ct);
+ if (rule->name == NULL)
+ return 0;
+
+ old_rules = filter->rules;
+
+ filter->rules =
+ malloc((filter->rule_ct + 1) * sizeof(struct acl_rule *));
+
+ memcpy(filter->rules,
+ old_rules,
+ filter->rule_ct * sizeof(struct acl_rule *));
+
+ filter->rules[filter->rule_ct] = rule;
+ filter->rule_ct++;
+
+ free(old_rules);
+
+ return 1;
+}
+
+int remove_filter_rule(struct acl_filter *filter, struct acl_rule *rule)
+{
+ char *filter_name = NULL;
+ int i, index = 0;
+ struct acl_rule **old_rules = NULL;
+
+ if ((filter == NULL) || (rule == NULL))
+ return 0;
+
+ if (parse_rule_id(rule->name, &filter_name, &index) == 0)
+ return 0;
+
+ if (index > filter->rule_ct)
+ return 0;
+
+ /* TODO: called infrequently, but needs optimization */
+ old_rules = filter->rules;
+ filter->rules = NULL;
+
+ for (i = 0; i < filter->rule_ct; i++)
+ if (index == i) {
+ cleanup_rule(old_rules[i]);
+ }
+ else
+ append_filter_rule(filter, old_rules[i]);
+
+ 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;
+}
+
+int remove_filter_ref(struct acl_filter *filter, const char *name)
+{
+ int i;
+ char **old_refs = NULL;
+
+ if ((filter == NULL) || (name == NULL))
+ return 0;
+
+ /* TODO: called infrequently, but needs optimization */
+ old_refs = filter->refs;
+
+ for (i = 0; i < filter->ref_ct; i++)
+ if (STREQC(old_refs[i], name)) {
+ free(old_refs[i]);
+ }
+ else
+ append_filter_ref(filter, old_refs[i]);
+
+ return 1;
+}
+
+int create_filter(virConnectPtr conn, struct acl_filter *filter)
+{
+ virNWFilterPtr vfilter = NULL;
+ char *xml = NULL;
+
+ if (filter == NULL)
+ return 0;
+
+ xml = filter_to_xml(filter);
+ if (xml == NULL)
+ return 0;
+
+ vfilter = virNWFilterDefineXML(conn, xml);
+
+ free(xml);
+
+ if (vfilter == NULL)
+ return 0;
+
+ virNWFilterFree(vfilter);
+
+ return 1;
+}
+
+int update_filter(virConnectPtr conn, struct acl_filter *filter)
+{
+ if (delete_filter(conn, filter) == 0 ||
+ create_filter(conn, filter) == 0)
+ return 0;
+
+ return 1;
+}
+
+int delete_filter(virConnectPtr conn, struct acl_filter *filter)
+{
+ virNWFilterPtr vfilter = NULL;
+
+ if (filter == NULL)
+ return 0;
+
+ vfilter = virNWFilterLookupByUUIDString(conn, filter->uuid);
+ if (vfilter == NULL)
+ return 0;
+
+ if (virNWFilterUndefine(vfilter) != 0) {
+ virNWFilterFree(vfilter);
+ return 0;
+ }
+
+ 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,218 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __ACL_PARSING_H
+#define __ACL_PARSING_H
+
+#include <libvirt/libvirt.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+
+struct acl_mac_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *protocol_id;
+ char *comment;
+};
+
+struct acl_arp_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *hw_type;
+ char *protocol_type;
+ char *opcode;
+ char *arpsrcmacaddr;
+ char *arpdstmacaddr;
+ char *arpsrcipaddr;
+ char *arpdstipaddr;
+ char *comment;
+};
+
+struct acl_ip_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *srcipaddr;
+ char *srcipmask;
+ char *dstipaddr;
+ char *dstipmask;
+
+ char *protocol;
+
+ char *srcportstart;
+ char *srcportend;
+ char *dstportstart;
+ char *dstportend;
+
+ char *comment;
+};
+
+struct acl_tcp_rule {
+ char *srcmacaddr;
+
+ char *srcipaddr;
+ char *srcipmask;
+ char *dstipaddr;
+ char *dstipmask;
+
+ char *srcipfrom;
+ char *srcipto;
+ char *dstipfrom;
+ char *dstipto;
+
+ char *srcportstart;
+ char *srcportend;
+ char *dstportstart;
+ char *dstportend;
+
+ char *comment;
+ char *state;
+};
+
+struct acl_igmp_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *srcipaddr;
+ char *srcipmask;
+ char *dstipaddr;
+ char *dstipmask;
+
+ char *srcipfrom;
+ char *srcipto;
+ char *dstipfrom;
+ char *dstipto;
+
+ char *type;
+ char *code;
+ char *comment;
+ char *state;
+};
+
+struct acl_icmp_rule {
+ char *srcmacaddr;
+ char *srcmacmask;
+ char *dstmacaddr;
+ char *dstmacmask;
+
+ char *srcipaddr;
+ char *srcipmask;
+ char *dstipaddr;
+ char *dstipmask;
+
+ char *srcipfrom;
+ char *srcipto;
+ char *dstipfrom;
+ char *dstipto;
+
+ char *type;
+ char *code;
+ char *comment;
+ char *state;
+};
+
+struct acl_rule {
+ char *name;
+ char *protocol_id;
+ char *action;
+ char *direction;
+ char *priority;
+ char *statematch;
+
+ enum {
+ UNKNOWN_RULE,
+ MAC_RULE,
+ ARP_RULE,
+ IP_RULE,
+ TCP_RULE,
+ ICMP_RULE,
+ IGMP_RULE
+ } type;
+
+ union {
+ struct acl_mac_rule mac;
+ struct acl_arp_rule arp;
+ struct acl_ip_rule ip;
+ struct acl_tcp_rule tcp;
+ struct acl_icmp_rule icmp;
+ struct acl_igmp_rule igmp;
+ } var;
+};
+
+struct acl_filter {
+ char *uuid;
+ char *name;
+ char *chain;
+
+ struct acl_rule **rules;
+ int rule_ct;
+
+ char **refs;
+ int ref_ct;
+};
+
+void cleanup_rule(struct acl_rule *rule);
+void cleanup_filter(struct acl_filter *filter);
+void cleanup_filters(struct acl_filter **filters, int count);
+
+int get_filters(virConnectPtr conn, struct acl_filter **list);
+
+int get_filter_from_xml(const char *xml, struct acl_filter **filter);
+int get_filter_by_uuid(virConnectPtr conn, const char *uuid,
+ struct acl_filter **filter);
+int get_filter_by_name(virConnectPtr conn, const char *name,
+ struct acl_filter **filter);
+
+char *make_rule_id(const char *filter, int index);
+int parse_rule_id(const char *rule_id, char **filter, int *index);
+
+int append_filter_rule(struct acl_filter *filter, struct acl_rule *rule);
+int remove_filter_rule(struct acl_filter *filter, struct acl_rule *rule);
+
+/* NOTE: caller allocates name and cleanup_filter() releases it */
+int append_filter_ref(struct acl_filter *filter, char *name);
+int remove_filter_ref(struct acl_filter *filter, const char *name);
+
+int create_filter(virConnectPtr conn, struct acl_filter *filter);
+int update_filter(virConnectPtr conn, struct acl_filter *filter);
+int delete_filter(virConnectPtr conn, struct acl_filter *filter);
+
+#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"))
@@ -1351,6 +1360,642 @@
return xml;
}
+static char *mac_rule_to_xml(xmlNodePtr root, struct acl_rule *rule)
+{
+ char *msg = XML_ERROR;
+ char *prop = NULL;
+
+ prop = rule->var.mac.protocol_id;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "protocolid",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.mac.srcmacaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcmacaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.mac.srcmacmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcmacmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.mac.dstmacaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstmacaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.mac.dstmacmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstmacaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.mac.comment;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "comment",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ msg = NULL; /* no error */
+ out:
+ return msg;
+}
+
+static char *arp_rule_to_xml(xmlNodePtr root, struct acl_rule *rule)
+{
+ char *msg = XML_ERROR;
+ char *prop = NULL;
+
+ prop = rule->var.arp.srcmacaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcmacaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.arp.srcmacmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcmacmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.arp.dstmacaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstmacaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.arp.dstmacmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstmacmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.arp.hw_type;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "hwtype",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.arp.protocol_type;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "protocol_type",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.arp.opcode;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "opcode",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.arp.arpsrcmacaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "arpsrcmacaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.arp.arpdstmacaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "arpdstmacaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.arp.arpsrcipaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "arpsrcipaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.arp.arpdstipaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "arpdstipaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.arp.comment;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "comment",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ msg = NULL; /* no error */
+ out:
+
+ return msg;
+}
+
+static char *ip_rule_to_xml(xmlNodePtr root, struct acl_rule *rule)
+{
+ char *msg = XML_ERROR;
+ char *prop = NULL;
+
+ rule->var.ip.srcmacaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcmacaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.ip.srcmacmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcmacmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.ip.dstmacaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstmacaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.ip.dstmacmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstmacmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.ip.srcipaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.ip.srcipmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.ip.dstipaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.ip.dstipmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.ip.protocol;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "protocol",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.ip.srcportstart;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcportstart",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.ip.srcportend;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcportend",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.ip.dstportstart;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstportstart",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.ip.dstportend;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstportend",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ rule->var.ip.comment;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "comment",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ msg = NULL; /* no error */
+ out:
+
+ return msg;
+}
+
+static char *tcp_rule_to_xml(xmlNodePtr root, struct acl_rule *rule)
+{
+ char *msg = XML_ERROR;
+ char *prop = NULL;
+
+ prop = rule->var.tcp.srcmacaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcmacaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop =rule->var.tcp.srcipaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.tcp.srcipmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.tcp.dstipaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop =rule->var.tcp.dstipmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.tcp.srcipfrom;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipfrom",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.tcp.srcipto;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipto",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop =rule->var.tcp.dstipfrom;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipfrom",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.tcp.dstipto;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipto",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.tcp.srcportstart;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcportstart",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.tcp.srcportend;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcportend",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.tcp.dstportstart;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstportstart",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.tcp.dstportend;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstportend",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.tcp.comment;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "comment",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.tcp.state;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "state",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ msg = NULL; /* no error */
+ out:
+
+ return msg;
+}
+
+static char *icmp_rule_to_xml(xmlNodePtr root, struct acl_rule *rule)
+{
+ char *msg = XML_ERROR;
+ char *prop = NULL;
+
+ prop = rule->var.icmp.srcmacaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "comment",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.icmp.srcmacmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcmacmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.icmp.dstmacaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstmacaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.icmp.dstmacmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstmacmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.icmp.srcipaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.icmp.srcipmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.icmp.dstipaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop =rule->var.icmp.dstipmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop =rule->var.icmp.srcipfrom;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipfrom",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.icmp.srcipto;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipto",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.icmp.dstipfrom;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipfrom",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.icmp.dstipto;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipto",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.icmp.comment;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "comment",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.icmp.state;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "state",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ msg = NULL; /* no error*/
+ out:
+
+ return msg;
+}
+
+static char *igmp_rule_to_xml(xmlNodePtr root, struct acl_rule *rule)
+{
+ char *msg = XML_ERROR;
+ char *prop = NULL;
+
+ prop = rule->var.igmp.srcmacaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcmacaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.srcmacmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcmacmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.dstmacaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstmacaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.dstmacmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstmacmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.srcipaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.srcipmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.dstipaddr;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipaddr",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.dstipmask;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipmask",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.srcipfrom;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipfrom",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.srcipto;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "srcipto",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.dstipfrom;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipfrom",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.dstipto;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "dstipto",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.type;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "type",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.code;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "code",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.comment;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "comment",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ prop = rule->var.igmp.state;
+ if (prop != NULL)
+ if (xmlNewProp(root, BAD_CAST "state",
+ BAD_CAST prop) == NULL)
+ goto out;
+
+ msg = NULL; /* no error*/
+ out:
+
+ return msg;
+}
+
+static char *rule_to_xml(xmlNodePtr root, struct acl_rule *rule)
+{
+ xmlNodePtr r = NULL;
+ char *msg = XML_ERROR;
+
+ r = xmlNewChild(root, NULL, BAD_CAST "rule", NULL);
+ if (r == NULL)
+ goto out;
+
+ if (rule->action != NULL)
+ if (xmlNewProp(r, BAD_CAST "action",
+ BAD_CAST rule->action) == NULL)
+ goto out;
+
+ if (rule->direction != NULL)
+ if (xmlNewProp(r, BAD_CAST "direction",
+ BAD_CAST rule->direction) == NULL)
+ goto out;
+
+ if (rule->priority != NULL)
+ if (xmlNewProp(r, BAD_CAST "priority",
+ BAD_CAST rule->priority) == NULL)
+ goto out;
+
+ if (rule->statematch != NULL)
+ if (xmlNewProp(r, BAD_CAST "statematch",
+ BAD_CAST rule->statematch) == NULL)
+ goto out;
+
+ switch (rule->type) {
+ case MAC_RULE:
+ msg = mac_rule_to_xml(r, rule);
+ break;
+ case ARP_RULE:
+ msg = arp_rule_to_xml(r, rule);
+ break;
+ case IP_RULE:
+ msg = ip_rule_to_xml(r, rule);
+ break;
+ case TCP_RULE:
+ msg = tcp_rule_to_xml(r, rule);
+ break;
+ case ICMP_RULE:
+ msg = icmp_rule_to_xml(r, rule);
+ break;
+ case IGMP_RULE:
+ msg = igmp_rule_to_xml(r, rule);
+ break;
+ case UNKNOWN_RULE:
+ default:
+ CU_DEBUG("Ignoring unknown rule.");
+ break;
+ }
+
+ out:
+ return msg;
+}
+
+char *filter_to_xml(struct acl_filter *filter)
+{
+ char *msg = XML_ERROR;
+ char *xml = NULL;
+ xmlNodePtr root = NULL;
+ xmlNodePtr tmp = NULL;
+ int i;
+
+ root = xmlNewNode(NULL, BAD_CAST "filter");
+ if (root == NULL)
+ goto out;
+
+ if (xmlNewProp(root, BAD_CAST "name", BAD_CAST filter->name) == NULL)
+ goto out;
+
+ if (filter->chain != NULL)
+ if (xmlNewProp(root, BAD_CAST "chain",
+ BAD_CAST filter->chain) == NULL)
+ goto out;
+
+ if (filter->uuid != NULL) {
+ tmp = xmlNewChild(root, NULL, BAD_CAST "uuid", NULL);
+ if (xmlNewProp(tmp, NULL, BAD_CAST filter->uuid) == NULL)
+ goto out;
+ }
+
+ for (i = 0; i < filter->ref_ct; i++) {
+ tmp = xmlNewChild(root, NULL, BAD_CAST "filterref", NULL);
+ if (xmlNewProp(tmp, BAD_CAST "filter",
+ BAD_CAST filter->refs[i]) == NULL)
+ goto out;
+ }
+
+ for (i = 0; i < filter->rule_ct; i++) {
+ msg = rule_to_xml(root, filter->rules[i]);
+ if (msg != NULL)
+ goto out;
+ }
+
+ xml = tree_to_xml(root);
+ if (xml != NULL)
+ msg = NULL; /* no errors */
+
+ out:
+ CU_DEBUG("Filter XML: %s", msg);
+
+ xmlFreeNode(root);
+
+ return xml;
+}
+
/*
* Local Variables:
* mode: C
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. 2010
+[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,627 @@
+/*
+ * Copyright IBM Corp. 2010
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_association.h>
+#include <libcmpiutil/std_instance.h>
+
+#include "device_parsing.h"
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "cs_util.h"
+
+#include "Virt_Device.h"
+#include "Virt_FilterList.h"
+
+static const CMPIBroker *_BROKER;
+
+/* TODO: Port to libcmpiutil/args_util.c */
+/**
+ * Get a reference property of an instance
+ *
+ * @param inst The instance
+ * @param prop The property name
+ * @param reference A pointer to a CMPIObjectPath* that will be set
+ * if successful
+ * @returns
+ * - CMPI_RC_OK on success
+ * - CMPI_RC_ERR_NO_SUCH_PROPERTY if prop is not present
+ * - CMPI_RC_ERR_TYPE_MISMATCH if prop is not a reference
+ * - CMPI_RC_OK otherwise
+ */
+static CMPIrc cu_get_ref_prop(const CMPIInstance *instance,
+ const char *prop,
+ CMPIObjectPath **reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIData value;
+
+ /* REQUIRE_PROPERY_DEFINED(instance, prop, value, &s); */
+ value = CMGetProperty(instance, prop, &s);
+ if ((s.rc != CMPI_RC_OK) || CMIsNullValue(value))
+ return CMPI_RC_ERR_NO_SUCH_PROPERTY;
+
+ if ((value.type != CMPI_ref) || CMIsNullObject(value.value.ref))
+ return CMPI_RC_ERR_TYPE_MISMATCH;
+
+ *reference = value.value.ref;
+
+ return CMPI_RC_OK;
+}
+
+/* TODO: Port to libcmpiutil/args_util.c */
+/**
+ * Get a reference component of an object path
+ *
+ * @param _reference The reference
+ * @param key The key name
+ * @param reference A pointer to a CMPIObjectPath* that will be set
+ * if successful
+ * @returns
+ * - CMPI_RC_OK on success
+ * - CMPI_RC_ERR_NO_SUCH_PROPERTY if prop is not present
+ * - CMPI_RC_ERR_TYPE_MISMATCH if prop is not a reference
+ * - CMPI_RC_OK otherwise
+ */
+static CMPIrc cu_get_ref_path(const CMPIObjectPath *reference,
+ const char *key,
+ CMPIObjectPath **_reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIData value;
+
+ /* REQUIRE_PROPERY_DEFINED(instance, prop, value, &s); */
+ value = CMGetKey(reference, key, &s);
+ if ((s.rc != CMPI_RC_OK) || CMIsNullValue(value))
+ return CMPI_RC_ERR_NO_SUCH_PROPERTY;
+
+ /* how to parse and object path? */
+
+ return CMPI_RC_OK;
+}
+
+/* TODO: Port to libxkutil/device_parsing.c */
+static int update_device(virDomainPtr dom,
+ struct virt_device *dev)
+{
+ char *xml = NULL;
+ int flags = VIR_DOMAIN_DEVICE_MODIFY_CURRENT |
+ VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
+ int ret = 0;
+
+ /** device_to_xml() is not exported, so this function needs
+ * to be moved
+ */
+
+ /* xml = device_to_xml(dev); */
+
+ if (xml == NULL) {
+ CU_DEBUG("Failed to get XML for device '%s'", dev->id);
+ goto out;
+ }
+
+ if (virDomainUpdateDeviceFlags(dom, xml, flags) != 0) {
+ CU_DEBUG("Failed to dynamically update device:");
+ CU_DEBUG("%s", xml);
+ goto out;
+ }
+
+ ret = 1;
+ out:
+ free(xml);
+
+ return ret;
+}
+
+/* TODO: Port to libxkutil/device_parsing.c */
+static int get_device_by_devid(virDomainPtr dom,
+ const char *devid,
+ int type,
+ struct virt_device **dev)
+{
+ int i, ret = 0;
+ struct virt_device *devices = NULL;
+ int count = get_devices(dom, &devices, type);
+
+ for (i = 0; i < count; i++) {
+ if (STREQC(devid, devices[i].id)) {
+ *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;
+ char *domain_name = NULL;
+ const char *device_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);
+
+ for (i = 0; i < count; i++) {
+ struct net_device *ndev = &(devices[i].dev.net);
+
+ 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,214 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_association.h>
+
+#include <strings.h>
+
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "Virt_FilterList.h"
+#include "Virt_FilterEntry.h"
+
+static const CMPIBroker *_BROKER;
+
+/**
+ * given a filter, find all *direct* children
+ */
+static CMPIStatus list_to_rule(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+ struct acl_filter *filter = NULL;
+ const char *name = NULL;
+ virConnectPtr conn = NULL;
+ int i;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ name = CMGetCharsPtr(CMGetKey(reference, "Name", &s).value.string, &s);
+ if (s.rc != CMPI_RC_OK)
+ 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)
+ 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 *_list = NULL;
+ struct acl_filter *filter = NULL;
+ CMPIInstance *instance = NULL;
+ const char *name = NULL;
+ virConnectPtr conn = NULL;
+ int count, i, j;
+
+ CU_DEBUG("Reference = %s", REF2STR(reference));
+
+ name = CMGetCharsPtr(CMGetKey(reference, "Name", &s).value.string, &s);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ count = get_filters(conn, &_list);
+ if (_list == NULL)
+ goto out;
+
+ /* return the filter that contains the rule */
+ for (i = 0; i < count; i++) {
+ for (j = 0; j < _list[i].rule_ct; j++) {
+ if (STREQC(name, _list[i].rules[j]->name)) {
+ 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);
+
+ cleanup_filter(filter);
+
+ filter = NULL;
+ instance = NULL;
+ }
+
+ }
+ }
+
+ out:
+ 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,886 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_instance.h>
+
+#include <arpa/inet.h>
+
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "xmlgen.h"
+
+#include "Virt_FilterEntry.h"
+#include "Virt_HostSystem.h"
+
+const static CMPIBroker *_BROKER;
+
+static bool is_mac_rule(int type)
+{
+ if (type == MAC_RULE || type == ARP_RULE)
+ return 1;
+
+ return 0;
+}
+
+static bool is_ip_rule(int type)
+{
+ if (type == IP_RULE || type == TCP_RULE || type == ICMP_RULE ||
+ type == IGMP_RULE)
+ return 1;
+
+ return 0;
+}
+
+static int octets_from_mac(const char * s, unsigned int *buffer,
+ unsigned int size)
+{
+ unsigned int _buffer[6];
+ unsigned int i, ret;
+
+ if ((s == 0) || (buffer == NULL) || (size < 6))
+ return 0;
+
+ ret = sscanf(s, "%x:%x:%x:%x:%x:%x",
+ &_buffer[0], &_buffer[1], &_buffer[2],
+ &_buffer[3], &_buffer[4], &_buffer[5]);
+
+ for (i = 0; i < ret; i++)
+ buffer[i] = _buffer[i];
+
+ return ret;
+}
+
+static int octets_from_ip(const char * s, unsigned int *buffer,
+ unsigned int size)
+{
+ struct in6_addr addr;
+ unsigned int family = 0;
+ unsigned int n = 0;
+ int i;
+
+ if (s == 0)
+ return 0;
+
+ 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(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 int parse_rule_name(const char *name, char **filter, int *index)
+{
+ int ret;
+
+ ret = sscanf(name, "%a[^:]:%u", filter, index);
+ if (ret != 2) {
+ free(*filter);
+ return 0;
+ }
+
+ return 1;
+}
+
+
+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);
+
+ size = octets_from_mac(rule->var.mac.srcmacaddr,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcMACAddr8021",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ size = octets_from_mac(rule->var.mac.srcmacmask,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcMACMask8021",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ size = octets_from_mac(rule->var.mac.dstmacaddr,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestMACAddr8021", (CMPIValue *)
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ size = octets_from_mac(rule->var.mac.dstmacmask,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(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) {
+ size = octets_from_ip(rule->var.tcp.srcipfrom,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcAddress",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ size = octets_from_ip(rule->var.tcp.srcipto,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcAddressEndOfRange",
+ (CMPIValue *)&array, CMPI_uint8A);
+ } else {
+ size = octets_from_ip(rule->var.tcp.srcmacaddr,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcAddress",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ size = octets_from_ip(rule->var.tcp.srcipmask,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrSrcMask",
+ (CMPIValue *)&array, CMPI_uint8A);
+ }
+
+ if (rule->var.tcp.dstipfrom && rule->var.tcp.dstipto) {
+ size = octets_from_ip(rule->var.tcp.dstipfrom,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestAddress",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ size = octets_from_ip(rule->var.tcp.dstipto,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestAddressEndOfRange",
+ (CMPIValue *)&array, CMPI_uint8A);
+ } else {
+ size = octets_from_ip(rule->var.tcp.dstipaddr,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(bytes, size);
+ if (array != NULL)
+ CMSetProperty(inst, "HdrDestAddress",
+ (CMPIValue *)&array, CMPI_uint8A);
+
+ size = octets_from_ip(rule->var.tcp.dstipmask,
+ bytes, sizeof(bytes));
+
+ array = octets_to_cmpi(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;
+}
+
+static struct acl_rule *convert_instance_to_rule(
+ const CMPIInstance *instance)
+{
+ struct acl_rule *rule = NULL;
+
+ return rule;
+}
+
+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, FILTER} 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;
+ else if (STREQC(CLASSNAME(reference), "KVM_FilterEntry"))
+ class_type = FILTER;
+
+ 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++) {
+ 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 ret, 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;
+ }
+
+ ret = sscanf(name, "%a[^:]:%u", &filter_name, &rule_index);
+ if (ret != 2) {
+ 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;
+}
+
+static CMPIStatus CreateInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIInstance *instance)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ const char *name = NULL;
+ virConnectPtr conn = NULL;
+ struct acl_filter *filter = NULL;
+ struct acl_rule *rule = NULL;
+ char *filter_name = NULL;
+ int index;
+
+ /** Get Name from instance rather than reference since keys
+ * are set by this provider, not the client.
+ */
+ if (cu_get_str_prop(instance, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Name property");
+ goto out;
+ }
+
+ if (parse_rule_name(name, &filter_name, &index) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to parse Name property");
+ goto out;
+ }
+
+ 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 parent filter");
+ CU_DEBUG("%s:%s", s.msg, filter_name);
+ goto out;
+ }
+
+ rule = convert_instance_to_rule(instance);
+ if (rule == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to convert instance");
+ goto out;
+ }
+
+ append_filter_rule(filter, rule);
+ update_filter(conn, filter);
+
+ out:
+ free(filter_name);
+ cleanup_filter(filter);
+ virConnectClose(conn);
+
+ return s;
+}
+
+static CMPIStatus ModifyInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIInstance *instance,
+ const char **properties)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ virConnectPtr conn = NULL;
+ struct acl_filter *filter = NULL;
+ struct acl_rule *rule = NULL;
+ const char *name = NULL;
+ char *filter_name = NULL;
+ int i, index;
+
+ 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_name(name, &filter_name, &index) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to parse Name property");
+ goto out;
+ }
+
+ 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 parent filter");
+ goto out;
+ }
+
+ for (i = 0; i < filter->rule_ct; i++) {
+ if (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;
+ }
+
+ /* TODO: Needs to be done so that previous instance is not
+ * removed if error occurs later
+ */
+ remove_filter_rule(filter, rule);
+ cleanup_rule(rule);
+
+ rule = convert_instance_to_rule(instance);
+ if (rule == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to convert instance");
+ goto out;
+ }
+
+ append_filter_rule(filter, rule);
+ update_filter(conn, filter);
+
+ out:
+ free(filter_name);
+ cleanup_filter(filter);
+ virConnectClose(conn);
+
+ return s;
+}
+
+static CMPIStatus DeleteInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ virConnectPtr conn = NULL;
+ struct acl_filter *filter = NULL;
+ struct acl_rule *rule = NULL;
+ const char *name = NULL;
+ char *filter_name = NULL;
+ int i, index;
+
+ 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_name(name, &filter_name, &index) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to parse Name property");
+ goto out;
+ }
+
+ 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 parent filter");
+ goto out;
+ }
+
+ for (i = 0; i < filter->rule_ct; i++) {
+ if (i == index) {
+ rule = filter->rules[i];
+ break;
+ }
+ }
+
+ if (rule == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Could not retrieve rule");
+ goto out;
+ }
+
+ remove_filter_rule(filter, rule);
+ update_filter(conn, filter);
+
+ out:
+ free(filter_name);
+ cleanup_filter(filter);
+ virConnectClose(conn);
+
+ return s;
+}
+
+DEFAULT_EQ();
+DEFAULT_INST_CLEANUP();
+
+STD_InstanceMIStub(,
+ Virt_FilterEntry,
+ _BROKER,
+ libvirt_cim_init());
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_FilterEntry.h b/src/Virt_FilterEntry.h
new file mode 100644
--- /dev/null
+++ b/src/Virt_FilterEntry.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __VIRT_FILTERENTRY_H
+#define __VIRT_FILTERENTRY_H
+
+/**
+ * Return a list of filter instances
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class name
+ * prefix), but can also be used to scope the results by
+ * specifying the parent filter
+ * @param list A pointer to an array of CMPIInstance objects
+ * (called inits before and frees after)
+ */
+CMPIStatus enum_filter_rules(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct inst_list *list);
+
+/**
+ * Return a single filter instance by reference
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class name
+ * prefix), but can also be used to scope the results by
+ * specifying the parent filter
+ * @param list A pointer to a CMPIInstance *
+ */
+CMPIStatus get_rule_by_ref(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIInstance **instance);
+
+/**
+ * Get an instance representing a filter rule
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class name
+ * prefix), but can also be used to scope the results by
+ * specifying the parent filter
+ * @param rule A pointer to a filter rule
+ * @param instance A pointer to a CMPIInstance *
+ */
+CMPIStatus instance_from_rule(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct acl_rule *rule,
+ CMPIInstance **instance);
+
+#endif
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_FilterList.c b/src/Virt_FilterList.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_FilterList.c
@@ -0,0 +1,446 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_instance.h>
+
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "xmlgen.h"
+
+#include "Virt_FilterList.h"
+#include "Virt_HostSystem.h"
+
+const static CMPIBroker *_BROKER;
+
+static CMPIInstance *convert_filter_to_instance(
+ struct acl_filter *filter,
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ CMPIStatus *s)
+{
+ CMPIInstance *inst = NULL;
+ const char *sys_name = NULL;
+ const char *sys_ccname = NULL;
+ int direction = 0;
+
+ inst = get_typed_instance(broker,
+ CLASSNAME(reference),
+ "FilterList",
+ NAMESPACE(reference));
+ if (inst == NULL) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get filter list instance");
+ goto out;
+ }
+
+ *s = get_host_system_properties(&sys_name,
+ &sys_ccname,
+ reference,
+ broker,
+ context);
+
+ if (s->rc != CMPI_RC_OK) {
+ cu_statusf(broker, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get host attributes");
+ goto out;
+ }
+
+ CMSetProperty(inst, "SystemName", sys_name, CMPI_chars);
+ CMSetProperty(inst, "SystemCreationClassName", sys_ccname, CMPI_chars);
+ CMSetProperty(inst, "Name", (CMPIValue *)filter->name, CMPI_chars);
+ CMSetProperty(inst, "InstanceID", (CMPIValue *)filter->uuid,
+ CMPI_chars);
+ CMSetProperty(inst, "Direction", (CMPIValue *)&direction, CMPI_uint16);
+
+ out:
+ return inst;
+}
+
+static struct acl_filter *convert_instance_to_filter(
+ const CMPIInstance *instance,
+ const CMPIContext *context,
+ CMPIStatus *s)
+{
+ struct acl_filter *filter = NULL;
+ const char *name = NULL;
+
+ if (cu_get_str_prop(instance, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Name property");
+ goto out;
+ }
+
+ filter = malloc(sizeof(*filter));
+ if (filter == NULL)
+ goto out;
+
+ memset(filter, 0, sizeof(*filter));
+ filter->name = (char *)name;
+
+ out:
+ return filter;
+}
+
+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;
+}
+
+static CMPIStatus CreateInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIInstance *instance)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ const char *name = NULL;
+ struct acl_filter *filter = NULL;
+ CMPIInstance *_instance = NULL;
+ virConnectPtr conn = NULL;
+
+ /**Get Name from instance rather than reference since keys
+ * are set by this provider, not the client.
+ */
+ if (cu_get_str_prop(instance, "Name", &name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Name property");
+ 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_ALREADY_EXISTS,
+ "Instance already exists");
+ goto out;
+ }
+
+ filter = convert_instance_to_filter(instance, context, &s);
+ if (filter == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to convert instance to filter");
+ goto out;
+ }
+
+ if (create_filter(conn, filter) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to create filter");
+ goto out;
+ }
+
+ cleanup_filter(filter);
+
+ get_filter_by_name(conn, name, &filter);
+ if (filter == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to get filter");
+ goto out;
+ }
+
+ _instance = convert_filter_to_instance(filter,
+ _BROKER,
+ context,
+ reference,
+ &s);
+
+ if(_instance != NULL)
+ cu_return_instance_name(results, _instance);
+
+ CU_DEBUG("CreateInstance complete");
+
+ out:
+ free((char *)name);
+ cleanup_filter(filter);
+ virConnectClose(conn);
+
+ return s;
+}
+
+static CMPIStatus ModifyInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference,
+ const CMPIInstance *instance,
+ const char **properties)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ const char *name = NULL;
+ struct acl_filter *filter = NULL;
+ virConnectPtr conn = 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,
+ "Instance does not exist");
+ goto out;
+ }
+
+ filter = convert_instance_to_filter(instance, context, &s);
+ if (filter == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_NOT_FOUND,
+ "Failed to convert instance to filter");
+ goto out;
+ }
+
+ if (create_filter(conn, filter) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to create filter");
+ goto out;
+ }
+ out:
+ cleanup_filter(filter);
+ virConnectClose(conn);
+
+ return s;
+}
+
+static CMPIStatus DeleteInstance(
+ CMPIInstanceMI *self,
+ const CMPIContext *context,
+ const CMPIResult *results,
+ const CMPIObjectPath *reference)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ const char *name = NULL;
+ struct acl_filter *filter = NULL;
+ virConnectPtr conn = 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,
+ "Instance does not exist");
+ goto out;
+ }
+
+ delete_filter(conn, filter);
+
+ out:
+ cleanup_filter(filter);
+ virConnectClose(conn);
+
+ return s;
+}
+
+DEFAULT_EQ();
+DEFAULT_INST_CLEANUP();
+
+STD_InstanceMIStub(,
+ Virt_FilterList,
+ _BROKER,
+ libvirt_cim_init());
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_FilterList.h b/src/Virt_FilterList.h
new file mode 100644
--- /dev/null
+++ b/src/Virt_FilterList.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __VIRT_FILTERLIST_H
+#define __VIRT_FILTERLIST_H
+
+#include "acl_parsing.h"
+
+/**
+ * Return a list of filter lists
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class name
+ * prefix), but can also be used to scope the results by
+ * specifying a specific filter
+ * @param list A pointer to an array of CMPIInstance objects
+ * (caller inits before and frees after)
+ */
+CMPIStatus enum_filter_lists(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct inst_list *list);
+
+/**
+ * Return a filter instance by reference
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class name
+ * prefix), but can also be used to scope the results by
+ * specifying a specific filter
+ * @param instance A pointer to a CMPIInstance * to place the new instance
+ */
+CMPIStatus get_filter_by_ref(
+ const CMPIBroker *broker,
+ const CMPIContext *contest,
+ const CMPIObjectPath *reference,
+ CMPIInstance **instance);
+
+/**
+ * Return a list of filter lists
+ *
+ * @param broker A pointer to the CIM broker
+ * @param context A pointer to an operation context
+ * @param reference Defines the libvirt connection to use (via class name
+ * prefix), but can also be used to scope the results by
+ * specifying a specific filter
+ * @param filter A pointer to a acl_filter
+ * @param instance A pointer to a CMPIInstance * to place the new instance
+ */
+CMPIStatus instance_from_filter(
+ const CMPIBroker *broker,
+ const CMPIContext *context,
+ const CMPIObjectPath *reference,
+ struct acl_filter *filter,
+ CMPIInstance **instance);
+
+#endif
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_HostedFilterList.c b/src/Virt_HostedFilterList.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_HostedFilterList.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_association.h>
+
+#include "misc_util.h"
+#include "Virt_HostSystem.h"
+#include "Virt_FilterList.h"
+
+static const CMPIBroker *_BROKER;
+
+static CMPIStatus host_to_list(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+
+ /* validate host reference */
+ s = get_host(_BROKER, info->context, reference, &instance, false);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ s = cu_validate_ref(_BROKER, reference, instance);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ s = enum_filter_lists(_BROKER, info->context, reference, list);
+
+ out:
+ return s;
+}
+
+static CMPIStatus list_to_host(
+ const CMPIObjectPath *reference,
+ struct std_assoc_info *info,
+ struct inst_list *list)
+{
+ CMPIStatus s = {CMPI_RC_OK, NULL};
+ CMPIInstance *instance = NULL;
+
+ /* validate filter reference */
+ s = get_filter_by_ref(_BROKER, info->context, reference, &instance);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ s = get_host(_BROKER, info->context, reference, &instance, false);
+ if (s.rc != CMPI_RC_OK)
+ goto out;
+
+ if (instance != NULL)
+ inst_list_add(list, instance);
+
+ out:
+ return s;
+}
+
+LIBVIRT_CIM_DEFAULT_MAKEREF()
+
+static char *antecedent[] = {
+ "KVM_HostSystem",
+ NULL
+};
+
+static char *dependent[] = {
+ "KVM_FilterList",
+ NULL
+};
+
+static char *assoc_class_name[] = {
+ "KVM_HostedFilterList",
+ NULL
+};
+
+static struct std_assoc _host_to_list = {
+ .source_class = (char **)&antecedent,
+ .source_prop = "Antecedent",
+
+ .target_class = (char **)&dependent,
+ .target_prop = "Dependent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = host_to_list,
+ .make_ref = make_ref
+};
+
+static struct std_assoc _list_to_host = {
+ .source_class = (char **)&dependent,
+ .source_prop = "Dependent",
+
+ .target_class = (char **)&antecedent,
+ .target_prop = "Antecedent",
+
+ .assoc_class = (char **)&assoc_class_name,
+
+ .handler = list_to_host,
+ .make_ref = make_ref
+};
+
+static struct std_assoc *handlers[] = {
+ &_host_to_list,
+ &_list_to_host,
+ NULL
+};
+
+STDA_AssocMIStub(,
+ Virt_HostedFilterList,
+ _BROKER,
+ libvirt_cim_init(),
+ handlers);
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_NestedFilterList.c b/src/Virt_NestedFilterList.c
new file mode 100644
--- /dev/null
+++ b/src/Virt_NestedFilterList.c
@@ -0,0 +1,503 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ * Chip Vincent <cvincent(a)us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_association.h>
+#include <libcmpiutil/std_instance.h>
+
+/* FIXME: This seems to be needed to compile STREQC, which suggests
+ * libcmpiutil.h needs to add the include since the marco is defined there.
+ */
+#include <string.h>
+#include <strings.h>
+
+#include "acl_parsing.h"
+#include "misc_util.h"
+#include "Virt_FilterList.h"
+
+static const CMPIBroker *_BROKER;
+
+/* 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;
+}
+
+
+/**
+ * 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);
+
+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 *parent_name = NULL;
+ struct acl_filter *parent_filter = NULL;
+ CMPIObjectPath *dependent = NULL;
+ const char *child_name = NULL;
+ struct acl_filter *child_filter = NULL;
+ virConnectPtr conn = NULL;
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ 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", &parent_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, parent_name, &parent_filter);
+ if (parent_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, "Name", &child_name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Dependent.Name property");
+ goto out;
+ }
+
+ get_filter_by_name(conn, child_name, &child_filter);
+ if (child_filter == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Dependent.Name object does not exist");
+ goto out;
+ }
+
+ char *dup = strdup(child_name);
+
+ if (append_filter_ref(parent_filter, dup) == 0) {
+ free(dup);
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to append filter reference");
+ goto out;
+ }
+
+ if (update_filter(conn, parent_filter) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to update filter");
+ goto out;
+ }
+
+ out:
+ free((char *)parent_name);
+ free((char *)child_name);
+
+ cleanup_filter(parent_filter);
+ cleanup_filter(child_filter);
+
+ 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 *parent_name = NULL;
+ struct acl_filter *parent_filter = NULL;
+ CMPIObjectPath *dependent = NULL;
+ const char *child_name = NULL;
+ struct acl_filter *child_filter = NULL;
+ virConnectPtr conn = NULL;
+
+ conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
+ if (conn == NULL)
+ goto out;
+
+ 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", &parent_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, parent_name, &parent_filter);
+ if (parent_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, "Name", &child_name) != CMPI_RC_OK) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Unable to get Dependent.Name property");
+ goto out;
+ }
+
+ get_filter_by_name(conn, child_name, &child_filter);
+ if (child_filter == NULL) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Dependent.Name object does not exist");
+ goto out;
+ }
+
+ if (remove_filter_ref(parent_filter, child_name) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to remove filter reference");
+ goto out;
+ }
+
+ if (update_filter(conn, parent_filter) == 0) {
+ cu_statusf(_BROKER, &s,
+ CMPI_RC_ERR_FAILED,
+ "Failed to update filter");
+ goto out;
+ }
+
+ out:
+ free((char *)parent_name);
+ free((char *)child_name);
+
+ cleanup_filter(parent_filter);
+ cleanup_filter(child_filter);
+
+ 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:
+ */
+
13 years, 5 months
[PATCH] #2 Configure tweaks
by Eduardo Lima (Etrunko)
# HG changeset patch
# User Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
# Date 1306269980 10800
# Node ID 1a731e7afdcf6e7115f0fe01b2a121c510acd8f1
# Parent a93bab93b304329e9f63d50a8d46cab427271c8d
Configure tweaks
acinclude.m4
- Better output when checking for CMPI includes
configure.ac
- Use automake silent rules if available
- Introduce libtool version-info.
Changes from #1
Makefile.am
- Generate versioned .so files
Signed-off-by: Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
diff -r a93bab93b304 -r 1a731e7afdcf acinclude.m4
--- a/acinclude.m4 Tue May 24 17:02:49 2011 -0300
+++ b/acinclude.m4 Tue May 24 17:46:20 2011 -0300
@@ -71,11 +71,9 @@
],
[
have_CMPI=yes
- dnl AC_MSG_RESULT(yes)
],
[
have_CMPI=no
- dnl AC_MSG_RESULT(no)
])
])
@@ -88,7 +86,7 @@
AC_DEFUN([CHECK_CMPI],
[
- AC_MSG_CHECKING(for CMPI headers)
+ AC_MSG_NOTICE([checking for CMPI headers...])
dnl Check just with the standard include paths
CMPI_CPP_FLAGS="$CPPFLAGS"
_CHECK_CMPI(standard)
@@ -96,6 +94,7 @@
dnl The standard include paths worked.
AC_MSG_RESULT(yes)
else
+ AC_MSG_RESULT(no)
_DIRS_="/usr/include/cmpi \
/usr/local/include/cmpi \
$PEGASUS_ROOT/src/Pegasus/Provider/CMPI \
@@ -115,13 +114,15 @@
dnl Save the new -I parameter
CMPI_CPP_FLAGS="$CPPFLAGS"
break
+ else
+ AC_MSG_RESULT(no)
fi
CPPFLAGS=$_cppflags
done
fi
CPPFLAGS="$CMPI_CPP_FLAGS"
if test "$have_CMPI" == "no"; then
- AC_MSG_ERROR(no. Sorry cannot find CMPI headers files.)
+ AC_MSG_ERROR(Cannot find CMPI headers files.)
fi
]
)
@@ -133,7 +134,7 @@
AC_DEFUN([CHECK_PROVIDERDIR],
[
- AC_MSG_CHECKING(for CMPI provider directory)
+ AC_MSG_NOTICE([checking for CMPI provider directory])
_DIRS="$libdir/cmpi"
save_exec_prefix=${exec_prefix}
save_prefix=${prefix}
@@ -146,7 +147,7 @@
for _dir in $_DIRS
do
_xdir=`eval echo $_dir`
- AC_MSG_CHECKING( $_dir )
+ AC_MSG_CHECKING([for $_dir])
if test -d $_xdir ; then
dnl Found it
AC_MSG_RESULT(yes)
@@ -172,7 +173,7 @@
AC_DEFUN([CHECK_CIMSERVER],
[
- AC_MSG_CHECKING(for CIM servers)
+ AC_MSG_NOTICE([checking for CIM servers])
if test x"$CIMSERVER" = x
then
_SERVERS="sfcbd cimserver owcimomd"
@@ -194,13 +195,18 @@
esac
fi
break;
- fi
+ fi
+ done
+ if test x"$CIMSERVER" == x; then
+ AC_MSG_RESULT(no)
+ else
+ break
+ fi
done
- done
PATH=$_SAVE_PATH
if test x"$CIMSERVER" == x ; then
CIMSERVER=sfcb
- AC_MSG_RESULT(implied: $CIMSERVER)
+ AC_MSG_WARN([CIM server implied: $CIMSERVER])
fi
fi
# Cross platform only needed for sfcb currently
diff -r a93bab93b304 -r 1a731e7afdcf configure.ac
--- a/configure.ac Tue May 24 17:02:49 2011 -0300
+++ b/configure.ac Tue May 24 17:46:20 2011 -0300
@@ -1,10 +1,34 @@
# (C) Copyright IBM Corp. 2005
+m4_define([libvirtcim_maj], [0])
+m4_define([libvirtcim_min], [5])
+m4_define([libvirtcim_mic], [12])
+m4_define([libvirtcim_version], [libvirtcim_maj.libvirtcim_min.libvirtcim_mic])
-AC_INIT(libvirt CMPI provider, 0.5.12, cvincent(a)us.ibm.com, libvirt-cim)
+AC_INIT([libvirt CMPI provider], [libvirtcim_version], [cvincent(a)us.ibm.com],
+ [libvirt-cim])
AC_CONFIG_SRCDIR([src/Virt_ComputerSystem.c])
+# Autogenerate the autoconf header file to store build settings
+AC_CONFIG_HEADER([config.h])
+
+# Use silent rules if possible
+AM_INIT_AUTOMAKE
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+m4_define([lt_cur], m4_eval(libvirtcim_maj + libvirtcim_min))
+m4_define([lt_rev], libvirtcim_mic)
+m4_define([lt_age], libvirtcim_min)
+VERSION_INFO="lt_cur:lt_rev:lt_age"
+AC_SUBST(VERSION_INFO)
+
+AC_PROG_CC
+AC_C_CONST
+AC_PROG_LIBTOOL
+AC_PROG_INSTALL
+AC_CHECK_HEADERS([stdlib.h string.h unistd.h])
AC_CHECK_HEADERS([stdarg.h errno.h])
+AC_HEADER_STDC
AC_CHECK_FUNCS([popen pclose fgets asprintf vfprintf fprintf snprintf sscanf])
CPPFLAGS="$CPPFLAGS -DCMPI_VERSION=100"
@@ -109,12 +133,6 @@
AC_SUBST(XEN_EMULATOR)
AC_DEFINE_UNQUOTED(XEN_EMULATOR, "$XEN_EMULATOR", [Location of Xen FullVirt emulator])
-# Autogenerate the autoconf header file to store build settings
-AC_CONFIG_HEADER([config.h])
-
-topdir=`pwd`
-AC_SUBST(topdir)
-
AC_PATH_PROG(XSLTPROC, xsltproc, /usr/bin/xsltproc)
# Autogenerate the Makefile
@@ -129,14 +147,6 @@
Makefile
])
-AM_INIT_AUTOMAKE
-
-AC_PROG_CC
-AC_C_CONST
-AC_PROG_LIBTOOL
-AC_PROG_INSTALL
-AC_CHECK_HEADERS([stdlib.h string.h unistd.h])
-AC_HEADER_STDC
# Check for the required CMPI header files (this macro is defined in acinclude.m4)
CHECK_CMPI
diff -r a93bab93b304 -r 1a731e7afdcf libxkutil/Makefile.am
--- a/libxkutil/Makefile.am Tue May 24 17:02:49 2011 -0300
+++ b/libxkutil/Makefile.am Tue May 24 17:46:20 2011 -0300
@@ -3,6 +3,8 @@
CFLAGS += $(CFLAGS_STRICT)
+AM_LDFLAGS = -version-info @VERSION_INFO@
+
noinst_HEADERS = cs_util.h misc_util.h device_parsing.h xmlgen.h infostore.h \
pool_parsing.h
diff -r a93bab93b304 -r 1a731e7afdcf src/Makefile.am
--- a/src/Makefile.am Tue May 24 17:02:49 2011 -0300
+++ b/src/Makefile.am Tue May 24 17:46:20 2011 -0300
@@ -29,7 +29,8 @@
CFLAGS += -I$(top_builddir)/libxkutil $(CFLAGS_STRICT)
-AM_LDFLAGS = $(XKUADD)
+AM_LDFLAGS = $(XKUADD) \
+ -version-info @VERSION_INFO@
providerdir = $(PROVIDERDIR)
13 years, 5 months