interfacemgr.c revision a98f70acc8d36bf73c000808ffed455ad8f15b02
a7038d1a0513c8e804937ebc95fc9cb3a46c04f5Mark Andrews * Copyright (C) 2004-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Copyright (C) 1999-2002 Internet Software Consortium.
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews * Permission to use, copy, modify, and/or distribute this software for any
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews * purpose with or without fee is hereby granted, provided that the above
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * copyright notice and this permission notice appear in all copies.
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
15a44745412679c30a6d022733925af70a38b715David Lawrence * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15a44745412679c30a6d022733925af70a38b715David Lawrence * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15a44745412679c30a6d022733925af70a38b715David Lawrence * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15a44745412679c30a6d022733925af70a38b715David Lawrence * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15a44745412679c30a6d022733925af70a38b715David Lawrence * PERFORMANCE OF THIS SOFTWARE.
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews/* $Id: interfacemgr.c,v 1.101 2011/11/09 18:44:03 each Exp $ */
d10099d8663f4a4b21219f0c4bcc4f2b1ca1d877Bob Halley#if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR)
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence#if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews#if defined(RTM_NEWADDR) && defined(RTM_DELADDR)
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews#endif /* TUNE_LARGE */
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence#define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G')
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence#define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC)
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence/*% nameserver interface manager structure */
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews isc_socketmgr_t * socketmgr; /*%< Socket manager. */
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence unsigned int generation; /*%< Current generation no. */
add4043305ca411202ed9cf1929a4179016515ceBrian Wellington dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */
add4043305ca411202ed9cf1929a4179016515ceBrian Wellington ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */
add4043305ca411202ed9cf1929a4179016515ceBrian Wellingtonroute_event(isc_task_t *task, isc_event_t *event) {
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews "automatic interface scanning "
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews "terminated: %s",
91cd0f93ad34d23e8b09dca337120f64fbe8f0a1Andreas Gustafsson isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews "automatic interface rescanning disabled: "
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews "rtm->rtm_version mismatch (%u != %u) "
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrews if (mgr->route != NULL && ns_g_server->interface_auto)
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence * Look for next route event.
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrewsns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews * The listen-on lists are initially empty.
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence result = ns_listenlist_create(mctx, &mgr->listenon4);
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);
a3c9e34301218c7092cd8b6add6eec0957ab5483Andreas Gustafsson result = dns_aclenv_init(mctx, &mgr->aclenv);
a3c9e34301218c7092cd8b6add6eec0957ab5483Andreas Gustafsson result = isc_socket_create(mgr->socketmgr, ROUTE_SOCKET_PROTOCOL,
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews mgr->references = (mgr->route != NULL) ? 2 : 1;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence isc_region_t r = { mgr->buf, sizeof(mgr->buf) };
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrewsns_interfacemgr_destroy(ns_interfacemgr_t *mgr) {
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrencens_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrewsns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) {
8d3e74b1683f714a484bbcf73249e8ee470e36d7Mark Andrewsns_interfacemgr_detach(ns_interfacemgr_t **targetp) {
b589e90689c6e87bf9608424ca8d99571c18bc61Mark Andrewsns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence * Shut down and detach all interfaces.
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence * By incrementing the generation count, we make purge_old_interfaces()
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrews * consider all interfaces "old".
41aad56b6cc458cbf7b8483576d990a77ae9bac2Andreas Gustafsson isc_socket_cancel(mgr->route, mgr->task, ISC_SOCKCANCEL_RECV);
f427e7850928d15ffc37b1f68c60588995c9b318Mark Andrewsns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
cf3f14106d082e4676431c10c54b60b9a0e9b127Brian Wellington strncpy(ifp->name, name, sizeof(ifp->name));
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr,
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence "ns_clientmgr_create() failed: %s",
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence for (disp = 0; disp < MAX_UDP_DISPATCH; disp++)
373ce67419680a398ba3dc51a14a486caaf0afb0Mark Andrews * Create a single TCP client object. It will replace itself
cf3f14106d082e4676431c10c54b60b9a0e9b127Brian Wellington * with a new one as soon as it gets a connection, so the actual
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence * connections will be handled in parallel even though there is
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence * only one client initially.
cf3f14106d082e4676431c10c54b60b9a0e9b127Brian Wellingtonns_interface_listenudp(ns_interface_t *ifp) {
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews unsigned int attrs;
cf3f14106d082e4676431c10c54b60b9a0e9b127Brian Wellington if (isc_sockaddr_pf(&ifp->addr) == AF_INET)
cf3f14106d082e4676431c10c54b60b9a0e9b127Brian Wellington attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
cf3f14106d082e4676431c10c54b60b9a0e9b127Brian Wellington attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence ifp->nudpdispatch = ISC_MIN(ns_g_udpdisp, MAX_UDP_DISPATCH);
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence for (disp = 0; disp < ifp->nudpdispatch; disp++) {
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence result = dns_dispatch_getudp_dup(ifp->mgr->dispatchmgr,
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence "could not listen on UDP socket: %s",
85bdc128fcda11c89ec1d76ea4221f4fa8e4fc24Mark Andrews result = ns_clientmgr_createclients(ifp->clientmgr, ifp->nudpdispatch,
cf3f14106d082e4676431c10c54b60b9a0e9b127Brian Wellington "UDP ns_clientmgr_createclients(): %s",
652c80435a97ca558a47e2f320047b73b3626cd1David Lawrence dns_dispatch_changeattributes(ifp->udpdispatch[i], 0,
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews * Open a TCP socket.
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence result = isc_socket_create(ifp->mgr->socketmgr,
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews "creating TCP socket: %s",
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews isc_socket_setname(ifp->tcpsocket, "dispatcher", NULL);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews result = isc_socket_bind(ifp->tcpsocket, &ifp->addr,
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
82ca33427bdd4f3bc4ed3431e86bd810fe751674Andreas Gustafsson "binding TCP socket: %s",
d981ca645597116d227a48bf37cc5edc061c854dBob Halley result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
82ca33427bdd4f3bc4ed3431e86bd810fe751674Andreas Gustafsson "listening on TCP socket: %s",
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff * If/when there a multiple filters listen to the
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews (void)isc_socket_filter(ifp->tcpsocket, "dataready");
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews result = ns_clientmgr_createclients(ifp->clientmgr,
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews "TCP ns_clientmgr_createclients(): %s",
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrewsns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
return (result);
goto cleanup_interface;
return (result);
return (result);
int disp;
if (need_destroy)
static ns_interface_t *
return (ifp);
static isc_result_t
return (result);
return (ISC_R_SUCCESS);
static isc_boolean_t
static isc_result_t
unsigned int prefixlen;
return (result);
&prefixlen);
return (result);
return (ISC_R_SUCCESS);
if (prefixlen == 0U) {
return (ISC_R_SUCCESS);
return (result);
return (ISC_R_SUCCESS);
static isc_result_t
#ifdef WANT_IPV6
else if (!ns_g_disable6)
else if (!ns_g_disable4)
#ifndef ISC_ALLOW_MAPPED
sizeof(sabuf));
NULL);
return (result);
goto cleanup_iter;
goto cleanup_iter;
unsigned int family;
goto ignore_interface;
int match;
if (match <= 0)
match = 0;
if (match > 0 &&
match = 0;
sizeof(sabuf));
&ifp,
&addr_in_use);
if (!addr_in_use)
return (result);
static isc_result_t
if (purge)
return (result);
return (ISC_TRUE);
return (ISC_FALSE);