From: Laine Stump <laine@redhat.com>
The Linux/libnl version of virNetDevIPRouteAdd() has always had code
that would use "0.0.0.0" (or "::" for IPv6) for the route's
destination address if none was specified, but 1) our validation code
has always required it to be specified anyway, 2) the FreeBSD version
of virnertDevIPRouteAdd() expected that it would be specified, and 3)
virNetDevIPRouteFormat() also expected route->address to be
valid. This patch fixes those 3 deficiencies, so that this XML now
works:
<route gateway='1.2.3.4'/>
i.e. it is the same as:
<route address='0.0.0.0' prefix='0' gateway='1.2.3.4'/>
Signed-off-by: Laine Stump <laine@redhat.com>
---
src/conf/networkcommon_conf.c | 74 ++++++++++++++----------------
src/conf/schemas/networkcommon.rng | 4 +-
src/util/virnetdevip.c | 12 ++++-
3 files changed, 48 insertions(+), 42 deletions(-)
diff --git a/src/conf/networkcommon_conf.c b/src/conf/networkcommon_conf.c
index 6f88d173c6..bfa58a26a8 100644
--- a/src/conf/networkcommon_conf.c
+++ b/src/conf/networkcommon_conf.c
@@ -50,15 +50,6 @@ virNetDevIPRouteCreate(const char *errorDetail,
def->metric = metric;
def->has_metric = hasMetric;
- /* Note: both network and gateway addresses must be specified */
-
- if (!address) {
- virReportError(VIR_ERR_XML_ERROR,
- _("%1$s: Missing required address attribute in route definition"),
- errorDetail);
- return NULL;
- }
-
if (!gateway) {
virReportError(VIR_ERR_XML_ERROR,
_("%1$s: Missing required gateway attribute in route definition"),
@@ -66,17 +57,17 @@ virNetDevIPRouteCreate(const char *errorDetail,
return NULL;
}
- if (virSocketAddrParse(&def->address, address, AF_UNSPEC) < 0) {
+ if (virSocketAddrParse(&def->gateway, gateway, AF_UNSPEC) < 0) {
virReportError(VIR_ERR_XML_ERROR,
- _("%1$s: Bad network address '%2$s' in route definition"),
- errorDetail, address);
+ _("%1$s: Bad gateway address '%2$s' in route definition"),
+ errorDetail, gateway);
return NULL;
}
- if (virSocketAddrParse(&def->gateway, gateway, AF_UNSPEC) < 0) {
+ if (address && virSocketAddrParse(&def->address, address, AF_UNSPEC) < 0) {
virReportError(VIR_ERR_XML_ERROR,
- _("%1$s: Bad gateway address '%2$s' in route definition"),
- errorDetail, gateway);
+ _("%1$s: Bad network address '%2$s' in route definition"),
+ errorDetail, address);
return NULL;
}
@@ -127,7 +118,8 @@ virNetDevIPRouteCreate(const char *errorDetail,
return NULL;
}
} else if (STREQ(def->family, "ipv6")) {
- if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET6)) {
+ if (!(VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET6) ||
+ VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_UNSPEC))) {
virReportError(VIR_ERR_XML_ERROR,
_("%1$s: ipv6 family specified for non-IPv6 address '%2$s' in route definition"),
errorDetail, address);
@@ -158,29 +150,32 @@ virNetDevIPRouteCreate(const char *errorDetail,
return NULL;
}
- /* make sure the address is a network address */
- if (netmask) {
- if (virSocketAddrMask(&def->address, &def->netmask, &testAddr) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("%1$s: Error converting address '%2$s' with netmask '%3$s' to network-address in route definition"),
- errorDetail, address, netmask);
- return NULL;
+ if (address) {
+ /* make sure the address is a network address */
+
+ if (netmask) {
+ if (virSocketAddrMask(&def->address, &def->netmask, &testAddr) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("%1$s: Error converting address '%2$s' with netmask '%3$s' to network-address in route definition"),
+ errorDetail, address, netmask);
+ return NULL;
+ }
+ } else {
+ if (virSocketAddrMaskByPrefix(&def->address,
+ def->prefix, &testAddr) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("%1$s: Error converting address '%2$s' with prefix %3$u to network-address in route definition"),
+ errorDetail, address, def->prefix);
+ return NULL;
+ }
}
- } else {
- if (virSocketAddrMaskByPrefix(&def->address,
- def->prefix, &testAddr) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("%1$s: Error converting address '%2$s' with prefix %3$u to network-address in route definition"),
- errorDetail, address, def->prefix);
+ if (!virSocketAddrEqual(&def->address, &testAddr)) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("%1$s: Address '%2$s' in route definition is not a network address"),
+ errorDetail, address);
return NULL;
}
}
- if (!virSocketAddrEqual(&def->address, &testAddr)) {
- virReportError(VIR_ERR_XML_ERROR,
- _("%1$s: Address '%2$s' in route definition is not a network address"),
- errorDetail, address);
- return NULL;
- }
return g_steal_pointer(&def);
}
@@ -229,10 +224,11 @@ virNetDevIPRouteFormat(virBuffer *buf,
if (def->family)
virBufferAsprintf(buf, " family='%s'", def->family);
- if (!(address = virSocketAddrFormat(&def->address)))
- return -1;
- virBufferAsprintf(buf, " address='%s'", address);
-
+ if (VIR_SOCKET_ADDR_VALID(&def->address)) {
+ if (!(address = virSocketAddrFormat(&def->address)))
+ return -1;
+ virBufferAsprintf(buf, " address='%s'", address);
+ }
if (VIR_SOCKET_ADDR_VALID(&def->netmask)) {
if (!(netmask = virSocketAddrFormat(&def->netmask)))
return -1;
diff --git a/src/conf/schemas/networkcommon.rng b/src/conf/schemas/networkcommon.rng
index 28424f9abd..49149a3d4b 100644
--- a/src/conf/schemas/networkcommon.rng
+++ b/src/conf/schemas/networkcommon.rng
@@ -253,7 +253,9 @@
<optional>
<attribute name="family"><ref name="addr-family"/></attribute>
</optional>
- <attribute name="address"><ref name="ipAddr"/></attribute>
+ <optional>
+ <attribute name="address"><ref name="ipAddr"/></attribute>
+ </optional>
<optional>
<choice>
<attribute name="netmask"><ref name="ipv4Addr"/></attribute>
diff --git a/src/util/virnetdevip.c b/src/util/virnetdevip.c
index 5ffd2bf398..8786bb236e 100644
--- a/src/util/virnetdevip.c
+++ b/src/util/virnetdevip.c
@@ -465,8 +465,16 @@ virNetDevIPRouteAdd(const char *ifname,
g_autofree char *addrstr = NULL;
g_autofree char *gatewaystr = NULL;
- if (!(addrstr = virSocketAddrFormat(addr)))
- return -1;
+ if (VIR_SOCKET_ADDR_VALID(addr)) {
+ if (!(addrstr = virSocketAddrFormat(addr)))
+ return -1;
+ } else {
+ if (VIR_SOCKET_ADDR_IS_FAMILY(gateway, AF_INET6))
+ addrstr = g_strdup(VIR_SOCKET_ADDR_IPV6_ALL);
+ else
+ addrstr = g_strdup(VIR_SOCKET_ADDR_IPV4_ALL);
+ }
+
if (!(gatewaystr = virSocketAddrFormat(gateway)))
return -1;
cmd = virCommandNew("ip");
--
2.52.0
On 2/24/26 08:52, Laine Stump via Devel wrote: > From: Laine Stump <laine@redhat.com> > > The Linux/libnl version of virNetDevIPRouteAdd() has always had code > that would use "0.0.0.0" (or "::" for IPv6) for the route's > destination address if none was specified, but 1) our validation code > has always required it to be specified anyway, 2) the FreeBSD version > of virnertDevIPRouteAdd() expected that it would be specified, and 3) > virNetDevIPRouteFormat() also expected route->address to be > valid. This patch fixes those 3 deficiencies, so that this XML now > works: > > <route gateway='1.2.3.4'/> > > i.e. it is the same as: > > <route address='0.0.0.0' prefix='0' gateway='1.2.3.4'/> > > Signed-off-by: Laine Stump <laine@redhat.com> > --- > src/conf/networkcommon_conf.c | 74 ++++++++++++++---------------- > src/conf/schemas/networkcommon.rng | 4 +- > src/util/virnetdevip.c | 12 ++++- > 3 files changed, 48 insertions(+), 42 deletions(-) Either this patch or the next one should mention this in the docs: https://libvirt.org/formatdomain.html#ip-configuration Esp. the part about "This is used by the LXC driver." Michal
On 2/24/26 8:13 AM, Michal Prívozník via Devel wrote: > On 2/24/26 08:52, Laine Stump via Devel wrote: >> From: Laine Stump <laine@redhat.com> >> >> The Linux/libnl version of virNetDevIPRouteAdd() has always had code >> that would use "0.0.0.0" (or "::" for IPv6) for the route's >> destination address if none was specified, but 1) our validation code >> has always required it to be specified anyway, 2) the FreeBSD version >> of virnertDevIPRouteAdd() expected that it would be specified, and 3) >> virNetDevIPRouteFormat() also expected route->address to be >> valid. This patch fixes those 3 deficiencies, so that this XML now >> works: >> >> <route gateway='1.2.3.4'/> >> >> i.e. it is the same as: >> >> <route address='0.0.0.0' prefix='0' gateway='1.2.3.4'/> >> >> Signed-off-by: Laine Stump <laine@redhat.com> >> --- >> src/conf/networkcommon_conf.c | 74 ++++++++++++++---------------- >> src/conf/schemas/networkcommon.rng | 4 +- >> src/util/virnetdevip.c | 12 ++++- >> 3 files changed, 48 insertions(+), 42 deletions(-) > > Either this patch or the next one should mention this in the docs: > > https://libvirt.org/formatdomain.html#ip-configuration > > Esp. the part about "This is used by the LXC driver." Good point! Actually each of them needs a tweak to the docs - this one should point out that address is optional (and defaults to the "all" address for the given family if not specified), and the next should say that it's used for the QEMU driver with a passt-backed interface. > > Michal >
© 2016 - 2026 Red Hat, Inc.