1 /* $NetBSD: lwresd.c,v 1.6 2014/12/10 04:37:51 christos Exp $ */
4 * Copyright (C) 2004-2009, 2012, 2013 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: lwresd.c,v 1.60 2009/09/02 23:48:01 tbox Exp */
24 * Main program for the Lightweight Resolver Daemon.
26 * To paraphrase the old saying about X11, "It's not a lightweight deamon
27 * for resolvers, it's a deamon for lightweight resolvers".
36 #include <isc/magic.h>
39 #include <isc/print.h>
40 #include <isc/socket.h>
44 #include <isccfg/namedconf.h>
47 #include <dns/result.h>
50 #include <named/config.h>
51 #include <named/globals.h>
52 #include <named/log.h>
53 #include <named/lwaddr.h>
54 #include <named/lwresd.h>
55 #include <named/lwdclient.h>
56 #include <named/lwsearch.h>
57 #include <named/server.h>
59 #define LWRESD_MAGIC ISC_MAGIC('L', 'W', 'R', 'D')
60 #define VALID_LWRESD(l) ISC_MAGIC_VALID(l, LWRESD_MAGIC)
62 #define LWRESLISTENER_MAGIC ISC_MAGIC('L', 'W', 'R', 'L')
63 #define VALID_LWRESLISTENER(l) ISC_MAGIC_VALID(l, LWRESLISTENER_MAGIC)
66 * The total number of clients we can handle will be NTASKS * NRECVS.
68 #define NTASKS 2 /*%< tasks to create to handle lwres queries */
69 #define NRECVS 2 /*%< max clients per task */
71 typedef ISC_LIST(ns_lwreslistener_t
) ns_lwreslistenerlist_t
;
73 static ns_lwreslistenerlist_t listeners
;
74 static isc_mutex_t listeners_lock
;
75 static isc_once_t once
= ISC_ONCE_INIT
;
79 initialize_mutex(void) {
80 RUNTIME_CHECK(isc_mutex_init(&listeners_lock
) == ISC_R_SUCCESS
);
85 * Wrappers around our memory management stuff, for the lwres functions.
88 ns__lwresd_memalloc(void *arg
, size_t size
) {
89 return (isc_mem_get(arg
, size
));
93 ns__lwresd_memfree(void *arg
, void *mem
, size_t size
) {
94 isc_mem_put(arg
, mem
, size
);
100 if (result != ISC_R_SUCCESS) goto cleanup; \
101 } while (/*CONSTCOND*/0)
104 buffer_putstr(isc_buffer_t
*b
, const char *s
) {
105 unsigned int len
= strlen(s
);
106 if (isc_buffer_availablelength(b
) <= len
)
107 return (ISC_R_NOSPACE
);
108 isc_buffer_putmem(b
, (const unsigned char *)s
, len
);
109 return (ISC_R_SUCCESS
);
113 * Convert a resolv.conf file into a config structure.
116 ns_lwresd_parseeresolvconf(isc_mem_t
*mctx
, cfg_parser_t
*pctx
,
122 lwres_context_t
*lwctx
= NULL
;
123 lwres_conf_t
*lwc
= NULL
;
128 lwres_result_t lwresult
;
131 lwresult
= lwres_context_create(&lwctx
, mctx
, ns__lwresd_memalloc
,
133 LWRES_CONTEXT_SERVERMODE
);
134 if (lwresult
!= LWRES_R_SUCCESS
) {
135 result
= ISC_R_NOMEMORY
;
139 lwresult
= lwres_conf_parse(lwctx
, lwresd_g_resolvconffile
);
140 if (lwresult
!= LWRES_R_SUCCESS
) {
141 result
= DNS_R_SYNTAX
;
145 lwc
= lwres_conf_get(lwctx
);
148 isc_buffer_init(&b
, text
, sizeof(text
));
150 CHECK(buffer_putstr(&b
, "options {\n"));
153 * Build the list of forwarders.
155 if (lwc
->nsnext
> 0) {
156 CHECK(buffer_putstr(&b
, "\tforwarders {\n"));
158 for (i
= 0; i
< lwc
->nsnext
; i
++) {
159 CHECK(lwaddr_sockaddr_fromlwresaddr(
161 &lwc
->nameservers
[i
],
163 isc_netaddr_fromsockaddr(&na
, &sa
);
164 CHECK(buffer_putstr(&b
, "\t\t"));
165 CHECK(isc_netaddr_totext(&na
, &b
));
166 CHECK(buffer_putstr(&b
, ";\n"));
168 CHECK(buffer_putstr(&b
, "\t};\n"));
174 if (lwc
->sortlistnxt
> 0) {
175 CHECK(buffer_putstr(&b
, "\tsortlist {\n"));
176 CHECK(buffer_putstr(&b
, "\t\t{\n"));
177 CHECK(buffer_putstr(&b
, "\t\t\tany;\n"));
178 CHECK(buffer_putstr(&b
, "\t\t\t{\n"));
179 for (i
= 0; i
< lwc
->sortlistnxt
; i
++) {
180 lwres_addr_t
*lwaddr
= &lwc
->sortlist
[i
].addr
;
181 lwres_addr_t
*lwmask
= &lwc
->sortlist
[i
].mask
;
184 CHECK(lwaddr_sockaddr_fromlwresaddr(&sa
, lwmask
, 0));
185 isc_netaddr_fromsockaddr(&na
, &sa
);
186 result
= isc_netaddr_masktoprefixlen(&na
, &mask
);
187 if (result
!= ISC_R_SUCCESS
) {
188 char addrtext
[ISC_NETADDR_FORMATSIZE
];
189 isc_netaddr_format(&na
, addrtext
,
191 isc_log_write(ns_g_lctx
,
192 NS_LOGCATEGORY_GENERAL
,
195 "processing sortlist: '%s' is "
196 "not a valid netmask",
201 CHECK(lwaddr_sockaddr_fromlwresaddr(&sa
, lwaddr
, 0));
202 isc_netaddr_fromsockaddr(&na
, &sa
);
204 CHECK(buffer_putstr(&b
, "\t\t\t\t"));
205 CHECK(isc_netaddr_totext(&na
, &b
));
206 snprintf(str
, sizeof(str
), "%u", mask
);
207 CHECK(buffer_putstr(&b
, "/"));
208 CHECK(buffer_putstr(&b
, str
));
209 CHECK(buffer_putstr(&b
, ";\n"));
211 CHECK(buffer_putstr(&b
, "\t\t\t};\n"));
212 CHECK(buffer_putstr(&b
, "\t\t};\n"));
213 CHECK(buffer_putstr(&b
, "\t};\n"));
216 CHECK(buffer_putstr(&b
, "};\n\n"));
218 CHECK(buffer_putstr(&b
, "lwres {\n"));
221 * Build the search path
223 if (lwc
->searchnxt
> 0) {
224 if (lwc
->searchnxt
> 0) {
225 CHECK(buffer_putstr(&b
, "\tsearch {\n"));
226 for (i
= 0; i
< lwc
->searchnxt
; i
++) {
227 CHECK(buffer_putstr(&b
, "\t\t\""));
228 CHECK(buffer_putstr(&b
, lwc
->search
[i
]));
229 CHECK(buffer_putstr(&b
, "\";\n"));
231 CHECK(buffer_putstr(&b
, "\t};\n"));
236 * Build the ndots line
238 if (lwc
->ndots
!= 1) {
239 CHECK(buffer_putstr(&b
, "\tndots "));
240 snprintf(str
, sizeof(str
), "%u", lwc
->ndots
);
241 CHECK(buffer_putstr(&b
, str
));
242 CHECK(buffer_putstr(&b
, ";\n"));
246 * Build the listen-on line
248 if (lwc
->lwnext
> 0) {
249 CHECK(buffer_putstr(&b
, "\tlisten-on {\n"));
251 for (i
= 0; i
< lwc
->lwnext
; i
++) {
252 CHECK(lwaddr_sockaddr_fromlwresaddr(&sa
,
255 isc_netaddr_fromsockaddr(&na
, &sa
);
256 CHECK(buffer_putstr(&b
, "\t\t"));
257 CHECK(isc_netaddr_totext(&na
, &b
));
258 CHECK(buffer_putstr(&b
, ";\n"));
260 CHECK(buffer_putstr(&b
, "\t};\n"));
263 CHECK(buffer_putstr(&b
, "};\n"));
267 (int)isc_buffer_usedlength(&b
),
268 (char *)isc_buffer_base(&b
));
271 lwres_conf_clear(lwctx
);
272 lwres_context_destroy(&lwctx
);
274 return (cfg_parse_buffer(pctx
, &b
, &cfg_type_namedconf
, configp
));
279 lwres_conf_clear(lwctx
);
280 lwres_context_destroy(&lwctx
);
288 * Handle lwresd manager objects
291 ns_lwdmanager_create(isc_mem_t
*mctx
, const cfg_obj_t
*lwres
,
292 ns_lwresd_t
**lwresdp
)
296 dns_rdataclass_t vclass
;
297 const cfg_obj_t
*obj
, *viewobj
, *searchobj
;
298 const cfg_listelt_t
*element
;
301 INSIST(lwresdp
!= NULL
&& *lwresdp
== NULL
);
303 lwresd
= isc_mem_get(mctx
, sizeof(ns_lwresd_t
));
305 return (ISC_R_NOMEMORY
);
308 isc_mem_attach(mctx
, &lwresd
->mctx
);
310 lwresd
->search
= NULL
;
314 (void)cfg_map_get(lwres
, "ndots", &obj
);
316 lwresd
->ndots
= cfg_obj_asuint32(obj
);
320 RUNTIME_CHECK(isc_mutex_init(&lwresd
->lock
) == ISC_R_SUCCESS
);
322 lwresd
->shutting_down
= ISC_FALSE
;
325 (void)cfg_map_get(lwres
, "view", &viewobj
);
326 if (viewobj
!= NULL
) {
327 vname
= cfg_obj_asstring(cfg_tuple_get(viewobj
, "name"));
328 obj
= cfg_tuple_get(viewobj
, "class");
329 result
= ns_config_getclass(obj
, dns_rdataclass_in
, &vclass
);
330 if (result
!= ISC_R_SUCCESS
)
334 vclass
= dns_rdataclass_in
;
337 result
= dns_viewlist_find(&ns_g_server
->viewlist
, vname
, vclass
,
339 if (result
!= ISC_R_SUCCESS
) {
340 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
341 NS_LOGMODULE_LWRESD
, ISC_LOG_WARNING
,
342 "couldn't find view %s", vname
);
347 (void)cfg_map_get(lwres
, "search", &searchobj
);
348 if (searchobj
!= NULL
) {
349 lwresd
->search
= NULL
;
350 result
= ns_lwsearchlist_create(lwresd
->mctx
,
352 if (result
!= ISC_R_SUCCESS
) {
353 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
354 NS_LOGMODULE_LWRESD
, ISC_LOG_WARNING
,
355 "couldn't create searchlist");
358 for (element
= cfg_list_first(searchobj
);
360 element
= cfg_list_next(element
))
362 const cfg_obj_t
*search
;
363 const char *searchstr
;
364 isc_buffer_t namebuf
;
365 dns_fixedname_t fname
;
368 search
= cfg_listelt_value(element
);
369 searchstr
= cfg_obj_asstring(search
);
371 dns_fixedname_init(&fname
);
372 name
= dns_fixedname_name(&fname
);
373 isc_buffer_constinit(&namebuf
, searchstr
,
375 isc_buffer_add(&namebuf
, strlen(searchstr
));
376 result
= dns_name_fromtext(name
, &namebuf
,
377 dns_rootname
, 0, NULL
);
378 if (result
!= ISC_R_SUCCESS
) {
379 isc_log_write(ns_g_lctx
,
380 NS_LOGCATEGORY_GENERAL
,
383 "invalid name %s in searchlist",
388 result
= ns_lwsearchlist_append(lwresd
->search
, name
);
389 if (result
!= ISC_R_SUCCESS
) {
390 isc_log_write(ns_g_lctx
,
391 NS_LOGCATEGORY_GENERAL
,
394 "couldn't update searchlist");
400 lwresd
->magic
= LWRESD_MAGIC
;
403 return (ISC_R_SUCCESS
);
406 if (lwresd
->view
!= NULL
)
407 dns_view_detach(&lwresd
->view
);
408 if (lwresd
->search
!= NULL
)
409 ns_lwsearchlist_detach(&lwresd
->search
);
410 if (lwresd
->mctx
!= NULL
)
411 isc_mem_detach(&lwresd
->mctx
);
412 isc_mem_put(mctx
, lwresd
, sizeof(ns_lwresd_t
));
417 ns_lwdmanager_attach(ns_lwresd_t
*source
, ns_lwresd_t
**targetp
) {
418 INSIST(VALID_LWRESD(source
));
419 INSIST(targetp
!= NULL
&& *targetp
== NULL
);
423 UNLOCK(&source
->lock
);
429 ns_lwdmanager_detach(ns_lwresd_t
**lwresdp
) {
432 isc_boolean_t done
= ISC_FALSE
;
434 INSIST(lwresdp
!= NULL
&& *lwresdp
!= NULL
);
435 INSIST(VALID_LWRESD(*lwresdp
));
441 INSIST(lwresd
->refs
> 0);
443 if (lwresd
->refs
== 0)
445 UNLOCK(&lwresd
->lock
);
450 dns_view_detach(&lwresd
->view
);
451 if (lwresd
->search
!= NULL
)
452 ns_lwsearchlist_detach(&lwresd
->search
);
455 isc_mem_put(mctx
, lwresd
, sizeof(*lwresd
));
456 isc_mem_detach(&mctx
);
461 * Handle listener objects
464 ns_lwreslistener_attach(ns_lwreslistener_t
*source
,
465 ns_lwreslistener_t
**targetp
)
467 INSIST(VALID_LWRESLISTENER(source
));
468 INSIST(targetp
!= NULL
&& *targetp
== NULL
);
472 UNLOCK(&source
->lock
);
478 ns_lwreslistener_detach(ns_lwreslistener_t
**listenerp
) {
479 ns_lwreslistener_t
*listener
;
481 isc_boolean_t done
= ISC_FALSE
;
483 INSIST(listenerp
!= NULL
&& *listenerp
!= NULL
);
484 INSIST(VALID_LWRESLISTENER(*listenerp
));
486 listener
= *listenerp
;
488 LOCK(&listener
->lock
);
489 INSIST(listener
->refs
> 0);
491 if (listener
->refs
== 0)
493 UNLOCK(&listener
->lock
);
498 if (listener
->manager
!= NULL
)
499 ns_lwdmanager_detach(&listener
->manager
);
501 if (listener
->sock
!= NULL
)
502 isc_socket_detach(&listener
->sock
);
505 mctx
= listener
->mctx
;
506 isc_mem_put(mctx
, listener
, sizeof(*listener
));
507 isc_mem_detach(&mctx
);
512 listener_create(isc_mem_t
*mctx
, ns_lwresd_t
*lwresd
,
513 ns_lwreslistener_t
**listenerp
)
515 ns_lwreslistener_t
*listener
;
518 REQUIRE(listenerp
!= NULL
&& *listenerp
== NULL
);
520 listener
= isc_mem_get(mctx
, sizeof(ns_lwreslistener_t
));
521 if (listener
== NULL
)
522 return (ISC_R_NOMEMORY
);
524 result
= isc_mutex_init(&listener
->lock
);
525 if (result
!= ISC_R_SUCCESS
) {
526 isc_mem_put(mctx
, listener
, sizeof(ns_lwreslistener_t
));
530 listener
->magic
= LWRESLISTENER_MAGIC
;
533 listener
->sock
= NULL
;
535 listener
->manager
= NULL
;
536 ns_lwdmanager_attach(lwresd
, &listener
->manager
);
538 listener
->mctx
= NULL
;
539 isc_mem_attach(mctx
, &listener
->mctx
);
541 ISC_LINK_INIT(listener
, link
);
542 ISC_LIST_INIT(listener
->cmgrs
);
544 *listenerp
= listener
;
545 return (ISC_R_SUCCESS
);
549 listener_bind(ns_lwreslistener_t
*listener
, isc_sockaddr_t
*address
) {
550 isc_socket_t
*sock
= NULL
;
551 isc_result_t result
= ISC_R_SUCCESS
;
554 pf
= isc_sockaddr_pf(address
);
555 if ((pf
== AF_INET
&& isc_net_probeipv4() != ISC_R_SUCCESS
) ||
556 (pf
== AF_INET6
&& isc_net_probeipv6() != ISC_R_SUCCESS
))
557 return (ISC_R_FAMILYNOSUPPORT
);
559 listener
->address
= *address
;
561 if (isc_sockaddr_getport(&listener
->address
) == 0) {
563 port
= lwresd_g_listenport
;
565 port
= LWRES_UDP_PORT
;
566 isc_sockaddr_setport(&listener
->address
, port
);
570 result
= isc_socket_create(ns_g_socketmgr
, pf
,
571 isc_sockettype_udp
, &sock
);
572 if (result
!= ISC_R_SUCCESS
) {
573 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
574 NS_LOGMODULE_LWRESD
, ISC_LOG_WARNING
,
575 "failed to create lwres socket: %s",
576 isc_result_totext(result
));
580 result
= isc_socket_bind(sock
, &listener
->address
,
581 ISC_SOCKET_REUSEADDRESS
);
582 if (result
!= ISC_R_SUCCESS
) {
583 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
584 isc_sockaddr_format(&listener
->address
, socktext
,
586 isc_socket_detach(&sock
);
587 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
588 NS_LOGMODULE_LWRESD
, ISC_LOG_WARNING
,
589 "failed to add lwres socket: %s: %s",
590 socktext
, isc_result_totext(result
));
593 listener
->sock
= sock
;
594 return (ISC_R_SUCCESS
);
598 listener_copysock(ns_lwreslistener_t
*oldlistener
,
599 ns_lwreslistener_t
*newlistener
)
601 newlistener
->address
= oldlistener
->address
;
602 isc_socket_attach(oldlistener
->sock
, &newlistener
->sock
);
606 listener_startclients(ns_lwreslistener_t
*listener
) {
607 ns_lwdclientmgr_t
*cm
;
612 * Create the client managers.
614 result
= ISC_R_SUCCESS
;
615 for (i
= 0; i
< NTASKS
&& result
== ISC_R_SUCCESS
; i
++)
616 result
= ns_lwdclientmgr_create(listener
, NRECVS
,
620 * Ensure that we have created at least one.
622 if (ISC_LIST_EMPTY(listener
->cmgrs
))
626 * Walk the list of clients and start each one up.
628 LOCK(&listener
->lock
);
629 cm
= ISC_LIST_HEAD(listener
->cmgrs
);
631 result
= ns_lwdclient_startrecv(cm
);
632 if (result
!= ISC_R_SUCCESS
)
633 isc_log_write(ns_g_lctx
, NS_LOGCATEGORY_GENERAL
,
634 NS_LOGMODULE_LWRESD
, ISC_LOG_ERROR
,
635 "could not start lwres "
636 "client handler: %s",
637 isc_result_totext(result
));
638 cm
= ISC_LIST_NEXT(cm
, link
);
640 UNLOCK(&listener
->lock
);
642 return (ISC_R_SUCCESS
);
646 listener_shutdown(ns_lwreslistener_t
*listener
) {
647 ns_lwdclientmgr_t
*cm
;
649 cm
= ISC_LIST_HEAD(listener
->cmgrs
);
651 isc_task_shutdown(cm
->task
);
652 cm
= ISC_LIST_NEXT(cm
, link
);
657 find_listener(isc_sockaddr_t
*address
, ns_lwreslistener_t
**listenerp
) {
658 ns_lwreslistener_t
*listener
;
660 INSIST(listenerp
!= NULL
&& *listenerp
== NULL
);
662 for (listener
= ISC_LIST_HEAD(listeners
);
664 listener
= ISC_LIST_NEXT(listener
, link
))
666 if (!isc_sockaddr_equal(address
, &listener
->address
))
668 *listenerp
= listener
;
669 return (ISC_R_SUCCESS
);
671 return (ISC_R_NOTFOUND
);
675 ns_lwreslistener_unlinkcm(ns_lwreslistener_t
*listener
, ns_lwdclientmgr_t
*cm
)
677 REQUIRE(VALID_LWRESLISTENER(listener
));
679 LOCK(&listener
->lock
);
680 ISC_LIST_UNLINK(listener
->cmgrs
, cm
, link
);
681 UNLOCK(&listener
->lock
);
685 ns_lwreslistener_linkcm(ns_lwreslistener_t
*listener
, ns_lwdclientmgr_t
*cm
) {
686 REQUIRE(VALID_LWRESLISTENER(listener
));
689 * This does no locking, since it's called early enough that locking
692 ISC_LIST_APPEND(listener
->cmgrs
, cm
, link
);
696 configure_listener(isc_sockaddr_t
*address
, ns_lwresd_t
*lwresd
,
697 isc_mem_t
*mctx
, ns_lwreslistenerlist_t
*newlisteners
)
699 ns_lwreslistener_t
*listener
, *oldlistener
= NULL
;
700 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
703 (void)find_listener(address
, &oldlistener
);
705 result
= listener_create(mctx
, lwresd
, &listener
);
706 if (result
!= ISC_R_SUCCESS
) {
707 isc_sockaddr_format(address
, socktext
, sizeof(socktext
));
708 isc_log_write(ns_g_lctx
, ISC_LOGCATEGORY_GENERAL
,
709 NS_LOGMODULE_LWRESD
, ISC_LOG_WARNING
,
710 "lwres failed to configure %s: %s",
711 socktext
, isc_result_totext(result
));
716 * If there's already a listener, don't rebind the socket.
718 if (oldlistener
== NULL
) {
719 result
= listener_bind(listener
, address
);
720 if (result
!= ISC_R_SUCCESS
) {
721 ns_lwreslistener_detach(&listener
);
722 return (ISC_R_SUCCESS
);
725 listener_copysock(oldlistener
, listener
);
727 result
= listener_startclients(listener
);
728 if (result
!= ISC_R_SUCCESS
) {
729 isc_sockaddr_format(address
, socktext
, sizeof(socktext
));
730 isc_log_write(ns_g_lctx
, ISC_LOGCATEGORY_GENERAL
,
731 NS_LOGMODULE_LWRESD
, ISC_LOG_WARNING
,
732 "lwres: failed to start %s: %s", socktext
,
733 isc_result_totext(result
));
734 ns_lwreslistener_detach(&listener
);
735 return (ISC_R_SUCCESS
);
738 if (oldlistener
!= NULL
) {
740 * Remove the old listener from the old list and shut it down.
742 ISC_LIST_UNLINK(listeners
, oldlistener
, link
);
743 listener_shutdown(oldlistener
);
744 ns_lwreslistener_detach(&oldlistener
);
746 isc_sockaddr_format(address
, socktext
, sizeof(socktext
));
747 isc_log_write(ns_g_lctx
, ISC_LOGCATEGORY_GENERAL
,
748 NS_LOGMODULE_LWRESD
, ISC_LOG_NOTICE
,
749 "lwres listening on %s", socktext
);
752 ISC_LIST_APPEND(*newlisteners
, listener
, link
);
757 ns_lwresd_configure(isc_mem_t
*mctx
, const cfg_obj_t
*config
) {
758 const cfg_obj_t
*lwreslist
= NULL
;
759 const cfg_obj_t
*lwres
= NULL
;
760 const cfg_obj_t
*listenerslist
= NULL
;
761 const cfg_listelt_t
*element
= NULL
;
762 ns_lwreslistener_t
*listener
;
763 ns_lwreslistenerlist_t newlisteners
;
765 char socktext
[ISC_SOCKADDR_FORMATSIZE
];
766 isc_sockaddr_t
*addrs
= NULL
;
767 ns_lwresd_t
*lwresd
= NULL
;
768 isc_uint32_t count
= 0;
770 REQUIRE(mctx
!= NULL
);
771 REQUIRE(config
!= NULL
);
773 RUNTIME_CHECK(isc_once_do(&once
, initialize_mutex
) == ISC_R_SUCCESS
);
775 ISC_LIST_INIT(newlisteners
);
777 result
= cfg_map_get(config
, "lwres", &lwreslist
);
778 if (result
!= ISC_R_SUCCESS
)
779 return (ISC_R_SUCCESS
);
781 LOCK(&listeners_lock
);
783 * Run through the new lwres address list, noting sockets that
784 * are already being listened on and moving them to the new list.
786 * Identifying duplicates addr/port combinations is left to either
787 * the underlying config code, or to the bind attempt getting an
788 * address-in-use error.
790 for (element
= cfg_list_first(lwreslist
);
792 element
= cfg_list_next(element
))
796 lwres
= cfg_listelt_value(element
);
797 CHECK(ns_lwdmanager_create(mctx
, lwres
, &lwresd
));
799 port
= lwresd_g_listenport
;
801 port
= LWRES_UDP_PORT
;
803 listenerslist
= NULL
;
804 (void)cfg_map_get(lwres
, "listen-on", &listenerslist
);
805 if (listenerslist
== NULL
) {
806 struct in_addr localhost
;
807 isc_sockaddr_t address
;
809 localhost
.s_addr
= htonl(INADDR_LOOPBACK
);
810 isc_sockaddr_fromin(&address
, &localhost
, port
);
811 CHECK(configure_listener(&address
, lwresd
, mctx
,
816 CHECK(ns_config_getiplist(config
, listenerslist
,
817 port
, mctx
, &addrs
, NULL
,
819 for (i
= 0; i
< count
; i
++)
820 CHECK(configure_listener(&addrs
[i
], lwresd
,
821 mctx
, &newlisteners
));
822 ns_config_putiplist(mctx
, &addrs
, NULL
, count
);
824 ns_lwdmanager_detach(&lwresd
);
828 * Shutdown everything on the listeners list, and remove them from
829 * the list. Then put all of the new listeners on it.
832 while (!ISC_LIST_EMPTY(listeners
)) {
833 listener
= ISC_LIST_HEAD(listeners
);
834 ISC_LIST_UNLINK(listeners
, listener
, link
);
836 isc_sockaddr_format(&listener
->address
,
837 socktext
, sizeof(socktext
));
839 listener_shutdown(listener
);
840 ns_lwreslistener_detach(&listener
);
842 isc_log_write(ns_g_lctx
, ISC_LOGCATEGORY_GENERAL
,
843 NS_LOGMODULE_LWRESD
, ISC_LOG_NOTICE
,
844 "lwres no longer listening on %s", socktext
);
848 ISC_LIST_APPENDLIST(listeners
, newlisteners
, link
);
851 ns_config_putiplist(mctx
, &addrs
, NULL
, count
);
854 ns_lwdmanager_detach(&lwresd
);
856 UNLOCK(&listeners_lock
);
862 ns_lwresd_shutdown(void) {
863 ns_lwreslistener_t
*listener
;
865 RUNTIME_CHECK(isc_once_do(&once
, initialize_mutex
) == ISC_R_SUCCESS
);
867 while (!ISC_LIST_EMPTY(listeners
)) {
868 listener
= ISC_LIST_HEAD(listeners
);
869 ISC_LIST_UNLINK(listeners
, listener
, link
);
870 ns_lwreslistener_detach(&listener
);