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