From 0b6336c2d98ff0e3545a0334f506ae90b664c85f Mon Sep 17 00:00:00 2001 From: Laine Stump Date: Thu, 11 Aug 2016 22:28:27 -0400 Subject: [PATCH] network: allow limiting a element to certain domains For some unknown reason the original implementation of the element only took advantage of part of the functionality in the dnsmasq feature it exposes - it allowed specifying the ip address of a DNS server which *all* DNS requests would be forwarded to, like this: This is a frontend for dnsmasq's "server" option, which also allows you to specify a domain that must be matched in order for a request to be forwarded to a particular server. This patch adds support for specifying the domain. For example: would forward requests for bob.example.com, ftp.example.com and joe.corp.example.com all to the DNS server at 192.168.1.1, but would forward requests for travesty.org and www.travesty.org to 10.0.0.1. And due to the second line, requests for www.example.com, and odd.www.example.com would be resolved by the libvirt network's own DNS server (i.e. thery wouldn't be immediately forwarded) even though they also match 'example.com' - the match is given to the entry with the longest matching domain. DNS requests not matching any of the entries would be resolved by the libvirt network's own DNS server. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1331796 --- docs/formatnetwork.html.in | 28 ++++++++--- docs/schemas/network.rng | 8 ++- src/conf/network_conf.c | 49 ++++++++++++++++--- src/conf/network_conf.h | 8 ++- src/network/bridge_driver.c | 17 ++++++- .../nat-network-dns-forwarders.conf | 2 + .../nat-network-dns-forwarders.xml | 2 + .../nat-network-dns-forwarders.xml | 6 ++- .../nat-network-dns-forwarders.xml | 2 + 9 files changed, 101 insertions(+), 21 deletions(-) diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in index e103dd7857..13ca32de97 100644 --- a/docs/formatnetwork.html.in +++ b/docs/formatnetwork.html.in @@ -847,7 +847,8 @@ <dns> <txt name="example" value="example value" /> <forwarder addr="8.8.8.8"/> - <forwarder addr="8.8.4.4"/> + <forwarder domain='example.com' addr="8.8.4.4"/> + <forwarder domain='www.example.com'/> <srv service='name' protocol='tcp' domain='test-domain-name' target='.' port='1024' priority='10' weight='10'/> <host ip='192.168.122.2'> <hostname>myhost</hostname> @@ -915,12 +916,25 @@ Currently supported sub-elements of <dns> are:
forwarder
-
A dns element can have 0 or - more forwarder elements. Each forwarder - element defines an IP address to be used as forwarder in - DNS server configuration. The addr attribute is required - and defines the IP address of every - forwarder. Since 1.1.3 +
The dns element can have 0 or + more <forwarder> elements. Each + forwarder element defines an alternate DNS server to use + for some, or all, DNS requests sent to this network's DNS + server. There are two attributes - domain, + and addr; at least one of these must be + specified in any <forwarder> + element. If both domain and addr + are specified, then all requests that match the given + domain will be forwarded to the DNS server at addr. If + only domain is specified, then all matching + domains will be resolved locally (or via the host's + standard DNS forwarding if they can't be resolved + locally). If an addr is specified by itself, + then all DNS requests to the network's DNS server will be + forwarded to the DNS server at that address with no + exceptions. addr Since + 1.1.3, domain Since + 2.2.0.
txt
A dns element can have 0 or more txt elements. diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng index 12d4b34505..1a18e64b24 100644 --- a/docs/schemas/network.rng +++ b/docs/schemas/network.rng @@ -260,7 +260,13 @@ - + + + + + + + diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index d77b8379fe..aa397768c9 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -349,12 +349,20 @@ virNetworkDNSSrvDefClear(virNetworkDNSSrvDefPtr def) VIR_FREE(def->target); } + +static void +virNetworkDNSForwarderClear(virNetworkDNSForwarderPtr def) +{ + VIR_FREE(def->domain); +} + + static void virNetworkDNSDefClear(virNetworkDNSDefPtr def) { if (def->forwarders) { while (def->nfwds) - VIR_FREE(def->forwarders[--def->nfwds]); + virNetworkDNSForwarderClear(&def->forwarders[--def->nfwds]); VIR_FREE(def->forwarders); } if (def->txts) { @@ -1379,14 +1387,25 @@ virNetworkDNSDefParseXML(const char *networkName, goto cleanup; for (i = 0; i < nfwds; i++) { - def->forwarders[i] = virXMLPropString(fwdNodes[i], "addr"); - if (virSocketAddrParse(NULL, def->forwarders[i], AF_UNSPEC) < 0) { + char *addr = virXMLPropString(fwdNodes[i], "addr"); + + if (addr && virSocketAddrParse(&def->forwarders[i].addr, + addr, AF_UNSPEC) < 0) { virReportError(VIR_ERR_XML_ERROR, - _("Invalid forwarder IP address '%s' " - "in network '%s'"), - def->forwarders[i], networkName); + _("Invalid forwarder IP address '%s' " + "in network '%s'"), + addr, networkName); + VIR_FREE(addr); goto cleanup; } + def->forwarders[i].domain = virXMLPropString(fwdNodes[i], "domain"); + if (!(addr || def->forwarders[i].domain)) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Invalid forwarder element, must contain " + "at least one of addr or domain")); + goto cleanup; + } + VIR_FREE(addr); def->nfwds++; } } @@ -2554,8 +2573,22 @@ virNetworkDNSDefFormat(virBufferPtr buf, virBufferAdjustIndent(buf, 2); for (i = 0; i < def->nfwds; i++) { - virBufferAsprintf(buf, "\n", - def->forwarders[i]); + + virBufferAddLit(buf, "forwarders[i].domain) { + virBufferEscapeString(buf, " domain='%s'", + def->forwarders[i].domain); + } + if (VIR_SOCKET_ADDR_VALID(&def->forwarders[i].addr)) { + char *addr = virSocketAddrFormat(&def->forwarders[i].addr); + + if (!addr) + return -1; + + virBufferAsprintf(buf, " addr='%s'", addr); + VIR_FREE(addr); + } + virBufferAddLit(buf, "/>\n"); } for (i = 0; i < def->ntxts; i++) { diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 9ebd4a73eb..3b227db6f3 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -125,6 +125,12 @@ struct _virNetworkDNSHostDef { char **names; }; + +typedef struct _virNetworkDNSForwarder { + virSocketAddr addr; + char *domain; +} virNetworkDNSForwarder, *virNetworkDNSForwarderPtr; + typedef struct _virNetworkDNSDef virNetworkDNSDef; typedef virNetworkDNSDef *virNetworkDNSDefPtr; struct _virNetworkDNSDef { @@ -137,7 +143,7 @@ struct _virNetworkDNSDef { size_t nsrvs; virNetworkDNSSrvDefPtr srvs; size_t nfwds; - char **forwarders; + virNetworkDNSForwarderPtr forwarders; }; typedef struct _virNetworkIPDef virNetworkIPDef; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 49c0a2fa76..74f75d015f 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -958,8 +958,21 @@ networkDnsmasqConfContents(virNetworkObjPtr network, 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->dns.forwarders[i]); + virNetworkDNSForwarderPtr fwd = &network->def->dns.forwarders[i]; + + virBufferAddLit(&configbuf, "server="); + if (fwd->domain) + virBufferAsprintf(&configbuf, "/%s/", fwd->domain); + if (VIR_SOCKET_ADDR_VALID(&fwd->addr)) { + char *addr = virSocketAddrFormat(&fwd->addr); + + if (!addr) + goto cleanup; + virBufferAsprintf(&configbuf, "%s\n", addr); + } else { + /* "don't forward requests for this domain" */ + virBufferAddLit(&configbuf, "#\n"); + } } } diff --git a/tests/networkxml2confdata/nat-network-dns-forwarders.conf b/tests/networkxml2confdata/nat-network-dns-forwarders.conf index 8bf3b9c360..0bd76bf60c 100644 --- a/tests/networkxml2confdata/nat-network-dns-forwarders.conf +++ b/tests/networkxml2confdata/nat-network-dns-forwarders.conf @@ -8,6 +8,8 @@ strict-order no-resolv server=8.8.8.8 server=8.8.4.4 +server=/example.com/192.168.1.1 +server=/www.example.com/# except-interface=lo bind-dynamic interface=virbr0 diff --git a/tests/networkxml2confdata/nat-network-dns-forwarders.xml b/tests/networkxml2confdata/nat-network-dns-forwarders.xml index 8fab78ea3a..5d4f3fa697 100644 --- a/tests/networkxml2confdata/nat-network-dns-forwarders.xml +++ b/tests/networkxml2confdata/nat-network-dns-forwarders.xml @@ -6,6 +6,8 @@ + + diff --git a/tests/networkxml2xmlin/nat-network-dns-forwarders.xml b/tests/networkxml2xmlin/nat-network-dns-forwarders.xml index 4d7310d1c6..426dd45cd9 100644 --- a/tests/networkxml2xmlin/nat-network-dns-forwarders.xml +++ b/tests/networkxml2xmlin/nat-network-dns-forwarders.xml @@ -4,8 +4,10 @@ - - + + + + diff --git a/tests/networkxml2xmlout/nat-network-dns-forwarders.xml b/tests/networkxml2xmlout/nat-network-dns-forwarders.xml index 930a42abc0..c05ad5514d 100644 --- a/tests/networkxml2xmlout/nat-network-dns-forwarders.xml +++ b/tests/networkxml2xmlout/nat-network-dns-forwarders.xml @@ -8,6 +8,8 @@ + +