1258945Sroberto/* 2258945Sroberto * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") 3258945Sroberto * Copyright (C) 1998-2002 Internet Software Consortium. 4258945Sroberto * 5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any 6258945Sroberto * purpose with or without fee is hereby granted, provided that the above 7258945Sroberto * copyright notice and this permission notice appear in all copies. 8258945Sroberto * 9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11258945Sroberto * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15258945Sroberto * PERFORMANCE OF THIS SOFTWARE. 16258945Sroberto */ 17258945Sroberto 18258945Sroberto/* $Id: buffer.c,v 1.49 2008/09/25 04:02:39 tbox Exp $ */ 19258945Sroberto 20258945Sroberto/*! \file */ 21258945Sroberto 22258945Sroberto#include <config.h> 23258945Sroberto 24258945Sroberto#include <isc/buffer.h> 25258945Sroberto#include <isc/mem.h> 26258945Sroberto#include <isc/region.h> 27258945Sroberto#include <isc/string.h> 28258945Sroberto#include <isc/util.h> 29258945Sroberto 30258945Srobertovoid 31258945Srobertoisc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length) { 32258945Sroberto /* 33258945Sroberto * Make 'b' refer to the 'length'-byte region starting at 'base'. 34258945Sroberto * XXXDCL see the comment in buffer.h about base being const. 35258945Sroberto */ 36258945Sroberto 37258945Sroberto REQUIRE(b != NULL); 38258945Sroberto 39258945Sroberto ISC__BUFFER_INIT(b, base, length); 40258945Sroberto} 41258945Sroberto 42258945Srobertovoid 43258945Srobertoisc__buffer_initnull(isc_buffer_t *b) { 44258945Sroberto /* 45258945Sroberto * Initialize a new buffer which has no backing store. This can 46258945Sroberto * later be grown as needed and swapped in place. 47258945Sroberto */ 48258945Sroberto 49258945Sroberto ISC__BUFFER_INIT(b, NULL, 0); 50258945Sroberto} 51258945Sroberto 52258945Srobertovoid 53258945Srobertoisc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) { 54258945Sroberto /* 55258945Sroberto * Re-initialize the buffer enough to reconfigure the base of the 56258945Sroberto * buffer. We will swap in the new buffer, after copying any 57258945Sroberto * data we contain into the new buffer and adjusting all of our 58258945Sroberto * internal pointers. 59258945Sroberto * 60258945Sroberto * The buffer must not be smaller than the length of the original 61258945Sroberto * buffer. 62258945Sroberto */ 63258945Sroberto REQUIRE(b->length <= length); 64258945Sroberto REQUIRE(base != NULL); 65258945Sroberto 66258945Sroberto (void)memmove(base, b->base, b->length); 67258945Sroberto b->base = base; 68258945Sroberto b->length = length; 69258945Sroberto} 70258945Sroberto 71258945Srobertovoid 72258945Srobertoisc__buffer_invalidate(isc_buffer_t *b) { 73258945Sroberto /* 74258945Sroberto * Make 'b' an invalid buffer. 75258945Sroberto */ 76258945Sroberto 77258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 78258945Sroberto REQUIRE(!ISC_LINK_LINKED(b, link)); 79258945Sroberto REQUIRE(b->mctx == NULL); 80258945Sroberto 81258945Sroberto ISC__BUFFER_INVALIDATE(b); 82258945Sroberto} 83258945Sroberto 84258945Srobertovoid 85258945Srobertoisc__buffer_region(isc_buffer_t *b, isc_region_t *r) { 86258945Sroberto /* 87258945Sroberto * Make 'r' refer to the region of 'b'. 88258945Sroberto */ 89258945Sroberto 90258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 91258945Sroberto REQUIRE(r != NULL); 92258945Sroberto 93258945Sroberto ISC__BUFFER_REGION(b, r); 94258945Sroberto} 95258945Sroberto 96258945Srobertovoid 97258945Srobertoisc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r) { 98258945Sroberto /* 99258945Sroberto * Make 'r' refer to the used region of 'b'. 100258945Sroberto */ 101258945Sroberto 102258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 103258945Sroberto REQUIRE(r != NULL); 104258945Sroberto 105258945Sroberto ISC__BUFFER_USEDREGION(b, r); 106258945Sroberto} 107258945Sroberto 108258945Srobertovoid 109258945Srobertoisc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r) { 110258945Sroberto /* 111258945Sroberto * Make 'r' refer to the available region of 'b'. 112258945Sroberto */ 113258945Sroberto 114258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 115258945Sroberto REQUIRE(r != NULL); 116258945Sroberto 117258945Sroberto ISC__BUFFER_AVAILABLEREGION(b, r); 118258945Sroberto} 119258945Sroberto 120258945Srobertovoid 121258945Srobertoisc__buffer_add(isc_buffer_t *b, unsigned int n) { 122258945Sroberto /* 123258945Sroberto * Increase the 'used' region of 'b' by 'n' bytes. 124258945Sroberto */ 125258945Sroberto 126258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 127258945Sroberto REQUIRE(b->used + n <= b->length); 128258945Sroberto 129258945Sroberto ISC__BUFFER_ADD(b, n); 130258945Sroberto} 131258945Sroberto 132258945Srobertovoid 133258945Srobertoisc__buffer_subtract(isc_buffer_t *b, unsigned int n) { 134258945Sroberto /* 135258945Sroberto * Decrease the 'used' region of 'b' by 'n' bytes. 136258945Sroberto */ 137258945Sroberto 138258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 139258945Sroberto REQUIRE(b->used >= n); 140258945Sroberto 141258945Sroberto ISC__BUFFER_SUBTRACT(b, n); 142258945Sroberto} 143258945Sroberto 144258945Srobertovoid 145258945Srobertoisc__buffer_clear(isc_buffer_t *b) { 146258945Sroberto /* 147258945Sroberto * Make the used region empty. 148258945Sroberto */ 149258945Sroberto 150258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 151258945Sroberto 152258945Sroberto ISC__BUFFER_CLEAR(b); 153258945Sroberto} 154258945Sroberto 155258945Srobertovoid 156258945Srobertoisc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) { 157258945Sroberto /* 158258945Sroberto * Make 'r' refer to the consumed region of 'b'. 159258945Sroberto */ 160258945Sroberto 161258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 162258945Sroberto REQUIRE(r != NULL); 163258945Sroberto 164258945Sroberto ISC__BUFFER_CONSUMEDREGION(b, r); 165258945Sroberto} 166258945Sroberto 167258945Srobertovoid 168258945Srobertoisc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) { 169258945Sroberto /* 170258945Sroberto * Make 'r' refer to the remaining region of 'b'. 171258945Sroberto */ 172258945Sroberto 173258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 174258945Sroberto REQUIRE(r != NULL); 175258945Sroberto 176258945Sroberto ISC__BUFFER_REMAININGREGION(b, r); 177258945Sroberto} 178258945Sroberto 179258945Srobertovoid 180258945Srobertoisc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r) { 181258945Sroberto /* 182258945Sroberto * Make 'r' refer to the active region of 'b'. 183258945Sroberto */ 184258945Sroberto 185258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 186258945Sroberto REQUIRE(r != NULL); 187258945Sroberto 188258945Sroberto ISC__BUFFER_ACTIVEREGION(b, r); 189258945Sroberto} 190258945Sroberto 191258945Srobertovoid 192258945Srobertoisc__buffer_setactive(isc_buffer_t *b, unsigned int n) { 193258945Sroberto /* 194258945Sroberto * Sets the end of the active region 'n' bytes after current. 195258945Sroberto */ 196258945Sroberto 197258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 198258945Sroberto REQUIRE(b->current + n <= b->used); 199258945Sroberto 200258945Sroberto ISC__BUFFER_SETACTIVE(b, n); 201258945Sroberto} 202258945Sroberto 203258945Srobertovoid 204258945Srobertoisc__buffer_first(isc_buffer_t *b) { 205258945Sroberto /* 206258945Sroberto * Make the consumed region empty. 207258945Sroberto */ 208258945Sroberto 209258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 210258945Sroberto 211258945Sroberto ISC__BUFFER_FIRST(b); 212258945Sroberto} 213258945Sroberto 214258945Srobertovoid 215258945Srobertoisc__buffer_forward(isc_buffer_t *b, unsigned int n) { 216258945Sroberto /* 217258945Sroberto * Increase the 'consumed' region of 'b' by 'n' bytes. 218258945Sroberto */ 219258945Sroberto 220258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 221258945Sroberto REQUIRE(b->current + n <= b->used); 222258945Sroberto 223258945Sroberto ISC__BUFFER_FORWARD(b, n); 224258945Sroberto} 225258945Sroberto 226258945Srobertovoid 227258945Srobertoisc__buffer_back(isc_buffer_t *b, unsigned int n) { 228258945Sroberto /* 229258945Sroberto * Decrease the 'consumed' region of 'b' by 'n' bytes. 230258945Sroberto */ 231258945Sroberto 232258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 233258945Sroberto REQUIRE(n <= b->current); 234258945Sroberto 235258945Sroberto ISC__BUFFER_BACK(b, n); 236258945Sroberto} 237258945Sroberto 238258945Srobertovoid 239258945Srobertoisc_buffer_compact(isc_buffer_t *b) { 240258945Sroberto unsigned int length; 241258945Sroberto void *src; 242258945Sroberto 243258945Sroberto /* 244258945Sroberto * Compact the used region by moving the remaining region so it occurs 245258945Sroberto * at the start of the buffer. The used region is shrunk by the size 246258945Sroberto * of the consumed region, and the consumed region is then made empty. 247258945Sroberto */ 248258945Sroberto 249258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 250258945Sroberto 251258945Sroberto src = isc_buffer_current(b); 252258945Sroberto length = isc_buffer_remaininglength(b); 253258945Sroberto (void)memmove(b->base, src, (size_t)length); 254258945Sroberto 255258945Sroberto if (b->active > b->current) 256258945Sroberto b->active -= b->current; 257258945Sroberto else 258258945Sroberto b->active = 0; 259258945Sroberto b->current = 0; 260258945Sroberto b->used = length; 261258945Sroberto} 262258945Sroberto 263258945Srobertoisc_uint8_t 264258945Srobertoisc_buffer_getuint8(isc_buffer_t *b) { 265258945Sroberto unsigned char *cp; 266258945Sroberto isc_uint8_t result; 267258945Sroberto 268258945Sroberto /* 269258945Sroberto * Read an unsigned 8-bit integer from 'b' and return it. 270258945Sroberto */ 271258945Sroberto 272258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 273258945Sroberto REQUIRE(b->used - b->current >= 1); 274258945Sroberto 275258945Sroberto cp = isc_buffer_current(b); 276258945Sroberto b->current += 1; 277258945Sroberto result = ((isc_uint8_t)(cp[0])); 278258945Sroberto 279258945Sroberto return (result); 280258945Sroberto} 281258945Sroberto 282258945Srobertovoid 283258945Srobertoisc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val) { 284258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 285258945Sroberto REQUIRE(b->used + 1 <= b->length); 286258945Sroberto 287258945Sroberto ISC__BUFFER_PUTUINT8(b, val); 288258945Sroberto} 289258945Sroberto 290258945Srobertoisc_uint16_t 291258945Srobertoisc_buffer_getuint16(isc_buffer_t *b) { 292258945Sroberto unsigned char *cp; 293258945Sroberto isc_uint16_t result; 294258945Sroberto 295258945Sroberto /* 296258945Sroberto * Read an unsigned 16-bit integer in network byte order from 'b', 297258945Sroberto * convert it to host byte order, and return it. 298258945Sroberto */ 299258945Sroberto 300258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 301258945Sroberto REQUIRE(b->used - b->current >= 2); 302258945Sroberto 303258945Sroberto cp = isc_buffer_current(b); 304258945Sroberto b->current += 2; 305258945Sroberto result = ((unsigned int)(cp[0])) << 8; 306258945Sroberto result |= ((unsigned int)(cp[1])); 307258945Sroberto 308258945Sroberto return (result); 309258945Sroberto} 310258945Sroberto 311258945Srobertovoid 312258945Srobertoisc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val) { 313258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 314258945Sroberto REQUIRE(b->used + 2 <= b->length); 315258945Sroberto 316258945Sroberto ISC__BUFFER_PUTUINT16(b, val); 317258945Sroberto} 318258945Sroberto 319258945Srobertovoid 320258945Srobertoisc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val) { 321258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 322258945Sroberto REQUIRE(b->used + 3 <= b->length); 323258945Sroberto 324258945Sroberto ISC__BUFFER_PUTUINT24(b, val); 325258945Sroberto} 326258945Sroberto 327258945Srobertoisc_uint32_t 328258945Srobertoisc_buffer_getuint32(isc_buffer_t *b) { 329258945Sroberto unsigned char *cp; 330258945Sroberto isc_uint32_t result; 331258945Sroberto 332258945Sroberto /* 333258945Sroberto * Read an unsigned 32-bit integer in network byte order from 'b', 334258945Sroberto * convert it to host byte order, and return it. 335258945Sroberto */ 336258945Sroberto 337258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 338258945Sroberto REQUIRE(b->used - b->current >= 4); 339258945Sroberto 340258945Sroberto cp = isc_buffer_current(b); 341258945Sroberto b->current += 4; 342258945Sroberto result = ((unsigned int)(cp[0])) << 24; 343258945Sroberto result |= ((unsigned int)(cp[1])) << 16; 344258945Sroberto result |= ((unsigned int)(cp[2])) << 8; 345258945Sroberto result |= ((unsigned int)(cp[3])); 346258945Sroberto 347258945Sroberto return (result); 348258945Sroberto} 349258945Sroberto 350258945Srobertovoid 351258945Srobertoisc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) { 352258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 353258945Sroberto REQUIRE(b->used + 4 <= b->length); 354258945Sroberto 355258945Sroberto ISC__BUFFER_PUTUINT32(b, val); 356258945Sroberto} 357258945Sroberto 358258945Srobertoisc_uint64_t 359258945Srobertoisc_buffer_getuint48(isc_buffer_t *b) { 360258945Sroberto unsigned char *cp; 361258945Sroberto isc_uint64_t result; 362258945Sroberto 363258945Sroberto /* 364258945Sroberto * Read an unsigned 48-bit integer in network byte order from 'b', 365258945Sroberto * convert it to host byte order, and return it. 366258945Sroberto */ 367258945Sroberto 368258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 369258945Sroberto REQUIRE(b->used - b->current >= 6); 370258945Sroberto 371258945Sroberto cp = isc_buffer_current(b); 372258945Sroberto b->current += 6; 373258945Sroberto result = ((isc_int64_t)(cp[0])) << 40; 374258945Sroberto result |= ((isc_int64_t)(cp[1])) << 32; 375258945Sroberto result |= ((isc_int64_t)(cp[2])) << 24; 376258945Sroberto result |= ((isc_int64_t)(cp[3])) << 16; 377258945Sroberto result |= ((isc_int64_t)(cp[4])) << 8; 378258945Sroberto result |= ((isc_int64_t)(cp[5])); 379258945Sroberto 380258945Sroberto return (result); 381258945Sroberto} 382258945Sroberto 383258945Srobertovoid 384258945Srobertoisc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) { 385258945Sroberto isc_uint16_t valhi; 386258945Sroberto isc_uint32_t vallo; 387258945Sroberto 388258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 389258945Sroberto REQUIRE(b->used + 6 <= b->length); 390258945Sroberto 391258945Sroberto valhi = (isc_uint16_t)(val >> 32); 392258945Sroberto vallo = (isc_uint32_t)(val & 0xFFFFFFFF); 393258945Sroberto ISC__BUFFER_PUTUINT16(b, valhi); 394258945Sroberto ISC__BUFFER_PUTUINT32(b, vallo); 395258945Sroberto} 396258945Sroberto 397258945Srobertovoid 398258945Srobertoisc__buffer_putmem(isc_buffer_t *b, const unsigned char *base, 399258945Sroberto unsigned int length) 400258945Sroberto{ 401258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 402258945Sroberto REQUIRE(b->used + length <= b->length); 403258945Sroberto 404258945Sroberto ISC__BUFFER_PUTMEM(b, base, length); 405258945Sroberto} 406258945Sroberto 407258945Srobertovoid 408258945Srobertoisc__buffer_putstr(isc_buffer_t *b, const char *source) { 409293893Sglebius size_t l; 410258945Sroberto unsigned char *cp; 411258945Sroberto 412258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 413258945Sroberto REQUIRE(source != NULL); 414258945Sroberto 415258945Sroberto /* 416258945Sroberto * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once. 417258945Sroberto */ 418258945Sroberto l = strlen(source); 419258945Sroberto 420258945Sroberto REQUIRE(l <= isc_buffer_availablelength(b)); 421258945Sroberto 422258945Sroberto cp = isc_buffer_used(b); 423258945Sroberto memcpy(cp, source, l); 424293893Sglebius b->used += (u_int)l; /* checked above - no overflow here */ 425258945Sroberto} 426258945Sroberto 427258945Srobertoisc_result_t 428258945Srobertoisc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) { 429258945Sroberto unsigned char *base; 430258945Sroberto unsigned int available; 431258945Sroberto 432258945Sroberto REQUIRE(ISC_BUFFER_VALID(b)); 433258945Sroberto REQUIRE(r != NULL); 434258945Sroberto 435258945Sroberto /* 436258945Sroberto * XXXDCL 437258945Sroberto */ 438258945Sroberto base = isc_buffer_used(b); 439258945Sroberto available = isc_buffer_availablelength(b); 440258945Sroberto if (r->length > available) 441258945Sroberto return (ISC_R_NOSPACE); 442258945Sroberto memcpy(base, r->base, r->length); 443258945Sroberto b->used += r->length; 444258945Sroberto 445258945Sroberto return (ISC_R_SUCCESS); 446258945Sroberto} 447258945Sroberto 448258945Srobertoisc_result_t 449258945Srobertoisc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer, 450258945Sroberto unsigned int length) 451258945Sroberto{ 452258945Sroberto isc_buffer_t *dbuf; 453258945Sroberto 454258945Sroberto REQUIRE(dynbuffer != NULL); 455258945Sroberto REQUIRE(*dynbuffer == NULL); 456258945Sroberto 457258945Sroberto dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t)); 458258945Sroberto if (dbuf == NULL) 459258945Sroberto return (ISC_R_NOMEMORY); 460258945Sroberto 461258945Sroberto isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t), 462258945Sroberto length); 463258945Sroberto dbuf->mctx = mctx; 464258945Sroberto 465258945Sroberto *dynbuffer = dbuf; 466258945Sroberto 467258945Sroberto return (ISC_R_SUCCESS); 468258945Sroberto} 469258945Sroberto 470258945Srobertovoid 471258945Srobertoisc_buffer_free(isc_buffer_t **dynbuffer) { 472258945Sroberto unsigned int real_length; 473258945Sroberto isc_buffer_t *dbuf; 474258945Sroberto isc_mem_t *mctx; 475258945Sroberto 476258945Sroberto REQUIRE(dynbuffer != NULL); 477258945Sroberto REQUIRE(ISC_BUFFER_VALID(*dynbuffer)); 478258945Sroberto REQUIRE((*dynbuffer)->mctx != NULL); 479258945Sroberto 480258945Sroberto dbuf = *dynbuffer; 481258945Sroberto *dynbuffer = NULL; /* destroy external reference */ 482258945Sroberto 483258945Sroberto real_length = dbuf->length + sizeof(isc_buffer_t); 484258945Sroberto mctx = dbuf->mctx; 485258945Sroberto dbuf->mctx = NULL; 486258945Sroberto isc_buffer_invalidate(dbuf); 487258945Sroberto 488258945Sroberto isc_mem_put(mctx, dbuf, real_length); 489258945Sroberto} 490