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