omapip/protocol.c

Go to the documentation of this file.
00001 /* protocol.c
00002 
00003    Functions supporting the object management protocol... */
00004 
00005 /*
00006  * Copyright (c) 2009,2012,2014 by Internet Systems Consortium, Inc. ("ISC")
00007  * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
00008  * Copyright (c) 1999-2003 by Internet Software Consortium
00009  *
00010  * Permission to use, copy, modify, and distribute this software for any
00011  * purpose with or without fee is hereby granted, provided that the above
00012  * copyright notice and this permission notice appear in all copies.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00015  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00016  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00017  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00018  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00019  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00020  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00021  *
00022  *   Internet Systems Consortium, Inc.
00023  *   950 Charter Street
00024  *   Redwood City, CA 94063
00025  *   <info@isc.org>
00026  *   https://www.isc.org/
00027  *
00028  */
00029 
00030 #include "dhcpd.h"
00031 
00032 #include <omapip/omapip_p.h>
00033 
00034 OMAPI_OBJECT_ALLOC (omapi_protocol, omapi_protocol_object_t,
00035                     omapi_type_protocol)
00036 OMAPI_OBJECT_ALLOC (omapi_protocol_listener, omapi_protocol_listener_object_t,
00037                     omapi_type_protocol_listener)
00038 
00039 isc_result_t omapi_protocol_connect (omapi_object_t *h,
00040                                      const char *server_name,
00041                                      unsigned port,
00042                                      omapi_object_t *a)
00043 {
00044         isc_result_t rstatus, status;
00045         omapi_protocol_object_t *obj;
00046 
00047 #ifdef DEBUG_PROTOCOL
00048         log_debug ("omapi_protocol_connect(%s port=%d)", server_name, port);
00049 #endif
00050 
00051         obj = (omapi_protocol_object_t *)0;
00052         status = omapi_protocol_allocate (&obj, MDL);
00053         if (status != ISC_R_SUCCESS)
00054                 return status;
00055 
00056         rstatus = omapi_connect ((omapi_object_t *)obj, server_name, port);
00057         if (rstatus != ISC_R_SUCCESS && rstatus != DHCP_R_INCOMPLETE) {
00058                 omapi_protocol_dereference (&obj, MDL);
00059                 return rstatus;
00060         }
00061         status = omapi_object_reference (&h -> outer,
00062                                          (omapi_object_t *)obj, MDL);
00063         if (status != ISC_R_SUCCESS) {
00064                 omapi_protocol_dereference (&obj, MDL);
00065                 return status;
00066         }
00067         status = omapi_object_reference (&obj -> inner, h, MDL);
00068         if (status != ISC_R_SUCCESS) {
00069                 omapi_protocol_dereference (&obj, MDL);
00070                 return status;
00071         }
00072 
00073         /* If we were passed a default authenticator, store it now.  We'll
00074            open it once we're connected. */
00075         if (a) {
00076                 obj -> default_auth =
00077                         dmalloc (sizeof(omapi_remote_auth_t), MDL);
00078                 if (!obj -> default_auth) {
00079                         omapi_protocol_dereference (&obj, MDL);
00080                         return ISC_R_NOMEMORY;
00081                 }
00082 
00083                 obj -> default_auth -> next = (omapi_remote_auth_t *)0;
00084                 status = omapi_object_reference (&obj -> default_auth -> a,
00085                                                  a, MDL);
00086                 if (status != ISC_R_SUCCESS) {
00087                         dfree (obj -> default_auth, MDL);
00088                         omapi_protocol_dereference (&obj, MDL);
00089                         return status;
00090                 }
00091 
00092                 obj -> insecure = 0;
00093                 rstatus = DHCP_R_INCOMPLETE;
00094         } else {
00095                 obj -> insecure = 1;
00096 #if 0
00097                 status = ISC_R_SUCCESS;
00098 #endif
00099         }
00100 
00101         omapi_protocol_dereference (&obj, MDL);
00102         return rstatus;
00103 }
00104 
00105 /* Send the protocol introduction message. */
00106 isc_result_t omapi_protocol_send_intro (omapi_object_t *h,
00107                                         unsigned ver,
00108                                         unsigned hsize)
00109 {
00110         isc_result_t status;
00111         omapi_protocol_object_t *p;
00112 
00113 #ifdef DEBUG_PROTOCOL
00114         log_debug ("omapi_protocol_send_intro()");
00115 #endif
00116 
00117         if (h -> type != omapi_type_protocol)
00118                 return DHCP_R_INVALIDARG;
00119         p = (omapi_protocol_object_t *)h;
00120 
00121         if (!h -> outer || h -> outer -> type != omapi_type_connection)
00122                 return ISC_R_NOTCONNECTED;
00123 
00124         status = omapi_connection_put_uint32 (h -> outer, ver);
00125         if (status != ISC_R_SUCCESS)
00126                 return status;
00127 
00128         status = omapi_connection_put_uint32 (h -> outer, hsize);
00129 
00130         if (status != ISC_R_SUCCESS)
00131                 return status;
00132 
00133         /* Require the other end to send an intro - this kicks off the
00134            protocol input state machine. */
00135         p -> state = omapi_protocol_intro_wait;
00136         status = omapi_connection_require (h -> outer, 8);
00137         if (status != ISC_R_SUCCESS && status != DHCP_R_NOTYET)
00138                 return status;
00139 
00140         /* Make up an initial transaction ID for this connection. */
00141         p -> next_xid = random ();
00142         return ISC_R_SUCCESS;
00143 }
00144 
00145 #ifdef DEBUG_PROTOCOL
00146 extern const char *omapi_message_op_name(int);
00147 #endif /* DEBUG_PROTOCOL */
00148 
00149 isc_result_t omapi_protocol_send_message (omapi_object_t *po,
00150                                           omapi_object_t *id,
00151                                           omapi_object_t *mo,
00152                                           omapi_object_t *omo)
00153 {
00154         omapi_protocol_object_t *p;
00155         omapi_object_t *c;
00156         omapi_message_object_t *m, *om;
00157         omapi_remote_auth_t *ra;
00158         omapi_value_t *signature;
00159         isc_result_t status;
00160         unsigned auth_len;
00161 
00162         if (po -> type != omapi_type_protocol ||
00163             !po -> outer || po -> outer -> type != omapi_type_connection ||
00164             mo -> type != omapi_type_message)
00165                 return DHCP_R_INVALIDARG;
00166         if (omo && omo -> type != omapi_type_message)
00167                 return DHCP_R_INVALIDARG;
00168         p = (omapi_protocol_object_t *)po;
00169         c = (omapi_object_t *)(po -> outer);
00170         m = (omapi_message_object_t *)mo;
00171         om = (omapi_message_object_t *)omo;
00172 
00173 #ifdef DEBUG_PROTOCOL
00174         log_debug ("omapi_protocol_send_message(): "
00175                    "op=%s  handle=%#lx  id=%#lx  rid=%#lx",
00176                    omapi_message_op_name (m->op),
00177                    (long)(m -> object ? m -> object -> handle : m -> handle),
00178                    (long)p -> next_xid, (long)m -> rid);
00179 #endif
00180 
00181         /* Find the authid to use for this message. */
00182         if (id) {
00183                 for (ra = p -> remote_auth_list; ra; ra = ra -> next) {
00184                         if (ra -> a == id) {
00185                                 break;
00186                         }
00187                 }
00188 
00189                 if (!ra)
00190                         return DHCP_R_KEY_UNKNOWN;
00191         } else if (p -> remote_auth_list) {
00192                 ra = p -> default_auth;
00193         } else {
00194                 ra = (omapi_remote_auth_t *)0;
00195         }
00196 
00197         if (ra) {
00198                 m -> authid = ra -> remote_handle;
00199                 status = omapi_object_reference (&m -> id_object,
00200                                                  ra -> a, MDL);
00201                 if (status != ISC_R_SUCCESS)
00202                         return status;
00203         }
00204 
00205         /* Write the ID of the authentication key we're using. */
00206         status = omapi_connection_put_uint32 (c, ra ? ra -> remote_handle : 0);
00207         if (status != ISC_R_SUCCESS) {
00208                 omapi_disconnect (c, 1);
00209                 return status;
00210         }
00211 
00212         /* Activate the authentication key on the connection. */
00213         auth_len = 0;
00214         if (ra) {
00215                 status = omapi_set_object_value (c, (omapi_object_t *)0,
00216                                                  "output-authenticator",
00217                                                  ra -> a);
00218                 if (status != ISC_R_SUCCESS) {
00219                         omapi_disconnect (c, 1);
00220                         return status;
00221                 }
00222 
00223                 status = omapi_connection_output_auth_length (c, &auth_len);
00224                 if (status != ISC_R_SUCCESS) {
00225                         omapi_disconnect (c, 1);
00226                         return status;
00227                 }
00228         }
00229 
00230         /* Write the authenticator length */
00231         status = omapi_connection_put_uint32 (c, auth_len);
00232         if (status != ISC_R_SUCCESS) {
00233                 omapi_disconnect (c, 1);
00234                 return status;
00235         }
00236 
00237         /* Write the opcode. */
00238         status = omapi_connection_put_uint32 (c, m -> op);
00239         if (status != ISC_R_SUCCESS) {
00240                 omapi_disconnect (c, 1);
00241                 return status;
00242         }
00243 
00244         /* Write the handle.  If we've been given an explicit handle, use
00245            that.   Otherwise, use the handle of the object we're sending.
00246            The caller is responsible for arranging for one of these handles
00247            to be set (or not). */
00248         status = omapi_connection_put_uint32 (c, (m -> h
00249                                                   ? m -> h
00250                                                   : (m -> object
00251                                                      ? m -> object -> handle
00252                                                      : 0)));
00253         if (status != ISC_R_SUCCESS) {
00254                 omapi_disconnect (c, 1);
00255                 return status;
00256         }
00257 
00258         /* Set and write the transaction ID. */
00259         m -> id = p -> next_xid++;
00260         status = omapi_connection_put_uint32 (c, m -> id);
00261         if (status != ISC_R_SUCCESS) {
00262                 omapi_disconnect (c, 1);
00263                 return status;
00264         }
00265 
00266         /* Write the transaction ID of the message to which this is a
00267            response, if there is such a message. */
00268         status = omapi_connection_put_uint32 (c, om ? om -> id : m -> rid);
00269         if (status != ISC_R_SUCCESS) {
00270                 omapi_disconnect (c, 1);
00271                 return status;
00272         }
00273 
00274         /* Stuff out the name/value pairs specific to this message. */
00275         status = omapi_stuff_values (c, id, (omapi_object_t *)m);
00276         if (status != ISC_R_SUCCESS) {
00277                 omapi_disconnect (c, 1);
00278                 return status;
00279         }
00280 
00281         /* Write the zero-length name that terminates the list of name/value
00282            pairs specific to the message. */
00283         status = omapi_connection_put_uint16 (c, 0);
00284         if (status != ISC_R_SUCCESS) {
00285                 omapi_disconnect (c, 1);
00286                 return status;
00287         }
00288 
00289         /* Stuff out all the published name/value pairs in the object that's
00290            being sent in the message, if there is one. */
00291         if (m -> object) {
00292                 status = omapi_stuff_values (c, id, m -> object);
00293                 if (status != ISC_R_SUCCESS) {
00294                         omapi_disconnect (c, 1);
00295                         return status;
00296                 }
00297         }
00298 
00299         /* Write the zero-length name that terminates the list of name/value
00300            pairs for the associated object. */
00301         status = omapi_connection_put_uint16 (c, 0);
00302         if (status != ISC_R_SUCCESS) {
00303                 omapi_disconnect (c, 1);
00304                 return status;
00305         }
00306 
00307         if (ra) {
00308                 /* Calculate the message signature. */
00309                 signature = (omapi_value_t *)0;
00310                 status = omapi_get_value_str (c, (omapi_object_t *)0,
00311                                               "output-signature", &signature);
00312                 if (status != ISC_R_SUCCESS) {
00313                         omapi_disconnect (c, 1);
00314                         return status;
00315                 }
00316 
00317                 /* Write the authenticator... */
00318                 status = (omapi_connection_copyin
00319                           (c, signature -> value -> u.buffer.value,
00320                            signature -> value -> u.buffer.len));
00321                 omapi_value_dereference (&signature, MDL);
00322                 if (status != ISC_R_SUCCESS) {
00323                         omapi_disconnect (c, 1);
00324                         return status;
00325                 }
00326 
00327                 /* Dectivate the authentication key on the connection. */
00328                 status = omapi_set_value_str (c, (omapi_object_t *)0,
00329                                                  "output-authenticator",
00330                                                  (omapi_typed_data_t *)0);
00331                 if (status != ISC_R_SUCCESS) {
00332                         omapi_disconnect (c, 1);
00333                         return status;
00334                 }
00335         }
00336 
00337         if (!omo) {
00338                 omapi_protocol_reference (&m -> protocol_object, p, MDL);
00339         }
00340         return ISC_R_SUCCESS;
00341 }
00342                                           
00343 
00344 isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
00345                                             const char *name, va_list ap)
00346 {
00347         isc_result_t status;
00348         omapi_protocol_object_t *p;
00349         omapi_object_t *c;
00350         omapi_message_object_t *m;
00351         omapi_value_t *signature = NULL;
00352         u_int16_t nlen;
00353         u_int32_t vlen;
00354         u_int32_t th;
00355 #if defined (DEBUG_MEMORY_LEAKAGE)
00356         unsigned long previous_outstanding = 0xDEADBEEF;
00357         unsigned long connect_outstanding = 0xDEADBEEF;
00358 #endif
00359 
00360         if (h -> type != omapi_type_protocol) {
00361                 /* XXX shouldn't happen.   Put an assert here? */
00362                 return ISC_R_UNEXPECTED;
00363         }
00364         p = (omapi_protocol_object_t *)h;
00365 
00366         if (!strcmp (name, "connect")) {
00367 #if defined (DEBUG_MEMORY_LEAKAGE)
00368                 connect_outstanding = dmalloc_outstanding;
00369 #endif
00370                 /* Send the introductory message. */
00371                 status = omapi_protocol_send_intro
00372                         (h, OMAPI_PROTOCOL_VERSION,
00373                          sizeof (omapi_protocol_header_t));
00374                 if (status != ISC_R_SUCCESS) {
00375                         omapi_disconnect (p -> outer, 1);
00376                         return status;
00377                 }
00378                 return ISC_R_SUCCESS;
00379         }
00380 
00381         /* Should only receive these when opening the initial authenticator. */
00382         if (!strcmp (name, "status")) {
00383                 status = va_arg (ap, isc_result_t);
00384                 if (status != ISC_R_SUCCESS) {
00385                         omapi_signal_in (h -> inner, "status", status,
00386                                          (omapi_object_t *)0);
00387                         omapi_disconnect (p -> outer, 1);
00388                         return status;
00389                 } else {
00390                         return omapi_signal_in (h -> inner, "ready");
00391                 }
00392         }
00393 
00394         /* If we get a disconnect, dump memory usage. */
00395         if (!strcmp (name, "disconnect")) {
00396 #if defined (DEBUG_MEMORY_LEAKAGE)
00397             if (connect_outstanding != 0xDEADBEEF) {
00398                 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
00399                           dmalloc_generation,
00400                           dmalloc_outstanding - previous_outstanding,
00401                           dmalloc_outstanding, dmalloc_longterm, " long-term");
00402             }
00403 #endif
00404 #if defined (DEBUG_MEMORY_LEAKAGE)
00405             dmalloc_dump_outstanding ();
00406 #endif
00407 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
00408             dump_rc_history (h);
00409 #endif
00410             for (m = omapi_registered_messages; m; m = m -> next) {
00411                 if (m -> protocol_object == p) {
00412                     if (m -> object)
00413                         omapi_signal (m -> object, "disconnect");
00414                 }
00415             }
00416 
00417             /* XXX */
00418             return ISC_R_SUCCESS;
00419         }
00420 
00421         /* Not a signal we recognize? */
00422         if (strcmp (name, "ready")) {
00423                 if (p -> inner && p -> inner -> type -> signal_handler)
00424                         return (*(p -> inner -> type -> signal_handler)) (h,
00425                                                                           name,
00426                                                                           ap);
00427                 return ISC_R_NOTFOUND;
00428         }
00429 
00430         if (!p -> outer || p -> outer -> type != omapi_type_connection)
00431                 return DHCP_R_INVALIDARG;
00432         c = p -> outer;
00433 
00434         /* We get here because we requested that we be woken up after
00435            some number of bytes were read, and that number of bytes
00436            has in fact been read. */
00437         switch (p -> state) {
00438               case omapi_protocol_intro_wait:
00439                 /* Get protocol version and header size in network
00440                    byte order. */
00441                 omapi_connection_get_uint32 (c, &p -> protocol_version);
00442                 omapi_connection_get_uint32 (c, &p -> header_size);
00443         
00444                 /* We currently only support the current protocol version. */
00445                 if (p -> protocol_version != OMAPI_PROTOCOL_VERSION) {
00446                         omapi_disconnect (c, 1);
00447                         return DHCP_R_VERSIONMISMATCH;
00448                 }
00449 
00450                 if (p -> header_size < sizeof (omapi_protocol_header_t)) {
00451                         omapi_disconnect (c, 1);
00452                         return DHCP_R_PROTOCOLERROR;
00453                 }
00454 
00455                 if (p -> default_auth) {
00456                         status = omapi_protocol_send_open
00457                                 (h, (omapi_object_t *)0, "authenticator",
00458                                  p -> default_auth -> a,
00459                                  OMAPI_NOTIFY_PROTOCOL);
00460                         if (status != ISC_R_SUCCESS) {
00461                                 omapi_disconnect (c, 1);
00462                                 return status;
00463                         }
00464                 } else {
00465                         status = omapi_signal_in (h -> inner, "ready");
00466                 }
00467 
00468               to_header_wait:
00469                 /* The next thing we're expecting is a message header. */
00470                 p -> state = omapi_protocol_header_wait;
00471 
00472                 /* Register a need for the number of bytes in a
00473                    header, and if we already have that many, process
00474                    them immediately. */
00475                 if ((omapi_connection_require (c, p -> header_size)) !=
00476                     ISC_R_SUCCESS)
00477                         break;
00478                 /* If we already have the data, fall through. */
00479 
00480               case omapi_protocol_header_wait:
00481 #if defined (DEBUG_MEMORY_LEAKAGE)
00482                 if (previous_outstanding != 0xDEADBEEF) {
00483                         log_info ("%s %ld: %ld new, %ld outstanding, %ld%s",
00484                                   "generation", dmalloc_generation,
00485                                   dmalloc_outstanding - previous_outstanding,
00486                                   dmalloc_outstanding, dmalloc_longterm,
00487                                   " long-term");
00488 #endif
00489 #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
00490                         dmalloc_dump_outstanding ();
00491 #endif
00492 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
00493                         dump_rc_history (h);
00494 #endif
00495 #if defined (DEBUG_MEMORY_LEAKAGE)
00496                 }
00497                 previous_outstanding = dmalloc_outstanding;
00498 #endif
00499                 status = omapi_message_new ((omapi_object_t **)&p -> message,
00500                                             MDL);
00501                 if (status != ISC_R_SUCCESS) {
00502                         omapi_disconnect (c, 1);
00503                         return status;
00504                 }
00505 
00506                 p -> verify_result = ISC_R_SUCCESS;
00507 
00508                 /* Swap in the header... */
00509                 omapi_connection_get_uint32 (c, &p -> message -> authid);
00510 
00511                 /* Bind the authenticator to the message object. */
00512                 if (p -> message -> authid) {
00513                         status = (omapi_protocol_lookup_auth
00514                                   (&p -> message -> id_object, h,
00515                                    p -> message -> authid));
00516                         if (status != ISC_R_SUCCESS)
00517                                 p -> verify_result = status;
00518 
00519                         /* Activate the authentication key. */
00520                         status = omapi_set_object_value
00521                                 (c, (omapi_object_t *)0, "input-authenticator",
00522                                  p -> message -> id_object);
00523                         if (status != ISC_R_SUCCESS) {
00524                                 omapi_disconnect (c, 1);
00525                                 return status;
00526                         }
00527                 }
00528 
00529                 omapi_connection_get_uint32 (c, &p -> message -> authlen);
00530                 omapi_connection_get_uint32 (c, &p -> message -> op);
00531                 omapi_connection_get_uint32 (c, &th);
00532                 p -> message -> h = th;
00533                 omapi_connection_get_uint32 (c, &p -> message -> id);
00534                 omapi_connection_get_uint32 (c, &p -> message -> rid);
00535 
00536                 /* If there was any extra header data, skip over it. */
00537                 if (p -> header_size > sizeof (omapi_protocol_header_t)) {
00538                         omapi_connection_copyout
00539                                 (0, c, (p -> header_size -
00540                                         sizeof (omapi_protocol_header_t)));
00541                 }
00542                                                      
00543                 /* XXX must compute partial signature across the
00544                    XXX preceding bytes.    Also, if authenticator
00545                    specifies encryption as well as signing, we may
00546                    have to decrypt the data on the way in. */
00547 
00548                 /* First we read in message-specific values, then object
00549                    values. */
00550                 p -> reading_message_values = 1;
00551 
00552               need_name_length:
00553                 /* The next thing we're expecting is length of the
00554                    first name. */
00555                 p -> state = omapi_protocol_name_length_wait;
00556 
00557                 /* Wait for a 16-bit length. */
00558                 if ((omapi_connection_require (c, 2)) != ISC_R_SUCCESS)
00559                         break;
00560                 /* If it's already here, fall through. */
00561 
00562               case omapi_protocol_name_length_wait:
00563                 omapi_connection_get_uint16 (c, &nlen);
00564                 /* A zero-length name means that we're done reading name+value
00565                    pairs. */
00566                 if (nlen == 0) {
00567                         /* If we've already read in the object, we are
00568                            done reading the message, but if we've just
00569                            finished reading in the values associated
00570                            with the message, we need to read the
00571                            object. */
00572                         if (p -> reading_message_values) {
00573                                 p -> reading_message_values = 0;
00574                                 goto need_name_length;
00575                         }
00576 
00577                         /* If the authenticator length is zero, there's no
00578                            signature to read in, so go straight to processing
00579                            the message. */
00580                         if (p -> message -> authlen == 0)
00581                                 goto message_done;
00582 
00583                         /* The next thing we're expecting is the
00584                            message signature. */
00585                         p -> state = omapi_protocol_signature_wait;
00586 
00587                         /* Wait for the number of bytes specified for
00588                            the authenticator.  If we already have it,
00589                            go read it in. */
00590                         if (omapi_connection_require
00591                             (c, p -> message -> authlen) == ISC_R_SUCCESS)
00592                                 goto signature_wait;
00593                         break;
00594                 }
00595 
00596                 /* Allocate a buffer for the name. */
00597                 status = (omapi_data_string_new (&p -> name, nlen, MDL));
00598                 if (status != ISC_R_SUCCESS) {
00599                         omapi_disconnect (c, 1);
00600                         return ISC_R_NOMEMORY;
00601                 }
00602                 p -> state = omapi_protocol_name_wait;
00603                 if (omapi_connection_require (c, nlen) != ISC_R_SUCCESS)
00604                         break;
00605                 /* If it's already here, fall through. */
00606                                              
00607               case omapi_protocol_name_wait:
00608                 omapi_connection_copyout (p -> name -> value, c,
00609                                           p -> name -> len);
00610                 /* Wait for a 32-bit length. */
00611                 p -> state = omapi_protocol_value_length_wait;
00612                 if ((omapi_connection_require (c, 4)) != ISC_R_SUCCESS)
00613                         break;
00614                 /* If it's already here, fall through. */
00615 
00616               case omapi_protocol_value_length_wait:
00617                 omapi_connection_get_uint32 (c, &vlen);
00618 
00619                 /* Zero-length values are allowed - if we get one, we
00620                    don't have to read any data for the value - just
00621                    get the next one, if there is a next one. */
00622                 if (!vlen)
00623                         goto insert_new_value;
00624 
00625                 status = omapi_typed_data_new (MDL, &p -> value,
00626                                                omapi_datatype_data,
00627                                                vlen);
00628                 if (status != ISC_R_SUCCESS) {
00629                         omapi_disconnect (c, 1);
00630                         return ISC_R_NOMEMORY;
00631                 }
00632 
00633                 p -> state = omapi_protocol_value_wait;
00634                 if (omapi_connection_require (c, vlen) != ISC_R_SUCCESS)
00635                         break;
00636                 /* If it's already here, fall through. */
00637                                              
00638               case omapi_protocol_value_wait:
00639                 omapi_connection_copyout (p -> value -> u.buffer.value, c,
00640                                           p -> value -> u.buffer.len);
00641 
00642               insert_new_value:
00643                 if (p -> reading_message_values) {
00644                         status = (omapi_set_value
00645                                   ((omapi_object_t *)p -> message,
00646                                    p -> message -> id_object,
00647                                    p -> name, p -> value));
00648                 } else {
00649                         if (!p -> message -> object) {
00650                                 /* We need a generic object to hang off of the
00651                                    incoming message. */
00652                                 status = (omapi_generic_new
00653                                           (&p -> message -> object, MDL));
00654                                 if (status != ISC_R_SUCCESS) {
00655                                         omapi_disconnect (c, 1);
00656                                         return status;
00657                                 }
00658                         }
00659                         status = (omapi_set_value
00660                                   ((omapi_object_t *)p -> message -> object,
00661                                    p -> message -> id_object,
00662                                    p -> name, p -> value));
00663                 }
00664                 if (status != ISC_R_SUCCESS) {
00665                         omapi_disconnect (c, 1);
00666                         return status;
00667                 }
00668                 omapi_data_string_dereference (&p -> name, MDL);
00669                 if (p -> value)
00670                         omapi_typed_data_dereference (&p -> value, MDL);
00671                 goto need_name_length;
00672 
00673               signature_wait:
00674               case omapi_protocol_signature_wait:
00675                 if (p -> message -> id_object) {
00676                         /* Compute the signature of the message. */
00677                         status = omapi_get_value_str (c, (omapi_object_t *)0,
00678                                                       "input-signature",
00679                                                       &signature);
00680                         if (status != ISC_R_SUCCESS) {
00681                                 omapi_disconnect (c, 1);
00682                                 return status;
00683                         }
00684 
00685                         /* Disable the authentication key on the connection. */
00686                         status = omapi_set_value_str (c, (omapi_object_t *)0,
00687                                                       "input-authenticator",
00688                                                       (omapi_typed_data_t *)0);
00689                         if (status != ISC_R_SUCCESS) {
00690                                 omapi_value_dereference (&signature, MDL);
00691                                 omapi_disconnect (c, 1);
00692                                 return status;
00693                         }
00694                 }
00695 
00696                 /* Read the authenticator. */
00697                 status = omapi_typed_data_new (MDL,
00698                                                &p -> message -> authenticator,
00699                                                omapi_datatype_data,
00700                                                p -> message -> authlen);
00701                         
00702                 if (status != ISC_R_SUCCESS) {
00703                         if (signature != NULL) {
00704                                 omapi_value_dereference (&signature, MDL);
00705                         }
00706                         omapi_disconnect (c, 1);
00707                         return ISC_R_NOMEMORY;
00708                 }
00709                 omapi_connection_copyout
00710                         (p -> message -> authenticator -> u.buffer.value, c,
00711                          p -> message -> authlen);
00712 
00713                 /* Verify the signature. */
00714                 if (p -> message -> id_object &&
00715                     ((signature -> value -> u.buffer.len !=
00716                       p -> message -> authlen) ||
00717                      (memcmp (signature -> value -> u.buffer.value,
00718                               p -> message -> authenticator -> u.buffer.value,
00719                               p -> message -> authlen) != 0))) {
00720                         /* Invalid signature. */
00721                         p->verify_result = DHCP_R_INVALIDKEY;
00722                 }
00723 
00724                 if (signature != NULL) {
00725                         omapi_value_dereference (&signature, MDL);
00726                 }
00727 
00728                 /* Process the message. */
00729               message_done:
00730                 if (p -> verify_result != ISC_R_SUCCESS) {
00731                         status = omapi_protocol_send_status
00732                                 (h, (omapi_object_t *)0, p -> verify_result,
00733                                  p -> message -> id, (char *)0);
00734                 } else {
00735                         status = omapi_message_process
00736                                 ((omapi_object_t *)p -> message, h);
00737                 }
00738                 if (status != ISC_R_SUCCESS) {
00739                         omapi_disconnect (c, 1);
00740                         return ISC_R_NOMEMORY;
00741                 }
00742 
00743                 omapi_message_dereference (&p -> message, MDL);
00744 #if defined (DEBUG_MEMORY_LEAKAGE)
00745                 log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
00746                           dmalloc_generation,
00747                           dmalloc_outstanding - previous_outstanding,
00748                           dmalloc_outstanding, dmalloc_longterm, " long-term");
00749 #endif
00750 #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
00751                 dmalloc_dump_outstanding ();
00752 #endif
00753 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
00754                 dump_rc_history (h);
00755 #endif
00756 #if defined (DEBUG_MEMORY_LEAKAGE)
00757                 previous_outstanding = 0xDEADBEEF;
00758 #endif
00759                 /* Now wait for the next message. */
00760                 goto to_header_wait;            
00761 
00762               default:
00763                 /* XXX should never get here.   Assertion? */
00764                 break;
00765         }
00766         return ISC_R_SUCCESS;
00767 }
00768 
00769 isc_result_t omapi_protocol_add_auth (omapi_object_t *po,
00770                                       omapi_object_t *ao,
00771                                       omapi_handle_t handle)
00772 {
00773         omapi_protocol_object_t *p;
00774         omapi_remote_auth_t *r;
00775         isc_result_t status;
00776 
00777         if (ao -> type != omapi_type_auth_key &&
00778             (!ao -> inner || ao -> inner -> type != omapi_type_auth_key))
00779                 return DHCP_R_INVALIDARG;
00780 
00781         if (po -> type != omapi_type_protocol)
00782                 return DHCP_R_INVALIDARG;
00783         p = (omapi_protocol_object_t *)po;
00784 
00785 #ifdef DEBUG_PROTOCOL
00786         log_debug ("omapi_protocol_add_auth(name=%s)",
00787                    ((omapi_auth_key_t *)ao) -> name);
00788 #endif
00789 
00790         if (p -> verify_auth) {
00791                 status = (p -> verify_auth) (po, (omapi_auth_key_t *)ao);
00792                 if (status != ISC_R_SUCCESS)
00793                         return status;
00794         }
00795 
00796         /* If omapi_protocol_connect() was called with a default
00797            authenticator, p -> default_auth will already be set,
00798            but p -> remote_auth_list will not yet be initialized. */
00799         if (p -> default_auth && !p -> remote_auth_list) {
00800                 if (p -> default_auth -> a != ao) {
00801                         /* Something just went horribly wrong. */
00802                         omapi_disconnect (p -> outer, 1);
00803                         return ISC_R_UNEXPECTED;
00804                 }
00805 
00806                 p -> remote_auth_list = p -> default_auth;
00807                 p -> default_auth -> remote_handle = handle;
00808 
00809                 return omapi_signal_in (p -> inner, "ready");
00810         }
00811 
00812         r = dmalloc (sizeof(*r), MDL);
00813         if (!r)
00814                 return ISC_R_NOMEMORY;
00815 
00816         status = omapi_object_reference (&r -> a, ao, MDL);
00817         if (status != ISC_R_SUCCESS) {
00818                 dfree (r, MDL);
00819                 return status;
00820         }
00821 
00822         r -> remote_handle = handle;
00823         r -> next = p -> remote_auth_list;
00824         p -> remote_auth_list = r;
00825 
00826         return ISC_R_SUCCESS;
00827 }
00828 
00829 isc_result_t omapi_protocol_lookup_auth (omapi_object_t **a,
00830                                          omapi_object_t *po,
00831                                          omapi_handle_t handle)
00832 {
00833         omapi_protocol_object_t *p;
00834         omapi_remote_auth_t *r;
00835 
00836         if (po -> type != omapi_type_protocol)
00837                 return DHCP_R_INVALIDARG;
00838         p = (omapi_protocol_object_t *)po;
00839 
00840         for (r = p -> remote_auth_list; r; r = r -> next)
00841                 if (r -> remote_handle == handle)
00842                         return omapi_object_reference (a, r -> a, MDL);
00843 
00844         return DHCP_R_KEY_UNKNOWN;
00845 }
00846 
00847 isc_result_t omapi_protocol_set_value (omapi_object_t *h,
00848                                        omapi_object_t *id,
00849                                        omapi_data_string_t *name,
00850                                        omapi_typed_data_t *value)
00851 {
00852         omapi_protocol_object_t *p;
00853         omapi_remote_auth_t *r;
00854 
00855         if (h -> type != omapi_type_protocol)
00856                 return DHCP_R_INVALIDARG;
00857         p = (omapi_protocol_object_t *)h;
00858 
00859         if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
00860                 if (!value || value -> type != omapi_datatype_object)
00861                         return DHCP_R_INVALIDARG;
00862 
00863                 if (!value -> u.object) {
00864                         p -> default_auth = (omapi_remote_auth_t *)0;
00865                 } else {
00866                         for (r = p -> remote_auth_list; r; r = r -> next)
00867                                 if (r -> a == value -> u.object)
00868                                         break;
00869 
00870                         if (!r)
00871                                 return DHCP_R_KEY_UNKNOWN;
00872 
00873                         p -> default_auth = r;
00874                 }
00875 
00876                 return ISC_R_SUCCESS;
00877         }
00878 
00879         if (h -> inner && h -> inner -> type -> set_value)
00880                 return (*(h -> inner -> type -> set_value))
00881                         (h -> inner, id, name, value);
00882         return ISC_R_NOTFOUND;
00883 }
00884 
00885 isc_result_t omapi_protocol_get_value (omapi_object_t *h,
00886                                        omapi_object_t *id,
00887                                        omapi_data_string_t *name,
00888                                        omapi_value_t **value)
00889 {
00890         omapi_protocol_object_t *p;
00891 
00892         if (h -> type != omapi_type_protocol)
00893                 return DHCP_R_INVALIDARG;
00894         p = (omapi_protocol_object_t *)h;
00895 
00896         if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
00897                 if (!p -> default_auth)
00898                         return ISC_R_NOTFOUND;
00899 
00900                 return omapi_make_object_value (value, name,
00901                                                 p -> default_auth -> a, MDL);
00902         }
00903         
00904         if (h -> inner && h -> inner -> type -> get_value)
00905                 return (*(h -> inner -> type -> get_value))
00906                         (h -> inner, id, name, value);
00907         return ISC_R_NOTFOUND;
00908 }
00909 
00910 isc_result_t omapi_protocol_destroy (omapi_object_t *h,
00911                                      const char *file, int line)
00912 {
00913         omapi_protocol_object_t *p;
00914         if (h -> type != omapi_type_protocol)
00915                 return DHCP_R_INVALIDARG;
00916         p = (omapi_protocol_object_t *)h;
00917         if (p -> message)
00918                 omapi_message_dereference (&p -> message, file, line);
00919 
00920         /* This will happen if: 1) A default authenticator is supplied to
00921            omapi_protocol_connect(), and 2) something goes wrong before
00922            the authenticator can be opened. */
00923         if (p -> default_auth && !p -> remote_auth_list)
00924                 dfree (p -> default_auth, file, line);
00925 
00926         while (p -> remote_auth_list) {
00927                 omapi_remote_auth_t *r = p -> remote_auth_list;
00928                 p -> remote_auth_list =  p -> remote_auth_list -> next;
00929                 omapi_object_dereference (&r -> a, file, line);
00930                 dfree (r, file, line);
00931         }
00932         return ISC_R_SUCCESS;
00933 }
00934 
00935 /* Write all the published values associated with the object through the
00936    specified connection. */
00937 
00938 isc_result_t omapi_protocol_stuff_values (omapi_object_t *c,
00939                                           omapi_object_t *id,
00940                                           omapi_object_t *p)
00941 {
00942         if (p -> type != omapi_type_protocol)
00943                 return DHCP_R_INVALIDARG;
00944 
00945         if (p -> inner && p -> inner -> type -> stuff_values)
00946                 return (*(p -> inner -> type -> stuff_values)) (c, id,
00947                                                                 p -> inner);
00948         return ISC_R_SUCCESS;
00949 }
00950 
00951 /* Returns a boolean indicating whether this protocol requires that
00952    messages be authenticated or not. */
00953 
00954 isc_boolean_t omapi_protocol_authenticated (omapi_object_t *h)
00955 {
00956         if (h -> type != omapi_type_protocol)
00957                 return isc_boolean_false;
00958         if (((omapi_protocol_object_t *)h) -> insecure)
00959                 return isc_boolean_false;
00960         else
00961                 return isc_boolean_true;
00962 }
00963 
00964 /* Sets the address and authenticator verification callbacks.  The handle
00965    is to a listener object, not a protocol object. */
00966 
00967 isc_result_t omapi_protocol_configure_security (omapi_object_t *h,
00968                                                 isc_result_t (*verify_addr)
00969                                                  (omapi_object_t *,
00970                                                   omapi_addr_t *),
00971                                                 isc_result_t (*verify_auth)
00972                                                  (omapi_object_t *,
00973                                                   omapi_auth_key_t *))
00974 {
00975         omapi_protocol_listener_object_t *l;
00976 
00977         if (h -> outer && h -> outer -> type == omapi_type_protocol_listener)
00978                 h = h -> outer;
00979 
00980         if (h -> type != omapi_type_protocol_listener)
00981                 return DHCP_R_INVALIDARG;
00982         l = (omapi_protocol_listener_object_t *)h;
00983 
00984         l -> verify_auth = verify_auth;
00985         l -> insecure = 0;
00986 
00987         if (h -> outer != NULL) {
00988                 return omapi_listener_configure_security (h -> outer, verify_addr);
00989         } else {
00990                 return DHCP_R_INVALIDARG;
00991         }
00992 }
00993                                               
00994 
00995 /* Set up a listener for the omapi protocol.    The handle stored points to
00996    a listener object, not a protocol object. */
00997 
00998 isc_result_t omapi_protocol_listen (omapi_object_t *h,
00999                                     unsigned port,
01000                                     int max)
01001 {
01002         isc_result_t status;
01003         omapi_protocol_listener_object_t *obj;
01004 
01005         obj = (omapi_protocol_listener_object_t *)0;
01006         status = omapi_protocol_listener_allocate (&obj, MDL);
01007         if (status != ISC_R_SUCCESS)
01008                 return status;
01009 
01010         status = omapi_object_reference (&h -> outer,
01011                                          (omapi_object_t *)obj, MDL);
01012         if (status != ISC_R_SUCCESS) {
01013                 omapi_protocol_listener_dereference (&obj, MDL);
01014                 return status;
01015         }
01016         status = omapi_object_reference (&obj -> inner, h, MDL);
01017         if (status != ISC_R_SUCCESS) {
01018                 omapi_protocol_listener_dereference (&obj, MDL);
01019                 return status;
01020         }
01021 
01022         /* What a terrible default. */
01023         obj -> insecure = 1;
01024 
01025         status = omapi_listen ((omapi_object_t *)obj, port, max);
01026         omapi_protocol_listener_dereference (&obj, MDL);
01027         return status;
01028 }
01029 
01030 /* Signal handler for protocol listener - if we get a connect signal,
01031    create a new protocol connection, otherwise pass the signal down. */
01032 
01033 isc_result_t omapi_protocol_listener_signal (omapi_object_t *o,
01034                                              const char *name, va_list ap)
01035 {
01036         isc_result_t status;
01037         omapi_object_t *c;
01038         omapi_protocol_object_t *obj;
01039         omapi_protocol_listener_object_t *p;
01040 
01041         if (!o || o -> type != omapi_type_protocol_listener)
01042                 return DHCP_R_INVALIDARG;
01043         p = (omapi_protocol_listener_object_t *)o;
01044 
01045         /* Not a signal we recognize? */
01046         if (strcmp (name, "connect")) {
01047                 if (p -> inner && p -> inner -> type -> signal_handler)
01048                         return (*(p -> inner -> type -> signal_handler))
01049                                 (p -> inner, name, ap);
01050                 return ISC_R_NOTFOUND;
01051         }
01052 
01053         c = va_arg (ap, omapi_object_t *);
01054         if (!c || c -> type != omapi_type_connection)
01055                 return DHCP_R_INVALIDARG;
01056 
01057         obj = (omapi_protocol_object_t *)0;
01058         status = omapi_protocol_allocate (&obj, MDL);
01059         if (status != ISC_R_SUCCESS)
01060                 return status;
01061 
01062         obj -> verify_auth = p -> verify_auth;
01063         obj -> insecure = p -> insecure;
01064 
01065         status = omapi_object_reference (&obj -> outer, c, MDL);
01066         if (status != ISC_R_SUCCESS) {
01067               lose:
01068                 omapi_protocol_dereference (&obj, MDL);
01069                 omapi_disconnect (c, 1);
01070                 return status;
01071         }
01072 
01073         status = omapi_object_reference (&c -> inner,
01074                                          (omapi_object_t *)obj, MDL);
01075         if (status != ISC_R_SUCCESS)
01076                 goto lose;
01077 
01078         /* Send the introductory message. */
01079         status = omapi_protocol_send_intro ((omapi_object_t *)obj,
01080                                             OMAPI_PROTOCOL_VERSION,
01081                                             sizeof (omapi_protocol_header_t));
01082         if (status != ISC_R_SUCCESS)
01083                 goto lose;
01084 
01085         omapi_protocol_dereference (&obj, MDL);
01086         return status;
01087 }
01088 
01089 isc_result_t omapi_protocol_listener_set_value (omapi_object_t *h,
01090                                                 omapi_object_t *id,
01091                                                 omapi_data_string_t *name,
01092                                                 omapi_typed_data_t *value)
01093 {
01094         if (h -> type != omapi_type_protocol_listener)
01095                 return DHCP_R_INVALIDARG;
01096         
01097         if (h -> inner && h -> inner -> type -> set_value)
01098                 return (*(h -> inner -> type -> set_value))
01099                         (h -> inner, id, name, value);
01100         return ISC_R_NOTFOUND;
01101 }
01102 
01103 isc_result_t omapi_protocol_listener_get_value (omapi_object_t *h,
01104                                                 omapi_object_t *id,
01105                                                 omapi_data_string_t *name,
01106                                                 omapi_value_t **value)
01107 {
01108         if (h -> type != omapi_type_protocol_listener)
01109                 return DHCP_R_INVALIDARG;
01110         
01111         if (h -> inner && h -> inner -> type -> get_value)
01112                 return (*(h -> inner -> type -> get_value))
01113                         (h -> inner, id, name, value);
01114         return ISC_R_NOTFOUND;
01115 }
01116 
01117 isc_result_t omapi_protocol_listener_destroy (omapi_object_t *h,
01118                                               const char *file, int line)
01119 {
01120         if (h -> type != omapi_type_protocol_listener)
01121                 return DHCP_R_INVALIDARG;
01122         return ISC_R_SUCCESS;
01123 }
01124 
01125 /* Write all the published values associated with the object through the
01126    specified connection. */
01127 
01128 isc_result_t omapi_protocol_listener_stuff (omapi_object_t *c,
01129                                             omapi_object_t *id,
01130                                             omapi_object_t *p)
01131 {
01132         if (p -> type != omapi_type_protocol_listener)
01133                 return DHCP_R_INVALIDARG;
01134 
01135         if (p -> inner && p -> inner -> type -> stuff_values)
01136                 return (*(p -> inner -> type -> stuff_values)) (c, id,
01137                                                                 p -> inner);
01138         return ISC_R_SUCCESS;
01139 }
01140 
01141 isc_result_t omapi_protocol_send_status (omapi_object_t *po,
01142                                          omapi_object_t *id,
01143                                          isc_result_t waitstatus,
01144                                          unsigned rid, const char *msg)
01145 {
01146         isc_result_t status;
01147         omapi_message_object_t *message = (omapi_message_object_t *)0;
01148         omapi_object_t *mo;
01149 
01150         if (po -> type != omapi_type_protocol)
01151                 return DHCP_R_INVALIDARG;
01152 
01153         status = omapi_message_new ((omapi_object_t **)&message, MDL);
01154         if (status != ISC_R_SUCCESS)
01155                 return status;
01156         mo = (omapi_object_t *)message;
01157 
01158         status = omapi_set_int_value (mo, (omapi_object_t *)0,
01159                                       "op", OMAPI_OP_STATUS);
01160         if (status != ISC_R_SUCCESS) {
01161                 omapi_message_dereference (&message, MDL);
01162                 return status;
01163         }
01164 
01165         status = omapi_set_int_value (mo, (omapi_object_t *)0,
01166                                       "rid", (int)rid);
01167         if (status != ISC_R_SUCCESS) {
01168                 omapi_message_dereference (&message, MDL);
01169                 return status;
01170         }
01171 
01172         status = omapi_set_int_value (mo, (omapi_object_t *)0,
01173                                       "result", (int)waitstatus);
01174         if (status != ISC_R_SUCCESS) {
01175                 omapi_message_dereference (&message, MDL);
01176                 return status;
01177         }
01178 
01179         /* If a message has been provided, send it. */
01180         if (msg) {
01181                 status = omapi_set_string_value (mo, (omapi_object_t *)0,
01182                                                  "message", msg);
01183                 if (status != ISC_R_SUCCESS) {
01184                         omapi_message_dereference (&message, MDL);
01185                         return status;
01186                 }
01187         }
01188 
01189         status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
01190         omapi_message_dereference (&message, MDL);
01191         return status;
01192 }
01193 
01194 /* The OMAPI_NOTIFY_PROTOCOL flag will cause the notify-object for the
01195    message to be set to the protocol object.  This is used when opening
01196    the default authenticator. */
01197 
01198 isc_result_t omapi_protocol_send_open (omapi_object_t *po,
01199                                        omapi_object_t *id,
01200                                        const char *type,
01201                                        omapi_object_t *object,
01202                                        unsigned flags)
01203 {
01204         isc_result_t status;
01205         omapi_message_object_t *message = (omapi_message_object_t *)0;
01206         omapi_object_t *mo;
01207 
01208         if (po -> type != omapi_type_protocol)
01209                 return DHCP_R_INVALIDARG;
01210 
01211         status = omapi_message_new ((omapi_object_t **)&message, MDL);
01212         mo = (omapi_object_t *)message;
01213 
01214         if (status == ISC_R_SUCCESS)
01215                 status = omapi_set_int_value (mo, (omapi_object_t *)0,
01216                                               "op", OMAPI_OP_OPEN);
01217 
01218         if (status == ISC_R_SUCCESS)
01219                 status = omapi_set_object_value (mo, (omapi_object_t *)0,
01220                                                  "object", object);
01221 
01222         if ((flags & OMAPI_CREATE) && (status == ISC_R_SUCCESS))
01223                 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
01224                                                   "create", 1);
01225 
01226         if ((flags & OMAPI_UPDATE) && (status == ISC_R_SUCCESS))
01227                 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
01228                                                   "update", 1);
01229 
01230         if ((flags & OMAPI_EXCL) && (status == ISC_R_SUCCESS))
01231                 status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
01232                                                   "exclusive", 1);
01233 
01234         if ((flags & OMAPI_NOTIFY_PROTOCOL) && (status == ISC_R_SUCCESS))
01235                 status = omapi_set_object_value (mo, (omapi_object_t *)0,
01236                                                  "notify-object", po);
01237 
01238         if (type && (status == ISC_R_SUCCESS))
01239                 status = omapi_set_string_value (mo, (omapi_object_t *)0,
01240                                                  "type", type);
01241 
01242         if (status == ISC_R_SUCCESS)
01243                 status = omapi_message_register (mo);
01244 
01245         if (status == ISC_R_SUCCESS) {
01246                 status = omapi_protocol_send_message (po, id, mo,
01247                                                       (omapi_object_t *)0);
01248                 if (status != ISC_R_SUCCESS)
01249                         omapi_message_unregister (mo);
01250         }
01251 
01252         if (message)
01253                 omapi_message_dereference (&message, MDL);
01254 
01255         return status;
01256 }
01257 
01258 isc_result_t omapi_protocol_send_update (omapi_object_t *po,
01259                                          omapi_object_t *id,
01260                                          unsigned rid,
01261                                          omapi_object_t *object)
01262 {
01263         isc_result_t status;
01264         omapi_message_object_t *message = (omapi_message_object_t *)0;
01265         omapi_object_t *mo;
01266 
01267         if (po -> type != omapi_type_protocol)
01268                 return DHCP_R_INVALIDARG;
01269 
01270         status = omapi_message_new ((omapi_object_t **)&message, MDL);
01271         if (status != ISC_R_SUCCESS)
01272                 return status;
01273         mo = (omapi_object_t *)message;
01274 
01275         status = omapi_set_int_value (mo, (omapi_object_t *)0,
01276                                       "op", OMAPI_OP_UPDATE);
01277         if (status != ISC_R_SUCCESS) {
01278                 omapi_message_dereference (&message, MDL);
01279                 return status;
01280         }
01281 
01282         if (rid) {
01283                 omapi_handle_t handle;
01284                 status = omapi_set_int_value (mo, (omapi_object_t *)0,
01285                                               "rid", (int)rid);
01286                 if (status != ISC_R_SUCCESS) {
01287                         omapi_message_dereference (&message, MDL);
01288                         return status;
01289                 }
01290 
01291                 status = omapi_object_handle (&handle, object);
01292                 if (status != ISC_R_SUCCESS) {
01293                         omapi_message_dereference (&message, MDL);
01294                         return status;
01295                 }
01296                 status = omapi_set_int_value (mo, (omapi_object_t *)0,
01297                                               "handle", (int)handle);
01298                 if (status != ISC_R_SUCCESS) {
01299                         omapi_message_dereference (&message, MDL);
01300                         return status;
01301                 }
01302         }               
01303                 
01304         status = omapi_set_object_value (mo, (omapi_object_t *)0,
01305                                          "object", object);
01306         if (status != ISC_R_SUCCESS) {
01307                 omapi_message_dereference (&message, MDL);
01308                 return status;
01309         }
01310 
01311         status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
01312         omapi_message_dereference (&message, MDL);
01313         return status;
01314 }

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1