interfacemgr.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2009, 2011-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1999-2002  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id: interfacemgr.c,v 1.101 2011/11/09 18:44:03 each Exp $ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <isc/interfaceiter.h>
00025 #include <isc/os.h>
00026 #include <isc/string.h>
00027 #include <isc/task.h>
00028 #include <isc/util.h>
00029 
00030 #include <dns/acl.h>
00031 #include <dns/dispatch.h>
00032 
00033 #include <named/client.h>
00034 #include <named/log.h>
00035 #include <named/interfacemgr.h>
00036 #include <named/server.h>
00037 
00038 #ifdef HAVE_NET_ROUTE_H
00039 #include <net/route.h>
00040 #if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR)
00041 #define USE_ROUTE_SOCKET 1
00042 #define ROUTE_SOCKET_PROTOCOL PF_ROUTE
00043 #define MSGHDR rt_msghdr
00044 #define MSGTYPE rtm_type
00045 #endif
00046 #endif
00047 
00048 #if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H)
00049 #include <linux/netlink.h>
00050 #include <linux/rtnetlink.h>
00051 #if defined(RTM_NEWADDR) && defined(RTM_DELADDR)
00052 #define USE_ROUTE_SOCKET 1
00053 #define ROUTE_SOCKET_PROTOCOL PF_NETLINK
00054 #define MSGHDR nlmsghdr
00055 #define MSGTYPE nlmsg_type
00056 #endif
00057 #endif
00058 
00059 #ifdef TUNE_LARGE
00060 #define UDPBUFFERS 32768
00061 #else
00062 #define UDPBUFFERS 1000
00063 #endif /* TUNE_LARGE */
00064 
00065 #define IFMGR_MAGIC                     ISC_MAGIC('I', 'F', 'M', 'G')
00066 #define NS_INTERFACEMGR_VALID(t)        ISC_MAGIC_VALID(t, IFMGR_MAGIC)
00067 
00068 #define IFMGR_COMMON_LOGARGS \
00069         ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR
00070 
00071 /*% nameserver interface manager structure */
00072 struct ns_interfacemgr {
00073         unsigned int            magic;          /*%< Magic number. */
00074         int                     references;
00075         isc_mutex_t             lock;
00076         isc_mem_t *             mctx;           /*%< Memory context. */
00077         isc_taskmgr_t *         taskmgr;        /*%< Task manager. */
00078         isc_socketmgr_t *       socketmgr;      /*%< Socket manager. */
00079         dns_dispatchmgr_t *     dispatchmgr;
00080         unsigned int            generation;     /*%< Current generation no. */
00081         ns_listenlist_t *       listenon4;
00082         ns_listenlist_t *       listenon6;
00083         dns_aclenv_t            aclenv;         /*%< Localhost/localnets ACLs */
00084         ISC_LIST(ns_interface_t) interfaces;    /*%< List of interfaces. */
00085         ISC_LIST(isc_sockaddr_t) listenon;
00086 #ifdef USE_ROUTE_SOCKET
00087         isc_task_t *            task;
00088         isc_socket_t *          route;
00089         unsigned char           buf[2048];
00090 #endif
00091 };
00092 
00093 static void
00094 purge_old_interfaces(ns_interfacemgr_t *mgr);
00095 
00096 static void
00097 clearlistenon(ns_interfacemgr_t *mgr);
00098 
00099 #ifdef USE_ROUTE_SOCKET
00100 static void
00101 route_event(isc_task_t *task, isc_event_t *event) {
00102         isc_socketevent_t *sevent = NULL;
00103         ns_interfacemgr_t *mgr = NULL;
00104         isc_region_t r;
00105         isc_result_t result;
00106         struct MSGHDR *rtm;
00107         isc_boolean_t done = ISC_TRUE;
00108 
00109         UNUSED(task);
00110 
00111         REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
00112         mgr = event->ev_arg;
00113         sevent = (isc_socketevent_t *)event;
00114 
00115         if (sevent->result != ISC_R_SUCCESS) {
00116                 if (sevent->result != ISC_R_CANCELED)
00117                         isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
00118                                       "automatic interface scanning "
00119                                       "terminated: %s",
00120                                       isc_result_totext(sevent->result));
00121                 ns_interfacemgr_detach(&mgr);
00122                 isc_event_free(&event);
00123                 return;
00124         }
00125 
00126         rtm = (struct MSGHDR *)mgr->buf;
00127 #ifdef RTM_VERSION
00128         if (rtm->rtm_version != RTM_VERSION) {
00129                 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
00130                               "automatic interface rescanning disabled: "
00131                               "rtm->rtm_version mismatch (%u != %u) "
00132                               "recompile required", rtm->rtm_version,
00133                               RTM_VERSION);
00134                 ns_interfacemgr_detach(&mgr);
00135                 isc_event_free(&event);
00136                 return;
00137         }
00138 #endif
00139 
00140         switch (rtm->MSGTYPE) {
00141         case RTM_NEWADDR:
00142         case RTM_DELADDR:
00143                 if (mgr->route != NULL && ns_g_server->interface_auto)
00144                         ns_server_scan_interfaces(ns_g_server);
00145                 break;
00146         default:
00147                 break;
00148         }
00149 
00150         LOCK(&mgr->lock);
00151         if (mgr->route != NULL) {
00152                 /*
00153                  * Look for next route event.
00154                  */
00155                 r.base = mgr->buf;
00156                 r.length = sizeof(mgr->buf);
00157                 result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
00158                                          route_event, mgr);
00159                 if (result == ISC_R_SUCCESS)
00160                         done = ISC_FALSE;
00161         }
00162         UNLOCK(&mgr->lock);
00163 
00164         if (done)
00165                 ns_interfacemgr_detach(&mgr);
00166         isc_event_free(&event);
00167         return;
00168 }
00169 #endif
00170 
00171 isc_result_t
00172 ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
00173                        isc_socketmgr_t *socketmgr,
00174                        dns_dispatchmgr_t *dispatchmgr,
00175                        isc_task_t *task, ns_interfacemgr_t **mgrp)
00176 {
00177         isc_result_t result;
00178         ns_interfacemgr_t *mgr;
00179 
00180 #ifndef USE_ROUTE_SOCKET
00181         UNUSED(task);
00182 #endif
00183 
00184         REQUIRE(mctx != NULL);
00185         REQUIRE(mgrp != NULL);
00186         REQUIRE(*mgrp == NULL);
00187 
00188         mgr = isc_mem_get(mctx, sizeof(*mgr));
00189         if (mgr == NULL)
00190                 return (ISC_R_NOMEMORY);
00191 
00192         mgr->mctx = NULL;
00193         isc_mem_attach(mctx, &mgr->mctx);
00194 
00195         result = isc_mutex_init(&mgr->lock);
00196         if (result != ISC_R_SUCCESS)
00197                 goto cleanup_mem;
00198 
00199         mgr->taskmgr = taskmgr;
00200         mgr->socketmgr = socketmgr;
00201         mgr->dispatchmgr = dispatchmgr;
00202         mgr->generation = 1;
00203         mgr->listenon4 = NULL;
00204         mgr->listenon6 = NULL;
00205 
00206         ISC_LIST_INIT(mgr->interfaces);
00207         ISC_LIST_INIT(mgr->listenon);
00208 
00209         /*
00210          * The listen-on lists are initially empty.
00211          */
00212         result = ns_listenlist_create(mctx, &mgr->listenon4);
00213         if (result != ISC_R_SUCCESS)
00214                 goto cleanup_mem;
00215         ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);
00216 
00217         result = dns_aclenv_init(mctx, &mgr->aclenv);
00218         if (result != ISC_R_SUCCESS)
00219                 goto cleanup_listenon;
00220 #ifdef HAVE_GEOIP
00221         mgr->aclenv.geoip = ns_g_geoip;
00222 #endif
00223 
00224 #ifdef USE_ROUTE_SOCKET
00225         mgr->route = NULL;
00226         result = isc_socket_create(mgr->socketmgr, ROUTE_SOCKET_PROTOCOL,
00227                                    isc_sockettype_raw, &mgr->route);
00228         switch (result) {
00229         case ISC_R_NOPERM:
00230         case ISC_R_SUCCESS:
00231         case ISC_R_NOTIMPLEMENTED:
00232         case ISC_R_FAMILYNOSUPPORT:
00233             break;
00234         default:
00235                 goto cleanup_aclenv;
00236         }
00237 
00238         mgr->task = NULL;
00239         if (mgr->route != NULL)
00240                 isc_task_attach(task, &mgr->task);
00241         mgr->references = (mgr->route != NULL) ? 2 : 1;
00242 #else
00243         mgr->references = 1;
00244 #endif
00245         mgr->magic = IFMGR_MAGIC;
00246         *mgrp = mgr;
00247 
00248 #ifdef USE_ROUTE_SOCKET
00249         if (mgr->route != NULL) {
00250                 isc_region_t r = { mgr->buf, sizeof(mgr->buf) };
00251 
00252                 result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
00253                                          route_event, mgr);
00254                 if (result != ISC_R_SUCCESS) {
00255                         isc_task_detach(&mgr->task);
00256                         isc_socket_detach(&mgr->route);
00257                         ns_interfacemgr_detach(&mgr);
00258                 }
00259         }
00260 #endif
00261         return (ISC_R_SUCCESS);
00262 
00263 #ifdef USE_ROUTE_SOCKET
00264  cleanup_aclenv:
00265         dns_aclenv_destroy(&mgr->aclenv);
00266 #endif
00267  cleanup_listenon:
00268         ns_listenlist_detach(&mgr->listenon4);
00269         ns_listenlist_detach(&mgr->listenon6);
00270  cleanup_mem:
00271         isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
00272         return (result);
00273 }
00274 
00275 static void
00276 ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) {
00277         REQUIRE(NS_INTERFACEMGR_VALID(mgr));
00278 
00279 #ifdef USE_ROUTE_SOCKET
00280         if (mgr->route != NULL)
00281                 isc_socket_detach(&mgr->route);
00282         if (mgr->task != NULL)
00283                 isc_task_detach(&mgr->task);
00284 #endif
00285         dns_aclenv_destroy(&mgr->aclenv);
00286         ns_listenlist_detach(&mgr->listenon4);
00287         ns_listenlist_detach(&mgr->listenon6);
00288         clearlistenon(mgr);
00289         DESTROYLOCK(&mgr->lock);
00290         mgr->magic = 0;
00291         isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
00292 }
00293 
00294 dns_aclenv_t *
00295 ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
00296         return (&mgr->aclenv);
00297 }
00298 
00299 void
00300 ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) {
00301         REQUIRE(NS_INTERFACEMGR_VALID(source));
00302         LOCK(&source->lock);
00303         INSIST(source->references > 0);
00304         source->references++;
00305         UNLOCK(&source->lock);
00306         *target = source;
00307 }
00308 
00309 void
00310 ns_interfacemgr_detach(ns_interfacemgr_t **targetp) {
00311         isc_result_t need_destroy = ISC_FALSE;
00312         ns_interfacemgr_t *target = *targetp;
00313         REQUIRE(target != NULL);
00314         REQUIRE(NS_INTERFACEMGR_VALID(target));
00315         LOCK(&target->lock);
00316         REQUIRE(target->references > 0);
00317         target->references--;
00318         if (target->references == 0)
00319                 need_destroy = ISC_TRUE;
00320         UNLOCK(&target->lock);
00321         if (need_destroy)
00322                 ns_interfacemgr_destroy(target);
00323         *targetp = NULL;
00324 }
00325 
00326 void
00327 ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
00328         REQUIRE(NS_INTERFACEMGR_VALID(mgr));
00329 
00330         /*%
00331          * Shut down and detach all interfaces.
00332          * By incrementing the generation count, we make purge_old_interfaces()
00333          * consider all interfaces "old".
00334          */
00335         mgr->generation++;
00336 #ifdef USE_ROUTE_SOCKET
00337         LOCK(&mgr->lock);
00338         if (mgr->route != NULL) {
00339                 isc_socket_cancel(mgr->route, mgr->task, ISC_SOCKCANCEL_RECV);
00340                 isc_socket_detach(&mgr->route);
00341                 isc_task_detach(&mgr->task);
00342         }
00343         UNLOCK(&mgr->lock);
00344 #endif
00345         purge_old_interfaces(mgr);
00346 }
00347 
00348 
00349 static isc_result_t
00350 ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
00351                     const char *name, ns_interface_t **ifpret)
00352 {
00353         ns_interface_t *ifp;
00354         isc_result_t result;
00355         int disp;
00356 
00357         REQUIRE(NS_INTERFACEMGR_VALID(mgr));
00358 
00359         ifp = isc_mem_get(mgr->mctx, sizeof(*ifp));
00360         if (ifp == NULL)
00361                 return (ISC_R_NOMEMORY);
00362 
00363         ifp->mgr = NULL;
00364         ifp->generation = mgr->generation;
00365         ifp->addr = *addr;
00366         ifp->flags = 0;
00367         strncpy(ifp->name, name, sizeof(ifp->name));
00368         ifp->name[sizeof(ifp->name)-1] = '\0';
00369         ifp->clientmgr = NULL;
00370 
00371         result = isc_mutex_init(&ifp->lock);
00372         if (result != ISC_R_SUCCESS)
00373                 goto lock_create_failure;
00374 
00375         result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr,
00376                                      ns_g_timermgr,
00377                                      &ifp->clientmgr);
00378         if (result != ISC_R_SUCCESS) {
00379                 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
00380                               "ns_clientmgr_create() failed: %s",
00381                               isc_result_totext(result));
00382                 goto clientmgr_create_failure;
00383         }
00384 
00385         for (disp = 0; disp < MAX_UDP_DISPATCH; disp++)
00386                 ifp->udpdispatch[disp] = NULL;
00387 
00388         ifp->tcpsocket = NULL;
00389 
00390         /*
00391          * Create a single TCP client object.  It will replace itself
00392          * with a new one as soon as it gets a connection, so the actual
00393          * connections will be handled in parallel even though there is
00394          * only one client initially.
00395          */
00396         ifp->ntcptarget = 1;
00397         ifp->ntcpcurrent = 0;
00398         ifp->nudpdispatch = 0;
00399 
00400         ifp->dscp = -1;
00401 
00402         ISC_LINK_INIT(ifp, link);
00403 
00404         ns_interfacemgr_attach(mgr, &ifp->mgr);
00405         ISC_LIST_APPEND(mgr->interfaces, ifp, link);
00406 
00407         ifp->references = 1;
00408         ifp->magic = IFACE_MAGIC;
00409         *ifpret = ifp;
00410 
00411         return (ISC_R_SUCCESS);
00412 
00413  clientmgr_create_failure:
00414         DESTROYLOCK(&ifp->lock);
00415 
00416  lock_create_failure:
00417         ifp->magic = 0;
00418         isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));
00419 
00420         return (ISC_R_UNEXPECTED);
00421 }
00422 
00423 static isc_result_t
00424 ns_interface_listenudp(ns_interface_t *ifp) {
00425         isc_result_t result;
00426         unsigned int attrs;
00427         unsigned int attrmask;
00428         int disp, i;
00429 
00430         attrs = 0;
00431         attrs |= DNS_DISPATCHATTR_UDP;
00432         if (isc_sockaddr_pf(&ifp->addr) == AF_INET)
00433                 attrs |= DNS_DISPATCHATTR_IPV4;
00434         else
00435                 attrs |= DNS_DISPATCHATTR_IPV6;
00436         attrs |= DNS_DISPATCHATTR_NOLISTEN;
00437         attrmask = 0;
00438         attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
00439         attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
00440 
00441         ifp->nudpdispatch = ISC_MIN(ns_g_udpdisp, MAX_UDP_DISPATCH);
00442         for (disp = 0; disp < ifp->nudpdispatch; disp++) {
00443                 result = dns_dispatch_getudp_dup(ifp->mgr->dispatchmgr,
00444                                                  ns_g_socketmgr,
00445                                                  ns_g_taskmgr, &ifp->addr,
00446                                                  4096, UDPBUFFERS,
00447                                                  32768, 8219, 8237,
00448                                                  attrs, attrmask,
00449                                                  &ifp->udpdispatch[disp],
00450                                                  disp == 0
00451                                                     ? NULL
00452                                                     : ifp->udpdispatch[0]);
00453                 if (result != ISC_R_SUCCESS) {
00454                         isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
00455                                       "could not listen on UDP socket: %s",
00456                                       isc_result_totext(result));
00457                         goto udp_dispatch_failure;
00458                 }
00459 
00460         }
00461 
00462         result = ns_clientmgr_createclients(ifp->clientmgr, ifp->nudpdispatch,
00463                                             ifp, ISC_FALSE);
00464         if (result != ISC_R_SUCCESS) {
00465                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00466                                  "UDP ns_clientmgr_createclients(): %s",
00467                                  isc_result_totext(result));
00468                 goto addtodispatch_failure;
00469         }
00470 
00471         return (ISC_R_SUCCESS);
00472 
00473  addtodispatch_failure:
00474         for (i = disp - 1; i <= 0; i--) {
00475                 dns_dispatch_changeattributes(ifp->udpdispatch[i], 0,
00476                                               DNS_DISPATCHATTR_NOLISTEN);
00477                 dns_dispatch_detach(&(ifp->udpdispatch[i]));
00478         }
00479         ifp->nudpdispatch = 0;
00480 
00481  udp_dispatch_failure:
00482         return (result);
00483 }
00484 
00485 static isc_result_t
00486 ns_interface_accepttcp(ns_interface_t *ifp) {
00487         isc_result_t result;
00488 
00489         /*
00490          * Open a TCP socket.
00491          */
00492         result = isc_socket_create(ifp->mgr->socketmgr,
00493                                    isc_sockaddr_pf(&ifp->addr),
00494                                    isc_sockettype_tcp,
00495                                    &ifp->tcpsocket);
00496         if (result != ISC_R_SUCCESS) {
00497                 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
00498                                  "creating TCP socket: %s",
00499                                  isc_result_totext(result));
00500                 goto tcp_socket_failure;
00501         }
00502         isc_socket_setname(ifp->tcpsocket, "dispatcher", NULL);
00503 #ifndef ISC_ALLOW_MAPPED
00504         isc_socket_ipv6only(ifp->tcpsocket, ISC_TRUE);
00505 #endif
00506         result = isc_socket_bind(ifp->tcpsocket, &ifp->addr,
00507                                  ISC_SOCKET_REUSEADDRESS);
00508         if (result != ISC_R_SUCCESS) {
00509                 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
00510                                  "binding TCP socket: %s",
00511                                  isc_result_totext(result));
00512                 goto tcp_bind_failure;
00513         }
00514 
00515         if (ifp->dscp != -1)
00516                 isc_socket_dscp(ifp->tcpsocket, ifp->dscp);
00517 
00518         result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
00519         if (result != ISC_R_SUCCESS) {
00520                 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
00521                                  "listening on TCP socket: %s",
00522                                  isc_result_totext(result));
00523                 goto tcp_listen_failure;
00524         }
00525 
00526         /*
00527          * If/when there a multiple filters listen to the
00528          * result.
00529          */
00530         (void)isc_socket_filter(ifp->tcpsocket, "dataready");
00531 
00532         result = ns_clientmgr_createclients(ifp->clientmgr,
00533                                             ifp->ntcptarget, ifp,
00534                                             ISC_TRUE);
00535         if (result != ISC_R_SUCCESS) {
00536                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00537                                  "TCP ns_clientmgr_createclients(): %s",
00538                                  isc_result_totext(result));
00539                 goto accepttcp_failure;
00540         }
00541         return (ISC_R_SUCCESS);
00542 
00543  accepttcp_failure:
00544  tcp_listen_failure:
00545  tcp_bind_failure:
00546         isc_socket_detach(&ifp->tcpsocket);
00547  tcp_socket_failure:
00548         return (result);
00549 }
00550 
00551 static isc_result_t
00552 ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
00553                    const char *name, ns_interface_t **ifpret,
00554                    isc_boolean_t accept_tcp, isc_dscp_t dscp,
00555                    isc_boolean_t *addr_in_use)
00556 {
00557         isc_result_t result;
00558         ns_interface_t *ifp = NULL;
00559         REQUIRE(ifpret != NULL && *ifpret == NULL);
00560         REQUIRE(addr_in_use == NULL || *addr_in_use == ISC_FALSE);
00561 
00562         result = ns_interface_create(mgr, addr, name, &ifp);
00563         if (result != ISC_R_SUCCESS)
00564                 return (result);
00565 
00566         ifp->dscp = dscp;
00567 
00568         result = ns_interface_listenudp(ifp);
00569         if (result != ISC_R_SUCCESS) {
00570                 if ((result == ISC_R_ADDRINUSE) && (addr_in_use != NULL))
00571                         *addr_in_use = ISC_TRUE;
00572                 goto cleanup_interface;
00573         }
00574 
00575         if (!ns_g_notcp && accept_tcp == ISC_TRUE) {
00576                 result = ns_interface_accepttcp(ifp);
00577                 if (result != ISC_R_SUCCESS) {
00578                         if ((result == ISC_R_ADDRINUSE) &&
00579                             (addr_in_use != NULL))
00580                                 *addr_in_use = ISC_TRUE;
00581 
00582                         /*
00583                          * XXXRTH We don't currently have a way to easily stop
00584                          * dispatch service, so we currently return
00585                          * ISC_R_SUCCESS (the UDP stuff will work even if TCP
00586                          * creation failed).  This will be fixed later.
00587                          */
00588                         result = ISC_R_SUCCESS;
00589                 }
00590         }
00591         *ifpret = ifp;
00592         return (result);
00593 
00594  cleanup_interface:
00595         ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
00596         ns_interface_detach(&ifp);
00597         return (result);
00598 }
00599 
00600 void
00601 ns_interface_shutdown(ns_interface_t *ifp) {
00602         if (ifp->clientmgr != NULL)
00603                 ns_clientmgr_destroy(&ifp->clientmgr);
00604 }
00605 
00606 static void
00607 ns_interface_destroy(ns_interface_t *ifp) {
00608         isc_mem_t *mctx = ifp->mgr->mctx;
00609         int disp;
00610 
00611         REQUIRE(NS_INTERFACE_VALID(ifp));
00612 
00613         ns_interface_shutdown(ifp);
00614 
00615         for (disp = 0; disp < ifp->nudpdispatch; disp++)
00616                 if (ifp->udpdispatch[disp] != NULL) {
00617                         dns_dispatch_changeattributes(ifp->udpdispatch[disp], 0,
00618                                                     DNS_DISPATCHATTR_NOLISTEN);
00619                         dns_dispatch_detach(&(ifp->udpdispatch[disp]));
00620                 }
00621 
00622         if (ifp->tcpsocket != NULL)
00623                 isc_socket_detach(&ifp->tcpsocket);
00624 
00625         DESTROYLOCK(&ifp->lock);
00626 
00627         ns_interfacemgr_detach(&ifp->mgr);
00628 
00629         ifp->magic = 0;
00630         isc_mem_put(mctx, ifp, sizeof(*ifp));
00631 }
00632 
00633 void
00634 ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
00635         REQUIRE(NS_INTERFACE_VALID(source));
00636         LOCK(&source->lock);
00637         INSIST(source->references > 0);
00638         source->references++;
00639         UNLOCK(&source->lock);
00640         *target = source;
00641 }
00642 
00643 void
00644 ns_interface_detach(ns_interface_t **targetp) {
00645         isc_result_t need_destroy = ISC_FALSE;
00646         ns_interface_t *target = *targetp;
00647         REQUIRE(target != NULL);
00648         REQUIRE(NS_INTERFACE_VALID(target));
00649         LOCK(&target->lock);
00650         REQUIRE(target->references > 0);
00651         target->references--;
00652         if (target->references == 0)
00653                 need_destroy = ISC_TRUE;
00654         UNLOCK(&target->lock);
00655         if (need_destroy)
00656                 ns_interface_destroy(target);
00657         *targetp = NULL;
00658 }
00659 
00660 /*%
00661  * Search the interface list for an interface whose address and port
00662  * both match those of 'addr'.  Return a pointer to it, or NULL if not found.
00663  */
00664 static ns_interface_t *
00665 find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
00666         ns_interface_t *ifp;
00667         for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
00668              ifp = ISC_LIST_NEXT(ifp, link)) {
00669                 if (isc_sockaddr_equal(&ifp->addr, addr))
00670                         break;
00671         }
00672         return (ifp);
00673 }
00674 
00675 /*%
00676  * Remove any interfaces whose generation number is not the current one.
00677  */
00678 static void
00679 purge_old_interfaces(ns_interfacemgr_t *mgr) {
00680         ns_interface_t *ifp, *next;
00681         for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
00682                 INSIST(NS_INTERFACE_VALID(ifp));
00683                 next = ISC_LIST_NEXT(ifp, link);
00684                 if (ifp->generation != mgr->generation) {
00685                         char sabuf[256];
00686                         ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
00687                         isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
00688                         isc_log_write(IFMGR_COMMON_LOGARGS,
00689                                       ISC_LOG_INFO,
00690                                       "no longer listening on %s", sabuf);
00691                         ns_interface_shutdown(ifp);
00692                         ns_interface_detach(&ifp);
00693                 }
00694         }
00695 }
00696 
00697 static isc_result_t
00698 clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
00699         dns_acl_t *newacl = NULL;
00700         isc_result_t result;
00701         result = dns_acl_create(mctx, 0, &newacl);
00702         if (result != ISC_R_SUCCESS)
00703                 return (result);
00704         dns_acl_detach(aclp);
00705         dns_acl_attach(newacl, aclp);
00706         dns_acl_detach(&newacl);
00707         return (ISC_R_SUCCESS);
00708 }
00709 
00710 static isc_boolean_t
00711 listenon_is_ip6_any(ns_listenelt_t *elt) {
00712         REQUIRE(elt && elt->acl);
00713         return dns_acl_isany(elt->acl);
00714 }
00715 
00716 static isc_result_t
00717 setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
00718         isc_result_t result;
00719         unsigned int prefixlen;
00720         isc_netaddr_t *netaddr;
00721 
00722         netaddr = &interface->address;
00723 
00724         /* First add localhost address */
00725         prefixlen = (netaddr->family == AF_INET) ? 32 : 128;
00726         result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable,
00727                                        netaddr, prefixlen, ISC_TRUE);
00728         if (result != ISC_R_SUCCESS)
00729                 return (result);
00730 
00731         /* Then add localnets prefix */
00732         result = isc_netaddr_masktoprefixlen(&interface->netmask,
00733                                              &prefixlen);
00734 
00735         /* Non contiguous netmasks not allowed by IPv6 arch. */
00736         if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6)
00737                 return (result);
00738 
00739         if (result != ISC_R_SUCCESS) {
00740                 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
00741                               "omitting IPv4 interface %s from "
00742                               "localnets ACL: %s", interface->name,
00743                               isc_result_totext(result));
00744                 return (ISC_R_SUCCESS);
00745         }
00746 
00747         if (prefixlen == 0U) {
00748                 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
00749                               "omitting %s interface %s from localnets ACL: "
00750                               "zero prefix length detected",
00751                               (netaddr->family == AF_INET) ? "IPv4" : "IPv6",
00752                               interface->name);
00753                 return (ISC_R_SUCCESS);
00754         }
00755 
00756         result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable,
00757                                        netaddr, prefixlen, ISC_TRUE);
00758         if (result != ISC_R_SUCCESS)
00759                 return (result);
00760 
00761         return (ISC_R_SUCCESS);
00762 }
00763 
00764 static void
00765 setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface,
00766                in_port_t port)
00767 {
00768         isc_sockaddr_t *addr;
00769         isc_sockaddr_t *old;
00770 
00771         addr = isc_mem_get(mgr->mctx, sizeof(*addr));
00772         if (addr == NULL)
00773                 return;
00774 
00775         isc_sockaddr_fromnetaddr(addr, &interface->address, port);
00776 
00777         for (old = ISC_LIST_HEAD(mgr->listenon);
00778              old != NULL;
00779              old = ISC_LIST_NEXT(old, link))
00780                 if (isc_sockaddr_equal(addr, old))
00781                         break;
00782 
00783         if (old != NULL)
00784                 isc_mem_put(mgr->mctx, addr, sizeof(*addr));
00785         else
00786                 ISC_LIST_APPEND(mgr->listenon, addr, link);
00787 }
00788 
00789 static void
00790 clearlistenon(ns_interfacemgr_t *mgr) {
00791         isc_sockaddr_t *old;
00792 
00793         old = ISC_LIST_HEAD(mgr->listenon);
00794         while (old != NULL) {
00795                 ISC_LIST_UNLINK(mgr->listenon, old, link);
00796                 isc_mem_put(mgr->mctx, old, sizeof(*old));
00797                 old = ISC_LIST_HEAD(mgr->listenon);
00798         }
00799 }
00800 
00801 static isc_result_t
00802 do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
00803         isc_boolean_t verbose)
00804 {
00805         isc_interfaceiter_t *iter = NULL;
00806         isc_boolean_t scan_ipv4 = ISC_FALSE;
00807         isc_boolean_t scan_ipv6 = ISC_FALSE;
00808         isc_boolean_t adjusting = ISC_FALSE;
00809         isc_boolean_t ipv6only = ISC_TRUE;
00810         isc_boolean_t ipv6pktinfo = ISC_TRUE;
00811         isc_result_t result;
00812         isc_netaddr_t zero_address, zero_address6;
00813         ns_listenelt_t *le;
00814         isc_sockaddr_t listen_addr;
00815         ns_interface_t *ifp;
00816         isc_boolean_t log_explicit = ISC_FALSE;
00817         isc_boolean_t dolistenon;
00818         char sabuf[ISC_SOCKADDR_FORMATSIZE];
00819         isc_boolean_t tried_listening;
00820         isc_boolean_t all_addresses_in_use;
00821 
00822         if (ext_listen != NULL)
00823                 adjusting = ISC_TRUE;
00824 
00825         if (isc_net_probeipv6() == ISC_R_SUCCESS)
00826                 scan_ipv6 = ISC_TRUE;
00827 #ifdef WANT_IPV6
00828         else if (!ns_g_disable6)
00829                 isc_log_write(IFMGR_COMMON_LOGARGS,
00830                               verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
00831                               "no IPv6 interfaces found");
00832 #endif
00833 
00834         if (isc_net_probeipv4() == ISC_R_SUCCESS)
00835                 scan_ipv4 = ISC_TRUE;
00836         else if (!ns_g_disable4)
00837                 isc_log_write(IFMGR_COMMON_LOGARGS,
00838                               verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
00839                               "no IPv4 interfaces found");
00840 
00841         /*
00842          * A special, but typical case; listen-on-v6 { any; }.
00843          * When we can make the socket IPv6-only, open a single wildcard
00844          * socket for IPv6 communication.  Otherwise, make separate socket
00845          * for each IPv6 address in order to avoid accepting IPv4 packets
00846          * as the form of mapped addresses unintentionally unless explicitly
00847          * allowed.
00848          */
00849 #ifndef ISC_ALLOW_MAPPED
00850         if (scan_ipv6 == ISC_TRUE &&
00851             isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
00852                 ipv6only = ISC_FALSE;
00853                 log_explicit = ISC_TRUE;
00854         }
00855 #endif
00856         if (scan_ipv6 == ISC_TRUE &&
00857             isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
00858                 ipv6pktinfo = ISC_FALSE;
00859                 log_explicit = ISC_TRUE;
00860         }
00861         if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) {
00862                 for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
00863                      le != NULL;
00864                      le = ISC_LIST_NEXT(le, link)) {
00865                         struct in6_addr in6a;
00866 
00867                         if (!listenon_is_ip6_any(le))
00868                                 continue;
00869 
00870                         in6a = in6addr_any;
00871                         isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
00872 
00873                         ifp = find_matching_interface(mgr, &listen_addr);
00874                         if (ifp != NULL) {
00875                                 ifp->generation = mgr->generation;
00876                                 if (le->dscp != -1 && ifp->dscp == -1)
00877                                         ifp->dscp = le->dscp;
00878                                 else if (le->dscp != ifp->dscp) {
00879                                         isc_sockaddr_format(&listen_addr,
00880                                                             sabuf,
00881                                                             sizeof(sabuf));
00882                                         isc_log_write(IFMGR_COMMON_LOGARGS,
00883                                                       ISC_LOG_WARNING,
00884                                                       "%s: conflicting DSCP "
00885                                                       "values, using %d",
00886                                                       sabuf, ifp->dscp);
00887                                 }
00888                         } else {
00889                                 isc_log_write(IFMGR_COMMON_LOGARGS,
00890                                               ISC_LOG_INFO,
00891                                               "listening on IPv6 "
00892                                               "interfaces, port %u",
00893                                               le->port);
00894                                 result = ns_interface_setup(mgr, &listen_addr,
00895                                                             "<any>", &ifp,
00896                                                             ISC_TRUE,
00897                                                             le->dscp,
00898                                                             NULL);
00899                                 if (result == ISC_R_SUCCESS)
00900                                         ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
00901                                 else
00902                                         isc_log_write(IFMGR_COMMON_LOGARGS,
00903                                                       ISC_LOG_ERROR,
00904                                                       "listening on all IPv6 "
00905                                                       "interfaces failed");
00906                                 /* Continue. */
00907                         }
00908                 }
00909         }
00910 
00911         isc_netaddr_any(&zero_address);
00912         isc_netaddr_any6(&zero_address6);
00913 
00914         result = isc_interfaceiter_create(mgr->mctx, &iter);
00915         if (result != ISC_R_SUCCESS)
00916                 return (result);
00917 
00918         if (adjusting == ISC_FALSE) {
00919                 result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
00920                 if (result != ISC_R_SUCCESS)
00921                         goto cleanup_iter;
00922                 result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
00923                 if (result != ISC_R_SUCCESS)
00924                         goto cleanup_iter;
00925                 clearlistenon(mgr);
00926         }
00927 
00928         tried_listening = ISC_FALSE;
00929         all_addresses_in_use = ISC_TRUE;
00930         for (result = isc_interfaceiter_first(iter);
00931              result == ISC_R_SUCCESS;
00932              result = isc_interfaceiter_next(iter))
00933         {
00934                 isc_interface_t interface;
00935                 ns_listenlist_t *ll;
00936                 unsigned int family;
00937 
00938                 result = isc_interfaceiter_current(iter, &interface);
00939                 if (result != ISC_R_SUCCESS)
00940                         break;
00941 
00942                 family = interface.address.family;
00943                 if (family != AF_INET && family != AF_INET6)
00944                         continue;
00945                 if (scan_ipv4 == ISC_FALSE && family == AF_INET)
00946                         continue;
00947                 if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
00948                         continue;
00949 
00950                 /*
00951                  * Test for the address being nonzero rather than testing
00952                  * INTERFACE_F_UP, because on some systems the latter
00953                  * follows the media state and we could end up ignoring
00954                  * the interface for an entire rescan interval due to
00955                  * a temporary media glitch at rescan time.
00956                  */
00957                 if (family == AF_INET &&
00958                     isc_netaddr_equal(&interface.address, &zero_address)) {
00959                         continue;
00960                 }
00961                 if (family == AF_INET6 &&
00962                     isc_netaddr_equal(&interface.address, &zero_address6)) {
00963                         continue;
00964                 }
00965 
00966                 if (adjusting == ISC_FALSE) {
00967                         result = setup_locals(mgr, &interface);
00968                         if (result != ISC_R_SUCCESS)
00969                                 goto ignore_interface;
00970                 }
00971 
00972                 ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
00973                 dolistenon = ISC_TRUE;
00974                 for (le = ISC_LIST_HEAD(ll->elts);
00975                      le != NULL;
00976                      le = ISC_LIST_NEXT(le, link))
00977                 {
00978                         int match;
00979                         isc_boolean_t ipv6_wildcard = ISC_FALSE;
00980                         isc_netaddr_t listen_netaddr;
00981                         isc_sockaddr_t listen_sockaddr;
00982 
00983                         /*
00984                          * Construct a socket address for this IP/port
00985                          * combination.
00986                          */
00987                         if (family == AF_INET) {
00988                                 isc_netaddr_fromin(&listen_netaddr,
00989                                                    &interface.address.type.in);
00990                         } else {
00991                                 isc_netaddr_fromin6(&listen_netaddr,
00992                                                     &interface.address.type.in6);
00993                                 isc_netaddr_setzone(&listen_netaddr,
00994                                                     interface.address.zone);
00995                         }
00996                         isc_sockaddr_fromnetaddr(&listen_sockaddr,
00997                                                  &listen_netaddr,
00998                                                  le->port);
00999 
01000                         /*
01001                          * See if the address matches the listen-on statement;
01002                          * if not, ignore the interface.
01003                          */
01004                         (void)dns_acl_match(&listen_netaddr, NULL, le->acl,
01005                                             &mgr->aclenv, &match, NULL);
01006                         if (match <= 0)
01007                                 continue;
01008 
01009                         if (adjusting == ISC_FALSE && dolistenon == ISC_TRUE) {
01010                                 setup_listenon(mgr, &interface, le->port);
01011                                 dolistenon = ISC_FALSE;
01012                         }
01013 
01014                         /*
01015                          * The case of "any" IPv6 address will require
01016                          * special considerations later, so remember it.
01017                          */
01018                         if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
01019                             listenon_is_ip6_any(le))
01020                                 ipv6_wildcard = ISC_TRUE;
01021 
01022                         /*
01023                          * When adjusting interfaces with extra a listening
01024                          * list, see if the address matches the extra list.
01025                          * If it does, and is also covered by a wildcard
01026                          * interface, we need to listen on the address
01027                          * explicitly.
01028                          */
01029                         if (adjusting == ISC_TRUE) {
01030                                 ns_listenelt_t *ele;
01031 
01032                                 match = 0;
01033                                 for (ele = ISC_LIST_HEAD(ext_listen->elts);
01034                                      ele != NULL;
01035                                      ele = ISC_LIST_NEXT(ele, link)) {
01036                                         (void)dns_acl_match(&listen_netaddr,
01037                                                             NULL, ele->acl,
01038                                                             NULL, &match, NULL);
01039                                         if (match > 0 &&
01040                                             (ele->port == le->port ||
01041                                             ele->port == 0))
01042                                                 break;
01043                                         else
01044                                                 match = 0;
01045                                 }
01046                                 if (ipv6_wildcard == ISC_TRUE && match == 0)
01047                                         continue;
01048                         }
01049 
01050                         ifp = find_matching_interface(mgr, &listen_sockaddr);
01051                         if (ifp != NULL) {
01052                                 ifp->generation = mgr->generation;
01053                                 if (le->dscp != -1 && ifp->dscp == -1)
01054                                         ifp->dscp = le->dscp;
01055                                 else if (le->dscp != ifp->dscp) {
01056                                         isc_sockaddr_format(&listen_sockaddr,
01057                                                             sabuf,
01058                                                             sizeof(sabuf));
01059                                         isc_log_write(IFMGR_COMMON_LOGARGS,
01060                                                       ISC_LOG_WARNING,
01061                                                       "%s: conflicting DSCP "
01062                                                       "values, using %d",
01063                                                       sabuf, ifp->dscp);
01064                                 }
01065                         } else {
01066                                 isc_boolean_t addr_in_use = ISC_FALSE;
01067 
01068                                 if (adjusting == ISC_FALSE &&
01069                                     ipv6_wildcard == ISC_TRUE)
01070                                         continue;
01071 
01072                                 if (log_explicit && family == AF_INET6 &&
01073                                     !adjusting && listenon_is_ip6_any(le)) {
01074                                         isc_log_write(IFMGR_COMMON_LOGARGS,
01075                                                       verbose ? ISC_LOG_INFO :
01076                                                               ISC_LOG_DEBUG(1),
01077                                                       "IPv6 socket API is "
01078                                                       "incomplete; explicitly "
01079                                                       "binding to each IPv6 "
01080                                                       "address separately");
01081                                         log_explicit = ISC_FALSE;
01082                                 }
01083                                 isc_sockaddr_format(&listen_sockaddr,
01084                                                     sabuf, sizeof(sabuf));
01085                                 isc_log_write(IFMGR_COMMON_LOGARGS,
01086                                               ISC_LOG_INFO,
01087                                               "%s"
01088                                               "listening on %s interface "
01089                                               "%s, %s",
01090                                               (adjusting == ISC_TRUE) ?
01091                                               "additionally " : "",
01092                                               (family == AF_INET) ?
01093                                               "IPv4" : "IPv6",
01094                                               interface.name, sabuf);
01095 
01096                                 result = ns_interface_setup(mgr,
01097                                                     &listen_sockaddr,
01098                                                     interface.name,
01099                                                     &ifp,
01100                                                     (adjusting == ISC_TRUE) ?
01101                                                     ISC_FALSE : ISC_TRUE,
01102                                                     le->dscp,
01103                                                     &addr_in_use);
01104 
01105                                 tried_listening = ISC_TRUE;
01106                                 if (!addr_in_use)
01107                                         all_addresses_in_use = ISC_FALSE;
01108 
01109                                 if (result != ISC_R_SUCCESS) {
01110                                         isc_log_write(IFMGR_COMMON_LOGARGS,
01111                                                       ISC_LOG_ERROR,
01112                                                       "creating %s interface "
01113                                                       "%s failed; interface "
01114                                                       "ignored",
01115                                                       (family == AF_INET) ?
01116                                                       "IPv4" : "IPv6",
01117                                                       interface.name);
01118                                 }
01119                                 /* Continue. */
01120                         }
01121 
01122                 }
01123                 continue;
01124 
01125         ignore_interface:
01126                 isc_log_write(IFMGR_COMMON_LOGARGS,
01127                               ISC_LOG_ERROR,
01128                               "ignoring %s interface %s: %s",
01129                               (family == AF_INET) ? "IPv4" : "IPv6",
01130                               interface.name, isc_result_totext(result));
01131                 continue;
01132         }
01133         if (result != ISC_R_NOMORE)
01134                 UNEXPECTED_ERROR(__FILE__, __LINE__,
01135                                  "interface iteration failed: %s",
01136                                  isc_result_totext(result));
01137         else
01138                 result = ((tried_listening && all_addresses_in_use) ?
01139                           ISC_R_ADDRINUSE : ISC_R_SUCCESS);
01140  cleanup_iter:
01141         isc_interfaceiter_destroy(&iter);
01142         return (result);
01143 }
01144 
01145 static isc_result_t
01146 ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
01147                       isc_boolean_t verbose)
01148 {
01149         isc_result_t result;
01150         isc_boolean_t purge = ISC_TRUE;
01151 
01152         REQUIRE(NS_INTERFACEMGR_VALID(mgr));
01153 
01154         mgr->generation++;      /* Increment the generation count. */
01155 
01156         result = do_scan(mgr, ext_listen, verbose);
01157         if ((result != ISC_R_SUCCESS) && (result != ISC_R_ADDRINUSE))
01158                 purge = ISC_FALSE;
01159 
01160         /*
01161          * Now go through the interface list and delete anything that
01162          * does not have the current generation number.  This is
01163          * how we catch interfaces that go away or change their
01164          * addresses.
01165          */
01166         if (purge)
01167                 purge_old_interfaces(mgr);
01168 
01169         /*
01170          * Warn if we are not listening on any interface, unless
01171          * we're in lwresd-only mode, in which case that is to
01172          * be expected.
01173          */
01174         if (ext_listen == NULL &&
01175             ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) {
01176                 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
01177                               "not listening on any interfaces");
01178         }
01179 
01180         return (result);
01181 }
01182 
01183 isc_boolean_t
01184 ns_interfacemgr_islistening(ns_interfacemgr_t *mgr) {
01185         REQUIRE(NS_INTERFACEMGR_VALID(mgr));
01186 
01187         return (ISC_LIST_EMPTY(mgr->interfaces) ? ISC_FALSE : ISC_TRUE);
01188 }
01189 
01190 isc_result_t
01191 ns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose) {
01192         return (ns_interfacemgr_scan0(mgr, NULL, verbose));
01193 }
01194 
01195 isc_result_t
01196 ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
01197                        isc_boolean_t verbose)
01198 {
01199         return (ns_interfacemgr_scan0(mgr, list, verbose));
01200 }
01201 
01202 void
01203 ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
01204         LOCK(&mgr->lock);
01205         ns_listenlist_detach(&mgr->listenon4);
01206         ns_listenlist_attach(value, &mgr->listenon4);
01207         UNLOCK(&mgr->lock);
01208 }
01209 
01210 void
01211 ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
01212         LOCK(&mgr->lock);
01213         ns_listenlist_detach(&mgr->listenon6);
01214         ns_listenlist_attach(value, &mgr->listenon6);
01215         UNLOCK(&mgr->lock);
01216 }
01217 
01218 void
01219 ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
01220         ns_interface_t *interface;
01221 
01222         LOCK(&mgr->lock);
01223         interface = ISC_LIST_HEAD(mgr->interfaces);
01224         while (interface != NULL) {
01225                 if (interface->clientmgr != NULL)
01226                         ns_client_dumprecursing(f, interface->clientmgr);
01227                 interface = ISC_LIST_NEXT(interface, link);
01228         }
01229         UNLOCK(&mgr->lock);
01230 }
01231 
01232 isc_boolean_t
01233 ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
01234         isc_sockaddr_t *old;
01235 
01236         for (old = ISC_LIST_HEAD(mgr->listenon);
01237              old != NULL;
01238              old = ISC_LIST_NEXT(old, link))
01239                 if (isc_sockaddr_equal(old, addr))
01240                         return (ISC_TRUE);
01241         return (ISC_FALSE);
01242 }

Generated on Tue Apr 28 17:40:54 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha