virsocketaddr.c 36.0 KB
Newer Older
1
/*
2
 * Copyright (C) 2009-2016 Red Hat, Inc.
3 4 5 6 7 8 9 10 11 12 13 14
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
15
 * License along with this library.  If not, see
O
Osier Yang 已提交
16
 * <http://www.gnu.org/licenses/>.
17 18 19 20 21
 */

#include <config.h>

#include "virsocketaddr.h"
22
#include "virerror.h"
23
#include "virstring.h"
24
#include "virbuffer.h"
25
#include "viralloc.h"
26 27 28 29 30 31 32 33 34 35 36 37 38

#include <netdb.h>

#define VIR_FROM_THIS VIR_FROM_NONE

/*
 * Helpers to extract the IP arrays from the virSocketAddrPtr
 * That part is the less portable of the module
 */
typedef unsigned char virSocketAddrIPv4[4];
typedef virSocketAddrIPv4 *virSocketAddrIPv4Ptr;
typedef unsigned short virSocketAddrIPv6[8];
typedef virSocketAddrIPv6 *virSocketAddrIPv6Ptr;
39 40
typedef unsigned char virSocketAddrIPv6Nibbles[32];
typedef virSocketAddrIPv6Nibbles *virSocketAddrIPv6NibblesPtr;
41

42 43 44 45
static int
virSocketAddrGetIPv4Addr(const virSocketAddr *addr,
                         virSocketAddrIPv4Ptr tab)
{
46
    unsigned long val;
47
    size_t i;
48

49
    if (!addr || !tab || addr->data.stor.ss_family != AF_INET)
50
        return -1;
51 52 53

    val = ntohl(addr->data.inet4.sin_addr.s_addr);

54
    for (i = 0; i < 4; i++) {
55 56 57 58
        (*tab)[3 - i] = val & 0xFF;
        val >>= 8;
    }

59
    return 0;
60 61
}

62 63 64
static int
virSocketAddrGetIPv6Addr(const virSocketAddr *addr, virSocketAddrIPv6Ptr tab)
{
65
    size_t i;
66

67
    if (!addr || !tab || addr->data.stor.ss_family != AF_INET6)
68
        return -1;
69

70
    for (i = 0; i < 8; i++) {
71 72 73 74
        (*tab)[i] = ((addr->data.inet6.sin6_addr.s6_addr[2 * i] << 8) |
                     addr->data.inet6.sin6_addr.s6_addr[2 * i + 1]);
    }

75
    return 0;
76 77
}

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
static int
virSocketAddrGetIPv6Nibbles(const virSocketAddr *addr,
                            virSocketAddrIPv6NibblesPtr tab)
{
    size_t i;

    if (!addr || !tab || addr->data.stor.ss_family != AF_INET6)
        return -1;

    for (i = 0; i < 16; i++) {
        (*tab)[2 * i] = addr->data.inet6.sin6_addr.s6_addr[i] >> 4;
        (*tab)[2 * i + 1] = addr->data.inet6.sin6_addr.s6_addr[i] & 0xF;
    }

    return 0;
}

95 96 97 98
static int
virSocketAddrParseInternal(struct addrinfo **res,
                           const char *val,
                           int family,
99
                           int ai_flags,
100 101 102 103 104 105
                           bool reportError)
{
    struct addrinfo hints;
    int err;

    if (val == NULL) {
106 107
        if (reportError)
            virReportError(VIR_ERR_INVALID_ARG, "%s", _("Missing address"));
108 109 110 111 112
        return -1;
    }

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = family;
113
    hints.ai_flags = ai_flags;
114 115 116 117 118 119 120 121 122 123 124 125
    if ((err = getaddrinfo(val, NULL, &hints, res)) != 0) {
        if (reportError)
            virReportError(VIR_ERR_SYSTEM_ERROR,
                           _("Cannot parse socket address '%s': %s"),
                           val, gai_strerror(err));

        return -1;
    }

    return 0;
}

126 127 128 129 130 131 132 133 134 135 136
/**
 * virSocketAddrParse:
 * @val: a numeric network address IPv4 or IPv6
 * @addr: where to store the return value, optional.
 * @family: address family to pass down to getaddrinfo
 *
 * Mostly a wrapper for getaddrinfo() extracting the address storage
 * from the numeric string like 1.2.3.4 or 2001:db8:85a3:0:0:8a2e:370:7334
 *
 * Returns the length of the network address or -1 in case of error.
 */
137 138
int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family)
{
139
    int len;
140
    struct addrinfo *res;
141

142
    if (virSocketAddrParseInternal(&res, val, family, AI_NUMERICHOST, true) < 0)
143 144 145
        return -1;

    if (res == NULL) {
146
        virReportError(VIR_ERR_SYSTEM_ERROR,
147 148 149 150 151 152 153 154 155 156 157 158
                       _("No socket addresses found for '%s'"),
                       val);
        return -1;
    }

    len = res->ai_addrlen;
    if (addr != NULL) {
        memcpy(&addr->data.stor, res->ai_addr, len);
        addr->len = res->ai_addrlen;
    }

    freeaddrinfo(res);
159
    return len;
160 161
}

