[libvirt] [PATCHv4 0/2] DHCPv6; put dnsmasq parameters in conf-file

Updated based on Laine Stump review and rebased 6 December 2012 Note to Laine: I "ignored" one of your comments involving moving the order of some dnsmasq parameters in the spirit of "what is done is done." Changing that would have required more changes to test files as well as the conf-file patch file. These two patch files are packaged together because they serially depend on each other. The DHCPv6 support checks dnsmasq's version and requires a minimum of 2.64. Also, using dnsmasq for providing the RA service is checked against the dnsmasq version and is currently 2.64. There are separate checks for DHCPv6 and Router Advertising support by dnsmasq. Dnsmasq version 2.64 final is not released and staged for both Fedora 18 and Fedora 17. As with IPv4, IPv6 DHCP is only one subnetwork on an interface. Additionally, if other IPv6 addresses are defined, a warning message is issued since the Router Advertisement service will support only state-full (DHCP) or state-less (SLAAC) addressing on a network interface (not both). Thus, the additional subnetworks will need to be manually configured to properly function. If dnsmasq provides the RA service, it also points to itself as a RDNSS (Recursive DNS Server) as part of the information is supplies. If IPv6 DHCP is not being run, then SLAAC addressing is supported for any IPv6 addresses specified. Gene Czarcinski (2): v8.3 add support for DHCPv6 v8.0: put dnsmasq parameters into conf-file docs/formatnetwork.html.in | 108 +++- docs/schemas/network.rng | 12 +- src/conf/network_conf.c | 96 ++-- src/network/bridge_driver.c | 556 ++++++++++++++------- src/network/bridge_driver.h | 13 +- src/util/dnsmasq.c | 29 +- src/util/dnsmasq.h | 17 +- tests/networkxml2argvdata/dhcp6-nat-network.conf | 19 + tests/networkxml2argvdata/dhcp6-nat-network.xml | 24 + tests/networkxml2argvdata/dhcp6-network.conf | 19 + tests/networkxml2argvdata/dhcp6-network.xml | 14 + .../dhcp6host-routed-network.conf | 17 + .../dhcp6host-routed-network.xml | 19 + tests/networkxml2argvdata/isolated-network.argv | 10 - tests/networkxml2argvdata/isolated-network.conf | 20 + .../networkxml2argvdata/nat-network-dns-hosts.argv | 5 - .../networkxml2argvdata/nat-network-dns-hosts.conf | 14 + .../nat-network-dns-srv-record-minimal.argv | 16 - .../nat-network-dns-srv-record-minimal.conf | 23 + .../nat-network-dns-srv-record.argv | 11 - .../nat-network-dns-srv-record.conf | 18 + .../nat-network-dns-txt-record.argv | 9 - .../nat-network-dns-txt-record.conf | 18 + tests/networkxml2argvdata/nat-network.argv | 8 - tests/networkxml2argvdata/nat-network.conf | 19 + tests/networkxml2argvdata/netboot-network.argv | 10 - tests/networkxml2argvdata/netboot-network.conf | 23 + .../networkxml2argvdata/netboot-proxy-network.argv | 10 - .../networkxml2argvdata/netboot-proxy-network.conf | 21 + tests/networkxml2argvdata/routed-network.argv | 4 - tests/networkxml2argvdata/routed-network.conf | 12 + tests/networkxml2argvtest.c | 49 +- 32 files changed, 865 insertions(+), 378 deletions(-) create mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.conf create mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.xml create mode 100644 tests/networkxml2argvdata/dhcp6-network.conf create mode 100644 tests/networkxml2argvdata/dhcp6-network.xml create mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.conf create mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.xml delete mode 100644 tests/networkxml2argvdata/isolated-network.argv create mode 100644 tests/networkxml2argvdata/isolated-network.conf delete mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.conf delete mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.conf delete mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record.conf delete mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.conf delete mode 100644 tests/networkxml2argvdata/nat-network.argv create mode 100644 tests/networkxml2argvdata/nat-network.conf delete mode 100644 tests/networkxml2argvdata/netboot-network.argv create mode 100644 tests/networkxml2argvdata/netboot-network.conf delete mode 100644 tests/networkxml2argvdata/netboot-proxy-network.argv create mode 100644 tests/networkxml2argvdata/netboot-proxy-network.conf delete mode 100644 tests/networkxml2argvdata/routed-network.argv create mode 100644 tests/networkxml2argvdata/routed-network.conf -- 1.7.11.7

