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