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 32 void 33 isc__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 44 void 45 isc__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 54 void 55 isc_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 73 void 74 isc__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 86 void 87 isc__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 98 void 99 isc__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 110 void 111 isc__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 122 void 123 isc__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 134 void 135 isc__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 146 void 147 isc__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 157 void 158 isc__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 169 void 170 isc__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 181 void 182 isc__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 193 void 194 isc__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 205 void 206 isc__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 216 void 217 isc__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 228 void 229 isc__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 240 void 241 isc_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 265 isc_uint8_t 266 isc_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 284 void 285 isc__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 292 isc_uint16_t 293 isc_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 313 void 314 isc__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 321 void 322 isc__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 329 isc_uint32_t 330 isc_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 352 void 353 isc__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 360 isc_uint64_t 361 isc_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 385 void 386 isc__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 399 void 400 isc__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 409 void 410 isc__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 429 isc_result_t 430 isc_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 450 isc_result_t 451 isc_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 472 void 473 isc_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