diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in index f7c483d39f..41a83fa9d1 100644 --- a/docs/formatnetwork.html.in +++ b/docs/formatnetwork.html.in @@ -782,6 +782,11 @@

Below is another IPv6 varition. Instead of a dhcp range being specified, this example has a couple of IPv6 host definitions. + Note that most of the dhcp host definitions use an "id" (client + id or DUID) since this has proven to be a more reliable way + of specifying the interface and its association with an IPv6 + address. The first is a DUID-LLT, the second a DUID-LL, and + the third a DUID-UUID. Since 1.0.3

@@ -797,7 +802,9 @@
         <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" />
+            <host id="0:1:0:1:18:aa:62:fe:0:16:3e:44:55:66"    ip="2001:db8:ca2:2:3::2" />
+            <host id="0:3:0:1:0:16:3e:11:22:33" name="ralph"  ip="2001:db8:ca2:2:3::3" />
+            <host id="0:4:7e:7d:f0:7d:a8:bc:c5:d2:13:32:11:ed:16:ea:84:63" name="badbob" ip="2001:db8:ca2:2:3::4" />
           </dhcp>
         </ip>
       </network>
@@ -828,6 +835,11 @@

This variation of an isolated network defines only IPv6. + Note that most of the dhcp host definitions use an "id" (client + id or DUID) since this has proven to be a more reliable way + of specifying the interface and its association with an IPv6 + address. The first is a DUID-LLT, the second a DUID-LL, and + the third a DUID-UUID. Since 1.0.3

@@ -837,7 +849,9 @@
         <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" />
