2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 05:28:00 +00:00

Remove OMAPI.

This commit is contained in:
Brian Wellington 2001-03-27 00:53:58 +00:00
parent 1b4e6163be
commit badf66abe0
38 changed files with 7 additions and 9127 deletions

View File

@ -1,57 +0,0 @@
/*
* Copyright (C) 2000, 2001 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.
*/
/* $Id: omapi.h,v 1.20 2001/03/04 21:21:35 bwelling Exp $ */
#ifndef NAMED_OMAPI_H
#define NAMED_OMAPI_H 1
#include <omapi/omapi.h>
#include <named/aclconf.h>
#define NS_OMAPI_PORT 953
/*
* This string is the registration name of objects of type control_object_t.
*/
#define NS_OMAPI_CONTROL "control"
#define NS_OMAPI_COMMAND_STOP "stop"
#define NS_OMAPI_COMMAND_HALT "halt"
#define NS_OMAPI_COMMAND_RELOAD "reload"
#define NS_OMAPI_COMMAND_RELOADCONFIG "reload-config"
#define NS_OMAPI_COMMAND_RELOADZONES "reload-zones"
#define NS_OMAPI_COMMAND_REFRESH "refresh"
#define NS_OMAPI_COMMAND_DUMPSTATS "stats"
#define NS_OMAPI_COMMAND_QUERYLOG "querylog"
#define NS_OMAPI_COMMAND_DUMPDB "dumpdb"
#define NS_OMAPI_COMMAND_TRACE "trace"
#define NS_OMAPI_COMMAND_NOTRACE "notrace"
isc_result_t
ns_omapi_init(void);
isc_result_t
ns_omapi_configure(isc_mem_t *mctx, cfg_obj_t *config,
ns_aclconfctx_t *aclconfctx);
void
ns_omapi_shutdown(isc_boolean_t exiting);
#endif /* NAMED_OMAPI_H */

View File

@ -1,203 +0,0 @@
/*
* Copyright (C) 2000, 2001 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.
*/
/* $Id: omapi.c,v 1.32 2001/02/07 00:50:40 bwelling Exp $ */
/*
* Principal Author: DCL
*/
#include <config.h>
#include <string.h>
#include <isc/app.h>
#include <isc/event.h>
#include <isc/mem.h>
#include <isc/util.h>
#include <named/log.h>
#include <named/omapi.h>
#include <named/server.h>
/*
* The control_object structure is used for receiving commands that
* request the server to perform some action, but that do not set or
* get any state.
*/
typedef struct control_object {
OMAPI_OBJECT_PREAMBLE;
} control_object_t;
static control_object_t control;
static omapi_objecttype_t *control_type;
#undef REGION_FMT
/*
* Ok, kind of gross. Sorry. A little.
*/
#define REGION_FMT(r) (int)(r)->length, (r)->base
/*
* This is the function that is called when an incoming OMAPI_OP_OPEN
* message is received with either the create or update option set.
* It is called once for each name/value pair in the message's object
* value list.
*/
static isc_result_t
control_setvalue(omapi_object_t *handle, omapi_string_t *name,
omapi_data_t *value)
{
isc_region_t region;
isc_result_t result;
char *args;
INSIST(handle == (omapi_object_t *)&control);
omapi_string_totext(name, &region);
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_OMAPI, ISC_LOG_DEBUG(1),
"received control channel command '%.*s'",
REGION_FMT(&region));
if (value == NULL)
return (ISC_R_FAILURE); /* XXX can this happen? */
args = omapi_data_strdup(ns_g_mctx, value);
if (args == NULL)
return (ISC_R_NOMEMORY);
/*
* Compare the 'name' parameter against all known control commands.
*/
if (omapi_string_strcmp(name, NS_OMAPI_COMMAND_RELOAD) == 0) {
result = ns_server_reloadcommand(ns_g_server, args);
} else if (omapi_string_strcmp(name, NS_OMAPI_COMMAND_REFRESH) == 0) {
result = ns_server_refreshcommand(ns_g_server, args);
} else if (omapi_string_strcmp(name, NS_OMAPI_COMMAND_HALT) == 0) {
ns_server_flushonshutdown(ns_g_server, ISC_FALSE);
isc_app_shutdown();
result = ISC_R_SUCCESS;
} else if (omapi_string_strcmp(name, NS_OMAPI_COMMAND_STOP) == 0) {
ns_server_flushonshutdown(ns_g_server, ISC_TRUE);
isc_app_shutdown();
result = ISC_R_SUCCESS;
} else if (omapi_string_strcmp(name,
NS_OMAPI_COMMAND_RELOADCONFIG) == 0 ||
omapi_string_strcmp(name,
NS_OMAPI_COMMAND_RELOADZONES) == 0) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_OMAPI, ISC_LOG_WARNING,
"unimplemented channel command '%.*s'",
REGION_FMT(&region));
result = ISC_R_NOTIMPLEMENTED;
} else if (omapi_string_strcmp(name, NS_OMAPI_COMMAND_DUMPSTATS)
== 0) {
result = ns_server_dumpstats(ns_g_server);
} else if (omapi_string_strcmp(name, NS_OMAPI_COMMAND_QUERYLOG) == 0) {
result = ns_server_togglequerylog(ns_g_server);
} else if (omapi_string_strcmp(name, NS_OMAPI_COMMAND_DUMPDB) == 0) {
ns_server_dumpdb(ns_g_server);
result = ISC_R_SUCCESS;
} else if (omapi_string_strcmp(name, NS_OMAPI_COMMAND_TRACE) == 0) {
result = ns_server_setdebuglevel(ns_g_server, args);
} else if (omapi_string_strcmp(name, NS_OMAPI_COMMAND_NOTRACE) == 0) {
ns_g_debuglevel = 0;
isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
result = ISC_R_SUCCESS;
} else {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_OMAPI, ISC_LOG_WARNING,
"unknown control channel command '%.*s'",
REGION_FMT(&region));
result = omapi_object_passsetvalue(handle, name, value);
}
isc_mem_free(ns_g_mctx, args);
return (result);
}
/*
* This is the function that is called by the library's internal
* message_process function when an incoming OMAPI_OP_OPEN message is received.
* It is supposed to look up the object in the server that corresponds to the
* key data (name/value pair(s)) in 'key'.
*/
static isc_result_t
control_lookup(omapi_object_t **control_object, omapi_object_t *key) {
/*
* There is only one control object so no key is needed to look it up.
*/
UNUSED(key);
omapi_object_reference(control_object, (omapi_object_t *)&control);
return (ISC_R_SUCCESS);
}
/*
* This function is called when the server is sending a reply to a client
* that opened an object of its type. It needs to output all published
* name/value pairs for the object, and will typically also put the data
* for any inner objects (but in this program, there will be no inner
* objects). The handle parameter is an object of the type registered
* in ns_omapi_listen.
*/
static isc_result_t
control_stuffvalues(omapi_object_t *connection, omapi_object_t *handle) {
/*
* Currently the server has no values to publish, but it needs
* to publish something for its OMAPI_OP_UPDATE function to work
* when received by the client.
*/
return (omapi_object_passstuffvalues(connection, handle));
}
isc_result_t
ns_omapi_init(void) {
isc_result_t result;
result = omapi_lib_init(ns_g_mctx, ns_g_taskmgr, ns_g_socketmgr);
if (result == ISC_R_SUCCESS)
/*
* Register the control_object. NS_OMAPI_CONTROL is
* what a client would need to specify as a value for
* the value of "type" in a message when contacting
* the server to perform a control function.
*/
result = omapi_object_register(&control_type, NS_OMAPI_CONTROL,
control_setvalue,
NULL, /* getvalue */
NULL, /* destroy */
NULL, /* signalhandler */
control_stuffvalues,
control_lookup,
NULL, /* create */
NULL); /* remove */
if (result == ISC_R_SUCCESS) {
/*
* Initialize the static control object.
*/
control.refcnt = 1;
control.type = control_type;
}
return (result);
}

View File

@ -1,660 +0,0 @@
/*
* Copyright (C) 2000, 2001 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.
*/
/* $Id: omapiconf.c,v 1.17 2001/03/22 00:06:51 bwelling Exp $ */
/*
* Principal Author: DCL
*/
#include <config.h>
#include <isc/base64.h>
#include <isc/buffer.h>
#include <isc/event.h>
#include <isc/mem.h>
#include <isc/once.h>
#include <isc/string.h>
#include <isc/util.h>
#include <isccfg/cfg.h>
#include <dns/result.h>
#include <named/log.h>
#include <named/omapi.h>
#include <named/server.h>
typedef struct ns_omapikey ns_omapikey_t;
typedef ISC_LIST(ns_omapikey_t) ns_omapikeylist_t;
struct ns_omapikey {
char *keyname;
ISC_LINK(ns_omapikey_t) link;
};
typedef struct ns_omapilistener ns_omapilistener_t;
typedef ISC_LIST(ns_omapilistener_t) ns_omapilistenerlist_t;
struct ns_omapilistener {
/* XXXDCL magic */
isc_mem_t * mctx;
omapi_object_t * manager;
isc_sockaddr_t address;
dns_acl_t * acl;
ns_omapikeylist_t keyids;
ISC_LINK(ns_omapilistener_t) link;
};
static ns_omapilistenerlist_t listeners;
static isc_mutex_t listeners_lock;
static isc_once_t once = ISC_ONCE_INIT;
static isc_boolean_t server_exiting = ISC_FALSE;
static void
initialize_mutex(void) {
RUNTIME_CHECK(isc_mutex_init(&listeners_lock) == ISC_R_SUCCESS);
}
static void
free_omapikeylist(ns_omapikeylist_t *keylist, isc_mem_t *mctx) {
while (!ISC_LIST_EMPTY(*keylist)) {
ns_omapikey_t *key = ISC_LIST_HEAD(*keylist);
ISC_LIST_UNLINK(*keylist, key, link);
isc_mem_free(mctx, key->keyname);
isc_mem_put(mctx, key, sizeof(*key));
}
}
static void
free_listener(ns_omapilistener_t *listener) {
free_omapikeylist(&listener->keyids, listener->mctx);
if (listener->acl != NULL)
dns_acl_detach(&listener->acl);
if (listener->manager != NULL)
omapi_object_dereference(&listener->manager);
isc_mem_put(listener->mctx, listener, sizeof(*listener));
}
static void
listen_done(isc_task_t *task, isc_event_t *event) {
ns_omapilistener_t *listener;
UNUSED(task);
listener = event->ev_arg;
LOCK(&listeners_lock);
ISC_LIST_UNLINK(listeners, listener, link);
free_listener(listener);
if (server_exiting && ISC_LIST_EMPTY(listeners))
omapi_lib_destroy();
UNLOCK(&listeners_lock);
isc_event_free(&event);
}
void
ns_omapi_shutdown(isc_boolean_t exiting) {
ns_omapilistener_t *listener;
RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
if (exiting) {
/*
* When not exiting, this function is called from
* ns_omapi_configure(), which already holds the lock.
*/
LOCK(&listeners_lock);
if (ISC_LIST_EMPTY(listeners))
omapi_lib_destroy();
else
server_exiting = exiting;
}
for (listener = ISC_LIST_HEAD(listeners);
listener != NULL;
listener = ISC_LIST_NEXT(listener, link))
/*
* This is asynchronous. As listeners shut down, they will
* call listen_done().
*/
omapi_listener_shutdown(listener->manager);
if (exiting)
UNLOCK(&listeners_lock);
}
static isc_boolean_t
verify_connection(isc_sockaddr_t *sockaddr, void *arg) {
ns_omapilistener_t *listener;
isc_netaddr_t netaddr;
isc_result_t result;
int match;
isc_netaddr_fromsockaddr(&netaddr, sockaddr);
listener = arg;
result = dns_acl_match(&netaddr, NULL, listener->acl,
&ns_g_server->aclenv, &match, NULL);
if (result != ISC_R_SUCCESS || match <= 0)
return (ISC_FALSE);
else
return (ISC_TRUE);
}
static isc_boolean_t
omapikeylist_find(ns_omapikeylist_t *keylist, const char *keyname) {
ns_omapikey_t *key;
for (key = ISC_LIST_HEAD(*keylist);
key != NULL;
key = ISC_LIST_NEXT(key, link))
{
if (strcasecmp(keyname, key->keyname) == 0)
return (ISC_TRUE);
}
return (ISC_FALSE);
}
static isc_result_t
cfgkeylist_find(cfg_obj_t *keylist, const char *keyname, cfg_obj_t **objp) {
cfg_listelt_t *element;
const char *str;
cfg_obj_t *obj;
for (element = cfg_list_first(keylist);
element != NULL;
element = cfg_list_next(element))
{
obj = cfg_listelt_value(element);
str = cfg_obj_asstring(cfg_map_getname(obj));
if (strcasecmp(str, keyname) == 0)
break;
}
if (element == NULL)
return (ISC_R_NOTFOUND);
obj = cfg_listelt_value(element);
*objp = obj;
return (ISC_R_SUCCESS);
}
static isc_result_t
omapikeylist_fromcfg(cfg_obj_t *keylist, isc_mem_t *mctx,
ns_omapikeylist_t *keyids)
{
cfg_listelt_t *element;
char *newstr = NULL;
const char *str;
cfg_obj_t *obj;
ns_omapikey_t *key = NULL;
for (element = cfg_list_first(keylist);
element != NULL;
element = cfg_list_next(element))
{
obj = cfg_listelt_value(element);
str = cfg_obj_asstring(obj);
newstr = isc_mem_strdup(mctx, str);
if (newstr == NULL)
goto cleanup;
key = isc_mem_get(mctx, sizeof(*key));
if (key == NULL)
goto cleanup;
key->keyname = newstr;
ISC_LINK_INIT(key, link);
ISC_LIST_APPEND(*keyids, key, link);
key = NULL;
newstr = NULL;
}
return (ISC_R_SUCCESS);
cleanup:
if (newstr != NULL)
isc_mem_free(mctx, newstr);
if (key != NULL)
isc_mem_put(mctx, key, sizeof(*key));
free_omapikeylist(keyids, mctx);
return (ISC_R_NOMEMORY);
}
static isc_boolean_t
verify_key(const char *name, unsigned int algorithm, void *arg) {
ns_omapilistener_t *listener;
/*
* XXXDCL Ideally algorithm would be checked, too, but the current
* config API makes this moderately hard, and omapi will check it
* anyway.
*/
UNUSED(algorithm);
listener = arg;
return (omapikeylist_find(&listener->keyids, name));
}
static isc_result_t
ns_omapi_listen(ns_omapilistener_t *listener) {
isc_result_t result;
REQUIRE(listener->manager == NULL);
/*
* Create a generic object to be the manager for handling
* incoming server connections.
*/
result = omapi_object_create(&listener->manager, NULL, 0);
if (result == ISC_R_SUCCESS)
/*
* Start listening for connections.
*/
result = omapi_protocol_listen(listener->manager,
&listener->address,
verify_connection, verify_key,
listen_done, listener);
if (result != ISC_R_SUCCESS && listener->manager != NULL)
omapi_object_dereference(&listener->manager);
return (result);
}
static void
register_keys(cfg_obj_t *control, cfg_obj_t *keylist, char *socktext) {
char *keyid;
cfg_obj_t *key;
cfg_obj_t *keydef;
cfg_listelt_t *element;
char secret[1024];
isc_buffer_t b;
isc_result_t result;
/*
* Register the keys used by this listener. omapi_auth_deregister()
* is used to delete any existing key in case its secret or algorithm
* changed.
*
* XXXDCL but this means a little extra work overall when nothing
* changed. In fact, the same key will be register/deregistered/
* reregistered if it appears more than once in the controls statement.
*
* XXXDCL a separate problem is that keys that have been removed
* from the controls statement in a reconfiguration are not deleted
* until the server shuts down.
*/
for (element = cfg_list_first(keylist);
element != NULL;
element = cfg_list_next(element))
{
key = cfg_listelt_value(element);
keyid = cfg_obj_asstring(cfg_map_getname(key));
omapi_auth_deregister(keyid);
/*
* XXXDCL confparser.y apparently allows any keyid
* in the list even if it has not been defined with
* the keys statement.
*/
keydef = NULL;
result = cfgkeylist_find(keylist, keyid, &keydef);
if (result != ISC_R_SUCCESS)
cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
"couldn't find key %s for use with "
"command channel %s", keyid, socktext);
else {
cfg_obj_t *algobj = NULL;
cfg_obj_t *secretobj = NULL;
char *algstr = NULL;
char *secretstr = NULL;
(void)cfg_map_get(keydef, "algorithm", &algobj);
(void)cfg_map_get(keydef, "secret", &secretobj);
INSIST(algobj != NULL && secretobj != NULL);
algstr = cfg_obj_asstring(algobj);
secretstr = cfg_obj_asstring(secretobj);
if (strcasecmp(algstr, "hmac-md5") != 0) {
cfg_obj_log(control, ns_g_lctx,
ISC_LOG_WARNING,
"unsupported algorithm '%s' in "
"key '%s' for use with command "
"channel %s",
algstr, keyid, socktext);
continue;
}
isc_buffer_init(&b, secret, sizeof(secret));
result = isc_base64_decodestring(secretstr, &b);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING,
"secret for key '%s' on "
"command channel %s: %s",
keyid, socktext,
isc_result_totext(result));
continue;
}
result = omapi_auth_register(keyid,
OMAPI_AUTH_HMACMD5,
isc_buffer_base(&b),
isc_buffer_usedlength(&b));
if (result != ISC_R_SUCCESS)
cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING,
"couldn't register key '%s' for"
"use with command channel %s: %s",
keyid, socktext,
isc_result_totext(result));
}
}
}
static void
update_listener(ns_omapilistener_t **listenerp, cfg_obj_t *control,
cfg_obj_t *config, isc_sockaddr_t *addr,
ns_aclconfctx_t *aclconfctx, char *socktext)
{
ns_omapilistener_t *listener;
cfg_obj_t *allow;
cfg_obj_t *keys;
dns_acl_t *new_acl = NULL;
ns_omapikeylist_t keyids;
isc_result_t result;
for (listener = ISC_LIST_HEAD(listeners);
listener != NULL;
listener = ISC_LIST_NEXT(listener, link))
if (isc_sockaddr_equal(addr, &listener->address))
break;
if (listener == NULL) {
*listenerp = NULL;
return;
}
/*
* There is already a listener for this sockaddr.
* Update the access list and key information.
*
* First, keep the old access list unless a new one can be made.
*/
allow = cfg_tuple_get(control, "allow");
result = ns_acl_fromconfig(allow, config, aclconfctx,
listener->mctx, &new_acl);
if (result == ISC_R_SUCCESS) {
dns_acl_detach(&listener->acl);
dns_acl_attach(new_acl, &listener->acl);
dns_acl_detach(&new_acl);
} else
/* XXXDCL say the old acl is still used? */
cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
"couldn't install new acl for "
"command channel %s: %s",
socktext, isc_result_totext(result));
keys = cfg_tuple_get(control, "keys");
ISC_LIST_INIT(keyids);
result = omapikeylist_fromcfg(keys, listener->mctx, &keyids);
if (result != ISC_R_SUCCESS)
cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
"couldn't install new keys for "
"command channel %s: %s",
socktext, isc_result_totext(result));
else {
free_omapikeylist(&listener->keyids, listener->mctx);
listener->keyids = keyids;
}
*listenerp = listener;
}
static void
add_listener(isc_mem_t *mctx, ns_omapilistener_t **listenerp,
cfg_obj_t *control, cfg_obj_t *config, isc_sockaddr_t *addr,
ns_aclconfctx_t *aclconfctx, char *socktext)
{
ns_omapilistener_t *listener;
cfg_obj_t *allow;
cfg_obj_t *keys;
dns_acl_t *new_acl = NULL;
isc_result_t result = ISC_R_SUCCESS;
listener = isc_mem_get(mctx, sizeof(ns_omapilistener_t));
if (listener == NULL)
result = ISC_R_NOMEMORY;
if (result == ISC_R_SUCCESS) {
listener->mctx = mctx;
listener->manager = NULL;
listener->address = *addr;
ISC_LINK_INIT(listener, link);
ISC_LIST_INIT(listener->keyids);
/*
* Make the acl.
*/
allow = cfg_tuple_get(control, "allow");
result = ns_acl_fromconfig(allow, config, aclconfctx, mctx,
&new_acl);
}
if (result == ISC_R_SUCCESS) {
dns_acl_attach(new_acl, &listener->acl);
dns_acl_detach(&new_acl);
keys = cfg_tuple_get(control, "keys");
result = omapikeylist_fromcfg(keys, listener->mctx,
&listener->keyids);
if (result != ISC_R_SUCCESS)
cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
"couldn't install new keys for "
"command channel %s: %s",
socktext, isc_result_totext(result));
}
if (result == ISC_R_SUCCESS)
result = ns_omapi_listen(listener);
if (result == ISC_R_SUCCESS) {
isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
NS_LOGMODULE_OMAPI, ISC_LOG_NOTICE,
"command channel listening on %s", socktext);
*listenerp = listener;
} else {
if (listener != NULL)
free_listener(listener);
cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
"couldn't add command channel %s: %s",
socktext, isc_result_totext(result));
*listenerp = NULL;
}
/* XXXDCL return error results? fail hard? */
}
isc_result_t
ns_omapi_configure(isc_mem_t *mctx, cfg_obj_t *config,
ns_aclconfctx_t *aclconfctx)
{
ns_omapilistener_t *listener;
ns_omapilistenerlist_t new_listeners;
cfg_obj_t *controlslist = NULL;
cfg_obj_t *keylist = NULL;
cfg_listelt_t *element, *element2;
char socktext[ISC_SOCKADDR_FORMATSIZE];
RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
ISC_LIST_INIT(new_listeners);
/*
* Get te list of named.conf 'controls' statements.
*/
(void)cfg_map_get(config, "controls", &controlslist);
LOCK(&listeners_lock);
/*
* Run through the new control channel list, noting sockets that
* are already being listened on and moving them to the new list.
*
* Identifying duplicates addr/port combinations is left to either
* the underlying config code, or to the bind attempt getting an
* address-in-use error.
*/
if (controlslist != NULL) {
(void)cfg_map_get(config, "key", &keylist);
if (keylist == NULL)
cfg_obj_log(controlslist, ns_g_lctx, ISC_LOG_WARNING,
"no key statements for use by "
"control channels");
for (element = cfg_list_first(controlslist);
element != NULL;
element = cfg_list_next(element))
{
cfg_obj_t *controls;
cfg_obj_t *inetcontrols = NULL;
controls = cfg_listelt_value(element);
(void)cfg_map_get(controls, "inet", &inetcontrols);
if (inetcontrols == NULL)
continue;
for (element2 = cfg_list_first(inetcontrols);
element2 != NULL;
element2 = cfg_list_next(element2))
{
cfg_obj_t *control;
cfg_obj_t *obj;
isc_sockaddr_t *addr;
/*
* The parser handles BIND 8 configuration file
* syntax, so it allows unix phrases as well
* inet phrases with no keys{} clause.
*
* "unix" phrases have been reported as
* unsupported by the parser.
*
* The keylist == NULL case was already warned
* about a few lines above.
*/
control = cfg_listelt_value(element2);
obj = cfg_tuple_get(control, "address");
addr = cfg_obj_assockaddr(obj);
if (isc_sockaddr_getport(addr) == 0)
isc_sockaddr_setport(addr,
NS_OMAPI_PORT);
isc_sockaddr_format(addr, socktext,
sizeof(socktext));
obj = cfg_tuple_get(control, "keys");
if (cfg_obj_isvoid(obj)) {
cfg_obj_log(obj, ns_g_lctx,
ISC_LOG_ERROR,
"no keys clause in "
"control channel %s",
socktext);
continue;
}
if (cfg_list_first(obj) == NULL) {
cfg_obj_log(obj, ns_g_lctx,
ISC_LOG_ERROR,
"no keys specified in "
"control channel %s",
socktext);
continue;
}
if (keylist == NULL)
continue;
isc_log_write(ns_g_lctx,
ISC_LOGCATEGORY_GENERAL,
NS_LOGMODULE_OMAPI,
ISC_LOG_DEBUG(9),
"processing control channel %s",
socktext);
register_keys(control, keylist, socktext);
update_listener(&listener, control, config,
addr, aclconfctx, socktext);
if (listener != NULL)
/*
* Remove the listener from the old
* list, so it won't be shut down.
*/
ISC_LIST_UNLINK(listeners, listener,
link);
else
/*
* This is a new listener.
*/
add_listener(mctx, &listener, control,
config, addr, aclconfctx,
socktext);
if (listener != NULL)
ISC_LIST_APPEND(new_listeners,
listener, link);
}
}
}
/*
* ns_omapi_shutdown() will stop whatever is on the global listeners
* list, which currently only has whatever sockaddr was in the previous
* configuration (if any) that does not remain in the current
* configuration.
*/
ns_omapi_shutdown(ISC_FALSE);
/*
* Put all of the valid listeners on the listeners list.
* Anything already on listeners in the process of shutting down
* will be taken care of by listen_done().
*/
ISC_LIST_APPENDLIST(listeners, new_listeners, link);
UNLOCK(&listeners_lock);
return (ISC_R_SUCCESS);
}

View File

@ -13,7 +13,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: Makefile.in,v 1.111 2001/03/13 02:47:15 bwelling Exp $
# $Id: Makefile.in,v 1.112 2001/03/27 00:53:16 bwelling Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@ -30,13 +30,11 @@ CWARNINGS =
DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_OPENSSL_LIBS@ @DNS_GSSAPI_LIBS@
ISCLIBS = ../../lib/isc/libisc.@A@
ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
OMAPILIBS = ../../lib/omapi/libomapi.@A@
LWRESLIBS = ../../lib/lwres/liblwres.@A@
DNSDEPLIBS = ../../lib/dns/libdns.@A@
ISCDEPLIBS = ../../lib/isc/libisc.@A@
ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
OMAPIDEPLIBS = ../../lib/omapi/libomapi.@A@
LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
LIBS = @LIBS@
@ -70,7 +68,6 @@ XTARGETS = adb_test \
mempool_test \
name_test \
nxtify \
omapi_test \
ratelimiter_test \
rbt_test \
rdata_test \
@ -109,7 +106,6 @@ SRCS = adb_test.c \
mempool_test.c \
name_test.c \
nxtify.c \
omapi_test.c \
printmsg.c \
ratelimiter_test.c \
rbt_test.c \
@ -164,10 +160,6 @@ name_test: name_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
${LIBTOOL} ${PURIFY} ${CC} ${CFLAGS} -o $@ name_test.@O@ \
${DNSLIBS} ${ISCLIBS} ${LIBS}
omapi_test: omapi_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${OMAPIDEPLIBS}
${LIBTOOL} ${PURIFY} ${CC} ${CFLAGS} -o $@ omapi_test.@O@ \
${OMAPILIBS} ${DNSLIBS} ${ISCLIBS} ${LIBS}
hash_test: hash_test.@O@ ${ISCDEPLIBS}
${LIBTOOL} ${PURIFY} ${CC} ${CFLAGS} -o $@ hash_test.@O@ \
${ISCLIBS} ${LIBS}

