Annotation of embedaddon/strongswan/src/libstrongswan/bio/bio_reader.c, revision 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>