Annotation of embedaddon/strongswan/src/libcharon/plugins/ha/ha_message.c, revision 1.1.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>