Annotation of embedaddon/strongswan/src/libcharon/encoding/payloads/endpoint_notify.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2007 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "endpoint_notify.h"
                     17: 
                     18: #include <math.h>
                     19: 
                     20: #include <daemon.h>
                     21: 
                     22: typedef struct private_endpoint_notify_t private_endpoint_notify_t;
                     23: 
                     24: /**
                     25:  * Private data of an notify_payload_t object.
                     26:  */
                     27: struct private_endpoint_notify_t {
                     28:        /**
                     29:         * Public endpoint_notify_t interface.
                     30:         */
                     31:        endpoint_notify_t public;
                     32: 
                     33:        /**
                     34:         * Priority
                     35:         */
                     36:        uint32_t priority;
                     37: 
                     38:        /**
                     39:         * Family
                     40:         */
                     41:        me_endpoint_family_t family;
                     42: 
                     43:        /**
                     44:         * Endpoint type
                     45:         */
                     46:        me_endpoint_type_t type;
                     47: 
                     48:        /**
                     49:         * Endpoint
                     50:         */
                     51:        host_t *endpoint;
                     52: 
                     53:        /**
                     54:         * Base (used for server reflexive endpoints)
                     55:         */
                     56:        host_t *base;
                     57: };
                     58: 
                     59: /*    Notification data:
                     60:                            1                   2                   3
                     61:        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
                     62:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     63:       !                           Priority                            !
                     64:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     65:       !     Family    !      Type     !              Port             !
                     66:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     67:       !                       IP Address (variable)                   !
                     68:       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                     69: */
                     70: 
                     71: ENUM(me_endpoint_type_names, HOST, RELAYED,
                     72:        "HOST",
                     73:        "PEER_REFLEXIVE",
                     74:        "SERVER_REFLEXIVE",
                     75:        "RELAYED"
                     76: );
                     77: 
                     78: /**
                     79:  * Forward declaration
                     80:  */
                     81: static private_endpoint_notify_t *endpoint_notify_create();
                     82: 
                     83: /**
                     84:  * Helper functions to parse integer values
                     85:  */
                     86: static status_t parse_uint8(uint8_t **cur, uint8_t *top, uint8_t *val)
                     87: {
                     88:        if (*cur + sizeof(uint8_t) > top)
                     89:        {
                     90:                return FAILED;
                     91:        }
                     92:        *val =  *(uint8_t*)*cur;
                     93:        *cur += sizeof(uint8_t);
                     94:        return SUCCESS;
                     95: }
                     96: 
                     97: static status_t parse_uint16(uint8_t **cur, uint8_t *top, uint16_t *val)
                     98: {
                     99:        if (*cur + sizeof(uint16_t) > top)
                    100:        {
                    101:                return FAILED;
                    102:        }
                    103:        *val =  ntohs(*(uint16_t*)*cur);
                    104:        *cur += sizeof(uint16_t);
                    105:        return SUCCESS;
                    106: }
                    107: 
                    108: static status_t parse_uint32(uint8_t **cur, uint8_t *top, uint32_t *val)
                    109: {
                    110:        if (*cur + sizeof(uint32_t) > top)
                    111:        {
                    112:                return FAILED;
                    113:        }
                    114:        *val =  ntohl(*(uint32_t*)*cur);
                    115:        *cur += sizeof(uint32_t);
                    116:        return SUCCESS;
                    117: }
                    118: 
                    119: /**
                    120:  * Parses the notification data of a ME_ENDPOINT notify
                    121:  */
                    122: static status_t parse_notification_data(private_endpoint_notify_t *this, chunk_t data)
                    123: {
                    124:        uint8_t family, type, addr_family;
                    125:        uint16_t port;
                    126:        chunk_t addr;
                    127:        uint8_t *cur = data.ptr;
                    128:        uint8_t *top = data.ptr + data.len;
                    129: 
                    130:        DBG3(DBG_IKE, "me_endpoint_data %B", &data);
                    131: 
                    132:        if (parse_uint32(&cur, top, &this->priority) != SUCCESS)
                    133:        {
                    134:                DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid priority");
                    135:                return FAILED;
                    136:        }
                    137: 
                    138:        if (parse_uint8(&cur, top, &family) != SUCCESS || family >= MAX_FAMILY)
                    139:        {
                    140:                DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid family");
                    141:                return FAILED;
                    142:        }
                    143:        this->family = (me_endpoint_family_t)family;
                    144: 
                    145:        if (parse_uint8(&cur, top, &type) != SUCCESS ||
                    146:                type == NO_TYPE || type >= MAX_TYPE)
                    147:        {
                    148:                DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid type");
                    149:                return FAILED;
                    150:        }
                    151:        this->type = (me_endpoint_type_t)type;
                    152: 
                    153:        addr_family = AF_INET;
                    154:        addr.len = 4;
                    155: 
                    156:        switch(this->family)
                    157:        {
                    158:                case IPv6:
                    159:                        addr_family = AF_INET6;
                    160:                        addr.len = 16;
                    161:                        /* fall-through */
                    162:                case IPv4:
                    163:                        if (parse_uint16(&cur, top, &port) != SUCCESS)
                    164:                        {
                    165:                                DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid port");
                    166:                                return FAILED;
                    167:                        }
                    168: 
                    169:                        if (cur + addr.len > top)
                    170:                        {
                    171:                                DBG1(DBG_IKE, "failed to parse ME_ENDPOINT: invalid IP address");
                    172:                                return FAILED;
                    173:                        }
                    174: 
                    175:                        addr.ptr = cur;
                    176:                        this->endpoint = host_create_from_chunk(addr_family, addr, port);
                    177:                        break;
                    178:                case NO_FAMILY:
                    179:                default:
                    180:                        this->endpoint = NULL;
                    181:                        break;
                    182:        }
                    183:        return SUCCESS;
                    184: }
                    185: 
                    186: 
                    187: /**
                    188:  * Generates the notification data of a ME_ENDPOINT notify
                    189:  */
                    190: static chunk_t build_notification_data(private_endpoint_notify_t *this)
                    191: {
                    192:        chunk_t prio_chunk, family_chunk, type_chunk, port_chunk, addr_chunk;
                    193:        chunk_t data;
                    194:        uint32_t prio;
                    195:        uint16_t port;
                    196:        uint8_t family, type;
                    197: 
                    198:        prio = htonl(this->priority);
                    199:        prio_chunk = chunk_from_thing(prio);
                    200:        family = this->family;
                    201:        family_chunk = chunk_from_thing(family);
                    202:        type = this->type;
                    203:        type_chunk = chunk_from_thing(type);
                    204: 
                    205:        if (this->endpoint)
                    206:        {
                    207:                port = htons(this->endpoint->get_port(this->endpoint));
                    208:                addr_chunk = this->endpoint->get_address(this->endpoint);
                    209:        }
                    210:        else
                    211:        {
                    212:                port = 0;
                    213:                addr_chunk = chunk_empty;
                    214:        }
                    215:        port_chunk = chunk_from_thing(port);
                    216: 
                    217:        /* data = prio | family | type | port | addr */
                    218:        data = chunk_cat("ccccc", prio_chunk, family_chunk, type_chunk,
                    219:                                         port_chunk, addr_chunk);
                    220:        DBG3(DBG_IKE, "me_endpoint_data %B", &data);
                    221:        return data;
                    222: }
                    223: 
                    224: METHOD(endpoint_notify_t, build_notify, notify_payload_t*,
                    225:        private_endpoint_notify_t *this)
                    226: {
                    227:        chunk_t data;
                    228:        notify_payload_t *notify;
                    229: 
                    230:        notify = notify_payload_create(PLV2_NOTIFY);
                    231:        notify->set_notify_type(notify, ME_ENDPOINT);
                    232:        data = build_notification_data(this);
                    233:        notify->set_notification_data(notify, data);
                    234:        chunk_free(&data);
                    235: 
                    236:        return notify;
                    237: }
                    238: 
                    239: 
                    240: METHOD(endpoint_notify_t, get_priority, uint32_t,
                    241:        private_endpoint_notify_t *this)
                    242: {
                    243:        return this->priority;
                    244: }
                    245: 
                    246: METHOD(endpoint_notify_t, set_priority, void,
                    247:        private_endpoint_notify_t *this, uint32_t priority)
                    248: {
                    249:        this->priority = priority;
                    250: }
                    251: 
                    252: METHOD(endpoint_notify_t, get_type,  me_endpoint_type_t,
                    253:        private_endpoint_notify_t *this)
                    254: {
                    255:        return this->type;
                    256: }
                    257: 
                    258: METHOD(endpoint_notify_t, get_family, me_endpoint_family_t,
                    259:        private_endpoint_notify_t *this)
                    260: {
                    261:        return this->family;
                    262: }
                    263: 
                    264: METHOD(endpoint_notify_t, get_host, host_t*,
                    265:        private_endpoint_notify_t *this)
                    266: {
                    267:        return this->endpoint;
                    268: }
                    269: 
                    270: METHOD(endpoint_notify_t, get_base, host_t*,
                    271:        private_endpoint_notify_t *this)
                    272: {
                    273:        return (!this->base) ? this->endpoint : this->base;
                    274: }
                    275: 
                    276: METHOD(endpoint_notify_t, clone_, endpoint_notify_t*,
                    277:        private_endpoint_notify_t *this)
                    278: {
                    279:        private_endpoint_notify_t *clone;
                    280: 
                    281:        clone = endpoint_notify_create();
                    282:        clone->priority = this->priority;
                    283:        clone->type = this->type;
                    284:        clone->family = this->family;
                    285: 
                    286:        if (this->endpoint)
                    287:        {
                    288:                clone->endpoint = this->endpoint->clone(this->endpoint);
                    289:        }
                    290: 
                    291:        if (this->base)
                    292:        {
                    293:                clone->base = this->base->clone(this->base);
                    294:        }
                    295: 
                    296:        return &clone->public;
                    297: }
                    298: 
                    299: METHOD(endpoint_notify_t, destroy, void,
                    300:        private_endpoint_notify_t *this)
                    301: {
                    302:        DESTROY_IF(this->endpoint);
                    303:        DESTROY_IF(this->base);
                    304:        free(this);
                    305: }
                    306: 
                    307: /**
                    308:  * Creates an empty endpoint notify
                    309:  */
                    310: static private_endpoint_notify_t *endpoint_notify_create()
                    311: {
                    312:        private_endpoint_notify_t *this;
                    313: 
                    314:        INIT(this,
                    315:                .public = {
                    316:                        .get_priority = _get_priority,
                    317:                        .set_priority = _set_priority,
                    318:                        .get_type = _get_type,
                    319:                        .get_family = _get_family,
                    320:                        .get_host = _get_host,
                    321:                        .get_base = _get_base,
                    322:                        .build_notify = _build_notify,
                    323:                        .clone = _clone_,
                    324:                        .destroy = _destroy,
                    325:                },
                    326:                .family = NO_FAMILY,
                    327:                .type = NO_TYPE,
                    328:        );
                    329: 
                    330:        return this;
                    331: }
                    332: 
                    333: /**
                    334:  * Described in header
                    335:  */
                    336: endpoint_notify_t *endpoint_notify_create_from_host(me_endpoint_type_t type,
                    337:                                                                                                        host_t *host, host_t *base)
                    338: {
                    339:        private_endpoint_notify_t *this = endpoint_notify_create();
                    340:        this->type = type;
                    341: 
                    342:        switch(type)
                    343:        {
                    344:                case HOST:
                    345:                        this->priority = pow(2, 16) * ME_PRIO_HOST;
                    346:                        break;
                    347:                case PEER_REFLEXIVE:
                    348:                        this->priority = pow(2, 16) * ME_PRIO_PEER;
                    349:                        break;
                    350:                case SERVER_REFLEXIVE:
                    351:                        this->priority = pow(2, 16) * ME_PRIO_SERVER;
                    352:                        break;
                    353:                case RELAYED:
                    354:                default:
                    355:                        this->priority = pow(2, 16) * ME_PRIO_RELAY;
                    356:                        break;
                    357:        }
                    358: 
                    359:        /* FIXME: if there is more than one ip address we should vary this priority */
                    360:        this->priority += 65535;
                    361: 
                    362:        if (!host)
                    363:        {
                    364:                return &this->public;
                    365:        }
                    366: 
                    367:        switch(host->get_family(host))
                    368:        {
                    369:                case AF_INET:
                    370:                        this->family = IPv4;
                    371:                        break;
                    372:                case AF_INET6:
                    373:                        this->family = IPv6;
                    374:                        break;
                    375:                default:
                    376:                        /* unsupported family type, we do not set the host
                    377:                         * (family is set to NO_FAMILY) */
                    378:                        return &this->public;
                    379:        }
                    380: 
                    381:        this->endpoint = host->clone(host);
                    382: 
                    383:        if (base)
                    384:        {
                    385:                this->base = base->clone(base);
                    386:        }
                    387: 
                    388:        return &this->public;
                    389: }
                    390: 
                    391: /**
                    392:  * Described in header
                    393:  */
                    394: endpoint_notify_t *endpoint_notify_create_from_payload(notify_payload_t *notify)
                    395: {
                    396:        private_endpoint_notify_t *this;
                    397:        chunk_t data;
                    398: 
                    399:        if (notify->get_notify_type(notify) != ME_ENDPOINT)
                    400:        {
                    401:                return NULL;
                    402:        }
                    403: 
                    404:        this = endpoint_notify_create();
                    405:        data = notify->get_notification_data(notify);
                    406: 
                    407:        if (parse_notification_data(this, data) != SUCCESS)
                    408:        {
                    409:                destroy(this);
                    410:                return NULL;
                    411:        }
                    412:        return &this->public;
                    413: }

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