[libvirt] [PATCH 2/3] v7.1 add support for DHCPv6
Gene Czarcinski
gene at czarc.net
Thu Nov 22 19:21:51 UTC 2012
On 11/21/2012 04:18 PM, Gene Czarcinski wrote:
> 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.
>
> Note that the check for dnsmasq version is performed at
> network start and only then will an error condition occur.
> Thus, it is possible to define/edit a network configuration
> which will not start. The error message indicates that
> dnsmasq version 2.64 or later is required.
>
> This patch provides the same DHCP support for IPv6 which
> has been available for IPv4.
>
> With dnsmasq >= 2.64, support for the RA service is now provided
> by dnsmasq (radvd is no longer needed/used/started).
>
> Documentation has been updated to reflect the new support.
Oops. I did not realize that there are schemas that should be updated.
I have most of what is needed figured out but there are a couple of
things not working cleanly. I should have a update patch submitted
"real soon now".
Suggestion: add something to the developers guidance so that you check
to make sure that the schemas are updated properly. I wonder if the
tests would pass testing?
Gene
> ---
> docs/formatnetwork.html.in | 108 ++++++-
> src/conf/network_conf.c | 100 ++++---
> src/conf/network_conf.h | 1 +
> src/network/bridge_driver.c | 333 +++++++++++++++------
> src/util/dnsmasq.c | 9 +-
> tests/networkxml2argvdata/dhcp6-network.argv | 17 ++
> tests/networkxml2argvdata/dhcp6-network.xml | 16 +
> tests/networkxml2argvdata/isolated-network.argv | 15 +-
> tests/networkxml2argvdata/nat-network-dhcp6.argv | 20 ++
> tests/networkxml2argvdata/nat-network-dhcp6.xml | 26 ++
> .../networkxml2argvdata/nat-network-dns-hosts.argv | 15 +-
> .../nat-network-dns-srv-record-minimal.argv | 11 +-
> .../nat-network-dns-srv-record.argv | 11 +-
> .../nat-network-dns-txt-record.argv | 23 +-
> tests/networkxml2argvdata/nat-network.argv | 23 +-
> tests/networkxml2argvdata/netboot-network.argv | 23 +-
> .../networkxml2argvdata/netboot-proxy-network.argv | 20 +-
> .../routed-network-dhcphost.argv | 15 +
> .../routed-network-dhcphost.xml | 19 ++
> tests/networkxml2argvdata/routed-network.argv | 11 +-
> tests/networkxml2argvtest.c | 4 +
> 21 files changed, 633 insertions(+), 187 deletions(-)
> create mode 100644 tests/networkxml2argvdata/dhcp6-network.argv
> create mode 100644 tests/networkxml2argvdata/dhcp6-network.xml
> create mode 100644 tests/networkxml2argvdata/nat-network-dhcp6.argv
> create mode 100644 tests/networkxml2argvdata/nat-network-dhcp6.xml
> create mode 100644 tests/networkxml2argvdata/routed-network-dhcphost.argv
> create mode 100644 tests/networkxml2argvdata/routed-network-dhcphost.xml
>
> diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
> index 7b3b25c..50e00f9 100644
> --- a/docs/formatnetwork.html.in
> +++ b/docs/formatnetwork.html.in
> @@ -577,8 +577,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
> @@ -587,10 +589,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
> @@ -611,27 +616,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
> @@ -674,6 +698,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>
> @@ -698,6 +745,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>
> @@ -720,6 +790,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/src/conf/network_conf.c b/src/conf/network_conf.c
> index 228951d..a56b2e6 100644
> --- a/src/conf/network_conf.c
> +++ b/src/conf/network_conf.c
> @@ -633,6 +633,7 @@ cleanup:
>
> static int
> virNetworkDHCPHostDefParse(const char *networkName,
> + 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 IPv6 network '%s'"),
> + 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,19 @@ virNetworkDHCPHostDefParse(const char *networkName,
> networkName);
> }
> } else {
> + 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;
> + }
> + }
> /* normal usage - you need at least one MAC address or one host name */
> - if (!(mac || name)) {
> + 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,36 +765,39 @@ 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")) {
> - char *file;
> - char *server;
> - virSocketAddr inaddr;
> - memset(&inaddr, 0, sizeof(inaddr));
> -
> - if (!(file = virXMLPropString(cur, "file"))) {
> - cur = cur->next;
> - continue;
> - }
> - server = virXMLPropString(cur, "server");
> + } else if (VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET)) {
> + /* the following only applies to IPv4 */
> + if (cur->type == XML_ELEMENT_NODE &&
> + xmlStrEqual(cur->name, BAD_CAST "bootp")) {
> + char *file;
> + char *server;
> + virSocketAddr inaddr;
> + memset(&inaddr, 0, sizeof(inaddr));
> +
> + if (!(file = virXMLPropString(cur, "file"))) {
> + cur = cur->next;
> + continue;
> + }
> + server = virXMLPropString(cur, "server");
> +
> + if (server &&
> + virSocketAddrParse(&inaddr, server, AF_UNSPEC) < 0) {
> + VIR_FREE(file);
> + VIR_FREE(server);
> + return -1;
> + }
>
> - if (server &&
> - virSocketAddrParse(&inaddr, server, AF_UNSPEC) < 0) {
> - VIR_FREE(file);
> + def->bootfile = file;
> + def->bootserver = inaddr;
> VIR_FREE(server);
> - return -1;
> }
> -
> - def->bootfile = file;
> - def->bootserver = inaddr;
> - VIR_FREE(server);
> }
>
> cur = cur->next;
> @@ -1139,6 +1159,20 @@ virNetworkIPParseXML(const char *networkName,
> }
> }
>
> + if (VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET6)) {
> + /* parse IPv6-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;
> + }
> + cur = cur->next;
> + }
> + }
> +
> result = 0;
>
> error:
> @@ -2347,11 +2381,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'> "
> "element found at index %d in network '%s'"),
> parentIndex, def->name);
> }
> @@ -2364,17 +2396,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'> "
> "element found in network '%s'"), def->name);
> }
> return ipdef;
> @@ -2404,7 +2436,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),
> @@ -2437,7 +2469,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 */
> @@ -2483,7 +2515,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/conf/network_conf.h b/src/conf/network_conf.h
> index 3e46304..226da04 100644
> --- a/src/conf/network_conf.h
> +++ b/src/conf/network_conf.h
> @@ -218,6 +218,7 @@ struct _virNetworkObj {
> unsigned int active : 1;
> unsigned int autostart : 1;
> unsigned int persistent : 1;
> + unsigned int dnsmasqVersion;
>
> virNetworkDefPtr def; /* The current definition */
> virNetworkDefPtr newDef; /* New definition to activate at shutdown */
> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
> index 9c67348..19a9170 100644
> --- a/src/network/bridge_driver.c
> +++ b/src/network/bridge_driver.c
> @@ -75,6 +75,11 @@
>
> #define VIR_FROM_THIS VIR_FROM_NETWORK
>
> +#define DNSMASQ_PREFIX_TEXT "Dnsmasq version "
> +
> +#define CHECK_DNSMASQ_VERSION() \
> + (network->dnsmasqVersion >= 2064)
> +
> /* Main driver state */
> struct network_driver {
> virMutex lock;
> @@ -582,20 +587,32 @@ 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;
>
> for (i = 0; i < ipdef->nhosts; i++) {
> virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]);
> - if ((host->mac) && VIR_SOCKET_ADDR_VALID(&host->ip))
> + if (VIR_SOCKET_ADDR_VALID(&host->ip))
> if (dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name) < 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]);
> @@ -613,7 +630,6 @@ networkBuildDnsmasqHostsfile(dnsmasqContext *dctx,
>
> static int
> networkBuildDnsmasqArgv(virNetworkObjPtr network,
> - virNetworkIpDefPtr ipdef,
> const char *pidfile,
> virCommandPtr cmd,
> dnsmasqContext *dctx)
> @@ -625,7 +641,8 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
> char *recordPort = NULL;
> char *recordWeight = NULL;
> char *recordPriority = NULL;
> - virNetworkIpDefPtr tmpipdef;
> + virNetworkIpDefPtr tmpipdef, ipdef, ipv4def, ipv6def;
> + bool dhcp4flag, dhcp6flag;
>
> /*
> * NB, be careful about syntax for dnsmasq options in long format.
> @@ -650,14 +667,19 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
> * Needed to ensure dnsmasq uses same algorithm for processing
> * multiple namedriver entries in /etc/resolv.conf as GLibC.
> */
> - virCommandAddArgList(cmd, "--strict-order", "--bind-interfaces", NULL);
> + virCommandAddArgList(cmd, "--strict-order",
> + "--bind-interfaces",
> + "--domain-needed",
> + "--except-interface=lo",
> + 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);
> @@ -665,10 +687,6 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
> /* *no* conf file */
> virCommandAddArg(cmd, "--conf-file=");
>
> - virCommandAddArgList(cmd,
> - "--except-interface", "lo",
> - NULL);
> -
> /* 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
> @@ -751,7 +769,39 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
> VIR_FREE(ipaddr);
> }
>
> - if (ipdef) {
> + /* Find the first dhcp for both IPv4 and IPv6 */
> + for (ii = 0, ipv4def = NULL, ipv6def = NULL, dhcp4flag = false, dhcp6flag = 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) {
> + ipv4def = ipdef;
> + dhcp4flag = true;
> + }
> + }
> + }
> + if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) {
> + if (ipdef->nranges || ipdef->nhosts) {
> + if (!CHECK_DNSMASQ_VERSION()) {
> + virReportError(VIR_ERR_XML_ERROR, "%s",
> + _("dnsmasq version >= 2.64 required to specify DHCPv6 range or host"));
> + goto cleanup;
> + }
> + if (!ipv6def) {
> + ipv6def = ipdef;
> + dhcp6flag = true;
> + }
> + }
> + }
> + }
> +
> + if (ipv4def)
> + ipdef = ipv4def;
> + else
> + ipdef = ipv6def;
> +
> + while (ipdef) {
> for (r = 0 ; r < ipdef->nranges ; r++) {
> char *saddr = virSocketAddrFormat(&ipdef->ranges[r].start);
> if (!saddr)
> @@ -772,7 +822,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);
> @@ -783,61 +833,93 @@ 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 (networkBuildDnsmasqDhcpHostsList(dctx, ipdef) < 0)
> + goto cleanup;
>
> - if (ipdef->nranges || ipdef->nhosts)
> - virCommandAddArg(cmd, "--dhcp-no-override");
> + /* 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");
>
> - /* add domain to any non-qualified hostnames in /etc/hosts or addn-hosts */
> - if (network->def->domain)
> - virCommandAddArg(cmd, "--expand-hosts");
> + if (ipdef->tftproot) {
> + virCommandAddArgList(cmd, "--enable-tftp",
> + "--tftp-root", ipdef->tftproot,
> + NULL);
> + }
>
> - if (networkBuildDnsmasqHostsfile(dctx, ipdef, network->def->dns) < 0)
> - goto cleanup;
> + if (ipdef->bootfile) {
> + virCommandAddArg(cmd, "--dhcp-boot");
> + if (VIR_SOCKET_ADDR_VALID(&ipdef->bootserver)) {
> + char *bootserver = virSocketAddrFormat(&ipdef->bootserver);
>
> - /* 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 (!bootserver)
> + goto cleanup;
> + virCommandAddArgFormat(cmd, "%s%s%s",
> + ipdef->bootfile, ",,", bootserver);
> + VIR_FREE(bootserver);
> + } else {
> + virCommandAddArg(cmd, ipdef->bootfile);
> + }
> + }
> + }
> + if (ipdef == ipv6def)
> + ipdef = NULL;
> + else
> + ipdef = ipv6def;
> + }
>
> - /* 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 (nbleases > 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->tftproot) {
> - virCommandAddArgList(cmd, "--enable-tftp",
> - "--tftp-root", ipdef->tftproot,
> - NULL);
> - }
> - if (ipdef->bootfile) {
> - virCommandAddArg(cmd, "--dhcp-boot");
> - if (VIR_SOCKET_ADDR_VALID(&ipdef->bootserver)) {
> - char *bootserver = virSocketAddrFormat(&ipdef->bootserver);
> + /* this is done once per interface */
> + if (networkBuildDnsmasqHostsList(dctx, network->def->dns) < 0)
> + goto cleanup;
>
> - if (!bootserver)
> + /* 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 (dhcp4flag || dhcp6flag)
> + virCommandAddArgPair(cmd, "--dhcp-hostsfile",
> + dctx->hostsfile->path);
> +
> + /* Likewise, always create this file and put it on the commandline, to allow for
> + * for runtime additions.
> + */
> + virCommandAddArgPair(cmd, "--addn-hosts",
> + dctx->addnhostsfile->path);
> +
> + /* we are doing RA instead of radvd */
> + if (CHECK_DNSMASQ_VERSION()) {
> + if (dhcp6flag)
> + virCommandAddArg(cmd, "--enable-ra");
> + else {
> + char *bridgeaddr = NULL;
> + ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET6, 0);
> + if (ipdef) {
> + bridgeaddr = virSocketAddrFormat(&ipdef->address);
> + if (bridgeaddr) {
> + virCommandAddArgFormat(cmd,
> + "--dhcp-range=%s,ra-only", bridgeaddr);
> + } else {
> + virReportError(VIR_ERR_XML_ERROR,
> + _("invalid IPv6 configuration for %s ra-only"),
> + network->def->name);
> goto cleanup;
> - virCommandAddArgFormat(cmd, "%s%s%s",
> - ipdef->bootfile, ",,", bootserver);
> - VIR_FREE(bootserver);
> - } else {
> - virCommandAddArg(cmd, ipdef->bootfile);
> + }
> + VIR_FREE(bridgeaddr);
> }
> }
> }
>
> ret = 0;
> +
> cleanup:
> VIR_FREE(record);
> VIR_FREE(recordPort);
> @@ -877,7 +959,7 @@ networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, virCommandPtr *cmdou
> return 0;
>
> cmd = virCommandNew(DNSMASQ);
> - if (networkBuildDnsmasqArgv(network, ipdef, pidfile, cmd, dctx) < 0) {
> + if (networkBuildDnsmasqArgv(network, pidfile, cmd, dctx) < 0) {
> goto cleanup;
> }
>
> @@ -894,18 +976,45 @@ static int
> networkStartDhcpDaemon(virNetworkObjPtr network)
> {
> virCommandPtr cmd = NULL;
> + const char *cmdname = DNSMASQ;
> + char *tmp, *version = NULL;
> + unsigned int major = 0, minor = 0;
> 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;
> }
>
> + if (!virFileIsExecutable(cmdname)) {
> + VIR_WARN("file %s missing or not executable", cmdname);
> + goto cleanup;
> + }
> + VIR_INFO("starting dhcp daemon (%s)", cmdname);
> + network->dnsmasqVersion = 0;
> +
> + cmd = virCommandNew(cmdname);
> + virCommandAddArg(cmd, "--version");
> + virCommandSetOutputBuffer(cmd, &version);
> + if (virCommandRun(cmd, NULL) < 0)
> + goto cleanup;
> + virCommandFree(cmd);
> + cmd = NULL;
> +
> + if ((version!=NULL) &&
> + (STREQLEN(version, DNSMASQ_PREFIX_TEXT, strlen(DNSMASQ_PREFIX_TEXT)))) {
> + tmp = version + strlen(DNSMASQ_PREFIX_TEXT);
> + if (virStrToLong_ui(tmp, &tmp, 10, &major) >= 0) {
> + if ((*tmp == '.') &&
> + virStrToLong_ui(tmp + 1, &tmp, 10, &minor) >= 0) {
> + network->dnsmasqVersion = (major * 1000) + minor;
> + }
> + }
> + }
> +
> if (virFileMakePath(NETWORK_PID_DIR) < 0) {
> virReportSystemError(errno,
> _("cannot create directory %s"),
> @@ -939,18 +1048,6 @@ networkStartDhcpDaemon(virNetworkObjPtr network)
> 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;
> @@ -976,6 +1073,7 @@ networkStartDhcpDaemon(virNetworkObjPtr network)
> ret = 0;
> cleanup:
> VIR_FREE(pidfile);
> + VIR_FREE(version);
> virCommandFree(cmd);
> dnsmasqContextFree(dctx);
> return ret;
> @@ -994,31 +1092,35 @@ networkRefreshDhcpDaemon(virNetworkObjPtr network)
> virNetworkIpDefPtr ipdef;
> 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(network);
>
> - /* Look for first IPv4 address that has dhcp defined. */
> - /* We support dhcp config on 1 IPv4 interface only. */
> + VIR_INFO("REFRESH: DhcpDaemon: for %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 1 IPv4 interface.
> + */
> 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 (!ipdef) {
> - /* no <ip> elements, so nothing to do */
> - return 0;
> - }
> -
> - if (!(dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR)))
> - goto cleanup;
> + if (ipdef)
> + if (networkBuildDnsmasqDhcpHostsList(dctx, ipdef) < 0)
> + goto cleanup;
>
> - if (networkBuildDnsmasqHostsfile(dctx, ipdef, network->def->dns) < 0)
> + if (networkBuildDnsmasqHostsList(dctx, network->def->dns) < 0)
> goto cleanup;
>
> if ((ret = dnsmasqSave(dctx)) < 0)
> @@ -1170,6 +1272,12 @@ networkStartRadvd(virNetworkObjPtr network)
> virCommandPtr cmd = NULL;
> int ret = -1;
>
> + /* is dnsmasq handling RA */
> + if (CHECK_DNSMASQ_VERSION()) {
> + ret = 0;
> + goto cleanup;
> + }
> +
> network->radvdPid = -1;
>
> if (!virNetworkDefGetIpByIndex(network->def, AF_INET6, 0)) {
> @@ -1247,6 +1355,10 @@ cleanup:
> static int
> networkRefreshRadvd(virNetworkObjPtr network)
> {
> + /* is dnsmasq handling RA */
> + if (CHECK_DNSMASQ_VERSION())
> + return 0;
> +
> /* if there's no running radvd, just start it */
> if (network->radvdPid <= 0 || (kill(network->radvdPid, 0) < 0))
> return networkStartRadvd(network);
> @@ -1626,9 +1738,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:
> @@ -1646,6 +1768,7 @@ networkRemoveGeneralIp6tablesRules(struct network_driver *driver,
> virNetworkObjPtr network)
> {
> 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);
> }
> @@ -2695,8 +2818,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)
> @@ -2715,17 +2837,36 @@ networkValidate(struct network_driver *driver,
> virNetworkSetBridgeMacAddr(def);
> }
>
> - /* 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 9d1c07b..b0cf3ce 100644
> --- a/src/util/dnsmasq.c
> +++ b/src/util/dnsmasq.c
> @@ -304,7 +304,14 @@ hostsfileAdd(dnsmasqHostsfile *hostsfile,
> if (!(ipstr = virSocketAddrFormat(ip)))
> return -1;
>
> - if (name) {
> + /* the first test determins if it is a dhcpv6 host */
> + if (mac==NULL) {
> + if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,[%s]",
> + name, ipstr) < 0) {
> + goto alloc_error;
> + }
> + }
> + else if (name) {
> if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s,%s",
> mac, ipstr, name) < 0) {
> goto alloc_error;
> diff --git a/tests/networkxml2argvdata/dhcp6-network.argv b/tests/networkxml2argvdata/dhcp6-network.argv
> new file mode 100644
> index 0000000..87c68ac
> --- /dev/null
> +++ b/tests/networkxml2argvdata/dhcp6-network.argv
> @@ -0,0 +1,17 @@
> + at DNSMASQ@ \
> +--strict-order \
> +--bind-interfaces \
> +--domain-needed \
> +--except-interface=lo \
> +--domain=mynet \
> +--expand-hosts \
> +--local=/mynet/ \
> +--conf-file= \
> +--listen-address 2001:db8:ac10:fe01::1 \
> +--listen-address 2001:db8:ac10:fd01::1 \
> +--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..990b403
> --- /dev/null
> +++ b/tests/networkxml2argvdata/dhcp6-network.xml
> @@ -0,0 +1,16 @@
> +<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:fe01::1' prefix='64'>
> + </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>
> +</network>
> diff --git a/tests/networkxml2argvdata/isolated-network.argv b/tests/networkxml2argvdata/isolated-network.argv
> index 13e77b2..97f7b11 100644
> --- a/tests/networkxml2argvdata/isolated-network.argv
> +++ b/tests/networkxml2argvdata/isolated-network.argv
> @@ -1,9 +1,16 @@
> - at DNSMASQ@ --strict-order --bind-interfaces \
> ---local=// --domain-needed --conf-file= \
> ---except-interface lo --dhcp-option=3 --no-resolv \
> + at DNSMASQ@ \
> +--strict-order \
> +--bind-interfaces \
> +--domain-needed \
> +--except-interface=lo \
> +--local=// \
> +--conf-file= \
> +--dhcp-option=3 \
> +--no-resolv \
> --listen-address 192.168.152.1 \
> --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-dhcp6.argv b/tests/networkxml2argvdata/nat-network-dhcp6.argv
> new file mode 100644
> index 0000000..a4795e5
> --- /dev/null
> +++ b/tests/networkxml2argvdata/nat-network-dhcp6.argv
> @@ -0,0 +1,20 @@
> + at DNSMASQ@ \
> +--strict-order \
> +--bind-interfaces \
> +--domain-needed \
> +--except-interface=lo \
> +--local=// \
> +--conf-file= \
> +--listen-address 192.168.122.1 \
> +--listen-address 192.168.123.1 \
> +--listen-address 2001:db8:ac10:fe01::1 \
> +--listen-address 2001:db8:ac10:fd01::1 \
> +--listen-address 10.24.10.1 \
> +--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/nat-network-dhcp6.xml b/tests/networkxml2argvdata/nat-network-dhcp6.xml
> new file mode 100644
> index 0000000..f993a26
> --- /dev/null
> +++ b/tests/networkxml2argvdata/nat-network-dhcp6.xml
> @@ -0,0 +1,26 @@
> +<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:fe01::1' prefix='64'>
> + </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/nat-network-dns-hosts.argv b/tests/networkxml2argvdata/nat-network-dns-hosts.argv
> index 03a0676..32ad19f 100644
> --- a/tests/networkxml2argvdata/nat-network-dns-hosts.argv
> +++ b/tests/networkxml2argvdata/nat-network-dns-hosts.argv
> @@ -1,4 +1,11 @@
> - at DNSMASQ@ --strict-order --bind-interfaces --domain=example.com \
> ---local=/example.com/ --domain-needed \
> ---conf-file= --except-interface lo --listen-address 192.168.122.1 \
> ---expand-hosts --addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts\
> + at DNSMASQ@ \
> +--strict-order \
> +--bind-interfaces \
> +--domain-needed \
> +--except-interface=lo \
> +--domain=example.com \
> +--expand-hosts \
> +--local=/example.com/ \
> +--conf-file= \
> +--listen-address 192.168.122.1 \
> +--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 210a60c..4c21ff1 100644
> --- a/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv
> +++ b/tests/networkxml2argvdata/nat-network-dns-srv-record-minimal.argv
> @@ -1,8 +1,10 @@
> @DNSMASQ@ \
> --strict-order \
> --bind-interfaces \
> ---local=// --domain-needed --conf-file= \
> ---except-interface lo \
> +--domain-needed \
> +--except-interface=lo \
> +--local=// \
> +--conf-file= \
> --srv-host=name.tcp.,,,, \
> --listen-address 192.168.122.1 \
> --listen-address 192.168.123.1 \
> @@ -10,8 +12,9 @@
> --listen-address 2001:db8:ac10:fd01::1 \
> --listen-address 10.24.10.1 \
> --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\
> +--addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts \
> +--dhcp-range=2001:db8:ac10:fe01::1,ra-only\
> diff --git a/tests/networkxml2argvdata/nat-network-dns-srv-record.argv b/tests/networkxml2argvdata/nat-network-dns-srv-record.argv
> index 833d3cd..246dbeb 100644
> --- a/tests/networkxml2argvdata/nat-network-dns-srv-record.argv
> +++ b/tests/networkxml2argvdata/nat-network-dns-srv-record.argv
> @@ -1,8 +1,10 @@
> @DNSMASQ@ \
> --strict-order \
> --bind-interfaces \
> ---local=// --domain-needed --conf-file= \
> ---except-interface lo \
> +--domain-needed \
> +--except-interface=lo \
> +--local=// \
> +--conf-file= \
> --srv-host=name.tcp.test-domain-name,.,1024,10,10 \
> --listen-address 192.168.122.1 \
> --listen-address 192.168.123.1 \
> @@ -10,8 +12,9 @@
> --listen-address 2001:db8:ac10:fd01::1 \
> --listen-address 10.24.10.1 \
> --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\
> +--addn-hosts=/var/lib/libvirt/dnsmasq/default.addnhosts \
> +--dhcp-range=2001:db8:ac10:fe01::1,ra-only\
> diff --git a/tests/networkxml2argvdata/nat-network-dns-txt-record.argv b/tests/networkxml2argvdata/nat-network-dns-txt-record.argv
> index 3481507..8d18f3f 100644
> --- a/tests/networkxml2argvdata/nat-network-dns-txt-record.argv
> +++ b/tests/networkxml2argvdata/nat-network-dns-txt-record.argv
> @@ -1,11 +1,20 @@
> - at DNSMASQ@ --strict-order --bind-interfaces \
> ---local=// --domain-needed --conf-file= \
> ---except-interface lo '--txt-record=example,example value' \
> ---listen-address 192.168.122.1 --listen-address 192.168.123.1 \
> + at DNSMASQ@ \
> +--strict-order \
> +--bind-interfaces \
> +--domain-needed \
> +--except-interface=lo \
> +--local=// \
> +--conf-file= \
> +'--txt-record=example,example value' \
> +--listen-address 192.168.122.1 \
> +--listen-address 192.168.123.1 \
> --listen-address 2001:db8:ac10:fe01::1 \
> ---listen-address 2001:db8:ac10:fd01::1 --listen-address 10.24.10.1 \
> +--listen-address 2001:db8:ac10:fd01::1 \
> +--listen-address 10.24.10.1 \
> --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\
> diff --git a/tests/networkxml2argvdata/nat-network.argv b/tests/networkxml2argvdata/nat-network.argv
> index 37fd2fc..32afeaa 100644
> --- a/tests/networkxml2argvdata/nat-network.argv
> +++ b/tests/networkxml2argvdata/nat-network.argv
> @@ -1,10 +1,19 @@
> - at DNSMASQ@ --strict-order --bind-interfaces \
> ---local=// --domain-needed --conf-file= \
> ---except-interface lo --listen-address 192.168.122.1 \
> ---listen-address 192.168.123.1 --listen-address 2001:db8:ac10:fe01::1 \
> ---listen-address 2001:db8:ac10:fd01::1 --listen-address 10.24.10.1 \
> + at DNSMASQ@ \
> +--strict-order \
> +--bind-interfaces \
> +--domain-needed \
> +--except-interface=lo \
> +--local=// \
> +--conf-file= \
> +--listen-address 192.168.122.1 \
> +--listen-address 192.168.123.1 \
> +--listen-address 2001:db8:ac10:fe01::1 \
> +--listen-address 2001:db8:ac10:fd01::1 \
> +--listen-address 10.24.10.1 \
> --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\
> diff --git a/tests/networkxml2argvdata/netboot-network.argv b/tests/networkxml2argvdata/netboot-network.argv
> index 5408eb7..41e9416 100644
> --- a/tests/networkxml2argvdata/netboot-network.argv
> +++ b/tests/networkxml2argvdata/netboot-network.argv
> @@ -1,10 +1,19 @@
> - at DNSMASQ@ --strict-order --bind-interfaces --domain=example.com \
> ---local=/example.com/ --domain-needed --conf-file= \
> ---except-interface lo --listen-address 192.168.122.1 \
> + at DNSMASQ@ \
> +--strict-order \
> +--bind-interfaces \
> +--domain-needed \
> +--except-interface=lo \
> +--domain=example.com \
> +--expand-hosts \
> +--local=/example.com/ \
> +--conf-file= \
> +--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 21e01e3..eebe560 100644
> --- a/tests/networkxml2argvdata/netboot-proxy-network.argv
> +++ b/tests/networkxml2argvdata/netboot-proxy-network.argv
> @@ -1,9 +1,17 @@
> - at DNSMASQ@ --strict-order --bind-interfaces --domain=example.com \
> ---local=/example.com/ --domain-needed --conf-file= \
> ---except-interface lo --listen-address 192.168.122.1 \
> + at DNSMASQ@ \
> +--strict-order \
> +--bind-interfaces \
> +--domain-needed \
> +--except-interface=lo \
> +--domain=example.com \
> +--expand-hosts \
> +--local=/example.com/ \
> +--conf-file= \
> +--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-dhcphost.argv b/tests/networkxml2argvdata/routed-network-dhcphost.argv
> new file mode 100644
> index 0000000..9f52b98
> --- /dev/null
> +++ b/tests/networkxml2argvdata/routed-network-dhcphost.argv
> @@ -0,0 +1,15 @@
> + at DNSMASQ@ \
> +--strict-order \
> +--bind-interfaces \
> +--domain-needed \
> +--except-interface=lo \
> +--local=// \
> +--conf-file= \
> +--listen-address 192.168.122.1 \
> +--listen-address 2001:db8:ac10:fd01::1 \
> +--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/routed-network-dhcphost.xml b/tests/networkxml2argvdata/routed-network-dhcphost.xml
> new file mode 100644
> index 0000000..38d9ebf
> --- /dev/null
> +++ b/tests/networkxml2argvdata/routed-network-dhcphost.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/routed-network.argv b/tests/networkxml2argvdata/routed-network.argv
> index 9fedb2b..78ad8a2 100644
> --- a/tests/networkxml2argvdata/routed-network.argv
> +++ b/tests/networkxml2argvdata/routed-network.argv
> @@ -1,4 +1,9 @@
> - at DNSMASQ@ --strict-order --bind-interfaces \
> ---local=// --domain-needed --conf-file= \
> ---except-interface lo --listen-address 192.168.122.1 \
> + at DNSMASQ@ \
> +--strict-order \
> +--bind-interfaces \
> +--domain-needed \
> +--except-interface=lo \
> +--local=// \
> +--conf-file= \
> +--listen-address 192.168.122.1 \
> --addn-hosts=/var/lib/libvirt/dnsmasq/local.addnhosts\
> diff --git a/tests/networkxml2argvtest.c b/tests/networkxml2argvtest.c
> index 87519e4..206e2d7 100644
> --- a/tests/networkxml2argvtest.c
> +++ b/tests/networkxml2argvtest.c
> @@ -73,6 +73,7 @@ static int testCompareXMLToArgvFiles(const char *inxml, const char *outargv) {
> goto fail;
>
> obj->def = dev;
> + obj->dnsmasqVersion = 2064;
> dctx = dnsmasqContextNew(dev->name, "/var/lib/libvirt/dnsmasq");
>
> if (dctx == NULL)
> @@ -157,6 +158,9 @@ mymain(void)
> DO_TEST("nat-network-dns-srv-record");
> DO_TEST("nat-network-dns-srv-record-minimal");
> DO_TEST("nat-network-dns-hosts");
> + DO_TEST("nat-network-dhcp6");
> + DO_TEST("routed-network-dhcphost");
> + DO_TEST("dhcp6-network");
>
> return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
> }
More information about the libvir-list
mailing list