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

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

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