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