From nobody Mon Feb 9 01:16:35 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) client-ip=205.139.110.120; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1587441905; cv=none; d=zohomail.com; s=zohoarc; b=Rgl4tLdCC9GbXRDMI4Xaj+Lxr8hl5BbLKLu4su1e/6z/hb1q2c4b5Ll6RwOT/1Nc0ERyqVXTgz0QdXLAL4tEVhHH7/CLcQ3+zlfXen53MTvbGYEVM1H362jhGzJnom5xYAGgckCiL9DJa742uB9OjFmmgHULvsowRGuew5QTKTw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1587441905; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=QIemoSv1EepECh4OL21SkJsd8VDvxfKWavAiwxLUdxg=; b=cmdKzQSgyalaBZw7wNd8OY6JmqUZ4QH8X3dzCVG77V36DV1DS0q2rOqxqaGvknf/iO+SCTj1xeTp5eAceuDdEky2nHgAzYURKVhv6c538XgHGyoONkjj4SPkOJAl3oT+fQbEwxcvPGqHIUhMQYx5RQ7PR5vcjouVGxLaUmLOb2s= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by mx.zohomail.com with SMTPS id 1587441905866722.3581370730768; Mon, 20 Apr 2020 21:05:05 -0700 (PDT) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-113-t0RIgDE3Nvm53L2g-V71aw-1; Tue, 21 Apr 2020 00:04:31 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id EE1F48024CE; Tue, 21 Apr 2020 04:04:25 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8FB505C219; Tue, 21 Apr 2020 04:04:25 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 4434918089CE; Tue, 21 Apr 2020 04:04:23 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 03L44LET017878 for ; Tue, 21 Apr 2020 00:04:21 -0400 Received: by smtp.corp.redhat.com (Postfix) id 29C4B10CD617; Tue, 21 Apr 2020 04:04:21 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast02.extmail.prod.ext.rdu2.redhat.com [10.11.55.18]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 24FE710CD616 for ; Tue, 21 Apr 2020 04:04:19 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id DA92B8007D2 for ; Tue, 21 Apr 2020 04:04:18 +0000 (UTC) Received: from mail-qt1-f170.google.com (mail-qt1-f170.google.com [209.85.160.170]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-461-vuwGsIkEO-y49A_qJ4Ed0g-1; Tue, 21 Apr 2020 00:04:15 -0400 Received: by mail-qt1-f170.google.com with SMTP id i68so4871416qtb.5 for ; Mon, 20 Apr 2020 21:04:15 -0700 (PDT) Received: from localhost.localdomain ([179.111.126.123]) by smtp.gmail.com with ESMTPSA id z65sm1105269qka.60.2020.04.20.21.04.12 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 20 Apr 2020 21:04:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1587441904; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=QIemoSv1EepECh4OL21SkJsd8VDvxfKWavAiwxLUdxg=; b=c3/Ie+q74oHP2c5QSF4wWFQMIetxLM/2jKFWJiGfq3Tmz/ojuaQFisoD3gwPmcxUZucBD1 o4pcu2Gp8iI0N7+latjE1N6Catva5Mrg46Op+l1LOgWo9NDnPvxQ0r7fEghrs2d8rRWQYi hGHcFTOICfZTHFgqh6kD0eWg696GVQI= X-MC-Unique: t0RIgDE3Nvm53L2g-V71aw-1 X-MC-Unique: vuwGsIkEO-y49A_qJ4Ed0g-1 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lpJ7YENigigYAx5uGaDskgWqIfdxoaz5cEbUoa9e7dQ=; b=GXTWPXNQO5ZXB3iMfTO4aqIuaRHdhzs8oW91IFWiLNWOK4ICPT1hWROW8R95TbSt2R ObZgJe6CMmwucIXbWzIxnO3zUDMv1LgECKmxnC0xFv5u9mYMNM+YsDl/7M0emDC2QpQ0 iCn9pn5lVIEGQNIUS3VG8SXO0aB4C/8q7/Dy2JjnO0fRiPM1GiFu75E13oIOBlJaSe3W aNtkdrW1lGdsFT/Q7AyX/8iuod96FunsO82YcfU9gMz+6nueGv3ZLTyAM59/Cxv+aRbz 4ttdW879zwHoK9itYfA4c+Z5ivdnmtwPnzbDvNJs0tUitkSariGyvLdhFVUs2Q9F+Hrd ge9g== X-Gm-Message-State: AGi0Pua6rvRDOB9jSy1dWEisIEz84rbl/EBFPTlAVOGKjYu4iM/glxq5 AsCRpucAaOdmgqDdYzwGPbBAvwtUde0= X-Google-Smtp-Source: APiQypKISpGIqge5a+Z5mP+5Alv4uquFMKrpJ5oEqzfmgO/uanrMO+RegdV6gaHRMJbHXRRMgKFBpg== X-Received: by 2002:ac8:776f:: with SMTP id h15mr19668925qtu.36.1587441854129; Mon, 20 Apr 2020 21:04:14 -0700 (PDT) From: Julio Faracco To: libvir-list@redhat.com Subject: [PATCH v2 1/2] conf: Add option for settings Date: Tue, 21 Apr 2020 01:03:54 -0300 Message-Id: <20200421040355.1030902-2-jcfaracco@gmail.com> In-Reply-To: <20200421040355.1030902-1-jcfaracco@gmail.com> References: <20200421040355.1030902-1-jcfaracco@gmail.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-MIME-Autoconverted: from quoted-printable to 8bit by lists01.pubmisc.prod.ext.phx2.redhat.com id 03L44LET017878 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" 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: Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=3D913446 Signed-off-by: Julio Faracco --- 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 @@ =20 + + + seconds + mins + hours + + + 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 @@ + + + + + + + + + + @@ -388,6 +398,16 @@ + + + + + + + + + + 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", ); =20 +VIR_ENUM_IMPL(virNetworkDHCPLeaseTimeUnit, + VIR_NETWORK_DHCP_LEASETIME_UNIT_LAST, + "seconds", + "mins", + "hours", +); + static virClassPtr virNetworkXMLOptionClass; =20 static void @@ -132,12 +139,20 @@ virNetworkForwardPfDefClear(virNetworkForwardPfDefPtr= def) } =20 =20 +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); } =20 =20 @@ -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); =20 while (def->nhosts) @@ -391,11 +409,55 @@ int virNetworkIPDefNetmask(const virNetworkIPDef *def, =20 =20 static int -virSocketAddrRangeParseXML(const char *networkName, - virNetworkIPDefPtr ipdef, - xmlNodePtr node, - virSocketAddrRangePtr range) +virNetworkDHCPLeaseTimeDefParseXML(virNetworkDHCPLeaseTimeDefPtr *lease, + xmlNodePtr node) +{ + virNetworkDHCPLeaseTimeDefPtr new_lease =3D *lease; + g_autofree char *expiry =3D NULL, *unit =3D NULL; + + if (!(expiry =3D 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 =3D virXMLPropString(node, "unit"))) + new_lease->unit =3D VIR_NETWORK_DHCP_LEASETIME_UNIT_MINUTES; + else + new_lease->unit =3D 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 =3D=3D VIR_NETWORK_DHCP_LEASETIME_UNIT_SECOND= S && + new_lease->expiry < 120) || + (new_lease->unit =3D=3D VIR_NETWORK_DHCP_LEASETIME_UNIT_MINUTE= S && + new_lease->expiry < 2)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("The minimum lease time should be greater " + "than 2 minutes")); + return -1; + } + } + + *lease =3D new_lease; + + return 0; +} + + +static int +virNetworkDHCPRangeDefParseXML(const char *networkName, + virNetworkIPDefPtr ipdef, + xmlNodePtr node, + virNetworkDHCPRangeDefPtr range) { + virSocketAddrRangePtr addr =3D &range->addr; + xmlNodePtr cur =3D node->children; char *start =3D NULL, *end =3D NULL; int ret =3D -1; =20 @@ -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; =20 if (!(end =3D 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; =20 /* 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; =20 + while (cur !=3D NULL) { + if (cur->type =3D=3D XML_ELEMENT_NODE && + virXMLNodeNameEqual(cur, "lease")) { + + if (virNetworkDHCPLeaseTimeDefParseXML(&range->lease, cur) < 0) + goto cleanup; + } + cur =3D cur->next; + } + ret =3D 0; =20 cleanup: @@ -441,6 +513,7 @@ virNetworkDHCPHostDefParseXML(const char *networkName, char *mac =3D NULL, *name =3D NULL, *ip =3D NULL, *id =3D NULL; virMacAddr addr; virSocketAddr inaddr; + xmlNodePtr cur =3D node->children; int ret =3D -1; =20 mac =3D virXMLPropString(node, "mac"); @@ -533,6 +606,16 @@ virNetworkDHCPHostDefParseXML(const char *networkName, } } =20 + while (cur !=3D NULL) { + if (cur->type =3D=3D XML_ELEMENT_NODE && + virXMLNodeNameEqual(cur, "lease")) { + + if (virNetworkDHCPLeaseTimeDefParseXML(&host->lease, cur) < 0) + goto cleanup; + } + cur =3D cur->next; + } + host->mac =3D mac; mac =3D NULL; host->id =3D id; @@ -559,7 +642,7 @@ virNetworkDHCPDefParseXML(const char *networkName, { int ret =3D -1; xmlNodePtr cur; - virSocketAddrRange range; + virNetworkDHCPRangeDef range; virNetworkDHCPHostDef host; =20 memset(&range, 0, sizeof(range)); @@ -570,7 +653,7 @@ virNetworkDHCPDefParseXML(const char *networkName, if (cur->type =3D=3D XML_ELEMENT_NODE && virXMLNodeNameEqual(cur, "range")) { =20 - if (virSocketAddrRangeParseXML(networkName, def, cur, &range) = < 0) + if (virNetworkDHCPRangeDefParseXML(networkName, def, cur, &ran= ge) < 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 =3D=3D XML_ELEMENT_NODE && virXMLNodeNameEqual(cur, "bootp")) { @@ -2300,20 +2382,39 @@ virNetworkIPDefFormat(virBufferPtr buf, virBufferAdjustIndent(buf, 2); =20 for (i =3D 0; i < def->nranges; i++) { - char *saddr =3D virSocketAddrFormat(&def->ranges[i].start); + virSocketAddrRange addr =3D def->ranges[i].addr; + virNetworkDHCPLeaseTimeDefPtr lease =3D def->ranges[i].lease; + + char *saddr =3D virSocketAddrFormat(&addr.start); if (!saddr) return -1; - char *eaddr =3D virSocketAddrFormat(&def->ranges[i].end); + char *eaddr =3D virSocketAddrFormat(&addr.end); if (!eaddr) { VIR_FREE(saddr); return -1; } - virBufferAsprintf(buf, "\n", + virBufferAsprintf(buf, "\n"); + virBufferAdjustIndent(buf, 2); + if (!lease->expiry) { + virBufferAddLit(buf, "\n"); + } else { + virBufferAsprintf(buf, "\n", + lease->expiry, + virNetworkDHCPLeaseTimeUnitTypeToStr= ing(lease->unit)); + } + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + } else { + virBufferAddLit(buf, "/>\n"); + } VIR_FREE(saddr); VIR_FREE(eaddr); } for (i =3D 0; i < def->nhosts; i++) { + virNetworkDHCPLeaseTimeDefPtr lease =3D def->hosts[i].lease; virBufferAddLit(buf, "hosts[i].mac) virBufferAsprintf(buf, " mac=3D'%s'", def->hosts[i].mac); @@ -2328,7 +2429,21 @@ virNetworkIPDefFormat(virBufferPtr buf, virBufferAsprintf(buf, " ip=3D'%s'", ipaddr); VIR_FREE(ipaddr); } - virBufferAddLit(buf, "/>\n"); + if (lease) { + virBufferAddLit(buf, ">\n"); + virBufferAdjustIndent(buf, 2); + if (!lease->expiry) { + virBufferAddLit(buf, "\n"); + } else { + virBufferAsprintf(buf, "\n", + lease->expiry, + virNetworkDHCPLeaseTimeUnitTypeToStr= ing(lease->unit)); + } + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + } else { + virBufferAddLit(buf, "/>\n"); + } } if (def->bootfile) { virBufferEscapeString(buf, "\n"); =20 } - virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "\n"); } @@ -3080,7 +3194,7 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def, { size_t i; virNetworkIPDefPtr ipdef =3D virNetworkIPDefByIndex(def, parentIndex); - virSocketAddrRange range; + virNetworkDHCPRangeDef range; =20 memset(&range, 0, sizeof(range)); =20 @@ -3100,11 +3214,11 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def, return -1; } =20 - if (virSocketAddrRangeParseXML(def->name, ipdef, ctxt->node, &range) <= 0) + if (virNetworkDHCPRangeDefParseXML(def->name, ipdef, ctxt->node, &rang= e) < 0) return -1; =20 if (VIR_SOCKET_ADDR_FAMILY(&ipdef->address) - !=3D VIR_SOCKET_ADDR_FAMILY(&range.start)) { + !=3D 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, =20 /* check if an entry with same name/address/ip already exists */ for (i =3D 0; i < ipdef->nranges; i++) { - if (virSocketAddrEqual(&range.start, &ipdef->ranges[i].start) && - virSocketAddrEqual(&range.end, &ipdef->ranges[i].end)) { + virSocketAddrRange addr =3D 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; =20 if (i < ipdef->nranges) { - char *startip =3D virSocketAddrFormat(&range.start); - char *endip =3D virSocketAddrFormat(&range.end); + char *startip =3D virSocketAddrFormat(&range.addr.start); + char *endip =3D virSocketAddrFormat(&range.addr.end); =20 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; =20 +typedef enum { + VIR_NETWORK_DHCP_LEASETIME_UNIT_SECONDS =3D 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 { =20 VIR_ENUM_DECL(virNetworkForwardDriverName); =20 +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; }; =20 typedef struct _virNetworkDNSTxtDef virNetworkDNSTxtDef; @@ -171,7 +196,7 @@ struct _virNetworkIPDef { int localPTR; /* virTristateBool */ =20 size_t nranges; /* Zero or more dhcp ranges */ - virSocketAddrRangePtr ranges; + virNetworkDHCPRangeDefPtr ranges; =20 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; =20 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) } =20 =20 +static char * +networkBuildDnsmasqLeaseTime(virNetworkDHCPLeaseTimeDefPtr lease) +{ + char *leasetime =3D NULL; + const char *unit; + g_auto(virBuffer) buf =3D VIR_BUFFER_INITIALIZER; + + if (!lease) + return NULL; + + if (lease->expiry =3D=3D 0) { + virBufferAddLit(&buf, "infinite"); + } else { + unit =3D virNetworkDHCPLeaseTimeUnitTypeToString(lease->unit); + /* We get only first compatible char from string: 's', 'm' or 'h' = */ + virBufferAsprintf(&buf, "%lu%c", lease->expiry, unit[0]); + } + + leasetime =3D 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 =3D false; + g_autofree char *leasetime =3D NULL; =20 if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) ipv6 =3D true; for (i =3D 0; i < ipdef->nhosts; i++) { virNetworkDHCPHostDefPtr host =3D &(ipdef->hosts[i]); + + leasetime =3D 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; } =20 @@ -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 =3D 0; r < ipdef->nranges; r++) { int thisRange; + virNetworkDHCPRangeDef range =3D ipdef->ranges[r]; + g_autofree char *leasetime =3D NULL; =20 - if (!(saddr =3D virSocketAddrFormat(&ipdef->ranges[r].start)) = || - !(eaddr =3D virSocketAddrFormat(&ipdef->ranges[r].end))) + if (!(saddr =3D virSocketAddrFormat(&range.addr.start)) || + !(eaddr =3D virSocketAddrFormat(&range.addr.end))) goto cleanup; =20 if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) { - virBufferAsprintf(&configbuf, "dhcp-range=3D%s,%s,%d\n", + virBufferAsprintf(&configbuf, "dhcp-range=3D%s,%s,%d", saddr, eaddr, prefix); } else { /* IPv4 - dnsmasq requires a netmask rather than prefix */ @@ -1404,14 +1435,19 @@ networkDnsmasqConfContents(virNetworkObjPtr obj, =20 if (!(netmaskStr =3D virSocketAddrFormat(&netmask))) goto cleanup; - virBufferAsprintf(&configbuf, "dhcp-range=3D%s,%s,%s\n", + virBufferAsprintf(&configbuf, "dhcp-range=3D%s,%s,%s", saddr, eaddr, netmaskStr); } =20 + if ((leasetime =3D networkBuildDnsmasqLeaseTime(range.lease))) + virBufferAsprintf(&configbuf, ",%s", leasetime); + + virBufferAddLit(&configbuf, "\n"); + VIR_FREE(saddr); VIR_FREE(eaddr); - thisRange =3D virSocketAddrGetRange(&ipdef->ranges[r].start, - &ipdef->ranges[r].end, + thisRange =3D 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; =20 + *hostsfilestr =3D 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(virNetworkDriverS= tatePtr driver, int ret =3D -1; char *configfile =3D NULL; char *configstr =3D NULL; + char *hostsfilestr =3D NULL; char *leaseshelper_path =3D NULL; =20 virNetworkObjSetDnsmasqPid(obj, -1); =20 - 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 drive= r, net_def->ips->prefix= ); =20 if (net_def->ips->nranges > 0) - addr =3D net_def->ips->ranges[0].start; + addr =3D net_def->ips->ranges[0].addr.start; else addr =3D net_def->ips->address; =20 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 =3D NULL; + g_autofree char *ipstr =3D NULL; + g_auto(virBuffer) buf =3D VIR_BUFFER_INITIALIZER; + if (VIR_REALLOC_N(hostsfile->hosts, hostsfile->nhosts + 1) < 0) - goto error; + return -1; =20 if (!(ipstr =3D 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 =3D 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 =3D g_strdup_printf("= %s,[%s]", - nam= e, ipstr); + virBufferAsprintf(&buf, "%s", name); } else if (!name && id) { - hostsfile->hosts[hostsfile->nhosts].host =3D 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 =3D g_strdup_printf("%s,%= s,%s", - mac, ip= str, name); + virBufferAsprintf(&buf, "%s,%s,%s", mac, ipstr, name); } else if (name && !mac) { - hostsfile->hosts[hostsfile->nhosts].host =3D g_strdup_printf("%s,%= s", name, - ipstr); + virBufferAsprintf(&buf, "%s,%s", name, ipstr); } else { - hostsfile->hosts[hostsfile->nhosts].host =3D 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 =3D virBufferContentAnd= Reset(&buf))) + return -1; =20 hostsfile->nhosts++; =20 return 0; - - error: - VIR_FREE(ipstr); - return -1; } =20 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= ); } =20 /* @@ -862,3 +862,31 @@ dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags f= lag) { 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 hostsfil= es + * testable. Returs NULL if nhosts is 0. + */ +char * +dnsmasqDhcpHostsToString(dnsmasqDhcpHost *hosts, + unsigned int nhosts) +{ + size_t i; + char *result =3D NULL; + virBuffer hostsfilebuf =3D VIR_BUFFER_INITIALIZER; + + if (nhosts =3D=3D 0) + goto cleanup; + + for (i =3D 0; i < nhosts; i++) + virBufferAsprintf(&hostsfilebuf, "%s\n", hosts[i].host); + + result =3D 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); =20 #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 ch= ar *xml, bool start) virNetworkIPDefPtr ipdef =3D NULL; unsigned char uuid[VIR_UUID_BUFLEN]; vboxIID vboxnetiid; + virSocketAddrRange addr; virSocketAddr netmask; IHost *host =3D NULL; virNetworkPtr ret =3D NULL; @@ -440,9 +441,10 @@ vboxNetworkDefineCreateXML(virConnectPtr conn, const c= har *xml, bool start) /* Currently support only one dhcp server per network * with contigious address space from start to end */ + addr =3D ipdef->ranges[0].addr; if ((ipdef->nranges >=3D 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 =3D NULL; =20 gVBoxAPI.UIVirtualBox.FindDHCPServerByNetworkName(data->vboxObj, @@ -464,8 +466,8 @@ vboxNetworkDefineCreateXML(virConnectPtr conn, const ch= ar *xml, bool start) =20 ipAddressUtf16 =3D vboxSocketFormatAddrUtf16(data, &ipdef->add= ress); networkMaskUtf16 =3D vboxSocketFormatAddrUtf16(data, &netmask); - fromIPAddressUtf16 =3D vboxSocketFormatAddrUtf16(data, &ipdef-= >ranges[0].start); - toIPAddressUtf16 =3D vboxSocketFormatAddrUtf16(data, &ipdef->r= anges[0].end); + fromIPAddressUtf16 =3D vboxSocketFormatAddrUtf16(data, &addr.s= tart); + toIPAddressUtf16 =3D vboxSocketFormatAddrUtf16(data, &addr.end= ); =20 if (ipAddressUtf16 =3D=3D NULL || networkMaskUtf16 =3D=3D NULL= || fromIPAddressUtf16 =3D=3D NULL || toIPAddressUtf16 =3D=3D = NULL) { @@ -770,6 +772,7 @@ static char *vboxNetworkGetXMLDesc(virNetworkPtr networ= k, unsigned int flags) vboxIID vboxnet0IID; IHost *host =3D NULL; char *ret =3D NULL; + virSocketAddrRange addr; nsresult rc; =20 if (!data->vboxObj) @@ -833,14 +836,15 @@ static char *vboxNetworkGetXMLDesc(virNetworkPtr netw= ork, unsigned int flags) /* Currently virtualbox supports only one dhcp server per netw= ork * with contigious address space from start to end */ + addr =3D 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 =3D true; } =20 --=20 2.24.1