1999-10-27 22:24:32 +00:00
|
|
|
/*
|
1999-11-02 04:01:34 +00:00
|
|
|
* Copyright (C) 1996, 1997, 1998, 1999 Internet Software Consortium.
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
|
|
|
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
|
|
|
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
|
|
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
|
|
|
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
|
|
* SOFTWARE.
|
1999-10-27 22:24:32 +00:00
|
|
|
*/
|
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
|
|
|
* Functions supporting the object management protocol.
|
|
|
|
*/
|
|
|
|
#include <stddef.h> /* NULL */
|
2000-01-04 20:04:42 +00:00
|
|
|
#include <stdlib.h> /* random */
|
1999-11-02 04:01:34 +00:00
|
|
|
#include <string.h> /* memset */
|
|
|
|
|
|
|
|
#include <isc/assertions.h>
|
|
|
|
#include <isc/error.h>
|
|
|
|
|
2000-01-04 20:04:42 +00:00
|
|
|
#include <omapi/private.h>
|
1999-11-02 04:01:34 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
/*
|
|
|
|
* OMAPI protocol header, version 1.00
|
|
|
|
*/
|
|
|
|
typedef struct omapi_protocolheader {
|
|
|
|
unsigned int authlen; /* Length of authenticator. */
|
|
|
|
unsigned int authid; /* Authenticator object ID. */
|
|
|
|
unsigned int op; /* Operation code. */
|
|
|
|
omapi_handle_t handle; /* Handle of object being operated on or 0. */
|
|
|
|
unsigned int id; /* Transaction ID. */
|
|
|
|
unsigned int rid; /* ID of transaction responding to. */
|
|
|
|
} omapi_protocolheader_t;
|
1999-11-02 04:01:34 +00:00
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
omapi_protocol_connect(omapi_object_t *h, const char *server_name,
|
|
|
|
int port, omapi_object_t *authinfo)
|
1999-10-27 22:24:32 +00:00
|
|
|
{
|
1999-11-02 04:01:34 +00:00
|
|
|
isc_result_t result;
|
2000-01-22 00:18:05 +00:00
|
|
|
omapi_protocol_t *obj;
|
1999-10-27 22:24:32 +00:00
|
|
|
|
2000-01-17 18:02:11 +00:00
|
|
|
obj = NULL;
|
|
|
|
result = omapi_object_create((omapi_object_t **)&obj,
|
|
|
|
omapi_type_protocol, sizeof(*obj));
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
1999-11-02 04:01:34 +00:00
|
|
|
|
2000-01-17 20:06:37 +00:00
|
|
|
result = connect_toserver((omapi_object_t *)obj, server_name, port);
|
1999-11-02 04:01:34 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-01-17 18:02:11 +00:00
|
|
|
OBJECT_DEREF(&obj);
|
1999-11-02 04:01:34 +00:00
|
|
|
return (result);
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|
2000-01-17 18:02:11 +00:00
|
|
|
OBJECT_REF(&h->outer, obj);
|
|
|
|
OBJECT_REF(&obj->inner, h);
|
1999-11-02 04:01:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Send the introductory message.
|
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
result = send_intro((omapi_object_t *)obj, OMAPI_PROTOCOL_VERSION);
|
1999-11-02 04:01:34 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-01-17 18:02:11 +00:00
|
|
|
OBJECT_DEREF(&obj);
|
1999-11-02 04:01:34 +00:00
|
|
|
return (result);
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
/*
|
|
|
|
* Wait for the server's introductory message before proceeding.
|
|
|
|
* While the original design for OMAPI declared that this was
|
|
|
|
* to be entirely asynchronous, it just won't work for the client
|
|
|
|
* side program to go storming ahead, making calls that try to
|
|
|
|
* use the connection object, when it is possible that the thread
|
|
|
|
* that reads the socket will wake up with the server's intro
|
|
|
|
* message, find some sort of problem, and then blow away the
|
|
|
|
* connection object while the client program is asynchronously
|
|
|
|
* trying to use it. (This could be done, of course, with a lot
|
|
|
|
* more thread locking than currently happens.)
|
|
|
|
* XXXDCL of course, the above also implies that this function
|
|
|
|
* will return something *useful* if the task thread blows away the
|
|
|
|
* connection, but that is not currently true. I need to make it so.
|
|
|
|
*/
|
|
|
|
result = connection_wait(obj->outer, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
OBJECT_DEREF(&obj);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (authinfo != NULL)
|
2000-01-17 18:02:11 +00:00
|
|
|
OBJECT_REF(&obj->authinfo, authinfo);
|
2000-01-22 00:18:05 +00:00
|
|
|
|
2000-01-17 18:02:11 +00:00
|
|
|
OBJECT_DEREF(&obj);
|
2000-01-22 00:18:05 +00:00
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
2000-01-06 23:56:51 +00:00
|
|
|
void
|
|
|
|
omapi_protocol_disconnect(omapi_object_t *handle, isc_boolean_t force) {
|
2000-01-22 00:18:05 +00:00
|
|
|
omapi_protocol_t *protocol;
|
|
|
|
omapi_connection_t *connection;
|
2000-01-06 23:56:51 +00:00
|
|
|
|
|
|
|
REQUIRE(handle != NULL);
|
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol = (omapi_protocol_t *)handle->outer;
|
2000-01-06 23:56:51 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
INSIST(protocol != NULL && protocol->type == omapi_type_protocol);
|
2000-01-06 23:56:51 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
connection = (omapi_connection_t *)protocol->outer;
|
2000-01-06 23:56:51 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
INSIST(connection != NULL &&
|
2000-01-14 23:10:04 +00:00
|
|
|
connection->type == omapi_type_connection);
|
2000-01-06 23:56:51 +00:00
|
|
|
|
|
|
|
omapi_connection_disconnect((omapi_object_t *)connection, force);
|
|
|
|
}
|
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
|
|
|
* Send the protocol introduction message.
|
|
|
|
*/
|
|
|
|
isc_result_t
|
2000-01-22 00:18:05 +00:00
|
|
|
send_intro(omapi_object_t *h, unsigned int ver) {
|
1999-11-02 04:01:34 +00:00
|
|
|
isc_result_t result;
|
2000-01-22 00:18:05 +00:00
|
|
|
omapi_protocol_t *p;
|
|
|
|
omapi_connection_t *connection;
|
1999-10-27 22:24:32 +00:00
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
REQUIRE(h != NULL && h->type == omapi_type_protocol);
|
1999-10-27 22:24:32 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
p = (omapi_protocol_t *)h;
|
|
|
|
connection = (omapi_connection_t *)h->outer;
|
1999-10-27 22:24:32 +00:00
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
if (h->outer == NULL || h->outer->type != omapi_type_connection)
|
2000-01-06 23:56:51 +00:00
|
|
|
return (OMAPI_R_NOTCONNECTED);
|
1999-11-02 04:01:34 +00:00
|
|
|
|
2000-01-06 03:36:32 +00:00
|
|
|
result = omapi_connection_putuint32((omapi_object_t *)connection,
|
2000-01-04 20:04:42 +00:00
|
|
|
ver);
|
1999-11-02 04:01:34 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
2000-01-06 03:36:32 +00:00
|
|
|
result = omapi_connection_putuint32((omapi_object_t *)connection,
|
2000-01-22 00:18:05 +00:00
|
|
|
sizeof(omapi_protocolheader_t));
|
1999-11-02 04:01:34 +00:00
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Require the other end to send an intro - this kicks off the
|
|
|
|
* protocol input state machine.
|
|
|
|
*/
|
|
|
|
p->state = omapi_protocol_intro_wait;
|
2000-01-22 00:18:05 +00:00
|
|
|
result = connection_require(connection, 8);
|
2000-01-06 03:36:32 +00:00
|
|
|
if (result != ISC_R_SUCCESS && result != OMAPI_R_NOTYET)
|
1999-11-02 04:01:34 +00:00
|
|
|
return (result);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make up an initial transaction ID for this connection.
|
|
|
|
* XXXDCL better generator than random()?
|
|
|
|
*/
|
|
|
|
p->next_xid = random();
|
2000-01-04 20:04:42 +00:00
|
|
|
|
2000-01-06 03:36:32 +00:00
|
|
|
connection_send(connection);
|
2000-01-04 20:04:42 +00:00
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
2000-01-17 20:06:37 +00:00
|
|
|
/*
|
|
|
|
* Set up a listener for the omapi protocol.
|
|
|
|
*/
|
|
|
|
isc_result_t
|
|
|
|
omapi_protocol_listen(omapi_object_t *manager, int port, int max) {
|
|
|
|
return (omapi_listener_listen((omapi_object_t *)manager, port, max));
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2000-01-22 00:18:05 +00:00
|
|
|
send_status(omapi_object_t *po, isc_result_t waitstatus,
|
|
|
|
unsigned int rid, const char *msg)
|
2000-01-17 20:06:37 +00:00
|
|
|
{
|
|
|
|
isc_result_t result;
|
|
|
|
omapi_object_t *message = NULL;
|
|
|
|
|
|
|
|
REQUIRE(po != NULL && po->type == omapi_type_protocol);
|
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_message_create(&message);
|
2000-01-17 20:06:37 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_object_setinteger(message, "op", OMAPI_OP_STATUS);
|
2000-01-17 20:06:37 +00:00
|
|
|
|
|
|
|
if (result == ISC_R_SUCCESS)
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_object_setinteger(message, "rid", (int)rid);
|
2000-01-17 20:06:37 +00:00
|
|
|
|
|
|
|
if (result == ISC_R_SUCCESS)
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_object_setinteger(message, "result",
|
|
|
|
(int)waitstatus);
|
2000-01-17 20:06:37 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If a message has been provided, send it.
|
|
|
|
*/
|
|
|
|
if (result == ISC_R_SUCCESS && msg != NULL)
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_object_setstring(message, "message", msg);
|
2000-01-17 20:06:37 +00:00
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
OBJECT_DEREF(&message);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
return (omapi_message_send(message, po));
|
2000-01-17 20:06:37 +00:00
|
|
|
}
|
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
isc_result_t
|
2000-01-22 00:18:05 +00:00
|
|
|
send_update(omapi_object_t *po, unsigned int rid, omapi_object_t *object) {
|
2000-01-17 20:06:37 +00:00
|
|
|
isc_result_t result;
|
|
|
|
omapi_object_t *message = NULL;
|
|
|
|
|
|
|
|
REQUIRE(po != NULL && po->type == omapi_type_protocol);
|
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_message_create(&message);
|
2000-01-17 20:06:37 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_object_setinteger(message, "op", OMAPI_OP_UPDATE);
|
2000-01-17 20:06:37 +00:00
|
|
|
|
|
|
|
if (result == ISC_R_SUCCESS && rid != 0) {
|
|
|
|
omapi_handle_t handle;
|
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_object_setinteger(message, "rid", (int)rid);
|
2000-01-17 20:06:37 +00:00
|
|
|
|
|
|
|
if (result == ISC_R_SUCCESS)
|
2000-01-22 00:18:05 +00:00
|
|
|
result = object_gethandle(&handle, object);
|
2000-01-17 20:06:37 +00:00
|
|
|
|
|
|
|
if (result == ISC_R_SUCCESS)
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_object_setinteger(message, "handle",
|
|
|
|
(int)handle);
|
2000-01-17 20:06:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (result == ISC_R_SUCCESS)
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_object_setobject(message, "object", object);
|
2000-01-17 20:06:37 +00:00
|
|
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
OBJECT_DEREF(&message);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
return (omapi_message_send(message, po));
|
2000-01-17 20:06:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
2000-01-22 00:18:05 +00:00
|
|
|
dispatch_messages(omapi_protocol_t *protocol,
|
|
|
|
omapi_connection_t *connection)
|
1999-10-27 22:24:32 +00:00
|
|
|
{
|
1999-11-02 04:01:34 +00:00
|
|
|
isc_uint16_t nlen;
|
|
|
|
isc_uint32_t vlen;
|
2000-01-22 00:18:05 +00:00
|
|
|
isc_result_t result;
|
1999-11-02 04:01:34 +00:00
|
|
|
|
2000-01-13 06:13:26 +00:00
|
|
|
/*
|
|
|
|
* XXXDCL figure out how come when this function throws
|
2000-01-22 00:18:05 +00:00
|
|
|
* an error, it does not seem to be seen by the driving program.
|
|
|
|
* (this comment may no longer be true, but bears testing anyway)
|
2000-01-13 06:13:26 +00:00
|
|
|
*/
|
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
|
|
|
* We get here because we requested that we be woken up after
|
|
|
|
* some number of bytes were read, and that number of bytes
|
|
|
|
* has in fact been read.
|
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
switch (protocol->state) {
|
1999-11-02 04:01:34 +00:00
|
|
|
case omapi_protocol_intro_wait:
|
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Get protocol version and header size in network byte order.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
connection_getuint32(connection, &protocol->protocol_version);
|
|
|
|
connection_getuint32(connection, &protocol->header_size);
|
1999-10-27 22:24:32 +00:00
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Currently only the current protocol version is supported.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
if (protocol->protocol_version != OMAPI_PROTOCOL_VERSION)
|
|
|
|
return (OMAPI_R_VERSIONMISMATCH);
|
1999-10-27 22:24:32 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
if (protocol->header_size < sizeof(omapi_protocolheader_t))
|
|
|
|
return (OMAPI_R_PROTOCOLERROR);
|
1999-10-27 22:24:32 +00:00
|
|
|
|
2000-01-17 18:02:11 +00:00
|
|
|
/*
|
|
|
|
* The next thing that shows up on incoming connections
|
|
|
|
* should be a message header.
|
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol->state = omapi_protocol_header_wait;
|
2000-01-17 18:02:11 +00:00
|
|
|
|
2000-01-13 06:13:26 +00:00
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Signal connection_wait() to wake up.
|
|
|
|
* Only do this for the client side, which needs to be
|
|
|
|
* blocked otherwise it might try to use a connection
|
|
|
|
* which is destroyed during the processing that is
|
|
|
|
* driven by the socket thread.
|
|
|
|
*
|
|
|
|
* XXXDCL this code is duplicated below
|
2000-01-13 06:13:26 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
if (connection->is_client) {
|
|
|
|
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) ==
|
2000-01-14 23:10:04 +00:00
|
|
|
ISC_R_SUCCESS);
|
2000-01-13 06:13:26 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
INSIST(connection->messages_expected > 0);
|
|
|
|
connection->messages_expected--;
|
2000-01-13 06:13:26 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
RUNTIME_CHECK(isc_condition_signal(&connection->waiter)
|
|
|
|
== ISC_R_SUCCESS);
|
2000-01-13 06:13:26 +00:00
|
|
|
|
|
|
|
/*
|
2000-01-17 18:02:11 +00:00
|
|
|
* If the driving program has already called
|
2000-01-22 00:18:05 +00:00
|
|
|
* omapi_message_send and the lock
|
2000-01-17 18:02:11 +00:00
|
|
|
* was acquired in that function, then since
|
|
|
|
* messages_expected would have been >= 2 at
|
|
|
|
* the critical test, the omapi_connection_require
|
|
|
|
* would not have been done yet, and will need
|
|
|
|
* to be. Since messages_expected was decremented,
|
|
|
|
* drop through to the connection_require only if
|
2000-01-22 00:18:05 +00:00
|
|
|
* messages_expected is >= 1.
|
|
|
|
*
|
|
|
|
* The "not yet" response tells the calling
|
|
|
|
* signal handler that there is not yet another
|
|
|
|
* message to be processed.
|
2000-01-17 18:02:11 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
if (connection->messages_expected == 0) {
|
|
|
|
RUNTIME_CHECK(isc_mutex_unlock(&connection->
|
|
|
|
mutex)
|
|
|
|
== ISC_R_SUCCESS);
|
|
|
|
result = OMAPI_R_NOTYET;
|
2000-01-17 18:02:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Proceed to the omapi_connection_require
|
|
|
|
* for the first "real" message's header.
|
2000-01-13 06:13:26 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
|
2000-01-14 23:10:04 +00:00
|
|
|
ISC_R_SUCCESS);
|
2000-01-13 06:13:26 +00:00
|
|
|
}
|
1999-10-27 22:24:32 +00:00
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
2000-01-17 18:02:11 +00:00
|
|
|
* Register a need for the number of bytes in a header, and if
|
|
|
|
* that many are here already, process them immediately.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
result = connection_require(connection, protocol->header_size);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-10-27 22:24:32 +00:00
|
|
|
break;
|
2000-01-17 18:02:11 +00:00
|
|
|
|
|
|
|
/* FALLTHROUGH */
|
1999-11-02 04:01:34 +00:00
|
|
|
|
|
|
|
case omapi_protocol_header_wait:
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_message_create((omapi_object_t **)
|
|
|
|
&protocol->message);
|
2000-01-14 23:10:04 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-01-22 00:18:05 +00:00
|
|
|
break;
|
1999-10-27 22:24:32 +00:00
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Fetch the header values.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
connection_getuint32(connection, &protocol->message->authid);
|
1999-11-02 04:01:34 +00:00
|
|
|
/* XXXTL bind the authenticator here! */
|
2000-01-22 00:18:05 +00:00
|
|
|
connection_getuint32(connection, &protocol->message->authlen);
|
|
|
|
connection_getuint32(connection, &protocol->message->op);
|
2000-01-24 15:22:46 +00:00
|
|
|
connection_getuint32(connection, &protocol->message->h);
|
2000-01-22 00:18:05 +00:00
|
|
|
connection_getuint32(connection, &protocol->message->id);
|
|
|
|
connection_getuint32(connection, &protocol->message->rid);
|
1999-11-02 04:01:34 +00:00
|
|
|
|
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* If there was any extra header data, skip over it,
|
|
|
|
* because it has no use in this version of the protocol.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
if (protocol->header_size > sizeof(omapi_protocolheader_t))
|
|
|
|
connection_copyout(NULL, connection,
|
|
|
|
(protocol->header_size -
|
|
|
|
sizeof(omapi_protocolheader_t)));
|
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
|
|
|
* XXXTL must compute partial signature across the preceding
|
|
|
|
* bytes. Also, if authenticator specifies encryption as well
|
|
|
|
* as signing, we may have to decrypt the data on the way in.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* After reading the header, first read in message-specific
|
|
|
|
* values, then object values.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol->reading_message_values = ISC_TRUE;
|
1999-11-02 04:01:34 +00:00
|
|
|
|
|
|
|
need_name_length:
|
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Need to get the 16-bit length of the value's name.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol->state = omapi_protocol_name_length_wait;
|
|
|
|
result = connection_require(connection, 2);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-10-27 22:24:32 +00:00
|
|
|
break;
|
2000-01-17 18:02:11 +00:00
|
|
|
|
|
|
|
/* FALLTHROUGH */
|
1999-11-02 04:01:34 +00:00
|
|
|
case omapi_protocol_name_length_wait:
|
2000-01-22 00:18:05 +00:00
|
|
|
connection_getuint16(connection, &nlen);
|
1999-10-27 22:24:32 +00:00
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* A zero-length name signals the end of name+value pairs.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
1999-10-27 22:24:32 +00:00
|
|
|
if (nlen == 0) {
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* If the message values were being read, now
|
|
|
|
* the object values need to be read. Otherwise
|
|
|
|
* move on to reading the authenticator.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
if (protocol->reading_message_values) {
|
|
|
|
protocol->reading_message_values = ISC_FALSE;
|
|
|
|
/*
|
|
|
|
* The goto could be removed by setting the
|
|
|
|
* state and doing omapi_connection_require()
|
|
|
|
* here, then returning the result to
|
|
|
|
* protocol_signalhandler which would call
|
|
|
|
* this function immediately if the result
|
|
|
|
* was ISC_R_SUCCESS, but that seems even
|
|
|
|
* more obtuse than using goto.
|
|
|
|
*/
|
1999-10-27 22:24:32 +00:00
|
|
|
goto need_name_length;
|
|
|
|
}
|
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
|
|
|
* If the authenticator length is zero, there's no
|
|
|
|
* signature to read in, so go straight to processing
|
|
|
|
* the message.
|
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
if (protocol->message->authlen == 0)
|
1999-10-27 22:24:32 +00:00
|
|
|
goto message_done;
|
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* The next thing that is expected is the message
|
|
|
|
* signature.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol->state = omapi_protocol_signature_wait;
|
|
|
|
|
|
|
|
/* Wait for the number of bytes specified for the
|
|
|
|
* authenticator. If they are all here, go read it in.
|
|
|
|
* As noted above, the goto could be removed by
|
|
|
|
* returning the result to the caller no matter
|
|
|
|
* what its value, because the protocol_signalhandler
|
|
|
|
* would just call this function right back, but
|
|
|
|
* something seems more obtuse about that than goto.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
result = connection_require(connection,
|
|
|
|
protocol->message->authlen);
|
|
|
|
if (result == ISC_R_SUCCESS)
|
1999-10-27 22:24:32 +00:00
|
|
|
goto signature_wait;
|
2000-01-17 18:02:11 +00:00
|
|
|
else
|
2000-01-22 00:18:05 +00:00
|
|
|
break;
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Non-zero name length. Allocate a buffer for the name
|
|
|
|
* then wait for all its bytes to be available.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_string_create(&protocol->name, nlen);
|
2000-01-14 23:10:04 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-01-22 00:18:05 +00:00
|
|
|
break;
|
2000-01-14 23:10:04 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol->state = omapi_protocol_name_wait;
|
|
|
|
result = connection_require(connection, nlen);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-10-27 22:24:32 +00:00
|
|
|
break;
|
2000-01-17 18:02:11 +00:00
|
|
|
|
|
|
|
/* FALLTHROUGH */
|
1999-11-02 04:01:34 +00:00
|
|
|
case omapi_protocol_name_wait:
|
2000-01-22 00:18:05 +00:00
|
|
|
connection_copyout(protocol->name->value, connection,
|
|
|
|
protocol->name->len);
|
1999-11-02 04:01:34 +00:00
|
|
|
|
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Wait for the 32-bit length of the value.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol->state = omapi_protocol_value_length_wait;
|
|
|
|
result = connection_require(connection, 4);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-10-27 22:24:32 +00:00
|
|
|
break;
|
|
|
|
|
2000-01-17 18:02:11 +00:00
|
|
|
/* FALLTHROUGH */
|
1999-11-02 04:01:34 +00:00
|
|
|
case omapi_protocol_value_length_wait:
|
2000-01-22 00:18:05 +00:00
|
|
|
connection_getuint32(connection, &vlen);
|
1999-11-02 04:01:34 +00:00
|
|
|
|
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Zero-length values are allowed; they are for deleted
|
|
|
|
* values. If the value length is zero, skip the read but
|
|
|
|
* still store the name with its zero length value.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
|
|
|
if (vlen == 0)
|
1999-10-27 22:24:32 +00:00
|
|
|
goto insert_new_value;
|
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_data_create(&protocol->value,
|
|
|
|
omapi_datatype_data, vlen);
|
2000-01-14 23:10:04 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
1999-10-27 22:24:32 +00:00
|
|
|
break;
|
2000-01-22 00:18:05 +00:00
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Check to see if all the bytes of the value are here.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol->state = omapi_protocol_value_wait;
|
|
|
|
result = connection_require(connection, vlen);
|
2000-01-14 23:10:04 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-01-22 00:18:05 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
case omapi_protocol_value_wait:
|
|
|
|
connection_copyout(protocol->value->u.buffer.value,
|
|
|
|
connection,
|
|
|
|
protocol->value->u.buffer.len);
|
1999-11-02 04:01:34 +00:00
|
|
|
|
|
|
|
insert_new_value:
|
2000-01-22 00:18:05 +00:00
|
|
|
if (protocol->reading_message_values)
|
|
|
|
result = omapi_object_set((omapi_object_t *)
|
|
|
|
protocol->message,
|
|
|
|
protocol->name,
|
|
|
|
protocol->value);
|
|
|
|
|
|
|
|
else {
|
|
|
|
if (protocol->message->object == NULL) {
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Create a generic object to receive the
|
|
|
|
* values of the object in the incoming
|
|
|
|
* message.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_object_create(&protocol->
|
|
|
|
message->object,
|
|
|
|
NULL, 0);
|
2000-01-14 23:10:04 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-01-22 00:18:05 +00:00
|
|
|
break;
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|
2000-01-14 23:10:04 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_object_set((omapi_object_t *)
|
|
|
|
protocol->message->object,
|
|
|
|
protocol->name,
|
|
|
|
protocol->value);
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|
2000-01-14 23:10:04 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-01-22 00:18:05 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
omapi_string_dereference(&protocol->name);
|
|
|
|
omapi_data_dereference(&protocol->value);
|
2000-01-14 23:10:04 +00:00
|
|
|
|
1999-10-27 22:24:32 +00:00
|
|
|
goto need_name_length;
|
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
signature_wait:
|
|
|
|
case omapi_protocol_signature_wait:
|
2000-01-22 00:18:05 +00:00
|
|
|
result = omapi_data_create(&protocol->message->authenticator,
|
|
|
|
omapi_datatype_data,
|
|
|
|
protocol->message->authlen);
|
2000-01-04 20:04:42 +00:00
|
|
|
|
2000-01-14 23:10:04 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
2000-01-22 00:18:05 +00:00
|
|
|
return (result);
|
2000-01-14 23:10:04 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
connection_copyout(protocol->message->authenticator->
|
|
|
|
u.buffer.value,
|
|
|
|
connection,
|
|
|
|
protocol->message->authlen);
|
1999-11-02 04:01:34 +00:00
|
|
|
|
|
|
|
/* XXXTL now do something to verify the signature. */
|
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
/* FALLTHROUGH */
|
|
|
|
message_done:
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Hail, hail, the gang's all here! The whole message
|
|
|
|
* has been read in, so process it. Even if an error
|
|
|
|
* is returned, a bit of cleanup has to be done, but
|
|
|
|
* it can't muck with the result assigned here.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
result = message_process((omapi_object_t *)protocol->message,
|
|
|
|
(omapi_object_t *)protocol);
|
2000-01-13 06:13:26 +00:00
|
|
|
|
2000-01-17 18:02:11 +00:00
|
|
|
/* XXXTL unbind the authenticator. */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Free the message object.
|
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
OBJECT_DEREF(&protocol->message);
|
2000-01-17 18:02:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The next thing the protocol reads will be a new message.
|
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol->state = omapi_protocol_header_wait;
|
2000-01-17 18:02:11 +00:00
|
|
|
|
2000-01-13 06:13:26 +00:00
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Signal connection_wait() to wake up.
|
|
|
|
* XXXDCL code is duplicated from above.
|
2000-01-13 06:13:26 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
if (connection->is_client) {
|
|
|
|
RUNTIME_CHECK(isc_mutex_lock(&connection->mutex) ==
|
2000-01-14 23:10:04 +00:00
|
|
|
ISC_R_SUCCESS);
|
2000-01-13 06:13:26 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
INSIST(connection->messages_expected > 0);
|
|
|
|
connection->messages_expected--;
|
2000-01-13 06:13:26 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
RUNTIME_CHECK(isc_condition_signal(&connection->waiter)
|
|
|
|
== ISC_R_SUCCESS);
|
2000-01-13 06:13:26 +00:00
|
|
|
|
2000-01-17 18:02:11 +00:00
|
|
|
/*
|
|
|
|
* If there are no more messages expected, exit
|
|
|
|
* the signal handler.
|
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
if (connection->messages_expected == 0) {
|
|
|
|
RUNTIME_CHECK(isc_mutex_unlock(&connection->
|
|
|
|
mutex) ==
|
2000-01-17 18:02:11 +00:00
|
|
|
ISC_R_SUCCESS);
|
2000-01-22 00:18:05 +00:00
|
|
|
result = OMAPI_R_NOTYET;
|
2000-01-17 18:02:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
RUNTIME_CHECK(isc_mutex_unlock(&connection->mutex) ==
|
2000-01-14 23:10:04 +00:00
|
|
|
ISC_R_SUCCESS);
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
2000-01-13 06:13:26 +00:00
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Now, if message_process had indicated an error, let it be
|
|
|
|
* returned from here.
|
2000-01-13 06:13:26 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
break;
|
1999-10-27 22:24:32 +00:00
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
/*
|
2000-01-22 00:18:05 +00:00
|
|
|
* Queue up the next recv; if this next header is already
|
|
|
|
* received, ISC_R_SUCCESS will be returned to
|
|
|
|
* protocol_signalhandler, which will cause it to immediately
|
|
|
|
* call this function again to process it.
|
1999-11-02 04:01:34 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
result = connection_require(connection, protocol->header_size);
|
|
|
|
break;
|
1999-10-27 22:24:32 +00:00
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
default:
|
2000-01-14 23:10:04 +00:00
|
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__, "unknown state in "
|
1999-11-02 04:01:34 +00:00
|
|
|
"omapi_protocol_signal_handler: %d\n",
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol->state);
|
|
|
|
result = ISC_R_UNEXPECTED;
|
1999-10-27 22:24:32 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-11-02 04:01:34 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
return (result);
|
|
|
|
}
|
2000-01-13 06:13:26 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
static isc_result_t
|
|
|
|
protocol_signalhandler(omapi_object_t *h, const char *name, va_list ap)
|
|
|
|
{
|
|
|
|
isc_result_t result;
|
|
|
|
omapi_protocol_t *p;
|
|
|
|
omapi_object_t *connection;
|
|
|
|
omapi_connection_t *c;
|
|
|
|
|
|
|
|
REQUIRE(h != NULL && h->type == omapi_type_protocol);
|
|
|
|
|
|
|
|
p = (omapi_protocol_t *)h;
|
|
|
|
c = (omapi_connection_t *)p->outer;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Not a signal we recognize?
|
2000-01-13 06:13:26 +00:00
|
|
|
*/
|
2000-01-22 00:18:05 +00:00
|
|
|
if (strcmp(name, "ready") != 0)
|
|
|
|
return (omapi_object_passsignal(h, name, ap));
|
|
|
|
|
|
|
|
INSIST(p->outer != NULL && p->outer->type == omapi_type_connection);
|
|
|
|
|
|
|
|
connection = p->outer;
|
|
|
|
|
|
|
|
do {
|
|
|
|
result = dispatch_messages(p, c);
|
|
|
|
} while (result == ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Getting "not yet" means more data is needed before another message
|
|
|
|
* can be processed.
|
|
|
|
*/
|
|
|
|
if (result == OMAPI_R_NOTYET)
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
|
2000-01-13 06:13:26 +00:00
|
|
|
return (result);
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
2000-01-17 20:06:37 +00:00
|
|
|
static isc_result_t
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol_setvalue(omapi_object_t *h, omapi_string_t *name, omapi_data_t *value)
|
1999-10-27 22:24:32 +00:00
|
|
|
{
|
1999-11-02 04:01:34 +00:00
|
|
|
REQUIRE(h != NULL && h->type == omapi_type_protocol);
|
1999-10-27 22:24:32 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
return (omapi_object_passsetvalue(h, name, value));
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
2000-01-17 20:06:37 +00:00
|
|
|
static isc_result_t
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol_getvalue(omapi_object_t *h, omapi_string_t *name,
|
|
|
|
omapi_value_t **value)
|
1999-10-27 22:24:32 +00:00
|
|
|
{
|
1999-11-02 04:01:34 +00:00
|
|
|
REQUIRE(h != NULL && h->type == omapi_type_protocol);
|
1999-10-27 22:24:32 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
return (omapi_object_passgetvalue(h, name, value));
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
2000-01-17 20:06:37 +00:00
|
|
|
static void
|
|
|
|
protocol_destroy(omapi_object_t *h) {
|
2000-01-22 00:18:05 +00:00
|
|
|
omapi_protocol_t *p;
|
1999-11-02 04:01:34 +00:00
|
|
|
|
|
|
|
REQUIRE(h != NULL && h->type == omapi_type_protocol);
|
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
p = (omapi_protocol_t *)h;
|
1999-11-02 04:01:34 +00:00
|
|
|
|
|
|
|
if (p->message != NULL)
|
2000-01-17 18:02:11 +00:00
|
|
|
OBJECT_DEREF(&p->message);
|
1999-11-02 04:01:34 +00:00
|
|
|
|
|
|
|
if (p->authinfo != NULL)
|
2000-01-17 18:02:11 +00:00
|
|
|
OBJECT_DEREF(&p->authinfo);
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
2000-01-17 20:06:37 +00:00
|
|
|
static isc_result_t
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol_stuffvalues(omapi_object_t *connection, omapi_object_t *h)
|
1999-10-27 22:24:32 +00:00
|
|
|
{
|
1999-11-02 04:01:34 +00:00
|
|
|
REQUIRE(h != NULL && h->type == omapi_type_protocol);
|
1999-10-27 22:24:32 +00:00
|
|
|
|
2000-01-22 00:18:05 +00:00
|
|
|
return (omapi_object_passstuffvalues(connection, h));
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|
|
|
|
|
1999-11-02 04:01:34 +00:00
|
|
|
isc_result_t
|
2000-01-22 00:18:05 +00:00
|
|
|
protocol_init(void) {
|
2000-01-17 20:06:37 +00:00
|
|
|
return (omapi_object_register(&omapi_type_protocol, "protocol",
|
|
|
|
protocol_setvalue,
|
|
|
|
protocol_getvalue,
|
|
|
|
protocol_destroy,
|
|
|
|
protocol_signalhandler,
|
|
|
|
protocol_stuffvalues,
|
|
|
|
NULL, NULL, NULL));
|
1999-10-27 22:24:32 +00:00
|
|
|
}
|