"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/lib/isc/netaddr.c" (4 Sep 2020, 10308 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "netaddr.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /*! \file */
   13 
   14 #include <inttypes.h>
   15 #include <stdbool.h>
   16 #include <stdio.h>
   17 
   18 #include <isc/buffer.h>
   19 #include <isc/net.h>
   20 #include <isc/netaddr.h>
   21 #include <isc/print.h>
   22 #include <isc/sockaddr.h>
   23 #include <isc/string.h>
   24 #include <isc/util.h>
   25 
   26 bool
   27 isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
   28     REQUIRE(a != NULL && b != NULL);
   29 
   30     if (a->family != b->family) {
   31         return (false);
   32     }
   33 
   34     if (a->zone != b->zone) {
   35         return (false);
   36     }
   37 
   38     switch (a->family) {
   39     case AF_INET:
   40         if (a->type.in.s_addr != b->type.in.s_addr) {
   41             return (false);
   42         }
   43         break;
   44     case AF_INET6:
   45         if (memcmp(&a->type.in6, &b->type.in6, sizeof(a->type.in6)) !=
   46                 0 ||
   47             a->zone != b->zone)
   48         {
   49             return (false);
   50         }
   51         break;
   52 #ifdef ISC_PLATFORM_HAVESYSUNH
   53     case AF_UNIX:
   54         if (strcmp(a->type.un, b->type.un) != 0) {
   55             return (false);
   56         }
   57         break;
   58 #endif /* ifdef ISC_PLATFORM_HAVESYSUNH */
   59     default:
   60         return (false);
   61     }
   62     return (true);
   63 }
   64 
   65 bool
   66 isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
   67              unsigned int prefixlen) {
   68     const unsigned char *pa = NULL, *pb = NULL;
   69     unsigned int ipabytes = 0; /* Length of whole IP address in bytes */
   70     unsigned int nbytes;       /* Number of significant whole bytes */
   71     unsigned int nbits;    /* Number of significant leftover bits */
   72 
   73     REQUIRE(a != NULL && b != NULL);
   74 
   75     if (a->family != b->family) {
   76         return (false);
   77     }
   78 
   79     if (a->zone != b->zone && b->zone != 0) {
   80         return (false);
   81     }
   82 
   83     switch (a->family) {
   84     case AF_INET:
   85         pa = (const unsigned char *)&a->type.in;
   86         pb = (const unsigned char *)&b->type.in;
   87         ipabytes = 4;
   88         break;
   89     case AF_INET6:
   90         pa = (const unsigned char *)&a->type.in6;
   91         pb = (const unsigned char *)&b->type.in6;
   92         ipabytes = 16;
   93         break;
   94     default:
   95         return (false);
   96     }
   97 
   98     /*
   99      * Don't crash if we get a pattern like 10.0.0.1/9999999.
  100      */
  101     if (prefixlen > ipabytes * 8) {
  102         prefixlen = ipabytes * 8;
  103     }
  104 
  105     nbytes = prefixlen / 8;
  106     nbits = prefixlen % 8;
  107 
  108     if (nbytes > 0) {
  109         if (memcmp(pa, pb, nbytes) != 0) {
  110             return (false);
  111         }
  112     }
  113     if (nbits > 0) {
  114         unsigned int bytea, byteb, mask;
  115         INSIST(nbytes < ipabytes);
  116         INSIST(nbits < 8);
  117         bytea = pa[nbytes];
  118         byteb = pb[nbytes];
  119         mask = (0xFF << (8 - nbits)) & 0xFF;
  120         if ((bytea & mask) != (byteb & mask)) {
  121             return (false);
  122         }
  123     }
  124     return (true);
  125 }
  126 
  127 isc_result_t
  128 isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) {
  129     char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
  130     char zbuf[sizeof("%4294967295")];
  131     unsigned int alen;
  132     int zlen;
  133     const char *r;
  134     const void *type;
  135 
  136     REQUIRE(netaddr != NULL);
  137 
  138     switch (netaddr->family) {
  139     case AF_INET:
  140         type = &netaddr->type.in;
  141         break;
  142     case AF_INET6:
  143         type = &netaddr->type.in6;
  144         break;
  145 #ifdef ISC_PLATFORM_HAVESYSUNH
  146     case AF_UNIX:
  147         alen = strlen(netaddr->type.un);
  148         if (alen > isc_buffer_availablelength(target)) {
  149             return (ISC_R_NOSPACE);
  150         }
  151         isc_buffer_putmem(target,
  152                   (const unsigned char *)(netaddr->type.un),
  153                   alen);
  154         return (ISC_R_SUCCESS);
  155 #endif /* ifdef ISC_PLATFORM_HAVESYSUNH */
  156     default:
  157         return (ISC_R_FAILURE);
  158     }
  159     r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf));
  160     if (r == NULL) {
  161         return (ISC_R_FAILURE);
  162     }
  163 
  164     alen = strlen(abuf);
  165     INSIST(alen < sizeof(abuf));
  166 
  167     zlen = 0;
  168     if (netaddr->family == AF_INET6 && netaddr->zone != 0) {
  169         zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone);
  170         if (zlen < 0) {
  171             return (ISC_R_FAILURE);
  172         }
  173         INSIST((unsigned int)zlen < sizeof(zbuf));
  174     }
  175 
  176     if (alen + zlen > isc_buffer_availablelength(target)) {
  177         return (ISC_R_NOSPACE);
  178     }
  179 
  180     isc_buffer_putmem(target, (unsigned char *)abuf, alen);
  181     isc_buffer_putmem(target, (unsigned char *)zbuf, (unsigned int)zlen);
  182 
  183     return (ISC_R_SUCCESS);
  184 }
  185 
  186 void
  187 isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) {
  188     isc_result_t result;
  189     isc_buffer_t buf;
  190 
  191     isc_buffer_init(&buf, array, size);
  192     result = isc_netaddr_totext(na, &buf);
  193 
  194     if (size == 0) {
  195         return;
  196     }
  197 
  198     /*
  199      * Null terminate.
  200      */
  201     if (result == ISC_R_SUCCESS) {
  202         if (isc_buffer_availablelength(&buf) >= 1) {
  203             isc_buffer_putuint8(&buf, 0);
  204         } else {
  205             result = ISC_R_NOSPACE;
  206         }
  207     }
  208 
  209     if (result != ISC_R_SUCCESS) {
  210         snprintf(array, size, "<unknown address, family %u>",
  211              na->family);
  212         array[size - 1] = '\0';
  213     }
  214 }
  215 
  216 isc_result_t
  217 isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
  218     static const unsigned char zeros[16];
  219     unsigned int nbits, nbytes, ipbytes = 0;
  220     const unsigned char *p;
  221 
  222     switch (na->family) {
  223     case AF_INET:
  224         p = (const unsigned char *)&na->type.in;
  225         ipbytes = 4;
  226         if (prefixlen > 32) {
  227             return (ISC_R_RANGE);
  228         }
  229         break;
  230     case AF_INET6:
  231         p = (const unsigned char *)&na->type.in6;
  232         ipbytes = 16;
  233         if (prefixlen > 128) {
  234             return (ISC_R_RANGE);
  235         }
  236         break;
  237     default:
  238         return (ISC_R_NOTIMPLEMENTED);
  239     }
  240     nbytes = prefixlen / 8;
  241     nbits = prefixlen % 8;
  242     if (nbits != 0) {
  243         INSIST(nbytes < ipbytes);
  244         if ((p[nbytes] & (0xff >> nbits)) != 0U) {
  245             return (ISC_R_FAILURE);
  246         }
  247         nbytes++;
  248     }
  249     if (nbytes < ipbytes &&
  250         memcmp(p + nbytes, zeros, ipbytes - nbytes) != 0) {
  251         return (ISC_R_FAILURE);
  252     }
  253     return (ISC_R_SUCCESS);
  254 }
  255 
  256 isc_result_t
  257 isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
  258     unsigned int nbits = 0, nbytes = 0, ipbytes = 0, i;
  259     const unsigned char *p;
  260 
  261     switch (s->family) {
  262     case AF_INET:
  263         p = (const unsigned char *)&s->type.in;
  264         ipbytes = 4;
  265         break;
  266     case AF_INET6:
  267         p = (const unsigned char *)&s->type.in6;
  268         ipbytes = 16;
  269         break;
  270     default:
  271         return (ISC_R_NOTIMPLEMENTED);
  272     }
  273     for (i = 0; i < ipbytes; i++) {
  274         if (p[i] != 0xFF) {
  275             break;
  276         }
  277     }
  278     nbytes = i;
  279     if (i < ipbytes) {
  280         unsigned int c = p[nbytes];
  281         while ((c & 0x80) != 0 && nbits < 8) {
  282             c <<= 1;
  283             nbits++;
  284         }
  285         if ((c & 0xFF) != 0) {
  286             return (ISC_R_MASKNONCONTIG);
  287         }
  288         i++;
  289     }
  290     for (; i < ipbytes; i++) {
  291         if (p[i] != 0) {
  292             return (ISC_R_MASKNONCONTIG);
  293         }
  294     }
  295     *lenp = nbytes * 8 + nbits;
  296     return (ISC_R_SUCCESS);
  297 }
  298 
  299 void
  300 isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) {
  301     memset(netaddr, 0, sizeof(*netaddr));
  302     netaddr->family = AF_INET;
  303     netaddr->type.in = *ina;
  304 }
  305 
  306 void
  307 isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
  308     memset(netaddr, 0, sizeof(*netaddr));
  309     netaddr->family = AF_INET6;
  310     netaddr->type.in6 = *ina6;
  311 }
  312 
  313 isc_result_t
  314 isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) {
  315 #ifdef ISC_PLATFORM_HAVESYSUNH
  316     if (strlen(path) > sizeof(netaddr->type.un) - 1) {
  317         return (ISC_R_NOSPACE);
  318     }
  319 
  320     memset(netaddr, 0, sizeof(*netaddr));
  321     netaddr->family = AF_UNIX;
  322     strlcpy(netaddr->type.un, path, sizeof(netaddr->type.un));
  323     netaddr->zone = 0;
  324     return (ISC_R_SUCCESS);
  325 #else  /* ifdef ISC_PLATFORM_HAVESYSUNH */
  326     UNUSED(netaddr);
  327     UNUSED(path);
  328     return (ISC_R_NOTIMPLEMENTED);
  329 #endif /* ifdef ISC_PLATFORM_HAVESYSUNH */
  330 }
  331 
  332 void
  333 isc_netaddr_setzone(isc_netaddr_t *netaddr, uint32_t zone) {
  334     /* we currently only support AF_INET6. */
  335     REQUIRE(netaddr->family == AF_INET6);
  336 
  337     netaddr->zone = zone;
  338 }
  339 
  340 uint32_t
  341 isc_netaddr_getzone(const isc_netaddr_t *netaddr) {
  342     return (netaddr->zone);
  343 }
  344 
  345 void
  346 isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) {
  347     int family = s->type.sa.sa_family;
  348     t->family = family;
  349     switch (family) {
  350     case AF_INET:
  351         t->type.in = s->type.sin.sin_addr;
  352         t->zone = 0;
  353         break;
  354     case AF_INET6:
  355         memmove(&t->type.in6, &s->type.sin6.sin6_addr, 16);
  356         t->zone = s->type.sin6.sin6_scope_id;
  357         break;
  358 #ifdef ISC_PLATFORM_HAVESYSUNH
  359     case AF_UNIX:
  360         memmove(t->type.un, s->type.sunix.sun_path, sizeof(t->type.un));
  361         t->zone = 0;
  362         break;
  363 #endif /* ifdef ISC_PLATFORM_HAVESYSUNH */
  364     default:
  365         INSIST(0);
  366         ISC_UNREACHABLE();
  367     }
  368 }
  369 
  370 void
  371 isc_netaddr_any(isc_netaddr_t *netaddr) {
  372     memset(netaddr, 0, sizeof(*netaddr));
  373     netaddr->family = AF_INET;
  374     netaddr->type.in.s_addr = INADDR_ANY;
  375 }
  376 
  377 void
  378 isc_netaddr_any6(isc_netaddr_t *netaddr) {
  379     memset(netaddr, 0, sizeof(*netaddr));
  380     netaddr->family = AF_INET6;
  381     netaddr->type.in6 = in6addr_any;
  382 }
  383 
  384 void
  385 isc_netaddr_unspec(isc_netaddr_t *netaddr) {
  386     memset(netaddr, 0, sizeof(*netaddr));
  387     netaddr->family = AF_UNSPEC;
  388 }
  389 
  390 bool
  391 isc_netaddr_ismulticast(const isc_netaddr_t *na) {
  392     switch (na->family) {
  393     case AF_INET:
  394         return (ISC_IPADDR_ISMULTICAST(na->type.in.s_addr));
  395     case AF_INET6:
  396         return (IN6_IS_ADDR_MULTICAST(&na->type.in6));
  397     default:
  398         return (false); /* XXXMLG ? */
  399     }
  400 }
  401 
  402 bool
  403 isc_netaddr_isexperimental(const isc_netaddr_t *na) {
  404     switch (na->family) {
  405     case AF_INET:
  406         return (ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr));
  407     default:
  408         return (false); /* XXXMLG ? */
  409     }
  410 }
  411 
  412 bool
  413 isc_netaddr_islinklocal(const isc_netaddr_t *na) {
  414     switch (na->family) {
  415     case AF_INET:
  416         return (false);
  417     case AF_INET6:
  418         return (IN6_IS_ADDR_LINKLOCAL(&na->type.in6));
  419     default:
  420         return (false);
  421     }
  422 }
  423 
  424 bool
  425 isc_netaddr_issitelocal(const isc_netaddr_t *na) {
  426     switch (na->family) {
  427     case AF_INET:
  428         return (false);
  429     case AF_INET6:
  430         return (IN6_IS_ADDR_SITELOCAL(&na->type.in6));
  431     default:
  432         return (false);
  433     }
  434 }
  435 
  436 #define ISC_IPADDR_ISNETZERO(i) \
  437     (((uint32_t)(i)&ISC__IPADDR(0xff000000)) == ISC__IPADDR(0x00000000))
  438 
  439 bool
  440 isc_netaddr_isnetzero(const isc_netaddr_t *na) {
  441     switch (na->family) {
  442     case AF_INET:
  443         return (ISC_IPADDR_ISNETZERO(na->type.in.s_addr));
  444     case AF_INET6:
  445         return (false);
  446     default:
  447         return (false);
  448     }
  449 }
  450 
  451 void
  452 isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) {
  453     isc_netaddr_t *src;
  454 
  455     DE_CONST(s, src); /* Must come before IN6_IS_ADDR_V4MAPPED. */
  456 
  457     REQUIRE(s->family == AF_INET6);
  458     REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6));
  459 
  460     memset(t, 0, sizeof(*t));
  461     t->family = AF_INET;
  462     memmove(&t->type.in, (char *)&src->type.in6 + 12, 4);
  463     return;
  464 }
  465 
  466 bool
  467 isc_netaddr_isloopback(const isc_netaddr_t *na) {
  468     switch (na->family) {
  469     case AF_INET:
  470         return (((ntohl(na->type.in.s_addr) & 0xff000000U) ==
  471              0x7f000000U));
  472     case AF_INET6:
  473         return (IN6_IS_ADDR_LOOPBACK(&na->type.in6));
  474     default:
  475         return (false);
  476     }
  477 }