1 /*- 2 * Copyright (c) 2003, 2004 David Young. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 16 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID 17 * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 19 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 24 * OF SUCH DAMAGE. 25 */ 26 27 #define NETDISSECT_REWORKED 28 #ifdef HAVE_CONFIG_H 29 #include "config.h" 30 #endif 31 32 #include <stdlib.h> 33 #include <string.h> 34 #include <tcpdump-stdinc.h> 35 36 #include "cpack.h" 37 #include "extract.h" 38 39 uint8_t * 40 cpack_next_boundary(uint8_t *buf, uint8_t *p, size_t alignment) 41 { 42 size_t misalignment = (size_t)(p - buf) % alignment; 43 44 if (misalignment == 0) 45 return p; 46 47 return p + (alignment - misalignment); 48 } 49 50 /* Advance to the next wordsize boundary. Return NULL if fewer than 51 * wordsize bytes remain in the buffer after the boundary. Otherwise, 52 * return a pointer to the boundary. 53 */ 54 uint8_t * 55 cpack_align_and_reserve(struct cpack_state *cs, size_t wordsize) 56 { 57 uint8_t *next; 58 59 /* Ensure alignment. */ 60 next = cpack_next_boundary(cs->c_buf, cs->c_next, wordsize); 61 62 /* Too little space for wordsize bytes? */ 63 if (next - cs->c_buf + wordsize > cs->c_len) 64 return NULL; 65 66 return next; 67 } 68 69 /* Advance by N bytes without returning them. */ 70 int 71 cpack_advance(struct cpack_state *cs, const size_t toskip) 72 { 73 /* No space left? */ 74 if (cs->c_next - cs->c_buf + toskip > cs->c_len) 75 return -1; 76 cs->c_next += toskip; 77 return 0; 78 } 79 80 int 81 cpack_init(struct cpack_state *cs, uint8_t *buf, size_t buflen) 82 { 83 memset(cs, 0, sizeof(*cs)); 84 85 cs->c_buf = buf; 86 cs->c_len = buflen; 87 cs->c_next = cs->c_buf; 88 89 return 0; 90 } 91 92 /* Unpack a 64-bit unsigned integer. */ 93 int 94 cpack_uint64(struct cpack_state *cs, uint64_t *u) 95 { 96 uint8_t *next; 97 98 if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 99 return -1; 100 101 *u = EXTRACT_LE_64BITS(next); 102 103 /* Move pointer past the uint64_t. */ 104 cs->c_next = next + sizeof(*u); 105 return 0; 106 } 107 108 /* Unpack a 32-bit unsigned integer. */ 109 int 110 cpack_uint32(struct cpack_state *cs, uint32_t *u) 111 { 112 uint8_t *next; 113 114 if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 115 return -1; 116 117 *u = EXTRACT_LE_32BITS(next); 118 119 /* Move pointer past the uint32_t. */ 120 cs->c_next = next + sizeof(*u); 121 return 0; 122 } 123 124 /* Unpack a 16-bit unsigned integer. */ 125 int 126 cpack_uint16(struct cpack_state *cs, uint16_t *u) 127 { 128 uint8_t *next; 129 130 if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 131 return -1; 132 133 *u = EXTRACT_LE_16BITS(next); 134 135 /* Move pointer past the uint16_t. */ 136 cs->c_next = next + sizeof(*u); 137 return 0; 138 } 139 140 /* Unpack an 8-bit unsigned integer. */ 141 int 142 cpack_uint8(struct cpack_state *cs, uint8_t *u) 143 { 144 /* No space left? */ 145 if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len) 146 return -1; 147 148 *u = *cs->c_next; 149 150 /* Move pointer past the uint8_t. */ 151 cs->c_next++; 152 return 0; 153 } 154