On 05/26/2015 03:48 PM, Laine Stump wrote:
> virSocketAddrGetRange() has been updated to take the network address
> and prefix, and now checks that both the start and end of the range
> are within that network, thus validating that the entire range of
> addresses is in the network. For IPv4, it also checks that ranges to
> not start with the "network address" of the subnet, nor end with the
> broadcast address of the subnet (this check doesn't apply to IPv6,
> since IPv6 doesn't have a broadcast or network address)
>
> Negative tests have been added to the network update and socket tests
> to verify that bad ranges properly generate an error.
>
> This resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=985653
> ---
> src/conf/network_conf.c | 14 ++---
> src/network/bridge_driver.c | 4 +-
> src/util/virsocketaddr.c | 61 ++++++++++++++++++----
> src/util/virsocketaddr.h | 6 ++-
> tests/networkxml2xmlupdatein/dhcp-range-10.xml | 1 +
> tests/networkxml2xmlupdatein/dhcp-range.xml | 2 +-
> .../dhcp6host-routed-network-another-range.xml | 2 +-
> .../dhcp6host-routed-network-range.xml | 2 +-
> tests/networkxml2xmlupdatetest.c | 5 ++
> tests/sockettest.c | 55 ++++++++++++-------
> 10 files changed, 112 insertions(+), 40 deletions(-)
> create mode 100644 tests/networkxml2xmlupdatein/dhcp-range-10.xml
>
> diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
> index bc63a3d..f9f3d3d 100644
> --- a/src/conf/network_conf.c
> +++ b/src/conf/network_conf.c
> @@ -832,8 +832,9 @@ int virNetworkIpDefNetmask(const virNetworkIpDef *def,
>
> static int
> virSocketAddrRangeParseXML(const char *networkName,
> - xmlNodePtr node,
> - virSocketAddrRangePtr range)
> + virNetworkIpDefPtr ipdef,
> + xmlNodePtr node,
> + virSocketAddrRangePtr range)
> {
>
>
> @@ -859,7 +860,8 @@ virSocketAddrRangeParseXML(const char *networkName,
> goto cleanup;
>
> /* do a sanity check of the range */
> - if (virSocketAddrGetRange(&range->start, &range->end) < 0) {
> + if (virSocketAddrGetRange(&range->start, &range->end,
&ipdef->address,
> + virNetworkIpDefPrefix(ipdef)) < 0) {
> virReportError(VIR_ERR_XML_ERROR,
> _("Invalid dhcp range '%s' to '%s' in
network '%s'"),
> start, end, networkName);
> @@ -1009,8 +1011,8 @@ virNetworkDHCPDefParseXML(const char *networkName,
>
> if (VIR_REALLOC_N(def->ranges, def->nranges + 1) < 0)
> return -1;
> - if (virSocketAddrRangeParseXML(networkName, cur,
> - &def->ranges[def->nranges])
< 0) {
> + if (virSocketAddrRangeParseXML(networkName, def, cur,
> + &def->ranges[def->nranges])
< 0) {
> return -1;
> }
> def->nranges++;
> @@ -3608,7 +3610,7 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def,
> goto cleanup;
> }
>
> - if (virSocketAddrRangeParseXML(def->name, ctxt->node, &range) < 0)
> + if (virSocketAddrRangeParseXML(def->name, ipdef, ctxt->node, &range)
< 0)
> goto cleanup;
>
> /* check if an entry with same name/address/ip already exists */
> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
> index 4b53475..e08a316 100644
> --- a/src/network/bridge_driver.c
> +++ b/src/network/bridge_driver.c
> @@ -1193,7 +1193,9 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
> VIR_FREE(saddr);
> VIR_FREE(eaddr);
> nbleases += virSocketAddrGetRange(&ipdef->ranges[r].start,
> - &ipdef->ranges[r].end);
> + &ipdef->ranges[r].end,
> + &ipdef->address,
> + virNetworkIpDefPrefix(ipdef));
> }
>
> /*
> diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c
> index 67ed330..0edf345 100644
> --- a/src/util/virsocketaddr.c
> +++ b/src/util/virsocketaddr.c
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (C) 2009-2014 Red Hat, Inc.
> + * Copyright (C) 2009-2015 Red Hat, Inc.
> *
> * This library is free software; you can redistribute it and/or
> * modify it under the terms of the GNU Lesser General Public
> @@ -605,31 +605,69 @@ int virSocketAddrCheckNetmask(virSocketAddrPtr addr1,
virSocketAddrPtr addr2,
> * virSocketGetRange:
> * @start: start of an IP range
> * @end: end of an IP range
> + * @network: IP address of network that should completely contain this range
> + * @prefix: prefix of the network
> *
> - * Check the order of the 2 addresses and compute the range, this
> - * will return 1 for identical addresses. Errors can come from incompatible
> - * addresses type, excessive range (>= 2^^16) where the two addresses are
> - * unrelated or inverted start and end.
> + * Check the order of the 2 addresses and compute the range, this will
> + * return 1 for identical addresses. Errors can come from incompatible
> + * addresses type, excessive range (>= 2^^16) where the two addresses
> + * are unrelated, inverted start and end, or a range that is not
> + * within network/prefix.
> *
> * Returns the size of the range or -1 in case of failure
> */
> -int virSocketAddrGetRange(virSocketAddrPtr start, virSocketAddrPtr end)
> +int
> +virSocketAddrGetRange(virSocketAddrPtr start, virSocketAddrPtr end,
> + virSocketAddrPtr network, int prefix)
> {
> int ret = 0;
> size_t i;
> + virSocketAddr netmask;
> +
> + if (start == NULL || end == NULL || network == NULL)
> + return -1;
> +
> + if (VIR_SOCKET_ADDR_FAMILY(start) != VIR_SOCKET_ADDR_FAMILY(end) ||
> + VIR_SOCKET_ADDR_FAMILY(start) != VIR_SOCKET_ADDR_FAMILY(network))
> + return -1;
>
> - if ((start == NULL) || (end == NULL))
> + if (prefix < 0 ||
> + virSocketAddrPrefixToNetmask(prefix, &netmask,
VIR_SOCKET_ADDR_FAMILY(network)) < 0)
> return -1;
> - if (start->data.stor.ss_family != end->data.stor.ss_family)
> +
> + /* both start and end of range need to be in the same network as
> + * "network"
> + */
> + if (virSocketAddrCheckNetmask(start, network, &netmask) <= 0 ||
> + virSocketAddrCheckNetmask(start, network, &netmask) <= 0)
Should I assume this is a cut-n-paste (eg, the second call should use
end not start)...
Side note - seems there's no "FAIL" test for this condition -
considering we passed the tests with the check this way...
+ DO_TEST_RANGE("192.168.122.20", "10.0.0.1",
"192.168.122.1", 24, -1, false);
But that one fails anyway, because the end address is lower than the
start address.
Thankfully I was waiting until after release to push . I'll change the
offending "start" to "end", and add this test:
DO_TEST_RANGE("192.168.122.20", "192.168.123.1",
"192.168.122.1", 24,
-1, false);
Thanks for your eagle eye!