1/* 2 * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2000, 2001 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: lwbuffer.c,v 1.15 2007/06/19 23:47:22 tbox Exp $ */ 19 20/*! \file */ 21 22/** 23 * These functions provide bounds checked access to a region of memory 24 * where data is being read or written. They are based on, and similar 25 * to, the isc_buffer_ functions in the ISC library. 26 * 27 * A buffer is a region of memory, together with a set of related 28 * subregions. The used region and the available region are disjoint, and 29 * their union is the buffer's region. The used region extends from the 30 * beginning of the buffer region to the last used byte. The available 31 * region extends from one byte greater than the last used byte to the 32 * end of the buffer's region. The size of the used region can be changed 33 * using various buffer commands. Initially, the used region is empty. 34 * 35 * The used region is further subdivided into two disjoint regions: the 36 * consumed region and the remaining region. The union of these two 37 * regions is the used region. The consumed region extends from the 38 * beginning of the used region to the byte before the current offset (if 39 * any). The remaining region the current pointer to the end of the used 40 * region. The size of the consumed region can be changed using various 41 * buffer commands. Initially, the consumed region is empty. 42 * 43 * The active region is an (optional) subregion of the remaining region. 44 * It extends from the current offset to an offset in the remaining 45 * region. Initially, the active region is empty. If the current offset 46 * advances beyond the chosen offset, the active region will also be 47 * empty. 48 * 49 * 50 * \verbatim 51 * /------------entire length---------------\\ 52 * /----- used region -----\\/-- available --\\ 53 * +----------------------------------------+ 54 * | consumed | remaining | | 55 * +----------------------------------------+ 56 * a b c d e 57 * 58 * a == base of buffer. 59 * b == current pointer. Can be anywhere between a and d. 60 * c == active pointer. Meaningful between b and d. 61 * d == used pointer. 62 * e == length of buffer. 63 * 64 * a-e == entire length of buffer. 65 * a-d == used region. 66 * a-b == consumed region. 67 * b-d == remaining region. 68 * b-c == optional active region. 69 * \endverbatim 70 * 71 * lwres_buffer_init() initializes the lwres_buffer_t *b and assocates it 72 * with the memory region of size length bytes starting at location base. 73 * 74 * lwres_buffer_invalidate() marks the buffer *b as invalid. Invalidating 75 * a buffer after use is not required, but makes it possible to catch its 76 * possible accidental use. 77 * 78 * The functions lwres_buffer_add() and lwres_buffer_subtract() 79 * respectively increase and decrease the used space in buffer *b by n 80 * bytes. lwres_buffer_add() checks for buffer overflow and 81 * lwres_buffer_subtract() checks for underflow. These functions do not 82 * allocate or deallocate memory. They just change the value of used. 83 * 84 * A buffer is re-initialised by lwres_buffer_clear(). The function sets 85 * used , current and active to zero. 86 * 87 * lwres_buffer_first() makes the consumed region of buffer *p empty by 88 * setting current to zero (the start of the buffer). 89 * 90 * lwres_buffer_forward() increases the consumed region of buffer *b by n 91 * bytes, checking for overflow. Similarly, lwres_buffer_back() decreases 92 * buffer b's consumed region by n bytes and checks for underflow. 93 * 94 * lwres_buffer_getuint8() reads an unsigned 8-bit integer from *b and 95 * returns it. lwres_buffer_putuint8() writes the unsigned 8-bit integer 96 * val to buffer *b. 97 * 98 * lwres_buffer_getuint16() and lwres_buffer_getuint32() are identical to 99 * lwres_buffer_putuint8() except that they respectively read an unsigned 100 * 16-bit or 32-bit integer in network byte order from b. Similarly, 101 * lwres_buffer_putuint16() and lwres_buffer_putuint32() writes the 102 * unsigned 16-bit or 32-bit integer val to buffer b, in network byte 103 * order. 104 * 105 * Arbitrary amounts of data are read or written from a lightweight 106 * resolver buffer with lwres_buffer_getmem() and lwres_buffer_putmem() 107 * respectively. lwres_buffer_putmem() copies length bytes of memory at 108 * base to b. Conversely, lwres_buffer_getmem() copies length bytes of 109 * memory from b to base. 110 */ 111 112#include <config.h> 113 114#include <string.h> 115 116#include <lwres/lwbuffer.h> 117 118#include "assert_p.h" 119 120void 121lwres_buffer_init(lwres_buffer_t *b, void *base, unsigned int length) 122{ 123 /* 124 * Make 'b' refer to the 'length'-byte region starting at base. 125 */ 126 127 REQUIRE(b != NULL); 128 129 b->magic = LWRES_BUFFER_MAGIC; 130 b->base = base; 131 b->length = length; 132 b->used = 0; 133 b->current = 0; 134 b->active = 0; 135} 136 137/* Make 'b' an invalid buffer. */ 138void 139lwres_buffer_invalidate(lwres_buffer_t *b) 140{ 141 142 REQUIRE(LWRES_BUFFER_VALID(b)); 143 144 b->magic = 0; 145 b->base = NULL; 146 b->length = 0; 147 b->used = 0; 148 b->current = 0; 149 b->active = 0; 150} 151 152/* Increase the 'used' region of 'b' by 'n' bytes. */ 153void 154lwres_buffer_add(lwres_buffer_t *b, unsigned int n) 155{ 156 157 REQUIRE(LWRES_BUFFER_VALID(b)); 158 REQUIRE(b->used + n <= b->length); 159 160 b->used += n; 161} 162 163/* Decrease the 'used' region of 'b' by 'n' bytes. */ 164void 165lwres_buffer_subtract(lwres_buffer_t *b, unsigned int n) 166{ 167 168 REQUIRE(LWRES_BUFFER_VALID(b)); 169 REQUIRE(b->used >= n); 170 171 b->used -= n; 172 if (b->current > b->used) 173 b->current = b->used; 174 if (b->active > b->used) 175 b->active = b->used; 176} 177 178/* Make the used region empty. */ 179void 180lwres_buffer_clear(lwres_buffer_t *b) 181{ 182 183 REQUIRE(LWRES_BUFFER_VALID(b)); 184 185 b->used = 0; 186 b->current = 0; 187 b->active = 0; 188} 189 190/* Make the consumed region empty. */ 191void 192lwres_buffer_first(lwres_buffer_t *b) 193{ 194 195 REQUIRE(LWRES_BUFFER_VALID(b)); 196 197 b->current = 0; 198} 199 200/* Increase the 'consumed' region of 'b' by 'n' bytes. */ 201void 202lwres_buffer_forward(lwres_buffer_t *b, unsigned int n) 203{ 204 205 REQUIRE(LWRES_BUFFER_VALID(b)); 206 REQUIRE(b->current + n <= b->used); 207 208 b->current += n; 209} 210 211/* Decrease the 'consumed' region of 'b' by 'n' bytes. */ 212void 213lwres_buffer_back(lwres_buffer_t *b, unsigned int n) 214{ 215 216 REQUIRE(LWRES_BUFFER_VALID(b)); 217 REQUIRE(n <= b->current); 218 219 b->current -= n; 220} 221 222/* Read an unsigned 8-bit integer from 'b' and return it. */ 223lwres_uint8_t 224lwres_buffer_getuint8(lwres_buffer_t *b) 225{ 226 unsigned char *cp; 227 lwres_uint8_t result; 228 229 230 REQUIRE(LWRES_BUFFER_VALID(b)); 231 REQUIRE(b->used - b->current >= 1); 232 233 cp = b->base; 234 cp += b->current; 235 b->current += 1; 236 result = ((unsigned int)(cp[0])); 237 238 return (result); 239} 240 241/* Put an unsigned 8-bit integer */ 242void 243lwres_buffer_putuint8(lwres_buffer_t *b, lwres_uint8_t val) 244{ 245 unsigned char *cp; 246 247 REQUIRE(LWRES_BUFFER_VALID(b)); 248 REQUIRE(b->used + 1 <= b->length); 249 250 cp = b->base; 251 cp += b->used; 252 b->used += 1; 253 cp[0] = (val & 0x00ff); 254} 255 256/* Read an unsigned 16-bit integer in network byte order from 'b', convert it to host byte order, and return it. */ 257lwres_uint16_t 258lwres_buffer_getuint16(lwres_buffer_t *b) 259{ 260 unsigned char *cp; 261 lwres_uint16_t result; 262 263 264 REQUIRE(LWRES_BUFFER_VALID(b)); 265 REQUIRE(b->used - b->current >= 2); 266 267 cp = b->base; 268 cp += b->current; 269 b->current += 2; 270 result = ((unsigned int)(cp[0])) << 8; 271 result |= ((unsigned int)(cp[1])); 272 273 return (result); 274} 275 276/* Put an unsigned 16-bit integer. */ 277void 278lwres_buffer_putuint16(lwres_buffer_t *b, lwres_uint16_t val) 279{ 280 unsigned char *cp; 281 282 REQUIRE(LWRES_BUFFER_VALID(b)); 283 REQUIRE(b->used + 2 <= b->length); 284 285 cp = b->base; 286 cp += b->used; 287 b->used += 2; 288 cp[0] = (val & 0xff00) >> 8; 289 cp[1] = (val & 0x00ff); 290} 291 292/* Read an unsigned 32-bit integer in network byte order from 'b', convert it to host byte order, and return it. */ 293lwres_uint32_t 294lwres_buffer_getuint32(lwres_buffer_t *b) 295{ 296 unsigned char *cp; 297 lwres_uint32_t result; 298 299 REQUIRE(LWRES_BUFFER_VALID(b)); 300 REQUIRE(b->used - b->current >= 4); 301 302 cp = b->base; 303 cp += b->current; 304 b->current += 4; 305 result = ((unsigned int)(cp[0])) << 24; 306 result |= ((unsigned int)(cp[1])) << 16; 307 result |= ((unsigned int)(cp[2])) << 8; 308 result |= ((unsigned int)(cp[3])); 309 310 return (result); 311} 312 313/* Put an unsigned 32-bit integer. */ 314void 315lwres_buffer_putuint32(lwres_buffer_t *b, lwres_uint32_t val) 316{ 317 unsigned char *cp; 318 319 REQUIRE(LWRES_BUFFER_VALID(b)); 320 REQUIRE(b->used + 4 <= b->length); 321 322 cp = b->base; 323 cp += b->used; 324 b->used += 4; 325 cp[0] = (unsigned char)((val & 0xff000000) >> 24); 326 cp[1] = (unsigned char)((val & 0x00ff0000) >> 16); 327 cp[2] = (unsigned char)((val & 0x0000ff00) >> 8); 328 cp[3] = (unsigned char)(val & 0x000000ff); 329} 330 331/* copies length bytes of memory at base to b */ 332void 333lwres_buffer_putmem(lwres_buffer_t *b, const unsigned char *base, 334 unsigned int length) 335{ 336 unsigned char *cp; 337 338 REQUIRE(LWRES_BUFFER_VALID(b)); 339 REQUIRE(b->used + length <= b->length); 340 341 cp = (unsigned char *)b->base + b->used; 342 memcpy(cp, base, length); 343 b->used += length; 344} 345 346/* copies length bytes of memory at b to base */ 347void 348lwres_buffer_getmem(lwres_buffer_t *b, unsigned char *base, 349 unsigned int length) 350{ 351 unsigned char *cp; 352 353 REQUIRE(LWRES_BUFFER_VALID(b)); 354 REQUIRE(b->used - b->current >= length); 355 356 cp = b->base; 357 cp += b->current; 358 b->current += length; 359 360 memcpy(base, cp, length); 361} 362