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