12949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project/*-
22949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * Copyright (c) 2003, 2004 David Young.  All rights reserved.
32949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *
42949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * Redistribution and use in source and binary forms, with or without
52949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * modification, are permitted provided that the following conditions
62949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * are met:
72949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
82949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
92949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
102949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
112949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *    documentation and/or other materials provided with the distribution.
122949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * 3. The name of David Young may not be used to endorse or promote
132949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *    products derived from this software without specific prior
142949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *    written permission.
152949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *
162949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
172949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
182949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
192949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DAVID
202949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
212949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
222949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
242949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
252949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
262949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
272949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * OF SUCH DAMAGE.
282949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project */
292949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
302949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef HAVE_CONFIG_H
312949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include "config.h"
322949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
332949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
342949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <stdlib.h>
352949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <string.h>
362949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <tcpdump-stdinc.h>
372949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
382949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include "cpack.h"
392949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include "extract.h"
402949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
412949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectstatic u_int8_t *
422949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectcpack_next_boundary(u_int8_t *buf, u_int8_t *p, size_t alignment)
432949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
442949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	size_t misalignment = (size_t)(p - buf) % alignment;
452949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
462949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if (misalignment == 0)
472949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return p;
482949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
492949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return p + (alignment - misalignment);
502949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
512949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
522949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project/* Advance to the next wordsize boundary. Return NULL if fewer than
532949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * wordsize bytes remain in the buffer after the boundary.  Otherwise,
542949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * return a pointer to the boundary.
552949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project */
562949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectstatic u_int8_t *
572949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectcpack_align_and_reserve(struct cpack_state *cs, size_t wordsize)
582949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
592949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	u_int8_t *next;
602949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
612949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	/* Ensure alignment. */
622949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	next = cpack_next_boundary(cs->c_buf, cs->c_next, wordsize);
632949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
642949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	/* Too little space for wordsize bytes? */
652949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if (next - cs->c_buf + wordsize > cs->c_len)
662949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return NULL;
672949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
682949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return next;
692949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
702949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
712949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectint
722949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectcpack_init(struct cpack_state *cs, u_int8_t *buf, size_t buflen)
732949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
742949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	memset(cs, 0, sizeof(*cs));
752949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
762949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_buf = buf;
772949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_len = buflen;
782949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_next = cs->c_buf;
792949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
802949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return 0;
812949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
822949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
832949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project/* Unpack a 64-bit unsigned integer. */
842949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectint
852949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectcpack_uint64(struct cpack_state *cs, u_int64_t *u)
862949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
872949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	u_int8_t *next;
882949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
892949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
902949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return -1;
912949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
922949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	*u = EXTRACT_LE_64BITS(next);
932949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
942949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	/* Move pointer past the u_int64_t. */
952949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_next = next + sizeof(*u);
962949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return 0;
972949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
982949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
992949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project/* Unpack a 32-bit unsigned integer. */
1002949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectint
1012949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectcpack_uint32(struct cpack_state *cs, u_int32_t *u)
1022949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
1032949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	u_int8_t *next;
1042949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1052949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
1062949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return -1;
1072949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1082949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	*u = EXTRACT_LE_32BITS(next);
1092949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1102949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	/* Move pointer past the u_int32_t. */
1112949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_next = next + sizeof(*u);
1122949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return 0;
1132949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
1142949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1152949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project/* Unpack a 16-bit unsigned integer. */
1162949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectint
1172949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectcpack_uint16(struct cpack_state *cs, u_int16_t *u)
1182949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
1192949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	u_int8_t *next;
1202949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1212949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
1222949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return -1;
1232949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1242949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	*u = EXTRACT_LE_16BITS(next);
1252949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1262949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	/* Move pointer past the u_int16_t. */
1272949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_next = next + sizeof(*u);
1282949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return 0;
1292949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
1302949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1312949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project/* Unpack an 8-bit unsigned integer. */
1322949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectint
1332949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectcpack_uint8(struct cpack_state *cs, u_int8_t *u)
1342949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
1352949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	/* No space left? */
1362949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len)
1372949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return -1;
1382949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1392949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	*u = *cs->c_next;
1402949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1412949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	/* Move pointer past the u_int8_t. */
1422949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_next++;
1432949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return 0;
1442949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
145