xmlNodePtr *txtNodes = NULL;
xmlNodePtr *fwdNodes = NULL;
char *forwardPlainNames = NULL;
+ char *enable = NULL;
int nhosts, nsrvs, ntxts, nfwds;
size_t i;
int ret = -1;
ctxt->node = node;
+ enable = virXPathString("string(./@enable)", ctxt);
+ if (enable) {
+ def->enable = virTristateBoolTypeFromString(enable);
+ if (def->enable <= 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid dns enable setting '%s' "
+ "in network '%s'"),
+ enable, networkName);
+ goto cleanup;
+ }
+ }
+
forwardPlainNames = virXPathString("string(./@forwardPlainNames)", ctxt);
if (forwardPlainNames) {
def->forwardPlainNames = virTristateBoolTypeFromString(forwardPlainNames);
}
}
+ if (def->enable == VIR_TRISTATE_BOOL_NO &&
+ (nfwds || nhosts || nsrvs || ntxts)) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Extra data in disabled network '%s'"),
+ networkName);
+ goto cleanup;
+ }
+
ret = 0;
cleanup:
+ VIR_FREE(enable);
VIR_FREE(forwardPlainNames);
VIR_FREE(fwdNodes);
VIR_FREE(hostNodes);
{
size_t i, j;
- if (!(def->forwardPlainNames || def->nfwds || def->nhosts ||
+ if (!(def->enable || def->forwardPlainNames || def->nfwds || def->nhosts ||
def->nsrvs || def->ntxts))
return 0;
virBufferAddLit(buf, "<dns");
- /* default to "yes", but don't format it in the XML */
+ if (def->enable) {
+ const char *fwd = virTristateBoolTypeToString(def->enable);
+
+ if (!fwd) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unknown enable type %d in network"),
+ def->enable);
+ return -1;
+ }
+ virBufferAsprintf(buf, " enable='%s'", fwd);
+ }
if (def->forwardPlainNames) {
const char *fwd = virTristateBoolTypeToString(def->forwardPlainNames);
return -1;
}
virBufferAsprintf(buf, " forwardPlainNames='%s'", fwd);
- if (!(def->nfwds || def->nhosts || def->nsrvs || def->ntxts)) {
- virBufferAddLit(buf, "/>\n");
- return 0;
- }
+ }
+ if (!(def->nfwds || def->nhosts || def->nsrvs || def->ntxts)) {
+ virBufferAddLit(buf, "/>\n");
+ return 0;
}
virBufferAddLit(buf, ">\n");
int nbleases = 0;
size_t i;
virNetworkDNSDefPtr dns = &network->def->dns;
+ bool wantDNS = dns->enable != VIR_TRISTATE_BOOL_NO;
virNetworkIPDefPtr tmpipdef, ipdef, ipv4def, ipv6def;
bool ipv6SLAAC;
char *saddr = NULL, *eaddr = NULL;
"strict-order\n",
network->def->name);
- if (network->def->dns.forwarders) {
+ /* if dns is disabled, set its listening port to 0, which
+ * tells dnsmasq to not listen
+ */
+ if (!wantDNS)
+ virBufferAddLit(&configbuf, "port=0\n");
+
+ if (wantDNS && network->def->dns.forwarders) {
virBufferAddLit(&configbuf, "no-resolv\n");
for (i = 0; i < network->def->dns.nfwds; i++) {
virBufferAsprintf(&configbuf, "server=%s\n",
network->def->domain);
}
- if (network->def->dns.forwardPlainNames == VIR_TRISTATE_BOOL_NO) {
+ if (wantDNS && network->def->dns.forwardPlainNames == VIR_TRISTATE_BOOL_NO) {
virBufferAddLit(&configbuf, "domain-needed\n");
/* need to specify local=// whether or not a domain is
* specified, unless the config says we should forward "plain"
}
}
- for (i = 0; i < dns->ntxts; i++) {
- virBufferAsprintf(&configbuf, "txt-record=%s,%s\n",
- dns->txts[i].name,
- dns->txts[i].value);
- }
-
- for (i = 0; i < dns->nsrvs; i++) {
- /* service/protocol are required, and should have been validated
- * by the parser.
- */
- if (!dns->srvs[i].service) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Missing required 'service' "
- "attribute in SRV record of network '%s'"),
- network->def->name);
- goto cleanup;
+ if (wantDNS) {
+ for (i = 0; i < dns->ntxts; i++) {
+ virBufferAsprintf(&configbuf, "txt-record=%s,%s\n",
+ dns->txts[i].name,
+ dns->txts[i].value);
}
- if (!dns->srvs[i].protocol) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Missing required 'service' "
- "attribute in SRV record of network '%s'"),
- network->def->name);
- goto cleanup;
- }
- /* RFC2782 requires that service and protocol be preceded by
- * an underscore.
- */
- virBufferAsprintf(&configbuf, "srv-host=_%s._%s",
- dns->srvs[i].service, dns->srvs[i].protocol);
- /* domain is optional - it defaults to the domain of this network */
- if (dns->srvs[i].domain)
- virBufferAsprintf(&configbuf, ".%s", dns->srvs[i].domain);
+ for (i = 0; i < dns->nsrvs; i++) {
+ /* service/protocol are required, and should have been validated
+ * by the parser.
+ */
+ if (!dns->srvs[i].service) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Missing required 'service' "
+ "attribute in SRV record of network '%s'"),
+ network->def->name);
+ goto cleanup;
+ }
+ if (!dns->srvs[i].protocol) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Missing required 'service' "
+ "attribute in SRV record of network '%s'"),
+ network->def->name);
+ goto cleanup;
+ }
+ /* RFC2782 requires that service and protocol be preceded by
+ * an underscore.
+ */
+ virBufferAsprintf(&configbuf, "srv-host=_%s._%s",
+ dns->srvs[i].service, dns->srvs[i].protocol);
- /* If target is empty or ".", that means "the service is
- * decidedly not available at this domain" (RFC2782). In that
- * case, any port, priority, or weight is irrelevant.
- */
- if (dns->srvs[i].target && STRNEQ(dns->srvs[i].target, ".")) {
-
- virBufferAsprintf(&configbuf, ",%s", dns->srvs[i].target);
- /* port, priority, and weight are optional, but are
- * identified by their position in the line. If an item is
- * unspecified, but something later in the line *is*
- * specified, we need to give the default value for the
- * unspecified item. (According to the dnsmasq manpage,
- * the default for port is 1).
+ /* domain is optional - it defaults to the domain of this network */
+ if (dns->srvs[i].domain)
+ virBufferAsprintf(&configbuf, ".%s", dns->srvs[i].domain);
+
+ /* If target is empty or ".", that means "the service is
+ * decidedly not available at this domain" (RFC2782). In that
+ * case, any port, priority, or weight is irrelevant.
*/
- if (dns->srvs[i].port ||
- dns->srvs[i].priority || dns->srvs[i].weight)
- virBufferAsprintf(&configbuf, ",%d",
- dns->srvs[i].port ? dns->srvs[i].port : 1);
- if (dns->srvs[i].priority || dns->srvs[i].weight)
- virBufferAsprintf(&configbuf, ",%d", dns->srvs[i].priority);
- if (dns->srvs[i].weight)
- virBufferAsprintf(&configbuf, ",%d", dns->srvs[i].weight);
+ if (dns->srvs[i].target && STRNEQ(dns->srvs[i].target, ".")) {
+
+ virBufferAsprintf(&configbuf, ",%s", dns->srvs[i].target);
+ /* port, priority, and weight are optional, but are
+ * identified by their position in the line. If an item is
+ * unspecified, but something later in the line *is*
+ * specified, we need to give the default value for the
+ * unspecified item. (According to the dnsmasq manpage,
+ * the default for port is 1).
+ */
+ if (dns->srvs[i].port ||
+ dns->srvs[i].priority || dns->srvs[i].weight)
+ virBufferAsprintf(&configbuf, ",%d",
+ dns->srvs[i].port ? dns->srvs[i].port : 1);
+ if (dns->srvs[i].priority || dns->srvs[i].weight)
+ virBufferAsprintf(&configbuf, ",%d", dns->srvs[i].priority);
+ if (dns->srvs[i].weight)
+ virBufferAsprintf(&configbuf, ",%d", dns->srvs[i].weight);
+ }
+ virBufferAddLit(&configbuf, "\n");
}
- virBufferAddLit(&configbuf, "\n");
}
/* Find the first dhcp for both IPv4 and IPv6 */
virBufferAsprintf(&configbuf, "dhcp-range=%s,%s",
saddr, eaddr);
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
- virBufferAsprintf(&configbuf, ",%d", prefix);
+ virBufferAsprintf(&configbuf, ",%d", prefix);
virBufferAddLit(&configbuf, "\n");
VIR_FREE(saddr);
virBufferAsprintf(&configbuf, "dhcp-range=%s,static",
bridgeaddr);
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
- virBufferAsprintf(&configbuf, ",%d", prefix);
+ virBufferAsprintf(&configbuf, ",%d", prefix);
virBufferAddLit(&configbuf, "\n");
VIR_FREE(bridgeaddr);
}
/* Likewise, always create this file and put it on the
* commandline, to allow for runtime additions.
*/
- virBufferAsprintf(&configbuf, "addn-hosts=%s\n",
- dctx->addnhostsfile->path);
+ if (wantDNS) {
+ virBufferAsprintf(&configbuf, "addn-hosts=%s\n",
+ dctx->addnhostsfile->path);
+ }
/* Are we doing RA instead of radvd? */
if (DNSMASQ_RA_SUPPORT(caps)) {
networkStartDhcpDaemon(virNetworkDriverStatePtr driver,
virNetworkObjPtr network)
{
+ virNetworkIPDefPtr ipdef;
+ size_t i;
+ bool needDnsmasq = false;
virCommandPtr cmd = NULL;
char *pidfile = NULL;
int ret = -1;
dnsmasqContext *dctx = NULL;
- if (!virNetworkDefGetIPByIndex(network->def, AF_UNSPEC, 0)) {
+ if (!(ipdef = virNetworkDefGetIPByIndex(network->def, AF_UNSPEC, 0))) {
/* no IP addresses, so we don't need to run */
ret = 0;
goto cleanup;
}
+ /* see if there are any IP addresses that need a dhcp server */
+ for (i = 0; ipdef && !needDnsmasq;
+ ipdef = virNetworkDefGetIPByIndex(network->def, AF_UNSPEC, i + 1)) {
+ if (ipdef->nranges || ipdef->nhosts)
+ needDnsmasq = true;
+ }
+
+ if (!needDnsmasq && network->def->dns.enable == VIR_TRISTATE_BOOL_NO) {
+ ret = 0;
+ goto cleanup;
+ }
+
if (virFileMakePath(driver->pidDir) < 0) {
virReportSystemError(errno,
_("cannot create directory %s"),