162 163 164 165 166 167 168 169 170 171 172 173
/**
 * virSocketAddrParseAny:
 * @addr: where to store the return value, optional.
 * @val: a network host name or a numeric network address IPv4 or IPv6
 * @family: address family to pass down to getaddrinfo
 * @reportError: boolean to control error reporting
 *
 * Mostly a wrapper for getaddrinfo() extracting the address storage
 * from a host name like acme.example.com or a numeric string like 1.2.3.4
 * or 2001:db8:85a3:0:0:8a2e:370:7334.
 *
 * When @val is a network host name, this function may be susceptible to a
174
 * delay due to potentially lengthy network host address lookups.
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
 *
 * Returns the length of the network address or -1 in case of error.
 */
int virSocketAddrParseAny(virSocketAddrPtr addr,
                          const char *val,
                          int family,
                          bool reportError)
{
    int len;
    struct addrinfo *res;

    if (virSocketAddrParseInternal(&res, val, family, 0, reportError) < 0)
        return -1;

    if (res == NULL) {
        if (reportError) {
            virReportError(VIR_ERR_SYSTEM_ERROR,
                           _("No socket addresses found for '%s'"),
                           val);
        }
        return -1;
    }

    len = res->ai_addrlen;
    if (addr != NULL) {
        memcpy(&addr->data.stor, res->ai_addr, len);
        addr->len = res->ai_addrlen;
    }

    freeaddrinfo(res);
    return len;
}

208 209 210 211 212 213 214 215 216 217
/*
 * virSocketAddrParseIPv4:
 * @val: an IPv4 numeric address
 * @addr: the location to store the result
 *
 * Extract the address storage from an IPv4 numeric address
 *
 * Returns the length of the network address or -1 in case of error.
 */
int
218 219
virSocketAddrParseIPv4(virSocketAddrPtr addr, const char *val)
{
220 221 222 223 224 225 226 227 228 229 230 231 232
    return virSocketAddrParse(addr, val, AF_INET);
}

/*
 * virSocketAddrParseIPv6:
 * @val: an IPv6 numeric address
 * @addr: the location to store the result
 *
 * Extract the address storage from an IPv6 numeric address
 *
 * Returns the length of the network address or -1 in case of error.
 */
int
233 234
virSocketAddrParseIPv6(virSocketAddrPtr addr, const char *val)
{
235 236 237
    return virSocketAddrParse(addr, val, AF_INET6);
}

238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
/*
 * virSocketAddrSetIPv4AddrNetOrder:
 * @addr: the location to store the result
 * @val: the 32bit integer in network byte order representing the IPv4 address
 *
 * Set the IPv4 address given an integer in network order. This function does not
 * touch any previously set port.
 */
void
virSocketAddrSetIPv4AddrNetOrder(virSocketAddrPtr addr, uint32_t val)
{
    addr->data.stor.ss_family = AF_INET;
    addr->data.inet4.sin_addr.s_addr = val;
    addr->len = sizeof(struct sockaddr_in);
}

254 255 256 257 258 259 260 261 262 263 264
/*
 * virSocketAddrSetIPv4Addr:
 * @addr: the location to store the result
 * @val: the 32bit integer in host byte order representing the IPv4 address
 *
 * Set the IPv4 address given an integer in host order. This function does not
 * touch any previously set port.
 */
void
virSocketAddrSetIPv4Addr(virSocketAddrPtr addr, uint32_t val)
{
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
    virSocketAddrSetIPv4AddrNetOrder(addr, htonl(val));
}

/*
 * virSocketAddrSetIPv6AddrNetOrder:
 * @addr: the location to store the result
 * @val: the 128bit integer in network byte order representing the IPv6 address
 *
 * Set the IPv6 address given an integer in network order. This function does not
 * touch any previously set port.
 */
void virSocketAddrSetIPv6AddrNetOrder(virSocketAddrPtr addr, uint32_t val[4])
{
    addr->data.stor.ss_family = AF_INET6;
    memcpy(addr->data.inet6.sin6_addr.s6_addr, val, 4 * sizeof(*val));
    addr->len = sizeof(struct sockaddr_in6);
281 282
}

283 284 285 286 287 288 289 290 291 292
/*
 * virSocketAddrSetIPv6Addr:
 * @addr: the location to store the result
 * @val: the 128bit integer in host byte order representing the IPv6 address
 *
 * Set the IPv6 address given an integer in host order. This function does not
 * touch any previously set port.
 */
void virSocketAddrSetIPv6Addr(virSocketAddrPtr addr, uint32_t val[4])
{
293 294 295 296 297 298 299
    size_t i = 0;
    uint32_t host_val[4];

    for (i = 0; i < 4; i++)
        host_val[i] = htonl(val[i]);

    virSocketAddrSetIPv6AddrNetOrder(addr, host_val);
300 301
}

302 303 304 305 306 307 308 309 310
/*
 * virSocketAddrEqual:
 * @s1: the location of the one IP address
 * @s2: the location of the other IP address
 *
 * Compare two IP addresses for equality. Two addresses are equal
 * if their IP addresses and ports are equal.
 */
