interfacemgr.c revision 1.10
1/* $NetBSD: interfacemgr.c,v 1.10 2021/03/23 20:59:03 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#ifndef __lint__ // XXX: bug 402 *ifp = (ns_interface_t){ .generation = mgr->generation, 403 .addr = *addr, 404 .dscp = -1 }; 405#endif 406 407 strlcpy(ifp->name, name, sizeof(ifp->name)); 408 409 isc_mutex_init(&ifp->lock); 410 411 for (disp = 0; disp < MAX_UDP_DISPATCH; disp++) { 412 ifp->udpdispatch[disp] = NULL; 413 } 414 415 /* 416 * Create a single TCP client object. It will replace itself 417 * with a new one as soon as it gets a connection, so the actual 418 * connections will be handled in parallel even though there is 419 * only one client initially. 420 */ 421 isc_refcount_init(&ifp->ntcpaccepting, 0); 422 isc_refcount_init(&ifp->ntcpactive, 0); 423 424 ISC_LINK_INIT(ifp, link); 425 426 ns_interfacemgr_attach(mgr, &ifp->mgr); 427 LOCK(&mgr->lock); 428 ISC_LIST_APPEND(mgr->interfaces, ifp, link); 429 UNLOCK(&mgr->lock); 430 431 isc_refcount_init(&ifp->references, 1); 432 ifp->magic = IFACE_MAGIC; 433 434 result = ns_clientmgr_create(mgr->mctx, mgr->sctx, mgr->taskmgr, 435 mgr->timermgr, ifp, mgr->ncpus, 436 &ifp->clientmgr); 437 if (result != ISC_R_SUCCESS) { 438 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 439 "ns_clientmgr_create() failed: %s", 440 isc_result_totext(result)); 441 goto failure; 442 } 443 444 *ifpret = ifp; 445 446 return (ISC_R_SUCCESS); 447 448failure: 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 461 /* Reserve space for an ns_client_t with the netmgr handle */ 462 result = isc_nm_listenudp(ifp->mgr->nm, (isc_nmiface_t *)&ifp->addr, 463 ns__client_request, ifp, sizeof(ns_client_t), 464 &ifp->udplistensocket); 465 return (result); 466} 467 468static isc_result_t 469ns_interface_listentcp(ns_interface_t *ifp) { 470 isc_result_t result; 471 472 result = isc_nm_listentcpdns( 473 ifp->mgr->nm, (isc_nmiface_t *)&ifp->addr, ns__client_request, 474 ifp, ns__client_tcpconn, ifp, sizeof(ns_client_t), 475 ifp->mgr->backlog, &ifp->mgr->sctx->tcpquota, 476 &ifp->tcplistensocket); 477 if (result != ISC_R_SUCCESS) { 478 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 479 "creating TCP socket: %s", 480 isc_result_totext(result)); 481 } 482 483 /* 484 * We call this now to update the tcp-highwater statistic: 485 * this is necessary because we are adding to the TCP quota just 486 * by listening. 487 */ 488 result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp); 489 if (result != ISC_R_SUCCESS) { 490 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 491 "connecting TCP socket: %s", 492 isc_result_totext(result)); 493 } 494 495#if 0 496#ifndef ISC_ALLOW_MAPPED 497 isc_socket_ipv6only(ifp->tcpsocket,true); 498#endif /* ifndef ISC_ALLOW_MAPPED */ 499 500 if (ifp->dscp != -1) { 501 isc_socket_dscp(ifp->tcpsocket,ifp->dscp); 502 } 503 504 (void)isc_socket_filter(ifp->tcpsocket,"dataready"); 505#endif /* if 0 */ 506 return (result); 507} 508 509static isc_result_t 510ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, 511 const char *name, ns_interface_t **ifpret, bool accept_tcp, 512 isc_dscp_t dscp, bool *addr_in_use) { 513 isc_result_t result; 514 ns_interface_t *ifp = NULL; 515 REQUIRE(ifpret != NULL && *ifpret == NULL); 516 REQUIRE(addr_in_use == NULL || !*addr_in_use); 517 518 result = ns_interface_create(mgr, addr, name, &ifp); 519 if (result != ISC_R_SUCCESS) { 520 return (result); 521 } 522 523 ifp->dscp = dscp; 524 525 result = ns_interface_listenudp(ifp); 526 if (result != ISC_R_SUCCESS) { 527 if ((result == ISC_R_ADDRINUSE) && (addr_in_use != NULL)) { 528 *addr_in_use = true; 529 } 530 goto cleanup_interface; 531 } 532 533 if (((mgr->sctx->options & NS_SERVER_NOTCP) == 0) && accept_tcp) { 534 result = ns_interface_listentcp(ifp); 535 if (result != ISC_R_SUCCESS) { 536 if ((result == ISC_R_ADDRINUSE) && 537 (addr_in_use != NULL)) { 538 *addr_in_use = true; 539 } 540 541 /* 542 * XXXRTH We don't currently have a way to easily stop 543 * dispatch service, so we currently return 544 * ISC_R_SUCCESS (the UDP stuff will work even if TCP 545 * creation failed). This will be fixed later. 546 */ 547 result = ISC_R_SUCCESS; 548 } 549 } 550 *ifpret = ifp; 551 return (result); 552 553cleanup_interface: 554 LOCK(&ifp->mgr->lock); 555 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link); 556 UNLOCK(&ifp->mgr->lock); 557 ns_interface_detach(&ifp); 558 return (result); 559} 560 561void 562ns_interface_shutdown(ns_interface_t *ifp) { 563 if (ifp->udplistensocket != NULL) { 564 isc_nm_stoplistening(ifp->udplistensocket); 565 isc_nmsocket_close(&ifp->udplistensocket); 566 } 567 if (ifp->tcplistensocket != NULL) { 568 isc_nm_stoplistening(ifp->tcplistensocket); 569 isc_nmsocket_close(&ifp->tcplistensocket); 570 } 571 if (ifp->clientmgr != NULL) { 572 ns_clientmgr_destroy(&ifp->clientmgr); 573 } 574} 575 576static void 577ns_interface_destroy(ns_interface_t *ifp) { 578 REQUIRE(NS_INTERFACE_VALID(ifp)); 579 580 isc_mem_t *mctx = ifp->mgr->mctx; 581 582 ns_interface_shutdown(ifp); 583 584 for (int disp = 0; disp < ifp->nudpdispatch; disp++) { 585 if (ifp->udpdispatch[disp] != NULL) { 586 dns_dispatch_changeattributes( 587 ifp->udpdispatch[disp], 0, 588 DNS_DISPATCHATTR_NOLISTEN); 589 dns_dispatch_detach(&(ifp->udpdispatch[disp])); 590 } 591 } 592 593 if (ifp->tcpsocket != NULL) { 594 isc_socket_detach(&ifp->tcpsocket); 595 } 596 597 isc_mutex_destroy(&ifp->lock); 598 599 ns_interfacemgr_detach(&ifp->mgr); 600 601 isc_refcount_destroy(&ifp->ntcpactive); 602 isc_refcount_destroy(&ifp->ntcpaccepting); 603 604 ifp->magic = 0; 605 606 isc_mem_put(mctx, ifp, sizeof(*ifp)); 607} 608 609void 610ns_interface_attach(ns_interface_t *source, ns_interface_t **target) { 611 REQUIRE(NS_INTERFACE_VALID(source)); 612 isc_refcount_increment(&source->references); 613 *target = source; 614} 615 616void 617ns_interface_detach(ns_interface_t **targetp) { 618 ns_interface_t *target = *targetp; 619 *targetp = NULL; 620 REQUIRE(target != NULL); 621 REQUIRE(NS_INTERFACE_VALID(target)); 622 if (isc_refcount_decrement(&target->references) == 1) { 623 ns_interface_destroy(target); 624 } 625} 626 627/*% 628 * Search the interface list for an interface whose address and port 629 * both match those of 'addr'. Return a pointer to it, or NULL if not found. 630 */ 631static ns_interface_t * 632find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) { 633 ns_interface_t *ifp; 634 LOCK(&mgr->lock); 635 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; 636 ifp = ISC_LIST_NEXT(ifp, link)) 637 { 638 if (isc_sockaddr_equal(&ifp->addr, addr)) { 639 break; 640 } 641 } 642 UNLOCK(&mgr->lock); 643 return (ifp); 644} 645 646/*% 647 * Remove any interfaces whose generation number is not the current one. 648 */ 649static void 650purge_old_interfaces(ns_interfacemgr_t *mgr) { 651 ns_interface_t *ifp, *next; 652 LOCK(&mgr->lock); 653 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) { 654 INSIST(NS_INTERFACE_VALID(ifp)); 655 next = ISC_LIST_NEXT(ifp, link); 656 if (ifp->generation != mgr->generation) { 657 char sabuf[256]; 658 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link); 659 isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf)); 660 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, 661 "no longer listening on %s", sabuf); 662 ns_interface_shutdown(ifp); 663 ns_interface_detach(&ifp); 664 } 665 } 666 UNLOCK(&mgr->lock); 667} 668 669static isc_result_t 670clearacl(isc_mem_t *mctx, dns_acl_t **aclp) { 671 dns_acl_t *newacl = NULL; 672 isc_result_t result; 673 result = dns_acl_create(mctx, 0, &newacl); 674 if (result != ISC_R_SUCCESS) { 675 return (result); 676 } 677 dns_acl_detach(aclp); 678 dns_acl_attach(newacl, aclp); 679 dns_acl_detach(&newacl); 680 return (ISC_R_SUCCESS); 681} 682 683static bool 684listenon_is_ip6_any(ns_listenelt_t *elt) { 685 REQUIRE(elt && elt->acl); 686 return (dns_acl_isany(elt->acl)); 687} 688 689static isc_result_t 690setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) { 691 isc_result_t result; 692 unsigned int prefixlen; 693 isc_netaddr_t *netaddr; 694 695 netaddr = &interface->address; 696 697 /* First add localhost address */ 698 prefixlen = (netaddr->family == AF_INET) ? 32 : 128; 699 result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable, netaddr, 700 prefixlen, true); 701 if (result != ISC_R_SUCCESS) { 702 return (result); 703 } 704 705 /* Then add localnets prefix */ 706 result = isc_netaddr_masktoprefixlen(&interface->netmask, &prefixlen); 707 708 /* Non contiguous netmasks not allowed by IPv6 arch. */ 709 if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6) { 710 return (result); 711 } 712 713 if (result != ISC_R_SUCCESS) { 714 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, 715 "omitting IPv4 interface %s from " 716 "localnets ACL: %s", 717 interface->name, isc_result_totext(result)); 718 return (ISC_R_SUCCESS); 719 } 720 721 if (prefixlen == 0U) { 722 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, 723 "omitting %s interface %s from localnets ACL: " 724 "zero prefix length detected", 725 (netaddr->family == AF_INET) ? "IPv4" : "IPv6", 726 interface->name); 727 return (ISC_R_SUCCESS); 728 } 729 730 result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable, netaddr, 731 prefixlen, true); 732 if (result != ISC_R_SUCCESS) { 733 return (result); 734 } 735 736 return (ISC_R_SUCCESS); 737} 738 739static void 740setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface, 741 in_port_t port) { 742 isc_sockaddr_t *addr; 743 isc_sockaddr_t *old; 744 745 addr = isc_mem_get(mgr->mctx, sizeof(*addr)); 746 747 isc_sockaddr_fromnetaddr(addr, &interface->address, port); 748 749 LOCK(&mgr->lock); 750 for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL; 751 old = ISC_LIST_NEXT(old, link)) 752 { 753 if (isc_sockaddr_equal(addr, old)) { 754 break; 755 } 756 } 757 758 if (old != NULL) { 759 isc_mem_put(mgr->mctx, addr, sizeof(*addr)); 760 } else { 761 ISC_LIST_APPEND(mgr->listenon, addr, link); 762 } 763 UNLOCK(&mgr->lock); 764} 765 766static void 767clearlistenon(ns_interfacemgr_t *mgr) { 768 isc_sockaddr_t *old; 769 770 LOCK(&mgr->lock); 771 old = ISC_LIST_HEAD(mgr->listenon); 772 while (old != NULL) { 773 ISC_LIST_UNLINK(mgr->listenon, old, link); 774 isc_mem_put(mgr->mctx, old, sizeof(*old)); 775 old = ISC_LIST_HEAD(mgr->listenon); 776 } 777 UNLOCK(&mgr->lock); 778} 779 780static isc_result_t 781do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, bool verbose) { 782 isc_interfaceiter_t *iter = NULL; 783 bool scan_ipv4 = false; 784 bool scan_ipv6 = false; 785 bool adjusting = false; 786 bool ipv6only = true; 787 bool ipv6pktinfo = true; 788 isc_result_t result; 789 isc_netaddr_t zero_address, zero_address6; 790 ns_listenelt_t *le; 791 isc_sockaddr_t listen_addr; 792 ns_interface_t *ifp; 793 bool log_explicit = false; 794 bool dolistenon; 795 char sabuf[ISC_SOCKADDR_FORMATSIZE]; 796 bool tried_listening; 797 bool all_addresses_in_use; 798 799 if (ext_listen != NULL) { 800 adjusting = true; 801 } 802 803 if (isc_net_probeipv6() == ISC_R_SUCCESS) { 804 scan_ipv6 = true; 805 } else if ((mgr->sctx->options & NS_SERVER_DISABLE6) == 0) { 806 isc_log_write(IFMGR_COMMON_LOGARGS, 807 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), 808 "no IPv6 interfaces found"); 809 } 810 811 if (isc_net_probeipv4() == ISC_R_SUCCESS) { 812 scan_ipv4 = true; 813 } else if ((mgr->sctx->options & NS_SERVER_DISABLE4) == 0) { 814 isc_log_write(IFMGR_COMMON_LOGARGS, 815 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), 816 "no IPv4 interfaces found"); 817 } 818 819 /* 820 * A special, but typical case; listen-on-v6 { any; }. 821 * When we can make the socket IPv6-only, open a single wildcard 822 * socket for IPv6 communication. Otherwise, make separate 823 * socket for each IPv6 address in order to avoid accepting IPv4 824 * packets as the form of mapped addresses unintentionally 825 * unless explicitly allowed. 826 */ 827#ifndef ISC_ALLOW_MAPPED 828 if (scan_ipv6 && isc_net_probe_ipv6only() != ISC_R_SUCCESS) { 829 ipv6only = false; 830 log_explicit = true; 831 } 832#endif /* ifndef ISC_ALLOW_MAPPED */ 833 if (scan_ipv6 && isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) { 834 ipv6pktinfo = false; 835 log_explicit = true; 836 } 837 if (scan_ipv6 && ipv6only && ipv6pktinfo) { 838 for (le = ISC_LIST_HEAD(mgr->listenon6->elts); le != NULL; 839 le = ISC_LIST_NEXT(le, link)) 840 { 841 struct in6_addr in6a; 842 843 if (!listenon_is_ip6_any(le)) { 844 continue; 845 } 846 847 in6a = in6addr_any; 848 isc_sockaddr_fromin6(&listen_addr, &in6a, le->port); 849 850 ifp = find_matching_interface(mgr, &listen_addr); 851 if (ifp != NULL) { 852 ifp->generation = mgr->generation; 853 if (le->dscp != -1 && ifp->dscp == -1) { 854 ifp->dscp = le->dscp; 855 } else if (le->dscp != ifp->dscp) { 856 isc_sockaddr_format(&listen_addr, sabuf, 857 sizeof(sabuf)); 858 isc_log_write(IFMGR_COMMON_LOGARGS, 859 ISC_LOG_WARNING, 860 "%s: conflicting DSCP " 861 "values, using %d", 862 sabuf, ifp->dscp); 863 } 864 } else { 865 isc_log_write(IFMGR_COMMON_LOGARGS, 866 ISC_LOG_INFO, 867 "listening on IPv6 " 868 "interfaces, port %u", 869 le->port); 870 result = ns_interface_setup(mgr, &listen_addr, 871 "<any>", &ifp, true, 872 le->dscp, NULL); 873 if (result == ISC_R_SUCCESS) { 874 ifp->flags |= NS_INTERFACEFLAG_ANYADDR; 875 } else { 876 isc_log_write(IFMGR_COMMON_LOGARGS, 877 ISC_LOG_ERROR, 878 "listening on all IPv6 " 879 "interfaces failed"); 880 } 881 /* Continue. */ 882 } 883 } 884 } 885 886 isc_netaddr_any(&zero_address); 887 isc_netaddr_any6(&zero_address6); 888 889 result = isc_interfaceiter_create(mgr->mctx, &iter); 890 if (result != ISC_R_SUCCESS) { 891 return (result); 892 } 893 894 if (!adjusting) { 895 result = clearacl(mgr->mctx, &mgr->aclenv.localhost); 896 if (result != ISC_R_SUCCESS) { 897 goto cleanup_iter; 898 } 899 result = clearacl(mgr->mctx, &mgr->aclenv.localnets); 900 if (result != ISC_R_SUCCESS) { 901 goto cleanup_iter; 902 } 903 clearlistenon(mgr); 904 } 905 906 tried_listening = false; 907 all_addresses_in_use = true; 908 for (result = isc_interfaceiter_first(iter); result == ISC_R_SUCCESS; 909 result = isc_interfaceiter_next(iter)) 910 { 911 isc_interface_t interface; 912 ns_listenlist_t *ll; 913 unsigned int family; 914 915 result = isc_interfaceiter_current(iter, &interface); 916 if (result != ISC_R_SUCCESS) { 917 break; 918 } 919 920 family = interface.address.family; 921 if (family != AF_INET && family != AF_INET6) { 922 continue; 923 } 924 if (!scan_ipv4 && family == AF_INET) { 925 continue; 926 } 927 if (!scan_ipv6 && family == AF_INET6) { 928 continue; 929 } 930 931 /* 932 * Test for the address being nonzero rather than testing 933 * INTERFACE_F_UP, because on some systems the latter 934 * follows the media state and we could end up ignoring 935 * the interface for an entire rescan interval due to 936 * a temporary media glitch at rescan time. 937 */ 938 if (family == AF_INET && 939 isc_netaddr_equal(&interface.address, &zero_address)) { 940 continue; 941 } 942 if (family == AF_INET6 && 943 isc_netaddr_equal(&interface.address, &zero_address6)) { 944 continue; 945 } 946 947 if (!adjusting) { 948 /* 949 * If running with -T fixedlocal, then we only 950 * want 127.0.0.1 and ::1 in the localhost ACL. 951 */ 952 if (((mgr->sctx->options & NS_SERVER_FIXEDLOCAL) != 953 0) && 954 !isc_netaddr_isloopback(&interface.address)) 955 { 956 goto listenon; 957 } 958 959 result = setup_locals(mgr, &interface); 960 if (result != ISC_R_SUCCESS) { 961 goto ignore_interface; 962 } 963 } 964 965 listenon: 966 ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6; 967 dolistenon = true; 968 for (le = ISC_LIST_HEAD(ll->elts); le != NULL; 969 le = ISC_LIST_NEXT(le, link)) { 970 int match; 971 bool ipv6_wildcard = false; 972 isc_netaddr_t listen_netaddr; 973 isc_sockaddr_t listen_sockaddr; 974 975 /* 976 * Construct a socket address for this IP/port 977 * combination. 978 */ 979 if (family == AF_INET) { 980 isc_netaddr_fromin(&listen_netaddr, 981 &interface.address.type.in); 982 } else { 983 isc_netaddr_fromin6( 984 &listen_netaddr, 985 &interface.address.type.in6); 986 isc_netaddr_setzone(&listen_netaddr, 987 interface.address.zone); 988 } 989 isc_sockaddr_fromnetaddr(&listen_sockaddr, 990 &listen_netaddr, le->port); 991 992 /* 993 * See if the address matches the listen-on statement; 994 * if not, ignore the interface. 995 */ 996 (void)dns_acl_match(&listen_netaddr, NULL, le->acl, 997 &mgr->aclenv, &match, NULL); 998 if (match <= 0) { 999 continue; 1000 } 1001 1002 if (!adjusting && dolistenon) { 1003 setup_listenon(mgr, &interface, le->port); 1004 dolistenon = false; 1005 } 1006 1007 /* 1008 * The case of "any" IPv6 address will require 1009 * special considerations later, so remember it. 1010 */ 1011 if (family == AF_INET6 && ipv6only && ipv6pktinfo && 1012 listenon_is_ip6_any(le)) { 1013 ipv6_wildcard = true; 1014 } 1015 1016 /* 1017 * When adjusting interfaces with extra a listening 1018 * list, see if the address matches the extra list. 1019 * If it does, and is also covered by a wildcard 1020 * interface, we need to listen on the address 1021 * explicitly. 1022 */ 1023 if (adjusting) { 1024 ns_listenelt_t *ele; 1025 1026 match = 0; 1027 for (ele = ISC_LIST_HEAD(ext_listen->elts); 1028 ele != NULL; 1029 ele = ISC_LIST_NEXT(ele, link)) 1030 { 1031 (void)dns_acl_match(&listen_netaddr, 1032 NULL, ele->acl, 1033 NULL, &match, NULL); 1034 if (match > 0 && 1035 (ele->port == le->port || 1036 ele->port == 0)) { 1037 break; 1038 } else { 1039 match = 0; 1040 } 1041 } 1042 if (ipv6_wildcard && match == 0) { 1043 continue; 1044 } 1045 } 1046 1047 ifp = find_matching_interface(mgr, &listen_sockaddr); 1048 if (ifp != NULL) { 1049 ifp->generation = mgr->generation; 1050 if (le->dscp != -1 && ifp->dscp == -1) { 1051 ifp->dscp = le->dscp; 1052 } else if (le->dscp != ifp->dscp) { 1053 isc_sockaddr_format(&listen_sockaddr, 1054 sabuf, 1055 sizeof(sabuf)); 1056 isc_log_write(IFMGR_COMMON_LOGARGS, 1057 ISC_LOG_WARNING, 1058 "%s: conflicting DSCP " 1059 "values, using %d", 1060 sabuf, ifp->dscp); 1061 } 1062 } else { 1063 bool addr_in_use = false; 1064 1065 if (!adjusting && ipv6_wildcard) { 1066 continue; 1067 } 1068 1069 if (log_explicit && family == AF_INET6 && 1070 !adjusting && listenon_is_ip6_any(le)) { 1071 isc_log_write( 1072 IFMGR_COMMON_LOGARGS, 1073 verbose ? ISC_LOG_INFO 1074 : ISC_LOG_DEBUG(1), 1075 "IPv6 socket API is " 1076 "incomplete; explicitly " 1077 "binding to each IPv6 " 1078 "address separately"); 1079 log_explicit = false; 1080 } 1081 isc_sockaddr_format(&listen_sockaddr, sabuf, 1082 sizeof(sabuf)); 1083 isc_log_write( 1084 IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, 1085 "%s" 1086 "listening on %s interface " 1087 "%s, %s", 1088 (adjusting) ? "additionally " : "", 1089 (family == AF_INET) ? "IPv4" : "IPv6", 1090 interface.name, sabuf); 1091 1092 result = ns_interface_setup( 1093 mgr, &listen_sockaddr, interface.name, 1094 &ifp, (adjusting) ? false : true, 1095 le->dscp, &addr_in_use); 1096 1097 tried_listening = true; 1098 if (!addr_in_use) { 1099 all_addresses_in_use = false; 1100 } 1101 1102 if (result != ISC_R_SUCCESS) { 1103 isc_log_write(IFMGR_COMMON_LOGARGS, 1104 ISC_LOG_ERROR, 1105 "creating %s interface " 1106 "%s failed; interface " 1107 "ignored", 1108 (family == AF_INET) ? "IP" 1109 "v4" 1110 : "IP" 1111 "v" 1112 "6", 1113 interface.name); 1114 } 1115 /* Continue. */ 1116 } 1117 } 1118 continue; 1119 1120 ignore_interface: 1121 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, 1122 "ignoring %s interface %s: %s", 1123 (family == AF_INET) ? "IPv4" : "IPv6", 1124 interface.name, isc_result_totext(result)); 1125 continue; 1126 } 1127 if (result != ISC_R_NOMORE) { 1128 UNEXPECTED_ERROR(__FILE__, __LINE__, 1129 "interface iteration failed: %s", 1130 isc_result_totext(result)); 1131 } else { 1132 result = ((tried_listening && all_addresses_in_use) 1133 ? ISC_R_ADDRINUSE 1134 : ISC_R_SUCCESS); 1135 } 1136cleanup_iter: 1137 isc_interfaceiter_destroy(&iter); 1138 return (result); 1139} 1140 1141static isc_result_t 1142ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, 1143 bool verbose) { 1144 isc_result_t result; 1145 bool purge = true; 1146 1147 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1148 1149 mgr->generation++; /* Increment the generation count. */ 1150 1151 result = do_scan(mgr, ext_listen, verbose); 1152 if ((result != ISC_R_SUCCESS) && (result != ISC_R_ADDRINUSE)) { 1153 purge = false; 1154 } 1155 1156 /* 1157 * Now go through the interface list and delete anything that 1158 * does not have the current generation number. This is 1159 * how we catch interfaces that go away or change their 1160 * addresses. 1161 */ 1162 if (purge) { 1163 purge_old_interfaces(mgr); 1164 } 1165 1166 /* 1167 * Warn if we are not listening on any interface. 1168 */ 1169 if (ext_listen == NULL && ISC_LIST_EMPTY(mgr->interfaces)) { 1170 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, 1171 "not listening on any interfaces"); 1172 } 1173 1174 return (result); 1175} 1176 1177bool 1178ns_interfacemgr_islistening(ns_interfacemgr_t *mgr) { 1179 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1180 1181 return (ISC_LIST_EMPTY(mgr->interfaces) ? false : true); 1182} 1183 1184isc_result_t 1185ns_interfacemgr_scan(ns_interfacemgr_t *mgr, bool verbose) { 1186 isc_result_t result; 1187 bool unlock = false; 1188 1189 /* 1190 * Check for success because we may already be task-exclusive 1191 * at this point. Only if we succeed at obtaining an exclusive 1192 * lock now will we need to relinquish it later. 1193 */ 1194 result = isc_task_beginexclusive(mgr->excl); 1195 if (result == ISC_R_SUCCESS) { 1196 unlock = true; 1197 } 1198 1199 result = ns_interfacemgr_scan0(mgr, NULL, verbose); 1200 1201 if (unlock) { 1202 isc_task_endexclusive(mgr->excl); 1203 } 1204 1205 return (result); 1206} 1207 1208isc_result_t 1209ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list, 1210 bool verbose) { 1211 return (ns_interfacemgr_scan0(mgr, list, verbose)); 1212} 1213 1214void 1215ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { 1216 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1217 1218 LOCK(&mgr->lock); 1219 ns_listenlist_detach(&mgr->listenon4); 1220 ns_listenlist_attach(value, &mgr->listenon4); 1221 UNLOCK(&mgr->lock); 1222} 1223 1224void 1225ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { 1226 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1227 1228 LOCK(&mgr->lock); 1229 ns_listenlist_detach(&mgr->listenon6); 1230 ns_listenlist_attach(value, &mgr->listenon6); 1231 UNLOCK(&mgr->lock); 1232} 1233 1234void 1235ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) { 1236 ns_interface_t *interface; 1237 1238 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1239 1240 LOCK(&mgr->lock); 1241 interface = ISC_LIST_HEAD(mgr->interfaces); 1242 while (interface != NULL) { 1243 if (interface->clientmgr != NULL) { 1244 ns_client_dumprecursing(f, interface->clientmgr); 1245 } 1246 interface = ISC_LIST_NEXT(interface, link); 1247 } 1248 UNLOCK(&mgr->lock); 1249} 1250 1251bool 1252ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, 1253 const isc_sockaddr_t *addr) { 1254 isc_sockaddr_t *old; 1255 bool result = false; 1256 1257 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1258 /* 1259 * If the manager is shutting down it's safer to 1260 * return true. 1261 */ 1262 if (atomic_load(&mgr->shuttingdown)) { 1263 return (true); 1264 } 1265 LOCK(&mgr->lock); 1266 for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL; 1267 old = ISC_LIST_NEXT(old, link)) 1268 { 1269 if (isc_sockaddr_equal(old, addr)) { 1270 result = true; 1271 break; 1272 } 1273 } 1274 UNLOCK(&mgr->lock); 1275 1276 return (result); 1277} 1278 1279ns_server_t * 1280ns_interfacemgr_getserver(ns_interfacemgr_t *mgr) { 1281 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1282 1283 return (mgr->sctx); 1284} 1285 1286ns_interface_t * 1287ns__interfacemgr_getif(ns_interfacemgr_t *mgr) { 1288 ns_interface_t *head; 1289 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1290 LOCK(&mgr->lock); 1291 head = ISC_LIST_HEAD(mgr->interfaces); 1292 UNLOCK(&mgr->lock); 1293 return (head); 1294} 1295 1296ns_interface_t * 1297ns__interfacemgr_nextif(ns_interface_t *ifp) { 1298 ns_interface_t *next; 1299 LOCK(&ifp->lock); 1300 next = ISC_LIST_NEXT(ifp, link); 1301 UNLOCK(&ifp->lock); 1302 return (next); 1303} 1304