[libvirt] [PATCH v2 0/4] support for changing cpu.shares for inactive domains from virsh cmd
by Hu Tao
Currently cpu.shares can only be configured by editing domains' xmls.
this series enables us to change cpu.shares from virsh cmd schedinfo
even when domain is inactive.
changes:
v2:
- since v1 patches that delete all generated RPC files(by Daniel) and
that refactor remote generator(by Matthias) have gone into master
branch, which affects the series heavily. So rebase the series on
the latest code.
Hu Tao (4):
introduce virDomainSetSchedulerParametersFlags
qemu: introduce qemuSetSchedulerParametersFlags
remote: introduce remoteSetSchedulerParametersFlags
virsh: add --persistent to cmd schedinfo
daemon/remote.c | 71 ++++++++++++++++++++++++++++++++++++++++++
daemon/remote_generator.pl | 2 +
include/libvirt/libvirt.h.in | 13 ++++++++
python/generator.py | 1 +
src/driver.h | 8 +++++
src/esx/esx_driver.c | 1 +
src/libvirt.c | 62 ++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 5 +++
src/libxl/libxl_driver.c | 1 +
src/lxc/lxc_driver.c | 1 +
src/openvz/openvz_driver.c | 1 +
src/phyp/phyp_driver.c | 1 +
src/qemu/qemu_driver.c | 66 ++++++++++++++++++++++++++++++---------
src/remote/remote_driver.c | 69 ++++++++++++++++++++++++++++++++++++++++
src/remote/remote_protocol.x | 10 +++++-
src/test/test_driver.c | 1 +
src/uml/uml_driver.c | 1 +
src/vbox/vbox_tmpl.c | 1 +
src/vmware/vmware_driver.c | 1 +
src/xen/xen_driver.c | 1 +
src/xenapi/xenapi_driver.c | 1 +
tools/virsh.c | 14 ++++++++-
22 files changed, 315 insertions(+), 17 deletions(-)
--
1.7.3.1
--
Thanks,
Hu Tao
13 years, 7 months
[libvirt] [PATCH 8/9] add DHCP snooping support to nwfilter
by David L Stevens
This patch adds DHCP Snooping support to libvirt.
Signed-off-by: David L Stevens <dlstevens(a)us.ibm.com>
diff --git a/examples/xml/nwfilter/no-ip-spoofing.xml b/examples/xml/nwfilter/no-ip-spoofing.xml
index 2fccd12..2ae9500 100644
--- a/examples/xml/nwfilter/no-ip-spoofing.xml
+++ b/examples/xml/nwfilter/no-ip-spoofing.xml
@@ -4,4 +4,9 @@
<rule action='return' direction='out'>
<ip match='yes' srcipaddr='$IP' />
</rule>
+ <!-- allow DHCP requests -->
+ <rule action='return' direction='out'>
+ <ip match='yes' srcipaddr='0.0.0.0' protocol='udp' srcportstart='68'
+ srcportend='68' />
+ </rule>
</filter>
diff --git a/src/Makefile.am b/src/Makefile.am
index 1eaa7d1..3da0797 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -386,6 +386,8 @@ NWFILTER_DRIVER_SOURCES = \
nwfilter/nwfilter_driver.h nwfilter/nwfilter_driver.c \
nwfilter/nwfilter_gentech_driver.c \
nwfilter/nwfilter_gentech_driver.h \
+ nwfilter/nwfilter_dhcpsnoop.c \
+ nwfilter/nwfilter_dhcpsnoop.h \
nwfilter/nwfilter_ebiptables_driver.c \
nwfilter/nwfilter_ebiptables_driver.h \
nwfilter/nwfilter_learnipaddr.c \
diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c
new file mode 100644
index 0000000..af83149
--- /dev/null
+++ b/src/nwfilter/nwfilter_dhcpsnoop.c
@@ -0,0 +1,582 @@
+
+/*
+ * nwfilter_dhcpsnoop.c: support for DHCP snooping used by a VM
+ * on an interface
+ *
+ * Copyright (C) 2011 IBM Corp.
+ * Copyright (C) 2011 David L Stevens
+ *
+ * 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
+ *
+ * Author: David L Stevens <dlstevens(a)us.ibm.com>
+ * Based in part on work by Stefan Berger <stefanb(a)us.ibm.com>
+ */
+
+#include <config.h>
+
+#ifdef HAVE_LIBPCAP
+#include <pcap.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+
+#include <arpa/inet.h>
+#include <net/ethernet.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <intprops.h>
+
+#include "internal.h"
+
+#include "buf.h"
+#include "memory.h"
+#include "logging.h"
+#include "datatypes.h"
+#include "interface.h"
+#include "virterror_internal.h"
+#include "threads.h"
+#include "conf/nwfilter_params.h"
+#include "conf/domain_conf.h"
+#include "nwfilter_gentech_driver.h"
+#include "nwfilter_ebiptables_driver.h"
+#include "nwfilter_dhcpsnoop.h"
+
+#define VIR_FROM_THIS VIR_FROM_NWFILTER
+
+static virHashTablePtr SnoopReqs;
+
+struct virNWFilterSnoopReq {
+ virConnectPtr conn;
+ virNWFilterTechDriverPtr techdriver;
+ enum virDomainNetType nettype;
+ virNWFilterDefPtr filter;
+ const char *ifname;
+ virNWFilterHashTablePtr vars;
+ virNWFilterDriverStatePtr driver;
+ pthread_t thread;
+ /* start and end of lease list, ordered by lease time */
+ struct iplease *start;
+ struct iplease *end;
+ bool die;
+};
+
+#define POLL_INTERVAL 10*1000 /* 10 secs */
+
+struct iplease {
+ uint32_t ipl_ipaddr;
+ uint32_t ipl_server;
+ struct virNWFilterSnoopReq *ipl_req;
+ unsigned int ipl_timeout;
+ /* timer list */
+ struct iplease *ipl_prev;
+ struct iplease *ipl_next;
+};
+
+static struct iplease *ipl_getbyip(struct iplease *start, uint32_t ipaddr);
+static void ipl_update(struct iplease *pl, uint32_t timeout);
+
+
+/*
+ * ipl_tadd - add an IP lease to the timer list
+ */
+static void
+ipl_tadd(struct iplease *plnew)
+{
+ struct virNWFilterSnoopReq *req = plnew->ipl_req;
+ struct iplease *pl;
+
+ plnew->ipl_next = plnew->ipl_prev = 0;
+ if (!req->start) {
+ plnew->ipl_prev = plnew->ipl_next = 0;
+ req->start = req->end = plnew;
+ return;
+ }
+ for (pl = req->end; pl && plnew->ipl_timeout < pl->ipl_timeout;
+ pl = pl->ipl_prev)
+ /* empty */ ;
+ if (!pl) {
+ plnew->ipl_next = req->start;
+ req->start = plnew;
+ } else {
+ plnew->ipl_next = pl->ipl_next;
+ pl->ipl_next = plnew;
+ }
+ plnew->ipl_prev = pl;
+ if (plnew->ipl_next)
+ plnew->ipl_next->ipl_prev = plnew;
+ else
+ req->end = plnew;
+}
+
+/*
+ * ipl_add - create or update an IP lease
+ */
+static void
+ipl_add(struct iplease *plnew)
+{
+ struct iplease *pl;
+ int rc;
+ char ipbuf[20]; /* dotted decimal IP addr string */
+ char *ipstr;
+
+ pl = ipl_getbyip(plnew->ipl_req->start, plnew->ipl_ipaddr);
+ if (pl) {
+ ipl_update(pl, plnew->ipl_timeout);
+ return;
+ }
+ if (VIR_ALLOC(pl) < 0) {
+ virReportOOMError();
+ return;
+ }
+ *pl = *plnew;
+
+ if (!inet_ntop(AF_INET, &pl->ipl_ipaddr, ipbuf, sizeof(ipbuf))) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("ipl_add inet_ntop " "failed (0x%08X)"),
+ pl->ipl_ipaddr);
+ VIR_FREE(pl);
+ return;
+
+ }
+
+ ipstr = strdup(ipbuf);
+ if (!ipstr) {
+ VIR_FREE(pl);
+ virReportOOMError();
+ return;
+ }
+ rc = virNWFilterChangeVar(pl->ipl_req->conn,
+ pl->ipl_req->techdriver,
+ pl->ipl_req->nettype,
+ pl->ipl_req->filter,
+ pl->ipl_req->ifname,
+ pl->ipl_req->vars,
+ pl->ipl_req->driver, "IP", ipstr, 0);
+ if (rc) {
+ VIR_FREE(ipstr);
+ VIR_FREE(pl);
+ return;
+ }
+ ipl_tadd(pl);
+}
+
+/*
+ * ipl_tdel - remove an IP lease from the timer list
+ */
+static void
+ipl_tdel(struct iplease *ipl)
+{
+ struct virNWFilterSnoopReq *req = ipl->ipl_req;
+
+ if (ipl->ipl_prev)
+ ipl->ipl_prev->ipl_next = ipl->ipl_next;
+ else
+ req->start = ipl->ipl_next;
+ if (ipl->ipl_next)
+ ipl->ipl_next->ipl_prev = ipl->ipl_prev;
+ else
+ req->end = ipl->ipl_prev;
+ ipl->ipl_next = ipl->ipl_prev = 0;
+}
+
+/*
+ * ipl_del - delete an IP lease
+ */
+static void
+ipl_del(struct iplease *ipl)
+{
+ struct virNWFilterSnoopReq *req;
+ char ipbuf[20]; /* dotted decimal IP addr string */
+ char *ipstr;
+
+ if (!ipl)
+ return;
+
+ req = ipl->ipl_req;
+
+ ipl_tdel(ipl);
+
+ if (inet_ntop(AF_INET, &ipl->ipl_ipaddr, ipbuf, sizeof(ipbuf))) {
+ ipstr = strdup(ipbuf);
+ if (virNWFilterChangeVar(req->conn,
+ req->techdriver,
+ req->nettype,
+ req->filter,
+ req->ifname,
+ req->vars, req->driver, "IP", ipstr, 1))
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("ipl_del virNWFilterChangeVar failed; "
+ "filter not deleted"));
+ } else
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("ipl_del inet_ntop " "failed (0x%08X)"),
+ ipl->ipl_ipaddr);
+ VIR_FREE(ipl);
+}
+
+/*
+ * ipl_update - update the timeout on an IP lease
+ */
+static void
+ipl_update(struct iplease *ipl, uint32_t timeout)
+{
+ ipl_tdel(ipl);
+ ipl->ipl_timeout = timeout;
+ ipl_tadd(ipl);
+ return;
+}
+
+/*
+ * ipl_getbyip - lookup IP lease by IP address
+ */
+static struct iplease *
+ipl_getbyip(struct iplease *start, uint32_t ipaddr)
+{
+ struct iplease *pl;
+
+ for (pl = start; pl && pl->ipl_ipaddr != ipaddr; pl = pl->ipl_next)
+ /* empty */ ;
+ return pl;
+}
+
+#define GRACE 5
+
+/*
+ * ipl_trun - run the IP lease timeout list
+ */
+static unsigned int
+ipl_trun(struct virNWFilterSnoopReq *req)
+{
+ uint32_t now;
+
+ now = time(0);
+ while (req->start && req->start->ipl_timeout <= now)
+ ipl_del(req->start);
+ return 0;
+}
+
+typedef unsigned char Eaddr[6];
+
+struct eth {
+ Eaddr eh_dst;
+ Eaddr eh_src;
+ unsigned short eh_type;
+ unsigned char eh_data[0];
+};
+
+struct dhcp {
+ unsigned char d_op;
+ unsigned char d_htype;
+ unsigned char d_hlen;
+ unsigned char d_hops;
+ unsigned int d_xid;
+ unsigned short d_secs;
+ unsigned short d_flags;
+ unsigned int d_ciaddr;
+ unsigned int d_yiaddr;
+ unsigned int d_siaddr;
+ unsigned int d_giaddr;
+ unsigned char d_chaddr[16];
+ char d_sname[64];
+ char d_file[128];
+ unsigned char d_opts[0];
+};
+
+/* DHCP options */
+
+#define DHCPO_PAD 0
+#define DHCPO_LEASE 51 /* lease time in secs */
+#define DHCPO_MTYPE 53 /* message type */
+#define DHCPO_END 255 /* end of options */
+
+/* DHCP message types */
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPRELEASE 7
+
+unsigned char dhcp_magic[4] = { 99, 130, 83, 99 };
+
+static int
+dhcp_getopt(struct dhcp *pd, int len, int *pmtype, int *pleasetime)
+{
+ int oind, olen;
+ int oend;
+
+ olen = len - sizeof *pd;
+ oind = 0;
+
+ if (olen < 4) /* bad magic */
+ return -1;
+ for (oind = 0; oind < sizeof dhcp_magic; ++oind)
+ if (pd->d_opts[oind] != dhcp_magic[oind])
+ return -1; /* bad magic */
+
+ oend = 0;
+
+ *pmtype = *pleasetime = 0;
+
+ while (oind < olen) {
+ switch (pd->d_opts[oind]) {
+ case DHCPO_LEASE:
+ if (olen - oind < 6)
+ goto malformed;
+ if (*pleasetime)
+ return -1; /* duplicate lease time */
+ *pleasetime =
+ ntohl(*(unsigned int *) (pd->d_opts + oind + 2));
+ break;
+ case DHCPO_MTYPE:
+ if (olen - oind < 3)
+ goto malformed;
+ if (*pmtype)
+ return -1; /* duplicate message type */
+ *pmtype = pd->d_opts[oind + 2];
+ break;
+ case DHCPO_PAD:
+ oind++;
+ continue;
+
+ case DHCPO_END:
+ oend = 1;
+ break;
+ default:
+ if (olen - oind < 2)
+ goto malformed;
+ }
+ if (oend)
+ break;
+ oind += pd->d_opts[oind + 1] + 2;
+ }
+ return 0;
+ malformed:
+ VIR_WARN0(_("got lost in the options!"));
+ return -1;
+}
+
+static void
+dhcpdecode(struct virNWFilterSnoopReq *req, struct eth *pep, int len)
+{
+ struct iphdr *pip;
+ struct udphdr *pup;
+ struct dhcp *pd;
+ struct iplease ipl, *pipl;
+ int mtype, leasetime;
+
+ /* go through the protocol headers */
+ pip = (struct iphdr *) pep->eh_data;
+ len -= sizeof(*pep);
+ pup = (struct udphdr *) ((char *) pip + (pip->ihl << 2));
+ len -= pip->ihl << 2;
+ pd = (struct dhcp *) ((char *) pup + sizeof(*pup));
+ len -= sizeof(*pup);
+ if (len < 0)
+ return; /* dhcpdecode: invalid packet length */
+ if (dhcp_getopt(pd, len, &mtype, &leasetime) < 0)
+ return;
+
+ memset(&ipl, 0, sizeof(ipl));
+ ipl.ipl_ipaddr = pd->d_yiaddr;
+ ipl.ipl_server = pd->d_siaddr;
+ if (leasetime == ~0)
+ ipl.ipl_timeout = ~0;
+ else
+ ipl.ipl_timeout = time(0) + leasetime;
+ ipl.ipl_req = req;
+
+ switch (mtype) {
+ case DHCPACK:
+ ipl_add(&ipl);
+ break;
+ case DHCPDECLINE:
+ case DHCPRELEASE:
+ pipl = ipl_getbyip(req->start, ipl.ipl_ipaddr);
+ ipl_del(pipl);
+ break;
+ default:
+ break;
+ }
+}
+
+#define PBUFSIZE 576 /* >= IP/TCP/DHCP headers */
+
+static pcap_t *
+dhcpopen(const char *intf)
+{
+ pcap_t *handle;
+ struct bpf_program fp;
+ char filter[64];
+ char pcap_errbuf[PCAP_ERRBUF_SIZE];
+
+ handle = pcap_open_live(intf, PBUFSIZE, 0, POLL_INTERVAL, pcap_errbuf);
+ if (handle == NULL) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("pcap_open_live: %s"), pcap_errbuf);
+ return 0;
+ }
+
+ sprintf(filter, "port 67 or dst port 68");
+ if (pcap_compile(handle, &fp, filter, 1, PCAP_NETMASK_UNKNOWN) != 0) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("pcap_compile: %s"), pcap_geterr(handle));
+ return 0;
+ }
+ if (pcap_setfilter(handle, &fp) != 0) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("pcap_setfilter: %s"), pcap_geterr(handle));
+ return 0;
+ }
+ pcap_freecode(&fp);
+ return handle;
+}
+
+static void *
+virNWFilterDHCPSnoop(void *req0)
+{
+ struct virNWFilterSnoopReq *req = req0;
+ pcap_t *handle;
+ struct pcap_pkthdr hdr;
+ struct eth *packet;
+ struct iplease *ipl;
+ int ifindex;
+
+ handle = dhcpopen(req->ifname);
+ if (!handle)
+ return 0;
+
+ ifindex = if_nametoindex(req->ifname);
+
+ while (1) {
+ if (req->die)
+ break;
+ ipl_trun(req);
+
+ packet = (struct eth *) pcap_next(handle, &hdr);
+
+ if (!packet) {
+ if (ifaceCheck(false, req->ifname, NULL, ifindex))
+ virNWFilterDHCPSnoopEnd(req->ifname);
+ continue;
+ }
+
+ dhcpdecode(req, packet, hdr.caplen);
+ }
+ /* free all leases */
+ for (ipl = req->start; ipl; ipl = req->start)
+ ipl_del(ipl);
+
+ /* free all req data */
+ VIR_FREE(req->ifname);
+ virNWFilterHashTableFree(req->vars);
+ VIR_FREE(req);
+ return 0;
+}
+
+int
+virNWFilterDHCPSnoopReq(virConnectPtr conn,
+ virNWFilterTechDriverPtr techdriver ATTRIBUTE_UNUSED,
+ enum virDomainNetType nettype ATTRIBUTE_UNUSED,
+ virNWFilterDefPtr filter ATTRIBUTE_UNUSED,
+ const char *ifname ATTRIBUTE_UNUSED,
+ virNWFilterHashTablePtr vars ATTRIBUTE_UNUSED,
+ virNWFilterDriverStatePtr driver ATTRIBUTE_UNUSED)
+{
+ struct virNWFilterSnoopReq *req;
+
+ req = virHashLookup(SnoopReqs, ifname);
+ if (req)
+ return 0;
+ if (VIR_ALLOC(req) < 0) {
+ virReportOOMError();
+ return 1;
+ }
+
+ req->conn = conn;
+ req->techdriver = techdriver;
+ req->nettype = nettype;
+ req->filter = filter;
+ req->ifname = strdup(ifname);
+ req->vars = virNWFilterHashTableCreate(0);
+ if (!req->vars) {
+ virReportOOMError();
+ return 1;
+ }
+ if (virNWFilterHashTablePutAll(vars, req->vars)) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("virNWFilterDHCPSnoopReq: can't copy variables"
+ " on if %s"), ifname);
+ return 1;
+ }
+ req->driver = driver;
+ req->start = req->end = 0;
+
+ if (virHashAddEntry(SnoopReqs, ifname, req)) {
+ VIR_FREE(req);
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("virNWFilterDHCPSnoopReq req add failed on"
+ "interface \"%s\""), ifname);
+ return 1;
+ }
+ if (pthread_create(&req->thread, NULL, virNWFilterDHCPSnoop, req) != 0) {
+ (void) virHashRemoveEntry(SnoopReqs, ifname);
+ VIR_FREE(req);
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("virNWFilterDHCPSnoopReq pthread_create failed"
+ " oninterface \"%s\""), ifname);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * freeReq - hash table free function to kill a request
+ */
+static void
+freeReq(void *req0, const void *name ATTRIBUTE_UNUSED)
+{
+ struct virNWFilterSnoopReq *req = (struct virNWFilterSnoopReq *) req0;
+
+ if (!req)
+ return;
+
+ req->die = 1;
+}
+
+int
+virNWFilterDHCPSnoopInit(void)
+{
+ if (SnoopReqs)
+ return 0;
+ SnoopReqs = virHashCreate(0, freeReq);
+ if (!SnoopReqs) {
+ virReportOOMError();
+ return -1;
+ }
+ return 0;
+}
+
+void
+virNWFilterDHCPSnoopEnd(const char *ifname)
+{
+ if (!SnoopReqs)
+ return;
+ if (ifname)
+ virHashRemoveEntry(SnoopReqs, ifname);
+ else /* free all of them */
+ virHashFree(SnoopReqs);
+}
diff --git a/src/nwfilter/nwfilter_dhcpsnoop.h b/src/nwfilter/nwfilter_dhcpsnoop.h
new file mode 100644
index 0000000..248b1a0
--- /dev/null
+++ b/src/nwfilter/nwfilter_dhcpsnoop.h
@@ -0,0 +1,36 @@
+/*
+ * nwfilter_dhcpsnoop.h: support DHCP snooping for a VM on an interface
+ *
+ * Copyright (C) 2010 IBM Corp.
+ * Copyright (C) 2010 David L Stevens
+ *
+ * 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
+ *
+ * Author: David L Stevens <dlstevens(a)us.ibm.com>
+ */
+
+#ifndef __NWFILTER_DHCPSNOOP_H
+# define __NWFILTER_DHCPSNOOP_H
+
+int virNWFilterDHCPSnoopInit(void);
+int virNWFilterDHCPSnoopReq(virConnectPtr conn,
+ virNWFilterTechDriverPtr techdriver,
+ enum virDomainNetType,
+ virNWFilterDefPtr filter,
+ const char *ifname,
+ virNWFilterHashTablePtr vars,
+ virNWFilterDriverStatePtr driver);
+void virNWFilterDHCPSnoopEnd(const char *ifname);
+#endif /* __NWFILTER_DHCPSNOOP_H */
diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
index 8af3f8a..2e20e59 100644
--- a/src/nwfilter/nwfilter_driver.c
+++ b/src/nwfilter/nwfilter_driver.c
@@ -39,6 +39,7 @@
#include "nwfilter_gentech_driver.h"
#include "configmake.h"
+#include "nwfilter_dhcpsnoop.h"
#include "nwfilter_learnipaddr.h"
#define VIR_FROM_THIS VIR_FROM_NWFILTER
@@ -66,6 +67,8 @@ static int
nwfilterDriverStartup(int privileged) {
char *base = NULL;
+ if (virNWFilterDHCPSnoopInit() < 0)
+ return -1;
if (virNWFilterLearnInit() < 0)
return -1;
@@ -127,6 +130,7 @@ alloc_err_exit:
conf_init_err:
virNWFilterTechDriversShutdown();
+ virNWFilterDHCPSnoopEnd(0);
virNWFilterLearnShutdown();
return -1;
@@ -201,6 +205,7 @@ nwfilterDriverShutdown(void) {
virNWFilterConfLayerShutdown();
virNWFilterTechDriversShutdown();
+ virNWFilterDHCPSnoopEnd(0);
virNWFilterLearnShutdown();
nwfilterDriverLock(driverState);
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
index a459974..c6e6600 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -33,6 +33,7 @@
#include "virterror_internal.h"
#include "nwfilter_gentech_driver.h"
#include "nwfilter_ebiptables_driver.h"
+#include "nwfilter_dhcpsnoop.h"
#include "nwfilter_learnipaddr.h"
@@ -670,13 +671,12 @@ virNWFilterInstantiate(virConnectPtr conn,
virNWFilterDefPtr filter,
const char *ifname,
int ifindex,
- const char *linkdev,
+ const char *linkdev ATTRIBUTE_UNUSED,
virNWFilterHashTablePtr vars,
enum instCase useNewFilter, bool *foundNewFilter,
bool teardownOld,
- const unsigned char *macaddr,
- virNWFilterDriverStatePtr driver,
- bool forceWithPendingReq)
+ const unsigned char *macaddr ATTRIBUTE_UNUSED,
+ virNWFilterDriverStatePtr driver)
{
int rc;
int j, nptrs;
@@ -704,39 +704,38 @@ virNWFilterInstantiate(virConnectPtr conn,
if (virHashSize(missing_vars->hashTable) == 1) {
if (virHashLookup(missing_vars->hashTable,
NWFILTER_STD_VAR_IP) != NULL) {
- if (virNWFilterLookupLearnReq(ifindex) == NULL) {
- rc = virNWFilterLearnIPAddress(techdriver,
- ifname,
- ifindex,
- linkdev,
- nettype, macaddr,
- filter->name,
- vars, driver,
- DETECT_DHCP|DETECT_STATIC);
- }
+
+ rc = _virNWFilterInstantiateRec(conn,
+ techdriver,
+ nettype,
+ filter,
+ ifname,
+ vars,
+ NWFILTER_STD_VAR_IP, 1,
+ &nEntries, &insts,
+ useNewFilter, foundNewFilter,
+ driver);
+ if (!rc)
+ rc = virNWFilterDHCPSnoopReq(conn, techdriver, nettype, filter,
+ ifname, vars, driver);
+ } else
+ rc = 1;
+ if (rc)
goto err_exit;
- }
- rc = 1;
- goto err_exit;
} else if (virHashSize(missing_vars->hashTable) > 1) {
rc = 1;
goto err_exit;
- } else if (!forceWithPendingReq &&
- virNWFilterLookupLearnReq(ifindex) != NULL) {
- goto err_exit;
- }
-
- rc = _virNWFilterInstantiateRec(conn,
- techdriver,
- nettype,
- filter,
- ifname,
- vars,
- 0, 0,
- &nEntries, &insts,
- useNewFilter, foundNewFilter,
- driver);
-
+ } else
+ rc = _virNWFilterInstantiateRec(conn,
+ techdriver,
+ nettype,
+ filter,
+ ifname,
+ vars,
+ 0, 0,
+ &nEntries, &insts,
+ useNewFilter, foundNewFilter,
+ driver);
if (rc)
goto err_exit;
@@ -802,7 +801,6 @@ __virNWFilterInstantiateFilter(virConnectPtr conn,
virNWFilterHashTablePtr filterparams,
enum instCase useNewFilter,
virNWFilterDriverStatePtr driver,
- bool forceWithPendingReq,
bool *foundNewFilter)
{
int rc;
@@ -903,8 +901,7 @@ __virNWFilterInstantiateFilter(virConnectPtr conn,
useNewFilter, foundNewFilter,
teardownOld,
macaddr,
- driver,
- forceWithPendingReq);
+ driver);
virNWFilterHashTableFree(vars);
@@ -950,7 +947,6 @@ _virNWFilterInstantiateFilter(virConnectPtr conn,
net->filterparams,
useNewFilter,
conn->nwfilterPrivateData,
- false,
foundNewFilter);
virNWFilterUnlockFilterUpdates();
@@ -986,7 +982,6 @@ virNWFilterInstantiateFilterLate(virConnectPtr conn,
filterparams,
INSTANTIATE_ALWAYS,
driver,
- true,
&foundNewFilter);
if (rc) {
/* something went wrong... 'DOWN' the interface */
@@ -1098,6 +1093,8 @@ _virNWFilterTeardownFilter(const char *ifname)
return 1;
}
+ virNWFilterDHCPSnoopEnd(ifname);
+
virNWFilterTerminateLearnReq(ifname);
if (virNWFilterLockIface(ifname))
13 years, 7 months
[libvirt] [PATCH 7/9] add DHCP snooping support to nwfilter
by David L Stevens
This patch adds a function that applies or deletes filter rules to existing
chains. Rules referencing the given variable are instantiated with the given
value, or optionally deleted. For example, passing variable "IP" with different
values will install rules using the IP variable with each of the different
values. These rules can later be removed by calling this function with the
same variable and value and "delete" argument set to "1".
Signed-off-by: David L Stevens <dlstevens(a)us.ibm.com>
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
index 0bc3537..a36edbc 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -558,6 +558,92 @@ virNWFilterRuleInstancesToArray(int nEntries,
/**
+ * virNWFilterChangeVar:
+ * @conn: pointer to virConnect object
+ * @techdriver: The driver to use for instantiation
+ * @filter: The filter to instantiate
+ * @ifname: The name of the interface to apply the rules to
+ * @vars: A map holding variable names and values used for instantiating
+ * the filter and its subfilters.
+ * @var: name of variable to change
+ * @value: value of variable to change
+ * @delete: =0 to create or =1 to delete the rules
+ *
+ * Returns 0 on success, a value otherwise.
+ *
+ * Instantiate or delete a filter and all subfilters with variable "var"
+ * set to value "value".
+ * The name of the interface to which the rules belong must be
+ * provided.
+ *
+ * Call this function while holding the NWFilter filter update lock
+ */
+int
+virNWFilterChangeVar(virConnectPtr conn,
+ virNWFilterTechDriverPtr techdriver,
+ enum virDomainNetType nettype,
+ virNWFilterDefPtr filter,
+ const char *ifname,
+ virNWFilterHashTablePtr vars,
+ virNWFilterDriverStatePtr driver,
+ const char *var,
+ char *value,
+ bool delete)
+{
+ int rc;
+ int j, nptrs;
+ int nEntries = 0;
+ virNWFilterRuleInstPtr *insts = NULL;
+ void **ptrs = NULL;
+ bool foundNewFilter = 0;
+
+ if (virNWFilterHashTablePut(vars, var, value, 1)) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, _("Cound not add "
+ "variable \"%s\" to hashmap"), var);
+ return 1;
+ }
+ rc = _virNWFilterInstantiateRec(conn,
+ techdriver,
+ nettype,
+ filter,
+ ifname,
+ vars,
+ NWFILTER_STD_VAR_IP, 0,
+ &nEntries, &insts,
+ INSTANTIATE_ALWAYS, &foundNewFilter,
+ driver);
+ if (rc)
+ goto err_exit;
+ rc = virNWFilterRuleInstancesToArray(nEntries, insts, &ptrs, &nptrs);
+ if (rc)
+ goto err_exit;
+
+ if (virNWFilterHashTableRemoveEntry(vars, var) < 0) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, _("Cound not remove "
+ "variable \"%s\" from hashmap"), var);
+ return 1;
+ }
+
+ if (virNWFilterLockIface(ifname))
+ goto err_exit;
+
+ if (delete)
+ rc = techdriver->removeRules(conn, ifname, nptrs, ptrs);
+ else
+ rc = techdriver->addRules(conn, ifname, nptrs, ptrs);
+ virNWFilterUnlockIface(ifname);
+ VIR_FREE(ptrs);
+
+err_exit:
+
+ for (j = 0; j < nEntries; j++)
+ virNWFilterRuleInstFree(insts[j]);
+ VIR_FREE(insts);
+ return rc;
+}
+
+
+/**
* virNWFilterInstantiate:
* @conn: pointer to virConnect object
* @techdriver: The driver to use for instantiation
diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h
index fa86030..48e87d6 100644
--- a/src/nwfilter/nwfilter_gentech_driver.h
+++ b/src/nwfilter/nwfilter_gentech_driver.h
@@ -48,6 +48,17 @@ int virNWFilterRollbackUpdateFilter(virConnectPtr conn,
int virNWFilterTearOldFilter(virConnectPtr conn,
const virDomainNetDefPtr net);
+int virNWFilterChangeVar(virConnectPtr conn,
+ virNWFilterTechDriverPtr techdriver,
+ enum virDomainNetType nettype,
+ virNWFilterDefPtr filter,
+ const char *ifname,
+ virNWFilterHashTablePtr vars,
+ virNWFilterDriverStatePtr driver,
+ const char *var,
+ char *value,
+ bool delete);
+
int virNWFilterInstantiateFilterLate(virConnectPtr conn,
const char *ifname,
int ifindex,
13 years, 7 months
[libvirt] [PATCH 7/9] add DHCP snooping support to nwfilter
by David L Stevens
This patch adds a function that applies or deletes filter rules to existing
chains. Rules referencing the given variable are instantiated with the given
value, or optionally deleted. For example, passing variable "IP" with different
values will install rules using the IP variable with each of the different
values. These rules can later be removed by calling this function with the
same variable and value and "delete" argument set to "1".
Signed-off-by: David L Stevens <dlstevens(a)us.ibm.com>
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
index 0bc3537..a36edbc 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -558,6 +558,92 @@ virNWFilterRuleInstancesToArray(int nEntries,
/**
+ * virNWFilterChangeVar:
+ * @conn: pointer to virConnect object
+ * @techdriver: The driver to use for instantiation
+ * @filter: The filter to instantiate
+ * @ifname: The name of the interface to apply the rules to
+ * @vars: A map holding variable names and values used for instantiating
+ * the filter and its subfilters.
+ * @var: name of variable to change
+ * @value: value of variable to change
+ * @delete: =0 to create or =1 to delete the rules
+ *
+ * Returns 0 on success, a value otherwise.
+ *
+ * Instantiate or delete a filter and all subfilters with variable "var"
+ * set to value "value".
+ * The name of the interface to which the rules belong must be
+ * provided.
+ *
+ * Call this function while holding the NWFilter filter update lock
+ */
+int
+virNWFilterChangeVar(virConnectPtr conn,
+ virNWFilterTechDriverPtr techdriver,
+ enum virDomainNetType nettype,
+ virNWFilterDefPtr filter,
+ const char *ifname,
+ virNWFilterHashTablePtr vars,
+ virNWFilterDriverStatePtr driver,
+ const char *var,
+ char *value,
+ bool delete)
+{
+ int rc;
+ int j, nptrs;
+ int nEntries = 0;
+ virNWFilterRuleInstPtr *insts = NULL;
+ void **ptrs = NULL;
+ bool foundNewFilter = 0;
+
+ if (virNWFilterHashTablePut(vars, var, value, 1)) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, _("Cound not add "
+ "variable \"%s\" to hashmap"), var);
+ return 1;
+ }
+ rc = _virNWFilterInstantiateRec(conn,
+ techdriver,
+ nettype,
+ filter,
+ ifname,
+ vars,
+ NWFILTER_STD_VAR_IP, 0,
+ &nEntries, &insts,
+ INSTANTIATE_ALWAYS, &foundNewFilter,
+ driver);
+ if (rc)
+ goto err_exit;
+ rc = virNWFilterRuleInstancesToArray(nEntries, insts, &ptrs, &nptrs);
+ if (rc)
+ goto err_exit;
+
+ if (virNWFilterHashTableRemoveEntry(vars, var) < 0) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, _("Cound not remove "
+ "variable \"%s\" from hashmap"), var);
+ return 1;
+ }
+
+ if (virNWFilterLockIface(ifname))
+ goto err_exit;
+
+ if (delete)
+ rc = techdriver->removeRules(conn, ifname, nptrs, ptrs);
+ else
+ rc = techdriver->addRules(conn, ifname, nptrs, ptrs);
+ virNWFilterUnlockIface(ifname);
+ VIR_FREE(ptrs);
+
+err_exit:
+
+ for (j = 0; j < nEntries; j++)
+ virNWFilterRuleInstFree(insts[j]);
+ VIR_FREE(insts);
+ return rc;
+}
+
+
+/**
* virNWFilterInstantiate:
* @conn: pointer to virConnect object
* @techdriver: The driver to use for instantiation
diff --git a/src/nwfilter/nwfilter_gentech_driver.h b/src/nwfilter/nwfilter_gentech_driver.h
index fa86030..48e87d6 100644
--- a/src/nwfilter/nwfilter_gentech_driver.h
+++ b/src/nwfilter/nwfilter_gentech_driver.h
@@ -48,6 +48,17 @@ int virNWFilterRollbackUpdateFilter(virConnectPtr conn,
int virNWFilterTearOldFilter(virConnectPtr conn,
const virDomainNetDefPtr net);
+int virNWFilterChangeVar(virConnectPtr conn,
+ virNWFilterTechDriverPtr techdriver,
+ enum virDomainNetType nettype,
+ virNWFilterDefPtr filter,
+ const char *ifname,
+ virNWFilterHashTablePtr vars,
+ virNWFilterDriverStatePtr driver,
+ const char *var,
+ char *value,
+ bool delete);
+
int virNWFilterInstantiateFilterLate(virConnectPtr conn,
const char *ifname,
int ifindex,
13 years, 7 months
[libvirt] [PATCH 6/9] add DHCP snooping support to nwfilter
by David L Stevens
This patch adds the capability of adding individual rules to existing chains.
Signed-off-by: David L Stevens <dlstevens(a)us.ibm.com>
diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
index 25f7b60..4b6759a 100644
--- a/src/conf/nwfilter_conf.h
+++ b/src/conf/nwfilter_conf.h
@@ -532,6 +532,11 @@ typedef int (*virNWFilterRuleTeardownNewRules)(virConnectPtr conn,
typedef int (*virNWFilterRuleTeardownOldRules)(virConnectPtr conn,
const char *ifname);
+typedef int (*virNWFilterRuleAddRules)(virConnectPtr conn,
+ const char *ifname,
+ int nruleInstances,
+ void **_inst);
+
typedef int (*virNWFilterRuleRemoveRules)(virConnectPtr conn,
const char *ifname,
int nruleInstances,
@@ -572,6 +577,7 @@ struct _virNWFilterTechDriver {
virNWFilterRuleApplyNewRules applyNewRules;
virNWFilterRuleTeardownNewRules tearNewRules;
virNWFilterRuleTeardownOldRules tearOldRules;
+ virNWFilterRuleAddRules addRules;
virNWFilterRuleRemoveRules removeRules;
virNWFilterRuleAllTeardown allTeardown;
virNWFilterRuleFreeInstanceData freeRuleInstance;
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c
index f74f63b..0cb4d00 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -3686,6 +3686,78 @@ err_exit:
return rc;
}
+/**
+ * ebiptablesAddRules:
+ * @conn : pointer to virConnect object
+ * @ifname : the name of the interface to which the rules apply
+ * @nRuleInstance : the number of given rules
+ * @_inst : array of rule instantiation data
+ *
+ * Add all rules one after the other
+ *
+ * Return 0 on success, 1 if execution of one or more cleanup
+ * commands failed.
+ */
+static int
+ebiptablesAddRules(virConnectPtr conn,
+ const char *ifname,
+ int nruleInstances,
+ void **_inst)
+{
+ int i;
+ int cli_status;
+ ebiptablesRuleInstPtr *inst = (ebiptablesRuleInstPtr *)_inst;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ bool haveIptables = false;
+ bool haveIp6tables = false;
+
+ for (i = 0; i < nruleInstances; i++) {
+ sa_assert (inst);
+ switch (inst[i]->ruleType) {
+ case RT_EBTABLES:
+ ebiptablesInstCommand(&buf,
+ inst[i]->commandTemplate,
+ 'A', -1, 1);
+ break;
+ case RT_IPTABLES:
+ if (inst[i]->ruleType == RT_IPTABLES)
+ iptablesInstCommand(&buf,
+ inst[i]->commandTemplate,
+ 'A', -1, 1);
+ haveIptables = true;
+ break;
+ case RT_IP6TABLES:
+ if (inst[i]->ruleType == RT_IP6TABLES)
+ iptablesInstCommand(&buf,
+ inst[i]->commandTemplate,
+ 'A', -1, 1);
+ haveIp6tables = true;
+ break;
+ }
+ }
+
+ if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0)
+ goto err_exit;
+
+ if (haveIptables)
+ iptablesCheckBridgeNFCallEnabled(false);
+
+ if (haveIp6tables)
+ iptablesCheckBridgeNFCallEnabled(true);
+
+ return 0;
+
+err_exit:
+ (void) ebiptablesRemoveRules(conn, ifname, nruleInstances, _inst);
+
+ virNWFilterReportError(VIR_ERR_BUILD_FIREWALL,
+ _("Some rules could not be created for "
+ "interface %s."),
+ ifname);
+
+ return 1;
+}
+
/**
* ebiptablesAllTeardown:
@@ -3742,6 +3814,7 @@ virNWFilterTechDriver ebiptables_driver = {
.tearNewRules = ebiptablesTearNewRules,
.tearOldRules = ebiptablesTearOldRules,
.allTeardown = ebiptablesAllTeardown,
+ .addRules = ebiptablesAddRules,
.removeRules = ebiptablesRemoveRules,
.freeRuleInstance = ebiptablesFreeRuleInstance,
.displayRuleInstance = ebiptablesDisplayRuleInstance,
13 years, 7 months
[libvirt] [PATCH 6/9] add DHCP snooping support to nwfilter
by David L Stevens
This patch adds the capability of adding individual rules to existing chains.
Signed-off-by: David L Stevens <dlstevens(a)us.ibm.com>
diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
index 25f7b60..4b6759a 100644
--- a/src/conf/nwfilter_conf.h
+++ b/src/conf/nwfilter_conf.h
@@ -532,6 +532,11 @@ typedef int (*virNWFilterRuleTeardownNewRules)(virConnectPtr conn,
typedef int (*virNWFilterRuleTeardownOldRules)(virConnectPtr conn,
const char *ifname);
+typedef int (*virNWFilterRuleAddRules)(virConnectPtr conn,
+ const char *ifname,
+ int nruleInstances,
+ void **_inst);
+
typedef int (*virNWFilterRuleRemoveRules)(virConnectPtr conn,
const char *ifname,
int nruleInstances,
@@ -572,6 +577,7 @@ struct _virNWFilterTechDriver {
virNWFilterRuleApplyNewRules applyNewRules;
virNWFilterRuleTeardownNewRules tearNewRules;
virNWFilterRuleTeardownOldRules tearOldRules;
+ virNWFilterRuleAddRules addRules;
virNWFilterRuleRemoveRules removeRules;
virNWFilterRuleAllTeardown allTeardown;
virNWFilterRuleFreeInstanceData freeRuleInstance;
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c
index f74f63b..0cb4d00 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -3686,6 +3686,78 @@ err_exit:
return rc;
}
+/**
+ * ebiptablesAddRules:
+ * @conn : pointer to virConnect object
+ * @ifname : the name of the interface to which the rules apply
+ * @nRuleInstance : the number of given rules
+ * @_inst : array of rule instantiation data
+ *
+ * Add all rules one after the other
+ *
+ * Return 0 on success, 1 if execution of one or more cleanup
+ * commands failed.
+ */
+static int
+ebiptablesAddRules(virConnectPtr conn,
+ const char *ifname,
+ int nruleInstances,
+ void **_inst)
+{
+ int i;
+ int cli_status;
+ ebiptablesRuleInstPtr *inst = (ebiptablesRuleInstPtr *)_inst;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ bool haveIptables = false;
+ bool haveIp6tables = false;
+
+ for (i = 0; i < nruleInstances; i++) {
+ sa_assert (inst);
+ switch (inst[i]->ruleType) {
+ case RT_EBTABLES:
+ ebiptablesInstCommand(&buf,
+ inst[i]->commandTemplate,
+ 'A', -1, 1);
+ break;
+ case RT_IPTABLES:
+ if (inst[i]->ruleType == RT_IPTABLES)
+ iptablesInstCommand(&buf,
+ inst[i]->commandTemplate,
+ 'A', -1, 1);
+ haveIptables = true;
+ break;
+ case RT_IP6TABLES:
+ if (inst[i]->ruleType == RT_IP6TABLES)
+ iptablesInstCommand(&buf,
+ inst[i]->commandTemplate,
+ 'A', -1, 1);
+ haveIp6tables = true;
+ break;
+ }
+ }
+
+ if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0)
+ goto err_exit;
+
+ if (haveIptables)
+ iptablesCheckBridgeNFCallEnabled(false);
+
+ if (haveIp6tables)
+ iptablesCheckBridgeNFCallEnabled(true);
+
+ return 0;
+
+err_exit:
+ (void) ebiptablesRemoveRules(conn, ifname, nruleInstances, _inst);
+
+ virNWFilterReportError(VIR_ERR_BUILD_FIREWALL,
+ _("Some rules could not be created for "
+ "interface %s."),
+ ifname);
+
+ return 1;
+}
+
/**
* ebiptablesAllTeardown:
@@ -3742,6 +3814,7 @@ virNWFilterTechDriver ebiptables_driver = {
.tearNewRules = ebiptablesTearNewRules,
.tearOldRules = ebiptablesTearOldRules,
.allTeardown = ebiptablesAllTeardown,
+ .addRules = ebiptablesAddRules,
.removeRules = ebiptablesRemoveRules,
.freeRuleInstance = ebiptablesFreeRuleInstance,
.displayRuleInstance = ebiptablesDisplayRuleInstance,
13 years, 7 months
[libvirt] [PATCH 5/9] add DHCP snooping support to nwfilter
by David L Stevens
This patch adds the internal capability to add rules to existing chains
instead of using temporary chains and to generate placeholders for chains
that are referenced without generating a rule for them immediately. Finally,
it includes variable matching for filter instantiation (i.e., instantiate only
when a given variable is present in a filter, or only when it is not).
Signed-off-by: David L Stevens <dlstevens(a)us.ibm.com>
diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
index 72bdade..25f7b60 100644
--- a/src/conf/nwfilter_conf.h
+++ b/src/conf/nwfilter_conf.h
@@ -517,7 +517,9 @@ typedef int (*virNWFilterRuleCreateInstance)(virConnectPtr conn,
virNWFilterRuleDefPtr rule,
const char *ifname,
virNWFilterHashTablePtr vars,
- virNWFilterRuleInstPtr res);
+ virNWFilterRuleInstPtr res,
+ bool usetemp,
+ bool dummy);
typedef int (*virNWFilterRuleApplyNewRules)(virConnectPtr conn,
const char *ifname,
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c
index f16a143..f74f63b 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -1134,6 +1134,7 @@ iptablesEnforceDirection(int directionIn,
* @isIPv6 : Whether this is an IPv6 rule
* @maySkipICMP : whether this rule may under certain circumstances skip
* the ICMP rule from being created
+ * @dummy : generate rule placeholder without installing
*
* Convert a single rule into its representation for later instantiation
*
@@ -1152,7 +1153,8 @@ _iptablesCreateRuleInstance(int directionIn,
const char *match, bool defMatch,
const char *accept_target,
bool isIPv6,
- bool maySkipICMP)
+ bool maySkipICMP,
+ bool dummy)
{
char chain[MAX_CHAINNAME_LENGTH];
char number[20];
@@ -1179,6 +1181,13 @@ _iptablesCreateRuleInstance(int directionIn,
PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname);
+ if (dummy) {
+ virBufferVSprintf(&buf, CMD_DEF_PRE "%s -- %s -%%c %s %%s",
+ "echo", iptables_cmd, chain);
+ bufUsed = virBufferUse(&buf);
+ goto prskip;
+ }
+
switch (rule->prtclType) {
case VIR_NWFILTER_RULE_PROTOCOL_TCP:
case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6:
@@ -1510,6 +1519,8 @@ _iptablesCreateRuleInstance(int directionIn,
return -1;
}
+prskip:
+
if ((srcMacSkipped && bufUsed == virBufferUse(&buf)) ||
skipRule) {
virBufferFreeAndReset(&buf);
@@ -1625,7 +1636,9 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
const char *ifname,
virNWFilterHashTablePtr vars,
virNWFilterRuleInstPtr res,
- bool isIPv6)
+ bool isIPv6,
+ bool usetemp,
+ bool dummy)
{
int rc;
int directionIn = 0, directionOut = 0;
@@ -1658,7 +1671,7 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
return 1;
}
- chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
if (create) {
rc = _iptablesCreateRuleInstance(directionIn,
chainPrefix,
@@ -1670,7 +1683,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
matchState, false,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
VIR_FREE(matchState);
if (rc)
@@ -1690,7 +1704,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
return 1;
}
- chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_OUT_TEMP :
+ CHAINPREFIX_HOST_OUT;
if (create) {
rc = _iptablesCreateRuleInstance(!directionIn,
chainPrefix,
@@ -1702,7 +1717,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
matchState, false,
"ACCEPT",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
VIR_FREE(matchState);
@@ -1726,7 +1742,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
if (create) {
chainPrefix[0] = 'H';
- chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP :
+ CHAINPREFIX_HOST_IN;
rc = _iptablesCreateRuleInstance(directionIn,
chainPrefix,
nwfilter,
@@ -1737,7 +1754,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
matchState, false,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
VIR_FREE(matchState);
}
@@ -1751,7 +1769,9 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
const char *ifname,
virNWFilterHashTablePtr vars,
virNWFilterRuleInstPtr res,
- bool isIPv6)
+ bool isIPv6,
+ bool usetemp,
+ bool dummy)
{
int rc;
int directionIn = 0;
@@ -1767,7 +1787,9 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
ifname,
vars,
res,
- isIPv6);
+ isIPv6,
+ usetemp,
+ dummy);
}
if ((rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN) ||
@@ -1790,7 +1812,7 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
else
matchState = NULL;
- chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
rc = _iptablesCreateRuleInstance(directionIn,
chainPrefix,
nwfilter,
@@ -1801,7 +1823,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState, true,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
if (rc)
return rc;
@@ -1812,7 +1835,7 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
else
matchState = NULL;
- chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_OUT_TEMP : CHAINPREFIX_HOST_OUT;
rc = _iptablesCreateRuleInstance(!directionIn,
chainPrefix,
nwfilter,
@@ -1823,7 +1846,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState, true,
"ACCEPT",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
if (rc)
return rc;
@@ -1834,7 +1858,7 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState = NULL;
chainPrefix[0] = 'H';
- chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
rc = _iptablesCreateRuleInstance(directionIn,
chainPrefix,
nwfilter,
@@ -1845,7 +1869,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState, true,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
return rc;
}
@@ -1876,7 +1901,8 @@ ebtablesCreateRuleInstance(char chainPrefix,
const char *ifname,
virNWFilterHashTablePtr vars,
virNWFilterRuleInstPtr res,
- bool reverse)
+ bool reverse,
+ bool dummy)
{
char macaddr[VIR_MAC_STRING_BUFLEN],
ipaddr[INET_ADDRSTRLEN],
@@ -1899,6 +1925,11 @@ ebtablesCreateRuleInstance(char chainPrefix,
PRINT_CHAIN(chain, chainPrefix, ifname,
virNWFilterChainSuffixTypeToString(nwfilter->chainsuffix));
+ if (dummy) {
+ virBufferVSprintf(&buf, CMD_DEF_PRE "%s -- -t %s -%%c %s %%s",
+ "echo", EBTABLES_DEFAULT_TABLE, chain);
+ goto prskip;
+ }
switch (rule->prtclType) {
case VIR_NWFILTER_RULE_PROTOCOL_MAC:
@@ -2300,6 +2331,8 @@ ebtablesCreateRuleInstance(char chainPrefix,
return -1;
}
+prskip:
+
switch (rule->action) {
case VIR_NWFILTER_RULE_ACTION_REJECT:
/* REJECT not supported */
@@ -2357,11 +2390,15 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
virNWFilterRuleDefPtr rule,
const char *ifname,
virNWFilterHashTablePtr vars,
- virNWFilterRuleInstPtr res)
+ virNWFilterRuleInstPtr res,
+ bool usetemp,
+ bool dummy)
{
int rc = 0;
bool isIPv6;
+ char chainPrefix;
+ chainPrefix = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
switch (rule->prtclType) {
case VIR_NWFILTER_RULE_PROTOCOL_IP:
case VIR_NWFILTER_RULE_PROTOCOL_MAC:
@@ -2372,26 +2409,30 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_OUT ||
rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) {
- rc = ebtablesCreateRuleInstance(CHAINPREFIX_HOST_IN_TEMP,
+ rc = ebtablesCreateRuleInstance(chainPrefix,
nwfilter,
rule,
ifname,
vars,
res,
- rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT);
+ rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT,
+ dummy);
if (rc)
return rc;
}
+ chainPrefix = usetemp ? CHAINPREFIX_HOST_OUT_TEMP :
+ CHAINPREFIX_HOST_OUT;
if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN ||
rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) {
- rc = ebtablesCreateRuleInstance(CHAINPREFIX_HOST_OUT_TEMP,
+ rc = ebtablesCreateRuleInstance(chainPrefix,
nwfilter,
rule,
ifname,
vars,
res,
- false);
+ false,
+ dummy);
}
break;
@@ -2417,7 +2458,9 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
ifname,
vars,
res,
- isIPv6);
+ isIPv6,
+ usetemp,
+ dummy);
break;
case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6:
@@ -2441,7 +2484,9 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
ifname,
vars,
res,
- isIPv6);
+ isIPv6,
+ usetemp,
+ dummy);
break;
case VIR_NWFILTER_RULE_PROTOCOL_LAST:
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
index f89fb79..0bc3537 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -222,7 +222,9 @@ virNWFilterRuleInstantiate(virConnectPtr conn,
virNWFilterDefPtr filter,
virNWFilterRuleDefPtr rule,
const char *ifname,
- virNWFilterHashTablePtr vars)
+ virNWFilterHashTablePtr vars,
+ bool usetemp,
+ bool dummy)
{
int rc;
int i;
@@ -235,8 +237,8 @@ virNWFilterRuleInstantiate(virConnectPtr conn,
ret->techdriver = techdriver;
- rc = techdriver->createRuleInstance(conn, nettype, filter,
- rule, ifname, vars, ret);
+ rc = techdriver->createRuleInstance(conn, nettype, filter, rule, ifname,
+ vars, ret, usetemp, dummy);
if (rc) {
for (i = 0; i < ret->ndata; i++)
@@ -292,6 +294,8 @@ err_exit:
* @ifname: The name of the interface to apply the rules to
* @vars: A map holding variable names and values used for instantiating
* the filter and its subfilters.
+ * @matchvar: if non-null, variable name to match
+ * @notmatch: if matchvar set, match filters that do not reference matchvar
* @nEntries: number of virNWFilterInst objects collected
* @insts: pointer to array for virNWFilterIns object pointers
* @useNewFilter: instruct whether to use a newDef pointer rather than a
@@ -315,6 +319,8 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
virNWFilterDefPtr filter,
const char *ifname,
virNWFilterHashTablePtr vars,
+ const char *matchvar,
+ bool notmatch,
int *nEntries,
virNWFilterRuleInstPtr **insts,
enum instCase useNewFilter, bool *foundNewFilter,
@@ -325,18 +331,34 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
int i;
virNWFilterRuleInstPtr inst;
virNWFilterDefPtr next_filter;
+ bool usetemp, dummy;
for (i = 0; i < filter->nentries; i++) {
virNWFilterRuleDefPtr rule = filter->filterEntries[i]->rule;
virNWFilterIncludeDefPtr inc = filter->filterEntries[i]->include;
if (rule) {
+ usetemp = 1;
+ dummy = 0;
+ if (matchvar) {
+ int j;
+
+ for (j = 0; j < rule->nvars; ++j)
+ if (strcmp(rule->vars[j], matchvar) == 0)
+ break;
+ /* use temp chains only on base rule install */
+ usetemp = notmatch;
+ /* skip if not found; notmatch reverses the sense */
+ dummy = (j == rule->nvars) ^ notmatch;
+ }
inst = virNWFilterRuleInstantiate(conn,
techdriver,
nettype,
filter,
rule,
ifname,
- vars);
+ vars,
+ usetemp,
+ dummy);
if (!inst) {
rc = 1;
break;
@@ -394,6 +416,7 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
next_filter,
ifname,
tmpvars,
+ matchvar, notmatch,
nEntries, insts,
useNewFilter,
foundNewFilter,
@@ -623,6 +646,7 @@ virNWFilterInstantiate(virConnectPtr conn,
filter,
ifname,
vars,
+ 0, 0,
&nEntries, &insts,
useNewFilter, foundNewFilter,
driver);
13 years, 7 months
[libvirt] [PATCH 5/9] add DHCP snooping support to nwfilter
by David L Stevens
This patch adds the internal capability to add rules to existing chains
instead of using temporary chains and to generate placeholders for chains
that are referenced without generating a rule for them immediately. Finally,
it includes variable matching for filter instantiation (i.e., instantiate only
when a given variable is present in a filter, or only when it is not).
Signed-off-by: David L Stevens <dlstevens(a)us.ibm.com>
diff --git a/src/conf/nwfilter_conf.h b/src/conf/nwfilter_conf.h
index 72bdade..25f7b60 100644
--- a/src/conf/nwfilter_conf.h
+++ b/src/conf/nwfilter_conf.h
@@ -517,7 +517,9 @@ typedef int (*virNWFilterRuleCreateInstance)(virConnectPtr conn,
virNWFilterRuleDefPtr rule,
const char *ifname,
virNWFilterHashTablePtr vars,
- virNWFilterRuleInstPtr res);
+ virNWFilterRuleInstPtr res,
+ bool usetemp,
+ bool dummy);
typedef int (*virNWFilterRuleApplyNewRules)(virConnectPtr conn,
const char *ifname,
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c
index f16a143..f74f63b 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -1134,6 +1134,7 @@ iptablesEnforceDirection(int directionIn,
* @isIPv6 : Whether this is an IPv6 rule
* @maySkipICMP : whether this rule may under certain circumstances skip
* the ICMP rule from being created
+ * @dummy : generate rule placeholder without installing
*
* Convert a single rule into its representation for later instantiation
*
@@ -1152,7 +1153,8 @@ _iptablesCreateRuleInstance(int directionIn,
const char *match, bool defMatch,
const char *accept_target,
bool isIPv6,
- bool maySkipICMP)
+ bool maySkipICMP,
+ bool dummy)
{
char chain[MAX_CHAINNAME_LENGTH];
char number[20];
@@ -1179,6 +1181,13 @@ _iptablesCreateRuleInstance(int directionIn,
PRINT_IPT_ROOT_CHAIN(chain, chainPrefix, ifname);
+ if (dummy) {
+ virBufferVSprintf(&buf, CMD_DEF_PRE "%s -- %s -%%c %s %%s",
+ "echo", iptables_cmd, chain);
+ bufUsed = virBufferUse(&buf);
+ goto prskip;
+ }
+
switch (rule->prtclType) {
case VIR_NWFILTER_RULE_PROTOCOL_TCP:
case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6:
@@ -1510,6 +1519,8 @@ _iptablesCreateRuleInstance(int directionIn,
return -1;
}
+prskip:
+
if ((srcMacSkipped && bufUsed == virBufferUse(&buf)) ||
skipRule) {
virBufferFreeAndReset(&buf);
@@ -1625,7 +1636,9 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
const char *ifname,
virNWFilterHashTablePtr vars,
virNWFilterRuleInstPtr res,
- bool isIPv6)
+ bool isIPv6,
+ bool usetemp,
+ bool dummy)
{
int rc;
int directionIn = 0, directionOut = 0;
@@ -1658,7 +1671,7 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
return 1;
}
- chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
if (create) {
rc = _iptablesCreateRuleInstance(directionIn,
chainPrefix,
@@ -1670,7 +1683,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
matchState, false,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
VIR_FREE(matchState);
if (rc)
@@ -1690,7 +1704,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
return 1;
}
- chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_OUT_TEMP :
+ CHAINPREFIX_HOST_OUT;
if (create) {
rc = _iptablesCreateRuleInstance(!directionIn,
chainPrefix,
@@ -1702,7 +1717,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
matchState, false,
"ACCEPT",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
VIR_FREE(matchState);
@@ -1726,7 +1742,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
if (create) {
chainPrefix[0] = 'H';
- chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP :
+ CHAINPREFIX_HOST_IN;
rc = _iptablesCreateRuleInstance(directionIn,
chainPrefix,
nwfilter,
@@ -1737,7 +1754,8 @@ iptablesCreateRuleInstanceStateCtrl(virNWFilterDefPtr nwfilter,
matchState, false,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
VIR_FREE(matchState);
}
@@ -1751,7 +1769,9 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
const char *ifname,
virNWFilterHashTablePtr vars,
virNWFilterRuleInstPtr res,
- bool isIPv6)
+ bool isIPv6,
+ bool usetemp,
+ bool dummy)
{
int rc;
int directionIn = 0;
@@ -1767,7 +1787,9 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
ifname,
vars,
res,
- isIPv6);
+ isIPv6,
+ usetemp,
+ dummy);
}
if ((rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN) ||
@@ -1790,7 +1812,7 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
else
matchState = NULL;
- chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
rc = _iptablesCreateRuleInstance(directionIn,
chainPrefix,
nwfilter,
@@ -1801,7 +1823,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState, true,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
if (rc)
return rc;
@@ -1812,7 +1835,7 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
else
matchState = NULL;
- chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_OUT_TEMP : CHAINPREFIX_HOST_OUT;
rc = _iptablesCreateRuleInstance(!directionIn,
chainPrefix,
nwfilter,
@@ -1823,7 +1846,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState, true,
"ACCEPT",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
if (rc)
return rc;
@@ -1834,7 +1858,7 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState = NULL;
chainPrefix[0] = 'H';
- chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
+ chainPrefix[1] = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
rc = _iptablesCreateRuleInstance(directionIn,
chainPrefix,
nwfilter,
@@ -1845,7 +1869,8 @@ iptablesCreateRuleInstance(virNWFilterDefPtr nwfilter,
matchState, true,
"RETURN",
isIPv6,
- maySkipICMP);
+ maySkipICMP,
+ dummy);
return rc;
}
@@ -1876,7 +1901,8 @@ ebtablesCreateRuleInstance(char chainPrefix,
const char *ifname,
virNWFilterHashTablePtr vars,
virNWFilterRuleInstPtr res,
- bool reverse)
+ bool reverse,
+ bool dummy)
{
char macaddr[VIR_MAC_STRING_BUFLEN],
ipaddr[INET_ADDRSTRLEN],
@@ -1899,6 +1925,11 @@ ebtablesCreateRuleInstance(char chainPrefix,
PRINT_CHAIN(chain, chainPrefix, ifname,
virNWFilterChainSuffixTypeToString(nwfilter->chainsuffix));
+ if (dummy) {
+ virBufferVSprintf(&buf, CMD_DEF_PRE "%s -- -t %s -%%c %s %%s",
+ "echo", EBTABLES_DEFAULT_TABLE, chain);
+ goto prskip;
+ }
switch (rule->prtclType) {
case VIR_NWFILTER_RULE_PROTOCOL_MAC:
@@ -2300,6 +2331,8 @@ ebtablesCreateRuleInstance(char chainPrefix,
return -1;
}
+prskip:
+
switch (rule->action) {
case VIR_NWFILTER_RULE_ACTION_REJECT:
/* REJECT not supported */
@@ -2357,11 +2390,15 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
virNWFilterRuleDefPtr rule,
const char *ifname,
virNWFilterHashTablePtr vars,
- virNWFilterRuleInstPtr res)
+ virNWFilterRuleInstPtr res,
+ bool usetemp,
+ bool dummy)
{
int rc = 0;
bool isIPv6;
+ char chainPrefix;
+ chainPrefix = usetemp ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_IN;
switch (rule->prtclType) {
case VIR_NWFILTER_RULE_PROTOCOL_IP:
case VIR_NWFILTER_RULE_PROTOCOL_MAC:
@@ -2372,26 +2409,30 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_OUT ||
rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) {
- rc = ebtablesCreateRuleInstance(CHAINPREFIX_HOST_IN_TEMP,
+ rc = ebtablesCreateRuleInstance(chainPrefix,
nwfilter,
rule,
ifname,
vars,
res,
- rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT);
+ rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT,
+ dummy);
if (rc)
return rc;
}
+ chainPrefix = usetemp ? CHAINPREFIX_HOST_OUT_TEMP :
+ CHAINPREFIX_HOST_OUT;
if (rule->tt == VIR_NWFILTER_RULE_DIRECTION_IN ||
rule->tt == VIR_NWFILTER_RULE_DIRECTION_INOUT) {
- rc = ebtablesCreateRuleInstance(CHAINPREFIX_HOST_OUT_TEMP,
+ rc = ebtablesCreateRuleInstance(chainPrefix,
nwfilter,
rule,
ifname,
vars,
res,
- false);
+ false,
+ dummy);
}
break;
@@ -2417,7 +2458,9 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
ifname,
vars,
res,
- isIPv6);
+ isIPv6,
+ usetemp,
+ dummy);
break;
case VIR_NWFILTER_RULE_PROTOCOL_TCPoIPV6:
@@ -2441,7 +2484,9 @@ ebiptablesCreateRuleInstance(virConnectPtr conn ATTRIBUTE_UNUSED,
ifname,
vars,
res,
- isIPv6);
+ isIPv6,
+ usetemp,
+ dummy);
break;
case VIR_NWFILTER_RULE_PROTOCOL_LAST:
diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
index f89fb79..0bc3537 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -222,7 +222,9 @@ virNWFilterRuleInstantiate(virConnectPtr conn,
virNWFilterDefPtr filter,
virNWFilterRuleDefPtr rule,
const char *ifname,
- virNWFilterHashTablePtr vars)
+ virNWFilterHashTablePtr vars,
+ bool usetemp,
+ bool dummy)
{
int rc;
int i;
@@ -235,8 +237,8 @@ virNWFilterRuleInstantiate(virConnectPtr conn,
ret->techdriver = techdriver;
- rc = techdriver->createRuleInstance(conn, nettype, filter,
- rule, ifname, vars, ret);
+ rc = techdriver->createRuleInstance(conn, nettype, filter, rule, ifname,
+ vars, ret, usetemp, dummy);
if (rc) {
for (i = 0; i < ret->ndata; i++)
@@ -292,6 +294,8 @@ err_exit:
* @ifname: The name of the interface to apply the rules to
* @vars: A map holding variable names and values used for instantiating
* the filter and its subfilters.
+ * @matchvar: if non-null, variable name to match
+ * @notmatch: if matchvar set, match filters that do not reference matchvar
* @nEntries: number of virNWFilterInst objects collected
* @insts: pointer to array for virNWFilterIns object pointers
* @useNewFilter: instruct whether to use a newDef pointer rather than a
@@ -315,6 +319,8 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
virNWFilterDefPtr filter,
const char *ifname,
virNWFilterHashTablePtr vars,
+ const char *matchvar,
+ bool notmatch,
int *nEntries,
virNWFilterRuleInstPtr **insts,
enum instCase useNewFilter, bool *foundNewFilter,
@@ -325,18 +331,34 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
int i;
virNWFilterRuleInstPtr inst;
virNWFilterDefPtr next_filter;
+ bool usetemp, dummy;
for (i = 0; i < filter->nentries; i++) {
virNWFilterRuleDefPtr rule = filter->filterEntries[i]->rule;
virNWFilterIncludeDefPtr inc = filter->filterEntries[i]->include;
if (rule) {
+ usetemp = 1;
+ dummy = 0;
+ if (matchvar) {
+ int j;
+
+ for (j = 0; j < rule->nvars; ++j)
+ if (strcmp(rule->vars[j], matchvar) == 0)
+ break;
+ /* use temp chains only on base rule install */
+ usetemp = notmatch;
+ /* skip if not found; notmatch reverses the sense */
+ dummy = (j == rule->nvars) ^ notmatch;
+ }
inst = virNWFilterRuleInstantiate(conn,
techdriver,
nettype,
filter,
rule,
ifname,
- vars);
+ vars,
+ usetemp,
+ dummy);
if (!inst) {
rc = 1;
break;
@@ -394,6 +416,7 @@ _virNWFilterInstantiateRec(virConnectPtr conn,
next_filter,
ifname,
tmpvars,
+ matchvar, notmatch,
nEntries, insts,
useNewFilter,
foundNewFilter,
@@ -623,6 +646,7 @@ virNWFilterInstantiate(virConnectPtr conn,
filter,
ifname,
vars,
+ 0, 0,
&nEntries, &insts,
useNewFilter, foundNewFilter,
driver);
13 years, 7 months
[libvirt] [PATCH 4/9] add DHCP snooping support to nwfilter
by David L Stevens
This patch simplifies the table rules by setting the protocol chains policy to
be "DROP" and removes the explicit "-j DROP" entries that the protocol rules
had previously. It also makes "no-other-rarp-traffic.xml" obsolete.
Signed-off-by: David L Stevens <dlstevens(a)us.ibm.com>
diff --git a/examples/xml/nwfilter/Makefile.am b/examples/xml/nwfilter/Makefile.am
index 8ef9a71..60301c9 100644
--- a/examples/xml/nwfilter/Makefile.am
+++ b/examples/xml/nwfilter/Makefile.am
@@ -14,7 +14,6 @@ FILTERS = \
no-mac-broadcast.xml \
no-mac-spoofing.xml \
no-other-l2-traffic.xml \
- no-other-rarp-traffic.xml \
qemu-announce-self.xml \
qemu-announce-self-rarp.xml
diff --git a/examples/xml/nwfilter/no-arpip-spoofing.xml b/examples/xml/nwfilter/no-arpip-spoofing.xml
index ee42d40..7ef6f0f 100644
--- a/examples/xml/nwfilter/no-arpip-spoofing.xml
+++ b/examples/xml/nwfilter/no-arpip-spoofing.xml
@@ -7,6 +7,4 @@
<rule action='return' direction='out' priority='410' >
<arp match='yes' arpsrcipaddr='0.0.0.0' />
</rule>
- <!-- drop everything else -->
- <rule action='drop' direction='out' priority='1000' />
</filter>
diff --git a/examples/xml/nwfilter/no-arpmac-spoofing.xml b/examples/xml/nwfilter/no-arpmac-spoofing.xml
index 90499d3..3834047 100644
--- a/examples/xml/nwfilter/no-arpmac-spoofing.xml
+++ b/examples/xml/nwfilter/no-arpmac-spoofing.xml
@@ -2,6 +2,4 @@
<rule action='return' direction='out' priority='350' >
<arp match='yes' arpsrcmacaddr='$MAC'/>
</rule>
- <!-- drop everything else -->
- <rule action='drop' direction='out' priority='1000' />
</filter>
diff --git a/examples/xml/nwfilter/no-ip-spoofing.xml b/examples/xml/nwfilter/no-ip-spoofing.xml
index 84e8a5e..2fccd12 100644
--- a/examples/xml/nwfilter/no-ip-spoofing.xml
+++ b/examples/xml/nwfilter/no-ip-spoofing.xml
@@ -4,6 +4,4 @@
<rule action='return' direction='out'>
<ip match='yes' srcipaddr='$IP' />
</rule>
- <!-- drop any that don't match the source IP list -->
- <rule action='drop' direction='out' />
</filter>
diff --git a/examples/xml/nwfilter/no-mac-spoofing.xml b/examples/xml/nwfilter/no-mac-spoofing.xml
index aee56c7..e2e8c03 100644
--- a/examples/xml/nwfilter/no-mac-spoofing.xml
+++ b/examples/xml/nwfilter/no-mac-spoofing.xml
@@ -4,6 +4,4 @@
<rule action='return' direction='out' priority='350' >
<mac match='yes' srcmacaddr='$MAC'/>
</rule>
- <!-- drop everything else -->
- <rule action='drop' direction='out' priority='1000' />
</filter>
diff --git a/examples/xml/nwfilter/no-other-rarp-traffic.xml b/examples/xml/nwfilter/no-other-rarp-traffic.xml
deleted file mode 100644
index 7729996..0000000
--- a/examples/xml/nwfilter/no-other-rarp-traffic.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<filter name='no-other-rarp-traffic' chain='rarp'>
- <rule action='drop' direction='inout' priority='1000'/>
-</filter>
diff --git a/examples/xml/nwfilter/qemu-announce-self.xml b/examples/xml/nwfilter/qemu-announce-self.xml
index 352db50..12957b5 100644
--- a/examples/xml/nwfilter/qemu-announce-self.xml
+++ b/examples/xml/nwfilter/qemu-announce-self.xml
@@ -8,6 +8,5 @@
<!-- accept if it was changed to rarp -->
<filterref filter='qemu-announce-self-rarp'/>
- <filterref filter='no-other-rarp-traffic'/>
</filter>
diff --git a/src/nwfilter/nwfilter_ebiptables_driver.c b/src/nwfilter/nwfilter_ebiptables_driver.c
index fa6f719..dc0ad2e 100644
--- a/src/nwfilter/nwfilter_ebiptables_driver.c
+++ b/src/nwfilter/nwfilter_ebiptables_driver.c
@@ -2783,7 +2783,7 @@ ebtablesCreateTmpSubChain(virBufferPtr buf,
protostr[0] = '\0';
virBufferVSprintf(buf,
- CMD_DEF("%s -t %s -N %s") CMD_SEPARATOR
+ CMD_DEF("%s -t %s -N %s -P DROP") CMD_SEPARATOR
CMD_EXEC
"%s"
CMD_DEF("%s -t %s -A %s %s -j %s") CMD_SEPARATOR
@@ -3006,14 +3006,6 @@ ebtablesApplyBasicRules(const char *ifname,
ebtablesCreateTmpRootChain(&buf, 1, ifname, 1);
PRINT_ROOT_CHAIN(chain, chainPrefix, ifname);
- virBufferVSprintf(&buf,
- CMD_DEF("%s -t %s -A %s -s ! %s -j DROP") CMD_SEPARATOR
- CMD_EXEC
- "%s",
-
- ebtables_cmd_path, EBTABLES_DEFAULT_TABLE,
- chain, macaddr_str,
- CMD_STOPONERR(1));
virBufferVSprintf(&buf,
CMD_DEF("%s -t %s -A %s -p IPv4 -j ACCEPT") CMD_SEPARATOR
13 years, 7 months