[libvirt] [PATCH 1/2] dnsmasq: add option to disable IPv6 default gateway in RA

Maxim Perevedentsev mperevedentsev at virtuozzo.com
Wed Jun 29 14:17:53 UTC 2016


If no gateway is specified in RA the a guest will install
a default route to link-local address of the source of RA
(in this case, virbr*), which may disturb guest's networking
e.g. if the 'expected' default route is through another interface.

This patch adds an attribute 'ipv6noDefRoute=yes|no' to network
definition. If this attribute is set, we add

   ra-param=*,0,0
// <interface>,<RA interval>,<default gateway lifetime>
// here we have "any interface","default interval","0 seconds"

to dnsmasq config. This makes the 'default gateway lifetime'
to be 0 seconds, which means that receiver of RA must not
install a default route from this RA.
---
 src/conf/network_conf.c     | 17 +++++++++++++++++
 src/conf/network_conf.h     |  3 +++
 src/network/bridge_driver.c | 22 ++++++++++++++++++++++
 src/util/virdnsmasq.h       |  6 ++++++
 4 files changed, 48 insertions(+)

diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 2d904df..364f3fe 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -2056,6 +2056,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
     xmlNodePtr forwardNode = NULL;
     char *ipv6nogwStr = NULL;
     char *trustGuestRxFilters = NULL;
+    char *ipv6noDefRouteStr = NULL;
     xmlNodePtr save = ctxt->node;
     xmlNodePtr bandwidthNode = NULL;
     xmlNodePtr vlanNode;
@@ -2124,6 +2125,19 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
         VIR_FREE(trustGuestRxFilters);
     }
 
+    ipv6noDefRouteStr = virXPathString("string(./@ipv6noDefRoute)", ctxt);
+    if (ipv6noDefRouteStr) {
+        if (STREQ(ipv6noDefRouteStr, "yes")) {
+            def->ipv6noDefRoute = true;
+        } else if (STRNEQ(ipv6noDefRouteStr, "no")) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Invalid ipv6noDefRoute setting '%s' in network '%s'"),
+                           ipv6noDefRouteStr, def->name);
+            goto error;
+        }
+        VIR_FREE(ipv6noDefRouteStr);
+    }
+
     /* Parse network domain information */
     def->domain = virXPathString("string(./domain[1]/@name)", ctxt);
     tmp = virXPathString("string(./domain[1]/@localOnly)", ctxt);
@@ -2401,6 +2415,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
     VIR_FREE(ipNodes);
     VIR_FREE(portGroupNodes);
     VIR_FREE(ipv6nogwStr);
+    VIR_FREE(ipv6noDefRouteStr);
     VIR_FREE(trustGuestRxFilters);
     ctxt->node = save;
     return NULL;
@@ -2728,6 +2743,8 @@ virNetworkDefFormatBuf(virBufferPtr buf,
     if (def->trustGuestRxFilters)
         virBufferAsprintf(buf, " trustGuestRxFilters='%s'",
                           virTristateBoolTypeToString(def->trustGuestRxFilters));
+    if (def->ipv6noDefRoute)
+        virBufferAddLit(buf, " ipv6noDefRoute='yes'");
     virBufferAddLit(buf, ">\n");
     virBufferAdjustIndent(buf, 2);
     virBufferEscapeString(buf, "<name>%s</name>\n", def->name);
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index e7ce674..e2d926f 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -253,6 +253,9 @@ struct _virNetworkDef {
     virNetDevBandwidthPtr bandwidth;
     virNetDevVlan vlan;
     int trustGuestRxFilters; /* enum virTristateBool */
+
+    /* forbid dnsmasq to announce our link-local address as default gateway */
+    bool ipv6noDefRoute;
 };
 
 typedef struct _virNetworkObj virNetworkObj;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 0221a38..a5998bb 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1051,6 +1051,28 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
     if (network->def->forward.type == VIR_NETWORK_FORWARD_NONE) {
         virBufferAddLit(&configbuf, "dhcp-option=3\n"
                         "no-resolv\n");
+        if (network->def->ipv6noDefRoute) {
+            /* Set RA interval to 0
+             * (= default, we cannot set 3rd parameter without setting 2nd)
+             * and default route lifetime to 0 seconds i.e.
+             * do not announce our link-local address as default gateway
+             */
+            if (!DNSMASQ_RA_PARAM_SUPPORT(caps)) {
+                unsigned long version = dnsmasqCapsGetVersion(caps);
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                               _("The version of dnsmasq on this host "
+                                 "(%d.%d) doesn't support 'ra-param' option "
+                                 "which is needed to disable "
+                                 "IPv6 default route. "
+                                 "Version %d.%d or later is required."),
+                               (int)version / 1000000,
+                               (int)(version % 1000000) / 1000,
+                               DNSMASQ_RA_PARAM_MAJOR_REQD,
+                               DNSMASQ_RA_PARAM_MINOR_REQD);
+                goto cleanup;
+            }
+            virBufferAddLit(&configbuf, "ra-param=*,0,0\n");
+        }
     }
 
     for (i = 0; i < dns->ntxts; i++) {
diff --git a/src/util/virdnsmasq.h b/src/util/virdnsmasq.h
index ed560da..95f4488 100644
--- a/src/util/virdnsmasq.h
+++ b/src/util/virdnsmasq.h
@@ -109,6 +109,8 @@ unsigned long dnsmasqCapsGetVersion(dnsmasqCapsPtr caps);
 # define DNSMASQ_DHCPv6_MINOR_REQD 64
 # define DNSMASQ_RA_MAJOR_REQD 2
 # define DNSMASQ_RA_MINOR_REQD 64
+# define DNSMASQ_RA_PARAM_MAJOR_REQD 2
+# define DNSMASQ_RA_PARAM_MINOR_REQD 67
 
 # define DNSMASQ_DHCPv6_SUPPORT(CAPS)        \
     (dnsmasqCapsGetVersion(CAPS) >=          \
@@ -118,4 +120,8 @@ unsigned long dnsmasqCapsGetVersion(dnsmasqCapsPtr caps);
     (dnsmasqCapsGetVersion(CAPS) >=          \
      (DNSMASQ_RA_MAJOR_REQD * 1000000) +     \
      (DNSMASQ_RA_MINOR_REQD * 1000))
+# define DNSMASQ_RA_PARAM_SUPPORT(CAPS)        \
+    (dnsmasqCapsGetVersion(CAPS) >=            \
+     (DNSMASQ_RA_PARAM_MAJOR_REQD * 1000000) + \
+     (DNSMASQ_RA_PARAM_MINOR_REQD * 1000))
 #endif /* __DNSMASQ_H__ */
-- 
1.8.3.1




More information about the libvir-list mailing list