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