Annotation of embedaddon/ntp/lib/isc/netaddr.c, revision 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>