View File

@ -1,759 +0,0 @@
/*
* Copyright (C) 1996-2001 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.
*/
/* $Id: omapi_test.c,v 1.29 2001/02/16 01:00:42 bwelling Exp $ */
/*
* Test code for OMAPI.
*/
#include <config.h>
#include <stdlib.h>
#include <isc/commandline.h>
#include <isc/condition.h>
#include <isc/entropy.h>
#include <isc/mem.h>
#include <isc/socket.h>
#include <isc/string.h>
#include <isc/task.h>
#include <isc/util.h>
#include <dns/acl.h>
#include <dst/dst.h>
#include <dst/result.h>
#include <omapi/omapi.h>
char *progname;
isc_mem_t *mctx;
isc_boolean_t error_noobject = ISC_FALSE;
isc_boolean_t error_nosig = ISC_FALSE;
isc_boolean_t error_badsig = ISC_FALSE;
isc_boolean_t error_unknownsig = ISC_FALSE;
isc_boolean_t error_denyall = ISC_FALSE;
/*
* Two different structures are used in this program to store the
* value of interest on both the client and the server, but the
* same structure can be used on each if desired (with the other variables
* that are not in common between them being stored elsewhere).
*/
typedef struct server_object {
OMAPI_OBJECT_PREAMBLE;
unsigned long value;
isc_boolean_t target_reached;
} server_object_t;
typedef struct client_object {
OMAPI_OBJECT_PREAMBLE;
unsigned long value;
} client_object_t;
static server_object_t master_data;
static omapi_objecttype_t *server_type;
static omapi_objecttype_t *client_type;
static isc_condition_t waiter;
static isc_mutex_t mutex;
/*
* This is a string that names the registry of objects of type server_object_t.
*/
#define SERVER_OBJECT_TYPE "test-data"
/*
* This is the name of the variable that is being manipulated in the server.
* Note that it necessarily has no direct relevance to the *real* name of
* the variable (but of course, making them the same would make for clearer
* programming).
*/
#define MASTER_VALUE "amount"
#define KEY1_NAME "test-key"
#define KEY2_NAME "another-key"
/*
* Create an OMAPI message on the client that requests an object on the
* server be opened. If the boolean 'update' is given, then the value
* of the client's object will set the value of the server's object,
* otherwise the server just refreshes the values in the client's object
* with the master data.
*/
static isc_result_t
open_object(omapi_object_t *handle, omapi_object_t *manager,
isc_boolean_t update)
{
omapi_object_t *message = NULL;
REQUIRE(handle->type == client_type);
/*
* Create a new message object to store the information that will
* be sent to the server.
*/
RUNTIME_CHECK(omapi_message_create(&message) == ISC_R_SUCCESS);
/*
* Specify the OPEN operation, and the UPDATE option if requested.
*/
RUNTIME_CHECK(omapi_object_setinteger(message, "op", OMAPI_OP_OPEN)
== ISC_R_SUCCESS);
if (update)
RUNTIME_CHECK(omapi_object_setboolean(message, "update",
ISC_TRUE)
== ISC_R_SUCCESS);
/*
* Tell the server the type of the object being opened; it needs
* to know this so that it can apply the proper object methods
* for lookup/setvalue.
*/
RUNTIME_CHECK(omapi_object_setstring(message, "type",
SERVER_OBJECT_TYPE)
== ISC_R_SUCCESS);
/*
* Associate the client object with the message, so that it
* will have its values stuffed in the message. Without it,
* the OPEN operation will fail because there is no name/value
* pair to use as a key for looking up the desired object at
* the server.
*/
if (! error_noobject)
RUNTIME_CHECK(omapi_object_setobject(message, "object", handle)
== ISC_R_SUCCESS);
/*
* Set up an object that will receive the "status" signal in its
* signal handler when the response is received from the server.
* This is not needed as a general rule, because normally the
* the object associated with the name "object" in the message
* is what gets that message. However, in this case the
* particular error that is being tested when error_noobject is true
* is one where no item named "object" has been set, so not only
* can it not be used as a key when the server gets the message,
* it can't be used to get the "status" signal on the client
* when the server's "no key" error message comes back.
*
* If both "object" and "notify-object" are set, only the latter
* will receive the signal (as currently written; it was originally
* the other way 'round). In this particular case it hardly matters,
* as both "object" and "notify-object" are the same object.
*/
RUNTIME_CHECK(omapi_object_setobject(message, "notify-object", handle)
== ISC_R_SUCCESS);
/*
* Add the new message to the list of known messages. When the
* server's response comes back, the client will verify that
* the response was for a message it really sent.
*/
omapi_message_register(message);
/*
* Deliver the message to the server. The manager's outer object
* is the connection object to the server.
*/
RUNTIME_CHECK(omapi_message_send(message, manager) == ISC_R_SUCCESS);
/*
* Free the message.
*/
omapi_message_unregister(message);
omapi_object_dereference(&message);
return (ISC_R_SUCCESS);
}
/*
* client_setvalue() is called on the client by the library's internal
* message_process() function when the server replies to the OPEN operation
* with its own REFRESH message for the client. It is how the client learns
* what data is on the server.
*/
static isc_result_t
client_setvalue(omapi_object_t *handle, omapi_string_t *name,
omapi_data_t *value)
{
isc_region_t region;
client_object_t *client;
REQUIRE(handle->type == client_type);
client = (client_object_t *)handle;
/*
* Only the MASTER_VALUE value has meaning in this program.
*/
if (omapi_string_strcmp(name, MASTER_VALUE) == 0) {
client->value = omapi_data_getint(value);
return (ISC_R_SUCCESS);
} else if (omapi_string_strcmp(name, "remote-handle") == 0) {
/*
* The server will also set "remote-handle" to let the client
* have an identifier for the object on the server that could
* be used with the other OMAPI operations, such as
* OMAPI_OP_DELETE. The value of remote-handle is an integer,
* fetched with:
* omapi_data_getint(&remote_handle, value).
*
* It is not used by this test program.
*/
return (ISC_R_SUCCESS);
}
omapi_string_totext(name, &region);
fprintf(stderr, "client_setvalue: unknown name: '%.*s'\n",
(int)region.length, region.base);
return (ISC_R_NOTFOUND);
}
/*
* This function is used by omapi_message_send to publish the values of
* the data in a client object.
*/
static isc_result_t
client_stuffvalues(omapi_object_t *connection, omapi_object_t *handle) {
client_object_t *client;
REQUIRE(handle->type == client_type);
client = (client_object_t *)handle;
/*
* Write the MASTER_VALUE name, followed by the value length,
* follwed by its value.
*/
RUNTIME_CHECK(omapi_connection_putname(connection, MASTER_VALUE)
== ISC_R_SUCCESS);
RUNTIME_CHECK(omapi_connection_putuint32(connection,
sizeof(isc_uint32_t))
== ISC_R_SUCCESS);
RUNTIME_CHECK(omapi_connection_putuint32(connection, client->value)
== ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
}
static isc_result_t
client_signalhandler(omapi_object_t *handle, const char *name, va_list ap) {
client_object_t *client;
omapi_value_t *tv;
isc_region_t region;
isc_boolean_t expected;
REQUIRE(handle->type == client_type);
client = (client_object_t *)handle;
if (strcmp(name, "updated") == 0) {
client->waitresult = ISC_R_SUCCESS;
} else if (strcmp(name, "status") == 0) {
/*
* "status" is signalled with the result of the message's
* operation.
*/
client->waitresult = va_arg(ap, isc_result_t);
expected = ISC_TF((error_noobject &&
client->waitresult == ISC_R_NOTFOUND) ||
(error_nosig &&
client->waitresult == ISC_R_NOPERM) ||
(error_badsig &&
client->waitresult == DST_R_VERIFYFAILURE));
if (client->waitresult != ISC_R_SUCCESS)
fprintf(stderr, "%s: message status: %s (%s)\n",
progname,
isc_result_totext(client->waitresult),
expected ? "expected" : "UNEXPECTED");
tv = va_arg(ap, omapi_value_t *);
if (tv != NULL) {
omapi_value_getregion(tv, &region);
fprintf(stderr, "%s: additional text provided: %.*s\n",
progname, (int)region.length, region.base);
}
} else {
/*
* Pass any unknown signal any internal object.
* (This normally does not happen; there is no
* inner object, nor anything else being signalled.)
*/
fprintf(stderr, "%s: client_signalhandler: unknown signal: %s",
progname, name);
return (omapi_object_passsignal(handle, name, ap));
}
return (ISC_R_SUCCESS);
}
/*
* This is the function that is called when an incoming OMAPI_OP_OPEN
* message is received with either the create or update option set.
* It is called once for each name/value pair in the message's object
* value list.
*
* (Primary caller: message_process())
*/
static isc_result_t
server_setvalue(omapi_object_t *handle, omapi_string_t *name,
omapi_data_t *value)
{
isc_region_t region;
RUNTIME_CHECK(handle == (omapi_object_t *)&master_data);
/*
* Only one name is supported for this object, MASTER_VALUE.
*/
if (omapi_string_strcmp(name, MASTER_VALUE) == 0) {
fprintf(stderr, "existing value: %lu\n", master_data.value);
master_data.value = omapi_data_getint(value);
fprintf(stderr, "new value: %lu\n", master_data.value);
/*
* 32 is an arbitrary disconnect point.
*/
if (master_data.value >= 32) {
master_data.target_reached = ISC_TRUE;
SIGNAL(&waiter);
}
return (ISC_R_SUCCESS);
}
omapi_string_totext(name, &region);
fprintf(stderr, "server_setvalue: unknown name: '%.*s'\n",
(int)region.length, region.base);
return (ISC_R_NOTFOUND);
}
/*
* This is the function that is called by the library's internal
* message_process() function when an incoming OMAPI_OP_OPEN
* message is received. It is normally supposed to look up the object
* in the server that corresponds to the key data (name/value pair(s))
* in 'ref'.
*/
static isc_result_t
server_lookup(omapi_object_t **server_object, omapi_object_t *key) {
/*
* For this test program, there is only one static structure
* which is being used, so key is not needed.
*/
UNUSED(key);
omapi_object_reference(server_object, (omapi_object_t *)&master_data);
return (ISC_R_SUCCESS);
}
/*
* This function is called when the server is sending a reply to a client
* that opened an object of its type. It needs to output all published
* name/value pairs for the object, and will typically also put the data
* for any inner objects (but in this program, there will be no inner
* objects).
*/
static isc_result_t
server_stuffvalues(omapi_object_t *connection, omapi_object_t *handle) {
server_object_t *master = (server_object_t *)handle;
/*
* Write the MASTER_VALUE name, followed by the value length,
* follwed by its value.
*/
RUNTIME_CHECK(omapi_connection_putname(connection, MASTER_VALUE)
== ISC_R_SUCCESS);
RUNTIME_CHECK(omapi_connection_putuint32(connection,
sizeof(isc_uint32_t))
== ISC_R_SUCCESS);
RUNTIME_CHECK(omapi_connection_putuint32(connection, master->value)
== ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
}
static void
do_connect(const char *host, int port) {
omapi_object_t *manager;
omapi_object_t *omapi_client = NULL;
client_object_t *client = NULL;
isc_result_t result;
const char *key;
const char *bad_secret1 = "this secret is wrong";
const char *bad_secret2 = "Yet Another Secret";
RUNTIME_CHECK(omapi_object_register(&client_type, "client",
client_setvalue,
NULL, /* getvalue */
NULL, /* destroy */
client_signalhandler,
client_stuffvalues,
NULL, /* lookup */
NULL, /* create */
NULL) /* remove */
== ISC_R_SUCCESS);
/*
* Create the top level object which will manage the
* connection to the server.
*/
manager = NULL;
RUNTIME_CHECK(omapi_object_create(&manager, NULL, 0)
== ISC_R_SUCCESS);
result = omapi_protocol_connect(manager, host, port, NULL);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "%s: omapi_protocol_connect: %s\n",
progname, isc_result_totext(result));
omapi_object_dereference(&manager);
return;
}
/*
* Authenticate to the server.
*/
key = KEY1_NAME;
if (error_badsig) {
omapi_auth_deregister(KEY1_NAME);
RUNTIME_CHECK(omapi_auth_register(KEY1_NAME,
OMAPI_AUTH_HMACMD5,
bad_secret1,
strlen(bad_secret1))
== ISC_R_SUCCESS);
} else if (error_unknownsig) {
RUNTIME_CHECK(omapi_auth_register(KEY2_NAME,
OMAPI_AUTH_HMACMD5,
bad_secret2,
strlen(bad_secret2))
== ISC_R_SUCCESS);
key = KEY2_NAME;
}
if (! error_nosig) {
result = omapi_auth_use(manager, key, OMAPI_AUTH_HMACMD5);
if (result != ISC_R_SUCCESS)
fprintf(stderr, "%s: omapi_auth_use: %s (%s)\n",
progname, isc_result_totext(result),
(error_unknownsig && result == ISC_R_NOTFOUND)
? "expected" : "UNEXPECTED");
}
if (result == ISC_R_SUCCESS) {
/*
* Create the client's object.
*/
omapi_object_create((omapi_object_t **)&client, client_type,
sizeof(client_object_t));
omapi_client = (omapi_object_t *)client;
/*
* The object needs to have a name/value pair created for it
* even before it contacts the server so the server will know
* that there is an object that needs values filled in. This
* name/value is created with the value of 0, but any interger
* value would work.
*/
RUNTIME_CHECK(omapi_object_setinteger(omapi_client,
MASTER_VALUE, 0)
== ISC_R_SUCCESS);
RUNTIME_CHECK(open_object(omapi_client, manager, ISC_FALSE)
== ISC_R_SUCCESS);
if (client->waitresult == ISC_R_SUCCESS) {
/*
* Set the new value to be stored at the server and
* reopen the server object with an UPDATE operation.
*/
fprintf(stderr, "existing value: %lu\n",
client->value);
client->value *= 2;
if (client->value == 0) /* Check overflow. */
client->value = 1;
fprintf(stderr, "new value: %lu\n", client->value);
RUNTIME_CHECK(open_object(omapi_client, manager,
ISC_TRUE)
== ISC_R_SUCCESS);
RUNTIME_CHECK(client->waitresult == ISC_R_SUCCESS);
}
}
/*
* Close the connection and wait to be disconnected.
*/
omapi_protocol_disconnect(manager, OMAPI_CLEAN_DISCONNECT);
/*
* Free the protocol manager and client object.
*/
omapi_object_dereference(&manager);
if (omapi_client != NULL)
omapi_object_dereference(&omapi_client);
}
static void
listen_done(isc_task_t *task, isc_event_t *event) {
omapi_object_t *listener = event->ev_arg;
UNUSED(task);
fprintf(stderr, "SERVER STOPPED\n");
isc_event_free(&event);
omapi_object_dereference(&listener);
omapi_lib_destroy();
}
static isc_boolean_t
verify_connection(isc_sockaddr_t *sockaddr, void *arg) {
/* XXXDCL test the connection verification code */
UNUSED(sockaddr);
UNUSED(arg);
return (ISC_TRUE);
}
static isc_boolean_t
verify_key(const char *name, unsigned int algorithm, void *arg) {
/* XXXDCL test the key verification code */
UNUSED(name);
UNUSED(algorithm);
UNUSED(arg);
return (ISC_TRUE);
}
static void
do_listen(int port) {
omapi_object_t *listener = NULL;
isc_sockaddr_t sockaddr;
struct in_addr inaddr;
dns_acl_t *acl;
/*
* Create the manager for handling incoming server connections.
*/
RUNTIME_CHECK(omapi_object_create(&listener, NULL, 0)
== ISC_R_SUCCESS);
/*
* Register the server_object. The SERVER_OBJECT_TYPE is what
* a client would need to specify as a value for the name "type"
* when contacting the server in order to be able to find objects
* server_type.
*/
RUNTIME_CHECK(omapi_object_register(&server_type, SERVER_OBJECT_TYPE,
server_setvalue,
NULL, /* getvalue */
NULL, /* destroy */
NULL, /* signalhandler */
server_stuffvalues,
server_lookup,
NULL, /* create */
NULL) /* remove */
== ISC_R_SUCCESS);
/*
* Initialize the server_object data.
*/
master_data.type = server_type;
master_data.refcnt = 1;
master_data.value = 2;
master_data.target_reached = ISC_FALSE;
LOCK(&mutex);
/*
* Set the access control list for valid connections.
*/
if (error_denyall)
RUNTIME_CHECK(dns_acl_none(mctx, &acl) == ISC_R_SUCCESS);
else
RUNTIME_CHECK(dns_acl_any(mctx, &acl) == ISC_R_SUCCESS);
/*
* Start listening for connections.
*/
inaddr.s_addr = INADDR_ANY;
isc_sockaddr_fromin(&sockaddr, &inaddr, port);
RUNTIME_CHECK(omapi_protocol_listen(listener, &sockaddr,
verify_connection, verify_key,
listen_done, listener)
== ISC_R_SUCCESS);
fprintf(stderr, "SERVER STARTED\n");
/*
* Lose one reference to the acl; the omapi library holds another
* reference and should free it when it is done.
*/
dns_acl_detach(&acl);
/*
* Block until done. "Done" is when server_setvalue has reached
* its trigger value.
*/
do {
WAIT(&waiter, &mutex);
} while (! master_data.target_reached);
omapi_listener_shutdown(listener);
}
#undef ARG_IS
#define ARG_IS(s) (strcmp(isc_commandline_argument, (s)) == 0)
int
main(int argc, char **argv) {
isc_boolean_t show_final_mem = ISC_FALSE;
isc_socketmgr_t *socketmgr = NULL;
isc_taskmgr_t *taskmgr = NULL;
isc_entropy_t *entropy = NULL;
const char *secret = "shhh, this is a secret";
int ch;
progname = strrchr(*argv, '/');
if (progname != NULL)
progname++;
else
progname = *argv;
while ((ch = isc_commandline_parse(argc, argv, "e:m")) != -1) {
switch (ch) {
case 'e':
if (ARG_IS("noobject"))
error_noobject = ISC_TRUE;
else if (ARG_IS("nosig"))
error_nosig = ISC_TRUE;
else if (ARG_IS("badsig"))
error_badsig = ISC_TRUE;
else if (ARG_IS("unknownsig"))
error_unknownsig = ISC_TRUE;
else if (ARG_IS("denyall"))
error_denyall = ISC_TRUE;
else {
fprintf(stderr, "Unknown forced error: %s\n",
isc_commandline_argument);
fprintf(stderr, "Valid forced errors: "
"noobject nosig badsig unknownsig\n");
exit(1);
}
break;
case 'm':
show_final_mem = ISC_TRUE;
break;
}
}
argc -= isc_commandline_index;
argv += isc_commandline_index;
RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr)
== ISC_R_SUCCESS);
RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr)
== ISC_R_SUCCESS);
RUNTIME_CHECK(omapi_lib_init(mctx, taskmgr, socketmgr)
== ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mutex_init(&mutex) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_condition_init(&waiter) == ISC_R_SUCCESS);
/*
* Initialize the signature library.
*/
RUNTIME_CHECK(isc_entropy_create(mctx, &entropy) == ISC_R_SUCCESS);
RUNTIME_CHECK(dst_lib_init(mctx, entropy, 0) == ISC_R_SUCCESS);
/*
* The secret key is shared on both the client and server side.
*/
RUNTIME_CHECK(omapi_auth_register(KEY1_NAME, OMAPI_AUTH_HMACMD5,
secret, strlen(secret))
== ISC_R_SUCCESS);
if (argc >= 1 && strcmp(argv[0], "listen") == 0) {
if (argc != 2) {
fprintf(stderr, "Usage: %s listen port\n", progname);
exit (1);
}
do_listen(atoi(argv[1]));
} else if (argc >= 1 && !strcmp (argv[0], "connect")) {
if (argc != 3) {
fprintf(stderr, "Usage: %s connect address port\n",
progname);
exit (1);
}
do_connect(argv[1], atoi(argv[2]));
omapi_lib_destroy();
} else {
fprintf(stderr, "Usage: %s [-m] [listen | connect] ...\n",
progname);
exit (1);
}
isc_socketmgr_destroy(&socketmgr);
isc_taskmgr_destroy(&taskmgr);
dst_lib_destroy();
isc_entropy_detach(&entropy);
if (show_final_mem)
isc_mem_stats(mctx, stderr);
isc_mem_destroy(&mctx);
return (0);
}

View File

