interfacemgr.c revision 1.5
1/* $NetBSD: interfacemgr.c,v 1.5 2019/09/05 19:33:00 christos Exp $ */ 2 3/* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * See the COPYRIGHT file distributed with this work for additional 11 * information regarding copyright ownership. 12 */ 13 14/*! \file */ 15 16#include <config.h> 17 18#include <stdbool.h> 19 20#include <isc/interfaceiter.h> 21#include <isc/os.h> 22#include <isc/random.h> 23#include <isc/string.h> 24#include <isc/task.h> 25#include <isc/util.h> 26 27#include <dns/acl.h> 28#include <dns/dispatch.h> 29 30#include <ns/client.h> 31#include <ns/log.h> 32#include <ns/interfacemgr.h> 33#include <ns/server.h> 34 35#ifdef HAVE_NET_ROUTE_H 36#include <net/route.h> 37#if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR) 38#define USE_ROUTE_SOCKET 1 39#define ROUTE_SOCKET_PROTOCOL PF_ROUTE 40#define MSGHDR rt_msghdr 41#define MSGTYPE rtm_type 42#endif 43#endif 44 45#if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) 46#include <linux/netlink.h> 47#include <linux/rtnetlink.h> 48#if defined(RTM_NEWADDR) && defined(RTM_DELADDR) 49#define USE_ROUTE_SOCKET 1 50#define ROUTE_SOCKET_PROTOCOL PF_NETLINK 51#define MSGHDR nlmsghdr 52#define MSGTYPE nlmsg_type 53#endif 54#endif 55 56#ifdef TUNE_LARGE 57#define UDPBUFFERS 32768 58#else 59#define UDPBUFFERS 1000 60#endif /* TUNE_LARGE */ 61 62#define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G') 63#define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC) 64 65#define IFMGR_COMMON_LOGARGS \ 66 ns_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR 67 68/*% nameserver interface manager structure */ 69struct ns_interfacemgr { 70 unsigned int magic; /*%< Magic number. */ 71 int references; 72 isc_mutex_t lock; 73 isc_mem_t * mctx; /*%< Memory context. */ 74 ns_server_t * sctx; /*%< Server context. */ 75 isc_taskmgr_t * taskmgr; /*%< Task manager. */ 76 isc_task_t * excl; /*%< Exclusive task. */ 77 isc_timermgr_t * timermgr; /*%< Timer manager. */ 78 isc_socketmgr_t * socketmgr; /*%< Socket manager. */ 79 dns_dispatchmgr_t * dispatchmgr; 80 unsigned int generation; /*%< Current generation no. */ 81 ns_listenlist_t * listenon4; 82 ns_listenlist_t * listenon6; 83 dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */ 84 ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */ 85 ISC_LIST(isc_sockaddr_t) listenon; 86 int backlog; /*%< Listen queue size */ 87 unsigned int udpdisp; /*%< UDP dispatch count */ 88#ifdef USE_ROUTE_SOCKET 89 isc_task_t * task; 90 isc_socket_t * route; 91 unsigned char buf[2048]; 92#endif 93}; 94 95static void 96purge_old_interfaces(ns_interfacemgr_t *mgr); 97 98static void 99clearlistenon(ns_interfacemgr_t *mgr); 100 101#ifdef USE_ROUTE_SOCKET 102static void 103route_event(isc_task_t *task, isc_event_t *event) { 104 isc_socketevent_t *sevent = NULL; 105 ns_interfacemgr_t *mgr = NULL; 106 isc_region_t r; 107 isc_result_t result; 108 struct MSGHDR *rtm; 109 bool done = true; 110 111 UNUSED(task); 112 113 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE); 114 mgr = event->ev_arg; 115 sevent = (isc_socketevent_t *)event; 116 117 if (sevent->result != ISC_R_SUCCESS) { 118 if (sevent->result != ISC_R_CANCELED) 119 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 120 "automatic interface scanning " 121 "terminated: %s", 122 isc_result_totext(sevent->result)); 123 ns_interfacemgr_detach(&mgr); 124 isc_event_free(&event); 125 return; 126 } 127 128 rtm = (struct MSGHDR *)mgr->buf; 129#ifdef RTM_VERSION 130 if (rtm->rtm_version != RTM_VERSION) { 131 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 132 "automatic interface rescanning disabled: " 133 "rtm->rtm_version mismatch (%u != %u) " 134 "recompile required", rtm->rtm_version, 135 RTM_VERSION); 136 ns_interfacemgr_detach(&mgr); 137 isc_event_free(&event); 138 return; 139 } 140#endif 141 142 switch (rtm->MSGTYPE) { 143 case RTM_NEWADDR: 144 case RTM_DELADDR: 145 if (mgr->route != NULL && mgr->sctx->interface_auto) 146 ns_interfacemgr_scan(mgr, false); 147 break; 148 default: 149 break; 150 } 151 152 LOCK(&mgr->lock); 153 if (mgr->route != NULL) { 154 /* 155 * Look for next route event. 156 */ 157 r.base = mgr->buf; 158 r.length = sizeof(mgr->buf); 159 result = isc_socket_recv(mgr->route, &r, 1, mgr->task, 160 route_event, mgr); 161 if (result == ISC_R_SUCCESS) 162 done = false; 163 } 164 UNLOCK(&mgr->lock); 165 166 if (done) 167 ns_interfacemgr_detach(&mgr); 168 isc_event_free(&event); 169 return; 170} 171#endif 172 173isc_result_t 174ns_interfacemgr_create(isc_mem_t *mctx, 175 ns_server_t *sctx, 176 isc_taskmgr_t *taskmgr, 177 isc_timermgr_t *timermgr, 178 isc_socketmgr_t *socketmgr, 179 dns_dispatchmgr_t *dispatchmgr, 180 isc_task_t *task, 181 unsigned int udpdisp, 182 dns_geoip_databases_t *geoip, 183 ns_interfacemgr_t **mgrp) 184{ 185 isc_result_t result; 186 ns_interfacemgr_t *mgr; 187 188#ifndef USE_ROUTE_SOCKET 189 UNUSED(task); 190#endif 191 192 REQUIRE(mctx != NULL); 193 REQUIRE(mgrp != NULL); 194 REQUIRE(*mgrp == NULL); 195 196 mgr = isc_mem_get(mctx, sizeof(*mgr)); 197 if (mgr == NULL) 198 return (ISC_R_NOMEMORY); 199 200 mgr->mctx = NULL; 201 isc_mem_attach(mctx, &mgr->mctx); 202 203 mgr->sctx = NULL; 204 ns_server_attach(sctx, &mgr->sctx); 205 206 isc_mutex_init(&mgr->lock); 207 208 mgr->excl = NULL; 209 result = isc_taskmgr_excltask(taskmgr, &mgr->excl); 210 if (result != ISC_R_SUCCESS) { 211 goto cleanup_lock; 212 } 213 214 mgr->taskmgr = taskmgr; 215 mgr->timermgr = timermgr; 216 mgr->socketmgr = socketmgr; 217 mgr->dispatchmgr = dispatchmgr; 218 mgr->generation = 1; 219 mgr->listenon4 = NULL; 220 mgr->listenon6 = NULL; 221 mgr->udpdisp = udpdisp; 222 223 ISC_LIST_INIT(mgr->interfaces); 224 ISC_LIST_INIT(mgr->listenon); 225 226 /* 227 * The listen-on lists are initially empty. 228 */ 229 result = ns_listenlist_create(mctx, &mgr->listenon4); 230 if (result != ISC_R_SUCCESS) 231 goto cleanup_ctx; 232 ns_listenlist_attach(mgr->listenon4, &mgr->listenon6); 233 234 result = dns_aclenv_init(mctx, &mgr->aclenv); 235 if (result != ISC_R_SUCCESS) 236 goto cleanup_listenon; 237#if defined(HAVE_GEOIP) || defined(HAVE_GEOIP2) 238 mgr->aclenv.geoip = geoip; 239#else 240 UNUSED(geoip); 241#endif 242 243#ifdef USE_ROUTE_SOCKET 244 mgr->route = NULL; 245 result = isc_socket_create(mgr->socketmgr, ROUTE_SOCKET_PROTOCOL, 246 isc_sockettype_raw, &mgr->route); 247 switch (result) { 248 case ISC_R_NOPERM: 249 case ISC_R_SUCCESS: 250 case ISC_R_NOTIMPLEMENTED: 251 case ISC_R_FAMILYNOSUPPORT: 252 break; 253 default: 254 goto cleanup_aclenv; 255 } 256 257 mgr->task = NULL; 258 if (mgr->route != NULL) 259 isc_task_attach(task, &mgr->task); 260 mgr->references = (mgr->route != NULL) ? 2 : 1; 261#else 262 mgr->references = 1; 263#endif 264 mgr->magic = IFMGR_MAGIC; 265 *mgrp = mgr; 266 267#ifdef USE_ROUTE_SOCKET 268 if (mgr->route != NULL) { 269 isc_region_t r = { mgr->buf, sizeof(mgr->buf) }; 270 271 result = isc_socket_recv(mgr->route, &r, 1, mgr->task, 272 route_event, mgr); 273 if (result != ISC_R_SUCCESS) { 274 isc_task_detach(&mgr->task); 275 isc_socket_detach(&mgr->route); 276 ns_interfacemgr_detach(&mgr); 277 } 278 } 279#endif 280 return (ISC_R_SUCCESS); 281 282#ifdef USE_ROUTE_SOCKET 283 cleanup_aclenv: 284 dns_aclenv_destroy(&mgr->aclenv); 285#endif 286 cleanup_listenon: 287 ns_listenlist_detach(&mgr->listenon4); 288 ns_listenlist_detach(&mgr->listenon6); 289 cleanup_lock: 290 isc_mutex_destroy(&mgr->lock); 291 cleanup_ctx: 292 ns_server_detach(&mgr->sctx); 293 isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr)); 294 return (result); 295} 296 297static void 298ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) { 299 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 300 301#ifdef USE_ROUTE_SOCKET 302 if (mgr->route != NULL) 303 isc_socket_detach(&mgr->route); 304 if (mgr->task != NULL) 305 isc_task_detach(&mgr->task); 306#endif 307 dns_aclenv_destroy(&mgr->aclenv); 308 ns_listenlist_detach(&mgr->listenon4); 309 ns_listenlist_detach(&mgr->listenon6); 310 clearlistenon(mgr); 311 isc_mutex_destroy(&mgr->lock); 312 if (mgr->sctx != NULL) 313 ns_server_detach(&mgr->sctx); 314 if (mgr->excl != NULL) 315 isc_task_detach(&mgr->excl); 316 mgr->magic = 0; 317 isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr)); 318} 319 320void 321ns_interfacemgr_setbacklog(ns_interfacemgr_t *mgr, int backlog) { 322 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 323 LOCK(&mgr->lock); 324 mgr->backlog = backlog; 325 UNLOCK(&mgr->lock); 326 327} 328 329dns_aclenv_t * 330ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) { 331 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 332 333 return (&mgr->aclenv); 334} 335 336void 337ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) { 338 REQUIRE(NS_INTERFACEMGR_VALID(source)); 339 LOCK(&source->lock); 340 INSIST(source->references > 0); 341 source->references++; 342 UNLOCK(&source->lock); 343 *target = source; 344} 345 346void 347ns_interfacemgr_detach(ns_interfacemgr_t **targetp) { 348 isc_result_t need_destroy = false; 349 ns_interfacemgr_t *target = *targetp; 350 REQUIRE(target != NULL); 351 REQUIRE(NS_INTERFACEMGR_VALID(target)); 352 LOCK(&target->lock); 353 REQUIRE(target->references > 0); 354 target->references--; 355 if (target->references == 0) 356 need_destroy = true; 357 UNLOCK(&target->lock); 358 if (need_destroy) 359 ns_interfacemgr_destroy(target); 360 *targetp = NULL; 361} 362 363void 364ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) { 365 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 366 367 /*% 368 * Shut down and detach all interfaces. 369 * By incrementing the generation count, we make purge_old_interfaces() 370 * consider all interfaces "old". 371 */ 372 mgr->generation++; 373#ifdef USE_ROUTE_SOCKET 374 LOCK(&mgr->lock); 375 if (mgr->route != NULL) { 376 isc_socket_cancel(mgr->route, mgr->task, ISC_SOCKCANCEL_RECV); 377 isc_socket_detach(&mgr->route); 378 isc_task_detach(&mgr->task); 379 } 380 UNLOCK(&mgr->lock); 381#endif 382 purge_old_interfaces(mgr); 383} 384 385 386static isc_result_t 387ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, 388 const char *name, ns_interface_t **ifpret) 389{ 390 ns_interface_t *ifp; 391 isc_result_t result; 392 int disp; 393 394 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 395 396 ifp = isc_mem_get(mgr->mctx, sizeof(*ifp)); 397 if (ifp == NULL) 398 return (ISC_R_NOMEMORY); 399 400 ifp->mgr = NULL; 401 ifp->generation = mgr->generation; 402 ifp->addr = *addr; 403 ifp->flags = 0; 404 strlcpy(ifp->name, name, sizeof(ifp->name)); 405 ifp->clientmgr = NULL; 406 407 isc_mutex_init(&ifp->lock); 408 409 result = ns_clientmgr_create(mgr->mctx, mgr->sctx, 410 mgr->taskmgr, mgr->timermgr, 411 &ifp->clientmgr); 412 if (result != ISC_R_SUCCESS) { 413 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 414 "ns_clientmgr_create() failed: %s", 415 isc_result_totext(result)); 416 goto clientmgr_create_failure; 417 } 418 419 for (disp = 0; disp < MAX_UDP_DISPATCH; disp++) 420 ifp->udpdispatch[disp] = NULL; 421 422 ifp->tcpsocket = NULL; 423 424 /* 425 * Create a single TCP client object. It will replace itself 426 * with a new one as soon as it gets a connection, so the actual 427 * connections will be handled in parallel even though there is 428 * only one client initially. 429 */ 430 isc_refcount_init(&ifp->ntcpaccepting, 0); 431 isc_refcount_init(&ifp->ntcpactive, 0); 432 433 ifp->nudpdispatch = 0; 434 435 ifp->dscp = -1; 436 437 ISC_LINK_INIT(ifp, link); 438 439 ns_interfacemgr_attach(mgr, &ifp->mgr); 440 ISC_LIST_APPEND(mgr->interfaces, ifp, link); 441 442 ifp->references = 1; 443 ifp->magic = IFACE_MAGIC; 444 *ifpret = ifp; 445 446 return (ISC_R_SUCCESS); 447 448 clientmgr_create_failure: 449 isc_mutex_destroy(&ifp->lock); 450 451 ifp->magic = 0; 452 isc_mem_put(mgr->mctx, ifp, sizeof(*ifp)); 453 454 return (ISC_R_UNEXPECTED); 455} 456 457static isc_result_t 458ns_interface_listenudp(ns_interface_t *ifp) { 459 isc_result_t result; 460 unsigned int attrs; 461 unsigned int attrmask; 462 int disp, i; 463 464 attrs = 0; 465 attrs |= DNS_DISPATCHATTR_UDP; 466 if (isc_sockaddr_pf(&ifp->addr) == AF_INET) 467 attrs |= DNS_DISPATCHATTR_IPV4; 468 else 469 attrs |= DNS_DISPATCHATTR_IPV6; 470 attrs |= DNS_DISPATCHATTR_NOLISTEN; 471 attrs |= DNS_DISPATCHATTR_CANREUSE; 472 attrmask = 0; 473 attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP; 474 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6; 475 476 ifp->nudpdispatch = ISC_MIN(ifp->mgr->udpdisp, MAX_UDP_DISPATCH); 477 for (disp = 0; disp < ifp->nudpdispatch; disp++) { 478 result = dns_dispatch_getudp_dup(ifp->mgr->dispatchmgr, 479 ifp->mgr->socketmgr, 480 ifp->mgr->taskmgr, &ifp->addr, 481 4096, UDPBUFFERS, 482 32768, 8219, 8237, 483 attrs, attrmask, 484 &ifp->udpdispatch[disp], 485 disp == 0 486 ? NULL 487 : ifp->udpdispatch[0]); 488 if (result != ISC_R_SUCCESS) { 489 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 490 "could not listen on UDP socket: %s", 491 isc_result_totext(result)); 492 goto udp_dispatch_failure; 493 } 494 495 } 496 497 result = ns_clientmgr_createclients(ifp->clientmgr, ifp->nudpdispatch, 498 ifp, false); 499 if (result != ISC_R_SUCCESS) { 500 UNEXPECTED_ERROR(__FILE__, __LINE__, 501 "UDP ns_clientmgr_createclients(): %s", 502 isc_result_totext(result)); 503 goto addtodispatch_failure; 504 } 505 506 return (ISC_R_SUCCESS); 507 508 addtodispatch_failure: 509 for (i = disp - 1; i >= 0; i--) { 510 dns_dispatch_changeattributes(ifp->udpdispatch[i], 0, 511 DNS_DISPATCHATTR_NOLISTEN); 512 dns_dispatch_detach(&(ifp->udpdispatch[i])); 513 } 514 ifp->nudpdispatch = 0; 515 516 udp_dispatch_failure: 517 return (result); 518} 519 520static isc_result_t 521ns_interface_accepttcp(ns_interface_t *ifp) { 522 isc_result_t result; 523 524 /* 525 * Open a TCP socket. 526 */ 527 result = isc_socket_create(ifp->mgr->socketmgr, 528 isc_sockaddr_pf(&ifp->addr), 529 isc_sockettype_tcp, 530 &ifp->tcpsocket); 531 if (result != ISC_R_SUCCESS) { 532 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 533 "creating TCP socket: %s", 534 isc_result_totext(result)); 535 goto tcp_socket_failure; 536 } 537 isc_socket_setname(ifp->tcpsocket, "dispatcher", NULL); 538#ifndef ISC_ALLOW_MAPPED 539 isc_socket_ipv6only(ifp->tcpsocket, true); 540#endif 541 result = isc_socket_bind(ifp->tcpsocket, &ifp->addr, 542 ISC_SOCKET_REUSEADDRESS); 543 if (result != ISC_R_SUCCESS) { 544 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 545 "binding TCP socket: %s", 546 isc_result_totext(result)); 547 goto tcp_bind_failure; 548 } 549 550 if (ifp->dscp != -1) 551 isc_socket_dscp(ifp->tcpsocket, ifp->dscp); 552 553 result = isc_socket_listen(ifp->tcpsocket, ifp->mgr->backlog); 554 if (result != ISC_R_SUCCESS) { 555 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 556 "listening on TCP socket: %s", 557 isc_result_totext(result)); 558 goto tcp_listen_failure; 559 } 560 561 /* 562 * If/when there a multiple filters listen to the 563 * result. 564 */ 565 (void)isc_socket_filter(ifp->tcpsocket, "dataready"); 566 567 result = ns_clientmgr_createclients(ifp->clientmgr, 1, ifp, true); 568 if (result != ISC_R_SUCCESS) { 569 UNEXPECTED_ERROR(__FILE__, __LINE__, 570 "TCP ns_clientmgr_createclients(): %s", 571 isc_result_totext(result)); 572 goto accepttcp_failure; 573 } 574 return (ISC_R_SUCCESS); 575 576 accepttcp_failure: 577 tcp_listen_failure: 578 tcp_bind_failure: 579 isc_socket_detach(&ifp->tcpsocket); 580 tcp_socket_failure: 581 return (result); 582} 583 584static isc_result_t 585ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, 586 const char *name, ns_interface_t **ifpret, 587 bool accept_tcp, isc_dscp_t dscp, 588 bool *addr_in_use) 589{ 590 isc_result_t result; 591 ns_interface_t *ifp = NULL; 592 REQUIRE(ifpret != NULL && *ifpret == NULL); 593 REQUIRE(addr_in_use == NULL || *addr_in_use == false); 594 595 result = ns_interface_create(mgr, addr, name, &ifp); 596 if (result != ISC_R_SUCCESS) 597 return (result); 598 599 ifp->dscp = dscp; 600 601 result = ns_interface_listenudp(ifp); 602 if (result != ISC_R_SUCCESS) { 603 if ((result == ISC_R_ADDRINUSE) && (addr_in_use != NULL)) 604 *addr_in_use = true; 605 goto cleanup_interface; 606 } 607 608 if (((mgr->sctx->options & NS_SERVER_NOTCP) == 0) && 609 accept_tcp == true) 610 { 611 result = ns_interface_accepttcp(ifp); 612 if (result != ISC_R_SUCCESS) { 613 if ((result == ISC_R_ADDRINUSE) && 614 (addr_in_use != NULL)) 615 *addr_in_use = true; 616 617 /* 618 * XXXRTH We don't currently have a way to easily stop 619 * dispatch service, so we currently return 620 * ISC_R_SUCCESS (the UDP stuff will work even if TCP 621 * creation failed). This will be fixed later. 622 */ 623 result = ISC_R_SUCCESS; 624 } 625 } 626 *ifpret = ifp; 627 return (result); 628 629 cleanup_interface: 630 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link); 631 ns_interface_detach(&ifp); 632 return (result); 633} 634 635void 636ns_interface_shutdown(ns_interface_t *ifp) { 637 if (ifp->clientmgr != NULL) 638 ns_clientmgr_destroy(&ifp->clientmgr); 639} 640 641static void 642ns_interface_destroy(ns_interface_t *ifp) { 643 isc_mem_t *mctx = ifp->mgr->mctx; 644 int disp; 645 646 REQUIRE(NS_INTERFACE_VALID(ifp)); 647 648 ns_interface_shutdown(ifp); 649 650 for (disp = 0; disp < ifp->nudpdispatch; disp++) 651 if (ifp->udpdispatch[disp] != NULL) { 652 dns_dispatch_changeattributes(ifp->udpdispatch[disp], 0, 653 DNS_DISPATCHATTR_NOLISTEN); 654 dns_dispatch_detach(&(ifp->udpdispatch[disp])); 655 } 656 657 if (ifp->tcpsocket != NULL) 658 isc_socket_detach(&ifp->tcpsocket); 659 660 isc_mutex_destroy(&ifp->lock); 661 662 ns_interfacemgr_detach(&ifp->mgr); 663 664 isc_refcount_destroy(&ifp->ntcpactive); 665 isc_refcount_destroy(&ifp->ntcpaccepting); 666 667 ifp->magic = 0; 668 isc_mem_put(mctx, ifp, sizeof(*ifp)); 669} 670 671void 672ns_interface_attach(ns_interface_t *source, ns_interface_t **target) { 673 REQUIRE(NS_INTERFACE_VALID(source)); 674 LOCK(&source->lock); 675 INSIST(source->references > 0); 676 source->references++; 677 UNLOCK(&source->lock); 678 *target = source; 679} 680 681void 682ns_interface_detach(ns_interface_t **targetp) { 683 isc_result_t need_destroy = false; 684 ns_interface_t *target = *targetp; 685 REQUIRE(target != NULL); 686 REQUIRE(NS_INTERFACE_VALID(target)); 687 LOCK(&target->lock); 688 REQUIRE(target->references > 0); 689 target->references--; 690 if (target->references == 0) 691 need_destroy = true; 692 UNLOCK(&target->lock); 693 if (need_destroy) 694 ns_interface_destroy(target); 695 *targetp = NULL; 696} 697 698/*% 699 * Search the interface list for an interface whose address and port 700 * both match those of 'addr'. Return a pointer to it, or NULL if not found. 701 */ 702static ns_interface_t * 703find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) { 704 ns_interface_t *ifp; 705 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; 706 ifp = ISC_LIST_NEXT(ifp, link)) { 707 if (isc_sockaddr_equal(&ifp->addr, addr)) 708 break; 709 } 710 return (ifp); 711} 712 713/*% 714 * Remove any interfaces whose generation number is not the current one. 715 */ 716static void 717purge_old_interfaces(ns_interfacemgr_t *mgr) { 718 ns_interface_t *ifp, *next; 719 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) { 720 INSIST(NS_INTERFACE_VALID(ifp)); 721 next = ISC_LIST_NEXT(ifp, link); 722 if (ifp->generation != mgr->generation) { 723 char sabuf[256]; 724 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link); 725 isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf)); 726 isc_log_write(IFMGR_COMMON_LOGARGS, 727 ISC_LOG_INFO, 728 "no longer listening on %s", sabuf); 729 ns_interface_shutdown(ifp); 730 ns_interface_detach(&ifp); 731 } 732 } 733} 734 735static isc_result_t 736clearacl(isc_mem_t *mctx, dns_acl_t **aclp) { 737 dns_acl_t *newacl = NULL; 738 isc_result_t result; 739 result = dns_acl_create(mctx, 0, &newacl); 740 if (result != ISC_R_SUCCESS) 741 return (result); 742 dns_acl_detach(aclp); 743 dns_acl_attach(newacl, aclp); 744 dns_acl_detach(&newacl); 745 return (ISC_R_SUCCESS); 746} 747 748static bool 749listenon_is_ip6_any(ns_listenelt_t *elt) { 750 REQUIRE(elt && elt->acl); 751 return dns_acl_isany(elt->acl); 752} 753 754static isc_result_t 755setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) { 756 isc_result_t result; 757 unsigned int prefixlen; 758 isc_netaddr_t *netaddr; 759 760 netaddr = &interface->address; 761 762 /* First add localhost address */ 763 prefixlen = (netaddr->family == AF_INET) ? 32 : 128; 764 result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable, 765 netaddr, prefixlen, true); 766 if (result != ISC_R_SUCCESS) 767 return (result); 768 769 /* Then add localnets prefix */ 770 result = isc_netaddr_masktoprefixlen(&interface->netmask, 771 &prefixlen); 772 773 /* Non contiguous netmasks not allowed by IPv6 arch. */ 774 if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6) 775 return (result); 776 777 if (result != ISC_R_SUCCESS) { 778 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, 779 "omitting IPv4 interface %s from " 780 "localnets ACL: %s", interface->name, 781 isc_result_totext(result)); 782 return (ISC_R_SUCCESS); 783 } 784 785 if (prefixlen == 0U) { 786 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, 787 "omitting %s interface %s from localnets ACL: " 788 "zero prefix length detected", 789 (netaddr->family == AF_INET) ? "IPv4" : "IPv6", 790 interface->name); 791 return (ISC_R_SUCCESS); 792 } 793 794 result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable, 795 netaddr, prefixlen, true); 796 if (result != ISC_R_SUCCESS) 797 return (result); 798 799 return (ISC_R_SUCCESS); 800} 801 802static void 803setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface, 804 in_port_t port) 805{ 806 isc_sockaddr_t *addr; 807 isc_sockaddr_t *old; 808 809 addr = isc_mem_get(mgr->mctx, sizeof(*addr)); 810 if (addr == NULL) 811 return; 812 813 isc_sockaddr_fromnetaddr(addr, &interface->address, port); 814 815 for (old = ISC_LIST_HEAD(mgr->listenon); 816 old != NULL; 817 old = ISC_LIST_NEXT(old, link)) 818 if (isc_sockaddr_equal(addr, old)) 819 break; 820 821 if (old != NULL) 822 isc_mem_put(mgr->mctx, addr, sizeof(*addr)); 823 else 824 ISC_LIST_APPEND(mgr->listenon, addr, link); 825} 826 827static void 828clearlistenon(ns_interfacemgr_t *mgr) { 829 isc_sockaddr_t *old; 830 831 old = ISC_LIST_HEAD(mgr->listenon); 832 while (old != NULL) { 833 ISC_LIST_UNLINK(mgr->listenon, old, link); 834 isc_mem_put(mgr->mctx, old, sizeof(*old)); 835 old = ISC_LIST_HEAD(mgr->listenon); 836 } 837} 838 839static isc_result_t 840do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, 841 bool verbose) 842{ 843 isc_interfaceiter_t *iter = NULL; 844 bool scan_ipv4 = false; 845 bool scan_ipv6 = false; 846 bool adjusting = false; 847 bool ipv6only = true; 848 bool ipv6pktinfo = true; 849 isc_result_t result; 850 isc_netaddr_t zero_address, zero_address6; 851 ns_listenelt_t *le; 852 isc_sockaddr_t listen_addr; 853 ns_interface_t *ifp; 854 bool log_explicit = false; 855 bool dolistenon; 856 char sabuf[ISC_SOCKADDR_FORMATSIZE]; 857 bool tried_listening; 858 bool all_addresses_in_use; 859 860 if (ext_listen != NULL) 861 adjusting = true; 862 863 if (isc_net_probeipv6() == ISC_R_SUCCESS) 864 scan_ipv6 = true; 865 else if ((mgr->sctx->options & NS_SERVER_DISABLE6) == 0) 866 isc_log_write(IFMGR_COMMON_LOGARGS, 867 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), 868 "no IPv6 interfaces found"); 869 870 if (isc_net_probeipv4() == ISC_R_SUCCESS) 871 scan_ipv4 = true; 872 else if ((mgr->sctx->options & NS_SERVER_DISABLE4) == 0) 873 isc_log_write(IFMGR_COMMON_LOGARGS, 874 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), 875 "no IPv4 interfaces found"); 876 877 /* 878 * A special, but typical case; listen-on-v6 { any; }. 879 * When we can make the socket IPv6-only, open a single wildcard 880 * socket for IPv6 communication. Otherwise, make separate socket 881 * for each IPv6 address in order to avoid accepting IPv4 packets 882 * as the form of mapped addresses unintentionally unless explicitly 883 * allowed. 884 */ 885#ifndef ISC_ALLOW_MAPPED 886 if (scan_ipv6 == true && 887 isc_net_probe_ipv6only() != ISC_R_SUCCESS) { 888 ipv6only = false; 889 log_explicit = true; 890 } 891#endif 892 if (scan_ipv6 == true && 893 isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) { 894 ipv6pktinfo = false; 895 log_explicit = true; 896 } 897 if (scan_ipv6 == true && ipv6only && ipv6pktinfo) { 898 for (le = ISC_LIST_HEAD(mgr->listenon6->elts); 899 le != NULL; 900 le = ISC_LIST_NEXT(le, link)) { 901 struct in6_addr in6a; 902 903 if (!listenon_is_ip6_any(le)) 904 continue; 905 906 in6a = in6addr_any; 907 isc_sockaddr_fromin6(&listen_addr, &in6a, le->port); 908 909 ifp = find_matching_interface(mgr, &listen_addr); 910 if (ifp != NULL) { 911 ifp->generation = mgr->generation; 912 if (le->dscp != -1 && ifp->dscp == -1) 913 ifp->dscp = le->dscp; 914 else if (le->dscp != ifp->dscp) { 915 isc_sockaddr_format(&listen_addr, 916 sabuf, 917 sizeof(sabuf)); 918 isc_log_write(IFMGR_COMMON_LOGARGS, 919 ISC_LOG_WARNING, 920 "%s: conflicting DSCP " 921 "values, using %d", 922 sabuf, ifp->dscp); 923 } 924 } else { 925 isc_log_write(IFMGR_COMMON_LOGARGS, 926 ISC_LOG_INFO, 927 "listening on IPv6 " 928 "interfaces, port %u", 929 le->port); 930 result = ns_interface_setup(mgr, &listen_addr, 931 "<any>", &ifp, 932 true, 933 le->dscp, 934 NULL); 935 if (result == ISC_R_SUCCESS) 936 ifp->flags |= NS_INTERFACEFLAG_ANYADDR; 937 else 938 isc_log_write(IFMGR_COMMON_LOGARGS, 939 ISC_LOG_ERROR, 940 "listening on all IPv6 " 941 "interfaces failed"); 942 /* Continue. */ 943 } 944 } 945 } 946 947 isc_netaddr_any(&zero_address); 948 isc_netaddr_any6(&zero_address6); 949 950 result = isc_interfaceiter_create(mgr->mctx, &iter); 951 if (result != ISC_R_SUCCESS) 952 return (result); 953 954 if (adjusting == false) { 955 result = clearacl(mgr->mctx, &mgr->aclenv.localhost); 956 if (result != ISC_R_SUCCESS) 957 goto cleanup_iter; 958 result = clearacl(mgr->mctx, &mgr->aclenv.localnets); 959 if (result != ISC_R_SUCCESS) 960 goto cleanup_iter; 961 clearlistenon(mgr); 962 } 963 964 tried_listening = false; 965 all_addresses_in_use = true; 966 for (result = isc_interfaceiter_first(iter); 967 result == ISC_R_SUCCESS; 968 result = isc_interfaceiter_next(iter)) 969 { 970 isc_interface_t interface; 971 ns_listenlist_t *ll; 972 unsigned int family; 973 974 result = isc_interfaceiter_current(iter, &interface); 975 if (result != ISC_R_SUCCESS) 976 break; 977 978 family = interface.address.family; 979 if (family != AF_INET && family != AF_INET6) 980 continue; 981 if (scan_ipv4 == false && family == AF_INET) 982 continue; 983 if (scan_ipv6 == false && family == AF_INET6) 984 continue; 985 986 /* 987 * Test for the address being nonzero rather than testing 988 * INTERFACE_F_UP, because on some systems the latter 989 * follows the media state and we could end up ignoring 990 * the interface for an entire rescan interval due to 991 * a temporary media glitch at rescan time. 992 */ 993 if (family == AF_INET && 994 isc_netaddr_equal(&interface.address, &zero_address)) { 995 continue; 996 } 997 if (family == AF_INET6 && 998 isc_netaddr_equal(&interface.address, &zero_address6)) { 999 continue; 1000 } 1001 1002 if (adjusting == false) { 1003 /* 1004 * If running with -T fixedlocal, then we only 1005 * want 127.0.0.1 and ::1 in the localhost ACL. 1006 */ 1007 if (((mgr->sctx->options & 1008 NS_SERVER_FIXEDLOCAL) != 0) && 1009 !isc_netaddr_isloopback(&interface.address)) 1010 { 1011 goto listenon; 1012 } 1013 1014 result = setup_locals(mgr, &interface); 1015 if (result != ISC_R_SUCCESS) 1016 goto ignore_interface; 1017 } 1018 1019 listenon: 1020 ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6; 1021 dolistenon = true; 1022 for (le = ISC_LIST_HEAD(ll->elts); 1023 le != NULL; 1024 le = ISC_LIST_NEXT(le, link)) 1025 { 1026 int match; 1027 bool ipv6_wildcard = false; 1028 isc_netaddr_t listen_netaddr; 1029 isc_sockaddr_t listen_sockaddr; 1030 1031 /* 1032 * Construct a socket address for this IP/port 1033 * combination. 1034 */ 1035 if (family == AF_INET) { 1036 isc_netaddr_fromin(&listen_netaddr, 1037 &interface.address.type.in); 1038 } else { 1039 isc_netaddr_fromin6(&listen_netaddr, 1040 &interface.address.type.in6); 1041 isc_netaddr_setzone(&listen_netaddr, 1042 interface.address.zone); 1043 } 1044 isc_sockaddr_fromnetaddr(&listen_sockaddr, 1045 &listen_netaddr, 1046 le->port); 1047 1048 /* 1049 * See if the address matches the listen-on statement; 1050 * if not, ignore the interface. 1051 */ 1052 (void)dns_acl_match(&listen_netaddr, NULL, le->acl, 1053 &mgr->aclenv, &match, NULL); 1054 if (match <= 0) { 1055 continue; 1056 } 1057 1058 if (adjusting == false && dolistenon == true) { 1059 setup_listenon(mgr, &interface, le->port); 1060 dolistenon = false; 1061 } 1062 1063 /* 1064 * The case of "any" IPv6 address will require 1065 * special considerations later, so remember it. 1066 */ 1067 if (family == AF_INET6 && ipv6only && ipv6pktinfo && 1068 listenon_is_ip6_any(le)) 1069 ipv6_wildcard = true; 1070 1071 /* 1072 * When adjusting interfaces with extra a listening 1073 * list, see if the address matches the extra list. 1074 * If it does, and is also covered by a wildcard 1075 * interface, we need to listen on the address 1076 * explicitly. 1077 */ 1078 if (adjusting == true) { 1079 ns_listenelt_t *ele; 1080 1081 match = 0; 1082 for (ele = ISC_LIST_HEAD(ext_listen->elts); 1083 ele != NULL; 1084 ele = ISC_LIST_NEXT(ele, link)) 1085 { 1086 (void)dns_acl_match(&listen_netaddr, 1087 NULL, ele->acl, 1088 NULL, &match, 1089 NULL); 1090 if (match > 0 && 1091 (ele->port == le->port || 1092 ele->port == 0)) 1093 { 1094 break; 1095 } else { 1096 match = 0; 1097 } 1098 } 1099 if (ipv6_wildcard == true && match == 0) 1100 continue; 1101 } 1102 1103 ifp = find_matching_interface(mgr, &listen_sockaddr); 1104 if (ifp != NULL) { 1105 ifp->generation = mgr->generation; 1106 if (le->dscp != -1 && ifp->dscp == -1) 1107 ifp->dscp = le->dscp; 1108 else if (le->dscp != ifp->dscp) { 1109 isc_sockaddr_format(&listen_sockaddr, 1110 sabuf, 1111 sizeof(sabuf)); 1112 isc_log_write(IFMGR_COMMON_LOGARGS, 1113 ISC_LOG_WARNING, 1114 "%s: conflicting DSCP " 1115 "values, using %d", 1116 sabuf, ifp->dscp); 1117 } 1118 } else { 1119 bool addr_in_use = false; 1120 1121 if (adjusting == false && 1122 ipv6_wildcard == true) 1123 continue; 1124 1125 if (log_explicit && family == AF_INET6 && 1126 !adjusting && listenon_is_ip6_any(le)) { 1127 isc_log_write(IFMGR_COMMON_LOGARGS, 1128 verbose ? ISC_LOG_INFO : 1129 ISC_LOG_DEBUG(1), 1130 "IPv6 socket API is " 1131 "incomplete; explicitly " 1132 "binding to each IPv6 " 1133 "address separately"); 1134 log_explicit = false; 1135 } 1136 isc_sockaddr_format(&listen_sockaddr, 1137 sabuf, sizeof(sabuf)); 1138 isc_log_write(IFMGR_COMMON_LOGARGS, 1139 ISC_LOG_INFO, 1140 "%s" 1141 "listening on %s interface " 1142 "%s, %s", 1143 (adjusting == true) ? 1144 "additionally " : "", 1145 (family == AF_INET) ? 1146 "IPv4" : "IPv6", 1147 interface.name, sabuf); 1148 1149 result = ns_interface_setup(mgr, 1150 &listen_sockaddr, 1151 interface.name, 1152 &ifp, 1153 (adjusting == true) ? 1154 false : true, 1155 le->dscp, 1156 &addr_in_use); 1157 1158 tried_listening = true; 1159 if (!addr_in_use) 1160 all_addresses_in_use = false; 1161 1162 if (result != ISC_R_SUCCESS) { 1163 isc_log_write(IFMGR_COMMON_LOGARGS, 1164 ISC_LOG_ERROR, 1165 "creating %s interface " 1166 "%s failed; interface " 1167 "ignored", 1168 (family == AF_INET) ? 1169 "IPv4" : "IPv6", 1170 interface.name); 1171 } 1172 /* Continue. */ 1173 } 1174 1175 } 1176 continue; 1177 1178 ignore_interface: 1179 isc_log_write(IFMGR_COMMON_LOGARGS, 1180 ISC_LOG_ERROR, 1181 "ignoring %s interface %s: %s", 1182 (family == AF_INET) ? "IPv4" : "IPv6", 1183 interface.name, isc_result_totext(result)); 1184 continue; 1185 } 1186 if (result != ISC_R_NOMORE) 1187 UNEXPECTED_ERROR(__FILE__, __LINE__, 1188 "interface iteration failed: %s", 1189 isc_result_totext(result)); 1190 else 1191 result = ((tried_listening && all_addresses_in_use) ? 1192 ISC_R_ADDRINUSE : ISC_R_SUCCESS); 1193 cleanup_iter: 1194 isc_interfaceiter_destroy(&iter); 1195 return (result); 1196} 1197 1198static isc_result_t 1199ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, 1200 bool verbose) 1201{ 1202 isc_result_t result; 1203 bool purge = true; 1204 1205 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1206 1207 mgr->generation++; /* Increment the generation count. */ 1208 1209 result = do_scan(mgr, ext_listen, verbose); 1210 if ((result != ISC_R_SUCCESS) && (result != ISC_R_ADDRINUSE)) 1211 purge = false; 1212 1213 /* 1214 * Now go through the interface list and delete anything that 1215 * does not have the current generation number. This is 1216 * how we catch interfaces that go away or change their 1217 * addresses. 1218 */ 1219 if (purge) 1220 purge_old_interfaces(mgr); 1221 1222 /* 1223 * Warn if we are not listening on any interface. 1224 */ 1225 if (ext_listen == NULL && 1226 ISC_LIST_EMPTY(mgr->interfaces)) 1227 { 1228 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, 1229 "not listening on any interfaces"); 1230 } 1231 1232 return (result); 1233} 1234 1235bool 1236ns_interfacemgr_islistening(ns_interfacemgr_t *mgr) { 1237 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1238 1239 return (ISC_LIST_EMPTY(mgr->interfaces) ? false : true); 1240} 1241 1242isc_result_t 1243ns_interfacemgr_scan(ns_interfacemgr_t *mgr, bool verbose) { 1244 isc_result_t result; 1245 bool unlock = false; 1246 1247 /* 1248 * Check for success because we may already be task-exclusive 1249 * at this point. Only if we succeed at obtaining an exclusive 1250 * lock now will we need to relinquish it later. 1251 */ 1252 result = isc_task_beginexclusive(mgr->excl); 1253 if (result == ISC_R_SUCCESS) 1254 unlock = true; 1255 1256 result = ns_interfacemgr_scan0(mgr, NULL, verbose); 1257 1258 if (unlock) 1259 isc_task_endexclusive(mgr->excl); 1260 1261 return (result); 1262} 1263 1264isc_result_t 1265ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list, 1266 bool verbose) 1267{ 1268 return (ns_interfacemgr_scan0(mgr, list, verbose)); 1269} 1270 1271void 1272ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { 1273 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1274 1275 LOCK(&mgr->lock); 1276 ns_listenlist_detach(&mgr->listenon4); 1277 ns_listenlist_attach(value, &mgr->listenon4); 1278 UNLOCK(&mgr->lock); 1279} 1280 1281void 1282ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { 1283 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1284 1285 LOCK(&mgr->lock); 1286 ns_listenlist_detach(&mgr->listenon6); 1287 ns_listenlist_attach(value, &mgr->listenon6); 1288 UNLOCK(&mgr->lock); 1289} 1290 1291void 1292ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) { 1293 ns_interface_t *interface; 1294 1295 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1296 1297 LOCK(&mgr->lock); 1298 interface = ISC_LIST_HEAD(mgr->interfaces); 1299 while (interface != NULL) { 1300 if (interface->clientmgr != NULL) 1301 ns_client_dumprecursing(f, interface->clientmgr); 1302 interface = ISC_LIST_NEXT(interface, link); 1303 } 1304 UNLOCK(&mgr->lock); 1305} 1306 1307bool 1308ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, 1309 const isc_sockaddr_t *addr) 1310{ 1311 isc_sockaddr_t *old; 1312 1313 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1314 1315 for (old = ISC_LIST_HEAD(mgr->listenon); 1316 old != NULL; 1317 old = ISC_LIST_NEXT(old, link)) 1318 if (isc_sockaddr_equal(old, addr)) 1319 return (true); 1320 return (false); 1321} 1322 1323ns_interface_t * 1324ns__interfacemgr_getif(ns_interfacemgr_t *mgr) { 1325 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1326 1327 return (ISC_LIST_HEAD(mgr->interfaces)); 1328} 1329 1330ns_interface_t * 1331ns__interfacemgr_nextif(ns_interface_t *ifp) { 1332 return (ISC_LIST_NEXT(ifp, link)); 1333} 1334