interfacemgr.c revision 1.16
1/* $NetBSD: interfacemgr.c,v 1.16 2024/02/21 22:52:46 christos Exp $ */ 2 3/* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16/*! \file */ 17 18#include <stdbool.h> 19 20#include <isc/interfaceiter.h> 21#include <isc/netmgr.h> 22#include <isc/os.h> 23#include <isc/random.h> 24#include <isc/string.h> 25#include <isc/task.h> 26#include <isc/util.h> 27 28#include <dns/acl.h> 29#include <dns/dispatch.h> 30 31#include <ns/client.h> 32#include <ns/interfacemgr.h> 33#include <ns/log.h> 34#include <ns/server.h> 35#include <ns/stats.h> 36 37#ifdef HAVE_NET_ROUTE_H 38#include <net/route.h> 39#if defined(RTM_VERSION) && defined(RTM_NEWADDR) && defined(RTM_DELADDR) 40#define MSGHDR rt_msghdr 41#define MSGTYPE rtm_type 42#endif /* if defined(RTM_VERSION) && defined(RTM_NEWADDR) && \ 43 * defined(RTM_DELADDR) */ 44#endif /* ifdef HAVE_NET_ROUTE_H */ 45 46#if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) 47#define LINUX_NETLINK_AVAILABLE 48#include <linux/netlink.h> 49#include <linux/rtnetlink.h> 50#if defined(RTM_NEWADDR) && defined(RTM_DELADDR) 51#define MSGHDR nlmsghdr 52#define MSGTYPE nlmsg_type 53#endif /* if defined(RTM_NEWADDR) && defined(RTM_DELADDR) */ 54#endif /* if defined(HAVE_LINUX_NETLINK_H) && defined(HAVE_LINUX_RTNETLINK_H) \ 55 */ 56 57#define LISTENING(ifp) (((ifp)->flags & NS_INTERFACEFLAG_LISTENING) != 0) 58 59#ifdef TUNE_LARGE 60#define UDPBUFFERS 32768 61#else /* ifdef TUNE_LARGE */ 62#define UDPBUFFERS 1000 63#endif /* TUNE_LARGE */ 64 65#define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G') 66#define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC) 67 68#define IFMGR_COMMON_LOGARGS \ 69 ns_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR 70 71/*% nameserver interface manager structure */ 72struct ns_interfacemgr { 73 unsigned int magic; /*%< Magic number */ 74 isc_refcount_t references; 75 isc_mutex_t lock; 76 isc_mem_t *mctx; /*%< Memory context */ 77 ns_server_t *sctx; /*%< Server context */ 78 isc_taskmgr_t *taskmgr; /*%< Task manager */ 79 isc_task_t *task; /*%< Task */ 80 isc_timermgr_t *timermgr; /*%< Timer manager */ 81 isc_nm_t *nm; /*%< Net manager */ 82 int ncpus; /*%< Number of workers */ 83 dns_dispatchmgr_t *dispatchmgr; 84 unsigned int generation; /*%< Current generation no */ 85 ns_listenlist_t *listenon4; 86 ns_listenlist_t *listenon6; 87 dns_aclenv_t *aclenv; /*%< Localhost/localnets ACLs */ 88 ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces */ 89 ISC_LIST(isc_sockaddr_t) listenon; 90 int backlog; /*%< Listen queue size */ 91 atomic_bool shuttingdown; /*%< Interfacemgr shutting down */ 92 ns_clientmgr_t **clientmgrs; /*%< Client managers */ 93 isc_nmhandle_t *route; 94}; 95 96static void 97purge_old_interfaces(ns_interfacemgr_t *mgr); 98 99static void 100clearlistenon(ns_interfacemgr_t *mgr); 101 102static bool 103need_rescan(ns_interfacemgr_t *mgr, struct MSGHDR *rtm, size_t len) { 104 if (rtm->MSGTYPE != RTM_NEWADDR && rtm->MSGTYPE != RTM_DELADDR) { 105 return (false); 106 } 107 108#ifndef LINUX_NETLINK_AVAILABLE 109 UNUSED(mgr); 110 UNUSED(len); 111 /* On most systems, any NEWADDR or DELADDR means we rescan */ 112 return (true); 113#else /* LINUX_NETLINK_AVAILABLE */ 114 /* ...but on linux we need to check the messages more carefully */ 115 for (struct MSGHDR *nlh = rtm; 116 NLMSG_OK(nlh, len) && nlh->nlmsg_type != NLMSG_DONE; 117 nlh = NLMSG_NEXT(nlh, len)) 118 { 119 struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA(nlh); 120 struct rtattr *rth = IFA_RTA(ifa); 121 size_t rtl = IFA_PAYLOAD(nlh); 122 123 while (rtl > 0 && RTA_OK(rth, rtl)) { 124 /* 125 * Look for IFA_ADDRESS to detect IPv6 interface 126 * state changes. 127 */ 128 if (rth->rta_type == IFA_ADDRESS && 129 ifa->ifa_family == AF_INET6) 130 { 131 bool existed = false; 132 bool was_listening = false; 133 isc_netaddr_t addr = { 0 }; 134 ns_interface_t *ifp = NULL; 135 136 isc_netaddr_fromin6(&addr, RTA_DATA(rth)); 137 INSIST(isc_netaddr_getzone(&addr) == 0); 138 139 /* 140 * Check whether we were listening on the 141 * address. We need to do this as the 142 * Linux kernel seems to issue messages 143 * containing IFA_ADDRESS far more often 144 * than the actual state changes (on 145 * router advertisements?) 146 */ 147 LOCK(&mgr->lock); 148 for (ifp = ISC_LIST_HEAD(mgr->interfaces); 149 ifp != NULL; 150 ifp = ISC_LIST_NEXT(ifp, link)) 151 { 152 isc_netaddr_t tmp = { 0 }; 153 isc_netaddr_fromsockaddr(&tmp, 154 &ifp->addr); 155 if (tmp.family != AF_INET6) { 156 continue; 157 } 158 159 /* 160 * We have to nullify the zone (IPv6 161 * scope ID) because we haven't got one 162 * from the kernel. Otherwise match 163 * could fail even for an existing 164 * address. 165 */ 166 isc_netaddr_setzone(&tmp, 0); 167 if (isc_netaddr_equal(&tmp, &addr)) { 168 was_listening = LISTENING(ifp); 169 existed = true; 170 break; 171 } 172 } 173 UNLOCK(&mgr->lock); 174 175 /* 176 * Do rescan if the state of the interface 177 * has changed. 178 */ 179 if ((!existed && rtm->MSGTYPE == RTM_NEWADDR) || 180 (existed && was_listening && 181 rtm->MSGTYPE == RTM_DELADDR)) 182 { 183 return (true); 184 } 185 } else if (rth->rta_type == IFA_ADDRESS && 186 ifa->ifa_family == AF_INET) 187 { 188 /* 189 * It seems that the IPv4 P2P link state 190 * has changed. 191 */ 192 return (true); 193 } else if (rth->rta_type == IFA_LOCAL) { 194 /* 195 * Local address state has changed - do 196 * rescan. 197 */ 198 return (true); 199 } 200 rth = RTA_NEXT(rth, rtl); 201 } 202 } 203#endif /* LINUX_NETLINK_AVAILABLE */ 204 205 return (false); 206} 207 208static void 209route_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, 210 void *arg) { 211 ns_interfacemgr_t *mgr = (ns_interfacemgr_t *)arg; 212 struct MSGHDR *rtm = NULL; 213 size_t rtmlen; 214 215 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_DEBUG(9), "route_recv: %s", 216 isc_result_totext(eresult)); 217 218 if (handle == NULL) { 219 return; 220 } 221 222 if (eresult != ISC_R_SUCCESS) { 223 if (eresult != ISC_R_CANCELED && eresult != ISC_R_SHUTTINGDOWN) 224 { 225 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 226 "automatic interface scanning " 227 "terminated: %s", 228 isc_result_totext(eresult)); 229 } 230 isc_nmhandle_detach(&mgr->route); 231 ns_interfacemgr_detach(&mgr); 232 return; 233 } 234 235 rtm = (struct MSGHDR *)region->base; 236 rtmlen = region->length; 237 238#ifdef RTM_VERSION 239 if (rtm->rtm_version != RTM_VERSION) { 240 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 241 "automatic interface rescanning disabled: " 242 "rtm->rtm_version mismatch (%u != %u) " 243 "recompile required", 244 rtm->rtm_version, RTM_VERSION); 245 isc_nmhandle_detach(&mgr->route); 246 ns_interfacemgr_detach(&mgr); 247 return; 248 } 249#endif /* ifdef RTM_VERSION */ 250 251 REQUIRE(mgr->route != NULL); 252 253 if (need_rescan(mgr, rtm, rtmlen) && mgr->sctx->interface_auto) { 254 ns_interfacemgr_scan(mgr, false, false); 255 } 256 257 isc_nm_read(handle, route_recv, mgr); 258 return; 259} 260 261static void 262route_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { 263 ns_interfacemgr_t *mgr = (ns_interfacemgr_t *)arg; 264 265 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_DEBUG(9), 266 "route_connected: %s", isc_result_totext(eresult)); 267 268 if (eresult != ISC_R_SUCCESS) { 269 ns_interfacemgr_detach(&mgr); 270 return; 271 } 272 273 INSIST(mgr->route == NULL); 274 275 isc_nmhandle_attach(handle, &mgr->route); 276 isc_nm_read(handle, route_recv, mgr); 277} 278 279isc_result_t 280ns_interfacemgr_create(isc_mem_t *mctx, ns_server_t *sctx, 281 isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr, 282 isc_nm_t *nm, dns_dispatchmgr_t *dispatchmgr, 283 isc_task_t *task, dns_geoip_databases_t *geoip, 284 int ncpus, bool scan, ns_interfacemgr_t **mgrp) { 285 isc_result_t result; 286 ns_interfacemgr_t *mgr = NULL; 287 288 UNUSED(task); 289 290 REQUIRE(mctx != NULL); 291 REQUIRE(mgrp != NULL); 292 REQUIRE(*mgrp == NULL); 293 294 mgr = isc_mem_get(mctx, sizeof(*mgr)); 295 *mgr = (ns_interfacemgr_t){ .taskmgr = taskmgr, 296 .timermgr = timermgr, 297 .nm = nm, 298 .dispatchmgr = dispatchmgr, 299 .generation = 1, 300 .ncpus = ncpus }; 301 302 isc_mem_attach(mctx, &mgr->mctx); 303 ns_server_attach(sctx, &mgr->sctx); 304 305 isc_mutex_init(&mgr->lock); 306 307 result = isc_task_create_bound(taskmgr, 0, &mgr->task, 0); 308 if (result != ISC_R_SUCCESS) { 309 goto cleanup_lock; 310 } 311 312 atomic_init(&mgr->shuttingdown, false); 313 314 ISC_LIST_INIT(mgr->interfaces); 315 ISC_LIST_INIT(mgr->listenon); 316 317 /* 318 * The listen-on lists are initially empty. 319 */ 320 result = ns_listenlist_create(mctx, &mgr->listenon4); 321 if (result != ISC_R_SUCCESS) { 322 goto cleanup_task; 323 } 324 ns_listenlist_attach(mgr->listenon4, &mgr->listenon6); 325 326 result = dns_aclenv_create(mctx, &mgr->aclenv); 327 if (result != ISC_R_SUCCESS) { 328 goto cleanup_listenon; 329 } 330#if defined(HAVE_GEOIP2) 331 mgr->aclenv->geoip = geoip; 332#else /* if defined(HAVE_GEOIP2) */ 333 UNUSED(geoip); 334#endif /* if defined(HAVE_GEOIP2) */ 335 336 isc_refcount_init(&mgr->references, 1); 337 mgr->magic = IFMGR_MAGIC; 338 *mgrp = mgr; 339 340 mgr->clientmgrs = isc_mem_get(mgr->mctx, 341 mgr->ncpus * sizeof(mgr->clientmgrs[0])); 342 for (size_t i = 0; i < (size_t)mgr->ncpus; i++) { 343 result = ns_clientmgr_create(mgr->sctx, mgr->taskmgr, 344 mgr->timermgr, mgr->aclenv, (int)i, 345 &mgr->clientmgrs[i]); 346 RUNTIME_CHECK(result == ISC_R_SUCCESS); 347 } 348 349 if (scan) { 350 ns_interfacemgr_t *imgr = NULL; 351 352 ns_interfacemgr_attach(mgr, &imgr); 353 354 result = isc_nm_routeconnect(nm, route_connected, imgr, 0); 355 if (result == ISC_R_NOTIMPLEMENTED) { 356 ns_interfacemgr_detach(&imgr); 357 } 358 if (result != ISC_R_SUCCESS) { 359 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, 360 "unable to open route socket: %s", 361 isc_result_totext(result)); 362 } 363 } 364 365 return (ISC_R_SUCCESS); 366 367cleanup_listenon: 368 ns_listenlist_detach(&mgr->listenon4); 369 ns_listenlist_detach(&mgr->listenon6); 370cleanup_task: 371 isc_task_detach(&mgr->task); 372cleanup_lock: 373 isc_mutex_destroy(&mgr->lock); 374 ns_server_detach(&mgr->sctx); 375 isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr)); 376 return (result); 377} 378 379static void 380ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) { 381 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 382 383 isc_refcount_destroy(&mgr->references); 384 385 dns_aclenv_detach(&mgr->aclenv); 386 ns_listenlist_detach(&mgr->listenon4); 387 ns_listenlist_detach(&mgr->listenon6); 388 clearlistenon(mgr); 389 isc_mutex_destroy(&mgr->lock); 390 for (size_t i = 0; i < (size_t)mgr->ncpus; i++) { 391 ns_clientmgr_detach(&mgr->clientmgrs[i]); 392 } 393 isc_mem_put(mgr->mctx, mgr->clientmgrs, 394 mgr->ncpus * sizeof(mgr->clientmgrs[0])); 395 396 if (mgr->sctx != NULL) { 397 ns_server_detach(&mgr->sctx); 398 } 399 isc_task_detach(&mgr->task); 400 mgr->magic = 0; 401 isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr)); 402} 403 404void 405ns_interfacemgr_setbacklog(ns_interfacemgr_t *mgr, int backlog) { 406 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 407 LOCK(&mgr->lock); 408 mgr->backlog = backlog; 409 UNLOCK(&mgr->lock); 410} 411 412dns_aclenv_t * 413ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) { 414 dns_aclenv_t *aclenv = NULL; 415 416 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 417 418 LOCK(&mgr->lock); 419 aclenv = mgr->aclenv; 420 UNLOCK(&mgr->lock); 421 422 return (aclenv); 423} 424 425void 426ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) { 427 REQUIRE(NS_INTERFACEMGR_VALID(source)); 428 isc_refcount_increment(&source->references); 429 *target = source; 430} 431 432void 433ns_interfacemgr_detach(ns_interfacemgr_t **targetp) { 434 ns_interfacemgr_t *target = *targetp; 435 *targetp = NULL; 436 REQUIRE(target != NULL); 437 REQUIRE(NS_INTERFACEMGR_VALID(target)); 438 if (isc_refcount_decrement(&target->references) == 1) { 439 ns_interfacemgr_destroy(target); 440 } 441} 442 443void 444ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) { 445 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 446 447 /*% 448 * Shut down and detach all interfaces. 449 * By incrementing the generation count, we make 450 * purge_old_interfaces() consider all interfaces "old". 451 */ 452 mgr->generation++; 453 atomic_store(&mgr->shuttingdown, true); 454 455 purge_old_interfaces(mgr); 456 457 if (mgr->route != NULL) { 458 isc_nm_cancelread(mgr->route); 459 } 460 461 for (size_t i = 0; i < (size_t)mgr->ncpus; i++) { 462 ns_clientmgr_shutdown(mgr->clientmgrs[i]); 463 } 464} 465 466static void 467interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, const char *name, 468 ns_interface_t **ifpret) { 469 ns_interface_t *ifp = NULL; 470 471 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 472 473 ifp = isc_mem_get(mgr->mctx, sizeof(*ifp)); 474 *ifp = (ns_interface_t){ .generation = mgr->generation, .addr = *addr }; 475 476 strlcpy(ifp->name, name, sizeof(ifp->name)); 477 478 isc_mutex_init(&ifp->lock); 479 480 isc_refcount_init(&ifp->ntcpaccepting, 0); 481 isc_refcount_init(&ifp->ntcpactive, 0); 482 483 ISC_LINK_INIT(ifp, link); 484 485 ns_interfacemgr_attach(mgr, &ifp->mgr); 486 ifp->magic = IFACE_MAGIC; 487 488 LOCK(&mgr->lock); 489 ISC_LIST_APPEND(mgr->interfaces, ifp, link); 490 UNLOCK(&mgr->lock); 491 492 *ifpret = ifp; 493} 494 495static isc_result_t 496ns_interface_listenudp(ns_interface_t *ifp) { 497 isc_result_t result; 498 499 /* Reserve space for an ns_client_t with the netmgr handle */ 500 result = isc_nm_listenudp(ifp->mgr->nm, &ifp->addr, ns__client_request, 501 ifp, sizeof(ns_client_t), 502 &ifp->udplistensocket); 503 return (result); 504} 505 506static isc_result_t 507ns_interface_listentcp(ns_interface_t *ifp) { 508 isc_result_t result; 509 510 result = isc_nm_listentcpdns( 511 ifp->mgr->nm, &ifp->addr, ns__client_request, ifp, 512 ns__client_tcpconn, ifp, sizeof(ns_client_t), ifp->mgr->backlog, 513 &ifp->mgr->sctx->tcpquota, &ifp->tcplistensocket); 514 if (result != ISC_R_SUCCESS) { 515 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 516 "creating TCP socket: %s", 517 isc_result_totext(result)); 518 } 519 520 /* 521 * We call this now to update the tcp-highwater statistic: 522 * this is necessary because we are adding to the TCP quota just 523 * by listening. 524 */ 525 result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp); 526 if (result != ISC_R_SUCCESS) { 527 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 528 "connecting TCP socket: %s", 529 isc_result_totext(result)); 530 } 531 532 return (result); 533} 534 535/* 536 * XXXWPK we should probably pass a complete object with key, cert, and other 537 * TLS related options. 538 */ 539static isc_result_t 540ns_interface_listentls(ns_interface_t *ifp, isc_tlsctx_t *sslctx) { 541 isc_result_t result; 542 543 result = isc_nm_listentlsdns( 544 ifp->mgr->nm, &ifp->addr, ns__client_request, ifp, 545 ns__client_tcpconn, ifp, sizeof(ns_client_t), ifp->mgr->backlog, 546 &ifp->mgr->sctx->tcpquota, sslctx, &ifp->tcplistensocket); 547 548 if (result != ISC_R_SUCCESS) { 549 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 550 "creating TLS socket: %s", 551 isc_result_totext(result)); 552 return (result); 553 } 554 555 /* 556 * We call this now to update the tcp-highwater statistic: 557 * this is necessary because we are adding to the TCP quota just 558 * by listening. 559 */ 560 result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp); 561 if (result != ISC_R_SUCCESS) { 562 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 563 "updating TCP stats: %s", 564 isc_result_totext(result)); 565 } 566 567 return (result); 568} 569 570#ifdef HAVE_LIBNGHTTP2 571static isc_result_t 572load_http_endpoints(isc_nm_http_endpoints_t *epset, ns_interface_t *ifp, 573 char **eps, size_t neps) { 574 isc_result_t result = ISC_R_FAILURE; 575 576 for (size_t i = 0; i < neps; i++) { 577 result = isc_nm_http_endpoints_add(epset, eps[i], 578 ns__client_request, ifp, 579 sizeof(ns_client_t)); 580 if (result != ISC_R_SUCCESS) { 581 break; 582 } 583 } 584 585 return (result); 586} 587#endif /* HAVE_LIBNGHTTP2 */ 588 589static isc_result_t 590ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps, 591 size_t neps, uint32_t max_clients, 592 uint32_t max_concurrent_streams) { 593#if HAVE_LIBNGHTTP2 594 isc_result_t result = ISC_R_FAILURE; 595 isc_nmsocket_t *sock = NULL; 596 isc_nm_http_endpoints_t *epset = NULL; 597 isc_quota_t *quota = NULL; 598 599 epset = isc_nm_http_endpoints_new(ifp->mgr->mctx); 600 601 result = load_http_endpoints(epset, ifp, eps, neps); 602 603 if (result == ISC_R_SUCCESS) { 604 quota = isc_mem_get(ifp->mgr->mctx, sizeof(*quota)); 605 isc_quota_init(quota, max_clients); 606 result = isc_nm_listenhttp( 607 ifp->mgr->nm, &ifp->addr, ifp->mgr->backlog, quota, 608 sslctx, epset, max_concurrent_streams, &sock); 609 } 610 611 isc_nm_http_endpoints_detach(&epset); 612 613 if (quota != NULL) { 614 if (result != ISC_R_SUCCESS) { 615 isc_quota_destroy(quota); 616 isc_mem_put(ifp->mgr->mctx, quota, sizeof(*quota)); 617 } else { 618 ifp->http_quota = quota; 619 ns_server_append_http_quota(ifp->mgr->sctx, quota); 620 } 621 } 622 623 if (result != ISC_R_SUCCESS) { 624 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 625 "creating %s socket: %s", 626 sslctx ? "HTTPS" : "HTTP", 627 isc_result_totext(result)); 628 return (result); 629 } 630 631 if (sslctx) { 632 ifp->http_secure_listensocket = sock; 633 } else { 634 ifp->http_listensocket = sock; 635 } 636 637 /* 638 * We call this now to update the tcp-highwater statistic: 639 * this is necessary because we are adding to the TCP quota just 640 * by listening. 641 */ 642 result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp); 643 if (result != ISC_R_SUCCESS) { 644 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 645 "updating TCP stats: %s", 646 isc_result_totext(result)); 647 } 648 649 return (result); 650#else 651 UNUSED(ifp); 652 UNUSED(sslctx); 653 UNUSED(eps); 654 UNUSED(neps); 655 UNUSED(max_clients); 656 UNUSED(max_concurrent_streams); 657 return (ISC_R_NOTIMPLEMENTED); 658#endif 659} 660 661static isc_result_t 662interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, const char *name, 663 ns_interface_t **ifpret, ns_listenelt_t *elt, 664 bool *addr_in_use) { 665 isc_result_t result; 666 ns_interface_t *ifp = NULL; 667 668 REQUIRE(ifpret != NULL); 669 REQUIRE(addr_in_use == NULL || !*addr_in_use); 670 671 ifp = *ifpret; 672 673 if (ifp == NULL) { 674 interface_create(mgr, addr, name, &ifp); 675 } else { 676 REQUIRE(!LISTENING(ifp)); 677 } 678 679 ifp->flags |= NS_INTERFACEFLAG_LISTENING; 680 681 if (elt->is_http) { 682 result = ns_interface_listenhttp( 683 ifp, elt->sslctx, elt->http_endpoints, 684 elt->http_endpoints_number, elt->http_max_clients, 685 elt->max_concurrent_streams); 686 if (result != ISC_R_SUCCESS) { 687 goto cleanup_interface; 688 } 689 *ifpret = ifp; 690 return (result); 691 } 692 693 if (elt->sslctx != NULL) { 694 result = ns_interface_listentls(ifp, elt->sslctx); 695 if (result != ISC_R_SUCCESS) { 696 goto cleanup_interface; 697 } 698 *ifpret = ifp; 699 return (result); 700 } 701 702 result = ns_interface_listenudp(ifp); 703 if (result != ISC_R_SUCCESS) { 704 if ((result == ISC_R_ADDRINUSE) && (addr_in_use != NULL)) { 705 *addr_in_use = true; 706 } 707 goto cleanup_interface; 708 } 709 710 if (((mgr->sctx->options & NS_SERVER_NOTCP) == 0)) { 711 result = ns_interface_listentcp(ifp); 712 if (result != ISC_R_SUCCESS) { 713 if ((result == ISC_R_ADDRINUSE) && 714 (addr_in_use != NULL)) 715 { 716 *addr_in_use = true; 717 } 718 719 /* 720 * XXXRTH We don't currently have a way to easily stop 721 * dispatch service, so we currently return 722 * ISC_R_SUCCESS (the UDP stuff will work even if TCP 723 * creation failed). This will be fixed later. 724 */ 725 result = ISC_R_SUCCESS; 726 } 727 } 728 *ifpret = ifp; 729 return (result); 730 731cleanup_interface: 732 ns_interface_shutdown(ifp); 733 return (result); 734} 735 736void 737ns_interface_shutdown(ns_interface_t *ifp) { 738 ifp->flags &= ~NS_INTERFACEFLAG_LISTENING; 739 740 if (ifp->udplistensocket != NULL) { 741 isc_nm_stoplistening(ifp->udplistensocket); 742 isc_nmsocket_close(&ifp->udplistensocket); 743 } 744 if (ifp->tcplistensocket != NULL) { 745 isc_nm_stoplistening(ifp->tcplistensocket); 746 isc_nmsocket_close(&ifp->tcplistensocket); 747 } 748 if (ifp->http_listensocket != NULL) { 749 isc_nm_stoplistening(ifp->http_listensocket); 750 isc_nmsocket_close(&ifp->http_listensocket); 751 } 752 if (ifp->http_secure_listensocket != NULL) { 753 isc_nm_stoplistening(ifp->http_secure_listensocket); 754 isc_nmsocket_close(&ifp->http_secure_listensocket); 755 } 756 ifp->http_quota = NULL; 757} 758 759static void 760interface_destroy(ns_interface_t **interfacep) { 761 ns_interface_t *ifp = NULL; 762 ns_interfacemgr_t *mgr = NULL; 763 764 REQUIRE(interfacep != NULL); 765 766 ifp = *interfacep; 767 *interfacep = NULL; 768 769 REQUIRE(NS_INTERFACE_VALID(ifp)); 770 771 mgr = ifp->mgr; 772 773 ns_interface_shutdown(ifp); 774 775 ifp->magic = 0; 776 isc_mutex_destroy(&ifp->lock); 777 ns_interfacemgr_detach(&ifp->mgr); 778 isc_refcount_destroy(&ifp->ntcpactive); 779 isc_refcount_destroy(&ifp->ntcpaccepting); 780 781 isc_mem_put(mgr->mctx, ifp, sizeof(*ifp)); 782} 783 784/*% 785 * Search the interface list for an interface whose address and port 786 * both match those of 'addr'. Return a pointer to it, or NULL if not found. 787 */ 788static ns_interface_t * 789find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) { 790 ns_interface_t *ifp; 791 LOCK(&mgr->lock); 792 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; 793 ifp = ISC_LIST_NEXT(ifp, link)) 794 { 795 if (isc_sockaddr_equal(&ifp->addr, addr)) { 796 break; 797 } 798 } 799 UNLOCK(&mgr->lock); 800 return (ifp); 801} 802 803/*% 804 * Remove any interfaces whose generation number is not the current one. 805 */ 806static void 807purge_old_interfaces(ns_interfacemgr_t *mgr) { 808 ns_interface_t *ifp = NULL, *next = NULL; 809 ISC_LIST(ns_interface_t) interfaces; 810 811 ISC_LIST_INIT(interfaces); 812 813 LOCK(&mgr->lock); 814 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) { 815 INSIST(NS_INTERFACE_VALID(ifp)); 816 next = ISC_LIST_NEXT(ifp, link); 817 if (ifp->generation != mgr->generation) { 818 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link); 819 ISC_LIST_APPEND(interfaces, ifp, link); 820 } 821 } 822 UNLOCK(&mgr->lock); 823 824 for (ifp = ISC_LIST_HEAD(interfaces); ifp != NULL; ifp = next) { 825 next = ISC_LIST_NEXT(ifp, link); 826 if (LISTENING(ifp)) { 827 char sabuf[256]; 828 isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf)); 829 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, 830 "no longer listening on %s", sabuf); 831 ns_interface_shutdown(ifp); 832 } 833 ISC_LIST_UNLINK(interfaces, ifp, link); 834 interface_destroy(&ifp); 835 } 836} 837 838static bool 839listenon_is_ip6_any(ns_listenelt_t *elt) { 840 REQUIRE(elt && elt->acl); 841 return (dns_acl_isany(elt->acl)); 842} 843 844static isc_result_t 845setup_locals(isc_interface_t *interface, dns_acl_t *localhost, 846 dns_acl_t *localnets) { 847 isc_result_t result; 848 unsigned int prefixlen; 849 isc_netaddr_t *netaddr; 850 851 netaddr = &interface->address; 852 853 /* First add localhost address */ 854 prefixlen = (netaddr->family == AF_INET) ? 32 : 128; 855 result = dns_iptable_addprefix(localhost->iptable, netaddr, prefixlen, 856 true); 857 if (result != ISC_R_SUCCESS) { 858 return (result); 859 } 860 861 /* Then add localnets prefix */ 862 result = isc_netaddr_masktoprefixlen(&interface->netmask, &prefixlen); 863 864 /* Non contiguous netmasks not allowed by IPv6 arch. */ 865 if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6) { 866 return (result); 867 } 868 869 if (result != ISC_R_SUCCESS) { 870 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, 871 "omitting IPv4 interface %s from " 872 "localnets ACL: %s", 873 interface->name, isc_result_totext(result)); 874 return (ISC_R_SUCCESS); 875 } 876 877 if (prefixlen == 0U) { 878 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, 879 "omitting %s interface %s from localnets ACL: " 880 "zero prefix length detected", 881 (netaddr->family == AF_INET) ? "IPv4" : "IPv6", 882 interface->name); 883 return (ISC_R_SUCCESS); 884 } 885 886 result = dns_iptable_addprefix(localnets->iptable, netaddr, prefixlen, 887 true); 888 if (result != ISC_R_SUCCESS) { 889 return (result); 890 } 891 892 return (ISC_R_SUCCESS); 893} 894 895static void 896setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface, 897 in_port_t port) { 898 isc_sockaddr_t *addr; 899 isc_sockaddr_t *old; 900 901 addr = isc_mem_get(mgr->mctx, sizeof(*addr)); 902 903 isc_sockaddr_fromnetaddr(addr, &interface->address, port); 904 905 LOCK(&mgr->lock); 906 for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL; 907 old = ISC_LIST_NEXT(old, link)) 908 { 909 if (isc_sockaddr_equal(addr, old)) { 910 /* We found an existing address */ 911 isc_mem_put(mgr->mctx, addr, sizeof(*addr)); 912 goto unlock; 913 } 914 } 915 916 ISC_LIST_APPEND(mgr->listenon, addr, link); 917unlock: 918 UNLOCK(&mgr->lock); 919} 920 921static void 922clearlistenon(ns_interfacemgr_t *mgr) { 923 ISC_LIST(isc_sockaddr_t) listenon; 924 isc_sockaddr_t *old; 925 926 ISC_LIST_INIT(listenon); 927 928 LOCK(&mgr->lock); 929 ISC_LIST_MOVE(listenon, mgr->listenon); 930 UNLOCK(&mgr->lock); 931 932 old = ISC_LIST_HEAD(listenon); 933 while (old != NULL) { 934 ISC_LIST_UNLINK(listenon, old, link); 935 isc_mem_put(mgr->mctx, old, sizeof(*old)); 936 old = ISC_LIST_HEAD(listenon); 937 } 938} 939 940static void 941replace_listener_tlsctx(ns_interface_t *ifp, isc_tlsctx_t *newctx) { 942 char sabuf[ISC_SOCKADDR_FORMATSIZE]; 943 944 isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf)); 945 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, 946 "updating TLS context on %s", sabuf); 947 if (ifp->tcplistensocket != NULL) { 948 /* 'tcplistensocket' is used for DoT */ 949 isc_nmsocket_set_tlsctx(ifp->tcplistensocket, newctx); 950 } else if (ifp->http_secure_listensocket != NULL) { 951 isc_nmsocket_set_tlsctx(ifp->http_secure_listensocket, newctx); 952 } 953} 954 955#ifdef HAVE_LIBNGHTTP2 956static void 957update_http_settings(ns_interface_t *ifp, ns_listenelt_t *le) { 958 isc_result_t result; 959 isc_nmsocket_t *listener; 960 isc_nm_http_endpoints_t *epset; 961 962 REQUIRE(le->is_http); 963 964 INSIST(ifp->http_quota != NULL); 965 isc_quota_max(ifp->http_quota, le->http_max_clients); 966 967 if (ifp->http_secure_listensocket != NULL) { 968 listener = ifp->http_secure_listensocket; 969 } else { 970 INSIST(ifp->http_listensocket != NULL); 971 listener = ifp->http_listensocket; 972 } 973 974 isc_nmsocket_set_max_streams(listener, le->max_concurrent_streams); 975 976 epset = isc_nm_http_endpoints_new(ifp->mgr->mctx); 977 978 result = load_http_endpoints(epset, ifp, le->http_endpoints, 979 le->http_endpoints_number); 980 981 if (result == ISC_R_SUCCESS) { 982 isc_nm_http_set_endpoints(listener, epset); 983 } 984 985 isc_nm_http_endpoints_detach(&epset); 986} 987#endif /* HAVE_LIBNGHTTP2 */ 988 989static void 990update_listener_configuration(ns_interfacemgr_t *mgr, ns_interface_t *ifp, 991 ns_listenelt_t *le) { 992 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 993 REQUIRE(NS_INTERFACE_VALID(ifp)); 994 REQUIRE(le != NULL); 995 996 LOCK(&mgr->lock); 997 /* 998 * We need to update the TLS contexts 999 * inside the TLS/HTTPS listeners during 1000 * a reconfiguration because the 1001 * certificates could have been changed. 1002 */ 1003 if (le->sslctx != NULL) { 1004 replace_listener_tlsctx(ifp, le->sslctx); 1005 } 1006 1007#ifdef HAVE_LIBNGHTTP2 1008 /* 1009 * Let's update HTTP listener settings 1010 * on reconfiguration. 1011 */ 1012 if (le->is_http) { 1013 update_http_settings(ifp, le); 1014 } 1015#endif /* HAVE_LIBNGHTTP2 */ 1016 1017 UNLOCK(&mgr->lock); 1018} 1019 1020static isc_result_t 1021do_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) { 1022 isc_interfaceiter_t *iter = NULL; 1023 bool scan_ipv4 = false; 1024 bool scan_ipv6 = false; 1025 bool ipv6only = true; 1026 bool ipv6pktinfo = true; 1027 isc_result_t result; 1028 isc_netaddr_t zero_address, zero_address6; 1029 ns_listenelt_t *le = NULL; 1030 isc_sockaddr_t listen_addr; 1031 ns_interface_t *ifp = NULL; 1032 bool log_explicit = false; 1033 bool dolistenon; 1034 char sabuf[ISC_SOCKADDR_FORMATSIZE]; 1035 bool tried_listening; 1036 bool all_addresses_in_use; 1037 dns_acl_t *localhost = NULL; 1038 dns_acl_t *localnets = NULL; 1039 1040 if (isc_net_probeipv6() == ISC_R_SUCCESS) { 1041 scan_ipv6 = true; 1042 } else if ((mgr->sctx->options & NS_SERVER_DISABLE6) == 0) { 1043 isc_log_write(IFMGR_COMMON_LOGARGS, 1044 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), 1045 "no IPv6 interfaces found"); 1046 } 1047 1048 if (isc_net_probeipv4() == ISC_R_SUCCESS) { 1049 scan_ipv4 = true; 1050 } else if ((mgr->sctx->options & NS_SERVER_DISABLE4) == 0) { 1051 isc_log_write(IFMGR_COMMON_LOGARGS, 1052 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), 1053 "no IPv4 interfaces found"); 1054 } 1055 1056 /* 1057 * A special, but typical case; listen-on-v6 { any; }. 1058 * When we can make the socket IPv6-only, open a single wildcard 1059 * socket for IPv6 communication. Otherwise, make separate 1060 * socket for each IPv6 address in order to avoid accepting IPv4 1061 * packets as the form of mapped addresses unintentionally 1062 * unless explicitly allowed. 1063 */ 1064 if (scan_ipv6 && isc_net_probe_ipv6only() != ISC_R_SUCCESS) { 1065 ipv6only = false; 1066 log_explicit = true; 1067 } 1068 if (scan_ipv6 && isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) { 1069 ipv6pktinfo = false; 1070 log_explicit = true; 1071 } 1072 if (scan_ipv6 && ipv6only && ipv6pktinfo) { 1073 for (le = ISC_LIST_HEAD(mgr->listenon6->elts); le != NULL; 1074 le = ISC_LIST_NEXT(le, link)) 1075 { 1076 struct in6_addr in6a; 1077 1078 if (!listenon_is_ip6_any(le)) { 1079 continue; 1080 } 1081 1082 in6a = in6addr_any; 1083 isc_sockaddr_fromin6(&listen_addr, &in6a, le->port); 1084 1085 ifp = find_matching_interface(mgr, &listen_addr); 1086 if (ifp != NULL) { 1087 ifp->generation = mgr->generation; 1088 if (LISTENING(ifp)) { 1089 if (config) { 1090 update_listener_configuration( 1091 mgr, ifp, le); 1092 } 1093 continue; 1094 } 1095 } 1096 1097 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, 1098 "listening on IPv6 " 1099 "interfaces, port %u", 1100 le->port); 1101 result = interface_setup(mgr, &listen_addr, "<any>", 1102 &ifp, le, NULL); 1103 if (result == ISC_R_SUCCESS) { 1104 ifp->flags |= NS_INTERFACEFLAG_ANYADDR; 1105 } else { 1106 isc_log_write(IFMGR_COMMON_LOGARGS, 1107 ISC_LOG_ERROR, 1108 "listening on all IPv6 " 1109 "interfaces failed"); 1110 } 1111 /* Continue. */ 1112 } 1113 } 1114 1115 isc_netaddr_any(&zero_address); 1116 isc_netaddr_any6(&zero_address6); 1117 1118 result = isc_interfaceiter_create(mgr->mctx, &iter); 1119 if (result != ISC_R_SUCCESS) { 1120 return (result); 1121 } 1122 1123 result = dns_acl_create(mgr->mctx, 0, &localhost); 1124 if (result != ISC_R_SUCCESS) { 1125 goto cleanup_iter; 1126 } 1127 result = dns_acl_create(mgr->mctx, 0, &localnets); 1128 if (result != ISC_R_SUCCESS) { 1129 goto cleanup_localhost; 1130 } 1131 1132 clearlistenon(mgr); 1133 1134 tried_listening = false; 1135 all_addresses_in_use = true; 1136 for (result = isc_interfaceiter_first(iter); result == ISC_R_SUCCESS; 1137 result = isc_interfaceiter_next(iter)) 1138 { 1139 isc_interface_t interface; 1140 ns_listenlist_t *ll = NULL; 1141 unsigned int family; 1142 1143 result = isc_interfaceiter_current(iter, &interface); 1144 if (result != ISC_R_SUCCESS) { 1145 break; 1146 } 1147 1148 family = interface.address.family; 1149 if (family != AF_INET && family != AF_INET6) { 1150 continue; 1151 } 1152 if (!scan_ipv4 && family == AF_INET) { 1153 continue; 1154 } 1155 if (!scan_ipv6 && family == AF_INET6) { 1156 continue; 1157 } 1158 1159 /* 1160 * Test for the address being nonzero rather than testing 1161 * INTERFACE_F_UP, because on some systems the latter 1162 * follows the media state and we could end up ignoring 1163 * the interface for an entire rescan interval due to 1164 * a temporary media glitch at rescan time. 1165 */ 1166 if (family == AF_INET && 1167 isc_netaddr_equal(&interface.address, &zero_address)) 1168 { 1169 continue; 1170 } 1171 if (family == AF_INET6 && 1172 isc_netaddr_equal(&interface.address, &zero_address6)) 1173 { 1174 continue; 1175 } 1176 1177 /* 1178 * If running with -T fixedlocal, then we only 1179 * want 127.0.0.1 and ::1 in the localhost ACL. 1180 */ 1181 if (((mgr->sctx->options & NS_SERVER_FIXEDLOCAL) != 0) && 1182 !isc_netaddr_isloopback(&interface.address)) 1183 { 1184 goto listenon; 1185 } 1186 1187 result = setup_locals(&interface, localhost, localnets); 1188 if (result != ISC_R_SUCCESS) { 1189 goto ignore_interface; 1190 } 1191 1192 listenon: 1193 ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6; 1194 dolistenon = true; 1195 for (le = ISC_LIST_HEAD(ll->elts); le != NULL; 1196 le = ISC_LIST_NEXT(le, link)) 1197 { 1198 int match; 1199 bool addr_in_use = false; 1200 bool ipv6_wildcard = false; 1201 isc_sockaddr_t listen_sockaddr; 1202 1203 isc_sockaddr_fromnetaddr(&listen_sockaddr, 1204 &interface.address, le->port); 1205 1206 /* 1207 * See if the address matches the listen-on statement; 1208 * if not, ignore the interface, but store it in 1209 * the interface table so we know we've seen it 1210 * before. 1211 */ 1212 (void)dns_acl_match(&interface.address, NULL, le->acl, 1213 mgr->aclenv, &match, NULL); 1214 if (match <= 0) { 1215 ns_interface_t *new = NULL; 1216 interface_create(mgr, &listen_sockaddr, 1217 interface.name, &new); 1218 continue; 1219 } 1220 1221 if (dolistenon) { 1222 setup_listenon(mgr, &interface, le->port); 1223 dolistenon = false; 1224 } 1225 1226 /* 1227 * The case of "any" IPv6 address will require 1228 * special considerations later, so remember it. 1229 */ 1230 if (family == AF_INET6 && ipv6only && ipv6pktinfo && 1231 listenon_is_ip6_any(le)) 1232 { 1233 ipv6_wildcard = true; 1234 } 1235 1236 ifp = find_matching_interface(mgr, &listen_sockaddr); 1237 if (ifp != NULL) { 1238 ifp->generation = mgr->generation; 1239 if (LISTENING(ifp)) { 1240 if (config) { 1241 update_listener_configuration( 1242 mgr, ifp, le); 1243 } 1244 continue; 1245 } 1246 } 1247 1248 if (ipv6_wildcard) { 1249 continue; 1250 } 1251 1252 if (log_explicit && family == AF_INET6 && 1253 listenon_is_ip6_any(le)) 1254 { 1255 isc_log_write(IFMGR_COMMON_LOGARGS, 1256 verbose ? ISC_LOG_INFO 1257 : ISC_LOG_DEBUG(1), 1258 "IPv6 socket API is " 1259 "incomplete; explicitly " 1260 "binding to each IPv6 " 1261 "address separately"); 1262 log_explicit = false; 1263 } 1264 isc_sockaddr_format(&listen_sockaddr, sabuf, 1265 sizeof(sabuf)); 1266 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, 1267 "listening on %s interface " 1268 "%s, %s", 1269 (family == AF_INET) ? "IPv4" : "IPv6", 1270 interface.name, sabuf); 1271 1272 result = interface_setup(mgr, &listen_sockaddr, 1273 interface.name, &ifp, le, 1274 &addr_in_use); 1275 1276 tried_listening = true; 1277 if (!addr_in_use) { 1278 all_addresses_in_use = false; 1279 } 1280 1281 if (result != ISC_R_SUCCESS) { 1282 isc_log_write( 1283 IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 1284 "creating %s interface " 1285 "%s failed; interface ignored", 1286 (family == AF_INET) ? "IPv4" : "IPv6", 1287 interface.name); 1288 } 1289 /* Continue. */ 1290 } 1291 continue; 1292 1293 ignore_interface: 1294 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 1295 "ignoring %s interface %s: %s", 1296 (family == AF_INET) ? "IPv4" : "IPv6", 1297 interface.name, isc_result_totext(result)); 1298 continue; 1299 } 1300 if (result != ISC_R_NOMORE) { 1301 UNEXPECTED_ERROR("interface iteration failed: %s", 1302 isc_result_totext(result)); 1303 } else { 1304 result = ((tried_listening && all_addresses_in_use) 1305 ? ISC_R_ADDRINUSE 1306 : ISC_R_SUCCESS); 1307 } 1308 1309 dns_aclenv_set(mgr->aclenv, localhost, localnets); 1310 1311 /* cleanup_localnets: */ 1312 dns_acl_detach(&localnets); 1313 1314cleanup_localhost: 1315 dns_acl_detach(&localhost); 1316 1317cleanup_iter: 1318 isc_interfaceiter_destroy(&iter); 1319 return (result); 1320} 1321 1322isc_result_t 1323ns_interfacemgr_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) { 1324 isc_result_t result; 1325 bool purge = true; 1326 1327 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1328 REQUIRE(isc_nm_tid() == 0); 1329 1330 mgr->generation++; /* Increment the generation count. */ 1331 1332 result = do_scan(mgr, verbose, config); 1333 if ((result != ISC_R_SUCCESS) && (result != ISC_R_ADDRINUSE)) { 1334 purge = false; 1335 } 1336 1337 /* 1338 * Now go through the interface list and delete anything that 1339 * does not have the current generation number. This is 1340 * how we catch interfaces that go away or change their 1341 * addresses. 1342 */ 1343 if (purge) { 1344 purge_old_interfaces(mgr); 1345 } 1346 1347 /* 1348 * Warn if we are not listening on any interface. 1349 */ 1350 if (ISC_LIST_EMPTY(mgr->interfaces)) { 1351 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, 1352 "not listening on any interfaces"); 1353 } 1354 1355 return (result); 1356} 1357 1358bool 1359ns_interfacemgr_islistening(ns_interfacemgr_t *mgr) { 1360 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1361 1362 return (ISC_LIST_EMPTY(mgr->interfaces) ? false : true); 1363} 1364 1365void 1366ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { 1367 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1368 1369 LOCK(&mgr->lock); 1370 ns_listenlist_detach(&mgr->listenon4); 1371 ns_listenlist_attach(value, &mgr->listenon4); 1372 UNLOCK(&mgr->lock); 1373} 1374 1375void 1376ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { 1377 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1378 1379 LOCK(&mgr->lock); 1380 ns_listenlist_detach(&mgr->listenon6); 1381 ns_listenlist_attach(value, &mgr->listenon6); 1382 UNLOCK(&mgr->lock); 1383} 1384 1385void 1386ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) { 1387 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1388 1389 LOCK(&mgr->lock); 1390 for (size_t i = 0; i < (size_t)mgr->ncpus; i++) { 1391 ns_client_dumprecursing(f, mgr->clientmgrs[i]); 1392 } 1393 UNLOCK(&mgr->lock); 1394} 1395 1396bool 1397ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, 1398 const isc_sockaddr_t *addr) { 1399 isc_sockaddr_t *old; 1400 bool result = false; 1401 1402 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1403 /* 1404 * If the manager is shutting down it's safer to 1405 * return true. 1406 */ 1407 if (atomic_load(&mgr->shuttingdown)) { 1408 return (true); 1409 } 1410 LOCK(&mgr->lock); 1411 for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL; 1412 old = ISC_LIST_NEXT(old, link)) 1413 { 1414 if (isc_sockaddr_equal(old, addr)) { 1415 result = true; 1416 break; 1417 } 1418 } 1419 UNLOCK(&mgr->lock); 1420 1421 return (result); 1422} 1423 1424ns_server_t * 1425ns_interfacemgr_getserver(ns_interfacemgr_t *mgr) { 1426 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1427 1428 return (mgr->sctx); 1429} 1430 1431ns_clientmgr_t * 1432ns_interfacemgr_getclientmgr(ns_interfacemgr_t *mgr) { 1433 int tid = isc_nm_tid(); 1434 1435 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1436 REQUIRE(tid >= 0); 1437 REQUIRE(tid < mgr->ncpus); 1438 1439 return (mgr->clientmgrs[tid]); 1440} 1441