xref: /minix/external/bsd/bind/dist/lib/lwres/lwbuffer.c (revision 00b67f09)
1 /*	$NetBSD: lwbuffer.c,v 1.5 2014/12/10 04:38:02 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004, 2005, 2007, 2014  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 2000, 2001  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: lwbuffer.c,v 1.15 2007/06/19 23:47:22 tbox Exp  */
21 
22 /*! \file */
23 
24 /**
25  *    These functions provide bounds checked access to a region of memory
26  *    where data is being read or written. They are based on, and similar
27  *    to, the isc_buffer_ functions in the ISC library.
28  *
29  *    A buffer is a region of memory, together with a set of related
30  *    subregions. The used region and the available region are disjoint, and
31  *    their union is the buffer's region. The used region extends from the
32  *    beginning of the buffer region to the last used byte. The available
33  *    region extends from one byte greater than the last used byte to the
34  *    end of the buffer's region. The size of the used region can be changed
35  *    using various buffer commands. Initially, the used region is empty.
36  *
37  *    The used region is further subdivided into two disjoint regions: the
38  *    consumed region and the remaining region. The union of these two
39  *    regions is the used region. The consumed region extends from the
40  *    beginning of the used region to the byte before the current offset (if
41  *    any). The remaining region the current pointer to the end of the used
42  *    region. The size of the consumed region can be changed using various
43  *    buffer commands. Initially, the consumed region is empty.
44  *
45  *    The active region is an (optional) subregion of the remaining region.
46  *    It extends from the current offset to an offset in the remaining
47  *    region. Initially, the active region is empty. If the current offset
48  *    advances beyond the chosen offset, the active region will also be
49  *    empty.
50  *
51  *
52  * \verbatim
53  *    /------------entire length---------------\\
54  *    /----- used region -----\\/-- available --\\
55  *    +----------------------------------------+
56  *    | consumed  | remaining |                |
57  *    +----------------------------------------+
58  *    a           b     c     d                e
59  *
60  *   a == base of buffer.
61  *   b == current pointer.  Can be anywhere between a and d.
62  *   c == active pointer.  Meaningful between b and d.
63  *   d == used pointer.
64  *   e == length of buffer.
65  *
66  *   a-e == entire length of buffer.
67  *   a-d == used region.
68  *   a-b == consumed region.
69  *   b-d == remaining region.
70  *   b-c == optional active region.
71  * \endverbatim
72  *
73  *    lwres_buffer_init() initializes the lwres_buffer_t *b and assocates it
74  *    with the memory region of size length bytes starting at location base.
75  *
76  *    lwres_buffer_invalidate() marks the buffer *b as invalid. Invalidating
77  *    a buffer after use is not required, but makes it possible to catch its
78  *    possible accidental use.
79  *
80  *    The functions lwres_buffer_add() and lwres_buffer_subtract()
81  *    respectively increase and decrease the used space in buffer *b by n
82  *    bytes. lwres_buffer_add() checks for buffer overflow and
83  *    lwres_buffer_subtract() checks for underflow. These functions do not
84  *    allocate or deallocate memory. They just change the value of used.
85  *
86  *    A buffer is re-initialised by lwres_buffer_clear(). The function sets
87  *    used , current and active to zero.
88  *
89  *    lwres_buffer_first() makes the consumed region of buffer *p empty by
90  *    setting current to zero (the start of the buffer).
91  *
92  *    lwres_buffer_forward() increases the consumed region of buffer *b by n
93  *    bytes, checking for overflow. Similarly, lwres_buffer_back() decreases
94  *    buffer b's consumed region by n bytes and checks for underflow.
95  *
96  *    lwres_buffer_getuint8() reads an unsigned 8-bit integer from *b and
97  *    returns it. lwres_buffer_putuint8() writes the unsigned 8-bit integer
98  *    val to buffer *b.
99  *
100  *    lwres_buffer_getuint16() and lwres_buffer_getuint32() are identical to
101  *    lwres_buffer_putuint8() except that they respectively read an unsigned
102  *    16-bit or 32-bit integer in network byte order from b. Similarly,
103  *    lwres_buffer_putuint16() and lwres_buffer_putuint32() writes the
104  *    unsigned 16-bit or 32-bit integer val to buffer b, in network byte
105  *    order.
106  *
107  *    Arbitrary amounts of data are read or written from a lightweight
108  *    resolver buffer with lwres_buffer_getmem() and lwres_buffer_putmem()
109  *    respectively. lwres_buffer_putmem() copies length bytes of memory at
110  *    base to b. Conversely, lwres_buffer_getmem() copies length bytes of
111  *    memory from b to base.
112  */
113 
114 #include <config.h>
115 
116 #include <string.h>
117 
118 #include <lwres/lwbuffer.h>
119 
120 #include "assert_p.h"
121 
122 void
lwres_buffer_init(lwres_buffer_t * b,void * base,unsigned int length)123 lwres_buffer_init(lwres_buffer_t *b, void *base, unsigned int length)
124 {
125 	/*
126 	 * Make 'b' refer to the 'length'-byte region starting at base.
127 	 */
128 
129 	REQUIRE(b != NULL);
130 
131 	b->magic = LWRES_BUFFER_MAGIC;
132 	b->base = base;
133 	b->length = length;
134 	b->used = 0;
135 	b->current = 0;
136 	b->active = 0;
137 }
138 
139 /*  Make 'b' an invalid buffer. */
140 void
lwres_buffer_invalidate(lwres_buffer_t * b)141 lwres_buffer_invalidate(lwres_buffer_t *b)
142 {
143 
144 	REQUIRE(LWRES_BUFFER_VALID(b));
145 
146 	b->magic = 0;
147 	b->base = NULL;
148 	b->length = 0;
149 	b->used = 0;
150 	b->current = 0;
151 	b->active = 0;
152 }
153 
154 /* Increase the 'used' region of 'b' by 'n' bytes. */
155 void
lwres_buffer_add(lwres_buffer_t * b,unsigned int n)156 lwres_buffer_add(lwres_buffer_t *b, unsigned int n)
157 {
158 
159 	REQUIRE(LWRES_BUFFER_VALID(b));
160 	REQUIRE(b->used + n <= b->length);
161 
162 	b->used += n;
163 }
164 
165 /* Decrease the 'used' region of 'b' by 'n' bytes. */
166 void
lwres_buffer_subtract(lwres_buffer_t * b,unsigned int n)167 lwres_buffer_subtract(lwres_buffer_t *b, unsigned int n)
168 {
169 
170 	REQUIRE(LWRES_BUFFER_VALID(b));
171 	REQUIRE(b->used >= n);
172 
173 	b->used -= n;
174 	if (b->current > b->used)
175 		b->current = b->used;
176 	if (b->active > b->used)
177 		b->active = b->used;
178 }
179 
180 /* Make the used region empty. */
181 void
lwres_buffer_clear(lwres_buffer_t * b)182 lwres_buffer_clear(lwres_buffer_t *b)
183 {
184 
185 	REQUIRE(LWRES_BUFFER_VALID(b));
186 
187 	b->used = 0;
188 	b->current = 0;
189 	b->active = 0;
190 }
191 
192 /* Make the consumed region empty. */
193 void
lwres_buffer_first(lwres_buffer_t * b)194 lwres_buffer_first(lwres_buffer_t *b)
195 {
196 
197 	REQUIRE(LWRES_BUFFER_VALID(b));
198 
199 	b->current = 0;
200 }
201 
202 /* Increase the 'consumed' region of 'b' by 'n' bytes. */
203 void
lwres_buffer_forward(lwres_buffer_t * b,unsigned int n)204 lwres_buffer_forward(lwres_buffer_t *b, unsigned int n)
205 {
206 
207 	REQUIRE(LWRES_BUFFER_VALID(b));
208 	REQUIRE(b->current + n <= b->used);
209 
210 	b->current += n;
211 }
212 
213 /* Decrease the 'consumed' region of 'b' by 'n' bytes. */
214 void
lwres_buffer_back(lwres_buffer_t * b,unsigned int n)215 lwres_buffer_back(lwres_buffer_t *b, unsigned int n)
216 {
217 
218 	REQUIRE(LWRES_BUFFER_VALID(b));
219 	REQUIRE(n <= b->current);
220 
221 	b->current -= n;
222 }
223 
224 /* Read an unsigned 8-bit integer from 'b' and return it. */
225 lwres_uint8_t
lwres_buffer_getuint8(lwres_buffer_t * b)226 lwres_buffer_getuint8(lwres_buffer_t *b)
227 {
228 	unsigned char *cp;
229 	lwres_uint8_t result;
230 
231 
232 	REQUIRE(LWRES_BUFFER_VALID(b));
233 	REQUIRE(b->used - b->current >= 1);
234 
235 	cp = b->base;
236 	cp += b->current;
237 	b->current += 1;
238 	result = ((unsigned int)(cp[0]));
239 
240 	return (result);
241 }
242 
243 /* Put an unsigned 8-bit integer */
244 void
lwres_buffer_putuint8(lwres_buffer_t * b,lwres_uint8_t val)245 lwres_buffer_putuint8(lwres_buffer_t *b, lwres_uint8_t val)
246 {
247 	unsigned char *cp;
248 
249 	REQUIRE(LWRES_BUFFER_VALID(b));
250 	REQUIRE(b->used + 1 <= b->length);
251 
252 	cp = b->base;
253 	cp += b->used;
254 	b->used += 1;
255 	cp[0] = (val & 0x00ff);
256 }
257 
258 /*  Read an unsigned 16-bit integer in network byte order from 'b', convert it to host byte order, and return it. */
259 lwres_uint16_t
lwres_buffer_getuint16(lwres_buffer_t * b)260 lwres_buffer_getuint16(lwres_buffer_t *b)
261 {
262 	unsigned char *cp;
263 	lwres_uint16_t result;
264 
265 
266 	REQUIRE(LWRES_BUFFER_VALID(b));
267 	REQUIRE(b->used - b->current >= 2);
268 
269 	cp = b->base;
270 	cp += b->current;
271 	b->current += 2;
272 	result = ((unsigned int)(cp[0])) << 8;
273 	result |= ((unsigned int)(cp[1]));
274 
275 	return (result);
276 }
277 
278 /* Put an unsigned 16-bit integer. */
279 void
lwres_buffer_putuint16(lwres_buffer_t * b,lwres_uint16_t val)280 lwres_buffer_putuint16(lwres_buffer_t *b, lwres_uint16_t val)
281 {
282 	unsigned char *cp;
283 
284 	REQUIRE(LWRES_BUFFER_VALID(b));
285 	REQUIRE(b->used + 2 <= b->length);
286 
287 	cp = b->base;
288 	cp += b->used;
289 	b->used += 2;
290 	cp[0] = (val & 0xff00) >> 8;
291 	cp[1] = (val & 0x00ff);
292 }
293 
294 /*  Read an unsigned 32-bit integer in network byte order from 'b', convert it to host byte order, and return it. */
295 lwres_uint32_t
lwres_buffer_getuint32(lwres_buffer_t * b)296 lwres_buffer_getuint32(lwres_buffer_t *b)
297 {
298 	unsigned char *cp;
299 	lwres_uint32_t result;
300 
301 	REQUIRE(LWRES_BUFFER_VALID(b));
302 	REQUIRE(b->used - b->current >= 4);
303 
304 	cp = b->base;
305 	cp += b->current;
306 	b->current += 4;
307 	result = ((unsigned int)(cp[0])) << 24;
308 	result |= ((unsigned int)(cp[1])) << 16;
309 	result |= ((unsigned int)(cp[2])) << 8;
310 	result |= ((unsigned int)(cp[3]));
311 
312 	return (result);
313 }
314 
315 /* Put an unsigned 32-bit integer. */
316 void
lwres_buffer_putuint32(lwres_buffer_t * b,lwres_uint32_t val)317 lwres_buffer_putuint32(lwres_buffer_t *b, lwres_uint32_t val)
318 {
319 	unsigned char *cp;
320 
321 	REQUIRE(LWRES_BUFFER_VALID(b));
322 	REQUIRE(b->used + 4 <= b->length);
323 
324 	cp = b->base;
325 	cp += b->used;
326 	b->used += 4;
327 	cp[0] = (unsigned char)((val & 0xff000000) >> 24);
328 	cp[1] = (unsigned char)((val & 0x00ff0000) >> 16);
329 	cp[2] = (unsigned char)((val & 0x0000ff00) >> 8);
330 	cp[3] = (unsigned char)(val & 0x000000ff);
331 }
332 
333 /* copies length bytes of memory at base to b */
334 void
lwres_buffer_putmem(lwres_buffer_t * b,const unsigned char * base,unsigned int length)335 lwres_buffer_putmem(lwres_buffer_t *b, const unsigned char *base,
336 		    unsigned int length)
337 {
338 	unsigned char *cp;
339 
340 	REQUIRE(LWRES_BUFFER_VALID(b));
341 	REQUIRE(b->used + length <= b->length);
342 
343 	cp = (unsigned char *)b->base + b->used;
344 	memmove(cp, base, length);
345 	b->used += length;
346 }
347 
348 /* copies length bytes of memory at b to base */
349 void
lwres_buffer_getmem(lwres_buffer_t * b,unsigned char * base,unsigned int length)350 lwres_buffer_getmem(lwres_buffer_t *b, unsigned char *base,
351 		    unsigned int length)
352 {
353 	unsigned char *cp;
354 
355 	REQUIRE(LWRES_BUFFER_VALID(b));
356 	REQUIRE(b->used - b->current >= length);
357 
358 	cp = b->base;
359 	cp += b->current;
360 	b->current += length;
361 
362 	memmove(base, cp, length);
363 }
364