bool
311
virSocketAddrEqual(const virSocketAddr *s1, const virSocketAddr *s2)
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
{
    if (s1->data.stor.ss_family != s2->data.stor.ss_family)
        return false;

    switch (s1->data.stor.ss_family) {
    case AF_INET:
        return (memcmp(&s1->data.inet4.sin_addr.s_addr,
                       &s2->data.inet4.sin_addr.s_addr,
                       sizeof(s1->data.inet4.sin_addr.s_addr)) == 0 &&
                s1->data.inet4.sin_port == s2->data.inet4.sin_port);
    case AF_INET6:
        return (memcmp(&s1->data.inet6.sin6_addr.s6_addr,
                       &s2->data.inet6.sin6_addr.s6_addr,
                       sizeof(s1->data.inet6.sin6_addr.s6_addr)) == 0 &&
                s1->data.inet6.sin6_port == s2->data.inet6.sin6_port);
    }
328 329 330 331 332 333 334 335 336
    return false;
}

/*
 * virSocketAddrIsPrivate:
 * @s: the location of the IP address
 *
 * Return true if this address is in its family's defined
 * "private/local" address space. For IPv4, private addresses are in
337
 * the range of 192.168.0.0/16, 172.16.0.0/12, or 10.0.0.0/8.  For
338 339 340 341 342 343
 * IPv6, local addresses are in the range of FC00::/7 or FEC0::/10
 * (that last one is deprecated, but still in use).
 *
 * See RFC1918, RFC3484, and RFC4193 for details.
 */
bool
344
virSocketAddrIsPrivate(const virSocketAddr *addr)
345 346 347 348 349 350 351
{
    unsigned long val;

    switch (addr->data.stor.ss_family) {
    case AF_INET:
       val = ntohl(addr->data.inet4.sin_addr.s_addr);

352 353 354
       return ((val & 0xFFFF0000) == ((192UL << 24) + (168 << 16)) ||
               (val & 0xFFF00000) == ((172UL << 24) + (16  << 16)) ||
               (val & 0xFF000000) == ((10UL  << 24)));
355 356 357 358 359 360

    case AF_INET6:
        return ((addr->data.inet6.sin6_addr.s6_addr[0] & 0xFE) == 0xFC ||
                ((addr->data.inet6.sin6_addr.s6_addr[0] & 0xFF) == 0xFE &&
                 (addr->data.inet6.sin6_addr.s6_addr[1] & 0xC0) == 0xC0));
    }
361 362 363
    return false;
}

364 365 366 367 368 369 370
/*
 * virSocketAddrIsWildcard:
 * @addr: address to check
 *
 * Check if passed address is a variant of ANYCAST address.
 */
bool
371
virSocketAddrIsWildcard(const virSocketAddr *addr)
372
{
373
    struct in_addr tmp = { .s_addr = INADDR_ANY };
374 375
    switch (addr->data.stor.ss_family) {
    case AF_INET:
376
        return memcmp(&addr->data.inet4.sin_addr.s_addr, &tmp.s_addr,
377 378
                      sizeof(addr->data.inet4.sin_addr.s_addr)) == 0;
    case AF_INET6:
379
        return IN6_IS_ADDR_UNSPECIFIED(&addr->data.inet6.sin6_addr);
380 381 382 383
    }
    return false;
}

384 385 386 387 388 389 390 391 392
/*
 * virSocketAddrFormat:
 * @addr: an initialized virSocketAddrPtr
 *
 * Returns a string representation of the given address
 * Returns NULL on any error
 * Caller must free the returned string
 */
char *
393 394
virSocketAddrFormat(const virSocketAddr *addr)
{
395 396 397 398 399 400 401 402 403 404
    return virSocketAddrFormatFull(addr, false, NULL);
}


/*
 * virSocketAddrFormatFull:
 * @addr: an initialized virSocketAddrPtr
 * @withService: if true, then service info is appended
 * @separator: separator between hostname & service.
 *
405 406 407 408 409
 * Returns a string representation of the given address. If a format conforming
 * to URI specification is required, NULL should be passed to separator.
 * Set @separator only if non-URI format is required, e.g. passing ';' for
 * @separator if the address should be used with SASL.
 * Caller must free the returned string.
410 411
 */