@ -18,7 +18,7 @@ AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl
esyscmd([sed "s/^/# /" COPYRIGHT])dnl
AC_DIVERT_POP()dnl
AC_REVISION($Revision: 1.241 $)
AC_REVISION($Revision: 1.242 $)
AC_INIT(lib/dns/name.c)
AC_PREREQ(2.13)
@ -1413,21 +1413,18 @@ AC_SUBST(BIND9_ISC_BUILDINCLUDE)
AC_SUBST(BIND9_ISCCC_BUILDINCLUDE)
AC_SUBST(BIND9_ISCCFG_BUILDINCLUDE)
AC_SUBST(BIND9_DNS_BUILDINCLUDE)
AC_SUBST(BIND9_OMAPI_BUILDINCLUDE)
AC_SUBST(BIND9_LWRES_BUILDINCLUDE)
if test "X$srcdir" != "X"; then
BIND9_ISC_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isc/include"
BIND9_ISCCC_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isccc/include"
BIND9_ISCCFG_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isccfg/include"
BIND9_DNS_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/dns/include"
BIND9_OMAPI_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/omapi/include"
BIND9_LWRES_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/lwres/include"
else
BIND9_ISC_BUILDINCLUDE=""
BIND9_ISCCC_BUILDINCLUDE=""
BIND9_ISCCFG_BUILDINCLUDE=""
BIND9_DNS_BUILDINCLUDE=""
BIND9_OMAPI_BUILDINCLUDE=""
BIND9_LWRES_BUILDINCLUDE=""
fi
@ -1456,9 +1453,6 @@ LIBDNS_API=$srcdir/lib/dns/api
AC_SUBST_FILE(LIBLWRES_API)
LIBLWRES_API=$srcdir/lib/lwres/api
AC_SUBST_FILE(LIBOMAPI_API)
LIBOMAPI_API=$srcdir/lib/omapi/api
AC_OUTPUT(
make/rules
make/includes
@ -1497,9 +1491,6 @@ AC_OUTPUT(
lib/lwres/include/lwres/netdb.h
lib/lwres/include/lwres/platform.h
lib/lwres/man/Makefile
lib/omapi/Makefile
lib/omapi/include/Makefile
lib/omapi/include/omapi/Makefile
lib/tests/Makefile
lib/tests/include/Makefile
lib/tests/include/tests/Makefile

View File

@ -1,447 +0,0 @@
Copyright (C) 1999-2001 Internet Software Consortium.
See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
$Id: omapi,v 1.7 2001/01/09 21:46:48 bwelling Exp $
This file documents the protocol that the ISC DHCP server and ISC
Object Management clients (clients that use the ISC Object Management
API) speak between one another.
Protocol:
All multi-byte numbers are represented in network byte order.
On startup, each side sends a status message indicating what version
of the protocol they are speaking. The status message looks like
this:
+---------+---------+
| version | hlength |
+---------+---------+
version - a 32-bit fixed-point number with the decimal point between
the third and second decimal digits from the left,
representing the version of the protocol. The current
protocol version is 1.00. If the field were considered as
a 32-bit integer, this would correspond to a value of 100
decimal, or 0x64.
hlength - a 32-bit integer representing the length of the fixed-length
header in subsequent messages. This is normally 56, but
can be changed to a value larger than 56 by either side
without upgrading the revision number.
The startup message is not authenticated. Either side may reject the
other side's startup message as invalid by simply closing the
connection. The only fixed part of the startup message is the
version number - future versions may delete hlength, or add further
startup information.
Following the startup message, all messages have the same format.
Currently, the format includes a fixed-length header (the length in
hlength, above)
+--------+----+--------+----+-----+---------+------------+------------+-----+
| authid | op | handle | id | rid | authlen | msg values | obj values | sig |
+--------+----+--------+----+-----+---------+------------+------------+-----+
The fixed-length header consists of:
authid = a 32-bit authenticator handle.
For an original message (one not in response to some other
message), this will be chosen by the originator. For a
message in response to another message, the authenticator for
that message is used, except if the response is an error
message indicating that the authenticator used was unknown,
in which case the null authenticator is used. Messages that
are generated as the result of a notify registration use the
authenticator used in the original notify registration.
The authenticator itself is generated by having one side of
the connection send an object of type "authenticator" to the
other side with values that indicate what kind of
authentication mechanism to use and what key to use. The two
most likely things here are a Kerberos V principal name or the
name of a shared secret that can be used to calculate an MD5
hash. The mechanism for doing this has yet to be finalized.
If authid is zero, the message is not authenticated.
[[
This is not consistent with what the code does (as originally written),
which is read a header that has, in order:
authid, authlen, op, handle, id, rid
]]
op = 32-bit opcode, one of:
open = 1
refresh = 2
update = 3
notify = 4
error = 5
delete = 6
handle = 32-bit object handle
A handle on the object being opened, created, refreshed or
updated. If no handle is yet available (e.g., with open and
new), then the value zero is sent.
id = 32-bit transaction id of the message - a monotonically increasing
number that starts with some randomly chosen number at the
beginning of the life of the connection. The value should never
be zero.
rid = 32-bit transaction ID of the message to which this message is a
response, or zero if this message is not in response to a
message from the other side.
authlen = a 32-bit number representing the length of the authenticator
msg values = a series of name+value pairs, specific to this message.
Each name+value pair starts with a 16-bit name length,
followed by that many bytes of name, followed by a 32-bit
value length, followed by that many bytes of value. If the
length is zero, this is a value of the blank string. If the
length is all ones (2^32-1), then there is no value - for an
update, this means the value for this name and the name
itself should be deleted from the object, which may or may
not be possible. The list of name/value pairs ends with a
zero-length name, which is not followed by a value
length/value pair.
obj values = a series of name+value pairs, as above, specific to the
object being created, updated or refreshed.
signature = authlen bytes of data signing the message. The signature
algorithm is a property of the authenticator handle.
Message types:
1: open
relevant input values:
object-type = the name of the type of object
open:create = boolean - create the object if it doesn't yet exist
open:exclusive = boolean - don't open the object if it does exist
open:update = boolean - update the object with included values
if it matches.
the handle should always be the null handle
The input value must also contain key information for the type of
object being searched that uniquely identifies an object, or search
information that matches only one object. Each object has a key
specification (a key is something that uniquely identifies an
object), so see the key specification for that object to see
what to send here. An open message with the create flag set must
specify a key, and not merely matching criteria. Some objects may
allow more than one key, and it may be that the union of those keys
is required to uniquely identify the object, or it may be that any
one such key will uniquely identify the object. The documentation
for the type of object will specify this.
An open message will result in an immediate response message whose
opcode will either be "error" or "update". The error message may
include an error:reason value containing a text string explaining
the error, and will always include an error:code value which will
be the numeric error code for what went wrong. Possible error
codes are:
not found - no such object exists
already exists - object already exists, and exclusive flag was
set.
not unique - more than one object matching the specification
exists.
permission denied - the authenticator ID specified does not
have authorization to access this object,
or if the update flag was specified, to
update the object.
If the response is an update message, the update message will
include the object handle and all of the name/value pairs
associated with that object.
2: refresh
no input values except the handle need be specified. The null
handle may not be specified. If the handle is valid, and the
authenticator ID specified has permission to examine the object,
then an update message will be sent for that object. Otherwise,
one of the following errors will be sent:
invalid handle - the handle does not refer to a known object
permisson denied - the handle refers to an object that the
requestor does not have permission to
examine.
3: update
Requests that the contents of the specified object be updated with
the values included. Values that are not specified are not
updated. The response will be either an error message or an
update-ok message. If rid is nonzero, no response will be
generated, even if there was an error. Possible errors include:
invalid handle - no such object was found
permission denied - the handle refers to an object that the
requestor does not have permission to
modify.
not confirmed - the update could not be committed due to some
kind of resource problem, for example
insufficient memory or a disk failure.
4: notify
Requests that whenever the object with the specified handle is
modified, an update be sent. If there is something wrong with the
request, an error message will be returned immediately.
Otherwise, whenever a change is made to the object, an update
message will be sent containing whatever changes were made (or
possibly all the values associated with the object, depending on
the implementation). Possible errors:
invalid handle
permission denied - the handle refers to an object that the
requestor does not have permission to
examine.
not supported - the object implementation does not support
notifications
5: status
Sends a status code in response to a message. Always sent in
response to a message sent by the other side. There should never
be a response to this message.
6: delete
Deletes the specified object. Response will be either request-ok,
or error. Possible errors include:
invalid handle - no such object was found
permission denied - the handle refers to an object that the
requestor does not have permission to
modify.
not confirmed - the deletion could not be committed due to
some kind of resource problem, for example
insufficient memory or a disk failure.
7: notify-cancel
Like notify, but requests that an existing notification be cancelled.
8: notify-cancelled
Indicates that because of a local change, a notification that had
been registered can no longer be performed. This could be as a
result of the permissions on a object changing, or an object being
deleted. There should never be a response to this message.
internals:
Both client and server use same protocol and infrastructure. There
are many object types, each of which is stored in a registry.
Objects whose type is not recognized can either be handled by the
generic object type, which is registered with the type "*". If no
generic object type is registered, then objects with unknown types are
simply not supported. On the client, there are probably no special
object handlers (although this is by no means forbidden). On the
server, probably everything is a special object.
Each object type has the following methods:
dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection,
char *server_name, int port,
dhcpctl_handle *authinfo)
synchronous
returns nonzero status code if it didn't connect, zero otherwise
stores connection handle through connection, which can be used
for subsequent access to the specified server.
server_name is the name of the server, and port is the TCP
port on which it is listening.
authinfo is the handle to an object containing authentication
information.
dhcpctl_status dhcpctl_open_object (dhcpctl_handle h,
dhcpctl_handle connection,
int flags)
asynchronous - just queues the request
returns nonzero status code if open couldn't be queued
returns zero if open was queued
h is a handle to an object created by dhcpctl_new_object
connection is a connection to a DHCP server
flags include:
DHCPCTL_CREATE - if the object doesn't exist, create it
DHCPCTL_UPDATE - update the object on the server using the
attached parameters
DHCPCTL_EXCL - error if the object exists and DHCPCTL_CREATE
was also specified
dhcpctl_status dhcpctl_new_object (dhcpctl_handle *h,
dhcpctl_handle connection,
char *object_type)
synchronous - creates a local handle for a host entry.
returns nonzero status code if the local host entry couldn't
be created
stores handle to host through h if successful, and returns zero.
object_type is a pointer to a NUL-terminated string containing
the ascii name of the type of object being accessed - e.g., "host"
dhcpctl_status dhcpctl_set_callback (dhcpctl_handle h, void *data,
void (*callback) (dhcpctl_handle,
dhcpctl_status, void *))
synchronous, with asynchronous aftereffect
handle is some object upon which some kind of process has been
started - e.g., an open, an update or a refresh.
data is an anonymous pointer containing some information that
the callback will use to figure out what event completed.
return value of 0 means callback was successfully set, a nonzero
status code is returned otherwise.
Upon completion of whatever task is in process, the callback
will be passed the handle to the object, a status code
indicating what happened, and the anonymous pointer passed to
dhcpctl_status dhcpctl_wait_for_completion (dhcpctl_handle h,
dhcpctl_status *s)
synchronous
returns zero if the callback completes, a nonzero status if
there was some problem relating to the wait operation. The
status of the queued request will be stored through s, and
will also be either zero for success or nonzero for some kind
of failure. Never returns until completion or until the
connection to the server is lost. This performs the same
function as dhcpctl_set_callback and the subsequent callback,
for programs that want to do inline execution instead of using
callbacks.
dhcpctl_status dhcpctl_get_value (data_string *result,
dhcpctl_handle h, char *value_name)
synchronous
returns zero if the call succeeded, a nonzero status code if
it didn't.
result is the address of an empty data string (initialized
with bzero or cleared with data_string_forget). On
successful completion, the addressed data string will contain
the value that was fetched.
dhcpctl_handle refers to some dhcpctl item
value_name refers to some value related to that item - e.g.,
for a handle associated with a completed host lookup, value
could be one of "hardware-address", "dhcp-client-identifier",
"known" or "client-hostname".
dhcpctl_status dhcpctl_get_boolean (int *result,
dhcpctl_handle h, char *value_name)
like dhcpctl_get_value, but more convenient for boolean
values, since no data_string needs to be dealt with.
dhcpctl_status dhcpctl_set_value (dhcpctl_handle h, data_string value,
char *value_name)
Sets a value on an object referred to by a dhcpctl_handle.
The opposite of dhcpctl_get_value. Does not update the
server - just sets the value on the handle.
dhcpctl_status dhcpctl_set_string_value (dhcpctl_handle h, char *value,
char *value_name)
Sets a NUL-terminated ASCII value on an object referred to by
a dhcpctl_handle. like dhcpctl_set_value, but saves the
trouble of creating a data_string for a NUL-terminated string.
Does not update the server - just sets the value on the handle.
dhcpctl_status dhcpctl_set_boolean (dhcpctl_handle h, int value,
char *value_name)
Sets a boolean value on an object - like dhcpctl_set_value,
only more convenient for booleans.
dhcpctl_status dhcpctl_object_update (dhcpctl_handle h)
Queues an update on the object referenced by the handle (there
can't be any other work in progress on the handle). An
update means local parameters will be sent to the server.
dhcpctl_status dhcpctl_object_refresh (dhcpctl_handle h)
Queues an update on the object referenced by the handle (there
can't be any other work in progress on the handle). An
update means local parameters will be sent to the server.
dhcpctl_status dhcpctl_object_delete (dhcpctl_handle h)
Queues a delete of the object referenced by the handle (there
can't be any other work in progress on the handle). A
delete means that the object will be permanently deleted on
the remote end, assuming the remote end supports object
persistence.
So a sample program that would update a host declaration would look
something like this:
/* Create a local object into which to store authentication
information. */
if ((status = dhcpctl_new_object (&auth, dhcpctl_null_handle,
"authentication-information")))
dhcpctl_error ("Can't create authentication information: %m");
/* Set up the authenticator with an algorithm type, user name and
password. */
if ((status = dhcpctl_set_string_value (&auth, "mellon", "username")))
dhcpctl_error ("Can't set username: %m", status);
if ((status = dhcpctl_set_string_value (&auth, "three blind mice",
"password")))
dhcpctl_error ("Can't set password: %m", status);
if ((status = dhcpctl_set_string_value (&auth, "md5-hash",
"algorithm")))
dhcpctl_error ("Can't set authentication algorithm: %m.",
status);
/* Connect to the server. */
if ((status = dhcpctl_connect (&c, "dhcp.server.com", 612, &auth)))
dhcpctl_error ("Can't connect to dhcp.server.com: %m",
status);
/* Create a host object. */
if ((status = dhcpctl_new_object (&hp, c, "host")))
dhcpctl_error ("Host create failed: %m", status);
/* Create a data_string to contain the host's client
identifier, and set it. */
if ((status =
data_string_create_from_hex (&client_id,
"1:08:00:2b:34:1a:c3")))
dhcpctl_error ("Can't create client identifier: %m");
if ((status = dhcpctl_set_value (hp, client_id,
"dhcp-client-identifier")))
dhcpctl_error ("Host client identifier set failed.");
/* Set the known flag to 1. */
if ((status = dhcpctl_set_boolean (hp, 1, "known")))
dhcpctl_error ("Host known set failed.");
/* Open an existing host object that matches the client identifier,
and update it from the local context, or if no host entry
yet exists matching the identifier, create one and
initialize it. */
if ((status = dhcpctl_open_object (&hp, c,
DHCPCTL_CREATE | DHCPCTL_UPDATE)))
dhcpctl_error ("Can't open host: %m", status);
/* Wait for the process to complete, check status. */
if ((status = dhcpctl_wait_for_completion (hp, &wait_status)))
dhcpctl_error ("Host create/lookup wait failed: %m", status);
if (waitstatus)
dhcpctl_error ("Host create/lookup failed: %m", status);
The API is a bit complicated, for a couple of reasons. I want to
make it general, so that there aren't a bazillion functions to call,
one for each data type. I want it to be thread-safe, which is why
each function returns a status and the error printer requires a status
code for input. I want it to be possible to make it asynchronous, so
that it can work in tandem with, for example, an X toolkit. If
you're just writing a simple update cgi program, you probably won't
want to bother to use the asynchronous callbacks, and indeed the above
example doesn't.
I glossed over data strings above - basically, they're objects with a
pointer to a reference-counted buffer structure, an offset into that
buffer, and a length. These are used within the DHCP server, so you
can get an idea of how they work - basically, they're a convenient and
efficient way to store a string with a length such that substrings can
easily be taken and such that more than one user at a time can have a
pointer to the string.
I will also probably add locking primitives, so that you can get the
value of something and be sure that some other updator process won't
modify it while you have the lock.

View File

@ -1,7 +1,7 @@
Copyright (C) 2000, 2001 Internet Software Consortium.
See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
$Id: roadmap,v 1.2 2001/01/09 21:47:05 bwelling Exp $
$Id: roadmap,v 1.3 2001/03/27 00:53:20 bwelling Exp $
Road Map to the BIND 9 Source Tree
@ -27,7 +27,7 @@ lib/dns/sec Cryptographic libraries for DNSSEC
lib/isc The ISC library
task.c Task library
unix/socket.c Unix implementation of socket library
lib/omapi The OMAPI remote object access library, used by rndc.
lib/isccc The command channel library, used by rndc.
lib/tests Support code for the test suites.
lib/lwres The lightweight resolver library.
doc/draft Current internet-drafts pertaining to the DNS

View File

@ -13,13 +13,13 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: Makefile.in,v 1.14 2001/03/27 00:44:43 bwelling Exp $
# $Id: Makefile.in,v 1.15 2001/03/27 00:53:21 bwelling Exp $
srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
SUBDIRS = isc isccc isccfg dns lwres omapi tests
SUBDIRS = isc isccc isccfg dns lwres tests
TARGETS =
@BIND9_MAKE_RULES@

View File

@ -1,5 +0,0 @@
Makefile
timestamp
.libs
*.la
*.lo

View File

@ -1,80 +0,0 @@
# Copyright (C) 1999-2001 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.
# $Id: Makefile.in,v 1.17 2001/02/15 19:44:40 bwelling Exp $
srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
@BIND9_VERSION@
@LIBOMAPI_API@
@BIND9_INCLUDES@
CINCLUDES = -I./include \
-I${srcdir}/include \
${ISC_INCLUDES}
CDEFINES =
CWARNINGS =
# Alphabetically
OBJS = auth.@O@ connection.@O@ data.@O@ generic.@O@ handle.@O@ \
lib.@O@ listener.@O@ message.@O@ object.@O@ protocol.@O@ \
result.@O@ string.@O@ value.@O@ version.@O@
# Alphabetically
SRCS = auth.c connection.c data.c generic.c handle.c \
lib.c listener.c message.c object.c protocol.c \
result.c string.c value.c version.c
LIBS = @LIBS@
SUBDIRS = include
TARGETS = timestamp
@BIND9_MAKE_RULES@
version.@O@: version.c
${LIBTOOL} ${CC} ${ALL_CFLAGS} \
-DVERSION=\"${VERSION}\" \
-DLIBINTERFACE=${LIBINTERFACE} \
-DLIBREVISION=${LIBREVISION} \
-DLIBAGE=${LIBAGE} \
-c ${srcdir}/version.c
libomapi.@SA@: ${OBJS}
${AR} ${ARFLAGS} $@ ${OBJS}
${RANLIB} $@
libomapi.la: ${OBJS}
${LIBTOOL} --mode=link \
${CC} ${ALL_CFLAGS} -o libomapi.la -rpath ${libdir} \
-version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
${OBJS} ${LIBS}
timestamp: libomapi.@A@
touch timestamp
installdirs:
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir}
install:: timestamp installdirs
${LIBTOOL} ${INSTALL_DATA} libomapi.@A@ ${DESTDIR}${libdir}
clean distclean::
rm -f libomapi.@A@ libomapi.la timestamp

View File

@ -1,3 +0,0 @@
LIBINTERFACE = 3
LIBREVISION = 0
LIBAGE = 0

View File

@ -1,347 +0,0 @@
/*
* Copyright (C) 2000, 2001 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.
*/
/* $Id: auth.c,v 1.21 2001/02/17 00:53:59 bwelling Exp $ */
/* Principal Author: DCL */
/*
* XXXDCL Todo:
* How do keys get specified by named.conf for the control channel?
* Could use the keys in the address_match_list (acl) specified in the
* "controls" statement. All of the keys would need to be at the beginning,
* so the match does not stop at an IP address. The server would register
* all of the keys. Currently, however, there is no way to limit a key
* to a particular listening interface on the server, as the configuration
* file would allow.
*/
/*
* Subroutines for dealing with authorization.
*/
#include <config.h>
#include <isc/buffer.h>
#include <isc/mem.h>
#include <isc/once.h>
#include <isc/string.h>
#include <isc/util.h>
#include <omapi/private.h>
typedef struct auth auth_t;
#define AUTH_MAGIC 0x41555448U /* AUTH. */
#define VALID_AUTH(a) ((a) != NULL && (a)->magic == AUTH_MAGIC)
/*
* XXXDCL For reloading, Make refcounted, and use attach and detach?
*/
struct auth {
unsigned int magic;
char *name;
unsigned char *secret;
size_t secretlen;
unsigned int algorithms;
ISC_LINK(auth_t) link;
};
static ISC_LIST(auth_t) omapi_authlist;
static isc_mutex_t mutex; /* To lock the previous variable. */
static isc_once_t once = ISC_ONCE_INIT; /* To initialize the mutex. */
static void
initialize_mutex(void) {
RUNTIME_CHECK(isc_mutex_init(&mutex) == ISC_R_SUCCESS);
}
static isc_result_t
auth_find(const char *name, unsigned int algorithm, auth_t **ap) {
auth_t *a;
isc_result_t result;
REQUIRE(name != NULL);
REQUIRE(ap != NULL && *ap == NULL);
for (a = ISC_LIST_HEAD(omapi_authlist); a != NULL;
a = ISC_LIST_NEXT(a, link))
if (strcmp(name, a->name) == 0)
break;
if (a == NULL)
result = ISC_R_NOTFOUND;
else if (algorithm != 0 && (algorithm & a->algorithms) != algorithm)
result = ISC_R_NOTIMPLEMENTED;
else {
ENSURE(VALID_AUTH(a));
*ap = a;
result = ISC_R_SUCCESS;
}
return (result);
}
isc_result_t
auth_makekey(const char *name, unsigned int algorithm, isc_region_t **keyp) {
isc_result_t result;
auth_t *auth = NULL;
isc_region_t *key;
REQUIRE(name != NULL && algorithm != 0);
REQUIRE(keyp != NULL && *keyp == NULL);
RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
LOCK(&mutex);
result = auth_find(name, algorithm, &auth);
if (result == ISC_R_SUCCESS) {
switch (algorithm) {
case OMAPI_AUTH_HMACMD5:
break;
default:
UNEXPECTED_ERROR(__FILE__, __LINE__,
"unknown auth algorithm %d",
algorithm);
return (ISC_R_UNEXPECTED);
}
key = isc_mem_get(omapi_mctx, sizeof(isc_region_t));
if (key == NULL)
result = ISC_R_NOMEMORY;
if (result == ISC_R_SUCCESS) {
key->base = auth->secret;
key->length = auth->secretlen;
*keyp = key;
}
}
UNLOCK(&mutex);
return (result);
}
static void
auth_delete(auth_t *a) {
REQUIRE(VALID_AUTH(a));
ISC_LIST_UNLINK(omapi_authlist, a, link);
a->magic = 0;
isc_mem_free(omapi_mctx, a->secret);
isc_mem_free(omapi_mctx, a->name);
isc_mem_put(omapi_mctx, a, sizeof(*a));
}
isc_result_t
omapi_auth_register(const char *name, unsigned int algorithms,
const unsigned char *secret, size_t secretlen)
{
auth_t *new = NULL;
isc_result_t result = ISC_R_SUCCESS;
REQUIRE(name != NULL && secret != NULL);
REQUIRE(algorithms != 0);
RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
LOCK(&mutex);
if (auth_find(name, 0, &new) == ISC_R_SUCCESS)
result = ISC_R_EXISTS;
if (result == ISC_R_SUCCESS) {
new = isc_mem_get(omapi_mctx, sizeof(*new));
if (new != NULL)
memset(new, 0, sizeof(*new));
else
result = ISC_R_NOMEMORY;
}
if (result == ISC_R_SUCCESS) {
new->name = isc_mem_strdup(omapi_mctx, name);
if (new->name == NULL)
result = ISC_R_NOMEMORY;
new->secret = isc_mem_allocate(omapi_mctx, secretlen);
if (new->secret == NULL)
result = ISC_R_NOMEMORY;
else {
memcpy(new->secret, secret, secretlen);
new->secretlen = secretlen;
}
new->algorithms = algorithms;
ISC_LINK_INIT(new, link);
new->magic = AUTH_MAGIC;
ISC_LIST_APPEND(omapi_authlist, new, link);
}
UNLOCK(&mutex);
if (result != ISC_R_SUCCESS) {
if (new->secret != NULL)
isc_mem_free(omapi_mctx, new->secret);
if (new->name != NULL)
isc_mem_free(omapi_mctx, new->name);
if (new != NULL)
isc_mem_put(omapi_mctx, new, sizeof(*new));
}
return (result);
}
/*
* Currently the way to effect a reload is to use omapi_auth_deregister(NULL)
* to remove all of the existing auth structs before building a new
* omapi_authlist via omapi_auth_register calls. This clearly leaves a
* window, however small, where there is no authentication possible.
*/
void
omapi_auth_deregister(const char *name) {
auth_t *a = NULL;
RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
LOCK(&mutex);
if (name == NULL)
while ((a = ISC_LIST_HEAD(omapi_authlist)) != NULL)
auth_delete(a);
else
if (auth_find(name, 0, &a) == ISC_R_SUCCESS)
auth_delete(a);
UNLOCK(&mutex);
}
/*
* Send a message from the client to the server that says the key with the
* given name should be used to authenticate messages.
*/
isc_result_t
omapi_auth_use(omapi_object_t *manager, const char *name,
unsigned int algorithm) {
omapi_protocol_t *protocol;
omapi_connection_t *connection;
omapi_object_t *message = NULL;
omapi_object_t *generic = NULL;
isc_result_t result;
auth_t *auth = NULL;
REQUIRE(manager != NULL);
REQUIRE(manager->type == omapi_type_protocol ||
(manager->outer != NULL &&
manager->outer->type == omapi_type_protocol));
if (manager->type == omapi_type_protocol)
protocol = (omapi_protocol_t *)manager;
else
protocol = (omapi_protocol_t *)manager->outer;
REQUIRE(protocol->outer != NULL &&
protocol->outer->type == omapi_type_connection);
connection = (omapi_connection_t *)protocol->outer;
INSIST(connection->is_client);
RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
LOCK(&mutex);
result = auth_find(name, algorithm, &auth);
UNLOCK(&mutex);
if (result == ISC_R_SUCCESS)
result = omapi_object_create(&generic, NULL, 0);
if (result == ISC_R_SUCCESS)
result = omapi_message_create(&message);
if (result == ISC_R_SUCCESS)
result = omapi_object_setinteger(message, "op", OMAPI_OP_OPEN);
if (result == ISC_R_SUCCESS)
result = omapi_object_setboolean(message, "update", ISC_TRUE);
if (result == ISC_R_SUCCESS)
result = omapi_object_setstring(message, "type", "protocol");
if (result == ISC_R_SUCCESS)
result = omapi_object_setobject(message, "object", generic);
if (result == ISC_R_SUCCESS)
result = omapi_object_setstring(generic, "auth-name", name);
if (result == ISC_R_SUCCESS)
result = omapi_object_setinteger(generic, "auth-algorithm",
(int)algorithm);
if (message != NULL)
omapi_message_register(message);
if (result == ISC_R_SUCCESS)
result = omapi_message_send(message, manager);
if (message != NULL) {
omapi_message_unregister(message);
omapi_object_dereference(&message);
}
if (result == ISC_R_SUCCESS)
/*
* If the name was not found on the server, ISC_R_NOTFOUND
* will be returned. Unlike with a username/password pair,
* where it is undesirable to disclose whether it was the
* username or password that was at fault, only one item
* can be discerned here -- the name, since the secret is
* not exchanged. Therefore there is no point in having
* the server obfuscate the ISC_R_NOTFOUND error into some
* other error.
*/
result = generic->waitresult;
if (result == ISC_R_SUCCESS)
/*
* This sets up the key in the protocol structure
* on this side of the connection.
*/
result = object_update((omapi_object_t *)protocol, generic, 0);
if (generic != NULL)
omapi_object_dereference(&generic);
return (result);
}
void
auth_destroy(void) {
omapi_auth_deregister(NULL);
DESTROYLOCK(&mutex);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,214 +0,0 @@
/*
* Copyright (C) 1996-2001 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.
*/
/* $Id: data.c,v 1.19 2001/01/09 21:59:56 bwelling Exp $ */
/* Principal Author: Ted Lemon */
/*
* Functions supporting memory allocation for the object management protocol.
*/
#include <config.h>
#include <stdlib.h> /* Required on BSD/OS 3.1 for abort() used in va_arg(). */
#include <isc/mem.h>
#include <isc/string.h>
#include <isc/util.h>
#include <omapi/private.h>
isc_result_t
omapi_data_create(omapi_data_t **t, omapi_datatype_t type, ...) {
va_list l;
omapi_data_t *new;
unsigned int len;
unsigned int val;
int intval;
char *s;
REQUIRE(type == omapi_datatype_int ||
type == omapi_datatype_data ||
type == omapi_datatype_string ||
type == omapi_datatype_object);
va_start(l, type);
/*
* Quiet bogus "might be used uninitialized in this function" warnings.
*/
val = 0;
intval = 0;
s = NULL;
switch (type) {
case omapi_datatype_int:
len = OMAPI_DATA_INT_LEN;
intval = va_arg(l, int);
break;
case omapi_datatype_string:
s = va_arg(l, char *);
val = strlen(s);
len = OMAPI_DATA_NOBUFFER_LEN + val;
break;
case omapi_datatype_data:
val = va_arg(l, unsigned int);
len = OMAPI_DATA_NOBUFFER_LEN + val;
break;
case omapi_datatype_object:
len = OMAPI_DATA_OBJECT_LEN;
break;
default:
UNEXPECTED_ERROR(__FILE__, __LINE__,
"unknown type in omapi_data_create: %d",
type);
return (ISC_R_UNEXPECTED);
}
new = isc_mem_get(omapi_mctx, len);
if (new == NULL)
return (ISC_R_NOMEMORY);
memset(new, 0, len);
switch (type) {
case omapi_datatype_int:
new->u.integer = intval;
break;
case omapi_datatype_string:
memcpy(new->u.buffer.value, s, val);
new->u.buffer.len = val;
break;
case omapi_datatype_data:
new->u.buffer.len = val;
break;
case omapi_datatype_object:
OBJECT_REF(&new->u.object, va_arg(l, omapi_object_t *));
break;
}
new->type = type;
omapi_data_reference(t, new);
return (ISC_R_SUCCESS);
}
void
omapi_data_reference(omapi_data_t **r, omapi_data_t *h) {
REQUIRE(r != NULL && h != NULL);
REQUIRE(*r == NULL);
*r = h;
h->refcnt++;
}
void
omapi_data_dereference(omapi_data_t **h) {
unsigned int length = 0;
REQUIRE(h != NULL && *h != NULL);
REQUIRE((*h)->refcnt > 0);
if (--((*h)->refcnt) == 0) {
switch ((*h)->type) {
case omapi_datatype_int:
length = OMAPI_DATA_INT_LEN;
break;
case omapi_datatype_string:
length = OMAPI_DATA_NOBUFFER_LEN + (*h)->u.buffer.len;
break;
case omapi_datatype_data:
length = OMAPI_DATA_NOBUFFER_LEN + (*h)->u.buffer.len;
break;
case omapi_datatype_object:
OBJECT_DEREF(&(*h)->u.object);
length = OMAPI_DATA_OBJECT_LEN;
break;
default:
FATAL_ERROR(__FILE__, __LINE__,
"unknown datatype in "
"omapi_data_dereference: %d\n",
(*h)->type);
/* NOTREACHED */
break;
}
isc_mem_put(omapi_mctx, *h, length);
}
*h = NULL;
}
int
omapi_data_strcmp(omapi_data_t *s1, const char *s2) {
unsigned int len, slen;
int order;
REQUIRE(s1->type == omapi_datatype_data ||
s1->type == omapi_datatype_string);
slen = strlen(s2);
if (slen > s1->u.buffer.len)
len = s1->u.buffer.len;
else
len = slen;
order = memcmp(s1->u.buffer.value, s2, len);
if (order == 0) {
if (s1->u.buffer.len > slen)
order = 1;
else if (s1->u.buffer.len < slen)
order = -1;
}
return (order);
}
int
omapi_data_getint(omapi_data_t *t) {
isc_uint32_t stored_value; /* Stored in network byte order. */
REQUIRE(t != NULL);
REQUIRE(t->type == omapi_datatype_int ||
((t->type == omapi_datatype_data ||
(t->type == omapi_datatype_string)) &&
t->u.buffer.len == sizeof(stored_value)));
if (t->type == omapi_datatype_int)
return (t->u.integer);
memcpy(&stored_value, t->u.buffer.value, sizeof(stored_value));
return (ntohl(stored_value));
}
char *
omapi_data_strdup(isc_mem_t *mctx, omapi_data_t *t) {
char *s;
REQUIRE(mctx != NULL && t != NULL);
REQUIRE(t->type == omapi_datatype_string ||
t->type == omapi_datatype_data);
s = isc_mem_allocate(mctx, t->u.buffer.len + 1);
if (s != NULL) {
memcpy(s, t->u.buffer.value, t->u.buffer.len);
s[t->u.buffer.len] = '\0';
}
return (s);
}

View File

@ -1,256 +0,0 @@
/*
* Copyright (C) 1996-2001 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.
*/
/* $Id: generic.c,v 1.18 2001/01/09 21:59:57 bwelling Exp $ */
/* Principal Author: Ted Lemon */
/*
* Subroutines that support the generic object.
*/
#include <config.h>
#include <stdlib.h> /* Required on BSD/OS 3.1 for abort() used in va_arg(). */
#include <isc/mem.h>
#include <isc/string.h>
#include <isc/util.h>
#include <omapi/private.h>
static isc_result_t
generic_setvalue(omapi_object_t *h, omapi_string_t *name, omapi_data_t *value)
{
omapi_generic_t *g;
omapi_value_t *new;
omapi_value_t **va;
int vm_new;
unsigned int i;
isc_result_t result;
REQUIRE(h != NULL && h->type == omapi_type_generic);
g = (omapi_generic_t *)h;
/*
* See if there's already a value with this name attached to
* the generic object, and if so, replace the current value
* with the new one.
*/
for (i = 0; i < g->nvalues; i++) {
if (omapi_string_stringcmp(name, g->values[i]->name) == 0) {
/*
* There's an inconsistency here: the standard
* behaviour of a set_values method when
* passed a matching name and a null value is
* to delete the value associated with that
* name (where possible). In the generic
* object, we remember the name/null pair,
* because generic objects are generally used
* to pass messages around, and this is the
* way that remote entities delete values from
* local objects. If the get_value method of
* a generic object is called for a name that
* maps to a name/null pair, ISC_R_NOTFOUND is
* returned.
*/
new = NULL;
result = omapi_value_create(&new);
if (result != ISC_R_SUCCESS)
return (result);
omapi_string_reference(&new->name, name);
if (value != NULL)
omapi_data_reference(&new->value, value);
omapi_value_dereference(&(g->values[i]));
omapi_value_reference(&(g->values[i]), new);
omapi_value_dereference(&new);
return (ISC_R_SUCCESS);
}
}
/*
* If the name isn't already attached to this object, see if an
* inner object has it.
*/
result = omapi_object_passsetvalue(h, name, value);
if (result != ISC_R_NOTFOUND)
return (result);
/*
* Okay, so it's a value that no inner object knows about, and
* (implicitly, since the outer object set_value method would
* have called this object's set_value method) it's an object that
* no outer object knows about, it's this object's responsibility
* to remember it - that's what generic objects do.
*/
/*
* Arrange for there to be space for the pointer to the new
* name/value pair if necessary.
*/
if (g->nvalues == g->va_max) {
/*
* Increase the maximum number of values by 10.
* 10 is an arbitrary constant.
*/
vm_new = g->va_max + 10;
va = isc_mem_get(omapi_mctx, vm_new * sizeof(*va));
if (va == NULL)
return (ISC_R_NOMEMORY);
if (g->va_max != 0) {
memcpy(va, g->values, g->va_max * sizeof(*va));
isc_mem_put(omapi_mctx, g->values,
g->va_max * sizeof(*va));
}
memset(va + g->va_max, 0, (vm_new - g->va_max) * sizeof(*va));
g->values = va;
g->va_max = vm_new;
}
result = omapi_value_create(&g->values[g->nvalues]);
if (result != ISC_R_SUCCESS)
return (result);
omapi_string_reference(&g->values[g->nvalues]->name, name);
if (value != NULL)
omapi_data_reference(&g->values[g->nvalues]->value, value);
g->nvalues++;
return (ISC_R_SUCCESS);
}
static isc_result_t
generic_getvalue(omapi_object_t *h, omapi_string_t *name,
omapi_value_t **value)
{
unsigned int i;
omapi_generic_t *g;
REQUIRE(h != NULL && h->type == omapi_type_generic);
g = (omapi_generic_t *)h;
/*
* Look up the specified name in our list of objects.
*/
for (i = 0; i < g->nvalues; i++) {
if (omapi_string_stringcmp(name, g->values[i]->name) == 0) {
/*
* If this is a name/null value pair, this is the
* same as if there were no value that matched
* the specified name, so return ISC_R_NOTFOUND.
*/
if (g->values[i]->value == NULL)
return (ISC_R_NOTFOUND);
/*
* Otherwise, return the name/value pair.
*/
omapi_value_reference(value, g->values[i]);
return (ISC_R_SUCCESS);
}
}
return (omapi_object_passgetvalue(h, name, value));
}
static void
generic_destroy(omapi_object_t *h) {
omapi_generic_t *g;
unsigned int i;
REQUIRE(h != NULL && h->type == omapi_type_generic);
g = (omapi_generic_t *)h;
if (g->values != NULL) {
for (i = 0; i < g->nvalues; i++)
if (g->values[i] != NULL)
omapi_value_dereference(&g->values[i]);
isc_mem_put(omapi_mctx, g->values,
g->va_max * sizeof(*g->values));
g->values = NULL;
g->va_max = 0;
}
}
static isc_result_t
generic_signalhandler(omapi_object_t *h, const char *name, va_list ap) {
REQUIRE(h != NULL && h->type == omapi_type_generic);
/*
* XXXDCL I suppose that ideally the status would be set in all
* objects in the chain.
*/
if (strcmp(name, "status") == 0) {
h->waitresult = va_arg(ap, isc_result_t);
return (ISC_R_SUCCESS);
}
return (omapi_object_passsignal(h, name, ap));
}
/*
* Write all the published values associated with the object through the
* specified connection.
*/
static isc_result_t
generic_stuffvalues(omapi_object_t *connection, omapi_object_t *h) {
omapi_generic_t *src;
unsigned int i;
isc_result_t result;
REQUIRE(h != NULL && h->type == omapi_type_generic);
src = (omapi_generic_t *)h;
for (i = 0; i < src->nvalues; i++) {
if (src->values[i] != NULL &&
src->values[i]->name->len != 0) {
result = omapi_connection_putuint16(connection,
src->values[i]->name->len);
if (result != ISC_R_SUCCESS)
return (result);
result = omapi_connection_putmem(connection,
src->values[i]->name->value,
src->values[i]->name->len);
if (result != ISC_R_SUCCESS)
return (result);
result = omapi_connection_putdata(connection,
src->values[i]->value);
if (result != ISC_R_SUCCESS)
return (result);
}
}
return (omapi_object_passstuffvalues(connection, h));
}
isc_result_t
generic_init(void) {
return (omapi_object_register(&omapi_type_generic, "generic",
generic_setvalue,
generic_getvalue,
generic_destroy,
generic_signalhandler,
generic_stuffvalues,
NULL, NULL, NULL));
}

View File

@ -1,352 +0,0 @@
/*
* Copyright (C) 1996-2001 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.
*/
/* $Id: handle.c,v 1.18 2001/01/09 21:59:58 bwelling Exp $ */
/* Principal Author: Ted Lemon */
/*
* Functions for maintaining handles on objects.
*/
#include <config.h>
#include <isc/mem.h>
#include <isc/once.h>
#include <isc/string.h>
#include <isc/util.h>
#include <omapi/private.h>
/*
* The handle table is a hierarchical tree designed for quick mapping
* of handle identifiers to objects. Objects contain their own handle
* identifiers if they have them, so the reverse mapping is also
* quick. The hierarchy is made up of table objects, each of which
* has 120 entries, a flag indicating whether the table is a leaf
* table or an indirect table, the handle of the first object covered
* by the table and the first object after that that's *not* covered
* by the table, a count of how many objects of either type are
* currently stored in the table, and an array of 120 entries pointing
* either to objects or tables.
*
* When we go to add an object to the table, we look to see if the
* next object handle to be assigned is covered by the outermost
* table. If it is, we find the place within that table where the
* next handle should go, and if necessary create additional nodes in
* the tree to contain the new handle. The pointer to the object is
* then stored in the correct position.
*
* XXXTL
* Theoretically, we could have some code here to free up handle
* tables as they go out of use, but by and large handle tables won't
* go out of use, so this is being skipped for now. It shouldn't be
* too hard to implement in the future if there's a different
* application.
*/
#define OMAPI_HANDLETABLE_SIZE 120
typedef struct omapi_handletable {
omapi_handle_t first;
omapi_handle_t limit;
omapi_handle_t next;
isc_boolean_t leaf;
union {
omapi_object_t * object;
struct omapi_handletable * table;
} children[OMAPI_HANDLETABLE_SIZE];
} omapi_handletable_t;
static omapi_handletable_t *toptable;
static omapi_handle_t next_handle = 1; /* Next handle to be assigned. */
static isc_mutex_t mutex; /* To lock the 2 previous variables. */
static isc_once_t once = ISC_ONCE_INIT; /* To initialize the mutex. */
/*
* initialize_mutex() is called by isc_once_do in object_gethandle()
*/
static void
initialize_mutex(void) {
RUNTIME_CHECK(isc_mutex_init(&mutex) == ISC_R_SUCCESS);
}
static isc_result_t
table_enclose(omapi_handletable_t **table) {
omapi_handletable_t *inner = *table;
omapi_handletable_t *new;
int idx, base, scale;
/*
* The scale of the table we're enclosing is going to be the
* difference between its "first" and "limit" members. So the
* scale of the table enclosing it is going to be that multiplied
* by the table size.
*/
scale = (inner->first - inner->limit) * OMAPI_HANDLETABLE_SIZE;
/*
* The range that the enclosing table covers is going to be
* the result of subtracting the remainder of dividing the
* enclosed table's first entry number by the enclosing
* table's scale. If handle IDs are being allocated
* sequentially, the enclosing table's "first" value will be
* the same as the enclosed table's "first" value.
*/
base = inner->first - inner->first % scale;
/*
* The index into the enclosing table at which the enclosed table
* will be stored is going to be the difference between the "first"
* value of the enclosing table and the enclosed table - zero, if
* we are allocating sequentially.
*/
idx = (base - inner->first) / OMAPI_HANDLETABLE_SIZE;
new = isc_mem_get(omapi_mctx, sizeof(*new));
if (new == NULL)
return (ISC_R_NOMEMORY);
memset(new, 0, sizeof *new);
new->first = base;
new->limit = base + scale;
if (scale == OMAPI_HANDLETABLE_SIZE)
new->leaf = ISC_FALSE;
new->children[idx].table = inner;
*table = new;
return (ISC_R_SUCCESS);
}
static isc_result_t
handle_store(omapi_handle_t h, omapi_handletable_t *table, omapi_object_t *o) {
omapi_handletable_t *inner;
omapi_handle_t scale, idx;
isc_result_t result;
if (table->first > h || table->limit <= h)
return (ISC_R_NOSPACE);
/*
* If this is a leaf table, just stash the object in the
* appropriate place.
*/
if (table->leaf) {
OBJECT_REF(&table->children[h - table->first].object, o);
o->handle = h;
return (ISC_R_SUCCESS);
}
/*
* Scale is the number of handles represented by each child of this
* table. For a leaf table, scale would be 1. For a first level
* of indirection, 120. For a second, 120 * 120. Et cetera.
*/
scale = (table->limit - table->first) / OMAPI_HANDLETABLE_SIZE;
/*
* So the next most direct table from this one that contains the
* handle must be the subtable of this table whose index into this
* table's array of children is the handle divided by the scale.
*/
idx = (h - table->first) / scale;
inner = table->children[idx].table;
/*
* If there is no more direct table than this one in the slot
* we came up with, make one.
*/
if (inner == NULL) {
inner = isc_mem_get(omapi_mctx, sizeof(*inner));
if (inner == NULL)
return (ISC_R_NOMEMORY);
memset(inner, 0, sizeof(*inner));
inner->first = idx * scale + table->first;
inner->limit = inner->first + scale;
if (scale == OMAPI_HANDLETABLE_SIZE)
inner->leaf = ISC_TRUE;
table->children[idx].table = inner;
}
result = handle_store(h, inner, o);
if (result == ISC_R_NOSPACE) {
result = (table_enclose
(&table->children[idx].table));
if (result != ISC_R_SUCCESS)
return (result);
return (handle_store(h, table->children[idx].table, o));
}
return (result);
}
isc_result_t
object_gethandle(omapi_handle_t *h, omapi_object_t *o) {
isc_result_t result = ISC_R_SUCCESS;
RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
LOCK(&mutex);
if (o->handle != 0) {
*h = o->handle;
UNLOCK(&mutex);
return (ISC_R_SUCCESS);
}
if (toptable == NULL) {
toptable = isc_mem_get(omapi_mctx, sizeof(*toptable));
if (toptable != NULL) {
memset(toptable, 0, sizeof(*toptable));
toptable->first = 0;
toptable->limit = OMAPI_HANDLETABLE_SIZE;
toptable->leaf = ISC_TRUE;
} else
result = ISC_R_NOMEMORY;
}
if (result == ISC_R_SUCCESS)
/*
* If this handle doesn't fit in the outer table, we need to
* make a new outer table. This is a while loop in case for
* some reason we decide to do disjoint handle allocation,
* where the next level of indirection still isn't big enough
* to enclose the next handle ID.
*/
while (next_handle >= toptable->limit) {
omapi_handletable_t *new;
new = isc_mem_get(omapi_mctx, sizeof(*new));
if (new != NULL) {
memset(new, 0, sizeof(*new));
new->first = 0;
new->limit = toptable->limit *
OMAPI_HANDLETABLE_SIZE;
new->leaf = ISC_FALSE;
new->children[0].table = toptable;
toptable = new;
} else
result = ISC_R_NOMEMORY;
}
/*
* Try to cram this handle into the existing table.
*/
if (result == ISC_R_SUCCESS)
result = handle_store(next_handle, toptable, o);
if (result == ISC_R_NOSPACE) {
result = table_enclose(&toptable);
if (result == ISC_R_SUCCESS)
result = handle_store(next_handle, toptable, o);
}
/*
* If it worked, return the next handle and increment it.
*/
if (result == ISC_R_SUCCESS)
*h = next_handle++;
UNLOCK(&mutex);
return (result);
}
static isc_result_t
lookup_iterate(omapi_object_t **o, omapi_handle_t h,
omapi_handletable_t *table)
{
omapi_handletable_t *inner;
omapi_handle_t scale, idx;
if (table == NULL || table->first > h || table->limit <= h)
return (ISC_R_NOTFOUND);
/*
* If this is a leaf table, just grab the object.
*/
if (table->leaf) {
/*
* Not there?
*/
if (table->children[h - table->first].object == NULL)
return (ISC_R_NOTFOUND);
OBJECT_REF(o, table->children[h - table->first].object);
return (ISC_R_SUCCESS);
}
/*
* Scale is the number of handles represented by each child of this
* table. For a leaf table, scale would be 1. For a first level
* of indirection, 120. For a second, 120 * 120. Et cetera.
*/
scale = (table->limit - table->first) / OMAPI_HANDLETABLE_SIZE;
/*
* So the next most direct table from this one that contains the
* handle must be the subtable of this table whose index into this
* table's array of children is the handle divided by the scale.
*/
idx = (h - table->first) / scale;
inner = table->children[idx].table;
return (lookup_iterate(o, h, inner));
}
isc_result_t
handle_lookup(omapi_object_t **o, omapi_handle_t h) {
isc_result_t result;
LOCK(&mutex);
result = lookup_iterate(o, h, toptable);
UNLOCK(&mutex);
return (result);
}
static void
free_table(omapi_handletable_t **table) {
int i;
if ((*table)->leaf)
isc_mem_put(omapi_mctx, *table, sizeof(**table));
else
for (i = 0; i < OMAPI_HANDLETABLE_SIZE; i++)
if ((*table)->children[i].table != NULL)
free_table(&(*table)->children[i].table);
else
break;
*table = NULL;
}
void
handle_destroy(void) {
RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
LOCK(&mutex);
if (toptable != NULL)
free_table(&toptable);
UNLOCK(&mutex);
DESTROYLOCK(&mutex);
}

View File

@ -1 +0,0 @@
Makefile

View File

@ -1,25 +0,0 @@
# Copyright (C) 1999-2001 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.
# $Id: Makefile.in,v 1.6 2001/01/09 22:00:22 bwelling Exp $
srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
SUBDIRS = omapi
TARGETS =
@BIND9_MAKE_RULES@

View File

@ -1 +0,0 @@
Makefile

View File

@ -1,37 +0,0 @@
# Copyright (C) 1999-2001 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.
# $Id: Makefile.in,v 1.11 2001/01/09 22:00:24 bwelling Exp $
srcdir = @srcdir@
VPATH = @srcdir@
top_srcdir = @top_srcdir@
@BIND9_VERSION@
HEADERS = compatibility.h lib.h omapi.h private.h result.h types.h
SUBDIRS =
TARGETS =
@BIND9_MAKE_RULES@
installdirs:
$(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/omapi
install:: installdirs
for i in ${HEADERS}; do \
${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/omapi ; \
done

View File

@ -1,93 +0,0 @@
/*
* Copyright (C) 2000, 2001 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.
*/
/* $Id: compatibility.h,v 1.7 2001/01/09 22:00:25 bwelling Exp $ */
#ifndef OMAPI_COMPATIBILITY_H
#define OMAPI_COMPATIBILITY_H 1
#include <isc/result.h>
/*****
***** Macro definitions for partial compatability with Ted Lemon's original
***** design of OMAPI for DCHP. The intent is that with by using this header
***** than few changes need be made immediately to the source code in order
***** to get it working with the updated OMAPI library. The other changes
***** can then be made as is convenient.
*****/
/*
* Waiting is done inherently on the client now. It didn't seem to me
* that the server needs it, but if it does, connection_wait() could
* be made public as omapi_connection_wait().
*/
#define omapi_wait_for_completion(o, t) ISC_R_SUCCESS
#define omapi_value_new(v, i) omapi_value_create(v)
#define omapi_make_value omapi_value_storedata
#define omapi_make_const_value omapi_value_storemem
#define omapi_make_int_value omapi_value_storeint
#define omapi_make_handle_value omapi_value_storeobject
#define omapi_make_string_value omapi_value_storestr
#define omapi_data_new omapi_data_create
#define omapi_td_strcmp omapi_data_strcmp
#define omapi_get_int_value omapi_data_getint
#define omapi_data_string_new(s, l, i) omapi_string_create(s, l)
#define omapi_data_string_cmp omapi_string_stringcmp
#define omapi_ds_strcmp omapi_string_strcmp
/*
* The get_value, set_value and stuff_values methods all had their id
* parameter removed, so those functions for special client/server objects
* need to have their definitions adjusted.
*
*/
#define omapi_set_value(h, id, name, value) \
omapi_object_set(h, name, value)
#define omapi_set_value_str(h, id, name, value) \
omapi_object_setdata(h, name, value)
#define omapi_set_boolean_value(h, id, name, value) \
omapi_object_setboolean(h, name, value)
#define omapi_set_int_value(h, id, name, value) \
omapi_object_setinteger(h, name, value)
#define omapi_set_object_value(h, id, name, value) \
omapi_object_setobject(h, name, value)
#define omapi_set_string_value(h, id, name, value) \
omapi_object_setstring(h, name, value)
#define omapi_get_value_str(h, id, name, value) \
omapi_object_getvalue(h, name, value)
#define omapi_object_type_register omapi_object_register
#define omapi_init omapi_lib_init
#define omapi_message_new(m, id) omapi_message_create(m)
#define omapi_protocol_send_message(po, id, mo, omo) \
omapi_message_send(mo, po)
#define omapi_listen omapi_listener_listen
#define omapi_connection_copyin omapi_connection_putmem
#define omapi_connection_put_uint16 omapi_connection_putuin16
#define omapi_connection_put_uint32 omapi_connection_putuin32
#define omapi_connection_put_name omapi_connection_putname
#define omapi_connection_put_string omapi_connection_putstring
#define omapi_connection_put_handle omapi_connection_puthandle
#define omapi_connection_write_typed_data omapi_connection_putdata
#endif /* OMAPI_COMPATIBILITY_H */

View File

@ -1,39 +0,0 @@
/*
* Copyright (C) 1999-2001 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.
*/
/* $Id: lib.h,v 1.6 2001/01/09 22:00:26 bwelling Exp $ */
#ifndef OMAPI_LIB_H
#define OMAPI_LIB_H 1
#include <isc/types.h>
#include <isc/lang.h>
ISC_LANG_BEGINDECLS
extern isc_msgcat_t *omapi_msgcat;
void
omapi_lib_initmsgcat(void);
/*
* Initialize the OMAPI library's message catalog, omapi_msgcat, if it
* has not already been initialized.
*/
ISC_LANG_ENDDECLS
#endif /* OMAPI_LIB_H */

View File

@ -1,382 +0,0 @@
/*
* Copyright (C) 1996-2001 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.
*/
/* $Id: omapi.h,v 1.19 2001/02/15 19:13:48 bwelling Exp $ */
/*
* Definitions for the object management API and protocol.
*/
#ifndef OMAPI_OMAPI_H
#define OMAPI_OMAPI_H 1
#include <stdarg.h>
#include <isc/boolean.h>
#include <isc/eventclass.h>
#include <isc/lang.h>
#include <omapi/types.h>
ISC_LANG_BEGINDECLS
#define OMAPI_PROTOCOL_VERSION 100
/*
* Protocol operations.
*/
#define OMAPI_OP_OPEN 1
#define OMAPI_OP_REFRESH 2
#define OMAPI_OP_UPDATE 3
#define OMAPI_OP_NOTIFY 4
#define OMAPI_OP_STATUS 5
#define OMAPI_OP_DELETE 6
/*
* This preamble is common to all objects manipulated by libomapi.a,
* including specials objects created by external users of the library.
* It needs to be at the start of every struct that gets used as an object.
*/
#define OMAPI_OBJECT_PREAMBLE \
omapi_objecttype_t * type; \
size_t object_size; \
int refcnt; \
isc_result_t waitresult; \
omapi_handle_t handle; \
omapi_object_t *outer, *inner; \
isc_taskaction_t destroy_action; \
void * destroy_arg
/*
* This is the most basic OMAPI object, used as the handle for all
* other object types in most public calls.
*/
struct omapi_object {
OMAPI_OBJECT_PREAMBLE;
};
/*
* For use with omapi_connection_disconnect().
* XXXDCL rename
*/
#define OMAPI_FORCE_DISCONNECT ISC_TRUE
#define OMAPI_CLEAN_DISCONNECT ISC_FALSE
/*
* For use with omapi_auth_*. Will be powers of 2 when there is ever
* more than one authentication algorithm available.
*/
#define OMAPI_AUTH_HMACMD5 1
#define OMAPI_EVENT_OBJECTFREED (ISC_EVENTCLASS_OMAPI + 1)
/*****
***** Function Prototypes.
*****/
/*
* Public functions defined in auth.c.
*/
isc_result_t
omapi_auth_register(const char *name, unsigned int algorithms,
const unsigned char *secret, size_t secretlen);
void
omapi_auth_deregister(const char *name);
isc_result_t
omapi_auth_use(omapi_object_t *manager, const char *name,
unsigned int algorithm);
/*
* Public functions defined in protocol.c.
*/
isc_result_t
omapi_protocol_connect(omapi_object_t *object, const char *server,
in_port_t port, omapi_object_t *authinfo);
void
omapi_protocol_disconnect(omapi_object_t *handle, isc_boolean_t force);
/*
* XXXDCL The use of one void *arg for all three callbacks/taskactions is
* questionable.
*/
isc_result_t
omapi_protocol_listen(omapi_object_t *mgr, isc_sockaddr_t *addr,
isc_boolean_t ((*verify_connection)
(isc_sockaddr_t *incoming,
void *connect_arg)),
isc_boolean_t ((*verify_key)
(const char *name,
unsigned int algorithm,
void *key_arg)),
isc_taskaction_t destroy_action, void *arg);
/*
* Public functions defined in connection.c.
*/
void
omapi_connection_disconnect(omapi_object_t *connection, isc_boolean_t how);
isc_result_t
omapi_connection_putmem(omapi_object_t *connection, const unsigned char *data,
unsigned int length);
isc_result_t
omapi_connection_putuint16(omapi_object_t *c, isc_uint32_t value);
isc_result_t
omapi_connection_putuint32(omapi_object_t *c, isc_uint32_t value);
isc_result_t
omapi_connection_putdata(omapi_object_t *connection, omapi_data_t *data);
isc_result_t
omapi_connection_putname(omapi_object_t *connection, const char *name);
isc_result_t
omapi_connection_putstring(omapi_object_t *connection, const char *string);
isc_result_t
omapi_connection_puthandle(omapi_object_t *connection, omapi_object_t *object);
/*
* Public functions defined in listen.c.
*/
isc_result_t
omapi_listener_listen(omapi_object_t *mgr, isc_sockaddr_t *addr,
isc_boolean_t ((*verify_connection)
(isc_sockaddr_t *incoming,
void *connect_arg)),
isc_boolean_t ((*verify_key)
(const char *name,
unsigned int algorithm,
void *key_arg)),
isc_taskaction_t destroy_action, void *arg);
void
omapi_listener_shutdown(omapi_object_t *mgr);
/*
* Public functions defined in message.c.
*/
isc_result_t
omapi_message_create(omapi_object_t **message);
void
omapi_message_register(omapi_object_t *message);
void
omapi_message_unregister(omapi_object_t *message);
isc_result_t
omapi_message_send(omapi_object_t *message, omapi_object_t *protocol);
/*
* Public functions defined in lib.c.
*/
isc_result_t
omapi_lib_init(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_socketmgr_t *socketmgr);
void
omapi_lib_destroy(void);
/*
* Public functions defined in object.c.
*/
isc_result_t
omapi_object_create(omapi_object_t **object, omapi_objecttype_t *type,
size_t size);
void
omapi_object_reference(omapi_object_t **reference, omapi_object_t *object);
void
omapi_object_dereference(omapi_object_t **reference);
isc_result_t
omapi_object_register(omapi_objecttype_t **type, const char *name,
isc_result_t ((*set_value)(omapi_object_t *,
omapi_string_t *,
omapi_data_t *)),
isc_result_t ((*get_value)(omapi_object_t *,
omapi_string_t *,
omapi_value_t **)),
void ((*destroy)(omapi_object_t *)),
isc_result_t ((*signal_handler)(omapi_object_t *,
const char *,
va_list)),
isc_result_t ((*stuff_values)(omapi_object_t *,
omapi_object_t *)),
isc_result_t ((*lookup)(omapi_object_t **,
omapi_object_t *)),
isc_result_t ((*create)(omapi_object_t **)),
isc_result_t ((*expunge)(omapi_object_t *)));
isc_result_t
omapi_object_set(omapi_object_t *handle, omapi_string_t *name,
omapi_data_t *value);
isc_result_t
omapi_object_setdata(omapi_object_t *handle, const char *name,
omapi_data_t *value);
isc_result_t
omapi_object_setboolean(omapi_object_t *handle, const char *name,
isc_boolean_t value);
isc_result_t
omapi_object_setinteger(omapi_object_t *handle, const char *name,
int value);
isc_result_t
omapi_object_setobject(omapi_object_t *handle, const char *name,
omapi_object_t *value);
isc_result_t
omapi_object_setstring(omapi_object_t *handle, const char *name,
const char *value);
isc_result_t
omapi_object_getvalue(omapi_object_t *handle, const char *name,
omapi_value_t **value);
isc_result_t
omapi_object_passgetvalue(omapi_object_t *object, omapi_string_t *name,
omapi_value_t **value);
isc_result_t
omapi_object_passsetvalue(omapi_object_t *object, omapi_string_t *name,
omapi_data_t *value);
isc_result_t
omapi_object_passsignal(omapi_object_t *object, const char *name,
va_list args);
isc_result_t
omapi_object_passstuffvalues(omapi_object_t *connection,
omapi_object_t *object);
/*
* Public functions defined in data.c.
*/
isc_result_t
omapi_data_create(omapi_data_t **data, omapi_datatype_t type, ...);
void
omapi_data_reference(omapi_data_t **reference, omapi_data_t *data);
void
omapi_data_dereference(omapi_data_t **reference);
int
omapi_data_strcmp(omapi_data_t *string_type, const char *string);
int
omapi_data_getint(omapi_data_t *data);
char *
omapi_data_strdup(isc_mem_t *mctx, omapi_data_t *t);
/*
* Public functions defined in string.c.
*/
isc_result_t
omapi_string_create(omapi_string_t **string, unsigned int length);
void
omapi_string_reference(omapi_string_t **reference, omapi_string_t *string);
void
omapi_string_dereference(omapi_string_t **);
/*
* XXXDCL consider better API
*/
void
omapi_string_totext(omapi_string_t *string, isc_region_t *region);
int
omapi_string_stringcmp(omapi_string_t *string1, omapi_string_t *string2);
int
omapi_string_strcmp(omapi_string_t *data_string, const char *string);
/*
* Public functions defined in value.c.
*/
isc_result_t
omapi_value_create(omapi_value_t **value);
void
omapi_value_reference(omapi_value_t **reference, omapi_value_t *value);
void
omapi_value_dereference(omapi_value_t **reference);
isc_result_t
omapi_value_storedata(omapi_value_t **valuep, omapi_string_t *name,
omapi_data_t *value);
isc_result_t
omapi_value_storemem(omapi_value_t **valuep, omapi_string_t *name,
const unsigned char *value, unsigned int length);
isc_result_t
omapi_value_storeint(omapi_value_t **valuep, omapi_string_t *name,
int value);
isc_result_t
omapi_value_storeobject(omapi_value_t **valuep, omapi_string_t *name,
omapi_object_t *handle);
isc_result_t
omapi_value_storestr(omapi_value_t **valuep, omapi_string_t *name,
char *string);
/*
* XXXDCL for completeness, it would be good to have more functions that
* can fetch the value out of an omapi_data_t into a form that a C progammer
* is more used to working with.
*/
int
omapi_value_getint(omapi_value_t *value);
/*
* WARNING: The region returned is (currently) only valid for as long
* as the value pointer is valid, which means "until it is completely
* dereferenced". If you want to ensure it hangs around, you should
* use omapi_value_reference to add another reference to the value pointer,
* and then remember to use omapi_value_dereference to free it.
* XXXDCL yes, kind of lame. the interface to the omapi_value_get* functions
* will probably change.
*/
void
omapi_value_getregion(omapi_value_t *value, isc_region_t *region);
ISC_LANG_ENDDECLS
#endif /* OMAPI_OMAPI_H */

View File

@ -1,449 +0,0 @@
/*
* Copyright (C) 1996-2001 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.
*/
/* $Id: private.h,v 1.28 2001/02/15 20:10:04 bwelling Exp $ */
/*****
***** Private master include file for the OMAPI library.
*****/
#ifndef OMAPI_PRIVATE_H
#define OMAPI_PRIVATE_H 1
#include <isc/condition.h>
#include <isc/hmacmd5.h>
#include <isc/lang.h>
#include <isc/mutex.h>
#include <isc/socket.h>
#include <omapi/omapi.h>
#define OMAPI_BUFFER_SIZE 4096
/*
* Types shared among multiple library files.
*/
typedef struct omapi_generic omapi_generic_t;
typedef struct omapi_message omapi_message_t;
typedef struct omapi_connection omapi_connection_t;
typedef struct omapi_protocol omapi_protocol_t;
typedef enum {
omapi_connection_unconnected,
omapi_connection_connecting,
omapi_connection_connected,
omapi_connection_disconnecting,
omapi_connection_closed
} omapi_connection_state_t;
typedef enum {
omapi_protocol_intro_wait,
omapi_protocol_header_wait,
omapi_protocol_signature_wait,
omapi_protocol_name_wait,
omapi_protocol_name_length_wait,
omapi_protocol_value_wait,
omapi_protocol_value_length_wait
} omapi_protocol_state_t;
/*
* OMAPI data types.
*/
struct omapi_data {
#define OMAPI_DATA_HEADER_LEN (sizeof(int) + sizeof(omapi_datatype_t))
int refcnt;
omapi_datatype_t type;
union {
/*
* OMAPI_DATA_NOBUFFER_LEN purposefully does not
* include the 'value' byte, which only serves as a
* handle to memory allocated for (usually) more than
* one byte that begins at the 'value' location.
*/
#define OMAPI_DATA_NOBUFFER_LEN (OMAPI_DATA_HEADER_LEN + sizeof(int))
struct {
unsigned int len;
unsigned char value[1];
} buffer;
#define OMAPI_DATA_OBJECT_LEN \
(OMAPI_DATA_HEADER_LEN + sizeof(omapi_object_t *))
omapi_object_t *object;
#define OMAPI_DATA_INT_LEN (OMAPI_DATA_HEADER_LEN + sizeof(int))
int integer;
} u;
};
struct omapi_string {
/*
* OMAPI_STRING_EMPTY_SIZE purposefully does not
* include the 'value' byte, which only serves as a
* handle to memory allocated for (usually) more than
* one byte that begins at the 'value' location.
*/
#define OMAPI_STRING_EMPTY_SIZE (2 * sizeof(int))
int refcnt;
unsigned int len;
unsigned char value[1];
};
struct omapi_value {
int refcnt;
omapi_string_t * name;
omapi_data_t * value;
};
struct omapi_generic {
OMAPI_OBJECT_PREAMBLE;
omapi_value_t ** values;
unsigned int nvalues;
unsigned int va_max;
};
struct omapi_message {
OMAPI_OBJECT_PREAMBLE;
omapi_message_t * next;
omapi_message_t * prev;
omapi_object_t * object;
omapi_object_t * notify_object;
isc_uint32_t authlen;
omapi_data_t * authenticator;
isc_uint32_t authid;
isc_uint32_t op;
omapi_handle_t h;
isc_uint32_t id;
isc_uint32_t rid;
};
struct omapi_connection {
OMAPI_OBJECT_PREAMBLE;
/*
* The wait lock is necessary to ensure that connection_wait is
* blocking for the signal before any event is received that might
* potentially free the connection. This ensures that end_connection
* will unblock connection_wait so that connection_wait can free
* the connection.
*
* Consider, for example, the problem that send_intro has without
* this lock. It first needs to call connection_require to start
* a recv task to get the server's intro. Then it needs to send
* the intro itself. One sample problem that can then arise from
* this is that the recv task completes before the wait is established
* and it triggers an error, such as an premature EOF or an unsupported
* version number in the header. The client would have no way of
* knowing an error occurred.
*
* Fortunately, there is no such problem in the server. Since all
* uses of the connection object happen from the socket thread,
* no function will continue to use a connection object after there
* has been an error on it, no other event can be posted until the
* current event handler is done, and all events subsequent to
* abandoning the connection will be ISC_R_CANCELED, so the event
* handlers will not try to use the connection object.
*
* XXXDCL the above comments are somewhat out of date.
*/
isc_mutex_t wait_lock;
isc_socket_t *socket;
isc_task_t *task;
/*
* The error that caused the connection to be freed.
*/
isc_result_t result;
/*
* Number of socket events outstanding. This should always be
* either 0 or 1 under the current model; having any more than
* one event pending at any given time complicates the thread
* locking issues.
*/
unsigned int events_pending;
/*
* Blocks connection_wait until the outstanding event completes.
*/
isc_condition_t waiter;
/*
* True if connection_wait is blocking on the water condition variable.
*/
isc_boolean_t waiting;
omapi_connection_state_t state;
/*
* These are set when a connection is made, but not currently used.
*/
isc_sockaddr_t remote_addr;
isc_sockaddr_t local_addr;
/*
* Bytes of input needed before wakeup.
*/
isc_uint32_t bytes_needed;
/*
* Bytes of input already buffered.
* XXXDCL use isc_bufferlist_available() instead?
*/
isc_uint32_t in_bytes;
isc_bufferlist_t input_buffers;
/*
* Bytes of output in output buffers.
*/
isc_uint32_t out_bytes;
isc_bufferlist_t output_buffers;
/*
* True if the connection was created by omapi_protocol_connect.
*/
isc_boolean_t is_client;
/*
* The listener that accepted the connection.
* XXXDCL (Means is_client is false, making is_client is somewhat
* redundant.)
*/
omapi_object_t * listener;
/*
* The server links known connections in a list at the connections
* member of the omapi_listener_t struct.
*/
ISC_LINK(omapi_connection_t) link;
};
struct omapi_protocol {
OMAPI_OBJECT_PREAMBLE;
isc_uint32_t header_size;
isc_uint32_t protocol_version;
isc_uint32_t next_xid;
omapi_object_t * authinfo; /* Default authinfo. */
omapi_protocol_state_t state; /* Input state. */
isc_boolean_t reading_message_values;
omapi_message_t * message; /* Incoming message. */
omapi_string_t * name; /* Incoming name. */
omapi_data_t * value; /* Incoming value. */
/*
* Authentication information.
*/
char * authname;
unsigned int algorithm;
isc_boolean_t auth_update;
isc_region_t *key;
isc_hmacmd5_t hmacctx;
isc_region_t signature_in;
isc_buffer_t *signature_out;
isc_result_t verify_result;
/*
* A callback to find out whether a requested key is valid on
* the connection, and the arg the caller wants to help it decide.
* Only gets set on the server side.
*/
isc_boolean_t ((*verify_key)(const char *name,
unsigned int algorithm,
void *key_arg));
void * verify_key_arg;
};
/*****
***** Private Global Library Variables.
*****/
extern omapi_objecttype_t *omapi_type_connection;
extern omapi_objecttype_t *omapi_type_listener;
extern omapi_objecttype_t *omapi_type_generic;
extern omapi_objecttype_t *omapi_type_protocol;
extern omapi_objecttype_t *omapi_type_message;
extern omapi_objecttype_t *omapi_object_types;
/*
* Everything needs a memory context.
*/
extern isc_mem_t *omapi_mctx;
/*
* Task to keep the omapi_taskmgr alive until omapi_lib_destroy is called.
*/
extern isc_task_t *omapi_task;
/*
* XXXDCL comment, localize?
*/
extern isc_taskmgr_t *omapi_taskmgr;
/*
* XXXDCL comment, localize?
*/
extern isc_socketmgr_t *omapi_socketmgr;
/*****
***** Convenience macros.
*****/
#define OBJECT_REF(objectp, object) \
omapi_object_reference((omapi_object_t **)objectp, \
(omapi_object_t *)object)
#define OBJECT_DEREF(objectp) \
omapi_object_dereference((omapi_object_t **)objectp)
#define PASS_CHECK(object, function) \
(object->inner != NULL && object->inner->type->function != NULL)
ISC_LANG_BEGINDECLS
/*
* Private library functions defined in auth.c.
*/
#define auth_destroy omapi__auth_destroy
void
auth_destroy(void);
#define auth_makekey omapi__auth_makekey
isc_result_t
auth_makekey(const char *name, unsigned int algorithm, isc_region_t **keyp);
/*
* Private library functions defined in connection.c.
*/
#define connection_init omapi__connection_init
isc_result_t
connection_init(void);
#define connect_toserver omapi__connect_toserver
isc_result_t
connect_toserver(omapi_object_t *connection, const char *server,
in_port_t port);
#define connection_send omapi__connection_send
isc_result_t
connection_send(omapi_connection_t *connection);
#define connection_require omapi__connection_require
isc_result_t
connection_require(omapi_connection_t *connection, unsigned int bytes);
#define connection_copyout omapi__connection_copyout
void
connection_copyout(unsigned char *data, omapi_connection_t *connection,
unsigned int length);
#define connection_getuint32 omapi__connection_getuint32
void
connection_getuint32(omapi_connection_t *c, isc_uint32_t *value);
#define connection_getuint16 omapi__connection_getuint16
void
connection_getuint16(omapi_connection_t *c, isc_uint16_t *value);
/*
* Private library functions defined in generic.c.
*/
#define generic_init omapi__generic_init
isc_result_t
generic_init(void);
/*
* Private functions defined in handle.c.
*/
#define object_gethandle omapi__object_gethandle
isc_result_t
object_gethandle(omapi_handle_t *handle, omapi_object_t *object);
#define handle_lookup omapi__handle_lookup
isc_result_t
handle_lookup(omapi_object_t **object, omapi_handle_t handle);
#define handle_destroy omapi__handle_destroy
void
handle_destroy(void);
/*
* Private library functions defined in listener.c.
*/
#define listener_init omapi__listener_init
isc_result_t
listener_init(void);
/*
* Private library functions defined in message.c.
*/
#define message_init omapi__message_init
isc_result_t
message_init(void);
#define message_process omapi__message_process
isc_result_t
message_process(omapi_object_t *message, omapi_object_t *protocol);
/*
* Private library functions defined in object.c.
*/
#define object_signal omapi__object_signal
isc_result_t
object_signal(omapi_object_t *handle, const char *name, ...);
#define object_vsignal omapi__object_vsignal
isc_result_t
object_vsignal(omapi_object_t *handle, const char *name, va_list ap);
#define object_stuffvalues omapi__object_stuffvalues
isc_result_t
object_stuffvalues(omapi_object_t *handle, omapi_object_t *object);
#define object_update omapi__object_update
isc_result_t
object_update(omapi_object_t *object, omapi_object_t *source,
omapi_handle_t handle);
#define object_findtype omapi__object_findtype
omapi_objecttype_t *
object_findtype(omapi_value_t *tv);
#define object_methodlookup omapi__object_methodlookup
isc_result_t
object_methodlookup(omapi_objecttype_t *type, omapi_object_t **object,
omapi_object_t *key);
#define object_methodcreate omapi__object_methodcreate
isc_result_t
object_methodcreate(omapi_objecttype_t *type, omapi_object_t **object);
#define object_methodexpunge omapi__object_methodexpunge
isc_result_t
object_methodexpunge(omapi_objecttype_t *type, omapi_object_t *object);
#define object_destroytypes omapi__object_destroytypes
void
object_destroytypes(void);
/*
* Private library functions defined in protocol.c.
*/
#define protocol_init omapi__protocol_init
isc_result_t
protocol_init(void);
#define send_intro omapi__send_intro
isc_result_t
send_intro(omapi_object_t *object, unsigned int version);
#define send_status omapi__send_status
isc_result_t
send_status(omapi_object_t *protcol, isc_result_t waitstatus,
unsigned int response_id, const char *message);
#define send_update omapi__send_update
isc_result_t
send_update(omapi_object_t *protocol, unsigned int response_id,
omapi_object_t *object);
ISC_LANG_ENDDECLS
#endif /* OMAPI_PRIVATE_H */

View File

@ -1,46 +0,0 @@
/*
* Copyright (C) 1999-2001 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.
*/
/* $Id: result.h,v 1.8 2001/01/09 22:00:30 bwelling Exp $ */
#ifndef OMAPI_RESULT_H
#define OMAPI_RESULT_H 1
#include <isc/lang.h>
#include <isc/result.h> /* Contractual promise. */
#include <isc/resultclass.h>
ISC_LANG_BEGINDECLS
#define OMAPI_R_NOTYET (ISC_RESULTCLASS_OMAPI + 0)
#define OMAPI_R_NOTCONNECTED (ISC_RESULTCLASS_OMAPI + 1)
#define OMAPI_R_NOKEYS (ISC_RESULTCLASS_OMAPI + 2)
#define OMAPI_R_INVALIDARG (ISC_RESULTCLASS_OMAPI + 3)
#define OMAPI_R_VERSIONMISMATCH (ISC_RESULTCLASS_OMAPI + 4)
#define OMAPI_R_PROTOCOLERROR (ISC_RESULTCLASS_OMAPI + 5)
#define OMAPI_R_NRESULTS 6 /* Number of results */
const char *
omapi_result_totext(isc_result_t);
void
omapi_result_register(void);
ISC_LANG_ENDDECLS
#endif /* OMAPI_RESULT_H */

View File

@ -1,46 +0,0 @@
/*
* Copyright (C) 1996-2001 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.
*/
/* $Id: types.h,v 1.8 2001/01/09 22:00:31 bwelling Exp $ */
#ifndef OMAPI_TYPES_H
#define OMAPI_TYPES_H 1
/*****
***** Type definitions.
*****/
/*
* These structures are all opaque; they are fully defined in private.h
* for use only by the internal library. If there is a need to get
* at their internal data for some purpose, new APIs can be added for that.
*/
typedef unsigned int omapi_handle_t;
typedef struct omapi_object omapi_object_t;
typedef struct omapi_objecttype omapi_objecttype_t;
typedef struct omapi_data omapi_data_t;
typedef struct omapi_string omapi_string_t;
typedef struct omapi_value omapi_value_t;
typedef enum {
omapi_datatype_int,
omapi_datatype_string,
omapi_datatype_data,
omapi_datatype_object
} omapi_datatype_t;
#endif /* OMAPI_TYPES_H */

View File

@ -1,140 +0,0 @@
/*
* Copyright (C) 1999-2001 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.
*/
/* $Id: lib.c,v 1.15 2001/02/16 04:14:16 tale Exp $ */
#include <config.h>
#include <stddef.h>
#include <isc/msgcat.h>
#include <isc/once.h>
#include <isc/task.h>
#include <isc/util.h>
#include <omapi/lib.h>
#include <omapi/private.h>
/***
*** Library Globals.
***/
isc_msgcat_t *omapi_msgcat = NULL;
omapi_objecttype_t *omapi_type_connection;
omapi_objecttype_t *omapi_type_listener;
omapi_objecttype_t *omapi_type_generic;
omapi_objecttype_t *omapi_type_protocol;
omapi_objecttype_t *omapi_type_message;
omapi_objecttype_t *omapi_object_types;
isc_mem_t *omapi_mctx;
isc_task_t *omapi_task;
isc_taskmgr_t *omapi_taskmgr;
isc_socketmgr_t *omapi_socketmgr;
/***
*** Private to lib.c.
***/
static isc_once_t msgcat_once = ISC_ONCE_INIT;
/***
*** Functions.
***/
static void
open_msgcat(void) {
isc_msgcat_open("libomapi.cat", &omapi_msgcat);
}
void
omapi_lib_initmsgcat(void) {
/*
* Initialize the OMAPI library's message catalog, omapi_msgcat, if it
* has not already been initialized.
*/
RUNTIME_CHECK(isc_once_do(&msgcat_once, open_msgcat) == ISC_R_SUCCESS);
}
isc_result_t
omapi_lib_init(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_socketmgr_t *socketmgr)
{
isc_result_t result;
/*
* Can only be called once without an intervening omapi_lib_destroy.
*/
REQUIRE(omapi_mctx == NULL &&
omapi_socketmgr == NULL &&
omapi_taskmgr == NULL &&
omapi_task == NULL &&
omapi_object_types == NULL);
REQUIRE(mctx != NULL && taskmgr != NULL && socketmgr != NULL);
omapi_mctx = mctx;
omapi_taskmgr = taskmgr;
omapi_socketmgr = socketmgr;
result = isc_task_create(omapi_taskmgr, 0, &omapi_task);
if (result == ISC_R_SUCCESS)
isc_task_setname(omapi_task, "omapi", NULL);
/*
* Initialize the standard object types.
*/
if (result == ISC_R_SUCCESS)
result = generic_init();
if (result == ISC_R_SUCCESS)
result = listener_init();
if (result == ISC_R_SUCCESS)
result = connection_init();
if (result == ISC_R_SUCCESS)
result = protocol_init();
if (result == ISC_R_SUCCESS)
result = message_init();
return (result);
}
/*
* This does not free connections and other in-use objects, only the
* things created by omapi_lib_init(). It is the callers responsibility to
* free the other things (as via omapi_connection_disconnect or
* omapi_object_dereference).
*/
void
omapi_lib_destroy(void) {
object_destroytypes();
handle_destroy();
auth_destroy();
isc_task_destroy(&omapi_task);
omapi_mctx = NULL;
omapi_socketmgr = NULL;
omapi_taskmgr = NULL;
}

View File

@ -1,506 +0,0 @@
/*
* Copyright (C) 1996-2001 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.
*/
/* $Id: listener.c,v 1.32 2001/01/09 22:00:01 bwelling Exp $ */
/*
* Subroutines that support the generic listener object.
*/
#include <config.h>
#include <stdlib.h> /* NULL and abort() */
#include <isc/buffer.h>
#include <isc/bufferlist.h>
#include <isc/mem.h>
#include <isc/string.h>
#include <isc/task.h>
#include <isc/util.h>
#include <omapi/private.h>
typedef struct omapi_listener_object {
OMAPI_OBJECT_PREAMBLE;
isc_mutex_t mutex;
isc_task_t *task;
isc_socket_t *socket; /* Listening socket. */
isc_boolean_t (*verify_connection)(isc_sockaddr_t *sockaddr,
void *connect_arg);
isc_boolean_t (*verify_key)(const char *name, unsigned int algorithm,
void *key_arg);
void *callback_arg;
/*
* Locked by mutex.
*/
isc_boolean_t listening;
ISC_LIST(omapi_connection_t) connections;
} omapi_listener_t;
static void
free_listener(omapi_listener_t *listener) {
/*
* Break the link between the listener object and its parent
* (usually a generic object); this is done so the server's
* reference to its managing object does not prevent the
* listener object from being destroyed.
*/
OBJECT_DEREF(&listener->inner->outer);
OBJECT_DEREF(&listener->inner);
/*
* The listener object can now be freed.
*/
OBJECT_DEREF(&listener);
}
/*
* Reader callback for a listener object. Accept an incoming connection.
*/
static void
listener_accept(isc_task_t *task, isc_event_t *event) {
isc_result_t result;
isc_buffer_t *ibuffer = NULL;
isc_buffer_t *obuffer = NULL;
isc_task_t *connection_task = NULL;
isc_socket_t *sock;
isc_sockaddr_t sockaddr;
omapi_connection_t *connection = NULL;
omapi_protocol_t *protocol = NULL;
omapi_listener_t *listener;
/*
* XXXDCL audit error handling
*/
result = ((isc_socket_newconnev_t *)event)->result;
sock = ((isc_socket_newconnev_t *)event)->newsocket;
listener = (omapi_listener_t *)event->ev_arg;
/*
* No more need for the event, once all the desired data has been
* used from it.
*/
isc_event_free(&event);
if (result == ISC_R_CANCELED) {
/*
* omapi_listener_shutdown was called.
*/
LOCK(&listener->mutex);
listener->listening = ISC_FALSE;
if (ISC_LIST_HEAD(listener->connections) == NULL) {
UNLOCK(&listener->mutex);
free_listener(listener);
} else {
/*
* All connections this listener was responsible for
* must be removed.
*
* XXXDCL
* Since it is possible that this shutdown was
* triggered by one of the clients, it would be nice
* to give it a little time to exit, as well as allow
* any other connections to finish up cleanly.
* Unfortunately, since this could be called in the
* task/event thread of a program (as it is in named),
* no other events can be delivered while this routine
* blocks, so a loop to use isc_condition_waituntil
* until all of the connections are gone is pointless.
*/
for (connection = ISC_LIST_HEAD(listener->connections);
connection != NULL;
connection = ISC_LIST_NEXT(connection, link))
omapi_connection_disconnect((omapi_object_t *)
connection,
OMAPI_FORCE_DISCONNECT);
UNLOCK(&listener->mutex);
}
return;
}
/*
* Set up another accept task for the socket.
*/
isc_socket_accept(listener->socket, task, listener_accept, listener);
/*
* Check for the validity of new connection event.
* If the result is not ISC_R_SUCCESS, what can really
* be done about it other than just flunking out of here?
*/
if (result != ISC_R_SUCCESS)
return;
/*
* Is the connection from a valid host?
*/
result = isc_socket_getpeername(sock, &sockaddr);
if (result != ISC_R_SUCCESS ||
!listener->verify_connection(&sockaddr, listener->callback_arg)) {
/*
* Permission denied. Close the connection.
* XXXDCL isc_log_write an error.
*/
isc_socket_detach(&sock);
return;
}
/*
* The new connection is good to go. Allocate the buffers for it and
* prepare its own task.
*/
if (isc_task_create(omapi_taskmgr, 0, &connection_task) !=
ISC_R_SUCCESS)
goto free_task;
ibuffer = NULL;
result = isc_buffer_allocate(omapi_mctx, &ibuffer, OMAPI_BUFFER_SIZE);
if (result != ISC_R_SUCCESS)
goto free_ibuffer;
obuffer = NULL;
result = isc_buffer_allocate(omapi_mctx, &obuffer, OMAPI_BUFFER_SIZE);
if (result != ISC_R_SUCCESS)
goto free_obuffer;
/*
* Create a new connection object.
*/
result = omapi_object_create((omapi_object_t **)&connection,
omapi_type_connection, sizeof(*connection));
if (result != ISC_R_SUCCESS)
goto free_obuffer;
connection->task = connection_task;
connection->state = omapi_connection_connected;
connection->socket = sock;
connection->is_client = ISC_FALSE;
ISC_LIST_INIT(connection->input_buffers);
ISC_LIST_APPEND(connection->input_buffers, ibuffer, link);
ISC_LIST_INIT(connection->output_buffers);
ISC_LIST_APPEND(connection->output_buffers, obuffer, link);
ISC_LINK_INIT(connection, link);
/*
* Create a new protocol object to oversee the handling of this
* connection.
*/
protocol = NULL;
result = omapi_object_create((omapi_object_t **)&protocol,
omapi_type_protocol,
sizeof(omapi_protocol_t));
if (result != ISC_R_SUCCESS)
goto free_connection_object;
/*
* Hand off the key verification information to the protocol object.
*/
protocol->verify_key = listener->verify_key;
protocol->verify_key_arg = listener->callback_arg;
/*
* Tie the protocol object bidirectionally to the connection
* object, with the connection as the outer object.
*/
OBJECT_REF(&protocol->outer, connection);
OBJECT_REF(&connection->inner, protocol);
/*
* Lose the external reference to the protocol object so both the
* connection object and protocol object will be freed when the
* connection ends.
*/
OBJECT_DEREF(&protocol);
/*
* Add the connection to the list of connections known by the
* listener. This is an added reference to the connection
* object, but since there's no easy way to use omapi_object_reference
* with the ISC_LIST macros, that reference is just not counted.
*/
LOCK(&listener->mutex);
ISC_LIST_APPEND(listener->connections, connection, link);
UNLOCK(&listener->mutex);
/*
* Remember the listener that accepted the connection, so it
* can be told when the connection goes away.
*/
OBJECT_REF(&connection->listener, listener);
/*
* Send the introductory message. The return value does not
* matter; if send_intro failed, it already destroyed the connection.
*/
(void)send_intro(connection->inner, OMAPI_PROTOCOL_VERSION);
return;
free_connection_object:
/*
* Destroy the connection. This will free everything created
* in this function but the event, which was already freed.
*/
OBJECT_DEREF(&connection);
return;
/*
* Free resources that were being created for the connection object.
*/
free_obuffer:
isc_buffer_free(&obuffer);
free_ibuffer:
isc_buffer_free(&ibuffer);
free_task:
isc_task_destroy(&connection_task);
}
isc_result_t
omapi_listener_listen(omapi_object_t *manager, isc_sockaddr_t *addr,
isc_boolean_t ((*verify_connection)
(isc_sockaddr_t *incoming,
void *connect_arg)),
isc_boolean_t ((*verify_key)
(const char *name,
unsigned int algorithm,
void *key_arg)),
isc_taskaction_t destroy_action, void *arg)
{
isc_result_t result;
isc_task_t *task;
omapi_listener_t *listener;
REQUIRE(manager != NULL);
REQUIRE(addr != NULL && isc_sockaddr_getport(addr) != 0);
task = NULL;
result = isc_task_create(omapi_taskmgr, 0, &task);
if (result != ISC_R_SUCCESS)
return (result);
/*
* Create the listener object.
*/
listener = NULL;
result = omapi_object_create((omapi_object_t **)&listener,
omapi_type_listener, sizeof(*listener));
if (result != ISC_R_SUCCESS) {
isc_task_destroy(&task);
return (result);
}
listener->task = task;
RUNTIME_CHECK(isc_mutex_init(&listener->mutex) == ISC_R_SUCCESS);
ISC_LIST_INIT(listener->connections);
/*
* Create a socket on which to listen.
*/
listener->socket = NULL;
result = isc_socket_create(omapi_socketmgr, PF_INET,
isc_sockettype_tcp, &listener->socket);
if (result == ISC_R_SUCCESS)
result = isc_socket_bind(listener->socket, addr);
if (result == ISC_R_SUCCESS)
/*
* Now tell the kernel to listen for connections.
*/
result = isc_socket_listen(listener->socket, 0);
if (result == ISC_R_SUCCESS) {
/*
* Queue up the first accept event. The listener object
* will be passed to listener_accept() when it is called.
*/
listener->listening = ISC_TRUE;
result = isc_socket_accept(listener->socket, task,
listener_accept, listener);
}
if (result == ISC_R_SUCCESS) {
/*
* Tie the listener object to the calling object.
*/
OBJECT_REF(&manager->outer, listener);
OBJECT_REF(&listener->inner, manager);
/*
* The destroy action is not set until here because it should
* only be called if the listener was successfully set up.
*/
listener->destroy_action = destroy_action;
listener->destroy_arg = arg;
listener->verify_connection = verify_connection;
listener->verify_key = verify_key;
listener->callback_arg = arg;
} else {
/*
* Failed to set up the listener.
*/
listener->listening = ISC_FALSE;
OBJECT_DEREF(&listener);
}
return (result);
}
void
omapi_listener_shutdown(omapi_object_t *listener) {
omapi_listener_t *l;
REQUIRE((listener != NULL && listener->type == omapi_type_listener) ||
(listener->outer != NULL &&
listener->outer->type == omapi_type_listener));
if (listener->type == omapi_type_listener)
l = (omapi_listener_t *)listener;
else
l = (omapi_listener_t *)listener->outer;
/*
* It is improper to call this function without having had a successful
* run of omapi_listener_listen.
*/
REQUIRE(l->socket != NULL && l->task != NULL);
/*
* Stop accepting connections.
*/
isc_socket_cancel(l->socket, NULL, ISC_SOCKCANCEL_ACCEPT);
}
static isc_result_t
listener_setvalue(omapi_object_t *listener, omapi_string_t *name,
omapi_data_t *value)
{
/*
* Nothing meaningful can be set in a listener object; just
* continue the call through the object chain.
*/
REQUIRE(listener != NULL && listener->type == omapi_type_listener);
return (omapi_object_passsetvalue(listener, name, value));
}
static isc_result_t
listener_getvalue(omapi_object_t *listener, omapi_string_t *name,
omapi_value_t **value)
{
/*
* Nothing meaningful can be fetched from a listener object; just
* continue the call through the object chain.
*/
REQUIRE(listener != NULL && listener->type == omapi_type_listener);
return (omapi_object_passgetvalue(listener, name, value));
}
static void
listener_destroy(omapi_object_t *listener) {
omapi_listener_t *l;
REQUIRE(listener != NULL && listener->type == omapi_type_listener);
l = (omapi_listener_t *)listener;
LOCK(&l->mutex);
INSIST(ISC_LIST_EMPTY(l->connections));
UNLOCK(&l->mutex);
DESTROYLOCK(&l->mutex);
if (l->task != NULL)
isc_task_destroy(&l->task);
if (l->socket != NULL)
isc_socket_detach(&l->socket);
}
static isc_result_t
listener_signalhandler(omapi_object_t *listener, const char *name, va_list ap)
{
omapi_connection_t *c;
omapi_listener_t *l;
isc_result_t result;
REQUIRE(listener != NULL && listener->type == omapi_type_listener);
l = (omapi_listener_t *)listener;
/*
* free_connection() signals the listener when one of the connections
* it accepted has gone away.
*/
if (strcmp(name, "disconnect") == 0) {
c = va_arg(ap, omapi_connection_t *);
LOCK(&l->mutex);
ISC_LIST_UNLINK(l->connections, c, link);
if (! l->listening && ISC_LIST_HEAD(l->connections) == NULL) {
/*
* The listener has been shutdown and the last
* connection was received.
*/
UNLOCK(&l->mutex);
free_listener(l);
} else
UNLOCK(&l->mutex);
result = ISC_R_SUCCESS;
} else
result = omapi_object_passsignal(listener, name, ap);
return (result);
}
/*
* Write all the published values associated with the object through the
* specified connection.
*/
static isc_result_t
listener_stuffvalues(omapi_object_t *connection, omapi_object_t *listener)
{
REQUIRE(listener != NULL && listener->type == omapi_type_listener);
return (omapi_object_passstuffvalues(connection, listener));
}
isc_result_t
listener_init(void) {
return (omapi_object_register(&omapi_type_listener, "listener",
listener_setvalue,
listener_getvalue,
listener_destroy,
listener_signalhandler,
listener_stuffvalues,
NULL, NULL, NULL));
}

View File

@ -1,946 +0,0 @@
/*
* Copyright (C) 1996-2001 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.
*/
/* $Id: message.c,v 1.30 2001/02/15 19:44:43 bwelling Exp $ */
/*
* Subroutines for dealing with message objects.
*/
#include <config.h>
#include <stddef.h>
#include <isc/buffer.h>
#include <isc/string.h>
#include <isc/util.h>
#include <omapi/private.h>
#include <omapi/result.h>
omapi_message_t *registered_messages;
isc_result_t
omapi_message_create(omapi_object_t **o) {
omapi_message_t *message = NULL;
omapi_object_t *g;
isc_result_t result;
result = omapi_object_create((omapi_object_t **)&message,
omapi_type_message, sizeof(*message));
if (result != ISC_R_SUCCESS)
return (result);
g = NULL;
result = omapi_object_create(&g, NULL, 0);
if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&message);
return (result);
}
OBJECT_REF(&message->inner, g);
OBJECT_REF(&g->outer, message);
OBJECT_REF(o, message);
OBJECT_DEREF(&message);
OBJECT_DEREF(&g);
return (result);
}
/*
* XXXDCL Make register/unregister implicitly part of omapi_message_send?
*/
void
omapi_message_register(omapi_object_t *h) {
omapi_message_t *m;
REQUIRE(h != NULL && h->type == omapi_type_message);
m = (omapi_message_t *)h;
/*
* Already registered?
*/
REQUIRE(m->prev == NULL && m->next == NULL &&
registered_messages != m);
if (registered_messages != NULL) {
OBJECT_REF(&m->next, registered_messages);
OBJECT_REF(&registered_messages->prev, m);
OBJECT_DEREF(&registered_messages);
}
OBJECT_REF(&registered_messages, m);
}
void
omapi_message_unregister(omapi_object_t *h) {
omapi_message_t *m;
omapi_message_t *n;
REQUIRE(h != NULL && h->type == omapi_type_message);
m = (omapi_message_t *)h;
/*
* Not registered?
*/
REQUIRE(m->prev != NULL || registered_messages == m);
n = NULL;
if (m->next != NULL) {
OBJECT_REF(&n, m->next);
OBJECT_DEREF(&m->next);
}
if (m->prev != NULL) {
omapi_message_t *tmp = NULL;
OBJECT_REF(&tmp, m->prev);
OBJECT_DEREF(&m->prev);
if (tmp->next != NULL)
OBJECT_DEREF(&tmp->next);
if (n != NULL)
OBJECT_REF(&tmp->next, n);
OBJECT_DEREF(&tmp);
} else {
OBJECT_DEREF(&registered_messages);
if (n != NULL)
OBJECT_REF(&registered_messages, n);
}
if (n != NULL)
OBJECT_DEREF(&n);
}
isc_result_t
omapi_message_send(omapi_object_t *message, omapi_object_t *protocol) {
/*
* For this function, at least, generic objects have fully spelled
* names and special type objects have short names.
* XXXDCL It would be good to be more consistent about this throughout
* the omapi library code.
*/
omapi_protocol_t *p;
omapi_connection_t *c;
omapi_message_t *m;
omapi_object_t *connection;
unsigned int authlen = 0;
isc_result_t result = ISC_R_SUCCESS;
REQUIRE(message != NULL && message->type == omapi_type_message);
/*
* Allow the function to be called with an object that is managing
* the client side.
*/
REQUIRE((protocol != NULL && protocol->type == omapi_type_protocol) ||
(protocol->outer != NULL &&
protocol->outer->type == omapi_type_protocol));
if (protocol->type != omapi_type_protocol)
protocol = protocol->outer;
p = (omapi_protocol_t *)protocol;
connection = (omapi_object_t *)(protocol->outer);
c = (omapi_connection_t *)connection;
INSIST(connection != NULL &&
connection->type == omapi_type_connection);
m = (omapi_message_t *)message;
if (p->key != NULL) {
isc_hmacmd5_init(&p->hmacctx, p->key->base, p->key->length);
authlen = ISC_MD5_DIGESTLENGTH;
p->auth_update = ISC_TRUE;
}
if (result == ISC_R_SUCCESS)
/* XXXTL Write the ID of the authentication key we're using. */
result = omapi_connection_putuint32(connection, 0);
if (result == ISC_R_SUCCESS)
result = omapi_connection_putuint32(connection, authlen);
if (result == ISC_R_SUCCESS)
/*
* Write the opcode.
*/
result = omapi_connection_putuint32(connection, m->op);
if (result == ISC_R_SUCCESS)
/*
* Write the handle. If we've been given an explicit handle,
* use that. Otherwise, use the handle of the object we're
* sending. The caller is responsible for arranging for one of
* these handles to be set (or not).
*/
result = omapi_connection_putuint32(connection,
(m->h ? m->h
: (m->object ?
m->object->handle
: 0)));
if (result == ISC_R_SUCCESS) {
/*
* Set and write the transaction ID.
*/
m->id = p->next_xid++;
result = omapi_connection_putuint32(connection, m->id);
}
if (result == ISC_R_SUCCESS)
/*
* Write the transaction ID of the message to which this is a
* response.
*/
result = omapi_connection_putuint32(connection, m->rid);
if (result == ISC_R_SUCCESS)
/*
* Stuff out the name/value pairs specific to this message.
*/
result = object_stuffvalues(connection, message);
if (result == ISC_R_SUCCESS)
/*
* Write the zero-length name that terminates the list of
* name/value pairs specific to the message.
*/
result = omapi_connection_putuint16(connection, 0);
if (result == ISC_R_SUCCESS && m->object != NULL)
/*
* Stuff out all the published name/value pairs in the object
* that's being sent in the message, if there is one.
*/
result = object_stuffvalues(connection, m->object);
if (result == ISC_R_SUCCESS)
/*
* Write the zero-length name length value that terminates
* the list of name/value pairs for the associated object.
*/
result = omapi_connection_putuint16(connection, 0);
if (result == ISC_R_SUCCESS && p->key != NULL) {
isc_region_t r;
isc_buffer_clear(p->signature_out);
INSIST(isc_buffer_availablelength(p->signature_out) >=
ISC_MD5_DIGESTLENGTH);
isc_hmacmd5_sign(&p->hmacctx,
isc_buffer_base(p->signature_out));
isc_hmacmd5_invalidate(&p->hmacctx);
isc_buffer_region(p->signature_out, &r);
p->auth_update = ISC_FALSE;
if (result == ISC_R_SUCCESS)
result = omapi_connection_putmem(connection,
r.base, r.length);
}
/*
* Prime the bytes_needed for the server's reply message.
* There is no need to lock. In the server everything happens in
* the socket thread so only one event function is running at a time,
* and in the client, there should be no events outstanding which
* would cause the socket thread to access this variable .
*/
if (result == ISC_R_SUCCESS) {
INSIST(c->bytes_needed == 0);
c->bytes_needed = p->header_size;
result = connection_send(c);
/*
* The client waited for the result; the server did not.
* The server's result will always be ISC_R_SUCCESS.
*
* If the client's result is not ISC_R_SUCCESS, the connection
* was already closed by the socket event handler that got
* the error. Unfortunately, it is not known whether
* it was send_done or recv_done that ended the connection;
* if the connection object were not destroyed, one way it
* could be inferred is by seeing whether connection->out_bytes
* is 0.
*
* XXXDCL "connection disconnected"
*/
if (result != ISC_R_SUCCESS)
object_signal(message, "status", result, NULL);
} else if (c->is_client) {
/*
* One of the calls to omapi_connection_put* or to
* object_stuffvalues failed. As of the time of writing
* this comment, that would pretty much only happen if
* the required output buffer space could be dynamically
* allocated.
*
* The server is in recv_done; let the error propagate back up
* the stack to there, and it will close the connection safely.
* If the server tried to free the connection here, recv_done
* wouldn't be able to distinguish the error from errors
* coming out of parts of the library that did not destroy
* the connection.
*
* The client needs the connection destroyed right here,
* because control is about to return to the driving thread
* and it is guaranteed that if omapi_message_send returns
* an error for any reason, then the connection will be gone.
* Otherwise the client would have the same problem described
* for recv_done on the server -- it wouldn't be able to tell
* whether the error freed the connection.
*/
omapi_connection_disconnect(connection,
OMAPI_FORCE_DISCONNECT);
/*
* The client also needs to be notified the message
* never got sent.
*
* XXXDCL "message not sent; connection disconnected"
*/
object_signal(message, "status", result, NULL);
}
return (result);
}
isc_result_t
message_process(omapi_object_t *mo, omapi_object_t *po) {
omapi_message_t *message, *m;
omapi_object_t *object = NULL;
omapi_objecttype_t *type = NULL;
omapi_protocol_t *protocol;
omapi_connection_t *connection;
omapi_value_t *tv = NULL;
unsigned long create, update, exclusive;
isc_result_t result, waitstatus;
REQUIRE(mo != NULL && mo->type == omapi_type_message);
REQUIRE(po != NULL);
message = (omapi_message_t *)mo;
protocol = (omapi_protocol_t *)po;
INSIST(po->outer != NULL && po->outer->type == omapi_type_connection);
/*
* Note that the checking of connection->is_client throughout this
* function pretty much means that peer-to-peer transactions can't
* happen over a single connection. It is not clear, yet, whether that
* is such a bad thing, but the original design document didn't
* specify that particular operations were only valid on the client
* or on the server.
*/
connection = (omapi_connection_t *)po->outer;
if (message->rid != 0) {
for (m = registered_messages; m != NULL; m = m->next)
if (m->id == message->rid)
break;
/*
* If we don't have a real message corresponding to
* the message ID to which this message claims it is a
* response, something's fishy.
*/
if (m == NULL)
return (ISC_R_NOTFOUND);
} else
m = NULL;
if (protocol->key != NULL) {
if (protocol->signature_in.length < ISC_MD5_DIGESTLENGTH ||
!isc_hmacmd5_verify(&protocol->hmacctx,
protocol->signature_in.base))
protocol->verify_result = ISC_R_FAILURE;
isc_hmacmd5_invalidate(&protocol->hmacctx);
if (protocol->verify_result != ISC_R_SUCCESS) {
if (connection->is_client) {
INSIST(m != NULL);
result = omapi_object_setstring(mo, "message",
"failed to verify signature");
if (result == ISC_R_SUCCESS)
(void)omapi_object_getvalue(mo,
"message",
&tv);
object_signal((omapi_object_t *)m, "status",
protocol->verify_result, tv);
if (tv != NULL)
omapi_value_dereference(&tv);
/*
* This keeps the connection from being blown
* away, although it seems fairly reasonable
* to force a disconnect.
*/
return (ISC_R_SUCCESS);
} else
/*
* XXXDCL Should the key be stricken?
* The curious thing about the way this
* is currently set up is that the status
* message won't verify on the client if
* the secret was wrong ... so rather than
* getting processed in OMAPI_OP_STATUS
* below, it will be handled by this ``if''
* statement on the client.
*/
return (send_status(po,
protocol->verify_result,
message->id,
"failed to verify "
"signature"));
}
}
switch (message->op) {
case OMAPI_OP_OPEN:
if (connection->is_client)
return (ISC_R_UNEXPECTED);
if (m != NULL) {
return (send_status(po, OMAPI_R_INVALIDARG,
message->id,
"OPEN can't be a response"));
}
/*
* Get the type of the requested object, if one was
* specified.
*
* In this and subsequent calls to omapi_object_getvalue,
* an error could be returned, typically ISC_R_NOMEMORY.
* send_status *might* fail if the problem is being out
* of memory ... but it is worth a shot.
*/
result = omapi_object_getvalue(mo, "type", &tv);
if (result == ISC_R_SUCCESS) {
if (tv->value->type == omapi_datatype_data ||
tv->value->type == omapi_datatype_string)
type = object_findtype(tv);
omapi_value_dereference(&tv);
} else if (result == ISC_R_NOTFOUND)
type = NULL;
else
return (send_status(po, result, message->id,
isc_result_totext(result)));
/*
* Get the create flag.
*/
result = omapi_object_getvalue(mo, "create", &tv);
if (result == ISC_R_SUCCESS) {
create = omapi_value_getint(tv);
omapi_value_dereference(&tv);
} else if (result == ISC_R_NOTFOUND)
create = 0;
else
return (send_status(po, result, message->id,
isc_result_totext(result)));
/*
* Get the update flag.
*/
result = omapi_object_getvalue(mo, "update", &tv);
if (result == ISC_R_SUCCESS) {
update = omapi_value_getint(tv);
omapi_value_dereference(&tv);
} else if (result == ISC_R_NOTFOUND)
update = 0;
else
return (send_status(po, result, message->id,
isc_result_totext(result)));
/*
* Get the exclusive flag.
*/
result = omapi_object_getvalue(mo, "exclusive", &tv);
if (result == ISC_R_SUCCESS) {
exclusive = omapi_value_getint(tv);
omapi_value_dereference(&tv);
} else if (result == ISC_R_NOTFOUND)
exclusive = 0;
else
return (send_status(po, result, message->id,
isc_result_totext(result)));
/*
* All messages except for the first attempt to set
* the dst key used by the protocol must be signed.
*/
#ifdef notyet /* not for 9.0.0 */
if (type != omapi_type_protocol && protocol->key == NULL)
return (send_status(po, ISC_R_NOPERM, message->id,
"unauthorized access"));
#endif /* notyet */
/*
* If we weren't given a type, look the object up with
* the handle.
*/
if (type == NULL) {
if (create != 0)
return (send_status(po, OMAPI_R_INVALIDARG,
message->id,
"type required on create"));
goto refresh;
}
if (message->object == NULL)
return (send_status(po, ISC_R_NOTFOUND, message->id,
"no lookup key specified"));
/*
* This is pretty hackish, a special case for an attempt
* to open the protocol object. It was done because
* under the current design of OMAPI, there just isn't
* a good way to set the authentication values. The
* connection object and protocol object are the only
* things that hold state on the server throughout the life
* of a particular connection, and the original design
* for lookup methods does not provide a way to identify
* the current protocol or connection object.
*
* To minimize the hackishness, at least the rest of
* the manipulation of the protocol object is done through
* the normal object interfaces, rather than having a
* a special block do the work directly. Small consolation.
*/
if (type == omapi_type_protocol) {
OBJECT_REF(&object, po);
result = ISC_R_SUCCESS;
} else
result = object_methodlookup(type, &object,
message->object);
if (result == ISC_R_NOTIMPLEMENTED)
return (send_status(po, result, message->id,
"unsearchable object type"));
if (result != ISC_R_SUCCESS &&
result != ISC_R_NOTFOUND &&
result != OMAPI_R_NOKEYS)
return (send_status(po, result, message->id,
"object lookup failed"));
/*
* If we didn't find the object and we aren't supposed to
* create it, return an error.
*/
if (result == ISC_R_NOTFOUND && create == 0) {
return (send_status(po, ISC_R_NOTFOUND, message->id,
"no object matches specification"));
}
/*
* If we found an object, we're supposed to be creating an
* object, and we're not supposed to have found an object,
* return an error.
*/
if (result == ISC_R_SUCCESS && create != 0 && exclusive != 0) {
OBJECT_DEREF(&object);
return (send_status(po, ISC_R_EXISTS, message->id,
"specified object already exists"));
}
/*
* If we're creating the object, do it now.
*/
if (object == NULL) {
result = object_methodcreate(type, &object);
if (result != ISC_R_SUCCESS)
return (send_status(po, result, message->id,
"can't create new object"));
}
/*
* If we're updating it, do so now.
*/
if (create != 0 || update != 0) {
result = object_update(object, message->object,
message->h);
if (result != ISC_R_SUCCESS) {
OBJECT_DEREF(&object);
return (send_status(po, result, message->id,
"can't update object"));
}
}
/*
* Now send the new contents of the object back in response.
*/
goto send;
case OMAPI_OP_REFRESH:
if (connection->is_client)
return (ISC_R_UNEXPECTED);
#ifdef notyet /* not for 9.0.0 */
if (protocol->key == NULL)
return (send_status(po, ISC_R_NOPERM, message->id,
"unauthorized access"));
#endif /* notyet */
refresh:
result = handle_lookup(&object, message->h);
if (result != ISC_R_SUCCESS)
return (send_status(po, result, message->id,
"no matching handle"));
send:
result = send_update(po, message->id, object);
OBJECT_DEREF(&object);
return (result);
case OMAPI_OP_UPDATE:
if (! connection->is_client)
return (send_status(po, OMAPI_R_INVALIDARG,
message->id,
"OMAPI_OP_UPDATE is not a "
"valid server operation"));
if (m->object != NULL)
OBJECT_REF(&object, m->object);
else {
result = handle_lookup(&object, message->h);
if (result != ISC_R_SUCCESS)
return (send_status(po, result, message->id,
"no matching handle"));
}
if (message->object != NULL)
result = object_update(object, message->object,
message->h);
else
result = ISC_R_SUCCESS;
OBJECT_DEREF(&object);
if (result != ISC_R_SUCCESS) {
if (message->rid == 0)
return (send_status(po, result, message->id,
"can't update object"));
if (m != NULL)
object_signal((omapi_object_t *)m,
"status", result, NULL);
return (ISC_R_SUCCESS);
}
if (message->rid == 0)
result = send_status(po, ISC_R_SUCCESS, message->id,
NULL);
if (m != NULL)
object_signal((omapi_object_t *)m, "status",
ISC_R_SUCCESS, NULL);
return (result);
case OMAPI_OP_NOTIFY:
return (send_status(po, ISC_R_NOTIMPLEMENTED, message->id,
"notify not implemented yet"));
case OMAPI_OP_STATUS:
if (! connection->is_client)
return (send_status(po, OMAPI_R_INVALIDARG,
message->id,
"OMAPI_OP_STATUS is not a "
"valid server operation"));
/*
* The return status of a request.
*/
if (m == NULL)
return (ISC_R_UNEXPECTED);
/*
* Get the wait status.
*/
result = omapi_object_getvalue(mo, "result", &tv);
if (result == ISC_R_SUCCESS) {
waitstatus = omapi_value_getint(tv);
omapi_value_dereference(&tv);
} else
waitstatus = ISC_R_UNEXPECTED;
result = omapi_object_getvalue(mo, "message", &tv);
object_signal((omapi_object_t *)m, "status", waitstatus, tv);
if (result == ISC_R_SUCCESS)
omapi_value_dereference(&tv);
/*
* Even if the two omapi_object_getvalue calls in this
* section returned errors, the operation is considered
* successful. XXXDCL (should it be?)
*/
return (ISC_R_SUCCESS);
case OMAPI_OP_DELETE:
if (connection->is_client)
return (ISC_R_UNEXPECTED);
if (protocol->key == NULL)
return (send_status(po, ISC_R_NOPERM, message->id,
"unauthorized delete"));
result = handle_lookup(&object, message->h);
if (result != ISC_R_SUCCESS)
return (send_status(po, result, message->id,
"no matching handle"));
result = object_methodexpunge(object->type, object);
if (result == ISC_R_NOTIMPLEMENTED)
return (send_status(po, ISC_R_NOTIMPLEMENTED,
message->id,
"no remove method for object"));
OBJECT_DEREF(&object);
return (send_status(po, result, message->id, NULL));
}
return (ISC_R_NOTIMPLEMENTED);
}
static isc_result_t
message_setvalue(omapi_object_t *h, omapi_string_t *name, omapi_data_t *value)
{
omapi_message_t *m;
REQUIRE(h != NULL && h->type == omapi_type_message);
m = (omapi_message_t *)h;
/*
* Can't set authlen.
*/
/*
* Can set authenticator, but the value must be typed data.
* XXXDCL (no longer meaningful)
*/
if (omapi_string_strcmp(name, "authenticator") == 0) {
if (m->authenticator != NULL)
omapi_data_dereference(&m->authenticator);
omapi_data_reference(&m->authenticator, value);
return (ISC_R_SUCCESS);
} else if (omapi_string_strcmp(name, "object") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_object);
if (m->object != NULL)
OBJECT_DEREF(&m->object);
OBJECT_REF(&m->object, value->u.object);
return (ISC_R_SUCCESS);
} else if (omapi_string_strcmp(name, "notify-object") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_object);
if (m->notify_object != NULL)
OBJECT_DEREF(&m->notify_object);
OBJECT_REF(&m->notify_object, value->u.object);
return (ISC_R_SUCCESS);
/*
* Can set authid, but it has to be an integer.
*/
} else if (omapi_string_strcmp(name, "authid") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->authid = value->u.integer;
return (ISC_R_SUCCESS);
/*
* Can set op, but it has to be an integer.
*/
} else if (omapi_string_strcmp(name, "op") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->op = value->u.integer;
return (ISC_R_SUCCESS);
/*
* Handle also has to be an integer.
*/
} else if (omapi_string_strcmp(name, "handle") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->h = value->u.integer;
return (ISC_R_SUCCESS);
/*
* Transaction ID has to be an integer.
*/
} else if (omapi_string_strcmp(name, "id") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->id = value->u.integer;
return (ISC_R_SUCCESS);
/*
* Remote transaction ID has to be an integer.
*/
} else if (omapi_string_strcmp(name, "rid") == 0) {
INSIST(value != NULL && value->type == omapi_datatype_int);
m->rid = value->u.integer;
return (ISC_R_SUCCESS);
}
/*
* Try to find some inner object that can take the value.
*/
return (omapi_object_passsetvalue(h, name, value));
}
static isc_result_t
message_getvalue(omapi_object_t *h, omapi_string_t *name,
omapi_value_t **value)
{
omapi_message_t *m;
REQUIRE(h != NULL && h->type == omapi_type_message);
m = (omapi_message_t *)h;
/*
* Look for values that are in the message data structure.
*/
if (omapi_string_strcmp(name, "authenticator") == 0) {
if (m->authenticator != NULL)
return (omapi_value_storedata(value, name,
m->authenticator));
else
return (ISC_R_NOTFOUND);
} else if (omapi_string_strcmp(name, "authlen") == 0)
return (omapi_value_storeint(value, name, (int)m->authlen));
else if (omapi_string_strcmp(name, "authid") == 0)
return (omapi_value_storeint(value, name, (int)m->authid));
else if (omapi_string_strcmp(name, "op") == 0)
return (omapi_value_storeint(value, name, (int)m->op));
else if (omapi_string_strcmp(name, "handle") == 0)
return (omapi_value_storeint(value, name, (int)m->h));
else if (omapi_string_strcmp(name, "id") == 0)
return (omapi_value_storeint(value, name, (int)m->id));
else if (omapi_string_strcmp(name, "rid") == 0)
return (omapi_value_storeint(value, name, (int)m->rid));
/*
* See if there's an inner object that has the value.
*/
return (omapi_object_passgetvalue(h, name, value));
}
static void
message_destroy(omapi_object_t *handle) {
omapi_message_t *message;
REQUIRE(handle != NULL && handle->type == omapi_type_message);
message = (omapi_message_t *)handle;
if (message->authenticator != NULL)
omapi_data_dereference(&message->authenticator);
INSIST(message->prev == NULL && message->next == NULL &&
registered_messages != message);
if (message->object != NULL)
OBJECT_DEREF(&message->object);
if (message->notify_object != NULL)
OBJECT_DEREF(&message->notify_object);
}
static isc_result_t
message_signalhandler(omapi_object_t *handle, const char *name, va_list ap) {
omapi_message_t *message;
REQUIRE(handle != NULL && handle->type == omapi_type_message);
message = (omapi_message_t *)handle;
/*
* XXXDCL It would make the client side a bit cleaner if when "status"
* is signalled, it sets both "waitresult" and "waittext" (or some
* such) in the OMAPI_OBJECT_PREAMBLE of both the message and
* the notify_object or regular object.
*/
if (strcmp(name, "status") == 0 &&
(message->object != NULL || message->notify_object != NULL)) {
if (message->notify_object != NULL)
return (object_vsignal(message->notify_object, name,
ap));
else
return (object_vsignal(message->object, name, ap));
}
return (omapi_object_passsignal(handle, name, ap));
}
/*
* Write all the published values associated with the object through the
* specified connection.
*/
static isc_result_t
message_stuffvalues(omapi_object_t *connection, omapi_object_t *message)
{
REQUIRE(message != NULL && message->type == omapi_type_message);
return (omapi_object_passstuffvalues(connection, message));
}
isc_result_t
message_init(void) {
return (omapi_object_register(&omapi_type_message, "message",
message_setvalue,
message_getvalue,
message_destroy,
message_signalhandler,
message_stuffvalues,
NULL, NULL, NULL));
}

View File

@ -1,598 +0,0 @@
/*
* Copyright (C) 1996-2001 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.
*/
/* $Id: object.c,v 1.23 2001/01/09 22:00:04 bwelling Exp $ */
/* Principal Author: Ted Lemon */
#include <config.h>
#include <isc/mem.h>
#include <isc/string.h>
#include <isc/task.h>
#include <isc/util.h>
#include <omapi/private.h>
struct omapi_objecttype {
const char * name;
omapi_objecttype_t * next;
isc_result_t (*set_value)(omapi_object_t *object,
omapi_string_t *name,
omapi_data_t *value);
isc_result_t (*get_value)(omapi_object_t *object,
omapi_string_t *name,
omapi_value_t **value);
void (*destroy)(omapi_object_t *object);
isc_result_t (*signal_handler)(omapi_object_t *object,
const char *name,
va_list args);
isc_result_t (*stuff_values)(omapi_object_t *connection,
omapi_object_t *object);
isc_result_t (*lookup)(omapi_object_t **object,
omapi_object_t *key);
isc_result_t (*create)(omapi_object_t **object);
isc_result_t (*expunge)(omapi_object_t *object);
};
isc_result_t
omapi_object_create(omapi_object_t **object, omapi_objecttype_t *type,
size_t size)
{
omapi_object_t *new;
REQUIRE(object != NULL && *object == NULL);
REQUIRE(size > 0 || type == NULL);
if (type == NULL) {
type = omapi_type_generic;
size = sizeof(omapi_generic_t);
}
new = isc_mem_get(omapi_mctx, size);
if (new == NULL)
return (ISC_R_NOMEMORY);
memset(new, 0, size);
new->object_size = size;
new->refcnt = 1;
new->type = type;
*object = new;
return (ISC_R_SUCCESS);
}
void
omapi_object_reference(omapi_object_t **r, omapi_object_t *h) {
REQUIRE(r != NULL && *r == NULL);
REQUIRE(h != NULL);
*r = h;
h->refcnt++;
}
void
omapi_object_dereference(omapi_object_t **h) {
int outer_reference = 0;
int inner_reference = 0;
int handle_reference = 0;
int extra_references;
omapi_object_t *p = NULL;
REQUIRE(h != NULL && *h != NULL);
REQUIRE((*h)->refcnt > 0);
/*
* See if this object's inner object refers back to it, but don't
* count this as a reference if we're being asked to free the
* reference from the inner object.
*/
/*
* XXXDCL my wording
* Note whether the object being dereferenced has an inner object, but
* only if the inner object's own outer pointer is not what is
* being dereferenced.
* (XXXDCL when does it happen that way ?)
*/
if ((*h)->inner != NULL && (*h)->inner->outer != NULL &&
h != &((*h)->inner->outer))
inner_reference = 1;
/*
* Ditto for the outer object.
*/
if ((*h)->outer != NULL && (*h)->outer->inner != NULL &&
h != &((*h)->outer->inner))
outer_reference = 1;
/*
* Ditto for the handle object. The code below assumes that
* the only reason we'd get a dereference from the handle
* table is if this function does it - otherwise we'd have to
* traverse the handle table to find the address where the
* reference is stored and compare against that, and we don't
* want to do that if we can avoid it.
*/
if ((*h)->handle != 0)
handle_reference = 1;
/*
* If we are getting rid of the last reference other than
* references to inner and outer objects, or from the handle
* table, then we must examine all the objects in either
* direction to see if they hold any non-inner, non-outer,
* non-handle-table references. If not, we need to free the
* entire chain of objects.
*/
INSIST((*h)->refcnt >=
inner_reference + outer_reference + handle_reference + 1);
if ((*h)->refcnt ==
inner_reference + outer_reference + handle_reference + 1) {
/*
* If refcnt is > 1, then inner_reference + outer_reference +
* handle_reference is > 0, so there are list references to
* chase.
*/
if ((*h)->refcnt > 1) {
/*
* XXXTL we could check for a reference from the
* handle table here.
*/
extra_references = 0;
if (inner_reference != 0)
for (p = (*h)->inner;
p != NULL && extra_references == 0;
p = p->inner) {
extra_references += p->refcnt - 1;
if (p->inner != NULL)
--extra_references;
if (p->handle != 0)
--extra_references;
}
if (outer_reference != 0)
for (p = (*h)->outer;
p != NULL && extra_references == 0;
p = p->outer) {
extra_references += p->refcnt - 1;
if (p->outer != NULL)
--extra_references;
if (p->handle != 0)
--extra_references;
}
} else
extra_references = 0;
if (extra_references == 0) {
isc_taskaction_t action = (*h)->destroy_action;
void *arg = (*h)->destroy_arg;
if (inner_reference != 0)
OBJECT_DEREF(&(*h)->inner);
if (outer_reference != 0)
OBJECT_DEREF(&(*h)->outer);
if ((*h)->type->destroy != NULL)
(*((*h)->type->destroy))(*h);
(*h)->refcnt = 0;
isc_mem_put(omapi_mctx, *h, (*h)->object_size);
if (action != NULL) {
isc_event_t *event;
event = isc_event_allocate(omapi_mctx, NULL,
OMAPI_EVENT_OBJECTFREED,
action, arg,
sizeof(isc_event_t));
if (event != NULL)
isc_task_send(omapi_task, &event);
}
} else
(*h)->refcnt--;
} else
(*h)->refcnt--;
*h = NULL;
}
isc_result_t
omapi_object_register(omapi_objecttype_t **type, const char *name,
isc_result_t (*set_value)(omapi_object_t *,
omapi_string_t *,
omapi_data_t *),
isc_result_t (*get_value)(omapi_object_t *,
omapi_string_t *,
omapi_value_t **),
void (*destroy)(omapi_object_t *),
isc_result_t (*signal_handler)(omapi_object_t *,
const char *, va_list),
isc_result_t (*stuff_values)(omapi_object_t *,
omapi_object_t *),
isc_result_t (*lookup)(omapi_object_t **,
omapi_object_t *),
isc_result_t (*create)(omapi_object_t **),
isc_result_t (*expunge)(omapi_object_t *))
{
omapi_objecttype_t *t;
t = isc_mem_get(omapi_mctx, sizeof(*t));
if (t == NULL)
return (ISC_R_NOMEMORY);
memset(t, 0, sizeof(*t));
t->name = name;
t->set_value = set_value;
t->get_value = get_value;
t->destroy = destroy;
t->signal_handler = signal_handler;
t->stuff_values = stuff_values;
t->lookup = lookup;
t->create = create;
t->expunge = expunge;
t->next = omapi_object_types;
omapi_object_types = t;
if (type != NULL)
*type = t;
return (ISC_R_SUCCESS);
}
omapi_objecttype_t *
object_findtype(omapi_value_t *tv) {
omapi_objecttype_t *type;
for (type = omapi_object_types; type != NULL; type = type->next)
if (omapi_data_strcmp(tv->value, type->name) == 0)
break;
return (type);
}
void
object_destroytypes(void) {
omapi_objecttype_t *type, *next_type;
for (type = omapi_object_types; type != NULL; type = next_type) {
next_type = type->next;
isc_mem_put(omapi_mctx, type, sizeof(*type));
}
omapi_object_types = NULL;
}
/*
* Call the signal method for an object chain, starting at the outermost
* object.
*/
isc_result_t
object_signal(omapi_object_t *handle, const char *name, ...) {
va_list ap;
omapi_object_t *outer;
isc_result_t result;
va_start(ap, name);
for (outer = handle; outer->outer != NULL; outer = outer->outer)
;
if (outer->type->signal_handler != NULL)
result = (*(outer->type->signal_handler))(outer, name, ap);
else
result = ISC_R_NOTFOUND;
va_end(ap);
return (result);
}
/*
* Call the signal method for the named object. Used by message_process().
*/
isc_result_t
object_vsignal(omapi_object_t *handle, const char *name, va_list ap) {
REQUIRE(handle != NULL);
if (handle->type->signal_handler != NULL)
return ((handle->type->signal_handler)(handle, name, ap));
else
return (ISC_R_NOTFOUND);
}
isc_result_t
omapi_object_set(omapi_object_t *h, omapi_string_t *name, omapi_data_t *value)
{
omapi_object_t *outer;
for (outer = h; outer->outer != NULL; outer = outer->outer)
;
if (outer->type->set_value != NULL)
return (*(outer->type->set_value))(outer, name, value);
return (ISC_R_NOTFOUND);
}
isc_result_t
omapi_object_setdata(omapi_object_t *h, const char *name, omapi_data_t *value)
{
omapi_string_t *nds;
isc_result_t result;
nds = NULL;
result = omapi_string_create(&nds, strlen(name));
if (result != ISC_R_SUCCESS)
return (result);
memcpy(nds->value, name, strlen(name));
return (omapi_object_set(h, nds, value));
}
isc_result_t
omapi_object_setboolean(omapi_object_t *h, const char *name,
isc_boolean_t value)
{
int boolean_value;
isc_result_t result;
omapi_data_t *tv = NULL;
omapi_string_t *n = NULL;
result = omapi_string_create(&n, strlen(name));
if (result != ISC_R_SUCCESS)
return (result);
memcpy(n->value, name, strlen(name));
boolean_value = (value == ISC_TRUE ? 1 : 0);
result = omapi_data_create(&tv, omapi_datatype_int, boolean_value);
if (result != ISC_R_SUCCESS) {
omapi_string_dereference(&n);
return (result);
}
result = omapi_object_set(h, n, tv);
omapi_string_dereference(&n);
omapi_data_dereference(&tv);
return (result);
}
isc_result_t
omapi_object_setinteger(omapi_object_t *h, const char *name, int value) {
isc_result_t result;
omapi_data_t *tv = NULL;
omapi_string_t *n = NULL;
result = omapi_string_create(&n, strlen(name));
if (result != ISC_R_SUCCESS)
return (result);
memcpy(n->value, name, strlen(name));
result = omapi_data_create(&tv, omapi_datatype_int, value);
if (result != ISC_R_SUCCESS) {
omapi_string_dereference(&n);
return (result);
}
result = omapi_object_set(h, n, tv);
omapi_string_dereference(&n);
omapi_data_dereference(&tv);
return (result);
}
isc_result_t
omapi_object_setobject(omapi_object_t *h, const char *name,
omapi_object_t *value)
{
isc_result_t result;
omapi_data_t *tv = NULL;
omapi_string_t *n = NULL;
result = omapi_string_create(&n, strlen(name));
if (result != ISC_R_SUCCESS)
return (result);
memcpy(n->value, name, strlen(name));
result = omapi_data_create(&tv, omapi_datatype_object, value);
if (result != ISC_R_SUCCESS) {
omapi_string_dereference(&n);
return (result);
}
result = omapi_object_set(h, n, tv);
omapi_string_dereference(&n);
omapi_data_dereference(&tv);
return (result);
}
isc_result_t
omapi_object_setstring(omapi_object_t *h, const char *name, const char *value)
{
isc_result_t result;
omapi_data_t *tv = NULL;
omapi_string_t *n = NULL;
result = omapi_string_create(&n, strlen(name));
if (result != ISC_R_SUCCESS)
return (result);
memcpy(n->value, name, strlen(name));
result = omapi_data_create(&tv, omapi_datatype_string, value);
if (result != ISC_R_SUCCESS) {
omapi_string_dereference(&n);
return (result);
}
result = omapi_object_set(h, n, tv);
omapi_string_dereference(&n);
omapi_data_dereference(&tv);
return (result);
}
isc_result_t
omapi_object_getvalue(omapi_object_t *h, const char *name,
omapi_value_t **value)
{
omapi_object_t *outer;
omapi_string_t *nds;
isc_result_t result;
nds = NULL;
result = omapi_string_create(&nds, strlen(name));
if (result != ISC_R_SUCCESS)
return (result);
memcpy(nds->value, name, strlen(name));
for (outer = h; outer->outer != NULL; outer = outer->outer)
;
if (outer->type->get_value != NULL)
result = (*(outer->type->get_value))(outer, nds, value);
else
result = ISC_R_NOTFOUND;
omapi_string_dereference(&nds);
return (result);
}
isc_result_t
object_stuffvalues(omapi_object_t *connection, omapi_object_t *object) {
omapi_object_t *outer;
for (outer = object; outer->outer != NULL; outer = outer->outer)
;
if (outer->type->stuff_values != NULL)
return ((*(outer->type->stuff_values))(connection, outer));
return (ISC_R_NOTFOUND);
}
isc_result_t
object_update(omapi_object_t *obj, omapi_object_t *src, omapi_handle_t handle)
{
omapi_generic_t *gsrc;
isc_result_t result;
unsigned int i;
REQUIRE(src != NULL);
if (src->type != omapi_type_generic)
return (ISC_R_NOTIMPLEMENTED);
gsrc = (omapi_generic_t *)src;
for (i = 0; i < gsrc->nvalues; i++) {
result = omapi_object_set(obj,
gsrc->values[i]->name,
gsrc->values[i]->value);
if (result != ISC_R_SUCCESS)
return (result);
}
if (handle != 0)
omapi_object_setinteger(obj, "remote-handle", (int)handle);
result = object_signal(obj, "updated");
if (result != ISC_R_NOTFOUND)
return (result);
return (ISC_R_SUCCESS);
}
isc_result_t
omapi_object_passgetvalue(omapi_object_t *object, omapi_string_t *name,
omapi_value_t **value)
{
if (PASS_CHECK(object, get_value))
return (*(object->inner->type->get_value))(object->inner,
name, value);
else
return (ISC_R_NOTFOUND);
}
isc_result_t
omapi_object_passsetvalue(omapi_object_t *object, omapi_string_t *name,
omapi_data_t *value)
{
if (PASS_CHECK(object, set_value))
return (*(object->inner->type->set_value))(object->inner,
name, value);
else
return (ISC_R_NOTFOUND);
}
isc_result_t
omapi_object_passsignal(omapi_object_t *object, const char *name, va_list ap) {
if (PASS_CHECK(object, signal_handler))
return (*(object->inner->type->signal_handler))(object->inner,
name, ap);
else
return (ISC_R_NOTFOUND);
}
isc_result_t
omapi_object_passstuffvalues(omapi_object_t *connection,
omapi_object_t *object)
{
if (PASS_CHECK(object, stuff_values))
return (*(object->inner->type->stuff_values))(connection,
object->inner);
else
return (ISC_R_SUCCESS);
}
isc_result_t
object_methodlookup(omapi_objecttype_t *type, omapi_object_t **object,
omapi_object_t *key)
{
if (type->lookup != NULL)
return ((*(type->lookup))(object, key));
else
return (ISC_R_NOTIMPLEMENTED);
}
isc_result_t
object_methodcreate(omapi_objecttype_t *type, omapi_object_t **object) {
if (type->create != NULL)
return ((*(type->create))(object));
else
return (ISC_R_NOTIMPLEMENTED);
}
isc_result_t
object_methodexpunge(omapi_objecttype_t *type, omapi_object_t *object) {
if (type->expunge != NULL)
return ((*(type->expunge))(object));
else
return (ISC_R_NOTIMPLEMENTED);
}

View File

@ -1,812 +0,0 @@
/*
* Copyright (C) 1996-2001 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.
*/
/* $Id: protocol.c,v 1.37 2001/03/14 17:59:25 halley Exp $ */
/*
* Functions supporting the object management protocol.
*/
#include <config.h>
#include <stddef.h> /* NULL */
#include <stdlib.h> /* random */
#include <isc/buffer.h>
#include <isc/mem.h>
#include <isc/string.h>
#include <isc/util.h>
#include <omapi/private.h>
#include <omapi/result.h>
/*
* 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;
isc_result_t
omapi_protocol_connect(omapi_object_t *h, const char *server_name,
in_port_t port, omapi_object_t *authinfo)
{
isc_result_t result;
omapi_protocol_t *obj = NULL;
REQUIRE(h != NULL && server_name != NULL);
REQUIRE(port != 0);
result = omapi_object_create((omapi_object_t **)&obj,
omapi_type_protocol, sizeof(*obj));
if (result != ISC_R_SUCCESS)
return (result);
OBJECT_REF(&h->outer, obj);
OBJECT_REF(&obj->inner, h);
/*
* Drop this function's direct reference to the protocol object
* so that connect_toserver or send_intro can free the connection
* and protocol objects in the event of an error.
*/
OBJECT_DEREF(&obj);
result = connect_toserver(h->outer, server_name, port);
/*
* Send the introductory message. This will also wait (via
* connection_send) 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.)
*
* If send_intro fails, the connection is already destroyed.
*/
if (result == ISC_R_SUCCESS)
result = send_intro(h->outer, OMAPI_PROTOCOL_VERSION);
if (authinfo != NULL)
OBJECT_REF(&((omapi_protocol_t *)h->outer)->authinfo,authinfo);
return (result);
}
void
omapi_protocol_disconnect(omapi_object_t *handle, isc_boolean_t force) {
omapi_protocol_t *protocol;
omapi_connection_t *connection;
REQUIRE(handle != NULL);
protocol = (omapi_protocol_t *)handle->outer;
if (protocol == NULL)
return; /* Already disconnected. */
INSIST(protocol->type == omapi_type_protocol);
connection = (omapi_connection_t *)protocol->outer;
INSIST(connection != NULL &&
connection->type == omapi_type_connection);
omapi_connection_disconnect((omapi_object_t *)connection, force);
}
/*
* Send the protocol introduction message.
*/
isc_result_t
send_intro(omapi_object_t *h, unsigned int ver) {
isc_result_t result;
omapi_protocol_t *p;
omapi_connection_t *connection;
REQUIRE(h != NULL && h->type == omapi_type_protocol);
REQUIRE(h->outer != NULL && h->outer->type == omapi_type_connection);
p = (omapi_protocol_t *)h;
connection = (omapi_connection_t *)h->outer;
result = omapi_connection_putuint32((omapi_object_t *)connection, ver);
if (result == ISC_R_SUCCESS)
result =
omapi_connection_putuint32((omapi_object_t *)connection,
sizeof(omapi_protocolheader_t));
/*
* Require the other end to send an intro - this kicks off the
* protocol input state machine. This does not use connection_require
* to set the number of bytes required because then a socket recv would
* be queued. To simplify the MT issues, the library only expects to
* have one task outstanding at a time, so the number of bytes
* that will be expected is set here, but the actual recv for
* them is not queued until after the send event posts.
*/
if (result == ISC_R_SUCCESS) {
p->state = omapi_protocol_intro_wait;
connection->bytes_needed = 8;
/*
* Make up an initial transaction ID for this connection.
* XXXDCL better generator than random()?
*/
p->next_xid = random();
result = connection_send(connection);
/*
* The client waited for the result; the server did not.
* The server's result will always be ISC_R_SUCCESS.
*
* If the client's result is not ISC_R_SUCCESS, the connection
* was already closed by the socket event handler that got
* the error.
*/
} else
/*
* One of the calls to omapi_connection_put* failed. As of the
* time of writing this comment, that would pretty much only
* happen if the required output buffer space could be
* dynamically allocated.
*
* The server is in listener_accept, so the connection can just
* be freed right here; listener_accept will not try to
* use it when this function exits.
*
* The client is in omapi_protocol_connect, its driving thread.
* It too has no events pending, so the connection will
* be freed.
*/
omapi_connection_disconnect(h->outer, OMAPI_FORCE_DISCONNECT);
return (result);
}
/*
* Set up a listener for the omapi protocol.
*/
isc_result_t
omapi_protocol_listen(omapi_object_t *manager, isc_sockaddr_t *addr,
isc_boolean_t ((*verify_connection)
(isc_sockaddr_t *incoming,
void *connect_arg)),
isc_boolean_t ((*verify_key)
(const char *name,
unsigned int algorithm,
void *key_arg)),
isc_taskaction_t destroy_action, void *arg)
{
return (omapi_listener_listen(manager, addr, verify_connection,
verify_key, destroy_action, arg));
}
isc_result_t
send_status(omapi_object_t *po, isc_result_t waitstatus,
unsigned int rid, const char *msg)
{
isc_result_t result;
omapi_object_t *message = NULL;
REQUIRE(po != NULL && po->type == omapi_type_protocol);
REQUIRE(po->outer != NULL && po->outer->type == omapi_type_connection);
REQUIRE(! ((omapi_connection_t *)po->outer)->is_client);
result = omapi_message_create(&message);
if (result != ISC_R_SUCCESS)
return (result);
result = omapi_object_setinteger(message, "op", OMAPI_OP_STATUS);
if (result == ISC_R_SUCCESS)
result = omapi_object_setinteger(message, "rid", (int)rid);
if (result == ISC_R_SUCCESS)
result = omapi_object_setinteger(message, "result",
(int)waitstatus);
/*
* If a message has been provided, send it.
*/
if (result == ISC_R_SUCCESS && msg != NULL)
result = omapi_object_setstring(message, "message", msg);
if (result == ISC_R_SUCCESS)
result = omapi_message_send(message, po);
OBJECT_DEREF(&message);
return (result);
}
isc_result_t
send_update(omapi_object_t *po, unsigned int rid, omapi_object_t *object) {
isc_result_t result;
omapi_object_t *message = NULL;
REQUIRE(po != NULL && po->type == omapi_type_protocol);
REQUIRE(! ((omapi_connection_t *)po->outer)->is_client);
result = omapi_message_create(&message);
if (result != ISC_R_SUCCESS)
return (result);
result = omapi_object_setinteger(message, "op", OMAPI_OP_UPDATE);
if (result == ISC_R_SUCCESS && rid != 0) {
omapi_handle_t handle;
result = omapi_object_setinteger(message, "rid", (int)rid);
if (result == ISC_R_SUCCESS)
result = object_gethandle(&handle, object);
if (result == ISC_R_SUCCESS)
result = omapi_object_setinteger(message, "handle",
(int)handle);
}
if (result == ISC_R_SUCCESS)
result = omapi_object_setobject(message, "object", object);
if (result == ISC_R_SUCCESS)
result = omapi_message_send(message, po);
OBJECT_DEREF(&message);
return (result);
}
static isc_result_t
dispatch_messages(omapi_protocol_t *protocol,
omapi_connection_t *connection)
{
isc_uint16_t nlen;
isc_uint32_t vlen;
isc_result_t result;
/*
* XXXDCL figure out how come when this function throws
* an error, it does not seem to be seen by the driving program.
* (this comment may no longer be true, but bears testing anyway)
*/
/*
* 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.
*/
switch (protocol->state) {
case omapi_protocol_intro_wait:
/*
* Get protocol version and header size in network byte order.
*/
connection_getuint32(connection, &protocol->protocol_version);
connection_getuint32(connection, &protocol->header_size);
/*
* Currently only the current protocol version is supported.
*/
if (protocol->protocol_version != OMAPI_PROTOCOL_VERSION)
return (OMAPI_R_VERSIONMISMATCH);
if (protocol->header_size < sizeof(omapi_protocolheader_t))
return (OMAPI_R_PROTOCOLERROR);
/*
* The next thing that shows up on incoming connections
* should be a message header.
*/
protocol->state = omapi_protocol_header_wait;
/*
* The client needs to have bytes_needed primed for the
* size of a message header, so that when send_done runs,
* it can kick off an isc_socket_recv (via connection_require)
* to get the server's response. It does this in
* omapi_message_send, so nothing need be done here now.
*
* The server needs to actually kick off its recv now to
* be ready for the first message from the client. The
* server's startup path looks like this:
* 1 server sends intro, bytes_needed is set to intro size (8).
* 2 send_done posts, recv of 8 for intro is queued.
* 3 recv_done posts, calls the protocol_signalhandler and
* ends up here.
*/
if (connection->is_client) {
result = OMAPI_R_NOTYET;
break;
}
/*
* Register a need for the number of bytes in a header, and if
* that many are here already, process them immediately.
*/
result = connection_require(connection, protocol->header_size);
if (result != ISC_R_SUCCESS)
break;
/* FALLTHROUGH */
case omapi_protocol_header_wait:
result = omapi_message_create((omapi_object_t **)
&protocol->message);
if (result != ISC_R_SUCCESS)
break;
if (protocol->key != NULL) {
isc_hmacmd5_init(&protocol->hmacctx,
protocol->key->base,
protocol->key->length);
protocol->verify_result = ISC_R_SUCCESS;
protocol->auth_update = ISC_TRUE;
}
/*
* Fetch the header values.
*/
/* XXXDCL authid is unused */
connection_getuint32(connection, &protocol->message->authid);
/* XXXTL bind the authenticator here! */
connection_getuint32(connection, &protocol->message->authlen);
connection_getuint32(connection, &protocol->message->op);
connection_getuint32(connection, &protocol->message->h);
connection_getuint32(connection, &protocol->message->id);
connection_getuint32(connection, &protocol->message->rid);
/*
* If there was any extra header data, skip over it,
* because it has no use in this version of the protocol.
*/
if (protocol->header_size > sizeof(omapi_protocolheader_t))
connection_copyout(NULL, connection,
(protocol->header_size -
sizeof(omapi_protocolheader_t)));
/*
* 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.
*/
/*
* After reading the header, first read in message-specific
* values, then object values.
*/
protocol->reading_message_values = ISC_TRUE;
need_name_length:
/*
* Need to get the 16-bit length of the value's name.
*/
protocol->state = omapi_protocol_name_length_wait;
result = connection_require(connection, 2);
if (result != ISC_R_SUCCESS)
break;
/* FALLTHROUGH */
case omapi_protocol_name_length_wait:
connection_getuint16(connection, &nlen);
/*
* A zero-length name signals the end of name+value pairs.
*/
if (nlen == 0) {
/*
* If the message values were being read, now
* the object values need to be read. Otherwise
* move on to reading the authenticator.
*/
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.
*/
goto need_name_length;
}
/*
* If the authenticator length is zero, there's no
* signature to read in, so go straight to processing
* the message.
*/
if (protocol->message->authlen == 0)
goto message_done;
/*
* The next thing that is expected is the message
* signature.
*/
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.
*/
result = connection_require(connection,
protocol->message->authlen);
if (result == ISC_R_SUCCESS)
goto signature_wait;
else
break;
}
/*
* Non-zero name length. Allocate a buffer for the name
* then wait for all its bytes to be available.
*/
result = omapi_string_create(&protocol->name, nlen);
if (result != ISC_R_SUCCESS)
break;
protocol->state = omapi_protocol_name_wait;
result = connection_require(connection, nlen);
if (result != ISC_R_SUCCESS)
break;
/* FALLTHROUGH */
case omapi_protocol_name_wait:
connection_copyout(protocol->name->value, connection,
protocol->name->len);
/*
* Wait for the 32-bit length of the value.
*/
protocol->state = omapi_protocol_value_length_wait;
result = connection_require(connection, 4);
if (result != ISC_R_SUCCESS)
break;
/* FALLTHROUGH */
case omapi_protocol_value_length_wait:
connection_getuint32(connection, &vlen);
/*
* 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.
*/
if (vlen == 0)
goto insert_new_value;
result = omapi_data_create(&protocol->value,
omapi_datatype_data, vlen);
if (result != ISC_R_SUCCESS)
break;
/*
* Check to see if all the bytes of the value are here.
*/
protocol->state = omapi_protocol_value_wait;
result = connection_require(connection, vlen);
if (result != ISC_R_SUCCESS)
break;
/* FALLTHROUGH */
case omapi_protocol_value_wait:
connection_copyout(protocol->value->u.buffer.value,
connection,
protocol->value->u.buffer.len);
/*
* Silence the gcc message "warning: `result' might be used
* uninitialized in this function"
*/
result = ISC_R_SUCCESS;
insert_new_value:
if (protocol->reading_message_values)
result = omapi_object_set((omapi_object_t *)
protocol->message,
protocol->name,
protocol->value);
else {
if (protocol->message->object == NULL) {
/*
* Create a generic object to receive the
* values of the object in the incoming
* message.
*/
result = omapi_object_create(&protocol->
message->object,
NULL, 0);
if (result != ISC_R_SUCCESS)
break;
}
result = omapi_object_set((omapi_object_t *)
protocol->message->object,
protocol->name,
protocol->value);
}
if (result != ISC_R_SUCCESS)
break;
omapi_string_dereference(&protocol->name);
if (protocol->value != NULL)
omapi_data_dereference(&protocol->value);
goto need_name_length;
signature_wait:
case omapi_protocol_signature_wait:
result = omapi_data_create(&protocol->message->authenticator,
omapi_datatype_data,
protocol->message->authlen);
if (result != ISC_R_SUCCESS)
return (result);
/*
* Turn off the dst_verify updating while the signature
* bytes are copied; they are not part of what was signed.
*/
protocol->auth_update = ISC_FALSE;
connection_copyout(protocol->message->authenticator->
u.buffer.value,
connection,
protocol->message->authlen);
protocol->signature_in.base =
protocol->message->authenticator->u.buffer.value;
protocol->signature_in.length = protocol->message->authlen;
/* XXXTL now do something to verify the signature. */
/* FALLTHROUGH */
message_done:
/*
* 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.
*/
result = message_process((omapi_object_t *)protocol->message,
(omapi_object_t *)protocol);
/* XXXTL unbind the authenticator. */
/*
* Free the message object.
*/
OBJECT_DEREF(&protocol->message);
/*
* The next thing the protocol reads will be a new message.
*/
protocol->state = omapi_protocol_header_wait;
/*
* Now, if message_process had indicated an error, let it be
* returned from here.
*/
if (result != ISC_R_SUCCESS)
break;
/*
* The next recv will be queued from send_done. On the
* server, this will be after it has sent its reply to the
* just-processed message by using omapi_message_send.
* On the client it will happen after it sends its
* next message with omapi_message_send.
*
* The OMAPI_R_NOTYET return value tells protocol_signalhandler
* that to return ISC_R_SUCCESS back to recv_done.
*/
result = OMAPI_R_NOTYET;
break;
default:
UNEXPECTED_ERROR(__FILE__, __LINE__, "unknown state in "
"omapi_protocol_signal_handler: %d",
protocol->state);
result = ISC_R_UNEXPECTED;
break;
}
return (result);
}
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_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?
*/
if (strcmp(name, "ready") != 0)
return (omapi_object_passsignal(h, name, ap));
INSIST(p->outer != NULL && p->outer->type == omapi_type_connection);
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;
return (result);
}
static isc_result_t
protocol_setvalue(omapi_object_t *h, omapi_string_t *name, omapi_data_t *value)
{
omapi_protocol_t *p;
isc_result_t result = ISC_R_SUCCESS;
REQUIRE(h != NULL && h->type == omapi_type_protocol);
p = (omapi_protocol_t *)h;
if (omapi_string_strcmp(name, "auth-name") == 0) {
p->authname = omapi_data_strdup(omapi_mctx, value);
if (p->authname == NULL)
return (ISC_R_NOMEMORY);
} else if (omapi_string_strcmp(name, "auth-algorithm") == 0) {
p->algorithm = omapi_data_getint(value);
if (p->algorithm == 0)
/*
* XXXDCL better error?
*/
return (ISC_R_NOTIMPLEMENTED);
} else
return (omapi_object_passsetvalue(h, name, value));
/*
* XXXDCL if either auth-name or auth-algorithm is not in the incoming
* message, then the client will not get a meaningful error message
* in reply. this is bad.
*
* ... it is a general problem in the current omapi design ...
*/
if (p->authname != NULL && p->algorithm != 0) {
/*
* Verifying the key through a callback is (currently) only
* done by the server.
* XXXDCL the client should have some way of checking whether
* what is being set is what it asked for.
*/
if (p->verify_key != NULL &&
!p->verify_key(p->authname, p->algorithm,
p->verify_key_arg))
return (ISC_R_NOPERM);
if (p->key != NULL) {
isc_mem_put(omapi_mctx, p->key, sizeof(isc_region_t));
p->key = NULL;
}
result = auth_makekey(p->authname, p->algorithm, &p->key);
if (result == ISC_R_SUCCESS)
result = isc_buffer_allocate(omapi_mctx,
&p->signature_out,
ISC_MD5_DIGESTLENGTH);
if (result != ISC_R_SUCCESS) {
if (p->key != NULL) {
isc_mem_put(omapi_mctx, p->key,
sizeof(isc_region_t));
p->key = NULL;
}
isc_mem_free(omapi_mctx, p->authname);
p->authname = NULL;
p->algorithm = 0;
p->key = NULL;
}
}
return (result);
}
static isc_result_t
protocol_getvalue(omapi_object_t *h, omapi_string_t *name,
omapi_value_t **value)
{
REQUIRE(h != NULL && h->type == omapi_type_protocol);
return (omapi_object_passgetvalue(h, name, value));
}
static void
protocol_destroy(omapi_object_t *h) {
omapi_protocol_t *p;
REQUIRE(h != NULL && h->type == omapi_type_protocol);
p = (omapi_protocol_t *)h;
if (p->message != NULL)
OBJECT_DEREF(&p->message);
if (p->authinfo != NULL)
OBJECT_DEREF(&p->authinfo);
if (p->authname != NULL) {
isc_mem_free(omapi_mctx, p->authname);
p->authname = NULL;
}
if (p->signature_out != NULL) {
isc_buffer_free(&p->signature_out);
p->signature_out = NULL;
}
if (p->key != NULL) {
isc_mem_put(omapi_mctx, p->key, sizeof(isc_region_t));
p->key = NULL;
}
}
static isc_result_t
protocol_stuffvalues(omapi_object_t *connection, omapi_object_t *h) {
REQUIRE(h != NULL && h->type == omapi_type_protocol);
return (omapi_object_passstuffvalues(connection, h));
}
isc_result_t
protocol_init(void) {
return (omapi_object_register(&omapi_type_protocol, "protocol",
protocol_setvalue,
protocol_getvalue,
protocol_destroy,
protocol_signalhandler,
protocol_stuffvalues,
NULL, NULL, NULL));
}

