If an user is trying to configure a dhcp neetwork settings, it is not
possible to change the leasetime of a range or a host entry. This is
available using dnsmasq extra options, but they are associated with
dhcp-range or dhcp-hosts fields. This patch implements a leasetime for
range and hosts tags. They can be defined under that settings:
<dhcp>
<range ...>
<lease/>
</range>
<host ...>
<lease/>
</host>
</dhcp>
Resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=913446
Signed-off-by: Julio Faracco <jcfaracco(a)gmail.com>
---
docs/schemas/basictypes.rng | 8 ++
docs/schemas/network.rng | 20 +++++
src/conf/network_conf.c | 159 +++++++++++++++++++++++++++++++-----
src/conf/network_conf.h | 27 +++++-
src/libvirt_private.syms | 3 +
src/network/bridge_driver.c | 56 +++++++++++--
src/network/bridge_driver.h | 1 +
src/test/test_driver.c | 2 +-
src/util/virdnsmasq.c | 68 ++++++++++-----
src/util/virdnsmasq.h | 3 +
src/vbox/vbox_network.c | 16 ++--
11 files changed, 305 insertions(+), 58 deletions(-)
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
index 81465273c8..271ed18afb 100644
--- a/docs/schemas/basictypes.rng
+++ b/docs/schemas/basictypes.rng
@@ -607,4 +607,12 @@
</element>
</define>
+ <define name="leaseUnit">
+ <choice>
+ <value>seconds</value>
+ <value>mins</value>
+ <value>hours</value>
+ </choice>
+ </define>
+
</grammar>
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 60453225d6..88b6f4dfdd 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -371,6 +371,16 @@
<element name="range">
<attribute name="start"><ref
name="ipAddr"/></attribute>
<attribute name="end"><ref
name="ipAddr"/></attribute>
+ <interleave>
+ <optional>
+ <element name="lease">
+ <attribute name="expiry"><ref
name="unsignedLong"/></attribute>
+ <optional>
+ <attribute name="unit"><ref
name="leaseUnit"/></attribute>
+ </optional>
+ </element>
+ </optional>
+ </interleave>
</element>
</zeroOrMore>
<zeroOrMore>
@@ -388,6 +398,16 @@
<attribute
name="name"><text/></attribute>
</choice>
<attribute name="ip"><ref
name="ipAddr"/></attribute>
+ <interleave>
+ <optional>
+ <element name="lease">
+ <attribute name="expiry"><ref
name="unsignedLong"/></attribute>
+ <optional>
+ <attribute name="unit"><ref
name="leaseUnit"/></attribute>
+ </optional>
+ </element>
+ </optional>
+ </interleave>
</element>
</zeroOrMore>
<optional>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 819b645df7..286a0edb7c 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -70,6 +70,13 @@ VIR_ENUM_IMPL(virNetworkTaint,
"hook-script",
);
+VIR_ENUM_IMPL(virNetworkDHCPLeaseTimeUnit,
+ VIR_NETWORK_DHCP_LEASETIME_UNIT_LAST,
+ "seconds",
+ "mins",
+ "hours",
+);
+
static virClassPtr virNetworkXMLOptionClass;
static void
@@ -132,12 +139,20 @@ virNetworkForwardPfDefClear(virNetworkForwardPfDefPtr def)
}
+static void
+virNetworkDHCPLeaseTimeDefClear(virNetworkDHCPLeaseTimeDefPtr lease)
+{
+ VIR_FREE(lease);
+}
+
+
static void
virNetworkDHCPHostDefClear(virNetworkDHCPHostDefPtr def)
{
VIR_FREE(def->mac);
VIR_FREE(def->id);
VIR_FREE(def->name);
+ VIR_FREE(def->lease);
}
@@ -145,6 +160,9 @@ static void
virNetworkIPDefClear(virNetworkIPDefPtr def)
{
VIR_FREE(def->family);
+
+ while (def->nranges)
+ virNetworkDHCPLeaseTimeDefClear(def->ranges[--def->nranges].lease);
VIR_FREE(def->ranges);
while (def->nhosts)
@@ -391,11 +409,55 @@ int virNetworkIPDefNetmask(const virNetworkIPDef *def,
static int
-virSocketAddrRangeParseXML(const char *networkName,
- virNetworkIPDefPtr ipdef,
- xmlNodePtr node,
- virSocketAddrRangePtr range)
+virNetworkDHCPLeaseTimeDefParseXML(virNetworkDHCPLeaseTimeDefPtr *lease,
+ xmlNodePtr node)
+{
+ virNetworkDHCPLeaseTimeDefPtr new_lease = *lease;
+ g_autofree char *expiry = NULL, *unit = NULL;
+
+ if (!(expiry = virXMLPropString(node, "expiry")))
+ return 0;
+
+ if (VIR_ALLOC(new_lease) < 0)
+ return -1;
+
+ if (virStrToLong_ul(expiry, NULL, 10, &new_lease->expiry) < 0)
+ return -1;
+
+ if (!(unit = virXMLPropString(node, "unit")))
+ new_lease->unit = VIR_NETWORK_DHCP_LEASETIME_UNIT_MINUTES;
+ else
+ new_lease->unit = virNetworkDHCPLeaseTimeUnitTypeFromString(unit);
+
+ /* infinite */
+ if (new_lease->expiry > 0) {
+ /* This boundary check is related to dnsmasq man page settings:
+ * "The minimum lease time is two minutes." */
+ if ((new_lease->unit == VIR_NETWORK_DHCP_LEASETIME_UNIT_SECONDS &&
+ new_lease->expiry < 120) ||
+ (new_lease->unit == VIR_NETWORK_DHCP_LEASETIME_UNIT_MINUTES &&
+ new_lease->expiry < 2)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("The minimum lease time should be greater "
+ "than 2 minutes"));
+ return -1;
+ }
+ }
+
+ *lease = new_lease;
+
+ return 0;
+}
+
+
+static int
+virNetworkDHCPRangeDefParseXML(const char *networkName,
+ virNetworkIPDefPtr ipdef,
+ xmlNodePtr node,
+ virNetworkDHCPRangeDefPtr range)
{
+ virSocketAddrRangePtr addr = &range->addr;
+ xmlNodePtr cur = node->children;
char *start = NULL, *end = NULL;
int ret = -1;
@@ -405,7 +467,7 @@ virSocketAddrRangeParseXML(const char *networkName,
networkName);
goto cleanup;
}
- if (virSocketAddrParse(&range->start, start, AF_UNSPEC) < 0)
+ if (virSocketAddrParse(&addr->start, start, AF_UNSPEC) < 0)
goto cleanup;
if (!(end = virXMLPropString(node, "end"))) {
@@ -414,14 +476,24 @@ virSocketAddrRangeParseXML(const char *networkName,
networkName);
goto cleanup;
}
- if (virSocketAddrParse(&range->end, end, AF_UNSPEC) < 0)
+ if (virSocketAddrParse(&addr->end, end, AF_UNSPEC) < 0)
goto cleanup;
/* do a sanity check of the range */
- if (virSocketAddrGetRange(&range->start, &range->end,
&ipdef->address,
+ if (virSocketAddrGetRange(&addr->start, &addr->end,
&ipdef->address,
virNetworkIPDefPrefix(ipdef)) < 0)
goto cleanup;
+ while (cur != NULL) {
+ if (cur->type == XML_ELEMENT_NODE &&
+ virXMLNodeNameEqual(cur, "lease")) {
+
+ if (virNetworkDHCPLeaseTimeDefParseXML(&range->lease, cur) < 0)
+ goto cleanup;
+ }
+ cur = cur->next;
+ }
+
ret = 0;
cleanup:
@@ -441,6 +513,7 @@ virNetworkDHCPHostDefParseXML(const char *networkName,
char *mac = NULL, *name = NULL, *ip = NULL, *id = NULL;
virMacAddr addr;
virSocketAddr inaddr;
+ xmlNodePtr cur = node->children;
int ret = -1;
mac = virXMLPropString(node, "mac");
@@ -533,6 +606,16 @@ virNetworkDHCPHostDefParseXML(const char *networkName,
}
}
+ while (cur != NULL) {
+ if (cur->type == XML_ELEMENT_NODE &&
+ virXMLNodeNameEqual(cur, "lease")) {
+
+ if (virNetworkDHCPLeaseTimeDefParseXML(&host->lease, cur) < 0)
+ goto cleanup;
+ }
+ cur = cur->next;
+ }
+
host->mac = mac;
mac = NULL;
host->id = id;
@@ -559,7 +642,7 @@ virNetworkDHCPDefParseXML(const char *networkName,
{
int ret = -1;
xmlNodePtr cur;
- virSocketAddrRange range;
+ virNetworkDHCPRangeDef range;
virNetworkDHCPHostDef host;
memset(&range, 0, sizeof(range));
@@ -570,7 +653,7 @@ virNetworkDHCPDefParseXML(const char *networkName,
if (cur->type == XML_ELEMENT_NODE &&
virXMLNodeNameEqual(cur, "range")) {
- if (virSocketAddrRangeParseXML(networkName, def, cur, &range) < 0)
+ if (virNetworkDHCPRangeDefParseXML(networkName, def, cur, &range) <
0)
goto cleanup;
if (VIR_APPEND_ELEMENT(def->ranges, def->nranges, range) < 0)
goto cleanup;
@@ -583,7 +666,6 @@ virNetworkDHCPDefParseXML(const char *networkName,
goto cleanup;
if (VIR_APPEND_ELEMENT(def->hosts, def->nhosts, host) < 0)
goto cleanup;
-
} else if (VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET) &&
cur->type == XML_ELEMENT_NODE &&
virXMLNodeNameEqual(cur, "bootp")) {
@@ -2300,20 +2382,39 @@ virNetworkIPDefFormat(virBufferPtr buf,
virBufferAdjustIndent(buf, 2);
for (i = 0; i < def->nranges; i++) {
- char *saddr = virSocketAddrFormat(&def->ranges[i].start);
+ virSocketAddrRange addr = def->ranges[i].addr;
+ virNetworkDHCPLeaseTimeDefPtr lease = def->ranges[i].lease;
+
+ char *saddr = virSocketAddrFormat(&addr.start);
if (!saddr)
return -1;
- char *eaddr = virSocketAddrFormat(&def->ranges[i].end);
+ char *eaddr = virSocketAddrFormat(&addr.end);
if (!eaddr) {
VIR_FREE(saddr);
return -1;
}
- virBufferAsprintf(buf, "<range start='%s'
end='%s'/>\n",
+ virBufferAsprintf(buf, "<range start='%s'
end='%s'",
saddr, eaddr);
+ if (lease) {
+ virBufferAddLit(buf, ">\n");
+ virBufferAdjustIndent(buf, 2);
+ if (!lease->expiry) {
+ virBufferAddLit(buf, "<lease
expiry='0'/>\n");
+ } else {
+ virBufferAsprintf(buf, "<lease expiry='%lu'
unit='%s'/>\n",
+ lease->expiry,
+
virNetworkDHCPLeaseTimeUnitTypeToString(lease->unit));
+ }
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</range>\n");
+ } else {
+ virBufferAddLit(buf, "/>\n");
+ }
VIR_FREE(saddr);
VIR_FREE(eaddr);
}
for (i = 0; i < def->nhosts; i++) {
+ virNetworkDHCPLeaseTimeDefPtr lease = def->hosts[i].lease;
virBufferAddLit(buf, "<host");
if (def->hosts[i].mac)
virBufferAsprintf(buf, " mac='%s'",
def->hosts[i].mac);
@@ -2328,7 +2429,21 @@ virNetworkIPDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " ip='%s'", ipaddr);
VIR_FREE(ipaddr);
}
- virBufferAddLit(buf, "/>\n");
+ if (lease) {
+ virBufferAddLit(buf, ">\n");
+ virBufferAdjustIndent(buf, 2);
+ if (!lease->expiry) {
+ virBufferAddLit(buf, "<lease
expiry='0'/>\n");
+ } else {
+ virBufferAsprintf(buf, "<lease expiry='%lu'
unit='%s'/>\n",
+ lease->expiry,
+
virNetworkDHCPLeaseTimeUnitTypeToString(lease->unit));
+ }
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</host>\n");
+ } else {
+ virBufferAddLit(buf, "/>\n");
+ }
}
if (def->bootfile) {
virBufferEscapeString(buf, "<bootp file='%s'",
@@ -2343,7 +2458,6 @@ virNetworkIPDefFormat(virBufferPtr buf,
virBufferAddLit(buf, "/>\n");
}
-
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</dhcp>\n");
}
@@ -3080,7 +3194,7 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def,
{
size_t i;
virNetworkIPDefPtr ipdef = virNetworkIPDefByIndex(def, parentIndex);
- virSocketAddrRange range;
+ virNetworkDHCPRangeDef range;
memset(&range, 0, sizeof(range));
@@ -3100,11 +3214,11 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def,
return -1;
}
- if (virSocketAddrRangeParseXML(def->name, ipdef, ctxt->node, &range) <
0)
+ if (virNetworkDHCPRangeDefParseXML(def->name, ipdef, ctxt->node, &range)
< 0)
return -1;
if (VIR_SOCKET_ADDR_FAMILY(&ipdef->address)
- != VIR_SOCKET_ADDR_FAMILY(&range.start)) {
+ != VIR_SOCKET_ADDR_FAMILY(&range.addr.start)) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("the address family of a dhcp range must match "
"the address family of the dhcp element's
parent"));
@@ -3113,8 +3227,9 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def,
/* check if an entry with same name/address/ip already exists */
for (i = 0; i < ipdef->nranges; i++) {
- if (virSocketAddrEqual(&range.start, &ipdef->ranges[i].start)
&&
- virSocketAddrEqual(&range.end, &ipdef->ranges[i].end)) {
+ virSocketAddrRange addr = ipdef->ranges[i].addr;
+ if (virSocketAddrEqual(&range.addr.start, &addr.start) &&
+ virSocketAddrEqual(&range.addr.end, &addr.end)) {
break;
}
}
@@ -3126,8 +3241,8 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def,
return -1;
if (i < ipdef->nranges) {
- char *startip = virSocketAddrFormat(&range.start);
- char *endip = virSocketAddrFormat(&range.end);
+ char *startip = virSocketAddrFormat(&range.addr.start);
+ char *endip = virSocketAddrFormat(&range.addr.end);
virReportError(VIR_ERR_OPERATION_INVALID,
_("there is an existing dhcp range entry in "
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index db7243eef5..f2dc388ef0 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -80,6 +80,16 @@ typedef enum {
VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST,
} virNetworkForwardHostdevDeviceType;
+typedef enum {
+ VIR_NETWORK_DHCP_LEASETIME_UNIT_SECONDS = 0,
+ VIR_NETWORK_DHCP_LEASETIME_UNIT_MINUTES,
+ VIR_NETWORK_DHCP_LEASETIME_UNIT_HOURS,
+
+ VIR_NETWORK_DHCP_LEASETIME_UNIT_LAST,
+} virNetworkDHCPLeaseTimeUnitType;
+
+VIR_ENUM_DECL(virNetworkDHCPLeaseTimeUnit);
+
/* The backend driver used for devices from the pool. Currently used
* only for PCI devices (vfio vs. kvm), but could be used for other
* device types in the future.
@@ -94,6 +104,20 @@ typedef enum {
VIR_ENUM_DECL(virNetworkForwardDriverName);
+typedef struct _virNetworkDHCPLeaseTimeDef virNetworkDHCPLeaseTimeDef;
+typedef virNetworkDHCPLeaseTimeDef *virNetworkDHCPLeaseTimeDefPtr;
+struct _virNetworkDHCPLeaseTimeDef {
+ unsigned long expiry;
+ virNetworkDHCPLeaseTimeUnitType unit;
+};
+
+typedef struct _virNetworkDHCPRangeDef virNetworkDHCPRangeDef;
+typedef virNetworkDHCPRangeDef *virNetworkDHCPRangeDefPtr;
+struct _virNetworkDHCPRangeDef {
+ virSocketAddrRange addr;
+ virNetworkDHCPLeaseTimeDefPtr lease;
+};
+
typedef struct _virNetworkDHCPHostDef virNetworkDHCPHostDef;
typedef virNetworkDHCPHostDef *virNetworkDHCPHostDefPtr;
struct _virNetworkDHCPHostDef {
@@ -101,6 +125,7 @@ struct _virNetworkDHCPHostDef {
char *id;
char *name;
virSocketAddr ip;
+ virNetworkDHCPLeaseTimeDefPtr lease;
};
typedef struct _virNetworkDNSTxtDef virNetworkDNSTxtDef;
@@ -171,7 +196,7 @@ struct _virNetworkIPDef {
int localPTR; /* virTristateBool */
size_t nranges; /* Zero or more dhcp ranges */
- virSocketAddrRangePtr ranges;
+ virNetworkDHCPRangeDefPtr ranges;
size_t nhosts; /* Zero or more dhcp hosts */
virNetworkDHCPHostDefPtr hosts;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 182a570382..b7e18c146d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -770,6 +770,8 @@ virNetworkDefParseNode;
virNetworkDefParseString;
virNetworkDefParseXML;
virNetworkDefUpdateSection;
+virNetworkDHCPLeaseTimeUnitTypeFromString;
+virNetworkDHCPLeaseTimeUnitTypeToString;
virNetworkForwardTypeToString;
virNetworkIPDefNetmask;
virNetworkIPDefPrefix;
@@ -1948,6 +1950,7 @@ dnsmasqCapsRefresh;
dnsmasqContextFree;
dnsmasqContextNew;
dnsmasqDelete;
+dnsmasqDhcpHostsToString;
dnsmasqReload;
dnsmasqSave;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index f06099297a..db17e6b2fd 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -966,6 +966,30 @@ static int networkConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED)
}
+static char *
+networkBuildDnsmasqLeaseTime(virNetworkDHCPLeaseTimeDefPtr lease)
+{
+ char *leasetime = NULL;
+ const char *unit;
+ g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+
+ if (!lease)
+ return NULL;
+
+ if (lease->expiry == 0) {
+ virBufferAddLit(&buf, "infinite");
+ } else {
+ unit = virNetworkDHCPLeaseTimeUnitTypeToString(lease->unit);
+ /* We get only first compatible char from string: 's', 'm' or
'h' */
+ virBufferAsprintf(&buf, "%lu%c", lease->expiry, unit[0]);
+ }
+
+ leasetime = virBufferContentAndReset(&buf);
+
+ return leasetime;
+}
+
+
/* the following does not build a file, it builds a list
* which is later saved into a file
*/
@@ -975,14 +999,18 @@ networkBuildDnsmasqDhcpHostsList(dnsmasqContext *dctx,
{
size_t i;
bool ipv6 = false;
+ g_autofree char *leasetime = NULL;
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
ipv6 = true;
for (i = 0; i < ipdef->nhosts; i++) {
virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]);
+
+ leasetime = networkBuildDnsmasqLeaseTime(host->lease);
if (VIR_SOCKET_ADDR_VALID(&host->ip))
if (dnsmasqAddDhcpHost(dctx, host->mac, &host->ip,
- host->name, host->id, ipv6) < 0)
+ host->name, host->id, leasetime,
+ ipv6) < 0)
return -1;
}
@@ -1052,6 +1080,7 @@ int
networkDnsmasqConfContents(virNetworkObjPtr obj,
const char *pidfile,
char **configstr,
+ char **hostsfilestr,
dnsmasqContext *dctx,
dnsmasqCapsPtr caps G_GNUC_UNUSED)
{
@@ -1381,13 +1410,15 @@ networkDnsmasqConfContents(virNetworkObjPtr obj,
}
for (r = 0; r < ipdef->nranges; r++) {
int thisRange;
+ virNetworkDHCPRangeDef range = ipdef->ranges[r];
+ g_autofree char *leasetime = NULL;
- if (!(saddr = virSocketAddrFormat(&ipdef->ranges[r].start)) ||
- !(eaddr = virSocketAddrFormat(&ipdef->ranges[r].end)))
+ if (!(saddr = virSocketAddrFormat(&range.addr.start)) ||
+ !(eaddr = virSocketAddrFormat(&range.addr.end)))
goto cleanup;
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) {
- virBufferAsprintf(&configbuf, "dhcp-range=%s,%s,%d\n",
+ virBufferAsprintf(&configbuf, "dhcp-range=%s,%s,%d",
saddr, eaddr, prefix);
} else {
/* IPv4 - dnsmasq requires a netmask rather than prefix */
@@ -1404,14 +1435,19 @@ networkDnsmasqConfContents(virNetworkObjPtr obj,
if (!(netmaskStr = virSocketAddrFormat(&netmask)))
goto cleanup;
- virBufferAsprintf(&configbuf, "dhcp-range=%s,%s,%s\n",
+ virBufferAsprintf(&configbuf, "dhcp-range=%s,%s,%s",
saddr, eaddr, netmaskStr);
}
+ if ((leasetime = networkBuildDnsmasqLeaseTime(range.lease)))
+ virBufferAsprintf(&configbuf, ",%s", leasetime);
+
+ virBufferAddLit(&configbuf, "\n");
+
VIR_FREE(saddr);
VIR_FREE(eaddr);
- thisRange = virSocketAddrGetRange(&ipdef->ranges[r].start,
- &ipdef->ranges[r].end,
+ thisRange = virSocketAddrGetRange(&range.addr.start,
+ &range.addr.end,
&ipdef->address,
virNetworkIPDefPrefix(ipdef));
if (thisRange < 0)
@@ -1440,6 +1476,9 @@ networkDnsmasqConfContents(virNetworkObjPtr obj,
if (networkBuildDnsmasqDhcpHostsList(dctx, ipdef) < 0)
goto cleanup;
+ *hostsfilestr = dnsmasqDhcpHostsToString(dctx->hostsfile->hosts,
+ dctx->hostsfile->nhosts);
+
/* Note: the following is IPv4 only */
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET)) {
if (ipdef->nranges || ipdef->nhosts) {
@@ -1549,11 +1588,12 @@ networkBuildDhcpDaemonCommandLine(virNetworkDriverStatePtr
driver,
int ret = -1;
char *configfile = NULL;
char *configstr = NULL;
+ char *hostsfilestr = NULL;
char *leaseshelper_path = NULL;
virNetworkObjSetDnsmasqPid(obj, -1);
- if (networkDnsmasqConfContents(obj, pidfile, &configstr,
+ if (networkDnsmasqConfContents(obj, pidfile, &configstr, &hostsfilestr,
dctx, dnsmasq_caps) < 0)
goto cleanup;
if (!configstr)
diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h
index d35850d293..fb0ccad4b1 100644
--- a/src/network/bridge_driver.h
+++ b/src/network/bridge_driver.h
@@ -46,5 +46,6 @@ int
networkDnsmasqConfContents(virNetworkObjPtr obj,
const char *pidfile,
char **configstr,
+ char **hostsfilestr,
dnsmasqContext *dctx,
dnsmasqCapsPtr caps);
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 7759847c2d..0506147888 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -5025,7 +5025,7 @@ testDomainInterfaceAddressFromNet(testDriverPtr driver,
net_def->ips->prefix);
if (net_def->ips->nranges > 0)
- addr = net_def->ips->ranges[0].start;
+ addr = net_def->ips->ranges[0].addr.start;
else
addr = net_def->ips->address;
diff --git a/src/util/virdnsmasq.c b/src/util/virdnsmasq.c
index adc6f96bb6..ee4c458290 100644
--- a/src/util/virdnsmasq.c
+++ b/src/util/virdnsmasq.c
@@ -296,11 +296,14 @@ hostsfileAdd(dnsmasqHostsfile *hostsfile,
virSocketAddr *ip,
const char *name,
const char *id,
+ const char *leasetime,
bool ipv6)
{
- char *ipstr = NULL;
+ g_autofree char *ipstr = NULL;
+ g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+
if (VIR_REALLOC_N(hostsfile->hosts, hostsfile->nhosts + 1) < 0)
- goto error;
+ return -1;
if (!(ipstr = virSocketAddrFormat(ip)))
return -1;
@@ -308,34 +311,30 @@ hostsfileAdd(dnsmasqHostsfile *hostsfile,
/* the first test determines if it is a dhcpv6 host */
if (ipv6) {
if (name && id) {
- hostsfile->hosts[hostsfile->nhosts].host =
g_strdup_printf("id:%s,%s,[%s]",
- id, name, ipstr);
+ virBufferAsprintf(&buf, "id:%s,%s", id, name);
} else if (name && !id) {
- hostsfile->hosts[hostsfile->nhosts].host =
g_strdup_printf("%s,[%s]",
- name, ipstr);
+ virBufferAsprintf(&buf, "%s", name);
} else if (!name && id) {
- hostsfile->hosts[hostsfile->nhosts].host =
g_strdup_printf("id:%s,[%s]",
- id, ipstr);
+ virBufferAsprintf(&buf, "id:%s", id);
}
+ virBufferAsprintf(&buf, ",[%s]", ipstr);
} else if (name && mac) {
- hostsfile->hosts[hostsfile->nhosts].host =
g_strdup_printf("%s,%s,%s",
- mac, ipstr, name);
+ virBufferAsprintf(&buf, "%s,%s,%s", mac, ipstr, name);
} else if (name && !mac) {
- hostsfile->hosts[hostsfile->nhosts].host =
g_strdup_printf("%s,%s", name,
- ipstr);
+ virBufferAsprintf(&buf, "%s,%s", name, ipstr);
} else {
- hostsfile->hosts[hostsfile->nhosts].host =
g_strdup_printf("%s,%s", mac,
- ipstr);
+ virBufferAsprintf(&buf, "%s,%s", mac, ipstr);
}
- VIR_FREE(ipstr);
+
+ if (leasetime)
+ virBufferAsprintf(&buf, ",%s", leasetime);
+
+ if (!(hostsfile->hosts[hostsfile->nhosts].host =
virBufferContentAndReset(&buf)))
+ return -1;
hostsfile->nhosts++;
return 0;
-
- error:
- VIR_FREE(ipstr);
- return -1;
}
static dnsmasqHostsfile *
@@ -501,9 +500,10 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx,
virSocketAddr *ip,
const char *name,
const char *id,
+ const char *leasetime,
bool ipv6)
{
- return hostsfileAdd(ctx->hostsfile, mac, ip, name, id, ipv6);
+ return hostsfileAdd(ctx->hostsfile, mac, ip, name, id, leasetime, ipv6);
}
/*
@@ -862,3 +862,31 @@ dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags flag)
{
return caps && virBitmapIsBitSet(caps->flags, flag);
}
+
+
+/** dnsmasqDhcpHostsToString:
+ *
+ * Turns a vector of dnsmasqDhcpHost into the string that is ought to be
+ * stored in the hostsfile, this functionality is split to make hostsfiles
+ * testable. Returs NULL if nhosts is 0.
+ */
+char *
+dnsmasqDhcpHostsToString(dnsmasqDhcpHost *hosts,
+ unsigned int nhosts)
+{
+ size_t i;
+ char *result = NULL;
+ virBuffer hostsfilebuf = VIR_BUFFER_INITIALIZER;
+
+ if (nhosts == 0)
+ goto cleanup;
+
+ for (i = 0; i < nhosts; i++)
+ virBufferAsprintf(&hostsfilebuf, "%s\n", hosts[i].host);
+
+ result = virBufferContentAndReset(&hostsfilebuf);
+
+ cleanup:
+ virBufferFreeAndReset(&hostsfilebuf);
+ return result;
+}
diff --git a/src/util/virdnsmasq.h b/src/util/virdnsmasq.h
index ff0e56d635..4c14bc6ca7 100644
--- a/src/util/virdnsmasq.h
+++ b/src/util/virdnsmasq.h
@@ -87,6 +87,7 @@ int dnsmasqAddDhcpHost(dnsmasqContext *ctx,
virSocketAddr *ip,
const char *name,
const char *id,
+ const char *leasetime,
bool ipv6);
int dnsmasqAddHost(dnsmasqContext *ctx,
virSocketAddr *ip,
@@ -104,6 +105,8 @@ int dnsmasqCapsRefresh(dnsmasqCapsPtr *caps, const char *binaryPath);
bool dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags flag);
const char *dnsmasqCapsGetBinaryPath(dnsmasqCapsPtr caps);
unsigned long dnsmasqCapsGetVersion(dnsmasqCapsPtr caps);
+char *dnsmasqDhcpHostsToString(dnsmasqDhcpHost *hosts,
+ unsigned int nhosts);
#define DNSMASQ_DHCPv6_MAJOR_REQD 2
#define DNSMASQ_DHCPv6_MINOR_REQD 64
diff --git a/src/vbox/vbox_network.c b/src/vbox/vbox_network.c
index 19b4d23ed8..cf273b9a48 100644
--- a/src/vbox/vbox_network.c
+++ b/src/vbox/vbox_network.c
@@ -379,6 +379,7 @@ vboxNetworkDefineCreateXML(virConnectPtr conn, const char *xml, bool
start)
virNetworkIPDefPtr ipdef = NULL;
unsigned char uuid[VIR_UUID_BUFLEN];
vboxIID vboxnetiid;
+ virSocketAddrRange addr;
virSocketAddr netmask;
IHost *host = NULL;
virNetworkPtr ret = NULL;
@@ -440,9 +441,10 @@ vboxNetworkDefineCreateXML(virConnectPtr conn, const char *xml, bool
start)
/* Currently support only one dhcp server per network
* with contigious address space from start to end
*/
+ addr = ipdef->ranges[0].addr;
if ((ipdef->nranges >= 1) &&
- VIR_SOCKET_ADDR_VALID(&ipdef->ranges[0].start) &&
- VIR_SOCKET_ADDR_VALID(&ipdef->ranges[0].end)) {
+ VIR_SOCKET_ADDR_VALID(&addr.start) &&
+ VIR_SOCKET_ADDR_VALID(&addr.end)) {
IDHCPServer *dhcpServer = NULL;
gVBoxAPI.UIVirtualBox.FindDHCPServerByNetworkName(data->vboxObj,
@@ -464,8 +466,8 @@ vboxNetworkDefineCreateXML(virConnectPtr conn, const char *xml, bool
start)
ipAddressUtf16 = vboxSocketFormatAddrUtf16(data, &ipdef->address);
networkMaskUtf16 = vboxSocketFormatAddrUtf16(data, &netmask);
- fromIPAddressUtf16 = vboxSocketFormatAddrUtf16(data,
&ipdef->ranges[0].start);
- toIPAddressUtf16 = vboxSocketFormatAddrUtf16(data,
&ipdef->ranges[0].end);
+ fromIPAddressUtf16 = vboxSocketFormatAddrUtf16(data, &addr.start);
+ toIPAddressUtf16 = vboxSocketFormatAddrUtf16(data, &addr.end);
if (ipAddressUtf16 == NULL || networkMaskUtf16 == NULL ||
fromIPAddressUtf16 == NULL || toIPAddressUtf16 == NULL) {
@@ -770,6 +772,7 @@ static char *vboxNetworkGetXMLDesc(virNetworkPtr network, unsigned int
flags)
vboxIID vboxnet0IID;
IHost *host = NULL;
char *ret = NULL;
+ virSocketAddrRange addr;
nsresult rc;
if (!data->vboxObj)
@@ -833,14 +836,15 @@ static char *vboxNetworkGetXMLDesc(virNetworkPtr network, unsigned
int flags)
/* Currently virtualbox supports only one dhcp server per network
* with contigious address space from start to end
*/
+ addr = ipdef->ranges[0].addr;
if (vboxSocketParseAddrUtf16(data, ipAddressUtf16,
&ipdef->address) < 0 ||
vboxSocketParseAddrUtf16(data, networkMaskUtf16,
&ipdef->netmask) < 0 ||
vboxSocketParseAddrUtf16(data, fromIPAddressUtf16,
- &ipdef->ranges[0].start) < 0 ||
+ &addr.start) < 0 ||
vboxSocketParseAddrUtf16(data, toIPAddressUtf16,
- &ipdef->ranges[0].end) < 0) {
+ &addr.end) < 0) {
errorOccurred = true;
}
--
2.24.1