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