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>
36e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes#include <netdissect-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
41e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughesconst uint8_t *
42e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughescpack_next_boundary(const uint8_t *buf, const uint8_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 */
56e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughesconst uint8_t *
572949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectcpack_align_and_reserve(struct cpack_state *cs, size_t wordsize)
582949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
59e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes	const uint8_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
7153f17a9db278d33517d9888dd77848f554522a38JP Abgrall/* Advance by N bytes without returning them. */
7253f17a9db278d33517d9888dd77848f554522a38JP Abgrallint
7353f17a9db278d33517d9888dd77848f554522a38JP Abgrallcpack_advance(struct cpack_state *cs, const size_t toskip)
7453f17a9db278d33517d9888dd77848f554522a38JP Abgrall{
7553f17a9db278d33517d9888dd77848f554522a38JP Abgrall	/* No space left? */
7653f17a9db278d33517d9888dd77848f554522a38JP Abgrall	if (cs->c_next - cs->c_buf + toskip > cs->c_len)
7753f17a9db278d33517d9888dd77848f554522a38JP Abgrall		return -1;
7853f17a9db278d33517d9888dd77848f554522a38JP Abgrall	cs->c_next += toskip;
7953f17a9db278d33517d9888dd77848f554522a38JP Abgrall	return 0;
8053f17a9db278d33517d9888dd77848f554522a38JP Abgrall}
8153f17a9db278d33517d9888dd77848f554522a38JP Abgrall
822949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectint
83e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughescpack_init(struct cpack_state *cs, const uint8_t *buf, size_t buflen)
842949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
852949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	memset(cs, 0, sizeof(*cs));
862949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
872949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_buf = buf;
882949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_len = buflen;
892949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_next = cs->c_buf;
902949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
912949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return 0;
922949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
932949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
942949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project/* Unpack a 64-bit unsigned integer. */
952949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectint
96892a68bdf2f50b40781212e4d7ee7369c8165953Elliott Hughescpack_uint64(struct cpack_state *cs, uint64_t *u)
972949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
98e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes	const uint8_t *next;
992949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1002949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
1012949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return -1;
1022949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1032949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	*u = EXTRACT_LE_64BITS(next);
1042949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
105892a68bdf2f50b40781212e4d7ee7369c8165953Elliott Hughes	/* Move pointer past the uint64_t. */
1062949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_next = next + sizeof(*u);
1072949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return 0;
1082949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
1092949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1102949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project/* Unpack a 32-bit unsigned integer. */
1112949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectint
112892a68bdf2f50b40781212e4d7ee7369c8165953Elliott Hughescpack_uint32(struct cpack_state *cs, uint32_t *u)
1132949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
114e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes	const uint8_t *next;
1152949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1162949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
1172949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return -1;
1182949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1192949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	*u = EXTRACT_LE_32BITS(next);
1202949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
121892a68bdf2f50b40781212e4d7ee7369c8165953Elliott Hughes	/* Move pointer past the uint32_t. */
1222949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_next = next + sizeof(*u);
1232949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return 0;
1242949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
1252949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1262949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project/* Unpack a 16-bit unsigned integer. */
1272949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectint
128892a68bdf2f50b40781212e4d7ee7369c8165953Elliott Hughescpack_uint16(struct cpack_state *cs, uint16_t *u)
1292949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
130e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes	const uint8_t *next;
1312949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1322949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
1332949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return -1;
1342949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1352949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	*u = EXTRACT_LE_16BITS(next);
1362949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
137892a68bdf2f50b40781212e4d7ee7369c8165953Elliott Hughes	/* Move pointer past the uint16_t. */
1382949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_next = next + sizeof(*u);
1392949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return 0;
1402949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
1412949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1422949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project/* Unpack an 8-bit unsigned integer. */
1432949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectint
144892a68bdf2f50b40781212e4d7ee7369c8165953Elliott Hughescpack_uint8(struct cpack_state *cs, uint8_t *u)
1452949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
1462949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	/* No space left? */
1472949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len)
1482949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return -1;
1492949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1502949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	*u = *cs->c_next;
1512949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
152892a68bdf2f50b40781212e4d7ee7369c8165953Elliott Hughes	/* Move pointer past the uint8_t. */
1532949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	cs->c_next++;
1542949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return 0;
1552949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
156