1 /*
2 * Copyright (C) 2004-2009, 2011-2015 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2002 Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /* $Id: interfacemgr.c,v 1.101 2011/11/09 18:44:03 each Exp $ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <isc/interfaceiter.h>
25 #include <isc/os.h>
26 #include <isc/string.h>
27 #include <isc/task.h>
28 #include <isc/util.h>
29
30 #include <dns/acl.h>
31 #include <dns/dispatch.h>
32
33 #include <named/client.h>
34 #include <named/log.h>
35 #include <named/interfacemgr.h>
36
37 #define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G')
38 #define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC)
39
40 #define IFMGR_COMMON_LOGARGS \
41 ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR
42
43 /*% nameserver interface manager structure */
44 struct ns_interfacemgr {
45 unsigned int magic; /*%< Magic number. */
46 int references;
47 isc_mutex_t lock;
48 isc_mem_t * mctx; /*%< Memory context. */
49 isc_taskmgr_t * taskmgr; /*%< Task manager. */
50 isc_socketmgr_t * socketmgr; /*%< Socket manager. */
51 dns_dispatchmgr_t * dispatchmgr;
52 unsigned int generation; /*%< Current generation no. */
53 ns_listenlist_t * listenon4;
54 ns_listenlist_t * listenon6;
55 dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */
56 ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */
57 ISC_LIST(isc_sockaddr_t) listenon;
58 };
59
60 static void
61 purge_old_interfaces(ns_interfacemgr_t *mgr);
62
63 static void
64 clearlistenon(ns_interfacemgr_t *mgr);
65
66 isc_result_t
ns_interfacemgr_create(isc_mem_t * mctx,isc_taskmgr_t * taskmgr,isc_socketmgr_t * socketmgr,dns_dispatchmgr_t * dispatchmgr,ns_interfacemgr_t ** mgrp)67 ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
68 isc_socketmgr_t *socketmgr,
69 dns_dispatchmgr_t *dispatchmgr,
70 ns_interfacemgr_t **mgrp)
71 {
72 isc_result_t result;
73 ns_interfacemgr_t *mgr;
74
75 REQUIRE(mctx != NULL);
76 REQUIRE(mgrp != NULL);
77 REQUIRE(*mgrp == NULL);
78
79 mgr = isc_mem_get(mctx, sizeof(*mgr));
80 if (mgr == NULL)
81 return (ISC_R_NOMEMORY);
82
83 mgr->mctx = NULL;
84 isc_mem_attach(mctx, &mgr->mctx);
85
86 result = isc_mutex_init(&mgr->lock);
87 if (result != ISC_R_SUCCESS)
88 goto cleanup_mem;
89
90 mgr->taskmgr = taskmgr;
91 mgr->socketmgr = socketmgr;
92 mgr->dispatchmgr = dispatchmgr;
93 mgr->generation = 1;
94 mgr->listenon4 = NULL;
95 mgr->listenon6 = NULL;
96
97 ISC_LIST_INIT(mgr->interfaces);
98 ISC_LIST_INIT(mgr->listenon);
99
100 /*
101 * The listen-on lists are initially empty.
102 */
103 result = ns_listenlist_create(mctx, &mgr->listenon4);
104 if (result != ISC_R_SUCCESS)
105 goto cleanup_mem;
106 ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);
107
108 result = dns_aclenv_init(mctx, &mgr->aclenv);
109 if (result != ISC_R_SUCCESS)
110 goto cleanup_listenon;
111
112 mgr->references = 1;
113 mgr->magic = IFMGR_MAGIC;
114 *mgrp = mgr;
115 return (ISC_R_SUCCESS);
116
117 cleanup_listenon:
118 ns_listenlist_detach(&mgr->listenon4);
119 ns_listenlist_detach(&mgr->listenon6);
120 cleanup_mem:
121 isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
122 return (result);
123 }
124
125 static void
ns_interfacemgr_destroy(ns_interfacemgr_t * mgr)126 ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) {
127 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
128 dns_aclenv_destroy(&mgr->aclenv);
129 ns_listenlist_detach(&mgr->listenon4);
130 ns_listenlist_detach(&mgr->listenon6);
131 clearlistenon(mgr);
132 DESTROYLOCK(&mgr->lock);
133 mgr->magic = 0;
134 isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr));
135 }
136
137 dns_aclenv_t *
ns_interfacemgr_getaclenv(ns_interfacemgr_t * mgr)138 ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
139 return (&mgr->aclenv);
140 }
141
142 void
ns_interfacemgr_attach(ns_interfacemgr_t * source,ns_interfacemgr_t ** target)143 ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) {
144 REQUIRE(NS_INTERFACEMGR_VALID(source));
145 LOCK(&source->lock);
146 INSIST(source->references > 0);
147 source->references++;
148 UNLOCK(&source->lock);
149 *target = source;
150 }
151
152 void
ns_interfacemgr_detach(ns_interfacemgr_t ** targetp)153 ns_interfacemgr_detach(ns_interfacemgr_t **targetp) {
154 isc_result_t need_destroy = ISC_FALSE;
155 ns_interfacemgr_t *target = *targetp;
156 REQUIRE(target != NULL);
157 REQUIRE(NS_INTERFACEMGR_VALID(target));
158 LOCK(&target->lock);
159 REQUIRE(target->references > 0);
160 target->references--;
161 if (target->references == 0)
162 need_destroy = ISC_TRUE;
163 UNLOCK(&target->lock);
164 if (need_destroy)
165 ns_interfacemgr_destroy(target);
166 *targetp = NULL;
167 }
168
169 void
ns_interfacemgr_shutdown(ns_interfacemgr_t * mgr)170 ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
171 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
172
173 /*%
174 * Shut down and detach all interfaces.
175 * By incrementing the generation count, we make purge_old_interfaces()
176 * consider all interfaces "old".
177 */
178 mgr->generation++;
179 purge_old_interfaces(mgr);
180 }
181
182
183 static isc_result_t
ns_interface_create(ns_interfacemgr_t * mgr,isc_sockaddr_t * addr,const char * name,ns_interface_t ** ifpret)184 ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
185 const char *name, ns_interface_t **ifpret)
186 {
187 ns_interface_t *ifp;
188 isc_result_t result;
189 int disp;
190
191 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
192
193 ifp = isc_mem_get(mgr->mctx, sizeof(*ifp));
194 if (ifp == NULL)
195 return (ISC_R_NOMEMORY);
196
197 ifp->mgr = NULL;
198 ifp->generation = mgr->generation;
199 ifp->addr = *addr;
200 ifp->flags = 0;
201 strncpy(ifp->name, name, sizeof(ifp->name));
202 ifp->name[sizeof(ifp->name)-1] = '\0';
203 ifp->clientmgr = NULL;
204
205 result = isc_mutex_init(&ifp->lock);
206 if (result != ISC_R_SUCCESS)
207 goto lock_create_failure;
208
209 result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr,
210 ns_g_timermgr,
211 &ifp->clientmgr);
212 if (result != ISC_R_SUCCESS) {
213 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
214 "ns_clientmgr_create() failed: %s",
215 isc_result_totext(result));
216 goto clientmgr_create_failure;
217 }
218
219 for (disp = 0; disp < MAX_UDP_DISPATCH; disp++)
220 ifp->udpdispatch[disp] = NULL;
221
222 ifp->tcpsocket = NULL;
223
224 /*
225 * Create a single TCP client object. It will replace itself
226 * with a new one as soon as it gets a connection, so the actual
227 * connections will be handled in parallel even though there is
228 * only one client initially.
229 */
230 ifp->ntcptarget = 1;
231 ifp->ntcpcurrent = 0;
232 ifp->nudpdispatch = 0;
233
234 ISC_LINK_INIT(ifp, link);
235
236 ns_interfacemgr_attach(mgr, &ifp->mgr);
237 ISC_LIST_APPEND(mgr->interfaces, ifp, link);
238
239 ifp->references = 1;
240 ifp->magic = IFACE_MAGIC;
241 *ifpret = ifp;
242
243 return (ISC_R_SUCCESS);
244
245 clientmgr_create_failure:
246 DESTROYLOCK(&ifp->lock);
247
248 lock_create_failure:
249 ifp->magic = 0;
250 isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));
251
252 return (ISC_R_UNEXPECTED);
253 }
254
255 static isc_result_t
ns_interface_listenudp(ns_interface_t * ifp)256 ns_interface_listenudp(ns_interface_t *ifp) {
257 isc_result_t result;
258 unsigned int attrs;
259 unsigned int attrmask;
260 int disp, i;
261
262 attrs = 0;
263 attrs |= DNS_DISPATCHATTR_UDP;
264 if (isc_sockaddr_pf(&ifp->addr) == AF_INET)
265 attrs |= DNS_DISPATCHATTR_IPV4;
266 else
267 attrs |= DNS_DISPATCHATTR_IPV6;
268 attrs |= DNS_DISPATCHATTR_NOLISTEN;
269 attrmask = 0;
270 attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
271 attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
272
273 ifp->nudpdispatch = ISC_MIN(ns_g_udpdisp, MAX_UDP_DISPATCH);
274 for (disp = 0; disp < ifp->nudpdispatch; disp++) {
275 result = dns_dispatch_getudp_dup(ifp->mgr->dispatchmgr,
276 ns_g_socketmgr,
277 ns_g_taskmgr, &ifp->addr,
278 4096, 1000, 32768, 8219, 8237,
279 attrs, attrmask,
280 &ifp->udpdispatch[disp],
281 disp == 0
282 ? NULL
283 : ifp->udpdispatch[0]);
284 if (result != ISC_R_SUCCESS) {
285 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
286 "could not listen on UDP socket: %s",
287 isc_result_totext(result));
288 goto udp_dispatch_failure;
289 }
290
291 }
292
293 result = ns_clientmgr_createclients(ifp->clientmgr, ifp->nudpdispatch,
294 ifp, ISC_FALSE);
295 if (result != ISC_R_SUCCESS) {
296 UNEXPECTED_ERROR(__FILE__, __LINE__,
297 "UDP ns_clientmgr_createclients(): %s",
298 isc_result_totext(result));
299 goto addtodispatch_failure;
300 }
301
302 return (ISC_R_SUCCESS);
303
304 addtodispatch_failure:
305 for (i = disp - 1; i >= 0; i--) {
306 dns_dispatch_changeattributes(ifp->udpdispatch[i], 0,
307 DNS_DISPATCHATTR_NOLISTEN);
308 dns_dispatch_detach(&(ifp->udpdispatch[i]));
309 }
310 ifp->nudpdispatch = 0;
311
312 udp_dispatch_failure:
313 return (result);
314 }
315
316 static isc_result_t
ns_interface_accepttcp(ns_interface_t * ifp)317 ns_interface_accepttcp(ns_interface_t *ifp) {
318 isc_result_t result;
319
320 /*
321 * Open a TCP socket.
322 */
323 result = isc_socket_create(ifp->mgr->socketmgr,
324 isc_sockaddr_pf(&ifp->addr),
325 isc_sockettype_tcp,
326 &ifp->tcpsocket);
327 if (result != ISC_R_SUCCESS) {
328 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
329 "creating TCP socket: %s",
330 isc_result_totext(result));
331 goto tcp_socket_failure;
332 }
333 isc_socket_setname(ifp->tcpsocket, "dispatcher", NULL);
334 #ifndef ISC_ALLOW_MAPPED
335 isc_socket_ipv6only(ifp->tcpsocket, ISC_TRUE);
336 #endif
337 result = isc_socket_bind(ifp->tcpsocket, &ifp->addr,
338 ISC_SOCKET_REUSEADDRESS);
339 if (result != ISC_R_SUCCESS) {
340 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
341 "binding TCP socket: %s",
342 isc_result_totext(result));
343 goto tcp_bind_failure;
344 }
345 result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
346 if (result != ISC_R_SUCCESS) {
347 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
348 "listening on TCP socket: %s",
349 isc_result_totext(result));
350 goto tcp_listen_failure;
351 }
352
353 /*
354 * If/when there a multiple filters listen to the
355 * result.
356 */
357 (void)isc_socket_filter(ifp->tcpsocket, "dataready");
358
359 result = ns_clientmgr_createclients(ifp->clientmgr,
360 ifp->ntcptarget, ifp,
361 ISC_TRUE);
362 if (result != ISC_R_SUCCESS) {
363 UNEXPECTED_ERROR(__FILE__, __LINE__,
364 "TCP ns_clientmgr_createclients(): %s",
365 isc_result_totext(result));
366 goto accepttcp_failure;
367 }
368 return (ISC_R_SUCCESS);
369
370 accepttcp_failure:
371 tcp_listen_failure:
372 tcp_bind_failure:
373 isc_socket_detach(&ifp->tcpsocket);
374 tcp_socket_failure:
375 return (ISC_R_SUCCESS);
376 }
377
378 static isc_result_t
ns_interface_setup(ns_interfacemgr_t * mgr,isc_sockaddr_t * addr,const char * name,ns_interface_t ** ifpret,isc_boolean_t accept_tcp)379 ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
380 const char *name, ns_interface_t **ifpret,
381 isc_boolean_t accept_tcp)
382 {
383 isc_result_t result;
384 ns_interface_t *ifp = NULL;
385 REQUIRE(ifpret != NULL && *ifpret == NULL);
386
387 result = ns_interface_create(mgr, addr, name, &ifp);
388 if (result != ISC_R_SUCCESS)
389 return (result);
390
391 result = ns_interface_listenudp(ifp);
392 if (result != ISC_R_SUCCESS)
393 goto cleanup_interface;
394
395 if (!ns_g_notcp && accept_tcp == ISC_TRUE) {
396 result = ns_interface_accepttcp(ifp);
397 if (result != ISC_R_SUCCESS) {
398 /*
399 * XXXRTH We don't currently have a way to easily stop
400 * dispatch service, so we currently return
401 * ISC_R_SUCCESS (the UDP stuff will work even if TCP
402 * creation failed). This will be fixed later.
403 */
404 result = ISC_R_SUCCESS;
405 }
406 }
407 *ifpret = ifp;
408 return (result);
409
410 cleanup_interface:
411 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
412 ns_interface_detach(&ifp);
413 return (result);
414 }
415
416 void
ns_interface_shutdown(ns_interface_t * ifp)417 ns_interface_shutdown(ns_interface_t *ifp) {
418 if (ifp->clientmgr != NULL)
419 ns_clientmgr_destroy(&ifp->clientmgr);
420 }
421
422 static void
ns_interface_destroy(ns_interface_t * ifp)423 ns_interface_destroy(ns_interface_t *ifp) {
424 isc_mem_t *mctx = ifp->mgr->mctx;
425 int disp;
426
427 REQUIRE(NS_INTERFACE_VALID(ifp));
428
429 ns_interface_shutdown(ifp);
430
431 for (disp = 0; disp < ifp->nudpdispatch; disp++)
432 if (ifp->udpdispatch[disp] != NULL) {
433 dns_dispatch_changeattributes(ifp->udpdispatch[disp], 0,
434 DNS_DISPATCHATTR_NOLISTEN);
435 dns_dispatch_detach(&(ifp->udpdispatch[disp]));
436 }
437
438 if (ifp->tcpsocket != NULL)
439 isc_socket_detach(&ifp->tcpsocket);
440
441 DESTROYLOCK(&ifp->lock);
442
443 ns_interfacemgr_detach(&ifp->mgr);
444
445 ifp->magic = 0;
446 isc_mem_put(mctx, ifp, sizeof(*ifp));
447 }
448
449 void
ns_interface_attach(ns_interface_t * source,ns_interface_t ** target)450 ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
451 REQUIRE(NS_INTERFACE_VALID(source));
452 LOCK(&source->lock);
453 INSIST(source->references > 0);
454 source->references++;
455 UNLOCK(&source->lock);
456 *target = source;
457 }
458
459 void
ns_interface_detach(ns_interface_t ** targetp)460 ns_interface_detach(ns_interface_t **targetp) {
461 isc_result_t need_destroy = ISC_FALSE;
462 ns_interface_t *target = *targetp;
463 REQUIRE(target != NULL);
464 REQUIRE(NS_INTERFACE_VALID(target));
465 LOCK(&target->lock);
466 REQUIRE(target->references > 0);
467 target->references--;
468 if (target->references == 0)
469 need_destroy = ISC_TRUE;
470 UNLOCK(&target->lock);
471 if (need_destroy)
472 ns_interface_destroy(target);
473 *targetp = NULL;
474 }
475
476 /*%
477 * Search the interface list for an interface whose address and port
478 * both match those of 'addr'. Return a pointer to it, or NULL if not found.
479 */
480 static ns_interface_t *
find_matching_interface(ns_interfacemgr_t * mgr,isc_sockaddr_t * addr)481 find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
482 ns_interface_t *ifp;
483 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
484 ifp = ISC_LIST_NEXT(ifp, link)) {
485 if (isc_sockaddr_equal(&ifp->addr, addr))
486 break;
487 }
488 return (ifp);
489 }
490
491 /*%
492 * Remove any interfaces whose generation number is not the current one.
493 */
494 static void
purge_old_interfaces(ns_interfacemgr_t * mgr)495 purge_old_interfaces(ns_interfacemgr_t *mgr) {
496 ns_interface_t *ifp, *next;
497 for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
498 INSIST(NS_INTERFACE_VALID(ifp));
499 next = ISC_LIST_NEXT(ifp, link);
500 if (ifp->generation != mgr->generation) {
501 char sabuf[256];
502 ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
503 isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
504 isc_log_write(IFMGR_COMMON_LOGARGS,
505 ISC_LOG_INFO,
506 "no longer listening on %s", sabuf);
507 ns_interface_shutdown(ifp);
508 ns_interface_detach(&ifp);
509 }
510 }
511 }
512
513 static isc_result_t
clearacl(isc_mem_t * mctx,dns_acl_t ** aclp)514 clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
515 dns_acl_t *newacl = NULL;
516 isc_result_t result;
517 result = dns_acl_create(mctx, 0, &newacl);
518 if (result != ISC_R_SUCCESS)
519 return (result);
520 dns_acl_detach(aclp);
521 dns_acl_attach(newacl, aclp);
522 dns_acl_detach(&newacl);
523 return (ISC_R_SUCCESS);
524 }
525
526 static isc_boolean_t
listenon_is_ip6_any(ns_listenelt_t * elt)527 listenon_is_ip6_any(ns_listenelt_t *elt) {
528 REQUIRE(elt && elt->acl);
529 return dns_acl_isany(elt->acl);
530 }
531
532 static isc_result_t
setup_locals(ns_interfacemgr_t * mgr,isc_interface_t * interface)533 setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
534 isc_result_t result;
535 unsigned int prefixlen;
536 isc_netaddr_t *netaddr;
537
538 netaddr = &interface->address;
539
540 /* First add localhost address */
541 prefixlen = (netaddr->family == AF_INET) ? 32 : 128;
542 result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable,
543 netaddr, prefixlen, ISC_TRUE);
544 if (result != ISC_R_SUCCESS)
545 return (result);
546
547 /* Then add localnets prefix */
548 result = isc_netaddr_masktoprefixlen(&interface->netmask,
549 &prefixlen);
550
551 /* Non contiguous netmasks not allowed by IPv6 arch. */
552 if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6)
553 return (result);
554
555 if (result != ISC_R_SUCCESS) {
556 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
557 "omitting IPv4 interface %s from "
558 "localnets ACL: %s", interface->name,
559 isc_result_totext(result));
560 return (ISC_R_SUCCESS);
561 }
562
563 if (prefixlen == 0U) {
564 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
565 "omitting %s interface %s from localnets ACL: "
566 "zero prefix length detected",
567 (netaddr->family == AF_INET) ? "IPv4" : "IPv6",
568 interface->name);
569 return (ISC_R_SUCCESS);
570 }
571
572 result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable,
573 netaddr, prefixlen, ISC_TRUE);
574 if (result != ISC_R_SUCCESS)
575 return (result);
576
577 return (ISC_R_SUCCESS);
578 }
579
580 static void
setup_listenon(ns_interfacemgr_t * mgr,isc_interface_t * interface,in_port_t port)581 setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface,
582 in_port_t port)
583 {
584 isc_sockaddr_t *addr;
585 isc_sockaddr_t *old;
586
587 addr = isc_mem_get(mgr->mctx, sizeof(*addr));
588 if (addr == NULL)
589 return;
590
591 isc_sockaddr_fromnetaddr(addr, &interface->address, port);
592
593 for (old = ISC_LIST_HEAD(mgr->listenon);
594 old != NULL;
595 old = ISC_LIST_NEXT(old, link))
596 if (isc_sockaddr_equal(addr, old))
597 break;
598
599 if (old != NULL)
600 isc_mem_put(mgr->mctx, addr, sizeof(*addr));
601 else
602 ISC_LIST_APPEND(mgr->listenon, addr, link);
603 }
604
605 static void
clearlistenon(ns_interfacemgr_t * mgr)606 clearlistenon(ns_interfacemgr_t *mgr) {
607 isc_sockaddr_t *old;
608
609 old = ISC_LIST_HEAD(mgr->listenon);
610 while (old != NULL) {
611 ISC_LIST_UNLINK(mgr->listenon, old, link);
612 isc_mem_put(mgr->mctx, old, sizeof(*old));
613 old = ISC_LIST_HEAD(mgr->listenon);
614 }
615 }
616
617 static isc_result_t
do_scan(ns_interfacemgr_t * mgr,ns_listenlist_t * ext_listen,isc_boolean_t verbose)618 do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
619 isc_boolean_t verbose)
620 {
621 isc_interfaceiter_t *iter = NULL;
622 isc_boolean_t scan_ipv4 = ISC_FALSE;
623 isc_boolean_t scan_ipv6 = ISC_FALSE;
624 isc_boolean_t adjusting = ISC_FALSE;
625 isc_boolean_t ipv6only = ISC_TRUE;
626 isc_boolean_t ipv6pktinfo = ISC_TRUE;
627 isc_result_t result;
628 isc_netaddr_t zero_address, zero_address6;
629 ns_listenelt_t *le;
630 isc_sockaddr_t listen_addr;
631 ns_interface_t *ifp;
632 isc_boolean_t log_explicit = ISC_FALSE;
633 isc_boolean_t dolistenon;
634
635 if (ext_listen != NULL)
636 adjusting = ISC_TRUE;
637
638 if (isc_net_probeipv6() == ISC_R_SUCCESS)
639 scan_ipv6 = ISC_TRUE;
640 #ifdef WANT_IPV6
641 else if (!ns_g_disable6)
642 isc_log_write(IFMGR_COMMON_LOGARGS,
643 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
644 "no IPv6 interfaces found");
645 #endif
646
647 if (isc_net_probeipv4() == ISC_R_SUCCESS)
648 scan_ipv4 = ISC_TRUE;
649 else if (!ns_g_disable4)
650 isc_log_write(IFMGR_COMMON_LOGARGS,
651 verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
652 "no IPv4 interfaces found");
653
654 /*
655 * A special, but typical case; listen-on-v6 { any; }.
656 * When we can make the socket IPv6-only, open a single wildcard
657 * socket for IPv6 communication. Otherwise, make separate socket
658 * for each IPv6 address in order to avoid accepting IPv4 packets
659 * as the form of mapped addresses unintentionally unless explicitly
660 * allowed.
661 */
662 #ifndef ISC_ALLOW_MAPPED
663 if (scan_ipv6 == ISC_TRUE &&
664 isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
665 ipv6only = ISC_FALSE;
666 log_explicit = ISC_TRUE;
667 }
668 #endif
669 if (scan_ipv6 == ISC_TRUE &&
670 isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
671 ipv6pktinfo = ISC_FALSE;
672 log_explicit = ISC_TRUE;
673 }
674 if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) {
675 for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
676 le != NULL;
677 le = ISC_LIST_NEXT(le, link)) {
678 struct in6_addr in6a;
679
680 if (!listenon_is_ip6_any(le))
681 continue;
682
683 in6a = in6addr_any;
684 isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
685
686 ifp = find_matching_interface(mgr, &listen_addr);
687 if (ifp != NULL) {
688 ifp->generation = mgr->generation;
689 } else {
690 isc_log_write(IFMGR_COMMON_LOGARGS,
691 ISC_LOG_INFO,
692 "listening on IPv6 "
693 "interfaces, port %u",
694 le->port);
695 result = ns_interface_setup(mgr, &listen_addr,
696 "<any>", &ifp,
697 ISC_TRUE);
698 if (result == ISC_R_SUCCESS)
699 ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
700 else
701 isc_log_write(IFMGR_COMMON_LOGARGS,
702 ISC_LOG_ERROR,
703 "listening on all IPv6 "
704 "interfaces failed");
705 /* Continue. */
706 }
707 }
708 }
709
710 isc_netaddr_any(&zero_address);
711 isc_netaddr_any6(&zero_address6);
712
713 result = isc_interfaceiter_create(mgr->mctx, &iter);
714 if (result != ISC_R_SUCCESS)
715 return (result);
716
717 if (adjusting == ISC_FALSE) {
718 result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
719 if (result != ISC_R_SUCCESS)
720 goto cleanup_iter;
721 result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
722 if (result != ISC_R_SUCCESS)
723 goto cleanup_iter;
724 clearlistenon(mgr);
725 }
726
727 for (result = isc_interfaceiter_first(iter);
728 result == ISC_R_SUCCESS;
729 result = isc_interfaceiter_next(iter))
730 {
731 isc_interface_t interface;
732 ns_listenlist_t *ll;
733 unsigned int family;
734
735 result = isc_interfaceiter_current(iter, &interface);
736 if (result != ISC_R_SUCCESS)
737 break;
738
739 family = interface.address.family;
740 if (family != AF_INET && family != AF_INET6)
741 continue;
742 if (scan_ipv4 == ISC_FALSE && family == AF_INET)
743 continue;
744 if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
745 continue;
746
747 /*
748 * Test for the address being nonzero rather than testing
749 * INTERFACE_F_UP, because on some systems the latter
750 * follows the media state and we could end up ignoring
751 * the interface for an entire rescan interval due to
752 * a temporary media glitch at rescan time.
753 */
754 if (family == AF_INET &&
755 isc_netaddr_equal(&interface.address, &zero_address)) {
756 continue;
757 }
758 if (family == AF_INET6 &&
759 isc_netaddr_equal(&interface.address, &zero_address6)) {
760 continue;
761 }
762
763 if (adjusting == ISC_FALSE) {
764 result = setup_locals(mgr, &interface);
765 if (result != ISC_R_SUCCESS)
766 goto ignore_interface;
767 }
768
769 ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
770 dolistenon = ISC_TRUE;
771 for (le = ISC_LIST_HEAD(ll->elts);
772 le != NULL;
773 le = ISC_LIST_NEXT(le, link))
774 {
775 int match;
776 isc_boolean_t ipv6_wildcard = ISC_FALSE;
777 isc_netaddr_t listen_netaddr;
778 isc_sockaddr_t listen_sockaddr;
779
780 /*
781 * Construct a socket address for this IP/port
782 * combination.
783 */
784 if (family == AF_INET) {
785 isc_netaddr_fromin(&listen_netaddr,
786 &interface.address.type.in);
787 } else {
788 isc_netaddr_fromin6(&listen_netaddr,
789 &interface.address.type.in6);
790 isc_netaddr_setzone(&listen_netaddr,
791 interface.address.zone);
792 }
793 isc_sockaddr_fromnetaddr(&listen_sockaddr,
794 &listen_netaddr,
795 le->port);
796
797 /*
798 * See if the address matches the listen-on statement;
799 * if not, ignore the interface.
800 */
801 (void)dns_acl_match(&listen_netaddr, NULL, le->acl,
802 &mgr->aclenv, &match, NULL);
803 if (match <= 0)
804 continue;
805
806 if (adjusting == ISC_FALSE && dolistenon == ISC_TRUE) {
807 setup_listenon(mgr, &interface, le->port);
808 dolistenon = ISC_FALSE;
809 }
810
811 /*
812 * The case of "any" IPv6 address will require
813 * special considerations later, so remember it.
814 */
815 if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
816 listenon_is_ip6_any(le))
817 ipv6_wildcard = ISC_TRUE;
818
819 /*
820 * When adjusting interfaces with extra a listening
821 * list, see if the address matches the extra list.
822 * If it does, and is also covered by a wildcard
823 * interface, we need to listen on the address
824 * explicitly.
825 */
826 if (adjusting == ISC_TRUE) {
827 ns_listenelt_t *ele;
828
829 match = 0;
830 for (ele = ISC_LIST_HEAD(ext_listen->elts);
831 ele != NULL;
832 ele = ISC_LIST_NEXT(ele, link)) {
833 (void)dns_acl_match(&listen_netaddr,
834 NULL, ele->acl,
835 NULL, &match, NULL);
836 if (match > 0 &&
837 (ele->port == le->port ||
838 ele->port == 0))
839 break;
840 else
841 match = 0;
842 }
843 if (ipv6_wildcard == ISC_TRUE && match == 0)
844 continue;
845 }
846
847 ifp = find_matching_interface(mgr, &listen_sockaddr);
848 if (ifp != NULL) {
849 ifp->generation = mgr->generation;
850 } else {
851 char sabuf[ISC_SOCKADDR_FORMATSIZE];
852
853 if (adjusting == ISC_FALSE &&
854 ipv6_wildcard == ISC_TRUE)
855 continue;
856
857 if (log_explicit && family == AF_INET6 &&
858 !adjusting && listenon_is_ip6_any(le)) {
859 isc_log_write(IFMGR_COMMON_LOGARGS,
860 verbose ? ISC_LOG_INFO :
861 ISC_LOG_DEBUG(1),
862 "IPv6 socket API is "
863 "incomplete; explicitly "
864 "binding to each IPv6 "
865 "address separately");
866 log_explicit = ISC_FALSE;
867 }
868 isc_sockaddr_format(&listen_sockaddr,
869 sabuf, sizeof(sabuf));
870 isc_log_write(IFMGR_COMMON_LOGARGS,
871 ISC_LOG_INFO,
872 "%s"
873 "listening on %s interface "
874 "%s, %s",
875 (adjusting == ISC_TRUE) ?
876 "additionally " : "",
877 (family == AF_INET) ?
878 "IPv4" : "IPv6",
879 interface.name, sabuf);
880
881 result = ns_interface_setup(mgr,
882 &listen_sockaddr,
883 interface.name,
884 &ifp,
885 (adjusting == ISC_TRUE) ?
886 ISC_FALSE :
887 ISC_TRUE);
888
889 if (result != ISC_R_SUCCESS) {
890 isc_log_write(IFMGR_COMMON_LOGARGS,
891 ISC_LOG_ERROR,
892 "creating %s interface "
893 "%s failed; interface "
894 "ignored",
895 (family == AF_INET) ?
896 "IPv4" : "IPv6",
897 interface.name);
898 }
899 /* Continue. */
900 }
901
902 }
903 continue;
904
905 ignore_interface:
906 isc_log_write(IFMGR_COMMON_LOGARGS,
907 ISC_LOG_ERROR,
908 "ignoring %s interface %s: %s",
909 (family == AF_INET) ? "IPv4" : "IPv6",
910 interface.name, isc_result_totext(result));
911 continue;
912 }
913 if (result != ISC_R_NOMORE)
914 UNEXPECTED_ERROR(__FILE__, __LINE__,
915 "interface iteration failed: %s",
916 isc_result_totext(result));
917 else
918 result = ISC_R_SUCCESS;
919 cleanup_iter:
920 isc_interfaceiter_destroy(&iter);
921 return (result);
922 }
923
924 static void
ns_interfacemgr_scan0(ns_interfacemgr_t * mgr,ns_listenlist_t * ext_listen,isc_boolean_t verbose)925 ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
926 isc_boolean_t verbose)
927 {
928 isc_boolean_t purge = ISC_TRUE;
929
930 REQUIRE(NS_INTERFACEMGR_VALID(mgr));
931
932 mgr->generation++; /* Increment the generation count. */
933
934 if (do_scan(mgr, ext_listen, verbose) != ISC_R_SUCCESS)
935 purge = ISC_FALSE;
936
937 /*
938 * Now go through the interface list and delete anything that
939 * does not have the current generation number. This is
940 * how we catch interfaces that go away or change their
941 * addresses.
942 */
943 if (purge)
944 purge_old_interfaces(mgr);
945
946 /*
947 * Warn if we are not listening on any interface, unless
948 * we're in lwresd-only mode, in which case that is to
949 * be expected.
950 */
951 if (ext_listen == NULL &&
952 ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) {
953 isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
954 "not listening on any interfaces");
955 }
956 }
957
958 void
ns_interfacemgr_scan(ns_interfacemgr_t * mgr,isc_boolean_t verbose)959 ns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose) {
960 ns_interfacemgr_scan0(mgr, NULL, verbose);
961 }
962
963 void
ns_interfacemgr_adjust(ns_interfacemgr_t * mgr,ns_listenlist_t * list,isc_boolean_t verbose)964 ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
965 isc_boolean_t verbose)
966 {
967 ns_interfacemgr_scan0(mgr, list, verbose);
968 }
969
970 void
ns_interfacemgr_setlistenon4(ns_interfacemgr_t * mgr,ns_listenlist_t * value)971 ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
972 LOCK(&mgr->lock);
973 ns_listenlist_detach(&mgr->listenon4);
974 ns_listenlist_attach(value, &mgr->listenon4);
975 UNLOCK(&mgr->lock);
976 }
977
978 void
ns_interfacemgr_setlistenon6(ns_interfacemgr_t * mgr,ns_listenlist_t * value)979 ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
980 LOCK(&mgr->lock);
981 ns_listenlist_detach(&mgr->listenon6);
982 ns_listenlist_attach(value, &mgr->listenon6);
983 UNLOCK(&mgr->lock);
984 }
985
986 void
ns_interfacemgr_dumprecursing(FILE * f,ns_interfacemgr_t * mgr)987 ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
988 ns_interface_t *interface;
989
990 LOCK(&mgr->lock);
991 interface = ISC_LIST_HEAD(mgr->interfaces);
992 while (interface != NULL) {
993 if (interface->clientmgr != NULL)
994 ns_client_dumprecursing(f, interface->clientmgr);
995 interface = ISC_LIST_NEXT(interface, link);
996 }
997 UNLOCK(&mgr->lock);
998 }
999
1000 isc_boolean_t
ns_interfacemgr_listeningon(ns_interfacemgr_t * mgr,isc_sockaddr_t * addr)1001 ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
1002 isc_sockaddr_t *old;
1003
1004 for (old = ISC_LIST_HEAD(mgr->listenon);
1005 old != NULL;
1006 old = ISC_LIST_NEXT(old, link))
1007 if (isc_sockaddr_equal(old, addr))
1008 return (ISC_TRUE);
1009 return (ISC_FALSE);
1010 }
1011