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

1.1       misho       1: /*
                      2:  * Copyright (C) 2004-2007  Internet Systems Consortium, Inc. ("ISC")
                      3:  * Copyright (C) 1999-2003  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: sockaddr.c,v 1.70 2007/06/19 23:47:17 tbox Exp $ */
                     19: 
                     20: /*! \file */
                     21: 
                     22: #include <config.h>
                     23: 
                     24: #include <stdio.h>
                     25: 
                     26: #include <isc/buffer.h>
                     27: #include <isc/hash.h>
                     28: #include <isc/msgs.h>
                     29: #include <isc/netaddr.h>
                     30: #include <isc/print.h>
                     31: #include <isc/region.h>
                     32: #include <isc/sockaddr.h>
                     33: #include <isc/string.h>
                     34: #include <isc/util.h>
                     35: 
                     36: isc_boolean_t
                     37: isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
                     38:        return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR|
                     39:                                           ISC_SOCKADDR_CMPPORT|
                     40:                                           ISC_SOCKADDR_CMPSCOPE));
                     41: }
                     42: 
                     43: isc_boolean_t
                     44: isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
                     45:        return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR|
                     46:                                           ISC_SOCKADDR_CMPSCOPE));
                     47: }
                     48: 
                     49: isc_boolean_t
                     50: isc_sockaddr_compare(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
                     51:                     unsigned int flags)
                     52: {
                     53:        REQUIRE(a != NULL && b != NULL);
                     54: 
                     55:        if (a->length != b->length)
                     56:                return (ISC_FALSE);
                     57: 
                     58:        /*
                     59:         * We don't just memcmp because the sin_zero field isn't always
                     60:         * zero.
                     61:         */
                     62: 
                     63:        if (a->type.sa.sa_family != b->type.sa.sa_family)
                     64:                return (ISC_FALSE);
                     65:        switch (a->type.sa.sa_family) {
                     66:        case AF_INET:
                     67:                if ((flags & ISC_SOCKADDR_CMPADDR) != 0 &&
                     68:                    memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr,
                     69:                           sizeof(a->type.sin.sin_addr)) != 0)
                     70:                        return (ISC_FALSE);
                     71:                if ((flags & ISC_SOCKADDR_CMPPORT) != 0 &&
                     72:                    a->type.sin.sin_port != b->type.sin.sin_port)
                     73:                        return (ISC_FALSE);
                     74:                break;
                     75:        case AF_INET6:
                     76:                if ((flags & ISC_SOCKADDR_CMPADDR) != 0 &&
                     77:                    memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr,
                     78:                           sizeof(a->type.sin6.sin6_addr)) != 0)
                     79:                        return (ISC_FALSE);
                     80: #ifdef ISC_PLATFORM_HAVESCOPEID
                     81:                /*
                     82:                 * If ISC_SOCKADDR_CMPSCOPEZERO is set then don't return
                     83:                 * ISC_FALSE if one of the scopes in zero.
                     84:                 */
                     85:                if ((flags & ISC_SOCKADDR_CMPSCOPE) != 0 &&
                     86:                    a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id &&
                     87:                    ((flags & ISC_SOCKADDR_CMPSCOPEZERO) == 0 ||
                     88:                      (a->type.sin6.sin6_scope_id != 0 &&
                     89:                       b->type.sin6.sin6_scope_id != 0)))
                     90:                        return (ISC_FALSE);
                     91: #endif
                     92:                if ((flags & ISC_SOCKADDR_CMPPORT) != 0 &&
                     93:                    a->type.sin6.sin6_port != b->type.sin6.sin6_port)
                     94:                        return (ISC_FALSE);
                     95:                break;
                     96:        default:
                     97:                if (memcmp(&a->type, &b->type, a->length) != 0)
                     98:                        return (ISC_FALSE);
                     99:        }
                    100:        return (ISC_TRUE);
                    101: }
                    102: 
                    103: isc_boolean_t
                    104: isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
                    105:                          unsigned int prefixlen)
                    106: {
                    107:        isc_netaddr_t na, nb;
                    108:        isc_netaddr_fromsockaddr(&na, a);
                    109:        isc_netaddr_fromsockaddr(&nb, b);
                    110:        return (isc_netaddr_eqprefix(&na, &nb, prefixlen));
                    111: }
                    112: 
                    113: isc_result_t
                    114: isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) {
                    115:        isc_result_t result;
                    116:        isc_netaddr_t netaddr;
                    117:        char pbuf[sizeof("65000")];
                    118:        unsigned int plen;
                    119:        isc_region_t avail;
                    120: 
                    121:        REQUIRE(sockaddr != NULL);
                    122: 
                    123:        /*
                    124:         * Do the port first, giving us the opportunity to check for
                    125:         * unsupported address families before calling
                    126:         * isc_netaddr_fromsockaddr().
                    127:         */
                    128:        switch (sockaddr->type.sa.sa_family) {
                    129:        case AF_INET:
                    130:                snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port));
                    131:                break;
                    132:        case AF_INET6:
                    133:                snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port));
                    134:                break;
                    135: #ifdef ISC_PLAFORM_HAVESYSUNH
                    136:        case AF_UNIX:
                    137:                plen = strlen(sockaddr->type.sunix.sun_path);
                    138:                if (plen >= isc_buffer_availablelength(target))
                    139:                        return (ISC_R_NOSPACE);
                    140: 
                    141:                isc_buffer_putmem(target, sockaddr->type.sunix.sun_path, plen);
                    142: 
                    143:                /*
                    144:                 * Null terminate after used region.
                    145:                 */
                    146:                isc_buffer_availableregion(target, &avail);
                    147:                INSIST(avail.length >= 1);
                    148:                avail.base[0] = '\0';
                    149: 
                    150:                return (ISC_R_SUCCESS);
                    151: #endif
                    152:        default:
                    153:                return (ISC_R_FAILURE);
                    154:        }
                    155: 
                    156:        plen = strlen(pbuf);
                    157:        INSIST(plen < sizeof(pbuf));
                    158: 
                    159:        isc_netaddr_fromsockaddr(&netaddr, sockaddr);
                    160:        result = isc_netaddr_totext(&netaddr, target);
                    161:        if (result != ISC_R_SUCCESS)
                    162:                return (result);
                    163: 
                    164:        if (1 + plen + 1 > isc_buffer_availablelength(target))
                    165:                return (ISC_R_NOSPACE);
                    166: 
                    167:        isc_buffer_putmem(target, (const unsigned char *)"#", 1);
                    168:        isc_buffer_putmem(target, (const unsigned char *)pbuf, plen);
                    169: 
                    170:        /*
                    171:         * Null terminate after used region.
                    172:         */
                    173:        isc_buffer_availableregion(target, &avail);
                    174:        INSIST(avail.length >= 1);
                    175:        avail.base[0] = '\0';
                    176: 
                    177:        return (ISC_R_SUCCESS);
                    178: }
                    179: 
                    180: void
                    181: isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) {
                    182:        isc_result_t result;
                    183:        isc_buffer_t buf;
                    184: 
                    185:        isc_buffer_init(&buf, array, size);
                    186:        result = isc_sockaddr_totext(sa, &buf);
                    187:        if (result != ISC_R_SUCCESS) {
                    188:                /*
                    189:                 * The message is the same as in netaddr.c.
                    190:                 */
                    191:                snprintf(array, size,
                    192:                         isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
                    193:                                        ISC_MSG_UNKNOWNADDR,
                    194:                                        "<unknown address, family %u>"),
                    195:                         sa->type.sa.sa_family);
                    196:                array[size - 1] = '\0';
                    197:        }
                    198: }
                    199: 
                    200: unsigned int
                    201: isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) {
                    202:        unsigned int length = 0;
                    203:        const unsigned char *s = NULL;
                    204:        unsigned int h = 0;
                    205:        unsigned int g;
                    206:        unsigned int p = 0;
                    207:        const struct in6_addr *in6;
                    208: 
                    209:        REQUIRE(sockaddr != NULL);
                    210: 
                    211:        switch (sockaddr->type.sa.sa_family) {
                    212:        case AF_INET:
                    213:                s = (const unsigned char *)&sockaddr->type.sin.sin_addr;
                    214:                p = ntohs(sockaddr->type.sin.sin_port);
                    215:                length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
                    216:                break;
                    217:        case AF_INET6:
                    218:                in6 = &sockaddr->type.sin6.sin6_addr;
                    219:                if (IN6_IS_ADDR_V4MAPPED(in6)) {
                    220:                        s = (const unsigned char *)&in6[12];
                    221:                        length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
                    222:                } else {
                    223:                        s = (const unsigned char *)in6;
                    224:                        length = sizeof(sockaddr->type.sin6.sin6_addr);
                    225:                }
                    226:                p = ntohs(sockaddr->type.sin6.sin6_port);
                    227:                break;
                    228:        default:
                    229:                UNEXPECTED_ERROR(__FILE__, __LINE__,
                    230:                                 isc_msgcat_get(isc_msgcat,
                    231:                                                ISC_MSGSET_SOCKADDR,
                    232:                                                ISC_MSG_UNKNOWNFAMILY,
                    233:                                                "unknown address family: %d"),
                    234:                                             (int)sockaddr->type.sa.sa_family);
                    235:                s = (const unsigned char *)&sockaddr->type;
                    236:                length = sockaddr->length;
                    237:                p = 0;
                    238:        }
                    239: 
                    240:        h = isc_hash_calc(s, length, ISC_TRUE);
                    241:        if (!address_only) {
                    242:                g = isc_hash_calc((const unsigned char *)&p, sizeof(p),
                    243:                                  ISC_TRUE);
                    244:                h = h ^ g; /* XXX: we should concatenate h and p first */
                    245:        }
                    246: 
                    247:        return (h);
                    248: }
                    249: 
                    250: void
                    251: isc_sockaddr_any(isc_sockaddr_t *sockaddr)
                    252: {
                    253:        memset(sockaddr, 0, sizeof(*sockaddr));
                    254:        sockaddr->type.sin.sin_family = AF_INET;
                    255: #ifdef ISC_PLATFORM_HAVESALEN
                    256:        sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
                    257: #endif
                    258:        sockaddr->type.sin.sin_addr.s_addr = INADDR_ANY;
                    259:        sockaddr->type.sin.sin_port = 0;
                    260:        sockaddr->length = sizeof(sockaddr->type.sin);
                    261:        ISC_LINK_INIT(sockaddr, link);
                    262: }
                    263: 
                    264: void
                    265: isc_sockaddr_any6(isc_sockaddr_t *sockaddr)
                    266: {
                    267:        memset(sockaddr, 0, sizeof(*sockaddr));
                    268:        sockaddr->type.sin6.sin6_family = AF_INET6;
                    269: #ifdef ISC_PLATFORM_HAVESALEN
                    270:        sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
                    271: #endif
                    272:        sockaddr->type.sin6.sin6_addr = in6addr_any;
                    273:        sockaddr->type.sin6.sin6_port = 0;
                    274:        sockaddr->length = sizeof(sockaddr->type.sin6);
                    275:        ISC_LINK_INIT(sockaddr, link);
                    276: }
                    277: 
                    278: void
                    279: isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
                    280:                    in_port_t port)
                    281: {
                    282:        memset(sockaddr, 0, sizeof(*sockaddr));
                    283:        sockaddr->type.sin.sin_family = AF_INET;
                    284: #ifdef ISC_PLATFORM_HAVESALEN
                    285:        sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
                    286: #endif
                    287:        sockaddr->type.sin.sin_addr = *ina;
                    288:        sockaddr->type.sin.sin_port = htons(port);
                    289:        sockaddr->length = sizeof(sockaddr->type.sin);
                    290:        ISC_LINK_INIT(sockaddr, link);
                    291: }
                    292: 
                    293: void
                    294: isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int pf) {
                    295:      switch (pf) {
                    296:      case AF_INET:
                    297:             isc_sockaddr_any(sockaddr);
                    298:             break;
                    299:      case AF_INET6:
                    300:             isc_sockaddr_any6(sockaddr);
                    301:             break;
                    302:      default:
                    303:             INSIST(0);
                    304:      }
                    305: }
                    306: 
                    307: void
                    308: isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6,
                    309:                     in_port_t port)
                    310: {
                    311:        memset(sockaddr, 0, sizeof(*sockaddr));
                    312:        sockaddr->type.sin6.sin6_family = AF_INET6;
                    313: #ifdef ISC_PLATFORM_HAVESALEN
                    314:        sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
                    315: #endif
                    316:        sockaddr->type.sin6.sin6_addr = *ina6;
                    317:        sockaddr->type.sin6.sin6_port = htons(port);
                    318:        sockaddr->length = sizeof(sockaddr->type.sin6);
                    319:        ISC_LINK_INIT(sockaddr, link);
                    320: }
                    321: 
                    322: void
                    323: isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
                    324:                      in_port_t port)
                    325: {
                    326:        memset(sockaddr, 0, sizeof(*sockaddr));
                    327:        sockaddr->type.sin6.sin6_family = AF_INET6;
                    328: #ifdef ISC_PLATFORM_HAVESALEN
                    329:        sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
                    330: #endif
                    331:        sockaddr->type.sin6.sin6_addr.s6_addr[10] = 0xff;
                    332:        sockaddr->type.sin6.sin6_addr.s6_addr[11] = 0xff;
                    333:        memcpy(&sockaddr->type.sin6.sin6_addr.s6_addr[12], ina, 4);
                    334:        sockaddr->type.sin6.sin6_port = htons(port);
                    335:        sockaddr->length = sizeof(sockaddr->type.sin6);
                    336:        ISC_LINK_INIT(sockaddr, link);
                    337: }
                    338: 
                    339: int
                    340: isc_sockaddr_pf(const isc_sockaddr_t *sockaddr) {
                    341: 
                    342:        /*
                    343:         * Get the protocol family of 'sockaddr'.
                    344:         */
                    345: 
                    346: #if (AF_INET == PF_INET && AF_INET6 == PF_INET6)
                    347:        /*
                    348:         * Assume that PF_xxx == AF_xxx for all AF and PF.
                    349:         */
                    350:        return (sockaddr->type.sa.sa_family);
                    351: #else
                    352:        switch (sockaddr->type.sa.sa_family) {
                    353:        case AF_INET:
                    354:                return (PF_INET);
                    355:        case AF_INET6:
                    356:                return (PF_INET6);
                    357:        default:
                    358:                FATAL_ERROR(__FILE__, __LINE__,
                    359:                            isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
                    360:                                           ISC_MSG_UNKNOWNFAMILY,
                    361:                                           "unknown address family: %d"),
                    362:                            (int)sockaddr->type.sa.sa_family);
                    363:        }
                    364: #endif
                    365: }
                    366: 
                    367: void
                    368: isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
                    369:                    in_port_t port)
                    370: {
                    371:        memset(sockaddr, 0, sizeof(*sockaddr));
                    372:        sockaddr->type.sin.sin_family = (short)na->family;
                    373:        switch (na->family) {
                    374:        case AF_INET:
                    375:                sockaddr->length = sizeof(sockaddr->type.sin);
                    376: #ifdef ISC_PLATFORM_HAVESALEN
                    377:                sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
                    378: #endif
                    379:                sockaddr->type.sin.sin_addr = na->type.in;
                    380:                sockaddr->type.sin.sin_port = htons(port);
                    381:                break;
                    382:        case AF_INET6:
                    383:                sockaddr->length = sizeof(sockaddr->type.sin6);
                    384: #ifdef ISC_PLATFORM_HAVESALEN
                    385:                sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
                    386: #endif
                    387:                memcpy(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16);
                    388: #ifdef ISC_PLATFORM_HAVESCOPEID
                    389:                sockaddr->type.sin6.sin6_scope_id = isc_netaddr_getzone(na);
                    390: #endif
                    391:                sockaddr->type.sin6.sin6_port = htons(port);
                    392:                break;
                    393:         default:
                    394:                 INSIST(0);
                    395:        }
                    396:        ISC_LINK_INIT(sockaddr, link);
                    397: }
                    398: 
                    399: void
                    400: isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) {
                    401:        switch (sockaddr->type.sa.sa_family) {
                    402:        case AF_INET:
                    403:                sockaddr->type.sin.sin_port = htons(port);
                    404:                break;
                    405:        case AF_INET6:
                    406:                sockaddr->type.sin6.sin6_port = htons(port);
                    407:                break;
                    408:        default:
                    409:                FATAL_ERROR(__FILE__, __LINE__,
                    410:                            isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
                    411:                                           ISC_MSG_UNKNOWNFAMILY,
                    412:                                           "unknown address family: %d"),
                    413:                            (int)sockaddr->type.sa.sa_family);
                    414:        }
                    415: }
                    416: 
                    417: in_port_t
                    418: isc_sockaddr_getport(const isc_sockaddr_t *sockaddr) {
                    419:        in_port_t port = 0;
                    420: 
                    421:        switch (sockaddr->type.sa.sa_family) {
                    422:        case AF_INET:
                    423:                port = ntohs(sockaddr->type.sin.sin_port);
                    424:                break;
                    425:        case AF_INET6:
                    426:                port = ntohs(sockaddr->type.sin6.sin6_port);
                    427:                break;
                    428:        default:
                    429:                FATAL_ERROR(__FILE__, __LINE__,
                    430:                            isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
                    431:                                           ISC_MSG_UNKNOWNFAMILY,
                    432:                                           "unknown address family: %d"),
                    433:                            (int)sockaddr->type.sa.sa_family);
                    434:        }
                    435: 
                    436:        return (port);
                    437: }
                    438: 
                    439: isc_boolean_t
                    440: isc_sockaddr_ismulticast(const isc_sockaddr_t *sockaddr) {
                    441:        isc_netaddr_t netaddr;
                    442: 
                    443:        if (sockaddr->type.sa.sa_family == AF_INET ||
                    444:            sockaddr->type.sa.sa_family == AF_INET6) {
                    445:                isc_netaddr_fromsockaddr(&netaddr, sockaddr);
                    446:                return (isc_netaddr_ismulticast(&netaddr));
                    447:        }
                    448:        return (ISC_FALSE);
                    449: }
                    450: 
                    451: isc_boolean_t
                    452: isc_sockaddr_isexperimental(const isc_sockaddr_t *sockaddr) {
                    453:        isc_netaddr_t netaddr;
                    454: 
                    455:        if (sockaddr->type.sa.sa_family == AF_INET) {
                    456:                isc_netaddr_fromsockaddr(&netaddr, sockaddr);
                    457:                return (isc_netaddr_isexperimental(&netaddr));
                    458:        }
                    459:        return (ISC_FALSE);
                    460: }
                    461: 
                    462: isc_boolean_t
                    463: isc_sockaddr_issitelocal(const isc_sockaddr_t *sockaddr) {
                    464:        isc_netaddr_t netaddr;
                    465: 
                    466:        if (sockaddr->type.sa.sa_family == AF_INET6) {
                    467:                isc_netaddr_fromsockaddr(&netaddr, sockaddr);
                    468:                return (isc_netaddr_issitelocal(&netaddr));
                    469:        }
                    470:        return (ISC_FALSE);
                    471: }
                    472: 
                    473: isc_boolean_t
                    474: isc_sockaddr_islinklocal(const isc_sockaddr_t *sockaddr) {
                    475:        isc_netaddr_t netaddr;
                    476: 
                    477:        if (sockaddr->type.sa.sa_family == AF_INET6) {
                    478:                isc_netaddr_fromsockaddr(&netaddr, sockaddr);
                    479:                return (isc_netaddr_islinklocal(&netaddr));
                    480:        }
                    481:        return (ISC_FALSE);
                    482: }
                    483: 
                    484: isc_result_t
                    485: isc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path) {
                    486: #ifdef ISC_PLATFORM_HAVESYSUNH
                    487:        if (strlen(path) >= sizeof(sockaddr->type.sunix.sun_path))
                    488:                return (ISC_R_NOSPACE);
                    489:        memset(sockaddr, 0, sizeof(*sockaddr));
                    490:        sockaddr->length = sizeof(sockaddr->type.sunix);
                    491:        sockaddr->type.sunix.sun_family = AF_UNIX;
                    492: #ifdef ISC_PLATFORM_HAVESALEN
                    493:        sockaddr->type.sunix.sun_len =
                    494:                        (unsigned char)sizeof(sockaddr->type.sunix);
                    495: #endif
                    496:        strcpy(sockaddr->type.sunix.sun_path, path);
                    497:        return (ISC_R_SUCCESS);
                    498: #else
                    499:        UNUSED(sockaddr);
                    500:        UNUSED(path);
                    501:        return (ISC_R_NOTIMPLEMENTED);
                    502: #endif
                    503: }

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