interfacemgr.c revision 1.7
1/* $NetBSD: interfacemgr.c,v 1.7 2020/05/24 19:46:29 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->mgr->sctx, 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 ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp->mgr->sctx); 490 491#if 0 492#ifndef ISC_ALLOW_MAPPED 493 isc_socket_ipv6only(ifp->tcpsocket,true); 494#endif /* ifndef ISC_ALLOW_MAPPED */ 495 496 if (ifp->dscp != -1) { 497 isc_socket_dscp(ifp->tcpsocket,ifp->dscp); 498 } 499 500 (void)isc_socket_filter(ifp->tcpsocket,"dataready"); 501#endif /* if 0 */ 502 return (result); 503} 504 505static isc_result_t 506ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, 507 const char *name, ns_interface_t **ifpret, bool accept_tcp, 508 isc_dscp_t dscp, bool *addr_in_use) { 509 isc_result_t result; 510 ns_interface_t *ifp = NULL; 511 REQUIRE(ifpret != NULL && *ifpret == NULL); 512 REQUIRE(addr_in_use == NULL || *addr_in_use == false); 513 514 result = ns_interface_create(mgr, addr, name, &ifp); 515 if (result != ISC_R_SUCCESS) { 516 return (result); 517 } 518 519 ifp->dscp = dscp; 520 521 result = ns_interface_listenudp(ifp); 522 if (result != ISC_R_SUCCESS) { 523 if ((result == ISC_R_ADDRINUSE) && (addr_in_use != NULL)) { 524 *addr_in_use = true; 525 } 526 goto cleanup_interface; 527 } 528 529 if (((mgr->sctx->options & NS_SERVER_NOTCP) == 0) && accept_tcp == true) 530 { 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_detach(&ifp); 555 return (result); 556} 557 558void 559ns_interface_shutdown(ns_interface_t *ifp) { 560 if (ifp->udplistensocket != NULL) { 561 isc_nm_stoplistening(ifp->udplistensocket); 562 isc_nmsocket_detach(&ifp->udplistensocket); 563 } 564 if (ifp->tcplistensocket != NULL) { 565 isc_nm_stoplistening(ifp->tcplistensocket); 566 isc_nmsocket_detach(&ifp->tcplistensocket); 567 } 568 if (ifp->clientmgr != NULL) { 569 ns_clientmgr_destroy(&ifp->clientmgr); 570 } 571} 572 573static void 574ns_interface_destroy(ns_interface_t *ifp) { 575 REQUIRE(NS_INTERFACE_VALID(ifp)); 576 577 isc_mem_t *mctx = ifp->mgr->mctx; 578 579 ns_interface_shutdown(ifp); 580 581 for (int disp = 0; disp < ifp->nudpdispatch; disp++) { 582 if (ifp->udpdispatch[disp] != NULL) { 583 dns_dispatch_changeattributes( 584 ifp->udpdispatch[disp], 0, 585 DNS_DISPATCHATTR_NOLISTEN); 586 dns_dispatch_detach(&(ifp->udpdispatch[disp])); 587 } 588 } 589 590 if (ifp->tcpsocket != NULL) { 591 isc_socket_detach(&ifp->tcpsocket); 592 } 593 594 isc_mutex_destroy(&ifp->lock); 595 596 ns_interfacemgr_detach(&ifp->mgr); 597 598 isc_refcount_destroy(&ifp->ntcpactive); 599 isc_refcount_destroy(&ifp->ntcpaccepting); 600 601 ifp->magic = 0; 602 603 isc_mem_put(mctx, ifp, sizeof(*ifp)); 604} 605 606void 607ns_interface_attach(ns_interface_t *source, ns_interface_t **target) { 608 REQUIRE(NS_INTERFACE_VALID(source)); 609 isc_refcount_increment(&source->references); 610 *target = source; 611} 612 613void 614ns_interface_detach(ns_interface_t **targetp) { 615 ns_interface_t *target = *targetp; 616 *targetp = NULL; 617 REQUIRE(target != NULL); 618 REQUIRE(NS_INTERFACE_VALID(target)); 619 if (isc_refcount_decrement(&target->references) == 1) { 620 ns_interface_destroy(target); 621 } 622} 623 624/*% 625 * Search the interface list for an interface whose address and port 626 * both match those of 'addr'. Return a pointer to it, or NULL if not found. 627 */ 628static ns_interface_t * 629find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) { 630 ns_interface_t *ifp; 631 LOCK(&mgr->lock); 632 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; 633 ifp = ISC_LIST_NEXT(ifp, link)) 634 { 635 if (isc_sockaddr_equal(&ifp->addr, addr)) { 636 break; 637 } 638 } 639 UNLOCK(&mgr->lock); 640 return (ifp); 641} 642 643/*% 644 * Remove any interfaces whose generation number is not the current one. 645 */ 646static void 647purge_old_interfaces(ns_interfacemgr_t *mgr) { 648 ns_interface_t *ifp, *next; 649 LOCK(&mgr->lock); 650 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) { 651 INSIST(NS_INTERFACE_VALID(ifp)); 652 next = ISC_LIST_NEXT(ifp, link); 653 if (ifp->generation != mgr->generation) { 654 char sabuf[256]; 655 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link); 656 isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf)); 657 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, 658 "no longer listening on %s", sabuf); 659 ns_interface_shutdown(ifp); 660 ns_interface_detach(&ifp); 661 } 662 } 663 UNLOCK(&mgr->lock); 664} 665 666static isc_result_t 667clearacl(isc_mem_t *mctx, dns_acl_t **aclp) { 668 dns_acl_t *newacl = NULL; 669 isc_result_t result; 670 result = dns_acl_create(mctx, 0, &newacl); 671 if (result != ISC_R_SUCCESS) { 672 return (result); 673 } 674 dns_acl_detach(aclp); 675 dns_acl_attach(newacl, aclp); 676 dns_acl_detach(&newacl); 677 return (ISC_R_SUCCESS); 678} 679 680static bool 681listenon_is_ip6_any(ns_listenelt_t *elt) { 682 REQUIRE(elt && elt->acl); 683 return (dns_acl_isany(elt->acl)); 684} 685 686static isc_result_t 687setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) { 688 isc_result_t result; 689 unsigned int prefixlen; 690 isc_netaddr_t *netaddr; 691 692 netaddr = &interface->address; 693 694 /* First add localhost address */ 695 prefixlen = (netaddr->family == AF_INET) ? 32 : 128; 696 result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable, netaddr, 697 prefixlen, true); 698 if (result != ISC_R_SUCCESS) { 699 return (result); 700 } 701 702 /* Then add localnets prefix */ 703 result = isc_netaddr_masktoprefixlen(&interface->netmask, &prefixlen); 704 705 /* Non contiguous netmasks not allowed by IPv6 arch. */ 706 if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6) { 707 return (result); 708 } 709 710 if (result != ISC_R_SUCCESS) { 711 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, 712 "omitting IPv4 interface %s from " 713 "localnets ACL: %s", 714 interface->name, isc_result_totext(result)); 715 return (ISC_R_SUCCESS); 716 } 717 718 if (prefixlen == 0U) { 719 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, 720 "omitting %s interface %s from localnets ACL: " 721 "zero prefix length detected", 722 (netaddr->family == AF_INET) ? "IPv4" : "IPv6", 723 interface->name); 724 return (ISC_R_SUCCESS); 725 } 726 727 result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable, netaddr, 728 prefixlen, true); 729 if (result != ISC_R_SUCCESS) { 730 return (result); 731 } 732 733 return (ISC_R_SUCCESS); 734} 735 736static void 737setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface, 738 in_port_t port) { 739 isc_sockaddr_t *addr; 740 isc_sockaddr_t *old; 741 742 addr = isc_mem_get(mgr->mctx, sizeof(*addr)); 743 744 isc_sockaddr_fromnetaddr(addr, &interface->address, port); 745 746 LOCK(&mgr->lock); 747 for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL; 748 old = ISC_LIST_NEXT(old, link)) 749 { 750 if (isc_sockaddr_equal(addr, old)) { 751 break; 752 } 753 } 754 755 if (old != NULL) { 756 isc_mem_put(mgr->mctx, addr, sizeof(*addr)); 757 } else { 758 ISC_LIST_APPEND(mgr->listenon, addr, link); 759 } 760 UNLOCK(&mgr->lock); 761} 762 763static void 764clearlistenon(ns_interfacemgr_t *mgr) { 765 isc_sockaddr_t *old; 766 767 LOCK(&mgr->lock); 768 old = ISC_LIST_HEAD(mgr->listenon); 769 while (old != NULL) { 770 ISC_LIST_UNLINK(mgr->listenon, old, link); 771 isc_mem_put(mgr->mctx, old, sizeof(*old)); 772 old = ISC_LIST_HEAD(mgr->listenon); 773 } 774 UNLOCK(&mgr->lock); 775} 776 777static isc_result_t 778do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, bool verbose) { 779 isc_interfaceiter_t *iter = NULL; 780 bool scan_ipv4 = false; 781 bool scan_ipv6 = false; 782 bool adjusting = false; 783 bool ipv6only = true; 784 bool ipv6pktinfo = true; 785 isc_result_t result; 786 isc_netaddr_t zero_address, zero_address6; 787 ns_listenelt_t *le; 788 isc_sockaddr_t listen_addr; 789 ns_interface_t *ifp; 790 bool log_explicit = false; 791 bool dolistenon; 792 char sabuf[ISC_SOCKADDR_FORMATSIZE]; 793 bool tried_listening; 794 bool all_addresses_in_use; 795 796 if (ext_listen != NULL) { 797 adjusting = true; 798 } 799 800 if (isc_net_probeipv6() == ISC_R_SUCCESS) { 801 scan_ipv6 = true; 802 } else if ((mgr->sctx->options & NS_SERVER_DISABLE6) == 0) { 803 isc_log_write(IFMGR_COMMON_LOGARGS, 804 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), 805 "no IPv6 interfaces found"); 806 } 807 808 if (isc_net_probeipv4() == ISC_R_SUCCESS) { 809 scan_ipv4 = true; 810 } else if ((mgr->sctx->options & NS_SERVER_DISABLE4) == 0) { 811 isc_log_write(IFMGR_COMMON_LOGARGS, 812 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), 813 "no IPv4 interfaces found"); 814 } 815 816 /* 817 * A special, but typical case; listen-on-v6 { any; }. 818 * When we can make the socket IPv6-only, open a single wildcard 819 * socket for IPv6 communication. Otherwise, make separate 820 * socket for each IPv6 address in order to avoid accepting IPv4 821 * packets as the form of mapped addresses unintentionally 822 * unless explicitly allowed. 823 */ 824#ifndef ISC_ALLOW_MAPPED 825 if (scan_ipv6 == true && isc_net_probe_ipv6only() != ISC_R_SUCCESS) { 826 ipv6only = false; 827 log_explicit = true; 828 } 829#endif /* ifndef ISC_ALLOW_MAPPED */ 830 if (scan_ipv6 == true && isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) { 831 ipv6pktinfo = false; 832 log_explicit = true; 833 } 834 if (scan_ipv6 == true && ipv6only && ipv6pktinfo) { 835 for (le = ISC_LIST_HEAD(mgr->listenon6->elts); le != NULL; 836 le = ISC_LIST_NEXT(le, link)) 837 { 838 struct in6_addr in6a; 839 840 if (!listenon_is_ip6_any(le)) { 841 continue; 842 } 843 844 in6a = in6addr_any; 845 isc_sockaddr_fromin6(&listen_addr, &in6a, le->port); 846 847 ifp = find_matching_interface(mgr, &listen_addr); 848 if (ifp != NULL) { 849 ifp->generation = mgr->generation; 850 if (le->dscp != -1 && ifp->dscp == -1) { 851 ifp->dscp = le->dscp; 852 } else if (le->dscp != ifp->dscp) { 853 isc_sockaddr_format(&listen_addr, sabuf, 854 sizeof(sabuf)); 855 isc_log_write(IFMGR_COMMON_LOGARGS, 856 ISC_LOG_WARNING, 857 "%s: conflicting DSCP " 858 "values, using %d", 859 sabuf, ifp->dscp); 860 } 861 } else { 862 isc_log_write(IFMGR_COMMON_LOGARGS, 863 ISC_LOG_INFO, 864 "listening on IPv6 " 865 "interfaces, port %u", 866 le->port); 867 result = ns_interface_setup(mgr, &listen_addr, 868 "<any>", &ifp, true, 869 le->dscp, NULL); 870 if (result == ISC_R_SUCCESS) { 871 ifp->flags |= NS_INTERFACEFLAG_ANYADDR; 872 } else { 873 isc_log_write(IFMGR_COMMON_LOGARGS, 874 ISC_LOG_ERROR, 875 "listening on all IPv6 " 876 "interfaces failed"); 877 } 878 /* Continue. */ 879 } 880 } 881 } 882 883 isc_netaddr_any(&zero_address); 884 isc_netaddr_any6(&zero_address6); 885 886 result = isc_interfaceiter_create(mgr->mctx, &iter); 887 if (result != ISC_R_SUCCESS) { 888 return (result); 889 } 890 891 if (adjusting == false) { 892 result = clearacl(mgr->mctx, &mgr->aclenv.localhost); 893 if (result != ISC_R_SUCCESS) { 894 goto cleanup_iter; 895 } 896 result = clearacl(mgr->mctx, &mgr->aclenv.localnets); 897 if (result != ISC_R_SUCCESS) { 898 goto cleanup_iter; 899 } 900 clearlistenon(mgr); 901 } 902 903 tried_listening = false; 904 all_addresses_in_use = true; 905 for (result = isc_interfaceiter_first(iter); result == ISC_R_SUCCESS; 906 result = isc_interfaceiter_next(iter)) 907 { 908 isc_interface_t interface; 909 ns_listenlist_t *ll; 910 unsigned int family; 911 912 result = isc_interfaceiter_current(iter, &interface); 913 if (result != ISC_R_SUCCESS) { 914 break; 915 } 916 917 family = interface.address.family; 918 if (family != AF_INET && family != AF_INET6) { 919 continue; 920 } 921 if (scan_ipv4 == false && family == AF_INET) { 922 continue; 923 } 924 if (scan_ipv6 == false && family == AF_INET6) { 925 continue; 926 } 927 928 /* 929 * Test for the address being nonzero rather than testing 930 * INTERFACE_F_UP, because on some systems the latter 931 * follows the media state and we could end up ignoring 932 * the interface for an entire rescan interval due to 933 * a temporary media glitch at rescan time. 934 */ 935 if (family == AF_INET && 936 isc_netaddr_equal(&interface.address, &zero_address)) { 937 continue; 938 } 939 if (family == AF_INET6 && 940 isc_netaddr_equal(&interface.address, &zero_address6)) { 941 continue; 942 } 943 944 if (adjusting == false) { 945 /* 946 * If running with -T fixedlocal, then we only 947 * want 127.0.0.1 and ::1 in the localhost ACL. 948 */ 949 if (((mgr->sctx->options & NS_SERVER_FIXEDLOCAL) != 950 0) && 951 !isc_netaddr_isloopback(&interface.address)) 952 { 953 goto listenon; 954 } 955 956 result = setup_locals(mgr, &interface); 957 if (result != ISC_R_SUCCESS) { 958 goto ignore_interface; 959 } 960 } 961 962 listenon: 963 ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6; 964 dolistenon = true; 965 for (le = ISC_LIST_HEAD(ll->elts); le != NULL; 966 le = ISC_LIST_NEXT(le, link)) { 967 int match; 968 bool ipv6_wildcard = false; 969 isc_netaddr_t listen_netaddr; 970 isc_sockaddr_t listen_sockaddr; 971 972 /* 973 * Construct a socket address for this IP/port 974 * combination. 975 */ 976 if (family == AF_INET) { 977 isc_netaddr_fromin(&listen_netaddr, 978 &interface.address.type.in); 979 } else { 980 isc_netaddr_fromin6( 981 &listen_netaddr, 982 &interface.address.type.in6); 983 isc_netaddr_setzone(&listen_netaddr, 984 interface.address.zone); 985 } 986 isc_sockaddr_fromnetaddr(&listen_sockaddr, 987 &listen_netaddr, le->port); 988 989 /* 990 * See if the address matches the listen-on statement; 991 * if not, ignore the interface. 992 */ 993 (void)dns_acl_match(&listen_netaddr, NULL, le->acl, 994 &mgr->aclenv, &match, NULL); 995 if (match <= 0) { 996 continue; 997 } 998 999 if (adjusting == false && dolistenon == true) { 1000 setup_listenon(mgr, &interface, le->port); 1001 dolistenon = false; 1002 } 1003 1004 /* 1005 * The case of "any" IPv6 address will require 1006 * special considerations later, so remember it. 1007 */ 1008 if (family == AF_INET6 && ipv6only && ipv6pktinfo && 1009 listenon_is_ip6_any(le)) { 1010 ipv6_wildcard = true; 1011 } 1012 1013 /* 1014 * When adjusting interfaces with extra a listening 1015 * list, see if the address matches the extra list. 1016 * If it does, and is also covered by a wildcard 1017 * interface, we need to listen on the address 1018 * explicitly. 1019 */ 1020 if (adjusting == true) { 1021 ns_listenelt_t *ele; 1022 1023 match = 0; 1024 for (ele = ISC_LIST_HEAD(ext_listen->elts); 1025 ele != NULL; 1026 ele = ISC_LIST_NEXT(ele, link)) 1027 { 1028 (void)dns_acl_match(&listen_netaddr, 1029 NULL, ele->acl, 1030 NULL, &match, NULL); 1031 if (match > 0 && 1032 (ele->port == le->port || 1033 ele->port == 0)) { 1034 break; 1035 } else { 1036 match = 0; 1037 } 1038 } 1039 if (ipv6_wildcard == true && match == 0) { 1040 continue; 1041 } 1042 } 1043 1044 ifp = find_matching_interface(mgr, &listen_sockaddr); 1045 if (ifp != NULL) { 1046 ifp->generation = mgr->generation; 1047 if (le->dscp != -1 && ifp->dscp == -1) { 1048 ifp->dscp = le->dscp; 1049 } else if (le->dscp != ifp->dscp) { 1050 isc_sockaddr_format(&listen_sockaddr, 1051 sabuf, 1052 sizeof(sabuf)); 1053 isc_log_write(IFMGR_COMMON_LOGARGS, 1054 ISC_LOG_WARNING, 1055 "%s: conflicting DSCP " 1056 "values, using %d", 1057 sabuf, ifp->dscp); 1058 } 1059 } else { 1060 bool addr_in_use = false; 1061 1062 if (adjusting == false && ipv6_wildcard == true) 1063 { 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 == true) ? "additionally " 1087 : "", 1088 (family == AF_INET) ? "IPv4" : "IPv6", 1089 interface.name, sabuf); 1090 1091 result = ns_interface_setup( 1092 mgr, &listen_sockaddr, interface.name, 1093 &ifp, 1094 (adjusting == true) ? 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_interface_t * 1280ns__interfacemgr_getif(ns_interfacemgr_t *mgr) { 1281 ns_interface_t *head; 1282 REQUIRE(NS_INTERFACEMGR_VALID(mgr)); 1283 LOCK(&mgr->lock); 1284 head = ISC_LIST_HEAD(mgr->interfaces); 1285 UNLOCK(&mgr->lock); 1286 return (head); 1287} 1288 1289ns_interface_t * 1290ns__interfacemgr_nextif(ns_interface_t *ifp) { 1291 ns_interface_t *next; 1292 LOCK(&ifp->lock); 1293 next = ISC_LIST_NEXT(ifp, link); 1294 UNLOCK(&ifp->lock); 1295 return (next); 1296} 1297