char *
412
virSocketAddrFormatFull(const virSocketAddr *addr,
413 414 415 416 417 418 419 420
                        bool withService,
                        const char *separator)
{
    char host[NI_MAXHOST], port[NI_MAXSERV];
    char *addrstr;
    int err;

    if (addr == NULL) {
421
        virReportError(VIR_ERR_INVALID_ARG, "%s", _("Missing address"));
422 423 424 425 426 427 428
        return NULL;
    }

    /* Short-circuit since getnameinfo doesn't work
     * nicely for UNIX sockets */
    if (addr->data.sa.sa_family == AF_UNIX) {
        if (withService) {
429
            if (virAsprintf(&addrstr, VIR_LOOPBACK_IPV4_ADDR"%s0",
430
                            separator ? separator : ":") < 0)
431
                return NULL;
432
        } else {
433
            if (VIR_STRDUP(addrstr, VIR_LOOPBACK_IPV4_ADDR) < 0)
434
                return NULL;
435 436 437 438 439 440 441 442 443
        }
        return addrstr;
    }

    if ((err = getnameinfo(&addr->data.sa,
                           addr->len,
                           host, sizeof(host),
                           port, sizeof(port),
                           NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
444
        virReportError(VIR_ERR_SYSTEM_ERROR,
445 446 447 448 449 450
                       _("Cannot convert socket address to string: %s"),
                       gai_strerror(err));
        return NULL;
    }

    if (withService) {
451
        VIR_AUTOFREE(char *) ipv6_host = NULL;
452 453 454 455 456 457
        /* sasl_new_client demands the socket address to be in an odd format:
         * a.b.c.d;port or e:f:g:h:i:j:k:l;port, so use square brackets for
         * IPv6 only if no separator is passed to the function
         */
        if (!separator && VIR_SOCKET_ADDR_FAMILY(addr) == AF_INET6) {
            if (virAsprintf(&ipv6_host, "[%s]", host) < 0)
458
                return NULL;
459 460 461 462
        }

        if (virAsprintf(&addrstr, "%s%s%s",
                        ipv6_host ? ipv6_host : host,
463
                        separator ? separator : ":", port) == -1) {
464
            return NULL;
465
        }
466
    } else {
467
        if (VIR_STRDUP(addrstr, host) < 0)
468
            return NULL;
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
    }

    return addrstr;
}


/*
 * virSocketAddrSetPort:
 * @addr: an initialized virSocketAddrPtr
 * @port: the port number to set
 *
 * Set the transport layer port of the given virtSocketAddr
 *
 * Returns 0 on success, -1 on failure
 */
int
485 486
virSocketAddrSetPort(virSocketAddrPtr addr, int port)
{
487 488 489 490 491
    if (addr == NULL)
        return -1;

    port = htons(port);

492
    if (addr->data.stor.ss_family == AF_INET) {
493
        addr->data.inet4.sin_port = port;
494
    } else if (addr->data.stor.ss_family == AF_INET6) {
495
        addr->data.inet6.sin6_port = port;
496
    } else {
497 498 499 500 501 502 503 504 505 506 507 508 509 510
        return -1;
    }

    return 0;
}

/*
 * virSocketGetPort:
 * @addr: an initialized virSocketAddrPtr
 *
 * Returns the transport layer port of the given virtSocketAddr
 * Returns -1 if @addr is invalid
 */
int
511 512
virSocketAddrGetPort(virSocketAddrPtr addr)
{
513 514 515
    if (addr == NULL)
        return -1;

516
    if (addr->data.stor.ss_family == AF_INET) {
517
        return ntohs(addr->data.inet4.sin_port);
518
    } else if (addr->data.stor.ss_family == AF_INET6) {
519 520 521 522 523 524 525 526 527 528 529 530 531 532
        return ntohs(addr->data.inet6.sin6_port);
    }

    return -1;
}

/**
 * virSocketAddrIsNetmask:
 * @netmask: the netmask address
 *
 * Check that @netmask is a proper network mask
 *
 * Returns 0 in case of success and -1 in case of error
 */
533 534
int virSocketAddrIsNetmask(virSocketAddrPtr netmask)
{
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
    int n = virSocketAddrGetNumNetmaskBits(netmask);
    if (n < 0)
        return -1;
    return 0;
}

/**
 * virSocketAddrMask:
 * @addr: address that needs to be masked
 * @netmask: the netmask address
 * @network: where to store the result, can be same as @addr
 *
 * Mask off the host bits of @addr according to @netmask, turning it
 * into a network address.
 *
 * Returns 0 in case of success, or -1 on error.
 */
int
553 554 555
virSocketAddrMask(const virSocketAddr *addr,
                  const virSocketAddr *netmask,
                  virSocketAddrPtr network)
556
{
557
    memset(network, 0, sizeof(*network));
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
    if (addr->data.stor.ss_family != netmask->data.stor.ss_family) {
        network->data.stor.ss_family = AF_UNSPEC;
        return -1;
    }

    if (addr->data.stor.ss_family == AF_INET) {
        network->data.inet4.sin_addr.s_addr
            = (addr->data.inet4.sin_addr.s_addr
               & netmask->data.inet4.sin_addr.s_addr);
        network->data.inet4.sin_port = 0;
        network->data.stor.ss_family = AF_INET;
        network->len = addr->len;
        return 0;
    }
    if (addr->data.stor.ss_family == AF_INET6) {
573 574 575 576 577
        size_t i;
        for (i = 0; i < 16; i++) {
            network->data.inet6.sin6_addr.s6_addr[i]
                = (addr->data.inet6.sin6_addr.s6_addr[i]
                   & netmask->data.inet6.sin6_addr.s6_addr[i]);
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
        }
        network->data.inet6.sin6_port = 0;
        network->data.stor.ss_family = AF_INET6;
        network->len = addr->len;
        return 0;
    }
    network->data.stor.ss_family = AF_UNSPEC;
    return -1;
}

/**
 * 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
600 601 602
virSocketAddrMaskByPrefix(const virSocketAddr *addr,
                          unsigned int prefix,
                          virSocketAddrPtr network)
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
{
    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);
}

/**
 * virSocketAddrBroadcast:
 * @addr: address that needs to be turned into broadcast address (IPv4 only)
 * @netmask: the netmask address
J
Ján Tomko 已提交
619
 * @broadcast: virSocketAddr to receive the broadcast address
620 621 622 623 624 625 626
 *
 * Mask ON the host bits of @addr according to @netmask, turning it
 * into a broadcast address.
 *
 * Returns 0 in case of success, or -1 on error.
 */
int
627 628 629
virSocketAddrBroadcast(const virSocketAddr *addr,
                       const virSocketAddr *netmask,
                       virSocketAddrPtr broadcast)
630
{
631 632
    memset(broadcast, 0, sizeof(*broadcast));

633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
    if ((addr->data.stor.ss_family != AF_INET) ||
        (netmask->data.stor.ss_family != AF_INET)) {
        broadcast->data.stor.ss_family = AF_UNSPEC;
        return -1;
    }

    broadcast->data.stor.ss_family = AF_INET;
    broadcast->len = addr->len;
    broadcast->data.inet4.sin_addr.s_addr
        = (addr->data.inet4.sin_addr.s_addr
           | ~netmask->data.inet4.sin_addr.s_addr);
    return 0;
}

/**
 * virSocketAddrBroadcastByPrefix:
 * @addr: address that needs to be turned into broadcast address (IPv4 only)
 * @prefix: prefix (# of 1 bits) of netmask to apply
J
Ján Tomko 已提交
651
 * @broadcast: virSocketAddr to receive the broadcast address
652 653 654 655 656 657 658
 *
 * 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
659 660 661
virSocketAddrBroadcastByPrefix(const virSocketAddr *addr,
                               unsigned int prefix,
                               virSocketAddrPtr broadcast)
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
{
    virSocketAddr netmask;

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

    return virSocketAddrBroadcast(addr, &netmask, broadcast);
}

/**
 * virSocketCheckNetmask:
 * @addr1: a first network address
 * @addr2: a second network address
 * @netmask: the netmask address
 *
 * Check that @addr1 and @addr2 pertain to the same @netmask address
 * range and returns the size of the range
 *
 * Returns 1 in case of success and 0 in case of failure and
 *         -1 in case of error
 */
int virSocketAddrCheckNetmask(virSocketAddrPtr addr1, virSocketAddrPtr addr2,
685 686
                              virSocketAddrPtr netmask)
{
687
    size_t i;
688 689

    if ((addr1 == NULL) || (addr2 == NULL) || (netmask == NULL))
690
        return -1;
691 692
    if ((addr1->data.stor.ss_family != addr2->data.stor.ss_family) ||
        (addr1->data.stor.ss_family != netmask->data.stor.ss_family))
693
        return -1;
694 695

    if (virSocketAddrIsNetmask(netmask) != 0)
696
        return -1;
697 698 699 700 701 702 703

    if (addr1->data.stor.ss_family == AF_INET) {
        virSocketAddrIPv4 t1, t2, tm;

        if ((virSocketAddrGetIPv4Addr(addr1, &t1) < 0) ||
            (virSocketAddrGetIPv4Addr(addr2, &t2) < 0) ||
            (virSocketAddrGetIPv4Addr(netmask, &tm) < 0))
704
            return -1;
705

706
        for (i = 0; i < 4; i++) {
707
            if ((t1[i] & tm[i]) != (t2[i] & tm[i]))
708
                return 0;
709 710 711 712 713 714 715 716
        }

    } else if (addr1->data.stor.ss_family == AF_INET6) {
        virSocketAddrIPv6 t1, t2, tm;

        if ((virSocketAddrGetIPv6Addr(addr1, &t1) < 0) ||
            (virSocketAddrGetIPv6Addr(addr2, &t2) < 0) ||
            (virSocketAddrGetIPv6Addr(netmask, &tm) < 0))
717
            return -1;
718

719
        for (i = 0; i < 8; i++) {
720
            if ((t1[i] & tm[i]) != (t2[i] & tm[i]))
721
                return 0;
722 723 724
        }

    } else {
725
        return -1;
726
    }
727
    return 1;
728 729 730 731 732 733
}

/**
 * virSocketGetRange:
 * @start: start of an IP range
 * @end: end of an IP range
734 735
 * @network: IP address of network that should completely contain this range
 * @prefix: prefix of the network
736
 *
737 738 739 740 741
 * 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.
742 743 744
 *
 * Returns the size of the range or -1 in case of failure
 */
745 746 747
int
virSocketAddrGetRange(virSocketAddrPtr start, virSocketAddrPtr end,
                      virSocketAddrPtr network, int prefix)
748
{
749 750
    int ret = 0;
    size_t i;
751
    virSocketAddr netmask;
752 753 754
    VIR_AUTOFREE(char *) startStr = NULL;
    VIR_AUTOFREE(char *) endStr = NULL;
    VIR_AUTOFREE(char *) netStr = NULL;
755

756
    if (start == NULL || end == NULL) {
757
        virReportError(VIR_ERR_INTERNAL_ERROR,
758
                       _("NULL argument - %p %p"), start, end);
759
        return -1;
760 761 762 763
    }

    startStr = virSocketAddrFormat(start);
    endStr = virSocketAddrFormat(end);
764
    if (!startStr || !endStr)
765
        return -1; /*error already reported */
766

767
    if (VIR_SOCKET_ADDR_FAMILY(start) != VIR_SOCKET_ADDR_FAMILY(end)) {
768
        virReportError(VIR_ERR_INTERNAL_ERROR,
769 770
                       _("mismatch of address family in range %s - %s"),
                       startStr, endStr);
771
        return -1;
772
    }
773

774 775 776 777 778
    if (network) {
        /* some checks can only be done if we have details of the
         * network the range should be within
         */
        if (!(netStr = virSocketAddrFormat(network)))
779
            return -1;
780

781
        if (VIR_SOCKET_ADDR_FAMILY(start) != VIR_SOCKET_ADDR_FAMILY(network)) {
782
            virReportError(VIR_ERR_INTERNAL_ERROR,
783 784 785
                           _("mismatch of address family in "
                             "range %s - %s for network %s"),
                           startStr, endStr, netStr);
786
            return -1;
787
        }
788

789 790 791
        if (prefix < 0 ||
            virSocketAddrPrefixToNetmask(prefix, &netmask,
                                         VIR_SOCKET_ADDR_FAMILY(network)) < 0) {
792
            virReportError(VIR_ERR_INTERNAL_ERROR,
793 794 795
                           _("bad prefix %d for network %s when "
                             " checking range %s - %s"),
                           prefix, netStr, startStr, endStr);
796
            return -1;
797 798
        }

799 800 801
        /* both start and end of range need to be within network */
        if (virSocketAddrCheckNetmask(start, network, &netmask) <= 0 ||
            virSocketAddrCheckNetmask(end, network, &netmask) <= 0) {
802
            virReportError(VIR_ERR_INTERNAL_ERROR,
803 804
                           _("range %s - %s is not entirely within "
                             "network %s/%d"),
805
                           startStr, endStr, netStr, prefix);
806
            return -1;
807
        }
808

809 810 811 812 813 814 815 816 817
        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);
818
                return -1;
819 820 821 822 823 824 825 826 827 828 829 830 831 832
            }

            /* 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);
833
                return -1;
834 835 836 837 838 839 840
            }

            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);
841
                return -1;
842 843 844 845 846 847 848 849 850
            }
        }
    }

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

        if (virSocketAddrGetIPv4Addr(start, &t1) < 0 ||
            virSocketAddrGetIPv4Addr(end, &t2) < 0) {
851 852
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to get IPv4 address "
853 854
                             "for start or end of range %s - %s"),
                           startStr, endStr);
855
            return -1;
856
        }
857

858 859
        /* legacy check that everything except the last two bytes
         * are the same
860
         */
861
        for (i = 0; i < 2; i++) {
862
            if (t1[i] != t2[i]) {
863 864 865 866
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("range %s - %s is too large (> 65535)"),
                               startStr, endStr);
                return -1;
867
            }
868 869
        }
        ret = (t2[2] - t1[2]) * 256 + (t2[3] - t1[3]);
870 871
        if (ret < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
872 873
                           _("range %s - %s is reversed "),
                           startStr, endStr);
874
            return -1;
875
        }
