[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 2/2] nwfilter: Add multiple IP address support to DHCP snooping



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,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]