Annotation of embedaddon/ntp/lib/isc/netaddr.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
                      3:  * Copyright (C) 1999-2002  Internet Software Consortium.
                      4:  *
                      5:  * Permission to use, copy, modify, and/or distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
                     10:  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
                     11:  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
                     12:  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
                     13:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
                     14:  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
                     15:  * PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17: 
                     18: /* $Id: netaddr.c,v 1.38 2007/06/18 23:47:44 tbox Exp $ */
                     19: 
                     20: /*! \file */
                     21: 
                     22: #include <config.h>
                     23: 
                     24: #include <stdio.h>
                     25: 
                     26: #include <isc/buffer.h>
                     27: #include <isc/msgs.h>
                     28: #include <isc/net.h>
                     29: #include <isc/netaddr.h>
                     30: #include <isc/print.h>
                     31: #include <isc/sockaddr.h>
                     32: #include <isc/string.h>
                     33: #include <isc/util.h>
                     34: 
                     35: isc_boolean_t
                     36: isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
                     37:        REQUIRE(a != NULL && b != NULL);
                     38: 
                     39:        if (a->family != b->family)
                     40:                return (ISC_FALSE);
                     41: 
                     42:        if (a->zone != b->zone)
                     43:                return (ISC_FALSE);
                     44: 
                     45:        switch (a->family) {
                     46:        case AF_INET:
                     47:                if (a->type.in.s_addr != b->type.in.s_addr)
                     48:                        return (ISC_FALSE);
                     49:                break;
                     50:        case AF_INET6:
                     51:                if (memcmp(&a->type.in6, &b->type.in6,
                     52:                           sizeof(a->type.in6)) != 0 ||
                     53:                    a->zone != b->zone)
                     54:                        return (ISC_FALSE);
                     55:                break;
                     56: #ifdef ISC_PLATFORM_HAVESYSUNH
                     57:        case AF_UNIX:
                     58:                if (strcmp(a->type.un, b->type.un) != 0)
                     59:                        return (ISC_FALSE);
                     60:                break;
                     61: #endif
                     62:        default:
                     63:                return (ISC_FALSE);
                     64:        }
                     65:        return (ISC_TRUE);
                     66: }
                     67: 
                     68: isc_boolean_t
                     69: isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
                     70:                     unsigned int prefixlen)
                     71: {
                     72:        const unsigned char *pa, *pb;
                     73:        unsigned int ipabytes; /* Length of whole IP address in bytes */
                     74:        unsigned int nbytes;   /* Number of significant whole bytes */
                     75:        unsigned int nbits;    /* Number of significant leftover bits */
                     76: 
                     77:        REQUIRE(a != NULL && b != NULL);
                     78: 
                     79:        if (a->family != b->family)
                     80:                return (ISC_FALSE);
                     81: 
                     82:        if (a->zone != b->zone && b->zone != 0)
                     83:                return (ISC_FALSE);
                     84: 
                     85:        switch (a->family) {
                     86:        case AF_INET:
                     87:                pa = (const unsigned char *) &a->type.in;
                     88:                pb = (const unsigned char *) &b->type.in;
                     89:                ipabytes = 4;
                     90:                break;
                     91:        case AF_INET6:
                     92:                pa = (const unsigned char *) &a->type.in6;
                     93:                pb = (const unsigned char *) &b->type.in6;
                     94:                ipabytes = 16;
                     95:                break;
                     96:        default:
                     97:                pa = pb = NULL; /* Avoid silly compiler warning. */
                     98:                ipabytes = 0; /* Ditto. */
                     99:                return (ISC_FALSE);
                    100:        }
                    101: 
                    102:        /*
                    103:         * Don't crash if we get a pattern like 10.0.0.1/9999999.
                    104:         */
                    105:        if (prefixlen > ipabytes * 8)
                    106:                prefixlen = ipabytes * 8;
                    107: 
                    108:        nbytes = prefixlen / 8;
                    109:        nbits = prefixlen % 8;
                    110: 
                    111:        if (nbytes > 0) {
                    112:                if (memcmp(pa, pb, nbytes) != 0)
                    113:                        return (ISC_FALSE);
                    114:        }
                    115:        if (nbits > 0) {
                    116:                unsigned int bytea, byteb, mask;
                    117:                INSIST(nbytes < ipabytes);
                    118:                INSIST(nbits < 8);
                    119:                bytea = pa[nbytes];
                    120:                byteb = pb[nbytes];
                    121:                mask = (0xFF << (8-nbits)) & 0xFF;
                    122:                if ((bytea & mask) != (byteb & mask))
                    123:                        return (ISC_FALSE);
                    124:        }
                    125:        return (ISC_TRUE);
                    126: }
                    127: 
                    128: isc_result_t
                    129: isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) {
                    130:        char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
                    131:        char zbuf[sizeof("%4294967295")];
                    132:        unsigned int alen;
                    133:        int zlen;
                    134:        const char *r;
                    135:        const void *type;
                    136: 
                    137:        REQUIRE(netaddr != NULL);
                    138: 
                    139:        switch (netaddr->family) {
                    140:        case AF_INET:
                    141:                type = &netaddr->type.in;
                    142:                break;
                    143:        case AF_INET6:
                    144:                type = &netaddr->type.in6;
                    145:                break;
                    146: #ifdef ISC_PLATFORM_HAVESYSUNH
                    147:        case AF_UNIX:
                    148:                alen = strlen(netaddr->type.un);
                    149:                if (alen > isc_buffer_availablelength(target))
                    150:                        return (ISC_R_NOSPACE);
                    151:                isc_buffer_putmem(target,
                    152:                                  (const unsigned char *)(netaddr->type.un),
                    153:                                  alen);
                    154:                return (ISC_R_SUCCESS);
                    155: #endif
                    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:        alen = strlen(abuf);
                    164:        INSIST(alen < sizeof(abuf));
                    165: 
                    166:        zlen = 0;
                    167:        if (netaddr->family == AF_INET6 && netaddr->zone != 0) {
                    168:                zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone);
                    169:                if (zlen < 0)
                    170:                        return (ISC_R_FAILURE);
                    171:                INSIST((unsigned int)zlen < sizeof(zbuf));
                    172:        }
                    173: 
                    174:        if (alen + zlen > isc_buffer_availablelength(target))
                    175:                return (ISC_R_NOSPACE);
                    176: 
                    177:        isc_buffer_putmem(target, (unsigned char *)abuf, alen);
                    178:        isc_buffer_putmem(target, (unsigned char *)zbuf, zlen);
                    179: 
                    180:        return (ISC_R_SUCCESS);
                    181: }
                    182: 
                    183: void
                    184: isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) {
                    185:        isc_result_t result;
                    186:        isc_buffer_t buf;
                    187: 
                    188:        isc_buffer_init(&buf, array, size);
                    189:        result = isc_netaddr_totext(na, &buf);
                    190: 
                    191:        /*
                    192:         * Null terminate.
                    193:         */
                    194:        if (result == ISC_R_SUCCESS) {
                    195:                if (isc_buffer_availablelength(&buf) >= 1)
                    196:                        isc_buffer_putuint8(&buf, 0);
                    197:                else
                    198:                        result = ISC_R_NOSPACE;
                    199:        }
                    200: 
                    201:        if (result != ISC_R_SUCCESS) {
                    202:                snprintf(array, size,
                    203:                         isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
                    204:                                        ISC_MSG_UNKNOWNADDR,
                    205:                                        "<unknown address, family %u>"),
                    206:                         na->family);
                    207:                array[size - 1] = '\0';
                    208:        }
                    209: }
                    210: 
                    211: 
                    212: isc_result_t
                    213: isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
                    214:        static const unsigned char zeros[16] = { 0 };
                    215:        unsigned int nbits, nbytes, ipbytes;
                    216:        const unsigned char *p;
                    217: 
                    218:        switch (na->family) {
                    219:        case AF_INET:
                    220:                p = (const unsigned char *) &na->type.in;
                    221:                ipbytes = 4;
                    222:                if (prefixlen > 32)
                    223:                        return (ISC_R_RANGE);
                    224:                break;
                    225:        case AF_INET6:
                    226:                p = (const unsigned char *) &na->type.in6;
                    227:                ipbytes = 16;
                    228:                if (prefixlen > 128)
                    229:                        return (ISC_R_RANGE);
                    230:                break;
                    231:        default:
                    232:                ipbytes = 0;
                    233:                return (ISC_R_NOTIMPLEMENTED);
                    234:        }
                    235:        nbytes = prefixlen / 8;
                    236:        nbits = prefixlen % 8;
                    237:        if (nbits != 0) {
                    238:                if ((p[nbytes] & (0xff>>nbits)) != 0U)
                    239:                        return (ISC_R_FAILURE);
                    240:                nbytes++;
                    241:        }
                    242:        if (memcmp(p + nbytes, zeros, ipbytes - nbytes) != 0)
                    243:                return (ISC_R_FAILURE);
                    244:        return (ISC_R_SUCCESS);
                    245: }
                    246: 
                    247: isc_result_t
                    248: isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
                    249:        unsigned int nbits, nbytes, ipbytes, i;
                    250:        const unsigned char *p;
                    251: 
                    252:        switch (s->family) {
                    253:        case AF_INET:
                    254:                p = (const unsigned char *) &s->type.in;
                    255:                ipbytes = 4;
                    256:                break;
                    257:        case AF_INET6:
                    258:                p = (const unsigned char *) &s->type.in6;
                    259:                ipbytes = 16;
                    260:                break;
                    261:        default:
                    262:                ipbytes = 0;
                    263:                return (ISC_R_NOTIMPLEMENTED);
                    264:        }
                    265:        nbytes = nbits = 0;
                    266:        for (i = 0; i < ipbytes; i++) {
                    267:                if (p[i] != 0xFF)
                    268:                        break;
                    269:        }
                    270:        nbytes = i;
                    271:        if (i < ipbytes) {
                    272:                unsigned int c = p[nbytes];
                    273:                while ((c & 0x80) != 0 && nbits < 8) {
                    274:                        c <<= 1; nbits++;
                    275:                }
                    276:                if ((c & 0xFF) != 0)
                    277:                        return (ISC_R_MASKNONCONTIG);
                    278:                i++;
                    279:        }
                    280:        for (; i < ipbytes; i++) {
                    281:                if (p[i] != 0)
                    282:                        return (ISC_R_MASKNONCONTIG);
                    283:                i++;
                    284:        }
                    285:        *lenp = nbytes * 8 + nbits;
                    286:        return (ISC_R_SUCCESS);
                    287: }
                    288: 
                    289: void
                    290: isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) {
                    291:        memset(netaddr, 0, sizeof(*netaddr));
                    292:        netaddr->family = AF_INET;
                    293:        netaddr->type.in = *ina;
                    294: }
                    295: 
                    296: void
                    297: isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
                    298:        memset(netaddr, 0, sizeof(*netaddr));
                    299:        netaddr->family = AF_INET6;
                    300:        netaddr->type.in6 = *ina6;
                    301: }
                    302: 
                    303: isc_result_t
                    304: isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) {
                    305: #ifdef ISC_PLATFORM_HAVESYSUNH
                    306:         if (strlen(path) > sizeof(netaddr->type.un) - 1)
                    307:                 return (ISC_R_NOSPACE);
                    308: 
                    309:         memset(netaddr, 0, sizeof(*netaddr));
                    310:         netaddr->family = AF_UNIX;
                    311:         strcpy(netaddr->type.un, path);
                    312:         netaddr->zone = 0;
                    313:         return (ISC_R_SUCCESS);
                    314: #else 
                    315:        UNUSED(netaddr);
                    316:        UNUSED(path);
                    317:         return (ISC_R_NOTIMPLEMENTED);
                    318: #endif
                    319: }
                    320: 
                    321: 
                    322: void
                    323: isc_netaddr_setzone(isc_netaddr_t *netaddr, isc_uint32_t zone) {
                    324:        /* we currently only support AF_INET6. */
                    325:        REQUIRE(netaddr->family == AF_INET6);
                    326: 
                    327:        netaddr->zone = zone;
                    328: }
                    329: 
                    330: isc_uint32_t
                    331: isc_netaddr_getzone(const isc_netaddr_t *netaddr) {
                    332:        return (netaddr->zone);
                    333: }
                    334: 
                    335: void
                    336: isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) {
                    337:        int family = s->type.sa.sa_family;
                    338:        t->family = family;
                    339:        switch (family) {
                    340:        case AF_INET:
                    341:                t->type.in = s->type.sin.sin_addr;
                    342:                t->zone = 0;
                    343:                break;
                    344:        case AF_INET6:
                    345:                memcpy(&t->type.in6, &s->type.sin6.sin6_addr, 16);
                    346: #ifdef ISC_PLATFORM_HAVESCOPEID
                    347:                t->zone = s->type.sin6.sin6_scope_id;
                    348: #else
                    349:                t->zone = 0;
                    350: #endif
                    351:                break;
                    352: #ifdef ISC_PLATFORM_HAVESYSUNH
                    353:        case AF_UNIX:
                    354:                memcpy(t->type.un, s->type.sunix.sun_path, sizeof(t->type.un));
                    355:                t->zone = 0;
                    356:                break;
                    357: #endif
                    358:        default:
                    359:                INSIST(0);
                    360:        }
                    361: }
                    362: 
                    363: void
                    364: isc_netaddr_any(isc_netaddr_t *netaddr) {
                    365:        memset(netaddr, 0, sizeof(*netaddr));
                    366:        netaddr->family = AF_INET;
                    367:        netaddr->type.in.s_addr = INADDR_ANY;
                    368: }
                    369: 
                    370: void
                    371: isc_netaddr_any6(isc_netaddr_t *netaddr) {
                    372:        memset(netaddr, 0, sizeof(*netaddr));
                    373:        netaddr->family = AF_INET6;
                    374:        netaddr->type.in6 = in6addr_any;
                    375: }
                    376: 
                    377: isc_boolean_t
                    378: isc_netaddr_ismulticast(isc_netaddr_t *na) {
                    379:        switch (na->family) {
                    380:        case AF_INET:
                    381:                return (ISC_TF(ISC_IPADDR_ISMULTICAST(na->type.in.s_addr)));
                    382:        case AF_INET6:
                    383:                return (ISC_TF(IN6_IS_ADDR_MULTICAST(&na->type.in6)));
                    384:        default:
                    385:                return (ISC_FALSE);  /* XXXMLG ? */
                    386:        }
                    387: }
                    388: 
                    389: isc_boolean_t
                    390: isc_netaddr_isexperimental(isc_netaddr_t *na) {
                    391:        switch (na->family) {
                    392:        case AF_INET:
                    393:                return (ISC_TF(ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr)));
                    394:        default:
                    395:                return (ISC_FALSE);  /* XXXMLG ? */
                    396:        }
                    397: }
                    398: 
                    399: isc_boolean_t
                    400: isc_netaddr_islinklocal(isc_netaddr_t *na) {
                    401:        switch (na->family) {
                    402:        case AF_INET:
                    403:                return (ISC_FALSE);
                    404:        case AF_INET6:
                    405:                return (ISC_TF(IN6_IS_ADDR_LINKLOCAL(&na->type.in6)));
                    406:        default:
                    407:                return (ISC_FALSE);
                    408:        }
                    409: }
                    410: 
                    411: isc_boolean_t
                    412: isc_netaddr_issitelocal(isc_netaddr_t *na) {
                    413:        switch (na->family) {
                    414:        case AF_INET:
                    415:                return (ISC_FALSE);
                    416:        case AF_INET6:
                    417:                return (ISC_TF(IN6_IS_ADDR_SITELOCAL(&na->type.in6)));
                    418:        default:
                    419:                return (ISC_FALSE);
                    420:        }
                    421: }
                    422: 
                    423: void
                    424: isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) {
                    425:        isc_netaddr_t *src;
                    426: 
                    427:        DE_CONST(s, src);       /* Must come before IN6_IS_ADDR_V4MAPPED. */
                    428: 
                    429:        REQUIRE(s->family == AF_INET6);
                    430:        REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6));
                    431: 
                    432:        memset(t, 0, sizeof(*t));
                    433:        t->family = AF_INET;
                    434:        memcpy(&t->type.in, (char *)&src->type.in6 + 12, 4);
                    435:        return;
                    436: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>