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 static 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 static 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 int 69 cpack_init(struct cpack_state *cs, u_int8_t *buf, size_t buflen) 70 { 71 memset(cs, 0, sizeof(*cs)); 72 73 cs->c_buf = buf; 74 cs->c_len = buflen; 75 cs->c_next = cs->c_buf; 76 77 return 0; 78 } 79 80 /* Unpack a 64-bit unsigned integer. */ 81 int 82 cpack_uint64(struct cpack_state *cs, u_int64_t *u) 83 { 84 u_int8_t *next; 85 86 if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 87 return -1; 88 89 *u = EXTRACT_LE_64BITS(next); 90 91 /* Move pointer past the u_int64_t. */ 92 cs->c_next = next + sizeof(*u); 93 return 0; 94 } 95 96 /* Unpack a 32-bit unsigned integer. */ 97 int 98 cpack_uint32(struct cpack_state *cs, u_int32_t *u) 99 { 100 u_int8_t *next; 101 102 if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 103 return -1; 104 105 *u = EXTRACT_LE_32BITS(next); 106 107 /* Move pointer past the u_int32_t. */ 108 cs->c_next = next + sizeof(*u); 109 return 0; 110 } 111 112 /* Unpack a 16-bit unsigned integer. */ 113 int 114 cpack_uint16(struct cpack_state *cs, u_int16_t *u) 115 { 116 u_int8_t *next; 117 118 if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL) 119 return -1; 120 121 *u = EXTRACT_LE_16BITS(next); 122 123 /* Move pointer past the u_int16_t. */ 124 cs->c_next = next + sizeof(*u); 125 return 0; 126 } 127 128 /* Unpack an 8-bit unsigned integer. */ 129 int 130 cpack_uint8(struct cpack_state *cs, u_int8_t *u) 131 { 132 /* No space left? */ 133 if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len) 134 return -1; 135 136 *u = *cs->c_next; 137 138 /* Move pointer past the u_int8_t. */ 139 cs->c_next++; 140 return 0; 141 } 142