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