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