876
        ret++;
877
    } else if (VIR_SOCKET_ADDR_IS_FAMILY(start, AF_INET6)) {
878 879
        virSocketAddrIPv6 t1, t2;

880 881
        if (virSocketAddrGetIPv6Addr(start, &t1) < 0 ||
            virSocketAddrGetIPv6Addr(end, &t2) < 0) {
882 883
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("failed to get IPv6 address "
884 885
                             "for start or end of range %s - %s"),
                           startStr, endStr);
886
            return -1;
887
        }
888

889 890 891
        /* legacy check that everything except the last two bytes are
         * the same
         */
892
        for (i = 0; i < 7; i++) {
893 894
            if (t1[i] != t2[i]) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
895 896
                               _("range %s - %s is too large (> 65535)"),
                               startStr, endStr);
897
                return -1;
898
            }
899 900
        }
        ret = t2[7] - t1[7];
901 902
        if (ret < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
903 904
                           _("range %s - %s start larger than end"),
                           startStr, endStr);
905
            return -1;
906
        }
907 908
        ret++;
    } else {
909 910
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unsupported address family "
911 912
                         "for range %s - %s, must be ipv4 or ipv6"),
                       startStr, endStr);
913
        return -1;
914
    }
915

916
    return ret;
917 918 919 920 921 922 923 924 925 926 927 928
}