View File

@ -1,69 +0,0 @@
/*
* Copyright (C) 1999-2001 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.
*/
/* $Id: result.c,v 1.11 2001/01/09 22:00:10 bwelling Exp $ */
#include <config.h>
#include <isc/once.h>
#include <isc/util.h>
#include <omapi/result.h>
#include <omapi/lib.h>
static const char *text[OMAPI_R_NRESULTS] = {
"data not yet available", /* 0 */
"not connected", /* 1 */
"no key specified", /* 2 */
"invalid argument", /* 3 */
"protocol version mismatch", /* 4 */
"protocol error", /* 5 */
};
#define OMAPI_RESULT_RESULTSET 2
static isc_once_t once = ISC_ONCE_INIT;
static void
initialize_action(void) {
isc_result_t result;
result = isc_result_register(ISC_RESULTCLASS_OMAPI, OMAPI_R_NRESULTS,
text, omapi_msgcat,
OMAPI_RESULT_RESULTSET);
if (result != ISC_R_SUCCESS)
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_result_register() failed: %u", result);
}
static void
initialize(void) {
omapi_lib_initmsgcat();
RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
}
const char *
omapi_result_totext(isc_result_t result) {
initialize();
return (isc_result_totext(result));
}
void
omapi_result_register(void) {
initialize();
}

