With support for multiple IP addresses per interface in place, this patch
now adds support for multiple IP addresses per interface to the DHCP
snooping code.
---
This patch applies to David Stevens's DHCP snooping patch v8 plus the
patch I applied on top of v8.
Testing:
Since the infrastructure I tested this with does not provide multiple IP
addresses per MAC address (anymore), I either had to plug the VM's interface
from the virtual bride connected directly to the infrastructure to virbr0
to get a 2nd IP address from dnsmasq (kill and run dhclient inside the VM)
or changed the lease file (/var/run/libvirt/network/nwfilter.leases) and
restart libvirtd to have a 2nd IP address on an existing interface.
Note that dnsmasq can take a lease timeout parameter as part of the
--dhcp-range
command line parameter, so that timeouts can be tested that way
(--dhcp-range 192.168.122.2,192.168.122.254,120). So, terminating and
restarting
dnsmasq with that parameter is another choice to watch an IP address
disappear
after 120 seconds.
Regards,
Stefan
---
src/nwfilter/nwfilter_dhcpsnoop.c | 54
+++++++++++++++++++++++---------------
1 file changed, 34 insertions(+), 20 deletions(-)
Index: libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_dhcpsnoop.c
+++ libvirt-acl/src/nwfilter/nwfilter_dhcpsnoop.c
@@ -43,6 +43,7 @@
#include "conf/domain_conf.h"
#include "nwfilter_gentech_driver.h"
#include "nwfilter_dhcpsnoop.h"
+#include "nwfilter_ipaddrmap.h"
#include "virnetdev.h"
#include "virfile.h"
#include "configmake.h"
@@ -222,7 +223,7 @@ virNWFilterSnoopInstallRule(struct virNW
{
char ipbuf[INET_ADDRSTRLEN];
int rc;
- virNWFilterVarValuePtr ipVar;
+ char *ipaddr;
if (!inet_ntop(AF_INET, &ipl->IPAddress, ipbuf, sizeof(ipbuf))) {
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
@@ -230,17 +231,19 @@ virNWFilterSnoopInstallRule(struct virNW
" (0x%08X)"), ipl->IPAddress);
return -1;
}
- ipVar = virNWFilterVarValueCreateSimpleCopyValue(ipbuf);
- if (!ipVar) {
+
+ ipaddr = strdup(ipbuf);
+ if (ipaddr == NULL) {
virReportOOMError();
return -1;
}
- if (virNWFilterHashTablePut(ipl->SnoopReq->vars, "IP", ipVar, 1)) {
- virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
- _("Could not add variable \"IP\" to
hashmap"));
- virNWFilterVarValueFree(ipVar);
+
+ if (virNWFilterIPAddrMapAddIPAddrForIfname(ipl->SnoopReq->ifname,
+ ipaddr) < 0) {
+ VIR_FREE(ipaddr);
return -1;
}
+
rc = virNWFilterInstantiateFilterLate(NULL,
ipl->SnoopReq->ifname,
ipl->SnoopReq->ifindex,
@@ -272,14 +275,6 @@ virNWFilterSnoopLeaseAdd(struct virNWFil
virNWFilterSnoopLeaseFileSave(pl);
return;
}
- /* support for multiple addresses requires the ability to add filters
- * to existing chains, or to instantiate address lists via
- * virNWFilterInstantiateFilterLate(). Until one of those capabilities
- * is added, don't allow a new address when one is already assigned to
- * this interface.
- */
- if (req->start)
- return; /* silently ignore multiple addresses */
if (VIR_ALLOC(pl) < 0) {
virReportOOMError();
@@ -336,20 +331,39 @@ virNWFilterSnoopLeaseDel(struct virNWFil
uint32_t ipaddr, bool update_leasefile)
{
struct virNWFilterSnoopIPLease *ipl;
+ char ipstr[INET_ADDRSTRLEN];
+ int ipAddrLeft;
ipl = virNWFilterSnoopGetByIP(req->start, ipaddr);
if (ipl == NULL)
return;
+ if (!inet_ntop(AF_INET, &ipl->IPAddress, ipstr, sizeof(ipstr))) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("%s: inet_ntop failed (0x%08X)"),
+ __func__, ipl->IPAddress);
+ return;
+ }
+
virNWFilterSnoopTimerDel(ipl);
- if (update_leasefile) {
+ if (update_leasefile)
virNWFilterSnoopLeaseFileSave(ipl);
- /*
- * for multiple address support, this needs to remove those rules
- * referencing "IP" with ipl's ip value.
- */
+ ipAddrLeft =
virNWFilterIPAddrMapDelIPAddrForIfname(ipl->SnoopReq->ifname,
+ ipstr);
+
+ if (ipAddrLeft > 0) {
+ virNWFilterInstantiateFilterLate(NULL,
+ ipl->SnoopReq->ifname,
+ ipl->SnoopReq->ifindex,
+ ipl->SnoopReq->linkdev,
+ ipl->SnoopReq->nettype,
+ ipl->SnoopReq->macaddr,
+ ipl->SnoopReq->filtername,
+ ipl->SnoopReq->vars,
+ ipl->SnoopReq->driver);
+ } else {
if (req->techdriver->applyDHCPOnlyRules(req->ifname, req->macaddr,
NULL, false))
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,