Annotation of embedaddon/strongswan/src/libstrongswan/bio/bio_reader.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2012 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * Copyright (C) 2010 Martin Willi
                      6:  * Copyright (C) 2010 revosec AG
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify it
                      9:  * under the terms of the GNU General Public License as published by the
                     10:  * Free Software Foundation; either version 2 of the License, or (at your
                     11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful, but
                     14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     16:  * for more details.
                     17:  */
                     18: 
                     19: #include "bio_reader.h"
                     20: 
                     21: #include <utils/debug.h>
                     22: 
                     23: typedef struct private_bio_reader_t private_bio_reader_t;
                     24: 
                     25: /**
                     26:  * Private data of an bio_reader_t object.
                     27:  */
                     28: struct private_bio_reader_t {
                     29: 
                     30:        /**
                     31:         * Public bio_reader_t interface.
                     32:         */
                     33:        bio_reader_t public;
                     34: 
                     35:        /**
                     36:         * Remaining data to process
                     37:         */
                     38:        chunk_t buf;
                     39: 
                     40:        /**
                     41:         * Optional data to free during destruction
                     42:         */
                     43:        chunk_t cleanup;
                     44: };
                     45: 
                     46: METHOD(bio_reader_t, remaining, uint32_t,
                     47:        private_bio_reader_t *this)
                     48: {
                     49:        return this->buf.len;
                     50: }
                     51: 
                     52: METHOD(bio_reader_t, peek, chunk_t,
                     53:        private_bio_reader_t *this)
                     54: {
                     55:        return this->buf;
                     56: }
                     57: 
                     58: /**
                     59:  * A version of chunk_skip() that supports skipping from the end (i.e. simply
                     60:  * reducing the size)
                     61:  */
                     62: static inline chunk_t chunk_skip_end(chunk_t chunk, size_t bytes, bool from_end)
                     63: {
                     64:        if (chunk.len > bytes)
                     65:        {
                     66:                if (!from_end)
                     67:                {
                     68:                        chunk.ptr += bytes;
                     69:                }
                     70:                chunk.len -= bytes;
                     71:                return chunk;
                     72:        }
                     73:        return chunk_empty;
                     74: }
                     75: 
                     76: /**
                     77:  * Returns a pointer to the data to read, optionally from the end
                     78:  */
                     79: static inline u_char *get_ptr_end(private_bio_reader_t *this, uint32_t len,
                     80:                                                                  bool from_end)
                     81: {
                     82:        return from_end ? this->buf.ptr + (this->buf.len - len) : this->buf.ptr;
                     83: }
                     84: 
                     85: /**
                     86:  * Read an uint8_t from the buffer, optionally from the end of the buffer
                     87:  */
                     88: static bool read_uint8_internal(private_bio_reader_t *this, uint8_t *res,
                     89:                                                                bool from_end)
                     90: {
                     91:        if (this->buf.len < 1)
                     92:        {
                     93:                DBG1(DBG_LIB, "%d bytes insufficient to parse u_int8 data",
                     94:                         this->buf.len);
                     95:                return FALSE;
                     96:        }
                     97:        *res = *get_ptr_end(this, 1, from_end);
                     98:        this->buf = chunk_skip_end(this->buf, 1, from_end);
                     99:        return TRUE;
                    100: }
                    101: 
                    102: /**
                    103:  * Read an uint16_t from the buffer, optionally from the end
                    104:  */
                    105: static bool read_uint16_internal(private_bio_reader_t *this, uint16_t *res,
                    106:                                                                 bool from_end)
                    107: {
                    108:        if (this->buf.len < 2)
                    109:        {
                    110:                DBG1(DBG_LIB, "%d bytes insufficient to parse u_int16 data",
                    111:                         this->buf.len);
                    112:                return FALSE;
                    113:        }
                    114:        *res = untoh16(get_ptr_end(this, 2, from_end));
                    115:        this->buf = chunk_skip_end(this->buf, 2, from_end);
                    116:        return TRUE;
                    117: }
                    118: 
                    119: /**
                    120:  * Read an uint32_t (only 24-bit) from the buffer, optionally from the end
                    121:  */
                    122: static bool read_uint24_internal(private_bio_reader_t *this, uint32_t *res,
                    123:                                                                 bool from_end)
                    124: {
                    125:        uint32_t tmp;
                    126: 
                    127:        if (this->buf.len < 3)
                    128:        {
                    129:                DBG1(DBG_LIB, "%d bytes insufficient to parse u_int24 data",
                    130:                         this->buf.len);
                    131:                return FALSE;
                    132:        }
                    133:        memcpy(&tmp, get_ptr_end(this, 3, from_end), 3);
                    134:        *res = ntohl(tmp) >> 8;
                    135:        this->buf = chunk_skip_end(this->buf, 3, from_end);
                    136:        return TRUE;
                    137: }
                    138: 
                    139: /**
                    140:  * Read an uint32_t from the buffer, optionally from the end
                    141:  */
                    142: static bool read_uint32_internal(private_bio_reader_t *this, uint32_t *res,
                    143:                                                                 bool from_end)
                    144: {
                    145:        if (this->buf.len < 4)
                    146:        {
                    147:                DBG1(DBG_LIB, "%d bytes insufficient to parse u_int32 data",
                    148:                         this->buf.len);
                    149:                return FALSE;
                    150:        }
                    151:        *res = untoh32(get_ptr_end(this, 4, from_end));
                    152:        this->buf = chunk_skip_end(this->buf, 4, from_end);
                    153:        return TRUE;
                    154: }
                    155: 
                    156: /**
                    157:  * Read an uint64_t from the buffer, optionally from the end
                    158:  */
                    159: static bool read_uint64_internal(private_bio_reader_t *this, uint64_t *res,
                    160:                                                                 bool from_end)
                    161: {
                    162:        if (this->buf.len < 8)
                    163:        {
                    164:                DBG1(DBG_LIB, "%d bytes insufficient to parse u_int64 data",
                    165:                         this->buf.len);
                    166:                return FALSE;
                    167:        }
                    168:        *res = untoh64(get_ptr_end(this, 8, from_end));
                    169:        this->buf = chunk_skip_end(this->buf, 8, from_end);
                    170:        return TRUE;
                    171: }
                    172: 
                    173: /**
                    174:  * Read a chunk of data from the buffer, optionally from the end
                    175:  */
                    176: static bool read_data_internal(private_bio_reader_t *this, uint32_t len,
                    177:                                                           chunk_t *res, bool from_end)
                    178: {
                    179:        if (this->buf.len < len)
                    180:        {
                    181:                DBG1(DBG_LIB, "%d bytes insufficient to parse %d bytes of data",
                    182:                         this->buf.len, len);
                    183:                return FALSE;
                    184:        }
                    185:        *res = chunk_create(get_ptr_end(this, len, from_end), len);
                    186:        this->buf = chunk_skip_end(this->buf, len, from_end);
                    187:        return TRUE;
                    188: }
                    189: 
                    190: METHOD(bio_reader_t, read_uint8, bool,
                    191:        private_bio_reader_t *this, uint8_t *res)
                    192: {
                    193:        return read_uint8_internal(this, res, FALSE);
                    194: }
                    195: 
                    196: METHOD(bio_reader_t, read_uint16, bool,
                    197:        private_bio_reader_t *this, uint16_t *res)
                    198: {
                    199:        return read_uint16_internal(this, res, FALSE);
                    200: }
                    201: 
                    202: METHOD(bio_reader_t, read_uint24, bool,
                    203:        private_bio_reader_t *this, uint32_t *res)
                    204: {
                    205:        return read_uint24_internal(this, res, FALSE);
                    206: }
                    207: 
                    208: METHOD(bio_reader_t, read_uint32, bool,
                    209:        private_bio_reader_t *this, uint32_t *res)
                    210: {
                    211:        return read_uint32_internal(this, res, FALSE);
                    212: }
                    213: 
                    214: METHOD(bio_reader_t, read_uint64, bool,
                    215:        private_bio_reader_t *this, uint64_t *res)
                    216: {
                    217:        return read_uint64_internal(this, res, FALSE);
                    218: }
                    219: 
                    220: METHOD(bio_reader_t, read_data, bool,
                    221:        private_bio_reader_t *this, uint32_t len, chunk_t *res)
                    222: {
                    223:        return read_data_internal(this, len, res, FALSE);
                    224: }
                    225: 
                    226: METHOD(bio_reader_t, read_uint8_end, bool,
                    227:        private_bio_reader_t *this, uint8_t *res)
                    228: {
                    229:        return read_uint8_internal(this, res, TRUE);
                    230: }
                    231: 
                    232: METHOD(bio_reader_t, read_uint16_end, bool,
                    233:        private_bio_reader_t *this, uint16_t *res)
                    234: {
                    235:        return read_uint16_internal(this, res, TRUE);
                    236: }
                    237: 
                    238: METHOD(bio_reader_t, read_uint24_end, bool,
                    239:        private_bio_reader_t *this, uint32_t *res)
                    240: {
                    241:        return read_uint24_internal(this, res, TRUE);
                    242: }
                    243: 
                    244: METHOD(bio_reader_t, read_uint32_end, bool,
                    245:        private_bio_reader_t *this, uint32_t *res)
                    246: {
                    247:        return read_uint32_internal(this, res, TRUE);
                    248: }
                    249: 
                    250: METHOD(bio_reader_t, read_uint64_end, bool,
                    251:        private_bio_reader_t *this, uint64_t *res)
                    252: {
                    253:        return read_uint64_internal(this, res, TRUE);
                    254: }
                    255: 
                    256: METHOD(bio_reader_t, read_data_end, bool,
                    257:        private_bio_reader_t *this, uint32_t len, chunk_t *res)
                    258: {
                    259:        return read_data_internal(this, len, res, TRUE);
                    260: }
                    261: 
                    262: METHOD(bio_reader_t, read_data8, bool,
                    263:        private_bio_reader_t *this, chunk_t *res)
                    264: {
                    265:        uint8_t len;
                    266: 
                    267:        if (!read_uint8(this, &len))
                    268:        {
                    269:                return FALSE;
                    270:        }
                    271:        return read_data(this, len, res);
                    272: }
                    273: 
                    274: METHOD(bio_reader_t, read_data16, bool,
                    275:        private_bio_reader_t *this, chunk_t *res)
                    276: {
                    277:        uint16_t len;
                    278: 
                    279:        if (!read_uint16(this, &len))
                    280:        {
                    281:                return FALSE;
                    282:        }
                    283:        return read_data(this, len, res);
                    284: }
                    285: 
                    286: METHOD(bio_reader_t, read_data24, bool,
                    287:        private_bio_reader_t *this, chunk_t *res)
                    288: {
                    289:        uint32_t len;
                    290: 
                    291:        if (!read_uint24(this, &len))
                    292:        {
                    293:                return FALSE;
                    294:        }
                    295:        return read_data(this, len, res);
                    296: }
                    297: 
                    298: METHOD(bio_reader_t, read_data32, bool,
                    299:        private_bio_reader_t *this, chunk_t *res)
                    300: {
                    301:        uint32_t len;
                    302: 
                    303:        if (!read_uint32(this, &len))
                    304:        {
                    305:                return FALSE;
                    306:        }
                    307:        return read_data(this, len, res);
                    308: }
                    309: 
                    310: METHOD(bio_reader_t, destroy, void,
                    311:        private_bio_reader_t *this)
                    312: {
                    313:        free(this->cleanup.ptr);
                    314:        free(this);
                    315: }
                    316: 
                    317: /**
                    318:  * See header
                    319:  */
                    320: bio_reader_t *bio_reader_create(chunk_t data)
                    321: {
                    322:        private_bio_reader_t *this;
                    323: 
                    324:        INIT(this,
                    325:                .public = {
                    326:                        .remaining = _remaining,
                    327:                        .peek = _peek,
                    328:                        .read_uint8 = _read_uint8,
                    329:                        .read_uint16 = _read_uint16,
                    330:                        .read_uint24 = _read_uint24,
                    331:                        .read_uint32 = _read_uint32,
                    332:                        .read_uint64 = _read_uint64,
                    333:                        .read_data = _read_data,
                    334:                        .read_uint8_end = _read_uint8_end,
                    335:                        .read_uint16_end = _read_uint16_end,
                    336:                        .read_uint24_end = _read_uint24_end,
                    337:                        .read_uint32_end = _read_uint32_end,
                    338:                        .read_uint64_end = _read_uint64_end,
                    339:                        .read_data_end = _read_data_end,
                    340:                        .read_data8 = _read_data8,
                    341:                        .read_data16 = _read_data16,
                    342:                        .read_data24 = _read_data24,
                    343:                        .read_data32 = _read_data32,
                    344:                        .destroy = _destroy,
                    345:                },
                    346:                .buf = data,
                    347:        );
                    348: 
                    349:        return &this->public;
                    350: }
                    351: 
                    352: /**
                    353:  * See header
                    354:  */
                    355: bio_reader_t *bio_reader_create_own(chunk_t data)
                    356: {
                    357:        private_bio_reader_t *this;
                    358: 
                    359:        this = (private_bio_reader_t*)bio_reader_create(data);
                    360: 
                    361:        this->cleanup = data;
                    362: 
                    363:        return &this->public;
                    364: }

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