/**
 * virSocketAddrGetNumNetmaskBits
 * @netmask: the presumed netmask
 *
 * Get the number of netmask bits in a netmask.
 *
 * Returns the number of bits in the netmask or -1 if an error occurred
 * or the netmask is invalid.
 */
929
int virSocketAddrGetNumNetmaskBits(const virSocketAddr *netmask)
930
{
931
    size_t i, j;
932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952
    int c = 0;

    if (netmask->data.stor.ss_family == AF_INET) {
        virSocketAddrIPv4 tm;
        uint8_t bit;

        if (virSocketAddrGetIPv4Addr(netmask, &tm) < 0)
            return -1;

        for (i = 0; i < 4; i++)
            if (tm[i] == 0xff)
                c += 8;
            else
                break;

        if (c == 8 * 4)
            return c;

        j = i << 3;
        while (j < (8 * 4)) {
            bit = 1 << (7 - (j & 7));
953
            if ((tm[j >> 3] & bit))
954
                c++;
955
            else
956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
                break;
            j++;
        }

        while (j < (8 * 4)) {
            bit = 1 << (7 - (j & 7));
            if ((tm[j >> 3] & bit))
                return -1;
            j++;
        }

        return c;
    } else if (netmask->data.stor.ss_family == AF_INET6) {
        virSocketAddrIPv6 tm;
        uint16_t bit;

        if (virSocketAddrGetIPv6Addr(netmask, &tm) < 0)
            return -1;

        for (i = 0; i < 8; i++)
            if (tm[i] == 0xffff)
                c += 16;
            else
                break;

        if (c == 16 * 8)
            return c;

        j = i << 4;
        while (j < (16 * 8)) {
            bit = 1 << (15 - (j & 0xf));
987
            if ((tm[j >> 4] & bit))
988
                c++;
989
            else
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
                break;
            j++;
        }

        while (j < (16 * 8)) {
            bit = 1 << (15 - (j & 0xf));
            if ((tm[j >> 4]) & bit)
                return -1;
            j++;
        }

        return c;
    }
    return -1;
}

