]> git.ipfire.org Git - thirdparty/dhcp.git/blame - omapip/buffer.c
[master] Update dmalloc to use a size_t as an argument
[thirdparty/dhcp.git] / omapip / buffer.c
CommitLineData
61b844bf
TL
1/* buffer.c
2
3 Buffer access functions for the object management protocol... */
4
5/*
edad9be5 6 * Copyright (c) 2009,2012-2014 by Internet Systems Consortium, Inc. ("ISC")
0f750c4f 7 * Copyright (c) 2004,2005,2007 by Internet Systems Consortium, Inc. ("ISC")
98311e4b 8 * Copyright (c) 1999-2003 by Internet Software Consortium
61b844bf 9 *
98311e4b
DH
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
61b844bf 13 *
98311e4b
DH
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
61b844bf 21 *
98311e4b
DH
22 * Internet Systems Consortium, Inc.
23 * 950 Charter Street
24 * Redwood City, CA 94063
25 * <info@isc.org>
2c85ac9b 26 * https://www.isc.org/
49733f31 27 *
61b844bf
TL
28 */
29
fe5b0fdd
DH
30#include "dhcpd.h"
31
6a4c4be8 32#include <omapip/omapip_p.h>
fe5b0fdd 33#include <errno.h>
61b844bf 34
c1a3453e
TL
35#if defined (TRACING)
36static void trace_connection_input_input (trace_type_t *, unsigned, char *);
37static void trace_connection_input_stop (trace_type_t *);
38static void trace_connection_output_input (trace_type_t *, unsigned, char *);
39static void trace_connection_output_stop (trace_type_t *);
40static trace_type_t *trace_connection_input;
41static trace_type_t *trace_connection_output;
42static isc_result_t omapi_connection_reader_trace (omapi_object_t *,
43 unsigned, char *,
44 unsigned *);
45extern omapi_array_t *omapi_connections;
46
47void omapi_buffer_trace_setup ()
48{
49 trace_connection_input =
50 trace_type_register ("connection-input",
51 (void *)0,
52 trace_connection_input_input,
53 trace_connection_input_stop, MDL);
54 trace_connection_output =
55 trace_type_register ("connection-output",
56 (void *)0,
57 trace_connection_output_input,
58 trace_connection_output_stop, MDL);
59}
60
61static void trace_connection_input_input (trace_type_t *ttype,
62 unsigned length, char *buf)
63{
d758ad8c 64 unsigned left, taken, cc = 0;
c1a3453e
TL
65 char *s;
66 int32_t connect_index;
67 isc_result_t status;
68 omapi_connection_object_t *c = (omapi_connection_object_t *)0;
69
70 memcpy (&connect_index, buf, sizeof connect_index);
71 connect_index = ntohl (connect_index);
72
73 omapi_array_foreach_begin (omapi_connections,
74 omapi_connection_object_t, lp) {
75 if (lp -> index == ntohl (connect_index)) {
76 omapi_connection_reference (&c, lp, MDL);
d758ad8c 77 omapi_connection_dereference (&lp, MDL);
c1a3453e
TL
78 break;
79 }
80 } omapi_array_foreach_end (omapi_connections,
81 omapi_connection_object_t, lp);
82
83 if (!c) {
b209f985
DN
84 log_error ("trace connection input: no connection index %ld",
85 (long int)connect_index);
c1a3453e
TL
86 return;
87 }
88
89 s = buf + sizeof connect_index;
d758ad8c 90 left = length - sizeof connect_index;
c1a3453e
TL
91
92 while (left) {
d758ad8c 93 taken = 0;
c1a3453e 94 status = omapi_connection_reader_trace ((omapi_object_t *)c,
d758ad8c 95 left, s, &taken);
c1a3453e
TL
96 if (status != ISC_R_SUCCESS) {
97 log_error ("trace connection input: %s",
98 isc_result_totext (status));
99 break;
100 }
d758ad8c 101 if (!taken) {
c1a3453e
TL
102 if (cc > 0) {
103 log_error ("trace connection_input: %s",
104 "input is not being consumed.");
105 break;
106 }
107 cc++;
d758ad8c 108 } else {
c1a3453e 109 cc = 0;
d758ad8c
TL
110 left -= taken;
111 }
c1a3453e 112 }
d758ad8c 113 omapi_connection_dereference (&c, MDL);
c1a3453e
TL
114}
115
116static void trace_connection_input_stop (trace_type_t *ttype) { }
117
118static void trace_connection_output_input (trace_type_t *ttype,
119 unsigned length, char *buf)
120{
121 /* We *could* check to see if the output is correct, but for now
122 we aren't going to do that. */
123}
124
125static void trace_connection_output_stop (trace_type_t *ttype) { }
126
127#endif
128
61b844bf
TL
129/* Make sure that at least len bytes are in the input buffer, and if not,
130 read enough bytes to make up the difference. */
131
132isc_result_t omapi_connection_reader (omapi_object_t *h)
133{
c1a3453e 134#if defined (TRACING)
a7394d15 135 return omapi_connection_reader_trace (h, 0, (char *)0, (unsigned *)0);
c1a3453e
TL
136}
137
138static isc_result_t omapi_connection_reader_trace (omapi_object_t *h,
139 unsigned stuff_len,
140 char *stuff_buf,
141 unsigned *stuff_taken)
142{
143#endif
61b844bf
TL
144 omapi_buffer_t *buffer;
145 isc_result_t status;
b1b7b521
TL
146 unsigned read_len;
147 int read_status;
61b844bf 148 omapi_connection_object_t *c;
b1b7b521 149 unsigned bytes_to_read;
c1a3453e 150
61b844bf 151 if (!h || h -> type != omapi_type_connection)
98bf1607 152 return DHCP_R_INVALIDARG;
61b844bf
TL
153 c = (omapi_connection_object_t *)h;
154
61b844bf
TL
155 /* See if there are enough bytes. */
156 if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 &&
157 c -> in_bytes > c -> bytes_needed)
158 return ISC_R_SUCCESS;
159
c1a3453e 160
61b844bf
TL
161 if (c -> inbufs) {
162 for (buffer = c -> inbufs; buffer -> next;
163 buffer = buffer -> next)
164 ;
c936e8c1 165 if (!BUFFER_BYTES_FREE (buffer)) {
4bd8800e 166 status = omapi_buffer_new (&buffer -> next, MDL);
61b844bf
TL
167 if (status != ISC_R_SUCCESS)
168 return status;
169 buffer = buffer -> next;
170 }
171 } else {
4bd8800e 172 status = omapi_buffer_new (&c -> inbufs, MDL);
61b844bf
TL
173 if (status != ISC_R_SUCCESS)
174 return status;
175 buffer = c -> inbufs;
176 }
177
c936e8c1 178 bytes_to_read = BUFFER_BYTES_FREE (buffer);
61b844bf
TL
179
180 while (bytes_to_read) {
c936e8c1
TL
181 if (buffer -> tail > buffer -> head)
182 read_len = sizeof (buffer -> buf) - buffer -> tail;
61b844bf 183 else
c936e8c1 184 read_len = buffer -> head - buffer -> tail;
61b844bf 185
c1a3453e
TL
186#if defined (TRACING)
187 if (trace_playback()) {
188 if (stuff_len) {
189 if (read_len > stuff_len)
190 read_len = stuff_len;
191 if (stuff_taken)
192 *stuff_taken += read_len;
193 memcpy (&buffer -> buf [buffer -> tail],
194 stuff_buf, read_len);
195 stuff_len -= read_len;
196 stuff_buf += read_len;
197 read_status = read_len;
198 } else {
199 break;
200 }
201 } else
202#endif
203 {
204 read_status = read (c -> socket,
205 &buffer -> buf [buffer -> tail],
206 read_len);
207 }
61b844bf
TL
208 if (read_status < 0) {
209 if (errno == EWOULDBLOCK)
c936e8c1 210 break;
61b844bf
TL
211 else if (errno == EIO)
212 return ISC_R_IOERROR;
213 else if (errno == EINVAL)
98bf1607 214 return DHCP_R_INVALIDARG;
61b844bf 215 else if (errno == ECONNRESET) {
d889f744 216 omapi_disconnect (h, 1);
61b844bf
TL
217 return ISC_R_SHUTTINGDOWN;
218 } else
219 return ISC_R_UNEXPECTED;
220 }
c1a3453e 221
c936e8c1
TL
222 /* If we got a zero-length read, as opposed to EWOULDBLOCK,
223 the remote end closed the connection. */
61b844bf
TL
224 if (read_status == 0) {
225 omapi_disconnect (h, 0);
226 return ISC_R_SHUTTINGDOWN;
227 }
c1a3453e
TL
228#if defined (TRACING)
229 if (trace_record ()) {
230 trace_iov_t iov [2];
231 int32_t connect_index;
232
233 connect_index = htonl (c -> index);
234
235 iov [0].buf = (char *)&connect_index;
236 iov [0].len = sizeof connect_index;
237 iov [1].buf = &buffer -> buf [buffer -> tail];
238 iov [1].len = read_status;
239
240 status = (trace_write_packet_iov
241 (trace_connection_input, 2, iov, MDL));
242 if (status != ISC_R_SUCCESS) {
243 trace_stop ();
244 log_error ("trace connection input: %s",
245 isc_result_totext (status));
246 }
247 }
248#endif
61b844bf
TL
249 buffer -> tail += read_status;
250 c -> in_bytes += read_status;
251 if (buffer -> tail == sizeof buffer -> buf)
252 buffer -> tail = 0;
253 if (read_status < read_len)
254 break;
255 bytes_to_read -= read_status;
256 }
257
581e37e4 258 if (c -> bytes_needed <= c -> in_bytes) {
61b844bf
TL
259 omapi_signal (h, "ready", c);
260 }
261 return ISC_R_SUCCESS;
262}
263
264/* Put some bytes into the output buffer for a connection. */
265
266isc_result_t omapi_connection_copyin (omapi_object_t *h,
b1b7b521
TL
267 const unsigned char *bufp,
268 unsigned len)
61b844bf
TL
269{
270 omapi_buffer_t *buffer;
271 isc_result_t status;
272 int bytes_copied = 0;
b1b7b521 273 unsigned copy_len;
49146f3c 274 int sig_flags = SIG_MODE_UPDATE;
61b844bf
TL
275 omapi_connection_object_t *c;
276
0f750c4f 277 /* no need to verify len as it's unsigned */
61b844bf 278 if (!h || h -> type != omapi_type_connection)
98bf1607 279 return DHCP_R_INVALIDARG;
61b844bf
TL
280 c = (omapi_connection_object_t *)h;
281
c1d58ae6
TL
282 /* If the connection is closed, return an error if the caller
283 tries to copy in. */
284 if (c -> state == omapi_connection_disconnecting ||
285 c -> state == omapi_connection_closed)
286 return ISC_R_NOTCONNECTED;
287
61b844bf
TL
288 if (c -> outbufs) {
289 for (buffer = c -> outbufs;
290 buffer -> next; buffer = buffer -> next)
291 ;
292 } else {
4bd8800e 293 status = omapi_buffer_new (&c -> outbufs, MDL);
61b844bf 294 if (status != ISC_R_SUCCESS)
98bf1607 295 goto leave;
61b844bf
TL
296 buffer = c -> outbufs;
297 }
298
299 while (bytes_copied < len) {
300 /* If there is no space available in this buffer,
301 allocate a new one. */
c936e8c1 302 if (!BUFFER_BYTES_FREE (buffer)) {
4bd8800e 303 status = (omapi_buffer_new (&buffer -> next, MDL));
61b844bf 304 if (status != ISC_R_SUCCESS)
98bf1607 305 goto leave;
61b844bf
TL
306 buffer = buffer -> next;
307 }
308
c936e8c1
TL
309 if (buffer -> tail > buffer -> head)
310 copy_len = sizeof (buffer -> buf) - buffer -> tail;
61b844bf 311 else
c936e8c1
TL
312 copy_len = buffer -> head - buffer -> tail;
313
61b844bf
TL
314 if (copy_len > (len - bytes_copied))
315 copy_len = len - bytes_copied;
316
49146f3c
DN
317 if (c -> out_key) {
318 if (!c -> out_context)
319 sig_flags |= SIG_MODE_INIT;
320 status = omapi_connection_sign_data
321 (sig_flags, c -> out_key, &c -> out_context,
322 &bufp [bytes_copied], copy_len,
323 (omapi_typed_data_t **)0);
324 if (status != ISC_R_SUCCESS)
98bf1607 325 goto leave;
49146f3c
DN
326 }
327
61b844bf
TL
328 memcpy (&buffer -> buf [buffer -> tail],
329 &bufp [bytes_copied], copy_len);
330 buffer -> tail += copy_len;
331 c -> out_bytes += copy_len;
332 bytes_copied += copy_len;
333 if (buffer -> tail == sizeof buffer -> buf)
334 buffer -> tail = 0;
335 }
98bf1607
SR
336
337 status = ISC_R_SUCCESS;
338
339 leave:
340 /*
341 * If we have any bytes to send and we have a proper io object
342 * inform the socket code that we would like to know when we
343 * can send more bytes.
344 */
345 if (c->out_bytes != 0) {
346 if ((c->outer != NULL) &&
347 (c->outer->type == omapi_type_io_object)) {
348 omapi_io_object_t *io = (omapi_io_object_t *)c->outer;
349 isc_socket_fdwatchpoke(io->fd,
350 ISC_SOCKFDWATCH_WRITE);
351 }
352 }
353
354 return (status);
61b844bf
TL
355}
356
357/* Copy some bytes from the input buffer, and advance the input buffer
358 pointer beyond the bytes copied out. */
359
e92653f1
TL
360isc_result_t omapi_connection_copyout (unsigned char *buf,
361 omapi_object_t *h,
b1b7b521 362 unsigned size)
61b844bf 363{
b1b7b521
TL
364 unsigned bytes_remaining;
365 unsigned bytes_this_copy;
c936e8c1 366 unsigned first_byte;
61b844bf
TL
367 omapi_buffer_t *buffer;
368 unsigned char *bufp;
49146f3c 369 int sig_flags = SIG_MODE_UPDATE;
61b844bf 370 omapi_connection_object_t *c;
49146f3c 371 isc_result_t status;
61b844bf
TL
372
373 if (!h || h -> type != omapi_type_connection)
98bf1607 374 return DHCP_R_INVALIDARG;
61b844bf
TL
375 c = (omapi_connection_object_t *)h;
376
377 if (size > c -> in_bytes)
378 return ISC_R_NOMORE;
379 bufp = buf;
380 bytes_remaining = size;
381 buffer = c -> inbufs;
382
383 while (bytes_remaining) {
384 if (!buffer)
385 return ISC_R_UNEXPECTED;
c936e8c1
TL
386 if (BYTES_IN_BUFFER (buffer)) {
387 if (buffer -> head == (sizeof buffer -> buf) - 1)
388 first_byte = 0;
389 else
390 first_byte = buffer -> head + 1;
391
392 if (first_byte > buffer -> tail) {
61b844bf 393 bytes_this_copy = (sizeof buffer -> buf -
c936e8c1 394 first_byte);
61b844bf
TL
395 } else {
396 bytes_this_copy =
c936e8c1 397 buffer -> tail - first_byte;
61b844bf
TL
398 }
399 if (bytes_this_copy > bytes_remaining)
400 bytes_this_copy = bytes_remaining;
401 if (bufp) {
49146f3c
DN
402 if (c -> in_key) {
403 if (!c -> in_context)
404 sig_flags |= SIG_MODE_INIT;
405 status = omapi_connection_sign_data
406 (sig_flags,
407 c -> in_key,
408 &c -> in_context,
a69fc68a 409 (unsigned char *)
49146f3c
DN
410 &buffer -> buf [first_byte],
411 bytes_this_copy,
412 (omapi_typed_data_t **)0);
413 if (status != ISC_R_SUCCESS)
414 return status;
415 }
416
c936e8c1 417 memcpy (bufp, &buffer -> buf [first_byte],
61b844bf
TL
418 bytes_this_copy);
419 bufp += bytes_this_copy;
420 }
421 bytes_remaining -= bytes_this_copy;
c936e8c1 422 buffer -> head = first_byte + bytes_this_copy - 1;
61b844bf
TL
423 c -> in_bytes -= bytes_this_copy;
424 }
425
c936e8c1 426 if (!BYTES_IN_BUFFER (buffer))
61b844bf
TL
427 buffer = buffer -> next;
428 }
429
430 /* Get rid of any input buffers that we emptied. */
431 buffer = (omapi_buffer_t *)0;
432 while (c -> inbufs &&
c936e8c1 433 !BYTES_IN_BUFFER (c -> inbufs)) {
61b844bf 434 if (c -> inbufs -> next) {
4bd8800e
TL
435 omapi_buffer_reference (&buffer,
436 c -> inbufs -> next, MDL);
437 omapi_buffer_dereference (&c -> inbufs -> next, MDL);
61b844bf 438 }
4bd8800e 439 omapi_buffer_dereference (&c -> inbufs, MDL);
c936e8c1
TL
440 if (buffer) {
441 omapi_buffer_reference
4bd8800e
TL
442 (&c -> inbufs, buffer, MDL);
443 omapi_buffer_dereference (&buffer, MDL);
c936e8c1 444 }
61b844bf
TL
445 }
446 return ISC_R_SUCCESS;
447}
448
e92653f1 449isc_result_t omapi_connection_writer (omapi_object_t *h)
61b844bf 450{
b1b7b521 451 unsigned bytes_this_write;
f0b8a59f 452 int bytes_written;
c936e8c1 453 unsigned first_byte;
61b844bf 454 omapi_buffer_t *buffer;
61b844bf
TL
455 omapi_connection_object_t *c;
456
457 if (!h || h -> type != omapi_type_connection)
98bf1607 458 return DHCP_R_INVALIDARG;
61b844bf
TL
459 c = (omapi_connection_object_t *)h;
460
461 /* Already flushed... */
462 if (!c -> out_bytes)
463 return ISC_R_SUCCESS;
464
465 buffer = c -> outbufs;
466
467 while (c -> out_bytes) {
468 if (!buffer)
469 return ISC_R_UNEXPECTED;
c936e8c1
TL
470 if (BYTES_IN_BUFFER (buffer)) {
471 if (buffer -> head == (sizeof buffer -> buf) - 1)
472 first_byte = 0;
473 else
474 first_byte = buffer -> head + 1;
475
476 if (first_byte > buffer -> tail) {
61b844bf 477 bytes_this_write = (sizeof buffer -> buf -
c936e8c1 478 first_byte);
61b844bf
TL
479 } else {
480 bytes_this_write =
c936e8c1 481 buffer -> tail - first_byte;
61b844bf
TL
482 }
483 bytes_written = write (c -> socket,
c936e8c1 484 &buffer -> buf [first_byte],
61b844bf
TL
485 bytes_this_write);
486 /* If the write failed with EWOULDBLOCK or we wrote
487 zero bytes, a further write would block, so we have
488 flushed as much as we can for now. Other errors
489 are really errors. */
490 if (bytes_written < 0) {
491 if (errno == EWOULDBLOCK || errno == EAGAIN)
98bf1607 492 return ISC_R_INPROGRESS;
61b844bf
TL
493 else if (errno == EPIPE)
494 return ISC_R_NOCONN;
1bd18042 495#ifdef EDQUOT
61b844bf 496 else if (errno == EFBIG || errno == EDQUOT)
1bd18042
TL
497#else
498 else if (errno == EFBIG)
499#endif
61b844bf
TL
500 return ISC_R_NORESOURCES;
501 else if (errno == ENOSPC)
502 return ISC_R_NOSPACE;
503 else if (errno == EIO)
504 return ISC_R_IOERROR;
505 else if (errno == EINVAL)
98bf1607 506 return DHCP_R_INVALIDARG;
61b844bf
TL
507 else if (errno == ECONNRESET)
508 return ISC_R_SHUTTINGDOWN;
509 else
510 return ISC_R_UNEXPECTED;
511 }
512 if (bytes_written == 0)
98bf1607 513 return ISC_R_INPROGRESS;
61b844bf 514
c1a3453e
TL
515#if defined (TRACING)
516 if (trace_record ()) {
66cebfcb 517 isc_result_t status;
c1a3453e
TL
518 trace_iov_t iov [2];
519 int32_t connect_index;
520
521 connect_index = htonl (c -> index);
522
523 iov [0].buf = (char *)&connect_index;
524 iov [0].len = sizeof connect_index;
525 iov [1].buf = &buffer -> buf [buffer -> tail];
526 iov [1].len = bytes_written;
527
528 status = (trace_write_packet_iov
529 (trace_connection_input, 2, iov,
530 MDL));
531 if (status != ISC_R_SUCCESS) {
532 trace_stop ();
533 log_error ("trace %s output: %s",
534 "connection",
535 isc_result_totext (status));
536 }
537 }
538#endif
539
c936e8c1 540 buffer -> head = first_byte + bytes_written - 1;
61b844bf
TL
541 c -> out_bytes -= bytes_written;
542
543 /* If we didn't finish out the write, we filled the
544 O.S. output buffer and a further write would block,
545 so stop trying to flush now. */
546 if (bytes_written != bytes_this_write)
98bf1607 547 return ISC_R_INPROGRESS;
61b844bf
TL
548 }
549
c936e8c1 550 if (!BYTES_IN_BUFFER (buffer))
61b844bf
TL
551 buffer = buffer -> next;
552 }
553
554 /* Get rid of any output buffers we emptied. */
555 buffer = (omapi_buffer_t *)0;
556 while (c -> outbufs &&
c936e8c1 557 !BYTES_IN_BUFFER (c -> outbufs)) {
61b844bf 558 if (c -> outbufs -> next) {
4bd8800e
TL
559 omapi_buffer_reference (&buffer,
560 c -> outbufs -> next, MDL);
561 omapi_buffer_dereference (&c -> outbufs -> next, MDL);
61b844bf 562 }
4bd8800e 563 omapi_buffer_dereference (&c -> outbufs, MDL);
61b844bf 564 if (buffer) {
4bd8800e
TL
565 omapi_buffer_reference (&c -> outbufs, buffer, MDL);
566 omapi_buffer_dereference (&buffer, MDL);
61b844bf
TL
567 }
568 }
569 return ISC_R_SUCCESS;
570}
571
572isc_result_t omapi_connection_get_uint32 (omapi_object_t *c,
573 u_int32_t *result)
574{
575 u_int32_t inbuf;
576 isc_result_t status;
577
578 status = omapi_connection_copyout ((unsigned char *)&inbuf,
579 c, sizeof inbuf);
580 if (status != ISC_R_SUCCESS)
581 return status;
582
583 *result = ntohl (inbuf);
584 return ISC_R_SUCCESS;
585}
586
587isc_result_t omapi_connection_put_uint32 (omapi_object_t *c,
588 u_int32_t value)
589{
590 u_int32_t inbuf;
61b844bf
TL
591
592 inbuf = htonl (value);
593
594 return omapi_connection_copyin (c, (unsigned char *)&inbuf,
595 sizeof inbuf);
596}
597
598isc_result_t omapi_connection_get_uint16 (omapi_object_t *c,
599 u_int16_t *result)
600{
601 u_int16_t inbuf;
602 isc_result_t status;
603
604 status = omapi_connection_copyout ((unsigned char *)&inbuf,
605 c, sizeof inbuf);
606 if (status != ISC_R_SUCCESS)
607 return status;
608
609 *result = ntohs (inbuf);
610 return ISC_R_SUCCESS;
611}
612
613isc_result_t omapi_connection_put_uint16 (omapi_object_t *c,
b1b7b521 614 u_int32_t value)
61b844bf
TL
615{
616 u_int16_t inbuf;
61b844bf
TL
617
618 inbuf = htons (value);
619
620 return omapi_connection_copyin (c, (unsigned char *)&inbuf,
621 sizeof inbuf);
622}
623
581e37e4
TL
624isc_result_t omapi_connection_write_typed_data (omapi_object_t *c,
625 omapi_typed_data_t *data)
626{
627 isc_result_t status;
628 omapi_handle_t handle;
629
84b00685
TL
630 /* Null data is valid. */
631 if (!data)
632 return omapi_connection_put_uint32 (c, 0);
633
581e37e4
TL
634 switch (data -> type) {
635 case omapi_datatype_int:
636 status = omapi_connection_put_uint32 (c, sizeof (u_int32_t));
637 if (status != ISC_R_SUCCESS)
638 return status;
b1b7b521
TL
639 return omapi_connection_put_uint32 (c, ((u_int32_t)
640 (data -> u.integer)));
581e37e4
TL
641
642 case omapi_datatype_string:
643 case omapi_datatype_data:
644 status = omapi_connection_put_uint32 (c, data -> u.buffer.len);
645 if (status != ISC_R_SUCCESS)
646 return status;
0e603324
TL
647 if (data -> u.buffer.len)
648 return omapi_connection_copyin
649 (c, data -> u.buffer.value,
650 data -> u.buffer.len);
651 return ISC_R_SUCCESS;
581e37e4
TL
652
653 case omapi_datatype_object:
0e603324
TL
654 if (data -> u.object) {
655 status = omapi_object_handle (&handle,
656 data -> u.object);
657 if (status != ISC_R_SUCCESS)
658 return status;
659 } else
660 handle = 0;
581e37e4
TL
661 status = omapi_connection_put_uint32 (c, sizeof handle);
662 if (status != ISC_R_SUCCESS)
663 return status;
664 return omapi_connection_put_uint32 (c, handle);
665
666 }
98bf1607 667 return DHCP_R_INVALIDARG;
581e37e4
TL
668}
669
b1b7b521 670isc_result_t omapi_connection_put_name (omapi_object_t *c, const char *name)
581e37e4
TL
671{
672 isc_result_t status;
b1b7b521 673 unsigned len = strlen (name);
581e37e4
TL
674
675 status = omapi_connection_put_uint16 (c, len);
676 if (status != ISC_R_SUCCESS)
677 return status;
b1b7b521 678 return omapi_connection_copyin (c, (const unsigned char *)name, len);
581e37e4
TL
679}
680
b1b7b521
TL
681isc_result_t omapi_connection_put_string (omapi_object_t *c,
682 const char *string)
581e37e4
TL
683{
684 isc_result_t status;
b1b7b521 685 unsigned len;
581e37e4 686
0e603324
TL
687 if (string)
688 len = strlen (string);
689 else
690 len = 0;
581e37e4
TL
691
692 status = omapi_connection_put_uint32 (c, len);
693 if (status != ISC_R_SUCCESS)
694 return status;
0e603324
TL
695 if (len)
696 return omapi_connection_copyin
697 (c, (const unsigned char *)string, len);
698 return ISC_R_SUCCESS;
581e37e4
TL
699}
700
701isc_result_t omapi_connection_put_handle (omapi_object_t *c, omapi_object_t *h)
702{
703 isc_result_t status;
704 omapi_handle_t handle;
705
0e603324
TL
706 if (h) {
707 status = omapi_object_handle (&handle, h);
708 if (status != ISC_R_SUCCESS)
709 return status;
710 } else
711 handle = 0; /* The null handle. */
581e37e4
TL
712 status = omapi_connection_put_uint32 (c, sizeof handle);
713 if (status != ISC_R_SUCCESS)
714 return status;
715 return omapi_connection_put_uint32 (c, handle);
716}
08b2d347
SR
717
718isc_result_t omapi_connection_put_named_uint32 (omapi_object_t *c,
719 const char *name,
720 u_int32_t value)
721{
722 isc_result_t status;
723
724 status = omapi_connection_put_name(c, name);
725 if (status != ISC_R_SUCCESS)
726 return (status);
727
728 status = omapi_connection_put_uint32(c, sizeof(u_int32_t));
729 if (status != ISC_R_SUCCESS)
730 return (status);
731
732 status = omapi_connection_put_uint32(c, value);
733 return (status);
734}
735