1*eabc0478Schristos /* $NetBSD: buffer.c,v 1.2 2024/08/18 20:47:14 christos Exp $ */ 2897be3a4Schristos 3897be3a4Schristos /* 4897be3a4Schristos * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") 5897be3a4Schristos * Copyright (C) 1998-2002 Internet Software Consortium. 6897be3a4Schristos * 7897be3a4Schristos * Permission to use, copy, modify, and/or distribute this software for any 8897be3a4Schristos * purpose with or without fee is hereby granted, provided that the above 9897be3a4Schristos * copyright notice and this permission notice appear in all copies. 10897be3a4Schristos * 11897be3a4Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12897be3a4Schristos * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13897be3a4Schristos * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14897be3a4Schristos * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15897be3a4Schristos * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16897be3a4Schristos * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17897be3a4Schristos * PERFORMANCE OF THIS SOFTWARE. 18897be3a4Schristos */ 19897be3a4Schristos 20897be3a4Schristos /* Id: buffer.c,v 1.49 2008/09/25 04:02:39 tbox Exp */ 21897be3a4Schristos 22897be3a4Schristos /*! \file */ 23897be3a4Schristos 24897be3a4Schristos #include <config.h> 25897be3a4Schristos 26897be3a4Schristos #include <isc/buffer.h> 27897be3a4Schristos #include <isc/mem.h> 28897be3a4Schristos #include <isc/region.h> 29897be3a4Schristos #include <isc/string.h> 30897be3a4Schristos #include <isc/util.h> 31897be3a4Schristos 32897be3a4Schristos void 33897be3a4Schristos isc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length) { 34897be3a4Schristos /* 35897be3a4Schristos * Make 'b' refer to the 'length'-byte region starting at 'base'. 36897be3a4Schristos * XXXDCL see the comment in buffer.h about base being const. 37897be3a4Schristos */ 38897be3a4Schristos 39897be3a4Schristos REQUIRE(b != NULL); 40897be3a4Schristos 41897be3a4Schristos ISC__BUFFER_INIT(b, base, length); 42897be3a4Schristos } 43897be3a4Schristos 44897be3a4Schristos void 45897be3a4Schristos isc__buffer_initnull(isc_buffer_t *b) { 46897be3a4Schristos /* 47897be3a4Schristos * Initialize a new buffer which has no backing store. This can 48897be3a4Schristos * later be grown as needed and swapped in place. 49897be3a4Schristos */ 50897be3a4Schristos 51897be3a4Schristos ISC__BUFFER_INIT(b, NULL, 0); 52897be3a4Schristos } 53897be3a4Schristos 54897be3a4Schristos void 55897be3a4Schristos isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) { 56897be3a4Schristos /* 57897be3a4Schristos * Re-initialize the buffer enough to reconfigure the base of the 58897be3a4Schristos * buffer. We will swap in the new buffer, after copying any 59897be3a4Schristos * data we contain into the new buffer and adjusting all of our 60897be3a4Schristos * internal pointers. 61897be3a4Schristos * 62897be3a4Schristos * The buffer must not be smaller than the length of the original 63897be3a4Schristos * buffer. 64897be3a4Schristos */ 65897be3a4Schristos REQUIRE(b->length <= length); 66897be3a4Schristos REQUIRE(base != NULL); 67897be3a4Schristos 68897be3a4Schristos (void)memmove(base, b->base, b->length); 69897be3a4Schristos b->base = base; 70897be3a4Schristos b->length = length; 71897be3a4Schristos } 72897be3a4Schristos 73897be3a4Schristos void 74897be3a4Schristos isc__buffer_invalidate(isc_buffer_t *b) { 75897be3a4Schristos /* 76897be3a4Schristos * Make 'b' an invalid buffer. 77897be3a4Schristos */ 78897be3a4Schristos 79897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 80897be3a4Schristos REQUIRE(!ISC_LINK_LINKED(b, link)); 81897be3a4Schristos REQUIRE(b->mctx == NULL); 82897be3a4Schristos 83897be3a4Schristos ISC__BUFFER_INVALIDATE(b); 84897be3a4Schristos } 85897be3a4Schristos 86897be3a4Schristos void 87897be3a4Schristos isc__buffer_region(isc_buffer_t *b, isc_region_t *r) { 88897be3a4Schristos /* 89897be3a4Schristos * Make 'r' refer to the region of 'b'. 90897be3a4Schristos */ 91897be3a4Schristos 92897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 93897be3a4Schristos REQUIRE(r != NULL); 94897be3a4Schristos 95897be3a4Schristos ISC__BUFFER_REGION(b, r); 96897be3a4Schristos } 97897be3a4Schristos 98897be3a4Schristos void 99897be3a4Schristos isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r) { 100897be3a4Schristos /* 101897be3a4Schristos * Make 'r' refer to the used region of 'b'. 102897be3a4Schristos */ 103897be3a4Schristos 104897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 105897be3a4Schristos REQUIRE(r != NULL); 106897be3a4Schristos 107897be3a4Schristos ISC__BUFFER_USEDREGION(b, r); 108897be3a4Schristos } 109897be3a4Schristos 110897be3a4Schristos void 111897be3a4Schristos isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r) { 112897be3a4Schristos /* 113897be3a4Schristos * Make 'r' refer to the available region of 'b'. 114897be3a4Schristos */ 115897be3a4Schristos 116897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 117897be3a4Schristos REQUIRE(r != NULL); 118897be3a4Schristos 119897be3a4Schristos ISC__BUFFER_AVAILABLEREGION(b, r); 120897be3a4Schristos } 121897be3a4Schristos 122897be3a4Schristos void 123897be3a4Schristos isc__buffer_add(isc_buffer_t *b, unsigned int n) { 124897be3a4Schristos /* 125897be3a4Schristos * Increase the 'used' region of 'b' by 'n' bytes. 126897be3a4Schristos */ 127897be3a4Schristos 128897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 129897be3a4Schristos REQUIRE(b->used + n <= b->length); 130897be3a4Schristos 131897be3a4Schristos ISC__BUFFER_ADD(b, n); 132897be3a4Schristos } 133897be3a4Schristos 134897be3a4Schristos void 135897be3a4Schristos isc__buffer_subtract(isc_buffer_t *b, unsigned int n) { 136897be3a4Schristos /* 137897be3a4Schristos * Decrease the 'used' region of 'b' by 'n' bytes. 138897be3a4Schristos */ 139897be3a4Schristos 140897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 141897be3a4Schristos REQUIRE(b->used >= n); 142897be3a4Schristos 143897be3a4Schristos ISC__BUFFER_SUBTRACT(b, n); 144897be3a4Schristos } 145897be3a4Schristos 146897be3a4Schristos void 147897be3a4Schristos isc__buffer_clear(isc_buffer_t *b) { 148897be3a4Schristos /* 149897be3a4Schristos * Make the used region empty. 150897be3a4Schristos */ 151897be3a4Schristos 152897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 153897be3a4Schristos 154897be3a4Schristos ISC__BUFFER_CLEAR(b); 155897be3a4Schristos } 156897be3a4Schristos 157897be3a4Schristos void 158897be3a4Schristos isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) { 159897be3a4Schristos /* 160897be3a4Schristos * Make 'r' refer to the consumed region of 'b'. 161897be3a4Schristos */ 162897be3a4Schristos 163897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 164897be3a4Schristos REQUIRE(r != NULL); 165897be3a4Schristos 166897be3a4Schristos ISC__BUFFER_CONSUMEDREGION(b, r); 167897be3a4Schristos } 168897be3a4Schristos 169897be3a4Schristos void 170897be3a4Schristos isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) { 171897be3a4Schristos /* 172897be3a4Schristos * Make 'r' refer to the remaining region of 'b'. 173897be3a4Schristos */ 174897be3a4Schristos 175897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 176897be3a4Schristos REQUIRE(r != NULL); 177897be3a4Schristos 178897be3a4Schristos ISC__BUFFER_REMAININGREGION(b, r); 179897be3a4Schristos } 180897be3a4Schristos 181897be3a4Schristos void 182897be3a4Schristos isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r) { 183897be3a4Schristos /* 184897be3a4Schristos * Make 'r' refer to the active region of 'b'. 185897be3a4Schristos */ 186897be3a4Schristos 187897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 188897be3a4Schristos REQUIRE(r != NULL); 189897be3a4Schristos 190897be3a4Schristos ISC__BUFFER_ACTIVEREGION(b, r); 191897be3a4Schristos } 192897be3a4Schristos 193897be3a4Schristos void 194897be3a4Schristos isc__buffer_setactive(isc_buffer_t *b, unsigned int n) { 195897be3a4Schristos /* 196897be3a4Schristos * Sets the end of the active region 'n' bytes after current. 197897be3a4Schristos */ 198897be3a4Schristos 199897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 200897be3a4Schristos REQUIRE(b->current + n <= b->used); 201897be3a4Schristos 202897be3a4Schristos ISC__BUFFER_SETACTIVE(b, n); 203897be3a4Schristos } 204897be3a4Schristos 205897be3a4Schristos void 206897be3a4Schristos isc__buffer_first(isc_buffer_t *b) { 207897be3a4Schristos /* 208897be3a4Schristos * Make the consumed region empty. 209897be3a4Schristos */ 210897be3a4Schristos 211897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 212897be3a4Schristos 213897be3a4Schristos ISC__BUFFER_FIRST(b); 214897be3a4Schristos } 215897be3a4Schristos 216897be3a4Schristos void 217897be3a4Schristos isc__buffer_forward(isc_buffer_t *b, unsigned int n) { 218897be3a4Schristos /* 219897be3a4Schristos * Increase the 'consumed' region of 'b' by 'n' bytes. 220897be3a4Schristos */ 221897be3a4Schristos 222897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 223897be3a4Schristos REQUIRE(b->current + n <= b->used); 224897be3a4Schristos 225897be3a4Schristos ISC__BUFFER_FORWARD(b, n); 226897be3a4Schristos } 227897be3a4Schristos 228897be3a4Schristos void 229897be3a4Schristos isc__buffer_back(isc_buffer_t *b, unsigned int n) { 230897be3a4Schristos /* 231897be3a4Schristos * Decrease the 'consumed' region of 'b' by 'n' bytes. 232897be3a4Schristos */ 233897be3a4Schristos 234897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 235897be3a4Schristos REQUIRE(n <= b->current); 236897be3a4Schristos 237897be3a4Schristos ISC__BUFFER_BACK(b, n); 238897be3a4Schristos } 239897be3a4Schristos 240897be3a4Schristos void 241897be3a4Schristos isc_buffer_compact(isc_buffer_t *b) { 242897be3a4Schristos unsigned int length; 243897be3a4Schristos void *src; 244897be3a4Schristos 245897be3a4Schristos /* 246897be3a4Schristos * Compact the used region by moving the remaining region so it occurs 247897be3a4Schristos * at the start of the buffer. The used region is shrunk by the size 248897be3a4Schristos * of the consumed region, and the consumed region is then made empty. 249897be3a4Schristos */ 250897be3a4Schristos 251897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 252897be3a4Schristos 253897be3a4Schristos src = isc_buffer_current(b); 254897be3a4Schristos length = isc_buffer_remaininglength(b); 255897be3a4Schristos (void)memmove(b->base, src, (size_t)length); 256897be3a4Schristos 257897be3a4Schristos if (b->active > b->current) 258897be3a4Schristos b->active -= b->current; 259897be3a4Schristos else 260897be3a4Schristos b->active = 0; 261897be3a4Schristos b->current = 0; 262897be3a4Schristos b->used = length; 263897be3a4Schristos } 264897be3a4Schristos 265897be3a4Schristos isc_uint8_t 266897be3a4Schristos isc_buffer_getuint8(isc_buffer_t *b) { 267897be3a4Schristos unsigned char *cp; 268897be3a4Schristos isc_uint8_t result; 269897be3a4Schristos 270897be3a4Schristos /* 271897be3a4Schristos * Read an unsigned 8-bit integer from 'b' and return it. 272897be3a4Schristos */ 273897be3a4Schristos 274897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 275897be3a4Schristos REQUIRE(b->used - b->current >= 1); 276897be3a4Schristos 277897be3a4Schristos cp = isc_buffer_current(b); 278897be3a4Schristos b->current += 1; 279897be3a4Schristos result = ((isc_uint8_t)(cp[0])); 280897be3a4Schristos 281897be3a4Schristos return (result); 282897be3a4Schristos } 283897be3a4Schristos 284897be3a4Schristos void 285897be3a4Schristos isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val) { 286897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 287897be3a4Schristos REQUIRE(b->used + 1 <= b->length); 288897be3a4Schristos 289897be3a4Schristos ISC__BUFFER_PUTUINT8(b, val); 290897be3a4Schristos } 291897be3a4Schristos 292897be3a4Schristos isc_uint16_t 293897be3a4Schristos isc_buffer_getuint16(isc_buffer_t *b) { 294897be3a4Schristos unsigned char *cp; 295897be3a4Schristos isc_uint16_t result; 296897be3a4Schristos 297897be3a4Schristos /* 298897be3a4Schristos * Read an unsigned 16-bit integer in network byte order from 'b', 299897be3a4Schristos * convert it to host byte order, and return it. 300897be3a4Schristos */ 301897be3a4Schristos 302897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 303897be3a4Schristos REQUIRE(b->used - b->current >= 2); 304897be3a4Schristos 305897be3a4Schristos cp = isc_buffer_current(b); 306897be3a4Schristos b->current += 2; 307897be3a4Schristos result = ((unsigned int)(cp[0])) << 8; 308897be3a4Schristos result |= ((unsigned int)(cp[1])); 309897be3a4Schristos 310897be3a4Schristos return (result); 311897be3a4Schristos } 312897be3a4Schristos 313897be3a4Schristos void 314897be3a4Schristos isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val) { 315897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 316897be3a4Schristos REQUIRE(b->used + 2 <= b->length); 317897be3a4Schristos 318897be3a4Schristos ISC__BUFFER_PUTUINT16(b, val); 319897be3a4Schristos } 320897be3a4Schristos 321897be3a4Schristos void 322897be3a4Schristos isc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val) { 323897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 324897be3a4Schristos REQUIRE(b->used + 3 <= b->length); 325897be3a4Schristos 326897be3a4Schristos ISC__BUFFER_PUTUINT24(b, val); 327897be3a4Schristos } 328897be3a4Schristos 329897be3a4Schristos isc_uint32_t 330897be3a4Schristos isc_buffer_getuint32(isc_buffer_t *b) { 331897be3a4Schristos unsigned char *cp; 332897be3a4Schristos isc_uint32_t result; 333897be3a4Schristos 334897be3a4Schristos /* 335897be3a4Schristos * Read an unsigned 32-bit integer in network byte order from 'b', 336897be3a4Schristos * convert it to host byte order, and return it. 337897be3a4Schristos */ 338897be3a4Schristos 339897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 340897be3a4Schristos REQUIRE(b->used - b->current >= 4); 341897be3a4Schristos 342897be3a4Schristos cp = isc_buffer_current(b); 343897be3a4Schristos b->current += 4; 344897be3a4Schristos result = ((unsigned int)(cp[0])) << 24; 345897be3a4Schristos result |= ((unsigned int)(cp[1])) << 16; 346897be3a4Schristos result |= ((unsigned int)(cp[2])) << 8; 347897be3a4Schristos result |= ((unsigned int)(cp[3])); 348897be3a4Schristos 349897be3a4Schristos return (result); 350897be3a4Schristos } 351897be3a4Schristos 352897be3a4Schristos void 353897be3a4Schristos isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) { 354897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 355897be3a4Schristos REQUIRE(b->used + 4 <= b->length); 356897be3a4Schristos 357897be3a4Schristos ISC__BUFFER_PUTUINT32(b, val); 358897be3a4Schristos } 359897be3a4Schristos 360897be3a4Schristos isc_uint64_t 361897be3a4Schristos isc_buffer_getuint48(isc_buffer_t *b) { 362897be3a4Schristos unsigned char *cp; 363897be3a4Schristos isc_uint64_t result; 364897be3a4Schristos 365897be3a4Schristos /* 366897be3a4Schristos * Read an unsigned 48-bit integer in network byte order from 'b', 367897be3a4Schristos * convert it to host byte order, and return it. 368897be3a4Schristos */ 369897be3a4Schristos 370897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 371897be3a4Schristos REQUIRE(b->used - b->current >= 6); 372897be3a4Schristos 373897be3a4Schristos cp = isc_buffer_current(b); 374897be3a4Schristos b->current += 6; 375897be3a4Schristos result = ((isc_int64_t)(cp[0])) << 40; 376897be3a4Schristos result |= ((isc_int64_t)(cp[1])) << 32; 377897be3a4Schristos result |= ((isc_int64_t)(cp[2])) << 24; 378897be3a4Schristos result |= ((isc_int64_t)(cp[3])) << 16; 379897be3a4Schristos result |= ((isc_int64_t)(cp[4])) << 8; 380897be3a4Schristos result |= ((isc_int64_t)(cp[5])); 381897be3a4Schristos 382897be3a4Schristos return (result); 383897be3a4Schristos } 384897be3a4Schristos 385897be3a4Schristos void 386897be3a4Schristos isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) { 387897be3a4Schristos isc_uint16_t valhi; 388897be3a4Schristos isc_uint32_t vallo; 389897be3a4Schristos 390897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 391897be3a4Schristos REQUIRE(b->used + 6 <= b->length); 392897be3a4Schristos 393897be3a4Schristos valhi = (isc_uint16_t)(val >> 32); 394897be3a4Schristos vallo = (isc_uint32_t)(val & 0xFFFFFFFF); 395897be3a4Schristos ISC__BUFFER_PUTUINT16(b, valhi); 396897be3a4Schristos ISC__BUFFER_PUTUINT32(b, vallo); 397897be3a4Schristos } 398897be3a4Schristos 399897be3a4Schristos void 400897be3a4Schristos isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base, 401897be3a4Schristos unsigned int length) 402897be3a4Schristos { 403897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 404897be3a4Schristos REQUIRE(b->used + length <= b->length); 405897be3a4Schristos 406897be3a4Schristos ISC__BUFFER_PUTMEM(b, base, length); 407897be3a4Schristos } 408897be3a4Schristos 409897be3a4Schristos void 410897be3a4Schristos isc__buffer_putstr(isc_buffer_t *b, const char *source) { 411897be3a4Schristos size_t l; 412897be3a4Schristos unsigned char *cp; 413897be3a4Schristos 414897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 415897be3a4Schristos REQUIRE(source != NULL); 416897be3a4Schristos 417897be3a4Schristos /* 418897be3a4Schristos * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once. 419897be3a4Schristos */ 420897be3a4Schristos l = strlen(source); 421897be3a4Schristos 422897be3a4Schristos REQUIRE(l <= isc_buffer_availablelength(b)); 423897be3a4Schristos 424897be3a4Schristos cp = isc_buffer_used(b); 425897be3a4Schristos memcpy(cp, source, l); 426897be3a4Schristos b->used += (u_int)l; /* checked above - no overflow here */ 427897be3a4Schristos } 428897be3a4Schristos 429897be3a4Schristos isc_result_t 430897be3a4Schristos isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) { 431897be3a4Schristos unsigned char *base; 432897be3a4Schristos unsigned int available; 433897be3a4Schristos 434897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(b)); 435897be3a4Schristos REQUIRE(r != NULL); 436897be3a4Schristos 437897be3a4Schristos /* 438897be3a4Schristos * XXXDCL 439897be3a4Schristos */ 440897be3a4Schristos base = isc_buffer_used(b); 441897be3a4Schristos available = isc_buffer_availablelength(b); 442897be3a4Schristos if (r->length > available) 443897be3a4Schristos return (ISC_R_NOSPACE); 444897be3a4Schristos memcpy(base, r->base, r->length); 445897be3a4Schristos b->used += r->length; 446897be3a4Schristos 447897be3a4Schristos return (ISC_R_SUCCESS); 448897be3a4Schristos } 449897be3a4Schristos 450897be3a4Schristos isc_result_t 451897be3a4Schristos isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer, 452897be3a4Schristos unsigned int length) 453897be3a4Schristos { 454897be3a4Schristos isc_buffer_t *dbuf; 455897be3a4Schristos 456897be3a4Schristos REQUIRE(dynbuffer != NULL); 457897be3a4Schristos REQUIRE(*dynbuffer == NULL); 458897be3a4Schristos 459897be3a4Schristos dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t)); 460897be3a4Schristos if (dbuf == NULL) 461897be3a4Schristos return (ISC_R_NOMEMORY); 462897be3a4Schristos 463897be3a4Schristos isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t), 464897be3a4Schristos length); 465897be3a4Schristos dbuf->mctx = mctx; 466897be3a4Schristos 467897be3a4Schristos *dynbuffer = dbuf; 468897be3a4Schristos 469897be3a4Schristos return (ISC_R_SUCCESS); 470897be3a4Schristos } 471897be3a4Schristos 472897be3a4Schristos void 473897be3a4Schristos isc_buffer_free(isc_buffer_t **dynbuffer) { 474897be3a4Schristos unsigned int real_length; 475897be3a4Schristos isc_buffer_t *dbuf; 476897be3a4Schristos isc_mem_t *mctx; 477897be3a4Schristos 478897be3a4Schristos REQUIRE(dynbuffer != NULL); 479897be3a4Schristos REQUIRE(ISC_BUFFER_VALID(*dynbuffer)); 480897be3a4Schristos REQUIRE((*dynbuffer)->mctx != NULL); 481897be3a4Schristos 482897be3a4Schristos dbuf = *dynbuffer; 483897be3a4Schristos *dynbuffer = NULL; /* destroy external reference */ 484897be3a4Schristos 485897be3a4Schristos real_length = dbuf->length + sizeof(isc_buffer_t); 486897be3a4Schristos mctx = dbuf->mctx; 487897be3a4Schristos dbuf->mctx = NULL; 488897be3a4Schristos isc_buffer_invalidate(dbuf); 489897be3a4Schristos 490897be3a4Schristos isc_mem_put(mctx, dbuf, real_length); 491897be3a4Schristos } 492