Example #1
0
/**
 * virSocketAddrMaskByPrefix:
 * @addr: address that needs to be masked
 * @prefix: prefix (# of 1 bits) of netmask to apply
 * @network: where to store the result, can be same as @addr
 *
 * Mask off the host bits of @addr according to @prefix, turning it
 * into a network address.
 *
 * Returns 0 in case of success, or -1 on error.
 */
int
virSocketAddrMaskByPrefix(const virSocketAddrPtr addr,
                          unsigned int           prefix,
                          virSocketAddrPtr       network)
{
    virSocketAddr netmask;

    if (virSocketAddrPrefixToNetmask(prefix, &netmask,
                                     addr->data.stor.ss_family) < 0) {
        network->data.stor.ss_family = AF_UNSPEC;
        return -1;
    }

    return virSocketAddrMask(addr, &netmask, network);
}
Example #2
0
virNetDevIPRoutePtr
virNetDevIPRouteCreate(const char *errorDetail,
                       const char *family,
                       const char *address,
                       const char *netmask,
                       const char *gateway,
                       unsigned int prefix,
                       bool hasPrefix,
                       unsigned int metric,
                       bool hasMetric)
{
    virNetDevIPRoutePtr def = NULL;
    virSocketAddr testAddr;

    if (VIR_ALLOC(def) < 0)
        return NULL;

    if (VIR_STRDUP(def->family, family) < 0)
        goto error;

    def->prefix = prefix;
    def->has_prefix = hasPrefix;
    def->metric = metric;
    def->has_metric = hasMetric;

    /* Note: both network and gateway addresses must be specified */

    if (!address) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("%s: Missing required address attribute "
                         "in route definition"),
                       errorDetail);
        goto error;
    }

    if (!gateway) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("%s: Missing required gateway attribute "
                         "in route definition"),
                       errorDetail);
        goto error;
    }

    if (virSocketAddrParse(&def->address, address, AF_UNSPEC) < 0) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("%s: Bad network address '%s' "
                         "in route definition"),
                       errorDetail, address);
        goto error;
    }

    if (virSocketAddrParse(&def->gateway, gateway, AF_UNSPEC) < 0) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("%s: Bad gateway address '%s' "
                         "in route definition"),
                       errorDetail, gateway);
        goto error;
    }

    /* 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) ||
              VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_UNSPEC))) {
            virReportError(VIR_ERR_XML_ERROR,
                           def->family == NULL ?
                           _("%s: No family specified for non-IPv4 address '%s' "
                             "in route definition") :
                           _("%s: IPv4 family specified for non-IPv4 address '%s' "
                             "in route definition"),
                           errorDetail, address);
            goto error;
        }
        if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->gateway, AF_INET)) {
            virReportError(VIR_ERR_XML_ERROR,
                           def->family == NULL ?
                           _("%s: No family specified for non-IPv4 gateway '%s' "
                             "in route definition") :
                           _("%s: IPv4 family specified for non-IPv4 gateway '%s' "
                             "in route definition"),
                           errorDetail, address);
            goto error;
        }
        if (netmask) {
            if (virSocketAddrParse(&def->netmask, netmask, AF_UNSPEC) < 0) {
                virReportError(VIR_ERR_XML_ERROR,
                               _("%s: Bad netmask address '%s' "
                                 "in route definition"),
                               errorDetail, netmask);
                goto error;
            }
            if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->netmask, AF_INET)) {
                virReportError(VIR_ERR_XML_ERROR,
                               _("%s: Invalid netmask '%s' "
                                 "for address '%s' (both must be IPv4)"),
                               errorDetail, netmask, address);
                goto error;
            }
            if (def->has_prefix) {
                /* can't have both netmask and prefix at the same time */
                virReportError(VIR_ERR_XML_ERROR,
                               _("%s: Route definition cannot have both "
                                 "a prefix and a netmask"),
                               errorDetail);
                goto error;
            }
        }
        if (def->prefix > 32) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("%s: Invalid prefix %u specified "
                             "in route definition, "
                             "must be 0 - 32"),
                           errorDetail, def->prefix);
            goto error;
        }
    } else if (STREQ(def->family, "ipv6")) {
        if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET6)) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("%s: ipv6 family specified for non-IPv6 address '%s' "
                             "in route definition"),
                           errorDetail, address);
            goto error;
        }
        if (netmask) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("%s: Specifying netmask invalid for IPv6 address '%s' "
                             "in route definition"),
                           errorDetail, address);
            goto error;
        }
        if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->gateway, AF_INET6)) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("%s: ipv6 specified for non-IPv6 gateway address '%s' "
                             "in route definition"),
                           errorDetail, gateway);
            goto error;
        }
        if (def->prefix > 128) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("%s: Invalid prefix %u specified "
                             "in route definition, "
                             "must be 0 - 128"),
                           errorDetail, def->prefix);
            goto error;
        }
    } else {
        virReportError(VIR_ERR_XML_ERROR,
                       _("%s: Unrecognized family '%s' "
                         "in route definition"),
                       errorDetail, def->family);
        goto error;
    }

    /* make sure the address is a network address */
    if (netmask) {
        if (virSocketAddrMask(&def->address, &def->netmask, &testAddr) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("%s: Error converting address '%s' with netmask '%s' "
                             "to network-address "
                             "in route definition"),
                           errorDetail, address, netmask);
            goto error;
        }
    } else {
        if (virSocketAddrMaskByPrefix(&def->address,
                                      def->prefix, &testAddr) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("%s: Error converting address '%s' with prefix %u "
                             "to network-address "
                             "in route definition"),
                           errorDetail, address, def->prefix);
            goto error;
        }
    }
    if (!virSocketAddrEqual(&def->address, &testAddr)) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("%s: Address '%s' in route definition "
                         "is not a network address"),
                       errorDetail, address);
        goto error;
    }

    return def;

 error:
    virNetDevIPRouteFree(def);
    return NULL;
}
Example #3
0
/**
 * 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, 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,
                      virSocketAddrPtr network, int prefix)
{
    int ret = 0;
    size_t i;
    virSocketAddr netmask;
    char *startStr = NULL, *endStr = NULL, *netStr = NULL;

    if (start == NULL || end == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("NULL argument - %p %p"), start, end);
        goto error;
    }

    startStr = virSocketAddrFormat(start);
    endStr = virSocketAddrFormat(end);
    if (!startStr || !endStr)
        goto error; /*error already reported */

    if (VIR_SOCKET_ADDR_FAMILY(start) != VIR_SOCKET_ADDR_FAMILY(end)) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("mismatch of address family in range %s - %s"),
                       startStr, endStr);
        goto error;
    }

    if (network) {
        /* some checks can only be done if we have details of the
         * network the range should be within
         */
        if (!(netStr = virSocketAddrFormat(network)))
            goto error;

        if (VIR_SOCKET_ADDR_FAMILY(start) != VIR_SOCKET_ADDR_FAMILY(network)) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("mismatch of address family in "
                             "range %s - %s for network %s"),
                           startStr, endStr, netStr);
            goto error;
        }

        if (prefix < 0 ||
            virSocketAddrPrefixToNetmask(prefix, &netmask,
                                         VIR_SOCKET_ADDR_FAMILY(network)) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("bad prefix %d for network %s when "
                             " checking range %s - %s"),
                           prefix, netStr, startStr, endStr);
            goto error;
        }

        /* both start and end of range need to be within network */
        if (virSocketAddrCheckNetmask(start, network, &netmask) <= 0 ||
            virSocketAddrCheckNetmask(end, network, &netmask) <= 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("range %s - %s is not entirely within "
                             "network %s/%d"),
                           startStr, endStr, netStr, prefix);
            goto error;
        }

        if (VIR_SOCKET_ADDR_IS_FAMILY(start, AF_INET)) {
            virSocketAddr netaddr, broadcast;

            if (virSocketAddrBroadcast(network, &netmask, &broadcast) < 0 ||
                virSocketAddrMask(network, &netmask, &netaddr) < 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("failed to construct broadcast or network "
                                 "address for network %s/%d"),
                               netStr, prefix);
                goto error;
            }

            /* Don't allow the start of the range to be the network
             * address (usually "...0") or the end of the range to be the
             * broadcast address (usually "...255"). (the opposite also
             * isn't allowed, but checking for that is implicit in all the
             * other combined checks) (IPv6 doesn't have broadcast and
             * network addresses, so this check is only done for IPv4)
             */
            if (virSocketAddrEqual(start, &netaddr)) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("start of range %s - %s in network %s/%d "
                                 "is the network address"),
                               startStr, endStr, netStr, prefix);
                goto error;
            }

            if (virSocketAddrEqual(end, &broadcast)) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("end of range %s - %s in network %s/%d "
                                 "is the broadcast address"),
                               startStr, endStr, netStr, prefix);
                goto error;
            }
        }
    }

    if (VIR_SOCKET_ADDR_IS_FAMILY(start, AF_INET)) {
        virSocketAddrIPv4 t1, t2;

        if (virSocketAddrGetIPv4Addr(start, &t1) < 0 ||
            virSocketAddrGetIPv4Addr(end, &t2) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to get IPv4 address "
                             "for start or end of range %s - %s"),
                           startStr, endStr);
            goto error;
        }

        /* legacy check that everything except the last two bytes
         * are the same
         */
        for (i = 0; i < 2; i++) {
            if (t1[i] != t2[i]) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("range %s - %s is too large (> 65535)"),
                           startStr, endStr);
            goto error;
            }
        }
        ret = (t2[2] - t1[2]) * 256 + (t2[3] - t1[3]);
        if (ret < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("range %s - %s is reversed "),
                           startStr, endStr);
            goto error;
        }
        ret++;
    } else if (VIR_SOCKET_ADDR_IS_FAMILY(start, AF_INET6)) {
        virSocketAddrIPv6 t1, t2;

        if (virSocketAddrGetIPv6Addr(start, &t1) < 0 ||
            virSocketAddrGetIPv6Addr(end, &t2) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to get IPv6 address "
                             "for start or end of range %s - %s"),
                           startStr, endStr);
            goto error;
        }

        /* legacy check that everything except the last two bytes are
         * the same
         */
        for (i = 0; i < 7; i++) {
            if (t1[i] != t2[i]) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("range %s - %s is too large (> 65535)"),
                               startStr, endStr);
                goto error;
            }
        }
        ret = t2[7] - t1[7];
        if (ret < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("range %s - %s start larger than end"),
                           startStr, endStr);
            goto error;
        }
        ret++;
    } else {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unsupported address family "
                         "for range %s - %s, must be ipv4 or ipv6"),
                       startStr, endStr);
        goto error;
    }

 cleanup:
    VIR_FREE(startStr);
    VIR_FREE(endStr);
    VIR_FREE(netStr);
    return ret;

 error:
    ret = -1;
    goto cleanup;
}