+            <host id="0:1:0:1:18:aa:62:fe:0:16:3e:44:55:66" ip="2001:db8:ca2:6:6::2" />
+            <host id="0:3:0:1:0:16:3e:11:22:33" name="dariusz" ip="2001:db8:ca2:6:6::3" />
+            <host id="0:4:7e:7d:f0:7d:a8:bc:c5:d2:13:32:11:ed:16:ea:84:63" name="anita" ip="2001:db8:ca2:6:6::4" />
           </dhcp>
         </ip>
       </network>
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng index cfc820889b..ec1d940218 100644 --- a/docs/schemas/basictypes.rng +++ b/docs/schemas/basictypes.rng @@ -101,6 +101,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + [0]{1,2}:[0]{0,1}[1]:[0]{1,2}:[0]{0,1}[a-fA-F1-9](:[a-fA-F0-9]{1,2}){4}(:[a-fA-F0-9]{1,2}){6,8} + + + + + + + [0]{1,2}:[0]{0,1}[2](:[a-fA-F0-9]{1,2}){4}(:[a-fA-F0-9]{1,2}){1,124} + + + + + + + [0]{1,2}:[0]{0,1}[3]:[0]{1,2}:[0]{0,1}[a-fA-F1-9](:[a-fA-F0-9]{1,2}){6,8} + + + + + + + [0]{1,2}:[0]{0,1}[4](:[a-fA-F0-9]{1,2}){16} + + + + + + + + + + + + + diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng index fff169b982..da7d8adcde 100644 --- a/docs/schemas/network.rng +++ b/docs/schemas/network.rng @@ -280,7 +280,10 @@ - + + + + diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 34fd05abe7..3fc01cf584 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -118,6 +118,7 @@ static void virNetworkDHCPHostDefClear(virNetworkDHCPHostDefPtr def) { VIR_FREE(def->mac); + VIR_FREE(def->id); VIR_FREE(def->name); } @@ -678,7 +679,7 @@ virNetworkDHCPHostDefParseXML(const char *networkName, virNetworkDHCPHostDefPtr host, bool partialOkay) { - char *mac = NULL, *name = NULL, *ip = NULL; + char *mac = NULL, *name = NULL, *ip = NULL, *id = NULL; virMacAddr addr; virSocketAddr inaddr; int ret = -1; @@ -707,10 +708,20 @@ virNetworkDHCPHostDefParseXML(const char *networkName, } } + id = virXMLPropString(node, "id"); + if (id) { + char *cp = id + strspn(id, "0123456789abcdefABCDEF:"); + if (*cp) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid character '%c' in id '%s' of network '%s'"), + *cp, id, networkName); + } + } + name = virXMLPropString(node, "name"); if (name && (!c_isalpha(name[0]))) { virReportError(VIR_ERR_XML_ERROR, - _("Cannot use name address '%s' in network '%s'"), + _("Cannot use host name '%s' in network '%s'"), name, networkName); goto cleanup; } @@ -738,10 +749,10 @@ virNetworkDHCPHostDefParseXML(const char *networkName, * address or name (IPv4) */ if (VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET6)) { - if (!name) { + if (!(id || name)) { virReportError(VIR_ERR_XML_ERROR, _("Static host definition in IPv6 network '%s' " - "must have name attribute"), + "must have id or name attribute"), networkName); goto cleanup; } @@ -763,6 +774,8 @@ virNetworkDHCPHostDefParseXML(const char *networkName, host->mac = mac; mac = NULL; + host->id = id; + id = NULL; host->name = name; name = NULL; if (ip) @@ -771,6 +784,7 @@ virNetworkDHCPHostDefParseXML(const char *networkName, cleanup: VIR_FREE(mac); + VIR_FREE(id); VIR_FREE(name); VIR_FREE(ip); return ret; @@ -2189,6 +2203,8 @@ virNetworkIpDefFormat(virBufferPtr buf, virBufferAddLit(buf, "hosts[ii].mac) virBufferAsprintf(buf, "mac='%s' ", def->hosts[ii].mac); + if (def->hosts[ii].id) + virBufferAsprintf(buf, "id='%s' ", def->hosts[ii].id); if (def->hosts[ii].name) virBufferAsprintf(buf, "name='%s' ", def->hosts[ii].name); if (VIR_SOCKET_ADDR_VALID(&def->hosts[ii].ip)) { diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index e7a4f95f2b..c509915cc1 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -66,6 +66,7 @@ typedef struct _virNetworkDHCPHostDef virNetworkDHCPHostDef; typedef virNetworkDHCPHostDef *virNetworkDHCPHostDefPtr; struct _virNetworkDHCPHostDef { char *mac; + char *id; char *name; virSocketAddr ip; }; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 0c3f778da8..0932cf8e5e 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -599,7 +599,8 @@ networkBuildDnsmasqDhcpHostsList(dnsmasqContext *dctx, for (i = 0; i < ipdef->nhosts; i++) { virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]); if (VIR_SOCKET_ADDR_VALID(&host->ip)) - if (dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, host->name, ipv6) < 0) + if (dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, + host->name, host->id, ipv6) < 0) return -1; } diff --git a/src/util/virdnsmasq.c b/src/util/virdnsmasq.c index 6637a8977d..2e63d83af2 100644 --- a/src/util/virdnsmasq.c +++ b/src/util/virdnsmasq.c @@ -303,6 +303,7 @@ hostsfileAdd(dnsmasqHostsfile *hostsfile, const char *mac, virSocketAddr *ip, const char *name, + const char *id, bool ipv6) { char *ipstr = NULL; @@ -314,11 +315,20 @@ hostsfileAdd(dnsmasqHostsfile *hostsfile, /* 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 (name && id) { + if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, + "id:%s,%s,[%s]", id, name, ipstr) < 0) + goto alloc_error; + } else if (name && !id) { + if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, + "%s,[%s]", name, ipstr) < 0) + goto alloc_error; + } else if (!name && id) { + if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, + "id:%s,[%s]", id, ipstr) < 0) + goto alloc_error; + } + } else if (name && mac) { if (virAsprintf(&hostsfile->hosts[hostsfile->nhosts].host, "%s,%s,%s", mac, ipstr, name) < 0) goto alloc_error; @@ -511,9 +521,10 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx, const char *mac, virSocketAddr *ip, const char *name, + const char *id, bool ipv6) { - return hostsfileAdd(ctx->hostsfile, mac, ip, name, ipv6); + return hostsfileAdd(ctx->hostsfile, mac, ip, name, id, ipv6); } /* diff --git a/src/util/virdnsmasq.h b/src/util/virdnsmasq.h index a97d3e6019..ed560da45d 100644 --- a/src/util/virdnsmasq.h +++ b/src/util/virdnsmasq.h @@ -86,6 +86,7 @@ int dnsmasqAddDhcpHost(dnsmasqContext *ctx, const char *mac, virSocketAddr *ip, const char *name, + const char *id, bool ipv6); int dnsmasqAddHost(dnsmasqContext *ctx, virSocketAddr *ip, diff --git a/tests/networkxml2confdata/dhcp6-nat-network.xml b/tests/networkxml2confdata/dhcp6-nat-network.xml index 72103f7139..4259173854 100644 --- a/tests/networkxml2confdata/dhcp6-nat-network.xml +++ b/tests/networkxml2confdata/dhcp6-nat-network.xml @@ -15,8 +15,11 @@ - + + + + diff --git a/tests/networkxml2confdata/dhcp6-network.xml b/tests/networkxml2confdata/dhcp6-network.xml index 311013ad52..776737e26c 100644 --- a/tests/networkxml2confdata/dhcp6-network.xml +++ b/tests/networkxml2confdata/dhcp6-network.xml @@ -7,8 +7,11 @@ - + + + + diff --git a/tests/networkxml2confdata/dhcp6host-routed-network.xml b/tests/networkxml2confdata/dhcp6host-routed-network.xml index 38d9ebf892..2693d872fc 100644 --- a/tests/networkxml2confdata/dhcp6host-routed-network.xml +++ b/tests/networkxml2confdata/dhcp6host-routed-network.xml @@ -12,8 +12,11 @@ - + + + + diff --git a/tests/networkxml2xmlin/dhcp6host-routed-network.xml b/tests/networkxml2xmlin/dhcp6host-routed-network.xml new file mode 100644 index 0000000000..2693d872fc --- /dev/null +++ b/tests/networkxml2xmlin/dhcp6host-routed-network.xml @@ -0,0 +1,22 @@ + + local + 81ff0d90-c91e-6742-64da-4a736edb9a9b + + + + + + + + + + + + + + + + + + + diff --git a/tests/networkxml2xmlout/dhcp6host-routed-network.xml b/tests/networkxml2xmlout/dhcp6host-routed-network.xml new file mode 100644 index 0000000000..7305043f37 --- /dev/null +++ b/tests/networkxml2xmlout/dhcp6host-routed-network.xml @@ -0,0 +1,24 @@ + + local + 81ff0d90-c91e-6742-64da-4a736edb9a9b + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c index 1cd74d1018..1063435651 100644 --- a/tests/networkxml2xmltest.c +++ b/tests/networkxml2xmltest.c @@ -92,6 +92,7 @@ mymain(void) } while (0) #define DO_TEST(name) DO_TEST_FULL(name, 0) + DO_TEST("dhcp6host-routed-network"); DO_TEST("empty-allow-ipv6"); DO_TEST("isolated-network"); DO_TEST("routed-network");