Annotation of embedaddon/strongswan/src/libcharon/plugins/ha/ha_message.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2008 Martin Willi
        !             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: #define _GNU_SOURCE
        !            17: #include <string.h>
        !            18: #include <arpa/inet.h>
        !            19: 
        !            20: #include "ha_message.h"
        !            21: 
        !            22: #include <daemon.h>
        !            23: 
        !            24: #define ALLOCATION_BLOCK 64
        !            25: 
        !            26: typedef struct private_ha_message_t private_ha_message_t;
        !            27: 
        !            28: /**
        !            29:  * Private data of an ha_message_t object.
        !            30:  */
        !            31: struct private_ha_message_t {
        !            32: 
        !            33:        /**
        !            34:         * Public ha_message_t interface.
        !            35:         */
        !            36:        ha_message_t public;
        !            37: 
        !            38:        /**
        !            39:         * Allocated size of buf
        !            40:         */
        !            41:        size_t allocated;
        !            42: 
        !            43:        /**
        !            44:         * Buffer containing encoded data
        !            45:         */
        !            46:        chunk_t buf;
        !            47: };
        !            48: 
        !            49: ENUM(ha_message_type_names, HA_IKE_ADD, HA_IKE_IV,
        !            50:        "IKE_ADD",
        !            51:        "IKE_UPDATE",
        !            52:        "IKE_MID_INITIATOR",
        !            53:        "IKE_MID_RESPONDER",
        !            54:        "IKE_DELETE",
        !            55:        "CHILD_ADD",
        !            56:        "CHILD_DELETE",
        !            57:        "SEGMENT_DROP",
        !            58:        "SEGMENT_TAKE",
        !            59:        "STATUS",
        !            60:        "RESYNC",
        !            61:        "IKE_IV",
        !            62: );
        !            63: 
        !            64: typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t;
        !            65: 
        !            66: /**
        !            67:  * Encoding if an ike_sa_id_t
        !            68:  */
        !            69: struct ike_sa_id_encoding_t {
        !            70:        uint8_t ike_version;
        !            71:        uint64_t initiator_spi;
        !            72:        uint64_t responder_spi;
        !            73:        uint8_t initiator;
        !            74: } __attribute__((packed));
        !            75: 
        !            76: typedef struct identification_encoding_t identification_encoding_t;
        !            77: 
        !            78: /**
        !            79:  * Encoding of a identification_t
        !            80:  */
        !            81: struct identification_encoding_t {
        !            82:        uint8_t type;
        !            83:        uint8_t len;
        !            84:        char encoding[];
        !            85: } __attribute__((packed));
        !            86: 
        !            87: typedef struct host_encoding_t host_encoding_t;
        !            88: 
        !            89: /**
        !            90:  * encoding of a host_t
        !            91:  */
        !            92: struct host_encoding_t {
        !            93:        uint16_t port;
        !            94:        uint8_t family;
        !            95:        char encoding[];
        !            96: } __attribute__((packed));
        !            97: 
        !            98: typedef struct ts_encoding_t ts_encoding_t;
        !            99: 
        !           100: /**
        !           101:  * encoding of a traffic_selector_t
        !           102:  */
        !           103: struct ts_encoding_t {
        !           104:        uint8_t type;
        !           105:        uint8_t protocol;
        !           106:        uint16_t from_port;
        !           107:        uint16_t to_port;
        !           108:        uint8_t dynamic;
        !           109:        char encoding[];
        !           110: } __attribute__((packed));
        !           111: 
        !           112: METHOD(ha_message_t, get_type, ha_message_type_t,
        !           113:        private_ha_message_t *this)
        !           114: {
        !           115:        return this->buf.ptr[1];
        !           116: }
        !           117: 
        !           118: /**
        !           119:  * check for space in buffer, increase if necessary
        !           120:  */
        !           121: static void check_buf(private_ha_message_t *this, size_t len)
        !           122: {
        !           123:        int increased = 0;
        !           124: 
        !           125:        while (this->buf.len + len > this->allocated)
        !           126:        {       /* double size */
        !           127:                this->allocated += ALLOCATION_BLOCK;
        !           128:                increased++;
        !           129:        }
        !           130:        if (increased)
        !           131:        {
        !           132:                this->buf.ptr = realloc(this->buf.ptr, this->allocated);
        !           133:        }
        !           134: }
        !           135: 
        !           136: METHOD(ha_message_t, add_attribute, void,
        !           137:        private_ha_message_t *this, ha_message_attribute_t attribute, ...)
        !           138: {
        !           139:        size_t len;
        !           140:        va_list args;
        !           141: 
        !           142:        check_buf(this, sizeof(uint8_t));
        !           143:        this->buf.ptr[this->buf.len] = attribute;
        !           144:        this->buf.len += sizeof(uint8_t);
        !           145: 
        !           146:        va_start(args, attribute);
        !           147:        switch (attribute)
        !           148:        {
        !           149:                /* ike_sa_id_t* */
        !           150:                case HA_IKE_ID:
        !           151:                case HA_IKE_REKEY_ID:
        !           152:                {
        !           153:                        ike_sa_id_encoding_t *enc;
        !           154:                        ike_sa_id_t *id;
        !           155: 
        !           156:                        id = va_arg(args, ike_sa_id_t*);
        !           157:                        check_buf(this, sizeof(ike_sa_id_encoding_t));
        !           158:                        enc = (ike_sa_id_encoding_t*)(this->buf.ptr + this->buf.len);
        !           159:                        this->buf.len += sizeof(ike_sa_id_encoding_t);
        !           160:                        enc->initiator = id->is_initiator(id);
        !           161:                        enc->ike_version = id->get_ike_version(id);
        !           162:                        enc->initiator_spi = id->get_initiator_spi(id);
        !           163:                        enc->responder_spi = id->get_responder_spi(id);
        !           164:                        break;
        !           165:                }
        !           166:                /* identification_t* */
        !           167:                case HA_LOCAL_ID:
        !           168:                case HA_REMOTE_ID:
        !           169:                case HA_REMOTE_EAP_ID:
        !           170:                {
        !           171:                        identification_encoding_t *enc;
        !           172:                        identification_t *id;
        !           173:                        chunk_t data;
        !           174: 
        !           175:                        id = va_arg(args, identification_t*);
        !           176:                        data = id->get_encoding(id);
        !           177:                        check_buf(this, sizeof(identification_encoding_t) + data.len);
        !           178:                        enc = (identification_encoding_t*)(this->buf.ptr + this->buf.len);
        !           179:                        this->buf.len += sizeof(identification_encoding_t) + data.len;
        !           180:                        enc->type = id->get_type(id);
        !           181:                        enc->len = data.len;
        !           182:                        memcpy(enc->encoding, data.ptr, data.len);
        !           183:                        break;
        !           184:                }
        !           185:                /* host_t* */
        !           186:                case HA_LOCAL_ADDR:
        !           187:                case HA_REMOTE_ADDR:
        !           188:                case HA_LOCAL_VIP:
        !           189:                case HA_REMOTE_VIP:
        !           190:                case HA_PEER_ADDR:
        !           191:                {
        !           192:                        host_encoding_t *enc;
        !           193:                        host_t *host;
        !           194:                        chunk_t data;
        !           195: 
        !           196:                        host = va_arg(args, host_t*);
        !           197:                        data = host->get_address(host);
        !           198:                        check_buf(this, sizeof(host_encoding_t) + data.len);
        !           199:                        enc = (host_encoding_t*)(this->buf.ptr + this->buf.len);
        !           200:                        this->buf.len += sizeof(host_encoding_t) + data.len;
        !           201:                        enc->family = host->get_family(host);
        !           202:                        enc->port = htons(host->get_port(host));
        !           203:                        memcpy(enc->encoding, data.ptr, data.len);
        !           204:                        break;
        !           205:                }
        !           206:                /* char* */
        !           207:                case HA_CONFIG_NAME:
        !           208:                {
        !           209:                        char *str;
        !           210: 
        !           211:                        str = va_arg(args, char*);
        !           212:                        len = strlen(str) + 1;
        !           213:                        check_buf(this, len);
        !           214:                        memcpy(this->buf.ptr + this->buf.len, str, len);
        !           215:                        this->buf.len += len;
        !           216:                        break;
        !           217:                }
        !           218:                /* uint8_t */
        !           219:                case HA_IKE_VERSION:
        !           220:                case HA_INITIATOR:
        !           221:                case HA_IPSEC_MODE:
        !           222:                case HA_IPCOMP:
        !           223:                {
        !           224:                        uint8_t val;
        !           225: 
        !           226:                        val = va_arg(args, u_int);
        !           227:                        check_buf(this, sizeof(val));
        !           228:                        this->buf.ptr[this->buf.len] = val;
        !           229:                        this->buf.len += sizeof(val);
        !           230:                        break;
        !           231:                }
        !           232:                /* uint16_t */
        !           233:                case HA_ALG_DH:
        !           234:                case HA_ALG_PRF:
        !           235:                case HA_ALG_OLD_PRF:
        !           236:                case HA_ALG_ENCR:
        !           237:                case HA_ALG_ENCR_LEN:
        !           238:                case HA_ALG_INTEG:
        !           239:                case HA_INBOUND_CPI:
        !           240:                case HA_OUTBOUND_CPI:
        !           241:                case HA_SEGMENT:
        !           242:                case HA_ESN:
        !           243:                case HA_AUTH_METHOD:
        !           244:                {
        !           245:                        uint16_t val;
        !           246: 
        !           247:                        val = va_arg(args, u_int);
        !           248:                        check_buf(this, sizeof(val));
        !           249:                        *(uint16_t*)(this->buf.ptr + this->buf.len) = htons(val);
        !           250:                        this->buf.len += sizeof(val);
        !           251:                        break;
        !           252:                }
        !           253:                /** uint32_t */
        !           254:                case HA_CONDITIONS:
        !           255:                case HA_EXTENSIONS:
        !           256:                case HA_INBOUND_SPI:
        !           257:                case HA_OUTBOUND_SPI:
        !           258:                case HA_MID:
        !           259:                {
        !           260:                        uint32_t val;
        !           261: 
        !           262:                        val = va_arg(args, u_int);
        !           263:                        check_buf(this, sizeof(val));
        !           264:                        *(uint32_t*)(this->buf.ptr + this->buf.len) = htonl(val);
        !           265:                        this->buf.len += sizeof(val);
        !           266:                        break;
        !           267:                }
        !           268:                /** chunk_t */
        !           269:                case HA_NONCE_I:
        !           270:                case HA_NONCE_R:
        !           271:                case HA_SECRET:
        !           272:                case HA_LOCAL_DH:
        !           273:                case HA_REMOTE_DH:
        !           274:                case HA_PSK:
        !           275:                case HA_IV:
        !           276:                case HA_OLD_SKD:
        !           277:                {
        !           278:                        chunk_t chunk;
        !           279: 
        !           280:                        chunk = va_arg(args, chunk_t);
        !           281:                        check_buf(this, chunk.len + sizeof(uint16_t));
        !           282:                        *(uint16_t*)(this->buf.ptr + this->buf.len) = htons(chunk.len);
        !           283:                        memcpy(this->buf.ptr + this->buf.len + sizeof(uint16_t),
        !           284:                                   chunk.ptr, chunk.len);
        !           285:                        this->buf.len += chunk.len + sizeof(uint16_t);;
        !           286:                        break;
        !           287:                }
        !           288:                /** traffic_selector_t */
        !           289:                case HA_LOCAL_TS:
        !           290:                case HA_REMOTE_TS:
        !           291:                {
        !           292:                        ts_encoding_t *enc;
        !           293:                        traffic_selector_t *ts;
        !           294:                        chunk_t data;
        !           295: 
        !           296:                        ts = va_arg(args, traffic_selector_t*);
        !           297:                        data = chunk_cata("cc", ts->get_from_address(ts),
        !           298:                                                          ts->get_to_address(ts));
        !           299:                        check_buf(this, sizeof(ts_encoding_t) + data.len);
        !           300:                        enc = (ts_encoding_t*)(this->buf.ptr + this->buf.len);
        !           301:                        this->buf.len += sizeof(ts_encoding_t) + data.len;
        !           302:                        enc->type = ts->get_type(ts);
        !           303:                        enc->protocol = ts->get_protocol(ts);
        !           304:                        enc->from_port = htons(ts->get_from_port(ts));
        !           305:                        enc->to_port = htons(ts->get_to_port(ts));
        !           306:                        enc->dynamic = ts->is_dynamic(ts);
        !           307:                        memcpy(enc->encoding, data.ptr, data.len);
        !           308:                        break;
        !           309:                }
        !           310:                default:
        !           311:                {
        !           312:                        DBG1(DBG_CFG, "unable to encode, attribute %d unknown", attribute);
        !           313:                        this->buf.len -= sizeof(uint8_t);
        !           314:                        break;
        !           315:                }
        !           316:        }
        !           317:        va_end(args);
        !           318: }
        !           319: 
        !           320: /**
        !           321:  * Attribute enumerator implementation
        !           322:  */
        !           323: typedef struct {
        !           324:        /** implements enumerator_t */
        !           325:        enumerator_t public;
        !           326:        /** position in message */
        !           327:        chunk_t buf;
        !           328:        /** cleanup handler of current element, if any */
        !           329:        void (*cleanup)(void* data);
        !           330:        /** data to pass to cleanup handler */
        !           331:        void *cleanup_data;
        !           332: } attribute_enumerator_t;
        !           333: 
        !           334: METHOD(enumerator_t, attribute_enumerate, bool,
        !           335:        attribute_enumerator_t *this, va_list args)
        !           336: {
        !           337:        ha_message_attribute_t attr, *attr_out;
        !           338:        ha_message_value_t *value;
        !           339: 
        !           340:        VA_ARGS_VGET(args, attr_out, value);
        !           341: 
        !           342:        if (this->cleanup)
        !           343:        {
        !           344:                this->cleanup(this->cleanup_data);
        !           345:                this->cleanup = NULL;
        !           346:        }
        !           347:        if (this->buf.len < 1)
        !           348:        {
        !           349:                return FALSE;
        !           350:        }
        !           351:        attr = this->buf.ptr[0];
        !           352:        this->buf = chunk_skip(this->buf, 1);
        !           353:        switch (attr)
        !           354:        {
        !           355:                /* ike_sa_id_t* */
        !           356:                case HA_IKE_ID:
        !           357:                case HA_IKE_REKEY_ID:
        !           358:                {
        !           359:                        ike_sa_id_encoding_t *enc;
        !           360: 
        !           361:                        if (this->buf.len < sizeof(ike_sa_id_encoding_t))
        !           362:                        {
        !           363:                                return FALSE;
        !           364:                        }
        !           365:                        enc = (ike_sa_id_encoding_t*)(this->buf.ptr);
        !           366:                        value->ike_sa_id = ike_sa_id_create(enc->ike_version,
        !           367:                                                                                enc->initiator_spi, enc->responder_spi,
        !           368:                                                                                enc->initiator);
        !           369:                        *attr_out = attr;
        !           370:                        this->cleanup = (void*)value->ike_sa_id->destroy;
        !           371:                        this->cleanup_data = value->ike_sa_id;
        !           372:                        this->buf = chunk_skip(this->buf, sizeof(ike_sa_id_encoding_t));
        !           373:                        return TRUE;
        !           374:                }
        !           375:                /* identification_t* */
        !           376:                case HA_LOCAL_ID:
        !           377:                case HA_REMOTE_ID:
        !           378:                case HA_REMOTE_EAP_ID:
        !           379:                {
        !           380:                        identification_encoding_t *enc;
        !           381: 
        !           382:                        enc = (identification_encoding_t*)(this->buf.ptr);
        !           383:                        if (this->buf.len < sizeof(identification_encoding_t) ||
        !           384:                                this->buf.len < sizeof(identification_encoding_t) + enc->len)
        !           385:                        {
        !           386:                                return FALSE;
        !           387:                        }
        !           388:                        value->id = identification_create_from_encoding(enc->type,
        !           389:                                                                                chunk_create(enc->encoding, enc->len));
        !           390:                        *attr_out = attr;
        !           391:                        this->cleanup = (void*)value->id->destroy;
        !           392:                        this->cleanup_data = value->id;
        !           393:                        this->buf = chunk_skip(this->buf,
        !           394:                                                                sizeof(identification_encoding_t) + enc->len);
        !           395:                        return TRUE;
        !           396:                }
        !           397:                /* host_t* */
        !           398:                case HA_LOCAL_ADDR:
        !           399:                case HA_REMOTE_ADDR:
        !           400:                case HA_LOCAL_VIP:
        !           401:                case HA_REMOTE_VIP:
        !           402:                case HA_PEER_ADDR:
        !           403:                {
        !           404:                        host_encoding_t *enc;
        !           405: 
        !           406:                        enc = (host_encoding_t*)(this->buf.ptr);
        !           407:                        if (this->buf.len < sizeof(host_encoding_t))
        !           408:                        {
        !           409:                                return FALSE;
        !           410:                        }
        !           411:                        value->host = host_create_from_chunk(enc->family,
        !           412:                                                                        chunk_create(enc->encoding,
        !           413:                                                                                this->buf.len - sizeof(host_encoding_t)),
        !           414:                                                                        ntohs(enc->port));
        !           415:                        if (!value->host)
        !           416:                        {
        !           417:                                return FALSE;
        !           418:                        }
        !           419:                        *attr_out = attr;
        !           420:                        this->cleanup = (void*)value->host->destroy;
        !           421:                        this->cleanup_data = value->host;
        !           422:                        this->buf = chunk_skip(this->buf, sizeof(host_encoding_t) +
        !           423:                                                                   value->host->get_address(value->host).len);
        !           424:                        return TRUE;
        !           425:                }
        !           426:                /* char* */
        !           427:                case HA_CONFIG_NAME:
        !           428:                {
        !           429:                        size_t len;
        !           430: 
        !           431:                        len = strnlen(this->buf.ptr, this->buf.len);
        !           432:                        if (len >= this->buf.len)
        !           433:                        {
        !           434:                                return FALSE;
        !           435:                        }
        !           436:                        value->str = this->buf.ptr;
        !           437:                        *attr_out = attr;
        !           438:                        this->buf = chunk_skip(this->buf, len + 1);
        !           439:                        return TRUE;
        !           440:                }
        !           441:                /* uint8_t */
        !           442:                case HA_IKE_VERSION:
        !           443:                case HA_INITIATOR:
        !           444:                case HA_IPSEC_MODE:
        !           445:                case HA_IPCOMP:
        !           446:                {
        !           447:                        if (this->buf.len < sizeof(uint8_t))
        !           448:                        {
        !           449:                                return FALSE;
        !           450:                        }
        !           451:                        value->u8 = *(uint8_t*)this->buf.ptr;
        !           452:                        *attr_out = attr;
        !           453:                        this->buf = chunk_skip(this->buf, sizeof(uint8_t));
        !           454:                        return TRUE;
        !           455:                }
        !           456:                /** uint16_t */
        !           457:                case HA_ALG_DH:
        !           458:                case HA_ALG_PRF:
        !           459:                case HA_ALG_OLD_PRF:
        !           460:                case HA_ALG_ENCR:
        !           461:                case HA_ALG_ENCR_LEN:
        !           462:                case HA_ALG_INTEG:
        !           463:                case HA_INBOUND_CPI:
        !           464:                case HA_OUTBOUND_CPI:
        !           465:                case HA_SEGMENT:
        !           466:                case HA_ESN:
        !           467:                case HA_AUTH_METHOD:
        !           468:                {
        !           469:                        if (this->buf.len < sizeof(uint16_t))
        !           470:                        {
        !           471:                                return FALSE;
        !           472:                        }
        !           473:                        value->u16 = ntohs(*(uint16_t*)this->buf.ptr);
        !           474:                        *attr_out = attr;
        !           475:                        this->buf = chunk_skip(this->buf, sizeof(uint16_t));
        !           476:                        return TRUE;
        !           477:                }
        !           478:                /** uint32_t */
        !           479:                case HA_CONDITIONS:
        !           480:                case HA_EXTENSIONS:
        !           481:                case HA_INBOUND_SPI:
        !           482:                case HA_OUTBOUND_SPI:
        !           483:                case HA_MID:
        !           484:                {
        !           485:                        if (this->buf.len < sizeof(uint32_t))
        !           486:                        {
        !           487:                                return FALSE;
        !           488:                        }
        !           489:                        value->u32 = ntohl(*(uint32_t*)this->buf.ptr);
        !           490:                        *attr_out = attr;
        !           491:                        this->buf = chunk_skip(this->buf, sizeof(uint32_t));
        !           492:                        return TRUE;
        !           493:                }
        !           494:                /** chunk_t */
        !           495:                case HA_NONCE_I:
        !           496:                case HA_NONCE_R:
        !           497:                case HA_SECRET:
        !           498:                case HA_LOCAL_DH:
        !           499:                case HA_REMOTE_DH:
        !           500:                case HA_PSK:
        !           501:                case HA_IV:
        !           502:                case HA_OLD_SKD:
        !           503:                {
        !           504:                        size_t len;
        !           505: 
        !           506:                        if (this->buf.len < sizeof(uint16_t))
        !           507:                        {
        !           508:                                return FALSE;
        !           509:                        }
        !           510:                        len = ntohs(*(uint16_t*)this->buf.ptr);
        !           511:                        this->buf = chunk_skip(this->buf, sizeof(uint16_t));
        !           512:                        if (this->buf.len < len)
        !           513:                        {
        !           514:                                return FALSE;
        !           515:                        }
        !           516:                        value->chunk.len = len;
        !           517:                        value->chunk.ptr = this->buf.ptr;
        !           518:                        *attr_out = attr;
        !           519:                        this->buf = chunk_skip(this->buf, len);
        !           520:                        return TRUE;
        !           521:                }
        !           522:                case HA_LOCAL_TS:
        !           523:                case HA_REMOTE_TS:
        !           524:                {
        !           525:                        ts_encoding_t *enc;
        !           526:                        host_t *host;
        !           527:                        int addr_len;
        !           528: 
        !           529:                        enc = (ts_encoding_t*)(this->buf.ptr);
        !           530:                        if (this->buf.len < sizeof(ts_encoding_t))
        !           531:                        {
        !           532:                                return FALSE;
        !           533:                        }
        !           534:                        switch (enc->type)
        !           535:                        {
        !           536:                                case TS_IPV4_ADDR_RANGE:
        !           537:                                        addr_len = 4;
        !           538:                                        if (this->buf.len < sizeof(ts_encoding_t) + 2 * addr_len)
        !           539:                                        {
        !           540:                                                return FALSE;
        !           541:                                        }
        !           542:                                        break;
        !           543:                                case TS_IPV6_ADDR_RANGE:
        !           544:                                        addr_len = 16;
        !           545:                                        if (this->buf.len < sizeof(ts_encoding_t) + 2 * addr_len)
        !           546:                                        {
        !           547:                                                return FALSE;
        !           548:                                        }
        !           549:                                        break;
        !           550:                                default:
        !           551:                                        return FALSE;
        !           552:                        }
        !           553:                        if (enc->dynamic)
        !           554:                        {
        !           555:                                host = host_create_from_chunk(0,
        !           556:                                                                        chunk_create(enc->encoding, addr_len), 0);
        !           557:                                if (!host)
        !           558:                                {
        !           559:                                        return FALSE;
        !           560:                                }
        !           561:                                value->ts = traffic_selector_create_dynamic(enc->protocol,
        !           562:                                                                        ntohs(enc->from_port), ntohs(enc->to_port));
        !           563:                                value->ts->set_address(value->ts, host);
        !           564:                                host->destroy(host);
        !           565:                        }
        !           566:                        else
        !           567:                        {
        !           568:                                value->ts = traffic_selector_create_from_bytes(enc->protocol,
        !           569:                                                                enc->type, chunk_create(enc->encoding, addr_len),
        !           570:                                                                ntohs(enc->from_port),
        !           571:                                                                chunk_create(enc->encoding + addr_len, addr_len),
        !           572:                                                                ntohs(enc->to_port));
        !           573:                                if (!value->ts)
        !           574:                                {
        !           575:                                        return FALSE;
        !           576:                                }
        !           577:                        }
        !           578:                        *attr_out = attr;
        !           579:                        this->cleanup = (void*)value->ts->destroy;
        !           580:                        this->cleanup_data = value->ts;
        !           581:                        this->buf = chunk_skip(this->buf, sizeof(ts_encoding_t)
        !           582:                                                                                + addr_len * 2);
        !           583:                        return TRUE;
        !           584:                }
        !           585:                default:
        !           586:                {
        !           587:                        return FALSE;
        !           588:                }
        !           589:        }
        !           590: }
        !           591: 
        !           592: METHOD(enumerator_t, enum_destroy, void,
        !           593:        attribute_enumerator_t *this)
        !           594: {
        !           595:        if (this->cleanup)
        !           596:        {
        !           597:                this->cleanup(this->cleanup_data);
        !           598:        }
        !           599:        free(this);
        !           600: }
        !           601: 
        !           602: METHOD(ha_message_t, create_attribute_enumerator, enumerator_t*,
        !           603:        private_ha_message_t *this)
        !           604: {
        !           605:        attribute_enumerator_t *e;
        !           606: 
        !           607:        INIT(e,
        !           608:                .public = {
        !           609:                        .enumerate = enumerator_enumerate_default,
        !           610:                        .venumerate = _attribute_enumerate,
        !           611:                        .destroy = _enum_destroy,
        !           612:                },
        !           613:                .buf = chunk_skip(this->buf, 2),
        !           614:        );
        !           615: 
        !           616:        return &e->public;
        !           617: }
        !           618: 
        !           619: METHOD(ha_message_t, get_encoding, chunk_t,
        !           620:        private_ha_message_t *this)
        !           621: {
        !           622:        return this->buf;
        !           623: }
        !           624: 
        !           625: METHOD(ha_message_t, destroy, void,
        !           626:        private_ha_message_t *this)
        !           627: {
        !           628:        free(this->buf.ptr);
        !           629:        free(this);
        !           630: }
        !           631: 
        !           632: 
        !           633: static private_ha_message_t *ha_message_create_generic()
        !           634: {
        !           635:        private_ha_message_t *this;
        !           636: 
        !           637:        INIT(this,
        !           638:                .public = {
        !           639:                        .get_type = _get_type,
        !           640:                        .add_attribute = _add_attribute,
        !           641:                        .create_attribute_enumerator = _create_attribute_enumerator,
        !           642:                        .get_encoding = _get_encoding,
        !           643:                        .destroy = _destroy,
        !           644:                },
        !           645:        );
        !           646:        return this;
        !           647: }
        !           648: 
        !           649: /**
        !           650:  * See header
        !           651:  */
        !           652: ha_message_t *ha_message_create(ha_message_type_t type)
        !           653: {
        !           654:        private_ha_message_t *this = ha_message_create_generic();
        !           655: 
        !           656:        this->allocated = ALLOCATION_BLOCK;
        !           657:        this->buf.ptr = malloc(this->allocated);
        !           658:        this->buf.len = 2;
        !           659:        this->buf.ptr[0] = HA_MESSAGE_VERSION;
        !           660:        this->buf.ptr[1] = type;
        !           661: 
        !           662:        return &this->public;
        !           663: }
        !           664: 
        !           665: /**
        !           666:  * See header
        !           667:  */
        !           668: ha_message_t *ha_message_parse(chunk_t data)
        !           669: {
        !           670:        private_ha_message_t *this;
        !           671: 
        !           672:        if (data.len < 2)
        !           673:        {
        !           674:                DBG1(DBG_CFG, "HA message too short");
        !           675:                return NULL;
        !           676:        }
        !           677:        if (data.ptr[0] != HA_MESSAGE_VERSION)
        !           678:        {
        !           679:                DBG1(DBG_CFG, "HA message has version %d, expected %d",
        !           680:                         data.ptr[0], HA_MESSAGE_VERSION);
        !           681:                return NULL;
        !           682:        }
        !           683: 
        !           684:        this = ha_message_create_generic();
        !           685:        this->buf = chunk_clone(data);
        !           686:        this->allocated = this->buf.len;
        !           687: 
        !           688:        return &this->public;
        !           689: }
        !           690: 

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