interfacemgr.c revision a55d0a9080c8ef4117d2fc27f63220a56afb2434
/*
* Copyright (C) 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <isc/assertions.h>
#include <isc/interfaceiter.h>
#include <dns/dispatch.h>
#include <named/listenlist.h>
#include <named/interfacemgr.h>
struct ns_interfacemgr {
unsigned int magic; /* Magic number. */
int references;
unsigned int generation; /* Current generation no. */
};
{
return (DNS_R_NOMEMORY);
if (result != ISC_R_SUCCESS)
goto cleanup;
if (result != DNS_R_SUCCESS)
goto cleanup;
return (DNS_R_SUCCESS);
return (result);
}
static void
{
}
void
{
source->references++;
}
void
{
target->references--;
if (target->references == 0)
if (need_destroy)
}
void
{
/*
* Shut down and detach all interfaces.
* By incrementing the generation count, we make purge_old_interfaces()
* consider all interfaces "old".
*/
mgr->generation++;
}
static isc_result_t
{
return (DNS_R_NOMEMORY);
if (result != ISC_R_SUCCESS)
goto lock_create_failure;
/*
* Create a task.
*/
if (result != ISC_R_SUCCESS) {
"isc_task_create() failed: %s",
goto task_create_failure;
}
ifp->ntcpcurrent = 0;
return (DNS_R_SUCCESS);
return (DNS_R_UNEXPECTED);
}
static isc_result_t
/*
* Open a UDP socket.
*/
if (result != ISC_R_SUCCESS) {
"creating UDP socket: %s",
goto udp_socket_failure;
}
if (result != ISC_R_SUCCESS) {
"binding UDP socket: %s",
goto udp_bind_failure;
}
/*
* XXXRTH hardwired constants. We're going to need to determine if
* this UDP socket will be shared with the resolver, and if so, we
* need to set the hashsize to be be something bigger than 17.
*/
&ifp->udpdispatch);
if (result != ISC_R_SUCCESS) {
"UDP dns_dispatch_create(): %s",
goto udp_dispatch_failure;
}
if (result != ISC_R_SUCCESS) {
"UDP ns_clientmgr_addtodispatch(): %s",
goto addtodispatch_failure;
}
return (ISC_R_SUCCESS);
return (result);
}
static isc_result_t
/*
* Open a TCP socket.
*/
if (result != ISC_R_SUCCESS) {
"creating TCP socket: %s",
goto tcp_socket_failure;
}
if (result != ISC_R_SUCCESS) {
"binding TCP socket: %s",
goto tcp_bind_failure;
}
if (result != ISC_R_SUCCESS) {
"listen TCP socket: %s",
goto tcp_listen_failure;
}
if (result != ISC_R_SUCCESS) {
"TCP ns_clientmgr_accepttcp(): %s",
goto accepttcp_failure;
}
return (ISC_R_SUCCESS);
return (DNS_R_SUCCESS);
}
static isc_result_t
{
if (result != DNS_R_SUCCESS)
return (result);
if (result != DNS_R_SUCCESS)
goto cleanup_interface;
if (result != DNS_R_SUCCESS) {
/*
* XXXRTH We don't currently have a way to easily stop dispatch
* service, so we return currently return DNS_R_SUCCESS (the UDP
* stuff will work even if TCP creation failed). This will be fixed
* later.
*/
}
return (ISC_R_SUCCESS);
return (result);
}
static void
}
}
}
void
{
source->references++;
}
void
{
target->references--;
if (target->references == 0)
if (need_destroy)
}
/*
* Search the interface list for an interface whose address and port
* both match those of 'addr'. Return a pointer to it, or NULL if not found.
*/
static ns_interface_t *
break;
}
return (ifp);
}
/*
* Remove any interfaces whose generation number is not the current one.
*/
static void
}
}
}
static void
if (result != ISC_R_SUCCESS)
return;
while (result == ISC_R_SUCCESS) {
/*
* XXX insert code to match against named.conf
* "listen-on" statements here. Also build list of
* local addresses and local networks.
*/
if (result != ISC_R_SUCCESS)
break;
{
int match;
char buf[128];
const char *addrstr;
/*
* combination.
*/
/*
* Construct a human-readable version of same.
*/
addrstr = "(bad address)";
/*
* See if the address matches the listen-on statement;
* if not, ignore the interface.
*/
if (match <= 0)
continue;
} else {
"listening on IPv4 interface %s, %s port %u",
if (result != DNS_R_SUCCESS) {
"creating IPv4 interface %s "
"failed; interface ignored",
}
/* Continue. */
}
}
}
if (result != ISC_R_NOMORE)
"IPv4: interface iteration failed: %s",
}
static void
in6a = in6addr_any;
} else {
"listening on IPv6 interfaces, port %u",
if (result != DNS_R_SUCCESS) {
"listening on IPv6 interfaces failed");
/* Continue. */
}
}
}
void
if (isc_net_probeipv6() == ISC_R_SUCCESS) {
} else
"no IPv6 interfaces found");
if (isc_net_probeipv4() == ISC_R_SUCCESS)
else
"no IPv4 interfaces found");
/*
* Now go through the interface list and delete anything that
* does not have the current generation number. This is
* how we catch interfaces that go away or change their
* addresses.
*/
"not listening on any interfaces");
/*
* Continue anyway.
*/
}
}
void
{
}