]> git.ipfire.org Git - thirdparty/dhcp.git/blame - omapip/buffer.c
Add some more trace hooks.
[thirdparty/dhcp.git] / omapip / buffer.c
CommitLineData
61b844bf
TL
1/* buffer.c
2
3 Buffer access functions for the object management protocol... */
4
5/*
49733f31
TL
6 * Copyright (c) 1999-2000 Internet Software Consortium.
7 * All rights reserved.
61b844bf 8 *
49733f31
TL
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
61b844bf 12 *
49733f31
TL
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
61b844bf 21 *
49733f31
TL
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
61b844bf
TL
42 */
43
6a4c4be8 44#include <omapip/omapip_p.h>
61b844bf
TL
45
46/* Make sure that at least len bytes are in the input buffer, and if not,
47 read enough bytes to make up the difference. */
48
49isc_result_t omapi_connection_reader (omapi_object_t *h)
50{
51 omapi_buffer_t *buffer;
52 isc_result_t status;
b1b7b521
TL
53 unsigned read_len;
54 int read_status;
61b844bf 55 omapi_connection_object_t *c;
b1b7b521 56 unsigned bytes_to_read;
61b844bf
TL
57
58 if (!h || h -> type != omapi_type_connection)
59 return ISC_R_INVALIDARG;
60 c = (omapi_connection_object_t *)h;
61
62 /* Make sure c -> bytes_needed is valid. */
63 if (c -> bytes_needed < 0)
64 return ISC_R_INVALIDARG;
65
66 /* See if there are enough bytes. */
67 if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 &&
68 c -> in_bytes > c -> bytes_needed)
69 return ISC_R_SUCCESS;
70
71 if (c -> inbufs) {
72 for (buffer = c -> inbufs; buffer -> next;
73 buffer = buffer -> next)
74 ;
c936e8c1 75 if (!BUFFER_BYTES_FREE (buffer)) {
4bd8800e 76 status = omapi_buffer_new (&buffer -> next, MDL);
61b844bf
TL
77 if (status != ISC_R_SUCCESS)
78 return status;
79 buffer = buffer -> next;
80 }
81 } else {
4bd8800e 82 status = omapi_buffer_new (&c -> inbufs, MDL);
61b844bf
TL
83 if (status != ISC_R_SUCCESS)
84 return status;
85 buffer = c -> inbufs;
86 }
87
c936e8c1 88 bytes_to_read = BUFFER_BYTES_FREE (buffer);
61b844bf
TL
89
90 while (bytes_to_read) {
c936e8c1
TL
91 if (buffer -> tail > buffer -> head)
92 read_len = sizeof (buffer -> buf) - buffer -> tail;
61b844bf 93 else
c936e8c1 94 read_len = buffer -> head - buffer -> tail;
61b844bf
TL
95
96 read_status = read (c -> socket,
97 &buffer -> buf [buffer -> tail], read_len);
98 if (read_status < 0) {
99 if (errno == EWOULDBLOCK)
c936e8c1 100 break;
61b844bf
TL
101 else if (errno == EIO)
102 return ISC_R_IOERROR;
103 else if (errno == EINVAL)
104 return ISC_R_INVALIDARG;
105 else if (errno == ECONNRESET) {
106 omapi_disconnect (h, 0);
107 return ISC_R_SHUTTINGDOWN;
108 } else
109 return ISC_R_UNEXPECTED;
110 }
c936e8c1
TL
111 /* If we got a zero-length read, as opposed to EWOULDBLOCK,
112 the remote end closed the connection. */
61b844bf
TL
113 if (read_status == 0) {
114 omapi_disconnect (h, 0);
115 return ISC_R_SHUTTINGDOWN;
116 }
117 buffer -> tail += read_status;
118 c -> in_bytes += read_status;
119 if (buffer -> tail == sizeof buffer -> buf)
120 buffer -> tail = 0;
121 if (read_status < read_len)
122 break;
123 bytes_to_read -= read_status;
124 }
125
581e37e4 126 if (c -> bytes_needed <= c -> in_bytes) {
61b844bf
TL
127 omapi_signal (h, "ready", c);
128 }
129 return ISC_R_SUCCESS;
130}
131
132/* Put some bytes into the output buffer for a connection. */
133
134isc_result_t omapi_connection_copyin (omapi_object_t *h,
b1b7b521
TL
135 const unsigned char *bufp,
136 unsigned len)
61b844bf
TL
137{
138 omapi_buffer_t *buffer;
139 isc_result_t status;
140 int bytes_copied = 0;
b1b7b521 141 unsigned copy_len;
49146f3c 142 int sig_flags = SIG_MODE_UPDATE;
61b844bf
TL
143 omapi_connection_object_t *c;
144
145 /* Make sure len is valid. */
146 if (len < 0)
147 return ISC_R_INVALIDARG;
148 if (!h || h -> type != omapi_type_connection)
149 return ISC_R_INVALIDARG;
150 c = (omapi_connection_object_t *)h;
151
152 if (c -> outbufs) {
153 for (buffer = c -> outbufs;
154 buffer -> next; buffer = buffer -> next)
155 ;
156 } else {
4bd8800e 157 status = omapi_buffer_new (&c -> outbufs, MDL);
61b844bf
TL
158 if (status != ISC_R_SUCCESS)
159 return status;
160 buffer = c -> outbufs;
161 }
162
163 while (bytes_copied < len) {
164 /* If there is no space available in this buffer,
165 allocate a new one. */
c936e8c1 166 if (!BUFFER_BYTES_FREE (buffer)) {
4bd8800e 167 status = (omapi_buffer_new (&buffer -> next, MDL));
61b844bf
TL
168 if (status != ISC_R_SUCCESS)
169 return status;
170 buffer = buffer -> next;
171 }
172
c936e8c1
TL
173 if (buffer -> tail > buffer -> head)
174 copy_len = sizeof (buffer -> buf) - buffer -> tail;
61b844bf 175 else
c936e8c1
TL
176 copy_len = buffer -> head - buffer -> tail;
177
61b844bf
TL
178 if (copy_len > (len - bytes_copied))
179 copy_len = len - bytes_copied;
180
49146f3c
DN
181 if (c -> out_key) {
182 if (!c -> out_context)
183 sig_flags |= SIG_MODE_INIT;
184 status = omapi_connection_sign_data
185 (sig_flags, c -> out_key, &c -> out_context,
186 &bufp [bytes_copied], copy_len,
187 (omapi_typed_data_t **)0);
188 if (status != ISC_R_SUCCESS)
189 return status;
190 }
191
61b844bf
TL
192 memcpy (&buffer -> buf [buffer -> tail],
193 &bufp [bytes_copied], copy_len);
194 buffer -> tail += copy_len;
195 c -> out_bytes += copy_len;
196 bytes_copied += copy_len;
197 if (buffer -> tail == sizeof buffer -> buf)
198 buffer -> tail = 0;
199 }
200 return ISC_R_SUCCESS;
201}
202
203/* Copy some bytes from the input buffer, and advance the input buffer
204 pointer beyond the bytes copied out. */
205
e92653f1
TL
206isc_result_t omapi_connection_copyout (unsigned char *buf,
207 omapi_object_t *h,
b1b7b521 208 unsigned size)
61b844bf 209{
b1b7b521
TL
210 unsigned bytes_remaining;
211 unsigned bytes_this_copy;
c936e8c1 212 unsigned first_byte;
61b844bf
TL
213 omapi_buffer_t *buffer;
214 unsigned char *bufp;
49146f3c 215 int sig_flags = SIG_MODE_UPDATE;
61b844bf 216 omapi_connection_object_t *c;
49146f3c 217 isc_result_t status;
61b844bf
TL
218
219 if (!h || h -> type != omapi_type_connection)
220 return ISC_R_INVALIDARG;
221 c = (omapi_connection_object_t *)h;
222
223 if (size > c -> in_bytes)
224 return ISC_R_NOMORE;
225 bufp = buf;
226 bytes_remaining = size;
227 buffer = c -> inbufs;
228
229 while (bytes_remaining) {
230 if (!buffer)
231 return ISC_R_UNEXPECTED;
c936e8c1
TL
232 if (BYTES_IN_BUFFER (buffer)) {
233 if (buffer -> head == (sizeof buffer -> buf) - 1)
234 first_byte = 0;
235 else
236 first_byte = buffer -> head + 1;
237
238 if (first_byte > buffer -> tail) {
61b844bf 239 bytes_this_copy = (sizeof buffer -> buf -
c936e8c1 240 first_byte);
61b844bf
TL
241 } else {
242 bytes_this_copy =
c936e8c1 243 buffer -> tail - first_byte;
61b844bf
TL
244 }
245 if (bytes_this_copy > bytes_remaining)
246 bytes_this_copy = bytes_remaining;
247 if (bufp) {
49146f3c
DN
248 if (c -> in_key) {
249 if (!c -> in_context)
250 sig_flags |= SIG_MODE_INIT;
251 status = omapi_connection_sign_data
252 (sig_flags,
253 c -> in_key,
254 &c -> in_context,
a69fc68a 255 (unsigned char *)
49146f3c
DN
256 &buffer -> buf [first_byte],
257 bytes_this_copy,
258 (omapi_typed_data_t **)0);
259 if (status != ISC_R_SUCCESS)
260 return status;
261 }
262
c936e8c1 263 memcpy (bufp, &buffer -> buf [first_byte],
61b844bf
TL
264 bytes_this_copy);
265 bufp += bytes_this_copy;
266 }
267 bytes_remaining -= bytes_this_copy;
c936e8c1 268 buffer -> head = first_byte + bytes_this_copy - 1;
61b844bf
TL
269 c -> in_bytes -= bytes_this_copy;
270 }
271
c936e8c1 272 if (!BYTES_IN_BUFFER (buffer))
61b844bf
TL
273 buffer = buffer -> next;
274 }
275
276 /* Get rid of any input buffers that we emptied. */
277 buffer = (omapi_buffer_t *)0;
278 while (c -> inbufs &&
c936e8c1 279 !BYTES_IN_BUFFER (c -> inbufs)) {
61b844bf 280 if (c -> inbufs -> next) {
4bd8800e
TL
281 omapi_buffer_reference (&buffer,
282 c -> inbufs -> next, MDL);
283 omapi_buffer_dereference (&c -> inbufs -> next, MDL);
61b844bf 284 }
4bd8800e 285 omapi_buffer_dereference (&c -> inbufs, MDL);
c936e8c1
TL
286 if (buffer) {
287 omapi_buffer_reference
4bd8800e
TL
288 (&c -> inbufs, buffer, MDL);
289 omapi_buffer_dereference (&buffer, MDL);
c936e8c1 290 }
61b844bf
TL
291 }
292 return ISC_R_SUCCESS;
293}
294
e92653f1 295isc_result_t omapi_connection_writer (omapi_object_t *h)
61b844bf 296{
b1b7b521 297 unsigned bytes_this_write;
f0b8a59f 298 int bytes_written;
c936e8c1 299 unsigned first_byte;
61b844bf
TL
300 omapi_buffer_t *buffer;
301 unsigned char *bufp;
302 omapi_connection_object_t *c;
303
304 if (!h || h -> type != omapi_type_connection)
305 return ISC_R_INVALIDARG;
306 c = (omapi_connection_object_t *)h;
307
308 /* Already flushed... */
309 if (!c -> out_bytes)
310 return ISC_R_SUCCESS;
311
312 buffer = c -> outbufs;
313
314 while (c -> out_bytes) {
315 if (!buffer)
316 return ISC_R_UNEXPECTED;
c936e8c1
TL
317 if (BYTES_IN_BUFFER (buffer)) {
318 if (buffer -> head == (sizeof buffer -> buf) - 1)
319 first_byte = 0;
320 else
321 first_byte = buffer -> head + 1;
322
323 if (first_byte > buffer -> tail) {
61b844bf 324 bytes_this_write = (sizeof buffer -> buf -
c936e8c1 325 first_byte);
61b844bf
TL
326 } else {
327 bytes_this_write =
c936e8c1 328 buffer -> tail - first_byte;
61b844bf
TL
329 }
330 bytes_written = write (c -> socket,
c936e8c1 331 &buffer -> buf [first_byte],
61b844bf
TL
332 bytes_this_write);
333 /* If the write failed with EWOULDBLOCK or we wrote
334 zero bytes, a further write would block, so we have
335 flushed as much as we can for now. Other errors
336 are really errors. */
337 if (bytes_written < 0) {
338 if (errno == EWOULDBLOCK || errno == EAGAIN)
339 return ISC_R_SUCCESS;
340 else if (errno == EPIPE)
341 return ISC_R_NOCONN;
342 else if (errno == EFBIG || errno == EDQUOT)
343 return ISC_R_NORESOURCES;
344 else if (errno == ENOSPC)
345 return ISC_R_NOSPACE;
346 else if (errno == EIO)
347 return ISC_R_IOERROR;
348 else if (errno == EINVAL)
349 return ISC_R_INVALIDARG;
350 else if (errno == ECONNRESET)
351 return ISC_R_SHUTTINGDOWN;
352 else
353 return ISC_R_UNEXPECTED;
354 }
355 if (bytes_written == 0)
356 return ISC_R_SUCCESS;
357
c936e8c1 358 buffer -> head = first_byte + bytes_written - 1;
61b844bf
TL
359 c -> out_bytes -= bytes_written;
360
361 /* If we didn't finish out the write, we filled the
362 O.S. output buffer and a further write would block,
363 so stop trying to flush now. */
364 if (bytes_written != bytes_this_write)
365 return ISC_R_SUCCESS;
366 }
367
c936e8c1 368 if (!BYTES_IN_BUFFER (buffer))
61b844bf
TL
369 buffer = buffer -> next;
370 }
371
372 /* Get rid of any output buffers we emptied. */
373 buffer = (omapi_buffer_t *)0;
374 while (c -> outbufs &&
c936e8c1 375 !BYTES_IN_BUFFER (c -> outbufs)) {
61b844bf 376 if (c -> outbufs -> next) {
4bd8800e
TL
377 omapi_buffer_reference (&buffer,
378 c -> outbufs -> next, MDL);
379 omapi_buffer_dereference (&c -> outbufs -> next, MDL);
61b844bf 380 }
4bd8800e 381 omapi_buffer_dereference (&c -> outbufs, MDL);
61b844bf 382 if (buffer) {
4bd8800e
TL
383 omapi_buffer_reference (&c -> outbufs, buffer, MDL);
384 omapi_buffer_dereference (&buffer, MDL);
61b844bf
TL
385 }
386 }
387 return ISC_R_SUCCESS;
388}
389
390isc_result_t omapi_connection_get_uint32 (omapi_object_t *c,
391 u_int32_t *result)
392{
393 u_int32_t inbuf;
394 isc_result_t status;
395
396 status = omapi_connection_copyout ((unsigned char *)&inbuf,
397 c, sizeof inbuf);
398 if (status != ISC_R_SUCCESS)
399 return status;
400
401 *result = ntohl (inbuf);
402 return ISC_R_SUCCESS;
403}
404
405isc_result_t omapi_connection_put_uint32 (omapi_object_t *c,
406 u_int32_t value)
407{
408 u_int32_t inbuf;
409 isc_result_t status;
410
411 inbuf = htonl (value);
412
413 return omapi_connection_copyin (c, (unsigned char *)&inbuf,
414 sizeof inbuf);
415}
416
417isc_result_t omapi_connection_get_uint16 (omapi_object_t *c,
418 u_int16_t *result)
419{
420 u_int16_t inbuf;
421 isc_result_t status;
422
423 status = omapi_connection_copyout ((unsigned char *)&inbuf,
424 c, sizeof inbuf);
425 if (status != ISC_R_SUCCESS)
426 return status;
427
428 *result = ntohs (inbuf);
429 return ISC_R_SUCCESS;
430}
431
432isc_result_t omapi_connection_put_uint16 (omapi_object_t *c,
b1b7b521 433 u_int32_t value)
61b844bf
TL
434{
435 u_int16_t inbuf;
436 isc_result_t status;
437
438 inbuf = htons (value);
439
440 return omapi_connection_copyin (c, (unsigned char *)&inbuf,
441 sizeof inbuf);
442}
443
581e37e4
TL
444isc_result_t omapi_connection_write_typed_data (omapi_object_t *c,
445 omapi_typed_data_t *data)
446{
447 isc_result_t status;
448 omapi_handle_t handle;
449
84b00685
TL
450 /* Null data is valid. */
451 if (!data)
452 return omapi_connection_put_uint32 (c, 0);
453
581e37e4
TL
454 switch (data -> type) {
455 case omapi_datatype_int:
456 status = omapi_connection_put_uint32 (c, sizeof (u_int32_t));
457 if (status != ISC_R_SUCCESS)
458 return status;
b1b7b521
TL
459 return omapi_connection_put_uint32 (c, ((u_int32_t)
460 (data -> u.integer)));
581e37e4
TL
461
462 case omapi_datatype_string:
463 case omapi_datatype_data:
464 status = omapi_connection_put_uint32 (c, data -> u.buffer.len);
465 if (status != ISC_R_SUCCESS)
466 return status;
0e603324
TL
467 if (data -> u.buffer.len)
468 return omapi_connection_copyin
469 (c, data -> u.buffer.value,
470 data -> u.buffer.len);
471 return ISC_R_SUCCESS;
581e37e4
TL
472
473 case omapi_datatype_object:
0e603324
TL
474 if (data -> u.object) {
475 status = omapi_object_handle (&handle,
476 data -> u.object);
477 if (status != ISC_R_SUCCESS)
478 return status;
479 } else
480 handle = 0;
581e37e4
TL
481 status = omapi_connection_put_uint32 (c, sizeof handle);
482 if (status != ISC_R_SUCCESS)
483 return status;
484 return omapi_connection_put_uint32 (c, handle);
485
486 }
487 return ISC_R_INVALIDARG;
488}
489
b1b7b521 490isc_result_t omapi_connection_put_name (omapi_object_t *c, const char *name)
581e37e4
TL
491{
492 isc_result_t status;
b1b7b521 493 unsigned len = strlen (name);
581e37e4
TL
494
495 status = omapi_connection_put_uint16 (c, len);
496 if (status != ISC_R_SUCCESS)
497 return status;
b1b7b521 498 return omapi_connection_copyin (c, (const unsigned char *)name, len);
581e37e4
TL
499}
500
b1b7b521
TL
501isc_result_t omapi_connection_put_string (omapi_object_t *c,
502 const char *string)
581e37e4
TL
503{
504 isc_result_t status;
b1b7b521 505 unsigned len;
581e37e4 506
0e603324
TL
507 if (string)
508 len = strlen (string);
509 else
510 len = 0;
581e37e4
TL
511
512 status = omapi_connection_put_uint32 (c, len);
513 if (status != ISC_R_SUCCESS)
514 return status;
0e603324
TL
515 if (len)
516 return omapi_connection_copyin
517 (c, (const unsigned char *)string, len);
518 return ISC_R_SUCCESS;
581e37e4
TL
519}
520
521isc_result_t omapi_connection_put_handle (omapi_object_t *c, omapi_object_t *h)
522{
523 isc_result_t status;
524 omapi_handle_t handle;
525
0e603324
TL
526 if (h) {
527 status = omapi_object_handle (&handle, h);
528 if (status != ISC_R_SUCCESS)
529 return status;
530 } else
531 handle = 0; /* The null handle. */
581e37e4
TL
532 status = omapi_connection_put_uint32 (c, sizeof handle);
533 if (status != ISC_R_SUCCESS)
534 return status;
535 return omapi_connection_put_uint32 (c, handle);
536}