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