Annotation of embedaddon/strongswan/src/libstrongswan/networking/host.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2006-2014 Tobias Brunner
        !             3:  * Copyright (C) 2006 Daniel Roethlisberger
        !             4:  * Copyright (C) 2005-2006 Martin Willi
        !             5:  * Copyright (C) 2005 Jan Hutter
        !             6:  * HSR Hochschule fuer Technik Rapperswil
        !             7:  *
        !             8:  * This program is free software; you can redistribute it and/or modify it
        !             9:  * under the terms of the GNU General Public License as published by the
        !            10:  * Free Software Foundation; either version 2 of the License, or (at your
        !            11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            12:  *
        !            13:  * This program is distributed in the hope that it will be useful, but
        !            14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            16:  * for more details.
        !            17:  */
        !            18: 
        !            19: #include "host.h"
        !            20: 
        !            21: #include <utils/debug.h>
        !            22: #include <library.h>
        !            23: 
        !            24: #define IPV4_LEN        4
        !            25: #define IPV6_LEN       16
        !            26: 
        !            27: typedef struct private_host_t private_host_t;
        !            28: 
        !            29: /**
        !            30:  * Private Data of a host object.
        !            31:  */
        !            32: struct private_host_t {
        !            33:        /**
        !            34:         * Public data
        !            35:         */
        !            36:        host_t public;
        !            37: 
        !            38:        /**
        !            39:         * low-lewel structure, which stores the address
        !            40:         */
        !            41:        union {
        !            42:                /** generic type */
        !            43:                struct sockaddr address;
        !            44:                /** maximum sockaddr size */
        !            45:                struct sockaddr_storage address_max;
        !            46:                /** IPv4 address */
        !            47:                struct sockaddr_in address4;
        !            48:                /** IPv6 address */
        !            49:                struct sockaddr_in6 address6;
        !            50:        };
        !            51:        /**
        !            52:         * length of address structure
        !            53:         */
        !            54:        socklen_t socklen;
        !            55: };
        !            56: 
        !            57: /**
        !            58:  * Update the sockaddr internal sa_len option, if available
        !            59:  */
        !            60: static inline void update_sa_len(private_host_t *this)
        !            61: {
        !            62: #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
        !            63:        this->address.sa_len = this->socklen;
        !            64: #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
        !            65: }
        !            66: 
        !            67: METHOD(host_t, get_sockaddr, sockaddr_t*,
        !            68:        private_host_t *this)
        !            69: {
        !            70:        return &(this->address);
        !            71: }
        !            72: 
        !            73: METHOD(host_t, get_sockaddr_len, socklen_t*,
        !            74:        private_host_t *this)
        !            75: {
        !            76:        return &(this->socklen);
        !            77: }
        !            78: 
        !            79: METHOD(host_t, is_anyaddr, bool,
        !            80:        private_host_t *this)
        !            81: {
        !            82:        static const uint8_t zeroes[IPV6_LEN];
        !            83: 
        !            84:        switch (this->address.sa_family)
        !            85:        {
        !            86:                case AF_INET:
        !            87:                {
        !            88:                        return memeq(zeroes, &(this->address4.sin_addr.s_addr), IPV4_LEN);
        !            89:                }
        !            90:                case AF_INET6:
        !            91:                {
        !            92:                        return memeq(zeroes, &(this->address6.sin6_addr.s6_addr), IPV6_LEN);
        !            93:                }
        !            94:                default:
        !            95:                {
        !            96:                        return FALSE;
        !            97:                }
        !            98:        }
        !            99: }
        !           100: 
        !           101: /**
        !           102:  * Described in header.
        !           103:  */
        !           104: int host_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
        !           105:                                         const void *const *args)
        !           106: {
        !           107:        private_host_t *this = *((private_host_t**)(args[0]));
        !           108:        char buffer[INET6_ADDRSTRLEN + 16];
        !           109: 
        !           110:        if (this == NULL)
        !           111:        {
        !           112:                snprintf(buffer, sizeof(buffer), "(null)");
        !           113:        }
        !           114:        else if (is_anyaddr(this) && !spec->plus && !spec->hash)
        !           115:        {
        !           116:                snprintf(buffer, sizeof(buffer), "%%any%s",
        !           117:                                 this->address.sa_family == AF_INET6 ? "6" : "");
        !           118:        }
        !           119:        else
        !           120:        {
        !           121:                void *address;
        !           122:                uint16_t port;
        !           123:                int len;
        !           124: 
        !           125:                address = &this->address6.sin6_addr;
        !           126:                port = this->address6.sin6_port;
        !           127: 
        !           128:                switch (this->address.sa_family)
        !           129:                {
        !           130:                        case AF_INET:
        !           131:                                address = &this->address4.sin_addr;
        !           132:                                port = this->address4.sin_port;
        !           133:                                /* fall */
        !           134:                        case AF_INET6:
        !           135: 
        !           136:                                if (inet_ntop(this->address.sa_family, address,
        !           137:                                                          buffer, sizeof(buffer)) == NULL)
        !           138:                                {
        !           139:                                        snprintf(buffer, sizeof(buffer),
        !           140:                                                         "(address conversion failed)");
        !           141:                                }
        !           142:                                else if (spec->hash && port)
        !           143:                                {
        !           144:                                        len = strlen(buffer);
        !           145:                                        snprintf(buffer + len, sizeof(buffer) - len,
        !           146:                                                         "[%d]", ntohs(port));
        !           147:                                }
        !           148:                                break;
        !           149:                        default:
        !           150:                                snprintf(buffer, sizeof(buffer), "(family not supported)");
        !           151:                                break;
        !           152:                }
        !           153:        }
        !           154:        if (spec->minus)
        !           155:        {
        !           156:                return print_in_hook(data, "%-*s", spec->width, buffer);
        !           157:        }
        !           158:        return print_in_hook(data, "%*s", spec->width, buffer);
        !           159: }
        !           160: 
        !           161: METHOD(host_t, get_address, chunk_t,
        !           162:        private_host_t *this)
        !           163: {
        !           164:        chunk_t address = chunk_empty;
        !           165: 
        !           166:        switch (this->address.sa_family)
        !           167:        {
        !           168:                case AF_INET:
        !           169:                {
        !           170:                        address.ptr = (char*)&(this->address4.sin_addr.s_addr);
        !           171:                        address.len = IPV4_LEN;
        !           172:                        return address;
        !           173:                }
        !           174:                case AF_INET6:
        !           175:                {
        !           176:                        address.ptr = (char*)&(this->address6.sin6_addr.s6_addr);
        !           177:                        address.len = IPV6_LEN;
        !           178:                        return address;
        !           179:                }
        !           180:                default:
        !           181:                {
        !           182:                        /* return empty chunk */
        !           183:                        return address;
        !           184:                }
        !           185:        }
        !           186: }
        !           187: 
        !           188: METHOD(host_t, get_family, int,
        !           189:        private_host_t *this)
        !           190: {
        !           191:        return this->address.sa_family;
        !           192: }
        !           193: 
        !           194: METHOD(host_t, get_port, uint16_t,
        !           195:        private_host_t *this)
        !           196: {
        !           197:        switch (this->address.sa_family)
        !           198:        {
        !           199:                case AF_INET:
        !           200:                {
        !           201:                        return ntohs(this->address4.sin_port);
        !           202:                }
        !           203:                case AF_INET6:
        !           204:                {
        !           205:                        return ntohs(this->address6.sin6_port);
        !           206:                }
        !           207:                default:
        !           208:                {
        !           209:                        return 0;
        !           210:                }
        !           211:        }
        !           212: }
        !           213: 
        !           214: METHOD(host_t, set_port, void,
        !           215:        private_host_t *this, uint16_t port)
        !           216: {
        !           217:        switch (this->address.sa_family)
        !           218:        {
        !           219:                case AF_INET:
        !           220:                {
        !           221:                        this->address4.sin_port = htons(port);
        !           222:                        break;
        !           223:                }
        !           224:                case AF_INET6:
        !           225:                {
        !           226:                        this->address6.sin6_port = htons(port);
        !           227:                        break;
        !           228:                }
        !           229:                default:
        !           230:                {
        !           231:                        break;
        !           232:                }
        !           233:        }
        !           234: }
        !           235: 
        !           236: METHOD(host_t, clone_, host_t*,
        !           237:        private_host_t *this)
        !           238: {
        !           239:        private_host_t *new;
        !           240: 
        !           241:        new = malloc_thing(private_host_t);
        !           242:        memcpy(new, this, sizeof(private_host_t));
        !           243: 
        !           244:        return &new->public;
        !           245: }
        !           246: 
        !           247: /**
        !           248:  * Implements host_t.ip_equals
        !           249:  */
        !           250: static bool ip_equals(private_host_t *this, private_host_t *other)
        !           251: {
        !           252:        if (this->address.sa_family != other->address.sa_family)
        !           253:        {
        !           254:                /* 0.0.0.0 and 0::0 are equal */
        !           255:                return (is_anyaddr(this) && is_anyaddr(other));
        !           256:        }
        !           257: 
        !           258:        switch (this->address.sa_family)
        !           259:        {
        !           260:                case AF_INET:
        !           261:                {
        !           262:                        return memeq(&this->address4.sin_addr, &other->address4.sin_addr,
        !           263:                                                 sizeof(this->address4.sin_addr));
        !           264:                }
        !           265:                case AF_INET6:
        !           266:                {
        !           267:                        return memeq(&this->address6.sin6_addr, &other->address6.sin6_addr,
        !           268:                                                 sizeof(this->address6.sin6_addr));
        !           269:                }
        !           270:                default:
        !           271:                        break;
        !           272:        }
        !           273:        return FALSE;
        !           274: }
        !           275: 
        !           276: /**
        !           277:  * Implements host_t.equals
        !           278:  */
        !           279: static bool equals(private_host_t *this, private_host_t *other)
        !           280: {
        !           281:        if (!ip_equals(this, other))
        !           282:        {
        !           283:                return FALSE;
        !           284:        }
        !           285: 
        !           286:        switch (this->address.sa_family)
        !           287:        {
        !           288:                case AF_INET:
        !           289:                {
        !           290:                        return (this->address4.sin_port == other->address4.sin_port);
        !           291:                }
        !           292:                case AF_INET6:
        !           293:                {
        !           294:                        return (this->address6.sin6_port == other->address6.sin6_port);
        !           295:                }
        !           296:                default:
        !           297:                        break;
        !           298:        }
        !           299:        return FALSE;
        !           300: }
        !           301: 
        !           302: METHOD(host_t, destroy, void,
        !           303:        private_host_t *this)
        !           304: {
        !           305:        free(this);
        !           306: }
        !           307: 
        !           308: /**
        !           309:  * Creates an empty host_t object
        !           310:  */
        !           311: static private_host_t *host_create_empty(void)
        !           312: {
        !           313:        private_host_t *this;
        !           314: 
        !           315:        INIT(this,
        !           316:                .public = {
        !           317:                        .get_sockaddr = _get_sockaddr,
        !           318:                        .get_sockaddr_len = _get_sockaddr_len,
        !           319:                        .clone = _clone_,
        !           320:                        .get_family = _get_family,
        !           321:                        .get_address = _get_address,
        !           322:                        .get_port = _get_port,
        !           323:                        .set_port = _set_port,
        !           324:                        .ip_equals = (bool (*)(host_t *,host_t *))ip_equals,
        !           325:                        .equals = (bool (*)(host_t *,host_t *)) equals,
        !           326:                        .is_anyaddr = _is_anyaddr,
        !           327:                        .destroy = _destroy,
        !           328:                },
        !           329:        );
        !           330: 
        !           331:        return this;
        !           332: }
        !           333: 
        !           334: /*
        !           335:  * Create a %any host with port
        !           336:  */
        !           337: static host_t *host_create_any_port(int family, uint16_t port)
        !           338: {
        !           339:        host_t *this;
        !           340: 
        !           341:        this = host_create_any(family);
        !           342:        this->set_port(this, port);
        !           343:        return this;
        !           344: }
        !           345: 
        !           346: /*
        !           347:  * Described in header.
        !           348:  */
        !           349: host_t *host_create_from_string_and_family(char *string, int family,
        !           350:                                                                                   uint16_t port)
        !           351: {
        !           352:        union {
        !           353:                struct sockaddr_in v4;
        !           354:                struct sockaddr_in6 v6;
        !           355:        } addr;
        !           356: 
        !           357:        if (!string)
        !           358:        {
        !           359:                return NULL;
        !           360:        }
        !           361:        if (streq(string, "%any"))
        !           362:        {
        !           363:                return host_create_any_port(family ? family : AF_INET, port);
        !           364:        }
        !           365:        if (family == AF_UNSPEC || family == AF_INET)
        !           366:        {
        !           367:                if (streq(string, "%any4") || streq(string, "0.0.0.0"))
        !           368:                {
        !           369:                        return host_create_any_port(AF_INET, port);
        !           370:                }
        !           371:        }
        !           372:        if (family == AF_UNSPEC || family == AF_INET6)
        !           373:        {
        !           374:                if (streq(string, "%any6") || streq(string, "::"))
        !           375:                {
        !           376:                        return host_create_any_port(AF_INET6, port);
        !           377:                }
        !           378:        }
        !           379:        switch (family)
        !           380:        {
        !           381:                case AF_UNSPEC:
        !           382:                        if (strchr(string, '.'))
        !           383:                        {
        !           384:                                goto af_inet;
        !           385:                        }
        !           386:                        /* FALL */
        !           387:                case AF_INET6:
        !           388:                        memset(&addr.v6, 0, sizeof(addr.v6));
        !           389:                        if (inet_pton(AF_INET6, string, &addr.v6.sin6_addr) != 1)
        !           390:                        {
        !           391:                                return NULL;
        !           392:                        }
        !           393:                        addr.v6.sin6_port = htons(port);
        !           394:                        addr.v6.sin6_family = AF_INET6;
        !           395:                        return host_create_from_sockaddr((sockaddr_t*)&addr);
        !           396:                case AF_INET:
        !           397:                        if (strchr(string, ':'))
        !           398:                        {       /* do not try to convert v6 addresses for v4 family */
        !           399:                                return NULL;
        !           400:                        }
        !           401:                af_inet:
        !           402:                        memset(&addr.v4, 0, sizeof(addr.v4));
        !           403:                        if (inet_pton(AF_INET, string, &addr.v4.sin_addr) != 1)
        !           404:                        {
        !           405:                                return NULL;
        !           406:                        }
        !           407:                        addr.v4.sin_port = htons(port);
        !           408:                        addr.v4.sin_family = AF_INET;
        !           409:                        return host_create_from_sockaddr((sockaddr_t*)&addr);
        !           410:                default:
        !           411:                        return NULL;
        !           412:        }
        !           413: }
        !           414: 
        !           415: /*
        !           416:  * Described in header.
        !           417:  */
        !           418: host_t *host_create_from_string(char *string, uint16_t port)
        !           419: {
        !           420:        return host_create_from_string_and_family(string, AF_UNSPEC, port);
        !           421: }
        !           422: 
        !           423: /*
        !           424:  * Described in header.
        !           425:  */
        !           426: host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
        !           427: {
        !           428:        private_host_t *this = host_create_empty();
        !           429: 
        !           430:        switch (sockaddr->sa_family)
        !           431:        {
        !           432:                case AF_INET:
        !           433:                {
        !           434:                        memcpy(&this->address4, (struct sockaddr_in*)sockaddr,
        !           435:                                   sizeof(struct sockaddr_in));
        !           436:                        this->socklen = sizeof(struct sockaddr_in);
        !           437:                        update_sa_len(this);
        !           438:                        return &this->public;
        !           439:                }
        !           440:                case AF_INET6:
        !           441:                {
        !           442:                        memcpy(&this->address6, (struct sockaddr_in6*)sockaddr,
        !           443:                                   sizeof(struct sockaddr_in6));
        !           444:                        this->socklen = sizeof(struct sockaddr_in6);
        !           445:                        update_sa_len(this);
        !           446:                        return &this->public;
        !           447:                }
        !           448:                default:
        !           449:                        break;
        !           450:        }
        !           451:        free(this);
        !           452:        return NULL;
        !           453: }
        !           454: 
        !           455: /*
        !           456:  * Described in header.
        !           457:  */
        !           458: host_t *host_create_from_dns(char *string, int af, uint16_t port)
        !           459: {
        !           460:        host_t *this;
        !           461: 
        !           462:        this = host_create_from_string_and_family(string, af, port);
        !           463:        if (!this)
        !           464:        {
        !           465:                this = lib->hosts->resolve(lib->hosts, string, af);
        !           466:        }
        !           467:        if (this)
        !           468:        {
        !           469:                this->set_port(this, port);
        !           470:        }
        !           471:        return this;
        !           472: }
        !           473: 
        !           474: /*
        !           475:  * Described in header.
        !           476:  */
        !           477: host_t *host_create_from_chunk(int family, chunk_t address, uint16_t port)
        !           478: {
        !           479:        private_host_t *this;
        !           480: 
        !           481:        switch (family)
        !           482:        {
        !           483:                case AF_INET:
        !           484:                        if (address.len < IPV4_LEN)
        !           485:                        {
        !           486:                                return NULL;
        !           487:                        }
        !           488:                        address.len = IPV4_LEN;
        !           489:                        break;
        !           490:                case AF_INET6:
        !           491:                        if (address.len < IPV6_LEN)
        !           492:                        {
        !           493:                                return NULL;
        !           494:                        }
        !           495:                        address.len = IPV6_LEN;
        !           496:                        break;
        !           497:                case AF_UNSPEC:
        !           498:                        switch (address.len)
        !           499:                        {
        !           500:                                case IPV4_LEN:
        !           501:                                        family = AF_INET;
        !           502:                                        break;
        !           503:                                case IPV6_LEN:
        !           504:                                        family = AF_INET6;
        !           505:                                        break;
        !           506:                                default:
        !           507:                                        return NULL;
        !           508:                        }
        !           509:                        break;
        !           510:                default:
        !           511:                        return NULL;
        !           512:        }
        !           513:        this = host_create_empty();
        !           514:        this->address.sa_family = family;
        !           515:        switch (family)
        !           516:        {
        !           517:                case AF_INET:
        !           518:                        memcpy(&this->address4.sin_addr.s_addr, address.ptr, address.len);
        !           519:                        this->address4.sin_port = htons(port);
        !           520:                        this->socklen = sizeof(struct sockaddr_in);
        !           521:                        break;
        !           522:                case AF_INET6:
        !           523:                        memcpy(&this->address6.sin6_addr.s6_addr, address.ptr, address.len);
        !           524:                        this->address6.sin6_port = htons(port);
        !           525:                        this->socklen = sizeof(struct sockaddr_in6);
        !           526:                        break;
        !           527:        }
        !           528:        update_sa_len(this);
        !           529:        return &this->public;
        !           530: }
        !           531: 
        !           532: /*
        !           533:  * Described in header.
        !           534:  */
        !           535: bool host_create_from_range(char *string, host_t **from, host_t **to)
        !           536: {
        !           537:        char *sep, *pos;
        !           538: 
        !           539:        sep = strchr(string, '-');
        !           540:        if (!sep)
        !           541:        {
        !           542:                return FALSE;
        !           543:        }
        !           544:        for (pos = sep+1; *pos && *pos == ' '; pos++)
        !           545:        {
        !           546:                /* trim spaces before to address*/
        !           547:        }
        !           548:        *to = host_create_from_string(pos, 0);
        !           549:        if (!*to)
        !           550:        {
        !           551:                return FALSE;
        !           552:        }
        !           553:        for (pos = sep-1; pos > string && *pos == ' '; pos--)
        !           554:        {
        !           555:                /* trim spaces behind from address */
        !           556:        }
        !           557:        pos = strndup(string, pos - string + 1);
        !           558:        *from = host_create_from_string_and_family(pos, (*to)->get_family(*to), 0);
        !           559:        free(pos);
        !           560:        if (!*from)
        !           561:        {
        !           562:                (*to)->destroy(*to);
        !           563:                return FALSE;
        !           564:        }
        !           565:        return TRUE;
        !           566: }
        !           567: 
        !           568: /*
        !           569:  * Described in header.
        !           570:  */
        !           571: host_t *host_create_from_subnet(char *string, int *bits)
        !           572: {
        !           573:        char *pos, buf[64];
        !           574:        host_t *net;
        !           575: 
        !           576:        pos = strchr(string, '/');
        !           577:        if (pos)
        !           578:        {
        !           579:                if (pos - string >= sizeof(buf))
        !           580:                {
        !           581:                        return NULL;
        !           582:                }
        !           583:                strncpy(buf, string, pos - string);
        !           584:                buf[pos - string] = '\0';
        !           585:                *bits = atoi(pos + 1);
        !           586:                return host_create_from_string(buf, 0);
        !           587:        }
        !           588:        net = host_create_from_string(string, 0);
        !           589:        if (net)
        !           590:        {
        !           591:                if (net->get_family(net) == AF_INET)
        !           592:                {
        !           593:                        *bits = 32;
        !           594:                }
        !           595:                else
        !           596:                {
        !           597:                        *bits = 128;
        !           598:                }
        !           599:        }
        !           600:        return net;
        !           601: }
        !           602: 
        !           603: /*
        !           604:  * See header.
        !           605:  */
        !           606: host_t *host_create_netmask(int family, int netbits)
        !           607: {
        !           608:        private_host_t *this;
        !           609:        int bits, bytes, len = 0;
        !           610:        char *target;
        !           611: 
        !           612:        switch (family)
        !           613:        {
        !           614:                case AF_INET:
        !           615:                        if (netbits < 0 || netbits > 32)
        !           616:                        {
        !           617:                                return NULL;
        !           618:                        }
        !           619:                        this = host_create_empty();
        !           620:                        this->socklen = sizeof(struct sockaddr_in);
        !           621:                        target = (char*)&this->address4.sin_addr;
        !           622:                        len = 4;
        !           623:                        break;
        !           624:                case AF_INET6:
        !           625:                        if (netbits < 0 || netbits > 128)
        !           626:                        {
        !           627:                                return NULL;
        !           628:                        }
        !           629:                        this = host_create_empty();
        !           630:                        this->socklen = sizeof(struct sockaddr_in6);
        !           631:                        target = (char*)&this->address6.sin6_addr;
        !           632:                        len = 16;
        !           633:                        break;
        !           634:                default:
        !           635:                        return NULL;
        !           636:        }
        !           637: 
        !           638:        memset(&this->address_max, 0, sizeof(struct sockaddr_storage));
        !           639:        this->address.sa_family = family;
        !           640:        update_sa_len(this);
        !           641: 
        !           642:        bytes = netbits / 8;
        !           643:        bits = 8 - (netbits & 0x07);
        !           644: 
        !           645:        memset(target, 0xff, bytes);
        !           646:        if (bytes < len)
        !           647:        {
        !           648:                memset(target + bytes, 0x00, len - bytes);
        !           649:                target[bytes] = (uint8_t)(0xff << bits);
        !           650:        }
        !           651:        return &this->public;
        !           652: }
        !           653: 
        !           654: /*
        !           655:  * Described in header.
        !           656:  */
        !           657: host_t *host_create_any(int family)
        !           658: {
        !           659:        private_host_t *this = host_create_empty();
        !           660: 
        !           661:        memset(&this->address_max, 0, sizeof(struct sockaddr_storage));
        !           662:        this->address.sa_family = family;
        !           663: 
        !           664:        switch (family)
        !           665:        {
        !           666:                case AF_INET:
        !           667:                {
        !           668:                        this->socklen = sizeof(struct sockaddr_in);
        !           669:                        update_sa_len(this);
        !           670:                        return &(this->public);
        !           671:                }
        !           672:                case AF_INET6:
        !           673:                {
        !           674:                        this->socklen = sizeof(struct sockaddr_in6);
        !           675:                        update_sa_len(this);
        !           676:                        return &this->public;
        !           677:                }
        !           678:                default:
        !           679:                        break;
        !           680:        }
        !           681:        free(this);
        !           682:        return NULL;
        !           683: }

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