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