
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,