1/* 2 * Copyright (C) 2004-2009, 2011 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2002 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: interfacemgr.c,v 1.95.426.2 2011/03/12 04:59:14 tbox Exp $ */ 19 20/*! \file */ 21 22#include <config.h> 23 24#include <isc/interfaceiter.h> 25#include <isc/string.h> 26#include <isc/task.h> 27#include <isc/util.h> 28 29#include <dns/acl.h> 30#include <dns/dispatch.h> 31 32#include <named/client.h> 33#include <named/log.h> 34#include <named/interfacemgr.h> 35 36#define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G') 37#define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC) 38 39#define IFMGR_COMMON_LOGARGS \ 40 ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR 41 42/*% nameserver interface manager structure */ 43struct ns_interfacemgr { 44 unsigned int magic; /*%< Magic number. */ 45 int references; 46 isc_mutex_t lock; 47 isc_mem_t * mctx; /*%< Memory context. */ 48 isc_taskmgr_t * taskmgr; /*%< Task manager. */ 49 isc_socketmgr_t * socketmgr; /*%< Socket manager. */ 50 dns_dispatchmgr_t * dispatchmgr; 51 unsigned int generation; /*%< Current generation no. */ 52 ns_listenlist_t * listenon4; 53 ns_listenlist_t * listenon6; 54 dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */ 55 ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */ 56 ISC_LIST(isc_sockaddr_t) listenon; 57}; 58 59static void 60purge_old_interfaces(ns_interfacemgr_t *mgr); 61 62static void 63clearlistenon(ns_interfacemgr_t *mgr); 64 65isc_result_t 66ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, 67 isc_socketmgr_t *socketmgr, 68 dns_dispatchmgr_t *dispatchmgr, 69 ns_interfacemgr_t **mgrp) 70{ 71 isc_result_t result; 72 ns_interfacemgr_t *mgr; 73 74 REQUIRE(mctx != NULL); 75 REQUIRE(mgrp != NULL); 76 REQUIRE(*mgrp == NULL); 77 78 mgr = isc_mem_get(mctx, sizeof(*mgr)); 79 if (mgr == NULL) 80 return (ISC_R_NOMEMORY); 81 82 result = isc_mutex_init(&mgr->lock); 83 if (result != ISC_R_SUCCESS) 84 goto cleanup_mem; 85 86 mgr->mctx = mctx; 87 mgr->taskmgr = taskmgr; 88 mgr->socketmgr = socketmgr; 89 mgr->dispatchmgr = dispatchmgr; 90 mgr->generation = 1; 91 mgr->listenon4 = NULL; 92 mgr->listenon6 = NULL; 93 94 ISC_LIST_INIT(mgr->interfaces); 95 ISC_LIST_INIT(mgr->listenon); 96 97 /* 98 * The listen-on lists are initially empty. 99 */ 100 result = ns_listenlist_create(mctx, &mgr->listenon4); 101 if (result != ISC_R_SUCCESS) 102 goto cleanup_mem; 103 ns_listenlist_attach(mgr->listenon4, &mgr->listenon6); 104 105 result = dns_aclenv_init(mctx, &mgr->aclenv); 106 if (result != ISC_R_SUCCESS) 107 goto cleanup_listenon; 108 109 mgr->references = 1; 110 mgr->magic = IFMGR_MAGIC; 111 *mgrp = mgr; 112 return (ISC_R_SUCCESS); 113 114 cleanup_listenon: 115 ns_listenlist_detach(&mgr->listenon4); 116 ns_listenlist_detach(&mgr->listenon6); 117 cleanup_mem: 118 isc_mem_put(mctx, mgr, sizeof(*mgr)); 119 return (result); 120} 121 122static void 123ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) { 124 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 125 dns_aclenv_destroy(&mgr->aclenv); 126 ns_listenlist_detach(&mgr->listenon4); 127 ns_listenlist_detach(&mgr->listenon6); 128 clearlistenon(mgr); 129 DESTROYLOCK(&mgr->lock); 130 mgr->magic = 0; 131 isc_mem_put(mgr->mctx, mgr, sizeof(*mgr)); 132} 133 134dns_aclenv_t * 135ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) { 136 return (&mgr->aclenv); 137} 138 139void 140ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) { 141 REQUIRE(NS_INTERFACEMGR_VALID(source)); 142 LOCK(&source->lock); 143 INSIST(source->references > 0); 144 source->references++; 145 UNLOCK(&source->lock); 146 *target = source; 147} 148 149void 150ns_interfacemgr_detach(ns_interfacemgr_t **targetp) { 151 isc_result_t need_destroy = ISC_FALSE; 152 ns_interfacemgr_t *target = *targetp; 153 REQUIRE(target != NULL); 154 REQUIRE(NS_INTERFACEMGR_VALID(target)); 155 LOCK(&target->lock); 156 REQUIRE(target->references > 0); 157 target->references--; 158 if (target->references == 0) 159 need_destroy = ISC_TRUE; 160 UNLOCK(&target->lock); 161 if (need_destroy) 162 ns_interfacemgr_destroy(target); 163 *targetp = NULL; 164} 165 166void 167ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) { 168 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 169 170 /*% 171 * Shut down and detach all interfaces. 172 * By incrementing the generation count, we make purge_old_interfaces() 173 * consider all interfaces "old". 174 */ 175 mgr->generation++; 176 purge_old_interfaces(mgr); 177} 178 179 180static isc_result_t 181ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, 182 const char *name, ns_interface_t **ifpret) 183{ 184 ns_interface_t *ifp; 185 isc_result_t result; 186 187 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 188 ifp = isc_mem_get(mgr->mctx, sizeof(*ifp)); 189 if (ifp == NULL) 190 return (ISC_R_NOMEMORY); 191 ifp->mgr = NULL; 192 ifp->generation = mgr->generation; 193 ifp->addr = *addr; 194 ifp->flags = 0; 195 strncpy(ifp->name, name, sizeof(ifp->name)); 196 ifp->name[sizeof(ifp->name)-1] = '\0'; 197 ifp->clientmgr = NULL; 198 199 result = isc_mutex_init(&ifp->lock); 200 if (result != ISC_R_SUCCESS) 201 goto lock_create_failure; 202 203 result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr, 204 ns_g_timermgr, 205 &ifp->clientmgr); 206 if (result != ISC_R_SUCCESS) { 207 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 208 "ns_clientmgr_create() failed: %s", 209 isc_result_totext(result)); 210 goto clientmgr_create_failure; 211 } 212 213 ifp->udpdispatch = NULL; 214 215 ifp->tcpsocket = NULL; 216 /* 217 * Create a single TCP client object. It will replace itself 218 * with a new one as soon as it gets a connection, so the actual 219 * connections will be handled in parallel even though there is 220 * only one client initially. 221 */ 222 ifp->ntcptarget = 1; 223 ifp->ntcpcurrent = 0; 224 225 ISC_LINK_INIT(ifp, link); 226 227 ns_interfacemgr_attach(mgr, &ifp->mgr); 228 ISC_LIST_APPEND(mgr->interfaces, ifp, link); 229 230 ifp->references = 1; 231 ifp->magic = IFACE_MAGIC; 232 *ifpret = ifp; 233 234 return (ISC_R_SUCCESS); 235 236 clientmgr_create_failure: 237 DESTROYLOCK(&ifp->lock); 238 lock_create_failure: 239 ifp->magic = 0; 240 isc_mem_put(mgr->mctx, ifp, sizeof(*ifp)); 241 242 return (ISC_R_UNEXPECTED); 243} 244 245static isc_result_t 246ns_interface_listenudp(ns_interface_t *ifp) { 247 isc_result_t result; 248 unsigned int attrs; 249 unsigned int attrmask; 250 251 attrs = 0; 252 attrs |= DNS_DISPATCHATTR_UDP; 253 if (isc_sockaddr_pf(&ifp->addr) == AF_INET) 254 attrs |= DNS_DISPATCHATTR_IPV4; 255 else 256 attrs |= DNS_DISPATCHATTR_IPV6; 257 attrs |= DNS_DISPATCHATTR_NOLISTEN; 258 attrmask = 0; 259 attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP; 260 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6; 261 result = dns_dispatch_getudp(ifp->mgr->dispatchmgr, ns_g_socketmgr, 262 ns_g_taskmgr, &ifp->addr, 263 4096, 1000, 32768, 8219, 8237, 264 attrs, attrmask, &ifp->udpdispatch); 265 if (result != ISC_R_SUCCESS) { 266 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 267 "could not listen on UDP socket: %s", 268 isc_result_totext(result)); 269 goto udp_dispatch_failure; 270 } 271 272 result = ns_clientmgr_createclients(ifp->clientmgr, ns_g_cpus, 273 ifp, ISC_FALSE); 274 if (result != ISC_R_SUCCESS) { 275 UNEXPECTED_ERROR(__FILE__, __LINE__, 276 "UDP ns_clientmgr_createclients(): %s", 277 isc_result_totext(result)); 278 goto addtodispatch_failure; 279 } 280 return (ISC_R_SUCCESS); 281 282 addtodispatch_failure: 283 dns_dispatch_changeattributes(ifp->udpdispatch, 0, 284 DNS_DISPATCHATTR_NOLISTEN); 285 dns_dispatch_detach(&ifp->udpdispatch); 286 udp_dispatch_failure: 287 return (result); 288} 289 290static isc_result_t 291ns_interface_accepttcp(ns_interface_t *ifp) { 292 isc_result_t result; 293 294 /* 295 * Open a TCP socket. 296 */ 297 result = isc_socket_create(ifp->mgr->socketmgr, 298 isc_sockaddr_pf(&ifp->addr), 299 isc_sockettype_tcp, 300 &ifp->tcpsocket); 301 if (result != ISC_R_SUCCESS) { 302 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 303 "creating TCP socket: %s", 304 isc_result_totext(result)); 305 goto tcp_socket_failure; 306 } 307 isc_socket_setname(ifp->tcpsocket, "dispatcher", NULL); 308#ifndef ISC_ALLOW_MAPPED 309 isc_socket_ipv6only(ifp->tcpsocket, ISC_TRUE); 310#endif 311 result = isc_socket_bind(ifp->tcpsocket, &ifp->addr, 312 ISC_SOCKET_REUSEADDRESS); 313 if (result != ISC_R_SUCCESS) { 314 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 315 "binding TCP socket: %s", 316 isc_result_totext(result)); 317 goto tcp_bind_failure; 318 } 319 result = isc_socket_listen(ifp->tcpsocket, ns_g_listen); 320 if (result != ISC_R_SUCCESS) { 321 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 322 "listening on TCP socket: %s", 323 isc_result_totext(result)); 324 goto tcp_listen_failure; 325 } 326 327 /* 328 * If/when there a multiple filters listen to the 329 * result. 330 */ 331 (void)isc_socket_filter(ifp->tcpsocket, "dataready"); 332 333 result = ns_clientmgr_createclients(ifp->clientmgr, 334 ifp->ntcptarget, ifp, 335 ISC_TRUE); 336 if (result != ISC_R_SUCCESS) { 337 UNEXPECTED_ERROR(__FILE__, __LINE__, 338 "TCP ns_clientmgr_createclients(): %s", 339 isc_result_totext(result)); 340 goto accepttcp_failure; 341 } 342 return (ISC_R_SUCCESS); 343 344 accepttcp_failure: 345 tcp_listen_failure: 346 tcp_bind_failure: 347 isc_socket_detach(&ifp->tcpsocket); 348 tcp_socket_failure: 349 return (ISC_R_SUCCESS); 350} 351 352static isc_result_t 353ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, 354 const char *name, ns_interface_t **ifpret, 355 isc_boolean_t accept_tcp) 356{ 357 isc_result_t result; 358 ns_interface_t *ifp = NULL; 359 REQUIRE(ifpret != NULL && *ifpret == NULL); 360 361 result = ns_interface_create(mgr, addr, name, &ifp); 362 if (result != ISC_R_SUCCESS) 363 return (result); 364 365 result = ns_interface_listenudp(ifp); 366 if (result != ISC_R_SUCCESS) 367 goto cleanup_interface; 368 369 if (accept_tcp == ISC_TRUE) { 370 result = ns_interface_accepttcp(ifp); 371 if (result != ISC_R_SUCCESS) { 372 /* 373 * XXXRTH We don't currently have a way to easily stop 374 * dispatch service, so we currently return 375 * ISC_R_SUCCESS (the UDP stuff will work even if TCP 376 * creation failed). This will be fixed later. 377 */ 378 result = ISC_R_SUCCESS; 379 } 380 } 381 *ifpret = ifp; 382 return (result); 383 384 cleanup_interface: 385 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link); 386 ns_interface_detach(&ifp); 387 return (result); 388} 389 390void 391ns_interface_shutdown(ns_interface_t *ifp) { 392 if (ifp->clientmgr != NULL) 393 ns_clientmgr_destroy(&ifp->clientmgr); 394} 395 396static void 397ns_interface_destroy(ns_interface_t *ifp) { 398 isc_mem_t *mctx = ifp->mgr->mctx; 399 REQUIRE(NS_INTERFACE_VALID(ifp)); 400 401 ns_interface_shutdown(ifp); 402 403 if (ifp->udpdispatch != NULL) { 404 dns_dispatch_changeattributes(ifp->udpdispatch, 0, 405 DNS_DISPATCHATTR_NOLISTEN); 406 dns_dispatch_detach(&ifp->udpdispatch); 407 } 408 if (ifp->tcpsocket != NULL) 409 isc_socket_detach(&ifp->tcpsocket); 410 411 DESTROYLOCK(&ifp->lock); 412 413 ns_interfacemgr_detach(&ifp->mgr); 414 415 ifp->magic = 0; 416 isc_mem_put(mctx, ifp, sizeof(*ifp)); 417} 418 419void 420ns_interface_attach(ns_interface_t *source, ns_interface_t **target) { 421 REQUIRE(NS_INTERFACE_VALID(source)); 422 LOCK(&source->lock); 423 INSIST(source->references > 0); 424 source->references++; 425 UNLOCK(&source->lock); 426 *target = source; 427} 428 429void 430ns_interface_detach(ns_interface_t **targetp) { 431 isc_result_t need_destroy = ISC_FALSE; 432 ns_interface_t *target = *targetp; 433 REQUIRE(target != NULL); 434 REQUIRE(NS_INTERFACE_VALID(target)); 435 LOCK(&target->lock); 436 REQUIRE(target->references > 0); 437 target->references--; 438 if (target->references == 0) 439 need_destroy = ISC_TRUE; 440 UNLOCK(&target->lock); 441 if (need_destroy) 442 ns_interface_destroy(target); 443 *targetp = NULL; 444} 445 446/*% 447 * Search the interface list for an interface whose address and port 448 * both match those of 'addr'. Return a pointer to it, or NULL if not found. 449 */ 450static ns_interface_t * 451find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) { 452 ns_interface_t *ifp; 453 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; 454 ifp = ISC_LIST_NEXT(ifp, link)) { 455 if (isc_sockaddr_equal(&ifp->addr, addr)) 456 break; 457 } 458 return (ifp); 459} 460 461/*% 462 * Remove any interfaces whose generation number is not the current one. 463 */ 464static void 465purge_old_interfaces(ns_interfacemgr_t *mgr) { 466 ns_interface_t *ifp, *next; 467 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) { 468 INSIST(NS_INTERFACE_VALID(ifp)); 469 next = ISC_LIST_NEXT(ifp, link); 470 if (ifp->generation != mgr->generation) { 471 char sabuf[256]; 472 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link); 473 isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf)); 474 isc_log_write(IFMGR_COMMON_LOGARGS, 475 ISC_LOG_INFO, 476 "no longer listening on %s", sabuf); 477 ns_interface_shutdown(ifp); 478 ns_interface_detach(&ifp); 479 } 480 } 481} 482 483static isc_result_t 484clearacl(isc_mem_t *mctx, dns_acl_t **aclp) { 485 dns_acl_t *newacl = NULL; 486 isc_result_t result; 487 result = dns_acl_create(mctx, 0, &newacl); 488 if (result != ISC_R_SUCCESS) 489 return (result); 490 dns_acl_detach(aclp); 491 dns_acl_attach(newacl, aclp); 492 dns_acl_detach(&newacl); 493 return (ISC_R_SUCCESS); 494} 495 496static isc_boolean_t 497listenon_is_ip6_any(ns_listenelt_t *elt) { 498 REQUIRE(elt && elt->acl); 499 return dns_acl_isany(elt->acl); 500} 501 502static isc_result_t 503setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) { 504 isc_result_t result; 505 unsigned int prefixlen; 506 isc_netaddr_t *netaddr; 507 508 netaddr = &interface->address; 509 510 /* First add localhost address */ 511 prefixlen = (netaddr->family == AF_INET) ? 32 : 128; 512 result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable, 513 netaddr, prefixlen, ISC_TRUE); 514 if (result != ISC_R_SUCCESS) 515 return (result); 516 517 /* Then add localnets prefix */ 518 result = isc_netaddr_masktoprefixlen(&interface->netmask, 519 &prefixlen); 520 521 /* Non contiguous netmasks not allowed by IPv6 arch. */ 522 if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6) 523 return (result); 524 525 if (result != ISC_R_SUCCESS) { 526 isc_log_write(IFMGR_COMMON_LOGARGS, 527 ISC_LOG_WARNING, 528 "omitting IPv4 interface %s from " 529 "localnets ACL: %s", 530 interface->name, 531 isc_result_totext(result)); 532 return (ISC_R_SUCCESS); 533 } 534 535 result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable, 536 netaddr, prefixlen, ISC_TRUE); 537 if (result != ISC_R_SUCCESS) 538 return (result); 539 540 return (ISC_R_SUCCESS); 541} 542 543static void 544setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface, 545 in_port_t port) 546{ 547 isc_sockaddr_t *addr; 548 isc_sockaddr_t *old; 549 550 addr = isc_mem_get(mgr->mctx, sizeof(*addr)); 551 if (addr == NULL) 552 return; 553 554 isc_sockaddr_fromnetaddr(addr, &interface->address, port); 555 556 for (old = ISC_LIST_HEAD(mgr->listenon); 557 old != NULL; 558 old = ISC_LIST_NEXT(old, link)) 559 if (isc_sockaddr_equal(addr, old)) 560 break; 561 562 if (old != NULL) 563 isc_mem_put(mgr->mctx, addr, sizeof(*addr)); 564 else 565 ISC_LIST_APPEND(mgr->listenon, addr, link); 566} 567 568static void 569clearlistenon(ns_interfacemgr_t *mgr) { 570 isc_sockaddr_t *old; 571 572 old = ISC_LIST_HEAD(mgr->listenon); 573 while (old != NULL) { 574 ISC_LIST_UNLINK(mgr->listenon, old, link); 575 isc_mem_put(mgr->mctx, old, sizeof(*old)); 576 old = ISC_LIST_HEAD(mgr->listenon); 577 } 578} 579 580static isc_result_t 581do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, 582 isc_boolean_t verbose) 583{ 584 isc_interfaceiter_t *iter = NULL; 585 isc_boolean_t scan_ipv4 = ISC_FALSE; 586 isc_boolean_t scan_ipv6 = ISC_FALSE; 587 isc_boolean_t adjusting = ISC_FALSE; 588 isc_boolean_t ipv6only = ISC_TRUE; 589 isc_boolean_t ipv6pktinfo = ISC_TRUE; 590 isc_result_t result; 591 isc_netaddr_t zero_address, zero_address6; 592 ns_listenelt_t *le; 593 isc_sockaddr_t listen_addr; 594 ns_interface_t *ifp; 595 isc_boolean_t log_explicit = ISC_FALSE; 596 isc_boolean_t dolistenon; 597 598 if (ext_listen != NULL) 599 adjusting = ISC_TRUE; 600 601 if (isc_net_probeipv6() == ISC_R_SUCCESS) 602 scan_ipv6 = ISC_TRUE; 603#ifdef WANT_IPV6 604 else 605 isc_log_write(IFMGR_COMMON_LOGARGS, 606 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), 607 "no IPv6 interfaces found"); 608#endif 609 610 if (isc_net_probeipv4() == ISC_R_SUCCESS) 611 scan_ipv4 = ISC_TRUE; 612 else 613 isc_log_write(IFMGR_COMMON_LOGARGS, 614 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), 615 "no IPv4 interfaces found"); 616 617 /* 618 * A special, but typical case; listen-on-v6 { any; }. 619 * When we can make the socket IPv6-only, open a single wildcard 620 * socket for IPv6 communication. Otherwise, make separate socket 621 * for each IPv6 address in order to avoid accepting IPv4 packets 622 * as the form of mapped addresses unintentionally unless explicitly 623 * allowed. 624 */ 625#ifndef ISC_ALLOW_MAPPED 626 if (scan_ipv6 == ISC_TRUE && 627 isc_net_probe_ipv6only() != ISC_R_SUCCESS) { 628 ipv6only = ISC_FALSE; 629 log_explicit = ISC_TRUE; 630 } 631#endif 632 if (scan_ipv6 == ISC_TRUE && 633 isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) { 634 ipv6pktinfo = ISC_FALSE; 635 log_explicit = ISC_TRUE; 636 } 637 if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) { 638 for (le = ISC_LIST_HEAD(mgr->listenon6->elts); 639 le != NULL; 640 le = ISC_LIST_NEXT(le, link)) { 641 struct in6_addr in6a; 642 643 if (!listenon_is_ip6_any(le)) 644 continue; 645 646 in6a = in6addr_any; 647 isc_sockaddr_fromin6(&listen_addr, &in6a, le->port); 648 649 ifp = find_matching_interface(mgr, &listen_addr); 650 if (ifp != NULL) { 651 ifp->generation = mgr->generation; 652 } else { 653 isc_log_write(IFMGR_COMMON_LOGARGS, 654 ISC_LOG_INFO, 655 "listening on IPv6 " 656 "interfaces, port %u", 657 le->port); 658 result = ns_interface_setup(mgr, &listen_addr, 659 "<any>", &ifp, 660 ISC_TRUE); 661 if (result == ISC_R_SUCCESS) 662 ifp->flags |= NS_INTERFACEFLAG_ANYADDR; 663 else 664 isc_log_write(IFMGR_COMMON_LOGARGS, 665 ISC_LOG_ERROR, 666 "listening on all IPv6 " 667 "interfaces failed"); 668 /* Continue. */ 669 } 670 } 671 } 672 673 isc_netaddr_any(&zero_address); 674 isc_netaddr_any6(&zero_address6); 675 676 result = isc_interfaceiter_create(mgr->mctx, &iter); 677 if (result != ISC_R_SUCCESS) 678 return (result); 679 680 if (adjusting == ISC_FALSE) { 681 result = clearacl(mgr->mctx, &mgr->aclenv.localhost); 682 if (result != ISC_R_SUCCESS) 683 goto cleanup_iter; 684 result = clearacl(mgr->mctx, &mgr->aclenv.localnets); 685 if (result != ISC_R_SUCCESS) 686 goto cleanup_iter; 687 clearlistenon(mgr); 688 } 689 690 for (result = isc_interfaceiter_first(iter); 691 result == ISC_R_SUCCESS; 692 result = isc_interfaceiter_next(iter)) 693 { 694 isc_interface_t interface; 695 ns_listenlist_t *ll; 696 unsigned int family; 697 698 result = isc_interfaceiter_current(iter, &interface); 699 if (result != ISC_R_SUCCESS) 700 break; 701 702 family = interface.address.family; 703 if (family != AF_INET && family != AF_INET6) 704 continue; 705 if (scan_ipv4 == ISC_FALSE && family == AF_INET) 706 continue; 707 if (scan_ipv6 == ISC_FALSE && family == AF_INET6) 708 continue; 709 710 /* 711 * Test for the address being nonzero rather than testing 712 * INTERFACE_F_UP, because on some systems the latter 713 * follows the media state and we could end up ignoring 714 * the interface for an entire rescan interval due to 715 * a temporary media glitch at rescan time. 716 */ 717 if (family == AF_INET && 718 isc_netaddr_equal(&interface.address, &zero_address)) { 719 continue; 720 } 721 if (family == AF_INET6 && 722 isc_netaddr_equal(&interface.address, &zero_address6)) { 723 continue; 724 } 725 726 if (adjusting == ISC_FALSE) { 727 result = setup_locals(mgr, &interface); 728 if (result != ISC_R_SUCCESS) 729 goto ignore_interface; 730 } 731 732 ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6; 733 dolistenon = ISC_TRUE; 734 for (le = ISC_LIST_HEAD(ll->elts); 735 le != NULL; 736 le = ISC_LIST_NEXT(le, link)) 737 { 738 int match; 739 isc_boolean_t ipv6_wildcard = ISC_FALSE; 740 isc_netaddr_t listen_netaddr; 741 isc_sockaddr_t listen_sockaddr; 742 743 /* 744 * Construct a socket address for this IP/port 745 * combination. 746 */ 747 if (family == AF_INET) { 748 isc_netaddr_fromin(&listen_netaddr, 749 &interface.address.type.in); 750 } else { 751 isc_netaddr_fromin6(&listen_netaddr, 752 &interface.address.type.in6); 753 isc_netaddr_setzone(&listen_netaddr, 754 interface.address.zone); 755 } 756 isc_sockaddr_fromnetaddr(&listen_sockaddr, 757 &listen_netaddr, 758 le->port); 759 760 /* 761 * See if the address matches the listen-on statement; 762 * if not, ignore the interface. 763 */ 764 (void)dns_acl_match(&listen_netaddr, NULL, le->acl, 765 &mgr->aclenv, &match, NULL); 766 if (match <= 0) 767 continue; 768 769 if (adjusting == ISC_FALSE && dolistenon == ISC_TRUE) { 770 setup_listenon(mgr, &interface, le->port); 771 dolistenon = ISC_FALSE; 772 } 773 774 /* 775 * The case of "any" IPv6 address will require 776 * special considerations later, so remember it. 777 */ 778 if (family == AF_INET6 && ipv6only && ipv6pktinfo && 779 listenon_is_ip6_any(le)) 780 ipv6_wildcard = ISC_TRUE; 781 782 /* 783 * When adjusting interfaces with extra a listening 784 * list, see if the address matches the extra list. 785 * If it does, and is also covered by a wildcard 786 * interface, we need to listen on the address 787 * explicitly. 788 */ 789 if (adjusting == ISC_TRUE) { 790 ns_listenelt_t *ele; 791 792 match = 0; 793 for (ele = ISC_LIST_HEAD(ext_listen->elts); 794 ele != NULL; 795 ele = ISC_LIST_NEXT(ele, link)) { 796 (void)dns_acl_match(&listen_netaddr, 797 NULL, ele->acl, 798 NULL, &match, NULL); 799 if (match > 0 && 800 (ele->port == le->port || 801 ele->port == 0)) 802 break; 803 else 804 match = 0; 805 } 806 if (ipv6_wildcard == ISC_TRUE && match == 0) 807 continue; 808 } 809 810 ifp = find_matching_interface(mgr, &listen_sockaddr); 811 if (ifp != NULL) { 812 ifp->generation = mgr->generation; 813 } else { 814 char sabuf[ISC_SOCKADDR_FORMATSIZE]; 815 816 if (adjusting == ISC_FALSE && 817 ipv6_wildcard == ISC_TRUE) 818 continue; 819 820 if (log_explicit && family == AF_INET6 && 821 !adjusting && listenon_is_ip6_any(le)) { 822 isc_log_write(IFMGR_COMMON_LOGARGS, 823 verbose ? ISC_LOG_INFO : 824 ISC_LOG_DEBUG(1), 825 "IPv6 socket API is " 826 "incomplete; explicitly " 827 "binding to each IPv6 " 828 "address separately"); 829 log_explicit = ISC_FALSE; 830 } 831 isc_sockaddr_format(&listen_sockaddr, 832 sabuf, sizeof(sabuf)); 833 isc_log_write(IFMGR_COMMON_LOGARGS, 834 ISC_LOG_INFO, 835 "%s" 836 "listening on %s interface " 837 "%s, %s", 838 (adjusting == ISC_TRUE) ? 839 "additionally " : "", 840 (family == AF_INET) ? 841 "IPv4" : "IPv6", 842 interface.name, sabuf); 843 844 result = ns_interface_setup(mgr, 845 &listen_sockaddr, 846 interface.name, 847 &ifp, 848 (adjusting == ISC_TRUE) ? 849 ISC_FALSE : 850 ISC_TRUE); 851 852 if (result != ISC_R_SUCCESS) { 853 isc_log_write(IFMGR_COMMON_LOGARGS, 854 ISC_LOG_ERROR, 855 "creating %s interface " 856 "%s failed; interface " 857 "ignored", 858 (family == AF_INET) ? 859 "IPv4" : "IPv6", 860 interface.name); 861 } 862 /* Continue. */ 863 } 864 865 } 866 continue; 867 868 ignore_interface: 869 isc_log_write(IFMGR_COMMON_LOGARGS, 870 ISC_LOG_ERROR, 871 "ignoring %s interface %s: %s", 872 (family == AF_INET) ? "IPv4" : "IPv6", 873 interface.name, isc_result_totext(result)); 874 continue; 875 } 876 if (result != ISC_R_NOMORE) 877 UNEXPECTED_ERROR(__FILE__, __LINE__, 878 "interface iteration failed: %s", 879 isc_result_totext(result)); 880 else 881 result = ISC_R_SUCCESS; 882 cleanup_iter: 883 isc_interfaceiter_destroy(&iter); 884 return (result); 885} 886 887static void 888ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, 889 isc_boolean_t verbose) 890{ 891 isc_boolean_t purge = ISC_TRUE; 892 893 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 894 895 mgr->generation++; /* Increment the generation count. */ 896 897 if (do_scan(mgr, ext_listen, verbose) != ISC_R_SUCCESS) 898 purge = ISC_FALSE; 899 900 /* 901 * Now go through the interface list and delete anything that 902 * does not have the current generation number. This is 903 * how we catch interfaces that go away or change their 904 * addresses. 905 */ 906 if (purge) 907 purge_old_interfaces(mgr); 908 909 /* 910 * Warn if we are not listening on any interface, unless 911 * we're in lwresd-only mode, in which case that is to 912 * be expected. 913 */ 914 if (ext_listen == NULL && 915 ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) { 916 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, 917 "not listening on any interfaces"); 918 } 919} 920 921void 922ns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose) { 923 ns_interfacemgr_scan0(mgr, NULL, verbose); 924} 925 926void 927ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list, 928 isc_boolean_t verbose) 929{ 930 ns_interfacemgr_scan0(mgr, list, verbose); 931} 932 933void 934ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { 935 LOCK(&mgr->lock); 936 ns_listenlist_detach(&mgr->listenon4); 937 ns_listenlist_attach(value, &mgr->listenon4); 938 UNLOCK(&mgr->lock); 939} 940 941void 942ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { 943 LOCK(&mgr->lock); 944 ns_listenlist_detach(&mgr->listenon6); 945 ns_listenlist_attach(value, &mgr->listenon6); 946 UNLOCK(&mgr->lock); 947} 948 949void 950ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) { 951 ns_interface_t *interface; 952 953 LOCK(&mgr->lock); 954 interface = ISC_LIST_HEAD(mgr->interfaces); 955 while (interface != NULL) { 956 if (interface->clientmgr != NULL) 957 ns_client_dumprecursing(f, interface->clientmgr); 958 interface = ISC_LIST_NEXT(interface, link); 959 } 960 UNLOCK(&mgr->lock); 961} 962 963isc_boolean_t 964ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) { 965 isc_sockaddr_t *old; 966 967 for (old = ISC_LIST_HEAD(mgr->listenon); 968 old != NULL; 969 old = ISC_LIST_NEXT(old, link)) 970 if (isc_sockaddr_equal(old, addr)) 971 return (ISC_TRUE); 972 return (ISC_FALSE); 973} 974