View File

@ -1,115 +0,0 @@
/*
* Copyright (C) 1996-2001 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.
*/
/* $Id: string.c,v 1.10 2001/01/09 22:00:12 bwelling Exp $ */
/* Principal Author: Ted Lemon */
#include <config.h>
#include <isc/mem.h>
#include <isc/string.h>
#include <isc/util.h>
#include <omapi/private.h>
isc_result_t
omapi_string_create(omapi_string_t **d, unsigned int len) {
omapi_string_t *new;
new = isc_mem_get(omapi_mctx, OMAPI_STRING_EMPTY_SIZE + len);
if (new == NULL)
return (ISC_R_NOMEMORY);
memset(new, 0, OMAPI_STRING_EMPTY_SIZE);
new->len = len;
omapi_string_reference(d, new);
return (ISC_R_SUCCESS);
}
void
omapi_string_reference(omapi_string_t **r, omapi_string_t *h) {
REQUIRE(r != NULL && h != NULL);
REQUIRE(*r == NULL);
*r = h;
h->refcnt++;
}
void
omapi_string_dereference(omapi_string_t **h) {
REQUIRE(h != NULL && *h != NULL);
REQUIRE((*h)->refcnt > 0);
if (--((*h)->refcnt) <= 0)
isc_mem_put(omapi_mctx, *h,
OMAPI_STRING_EMPTY_SIZE + (*h)->len);
*h = NULL;
}
void
omapi_string_totext(omapi_string_t *string, isc_region_t *region) {
REQUIRE(string != NULL && region != NULL);
region->base = string->value;
region->length = string->len;
}
int
omapi_string_stringcmp(omapi_string_t *s1, omapi_string_t *s2) {
unsigned int len;
int order;
if (s1->len > s2->len)
len = s2->len;
else
len = s1->len;
order = memcmp(s1->value, s2->value, len);
if (order == 0) {
if (s1->len > s2->len)
order = 1;
else if (s1->len < s2->len)
order = -1;
}
return (order);
}
int
omapi_string_strcmp(omapi_string_t *s1, const char *s2) {
unsigned int len, slen;
int order;
slen = strlen(s2);
if (slen > s1->len)
len = s1->len;
else
len = slen;
order = memcmp(s1->value, s2, len);
if (order == 0) {
if (s1->len > slen)
order = 1;
else if (s1->len < slen)
order= -1;
}
return (order);
}

