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