From ea648e70a989cca190cd7403fe892fd2dcc290b4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 5 May 2024 20:37:14 +0200 Subject: Adding upstream version 1:9.11.5.P4+dfsg. Signed-off-by: Daniel Baumann --- lib/irs/Atffile | 5 + lib/irs/Kyuafile | 4 + lib/irs/Makefile.in | 80 ++ lib/irs/api | 13 + lib/irs/context.c | 392 ++++++++ lib/irs/dnsconf.c | 263 +++++ lib/irs/gai_strerror.c | 89 ++ lib/irs/getaddrinfo.c | 1311 +++++++++++++++++++++++++ lib/irs/getnameinfo.c | 409 ++++++++ lib/irs/include/Makefile.in | 17 + lib/irs/include/irs/Makefile.in | 44 + lib/irs/include/irs/context.h | 153 +++ lib/irs/include/irs/dnsconf.h | 88 ++ lib/irs/include/irs/netdb.h.in | 160 +++ lib/irs/include/irs/platform.h.in | 38 + lib/irs/include/irs/resconf.h | 117 +++ lib/irs/include/irs/types.h | 25 + lib/irs/include/irs/version.h | 21 + lib/irs/resconf.c | 654 ++++++++++++ lib/irs/tests/Atffile | 5 + lib/irs/tests/Kyuafile | 4 + lib/irs/tests/Makefile.in | 53 + lib/irs/tests/resconf_test.c | 139 +++ lib/irs/tests/testdata/domain.conf | 10 + lib/irs/tests/testdata/nameserver-v4.conf | 10 + lib/irs/tests/testdata/nameserver-v6.conf | 10 + lib/irs/tests/testdata/options-bad-ndots.conf | 11 + lib/irs/tests/testdata/options-debug.conf | 10 + lib/irs/tests/testdata/options-empty.conf | 11 + lib/irs/tests/testdata/options-ndots.conf | 10 + lib/irs/tests/testdata/options-timeout.conf | 10 + lib/irs/tests/testdata/options-unknown.conf | 10 + lib/irs/tests/testdata/options.conf | 10 + lib/irs/tests/testdata/port.conf | 10 + lib/irs/tests/testdata/resolv.conf | 17 + lib/irs/tests/testdata/search.conf | 10 + lib/irs/tests/testdata/sortlist-v4.conf | 10 + lib/irs/tests/testdata/timeout.conf | 10 + lib/irs/tests/testdata/unknown.conf | 10 + lib/irs/version.c | 21 + lib/irs/win32/DLLMain.c | 50 + lib/irs/win32/Makefile.in | 17 + lib/irs/win32/include/Makefile.in | 17 + lib/irs/win32/include/irs/Makefile.in | 26 + lib/irs/win32/include/irs/netdb.h | 201 ++++ lib/irs/win32/include/irs/platform.h | 38 + lib/irs/win32/libirs.def | 27 + lib/irs/win32/libirs.dsp.in | 169 ++++ lib/irs/win32/libirs.dsw | 29 + lib/irs/win32/libirs.mak.in | 548 +++++++++++ lib/irs/win32/libirs.vcxproj.filters.in | 69 ++ lib/irs/win32/libirs.vcxproj.in | 133 +++ lib/irs/win32/libirs.vcxproj.user | 3 + lib/irs/win32/version.c | 21 + 54 files changed, 5622 insertions(+) create mode 100644 lib/irs/Atffile create mode 100644 lib/irs/Kyuafile create mode 100644 lib/irs/Makefile.in create mode 100644 lib/irs/api create mode 100644 lib/irs/context.c create mode 100644 lib/irs/dnsconf.c create mode 100644 lib/irs/gai_strerror.c create mode 100644 lib/irs/getaddrinfo.c create mode 100644 lib/irs/getnameinfo.c create mode 100644 lib/irs/include/Makefile.in create mode 100644 lib/irs/include/irs/Makefile.in create mode 100644 lib/irs/include/irs/context.h create mode 100644 lib/irs/include/irs/dnsconf.h create mode 100644 lib/irs/include/irs/netdb.h.in create mode 100644 lib/irs/include/irs/platform.h.in create mode 100644 lib/irs/include/irs/resconf.h create mode 100644 lib/irs/include/irs/types.h create mode 100644 lib/irs/include/irs/version.h create mode 100644 lib/irs/resconf.c create mode 100644 lib/irs/tests/Atffile create mode 100644 lib/irs/tests/Kyuafile create mode 100644 lib/irs/tests/Makefile.in create mode 100644 lib/irs/tests/resconf_test.c create mode 100644 lib/irs/tests/testdata/domain.conf create mode 100644 lib/irs/tests/testdata/nameserver-v4.conf create mode 100644 lib/irs/tests/testdata/nameserver-v6.conf create mode 100644 lib/irs/tests/testdata/options-bad-ndots.conf create mode 100644 lib/irs/tests/testdata/options-debug.conf create mode 100644 lib/irs/tests/testdata/options-empty.conf create mode 100644 lib/irs/tests/testdata/options-ndots.conf create mode 100644 lib/irs/tests/testdata/options-timeout.conf create mode 100644 lib/irs/tests/testdata/options-unknown.conf create mode 100644 lib/irs/tests/testdata/options.conf create mode 100644 lib/irs/tests/testdata/port.conf create mode 100644 lib/irs/tests/testdata/resolv.conf create mode 100644 lib/irs/tests/testdata/search.conf create mode 100644 lib/irs/tests/testdata/sortlist-v4.conf create mode 100644 lib/irs/tests/testdata/timeout.conf create mode 100644 lib/irs/tests/testdata/unknown.conf create mode 100644 lib/irs/version.c create mode 100644 lib/irs/win32/DLLMain.c create mode 100644 lib/irs/win32/Makefile.in create mode 100644 lib/irs/win32/include/Makefile.in create mode 100644 lib/irs/win32/include/irs/Makefile.in create mode 100644 lib/irs/win32/include/irs/netdb.h create mode 100644 lib/irs/win32/include/irs/platform.h create mode 100644 lib/irs/win32/libirs.def create mode 100644 lib/irs/win32/libirs.dsp.in create mode 100644 lib/irs/win32/libirs.dsw create mode 100644 lib/irs/win32/libirs.mak.in create mode 100644 lib/irs/win32/libirs.vcxproj.filters.in create mode 100644 lib/irs/win32/libirs.vcxproj.in create mode 100644 lib/irs/win32/libirs.vcxproj.user create mode 100644 lib/irs/win32/version.c (limited to 'lib/irs') diff --git a/lib/irs/Atffile b/lib/irs/Atffile new file mode 100644 index 0000000..1edb838 --- /dev/null +++ b/lib/irs/Atffile @@ -0,0 +1,5 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = bind9 + +tp: tests diff --git a/lib/irs/Kyuafile b/lib/irs/Kyuafile new file mode 100644 index 0000000..0739e3a --- /dev/null +++ b/lib/irs/Kyuafile @@ -0,0 +1,4 @@ +syntax(2) +test_suite('bind9') + +include('tests/Kyuafile') diff --git a/lib/irs/Makefile.in b/lib/irs/Makefile.in new file mode 100644 index 0000000..fc11447 --- /dev/null +++ b/lib/irs/Makefile.in @@ -0,0 +1,80 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://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@ + +@LIBIRS_API@ + +@BIND9_MAKE_INCLUDES@ + +CINCLUDES = -I. -I./include -I${srcdir}/include \ + ${DNS_INCLUDES} ${ISC_INCLUDES} \ + ${ISCCFG_INCLUDES} @ISC_OPENSSL_INC@ + +CDEFINES = @CRYPTO@ +CWARNINGS = + +# Alphabetically +OBJS = context.@O@ \ + dnsconf.@O@ \ + gai_strerror.@O@ getaddrinfo.@O@ getnameinfo.@O@ \ + resconf.@O@ + +# Alphabetically +SRCS = context.c \ + dnsconf.c \ + gai_strerror.c getaddrinfo.c getnameinfo.c \ + resconf.c + +LIBS = @LIBS@ + +SUBDIRS = include +TESTDIRS = @UNITTESTS@ +TARGETS = timestamp + +@BIND9_MAKE_RULES@ + +version.@O@: version.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ + -DVERSION=\"${VERSION}\" \ + -DLIBINTERFACE=${LIBINTERFACE} \ + -DLIBREVISION=${LIBREVISION} \ + -DLIBAGE=${LIBAGE} \ + -c ${srcdir}/version.c + +libirs.@SA@: ${OBJS} version.@O@ + ${AR} ${ARFLAGS} $@ ${OBJS} version.@O@ + ${RANLIB} $@ + +libirs.la: ${OBJS} version.@O@ + ${LIBTOOL_MODE_LINK} \ + ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libirs.la -rpath ${libdir} \ + -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \ + ${OBJS} version.@O@ ${LIBS} + +timestamp: libirs.@A@ + touch timestamp + +testdirs: libirs.@A@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} + +install:: timestamp installdirs + ${LIBTOOL_MODE_INSTALL} ${INSTALL_LIBRARY} libirs.@A@ ${DESTDIR}${libdir} + +uninstall:: + ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${libdir}/libirs.@A@ + +clean distclean:: + rm -f libirs.@A@ libirs.la timestamp diff --git a/lib/irs/api b/lib/irs/api new file mode 100644 index 0000000..79bb9eb --- /dev/null +++ b/lib/irs/api @@ -0,0 +1,13 @@ +# LIBINTERFACE ranges +# 9.6: 50-59, 110-119 +# 9.7: 60-79 +# 9.8: 80-89, 120-129 +# 9.9: 90-109, 170-179 +# 9.9-sub: 130-139, 150-159, 200-209 +# 9.10: 140-149, 190-199 +# 9.10-sub: 180-189 +# 9.11: 160-169,1100-1199 +# 9.12: 1200-1299 +LIBINTERFACE = 161 +LIBREVISION = 0 +LIBAGE = 0 diff --git a/lib/irs/context.c b/lib/irs/context.c new file mode 100644 index 0000000..b644693 --- /dev/null +++ b/lib/irs/context.c @@ -0,0 +1,392 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#define IRS_CONTEXT_MAGIC ISC_MAGIC('I', 'R', 'S', 'c') +#define IRS_CONTEXT_VALID(c) ISC_MAGIC_VALID(c, IRS_CONTEXT_MAGIC) + +#ifndef RESOLV_CONF +/*% location of resolve.conf */ +#define RESOLV_CONF "/etc/resolv.conf" +#endif + +#ifndef DNS_CONF +/*% location of dns.conf */ +#define DNS_CONF "/etc/dns.conf" +#endif + +#ifndef ISC_PLATFORM_USETHREADS +irs_context_t *irs_g_context = NULL; +#else +static bool thread_key_initialized = false; +static isc_mutex_t thread_key_mutex; +static isc_thread_key_t irs_context_key; +static isc_once_t once = ISC_ONCE_INIT; +#endif + + +struct irs_context { + /* + * An IRS context is a thread-specific object, and does not need to + * be locked. + */ + unsigned int magic; + isc_mem_t *mctx; + isc_appctx_t *actx; + isc_taskmgr_t *taskmgr; + isc_task_t *task; + isc_socketmgr_t *socketmgr; + isc_timermgr_t *timermgr; + dns_client_t *dnsclient; + irs_resconf_t *resconf; + irs_dnsconf_t *dnsconf; +}; + +static void +ctxs_destroy(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + if (taskmgrp != NULL) + isc_taskmgr_destroy(taskmgrp); + + if (timermgrp != NULL) + isc_timermgr_destroy(timermgrp); + + if (socketmgrp != NULL) + isc_socketmgr_destroy(socketmgrp); + + if (actxp != NULL) + isc_appctx_destroy(actxp); + + if (mctxp != NULL) + isc_mem_destroy(mctxp); +} + +static isc_result_t +ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp, + isc_taskmgr_t **taskmgrp, isc_socketmgr_t **socketmgrp, + isc_timermgr_t **timermgrp) +{ + isc_result_t result; + + result = isc_mem_create(0, 0, mctxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_appctx_create(*mctxp, actxp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp); + if (result != ISC_R_SUCCESS) + goto fail; + + return (ISC_R_SUCCESS); + + fail: + ctxs_destroy(mctxp, actxp, taskmgrp, socketmgrp, timermgrp); + + return (result); +} + +#ifdef ISC_PLATFORM_USETHREADS +static void +free_specific_context(void *arg) { + irs_context_t *context = arg; + + irs_context_destroy(&context); + + isc_thread_key_setspecific(irs_context_key, NULL); +} + +static void +thread_key_mutex_init(void) { + RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS); +} + +static isc_result_t +thread_key_init(void) { + isc_result_t result; + + result = isc_once_do(&once, thread_key_mutex_init); + if (result != ISC_R_SUCCESS) + return (result); + + if (!thread_key_initialized) { + LOCK(&thread_key_mutex); + + if (!thread_key_initialized && + isc_thread_key_create(&irs_context_key, + free_specific_context) != 0) { + result = ISC_R_FAILURE; + } else + thread_key_initialized = true; + + UNLOCK(&thread_key_mutex); + } + + return (result); +} +#endif /* ISC_PLATFORM_USETHREADS */ + +isc_result_t +irs_context_get(irs_context_t **contextp) { + irs_context_t *context; + isc_result_t result; + + REQUIRE(contextp != NULL && *contextp == NULL); + +#ifndef ISC_PLATFORM_USETHREADS + if (irs_g_context == NULL) { + result = irs_context_create(&irs_g_context); + if (result != ISC_R_SUCCESS) + return (result); + } + + context = irs_g_context; +#else + result = thread_key_init(); + if (result != ISC_R_SUCCESS) + return (result); + + context = isc_thread_key_getspecific(irs_context_key); + if (context == NULL) { + result = irs_context_create(&context); + if (result != ISC_R_SUCCESS) + return (result); + result = isc_thread_key_setspecific(irs_context_key, context); + if (result != ISC_R_SUCCESS) { + irs_context_destroy(&context); + return (result); + } + } +#endif /* ISC_PLATFORM_USETHREADS */ + + *contextp = context; + + return (ISC_R_SUCCESS); +} + +isc_result_t +irs_context_create(irs_context_t **contextp) { + isc_result_t result; + irs_context_t *context; + isc_appctx_t *actx = NULL; + isc_mem_t *mctx = NULL; + isc_taskmgr_t *taskmgr = NULL; + isc_socketmgr_t *socketmgr = NULL; + isc_timermgr_t *timermgr = NULL; + dns_client_t *client = NULL; + isc_sockaddrlist_t *nameservers; + irs_dnsconf_dnskeylist_t *trustedkeys; + irs_dnsconf_dnskey_t *trustedkey; + + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) + return (result); + + result = ctxs_init(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); + if (result != ISC_R_SUCCESS) + return (result); + + result = isc_app_ctxstart(actx); + if (result != ISC_R_SUCCESS) { + ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); + return (result); + } + + context = isc_mem_get(mctx, sizeof(*context)); + if (context == NULL) { + ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); + return (ISC_R_NOMEMORY); + } + + context->mctx = mctx; + context->actx = actx; + context->taskmgr = taskmgr; + context->socketmgr = socketmgr; + context->timermgr = timermgr; + context->resconf = NULL; + context->dnsconf = NULL; + context->task = NULL; + result = isc_task_create(taskmgr, 0, &context->task); + if (result != ISC_R_SUCCESS) + goto fail; + + /* Create a DNS client object */ + result = dns_client_createx(mctx, actx, taskmgr, socketmgr, timermgr, + 0, &client); + if (result != ISC_R_SUCCESS) + goto fail; + context->dnsclient = client; + + /* Read resolver configuration file */ + result = irs_resconf_load(mctx, RESOLV_CONF, &context->resconf); + if (result != ISC_R_SUCCESS) + goto fail; + /* Set nameservers */ + nameservers = irs_resconf_getnameservers(context->resconf); + result = dns_client_setservers(client, dns_rdataclass_in, NULL, + nameservers); + if (result != ISC_R_SUCCESS) + goto fail; + + /* Read advanced DNS configuration (if any) */ + result = irs_dnsconf_load(mctx, DNS_CONF, &context->dnsconf); + if (result != ISC_R_SUCCESS) + goto fail; + trustedkeys = irs_dnsconf_gettrustedkeys(context->dnsconf); + for (trustedkey = ISC_LIST_HEAD(*trustedkeys); + trustedkey != NULL; + trustedkey = ISC_LIST_NEXT(trustedkey, link)) { + result = dns_client_addtrustedkey(client, dns_rdataclass_in, + trustedkey->keyname, + trustedkey->keydatabuf); + if (result != ISC_R_SUCCESS) + goto fail; + } + + context->magic = IRS_CONTEXT_MAGIC; + *contextp = context; + + return (ISC_R_SUCCESS); + + fail: + if (context->task != NULL) + isc_task_detach(&context->task); + if (context->resconf != NULL) + irs_resconf_destroy(&context->resconf); + if (context->dnsconf != NULL) + irs_dnsconf_destroy(&context->dnsconf); + if (client != NULL) + dns_client_destroy(&client); + ctxs_destroy(NULL, &actx, &taskmgr, &socketmgr, &timermgr); + isc_mem_putanddetach(&mctx, context, sizeof(*context)); + + return (result); +} + +void +irs_context_destroy(irs_context_t **contextp) { + irs_context_t *context; + + REQUIRE(contextp != NULL); + context = *contextp; + REQUIRE(IRS_CONTEXT_VALID(context)); + + isc_task_detach(&context->task); + irs_dnsconf_destroy(&context->dnsconf); + irs_resconf_destroy(&context->resconf); + dns_client_destroy(&context->dnsclient); + + ctxs_destroy(NULL, &context->actx, &context->taskmgr, + &context->socketmgr, &context->timermgr); + + context->magic = 0; + + isc_mem_putanddetach(&context->mctx, context, sizeof(*context)); + + *contextp = NULL; + +#ifndef ISC_PLATFORM_USETHREADS + irs_g_context = NULL; +#else + (void)isc_thread_key_setspecific(irs_context_key, NULL); +#endif +} + +isc_mem_t * +irs_context_getmctx(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->mctx); +} + +isc_appctx_t * +irs_context_getappctx(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->actx); +} + +isc_taskmgr_t * +irs_context_gettaskmgr(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->taskmgr); +} + +isc_timermgr_t * +irs_context_gettimermgr(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->timermgr); +} + +isc_task_t * +irs_context_gettask(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->task); +} + +dns_client_t * +irs_context_getdnsclient(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->dnsclient); +} + +irs_resconf_t * +irs_context_getresconf(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->resconf); +} + +irs_dnsconf_t * +irs_context_getdnsconf(irs_context_t *context) { + REQUIRE(IRS_CONTEXT_VALID(context)); + + return (context->dnsconf); +} diff --git a/lib/irs/dnsconf.c b/lib/irs/dnsconf.c new file mode 100644 index 0000000..ee89af0 --- /dev/null +++ b/lib/irs/dnsconf.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#define IRS_DNSCONF_MAGIC ISC_MAGIC('D', 'c', 'f', 'g') +#define IRS_DNSCONF_VALID(c) ISC_MAGIC_VALID(c, IRS_DNSCONF_MAGIC) + +/*! + * configuration data structure + */ + +struct irs_dnsconf { + unsigned int magic; + isc_mem_t *mctx; + irs_dnsconf_dnskeylist_t trusted_keylist; +}; + +static isc_result_t +configure_dnsseckeys(irs_dnsconf_t *conf, cfg_obj_t *cfgobj, + dns_rdataclass_t rdclass) +{ + isc_mem_t *mctx = conf->mctx; + const cfg_obj_t *keys = NULL; + const cfg_obj_t *key, *keylist; + dns_fixedname_t fkeyname; + dns_name_t *keyname_base, *keyname; + const cfg_listelt_t *element, *element2; + isc_result_t result; + uint32_t flags, proto, alg; + const char *keystr, *keynamestr; + unsigned char keydata[4096]; + isc_buffer_t keydatabuf_base, *keydatabuf; + dns_rdata_dnskey_t keystruct; + unsigned char rrdata[4096]; + isc_buffer_t rrdatabuf; + isc_region_t r; + isc_buffer_t namebuf; + irs_dnsconf_dnskey_t *keyent; + + cfg_map_get(cfgobj, "trusted-keys", &keys); + if (keys == NULL) + return (ISC_R_SUCCESS); + + for (element = cfg_list_first(keys); + element != NULL; + element = cfg_list_next(element)) { + keylist = cfg_listelt_value(element); + for (element2 = cfg_list_first(keylist); + element2 != NULL; + element2 = cfg_list_next(element2)) + { + keydatabuf = NULL; + keyname = NULL; + + key = cfg_listelt_value(element2); + + flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); + proto = cfg_obj_asuint32(cfg_tuple_get(key, + "protocol")); + alg = cfg_obj_asuint32(cfg_tuple_get(key, + "algorithm")); + keynamestr = cfg_obj_asstring(cfg_tuple_get(key, + "name")); + + keystruct.common.rdclass = rdclass; + keystruct.common.rdtype = dns_rdatatype_dnskey; + keystruct.mctx = NULL; + ISC_LINK_INIT(&keystruct.common, link); + + if (flags > 0xffff) + return (ISC_R_RANGE); + if (proto > 0xff) + return (ISC_R_RANGE); + if (alg > 0xff) + return (ISC_R_RANGE); + keystruct.flags = (uint16_t)flags; + keystruct.protocol = (uint8_t)proto; + keystruct.algorithm = (uint8_t)alg; + + isc_buffer_init(&keydatabuf_base, keydata, + sizeof(keydata)); + isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); + + /* Configure key value */ + keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); + result = isc_base64_decodestring(keystr, + &keydatabuf_base); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_usedregion(&keydatabuf_base, &r); + keystruct.datalen = r.length; + keystruct.data = r.base; + + result = dns_rdata_fromstruct(NULL, + keystruct.common.rdclass, + keystruct.common.rdtype, + &keystruct, &rrdatabuf); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_usedregion(&rrdatabuf, &r); + result = isc_buffer_allocate(mctx, &keydatabuf, + r.length); + if (result != ISC_R_SUCCESS) + return (result); + result = isc_buffer_copyregion(keydatabuf, &r); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Configure key name */ + keyname_base = dns_fixedname_initname(&fkeyname); + isc_buffer_constinit(&namebuf, keynamestr, + strlen(keynamestr)); + isc_buffer_add(&namebuf, strlen(keynamestr)); + result = dns_name_fromtext(keyname_base, &namebuf, + dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) + return (result); + keyname = isc_mem_get(mctx, sizeof(*keyname)); + if (keyname == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + dns_name_init(keyname, NULL); + result = dns_name_dup(keyname_base, mctx, keyname); + if (result != ISC_R_SUCCESS) + goto cleanup; + + /* Add the key data to the list */ + keyent = isc_mem_get(mctx, sizeof(*keyent)); + if (keyent == NULL) { + dns_name_free(keyname, mctx); + result = ISC_R_NOMEMORY; + goto cleanup; + } + keyent->keyname = keyname; + keyent->keydatabuf = keydatabuf; + + ISC_LIST_APPEND(conf->trusted_keylist, keyent, link); + } + } + + return (ISC_R_SUCCESS); + + cleanup: + if (keydatabuf != NULL) + isc_buffer_free(&keydatabuf); + if (keyname != NULL) + isc_mem_put(mctx, keyname, sizeof(*keyname)); + + return (result); +} + +isc_result_t +irs_dnsconf_load(isc_mem_t *mctx, const char *filename, irs_dnsconf_t **confp) +{ + irs_dnsconf_t *conf; + cfg_parser_t *parser = NULL; + cfg_obj_t *cfgobj = NULL; + isc_result_t result = ISC_R_SUCCESS; + + REQUIRE(confp != NULL && *confp == NULL); + + conf = isc_mem_get(mctx, sizeof(*conf)); + if (conf == NULL) + return (ISC_R_NOMEMORY); + + conf->mctx = mctx; + ISC_LIST_INIT(conf->trusted_keylist); + + /* + * If the specified file does not exist, we'll simply with an empty + * configuration. + */ + if (!isc_file_exists(filename)) + goto cleanup; + + result = cfg_parser_create(mctx, NULL, &parser); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = cfg_parse_file(parser, filename, &cfg_type_dnsconf, + &cfgobj); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = configure_dnsseckeys(conf, cfgobj, dns_rdataclass_in); + + cleanup: + if (parser != NULL) { + if (cfgobj != NULL) + cfg_obj_destroy(parser, &cfgobj); + cfg_parser_destroy(&parser); + } + + conf->magic = IRS_DNSCONF_MAGIC; + + if (result == ISC_R_SUCCESS) + *confp = conf; + else + irs_dnsconf_destroy(&conf); + + return (result); +} + +void +irs_dnsconf_destroy(irs_dnsconf_t **confp) { + irs_dnsconf_t *conf; + irs_dnsconf_dnskey_t *keyent; + + REQUIRE(confp != NULL); + conf = *confp; + REQUIRE(IRS_DNSCONF_VALID(conf)); + + while ((keyent = ISC_LIST_HEAD(conf->trusted_keylist)) != NULL) { + ISC_LIST_UNLINK(conf->trusted_keylist, keyent, link); + + isc_buffer_free(&keyent->keydatabuf); + dns_name_free(keyent->keyname, conf->mctx); + isc_mem_put(conf->mctx, keyent->keyname, sizeof(dns_name_t)); + isc_mem_put(conf->mctx, keyent, sizeof(*keyent)); + } + + isc_mem_put(conf->mctx, conf, sizeof(*conf)); + + *confp = NULL; +} + +irs_dnsconf_dnskeylist_t * +irs_dnsconf_gettrustedkeys(irs_dnsconf_t *conf) { + REQUIRE(IRS_DNSCONF_VALID(conf)); + + return (&conf->trusted_keylist); +} diff --git a/lib/irs/gai_strerror.c b/lib/irs/gai_strerror.c new file mode 100644 index 0000000..76a561e --- /dev/null +++ b/lib/irs/gai_strerror.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file gai_strerror.c + * gai_strerror() returns an error message corresponding to an + * error code returned by getaddrinfo() and getnameinfo(). The following error + * codes and their meaning are defined in + * \link netdb.h include/irs/netdb.h.\endlink + * This implementation is almost an exact copy of lwres/gai_sterror.c except + * that it catches up the latest API standard, RFC3493. + * + * \li #EAI_ADDRFAMILY address family for hostname not supported + * \li #EAI_AGAIN temporary failure in name resolution + * \li #EAI_BADFLAGS invalid value for ai_flags + * \li #EAI_FAIL non-recoverable failure in name resolution + * \li #EAI_FAMILY ai_family not supported + * \li #EAI_MEMORY memory allocation failure + * \li #EAI_NODATA no address associated with hostname (obsoleted in RFC3493) + * \li #EAI_NONAME hostname nor servname provided, or not known + * \li #EAI_SERVICE servname not supported for ai_socktype + * \li #EAI_SOCKTYPE ai_socktype not supported + * \li #EAI_SYSTEM system error returned in errno + * \li #EAI_BADHINTS Invalid value for hints (non-standard) + * \li #EAI_PROTOCOL Resolved protocol is unknown (non-standard) + * \li #EAI_OVERFLOW Argument buffer overflow + * \li #EAI_INSECUREDATA Insecure Data (experimental) + * + * The message invalid error code is returned if ecode is out of range. + * + * ai_flags, ai_family and ai_socktype are elements of the struct + * addrinfo used by lwres_getaddrinfo(). + * + * \section gai_strerror_see See Also + * + * strerror(), getaddrinfo(), getnameinfo(), RFC3493. + */ +#include + +#include + +#include + +/*% Text of error messages. */ +static const char *gai_messages[] = { + "no error", + "address family for hostname not supported", + "temporary failure in name resolution", + "invalid value for ai_flags", + "non-recoverable failure in name resolution", + "ai_family not supported", + "memory allocation failure", + "no address associated with hostname", + "hostname nor servname provided, or not known", + "servname not supported for ai_socktype", + "ai_socktype not supported", + "system error returned in errno", + "bad hints", + "bad protocol", + "argument buffer overflow", + "insecure data provided" +}; + +/*% + * Returns an error message corresponding to an error code returned by + * getaddrinfo() and getnameinfo() + */ +IRS_GAISTRERROR_RETURN_T +gai_strerror(int ecode) { + union { + const char *const_ptr; + char *deconst_ptr; + } ptr; + + if ((ecode < 0) || + (ecode >= (int)(sizeof(gai_messages)/sizeof(*gai_messages)))) + ptr.const_ptr = "invalid error code"; + else + ptr.const_ptr = gai_messages[ecode]; + return (ptr.deconst_ptr); +} diff --git a/lib/irs/getaddrinfo.c b/lib/irs/getaddrinfo.c new file mode 100644 index 0000000..33a7fb5 --- /dev/null +++ b/lib/irs/getaddrinfo.c @@ -0,0 +1,1311 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* $Id: getaddrinfo.c,v 1.3 2009/09/02 23:48:02 tbox Exp $ */ + +/*! \file */ + +/** + * getaddrinfo() is used to get a list of IP addresses and port + * numbers for host hostname and service servname as defined in RFC3493. + * hostname and servname are pointers to null-terminated strings + * or NULL. hostname is either a host name or a numeric host address + * string: a dotted decimal IPv4 address or an IPv6 address. servname is + * either a decimal port number or a service name as listed in + * /etc/services. + * + * If the operating system does not provide a struct addrinfo, the + * following structure is used: + * + * \code + * struct addrinfo { + * int ai_flags; // AI_PASSIVE, AI_CANONNAME + * int ai_family; // PF_xxx + * int ai_socktype; // SOCK_xxx + * int ai_protocol; // 0 or IPPROTO_xxx for IPv4 and IPv6 + * size_t ai_addrlen; // length of ai_addr + * char *ai_canonname; // canonical name for hostname + * struct sockaddr *ai_addr; // binary address + * struct addrinfo *ai_next; // next structure in linked list + * }; + * \endcode + * + * + * hints is an optional pointer to a struct addrinfo. This structure can + * be used to provide hints concerning the type of socket that the caller + * supports or wishes to use. The caller can supply the following + * structure elements in *hints: + * + *
    + *
  • ai_family: + * The protocol family that should be used. When ai_family is set + * to PF_UNSPEC, it means the caller will accept any protocol + * family supported by the operating system.
  • + * + *
  • ai_socktype: + * denotes the type of socket -- SOCK_STREAM, SOCK_DGRAM or + * SOCK_RAW -- that is wanted. When ai_socktype is zero the caller + * will accept any socket type.
  • + * + *
  • ai_protocol: + * indicates which transport protocol is wanted: IPPROTO_UDP or + * IPPROTO_TCP. If ai_protocol is zero the caller will accept any + * protocol.
  • + * + *
  • ai_flags: + * Flag bits. If the AI_CANONNAME bit is set, a successful call to + * getaddrinfo() will return a null-terminated string + * containing the canonical name of the specified hostname in + * ai_canonname of the first addrinfo structure returned. Setting + * the AI_PASSIVE bit indicates that the returned socket address + * structure is intended for used in a call to bind(2). In this + * case, if the hostname argument is a NULL pointer, then the IP + * address portion of the socket address structure will be set to + * INADDR_ANY for an IPv4 address or IN6ADDR_ANY_INIT for an IPv6 + * address.

    + * + * When ai_flags does not set the AI_PASSIVE bit, the returned + * socket address structure will be ready for use in a call to + * connect(2) for a connection-oriented protocol or connect(2), + * sendto(2), or sendmsg(2) if a connectionless protocol was + * chosen. The IP address portion of the socket address structure + * will be set to the loopback address if hostname is a NULL + * pointer and AI_PASSIVE is not set in ai_flags.

    + * + * If ai_flags is set to AI_NUMERICHOST it indicates that hostname + * should be treated as a numeric string defining an IPv4 or IPv6 + * address and no name resolution should be attempted. + *