View File

@ -1,209 +0,0 @@
/*
* Copyright (C) 1996-2001 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.
*/
/* $Id: value.c,v 1.11 2001/01/09 22:00:15 bwelling Exp $ */
/* Principal Author: Ted Lemon */
#include <config.h>
#include <isc/mem.h>
#include <isc/string.h>
#include <isc/util.h>
#include <omapi/private.h>
isc_result_t
omapi_value_create(omapi_value_t **d) {
omapi_value_t *new;
new = isc_mem_get(omapi_mctx, sizeof(*new));
if (new == NULL)
return (ISC_R_NOMEMORY);
memset(new, 0, sizeof *new);
omapi_value_reference(d, new);
return (ISC_R_SUCCESS);
}
void
omapi_value_reference(omapi_value_t **r, omapi_value_t *h) {
REQUIRE(r != NULL && h != NULL);
REQUIRE(*r == NULL);
*r = h;
h->refcnt++;
}
void
omapi_value_dereference(omapi_value_t **h) {
REQUIRE(h != NULL && *h != NULL);
REQUIRE((*h)->refcnt > 0);
if (--((*h)->refcnt) <= 0) {
if ((*h)->name != NULL)
omapi_string_dereference(&(*h)->name);
if ((*h)->value != NULL)
omapi_data_dereference(&(*h)->value);
isc_mem_put(omapi_mctx, *h, sizeof(omapi_value_t));
}
*h = NULL;
}
isc_result_t
omapi_value_storedata(omapi_value_t **vp, omapi_string_t *name,
omapi_data_t *value)
{
isc_result_t result;
result = omapi_value_create(vp);
if (result != ISC_R_SUCCESS)
return (result);
omapi_string_reference(&(*vp)->name, name);
if (value != NULL)
omapi_data_reference(&(*vp)->value, value);
return (result);
}
isc_result_t
omapi_value_storemem(omapi_value_t **vp, omapi_string_t *name,
const unsigned char *value, unsigned int len)
{
isc_result_t result;
result = omapi_value_create(vp);
if (result != ISC_R_SUCCESS)
return (result);
omapi_string_reference(&(*vp)->name, name);
if (value != NULL) {
result = omapi_data_create(&(*vp)->value,
omapi_datatype_data, len);
if (result == ISC_R_SUCCESS)
memcpy((*vp)->value->u.buffer.value, value, len);
}
if (result != ISC_R_SUCCESS)
omapi_value_dereference(vp);
return (result);
}
isc_result_t
omapi_value_storeint(omapi_value_t **vp, omapi_string_t *name, int value) {
isc_result_t result;
result = omapi_value_create(vp);
if (result != ISC_R_SUCCESS)
return (result);
omapi_string_reference(&(*vp)->name, name);
result = omapi_data_create(&(*vp)->value, omapi_datatype_int);
if (result == ISC_R_SUCCESS)
(*vp)->value->u.integer = value;
if (result != ISC_R_SUCCESS)
omapi_value_dereference(vp);
return (result);
}
isc_result_t
omapi_value_storeobject(omapi_value_t **vp, omapi_string_t *name,
omapi_object_t *value)
{
isc_result_t result;
result = omapi_value_create(vp);
if (result != ISC_R_SUCCESS)
return (result);
omapi_string_reference(&(*vp)->name, name);
if (value != NULL) {
result = omapi_data_create(&(*vp)->value, omapi_datatype_int);
if (result == ISC_R_SUCCESS)
result = object_gethandle((omapi_handle_t *)
&(*vp)->value->u.integer,
value);
}
if (result != ISC_R_SUCCESS)
omapi_value_dereference(vp);
return (result);
}
isc_result_t
omapi_value_storestr(omapi_value_t **vp, omapi_string_t *name, char *value)
{
isc_result_t result;
result = omapi_value_create(vp);
if (result != ISC_R_SUCCESS)
return (result);
omapi_string_reference(&(*vp)->name, name);
if (value != NULL)
result = omapi_data_create(&(*vp)->value,
omapi_datatype_string, value);
if (result != ISC_R_SUCCESS)
omapi_value_dereference(vp);
return (result);
}
int
omapi_value_getint(omapi_value_t *value) {
REQUIRE(value != NULL && value->value != NULL);
REQUIRE(value->value->type == omapi_datatype_int ||
((value->value->type == omapi_datatype_data ||
(value->value->type == omapi_datatype_string)) &&
value->value->u.buffer.len == sizeof(isc_uint32_t)));
return (omapi_data_getint(value->value));
}
/*
* WARNING: The region is valid only as long as the value pointer
* is valid. See omapi.h.
*/
void
omapi_value_getregion(omapi_value_t *value, isc_region_t *region) {
REQUIRE(value != NULL && value->value != NULL);
REQUIRE(value->value->type == omapi_datatype_data ||
value->value->type == omapi_datatype_string);
/*
* Boy, the word "value" appears a lot. Almost like a Smurf song.
* La la la la la la, la la la la la.
*/
region->base = value->value->u.buffer.value;
region->length = value->value->u.buffer.len;
}

