Annotation of embedaddon/strongswan/src/libstrongswan/selectors/traffic_selector.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2007-2017 Tobias Brunner
                      3:  * Copyright (C) 2005-2007 Martin Willi
                      4:  * Copyright (C) 2005 Jan Hutter
                      5:  * HSR Hochschule fuer Technik Rapperswil
                      6:  *
                      7:  * This program is free software; you can redistribute it and/or modify it
                      8:  * under the terms of the GNU General Public License as published by the
                      9:  * Free Software Foundation; either version 2 of the License, or (at your
                     10:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     11:  *
                     12:  * This program is distributed in the hope that it will be useful, but
                     13:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     14:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     15:  * for more details.
                     16:  */
                     17: 
                     18: #include <string.h>
                     19: #include <stdio.h>
                     20: 
                     21: #include "traffic_selector.h"
                     22: 
                     23: #include <utils/debug.h>
                     24: #include <utils/utils.h>
                     25: #include <utils/identification.h>
                     26: #include <collections/linked_list.h>
                     27: 
                     28: #define IPV4_LEN       4
                     29: #define IPV6_LEN       16
                     30: #define TS_IP_LEN(this) ({ ((this)->type == TS_IPV4_ADDR_RANGE) ? IPV4_LEN : IPV6_LEN; })
                     31: 
                     32: #define NON_SUBNET_ADDRESS_RANGE       255
                     33: 
                     34: ENUM(ts_type_name, TS_IPV4_ADDR_RANGE, TS_IPV6_ADDR_RANGE,
                     35:        "TS_IPV4_ADDR_RANGE",
                     36:        "TS_IPV6_ADDR_RANGE",
                     37: );
                     38: 
                     39: typedef struct private_traffic_selector_t private_traffic_selector_t;
                     40: 
                     41: /**
                     42:  * Private data of an traffic_selector_t object
                     43:  */
                     44: struct private_traffic_selector_t {
                     45: 
                     46:        /**
                     47:         * Public part
                     48:         */
                     49:        traffic_selector_t public;
                     50: 
                     51:        /**
                     52:         * Type of address
                     53:         */
                     54:        ts_type_t type;
                     55: 
                     56:        /**
                     57:         * IP protocol (UDP, TCP, ICMP, ...)
                     58:         */
                     59:        uint8_t protocol;
                     60: 
                     61:        /**
                     62:         * narrow this traffic selector to hosts external ip
                     63:         * if set, from and to have no meaning until set_address() is called
                     64:         */
                     65:        bool dynamic;
                     66: 
                     67:        /**
                     68:         * subnet size in CIDR notation, 255 means a non-subnet address range
                     69:         */
                     70:        uint8_t netbits;
                     71: 
                     72:        /**
                     73:         * begin of address range, network order
                     74:         */
                     75:        char from[IPV6_LEN];
                     76: 
                     77:        /**
                     78:         * end of address range, network order
                     79:         */
                     80:        char to[IPV6_LEN];
                     81: 
                     82:        /**
                     83:         * begin of port range
                     84:         */
                     85:        uint16_t from_port;
                     86: 
                     87:        /**
                     88:         * end of port range
                     89:         */
                     90:        uint16_t to_port;
                     91: };
                     92: 
                     93: /**
                     94:  * calculate the "to"-address for the "from" address and a subnet size
                     95:  */
                     96: static void calc_range(private_traffic_selector_t *this, uint8_t netbits)
                     97: {
                     98:        size_t len;
                     99:        int bytes, bits;
                    100:        uint8_t mask;
                    101: 
                    102:        this->netbits = netbits;
                    103: 
                    104:        len   = TS_IP_LEN(this);
                    105:        bytes = (netbits + 7)/8;
                    106:        bits  = (bytes * 8) - netbits;
                    107:        mask  = bits ? (1 << bits) - 1 : 0;
                    108: 
                    109:        memcpy(this->to, this->from, bytes);
                    110:        memset(this->from + bytes, 0x00, len - bytes);
                    111:        memset(this->to   + bytes, 0xff, len - bytes);
                    112:        this->from[bytes-1] &= ~mask;
                    113:        this->to[bytes-1]   |=  mask;
                    114: }
                    115: 
                    116: /**
                    117:  * calculate the subnet size from the "to" and "from" addresses
                    118:  */
                    119: static uint8_t calc_netbits(private_traffic_selector_t *this)
                    120: {
                    121:        int byte, bit;
                    122:        uint8_t netbits;
                    123:        size_t size = TS_IP_LEN(this);
                    124:        bool prefix = TRUE;
                    125: 
                    126:        /* a perfect match results in a single address with a /32 or /128 netmask */
                    127:        netbits = (size * 8);
                    128:        this->netbits = netbits;
                    129: 
                    130:        /* go through all bits of the addresses, beginning in the front.
                    131:         * as long as they are equal, the subnet gets larger
                    132:         */
                    133:        for (byte = 0; byte < size; byte++)
                    134:        {
                    135:                for (bit = 7; bit >= 0; bit--)
                    136:                {
                    137:                        uint8_t bitmask = 1 << bit;
                    138: 
                    139:                        if (prefix)
                    140:                        {
                    141:                                if ((bitmask & this->from[byte]) != (bitmask & this->to[byte]))
                    142:                                {
                    143:                                        /* store the common prefix which might be a true subnet */
                    144:                                        netbits = (7 - bit) + (byte * 8);
                    145:                                        this->netbits = netbits;
                    146:                                        prefix = FALSE;
                    147:                                }
                    148:                        }
                    149:                        else
                    150:                        {
                    151:                                if ((bitmask & this->from[byte]) || !(bitmask & this->to[byte]))
                    152:                                {
                    153:                                        this->netbits = NON_SUBNET_ADDRESS_RANGE;
                    154:                                        return netbits;  /* return a pseudo subnet */
                    155: 
                    156:                                }
                    157:                        }
                    158:                }
                    159:        }
                    160:        return netbits;  /* return a true subnet */
                    161: }
                    162: 
                    163: /**
                    164:  * internal generic constructor
                    165:  */
                    166: static private_traffic_selector_t *traffic_selector_create(uint8_t protocol,
                    167:                                                ts_type_t type, uint16_t from_port, uint16_t to_port);
                    168: 
                    169: /**
                    170:  * Check if TS contains "opaque" ports
                    171:  */
                    172: static bool is_opaque(private_traffic_selector_t *this)
                    173: {
                    174:        return this->from_port == 0xffff && this->to_port == 0;
                    175: }
                    176: 
                    177: /**
                    178:  * Check if TS contains "any" ports
                    179:  */
                    180: static bool is_any(private_traffic_selector_t *this)
                    181: {
                    182:        return this->from_port == 0 && this->to_port == 0xffff;
                    183: }
                    184: 
                    185: /**
                    186:  * Print ICMP/ICMPv6 type and code
                    187:  */
                    188: static int print_icmp(printf_hook_data_t *data, uint16_t port)
                    189: {
                    190:        uint8_t type, code;
                    191: 
                    192:        type = traffic_selector_icmp_type(port);
                    193:        code = traffic_selector_icmp_code(port);
                    194:        if (code)
                    195:        {
                    196:                return print_in_hook(data, "%d(%d)", type, code);
                    197:        }
                    198:        return print_in_hook(data, "%d", type);
                    199: }
                    200: 
                    201: /**
                    202:  * Described in header.
                    203:  */
                    204: int traffic_selector_printf_hook(printf_hook_data_t *data,
                    205:                                                        printf_hook_spec_t *spec, const void *const *args)
                    206: {
                    207:        private_traffic_selector_t *this = *((private_traffic_selector_t**)(args[0]));
                    208:        linked_list_t *list = *((linked_list_t**)(args[0]));
                    209:        enumerator_t *enumerator;
                    210:        char from_str[INET6_ADDRSTRLEN] = "";
                    211:        char to_str[INET6_ADDRSTRLEN] = "";
                    212:        char *serv_proto = NULL, *sep = "";
                    213:        bool has_proto, has_ports;
                    214:        size_t written = 0, len;
                    215:        char from[IPV6_LEN], to[IPV6_LEN];
                    216: 
                    217:        if (this == NULL)
                    218:        {
                    219:                return print_in_hook(data, "(null)");
                    220:        }
                    221: 
                    222:        if (spec->hash)
                    223:        {
                    224:                enumerator = list->create_enumerator(list);
                    225:                while (enumerator->enumerate(enumerator, (void**)&this))
                    226:                {
                    227:                        written += print_in_hook(data, "%s%R", sep, this);
                    228:                        sep = " ";
                    229:                }
                    230:                enumerator->destroy(enumerator);
                    231:                return written;
                    232:        }
                    233: 
                    234:        len = TS_IP_LEN(this);
                    235:        memset(from, 0, len);
                    236:        memset(to, 0xFF, len);
                    237:        if (this->dynamic &&
                    238:                memeq(this->from, from, len) && memeq(this->to, to, len))
                    239:        {
                    240:                written += print_in_hook(data, "dynamic");
                    241:        }
                    242:        else
                    243:        {
                    244:                if (this->type == TS_IPV4_ADDR_RANGE)
                    245:                {
                    246:                        inet_ntop(AF_INET, &this->from, from_str, sizeof(from_str));
                    247:                }
                    248:                else
                    249:                {
                    250:                        inet_ntop(AF_INET6, &this->from, from_str, sizeof(from_str));
                    251:                }
                    252:                if (this->netbits == NON_SUBNET_ADDRESS_RANGE)
                    253:                {
                    254:                        if (this->type == TS_IPV4_ADDR_RANGE)
                    255:                        {
                    256:                                inet_ntop(AF_INET, &this->to, to_str, sizeof(to_str));
                    257:                        }
                    258:                        else
                    259:                        {
                    260:                                inet_ntop(AF_INET6, &this->to, to_str, sizeof(to_str));
                    261:                        }
                    262:                        written += print_in_hook(data, "%s..%s", from_str, to_str);
                    263:                }
                    264:                else
                    265:                {
                    266:                        written += print_in_hook(data, "%s/%d", from_str, this->netbits);
                    267:                }
                    268:        }
                    269: 
                    270:        /* check if we have protocol and/or port selectors */
                    271:        has_proto = this->protocol != 0;
                    272:        has_ports = !is_any(this);
                    273: 
                    274:        if (!has_proto && !has_ports)
                    275:        {
                    276:                return written;
                    277:        }
                    278: 
                    279:        written += print_in_hook(data, "[");
                    280: 
                    281:        /* build protocol string */
                    282:        if (has_proto)
                    283:        {
                    284:                struct protoent *proto = getprotobynumber(this->protocol);
                    285: 
                    286:                if (proto)
                    287:                {
                    288:                        written += print_in_hook(data, "%s", proto->p_name);
                    289:                        serv_proto = proto->p_name;
                    290:                }
                    291:                else
                    292:                {
                    293:                        written += print_in_hook(data, "%d", this->protocol);
                    294:                }
                    295:        }
                    296:        else
                    297:        {
                    298:                written += print_in_hook(data, "0");
                    299:        }
                    300: 
                    301:        /* build port string */
                    302:        if (has_ports)
                    303:        {
                    304:                written += print_in_hook(data, "/");
                    305: 
                    306:                if (this->from_port == this->to_port)
                    307:                {
                    308:                        struct servent *serv;
                    309: 
                    310:                        if (this->protocol == IPPROTO_ICMP ||
                    311:                                this->protocol == IPPROTO_ICMPV6)
                    312:                        {
                    313:                                written += print_icmp(data, this->from_port);
                    314:                        }
                    315:                        else
                    316:                        {
                    317:                                serv = getservbyport(htons(this->from_port), serv_proto);
                    318:                                if (serv)
                    319:                                {
                    320:                                        written += print_in_hook(data, "%s", serv->s_name);
                    321:                                }
                    322:                                else
                    323:                                {
                    324:                                        written += print_in_hook(data, "%d", this->from_port);
                    325:                                }
                    326:                        }
                    327:                }
                    328:                else if (is_opaque(this))
                    329:                {
                    330:                        written += print_in_hook(data, "OPAQUE");
                    331:                }
                    332:                else if (this->protocol == IPPROTO_ICMP ||
                    333:                                 this->protocol == IPPROTO_ICMPV6)
                    334:                {
                    335:                        written += print_icmp(data, this->from_port);
                    336:                        written += print_in_hook(data, "-");
                    337:                        written += print_icmp(data, this->to_port);
                    338:                }
                    339:                else
                    340:                {
                    341:                        written += print_in_hook(data, "%d-%d",
                    342:                                                                         this->from_port, this->to_port);
                    343:                }
                    344:        }
                    345: 
                    346:        written += print_in_hook(data, "]");
                    347: 
                    348:        return written;
                    349: }
                    350: 
                    351: METHOD(traffic_selector_t, get_subset, traffic_selector_t*,
                    352:        private_traffic_selector_t *this, traffic_selector_t *other_public)
                    353: {
                    354:        private_traffic_selector_t *other, *subset;
                    355:        uint16_t from_port, to_port;
                    356:        u_char *from, *to;
                    357:        uint8_t protocol;
                    358:        size_t size;
                    359: 
                    360:        other = (private_traffic_selector_t*)other_public;
                    361: 
                    362:        if (this->dynamic || other->dynamic)
                    363:        {       /* no set_address() applied, TS has no subset */
                    364:                return NULL;
                    365:        }
                    366: 
                    367:        if (this->type != other->type)
                    368:        {
                    369:                return NULL;
                    370:        }
                    371: 
                    372:        if (this->protocol != other->protocol &&
                    373:                this->protocol != 0 && other->protocol != 0)
                    374:        {
                    375:                return NULL;
                    376:        }
                    377:        /* select protocol, which is not zero */
                    378:        protocol = max(this->protocol, other->protocol);
                    379: 
                    380:        if ((is_opaque(this) && is_opaque(other)) ||
                    381:                (is_opaque(this) && is_any(other)) ||
                    382:                (is_opaque(other) && is_any(this)))
                    383:        {
                    384:                from_port = 0xffff;
                    385:                to_port = 0;
                    386:        }
                    387:        else
                    388:        {
                    389:                /* calculate the maximum port range allowed for both */
                    390:                from_port = max(this->from_port, other->from_port);
                    391:                to_port = min(this->to_port, other->to_port);
                    392:                if (from_port > to_port)
                    393:                {
                    394:                        return NULL;
                    395:                }
                    396:        }
                    397:        size = TS_IP_LEN(this);
                    398:        /* get higher from-address */
                    399:        if (memcmp(this->from, other->from, size) > 0)
                    400:        {
                    401:                from = this->from;
                    402:        }
                    403:        else
                    404:        {
                    405:                from = other->from;
                    406:        }
                    407:        /* get lower to-address */
                    408:        if (memcmp(this->to, other->to, size) > 0)
                    409:        {
                    410:                to = other->to;
                    411:        }
                    412:        else
                    413:        {
                    414:                to = this->to;
                    415:        }
                    416:        /* if "from" > "to", we don't have a match */
                    417:        if (memcmp(from, to, size) > 0)
                    418:        {
                    419:                return NULL;
                    420:        }
                    421: 
                    422:        /* we have a match in protocol, port, and address: return it... */
                    423:        subset = traffic_selector_create(protocol, this->type, from_port, to_port);
                    424:        memcpy(subset->from, from, size);
                    425:        memcpy(subset->to, to, size);
                    426:        calc_netbits(subset);
                    427: 
                    428:        return &subset->public;
                    429: }
                    430: 
                    431: METHOD(traffic_selector_t, equals, bool,
                    432:        private_traffic_selector_t *this, traffic_selector_t *other)
                    433: {
                    434:        return traffic_selector_cmp(&this->public, other, NULL) == 0;
                    435: }
                    436: 
                    437: METHOD(traffic_selector_t, get_from_address, chunk_t,
                    438:        private_traffic_selector_t *this)
                    439: {
                    440:        return chunk_create(this->from, TS_IP_LEN(this));
                    441: }
                    442: 
                    443: METHOD(traffic_selector_t, get_to_address, chunk_t,
                    444:        private_traffic_selector_t *this)
                    445: {
                    446:        return chunk_create(this->to, TS_IP_LEN(this));
                    447: }
                    448: 
                    449: METHOD(traffic_selector_t, get_from_port, uint16_t,
                    450:        private_traffic_selector_t *this)
                    451: {
                    452:        return this->from_port;
                    453: }
                    454: 
                    455: METHOD(traffic_selector_t, get_to_port, uint16_t,
                    456:        private_traffic_selector_t *this)
                    457: {
                    458:        return this->to_port;
                    459: }
                    460: 
                    461: METHOD(traffic_selector_t, get_type, ts_type_t,
                    462:        private_traffic_selector_t *this)
                    463: {
                    464:        return this->type;
                    465: }
                    466: 
                    467: METHOD(traffic_selector_t, get_protocol, uint8_t,
                    468:        private_traffic_selector_t *this)
                    469: {
                    470:        return this->protocol;
                    471: }
                    472: 
                    473: METHOD(traffic_selector_t, is_host, bool,
                    474:        private_traffic_selector_t *this, host_t *host)
                    475: {
                    476:        if (host)
                    477:        {
                    478:                chunk_t addr;
                    479:                int family = host->get_family(host);
                    480: 
                    481:                if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
                    482:                        (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
                    483:                {
                    484:                        addr = host->get_address(host);
                    485:                        if (memeq(addr.ptr, this->from, addr.len) &&
                    486:                                memeq(addr.ptr, this->to, addr.len))
                    487:                        {
                    488:                                return TRUE;
                    489:                        }
                    490:                }
                    491:        }
                    492:        else
                    493:        {
                    494:                size_t length = TS_IP_LEN(this);
                    495: 
                    496:                if (this->dynamic)
                    497:                {
                    498:                        return TRUE;
                    499:                }
                    500: 
                    501:                if (memeq(this->from, this->to, length))
                    502:                {
                    503:                        return TRUE;
                    504:                }
                    505:        }
                    506:        return FALSE;
                    507: }
                    508: 
                    509: METHOD(traffic_selector_t, is_dynamic, bool,
                    510:        private_traffic_selector_t *this)
                    511: {
                    512:        return this->dynamic;
                    513: }
                    514: 
                    515: METHOD(traffic_selector_t, set_address, void,
                    516:        private_traffic_selector_t *this, host_t *host)
                    517: {
                    518:        this->type = host->get_family(host) == AF_INET ? TS_IPV4_ADDR_RANGE
                    519:                                                                                                   : TS_IPV6_ADDR_RANGE;
                    520: 
                    521:        if (host->is_anyaddr(host))
                    522:        {
                    523:                memset(this->from, 0x00, sizeof(this->from));
                    524:                memset(this->to, 0xFF, sizeof(this->to));
                    525:                this->netbits = 0;
                    526:        }
                    527:        else
                    528:        {
                    529:                chunk_t from = host->get_address(host);
                    530:                memcpy(this->from, from.ptr, from.len);
                    531:                memcpy(this->to, from.ptr, from.len);
                    532:                this->netbits = from.len * 8;
                    533:        }
                    534:        this->dynamic = FALSE;
                    535: }
                    536: 
                    537: METHOD(traffic_selector_t, is_contained_in, bool,
                    538:        private_traffic_selector_t *this, traffic_selector_t *other)
                    539: {
                    540:        private_traffic_selector_t *subset;
                    541:        bool contained_in = FALSE;
                    542: 
                    543:        subset = (private_traffic_selector_t*)get_subset(this, other);
                    544: 
                    545:        if (subset)
                    546:        {
                    547:                if (equals(subset, &this->public))
                    548:                {
                    549:                        contained_in = TRUE;
                    550:                }
                    551:                free(subset);
                    552:        }
                    553:        return contained_in;
                    554: }
                    555: 
                    556: METHOD(traffic_selector_t, includes, bool,
                    557:        private_traffic_selector_t *this, host_t *host)
                    558: {
                    559:        chunk_t addr;
                    560:        int family = host->get_family(host);
                    561: 
                    562:        if ((family == AF_INET && this->type == TS_IPV4_ADDR_RANGE) ||
                    563:                (family == AF_INET6 && this->type == TS_IPV6_ADDR_RANGE))
                    564:        {
                    565:                addr = host->get_address(host);
                    566: 
                    567:                return memcmp(this->from, addr.ptr, addr.len) <= 0 &&
                    568:                                memcmp(this->to, addr.ptr, addr.len) >= 0;
                    569:        }
                    570: 
                    571:        return FALSE;
                    572: }
                    573: 
                    574: METHOD(traffic_selector_t, to_subnet, bool,
                    575:        private_traffic_selector_t *this, host_t **net, uint8_t *mask)
                    576: {
                    577:        /* there is no way to do this cleanly, as the address range may
                    578:         * be anything else but a subnet. We use from_addr as subnet
                    579:         * and try to calculate a usable subnet mask.
                    580:         */
                    581:        int family, non_zero_bytes;
                    582:        uint16_t port = 0;
                    583:        chunk_t net_chunk;
                    584: 
                    585:        *mask = (this->netbits == NON_SUBNET_ADDRESS_RANGE) ? calc_netbits(this)
                    586:                                                                                                                : this->netbits;
                    587: 
                    588:        switch (this->type)
                    589:        {
                    590:                case TS_IPV4_ADDR_RANGE:
                    591:                        family = AF_INET;
                    592:                        net_chunk.len = IPV4_LEN;
                    593:                        break;
                    594:                case TS_IPV6_ADDR_RANGE:
                    595:                        family = AF_INET6;
                    596:                        net_chunk.len = IPV6_LEN;
                    597:                        break;
                    598:                default:
                    599:                        /* unreachable */
                    600:                        return FALSE;
                    601:        }
                    602: 
                    603:        net_chunk.ptr = malloc(net_chunk.len);
                    604:        memset(net_chunk.ptr, 0x00, net_chunk.len);
                    605:        if (*mask)
                    606:        {
                    607:                non_zero_bytes = (*mask + 7) / 8;
                    608:                memcpy(net_chunk.ptr, this->from, non_zero_bytes);
                    609:                net_chunk.ptr[non_zero_bytes-1] &= 0xFF << (8 * non_zero_bytes - *mask);
                    610:        }
                    611: 
                    612:        if (this->to_port == this->from_port)
                    613:        {
                    614:                port = this->to_port;
                    615:        }
                    616: 
                    617:        *net = host_create_from_chunk(family, net_chunk, port);
                    618:        chunk_free(&net_chunk);
                    619: 
                    620:        return this->netbits != NON_SUBNET_ADDRESS_RANGE;
                    621: }
                    622: 
                    623: METHOD(traffic_selector_t, clone_, traffic_selector_t*,
                    624:        private_traffic_selector_t *this)
                    625: {
                    626:        private_traffic_selector_t *clone;
                    627:        size_t len = TS_IP_LEN(this);
                    628: 
                    629:        clone = traffic_selector_create(this->protocol, this->type,
                    630:                                                                        this->from_port, this->to_port);
                    631:        clone->netbits = this->netbits;
                    632:        clone->dynamic = this->dynamic;
                    633: 
                    634:        memcpy(clone->from, this->from, len);
                    635:        memcpy(clone->to, this->to, len);
                    636:        return &clone->public;
                    637: }
                    638: 
                    639: METHOD(traffic_selector_t, hash, u_int,
                    640:        private_traffic_selector_t *this, u_int hash)
                    641: {
                    642:        return chunk_hash_inc(get_from_address(this),
                    643:                        chunk_hash_inc(get_to_address(this),
                    644:                         chunk_hash_inc(chunk_from_thing(this->from_port),
                    645:                          chunk_hash_inc(chunk_from_thing(this->to_port),
                    646:                           chunk_hash_inc(chunk_from_thing(this->protocol),
                    647:                                hash)))));
                    648: }
                    649: 
                    650: METHOD(traffic_selector_t, destroy, void,
                    651:        private_traffic_selector_t *this)
                    652: {
                    653:        free(this);
                    654: }
                    655: 
                    656: /**
                    657:  * Compare two integers
                    658:  */
                    659: static int compare_int(int a, int b)
                    660: {
                    661:        return a - b;
                    662: }
                    663: 
                    664: /*
                    665:  * See header
                    666:  */
                    667: int traffic_selector_cmp(traffic_selector_t *a_pub, traffic_selector_t *b_pub,
                    668:                                                 void *opts)
                    669: {
                    670:        private_traffic_selector_t *a, *b;
                    671:        size_t len;
                    672:        int res;
                    673: 
                    674:        a = (private_traffic_selector_t*)a_pub;
                    675:        b = (private_traffic_selector_t*)b_pub;
                    676: 
                    677:        /* IPv4 before IPv6 */
                    678:        res = compare_int(a->type, b->type);
                    679:        if (res)
                    680:        {
                    681:                return res;
                    682:        }
                    683:        len = TS_IP_LEN(a);
                    684:        /* lower starting subnets first */
                    685:        res = memcmp(a->from, b->from, len);
                    686:        if (res)
                    687:        {
                    688:                return res;
                    689:        }
                    690:        /* larger subnets first */
                    691:        res = memcmp(b->to, a->to, len);
                    692:        if (res)
                    693:        {
                    694:                return res;
                    695:        }
                    696:        /* lower protocols first */
                    697:        res = compare_int(a->protocol, b->protocol);
                    698:        if (res)
                    699:        {
                    700:                return res;
                    701:        }
                    702:        /* lower starting ports first */
                    703:        res = compare_int(a->from_port, b->from_port);
                    704:        if (res)
                    705:        {
                    706:                return res;
                    707:        }
                    708:        /* larger port ranges first */
                    709:        return compare_int(b->to_port, a->to_port);
                    710: }
                    711: 
                    712: /*
                    713:  * see header
                    714:  */
                    715: traffic_selector_t *traffic_selector_create_from_bytes(uint8_t protocol,
                    716:                                                                                                ts_type_t type,
                    717:                                                                                                chunk_t from, uint16_t from_port,
                    718:                                                                                                chunk_t to, uint16_t to_port)
                    719: {
                    720:        private_traffic_selector_t *this = traffic_selector_create(protocol, type,
                    721:                                                                                                                        from_port, to_port);
                    722: 
                    723:        if (!this)
                    724:        {
                    725:                return NULL;
                    726:        }
                    727:        if (from.len != to.len || from.len != TS_IP_LEN(this))
                    728:        {
                    729:                free(this);
                    730:                return NULL;
                    731:        }
                    732:        memcpy(this->from, from.ptr, from.len);
                    733:        memcpy(this->to, to.ptr, to.len);
                    734:        calc_netbits(this);
                    735:        return &this->public;
                    736: }
                    737: 
                    738: /*
                    739:  * see header
                    740:  */
                    741: traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type,
                    742:                                                                                                chunk_t from, chunk_t to)
                    743: {
                    744:        private_traffic_selector_t *this = traffic_selector_create(0, type, 0, 65535);
                    745:        size_t len;
                    746: 
                    747:        if (!this)
                    748:        {
                    749:                return NULL;
                    750:        }
                    751:        len = TS_IP_LEN(this);
                    752: 
                    753:        memset(this->from, 0x00, len);
                    754:        memset(this->to  , 0xff, len);
                    755: 
                    756:        if (from.len > 1)
                    757:        {
                    758:                memcpy(this->from, from.ptr+1, from.len-1);
                    759:        }
                    760:        if (to.len > 1)
                    761:        {
                    762:                uint8_t mask = to.ptr[0] ? (1 << to.ptr[0]) - 1 : 0;
                    763: 
                    764:                memcpy(this->to, to.ptr+1, to.len-1);
                    765:                this->to[to.len-2] |= mask;
                    766:        }
                    767:        calc_netbits(this);
                    768:        return &this->public;
                    769: }
                    770: 
                    771: /*
                    772:  * see header
                    773:  */
                    774: traffic_selector_t *traffic_selector_create_from_subnet(host_t *net,
                    775:                                                        uint8_t netbits, uint8_t protocol,
                    776:                                                        uint16_t from_port, uint16_t to_port)
                    777: {
                    778:        private_traffic_selector_t *this;
                    779:        ts_type_t type;
                    780:        chunk_t from;
                    781: 
                    782:        switch (net->get_family(net))
                    783:        {
                    784:                case AF_INET:
                    785:                        type = TS_IPV4_ADDR_RANGE;
                    786:                        break;
                    787:                case AF_INET6:
                    788:                        type = TS_IPV6_ADDR_RANGE;
                    789:                        break;
                    790:                default:
                    791:                        net->destroy(net);
                    792:                        return NULL;
                    793:        }
                    794: 
                    795:        this = traffic_selector_create(protocol, type, from_port, to_port);
                    796: 
                    797:        from = net->get_address(net);
                    798:        memcpy(this->from, from.ptr, from.len);
                    799:        netbits = min(netbits, TS_IP_LEN(this) * 8);
                    800:        calc_range(this, netbits);
                    801:        net->destroy(net);
                    802:        return &this->public;
                    803: }
                    804: 
                    805: /*
                    806:  * see header
                    807:  */
                    808: traffic_selector_t *traffic_selector_create_from_string(
                    809:                                                                                uint8_t protocol, ts_type_t type,
                    810:                                                                                char *from_addr, uint16_t from_port,
                    811:                                                                                char *to_addr, uint16_t to_port)
                    812: {
                    813:        private_traffic_selector_t *this;
                    814:        int family;
                    815: 
                    816:        switch (type)
                    817:        {
                    818:                case TS_IPV4_ADDR_RANGE:
                    819:                        family = AF_INET;
                    820:                        break;
                    821:                case TS_IPV6_ADDR_RANGE:
                    822:                        family = AF_INET6;
                    823:                        break;
                    824:                default:
                    825:                        return NULL;
                    826:        }
                    827: 
                    828:        this = traffic_selector_create(protocol, type, from_port, to_port);
                    829: 
                    830:        if (inet_pton(family, from_addr, this->from) != 1 ||
                    831:                inet_pton(family, to_addr, this->to) != 1)
                    832:        {
                    833:                free(this);
                    834:                return NULL;
                    835:        }
                    836:        calc_netbits(this);
                    837:        return &this->public;
                    838: }
                    839: 
                    840: /*
                    841:  * see header
                    842:  */
                    843: traffic_selector_t *traffic_selector_create_from_cidr(
                    844:                                                                                char *string, uint8_t protocol,
                    845:                                                                                uint16_t from_port, uint16_t to_port)
                    846: {
                    847:        host_t *net;
                    848:        int bits;
                    849: 
                    850:        net = host_create_from_subnet(string, &bits);
                    851:        if (net)
                    852:        {
                    853:                return traffic_selector_create_from_subnet(net, bits, protocol,
                    854:                                                                                                   from_port, to_port);
                    855:        }
                    856:        return NULL;
                    857: }
                    858: 
                    859: /*
                    860:  * see header
                    861:  */
                    862: traffic_selector_t *traffic_selector_create_dynamic(uint8_t protocol,
                    863:                                                                        uint16_t from_port, uint16_t to_port)
                    864: {
                    865:        private_traffic_selector_t *this = traffic_selector_create(
                    866:                                                        protocol, TS_IPV4_ADDR_RANGE, from_port, to_port);
                    867: 
                    868:        memset(this->from, 0, sizeof(this->from));
                    869:        memset(this->to, 0xFF, sizeof(this->to));
                    870:        this->netbits = 0;
                    871:        this->dynamic = TRUE;
                    872: 
                    873:        return &this->public;
                    874: }
                    875: 
                    876: /*
                    877:  * see declaration
                    878:  */
                    879: static private_traffic_selector_t *traffic_selector_create(uint8_t protocol,
                    880:                                                ts_type_t type, uint16_t from_port, uint16_t to_port)
                    881: {
                    882:        private_traffic_selector_t *this;
                    883: 
                    884:        /* sanity check */
                    885:        if (type != TS_IPV4_ADDR_RANGE && type != TS_IPV6_ADDR_RANGE)
                    886:        {
                    887:                return NULL;
                    888:        }
                    889: 
                    890:        INIT(this,
                    891:                .public = {
                    892:                        .get_subset = _get_subset,
                    893:                        .equals = _equals,
                    894:                        .get_from_address = _get_from_address,
                    895:                        .get_to_address = _get_to_address,
                    896:                        .get_from_port = _get_from_port,
                    897:                        .get_to_port = _get_to_port,
                    898:                        .get_type = _get_type,
                    899:                        .get_protocol = _get_protocol,
                    900:                        .is_host = _is_host,
                    901:                        .is_dynamic = _is_dynamic,
                    902:                        .is_contained_in = _is_contained_in,
                    903:                        .includes = _includes,
                    904:                        .set_address = _set_address,
                    905:                        .to_subnet = _to_subnet,
                    906:                        .clone = _clone_,
                    907:                        .hash = _hash,
                    908:                        .destroy = _destroy,
                    909:                },
                    910:                .from_port = from_port,
                    911:                .to_port = to_port,
                    912:                .protocol = protocol,
                    913:                .type = type,
                    914:        );
                    915:        if (protocol == IPPROTO_ICMP || protocol == IPPROTO_ICMPV6)
                    916:        {
                    917:                this->from_port = from_port < 256 ? from_port << 8 : from_port;
                    918:                this->to_port = to_port < 256 ? to_port << 8 : to_port;
                    919:        }
                    920:        return this;
                    921: }

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