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,

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to