/**
 * virSocketPrefixToNetmask:
 * @prefix: number of 1 bits to put in the netmask
 * @netmask: address to fill in with the desired netmask
 * @family: family of the address (AF_INET or AF_INET6 only)
 *
 * given @prefix and @family, fill in @netmask with a netmask
 * (eg 255.255.255.0).
 *
 * Returns 0 on success or -1 on error.
 */

int
virSocketAddrPrefixToNetmask(unsigned int prefix,
                             virSocketAddrPtr netmask,
                             int family)
{
    int result = -1;

    netmask->data.stor.ss_family = AF_UNSPEC; /* assume failure */

    if (family == AF_INET) {
        int ip;

        if (prefix > 32)
            goto error;

        ip = prefix ? ~((1 << (32 - prefix)) - 1) : 0;
        netmask->data.inet4.sin_addr.s_addr = htonl(ip);
        netmask->data.stor.ss_family = AF_INET;
1036
        netmask->len = sizeof(struct sockaddr_in);
1037 1038 1039
        result = 0;

    } else if (family == AF_INET6) {
1040
        size_t i = 0;
1041 1042 1043 1044 1045 1046

        if (prefix > 128)
            goto error;

        while (prefix >= 8) {
            /* do as much as possible an entire byte at a time */
1047
            netmask->data.inet6.sin6_addr.s6_addr[i++] = 0xff;
1048 1049 1050 1051
            prefix -= 8;
        }
        if (prefix > 0) {
            /* final partial byte */
1052
            netmask->data.inet6.sin6_addr.s6_addr[i++]
1053 1054
                = ~((1 << (8 - prefix)) -1);
        }
1055
        while (i < 16) {
1056
            /* zerofill remainder in case it wasn't initialized */
1057
            netmask->data.inet6.sin6_addr.s6_addr[i++] = 0;
1058 1059
        }
        netmask->data.stor.ss_family = AF_INET6;
1060
        netmask->len = sizeof(struct sockaddr_in6);
1061 1062 1063
        result = 0;
    }

1064
 error:
1065
    return result;
1066 1067 1068
 }

/**
1069
 * virSocketAddrGetIPPrefix:
1070 1071 1072 1073 1074 1075 1076 1077
 * @address: network address
 * @netmask: netmask for this network
 * @prefix: prefix if specified instead of netmask
 *
 * Returns prefix value on success or -1 on error.
 */

int
1078
virSocketAddrGetIPPrefix(const virSocketAddr *address,
1079
                         const virSocketAddr *netmask,
1080 1081 1082 1083
                         int prefix)
{
    if (prefix > 0) {
        return prefix;
1084
    } else if (netmask && VIR_SOCKET_ADDR_VALID(netmask)) {
1085
        return virSocketAddrGetNumNetmaskBits(netmask);
1086
    } else if (address && VIR_SOCKET_ADDR_IS_FAMILY(address, AF_INET)) {
1087 1088 1089 1090 1091 1092 1093
        /* Return the natural prefix for the network's ip address.
         * On Linux we could use the IN_CLASSx() macros, but those
         * aren't guaranteed on all platforms, so we just deal with
         * the bits ourselves.
         */
        unsigned char octet
            = ntohl(address->data.inet4.sin_addr.s_addr) >> 24;
1094 1095 1096 1097 1098 1099

        /* If address is 0.0.0.0, we surely want to have 0 prefix for
         * the default route. */
        if (address->data.inet4.sin_addr.s_addr == 0)
            return 0;

1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
        if ((octet & 0x80) == 0) {
            /* Class A network */
            return 8;
        } else if ((octet & 0xC0) == 0x80) {
            /* Class B network */
            return 16;
        } else if ((octet & 0xE0) == 0xC0) {
            /* Class C network */
            return 24;
        }
        return -1;
1111
    } else if (address && VIR_SOCKET_ADDR_IS_FAMILY(address, AF_INET6)) {
1112
        if (virSocketAddrIsWildcard(address))
1113
            return 0;
1114 1115 1116 1117 1118 1119 1120 1121 1122
        return 64;
    }

    /* When none of the three (address/netmask/prefix) is given, 0 is
     * returned rather than error, because this is a valid
     * expectation, e.g. for the address/prefix used for a default
     * route (the destination of a default route is 0.0.0.0/0).
     */
    return 0;
1123
}
1124 1125