View File

@ -1,24 +0,0 @@
/*
* Copyright (C) 1999-2001 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.
*/
/* $Id: version.c,v 1.6 2001/01/09 22:00:18 bwelling Exp $ */
char omapi_version[] = VERSION;
unsigned int omapi_libinterface = LIBINTERFACE;
unsigned int omapi_librevision = LIBREVISION;
unsigned int omapi_libage = LIBAGE;

View File

@ -13,7 +13,7 @@
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# $Id: includes.in,v 1.13 2001/03/27 00:44:57 bwelling Exp $
# $Id: includes.in,v 1.14 2001/03/27 00:53:56 bwelling Exp $
# Search for machine-generated header files in the build tree,
# and for normal headers in the source tree (${top_srcdir}).
@ -37,9 +37,6 @@ DNS_INCLUDES = @BIND9_DNS_BUILDINCLUDE@ \
-I${top_srcdir}/lib/dns/include \
-I${top_srcdir}/lib/dns/sec/dst/include
OMAPI_INCLUDES = @BIND9_OMAPI_BUILDINCLUDE@ \
-I${top_srcdir}/lib/omapi/include
LWRES_INCLUDES = @BIND9_LWRES_BUILDINCLUDE@ \
-I${top_srcdir}/lib/lwres/include

View File

