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