+ * + * All other elements of the struct addrinfo passed via hints must be + * zero. + * + * A hints of NULL is treated as if the caller provided a struct addrinfo + * initialized to zero with ai_familyset to PF_UNSPEC. + * + * After a successful call to getaddrinfo(), *res is a pointer to a + * linked list of one or more addrinfo structures. Each struct addrinfo + * in this list cn be processed by following the ai_next pointer, until a + * NULL pointer is encountered. The three members ai_family, ai_socktype, + * and ai_protocol in each returned addrinfo structure contain the + * corresponding arguments for a call to socket(2). For each addrinfo + * structure in the list, the ai_addr member points to a filled-in socket + * address structure of length ai_addrlen. + * + * All of the information returned by getaddrinfo() is dynamically + * allocated: the addrinfo structures, and the socket address structures + * and canonical host name strings pointed to by the addrinfostructures. + * Memory allocated for the dynamically allocated structures created by a + * successful call to getaddrinfo() is released by freeaddrinfo(). + * ai is a pointer to a struct addrinfo created by a call to getaddrinfo(). + * + * \section irsreturn RETURN VALUES + * + * getaddrinfo() returns zero on success or one of the error codes + * listed in gai_strerror() if an error occurs. If both hostname and + * servname are NULL getaddrinfo() returns #EAI_NONAME. + * + * \section irssee SEE ALSO + * + * getaddrinfo(), freeaddrinfo(), + * gai_strerror(), RFC3493, getservbyname(3), connect(2), + * sendto(2), sendmsg(2), socket(2). + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define SA(addr) ((struct sockaddr *)(addr)) +#define SIN(addr) ((struct sockaddr_in *)(addr)) +#define SIN6(addr) ((struct sockaddr_in6 *)(addr)) +#define SLOCAL(addr) ((struct sockaddr_un *)(addr)) + +/*! \struct addrinfo + */ +static struct addrinfo + *ai_concat(struct addrinfo *ai1, struct addrinfo *ai2), + *ai_reverse(struct addrinfo *oai), + *ai_clone(struct addrinfo *oai, int family), + *ai_alloc(int family, int addrlen); +#ifdef AF_LOCAL +static int get_local(const char *name, int socktype, struct addrinfo **res); +#endif + +static int +resolve_name(int family, const char *hostname, int flags, + struct addrinfo **aip, int socktype, int port); + +static int add_ipv4(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port); +static int add_ipv6(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port); +static void set_order(int, int (**)(const char *, int, struct addrinfo **, + int, int)); +static void _freeaddrinfo(struct addrinfo *ai); + +#define FOUND_IPV4 0x1 +#define FOUND_IPV6 0x2 +#define FOUND_MAX 2 + +#define ISC_AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST) +/*% + * Get a list of IP addresses and port numbers for host hostname and + * service servname. + */ +int +getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + struct servent *sp; + const char *proto; + int family, socktype, flags, protocol; + struct addrinfo *ai, *ai_list; + int err = 0; + int port, i; + int (*net_order[FOUND_MAX+1])(const char *, int, struct addrinfo **, + int, int); + + if (hostname == NULL && servname == NULL) + return (EAI_NONAME); + + proto = NULL; + if (hints != NULL) { + if ((hints->ai_flags & ~(ISC_AI_MASK)) != 0) + return (EAI_BADFLAGS); + if (hints->ai_addrlen || hints->ai_canonname || + hints->ai_addr || hints->ai_next) { + errno = EINVAL; + return (EAI_SYSTEM); + } + family = hints->ai_family; + socktype = hints->ai_socktype; + protocol = hints->ai_protocol; + flags = hints->ai_flags; + switch (family) { + case AF_UNSPEC: + switch (hints->ai_socktype) { + case SOCK_STREAM: + proto = "tcp"; + break; + case SOCK_DGRAM: + proto = "udp"; + break; + } + break; + case AF_INET: + case AF_INET6: + switch (hints->ai_socktype) { + case 0: + break; + case SOCK_STREAM: + proto = "tcp"; + break; + case SOCK_DGRAM: + proto = "udp"; + break; + case SOCK_RAW: + break; + default: + return (EAI_SOCKTYPE); + } + break; +#ifdef AF_LOCAL + case AF_LOCAL: + switch (hints->ai_socktype) { + case 0: + break; + case SOCK_STREAM: + break; + case SOCK_DGRAM: + break; + default: + return (EAI_SOCKTYPE); + } + break; +#endif + default: + return (EAI_FAMILY); + } + } else { + protocol = 0; + family = 0; + socktype = 0; + flags = 0; + } + +#ifdef AF_LOCAL + /*! + * First, deal with AF_LOCAL. If the family was not set, + * then assume AF_LOCAL if the first character of the + * hostname/servname is '/'. + */ + + if (hostname != NULL && + (family == AF_LOCAL || (family == 0 && *hostname == '/'))) + return (get_local(hostname, socktype, res)); + + if (servname != NULL && + (family == AF_LOCAL || (family == 0 && *servname == '/'))) + return (get_local(servname, socktype, res)); +#endif + + /* + * Ok, only AF_INET and AF_INET6 left. + */ + ai_list = NULL; + + /* + * First, look up the service name (port) if it was + * requested. If the socket type wasn't specified, then + * try and figure it out. + */ + if (servname != NULL) { + char *e; + + port = strtol(servname, &e, 10); + if (*e == '\0') { + if (socktype == 0) + return (EAI_SOCKTYPE); + if (port < 0 || port > 65535) + return (EAI_SERVICE); + port = htons((unsigned short) port); + } else { + sp = getservbyname(servname, proto); + if (sp == NULL) + return (EAI_SERVICE); + port = sp->s_port; + if (socktype == 0) { + if (strcmp(sp->s_proto, "tcp") == 0) + socktype = SOCK_STREAM; + else if (strcmp(sp->s_proto, "udp") == 0) + socktype = SOCK_DGRAM; + } + } + } else + port = 0; + + /* + * Next, deal with just a service name, and no hostname. + * (we verified that one of them was non-null up above). + */ + if (hostname == NULL && (flags & AI_PASSIVE) != 0) { + if (family == AF_INET || family == 0) { + ai = ai_alloc(AF_INET, sizeof(struct sockaddr_in)); + if (ai == NULL) + return (EAI_MEMORY); + ai->ai_socktype = socktype; + ai->ai_protocol = protocol; + SIN(ai->ai_addr)->sin_port = port; + ai->ai_next = ai_list; + ai_list = ai; + } + + if (family == AF_INET6 || family == 0) { + ai = ai_alloc(AF_INET6, sizeof(struct sockaddr_in6)); + if (ai == NULL) { + _freeaddrinfo(ai_list); + return (EAI_MEMORY); + } + ai->ai_socktype = socktype; + ai->ai_protocol = protocol; + SIN6(ai->ai_addr)->sin6_port = port; + ai->ai_next = ai_list; + ai_list = ai; + } + + *res = ai_list; + return (0); + } + + /* + * If the family isn't specified or AI_NUMERICHOST specified, check + * first to see if it is a numeric address. + * Though the gethostbyname2() routine will recognize numeric addresses, + * it will only recognize the format that it is being called for. Thus, + * a numeric AF_INET address will be treated by the AF_INET6 call as + * a domain name, and vice versa. Checking for both numerics here + * avoids that. + */ + if (hostname != NULL && + (family == 0 || (flags & AI_NUMERICHOST) != 0)) { + char abuf[sizeof(struct in6_addr)]; + char nbuf[NI_MAXHOST]; + int addrsize, addroff; +#ifdef IRS_HAVE_SIN6_SCOPE_ID + char *p, *ep; + char ntmp[NI_MAXHOST]; + uint32_t scopeid; +#endif + +#ifdef IRS_HAVE_SIN6_SCOPE_ID + /* + * Scope identifier portion. + */ + ntmp[0] = '\0'; + if (strchr(hostname, '%') != NULL) { + strlcpy(ntmp, hostname, sizeof(ntmp)); + p = strchr(ntmp, '%'); + ep = NULL; + + /* + * Vendors may want to support non-numeric + * scopeid around here. + */ + + if (p != NULL) + scopeid = (uint32_t)strtoul(p + 1, + &ep, 10); + if (p != NULL && ep != NULL && ep[0] == '\0') + *p = '\0'; + else { + ntmp[0] = '\0'; + scopeid = 0; + } + } else + scopeid = 0; +#endif + + if (inet_pton(AF_INET, hostname, (struct in_addr *)abuf) + == 1) { + if (family == AF_INET6) { + /* + * Convert to a V4 mapped address. + */ + struct in6_addr *a6 = (struct in6_addr *)abuf; + memmove(&a6->s6_addr[12], &a6->s6_addr[0], 4); + memset(&a6->s6_addr[10], 0xff, 2); + memset(&a6->s6_addr[0], 0, 10); + goto inet6_addr; + } + addrsize = sizeof(struct in_addr); + addroff = offsetof(struct sockaddr_in, sin_addr); + family = AF_INET; + goto common; +#ifdef IRS_HAVE_SIN6_SCOPE_ID + } else if (ntmp[0] != '\0' && + inet_pton(AF_INET6, ntmp, abuf) == 1) { + if (family && family != AF_INET6) + return (EAI_NONAME); + addrsize = sizeof(struct in6_addr); + addroff = offsetof(struct sockaddr_in6, sin6_addr); + family = AF_INET6; + goto common; +#endif + } else if (inet_pton(AF_INET6, hostname, abuf) == 1) { + if (family != 0 && family != AF_INET6) + return (EAI_NONAME); + inet6_addr: + addrsize = sizeof(struct in6_addr); + addroff = offsetof(struct sockaddr_in6, sin6_addr); + family = AF_INET6; + + common: + ai = ai_alloc(family, + ((family == AF_INET6) ? + sizeof(struct sockaddr_in6) : + sizeof(struct sockaddr_in))); + if (ai == NULL) + return (EAI_MEMORY); + ai_list = ai; + ai->ai_socktype = socktype; + SIN(ai->ai_addr)->sin_port = port; + memmove((char *)ai->ai_addr + addroff, abuf, addrsize); + if ((flags & AI_CANONNAME) != 0) { +#ifdef IRS_HAVE_SIN6_SCOPE_ID + if (ai->ai_family == AF_INET6) + SIN6(ai->ai_addr)->sin6_scope_id = + scopeid; +#endif + if (getnameinfo(ai->ai_addr, + (socklen_t)ai->ai_addrlen, + nbuf, sizeof(nbuf), NULL, 0, + NI_NUMERICHOST) == 0) { + ai->ai_canonname = strdup(nbuf); + if (ai->ai_canonname == NULL) { + _freeaddrinfo(ai); + return (EAI_MEMORY); + } + } else { + /* XXX raise error? */ + ai->ai_canonname = NULL; + } + } + goto done; + } else if ((flags & AI_NUMERICHOST) != 0) { + return (EAI_NONAME); + } + } + + if (hostname == NULL && (flags & AI_PASSIVE) == 0) { + set_order(family, net_order); + for (i = 0; i < FOUND_MAX; i++) { + if (net_order[i] == NULL) + break; + err = (net_order[i])(hostname, flags, &ai_list, + socktype, port); + if (err != 0) { + if (ai_list != NULL) { + _freeaddrinfo(ai_list); + ai_list = NULL; + } + break; + } + } + } else + err = resolve_name(family, hostname, flags, &ai_list, + socktype, port); + + if (ai_list == NULL) { + if (err == 0) + err = EAI_NONAME; + return (err); + } + +done: + ai_list = ai_reverse(ai_list); + + *res = ai_list; + return (0); +} + +typedef struct gai_restrans { + dns_clientrestrans_t *xid; + bool is_inprogress; + int error; + struct addrinfo ai_sentinel; + struct gai_resstate *resstate; +} gai_restrans_t; + +typedef struct gai_resstate { + isc_mem_t *mctx; + struct gai_statehead *head; + dns_fixedname_t fixedname; + dns_name_t *qname; + gai_restrans_t *trans4; + gai_restrans_t *trans6; + ISC_LINK(struct gai_resstate) link; +} gai_resstate_t; + +typedef struct gai_statehead { + int ai_family; + int ai_flags; + int ai_socktype; + int ai_port; + isc_appctx_t *actx; + dns_client_t *dnsclient; + isc_mutex_t list_lock; + ISC_LIST(struct gai_resstate) resstates; + unsigned int activestates; +} gai_statehead_t; + +static isc_result_t +make_resstate(isc_mem_t *mctx, gai_statehead_t *head, const char *hostname, + const char *domain, gai_resstate_t **statep) +{ + isc_result_t result; + gai_resstate_t *state; + dns_fixedname_t fixeddomain; + dns_name_t *qdomain; + unsigned int namelen; + isc_buffer_t b; + bool need_v4 = false; + bool need_v6 = false; + + state = isc_mem_get(mctx, sizeof(*state)); + if (state == NULL) + return (ISC_R_NOMEMORY); + + /* Construct base domain name */ + namelen = strlen(domain); + isc_buffer_constinit(&b, domain, namelen); + isc_buffer_add(&b, namelen); + qdomain = dns_fixedname_initname(&fixeddomain); + result = dns_name_fromtext(qdomain, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, state, sizeof(*state)); + return (result); + } + + /* Construct query name */ + namelen = strlen(hostname); + isc_buffer_constinit(&b, hostname, namelen); + isc_buffer_add(&b, namelen); + state->qname = dns_fixedname_initname(&state->fixedname); + result = dns_name_fromtext(state->qname, &b, qdomain, 0, NULL); + if (result != ISC_R_SUCCESS) { + isc_mem_put(mctx, state, sizeof(*state)); + return (result); + } + + if (head->ai_family == AF_UNSPEC || head->ai_family == AF_INET) + need_v4 = true; + if (head->ai_family == AF_UNSPEC || head->ai_family == AF_INET6) + need_v6 = true; + + state->trans6 = NULL; + state->trans4 = NULL; + if (need_v4) { + state->trans4 = isc_mem_get(mctx, sizeof(gai_restrans_t)); + if (state->trans4 == NULL) { + isc_mem_put(mctx, state, sizeof(*state)); + return (ISC_R_NOMEMORY); + } + state->trans4->error = 0; + state->trans4->xid = NULL; + state->trans4->resstate = state; + state->trans4->is_inprogress = true; + state->trans4->ai_sentinel.ai_next = NULL; + } + if (need_v6) { + state->trans6 = isc_mem_get(mctx, sizeof(gai_restrans_t)); + if (state->trans6 == NULL) { + if (state->trans4 != NULL) + isc_mem_put(mctx, state->trans4, + sizeof(*state->trans4)); + isc_mem_put(mctx, state, sizeof(*state)); + return (ISC_R_NOMEMORY); + } + state->trans6->error = 0; + state->trans6->xid = NULL; + state->trans6->resstate = state; + state->trans6->is_inprogress = true; + state->trans6->ai_sentinel.ai_next = NULL; + } + + state->mctx = mctx; + state->head = head; + ISC_LINK_INIT(state, link); + + *statep = state; + + return (ISC_R_SUCCESS); +} + +static isc_result_t +make_resstates(isc_mem_t *mctx, const char *hostname, gai_statehead_t *head, + irs_resconf_t *resconf) +{ + isc_result_t result; + irs_resconf_searchlist_t *searchlist; + irs_resconf_search_t *searchent; + gai_resstate_t *resstate, *resstate0; + + resstate0 = NULL; + result = make_resstate(mctx, head, hostname, ".", &resstate0); + if (result != ISC_R_SUCCESS) + return (result); + + searchlist = irs_resconf_getsearchlist(resconf); + for (searchent = ISC_LIST_HEAD(*searchlist); searchent != NULL; + searchent = ISC_LIST_NEXT(searchent, link)) { + resstate = NULL; + result = make_resstate(mctx, head, hostname, + (const char *)searchent->domain, + &resstate); + if (result != ISC_R_SUCCESS) + break; + + ISC_LIST_APPEND(head->resstates, resstate, link); + head->activestates++; + } + + /* + * Insert the original hostname either at the head or the tail of the + * state list, depending on the number of labels contained in the + * original name and the 'ndots' configuration parameter. + */ + if (dns_name_countlabels(resstate0->qname) > + irs_resconf_getndots(resconf) + 1) { + ISC_LIST_PREPEND(head->resstates, resstate0, link); + } else + ISC_LIST_APPEND(head->resstates, resstate0, link); + head->activestates++; + + if (result != ISC_R_SUCCESS) { + while ((resstate = ISC_LIST_HEAD(head->resstates)) != NULL) { + ISC_LIST_UNLINK(head->resstates, resstate, link); + if (resstate->trans4 != NULL) { + isc_mem_put(mctx, resstate->trans4, + sizeof(*resstate->trans4)); + } + if (resstate->trans6 != NULL) { + isc_mem_put(mctx, resstate->trans6, + sizeof(*resstate->trans6)); + } + + isc_mem_put(mctx, resstate, sizeof(*resstate)); + } + } + + return (result); +} + +static void +process_answer(isc_task_t *task, isc_event_t *event) { + int error = 0, family; + gai_restrans_t *trans = event->ev_arg; + gai_resstate_t *resstate; + dns_clientresevent_t *rev = (dns_clientresevent_t *)event; + dns_rdatatype_t qtype; + dns_name_t *name; + bool wantcname; + + REQUIRE(trans != NULL); + resstate = trans->resstate; + REQUIRE(resstate != NULL); + REQUIRE(task != NULL); + + if (trans == resstate->trans4) { + family = AF_INET; + qtype = dns_rdatatype_a; + } else { + INSIST(trans == resstate->trans6); + family = AF_INET6; + qtype = dns_rdatatype_aaaa; + } + + INSIST(trans->is_inprogress); + trans->is_inprogress = false; + + switch (rev->result) { + case ISC_R_SUCCESS: + case DNS_R_NCACHENXDOMAIN: /* treat this as a fatal error? */ + case DNS_R_NCACHENXRRSET: + break; + default: + switch (rev->vresult) { + case DNS_R_SIGINVALID: + case DNS_R_SIGEXPIRED: + case DNS_R_SIGFUTURE: + case DNS_R_KEYUNAUTHORIZED: + case DNS_R_MUSTBESECURE: + case DNS_R_COVERINGNSEC: + case DNS_R_NOTAUTHORITATIVE: + case DNS_R_NOVALIDKEY: + case DNS_R_NOVALIDDS: + case DNS_R_NOVALIDSIG: + error = EAI_INSECUREDATA; + break; + default: + error = EAI_FAIL; + } + goto done; + } + + wantcname = (resstate->head->ai_flags & AI_CANONNAME); + + /* Parse the response and construct the addrinfo chain */ + for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; + name = ISC_LIST_NEXT(name, link)) { + isc_result_t result; + dns_rdataset_t *rdataset; + char cname[1024]; + + if (wantcname) { + isc_buffer_t b; + + isc_buffer_init(&b, cname, sizeof(cname)); + result = dns_name_totext(name, true, &b); + if (result != ISC_R_SUCCESS) { + error = EAI_FAIL; + goto done; + } + isc_buffer_putuint8(&b, '\0'); + } + + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (!dns_rdataset_isassociated(rdataset)) + continue; + if (rdataset->type != qtype) + continue; + + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + struct addrinfo *ai; + dns_rdata_t rdata; + dns_rdata_in_a_t rdata_a; + dns_rdata_in_aaaa_t rdata_aaaa; + + ai = ai_alloc(family, + ((family == AF_INET6) ? + sizeof(struct sockaddr_in6) : + sizeof(struct sockaddr_in))); + if (ai == NULL) { + error = EAI_MEMORY; + goto done; + } + ai->ai_socktype = resstate->head->ai_socktype; + ai->ai_next = trans->ai_sentinel.ai_next; + trans->ai_sentinel.ai_next = ai; + + /* + * Set AF-specific parameters + * (IPv4/v6 address/port) + */ + dns_rdata_init(&rdata); + switch (family) { + case AF_INET: + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, + &rdata_a, + NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + SIN(ai->ai_addr)->sin_port = + resstate->head->ai_port; + memmove(&SIN(ai->ai_addr)->sin_addr, + &rdata_a.in_addr, 4); + dns_rdata_freestruct(&rdata_a); + break; + case AF_INET6: + dns_rdataset_current(rdataset, &rdata); + result = dns_rdata_tostruct(&rdata, + &rdata_aaaa, + NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + SIN6(ai->ai_addr)->sin6_port = + resstate->head->ai_port; + memmove(&SIN6(ai->ai_addr)->sin6_addr, + &rdata_aaaa.in6_addr, 16); + dns_rdata_freestruct(&rdata_aaaa); + break; + } + + if (wantcname) { + ai->ai_canonname = strdup(cname); + if (ai->ai_canonname == NULL) { + error = EAI_MEMORY; + goto done; + } + } + } + } + } + + done: + dns_client_freeresanswer(resstate->head->dnsclient, &rev->answerlist); + dns_client_destroyrestrans(&trans->xid); + + isc_event_free(&event); + + /* Make sure that error == 0 iff we have a non-empty list */ + if (error == 0) { + if (trans->ai_sentinel.ai_next == NULL) + error = EAI_NONAME; + } else { + if (trans->ai_sentinel.ai_next != NULL) { + _freeaddrinfo(trans->ai_sentinel.ai_next); + trans->ai_sentinel.ai_next = NULL; + } + } + trans->error = error; + + /* Check whether we are done */ + if ((resstate->trans4 == NULL || !resstate->trans4->is_inprogress) && + (resstate->trans6 == NULL || !resstate->trans6->is_inprogress)) { + /* + * We're done for this state. If there is no other outstanding + * state, we can exit. + */ + resstate->head->activestates--; + if (resstate->head->activestates == 0) { + isc_app_ctxsuspend(resstate->head->actx); + return; + } + + /* + * There are outstanding states, but if we are at the head + * of the state list (i.e., at the highest search priority) + * and have any answer, we can stop now by canceling the + * others. + */ + LOCK(&resstate->head->list_lock); + if (resstate == ISC_LIST_HEAD(resstate->head->resstates)) { + if ((resstate->trans4 != NULL && + resstate->trans4->ai_sentinel.ai_next != NULL) || + (resstate->trans6 != NULL && + resstate->trans6->ai_sentinel.ai_next != NULL)) { + gai_resstate_t *rest; + + for (rest = ISC_LIST_NEXT(resstate, link); + rest != NULL; + rest = ISC_LIST_NEXT(rest, link)) { + if (rest->trans4 != NULL && + rest->trans4->xid != NULL) + dns_client_cancelresolve( + rest->trans4->xid); + if (rest->trans6 != NULL && + rest->trans6->xid != NULL) + dns_client_cancelresolve( + rest->trans6->xid); + } + } else { + /* + * This search fails, so we move to the tail + * of the list so that the next entry will + * have the highest priority. + */ + ISC_LIST_UNLINK(resstate->head->resstates, + resstate, link); + ISC_LIST_APPEND(resstate->head->resstates, + resstate, link); + } + } + UNLOCK(&resstate->head->list_lock); + } +} + +static int +resolve_name(int family, const char *hostname, int flags, + struct addrinfo **aip, int socktype, int port) +{ + isc_result_t result; + irs_context_t *irsctx; + irs_resconf_t *conf; + isc_mem_t *mctx; + isc_appctx_t *actx; + isc_task_t *task; + int terror = 0; + int error = 0; + dns_client_t *client; + gai_resstate_t *resstate; + gai_statehead_t head; + bool all_fail = true; + + /* get IRS context and the associated parameters */ + irsctx = NULL; + result = irs_context_get(&irsctx); + if (result != ISC_R_SUCCESS) + return (EAI_FAIL); + actx = irs_context_getappctx(irsctx); + + mctx = irs_context_getmctx(irsctx); + task = irs_context_gettask(irsctx); + conf = irs_context_getresconf(irsctx); + client = irs_context_getdnsclient(irsctx); + + /* construct resolution states */ + head.activestates = 0; + head.ai_family = family; + head.ai_socktype = socktype; + head.ai_flags = flags; + head.ai_port = port; + head.actx = actx; + head.dnsclient = client; + result = isc_mutex_init(&head.list_lock); + if (result != ISC_R_SUCCESS) { + return (EAI_FAIL); + } + + ISC_LIST_INIT(head.resstates); + result = make_resstates(mctx, hostname, &head, conf); + if (result != ISC_R_SUCCESS) { + DESTROYLOCK(&head.list_lock); + return (EAI_FAIL); + } + + LOCK(&head.list_lock); + for (resstate = ISC_LIST_HEAD(head.resstates); + resstate != NULL; resstate = ISC_LIST_NEXT(resstate, link)) { + if (resstate->trans4 != NULL) { + result = dns_client_startresolve(client, + resstate->qname, + dns_rdataclass_in, + dns_rdatatype_a, + 0, task, + process_answer, + resstate->trans4, + &resstate->trans4->xid); + if (result == ISC_R_SUCCESS) { + resstate->trans4->is_inprogress = true; + all_fail = false; + } else + resstate->trans4->is_inprogress = false; + } + if (resstate->trans6 != NULL) { + result = dns_client_startresolve(client, + resstate->qname, + dns_rdataclass_in, + dns_rdatatype_aaaa, + 0, task, + process_answer, + resstate->trans6, + &resstate->trans6->xid); + if (result == ISC_R_SUCCESS) { + resstate->trans6->is_inprogress = true; + all_fail = false; + } else + resstate->trans6->is_inprogress= false; + } + } + UNLOCK(&head.list_lock); + + if (!all_fail) { + /* Start all the events */ + isc_app_ctxrun(actx); + } else + error = EAI_FAIL; + + /* Cleanup */ + while ((resstate = ISC_LIST_HEAD(head.resstates)) != NULL) { + int terror4 = 0, terror6 = 0; + + ISC_LIST_UNLINK(head.resstates, resstate, link); + + if (*aip == NULL) { + struct addrinfo *sentinel4 = NULL; + struct addrinfo *sentinel6 = NULL; + + if (resstate->trans4 != NULL) { + sentinel4 = + resstate->trans4->ai_sentinel.ai_next; + resstate->trans4->ai_sentinel.ai_next = NULL; + } + if (resstate->trans6 != NULL) { + sentinel6 = + resstate->trans6->ai_sentinel.ai_next; + resstate->trans6->ai_sentinel.ai_next = NULL; + } + *aip = ai_concat(sentinel4, sentinel6); + } + + if (resstate->trans4 != NULL) { + INSIST(resstate->trans4->xid == NULL); + terror4 = resstate->trans4->error; + isc_mem_put(mctx, resstate->trans4, + sizeof(*resstate->trans4)); + } + if (resstate->trans6 != NULL) { + INSIST(resstate->trans6->xid == NULL); + terror6 = resstate->trans6->error; + isc_mem_put(mctx, resstate->trans6, + sizeof(*resstate->trans6)); + } + + /* + * If the entire lookup fails, we need to choose an appropriate + * error code from individual codes. We'll try to provide as + * specific a code as possible. In general, we are going to + * find an error code other than EAI_NONAME (which is too + * generic and may actually not be problematic in some cases). + * EAI_NONAME will be set below if no better code is found. + */ + if (terror == 0 || terror == EAI_NONAME) { + if (terror4 != 0 && terror4 != EAI_NONAME) + terror = terror4; + else if (terror6 != 0 && terror6 != EAI_NONAME) + terror = terror6; + } + + isc_mem_put(mctx, resstate, sizeof(*resstate)); + } + + if (*aip == NULL) { + error = terror; + if (error == 0) + error = EAI_NONAME; + } + +#if 1 /* XXX: enabled for finding leaks. should be cleaned up later. */ + isc_app_ctxfinish(actx); + irs_context_destroy(&irsctx); +#endif + + DESTROYLOCK(&head.list_lock); + return (error); +} + +static char * +irs_strsep(char **stringp, const char *delim) { + char *string = *stringp; + char *s; + const char *d; + char sc, dc; + + if (string == NULL) + return (NULL); + + for (s = string; *s != '\0'; s++) { + sc = *s; + for (d = delim; (dc = *d) != '\0'; d++) + if (sc == dc) { + *s++ = '\0'; + *stringp = s; + return (string); + } + } + *stringp = NULL; + return (string); +} + +static void +set_order(int family, int (**net_order)(const char *, int, struct addrinfo **, + int, int)) +{ + char *order, *tok; + int found; + + if (family) { + switch (family) { + case AF_INET: + *net_order++ = add_ipv4; + break; + case AF_INET6: + *net_order++ = add_ipv6; + break; + } + } else { + order = getenv("NET_ORDER"); + found = 0; + while (order != NULL) { + /* + * We ignore any unknown names. + */ + tok = irs_strsep(&order, ":"); + if (strcasecmp(tok, "inet6") == 0) { + if ((found & FOUND_IPV6) == 0) + *net_order++ = add_ipv6; + found |= FOUND_IPV6; + } else if (strcasecmp(tok, "inet") == 0 || + strcasecmp(tok, "inet4") == 0) { + if ((found & FOUND_IPV4) == 0) + *net_order++ = add_ipv4; + found |= FOUND_IPV4; + } + } + + /* + * Add in anything that we didn't find. + */ + if ((found & FOUND_IPV4) == 0) + *net_order++ = add_ipv4; + if ((found & FOUND_IPV6) == 0) + *net_order++ = add_ipv6; + } + *net_order = NULL; + return; +} + +static char v4_loop[4] = { 127, 0, 0, 1 }; + +static int +add_ipv4(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port) +{ + struct addrinfo *ai; + + UNUSED(hostname); + UNUSED(flags); + + ai = ai_clone(*aip, AF_INET); /* don't use ai_clone() */ + if (ai == NULL) + return (EAI_MEMORY); + + *aip = ai; + ai->ai_socktype = socktype; + SIN(ai->ai_addr)->sin_port = port; + memmove(&SIN(ai->ai_addr)->sin_addr, v4_loop, 4); + + return (0); +} + +static char v6_loop[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; + +static int +add_ipv6(const char *hostname, int flags, struct addrinfo **aip, + int socktype, int port) +{ + struct addrinfo *ai; + + UNUSED(hostname); + UNUSED(flags); + + ai = ai_clone(*aip, AF_INET6); /* don't use ai_clone() */ + if (ai == NULL) + return (EAI_MEMORY); + + *aip = ai; + ai->ai_socktype = socktype; + SIN6(ai->ai_addr)->sin6_port = port; + memmove(&SIN6(ai->ai_addr)->sin6_addr, v6_loop, 16); + + return (0); +} + +/*% Free address info. */ +void +freeaddrinfo(struct addrinfo *ai) { + _freeaddrinfo(ai); +} + +static void +_freeaddrinfo(struct addrinfo *ai) { + struct addrinfo *ai_next; + + while (ai != NULL) { + ai_next = ai->ai_next; + if (ai->ai_addr != NULL) + free(ai->ai_addr); + if (ai->ai_canonname) + free(ai->ai_canonname); + free(ai); + ai = ai_next; + } +} + +#ifdef AF_LOCAL +static int +get_local(const char *name, int socktype, struct addrinfo **res) { + struct addrinfo *ai; + struct sockaddr_un *slocal; + + if (socktype == 0) + return (EAI_SOCKTYPE); + + ai = ai_alloc(AF_LOCAL, sizeof(*slocal)); + if (ai == NULL) + return (EAI_MEMORY); + + slocal = SLOCAL(ai->ai_addr); + strlcpy(slocal->sun_path, name, sizeof(slocal->sun_path)); + + ai->ai_socktype = socktype; + /* + * ai->ai_flags, ai->ai_protocol, ai->ai_canonname, + * and ai->ai_next were initialized to zero. + */ + + *res = ai; + return (0); +} +#endif + +/*! + * Allocate an addrinfo structure, and a sockaddr structure + * of the specificed length. We initialize: + * ai_addrlen + * ai_family + * ai_addr + * ai_addr->sa_family + * ai_addr->sa_len (IRS_PLATFORM_HAVESALEN) + * and everything else is initialized to zero. + */ +static struct addrinfo * +ai_alloc(int family, int addrlen) { + struct addrinfo *ai; + + ai = (struct addrinfo *)calloc(1, sizeof(*ai)); + if (ai == NULL) + return (NULL); + + ai->ai_addr = SA(calloc(1, addrlen)); + if (ai->ai_addr == NULL) { + free(ai); + return (NULL); + } + ai->ai_addrlen = addrlen; + ai->ai_family = family; + ai->ai_addr->sa_family = family; +#ifdef IRS_PLATFORM_HAVESALEN + ai->ai_addr->sa_len = addrlen; +#endif + return (ai); +} + +static struct addrinfo * +ai_clone(struct addrinfo *oai, int family) { + struct addrinfo *ai; + + ai = ai_alloc(family, ((family == AF_INET6) ? + sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))); + + if (ai == NULL) + return (NULL); + if (oai == NULL) + return (ai); + + ai->ai_flags = oai->ai_flags; + ai->ai_socktype = oai->ai_socktype; + ai->ai_protocol = oai->ai_protocol; + ai->ai_canonname = NULL; + ai->ai_next = oai; + return (ai); +} + +static struct addrinfo * +ai_reverse(struct addrinfo *oai) { + struct addrinfo *nai, *tai; + + nai = NULL; + + while (oai != NULL) { + /* + * Grab one off the old list. + */ + tai = oai; + oai = oai->ai_next; + /* + * Put it on the front of the new list. + */ + tai->ai_next = nai; + nai = tai; + } + return (nai); +} + + +static struct addrinfo * +ai_concat(struct addrinfo *ai1, struct addrinfo *ai2) { + struct addrinfo *ai_tmp; + + if (ai1 == NULL) + return (ai2); + else if (ai2 == NULL) + return (ai1); + + for (ai_tmp = ai1; ai_tmp != NULL && ai_tmp->ai_next != NULL; + ai_tmp = ai_tmp->ai_next) + ; + + ai_tmp->ai_next = ai2; + + return (ai1); +} diff --git a/lib/irs/getnameinfo.c b/lib/irs/getnameinfo.c new file mode 100644 index 0000000..5069ba7 --- /dev/null +++ b/lib/irs/getnameinfo.c @@ -0,0 +1,409 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/** + * getnameinfo() returns the hostname for the struct sockaddr sa which is + * salen bytes long. The hostname is of length hostlen and is returned via + * *host. The maximum length of the hostname is 1025 bytes: #NI_MAXHOST. + * + * The name of the service associated with the port number in sa is + * returned in *serv. It is servlen bytes long. The maximum length of the + * service name is #NI_MAXSERV - 32 bytes. + * + * The flags argument sets the following bits: + * + * \li #NI_NOFQDN: + * A fully qualified domain name is not required for local hosts. + * The local part of the fully qualified domain name is returned + * instead. + * + * \li #NI_NUMERICHOST + * Return the address in numeric form, as if calling inet_ntop(), + * instead of a host name. + * + * \li #NI_NAMEREQD + * A name is required. If the hostname cannot be found in the DNS + * and this flag is set, a non-zero error code is returned. If the + * hostname is not found and the flag is not set, the address is + * returned in numeric form. + * + * \li #NI_NUMERICSERV + * The service name is returned as a digit string representing the + * port number. + * + * \li #NI_DGRAM + * Specifies that the service being looked up is a datagram + * service, and causes getservbyport() to be called with a second + * argument of "udp" instead of its default of "tcp". This is + * required for the few ports (512-514) that have different + * services for UDP and TCP. + * + * \section getnameinfo_return Return Values + * + * getnameinfo() returns 0 on success or a non-zero error code if + * an error occurs. + * + * \section getname_see See Also + * + * RFC3493, getservbyport(), + * getnamebyaddr(). inet_ntop(). + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define SUCCESS 0 + +/*% afd structure definition */ +static struct afd { + int a_af; + size_t a_addrlen; + size_t a_socklen; +} afdl [] = { + /*! + * First entry is linked last... + */ + { AF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in) }, + { AF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6) }, + {0, 0, 0}, +}; + +/*! + * The test against 0 is there to keep the Solaris compiler + * from complaining about "end-of-loop code not reached". + */ +#define ERR(code) \ + do { result = (code); \ + if (result != 0) goto cleanup; \ + } while (0) + +int +getnameinfo(const struct sockaddr *sa, IRS_GETNAMEINFO_SOCKLEN_T salen, + char *host, IRS_GETNAMEINFO_BUFLEN_T hostlen, + char *serv, IRS_GETNAMEINFO_BUFLEN_T servlen, + IRS_GETNAMEINFO_FLAGS_T flags) +{ + struct afd *afd = NULL; + struct servent *sp; + unsigned short port = 0; +#ifdef IRS_PLATFORM_HAVESALEN + size_t len; +#endif + int family, i; + const void *addr = NULL; + char *p; +#if 0 + unsigned long v4a; + unsigned char pfx; +#endif + char numserv[sizeof("65000")]; + char numaddr[sizeof("abcd:abcd:abcd:abcd:abcd:abcd:255.255.255.255") + + 1 + sizeof("4294967295")]; + const char *proto; + int result = SUCCESS; + + if (sa == NULL) + ERR(EAI_FAIL); + +#ifdef IRS_PLATFORM_HAVESALEN + len = sa->sa_len; + if (len != salen) + ERR(EAI_FAIL); +#endif + + family = sa->sa_family; + for (i = 0; afdl[i].a_af; i++) + if (afdl[i].a_af == family) { + afd = &afdl[i]; + goto found; + } + ERR(EAI_FAMILY); + + found: + if (salen != afd->a_socklen) + ERR(EAI_FAIL); + + switch (family) { + case AF_INET: + port = ((const struct sockaddr_in *)sa)->sin_port; + addr = &((const struct sockaddr_in *)sa)->sin_addr.s_addr; + break; + + case AF_INET6: + port = ((const struct sockaddr_in6 *)sa)->sin6_port; + addr = ((const struct sockaddr_in6 *)sa)->sin6_addr.s6_addr; + break; + + default: + INSIST(0); + } + proto = (flags & NI_DGRAM) ? "udp" : "tcp"; + + if (serv == NULL || servlen == 0U) { + /* + * Caller does not want service. + */ + } else if ((flags & NI_NUMERICSERV) != 0 || + (sp = getservbyport(port, proto)) == NULL) { + snprintf(numserv, sizeof(numserv), "%d", ntohs(port)); + if ((strlen(numserv) + 1) > servlen) + ERR(EAI_OVERFLOW); + strlcpy(serv, numserv, servlen); + } else { + if ((strlen(sp->s_name) + 1) > servlen) + ERR(EAI_OVERFLOW); + strlcpy(serv, sp->s_name, servlen); + } + +#if 0 + switch (sa->sa_family) { + case AF_INET: + v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr; + if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) + flags |= NI_NUMERICHOST; + v4a >>= IN_CLASSA_NSHIFT; + if (v4a == 0 || v4a == IN_LOOPBACKNET) + flags |= NI_NUMERICHOST; + break; + + case AF_INET6: + pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0]; + if (pfx == 0 || pfx == 0xfe || pfx == 0xff) + flags |= NI_NUMERICHOST; + break; + } +#endif + + if (host == NULL || hostlen == 0U) { + /* + * do nothing in this case. + * in case you are wondering if "&&" is more correct than + * "||" here: RFC3493 says that host == NULL or hostlen == 0 + * means that the caller does not want the result. + */ + } else if ((flags & NI_NUMERICHOST) != 0) { + if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) + == NULL) + ERR(EAI_SYSTEM); +#if defined(IRS_HAVE_SIN6_SCOPE_ID) + if (afd->a_af == AF_INET6 && + ((const struct sockaddr_in6 *)sa)->sin6_scope_id) { + char *p = numaddr + strlen(numaddr); + const char *stringscope = NULL; +#ifdef VENDOR_SPECIFIC + /* + * Vendors may want to add support for + * non-numeric scope identifier. + */ + stringscope = foo; +#endif + if (stringscope == NULL) { + snprintf(p, sizeof(numaddr) - (p - numaddr), + "%%%u", + ((const struct sockaddr_in6 *)sa)->sin6_scope_id); + } else { + snprintf(p, sizeof(numaddr) - (p - numaddr), + "%%%s", stringscope); + } + } +#endif + if (strlen(numaddr) + 1 > hostlen) + ERR(EAI_OVERFLOW); + strlcpy(host, numaddr, hostlen); + } else { + isc_netaddr_t netaddr; + dns_fixedname_t ptrfname; + dns_name_t *ptrname; + irs_context_t *irsctx = NULL; + dns_client_t *client; + bool found = false; + dns_namelist_t answerlist; + dns_rdataset_t *rdataset; + isc_region_t hostregion; + char hoststr[1024]; /* is this enough? */ + isc_result_t iresult; + + /* Get IRS context and the associated DNS client object */ + iresult = irs_context_get(&irsctx); + if (iresult != ISC_R_SUCCESS) + ERR(EAI_FAIL); + client = irs_context_getdnsclient(irsctx); + + /* Make query name */ + isc_netaddr_fromsockaddr(&netaddr, (const isc_sockaddr_t *)sa); + ptrname = dns_fixedname_initname(&ptrfname); + iresult = dns_byaddr_createptrname2(&netaddr, 0, ptrname); + if (iresult != ISC_R_SUCCESS) + ERR(EAI_FAIL); + + /* Get the PTR RRset */ + ISC_LIST_INIT(answerlist); + iresult = dns_client_resolve(client, ptrname, + dns_rdataclass_in, + dns_rdatatype_ptr, + DNS_CLIENTRESOPT_ALLOWRUN, + &answerlist); + switch (iresult) { + case ISC_R_SUCCESS: + /* + * a 'non-existent' error is not necessarily fatal for + * getnameinfo(). + */ + case DNS_R_NCACHENXDOMAIN: + case DNS_R_NCACHENXRRSET: + break; + case DNS_R_SIGINVALID: + case DNS_R_SIGEXPIRED: + case DNS_R_SIGFUTURE: + case DNS_R_KEYUNAUTHORIZED: + case DNS_R_MUSTBESECURE: + case DNS_R_COVERINGNSEC: + case DNS_R_NOTAUTHORITATIVE: + case DNS_R_NOVALIDKEY: + case DNS_R_NOVALIDDS: + case DNS_R_NOVALIDSIG: + /* + * Don't use ERR as GCC 7 wants to raise a + * warning with ERR about possible falling + * through which is impossible. + */ + result = EAI_INSECUREDATA; + goto cleanup; + default: + ERR(EAI_FAIL); + } + + /* Parse the answer for the hostname */ + for (ptrname = ISC_LIST_HEAD(answerlist); ptrname != NULL; + ptrname = ISC_LIST_NEXT(ptrname, link)) { + for (rdataset = ISC_LIST_HEAD(ptrname->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + if (!dns_rdataset_isassociated(rdataset)) + continue; + if (rdataset->type != dns_rdatatype_ptr) + continue; + + for (iresult = dns_rdataset_first(rdataset); + iresult == ISC_R_SUCCESS; + iresult = dns_rdataset_next(rdataset)) { + dns_rdata_t rdata; + dns_rdata_ptr_t rdata_ptr; + isc_buffer_t b; + + dns_rdata_init(&rdata); + dns_rdataset_current(rdataset, &rdata); + dns_rdata_tostruct(&rdata, &rdata_ptr, + NULL); + + isc_buffer_init(&b, hoststr, + sizeof(hoststr)); + iresult = + dns_name_totext(&rdata_ptr.ptr, + true, &b); + dns_rdata_freestruct(&rdata_ptr); + if (iresult == ISC_R_SUCCESS) { + /* + * We ignore the rest of the + * answer. After all, + * getnameinfo() can return + * at most one hostname. + */ + found = true; + isc_buffer_usedregion( + &b, &hostregion); + goto ptrfound; + } + + } + } + } + ptrfound: + dns_client_freeresanswer(client, &answerlist); + if (found) { + if ((flags & NI_NOFQDN) != 0) { + p = strchr(hoststr, '.'); + if (p) + *p = '\0'; + } + if (hostregion.length + 1 > hostlen) + ERR(EAI_OVERFLOW); + snprintf(host, hostlen, "%.*s", + (int)hostregion.length, + (char *)hostregion.base); + } else { + if ((flags & NI_NAMEREQD) != 0) + ERR(EAI_NONAME); + if (inet_ntop(afd->a_af, addr, numaddr, + sizeof(numaddr)) == NULL) + ERR(EAI_SYSTEM); + if ((strlen(numaddr) + 1) > hostlen) + ERR(EAI_OVERFLOW); + strlcpy(host, numaddr, hostlen); + } + } + result = SUCCESS; + + cleanup: + return (result); +} diff --git a/lib/irs/include/Makefile.in b/lib/irs/include/Makefile.in new file mode 100644 index 0000000..3601331 --- /dev/null +++ b/lib/irs/include/Makefile.in @@ -0,0 +1,17 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://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 = irs +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/irs/include/irs/Makefile.in b/lib/irs/include/irs/Makefile.in new file mode 100644 index 0000000..b0c5e14 --- /dev/null +++ b/lib/irs/include/irs/Makefile.in @@ -0,0 +1,44 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://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@ + +# +# Only list headers that are to be installed and are not +# machine generated. The latter are handled specially in the +# install target below. +# +HEADERS = context.h dnsconf.h resconf.h types.h version.h + +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/irs + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/irs || exit 1; \ + done + ${INSTALL_DATA} netdb.h ${DESTDIR}${includedir}/irs + ${INSTALL_DATA} platform.h ${DESTDIR}${includedir}/irs + +uninstall:: + rm -f ${DESTDIR}${includedir}/irs/platform.h + rm -f ${DESTDIR}${includedir}/irs/netdb.h + for i in ${HEADERS}; do \ + rm -f ${DESTDIR}${includedir}/irs/$$i || exit 1; \ + done + +distclean:: + rm -f netdb.h platform.h diff --git a/lib/irs/include/irs/context.h b/lib/irs/include/irs/context.h new file mode 100644 index 0000000..94e55c6 --- /dev/null +++ b/lib/irs/include/irs/context.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef IRS_CONTEXT_H +#define IRS_CONTEXT_H 1 + +/*! \file + * + * \brief + * The IRS context module provides an abstract interface to the DNS library + * with an application. An IRS context object initializes and holds various + * resources used in the DNS library. + */ + +#include +#include + +ISC_LANG_BEGINDECLS + +isc_result_t +irs_context_create(irs_context_t **contextp); +/*%< + * Create an IRS context. It internally initializes the ISC and DNS libraries + * (if not yet), creates a DNS client object and initializes the client using + * the configuration files parsed via the 'resconf' and 'dnsconf' IRS modules. + * Some of the internally initialized objects can be used by the application + * via irs_context_getxxx() functions (see below). + * + * Requires: + * + *\li contextp != NULL && *contextp == NULL. + */ + +isc_result_t +irs_context_get(irs_context_t **contextp); +/*%< + * Return an IRS context for the calling thread. If no IRS context is + * associated to the thread, this function creates a new one by calling + * irs_context_create(), and associates it with the thread as a thread specific + * data value. This function is provided for standard libraries that are + * expected to be thread-safe but do not accept an appropriate IRS context + * as a library parameter, e.g., getaddrinfo(). + * + * Requires: + * + *\li contextp != NULL && *contextp == NULL. + */ + +void +irs_context_destroy(irs_context_t **contextp); +/*%< + * Destroy an IRS context. + * + * Requires: + * + *\li '*contextp' is a valid IRS context. + * + * Ensures: + *\li '*contextp' == NULL. + */ + +isc_mem_t * +irs_context_getmctx(irs_context_t *context); +/*%< + * Return the memory context held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +isc_appctx_t * +irs_context_getappctx(irs_context_t *context); +/*%< + * Return the application context held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +isc_taskmgr_t * +irs_context_gettaskmgr(irs_context_t *context); +/*%< + * Return the task manager held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +isc_timermgr_t * +irs_context_gettimermgr(irs_context_t *context); +/*%< + * Return the timer manager held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +isc_task_t * +irs_context_gettask(irs_context_t *context); +/*%< + * Return the task object held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +dns_client_t * +irs_context_getdnsclient(irs_context_t *context); +/*%< + * Return the DNS client object held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +irs_resconf_t * +irs_context_getresconf(irs_context_t *context); +/*%< + * Return the resolver configuration object held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +irs_dnsconf_t * +irs_context_getdnsconf(irs_context_t *context); +/*%< + * Return the advanced DNS configuration object held in the context. + * + * Requires: + * + *\li 'context' is a valid IRS context. + */ + +ISC_LANG_ENDDECLS + +#endif /* IRS_CONTEXT_H */ diff --git a/lib/irs/include/irs/dnsconf.h b/lib/irs/include/irs/dnsconf.h new file mode 100644 index 0000000..89898ba --- /dev/null +++ b/lib/irs/include/irs/dnsconf.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef IRS_DNSCONF_H +#define IRS_DNSCONF_H 1 + +/*! \file + * + * \brief + * The IRS dnsconf module parses an "advanced" configuration file related to + * the DNS library, such as trusted keys for DNSSEC validation, and creates + * the corresponding configuration objects for the DNS library modules. + * + * Notes: + * This module is very experimental and the configuration syntax or library + * interfaces may change in future versions. Currently, only the + * 'trusted-keys' statement is supported, whose syntax is the same as the + * same name of statement for named.conf. + */ + +#include + +/*% + * A compound structure storing DNS key information mainly for DNSSEC + * validation. A dns_key_t object will be created using the 'keyname' and + * 'keydatabuf' members with the dst_key_fromdns() function. + */ +typedef struct irs_dnsconf_dnskey { + dns_name_t *keyname; + isc_buffer_t *keydatabuf; + ISC_LINK(struct irs_dnsconf_dnskey) link; +} irs_dnsconf_dnskey_t; + +typedef ISC_LIST(irs_dnsconf_dnskey_t) irs_dnsconf_dnskeylist_t; + +ISC_LANG_BEGINDECLS + +isc_result_t +irs_dnsconf_load(isc_mem_t *mctx, const char *filename, irs_dnsconf_t **confp); +/*%< + * Load the "advanced" DNS configuration file 'filename' in the "dns.conf" + * format, and create a new irs_dnsconf_t object from the configuration. + * + * Requires: + * + *\li 'mctx' is a valid memory context. + * + *\li 'filename' != NULL + * + *\li 'confp' != NULL && '*confp' == NULL + */ + +void +irs_dnsconf_destroy(irs_dnsconf_t **confp); +/*%< + * Destroy the dnsconf object. + * + * Requires: + * + *\li '*confp' is a valid dnsconf object. + * + * Ensures: + * + *\li *confp == NULL + */ + +irs_dnsconf_dnskeylist_t * +irs_dnsconf_gettrustedkeys(irs_dnsconf_t *conf); +/*%< + * Return a list of key information stored in 'conf'. + * + * Requires: + * + *\li 'conf' is a valid dnsconf object. + */ + +ISC_LANG_ENDDECLS + +#endif /* IRS_DNSCONF_H */ diff --git a/lib/irs/include/irs/netdb.h.in b/lib/irs/include/irs/netdb.h.in new file mode 100644 index 0000000..93fe47d --- /dev/null +++ b/lib/irs/include/irs/netdb.h.in @@ -0,0 +1,160 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#ifndef IRS_NETDB_H +#define IRS_NETDB_H 1 + +#include /* Required on FreeBSD (and others?) for size_t. */ +#include /* Contractual provision. */ + +/* + * Define if does not declare struct addrinfo. + */ +@ISC_IRS_NEEDADDRINFO@ + +#ifdef ISC_IRS_NEEDADDRINFO +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* Length of ai_addr */ + char *ai_canonname; /* Canonical name for hostname */ + struct sockaddr *ai_addr; /* Binary address */ + struct addrinfo *ai_next; /* Next structure in linked list */ +}; +#endif + +/* + * Undefine all #defines we are interested in as may or may not have + * defined them. + */ + +/* + * Error return codes from gethostbyname() and gethostbyaddr() + * (left in extern int h_errno). + */ + +#undef NETDB_INTERNAL +#undef NETDB_SUCCESS +#undef HOST_NOT_FOUND +#undef TRY_AGAIN +#undef NO_RECOVERY +#undef NO_DATA +#undef NO_ADDRESS + +#define NETDB_INTERNAL -1 /* see errno */ +#define NETDB_SUCCESS 0 /* no problem */ +#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ +#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */ +#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ +#define NO_DATA 4 /* Valid name, no data record of requested type */ +#define NO_ADDRESS NO_DATA /* no address, look for MX record */ + +/* + * Error return codes from getaddrinfo(). EAI_INSECUREDATA is our own extension + * and it's very unlikely to be already defined, but undef it just in case; it + * at least doesn't do any harm. + */ + +#undef EAI_ADDRFAMILY +#undef EAI_AGAIN +#undef EAI_BADFLAGS +#undef EAI_FAIL +#undef EAI_FAMILY +#undef EAI_MEMORY +#undef EAI_NODATA +#undef EAI_NONAME +#undef EAI_SERVICE +#undef EAI_SOCKTYPE +#undef EAI_SYSTEM +#undef EAI_BADHINTS +#undef EAI_PROTOCOL +#undef EAI_OVERFLOW +#undef EAI_INSECUREDATA +#undef EAI_MAX + +#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */ +#define EAI_AGAIN 2 /* temporary failure in name resolution */ +#define EAI_BADFLAGS 3 /* invalid value for ai_flags */ +#define EAI_FAIL 4 /* non-recoverable failure in name resolution */ +#define EAI_FAMILY 5 /* ai_family not supported */ +#define EAI_MEMORY 6 /* memory allocation failure */ +#define EAI_NODATA 7 /* no address associated with hostname */ +#define EAI_NONAME 8 /* hostname nor servname provided, or not known */ +#define EAI_SERVICE 9 /* servname not supported for ai_socktype */ +#define EAI_SOCKTYPE 10 /* ai_socktype not supported */ +#define EAI_SYSTEM 11 /* system error returned in errno */ +#define EAI_BADHINTS 12 +#define EAI_PROTOCOL 13 +#define EAI_OVERFLOW 14 +#define EAI_INSECUREDATA 15 +#define EAI_MAX 16 + +/* + * Flag values for getaddrinfo() + */ +#undef AI_PASSIVE +#undef AI_CANONNAME +#undef AI_NUMERICHOST + +#define AI_PASSIVE 0x00000001 +#define AI_CANONNAME 0x00000002 +#define AI_NUMERICHOST 0x00000004 + +/* + * Flag values for getipnodebyname() + */ +#undef AI_V4MAPPED +#undef AI_ALL +#undef AI_ADDRCONFIG +#undef AI_DEFAULT + +#define AI_V4MAPPED 0x00000008 +#define AI_ALL 0x00000010 +#define AI_ADDRCONFIG 0x00000020 +#define AI_DEFAULT (AI_V4MAPPED|AI_ADDRCONFIG) + +/* + * Constants for lwres_getnameinfo() + */ +#undef NI_MAXHOST +#undef NI_MAXSERV + +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +/* + * Flag values for lwres_getnameinfo() + */ +#undef NI_NOFQDN +#undef NI_NUMERICHOST +#undef NI_NAMEREQD +#undef NI_NUMERICSERV +#undef NI_DGRAM +#undef NI_NUMERICSCOPE + +#define NI_NOFQDN 0x00000001 +#define NI_NUMERICHOST 0x00000002 +#define NI_NAMEREQD 0x00000004 +#define NI_NUMERICSERV 0x00000008 +#define NI_DGRAM 0x00000010 + +/* + * Tell Emacs to use C mode on this file. + * Local variables: + * mode: c + * End: + */ + +#endif /* IRS_NETDB_H */ diff --git a/lib/irs/include/irs/platform.h.in b/lib/irs/include/irs/platform.h.in new file mode 100644 index 0000000..78c91ce --- /dev/null +++ b/lib/irs/include/irs/platform.h.in @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#ifndef IRS_PLATFORM_H +#define IRS_PLATFORM_H 1 + +/***** + ***** Platform-dependent defines. + *****/ + +#ifndef IRS_PLATFORM_USEDECLSPEC +#define LIBIRS_EXTERNAL_DATA +#else +#ifdef LIBIRS_EXPORTS +#define LIBIRS_EXTERNAL_DATA __declspec(dllexport) +#else +#define LIBIRS_EXTERNAL_DATA __declspec(dllimport) +#endif +#endif + +/* + * Tell Emacs to use C mode on this file. + * Local Variables: + * mode: c + * End: + */ + +#endif /* IRS_PLATFORM_H */ diff --git a/lib/irs/include/irs/resconf.h b/lib/irs/include/irs/resconf.h new file mode 100644 index 0000000..6c0a8cc --- /dev/null +++ b/lib/irs/include/irs/resconf.h @@ -0,0 +1,117 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef IRS_RESCONF_H +#define IRS_RESCONF_H 1 + +/*! \file + * + * \brief + * The IRS resconf module parses the legacy "/etc/resolv.conf" file and + * creates the corresponding configuration objects for the DNS library + * modules. + */ + +#include + +/*% + * A DNS search list specified in the 'domain' or 'search' statements + * in the "resolv.conf" file. + */ +typedef struct irs_resconf_search { + char *domain; + ISC_LINK(struct irs_resconf_search) link; +} irs_resconf_search_t; + +typedef ISC_LIST(irs_resconf_search_t) irs_resconf_searchlist_t; + +ISC_LANG_BEGINDECLS + +isc_result_t +irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp); +/*%< + * Load the resolver configuration file 'filename' in the "resolv.conf" format, + * and create a new irs_resconf_t object from the configuration. If the file + * is not found ISC_R_FILENOTFOUND is returned with the structure initialized + * as if file contained only: + * + * nameserver ::1 + * nameserver 127.0.0.1 + * + * Notes: + * + *\li Currently, only the following options are supported: + * nameserver, domain, search, sortlist, ndots, and options. + * In addition, 'sortlist' is not actually effective; it's parsed, but + * the application cannot use the configuration. + * + * Returns: + * \li ISC_R_SUCCESS on success + * \li ISC_R_FILENOTFOUND if the file was not found. *confp will be valid. + * \li other on error. + * + * Requires: + * + *\li 'mctx' is a valid memory context. + * + *\li 'filename' != NULL + * + *\li 'confp' != NULL && '*confp' == NULL + */ + +void +irs_resconf_destroy(irs_resconf_t **confp); +/*%< + * Destroy the resconf object. + * + * Requires: + * + *\li '*confp' is a valid resconf object. + * + * Ensures: + * + *\li *confp == NULL + */ + +isc_sockaddrlist_t * +irs_resconf_getnameservers(irs_resconf_t *conf); +/*%< + * Return a list of name server addresses stored in 'conf'. + * + * Requires: + * + *\li 'conf' is a valid resconf object. + */ + +irs_resconf_searchlist_t * +irs_resconf_getsearchlist(irs_resconf_t *conf); +/*%< + * Return the search list stored in 'conf'. + * + * Requires: + * + *\li 'conf' is a valid resconf object. + */ + +unsigned int +irs_resconf_getndots(irs_resconf_t *conf); +/*%< + * Return the 'ndots' value stored in 'conf'. + * + * Requires: + * + *\li 'conf' is a valid resconf object. + */ + +ISC_LANG_ENDDECLS + +#endif /* IRS_RESCONF_H */ diff --git a/lib/irs/include/irs/types.h b/lib/irs/include/irs/types.h new file mode 100644 index 0000000..1251e68 --- /dev/null +++ b/lib/irs/include/irs/types.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#ifndef IRS_TYPES_H +#define IRS_TYPES_H 1 + +/* Core Types. Alphabetized by defined type. */ + +/*%< per-thread IRS context */ +typedef struct irs_context irs_context_t; +/*%< resolv.conf configuration information */ +typedef struct irs_resconf irs_resconf_t; +/*%< advanced DNS-related configuration information */ +typedef struct irs_dnsconf irs_dnsconf_t; + +#endif /* IRS_TYPES_H */ diff --git a/lib/irs/include/irs/version.h b/lib/irs/include/irs/version.h new file mode 100644 index 0000000..a049374 --- /dev/null +++ b/lib/irs/include/irs/version.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include + +LIBIRS_EXTERNAL_DATA extern const char irs_version[]; + +LIBIRS_EXTERNAL_DATA extern const unsigned int irs_libinterface; +LIBIRS_EXTERNAL_DATA extern const unsigned int irs_librevision; +LIBIRS_EXTERNAL_DATA extern const unsigned int irs_libage; diff --git a/lib/irs/resconf.c b/lib/irs/resconf.c new file mode 100644 index 0000000..7288c72 --- /dev/null +++ b/lib/irs/resconf.c @@ -0,0 +1,654 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file resconf.c */ + +/** + * Module for parsing resolv.conf files (largely derived from lwconfig.c). + * + * irs_resconf_load() opens the file filename and parses it to initialize + * the configuration structure. + * + * \section lwconfig_return Return Values + * + * irs_resconf_load() returns #IRS_R_SUCCESS if it successfully read and + * parsed filename. It returns a non-0 error code if filename could not be + * opened or contained incorrect resolver statements. + * + * \section lwconfig_see See Also + * + * stdio(3), \link resolver resolver \endlink + * + * \section files Files + * + * /etc/resolv.conf + */ + +#include + +#ifndef WIN32 +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define IRS_RESCONF_MAGIC ISC_MAGIC('R', 'E', 'S', 'c') +#define IRS_RESCONF_VALID(c) ISC_MAGIC_VALID(c, IRS_RESCONF_MAGIC) + +/*! + * protocol constants + */ + +#if ! defined(NS_INADDRSZ) +#define NS_INADDRSZ 4 +#endif + +#if ! defined(NS_IN6ADDRSZ) +#define NS_IN6ADDRSZ 16 +#endif + +/*! + * resolv.conf parameters + */ + +#define RESCONFMAXNAMESERVERS 3U /*%< max 3 "nameserver" entries */ +#define RESCONFMAXSEARCH 8U /*%< max 8 domains in "search" entry */ +#define RESCONFMAXLINELEN 256U /*%< max size of a line */ +#define RESCONFMAXSORTLIST 10U /*%< max 10 */ + +/*! + * configuration data structure + */ + +struct irs_resconf { + /* + * The configuration data is a thread-specific object, and does not + * need to be locked. + */ + unsigned int magic; + isc_mem_t *mctx; + + isc_sockaddrlist_t nameservers; + unsigned int numns; /*%< number of configured servers */ + + char *domainname; + char *search[RESCONFMAXSEARCH]; + uint8_t searchnxt; /*%< index for next free slot */ + + irs_resconf_searchlist_t searchlist; + + struct { + isc_netaddr_t addr; + /*% mask has a non-zero 'family' if set */ + isc_netaddr_t mask; + } sortlist[RESCONFMAXSORTLIST]; + uint8_t sortlistnxt; + + /*%< non-zero if 'options debug' set */ + uint8_t resdebug; + /*%< set to n in 'options ndots:n' */ + uint8_t ndots; +}; + +static isc_result_t +resconf_parsenameserver(irs_resconf_t *conf, FILE *fp); +static isc_result_t +resconf_parsedomain(irs_resconf_t *conf, FILE *fp); +static isc_result_t +resconf_parsesearch(irs_resconf_t *conf, FILE *fp); +static isc_result_t +resconf_parsesortlist(irs_resconf_t *conf, FILE *fp); +static isc_result_t +resconf_parseoption(irs_resconf_t *ctx, FILE *fp); + +/*! + * Eat characters from FP until EOL or EOF. Returns EOF or '\n' + */ +static int +eatline(FILE *fp) { + int ch; + + ch = fgetc(fp); + while (ch != '\n' && ch != EOF) + ch = fgetc(fp); + + return (ch); +} + +/*! + * Eats white space up to next newline or non-whitespace character (of + * EOF). Returns the last character read. Comments are considered white + * space. + */ +static int +eatwhite(FILE *fp) { + int ch; + + ch = fgetc(fp); + while (ch != '\n' && ch != EOF && isspace((unsigned char)ch)) + ch = fgetc(fp); + + if (ch == ';' || ch == '#') + ch = eatline(fp); + + return (ch); +} + +/*! + * Skip over any leading whitespace and then read in the next sequence of + * non-whitespace characters. In this context newline is not considered + * whitespace. Returns EOF on end-of-file, or the character + * that caused the reading to stop. + */ +static int +getword(FILE *fp, char *buffer, size_t size) { + int ch; + char *p; + + REQUIRE(buffer != NULL); + REQUIRE(size > 0U); + + p = buffer; + *p = '\0'; + + ch = eatwhite(fp); + + if (ch == EOF) + return (EOF); + + do { + *p = '\0'; + + if (ch == EOF || isspace((unsigned char)ch)) + break; + else if ((size_t) (p - buffer) == size - 1) + return (EOF); /* Not enough space. */ + + *p++ = (char)ch; + ch = fgetc(fp); + } while (1); + + return (ch); +} + +static isc_result_t +add_server(isc_mem_t *mctx, const char *address_str, + isc_sockaddrlist_t *nameservers) +{ + int error; + isc_sockaddr_t *address = NULL; + struct addrinfo hints, *res; + isc_result_t result = ISC_R_SUCCESS; + + res = NULL; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_NUMERICHOST; + error = getaddrinfo(address_str, "53", &hints, &res); + if (error != 0) + return (ISC_R_BADADDRESSFORM); + + /* XXX: special case: treat all-0 IPv4 address as loopback */ + if (res->ai_family == AF_INET) { + struct in_addr *v4; + unsigned char zeroaddress[] = {0, 0, 0, 0}; + unsigned char loopaddress[] = {127, 0, 0, 1}; + + v4 = &((struct sockaddr_in *)res->ai_addr)->sin_addr; + if (memcmp(v4, zeroaddress, 4) == 0) + memmove(v4, loopaddress, 4); + } + + address = isc_mem_get(mctx, sizeof(*address)); + if (address == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + if (res->ai_addrlen > sizeof(address->type)) { + isc_mem_put(mctx, address, sizeof(*address)); + result = ISC_R_RANGE; + goto cleanup; + } + address->length = (unsigned int)res->ai_addrlen; + memmove(&address->type.ss, res->ai_addr, res->ai_addrlen); + ISC_LINK_INIT(address, link); + ISC_LIST_APPEND(*nameservers, address, link); + + cleanup: + freeaddrinfo(res); + + return (result); +} + +static isc_result_t +create_addr(const char *buffer, isc_netaddr_t *addr, int convert_zero) { + struct in_addr v4; + struct in6_addr v6; + + if (inet_aton(buffer, &v4) == 1) { + if (convert_zero) { + unsigned char zeroaddress[] = {0, 0, 0, 0}; + unsigned char loopaddress[] = {127, 0, 0, 1}; + if (memcmp(&v4, zeroaddress, 4) == 0) + memmove(&v4, loopaddress, 4); + } + addr->family = AF_INET; + memmove(&addr->type.in, &v4, NS_INADDRSZ); + addr->zone = 0; + } else if (inet_pton(AF_INET6, buffer, &v6) == 1) { + addr->family = AF_INET6; + memmove(&addr->type.in6, &v6, NS_IN6ADDRSZ); + addr->zone = 0; + } else + return (ISC_R_BADADDRESSFORM); /* Unrecognised format. */ + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parsenameserver(irs_resconf_t *conf, FILE *fp) { + char word[RESCONFMAXLINELEN]; + int cp; + isc_result_t result; + + if (conf->numns == RESCONFMAXNAMESERVERS) + return (ISC_R_SUCCESS); + + cp = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Nothing on line. */ + else if (cp == ' ' || cp == '\t') + cp = eatwhite(fp); + + if (cp != EOF && cp != '\n') + return (ISC_R_UNEXPECTEDTOKEN); /* Extra junk on line. */ + + result = add_server(conf->mctx, word, &conf->nameservers); + if (result != ISC_R_SUCCESS) + return (result); + conf->numns++; + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parsedomain(irs_resconf_t *conf, FILE *fp) { + char word[RESCONFMAXLINELEN]; + int res; + unsigned int i; + + res = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Nothing else on line. */ + else if (res == ' ' || res == '\t') + res = eatwhite(fp); + + if (res != EOF && res != '\n') + return (ISC_R_UNEXPECTEDTOKEN); /* Extra junk on line. */ + + if (conf->domainname != NULL) + isc_mem_free(conf->mctx, conf->domainname); + + /* + * Search and domain are mutually exclusive. + */ + for (i = 0; i < RESCONFMAXSEARCH; i++) { + if (conf->search[i] != NULL) { + isc_mem_free(conf->mctx, conf->search[i]); + conf->search[i] = NULL; + } + } + conf->searchnxt = 0; + + conf->domainname = isc_mem_strdup(conf->mctx, word); + if (conf->domainname == NULL) + return (ISC_R_NOMEMORY); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parsesearch(irs_resconf_t *conf, FILE *fp) { + int delim; + unsigned int idx; + char word[RESCONFMAXLINELEN]; + + if (conf->domainname != NULL) { + /* + * Search and domain are mutually exclusive. + */ + isc_mem_free(conf->mctx, conf->domainname); + conf->domainname = NULL; + } + + /* + * Remove any previous search definitions. + */ + for (idx = 0; idx < RESCONFMAXSEARCH; idx++) { + if (conf->search[idx] != NULL) { + isc_mem_free(conf->mctx, conf->search[idx]); + conf->search[idx] = NULL; + } + } + conf->searchnxt = 0; + + delim = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Nothing else on line. */ + + idx = 0; + while (strlen(word) > 0U) { + if (conf->searchnxt == RESCONFMAXSEARCH) + goto ignore; /* Too many domains. */ + + INSIST(idx < sizeof(conf->search)/sizeof(conf->search[0])); + conf->search[idx] = isc_mem_strdup(conf->mctx, word); + if (conf->search[idx] == NULL) + return (ISC_R_NOMEMORY); + idx++; + conf->searchnxt++; + + ignore: + if (delim == EOF || delim == '\n') + break; + else + delim = getword(fp, word, sizeof(word)); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parsesortlist(irs_resconf_t *conf, FILE *fp) { + int delim, res; + unsigned int idx; + char word[RESCONFMAXLINELEN]; + char *p; + + delim = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Empty line after keyword. */ + + while (strlen(word) > 0U) { + if (conf->sortlistnxt == RESCONFMAXSORTLIST) + return (ISC_R_QUOTA); /* Too many values. */ + + p = strchr(word, '/'); + if (p != NULL) + *p++ = '\0'; + + idx = conf->sortlistnxt; + INSIST(idx < sizeof(conf->sortlist)/sizeof(conf->sortlist[0])); + res = create_addr(word, &conf->sortlist[idx].addr, 1); + if (res != ISC_R_SUCCESS) + return (res); + + if (p != NULL) { + res = create_addr(p, &conf->sortlist[idx].mask, 0); + if (res != ISC_R_SUCCESS) + return (res); + } else { + /* + * Make up a mask. (XXX: is this correct?) + */ + conf->sortlist[idx].mask = conf->sortlist[idx].addr; + memset(&conf->sortlist[idx].mask.type, 0xff, + sizeof(conf->sortlist[idx].mask.type)); + } + + conf->sortlistnxt++; + + if (delim == EOF || delim == '\n') + break; + else + delim = getword(fp, word, sizeof(word)); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +resconf_parseoption(irs_resconf_t *conf, FILE *fp) { + int delim; + long ndots; + char *p; + char word[RESCONFMAXLINELEN]; + + delim = getword(fp, word, sizeof(word)); + if (strlen(word) == 0U) + return (ISC_R_UNEXPECTEDEND); /* Empty line after keyword. */ + + while (strlen(word) > 0U) { + if (strcmp("debug", word) == 0) { + conf->resdebug = 1; + } else if (strncmp("ndots:", word, 6) == 0) { + ndots = strtol(word + 6, &p, 10); + if (*p != '\0') /* Bad string. */ + return (ISC_R_UNEXPECTEDTOKEN); + if (ndots < 0 || ndots > 0xff) /* Out of range. */ + return (ISC_R_RANGE); + conf->ndots = (uint8_t)ndots; + } + + if (delim == EOF || delim == '\n') + break; + else + delim = getword(fp, word, sizeof(word)); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +add_search(irs_resconf_t *conf, char *domain) { + irs_resconf_search_t *entry; + + entry = isc_mem_get(conf->mctx, sizeof(*entry)); + if (entry == NULL) + return (ISC_R_NOMEMORY); + + entry->domain = domain; + ISC_LINK_INIT(entry, link); + ISC_LIST_APPEND(conf->searchlist, entry, link); + + return (ISC_R_SUCCESS); +} + +/*% parses a file and fills in the data structure. */ +isc_result_t +irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) +{ + FILE *fp = NULL; + char word[256]; + isc_result_t rval, ret = ISC_R_SUCCESS; + irs_resconf_t *conf; + unsigned int i; + int stopchar; + + REQUIRE(mctx != NULL); + REQUIRE(filename != NULL); + REQUIRE(strlen(filename) > 0U); + REQUIRE(confp != NULL && *confp == NULL); + + conf = isc_mem_get(mctx, sizeof(*conf)); + if (conf == NULL) + return (ISC_R_NOMEMORY); + + conf->mctx = mctx; + ISC_LIST_INIT(conf->nameservers); + ISC_LIST_INIT(conf->searchlist); + conf->numns = 0; + conf->domainname = NULL; + conf->searchnxt = 0; + conf->sortlistnxt = 0; + conf->resdebug = 0; + conf->ndots = 1; + for (i = 0; i < RESCONFMAXSEARCH; i++) + conf->search[i] = NULL; + + errno = 0; + if ((fp = fopen(filename, "r")) != NULL) { + do { + stopchar = getword(fp, word, sizeof(word)); + if (stopchar == EOF) { + rval = ISC_R_SUCCESS; + POST(rval); + break; + } + + if (strlen(word) == 0U) + rval = ISC_R_SUCCESS; + else if (strcmp(word, "nameserver") == 0) + rval = resconf_parsenameserver(conf, fp); + else if (strcmp(word, "domain") == 0) + rval = resconf_parsedomain(conf, fp); + else if (strcmp(word, "search") == 0) + rval = resconf_parsesearch(conf, fp); + else if (strcmp(word, "sortlist") == 0) + rval = resconf_parsesortlist(conf, fp); + else if (strcmp(word, "options") == 0) + rval = resconf_parseoption(conf, fp); + else { + /* unrecognised word. Ignore entire line */ + rval = ISC_R_SUCCESS; + stopchar = eatline(fp); + if (stopchar == EOF) { + break; + } + } + if (ret == ISC_R_SUCCESS && rval != ISC_R_SUCCESS) + ret = rval; + } while (1); + + fclose(fp); + } else { + switch (errno) { + case ENOENT: + break; + default: + isc_mem_put(mctx, conf, sizeof(*conf)); + return (ISC_R_INVALIDFILE); + } + } + + if (ret != ISC_R_SUCCESS) { + goto error; + } + + /* If we don't find a nameserver fall back to localhost */ + if (conf->numns == 0U) { + INSIST(ISC_LIST_EMPTY(conf->nameservers)); + + /* XXX: should we catch errors? */ + (void)add_server(conf->mctx, "127.0.0.1", &conf->nameservers); + (void)add_server(conf->mctx, "::1", &conf->nameservers); + } + + /* + * Construct unified search list from domain or configured + * search list + */ + if (conf->domainname != NULL) { + ret = add_search(conf, conf->domainname); + } else if (conf->searchnxt > 0) { + for (i = 0; i < conf->searchnxt; i++) { + ret = add_search(conf, conf->search[i]); + if (ret != ISC_R_SUCCESS) + break; + } + } + + error: + conf->magic = IRS_RESCONF_MAGIC; + + if (ret != ISC_R_SUCCESS) + irs_resconf_destroy(&conf); + else { + if (fp == NULL) + ret = ISC_R_FILENOTFOUND; + *confp = conf; + } + + return (ret); +} + +void +irs_resconf_destroy(irs_resconf_t **confp) { + irs_resconf_t *conf; + isc_sockaddr_t *address; + irs_resconf_search_t *searchentry; + unsigned int i; + + REQUIRE(confp != NULL); + conf = *confp; + REQUIRE(IRS_RESCONF_VALID(conf)); + + while ((searchentry = ISC_LIST_HEAD(conf->searchlist)) != NULL) { + ISC_LIST_UNLINK(conf->searchlist, searchentry, link); + isc_mem_put(conf->mctx, searchentry, sizeof(*searchentry)); + } + + while ((address = ISC_LIST_HEAD(conf->nameservers)) != NULL) { + ISC_LIST_UNLINK(conf->nameservers, address, link); + isc_mem_put(conf->mctx, address, sizeof(*address)); + } + + if (conf->domainname != NULL) + isc_mem_free(conf->mctx, conf->domainname); + + for (i = 0; i < RESCONFMAXSEARCH; i++) { + if (conf->search[i] != NULL) + isc_mem_free(conf->mctx, conf->search[i]); + } + + isc_mem_put(conf->mctx, conf, sizeof(*conf)); + + *confp = NULL; +} + +isc_sockaddrlist_t * +irs_resconf_getnameservers(irs_resconf_t *conf) { + REQUIRE(IRS_RESCONF_VALID(conf)); + + return (&conf->nameservers); +} + +irs_resconf_searchlist_t * +irs_resconf_getsearchlist(irs_resconf_t *conf) { + REQUIRE(IRS_RESCONF_VALID(conf)); + + return (&conf->searchlist); +} + +unsigned int +irs_resconf_getndots(irs_resconf_t *conf) { + REQUIRE(IRS_RESCONF_VALID(conf)); + + return ((unsigned int)conf->ndots); +} diff --git a/lib/irs/tests/Atffile b/lib/irs/tests/Atffile new file mode 100644 index 0000000..90f6d60 --- /dev/null +++ b/lib/irs/tests/Atffile @@ -0,0 +1,5 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = bind9 + +tp: resconf_test diff --git a/lib/irs/tests/Kyuafile b/lib/irs/tests/Kyuafile new file mode 100644 index 0000000..4ef7136 --- /dev/null +++ b/lib/irs/tests/Kyuafile @@ -0,0 +1,4 @@ +syntax(2) +test_suite('bind9') + +atf_test_program{name='resconf_test'} diff --git a/lib/irs/tests/Makefile.in b/lib/irs/tests/Makefile.in new file mode 100644 index 0000000..1a51aa9 --- /dev/null +++ b/lib/irs/tests/Makefile.in @@ -0,0 +1,53 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://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 -I../include ${ISC_INCLUDES} ${IRS_INCLUDES} +CDEFINES = -DTESTS="\"${top_builddir}/lib/irs/tests/\"" + +CFGLIBS = ../../isccfg/libisccfg.@A@ +CFGDEPLIBS = ../../isccfg/libisccfg.@A@ +DNSLIBS = ../../dns/libdns.@A@ @DNS_CRYPTO_LIBS@ +DNSDEPLIBS = ../../dns/libdns.@A@ +ISCLIBS = ../../isc/libisc.@A@ +ISCDEPLIBS = ../../isc/libisc.@A@ +IRSLIBS = ../libirs.@A@ +IRSDEPLIBS = ../libirs.@A@ + +LIBS = ${IRSLIBS} ${CFGLIBS} ${DNSLIBS} ${ISCLIBS} @LIBS@ @ATFLIBS@ + +OBJS = +SRCS = resconf_test.c + +SUBDIRS = +TARGETS = resconf_test@EXEEXT@ + +@BIND9_MAKE_RULES@ + +resconf_test@EXEEXT@: resconf_test.@O@ ${CFGDEPLIBS} ${DNSDEPLIBS} ${IRSDEPLIBS} ${ISCDEPLIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \ + resconf_test.@O@ ${LIBS} + +unit:: + sh ${top_builddir}/unit/unittest.sh + +clean distclean:: + rm -f ${TARGETS} + rm -f atf.out diff --git a/lib/irs/tests/resconf_test.c b/lib/irs/tests/resconf_test.c new file mode 100644 index 0000000..488ed5b --- /dev/null +++ b/lib/irs/tests/resconf_test.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +static isc_mem_t *mctx = NULL; + +static void +setup_test() { + isc_result_t result; + + result = isc_mem_create(0, 0, &mctx); + ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); + + /* + * atf-run changes us to a /tmp directory, so tests + * that access test data files must first chdir to the proper + * location. + */ + ATF_REQUIRE(chdir(TESTS) != -1); +} + +ATF_TC(irs_resconf_load); +ATF_TC_HEAD(irs_resconf_load, tc) { + atf_tc_set_md_var(tc, "descr", "irs_resconf_load"); +} +ATF_TC_BODY(irs_resconf_load, tc) { + isc_result_t result; + irs_resconf_t *resconf = NULL; + unsigned int i; + struct { + const char *file; + isc_result_t loadres; + isc_result_t (*check)(irs_resconf_t *resconf); + isc_result_t checkres; + } tests[] = { + { + "testdata/domain.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + }, { + "testdata/nameserver-v4.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + }, { + "testdata/nameserver-v6.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + }, { + "testdata/options-debug.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + }, { + "testdata/options-ndots.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + }, { + "testdata/options-timeout.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + }, { + "testdata/options-unknown.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + }, { + "testdata/options.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + }, { + "testdata/options-bad-ndots.conf", ISC_R_RANGE, + NULL, ISC_R_SUCCESS + }, { + "testdata/options-empty.conf", ISC_R_UNEXPECTEDEND, + NULL, ISC_R_SUCCESS + }, { + "testdata/port.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + }, { + "testdata/resolv.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + }, { + "testdata/search.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + }, { + "testdata/sortlist-v4.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + }, { + "testdata/timeout.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + }, { + "testdata/unknown.conf", ISC_R_SUCCESS, + NULL, ISC_R_SUCCESS + } + + }; + + UNUSED(tc); + + setup_test(); + + for (i = 0; i < sizeof(tests)/sizeof(tests[1]); i++) { + result = irs_resconf_load(mctx, tests[i].file, &resconf); + ATF_CHECK_EQ_MSG(result, tests[i].loadres, "%s", tests[i].file); + if (result == ISC_R_SUCCESS) + ATF_CHECK_MSG(resconf != NULL, "%s", tests[i].file); + else + ATF_CHECK_MSG(resconf == NULL, "%s", tests[i].file); + if (resconf != NULL && tests[i].check != NULL) { + result = (tests[i].check)(resconf); + ATF_CHECK_EQ_MSG(result, tests[i].checkres, "%s", + tests[i].file); + } + if (resconf != NULL) + irs_resconf_destroy(&resconf); + } + + isc_mem_detach(&mctx); +} + +/* + * Main + */ +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, irs_resconf_load); + return (atf_no_error()); +} diff --git a/lib/irs/tests/testdata/domain.conf b/lib/irs/tests/testdata/domain.conf new file mode 100644 index 0000000..6aef473 --- /dev/null +++ b/lib/irs/tests/testdata/domain.conf @@ -0,0 +1,10 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +domain example.com diff --git a/lib/irs/tests/testdata/nameserver-v4.conf b/lib/irs/tests/testdata/nameserver-v4.conf new file mode 100644 index 0000000..871d011 --- /dev/null +++ b/lib/irs/tests/testdata/nameserver-v4.conf @@ -0,0 +1,10 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +nameserver 10.0.0.1 diff --git a/lib/irs/tests/testdata/nameserver-v6.conf b/lib/irs/tests/testdata/nameserver-v6.conf new file mode 100644 index 0000000..9147462 --- /dev/null +++ b/lib/irs/tests/testdata/nameserver-v6.conf @@ -0,0 +1,10 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +nameserver 2001:DB8::1 diff --git a/lib/irs/tests/testdata/options-bad-ndots.conf b/lib/irs/tests/testdata/options-bad-ndots.conf new file mode 100644 index 0000000..5c104c7 --- /dev/null +++ b/lib/irs/tests/testdata/options-bad-ndots.conf @@ -0,0 +1,11 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +search example.com example.net +options ndots:256 diff --git a/lib/irs/tests/testdata/options-debug.conf b/lib/irs/tests/testdata/options-debug.conf new file mode 100644 index 0000000..b6e14c7 --- /dev/null +++ b/lib/irs/tests/testdata/options-debug.conf @@ -0,0 +1,10 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +options debug diff --git a/lib/irs/tests/testdata/options-empty.conf b/lib/irs/tests/testdata/options-empty.conf new file mode 100644 index 0000000..e8b902e --- /dev/null +++ b/lib/irs/tests/testdata/options-empty.conf @@ -0,0 +1,11 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +domain example.com +options diff --git a/lib/irs/tests/testdata/options-ndots.conf b/lib/irs/tests/testdata/options-ndots.conf new file mode 100644 index 0000000..2f143e1 --- /dev/null +++ b/lib/irs/tests/testdata/options-ndots.conf @@ -0,0 +1,10 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +option ndots:2 diff --git a/lib/irs/tests/testdata/options-timeout.conf b/lib/irs/tests/testdata/options-timeout.conf new file mode 100644 index 0000000..e211bba --- /dev/null +++ b/lib/irs/tests/testdata/options-timeout.conf @@ -0,0 +1,10 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +options timeout:1 diff --git a/lib/irs/tests/testdata/options-unknown.conf b/lib/irs/tests/testdata/options-unknown.conf new file mode 100644 index 0000000..f5df6bf --- /dev/null +++ b/lib/irs/tests/testdata/options-unknown.conf @@ -0,0 +1,10 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +options unknown diff --git a/lib/irs/tests/testdata/options.conf b/lib/irs/tests/testdata/options.conf new file mode 100644 index 0000000..0d4dfa0 --- /dev/null +++ b/lib/irs/tests/testdata/options.conf @@ -0,0 +1,10 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +options unknown debug timeout:1 ndots:2 diff --git a/lib/irs/tests/testdata/port.conf b/lib/irs/tests/testdata/port.conf new file mode 100644 index 0000000..04ed3e7 --- /dev/null +++ b/lib/irs/tests/testdata/port.conf @@ -0,0 +1,10 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +port 5300 diff --git a/lib/irs/tests/testdata/resolv.conf b/lib/irs/tests/testdata/resolv.conf new file mode 100644 index 0000000..ddf93ff --- /dev/null +++ b/lib/irs/tests/testdata/resolv.conf @@ -0,0 +1,17 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +port 5300 +nameserver 10.0.0.1 +nameserver 2001:DB8::1 +search example.com example.net +sortlist 130.155.160.0/255.255.240.0 130.155.0.0 +timeout 10 +unknown directive +options unknown debug timeout:1 ndots:2 diff --git a/lib/irs/tests/testdata/search.conf b/lib/irs/tests/testdata/search.conf new file mode 100644 index 0000000..5717006 --- /dev/null +++ b/lib/irs/tests/testdata/search.conf @@ -0,0 +1,10 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +search example.com example.net diff --git a/lib/irs/tests/testdata/sortlist-v4.conf b/lib/irs/tests/testdata/sortlist-v4.conf new file mode 100644 index 0000000..e903e37 --- /dev/null +++ b/lib/irs/tests/testdata/sortlist-v4.conf @@ -0,0 +1,10 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +sortlist 130.155.160.0/255.255.240.0 130.155.0.0 diff --git a/lib/irs/tests/testdata/timeout.conf b/lib/irs/tests/testdata/timeout.conf new file mode 100644 index 0000000..2b87b25 --- /dev/null +++ b/lib/irs/tests/testdata/timeout.conf @@ -0,0 +1,10 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +timeout 10 diff --git a/lib/irs/tests/testdata/unknown.conf b/lib/irs/tests/testdata/unknown.conf new file mode 100644 index 0000000..bfb9d7f --- /dev/null +++ b/lib/irs/tests/testdata/unknown.conf @@ -0,0 +1,10 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +unknown directive diff --git a/lib/irs/version.c b/lib/irs/version.c new file mode 100644 index 0000000..4e33c77 --- /dev/null +++ b/lib/irs/version.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#include + +const char irs_version[] = VERSION; + +const unsigned int irs_libinterface = LIBINTERFACE; +const unsigned int irs_librevision = LIBREVISION; +const unsigned int irs_libage = LIBAGE; diff --git a/lib/irs/win32/DLLMain.c b/lib/irs/win32/DLLMain.c new file mode 100644 index 0000000..8ff1017 --- /dev/null +++ b/lib/irs/win32/DLLMain.c @@ -0,0 +1,50 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include +#include + +/* + * 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/irs/win32/Makefile.in b/lib/irs/win32/Makefile.in new file mode 100644 index 0000000..419cf9f --- /dev/null +++ b/lib/irs/win32/Makefile.in @@ -0,0 +1,17 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://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 = include +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/irs/win32/include/Makefile.in b/lib/irs/win32/include/Makefile.in new file mode 100644 index 0000000..3601331 --- /dev/null +++ b/lib/irs/win32/include/Makefile.in @@ -0,0 +1,17 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://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 = irs +TARGETS = + +@BIND9_MAKE_RULES@ diff --git a/lib/irs/win32/include/irs/Makefile.in b/lib/irs/win32/include/irs/Makefile.in new file mode 100644 index 0000000..f73058f --- /dev/null +++ b/lib/irs/win32/include/irs/Makefile.in @@ -0,0 +1,26 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("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 http://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@ + +HEADERS = +SUBDIRS = +TARGETS = + +@BIND9_MAKE_RULES@ + +installdirs: + $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/irs + +install:: installdirs + for i in ${HEADERS}; do \ + ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/irs || exit 1; \ + done diff --git a/lib/irs/win32/include/irs/netdb.h b/lib/irs/win32/include/irs/netdb.h new file mode 100644 index 0000000..9e0fc72 --- /dev/null +++ b/lib/irs/win32/include/irs/netdb.h @@ -0,0 +1,201 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/*! \file */ + +#ifndef IRS_NETDB_H +#define IRS_NETDB_H 1 + +#include /* Required on FreeBSD (and others?) for size_t. */ + +/* + * Define if does not declare struct addrinfo. + */ +#undef ISC_IRS_NEEDADDRINFO + +#ifdef ISC_IRS_NEEDADDRINFO +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* Length of ai_addr */ + char *ai_canonname; /* Canonical name for hostname */ + struct sockaddr *ai_addr; /* Binary address */ + struct addrinfo *ai_next; /* Next structure in linked list */ +}; +#endif + +/* + * Undefine all #defines we are interested in as may or may not have + * defined them. + */ + +/* + * Error return codes from gethostbyname() and gethostbyaddr() + * (left in extern int h_errno). + */ + +#undef NETDB_INTERNAL +#undef NETDB_SUCCESS +#undef HOST_NOT_FOUND +#undef TRY_AGAIN +#undef NO_RECOVERY +#undef NO_DATA +#undef NO_ADDRESS + +#define NETDB_INTERNAL -1 /* see errno */ +#define NETDB_SUCCESS 0 /* no problem */ +#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ +#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */ +#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ +#define NO_DATA 4 /* Valid name, no data record of requested type */ +#define NO_ADDRESS NO_DATA /* no address, look for MX record */ + +/* + * Error return codes from getaddrinfo(). EAI_INSECUREDATA is our own extension + * and it's very unlikely to be already defined, but undef it just in case; it + * at least doesn't do any harm. + */ + +#undef EAI_ADDRFAMILY +#undef EAI_AGAIN +#undef EAI_BADFLAGS +#undef EAI_FAIL +#undef EAI_FAMILY +#undef EAI_MEMORY +#undef EAI_NODATA +#undef EAI_NONAME +#undef EAI_SERVICE +#undef EAI_SOCKTYPE +#undef EAI_SYSTEM +#undef EAI_BADHINTS +#undef EAI_PROTOCOL +#undef EAI_OVERFLOW +#undef EAI_INSECUREDATA +#undef EAI_MAX + +#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */ +#define EAI_AGAIN 2 /* temporary failure in name resolution */ +#define EAI_BADFLAGS 3 /* invalid value for ai_flags */ +#define EAI_FAIL 4 /* non-recoverable failure in name resolution */ +#define EAI_FAMILY 5 /* ai_family not supported */ +#define EAI_MEMORY 6 /* memory allocation failure */ +#define EAI_NODATA 7 /* no address associated with hostname */ +#define EAI_NONAME 8 /* hostname nor servname provided, or not known */ +#define EAI_SERVICE 9 /* servname not supported for ai_socktype */ +#define EAI_SOCKTYPE 10 /* ai_socktype not supported */ +#define EAI_SYSTEM 11 /* system error returned in errno */ +#define EAI_BADHINTS 12 +#define EAI_PROTOCOL 13 +#define EAI_OVERFLOW 14 +#define EAI_INSECUREDATA 15 +#define EAI_MAX 16 + +/* + * Flag values for getaddrinfo() + */ +#undef AI_PASSIVE +#undef AI_CANONNAME +#undef AI_NUMERICHOST + +#define AI_PASSIVE 0x00000001 +#define AI_CANONNAME 0x00000002 +#define AI_NUMERICHOST 0x00000004 + +/* + * Flag values for getipnodebyname() + */ +#undef AI_V4MAPPED +#undef AI_ALL +#undef AI_ADDRCONFIG +#undef AI_DEFAULT + +#define AI_V4MAPPED 0x00000008 +#define AI_ALL 0x00000010 +#define AI_ADDRCONFIG 0x00000020 +#define AI_DEFAULT (AI_V4MAPPED|AI_ADDRCONFIG) + +/* + * Constants for lwres_getnameinfo() + */ +#undef NI_MAXHOST +#undef NI_MAXSERV + +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +/* + * Flag values for lwres_getnameinfo() + */ +#undef NI_NOFQDN +#undef NI_NUMERICHOST +#undef NI_NAMEREQD +#undef NI_NUMERICSERV +#undef NI_DGRAM +#undef NI_NUMERICSCOPE + +#define NI_NOFQDN 0x00000001 +#define NI_NUMERICHOST 0x00000002 +#define NI_NAMEREQD 0x00000004 +#define NI_NUMERICSERV 0x00000008 +#define NI_DGRAM 0x00000010 + +/* + * Define to map into irs_ namespace. + */ + +#define IRS_NAMESPACE + +#ifdef IRS_NAMESPACE + +/* + * Use our versions not the ones from the C library. + */ + +#ifdef getnameinfo +#undef getnameinfo +#endif +#define getnameinfo irs_getnameinfo + +#ifdef getaddrinfo +#undef getaddrinfo +#endif +#define getaddrinfo irs_getaddrinfo + +#ifdef freeaddrinfo +#undef freeaddrinfo +#endif +#define freeaddrinfo irs_freeaddrinfo + +#ifdef gai_strerror +#undef gai_strerror +#endif +#define gai_strerror irs_gai_strerror + +#endif + +int getaddrinfo(const char *, const char *, + const struct addrinfo *, struct addrinfo **); +int getnameinfo(const struct sockaddr *, socklen_t, char *, + DWORD, char *, DWORD, int); +void freeaddrinfo(struct addrinfo *); +char *gai_strerror(int); + +/* + * Tell Emacs to use C mode on this file. + * Local variables: + * mode: c + * End: + */ + +#endif /* IRS_NETDB_H */ diff --git a/lib/irs/win32/include/irs/platform.h b/lib/irs/win32/include/irs/platform.h new file mode 100644 index 0000000..78c91ce --- /dev/null +++ b/lib/irs/win32/include/irs/platform.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/*! \file */ + +#ifndef IRS_PLATFORM_H +#define IRS_PLATFORM_H 1 + +/***** + ***** Platform-dependent defines. + *****/ + +#ifndef IRS_PLATFORM_USEDECLSPEC +#define LIBIRS_EXTERNAL_DATA +#else +#ifdef LIBIRS_EXPORTS +#define LIBIRS_EXTERNAL_DATA __declspec(dllexport) +#else +#define LIBIRS_EXTERNAL_DATA __declspec(dllimport) +#endif +#endif + +/* + * Tell Emacs to use C mode on this file. + * Local Variables: + * mode: c + * End: + */ + +#endif /* IRS_PLATFORM_H */ diff --git a/lib/irs/win32/libirs.def b/lib/irs/win32/libirs.def new file mode 100644 index 0000000..d4e9f6f --- /dev/null +++ b/lib/irs/win32/libirs.def @@ -0,0 +1,27 @@ +LIBRARY libirs + +; Exported Functions +EXPORTS +irs_context_create +irs_context_destroy +irs_context_get +irs_context_getappctx +irs_context_getdnsclient +irs_context_getdnsconf +irs_context_getmctx +irs_context_getresconf +irs_context_gettask +irs_context_gettaskmgr +irs_context_gettimermgr +irs_dnsconf_destroy +irs_dnsconf_gettrustedkeys +irs_dnsconf_load +irs_freeaddrinfo +irs_gai_strerror +irs_getaddrinfo +irs_getnameinfo +irs_resconf_destroy +irs_resconf_getnameservers +irs_resconf_getndots +irs_resconf_getsearchlist +irs_resconf_load diff --git a/lib/irs/win32/libirs.dsp.in b/lib/irs/win32/libirs.dsp.in new file mode 100644 index 0000000..3f6d1a7 --- /dev/null +++ b/lib/irs/win32/libirs.dsp.in @@ -0,0 +1,169 @@ +# Microsoft Developer Studio Project File - Name="libirs" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "@PLATFORM@ (x86) Dynamic-Link Library" 0x0102 + +CFG=libirs - @PLATFORM@ Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libirs.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libirs.mak" CFG="libirs - @PLATFORM@ Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libirs - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Dynamic-Link Library") +!MESSAGE "libirs - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "libirs_EXPORTS" @COPTY@ /FD /c +# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 @LIBXML2_INC@ @OPENSSL_INC@ @GEOIP_INC@ /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "WIN32" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" @CRYPTO@ /D "LIBIRS_EXPORTS" @COPTY@ /FD /c +# SUBTRACT CPP /X +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll @MACHINE@ +# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../isc/win32/Release/libisc.lib ../../dns/win32/Release/libdns.lib ../../isccfg/win32/Release/libisccfg.lib /nologo /dll @MACHINE@ /out:"../../../Build/Release/libirs.dll" + +!ELSEIF "$(CFG)" == "libirs - @PLATFORM@ Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "libirs_EXPORTS" @COPTY@ /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od @LIBXML2_INC@ @OPENSSL_INC@ @GEOIP_INC@ /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" @CRYPTO@ /D "LIBIRS_EXPORTS" /FR @COPTY@ /FD /GZ /c +# SUBTRACT CPP /X +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug @MACHINE@ /pdbtype:sept +# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../isc/win32/debug/libisc.lib ../../dns/win32/debug/libdns.lib ../../isccfg/win32/debug/libisccfg.lib /nologo /dll /debug @MACHINE@ /out:"../../../Build/Debug/libirs.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "libirs - @PLATFORM@ Release" +# Name "libirs - @PLATFORM@ Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\context.c +# End Source File +# Begin Source File + +SOURCE=.\DLLMain.c +# End Source File +# Begin Source File + +SOURCE=..\dnsconf.c +# End Source File +# Begin Source File + +SOURCE=..\gai_strerror.c +# End Source File +# Begin Source File + +SOURCE=..\getaddrinfo.c +# End Source File +# Begin Source File + +SOURCE=..\getnameinfo.c +# End Source File +# Begin Source File + +SOURCE=..\resconf.c +# End Source File +# Begin Source File + +SOURCE=.\version.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\include\irs\context.h +# End Source File +# Begin Source File + +SOURCE=..\include\irs\dnsconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\irs\netdb.h +# End Source File +# Begin Source File + +SOURCE=..\include\irs\platform.h +# End Source File +# Begin Source File + +SOURCE=..\include\irs\resconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\irs\types.h +# End Source File +# Begin Source File + +SOURCE=..\include\irs\version.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=.\libirs.def +# End Source File +# End Target +# End Project diff --git a/lib/irs/win32/libirs.dsw b/lib/irs/win32/libirs.dsw new file mode 100644 index 0000000..2034776 --- /dev/null +++ b/lib/irs/win32/libirs.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "libirs"=.\libirs.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/lib/irs/win32/libirs.mak.in b/lib/irs/win32/libirs.mak.in new file mode 100644 index 0000000..4894057 --- /dev/null +++ b/lib/irs/win32/libirs.mak.in @@ -0,0 +1,548 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on libirs.dsp +!IF "$(CFG)" == "" +CFG=libirs - @PLATFORM@ Release +!MESSAGE No configuration specified. Defaulting to libirs - @PLATFORM@ Release. +!ENDIF + +!IF "$(CFG)" != "libirs - @PLATFORM@ Release" && "$(CFG)" != "libirs - @PLATFORM@ Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libirs.mak" CFG="libirs - @PLATFORM@ Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libirs - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Dynamic-Link Library") +!MESSAGE "libirs - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" +_VC_MANIFEST_INC=0 +_VC_MANIFEST_BASENAME=__VC80 +!ELSE +_VC_MANIFEST_INC=1 +_VC_MANIFEST_BASENAME=__VC80.Debug +!ENDIF + +#################################################### +# Specifying name of temporary resource file used only in incremental builds: + +!if "$(_VC_MANIFEST_INC)" == "1" +_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res +!else +_VC_MANIFEST_AUTO_RES= +!endif + +#################################################### +# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE: + +!if "$(_VC_MANIFEST_INC)" == "1" + +#MT_SPECIAL_RETURN=1090650113 +#MT_SPECIAL_SWITCH=-notify_resource_update +MT_SPECIAL_RETURN=0 +MT_SPECIAL_SWITCH= +_VC_MANIFEST_EMBED_EXE= \ +if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ +if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ +rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ +link $** /out:$@ $(LFLAGS) + +!else + +_VC_MANIFEST_EMBED_EXE= \ +if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1 + +!endif + +#################################################### +# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL: + +!if "$(_VC_MANIFEST_INC)" == "1" + +#MT_SPECIAL_RETURN=1090650113 +#MT_SPECIAL_SWITCH=-notify_resource_update +MT_SPECIAL_RETURN=0 +MT_SPECIAL_SWITCH= +_VC_MANIFEST_EMBED_EXE= \ +if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \ +if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \ +rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \ +link $** /out:$@ $(LFLAGS) + +!else + +_VC_MANIFEST_EMBED_EXE= \ +if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2 + +!endif +#################################################### +# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily: + +!if "$(_VC_MANIFEST_INC)" == "1" + +_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \ + $(_VC_MANIFEST_BASENAME).auto.rc \ + $(_VC_MANIFEST_BASENAME).auto.manifest + +!else + +_VC_MANIFEST_CLEAN= + +!endif + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" + +OUTDIR=.\Release +INTDIR=.\Release + +!IF "$(RECURSE)" == "0" + +ALL : "..\..\..\Build\Release\libirs.dll" + +!ELSE + +ALL : "libisccfg - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\libirs.dll" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libisccfg - @PLATFORM@ ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\context.obj" + -@erase "$(INTDIR)\DLLMain.obj" + -@erase "$(INTDIR)\dnsconf.obj" + -@erase "$(INTDIR)\gai_strerror.obj" + -@erase "$(INTDIR)\getaddrinfo.obj" + -@erase "$(INTDIR)\getnameinfo.obj" + -@erase "$(INTDIR)\resconf.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\version.obj" + -@erase "$(OUTDIR)\libirs.exp" + -@erase "$(OUTDIR)\libirs.lib" + -@erase "..\..\..\Build\Release\libirs.dll" + -@$(_VC_MANIFEST_CLEAN) + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 @LIBXML2_INC@ @OPENSSL_INC@ @GEOIP_INC@ /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "WIN32" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" @CRYPTO@ /D "LIBIRS_EXPORTS" /Fp"$(INTDIR)\libirs.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\libirs.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../isc/win32/Release/libisc.lib ../../dns/win32/Release/libdns.lib ../../isccfg/win32/Release/libisccfg.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\libirs.pdb" @MACHINE@ /def:".\libirs.def" /out:"../../../Build/Release/libirs.dll" /implib:"$(OUTDIR)\libirs.lib" +DEF_FILE= \ + ".\libirs.def" +LINK32_OBJS= \ + "$(INTDIR)\context.obj" \ + "$(INTDIR)\DLLMain.obj" \ + "$(INTDIR)\dnsconf.obj" \ + "$(INTDIR)\gai_strerror.obj" \ + "$(INTDIR)\getaddrinfo.obj" \ + "$(INTDIR)\getnameinfo.obj" \ + "$(INTDIR)\resconf.obj" \ + "$(INTDIR)\version.obj" \ + "..\..\dns\win32\Release\libdns.lib" \ + "..\..\isc\win32\Release\libisc.lib" \ + "..\..\isccfg\win32\Release\libisccfg.lib" + +"..\..\..\Build\Release\libirs.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + $(_VC_MANIFEST_EMBED_DLL) + +!ELSEIF "$(CFG)" == "libirs - @PLATFORM@ Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "..\..\..\Build\Debug\libirs.dll" "$(OUTDIR)\libirs.bsc" + +!ELSE + +ALL : "libisccfg - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\libirs.dll" "$(OUTDIR)\libirs.bsc" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libisccfg - @PLATFORM@ DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\context.obj" + -@erase "$(INTDIR)\context.sbr" + -@erase "$(INTDIR)\DLLMain.obj" + -@erase "$(INTDIR)\DLLMain.sbr" + -@erase "$(INTDIR)\dnsconf.obj" + -@erase "$(INTDIR)\dnsconf.sbr" + -@erase "$(INTDIR)\gai_strerror.obj" + -@erase "$(INTDIR)\gai_strerror.sbr" + -@erase "$(INTDIR)\getaddrinfo.obj" + -@erase "$(INTDIR)\getaddrinfo.sbr" + -@erase "$(INTDIR)\getnameinfo.obj" + -@erase "$(INTDIR)\getnameinfo.sbr" + -@erase "$(INTDIR)\resconf.obj" + -@erase "$(INTDIR)\resconf.sbr" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\vc60.pdb" + -@erase "$(INTDIR)\version.obj" + -@erase "$(INTDIR)\version.sbr" + -@erase "$(OUTDIR)\libirs.bsc" + -@erase "$(OUTDIR)\libirs.exp" + -@erase "$(OUTDIR)\libirs.lib" + -@erase "$(OUTDIR)\libirs.pdb" + -@erase "..\..\..\Build\Debug\libirs.dll" + -@erase "..\..\..\Build\Debug\libirs.ilk" + -@$(_VC_MANIFEST_CLEAN) + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od @LIBXML2_INC@ @OPENSSL_INC@ @GEOIP_INC@ /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" @CRYPTO@ /D "LIBIRS_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libirs.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\libirs.bsc" +BSC32_SBRS= \ + "$(INTDIR)\context.sbr" \ + "$(INTDIR)\DLLMain.sbr" \ + "$(INTDIR)\dnsconf.sbr" \ + "$(INTDIR)\gai_strerror.sbr" \ + "$(INTDIR)\getaddrinfo.sbr" \ + "$(INTDIR)\getnameinfo.sbr" \ + "$(INTDIR)\resconf.sbr" \ + "$(INTDIR)\version.sbr" + +"$(OUTDIR)\libirs.bsc" : "$(OUTDIR)" $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../isc/win32/debug/libisc.lib ../../dns/win32/debug/libdns.lib ../../isccfg/win32/debug/libisccfg.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\libirs.pdb" /debug @MACHINE@ /def:".\libirs.def" /out:"../../../Build/Debug/libirs.dll" /implib:"$(OUTDIR)\libirs.lib" /pdbtype:sept +DEF_FILE= \ + ".\libirs.def" +LINK32_OBJS= \ + "$(INTDIR)\context.obj" \ + "$(INTDIR)\DLLMain.obj" \ + "$(INTDIR)\dnsconf.obj" \ + "$(INTDIR)\gai_strerror.obj" \ + "$(INTDIR)\getaddrinfo.obj" \ + "$(INTDIR)\getnameinfo.obj" \ + "$(INTDIR)\resconf.obj" \ + "$(INTDIR)\version.obj" \ + "..\..\dns\win32\Debug\libdns.lib" \ + "..\..\isc\win32\Debug\libisc.lib" \ + "..\..\isccfg\win32\Debug\libisccfg.lib" + +"..\..\..\Build\Debug\libirs.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + $(_VC_MANIFEST_EMBED_DLL) + +!ENDIF + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("libirs.dep") +!INCLUDE "libirs.dep" +!ELSE +!MESSAGE Warning: cannot find "libirs.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" || "$(CFG)" == "libirs - @PLATFORM@ Debug" +SOURCE=..\context.c + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" + + +"$(INTDIR)\context.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libirs - @PLATFORM@ Debug" + + +"$(INTDIR)\context.obj" "$(INTDIR)\context.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\DLLMain.c + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" + + +"$(INTDIR)\DLLMain.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libirs - @PLATFORM@ Debug" + + +"$(INTDIR)\DLLMain.obj" "$(INTDIR)\DLLMain.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=..\dnsconf.c + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" + + +"$(INTDIR)\dnsconf.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libirs - @PLATFORM@ Debug" + + +"$(INTDIR)\dnsconf.obj" "$(INTDIR)\dnsconf.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\gai_strerror.c + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" + + +"$(INTDIR)\gai_strerror.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libirs - @PLATFORM@ Debug" + + +"$(INTDIR)\gai_strerror.obj" "$(INTDIR)\gai_strerror.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\getaddrinfo.c + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" + + +"$(INTDIR)\getaddrinfo.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libirs - @PLATFORM@ Debug" + + +"$(INTDIR)\getaddrinfo.obj" "$(INTDIR)\getaddrinfo.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\getnameinfo.c + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" + + +"$(INTDIR)\getnameinfo.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libirs - @PLATFORM@ Debug" + + +"$(INTDIR)\getnameinfo.obj" "$(INTDIR)\getnameinfo.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\resconf.c + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" + + +"$(INTDIR)\resconf.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "libirs - @PLATFORM@ Debug" + + +"$(INTDIR)\resconf.obj" "$(INTDIR)\resconf.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\version.c + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" + + +"$(INTDIR)\version.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "libirs - @PLATFORM@ Debug" + + +"$(INTDIR)\version.obj" "$(INTDIR)\version.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" + +"libdns - @PLATFORM@ Release" : + cd "..\..\dns\win32" + $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" + cd "..\..\irs\win32" + +"libdns - @PLATFORM@ ReleaseCLEAN" : + cd "..\..\dns\win32" + $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN + cd "..\..\irs\win32" + +!ELSEIF "$(CFG)" == "libirs - @PLATFORM@ Debug" + +"libdns - @PLATFORM@ Debug" : + cd "..\..\dns\win32" + $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" + cd "..\..\irs\win32" + +"libdns - @PLATFORM@ DebugCLEAN" : + cd "..\..\dns\win32" + $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN + cd "..\..\irs\win32" + +!ENDIF + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" + +"libisc - @PLATFORM@ Release" : + cd "..\..\isc\win32" + $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" + cd "..\..\irs\win32" + +"libisc - @PLATFORM@ ReleaseCLEAN" : + cd "..\..\isc\win32" + $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN + cd "..\..\irs\win32" + +!ELSEIF "$(CFG)" == "libirs - @PLATFORM@ Debug" + +"libisc - @PLATFORM@ Debug" : + cd "..\..\isc\win32" + $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" + cd "..\..\irs\win32" + +"libisc - @PLATFORM@ DebugCLEAN" : + cd "..\..\isc\win32" + $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN + cd "..\..\irs\win32" + +!ENDIF + +!IF "$(CFG)" == "libirs - @PLATFORM@ Release" + +"libisccfg - @PLATFORM@ Release" : + cd "..\..\isccfg\win32" + $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release" + cd "..\..\irs\win32" + +"libisccfg - @PLATFORM@ ReleaseCLEAN" : + cd "..\..\isccfg\win32" + $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Release" RECURSE=1 CLEAN + cd "..\..\irs\win32" + +!ELSEIF "$(CFG)" == "libirs - @PLATFORM@ Debug" + +"libisccfg - @PLATFORM@ Debug" : + cd "..\..\isccfg\win32" + $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug" + cd "..\..\irs\win32" + +"libisccfg - @PLATFORM@ DebugCLEAN" : + cd "..\..\isccfg\win32" + $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - @PLATFORM@ Debug" RECURSE=1 CLEAN + cd "..\..\irs\win32" + +!ENDIF + + +!ENDIF + +#################################################### +# Commands to generate initial empty manifest file and the RC file +# that references it, and for generating the .res file: + +$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc + +$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest + type <<$@ +#include +1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest" +<< KEEP + +$(_VC_MANIFEST_BASENAME).auto.manifest : + type <<$@ + + + +<< KEEP diff --git a/lib/irs/win32/libirs.vcxproj.filters.in b/lib/irs/win32/libirs.vcxproj.filters.in new file mode 100644 index 0000000..eae47de --- /dev/null +++ b/lib/irs/win32/libirs.vcxproj.filters.in @@ -0,0 +1,69 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/lib/irs/win32/libirs.vcxproj.in b/lib/irs/win32/libirs.vcxproj.in new file mode 100644 index 0000000..96af09b --- /dev/null +++ b/lib/irs/win32/libirs.vcxproj.in @@ -0,0 +1,133 @@ + + + + + Debug + @PLATFORM@ + + + Release + @PLATFORM@ + + + + {A4F29CEB-7644-4A7F-BE9E-02B6A90E4919} + Win32Proj + libirs + + + + DynamicLibrary + true + MultiByte + + + DynamicLibrary + false + true + MultiByte + + + + + + + + + + + + + true + ..\..\..\Build\$(Configuration)\ + .\$(Configuration)\ + + + false + ..\..\..\Build\$(Configuration)\ + .\$(Configuration)\ + + + + + + Level3 + Disabled + WIN32;USE_MD5;@CRYPTO@_DEBUG;_WINDOWS;_USRDLL;LIBIRS_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions) + .\;..\..\..\;include;..\include;..\..\isc\win32;..\..\isc\win32\include;..\..\isc\include;..\..\isccfg\include;..\..\dns\include;@LIBXML2_INC@@OPENSSL_INC@@GEOIP_INC@%(AdditionalIncludeDirectories) + true + .\$(Configuration)\$(TargetName).pch + .\$(Configuration)\ + .\$(Configuration)\ + $(OutDir)$(TargetName).pdb + true + CompileAsC + + + Console + true + ..\..\isc\win32\$(Configuration);..\..\dns\win32\$(Configuration);..\..\isccfg\win32\$(Configuration);%(AdditionalLibraryDirectories) + libisc.lib;libdns.lib;libisccfg.lib;ws2_32.lib;%(AdditionalDependencies) + .\libirs.def + .\$(Configuration)\$(ProjectName).lib + ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) + + + + + Level3 + + + MaxSpeed + true + @INTRINSIC@ + WIN32;USE_MD5;@CRYPTO@NDEBUG;_WINDOWS;_USRDLL;LIBIRS_EXPORTS;%(PreprocessorDefinitions);%(PreprocessorDefinitions) + .\;..\..\..\;include;..\include;..\..\isc\win32;..\..\isc\win32\include;..\..\isc\include;..\..\isccfg\include;..\..\dns\include;@LIBXML2_INC@@OPENSSL_INC@@GEOIP_INC@%(AdditionalIncludeDirectories) + OnlyExplicitInline + false + true + .\$(Configuration)\$(TargetName).pch + .\$(Configuration)\ + .\$(Configuration)\ + $(OutDir)$(TargetName).pdb + CompileAsC + + + Console + false + true + true + ..\..\isc\win32\$(Configuration);..\..\dns\win32\$(Configuration);..\..\isccfg\win32\$(Configuration);%(AdditionalLibraryDirectories) + libisc.lib;libdns.lib;libisccfg.lib;ws2_32.lib;%(AdditionalDependencies) + .\libirs.def + .\$(Configuration)\$(ProjectName).lib + Default + ..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt) + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/irs/win32/libirs.vcxproj.user b/lib/irs/win32/libirs.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/lib/irs/win32/libirs.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/lib/irs/win32/version.c b/lib/irs/win32/version.c new file mode 100644 index 0000000..198e12d --- /dev/null +++ b/lib/irs/win32/version.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include + +#include + +LIBIRS_EXTERNAL_DATA const char irs_version[] = VERSION; + +LIBIRS_EXTERNAL_DATA const unsigned int irs_libinterface = LIBINTERFACE; +LIBIRS_EXTERNAL_DATA const unsigned int irs_librevision = LIBREVISION; +LIBIRS_EXTERNAL_DATA const unsigned int irs_libage = LIBAGE; -- cgit v1.2.3