@ -56,7 +56,6 @@
./bin/named/include/named/lwsearch.h C 2000,2001
./bin/named/include/named/main.h C 1999,2000,2001
./bin/named/include/named/notify.h C 1999,2000,2001
./bin/named/include/named/omapi.h C 2000,2001
./bin/named/include/named/query.h C 1999,2000,2001
./bin/named/include/named/server.h C 1999,2000,2001
./bin/named/include/named/sortlist.h C 2000,2001
@ -83,8 +82,6 @@
./bin/named/main.c C 1999,2000,2001
./bin/named/named.8 MAN 2000,2001
./bin/named/notify.c C 1999,2000,2001
./bin/named/omapi.c C 2000,2001
./bin/named/omapiconf.c C 2000,2001
./bin/named/query.c C 1999,2000,2001
./bin/named/server.c C 1999,2000,2001
./bin/named/sortlist.c C 2000,2001
@ -293,7 +290,6 @@
./bin/tests/net/sockaddr_multicast.c C 2000,2001
./bin/tests/net/testsuite.h C 2000,2001
./bin/tests/nxtify.c C 1999,2000,2001
./bin/tests/omapi_test.c C 1996,1997,1998,1999,2000,2001
./bin/tests/printmsg.c C 1998,1999,2000,2001
./bin/tests/printmsg.h C 1998,1999,2000,2001
./bin/tests/ratelimiter_test.c C 1999,2000,2001
@ -809,7 +805,6 @@
./doc/design/logging TXT.BRIEF 1999,2000,2001
./doc/design/lwres TXT.BRIEF 2000,2001
./doc/design/ncache TXT.BRIEF 1999,2000,2001
./doc/design/omapi TXT.BRIEF 1999,2000,2001
./doc/design/rdataset TXT.BRIEF 1999,2000,2001
./doc/design/red-black TXT.BRIEF 1999,2000,2001
./doc/design/resolver TXT.BRIEF 1999,2000,2001
@ -1461,33 +1456,6 @@
./lib/lwres/man/lwres_string_parse.3 MAN 2000,2001
./lib/lwres/man/resolver.5 MAN 2000,2001
./lib/lwres/version.c C 2000,2001
./lib/omapi/.cvsignore X 1999,2000,2001
./lib/omapi/Makefile.in MAKE 1999,2000,2001
./lib/omapi/api X 1999,2000,2001
./lib/omapi/auth.c C 2000,2001
./lib/omapi/connection.c C 1996,1997,1998,1999,2000,2001
./lib/omapi/data.c C 1996,1997,1998,1999,2000,2001
./lib/omapi/generic.c C 1996,1997,1998,1999,2000,2001
./lib/omapi/handle.c C 1996,1997,1998,1999,2000,2001
./lib/omapi/include/.cvsignore X 1999,2000,2001
./lib/omapi/include/Makefile.in MAKE 1999,2000,2001
./lib/omapi/include/omapi/.cvsignore X 1999,2000,2001
./lib/omapi/include/omapi/Makefile.in MAKE 1999,2000,2001
./lib/omapi/include/omapi/compatibility.h C 2000,2001
./lib/omapi/include/omapi/lib.h C 1999,2000,2001
./lib/omapi/include/omapi/omapi.h C 1996,1997,1998,1999,2000,2001
./lib/omapi/include/omapi/private.h C 1996,1997,1998,1999,2000,2001
./lib/omapi/include/omapi/result.h C 1999,2000,2001
./lib/omapi/include/omapi/types.h C 1996,1997,1998,1999,2000,2001
./lib/omapi/lib.c C 1999,2000,2001
./lib/omapi/listener.c C 1996,1997,1998,1999,2000,2001
./lib/omapi/message.c C 1996,1997,1998,1999,2000,2001
./lib/omapi/object.c C 1996,1997,1998,1999,2000,2001
./lib/omapi/protocol.c C 1996,1997,1998,1999,2000,2001
./lib/omapi/result.c C 1999,2000,2001
./lib/omapi/string.c C 1996,1997,1998,1999,2000,2001
./lib/omapi/value.c C 1996,1997,1998,1999,2000,2001
./lib/omapi/version.c C 1999,2000,2001
./lib/tests/.cvsignore X 1999,2000,2001
./lib/tests/Makefile.in MAKE 1998,1999,2000,2001
./lib/tests/include/.cvsignore X 1999,2000,2001