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