diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 2a6e3358fdf60e5149f88aaf45ef4c8fe4145306..56937d6a4e881a7a460025d6fdfa43dc15a1ef77 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -405,6 +405,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 1a4d6e7f7baaf534c9bc5521bd2c6436cf0adfdb..41fa89a4afb18fe9fb33cd86a0efb8f6ec743fe4 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -69,6 +69,8 @@
#include "virjson.h"
#include "virnetworkportdef.h"
+#include
+
#define VIR_FROM_THIS VIR_FROM_NETWORK
#define MAX_BRIDGE_ID 256
@@ -83,6 +85,8 @@
VIR_LOG_INIT("network.bridge_driver");
+#define DNSMASQ_NAMESPACE_HREF "http://libvirt.org/schemas/network/dnsmasq/1.0"
+
static virNetworkDriverStatePtr network_driver;
@@ -136,10 +140,126 @@ networkDnsmasqCapsRefresh(virNetworkDriverStatePtr driver)
return 0;
}
-static virNetworkXMLOptionPtr
+
+static void
+networkDnsmasqDefNamespaceFree(void *nsdata)
+{
+ networkDnsmasqXmlNsDefPtr def = nsdata;
+ if (!def)
+ return;
+
+ virStringListFreeCount(def->options, def->noptions);
+
+ VIR_FREE(def);
+}
+
+
+static int
+networkDnsmasqDefNamespaceParseOptions(networkDnsmasqXmlNsDefPtr nsdef,
+ xmlXPathContextPtr ctxt)
+{
+ VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
+ ssize_t nnodes;
+ size_t i;
+
+ if ((nnodes = virXPathNodeSet("./dnsmasq:options/dnsmasq:option",
+ ctxt, &nodes)) < 0)
+ return -1;
+
+ if (nnodes == 0)
+ return 0;
+
+ if (VIR_ALLOC_N(nsdef->options, nnodes) < 0)
+ return -1;
+
+ for (i = 0; i < nnodes; i++) {
+ if (!(nsdef->options[nsdef->noptions++] = virXMLPropString(nodes[i], "value"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("No dnsmasq options value specified"));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int
+networkDnsmasqDefNamespaceParse(xmlXPathContextPtr ctxt,
+ void **data)
+{
+ networkDnsmasqXmlNsDefPtr nsdata = NULL;
+ int ret = -1;
+
+ if (xmlXPathRegisterNs(ctxt, BAD_CAST "dnsmasq",
+ BAD_CAST DNSMASQ_NAMESPACE_HREF) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to register xml namespace '%s'"),
+ DNSMASQ_NAMESPACE_HREF);
+ return -1;
+ }
+
+ if (VIR_ALLOC(nsdata) < 0)
+ return -1;
+
+ if (networkDnsmasqDefNamespaceParseOptions(nsdata, ctxt))
+ goto cleanup;
+
+ if (nsdata->noptions > 0)
+ VIR_STEAL_PTR(*data, nsdata);
+
+ ret = 0;
+
+ cleanup:
+ networkDnsmasqDefNamespaceFree(nsdata);
+ return ret;
+}
+
+
+static int
+networkDnsmasqDefNamespaceFormatXML(virBufferPtr buf,
+ void *nsdata)
+{
+ networkDnsmasqXmlNsDefPtr def = nsdata;
+ size_t i;
+
+ if (!def->noptions)
+ return 0;
+
+ virBufferAddLit(buf, "\n");
+ virBufferAdjustIndent(buf, 2);
+
+ for (i = 0; i < def->noptions; i++) {
+ virBufferEscapeString(buf, "\n",
+ def->options[i]);
+ }
+
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "\n");
+
+ return 0;
+}
+
+
+static const char *
+networkDnsmasqDefNamespaceHref(void)
+{
+ return "xmlns:dnsmasq='" DNSMASQ_NAMESPACE_HREF "'";
+}
+
+
+virNetworkXMLNamespace networkDnsmasqXMLNamespace = {
+ .parse = networkDnsmasqDefNamespaceParse,
+ .free = networkDnsmasqDefNamespaceFree,
+ .format = networkDnsmasqDefNamespaceFormatXML,
+ .href = networkDnsmasqDefNamespaceHref,
+};
+
+
+virNetworkXMLOptionPtr
networkDnsmasqCreateXMLConf(void)
{
- return virNetworkXMLOptionNew(NULL);
+ return virNetworkXMLOptionNew(&networkDnsmasqXMLNamespace);
}
@@ -1480,6 +1600,12 @@ networkDnsmasqConfContents(virNetworkObjPtr obj,
}
}
+ if (def->namespaceData) {
+ networkDnsmasqXmlNsDefPtr dnsmasqxmlns = def->namespaceData;
+ for (i = 0; i < dnsmasqxmlns->noptions; i++)
+ virBufferAsprintf(&configbuf, "%s\n", dnsmasqxmlns->options[i]);
+ }
+
if (!(*configstr = virBufferContentAndReset(&configbuf)))
goto cleanup;
diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h
index 7357c1754c9712e97660a9cd26e726e05e592130..b095388a0b2acea4db31a83eee957c48b3892acf 100644
--- a/src/network/bridge_driver.h
+++ b/src/network/bridge_driver.h
@@ -27,6 +27,18 @@
#include "virdnsmasq.h"
#include "virnetworkobj.h"
+extern virNetworkXMLNamespace networkDnsmasqXMLNamespace;
+
+typedef struct _networkDnsmasqXmlNsDef networkDnsmasqXmlNsDef;
+typedef networkDnsmasqXmlNsDef *networkDnsmasqXmlNsDefPtr;
+struct _networkDnsmasqXmlNsDef {
+ size_t noptions;
+ char **options;
+};
+
+virNetworkXMLOptionPtr
+networkDnsmasqCreateXMLConf(void);
+
int
networkRegister(void);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2cb78c131059f21f7c79109ad8ec79ba4863d088..f480e68e7d3a2a93e9e6f57798951cee19b83f45 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -332,13 +332,13 @@ test_programs += virjsontest
endif WITH_YAJL
test_programs += \
- networkxml2xmltest \
networkxml2xmlupdatetest \
virnetworkportxml2xmltest \
$(NULL)
if WITH_NETWORK
test_programs += \
+ networkxml2xmltest \
networkxml2conftest \
networkxml2firewalltest \
$(NULL)
@@ -807,11 +807,6 @@ EXTRA_DIST += \
bhyveargv2xmlmock.c
endif ! WITH_BHYVE
-networkxml2xmltest_SOURCES = \
- networkxml2xmltest.c \
- testutils.c testutils.h
-networkxml2xmltest_LDADD = $(LDADDS)
-
networkxml2xmlupdatetest_SOURCES = \
networkxml2xmlupdatetest.c \
testutils.c testutils.h
@@ -823,6 +818,11 @@ virnetworkportxml2xmltest_SOURCES = \
virnetworkportxml2xmltest_LDADD = $(LDADDS)
if WITH_NETWORK
+networkxml2xmltest_SOURCES = \
+ networkxml2xmltest.c \
+ testutils.c testutils.h
+networkxml2xmltest_LDADD = ../src/libvirt_driver_network_impl.la $(LDADDS)
+
networkxml2conftest_SOURCES = \
networkxml2conftest.c \
testutils.c testutils.h
@@ -834,7 +834,7 @@ networkxml2firewalltest_SOURCES = \
networkxml2firewalltest_LDADD = ../src/libvirt_driver_network_impl.la $(LDADDS)
else ! WITH_NETWORK
-EXTRA_DIST += networkxml2conftest.c
+EXTRA_DIST += networkxml2xmltest.c networkxml2conftest.c
endif ! WITH_NETWORK
if WITH_STORAGE_SHEEPDOG
diff --git a/tests/networkxml2confdata/dnsmasq-options.conf b/tests/networkxml2confdata/dnsmasq-options.conf
new file mode 100644
index 0000000000000000000000000000000000000000..867f355c79c6a144ba67e72d431a5b20521f6915
--- /dev/null
+++ b/tests/networkxml2confdata/dnsmasq-options.conf
@@ -0,0 +1,18 @@
+##WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE
+##OVERWRITTEN AND LOST. Changes to this configuration should be made using:
+## virsh net-edit default
+## or other application using the libvirt API.
+##
+## dnsmasq conf file created by libvirt
+strict-order
+except-interface=lo
+bind-dynamic
+interface=virbr0
+dhcp-range=192.168.122.2,192.168.122.254,255.255.255.0
+dhcp-no-override
+dhcp-authoritative
+dhcp-lease-max=253
+dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile
+addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts
+foo=bar
+cname=*.cloudapps.example.com,master.example.com
diff --git a/tests/networkxml2confdata/dnsmasq-options.xml b/tests/networkxml2confdata/dnsmasq-options.xml
new file mode 100644
index 0000000000000000000000000000000000000000..35a87b8e3e467a46fcd3986fe478d59d62692756
--- /dev/null
+++ b/tests/networkxml2confdata/dnsmasq-options.xml
@@ -0,0 +1,15 @@
+
+ default
+ 81ff0d90-c91e-6742-64da-4a736edb9a9b
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/networkxml2conftest.c b/tests/networkxml2conftest.c
index c44555109945ad504ad8440eaf0e0816da472992..dcb99aad6e7515060e409328a874aadfd0a8e39f 100644
--- a/tests/networkxml2conftest.c
+++ b/tests/networkxml2conftest.c
@@ -25,8 +25,12 @@ testCompareXMLToConfFiles(const char *inxml, const char *outconf, dnsmasqCapsPtr
virCommandPtr cmd = NULL;
char *pidfile = NULL;
dnsmasqContext *dctx = NULL;
+ virNetworkXMLOptionPtr xmlopt = NULL;
- if (!(def = virNetworkDefParseFile(inxml, NULL)))
+ if (!(xmlopt = networkDnsmasqCreateXMLConf()))
+ goto fail;
+
+ if (!(def = virNetworkDefParseFile(inxml, xmlopt)))
goto fail;
if (!(obj = virNetworkObjNew()))
@@ -63,6 +67,7 @@ testCompareXMLToConfFiles(const char *inxml, const char *outconf, dnsmasqCapsPtr
VIR_FREE(actual);
VIR_FREE(pidfile);
virCommandFree(cmd);
+ virObjectUnref(xmlopt);
virNetworkObjEndAPI(&obj);
dnsmasqContextFree(dctx);
return ret;
@@ -141,6 +146,7 @@ mymain(void)
DO_TEST("dhcp6-nat-network", dhcpv6);
DO_TEST("dhcp6host-routed-network", dhcpv6);
DO_TEST("ptr-domains-auto", dhcpv6);
+ DO_TEST("dnsmasq-options", dhcpv6);
virObjectUnref(dhcpv6);
virObjectUnref(full);
diff --git a/tests/networkxml2xmlin/dnsmasq-options.xml b/tests/networkxml2xmlin/dnsmasq-options.xml
new file mode 100644
index 0000000000000000000000000000000000000000..35a87b8e3e467a46fcd3986fe478d59d62692756
--- /dev/null
+++ b/tests/networkxml2xmlin/dnsmasq-options.xml
@@ -0,0 +1,15 @@
+
+ default
+ 81ff0d90-c91e-6742-64da-4a736edb9a9b
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/networkxml2xmlout/dnsmasq-options.xml b/tests/networkxml2xmlout/dnsmasq-options.xml
new file mode 100644
index 0000000000000000000000000000000000000000..856a018f251157a98400b21e097ee20bdf56c512
--- /dev/null
+++ b/tests/networkxml2xmlout/dnsmasq-options.xml
@@ -0,0 +1,17 @@
+
+ default
+ 81ff0d90-c91e-6742-64da-4a736edb9a9b
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c
index cd76ce53752a340c05db411c74849dda690e817c..3d900234456c21237a50b6142a814d69f4698fba 100644
--- a/tests/networkxml2xmltest.c
+++ b/tests/networkxml2xmltest.c
@@ -10,6 +10,7 @@
#include "network_conf.h"
#include "testutilsqemu.h"
#include "virstring.h"
+#include "network/bridge_driver.h"
#define VIR_FROM_THIS VIR_FROM_NONE
@@ -29,15 +30,19 @@ testCompareXMLToXMLFiles(const char *inxml, const char *outxml,
int ret;
testCompareNetXML2XMLResult result = TEST_COMPARE_NET_XML2XML_RESULT_SUCCESS;
virNetworkDefPtr dev = NULL;
+ virNetworkXMLOptionPtr xmlopt = NULL;
- if (!(dev = virNetworkDefParseFile(inxml, NULL))) {
+ if (!(xmlopt = networkDnsmasqCreateXMLConf()))
+ goto cleanup;
+
+ if (!(dev = virNetworkDefParseFile(inxml, xmlopt))) {
result = TEST_COMPARE_NET_XML2XML_RESULT_FAIL_PARSE;
goto cleanup;
}
if (expectResult == TEST_COMPARE_NET_XML2XML_RESULT_FAIL_PARSE)
goto cleanup;
- if (!(actual = virNetworkDefFormat(dev, NULL, flags))) {
+ if (!(actual = virNetworkDefFormat(dev, xmlopt, flags))) {
result = TEST_COMPARE_NET_XML2XML_RESULT_FAIL_FORMAT;
goto cleanup;
}
@@ -67,6 +72,7 @@ testCompareXMLToXMLFiles(const char *inxml, const char *outxml,
VIR_FREE(actual);
virNetworkDefFree(dev);
+ virObjectUnref(xmlopt);
return ret;
}
@@ -158,6 +164,7 @@ mymain(void)
DO_TEST_PARSE_ERROR("passthrough-duplicate");
DO_TEST("metadata");
DO_TEST("set-mtu");
+ DO_TEST("dnsmasq-options");
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}