Annotation of embedaddon/dhcp/omapip/protocol.c, revision 1.1

1.1     ! misho       1: /* protocol.c
        !             2: 
        !             3:    Functions supporting the object management protocol... */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2004-2007,2009 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:  *   https://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:  * ``https://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 "dhcpd.h"
        !            36: 
        !            37: #include <omapip/omapip_p.h>
        !            38: 
        !            39: OMAPI_OBJECT_ALLOC (omapi_protocol, omapi_protocol_object_t,
        !            40:                    omapi_type_protocol)
        !            41: OMAPI_OBJECT_ALLOC (omapi_protocol_listener, omapi_protocol_listener_object_t,
        !            42:                    omapi_type_protocol_listener)
        !            43: 
        !            44: isc_result_t omapi_protocol_connect (omapi_object_t *h,
        !            45:                                     const char *server_name,
        !            46:                                     unsigned port,
        !            47:                                     omapi_object_t *a)
        !            48: {
        !            49:        isc_result_t rstatus, status;
        !            50:        omapi_protocol_object_t *obj;
        !            51: 
        !            52: #ifdef DEBUG_PROTOCOL
        !            53:        log_debug ("omapi_protocol_connect(%s port=%d)", server_name, port);
        !            54: #endif
        !            55: 
        !            56:        obj = (omapi_protocol_object_t *)0;
        !            57:        status = omapi_protocol_allocate (&obj, MDL);
        !            58:        if (status != ISC_R_SUCCESS)
        !            59:                return status;
        !            60: 
        !            61:        rstatus = omapi_connect ((omapi_object_t *)obj, server_name, port);
        !            62:        if (rstatus != ISC_R_SUCCESS && rstatus != ISC_R_INCOMPLETE) {
        !            63:                omapi_protocol_dereference (&obj, MDL);
        !            64:                return rstatus;
        !            65:        }
        !            66:        status = omapi_object_reference (&h -> outer,
        !            67:                                         (omapi_object_t *)obj, MDL);
        !            68:        if (status != ISC_R_SUCCESS) {
        !            69:                omapi_protocol_dereference (&obj, MDL);
        !            70:                return status;
        !            71:        }
        !            72:        status = omapi_object_reference (&obj -> inner, h, MDL);
        !            73:        if (status != ISC_R_SUCCESS) {
        !            74:                omapi_protocol_dereference (&obj, MDL);
        !            75:                return status;
        !            76:        }
        !            77: 
        !            78:        /* If we were passed a default authenticator, store it now.  We'll
        !            79:           open it once we're connected. */
        !            80:        if (a) {
        !            81:                obj -> default_auth =
        !            82:                        dmalloc (sizeof(omapi_remote_auth_t), MDL);
        !            83:                if (!obj -> default_auth) {
        !            84:                        omapi_protocol_dereference (&obj, MDL);
        !            85:                        return ISC_R_NOMEMORY;
        !            86:                }
        !            87: 
        !            88:                obj -> default_auth -> next = (omapi_remote_auth_t *)0;
        !            89:                status = omapi_object_reference (&obj -> default_auth -> a,
        !            90:                                                 a, MDL);
        !            91:                if (status != ISC_R_SUCCESS) {
        !            92:                        dfree (obj -> default_auth, MDL);
        !            93:                        omapi_protocol_dereference (&obj, MDL);
        !            94:                        return status;
        !            95:                }
        !            96: 
        !            97:                obj -> insecure = 0;
        !            98:                rstatus = ISC_R_INCOMPLETE;
        !            99:        } else {
        !           100:                obj -> insecure = 1;
        !           101: #if 0
        !           102:                status = ISC_R_SUCCESS;
        !           103: #endif
        !           104:        }
        !           105: 
        !           106:        omapi_protocol_dereference (&obj, MDL);
        !           107:        return rstatus;
        !           108: }
        !           109: 
        !           110: /* Send the protocol introduction message. */
        !           111: isc_result_t omapi_protocol_send_intro (omapi_object_t *h,
        !           112:                                        unsigned ver,
        !           113:                                        unsigned hsize)
        !           114: {
        !           115:        isc_result_t status;
        !           116:        omapi_protocol_object_t *p;
        !           117: 
        !           118: #ifdef DEBUG_PROTOCOL
        !           119:        log_debug ("omapi_protocol_send_intro()");
        !           120: #endif
        !           121: 
        !           122:        if (h -> type != omapi_type_protocol)
        !           123:                return ISC_R_INVALIDARG;
        !           124:        p = (omapi_protocol_object_t *)h;
        !           125: 
        !           126:        if (!h -> outer || h -> outer -> type != omapi_type_connection)
        !           127:                return ISC_R_NOTCONNECTED;
        !           128: 
        !           129:        status = omapi_connection_put_uint32 (h -> outer, ver);
        !           130:        if (status != ISC_R_SUCCESS)
        !           131:                return status;
        !           132: 
        !           133:        status = omapi_connection_put_uint32 (h -> outer, hsize);
        !           134: 
        !           135:        if (status != ISC_R_SUCCESS)
        !           136:                return status;
        !           137: 
        !           138:        /* Require the other end to send an intro - this kicks off the
        !           139:           protocol input state machine. */
        !           140:        p -> state = omapi_protocol_intro_wait;
        !           141:        status = omapi_connection_require (h -> outer, 8);
        !           142:        if (status != ISC_R_SUCCESS && status != ISC_R_NOTYET)
        !           143:                return status;
        !           144: 
        !           145:        /* Make up an initial transaction ID for this connection. */
        !           146:        p -> next_xid = random ();
        !           147:        return ISC_R_SUCCESS;
        !           148: }
        !           149: 
        !           150: #ifdef DEBUG_PROTOCOL
        !           151: extern const char *omapi_message_op_name(int);
        !           152: #endif /* DEBUG_PROTOCOL */
        !           153: 
        !           154: isc_result_t omapi_protocol_send_message (omapi_object_t *po,
        !           155:                                          omapi_object_t *id,
        !           156:                                          omapi_object_t *mo,
        !           157:                                          omapi_object_t *omo)
        !           158: {
        !           159:        omapi_protocol_object_t *p;
        !           160:        omapi_object_t *c;
        !           161:        omapi_message_object_t *m, *om;
        !           162:        omapi_remote_auth_t *ra;
        !           163:        omapi_value_t *signature;
        !           164:        isc_result_t status;
        !           165:        unsigned auth_len;
        !           166: 
        !           167:        if (po -> type != omapi_type_protocol ||
        !           168:            !po -> outer || po -> outer -> type != omapi_type_connection ||
        !           169:            mo -> type != omapi_type_message)
        !           170:                return ISC_R_INVALIDARG;
        !           171:        if (omo && omo -> type != omapi_type_message)
        !           172:                return ISC_R_INVALIDARG;
        !           173:        p = (omapi_protocol_object_t *)po;
        !           174:        c = (omapi_object_t *)(po -> outer);
        !           175:        m = (omapi_message_object_t *)mo;
        !           176:        om = (omapi_message_object_t *)omo;
        !           177: 
        !           178: #ifdef DEBUG_PROTOCOL
        !           179:        log_debug ("omapi_protocol_send_message(): "
        !           180:                   "op=%s  handle=%#lx  id=%#lx  rid=%#lx",
        !           181:                   omapi_message_op_name (m->op),
        !           182:                   (long)(m -> object ? m -> object -> handle : m -> handle),
        !           183:                   (long)p -> next_xid, (long)m -> rid);
        !           184: #endif
        !           185: 
        !           186:        /* Find the authid to use for this message. */
        !           187:        if (id) {
        !           188:                for (ra = p -> remote_auth_list; ra; ra = ra -> next) {
        !           189:                        if (ra -> a == id) {
        !           190:                                break;
        !           191:                        }
        !           192:                }
        !           193: 
        !           194:                if (!ra)
        !           195:                        return ISC_R_KEY_UNKNOWN;
        !           196:        } else if (p -> remote_auth_list) {
        !           197:                ra = p -> default_auth;
        !           198:        } else {
        !           199:                ra = (omapi_remote_auth_t *)0;
        !           200:        }
        !           201: 
        !           202:        if (ra) {
        !           203:                m -> authid = ra -> remote_handle;
        !           204:                status = omapi_object_reference (&m -> id_object,
        !           205:                                                 ra -> a, MDL);
        !           206:                if (status != ISC_R_SUCCESS)
        !           207:                        return status;
        !           208:        }
        !           209: 
        !           210:        /* Write the ID of the authentication key we're using. */
        !           211:        status = omapi_connection_put_uint32 (c, ra ? ra -> remote_handle : 0);
        !           212:        if (status != ISC_R_SUCCESS) {
        !           213:                omapi_disconnect (c, 1);
        !           214:                return status;
        !           215:        }
        !           216: 
        !           217:        /* Activate the authentication key on the connection. */
        !           218:        auth_len = 0;
        !           219:        if (ra) {
        !           220:                status = omapi_set_object_value (c, (omapi_object_t *)0,
        !           221:                                                 "output-authenticator",
        !           222:                                                 ra -> a);
        !           223:                if (status != ISC_R_SUCCESS) {
        !           224:                        omapi_disconnect (c, 1);
        !           225:                        return status;
        !           226:                }
        !           227: 
        !           228:                status = omapi_connection_output_auth_length (c, &auth_len);
        !           229:                if (status != ISC_R_SUCCESS) {
        !           230:                        omapi_disconnect (c, 1);
        !           231:                        return status;
        !           232:                }
        !           233:        }
        !           234: 
        !           235:        /* Write the authenticator length */
        !           236:        status = omapi_connection_put_uint32 (c, auth_len);
        !           237:        if (status != ISC_R_SUCCESS) {
        !           238:                omapi_disconnect (c, 1);
        !           239:                return status;
        !           240:        }
        !           241: 
        !           242:        /* Write the opcode. */
        !           243:        status = omapi_connection_put_uint32 (c, m -> op);
        !           244:        if (status != ISC_R_SUCCESS) {
        !           245:                omapi_disconnect (c, 1);
        !           246:                return status;
        !           247:        }
        !           248: 
        !           249:        /* Write the handle.  If we've been given an explicit handle, use
        !           250:           that.   Otherwise, use the handle of the object we're sending.
        !           251:           The caller is responsible for arranging for one of these handles
        !           252:           to be set (or not). */
        !           253:        status = omapi_connection_put_uint32 (c, (m -> h
        !           254:                                                  ? m -> h
        !           255:                                                  : (m -> object
        !           256:                                                     ? m -> object -> handle
        !           257:                                                     : 0)));
        !           258:        if (status != ISC_R_SUCCESS) {
        !           259:                omapi_disconnect (c, 1);
        !           260:                return status;
        !           261:        }
        !           262: 
        !           263:        /* Set and write the transaction ID. */
        !           264:        m -> id = p -> next_xid++;
        !           265:        status = omapi_connection_put_uint32 (c, m -> id);
        !           266:        if (status != ISC_R_SUCCESS) {
        !           267:                omapi_disconnect (c, 1);
        !           268:                return status;
        !           269:        }
        !           270: 
        !           271:        /* Write the transaction ID of the message to which this is a
        !           272:           response, if there is such a message. */
        !           273:        status = omapi_connection_put_uint32 (c, om ? om -> id : m -> rid);
        !           274:        if (status != ISC_R_SUCCESS) {
        !           275:                omapi_disconnect (c, 1);
        !           276:                return status;
        !           277:        }
        !           278: 
        !           279:        /* Stuff out the name/value pairs specific to this message. */
        !           280:        status = omapi_stuff_values (c, id, (omapi_object_t *)m);
        !           281:        if (status != ISC_R_SUCCESS) {
        !           282:                omapi_disconnect (c, 1);
        !           283:                return status;
        !           284:        }
        !           285: 
        !           286:        /* Write the zero-length name that terminates the list of name/value
        !           287:           pairs specific to the message. */
        !           288:        status = omapi_connection_put_uint16 (c, 0);
        !           289:        if (status != ISC_R_SUCCESS) {
        !           290:                omapi_disconnect (c, 1);
        !           291:                return status;
        !           292:        }
        !           293: 
        !           294:        /* Stuff out all the published name/value pairs in the object that's
        !           295:           being sent in the message, if there is one. */
        !           296:        if (m -> object) {
        !           297:                status = omapi_stuff_values (c, id, m -> object);
        !           298:                if (status != ISC_R_SUCCESS) {
        !           299:                        omapi_disconnect (c, 1);
        !           300:                        return status;
        !           301:                }
        !           302:        }
        !           303: 
        !           304:        /* Write the zero-length name that terminates the list of name/value
        !           305:           pairs for the associated object. */
        !           306:        status = omapi_connection_put_uint16 (c, 0);
        !           307:        if (status != ISC_R_SUCCESS) {
        !           308:                omapi_disconnect (c, 1);
        !           309:                return status;
        !           310:        }
        !           311: 
        !           312:        if (ra) {
        !           313:                /* Calculate the message signature. */
        !           314:                signature = (omapi_value_t *)0;
        !           315:                status = omapi_get_value_str (c, (omapi_object_t *)0,
        !           316:                                              "output-signature", &signature);
        !           317:                if (status != ISC_R_SUCCESS) {
        !           318:                        omapi_disconnect (c, 1);
        !           319:                        return status;
        !           320:                }
        !           321: 
        !           322:                /* Write the authenticator... */
        !           323:                status = (omapi_connection_copyin
        !           324:                          (c, signature -> value -> u.buffer.value,
        !           325:                           signature -> value -> u.buffer.len));
        !           326:                omapi_value_dereference (&signature, MDL);
        !           327:                if (status != ISC_R_SUCCESS) {
        !           328:                        omapi_disconnect (c, 1);
        !           329:                        return status;
        !           330:                }
        !           331: 
        !           332:                /* Dectivate the authentication key on the connection. */
        !           333:                status = omapi_set_value_str (c, (omapi_object_t *)0,
        !           334:                                                 "output-authenticator",
        !           335:                                                 (omapi_typed_data_t *)0);
        !           336:                if (status != ISC_R_SUCCESS) {
        !           337:                        omapi_disconnect (c, 1);
        !           338:                        return status;
        !           339:                }
        !           340:        }
        !           341: 
        !           342:        if (!omo) {
        !           343:                omapi_protocol_reference (&m -> protocol_object, p, MDL);
        !           344:        }
        !           345:        return ISC_R_SUCCESS;
        !           346: }
        !           347:                                          
        !           348: 
        !           349: isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
        !           350:                                            const char *name, va_list ap)
        !           351: {
        !           352:        isc_result_t status;
        !           353:        omapi_protocol_object_t *p;
        !           354:        omapi_object_t *c;
        !           355:        omapi_message_object_t *m;
        !           356:        omapi_value_t *signature;
        !           357:        u_int16_t nlen;
        !           358:        u_int32_t vlen;
        !           359:        u_int32_t th;
        !           360: #if defined (DEBUG_MEMORY_LEAKAGE)
        !           361:        unsigned long previous_outstanding = 0xDEADBEEF;
        !           362:        unsigned long connect_outstanding = 0xDEADBEEF;
        !           363: #endif
        !           364: 
        !           365:        if (h -> type != omapi_type_protocol) {
        !           366:                /* XXX shouldn't happen.   Put an assert here? */
        !           367:                return ISC_R_UNEXPECTED;
        !           368:        }
        !           369:        p = (omapi_protocol_object_t *)h;
        !           370: 
        !           371:        if (!strcmp (name, "connect")) {
        !           372: #if defined (DEBUG_MEMORY_LEAKAGE)
        !           373:                connect_outstanding = dmalloc_outstanding;
        !           374: #endif
        !           375:                /* Send the introductory message. */
        !           376:                status = omapi_protocol_send_intro
        !           377:                        (h, OMAPI_PROTOCOL_VERSION,
        !           378:                         sizeof (omapi_protocol_header_t));
        !           379:                if (status != ISC_R_SUCCESS) {
        !           380:                        omapi_disconnect (p -> outer, 1);
        !           381:                        return status;
        !           382:                }
        !           383:                return ISC_R_SUCCESS;
        !           384:        }
        !           385: 
        !           386:        /* Should only receive these when opening the initial authenticator. */
        !           387:        if (!strcmp (name, "status")) {
        !           388:                status = va_arg (ap, isc_result_t);
        !           389:                if (status != ISC_R_SUCCESS) {
        !           390:                        omapi_signal_in (h -> inner, "status", status,
        !           391:                                         (omapi_object_t *)0);
        !           392:                        omapi_disconnect (p -> outer, 1);
        !           393:                        return status;
        !           394:                } else {
        !           395:                        return omapi_signal_in (h -> inner, "ready");
        !           396:                }
        !           397:        }
        !           398: 
        !           399:        /* If we get a disconnect, dump memory usage. */
        !           400:        if (!strcmp (name, "disconnect")) {
        !           401: #if defined (DEBUG_MEMORY_LEAKAGE)
        !           402:            if (connect_outstanding != 0xDEADBEEF) {
        !           403:                log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
        !           404:                          dmalloc_generation,
        !           405:                          dmalloc_outstanding - previous_outstanding,
        !           406:                          dmalloc_outstanding, dmalloc_longterm, " long-term");
        !           407:            }
        !           408: #endif
        !           409: #if defined (DEBUG_MEMORY_LEAKAGE)
        !           410:            dmalloc_dump_outstanding ();
        !           411: #endif
        !           412: #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
        !           413:            dump_rc_history (h);
        !           414: #endif
        !           415:            for (m = omapi_registered_messages; m; m = m -> next) {
        !           416:                if (m -> protocol_object == p) {
        !           417:                    if (m -> object)
        !           418:                        omapi_signal (m -> object, "disconnect");
        !           419:                }
        !           420:            }
        !           421: 
        !           422:            /* XXX */
        !           423:            return ISC_R_SUCCESS;
        !           424:        }
        !           425: 
        !           426:        /* Not a signal we recognize? */
        !           427:        if (strcmp (name, "ready")) {
        !           428:                if (p -> inner && p -> inner -> type -> signal_handler)
        !           429:                        return (*(p -> inner -> type -> signal_handler)) (h,
        !           430:                                                                          name,
        !           431:                                                                          ap);
        !           432:                return ISC_R_NOTFOUND;
        !           433:        }
        !           434: 
        !           435:        if (!p -> outer || p -> outer -> type != omapi_type_connection)
        !           436:                return ISC_R_INVALIDARG;
        !           437:        c = p -> outer;
        !           438: 
        !           439:        /* We get here because we requested that we be woken up after
        !           440:            some number of bytes were read, and that number of bytes
        !           441:            has in fact been read. */
        !           442:        switch (p -> state) {
        !           443:              case omapi_protocol_intro_wait:
        !           444:                /* Get protocol version and header size in network
        !           445:                   byte order. */
        !           446:                omapi_connection_get_uint32 (c, &p -> protocol_version);
        !           447:                omapi_connection_get_uint32 (c, &p -> header_size);
        !           448:        
        !           449:                /* We currently only support the current protocol version. */
        !           450:                if (p -> protocol_version != OMAPI_PROTOCOL_VERSION) {
        !           451:                        omapi_disconnect (c, 1);
        !           452:                        return ISC_R_VERSIONMISMATCH;
        !           453:                }
        !           454: 
        !           455:                if (p -> header_size < sizeof (omapi_protocol_header_t)) {
        !           456:                        omapi_disconnect (c, 1);
        !           457:                        return ISC_R_PROTOCOLERROR;
        !           458:                }
        !           459: 
        !           460:                if (p -> default_auth) {
        !           461:                        status = omapi_protocol_send_open
        !           462:                                (h, (omapi_object_t *)0, "authenticator",
        !           463:                                 p -> default_auth -> a,
        !           464:                                 OMAPI_NOTIFY_PROTOCOL);
        !           465:                        if (status != ISC_R_SUCCESS) {
        !           466:                                omapi_disconnect (c, 1);
        !           467:                                return status;
        !           468:                        }
        !           469:                } else {
        !           470:                        status = omapi_signal_in (h -> inner, "ready");
        !           471:                }
        !           472: 
        !           473:              to_header_wait:
        !           474:                /* The next thing we're expecting is a message header. */
        !           475:                p -> state = omapi_protocol_header_wait;
        !           476: 
        !           477:                /* Register a need for the number of bytes in a
        !           478:                   header, and if we already have that many, process
        !           479:                   them immediately. */
        !           480:                if ((omapi_connection_require (c, p -> header_size)) !=
        !           481:                    ISC_R_SUCCESS)
        !           482:                        break;
        !           483:                /* If we already have the data, fall through. */
        !           484: 
        !           485:              case omapi_protocol_header_wait:
        !           486: #if defined (DEBUG_MEMORY_LEAKAGE)
        !           487:                if (previous_outstanding != 0xDEADBEEF) {
        !           488:                        log_info ("%s %ld: %ld new, %ld outstanding, %ld%s",
        !           489:                                  "generation", dmalloc_generation,
        !           490:                                  dmalloc_outstanding - previous_outstanding,
        !           491:                                  dmalloc_outstanding, dmalloc_longterm,
        !           492:                                  " long-term");
        !           493: #endif
        !           494: #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
        !           495:                        dmalloc_dump_outstanding ();
        !           496: #endif
        !           497: #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
        !           498:                        dump_rc_history (h);
        !           499: #endif
        !           500: #if defined (DEBUG_MEMORY_LEAKAGE)
        !           501:                }
        !           502:                previous_outstanding = dmalloc_outstanding;
        !           503: #endif
        !           504:                status = omapi_message_new ((omapi_object_t **)&p -> message,
        !           505:                                            MDL);
        !           506:                if (status != ISC_R_SUCCESS) {
        !           507:                        omapi_disconnect (c, 1);
        !           508:                        return status;
        !           509:                }
        !           510: 
        !           511:                p -> verify_result = ISC_R_SUCCESS;
        !           512: 
        !           513:                /* Swap in the header... */
        !           514:                omapi_connection_get_uint32 (c, &p -> message -> authid);
        !           515: 
        !           516:                /* Bind the authenticator to the message object. */
        !           517:                if (p -> message -> authid) {
        !           518:                        status = (omapi_protocol_lookup_auth
        !           519:                                  (&p -> message -> id_object, h,
        !           520:                                   p -> message -> authid));
        !           521:                        if (status != ISC_R_SUCCESS)
        !           522:                                p -> verify_result = status;
        !           523: 
        !           524:                        /* Activate the authentication key. */
        !           525:                        status = omapi_set_object_value
        !           526:                                (c, (omapi_object_t *)0, "input-authenticator",
        !           527:                                 p -> message -> id_object);
        !           528:                        if (status != ISC_R_SUCCESS) {
        !           529:                                omapi_disconnect (c, 1);
        !           530:                                return status;
        !           531:                        }
        !           532:                }
        !           533: 
        !           534:                omapi_connection_get_uint32 (c, &p -> message -> authlen);
        !           535:                omapi_connection_get_uint32 (c, &p -> message -> op);
        !           536:                omapi_connection_get_uint32 (c, &th);
        !           537:                p -> message -> h = th;
        !           538:                omapi_connection_get_uint32 (c, &p -> message -> id);
        !           539:                omapi_connection_get_uint32 (c, &p -> message -> rid);
        !           540: 
        !           541:                /* If there was any extra header data, skip over it. */
        !           542:                if (p -> header_size > sizeof (omapi_protocol_header_t)) {
        !           543:                        omapi_connection_copyout
        !           544:                                (0, c, (p -> header_size -
        !           545:                                        sizeof (omapi_protocol_header_t)));
        !           546:                }
        !           547:                                                     
        !           548:                /* XXX must compute partial signature across the
        !           549:                    XXX preceding bytes.    Also, if authenticator
        !           550:                   specifies encryption as well as signing, we may
        !           551:                   have to decrypt the data on the way in. */
        !           552: 
        !           553:                /* First we read in message-specific values, then object
        !           554:                   values. */
        !           555:                p -> reading_message_values = 1;
        !           556: 
        !           557:              need_name_length:
        !           558:                /* The next thing we're expecting is length of the
        !           559:                   first name. */
        !           560:                p -> state = omapi_protocol_name_length_wait;
        !           561: 
        !           562:                /* Wait for a 16-bit length. */
        !           563:                if ((omapi_connection_require (c, 2)) != ISC_R_SUCCESS)
        !           564:                        break;
        !           565:                /* If it's already here, fall through. */
        !           566: 
        !           567:              case omapi_protocol_name_length_wait:
        !           568:                omapi_connection_get_uint16 (c, &nlen);
        !           569:                /* A zero-length name means that we're done reading name+value
        !           570:                   pairs. */
        !           571:                if (nlen == 0) {
        !           572:                        /* If we've already read in the object, we are
        !           573:                           done reading the message, but if we've just
        !           574:                           finished reading in the values associated
        !           575:                           with the message, we need to read the
        !           576:                           object. */
        !           577:                        if (p -> reading_message_values) {
        !           578:                                p -> reading_message_values = 0;
        !           579:                                goto need_name_length;
        !           580:                        }
        !           581: 
        !           582:                        /* If the authenticator length is zero, there's no
        !           583:                           signature to read in, so go straight to processing
        !           584:                           the message. */
        !           585:                        if (p -> message -> authlen == 0)
        !           586:                                goto message_done;
        !           587: 
        !           588:                        /* The next thing we're expecting is the
        !           589:                            message signature. */
        !           590:                        p -> state = omapi_protocol_signature_wait;
        !           591: 
        !           592:                        /* Wait for the number of bytes specified for
        !           593:                           the authenticator.  If we already have it,
        !           594:                           go read it in. */
        !           595:                        if (omapi_connection_require
        !           596:                            (c, p -> message -> authlen) == ISC_R_SUCCESS)
        !           597:                                goto signature_wait;
        !           598:                        break;
        !           599:                }
        !           600: 
        !           601:                /* Allocate a buffer for the name. */
        !           602:                status = (omapi_data_string_new (&p -> name, nlen, MDL));
        !           603:                if (status != ISC_R_SUCCESS) {
        !           604:                        omapi_disconnect (c, 1);
        !           605:                        return ISC_R_NOMEMORY;
        !           606:                }
        !           607:                p -> state = omapi_protocol_name_wait;
        !           608:                if (omapi_connection_require (c, nlen) != ISC_R_SUCCESS)
        !           609:                        break;
        !           610:                /* If it's already here, fall through. */
        !           611:                                             
        !           612:              case omapi_protocol_name_wait:
        !           613:                omapi_connection_copyout (p -> name -> value, c,
        !           614:                                          p -> name -> len);
        !           615:                /* Wait for a 32-bit length. */
        !           616:                p -> state = omapi_protocol_value_length_wait;
        !           617:                if ((omapi_connection_require (c, 4)) != ISC_R_SUCCESS)
        !           618:                        break;
        !           619:                /* If it's already here, fall through. */
        !           620: 
        !           621:              case omapi_protocol_value_length_wait:
        !           622:                omapi_connection_get_uint32 (c, &vlen);
        !           623: 
        !           624:                /* Zero-length values are allowed - if we get one, we
        !           625:                   don't have to read any data for the value - just
        !           626:                   get the next one, if there is a next one. */
        !           627:                if (!vlen)
        !           628:                        goto insert_new_value;
        !           629: 
        !           630:                status = omapi_typed_data_new (MDL, &p -> value,
        !           631:                                               omapi_datatype_data,
        !           632:                                               vlen);
        !           633:                if (status != ISC_R_SUCCESS) {
        !           634:                        omapi_disconnect (c, 1);
        !           635:                        return ISC_R_NOMEMORY;
        !           636:                }
        !           637: 
        !           638:                p -> state = omapi_protocol_value_wait;
        !           639:                if (omapi_connection_require (c, vlen) != ISC_R_SUCCESS)
        !           640:                        break;
        !           641:                /* If it's already here, fall through. */
        !           642:                                             
        !           643:              case omapi_protocol_value_wait:
        !           644:                omapi_connection_copyout (p -> value -> u.buffer.value, c,
        !           645:                                          p -> value -> u.buffer.len);
        !           646: 
        !           647:              insert_new_value:
        !           648:                if (p -> reading_message_values) {
        !           649:                        status = (omapi_set_value
        !           650:                                  ((omapi_object_t *)p -> message,
        !           651:                                   p -> message -> id_object,
        !           652:                                   p -> name, p -> value));
        !           653:                } else {
        !           654:                        if (!p -> message -> object) {
        !           655:                                /* We need a generic object to hang off of the
        !           656:                                   incoming message. */
        !           657:                                status = (omapi_generic_new
        !           658:                                          (&p -> message -> object, MDL));
        !           659:                                if (status != ISC_R_SUCCESS) {
        !           660:                                        omapi_disconnect (c, 1);
        !           661:                                        return status;
        !           662:                                }
        !           663:                        }
        !           664:                        status = (omapi_set_value
        !           665:                                  ((omapi_object_t *)p -> message -> object,
        !           666:                                   p -> message -> id_object,
        !           667:                                   p -> name, p -> value));
        !           668:                }
        !           669:                if (status != ISC_R_SUCCESS) {
        !           670:                        omapi_disconnect (c, 1);
        !           671:                        return status;
        !           672:                }
        !           673:                omapi_data_string_dereference (&p -> name, MDL);
        !           674:                if (p -> value)
        !           675:                        omapi_typed_data_dereference (&p -> value, MDL);
        !           676:                goto need_name_length;
        !           677: 
        !           678:              signature_wait:
        !           679:              case omapi_protocol_signature_wait:
        !           680:                if (p -> message -> id_object) {
        !           681:                        /* Compute the signature of the message. */
        !           682:                        signature = (omapi_value_t *)0;
        !           683:                        status = omapi_get_value_str (c, (omapi_object_t *)0,
        !           684:                                                      "input-signature",
        !           685:                                                      &signature);
        !           686:                        if (status != ISC_R_SUCCESS) {
        !           687:                                omapi_disconnect (c, 1);
        !           688:                                return status;
        !           689:                        }
        !           690: 
        !           691:                        /* Disable the authentication key on the connection. */
        !           692:                        status = omapi_set_value_str (c, (omapi_object_t *)0,
        !           693:                                                      "input-authenticator",
        !           694:                                                      (omapi_typed_data_t *)0);
        !           695:                        if (status != ISC_R_SUCCESS) {
        !           696:                                omapi_value_dereference (&signature, MDL);
        !           697:                                omapi_disconnect (c, 1);
        !           698:                                return status;
        !           699:                        }
        !           700:                }
        !           701: 
        !           702:                /* Read the authenticator. */
        !           703:                status = omapi_typed_data_new (MDL,
        !           704:                                               &p -> message -> authenticator,
        !           705:                                               omapi_datatype_data,
        !           706:                                               p -> message -> authlen);
        !           707:                        
        !           708:                if (status != ISC_R_SUCCESS) {
        !           709:                        omapi_value_dereference (&signature, MDL);
        !           710:                        omapi_disconnect (c, 1);
        !           711:                        return ISC_R_NOMEMORY;
        !           712:                }
        !           713:                omapi_connection_copyout
        !           714:                        (p -> message -> authenticator -> u.buffer.value, c,
        !           715:                         p -> message -> authlen);
        !           716: 
        !           717:                /* Verify the signature. */
        !           718:                if (p -> message -> id_object &&
        !           719:                    ((signature -> value -> u.buffer.len !=
        !           720:                      p -> message -> authlen) ||
        !           721:                     (memcmp (signature -> value -> u.buffer.value,
        !           722:                              p -> message -> authenticator -> u.buffer.value,
        !           723:                              p -> message -> authlen) != 0))) {
        !           724:                        /* Invalid signature. */
        !           725:                        p -> verify_result = ISC_R_INVALIDKEY;
        !           726:                }
        !           727: 
        !           728:                omapi_value_dereference (&signature, MDL);
        !           729: 
        !           730:                /* Process the message. */
        !           731:              message_done:
        !           732:                if (p -> verify_result != ISC_R_SUCCESS) {
        !           733:                        status = omapi_protocol_send_status
        !           734:                                (h, (omapi_object_t *)0, p -> verify_result,
        !           735:                                 p -> message -> id, (char *)0);
        !           736:                } else {
        !           737:                        status = omapi_message_process
        !           738:                                ((omapi_object_t *)p -> message, h);
        !           739:                }
        !           740:                if (status != ISC_R_SUCCESS) {
        !           741:                        omapi_disconnect (c, 1);
        !           742:                        return ISC_R_NOMEMORY;
        !           743:                }
        !           744: 
        !           745:                omapi_message_dereference (&p -> message, MDL);
        !           746: #if defined (DEBUG_MEMORY_LEAKAGE)
        !           747:                log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
        !           748:                          dmalloc_generation,
        !           749:                          dmalloc_outstanding - previous_outstanding,
        !           750:                          dmalloc_outstanding, dmalloc_longterm, " long-term");
        !           751: #endif
        !           752: #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
        !           753:                dmalloc_dump_outstanding ();
        !           754: #endif
        !           755: #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
        !           756:                dump_rc_history (h);
        !           757: #endif
        !           758: #if defined (DEBUG_MEMORY_LEAKAGE)
        !           759:                previous_outstanding = 0xDEADBEEF;
        !           760: #endif
        !           761:                /* Now wait for the next message. */
        !           762:                goto to_header_wait;            
        !           763: 
        !           764:              default:
        !           765:                /* XXX should never get here.   Assertion? */
        !           766:                break;
        !           767:        }
        !           768:        return ISC_R_SUCCESS;
        !           769: }
        !           770: 
        !           771: isc_result_t omapi_protocol_add_auth (omapi_object_t *po,
        !           772:                                      omapi_object_t *ao,
        !           773:                                      omapi_handle_t handle)
        !           774: {
        !           775:        omapi_protocol_object_t *p;
        !           776:        omapi_remote_auth_t *r;
        !           777:        isc_result_t status;
        !           778: 
        !           779:        if (ao -> type != omapi_type_auth_key &&
        !           780:            (!ao -> inner || ao -> inner -> type != omapi_type_auth_key))
        !           781:                return ISC_R_INVALIDARG;
        !           782: 
        !           783:        if (po -> type != omapi_type_protocol)
        !           784:                return ISC_R_INVALIDARG;
        !           785:        p = (omapi_protocol_object_t *)po;
        !           786: 
        !           787: #ifdef DEBUG_PROTOCOL
        !           788:        log_debug ("omapi_protocol_add_auth(name=%s)",
        !           789:                   ((omapi_auth_key_t *)ao) -> name);
        !           790: #endif
        !           791: 
        !           792:        if (p -> verify_auth) {
        !           793:                status = (p -> verify_auth) (po, (omapi_auth_key_t *)ao);
        !           794:                if (status != ISC_R_SUCCESS)
        !           795:                        return status;
        !           796:        }
        !           797: 
        !           798:        /* If omapi_protocol_connect() was called with a default
        !           799:           authenticator, p -> default_auth will already be set,
        !           800:           but p -> remote_auth_list will not yet be initialized. */
        !           801:        if (p -> default_auth && !p -> remote_auth_list) {
        !           802:                if (p -> default_auth -> a != ao) {
        !           803:                        /* Something just went horribly wrong. */
        !           804:                        omapi_disconnect (p -> outer, 1);
        !           805:                        return ISC_R_UNEXPECTED;
        !           806:                }
        !           807: 
        !           808:                p -> remote_auth_list = p -> default_auth;
        !           809:                p -> default_auth -> remote_handle = handle;
        !           810: 
        !           811:                return omapi_signal_in (p -> inner, "ready");
        !           812:        }
        !           813: 
        !           814:        r = dmalloc (sizeof(*r), MDL);
        !           815:        if (!r)
        !           816:                return ISC_R_NOMEMORY;
        !           817: 
        !           818:        status = omapi_object_reference (&r -> a, ao, MDL);
        !           819:        if (status != ISC_R_SUCCESS) {
        !           820:                dfree (r, MDL);
        !           821:                return status;
        !           822:        }
        !           823: 
        !           824:        r -> remote_handle = handle;
        !           825:        r -> next = p -> remote_auth_list;
        !           826:        p -> remote_auth_list = r;
        !           827: 
        !           828:        return ISC_R_SUCCESS;
        !           829: }
        !           830: 
        !           831: isc_result_t omapi_protocol_lookup_auth (omapi_object_t **a,
        !           832:                                         omapi_object_t *po,
        !           833:                                         omapi_handle_t handle)
        !           834: {
        !           835:        omapi_protocol_object_t *p;
        !           836:        omapi_remote_auth_t *r;
        !           837: 
        !           838:        if (po -> type != omapi_type_protocol)
        !           839:                return ISC_R_INVALIDARG;
        !           840:        p = (omapi_protocol_object_t *)po;
        !           841: 
        !           842:        for (r = p -> remote_auth_list; r; r = r -> next)
        !           843:                if (r -> remote_handle == handle)
        !           844:                        return omapi_object_reference (a, r -> a, MDL);
        !           845: 
        !           846:        return ISC_R_KEY_UNKNOWN;
        !           847: }
        !           848: 
        !           849: isc_result_t omapi_protocol_set_value (omapi_object_t *h,
        !           850:                                       omapi_object_t *id,
        !           851:                                       omapi_data_string_t *name,
        !           852:                                       omapi_typed_data_t *value)
        !           853: {
        !           854:        omapi_protocol_object_t *p;
        !           855:        omapi_remote_auth_t *r;
        !           856: 
        !           857:        if (h -> type != omapi_type_protocol)
        !           858:                return ISC_R_INVALIDARG;
        !           859:        p = (omapi_protocol_object_t *)h;
        !           860: 
        !           861:        if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
        !           862:                if (value -> type != omapi_datatype_object)
        !           863:                        return ISC_R_INVALIDARG;
        !           864: 
        !           865:                if (!value || !value -> u.object) {
        !           866:                        p -> default_auth = (omapi_remote_auth_t *)0;
        !           867:                } else {
        !           868:                        for (r = p -> remote_auth_list; r; r = r -> next)
        !           869:                                if (r -> a == value -> u.object)
        !           870:                                        break;
        !           871: 
        !           872:                        if (!r)
        !           873:                                return ISC_R_KEY_UNKNOWN;
        !           874: 
        !           875:                        p -> default_auth = r;
        !           876:                }
        !           877: 
        !           878:                return ISC_R_SUCCESS;
        !           879:        }
        !           880: 
        !           881:        if (h -> inner && h -> inner -> type -> set_value)
        !           882:                return (*(h -> inner -> type -> set_value))
        !           883:                        (h -> inner, id, name, value);
        !           884:        return ISC_R_NOTFOUND;
        !           885: }
        !           886: 
        !           887: isc_result_t omapi_protocol_get_value (omapi_object_t *h,
        !           888:                                       omapi_object_t *id,
        !           889:                                       omapi_data_string_t *name,
        !           890:                                       omapi_value_t **value)
        !           891: {
        !           892:        omapi_protocol_object_t *p;
        !           893: 
        !           894:        if (h -> type != omapi_type_protocol)
        !           895:                return ISC_R_INVALIDARG;
        !           896:        p = (omapi_protocol_object_t *)h;
        !           897: 
        !           898:        if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
        !           899:                if (!p -> default_auth)
        !           900:                        return ISC_R_NOTFOUND;
        !           901: 
        !           902:                return omapi_make_object_value (value, name,
        !           903:                                                p -> default_auth -> a, MDL);
        !           904:        }
        !           905:        
        !           906:        if (h -> inner && h -> inner -> type -> get_value)
        !           907:                return (*(h -> inner -> type -> get_value))
        !           908:                        (h -> inner, id, name, value);
        !           909:        return ISC_R_NOTFOUND;
        !           910: }
        !           911: 
        !           912: isc_result_t omapi_protocol_destroy (omapi_object_t *h,
        !           913:                                     const char *file, int line)
        !           914: {
        !           915:        omapi_protocol_object_t *p;
        !           916:        if (h -> type != omapi_type_protocol)
        !           917:                return ISC_R_INVALIDARG;
        !           918:        p = (omapi_protocol_object_t *)h;
        !           919:        if (p -> message)
        !           920:                omapi_message_dereference (&p -> message, file, line);
        !           921: 
        !           922:        /* This will happen if: 1) A default authenticator is supplied to
        !           923:           omapi_protocol_connect(), and 2) something goes wrong before
        !           924:           the authenticator can be opened. */
        !           925:        if (p -> default_auth && !p -> remote_auth_list)
        !           926:                dfree (p -> default_auth, file, line);
        !           927: 
        !           928:        while (p -> remote_auth_list) {
        !           929:                omapi_remote_auth_t *r = p -> remote_auth_list -> next;
        !           930:                p -> remote_auth_list = r;
        !           931:                if (r) {
        !           932:                        omapi_object_dereference (&r -> a, file, line);
        !           933:                        dfree (r, file, line);
        !           934:                }
        !           935:        }
        !           936:        return ISC_R_SUCCESS;
        !           937: }
        !           938: 
        !           939: /* Write all the published values associated with the object through the
        !           940:    specified connection. */
        !           941: 
        !           942: isc_result_t omapi_protocol_stuff_values (omapi_object_t *c,
        !           943:                                          omapi_object_t *id,
        !           944:                                          omapi_object_t *p)
        !           945: {
        !           946:        if (p -> type != omapi_type_protocol)
        !           947:                return ISC_R_INVALIDARG;
        !           948: 
        !           949:        if (p -> inner && p -> inner -> type -> stuff_values)
        !           950:                return (*(p -> inner -> type -> stuff_values)) (c, id,
        !           951:                                                                p -> inner);
        !           952:        return ISC_R_SUCCESS;
        !           953: }
        !           954: 
        !           955: /* Returns a boolean indicating whether this protocol requires that
        !           956:    messages be authenticated or not. */
        !           957: 
        !           958: isc_boolean_t omapi_protocol_authenticated (omapi_object_t *h)
        !           959: {
        !           960:        if (h -> type != omapi_type_protocol)
        !           961:                return isc_boolean_false;
        !           962:        if (((omapi_protocol_object_t *)h) -> insecure)
        !           963:                return isc_boolean_false;
        !           964:        else
        !           965:                return isc_boolean_true;
        !           966: }
        !           967: 
        !           968: /* Sets the address and authenticator verification callbacks.  The handle
        !           969:    is to a listener object, not a protocol object. */
        !           970: 
        !           971: isc_result_t omapi_protocol_configure_security (omapi_object_t *h,
        !           972:                                                isc_result_t (*verify_addr)
        !           973:                                                 (omapi_object_t *,
        !           974:                                                  omapi_addr_t *),
        !           975:                                                isc_result_t (*verify_auth)
        !           976:                                                 (omapi_object_t *,
        !           977:                                                  omapi_auth_key_t *))
        !           978: {
        !           979:        omapi_protocol_listener_object_t *l;
        !           980: 
        !           981:        if (h -> outer && h -> outer -> type == omapi_type_protocol_listener)
        !           982:                h = h -> outer;
        !           983: 
        !           984:        if (h -> type != omapi_type_protocol_listener)
        !           985:                return ISC_R_INVALIDARG;
        !           986:        l = (omapi_protocol_listener_object_t *)h;
        !           987: 
        !           988:        l -> verify_auth = verify_auth;
        !           989:        l -> insecure = 0;
        !           990: 
        !           991:        return omapi_listener_configure_security (h -> outer, verify_addr);
        !           992: }
        !           993:                                              
        !           994: 
        !           995: /* Set up a listener for the omapi protocol.    The handle stored points to
        !           996:    a listener object, not a protocol object. */
        !           997: 
        !           998: isc_result_t omapi_protocol_listen (omapi_object_t *h,
        !           999:                                    unsigned port,
        !          1000:                                    int max)
        !          1001: {
        !          1002:        isc_result_t status;
        !          1003:        omapi_protocol_listener_object_t *obj;
        !          1004: 
        !          1005:        obj = (omapi_protocol_listener_object_t *)0;
        !          1006:        status = omapi_protocol_listener_allocate (&obj, MDL);
        !          1007:        if (status != ISC_R_SUCCESS)
        !          1008:                return status;
        !          1009: 
        !          1010:        status = omapi_object_reference (&h -> outer,
        !          1011:                                         (omapi_object_t *)obj, MDL);
        !          1012:        if (status != ISC_R_SUCCESS) {
        !          1013:                omapi_protocol_listener_dereference (&obj, MDL);
        !          1014:                return status;
        !          1015:        }
        !          1016:        status = omapi_object_reference (&obj -> inner, h, MDL);
        !          1017:        if (status != ISC_R_SUCCESS) {
        !          1018:                omapi_protocol_listener_dereference (&obj, MDL);
        !          1019:                return status;
        !          1020:        }
        !          1021: 
        !          1022:        /* What a terrible default. */
        !          1023:        obj -> insecure = 1;
        !          1024: 
        !          1025:        status = omapi_listen ((omapi_object_t *)obj, port, max);
        !          1026:        omapi_protocol_listener_dereference (&obj, MDL);
        !          1027:        return status;
        !          1028: }
        !          1029: 
        !          1030: /* Signal handler for protocol listener - if we get a connect signal,
        !          1031:    create a new protocol connection, otherwise pass the signal down. */
        !          1032: 
        !          1033: isc_result_t omapi_protocol_listener_signal (omapi_object_t *o,
        !          1034:                                             const char *name, va_list ap)
        !          1035: {
        !          1036:        isc_result_t status;
        !          1037:        omapi_object_t *c;
        !          1038:        omapi_protocol_object_t *obj;
        !          1039:        omapi_protocol_listener_object_t *p;
        !          1040: 
        !          1041:        if (!o || o -> type != omapi_type_protocol_listener)
        !          1042:                return ISC_R_INVALIDARG;
        !          1043:        p = (omapi_protocol_listener_object_t *)o;
        !          1044: 
        !          1045:        /* Not a signal we recognize? */
        !          1046:        if (strcmp (name, "connect")) {
        !          1047:                if (p -> inner && p -> inner -> type -> signal_handler)
        !          1048:                        return (*(p -> inner -> type -> signal_handler))
        !          1049:                                (p -> inner, name, ap);
        !          1050:                return ISC_R_NOTFOUND;
        !          1051:        }
        !          1052: 
        !          1053:        c = va_arg (ap, omapi_object_t *);
        !          1054:        if (!c || c -> type != omapi_type_connection)
        !          1055:                return ISC_R_INVALIDARG;
        !          1056: 
        !          1057:        obj = (omapi_protocol_object_t *)0;
        !          1058:        status = omapi_protocol_allocate (&obj, MDL);
        !          1059:        if (status != ISC_R_SUCCESS)
        !          1060:                return status;
        !          1061: 
        !          1062:        obj -> verify_auth = p -> verify_auth;
        !          1063:        obj -> insecure = p -> insecure;
        !          1064: 
        !          1065:        status = omapi_object_reference (&obj -> outer, c, MDL);
        !          1066:        if (status != ISC_R_SUCCESS) {
        !          1067:              lose:
        !          1068:                omapi_protocol_dereference (&obj, MDL);
        !          1069:                omapi_disconnect (c, 1);
        !          1070:                return status;
        !          1071:        }
        !          1072: 
        !          1073:        status = omapi_object_reference (&c -> inner,
        !          1074:                                         (omapi_object_t *)obj, MDL);
        !          1075:        if (status != ISC_R_SUCCESS)
        !          1076:                goto lose;
        !          1077: 
        !          1078:        /* Send the introductory message. */
        !          1079:        status = omapi_protocol_send_intro ((omapi_object_t *)obj,
        !          1080:                                            OMAPI_PROTOCOL_VERSION,
        !          1081:                                            sizeof (omapi_protocol_header_t));
        !          1082:        if (status != ISC_R_SUCCESS)
        !          1083:                goto lose;
        !          1084: 
        !          1085:        omapi_protocol_dereference (&obj, MDL);
        !          1086:        return status;
        !          1087: }
        !          1088: 
        !          1089: isc_result_t omapi_protocol_listener_set_value (omapi_object_t *h,
        !          1090:                                                omapi_object_t *id,
        !          1091:                                                omapi_data_string_t *name,
        !          1092:                                                omapi_typed_data_t *value)
        !          1093: {
        !          1094:        if (h -> type != omapi_type_protocol_listener)
        !          1095:                return ISC_R_INVALIDARG;
        !          1096:        
        !          1097:        if (h -> inner && h -> inner -> type -> set_value)
        !          1098:                return (*(h -> inner -> type -> set_value))
        !          1099:                        (h -> inner, id, name, value);
        !          1100:        return ISC_R_NOTFOUND;
        !          1101: }
        !          1102: 
        !          1103: isc_result_t omapi_protocol_listener_get_value (omapi_object_t *h,
        !          1104:                                                omapi_object_t *id,
        !          1105:                                                omapi_data_string_t *name,
        !          1106:                                                omapi_value_t **value)
        !          1107: {
        !          1108:        if (h -> type != omapi_type_protocol_listener)
        !          1109:                return ISC_R_INVALIDARG;
        !          1110:        
        !          1111:        if (h -> inner && h -> inner -> type -> get_value)
        !          1112:                return (*(h -> inner -> type -> get_value))
        !          1113:                        (h -> inner, id, name, value);
        !          1114:        return ISC_R_NOTFOUND;
        !          1115: }
        !          1116: 
        !          1117: isc_result_t omapi_protocol_listener_destroy (omapi_object_t *h,
        !          1118:                                              const char *file, int line)
        !          1119: {
        !          1120:        if (h -> type != omapi_type_protocol_listener)
        !          1121:                return ISC_R_INVALIDARG;
        !          1122:        return ISC_R_SUCCESS;
        !          1123: }
        !          1124: 
        !          1125: /* Write all the published values associated with the object through the
        !          1126:    specified connection. */
        !          1127: 
        !          1128: isc_result_t omapi_protocol_listener_stuff (omapi_object_t *c,
        !          1129:                                            omapi_object_t *id,
        !          1130:                                            omapi_object_t *p)
        !          1131: {
        !          1132:        if (p -> type != omapi_type_protocol_listener)
        !          1133:                return ISC_R_INVALIDARG;
        !          1134: 
        !          1135:        if (p -> inner && p -> inner -> type -> stuff_values)
        !          1136:                return (*(p -> inner -> type -> stuff_values)) (c, id,
        !          1137:                                                                p -> inner);
        !          1138:        return ISC_R_SUCCESS;
        !          1139: }
        !          1140: 
        !          1141: isc_result_t omapi_protocol_send_status (omapi_object_t *po,
        !          1142:                                         omapi_object_t *id,
        !          1143:                                         isc_result_t waitstatus,
        !          1144:                                         unsigned rid, const char *msg)
        !          1145: {
        !          1146:        isc_result_t status;
        !          1147:        omapi_message_object_t *message = (omapi_message_object_t *)0;
        !          1148:        omapi_object_t *mo;
        !          1149: 
        !          1150:        if (po -> type != omapi_type_protocol)
        !          1151:                return ISC_R_INVALIDARG;
        !          1152: 
        !          1153:        status = omapi_message_new ((omapi_object_t **)&message, MDL);
        !          1154:        if (status != ISC_R_SUCCESS)
        !          1155:                return status;
        !          1156:        mo = (omapi_object_t *)message;
        !          1157: 
        !          1158:        status = omapi_set_int_value (mo, (omapi_object_t *)0,
        !          1159:                                      "op", OMAPI_OP_STATUS);
        !          1160:        if (status != ISC_R_SUCCESS) {
        !          1161:                omapi_message_dereference (&message, MDL);
        !          1162:                return status;
        !          1163:        }
        !          1164: 
        !          1165:        status = omapi_set_int_value (mo, (omapi_object_t *)0,
        !          1166:                                      "rid", (int)rid);
        !          1167:        if (status != ISC_R_SUCCESS) {
        !          1168:                omapi_message_dereference (&message, MDL);
        !          1169:                return status;
        !          1170:        }
        !          1171: 
        !          1172:        status = omapi_set_int_value (mo, (omapi_object_t *)0,
        !          1173:                                      "result", (int)waitstatus);
        !          1174:        if (status != ISC_R_SUCCESS) {
        !          1175:                omapi_message_dereference (&message, MDL);
        !          1176:                return status;
        !          1177:        }
        !          1178: 
        !          1179:        /* If a message has been provided, send it. */
        !          1180:        if (msg) {
        !          1181:                status = omapi_set_string_value (mo, (omapi_object_t *)0,
        !          1182:                                                 "message", msg);
        !          1183:                if (status != ISC_R_SUCCESS) {
        !          1184:                        omapi_message_dereference (&message, MDL);
        !          1185:                        return status;
        !          1186:                }
        !          1187:        }
        !          1188: 
        !          1189:        status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
        !          1190:        omapi_message_dereference (&message, MDL);
        !          1191:        return status;
        !          1192: }
        !          1193: 
        !          1194: /* The OMAPI_NOTIFY_PROTOCOL flag will cause the notify-object for the
        !          1195:    message to be set to the protocol object.  This is used when opening
        !          1196:    the default authenticator. */
        !          1197: 
        !          1198: isc_result_t omapi_protocol_send_open (omapi_object_t *po,
        !          1199:                                       omapi_object_t *id,
        !          1200:                                       const char *type,
        !          1201:                                       omapi_object_t *object,
        !          1202:                                       unsigned flags)
        !          1203: {
        !          1204:        isc_result_t status;
        !          1205:        omapi_message_object_t *message = (omapi_message_object_t *)0;
        !          1206:        omapi_object_t *mo;
        !          1207: 
        !          1208:        if (po -> type != omapi_type_protocol)
        !          1209:                return ISC_R_INVALIDARG;
        !          1210: 
        !          1211:        status = omapi_message_new ((omapi_object_t **)&message, MDL);
        !          1212:        mo = (omapi_object_t *)message;
        !          1213: 
        !          1214:        if (status == ISC_R_SUCCESS)
        !          1215:                status = omapi_set_int_value (mo, (omapi_object_t *)0,
        !          1216:                                              "op", OMAPI_OP_OPEN);
        !          1217: 
        !          1218:        if (status == ISC_R_SUCCESS)
        !          1219:                status = omapi_set_object_value (mo, (omapi_object_t *)0,
        !          1220:                                                 "object", object);
        !          1221: 
        !          1222:        if ((flags & OMAPI_CREATE) && (status == ISC_R_SUCCESS))
        !          1223:                status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
        !          1224:                                                  "create", 1);
        !          1225: 
        !          1226:        if ((flags & OMAPI_UPDATE) && (status == ISC_R_SUCCESS))
        !          1227:                status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
        !          1228:                                                  "update", 1);
        !          1229: 
        !          1230:        if ((flags & OMAPI_EXCL) && (status == ISC_R_SUCCESS))
        !          1231:                status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
        !          1232:                                                  "exclusive", 1);
        !          1233: 
        !          1234:        if ((flags & OMAPI_NOTIFY_PROTOCOL) && (status == ISC_R_SUCCESS))
        !          1235:                status = omapi_set_object_value (mo, (omapi_object_t *)0,
        !          1236:                                                 "notify-object", po);
        !          1237: 
        !          1238:        if (type && (status == ISC_R_SUCCESS))
        !          1239:                status = omapi_set_string_value (mo, (omapi_object_t *)0,
        !          1240:                                                 "type", type);
        !          1241: 
        !          1242:        if (status == ISC_R_SUCCESS)
        !          1243:                status = omapi_message_register (mo);
        !          1244: 
        !          1245:        if (status == ISC_R_SUCCESS) {
        !          1246:                status = omapi_protocol_send_message (po, id, mo,
        !          1247:                                                      (omapi_object_t *)0);
        !          1248:                if (status != ISC_R_SUCCESS)
        !          1249:                        omapi_message_unregister (mo);
        !          1250:        }
        !          1251: 
        !          1252:        if (message)
        !          1253:                omapi_message_dereference (&message, MDL);
        !          1254: 
        !          1255:        return status;
        !          1256: }
        !          1257: 
        !          1258: isc_result_t omapi_protocol_send_update (omapi_object_t *po,
        !          1259:                                         omapi_object_t *id,
        !          1260:                                         unsigned rid,
        !          1261:                                         omapi_object_t *object)
        !          1262: {
        !          1263:        isc_result_t status;
        !          1264:        omapi_message_object_t *message = (omapi_message_object_t *)0;
        !          1265:        omapi_object_t *mo;
        !          1266: 
        !          1267:        if (po -> type != omapi_type_protocol)
        !          1268:                return ISC_R_INVALIDARG;
        !          1269: 
        !          1270:        status = omapi_message_new ((omapi_object_t **)&message, MDL);
        !          1271:        if (status != ISC_R_SUCCESS)
        !          1272:                return status;
        !          1273:        mo = (omapi_object_t *)message;
        !          1274: 
        !          1275:        status = omapi_set_int_value (mo, (omapi_object_t *)0,
        !          1276:                                      "op", OMAPI_OP_UPDATE);
        !          1277:        if (status != ISC_R_SUCCESS) {
        !          1278:                omapi_message_dereference (&message, MDL);
        !          1279:                return status;
        !          1280:        }
        !          1281: 
        !          1282:        if (rid) {
        !          1283:                omapi_handle_t handle;
        !          1284:                status = omapi_set_int_value (mo, (omapi_object_t *)0,
        !          1285:                                              "rid", (int)rid);
        !          1286:                if (status != ISC_R_SUCCESS) {
        !          1287:                        omapi_message_dereference (&message, MDL);
        !          1288:                        return status;
        !          1289:                }
        !          1290: 
        !          1291:                status = omapi_object_handle (&handle, object);
        !          1292:                if (status != ISC_R_SUCCESS) {
        !          1293:                        omapi_message_dereference (&message, MDL);
        !          1294:                        return status;
        !          1295:                }
        !          1296:                status = omapi_set_int_value (mo, (omapi_object_t *)0,
        !          1297:                                              "handle", (int)handle);
        !          1298:                if (status != ISC_R_SUCCESS) {
        !          1299:                        omapi_message_dereference (&message, MDL);
        !          1300:                        return status;
        !          1301:                }
        !          1302:        }               
        !          1303:                
        !          1304:        status = omapi_set_object_value (mo, (omapi_object_t *)0,
        !          1305:                                         "object", object);
        !          1306:        if (status != ISC_R_SUCCESS) {
        !          1307:                omapi_message_dereference (&message, MDL);
        !          1308:                return status;
        !          1309:        }
        !          1310: 
        !          1311:        status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
        !          1312:        omapi_message_dereference (&message, MDL);
        !          1313:        return status;
        !          1314: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>