diff options
author | des <des@FreeBSD.org> | 2013-09-30 17:23:45 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2013-09-30 17:23:45 +0000 |
commit | aa2e4b623cdc1d9d2b44a103d24ecb7e0c984de9 (patch) | |
tree | 1a2886b0de387ddff665d0e370f40ffc32778840 /contrib/bind9/lib/isc/unix | |
parent | 9e2a5c1c0e7dbd2e8116aa8f1ce21759dec75295 (diff) | |
download | FreeBSD-src-aa2e4b623cdc1d9d2b44a103d24ecb7e0c984de9.zip FreeBSD-src-aa2e4b623cdc1d9d2b44a103d24ecb7e0c984de9.tar.gz |
Remove BIND.
Approved by: re (gjb)
Diffstat (limited to 'contrib/bind9/lib/isc/unix')
37 files changed, 0 insertions, 13621 deletions
diff --git a/contrib/bind9/lib/isc/unix/Makefile.in b/contrib/bind9/lib/isc/unix/Makefile.in deleted file mode 100644 index c1411cb..0000000 --- a/contrib/bind9/lib/isc/unix/Makefile.in +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (C) 2004, 2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC") -# Copyright (C) 1998-2001 Internet Software Consortium. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -# PERFORMANCE OF THIS SOFTWARE. - -# $Id: Makefile.in,v 1.44 2009/12/05 23:31:41 each Exp $ - -srcdir = @srcdir@ -VPATH = @srcdir@ -top_srcdir = @top_srcdir@ - -CINCLUDES = -I${srcdir}/include \ - -I${srcdir}/../@ISC_THREAD_DIR@/include \ - -I../include \ - -I${srcdir}/../include \ - -I${srcdir}/.. - -CDEFINES = -CWARNINGS = - -# Alphabetically -OBJS = @ISC_IPV6_O@ \ - app.@O@ dir.@O@ entropy.@O@ errno2result.@O@ file.@O@ \ - fsaccess.@O@ interfaceiter.@O@ keyboard.@O@ net.@O@ \ - os.@O@ resource.@O@ socket.@O@ stdio.@O@ stdtime.@O@ \ - strerror.@O@ syslog.@O@ time.@O@ - -# Alphabetically -SRCS = @ISC_IPV6_C@ \ - app.c dir.c entropy.c errno2result.c file.c \ - fsaccess.c interfaceiter.c keyboard.c net.c \ - os.c resource.c socket.c stdio.c stdtime.c \ - strerror.c syslog.c time.c - -SUBDIRS = include -TARGETS = ${OBJS} - -@BIND9_MAKE_RULES@ - -interfaceiter.@O@: interfaceiter.c ifiter_ioctl.c ifiter_sysctl.c ifiter_getifaddrs.c - diff --git a/contrib/bind9/lib/isc/unix/app.c b/contrib/bind9/lib/isc/unix/app.c deleted file mode 100644 index 5393be9..0000000 --- a/contrib/bind9/lib/isc/unix/app.c +++ /dev/null @@ -1,946 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: app.c,v 1.64 2009/11/04 05:58:46 marka Exp $ */ - -/*! \file */ - -#include <config.h> - -#include <sys/param.h> /* Openserver 5.0.6A and FD_SETSIZE */ -#include <sys/types.h> - -#include <stddef.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <signal.h> -#include <sys/time.h> -#ifdef HAVE_EPOLL -#include <sys/epoll.h> -#endif - -#include <isc/app.h> -#include <isc/boolean.h> -#include <isc/condition.h> -#include <isc/mem.h> -#include <isc/msgs.h> -#include <isc/mutex.h> -#include <isc/event.h> -#include <isc/platform.h> -#include <isc/strerror.h> -#include <isc/string.h> -#include <isc/task.h> -#include <isc/time.h> -#include <isc/util.h> - -/*% - * For BIND9 internal applications built with threads, we use a single app - * context and let multiple worker, I/O, timer threads do actual jobs. - * For other cases (including BIND9 built without threads) an app context acts - * as an event loop dispatching various events. - */ -#if defined(ISC_PLATFORM_USETHREADS) && defined(BIND9) -#define USE_THREADS_SINGLECTX -#endif - -#ifdef ISC_PLATFORM_USETHREADS -#include <pthread.h> -#endif - -#ifndef USE_THREADS_SINGLECTX -#include "../timer_p.h" -#include "../task_p.h" -#include "socket_p.h" -#endif /* USE_THREADS_SINGLECTX */ - -#ifdef ISC_PLATFORM_USETHREADS -static pthread_t blockedthread; -#endif /* ISC_PLATFORM_USETHREADS */ - -/*% - * The following can be either static or public, depending on build environment. - */ - -#ifdef BIND9 -#define ISC_APPFUNC_SCOPE -#else -#define ISC_APPFUNC_SCOPE static -#endif - -ISC_APPFUNC_SCOPE isc_result_t isc__app_start(void); -ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxstart(isc_appctx_t *ctx); -ISC_APPFUNC_SCOPE isc_result_t isc__app_onrun(isc_mem_t *mctx, - isc_task_t *task, - isc_taskaction_t action, - void *arg); -ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxrun(isc_appctx_t *ctx); -ISC_APPFUNC_SCOPE isc_result_t isc__app_run(void); -ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxshutdown(isc_appctx_t *ctx); -ISC_APPFUNC_SCOPE isc_result_t isc__app_shutdown(void); -ISC_APPFUNC_SCOPE isc_result_t isc__app_reload(void); -ISC_APPFUNC_SCOPE isc_result_t isc__app_ctxsuspend(isc_appctx_t *ctx); -ISC_APPFUNC_SCOPE void isc__app_ctxfinish(isc_appctx_t *ctx); -ISC_APPFUNC_SCOPE void isc__app_finish(void); -ISC_APPFUNC_SCOPE void isc__app_block(void); -ISC_APPFUNC_SCOPE void isc__app_unblock(void); -ISC_APPFUNC_SCOPE isc_result_t isc__appctx_create(isc_mem_t *mctx, - isc_appctx_t **ctxp); -ISC_APPFUNC_SCOPE void isc__appctx_destroy(isc_appctx_t **ctxp); -ISC_APPFUNC_SCOPE void isc__appctx_settaskmgr(isc_appctx_t *ctx, - isc_taskmgr_t *taskmgr); -ISC_APPFUNC_SCOPE void isc__appctx_setsocketmgr(isc_appctx_t *ctx, - isc_socketmgr_t *socketmgr); -ISC_APPFUNC_SCOPE void isc__appctx_settimermgr(isc_appctx_t *ctx, - isc_timermgr_t *timermgr); - -/* - * The application context of this module. This implementation actually - * doesn't use it. (This may change in the future). - */ -#define APPCTX_MAGIC ISC_MAGIC('A', 'p', 'c', 'x') -#define VALID_APPCTX(c) ISC_MAGIC_VALID(c, APPCTX_MAGIC) - -typedef struct isc__appctx { - isc_appctx_t common; - isc_mem_t *mctx; - isc_mutex_t lock; - isc_eventlist_t on_run; - isc_boolean_t shutdown_requested; - isc_boolean_t running; - - /*! - * We assume that 'want_shutdown' can be read and written atomically. - */ - isc_boolean_t want_shutdown; - /* - * We assume that 'want_reload' can be read and written atomically. - */ - isc_boolean_t want_reload; - - isc_boolean_t blocked; - - isc_taskmgr_t *taskmgr; - isc_socketmgr_t *socketmgr; - isc_timermgr_t *timermgr; -} isc__appctx_t; - -static isc__appctx_t isc_g_appctx; - -static struct { - isc_appmethods_t methods; - - /*% - * The following are defined just for avoiding unused static functions. - */ -#ifndef BIND9 - void *run, *shutdown, *start, *onrun, *reload, *finish, - *block, *unblock; -#endif -} appmethods = { - { - isc__appctx_destroy, - isc__app_ctxstart, - isc__app_ctxrun, - isc__app_ctxsuspend, - isc__app_ctxshutdown, - isc__app_ctxfinish, - isc__appctx_settaskmgr, - isc__appctx_setsocketmgr, - isc__appctx_settimermgr - } -#ifndef BIND9 - , - (void *)isc__app_run, (void *)isc__app_shutdown, - (void *)isc__app_start, (void *)isc__app_onrun, (void *)isc__app_reload, - (void *)isc__app_finish, (void *)isc__app_block, - (void *)isc__app_unblock -#endif -}; - -#ifdef HAVE_LINUXTHREADS -/*! - * Linux has sigwait(), but it appears to prevent signal handlers from - * running, even if they're not in the set being waited for. This makes - * it impossible to get the default actions for SIGILL, SIGSEGV, etc. - * Instead of messing with it, we just use sigsuspend() instead. - */ -#undef HAVE_SIGWAIT -/*! - * We need to remember which thread is the main thread... - */ -static pthread_t main_thread; -#endif - -#ifndef HAVE_SIGWAIT -static void -exit_action(int arg) { - UNUSED(arg); - isc_g_appctx.want_shutdown = ISC_TRUE; -} - -static void -reload_action(int arg) { - UNUSED(arg); - isc_g_appctx.want_reload = ISC_TRUE; -} -#endif - -static isc_result_t -handle_signal(int sig, void (*handler)(int)) { - struct sigaction sa; - char strbuf[ISC_STRERRORSIZE]; - - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = handler; - - if (sigfillset(&sa.sa_mask) != 0 || - sigaction(sig, &sa, NULL) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, ISC_MSGSET_APP, - ISC_MSG_SIGNALSETUP, - "handle_signal() %d setup: %s"), - sig, strbuf); - return (ISC_R_UNEXPECTED); - } - - return (ISC_R_SUCCESS); -} - -ISC_APPFUNC_SCOPE isc_result_t -isc__app_ctxstart(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - isc_result_t result; - - REQUIRE(VALID_APPCTX(ctx)); - - /* - * Start an ISC library application. - */ - -#ifdef NEED_PTHREAD_INIT - /* - * BSDI 3.1 seg faults in pthread_sigmask() if we don't do this. - */ - presult = pthread_init(); - if (presult != 0) { - isc__strerror(presult, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_start() pthread_init: %s", strbuf); - return (ISC_R_UNEXPECTED); - } -#endif - -#ifdef HAVE_LINUXTHREADS - main_thread = pthread_self(); -#endif - - result = isc_mutex_init(&ctx->lock); - if (result != ISC_R_SUCCESS) - return (result); - - ISC_LIST_INIT(ctx->on_run); - - ctx->shutdown_requested = ISC_FALSE; - ctx->running = ISC_FALSE; - ctx->want_shutdown = ISC_FALSE; - ctx->want_reload = ISC_FALSE; - ctx->blocked = ISC_FALSE; - - return (ISC_R_SUCCESS); -} - -ISC_APPFUNC_SCOPE isc_result_t -isc__app_start(void) { - isc_result_t result; - int presult; - sigset_t sset; - char strbuf[ISC_STRERRORSIZE]; - - isc_g_appctx.common.impmagic = APPCTX_MAGIC; - isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC; - isc_g_appctx.common.methods = &appmethods.methods; - isc_g_appctx.mctx = NULL; - /* The remaining members will be initialized in ctxstart() */ - - result = isc__app_ctxstart((isc_appctx_t *)&isc_g_appctx); - if (result != ISC_R_SUCCESS) - return (result); - -#ifndef HAVE_SIGWAIT - /* - * Install do-nothing handlers for SIGINT and SIGTERM. - * - * We install them now because BSDI 3.1 won't block - * the default actions, regardless of what we do with - * pthread_sigmask(). - */ - result = handle_signal(SIGINT, exit_action); - if (result != ISC_R_SUCCESS) - return (result); - result = handle_signal(SIGTERM, exit_action); - if (result != ISC_R_SUCCESS) - return (result); -#endif - - /* - * Always ignore SIGPIPE. - */ - result = handle_signal(SIGPIPE, SIG_IGN); - if (result != ISC_R_SUCCESS) - return (result); - - /* - * On Solaris 2, delivery of a signal whose action is SIG_IGN - * will not cause sigwait() to return. We may have inherited - * unexpected actions for SIGHUP, SIGINT, and SIGTERM from our parent - * process (e.g, Solaris cron). Set an action of SIG_DFL to make - * sure sigwait() works as expected. Only do this for SIGTERM and - * SIGINT if we don't have sigwait(), since a different handler is - * installed above. - */ - result = handle_signal(SIGHUP, SIG_DFL); - if (result != ISC_R_SUCCESS) - return (result); - -#ifdef HAVE_SIGWAIT - result = handle_signal(SIGTERM, SIG_DFL); - if (result != ISC_R_SUCCESS) - return (result); - result = handle_signal(SIGINT, SIG_DFL); - if (result != ISC_R_SUCCESS) - return (result); -#endif - -#ifdef ISC_PLATFORM_USETHREADS - /* - * Block SIGHUP, SIGINT, SIGTERM. - * - * If isc_app_start() is called from the main thread before any other - * threads have been created, then the pthread_sigmask() call below - * will result in all threads having SIGHUP, SIGINT and SIGTERM - * blocked by default, ensuring that only the thread that calls - * sigwait() for them will get those signals. - */ - if (sigemptyset(&sset) != 0 || - sigaddset(&sset, SIGHUP) != 0 || - sigaddset(&sset, SIGINT) != 0 || - sigaddset(&sset, SIGTERM) != 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_start() sigsetops: %s", strbuf); - return (ISC_R_UNEXPECTED); - } - presult = pthread_sigmask(SIG_BLOCK, &sset, NULL); - if (presult != 0) { - isc__strerror(presult, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_start() pthread_sigmask: %s", - strbuf); - return (ISC_R_UNEXPECTED); - } -#else /* ISC_PLATFORM_USETHREADS */ - /* - * Unblock SIGHUP, SIGINT, SIGTERM. - * - * If we're not using threads, we need to make sure that SIGHUP, - * SIGINT and SIGTERM are not inherited as blocked from the parent - * process. - */ - if (sigemptyset(&sset) != 0 || - sigaddset(&sset, SIGHUP) != 0 || - sigaddset(&sset, SIGINT) != 0 || - sigaddset(&sset, SIGTERM) != 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_start() sigsetops: %s", strbuf); - return (ISC_R_UNEXPECTED); - } - presult = sigprocmask(SIG_UNBLOCK, &sset, NULL); - if (presult != 0) { - isc__strerror(presult, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_start() sigprocmask: %s", strbuf); - return (ISC_R_UNEXPECTED); - } -#endif /* ISC_PLATFORM_USETHREADS */ - - return (ISC_R_SUCCESS); -} - -ISC_APPFUNC_SCOPE isc_result_t -isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, - void *arg) -{ - isc_event_t *event; - isc_task_t *cloned_task = NULL; - isc_result_t result; - - LOCK(&isc_g_appctx.lock); - - if (isc_g_appctx.running) { - result = ISC_R_ALREADYRUNNING; - goto unlock; - } - - /* - * Note that we store the task to which we're going to send the event - * in the event's "sender" field. - */ - isc_task_attach(task, &cloned_task); - event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN, - action, arg, sizeof(*event)); - if (event == NULL) { - result = ISC_R_NOMEMORY; - goto unlock; - } - - ISC_LIST_APPEND(isc_g_appctx.on_run, event, ev_link); - - result = ISC_R_SUCCESS; - - unlock: - UNLOCK(&isc_g_appctx.lock); - - return (result); -} - -#ifndef USE_THREADS_SINGLECTX -/*! - * Event loop for nonthreaded programs. - */ -static isc_result_t -evloop(isc__appctx_t *ctx) { - isc_result_t result; - - while (!ctx->want_shutdown) { - int n; - isc_time_t when, now; - struct timeval tv, *tvp; - isc_socketwait_t *swait; - isc_boolean_t readytasks; - isc_boolean_t call_timer_dispatch = ISC_FALSE; - - /* - * Check the reload (or suspend) case first for exiting the - * loop as fast as possible in case: - * - the direct call to isc__taskmgr_dispatch() in - * isc__app_ctxrun() completes all the tasks so far, - * - there is thus currently no active task, and - * - there is a timer event - */ - if (ctx->want_reload) { - ctx->want_reload = ISC_FALSE; - return (ISC_R_RELOAD); - } - - readytasks = isc__taskmgr_ready(ctx->taskmgr); - if (readytasks) { - tv.tv_sec = 0; - tv.tv_usec = 0; - tvp = &tv; - call_timer_dispatch = ISC_TRUE; - } else { - result = isc__timermgr_nextevent(ctx->timermgr, &when); - if (result != ISC_R_SUCCESS) - tvp = NULL; - else { - isc_uint64_t us; - - TIME_NOW(&now); - us = isc_time_microdiff(&when, &now); - if (us == 0) - call_timer_dispatch = ISC_TRUE; - tv.tv_sec = us / 1000000; - tv.tv_usec = us % 1000000; - tvp = &tv; - } - } - - swait = NULL; - n = isc__socketmgr_waitevents(ctx->socketmgr, tvp, &swait); - - if (n == 0 || call_timer_dispatch) { - /* - * We call isc__timermgr_dispatch() only when - * necessary, in order to reduce overhead. If the - * select() call indicates a timeout, we need the - * dispatch. Even if not, if we set the 0-timeout - * for the select() call, we need to check the timer - * events. In the 'readytasks' case, there may be no - * timeout event actually, but there is no other way - * to reduce the overhead. - * Note that we do not have to worry about the case - * where a new timer is inserted during the select() - * call, since this loop only runs in the non-thread - * mode. - */ - isc__timermgr_dispatch(ctx->timermgr); - } - if (n > 0) - (void)isc__socketmgr_dispatch(ctx->socketmgr, swait); - (void)isc__taskmgr_dispatch(ctx->taskmgr); - } - return (ISC_R_SUCCESS); -} -#endif /* USE_THREADS_SINGLECTX */ - -#ifndef ISC_PLATFORM_USETHREADS -/* - * This is a gross hack to support waiting for condition - * variables in nonthreaded programs in a limited way; - * see lib/isc/nothreads/include/isc/condition.h. - * We implement isc_condition_wait() by entering the - * event loop recursively until the want_shutdown flag - * is set by isc_condition_signal(). - */ - -/*! - * \brief True if we are currently executing in the recursive - * event loop. - */ -static isc_boolean_t in_recursive_evloop = ISC_FALSE; - -/*! - * \brief True if we are exiting the event loop as the result of - * a call to isc_condition_signal() rather than a shutdown - * or reload. - */ -static isc_boolean_t signalled = ISC_FALSE; - -isc_result_t -isc__nothread_wait_hack(isc_condition_t *cp, isc_mutex_t *mp) { - isc_result_t result; - - UNUSED(cp); - UNUSED(mp); - - INSIST(!in_recursive_evloop); - in_recursive_evloop = ISC_TRUE; - - INSIST(*mp == 1); /* Mutex must be locked on entry. */ - --*mp; - - result = evloop(&isc_g_appctx); - if (result == ISC_R_RELOAD) - isc_g_appctx.want_reload = ISC_TRUE; - if (signalled) { - isc_g_appctx.want_shutdown = ISC_FALSE; - signalled = ISC_FALSE; - } - - ++*mp; - in_recursive_evloop = ISC_FALSE; - return (ISC_R_SUCCESS); -} - -isc_result_t -isc__nothread_signal_hack(isc_condition_t *cp) { - - UNUSED(cp); - - INSIST(in_recursive_evloop); - - isc_g_appctx.want_shutdown = ISC_TRUE; - signalled = ISC_TRUE; - return (ISC_R_SUCCESS); -} - -#endif /* ISC_PLATFORM_USETHREADS */ - -ISC_APPFUNC_SCOPE isc_result_t -isc__app_ctxrun(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - int result; - isc_event_t *event, *next_event; - isc_task_t *task; -#ifdef USE_THREADS_SINGLECTX - sigset_t sset; - char strbuf[ISC_STRERRORSIZE]; -#ifdef HAVE_SIGWAIT - int sig; -#endif -#endif /* USE_THREADS_SINGLECTX */ - - REQUIRE(VALID_APPCTX(ctx)); - -#ifdef HAVE_LINUXTHREADS - REQUIRE(main_thread == pthread_self()); -#endif - - LOCK(&ctx->lock); - - if (!ctx->running) { - ctx->running = ISC_TRUE; - - /* - * Post any on-run events (in FIFO order). - */ - for (event = ISC_LIST_HEAD(ctx->on_run); - event != NULL; - event = next_event) { - next_event = ISC_LIST_NEXT(event, ev_link); - ISC_LIST_UNLINK(ctx->on_run, event, ev_link); - task = event->ev_sender; - event->ev_sender = NULL; - isc_task_sendanddetach(&task, &event); - } - - } - - UNLOCK(&ctx->lock); - -#ifndef HAVE_SIGWAIT - /* - * Catch SIGHUP. - * - * We do this here to ensure that the signal handler is installed - * (i.e. that it wasn't a "one-shot" handler). - */ - if (ctx == &isc_g_appctx) { - result = handle_signal(SIGHUP, reload_action); - if (result != ISC_R_SUCCESS) - return (ISC_R_SUCCESS); - } -#endif - -#ifdef USE_THREADS_SINGLECTX - /* - * When we are using multiple contexts, we don't rely on signals. - */ - if (ctx != &isc_g_appctx) - return (ISC_R_SUCCESS); - - /* - * There is no danger if isc_app_shutdown() is called before we wait - * for signals. Signals are blocked, so any such signal will simply - * be made pending and we will get it when we call sigwait(). - */ - - while (!ctx->want_shutdown) { -#ifdef HAVE_SIGWAIT - /* - * Wait for SIGHUP, SIGINT, or SIGTERM. - */ - if (sigemptyset(&sset) != 0 || - sigaddset(&sset, SIGHUP) != 0 || - sigaddset(&sset, SIGINT) != 0 || - sigaddset(&sset, SIGTERM) != 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_run() sigsetops: %s", strbuf); - return (ISC_R_UNEXPECTED); - } - -#ifndef HAVE_UNIXWARE_SIGWAIT - result = sigwait(&sset, &sig); - if (result == 0) { - if (sig == SIGINT || sig == SIGTERM) - ctx->want_shutdown = ISC_TRUE; - else if (sig == SIGHUP) - ctx->want_reload = ISC_TRUE; - } - -#else /* Using UnixWare sigwait semantics. */ - sig = sigwait(&sset); - if (sig >= 0) { - if (sig == SIGINT || sig == SIGTERM) - ctx->want_shutdown = ISC_TRUE; - else if (sig == SIGHUP) - ctx->want_reload = ISC_TRUE; - } - -#endif /* HAVE_UNIXWARE_SIGWAIT */ -#else /* Don't have sigwait(). */ - /* - * Listen for all signals. - */ - if (sigemptyset(&sset) != 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_run() sigsetops: %s", - strbuf); - return (ISC_R_UNEXPECTED); - } - result = sigsuspend(&sset); -#endif /* HAVE_SIGWAIT */ - - if (ctx->want_reload) { - ctx->want_reload = ISC_FALSE; - return (ISC_R_RELOAD); - } - - if (ctx->want_shutdown && ctx->blocked) - exit(1); - } - -#else /* USE_THREADS_SINGLECTX */ - - (void)isc__taskmgr_dispatch(ctx->taskmgr); - - result = evloop(ctx); - if (result != ISC_R_SUCCESS) - return (result); - -#endif /* USE_THREADS_SINGLECTX */ - - return (ISC_R_SUCCESS); -} - -ISC_APPFUNC_SCOPE isc_result_t -isc__app_run() { - return (isc__app_ctxrun((isc_appctx_t *)&isc_g_appctx)); -} - -ISC_APPFUNC_SCOPE isc_result_t -isc__app_ctxshutdown(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - isc_boolean_t want_kill = ISC_TRUE; - char strbuf[ISC_STRERRORSIZE]; - - REQUIRE(VALID_APPCTX(ctx)); - - LOCK(&ctx->lock); - - REQUIRE(ctx->running); - - if (ctx->shutdown_requested) - want_kill = ISC_FALSE; - else - ctx->shutdown_requested = ISC_TRUE; - - UNLOCK(&ctx->lock); - - if (want_kill) { - if (ctx != &isc_g_appctx) - ctx->want_shutdown = ISC_TRUE; - else { -#ifdef HAVE_LINUXTHREADS - int result; - - result = pthread_kill(main_thread, SIGTERM); - if (result != 0) { - isc__strerror(result, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_shutdown() " - "pthread_kill: %s", - strbuf); - return (ISC_R_UNEXPECTED); - } -#else - if (kill(getpid(), SIGTERM) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_shutdown() " - "kill: %s", strbuf); - return (ISC_R_UNEXPECTED); - } -#endif /* HAVE_LINUXTHREADS */ - } - } - - return (ISC_R_SUCCESS); -} - -ISC_APPFUNC_SCOPE isc_result_t -isc__app_shutdown() { - return (isc__app_ctxshutdown((isc_appctx_t *)&isc_g_appctx)); -} - -ISC_APPFUNC_SCOPE isc_result_t -isc__app_ctxsuspend(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - isc_boolean_t want_kill = ISC_TRUE; - char strbuf[ISC_STRERRORSIZE]; - - REQUIRE(VALID_APPCTX(ctx)); - - LOCK(&ctx->lock); - - REQUIRE(ctx->running); - - /* - * Don't send the reload signal if we're shutting down. - */ - if (ctx->shutdown_requested) - want_kill = ISC_FALSE; - - UNLOCK(&ctx->lock); - - if (want_kill) { - if (ctx != &isc_g_appctx) - ctx->want_reload = ISC_TRUE; - else { -#ifdef HAVE_LINUXTHREADS - int result; - - result = pthread_kill(main_thread, SIGHUP); - if (result != 0) { - isc__strerror(result, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_reload() " - "pthread_kill: %s", - strbuf); - return (ISC_R_UNEXPECTED); - } -#else - if (kill(getpid(), SIGHUP) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_reload() " - "kill: %s", strbuf); - return (ISC_R_UNEXPECTED); - } -#endif - } - } - - return (ISC_R_SUCCESS); -} - -ISC_APPFUNC_SCOPE isc_result_t -isc__app_reload(void) { - return (isc__app_ctxsuspend((isc_appctx_t *)&isc_g_appctx)); -} - -ISC_APPFUNC_SCOPE void -isc__app_ctxfinish(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - - REQUIRE(VALID_APPCTX(ctx)); - - DESTROYLOCK(&ctx->lock); -} - -ISC_APPFUNC_SCOPE void -isc__app_finish(void) { - isc__app_ctxfinish((isc_appctx_t *)&isc_g_appctx); -} - -ISC_APPFUNC_SCOPE void -isc__app_block(void) { -#ifdef ISC_PLATFORM_USETHREADS - sigset_t sset; -#endif /* ISC_PLATFORM_USETHREADS */ - REQUIRE(isc_g_appctx.running); - REQUIRE(!isc_g_appctx.blocked); - - isc_g_appctx.blocked = ISC_TRUE; -#ifdef ISC_PLATFORM_USETHREADS - blockedthread = pthread_self(); - RUNTIME_CHECK(sigemptyset(&sset) == 0 && - sigaddset(&sset, SIGINT) == 0 && - sigaddset(&sset, SIGTERM) == 0); - RUNTIME_CHECK(pthread_sigmask(SIG_UNBLOCK, &sset, NULL) == 0); -#endif /* ISC_PLATFORM_USETHREADS */ -} - -ISC_APPFUNC_SCOPE void -isc__app_unblock(void) { -#ifdef ISC_PLATFORM_USETHREADS - sigset_t sset; -#endif /* ISC_PLATFORM_USETHREADS */ - - REQUIRE(isc_g_appctx.running); - REQUIRE(isc_g_appctx.blocked); - - isc_g_appctx.blocked = ISC_FALSE; - -#ifdef ISC_PLATFORM_USETHREADS - REQUIRE(blockedthread == pthread_self()); - - RUNTIME_CHECK(sigemptyset(&sset) == 0 && - sigaddset(&sset, SIGINT) == 0 && - sigaddset(&sset, SIGTERM) == 0); - RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0); -#endif /* ISC_PLATFORM_USETHREADS */ -} - -ISC_APPFUNC_SCOPE isc_result_t -isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) { - isc__appctx_t *ctx; - - REQUIRE(mctx != NULL); - REQUIRE(ctxp != NULL && *ctxp == NULL); - - ctx = isc_mem_get(mctx, sizeof(*ctx)); - if (ctx == NULL) - return (ISC_R_NOMEMORY); - - ctx->common.impmagic = APPCTX_MAGIC; - ctx->common.magic = ISCAPI_APPCTX_MAGIC; - ctx->common.methods = &appmethods.methods; - - ctx->mctx = NULL; - isc_mem_attach(mctx, &ctx->mctx); - - ctx->taskmgr = NULL; - ctx->socketmgr = NULL; - ctx->timermgr = NULL; - - *ctxp = (isc_appctx_t *)ctx; - - return (ISC_R_SUCCESS); -} - -ISC_APPFUNC_SCOPE void -isc__appctx_destroy(isc_appctx_t **ctxp) { - isc__appctx_t *ctx; - - REQUIRE(ctxp != NULL); - ctx = (isc__appctx_t *)*ctxp; - REQUIRE(VALID_APPCTX(ctx)); - - isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx)); - - *ctxp = NULL; -} - -ISC_APPFUNC_SCOPE void -isc__appctx_settaskmgr(isc_appctx_t *ctx0, isc_taskmgr_t *taskmgr) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - - REQUIRE(VALID_APPCTX(ctx)); - - ctx->taskmgr = taskmgr; -} - -ISC_APPFUNC_SCOPE void -isc__appctx_setsocketmgr(isc_appctx_t *ctx0, isc_socketmgr_t *socketmgr) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - - REQUIRE(VALID_APPCTX(ctx)); - - ctx->socketmgr = socketmgr; -} - -ISC_APPFUNC_SCOPE void -isc__appctx_settimermgr(isc_appctx_t *ctx0, isc_timermgr_t *timermgr) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - - REQUIRE(VALID_APPCTX(ctx)); - - ctx->timermgr = timermgr; -} - -#ifdef USE_APPIMPREGISTER -isc_result_t -isc__app_register() { - return (isc_app_register(isc__appctx_create)); -} -#endif diff --git a/contrib/bind9/lib/isc/unix/dir.c b/contrib/bind9/lib/isc/unix/dir.c deleted file mode 100644 index 0d64778..0000000 --- a/contrib/bind9/lib/isc/unix/dir.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id$ */ - -/*! \file - * \author Principal Authors: DCL */ - -#include <config.h> - -#include <sys/types.h> -#include <sys/stat.h> - -#include <ctype.h> -#include <errno.h> -#include <unistd.h> - -#include <isc/dir.h> -#include <isc/magic.h> -#include <isc/string.h> -#include <isc/util.h> - -#include "errno2result.h" - -#define ISC_DIR_MAGIC ISC_MAGIC('D', 'I', 'R', '*') -#define VALID_DIR(dir) ISC_MAGIC_VALID(dir, ISC_DIR_MAGIC) - -void -isc_dir_init(isc_dir_t *dir) { - REQUIRE(dir != NULL); - - dir->entry.name[0] = '\0'; - dir->entry.length = 0; - - dir->handle = NULL; - - dir->magic = ISC_DIR_MAGIC; -} - -/*! - * \brief Allocate workspace and open directory stream. If either one fails, - * NULL will be returned. - */ -isc_result_t -isc_dir_open(isc_dir_t *dir, const char *dirname) { - char *p; - isc_result_t result = ISC_R_SUCCESS; - - REQUIRE(VALID_DIR(dir)); - REQUIRE(dirname != NULL); - - /* - * Copy directory name. Need to have enough space for the name, - * a possible path separator, the wildcard, and the final NUL. - */ - if (strlen(dirname) + 3 > sizeof(dir->dirname)) - /* XXXDCL ? */ - return (ISC_R_NOSPACE); - strcpy(dir->dirname, dirname); - - /* - * Append path separator, if needed, and "*". - */ - p = dir->dirname + strlen(dir->dirname); - if (dir->dirname < p && *(p - 1) != '/') - *p++ = '/'; - *p++ = '*'; - *p = '\0'; - - /* - * Open stream. - */ - dir->handle = opendir(dirname); - - if (dir->handle == NULL) - return isc__errno2result(errno); - - return (result); -} - -/*! - * \brief Return previously retrieved file or get next one. - - * Unix's dirent has - * separate open and read functions, but the Win32 and DOS interfaces open - * the dir stream and reads the first file in one operation. - */ -isc_result_t -isc_dir_read(isc_dir_t *dir) { - struct dirent *entry; - - REQUIRE(VALID_DIR(dir) && dir->handle != NULL); - - /* - * Fetch next file in directory. - */ - entry = readdir(dir->handle); - - if (entry == NULL) - return (ISC_R_NOMORE); - - /* - * Make sure that the space for the name is long enough. - */ - if (sizeof(dir->entry.name) <= strlen(entry->d_name)) - return (ISC_R_UNEXPECTED); - - strcpy(dir->entry.name, entry->d_name); - - /* - * Some dirents have d_namlen, but it is not portable. - */ - dir->entry.length = strlen(entry->d_name); - - return (ISC_R_SUCCESS); -} - -/*! - * \brief Close directory stream. - */ -void -isc_dir_close(isc_dir_t *dir) { - REQUIRE(VALID_DIR(dir) && dir->handle != NULL); - - (void)closedir(dir->handle); - dir->handle = NULL; -} - -/*! - * \brief Reposition directory stream at start. - */ -isc_result_t -isc_dir_reset(isc_dir_t *dir) { - REQUIRE(VALID_DIR(dir) && dir->handle != NULL); - - rewinddir(dir->handle); - - return (ISC_R_SUCCESS); -} - -isc_result_t -isc_dir_chdir(const char *dirname) { - /*! - * \brief Change the current directory to 'dirname'. - */ - - REQUIRE(dirname != NULL); - - if (chdir(dirname) < 0) - return (isc__errno2result(errno)); - - return (ISC_R_SUCCESS); -} - -isc_result_t -isc_dir_chroot(const char *dirname) { - - REQUIRE(dirname != NULL); - -#ifdef HAVE_CHROOT - if (chroot(dirname) < 0 || chdir("/") < 0) - return (isc__errno2result(errno)); - - return (ISC_R_SUCCESS); -#else - return (ISC_R_NOTIMPLEMENTED); -#endif -} - -isc_result_t -isc_dir_createunique(char *templet) { - isc_result_t result; - char *x; - char *p; - int i; - int pid; - - REQUIRE(templet != NULL); - - /*! - * \brief mkdtemp is not portable, so this emulates it. - */ - - pid = getpid(); - - /* - * Replace trailing Xs with the process-id, zero-filled. - */ - for (x = templet + strlen(templet) - 1; *x == 'X' && x >= templet; - x--, pid /= 10) - *x = pid % 10 + '0'; - - x++; /* Set x to start of ex-Xs. */ - - do { - i = mkdir(templet, 0700); - if (i == 0 || errno != EEXIST) - break; - - /* - * The BSD algorithm. - */ - p = x; - while (*p != '\0') { - if (isdigit(*p & 0xff)) - *p = 'a'; - else if (*p != 'z') - ++*p; - else { - /* - * Reset character and move to next. - */ - *p++ = 'a'; - continue; - } - - break; - } - - if (*p == '\0') { - /* - * Tried all combinations. errno should already - * be EEXIST, but ensure it is anyway for - * isc__errno2result(). - */ - errno = EEXIST; - break; - } - } while (1); - - if (i == -1) - result = isc__errno2result(errno); - else - result = ISC_R_SUCCESS; - - return (result); -} diff --git a/contrib/bind9/lib/isc/unix/entropy.c b/contrib/bind9/lib/isc/unix/entropy.c deleted file mode 100644 index 9c422b5..0000000 --- a/contrib/bind9/lib/isc/unix/entropy.c +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Copyright (C) 2004-2008, 2012 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2000-2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: entropy.c,v 1.82 2008/12/01 23:47:45 tbox Exp $ */ - -/* \file unix/entropy.c - * \brief - * This is the system dependent part of the ISC entropy API. - */ - -#include <config.h> - -#include <sys/param.h> /* Openserver 5.0.6A and FD_SETSIZE */ -#include <sys/types.h> -#include <sys/time.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/un.h> - -#ifdef HAVE_NANOSLEEP -#include <time.h> -#endif -#include <unistd.h> - -#include <isc/platform.h> -#include <isc/strerror.h> - -#ifdef ISC_PLATFORM_NEEDSYSSELECTH -#include <sys/select.h> -#endif - -#include "errno2result.h" - -/*% - * There is only one variable in the entropy data structures that is not - * system independent, but pulling the structure that uses it into this file - * ultimately means pulling several other independent structures here also to - * resolve their interdependencies. Thus only the problem variable's type - * is defined here. - */ -#define FILESOURCE_HANDLE_TYPE int - -typedef struct { - int handle; - enum { - isc_usocketsource_disconnected, - isc_usocketsource_connecting, - isc_usocketsource_connected, - isc_usocketsource_ndesired, - isc_usocketsource_wrote, - isc_usocketsource_reading - } status; - size_t sz_to_recv; -} isc_entropyusocketsource_t; - -#include "../entropy.c" - -static unsigned int -get_from_filesource(isc_entropysource_t *source, isc_uint32_t desired) { - isc_entropy_t *ent = source->ent; - unsigned char buf[128]; - int fd = source->sources.file.handle; - ssize_t n, ndesired; - unsigned int added; - - if (source->bad) - return (0); - - desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0); - - added = 0; - while (desired > 0) { - ndesired = ISC_MIN(desired, sizeof(buf)); - n = read(fd, buf, ndesired); - if (n < 0) { - if (errno == EAGAIN || errno == EINTR) - goto out; - goto err; - } - if (n == 0) - goto err; - - entropypool_adddata(ent, buf, n, n * 8); - added += n * 8; - desired -= n; - } - goto out; - - err: - (void)close(fd); - source->sources.file.handle = -1; - source->bad = ISC_TRUE; - - out: - return (added); -} - -static unsigned int -get_from_usocketsource(isc_entropysource_t *source, isc_uint32_t desired) { - isc_entropy_t *ent = source->ent; - unsigned char buf[128]; - int fd = source->sources.usocket.handle; - ssize_t n = 0, ndesired; - unsigned int added; - size_t sz_to_recv = source->sources.usocket.sz_to_recv; - - if (source->bad) - return (0); - - desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0); - - added = 0; - while (desired > 0) { - ndesired = ISC_MIN(desired, sizeof(buf)); - eagain_loop: - - switch ( source->sources.usocket.status ) { - case isc_usocketsource_ndesired: - buf[0] = ndesired; - if ((n = sendto(fd, buf, 1, 0, NULL, 0)) < 0) { - if (errno == EWOULDBLOCK || errno == EINTR || - errno == ECONNRESET) - goto out; - goto err; - } - INSIST(n == 1); - source->sources.usocket.status = - isc_usocketsource_wrote; - goto eagain_loop; - - case isc_usocketsource_connecting: - case isc_usocketsource_connected: - buf[0] = 1; - buf[1] = ndesired; - if ((n = sendto(fd, buf, 2, 0, NULL, 0)) < 0) { - if (errno == EWOULDBLOCK || errno == EINTR || - errno == ECONNRESET) - goto out; - goto err; - } - if (n == 1) { - source->sources.usocket.status = - isc_usocketsource_ndesired; - goto eagain_loop; - } - INSIST(n == 2); - source->sources.usocket.status = - isc_usocketsource_wrote; - /*FALLTHROUGH*/ - - case isc_usocketsource_wrote: - if (recvfrom(fd, buf, 1, 0, NULL, NULL) != 1) { - if (errno == EAGAIN) { - /* - * The problem of EAGAIN (try again - * later) is a major issue on HP-UX. - * Solaris actually tries the recvfrom - * call again, while HP-UX just dies. - * This code is an attempt to let the - * entropy pool fill back up (at least - * that's what I think the problem is.) - * We go to eagain_loop because if we - * just "break", then the "desired" - * amount gets borked. - */ -#ifdef HAVE_NANOSLEEP - struct timespec ts; - - ts.tv_sec = 0; - ts.tv_nsec = 1000000; - nanosleep(&ts, NULL); -#else - usleep(1000); -#endif - goto eagain_loop; - } - if (errno == EWOULDBLOCK || errno == EINTR) - goto out; - goto err; - } - source->sources.usocket.status = - isc_usocketsource_reading; - sz_to_recv = buf[0]; - source->sources.usocket.sz_to_recv = sz_to_recv; - if (sz_to_recv > sizeof(buf)) - goto err; - /*FALLTHROUGH*/ - - case isc_usocketsource_reading: - if (sz_to_recv != 0U) { - n = recv(fd, buf, sz_to_recv, 0); - if (n < 0) { - if (errno == EWOULDBLOCK || - errno == EINTR) - goto out; - goto err; - } - } else - n = 0; - break; - - default: - goto err; - } - - if ((size_t)n != sz_to_recv) - source->sources.usocket.sz_to_recv -= n; - else - source->sources.usocket.status = - isc_usocketsource_connected; - - if (n == 0) - goto out; - - entropypool_adddata(ent, buf, n, n * 8); - added += n * 8; - desired -= n; - } - goto out; - - err: - close(fd); - source->bad = ISC_TRUE; - source->sources.usocket.status = isc_usocketsource_disconnected; - source->sources.usocket.handle = -1; - - out: - return (added); -} - -/* - * Poll each source, trying to get data from it to stuff into the entropy - * pool. - */ -static void -fillpool(isc_entropy_t *ent, unsigned int desired, isc_boolean_t blocking) { - unsigned int added; - unsigned int remaining; - unsigned int needed; - unsigned int nsource; - isc_entropysource_t *source; - - REQUIRE(VALID_ENTROPY(ent)); - - needed = desired; - - /* - * This logic is a little strange, so an explanation is in order. - * - * If needed is 0, it means we are being asked to "fill to whatever - * we think is best." This means that if we have at least a - * partially full pool (say, > 1/4th of the pool) we probably don't - * need to add anything. - * - * Also, we will check to see if the "pseudo" count is too high. - * If it is, try to mix in better data. Too high is currently - * defined as 1/4th of the pool. - * - * Next, if we are asked to add a specific bit of entropy, make - * certain that we will do so. Clamp how much we try to add to - * (DIGEST_SIZE * 8 < needed < POOLBITS - entropy). - * - * Note that if we are in a blocking mode, we will only try to - * get as much data as we need, not as much as we might want - * to build up. - */ - if (needed == 0) { - REQUIRE(!blocking); - - if ((ent->pool.entropy >= RND_POOLBITS / 4) - && (ent->pool.pseudo <= RND_POOLBITS / 4)) - return; - - needed = THRESHOLD_BITS * 4; - } else { - needed = ISC_MAX(needed, THRESHOLD_BITS); - needed = ISC_MIN(needed, RND_POOLBITS); - } - - /* - * In any case, clamp how much we need to how much we can add. - */ - needed = ISC_MIN(needed, RND_POOLBITS - ent->pool.entropy); - - /* - * But wait! If we're not yet initialized, we need at least - * THRESHOLD_BITS - * of randomness. - */ - if (ent->initialized < THRESHOLD_BITS) - needed = ISC_MAX(needed, THRESHOLD_BITS - ent->initialized); - - /* - * Poll each file source to see if we can read anything useful from - * it. XXXMLG When where are multiple sources, we should keep a - * record of which one we last used so we can start from it (or the - * next one) to avoid letting some sources build up entropy while - * others are always drained. - */ - - added = 0; - remaining = needed; - if (ent->nextsource == NULL) { - ent->nextsource = ISC_LIST_HEAD(ent->sources); - if (ent->nextsource == NULL) - return; - } - source = ent->nextsource; - again_file: - for (nsource = 0; nsource < ent->nsources; nsource++) { - unsigned int got; - - if (remaining == 0) - break; - - got = 0; - - switch ( source->type ) { - case ENTROPY_SOURCETYPE_FILE: - got = get_from_filesource(source, remaining); - break; - - case ENTROPY_SOURCETYPE_USOCKET: - got = get_from_usocketsource(source, remaining); - break; - } - - added += got; - - remaining -= ISC_MIN(remaining, got); - - source = ISC_LIST_NEXT(source, link); - if (source == NULL) - source = ISC_LIST_HEAD(ent->sources); - } - ent->nextsource = source; - - if (blocking && remaining != 0) { - int fds; - - fds = wait_for_sources(ent); - if (fds > 0) - goto again_file; - } - - /* - * Here, if there are bits remaining to be had and we can block, - * check to see if we have a callback source. If so, call them. - */ - source = ISC_LIST_HEAD(ent->sources); - while ((remaining != 0) && (source != NULL)) { - unsigned int got; - - got = 0; - - if (source->type == ENTROPY_SOURCETYPE_CALLBACK) - got = get_from_callback(source, remaining, blocking); - - added += got; - remaining -= ISC_MIN(remaining, got); - - if (added >= needed) - break; - - source = ISC_LIST_NEXT(source, link); - } - - /* - * Mark as initialized if we've added enough data. - */ - if (ent->initialized < THRESHOLD_BITS) - ent->initialized += added; -} - -static int -wait_for_sources(isc_entropy_t *ent) { - isc_entropysource_t *source; - int maxfd, fd; - int cc; - fd_set reads; - fd_set writes; - - maxfd = -1; - FD_ZERO(&reads); - FD_ZERO(&writes); - - source = ISC_LIST_HEAD(ent->sources); - while (source != NULL) { - if (source->type == ENTROPY_SOURCETYPE_FILE) { - fd = source->sources.file.handle; - if (fd >= 0) { - maxfd = ISC_MAX(maxfd, fd); - FD_SET(fd, &reads); - } - } - if (source->type == ENTROPY_SOURCETYPE_USOCKET) { - fd = source->sources.usocket.handle; - if (fd >= 0) { - switch (source->sources.usocket.status) { - case isc_usocketsource_disconnected: - break; - case isc_usocketsource_connecting: - case isc_usocketsource_connected: - case isc_usocketsource_ndesired: - maxfd = ISC_MAX(maxfd, fd); - FD_SET(fd, &writes); - break; - case isc_usocketsource_wrote: - case isc_usocketsource_reading: - maxfd = ISC_MAX(maxfd, fd); - FD_SET(fd, &reads); - break; - } - } - } - source = ISC_LIST_NEXT(source, link); - } - - if (maxfd < 0) - return (-1); - - cc = select(maxfd + 1, &reads, &writes, NULL, NULL); - if (cc < 0) - return (-1); - - return (cc); -} - -static void -destroyfilesource(isc_entropyfilesource_t *source) { - (void)close(source->handle); -} - -static void -destroyusocketsource(isc_entropyusocketsource_t *source) { - close(source->handle); -} - -/* - * Make a fd non-blocking - */ -static isc_result_t -make_nonblock(int fd) { - int ret; - int flags; - char strbuf[ISC_STRERRORSIZE]; -#ifdef USE_FIONBIO_IOCTL - int on = 1; - - ret = ioctl(fd, FIONBIO, (char *)&on); -#else - flags = fcntl(fd, F_GETFL, 0); - flags |= PORT_NONBLOCK; - ret = fcntl(fd, F_SETFL, flags); -#endif - - if (ret == -1) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, -#ifdef USE_FIONBIO_IOCTL - "ioctl(%d, FIONBIO, &on): %s", fd, -#else - "fcntl(%d, F_SETFL, %d): %s", fd, flags, -#endif - strbuf); - - return (ISC_R_UNEXPECTED); - } - - return (ISC_R_SUCCESS); -} - -isc_result_t -isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) { - int fd; - struct stat _stat; - isc_boolean_t is_usocket = ISC_FALSE; - isc_boolean_t is_connected = ISC_FALSE; - isc_result_t ret; - isc_entropysource_t *source; - - REQUIRE(VALID_ENTROPY(ent)); - REQUIRE(fname != NULL); - - LOCK(&ent->lock); - - if (stat(fname, &_stat) < 0) { - ret = isc__errno2result(errno); - goto errout; - } - /* - * Solaris 2.5.1 does not have support for sockets (S_IFSOCK), - * but it does return type S_IFIFO (the OS believes that - * the socket is a fifo). This may be an issue if we tell - * the program to look at an actual FIFO as its source of - * entropy. - */ -#if defined(S_ISSOCK) - if (S_ISSOCK(_stat.st_mode)) - is_usocket = ISC_TRUE; -#endif -#if defined(S_ISFIFO) && defined(sun) - if (S_ISFIFO(_stat.st_mode)) - is_usocket = ISC_TRUE; -#endif - if (is_usocket) - fd = socket(PF_UNIX, SOCK_STREAM, 0); - else - fd = open(fname, O_RDONLY | PORT_NONBLOCK, 0); - - if (fd < 0) { - ret = isc__errno2result(errno); - goto errout; - } - - ret = make_nonblock(fd); - if (ret != ISC_R_SUCCESS) - goto closefd; - - if (is_usocket) { - struct sockaddr_un sname; - - memset(&sname, 0, sizeof(sname)); - sname.sun_family = AF_UNIX; - strlcpy(sname.sun_path, fname, sizeof(sname.sun_path)); -#ifdef ISC_PLATFORM_HAVESALEN -#if !defined(SUN_LEN) -#define SUN_LEN(su) \ - (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) -#endif - sname.sun_len = SUN_LEN(&sname); -#endif - - if (connect(fd, (struct sockaddr *) &sname, - sizeof(struct sockaddr_un)) < 0) { - if (errno != EINPROGRESS) { - ret = isc__errno2result(errno); - goto closefd; - } - } else - is_connected = ISC_TRUE; - } - - source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t)); - if (source == NULL) { - ret = ISC_R_NOMEMORY; - goto closefd; - } - - /* - * From here down, no failures can occur. - */ - source->magic = SOURCE_MAGIC; - source->ent = ent; - source->total = 0; - source->bad = ISC_FALSE; - memset(source->name, 0, sizeof(source->name)); - ISC_LINK_INIT(source, link); - if (is_usocket) { - source->sources.usocket.handle = fd; - if (is_connected) - source->sources.usocket.status = - isc_usocketsource_connected; - else - source->sources.usocket.status = - isc_usocketsource_connecting; - source->sources.usocket.sz_to_recv = 0; - source->type = ENTROPY_SOURCETYPE_USOCKET; - } else { - source->sources.file.handle = fd; - source->type = ENTROPY_SOURCETYPE_FILE; - } - - /* - * Hook it into the entropy system. - */ - ISC_LIST_APPEND(ent->sources, source, link); - ent->nsources++; - - UNLOCK(&ent->lock); - return (ISC_R_SUCCESS); - - closefd: - (void)close(fd); - - errout: - UNLOCK(&ent->lock); - - return (ret); -} diff --git a/contrib/bind9/lib/isc/unix/errno2result.c b/contrib/bind9/lib/isc/unix/errno2result.c deleted file mode 100644 index f20aa29..0000000 --- a/contrib/bind9/lib/isc/unix/errno2result.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2000-2002 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id$ */ - -/*! \file */ - -#include <config.h> - -#include <isc/result.h> -#include <isc/strerror.h> -#include <isc/util.h> - -#include "errno2result.h" - -/*% - * Convert a POSIX errno value into an isc_result_t. The - * list of supported errno values is not complete; new users - * of this function should add any expected errors that are - * not already there. - */ -isc_result_t -isc___errno2result(int posixerrno, const char *file, unsigned int line) { - char strbuf[ISC_STRERRORSIZE]; - - switch (posixerrno) { - case ENOTDIR: - case ELOOP: - case EINVAL: /* XXX sometimes this is not for files */ - case ENAMETOOLONG: - case EBADF: - return (ISC_R_INVALIDFILE); - case ENOENT: - return (ISC_R_FILENOTFOUND); - case EACCES: - case EPERM: - return (ISC_R_NOPERM); - case EEXIST: - return (ISC_R_FILEEXISTS); - case EIO: - return (ISC_R_IOERROR); - case ENOMEM: - return (ISC_R_NOMEMORY); - case ENFILE: - case EMFILE: - return (ISC_R_TOOMANYOPENFILES); - case EPIPE: -#ifdef ECONNRESET - case ECONNRESET: -#endif -#ifdef ECONNABORTED - case ECONNABORTED: -#endif - return (ISC_R_CONNECTIONRESET); -#ifdef ENOTCONN - case ENOTCONN: - return (ISC_R_NOTCONNECTED); -#endif -#ifdef ETIMEDOUT - case ETIMEDOUT: - return (ISC_R_TIMEDOUT); -#endif -#ifdef ENOBUFS - case ENOBUFS: - return (ISC_R_NORESOURCES); -#endif -#ifdef EAFNOSUPPORT - case EAFNOSUPPORT: - return (ISC_R_FAMILYNOSUPPORT); -#endif -#ifdef ENETDOWN - case ENETDOWN: - return (ISC_R_NETDOWN); -#endif -#ifdef EHOSTDOWN - case EHOSTDOWN: - return (ISC_R_HOSTDOWN); -#endif -#ifdef ENETUNREACH - case ENETUNREACH: - return (ISC_R_NETUNREACH); -#endif -#ifdef EHOSTUNREACH - case EHOSTUNREACH: - return (ISC_R_HOSTUNREACH); -#endif -#ifdef EADDRINUSE - case EADDRINUSE: - return (ISC_R_ADDRINUSE); -#endif - case EADDRNOTAVAIL: - return (ISC_R_ADDRNOTAVAIL); - case ECONNREFUSED: - return (ISC_R_CONNREFUSED); - default: - isc__strerror(posixerrno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(file, line, "unable to convert errno " - "to isc_result: %d: %s", - posixerrno, strbuf); - /* - * XXXDCL would be nice if perhaps this function could - * return the system's error string, so the caller - * might have something more descriptive than "unexpected - * error" to log with. - */ - return (ISC_R_UNEXPECTED); - } -} diff --git a/contrib/bind9/lib/isc/unix/errno2result.h b/contrib/bind9/lib/isc/unix/errno2result.h deleted file mode 100644 index 1e49ed1..0000000 --- a/contrib/bind9/lib/isc/unix/errno2result.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2000, 2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id$ */ - -#ifndef UNIX_ERRNO2RESULT_H -#define UNIX_ERRNO2RESULT_H 1 - -/*! \file */ - -/* XXXDCL this should be moved to lib/isc/include/isc/errno2result.h. */ - -#include <errno.h> /* Provides errno. */ - -#include <isc/lang.h> -#include <isc/types.h> - -ISC_LANG_BEGINDECLS - -#define isc__errno2result(x) isc___errno2result(x, __FILE__, __LINE__) - -isc_result_t -isc___errno2result(int posixerrno, const char *file, unsigned int line); - -ISC_LANG_ENDDECLS - -#endif /* UNIX_ERRNO2RESULT_H */ diff --git a/contrib/bind9/lib/isc/unix/file.c b/contrib/bind9/lib/isc/unix/file.c deleted file mode 100644 index 7bb25d7..0000000 --- a/contrib/bind9/lib/isc/unix/file.c +++ /dev/null @@ -1,593 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2000-2002 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Portions Copyright (c) 1987, 1993 - * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. - */ - -/* $Id$ */ - -/*! \file */ - -#include <config.h> - -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stdlib.h> -#include <time.h> /* Required for utimes on some platforms. */ -#include <unistd.h> /* Required for mkstemp on NetBSD. */ - - -#include <sys/stat.h> -#include <sys/time.h> - -#include <isc/dir.h> -#include <isc/file.h> -#include <isc/log.h> -#include <isc/mem.h> -#include <isc/random.h> -#include <isc/string.h> -#include <isc/time.h> -#include <isc/util.h> - -#include "errno2result.h" - -/* - * XXXDCL As the API for accessing file statistics undoubtedly gets expanded, - * it might be good to provide a mechanism that allows for the results - * of a previous stat() to be used again without having to do another stat, - * such as perl's mechanism of using "_" in place of a file name to indicate - * that the results of the last stat should be used. But then you get into - * annoying MP issues. BTW, Win32 has stat(). - */ -static isc_result_t -file_stats(const char *file, struct stat *stats) { - isc_result_t result = ISC_R_SUCCESS; - - REQUIRE(file != NULL); - REQUIRE(stats != NULL); - - if (stat(file, stats) != 0) - result = isc__errno2result(errno); - - return (result); -} - -isc_result_t -isc_file_mode(const char *file, mode_t *modep) { - isc_result_t result; - struct stat stats; - - REQUIRE(modep != NULL); - - result = file_stats(file, &stats); - if (result == ISC_R_SUCCESS) - *modep = (stats.st_mode & 07777); - - return (result); -} - -isc_result_t -isc_file_getmodtime(const char *file, isc_time_t *time) { - isc_result_t result; - struct stat stats; - - REQUIRE(file != NULL); - REQUIRE(time != NULL); - - result = file_stats(file, &stats); - - if (result == ISC_R_SUCCESS) - /* - * XXXDCL some operating systems provide nanoseconds, too, - * such as BSD/OS via st_mtimespec. - */ - isc_time_set(time, stats.st_mtime, 0); - - return (result); -} - -isc_result_t -isc_file_settime(const char *file, isc_time_t *time) { - struct timeval times[2]; - - REQUIRE(file != NULL && time != NULL); - - /* - * tv_sec is at least a 32 bit quantity on all platforms we're - * dealing with, but it is signed on most (all?) of them, - * so we need to make sure the high bit isn't set. This unfortunately - * loses when either: - * * tv_sec becomes a signed 64 bit integer but long is 32 bits - * and isc_time_seconds > LONG_MAX, or - * * isc_time_seconds is changed to be > 32 bits but long is 32 bits - * and isc_time_seconds has at least 33 significant bits. - */ - times[0].tv_sec = times[1].tv_sec = (long)isc_time_seconds(time); - - /* - * Here is the real check for the high bit being set. - */ - if ((times[0].tv_sec & - (1ULL << (sizeof(times[0].tv_sec) * CHAR_BIT - 1))) != 0) - return (ISC_R_RANGE); - - /* - * isc_time_nanoseconds guarantees a value that divided by 1000 will - * fit into the minimum possible size tv_usec field. Unfortunately, - * we don't know what that type is so can't cast directly ... but - * we can at least cast to signed so the IRIX compiler shuts up. - */ - times[0].tv_usec = times[1].tv_usec = - (isc_int32_t)(isc_time_nanoseconds(time) / 1000); - - if (utimes(file, times) < 0) - return (isc__errno2result(errno)); - - return (ISC_R_SUCCESS); -} - -#undef TEMPLATE -#define TEMPLATE "tmp-XXXXXXXXXX" /*%< 14 characters. */ - -isc_result_t -isc_file_mktemplate(const char *path, char *buf, size_t buflen) { - return (isc_file_template(path, TEMPLATE, buf, buflen)); -} - -isc_result_t -isc_file_template(const char *path, const char *templet, char *buf, - size_t buflen) { - char *s; - - REQUIRE(path != NULL); - REQUIRE(templet != NULL); - REQUIRE(buf != NULL); - - s = strrchr(templet, '/'); - if (s != NULL) - templet = s + 1; - - s = strrchr(path, '/'); - - if (s != NULL) { - if ((s - path + 1 + strlen(templet) + 1) > buflen) - return (ISC_R_NOSPACE); - - strncpy(buf, path, s - path + 1); - buf[s - path + 1] = '\0'; - strcat(buf, templet); - } else { - if ((strlen(templet) + 1) > buflen) - return (ISC_R_NOSPACE); - - strcpy(buf, templet); - } - - return (ISC_R_SUCCESS); -} - -static char alphnum[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - -isc_result_t -isc_file_renameunique(const char *file, char *templet) { - char *x; - char *cp; - isc_uint32_t which; - - REQUIRE(file != NULL); - REQUIRE(templet != NULL); - - cp = templet; - while (*cp != '\0') - cp++; - if (cp == templet) - return (ISC_R_FAILURE); - - x = cp--; - while (cp >= templet && *cp == 'X') { - isc_random_get(&which); - *cp = alphnum[which % (sizeof(alphnum) - 1)]; - x = cp--; - } - while (link(file, templet) == -1) { - if (errno != EEXIST) - return (isc__errno2result(errno)); - for (cp = x;;) { - char *t; - if (*cp == '\0') - return (ISC_R_FAILURE); - t = strchr(alphnum, *cp); - if (t == NULL || *++t == '\0') - *cp++ = alphnum[0]; - else { - *cp = *t; - break; - } - } - } - if (unlink(file) < 0) - if (errno != ENOENT) - return (isc__errno2result(errno)); - return (ISC_R_SUCCESS); -} - -isc_result_t -isc_file_openunique(char *templet, FILE **fp) { - int mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; - return (isc_file_openuniquemode(templet, mode, fp)); -} - -isc_result_t -isc_file_openuniqueprivate(char *templet, FILE **fp) { - int mode = S_IWUSR|S_IRUSR; - return (isc_file_openuniquemode(templet, mode, fp)); -} - -isc_result_t -isc_file_openuniquemode(char *templet, int mode, FILE **fp) { - int fd; - FILE *f; - isc_result_t result = ISC_R_SUCCESS; - char *x; - char *cp; - isc_uint32_t which; - - REQUIRE(templet != NULL); - REQUIRE(fp != NULL && *fp == NULL); - - cp = templet; - while (*cp != '\0') - cp++; - if (cp == templet) - return (ISC_R_FAILURE); - - x = cp--; - while (cp >= templet && *cp == 'X') { - isc_random_get(&which); - *cp = alphnum[which % (sizeof(alphnum) - 1)]; - x = cp--; - } - - - while ((fd = open(templet, O_RDWR|O_CREAT|O_EXCL, mode)) == -1) { - if (errno != EEXIST) - return (isc__errno2result(errno)); - for (cp = x;;) { - char *t; - if (*cp == '\0') - return (ISC_R_FAILURE); - t = strchr(alphnum, *cp); - if (t == NULL || *++t == '\0') - *cp++ = alphnum[0]; - else { - *cp = *t; - break; - } - } - } - f = fdopen(fd, "w+"); - if (f == NULL) { - result = isc__errno2result(errno); - if (remove(templet) < 0) { - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_FILE, ISC_LOG_ERROR, - "remove '%s': failed", templet); - } - (void)close(fd); - } else - *fp = f; - - return (result); -} - -isc_result_t -isc_file_bopenunique(char *templet, FILE **fp) { - int mode = S_IWUSR|S_IRUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; - return (isc_file_openuniquemode(templet, mode, fp)); -} - -isc_result_t -isc_file_bopenuniqueprivate(char *templet, FILE **fp) { - int mode = S_IWUSR|S_IRUSR; - return (isc_file_openuniquemode(templet, mode, fp)); -} - -isc_result_t -isc_file_bopenuniquemode(char *templet, int mode, FILE **fp) { - return (isc_file_openuniquemode(templet, mode, fp)); -} - -isc_result_t -isc_file_remove(const char *filename) { - int r; - - REQUIRE(filename != NULL); - - r = unlink(filename); - if (r == 0) - return (ISC_R_SUCCESS); - else - return (isc__errno2result(errno)); -} - -isc_result_t -isc_file_rename(const char *oldname, const char *newname) { - int r; - - REQUIRE(oldname != NULL); - REQUIRE(newname != NULL); - - r = rename(oldname, newname); - if (r == 0) - return (ISC_R_SUCCESS); - else - return (isc__errno2result(errno)); -} - -isc_boolean_t -isc_file_exists(const char *pathname) { - struct stat stats; - - REQUIRE(pathname != NULL); - - return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS)); -} - -isc_result_t -isc_file_isplainfile(const char *filename) { - /* - * This function returns success if filename is a plain file. - */ - struct stat filestat; - memset(&filestat,0,sizeof(struct stat)); - - if ((stat(filename, &filestat)) == -1) - return(isc__errno2result(errno)); - - if(! S_ISREG(filestat.st_mode)) - return(ISC_R_INVALIDFILE); - - return(ISC_R_SUCCESS); -} - -isc_result_t -isc_file_isdirectory(const char *filename) { - /* - * This function returns success if filename exists and is a - * directory. - */ - struct stat filestat; - memset(&filestat,0,sizeof(struct stat)); - - if ((stat(filename, &filestat)) == -1) - return(isc__errno2result(errno)); - - if(! S_ISDIR(filestat.st_mode)) - return(ISC_R_INVALIDFILE); - - return(ISC_R_SUCCESS); -} - -isc_boolean_t -isc_file_isabsolute(const char *filename) { - REQUIRE(filename != NULL); - return (ISC_TF(filename[0] == '/')); -} - -isc_boolean_t -isc_file_iscurrentdir(const char *filename) { - REQUIRE(filename != NULL); - return (ISC_TF(filename[0] == '.' && filename[1] == '\0')); -} - -isc_boolean_t -isc_file_ischdiridempotent(const char *filename) { - REQUIRE(filename != NULL); - if (isc_file_isabsolute(filename)) - return (ISC_TRUE); - if (isc_file_iscurrentdir(filename)) - return (ISC_TRUE); - return (ISC_FALSE); -} - -const char * -isc_file_basename(const char *filename) { - char *s; - - REQUIRE(filename != NULL); - - s = strrchr(filename, '/'); - if (s == NULL) - return (filename); - - return (s + 1); -} - -isc_result_t -isc_file_progname(const char *filename, char *buf, size_t buflen) { - const char *base; - size_t len; - - REQUIRE(filename != NULL); - REQUIRE(buf != NULL); - - base = isc_file_basename(filename); - len = strlen(base) + 1; - - if (len > buflen) - return (ISC_R_NOSPACE); - memcpy(buf, base, len); - - return (ISC_R_SUCCESS); -} - -/* - * Put the absolute name of the current directory into 'dirname', which is - * a buffer of at least 'length' characters. End the string with the - * appropriate path separator, such that the final product could be - * concatenated with a relative pathname to make a valid pathname string. - */ -static isc_result_t -dir_current(char *dirname, size_t length) { - char *cwd; - isc_result_t result = ISC_R_SUCCESS; - - REQUIRE(dirname != NULL); - REQUIRE(length > 0U); - - cwd = getcwd(dirname, length); - - if (cwd == NULL) { - if (errno == ERANGE) - result = ISC_R_NOSPACE; - else - result = isc__errno2result(errno); - } else { - if (strlen(dirname) + 1 == length) - result = ISC_R_NOSPACE; - else if (dirname[1] != '\0') - strcat(dirname, "/"); - } - - return (result); -} - -isc_result_t -isc_file_absolutepath(const char *filename, char *path, size_t pathlen) { - isc_result_t result; - result = dir_current(path, pathlen); - if (result != ISC_R_SUCCESS) - return (result); - if (strlen(path) + strlen(filename) + 1 > pathlen) - return (ISC_R_NOSPACE); - strcat(path, filename); - return (ISC_R_SUCCESS); -} - -isc_result_t -isc_file_truncate(const char *filename, isc_offset_t size) { - isc_result_t result = ISC_R_SUCCESS; - - if (truncate(filename, size) < 0) - result = isc__errno2result(errno); - return (result); -} - -isc_result_t -isc_file_safecreate(const char *filename, FILE **fp) { - isc_result_t result; - int flags; - struct stat sb; - FILE *f; - int fd; - - REQUIRE(filename != NULL); - REQUIRE(fp != NULL && *fp == NULL); - - result = file_stats(filename, &sb); - if (result == ISC_R_SUCCESS) { - if ((sb.st_mode & S_IFREG) == 0) - return (ISC_R_INVALIDFILE); - flags = O_WRONLY | O_TRUNC; - } else if (result == ISC_R_FILENOTFOUND) { - flags = O_WRONLY | O_CREAT | O_EXCL; - } else - return (result); - - fd = open(filename, flags, S_IRUSR | S_IWUSR); - if (fd == -1) - return (isc__errno2result(errno)); - - f = fdopen(fd, "w"); - if (f == NULL) { - result = isc__errno2result(errno); - close(fd); - return (result); - } - - *fp = f; - return (ISC_R_SUCCESS); -} - -isc_result_t -isc_file_splitpath(isc_mem_t *mctx, char *path, char **dirname, char **basename) -{ - char *dir, *file, *slash; - - if (path == NULL) - return (ISC_R_INVALIDFILE); - - slash = strrchr(path, '/'); - - if (slash == path) { - file = ++slash; - dir = isc_mem_strdup(mctx, "/"); - } else if (slash != NULL) { - file = ++slash; - dir = isc_mem_allocate(mctx, slash - path); - if (dir != NULL) - strlcpy(dir, path, slash - path); - } else { - file = path; - dir = isc_mem_strdup(mctx, "."); - } - - if (dir == NULL) - return (ISC_R_NOMEMORY); - - if (*file == '\0') { - isc_mem_free(mctx, dir); - return (ISC_R_INVALIDFILE); - } - - *dirname = dir; - *basename = file; - - return (ISC_R_SUCCESS); -} diff --git a/contrib/bind9/lib/isc/unix/fsaccess.c b/contrib/bind9/lib/isc/unix/fsaccess.c deleted file mode 100644 index a2bd89a..0000000 --- a/contrib/bind9/lib/isc/unix/fsaccess.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2000, 2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: fsaccess.c,v 1.13 2007/06/19 23:47:18 tbox Exp $ */ - -#include <config.h> - -#include <sys/types.h> -#include <sys/stat.h> - -#include <errno.h> - -#include "errno2result.h" - -/*! \file - * \brief - * The OS-independent part of the API is in lib/isc. - */ -#include "../fsaccess.c" - -isc_result_t -isc_fsaccess_set(const char *path, isc_fsaccess_t access) { - struct stat statb; - mode_t mode; - isc_boolean_t is_dir = ISC_FALSE; - isc_fsaccess_t bits; - isc_result_t result; - - if (stat(path, &statb) != 0) - return (isc__errno2result(errno)); - - if ((statb.st_mode & S_IFDIR) != 0) - is_dir = ISC_TRUE; - else if ((statb.st_mode & S_IFREG) == 0) - return (ISC_R_INVALIDFILE); - - result = check_bad_bits(access, is_dir); - if (result != ISC_R_SUCCESS) - return (result); - - /* - * Done with checking bad bits. Set mode_t. - */ - mode = 0; - -#define SET_AND_CLEAR1(modebit) \ - if ((access & bits) != 0) { \ - mode |= modebit; \ - access &= ~bits; \ - } -#define SET_AND_CLEAR(user, group, other) \ - SET_AND_CLEAR1(user); \ - bits <<= STEP; \ - SET_AND_CLEAR1(group); \ - bits <<= STEP; \ - SET_AND_CLEAR1(other); - - bits = ISC_FSACCESS_READ | ISC_FSACCESS_LISTDIRECTORY; - - SET_AND_CLEAR(S_IRUSR, S_IRGRP, S_IROTH); - - bits = ISC_FSACCESS_WRITE | - ISC_FSACCESS_CREATECHILD | - ISC_FSACCESS_DELETECHILD; - - SET_AND_CLEAR(S_IWUSR, S_IWGRP, S_IWOTH); - - bits = ISC_FSACCESS_EXECUTE | - ISC_FSACCESS_ACCESSCHILD; - - SET_AND_CLEAR(S_IXUSR, S_IXGRP, S_IXOTH); - - INSIST(access == 0); - - if (chmod(path, mode) < 0) - return (isc__errno2result(errno)); - - return (ISC_R_SUCCESS); -} diff --git a/contrib/bind9/lib/isc/unix/ifiter_getifaddrs.c b/contrib/bind9/lib/isc/unix/ifiter_getifaddrs.c deleted file mode 100644 index 637450a..0000000 --- a/contrib/bind9/lib/isc/unix/ifiter_getifaddrs.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: ifiter_getifaddrs.c,v 1.13 2009/09/24 23:48:13 tbox Exp $ */ - -/*! \file - * \brief - * Obtain the list of network interfaces using the getifaddrs(3) library. - */ - -#include <ifaddrs.h> - -/*% Iterator Magic */ -#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'G') -/*% Valid Iterator */ -#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC) - -#ifdef __linux -static isc_boolean_t seenv6 = ISC_FALSE; -#endif - -/*% Iterator structure */ -struct isc_interfaceiter { - unsigned int magic; /*%< Magic number. */ - isc_mem_t *mctx; - void *buf; /*%< (unused) */ - unsigned int bufsize; /*%< (always 0) */ - struct ifaddrs *ifaddrs; /*%< List of ifaddrs */ - struct ifaddrs *pos; /*%< Ptr to current ifaddr */ - isc_interface_t current; /*%< Current interface data. */ - isc_result_t result; /*%< Last result code. */ -#ifdef __linux - FILE * proc; - char entry[ISC_IF_INET6_SZ]; - isc_result_t valid; -#endif -}; - -isc_result_t -isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { - isc_interfaceiter_t *iter; - isc_result_t result; - char strbuf[ISC_STRERRORSIZE]; - - REQUIRE(mctx != NULL); - REQUIRE(iterp != NULL); - REQUIRE(*iterp == NULL); - - iter = isc_mem_get(mctx, sizeof(*iter)); - if (iter == NULL) - return (ISC_R_NOMEMORY); - - iter->mctx = mctx; - iter->buf = NULL; - iter->bufsize = 0; - iter->ifaddrs = NULL; -#ifdef __linux - /* - * Only open "/proc/net/if_inet6" if we have never seen a IPv6 - * address returned by getifaddrs(). - */ - if (!seenv6) - iter->proc = fopen("/proc/net/if_inet6", "r"); - else - iter->proc = NULL; - iter->valid = ISC_R_FAILURE; -#endif - - if (getifaddrs(&iter->ifaddrs) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERGETIFADDRS, - ISC_MSG_GETIFADDRS, - "getting interface " - "addresses: getifaddrs: %s"), - strbuf); - result = ISC_R_UNEXPECTED; - goto failure; - } - - /* - * A newly created iterator has an undefined position - * until isc_interfaceiter_first() is called. - */ - iter->pos = NULL; - iter->result = ISC_R_FAILURE; - - iter->magic = IFITER_MAGIC; - *iterp = iter; - return (ISC_R_SUCCESS); - - failure: -#ifdef __linux - if (iter->proc != NULL) - fclose(iter->proc); -#endif - if (iter->ifaddrs != NULL) /* just in case */ - freeifaddrs(iter->ifaddrs); - isc_mem_put(mctx, iter, sizeof(*iter)); - return (result); -} - -/* - * Get information about the current interface to iter->current. - * If successful, return ISC_R_SUCCESS. - * If the interface has an unsupported address family, - * return ISC_R_IGNORE. - */ - -static isc_result_t -internal_current(isc_interfaceiter_t *iter) { - struct ifaddrs *ifa; - int family; - unsigned int namelen; - - REQUIRE(VALID_IFITER(iter)); - - ifa = iter->pos; - -#ifdef __linux - if (iter->pos == NULL) - return (linux_if_inet6_current(iter)); -#endif - - INSIST(ifa != NULL); - INSIST(ifa->ifa_name != NULL); - - if (ifa->ifa_addr == NULL) - return (ISC_R_IGNORE); - - family = ifa->ifa_addr->sa_family; - if (family != AF_INET && family != AF_INET6) - return (ISC_R_IGNORE); - -#ifdef __linux - if (family == AF_INET6) - seenv6 = ISC_TRUE; -#endif - - memset(&iter->current, 0, sizeof(iter->current)); - - namelen = strlen(ifa->ifa_name); - if (namelen > sizeof(iter->current.name) - 1) - namelen = sizeof(iter->current.name) - 1; - - memset(iter->current.name, 0, sizeof(iter->current.name)); - memcpy(iter->current.name, ifa->ifa_name, namelen); - - iter->current.flags = 0; - - if ((ifa->ifa_flags & IFF_UP) != 0) - iter->current.flags |= INTERFACE_F_UP; - - if ((ifa->ifa_flags & IFF_POINTOPOINT) != 0) - iter->current.flags |= INTERFACE_F_POINTTOPOINT; - - if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) - iter->current.flags |= INTERFACE_F_LOOPBACK; - - iter->current.af = family; - - get_addr(family, &iter->current.address, ifa->ifa_addr, ifa->ifa_name); - - if (ifa->ifa_netmask != NULL) - get_addr(family, &iter->current.netmask, ifa->ifa_netmask, - ifa->ifa_name); - - if (ifa->ifa_dstaddr != NULL && - (iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) - get_addr(family, &iter->current.dstaddress, ifa->ifa_dstaddr, - ifa->ifa_name); - - return (ISC_R_SUCCESS); -} - -/* - * Step the iterator to the next interface. Unlike - * isc_interfaceiter_next(), this may leave the iterator - * positioned on an interface that will ultimately - * be ignored. Return ISC_R_NOMORE if there are no more - * interfaces, otherwise ISC_R_SUCCESS. - */ -static isc_result_t -internal_next(isc_interfaceiter_t *iter) { - - if (iter->pos != NULL) - iter->pos = iter->pos->ifa_next; - if (iter->pos == NULL) { -#ifdef __linux - if (!seenv6) - return (linux_if_inet6_next(iter)); -#endif - return (ISC_R_NOMORE); - } - - return (ISC_R_SUCCESS); -} - -static void -internal_destroy(isc_interfaceiter_t *iter) { - -#ifdef __linux - if (iter->proc != NULL) - fclose(iter->proc); - iter->proc = NULL; -#endif - if (iter->ifaddrs) - freeifaddrs(iter->ifaddrs); - iter->ifaddrs = NULL; -} - -static -void internal_first(isc_interfaceiter_t *iter) { - -#ifdef __linux - linux_if_inet6_first(iter); -#endif - iter->pos = iter->ifaddrs; -} diff --git a/contrib/bind9/lib/isc/unix/ifiter_ioctl.c b/contrib/bind9/lib/isc/unix/ifiter_ioctl.c deleted file mode 100644 index 38c34fd..0000000 --- a/contrib/bind9/lib/isc/unix/ifiter_ioctl.c +++ /dev/null @@ -1,931 +0,0 @@ -/* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: ifiter_ioctl.c,v 1.62 2009/01/18 23:48:14 tbox Exp $ */ - -/*! \file - * \brief - * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl. - * See netintro(4). - */ - -#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) -#ifdef ISC_PLATFORM_HAVEIF_LADDRCONF -#define lifc_len iflc_len -#define lifc_buf iflc_buf -#define lifc_req iflc_req -#define LIFCONF if_laddrconf -#else -#define ISC_HAVE_LIFC_FAMILY 1 -#define ISC_HAVE_LIFC_FLAGS 1 -#define LIFCONF lifconf -#endif - -#ifdef ISC_PLATFORM_HAVEIF_LADDRREQ -#define lifr_addr iflr_addr -#define lifr_name iflr_name -#define lifr_dstaddr iflr_dstaddr -#define lifr_flags iflr_flags -#define ss_family sa_family -#define LIFREQ if_laddrreq -#else -#define LIFREQ lifreq -#endif -#endif - -#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T') -#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC) - -struct isc_interfaceiter { - unsigned int magic; /* Magic number. */ - isc_mem_t *mctx; - int mode; - int socket; - struct ifconf ifc; - void *buf; /* Buffer for sysctl data. */ - unsigned int bufsize; /* Bytes allocated. */ - unsigned int pos; /* Current offset in - SIOCGIFCONF data */ -#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) - int socket6; - struct LIFCONF lifc; - void *buf6; /* Buffer for sysctl data. */ - unsigned int bufsize6; /* Bytes allocated. */ - unsigned int pos6; /* Current offset in - SIOCGLIFCONF data */ - isc_result_t result6; /* Last result code. */ - isc_boolean_t first6; -#endif -#ifdef HAVE_TRUCLUSTER - int clua_context; /* Cluster alias context */ - isc_boolean_t clua_done; - struct sockaddr clua_sa; -#endif -#ifdef __linux - FILE * proc; - char entry[ISC_IF_INET6_SZ]; - isc_result_t valid; -#endif - isc_interface_t current; /* Current interface data. */ - isc_result_t result; /* Last result code. */ -}; - -#ifdef HAVE_TRUCLUSTER -#include <clua/clua.h> -#include <sys/socket.h> -#endif - - -/*% - * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system - * will have more than a megabyte of interface configuration data. - */ -#define IFCONF_BUFSIZE_INITIAL 4096 -#define IFCONF_BUFSIZE_MAX 1048576 - -#ifdef __linux -#ifndef IF_NAMESIZE -# ifdef IFNAMSIZ -# define IF_NAMESIZE IFNAMSIZ -# else -# define IF_NAMESIZE 16 -# endif -#endif -#endif - -static isc_result_t -getbuf4(isc_interfaceiter_t *iter) { - char strbuf[ISC_STRERRORSIZE]; - - iter->bufsize = IFCONF_BUFSIZE_INITIAL; - - for (;;) { - iter->buf = isc_mem_get(iter->mctx, iter->bufsize); - if (iter->buf == NULL) - return (ISC_R_NOMEMORY); - - memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len)); - iter->ifc.ifc_len = iter->bufsize; - iter->ifc.ifc_buf = iter->buf; - /* - * Ignore the HP/UX warning about "integer overflow during - * conversion". It comes from its own macro definition, - * and is really hard to shut up. - */ - if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc) - == -1) { - if (errno != EINVAL) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERIOCTL, - ISC_MSG_GETIFCONFIG, - "get interface " - "configuration: %s"), - strbuf); - goto unexpected; - } - /* - * EINVAL. Retry with a bigger buffer. - */ - } else { - /* - * The ioctl succeeded. - * Some OS's just return what will fit rather - * than set EINVAL if the buffer is too small - * to fit all the interfaces in. If - * ifc.lifc_len is too near to the end of the - * buffer we will grow it just in case and - * retry. - */ - if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq) - < iter->bufsize) - break; - } - if (iter->bufsize >= IFCONF_BUFSIZE_MAX) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERIOCTL, - ISC_MSG_BUFFERMAX, - "get interface " - "configuration: " - "maximum buffer " - "size exceeded")); - goto unexpected; - } - isc_mem_put(iter->mctx, iter->buf, iter->bufsize); - - iter->bufsize *= 2; - } - return (ISC_R_SUCCESS); - - unexpected: - isc_mem_put(iter->mctx, iter->buf, iter->bufsize); - iter->buf = NULL; - return (ISC_R_UNEXPECTED); -} - -#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) -static isc_result_t -getbuf6(isc_interfaceiter_t *iter) { - char strbuf[ISC_STRERRORSIZE]; - isc_result_t result; - - iter->bufsize6 = IFCONF_BUFSIZE_INITIAL; - - for (;;) { - iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6); - if (iter->buf6 == NULL) - return (ISC_R_NOMEMORY); - - memset(&iter->lifc, 0, sizeof(iter->lifc)); -#ifdef ISC_HAVE_LIFC_FAMILY - iter->lifc.lifc_family = AF_INET6; -#endif -#ifdef ISC_HAVE_LIFC_FLAGS - iter->lifc.lifc_flags = 0; -#endif - iter->lifc.lifc_len = iter->bufsize6; - iter->lifc.lifc_buf = iter->buf6; - /* - * Ignore the HP/UX warning about "integer overflow during - * conversion". It comes from its own macro definition, - * and is really hard to shut up. - */ - if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc) - == -1) { -#ifdef __hpux - /* - * IPv6 interface scanning is not available on all - * kernels w/ IPv6 sockets. - */ - if (errno == ENOENT) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_INTERFACE, - ISC_LOG_DEBUG(1), - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERIOCTL, - ISC_MSG_GETIFCONFIG, - "get interface " - "configuration: %s"), - strbuf); - result = ISC_R_FAILURE; - goto cleanup; - } -#endif - if (errno != EINVAL) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERIOCTL, - ISC_MSG_GETIFCONFIG, - "get interface " - "configuration: %s"), - strbuf); - result = ISC_R_UNEXPECTED; - goto cleanup; - } - /* - * EINVAL. Retry with a bigger buffer. - */ - } else { - /* - * The ioctl succeeded. - * Some OS's just return what will fit rather - * than set EINVAL if the buffer is too small - * to fit all the interfaces in. If - * ifc.ifc_len is too near to the end of the - * buffer we will grow it just in case and - * retry. - */ - if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ) - < iter->bufsize6) - break; - } - if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERIOCTL, - ISC_MSG_BUFFERMAX, - "get interface " - "configuration: " - "maximum buffer " - "size exceeded")); - result = ISC_R_UNEXPECTED; - goto cleanup; - } - isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); - - iter->bufsize6 *= 2; - } - - if (iter->lifc.lifc_len != 0) - iter->mode = 6; - return (ISC_R_SUCCESS); - - cleanup: - isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); - iter->buf6 = NULL; - return (result); -} -#endif - -isc_result_t -isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { - isc_interfaceiter_t *iter; - isc_result_t result; - char strbuf[ISC_STRERRORSIZE]; - - REQUIRE(mctx != NULL); - REQUIRE(iterp != NULL); - REQUIRE(*iterp == NULL); - - iter = isc_mem_get(mctx, sizeof(*iter)); - if (iter == NULL) - return (ISC_R_NOMEMORY); - - iter->mctx = mctx; - iter->mode = 4; - iter->buf = NULL; - iter->pos = (unsigned int) -1; -#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) - iter->buf6 = NULL; - iter->pos6 = (unsigned int) -1; - iter->result6 = ISC_R_NOMORE; - iter->socket6 = -1; - iter->first6 = ISC_FALSE; -#endif - - /* - * Get the interface configuration, allocating more memory if - * necessary. - */ - -#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) - result = isc_net_probeipv6(); - if (result == ISC_R_SUCCESS) { - /* - * Create an unbound datagram socket to do the SIOCGLIFCONF - * ioctl on. HP/UX requires an AF_INET6 socket for - * SIOCGLIFCONF to get IPv6 addresses. - */ - if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERIOCTL, - ISC_MSG_MAKESCANSOCKET, - "making interface " - "scan socket: %s"), - strbuf); - result = ISC_R_UNEXPECTED; - goto socket6_failure; - } - result = iter->result6 = getbuf6(iter); - if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS) - goto ioctl6_failure; - } -#endif - if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERIOCTL, - ISC_MSG_MAKESCANSOCKET, - "making interface " - "scan socket: %s"), - strbuf); - result = ISC_R_UNEXPECTED; - goto socket_failure; - } - result = getbuf4(iter); - if (result != ISC_R_SUCCESS) - goto ioctl_failure; - - /* - * A newly created iterator has an undefined position - * until isc_interfaceiter_first() is called. - */ -#ifdef HAVE_TRUCLUSTER - iter->clua_context = -1; - iter->clua_done = ISC_TRUE; -#endif -#ifdef __linux - iter->proc = fopen("/proc/net/if_inet6", "r"); - iter->valid = ISC_R_FAILURE; -#endif - iter->result = ISC_R_FAILURE; - - iter->magic = IFITER_MAGIC; - *iterp = iter; - return (ISC_R_SUCCESS); - - ioctl_failure: - if (iter->buf != NULL) - isc_mem_put(mctx, iter->buf, iter->bufsize); - (void) close(iter->socket); - - socket_failure: -#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) - if (iter->buf6 != NULL) - isc_mem_put(mctx, iter->buf6, iter->bufsize6); - ioctl6_failure: - if (iter->socket6 != -1) - (void) close(iter->socket6); - socket6_failure: -#endif - - isc_mem_put(mctx, iter, sizeof(*iter)); - return (result); -} - -#ifdef HAVE_TRUCLUSTER -static void -get_inaddr(isc_netaddr_t *dst, struct in_addr *src) { - dst->family = AF_INET; - memcpy(&dst->type.in, src, sizeof(struct in_addr)); -} - -static isc_result_t -internal_current_clusteralias(isc_interfaceiter_t *iter) { - struct clua_info ci; - if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS) - return (ISC_R_IGNORE); - memset(&iter->current, 0, sizeof(iter->current)); - iter->current.af = iter->clua_sa.sa_family; - memset(iter->current.name, 0, sizeof(iter->current.name)); - sprintf(iter->current.name, "clua%d", ci.aliasid); - iter->current.flags = INTERFACE_F_UP; - get_inaddr(&iter->current.address, &ci.addr); - get_inaddr(&iter->current.netmask, &ci.netmask); - return (ISC_R_SUCCESS); -} -#endif - -/* - * Get information about the current interface to iter->current. - * If successful, return ISC_R_SUCCESS. - * If the interface has an unsupported address family, or if - * some operation on it fails, return ISC_R_IGNORE to make - * the higher-level iterator code ignore it. - */ - -static isc_result_t -internal_current4(isc_interfaceiter_t *iter) { - struct ifreq *ifrp; - struct ifreq ifreq; - int family; - char strbuf[ISC_STRERRORSIZE]; -#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR) - struct lifreq lifreq; -#else - char sabuf[256]; -#endif - int i, bits, prefixlen; - - REQUIRE(VALID_IFITER(iter)); - - if (iter->ifc.ifc_len == 0 || - iter->pos == (unsigned int)iter->ifc.ifc_len) { -#ifdef __linux - return (linux_if_inet6_current(iter)); -#else - return (ISC_R_NOMORE); -#endif - } - - INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len); - - ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos); - - memset(&ifreq, 0, sizeof(ifreq)); - memcpy(&ifreq, ifrp, sizeof(ifreq)); - - family = ifreq.ifr_addr.sa_family; -#if defined(ISC_PLATFORM_HAVEIPV6) - if (family != AF_INET && family != AF_INET6) -#else - if (family != AF_INET) -#endif - return (ISC_R_IGNORE); - - memset(&iter->current, 0, sizeof(iter->current)); - iter->current.af = family; - - INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name)); - memset(iter->current.name, 0, sizeof(iter->current.name)); - memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name)); - - get_addr(family, &iter->current.address, - (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name); - - /* - * If the interface does not have a address ignore it. - */ - switch (family) { - case AF_INET: - if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY)) - return (ISC_R_IGNORE); - break; - case AF_INET6: - if (memcmp(&iter->current.address.type.in6, &in6addr_any, - sizeof(in6addr_any)) == 0) - return (ISC_R_IGNORE); - break; - } - - /* - * Get interface flags. - */ - - iter->current.flags = 0; - - /* - * Ignore the HP/UX warning about "integer overflow during - * conversion. It comes from its own macro definition, - * and is really hard to shut up. - */ - if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "%s: getting interface flags: %s", - ifreq.ifr_name, strbuf); - return (ISC_R_IGNORE); - } - - if ((ifreq.ifr_flags & IFF_UP) != 0) - iter->current.flags |= INTERFACE_F_UP; - -#ifdef IFF_POINTOPOINT - if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0) - iter->current.flags |= INTERFACE_F_POINTTOPOINT; -#endif - - if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0) - iter->current.flags |= INTERFACE_F_LOOPBACK; - - if (family == AF_INET) - goto inet; - -#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR) - memset(&lifreq, 0, sizeof(lifreq)); - memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name)); - memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6, - sizeof(iter->current.address.type.in6)); - - if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "%s: getting interface address: %s", - ifreq.ifr_name, strbuf); - return (ISC_R_IGNORE); - } - prefixlen = lifreq.lifr_addrlen; -#else - isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf)); - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_INTERFACE, - ISC_LOG_INFO, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERIOCTL, - ISC_MSG_GETIFCONFIG, - "prefix length for %s is unknown " - "(assume 128)"), sabuf); - prefixlen = 128; -#endif - - /* - * Netmask already zeroed. - */ - iter->current.netmask.family = family; - for (i = 0; i < 16; i++) { - if (prefixlen > 8) { - bits = 0; - prefixlen -= 8; - } else { - bits = 8 - prefixlen; - prefixlen = 0; - } - iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff; - } - return (ISC_R_SUCCESS); - - inet: - if (family != AF_INET) - return (ISC_R_IGNORE); -#ifdef IFF_POINTOPOINT - /* - * If the interface is point-to-point, get the destination address. - */ - if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { - /* - * Ignore the HP/UX warning about "integer overflow during - * conversion. It comes from its own macro definition, - * and is really hard to shut up. - */ - if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq) - < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERIOCTL, - ISC_MSG_GETDESTADDR, - "%s: getting " - "destination address: %s"), - ifreq.ifr_name, strbuf); - return (ISC_R_IGNORE); - } - get_addr(family, &iter->current.dstaddress, - (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name); - } -#endif - - /* - * Get the network mask. - */ - memset(&ifreq, 0, sizeof(ifreq)); - memcpy(&ifreq, ifrp, sizeof(ifreq)); - /* - * Ignore the HP/UX warning about "integer overflow during - * conversion. It comes from its own macro definition, - * and is really hard to shut up. - */ - if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERIOCTL, - ISC_MSG_GETNETMASK, - "%s: getting netmask: %s"), - ifreq.ifr_name, strbuf); - return (ISC_R_IGNORE); - } - get_addr(family, &iter->current.netmask, - (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name); - return (ISC_R_SUCCESS); -} - -#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) -static isc_result_t -internal_current6(isc_interfaceiter_t *iter) { - struct LIFREQ *ifrp; - struct LIFREQ lifreq; - int family; - char strbuf[ISC_STRERRORSIZE]; - int fd; - - REQUIRE(VALID_IFITER(iter)); - if (iter->result6 != ISC_R_SUCCESS) - return (iter->result6); - REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len); - - ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6); - - memset(&lifreq, 0, sizeof(lifreq)); - memcpy(&lifreq, ifrp, sizeof(lifreq)); - - family = lifreq.lifr_addr.ss_family; -#ifdef ISC_PLATFORM_HAVEIPV6 - if (family != AF_INET && family != AF_INET6) -#else - if (family != AF_INET) -#endif - return (ISC_R_IGNORE); - - memset(&iter->current, 0, sizeof(iter->current)); - iter->current.af = family; - - INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name)); - memset(iter->current.name, 0, sizeof(iter->current.name)); - memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name)); - - get_addr(family, &iter->current.address, - (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name); - - /* - * If the interface does not have a address ignore it. - */ - switch (family) { - case AF_INET: - if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY)) - return (ISC_R_IGNORE); - break; - case AF_INET6: - if (memcmp(&iter->current.address.type.in6, &in6addr_any, - sizeof(in6addr_any)) == 0) - return (ISC_R_IGNORE); - break; - } - - /* - * Get interface flags. - */ - - iter->current.flags = 0; - - if (family == AF_INET6) - fd = iter->socket6; - else - fd = iter->socket; - - /* - * Ignore the HP/UX warning about "integer overflow during - * conversion. It comes from its own macro definition, - * and is really hard to shut up. - */ - if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "%s: getting interface flags: %s", - lifreq.lifr_name, strbuf); - return (ISC_R_IGNORE); - } - - if ((lifreq.lifr_flags & IFF_UP) != 0) - iter->current.flags |= INTERFACE_F_UP; - -#ifdef IFF_POINTOPOINT - if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0) - iter->current.flags |= INTERFACE_F_POINTTOPOINT; -#endif - - if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0) - iter->current.flags |= INTERFACE_F_LOOPBACK; - -#ifdef IFF_POINTOPOINT - /* - * If the interface is point-to-point, get the destination address. - */ - if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { - /* - * Ignore the HP/UX warning about "integer overflow during - * conversion. It comes from its own macro definition, - * and is really hard to shut up. - */ - if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq) - < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERIOCTL, - ISC_MSG_GETDESTADDR, - "%s: getting " - "destination address: %s"), - lifreq.lifr_name, strbuf); - return (ISC_R_IGNORE); - } - get_addr(family, &iter->current.dstaddress, - (struct sockaddr *)&lifreq.lifr_dstaddr, - lifreq.lifr_name); - } -#endif - - /* - * Get the network mask. Netmask already zeroed. - */ - memset(&lifreq, 0, sizeof(lifreq)); - memcpy(&lifreq, ifrp, sizeof(lifreq)); - -#ifdef lifr_addrlen - /* - * Special case: if the system provides lifr_addrlen member, the - * netmask of an IPv6 address can be derived from the length, since - * an IPv6 address always has a contiguous mask. - */ - if (family == AF_INET6) { - int i, bits; - - iter->current.netmask.family = family; - for (i = 0; i < lifreq.lifr_addrlen; i += 8) { - bits = lifreq.lifr_addrlen - i; - bits = (bits < 8) ? (8 - bits) : 0; - iter->current.netmask.type.in6.s6_addr[i / 8] = - (~0 << bits) & 0xff; - } - - return (ISC_R_SUCCESS); - } -#endif - - /* - * Ignore the HP/UX warning about "integer overflow during - * conversion. It comes from its own macro definition, - * and is really hard to shut up. - */ - if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERIOCTL, - ISC_MSG_GETNETMASK, - "%s: getting netmask: %s"), - lifreq.lifr_name, strbuf); - return (ISC_R_IGNORE); - } - get_addr(family, &iter->current.netmask, - (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name); - - return (ISC_R_SUCCESS); -} -#endif - -static isc_result_t -internal_current(isc_interfaceiter_t *iter) { -#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) - if (iter->mode == 6) { - iter->result6 = internal_current6(iter); - if (iter->result6 != ISC_R_NOMORE) - return (iter->result6); - } -#endif -#ifdef HAVE_TRUCLUSTER - if (!iter->clua_done) - return(internal_current_clusteralias(iter)); -#endif - return (internal_current4(iter)); -} - -/* - * Step the iterator to the next interface. Unlike - * isc_interfaceiter_next(), this may leave the iterator - * positioned on an interface that will ultimately - * be ignored. Return ISC_R_NOMORE if there are no more - * interfaces, otherwise ISC_R_SUCCESS. - */ -static isc_result_t -internal_next4(isc_interfaceiter_t *iter) { -#ifdef ISC_PLATFORM_HAVESALEN - struct ifreq *ifrp; -#endif - - if (iter->pos < (unsigned int) iter->ifc.ifc_len) { -#ifdef ISC_PLATFORM_HAVESALEN - ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos); - - if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr)) - iter->pos += sizeof(ifrp->ifr_name) + - ifrp->ifr_addr.sa_len; - else -#endif - iter->pos += sizeof(struct ifreq); - - } else { - INSIST(iter->pos == (unsigned int) iter->ifc.ifc_len); -#ifdef __linux - return (linux_if_inet6_next(iter)); -#else - return (ISC_R_NOMORE); -#endif - } - return (ISC_R_SUCCESS); -} - -#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) -static isc_result_t -internal_next6(isc_interfaceiter_t *iter) { -#ifdef ISC_PLATFORM_HAVESALEN - struct LIFREQ *ifrp; -#endif - - if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE) - return (iter->result6); - - REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len); - -#ifdef ISC_PLATFORM_HAVESALEN - ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6); - - if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr)) - iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len; - else -#endif - iter->pos6 += sizeof(struct LIFREQ); - - if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len) - return (ISC_R_NOMORE); - - return (ISC_R_SUCCESS); -} -#endif - -static isc_result_t -internal_next(isc_interfaceiter_t *iter) { -#ifdef HAVE_TRUCLUSTER - int clua_result; -#endif -#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) - if (iter->mode == 6) { - iter->result6 = internal_next6(iter); - if (iter->result6 != ISC_R_NOMORE) - return (iter->result6); - if (iter->first6) { - iter->first6 = ISC_FALSE; - return (ISC_R_SUCCESS); - } - } -#endif -#ifdef HAVE_TRUCLUSTER - if (!iter->clua_done) { - clua_result = clua_getaliasaddress(&iter->clua_sa, - &iter->clua_context); - if (clua_result != CLUA_SUCCESS) - iter->clua_done = ISC_TRUE; - return (ISC_R_SUCCESS); - } -#endif - return (internal_next4(iter)); -} - -static void -internal_destroy(isc_interfaceiter_t *iter) { - (void) close(iter->socket); -#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) - if (iter->socket6 != -1) - (void) close(iter->socket6); - if (iter->buf6 != NULL) { - isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6); - } -#endif -#ifdef __linux - if (iter->proc != NULL) - fclose(iter->proc); -#endif -} - -static -void internal_first(isc_interfaceiter_t *iter) { -#ifdef HAVE_TRUCLUSTER - int clua_result; -#endif - iter->pos = 0; -#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) - iter->pos6 = 0; - if (iter->result6 == ISC_R_NOMORE) - iter->result6 = ISC_R_SUCCESS; - iter->first6 = ISC_TRUE; -#endif -#ifdef HAVE_TRUCLUSTER - iter->clua_context = 0; - clua_result = clua_getaliasaddress(&iter->clua_sa, - &iter->clua_context); - iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS); -#endif -#ifdef __linux - linux_if_inet6_first(iter); -#endif -} diff --git a/contrib/bind9/lib/isc/unix/ifiter_sysctl.c b/contrib/bind9/lib/isc/unix/ifiter_sysctl.c deleted file mode 100644 index 9d5bf6d..0000000 --- a/contrib/bind9/lib/isc/unix/ifiter_sysctl.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: ifiter_sysctl.c,v 1.25 2007/06/19 23:47:18 tbox Exp $ */ - -/*! \file - * \brief - * Obtain the list of network interfaces using sysctl. - * See TCP/IP Illustrated Volume 2, sections 19.8, 19.14, - * and 19.16. - */ - -#include <sys/param.h> -#include <sys/sysctl.h> - -#include <net/route.h> -#include <net/if_dl.h> - -/* XXX what about Alpha? */ -#ifdef sgi -#define ROUNDUP(a) ((a) > 0 ? \ - (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) : \ - sizeof(__uint64_t)) -#else -#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \ - : sizeof(long)) -#endif - -#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'S') -#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC) - -struct isc_interfaceiter { - unsigned int magic; /* Magic number. */ - isc_mem_t *mctx; - void *buf; /* Buffer for sysctl data. */ - unsigned int bufsize; /* Bytes allocated. */ - unsigned int bufused; /* Bytes used. */ - unsigned int pos; /* Current offset in - sysctl data. */ - isc_interface_t current; /* Current interface data. */ - isc_result_t result; /* Last result code. */ -}; - -static int mib[6] = { - CTL_NET, - PF_ROUTE, - 0, - 0, /* Any address family. */ - NET_RT_IFLIST, - 0 /* Flags. */ -}; - -isc_result_t -isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) { - isc_interfaceiter_t *iter; - isc_result_t result; - size_t bufsize; - size_t bufused; - char strbuf[ISC_STRERRORSIZE]; - - REQUIRE(mctx != NULL); - REQUIRE(iterp != NULL); - REQUIRE(*iterp == NULL); - - iter = isc_mem_get(mctx, sizeof(*iter)); - if (iter == NULL) - return (ISC_R_NOMEMORY); - - iter->mctx = mctx; - iter->buf = 0; - - /* - * Determine the amount of memory needed. - */ - bufsize = 0; - if (sysctl(mib, 6, NULL, &bufsize, NULL, (size_t) 0) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERSYSCTL, - ISC_MSG_GETIFLISTSIZE, - "getting interface " - "list size: sysctl: %s"), - strbuf); - result = ISC_R_UNEXPECTED; - goto failure; - } - iter->bufsize = bufsize; - - iter->buf = isc_mem_get(iter->mctx, iter->bufsize); - if (iter->buf == NULL) { - result = ISC_R_NOMEMORY; - goto failure; - } - - bufused = bufsize; - if (sysctl(mib, 6, iter->buf, &bufused, NULL, (size_t) 0) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_IFITERSYSCTL, - ISC_MSG_GETIFLIST, - "getting interface list: " - "sysctl: %s"), - strbuf); - result = ISC_R_UNEXPECTED; - goto failure; - } - iter->bufused = bufused; - INSIST(iter->bufused <= iter->bufsize); - - /* - * A newly created iterator has an undefined position - * until isc_interfaceiter_first() is called. - */ - iter->pos = (unsigned int) -1; - iter->result = ISC_R_FAILURE; - - iter->magic = IFITER_MAGIC; - *iterp = iter; - return (ISC_R_SUCCESS); - - failure: - if (iter->buf != NULL) - isc_mem_put(mctx, iter->buf, iter->bufsize); - isc_mem_put(mctx, iter, sizeof(*iter)); - return (result); -} - -/* - * Get information about the current interface to iter->current. - * If successful, return ISC_R_SUCCESS. - * If the interface has an unsupported address family, - * return ISC_R_IGNORE. In case of other failure, - * return ISC_R_UNEXPECTED. - */ - -static isc_result_t -internal_current(isc_interfaceiter_t *iter) { - struct ifa_msghdr *ifam, *ifam_end; - - REQUIRE(VALID_IFITER(iter)); - REQUIRE (iter->pos < (unsigned int) iter->bufused); - - ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos); - ifam_end = (struct ifa_msghdr *) ((char *) iter->buf + iter->bufused); - - if (ifam->ifam_type == RTM_IFINFO) { - struct if_msghdr *ifm = (struct if_msghdr *) ifam; - struct sockaddr_dl *sdl = (struct sockaddr_dl *) (ifm + 1); - unsigned int namelen; - - memset(&iter->current, 0, sizeof(iter->current)); - - namelen = sdl->sdl_nlen; - if (namelen > sizeof(iter->current.name) - 1) - namelen = sizeof(iter->current.name) - 1; - - memset(iter->current.name, 0, sizeof(iter->current.name)); - memcpy(iter->current.name, sdl->sdl_data, namelen); - - iter->current.flags = 0; - - if ((ifam->ifam_flags & IFF_UP) != 0) - iter->current.flags |= INTERFACE_F_UP; - - if ((ifam->ifam_flags & IFF_POINTOPOINT) != 0) - iter->current.flags |= INTERFACE_F_POINTTOPOINT; - - if ((ifam->ifam_flags & IFF_LOOPBACK) != 0) - iter->current.flags |= INTERFACE_F_LOOPBACK; - - /* - * This is not an interface address. - * Force another iteration. - */ - return (ISC_R_IGNORE); - } else if (ifam->ifam_type == RTM_NEWADDR) { - int i; - int family; - struct sockaddr *mask_sa = NULL; - struct sockaddr *addr_sa = NULL; - struct sockaddr *dst_sa = NULL; - - struct sockaddr *sa = (struct sockaddr *)(ifam + 1); - family = sa->sa_family; - - for (i = 0; i < RTAX_MAX; i++) - { - if ((ifam->ifam_addrs & (1 << i)) == 0) - continue; - - INSIST(sa < (struct sockaddr *) ifam_end); - - switch (i) { - case RTAX_NETMASK: /* Netmask */ - mask_sa = sa; - break; - case RTAX_IFA: /* Interface address */ - addr_sa = sa; - break; - case RTAX_BRD: /* Broadcast or destination address */ - dst_sa = sa; - break; - } -#ifdef ISC_PLATFORM_HAVESALEN - sa = (struct sockaddr *)((char*)(sa) - + ROUNDUP(sa->sa_len)); -#else -#ifdef sgi - /* - * Do as the contributed SGI code does. - */ - sa = (struct sockaddr *)((char*)(sa) - + ROUNDUP(_FAKE_SA_LEN_DST(sa))); -#else - /* XXX untested. */ - sa = (struct sockaddr *)((char*)(sa) - + ROUNDUP(sizeof(struct sockaddr))); -#endif -#endif - } - - if (addr_sa == NULL) - return (ISC_R_IGNORE); - - family = addr_sa->sa_family; - if (family != AF_INET && family != AF_INET6) - return (ISC_R_IGNORE); - - iter->current.af = family; - - get_addr(family, &iter->current.address, addr_sa, - iter->current.name); - - if (mask_sa != NULL) - get_addr(family, &iter->current.netmask, mask_sa, - iter->current.name); - - if (dst_sa != NULL && - (iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) - get_addr(family, &iter->current.dstaddress, dst_sa, - iter->current.name); - - return (ISC_R_SUCCESS); - } else { - printf(isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERSYSCTL, - ISC_MSG_UNEXPECTEDTYPE, - "warning: unexpected interface list " - "message type\n")); - return (ISC_R_IGNORE); - } -} - -/* - * Step the iterator to the next interface. Unlike - * isc_interfaceiter_next(), this may leave the iterator - * positioned on an interface that will ultimately - * be ignored. Return ISC_R_NOMORE if there are no more - * interfaces, otherwise ISC_R_SUCCESS. - */ -static isc_result_t -internal_next(isc_interfaceiter_t *iter) { - struct ifa_msghdr *ifam; - REQUIRE (iter->pos < (unsigned int) iter->bufused); - - ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos); - - iter->pos += ifam->ifam_msglen; - - if (iter->pos >= iter->bufused) - return (ISC_R_NOMORE); - - return (ISC_R_SUCCESS); -} - -static void -internal_destroy(isc_interfaceiter_t *iter) { - UNUSED(iter); /* Unused. */ - /* - * Do nothing. - */ -} - -static -void internal_first(isc_interfaceiter_t *iter) { - iter->pos = 0; -} diff --git a/contrib/bind9/lib/isc/unix/include/Makefile.in b/contrib/bind9/lib/isc/unix/include/Makefile.in deleted file mode 100644 index 46c243e..0000000 --- a/contrib/bind9/lib/isc/unix/include/Makefile.in +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (C) 2004, 2007, 2012 Internet Systems Consortium, Inc. ("ISC") -# Copyright (C) 1998-2001 Internet Software Consortium. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -# PERFORMANCE OF THIS SOFTWARE. - -# $Id: Makefile.in,v 1.14 2007/06/19 23:47:18 tbox Exp $ - -srcdir = @srcdir@ -VPATH = @srcdir@ -top_srcdir = @top_srcdir@ - -SUBDIRS = isc -TARGETS = - -@BIND9_MAKE_RULES@ diff --git a/contrib/bind9/lib/isc/unix/include/isc/Makefile.in b/contrib/bind9/lib/isc/unix/include/isc/Makefile.in deleted file mode 100644 index d3b5084..0000000 --- a/contrib/bind9/lib/isc/unix/include/isc/Makefile.in +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (C) 2004, 2007, 2012 Internet Systems Consortium, Inc. ("ISC") -# Copyright (C) 1998-2001 Internet Software Consortium. -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -# PERFORMANCE OF THIS SOFTWARE. - -# $Id: Makefile.in,v 1.30 2007/06/19 23:47:19 tbox Exp $ - -srcdir = @srcdir@ -VPATH = @srcdir@ -top_srcdir = @top_srcdir@ - -@BIND9_VERSION@ - -HEADERS = dir.h int.h net.h netdb.h offset.h stdtime.h \ - syslog.h time.h - -SUBDIRS = -TARGETS = - -@BIND9_MAKE_RULES@ - -installdirs: - $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc - -install:: installdirs - for i in ${HEADERS}; do \ - ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \ - done diff --git a/contrib/bind9/lib/isc/unix/include/isc/dir.h b/contrib/bind9/lib/isc/unix/include/isc/dir.h deleted file mode 100644 index e4a2ad0..0000000 --- a/contrib/bind9/lib/isc/unix/include/isc/dir.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: dir.h,v 1.21 2007/06/19 23:47:19 tbox Exp $ */ - -/* Principal Authors: DCL */ - -#ifndef ISC_DIR_H -#define ISC_DIR_H 1 - -/*! \file */ - -#include <sys/types.h> /* Required on some systems. */ -#include <dirent.h> - -#include <isc/lang.h> -#include <isc/result.h> - -#define ISC_DIR_NAMEMAX 256 -#define ISC_DIR_PATHMAX 1024 - -/*% Directory Entry */ -typedef struct isc_direntry { - /*! - * Ideally, this should be NAME_MAX, but AIX does not define it by - * default and dynamically allocating the space based on pathconf() - * complicates things undesirably, as does adding special conditionals - * just for AIX. So a comfortably sized buffer is chosen instead. - */ - char name[ISC_DIR_NAMEMAX]; - unsigned int length; -} isc_direntry_t; - -/*% Directory */ -typedef struct isc_dir { - unsigned int magic; - /*! - * As with isc_direntry_t->name, making this "right" for all systems - * is slightly problematic because AIX does not define PATH_MAX. - */ - char dirname[ISC_DIR_PATHMAX]; - isc_direntry_t entry; - DIR * handle; -} isc_dir_t; - -ISC_LANG_BEGINDECLS - -void -isc_dir_init(isc_dir_t *dir); - -isc_result_t -isc_dir_open(isc_dir_t *dir, const char *dirname); - -isc_result_t -isc_dir_read(isc_dir_t *dir); - -isc_result_t -isc_dir_reset(isc_dir_t *dir); - -void -isc_dir_close(isc_dir_t *dir); - -isc_result_t -isc_dir_chdir(const char *dirname); - -isc_result_t -isc_dir_chroot(const char *dirname); - -isc_result_t -isc_dir_createunique(char *templet); -/*!< - * Use a templet (such as from isc_file_mktemplate()) to create a uniquely - * named, empty directory. The templet string is modified in place. - * If result == ISC_R_SUCCESS, it is the name of the directory that was - * created. - */ - -ISC_LANG_ENDDECLS - -#endif /* ISC_DIR_H */ diff --git a/contrib/bind9/lib/isc/unix/include/isc/int.h b/contrib/bind9/lib/isc/unix/include/isc/int.h deleted file mode 100644 index 73feb3b..0000000 --- a/contrib/bind9/lib/isc/unix/include/isc/int.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: int.h,v 1.16 2007/06/19 23:47:19 tbox Exp $ */ - -#ifndef ISC_INT_H -#define ISC_INT_H 1 - -/*! \file */ - -typedef char isc_int8_t; -typedef unsigned char isc_uint8_t; -typedef short isc_int16_t; -typedef unsigned short isc_uint16_t; -typedef int isc_int32_t; -typedef unsigned int isc_uint32_t; -typedef long long isc_int64_t; -typedef unsigned long long isc_uint64_t; - -#define ISC_INT8_MIN -128 -#define ISC_INT8_MAX 127 -#define ISC_UINT8_MAX 255 - -#define ISC_INT16_MIN -32768 -#define ISC_INT16_MAX 32767 -#define ISC_UINT16_MAX 65535 - -/*% - * Note that "int" is 32 bits on all currently supported Unix-like operating - * systems, but "long" can be either 32 bits or 64 bits, thus the 32 bit - * constants are not qualified with "L". - */ -#define ISC_INT32_MIN -2147483648 -#define ISC_INT32_MAX 2147483647 -#define ISC_UINT32_MAX 4294967295U - -#define ISC_INT64_MIN -9223372036854775808LL -#define ISC_INT64_MAX 9223372036854775807LL -#define ISC_UINT64_MAX 18446744073709551615ULL - -#endif /* ISC_INT_H */ diff --git a/contrib/bind9/lib/isc/unix/include/isc/keyboard.h b/contrib/bind9/lib/isc/unix/include/isc/keyboard.h deleted file mode 100644 index 43f5e7e..0000000 --- a/contrib/bind9/lib/isc/unix/include/isc/keyboard.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2000, 2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: keyboard.h,v 1.11 2007/06/19 23:47:19 tbox Exp $ */ - -#ifndef ISC_KEYBOARD_H -#define ISC_KEYBOARD_H 1 - -/*! \file */ - -#include <termios.h> - -#include <isc/lang.h> -#include <isc/result.h> - -ISC_LANG_BEGINDECLS - -typedef struct { - int fd; - struct termios saved_mode; - isc_result_t result; -} isc_keyboard_t; - -isc_result_t -isc_keyboard_open(isc_keyboard_t *keyboard); - -isc_result_t -isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleepseconds); - -isc_result_t -isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp); - -isc_boolean_t -isc_keyboard_canceled(isc_keyboard_t *keyboard); - -ISC_LANG_ENDDECLS - -#endif /* ISC_KEYBOARD_H */ diff --git a/contrib/bind9/lib/isc/unix/include/isc/net.h b/contrib/bind9/lib/isc/unix/include/isc/net.h deleted file mode 100644 index efa67c2..0000000 --- a/contrib/bind9/lib/isc/unix/include/isc/net.h +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007, 2008, 2012 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id$ */ - -#ifndef ISC_NET_H -#define ISC_NET_H 1 - -/***** - ***** Module Info - *****/ - -/*! \file - * \brief - * Basic Networking Types - * - * This module is responsible for defining the following basic networking - * types: - * - *\li struct in_addr - *\li struct in6_addr - *\li struct in6_pktinfo - *\li struct sockaddr - *\li struct sockaddr_in - *\li struct sockaddr_in6 - *\li in_port_t - * - * It ensures that the AF_ and PF_ macros are defined. - * - * It declares ntoh[sl]() and hton[sl](). - * - * It declares inet_aton(), inet_ntop(), and inet_pton(). - * - * It ensures that #INADDR_LOOPBACK, #INADDR_ANY, #IN6ADDR_ANY_INIT, - * in6addr_any, and in6addr_loopback are available. - * - * It ensures that IN_MULTICAST() is available to check for multicast - * addresses. - * - * MP: - *\li No impact. - * - * Reliability: - *\li No anticipated impact. - * - * Resources: - *\li N/A. - * - * Security: - *\li No anticipated impact. - * - * Standards: - *\li BSD Socket API - *\li RFC2553 - */ - -/*** - *** Imports. - ***/ -#include <isc/platform.h> - -#include <sys/types.h> -#include <sys/socket.h> /* Contractual promise. */ - -#include <net/if.h> - -#include <netinet/in.h> /* Contractual promise. */ -#include <arpa/inet.h> /* Contractual promise. */ -#ifdef ISC_PLATFORM_NEEDNETINETIN6H -#include <netinet/in6.h> /* Required on UnixWare. */ -#endif -#ifdef ISC_PLATFORM_NEEDNETINET6IN6H -#include <netinet6/in6.h> /* Required on BSD/OS for in6_pktinfo. */ -#endif - -#ifndef ISC_PLATFORM_HAVEIPV6 -#include <isc/ipv6.h> /* Contractual promise. */ -#endif - -#include <isc/lang.h> -#include <isc/types.h> - -#ifdef ISC_PLATFORM_HAVEINADDR6 -#define in6_addr in_addr6 /*%< Required for pre RFC2133 implementations. */ -#endif - -#ifdef ISC_PLATFORM_HAVEIPV6 -#ifndef IN6ADDR_ANY_INIT -#ifdef s6_addr -/*% - * Required for some pre RFC2133 implementations. - * IN6ADDR_ANY_INIT and IN6ADDR_LOOPBACK_INIT were added in - * draft-ietf-ipngwg-bsd-api-04.txt or draft-ietf-ipngwg-bsd-api-05.txt. - * If 's6_addr' is defined then assume that there is a union and three - * levels otherwise assume two levels required. - */ -#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } -#else -#define IN6ADDR_ANY_INIT { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } -#endif -#endif - -#ifndef IN6ADDR_LOOPBACK_INIT -#ifdef s6_addr -/*% IPv6 address loopback init */ -#define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } } -#else -#define IN6ADDR_LOOPBACK_INIT { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } -#endif -#endif - -#ifndef IN6_IS_ADDR_V4MAPPED -/*% Is IPv6 address V4 mapped? */ -#define IN6_IS_ADDR_V4MAPPED(x) \ - (memcmp((x)->s6_addr, in6addr_any.s6_addr, 10) == 0 && \ - (x)->s6_addr[10] == 0xff && (x)->s6_addr[11] == 0xff) -#endif - -#ifndef IN6_IS_ADDR_V4COMPAT -/*% Is IPv6 address V4 compatible? */ -#define IN6_IS_ADDR_V4COMPAT(x) \ - (memcmp((x)->s6_addr, in6addr_any.s6_addr, 12) == 0 && \ - ((x)->s6_addr[12] != 0 || (x)->s6_addr[13] != 0 || \ - (x)->s6_addr[14] != 0 || \ - ((x)->s6_addr[15] != 0 && (x)->s6_addr[15] != 1))) -#endif - -#ifndef IN6_IS_ADDR_MULTICAST -/*% Is IPv6 address multicast? */ -#define IN6_IS_ADDR_MULTICAST(a) ((a)->s6_addr[0] == 0xff) -#endif - -#ifndef IN6_IS_ADDR_LINKLOCAL -/*% Is IPv6 address linklocal? */ -#define IN6_IS_ADDR_LINKLOCAL(a) \ - (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80)) -#endif - -#ifndef IN6_IS_ADDR_SITELOCAL -/*% is IPv6 address sitelocal? */ -#define IN6_IS_ADDR_SITELOCAL(a) \ - (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0)) -#endif - - -#ifndef IN6_IS_ADDR_LOOPBACK -/*% is IPv6 address loopback? */ -#define IN6_IS_ADDR_LOOPBACK(x) \ - (memcmp((x)->s6_addr, in6addr_loopback.s6_addr, 16) == 0) -#endif -#endif - -#ifndef AF_INET6 -/*% IPv6 */ -#define AF_INET6 99 -#endif - -#ifndef PF_INET6 -/*% IPv6 */ -#define PF_INET6 AF_INET6 -#endif - -#ifndef INADDR_LOOPBACK -/*% inaddr loopback */ -#define INADDR_LOOPBACK 0x7f000001UL -#endif - -#ifndef ISC_PLATFORM_HAVEIN6PKTINFO -/*% IPv6 packet info */ -struct in6_pktinfo { - struct in6_addr ipi6_addr; /*%< src/dst IPv6 address */ - unsigned int ipi6_ifindex; /*%< send/recv interface index */ -}; -#endif - -#if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRANY) -extern const struct in6_addr isc_net_in6addrany; -/*% - * Cope with a missing in6addr_any and in6addr_loopback. - */ -#define in6addr_any isc_net_in6addrany -#endif - -#if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRLOOPBACK) -extern const struct in6_addr isc_net_in6addrloop; -#define in6addr_loopback isc_net_in6addrloop -#endif - -#ifdef ISC_PLATFORM_FIXIN6ISADDR -#undef IN6_IS_ADDR_GEOGRAPHIC -/*! - * \brief - * Fix UnixWare 7.1.1's broken IN6_IS_ADDR_* definitions. - */ -#define IN6_IS_ADDR_GEOGRAPHIC(a) (((a)->S6_un.S6_l[0] & 0xE0) == 0x80) -#undef IN6_IS_ADDR_IPX -#define IN6_IS_ADDR_IPX(a) (((a)->S6_un.S6_l[0] & 0xFE) == 0x04) -#undef IN6_IS_ADDR_LINKLOCAL -#define IN6_IS_ADDR_LINKLOCAL(a) (((a)->S6_un.S6_l[0] & 0xC0FF) == 0x80FE) -#undef IN6_IS_ADDR_MULTICAST -#define IN6_IS_ADDR_MULTICAST(a) (((a)->S6_un.S6_l[0] & 0xFF) == 0xFF) -#undef IN6_IS_ADDR_NSAP -#define IN6_IS_ADDR_NSAP(a) (((a)->S6_un.S6_l[0] & 0xFE) == 0x02) -#undef IN6_IS_ADDR_PROVIDER -#define IN6_IS_ADDR_PROVIDER(a) (((a)->S6_un.S6_l[0] & 0xE0) == 0x40) -#undef IN6_IS_ADDR_SITELOCAL -#define IN6_IS_ADDR_SITELOCAL(a) (((a)->S6_un.S6_l[0] & 0xC0FF) == 0xC0FE) -#endif /* ISC_PLATFORM_FIXIN6ISADDR */ - -#ifdef ISC_PLATFORM_NEEDPORTT -/*% - * Ensure type in_port_t is defined. - */ -typedef isc_uint16_t in_port_t; -#endif - -#ifndef MSG_TRUNC -/*% - * If this system does not have MSG_TRUNC (as returned from recvmsg()) - * ISC_PLATFORM_RECVOVERFLOW will be defined. This will enable the MSG_TRUNC - * faking code in socket.c. - */ -#define ISC_PLATFORM_RECVOVERFLOW -#endif - -/*% IP address. */ -#define ISC__IPADDR(x) ((isc_uint32_t)htonl((isc_uint32_t)(x))) - -/*% Is IP address multicast? */ -#define ISC_IPADDR_ISMULTICAST(i) \ - (((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \ - == ISC__IPADDR(0xe0000000)) - -#define ISC_IPADDR_ISEXPERIMENTAL(i) \ - (((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \ - == ISC__IPADDR(0xf0000000)) - -/*** - *** Functions. - ***/ - -ISC_LANG_BEGINDECLS - -isc_result_t -isc_net_probeipv4(void); -/*%< - * Check if the system's kernel supports IPv4. - * - * Returns: - * - *\li #ISC_R_SUCCESS IPv4 is supported. - *\li #ISC_R_NOTFOUND IPv4 is not supported. - *\li #ISC_R_DISABLED IPv4 is disabled. - *\li #ISC_R_UNEXPECTED - */ - -isc_result_t -isc_net_probeipv6(void); -/*%< - * Check if the system's kernel supports IPv6. - * - * Returns: - * - *\li #ISC_R_SUCCESS IPv6 is supported. - *\li #ISC_R_NOTFOUND IPv6 is not supported. - *\li #ISC_R_DISABLED IPv6 is disabled. - *\li #ISC_R_UNEXPECTED - */ - -isc_result_t -isc_net_probe_ipv6only(void); -/*%< - * Check if the system's kernel supports the IPV6_V6ONLY socket option. - * - * Returns: - * - *\li #ISC_R_SUCCESS the option is supported for both TCP and UDP. - *\li #ISC_R_NOTFOUND IPv6 itself or the option is not supported. - *\li #ISC_R_UNEXPECTED - */ - -isc_result_t -isc_net_probe_ipv6pktinfo(void); -/* - * Check if the system's kernel supports the IPV6_(RECV)PKTINFO socket option - * for UDP sockets. - * - * Returns: - * - * \li #ISC_R_SUCCESS the option is supported. - * \li #ISC_R_NOTFOUND IPv6 itself or the option is not supported. - * \li #ISC_R_UNEXPECTED - */ - -void -isc_net_disableipv4(void); - -void -isc_net_disableipv6(void); - -void -isc_net_enableipv4(void); - -void -isc_net_enableipv6(void); - -isc_result_t -isc_net_probeunix(void); -/* - * Returns whether UNIX domain sockets are supported. - */ - -isc_result_t -isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high); -/*%< - * Returns system's default range of ephemeral UDP ports, if defined. - * If the range is not available or unknown, ISC_NET_PORTRANGELOW and - * ISC_NET_PORTRANGEHIGH will be returned. - * - * Requires: - * - *\li 'low' and 'high' must be non NULL. - * - * Returns: - * - *\li *low and *high will be the ports specifying the low and high ends of - * the range. - */ - -#ifdef ISC_PLATFORM_NEEDNTOP -const char * -isc_net_ntop(int af, const void *src, char *dst, size_t size); -#define inet_ntop isc_net_ntop -#endif - -#ifdef ISC_PLATFORM_NEEDPTON -int -isc_net_pton(int af, const char *src, void *dst); -#undef inet_pton -#define inet_pton isc_net_pton -#endif - -int -isc_net_aton(const char *cp, struct in_addr *addr); -#undef inet_aton -#define inet_aton isc_net_aton - -ISC_LANG_ENDDECLS - -#endif /* ISC_NET_H */ diff --git a/contrib/bind9/lib/isc/unix/include/isc/netdb.h b/contrib/bind9/lib/isc/unix/include/isc/netdb.h deleted file mode 100644 index ff12a26..0000000 --- a/contrib/bind9/lib/isc/unix/include/isc/netdb.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: netdb.h,v 1.11 2007/06/19 23:47:19 tbox Exp $ */ - -#ifndef ISC_NETDB_H -#define ISC_NETDB_H 1 - -/***** - ***** Module Info - *****/ - -/*! \file - * \brief - * Portable netdb.h support. - * - * This module is responsible for defining the get<x>by<y> APIs. - * - * MP: - *\li No impact. - * - * Reliability: - *\li No anticipated impact. - * - * Resources: - *\li N/A. - * - * Security: - *\li No anticipated impact. - * - * Standards: - *\li BSD API - */ - -/*** - *** Imports. - ***/ - -#include <isc/net.h> - -#include <netdb.h> - -#endif /* ISC_NETDB_H */ diff --git a/contrib/bind9/lib/isc/unix/include/isc/offset.h b/contrib/bind9/lib/isc/unix/include/isc/offset.h deleted file mode 100644 index 8bf3779..0000000 --- a/contrib/bind9/lib/isc/unix/include/isc/offset.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2000, 2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: offset.h,v 1.17 2008/12/01 23:47:45 tbox Exp $ */ - -#ifndef ISC_OFFSET_H -#define ISC_OFFSET_H 1 - -/*! \file - * \brief - * File offsets are operating-system dependent. - */ -#include <limits.h> /* Required for CHAR_BIT. */ -#include <sys/types.h> -#include <stddef.h> /* For Linux Standard Base. */ - -typedef off_t isc_offset_t; - -/*% - * POSIX says "Additionally, blkcnt_t and off_t are extended signed integral - * types", so the maximum value is all 1s except for the high bit. - * This definition is more complex than it really needs to be because it was - * crafted to keep both the SunOS 5.6 and the HP/UX 11 compilers quiet about - * integer overflow. For example, though this is equivalent to just left - * shifting 1 to the high bit and then inverting the bits, the SunOS compiler - * is unhappy about shifting a positive "1" to negative in a signed integer. - */ -#define ISC_OFFSET_MAXIMUM \ - (~(((off_t)-1 >> (sizeof(off_t) * CHAR_BIT - 1)) \ - << (sizeof(off_t) * CHAR_BIT - 1))) - -#endif /* ISC_OFFSET_H */ diff --git a/contrib/bind9/lib/isc/unix/include/isc/stat.h b/contrib/bind9/lib/isc/unix/include/isc/stat.h deleted file mode 100644 index b7a7986..0000000 --- a/contrib/bind9/lib/isc/unix/include/isc/stat.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: stat.h,v 1.5 2007/06/19 23:47:19 tbox Exp $ */ - -#ifndef ISC_STAT_H -#define ISC_STAT_H 1 - -/***** - ***** Module Info - *****/ - -/* - * Portable netdb.h support. - * - * This module is responsible for defining S_IS??? macros. - * - * MP: - * No impact. - * - * Reliability: - * No anticipated impact. - * - * Resources: - * N/A. - * - * Security: - * No anticipated impact. - * - */ - -/*** - *** Imports. - ***/ - -#include <sys/types.h> -#include <sys/stat.h> - -#endif /* ISC_STAT_H */ diff --git a/contrib/bind9/lib/isc/unix/include/isc/stdtime.h b/contrib/bind9/lib/isc/unix/include/isc/stdtime.h deleted file mode 100644 index c4931bf..0000000 --- a/contrib/bind9/lib/isc/unix/include/isc/stdtime.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id$ */ - -#ifndef ISC_STDTIME_H -#define ISC_STDTIME_H 1 - -/*! \file */ - -#include <isc/lang.h> -#include <isc/int.h> - -/*% - * It's public information that 'isc_stdtime_t' is an unsigned integral type. - * Applications that want maximum portability should not assume anything - * about its size. - */ -typedef isc_uint32_t isc_stdtime_t; - -/* but this flag helps... */ -#define STDTIME_ON_32BITS 1 - -/* - * isc_stdtime32_t is a 32-bit version of isc_stdtime_t. A variable of this - * type should only be used as an opaque integer (e.g.,) to compare two - * time values. - */ -typedef isc_uint32_t isc_stdtime32_t; - -ISC_LANG_BEGINDECLS -/* */ -void -isc_stdtime_get(isc_stdtime_t *t); -/*%< - * Set 't' to the number of seconds since 00:00:00 UTC, January 1, 1970. - * - * Requires: - * - *\li 't' is a valid pointer. - */ - -#define isc_stdtime_convert32(t, t32p) (*(t32p) = t) -/* - * Convert the standard time to its 32-bit version. - */ - -ISC_LANG_ENDDECLS - -#endif /* ISC_STDTIME_H */ diff --git a/contrib/bind9/lib/isc/unix/include/isc/strerror.h b/contrib/bind9/lib/isc/unix/include/isc/strerror.h deleted file mode 100644 index 899043b..0000000 --- a/contrib/bind9/lib/isc/unix/include/isc/strerror.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: strerror.h,v 1.10 2008/12/01 23:47:45 tbox Exp $ */ - -#ifndef ISC_STRERROR_H -#define ISC_STRERROR_H - -/*! \file */ - -#include <sys/types.h> - -#include <isc/lang.h> - -ISC_LANG_BEGINDECLS - -/*% String Error Size */ -#define ISC_STRERRORSIZE 128 - -/*% - * Provide a thread safe wrapper to strerror(). - * - * Requires: - * 'buf' to be non NULL. - */ -void -isc__strerror(int num, char *buf, size_t bufsize); - -ISC_LANG_ENDDECLS - -#endif /* ISC_STRERROR_H */ diff --git a/contrib/bind9/lib/isc/unix/include/isc/syslog.h b/contrib/bind9/lib/isc/unix/include/isc/syslog.h deleted file mode 100644 index 7e0c88c..0000000 --- a/contrib/bind9/lib/isc/unix/include/isc/syslog.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: syslog.h,v 1.7 2007/06/19 23:47:19 tbox Exp $ */ - -#ifndef ISC_SYSLOG_H -#define ISC_SYSLOG_H 1 - -/*! \file */ - -#include <isc/lang.h> -#include <isc/types.h> - -ISC_LANG_BEGINDECLS - -isc_result_t -isc_syslog_facilityfromstring(const char *str, int *facilityp); -/*%< - * Convert 'str' to the appropriate syslog facility constant. - * - * Requires: - * - *\li 'str' is not NULL - *\li 'facilityp' is not NULL - * - * Returns: - * \li #ISC_R_SUCCESS - * \li #ISC_R_NOTFOUND - */ - -ISC_LANG_ENDDECLS - -#endif /* ISC_SYSLOG_H */ diff --git a/contrib/bind9/lib/isc/unix/include/isc/time.h b/contrib/bind9/lib/isc/unix/include/isc/time.h deleted file mode 100644 index d81d854..0000000 --- a/contrib/bind9/lib/isc/unix/include/isc/time.h +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1998-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: time.h,v 1.40 2009/01/05 23:47:54 tbox Exp $ */ - -#ifndef ISC_TIME_H -#define ISC_TIME_H 1 - -/*! \file */ - -#include <isc/lang.h> -#include <isc/types.h> - -/*** - *** Intervals - ***/ - -/*! - * \brief - * The contents of this structure are private, and MUST NOT be accessed - * directly by callers. - * - * The contents are exposed only to allow callers to avoid dynamic allocation. - */ -struct isc_interval { - unsigned int seconds; - unsigned int nanoseconds; -}; - -extern const isc_interval_t * const isc_interval_zero; - -ISC_LANG_BEGINDECLS - -void -isc_interval_set(isc_interval_t *i, - unsigned int seconds, unsigned int nanoseconds); -/*%< - * Set 'i' to a value representing an interval of 'seconds' seconds and - * 'nanoseconds' nanoseconds, suitable for use in isc_time_add() and - * isc_time_subtract(). - * - * Requires: - * - *\li 't' is a valid pointer. - *\li nanoseconds < 1000000000. - */ - -isc_boolean_t -isc_interval_iszero(const isc_interval_t *i); -/*%< - * Returns ISC_TRUE iff. 'i' is the zero interval. - * - * Requires: - * - *\li 'i' is a valid pointer. - */ - -/*** - *** Absolute Times - ***/ - -/*% - * The contents of this structure are private, and MUST NOT be accessed - * directly by callers. - * - * The contents are exposed only to allow callers to avoid dynamic allocation. - */ - -struct isc_time { - unsigned int seconds; - unsigned int nanoseconds; -}; - -extern const isc_time_t * const isc_time_epoch; - -void -isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds); -/*%< - * Set 't' to a value which represents the given number of seconds and - * nanoseconds since 00:00:00 January 1, 1970, UTC. - * - * Notes: - *\li The Unix version of this call is equivalent to: - *\code - * isc_time_settoepoch(t); - * isc_interval_set(i, seconds, nanoseconds); - * isc_time_add(t, i, t); - *\endcode - * - * Requires: - *\li 't' is a valid pointer. - *\li nanoseconds < 1000000000. - */ - -void -isc_time_settoepoch(isc_time_t *t); -/*%< - * Set 't' to the time of the epoch. - * - * Notes: - *\li The date of the epoch is platform-dependent. - * - * Requires: - * - *\li 't' is a valid pointer. - */ - -isc_boolean_t -isc_time_isepoch(const isc_time_t *t); -/*%< - * Returns ISC_TRUE iff. 't' is the epoch ("time zero"). - * - * Requires: - * - *\li 't' is a valid pointer. - */ - -isc_result_t -isc_time_now(isc_time_t *t); -/*%< - * Set 't' to the current absolute time. - * - * Requires: - * - *\li 't' is a valid pointer. - * - * Returns: - * - *\li Success - *\li Unexpected error - * Getting the time from the system failed. - *\li Out of range - * The time from the system is too large to be represented - * in the current definition of isc_time_t. - */ - -isc_result_t -isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i); -/*%< - * Set *t to the current absolute time + i. - * - * Note: - *\li This call is equivalent to: - * - *\code - * isc_time_now(t); - * isc_time_add(t, i, t); - *\endcode - * - * Requires: - * - *\li 't' and 'i' are valid pointers. - * - * Returns: - * - *\li Success - *\li Unexpected error - * Getting the time from the system failed. - *\li Out of range - * The interval added to the time from the system is too large to - * be represented in the current definition of isc_time_t. - */ - -int -isc_time_compare(const isc_time_t *t1, const isc_time_t *t2); -/*%< - * Compare the times referenced by 't1' and 't2' - * - * Requires: - * - *\li 't1' and 't2' are valid pointers. - * - * Returns: - * - *\li -1 t1 < t2 (comparing times, not pointers) - *\li 0 t1 = t2 - *\li 1 t1 > t2 - */ - -isc_result_t -isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result); -/*%< - * Add 'i' to 't', storing the result in 'result'. - * - * Requires: - * - *\li 't', 'i', and 'result' are valid pointers. - * - * Returns: - *\li Success - *\li Out of range - * The interval added to the time is too large to - * be represented in the current definition of isc_time_t. - */ - -isc_result_t -isc_time_subtract(const isc_time_t *t, const isc_interval_t *i, - isc_time_t *result); -/*%< - * Subtract 'i' from 't', storing the result in 'result'. - * - * Requires: - * - *\li 't', 'i', and 'result' are valid pointers. - * - * Returns: - *\li Success - *\li Out of range - * The interval is larger than the time since the epoch. - */ - -isc_uint64_t -isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2); -/*%< - * Find the difference in microseconds between time t1 and time t2. - * t2 is the subtrahend of t1; ie, difference = t1 - t2. - * - * Requires: - * - *\li 't1' and 't2' are valid pointers. - * - * Returns: - *\li The difference of t1 - t2, or 0 if t1 <= t2. - */ - -isc_uint32_t -isc_time_seconds(const isc_time_t *t); -/*%< - * Return the number of seconds since the epoch stored in a time structure. - * - * Requires: - * - *\li 't' is a valid pointer. - */ - -isc_result_t -isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp); -/*%< - * Ensure the number of seconds in an isc_time_t is representable by a time_t. - * - * Notes: - *\li The number of seconds stored in an isc_time_t might be larger - * than the number of seconds a time_t is able to handle. Since - * time_t is mostly opaque according to the ANSI/ISO standard - * (essentially, all you can be sure of is that it is an arithmetic type, - * not even necessarily integral), it can be tricky to ensure that - * the isc_time_t is in the range a time_t can handle. Use this - * function in place of isc_time_seconds() any time you need to set a - * time_t from an isc_time_t. - * - * Requires: - *\li 't' is a valid pointer. - * - * Returns: - *\li Success - *\li Out of range - */ - -isc_uint32_t -isc_time_nanoseconds(const isc_time_t *t); -/*%< - * Return the number of nanoseconds stored in a time structure. - * - * Notes: - *\li This is the number of nanoseconds in excess of the number - * of seconds since the epoch; it will always be less than one - * full second. - * - * Requires: - *\li 't' is a valid pointer. - * - * Ensures: - *\li The returned value is less than 1*10^9. - */ - -void -isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len); -/*%< - * Format the time 't' into the buffer 'buf' of length 'len', - * using a format like "30-Aug-2000 04:06:47.997" and the local time zone. - * If the text does not fit in the buffer, the result is indeterminate, - * but is always guaranteed to be null terminated. - * - * Requires: - *\li 'len' > 0 - *\li 'buf' points to an array of at least len chars - * - */ - -void -isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len); -/*%< - * Format the time 't' into the buffer 'buf' of length 'len', - * using a format like "Mon, 30 Aug 2000 04:06:47 GMT" - * If the text does not fit in the buffer, the result is indeterminate, - * but is always guaranteed to be null terminated. - * - * Requires: - *\li 'len' > 0 - *\li 'buf' points to an array of at least len chars - * - */ - -void -isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len); -/*%< - * Format the time 't' into the buffer 'buf' of length 'len', - * using the ISO8601 format: "yyyy-mm-ddThh:mm:ssZ" - * If the text does not fit in the buffer, the result is indeterminate, - * but is always guaranteed to be null terminated. - * - * Requires: - *\li 'len' > 0 - *\li 'buf' points to an array of at least len chars - * - */ - -ISC_LANG_ENDDECLS - -#endif /* ISC_TIME_H */ diff --git a/contrib/bind9/lib/isc/unix/interfaceiter.c b/contrib/bind9/lib/isc/unix/interfaceiter.c deleted file mode 100644 index af2b06d..0000000 --- a/contrib/bind9/lib/isc/unix/interfaceiter.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: interfaceiter.c,v 1.45 2008/12/01 03:51:47 marka Exp $ */ - -/*! \file */ - -#include <config.h> - -#include <sys/types.h> -#include <sys/ioctl.h> -#ifdef HAVE_SYS_SOCKIO_H -#include <sys/sockio.h> /* Required for ifiter_ioctl.c. */ -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> - -#include <isc/interfaceiter.h> -#include <isc/log.h> -#include <isc/magic.h> -#include <isc/mem.h> -#include <isc/msgs.h> -#include <isc/net.h> -#include <isc/print.h> -#include <isc/result.h> -#include <isc/strerror.h> -#include <isc/string.h> -#include <isc/types.h> -#include <isc/util.h> - -/* Must follow <isc/net.h>. */ -#ifdef HAVE_NET_IF6_H -#include <net/if6.h> -#endif -#include <net/if.h> - -/* Common utility functions */ - -/*% - * Extract the network address part from a "struct sockaddr". - * \brief - * The address family is given explicitly - * instead of using src->sa_family, because the latter does not work - * for copying a network mask obtained by SIOCGIFNETMASK (it does - * not have a valid address family). - */ - -static void -get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src, - char *ifname) -{ - struct sockaddr_in6 *sa6; - -#if !defined(ISC_PLATFORM_HAVEIFNAMETOINDEX) || \ - !defined(ISC_PLATFORM_HAVESCOPEID) - UNUSED(ifname); -#endif - - /* clear any remaining value for safety */ - memset(dst, 0, sizeof(*dst)); - - dst->family = family; - switch (family) { - case AF_INET: - memcpy(&dst->type.in, - &((struct sockaddr_in *) src)->sin_addr, - sizeof(struct in_addr)); - break; - case AF_INET6: - sa6 = (struct sockaddr_in6 *)src; - memcpy(&dst->type.in6, &sa6->sin6_addr, - sizeof(struct in6_addr)); -#ifdef ISC_PLATFORM_HAVESCOPEID - if (sa6->sin6_scope_id != 0) - isc_netaddr_setzone(dst, sa6->sin6_scope_id); - else { - /* - * BSD variants embed scope zone IDs in the 128bit - * address as a kernel internal form. Unfortunately, - * the embedded IDs are not hidden from applications - * when getting access to them by sysctl or ioctl. - * We convert the internal format to the pure address - * part and the zone ID part. - * Since multicast addresses should not appear here - * and they cannot be distinguished from netmasks, - * we only consider unicast link-local addresses. - */ - if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) { - isc_uint16_t zone16; - - memcpy(&zone16, &sa6->sin6_addr.s6_addr[2], - sizeof(zone16)); - zone16 = ntohs(zone16); - if (zone16 != 0) { - /* the zone ID is embedded */ - isc_netaddr_setzone(dst, - (isc_uint32_t)zone16); - dst->type.in6.s6_addr[2] = 0; - dst->type.in6.s6_addr[3] = 0; -#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX - } else if (ifname != NULL) { - unsigned int zone; - - /* - * sin6_scope_id is still not provided, - * but the corresponding interface name - * is know. Use the interface ID as - * the link ID. - */ - zone = if_nametoindex(ifname); - if (zone != 0) { - isc_netaddr_setzone(dst, - (isc_uint32_t)zone); - } -#endif - } - } - } -#endif - break; - default: - INSIST(0); - break; - } -} - -/* - * Include system-dependent code. - */ - -#ifdef __linux -#define ISC_IF_INET6_SZ \ - sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n") -static isc_result_t linux_if_inet6_next(isc_interfaceiter_t *); -static isc_result_t linux_if_inet6_current(isc_interfaceiter_t *); -static void linux_if_inet6_first(isc_interfaceiter_t *iter); -#endif - -#if HAVE_GETIFADDRS -#include "ifiter_getifaddrs.c" -#elif HAVE_IFLIST_SYSCTL -#include "ifiter_sysctl.c" -#else -#include "ifiter_ioctl.c" -#endif - -#ifdef __linux -static void -linux_if_inet6_first(isc_interfaceiter_t *iter) { - if (iter->proc != NULL) { - rewind(iter->proc); - (void)linux_if_inet6_next(iter); - } else - iter->valid = ISC_R_NOMORE; -} - -static isc_result_t -linux_if_inet6_next(isc_interfaceiter_t *iter) { - if (iter->proc != NULL && - fgets(iter->entry, sizeof(iter->entry), iter->proc) != NULL) - iter->valid = ISC_R_SUCCESS; - else - iter->valid = ISC_R_NOMORE; - return (iter->valid); -} - -static isc_result_t -linux_if_inet6_current(isc_interfaceiter_t *iter) { - char address[33]; - char name[IF_NAMESIZE+1]; - struct in6_addr addr6; - int ifindex, prefix, flag3, flag4; - int res; - unsigned int i; - - if (iter->valid != ISC_R_SUCCESS) - return (iter->valid); - if (iter->proc == NULL) { - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, - "/proc/net/if_inet6:iter->proc == NULL"); - return (ISC_R_FAILURE); - } - - res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n", - address, &ifindex, &prefix, &flag3, &flag4, name); - if (res != 6) { - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, - "/proc/net/if_inet6:sscanf() -> %d (expected 6)", - res); - return (ISC_R_FAILURE); - } - if (strlen(address) != 32) { - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR, - "/proc/net/if_inet6:strlen(%s) != 32", address); - return (ISC_R_FAILURE); - } - for (i = 0; i < 16; i++) { - unsigned char byte; - static const char hex[] = "0123456789abcdef"; - byte = ((strchr(hex, address[i * 2]) - hex) << 4) | - (strchr(hex, address[i * 2 + 1]) - hex); - addr6.s6_addr[i] = byte; - } - iter->current.af = AF_INET6; - iter->current.flags = INTERFACE_F_UP; - isc_netaddr_fromin6(&iter->current.address, &addr6); - if (isc_netaddr_islinklocal(&iter->current.address)) { - isc_netaddr_setzone(&iter->current.address, - (isc_uint32_t)ifindex); - } - for (i = 0; i < 16; i++) { - if (prefix > 8) { - addr6.s6_addr[i] = 0xff; - prefix -= 8; - } else { - addr6.s6_addr[i] = (0xff << (8 - prefix)) & 0xff; - prefix = 0; - } - } - isc_netaddr_fromin6(&iter->current.netmask, &addr6); - strncpy(iter->current.name, name, sizeof(iter->current.name)); - return (ISC_R_SUCCESS); -} -#endif - -/* - * The remaining code is common to the sysctl and ioctl case. - */ - -isc_result_t -isc_interfaceiter_current(isc_interfaceiter_t *iter, - isc_interface_t *ifdata) -{ - REQUIRE(iter->result == ISC_R_SUCCESS); - memcpy(ifdata, &iter->current, sizeof(*ifdata)); - return (ISC_R_SUCCESS); -} - -isc_result_t -isc_interfaceiter_first(isc_interfaceiter_t *iter) { - isc_result_t result; - - REQUIRE(VALID_IFITER(iter)); - - internal_first(iter); - for (;;) { - result = internal_current(iter); - if (result != ISC_R_IGNORE) - break; - result = internal_next(iter); - if (result != ISC_R_SUCCESS) - break; - } - iter->result = result; - return (result); -} - -isc_result_t -isc_interfaceiter_next(isc_interfaceiter_t *iter) { - isc_result_t result; - - REQUIRE(VALID_IFITER(iter)); - REQUIRE(iter->result == ISC_R_SUCCESS); - - for (;;) { - result = internal_next(iter); - if (result != ISC_R_SUCCESS) - break; - result = internal_current(iter); - if (result != ISC_R_IGNORE) - break; - } - iter->result = result; - return (result); -} - -void -isc_interfaceiter_destroy(isc_interfaceiter_t **iterp) -{ - isc_interfaceiter_t *iter; - REQUIRE(iterp != NULL); - iter = *iterp; - REQUIRE(VALID_IFITER(iter)); - - internal_destroy(iter); - if (iter->buf != NULL) - isc_mem_put(iter->mctx, iter->buf, iter->bufsize); - - iter->magic = 0; - isc_mem_put(iter->mctx, iter, sizeof(*iter)); - *iterp = NULL; -} diff --git a/contrib/bind9/lib/isc/unix/ipv6.c b/contrib/bind9/lib/isc/unix/ipv6.c deleted file mode 100644 index 61e984f..0000000 --- a/contrib/bind9/lib/isc/unix/ipv6.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: ipv6.c,v 1.14 2007/06/19 23:47:18 tbox Exp $ */ - -/*! \file */ - -#include <config.h> - -#include <isc/ipv6.h> - -const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; -const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; diff --git a/contrib/bind9/lib/isc/unix/keyboard.c b/contrib/bind9/lib/isc/unix/keyboard.c deleted file mode 100644 index 8ee62d3..0000000 --- a/contrib/bind9/lib/isc/unix/keyboard.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2000, 2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: keyboard.c,v 1.13 2007/06/19 23:47:18 tbox Exp $ */ - -#include <config.h> - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/uio.h> - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> -#include <fcntl.h> - -#include <isc/keyboard.h> -#include <isc/util.h> - -isc_result_t -isc_keyboard_open(isc_keyboard_t *keyboard) { - int fd; - isc_result_t ret; - struct termios current_mode; - - REQUIRE(keyboard != NULL); - - fd = open("/dev/tty", O_RDONLY, 0); - if (fd < 0) - return (ISC_R_IOERROR); - - keyboard->fd = fd; - - if (tcgetattr(fd, &keyboard->saved_mode) < 0) { - ret = ISC_R_IOERROR; - goto errout; - } - - current_mode = keyboard->saved_mode; - - current_mode.c_iflag &= - ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); - current_mode.c_oflag &= ~OPOST; - current_mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); - current_mode.c_cflag &= ~(CSIZE|PARENB); - current_mode.c_cflag |= CS8; - - current_mode.c_cc[VMIN] = 1; - current_mode.c_cc[VTIME] = 0; - if (tcsetattr(fd, TCSAFLUSH, ¤t_mode) < 0) { - ret = ISC_R_IOERROR; - goto errout; - } - - keyboard->result = ISC_R_SUCCESS; - - return (ISC_R_SUCCESS); - - errout: - close (fd); - - return (ret); -} - -isc_result_t -isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleeptime) { - REQUIRE(keyboard != NULL); - - if (sleeptime > 0 && keyboard->result != ISC_R_CANCELED) - (void)sleep(sleeptime); - - (void)tcsetattr(keyboard->fd, TCSAFLUSH, &keyboard->saved_mode); - (void)close(keyboard->fd); - - keyboard->fd = -1; - - return (ISC_R_SUCCESS); -} - -isc_result_t -isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp) { - ssize_t cc; - unsigned char c; - cc_t *controlchars; - - REQUIRE(keyboard != NULL); - REQUIRE(cp != NULL); - - cc = read(keyboard->fd, &c, 1); - if (cc < 0) { - keyboard->result = ISC_R_IOERROR; - return (keyboard->result); - } - - controlchars = keyboard->saved_mode.c_cc; - if (c == controlchars[VINTR] || c == controlchars[VQUIT]) { - keyboard->result = ISC_R_CANCELED; - return (keyboard->result); - } - - *cp = c; - - return (ISC_R_SUCCESS); -} - -isc_boolean_t -isc_keyboard_canceled(isc_keyboard_t *keyboard) { - return (ISC_TF(keyboard->result == ISC_R_CANCELED)); -} diff --git a/contrib/bind9/lib/isc/unix/net.c b/contrib/bind9/lib/isc/unix/net.c deleted file mode 100644 index 1fedbc4..0000000 --- a/contrib/bind9/lib/isc/unix/net.c +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007, 2008, 2012 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id$ */ - -#include <config.h> - -#include <sys/types.h> - -#if defined(HAVE_SYS_SYSCTL_H) -#if defined(HAVE_SYS_PARAM_H) -#include <sys/param.h> -#endif -#include <sys/sysctl.h> -#endif - -#include <errno.h> -#include <unistd.h> - -#include <isc/log.h> -#include <isc/msgs.h> -#include <isc/net.h> -#include <isc/once.h> -#include <isc/strerror.h> -#include <isc/string.h> -#include <isc/util.h> - -/*% - * Definitions about UDP port range specification. This is a total mess of - * portability variants: some use sysctl (but the sysctl names vary), some use - * system-specific interfaces, some have the same interface for IPv4 and IPv6, - * some separate them, etc... - */ - -/*% - * The last resort defaults: use all non well known port space - */ -#ifndef ISC_NET_PORTRANGELOW -#define ISC_NET_PORTRANGELOW 1024 -#endif /* ISC_NET_PORTRANGELOW */ -#ifndef ISC_NET_PORTRANGEHIGH -#define ISC_NET_PORTRANGEHIGH 65535 -#endif /* ISC_NET_PORTRANGEHIGH */ - -#ifdef HAVE_SYSCTLBYNAME - -/*% - * sysctl variants - */ -#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__) -#define USE_SYSCTL_PORTRANGE -#define SYSCTL_V4PORTRANGE_LOW "net.inet.ip.portrange.hifirst" -#define SYSCTL_V4PORTRANGE_HIGH "net.inet.ip.portrange.hilast" -#define SYSCTL_V6PORTRANGE_LOW "net.inet.ip.portrange.hifirst" -#define SYSCTL_V6PORTRANGE_HIGH "net.inet.ip.portrange.hilast" -#endif - -#ifdef __NetBSD__ -#define USE_SYSCTL_PORTRANGE -#define SYSCTL_V4PORTRANGE_LOW "net.inet.ip.anonportmin" -#define SYSCTL_V4PORTRANGE_HIGH "net.inet.ip.anonportmax" -#define SYSCTL_V6PORTRANGE_LOW "net.inet6.ip6.anonportmin" -#define SYSCTL_V6PORTRANGE_HIGH "net.inet6.ip6.anonportmax" -#endif - -#else /* !HAVE_SYSCTLBYNAME */ - -#ifdef __OpenBSD__ -#define USE_SYSCTL_PORTRANGE -#define SYSCTL_V4PORTRANGE_LOW { CTL_NET, PF_INET, IPPROTO_IP, \ - IPCTL_IPPORT_HIFIRSTAUTO } -#define SYSCTL_V4PORTRANGE_HIGH { CTL_NET, PF_INET, IPPROTO_IP, \ - IPCTL_IPPORT_HILASTAUTO } -/* Same for IPv6 */ -#define SYSCTL_V6PORTRANGE_LOW SYSCTL_V4PORTRANGE_LOW -#define SYSCTL_V6PORTRANGE_HIGH SYSCTL_V4PORTRANGE_HIGH -#endif - -#endif /* HAVE_SYSCTLBYNAME */ - -#if defined(ISC_PLATFORM_HAVEIPV6) -# if defined(ISC_PLATFORM_NEEDIN6ADDRANY) -const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT; -# endif - -# if defined(ISC_PLATFORM_NEEDIN6ADDRLOOPBACK) -const struct in6_addr isc_net_in6addrloop = IN6ADDR_LOOPBACK_INIT; -# endif - -# if defined(WANT_IPV6) -static isc_once_t once_ipv6only = ISC_ONCE_INIT; -# endif - -# if defined(ISC_PLATFORM_HAVEIN6PKTINFO) -static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT; -# endif -#endif /* ISC_PLATFORM_HAVEIPV6 */ - -static isc_once_t once = ISC_ONCE_INIT; - -static isc_result_t ipv4_result = ISC_R_NOTFOUND; -static isc_result_t ipv6_result = ISC_R_NOTFOUND; -static isc_result_t unix_result = ISC_R_NOTFOUND; -static isc_result_t ipv6only_result = ISC_R_NOTFOUND; -static isc_result_t ipv6pktinfo_result = ISC_R_NOTFOUND; - -static isc_result_t -try_proto(int domain) { - int s; - isc_result_t result = ISC_R_SUCCESS; - char strbuf[ISC_STRERRORSIZE]; - - s = socket(domain, SOCK_STREAM, 0); - if (s == -1) { - switch (errno) { -#ifdef EAFNOSUPPORT - case EAFNOSUPPORT: -#endif -#ifdef EPROTONOSUPPORT - case EPROTONOSUPPORT: -#endif -#ifdef EINVAL - case EINVAL: -#endif - return (ISC_R_NOTFOUND); - default: - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "socket() %s: %s", - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - return (ISC_R_UNEXPECTED); - } - } - -#ifdef ISC_PLATFORM_HAVEIPV6 -#ifdef WANT_IPV6 -#ifdef ISC_PLATFORM_HAVEIN6PKTINFO - if (domain == PF_INET6) { - struct sockaddr_in6 sin6; - unsigned int len; - - /* - * Check to see if IPv6 is broken, as is common on Linux. - */ - len = sizeof(sin6); - if (getsockname(s, (struct sockaddr *)&sin6, (void *)&len) < 0) - { - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - "retrieving the address of an IPv6 " - "socket from the kernel failed."); - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - "IPv6 is not supported."); - result = ISC_R_NOTFOUND; - } else { - if (len == sizeof(struct sockaddr_in6)) - result = ISC_R_SUCCESS; - else { - isc_log_write(isc_lctx, - ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, - ISC_LOG_ERROR, - "IPv6 structures in kernel and " - "user space do not match."); - isc_log_write(isc_lctx, - ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, - ISC_LOG_ERROR, - "IPv6 is not supported."); - result = ISC_R_NOTFOUND; - } - } - } -#endif -#endif -#endif - - (void)close(s); - - return (result); -} - -static void -initialize_action(void) { - ipv4_result = try_proto(PF_INET); -#ifdef ISC_PLATFORM_HAVEIPV6 -#ifdef WANT_IPV6 -#ifdef ISC_PLATFORM_HAVEIN6PKTINFO - ipv6_result = try_proto(PF_INET6); -#endif -#endif -#endif -#ifdef ISC_PLATFORM_HAVESYSUNH - unix_result = try_proto(PF_UNIX); -#endif -} - -static void -initialize(void) { - RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS); -} - -isc_result_t -isc_net_probeipv4(void) { - initialize(); - return (ipv4_result); -} - -isc_result_t -isc_net_probeipv6(void) { - initialize(); - return (ipv6_result); -} - -isc_result_t -isc_net_probeunix(void) { - initialize(); - return (unix_result); -} - -#ifdef ISC_PLATFORM_HAVEIPV6 -#ifdef WANT_IPV6 -static void -try_ipv6only(void) { -#ifdef IPV6_V6ONLY - int s, on; - char strbuf[ISC_STRERRORSIZE]; -#endif - isc_result_t result; - - result = isc_net_probeipv6(); - if (result != ISC_R_SUCCESS) { - ipv6only_result = result; - return; - } - -#ifndef IPV6_V6ONLY - ipv6only_result = ISC_R_NOTFOUND; - return; -#else - /* check for TCP sockets */ - s = socket(PF_INET6, SOCK_STREAM, 0); - if (s == -1) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "socket() %s: %s", - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - ipv6only_result = ISC_R_UNEXPECTED; - return; - } - - on = 1; - if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { - ipv6only_result = ISC_R_NOTFOUND; - goto close; - } - - close(s); - - /* check for UDP sockets */ - s = socket(PF_INET6, SOCK_DGRAM, 0); - if (s == -1) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "socket() %s: %s", - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - ipv6only_result = ISC_R_UNEXPECTED; - return; - } - - on = 1; - if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { - ipv6only_result = ISC_R_NOTFOUND; - goto close; - } - - ipv6only_result = ISC_R_SUCCESS; - -close: - close(s); - return; -#endif /* IPV6_V6ONLY */ -} - -static void -initialize_ipv6only(void) { - RUNTIME_CHECK(isc_once_do(&once_ipv6only, - try_ipv6only) == ISC_R_SUCCESS); -} -#endif /* WANT_IPV6 */ - -#ifdef ISC_PLATFORM_HAVEIN6PKTINFO -static void -try_ipv6pktinfo(void) { - int s, on; - char strbuf[ISC_STRERRORSIZE]; - isc_result_t result; - int optname; - - result = isc_net_probeipv6(); - if (result != ISC_R_SUCCESS) { - ipv6pktinfo_result = result; - return; - } - - /* we only use this for UDP sockets */ - s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); - if (s == -1) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "socket() %s: %s", - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - ipv6pktinfo_result = ISC_R_UNEXPECTED; - return; - } - -#ifdef IPV6_RECVPKTINFO - optname = IPV6_RECVPKTINFO; -#else - optname = IPV6_PKTINFO; -#endif - on = 1; - if (setsockopt(s, IPPROTO_IPV6, optname, &on, sizeof(on)) < 0) { - ipv6pktinfo_result = ISC_R_NOTFOUND; - goto close; - } - - ipv6pktinfo_result = ISC_R_SUCCESS; - -close: - close(s); - return; -} - -static void -initialize_ipv6pktinfo(void) { - RUNTIME_CHECK(isc_once_do(&once_ipv6pktinfo, - try_ipv6pktinfo) == ISC_R_SUCCESS); -} -#endif /* ISC_PLATFORM_HAVEIN6PKTINFO */ -#endif /* ISC_PLATFORM_HAVEIPV6 */ - -isc_result_t -isc_net_probe_ipv6only(void) { -#ifdef ISC_PLATFORM_HAVEIPV6 -#ifdef WANT_IPV6 - initialize_ipv6only(); -#else - ipv6only_result = ISC_R_NOTFOUND; -#endif -#endif - return (ipv6only_result); -} - -isc_result_t -isc_net_probe_ipv6pktinfo(void) { -#ifdef ISC_PLATFORM_HAVEIPV6 -#ifdef ISC_PLATFORM_HAVEIN6PKTINFO -#ifdef WANT_IPV6 - initialize_ipv6pktinfo(); -#else - ipv6pktinfo_result = ISC_R_NOTFOUND; -#endif -#endif -#endif - return (ipv6pktinfo_result); -} - -#if defined(USE_SYSCTL_PORTRANGE) -#if defined(HAVE_SYSCTLBYNAME) -static isc_result_t -getudpportrange_sysctl(int af, in_port_t *low, in_port_t *high) { - int port_low, port_high; - size_t portlen; - const char *sysctlname_lowport, *sysctlname_hiport; - - if (af == AF_INET) { - sysctlname_lowport = SYSCTL_V4PORTRANGE_LOW; - sysctlname_hiport = SYSCTL_V4PORTRANGE_HIGH; - } else { - sysctlname_lowport = SYSCTL_V6PORTRANGE_LOW; - sysctlname_hiport = SYSCTL_V6PORTRANGE_HIGH; - } - portlen = sizeof(portlen); - if (sysctlbyname(sysctlname_lowport, &port_low, &portlen, - NULL, 0) < 0) { - return (ISC_R_FAILURE); - } - portlen = sizeof(portlen); - if (sysctlbyname(sysctlname_hiport, &port_high, &portlen, - NULL, 0) < 0) { - return (ISC_R_FAILURE); - } - if ((port_low & ~0xffff) != 0 || (port_high & ~0xffff) != 0) - return (ISC_R_RANGE); - - *low = (in_port_t)port_low; - *high = (in_port_t)port_high; - - return (ISC_R_SUCCESS); -} -#else /* !HAVE_SYSCTLBYNAME */ -static isc_result_t -getudpportrange_sysctl(int af, in_port_t *low, in_port_t *high) { - int mib_lo4[4] = SYSCTL_V4PORTRANGE_LOW; - int mib_hi4[4] = SYSCTL_V4PORTRANGE_HIGH; - int mib_lo6[4] = SYSCTL_V6PORTRANGE_LOW; - int mib_hi6[4] = SYSCTL_V6PORTRANGE_HIGH; - int *mib_lo, *mib_hi, miblen; - int port_low, port_high; - size_t portlen; - - if (af == AF_INET) { - mib_lo = mib_lo4; - mib_hi = mib_hi4; - miblen = sizeof(mib_lo4) / sizeof(mib_lo4[0]); - } else { - mib_lo = mib_lo6; - mib_hi = mib_hi6; - miblen = sizeof(mib_lo6) / sizeof(mib_lo6[0]); - } - - portlen = sizeof(portlen); - if (sysctl(mib_lo, miblen, &port_low, &portlen, NULL, 0) < 0) { - return (ISC_R_FAILURE); - } - - portlen = sizeof(portlen); - if (sysctl(mib_hi, miblen, &port_high, &portlen, NULL, 0) < 0) { - return (ISC_R_FAILURE); - } - - if ((port_low & ~0xffff) != 0 || (port_high & ~0xffff) != 0) - return (ISC_R_RANGE); - - *low = (in_port_t) port_low; - *high = (in_port_t) port_high; - - return (ISC_R_SUCCESS); -} -#endif /* HAVE_SYSCTLBYNAME */ -#endif /* USE_SYSCTL_PORTRANGE */ - -isc_result_t -isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) { - int result = ISC_R_FAILURE; - - REQUIRE(low != NULL && high != NULL); - -#if defined(USE_SYSCTL_PORTRANGE) - result = getudpportrange_sysctl(af, low, high); -#else - UNUSED(af); -#endif - - if (result != ISC_R_SUCCESS) { - *low = ISC_NET_PORTRANGELOW; - *high = ISC_NET_PORTRANGEHIGH; - } - - return (ISC_R_SUCCESS); /* we currently never fail in this function */ -} - -void -isc_net_disableipv4(void) { - initialize(); - if (ipv4_result == ISC_R_SUCCESS) - ipv4_result = ISC_R_DISABLED; -} - -void -isc_net_disableipv6(void) { - initialize(); - if (ipv6_result == ISC_R_SUCCESS) - ipv6_result = ISC_R_DISABLED; -} - -void -isc_net_enableipv4(void) { - initialize(); - if (ipv4_result == ISC_R_DISABLED) - ipv4_result = ISC_R_SUCCESS; -} - -void -isc_net_enableipv6(void) { - initialize(); - if (ipv6_result == ISC_R_DISABLED) - ipv6_result = ISC_R_SUCCESS; -} diff --git a/contrib/bind9/lib/isc/unix/os.c b/contrib/bind9/lib/isc/unix/os.c deleted file mode 100644 index c050d14..0000000 --- a/contrib/bind9/lib/isc/unix/os.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2000, 2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: os.c,v 1.18 2007/06/19 23:47:18 tbox Exp $ */ - -#include <config.h> - -#include <isc/os.h> - - -#ifdef HAVE_SYSCONF - -#include <unistd.h> - -#ifndef __hpux -static inline long -sysconf_ncpus(void) { -#if defined(_SC_NPROCESSORS_ONLN) - return sysconf((_SC_NPROCESSORS_ONLN)); -#elif defined(_SC_NPROC_ONLN) - return sysconf((_SC_NPROC_ONLN)); -#else - return (0); -#endif -} -#endif -#endif /* HAVE_SYSCONF */ - - -#ifdef __hpux - -#include <sys/pstat.h> - -static inline int -hpux_ncpus(void) { - struct pst_dynamic psd; - if (pstat_getdynamic(&psd, sizeof(psd), 1, 0) != -1) - return (psd.psd_proc_cnt); - else - return (0); -} - -#endif /* __hpux */ - -#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME) -#include <sys/types.h> /* for FreeBSD */ -#include <sys/param.h> /* for NetBSD */ -#include <sys/sysctl.h> - -static int -sysctl_ncpus(void) { - int ncpu, result; - size_t len; - - len = sizeof(ncpu); - result = sysctlbyname("hw.ncpu", &ncpu, &len , 0, 0); - if (result != -1) - return (ncpu); - return (0); -} -#endif - -unsigned int -isc_os_ncpus(void) { - long ncpus = 0; - -#ifdef __hpux - ncpus = hpux_ncpus(); -#elif defined(HAVE_SYSCONF) - ncpus = sysconf_ncpus(); -#endif -#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME) - if (ncpus <= 0) - ncpus = sysctl_ncpus(); -#endif - if (ncpus <= 0) - ncpus = 1; - - return ((unsigned int)ncpus); -} diff --git a/contrib/bind9/lib/isc/unix/resource.c b/contrib/bind9/lib/isc/unix/resource.c deleted file mode 100644 index 29596e2..0000000 --- a/contrib/bind9/lib/isc/unix/resource.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (C) 2004, 2007-2009 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2000, 2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: resource.c,v 1.23 2009/02/13 23:48:14 tbox Exp $ */ - -#include <config.h> - -#include <sys/types.h> -#include <sys/time.h> /* Required on some systems for <sys/resource.h>. */ -#include <sys/resource.h> - -#include <isc/platform.h> -#include <isc/resource.h> -#include <isc/result.h> -#include <isc/util.h> - -#ifdef __linux__ -#include <linux/fs.h> /* To get the large NR_OPEN. */ -#endif - -#if defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H) -#include <sys/dyntune.h> -#endif - -#include "errno2result.h" - -static isc_result_t -resource2rlim(isc_resource_t resource, int *rlim_resource) { - isc_result_t result = ISC_R_SUCCESS; - - switch (resource) { - case isc_resource_coresize: - *rlim_resource = RLIMIT_CORE; - break; - case isc_resource_cputime: - *rlim_resource = RLIMIT_CPU; - break; - case isc_resource_datasize: - *rlim_resource = RLIMIT_DATA; - break; - case isc_resource_filesize: - *rlim_resource = RLIMIT_FSIZE; - break; - case isc_resource_lockedmemory: -#ifdef RLIMIT_MEMLOCK - *rlim_resource = RLIMIT_MEMLOCK; -#else - result = ISC_R_NOTIMPLEMENTED; -#endif - break; - case isc_resource_openfiles: -#ifdef RLIMIT_NOFILE - *rlim_resource = RLIMIT_NOFILE; -#else - result = ISC_R_NOTIMPLEMENTED; -#endif - break; - case isc_resource_processes: -#ifdef RLIMIT_NPROC - *rlim_resource = RLIMIT_NPROC; -#else - result = ISC_R_NOTIMPLEMENTED; -#endif - break; - case isc_resource_residentsize: -#ifdef RLIMIT_RSS - *rlim_resource = RLIMIT_RSS; -#else - result = ISC_R_NOTIMPLEMENTED; -#endif - break; - case isc_resource_stacksize: - *rlim_resource = RLIMIT_STACK; - break; - default: - /* - * This test is not very robust if isc_resource_t - * changes, but generates a clear assertion message. - */ - REQUIRE(resource >= isc_resource_coresize && - resource <= isc_resource_stacksize); - - result = ISC_R_RANGE; - break; - } - - return (result); -} - -isc_result_t -isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) { - struct rlimit rl; - ISC_PLATFORM_RLIMITTYPE rlim_value; - int unixresult; - int unixresource; - isc_result_t result; - - result = resource2rlim(resource, &unixresource); - if (result != ISC_R_SUCCESS) - return (result); - - if (value == ISC_RESOURCE_UNLIMITED) - rlim_value = RLIM_INFINITY; - - else { - /* - * isc_resourcevalue_t was chosen as an unsigned 64 bit - * integer so that it could contain the maximum range of - * reasonable values. Unfortunately, this exceeds the typical - * range on Unix systems. Ensure the range of - * ISC_PLATFORM_RLIMITTYPE is not overflowed. - */ - isc_resourcevalue_t rlim_max; - isc_boolean_t rlim_t_is_signed = - ISC_TF(((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0); - - if (rlim_t_is_signed) - rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 << - (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1)); - else - rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1; - - if (value > rlim_max) - value = rlim_max; - - rlim_value = value; - } - - rl.rlim_cur = rl.rlim_max = rlim_value; - unixresult = setrlimit(unixresource, &rl); - - if (unixresult == 0) - return (ISC_R_SUCCESS); - -#if defined(OPEN_MAX) && defined(__APPLE__) - /* - * The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the - * maximum possible value is OPEN_MAX. BIND8 used to use - * sysconf(_SC_OPEN_MAX) for such a case, but this value is much - * smaller than OPEN_MAX and is not really effective. - */ - if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { - rl.rlim_cur = OPEN_MAX; - unixresult = setrlimit(unixresource, &rl); - if (unixresult == 0) - return (ISC_R_SUCCESS); - } -#elif defined(__linux__) -#ifndef NR_OPEN -#define NR_OPEN (1024*1024) -#endif - - /* - * Some Linux kernels don't accept RLIM_INFINIT; the maximum - * possible value is the NR_OPEN defined in linux/fs.h. - */ - if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { - rl.rlim_cur = rl.rlim_max = NR_OPEN; - unixresult = setrlimit(unixresource, &rl); - if (unixresult == 0) - return (ISC_R_SUCCESS); - } -#elif defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H) - if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { - uint64_t maxfiles; - if (gettune("maxfiles_lim", &maxfiles) == 0) { - rl.rlim_cur = rl.rlim_max = maxfiles; - unixresult = setrlimit(unixresource, &rl); - if (unixresult == 0) - return (ISC_R_SUCCESS); - } - } -#endif - if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { - if (getrlimit(unixresource, &rl) == 0) { - rl.rlim_cur = rl.rlim_max; - unixresult = setrlimit(unixresource, &rl); - if (unixresult == 0) - return (ISC_R_SUCCESS); - } - } - return (isc__errno2result(errno)); -} - -isc_result_t -isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) { - int unixresult; - int unixresource; - struct rlimit rl; - isc_result_t result; - - result = resource2rlim(resource, &unixresource); - if (result == ISC_R_SUCCESS) { - unixresult = getrlimit(unixresource, &rl); - INSIST(unixresult == 0); - *value = rl.rlim_max; - } - - return (result); -} - -isc_result_t -isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) { - int unixresult; - int unixresource; - struct rlimit rl; - isc_result_t result; - - result = resource2rlim(resource, &unixresource); - if (result == ISC_R_SUCCESS) { - unixresult = getrlimit(unixresource, &rl); - INSIST(unixresult == 0); - *value = rl.rlim_cur; - } - - return (result); -} diff --git a/contrib/bind9/lib/isc/unix/socket.c b/contrib/bind9/lib/isc/unix/socket.c deleted file mode 100644 index 7bd12aa..0000000 --- a/contrib/bind9/lib/isc/unix/socket.c +++ /dev/null @@ -1,6043 +0,0 @@ -/* - * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1998-2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id$ */ - -/*! \file */ - -#include <config.h> - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/uio.h> - -#include <errno.h> -#include <fcntl.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <isc/buffer.h> -#include <isc/bufferlist.h> -#include <isc/condition.h> -#include <isc/formatcheck.h> -#include <isc/list.h> -#include <isc/log.h> -#include <isc/mem.h> -#include <isc/msgs.h> -#include <isc/mutex.h> -#include <isc/net.h> -#include <isc/once.h> -#include <isc/platform.h> -#include <isc/print.h> -#include <isc/region.h> -#include <isc/socket.h> -#include <isc/stats.h> -#include <isc/strerror.h> -#include <isc/task.h> -#include <isc/thread.h> -#include <isc/util.h> -#include <isc/xml.h> - -#ifdef ISC_PLATFORM_HAVESYSUNH -#include <sys/un.h> -#endif -#ifdef ISC_PLATFORM_HAVEKQUEUE -#include <sys/event.h> -#endif -#ifdef ISC_PLATFORM_HAVEEPOLL -#include <sys/epoll.h> -#endif -#ifdef ISC_PLATFORM_HAVEDEVPOLL -#if defined(HAVE_SYS_DEVPOLL_H) -#include <sys/devpoll.h> -#elif defined(HAVE_DEVPOLL_H) -#include <devpoll.h> -#endif -#endif - -#include "errno2result.h" - -/* See task.c about the following definition: */ -#ifdef BIND9 -#ifdef ISC_PLATFORM_USETHREADS -#define USE_WATCHER_THREAD -#else -#define USE_SHARED_MANAGER -#endif /* ISC_PLATFORM_USETHREADS */ -#endif /* BIND9 */ - -#ifndef USE_WATCHER_THREAD -#include "socket_p.h" -#include "../task_p.h" -#endif /* USE_WATCHER_THREAD */ - -#if defined(SO_BSDCOMPAT) && defined(__linux__) -#include <sys/utsname.h> -#endif - -/*% - * Choose the most preferable multiplex method. - */ -#ifdef ISC_PLATFORM_HAVEKQUEUE -#define USE_KQUEUE -#elif defined (ISC_PLATFORM_HAVEEPOLL) -#define USE_EPOLL -#elif defined (ISC_PLATFORM_HAVEDEVPOLL) -#define USE_DEVPOLL -typedef struct { - unsigned int want_read : 1, - want_write : 1; -} pollinfo_t; -#else -#define USE_SELECT -#endif /* ISC_PLATFORM_HAVEKQUEUE */ - -#ifndef USE_WATCHER_THREAD -#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) -struct isc_socketwait { - int nevents; -}; -#elif defined (USE_SELECT) -struct isc_socketwait { - fd_set *readset; - fd_set *writeset; - int nfds; - int maxfd; -}; -#endif /* USE_KQUEUE */ -#endif /* !USE_WATCHER_THREAD */ - -/*% - * Maximum number of allowable open sockets. This is also the maximum - * allowable socket file descriptor. - * - * Care should be taken before modifying this value for select(): - * The API standard doesn't ensure select() accept more than (the system default - * of) FD_SETSIZE descriptors, and the default size should in fact be fine in - * the vast majority of cases. This constant should therefore be increased only - * when absolutely necessary and possible, i.e., the server is exhausting all - * available file descriptors (up to FD_SETSIZE) and the select() function - * and FD_xxx macros support larger values than FD_SETSIZE (which may not - * always by true, but we keep using some of them to ensure as much - * portability as possible). Note also that overall server performance - * may be rather worsened with a larger value of this constant due to - * inherent scalability problems of select(). - * - * As a special note, this value shouldn't have to be touched if - * this is a build for an authoritative only DNS server. - */ -#ifndef ISC_SOCKET_MAXSOCKETS -#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) -#define ISC_SOCKET_MAXSOCKETS 4096 -#elif defined(USE_SELECT) -#define ISC_SOCKET_MAXSOCKETS FD_SETSIZE -#endif /* USE_KQUEUE... */ -#endif /* ISC_SOCKET_MAXSOCKETS */ - -#ifdef USE_SELECT -/*% - * Mac OS X needs a special definition to support larger values in select(). - * We always define this because a larger value can be specified run-time. - */ -#ifdef __APPLE__ -#define _DARWIN_UNLIMITED_SELECT -#endif /* __APPLE__ */ -#endif /* USE_SELECT */ - -#ifdef ISC_SOCKET_USE_POLLWATCH -/*% - * If this macro is defined, enable workaround for a Solaris /dev/poll kernel - * bug: DP_POLL ioctl could keep sleeping even if socket I/O is possible for - * some of the specified FD. The idea is based on the observation that it's - * likely for a busy server to keep receiving packets. It specifically works - * as follows: the socket watcher is first initialized with the state of - * "poll_idle". While it's in the idle state it keeps sleeping until a socket - * event occurs. When it wakes up for a socket I/O event, it moves to the - * poll_active state, and sets the poll timeout to a short period - * (ISC_SOCKET_POLLWATCH_TIMEOUT msec). If timeout occurs in this state, the - * watcher goes to the poll_checking state with the same timeout period. - * In this state, the watcher tries to detect whether this is a break - * during intermittent events or the kernel bug is triggered. If the next - * polling reports an event within the short period, the previous timeout is - * likely to be a kernel bug, and so the watcher goes back to the active state. - * Otherwise, it moves to the idle state again. - * - * It's not clear whether this is a thread-related bug, but since we've only - * seen this with threads, this workaround is used only when enabling threads. - */ - -typedef enum { poll_idle, poll_active, poll_checking } pollstate_t; - -#ifndef ISC_SOCKET_POLLWATCH_TIMEOUT -#define ISC_SOCKET_POLLWATCH_TIMEOUT 10 -#endif /* ISC_SOCKET_POLLWATCH_TIMEOUT */ -#endif /* ISC_SOCKET_USE_POLLWATCH */ - -/*% - * Size of per-FD lock buckets. - */ -#ifdef ISC_PLATFORM_USETHREADS -#define FDLOCK_COUNT 1024 -#define FDLOCK_ID(fd) ((fd) % FDLOCK_COUNT) -#else -#define FDLOCK_COUNT 1 -#define FDLOCK_ID(fd) 0 -#endif /* ISC_PLATFORM_USETHREADS */ - -/*% - * Maximum number of events communicated with the kernel. There should normally - * be no need for having a large number. - */ -#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) -#ifndef ISC_SOCKET_MAXEVENTS -#define ISC_SOCKET_MAXEVENTS 64 -#endif -#endif - -/*% - * Some systems define the socket length argument as an int, some as size_t, - * some as socklen_t. This is here so it can be easily changed if needed. - */ -#ifndef ISC_SOCKADDR_LEN_T -#define ISC_SOCKADDR_LEN_T unsigned int -#endif - -/*% - * Define what the possible "soft" errors can be. These are non-fatal returns - * of various network related functions, like recv() and so on. - * - * For some reason, BSDI (and perhaps others) will sometimes return <0 - * from recv() but will have errno==0. This is broken, but we have to - * work around it here. - */ -#define SOFT_ERROR(e) ((e) == EAGAIN || \ - (e) == EWOULDBLOCK || \ - (e) == EINTR || \ - (e) == 0) - -#define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x) - -/*!< - * DLVL(90) -- Function entry/exit and other tracing. - * DLVL(70) -- Socket "correctness" -- including returning of events, etc. - * DLVL(60) -- Socket data send/receive - * DLVL(50) -- Event tracing, including receiving/sending completion events. - * DLVL(20) -- Socket creation/destruction. - */ -#define TRACE_LEVEL 90 -#define CORRECTNESS_LEVEL 70 -#define IOEVENT_LEVEL 60 -#define EVENT_LEVEL 50 -#define CREATION_LEVEL 20 - -#define TRACE DLVL(TRACE_LEVEL) -#define CORRECTNESS DLVL(CORRECTNESS_LEVEL) -#define IOEVENT DLVL(IOEVENT_LEVEL) -#define EVENT DLVL(EVENT_LEVEL) -#define CREATION DLVL(CREATION_LEVEL) - -typedef isc_event_t intev_t; - -#define SOCKET_MAGIC ISC_MAGIC('I', 'O', 'i', 'o') -#define VALID_SOCKET(s) ISC_MAGIC_VALID(s, SOCKET_MAGIC) - -/*! - * IPv6 control information. If the socket is an IPv6 socket we want - * to collect the destination address and interface so the client can - * set them on outgoing packets. - */ -#ifdef ISC_PLATFORM_HAVEIN6PKTINFO -#ifndef USE_CMSG -#define USE_CMSG 1 -#endif -#endif - -/*% - * NetBSD and FreeBSD can timestamp packets. XXXMLG Should we have - * a setsockopt() like interface to request timestamps, and if the OS - * doesn't do it for us, call gettimeofday() on every UDP receive? - */ -#ifdef SO_TIMESTAMP -#ifndef USE_CMSG -#define USE_CMSG 1 -#endif -#endif - -/*% - * The size to raise the receive buffer to (from BIND 8). - */ -#define RCVBUFSIZE (32*1024) - -/*% - * The number of times a send operation is repeated if the result is EINTR. - */ -#define NRETRIES 10 - -typedef struct isc__socket isc__socket_t; -typedef struct isc__socketmgr isc__socketmgr_t; - -#define NEWCONNSOCK(ev) ((isc__socket_t *)(ev)->newsocket) - -struct isc__socket { - /* Not locked. */ - isc_socket_t common; - isc__socketmgr_t *manager; - isc_mutex_t lock; - isc_sockettype_t type; - const isc_statscounter_t *statsindex; - - /* Locked by socket lock. */ - ISC_LINK(isc__socket_t) link; - unsigned int references; - int fd; - int pf; - char name[16]; - void * tag; - - ISC_LIST(isc_socketevent_t) send_list; - ISC_LIST(isc_socketevent_t) recv_list; - ISC_LIST(isc_socket_newconnev_t) accept_list; - isc_socket_connev_t *connect_ev; - - /* - * Internal events. Posted when a descriptor is readable or - * writable. These are statically allocated and never freed. - * They will be set to non-purgable before use. - */ - intev_t readable_ev; - intev_t writable_ev; - - isc_sockaddr_t peer_address; /* remote address */ - - unsigned int pending_recv : 1, - pending_send : 1, - pending_accept : 1, - listener : 1, /* listener socket */ - connected : 1, - connecting : 1, /* connect pending */ - bound : 1, /* bound to local addr */ - dupped : 1; - -#ifdef ISC_NET_RECVOVERFLOW - unsigned char overflow; /* used for MSG_TRUNC fake */ -#endif - - char *recvcmsgbuf; - ISC_SOCKADDR_LEN_T recvcmsgbuflen; - char *sendcmsgbuf; - ISC_SOCKADDR_LEN_T sendcmsgbuflen; - - void *fdwatcharg; - isc_sockfdwatch_t fdwatchcb; - int fdwatchflags; - isc_task_t *fdwatchtask; -}; - -#define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g') -#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC) - -struct isc__socketmgr { - /* Not locked. */ - isc_socketmgr_t common; - isc_mem_t *mctx; - isc_mutex_t lock; - isc_mutex_t *fdlock; - isc_stats_t *stats; -#ifdef USE_KQUEUE - int kqueue_fd; - int nevents; - struct kevent *events; -#endif /* USE_KQUEUE */ -#ifdef USE_EPOLL - int epoll_fd; - int nevents; - struct epoll_event *events; -#endif /* USE_EPOLL */ -#ifdef USE_DEVPOLL - int devpoll_fd; - int nevents; - struct pollfd *events; -#endif /* USE_DEVPOLL */ -#ifdef USE_SELECT - int fd_bufsize; -#endif /* USE_SELECT */ - unsigned int maxsocks; -#ifdef ISC_PLATFORM_USETHREADS - int pipe_fds[2]; -#endif - - /* Locked by fdlock. */ - isc__socket_t **fds; - int *fdstate; -#ifdef USE_DEVPOLL - pollinfo_t *fdpollinfo; -#endif - - /* Locked by manager lock. */ - ISC_LIST(isc__socket_t) socklist; -#ifdef USE_SELECT - fd_set *read_fds; - fd_set *read_fds_copy; - fd_set *write_fds; - fd_set *write_fds_copy; - int maxfd; -#endif /* USE_SELECT */ - int reserved; /* unlocked */ -#ifdef USE_WATCHER_THREAD - isc_thread_t watcher; - isc_condition_t shutdown_ok; -#else /* USE_WATCHER_THREAD */ - unsigned int refs; -#endif /* USE_WATCHER_THREAD */ - int maxudp; -}; - -#ifdef USE_SHARED_MANAGER -static isc__socketmgr_t *socketmgr = NULL; -#endif /* USE_SHARED_MANAGER */ - -#define CLOSED 0 /* this one must be zero */ -#define MANAGED 1 -#define CLOSE_PENDING 2 - -/* - * send() and recv() iovec counts - */ -#define MAXSCATTERGATHER_SEND (ISC_SOCKET_MAXSCATTERGATHER) -#ifdef ISC_NET_RECVOVERFLOW -# define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER + 1) -#else -# define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER) -#endif - -static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf, - isc_sockettype_t type, - isc_socket_t **socketp, - isc_socket_t *dup_socket); -static void send_recvdone_event(isc__socket_t *, isc_socketevent_t **); -static void send_senddone_event(isc__socket_t *, isc_socketevent_t **); -static void free_socket(isc__socket_t **); -static isc_result_t allocate_socket(isc__socketmgr_t *, isc_sockettype_t, - isc__socket_t **); -static void destroy(isc__socket_t **); -static void internal_accept(isc_task_t *, isc_event_t *); -static void internal_connect(isc_task_t *, isc_event_t *); -static void internal_recv(isc_task_t *, isc_event_t *); -static void internal_send(isc_task_t *, isc_event_t *); -static void internal_fdwatch_write(isc_task_t *, isc_event_t *); -static void internal_fdwatch_read(isc_task_t *, isc_event_t *); -static void process_cmsg(isc__socket_t *, struct msghdr *, isc_socketevent_t *); -static void build_msghdr_send(isc__socket_t *, isc_socketevent_t *, - struct msghdr *, struct iovec *, size_t *); -static void build_msghdr_recv(isc__socket_t *, isc_socketevent_t *, - struct msghdr *, struct iovec *, size_t *); -#ifdef USE_WATCHER_THREAD -static isc_boolean_t process_ctlfd(isc__socketmgr_t *manager); -#endif - -/*% - * The following can be either static or public, depending on build environment. - */ - -#ifdef BIND9 -#define ISC_SOCKETFUNC_SCOPE -#else -#define ISC_SOCKETFUNC_SCOPE static -#endif - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, - isc_socket_t **socketp); -ISC_SOCKETFUNC_SCOPE void -isc__socket_attach(isc_socket_t *sock, isc_socket_t **socketp); -ISC_SOCKETFUNC_SCOPE void -isc__socket_detach(isc_socket_t **socketp); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, - unsigned int maxsocks); -ISC_SOCKETFUNC_SCOPE void -isc__socketmgr_destroy(isc_socketmgr_t **managerp); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist, - unsigned int minimum, isc_task_t *task, - isc_taskaction_t action, const void *arg); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_recv(isc_socket_t *sock, isc_region_t *region, - unsigned int minimum, isc_task_t *task, - isc_taskaction_t action, const void *arg); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_recv2(isc_socket_t *sock, isc_region_t *region, - unsigned int minimum, isc_task_t *task, - isc_socketevent_t *event, unsigned int flags); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_send(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, isc_taskaction_t action, const void *arg); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_sendto(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist, - isc_task_t *task, isc_taskaction_t action, const void *arg); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_sendto2(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, - isc_socketevent_t *event, unsigned int flags); -ISC_SOCKETFUNC_SCOPE void -isc__socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm, - isc_uint32_t owner, isc_uint32_t group); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr, - unsigned int options); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_filter(isc_socket_t *sock, const char *filter); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_listen(isc_socket_t *sock, unsigned int backlog); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_accept(isc_socket_t *sock, - isc_task_t *task, isc_taskaction_t action, const void *arg); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, - isc_task_t *task, isc_taskaction_t action, - const void *arg); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp); -ISC_SOCKETFUNC_SCOPE void -isc__socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how); -ISC_SOCKETFUNC_SCOPE isc_sockettype_t -isc__socket_gettype(isc_socket_t *sock); -ISC_SOCKETFUNC_SCOPE isc_boolean_t -isc__socket_isbound(isc_socket_t *sock); -ISC_SOCKETFUNC_SCOPE void -isc__socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes); -#if defined(HAVE_LIBXML2) && defined(BIND9) -ISC_SOCKETFUNC_SCOPE void -isc__socketmgr_renderxml(isc_socketmgr_t *mgr0, xmlTextWriterPtr writer); -#endif - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags, - isc_sockfdwatch_t callback, void *cbarg, - isc_task_t *task, isc_socket_t **socketp); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_fdwatchpoke(isc_socket_t *sock, int flags); -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_dup(isc_socket_t *sock, isc_socket_t **socketp); -ISC_SOCKETFUNC_SCOPE int -isc__socket_getfd(isc_socket_t *sock); - -static struct { - isc_socketmethods_t methods; - - /*% - * The following are defined just for avoiding unused static functions. - */ -#ifndef BIND9 - void *recvv, *send, *sendv, *sendto2, *cleanunix, *permunix, *filter, - *listen, *accept, *getpeername, *isbound; -#endif -} socketmethods = { - { - isc__socket_attach, - isc__socket_detach, - isc__socket_bind, - isc__socket_sendto, - isc__socket_sendto2, - isc__socket_connect, - isc__socket_recv, - isc__socket_recv2, - isc__socket_cancel, - isc__socket_getsockname, - isc__socket_gettype, - isc__socket_ipv6only, - isc__socket_fdwatchpoke, - isc__socket_dup, - isc__socket_getfd - } -#ifndef BIND9 - , - (void *)isc__socket_recvv, (void *)isc__socket_send, - (void *)isc__socket_sendv, (void *)isc__socket_sendto2, - (void *)isc__socket_cleanunix, (void *)isc__socket_permunix, - (void *)isc__socket_filter, (void *)isc__socket_listen, - (void *)isc__socket_accept, (void *)isc__socket_getpeername, - (void *)isc__socket_isbound -#endif -}; - -static isc_socketmgrmethods_t socketmgrmethods = { - isc__socketmgr_destroy, - isc__socket_create, - isc__socket_fdwatchcreate -}; - -#define SELECT_POKE_SHUTDOWN (-1) -#define SELECT_POKE_NOTHING (-2) -#define SELECT_POKE_READ (-3) -#define SELECT_POKE_ACCEPT (-3) /*%< Same as _READ */ -#define SELECT_POKE_WRITE (-4) -#define SELECT_POKE_CONNECT (-4) /*%< Same as _WRITE */ -#define SELECT_POKE_CLOSE (-5) - -#define SOCK_DEAD(s) ((s)->references == 0) - -/*% - * Shortcut index arrays to get access to statistics counters. - */ -enum { - STATID_OPEN = 0, - STATID_OPENFAIL = 1, - STATID_CLOSE = 2, - STATID_BINDFAIL = 3, - STATID_CONNECTFAIL = 4, - STATID_CONNECT = 5, - STATID_ACCEPTFAIL = 6, - STATID_ACCEPT = 7, - STATID_SENDFAIL = 8, - STATID_RECVFAIL = 9 -}; -static const isc_statscounter_t udp4statsindex[] = { - isc_sockstatscounter_udp4open, - isc_sockstatscounter_udp4openfail, - isc_sockstatscounter_udp4close, - isc_sockstatscounter_udp4bindfail, - isc_sockstatscounter_udp4connectfail, - isc_sockstatscounter_udp4connect, - -1, - -1, - isc_sockstatscounter_udp4sendfail, - isc_sockstatscounter_udp4recvfail -}; -static const isc_statscounter_t udp6statsindex[] = { - isc_sockstatscounter_udp6open, - isc_sockstatscounter_udp6openfail, - isc_sockstatscounter_udp6close, - isc_sockstatscounter_udp6bindfail, - isc_sockstatscounter_udp6connectfail, - isc_sockstatscounter_udp6connect, - -1, - -1, - isc_sockstatscounter_udp6sendfail, - isc_sockstatscounter_udp6recvfail -}; -static const isc_statscounter_t tcp4statsindex[] = { - isc_sockstatscounter_tcp4open, - isc_sockstatscounter_tcp4openfail, - isc_sockstatscounter_tcp4close, - isc_sockstatscounter_tcp4bindfail, - isc_sockstatscounter_tcp4connectfail, - isc_sockstatscounter_tcp4connect, - isc_sockstatscounter_tcp4acceptfail, - isc_sockstatscounter_tcp4accept, - isc_sockstatscounter_tcp4sendfail, - isc_sockstatscounter_tcp4recvfail -}; -static const isc_statscounter_t tcp6statsindex[] = { - isc_sockstatscounter_tcp6open, - isc_sockstatscounter_tcp6openfail, - isc_sockstatscounter_tcp6close, - isc_sockstatscounter_tcp6bindfail, - isc_sockstatscounter_tcp6connectfail, - isc_sockstatscounter_tcp6connect, - isc_sockstatscounter_tcp6acceptfail, - isc_sockstatscounter_tcp6accept, - isc_sockstatscounter_tcp6sendfail, - isc_sockstatscounter_tcp6recvfail -}; -static const isc_statscounter_t unixstatsindex[] = { - isc_sockstatscounter_unixopen, - isc_sockstatscounter_unixopenfail, - isc_sockstatscounter_unixclose, - isc_sockstatscounter_unixbindfail, - isc_sockstatscounter_unixconnectfail, - isc_sockstatscounter_unixconnect, - isc_sockstatscounter_unixacceptfail, - isc_sockstatscounter_unixaccept, - isc_sockstatscounter_unixsendfail, - isc_sockstatscounter_unixrecvfail -}; -static const isc_statscounter_t fdwatchstatsindex[] = { - -1, - -1, - isc_sockstatscounter_fdwatchclose, - isc_sockstatscounter_fdwatchbindfail, - isc_sockstatscounter_fdwatchconnectfail, - isc_sockstatscounter_fdwatchconnect, - -1, - -1, - isc_sockstatscounter_fdwatchsendfail, - isc_sockstatscounter_fdwatchrecvfail -}; - -#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) || \ - defined(USE_WATCHER_THREAD) -static void -manager_log(isc__socketmgr_t *sockmgr, - isc_logcategory_t *category, isc_logmodule_t *module, int level, - const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6); -static void -manager_log(isc__socketmgr_t *sockmgr, - isc_logcategory_t *category, isc_logmodule_t *module, int level, - const char *fmt, ...) -{ - char msgbuf[2048]; - va_list ap; - - if (! isc_log_wouldlog(isc_lctx, level)) - return; - - va_start(ap, fmt); - vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); - va_end(ap); - - isc_log_write(isc_lctx, category, module, level, - "sockmgr %p: %s", sockmgr, msgbuf); -} -#endif - -static void -socket_log(isc__socket_t *sock, isc_sockaddr_t *address, - isc_logcategory_t *category, isc_logmodule_t *module, int level, - isc_msgcat_t *msgcat, int msgset, int message, - const char *fmt, ...) ISC_FORMAT_PRINTF(9, 10); -static void -socket_log(isc__socket_t *sock, isc_sockaddr_t *address, - isc_logcategory_t *category, isc_logmodule_t *module, int level, - isc_msgcat_t *msgcat, int msgset, int message, - const char *fmt, ...) -{ - char msgbuf[2048]; - char peerbuf[ISC_SOCKADDR_FORMATSIZE]; - va_list ap; - - if (! isc_log_wouldlog(isc_lctx, level)) - return; - - va_start(ap, fmt); - vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); - va_end(ap); - - if (address == NULL) { - isc_log_iwrite(isc_lctx, category, module, level, - msgcat, msgset, message, - "socket %p: %s", sock, msgbuf); - } else { - isc_sockaddr_format(address, peerbuf, sizeof(peerbuf)); - isc_log_iwrite(isc_lctx, category, module, level, - msgcat, msgset, message, - "socket %p %s: %s", sock, peerbuf, msgbuf); - } -} - -#if defined(_AIX) && defined(ISC_NET_BSD44MSGHDR) && \ - defined(USE_CMSG) && defined(IPV6_RECVPKTINFO) -/* - * AIX has a kernel bug where IPV6_RECVPKTINFO gets cleared by - * setting IPV6_V6ONLY. - */ -static void -FIX_IPV6_RECVPKTINFO(isc__socket_t *sock) -{ - char strbuf[ISC_STRERRORSIZE]; - int on = 1; - - if (sock->pf != AF_INET6 || sock->type != isc_sockettype_udp) - return; - - if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, - (void *)&on, sizeof(on)) < 0) { - - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "setsockopt(%d, IPV6_RECVPKTINFO) " - "%s: %s", sock->fd, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - } -} -#else -#define FIX_IPV6_RECVPKTINFO(sock) (void)0 -#endif - -/*% - * Increment socket-related statistics counters. - */ -static inline void -inc_stats(isc_stats_t *stats, isc_statscounter_t counterid) { - REQUIRE(counterid != -1); - - if (stats != NULL) - isc_stats_increment(stats, counterid); -} - -static inline isc_result_t -watch_fd(isc__socketmgr_t *manager, int fd, int msg) { - isc_result_t result = ISC_R_SUCCESS; - -#ifdef USE_KQUEUE - struct kevent evchange; - - memset(&evchange, 0, sizeof(evchange)); - if (msg == SELECT_POKE_READ) - evchange.filter = EVFILT_READ; - else - evchange.filter = EVFILT_WRITE; - evchange.flags = EV_ADD; - evchange.ident = fd; - if (kevent(manager->kqueue_fd, &evchange, 1, NULL, 0, NULL) != 0) - result = isc__errno2result(errno); - - return (result); -#elif defined(USE_EPOLL) - struct epoll_event event; - - if (msg == SELECT_POKE_READ) - event.events = EPOLLIN; - else - event.events = EPOLLOUT; - memset(&event.data, 0, sizeof(event.data)); - event.data.fd = fd; - if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_ADD, fd, &event) == -1 && - errno != EEXIST) { - result = isc__errno2result(errno); - } - - return (result); -#elif defined(USE_DEVPOLL) - struct pollfd pfd; - int lockid = FDLOCK_ID(fd); - - memset(&pfd, 0, sizeof(pfd)); - if (msg == SELECT_POKE_READ) - pfd.events = POLLIN; - else - pfd.events = POLLOUT; - pfd.fd = fd; - pfd.revents = 0; - LOCK(&manager->fdlock[lockid]); - if (write(manager->devpoll_fd, &pfd, sizeof(pfd)) == -1) - result = isc__errno2result(errno); - else { - if (msg == SELECT_POKE_READ) - manager->fdpollinfo[fd].want_read = 1; - else - manager->fdpollinfo[fd].want_write = 1; - } - UNLOCK(&manager->fdlock[lockid]); - - return (result); -#elif defined(USE_SELECT) - LOCK(&manager->lock); - if (msg == SELECT_POKE_READ) - FD_SET(fd, manager->read_fds); - if (msg == SELECT_POKE_WRITE) - FD_SET(fd, manager->write_fds); - UNLOCK(&manager->lock); - - return (result); -#endif -} - -static inline isc_result_t -unwatch_fd(isc__socketmgr_t *manager, int fd, int msg) { - isc_result_t result = ISC_R_SUCCESS; - -#ifdef USE_KQUEUE - struct kevent evchange; - - memset(&evchange, 0, sizeof(evchange)); - if (msg == SELECT_POKE_READ) - evchange.filter = EVFILT_READ; - else - evchange.filter = EVFILT_WRITE; - evchange.flags = EV_DELETE; - evchange.ident = fd; - if (kevent(manager->kqueue_fd, &evchange, 1, NULL, 0, NULL) != 0) - result = isc__errno2result(errno); - - return (result); -#elif defined(USE_EPOLL) - struct epoll_event event; - - if (msg == SELECT_POKE_READ) - event.events = EPOLLIN; - else - event.events = EPOLLOUT; - memset(&event.data, 0, sizeof(event.data)); - event.data.fd = fd; - if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_DEL, fd, &event) == -1 && - errno != ENOENT) { - char strbuf[ISC_STRERRORSIZE]; - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "epoll_ctl(DEL), %d: %s", fd, strbuf); - result = ISC_R_UNEXPECTED; - } - return (result); -#elif defined(USE_DEVPOLL) - struct pollfd pfds[2]; - size_t writelen = sizeof(pfds[0]); - int lockid = FDLOCK_ID(fd); - - memset(pfds, 0, sizeof(pfds)); - pfds[0].events = POLLREMOVE; - pfds[0].fd = fd; - - /* - * Canceling read or write polling via /dev/poll is tricky. Since it - * only provides a way of canceling per FD, we may need to re-poll the - * socket for the other operation. - */ - LOCK(&manager->fdlock[lockid]); - if (msg == SELECT_POKE_READ && - manager->fdpollinfo[fd].want_write == 1) { - pfds[1].events = POLLOUT; - pfds[1].fd = fd; - writelen += sizeof(pfds[1]); - } - if (msg == SELECT_POKE_WRITE && - manager->fdpollinfo[fd].want_read == 1) { - pfds[1].events = POLLIN; - pfds[1].fd = fd; - writelen += sizeof(pfds[1]); - } - - if (write(manager->devpoll_fd, pfds, writelen) == -1) - result = isc__errno2result(errno); - else { - if (msg == SELECT_POKE_READ) - manager->fdpollinfo[fd].want_read = 0; - else - manager->fdpollinfo[fd].want_write = 0; - } - UNLOCK(&manager->fdlock[lockid]); - - return (result); -#elif defined(USE_SELECT) - LOCK(&manager->lock); - if (msg == SELECT_POKE_READ) - FD_CLR(fd, manager->read_fds); - else if (msg == SELECT_POKE_WRITE) - FD_CLR(fd, manager->write_fds); - UNLOCK(&manager->lock); - - return (result); -#endif -} - -static void -wakeup_socket(isc__socketmgr_t *manager, int fd, int msg) { - isc_result_t result; - int lockid = FDLOCK_ID(fd); - - /* - * This is a wakeup on a socket. If the socket is not in the - * process of being closed, start watching it for either reads - * or writes. - */ - - INSIST(fd >= 0 && fd < (int)manager->maxsocks); - - if (msg == SELECT_POKE_CLOSE) { - /* No one should be updating fdstate, so no need to lock it */ - INSIST(manager->fdstate[fd] == CLOSE_PENDING); - manager->fdstate[fd] = CLOSED; - (void)unwatch_fd(manager, fd, SELECT_POKE_READ); - (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); - (void)close(fd); - return; - } - - LOCK(&manager->fdlock[lockid]); - if (manager->fdstate[fd] == CLOSE_PENDING) { - UNLOCK(&manager->fdlock[lockid]); - - /* - * We accept (and ignore) any error from unwatch_fd() as we are - * closing the socket, hoping it doesn't leave dangling state in - * the kernel. - * Note that unwatch_fd() must be called after releasing the - * fdlock; otherwise it could cause deadlock due to a lock order - * reversal. - */ - (void)unwatch_fd(manager, fd, SELECT_POKE_READ); - (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); - return; - } - if (manager->fdstate[fd] != MANAGED) { - UNLOCK(&manager->fdlock[lockid]); - return; - } - UNLOCK(&manager->fdlock[lockid]); - - /* - * Set requested bit. - */ - result = watch_fd(manager, fd, msg); - if (result != ISC_R_SUCCESS) { - /* - * XXXJT: what should we do? Ignoring the failure of watching - * a socket will make the application dysfunctional, but there - * seems to be no reasonable recovery process. - */ - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - "failed to start watching FD (%d): %s", - fd, isc_result_totext(result)); - } -} - -#ifdef USE_WATCHER_THREAD -/* - * Poke the select loop when there is something for us to do. - * The write is required (by POSIX) to complete. That is, we - * will not get partial writes. - */ -static void -select_poke(isc__socketmgr_t *mgr, int fd, int msg) { - int cc; - int buf[2]; - char strbuf[ISC_STRERRORSIZE]; - - buf[0] = fd; - buf[1] = msg; - - do { - cc = write(mgr->pipe_fds[1], buf, sizeof(buf)); -#ifdef ENOSR - /* - * Treat ENOSR as EAGAIN but loop slowly as it is - * unlikely to clear fast. - */ - if (cc < 0 && errno == ENOSR) { - sleep(1); - errno = EAGAIN; - } -#endif - } while (cc < 0 && SOFT_ERROR(errno)); - - if (cc < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - FATAL_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_WRITEFAILED, - "write() failed " - "during watcher poke: %s"), - strbuf); - } - - INSIST(cc == sizeof(buf)); -} - -/* - * Read a message on the internal fd. - */ -static void -select_readmsg(isc__socketmgr_t *mgr, int *fd, int *msg) { - int buf[2]; - int cc; - char strbuf[ISC_STRERRORSIZE]; - - cc = read(mgr->pipe_fds[0], buf, sizeof(buf)); - if (cc < 0) { - *msg = SELECT_POKE_NOTHING; - *fd = -1; /* Silence compiler. */ - if (SOFT_ERROR(errno)) - return; - - isc__strerror(errno, strbuf, sizeof(strbuf)); - FATAL_ERROR(__FILE__, __LINE__, - isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_READFAILED, - "read() failed " - "during watcher poke: %s"), - strbuf); - - return; - } - INSIST(cc == sizeof(buf)); - - *fd = buf[0]; - *msg = buf[1]; -} -#else /* USE_WATCHER_THREAD */ -/* - * Update the state of the socketmgr when something changes. - */ -static void -select_poke(isc__socketmgr_t *manager, int fd, int msg) { - if (msg == SELECT_POKE_SHUTDOWN) - return; - else if (fd >= 0) - wakeup_socket(manager, fd, msg); - return; -} -#endif /* USE_WATCHER_THREAD */ - -/* - * Make a fd non-blocking. - */ -static isc_result_t -make_nonblock(int fd) { - int ret; - int flags; - char strbuf[ISC_STRERRORSIZE]; -#ifdef USE_FIONBIO_IOCTL - int on = 1; - - ret = ioctl(fd, FIONBIO, (char *)&on); -#else - flags = fcntl(fd, F_GETFL, 0); - flags |= PORT_NONBLOCK; - ret = fcntl(fd, F_SETFL, flags); -#endif - - if (ret == -1) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, -#ifdef USE_FIONBIO_IOCTL - "ioctl(%d, FIONBIO, &on): %s", fd, -#else - "fcntl(%d, F_SETFL, %d): %s", fd, flags, -#endif - strbuf); - - return (ISC_R_UNEXPECTED); - } - - return (ISC_R_SUCCESS); -} - -#ifdef USE_CMSG -/* - * Not all OSes support advanced CMSG macros: CMSG_LEN and CMSG_SPACE. - * In order to ensure as much portability as possible, we provide wrapper - * functions of these macros. - * Note that cmsg_space() could run slow on OSes that do not have - * CMSG_SPACE. - */ -static inline ISC_SOCKADDR_LEN_T -cmsg_len(ISC_SOCKADDR_LEN_T len) { -#ifdef CMSG_LEN - return (CMSG_LEN(len)); -#else - ISC_SOCKADDR_LEN_T hdrlen; - - /* - * Cast NULL so that any pointer arithmetic performed by CMSG_DATA - * is correct. - */ - hdrlen = (ISC_SOCKADDR_LEN_T)CMSG_DATA(((struct cmsghdr *)NULL)); - return (hdrlen + len); -#endif -} - -static inline ISC_SOCKADDR_LEN_T -cmsg_space(ISC_SOCKADDR_LEN_T len) { -#ifdef CMSG_SPACE - return (CMSG_SPACE(len)); -#else - struct msghdr msg; - struct cmsghdr *cmsgp; - /* - * XXX: The buffer length is an ad-hoc value, but should be enough - * in a practical sense. - */ - char dummybuf[sizeof(struct cmsghdr) + 1024]; - - memset(&msg, 0, sizeof(msg)); - msg.msg_control = dummybuf; - msg.msg_controllen = sizeof(dummybuf); - - cmsgp = (struct cmsghdr *)dummybuf; - cmsgp->cmsg_len = cmsg_len(len); - - cmsgp = CMSG_NXTHDR(&msg, cmsgp); - if (cmsgp != NULL) - return ((char *)cmsgp - (char *)msg.msg_control); - else - return (0); -#endif -} -#endif /* USE_CMSG */ - -/* - * Process control messages received on a socket. - */ -static void -process_cmsg(isc__socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) { -#ifdef USE_CMSG - struct cmsghdr *cmsgp; -#ifdef ISC_PLATFORM_HAVEIN6PKTINFO - struct in6_pktinfo *pktinfop; -#endif -#ifdef SO_TIMESTAMP - void *timevalp; -#endif -#endif - - /* - * sock is used only when ISC_NET_BSD44MSGHDR and USE_CMSG are defined. - * msg and dev are used only when ISC_NET_BSD44MSGHDR is defined. - * They are all here, outside of the CPP tests, because it is - * more consistent with the usual ISC coding style. - */ - UNUSED(sock); - UNUSED(msg); - UNUSED(dev); - -#ifdef ISC_NET_BSD44MSGHDR - -#ifdef MSG_TRUNC - if ((msg->msg_flags & MSG_TRUNC) == MSG_TRUNC) - dev->attributes |= ISC_SOCKEVENTATTR_TRUNC; -#endif - -#ifdef MSG_CTRUNC - if ((msg->msg_flags & MSG_CTRUNC) == MSG_CTRUNC) - dev->attributes |= ISC_SOCKEVENTATTR_CTRUNC; -#endif - -#ifndef USE_CMSG - return; -#else - if (msg->msg_controllen == 0U || msg->msg_control == NULL) - return; - -#ifdef SO_TIMESTAMP - timevalp = NULL; -#endif -#ifdef ISC_PLATFORM_HAVEIN6PKTINFO - pktinfop = NULL; -#endif - - cmsgp = CMSG_FIRSTHDR(msg); - while (cmsgp != NULL) { - socket_log(sock, NULL, TRACE, - isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_PROCESSCMSG, - "processing cmsg %p", cmsgp); - -#ifdef ISC_PLATFORM_HAVEIN6PKTINFO - if (cmsgp->cmsg_level == IPPROTO_IPV6 - && cmsgp->cmsg_type == IPV6_PKTINFO) { - - pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp); - memcpy(&dev->pktinfo, pktinfop, - sizeof(struct in6_pktinfo)); - dev->attributes |= ISC_SOCKEVENTATTR_PKTINFO; - socket_log(sock, NULL, TRACE, - isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_IFRECEIVED, - "interface received on ifindex %u", - dev->pktinfo.ipi6_ifindex); - if (IN6_IS_ADDR_MULTICAST(&pktinfop->ipi6_addr)) - dev->attributes |= ISC_SOCKEVENTATTR_MULTICAST; - goto next; - } -#endif - -#ifdef SO_TIMESTAMP - if (cmsgp->cmsg_level == SOL_SOCKET - && cmsgp->cmsg_type == SCM_TIMESTAMP) { - struct timeval tv; - timevalp = CMSG_DATA(cmsgp); - memcpy(&tv, timevalp, sizeof(tv)); - dev->timestamp.seconds = tv.tv_sec; - dev->timestamp.nanoseconds = tv.tv_usec * 1000; - dev->attributes |= ISC_SOCKEVENTATTR_TIMESTAMP; - goto next; - } -#endif - - next: - cmsgp = CMSG_NXTHDR(msg, cmsgp); - } -#endif /* USE_CMSG */ - -#endif /* ISC_NET_BSD44MSGHDR */ -} - -/* - * Construct an iov array and attach it to the msghdr passed in. This is - * the SEND constructor, which will use the used region of the buffer - * (if using a buffer list) or will use the internal region (if a single - * buffer I/O is requested). - * - * Nothing can be NULL, and the done event must list at least one buffer - * on the buffer linked list for this function to be meaningful. - * - * If write_countp != NULL, *write_countp will hold the number of bytes - * this transaction can send. - */ -static void -build_msghdr_send(isc__socket_t *sock, isc_socketevent_t *dev, - struct msghdr *msg, struct iovec *iov, size_t *write_countp) -{ - unsigned int iovcount; - isc_buffer_t *buffer; - isc_region_t used; - size_t write_count; - size_t skip_count; - - memset(msg, 0, sizeof(*msg)); - - if (!sock->connected) { - msg->msg_name = (void *)&dev->address.type.sa; - msg->msg_namelen = dev->address.length; - } else { - msg->msg_name = NULL; - msg->msg_namelen = 0; - } - - buffer = ISC_LIST_HEAD(dev->bufferlist); - write_count = 0; - iovcount = 0; - - /* - * Single buffer I/O? Skip what we've done so far in this region. - */ - if (buffer == NULL) { - write_count = dev->region.length - dev->n; - iov[0].iov_base = (void *)(dev->region.base + dev->n); - iov[0].iov_len = write_count; - iovcount = 1; - - goto config; - } - - /* - * Multibuffer I/O. - * Skip the data in the buffer list that we have already written. - */ - skip_count = dev->n; - while (buffer != NULL) { - REQUIRE(ISC_BUFFER_VALID(buffer)); - if (skip_count < isc_buffer_usedlength(buffer)) - break; - skip_count -= isc_buffer_usedlength(buffer); - buffer = ISC_LIST_NEXT(buffer, link); - } - - while (buffer != NULL) { - INSIST(iovcount < MAXSCATTERGATHER_SEND); - - isc_buffer_usedregion(buffer, &used); - - if (used.length > 0) { - iov[iovcount].iov_base = (void *)(used.base - + skip_count); - iov[iovcount].iov_len = used.length - skip_count; - write_count += (used.length - skip_count); - skip_count = 0; - iovcount++; - } - buffer = ISC_LIST_NEXT(buffer, link); - } - - INSIST(skip_count == 0U); - - config: - msg->msg_iov = iov; - msg->msg_iovlen = iovcount; - -#ifdef ISC_NET_BSD44MSGHDR - msg->msg_control = NULL; - msg->msg_controllen = 0; - msg->msg_flags = 0; -#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO) - if ((sock->type == isc_sockettype_udp) - && ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0)) { -#if defined(IPV6_USE_MIN_MTU) - int use_min_mtu = 1; /* -1, 0, 1 */ -#endif - struct cmsghdr *cmsgp; - struct in6_pktinfo *pktinfop; - - socket_log(sock, NULL, TRACE, - isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_SENDTODATA, - "sendto pktinfo data, ifindex %u", - dev->pktinfo.ipi6_ifindex); - - msg->msg_controllen = cmsg_space(sizeof(struct in6_pktinfo)); - INSIST(msg->msg_controllen <= sock->sendcmsgbuflen); - msg->msg_control = (void *)sock->sendcmsgbuf; - - cmsgp = (struct cmsghdr *)sock->sendcmsgbuf; - cmsgp->cmsg_level = IPPROTO_IPV6; - cmsgp->cmsg_type = IPV6_PKTINFO; - cmsgp->cmsg_len = cmsg_len(sizeof(struct in6_pktinfo)); - pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp); - memcpy(pktinfop, &dev->pktinfo, sizeof(struct in6_pktinfo)); -#if defined(IPV6_USE_MIN_MTU) - /* - * Set IPV6_USE_MIN_MTU as a per packet option as FreeBSD - * ignores setsockopt(IPV6_USE_MIN_MTU) when IPV6_PKTINFO - * is used. - */ - cmsgp = (struct cmsghdr *)(sock->sendcmsgbuf + - msg->msg_controllen); - msg->msg_controllen += cmsg_space(sizeof(use_min_mtu)); - INSIST(msg->msg_controllen <= sock->sendcmsgbuflen); - - cmsgp->cmsg_level = IPPROTO_IPV6; - cmsgp->cmsg_type = IPV6_USE_MIN_MTU; - cmsgp->cmsg_len = cmsg_len(sizeof(use_min_mtu)); - memcpy(CMSG_DATA(cmsgp), &use_min_mtu, sizeof(use_min_mtu)); -#endif - } -#endif /* USE_CMSG && ISC_PLATFORM_HAVEIPV6 */ -#else /* ISC_NET_BSD44MSGHDR */ - msg->msg_accrights = NULL; - msg->msg_accrightslen = 0; -#endif /* ISC_NET_BSD44MSGHDR */ - - if (write_countp != NULL) - *write_countp = write_count; -} - -/* - * Construct an iov array and attach it to the msghdr passed in. This is - * the RECV constructor, which will use the available region of the buffer - * (if using a buffer list) or will use the internal region (if a single - * buffer I/O is requested). - * - * Nothing can be NULL, and the done event must list at least one buffer - * on the buffer linked list for this function to be meaningful. - * - * If read_countp != NULL, *read_countp will hold the number of bytes - * this transaction can receive. - */ -static void -build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev, - struct msghdr *msg, struct iovec *iov, size_t *read_countp) -{ - unsigned int iovcount; - isc_buffer_t *buffer; - isc_region_t available; - size_t read_count; - - memset(msg, 0, sizeof(struct msghdr)); - - if (sock->type == isc_sockettype_udp) { - memset(&dev->address, 0, sizeof(dev->address)); -#ifdef BROKEN_RECVMSG - if (sock->pf == AF_INET) { - msg->msg_name = (void *)&dev->address.type.sin; - msg->msg_namelen = sizeof(dev->address.type.sin6); - } else if (sock->pf == AF_INET6) { - msg->msg_name = (void *)&dev->address.type.sin6; - msg->msg_namelen = sizeof(dev->address.type.sin6); -#ifdef ISC_PLATFORM_HAVESYSUNH - } else if (sock->pf == AF_UNIX) { - msg->msg_name = (void *)&dev->address.type.sunix; - msg->msg_namelen = sizeof(dev->address.type.sunix); -#endif - } else { - msg->msg_name = (void *)&dev->address.type.sa; - msg->msg_namelen = sizeof(dev->address.type); - } -#else - msg->msg_name = (void *)&dev->address.type.sa; - msg->msg_namelen = sizeof(dev->address.type); -#endif -#ifdef ISC_NET_RECVOVERFLOW - /* If needed, steal one iovec for overflow detection. */ - maxiov--; -#endif - } else { /* TCP */ - msg->msg_name = NULL; - msg->msg_namelen = 0; - dev->address = sock->peer_address; - } - - buffer = ISC_LIST_HEAD(dev->bufferlist); - read_count = 0; - - /* - * Single buffer I/O? Skip what we've done so far in this region. - */ - if (buffer == NULL) { - read_count = dev->region.length - dev->n; - iov[0].iov_base = (void *)(dev->region.base + dev->n); - iov[0].iov_len = read_count; - iovcount = 1; - - goto config; - } - - /* - * Multibuffer I/O. - * Skip empty buffers. - */ - while (buffer != NULL) { - REQUIRE(ISC_BUFFER_VALID(buffer)); - if (isc_buffer_availablelength(buffer) != 0) - break; - buffer = ISC_LIST_NEXT(buffer, link); - } - - iovcount = 0; - while (buffer != NULL) { - INSIST(iovcount < MAXSCATTERGATHER_RECV); - - isc_buffer_availableregion(buffer, &available); - - if (available.length > 0) { - iov[iovcount].iov_base = (void *)(available.base); - iov[iovcount].iov_len = available.length; - read_count += available.length; - iovcount++; - } - buffer = ISC_LIST_NEXT(buffer, link); - } - - config: - - /* - * If needed, set up to receive that one extra byte. Note that - * we know there is at least one iov left, since we stole it - * at the top of this function. - */ -#ifdef ISC_NET_RECVOVERFLOW - if (sock->type == isc_sockettype_udp) { - iov[iovcount].iov_base = (void *)(&sock->overflow); - iov[iovcount].iov_len = 1; - iovcount++; - } -#endif - - msg->msg_iov = iov; - msg->msg_iovlen = iovcount; - -#ifdef ISC_NET_BSD44MSGHDR - msg->msg_control = NULL; - msg->msg_controllen = 0; - msg->msg_flags = 0; -#if defined(USE_CMSG) - if (sock->type == isc_sockettype_udp) { - msg->msg_control = sock->recvcmsgbuf; - msg->msg_controllen = sock->recvcmsgbuflen; - } -#endif /* USE_CMSG */ -#else /* ISC_NET_BSD44MSGHDR */ - msg->msg_accrights = NULL; - msg->msg_accrightslen = 0; -#endif /* ISC_NET_BSD44MSGHDR */ - - if (read_countp != NULL) - *read_countp = read_count; -} - -static void -set_dev_address(isc_sockaddr_t *address, isc__socket_t *sock, - isc_socketevent_t *dev) -{ - if (sock->type == isc_sockettype_udp) { - if (address != NULL) - dev->address = *address; - else - dev->address = sock->peer_address; - } else if (sock->type == isc_sockettype_tcp) { - INSIST(address == NULL); - dev->address = sock->peer_address; - } -} - -static void -destroy_socketevent(isc_event_t *event) { - isc_socketevent_t *ev = (isc_socketevent_t *)event; - - INSIST(ISC_LIST_EMPTY(ev->bufferlist)); - - (ev->destroy)(event); -} - -static isc_socketevent_t * -allocate_socketevent(isc__socket_t *sock, isc_eventtype_t eventtype, - isc_taskaction_t action, const void *arg) -{ - isc_socketevent_t *ev; - - ev = (isc_socketevent_t *)isc_event_allocate(sock->manager->mctx, - sock, eventtype, - action, arg, - sizeof(*ev)); - - if (ev == NULL) - return (NULL); - - ev->result = ISC_R_UNSET; - ISC_LINK_INIT(ev, ev_link); - ISC_LIST_INIT(ev->bufferlist); - ev->region.base = NULL; - ev->n = 0; - ev->offset = 0; - ev->attributes = 0; - ev->destroy = ev->ev_destroy; - ev->ev_destroy = destroy_socketevent; - - return (ev); -} - -#if defined(ISC_SOCKET_DEBUG) -static void -dump_msg(struct msghdr *msg) { - unsigned int i; - - printf("MSGHDR %p\n", msg); - printf("\tname %p, namelen %ld\n", msg->msg_name, - (long) msg->msg_namelen); - printf("\tiov %p, iovlen %ld\n", msg->msg_iov, - (long) msg->msg_iovlen); - for (i = 0; i < (unsigned int)msg->msg_iovlen; i++) - printf("\t\t%d\tbase %p, len %ld\n", i, - msg->msg_iov[i].iov_base, - (long) msg->msg_iov[i].iov_len); -#ifdef ISC_NET_BSD44MSGHDR - printf("\tcontrol %p, controllen %ld\n", msg->msg_control, - (long) msg->msg_controllen); -#endif -} -#endif - -#define DOIO_SUCCESS 0 /* i/o ok, event sent */ -#define DOIO_SOFT 1 /* i/o ok, soft error, no event sent */ -#define DOIO_HARD 2 /* i/o error, event sent */ -#define DOIO_EOF 3 /* EOF, no event sent */ - -static int -doio_recv(isc__socket_t *sock, isc_socketevent_t *dev) { - int cc; - struct iovec iov[MAXSCATTERGATHER_RECV]; - size_t read_count; - size_t actual_count; - struct msghdr msghdr; - isc_buffer_t *buffer; - int recv_errno; - char strbuf[ISC_STRERRORSIZE]; - - build_msghdr_recv(sock, dev, &msghdr, iov, &read_count); - -#if defined(ISC_SOCKET_DEBUG) - dump_msg(&msghdr); -#endif - - cc = recvmsg(sock->fd, &msghdr, 0); - recv_errno = errno; - -#if defined(ISC_SOCKET_DEBUG) - dump_msg(&msghdr); -#endif - - if (cc < 0) { - if (SOFT_ERROR(recv_errno)) - return (DOIO_SOFT); - - if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) { - isc__strerror(recv_errno, strbuf, sizeof(strbuf)); - socket_log(sock, NULL, IOEVENT, - isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_DOIORECV, - "doio_recv: recvmsg(%d) %d bytes, err %d/%s", - sock->fd, cc, recv_errno, strbuf); - } - -#define SOFT_OR_HARD(_system, _isc) \ - if (recv_errno == _system) { \ - if (sock->connected) { \ - dev->result = _isc; \ - inc_stats(sock->manager->stats, \ - sock->statsindex[STATID_RECVFAIL]); \ - return (DOIO_HARD); \ - } \ - return (DOIO_SOFT); \ - } -#define ALWAYS_HARD(_system, _isc) \ - if (recv_errno == _system) { \ - dev->result = _isc; \ - inc_stats(sock->manager->stats, \ - sock->statsindex[STATID_RECVFAIL]); \ - return (DOIO_HARD); \ - } - - SOFT_OR_HARD(ECONNREFUSED, ISC_R_CONNREFUSED); - SOFT_OR_HARD(ENETUNREACH, ISC_R_NETUNREACH); - SOFT_OR_HARD(EHOSTUNREACH, ISC_R_HOSTUNREACH); - SOFT_OR_HARD(EHOSTDOWN, ISC_R_HOSTDOWN); - /* HPUX 11.11 can return EADDRNOTAVAIL. */ - SOFT_OR_HARD(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL); - ALWAYS_HARD(ENOBUFS, ISC_R_NORESOURCES); - /* - * HPUX returns EPROTO and EINVAL on receiving some ICMP/ICMPv6 - * errors. - */ -#ifdef EPROTO - SOFT_OR_HARD(EPROTO, ISC_R_HOSTUNREACH); -#endif - SOFT_OR_HARD(EINVAL, ISC_R_HOSTUNREACH); - -#undef SOFT_OR_HARD -#undef ALWAYS_HARD - - dev->result = isc__errno2result(recv_errno); - inc_stats(sock->manager->stats, - sock->statsindex[STATID_RECVFAIL]); - return (DOIO_HARD); - } - - /* - * On TCP and UNIX sockets, zero length reads indicate EOF, - * while on UDP sockets, zero length reads are perfectly valid, - * although strange. - */ - switch (sock->type) { - case isc_sockettype_tcp: - case isc_sockettype_unix: - if (cc == 0) - return (DOIO_EOF); - break; - case isc_sockettype_udp: - break; - case isc_sockettype_fdwatch: - default: - INSIST(0); - } - - if (sock->type == isc_sockettype_udp) { - dev->address.length = msghdr.msg_namelen; - if (isc_sockaddr_getport(&dev->address) == 0) { - if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) { - socket_log(sock, &dev->address, IOEVENT, - isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_ZEROPORT, - "dropping source port zero packet"); - } - return (DOIO_SOFT); - } - /* - * Simulate a firewall blocking UDP responses bigger than - * 512 bytes. - */ - if (sock->manager->maxudp != 0 && cc > sock->manager->maxudp) - return (DOIO_SOFT); - } - - socket_log(sock, &dev->address, IOEVENT, - isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_PKTRECV, - "packet received correctly"); - - /* - * Overflow bit detection. If we received MORE bytes than we should, - * this indicates an overflow situation. Set the flag in the - * dev entry and adjust how much we read by one. - */ -#ifdef ISC_NET_RECVOVERFLOW - if ((sock->type == isc_sockettype_udp) && ((size_t)cc > read_count)) { - dev->attributes |= ISC_SOCKEVENTATTR_TRUNC; - cc--; - } -#endif - - /* - * If there are control messages attached, run through them and pull - * out the interesting bits. - */ - if (sock->type == isc_sockettype_udp) - process_cmsg(sock, &msghdr, dev); - - /* - * update the buffers (if any) and the i/o count - */ - dev->n += cc; - actual_count = cc; - buffer = ISC_LIST_HEAD(dev->bufferlist); - while (buffer != NULL && actual_count > 0U) { - REQUIRE(ISC_BUFFER_VALID(buffer)); - if (isc_buffer_availablelength(buffer) <= actual_count) { - actual_count -= isc_buffer_availablelength(buffer); - isc_buffer_add(buffer, - isc_buffer_availablelength(buffer)); - } else { - isc_buffer_add(buffer, actual_count); - actual_count = 0; - POST(actual_count); - break; - } - buffer = ISC_LIST_NEXT(buffer, link); - if (buffer == NULL) { - INSIST(actual_count == 0U); - } - } - - /* - * If we read less than we expected, update counters, - * and let the upper layer poke the descriptor. - */ - if (((size_t)cc != read_count) && (dev->n < dev->minimum)) - return (DOIO_SOFT); - - /* - * Full reads are posted, or partials if partials are ok. - */ - dev->result = ISC_R_SUCCESS; - return (DOIO_SUCCESS); -} - -/* - * Returns: - * DOIO_SUCCESS The operation succeeded. dev->result contains - * ISC_R_SUCCESS. - * - * DOIO_HARD A hard or unexpected I/O error was encountered. - * dev->result contains the appropriate error. - * - * DOIO_SOFT A soft I/O error was encountered. No senddone - * event was sent. The operation should be retried. - * - * No other return values are possible. - */ -static int -doio_send(isc__socket_t *sock, isc_socketevent_t *dev) { - int cc; - struct iovec iov[MAXSCATTERGATHER_SEND]; - size_t write_count; - struct msghdr msghdr; - char addrbuf[ISC_SOCKADDR_FORMATSIZE]; - int attempts = 0; - int send_errno; - char strbuf[ISC_STRERRORSIZE]; - - build_msghdr_send(sock, dev, &msghdr, iov, &write_count); - - resend: - cc = sendmsg(sock->fd, &msghdr, 0); - send_errno = errno; - - /* - * Check for error or block condition. - */ - if (cc < 0) { - if (send_errno == EINTR && ++attempts < NRETRIES) - goto resend; - - if (SOFT_ERROR(send_errno)) - return (DOIO_SOFT); - -#define SOFT_OR_HARD(_system, _isc) \ - if (send_errno == _system) { \ - if (sock->connected) { \ - dev->result = _isc; \ - inc_stats(sock->manager->stats, \ - sock->statsindex[STATID_SENDFAIL]); \ - return (DOIO_HARD); \ - } \ - return (DOIO_SOFT); \ - } -#define ALWAYS_HARD(_system, _isc) \ - if (send_errno == _system) { \ - dev->result = _isc; \ - inc_stats(sock->manager->stats, \ - sock->statsindex[STATID_SENDFAIL]); \ - return (DOIO_HARD); \ - } - - SOFT_OR_HARD(ECONNREFUSED, ISC_R_CONNREFUSED); - ALWAYS_HARD(EACCES, ISC_R_NOPERM); - ALWAYS_HARD(EAFNOSUPPORT, ISC_R_ADDRNOTAVAIL); - ALWAYS_HARD(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL); - ALWAYS_HARD(EHOSTUNREACH, ISC_R_HOSTUNREACH); -#ifdef EHOSTDOWN - ALWAYS_HARD(EHOSTDOWN, ISC_R_HOSTUNREACH); -#endif - ALWAYS_HARD(ENETUNREACH, ISC_R_NETUNREACH); - ALWAYS_HARD(ENOBUFS, ISC_R_NORESOURCES); - ALWAYS_HARD(EPERM, ISC_R_HOSTUNREACH); - ALWAYS_HARD(EPIPE, ISC_R_NOTCONNECTED); - ALWAYS_HARD(ECONNRESET, ISC_R_CONNECTIONRESET); - -#undef SOFT_OR_HARD -#undef ALWAYS_HARD - - /* - * The other error types depend on whether or not the - * socket is UDP or TCP. If it is UDP, some errors - * that we expect to be fatal under TCP are merely - * annoying, and are really soft errors. - * - * However, these soft errors are still returned as - * a status. - */ - isc_sockaddr_format(&dev->address, addrbuf, sizeof(addrbuf)); - isc__strerror(send_errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, "internal_send: %s: %s", - addrbuf, strbuf); - dev->result = isc__errno2result(send_errno); - inc_stats(sock->manager->stats, - sock->statsindex[STATID_SENDFAIL]); - return (DOIO_HARD); - } - - if (cc == 0) { - inc_stats(sock->manager->stats, - sock->statsindex[STATID_SENDFAIL]); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "doio_send: send() %s 0", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_RETURNED, "returned")); - } - - /* - * If we write less than we expected, update counters, poke. - */ - dev->n += cc; - if ((size_t)cc != write_count) - return (DOIO_SOFT); - - /* - * Exactly what we wanted to write. We're done with this - * entry. Post its completion event. - */ - dev->result = ISC_R_SUCCESS; - return (DOIO_SUCCESS); -} - -/* - * Kill. - * - * Caller must ensure that the socket is not locked and no external - * references exist. - */ -static void -closesocket(isc__socketmgr_t *manager, isc__socket_t *sock, int fd) { - isc_sockettype_t type = sock->type; - int lockid = FDLOCK_ID(fd); - - /* - * No one has this socket open, so the watcher doesn't have to be - * poked, and the socket doesn't have to be locked. - */ - LOCK(&manager->fdlock[lockid]); - manager->fds[fd] = NULL; - if (type == isc_sockettype_fdwatch) - manager->fdstate[fd] = CLOSED; - else - manager->fdstate[fd] = CLOSE_PENDING; - UNLOCK(&manager->fdlock[lockid]); - if (type == isc_sockettype_fdwatch) { - /* - * The caller may close the socket once this function returns, - * and `fd' may be reassigned for a new socket. So we do - * unwatch_fd() here, rather than defer it via select_poke(). - * Note: this may complicate data protection among threads and - * may reduce performance due to additional locks. One way to - * solve this would be to dup() the watched descriptor, but we - * take a simpler approach at this moment. - */ - (void)unwatch_fd(manager, fd, SELECT_POKE_READ); - (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); - } else - select_poke(manager, fd, SELECT_POKE_CLOSE); - - inc_stats(manager->stats, sock->statsindex[STATID_CLOSE]); - - /* - * update manager->maxfd here (XXX: this should be implemented more - * efficiently) - */ -#ifdef USE_SELECT - LOCK(&manager->lock); - if (manager->maxfd == fd) { - int i; - - manager->maxfd = 0; - for (i = fd - 1; i >= 0; i--) { - lockid = FDLOCK_ID(i); - - LOCK(&manager->fdlock[lockid]); - if (manager->fdstate[i] == MANAGED) { - manager->maxfd = i; - UNLOCK(&manager->fdlock[lockid]); - break; - } - UNLOCK(&manager->fdlock[lockid]); - } -#ifdef ISC_PLATFORM_USETHREADS - if (manager->maxfd < manager->pipe_fds[0]) - manager->maxfd = manager->pipe_fds[0]; -#endif - } - UNLOCK(&manager->lock); -#endif /* USE_SELECT */ -} - -static void -destroy(isc__socket_t **sockp) { - int fd; - isc__socket_t *sock = *sockp; - isc__socketmgr_t *manager = sock->manager; - - socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_DESTROYING, "destroying"); - - INSIST(ISC_LIST_EMPTY(sock->accept_list)); - INSIST(ISC_LIST_EMPTY(sock->recv_list)); - INSIST(ISC_LIST_EMPTY(sock->send_list)); - INSIST(sock->connect_ev == NULL); - REQUIRE(sock->fd == -1 || sock->fd < (int)manager->maxsocks); - - if (sock->fd >= 0) { - fd = sock->fd; - sock->fd = -1; - closesocket(manager, sock, fd); - } - - LOCK(&manager->lock); - - ISC_LIST_UNLINK(manager->socklist, sock, link); - -#ifdef USE_WATCHER_THREAD - if (ISC_LIST_EMPTY(manager->socklist)) - SIGNAL(&manager->shutdown_ok); -#endif /* USE_WATCHER_THREAD */ - - /* can't unlock manager as its memory context is still used */ - free_socket(sockp); - - UNLOCK(&manager->lock); -} - -static isc_result_t -allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type, - isc__socket_t **socketp) -{ - isc__socket_t *sock; - isc_result_t result; - ISC_SOCKADDR_LEN_T cmsgbuflen; - - sock = isc_mem_get(manager->mctx, sizeof(*sock)); - - if (sock == NULL) - return (ISC_R_NOMEMORY); - - sock->common.magic = 0; - sock->common.impmagic = 0; - sock->references = 0; - - sock->manager = manager; - sock->type = type; - sock->fd = -1; - sock->dupped = 0; - sock->statsindex = NULL; - - ISC_LINK_INIT(sock, link); - - sock->recvcmsgbuf = NULL; - sock->sendcmsgbuf = NULL; - - /* - * Set up cmsg buffers. - */ - cmsgbuflen = 0; -#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO) - cmsgbuflen += cmsg_space(sizeof(struct in6_pktinfo)); -#endif -#if defined(USE_CMSG) && defined(SO_TIMESTAMP) - cmsgbuflen += cmsg_space(sizeof(struct timeval)); -#endif - sock->recvcmsgbuflen = cmsgbuflen; - if (sock->recvcmsgbuflen != 0U) { - sock->recvcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen); - if (sock->recvcmsgbuf == NULL) { - result = ISC_R_NOMEMORY; - goto error; - } - } - - cmsgbuflen = 0; -#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO) - cmsgbuflen += cmsg_space(sizeof(struct in6_pktinfo)); -#if defined(IPV6_USE_MIN_MTU) - /* - * Provide space for working around FreeBSD's broken IPV6_USE_MIN_MTU - * support. - */ - cmsgbuflen += cmsg_space(sizeof(int)); -#endif -#endif - sock->sendcmsgbuflen = cmsgbuflen; - if (sock->sendcmsgbuflen != 0U) { - sock->sendcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen); - if (sock->sendcmsgbuf == NULL) { - result = ISC_R_NOMEMORY; - goto error; - } - } - - memset(sock->name, 0, sizeof(sock->name)); - sock->tag = NULL; - - /* - * Set up list of readers and writers to be initially empty. - */ - ISC_LIST_INIT(sock->recv_list); - ISC_LIST_INIT(sock->send_list); - ISC_LIST_INIT(sock->accept_list); - sock->connect_ev = NULL; - sock->pending_recv = 0; - sock->pending_send = 0; - sock->pending_accept = 0; - sock->listener = 0; - sock->connected = 0; - sock->connecting = 0; - sock->bound = 0; - - /* - * Initialize the lock. - */ - result = isc_mutex_init(&sock->lock); - if (result != ISC_R_SUCCESS) { - sock->common.magic = 0; - sock->common.impmagic = 0; - goto error; - } - - /* - * Initialize readable and writable events. - */ - ISC_EVENT_INIT(&sock->readable_ev, sizeof(intev_t), - ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTR, - NULL, sock, sock, NULL, NULL); - ISC_EVENT_INIT(&sock->writable_ev, sizeof(intev_t), - ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTW, - NULL, sock, sock, NULL, NULL); - - sock->common.magic = ISCAPI_SOCKET_MAGIC; - sock->common.impmagic = SOCKET_MAGIC; - *socketp = sock; - - return (ISC_R_SUCCESS); - - error: - if (sock->recvcmsgbuf != NULL) - isc_mem_put(manager->mctx, sock->recvcmsgbuf, - sock->recvcmsgbuflen); - if (sock->sendcmsgbuf != NULL) - isc_mem_put(manager->mctx, sock->sendcmsgbuf, - sock->sendcmsgbuflen); - isc_mem_put(manager->mctx, sock, sizeof(*sock)); - - return (result); -} - -/* - * This event requires that the various lists be empty, that the reference - * count be 1, and that the magic number is valid. The other socket bits, - * like the lock, must be initialized as well. The fd associated must be - * marked as closed, by setting it to -1 on close, or this routine will - * also close the socket. - */ -static void -free_socket(isc__socket_t **socketp) { - isc__socket_t *sock = *socketp; - - INSIST(sock->references == 0); - INSIST(VALID_SOCKET(sock)); - INSIST(!sock->connecting); - INSIST(!sock->pending_recv); - INSIST(!sock->pending_send); - INSIST(!sock->pending_accept); - INSIST(ISC_LIST_EMPTY(sock->recv_list)); - INSIST(ISC_LIST_EMPTY(sock->send_list)); - INSIST(ISC_LIST_EMPTY(sock->accept_list)); - INSIST(!ISC_LINK_LINKED(sock, link)); - - if (sock->recvcmsgbuf != NULL) - isc_mem_put(sock->manager->mctx, sock->recvcmsgbuf, - sock->recvcmsgbuflen); - if (sock->sendcmsgbuf != NULL) - isc_mem_put(sock->manager->mctx, sock->sendcmsgbuf, - sock->sendcmsgbuflen); - - sock->common.magic = 0; - sock->common.impmagic = 0; - - DESTROYLOCK(&sock->lock); - - isc_mem_put(sock->manager->mctx, sock, sizeof(*sock)); - - *socketp = NULL; -} - -#ifdef SO_BSDCOMPAT -/* - * This really should not be necessary to do. Having to workout - * which kernel version we are on at run time so that we don't cause - * the kernel to issue a warning about us using a deprecated socket option. - * Such warnings should *never* be on by default in production kernels. - * - * We can't do this a build time because executables are moved between - * machines and hence kernels. - * - * We can't just not set SO_BSDCOMAT because some kernels require it. - */ - -static isc_once_t bsdcompat_once = ISC_ONCE_INIT; -isc_boolean_t bsdcompat = ISC_TRUE; - -static void -clear_bsdcompat(void) { -#ifdef __linux__ - struct utsname buf; - char *endp; - long int major; - long int minor; - - uname(&buf); /* Can only fail if buf is bad in Linux. */ - - /* Paranoia in parsing can be increased, but we trust uname(). */ - major = strtol(buf.release, &endp, 10); - if (*endp == '.') { - minor = strtol(endp+1, &endp, 10); - if ((major > 2) || ((major == 2) && (minor >= 4))) { - bsdcompat = ISC_FALSE; - } - } -#endif /* __linux __ */ -} -#endif - -static void -use_min_mtu(isc__socket_t *sock) { -#if !defined(IPV6_USE_MIN_MTU) && !defined(IPV6_MTU) - UNUSED(sock); -#endif -#ifdef IPV6_USE_MIN_MTU - /* use minimum MTU */ - if (sock->pf == AF_INET6) { - int on = 1; - (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU, - (void *)&on, sizeof(on)); - } -#endif -#if defined(IPV6_MTU) - /* - * Use minimum MTU on IPv6 sockets. - */ - if (sock->pf == AF_INET6) { - int mtu = 1280; - (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU, - &mtu, sizeof(mtu)); - } -#endif -} - -static isc_result_t -opensocket(isc__socketmgr_t *manager, isc__socket_t *sock, - isc__socket_t *dup_socket) -{ - isc_result_t result; - char strbuf[ISC_STRERRORSIZE]; - const char *err = "socket"; - int tries = 0; -#if defined(USE_CMSG) || defined(SO_BSDCOMPAT) || defined(SO_NOSIGPIPE) - int on = 1; -#endif -#if defined(SO_RCVBUF) - ISC_SOCKADDR_LEN_T optlen; - int size; -#endif - - again: - if (dup_socket == NULL) { - switch (sock->type) { - case isc_sockettype_udp: - sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP); - break; - case isc_sockettype_tcp: - sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP); - break; - case isc_sockettype_unix: - sock->fd = socket(sock->pf, SOCK_STREAM, 0); - break; - case isc_sockettype_fdwatch: - /* - * We should not be called for isc_sockettype_fdwatch - * sockets. - */ - INSIST(0); - break; - } - } else { - sock->fd = dup(dup_socket->fd); - sock->dupped = 1; - sock->bound = dup_socket->bound; - } - if (sock->fd == -1 && errno == EINTR && tries++ < 42) - goto again; - -#ifdef F_DUPFD - /* - * Leave a space for stdio and TCP to work in. - */ - if (manager->reserved != 0 && sock->type == isc_sockettype_udp && - sock->fd >= 0 && sock->fd < manager->reserved) { - int new, tmp; - new = fcntl(sock->fd, F_DUPFD, manager->reserved); - tmp = errno; - (void)close(sock->fd); - errno = tmp; - sock->fd = new; - err = "isc_socket_create: fcntl/reserved"; - } else if (sock->fd >= 0 && sock->fd < 20) { - int new, tmp; - new = fcntl(sock->fd, F_DUPFD, 20); - tmp = errno; - (void)close(sock->fd); - errno = tmp; - sock->fd = new; - err = "isc_socket_create: fcntl"; - } -#endif - - if (sock->fd >= (int)manager->maxsocks) { - (void)close(sock->fd); - isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_TOOMANYFDS, - "socket: file descriptor exceeds limit (%d/%u)", - sock->fd, manager->maxsocks); - return (ISC_R_NORESOURCES); - } - - if (sock->fd < 0) { - switch (errno) { - case EMFILE: - case ENFILE: - isc__strerror(errno, strbuf, sizeof(strbuf)); - isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_TOOMANYFDS, - "%s: %s", err, strbuf); - /* fallthrough */ - case ENOBUFS: - return (ISC_R_NORESOURCES); - - case EPROTONOSUPPORT: - case EPFNOSUPPORT: - case EAFNOSUPPORT: - /* - * Linux 2.2 (and maybe others) return EINVAL instead of - * EAFNOSUPPORT. - */ - case EINVAL: - return (ISC_R_FAMILYNOSUPPORT); - - default: - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "%s() %s: %s", err, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - return (ISC_R_UNEXPECTED); - } - } - - if (dup_socket != NULL) - goto setup_done; - - result = make_nonblock(sock->fd); - if (result != ISC_R_SUCCESS) { - (void)close(sock->fd); - return (result); - } - -#ifdef SO_BSDCOMPAT - RUNTIME_CHECK(isc_once_do(&bsdcompat_once, - clear_bsdcompat) == ISC_R_SUCCESS); - if (sock->type != isc_sockettype_unix && bsdcompat && - setsockopt(sock->fd, SOL_SOCKET, SO_BSDCOMPAT, - (void *)&on, sizeof(on)) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "setsockopt(%d, SO_BSDCOMPAT) %s: %s", - sock->fd, - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed"), - strbuf); - /* Press on... */ - } -#endif - -#ifdef SO_NOSIGPIPE - if (setsockopt(sock->fd, SOL_SOCKET, SO_NOSIGPIPE, - (void *)&on, sizeof(on)) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "setsockopt(%d, SO_NOSIGPIPE) %s: %s", - sock->fd, - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed"), - strbuf); - /* Press on... */ - } -#endif - - /* - * Use minimum mtu if possible. - */ - use_min_mtu(sock); - -#if defined(USE_CMSG) || defined(SO_RCVBUF) - if (sock->type == isc_sockettype_udp) { - -#if defined(USE_CMSG) -#if defined(SO_TIMESTAMP) - if (setsockopt(sock->fd, SOL_SOCKET, SO_TIMESTAMP, - (void *)&on, sizeof(on)) < 0 - && errno != ENOPROTOOPT) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "setsockopt(%d, SO_TIMESTAMP) %s: %s", - sock->fd, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - /* Press on... */ - } -#endif /* SO_TIMESTAMP */ - -#if defined(ISC_PLATFORM_HAVEIPV6) - if (sock->pf == AF_INET6 && sock->recvcmsgbuflen == 0U) { - /* - * Warn explicitly because this anomaly can be hidden - * in usual operation (and unexpectedly appear later). - */ - UNEXPECTED_ERROR(__FILE__, __LINE__, - "No buffer available to receive " - "IPv6 destination"); - } -#ifdef ISC_PLATFORM_HAVEIN6PKTINFO -#ifdef IPV6_RECVPKTINFO - /* RFC 3542 */ - if ((sock->pf == AF_INET6) - && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, - (void *)&on, sizeof(on)) < 0)) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "setsockopt(%d, IPV6_RECVPKTINFO) " - "%s: %s", sock->fd, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - } -#else - /* RFC 2292 */ - if ((sock->pf == AF_INET6) - && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO, - (void *)&on, sizeof(on)) < 0)) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "setsockopt(%d, IPV6_PKTINFO) %s: %s", - sock->fd, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - } -#endif /* IPV6_RECVPKTINFO */ -#endif /* ISC_PLATFORM_HAVEIN6PKTINFO */ -#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT) - /* - * Turn off Path MTU discovery on IPv6/UDP sockets. - */ - if (sock->pf == AF_INET6) { - int action = IPV6_PMTUDISC_DONT; - (void)setsockopt(sock->fd, IPPROTO_IPV6, - IPV6_MTU_DISCOVER, &action, - sizeof(action)); - } -#endif -#endif /* ISC_PLATFORM_HAVEIPV6 */ -#endif /* defined(USE_CMSG) */ - -#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) - /* - * Turn off Path MTU discovery on IPv4/UDP sockets. - */ - if (sock->pf == AF_INET) { - int action = IP_PMTUDISC_DONT; - (void)setsockopt(sock->fd, IPPROTO_IP, IP_MTU_DISCOVER, - &action, sizeof(action)); - } -#endif -#if defined(IP_DONTFRAG) - /* - * Turn off Path MTU discovery on IPv4/UDP sockets. - */ - if (sock->pf == AF_INET) { - int off = 0; - (void)setsockopt(sock->fd, IPPROTO_IP, IP_DONTFRAG, - &off, sizeof(off)); - } -#endif - -#if defined(SO_RCVBUF) - optlen = sizeof(size); - if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, - (void *)&size, &optlen) >= 0 && - size < RCVBUFSIZE) { - size = RCVBUFSIZE; - if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, - (void *)&size, sizeof(size)) == -1) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "setsockopt(%d, SO_RCVBUF, %d) %s: %s", - sock->fd, size, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - } - } -#endif - } -#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */ - -setup_done: - inc_stats(manager->stats, sock->statsindex[STATID_OPEN]); - - return (ISC_R_SUCCESS); -} - -/* - * Create a 'type' socket or duplicate an existing socket, managed - * by 'manager'. Events will be posted to 'task' and when dispatched - * 'action' will be called with 'arg' as the arg value. The new - * socket is returned in 'socketp'. - */ -static isc_result_t -socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, - isc_socket_t **socketp, isc_socket_t *dup_socket) -{ - isc__socket_t *sock = NULL; - isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; - isc_result_t result; - int lockid; - - REQUIRE(VALID_MANAGER(manager)); - REQUIRE(socketp != NULL && *socketp == NULL); - REQUIRE(type != isc_sockettype_fdwatch); - - result = allocate_socket(manager, type, &sock); - if (result != ISC_R_SUCCESS) - return (result); - - switch (sock->type) { - case isc_sockettype_udp: - sock->statsindex = - (pf == AF_INET) ? udp4statsindex : udp6statsindex; - break; - case isc_sockettype_tcp: - sock->statsindex = - (pf == AF_INET) ? tcp4statsindex : tcp6statsindex; - break; - case isc_sockettype_unix: - sock->statsindex = unixstatsindex; - break; - default: - INSIST(0); - } - - sock->pf = pf; - - result = opensocket(manager, sock, (isc__socket_t *)dup_socket); - if (result != ISC_R_SUCCESS) { - inc_stats(manager->stats, sock->statsindex[STATID_OPENFAIL]); - free_socket(&sock); - return (result); - } - - sock->common.methods = (isc_socketmethods_t *)&socketmethods; - sock->references = 1; - *socketp = (isc_socket_t *)sock; - - /* - * Note we don't have to lock the socket like we normally would because - * there are no external references to it yet. - */ - - lockid = FDLOCK_ID(sock->fd); - LOCK(&manager->fdlock[lockid]); - manager->fds[sock->fd] = sock; - manager->fdstate[sock->fd] = MANAGED; -#ifdef USE_DEVPOLL - INSIST(sock->manager->fdpollinfo[sock->fd].want_read == 0 && - sock->manager->fdpollinfo[sock->fd].want_write == 0); -#endif - UNLOCK(&manager->fdlock[lockid]); - - LOCK(&manager->lock); - ISC_LIST_APPEND(manager->socklist, sock, link); -#ifdef USE_SELECT - if (manager->maxfd < sock->fd) - manager->maxfd = sock->fd; -#endif - UNLOCK(&manager->lock); - - socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_CREATED, dup_socket != NULL ? "dupped" : "created"); - - return (ISC_R_SUCCESS); -} - -/*% - * Create a new 'type' socket managed by 'manager'. Events - * will be posted to 'task' and when dispatched 'action' will be - * called with 'arg' as the arg value. The new socket is returned - * in 'socketp'. - */ -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, - isc_socket_t **socketp) -{ - return (socket_create(manager0, pf, type, socketp, NULL)); -} - -/*% - * Duplicate an existing socket. The new socket is returned - * in 'socketp'. - */ -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_dup(isc_socket_t *sock0, isc_socket_t **socketp) { - isc__socket_t *sock = (isc__socket_t *)sock0; - - REQUIRE(VALID_SOCKET(sock)); - REQUIRE(socketp != NULL && *socketp == NULL); - - return (socket_create((isc_socketmgr_t *) sock->manager, - sock->pf, sock->type, socketp, - sock0)); -} - -#ifdef BIND9 -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_open(isc_socket_t *sock0) { - isc_result_t result; - isc__socket_t *sock = (isc__socket_t *)sock0; - - REQUIRE(VALID_SOCKET(sock)); - - LOCK(&sock->lock); - REQUIRE(sock->references == 1); - REQUIRE(sock->type != isc_sockettype_fdwatch); - UNLOCK(&sock->lock); - /* - * We don't need to retain the lock hereafter, since no one else has - * this socket. - */ - REQUIRE(sock->fd == -1); - - result = opensocket(sock->manager, sock, NULL); - if (result != ISC_R_SUCCESS) - sock->fd = -1; - - if (result == ISC_R_SUCCESS) { - int lockid = FDLOCK_ID(sock->fd); - - LOCK(&sock->manager->fdlock[lockid]); - sock->manager->fds[sock->fd] = sock; - sock->manager->fdstate[sock->fd] = MANAGED; -#ifdef USE_DEVPOLL - INSIST(sock->manager->fdpollinfo[sock->fd].want_read == 0 && - sock->manager->fdpollinfo[sock->fd].want_write == 0); -#endif - UNLOCK(&sock->manager->fdlock[lockid]); - -#ifdef USE_SELECT - LOCK(&sock->manager->lock); - if (sock->manager->maxfd < sock->fd) - sock->manager->maxfd = sock->fd; - UNLOCK(&sock->manager->lock); -#endif - } - - return (result); -} -#endif /* BIND9 */ - -/* - * Create a new 'type' socket managed by 'manager'. Events - * will be posted to 'task' and when dispatched 'action' will be - * called with 'arg' as the arg value. The new socket is returned - * in 'socketp'. - */ -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_fdwatchcreate(isc_socketmgr_t *manager0, int fd, int flags, - isc_sockfdwatch_t callback, void *cbarg, - isc_task_t *task, isc_socket_t **socketp) -{ - isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; - isc__socket_t *sock = NULL; - isc_result_t result; - int lockid; - - REQUIRE(VALID_MANAGER(manager)); - REQUIRE(socketp != NULL && *socketp == NULL); - - result = allocate_socket(manager, isc_sockettype_fdwatch, &sock); - if (result != ISC_R_SUCCESS) - return (result); - - sock->fd = fd; - sock->fdwatcharg = cbarg; - sock->fdwatchcb = callback; - sock->fdwatchflags = flags; - sock->fdwatchtask = task; - sock->statsindex = fdwatchstatsindex; - - sock->common.methods = (isc_socketmethods_t *)&socketmethods; - sock->references = 1; - *socketp = (isc_socket_t *)sock; - - /* - * Note we don't have to lock the socket like we normally would because - * there are no external references to it yet. - */ - - lockid = FDLOCK_ID(sock->fd); - LOCK(&manager->fdlock[lockid]); - manager->fds[sock->fd] = sock; - manager->fdstate[sock->fd] = MANAGED; - UNLOCK(&manager->fdlock[lockid]); - - LOCK(&manager->lock); - ISC_LIST_APPEND(manager->socklist, sock, link); -#ifdef USE_SELECT - if (manager->maxfd < sock->fd) - manager->maxfd = sock->fd; -#endif - UNLOCK(&manager->lock); - - if (flags & ISC_SOCKFDWATCH_READ) - select_poke(sock->manager, sock->fd, SELECT_POKE_READ); - if (flags & ISC_SOCKFDWATCH_WRITE) - select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE); - - socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_CREATED, "fdwatch-created"); - - return (ISC_R_SUCCESS); -} - -/* - * Indicate to the manager that it should watch the socket again. - * This can be used to restart watching if the previous event handler - * didn't indicate there was more data to be processed. Primarily - * it is for writing but could be used for reading if desired - */ - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_fdwatchpoke(isc_socket_t *sock0, int flags) -{ - isc__socket_t *sock = (isc__socket_t *)sock0; - - REQUIRE(VALID_SOCKET(sock)); - - /* - * We check both flags first to allow us to get the lock - * once but only if we need it. - */ - - if ((flags & (ISC_SOCKFDWATCH_READ | ISC_SOCKFDWATCH_WRITE)) != 0) { - LOCK(&sock->lock); - if (((flags & ISC_SOCKFDWATCH_READ) != 0) && - !sock->pending_recv) - select_poke(sock->manager, sock->fd, - SELECT_POKE_READ); - if (((flags & ISC_SOCKFDWATCH_WRITE) != 0) && - !sock->pending_send) - select_poke(sock->manager, sock->fd, - SELECT_POKE_WRITE); - UNLOCK(&sock->lock); - } - - socket_log(sock, NULL, TRACE, isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_POKED, "fdwatch-poked flags: %d", flags); - - return (ISC_R_SUCCESS); -} - -/* - * Attach to a socket. Caller must explicitly detach when it is done. - */ -ISC_SOCKETFUNC_SCOPE void -isc__socket_attach(isc_socket_t *sock0, isc_socket_t **socketp) { - isc__socket_t *sock = (isc__socket_t *)sock0; - - REQUIRE(VALID_SOCKET(sock)); - REQUIRE(socketp != NULL && *socketp == NULL); - - LOCK(&sock->lock); - sock->references++; - UNLOCK(&sock->lock); - - *socketp = (isc_socket_t *)sock; -} - -/* - * Dereference a socket. If this is the last reference to it, clean things - * up by destroying the socket. - */ -ISC_SOCKETFUNC_SCOPE void -isc__socket_detach(isc_socket_t **socketp) { - isc__socket_t *sock; - isc_boolean_t kill_socket = ISC_FALSE; - - REQUIRE(socketp != NULL); - sock = (isc__socket_t *)*socketp; - REQUIRE(VALID_SOCKET(sock)); - - LOCK(&sock->lock); - REQUIRE(sock->references > 0); - sock->references--; - if (sock->references == 0) - kill_socket = ISC_TRUE; - UNLOCK(&sock->lock); - - if (kill_socket) - destroy(&sock); - - *socketp = NULL; -} - -#ifdef BIND9 -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_close(isc_socket_t *sock0) { - isc__socket_t *sock = (isc__socket_t *)sock0; - int fd; - isc__socketmgr_t *manager; - - fflush(stdout); - REQUIRE(VALID_SOCKET(sock)); - - LOCK(&sock->lock); - - REQUIRE(sock->references == 1); - REQUIRE(sock->type != isc_sockettype_fdwatch); - REQUIRE(sock->fd >= 0 && sock->fd < (int)sock->manager->maxsocks); - - INSIST(!sock->connecting); - INSIST(!sock->pending_recv); - INSIST(!sock->pending_send); - INSIST(!sock->pending_accept); - INSIST(ISC_LIST_EMPTY(sock->recv_list)); - INSIST(ISC_LIST_EMPTY(sock->send_list)); - INSIST(ISC_LIST_EMPTY(sock->accept_list)); - INSIST(sock->connect_ev == NULL); - - manager = sock->manager; - fd = sock->fd; - sock->fd = -1; - sock->dupped = 0; - memset(sock->name, 0, sizeof(sock->name)); - sock->tag = NULL; - sock->listener = 0; - sock->connected = 0; - sock->connecting = 0; - sock->bound = 0; - isc_sockaddr_any(&sock->peer_address); - - UNLOCK(&sock->lock); - - closesocket(manager, sock, fd); - - return (ISC_R_SUCCESS); -} -#endif /* BIND9 */ - -/* - * I/O is possible on a given socket. Schedule an event to this task that - * will call an internal function to do the I/O. This will charge the - * task with the I/O operation and let our select loop handler get back - * to doing something real as fast as possible. - * - * The socket and manager must be locked before calling this function. - */ -static void -dispatch_recv(isc__socket_t *sock) { - intev_t *iev; - isc_socketevent_t *ev; - isc_task_t *sender; - - INSIST(!sock->pending_recv); - - if (sock->type != isc_sockettype_fdwatch) { - ev = ISC_LIST_HEAD(sock->recv_list); - if (ev == NULL) - return; - socket_log(sock, NULL, EVENT, NULL, 0, 0, - "dispatch_recv: event %p -> task %p", - ev, ev->ev_sender); - sender = ev->ev_sender; - } else { - sender = sock->fdwatchtask; - } - - sock->pending_recv = 1; - iev = &sock->readable_ev; - - sock->references++; - iev->ev_sender = sock; - if (sock->type == isc_sockettype_fdwatch) - iev->ev_action = internal_fdwatch_read; - else - iev->ev_action = internal_recv; - iev->ev_arg = sock; - - isc_task_send(sender, (isc_event_t **)&iev); -} - -static void -dispatch_send(isc__socket_t *sock) { - intev_t *iev; - isc_socketevent_t *ev; - isc_task_t *sender; - - INSIST(!sock->pending_send); - - if (sock->type != isc_sockettype_fdwatch) { - ev = ISC_LIST_HEAD(sock->send_list); - if (ev == NULL) - return; - socket_log(sock, NULL, EVENT, NULL, 0, 0, - "dispatch_send: event %p -> task %p", - ev, ev->ev_sender); - sender = ev->ev_sender; - } else { - sender = sock->fdwatchtask; - } - - sock->pending_send = 1; - iev = &sock->writable_ev; - - sock->references++; - iev->ev_sender = sock; - if (sock->type == isc_sockettype_fdwatch) - iev->ev_action = internal_fdwatch_write; - else - iev->ev_action = internal_send; - iev->ev_arg = sock; - - isc_task_send(sender, (isc_event_t **)&iev); -} - -/* - * Dispatch an internal accept event. - */ -static void -dispatch_accept(isc__socket_t *sock) { - intev_t *iev; - isc_socket_newconnev_t *ev; - - INSIST(!sock->pending_accept); - - /* - * Are there any done events left, or were they all canceled - * before the manager got the socket lock? - */ - ev = ISC_LIST_HEAD(sock->accept_list); - if (ev == NULL) - return; - - sock->pending_accept = 1; - iev = &sock->readable_ev; - - sock->references++; /* keep socket around for this internal event */ - iev->ev_sender = sock; - iev->ev_action = internal_accept; - iev->ev_arg = sock; - - isc_task_send(ev->ev_sender, (isc_event_t **)&iev); -} - -static void -dispatch_connect(isc__socket_t *sock) { - intev_t *iev; - isc_socket_connev_t *ev; - - iev = &sock->writable_ev; - - ev = sock->connect_ev; - INSIST(ev != NULL); /* XXX */ - - INSIST(sock->connecting); - - sock->references++; /* keep socket around for this internal event */ - iev->ev_sender = sock; - iev->ev_action = internal_connect; - iev->ev_arg = sock; - - isc_task_send(ev->ev_sender, (isc_event_t **)&iev); -} - -/* - * Dequeue an item off the given socket's read queue, set the result code - * in the done event to the one provided, and send it to the task it was - * destined for. - * - * If the event to be sent is on a list, remove it before sending. If - * asked to, send and detach from the socket as well. - * - * Caller must have the socket locked if the event is attached to the socket. - */ -static void -send_recvdone_event(isc__socket_t *sock, isc_socketevent_t **dev) { - isc_task_t *task; - - task = (*dev)->ev_sender; - - (*dev)->ev_sender = sock; - - if (ISC_LINK_LINKED(*dev, ev_link)) - ISC_LIST_DEQUEUE(sock->recv_list, *dev, ev_link); - - if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED) - == ISC_SOCKEVENTATTR_ATTACHED) - isc_task_sendanddetach(&task, (isc_event_t **)dev); - else - isc_task_send(task, (isc_event_t **)dev); -} - -/* - * See comments for send_recvdone_event() above. - * - * Caller must have the socket locked if the event is attached to the socket. - */ -static void -send_senddone_event(isc__socket_t *sock, isc_socketevent_t **dev) { - isc_task_t *task; - - INSIST(dev != NULL && *dev != NULL); - - task = (*dev)->ev_sender; - (*dev)->ev_sender = sock; - - if (ISC_LINK_LINKED(*dev, ev_link)) - ISC_LIST_DEQUEUE(sock->send_list, *dev, ev_link); - - if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED) - == ISC_SOCKEVENTATTR_ATTACHED) - isc_task_sendanddetach(&task, (isc_event_t **)dev); - else - isc_task_send(task, (isc_event_t **)dev); -} - -/* - * Call accept() on a socket, to get the new file descriptor. The listen - * socket is used as a prototype to create a new isc_socket_t. The new - * socket has one outstanding reference. The task receiving the event - * will be detached from just after the event is delivered. - * - * On entry to this function, the event delivered is the internal - * readable event, and the first item on the accept_list should be - * the done event we want to send. If the list is empty, this is a no-op, - * so just unlock and return. - */ -static void -internal_accept(isc_task_t *me, isc_event_t *ev) { - isc__socket_t *sock; - isc__socketmgr_t *manager; - isc_socket_newconnev_t *dev; - isc_task_t *task; - ISC_SOCKADDR_LEN_T addrlen; - int fd; - isc_result_t result = ISC_R_SUCCESS; - char strbuf[ISC_STRERRORSIZE]; - const char *err = "accept"; - - UNUSED(me); - - sock = ev->ev_sender; - INSIST(VALID_SOCKET(sock)); - - LOCK(&sock->lock); - socket_log(sock, NULL, TRACE, - isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK, - "internal_accept called, locked socket"); - - manager = sock->manager; - INSIST(VALID_MANAGER(manager)); - - INSIST(sock->listener); - INSIST(sock->pending_accept == 1); - sock->pending_accept = 0; - - INSIST(sock->references > 0); - sock->references--; /* the internal event is done with this socket */ - if (sock->references == 0) { - UNLOCK(&sock->lock); - destroy(&sock); - return; - } - - /* - * Get the first item off the accept list. - * If it is empty, unlock the socket and return. - */ - dev = ISC_LIST_HEAD(sock->accept_list); - if (dev == NULL) { - UNLOCK(&sock->lock); - return; - } - - /* - * Try to accept the new connection. If the accept fails with - * EAGAIN or EINTR, simply poke the watcher to watch this socket - * again. Also ignore ECONNRESET, which has been reported to - * be spuriously returned on Linux 2.2.19 although it is not - * a documented error for accept(). ECONNABORTED has been - * reported for Solaris 8. The rest are thrown in not because - * we have seen them but because they are ignored by other - * daemons such as BIND 8 and Apache. - */ - - addrlen = sizeof(NEWCONNSOCK(dev)->peer_address.type); - memset(&NEWCONNSOCK(dev)->peer_address.type, 0, addrlen); - fd = accept(sock->fd, &NEWCONNSOCK(dev)->peer_address.type.sa, - (void *)&addrlen); - -#ifdef F_DUPFD - /* - * Leave a space for stdio to work in. - */ - if (fd >= 0 && fd < 20) { - int new, tmp; - new = fcntl(fd, F_DUPFD, 20); - tmp = errno; - (void)close(fd); - errno = tmp; - fd = new; - err = "accept/fcntl"; - } -#endif - - if (fd < 0) { - if (SOFT_ERROR(errno)) - goto soft_error; - switch (errno) { - case ENFILE: - case EMFILE: - isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_TOOMANYFDS, - "%s: too many open file descriptors", - err); - goto soft_error; - - case ENOBUFS: - case ENOMEM: - case ECONNRESET: - case ECONNABORTED: - case EHOSTUNREACH: - case EHOSTDOWN: - case ENETUNREACH: - case ENETDOWN: - case ECONNREFUSED: -#ifdef EPROTO - case EPROTO: -#endif -#ifdef ENONET - case ENONET: -#endif - goto soft_error; - default: - break; - } - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "internal_accept: %s() %s: %s", err, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - fd = -1; - result = ISC_R_UNEXPECTED; - } else { - if (addrlen == 0U) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "internal_accept(): " - "accept() failed to return " - "remote address"); - - (void)close(fd); - goto soft_error; - } else if (NEWCONNSOCK(dev)->peer_address.type.sa.sa_family != - sock->pf) - { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "internal_accept(): " - "accept() returned peer address " - "family %u (expected %u)", - NEWCONNSOCK(dev)->peer_address. - type.sa.sa_family, - sock->pf); - (void)close(fd); - goto soft_error; - } else if (fd >= (int)manager->maxsocks) { - isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_TOOMANYFDS, - "accept: " - "file descriptor exceeds limit (%d/%u)", - fd, manager->maxsocks); - (void)close(fd); - goto soft_error; - } - } - - if (fd != -1) { - NEWCONNSOCK(dev)->peer_address.length = addrlen; - NEWCONNSOCK(dev)->pf = sock->pf; - } - - /* - * Pull off the done event. - */ - ISC_LIST_UNLINK(sock->accept_list, dev, ev_link); - - /* - * Poke watcher if there are more pending accepts. - */ - if (!ISC_LIST_EMPTY(sock->accept_list)) - select_poke(sock->manager, sock->fd, SELECT_POKE_ACCEPT); - - UNLOCK(&sock->lock); - - if (fd != -1) { - result = make_nonblock(fd); - if (result != ISC_R_SUCCESS) { - (void)close(fd); - fd = -1; - } - } - - /* - * -1 means the new socket didn't happen. - */ - if (fd != -1) { - int lockid = FDLOCK_ID(fd); - - NEWCONNSOCK(dev)->fd = fd; - NEWCONNSOCK(dev)->bound = 1; - NEWCONNSOCK(dev)->connected = 1; - - /* - * Use minimum mtu if possible. - */ - use_min_mtu(NEWCONNSOCK(dev)); - - /* - * Save away the remote address - */ - dev->address = NEWCONNSOCK(dev)->peer_address; - - LOCK(&manager->fdlock[lockid]); - manager->fds[fd] = NEWCONNSOCK(dev); - manager->fdstate[fd] = MANAGED; - UNLOCK(&manager->fdlock[lockid]); - - LOCK(&manager->lock); - -#ifdef USE_SELECT - if (manager->maxfd < fd) - manager->maxfd = fd; -#endif - - socket_log(sock, &NEWCONNSOCK(dev)->peer_address, CREATION, - isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN, - "accepted connection, new socket %p", - dev->newsocket); - - ISC_LIST_APPEND(manager->socklist, NEWCONNSOCK(dev), link); - - UNLOCK(&manager->lock); - - inc_stats(manager->stats, sock->statsindex[STATID_ACCEPT]); - } else { - inc_stats(manager->stats, sock->statsindex[STATID_ACCEPTFAIL]); - NEWCONNSOCK(dev)->references--; - free_socket((isc__socket_t **)&dev->newsocket); - } - - /* - * Fill in the done event details and send it off. - */ - dev->result = result; - task = dev->ev_sender; - dev->ev_sender = sock; - - isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev)); - return; - - soft_error: - select_poke(sock->manager, sock->fd, SELECT_POKE_ACCEPT); - UNLOCK(&sock->lock); - - inc_stats(manager->stats, sock->statsindex[STATID_ACCEPTFAIL]); - return; -} - -static void -internal_recv(isc_task_t *me, isc_event_t *ev) { - isc_socketevent_t *dev; - isc__socket_t *sock; - - INSIST(ev->ev_type == ISC_SOCKEVENT_INTR); - - sock = ev->ev_sender; - INSIST(VALID_SOCKET(sock)); - - LOCK(&sock->lock); - socket_log(sock, NULL, IOEVENT, - isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV, - "internal_recv: task %p got event %p", me, ev); - - INSIST(sock->pending_recv == 1); - sock->pending_recv = 0; - - INSIST(sock->references > 0); - sock->references--; /* the internal event is done with this socket */ - if (sock->references == 0) { - UNLOCK(&sock->lock); - destroy(&sock); - return; - } - - /* - * Try to do as much I/O as possible on this socket. There are no - * limits here, currently. - */ - dev = ISC_LIST_HEAD(sock->recv_list); - while (dev != NULL) { - switch (doio_recv(sock, dev)) { - case DOIO_SOFT: - goto poke; - - case DOIO_EOF: - /* - * read of 0 means the remote end was closed. - * Run through the event queue and dispatch all - * the events with an EOF result code. - */ - do { - dev->result = ISC_R_EOF; - send_recvdone_event(sock, &dev); - dev = ISC_LIST_HEAD(sock->recv_list); - } while (dev != NULL); - goto poke; - - case DOIO_SUCCESS: - case DOIO_HARD: - send_recvdone_event(sock, &dev); - break; - } - - dev = ISC_LIST_HEAD(sock->recv_list); - } - - poke: - if (!ISC_LIST_EMPTY(sock->recv_list)) - select_poke(sock->manager, sock->fd, SELECT_POKE_READ); - - UNLOCK(&sock->lock); -} - -static void -internal_send(isc_task_t *me, isc_event_t *ev) { - isc_socketevent_t *dev; - isc__socket_t *sock; - - INSIST(ev->ev_type == ISC_SOCKEVENT_INTW); - - /* - * Find out what socket this is and lock it. - */ - sock = (isc__socket_t *)ev->ev_sender; - INSIST(VALID_SOCKET(sock)); - - LOCK(&sock->lock); - socket_log(sock, NULL, IOEVENT, - isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND, - "internal_send: task %p got event %p", me, ev); - - INSIST(sock->pending_send == 1); - sock->pending_send = 0; - - INSIST(sock->references > 0); - sock->references--; /* the internal event is done with this socket */ - if (sock->references == 0) { - UNLOCK(&sock->lock); - destroy(&sock); - return; - } - - /* - * Try to do as much I/O as possible on this socket. There are no - * limits here, currently. - */ - dev = ISC_LIST_HEAD(sock->send_list); - while (dev != NULL) { - switch (doio_send(sock, dev)) { - case DOIO_SOFT: - goto poke; - - case DOIO_HARD: - case DOIO_SUCCESS: - send_senddone_event(sock, &dev); - break; - } - - dev = ISC_LIST_HEAD(sock->send_list); - } - - poke: - if (!ISC_LIST_EMPTY(sock->send_list)) - select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE); - - UNLOCK(&sock->lock); -} - -static void -internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) { - isc__socket_t *sock; - int more_data; - - INSIST(ev->ev_type == ISC_SOCKEVENT_INTW); - - /* - * Find out what socket this is and lock it. - */ - sock = (isc__socket_t *)ev->ev_sender; - INSIST(VALID_SOCKET(sock)); - - LOCK(&sock->lock); - socket_log(sock, NULL, IOEVENT, - isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND, - "internal_fdwatch_write: task %p got event %p", me, ev); - - INSIST(sock->pending_send == 1); - - UNLOCK(&sock->lock); - more_data = (sock->fdwatchcb)(me, (isc_socket_t *)sock, - sock->fdwatcharg, ISC_SOCKFDWATCH_WRITE); - LOCK(&sock->lock); - - sock->pending_send = 0; - - INSIST(sock->references > 0); - sock->references--; /* the internal event is done with this socket */ - if (sock->references == 0) { - UNLOCK(&sock->lock); - destroy(&sock); - return; - } - - if (more_data) - select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE); - - UNLOCK(&sock->lock); -} - -static void -internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) { - isc__socket_t *sock; - int more_data; - - INSIST(ev->ev_type == ISC_SOCKEVENT_INTR); - - /* - * Find out what socket this is and lock it. - */ - sock = (isc__socket_t *)ev->ev_sender; - INSIST(VALID_SOCKET(sock)); - - LOCK(&sock->lock); - socket_log(sock, NULL, IOEVENT, - isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV, - "internal_fdwatch_read: task %p got event %p", me, ev); - - INSIST(sock->pending_recv == 1); - - UNLOCK(&sock->lock); - more_data = (sock->fdwatchcb)(me, (isc_socket_t *)sock, - sock->fdwatcharg, ISC_SOCKFDWATCH_READ); - LOCK(&sock->lock); - - sock->pending_recv = 0; - - INSIST(sock->references > 0); - sock->references--; /* the internal event is done with this socket */ - if (sock->references == 0) { - UNLOCK(&sock->lock); - destroy(&sock); - return; - } - - if (more_data) - select_poke(sock->manager, sock->fd, SELECT_POKE_READ); - - UNLOCK(&sock->lock); -} - -/* - * Process read/writes on each fd here. Avoid locking - * and unlocking twice if both reads and writes are possible. - */ -static void -process_fd(isc__socketmgr_t *manager, int fd, isc_boolean_t readable, - isc_boolean_t writeable) -{ - isc__socket_t *sock; - isc_boolean_t unlock_sock; - isc_boolean_t unwatch_read = ISC_FALSE, unwatch_write = ISC_FALSE; - int lockid = FDLOCK_ID(fd); - - /* - * If the socket is going to be closed, don't do more I/O. - */ - LOCK(&manager->fdlock[lockid]); - if (manager->fdstate[fd] == CLOSE_PENDING) { - UNLOCK(&manager->fdlock[lockid]); - - (void)unwatch_fd(manager, fd, SELECT_POKE_READ); - (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); - return; - } - - sock = manager->fds[fd]; - unlock_sock = ISC_FALSE; - if (readable) { - if (sock == NULL) { - unwatch_read = ISC_TRUE; - goto check_write; - } - unlock_sock = ISC_TRUE; - LOCK(&sock->lock); - if (!SOCK_DEAD(sock)) { - if (sock->listener) - dispatch_accept(sock); - else - dispatch_recv(sock); - } - unwatch_read = ISC_TRUE; - } -check_write: - if (writeable) { - if (sock == NULL) { - unwatch_write = ISC_TRUE; - goto unlock_fd; - } - if (!unlock_sock) { - unlock_sock = ISC_TRUE; - LOCK(&sock->lock); - } - if (!SOCK_DEAD(sock)) { - if (sock->connecting) - dispatch_connect(sock); - else - dispatch_send(sock); - } - unwatch_write = ISC_TRUE; - } - if (unlock_sock) - UNLOCK(&sock->lock); - - unlock_fd: - UNLOCK(&manager->fdlock[lockid]); - if (unwatch_read) - (void)unwatch_fd(manager, fd, SELECT_POKE_READ); - if (unwatch_write) - (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE); - -} - -#ifdef USE_KQUEUE -static isc_boolean_t -process_fds(isc__socketmgr_t *manager, struct kevent *events, int nevents) { - int i; - isc_boolean_t readable, writable; - isc_boolean_t done = ISC_FALSE; -#ifdef USE_WATCHER_THREAD - isc_boolean_t have_ctlevent = ISC_FALSE; -#endif - - if (nevents == manager->nevents) { - /* - * This is not an error, but something unexpected. If this - * happens, it may indicate the need for increasing - * ISC_SOCKET_MAXEVENTS. - */ - manager_log(manager, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_INFO, - "maximum number of FD events (%d) received", - nevents); - } - - for (i = 0; i < nevents; i++) { - REQUIRE(events[i].ident < manager->maxsocks); -#ifdef USE_WATCHER_THREAD - if (events[i].ident == (uintptr_t)manager->pipe_fds[0]) { - have_ctlevent = ISC_TRUE; - continue; - } -#endif - readable = ISC_TF(events[i].filter == EVFILT_READ); - writable = ISC_TF(events[i].filter == EVFILT_WRITE); - process_fd(manager, events[i].ident, readable, writable); - } - -#ifdef USE_WATCHER_THREAD - if (have_ctlevent) - done = process_ctlfd(manager); -#endif - - return (done); -} -#elif defined(USE_EPOLL) -static isc_boolean_t -process_fds(isc__socketmgr_t *manager, struct epoll_event *events, int nevents) -{ - int i; - isc_boolean_t done = ISC_FALSE; -#ifdef USE_WATCHER_THREAD - isc_boolean_t have_ctlevent = ISC_FALSE; -#endif - - if (nevents == manager->nevents) { - manager_log(manager, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_INFO, - "maximum number of FD events (%d) received", - nevents); - } - - for (i = 0; i < nevents; i++) { - REQUIRE(events[i].data.fd < (int)manager->maxsocks); -#ifdef USE_WATCHER_THREAD - if (events[i].data.fd == manager->pipe_fds[0]) { - have_ctlevent = ISC_TRUE; - continue; - } -#endif - if ((events[i].events & EPOLLERR) != 0 || - (events[i].events & EPOLLHUP) != 0) { - /* - * epoll does not set IN/OUT bits on an erroneous - * condition, so we need to try both anyway. This is a - * bit inefficient, but should be okay for such rare - * events. Note also that the read or write attempt - * won't block because we use non-blocking sockets. - */ - events[i].events |= (EPOLLIN | EPOLLOUT); - } - process_fd(manager, events[i].data.fd, - (events[i].events & EPOLLIN) != 0, - (events[i].events & EPOLLOUT) != 0); - } - -#ifdef USE_WATCHER_THREAD - if (have_ctlevent) - done = process_ctlfd(manager); -#endif - - return (done); -} -#elif defined(USE_DEVPOLL) -static isc_boolean_t -process_fds(isc__socketmgr_t *manager, struct pollfd *events, int nevents) { - int i; - isc_boolean_t done = ISC_FALSE; -#ifdef USE_WATCHER_THREAD - isc_boolean_t have_ctlevent = ISC_FALSE; -#endif - - if (nevents == manager->nevents) { - manager_log(manager, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_INFO, - "maximum number of FD events (%d) received", - nevents); - } - - for (i = 0; i < nevents; i++) { - REQUIRE(events[i].fd < (int)manager->maxsocks); -#ifdef USE_WATCHER_THREAD - if (events[i].fd == manager->pipe_fds[0]) { - have_ctlevent = ISC_TRUE; - continue; - } -#endif - process_fd(manager, events[i].fd, - (events[i].events & POLLIN) != 0, - (events[i].events & POLLOUT) != 0); - } - -#ifdef USE_WATCHER_THREAD - if (have_ctlevent) - done = process_ctlfd(manager); -#endif - - return (done); -} -#elif defined(USE_SELECT) -static void -process_fds(isc__socketmgr_t *manager, int maxfd, fd_set *readfds, - fd_set *writefds) -{ - int i; - - REQUIRE(maxfd <= (int)manager->maxsocks); - - for (i = 0; i < maxfd; i++) { -#ifdef USE_WATCHER_THREAD - if (i == manager->pipe_fds[0] || i == manager->pipe_fds[1]) - continue; -#endif /* USE_WATCHER_THREAD */ - process_fd(manager, i, FD_ISSET(i, readfds), - FD_ISSET(i, writefds)); - } -} -#endif - -#ifdef USE_WATCHER_THREAD -static isc_boolean_t -process_ctlfd(isc__socketmgr_t *manager) { - int msg, fd; - - for (;;) { - select_readmsg(manager, &fd, &msg); - - manager_log(manager, IOEVENT, - isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_WATCHERMSG, - "watcher got message %d " - "for socket %d"), msg, fd); - - /* - * Nothing to read? - */ - if (msg == SELECT_POKE_NOTHING) - break; - - /* - * Handle shutdown message. We really should - * jump out of this loop right away, but - * it doesn't matter if we have to do a little - * more work first. - */ - if (msg == SELECT_POKE_SHUTDOWN) - return (ISC_TRUE); - - /* - * This is a wakeup on a socket. Look - * at the event queue for both read and write, - * and decide if we need to watch on it now - * or not. - */ - wakeup_socket(manager, fd, msg); - } - - return (ISC_FALSE); -} - -/* - * This is the thread that will loop forever, always in a select or poll - * call. - * - * When select returns something to do, track down what thread gets to do - * this I/O and post the event to it. - */ -static isc_threadresult_t -watcher(void *uap) { - isc__socketmgr_t *manager = uap; - isc_boolean_t done; - int cc; -#ifdef USE_KQUEUE - const char *fnname = "kevent()"; -#elif defined (USE_EPOLL) - const char *fnname = "epoll_wait()"; -#elif defined(USE_DEVPOLL) - const char *fnname = "ioctl(DP_POLL)"; - struct dvpoll dvp; -#elif defined (USE_SELECT) - const char *fnname = "select()"; - int maxfd; - int ctlfd; -#endif - char strbuf[ISC_STRERRORSIZE]; -#ifdef ISC_SOCKET_USE_POLLWATCH - pollstate_t pollstate = poll_idle; -#endif - -#if defined (USE_SELECT) - /* - * Get the control fd here. This will never change. - */ - ctlfd = manager->pipe_fds[0]; -#endif - done = ISC_FALSE; - while (!done) { - do { -#ifdef USE_KQUEUE - cc = kevent(manager->kqueue_fd, NULL, 0, - manager->events, manager->nevents, NULL); -#elif defined(USE_EPOLL) - cc = epoll_wait(manager->epoll_fd, manager->events, - manager->nevents, -1); -#elif defined(USE_DEVPOLL) - dvp.dp_fds = manager->events; - dvp.dp_nfds = manager->nevents; -#ifndef ISC_SOCKET_USE_POLLWATCH - dvp.dp_timeout = -1; -#else - if (pollstate == poll_idle) - dvp.dp_timeout = -1; - else - dvp.dp_timeout = ISC_SOCKET_POLLWATCH_TIMEOUT; -#endif /* ISC_SOCKET_USE_POLLWATCH */ - cc = ioctl(manager->devpoll_fd, DP_POLL, &dvp); -#elif defined(USE_SELECT) - LOCK(&manager->lock); - memcpy(manager->read_fds_copy, manager->read_fds, - manager->fd_bufsize); - memcpy(manager->write_fds_copy, manager->write_fds, - manager->fd_bufsize); - maxfd = manager->maxfd + 1; - UNLOCK(&manager->lock); - - cc = select(maxfd, manager->read_fds_copy, - manager->write_fds_copy, NULL, NULL); -#endif /* USE_KQUEUE */ - - if (cc < 0 && !SOFT_ERROR(errno)) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - FATAL_ERROR(__FILE__, __LINE__, - "%s %s: %s", fnname, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), strbuf); - } - -#if defined(USE_DEVPOLL) && defined(ISC_SOCKET_USE_POLLWATCH) - if (cc == 0) { - if (pollstate == poll_active) - pollstate = poll_checking; - else if (pollstate == poll_checking) - pollstate = poll_idle; - } else if (cc > 0) { - if (pollstate == poll_checking) { - /* - * XXX: We'd like to use a more - * verbose log level as it's actually an - * unexpected event, but the kernel bug - * reportedly happens pretty frequently - * (and it can also be a false positive) - * so it would be just too noisy. - */ - manager_log(manager, - ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, - ISC_LOG_DEBUG(1), - "unexpected POLL timeout"); - } - pollstate = poll_active; - } -#endif - } while (cc < 0); - -#if defined(USE_KQUEUE) || defined (USE_EPOLL) || defined (USE_DEVPOLL) - done = process_fds(manager, manager->events, cc); -#elif defined(USE_SELECT) - process_fds(manager, maxfd, manager->read_fds_copy, - manager->write_fds_copy); - - /* - * Process reads on internal, control fd. - */ - if (FD_ISSET(ctlfd, manager->read_fds_copy)) - done = process_ctlfd(manager); -#endif - } - - manager_log(manager, TRACE, "%s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_EXITING, "watcher exiting")); - - return ((isc_threadresult_t)0); -} -#endif /* USE_WATCHER_THREAD */ - -#ifdef BIND9 -ISC_SOCKETFUNC_SCOPE void -isc__socketmgr_setreserved(isc_socketmgr_t *manager0, isc_uint32_t reserved) { - isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; - - REQUIRE(VALID_MANAGER(manager)); - - manager->reserved = reserved; -} - -ISC_SOCKETFUNC_SCOPE void -isc___socketmgr_maxudp(isc_socketmgr_t *manager0, int maxudp) { - isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; - - REQUIRE(VALID_MANAGER(manager)); - - manager->maxudp = maxudp; -} -#endif /* BIND9 */ - -/* - * Create a new socket manager. - */ - -static isc_result_t -setup_watcher(isc_mem_t *mctx, isc__socketmgr_t *manager) { - isc_result_t result; -#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) - char strbuf[ISC_STRERRORSIZE]; -#endif - -#ifdef USE_KQUEUE - manager->nevents = ISC_SOCKET_MAXEVENTS; - manager->events = isc_mem_get(mctx, sizeof(struct kevent) * - manager->nevents); - if (manager->events == NULL) - return (ISC_R_NOMEMORY); - manager->kqueue_fd = kqueue(); - if (manager->kqueue_fd == -1) { - result = isc__errno2result(errno); - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "kqueue %s: %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed"), - strbuf); - isc_mem_put(mctx, manager->events, - sizeof(struct kevent) * manager->nevents); - return (result); - } - -#ifdef USE_WATCHER_THREAD - result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); - if (result != ISC_R_SUCCESS) { - close(manager->kqueue_fd); - isc_mem_put(mctx, manager->events, - sizeof(struct kevent) * manager->nevents); - return (result); - } -#endif /* USE_WATCHER_THREAD */ -#elif defined(USE_EPOLL) - manager->nevents = ISC_SOCKET_MAXEVENTS; - manager->events = isc_mem_get(mctx, sizeof(struct epoll_event) * - manager->nevents); - if (manager->events == NULL) - return (ISC_R_NOMEMORY); - manager->epoll_fd = epoll_create(manager->nevents); - if (manager->epoll_fd == -1) { - result = isc__errno2result(errno); - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "epoll_create %s: %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed"), - strbuf); - isc_mem_put(mctx, manager->events, - sizeof(struct epoll_event) * manager->nevents); - return (result); - } -#ifdef USE_WATCHER_THREAD - result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); - if (result != ISC_R_SUCCESS) { - close(manager->epoll_fd); - isc_mem_put(mctx, manager->events, - sizeof(struct epoll_event) * manager->nevents); - return (result); - } -#endif /* USE_WATCHER_THREAD */ -#elif defined(USE_DEVPOLL) - /* - * XXXJT: /dev/poll seems to reject large numbers of events, - * so we should be careful about redefining ISC_SOCKET_MAXEVENTS. - */ - manager->nevents = ISC_SOCKET_MAXEVENTS; - manager->events = isc_mem_get(mctx, sizeof(struct pollfd) * - manager->nevents); - if (manager->events == NULL) - return (ISC_R_NOMEMORY); - /* - * Note: fdpollinfo should be able to support all possible FDs, so - * it must have maxsocks entries (not nevents). - */ - manager->fdpollinfo = isc_mem_get(mctx, sizeof(pollinfo_t) * - manager->maxsocks); - if (manager->fdpollinfo == NULL) { - isc_mem_put(mctx, manager->events, - sizeof(struct pollfd) * manager->nevents); - return (ISC_R_NOMEMORY); - } - memset(manager->fdpollinfo, 0, sizeof(pollinfo_t) * manager->maxsocks); - manager->devpoll_fd = open("/dev/poll", O_RDWR); - if (manager->devpoll_fd == -1) { - result = isc__errno2result(errno); - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "open(/dev/poll) %s: %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed"), - strbuf); - isc_mem_put(mctx, manager->events, - sizeof(struct pollfd) * manager->nevents); - isc_mem_put(mctx, manager->fdpollinfo, - sizeof(pollinfo_t) * manager->maxsocks); - return (result); - } -#ifdef USE_WATCHER_THREAD - result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); - if (result != ISC_R_SUCCESS) { - close(manager->devpoll_fd); - isc_mem_put(mctx, manager->events, - sizeof(struct pollfd) * manager->nevents); - isc_mem_put(mctx, manager->fdpollinfo, - sizeof(pollinfo_t) * manager->maxsocks); - return (result); - } -#endif /* USE_WATCHER_THREAD */ -#elif defined(USE_SELECT) - UNUSED(result); - -#if ISC_SOCKET_MAXSOCKETS > FD_SETSIZE - /* - * Note: this code should also cover the case of MAXSOCKETS <= - * FD_SETSIZE, but we separate the cases to avoid possible portability - * issues regarding howmany() and the actual representation of fd_set. - */ - manager->fd_bufsize = howmany(manager->maxsocks, NFDBITS) * - sizeof(fd_mask); -#else - manager->fd_bufsize = sizeof(fd_set); -#endif - - manager->read_fds = NULL; - manager->read_fds_copy = NULL; - manager->write_fds = NULL; - manager->write_fds_copy = NULL; - - manager->read_fds = isc_mem_get(mctx, manager->fd_bufsize); - if (manager->read_fds != NULL) - manager->read_fds_copy = isc_mem_get(mctx, manager->fd_bufsize); - if (manager->read_fds_copy != NULL) - manager->write_fds = isc_mem_get(mctx, manager->fd_bufsize); - if (manager->write_fds != NULL) { - manager->write_fds_copy = isc_mem_get(mctx, - manager->fd_bufsize); - } - if (manager->write_fds_copy == NULL) { - if (manager->write_fds != NULL) { - isc_mem_put(mctx, manager->write_fds, - manager->fd_bufsize); - } - if (manager->read_fds_copy != NULL) { - isc_mem_put(mctx, manager->read_fds_copy, - manager->fd_bufsize); - } - if (manager->read_fds != NULL) { - isc_mem_put(mctx, manager->read_fds, - manager->fd_bufsize); - } - return (ISC_R_NOMEMORY); - } - memset(manager->read_fds, 0, manager->fd_bufsize); - memset(manager->write_fds, 0, manager->fd_bufsize); - -#ifdef USE_WATCHER_THREAD - (void)watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); - manager->maxfd = manager->pipe_fds[0]; -#else /* USE_WATCHER_THREAD */ - manager->maxfd = 0; -#endif /* USE_WATCHER_THREAD */ -#endif /* USE_KQUEUE */ - - return (ISC_R_SUCCESS); -} - -static void -cleanup_watcher(isc_mem_t *mctx, isc__socketmgr_t *manager) { -#ifdef USE_WATCHER_THREAD - isc_result_t result; - - result = unwatch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ); - if (result != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "epoll_ctl(DEL) %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed")); - } -#endif /* USE_WATCHER_THREAD */ - -#ifdef USE_KQUEUE - close(manager->kqueue_fd); - isc_mem_put(mctx, manager->events, - sizeof(struct kevent) * manager->nevents); -#elif defined(USE_EPOLL) - close(manager->epoll_fd); - isc_mem_put(mctx, manager->events, - sizeof(struct epoll_event) * manager->nevents); -#elif defined(USE_DEVPOLL) - close(manager->devpoll_fd); - isc_mem_put(mctx, manager->events, - sizeof(struct pollfd) * manager->nevents); - isc_mem_put(mctx, manager->fdpollinfo, - sizeof(pollinfo_t) * manager->maxsocks); -#elif defined(USE_SELECT) - if (manager->read_fds != NULL) - isc_mem_put(mctx, manager->read_fds, manager->fd_bufsize); - if (manager->read_fds_copy != NULL) - isc_mem_put(mctx, manager->read_fds_copy, manager->fd_bufsize); - if (manager->write_fds != NULL) - isc_mem_put(mctx, manager->write_fds, manager->fd_bufsize); - if (manager->write_fds_copy != NULL) - isc_mem_put(mctx, manager->write_fds_copy, manager->fd_bufsize); -#endif /* USE_KQUEUE */ -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) { - return (isc__socketmgr_create2(mctx, managerp, 0)); -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp, - unsigned int maxsocks) -{ - int i; - isc__socketmgr_t *manager; -#ifdef USE_WATCHER_THREAD - char strbuf[ISC_STRERRORSIZE]; -#endif - isc_result_t result; - - REQUIRE(managerp != NULL && *managerp == NULL); - -#ifdef USE_SHARED_MANAGER - if (socketmgr != NULL) { - /* Don't allow maxsocks to be updated */ - if (maxsocks > 0 && socketmgr->maxsocks != maxsocks) - return (ISC_R_EXISTS); - - socketmgr->refs++; - *managerp = (isc_socketmgr_t *)socketmgr; - return (ISC_R_SUCCESS); - } -#endif /* USE_SHARED_MANAGER */ - - if (maxsocks == 0) - maxsocks = ISC_SOCKET_MAXSOCKETS; - - manager = isc_mem_get(mctx, sizeof(*manager)); - if (manager == NULL) - return (ISC_R_NOMEMORY); - - /* zero-clear so that necessary cleanup on failure will be easy */ - memset(manager, 0, sizeof(*manager)); - manager->maxsocks = maxsocks; - manager->reserved = 0; - manager->maxudp = 0; - manager->fds = isc_mem_get(mctx, - manager->maxsocks * sizeof(isc__socket_t *)); - if (manager->fds == NULL) { - result = ISC_R_NOMEMORY; - goto free_manager; - } - manager->fdstate = isc_mem_get(mctx, manager->maxsocks * sizeof(int)); - if (manager->fdstate == NULL) { - result = ISC_R_NOMEMORY; - goto free_manager; - } - manager->stats = NULL; - - manager->common.methods = &socketmgrmethods; - manager->common.magic = ISCAPI_SOCKETMGR_MAGIC; - manager->common.impmagic = SOCKET_MANAGER_MAGIC; - manager->mctx = NULL; - memset(manager->fds, 0, manager->maxsocks * sizeof(isc_socket_t *)); - ISC_LIST_INIT(manager->socklist); - result = isc_mutex_init(&manager->lock); - if (result != ISC_R_SUCCESS) - goto free_manager; - manager->fdlock = isc_mem_get(mctx, FDLOCK_COUNT * sizeof(isc_mutex_t)); - if (manager->fdlock == NULL) { - result = ISC_R_NOMEMORY; - goto cleanup_lock; - } - for (i = 0; i < FDLOCK_COUNT; i++) { - result = isc_mutex_init(&manager->fdlock[i]); - if (result != ISC_R_SUCCESS) { - while (--i >= 0) - DESTROYLOCK(&manager->fdlock[i]); - isc_mem_put(mctx, manager->fdlock, - FDLOCK_COUNT * sizeof(isc_mutex_t)); - manager->fdlock = NULL; - goto cleanup_lock; - } - } - -#ifdef USE_WATCHER_THREAD - if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_condition_init() %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed")); - result = ISC_R_UNEXPECTED; - goto cleanup_lock; - } - - /* - * Create the special fds that will be used to wake up the - * select/poll loop when something internal needs to be done. - */ - if (pipe(manager->pipe_fds) != 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "pipe() %s: %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed"), - strbuf); - result = ISC_R_UNEXPECTED; - goto cleanup_condition; - } - - RUNTIME_CHECK(make_nonblock(manager->pipe_fds[0]) == ISC_R_SUCCESS); -#if 0 - RUNTIME_CHECK(make_nonblock(manager->pipe_fds[1]) == ISC_R_SUCCESS); -#endif -#endif /* USE_WATCHER_THREAD */ - -#ifdef USE_SHARED_MANAGER - manager->refs = 1; -#endif /* USE_SHARED_MANAGER */ - - /* - * Set up initial state for the select loop - */ - result = setup_watcher(mctx, manager); - if (result != ISC_R_SUCCESS) - goto cleanup; - memset(manager->fdstate, 0, manager->maxsocks * sizeof(int)); -#ifdef USE_WATCHER_THREAD - /* - * Start up the select/poll thread. - */ - if (isc_thread_create(watcher, manager, &manager->watcher) != - ISC_R_SUCCESS) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_thread_create() %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed")); - cleanup_watcher(mctx, manager); - result = ISC_R_UNEXPECTED; - goto cleanup; - } -#endif /* USE_WATCHER_THREAD */ - isc_mem_attach(mctx, &manager->mctx); - -#ifdef USE_SHARED_MANAGER - socketmgr = manager; -#endif /* USE_SHARED_MANAGER */ - *managerp = (isc_socketmgr_t *)manager; - - return (ISC_R_SUCCESS); - -cleanup: -#ifdef USE_WATCHER_THREAD - (void)close(manager->pipe_fds[0]); - (void)close(manager->pipe_fds[1]); -#endif /* USE_WATCHER_THREAD */ - -#ifdef USE_WATCHER_THREAD -cleanup_condition: - (void)isc_condition_destroy(&manager->shutdown_ok); -#endif /* USE_WATCHER_THREAD */ - - -cleanup_lock: - if (manager->fdlock != NULL) { - for (i = 0; i < FDLOCK_COUNT; i++) - DESTROYLOCK(&manager->fdlock[i]); - } - DESTROYLOCK(&manager->lock); - -free_manager: - if (manager->fdlock != NULL) { - isc_mem_put(mctx, manager->fdlock, - FDLOCK_COUNT * sizeof(isc_mutex_t)); - } - if (manager->fdstate != NULL) { - isc_mem_put(mctx, manager->fdstate, - manager->maxsocks * sizeof(int)); - } - if (manager->fds != NULL) { - isc_mem_put(mctx, manager->fds, - manager->maxsocks * sizeof(isc_socket_t *)); - } - isc_mem_put(mctx, manager, sizeof(*manager)); - - return (result); -} - -#ifdef BIND9 -isc_result_t -isc__socketmgr_getmaxsockets(isc_socketmgr_t *manager0, unsigned int *nsockp) { - isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; - REQUIRE(VALID_MANAGER(manager)); - REQUIRE(nsockp != NULL); - - *nsockp = manager->maxsocks; - - return (ISC_R_SUCCESS); -} - -void -isc__socketmgr_setstats(isc_socketmgr_t *manager0, isc_stats_t *stats) { - isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; - - REQUIRE(VALID_MANAGER(manager)); - REQUIRE(ISC_LIST_EMPTY(manager->socklist)); - REQUIRE(manager->stats == NULL); - REQUIRE(isc_stats_ncounters(stats) == isc_sockstatscounter_max); - - isc_stats_attach(stats, &manager->stats); -} -#endif - -ISC_SOCKETFUNC_SCOPE void -isc__socketmgr_destroy(isc_socketmgr_t **managerp) { - isc__socketmgr_t *manager; - int i; - isc_mem_t *mctx; - - /* - * Destroy a socket manager. - */ - - REQUIRE(managerp != NULL); - manager = (isc__socketmgr_t *)*managerp; - REQUIRE(VALID_MANAGER(manager)); - -#ifdef USE_SHARED_MANAGER - manager->refs--; - if (manager->refs > 0) { - *managerp = NULL; - return; - } - socketmgr = NULL; -#endif /* USE_SHARED_MANAGER */ - - LOCK(&manager->lock); - - /* - * Wait for all sockets to be destroyed. - */ - while (!ISC_LIST_EMPTY(manager->socklist)) { -#ifdef USE_WATCHER_THREAD - manager_log(manager, CREATION, "%s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_SOCKETSREMAIN, - "sockets exist")); - WAIT(&manager->shutdown_ok, &manager->lock); -#else /* USE_WATCHER_THREAD */ - UNLOCK(&manager->lock); - isc__taskmgr_dispatch(NULL); - LOCK(&manager->lock); -#endif /* USE_WATCHER_THREAD */ - } - - UNLOCK(&manager->lock); - - /* - * Here, poke our select/poll thread. Do this by closing the write - * half of the pipe, which will send EOF to the read half. - * This is currently a no-op in the non-threaded case. - */ - select_poke(manager, 0, SELECT_POKE_SHUTDOWN); - -#ifdef USE_WATCHER_THREAD - /* - * Wait for thread to exit. - */ - if (isc_thread_join(manager->watcher, NULL) != ISC_R_SUCCESS) - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_thread_join() %s", - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed")); -#endif /* USE_WATCHER_THREAD */ - - /* - * Clean up. - */ - cleanup_watcher(manager->mctx, manager); - -#ifdef USE_WATCHER_THREAD - (void)close(manager->pipe_fds[0]); - (void)close(manager->pipe_fds[1]); - (void)isc_condition_destroy(&manager->shutdown_ok); -#endif /* USE_WATCHER_THREAD */ - - for (i = 0; i < (int)manager->maxsocks; i++) - if (manager->fdstate[i] == CLOSE_PENDING) /* no need to lock */ - (void)close(i); - - isc_mem_put(manager->mctx, manager->fds, - manager->maxsocks * sizeof(isc__socket_t *)); - isc_mem_put(manager->mctx, manager->fdstate, - manager->maxsocks * sizeof(int)); - - if (manager->stats != NULL) - isc_stats_detach(&manager->stats); - - if (manager->fdlock != NULL) { - for (i = 0; i < FDLOCK_COUNT; i++) - DESTROYLOCK(&manager->fdlock[i]); - isc_mem_put(manager->mctx, manager->fdlock, - FDLOCK_COUNT * sizeof(isc_mutex_t)); - } - DESTROYLOCK(&manager->lock); - manager->common.magic = 0; - manager->common.impmagic = 0; - mctx= manager->mctx; - isc_mem_put(mctx, manager, sizeof(*manager)); - - isc_mem_detach(&mctx); - - *managerp = NULL; - -#ifdef USE_SHARED_MANAGER - socketmgr = NULL; -#endif -} - -static isc_result_t -socket_recv(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, - unsigned int flags) -{ - int io_state; - isc_boolean_t have_lock = ISC_FALSE; - isc_task_t *ntask = NULL; - isc_result_t result = ISC_R_SUCCESS; - - dev->ev_sender = task; - - if (sock->type == isc_sockettype_udp) { - io_state = doio_recv(sock, dev); - } else { - LOCK(&sock->lock); - have_lock = ISC_TRUE; - - if (ISC_LIST_EMPTY(sock->recv_list)) - io_state = doio_recv(sock, dev); - else - io_state = DOIO_SOFT; - } - - switch (io_state) { - case DOIO_SOFT: - /* - * We couldn't read all or part of the request right now, so - * queue it. - * - * Attach to socket and to task - */ - isc_task_attach(task, &ntask); - dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED; - - if (!have_lock) { - LOCK(&sock->lock); - have_lock = ISC_TRUE; - } - - /* - * Enqueue the request. If the socket was previously not being - * watched, poke the watcher to start paying attention to it. - */ - if (ISC_LIST_EMPTY(sock->recv_list) && !sock->pending_recv) - select_poke(sock->manager, sock->fd, SELECT_POKE_READ); - ISC_LIST_ENQUEUE(sock->recv_list, dev, ev_link); - - socket_log(sock, NULL, EVENT, NULL, 0, 0, - "socket_recv: event %p -> task %p", - dev, ntask); - - if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0) - result = ISC_R_INPROGRESS; - break; - - case DOIO_EOF: - dev->result = ISC_R_EOF; - /* fallthrough */ - - case DOIO_HARD: - case DOIO_SUCCESS: - if ((flags & ISC_SOCKFLAG_IMMEDIATE) == 0) - send_recvdone_event(sock, &dev); - break; - } - - if (have_lock) - UNLOCK(&sock->lock); - - return (result); -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_recvv(isc_socket_t *sock0, isc_bufferlist_t *buflist, - unsigned int minimum, isc_task_t *task, - isc_taskaction_t action, const void *arg) -{ - isc__socket_t *sock = (isc__socket_t *)sock0; - isc_socketevent_t *dev; - isc__socketmgr_t *manager; - unsigned int iocount; - isc_buffer_t *buffer; - - REQUIRE(VALID_SOCKET(sock)); - REQUIRE(buflist != NULL); - REQUIRE(!ISC_LIST_EMPTY(*buflist)); - REQUIRE(task != NULL); - REQUIRE(action != NULL); - - manager = sock->manager; - REQUIRE(VALID_MANAGER(manager)); - - iocount = isc_bufferlist_availablecount(buflist); - REQUIRE(iocount > 0); - - INSIST(sock->bound); - - dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg); - if (dev == NULL) - return (ISC_R_NOMEMORY); - - /* - * UDP sockets are always partial read - */ - if (sock->type == isc_sockettype_udp) - dev->minimum = 1; - else { - if (minimum == 0) - dev->minimum = iocount; - else - dev->minimum = minimum; - } - - /* - * Move each buffer from the passed in list to our internal one. - */ - buffer = ISC_LIST_HEAD(*buflist); - while (buffer != NULL) { - ISC_LIST_DEQUEUE(*buflist, buffer, link); - ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link); - buffer = ISC_LIST_HEAD(*buflist); - } - - return (socket_recv(sock, dev, task, 0)); -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_recv(isc_socket_t *sock0, isc_region_t *region, - unsigned int minimum, isc_task_t *task, - isc_taskaction_t action, const void *arg) -{ - isc__socket_t *sock = (isc__socket_t *)sock0; - isc_socketevent_t *dev; - isc__socketmgr_t *manager; - - REQUIRE(VALID_SOCKET(sock)); - REQUIRE(action != NULL); - - manager = sock->manager; - REQUIRE(VALID_MANAGER(manager)); - - INSIST(sock->bound); - - dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg); - if (dev == NULL) - return (ISC_R_NOMEMORY); - - return (isc__socket_recv2(sock0, region, minimum, task, dev, 0)); -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_recv2(isc_socket_t *sock0, isc_region_t *region, - unsigned int minimum, isc_task_t *task, - isc_socketevent_t *event, unsigned int flags) -{ - isc__socket_t *sock = (isc__socket_t *)sock0; - - event->ev_sender = sock; - event->result = ISC_R_UNSET; - ISC_LIST_INIT(event->bufferlist); - event->region = *region; - event->n = 0; - event->offset = 0; - event->attributes = 0; - - /* - * UDP sockets are always partial read. - */ - if (sock->type == isc_sockettype_udp) - event->minimum = 1; - else { - if (minimum == 0) - event->minimum = region->length; - else - event->minimum = minimum; - } - - return (socket_recv(sock, event, task, flags)); -} - -static isc_result_t -socket_send(isc__socket_t *sock, isc_socketevent_t *dev, isc_task_t *task, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, - unsigned int flags) -{ - int io_state; - isc_boolean_t have_lock = ISC_FALSE; - isc_task_t *ntask = NULL; - isc_result_t result = ISC_R_SUCCESS; - - dev->ev_sender = task; - - set_dev_address(address, sock, dev); - if (pktinfo != NULL) { - dev->attributes |= ISC_SOCKEVENTATTR_PKTINFO; - dev->pktinfo = *pktinfo; - - if (!isc_sockaddr_issitelocal(&dev->address) && - !isc_sockaddr_islinklocal(&dev->address)) { - socket_log(sock, NULL, TRACE, isc_msgcat, - ISC_MSGSET_SOCKET, ISC_MSG_PKTINFOPROVIDED, - "pktinfo structure provided, ifindex %u " - "(set to 0)", pktinfo->ipi6_ifindex); - - /* - * Set the pktinfo index to 0 here, to let the - * kernel decide what interface it should send on. - */ - dev->pktinfo.ipi6_ifindex = 0; - } - } - - if (sock->type == isc_sockettype_udp) - io_state = doio_send(sock, dev); - else { - LOCK(&sock->lock); - have_lock = ISC_TRUE; - - if (ISC_LIST_EMPTY(sock->send_list)) - io_state = doio_send(sock, dev); - else - io_state = DOIO_SOFT; - } - - switch (io_state) { - case DOIO_SOFT: - /* - * We couldn't send all or part of the request right now, so - * queue it unless ISC_SOCKFLAG_NORETRY is set. - */ - if ((flags & ISC_SOCKFLAG_NORETRY) == 0) { - isc_task_attach(task, &ntask); - dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED; - - if (!have_lock) { - LOCK(&sock->lock); - have_lock = ISC_TRUE; - } - - /* - * Enqueue the request. If the socket was previously - * not being watched, poke the watcher to start - * paying attention to it. - */ - if (ISC_LIST_EMPTY(sock->send_list) && - !sock->pending_send) - select_poke(sock->manager, sock->fd, - SELECT_POKE_WRITE); - ISC_LIST_ENQUEUE(sock->send_list, dev, ev_link); - - socket_log(sock, NULL, EVENT, NULL, 0, 0, - "socket_send: event %p -> task %p", - dev, ntask); - - if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0) - result = ISC_R_INPROGRESS; - break; - } - - case DOIO_HARD: - case DOIO_SUCCESS: - if ((flags & ISC_SOCKFLAG_IMMEDIATE) == 0) - send_senddone_event(sock, &dev); - break; - } - - if (have_lock) - UNLOCK(&sock->lock); - - return (result); -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_send(isc_socket_t *sock, isc_region_t *region, - isc_task_t *task, isc_taskaction_t action, const void *arg) -{ - /* - * REQUIRE() checking is performed in isc_socket_sendto(). - */ - return (isc__socket_sendto(sock, region, task, action, arg, NULL, - NULL)); -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_sendto(isc_socket_t *sock0, isc_region_t *region, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) -{ - isc__socket_t *sock = (isc__socket_t *)sock0; - isc_socketevent_t *dev; - isc__socketmgr_t *manager; - - REQUIRE(VALID_SOCKET(sock)); - REQUIRE(region != NULL); - REQUIRE(task != NULL); - REQUIRE(action != NULL); - - manager = sock->manager; - REQUIRE(VALID_MANAGER(manager)); - - INSIST(sock->bound); - - dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg); - if (dev == NULL) - return (ISC_R_NOMEMORY); - - dev->region = *region; - - return (socket_send(sock, dev, task, address, pktinfo, 0)); -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_sendv(isc_socket_t *sock, isc_bufferlist_t *buflist, - isc_task_t *task, isc_taskaction_t action, const void *arg) -{ - return (isc__socket_sendtov(sock, buflist, task, action, arg, NULL, - NULL)); -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_sendtov(isc_socket_t *sock0, isc_bufferlist_t *buflist, - isc_task_t *task, isc_taskaction_t action, const void *arg, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo) -{ - isc__socket_t *sock = (isc__socket_t *)sock0; - isc_socketevent_t *dev; - isc__socketmgr_t *manager; - unsigned int iocount; - isc_buffer_t *buffer; - - REQUIRE(VALID_SOCKET(sock)); - REQUIRE(buflist != NULL); - REQUIRE(!ISC_LIST_EMPTY(*buflist)); - REQUIRE(task != NULL); - REQUIRE(action != NULL); - - manager = sock->manager; - REQUIRE(VALID_MANAGER(manager)); - - iocount = isc_bufferlist_usedcount(buflist); - REQUIRE(iocount > 0); - - dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg); - if (dev == NULL) - return (ISC_R_NOMEMORY); - - /* - * Move each buffer from the passed in list to our internal one. - */ - buffer = ISC_LIST_HEAD(*buflist); - while (buffer != NULL) { - ISC_LIST_DEQUEUE(*buflist, buffer, link); - ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link); - buffer = ISC_LIST_HEAD(*buflist); - } - - return (socket_send(sock, dev, task, address, pktinfo, 0)); -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_sendto2(isc_socket_t *sock0, isc_region_t *region, - isc_task_t *task, - isc_sockaddr_t *address, struct in6_pktinfo *pktinfo, - isc_socketevent_t *event, unsigned int flags) -{ - isc__socket_t *sock = (isc__socket_t *)sock0; - - REQUIRE(VALID_SOCKET(sock)); - REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0); - if ((flags & ISC_SOCKFLAG_NORETRY) != 0) - REQUIRE(sock->type == isc_sockettype_udp); - event->ev_sender = sock; - event->result = ISC_R_UNSET; - ISC_LIST_INIT(event->bufferlist); - event->region = *region; - event->n = 0; - event->offset = 0; - event->attributes = 0; - - return (socket_send(sock, event, task, address, pktinfo, flags)); -} - -ISC_SOCKETFUNC_SCOPE void -isc__socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) { -#ifdef ISC_PLATFORM_HAVESYSUNH - int s; - struct stat sb; - char strbuf[ISC_STRERRORSIZE]; - - if (sockaddr->type.sa.sa_family != AF_UNIX) - return; - -#ifndef S_ISSOCK -#if defined(S_IFMT) && defined(S_IFSOCK) -#define S_ISSOCK(mode) ((mode & S_IFMT)==S_IFSOCK) -#elif defined(_S_IFMT) && defined(S_IFSOCK) -#define S_ISSOCK(mode) ((mode & _S_IFMT)==S_IFSOCK) -#endif -#endif - -#ifndef S_ISFIFO -#if defined(S_IFMT) && defined(S_IFIFO) -#define S_ISFIFO(mode) ((mode & S_IFMT)==S_IFIFO) -#elif defined(_S_IFMT) && defined(S_IFIFO) -#define S_ISFIFO(mode) ((mode & _S_IFMT)==S_IFIFO) -#endif -#endif - -#if !defined(S_ISFIFO) && !defined(S_ISSOCK) -#error You need to define S_ISFIFO and S_ISSOCK as appropriate for your platform. See <sys/stat.h>. -#endif - -#ifndef S_ISFIFO -#define S_ISFIFO(mode) 0 -#endif - -#ifndef S_ISSOCK -#define S_ISSOCK(mode) 0 -#endif - - if (active) { - if (stat(sockaddr->type.sunix.sun_path, &sb) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - "isc_socket_cleanunix: stat(%s): %s", - sockaddr->type.sunix.sun_path, strbuf); - return; - } - if (!(S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) { - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - "isc_socket_cleanunix: %s: not a socket", - sockaddr->type.sunix.sun_path); - return; - } - if (unlink(sockaddr->type.sunix.sun_path) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - "isc_socket_cleanunix: unlink(%s): %s", - sockaddr->type.sunix.sun_path, strbuf); - } - return; - } - - s = socket(AF_UNIX, SOCK_STREAM, 0); - if (s < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING, - "isc_socket_cleanunix: socket(%s): %s", - sockaddr->type.sunix.sun_path, strbuf); - return; - } - - if (stat(sockaddr->type.sunix.sun_path, &sb) < 0) { - switch (errno) { - case ENOENT: /* We exited cleanly last time */ - break; - default: - isc__strerror(errno, strbuf, sizeof(strbuf)); - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING, - "isc_socket_cleanunix: stat(%s): %s", - sockaddr->type.sunix.sun_path, strbuf); - break; - } - goto cleanup; - } - - if (!(S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) { - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING, - "isc_socket_cleanunix: %s: not a socket", - sockaddr->type.sunix.sun_path); - goto cleanup; - } - - if (connect(s, (struct sockaddr *)&sockaddr->type.sunix, - sizeof(sockaddr->type.sunix)) < 0) { - switch (errno) { - case ECONNREFUSED: - case ECONNRESET: - if (unlink(sockaddr->type.sunix.sun_path) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, - ISC_LOG_WARNING, - "isc_socket_cleanunix: " - "unlink(%s): %s", - sockaddr->type.sunix.sun_path, - strbuf); - } - break; - default: - isc__strerror(errno, strbuf, sizeof(strbuf)); - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING, - "isc_socket_cleanunix: connect(%s): %s", - sockaddr->type.sunix.sun_path, strbuf); - break; - } - } - cleanup: - close(s); -#else - UNUSED(sockaddr); - UNUSED(active); -#endif -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm, - isc_uint32_t owner, isc_uint32_t group) -{ -#ifdef ISC_PLATFORM_HAVESYSUNH - isc_result_t result = ISC_R_SUCCESS; - char strbuf[ISC_STRERRORSIZE]; - char path[sizeof(sockaddr->type.sunix.sun_path)]; -#ifdef NEED_SECURE_DIRECTORY - char *slash; -#endif - - REQUIRE(sockaddr->type.sa.sa_family == AF_UNIX); - INSIST(strlen(sockaddr->type.sunix.sun_path) < sizeof(path)); - strcpy(path, sockaddr->type.sunix.sun_path); - -#ifdef NEED_SECURE_DIRECTORY - slash = strrchr(path, '/'); - if (slash != NULL) { - if (slash != path) - *slash = '\0'; - else - strcpy(path, "/"); - } else - strcpy(path, "."); -#endif - - if (chmod(path, perm) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - "isc_socket_permunix: chmod(%s, %d): %s", - path, perm, strbuf); - result = ISC_R_FAILURE; - } - if (chown(path, owner, group) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - "isc_socket_permunix: chown(%s, %d, %d): %s", - path, owner, group, - strbuf); - result = ISC_R_FAILURE; - } - return (result); -#else - UNUSED(sockaddr); - UNUSED(perm); - UNUSED(owner); - UNUSED(group); - return (ISC_R_NOTIMPLEMENTED); -#endif -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_bind(isc_socket_t *sock0, isc_sockaddr_t *sockaddr, - unsigned int options) { - isc__socket_t *sock = (isc__socket_t *)sock0; - char strbuf[ISC_STRERRORSIZE]; - int on = 1; - - REQUIRE(VALID_SOCKET(sock)); - - LOCK(&sock->lock); - - INSIST(!sock->bound); - INSIST(!sock->dupped); - - if (sock->pf != sockaddr->type.sa.sa_family) { - UNLOCK(&sock->lock); - return (ISC_R_FAMILYMISMATCH); - } - - /* - * Only set SO_REUSEADDR when we want a specific port. - */ -#ifdef AF_UNIX - if (sock->pf == AF_UNIX) - goto bind_socket; -#endif - if ((options & ISC_SOCKET_REUSEADDRESS) != 0 && - isc_sockaddr_getport(sockaddr) != (in_port_t)0 && - setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, - sizeof(on)) < 0) { - UNEXPECTED_ERROR(__FILE__, __LINE__, - "setsockopt(%d) %s", sock->fd, - isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, "failed")); - /* Press on... */ - } -#ifdef AF_UNIX - bind_socket: -#endif - if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) { - inc_stats(sock->manager->stats, - sock->statsindex[STATID_BINDFAIL]); - - UNLOCK(&sock->lock); - switch (errno) { - case EACCES: - return (ISC_R_NOPERM); - case EADDRNOTAVAIL: - return (ISC_R_ADDRNOTAVAIL); - case EADDRINUSE: - return (ISC_R_ADDRINUSE); - case EINVAL: - return (ISC_R_BOUND); - default: - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s", - strbuf); - return (ISC_R_UNEXPECTED); - } - } - - socket_log(sock, sockaddr, TRACE, - isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "bound"); - sock->bound = 1; - - UNLOCK(&sock->lock); - return (ISC_R_SUCCESS); -} - -/* - * Enable this only for specific OS versions, and only when they have repaired - * their problems with it. Until then, this is is broken and needs to be - * diabled by default. See RT22589 for details. - */ -#undef ENABLE_ACCEPTFILTER - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_filter(isc_socket_t *sock0, const char *filter) { - isc__socket_t *sock = (isc__socket_t *)sock0; -#if defined(SO_ACCEPTFILTER) && defined(ENABLE_ACCEPTFILTER) - char strbuf[ISC_STRERRORSIZE]; - struct accept_filter_arg afa; -#else - UNUSED(sock); - UNUSED(filter); -#endif - - REQUIRE(VALID_SOCKET(sock)); - -#if defined(SO_ACCEPTFILTER) && defined(ENABLE_ACCEPTFILTER) - bzero(&afa, sizeof(afa)); - strncpy(afa.af_name, filter, sizeof(afa.af_name)); - if (setsockopt(sock->fd, SOL_SOCKET, SO_ACCEPTFILTER, - &afa, sizeof(afa)) == -1) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET, - ISC_MSG_FILTER, "setsockopt(SO_ACCEPTFILTER): %s", - strbuf); - return (ISC_R_FAILURE); - } - return (ISC_R_SUCCESS); -#else - return (ISC_R_NOTIMPLEMENTED); -#endif -} - -/* - * Set up to listen on a given socket. We do this by creating an internal - * event that will be dispatched when the socket has read activity. The - * watcher will send the internal event to the task when there is a new - * connection. - * - * Unlike in read, we don't preallocate a done event here. Every time there - * is a new connection we'll have to allocate a new one anyway, so we might - * as well keep things simple rather than having to track them. - */ -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_listen(isc_socket_t *sock0, unsigned int backlog) { - isc__socket_t *sock = (isc__socket_t *)sock0; - char strbuf[ISC_STRERRORSIZE]; - - REQUIRE(VALID_SOCKET(sock)); - - LOCK(&sock->lock); - - REQUIRE(!sock->listener); - REQUIRE(sock->bound); - REQUIRE(sock->type == isc_sockettype_tcp || - sock->type == isc_sockettype_unix); - - if (backlog == 0) - backlog = SOMAXCONN; - - if (listen(sock->fd, (int)backlog) < 0) { - UNLOCK(&sock->lock); - isc__strerror(errno, strbuf, sizeof(strbuf)); - - UNEXPECTED_ERROR(__FILE__, __LINE__, "listen: %s", strbuf); - - return (ISC_R_UNEXPECTED); - } - - sock->listener = 1; - - UNLOCK(&sock->lock); - return (ISC_R_SUCCESS); -} - -/* - * This should try to do aggressive accept() XXXMLG - */ -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_accept(isc_socket_t *sock0, - isc_task_t *task, isc_taskaction_t action, const void *arg) -{ - isc__socket_t *sock = (isc__socket_t *)sock0; - isc_socket_newconnev_t *dev; - isc__socketmgr_t *manager; - isc_task_t *ntask = NULL; - isc__socket_t *nsock; - isc_result_t result; - isc_boolean_t do_poke = ISC_FALSE; - - REQUIRE(VALID_SOCKET(sock)); - manager = sock->manager; - REQUIRE(VALID_MANAGER(manager)); - - LOCK(&sock->lock); - - REQUIRE(sock->listener); - - /* - * Sender field is overloaded here with the task we will be sending - * this event to. Just before the actual event is delivered the - * actual ev_sender will be touched up to be the socket. - */ - dev = (isc_socket_newconnev_t *) - isc_event_allocate(manager->mctx, task, ISC_SOCKEVENT_NEWCONN, - action, arg, sizeof(*dev)); - if (dev == NULL) { - UNLOCK(&sock->lock); - return (ISC_R_NOMEMORY); - } - ISC_LINK_INIT(dev, ev_link); - - result = allocate_socket(manager, sock->type, &nsock); - if (result != ISC_R_SUCCESS) { - isc_event_free(ISC_EVENT_PTR(&dev)); - UNLOCK(&sock->lock); - return (result); - } - - /* - * Attach to socket and to task. - */ - isc_task_attach(task, &ntask); - if (isc_task_exiting(ntask)) { - free_socket(&nsock); - isc_task_detach(&ntask); - isc_event_free(ISC_EVENT_PTR(&dev)); - UNLOCK(&sock->lock); - return (ISC_R_SHUTTINGDOWN); - } - nsock->references++; - nsock->statsindex = sock->statsindex; - - dev->ev_sender = ntask; - dev->newsocket = (isc_socket_t *)nsock; - - /* - * Poke watcher here. We still have the socket locked, so there - * is no race condition. We will keep the lock for such a short - * bit of time waking it up now or later won't matter all that much. - */ - if (ISC_LIST_EMPTY(sock->accept_list)) - do_poke = ISC_TRUE; - - ISC_LIST_ENQUEUE(sock->accept_list, dev, ev_link); - - if (do_poke) - select_poke(manager, sock->fd, SELECT_POKE_ACCEPT); - - UNLOCK(&sock->lock); - return (ISC_R_SUCCESS); -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_connect(isc_socket_t *sock0, isc_sockaddr_t *addr, - isc_task_t *task, isc_taskaction_t action, const void *arg) -{ - isc__socket_t *sock = (isc__socket_t *)sock0; - isc_socket_connev_t *dev; - isc_task_t *ntask = NULL; - isc__socketmgr_t *manager; - int cc; - char strbuf[ISC_STRERRORSIZE]; - char addrbuf[ISC_SOCKADDR_FORMATSIZE]; - - REQUIRE(VALID_SOCKET(sock)); - REQUIRE(addr != NULL); - REQUIRE(task != NULL); - REQUIRE(action != NULL); - - manager = sock->manager; - REQUIRE(VALID_MANAGER(manager)); - REQUIRE(addr != NULL); - - if (isc_sockaddr_ismulticast(addr)) - return (ISC_R_MULTICAST); - - LOCK(&sock->lock); - - REQUIRE(!sock->connecting); - - dev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock, - ISC_SOCKEVENT_CONNECT, - action, arg, - sizeof(*dev)); - if (dev == NULL) { - UNLOCK(&sock->lock); - return (ISC_R_NOMEMORY); - } - ISC_LINK_INIT(dev, ev_link); - - /* - * Try to do the connect right away, as there can be only one - * outstanding, and it might happen to complete. - */ - sock->peer_address = *addr; - cc = connect(sock->fd, &addr->type.sa, addr->length); - if (cc < 0) { - /* - * HP-UX "fails" to connect a UDP socket and sets errno to - * EINPROGRESS if it's non-blocking. We'd rather regard this as - * a success and let the user detect it if it's really an error - * at the time of sending a packet on the socket. - */ - if (sock->type == isc_sockettype_udp && errno == EINPROGRESS) { - cc = 0; - goto success; - } - if (SOFT_ERROR(errno) || errno == EINPROGRESS) - goto queue; - - switch (errno) { -#define ERROR_MATCH(a, b) case a: dev->result = b; goto err_exit; - ERROR_MATCH(EACCES, ISC_R_NOPERM); - ERROR_MATCH(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL); - ERROR_MATCH(EAFNOSUPPORT, ISC_R_ADDRNOTAVAIL); - ERROR_MATCH(ECONNREFUSED, ISC_R_CONNREFUSED); - ERROR_MATCH(EHOSTUNREACH, ISC_R_HOSTUNREACH); -#ifdef EHOSTDOWN - ERROR_MATCH(EHOSTDOWN, ISC_R_HOSTUNREACH); -#endif - ERROR_MATCH(ENETUNREACH, ISC_R_NETUNREACH); - ERROR_MATCH(ENOBUFS, ISC_R_NORESOURCES); - ERROR_MATCH(EPERM, ISC_R_HOSTUNREACH); - ERROR_MATCH(EPIPE, ISC_R_NOTCONNECTED); - ERROR_MATCH(ECONNRESET, ISC_R_CONNECTIONRESET); -#undef ERROR_MATCH - } - - sock->connected = 0; - - isc__strerror(errno, strbuf, sizeof(strbuf)); - isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, "connect(%s) %d/%s", - addrbuf, errno, strbuf); - - UNLOCK(&sock->lock); - inc_stats(sock->manager->stats, - sock->statsindex[STATID_CONNECTFAIL]); - isc_event_free(ISC_EVENT_PTR(&dev)); - return (ISC_R_UNEXPECTED); - - err_exit: - sock->connected = 0; - isc_task_send(task, ISC_EVENT_PTR(&dev)); - - UNLOCK(&sock->lock); - inc_stats(sock->manager->stats, - sock->statsindex[STATID_CONNECTFAIL]); - return (ISC_R_SUCCESS); - } - - /* - * If connect completed, fire off the done event. - */ - success: - if (cc == 0) { - sock->connected = 1; - sock->bound = 1; - dev->result = ISC_R_SUCCESS; - isc_task_send(task, ISC_EVENT_PTR(&dev)); - - UNLOCK(&sock->lock); - - inc_stats(sock->manager->stats, - sock->statsindex[STATID_CONNECT]); - - return (ISC_R_SUCCESS); - } - - queue: - - /* - * Attach to task. - */ - isc_task_attach(task, &ntask); - - sock->connecting = 1; - - dev->ev_sender = ntask; - - /* - * Poke watcher here. We still have the socket locked, so there - * is no race condition. We will keep the lock for such a short - * bit of time waking it up now or later won't matter all that much. - */ - if (sock->connect_ev == NULL) - select_poke(manager, sock->fd, SELECT_POKE_CONNECT); - - sock->connect_ev = dev; - - UNLOCK(&sock->lock); - return (ISC_R_SUCCESS); -} - -/* - * Called when a socket with a pending connect() finishes. - */ -static void -internal_connect(isc_task_t *me, isc_event_t *ev) { - isc__socket_t *sock; - isc_socket_connev_t *dev; - isc_task_t *task; - int cc; - ISC_SOCKADDR_LEN_T optlen; - char strbuf[ISC_STRERRORSIZE]; - char peerbuf[ISC_SOCKADDR_FORMATSIZE]; - - UNUSED(me); - INSIST(ev->ev_type == ISC_SOCKEVENT_INTW); - - sock = ev->ev_sender; - INSIST(VALID_SOCKET(sock)); - - LOCK(&sock->lock); - - /* - * When the internal event was sent the reference count was bumped - * to keep the socket around for us. Decrement the count here. - */ - INSIST(sock->references > 0); - sock->references--; - if (sock->references == 0) { - UNLOCK(&sock->lock); - destroy(&sock); - return; - } - - /* - * Has this event been canceled? - */ - dev = sock->connect_ev; - if (dev == NULL) { - INSIST(!sock->connecting); - UNLOCK(&sock->lock); - return; - } - - INSIST(sock->connecting); - sock->connecting = 0; - - /* - * Get any possible error status here. - */ - optlen = sizeof(cc); - if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, - (void *)&cc, (void *)&optlen) < 0) - cc = errno; - else - errno = cc; - - if (errno != 0) { - /* - * If the error is EAGAIN, just re-select on this - * fd and pretend nothing strange happened. - */ - if (SOFT_ERROR(errno) || errno == EINPROGRESS) { - sock->connecting = 1; - select_poke(sock->manager, sock->fd, - SELECT_POKE_CONNECT); - UNLOCK(&sock->lock); - - return; - } - - inc_stats(sock->manager->stats, - sock->statsindex[STATID_CONNECTFAIL]); - - /* - * Translate other errors into ISC_R_* flavors. - */ - switch (errno) { -#define ERROR_MATCH(a, b) case a: dev->result = b; break; - ERROR_MATCH(EACCES, ISC_R_NOPERM); - ERROR_MATCH(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL); - ERROR_MATCH(EAFNOSUPPORT, ISC_R_ADDRNOTAVAIL); - ERROR_MATCH(ECONNREFUSED, ISC_R_CONNREFUSED); - ERROR_MATCH(EHOSTUNREACH, ISC_R_HOSTUNREACH); -#ifdef EHOSTDOWN - ERROR_MATCH(EHOSTDOWN, ISC_R_HOSTUNREACH); -#endif - ERROR_MATCH(ENETUNREACH, ISC_R_NETUNREACH); - ERROR_MATCH(ENOBUFS, ISC_R_NORESOURCES); - ERROR_MATCH(EPERM, ISC_R_HOSTUNREACH); - ERROR_MATCH(EPIPE, ISC_R_NOTCONNECTED); - ERROR_MATCH(ETIMEDOUT, ISC_R_TIMEDOUT); - ERROR_MATCH(ECONNRESET, ISC_R_CONNECTIONRESET); -#undef ERROR_MATCH - default: - dev->result = ISC_R_UNEXPECTED; - isc_sockaddr_format(&sock->peer_address, peerbuf, - sizeof(peerbuf)); - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "internal_connect: connect(%s) %s", - peerbuf, strbuf); - } - } else { - inc_stats(sock->manager->stats, - sock->statsindex[STATID_CONNECT]); - dev->result = ISC_R_SUCCESS; - sock->connected = 1; - sock->bound = 1; - } - - sock->connect_ev = NULL; - - UNLOCK(&sock->lock); - - task = dev->ev_sender; - dev->ev_sender = sock; - isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev)); -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_getpeername(isc_socket_t *sock0, isc_sockaddr_t *addressp) { - isc__socket_t *sock = (isc__socket_t *)sock0; - isc_result_t result; - - REQUIRE(VALID_SOCKET(sock)); - REQUIRE(addressp != NULL); - - LOCK(&sock->lock); - - if (sock->connected) { - *addressp = sock->peer_address; - result = ISC_R_SUCCESS; - } else { - result = ISC_R_NOTCONNECTED; - } - - UNLOCK(&sock->lock); - - return (result); -} - -ISC_SOCKETFUNC_SCOPE isc_result_t -isc__socket_getsockname(isc_socket_t *sock0, isc_sockaddr_t *addressp) { - isc__socket_t *sock = (isc__socket_t *)sock0; - ISC_SOCKADDR_LEN_T len; - isc_result_t result; - char strbuf[ISC_STRERRORSIZE]; - - REQUIRE(VALID_SOCKET(sock)); - REQUIRE(addressp != NULL); - - LOCK(&sock->lock); - - if (!sock->bound) { - result = ISC_R_NOTBOUND; - goto out; - } - - result = ISC_R_SUCCESS; - - len = sizeof(addressp->type); - if (getsockname(sock->fd, &addressp->type.sa, (void *)&len) < 0) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, "getsockname: %s", - strbuf); - result = ISC_R_UNEXPECTED; - goto out; - } - addressp->length = (unsigned int)len; - - out: - UNLOCK(&sock->lock); - - return (result); -} - -/* - * Run through the list of events on this socket, and cancel the ones - * queued for task "task" of type "how". "how" is a bitmask. - */ -ISC_SOCKETFUNC_SCOPE void -isc__socket_cancel(isc_socket_t *sock0, isc_task_t *task, unsigned int how) { - isc__socket_t *sock = (isc__socket_t *)sock0; - - REQUIRE(VALID_SOCKET(sock)); - - /* - * Quick exit if there is nothing to do. Don't even bother locking - * in this case. - */ - if (how == 0) - return; - - LOCK(&sock->lock); - - /* - * All of these do the same thing, more or less. - * Each will: - * o If the internal event is marked as "posted" try to - * remove it from the task's queue. If this fails, mark it - * as canceled instead, and let the task clean it up later. - * o For each I/O request for that task of that type, post - * its done event with status of "ISC_R_CANCELED". - * o Reset any state needed. - */ - if (((how & ISC_SOCKCANCEL_RECV) == ISC_SOCKCANCEL_RECV) - && !ISC_LIST_EMPTY(sock->recv_list)) { - isc_socketevent_t *dev; - isc_socketevent_t *next; - isc_task_t *current_task; - - dev = ISC_LIST_HEAD(sock->recv_list); - - while (dev != NULL) { - current_task = dev->ev_sender; - next = ISC_LIST_NEXT(dev, ev_link); - - if ((task == NULL) || (task == current_task)) { - dev->result = ISC_R_CANCELED; - send_recvdone_event(sock, &dev); - } - dev = next; - } - } - - if (((how & ISC_SOCKCANCEL_SEND) == ISC_SOCKCANCEL_SEND) - && !ISC_LIST_EMPTY(sock->send_list)) { - isc_socketevent_t *dev; - isc_socketevent_t *next; - isc_task_t *current_task; - - dev = ISC_LIST_HEAD(sock->send_list); - - while (dev != NULL) { - current_task = dev->ev_sender; - next = ISC_LIST_NEXT(dev, ev_link); - - if ((task == NULL) || (task == current_task)) { - dev->result = ISC_R_CANCELED; - send_senddone_event(sock, &dev); - } - dev = next; - } - } - - if (((how & ISC_SOCKCANCEL_ACCEPT) == ISC_SOCKCANCEL_ACCEPT) - && !ISC_LIST_EMPTY(sock->accept_list)) { - isc_socket_newconnev_t *dev; - isc_socket_newconnev_t *next; - isc_task_t *current_task; - - dev = ISC_LIST_HEAD(sock->accept_list); - while (dev != NULL) { - current_task = dev->ev_sender; - next = ISC_LIST_NEXT(dev, ev_link); - - if ((task == NULL) || (task == current_task)) { - - ISC_LIST_UNLINK(sock->accept_list, dev, - ev_link); - - NEWCONNSOCK(dev)->references--; - free_socket((isc__socket_t **)&dev->newsocket); - - dev->result = ISC_R_CANCELED; - dev->ev_sender = sock; - isc_task_sendanddetach(¤t_task, - ISC_EVENT_PTR(&dev)); - } - - dev = next; - } - } - - /* - * Connecting is not a list. - */ - if (((how & ISC_SOCKCANCEL_CONNECT) == ISC_SOCKCANCEL_CONNECT) - && sock->connect_ev != NULL) { - isc_socket_connev_t *dev; - isc_task_t *current_task; - - INSIST(sock->connecting); - sock->connecting = 0; - - dev = sock->connect_ev; - current_task = dev->ev_sender; - - if ((task == NULL) || (task == current_task)) { - sock->connect_ev = NULL; - - dev->result = ISC_R_CANCELED; - dev->ev_sender = sock; - isc_task_sendanddetach(¤t_task, - ISC_EVENT_PTR(&dev)); - } - } - - UNLOCK(&sock->lock); -} - -ISC_SOCKETFUNC_SCOPE isc_sockettype_t -isc__socket_gettype(isc_socket_t *sock0) { - isc__socket_t *sock = (isc__socket_t *)sock0; - - REQUIRE(VALID_SOCKET(sock)); - - return (sock->type); -} - -ISC_SOCKETFUNC_SCOPE isc_boolean_t -isc__socket_isbound(isc_socket_t *sock0) { - isc__socket_t *sock = (isc__socket_t *)sock0; - isc_boolean_t val; - - REQUIRE(VALID_SOCKET(sock)); - - LOCK(&sock->lock); - val = ((sock->bound) ? ISC_TRUE : ISC_FALSE); - UNLOCK(&sock->lock); - - return (val); -} - -ISC_SOCKETFUNC_SCOPE void -isc__socket_ipv6only(isc_socket_t *sock0, isc_boolean_t yes) { - isc__socket_t *sock = (isc__socket_t *)sock0; -#if defined(IPV6_V6ONLY) - int onoff = yes ? 1 : 0; -#else - UNUSED(yes); - UNUSED(sock); -#endif - - REQUIRE(VALID_SOCKET(sock)); - INSIST(!sock->dupped); - -#ifdef IPV6_V6ONLY - if (sock->pf == AF_INET6) { - if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY, - (void *)&onoff, sizeof(int)) < 0) { - char strbuf[ISC_STRERRORSIZE]; - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "setsockopt(%d, IPV6_V6ONLY) " - "%s: %s", sock->fd, - isc_msgcat_get(isc_msgcat, - ISC_MSGSET_GENERAL, - ISC_MSG_FAILED, - "failed"), - strbuf); - } - } - FIX_IPV6_RECVPKTINFO(sock); /* AIX */ -#endif -} - -#ifndef USE_WATCHER_THREAD -/* - * In our assumed scenario, we can simply use a single static object. - * XXX: this is not true if the application uses multiple threads with - * 'multi-context' mode. Fixing this is a future TODO item. - */ -static isc_socketwait_t swait_private; - -int -isc__socketmgr_waitevents(isc_socketmgr_t *manager0, struct timeval *tvp, - isc_socketwait_t **swaitp) -{ - isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; - - - int n; -#ifdef USE_KQUEUE - struct timespec ts, *tsp; -#endif -#ifdef USE_EPOLL - int timeout; -#endif -#ifdef USE_DEVPOLL - struct dvpoll dvp; -#endif - - REQUIRE(swaitp != NULL && *swaitp == NULL); - -#ifdef USE_SHARED_MANAGER - if (manager == NULL) - manager = socketmgr; -#endif - if (manager == NULL) - return (0); - -#ifdef USE_KQUEUE - if (tvp != NULL) { - ts.tv_sec = tvp->tv_sec; - ts.tv_nsec = tvp->tv_usec * 1000; - tsp = &ts; - } else - tsp = NULL; - swait_private.nevents = kevent(manager->kqueue_fd, NULL, 0, - manager->events, manager->nevents, - tsp); - n = swait_private.nevents; -#elif defined(USE_EPOLL) - if (tvp != NULL) - timeout = tvp->tv_sec * 1000 + (tvp->tv_usec + 999) / 1000; - else - timeout = -1; - swait_private.nevents = epoll_wait(manager->epoll_fd, - manager->events, - manager->nevents, timeout); - n = swait_private.nevents; -#elif defined(USE_DEVPOLL) - dvp.dp_fds = manager->events; - dvp.dp_nfds = manager->nevents; - if (tvp != NULL) { - dvp.dp_timeout = tvp->tv_sec * 1000 + - (tvp->tv_usec + 999) / 1000; - } else - dvp.dp_timeout = -1; - swait_private.nevents = ioctl(manager->devpoll_fd, DP_POLL, &dvp); - n = swait_private.nevents; -#elif defined(USE_SELECT) - memcpy(manager->read_fds_copy, manager->read_fds, manager->fd_bufsize); - memcpy(manager->write_fds_copy, manager->write_fds, - manager->fd_bufsize); - - swait_private.readset = manager->read_fds_copy; - swait_private.writeset = manager->write_fds_copy; - swait_private.maxfd = manager->maxfd + 1; - - n = select(swait_private.maxfd, swait_private.readset, - swait_private.writeset, NULL, tvp); -#endif - - *swaitp = &swait_private; - return (n); -} - -isc_result_t -isc__socketmgr_dispatch(isc_socketmgr_t *manager0, isc_socketwait_t *swait) { - isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0; - - REQUIRE(swait == &swait_private); - -#ifdef USE_SHARED_MANAGER - if (manager == NULL) - manager = socketmgr; -#endif - if (manager == NULL) - return (ISC_R_NOTFOUND); - -#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) - (void)process_fds(manager, manager->events, swait->nevents); - return (ISC_R_SUCCESS); -#elif defined(USE_SELECT) - process_fds(manager, swait->maxfd, swait->readset, swait->writeset); - return (ISC_R_SUCCESS); -#endif -} -#endif /* USE_WATCHER_THREAD */ - -#ifdef BIND9 -void -isc__socket_setname(isc_socket_t *socket0, const char *name, void *tag) { - isc__socket_t *socket = (isc__socket_t *)socket0; - - /* - * Name 'socket'. - */ - - REQUIRE(VALID_SOCKET(socket)); - - LOCK(&socket->lock); - memset(socket->name, 0, sizeof(socket->name)); - strncpy(socket->name, name, sizeof(socket->name) - 1); - socket->tag = tag; - UNLOCK(&socket->lock); -} - -ISC_SOCKETFUNC_SCOPE const char * -isc__socket_getname(isc_socket_t *socket0) { - isc__socket_t *socket = (isc__socket_t *)socket0; - - return (socket->name); -} - -void * -isc__socket_gettag(isc_socket_t *socket0) { - isc__socket_t *socket = (isc__socket_t *)socket0; - - return (socket->tag); -} -#endif /* BIND9 */ - -#ifdef USE_SOCKETIMPREGISTER -isc_result_t -isc__socket_register() { - return (isc_socket_register(isc__socketmgr_create)); -} -#endif - -ISC_SOCKETFUNC_SCOPE int -isc__socket_getfd(isc_socket_t *socket0) { - isc__socket_t *socket = (isc__socket_t *)socket0; - - return ((short) socket->fd); -} - -#if defined(HAVE_LIBXML2) && defined(BIND9) - -static const char * -_socktype(isc_sockettype_t type) -{ - if (type == isc_sockettype_udp) - return ("udp"); - else if (type == isc_sockettype_tcp) - return ("tcp"); - else if (type == isc_sockettype_unix) - return ("unix"); - else if (type == isc_sockettype_fdwatch) - return ("fdwatch"); - else - return ("not-initialized"); -} - -#define TRY0(a) do { xmlrc = (a); if (xmlrc < 0) goto error; } while(0) -ISC_SOCKETFUNC_SCOPE int -isc_socketmgr_renderxml(isc_socketmgr_t *mgr0, xmlTextWriterPtr writer) { - isc__socketmgr_t *mgr = (isc__socketmgr_t *)mgr0; - isc__socket_t *sock = NULL; - char peerbuf[ISC_SOCKADDR_FORMATSIZE]; - isc_sockaddr_t addr; - ISC_SOCKADDR_LEN_T len; - int xmlrc; - - LOCK(&mgr->lock); - -#ifdef USE_SHARED_MANAGER - TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "references")); - TRY0(xmlTextWriterWriteFormatString(writer, "%d", mgr->refs)); - TRY0(xmlTextWriterEndElement(writer)); -#endif /* USE_SHARED_MANAGER */ - - TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "sockets")); - sock = ISC_LIST_HEAD(mgr->socklist); - while (sock != NULL) { - LOCK(&sock->lock); - TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "socket")); - - TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "id")); - TRY0(xmlTextWriterWriteFormatString(writer, "%p", sock)); - TRY0(xmlTextWriterEndElement(writer)); - - if (sock->name[0] != 0) { - TRY0(xmlTextWriterStartElement(writer, - ISC_XMLCHAR "name")); - TRY0(xmlTextWriterWriteFormatString(writer, "%s", - sock->name)); - TRY0(xmlTextWriterEndElement(writer)); /* name */ - } - - TRY0(xmlTextWriterStartElement(writer, - ISC_XMLCHAR "references")); - TRY0(xmlTextWriterWriteFormatString(writer, "%d", - sock->references)); - TRY0(xmlTextWriterEndElement(writer)); - - TRY0(xmlTextWriterWriteElement(writer, ISC_XMLCHAR "type", - ISC_XMLCHAR _socktype(sock->type))); - - if (sock->connected) { - isc_sockaddr_format(&sock->peer_address, peerbuf, - sizeof(peerbuf)); - TRY0(xmlTextWriterWriteElement(writer, - ISC_XMLCHAR "peer-address", - ISC_XMLCHAR peerbuf)); - } - - len = sizeof(addr); - if (getsockname(sock->fd, &addr.type.sa, (void *)&len) == 0) { - isc_sockaddr_format(&addr, peerbuf, sizeof(peerbuf)); - TRY0(xmlTextWriterWriteElement(writer, - ISC_XMLCHAR "local-address", - ISC_XMLCHAR peerbuf)); - } - - TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "states")); - if (sock->pending_recv) - TRY0(xmlTextWriterWriteElement(writer, - ISC_XMLCHAR "state", - ISC_XMLCHAR "pending-receive")); - if (sock->pending_send) - TRY0(xmlTextWriterWriteElement(writer, - ISC_XMLCHAR "state", - ISC_XMLCHAR "pending-send")); - if (sock->pending_accept) - TRY0(xmlTextWriterWriteElement(writer, - ISC_XMLCHAR "state", - ISC_XMLCHAR "pending_accept")); - if (sock->listener) - TRY0(xmlTextWriterWriteElement(writer, - ISC_XMLCHAR "state", - ISC_XMLCHAR "listener")); - if (sock->connected) - TRY0(xmlTextWriterWriteElement(writer, - ISC_XMLCHAR "state", - ISC_XMLCHAR "connected")); - if (sock->connecting) - TRY0(xmlTextWriterWriteElement(writer, - ISC_XMLCHAR "state", - ISC_XMLCHAR "connecting")); - if (sock->bound) - TRY0(xmlTextWriterWriteElement(writer, - ISC_XMLCHAR "state", - ISC_XMLCHAR "bound")); - - TRY0(xmlTextWriterEndElement(writer)); /* states */ - - TRY0(xmlTextWriterEndElement(writer)); /* socket */ - - UNLOCK(&sock->lock); - sock = ISC_LIST_NEXT(sock, link); - } - TRY0(xmlTextWriterEndElement(writer)); /* sockets */ - - error: - if (sock != NULL) - UNLOCK(&sock->lock); - - UNLOCK(&mgr->lock); - - return (xmlrc); -} -#endif /* HAVE_LIBXML2 */ diff --git a/contrib/bind9/lib/isc/unix/socket_p.h b/contrib/bind9/lib/isc/unix/socket_p.h deleted file mode 100644 index 1316011..0000000 --- a/contrib/bind9/lib/isc/unix/socket_p.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2000, 2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: socket_p.h,v 1.15 2009/09/02 23:48:03 tbox Exp $ */ - -#ifndef ISC_SOCKET_P_H -#define ISC_SOCKET_P_H - -/*! \file */ - -#ifdef ISC_PLATFORM_NEEDSYSSELECTH -#include <sys/select.h> -#endif - -typedef struct isc_socketwait isc_socketwait_t; -int isc__socketmgr_waitevents(isc_socketmgr_t *, struct timeval *, - isc_socketwait_t **); -isc_result_t isc__socketmgr_dispatch(isc_socketmgr_t *, isc_socketwait_t *); -#endif /* ISC_SOCKET_P_H */ diff --git a/contrib/bind9/lib/isc/unix/stdio.c b/contrib/bind9/lib/isc/unix/stdio.c deleted file mode 100644 index 360c8c6..0000000 --- a/contrib/bind9/lib/isc/unix/stdio.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2004, 2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2000, 2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id$ */ - -#include <config.h> - -#include <errno.h> -#include <unistd.h> - -#include <isc/stdio.h> -#include <isc/stat.h> - -#include "errno2result.h" - -isc_result_t -isc_stdio_open(const char *filename, const char *mode, FILE **fp) { - FILE *f; - - f = fopen(filename, mode); - if (f == NULL) - return (isc__errno2result(errno)); - *fp = f; - return (ISC_R_SUCCESS); -} - -isc_result_t -isc_stdio_close(FILE *f) { - int r; - - r = fclose(f); - if (r == 0) - return (ISC_R_SUCCESS); - else - return (isc__errno2result(errno)); -} - -isc_result_t -isc_stdio_seek(FILE *f, long offset, int whence) { - int r; - - r = fseek(f, offset, whence); - if (r == 0) - return (ISC_R_SUCCESS); - else - return (isc__errno2result(errno)); -} - -isc_result_t -isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f, size_t *nret) { - isc_result_t result = ISC_R_SUCCESS; - size_t r; - - clearerr(f); - r = fread(ptr, size, nmemb, f); - if (r != nmemb) { - if (feof(f)) - result = ISC_R_EOF; - else - result = isc__errno2result(errno); - } - if (nret != NULL) - *nret = r; - return (result); -} - -isc_result_t -isc_stdio_write(const void *ptr, size_t size, size_t nmemb, FILE *f, - size_t *nret) -{ - isc_result_t result = ISC_R_SUCCESS; - size_t r; - - clearerr(f); - r = fwrite(ptr, size, nmemb, f); - if (r != nmemb) - result = isc__errno2result(errno); - if (nret != NULL) - *nret = r; - return (result); -} - -isc_result_t -isc_stdio_flush(FILE *f) { - int r; - - r = fflush(f); - if (r == 0) - return (ISC_R_SUCCESS); - else - return (isc__errno2result(errno)); -} - -/* - * OpenBSD has deprecated ENOTSUP in favor of EOPNOTSUPP. - */ -#if defined(EOPNOTSUPP) && !defined(ENOTSUP) -#define ENOTSUP EOPNOTSUPP -#endif - -isc_result_t -isc_stdio_sync(FILE *f) { - int r; - - r = fsync(fileno(f)); - /* - * fsync is not supported on sockets and pipes which - * result in EINVAL / ENOTSUP. - */ - if (r == 0 || errno == EINVAL || errno == ENOTSUP) - return (ISC_R_SUCCESS); - else - return (isc__errno2result(errno)); -} - diff --git a/contrib/bind9/lib/isc/unix/stdtime.c b/contrib/bind9/lib/isc/unix/stdtime.c deleted file mode 100644 index c5d0c47..0000000 --- a/contrib/bind9/lib/isc/unix/stdtime.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1999-2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: stdtime.c,v 1.19 2007/06/19 23:47:18 tbox Exp $ */ - -/*! \file */ - -#include <config.h> - -#include <stddef.h> /* NULL */ -#include <stdlib.h> /* NULL */ -#include <syslog.h> - -#include <sys/time.h> - -#include <isc/stdtime.h> -#include <isc/util.h> - -#ifndef ISC_FIX_TV_USEC -#define ISC_FIX_TV_USEC 1 -#endif - -#define US_PER_S 1000000 - -#if ISC_FIX_TV_USEC -static inline void -fix_tv_usec(struct timeval *tv) { - isc_boolean_t fixed = ISC_FALSE; - - if (tv->tv_usec < 0) { - fixed = ISC_TRUE; - do { - tv->tv_sec -= 1; - tv->tv_usec += US_PER_S; - } while (tv->tv_usec < 0); - } else if (tv->tv_usec >= US_PER_S) { - fixed = ISC_TRUE; - do { - tv->tv_sec += 1; - tv->tv_usec -= US_PER_S; - } while (tv->tv_usec >=US_PER_S); - } - /* - * Call syslog directly as we are called from the logging functions. - */ - if (fixed) - (void)syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected"); -} -#endif - -void -isc_stdtime_get(isc_stdtime_t *t) { - struct timeval tv; - - /* - * Set 't' to the number of seconds since 00:00:00 UTC, January 1, - * 1970. - */ - - REQUIRE(t != NULL); - - RUNTIME_CHECK(gettimeofday(&tv, NULL) != -1); - -#if ISC_FIX_TV_USEC - fix_tv_usec(&tv); - INSIST(tv.tv_usec >= 0); -#else - INSIST(tv.tv_usec >= 0 && tv.tv_usec < US_PER_S); -#endif - - *t = (unsigned int)tv.tv_sec; -} diff --git a/contrib/bind9/lib/isc/unix/strerror.c b/contrib/bind9/lib/isc/unix/strerror.c deleted file mode 100644 index caa6659..0000000 --- a/contrib/bind9/lib/isc/unix/strerror.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: strerror.c,v 1.10 2009/02/16 23:48:04 tbox Exp $ */ - -/*! \file */ - -#include <config.h> - -#include <stdio.h> -#include <string.h> - -#include <isc/mutex.h> -#include <isc/once.h> -#include <isc/print.h> -#include <isc/strerror.h> -#include <isc/util.h> - -#ifdef HAVE_STRERROR -/*% - * We need to do this this way for profiled locks. - */ -static isc_mutex_t isc_strerror_lock; -static void init_lock(void) { - RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS); -} -#else -extern const char * const sys_errlist[]; -extern const int sys_nerr; -#endif - -void -isc__strerror(int num, char *buf, size_t size) { -#ifdef HAVE_STRERROR - char *msg; - unsigned int unum = (unsigned int)num; - static isc_once_t once = ISC_ONCE_INIT; - - REQUIRE(buf != NULL); - - RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS); - - LOCK(&isc_strerror_lock); - msg = strerror(num); - if (msg != NULL) - snprintf(buf, size, "%s", msg); - else - snprintf(buf, size, "Unknown error: %u", unum); - UNLOCK(&isc_strerror_lock); -#else - unsigned int unum = (unsigned int)num; - - REQUIRE(buf != NULL); - - if (num >= 0 && num < sys_nerr) - snprintf(buf, size, "%s", sys_errlist[num]); - else - snprintf(buf, size, "Unknown error: %u", unum); -#endif -} diff --git a/contrib/bind9/lib/isc/unix/syslog.c b/contrib/bind9/lib/isc/unix/syslog.c deleted file mode 100644 index 997508e..0000000 --- a/contrib/bind9/lib/isc/unix/syslog.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 2001 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id: syslog.c,v 1.8 2007/09/13 04:45:18 each Exp $ */ - -/*! \file */ - -#include <config.h> - -#include <stdlib.h> -#include <syslog.h> - -#include <isc/result.h> -#include <isc/string.h> -#include <isc/syslog.h> -#include <isc/util.h> - -static struct dsn_c_pvt_sfnt { - int val; - const char *strval; -} facilities[] = { - { LOG_KERN, "kern" }, - { LOG_USER, "user" }, - { LOG_MAIL, "mail" }, - { LOG_DAEMON, "daemon" }, - { LOG_AUTH, "auth" }, - { LOG_SYSLOG, "syslog" }, - { LOG_LPR, "lpr" }, -#ifdef LOG_NEWS - { LOG_NEWS, "news" }, -#endif -#ifdef LOG_UUCP - { LOG_UUCP, "uucp" }, -#endif -#ifdef LOG_CRON - { LOG_CRON, "cron" }, -#endif -#ifdef LOG_AUTHPRIV - { LOG_AUTHPRIV, "authpriv" }, -#endif -#ifdef LOG_FTP - { LOG_FTP, "ftp" }, -#endif - { LOG_LOCAL0, "local0"}, - { LOG_LOCAL1, "local1"}, - { LOG_LOCAL2, "local2"}, - { LOG_LOCAL3, "local3"}, - { LOG_LOCAL4, "local4"}, - { LOG_LOCAL5, "local5"}, - { LOG_LOCAL6, "local6"}, - { LOG_LOCAL7, "local7"}, - { 0, NULL } -}; - -isc_result_t -isc_syslog_facilityfromstring(const char *str, int *facilityp) { - int i; - - REQUIRE(str != NULL); - REQUIRE(facilityp != NULL); - - for (i = 0; facilities[i].strval != NULL; i++) { - if (strcasecmp(facilities[i].strval, str) == 0) { - *facilityp = facilities[i].val; - return (ISC_R_SUCCESS); - } - } - return (ISC_R_NOTFOUND); - -} diff --git a/contrib/bind9/lib/isc/unix/time.c b/contrib/bind9/lib/isc/unix/time.c deleted file mode 100644 index e820afb..0000000 --- a/contrib/bind9/lib/isc/unix/time.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Copyright (C) 2004-2008, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") - * Copyright (C) 1998-2001, 2003 Internet Software Consortium. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* $Id$ */ - -/*! \file */ - -#include <config.h> - -#include <errno.h> -#include <limits.h> -#include <syslog.h> -#include <time.h> - -#include <sys/time.h> /* Required for struct timeval on some platforms. */ - -#include <isc/log.h> -#include <isc/print.h> -#include <isc/strerror.h> -#include <isc/string.h> -#include <isc/time.h> -#include <isc/util.h> - -#define NS_PER_S 1000000000 /*%< Nanoseconds per second. */ -#define NS_PER_US 1000 /*%< Nanoseconds per microsecond. */ -#define US_PER_S 1000000 /*%< Microseconds per second. */ - -/* - * All of the INSIST()s checks of nanoseconds < NS_PER_S are for - * consistency checking of the type. In lieu of magic numbers, it - * is the best we've got. The check is only performed on functions which - * need an initialized type. - */ - -#ifndef ISC_FIX_TV_USEC -#define ISC_FIX_TV_USEC 1 -#endif - -/*% - *** Intervals - ***/ - -static const isc_interval_t zero_interval = { 0, 0 }; -const isc_interval_t * const isc_interval_zero = &zero_interval; - -#if ISC_FIX_TV_USEC -static inline void -fix_tv_usec(struct timeval *tv) { - isc_boolean_t fixed = ISC_FALSE; - - if (tv->tv_usec < 0) { - fixed = ISC_TRUE; - do { - tv->tv_sec -= 1; - tv->tv_usec += US_PER_S; - } while (tv->tv_usec < 0); - } else if (tv->tv_usec >= US_PER_S) { - fixed = ISC_TRUE; - do { - tv->tv_sec += 1; - tv->tv_usec -= US_PER_S; - } while (tv->tv_usec >=US_PER_S); - } - /* - * Call syslog directly as was are called from the logging functions. - */ - if (fixed) - (void)syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected"); -} -#endif - -void -isc_interval_set(isc_interval_t *i, - unsigned int seconds, unsigned int nanoseconds) -{ - REQUIRE(i != NULL); - REQUIRE(nanoseconds < NS_PER_S); - - i->seconds = seconds; - i->nanoseconds = nanoseconds; -} - -isc_boolean_t -isc_interval_iszero(const isc_interval_t *i) { - REQUIRE(i != NULL); - INSIST(i->nanoseconds < NS_PER_S); - - if (i->seconds == 0 && i->nanoseconds == 0) - return (ISC_TRUE); - - return (ISC_FALSE); -} - - -/*** - *** Absolute Times - ***/ - -static const isc_time_t epoch = { 0, 0 }; -const isc_time_t * const isc_time_epoch = &epoch; - -void -isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) { - REQUIRE(t != NULL); - REQUIRE(nanoseconds < NS_PER_S); - - t->seconds = seconds; - t->nanoseconds = nanoseconds; -} - -void -isc_time_settoepoch(isc_time_t *t) { - REQUIRE(t != NULL); - - t->seconds = 0; - t->nanoseconds = 0; -} - -isc_boolean_t -isc_time_isepoch(const isc_time_t *t) { - REQUIRE(t != NULL); - INSIST(t->nanoseconds < NS_PER_S); - - if (t->seconds == 0 && t->nanoseconds == 0) - return (ISC_TRUE); - - return (ISC_FALSE); -} - - -isc_result_t -isc_time_now(isc_time_t *t) { - struct timeval tv; - char strbuf[ISC_STRERRORSIZE]; - - REQUIRE(t != NULL); - - if (gettimeofday(&tv, NULL) == -1) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf); - return (ISC_R_UNEXPECTED); - } - - /* - * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not, - * then this test will generate warnings for platforms on which it is - * unsigned. In any event, the chances of any of these problems - * happening are pretty much zero, but since the libisc library ensures - * certain things to be true ... - */ -#if ISC_FIX_TV_USEC - fix_tv_usec(&tv); - if (tv.tv_sec < 0) - return (ISC_R_UNEXPECTED); -#else - if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S) - return (ISC_R_UNEXPECTED); -#endif - - /* - * Ensure the tv_sec value fits in t->seconds. - */ - if (sizeof(tv.tv_sec) > sizeof(t->seconds) && - ((tv.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0U) - return (ISC_R_RANGE); - - t->seconds = tv.tv_sec; - t->nanoseconds = tv.tv_usec * NS_PER_US; - - return (ISC_R_SUCCESS); -} - -isc_result_t -isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) { - struct timeval tv; - char strbuf[ISC_STRERRORSIZE]; - - REQUIRE(t != NULL); - REQUIRE(i != NULL); - INSIST(i->nanoseconds < NS_PER_S); - - if (gettimeofday(&tv, NULL) == -1) { - isc__strerror(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf); - return (ISC_R_UNEXPECTED); - } - - /* - * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not, - * then this test will generate warnings for platforms on which it is - * unsigned. In any event, the chances of any of these problems - * happening are pretty much zero, but since the libisc library ensures - * certain things to be true ... - */ -#if ISC_FIX_TV_USEC - fix_tv_usec(&tv); - if (tv.tv_sec < 0) - return (ISC_R_UNEXPECTED); -#else - if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S) - return (ISC_R_UNEXPECTED); -#endif - - /* - * Ensure the resulting seconds value fits in the size of an - * unsigned int. (It is written this way as a slight optimization; - * note that even if both values == INT_MAX, then when added - * and getting another 1 added below the result is UINT_MAX.) - */ - if ((tv.tv_sec > INT_MAX || i->seconds > INT_MAX) && - ((long long)tv.tv_sec + i->seconds > UINT_MAX)) - return (ISC_R_RANGE); - - t->seconds = tv.tv_sec + i->seconds; - t->nanoseconds = tv.tv_usec * NS_PER_US + i->nanoseconds; - if (t->nanoseconds >= NS_PER_S) { - t->seconds++; - t->nanoseconds -= NS_PER_S; - } - - return (ISC_R_SUCCESS); -} - -int -isc_time_compare(const isc_time_t *t1, const isc_time_t *t2) { - REQUIRE(t1 != NULL && t2 != NULL); - INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S); - - if (t1->seconds < t2->seconds) - return (-1); - if (t1->seconds > t2->seconds) - return (1); - if (t1->nanoseconds < t2->nanoseconds) - return (-1); - if (t1->nanoseconds > t2->nanoseconds) - return (1); - return (0); -} - -isc_result_t -isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result) -{ - REQUIRE(t != NULL && i != NULL && result != NULL); - INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S); - - /* - * Ensure the resulting seconds value fits in the size of an - * unsigned int. (It is written this way as a slight optimization; - * note that even if both values == INT_MAX, then when added - * and getting another 1 added below the result is UINT_MAX.) - */ - if ((t->seconds > INT_MAX || i->seconds > INT_MAX) && - ((long long)t->seconds + i->seconds > UINT_MAX)) - return (ISC_R_RANGE); - - result->seconds = t->seconds + i->seconds; - result->nanoseconds = t->nanoseconds + i->nanoseconds; - if (result->nanoseconds >= NS_PER_S) { - result->seconds++; - result->nanoseconds -= NS_PER_S; - } - - return (ISC_R_SUCCESS); -} - -isc_result_t -isc_time_subtract(const isc_time_t *t, const isc_interval_t *i, - isc_time_t *result) -{ - REQUIRE(t != NULL && i != NULL && result != NULL); - INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S); - - if ((unsigned int)t->seconds < i->seconds || - ((unsigned int)t->seconds == i->seconds && - t->nanoseconds < i->nanoseconds)) - return (ISC_R_RANGE); - - result->seconds = t->seconds - i->seconds; - if (t->nanoseconds >= i->nanoseconds) - result->nanoseconds = t->nanoseconds - i->nanoseconds; - else { - result->nanoseconds = NS_PER_S - i->nanoseconds + - t->nanoseconds; - result->seconds--; - } - - return (ISC_R_SUCCESS); -} - -isc_uint64_t -isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) { - isc_uint64_t i1, i2, i3; - - REQUIRE(t1 != NULL && t2 != NULL); - INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S); - - i1 = (isc_uint64_t)t1->seconds * NS_PER_S + t1->nanoseconds; - i2 = (isc_uint64_t)t2->seconds * NS_PER_S + t2->nanoseconds; - - if (i1 <= i2) - return (0); - - i3 = i1 - i2; - - /* - * Convert to microseconds. - */ - i3 /= NS_PER_US; - - return (i3); -} - -isc_uint32_t -isc_time_seconds(const isc_time_t *t) { - REQUIRE(t != NULL); - INSIST(t->nanoseconds < NS_PER_S); - - return ((isc_uint32_t)t->seconds); -} - -isc_result_t -isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp) { - time_t seconds; - - REQUIRE(t != NULL); - INSIST(t->nanoseconds < NS_PER_S); - - /* - * Ensure that the number of seconds represented by t->seconds - * can be represented by a time_t. Since t->seconds is an unsigned - * int and since time_t is mostly opaque, this is trickier than - * it seems. (This standardized opaqueness of time_t is *very* - * frustrating; time_t is not even limited to being an integral - * type.) - * - * The mission, then, is to avoid generating any kind of warning - * about "signed versus unsigned" while trying to determine if the - * the unsigned int t->seconds is out range for tv_sec, which is - * pretty much only true if time_t is a signed integer of the same - * size as the return value of isc_time_seconds. - * - * If the paradox in the if clause below is true, t->seconds is out - * of range for time_t. - */ - seconds = (time_t)t->seconds; - - INSIST(sizeof(unsigned int) == sizeof(isc_uint32_t)); - INSIST(sizeof(time_t) >= sizeof(isc_uint32_t)); - - if (t->seconds > (~0U>>1) && seconds <= (time_t)(~0U>>1)) - return (ISC_R_RANGE); - - *secondsp = seconds; - - return (ISC_R_SUCCESS); -} - -isc_uint32_t -isc_time_nanoseconds(const isc_time_t *t) { - REQUIRE(t != NULL); - - ENSURE(t->nanoseconds < NS_PER_S); - - return ((isc_uint32_t)t->nanoseconds); -} - -void -isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) { - time_t now; - unsigned int flen; - - REQUIRE(len > 0); - - now = (time_t) t->seconds; - flen = strftime(buf, len, "%d-%b-%Y %X", localtime(&now)); - INSIST(flen < len); - if (flen != 0) - snprintf(buf + flen, len - flen, - ".%03u", t->nanoseconds / 1000000); - else - snprintf(buf, len, "99-Bad-9999 99:99:99.999"); -} - -void -isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) { - time_t now; - unsigned int flen; - - REQUIRE(len > 0); - - now = (time_t)t->seconds; - flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now)); - INSIST(flen < len); -} - -void -isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) { - time_t now; - unsigned int flen; - - REQUIRE(len > 0); - - now = (time_t)t->seconds; - flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now)); - INSIST(flen < len); -} |