1/* $NetBSD: buffer.c,v 1.2 2024/08/18 20:47:14 christos Exp $ */ 2 3/* 4 * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 1998-2002 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20/* Id: buffer.c,v 1.49 2008/09/25 04:02:39 tbox Exp */ 21 22/*! \file */ 23 24#include <config.h> 25 26#include <isc/buffer.h> 27#include <isc/mem.h> 28#include <isc/region.h> 29#include <isc/string.h> 30#include <isc/util.h> 31 32void 33isc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length) { 34 /* 35 * Make 'b' refer to the 'length'-byte region starting at 'base'. 36 * XXXDCL see the comment in buffer.h about base being const. 37 */ 38 39 REQUIRE(b != NULL); 40 41 ISC__BUFFER_INIT(b, base, length); 42} 43 44void 45isc__buffer_initnull(isc_buffer_t *b) { 46 /* 47 * Initialize a new buffer which has no backing store. This can 48 * later be grown as needed and swapped in place. 49 */ 50 51 ISC__BUFFER_INIT(b, NULL, 0); 52} 53 54void 55isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) { 56 /* 57 * Re-initialize the buffer enough to reconfigure the base of the 58 * buffer. We will swap in the new buffer, after copying any 59 * data we contain into the new buffer and adjusting all of our 60 * internal pointers. 61 * 62 * The buffer must not be smaller than the length of the original 63 * buffer. 64 */ 65 REQUIRE(b->length <= length); 66 REQUIRE(base != NULL); 67 68 (void)memmove(base, b->base, b->length); 69 b->base = base; 70 b->length = length; 71} 72 73void 74isc__buffer_invalidate(isc_buffer_t *b) { 75 /* 76 * Make 'b' an invalid buffer. 77 */ 78 79 REQUIRE(ISC_BUFFER_VALID(b)); 80 REQUIRE(!ISC_LINK_LINKED(b, link)); 81 REQUIRE(b->mctx == NULL); 82 83 ISC__BUFFER_INVALIDATE(b); 84} 85 86void 87isc__buffer_region(isc_buffer_t *b, isc_region_t *r) { 88 /* 89 * Make 'r' refer to the region of 'b'. 90 */ 91 92 REQUIRE(ISC_BUFFER_VALID(b)); 93 REQUIRE(r != NULL); 94 95 ISC__BUFFER_REGION(b, r); 96} 97 98void 99isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r) { 100 /* 101 * Make 'r' refer to the used region of 'b'. 102 */ 103 104 REQUIRE(ISC_BUFFER_VALID(b)); 105 REQUIRE(r != NULL); 106 107 ISC__BUFFER_USEDREGION(b, r); 108} 109 110void 111isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r) { 112 /* 113 * Make 'r' refer to the available region of 'b'. 114 */ 115 116 REQUIRE(ISC_BUFFER_VALID(b)); 117 REQUIRE(r != NULL); 118 119 ISC__BUFFER_AVAILABLEREGION(b, r); 120} 121 122void 123isc__buffer_add(isc_buffer_t *b, unsigned int n) { 124 /* 125 * Increase the 'used' region of 'b' by 'n' bytes. 126 */ 127 128 REQUIRE(ISC_BUFFER_VALID(b)); 129 REQUIRE(b->used + n <= b->length); 130 131 ISC__BUFFER_ADD(b, n); 132} 133 134void 135isc__buffer_subtract(isc_buffer_t *b, unsigned int n) { 136 /* 137 * Decrease the 'used' region of 'b' by 'n' bytes. 138 */ 139 140 REQUIRE(ISC_BUFFER_VALID(b)); 141 REQUIRE(b->used >= n); 142 143 ISC__BUFFER_SUBTRACT(b, n); 144} 145 146void 147isc__buffer_clear(isc_buffer_t *b) { 148 /* 149 * Make the used region empty. 150 */ 151 152 REQUIRE(ISC_BUFFER_VALID(b)); 153 154 ISC__BUFFER_CLEAR(b); 155} 156 157void 158isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) { 159 /* 160 * Make 'r' refer to the consumed region of 'b'. 161 */ 162 163 REQUIRE(ISC_BUFFER_VALID(b)); 164 REQUIRE(r != NULL); 165 166 ISC__BUFFER_CONSUMEDREGION(b, r); 167} 168 169void 170isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) { 171 /* 172 * Make 'r' refer to the remaining region of 'b'. 173 */ 174 175 REQUIRE(ISC_BUFFER_VALID(b)); 176 REQUIRE(r != NULL); 177 178 ISC__BUFFER_REMAININGREGION(b, r); 179} 180 181void 182isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r) { 183 /* 184 * Make 'r' refer to the active region of 'b'. 185 */ 186 187 REQUIRE(ISC_BUFFER_VALID(b)); 188 REQUIRE(r != NULL); 189 190 ISC__BUFFER_ACTIVEREGION(b, r); 191} 192 193void 194isc__buffer_setactive(isc_buffer_t *b, unsigned int n) { 195 /* 196 * Sets the end of the active region 'n' bytes after current. 197 */ 198 199 REQUIRE(ISC_BUFFER_VALID(b)); 200 REQUIRE(b->current + n <= b->used); 201 202 ISC__BUFFER_SETACTIVE(b, n); 203} 204 205void 206isc__buffer_first(isc_buffer_t *b) { 207 /* 208 * Make the consumed region empty. 209 */ 210 211 REQUIRE(ISC_BUFFER_VALID(b)); 212 213 ISC__BUFFER_FIRST(b); 214} 215 216void 217isc__buffer_forward(isc_buffer_t *b, unsigned int n) { 218 /* 219 * Increase the 'consumed' region of 'b' by 'n' bytes. 220 */ 221 222 REQUIRE(ISC_BUFFER_VALID(b)); 223 REQUIRE(b->current + n <= b->used); 224 225 ISC__BUFFER_FORWARD(b, n); 226} 227 228void 229isc__buffer_back(isc_buffer_t *b, unsigned int n) { 230 /* 231 * Decrease the 'consumed' region of 'b' by 'n' bytes. 232 */ 233 234 REQUIRE(ISC_BUFFER_VALID(b)); 235 REQUIRE(n <= b->current); 236 237 ISC__BUFFER_BACK(b, n); 238} 239 240void 241isc_buffer_compact(isc_buffer_t *b) { 242 unsigned int length; 243 void *src; 244 245 /* 246 * Compact the used region by moving the remaining region so it occurs 247 * at the start of the buffer. The used region is shrunk by the size 248 * of the consumed region, and the consumed region is then made empty. 249 */ 250 251 REQUIRE(ISC_BUFFER_VALID(b)); 252 253 src = isc_buffer_current(b); 254 length = isc_buffer_remaininglength(b); 255 (void)memmove(b->base, src, (size_t)length); 256 257 if (b->active > b->current) 258 b->active -= b->current; 259 else 260 b->active = 0; 261 b->current = 0; 262 b->used = length; 263} 264 265isc_uint8_t 266isc_buffer_getuint8(isc_buffer_t *b) { 267 unsigned char *cp; 268 isc_uint8_t result; 269 270 /* 271 * Read an unsigned 8-bit integer from 'b' and return it. 272 */ 273 274 REQUIRE(ISC_BUFFER_VALID(b)); 275 REQUIRE(b->used - b->current >= 1); 276 277 cp = isc_buffer_current(b); 278 b->current += 1; 279 result = ((isc_uint8_t)(cp[0])); 280 281 return (result); 282} 283 284void 285isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val) { 286 REQUIRE(ISC_BUFFER_VALID(b)); 287 REQUIRE(b->used + 1 <= b->length); 288 289 ISC__BUFFER_PUTUINT8(b, val); 290} 291 292isc_uint16_t 293isc_buffer_getuint16(isc_buffer_t *b) { 294 unsigned char *cp; 295 isc_uint16_t result; 296 297 /* 298 * Read an unsigned 16-bit integer in network byte order from 'b', 299 * convert it to host byte order, and return it. 300 */ 301 302 REQUIRE(ISC_BUFFER_VALID(b)); 303 REQUIRE(b->used - b->current >= 2); 304 305 cp = isc_buffer_current(b); 306 b->current += 2; 307 result = ((unsigned int)(cp[0])) << 8; 308 result |= ((unsigned int)(cp[1])); 309 310 return (result); 311} 312 313void 314isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val) { 315 REQUIRE(ISC_BUFFER_VALID(b)); 316 REQUIRE(b->used + 2 <= b->length); 317 318 ISC__BUFFER_PUTUINT16(b, val); 319} 320 321void 322isc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val) { 323 REQUIRE(ISC_BUFFER_VALID(b)); 324 REQUIRE(b->used + 3 <= b->length); 325 326 ISC__BUFFER_PUTUINT24(b, val); 327} 328 329isc_uint32_t 330isc_buffer_getuint32(isc_buffer_t *b) { 331 unsigned char *cp; 332 isc_uint32_t result; 333 334 /* 335 * Read an unsigned 32-bit integer in network byte order from 'b', 336 * convert it to host byte order, and return it. 337 */ 338 339 REQUIRE(ISC_BUFFER_VALID(b)); 340 REQUIRE(b->used - b->current >= 4); 341 342 cp = isc_buffer_current(b); 343 b->current += 4; 344 result = ((unsigned int)(cp[0])) << 24; 345 result |= ((unsigned int)(cp[1])) << 16; 346 result |= ((unsigned int)(cp[2])) << 8; 347 result |= ((unsigned int)(cp[3])); 348 349 return (result); 350} 351 352void 353isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) { 354 REQUIRE(ISC_BUFFER_VALID(b)); 355 REQUIRE(b->used + 4 <= b->length); 356 357 ISC__BUFFER_PUTUINT32(b, val); 358} 359 360isc_uint64_t 361isc_buffer_getuint48(isc_buffer_t *b) { 362 unsigned char *cp; 363 isc_uint64_t result; 364 365 /* 366 * Read an unsigned 48-bit integer in network byte order from 'b', 367 * convert it to host byte order, and return it. 368 */ 369 370 REQUIRE(ISC_BUFFER_VALID(b)); 371 REQUIRE(b->used - b->current >= 6); 372 373 cp = isc_buffer_current(b); 374 b->current += 6; 375 result = ((isc_int64_t)(cp[0])) << 40; 376 result |= ((isc_int64_t)(cp[1])) << 32; 377 result |= ((isc_int64_t)(cp[2])) << 24; 378 result |= ((isc_int64_t)(cp[3])) << 16; 379 result |= ((isc_int64_t)(cp[4])) << 8; 380 result |= ((isc_int64_t)(cp[5])); 381 382 return (result); 383} 384 385void 386isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) { 387 isc_uint16_t valhi; 388 isc_uint32_t vallo; 389 390 REQUIRE(ISC_BUFFER_VALID(b)); 391 REQUIRE(b->used + 6 <= b->length); 392 393 valhi = (isc_uint16_t)(val >> 32); 394 vallo = (isc_uint32_t)(val & 0xFFFFFFFF); 395 ISC__BUFFER_PUTUINT16(b, valhi); 396 ISC__BUFFER_PUTUINT32(b, vallo); 397} 398 399void 400isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base, 401 unsigned int length) 402{ 403 REQUIRE(ISC_BUFFER_VALID(b)); 404 REQUIRE(b->used + length <= b->length); 405 406 ISC__BUFFER_PUTMEM(b, base, length); 407} 408 409void 410isc__buffer_putstr(isc_buffer_t *b, const char *source) { 411 size_t l; 412 unsigned char *cp; 413 414 REQUIRE(ISC_BUFFER_VALID(b)); 415 REQUIRE(source != NULL); 416 417 /* 418 * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once. 419 */ 420 l = strlen(source); 421 422 REQUIRE(l <= isc_buffer_availablelength(b)); 423 424 cp = isc_buffer_used(b); 425 memcpy(cp, source, l); 426 b->used += (u_int)l; /* checked above - no overflow here */ 427} 428 429isc_result_t 430isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) { 431 unsigned char *base; 432 unsigned int available; 433 434 REQUIRE(ISC_BUFFER_VALID(b)); 435 REQUIRE(r != NULL); 436 437 /* 438 * XXXDCL 439 */ 440 base = isc_buffer_used(b); 441 available = isc_buffer_availablelength(b); 442 if (r->length > available) 443 return (ISC_R_NOSPACE); 444 memcpy(base, r->base, r->length); 445 b->used += r->length; 446 447 return (ISC_R_SUCCESS); 448} 449 450isc_result_t 451isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer, 452 unsigned int length) 453{ 454 isc_buffer_t *dbuf; 455 456 REQUIRE(dynbuffer != NULL); 457 REQUIRE(*dynbuffer == NULL); 458 459 dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t)); 460 if (dbuf == NULL) 461 return (ISC_R_NOMEMORY); 462 463 isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t), 464 length); 465 dbuf->mctx = mctx; 466 467 *dynbuffer = dbuf; 468 469 return (ISC_R_SUCCESS); 470} 471 472void 473isc_buffer_free(isc_buffer_t **dynbuffer) { 474 unsigned int real_length; 475 isc_buffer_t *dbuf; 476 isc_mem_t *mctx; 477 478 REQUIRE(dynbuffer != NULL); 479 REQUIRE(ISC_BUFFER_VALID(*dynbuffer)); 480 REQUIRE((*dynbuffer)->mctx != NULL); 481 482 dbuf = *dynbuffer; 483 *dynbuffer = NULL; /* destroy external reference */ 484 485 real_length = dbuf->length + sizeof(isc_buffer_t); 486 mctx = dbuf->mctx; 487 dbuf->mctx = NULL; 488 isc_buffer_invalidate(dbuf); 489 490 isc_mem_put(mctx, dbuf, real_length); 491} 492