diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 07:24:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 07:24:22 +0000 |
commit | 45d6379135504814ab723b57f0eb8be23393a51d (patch) | |
tree | d4f2ec4acca824a8446387a758b0ce4238a4dffa /lib/isccc | |
parent | Initial commit. (diff) | |
download | bind9-upstream/1%9.16.44.tar.xz bind9-upstream/1%9.16.44.zip |
Adding upstream version 1:9.16.44.upstream/1%9.16.44upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
34 files changed, 4216 insertions, 0 deletions
diff --git a/lib/isccc/Kyuafile b/lib/isccc/Kyuafile new file mode 100644 index 0000000..c796010 --- /dev/null +++ b/lib/isccc/Kyuafile @@ -0,0 +1,15 @@ +-- Copyright (C) Internet Systems Consortium, Inc. ("ISC") +-- +-- SPDX-License-Identifier: MPL-2.0 +-- +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, you can obtain one at https://mozilla.org/MPL/2.0/. +-- +-- See the COPYRIGHT file distributed with this work for additional +-- information regarding copyright ownership. + +syntax(2) +test_suite('bind9') + +include('tests/Kyuafile') diff --git a/lib/isccc/Makefile.in b/lib/isccc/Makefile.in new file mode 100644 index 0000000..b542441 --- /dev/null +++ b/lib/isccc/Makefile.in @@ -0,0 +1,81 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +VERSION=@BIND9_VERSION@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I. ${DNS_INCLUDES} ${ISC_INCLUDES} \ + ${ISCCC_INCLUDES} \ + ${OPENSSL_CFLAGS} + +CDEFINES = +CWARNINGS = + +ISCLIBS = ../../lib/isc/libisc.@A@ @NO_LIBTOOL_ISCLIBS@ +ISCCCLIBS = ../../lib/isccc/libisccc.@A@ + +ISCDEPLIBS = ../../lib/isc/libisc.@A@ +ISCCCDEPLIBS = libisccc.@A@ + +LIBS = @LIBS@ + +SUBDIRS = include + +# Alphabetically +OBJS = alist.@O@ base64.@O@ cc.@O@ ccmsg.@O@ \ + result.@O@ sexpr.@O@ symtab.@O@ version.@O@ + +# Alphabetically +SRCS = alist.c base64.c cc.c ccmsg.c \ + result.c sexpr.c symtab.c version.c + + +TARGETS = timestamp +TESTDIRS = @UNITTESTS@ + +@BIND9_MAKE_RULES@ + +version.@O@: version.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -c ${srcdir}/version.c + +libisccc.@SA@: ${OBJS} + ${AR} ${ARFLAGS} $@ ${OBJS} + ${RANLIB} $@ + +libisccc.la: ${OBJS} + ${LIBTOOL_MODE_LINK} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisccc.la -rpath ${libdir} \ + -release "${VERSION}" \ + ${OBJS} ${ISCLIBS} ${LIBS} + +timestamp: libisccc.@A@ + touch timestamp + +testdirs: libisccc.@A@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} + +install:: timestamp installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_LIBRARY} libisccc.@A@ ${DESTDIR}${libdir} + +uninstall:: + ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${libdir}/libisccc.@A@ + +clean distclean:: + rm -f libisccc.@A@ timestamp diff --git a/lib/isccc/alist.c b/lib/isccc/alist.c new file mode 100644 index 0000000..a39d4f9 --- /dev/null +++ b/lib/isccc/alist.c @@ -0,0 +1,320 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/*! \file */ + +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/assertions.h> +#include <isc/print.h> + +#include <isccc/alist.h> +#include <isccc/result.h> +#include <isccc/sexpr.h> +#include <isccc/util.h> + +#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); +} + +bool +isccc_alist_alistp(isccc_sexpr_t *alist) { + isccc_sexpr_t *car; + + if (alist == NULL || alist->type != ISCCC_SEXPRTYPE_DOTTEDPAIR) { + return (false); + } + car = CAR(alist); + if (car == NULL || car->type != ISCCC_SEXPRTYPE_STRING) { + return (false); + } + if (strcmp(car->value.as_string, ALIST_TAG) != 0) { + return (false); + } + return (true); +} + +bool +isccc_alist_emptyp(isccc_sexpr_t *alist) { + REQUIRE(isccc_alist_alistp(alist)); + + if (CDR(alist) == NULL) { + return (true); + } + return (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/base64.c b/lib/isccc/base64.c new file mode 100644 index 0000000..344d96a --- /dev/null +++ b/lib/isccc/base64.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/*! \file */ + +#include <isc/base64.h> +#include <isc/buffer.h> +#include <isc/region.h> +#include <isc/result.h> + +#include <isccc/base64.h> +#include <isccc/result.h> +#include <isccc/util.h> + +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 = (unsigned int)(source->rend - source->rstart); + isc_buffer_init(&tb, target->rstart, + (unsigned int)(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, + (unsigned int)(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 0000000..5a716bd --- /dev/null +++ b/lib/isccc/cc.c @@ -0,0 +1,1059 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/*! \file */ + +#include <errno.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/assertions.h> +#include <isc/hmac.h> +#include <isc/print.h> +#include <isc/safe.h> + +#include <pk11/site.h> + +#include <isccc/alist.h> +#include <isccc/base64.h> +#include <isccc/cc.h> +#include <isccc/result.h> +#include <isccc/sexpr.h> +#include <isccc/symtab.h> +#include <isccc/symtype.h> +#include <isccc/util.h> + +#define MAX_TAGS 256 +#define DUP_LIFETIME 900 +#ifndef ISCCC_MAXDEPTH +#define ISCCC_MAXDEPTH \ + 10 /* Big enough for rndc which just sends a string each way. */ +#endif + +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 /*%< 21 = 6 + 1 + 4 + 5 + 1 + 4 */ +#define HMD5_LENGTH 22 + +static unsigned char auth_hsha[] = { + 0x05, 0x5f, 0x61, 0x75, 0x74, 0x68, /*%< len + _auth */ + ISCCC_CCMSGTYPE_TABLE, /*%< message type */ + 0x00, 0x00, 0x00, 0x63, /*%< length == 99 */ + 0x04, 0x68, 0x73, 0x68, 0x61, /*%< len + hsha */ + ISCCC_CCMSGTYPE_BINARYDATA, /*%< message type */ + 0x00, 0x00, 0x00, 0x59, /*%< length == 89 */ + 0x00, /*%< algorithm */ + /* + * The base64 encoding of one of our HMAC-SHA* signatures is + * 88 bytes. + */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +#define HSHA_OFFSET 22 /*%< 21 = 6 + 1 + 4 + 5 + 1 + 4 + 1 */ +#define HSHA_LENGTH 88 + +static isc_result_t +table_towire(isccc_sexpr_t *alist, isc_buffer_t **buffer); + +static isc_result_t +list_towire(isccc_sexpr_t *alist, isc_buffer_t **buffer); + +static isc_result_t +value_towire(isccc_sexpr_t *elt, isc_buffer_t **buffer) { + unsigned int len; + isccc_region_t *vr; + isc_result_t result; + + if (isccc_sexpr_binaryp(elt)) { + vr = isccc_sexpr_tobinary(elt); + len = REGION_SIZE(*vr); + result = isc_buffer_reserve(buffer, 1 + 4); + if (result != ISC_R_SUCCESS) { + return (ISC_R_NOSPACE); + } + isc_buffer_putuint8(*buffer, ISCCC_CCMSGTYPE_BINARYDATA); + isc_buffer_putuint32(*buffer, len); + + result = isc_buffer_reserve(buffer, len); + if (result != ISC_R_SUCCESS) { + return (ISC_R_NOSPACE); + } + isc_buffer_putmem(*buffer, vr->rstart, len); + } else if (isccc_alist_alistp(elt)) { + unsigned int used; + isc_buffer_t b; + + result = isc_buffer_reserve(buffer, 1 + 4); + if (result != ISC_R_SUCCESS) { + return (ISC_R_NOSPACE); + } + isc_buffer_putuint8(*buffer, ISCCC_CCMSGTYPE_TABLE); + /* + * Emit a placeholder length. + */ + used = (*buffer)->used; + isc_buffer_putuint32(*buffer, 0); + + /* + * Emit the table. + */ + result = table_towire(elt, buffer); + if (result != ISC_R_SUCCESS) { + return (result); + } + + len = (*buffer)->used - used; + /* + * 'len' is 4 bytes too big, since it counts + * the placeholder length too. Adjust and + * emit. + */ + INSIST(len >= 4U); + len -= 4; + + isc_buffer_init(&b, (unsigned char *)(*buffer)->base + used, 4); + isc_buffer_putuint32(&b, len); + } else if (isccc_sexpr_listp(elt)) { + unsigned int used; + isc_buffer_t b; + + result = isc_buffer_reserve(buffer, 1 + 4); + if (result != ISC_R_SUCCESS) { + return (ISC_R_NOSPACE); + } + isc_buffer_putuint8(*buffer, ISCCC_CCMSGTYPE_LIST); + /* + * Emit a placeholder length. + */ + used = (*buffer)->used; + isc_buffer_putuint32(*buffer, 0); + + /* + * Emit the list. + */ + result = list_towire(elt, buffer); + if (result != ISC_R_SUCCESS) { + return (result); + } + + len = (*buffer)->used - used; + /* + * 'len' is 4 bytes too big, since it counts + * the placeholder length too. Adjust and + * emit. + */ + INSIST(len >= 4U); + len -= 4; + + isc_buffer_init(&b, (unsigned char *)(*buffer)->base + used, 4); + isc_buffer_putuint32(&b, len); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +table_towire(isccc_sexpr_t *alist, isc_buffer_t **buffer) { + isccc_sexpr_t *kv, *elt, *k, *v; + char *ks; + isc_result_t result; + unsigned int 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 = (unsigned int)strlen(ks); + INSIST(len <= 255U); + /* + * Emit the key name. + */ + result = isc_buffer_reserve(buffer, 1 + len); + if (result != ISC_R_SUCCESS) { + return (ISC_R_NOSPACE); + } + isc_buffer_putuint8(*buffer, (uint8_t)len); + isc_buffer_putmem(*buffer, (const unsigned char *)ks, len); + /* + * Emit the value. + */ + result = value_towire(v, buffer); + if (result != ISC_R_SUCCESS) { + return (result); + } + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +list_towire(isccc_sexpr_t *list, isc_buffer_t **buffer) { + isc_result_t result; + + while (list != NULL) { + result = value_towire(ISCCC_SEXPR_CAR(list), buffer); + 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 *hmac, + uint32_t algorithm, isccc_region_t *secret) { + const isc_md_type_t *md_type; + isc_result_t result; + isccc_region_t source, target; + unsigned char digest[ISC_MAX_MD_SIZE]; + unsigned int digestlen; + unsigned char digestb64[HSHA_LENGTH + 4]; + + source.rstart = digest; + + switch (algorithm) { + case ISCCC_ALG_HMACMD5: + md_type = ISC_MD_MD5; + break; + case ISCCC_ALG_HMACSHA1: + md_type = ISC_MD_SHA1; + break; + case ISCCC_ALG_HMACSHA224: + md_type = ISC_MD_SHA224; + break; + case ISCCC_ALG_HMACSHA256: + md_type = ISC_MD_SHA256; + break; + case ISCCC_ALG_HMACSHA384: + md_type = ISC_MD_SHA384; + break; + case ISCCC_ALG_HMACSHA512: + md_type = ISC_MD_SHA512; + break; + default: + return (ISC_R_NOTIMPLEMENTED); + } + + result = isc_hmac(md_type, secret->rstart, REGION_SIZE(*secret), data, + length, digest, &digestlen); + if (result != ISC_R_SUCCESS) { + return (result); + } + source.rend = digest + digestlen; + + memset(digestb64, 0, sizeof(digestb64)); + target.rstart = digestb64; + target.rend = digestb64 + sizeof(digestb64); + result = isccc_base64_encode(&source, 64, "", &target); + if (result != ISC_R_SUCCESS) { + return (result); + } + if (algorithm == ISCCC_ALG_HMACMD5) { + PUT_MEM(digestb64, HMD5_LENGTH, hmac); + } else { + PUT_MEM(digestb64, HSHA_LENGTH, hmac); + } + return (ISC_R_SUCCESS); +} + +isc_result_t +isccc_cc_towire(isccc_sexpr_t *alist, isc_buffer_t **buffer, uint32_t algorithm, + isccc_region_t *secret) { + unsigned int hmac_base, signed_base; + isc_result_t result; + + result = isc_buffer_reserve(buffer, + 4 + ((algorithm == ISCCC_ALG_HMACMD5) + ? sizeof(auth_hmd5) + : sizeof(auth_hsha))); + if (result != ISC_R_SUCCESS) { + return (ISC_R_NOSPACE); + } + + /* + * Emit protocol version. + */ + isc_buffer_putuint32(*buffer, 1); + + if (secret != NULL) { + /* + * Emit _auth section with zeroed HMAC signature. + * We'll replace the zeros with the real signature once + * we know what it is. + */ + if (algorithm == ISCCC_ALG_HMACMD5) { + hmac_base = (*buffer)->used + HMD5_OFFSET; + isc_buffer_putmem(*buffer, auth_hmd5, + sizeof(auth_hmd5)); + } else { + unsigned char *hmac_alg; + + hmac_base = (*buffer)->used + HSHA_OFFSET; + hmac_alg = (unsigned char *)isc_buffer_used(*buffer) + + HSHA_OFFSET - 1; + isc_buffer_putmem(*buffer, auth_hsha, + sizeof(auth_hsha)); + *hmac_alg = algorithm; + } + } else { + hmac_base = 0; + } + signed_base = (*buffer)->used; + /* + * 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, buffer); + if (result != ISC_R_SUCCESS) { + return (result); + } + if (secret != NULL) { + return (sign((unsigned char *)(*buffer)->base + signed_base, + (*buffer)->used - signed_base, + (unsigned char *)(*buffer)->base + hmac_base, + algorithm, secret)); + } + return (ISC_R_SUCCESS); +} + +static isc_result_t +verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length, + uint32_t algorithm, isccc_region_t *secret) { + const isc_md_type_t *md_type; + isccc_region_t source; + isccc_region_t target; + isc_result_t result; + isccc_sexpr_t *_auth, *hmac; + unsigned char digest[ISC_MAX_MD_SIZE]; + unsigned int digestlen; + unsigned char digestb64[HSHA_LENGTH * 4]; + + /* + * Extract digest. + */ + _auth = isccc_alist_lookup(alist, "_auth"); + if (!isccc_alist_alistp(_auth)) { + return (ISC_R_FAILURE); + } + if (algorithm == ISCCC_ALG_HMACMD5) { + hmac = isccc_alist_lookup(_auth, "hmd5"); + } else { + hmac = isccc_alist_lookup(_auth, "hsha"); + } + if (!isccc_sexpr_binaryp(hmac)) { + return (ISC_R_FAILURE); + } + /* + * Compute digest. + */ + source.rstart = digest; + + switch (algorithm) { + case ISCCC_ALG_HMACMD5: + md_type = ISC_MD_MD5; + break; + case ISCCC_ALG_HMACSHA1: + md_type = ISC_MD_SHA1; + break; + case ISCCC_ALG_HMACSHA224: + md_type = ISC_MD_SHA224; + break; + case ISCCC_ALG_HMACSHA256: + md_type = ISC_MD_SHA256; + break; + case ISCCC_ALG_HMACSHA384: + md_type = ISC_MD_SHA384; + break; + case ISCCC_ALG_HMACSHA512: + md_type = ISC_MD_SHA512; + break; + default: + return (ISC_R_NOTIMPLEMENTED); + } + + result = isc_hmac(md_type, secret->rstart, REGION_SIZE(*secret), data, + length, digest, &digestlen); + if (result != ISC_R_SUCCESS) { + return (result); + } + source.rend = digest + digestlen; + + target.rstart = digestb64; + target.rend = digestb64 + sizeof(digestb64); + memset(digestb64, 0, sizeof(digestb64)); + result = isccc_base64_encode(&source, 64, "", &target); + if (result != ISC_R_SUCCESS) { + return (result); + } + + /* + * Verify. + */ + if (algorithm == ISCCC_ALG_HMACMD5) { + isccc_region_t *region; + unsigned char *value; + + region = isccc_sexpr_tobinary(hmac); + if ((region->rend - region->rstart) != HMD5_LENGTH) { + return (ISCCC_R_BADAUTH); + } + value = region->rstart; + if (!isc_safe_memequal(value, digestb64, HMD5_LENGTH)) { + return (ISCCC_R_BADAUTH); + } + } else { + isccc_region_t *region; + unsigned char *value; + uint32_t valalg; + + region = isccc_sexpr_tobinary(hmac); + + /* + * Note: with non-MD5 algorithms, there's an extra octet + * to identify which algorithm is in use. + */ + if ((region->rend - region->rstart) != HSHA_LENGTH + 1) { + return (ISCCC_R_BADAUTH); + } + value = region->rstart; + GET8(valalg, value); + if ((valalg != algorithm) || + !isc_safe_memequal(value, digestb64, HSHA_LENGTH)) + { + return (ISCCC_R_BADAUTH); + } + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +table_fromwire(isccc_region_t *source, isccc_region_t *secret, + uint32_t algorithm, unsigned int depth, isccc_sexpr_t **alistp); + +static isc_result_t +list_fromwire(isccc_region_t *source, unsigned int depth, + isccc_sexpr_t **listp); + +static isc_result_t +value_fromwire(isccc_region_t *source, unsigned int depth, + isccc_sexpr_t **valuep) { + unsigned int msgtype; + uint32_t len; + isccc_sexpr_t *value; + isccc_region_t active; + isc_result_t result; + + if (depth > ISCCC_MAXDEPTH) { + return (ISCCC_R_MAXDEPTH); + } + + 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, 0, depth + 1, valuep); + } else if (msgtype == ISCCC_CCMSGTYPE_LIST) { + result = list_fromwire(&active, depth + 1, valuep); + } else { + result = ISCCC_R_SYNTAX; + } + + return (result); +} + +static isc_result_t +table_fromwire(isccc_region_t *source, isccc_region_t *secret, + uint32_t algorithm, unsigned int depth, isccc_sexpr_t **alistp) { + char key[256]; + uint32_t len; + isc_result_t result; + isccc_sexpr_t *alist, *value; + bool first_tag; + unsigned char *checksum_rstart; + + REQUIRE(alistp != NULL && *alistp == NULL); + + if (depth > ISCCC_MAXDEPTH) { + return (ISCCC_R_MAXDEPTH); + } + + checksum_rstart = NULL; + first_tag = 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, depth + 1, &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 = false; + } + + if (secret != NULL) { + if (checksum_rstart != NULL) { + result = verify( + alist, checksum_rstart, + (unsigned int)(source->rend - checksum_rstart), + algorithm, secret); + } else { + result = ISCCC_R_BADAUTH; + } + } else { + result = ISC_R_SUCCESS; + } + +bad: + if (result == ISC_R_SUCCESS) { + *alistp = alist; + } else { + isccc_sexpr_free(&alist); + } + + return (result); +} + +static isc_result_t +list_fromwire(isccc_region_t *source, unsigned int depth, + isccc_sexpr_t **listp) { + isccc_sexpr_t *list, *value; + isc_result_t result; + + if (depth > ISCCC_MAXDEPTH) { + return (ISCCC_R_MAXDEPTH); + } + + list = NULL; + while (!REGION_EMPTY(*source)) { + value = NULL; + result = value_fromwire(source, depth + 1, &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 (ISC_R_NOMEMORY); + } + } + + *listp = list; + + return (ISC_R_SUCCESS); +} + +isc_result_t +isccc_cc_fromwire(isccc_region_t *source, isccc_sexpr_t **alistp, + uint32_t algorithm, isccc_region_t *secret) { + unsigned int size; + 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, algorithm, 0, alistp)); +} + +static isc_result_t +createmessage(uint32_t version, const char *from, const char *to, + uint32_t serial, isccc_time_t now, isccc_time_t expires, + isccc_sexpr_t **alistp, bool 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(); + if (_ctrl == NULL) { + goto bad; + } + if (isccc_alist_define(alist, "_ctrl", _ctrl) == NULL) { + isccc_sexpr_free(&_ctrl); + goto bad; + } + + _data = isccc_alist_create(); + if (_data == NULL) { + goto bad; + } + if (isccc_alist_define(alist, "_data", _data) == NULL) { + isccc_sexpr_free(&_data); + 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(uint32_t version, const char *from, const char *to, + uint32_t serial, isccc_time_t now, isccc_time_t expires, + isccc_sexpr_t **alistp) { + return (createmessage(version, from, to, serial, now, expires, alistp, + true)); +} + +isc_result_t +isccc_cc_createack(isccc_sexpr_t *message, bool ok, isccc_sexpr_t **ackp) { + char *_frm, *_to; + 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 (!isccc_alist_alistp(_ctrl) || + 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, false); + if (result != ISC_R_SUCCESS) { + return (result); + } + + _ctrl = isccc_alist_lookup(ack, "_ctrl"); + if (_ctrl == NULL) { + result = ISC_R_FAILURE; + goto bad; + } + 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); +} + +bool +isccc_cc_isack(isccc_sexpr_t *message) { + isccc_sexpr_t *_ctrl; + + _ctrl = isccc_alist_lookup(message, "_ctrl"); + if (!isccc_alist_alistp(_ctrl)) { + return (false); + } + if (isccc_cc_lookupstring(_ctrl, "_ack", NULL) == ISC_R_SUCCESS) { + return (true); + } + return (false); +} + +bool +isccc_cc_isreply(isccc_sexpr_t *message) { + isccc_sexpr_t *_ctrl; + + _ctrl = isccc_alist_lookup(message, "_ctrl"); + if (!isccc_alist_alistp(_ctrl)) { + return (false); + } + if (isccc_cc_lookupstring(_ctrl, "_rpl", NULL) == ISC_R_SUCCESS) { + return (true); + } + return (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 = NULL; + 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 (!isccc_alist_alistp(_ctrl) || !isccc_alist_alistp(_data) || + 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) { + result = ISC_R_FAILURE; + goto bad; + } + + _data = isccc_alist_lookup(alist, "_data"); + if (_data == NULL) { + result = ISC_R_FAILURE; + goto bad; + } + + if (isccc_cc_definestring(_ctrl, "_rpl", "1") == NULL || + isccc_cc_definestring(_data, "type", type) == NULL) + { + result = ISC_R_NOMEMORY; + goto bad; + } + + *alistp = alist; + + return (ISC_R_SUCCESS); + +bad: + isccc_sexpr_free(&alist); + return (result); +} + +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, uint32_t i) { + char b[100]; + size_t len; + isccc_region_t r; + + snprintf(b, sizeof(b), "%u", i); + len = strlen(b); + r.rstart = (unsigned char *)b; + r.rend = (unsigned char *)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; + + REQUIRE(strp == NULL || *strp == NULL); + + 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, 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 = (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 bool +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 (false); + } + if ((*now - value.as_uinteger) < DUP_LIFETIME) { + return (false); + } + return (true); +} + +isc_result_t +isccc_cc_createsymtab(isccc_symtab_t **symtabp) { + return (isccc_symtab_create(11897, symtab_undefine, NULL, false, + symtabp)); +} + +void +isccc_cc_cleansymtab(isccc_symtab_t *symtab, isccc_time_t now) { + isccc_symtab_foreach(symtab, symtab_clean, &now); +} + +static bool +has_whitespace(const char *str) { + char c; + + if (str == NULL) { + return (false); + } + while ((c = *str++) != '\0') { + if (c == ' ' || c == '\t' || c == '\n') { + return (true); + } + } + return (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 = NULL, *_tim = NULL, *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 (!isccc_alist_alistp(_ctrl) || + isccc_cc_lookupstring(_ctrl, "_ser", &_ser) != ISC_R_SUCCESS || + isccc_cc_lookupstring(_ctrl, "_tim", &_tim) != ISC_R_SUCCESS) + { + return (ISC_R_FAILURE); + } + + INSIST(_ser != NULL); + INSIST(_tim != NULL); + + /* + * _frm and _to are optional. + */ + tmp = NULL; + if (isccc_cc_lookupstring(_ctrl, "_frm", &tmp) != ISC_R_SUCCESS) { + _frm = ""; + } else { + _frm = tmp; + } + tmp = NULL; + 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); + } + snprintf(key, len, "%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); +} diff --git a/lib/isccc/ccmsg.c b/lib/isccc/ccmsg.c new file mode 100644 index 0000000..bb60a53 --- /dev/null +++ b/lib/isccc/ccmsg.c @@ -0,0 +1,231 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/*! \file */ + +#include <inttypes.h> + +#include <isc/mem.h> +#include <isc/result.h> +#include <isc/task.h> +#include <isc/util.h> + +#include <isccc/ccmsg.h> +#include <isccc/events.h> + +#define CCMSG_MAGIC ISC_MAGIC('C', 'C', 'm', 's') +#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; /* 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); +} + +#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 /* if 0 */ + +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/.clang-format b/lib/isccc/include/.clang-format new file mode 120000 index 0000000..0e62f72 --- /dev/null +++ b/lib/isccc/include/.clang-format @@ -0,0 +1 @@ +../../../.clang-format.headers
\ No newline at end of file diff --git a/lib/isccc/include/Makefile.in b/lib/isccc/include/Makefile.in new file mode 100644 index 0000000..09c4dd7 --- /dev/null +++ b/lib/isccc/include/Makefile.in @@ -0,0 +1,19 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +SUBDIRS = isccc +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/isccc/include/isccc/Makefile.in b/lib/isccc/include/isccc/Makefile.in new file mode 100644 index 0000000..af4ddf3 --- /dev/null +++ b/lib/isccc/include/isccc/Makefile.in @@ -0,0 +1,41 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +VERSION=@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 base64.h cc.h ccmsg.h events.h result.h \ + sexpr.h symtab.h symtype.h types.h util.h version.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 || exit 1; \ + done + +uninstall:: + for i in ${HEADERS}; do \ + rm -f ${DESTDIR}${includedir}/isccc/$$i || exit 1; \ + done diff --git a/lib/isccc/include/isccc/alist.h b/lib/isccc/include/isccc/alist.h new file mode 100644 index 0000000..558378b --- /dev/null +++ b/lib/isccc/include/isccc/alist.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#ifndef ISCCC_ALIST_H +#define ISCCC_ALIST_H 1 + +/*! \file isccc/alist.h */ + +#include <stdbool.h> +#include <stdio.h> + +#include <isc/lang.h> + +#include <isccc/types.h> + +ISC_LANG_BEGINDECLS + +isccc_sexpr_t * +isccc_alist_create(void); + +bool +isccc_alist_alistp(isccc_sexpr_t *alist); + +bool +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 0000000..2eba95c --- /dev/null +++ b/lib/isccc/include/isccc/base64.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#ifndef ISCCC_BASE64_H +#define ISCCC_BASE64_H 1 + +/*! \file isccc/base64.h */ + +#include <isc/lang.h> + +#include <isccc/types.h> + +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: + *\li 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: + *\li 'source' is a region containing binary data. + *\li 'target' is a text region containing available space. + *\li '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: + *\li 'cstr' is non-null. + *\li 'target' is a valid region. + * + * Returns: + *\li #ISC_R_SUCCESS -- the entire decoded representation of 'cstring' + * fit in 'target'. + *\li #ISC_R_BADBASE64 -- 'cstr' is not a valid base64 encoding. + *\li #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 0000000..9b19904 --- /dev/null +++ b/lib/isccc/include/isccc/cc.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#ifndef ISCCC_CC_H +#define ISCCC_CC_H 1 + +/*! \file isccc/cc.h */ + +#include <inttypes.h> +#include <stdbool.h> + +#include <isc/buffer.h> +#include <isc/lang.h> + +#include <isccc/types.h> + +ISC_LANG_BEGINDECLS + +/*% from lib/dns/include/dst/dst.h */ + +#define ISCCC_ALG_UNKNOWN 0 +#define ISCCC_ALG_HMACMD5 157 +#define ISCCC_ALG_HMACSHA1 161 +#define ISCCC_ALG_HMACSHA224 162 +#define ISCCC_ALG_HMACSHA256 163 +#define ISCCC_ALG_HMACSHA384 164 +#define ISCCC_ALG_HMACSHA512 165 + +/*% Maximum Datagram Package */ +#define ISCCC_CC_MAXDGRAMPACKET 4096 + +/*% Message Type String */ +#define ISCCC_CCMSGTYPE_STRING 0x00 +/*% Message Type Binary Data */ +#define ISCCC_CCMSGTYPE_BINARYDATA 0x01 +/*% Message Type Table */ +#define ISCCC_CCMSGTYPE_TABLE 0x02 +/*% Message Type List */ +#define ISCCC_CCMSGTYPE_LIST 0x03 + +/*% Send to Wire */ +isc_result_t +isccc_cc_towire(isccc_sexpr_t *alist, isc_buffer_t **buffer, uint32_t algorithm, + isccc_region_t *secret); + +/*% Get From Wire */ +isc_result_t +isccc_cc_fromwire(isccc_region_t *source, isccc_sexpr_t **alistp, + uint32_t algorithm, isccc_region_t *secret); + +/*% Create Message */ +isc_result_t +isccc_cc_createmessage(uint32_t version, const char *from, const char *to, + uint32_t serial, isccc_time_t now, isccc_time_t expires, + isccc_sexpr_t **alistp); + +/*% Create Acknowledgment */ +isc_result_t +isccc_cc_createack(isccc_sexpr_t *message, bool ok, isccc_sexpr_t **ackp); + +/*% Is Ack? */ +bool +isccc_cc_isack(isccc_sexpr_t *message); + +/*% Is Reply? */ +bool +isccc_cc_isreply(isccc_sexpr_t *message); + +/*% Create Response */ +isc_result_t +isccc_cc_createresponse(isccc_sexpr_t *message, isccc_time_t now, + isccc_time_t expires, isccc_sexpr_t **alistp); + +/*% Define String */ +isccc_sexpr_t * +isccc_cc_definestring(isccc_sexpr_t *alist, const char *key, const char *str); + +/*% Define uint 32 */ +isccc_sexpr_t * +isccc_cc_defineuint32(isccc_sexpr_t *alist, const char *key, uint32_t i); + +/*% Lookup String */ +isc_result_t +isccc_cc_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp); + +/*% Lookup uint 32 */ +isc_result_t +isccc_cc_lookupuint32(isccc_sexpr_t *alist, const char *key, uint32_t *uintp); + +/*% Create Symbol Table */ +isc_result_t +isccc_cc_createsymtab(isccc_symtab_t **symtabp); + +/*% Clean up Symbol Table */ +void +isccc_cc_cleansymtab(isccc_symtab_t *symtab, isccc_time_t now); + +/*% Check for Duplicates */ +isc_result_t +isccc_cc_checkdup(isccc_symtab_t *symtab, isccc_sexpr_t *message, + isccc_time_t now); + +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 0000000..db64fcf --- /dev/null +++ b/lib/isccc/include/isccc/ccmsg.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#ifndef ISCCC_CCMSG_H +#define ISCCC_CCMSG_H 1 + +/*! \file isccc/ccmsg.h */ + +#include <inttypes.h> + +#include <isc/buffer.h> +#include <isc/lang.h> +#include <isc/socket.h> + +/*% ISCCC Message Structure */ +typedef struct isccc_ccmsg { + /* private (don't touch!) */ + unsigned int magic; + 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: + * + *\li "mctx" and "sock" be non-NULL and valid types. + * + *\li "sock" be a read/write TCP socket. + * + *\li "ccmsg" be non-NULL and an uninitialized or invalidated structure. + * + * Ensures: + * + *\li "ccmsg" is a valid structure. + */ + +void +isccc_ccmsg_setmaxsize(isccc_ccmsg_t *ccmsg, unsigned int maxsize); +/*% + * Set the maximum packet size to "maxsize" + * + * Requires: + * + *\li "ccmsg" be valid. + * + *\li 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 command channel message is + * readable, or when an error occurs on the socket. + * + * Requires: + * + *\li "ccmsg" be valid. + * + *\li "task", "taskaction", and "arg" be valid. + * + * Returns: + * + *\li #ISC_R_SUCCESS -- no error + *\li Anything that the isc_socket_recv() call can return. XXXMLG + * + * Notes: + * + *\li 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: + * + *\li "ccmsg" be valid. + */ + +void +isccc_ccmsg_invalidate(isccc_ccmsg_t *ccmsg); +/*% + * Clean up all allocated state, and invalidate the structure. + * + * Requires: + * + *\li "ccmsg" be valid. + * + * Ensures: + * + *\li "ccmsg" is invalidated and disassociated with all memory contexts, + * sockets, etc. + */ + +ISC_LANG_ENDDECLS + +#endif /* ISCCC_CCMSG_H */ diff --git a/lib/isccc/include/isccc/events.h b/lib/isccc/include/isccc/events.h new file mode 100644 index 0000000..78ee02d --- /dev/null +++ b/lib/isccc/include/isccc/events.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#ifndef ISCCC_EVENTS_H +#define ISCCC_EVENTS_H 1 + +/*! \file isccc/events.h */ + +#include <isc/eventclass.h> + +/*% + * 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/result.h b/lib/isccc/include/isccc/result.h new file mode 100644 index 0000000..56f9c38 --- /dev/null +++ b/lib/isccc/include/isccc/result.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2001 Nominum, Inc. + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#ifndef ISCCC_RESULT_H +#define ISCCC_RESULT_H 1 + +/*! \file isccc/result.h */ + +#include <isc/lang.h> +#include <isc/result.h> +#include <isc/resultclass.h> + +#include <isccc/types.h> + +/*% Unknown Version */ +#define ISCCC_R_UNKNOWNVERSION (ISC_RESULTCLASS_ISCCC + 0) +/*% Syntax Error */ +#define ISCCC_R_SYNTAX (ISC_RESULTCLASS_ISCCC + 1) +/*% Bad Authorization */ +#define ISCCC_R_BADAUTH (ISC_RESULTCLASS_ISCCC + 2) +/*% Expired */ +#define ISCCC_R_EXPIRED (ISC_RESULTCLASS_ISCCC + 3) +/*% Clock Skew */ +#define ISCCC_R_CLOCKSKEW (ISC_RESULTCLASS_ISCCC + 4) +/*% Duplicate */ +#define ISCCC_R_DUPLICATE (ISC_RESULTCLASS_ISCCC + 5) +/*% Maximum recursion depth */ +#define ISCCC_R_MAXDEPTH (ISC_RESULTCLASS_ISCCC + 6) + +#define ISCCC_R_NRESULTS 7 /*%< Number of results */ + +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_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 0000000..dae9906 --- /dev/null +++ b/lib/isccc/include/isccc/sexpr.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#ifndef ISCCC_SEXPR_H +#define ISCCC_SEXPR_H 1 + +/*! \file isccc/sexpr.h */ + +#include <stdbool.h> +#include <stdio.h> + +#include <isc/lang.h> + +#include <isccc/types.h> + +ISC_LANG_BEGINDECLS + +/*% dotted pair structure */ +struct isccc_dottedpair { + isccc_sexpr_t *car; + isccc_sexpr_t *cdr; +}; + +/*% iscc_sexpr structure */ +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_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); + +bool +isccc_sexpr_listp(isccc_sexpr_t *sexpr); + +bool +isccc_sexpr_emptyp(isccc_sexpr_t *sexpr); + +bool +isccc_sexpr_stringp(isccc_sexpr_t *sexpr); + +bool +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 0000000..ff978b2 --- /dev/null +++ b/lib/isccc/include/isccc/symtab.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#ifndef ISCCC_SYMTAB_H +#define ISCCC_SYMTAB_H 1 + +/***** +***** Module Info +*****/ + +/*! \file isccc/symtab.h + * \brief + * 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 <key, type, + * value> 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: + * + *\li isccc_symexists_reject Disallow the define, returning #ISC_R_EXISTS + *\li isccc_symexists_replace Replace the old value with the new. The + * undefine action (if provided) will be called + * with the old <key, type, value> tuple. + *\li 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 <stdbool.h> + +#include <isc/lang.h> + +#include <isccc/types.h> + +/*** + *** 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 bool (*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, bool 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 0000000..9003683 --- /dev/null +++ b/lib/isccc/include/isccc/symtype.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#ifndef ISCCC_SYMTYPE_H +#define ISCCC_SYMTYPE_H 1 + +/*! \file isccc/symtype.h */ + +#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 0000000..477e2df --- /dev/null +++ b/lib/isccc/include/isccc/types.h @@ -0,0 +1,55 @@ +/* + * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#ifndef ISCCC_TYPES_H +#define ISCCC_TYPES_H 1 + +/*! \file isccc/types.h */ + +#include <inttypes.h> + +#include <isc/result.h> + +/*% isccc_time_t typedef */ +typedef uint32_t isccc_time_t; + +/*% isccc_sexpr_t typedef */ +typedef struct isccc_sexpr isccc_sexpr_t; +/*% isccc_dottedpair_t typedef */ +typedef struct isccc_dottedpair isccc_dottedpair_t; +/*% isccc_symtab_t typedef */ +typedef struct isccc_symtab isccc_symtab_t; + +/*% iscc region structure */ +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 0000000..546423d --- /dev/null +++ b/lib/isccc/include/isccc/util.h @@ -0,0 +1,229 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#ifndef ISCCC_UTIL_H +#define ISCCC_UTIL_H 1 + +#include <inttypes.h> + +#include <isc/util.h> + +/*! \file isccc/util.h + * \brief + * 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 = (uint64_t)w[0] << 56; \ + v |= (uint64_t)w[1] << 48; \ + v |= (uint64_t)w[2] << 40; \ + v |= (uint64_t)w[3] << 32; \ + v |= (uint64_t)w[4] << 24; \ + v |= (uint64_t)w[5] << 16; \ + v |= (uint64_t)w[6] << 8; \ + v |= (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 { \ + memmove(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 <string.h> + +#define PUT_MEM(s, c, w) \ + do { \ + memmove(w, s, c); \ + w += c; \ + } while (0) + +/* + * 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/include/isccc/version.h b/lib/isccc/include/isccc/version.h new file mode 100644 index 0000000..9dc1a6d --- /dev/null +++ b/lib/isccc/include/isccc/version.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file isccc/version.h */ + +#include <isc/platform.h> + +LIBISCCC_EXTERNAL_DATA extern const char isccc_version[]; diff --git a/lib/isccc/result.c b/lib/isccc/result.c new file mode 100644 index 0000000..127dd77 --- /dev/null +++ b/lib/isccc/result.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2001 Nominum, Inc. + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <isc/once.h> +#include <isc/util.h> + +#include <isccc/result.h> + +static const char *text[ISCCC_R_NRESULTS] = { + "unknown version", /* 1 */ + "syntax error", /* 2 */ + "bad auth", /* 3 */ + "expired", /* 4 */ + "clock skew", /* 5 */ + "duplicate", /* 6 */ + "max depth" /* 7 */ +}; + +static const char *ids[ISCCC_R_NRESULTS] = { + "ISCCC_R_UNKNOWNVERSION", "ISCCC_R_SYNTAX", "ISCCC_R_BADAUTH", + "ISCCC_R_EXPIRED", "ISCCC_R_CLOCKSKEW", "ISCCC_R_DUPLICATE", + "ISCCC_R_MAXDEPTH" +}; + +#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_RESULT_RESULTSET); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_result_register() failed: %u", result); + } + + result = isc_result_registerids(ISC_RESULTCLASS_ISCCC, ISCCC_R_NRESULTS, + ids, ISCCC_RESULT_RESULTSET); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_result_registerids() failed: %u", result); + } +} + +static void +initialize(void) { + 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(); +} diff --git a/lib/isccc/sexpr.c b/lib/isccc/sexpr.c new file mode 100644 index 0000000..62c80c4 --- /dev/null +++ b/lib/isccc/sexpr.c @@ -0,0 +1,317 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/*! \file */ + +#include <ctype.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/assertions.h> +#include <isc/print.h> + +#include <isccc/sexpr.h> +#include <isccc/util.h> + +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; + memmove(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; + *sexprp = NULL; + 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); +} + +static bool +printable(isccc_region_t *r) { + unsigned char *curr; + + curr = r->rstart; + while (curr != r->rend) { + if (!isprint(*curr)) { + return (false); + } + curr++; + } + + return (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: + UNREACHABLE(); + } +} + +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); +} + +bool +isccc_sexpr_listp(isccc_sexpr_t *sexpr) { + if (sexpr == NULL || sexpr->type == ISCCC_SEXPRTYPE_DOTTEDPAIR) { + return (true); + } + return (false); +} + +bool +isccc_sexpr_emptyp(isccc_sexpr_t *sexpr) { + if (sexpr == NULL) { + return (true); + } + return (false); +} + +bool +isccc_sexpr_stringp(isccc_sexpr_t *sexpr) { + if (sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_STRING) { + return (true); + } + return (false); +} + +bool +isccc_sexpr_binaryp(isccc_sexpr_t *sexpr) { + if (sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_BINARY) { + return (true); + } + return (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 0000000..2ab969a --- /dev/null +++ b/lib/isccc/symtab.c @@ -0,0 +1,293 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 AND ISC + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * Copyright (C) 2001 Nominum, Inc. + * + * Permission to use, copy, modify, and/or 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 ISC AND NOMINUM DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/*! \file */ + +#include <ctype.h> +#include <stdbool.h> +#include <stdlib.h> + +#include <isc/assertions.h> +#include <isc/magic.h> +#include <isc/string.h> + +#include <isccc/result.h> +#include <isccc/symtab.h> +#include <isccc/util.h> + +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 ISC_MAGIC('S', 'y', 'm', 'T') +#define VALID_SYMTAB(st) ISC_MAGIC_VALID(st, SYMTAB_MAGIC) + +struct isccc_symtab { + unsigned int magic; + unsigned int size; + eltlist_t *table; + isccc_symtabundefaction_t undefine_action; + void *undefine_arg; + bool case_sensitive; +}; + +isc_result_t +isccc_symtab_create(unsigned int size, + isccc_symtabundefaction_t undefine_action, + void *undefine_arg, bool 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 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; + *symtabp = NULL; + 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); +} + +static unsigned int +hash(const char *key, bool 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/isccc/tests/Kyuafile b/lib/isccc/tests/Kyuafile new file mode 100644 index 0000000..79c8b3c --- /dev/null +++ b/lib/isccc/tests/Kyuafile @@ -0,0 +1,15 @@ +-- Copyright (C) Internet Systems Consortium, Inc. ("ISC") +-- +-- SPDX-License-Identifier: MPL-2.0 +-- +-- This Source Code Form is subject to the terms of the Mozilla Public +-- License, v. 2.0. If a copy of the MPL was not distributed with this +-- file, you can obtain one at https://mozilla.org/MPL/2.0/. +-- +-- See the COPYRIGHT file distributed with this work for additional +-- information regarding copyright ownership. + +syntax(2) +test_suite('bind9') + +tap_test_program{name='result_test'} diff --git a/lib/isccc/tests/Makefile.in b/lib/isccc/tests/Makefile.in new file mode 100644 index 0000000..f9f1968 --- /dev/null +++ b/lib/isccc/tests/Makefile.in @@ -0,0 +1,51 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +srcdir = @srcdir@ +VPATH = @srcdir@ +top_srcdir = @top_srcdir@ + +# Attempt to disable parallel processing. +.NOTPARALLEL: +.NO_PARALLEL: + +VERSION=@BIND9_VERSION@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I. -Iinclude ${ISCCC_INCLUDES} ${ISC_INCLUDES} @CMOCKA_CFLAGS@ +CDEFINES = + +ISCLIBS = ../../isc/libisc.@A@ +ISCDEPLIBS = ../../isc/libisc.@A@ +ISCCCLIBS = ../libisccc.@A@ +ISCCCDEPLIBS = ../libisccc.@A@ + +LIBS = @LIBS@ @CMOCKA_LIBS@ + +OBJS = +SRCS = result_test.c +SUBDIRS = +TARGETS = result_test@EXEEXT@ + +@BIND9_MAKE_RULES@ + +result_test@EXEEXT@: result_test.@O@ ${ISCDEPLIBS} ${ISCCCDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} \ + ${LDFLAGS} -o $@ result_test.@O@ \ + ${ISCCCLIBS} ${ISCLIBS} ${LIBS} + +unit:: + sh ${top_builddir}/unit/unittest.sh + +clean distclean:: + rm -f ${TARGETS} + rm -f atf.out diff --git a/lib/isccc/tests/result_test.c b/lib/isccc/tests/result_test.c new file mode 100644 index 0000000..b27ee22 --- /dev/null +++ b/lib/isccc/tests/result_test.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#if HAVE_CMOCKA + +#include <setjmp.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/result.h> +#include <isc/util.h> + +#include <isccc/result.h> + +/* + * Check tables are populated. + */ +static void +tables(void **state) { + const char *str; + isc_result_t result; + + UNUSED(state); + + isccc_result_register(); + + for (result = ISC_RESULTCLASS_ISCCC; + result < (ISC_RESULTCLASS_ISCCC + ISCCC_R_NRESULTS); result++) + { + str = isc_result_toid(result); + assert_non_null(str); + assert_string_not_equal(str, "(result code text not " + "available)"); + + str = isc_result_totext(result); + assert_non_null(str); + assert_string_not_equal(str, "(result code text not " + "available)"); + } + + str = isc_result_toid(result); + assert_non_null(str); + assert_string_equal(str, "(result code text not available)"); + + str = isc_result_totext(result); + assert_non_null(str); + assert_string_equal(str, "(result code text not available)"); +} + +int +main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test(tables), + }; + + return (cmocka_run_group_tests(tests, NULL, NULL)); +} + +#else /* HAVE_CMOCKA */ + +#include <stdio.h> + +int +main(void) { + printf("1..0 # Skipped: cmocka not available\n"); + return (SKIPPED_TEST_EXIT_CODE); +} + +#endif /* if HAVE_CMOCKA */ diff --git a/lib/isccc/version.c b/lib/isccc/version.c new file mode 100644 index 0000000..95f9ee2 --- /dev/null +++ b/lib/isccc/version.c @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#include <isccc/version.h> + +const char isccc_version[] = VERSION; diff --git a/lib/isccc/win32/DLLMain.c b/lib/isccc/win32/DLLMain.c new file mode 100644 index 0000000..62c6e53 --- /dev/null +++ b/lib/isccc/win32/DLLMain.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <signal.h> +#include <windows.h> + +/* + * Called when we enter the DLL + */ +__declspec(dllexport) BOOL WINAPI + DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { + switch (fdwReason) { + /* + * The DLL is loading due to process + * initialization or a call to LoadLibrary. + */ + case DLL_PROCESS_ATTACH: + break; + + /* The attached process creates a new thread. */ + case DLL_THREAD_ATTACH: + break; + + /* The thread of the attached process terminates. */ + case DLL_THREAD_DETACH: + break; + + /* + * The DLL is unloading from a process due to + * process termination or a call to FreeLibrary. + */ + case DLL_PROCESS_DETACH: + break; + + default: + break; + } + return (TRUE); +} diff --git a/lib/isccc/win32/libisccc.def b/lib/isccc/win32/libisccc.def new file mode 100644 index 0000000..5cb5662 --- /dev/null +++ b/lib/isccc/win32/libisccc.def @@ -0,0 +1,65 @@ +LIBRARY libisccc + +; Exported Functions +EXPORTS + +isccc_alist_create +isccc_alist_alistp +isccc_alist_emptyp +isccc_alist_first +isccc_alist_assq +isccc_alist_delete +isccc_alist_define +isccc_alist_definestring +isccc_alist_definebinary +isccc_alist_lookup +isccc_alist_lookupstring +isccc_alist_lookupbinary +isccc_alist_prettyprint +isccc_base64_encode +isccc_base64_decode +isccc_cc_towire +isccc_cc_fromwire +isccc_cc_createmessage +isccc_cc_createack +isccc_cc_isack +isccc_cc_isreply +isccc_cc_createresponse +isccc_cc_definestring +isccc_cc_defineuint32 +isccc_cc_lookupstring +isccc_cc_lookupuint32 +isccc_cc_createsymtab +isccc_cc_cleansymtab +isccc_cc_checkdup +isccc_ccmsg_init +isccc_ccmsg_setmaxsize +isccc_ccmsg_readmessage +isccc_ccmsg_cancelread +isccc_ccmsg_invalidate +isccc_result_totext +isccc_result_register +isccc_sexpr_cons +isccc_sexpr_tconst +isccc_sexpr_fromstring +isccc_sexpr_frombinary +isccc_sexpr_free +isccc_sexpr_print +isccc_sexpr_car +isccc_sexpr_cdr +isccc_sexpr_setcar +isccc_sexpr_setcdr +isccc_sexpr_addtolist +isccc_sexpr_listp +isccc_sexpr_emptyp +isccc_sexpr_stringp +isccc_sexpr_binaryp +isccc_sexpr_tostring +isccc_sexpr_tobinary +isccc_symtab_destroy +isccc_symtab_create +isccc_symtab_destroy +isccc_symtab_lookup +isccc_symtab_define +isccc_symtab_undefine +isccc_symtab_foreach diff --git a/lib/isccc/win32/libisccc.vcxproj.filters.in b/lib/isccc/win32/libisccc.vcxproj.filters.in new file mode 100644 index 0000000..1d1ff10 --- /dev/null +++ b/lib/isccc/win32/libisccc.vcxproj.filters.in @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + </ItemGroup> + <ItemGroup> + <None Include="libisccc.def" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="DLLMain.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="version.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\alist.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\base64.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\cc.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\ccmsg.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\result.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\sexpr.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\symtab.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\include\isccc\alist.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\isccc\base64.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\isccc\cc.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\isccc\ccmsg.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\isccc\events.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\isccc\result.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\isccc\sexpr.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\isccc\symtab.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\isccc\symtype.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\isccc\types.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\isccc\util.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\include\isccc\version.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> +</Project> diff --git a/lib/isccc/win32/libisccc.vcxproj.in b/lib/isccc/win32/libisccc.vcxproj.in new file mode 100644 index 0000000..86de718 --- /dev/null +++ b/lib/isccc/win32/libisccc.vcxproj.in @@ -0,0 +1,148 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="@TOOLS_VERSION@" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|@PLATFORM@"> + <Configuration>Debug</Configuration> + <Platform>@PLATFORM@</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|@PLATFORM@"> + <Configuration>Release</Configuration> + <Platform>@PLATFORM@</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{B556705F-1920-4400-878A-B259D3556047}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>libisccc</RootNamespace> + @WINDOWS_TARGET_PLATFORM_VERSION@ + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>MultiByte</CharacterSet> + @PLATFORM_TOOLSET@ + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + @PLATFORM_TOOLSET@ + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>..\..\..\Build\$(Configuration)\</OutDir> + <IntDir>.\$(Configuration)\</IntDir> + <IntDirSharingDetected>None</IntDirSharingDetected> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>..\..\..\Build\$(Configuration)\</OutDir> + <IntDir>.\$(Configuration)\</IntDir> + <IntDirSharingDetected>None</IntDirSharingDetected> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'"> + <ClCompile> + <PrecompiledHeader> + </PrecompiledHeader> + <WarningLevel>Level4</WarningLevel> + <TreatWarningAsError>false</TreatWarningAsError> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBISCCC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles> + <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@include;..\include;..\..\isc\win32;..\..\isc\win32\include;..\..\isc\include;..\..\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <FunctionLevelLinking>true</FunctionLevelLinking> + <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation> + <ObjectFileName>.\$(Configuration)\</ObjectFileName> + <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName> + <BrowseInformation>true</BrowseInformation> + <CompileAs>CompileAsC</CompileAs> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>..\..\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <ModuleDefinitionFile>$(ProjectName).def</ModuleDefinitionFile> + <ImportLibrary>.\$(Configuration)\$(ProjectName).lib</ImportLibrary> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'"> + <ClCompile> + <WarningLevel>Level1</WarningLevel> + <TreatWarningAsError>true</TreatWarningAsError> + <PrecompiledHeader> + </PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBISCCC_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions> + <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles> + <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@include;..\include;..\..\isc\win32;..\..\isc\win32\include;..\..\isc\include;..\..\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion> + <StringPooling>true</StringPooling> + <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile> + <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation> + <ObjectFileName>.\$(Configuration)\</ObjectFileName> + <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName> + <WholeProgramOptimization>false</WholeProgramOptimization> + <CompileAs>CompileAsC</CompileAs> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>false</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>..\..\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> + <ModuleDefinitionFile>$(ProjectName).def</ModuleDefinitionFile> + <ImportLibrary>.\$(Configuration)\$(ProjectName).lib</ImportLibrary> + <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <None Include="libisccc.def" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\alist.c" /> + <ClCompile Include="..\base64.c" /> + <ClCompile Include="..\cc.c" /> + <ClCompile Include="..\ccmsg.c" /> + <ClCompile Include="..\result.c" /> + <ClCompile Include="..\sexpr.c" /> + <ClCompile Include="..\symtab.c" /> + <ClCompile Include="DLLMain.c" /> + <ClCompile Include="version.c" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\include\isccc\alist.h" /> + <ClInclude Include="..\include\isccc\base64.h" /> + <ClInclude Include="..\include\isccc\cc.h" /> + <ClInclude Include="..\include\isccc\ccmsg.h" /> + <ClInclude Include="..\include\isccc\events.h" /> + <ClInclude Include="..\include\isccc\result.h" /> + <ClInclude Include="..\include\isccc\sexpr.h" /> + <ClInclude Include="..\include\isccc\symtab.h" /> + <ClInclude Include="..\include\isccc\symtype.h" /> + <ClInclude Include="..\include\isccc\types.h" /> + <ClInclude Include="..\include\isccc\util.h" /> + <ClInclude Include="..\include\isccc\version.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> diff --git a/lib/isccc/win32/libisccc.vcxproj.user b/lib/isccc/win32/libisccc.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/lib/isccc/win32/libisccc.vcxproj.user @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +</Project>
\ No newline at end of file diff --git a/lib/isccc/win32/version.c b/lib/isccc/win32/version.c new file mode 100644 index 0000000..6576b52 --- /dev/null +++ b/lib/isccc/win32/version.c @@ -0,0 +1,18 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include <versions.h> + +#include <isccc/version.h> + +LIBISCCC_EXTERNAL_DATA const char isccc_version[] = VERSION; |