/**
1126
 * virSocketAddrNumericFamily:
1127 1128
 * @address: address to check
 *
1129
 * Check if passed address is an IP address in numeric format.
1130
 *
1131 1132
 * Returns: AF_INET or AF_INET6 if @address is an numeric IP address,
 *          -1 otherwise.
1133
 */
1134 1135
int
virSocketAddrNumericFamily(const char *address)
1136 1137 1138 1139
{
    struct addrinfo *res;
    unsigned short family;

1140
    if (virSocketAddrParseInternal(&res, address, AF_UNSPEC, AI_NUMERICHOST, false) < 0)
1141
        return -1;
1142 1143 1144

    family = res->ai_addr->sa_family;
    freeaddrinfo(res);
1145
    return family;
1146
}
1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159

/**
 * virSocketAddrIsNumericLocalhost:
 * @address: address to check
 *
 * Check if passed address is a numeric 'localhost' address.
 *
 * Returns: true if @address is a numeric 'localhost' address,
 *          false otherwise
 */
bool
virSocketAddrIsNumericLocalhost(const char *addr)
{
R
Roman Bogorodskiy 已提交
1160
    virSocketAddr res;
1161 1162
    struct in_addr tmp = { .s_addr = htonl(INADDR_LOOPBACK) };

R
Roman Bogorodskiy 已提交
1163 1164
    if (virSocketAddrParse(&res, addr, AF_UNSPEC) < 0)
        return false;
1165

R
Roman Bogorodskiy 已提交
1166
    switch (res.data.stor.ss_family) {
1167
    case AF_INET:
R
Roman Bogorodskiy 已提交
1168
        return memcmp(&res.data.inet4.sin_addr.s_addr, &tmp.s_addr,
1169
                      sizeof(res.data.inet4.sin_addr.s_addr)) == 0;
1170
    case AF_INET6:
R
Roman Bogorodskiy 已提交
1171
        return IN6_IS_ADDR_LOOPBACK(&res.data.inet6.sin6_addr);
1172
    }
1173

R
Roman Bogorodskiy 已提交
1174
    return false;
1175
}
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240


/**
 * virSocketAddrPTRDomain:
 *
 * Create PTR domain which corresponds to @addr/@prefix. Both IPv4 and IPv6
 * addresses are supported, but @prefix must be divisible by 8 for IPv4 and
 * divisible by 4 for IPv6, otherwise -2 will be returned.
 *
 * Returns -2 if the PTR record cannot be automatically created,
 *         -1 on error,
  *         0 on success.
 */
int
virSocketAddrPTRDomain(const virSocketAddr *addr,
                       unsigned int prefix,
                       char **ptr)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    size_t i;
    int ret = -1;

    if (VIR_SOCKET_ADDR_IS_FAMILY(addr, AF_INET)) {
        virSocketAddrIPv4 ip;

        if (prefix == 0 || prefix >= 32 || prefix % 8 != 0)
            goto unsupported;

        if (virSocketAddrGetIPv4Addr(addr, &ip) < 0)
            goto cleanup;

        for (i = prefix / 8; i > 0; i--)
            virBufferAsprintf(&buf, "%u.", ip[i - 1]);

        virBufferAddLit(&buf, VIR_SOCKET_ADDR_IPV4_ARPA);
    } else if (VIR_SOCKET_ADDR_IS_FAMILY(addr, AF_INET6)) {
        virSocketAddrIPv6Nibbles ip;

        if (prefix == 0 || prefix >= 128 || prefix % 4 != 0)
            goto unsupported;

        if (virSocketAddrGetIPv6Nibbles(addr, &ip) < 0)
            goto cleanup;

        for (i = prefix / 4; i > 0; i--)
            virBufferAsprintf(&buf, "%x.", ip[i - 1]);

        virBufferAddLit(&buf, VIR_SOCKET_ADDR_IPV6_ARPA);
    } else {
        goto unsupported;
    }

    if (!(*ptr = virBufferContentAndReset(&buf)))
        goto cleanup;

    ret = 0;

 cleanup:
    virBufferFreeAndReset(&buf);
    return ret;

 unsupported:
    ret = -2;
    goto cleanup;
}
1241 1242 1243 1244 1245 1246

void
virSocketAddrFree(virSocketAddrPtr addr)
{
    VIR_FREE(addr);
}