conf/util: fix non-specification of IP route destination address

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>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Laine Stump
2026-03-09 01:14:55 -04:00
parent 21c8588683
commit acd8e9595f
4 changed files with 56 additions and 44 deletions
+6
View File
@@ -664,6 +664,12 @@ network is running, the configuration for the system-defined route should be
modified to have a higher metric, and the route on the virtual network given a
lower metric (for example, the default metric of "1").
Only the ``gateway`` attribute is mandatory for a ``route``
element. If ``address`` is unspecified, it is assumed to be "0.0.0.0"
(or "::" for IPv6), and if neither prefix nor netmask is specified, a
prefix of "0" is assumed (thus, a ``route`` with only gateway is
essentially specifying the "default route").
::
...
+37 -41
View File
@@ -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,13 +57,6 @@ virNetDevIPRouteCreate(const char *errorDetail,
return NULL;
}
if (virSocketAddrParse(&def->address, address, AF_UNSPEC) < 0) {
virReportError(VIR_ERR_XML_ERROR,
_("%1$s: Bad network address '%2$s' in route definition"),
errorDetail, address);
return NULL;
}
if (virSocketAddrParse(&def->gateway, gateway, AF_UNSPEC) < 0) {
virReportError(VIR_ERR_XML_ERROR,
_("%1$s: Bad gateway address '%2$s' in route definition"),
@@ -80,6 +64,13 @@ virNetDevIPRouteCreate(const char *errorDetail,
return NULL;
}
if (address && virSocketAddrParse(&def->address, address, AF_UNSPEC) < 0) {
virReportError(VIR_ERR_XML_ERROR,
_("%1$s: Bad network address '%2$s' in route definition"),
errorDetail, address);
return NULL;
}
/* validate network address, etc. for each family */
if ((def->family == NULL) || (STREQ(def->family, "ipv4"))) {
if (!(VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET) ||
@@ -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,28 +150,31 @@ 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);
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;
}
}
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;
}
} 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;
}
}
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;
+3 -1
View File
@@ -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>
+10 -2
View File
@@ -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");