Updated and rebased 06 Dec 2012. The DHCPv6 support includes IPV6 dhcp-range and dhcp-host for one IPv6 subnetwork on one interface. This support will only work if dnsmasq version >= 2.64; otherwise an error occurs if dhcp-range or dhcp-host is specified. Essentially, this change provides the same DHCP support for IPv6 that has been available for IPv4. With dnsmasq >= 2.64, support for the RA service is now provided by dnsmasq (radvd is no longer used/started). Dnsmasq 2.64 does contain the bugfixes released to DHCPv6 and dnsmasq's handling of Router Advertisement. Documentation and the network schema has been updated to reflect the new support. This version of the DHCPv6 patch files includes the changes from Laine Stump's review. --- docs/formatnetwork.html.in | 108 +++++- docs/schemas/network.rng | 12 +- src/conf/network_conf.c | 96 +++-- src/network/bridge_driver.c | 425 ++++++++++++++------- src/util/dnsmasq.c | 29 +- src/util/dnsmasq.h | 17 +- tests/networkxml2argvdata/dhcp6-nat-network.argv | 15 + tests/networkxml2argvdata/dhcp6-nat-network.xml | 24 ++ tests/networkxml2argvdata/dhcp6-network.argv | 15 + tests/networkxml2argvdata/dhcp6-network.xml | 14 + .../dhcp6host-routed-network.argv | 13 + .../dhcp6host-routed-network.xml | 19 + tests/networkxml2argvdata/isolated-network.argv | 16 +- .../networkxml2argvdata/nat-network-dns-hosts.argv | 13 +- .../nat-network-dns-srv-record-minimal.argv | 9 +- .../nat-network-dns-srv-record.argv | 9 +- .../nat-network-dns-txt-record.argv | 10 +- tests/networkxml2argvdata/nat-network.argv | 17 +- tests/networkxml2argvdata/netboot-network.argv | 23 +- .../networkxml2argvdata/netboot-proxy-network.argv | 19 +- tests/networkxml2argvdata/routed-network.argv | 10 +- tests/networkxml2argvtest.c | 7 +- 22 files changed, 677 insertions(+), 243 deletions(-) create mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.argv create mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.xml create mode 100644 tests/networkxml2argvdata/dhcp6-network.argv create mode 100644 tests/networkxml2argvdata/dhcp6-network.xml create mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.argv create mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.xml diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in index a3a5ced..0ce8813 100644 --- a/docs/formatnetwork.html.in +++ b/docs/formatnetwork.html.in @@ -583,8 +583,10 @@ dotted-decimal format, or an IPv6 address in standard colon-separated hexadecimal format, that will be configured on the bridge - device associated with the virtual network. To the guests this - address will be their default route. For IPv4 addresses, the <code>netmask</code> + device associated with the virtual network. To the guests this IPv4 + address will be their IPv4 default route. For IPv6, the default route is + established via Router Advertisement. + For IPv4 addresses, the <code>netmask</code> attribute defines the significant bits of the network address, again specified in dotted-decimal format. For IPv6 addresses, and as an alternate method for IPv4 addresses, you can specify @@ -593,10 +595,13 @@ could also be given as <code>prefix='24'</code>. The <code>family</code> attribute is used to specify the type of address - 'ipv4' or 'ipv6'; if no <code>family</code> is given, 'ipv4' is assumed. A network can have more than - one of each family of address defined, but only a single address can have a - <code>dhcp</code> or <code>tftp</code> element. <span class="since">Since 0.3.0; + one of each family of address defined, but only a single IPv4 address can have a + <code>dhcp</code> or <code>tftp</code> element. <span class="since">Since 0.3.0 </span> IPv6, multiple addresses on a single network, <code>family</code>, and - <code>prefix</code> since 0.8.7</span> + <code>prefix</code>. <span class="since">Since 0.8.7</span> In addition + to the one IPv4 address which has a <code>dhcp</code> definition, one IPv6 + address can have a <code>dhcp</code> definition. + <span class="since">Since 1.0.1</span> <dl> <dt><code>tftp</code></dt> <dd>Immediately within @@ -617,27 +622,46 @@ <code>dhcp</code> element is not supported for IPv6, and is only supported on a single IP address per network for IPv4. <span class="since">Since 0.3.0</span> + The <code>dhcp</code> element is now supported for IPv6. + Again, there is a restriction that only one IPv6 address definition + is able to have a <code>dhcp</code> element. + <span class="since">Since 1.0.1</span> <dl> <dt><code>range</code></dt> <dd>The <code>start</code> and <code>end</code> attributes on the <code>range</code> element specify the boundaries of a pool of - IPv4 addresses to be provided to DHCP clients. These two addresses + addresses to be provided to DHCP clients. These two addresses must lie within the scope of the network defined on the parent - <code>ip</code> element. <span class="since">Since 0.3.0</span> + <code>ip</code> element. There may be zero or more + <code>range</code> elements specified. + <span class="since">Since 0.3.0</span> + <code>range</code> can be specified for one IPv4 address, + one IPv6 address, or both. <span class="since">Since 1.0.1</span> </dd> <dt><code>host</code></dt> <dd>Within the <code>dhcp</code> element there may be zero or more - <code>host</code> elements; these specify hosts which will be given + <code>host</code> elements. These specify hosts which will be given names and predefined IP addresses by the built-in DHCP server. Any - such element must specify the MAC address of the host to be assigned + such IPv4 element must specify the MAC address of the host to be assigned a given name (via the <code>mac</code> attribute), the IP to be assigned to that host (via the <code>ip</code> attribute), and the name to be given that host by the DHCP server (via the <code>name</code> attribute). <span class="since">Since 0.4.5</span> + Within the IPv6 <code>dhcp</code> element zero or more + <code>host</code> elements are now supported. The definition for + an IPv6 <code>host</code> element differs from that for IPv4: + there is no <code>mac</code> attribute since a MAC address has no + defined meaning in IPv6. Instead, the <code>name</code> attribute is + used to identify the host to be assigned the IPv6 address. For DHCPv6, + the name is the plain name of the client host sent by the + client to the server. Note that this method of assigning a + specific IP address can be used instead of the <code>mac</code> + attribute for IPv4. <span class="since">Since 1.0.1</span> </dd> <dt><code>bootp</code></dt> <dd>The optional <code>bootp</code> - element specifies BOOTP options to be provided by the DHCP server. + element specifies BOOTP options to be provided by the DHCP + server for IPv4 only. Two attributes are supported: <code>file</code> is mandatory and gives the file to be used for the boot image; <code>server</code> is optional and gives the address of the TFTP server from which the boot @@ -680,6 +704,29 @@ <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" /> </network></pre> + + <p> + Below is a variation of the above example which adds an IPv6 + dhcp range definition. + </p> + + <pre> + <network> + <name>default6</name> + <bridge name="virbr0" /> + <forward mode="nat"/> + <ip address="192.168.122.1" netmask="255.255.255.0"> + <dhcp> + <range start="192.168.122.2" end="192.168.122.254" /> + </dhcp> + </ip> + <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" > + <dhcp> + <range start="2001:db8:ca2:2:1::10" end="2001:db8:ca2:2:1::ff" /> + </dhcp> + </ip> + </network></pre> + <h3><a name="examplesRoute">Routed network config</a></h3> <p> @@ -704,6 +751,29 @@ <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" /> </network></pre> + <p> + Below is another IPv6 varition. Instead of a dhcp range being + specified, this example has a couple of IPv6 host definitions. + </p> + + <pre> + <network> + <name>local6</name> + <bridge name="virbr1" /> + <forward mode="route" dev="eth1"/> + <ip address="192.168.122.1" netmask="255.255.255.0"> + <dhcp> + <range start="192.168.122.2" end="192.168.122.254" /> + </dhcp> + </ip> + <ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" > + <dhcp> + <host name="paul" ip="2001:db8:ca2:2:3::1" /> + <host name="bob" ip="2001:db8:ca2:2:3::2" /> + </dhcp> + </ip> + </network></pre> + <h3><a name="examplesPrivate">Isolated network config</a></h3> <p> @@ -726,6 +796,24 @@ <ip family="ipv6" address="2001:db8:ca2:3::1" prefix="64" /> </network></pre> + <h3><a name="examplesPrivate6">Isolated IPv6 network config</a></h3> + + <p> + This variation of an isolated network defines only IPv6. + </p> + + <pre> + <network> + <name>sixnet</name> + <bridge name="virbr6" /> + <ip family="ipv6" address="2001:db8:ca2:6::1" prefix="64" > + <dhcp> + <host name="peter" ip="2001:db8:ca2:6:6::1" /> + <host name="dariusz" ip="2001:db8:ca2:6:6::2" /> + </dhcp> + </ip> + </network></pre> + <h3><a name="examplesBridge">Using an existing host bridge</a></h3> <p> diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng index 0d67f7f..09d7c73 100644 --- a/docs/schemas/network.rng +++ b/docs/schemas/network.rng @@ -218,7 +218,7 @@ </zeroOrMore> <zeroOrMore> <element name="host"> - <attribute name="ip"><ref name="ipv4Addr"/></attribute> + <attribute name="ip"><ref name="ipAddr"/></attribute> <oneOrMore> <element name="hostname"><ref name="dnsName"/></element> </oneOrMore> @@ -272,15 +272,17 @@ <element name="dhcp"> <zeroOrMore> <element name="range"> - <attribute name="start"><ref name="ipv4Addr"/></attribute> - <attribute name="end"><ref name="ipv4Addr"/></attribute> + <attribute name="start"><ref name="ipAddr"/></attribute> + <attribute name="end"><ref name="ipAddr"/></attribute> </element> </zeroOrMore> <zeroOrMore> <element name="host"> - <attribute name="mac"><ref name="uniMacAddr"/></attribute> + <optional> + <attribute name="mac"><ref name="uniMacAddr"/></attribute> + </optional> <attribute name="name"><text/></attribute> - <attribute name="ip"><ref name="ipv4Addr"/></attribute> + <attribute name="ip"><ref name="ipAddr"/></attribute> </element> </zeroOrMore> <optional> diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 7220659..53ee7ea 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -633,6 +633,7 @@ cleanup: static int virNetworkDHCPHostDefParse(const char *networkName, + const virNetworkIpDefPtr def, xmlNodePtr node, virNetworkDHCPHostDefPtr host, bool partialOkay) @@ -644,6 +645,13 @@ virNetworkDHCPHostDefParse(const char *networkName, mac = virXMLPropString(node, "mac"); if (mac != NULL) { + if (VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET6)) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid to specify MAC address '%s' " + "in network '%s' IPv6 static host definition"), + mac, networkName); + goto cleanup; + } if (virMacAddrParse(mac, &addr) < 0) { virReportError(VIR_ERR_XML_ERROR, _("Cannot parse MAC address '%s' in network '%s'"), @@ -686,10 +694,20 @@ virNetworkDHCPHostDefParse(const char *networkName, networkName); } } else { - /* normal usage - you need at least one MAC address or one host name */ - if (!(mac || name)) { + /* normal usage - you need at least name (IPv6) or one of MAC + * address or name (IPv4) + */ + if (VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET6)) { + if (!name) { + virReportError(VIR_ERR_XML_ERROR, + _("Static host definition in IPv6 network '%s' " + "must have name attribute"), + networkName); + goto cleanup; + } + } else if (!(mac || name)) { virReportError(VIR_ERR_XML_ERROR, - _("Static host definition in network '%s' " + _("Static host definition in IPv4 network '%s' " "must have mac or name attribute"), networkName); goto cleanup; @@ -748,15 +766,16 @@ virNetworkDHCPDefParse(const char *networkName, virReportOOMError(); return -1; } - if (virNetworkDHCPHostDefParse(networkName, cur, + if (virNetworkDHCPHostDefParse(networkName, def, cur, &def->hosts[def->nhosts], false) < 0) { return -1; } def->nhosts++; - } else if (cur->type == XML_ELEMENT_NODE && - xmlStrEqual(cur->name, BAD_CAST "bootp")) { + } else if (VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET) && + cur->type == XML_ELEMENT_NODE && + xmlStrEqual(cur->name, BAD_CAST "bootp")) { char *file; char *server; virSocketAddr inaddr; @@ -1113,30 +1132,29 @@ virNetworkIPParseXML(const char *networkName, } } - if (VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET)) { - /* parse IPv4-related info */ - cur = node->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE && - xmlStrEqual(cur->name, BAD_CAST "dhcp")) { - result = virNetworkDHCPDefParse(networkName, def, cur); - if (result) - goto error; - - } else if (cur->type == XML_ELEMENT_NODE && - xmlStrEqual(cur->name, BAD_CAST "tftp")) { - char *root; - - if (!(root = virXMLPropString(cur, "root"))) { - cur = cur->next; - continue; - } + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE && + xmlStrEqual(cur->name, BAD_CAST "dhcp")) { + if (virNetworkDHCPDefParse(networkName, def, cur) < 0) + goto error; + } else if (cur->type == XML_ELEMENT_NODE && + xmlStrEqual(cur->name, BAD_CAST "tftp")) { + char *root; - def->tftproot = (char *)root; + if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unsupported <tftp> element in an IPv6 element in network '%s'"), + networkName); + goto error; } - - cur = cur->next; + if (!(root = virXMLPropString(cur, "root"))) { + cur = cur->next; + continue; + } + def->tftproot = (char *)root; } + cur = cur->next; } result = 0; @@ -2382,11 +2400,9 @@ virNetworkIpDefByIndex(virNetworkDefPtr def, int parentIndex) /* first find which ip element's dhcp host list to work on */ if (parentIndex >= 0) { ipdef = virNetworkDefGetIpByIndex(def, AF_UNSPEC, parentIndex); - if (!(ipdef && - VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET))) { + if (!(ipdef)) { virReportError(VIR_ERR_OPERATION_INVALID, - _("couldn't update dhcp host entry - " - "no <ip family='ipv4'> " + _("couldn't update dhcp host entry - no <ip> " "element found at index %d in network '%s'"), parentIndex, def->name); } @@ -2399,17 +2415,17 @@ virNetworkIpDefByIndex(virNetworkDefPtr def, int parentIndex) for (ii = 0; (ipdef = virNetworkDefGetIpByIndex(def, AF_UNSPEC, ii)); ii++) { - if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET) && - (ipdef->nranges || ipdef->nhosts)) { + if (ipdef->nranges || ipdef->nhosts) break; - } } - if (!ipdef) + if (!ipdef) { ipdef = virNetworkDefGetIpByIndex(def, AF_INET, 0); + if (!ipdef) + ipdef = virNetworkDefGetIpByIndex(def, AF_INET6, 0); + } if (!ipdef) { virReportError(VIR_ERR_OPERATION_INVALID, - _("couldn't update dhcp host entry - " - "no <ip family='ipv4'> " + _("couldn't update dhcp host entry - no <ip> " "element found in network '%s'"), def->name); } return ipdef; @@ -2439,7 +2455,7 @@ virNetworkDefUpdateIPDHCPHost(virNetworkDefPtr def, /* parse the xml into a virNetworkDHCPHostDef */ if (command == VIR_NETWORK_UPDATE_COMMAND_MODIFY) { - if (virNetworkDHCPHostDefParse(def->name, ctxt->node, &host, false) < 0) + if (virNetworkDHCPHostDefParse(def->name, ipdef, ctxt->node, &host, false) < 0) goto cleanup; /* search for the entry with this (mac|name), @@ -2472,7 +2488,7 @@ virNetworkDefUpdateIPDHCPHost(virNetworkDefPtr def, } else if ((command == VIR_NETWORK_UPDATE_COMMAND_ADD_FIRST) || (command == VIR_NETWORK_UPDATE_COMMAND_ADD_LAST)) { - if (virNetworkDHCPHostDefParse(def->name, ctxt->node, &host, true) < 0) + if (virNetworkDHCPHostDefParse(def->name, ipdef, ctxt->node, &host, true) < 0) goto cleanup; /* log error if an entry with same name/address/ip already exists */ @@ -2518,7 +2534,7 @@ virNetworkDefUpdateIPDHCPHost(virNetworkDefPtr def, } else if (command == VIR_NETWORK_UPDATE_COMMAND_DELETE) { - if (virNetworkDHCPHostDefParse(def->name, ctxt->node, &host, false) < 0) + if (virNetworkDHCPHostDefParse(def->name, ipdef, ctxt->node, &host, false) < 0) goto cleanup; /* find matching entry - all specified attributes must match */ diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 00cffee..c64baf7 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -564,20 +564,35 @@ cleanup: return ret; } + /* the following does not build a file, it builds a list + * which is later saved into a file + */ + static int -networkBuildDnsmasqHostsfile(dnsmasqContext *dctx, - virNetworkIpDefPtr ipdef, - virNetworkDNSDefPtr dnsdef) +networkBuildDnsmasqDhcpHostsList(dnsmasqContext *dctx, + virNetworkIpDefPtr ipdef) { - unsigned int i, j; + unsigned int i; + bool ipv6 = false; + if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) + ipv6 = true; for (i = 0; i < ipdef->nhosts; i++) { virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]); - if ((host->mac) && VIR_SOCKET_ADDR_VALID(&host->ip)) - if (dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name) < 0) + if (VIR_SOCKET_ADDR_VALID(&host->ip)) + if (dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name, ipv6) < 0) return -1; } + return 0; +} + +static int +networkBuildDnsmasqHostsList(dnsmasqContext *dctx, + virNetworkDNSDefPtr dnsdef) +{ + unsigned int i, j; + if (dnsdef) { for (i = 0; i < dnsdef->nhosts; i++) { virNetworkDNSHostsDefPtr host = &(dnsdef->hosts[i]); @@ -595,7 +610,6 @@ networkBuildDnsmasqHostsfile(dnsmasqContext *dctx, static int networkBuildDnsmasqArgv(virNetworkObjPtr network, - virNetworkIpDefPtr ipdef, const char *pidfile, virCommandPtr cmd, dnsmasqContext *dctx, @@ -608,7 +622,8 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, char *recordPort = NULL; char *recordWeight = NULL; char *recordPriority = NULL; - virNetworkIpDefPtr tmpipdef; + virNetworkIpDefPtr tmpipdef, ipdef, ipv4def, ipv6def; + bool ipv6SLAAC; /* * NB, be careful about syntax for dnsmasq options in long format. @@ -633,14 +648,17 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, * Needed to ensure dnsmasq uses same algorithm for processing * multiple namedriver entries in /etc/resolv.conf as GLibC. */ - virCommandAddArg(cmd, "--strict-order"); + virCommandAddArgList(cmd, "--strict-order", + "--domain-needed", + NULL); - if (network->def->domain) + if (network->def->domain) { virCommandAddArgPair(cmd, "--domain", network->def->domain); + virCommandAddArg(cmd, "--expand-hosts"); + } /* need to specify local even if no domain specified */ virCommandAddArgFormat(cmd, "--local=/%s/", network->def->domain ? network->def->domain : ""); - virCommandAddArg(cmd, "--domain-needed"); if (pidfile) virCommandAddArgPair(cmd, "--pid-file", pidfile); @@ -663,7 +681,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, } else { virCommandAddArgList(cmd, "--bind-interfaces", - "--except-interface", "lo", + "--except-interface=lo", NULL); /* * --interface does not actually work with dnsmasq < 2.47, @@ -767,7 +785,60 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, } } - if (ipdef) { + /* Find the first dhcp for both IPv4 and IPv6 */ + for (ii = 0, ipv4def = NULL, ipv6def = NULL, ipv6SLAAC = false; + (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, ii)); + ii++) { + if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET)) { + if (ipdef->nranges || ipdef->nhosts) { + if (ipv4def) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("For IPv4, multiple DHCP definitions cannot " + "be specified.")); + goto cleanup; + } else { + ipv4def = ipdef; + } + } + } + if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) { + if (ipdef->nranges || ipdef->nhosts) { + if (!DNSMASQ_DHCPv6_SUPPORT(caps)) { + unsigned long version = dnsmasqCapsGetVersion(caps); + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("The version of dnsmasq on this host (%d.%d) doesn't " + "adequately support IPv6 dhcp range or dhcp host " + "specification. Version %d.%d or later is required."), + (int)version / 1000000, (int)(version % 1000000) / 1000, + DNSMASQ_DHCPv6_MAJOR_REQD, DNSMASQ_DHCPv6_MINOR_REQD); + goto cleanup; + } + if (ipv6def) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("For IPv6, multiple DHCP definitions cannot " + "be specified.")); + goto cleanup; + } else { + ipv6def = ipdef; + } + } else { + ipv6SLAAC = true; + } + } + } + + if (ipv6def && ipv6SLAAC) { + VIR_WARN("For IPv6, when DHCP is specified for one address, then " + "state-full Router Advertising will occur. The additional " + "IPv6 addresses specified require manually configured guest " + "network to work properly since both state-full (DHCP) " + "and state-less (SLAAC) addressing are not supported " + "on the same network interface."); + } + + ipdef = ipv4def ? ipv4def : ipv6def; + + while (ipdef) { for (r = 0 ; r < ipdef->nranges ; r++) { char *saddr = virSocketAddrFormat(&ipdef->ranges[r].start); if (!saddr) @@ -788,7 +859,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, /* * For static-only DHCP, i.e. with no range but at least one host element, * we have to add a special --dhcp-range option to enable the service in - * dnsmasq. + * dnsmasq. (this is for dhcp-hosts= support) */ if (!ipdef->nranges && ipdef->nhosts) { char *bridgeaddr = virSocketAddrFormat(&ipdef->address); @@ -799,61 +870,92 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, VIR_FREE(bridgeaddr); } - if (ipdef->nranges > 0) { - char *leasefile = networkDnsmasqLeaseFileName(network->def->name); - if (!leasefile) - goto cleanup; - virCommandAddArgFormat(cmd, "--dhcp-leasefile=%s", leasefile); - VIR_FREE(leasefile); - virCommandAddArgFormat(cmd, "--dhcp-lease-max=%d", nbleases); - } - - if (ipdef->nranges || ipdef->nhosts) - virCommandAddArg(cmd, "--dhcp-no-override"); + if (networkBuildDnsmasqDhcpHostsList(dctx, ipdef) < 0) + goto cleanup; - /* add domain to any non-qualified hostnames in /etc/hosts or addn-hosts */ - if (network->def->domain) - virCommandAddArg(cmd, "--expand-hosts"); + /* Note: the following is IPv4 only */ + if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET)) { + if (ipdef->nranges || ipdef->nhosts) + virCommandAddArg(cmd, "--dhcp-no-override"); - if (networkBuildDnsmasqHostsfile(dctx, ipdef, network->def->dns) < 0) - goto cleanup; + if (ipdef->tftproot) { + virCommandAddArgList(cmd, "--enable-tftp", + "--tftp-root", ipdef->tftproot, + NULL); + } - /* Even if there are currently no static hosts, if we're - * listening for DHCP, we should write a 0-length hosts - * file to allow for runtime additions. - */ - if (ipdef->nranges || ipdef->nhosts) - virCommandAddArgPair(cmd, "--dhcp-hostsfile", - dctx->hostsfile->path); + if (ipdef->bootfile) { + virCommandAddArg(cmd, "--dhcp-boot"); + if (VIR_SOCKET_ADDR_VALID(&ipdef->bootserver)) { + char *bootserver = virSocketAddrFormat(&ipdef->bootserver); - /* Likewise, always create this file and put it on the commandline, to allow for - * for runtime additions. - */ - virCommandAddArgPair(cmd, "--addn-hosts", - dctx->addnhostsfile->path); + if (!bootserver) { + virReportOOMError(); + goto cleanup; + } + virCommandAddArgFormat(cmd, "%s%s%s", + ipdef->bootfile, ",,", bootserver); + VIR_FREE(bootserver); + } else { + virCommandAddArg(cmd, ipdef->bootfile); + } + } + } + ipdef = (ipdef == ipv6def) ? NULL : ipv6def; + } - if (ipdef->tftproot) { - virCommandAddArgList(cmd, "--enable-tftp", - "--tftp-root", ipdef->tftproot, - NULL); + if (nbleases > 0) { + char *leasefile = networkDnsmasqLeaseFileName(network->def->name); + if (!leasefile) { + virReportOOMError(); + goto cleanup; } - if (ipdef->bootfile) { - virCommandAddArg(cmd, "--dhcp-boot"); - if (VIR_SOCKET_ADDR_VALID(&ipdef->bootserver)) { - char *bootserver = virSocketAddrFormat(&ipdef->bootserver); + virCommandAddArgFormat(cmd, "--dhcp-leasefile=%s", leasefile); + VIR_FREE(leasefile); + virCommandAddArgFormat(cmd, "--dhcp-lease-max=%d", nbleases); + } - if (!bootserver) - goto cleanup; - virCommandAddArgFormat(cmd, "%s%s%s", - ipdef->bootfile, ",,", bootserver); - VIR_FREE(bootserver); - } else { - virCommandAddArg(cmd, ipdef->bootfile); + /* this is done once per interface */ + if (networkBuildDnsmasqHostsList(dctx, network->def->dns) < 0) + goto cleanup; + + /* Even if there are currently no static hosts, if we're + * listening for DHCP, we should write a 0-length hosts + * file to allow for runtime additions. + */ + if (ipv4def || ipv6def) + virCommandAddArgPair(cmd, "--dhcp-hostsfile", + dctx->hostsfile->path); + + /* Likewise, always create this file and put it on the commandline, + * to allow for runtime additions. + */ + virCommandAddArgPair(cmd, "--addn-hosts", + dctx->addnhostsfile->path); + + /* Are we doing RA instead of radvd? */ + if (DNSMASQ_RA_SUPPORT(caps)) { + if (ipv6def) + virCommandAddArg(cmd, "--enable-ra"); + else { + for (ii = 0; + (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET6, ii)); + ii++) { + if (!(ipdef->nranges || ipdef->nhosts)) { + char *bridgeaddr = virSocketAddrFormat(&ipdef->address); + if (bridgeaddr) { + virCommandAddArgFormat(cmd, + "--dhcp-range=%s,ra-only", bridgeaddr); + } else + goto cleanup; + VIR_FREE(bridgeaddr); + } } } } ret = 0; + cleanup: VIR_FREE(record); VIR_FREE(recordPort); @@ -868,33 +970,12 @@ networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, virCommandPtr *cmdou dnsmasqCapsPtr caps) { virCommandPtr cmd = NULL; - int ret = -1, ii; - virNetworkIpDefPtr ipdef; + int ret = -1; network->dnsmasqPid = -1; - /* Look for first IPv4 address that has dhcp defined. */ - /* We support dhcp config on 1 IPv4 interface only. */ - for (ii = 0; - (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, ii)); - ii++) { - if (ipdef->nranges || ipdef->nhosts) - break; - } - /* If no IPv4 addresses had dhcp info, pick the first (if there were any). */ - if (!ipdef) - ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, 0); - - /* If there are no IP addresses at all (v4 or v6), return now, since - * there won't be any address for dnsmasq to listen on anyway. - * If there are any addresses, even if no dhcp ranges or static entries, - * we should continue and run dnsmasq, just for the DNS capabilities. - */ - if (!virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, 0)) - return 0; - cmd = virCommandNew(dnsmasqCapsGetBinaryPath(caps)); - if (networkBuildDnsmasqArgv(network, ipdef, pidfile, cmd, dctx, caps) < 0) { + if (networkBuildDnsmasqArgv(network, pidfile, cmd, dctx, caps) < 0) { goto cleanup; } @@ -915,11 +996,9 @@ networkStartDhcpDaemon(struct network_driver *driver, char *pidfile = NULL; int ret = -1; dnsmasqContext *dctx = NULL; - virNetworkIpDefPtr ipdef; - int i; if (!virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, 0)) { - /* no IPv6 addresses, so we don't need to run radvd */ + /* no IP addresses, so we don't need to run */ ret = 0; goto cleanup; } @@ -960,18 +1039,6 @@ networkStartDhcpDaemon(struct network_driver *driver, if (ret < 0) goto cleanup; - /* populate dnsmasq hosts file */ - for (i = 0; (ipdef = virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, i)); i++) { - if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET) && - (ipdef->nranges || ipdef->nhosts)) { - if (networkBuildDnsmasqHostsfile(dctx, ipdef, - network->def->dns) < 0) - goto cleanup; - - break; - } - } - ret = dnsmasqSave(dctx); if (ret < 0) goto cleanup; @@ -1004,7 +1071,8 @@ cleanup: /* networkRefreshDhcpDaemon: * Update dnsmasq config files, then send a SIGHUP so that it rereads - * them. + * them. This only works for the dhcp-hostsfile and the + * addn-hosts file. * * Returns 0 on success, -1 on failure. */ @@ -1013,34 +1081,51 @@ networkRefreshDhcpDaemon(struct network_driver *driver, virNetworkObjPtr network) { int ret = -1, ii; - virNetworkIpDefPtr ipdef; + virNetworkIpDefPtr ipdef, ipv4def, ipv6def; dnsmasqContext *dctx = NULL; + /* if no IP addresses specified, nothing to do */ + if (virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, 0)) + return 0; + /* if there's no running dnsmasq, just start it */ if (network->dnsmasqPid <= 0 || (kill(network->dnsmasqPid, 0) < 0)) return networkStartDhcpDaemon(driver, network); - /* Look for first IPv4 address that has dhcp defined. */ - /* We support dhcp config on 1 IPv4 interface only. */ + VIR_INFO("Refreshing dnsmasq for network %s", network->def->bridge); + if (!(dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR))) + goto cleanup; + + /* Look for first IPv4 address that has dhcp defined. + * We only support dhcp-host config on one IPv4 subnetwork + * and on one IPv6 subnetwork. + */ + ipv4def = NULL; for (ii = 0; (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, ii)); ii++) { - if (ipdef->nranges || ipdef->nhosts) - break; + if (!ipv4def && (ipdef->nranges || ipdef->nhosts)) + ipv4def = ipdef; } /* If no IPv4 addresses had dhcp info, pick the first (if there were any). */ if (!ipdef) ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, 0); - if (!ipdef) { - /* no <ip> elements, so nothing to do */ - return 0; + ipv6def = NULL; + for (ii = 0; + (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET6, ii)); + ii++) { + if (!ipv6def && (ipdef->nranges || ipdef->nhosts)) + ipv6def = ipdef; } - if (!(dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR))) - goto cleanup; + if (ipv4def && (networkBuildDnsmasqDhcpHostsList(dctx, ipv4def) < 0)) + goto cleanup; - if (networkBuildDnsmasqHostsfile(dctx, ipdef, network->def->dns) < 0) + if (ipv6def && (networkBuildDnsmasqDhcpHostsList(dctx, ipv6def) < 0)) + goto cleanup; + + if (networkBuildDnsmasqHostsList(dctx, network->def->dns) < 0) goto cleanup; if ((ret = dnsmasqSave(dctx)) < 0) @@ -1073,27 +1158,51 @@ networkRestartDhcpDaemon(struct network_driver *driver, return networkStartDhcpDaemon(driver, network); } +static char radvd1[] = " AdvOtherConfigFlag off;\n\n"; +static char radvd2[] = " AdvAutonomous off;\n"; +static char radvd3[] = " AdvOnLink on;\n" + " AdvAutonomous on;\n" + " AdvRouterAddr off;\n"; + static int networkRadvdConfContents(virNetworkObjPtr network, char **configstr) { virBuffer configbuf = VIR_BUFFER_INITIALIZER; int ret = -1, ii; virNetworkIpDefPtr ipdef; - bool v6present = false; + bool v6present = false, dhcp6 = false; *configstr = NULL; + /* Check if DHCPv6 is needed */ + for (ii = 0; + (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET6, ii)); + ii++) { + v6present = true; + if (ipdef->nranges || ipdef->nhosts) { + dhcp6 = true; + break; + } + } + + /* If there are no IPv6 addresses, then we are done */ + if (!v6present) { + ret = 0; + goto cleanup; + } + /* create radvd config file appropriate for this network; * IgnoreIfMissing allows radvd to start even when the bridge is down */ virBufferAsprintf(&configbuf, "interface %s\n" "{\n" " AdvSendAdvert on;\n" - " AdvManagedFlag off;\n" - " AdvOtherConfigFlag off;\n" " IgnoreIfMissing on;\n" - "\n", - network->def->bridge); + " AdvManagedFlag %s;\n" + "%s", + network->def->bridge, + dhcp6 ? "on" : "off", + dhcp6 ? "\n" : radvd1); /* add a section for each IPv6 address in the config */ for (ii = 0; @@ -1102,7 +1211,6 @@ networkRadvdConfContents(virNetworkObjPtr network, char **configstr) int prefix; char *netaddr; - v6present = true; prefix = virNetworkIpDefPrefix(ipdef); if (prefix < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -1114,12 +1222,9 @@ networkRadvdConfContents(virNetworkObjPtr network, char **configstr) goto cleanup; virBufferAsprintf(&configbuf, " prefix %s/%d\n" - " {\n" - " AdvOnLink on;\n" - " AdvAutonomous on;\n" - " AdvRouterAddr off;\n" - " };\n", - netaddr, prefix); + " {\n%s };\n", + netaddr, prefix, + dhcp6 ? radvd2 : radvd3); VIR_FREE(netaddr); } @@ -1185,7 +1290,8 @@ cleanup: } static int -networkStartRadvd(virNetworkObjPtr network) +networkStartRadvd(struct network_driver *driver ATTRIBUTE_UNUSED, + virNetworkObjPtr network) { char *pidfile = NULL; char *radvdpidbase = NULL; @@ -1195,6 +1301,12 @@ networkStartRadvd(virNetworkObjPtr network) network->radvdPid = -1; + /* Is dnsmasq handling RA? */ + if (DNSMASQ_RA_SUPPORT(driver->dnsmasqCaps)) { + ret = 0; + goto cleanup; + } + if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) { /* no IPv6 addresses, so we don't need to run radvd */ ret = 0; @@ -1271,9 +1383,18 @@ static int networkRefreshRadvd(struct network_driver *driver ATTRIBUTE_UNUSED, virNetworkObjPtr network) { + /* Is dnsmasq handling RA? */ + if (DNSMASQ_RA_SUPPORT(driver->dnsmasqCaps)) { + if (network->radvdPid <= 0) + return 0; + else /* radvd should not be running but in case it is */ + kill(network->radvdPid, 0); + return 0; + } + /* if there's no running radvd, just start it */ if (network->radvdPid <= 0 || (kill(network->radvdPid, 0) < 0)) - return networkStartRadvd(network); + return networkStartRadvd(driver, network); if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) { /* no IPv6 addresses, so we don't need to run radvd */ @@ -1594,11 +1715,9 @@ networkRemoveRoutingIptablesRules(struct network_driver *driver, } /* Add all once/network rules required for IPv6. - * If no IPv6 addresses are defined and <network ipv6='yes'> is - * specified, then allow IPv6 commuinications between guests connected - * to this network. If any IPv6 addresses are defined, then add all - * rules for regular operation (including inter-guest communication). + * specified, then allow IPv6 commuinications between virtual systems. + * If any IPv6 addresses are defined, then add the rules for regular operation. */ static int networkAddGeneralIp6tablesRules(struct network_driver *driver, @@ -1606,9 +1725,8 @@ networkAddGeneralIp6tablesRules(struct network_driver *driver, { if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0) && - !network->def->ipv6nogw) { + !network->def->ipv6nogw) return 0; - } /* Catch all rules to block forwarding to/from bridges */ @@ -1658,9 +1776,19 @@ networkAddGeneralIp6tablesRules(struct network_driver *driver, goto err5; } + if (iptablesAddUdpInput(driver->iptables, AF_INET6, + network->def->bridge, 547) < 0) { + virReportError(VIR_ERR_SYSTEM_ERROR, + _("failed to add ip6tables rule to allow DHCP6 requests from '%s'"), + network->def->bridge); + goto err6; + } + return 0; /* unwind in reverse order from the point of failure */ +err6: + iptablesRemoveUdpInput(driver->iptables, AF_INET6, network->def->bridge, 53); err5: iptablesRemoveTcpInput(driver->iptables, AF_INET6, network->def->bridge, 53); err4: @@ -1681,6 +1809,7 @@ networkRemoveGeneralIp6tablesRules(struct network_driver *driver, !network->def->ipv6nogw) return; if (virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) { + iptablesRemoveUdpInput(driver->iptables, AF_INET6, network->def->bridge, 547); iptablesRemoveUdpInput(driver->iptables, AF_INET6, network->def->bridge, 53); iptablesRemoveTcpInput(driver->iptables, AF_INET6, network->def->bridge, 53); } @@ -2272,7 +2401,7 @@ networkStartNetworkVirtual(struct network_driver *driver, goto err3; /* start radvd if there are any ipv6 addresses */ - if (v6present && networkStartRadvd(network) < 0) + if (v6present && networkStartRadvd(driver, network) < 0) goto err4; /* DAD has happened (dnsmasq waits for it), dnsmasq is now bound to the @@ -2733,8 +2862,7 @@ networkValidate(struct network_driver *driver, bool vlanUsed, vlanAllowed, badVlanUse = false; virPortGroupDefPtr defaultPortGroup = NULL; virNetworkIpDefPtr ipdef; - bool ipv4def = false; - int i; + bool ipv4def = false, ipv6def = false; /* check for duplicate networks */ if (virNetworkObjIsDuplicate(&driver->networks, def, check_active) < 0) @@ -2782,17 +2910,36 @@ networkValidate(struct network_driver *driver, } } - /* We only support dhcp on one IPv4 address per defined network */ - for (i = 0; (ipdef = virNetworkDefGetIpByIndex(def, AF_INET, i)); i++) { - if (ipdef->nranges || ipdef->nhosts) { - if (ipv4def) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Multiple dhcp sections found. " + /* We only support dhcp on one IPv4 address and + * on one IPv6 address per defined network + */ + for (ii = 0; + (ipdef = virNetworkDefGetIpByIndex(def, AF_UNSPEC, ii)); + ii++) { + if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET)) { + if (ipdef->nranges || ipdef->nhosts) { + if (ipv4def) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Multiple IPv4 dhcp sections found -- " "dhcp is supported only for a " "single IPv4 address on each network")); - return -1; - } else { - ipv4def = true; + return -1; + } else { + ipv4def = true; + } + } + } + if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) { + if (ipdef->nranges || ipdef->nhosts) { + if (ipv6def) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Multiple IPv6 dhcp sections found -- " + "dhcp is supported only for a " + "single IPv6 address on each network")); + return -1; + } else { + ipv6def = true; + } } } } diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c index 4f210d2..a9f5520 100644 --- a/src/util/dnsmasq.c +++ b/src/util/dnsmasq.c @@ -293,11 +293,15 @@ hostsfileFree(dnsmasqHostsfile *hostsfile) VIR_FREE(hostsfile); } +/* Note: There are many additional dhcp-host specifications + * supported by dnsmasq. There are only the basic ones. + */ static int hostsfileAdd(dnsmasqHostsfile *hostsfile, const char *mac, virSocketAddr *ip, - const char *name) + const char *name, + bool ipv6) { char *ipstr = NULL; if (VIR_REALLOC_N(hostsfile->hosts, hostsfile->nhosts + 1) < 0) @@ -306,16 +310,24 @@ hostsfileAdd(dnsmasqHostsfile *hostsfile, if (!(ipstr = virSocketAddrFormat(ip))) return -1; - if (name) { + /* the first test determines if it is a dhcpv6 host */ + if (ipv6) { + if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,[%s]", + name, ipstr) < 0) + goto alloc_error; + } + else if (name && mac) { if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s,%s", - mac, ipstr, name) < 0) { + mac, ipstr, name) < 0) + goto alloc_error; + } else if (name && !mac){ + if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s", + name, ipstr) < 0) goto alloc_error; - } } else { if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s", - mac, ipstr) < 0) { + mac, ipstr) < 0) goto alloc_error; - } } VIR_FREE(ipstr); @@ -496,9 +508,10 @@ int dnsmasqAddDhcpHost(dnsmasqContext *ctx, const char *mac, virSocketAddr *ip, - const char *name) + const char *name, + bool ipv6) { - return hostsfileAdd(ctx->hostsfile, mac, ip, name); + return hostsfileAdd(ctx->hostsfile, mac, ip, name, ipv6); } /* diff --git a/src/util/dnsmasq.h b/src/util/dnsmasq.h index e8881a0..ec1dfb1 100644 --- a/src/util/dnsmasq.h +++ b/src/util/dnsmasq.h @@ -82,7 +82,8 @@ void dnsmasqContextFree(dnsmasqContext *ctx); int dnsmasqAddDhcpHost(dnsmasqContext *ctx, const char *mac, virSocketAddr *ip, - const char *name); + const char *name, + bool ipv6); int dnsmasqAddHost(dnsmasqContext *ctx, virSocketAddr *ip, const char *name); @@ -99,4 +100,18 @@ int dnsmasqCapsRefresh(dnsmasqCapsPtr *caps, const char *binaryPath); bool dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags flag); const char *dnsmasqCapsGetBinaryPath(dnsmasqCapsPtr caps); unsigned long dnsmasqCapsGetVersion(dnsmasqCapsPtr caps); + +#define DNSMASQ_DHCPv6_MAJOR_REQD 2 +#define DNSMASQ_DHCPv6_MINOR_REQD 64 +#define DNSMQASQ_RA_MAJOR_REQD 2 +#define DNSMSAQ_RA_MINOR_REQD 64 + +#define DNSMASQ_DHCPv6_SUPPORT(CAPS) \ + (dnsmasqCapsGetVersion(CAPS) >= \ + (DNSMASQ_DHCPv6_MAJOR_REQD * 1000000) + \ + (DNSMASQ_DHCPv6_MINOR_REQD * 1000)) +#define DNSMASQ_RA_SUPPORT(CAPS) \ + (dnsmasqCapsGetVersion(CAPS) >= \ + (DNSMASQ_RA_MAJOR_REQD * 1000000) + \ + (DNSMASQ_RA_MINOR_REQD * 1000)) #endif /* __DNSMASQ_H__ */ diff --git a/tests/networkxml2argvdata/dhcp6-nat-network.argv b/tests/networkxml2argvdata/dhcp6-nat-network.argv new file mode 100644 index 0000000..df8c507 --- /dev/null +++ b/tests/networkxml2argvdata/dhcp6-nat-network.argv @@ -0,0 +1,15 @@ +@DNSMASQ@ \ +--strict-order \ +--domain-needed \ +--local=// \ +--conf-file= \ +--bind-dynamic \ +--interface virbr0 \ +--dhcp-range 192.168.122.2,192.168.122.254 \ +--dhcp-no-override \ +--dhcp-range 2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff \ +--dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases \ +--dhcp-lease-max=493 \ +--dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile \ +--addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts \ +--enable-ra\ diff --git a/tests/networkxml2argvdata/dhcp6-nat-network.xml b/tests/networkxml2argvdata/dhcp6-nat-network.xml new file mode 100644 index 0000000..72103f7 --- /dev/null +++ b/tests/networkxml2argvdata/dhcp6-nat-network.xml @@ -0,0 +1,24 @@ +<network> + <name>default</name> + <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> + <forward dev='eth1' mode='nat'/> + <bridge name='virbr0' stp='on' delay='0' /> + <ip address='192.168.122.1' netmask='255.255.255.0'> + <dhcp> + <range start='192.168.122.2' end='192.168.122.254' /> + <host mac='00:16:3e:77:e2:ed' name='a.example.com' ip='192.168.122.10' /> + <host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' /> + </dhcp> + </ip> + <ip family='ipv4' address='192.168.123.1' netmask='255.255.255.0'> + </ip> + <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'> + <dhcp> + <range start='2001:db8:ac10:fd01::1:10' end='2001:db8:ac10:fd01::1:ff' /> + <host name='ralph' ip='2001:db8:ac10:fd01::1:20' /> + <host name='paul' ip='2001:db8:ac10:fd01::1:21' /> + </dhcp> + </ip> + <ip family='ipv4' address='10.24.10.1'> + </ip> +</network> diff --git a/tests/networkxml2argvdata/dhcp6-network.argv b/tests/networkxml2argvdata/dhcp6-network.argv new file mode 100644 index 0000000..059c418 --- /dev/null +++ b/tests/networkxml2argvdata/dhcp6-network.argv @@ -0,0 +1,15 @@ +@DNSMASQ@ \ +--strict-order \ +--domain-needed \ +--domain=mynet \ +--expand-hosts \ +--local=/mynet/ \ +--conf-file= \ +--bind-dynamic \ +--interface virbr0 \ +--dhcp-range 2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff \ +--dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases \ +--dhcp-lease-max=240 \ +--dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile \ +--addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts \ +--enable-ra\ diff --git a/tests/networkxml2argvdata/dhcp6-network.xml b/tests/networkxml2argvdata/dhcp6-network.xml new file mode 100644 index 0000000..311013a --- /dev/null +++ b/tests/networkxml2argvdata/dhcp6-network.xml @@ -0,0 +1,14 @@ +<network> + <name>default</name> + <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> + <forward dev='eth1' mode='nat'/> + <bridge name='virbr0' stp='on' delay='0' /> + <domain name='mynet'/> + <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'> + <dhcp> + <range start='2001:db8:ac10:fd01::1:10' end='2001:db8:ac10:fd01::1:ff' /> + <host name='ralph' ip='2001:db8:ac10:fd01::1:20' /> + <host name='paul' ip='2001:db8:ac10:fd01::1:21' /> + </dhcp> + </ip> +</network> diff --git a/tests/networkxml2argvdata/dhcp6host-routed-network.argv b/tests/networkxml2argvdata/dhcp6host-routed-network.argv new file mode 100644 index 0000000..8f6d7d3 --- /dev/null +++ b/tests/networkxml2argvdata/dhcp6host-routed-network.argv @@ -0,0 +1,13 @@ +@DNSMASQ@ \ +--strict-order \ +--domain-needed \ +--local=// \ +--conf-file= \ +--bind-dynamic \ +--interface virbr1 \ +--dhcp-range 192.168.122.1,static \ +--dhcp-no-override \ +--dhcp-range 2001:db8:ac10:fd01::1,static \ +--dhcp-hostsfile=/var/lib/libvirt/dnsmasq/local.hostsfile \ +--addn-hosts=/var/lib/libvirt/dnsmasq/local.addnhosts \ +--enable-ra\ diff --git a/tests/networkxml2argvdata/dhcp6host-routed-network.xml b/tests/networkxml2argvdata/dhcp6host-routed-network.xml new file mode 100644 index 0000000..38d9ebf --- /dev/null +++ b/tests/networkxml2argvdata/dhcp6host-routed-network.xml @@ -0,0 +1,19 @@ +<network> + <name>local</name> + <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid> + <forward dev='eth1' mode='route'/> + <bridge name='virbr1' stp='on' delay='0' /> + <mac address='12:34:56:78:9A:BC'/> + <ip address='192.168.122.1' netmask='255.255.255.0'> + <dhcp> + <host mac='00:16:3e:77:e2:ed' name='a.example.com' ip='192.168.122.10' /> + <host mac='00:16:3e:3e:a9:1a' name='b.example.com' ip='192.168.122.11' /> + </dhcp> + </ip> + <ip family='ipv6' address='2001:db8:ac10:fd01::1' prefix='64'> + <dhcp> + <host name='ralph' ip='2001:db8:ac10:fd01::1:20' /> + <host name='paul' ip='2001:db8:ac10:fd01::1:21' /> + </dhcp> + </ip> +</network> diff --git a/tests/networkxml2argvdata/isolated-network.argv b/tests/networkxml2argvdata/isolated-network.argv index 3d8601e..b0783bd 100644 --- a/tests/networkxml2argvdata/isolated-network.argv +++ b/tests/networkxml2argvdata/isolated-network.argv @@ -1,10 +1,16 @@ -@DNSMASQ@ --strict-order \ ---local=// --domain-needed --conf-file= \ ---bind-interfaces --except-interface lo \ +@DNSMASQ@ \ +--strict-order \ +--domain-needed \ +--local=// \ +--conf-file= \ +--bind-interfaces \ +--except-interface=lo \ --listen-address 192.168.152.1 \ ---dhcp-option=3 --no-resolv \ +--dhcp-option=3 \ +--no-resolv \ --dhcp-range 192.168.152.2,192.168.152.254 \ ---dhcp-leasefile=/var/lib/libvirt/dnsmasq/private.leases --dhcp-lease-max=253 \ --dhcp-no-override \ +--dhcp-leasefile=/var/lib/libvirt/dnsmasq/private.leases \ +--dhcp-lease-max=253 \ --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/private.hostsfile \ --addn-hosts=/var/lib/libvirt/dnsmasq/private.addnhosts\ diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.argv b/tests/networkxml2argvdata/nat-network-dns-hosts.argv index e5143ac..fee137f 100644 --- a/tests/networkxml2argvdata/nat-network-dns-hosts.argv +++ b/tests/networkxml2argvdata/nat-network-dns-hosts.argv @@ -1,5 +1,10 @@ -@DNSMASQ@ --strict-order --domain=example.com \ ---local=/example.com/ --domain-needed \ +@DNSMASQ@ \ +--strict-order \ +--domain-needed \ +--domain=example.com \ +--expand-hosts \ +--local=/example.com/ \ --conf-file= \ ---bind-dynamic --interface virbr0 \ ---expand-hosts --addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts\ +--bind-dynamic \ +--interface virbr0 \ +--addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts\ diff --git a/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv b/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv index 031da3f..1de6637 100644 --- a/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv +++ b/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv @@ -1,7 +1,10 @@ @DNSMASQ@ \ --strict-order \ ---local=// --domain-needed --conf-file= \ ---bind-interfaces --except-interface lo \ +--domain-needed \ +--local=// \ +--conf-file= \ +--bind-interfaces \ +--except-interface=lo \ --listen-address 192.168.122.1 \ --listen-address 192.168.123.1 \ --listen-address fc00:db8:ac10:fe01::1 \ @@ -9,8 +12,8 @@ --listen-address 10.24.10.1 \ --srv-host=name.tcp.,,,, \ --dhcp-range 192.168.122.2,192.168.122.254 \ +--dhcp-no-override \ --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases \ --dhcp-lease-max=253 \ ---dhcp-no-override \ --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile \ --addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts\ diff --git a/tests/networkxml2argvdata/nat-network-dns-srv-record.argv b/tests/networkxml2argvdata/nat-network-dns-srv-record.argv index beff591..e7ecaa5 100644 --- a/tests/networkxml2argvdata/nat-network-dns-srv-record.argv +++ b/tests/networkxml2argvdata/nat-network-dns-srv-record.argv @@ -1,11 +1,14 @@ @DNSMASQ@ \ --strict-order \ ---local=// --domain-needed --conf-file= \ ---bind-dynamic --interface virbr0 \ +--domain-needed \ +--local=// \ +--conf-file= \ +--bind-dynamic \ +--interface virbr0 \ --srv-host=name.tcp.test-domain-name,.,1024,10,10 \ --dhcp-range 192.168.122.2,192.168.122.254 \ +--dhcp-no-override \ --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases \ --dhcp-lease-max=253 \ ---dhcp-no-override \ --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile \ --addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts\ diff --git a/tests/networkxml2argvdata/nat-network-dns-txt-record.argv b/tests/networkxml2argvdata/nat-network-dns-txt-record.argv index fc164f6..8ea0004 100644 --- a/tests/networkxml2argvdata/nat-network-dns-txt-record.argv +++ b/tests/networkxml2argvdata/nat-network-dns-txt-record.argv @@ -1,9 +1,13 @@ -@DNSMASQ@ --strict-order \ ---local=// --domain-needed --conf-file= \ +@DNSMASQ@ \ +--strict-order \ +--domain-needed \ +--local=// \ +--conf-file= \ --bind-dynamic --interface virbr0 \ '--txt-record=example,example value' \ --dhcp-range 192.168.122.2,192.168.122.254 \ +--dhcp-no-override \ --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases \ ---dhcp-lease-max=253 --dhcp-no-override \ +--dhcp-lease-max=253 \ --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile \ --addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts\ diff --git a/tests/networkxml2argvdata/nat-network.argv b/tests/networkxml2argvdata/nat-network.argv index 6303f76..578a5ff 100644 --- a/tests/networkxml2argvdata/nat-network.argv +++ b/tests/networkxml2argvdata/nat-network.argv @@ -1,8 +1,15 @@ -@DNSMASQ@ --strict-order \ ---local=// --domain-needed --conf-file= \ ---bind-dynamic --interface virbr0 \ +@DNSMASQ@ \ +--strict-order \ +--domain-needed \ +--local=// \ +--conf-file= \ +--bind-dynamic \ +--interface virbr0 \ --dhcp-range 192.168.122.2,192.168.122.254 \ +--dhcp-no-override \ --dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases \ ---dhcp-lease-max=253 --dhcp-no-override \ +--dhcp-lease-max=253 \ --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile \ ---addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts\ +--addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts \ +--dhcp-range=2001:db8:ac10:fe01::1,ra-only \ +--dhcp-range=2001:db8:ac10:fd01::1,ra-only\ diff --git a/tests/networkxml2argvdata/netboot-network.argv b/tests/networkxml2argvdata/netboot-network.argv index 9699e5c..c5b75a3 100644 --- a/tests/networkxml2argvdata/netboot-network.argv +++ b/tests/networkxml2argvdata/netboot-network.argv @@ -1,10 +1,19 @@ -@DNSMASQ@ --strict-order --domain=example.com \ ---local=/example.com/ --domain-needed --conf-file= \ ---bind-interfaces --except-interface lo --listen-address 192.168.122.1 \ +@DNSMASQ@ \ +--strict-order \ +--domain-needed \ +--domain=example.com \ +--expand-hosts \ +--local=/example.com/ \ +--conf-file= \ +--bind-interfaces \ +--except-interface=lo \ +--listen-address 192.168.122.1 \ --dhcp-range 192.168.122.2,192.168.122.254 \ +--dhcp-no-override \ +--enable-tftp \ +--tftp-root /var/lib/tftproot \ +--dhcp-boot pxeboot.img \ --dhcp-leasefile=/var/lib/libvirt/dnsmasq/netboot.leases \ ---dhcp-lease-max=253 --dhcp-no-override --expand-hosts \ +--dhcp-lease-max=253 \ --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/netboot.hostsfile \ ---addn-hosts=/var/lib/libvirt/dnsmasq/netboot.addnhosts \ ---enable-tftp \ ---tftp-root /var/lib/tftproot --dhcp-boot pxeboot.img\ +--addn-hosts=/var/lib/libvirt/dnsmasq/netboot.addnhosts\ diff --git a/tests/networkxml2argvdata/netboot-proxy-network.argv b/tests/networkxml2argvdata/netboot-proxy-network.argv index 9ac3018..16e1c85 100644 --- a/tests/networkxml2argvdata/netboot-proxy-network.argv +++ b/tests/networkxml2argvdata/netboot-proxy-network.argv @@ -1,10 +1,17 @@ -@DNSMASQ@ --strict-order --domain=example.com \ ---local=/example.com/ --domain-needed --conf-file= \ ---bind-interfaces --except-interface lo \ +@DNSMASQ@ \ +--strict-order \ +--domain-needed \ +--domain=example.com \ +--expand-hosts \ +--local=/example.com/ \ +--conf-file= \ +--bind-interfaces \ +--except-interface=lo \ --listen-address 192.168.122.1 \ --dhcp-range 192.168.122.2,192.168.122.254 \ +--dhcp-no-override \ +--dhcp-boot pxeboot.img,,10.20.30.40 \ --dhcp-leasefile=/var/lib/libvirt/dnsmasq/netboot.leases \ ---dhcp-lease-max=253 --dhcp-no-override --expand-hosts \ +--dhcp-lease-max=253 \ --dhcp-hostsfile=/var/lib/libvirt/dnsmasq/netboot.hostsfile \ ---addn-hosts=/var/lib/libvirt/dnsmasq/netboot.addnhosts \ ---dhcp-boot pxeboot.img,,10.20.30.40\ +--addn-hosts=/var/lib/libvirt/dnsmasq/netboot.addnhosts\ diff --git a/tests/networkxml2argvdata/routed-network.argv b/tests/networkxml2argvdata/routed-network.argv index 700c904..b3fbf49 100644 --- a/tests/networkxml2argvdata/routed-network.argv +++ b/tests/networkxml2argvdata/routed-network.argv @@ -1,4 +1,8 @@ -@DNSMASQ@ --strict-order \ ---local=// --domain-needed --conf-file= \ ---bind-dynamic --interface virbr1 \ +@DNSMASQ@ \ +--strict-order \ +--domain-needed \ +--local=// \ +--conf-file= \ +--bind-dynamic \ +--interface virbr1 \ --addn-hosts=/var/lib/libvirt/dnsmasq/local.addnhosts\ diff --git a/tests/networkxml2argvtest.c b/tests/networkxml2argvtest.c index 69cbd1c..a020db9 100644 --- a/tests/networkxml2argvtest.c +++ b/tests/networkxml2argvtest.c @@ -152,6 +152,8 @@ mymain(void) = dnsmasqCapsNewFromBuffer("Dnsmasq version 2.48", DNSMASQ); dnsmasqCapsPtr full = dnsmasqCapsNewFromBuffer("Dnsmasq version 2.63\n--bind-dynamic", DNSMASQ); + dnsmasqCapsPtr dhcpv6 + = dnsmasqCapsNewFromBuffer("Dnsmasq version 2.64\n--bind-dynamic", DNSMASQ); networkDnsmasqLeaseFileName = testDnsmasqLeaseFileName; @@ -172,10 +174,13 @@ mymain(void) DO_TEST("netboot-proxy-network", restricted); DO_TEST("nat-network-dns-srv-record-minimal", restricted); DO_TEST("routed-network", full); - DO_TEST("nat-network", full); + DO_TEST("nat-network", dhcpv6); DO_TEST("nat-network-dns-txt-record", full); DO_TEST("nat-network-dns-srv-record", full); DO_TEST("nat-network-dns-hosts", full); + DO_TEST("dhcp6-network", dhcpv6); + DO_TEST("dhcp6-nat-network", dhcpv6); + DO_TEST("dhcp6host-routed-network", dhcpv6); return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 1.7.11.7

On 12/06/2012 12:20 PM, Gene Czarcinski wrote:
Updated and rebased 06 Dec 2012.
The DHCPv6 support includes IPV6 dhcp-range and dhcp-host for one IPv6 subnetwork on one interface. This support will only work if dnsmasq version >= 2.64; otherwise an error occurs if dhcp-range or dhcp-host is specified.
Essentially, this change provides the same DHCP support for IPv6 that has been available for IPv4.
With dnsmasq >= 2.64, support for the RA service is now provided by dnsmasq (radvd is no longer used/started).
Dnsmasq 2.64 does contain the bugfixes released to DHCPv6 and dnsmasq's handling of Router Advertisement.
Documentation and the network schema has been updated to reflect the new support.
This version of the DHCPv6 patch files includes the changes from Laine Stump's review.
Yep, got every point as far as I could see. I reworded the documentation a bit, and moved networkxml2argv* to networkxml2conf* (both the program and the data directory), rebased on top of latest master, and pushed. Thanks for the long hours you put into this. With all the debugging of dnsmasq you had to do, this definitely took longer than the average new feature.

Updated per Laine Stump's review commands and rebased 6 Dec 2012. This patch changes how parameters are passed to dnsmasq. Instead of being on the command line, the parameters are put into a file (one parameter per line) and a commandline --conf-file= specifies the location of the file. The file is located in the same directory as the leases file. Putting the dnsmasq parameters into a configuration file allows them to be examined and more easily understood than examining the command lines displayed by "ps ax". This is especially true when a number of networks have been started. I suspect that when the use of dnsmasq was originally done, the command line was simple but has gotten more complicated over time and will likely become even more complicated in the future. I believe that if use of dnsmasq was done today with the current requirements for dnsmasq, a configuration file would have been used. Many (most?) daemons use configuration files as oppose to large number of command line parameters. One potential addition to dnsmasq parameters is to specify the reverse-lookup queries which are not to be passed on up the chain. For IPv4, such queries are rather simple and take the form: <ipv4_address>.in-addr.arpa but ipv6 queries involve a lot longer specification. The IPv6 query will be of the form: <ipv6_address>.ip6.arpa where the above query expands to a 44 character string which is specified by --local=/<ipv6_address>.ip6.arpa/ which is certainly a lot of clutter to add to the command line. Note: The test conf files have all been renamed .conf instead of .argv. --- src/network/bridge_driver.c | 189 +++++++++++++-------- src/network/bridge_driver.h | 13 +- src/util/dnsmasq.h | 4 +- tests/networkxml2argvdata/dhcp6-nat-network.argv | 15 -- tests/networkxml2argvdata/dhcp6-nat-network.conf | 19 +++ tests/networkxml2argvdata/dhcp6-network.argv | 15 -- tests/networkxml2argvdata/dhcp6-network.conf | 19 +++ .../dhcp6host-routed-network.argv | 13 -- .../dhcp6host-routed-network.conf | 17 ++ tests/networkxml2argvdata/isolated-network.argv | 16 -- tests/networkxml2argvdata/isolated-network.conf | 20 +++ .../networkxml2argvdata/nat-network-dns-hosts.argv | 10 -- .../networkxml2argvdata/nat-network-dns-hosts.conf | 14 ++ .../nat-network-dns-srv-record-minimal.argv | 19 --- .../nat-network-dns-srv-record-minimal.conf | 23 +++ .../nat-network-dns-srv-record.argv | 14 -- .../nat-network-dns-srv-record.conf | 18 ++ .../nat-network-dns-txt-record.argv | 13 -- .../nat-network-dns-txt-record.conf | 18 ++ tests/networkxml2argvdata/nat-network.argv | 15 -- tests/networkxml2argvdata/nat-network.conf | 19 +++ tests/networkxml2argvdata/netboot-network.argv | 19 --- tests/networkxml2argvdata/netboot-network.conf | 23 +++ .../networkxml2argvdata/netboot-proxy-network.argv | 17 -- .../networkxml2argvdata/netboot-proxy-network.conf | 21 +++ tests/networkxml2argvdata/routed-network.argv | 8 - tests/networkxml2argvdata/routed-network.conf | 12 ++ tests/networkxml2argvtest.c | 42 +---- 28 files changed, 349 insertions(+), 296 deletions(-) delete mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.argv create mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.conf delete mode 100644 tests/networkxml2argvdata/dhcp6-network.argv create mode 100644 tests/networkxml2argvdata/dhcp6-network.conf delete mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.argv create mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.conf delete mode 100644 tests/networkxml2argvdata/isolated-network.argv create mode 100644 tests/networkxml2argvdata/isolated-network.conf delete mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.conf delete mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.conf delete mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record.conf delete mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.conf delete mode 100644 tests/networkxml2argvdata/nat-network.argv create mode 100644 tests/networkxml2argvdata/nat-network.conf delete mode 100644 tests/networkxml2argvdata/netboot-network.argv create mode 100644 tests/networkxml2argvdata/netboot-network.conf delete mode 100644 tests/networkxml2argvdata/netboot-proxy-network.argv create mode 100644 tests/networkxml2argvdata/netboot-proxy-network.conf delete mode 100644 tests/networkxml2argvdata/routed-network.argv create mode 100644 tests/networkxml2argvdata/routed-network.conf diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index c64baf7..51490e4 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -137,6 +137,16 @@ networkDnsmasqLeaseFileNameFunc networkDnsmasqLeaseFileName = networkDnsmasqLeaseFileNameDefault; static char * +networkDnsmasqConfigFileName(const char *netname) +{ + char *conffile; + + ignore_value(virAsprintf(&conffile, DNSMASQ_STATE_DIR "/%s.conf", + netname)); + return conffile; +} + +static char * networkRadvdPidfileBasename(const char *netname) { /* this is simple but we want to be sure it's consistently done */ @@ -163,6 +173,7 @@ networkRemoveInactive(struct network_driver *driver, { char *leasefile = NULL; char *radvdconfigfile = NULL; + char *configfile = NULL; char *radvdpidbase = NULL; dnsmasqContext *dctx = NULL; virNetworkDefPtr def = virNetworkObjGetPersistentDef(net); @@ -182,9 +193,13 @@ networkRemoveInactive(struct network_driver *driver, if (!(radvdpidbase = networkRadvdPidfileBasename(def->name))) goto no_memory; + if (!(configfile = networkDnsmasqConfigFileName(def->name))) + goto no_memory; + /* dnsmasq */ dnsmasqDelete(dctx); unlink(leasefile); + unlink(configfile); /* radvd */ unlink(radvdconfigfile); @@ -197,6 +212,7 @@ networkRemoveInactive(struct network_driver *driver, cleanup: VIR_FREE(leasefile); + VIR_FREE(configfile); VIR_FREE(radvdconfigfile); VIR_FREE(radvdpidbase); dnsmasqContextFree(dctx); @@ -608,13 +624,14 @@ networkBuildDnsmasqHostsList(dnsmasqContext *dctx, } -static int -networkBuildDnsmasqArgv(virNetworkObjPtr network, +int +networkDnsmasqConfContents(virNetworkObjPtr network, const char *pidfile, - virCommandPtr cmd, + char **configstr, dnsmasqContext *dctx, dnsmasqCapsPtr caps ATTRIBUTE_UNUSED) { + virBuffer configbuf = VIR_BUFFER_INITIALIZER; int r, ret = -1; int nbleases = 0; int ii; @@ -625,46 +642,48 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, virNetworkIpDefPtr tmpipdef, ipdef, ipv4def, ipv6def; bool ipv6SLAAC; + *configstr = NULL; + /* - * NB, be careful about syntax for dnsmasq options in long format. - * - * If the flag has a mandatory argument, it can be given using - * either syntax: + * All dnsmasq parameters are put into a configuration file, except the + * command line --conf-file=parameter which specifies the location of + * configuration file. * - * --foo bar - * --foo=bar - * - * If the flag has a optional argument, it *must* be given using - * the syntax: - * - * --foo=bar - * - * It is hard to determine whether a flag is optional or not, - * without reading the dnsmasq source :-( The manpage is not - * very explicit on this. + * All dnsmasq conf-file parameters must be specified as "foo=bar" + * as oppose to "--foo bar" which was acceptable on the command line. */ /* * Needed to ensure dnsmasq uses same algorithm for processing * multiple namedriver entries in /etc/resolv.conf as GLibC. */ - virCommandAddArgList(cmd, "--strict-order", - "--domain-needed", - NULL); - - if (network->def->domain) { - virCommandAddArgPair(cmd, "--domain", network->def->domain); - virCommandAddArg(cmd, "--expand-hosts"); - } - /* need to specify local even if no domain specified */ - virCommandAddArgFormat(cmd, "--local=/%s/", - network->def->domain ? network->def->domain : ""); - if (pidfile) - virCommandAddArgPair(cmd, "--pid-file", pidfile); - - /* *no* conf file */ - virCommandAddArg(cmd, "--conf-file="); + /* create dnsmasq config file appropriate for this network */ + virBufferAsprintf(&configbuf, + "##WARNING: THIS IS AN AUTO-GENERATED FILE. " + "CHANGES TO IT ARE LIKELY TO BE\n" + "##OVERWRITTEN AND LOST. Changes to this " + "configuration should be made using:\n" + "## virsh net-edit %s\n" + "## of other applications using the libvirt API.\n" + "##\n## dnsmasq conf file created by libvirt\n" + "strict-order\n" + "domain-needed\n", + network->def->name); + + if (network->def->domain) { + virBufferAsprintf(&configbuf, + "domain=%s\n" + "expand-hosts\n", + network->def->domain); + } + /* need to specify local even if no domain specified */ + virBufferAsprintf(&configbuf, + "local=/%s/\n", + network->def->domain ? network->def->domain : ""); + + if (pidfile) + virBufferAsprintf(&configbuf, "pid-file=%s\n", pidfile); if (dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC)) { /* using --bind-dynamic with only --interface (no @@ -674,15 +693,14 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, * other than one of the virtual guests connected directly to * this network). This was added in response to CVE 2012-3411. */ - virCommandAddArgList(cmd, - "--bind-dynamic", - "--interface", network->def->bridge, - NULL); + virBufferAsprintf(&configbuf, + "bind-dynamic\n" + "interface=%s\n", + network->def->bridge); } else { - virCommandAddArgList(cmd, - "--bind-interfaces", - "--except-interface=lo", - NULL); + virBufferAddLit(&configbuf, + "bind-interfaces\n" + "except-interface=lo\n"); /* * --interface does not actually work with dnsmasq < 2.47, * due to DAD for ipv6 addresses on the interface. @@ -699,7 +717,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, if (!ipaddr) goto cleanup; /* also part of CVE 2012-3411 - if the host's version of - * dnsmasq doesn't have --bind-dynamic, only allow listening on + * dnsmasq doesn't have bind-dynamic, only allow listening on * private/local IP addresses (see RFC1918/RFC3484/RFC4193) */ if (!virSocketAddrIsPrivate(&tmpipdef->address)) { @@ -708,7 +726,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Publicly routable address %s is prohibited. " "The version of dnsmasq on this host (%d.%d) doesn't " - "support the --bind-dynamic option, which is required " + "support the bind-dynamic option, which is required " "for safe operation on a publicly routable subnet " "(see CVE-2012-3411). You must either upgrade dnsmasq, " "or use a private/local subnet range for this network " @@ -716,21 +734,21 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, (int)version / 1000000, (int)(version % 1000000) / 1000); goto cleanup; } - virCommandAddArgList(cmd, "--listen-address", ipaddr, NULL); + virBufferAsprintf(&configbuf, "listen-address=%s\n", ipaddr); VIR_FREE(ipaddr); } } /* If this is an isolated network, set the default route option * (3) to be empty to avoid setting a default route that's - * guaranteed to not work, and set --no-resolv so that no dns + * guaranteed to not work, and set no-resolv so that no dns * requests are forwarded on to the dns server listed in the * host's /etc/resolv.conf (since this could be used as a channel * to build a connection to the outside). */ if (network->def->forwardType == VIR_NETWORK_FORWARD_NONE) { - virCommandAddArgList(cmd, "--dhcp-option=3", - "--no-resolv", NULL); + virBufferAddLit(&configbuf, "dhcp-option=3\n" + "no-resolv\n"); } if (network->def->dns != NULL) { @@ -738,7 +756,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, int i; for (i = 0; i < dns->ntxtrecords; i++) { - virCommandAddArgFormat(cmd, "--txt-record=%s,%s", + virBufferAsprintf(&configbuf, "txt-record=%s,%s\n", dns->txtrecords[i].name, dns->txtrecords[i].value); } @@ -776,7 +794,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, goto cleanup; } - virCommandAddArgPair(cmd, "--srv-host", record); + virBufferAsprintf(&configbuf, "srv-host=%s\n", record); VIR_FREE(record); VIR_FREE(recordPort); VIR_FREE(recordWeight); @@ -848,8 +866,8 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, VIR_FREE(saddr); goto cleanup; } - virCommandAddArg(cmd, "--dhcp-range"); - virCommandAddArgFormat(cmd, "%s,%s", saddr, eaddr); + virBufferAsprintf(&configbuf, "dhcp-range=%s,%s\n", + saddr, eaddr); VIR_FREE(saddr); VIR_FREE(eaddr); nbleases += virSocketAddrGetRange(&ipdef->ranges[r].start, @@ -865,8 +883,7 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, char *bridgeaddr = virSocketAddrFormat(&ipdef->address); if (!bridgeaddr) goto cleanup; - virCommandAddArg(cmd, "--dhcp-range"); - virCommandAddArgFormat(cmd, "%s,static", bridgeaddr); + virBufferAsprintf(&configbuf, "dhcp-range=%s,static\n", bridgeaddr); VIR_FREE(bridgeaddr); } @@ -876,16 +893,14 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, /* Note: the following is IPv4 only */ if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET)) { if (ipdef->nranges || ipdef->nhosts) - virCommandAddArg(cmd, "--dhcp-no-override"); + virBufferAddLit(&configbuf, "dhcp-no-override\n"); if (ipdef->tftproot) { - virCommandAddArgList(cmd, "--enable-tftp", - "--tftp-root", ipdef->tftproot, - NULL); + virBufferAddLit(&configbuf, "enable-tftp\n"); + virBufferAsprintf(&configbuf, "tftp-root=%s\n", ipdef->tftproot); } if (ipdef->bootfile) { - virCommandAddArg(cmd, "--dhcp-boot"); if (VIR_SOCKET_ADDR_VALID(&ipdef->bootserver)) { char *bootserver = virSocketAddrFormat(&ipdef->bootserver); @@ -893,11 +908,11 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, virReportOOMError(); goto cleanup; } - virCommandAddArgFormat(cmd, "%s%s%s", + virBufferAsprintf(&configbuf, "dhcp-boot=%s%s%s\n", ipdef->bootfile, ",,", bootserver); VIR_FREE(bootserver); } else { - virCommandAddArg(cmd, ipdef->bootfile); + virBufferAsprintf(&configbuf, "dhcp-boot=%s\n", ipdef->bootfile); } } } @@ -910,9 +925,9 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, virReportOOMError(); goto cleanup; } - virCommandAddArgFormat(cmd, "--dhcp-leasefile=%s", leasefile); + virBufferAsprintf(&configbuf, "dhcp-leasefile=%s\n", leasefile); VIR_FREE(leasefile); - virCommandAddArgFormat(cmd, "--dhcp-lease-max=%d", nbleases); + virBufferAsprintf(&configbuf, "dhcp-lease-max=%d\n", nbleases); } /* this is done once per interface */ @@ -924,19 +939,19 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, * file to allow for runtime additions. */ if (ipv4def || ipv6def) - virCommandAddArgPair(cmd, "--dhcp-hostsfile", - dctx->hostsfile->path); + virBufferAsprintf(&configbuf, "dhcp-hostsfile=%s\n", + dctx->hostsfile->path); - /* Likewise, always create this file and put it on the commandline, - * to allow for runtime additions. + /* Likewise, always create this file and put it on the commandline, to allow for + * for runtime additions. */ - virCommandAddArgPair(cmd, "--addn-hosts", - dctx->addnhostsfile->path); + virBufferAsprintf(&configbuf, "addn-hosts=%s\n", + dctx->addnhostsfile->path); /* Are we doing RA instead of radvd? */ if (DNSMASQ_RA_SUPPORT(caps)) { if (ipv6def) - virCommandAddArg(cmd, "--enable-ra"); + virBufferAddLit(&configbuf, "enable-ra\n"); else { for (ii = 0; (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET6, ii)); @@ -944,8 +959,8 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, if (!(ipdef->nranges || ipdef->nhosts)) { char *bridgeaddr = virSocketAddrFormat(&ipdef->address); if (bridgeaddr) { - virCommandAddArgFormat(cmd, - "--dhcp-range=%s,ra-only", bridgeaddr); + virBufferAsprintf(&configbuf, + "dhcp-range=%s,ra-only\n", bridgeaddr); } else goto cleanup; VIR_FREE(bridgeaddr); @@ -954,9 +969,13 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network, } } + if (!(*configstr = virBufferContentAndReset(&configbuf))) + goto cleanup; + ret = 0; cleanup: + virBufferFreeAndReset(&configbuf); VIR_FREE(record); VIR_FREE(recordPort); VIR_FREE(recordWeight); @@ -964,6 +983,7 @@ cleanup: return ret; } +/* build the dnsmasq command line */ int networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, virCommandPtr *cmdout, char *pidfile, dnsmasqContext *dctx, @@ -971,14 +991,33 @@ networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, virCommandPtr *cmdou { virCommandPtr cmd = NULL; int ret = -1; + char *configfile = NULL; + char *configstr = NULL; network->dnsmasqPid = -1; - cmd = virCommandNew(dnsmasqCapsGetBinaryPath(caps)); - if (networkBuildDnsmasqArgv(network, pidfile, cmd, dctx, caps) < 0) { + if (networkDnsmasqConfContents(network, pidfile, &configstr, dctx, caps) < 0) + goto cleanup; + if (!configstr) + goto cleanup; + + /* construct the filename */ + if (!(configfile = networkDnsmasqConfigFileName(network->def->name))) { + virReportOOMError(); + goto cleanup; + } + + /* Write the file */ + if (virFileWriteStr(configfile, configstr, 0600) < 0) { + virReportSystemError(errno, + _("couldn't write dnsmasq config file '%s'"), + configfile); goto cleanup; } + cmd = virCommandNew(dnsmasqCapsGetBinaryPath(caps)); + virCommandAddArgFormat(cmd, "--conf-file=%s", configfile); + if (cmdout) *cmdout = cmd; ret = 0; @@ -1302,7 +1341,7 @@ networkStartRadvd(struct network_driver *driver ATTRIBUTE_UNUSED, network->radvdPid = -1; /* Is dnsmasq handling RA? */ - if (DNSMASQ_RA_SUPPORT(driver->dnsmasqCaps)) { + if (DNSMASQ_RA_SUPPORT(driver->dnsmasqCaps)) { ret = 0; goto cleanup; } diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h index 8c16bdd..43fefc0 100644 --- a/src/network/bridge_driver.h +++ b/src/network/bridge_driver.h @@ -46,18 +46,19 @@ int networkReleaseActualDevice(virDomainNetDefPtr iface) int networkGetNetworkAddress(const char *netname, char **netaddr) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); -int networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, - virCommandPtr *cmdout, char *pidfile, - dnsmasqContext *dctx, - dnsmasqCapsPtr caps) - ; +int networkDnsmasqConfContents(virNetworkObjPtr network, + const char *pidfile, + char **configstr, + dnsmasqContext *dctx, + dnsmasqCapsPtr caps); # else /* Define no-op replacements that don't drag in any link dependencies. */ # define networkAllocateActualDevice(iface) 0 # define networkNotifyActualDevice(iface) (iface=iface, 0) # define networkReleaseActualDevice(iface) (iface=iface, 0) # define networkGetNetworkAddress(netname, netaddr) (-2) -# define networkBuildDhcpDaemonCommandLine(network, cmdout, pidfile, dctx, caps) 0 +# define networkDnsmasqConfContents(network, pidfile, configstr, \ + dctx, caps) 0 # endif typedef char *(*networkDnsmasqLeaseFileNameFunc)(const char *netname); diff --git a/src/util/dnsmasq.h b/src/util/dnsmasq.h index ec1dfb1..4a796c9 100644 --- a/src/util/dnsmasq.h +++ b/src/util/dnsmasq.h @@ -103,7 +103,7 @@ unsigned long dnsmasqCapsGetVersion(dnsmasqCapsPtr caps); #define DNSMASQ_DHCPv6_MAJOR_REQD 2 #define DNSMASQ_DHCPv6_MINOR_REQD 64 -#define DNSMQASQ_RA_MAJOR_REQD 2 +#define DNSMASQ_RA_MAJOR_REQD 2 #define DNSMSAQ_RA_MINOR_REQD 64 #define DNSMASQ_DHCPv6_SUPPORT(CAPS) \ @@ -113,5 +113,5 @@ unsigned long dnsmasqCapsGetVersion(dnsmasqCapsPtr caps); #define DNSMASQ_RA_SUPPORT(CAPS) \ (dnsmasqCapsGetVersion(CAPS) >= \ (DNSMASQ_RA_MAJOR_REQD * 1000000) + \ - (DNSMASQ_RA_MINOR_REQD * 1000)) + (DNSMSAQ_RA_MINOR_REQD * 1000)) #endif /* __DNSMASQ_H__ */ diff --git a/tests/networkxml2argvdata/dhcp6-nat-network.argv b/tests/networkxml2argvdata/dhcp6-nat-network.argv deleted file mode 100644 index df8c507..0000000 --- a/tests/networkxml2argvdata/dhcp6-nat-network.argv +++ /dev/null @@ -1,15 +0,0 @@ -@DNSMASQ@ \ ---strict-order \ ---domain-needed \ ---local=// \ ---conf-file= \ ---bind-dynamic \ ---interface virbr0 \ ---dhcp-range 192.168.122.2,192.168.122.254 \ ---dhcp-no-override \ ---dhcp-range 2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff \ ---dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases \ ---dhcp-lease-max=493 \ ---dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile \ ---addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts \ ---enable-ra\ diff --git a/tests/networkxml2argvdata/dhcp6-nat-network.conf b/tests/networkxml2argvdata/dhcp6-nat-network.conf new file mode 100644 index 0000000..3fa358a --- /dev/null +++ b/tests/networkxml2argvdata/dhcp6-nat-network.conf @@ -0,0 +1,19 @@ +##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 +## of other applications using the libvirt API. +## +## dnsmasq conf file created by libvirt +strict-order +domain-needed +local=// +bind-dynamic +interface=virbr0 +dhcp-range=192.168.122.2,192.168.122.254 +dhcp-no-override +dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff +dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases +dhcp-lease-max=493 +dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile +addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts +enable-ra diff --git a/tests/networkxml2argvdata/dhcp6-network.argv b/tests/networkxml2argvdata/dhcp6-network.argv deleted file mode 100644 index 059c418..0000000 --- a/tests/networkxml2argvdata/dhcp6-network.argv +++ /dev/null @@ -1,15 +0,0 @@ -@DNSMASQ@ \ ---strict-order \ ---domain-needed \ ---domain=mynet \ ---expand-hosts \ ---local=/mynet/ \ ---conf-file= \ ---bind-dynamic \ ---interface virbr0 \ ---dhcp-range 2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff \ ---dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases \ ---dhcp-lease-max=240 \ ---dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile \ ---addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts \ ---enable-ra\ diff --git a/tests/networkxml2argvdata/dhcp6-network.conf b/tests/networkxml2argvdata/dhcp6-network.conf new file mode 100644 index 0000000..e3b2f8c --- /dev/null +++ b/tests/networkxml2argvdata/dhcp6-network.conf @@ -0,0 +1,19 @@ +##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 +## of other applications using the libvirt API. +## +## dnsmasq conf file created by libvirt +strict-order +domain-needed +domain=mynet +expand-hosts +local=/mynet/ +bind-dynamic +interface=virbr0 +dhcp-range=2001:db8:ac10:fd01::1:10,2001:db8:ac10:fd01::1:ff +dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases +dhcp-lease-max=240 +dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile +addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts +enable-ra diff --git a/tests/networkxml2argvdata/dhcp6host-routed-network.argv b/tests/networkxml2argvdata/dhcp6host-routed-network.argv deleted file mode 100644 index 8f6d7d3..0000000 --- a/tests/networkxml2argvdata/dhcp6host-routed-network.argv +++ /dev/null @@ -1,13 +0,0 @@ -@DNSMASQ@ \ ---strict-order \ ---domain-needed \ ---local=// \ ---conf-file= \ ---bind-dynamic \ ---interface virbr1 \ ---dhcp-range 192.168.122.1,static \ ---dhcp-no-override \ ---dhcp-range 2001:db8:ac10:fd01::1,static \ ---dhcp-hostsfile=/var/lib/libvirt/dnsmasq/local.hostsfile \ ---addn-hosts=/var/lib/libvirt/dnsmasq/local.addnhosts \ ---enable-ra\ diff --git a/tests/networkxml2argvdata/dhcp6host-routed-network.conf b/tests/networkxml2argvdata/dhcp6host-routed-network.conf new file mode 100644 index 0000000..4702cea --- /dev/null +++ b/tests/networkxml2argvdata/dhcp6host-routed-network.conf @@ -0,0 +1,17 @@ +##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 local +## of other applications using the libvirt API. +## +## dnsmasq conf file created by libvirt +strict-order +domain-needed +local=// +bind-dynamic +interface=virbr1 +dhcp-range=192.168.122.1,static +dhcp-no-override +dhcp-range=2001:db8:ac10:fd01::1,static +dhcp-hostsfile=/var/lib/libvirt/dnsmasq/local.hostsfile +addn-hosts=/var/lib/libvirt/dnsmasq/local.addnhosts +enable-ra diff --git a/tests/networkxml2argvdata/isolated-network.argv b/tests/networkxml2argvdata/isolated-network.argv deleted file mode 100644 index b0783bd..0000000 --- a/tests/networkxml2argvdata/isolated-network.argv +++ /dev/null @@ -1,16 +0,0 @@ -@DNSMASQ@ \ ---strict-order \ ---domain-needed \ ---local=// \ ---conf-file= \ ---bind-interfaces \ ---except-interface=lo \ ---listen-address 192.168.152.1 \ ---dhcp-option=3 \ ---no-resolv \ ---dhcp-range 192.168.152.2,192.168.152.254 \ ---dhcp-no-override \ ---dhcp-leasefile=/var/lib/libvirt/dnsmasq/private.leases \ ---dhcp-lease-max=253 \ ---dhcp-hostsfile=/var/lib/libvirt/dnsmasq/private.hostsfile \ ---addn-hosts=/var/lib/libvirt/dnsmasq/private.addnhosts\ diff --git a/tests/networkxml2argvdata/isolated-network.conf b/tests/networkxml2argvdata/isolated-network.conf new file mode 100644 index 0000000..6e4b269 --- /dev/null +++ b/tests/networkxml2argvdata/isolated-network.conf @@ -0,0 +1,20 @@ +##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 private +## of other applications using the libvirt API. +## +## dnsmasq conf file created by libvirt +strict-order +domain-needed +local=// +bind-interfaces +except-interface=lo +listen-address=192.168.152.1 +dhcp-option=3 +no-resolv +dhcp-range=192.168.152.2,192.168.152.254 +dhcp-no-override +dhcp-leasefile=/var/lib/libvirt/dnsmasq/private.leases +dhcp-lease-max=253 +dhcp-hostsfile=/var/lib/libvirt/dnsmasq/private.hostsfile +addn-hosts=/var/lib/libvirt/dnsmasq/private.addnhosts diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.argv b/tests/networkxml2argvdata/nat-network-dns-hosts.argv deleted file mode 100644 index fee137f..0000000 --- a/tests/networkxml2argvdata/nat-network-dns-hosts.argv +++ /dev/null @@ -1,10 +0,0 @@ -@DNSMASQ@ \ ---strict-order \ ---domain-needed \ ---domain=example.com \ ---expand-hosts \ ---local=/example.com/ \ ---conf-file= \ ---bind-dynamic \ ---interface virbr0 \ ---addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts\ diff --git a/tests/networkxml2argvdata/nat-network-dns-hosts.conf b/tests/networkxml2argvdata/nat-network-dns-hosts.conf new file mode 100644 index 0000000..c50acd2 --- /dev/null +++ b/tests/networkxml2argvdata/nat-network-dns-hosts.conf @@ -0,0 +1,14 @@ +##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 +## of other applications using the libvirt API. +## +## dnsmasq conf file created by libvirt +strict-order +domain-needed +domain=example.com +expand-hosts +local=/example.com/ +bind-dynamic +interface=virbr0 +addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts diff --git a/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv b/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv deleted file mode 100644 index 1de6637..0000000 --- a/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv +++ /dev/null @@ -1,19 +0,0 @@ -@DNSMASQ@ \ ---strict-order \ ---domain-needed \ ---local=// \ ---conf-file= \ ---bind-interfaces \ ---except-interface=lo \ ---listen-address 192.168.122.1 \ ---listen-address 192.168.123.1 \ ---listen-address fc00:db8:ac10:fe01::1 \ ---listen-address fc00:db8:ac10:fd01::1 \ ---listen-address 10.24.10.1 \ ---srv-host=name.tcp.,,,, \ ---dhcp-range 192.168.122.2,192.168.122.254 \ ---dhcp-no-override \ ---dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases \ ---dhcp-lease-max=253 \ ---dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile \ ---addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts\ diff --git a/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.conf b/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.conf new file mode 100644 index 0000000..25af9c6 --- /dev/null +++ b/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.conf @@ -0,0 +1,23 @@ +##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 +## of other applications using the libvirt API. +## +## dnsmasq conf file created by libvirt +strict-order +domain-needed +local=// +bind-interfaces +except-interface=lo +listen-address=192.168.122.1 +listen-address=192.168.123.1 +listen-address=fc00:db8:ac10:fe01::1 +listen-address=fc00:db8:ac10:fd01::1 +listen-address=10.24.10.1 +srv-host=name.tcp.,,,, +dhcp-range=192.168.122.2,192.168.122.254 +dhcp-no-override +dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases +dhcp-lease-max=253 +dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile +addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts diff --git a/tests/networkxml2argvdata/nat-network-dns-srv-record.argv b/tests/networkxml2argvdata/nat-network-dns-srv-record.argv deleted file mode 100644 index e7ecaa5..0000000 --- a/tests/networkxml2argvdata/nat-network-dns-srv-record.argv +++ /dev/null @@ -1,14 +0,0 @@ -@DNSMASQ@ \ ---strict-order \ ---domain-needed \ ---local=// \ ---conf-file= \ ---bind-dynamic \ ---interface virbr0 \ ---srv-host=name.tcp.test-domain-name,.,1024,10,10 \ ---dhcp-range 192.168.122.2,192.168.122.254 \ ---dhcp-no-override \ ---dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases \ ---dhcp-lease-max=253 \ ---dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile \ ---addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts\ diff --git a/tests/networkxml2argvdata/nat-network-dns-srv-record.conf b/tests/networkxml2argvdata/nat-network-dns-srv-record.conf new file mode 100644 index 0000000..777f03d --- /dev/null +++ b/tests/networkxml2argvdata/nat-network-dns-srv-record.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 +## of other applications using the libvirt API. +## +## dnsmasq conf file created by libvirt +strict-order +domain-needed +local=// +bind-dynamic +interface=virbr0 +srv-host=name.tcp.test-domain-name,.,1024,10,10 +dhcp-range=192.168.122.2,192.168.122.254 +dhcp-no-override +dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases +dhcp-lease-max=253 +dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile +addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts diff --git a/tests/networkxml2argvdata/nat-network-dns-txt-record.argv b/tests/networkxml2argvdata/nat-network-dns-txt-record.argv deleted file mode 100644 index 8ea0004..0000000 --- a/tests/networkxml2argvdata/nat-network-dns-txt-record.argv +++ /dev/null @@ -1,13 +0,0 @@ -@DNSMASQ@ \ ---strict-order \ ---domain-needed \ ---local=// \ ---conf-file= \ ---bind-dynamic --interface virbr0 \ -'--txt-record=example,example value' \ ---dhcp-range 192.168.122.2,192.168.122.254 \ ---dhcp-no-override \ ---dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases \ ---dhcp-lease-max=253 \ ---dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile \ ---addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts\ diff --git a/tests/networkxml2argvdata/nat-network-dns-txt-record.conf b/tests/networkxml2argvdata/nat-network-dns-txt-record.conf new file mode 100644 index 0000000..75ed546 --- /dev/null +++ b/tests/networkxml2argvdata/nat-network-dns-txt-record.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 +## of other applications using the libvirt API. +## +## dnsmasq conf file created by libvirt +strict-order +domain-needed +local=// +bind-dynamic +interface=virbr0 +txt-record=example,example value +dhcp-range=192.168.122.2,192.168.122.254 +dhcp-no-override +dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases +dhcp-lease-max=253 +dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile +addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts diff --git a/tests/networkxml2argvdata/nat-network.argv b/tests/networkxml2argvdata/nat-network.argv deleted file mode 100644 index 578a5ff..0000000 --- a/tests/networkxml2argvdata/nat-network.argv +++ /dev/null @@ -1,15 +0,0 @@ -@DNSMASQ@ \ ---strict-order \ ---domain-needed \ ---local=// \ ---conf-file= \ ---bind-dynamic \ ---interface virbr0 \ ---dhcp-range 192.168.122.2,192.168.122.254 \ ---dhcp-no-override \ ---dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases \ ---dhcp-lease-max=253 \ ---dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile \ ---addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts \ ---dhcp-range=2001:db8:ac10:fe01::1,ra-only \ ---dhcp-range=2001:db8:ac10:fd01::1,ra-only\ diff --git a/tests/networkxml2argvdata/nat-network.conf b/tests/networkxml2argvdata/nat-network.conf new file mode 100644 index 0000000..f07456f --- /dev/null +++ b/tests/networkxml2argvdata/nat-network.conf @@ -0,0 +1,19 @@ +##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 +## of other applications using the libvirt API. +## +## dnsmasq conf file created by libvirt +strict-order +domain-needed +local=// +bind-dynamic +interface=virbr0 +dhcp-range=192.168.122.2,192.168.122.254 +dhcp-no-override +dhcp-leasefile=/var/lib/libvirt/dnsmasq/default.leases +dhcp-lease-max=253 +dhcp-hostsfile=/var/lib/libvirt/dnsmasq/default.hostsfile +addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts +dhcp-range=2001:db8:ac10:fe01::1,ra-only +dhcp-range=2001:db8:ac10:fd01::1,ra-only diff --git a/tests/networkxml2argvdata/netboot-network.argv b/tests/networkxml2argvdata/netboot-network.argv deleted file mode 100644 index c5b75a3..0000000 --- a/tests/networkxml2argvdata/netboot-network.argv +++ /dev/null @@ -1,19 +0,0 @@ -@DNSMASQ@ \ ---strict-order \ ---domain-needed \ ---domain=example.com \ ---expand-hosts \ ---local=/example.com/ \ ---conf-file= \ ---bind-interfaces \ ---except-interface=lo \ ---listen-address 192.168.122.1 \ ---dhcp-range 192.168.122.2,192.168.122.254 \ ---dhcp-no-override \ ---enable-tftp \ ---tftp-root /var/lib/tftproot \ ---dhcp-boot pxeboot.img \ ---dhcp-leasefile=/var/lib/libvirt/dnsmasq/netboot.leases \ ---dhcp-lease-max=253 \ ---dhcp-hostsfile=/var/lib/libvirt/dnsmasq/netboot.hostsfile \ ---addn-hosts=/var/lib/libvirt/dnsmasq/netboot.addnhosts\ diff --git a/tests/networkxml2argvdata/netboot-network.conf b/tests/networkxml2argvdata/netboot-network.conf new file mode 100644 index 0000000..bda7e2d --- /dev/null +++ b/tests/networkxml2argvdata/netboot-network.conf @@ -0,0 +1,23 @@ +##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 netboot +## of other applications using the libvirt API. +## +## dnsmasq conf file created by libvirt +strict-order +domain-needed +domain=example.com +expand-hosts +local=/example.com/ +bind-interfaces +except-interface=lo +listen-address=192.168.122.1 +dhcp-range=192.168.122.2,192.168.122.254 +dhcp-no-override +enable-tftp +tftp-root=/var/lib/tftproot +dhcp-boot=pxeboot.img +dhcp-leasefile=/var/lib/libvirt/dnsmasq/netboot.leases +dhcp-lease-max=253 +dhcp-hostsfile=/var/lib/libvirt/dnsmasq/netboot.hostsfile +addn-hosts=/var/lib/libvirt/dnsmasq/netboot.addnhosts diff --git a/tests/networkxml2argvdata/netboot-proxy-network.argv b/tests/networkxml2argvdata/netboot-proxy-network.argv deleted file mode 100644 index 16e1c85..0000000 --- a/tests/networkxml2argvdata/netboot-proxy-network.argv +++ /dev/null @@ -1,17 +0,0 @@ -@DNSMASQ@ \ ---strict-order \ ---domain-needed \ ---domain=example.com \ ---expand-hosts \ ---local=/example.com/ \ ---conf-file= \ ---bind-interfaces \ ---except-interface=lo \ ---listen-address 192.168.122.1 \ ---dhcp-range 192.168.122.2,192.168.122.254 \ ---dhcp-no-override \ ---dhcp-boot pxeboot.img,,10.20.30.40 \ ---dhcp-leasefile=/var/lib/libvirt/dnsmasq/netboot.leases \ ---dhcp-lease-max=253 \ ---dhcp-hostsfile=/var/lib/libvirt/dnsmasq/netboot.hostsfile \ ---addn-hosts=/var/lib/libvirt/dnsmasq/netboot.addnhosts\ diff --git a/tests/networkxml2argvdata/netboot-proxy-network.conf b/tests/networkxml2argvdata/netboot-proxy-network.conf new file mode 100644 index 0000000..42b8dfa --- /dev/null +++ b/tests/networkxml2argvdata/netboot-proxy-network.conf @@ -0,0 +1,21 @@ +##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 netboot +## of other applications using the libvirt API. +## +## dnsmasq conf file created by libvirt +strict-order +domain-needed +domain=example.com +expand-hosts +local=/example.com/ +bind-interfaces +except-interface=lo +listen-address=192.168.122.1 +dhcp-range=192.168.122.2,192.168.122.254 +dhcp-no-override +dhcp-boot=pxeboot.img,,10.20.30.40 +dhcp-leasefile=/var/lib/libvirt/dnsmasq/netboot.leases +dhcp-lease-max=253 +dhcp-hostsfile=/var/lib/libvirt/dnsmasq/netboot.hostsfile +addn-hosts=/var/lib/libvirt/dnsmasq/netboot.addnhosts diff --git a/tests/networkxml2argvdata/routed-network.argv b/tests/networkxml2argvdata/routed-network.argv deleted file mode 100644 index b3fbf49..0000000 --- a/tests/networkxml2argvdata/routed-network.argv +++ /dev/null @@ -1,8 +0,0 @@ -@DNSMASQ@ \ ---strict-order \ ---domain-needed \ ---local=// \ ---conf-file= \ ---bind-dynamic \ ---interface virbr1 \ ---addn-hosts=/var/lib/libvirt/dnsmasq/local.addnhosts\ diff --git a/tests/networkxml2argvdata/routed-network.conf b/tests/networkxml2argvdata/routed-network.conf new file mode 100644 index 0000000..f5f9680 --- /dev/null +++ b/tests/networkxml2argvdata/routed-network.conf @@ -0,0 +1,12 @@ +##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 local +## of other applications using the libvirt API. +## +## dnsmasq conf file created by libvirt +strict-order +domain-needed +local=// +bind-dynamic +interface=virbr1 +addn-hosts=/var/lib/libvirt/dnsmasq/local.addnhosts diff --git a/tests/networkxml2argvtest.c b/tests/networkxml2argvtest.c index a020db9..2e9020c 100644 --- a/tests/networkxml2argvtest.c +++ b/tests/networkxml2argvtest.c @@ -15,37 +15,6 @@ #include "memory.h" #include "network/bridge_driver.h" -/* Replace all occurrences of @token in @buf by @replacement and adjust size of - * @buf accordingly. Returns 0 on success and -1 on out-of-memory errors. */ -static int replaceTokens(char **buf, const char *token, const char *replacement) { - size_t token_start, token_end; - size_t buf_len, rest_len; - const size_t token_len = strlen(token); - const size_t replacement_len = strlen(replacement); - const int diff = replacement_len - token_len; - - buf_len = rest_len = strlen(*buf) + 1; - token_end = 0; - for (;;) { - char *match = strstr(*buf + token_end, token); - if (match == NULL) - break; - token_start = match - *buf; - rest_len -= token_start + token_len - token_end; - token_end = token_start + token_len; - buf_len += diff; - if (diff > 0) - if (VIR_REALLOC_N(*buf, buf_len) < 0) - return -1; - if (diff != 0) - memmove(*buf + token_end + diff, *buf + token_end, rest_len); - memcpy(*buf + token_start, replacement, replacement_len); - token_end += diff; - } - /* if diff < 0, we could shrink the buffer here... */ - return 0; -} - static int testCompareXMLToArgvFiles(const char *inxml, const char *outargv, dnsmasqCapsPtr caps) { @@ -65,9 +34,6 @@ testCompareXMLToArgvFiles(const char *inxml, const char *outargv, dnsmasqCapsPtr if (virtTestLoadFile(outargv, &outArgvData) < 0) goto fail; - if (replaceTokens(&outArgvData, "@DNSMASQ@", DNSMASQ)) - goto fail; - if (!(dev = virNetworkDefParseString(inXmlData))) goto fail; @@ -80,10 +46,8 @@ testCompareXMLToArgvFiles(const char *inxml, const char *outargv, dnsmasqCapsPtr if (dctx == NULL) goto fail; - if (networkBuildDhcpDaemonCommandLine(obj, &cmd, pidfile, dctx, caps) < 0) - goto fail; - - if (!(actual = virCommandToString(cmd))) + if (networkDnsmasqConfContents(obj, pidfile, &actual, + dctx, caps) < 0) goto fail; if (STRNEQ(outArgvData, actual)) { @@ -119,7 +83,7 @@ testCompareXMLToArgvHelper(const void *data) if (virAsprintf(&inxml, "%s/networkxml2argvdata/%s.xml", abs_srcdir, info->name) < 0 || - virAsprintf(&outxml, "%s/networkxml2argvdata/%s.argv", + virAsprintf(&outxml, "%s/networkxml2argvdata/%s.conf", abs_srcdir, info->name) < 0) { goto cleanup; } -- 1.7.11.7

On 12/06/2012 12:20 PM, Gene Czarcinski wrote:
Updated per Laine Stump's review commands and rebased 6 Dec 2012.
This patch changes how parameters are passed to dnsmasq. Instead of being on the command line, the parameters are put into a file (one parameter per line) and a commandline --conf-file= specifies the location of the file. The file is located in the same directory as the leases file.
Putting the dnsmasq parameters into a configuration file allows them to be examined and more easily understood than examining the command lines displayed by "ps ax". This is especially true when a number of networks have been started.
I suspect that when the use of dnsmasq was originally done, the command line was simple but has gotten more complicated over time and will likely become even more complicated in the future.
I believe that if use of dnsmasq was done today with the current requirements for dnsmasq, a configuration file would have been used. Many (most?) daemons use configuration files as oppose to large number of command line parameters.
One potential addition to dnsmasq parameters is to specify the reverse-lookup queries which are not to be passed on up the chain. For IPv4, such queries are rather simple and take the form: <ipv4_address>.in-addr.arpa but ipv6 queries involve a lot longer specification. The IPv6 query will be of the form: <ipv6_address>.ip6.arpa where the above query expands to a 44 character string which is specified by --local=/<ipv6_address>.ip6.arpa/ which is certainly a lot of clutter to add to the command line.
Note: The test conf files have all been renamed .conf instead of .argv. --- src/network/bridge_driver.c | 189 +++++++++++++-------- src/network/bridge_driver.h | 13 +- src/util/dnsmasq.h | 4 +- tests/networkxml2argvdata/dhcp6-nat-network.argv | 15 -- tests/networkxml2argvdata/dhcp6-nat-network.conf | 19 +++ tests/networkxml2argvdata/dhcp6-network.argv | 15 -- tests/networkxml2argvdata/dhcp6-network.conf | 19 +++ .../dhcp6host-routed-network.argv | 13 -- .../dhcp6host-routed-network.conf | 17 ++ tests/networkxml2argvdata/isolated-network.argv | 16 -- tests/networkxml2argvdata/isolated-network.conf | 20 +++ .../networkxml2argvdata/nat-network-dns-hosts.argv | 10 -- .../networkxml2argvdata/nat-network-dns-hosts.conf | 14 ++ .../nat-network-dns-srv-record-minimal.argv | 19 --- .../nat-network-dns-srv-record-minimal.conf | 23 +++ .../nat-network-dns-srv-record.argv | 14 -- .../nat-network-dns-srv-record.conf | 18 ++ .../nat-network-dns-txt-record.argv | 13 -- .../nat-network-dns-txt-record.conf | 18 ++ tests/networkxml2argvdata/nat-network.argv | 15 -- tests/networkxml2argvdata/nat-network.conf | 19 +++ tests/networkxml2argvdata/netboot-network.argv | 19 --- tests/networkxml2argvdata/netboot-network.conf | 23 +++ .../networkxml2argvdata/netboot-proxy-network.argv | 17 -- .../networkxml2argvdata/netboot-proxy-network.conf | 21 +++ tests/networkxml2argvdata/routed-network.argv | 8 - tests/networkxml2argvdata/routed-network.conf | 12 ++ tests/networkxml2argvtest.c | 42 +---- 28 files changed, 349 insertions(+), 296 deletions(-) delete mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.argv create mode 100644 tests/networkxml2argvdata/dhcp6-nat-network.conf delete mode 100644 tests/networkxml2argvdata/dhcp6-network.argv create mode 100644 tests/networkxml2argvdata/dhcp6-network.conf delete mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.argv create mode 100644 tests/networkxml2argvdata/dhcp6host-routed-network.conf delete mode 100644 tests/networkxml2argvdata/isolated-network.argv create mode 100644 tests/networkxml2argvdata/isolated-network.conf delete mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-hosts.conf delete mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.conf delete mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-srv-record.conf delete mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.argv create mode 100644 tests/networkxml2argvdata/nat-network-dns-txt-record.conf delete mode 100644 tests/networkxml2argvdata/nat-network.argv create mode 100644 tests/networkxml2argvdata/nat-network.conf delete mode 100644 tests/networkxml2argvdata/netboot-network.argv create mode 100644 tests/networkxml2argvdata/netboot-network.conf delete mode 100644 tests/networkxml2argvdata/netboot-proxy-network.argv create mode 100644 tests/networkxml2argvdata/netboot-proxy-network.conf delete mode 100644 tests/networkxml2argvdata/routed-network.argv create mode 100644 tests/networkxml2argvdata/routed-network.conf
Oops. *This* is the patch where I moved networkxml2argv* to networkxml2conf* :-) Anyway, there's a lot of change in this patch, but it's almost all very mechanical, and running make check verifies that the changes to the test data is correct. ACK. Now that the prerequisites are all pushed, I pushed this too.
participants (2)
-
Gene Czarcinski
-
Laine Stump