1/*	$NetBSD: buffer.c,v 1.6 2020/05/25 20:47:20 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