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 #ifdef HAVE_CONFIG_H 28 #include "config.h" 29 #endif 30 31 #include <stdlib.h> 32 #include <string.h> 33 #include <tcpdump-stdinc.h> 34 35 #include "cpack.h" 36 #include "extract.h" 37 38 u_int8_t * 39 cpack_next_boundary(u_int8_t *buf, u_int8_t *p, size_t alignment) 40 { 41 size_t misalignment = (size_t)(p - buf) % alignment; 42 43 if (misalignment == 0) 44 return p; 45 46 return p + (alignment - misalignment); 47 } 48 49 /* Advance to the next wordsize boundary. Return NULL if fewer than 50 * wordsize bytes remain in the buffer after the boundary. Otherwise, 51 * return a pointer to the boundary. 52 */ 53 u_int8_t * 54 cpack_align_and_reserve(struct cpack_state *cs, size_t wordsize) 55 { 56 u_int8_t *next; 57 58 /* Ensure alignment. */ 59 next = cpack_next_boundary(cs->c_buf, cs->c_next, wordsize); 60 61 /* Too little space for wordsize bytes? */ 62 if (next - cs->c_buf + wordsize > cs->c_len) 63 return NULL; 64 65 return next; 66 } 67 68 /* Advance by N bytes without returning them. */ 69 int 70 cpack_advance(struct cpack_state *cs, const size_t toskip) 71 { 72 /* No space left? */ 73 if (cs->c_next - cs->c_buf + toskip > cs->c_len) 74 return -1; 75 cs->c_next += toskip; 76 return 0; 77 } 78 79 int 80 cpack_init(struct cpack_state *cs, u_int8_t *buf, size_t buflen) 81 { 82 memset(cs, 0, sizeof(*cs)); 83 84 cs->c_buf = buf; 85 cs->c_len = buflen; 86 cs->c_next = cs->c_buf; 87 88 return 0; 89 } 90 91 /* Unpack a 64-bit unsigned integer. */ 92 int 93 cpack_uint64(struct cpack_state *cs, u_int64_t *u) 94 { 95 u_int8_t *next; 96 97 if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 98 return -1; 99 100 *u = EXTRACT_LE_64BITS(next); 101 102 /* Move pointer past the u_int64_t. */ 103 cs->c_next = next + sizeof(*u); 104 return 0; 105 } 106 107 /* Unpack a 32-bit unsigned integer. */ 108 int 109 cpack_uint32(struct cpack_state *cs, u_int32_t *u) 110 { 111 u_int8_t *next; 112 113 if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 114 return -1; 115 116 *u = EXTRACT_LE_32BITS(next); 117 118 /* Move pointer past the u_int32_t. */ 119 cs->c_next = next + sizeof(*u); 120 return 0; 121 } 122 123 /* Unpack a 16-bit unsigned integer. */ 124 int 125 cpack_uint16(struct cpack_state *cs, u_int16_t *u) 126 { 127 u_int8_t *next; 128 129 if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 130 return -1; 131 132 *u = EXTRACT_LE_16BITS(next); 133 134 /* Move pointer past the u_int16_t. */ 135 cs->c_next = next + sizeof(*u); 136 return 0; 137 } 138 139 /* Unpack an 8-bit unsigned integer. */ 140 int 141 cpack_uint8(struct cpack_state *cs, u_int8_t *u) 142 { 143 /* No space left? */ 144 if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len) 145 return -1; 146 147 *u = *cs->c_next; 148 149 /* Move pointer past the u_int8_t. */ 150 cs->c_next++; 151 return 0; 152 } 153