diff --git a/CHANGES b/CHANGES index 5d2feb4eb7..875c41e4e7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ + 792. [cleanup] Replace the OMAPI command channel protocol with a + simpler one. + 791. [bug] The command channel now works over IPv6. 790. [bug] Wildcards created using dynamic update or IXFR diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in index 9bf3d2691a..2dc3046a97 100644 --- a/bin/named/Makefile.in +++ b/bin/named/Makefile.in @@ -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.70 2001/03/06 02:40:11 bwelling Exp $ +# $Id: Makefile.in,v 1.71 2001/03/27 00:44:30 bwelling Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -32,37 +32,38 @@ DBDRIVER_INCLUDES = DBDRIVER_LIBS = CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include \ - ${LWRES_INCLUDES} ${OMAPI_INCLUDES} ${DNS_INCLUDES} \ - ${ISCCFG_INCLUDES} ${ISC_INCLUDES} ${DBDRIVER_INCLUDES} + ${LWRES_INCLUDES} ${DNS_INCLUDES} \ + ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \ + ${DBDRIVER_INCLUDES} CDEFINES = CWARNINGS = -OMAPILIBS = ../../lib/omapi/libomapi.@A@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_OPENSSL_LIBS@ @DNS_GSSAPI_LIBS@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ +ISCCCLIBS = ../../lib/isccc/libisccc.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ LWRESLIBS = ../../lib/lwres/liblwres.@A@ -OMAPIDEPLIBS = ../../lib/omapi/libomapi.@A@ DNSDEPLIBS = ../../lib/dns/libdns.@A@ ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ +ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@ -DEPLIBS = ${LWRESDEPLIBS} ${OMAPIDEPLIBS} ${DNSDEPLIBS} \ - ${ISCCFGDEPLIBS} ${ISCDEPLIBS} +DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} \ + ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${ISCDEPLIBS} -LIBS = ${LWRESLIBS} ${OMAPILIBS} ${DNSLIBS} \ - ${ISCCFGLIBS} ${ISCLIBS} ${DBDRIVER_LIBS} @LIBS@ +LIBS = ${LWRESLIBS} ${DNSLIBS} \ + ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} ${DBDRIVER_LIBS} @LIBS@ SUBDIRS = unix TARGETS = named lwresd -OBJS = aclconf.@O@ client.@O@ config.@O@ interfacemgr.@O@ \ +OBJS = aclconf.@O@ client.@O@ config.@O@ control.@O@ controlconf.@O@ interfacemgr.@O@ \ listenlist.@O@ log.@O@ logconf.@O@ main.@O@ notify.@O@ \ - omapi.@O@ omapiconf.@O@ query.@O@ server.@O@ sortlist.@O@ \ + query.@O@ server.@O@ sortlist.@O@ \ tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \ zoneconf.@O@ \ lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \ @@ -71,9 +72,9 @@ OBJS = aclconf.@O@ client.@O@ config.@O@ interfacemgr.@O@ \ UOBJS = unix/os.@O@ -SRCS = aclconf.c client.c config.c interfacemgr.c \ +SRCS = aclconf.c client.c config.c control.c controlconf.c interfacemgr.c \ listenlist.c log.c logconf.c main.c notify.c \ - omapi.c omapiconf.c query.c server.c sortlist.c \ + query.c server.c sortlist.c \ tkeyconf.c tsigconf.c update.c xfrout.c \ zoneconf.c \ lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \ diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index efc01e29e0..5d34fddce8 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: globals.h,v 1.53 2001/03/04 21:21:32 bwelling Exp $ */ +/* $Id: globals.h,v 1.54 2001/03/27 00:44:36 bwelling Exp $ */ #ifndef NAMED_GLOBALS_H #define NAMED_GLOBALS_H 1 @@ -28,8 +28,6 @@ #include -#include - #include #undef EXTERN @@ -54,7 +52,6 @@ EXTERN isc_entropy_t * ns_g_entropy INIT(NULL); */ EXTERN isc_timermgr_t * ns_g_timermgr INIT(NULL); EXTERN isc_socketmgr_t * ns_g_socketmgr INIT(NULL); -EXTERN omapi_object_t * ns_g_omapimgr INIT(NULL); EXTERN cfg_parser_t * ns_g_parser INIT(NULL); EXTERN const char * ns_g_version INIT(VERSION); EXTERN in_port_t ns_g_port INIT(0); diff --git a/bin/named/include/named/log.h b/bin/named/include/named/log.h index 403211b724..2a867f590d 100644 --- a/bin/named/include/named/log.h +++ b/bin/named/include/named/log.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.h,v 1.17 2001/01/09 21:40:17 bwelling Exp $ */ +/* $Id: log.h,v 1.18 2001/03/27 00:44:38 bwelling Exp $ */ #ifndef NAMED_LOG_H #define NAMED_LOG_H 1 @@ -47,7 +47,7 @@ #define NS_LOGMODULE_XFER_IN (&ns_g_modules[6]) #define NS_LOGMODULE_XFER_OUT (&ns_g_modules[7]) #define NS_LOGMODULE_NOTIFY (&ns_g_modules[8]) -#define NS_LOGMODULE_OMAPI (&ns_g_modules[9]) +#define NS_LOGMODULE_CONTROL (&ns_g_modules[9]) #define NS_LOGMODULE_LWRESD (&ns_g_modules[10]) isc_result_t diff --git a/bin/named/log.c b/bin/named/log.c index 2bf6049833..8a0344a3be 100644 --- a/bin/named/log.c +++ b/bin/named/log.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.c,v 1.30 2001/03/13 03:04:09 gson Exp $ */ +/* $Id: log.c,v 1.31 2001/03/27 00:44:31 bwelling Exp $ */ #include @@ -52,7 +52,7 @@ static isc_logmodule_t modules[] = { { "xfer-in", 0 }, { "xfer-out", 0 }, { "notify", 0 }, - { "omapi", 0 }, + { "control", 0 }, { "lwresd", 0 }, { NULL, 0 } }; diff --git a/bin/named/main.c b/bin/named/main.c index ba18c01be7..362e2cfe95 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: main.c,v 1.105 2001/03/06 02:40:13 bwelling Exp $ */ +/* $Id: main.c,v 1.106 2001/03/27 00:44:33 bwelling Exp $ */ #include @@ -33,20 +33,24 @@ #include #include +#include + #include -#include +#include #include +#include + /* * Defining NS_MAIN provides storage declarations (rather than extern) * for variables in named/globals.h. */ #define NS_MAIN 1 +#include #include /* Explicit, though named/log.h includes it. */ #include #include -#include #include #include #include @@ -417,10 +421,10 @@ static void destroy_managers(void) { if (!ns_g_lwresdonly) /* - * The omapi listeners need to be stopped here so that - * isc_taskmgr_destroy() won't block on the omapi task. + * The command channel listeners need to be stopped here so + * that isc_taskmgr_destroy() won't block on the server task. */ - ns_omapi_shutdown(ISC_TRUE); + ns_control_shutdown(ISC_TRUE); ns_lwresd_shutdown(); @@ -498,13 +502,6 @@ setup(void) { /* xxdb_init(); */ ns_server_create(ns_g_mctx, &ns_g_server); - - if (!ns_g_lwresdonly) { - result = ns_omapi_init(); - if (result != ISC_R_SUCCESS) - ns_main_earlyfatal("ns_omapi_init() failed: %s", - isc_result_totext(result)); - } } static void @@ -546,6 +543,7 @@ main(int argc, char *argv[]) { dns_result_register(); dst_result_register(); + isccc_result_register(); parse_command_line(argc, argv); diff --git a/bin/named/server.c b/bin/named/server.c index 73335446c8..abd5e057dc 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.311 2001/03/26 23:03:05 gson Exp $ */ +/* $Id: server.c,v 1.312 2001/03/27 00:44:34 bwelling Exp $ */ #include @@ -60,11 +60,11 @@ #include #include +#include #include #include #include #include -#include #include #include #include @@ -1855,9 +1855,9 @@ load_configuration(const char *filename, ns_server_t *server, } /* - * Bind the OMAPI port(s). + * Bind the control port(s). */ - CHECKM(ns_omapi_configure(ns_g_mctx, config, &aclconfctx), + CHECKM(ns_control_configure(ns_g_mctx, config, &aclconfctx), "binding control channel(s)"); /* diff --git a/bin/rndc/Makefile.in b/bin/rndc/Makefile.in index 7566b9eabb..b6dc25241f 100644 --- a/bin/rndc/Makefile.in +++ b/bin/rndc/Makefile.in @@ -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.20 2001/02/16 04:17:00 tale Exp $ +# $Id: Makefile.in,v 1.21 2001/03/27 00:44:41 bwelling Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -24,23 +24,22 @@ top_srcdir = @top_srcdir@ @BIND9_INCLUDES@ CINCLUDES = -I${top_srcdir}/bin/named/include \ - ${ISC_INCLUDES} ${ISCCFG_INCLUDES} \ - ${DNS_INCLUDES} ${OMAPI_INCLUDES} + ${ISC_INCLUDES} ${ISCCC_INCLUDES} ${ISCCFG_INCLUDES} CDEFINES = CWARNINGS = -OMAPILIBS = ../../lib/omapi/libomapi.@A@ ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@ +ISCCCLIBS = ../../lib/isccc/libisccc.@A@ ISCLIBS = ../../lib/isc/libisc.@A@ -OMAPIDEPLIBS = ../../lib/omapi/libomapi.@A@ -ISCDEPLIBS = ../../lib/isccfg/libisccfg.@A@ +ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@ +ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@ ISCDEPLIBS = ../../lib/isc/libisc.@A@ -DEPLIBS = ${OMAPIDEPLIBS} ${ISCCFGLIBS} ${ISCDEPLIBS} +DEPLIBS = ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${ISCDEPLIBS} -LIBS = ${OMAPILIBS} ${ISCCFGLIBS} ${ISCLIBS} @LIBS@ +LIBS = ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} @LIBS@ TARGETS = rndc diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c index e9e6437911..6987a82047 100644 --- a/bin/rndc/rndc.c +++ b/bin/rndc/rndc.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rndc.c,v 1.43 2001/03/22 00:07:01 bwelling Exp $ */ +/* $Id: rndc.c,v 1.44 2001/03/27 00:44:42 bwelling Exp $ */ /* * Principal Author: DCL @@ -24,36 +24,59 @@ #include #include +#include -#include +#include #include #include #include #include #include +#include #include #include #include #include -#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef HAVE_ADDRINFO +#ifdef HAVE_GETADDRINFO +#ifdef HAVE_GAISTRERROR +#define USE_GETADDRINFO +#endif +#endif +#endif + +#ifndef USE_GETADDRINFO +extern int h_errno; +#endif static const char *progname; static const char *conffile = RNDC_SYSCONFDIR "/rndc.conf"; static const char *version = VERSION; - +static unsigned int remoteport = NS_CONTROL_PORT; +static const char *servername = NULL; +static isc_socketmgr_t *socketmgr = NULL; +static unsigned char databuf[2048]; +static isccc_ccmsg_t ccmsg; +static char *args; +static isc_boolean_t have_ipv4, have_ipv6; +static isccc_region_t secret; static isc_boolean_t verbose; +static isc_boolean_t failed = ISC_FALSE; static isc_mem_t *mctx; - -typedef struct ndc_object { - OMAPI_OBJECT_PREAMBLE; -} ndc_object_t; - -#define REGION_FMT(x) (int)(x)->length, (x)->base - -static ndc_object_t ndc_g_ndc; -static omapi_objecttype_t *ndc_type; +char *command; static void notify(const char *fmt, ...) { @@ -67,188 +90,6 @@ notify(const char *fmt, ...) { } } -/* - * Send a control command to the server. 'command' is the command - * name, and 'args' is a space-delimited sequence of words, the - * first being the command name itself. - */ -static isc_result_t -send_command(omapi_object_t *manager, char *command, char *args) { - omapi_object_t *message = NULL; - isc_result_t result; - - REQUIRE(manager != NULL && command != NULL); - - /* - * Create a new message object to store the information that will - * be sent to the server. - */ - result = omapi_message_create(&message); - if (result != ISC_R_SUCCESS) - return (result); - - /* - * Specify the OPEN operation, with the UPDATE option if requested. - */ - result = omapi_object_setinteger(message, "op", OMAPI_OP_OPEN); - - if (result == ISC_R_SUCCESS) - result = omapi_object_setboolean(message, "update", ISC_TRUE); - - /* - * 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. - */ - if (result == ISC_R_SUCCESS) - result = omapi_object_setstring(message, "type", - NS_OMAPI_CONTROL); - - /* - * Associate the ndc 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; this is true even though the - * particular object being accessed on the server does not need a key - * to be found. - * - * This object will also have its signal handler called with a - * "status" signal that sends the result of the operation on the - * server. - */ - if (result == ISC_R_SUCCESS) - result = omapi_object_setobject(message, "object", - (omapi_object_t *)&ndc_g_ndc); - - /* - * Create a generic object to be the outer object for ndc_g_ndc, to - * handle the job of storing the command and stuffing it into the - * message. - * - * XXXDCL provide API so client does not need to refer to the - * outer member -- does not even need to know about how the whole - * outer/inner thing works. - */ - if (result == ISC_R_SUCCESS) - result = omapi_object_create(&ndc_g_ndc.outer, NULL, 0); - - /* - * Set the command being sent. - */ - result = omapi_object_setstring((omapi_object_t *)&ndc_g_ndc, - command, args); - - if (result == 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 and await its - * response. - */ - result = omapi_message_send(message, manager); - } - - /* - * Free the generic object and the message. - */ - if (ndc_g_ndc.outer != NULL) - omapi_object_dereference(&ndc_g_ndc.outer); - - omapi_message_unregister(message); - omapi_object_dereference(&message); - - return (result); -} - -/* - * The signal handler gets the "status" signals when the server's response - * is processed. It also gets the "updated" signal after all the values - * from the server have been incorporated via ndc_setvalue. - */ -static isc_result_t -ndc_signalhandler(omapi_object_t *handle, const char *name, va_list ap) { - ndc_object_t *ndc; - omapi_value_t *tv; - isc_region_t region; - isc_result_t result; - - REQUIRE(handle->type == ndc_type); - - ndc = (ndc_object_t *)handle; - notify("ndc_signalhandler: %s", name); - - if (strcmp(name, "status") == 0) { - /* - * "status" is signalled with the result of the message's - * operation. - */ - ndc->waitresult = va_arg(ap, isc_result_t); - - if (ndc->waitresult != ISC_R_SUCCESS) { - fprintf(stderr, "%s: operation failed: %s", - progname, isc_result_totext(ndc->waitresult)); - - tv = va_arg(ap, omapi_value_t *); - if (tv != NULL) { - omapi_value_getregion(tv, ®ion); - fprintf(stderr, " (%.*s)", - (int)region.length, region.base); - } - fprintf(stderr, "\n"); - } - - /* - * Even if the waitresult was not ISC_R_SUCCESS, the processing - * by the function still was. - */ - result = ISC_R_SUCCESS; - - } else if (strcmp(name, "updated") == 0) { - /* - * Nothing to do, really. - */ - result = ISC_R_SUCCESS; - - } 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: ndc_signalhandler: unknown signal: %s", - progname, name); - result = omapi_object_passsignal(handle, name, ap); - } - - return (result); -} - -static isc_result_t -ndc_setvalue(omapi_object_t *handle, omapi_string_t *name, - omapi_data_t *value) -{ - isc_region_t region; -/* - isc_result_t result; - char *message; -*/ - - INSIST(handle == (omapi_object_t *)&ndc_g_ndc); - - UNUSED(value); - UNUSED(handle); - - omapi_string_totext(name, ®ion); - notify("ndc_setvalue: %.*s\n", REGION_FMT(®ion)); - - return (ISC_R_SUCCESS); -} - static void usage(void) { fprintf(stderr, "\ @@ -278,6 +119,19 @@ Version: %s\n", progname, version); } +static void +fatal(const char *format, ...) { + va_list args; + + fprintf(stderr, "%s: ", progname); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + exit(1); +} + + #undef DO #define DO(name, function) \ do { \ @@ -290,16 +144,185 @@ Version: %s\n", notify(name); \ } while (0) + +static void +get_address(const char *host, in_port_t port, isc_sockaddr_t *sockaddr) { + struct in_addr in4; + struct in6_addr in6; +#ifdef USE_GETADDRINFO + struct addrinfo *res = NULL, hints; + int result; +#else + struct hostent *he; +#endif + + /* + * Assume we have v4 if we don't have v6, since setup_libs + * fatal()'s out if we don't have either. + */ + if (have_ipv6 && inet_pton(AF_INET6, host, &in6) == 1) + isc_sockaddr_fromin6(sockaddr, &in6, port); + else if (inet_pton(AF_INET, host, &in4) == 1) + isc_sockaddr_fromin(sockaddr, &in4, port); + else { +#ifdef USE_GETADDRINFO + memset(&hints, 0, sizeof(hints)); + if (!have_ipv6) + hints.ai_family = PF_INET; + else if (!have_ipv4) + hints.ai_family = PF_INET6; + else + hints.ai_family = PF_UNSPEC; + isc_app_block(); + result = getaddrinfo(host, NULL, &hints, &res); + isc_app_unblock(); + if (result != 0) + fatal("Couldn't find server '%s': %s", + host, gai_strerror(result)); + memcpy(&sockaddr->type.sa,res->ai_addr, res->ai_addrlen); + sockaddr->length = res->ai_addrlen; + isc_sockaddr_setport(sockaddr, port); + freeaddrinfo(res); +#else + isc_app_block(); + he = gethostbyname(host); + isc_app_unblock(); + if (he == NULL) + fatal("Couldn't find server '%s' (h_errno=%d)", + host, h_errno); + INSIST(he->h_addrtype == AF_INET); + isc_sockaddr_fromin(sockaddr, + (struct in_addr *)(he->h_addr_list[0]), + port); +#endif + } +} + +static void +rndc_senddone(isc_task_t *task, isc_event_t *event) { + isc_socketevent_t *sevent = (isc_socketevent_t *)event; + + UNUSED(task); + + if (sevent->result != ISC_R_SUCCESS) + fatal("send failed: %s", isc_result_totext(sevent->result)); + isc_event_free(&event); +} + +static void +rndc_recvdone(isc_task_t *task, isc_event_t *event) { + isc_socket_t *sock = ccmsg.sock; + isccc_sexpr_t *response = NULL; + isccc_sexpr_t *data; + isccc_region_t source; + char *errormsg = NULL; + isc_result_t result; + + if (ccmsg.result == ISC_R_EOF) { + fprintf(stderr, "%s: connection to remote host closed\n", + progname); + fprintf(stderr, + "This may indicate that the remote server is using " + "an older version of the\n" + "command protocol or this host is not authorized " + "to connect.\n"); + exit(1); + } + + if (ccmsg.result != ISC_R_SUCCESS) + fatal("recv failed: %s", isc_result_totext(ccmsg.result)); + + source.rstart = isc_buffer_base(&ccmsg.buffer); + source.rend = isc_buffer_used(&ccmsg.buffer); + DO("parse message", isccc_cc_fromwire(&source, &response, &secret)); + data = isccc_alist_lookup(response, "_data"); + if (data == NULL) + fatal("no data section in response"); + result = isccc_cc_lookupstring(data, "err", &errormsg); + if (result == ISC_R_SUCCESS) { + failed = ISC_TRUE; + fprintf(stderr, "%s: '%s' failed: %s\n", + progname, command, errormsg); + } + else if (result != ISC_R_NOTFOUND) + fprintf(stderr, "%s: parsing response failed: %s\n", + progname, isc_result_totext(result)); + + isc_event_free(&event); + isccc_sexpr_free(&response); + isc_socket_detach(&sock); + isc_task_shutdown(task); + isc_app_shutdown(); +} + +static void +rndc_connected(isc_task_t *task, isc_event_t *event) { + isc_socketevent_t *sevent = (isc_socketevent_t *)event; + isc_socket_t *sock = event->ev_sender; + isccc_sexpr_t *request = NULL; + isccc_sexpr_t *data; + isccc_time_t now; + isccc_region_t message; + isc_region_t r; + isc_uint32_t len; + isc_buffer_t b; + isc_result_t result; + + if (sevent->result != ISC_R_SUCCESS) + fatal("connect failed: %s", isc_result_totext(sevent->result)); + + isc_stdtime_get(&now); + DO("create message", isccc_cc_createmessage(1, NULL, NULL, random(), + now, now + 60, &request)); + data = isccc_alist_lookup(request, "_data"); + if (data == NULL) + fatal("_data section missing"); + if (isccc_cc_definestring(data, "type", args) == NULL) + fatal("out of memory"); + message.rstart = databuf + 4; + message.rend = databuf + sizeof(databuf); + DO("render message", isccc_cc_towire(request, &message, &secret)); + len = sizeof(databuf) - REGION_SIZE(message); + isc_buffer_init(&b, databuf, 4); + isc_buffer_putuint32(&b, len - 4); + r.length = len; + r.base = databuf; + + isccc_ccmsg_init(mctx, sock, &ccmsg); + + DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task, + rndc_recvdone, NULL)); + DO("send message", isc_socket_send(sock, &r, task, rndc_senddone, + NULL)); + isc_event_free(&event); + +} + +static void +rndc_start(isc_task_t *task, isc_event_t *event) { + isc_sockaddr_t addr; + isc_socket_t *sock = NULL; + isc_result_t result; + + isc_event_free(&event); + + get_address(servername, remoteport, &addr); + DO("create socket", isc_socket_create(socketmgr, + isc_sockaddr_pf(&addr), + isc_sockettype_tcp, &sock)); + DO("connect", isc_socket_connect(sock, &addr, task, rndc_connected, + NULL)); +} + int main(int argc, char **argv) { isc_boolean_t show_final_mem = ISC_FALSE; isc_result_t result = ISC_R_SUCCESS; - isc_socketmgr_t *socketmgr = NULL; isc_taskmgr_t *taskmgr = NULL; + isc_task_t *task = NULL; isc_log_t *log = NULL; isc_logconfig_t *logconfig = NULL; isc_logdestination_t logdest; - omapi_object_t *omapimgr = NULL; cfg_parser_t *pctx = NULL; cfg_obj_t *config = NULL; cfg_obj_t *options = NULL; @@ -312,18 +335,16 @@ main(int argc, char **argv) { cfg_obj_t *algorithmobj = NULL; cfg_listelt_t *elt; const char *keyname = NULL; - const char *secret; + const char *secretstr; const char *algorithm; char secretarray[1024]; - isc_buffer_t secretbuf; - char *command, *args, *p; + char *p; size_t argslen; - const char *servername = NULL; - int alg; - unsigned int port = NS_OMAPI_PORT; int ch; int i; + isc_app_start(); + progname = strrchr(*argv, '/'); if (progname != NULL) progname++; @@ -346,8 +367,8 @@ main(int argc, char **argv) { break; case 'p': - port = atoi(isc_commandline_argument); - if (port > 65535) { + remoteport = atoi(isc_commandline_argument); + if (remoteport > 65535) { fprintf(stderr, "%s: port out of range\n", progname); exit(1); @@ -386,6 +407,7 @@ main(int argc, char **argv) { DO("create memory context", isc_mem_create(0, 0, &mctx)); DO("create socket manager", isc_socketmgr_create(mctx, &socketmgr)); DO("create task manager", isc_taskmgr_create(mctx, 1, 0, &taskmgr)); + DO("create task", isc_task_create(taskmgr, 0, &task)); DO("create logging context", isc_log_create(mctx, &log, &logconfig)); isc_log_setcontext(log); @@ -400,7 +422,6 @@ main(int argc, char **argv) { ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL)); DO("enabling log channel", isc_log_usechannel(logconfig, "stderr", NULL, NULL)); - DO("create parser", cfg_parser_create(mctx, log, &pctx)); result = cfg_parse_file(pctx, conffile, &cfg_type_rndcconf, &config); if (result != ISC_R_SUCCESS) @@ -441,17 +462,18 @@ main(int argc, char **argv) { */ if (keyname != NULL) ; /* Was set on command line, do nothing. */ - else if (server != NULL) + else if (server != NULL) { DO("get key for server", cfg_map_get(server, "key", &defkey)); - else if (options != NULL) { + keyname = cfg_obj_asstring(defkey); + } else if (options != NULL) { DO("get default key", cfg_map_get(options, "default-key", &defkey)); + keyname = cfg_obj_asstring(defkey); } else { fprintf(stderr, "%s: no key for server and no default\n", progname); exit(1); } - keyname = cfg_obj_asstring(defkey); /* * Get the key's definition. @@ -475,57 +497,25 @@ main(int argc, char **argv) { progname); exit(1); } - secret = cfg_obj_asstring(secretobj); + secretstr = cfg_obj_asstring(secretobj); algorithm = cfg_obj_asstring(algorithmobj); - if (strcasecmp(algorithm, "hmac-md5") == 0) - alg = OMAPI_AUTH_HMACMD5; - else { + if (strcasecmp(algorithm, "hmac-md5") != 0) { fprintf(stderr, "%s: unsupported algorithm: %s\n", progname, algorithm); exit(1); } - isc_buffer_init(&secretbuf, secretarray, sizeof(secretarray)); - DO("decode base64 secret", - isc_base64_decodestring(secret, &secretbuf)); + secret.rstart = secretarray; + secret.rend = secretarray + sizeof(secretarray); + DO("decode base64 secret", isccc_base64_decode(secretstr, &secret)); + secret.rend = secret.rstart; + secret.rstart = secretarray; - DO("initialize omapi", omapi_lib_init(mctx, taskmgr, socketmgr)); + isccc_result_register(); - DO("register omapi object", - omapi_object_register(&ndc_type, "ndc", - ndc_setvalue, /* setvalue */ - NULL, /* getvalue */ - NULL, /* destroy */ - ndc_signalhandler, - NULL, /* stuffvalues */ - NULL, /* lookup */ - NULL, /* create */ - NULL)); /* remove */ - - /* - * Initialize the static ndc_g_ndc variable (normally this is done - * by omapi_object_create on a dynamic variable). - */ - ndc_g_ndc.refcnt = 1; - ndc_g_ndc.type = ndc_type; - - DO("register local authenticator", - omapi_auth_register(keyname, alg, isc_buffer_base(&secretbuf), - isc_buffer_usedlength(&secretbuf))); - - DO("create protocol manager", omapi_object_create(&omapimgr, NULL, 0)); - - DO("connect", omapi_protocol_connect(omapimgr, servername, - (in_port_t)port, NULL)); - - DO("send remote authenticator", - omapi_auth_use(omapimgr, keyname, alg)); - - /* - * Preload the waitresult as successful. - */ - ndc_g_ndc.waitresult = ISC_R_SUCCESS; + have_ipv4 = (isc_net_probeipv4() == ISC_R_SUCCESS); + have_ipv6 = (isc_net_probeipv6() == ISC_R_SUCCESS); command = *argv; @@ -556,49 +546,22 @@ main(int argc, char **argv) { notify(command); - if (strcmp(command, "restart") == 0 || - strcmp(command, "status") == 0) { - result = ISC_R_NOTIMPLEMENTED; - } else { - result = send_command(omapimgr, command, args); - } + if (strcmp(command, "restart") == 0 || strcmp(command, "status") == 0) + fatal("%s: '%s' is not implemented", progname, command); - if (result == ISC_R_NOTIMPLEMENTED) - fprintf(stderr, "%s: '%s' is not yet implemented\n", - progname, command); - else if (result != ISC_R_SUCCESS) - fprintf(stderr, "%s: protocol failure: %s\n", - progname, isc_result_totext(result)); - else if (ndc_g_ndc.waitresult != ISC_R_SUCCESS) - fprintf(stderr, "%s: %s command failure: %s\n", - progname, command, - isc_result_totext(ndc_g_ndc.waitresult)); - else - printf("%s: %s command successful\n", - progname, command); + DO("post event", isc_app_onrun(mctx, task, rndc_start, NULL)); + + isc_app_run(); isc_mem_put(mctx, args, argslen); - /* - * Close the connection and wait to be disconnected. The connection - * is only still open if the protocol object is still attached - * to the omapimgr. - */ - if (omapimgr != NULL) { - omapi_protocol_disconnect(omapimgr, OMAPI_CLEAN_DISCONNECT); - - /* - * Free the protocol manager. - */ - omapi_object_dereference(&omapimgr); - } - cfg_obj_destroy(pctx, &config); cfg_parser_destroy(&pctx); - omapi_lib_destroy(); + isccc_ccmsg_invalidate(&ccmsg); isc_socketmgr_destroy(&socketmgr); + isc_task_detach(&task); isc_taskmgr_destroy(&taskmgr); isc_log_destroy(&log); isc_log_setcontext(NULL); @@ -608,8 +571,8 @@ main(int argc, char **argv) { isc_mem_destroy(&mctx); - if (result != ISC_R_SUCCESS || ndc_g_ndc.waitresult != ISC_R_SUCCESS) - exit(1); + if (failed) + return (1); return (0); } diff --git a/configure b/configure index 7bf09da1a7..1edb34c1d4 100755 --- a/configure +++ b/configure @@ -5263,14 +5263,17 @@ BIND9_TOP_BUILDDIR=`pwd` + 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="" @@ -5291,6 +5294,9 @@ BIND9_VERSION="VERSION=${MAJORVER}.${MINORVER}.${PATCHVER}${RELEASETYPE}${RELEAS LIBISC_API=$srcdir/lib/isc/api +LIBISCCFG_API=$srcdir/lib/isccc/api + + LIBISCCFG_API=$srcdir/lib/isccfg/api @@ -5420,6 +5426,9 @@ trap 'rm -fr `echo "make/rules lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile + lib/isccc/Makefile + lib/isccc/include/Makefile + lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile @@ -5612,6 +5621,7 @@ s%@SGMLDIR@%$SGMLDIR%g s%@XMLDIR@%$XMLDIR%g s%@BIND9_TOP_BUILDDIR@%$BIND9_TOP_BUILDDIR%g s%@BIND9_ISC_BUILDINCLUDE@%$BIND9_ISC_BUILDINCLUDE%g +s%@BIND9_ISCCC_BUILDINCLUDE@%$BIND9_ISCCC_BUILDINCLUDE%g s%@BIND9_ISCCFG_BUILDINCLUDE@%$BIND9_ISCCFG_BUILDINCLUDE%g s%@BIND9_DNS_BUILDINCLUDE@%$BIND9_DNS_BUILDINCLUDE%g s%@BIND9_OMAPI_BUILDINCLUDE@%$BIND9_OMAPI_BUILDINCLUDE%g @@ -5623,6 +5633,8 @@ s%@BIND9_MAKE_RULES@%%g s%@BIND9_VERSION@%$BIND9_VERSION%g /@LIBISC_API@/r $LIBISC_API s%@LIBISC_API@%%g +/@LIBISCCC_API@/r $LIBISCCC_API +s%@LIBISCCC_API@%%g /@LIBISCCFG_API@/r $LIBISCCFG_API s%@LIBISCCFG_API@%%g /@LIBDNS_API@/r $LIBDNS_API @@ -5689,6 +5701,9 @@ CONFIG_FILES=\${CONFIG_FILES-"make/rules lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile + lib/isccc/Makefile + lib/isccc/include/Makefile + lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile diff --git a/configure.in b/configure.in index 164eaced92..eeace185a1 100644 --- a/configure.in +++ b/configure.in @@ -18,7 +18,7 @@ AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)dnl esyscmd([sed "s/^/# /" COPYRIGHT])dnl AC_DIVERT_POP()dnl -AC_REVISION($Revision: 1.240 $) +AC_REVISION($Revision: 1.241 $) AC_INIT(lib/dns/name.c) AC_PREREQ(2.13) @@ -1410,18 +1410,21 @@ AC_SUBST(BIND9_TOP_BUILDDIR) BIND9_TOP_BUILDDIR=`pwd` 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="" @@ -1441,6 +1444,9 @@ AC_SUBST(BIND9_VERSION) AC_SUBST_FILE(LIBISC_API) LIBISC_API=$srcdir/lib/isc/api +AC_SUBST_FILE(LIBISCCC_API) +LIBISCCFG_API=$srcdir/lib/isccc/api + AC_SUBST_FILE(LIBISCCFG_API) LIBISCCFG_API=$srcdir/lib/isccfg/api @@ -1471,6 +1477,9 @@ AC_OUTPUT( lib/isc/$thread_dir/Makefile lib/isc/$thread_dir/include/Makefile lib/isc/$thread_dir/include/isc/Makefile + lib/isccc/Makefile + lib/isccc/include/Makefile + lib/isccc/include/isccc/Makefile lib/isccfg/Makefile lib/isccfg/include/Makefile lib/isccfg/include/isccfg/Makefile diff --git a/lib/Makefile.in b/lib/Makefile.in index e0acfc55fb..caf26b4ee6 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -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.13 2001/02/15 04:14:11 gson Exp $ +# $Id: Makefile.in,v 1.14 2001/03/27 00:44:43 bwelling Exp $ srcdir = @srcdir@ VPATH = @srcdir@ top_srcdir = @top_srcdir@ -SUBDIRS = isc isccfg dns lwres omapi tests +SUBDIRS = isc isccc isccfg dns lwres omapi tests TARGETS = @BIND9_MAKE_RULES@ diff --git a/lib/isc/include/isc/eventclass.h b/lib/isc/include/isc/eventclass.h index 7b19343120..5e3953b775 100644 --- a/lib/isc/include/isc/eventclass.h +++ b/lib/isc/include/isc/eventclass.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: eventclass.h,v 1.12 2001/01/09 21:56:53 bwelling Exp $ */ +/* $Id: eventclass.h,v 1.13 2001/03/27 00:44:45 bwelling Exp $ */ #ifndef ISC_EVENTCLASS_H #define ISC_EVENTCLASS_H 1 @@ -44,6 +44,7 @@ #define ISC_EVENTCLASS_APP ISC_EVENTCLASS(5) #define ISC_EVENTCLASS_OMAPI ISC_EVENTCLASS(6) #define ISC_EVENTCLASS_RATELIMITER ISC_EVENTCLASS(7) +#define ISC_EVENTCLASS_ISCCC ISC_EVENTCLASS(8) /* * Event classes >= 1024 and <= 65535 are reserved for application use. diff --git a/lib/isc/include/isc/resultclass.h b/lib/isc/include/isc/resultclass.h index a9eb679687..052069777a 100644 --- a/lib/isc/include/isc/resultclass.h +++ b/lib/isc/include/isc/resultclass.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resultclass.h,v 1.10 2001/01/09 21:57:29 bwelling Exp $ */ +/* $Id: resultclass.h,v 1.11 2001/03/27 00:44:46 bwelling Exp $ */ #ifndef ISC_RESULTCLASS_H #define ISC_RESULTCLASS_H 1 @@ -45,6 +45,7 @@ #define ISC_RESULTCLASS_DST ISC_RESULTCLASS_FROMNUM(2) #define ISC_RESULTCLASS_DNSRCODE ISC_RESULTCLASS_FROMNUM(3) #define ISC_RESULTCLASS_OMAPI ISC_RESULTCLASS_FROMNUM(4) +#define ISC_RESULTCLASS_ISCCC ISC_RESULTCLASS_FROMNUM(5) /* * Result classes >= 1024 and <= 65535 are reserved for application use. diff --git a/lib/isccc/.cvsignore b/lib/isccc/.cvsignore new file mode 100644 index 0000000000..b3b8e7617f --- /dev/null +++ b/lib/isccc/.cvsignore @@ -0,0 +1,5 @@ +Makefile +timestamp +.libs +*.la +*.lo diff --git a/lib/isccc/Makefile.in b/lib/isccc/Makefile.in new file mode 100644 index 0000000000..642db69622 --- /dev/null +++ b/lib/isccc/Makefile.in @@ -0,0 +1,86 @@ +# Copyright (C) 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.1 2001/03/27 00:44:47 bwelling Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +@LIBISCCC_API@ + +@BIND9_INCLUDES@ + +CINCLUDES = -I. ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCC_INCLUDES} + +CDEFINES = +CWARNINGS = + +ISCLIBS = ../../lib/isc/libisc.@A@ +ISCCCLIBS = ../../lib/cc/libisccc.@A@ + +ISCDEPLIBS = ../../lib/isc/libisc.@A@ +ISCCCDEPLIBS = libisccc.@A@ + +LIBS = @LIBS@ + +SUBDIRS = include + +# Alphabetically +OBJS = alist.@O@ base64.@O@ cc.@O@ ccmsg.@O@ \ + lib.@O@ \ + result.@O@ sexpr.@O@ symtab.@O@ + +# Alphabetically +SRCS = alist.c base64.c cc.c ccmsg.c \ + lib.c \ + result.c sexpr.c symtab.c + + +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 + +libisccc.@SA@: ${OBJS} + ${AR} ${ARFLAGS} $@ ${OBJS} + ${RANLIB} $@ + +libisccc.la: ${OBJS} + ${LIBTOOL} --mode=link \ + ${CC} ${ALL_CFLAGS} -o libisccc.la -rpath ${libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} ${LIBS} + +timestamp: libisccc.@A@ + touch timestamp + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} + +install:: timestamp installdirs + ${LIBTOOL} ${INSTALL_DATA} libisccc.@A@ ${DESTDIR}${libdir} + +clean distclean:: + rm -f libisccc.@A@ timestamp diff --git a/lib/isccc/alist.c b/lib/isccc/alist.c new file mode 100644 index 0000000000..e5df16dbd4 --- /dev/null +++ b/lib/isccc/alist.c @@ -0,0 +1,296 @@ +/* + * Copyright (C) 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: alist.c,v 1.1 2001/03/27 00:44:47 bwelling Exp $ */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#define CAR(s) (s)->value.as_dottedpair.car +#define CDR(s) (s)->value.as_dottedpair.cdr + +#define ALIST_TAG "*alist*" +#define MAX_INDENT 64 + +static char spaces[MAX_INDENT + 1] = + " "; + +isccc_sexpr_t * +isccc_alist_create(void) +{ + isccc_sexpr_t *alist, *tag; + + tag = isccc_sexpr_fromstring(ALIST_TAG); + if (tag == NULL) + return (NULL); + alist = isccc_sexpr_cons(tag, NULL); + if (alist == NULL) { + isccc_sexpr_free(&tag); + return (NULL); + } + + return (alist); +} + +isc_boolean_t +isccc_alist_alistp(isccc_sexpr_t *alist) +{ + isccc_sexpr_t *car; + + if (alist == NULL || alist->type != ISCCC_SEXPRTYPE_DOTTEDPAIR) + return (ISC_FALSE); + car = CAR(alist); + if (car == NULL || car->type != ISCCC_SEXPRTYPE_STRING) + return (ISC_FALSE); + if (strcmp(car->value.as_string, ALIST_TAG) != 0) + return (ISC_FALSE); + return (ISC_TRUE); +} + +isc_boolean_t +isccc_alist_emptyp(isccc_sexpr_t *alist) +{ + REQUIRE(isccc_alist_alistp(alist)); + + if (CDR(alist) == NULL) + return (ISC_TRUE); + return (ISC_FALSE); +} + +isccc_sexpr_t * +isccc_alist_first(isccc_sexpr_t *alist) +{ + REQUIRE(isccc_alist_alistp(alist)); + + return (CDR(alist)); +} + +isccc_sexpr_t * +isccc_alist_assq(isccc_sexpr_t *alist, const char *key) +{ + isccc_sexpr_t *car, *caar; + + REQUIRE(isccc_alist_alistp(alist)); + + /* + * Skip alist type tag. + */ + alist = CDR(alist); + + while (alist != NULL) { + INSIST(alist->type == ISCCC_SEXPRTYPE_DOTTEDPAIR); + car = CAR(alist); + INSIST(car->type == ISCCC_SEXPRTYPE_DOTTEDPAIR); + caar = CAR(car); + if (caar->type == ISCCC_SEXPRTYPE_STRING && + strcmp(caar->value.as_string, key) == 0) + return (car); + alist = CDR(alist); + } + + return (NULL); +} + +void +isccc_alist_delete(isccc_sexpr_t *alist, const char *key) +{ + isccc_sexpr_t *car, *caar, *rest, *prev; + + REQUIRE(isccc_alist_alistp(alist)); + + prev = alist; + rest = CDR(alist); + while (rest != NULL) { + INSIST(rest->type == ISCCC_SEXPRTYPE_DOTTEDPAIR); + car = CAR(rest); + INSIST(car != NULL && car->type == ISCCC_SEXPRTYPE_DOTTEDPAIR); + caar = CAR(car); + if (caar->type == ISCCC_SEXPRTYPE_STRING && + strcmp(caar->value.as_string, key) == 0) { + CDR(prev) = CDR(rest); + CDR(rest) = NULL; + isccc_sexpr_free(&rest); + break; + } + prev = rest; + rest = CDR(rest); + } +} + +isccc_sexpr_t * +isccc_alist_define(isccc_sexpr_t *alist, const char *key, isccc_sexpr_t *value) +{ + isccc_sexpr_t *kv, *k, *elt; + + kv = isccc_alist_assq(alist, key); + if (kv == NULL) { + /* + * New association. + */ + k = isccc_sexpr_fromstring(key); + if (k == NULL) + return (NULL); + kv = isccc_sexpr_cons(k, value); + if (kv == NULL) { + isccc_sexpr_free(&kv); + return (NULL); + } + elt = isccc_sexpr_addtolist(&alist, kv); + if (elt == NULL) { + isccc_sexpr_free(&kv); + return (NULL); + } + } else { + /* + * We've already got an entry for this key. Replace it. + */ + isccc_sexpr_free(&CDR(kv)); + CDR(kv) = value; + } + + return (kv); +} + +isccc_sexpr_t * +isccc_alist_definestring(isccc_sexpr_t *alist, const char *key, const char *str) +{ + isccc_sexpr_t *v, *kv; + + v = isccc_sexpr_fromstring(str); + if (v == NULL) + return (NULL); + kv = isccc_alist_define(alist, key, v); + if (kv == NULL) + isccc_sexpr_free(&v); + + return (kv); +} + +isccc_sexpr_t * +isccc_alist_definebinary(isccc_sexpr_t *alist, const char *key, isccc_region_t *r) +{ + isccc_sexpr_t *v, *kv; + + v = isccc_sexpr_frombinary(r); + if (v == NULL) + return (NULL); + kv = isccc_alist_define(alist, key, v); + if (kv == NULL) + isccc_sexpr_free(&v); + + return (kv); +} + +isccc_sexpr_t * +isccc_alist_lookup(isccc_sexpr_t *alist, const char *key) +{ + isccc_sexpr_t *kv; + + kv = isccc_alist_assq(alist, key); + if (kv != NULL) + return (CDR(kv)); + return (NULL); +} + +isc_result_t +isccc_alist_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp) +{ + isccc_sexpr_t *kv, *v; + + kv = isccc_alist_assq(alist, key); + if (kv != NULL) { + v = CDR(kv); + if (isccc_sexpr_stringp(v)) { + if (strp != NULL) + *strp = isccc_sexpr_tostring(v); + return (ISC_R_SUCCESS); + } else + return (ISC_R_EXISTS); + } + + return (ISC_R_NOTFOUND); +} + +isc_result_t +isccc_alist_lookupbinary(isccc_sexpr_t *alist, const char *key, isccc_region_t **r) +{ + isccc_sexpr_t *kv, *v; + + kv = isccc_alist_assq(alist, key); + if (kv != NULL) { + v = CDR(kv); + if (isccc_sexpr_binaryp(v)) { + if (r != NULL) + *r = isccc_sexpr_tobinary(v); + return (ISC_R_SUCCESS); + } else + return (ISC_R_EXISTS); + } + + return (ISC_R_NOTFOUND); +} + +void +isccc_alist_prettyprint(isccc_sexpr_t *sexpr, unsigned int indent, FILE *stream) +{ + isccc_sexpr_t *elt, *kv, *k, *v; + + if (isccc_alist_alistp(sexpr)) { + fprintf(stream, "{\n"); + indent += 4; + for (elt = isccc_alist_first(sexpr); + elt != NULL; + elt = CDR(elt)) { + kv = CAR(elt); + INSIST(isccc_sexpr_listp(kv)); + k = CAR(kv); + v = CDR(kv); + INSIST(isccc_sexpr_stringp(k)); + fprintf(stream, "%.*s%s => ", (int)indent, spaces, + isccc_sexpr_tostring(k)); + isccc_alist_prettyprint(v, indent, stream); + if (CDR(elt) != NULL) + fprintf(stream, ","); + fprintf(stream, "\n"); + } + indent -= 4; + fprintf(stream, "%.*s}", (int)indent, spaces); + } else if (isccc_sexpr_listp(sexpr)) { + fprintf(stream, "(\n"); + indent += 4; + for (elt = sexpr; + elt != NULL; + elt = CDR(elt)) { + fprintf(stream, "%.*s", (int)indent, spaces); + isccc_alist_prettyprint(CAR(elt), indent, stream); + if (CDR(elt) != NULL) + fprintf(stream, ","); + fprintf(stream, "\n"); + } + indent -= 4; + fprintf(stream, "%.*s)", (int)indent, spaces); + } else + isccc_sexpr_print(sexpr, stream); +} diff --git a/lib/isccc/api b/lib/isccc/api new file mode 100644 index 0000000000..494278e7f5 --- /dev/null +++ b/lib/isccc/api @@ -0,0 +1,3 @@ +LIBINTERFACE = 0 +LIBREVISION = 0 +LIBAGE = 0 diff --git a/lib/isccc/base64.c b/lib/isccc/base64.c new file mode 100644 index 0000000000..6ac32c3fc2 --- /dev/null +++ b/lib/isccc/base64.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 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: base64.c,v 1.1 2001/03/27 00:44:48 bwelling Exp $ */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +isc_result_t +isccc_base64_encode(isccc_region_t *source, int wordlength, + const char *wordbreak, isccc_region_t *target) +{ + isc_region_t sr; + isc_buffer_t tb; + isc_result_t result; + + sr.base = source->rstart; + sr.length = source->rend - source->rstart; + isc_buffer_init(&tb, target->rstart, target->rend - target->rstart); + + result = isc_base64_totext(&sr, wordlength, wordbreak, &tb); + if (result != ISC_R_SUCCESS) + return (result); + source->rstart = source->rend; + target->rstart = isc_buffer_used(&tb); + return (ISC_R_SUCCESS); +} + +isc_result_t +isccc_base64_decode(const char *cstr, isccc_region_t *target) { + isc_buffer_t b; + isc_result_t result; + + isc_buffer_init(&b, target->rstart, target->rend - target->rstart); + result = isc_base64_decodestring(cstr, &b); + if (result != ISC_R_SUCCESS) + return (result); + target->rstart = isc_buffer_used(&b); + return (ISC_R_SUCCESS); +} diff --git a/lib/isccc/cc.c b/lib/isccc/cc.c new file mode 100644 index 0000000000..45182e22e1 --- /dev/null +++ b/lib/isccc/cc.c @@ -0,0 +1,920 @@ +/* + * Copyright (C) 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: cc.c,v 1.1 2001/03/27 00:44:48 bwelling Exp $ */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_TAGS 256 +#define DUP_LIFETIME 900 + +typedef isccc_sexpr_t *sexpr_ptr; + +static unsigned char auth_hmd5[] = { + 0x05, 0x5f, 0x61, 0x75, 0x74, 0x68, /* len + _auth */ + ISCCC_CCMSGTYPE_TABLE, /* message type */ + 0x00, 0x00, 0x00, 0x20, /* length == 32 */ + 0x04, 0x68, 0x6d, 0x64, 0x35, /* len + hmd5 */ + ISCCC_CCMSGTYPE_BINARYDATA, /* message type */ + 0x00, 0x00, 0x00, 0x16, /* length == 22 */ + /* + * The base64 encoding of one of our HMAC-MD5 signatures is + * 22 bytes. + */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +#define HMD5_OFFSET 21 /* 6 + 1 + 4 + 5 + 1 + 4 */ +#define HMD5_LENGTH 22 + +static isc_result_t +table_towire(isccc_sexpr_t *alist, isccc_region_t *target); + +static isc_result_t +list_towire(isccc_sexpr_t *alist, isccc_region_t *target); + +static isc_result_t +value_towire(isccc_sexpr_t *elt, isccc_region_t *target) +{ + size_t len; + unsigned char *lenp; + isccc_region_t *vr; + isc_result_t result; + + if (isccc_sexpr_binaryp(elt)) { + vr = isccc_sexpr_tobinary(elt); + len = REGION_SIZE(*vr); + if (REGION_SIZE(*target) < 1 + 4 + len) + return (ISC_R_NOSPACE); + PUT8(ISCCC_CCMSGTYPE_BINARYDATA, target->rstart); + PUT32(len, target->rstart); + if (REGION_SIZE(*target) < len) + return (ISC_R_NOSPACE); + PUT_MEM(vr->rstart, len, target->rstart); + } else if (isccc_alist_alistp(elt)) { + if (REGION_SIZE(*target) < 1 + 4) + return (ISC_R_NOSPACE); + PUT8(ISCCC_CCMSGTYPE_TABLE, target->rstart); + /* + * Emit a placeholder length. + */ + lenp = target->rstart; + PUT32(0, target->rstart); + /* + * Emit the table. + */ + result = table_towire(elt, target); + if (result != ISC_R_SUCCESS) + return (result); + len = (size_t)(target->rstart - lenp); + /* + * 'len' is 4 bytes too big, since it counts + * the placeholder length too. Adjust and + * emit. + */ + INSIST(len >= 4); + len -= 4; + PUT32(len, lenp); + } else if (isccc_sexpr_listp(elt)) { + if (REGION_SIZE(*target) < 1 + 4) + return (ISC_R_NOSPACE); + PUT8(ISCCC_CCMSGTYPE_LIST, target->rstart); + /* + * Emit a placeholder length and count. + */ + lenp = target->rstart; + PUT32(0, target->rstart); + /* + * Emit the list. + */ + result = list_towire(elt, target); + if (result != ISC_R_SUCCESS) + return (result); + len = (size_t)(target->rstart - lenp); + /* + * 'len' is 4 bytes too big, since it counts + * the placeholder length. Adjust and emit. + */ + INSIST(len >= 4); + len -= 4; + PUT32(len, lenp); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +table_towire(isccc_sexpr_t *alist, isccc_region_t *target) +{ + isccc_sexpr_t *kv, *elt, *k, *v; + char *ks; + isc_result_t result; + size_t len; + + for (elt = isccc_alist_first(alist); + elt != NULL; + elt = ISCCC_SEXPR_CDR(elt)) { + kv = ISCCC_SEXPR_CAR(elt); + k = ISCCC_SEXPR_CAR(kv); + ks = isccc_sexpr_tostring(k); + v = ISCCC_SEXPR_CDR(kv); + len = strlen(ks); + INSIST(len <= 255); + /* + * Emit the key name. + */ + if (REGION_SIZE(*target) < 1 + len) + return (ISC_R_NOSPACE); + PUT8(len, target->rstart); + PUT_MEM(ks, len, target->rstart); + /* + * Emit the value. + */ + result = value_towire(v, target); + if (result != ISC_R_SUCCESS) + return (result); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +list_towire(isccc_sexpr_t *list, isccc_region_t *target) +{ + isc_result_t result; + + while (list != NULL) { + result = value_towire(ISCCC_SEXPR_CAR(list), target); + if (result != ISC_R_SUCCESS) + return (result); + list = ISCCC_SEXPR_CDR(list); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +sign(unsigned char *data, unsigned int length, unsigned char *hmd5, + isccc_region_t *secret) +{ + isc_hmacmd5_t ctx; + isc_result_t result; + isccc_region_t source, target; + unsigned char digest[ISC_MD5_DIGESTLENGTH]; + unsigned char digestb64[ISC_MD5_DIGESTLENGTH * 4]; + + isc_hmacmd5_init(&ctx, secret->rstart, REGION_SIZE(*secret)); + isc_hmacmd5_update(&ctx, data, length); + isc_hmacmd5_sign(&ctx, digest); + source.rstart = digest; + source.rend = digest + ISC_MD5_DIGESTLENGTH; + target.rstart = digestb64; + target.rend = digestb64 + ISC_MD5_DIGESTLENGTH * 4; + result = isccc_base64_encode(&source, 64, "", &target); + if (result != ISC_R_SUCCESS) + return (result); + PUT_MEM(digestb64, HMD5_LENGTH, hmd5); + + return (ISC_R_SUCCESS); +} + +isc_result_t +isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target, + isccc_region_t *secret) +{ + unsigned char *hmd5_rstart, *signed_rstart; + isc_result_t result; + + if (REGION_SIZE(*target) < 4 + sizeof auth_hmd5) + return (ISC_R_NOSPACE); + /* + * Emit protocol version. + */ + PUT32(1, target->rstart); + if (secret != NULL) { + /* + * Emit _auth section with zeroed HMAC-MD5 signature. + * We'll replace the zeros with the real signature once + * we know what it is. + */ + hmd5_rstart = target->rstart + HMD5_OFFSET; + PUT_MEM(auth_hmd5, sizeof auth_hmd5, target->rstart); + } else + hmd5_rstart = NULL; + signed_rstart = target->rstart; + /* + * Delete any existing _auth section so that we don't try + * to encode it. + */ + isccc_alist_delete(alist, "_auth"); + /* + * Emit the message. + */ + result = table_towire(alist, target); + if (result != ISC_R_SUCCESS) + return (result); + if (secret != NULL) + return (sign(signed_rstart, (target->rstart - signed_rstart), + hmd5_rstart, secret)); + return (ISC_R_SUCCESS); +} + +static isc_result_t +verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, + isccc_region_t *secret) +{ + isc_hmacmd5_t ctx; + isccc_region_t source; + isccc_region_t target; + isc_result_t result; + isccc_sexpr_t *_auth, *hmd5; + unsigned char digest[ISC_MD5_DIGESTLENGTH]; + unsigned char digestb64[ISC_MD5_DIGESTLENGTH * 4]; + + /* + * Extract digest. + */ + _auth = isccc_alist_lookup(alist, "_auth"); + if (_auth == NULL) + return (ISC_R_FAILURE); + hmd5 = isccc_alist_lookup(_auth, "hmd5"); + if (hmd5 == NULL) + return (ISC_R_FAILURE); + /* + * Compute digest. + */ + isc_hmacmd5_init(&ctx, secret->rstart, REGION_SIZE(*secret)); + isc_hmacmd5_update(&ctx, data, length); + isc_hmacmd5_sign(&ctx, digest); + source.rstart = digest; + source.rend = digest + ISC_MD5_DIGESTLENGTH; + target.rstart = digestb64; + target.rend = digestb64 + ISC_MD5_DIGESTLENGTH * 4; + result = isccc_base64_encode(&source, 64, "", &target); + if (result != ISC_R_SUCCESS) + return (result); + /* + * Strip trailing == and NUL terminate target. + */ + target.rstart -= 2; + *target.rstart++ = '\0'; + /* + * Verify. + */ + if (strcmp(digestb64, isccc_sexpr_tostring(hmd5)) != 0) + return (ISCCC_R_BADAUTH); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +table_fromwire(isccc_region_t *source, isccc_region_t *secret, + isccc_sexpr_t **alistp); + +static isc_result_t +list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp); + +static isc_result_t +value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep) +{ + unsigned int msgtype; + isc_uint32_t len; + isccc_sexpr_t *value; + isccc_region_t active; + isc_result_t result; + + if (REGION_SIZE(*source) < 1 + 4) + return (ISC_R_UNEXPECTEDEND); + GET8(msgtype, source->rstart); + GET32(len, source->rstart); + if (REGION_SIZE(*source) < len) + return (ISC_R_UNEXPECTEDEND); + active.rstart = source->rstart; + active.rend = active.rstart + len; + source->rstart = active.rend; + if (msgtype == ISCCC_CCMSGTYPE_BINARYDATA) { + value = isccc_sexpr_frombinary(&active); + if (value != NULL) { + *valuep = value; + result = ISC_R_SUCCESS; + } else + result = ISC_R_NOMEMORY; + } else if (msgtype == ISCCC_CCMSGTYPE_TABLE) + result = table_fromwire(&active, NULL, valuep); + else if (msgtype == ISCCC_CCMSGTYPE_LIST) + result = list_fromwire(&active, valuep); + else + result = ISCCC_R_SYNTAX; + + return (result); +} + +static isc_result_t +table_fromwire(isccc_region_t *source, isccc_region_t *secret, + isccc_sexpr_t **alistp) +{ + char key[256]; + isc_uint32_t len; + isc_result_t result; + isccc_sexpr_t *alist, *value; + isc_boolean_t first_tag; + unsigned char *checksum_rstart; + + REQUIRE(alistp != NULL && *alistp == NULL); + + checksum_rstart = NULL; + first_tag = ISC_TRUE; + alist = isccc_alist_create(); + if (alist == NULL) + return (ISC_R_NOMEMORY); + + while (!REGION_EMPTY(*source)) { + GET8(len, source->rstart); + if (REGION_SIZE(*source) < len) { + result = ISC_R_UNEXPECTEDEND; + goto bad; + } + GET_MEM(key, len, source->rstart); + key[len] = '\0'; /* Ensure NUL termination. */ + value = NULL; + result = value_fromwire(source, &value); + if (result != ISC_R_SUCCESS) + goto bad; + if (isccc_alist_define(alist, key, value) == NULL) { + result = ISC_R_NOMEMORY; + goto bad; + } + if (first_tag && secret != NULL && strcmp(key, "_auth") == 0) + checksum_rstart = source->rstart; + first_tag = ISC_FALSE; + } + + *alistp = alist; + + if (secret != NULL) { + if (checksum_rstart != NULL) + return (verify(alist, checksum_rstart, + (source->rend - checksum_rstart), + secret)); + return (ISCCC_R_BADAUTH); + } + + return (ISC_R_SUCCESS); + + bad: + isccc_sexpr_free(&alist); + + return (result); +} + +static isc_result_t +list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp) +{ + isccc_sexpr_t *list, *value; + isc_result_t result; + + list = NULL; + while (!REGION_EMPTY(*source)) { + value = NULL; + result = value_fromwire(source, &value); + if (result != ISC_R_SUCCESS) { + isccc_sexpr_free(&list); + return (result); + } + if (isccc_sexpr_addtolist(&list, value) == NULL) { + isccc_sexpr_free(&value); + isccc_sexpr_free(&list); + return (result); + } + } + + *listp = list; + + return (ISC_R_SUCCESS); +} + +isc_result_t +isccc_cc_fromwire(isccc_region_t *source, isccc_sexpr_t **alistp, + isccc_region_t *secret) +{ + unsigned int size; + isc_uint32_t version; + + size = REGION_SIZE(*source); + if (size < 4) + return (ISC_R_UNEXPECTEDEND); + GET32(version, source->rstart); + if (version != 1) + return (ISCCC_R_UNKNOWNVERSION); + + return (table_fromwire(source, secret, alistp)); +} + +static isc_result_t +createmessage(isc_uint32_t version, const char *from, const char *to, + isc_uint32_t serial, isccc_time_t now, + isccc_time_t expires, isccc_sexpr_t **alistp, + isc_boolean_t want_expires) +{ + isccc_sexpr_t *alist, *_ctrl, *_data; + isc_result_t result; + + REQUIRE(alistp != NULL && *alistp == NULL); + + if (version != 1) + return (ISCCC_R_UNKNOWNVERSION); + + alist = isccc_alist_create(); + if (alist == NULL) + return (ISC_R_NOMEMORY); + + result = ISC_R_NOMEMORY; + + _ctrl = isccc_alist_create(); + _data = isccc_alist_create(); + if (_ctrl == NULL || _data == NULL) + goto bad; + if (isccc_alist_define(alist, "_ctrl", _ctrl) == NULL || + isccc_alist_define(alist, "_data", _data) == NULL) + goto bad; + if (isccc_cc_defineuint32(_ctrl, "_ser", serial) == NULL || + isccc_cc_defineuint32(_ctrl, "_tim", now) == NULL || + (want_expires && + isccc_cc_defineuint32(_ctrl, "_exp", expires) == NULL)) + goto bad; + if (from != NULL && + isccc_cc_definestring(_ctrl, "_frm", from) == NULL) + goto bad; + if (to != NULL && + isccc_cc_definestring(_ctrl, "_to", to) == NULL) + goto bad; + + *alistp = alist; + + return (ISC_R_SUCCESS); + + bad: + isccc_sexpr_free(&alist); + + return (result); +} + +isc_result_t +isccc_cc_createmessage(isc_uint32_t version, const char *from, const char *to, + isc_uint32_t serial, isccc_time_t now, + isccc_time_t expires, isccc_sexpr_t **alistp) +{ + return (createmessage(version, from, to, serial, now, expires, + alistp, ISC_TRUE)); +} + +isc_result_t +isccc_cc_createack(isccc_sexpr_t *message, isc_boolean_t ok, + isccc_sexpr_t **ackp) +{ + char *_frm, *_to; + isc_uint32_t serial; + isccc_sexpr_t *ack, *_ctrl; + isc_result_t result; + isccc_time_t t; + + REQUIRE(ackp != NULL && *ackp == NULL); + + _ctrl = isccc_alist_lookup(message, "_ctrl"); + if (_ctrl == NULL || + isccc_cc_lookupuint32(_ctrl, "_ser", &serial) != ISC_R_SUCCESS || + isccc_cc_lookupuint32(_ctrl, "_tim", &t) != ISC_R_SUCCESS) + return (ISC_R_FAILURE); + /* + * _frm and _to are optional. + */ + _frm = NULL; + (void)isccc_cc_lookupstring(_ctrl, "_frm", &_frm); + _to = NULL; + (void)isccc_cc_lookupstring(_ctrl, "_to", &_to); + /* + * Create the ack. + */ + ack = NULL; + result = createmessage(1, _to, _frm, serial, t, 0, &ack, ISC_FALSE); + if (result != ISC_R_SUCCESS) + return (result); + + _ctrl = isccc_alist_lookup(ack, "_ctrl"); + if (_ctrl == NULL) + return (ISC_R_FAILURE); + if (isccc_cc_definestring(ack, "_ack", (ok) ? "1" : "0") == NULL) { + result = ISC_R_NOMEMORY; + goto bad; + } + + *ackp = ack; + + return (ISC_R_SUCCESS); + + bad: + isccc_sexpr_free(&ack); + + return (result); +} + +isc_boolean_t +isccc_cc_isack(isccc_sexpr_t *message) +{ + isccc_sexpr_t *_ctrl; + + _ctrl = isccc_alist_lookup(message, "_ctrl"); + if (_ctrl == NULL) + return (ISC_R_FAILURE); + if (isccc_cc_lookupstring(_ctrl, "_ack", NULL) == ISC_R_SUCCESS) + return (ISC_TRUE); + return (ISC_FALSE); +} + +isc_boolean_t +isccc_cc_isreply(isccc_sexpr_t *message) +{ + isccc_sexpr_t *_ctrl; + + _ctrl = isccc_alist_lookup(message, "_ctrl"); + if (_ctrl == NULL) + return (ISC_R_FAILURE); + if (isccc_cc_lookupstring(_ctrl, "_rpl", NULL) == ISC_R_SUCCESS) + return (ISC_TRUE); + return (ISC_FALSE); +} + +isc_result_t +isccc_cc_createresponse(isccc_sexpr_t *message, isccc_time_t now, + isccc_time_t expires, isccc_sexpr_t **alistp) +{ + char *_frm, *_to, *type; + isc_uint32_t serial; + isccc_sexpr_t *alist, *_ctrl, *_data; + isc_result_t result; + + REQUIRE(alistp != NULL && *alistp == NULL); + + _ctrl = isccc_alist_lookup(message, "_ctrl"); + _data = isccc_alist_lookup(message, "_data"); + if (_ctrl == NULL || + _data == NULL || + isccc_cc_lookupuint32(_ctrl, "_ser", &serial) != ISC_R_SUCCESS || + isccc_cc_lookupstring(_data, "type", &type) != ISC_R_SUCCESS) + return (ISC_R_FAILURE); + /* + * _frm and _to are optional. + */ + _frm = NULL; + (void)isccc_cc_lookupstring(_ctrl, "_frm", &_frm); + _to = NULL; + (void)isccc_cc_lookupstring(_ctrl, "_to", &_to); + /* + * Create the response. + */ + alist = NULL; + result = isccc_cc_createmessage(1, _to, _frm, serial, now, expires, + &alist); + if (result != ISC_R_SUCCESS) + return (result); + _ctrl = isccc_alist_lookup(alist, "_ctrl"); + if (_ctrl == NULL) + return (ISC_R_FAILURE); + _data = isccc_alist_lookup(alist, "_data"); + if (_data == NULL) + return (ISC_R_FAILURE); + if (isccc_cc_definestring(_ctrl, "_rpl", "1") == NULL || + isccc_cc_definestring(_data, "type", type) == NULL) { + isccc_sexpr_free(&alist); + return (ISC_R_NOMEMORY); + } + + *alistp = alist; + + return (ISC_R_SUCCESS); +} + +isccc_sexpr_t * +isccc_cc_definestring(isccc_sexpr_t *alist, const char *key, const char *str) +{ + size_t len; + isccc_region_t r; + + len = strlen(str); + DE_CONST(str, r.rstart); + r.rend = r.rstart + len; + + return (isccc_alist_definebinary(alist, key, &r)); +} + +isccc_sexpr_t * +isccc_cc_defineuint32(isccc_sexpr_t *alist, const char *key, isc_uint32_t i) +{ + char b[100]; + size_t len; + isccc_region_t r; + + sprintf(b, "%u", i); + len = strlen(b); + r.rstart = b; + r.rend = b + len; + + return (isccc_alist_definebinary(alist, key, &r)); +} + +isc_result_t +isccc_cc_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp) +{ + isccc_sexpr_t *kv, *v; + + kv = isccc_alist_assq(alist, key); + if (kv != NULL) { + v = ISCCC_SEXPR_CDR(kv); + if (isccc_sexpr_binaryp(v)) { + if (strp != NULL) + *strp = isccc_sexpr_tostring(v); + return (ISC_R_SUCCESS); + } else + return (ISC_R_EXISTS); + } + + return (ISC_R_NOTFOUND); +} + +isc_result_t +isccc_cc_lookupuint32(isccc_sexpr_t *alist, const char *key, + isc_uint32_t *uintp) +{ + isccc_sexpr_t *kv, *v; + + kv = isccc_alist_assq(alist, key); + if (kv != NULL) { + v = ISCCC_SEXPR_CDR(kv); + if (isccc_sexpr_binaryp(v)) { + if (uintp != NULL) + *uintp = (isc_uint32_t) + strtoul(isccc_sexpr_tostring(v), + NULL, 10); + return (ISC_R_SUCCESS); + } else + return (ISC_R_EXISTS); + } + + return (ISC_R_NOTFOUND); +} + +static void +symtab_undefine(char *key, unsigned int type, isccc_symvalue_t value, + void *arg) +{ + UNUSED(type); + UNUSED(value); + UNUSED(arg); + + free(key); +} + +static isc_boolean_t +symtab_clean(char *key, unsigned int type, isccc_symvalue_t value, + void *arg) +{ + isccc_time_t *now; + + UNUSED(key); + UNUSED(type); + + now = arg; + + if (*now < value.as_uinteger) + return (ISC_FALSE); + if ((*now - value.as_uinteger) < DUP_LIFETIME) + return (ISC_FALSE); + return (ISC_TRUE); +} + +isc_result_t +isccc_cc_createsymtab(isccc_symtab_t **symtabp) +{ + return (isccc_symtab_create(11897, symtab_undefine, NULL, ISC_FALSE, + symtabp)); +} + +void +isccc_cc_cleansymtab(isccc_symtab_t *symtab, isccc_time_t now) +{ + isccc_symtab_foreach(symtab, symtab_clean, &now); +} + +static isc_boolean_t +has_whitespace(const char *str) +{ + char c; + + if (str == NULL) + return (ISC_FALSE); + while ((c = *str++) != '\0') { + if (c == ' ' || c == '\t' || c == '\n') + return (ISC_TRUE); + } + return (ISC_FALSE); +} + +isc_result_t +isccc_cc_checkdup(isccc_symtab_t *symtab, isccc_sexpr_t *message, + isccc_time_t now) +{ + const char *_frm; + const char *_to; + char *_ser, *_tim, *tmp; + isc_result_t result; + char *key; + size_t len; + isccc_symvalue_t value; + isccc_sexpr_t *_ctrl; + + _ctrl = isccc_alist_lookup(message, "_ctrl"); + if (_ctrl == NULL || + isccc_cc_lookupstring(_ctrl, "_ser", &_ser) != ISC_R_SUCCESS || + isccc_cc_lookupstring(_ctrl, "_tim", &_tim) != ISC_R_SUCCESS) + return (ISC_R_FAILURE); + /* + * _frm and _to are optional. + */ + if (isccc_cc_lookupstring(_ctrl, "_frm", &tmp) != ISC_R_SUCCESS) + _frm = ""; + else + _frm = tmp; + if (isccc_cc_lookupstring(_ctrl, "_to", &tmp) != ISC_R_SUCCESS) + _to = ""; + else + _to = tmp; + /* + * Ensure there is no newline in any of the strings. This is so + * we can write them to a file later. + */ + if (has_whitespace(_frm) || has_whitespace(_to) || + has_whitespace(_ser) || has_whitespace(_tim)) + return (ISC_R_FAILURE); + len = strlen(_frm) + strlen(_to) + strlen(_ser) + strlen(_tim) + 4; + key = malloc(len); + if (key == NULL) + return (ISC_R_NOMEMORY); + sprintf(key, "%s;%s;%s;%s", _frm, _to, _ser, _tim); + value.as_uinteger = now; + result = isccc_symtab_define(symtab, key, ISCCC_SYMTYPE_CCDUP, value, + isccc_symexists_reject); + if (result != ISC_R_SUCCESS) { + free(key); + return (result); + } + + return (ISC_R_SUCCESS); +} + +isc_result_t +isccc_cc_readsymtab(isccc_symtab_t *symtab, const char *filename) +{ + FILE *f; + size_t len; + char s[4096]; + char *key, *dup_key; + char *value; + isccc_symvalue_t sv; + isc_result_t result; + + f = fopen(filename, "r"); + if (f == NULL) { + if (errno == ENOENT) + return (ISC_R_NOTFOUND); + else + return (isccc_result_fromerrno(errno)); + } + while (fgets(s, sizeof s, f) != NULL) { + len = strlen(s); + if (len > 0 && s[len - 1] == '\n') { + s[len - 1] = '\0'; + len--; + } + key = s; + value = s; + while (*value != ' ' && *value != '\t' && *value != '\0') + value++; + if (value == '\0') { + /* + * No value? Skip this line. + */ + continue; + } + /* + * Option has a value. Terminate the key and skip to + * the beginning of the value. + */ + *value = '\0'; + value++; + while (*value == ' ' || *value == '\t') + value++; + dup_key = strdup(key); + if (dup_key == NULL) { + fclose(f); + return (ISC_R_NOMEMORY); + } + sv.as_uinteger = atoi(value); + result = isccc_symtab_define(symtab, dup_key, + ISCCC_SYMTYPE_CCDUP, + sv, isccc_symexists_reject); + if (result != ISC_R_SUCCESS) { + free(dup_key); + fclose(f); + return (result); + } + } + fclose(f); + + return (ISC_R_SUCCESS); +} + +static isc_boolean_t +symtab_print(char *key, unsigned int type, isccc_symvalue_t value, + void *arg) +{ + FILE *f; + + UNUSED(type); + + f = arg; + + (void)fprintf(f, "%s\t%u\n", key, value.as_uinteger); + + return (ISC_FALSE); +} + +isc_result_t +isccc_cc_writesymtab(isccc_symtab_t *symtab, const char *filename) +{ + FILE *f; + char *newfilename; + size_t len; + isc_result_t result; + + len = strlen(filename) + 4 + 1; + newfilename = malloc(len); + if (newfilename == NULL) + return (ISC_R_NOMEMORY); + /* + * This is safe. + */ + sprintf(newfilename, "%s.new", filename); + + f = fopen(newfilename, "w"); + if (f == NULL) { + free(newfilename); + return (isccc_result_fromerrno(errno)); + } + + isccc_symtab_foreach(symtab, symtab_print, f); + + result = ISC_R_SUCCESS; + if (ferror(f)) + result = ISC_R_FAILURE; + if (fclose(f) == EOF) + result = isccc_result_fromerrno(errno); + if (result == ISC_R_SUCCESS) { + if (rename(newfilename, filename) < 0) + result = isccc_result_fromerrno(errno); + } + free(newfilename); + + return (result); +} diff --git a/lib/isccc/ccmsg.c b/lib/isccc/ccmsg.c new file mode 100644 index 0000000000..b6eb621764 --- /dev/null +++ b/lib/isccc/ccmsg.c @@ -0,0 +1,229 @@ +/* + * Copyright (C) 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: ccmsg.c,v 1.1 2001/03/27 00:44:48 bwelling Exp $ */ + +#include + +#include +#include +#include +#include + +#include +#include + +#define CCMSG_MAGIC 0x43436d73 /* CCms */ +#define VALID_CCMSG(foo) ISC_MAGIC_VALID(foo, CCMSG_MAGIC) + +static void recv_length(isc_task_t *, isc_event_t *); +static void recv_message(isc_task_t *, isc_event_t *); + + +static void +recv_length(isc_task_t *task, isc_event_t *ev_in) { + isc_socketevent_t *ev = (isc_socketevent_t *)ev_in; + isc_event_t *dev; + isccc_ccmsg_t *ccmsg = ev_in->ev_arg; + isc_region_t region; + isc_result_t result; + + INSIST(VALID_CCMSG(ccmsg)); + + dev = &ccmsg->event; + + if (ev->result != ISC_R_SUCCESS) { + ccmsg->result = ev->result; + goto send_and_free; + } + + /* + * Success. + */ + ccmsg->size = ntohl(ccmsg->size); + if (ccmsg->size == 0) { + ccmsg->result = ISC_R_UNEXPECTEDEND; + goto send_and_free; + } + if (ccmsg->size > ccmsg->maxsize) { + ccmsg->result = ISC_R_RANGE; + goto send_and_free; + } + + region.base = isc_mem_get(ccmsg->mctx, ccmsg->size); + region.length = ccmsg->size; + if (region.base == NULL) { + ccmsg->result = ISC_R_NOMEMORY; + goto send_and_free; + } + + isc_buffer_init(&ccmsg->buffer, region.base, region.length); + result = isc_socket_recv(ccmsg->sock, ®ion, 0, + task, recv_message, ccmsg); + if (result != ISC_R_SUCCESS) { + ccmsg->result = result; + goto send_and_free; + } + + isc_event_free(&ev_in); + return; + + send_and_free: + isc_task_send(ccmsg->task, &dev); + ccmsg->task = NULL; + isc_event_free(&ev_in); + return; +} + +static void +recv_message(isc_task_t *task, isc_event_t *ev_in) { + isc_socketevent_t *ev = (isc_socketevent_t *)ev_in; + isc_event_t *dev; + isccc_ccmsg_t *ccmsg = ev_in->ev_arg; + + (void)task; + + INSIST(VALID_CCMSG(ccmsg)); + + dev = &ccmsg->event; + + if (ev->result != ISC_R_SUCCESS) { + ccmsg->result = ev->result; + goto send_and_free; + } + + ccmsg->result = ISC_R_SUCCESS; + isc_buffer_add(&ccmsg->buffer, ev->n); + ccmsg->address = ev->address; + + send_and_free: + isc_task_send(ccmsg->task, &dev); + ccmsg->task = NULL; + isc_event_free(&ev_in); +} + +void +isccc_ccmsg_init(isc_mem_t *mctx, isc_socket_t *sock, isccc_ccmsg_t *ccmsg) { + REQUIRE(mctx != NULL); + REQUIRE(sock != NULL); + REQUIRE(ccmsg != NULL); + + ccmsg->magic = CCMSG_MAGIC; + ccmsg->size = 0; + ccmsg->buffer.base = NULL; + ccmsg->buffer.length = 0; + ccmsg->maxsize = 4294967295U; /* Largest message possible. */ + ccmsg->mctx = mctx; + ccmsg->sock = sock; + ccmsg->task = NULL; /* None yet. */ + ccmsg->result = ISC_R_UNEXPECTED; /* None yet. */ + /* + * Should probably initialize the event here, but it can wait. + */ +} + + +void +isccc_ccmsg_setmaxsize(isccc_ccmsg_t *ccmsg, unsigned int maxsize) { + REQUIRE(VALID_CCMSG(ccmsg)); + + ccmsg->maxsize = maxsize; +} + + +isc_result_t +isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg, + isc_task_t *task, isc_taskaction_t action, void *arg) +{ + isc_result_t result; + isc_region_t region; + + REQUIRE(VALID_CCMSG(ccmsg)); + REQUIRE(task != NULL); + REQUIRE(ccmsg->task == NULL); /* not currently in use */ + + if (ccmsg->buffer.base != NULL) { + isc_mem_put(ccmsg->mctx, ccmsg->buffer.base, + ccmsg->buffer.length); + ccmsg->buffer.base = NULL; + ccmsg->buffer.length = 0; + } + + ccmsg->task = task; + ccmsg->action = action; + ccmsg->arg = arg; + ccmsg->result = ISC_R_UNEXPECTED; /* unknown right now */ + + ISC_EVENT_INIT(&ccmsg->event, sizeof(isc_event_t), 0, 0, + ISCCC_EVENT_CCMSG, action, arg, ccmsg, + NULL, NULL); + + region.base = (unsigned char *)&ccmsg->size; + region.length = 4; /* isc_uint32_t */ + result = isc_socket_recv(ccmsg->sock, ®ion, 0, + ccmsg->task, recv_length, ccmsg); + + if (result != ISC_R_SUCCESS) + ccmsg->task = NULL; + + return (result); +} + +void +isccc_ccmsg_cancelread(isccc_ccmsg_t *ccmsg) { + REQUIRE(VALID_CCMSG(ccmsg)); + + isc_socket_cancel(ccmsg->sock, NULL, ISC_SOCKCANCEL_RECV); +} + +void +isccc_ccmsg_keepbuffer(isccc_ccmsg_t *ccmsg, isc_buffer_t *buffer) { + REQUIRE(VALID_CCMSG(ccmsg)); + REQUIRE(buffer != NULL); + + *buffer = ccmsg->buffer; + ccmsg->buffer.base = NULL; + ccmsg->buffer.length = 0; +} + +#if 0 +void +isccc_ccmsg_freebuffer(isccc_ccmsg_t *ccmsg) { + REQUIRE(VALID_CCMSG(ccmsg)); + + if (ccmsg->buffer.base == NULL) + return; + + isc_mem_put(ccmsg->mctx, ccmsg->buffer.base, ccmsg->buffer.length); + ccmsg->buffer.base = NULL; + ccmsg->buffer.length = 0; +} +#endif + +void +isccc_ccmsg_invalidate(isccc_ccmsg_t *ccmsg) { + REQUIRE(VALID_CCMSG(ccmsg)); + + ccmsg->magic = 0; + + if (ccmsg->buffer.base != NULL) { + isc_mem_put(ccmsg->mctx, ccmsg->buffer.base, + ccmsg->buffer.length); + ccmsg->buffer.base = NULL; + ccmsg->buffer.length = 0; + } +} diff --git a/lib/isccc/include/.cvsignore b/lib/isccc/include/.cvsignore new file mode 100644 index 0000000000..177889918b --- /dev/null +++ b/lib/isccc/include/.cvsignore @@ -0,0 +1,18 @@ +# Copyright (C) 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: .cvsignore,v 1.1 2001/03/27 00:44:49 bwelling Exp $ + +Makefile diff --git a/lib/isccc/include/Makefile.in b/lib/isccc/include/Makefile.in new file mode 100644 index 0000000000..25b297ec84 --- /dev/null +++ b/lib/isccc/include/Makefile.in @@ -0,0 +1,25 @@ +# Copyright (C) 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.1 2001/03/27 00:44:49 bwelling Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +SUBDIRS = isccfg +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/isccc/include/isccc/.cvsignore b/lib/isccc/include/isccc/.cvsignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/lib/isccc/include/isccc/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/lib/isccc/include/isccc/Makefile.in b/lib/isccc/include/isccc/Makefile.in new file mode 100644 index 0000000000..0acfc8de25 --- /dev/null +++ b/lib/isccc/include/isccc/Makefile.in @@ -0,0 +1,42 @@ +# Copyright (C) 1998-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.1 2001/03/27 00:44:50 bwelling Exp $ + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +@BIND9_VERSION@ + +# +# Only list headers that are to be installed and are not +# machine generated. The latter are handled specially in the +# install target below. +# +HEADERS = alist.h cc.h sexpr.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isccc + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/isccc ; \ + done diff --git a/lib/isccc/include/isccc/alist.h b/lib/isccc/include/isccc/alist.h new file mode 100644 index 0000000000..86e037b5cc --- /dev/null +++ b/lib/isccc/include/isccc/alist.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 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: alist.h,v 1.1 2001/03/27 00:44:50 bwelling Exp $ */ + +#ifndef ISCCC_ALIST_H +#define ISCCC_ALIST_H 1 + +#include + +#include +#include + +ISC_LANG_BEGINDECLS + +isccc_sexpr_t * +isccc_alist_create(void); + +isc_boolean_t +isccc_alist_alistp(isccc_sexpr_t *alist); + +isc_boolean_t +isccc_alist_emptyp(isccc_sexpr_t *alist); + +isccc_sexpr_t * +isccc_alist_first(isccc_sexpr_t *alist); + +isccc_sexpr_t * +isccc_alist_assq(isccc_sexpr_t *alist, const char *key); + +void +isccc_alist_delete(isccc_sexpr_t *alist, const char *key); + +isccc_sexpr_t * +isccc_alist_define(isccc_sexpr_t *alist, const char *key, isccc_sexpr_t *value); + +isccc_sexpr_t * +isccc_alist_definestring(isccc_sexpr_t *alist, const char *key, const char *str); + +isccc_sexpr_t * +isccc_alist_definebinary(isccc_sexpr_t *alist, const char *key, isccc_region_t *r); + +isccc_sexpr_t * +isccc_alist_lookup(isccc_sexpr_t *alist, const char *key); + +isc_result_t +isccc_alist_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp); + +isc_result_t +isccc_alist_lookupbinary(isccc_sexpr_t *alist, const char *key, isccc_region_t **r); + +void +isccc_alist_prettyprint(isccc_sexpr_t *sexpr, unsigned int indent, FILE *stream); + +ISC_LANG_ENDDECLS + +#endif /* ISCCC_ALIST_H */ diff --git a/lib/isccc/include/isccc/base64.h b/lib/isccc/include/isccc/base64.h new file mode 100644 index 0000000000..271e0fa2fd --- /dev/null +++ b/lib/isccc/include/isccc/base64.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 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: base64.h,v 1.1 2001/03/27 00:44:50 bwelling Exp $ */ + +#ifndef ISCCC_BASE64_H +#define ISCCC_BASE64_H 1 + +#include +#include + +ISC_LANG_BEGINDECLS + +/*** + *** Functions + ***/ + +isc_result_t +isccc_base64_encode(isccc_region_t *source, int wordlength, + const char *wordbreak, isccc_region_t *target); +/* + * Convert data into base64 encoded text. + * + * Notes: + * The base64 encoded text in 'target' will be divided into + * words of at most 'wordlength' characters, separated by + * the 'wordbreak' string. No parentheses will surround + * the text. + * + * Requires: + * 'source' is a region containing binary data. + * 'target' is a text region containing available space. + * 'wordbreak' points to a null-terminated string of + * zero or more whitespace characters. + */ + +isc_result_t +isccc_base64_decode(const char *cstr, isccc_region_t *target); +/* + * Decode a null-terminated base64 string. + * + * Requires: + * 'cstr' is non-null. + * 'target' is a valid region. + * + * Returns: + * ISC_R_SUCCESS -- the entire decoded representation of 'cstring' + * fit in 'target'. + * ISC_R_BADBASE64 -- 'cstr' is not a valid base64 encoding. + * ISC_R_NOSPACE -- 'target' is not big enough. + */ + +ISC_LANG_ENDDECLS + +#endif /* ISCCC_BASE64_H */ diff --git a/lib/isccc/include/isccc/cc.h b/lib/isccc/include/isccc/cc.h new file mode 100644 index 0000000000..f4bece7b3f --- /dev/null +++ b/lib/isccc/include/isccc/cc.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 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: cc.h,v 1.1 2001/03/27 00:44:50 bwelling Exp $ */ + +#ifndef ISCCC_CC_H +#define ISCCC_CC_H 1 + +#include +#include + +ISC_LANG_BEGINDECLS + +#define ISCCC_CC_MAXDGRAMPACKET 4096 + +#define ISCCC_CCMSGTYPE_STRING 0x00 +#define ISCCC_CCMSGTYPE_BINARYDATA 0x01 +#define ISCCC_CCMSGTYPE_TABLE 0x02 +#define ISCCC_CCMSGTYPE_LIST 0x03 + +isc_result_t +isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target, + isccc_region_t *secret); + +isc_result_t +isccc_cc_fromwire(isccc_region_t *source, isccc_sexpr_t **alistp, + isccc_region_t *secret); + +isc_result_t +isccc_cc_createmessage(isc_uint32_t version, const char *from, const char *to, + isc_uint32_t serial, isccc_time_t now, + isccc_time_t expires, isccc_sexpr_t **alistp); + +isc_result_t +isccc_cc_createack(isccc_sexpr_t *message, isc_boolean_t ok, + isccc_sexpr_t **ackp); + +isc_boolean_t +isccc_cc_isack(isccc_sexpr_t *message); + +isc_boolean_t +isccc_cc_isreply(isccc_sexpr_t *message); + +isc_result_t +isccc_cc_createresponse(isccc_sexpr_t *message, isccc_time_t now, + isccc_time_t expires, isccc_sexpr_t **alistp); + +isccc_sexpr_t * +isccc_cc_definestring(isccc_sexpr_t *alist, const char *key, const char *str); + +isccc_sexpr_t * +isccc_cc_defineuint32(isccc_sexpr_t *alist, const char *key, isc_uint32_t i); + +isc_result_t +isccc_cc_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp); + +isc_result_t +isccc_cc_lookupuint32(isccc_sexpr_t *alist, const char *key, + isc_uint32_t *uintp); + +isc_result_t +isccc_cc_createsymtab(isccc_symtab_t **symtabp); + +void +isccc_cc_cleansymtab(isccc_symtab_t *symtab, isccc_time_t now); + +isc_result_t +isccc_cc_checkdup(isccc_symtab_t *symtab, isccc_sexpr_t *message, + isccc_time_t now); + +isc_result_t +isccc_cc_readsymtab(isccc_symtab_t *symtab, const char *filename); + +isc_result_t +isccc_cc_writesymtab(isccc_symtab_t *symtab, const char *filename); + +ISC_LANG_ENDDECLS + +#endif /* ISCCC_CC_H */ diff --git a/lib/isccc/include/isccc/ccmsg.h b/lib/isccc/include/isccc/ccmsg.h new file mode 100644 index 0000000000..a2a2981fcb --- /dev/null +++ b/lib/isccc/include/isccc/ccmsg.h @@ -0,0 +1,145 @@ +/* + * Copyright (C) 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: ccmsg.h,v 1.1 2001/03/27 00:44:51 bwelling Exp $ */ + +#ifndef DNS_CCMSG_H +#define DNS_CCMSG_H 1 + +#include +#include +#include + +typedef struct isccc_ccmsg { + /* private (don't touch!) */ + unsigned int magic; + isc_uint32_t size; + isc_buffer_t buffer; + unsigned int maxsize; + isc_mem_t *mctx; + isc_socket_t *sock; + isc_task_t *task; + isc_taskaction_t action; + void *arg; + isc_event_t event; + /* public (read-only) */ + isc_result_t result; + isc_sockaddr_t address; +} isccc_ccmsg_t; + +ISC_LANG_BEGINDECLS + +void +isccc_ccmsg_init(isc_mem_t *mctx, isc_socket_t *sock, isccc_ccmsg_t *ccmsg); +/* + * Associate a cc message state with a given memory context and + * TCP socket. + * + * Requires: + * + * "mctx" and "sock" be non-NULL and valid types. + * + * "sock" be a read/write TCP socket. + * + * "ccmsg" be non-NULL and an uninitialized or invalidated structure. + * + * Ensures: + * + * "ccmsg" is a valid structure. + */ + +void +isccc_ccmsg_setmaxsize(isccc_ccmsg_t *ccmsg, unsigned int maxsize); +/* + * Set the maximum packet size to "maxsize" + * + * Requires: + * + * "ccmsg" be valid. + * + * 512 <= "maxsize" <= 4294967296 + */ + +isc_result_t +isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg, + isc_task_t *task, isc_taskaction_t action, void *arg); +/* + * Schedule an event to be delivered when a DNS message is readable, or + * when an error occurs on the socket. + * + * Requires: + * + * "ccmsg" be valid. + * + * "task", "taskaction", and "arg" be valid. + * + * Returns: + * + * ISC_R_SUCCESS -- no error + * Anything that the isc_socket_recv() call can return. XXXMLG + * + * Notes: + * + * The event delivered is a fully generic event. It will contain no + * actual data. The sender will be a pointer to the isccc_ccmsg_t. + * The result code inside that structure should be checked to see + * what the final result was. + */ + +void +isccc_ccmsg_cancelread(isccc_ccmsg_t *ccmsg); +/* + * Cancel a readmessage() call. The event will still be posted with a + * CANCELED result code. + * + * Requires: + * + * "ccmsg" be valid. + */ + +void +isccc_ccmsg_keepbuffer(isccc_ccmsg_t *ccmsg, isc_buffer_t *buffer); +/* + * If a isccc buffer is to be kept between calls, this function marks the + * internal state-machine buffer as invalid, and copies all the contents + * of the state into "buffer". + * + * Requires: + * + * "ccmsg" be valid. + * + * "buffer" be non-NULL. + */ + +void +isccc_ccmsg_invalidate(isccc_ccmsg_t *ccmsg); +/* + * Clean up all allocated state, and invalidate the structure. + * + * Requires: + * + * "ccmsg" be valid. + * + * Ensures: + * + * "ccmsg" is invalidated and disassociated with all memory contexts, + * sockets, etc. + */ + +ISC_LANG_ENDDECLS + +#endif /* DNS_CCMSG_H */ diff --git a/lib/isccc/include/isccc/events.h b/lib/isccc/include/isccc/events.h new file mode 100644 index 0000000000..29f2166926 --- /dev/null +++ b/lib/isccc/include/isccc/events.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 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: events.h,v 1.1 2001/03/27 00:44:51 bwelling Exp $ */ + +#ifndef ISCCC_EVENTS_H +#define ISCCC_EVENTS_H 1 + +#include + +/* + * Registry of ISCCC event numbers. + */ + +#define ISCCC_EVENT_CCMSG (ISC_EVENTCLASS_ISCCC + 0) + +#define ISCCC_EVENT_FIRSTEVENT (ISC_EVENTCLASS_ISCCC + 0) +#define ISCCC_EVENT_LASTEVENT (ISC_EVENTCLASS_ISCCC + 65535) + +#endif /* ISCCC_EVENTS_H */ diff --git a/lib/isccc/include/isccc/lib.h b/lib/isccc/include/isccc/lib.h new file mode 100644 index 0000000000..a6e539b4d3 --- /dev/null +++ b/lib/isccc/include/isccc/lib.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 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.1 2001/03/27 00:44:51 bwelling Exp $ */ + +#ifndef ISCCC_LIB_H +#define ISCCC_LIB_H 1 + +#include +#include + +ISC_LANG_BEGINDECLS + +extern isc_msgcat_t *isccc_msgcat; + +void +isccc_lib_initmsgcat(void); +/* + * Initialize the ISCCC library's message catalog, isccc_msgcat, if it + * has not already been initialized. + */ + +ISC_LANG_ENDDECLS + +#endif /* ISCCC_LIB_H */ diff --git a/lib/isccc/include/isccc/result.h b/lib/isccc/include/isccc/result.h new file mode 100644 index 0000000000..c51a95dbb4 --- /dev/null +++ b/lib/isccc/include/isccc/result.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 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.1 2001/03/27 00:44:51 bwelling Exp $ */ + +#ifndef ISCCC_RESULT_H +#define ISCCC_RESULT_H 1 + +#include +#include +#include + +#include + +#define ISCCC_R_UNKNOWNVERSION (ISC_RESULTCLASS_ISCCC + 0) +#define ISCCC_R_SYNTAX (ISC_RESULTCLASS_ISCCC + 1) +#define ISCCC_R_BADAUTH (ISC_RESULTCLASS_ISCCC + 2) + +#define ISCCC_R_NRESULTS 3 /* Number of results */ + +#define ISCCC_RESULT_OSBASE 0x01000000 +#define ISCCC_RESULT_OSMASK 0x00ffffff + +ISC_LANG_BEGINDECLS + +const char * +isccc_result_totext(isc_result_t result); +/* + * Convert a isccc_result_t into a string message describing the result. + */ + +void +isccc_result_register(void); + +isc_result_t +isccc_result_fromerrno(int ecode); +/* + * Convert a UNIX errno into a isc_result_t. + */ + +ISC_LANG_ENDDECLS + +#endif /* ISCCC_RESULT_H */ diff --git a/lib/isccc/include/isccc/sexpr.h b/lib/isccc/include/isccc/sexpr.h new file mode 100644 index 0000000000..96e810edad --- /dev/null +++ b/lib/isccc/include/isccc/sexpr.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 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: sexpr.h,v 1.1 2001/03/27 00:44:51 bwelling Exp $ */ + +#ifndef ISCCC_SEXPR_H +#define ISCCC_SEXPR_H 1 + +#include + +#include +#include + +ISC_LANG_BEGINDECLS + +struct isccc_dottedpair { + isccc_sexpr_t *car; + isccc_sexpr_t *cdr; +}; + +struct isccc_sexpr { + unsigned int type; + union { + char * as_string; + isccc_dottedpair_t as_dottedpair; + isccc_region_t as_region; + } value; +}; + +#define ISCCC_SEXPRTYPE_NONE 0x00 /* Illegal. */ +#define ISCCC_SEXPRTYPE_T 0x01 +#define ISCCC_SEXPRTYPE_STRING 0x02 +#define ISCCC_SEXPRTYPE_DOTTEDPAIR 0x03 +#define ISCCC_SEXPRTYPE_BINARY 0x04 + +#define ISCCC_SEXPR_CAR(s) (s)->value.as_dottedpair.car +#define ISCCC_SEXPR_CDR(s) (s)->value.as_dottedpair.cdr + +isccc_sexpr_t * +isccc_sexpr_cons(isccc_sexpr_t *car, isccc_sexpr_t *cdr); + +isccc_sexpr_t * +isccc_sexpr_tconst(void); + +isccc_sexpr_t * +isccc_sexpr_nilconst(void); + +isccc_sexpr_t * +isccc_sexpr_fromstring(const char *str); + +isccc_sexpr_t * +isccc_sexpr_frombinary(const isccc_region_t *region); + +void +isccc_sexpr_free(isccc_sexpr_t **sexprp); + +void +isccc_sexpr_print(isccc_sexpr_t *sexpr, FILE *stream); + +isccc_sexpr_t * +isccc_sexpr_car(isccc_sexpr_t *list); + +isccc_sexpr_t * +isccc_sexpr_cdr(isccc_sexpr_t *list); + +void +isccc_sexpr_setcar(isccc_sexpr_t *pair, isccc_sexpr_t *car); + +void +isccc_sexpr_setcdr(isccc_sexpr_t *pair, isccc_sexpr_t *cdr); + +isccc_sexpr_t * +isccc_sexpr_addtolist(isccc_sexpr_t **l1p, isccc_sexpr_t *l2); + +isccc_sexpr_t * +isccc_sexpr_assq(isccc_sexpr_t *alist, const char *key); + +isccc_sexpr_t * +isccc_sexpr_define(isccc_sexpr_t *alist, const char *key, isccc_sexpr_t *value); + +isccc_sexpr_t * +isccc_sexpr_lookup(isccc_sexpr_t *alist, const char *key); + +isc_boolean_t +isccc_sexpr_listp(isccc_sexpr_t *sexpr); + +isc_boolean_t +isccc_sexpr_emptyp(isccc_sexpr_t *sexpr); + +isc_boolean_t +isccc_sexpr_stringp(isccc_sexpr_t *sexpr); + +isc_boolean_t +isccc_sexpr_binaryp(isccc_sexpr_t *sexpr); + +char * +isccc_sexpr_tostring(isccc_sexpr_t *sexpr); + +isccc_region_t * +isccc_sexpr_tobinary(isccc_sexpr_t *sexpr); + +ISC_LANG_ENDDECLS + +#endif /* ISCCC_SEXPR_H */ diff --git a/lib/isccc/include/isccc/symtab.h b/lib/isccc/include/isccc/symtab.h new file mode 100644 index 0000000000..b3fecd49bd --- /dev/null +++ b/lib/isccc/include/isccc/symtab.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 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: symtab.h,v 1.1 2001/03/27 00:44:51 bwelling Exp $ */ + +#ifndef ISCCC_SYMTAB_H +#define ISCCC_SYMTAB_H 1 + +/***** + ***** Module Info + *****/ + +/* + * Symbol Table + * + * Provides a simple memory-based symbol table. + * + * Keys are C strings. A type may be specified when looking up, + * defining, or undefining. A type value of 0 means "match any type"; + * any other value will only match the given type. + * + * It's possible that a client will attempt to define a tuple when a tuple with the given key and type already + * exists in the table. What to do in this case is specified by the + * client. Possible policies are: + * + * isccc_symexists_reject Disallow the define, returning ISC_R_EXISTS + * isccc_symexists_replace Replace the old value with the new. The + * undefine action (if provided) will be called + * with the old tuple. + * isccc_symexists_add Add the new tuple, leaving the old tuple in + * the table. Subsequent lookups will retrieve + * the most-recently-defined tuple. + * + * A lookup of a key using type 0 will return the most-recently + * defined symbol with that key. An undefine of a key using type 0 + * will undefine the most-recently defined symbol with that key. + * Trying to define a key with type 0 is illegal. + * + * The symbol table library does not make a copy the key field, so the + * caller must ensure that any key it passes to isccc_symtab_define() + * will not change until it calls isccc_symtab_undefine() or + * isccc_symtab_destroy(). + * + * A user-specified action will be called (if provided) when a symbol + * is undefined. It can be used to free memory associated with keys + * and/or values. + */ + +/*** + *** Imports. + ***/ + +#include +#include + +/*** + *** Symbol Tables. + ***/ + +typedef union isccc_symvalue { + void * as_pointer; + int as_integer; + unsigned int as_uinteger; +} isccc_symvalue_t; + +typedef void (*isccc_symtabundefaction_t)(char *key, unsigned int type, + isccc_symvalue_t value, void *userarg); + +typedef isc_boolean_t (*isccc_symtabforeachaction_t)(char *key, + unsigned int type, + isccc_symvalue_t value, + void *userarg); + +typedef enum { + isccc_symexists_reject = 0, + isccc_symexists_replace = 1, + isccc_symexists_add = 2 +} isccc_symexists_t; + +ISC_LANG_BEGINDECLS + +isc_result_t +isccc_symtab_create(unsigned int size, + isccc_symtabundefaction_t undefine_action, void *undefine_arg, + isc_boolean_t case_sensitive, isccc_symtab_t **symtabp); + +void +isccc_symtab_destroy(isccc_symtab_t **symtabp); + +isc_result_t +isccc_symtab_lookup(isccc_symtab_t *symtab, const char *key, unsigned int type, + isccc_symvalue_t *value); + +isc_result_t +isccc_symtab_define(isccc_symtab_t *symtab, char *key, unsigned int type, + isccc_symvalue_t value, isccc_symexists_t exists_policy); + +isc_result_t +isccc_symtab_undefine(isccc_symtab_t *symtab, const char *key, unsigned int type); + +void +isccc_symtab_foreach(isccc_symtab_t *symtab, isccc_symtabforeachaction_t action, + void *arg); + +ISC_LANG_ENDDECLS + +#endif /* ISCCC_SYMTAB_H */ diff --git a/lib/isccc/include/isccc/symtype.h b/lib/isccc/include/isccc/symtype.h new file mode 100644 index 0000000000..e88e7b408c --- /dev/null +++ b/lib/isccc/include/isccc/symtype.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 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: symtype.h,v 1.1 2001/03/27 00:44:51 bwelling Exp $ */ + +#ifndef ISCCC_SYMTYPE_H +#define ISCCC_SYMTYPE_H 1 + +#define ISCCC_SYMTYPE_ZONESTATS 0x0001 +#define ISCCC_SYMTYPE_CCDUP 0x0002 +#define ISCCC_SYMTYPE_TELLSERVICE 0x0003 +#define ISCCC_SYMTYPE_TELLRESPONSE 0x0004 + +#endif /* ISCCC_SYMTYPE_H */ diff --git a/lib/isccc/include/isccc/types.h b/lib/isccc/include/isccc/types.h new file mode 100644 index 0000000000..cd72b4ae49 --- /dev/null +++ b/lib/isccc/include/isccc/types.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 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.1 2001/03/27 00:44:51 bwelling Exp $ */ + +#ifndef ISCCC_TYPES_H +#define ISCCC_TYPES_H 1 + +#include +#include +#include + +typedef isc_uint32_t isccc_time_t; +typedef struct isccc_sexpr isccc_sexpr_t; +typedef struct isccc_dottedpair isccc_dottedpair_t; +typedef struct isccc_symtab isccc_symtab_t; + +typedef struct isccc_region { + unsigned char * rstart; + unsigned char * rend; +} isccc_region_t; + +#endif /* ISCCC_TYPES_H */ diff --git a/lib/isccc/include/isccc/util.h b/lib/isccc/include/isccc/util.h new file mode 100644 index 0000000000..4b2e043d5e --- /dev/null +++ b/lib/isccc/include/isccc/util.h @@ -0,0 +1,220 @@ +/* + * Copyright (C) 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: util.h,v 1.1 2001/03/27 00:44:51 bwelling Exp $ */ + +#ifndef ISCCC_UTIL_H +#define ISCCC_UTIL_H 1 + +#include + +/* + * Macros for dealing with unaligned numbers. + * + * Note: no side effects are allowed when invoking these macros! + */ + +#define GET8(v, w) \ + do { \ + v = *w; \ + w++; \ + } while (0) + +#define GET16(v, w) \ + do { \ + v = (unsigned int)w[0] << 8; \ + v |= (unsigned int)w[1]; \ + w += 2; \ + } while (0) + +#define GET24(v, w) \ + do { \ + v = (unsigned int)w[0] << 16; \ + v |= (unsigned int)w[1] << 8; \ + v |= (unsigned int)w[2]; \ + w += 3; \ + } while (0) + +#define GET32(v, w) \ + do { \ + v = (unsigned int)w[0] << 24; \ + v |= (unsigned int)w[1] << 16; \ + v |= (unsigned int)w[2] << 8; \ + v |= (unsigned int)w[3]; \ + w += 4; \ + } while (0) + +#define GET64(v, w) \ + do { \ + v = (isc_uint64_t)w[0] << 56; \ + v |= (isc_uint64_t)w[1] << 48; \ + v |= (isc_uint64_t)w[2] << 40; \ + v |= (isc_uint64_t)w[3] << 32; \ + v |= (isc_uint64_t)w[4] << 24; \ + v |= (isc_uint64_t)w[5] << 16; \ + v |= (isc_uint64_t)w[6] << 8; \ + v |= (isc_uint64_t)w[7]; \ + w += 8; \ + } while (0) + +#define GETC16(v, w, d) \ + do { \ + GET8(v, w); \ + if (v == 0) \ + d = ISCCC_TRUE; \ + else { \ + d = ISCCC_FALSE; \ + if (v == 255) \ + GET16(v, w); \ + } \ + } while (0) + +#define GETC32(v, w) \ + do { \ + GET24(v, w); \ + if (v == 0xffffffu) \ + GET32(v, w); \ + } while (0) + +#define GET_OFFSET(v, w) GET32(v, w) + +#define GET_MEM(v, c, w) \ + do { \ + memcpy(v, w, c); \ + w += c; \ + } while (0) + +#define GET_TYPE(v, w) \ + do { \ + GET8(v, w); \ + if (v > 127) { \ + if (v < 255) \ + v = ((v & 0x7f) << 16) | ISCCC_RDATATYPE_SIG; \ + else \ + GET32(v, w); \ + } \ + } while (0) + +#define PUT8(v, w) \ + do { \ + *w = (v & 0x000000ffU); \ + w++; \ + } while (0) + +#define PUT16(v, w) \ + do { \ + w[0] = (v & 0x0000ff00U) >> 8; \ + w[1] = (v & 0x000000ffU); \ + w += 2; \ + } while (0) + +#define PUT24(v, w) \ + do { \ + w[0] = (v & 0x00ff0000U) >> 16; \ + w[1] = (v & 0x0000ff00U) >> 8; \ + w[2] = (v & 0x000000ffU); \ + w += 3; \ + } while (0) + +#define PUT32(v, w) \ + do { \ + w[0] = (v & 0xff000000U) >> 24; \ + w[1] = (v & 0x00ff0000U) >> 16; \ + w[2] = (v & 0x0000ff00U) >> 8; \ + w[3] = (v & 0x000000ffU); \ + w += 4; \ + } while (0) + +#define PUT64(v, w) \ + do { \ + w[0] = (v & 0xff00000000000000ULL) >> 56; \ + w[1] = (v & 0x00ff000000000000ULL) >> 48; \ + w[2] = (v & 0x0000ff0000000000ULL) >> 40; \ + w[3] = (v & 0x000000ff00000000ULL) >> 32; \ + w[4] = (v & 0x00000000ff000000ULL) >> 24; \ + w[5] = (v & 0x0000000000ff0000ULL) >> 16; \ + w[6] = (v & 0x000000000000ff00ULL) >> 8; \ + w[7] = (v & 0x00000000000000ffULL); \ + w += 8; \ + } while (0) + +#define PUTC16(v, w) \ + do { \ + if (v > 0 && v < 255) \ + PUT8(v, w); \ + else { \ + PUT8(255, w); \ + PUT16(v, w); \ + } \ + } while (0) + +#define PUTC32(v, w) \ + do { \ + if (v < 0xffffffU) \ + PUT24(v, w); \ + else { \ + PUT24(0xffffffU, w); \ + PUT32(v, w); \ + } \ + } while (0) + +#define PUT_OFFSET(v, w) PUT32(v, w) + +#include + +#define PUT_MEM(s, c, w) \ + do { \ + memcpy(w, s, c); \ + w += c; \ + } while (0) + +/* + * Byte swapping + */ +#include +#include +#include + +#define N2HO(v) ntohl(v) +#define H2NO(v) htonl(v) + +/* + * Regions. + */ +#define REGION_SIZE(r) ((unsigned int)((r).rend - (r).rstart)) +#define REGION_EMPTY(r) ((r).rstart == (r).rend) +#define REGION_FROMSTRING(r, s) do { \ + (r).rstart = (unsigned char *)s; \ + (r).rend = (r).rstart + strlen(s); \ +} while (0) + +/* + * Use this to remove the const qualifier of a variable to assign it to + * a non-const variable or pass it as a non-const function argument ... + * but only when you are sure it won't then be changed! + * This is necessary to sometimes shut up some compilers + * (as with gcc -Wcast-qual) when there is just no other good way to avoid the + * situation. + */ +#define DE_CONST(konst, var) \ + do { \ + union { const void *k; void *v; } _u; \ + _u.k = konst; \ + var = _u.v; \ + } while (0) + +#endif /* ISCCC_UTIL_H */ diff --git a/lib/isccc/lib.c b/lib/isccc/lib.c new file mode 100644 index 0000000000..58cb77edb4 --- /dev/null +++ b/lib/isccc/lib.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 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.1 2001/03/27 00:44:48 bwelling Exp $ */ + +#include + +#include + +#include +#include +#include + +#include + +/*** + *** Globals + ***/ + +isc_msgcat_t * isccc_msgcat = NULL; + + +/*** + *** Private + ***/ + +static isc_once_t msgcat_once = ISC_ONCE_INIT; + + +/*** + *** Functions + ***/ + +static void +open_msgcat(void) { + isc_msgcat_open("libisccc.cat", &isccc_msgcat); +} + +void +isccc_lib_initmsgcat(void) { + + /* + * Initialize the DNS library's message catalog, isccc_msgcat, if it + * has not already been initialized. + */ + + RUNTIME_CHECK(isc_once_do(&msgcat_once, open_msgcat) == ISC_R_SUCCESS); +} diff --git a/lib/isccc/result.c b/lib/isccc/result.c new file mode 100644 index 0000000000..be3a68ed53 --- /dev/null +++ b/lib/isccc/result.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 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.1 2001/03/27 00:44:48 bwelling Exp $ */ + +#include + +#include +#include + +#include +#include + +static const char *text[ISCCC_R_NRESULTS] = { + "unknown version", /* 1 */ + "syntax error", /* 2 */ + "bad auth", /* 3 */ +}; + +#define ISCCC_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_ISCCC, ISCCC_R_NRESULTS, + text, isccc_msgcat, + ISCCC_RESULT_RESULTSET); + if (result != ISC_R_SUCCESS) + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_result_register() failed: %u", result); +} + +static void +initialize(void) { + isccc_lib_initmsgcat(); + RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); +} + +const char * +isccc_result_totext(isc_result_t result) { + initialize(); + + return (isc_result_totext(result)); +} + +void +isccc_result_register(void) { + initialize(); +} + +isc_result_t +isccc_result_fromerrno(int ecode) { + /* + * Convert a UNIX errno into a isc_result_t. + */ + if (ecode == 0) + return (ISC_R_SUCCESS); + else if (ecode >= ISCCC_RESULT_OSBASE || ecode < 0) + return (ISC_R_FAILURE); + return (ISCCC_RESULT_OSBASE | ecode); +} diff --git a/lib/isccc/sexpr.c b/lib/isccc/sexpr.c new file mode 100644 index 0000000000..ba5359075b --- /dev/null +++ b/lib/isccc/sexpr.c @@ -0,0 +1,309 @@ +/* + * Copyright (C) 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: sexpr.c,v 1.1 2001/03/27 00:44:48 bwelling Exp $ */ + +#include + +#include +#include +#include + +#include +#include +#include + +static isccc_sexpr_t sexpr_t = { ISCCC_SEXPRTYPE_T, { NULL } }; + +#define CAR(s) (s)->value.as_dottedpair.car +#define CDR(s) (s)->value.as_dottedpair.cdr + +isccc_sexpr_t * +isccc_sexpr_cons(isccc_sexpr_t *car, isccc_sexpr_t *cdr) +{ + isccc_sexpr_t *sexpr; + + sexpr = malloc(sizeof *sexpr); + if (sexpr == NULL) + return (NULL); + sexpr->type = ISCCC_SEXPRTYPE_DOTTEDPAIR; + CAR(sexpr) = car; + CDR(sexpr) = cdr; + + return (sexpr); +} + +isccc_sexpr_t * +isccc_sexpr_tconst(void) +{ + return (&sexpr_t); +} + +isccc_sexpr_t * +isccc_sexpr_fromstring(const char *str) +{ + isccc_sexpr_t *sexpr; + + sexpr = malloc(sizeof *sexpr); + if (sexpr == NULL) + return (NULL); + sexpr->type = ISCCC_SEXPRTYPE_STRING; + sexpr->value.as_string = strdup(str); + if (sexpr->value.as_string == NULL) { + free(sexpr); + return (NULL); + } + + return (sexpr); +} + +isccc_sexpr_t * +isccc_sexpr_frombinary(const isccc_region_t *region) +{ + isccc_sexpr_t *sexpr; + unsigned int region_size; + + sexpr = malloc(sizeof *sexpr); + if (sexpr == NULL) + return (NULL); + sexpr->type = ISCCC_SEXPRTYPE_BINARY; + region_size = REGION_SIZE(*region); + /* + * We add an extra byte when we malloc so we can NUL terminate + * the binary data. This allows the caller to use it as a C + * string. It's up to the caller to ensure this is safe. We don't + * add 1 to the length of the binary region, because the NUL is + * not part of the binary data. + */ + sexpr->value.as_region.rstart = malloc(region_size + 1); + if (sexpr->value.as_region.rstart == NULL) { + free(sexpr); + return (NULL); + } + sexpr->value.as_region.rend = sexpr->value.as_region.rstart + + region_size; + memcpy(sexpr->value.as_region.rstart, region->rstart, region_size); + /* + * NUL terminate. + */ + sexpr->value.as_region.rstart[region_size] = '\0'; + + return (sexpr); +} + +void +isccc_sexpr_free(isccc_sexpr_t **sexprp) +{ + isccc_sexpr_t *sexpr; + isccc_sexpr_t *item; + + sexpr = *sexprp; + if (sexpr == NULL) + return; + switch (sexpr->type) { + case ISCCC_SEXPRTYPE_STRING: + free(sexpr->value.as_string); + break; + case ISCCC_SEXPRTYPE_DOTTEDPAIR: + item = CAR(sexpr); + if (item != NULL) + isccc_sexpr_free(&item); + item = CDR(sexpr); + if (item != NULL) + isccc_sexpr_free(&item); + break; + case ISCCC_SEXPRTYPE_BINARY: + free(sexpr->value.as_region.rstart); + break; + } + free(sexpr); + + *sexprp = NULL; +} + +static isc_boolean_t +printable(isccc_region_t *r) +{ + unsigned char *curr; + + curr = r->rstart; + while (curr != r->rend) { + if (!isprint(*curr)) + return (ISC_FALSE); + curr++; + } + + return (ISC_TRUE); +} + +void +isccc_sexpr_print(isccc_sexpr_t *sexpr, FILE *stream) +{ + isccc_sexpr_t *cdr; + unsigned int size, i; + unsigned char *curr; + + if (sexpr == NULL) { + fprintf(stream, "nil"); + return; + } + + switch (sexpr->type) { + case ISCCC_SEXPRTYPE_T: + fprintf(stream, "t"); + break; + case ISCCC_SEXPRTYPE_STRING: + fprintf(stream, "\"%s\"", sexpr->value.as_string); + break; + case ISCCC_SEXPRTYPE_DOTTEDPAIR: + fprintf(stream, "("); + do { + isccc_sexpr_print(CAR(sexpr), stream); + cdr = CDR(sexpr); + if (cdr != NULL) { + fprintf(stream, " "); + if (cdr->type != ISCCC_SEXPRTYPE_DOTTEDPAIR) { + fprintf(stream, ". "); + isccc_sexpr_print(cdr, stream); + cdr = NULL; + } + } + sexpr = cdr; + } while (sexpr != NULL); + fprintf(stream, ")"); + break; + case ISCCC_SEXPRTYPE_BINARY: + size = REGION_SIZE(sexpr->value.as_region); + curr = sexpr->value.as_region.rstart; + if (printable(&sexpr->value.as_region)) { + fprintf(stream, "'%.*s'", (int)size, curr); + } else { + fprintf(stream, "0x"); + for (i = 0; i < size; i++) + fprintf(stream, "%02x", *curr++); + } + break; + default: + INSIST(0); + } +} + +isccc_sexpr_t * +isccc_sexpr_car(isccc_sexpr_t *list) +{ + REQUIRE(list->type == ISCCC_SEXPRTYPE_DOTTEDPAIR); + + return (CAR(list)); +} + +isccc_sexpr_t * +isccc_sexpr_cdr(isccc_sexpr_t *list) +{ + REQUIRE(list->type == ISCCC_SEXPRTYPE_DOTTEDPAIR); + + return (CDR(list)); +} + +void +isccc_sexpr_setcar(isccc_sexpr_t *pair, isccc_sexpr_t *car) +{ + REQUIRE(pair->type == ISCCC_SEXPRTYPE_DOTTEDPAIR); + + CAR(pair) = car; +} + +void +isccc_sexpr_setcdr(isccc_sexpr_t *pair, isccc_sexpr_t *cdr) +{ + REQUIRE(pair->type == ISCCC_SEXPRTYPE_DOTTEDPAIR); + + CDR(pair) = cdr; +} + +isccc_sexpr_t * +isccc_sexpr_addtolist(isccc_sexpr_t **l1p, isccc_sexpr_t *l2) +{ + isccc_sexpr_t *last, *elt, *l1; + + REQUIRE(l1p != NULL); + l1 = *l1p; + REQUIRE(l1 == NULL || l1->type == ISCCC_SEXPRTYPE_DOTTEDPAIR); + + elt = isccc_sexpr_cons(l2, NULL); + if (elt == NULL) + return (NULL); + if (l1 == NULL) { + *l1p = elt; + return (elt); + } + for (last = l1; CDR(last) != NULL; last = CDR(last)) + /* Nothing */; + CDR(last) = elt; + + return (elt); +} + +isc_boolean_t +isccc_sexpr_listp(isccc_sexpr_t *sexpr) +{ + if (sexpr == NULL || sexpr->type == ISCCC_SEXPRTYPE_DOTTEDPAIR) + return (ISC_TRUE); + return (ISC_FALSE); +} + +isc_boolean_t +isccc_sexpr_emptyp(isccc_sexpr_t *sexpr) +{ + if (sexpr == NULL) + return (ISC_TRUE); + return (ISC_FALSE); +} + +isc_boolean_t +isccc_sexpr_stringp(isccc_sexpr_t *sexpr) +{ + if (sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_STRING) + return (ISC_TRUE); + return (ISC_FALSE); +} + +isc_boolean_t +isccc_sexpr_binaryp(isccc_sexpr_t *sexpr) +{ + if (sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_BINARY) + return (ISC_TRUE); + return (ISC_FALSE); +} + +char * +isccc_sexpr_tostring(isccc_sexpr_t *sexpr) +{ + REQUIRE(sexpr != NULL && + (sexpr->type == ISCCC_SEXPRTYPE_STRING || + sexpr->type == ISCCC_SEXPRTYPE_BINARY)); + + if (sexpr->type == ISCCC_SEXPRTYPE_BINARY) + return ((char *)sexpr->value.as_region.rstart); + return (sexpr->value.as_string); +} + +isccc_region_t * +isccc_sexpr_tobinary(isccc_sexpr_t *sexpr) +{ + REQUIRE(sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_BINARY); + return (&sexpr->value.as_region); +} diff --git a/lib/isccc/symtab.c b/lib/isccc/symtab.c new file mode 100644 index 0000000000..c0559579a1 --- /dev/null +++ b/lib/isccc/symtab.c @@ -0,0 +1,276 @@ +/* + * Copyright (C) 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: symtab.c,v 1.1 2001/03/27 00:44:48 bwelling Exp $ */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +typedef struct elt { + char * key; + unsigned int type; + isccc_symvalue_t value; + ISC_LINK(struct elt) link; +} elt_t; + +typedef ISC_LIST(elt_t) eltlist_t; + +#define SYMTAB_MAGIC 0x53796D54U /* SymT. */ +#define VALID_SYMTAB(st) ((st) != NULL && \ + (st)->magic == SYMTAB_MAGIC) + +struct isccc_symtab { + unsigned int magic; + unsigned int size; + eltlist_t * table; + isccc_symtabundefaction_t undefine_action; + void * undefine_arg; + isc_boolean_t case_sensitive; +}; + +isc_result_t +isccc_symtab_create(unsigned int size, + isccc_symtabundefaction_t undefine_action, + void *undefine_arg, + isc_boolean_t case_sensitive, + isccc_symtab_t **symtabp) +{ + isccc_symtab_t *symtab; + unsigned int i; + + REQUIRE(symtabp != NULL && *symtabp == NULL); + REQUIRE(size > 0); /* Should be prime. */ + + symtab = malloc(sizeof *symtab); + if (symtab == NULL) + return (ISC_R_NOMEMORY); + symtab->table = malloc(size * sizeof (eltlist_t)); + if (symtab->table == NULL) { + free(symtab); + return (ISC_R_NOMEMORY); + } + for (i = 0; i < size; i++) + ISC_LIST_INIT(symtab->table[i]); + symtab->size = size; + symtab->undefine_action = undefine_action; + symtab->undefine_arg = undefine_arg; + symtab->case_sensitive = case_sensitive; + symtab->magic = SYMTAB_MAGIC; + + *symtabp = symtab; + + return (ISC_R_SUCCESS); +} + +static inline void +free_elt(isccc_symtab_t *symtab, unsigned int bucket, elt_t *elt) { + ISC_LIST_UNLINK(symtab->table[bucket], elt, link); + if (symtab->undefine_action != NULL) + (symtab->undefine_action)(elt->key, elt->type, elt->value, + symtab->undefine_arg); + free(elt); +} + +void +isccc_symtab_destroy(isccc_symtab_t **symtabp) { + isccc_symtab_t *symtab; + unsigned int i; + elt_t *elt, *nelt; + + REQUIRE(symtabp != NULL); + symtab = *symtabp; + REQUIRE(VALID_SYMTAB(symtab)); + + for (i = 0; i < symtab->size; i++) { + for (elt = ISC_LIST_HEAD(symtab->table[i]); + elt != NULL; + elt = nelt) { + nelt = ISC_LIST_NEXT(elt, link); + free_elt(symtab, i, elt); + } + } + free(symtab->table); + symtab->magic = 0; + free(symtab); + + *symtabp = NULL; +} + +static inline unsigned int +hash(const char *key, isc_boolean_t case_sensitive) { + const char *s; + unsigned int h = 0; + unsigned int g; + int c; + + /* + * P. J. Weinberger's hash function, adapted from p. 436 of + * _Compilers: Principles, Techniques, and Tools_, Aho, Sethi + * and Ullman, Addison-Wesley, 1986, ISBN 0-201-10088-6. + */ + + if (case_sensitive) { + for (s = key; *s != '\0'; s++) { + h = ( h << 4 ) + *s; + if ((g = ( h & 0xf0000000 )) != 0) { + h = h ^ (g >> 24); + h = h ^ g; + } + } + } else { + for (s = key; *s != '\0'; s++) { + c = *s; + c = tolower((unsigned char)c); + h = ( h << 4 ) + c; + if ((g = ( h & 0xf0000000 )) != 0) { + h = h ^ (g >> 24); + h = h ^ g; + } + } + } + + return (h); +} + +#define FIND(s, k, t, b, e) \ + b = hash((k), (s)->case_sensitive) % (s)->size; \ + if ((s)->case_sensitive) { \ + for (e = ISC_LIST_HEAD((s)->table[b]); \ + e != NULL; \ + e = ISC_LIST_NEXT(e, link)) { \ + if (((t) == 0 || e->type == (t)) && \ + strcmp(e->key, (k)) == 0) \ + break; \ + } \ + } else { \ + for (e = ISC_LIST_HEAD((s)->table[b]); \ + e != NULL; \ + e = ISC_LIST_NEXT(e, link)) { \ + if (((t) == 0 || e->type == (t)) && \ + strcasecmp(e->key, (k)) == 0) \ + break; \ + } \ + } + +isc_result_t +isccc_symtab_lookup(isccc_symtab_t *symtab, const char *key, unsigned int type, + isccc_symvalue_t *value) +{ + unsigned int bucket; + elt_t *elt; + + REQUIRE(VALID_SYMTAB(symtab)); + REQUIRE(key != NULL); + + FIND(symtab, key, type, bucket, elt); + + if (elt == NULL) + return (ISC_R_NOTFOUND); + + if (value != NULL) + *value = elt->value; + + return (ISC_R_SUCCESS); +} + +isc_result_t +isccc_symtab_define(isccc_symtab_t *symtab, char *key, unsigned int type, + isccc_symvalue_t value, isccc_symexists_t exists_policy) +{ + unsigned int bucket; + elt_t *elt; + + REQUIRE(VALID_SYMTAB(symtab)); + REQUIRE(key != NULL); + REQUIRE(type != 0); + + FIND(symtab, key, type, bucket, elt); + + if (exists_policy != isccc_symexists_add && elt != NULL) { + if (exists_policy == isccc_symexists_reject) + return (ISC_R_EXISTS); + INSIST(exists_policy == isccc_symexists_replace); + ISC_LIST_UNLINK(symtab->table[bucket], elt, link); + if (symtab->undefine_action != NULL) + (symtab->undefine_action)(elt->key, elt->type, + elt->value, + symtab->undefine_arg); + } else { + elt = malloc(sizeof *elt); + if (elt == NULL) + return (ISC_R_NOMEMORY); + ISC_LINK_INIT(elt, link); + } + + elt->key = key; + elt->type = type; + elt->value = value; + + /* + * We prepend so that the most recent definition will be found. + */ + ISC_LIST_PREPEND(symtab->table[bucket], elt, link); + + return (ISC_R_SUCCESS); +} + +isc_result_t +isccc_symtab_undefine(isccc_symtab_t *symtab, const char *key, unsigned int type) { + unsigned int bucket; + elt_t *elt; + + REQUIRE(VALID_SYMTAB(symtab)); + REQUIRE(key != NULL); + + FIND(symtab, key, type, bucket, elt); + + if (elt == NULL) + return (ISC_R_NOTFOUND); + + free_elt(symtab, bucket, elt); + + return (ISC_R_SUCCESS); +} + +void +isccc_symtab_foreach(isccc_symtab_t *symtab, isccc_symtabforeachaction_t action, + void *arg) +{ + unsigned int i; + elt_t *elt, *nelt; + + REQUIRE(VALID_SYMTAB(symtab)); + REQUIRE(action != NULL); + + for (i = 0; i < symtab->size; i++) { + for (elt = ISC_LIST_HEAD(symtab->table[i]); + elt != NULL; + elt = nelt) { + nelt = ISC_LIST_NEXT(elt, link); + if ((action)(elt->key, elt->type, elt->value, arg)) + free_elt(symtab, i, elt); + } + } +} diff --git a/lib/isccfg/Makefile.in b/lib/isccfg/Makefile.in index 438009665d..3178589352 100644 --- a/lib/isccfg/Makefile.in +++ b/lib/isccfg/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2000 Internet Software Consortium. +# Copyright (C) 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 @@ -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.3 2001/03/01 23:46:47 bwelling Exp $ +# $Id: Makefile.in,v 1.4 2001/03/27 00:44:52 bwelling Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/lib/isccfg/include/Makefile.in b/lib/isccfg/include/Makefile.in index 23505c8458..bd5b13daf7 100644 --- a/lib/isccfg/include/Makefile.in +++ b/lib/isccfg/include/Makefile.in @@ -1,3 +1,20 @@ +/* + * Copyright (C) 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. + */ + # Copyright (C) 1998-2001 Internet Software Consortium. # # Permission to use, copy, modify, and distribute this software for any @@ -13,7 +30,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.1 2001/02/15 04:21:16 gson Exp $ +# $Id: Makefile.in,v 1.2 2001/03/27 00:44:53 bwelling Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/lib/isccfg/include/isccfg/Makefile.in b/lib/isccfg/include/isccfg/Makefile.in index 44591d953a..dda97a6407 100644 --- a/lib/isccfg/include/isccfg/Makefile.in +++ b/lib/isccfg/include/isccfg/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2001 Internet Software Consortium. +# Copyright (C) 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 @@ -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.2 2001/03/01 23:46:48 bwelling Exp $ +# $Id: Makefile.in,v 1.3 2001/03/27 00:44:55 bwelling Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/lib/isccfg/include/isccfg/cfg.h b/lib/isccfg/include/isccfg/cfg.h index 7da59ba5a3..28a848a619 100644 --- a/lib/isccfg/include/isccfg/cfg.h +++ b/lib/isccfg/include/isccfg/cfg.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001 Internet Software Consortium. + * 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 @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: cfg.h,v 1.20 2001/03/03 02:18:13 gson Exp $ */ +/* $Id: cfg.h,v 1.21 2001/03/27 00:44:56 bwelling Exp $ */ #ifndef ISCCFG_CFG_H #define ISCCFG_CFG_H 1 diff --git a/make/includes.in b/make/includes.in index 0bb5fc7c64..078f9e1de5 100644 --- a/make/includes.in +++ b/make/includes.in @@ -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.12 2001/02/15 04:14:14 gson Exp $ +# $Id: includes.in,v 1.13 2001/03/27 00:44:57 bwelling Exp $ # Search for machine-generated header files in the build tree, # and for normal headers in the source tree (${top_srcdir}). @@ -27,6 +27,9 @@ ISC_INCLUDES = @BIND9_ISC_BUILDINCLUDE@ \ -I${top_srcdir}/lib/isc/unix/include \ -I${top_srcdir}/lib/isc/@ISC_THREAD_DIR@/include +ISCCC_INCLUDES = @BIND9_ISCCC_BUILDINCLUDE@ \ + -I${top_srcdir}/lib/isccc/include + ISCCFG_INCLUDES = @BIND9_ISCCFG_BUILDINCLUDE@ \ -I${top_srcdir}/lib/isccfg/include diff --git a/util/copyrights b/util/copyrights index adf595613f..f4dbecbbe6 100644 --- a/util/copyrights +++ b/util/copyrights @@ -1295,6 +1295,32 @@ ./lib/isc/win32/stdtime.c C 1999,2000,2001 ./lib/isc/win32/thread.c C 1998,1999,2000,2001 ./lib/isc/win32/time.c C 1998,1999,2000,2001 +./lib/isccc/.cvsignore X 2001 +./lib/isccc/Makefile.in MAKE 2001 +./lib/isccc/api X 2001 +./lib/isccc/alist.c C 2001 +./lib/isccc/base64.c C 2001 +./lib/isccc/cc.c C 2001 +./lib/isccc/ccmsg.c C 2001 +./lib/isccc/include/isccc/.cvsignore X 2001 +./lib/isccc/include/isccc/alist.h C 2001 +./lib/isccc/include/isccc/base64.h C 2001 +./lib/isccc/include/isccc/cc.h C 2001 +./lib/isccc/include/isccc/ccmsg.h C 2001 +./lib/isccc/include/isccc/events.h C 2001 +./lib/isccc/include/isccc/lib.h C 2001 +./lib/isccc/include/isccc/result.h C 2001 +./lib/isccc/include/isccc/sexpr.h C 2001 +./lib/isccc/include/isccc/symtab.h C 2001 +./lib/isccc/include/isccc/symtype.h C 2001 +./lib/isccc/include/isccc/types.h C 2001 +./lib/isccc/include/isccc/util.h C 2001 +./lib/isccc/include/.cvsignore MAKE 2001 +./lib/isccc/include/Makefile.in MAKE 2001 +./lib/isccc/lib.c C 2001 +./lib/isccc/result.c C 2001 +./lib/isccc/sexpr.c C 2001 +./lib/isccc/symtab.c C 2001 ./lib/isccfg/.cvsignore X 2001 ./lib/isccfg/Makefile.in MAKE 2001 ./lib/isccfg/api X 2001