/contrib/bind9/lib/isc/buffer.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 489 lines · 275 code · 111 blank · 103 comment · 19 complexity · e0ac7f45089b85f9dd906342ca5285f5 MD5 · raw file

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