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>