00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
00072 struct ns_interfacemgr {
00073 unsigned int magic;
00074 int references;
00075 isc_mutex_t lock;
00076 isc_mem_t * mctx;
00077 isc_taskmgr_t * taskmgr;
00078 isc_socketmgr_t * socketmgr;
00079 dns_dispatchmgr_t * dispatchmgr;
00080 unsigned int generation;
00081 ns_listenlist_t * listenon4;
00082 ns_listenlist_t * listenon6;
00083 dns_aclenv_t aclenv;
00084 ISC_LIST(ns_interface_t) 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
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
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
00332
00333
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
00392
00393
00394
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
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
00528
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
00584
00585
00586
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
00662
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
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
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
00732 result = isc_netaddr_masktoprefixlen(&interface->netmask,
00733 &prefixlen);
00734
00735
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
00843
00844
00845
00846
00847
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
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
00952
00953
00954
00955
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
00985
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
01002
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
01016
01017
01018 if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
01019 listenon_is_ip6_any(le))
01020 ipv6_wildcard = ISC_TRUE;
01021
01022
01023
01024
01025
01026
01027
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
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++;
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
01162
01163
01164
01165
01166 if (purge)
01167 purge_old_interfaces(mgr);
01168
01169
01170
01171
01172
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 }