lwresd.c revision c7c5645e062287294326fdb92e7e9b831950c4f3
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson/*
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Copyright (C) 2000-2002 Internet Software Consortium.
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews *
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Permission to use, copy, modify, and distribute this software for any
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * purpose with or without fee is hereby granted, provided that the above
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * copyright notice and this permission notice appear in all copies.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson *
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/* $Id: lwresd.c,v 1.44 2003/04/17 06:39:33 marka Exp $ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence * Main program for the Lightweight Resolver Daemon.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson *
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * To paraphrase the old saying about X11, "It's not a lightweight deamon
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * for resolvers, it's a deamon for lightweight resolvers".
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence */
364a82f7c25b62967678027043425201a5e5171aBob Halley
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#include <config.h>
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson#include <stdlib.h>
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#include <string.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#include <isc/list.h>
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#include <isc/magic.h>
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson#include <isc/mem.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/once.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/print.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/socket.h>
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson#include <isc/task.h>
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson#include <isc/util.h>
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#include <isccfg/namedconf.h>
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#include <dns/log.h>
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#include <dns/result.h>
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#include <dns/view.h>
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#include <named/config.h>
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#include <named/globals.h>
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#include <named/log.h>
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence#include <named/lwaddr.h>
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#include <named/lwresd.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <named/lwdclient.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <named/lwsearch.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <named/server.h>
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#define LWRESD_MAGIC ISC_MAGIC('L', 'W', 'R', 'D')
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#define VALID_LWRESD(l) ISC_MAGIC_VALID(l, LWRESD_MAGIC)
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#define LWRESLISTENER_MAGIC ISC_MAGIC('L', 'W', 'R', 'L')
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#define VALID_LWRESLISTENER(l) ISC_MAGIC_VALID(l, LWRESLISTENER_MAGIC)
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson/*
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson * The total number of clients we can handle will be NTASKS * NRECVS.
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson */
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#define NTASKS 2 /* tasks to create to handle lwres queries */
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson#define NRECVS 2 /* max clients per task */
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafssontypedef ISC_LIST(ns_lwreslistener_t) ns_lwreslistenerlist_t;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafssonstatic ns_lwreslistenerlist_t listeners;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafssonstatic isc_mutex_t listeners_lock;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafssonstatic isc_once_t once = ISC_ONCE_INIT;
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafssonstatic void
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafssoninitialize_mutex(void) {
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson RUNTIME_CHECK(isc_mutex_init(&listeners_lock) == ISC_R_SUCCESS);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson}
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson/*
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson * Wrappers around our memory management stuff, for the lwres functions.
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson */
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafssonvoid *
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafssonns__lwresd_memalloc(void *arg, size_t size) {
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson return (isc_mem_get(arg, size));
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson}
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafssonvoid
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafssonns__lwresd_memfree(void *arg, void *mem, size_t size) {
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson isc_mem_put(arg, mem, size);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson}
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson#define CHECK(op) \
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson do { result = (op); \
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson if (result != ISC_R_SUCCESS) goto cleanup; \
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson } while (0)
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafssonstatic isc_result_t
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafssonbuffer_putstr(isc_buffer_t *b, const char *s) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence unsigned int len = strlen(s);
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson if (isc_buffer_availablelength(b) <= len)
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence return (ISC_R_NOSPACE);
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson isc_buffer_putmem(b, (const unsigned char *)s, len);
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson return (ISC_R_SUCCESS);
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson}
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson/*
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson * Convert a resolv.conf file into a config structure.
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson */
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafssonisc_result_t
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafssonns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx,
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson cfg_obj_t **configp)
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson{
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson char text[4096];
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson char str[16];
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson isc_buffer_t b;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson lwres_context_t *lwctx = NULL;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson lwres_conf_t *lwc = NULL;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson isc_sockaddr_t sa;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson isc_netaddr_t na;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson int i;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson isc_result_t result;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson lwres_result_t lwresult;
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson lwctx = NULL;
fd0bc40a2580299d20ae212d89bda13862d78b3aAndreas Gustafsson lwresult = lwres_context_create(&lwctx, mctx, ns__lwresd_memalloc,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson ns__lwresd_memfree,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson LWRES_CONTEXT_SERVERMODE);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson if (lwresult != LWRES_R_SUCCESS) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson result = ISC_R_NOMEMORY;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson goto cleanup;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson }
8bb77cd31b7518fb5d2a6a9d75e16e4abd59df61Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson lwresult = lwres_conf_parse(lwctx, lwresd_g_resolvconffile);
d8d0c5b1bc97ac0f07e35a31b58ced80ce613c55David Lawrence if (lwresult != LWRES_R_SUCCESS) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson result = DNS_R_SYNTAX;
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson goto cleanup;
8bb77cd31b7518fb5d2a6a9d75e16e4abd59df61Andreas Gustafsson }
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence lwc = lwres_conf_get(lwctx);
ba7ea2326d98edb4296098749fc9cf44b5157643David Lawrence INSIST(lwc != NULL);
ba7ea2326d98edb4296098749fc9cf44b5157643David Lawrence
8bb77cd31b7518fb5d2a6a9d75e16e4abd59df61Andreas Gustafsson isc_buffer_init(&b, text, sizeof(text));
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson CHECK(buffer_putstr(&b, "options {\n"));
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson /*
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * Build the list of forwarders.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson if (lwc->nsnext > 0) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson CHECK(buffer_putstr(&b, "\tforwarders {\n"));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews for (i = 0; i < lwc->nsnext; i++) {
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews CHECK(lwaddr_sockaddr_fromlwresaddr(
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews &sa,
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews &lwc->nameservers[i],
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews ns_g_port));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews isc_netaddr_fromsockaddr(&na, &sa);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews CHECK(buffer_putstr(&b, "\t\t"));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews CHECK(isc_netaddr_totext(&na, &b));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews CHECK(buffer_putstr(&b, ";\n"));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews }
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews CHECK(buffer_putstr(&b, "\t};\n"));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews }
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews /*
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews * Build the sortlist
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews */
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews if (lwc->sortlistnxt > 0) {
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews CHECK(buffer_putstr(&b, "\tsortlist {\n"));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews CHECK(buffer_putstr(&b, "\t\t{\n"));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews CHECK(buffer_putstr(&b, "\t\t\tany;\n"));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews CHECK(buffer_putstr(&b, "\t\t\t{\n"));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews for (i = 0; i < lwc->sortlistnxt; i++) {
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson lwres_addr_t *lwaddr = &lwc->sortlist[i].addr;
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson lwres_addr_t *lwmask = &lwc->sortlist[i].mask;
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson unsigned int mask;
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwmask, 0));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson isc_netaddr_fromsockaddr(&na, &sa);
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson result = isc_netaddr_masktoprefixlen(&na, &mask);
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson if (result != ISC_R_SUCCESS) {
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington char addrtext[ISC_NETADDR_FORMATSIZE];
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington isc_netaddr_format(&na, addrtext,
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson sizeof(addrtext));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson isc_log_write(ns_g_lctx,
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson NS_LOGCATEGORY_GENERAL,
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson NS_LOGMODULE_LWRESD,
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson ISC_LOG_ERROR,
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington "processing sortlist: '%s' is "
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington "not a valid netmask",
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington addrtext);
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington goto cleanup;
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington }
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwaddr, 0));
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington isc_netaddr_fromsockaddr(&na, &sa);
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington CHECK(buffer_putstr(&b, "\t\t\t\t"));
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington CHECK(isc_netaddr_totext(&na, &b));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson snprintf(str, sizeof(str), "%u", mask);
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "/"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, str));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, ";\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson }
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "\t\t\t};\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "\t\t};\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "\t};\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson }
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "};\n\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "lwres {\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson /*
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson * Build the search path
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson */
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson if (lwc->searchnxt > 0) {
ba7ea2326d98edb4296098749fc9cf44b5157643David Lawrence if (lwc->searchnxt > 0) {
ba7ea2326d98edb4296098749fc9cf44b5157643David Lawrence CHECK(buffer_putstr(&b, "\tsearch {\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson for (i = 0; i < lwc->searchnxt; i++) {
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "\t\t\""));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, lwc->search[i]));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "\";\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson }
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "\t};\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson }
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson }
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson /*
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson * Build the ndots line
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson */
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson if (lwc->ndots != 1) {
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "\tndots "));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson snprintf(str, sizeof(str), "%u", lwc->ndots);
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, str));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, ";\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson }
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson /*
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson * Build the listen-on line
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson */
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson if (lwc->lwnext > 0) {
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "\tlisten-on {\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson for (i = 0; i < lwc->lwnext; i++) {
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(lwaddr_sockaddr_fromlwresaddr(&sa,
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson &lwc->lwservers[i],
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson 0));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson isc_netaddr_fromsockaddr(&na, &sa);
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "\t\t"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(isc_netaddr_totext(&na, &b));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, ";\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson }
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "\t};\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson }
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson CHECK(buffer_putstr(&b, "};\n"));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson#if 0
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson printf("%.*s\n",
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson (int)isc_buffer_usedlength(&b),
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson (char *)isc_buffer_base(&b));
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson#endif
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson lwres_conf_clear(lwctx);
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson lwres_context_destroy(&lwctx);
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson return (cfg_parse_buffer(pctx, &b, &cfg_type_namedconf, configp));
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence cleanup:
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson if (lwctx != NULL) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson lwres_conf_clear(lwctx);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson lwres_context_destroy(&lwctx);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson }
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence return (result);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson}
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson/*
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson * Handle lwresd manager objects
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson */
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssonisc_result_t
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafssonns_lwdmanager_create(isc_mem_t *mctx, cfg_obj_t *lwres,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson ns_lwresd_t **lwresdp)
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson{
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson ns_lwresd_t *lwresd;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson const char *vname;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson dns_rdataclass_t vclass;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson cfg_obj_t *obj, *viewobj, *searchobj;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson cfg_listelt_t *element;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson isc_result_t result;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
ea419adc4eca4c3e44f2c282035b5dce6b795fe2Andreas Gustafsson INSIST(lwresdp != NULL && *lwresdp == NULL);
ea419adc4eca4c3e44f2c282035b5dce6b795fe2Andreas Gustafsson
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson lwresd = isc_mem_get(mctx, sizeof(ns_lwresd_t));
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson if (lwresd == NULL)
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson return (ISC_R_NOMEMORY);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson lwresd->mctx = NULL;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson isc_mem_attach(mctx, &lwresd->mctx);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence lwresd->view = NULL;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson lwresd->search = NULL;
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson lwresd->refs = 1;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson obj = NULL;
aa23a35d81a9618a40c4a9b44be48009553e4777Andreas Gustafsson (void)cfg_map_get(lwres, "ndots", &obj);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson if (obj != NULL)
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson lwresd->ndots = cfg_obj_asuint32(obj);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson else
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson lwresd->ndots = 1;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence RUNTIME_CHECK(isc_mutex_init(&lwresd->lock) == ISC_R_SUCCESS);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson lwresd->shutting_down = ISC_FALSE;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson viewobj = NULL;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson (void)cfg_map_get(lwres, "view", &viewobj);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson if (viewobj != NULL) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson vname = cfg_obj_asstring(cfg_tuple_get(viewobj, "name"));
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews obj = cfg_tuple_get(viewobj, "class");
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews result = ns_config_getclass(obj, dns_rdataclass_in, &vclass);
aa39170da817cae7b4c6c735cc832e05ec3d2351Mark Andrews if (result != ISC_R_SUCCESS)
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson goto fail;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson } else {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson vname = "_default";
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson vclass = dns_rdataclass_in;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson }
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
7693d4de8fca501dfe6989a7f30d8d3c86fe096aAndreas Gustafsson result = dns_viewlist_find(&ns_g_server->viewlist, vname, vclass,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson &lwresd->view);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson if (result != ISC_R_SUCCESS) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson "couldn't find view %s", vname);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson goto fail;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson }
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson searchobj = NULL;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson (void)cfg_map_get(lwres, "search", &searchobj);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson if (searchobj != NULL) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson lwresd->search = NULL;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson result = ns_lwsearchlist_create(lwresd->mctx,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson &lwresd->search);
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson if (result != ISC_R_SUCCESS) {
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson "couldn't create searchlist");
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson goto fail;
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson }
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson for (element = cfg_list_first(searchobj);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson element != NULL;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson element = cfg_list_next(element))
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson {
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson cfg_obj_t *search;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson char *searchstr;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson isc_buffer_t namebuf;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson dns_fixedname_t fname;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson dns_name_t *name;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson search = cfg_listelt_value(element);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson searchstr = cfg_obj_asstring(search);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson dns_fixedname_init(&fname);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson name = dns_fixedname_name(&fname);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson isc_buffer_init(&namebuf, searchstr,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson strlen(searchstr));
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson isc_buffer_add(&namebuf, strlen(searchstr));
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson result = dns_name_fromtext(name, &namebuf,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson dns_rootname, ISC_FALSE,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson NULL);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson if (result != ISC_R_SUCCESS) {
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson isc_log_write(ns_g_lctx,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson NS_LOGCATEGORY_GENERAL,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson NS_LOGMODULE_LWRESD,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson ISC_LOG_WARNING,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson "invalid name %s in searchlist",
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson searchstr);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson continue;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson }
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson result = ns_lwsearchlist_append(lwresd->search, name);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson if (result != ISC_R_SUCCESS) {
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson isc_log_write(ns_g_lctx,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson NS_LOGCATEGORY_GENERAL,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson NS_LOGMODULE_LWRESD,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson ISC_LOG_WARNING,
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson "couldn't update searchlist");
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson goto fail;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson }
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson }
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson }
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson lwresd->magic = LWRESD_MAGIC;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson *lwresdp = lwresd;
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson return (ISC_R_SUCCESS);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson fail:
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson if (lwresd->view != NULL)
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson dns_view_detach(&lwresd->view);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson if (lwresd->search != NULL)
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson ns_lwsearchlist_detach(&lwresd->search);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson if (lwresd->mctx != NULL)
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson isc_mem_detach(&lwresd->mctx);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson return (result);
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson}
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafsson
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafssonvoid
9c566a852f31c3a5d0b9d6eaf11463114339c01dAndreas Gustafssonns_lwdmanager_attach(ns_lwresd_t *source, ns_lwresd_t **targetp) {
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson INSIST(VALID_LWRESD(source));
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence INSIST(targetp != NULL && *targetp == NULL);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson LOCK(&source->lock);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson source->refs++;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson UNLOCK(&source->lock);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson *targetp = source;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson}
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafssonvoid
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellingtonns_lwdmanager_detach(ns_lwresd_t **lwresdp) {
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson ns_lwresd_t *lwresd;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson isc_mem_t *mctx;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson isc_boolean_t done = ISC_FALSE;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson INSIST(lwresdp != NULL && *lwresdp != NULL);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson INSIST(VALID_LWRESD(*lwresdp));
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson lwresd = *lwresdp;
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence LOCK(&lwresd->lock);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson INSIST(lwresd->refs > 0);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson lwresd->refs--;
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson if (lwresd->refs == 0)
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson done = ISC_TRUE;
6eccf5bd07eb9abf65cc08fec4a8fc97b62c0e1bBrian Wellington UNLOCK(&lwresd->lock);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson if (!done)
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence return;
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson dns_view_detach(&lwresd->view);
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson if (lwresd->search != NULL)
a1747570262ed336c213aaf6bd31bc91993a46deAndreas Gustafsson ns_lwsearchlist_detach(&lwresd->search);
mctx = lwresd->mctx;
lwresd->magic = 0;
isc_mem_put(mctx, lwresd, sizeof(*lwresd));
isc_mem_detach(&mctx);
*lwresdp = NULL;
}
/*
* Handle listener objects
*/
void
ns_lwreslistener_attach(ns_lwreslistener_t *source,
ns_lwreslistener_t **targetp)
{
INSIST(VALID_LWRESLISTENER(source));
INSIST(targetp != NULL && *targetp == NULL);
LOCK(&source->lock);
source->refs++;
UNLOCK(&source->lock);
*targetp = source;
}
void
ns_lwreslistener_detach(ns_lwreslistener_t **listenerp) {
ns_lwreslistener_t *listener;
isc_mem_t *mctx;
isc_boolean_t done = ISC_FALSE;
INSIST(listenerp != NULL && *listenerp != NULL);
INSIST(VALID_LWRESLISTENER(*listenerp));
listener = *listenerp;
LOCK(&listener->lock);
INSIST(listener->refs > 0);
listener->refs--;
if (listener->refs == 0)
done = ISC_TRUE;
UNLOCK(&listener->lock);
if (!done)
return;
if (listener->manager != NULL)
ns_lwdmanager_detach(&listener->manager);
if (listener->sock != NULL)
isc_socket_detach(&listener->sock);
listener->magic = 0;
mctx = listener->mctx;
isc_mem_put(mctx, listener, sizeof(*listener));
isc_mem_detach(&mctx);
listenerp = NULL;
}
static isc_result_t
listener_create(isc_mem_t *mctx, ns_lwresd_t *lwresd,
ns_lwreslistener_t **listenerp)
{
ns_lwreslistener_t *listener;
REQUIRE(listenerp != NULL && *listenerp == NULL);
listener = isc_mem_get(mctx, sizeof(ns_lwreslistener_t));
if (listener == NULL)
return (ISC_R_NOMEMORY);
RUNTIME_CHECK(isc_mutex_init(&listener->lock) == ISC_R_SUCCESS);
listener->magic = LWRESLISTENER_MAGIC;
listener->refs = 1;
listener->sock = NULL;
listener->manager = NULL;
ns_lwdmanager_attach(lwresd, &listener->manager);
listener->mctx = NULL;
isc_mem_attach(mctx, &listener->mctx);
ISC_LINK_INIT(listener, link);
ISC_LIST_INIT(listener->cmgrs);
*listenerp = listener;
return (ISC_R_SUCCESS);
}
static isc_result_t
listener_bind(ns_lwreslistener_t *listener, isc_sockaddr_t *address) {
isc_socket_t *sock = NULL;
isc_result_t result = ISC_R_SUCCESS;
int pf;
pf = isc_sockaddr_pf(address);
if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
(pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
return (ISC_R_FAMILYNOSUPPORT);
listener->address = *address;
if (isc_sockaddr_getport(&listener->address) == 0) {
in_port_t port;
port = lwresd_g_listenport;
if (port == 0)
port = LWRES_UDP_PORT;
isc_sockaddr_setport(&listener->address, port);
}
sock = NULL;
result = isc_socket_create(ns_g_socketmgr, pf,
isc_sockettype_udp, &sock);
if (result != ISC_R_SUCCESS) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
"failed to create lwres socket: %s",
isc_result_totext(result));
return (result);
}
result = isc_socket_bind(sock, &listener->address);
if (result != ISC_R_SUCCESS) {
char socktext[ISC_SOCKADDR_FORMATSIZE];
isc_sockaddr_format(&listener->address, socktext,
sizeof(socktext));
isc_socket_detach(&sock);
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
"failed to add lwres socket: %s: %s",
socktext, isc_result_totext(result));
return (result);
}
listener->sock = sock;
return (ISC_R_SUCCESS);
}
static void
listener_copysock(ns_lwreslistener_t *oldlistener,
ns_lwreslistener_t *newlistener)
{
newlistener->address = oldlistener->address;
isc_socket_attach(oldlistener->sock, &newlistener->sock);
}
static isc_result_t
listener_startclients(ns_lwreslistener_t *listener) {
ns_lwdclientmgr_t *cm;
unsigned int i;
isc_result_t result;
/*
* Create the client managers.
*/
result = ISC_R_SUCCESS;
for (i = 0; i < NTASKS && result == ISC_R_SUCCESS; i++)
result = ns_lwdclientmgr_create(listener, NRECVS,
ns_g_taskmgr);
/*
* Ensure that we have created at least one.
*/
if (ISC_LIST_EMPTY(listener->cmgrs))
return (result);
/*
* Walk the list of clients and start each one up.
*/
LOCK(&listener->lock);
cm = ISC_LIST_HEAD(listener->cmgrs);
while (cm != NULL) {
result = ns_lwdclient_startrecv(cm);
if (result != ISC_R_SUCCESS)
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_LWRESD, ISC_LOG_ERROR,
"could not start lwres "
"client handler: %s",
isc_result_totext(result));
cm = ISC_LIST_NEXT(cm, link);
}
UNLOCK(&listener->lock);
return (ISC_R_SUCCESS);
}
static void
listener_shutdown(ns_lwreslistener_t *listener) {
ns_lwdclientmgr_t *cm;
cm = ISC_LIST_HEAD(listener->cmgrs);
while (cm != NULL) {
isc_task_shutdown(cm->task);
cm = ISC_LIST_NEXT(cm, link);
}
}
static isc_result_t
find_listener(isc_sockaddr_t *address, ns_lwreslistener_t **listenerp) {
ns_lwreslistener_t *listener;
INSIST(listenerp != NULL && *listenerp == NULL);
for (listener = ISC_LIST_HEAD(listeners);
listener != NULL;
listener = ISC_LIST_NEXT(listener, link))
{
if (!isc_sockaddr_equal(address, &listener->address))
continue;
*listenerp = listener;
return (ISC_R_SUCCESS);
}
return (ISC_R_NOTFOUND);
}
void
ns_lwreslistener_unlinkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm)
{
REQUIRE(VALID_LWRESLISTENER(listener));
LOCK(&listener->lock);
ISC_LIST_UNLINK(listener->cmgrs, cm, link);
UNLOCK(&listener->lock);
}
void
ns_lwreslistener_linkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm) {
REQUIRE(VALID_LWRESLISTENER(listener));
/*
* This does no locking, since it's called early enough that locking
* isn't needed.
*/
ISC_LIST_APPEND(listener->cmgrs, cm, link);
}
static isc_result_t
configure_listener(isc_sockaddr_t *address, ns_lwresd_t *lwresd,
isc_mem_t *mctx, ns_lwreslistenerlist_t *newlisteners)
{
ns_lwreslistener_t *listener, *oldlistener = NULL;
char socktext[ISC_SOCKADDR_FORMATSIZE];
isc_result_t result;
(void)find_listener(address, &oldlistener);
listener = NULL;
result = listener_create(mctx, lwresd, &listener);
if (result != ISC_R_SUCCESS) {
isc_sockaddr_format(address, socktext, sizeof(socktext));
isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
"lwres failed to configure %s: %s",
socktext, isc_result_totext(result));
return (result);
}
/*
* If there's already a listener, don't rebind the socket.
*/
if (oldlistener == NULL) {
result = listener_bind(listener, address);
if (result != ISC_R_SUCCESS) {
ns_lwreslistener_detach(&listener);
return (ISC_R_SUCCESS);
}
} else
listener_copysock(oldlistener, listener);
result = listener_startclients(listener);
if (result != ISC_R_SUCCESS) {
isc_sockaddr_format(address, socktext, sizeof(socktext));
isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
"lwres: failed to start %s: %s", socktext,
isc_result_totext(result));
ns_lwreslistener_detach(&listener);
return (ISC_R_SUCCESS);
}
if (oldlistener != NULL) {
/*
* Remove the old listener from the old list and shut it down.
*/
ISC_LIST_UNLINK(listeners, oldlistener, link);
listener_shutdown(oldlistener);
ns_lwreslistener_detach(&oldlistener);
} else {
isc_sockaddr_format(address, socktext, sizeof(socktext));
isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE,
"lwres listening on %s", socktext);
}
ISC_LIST_APPEND(*newlisteners, listener, link);
return (result);
}
isc_result_t
ns_lwresd_configure(isc_mem_t *mctx, cfg_obj_t *config) {
cfg_obj_t *lwreslist = NULL;
cfg_obj_t *lwres = NULL;
cfg_obj_t *listenerslist = NULL;
cfg_listelt_t *element = NULL;
ns_lwreslistener_t *listener;
ns_lwreslistenerlist_t newlisteners;
isc_result_t result;
char socktext[ISC_SOCKADDR_FORMATSIZE];
isc_sockaddr_t *addrs = NULL;
ns_lwresd_t *lwresd = NULL;
isc_uint32_t count = 0;
REQUIRE(mctx != NULL);
REQUIRE(config != NULL);
RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
ISC_LIST_INIT(newlisteners);
result = cfg_map_get(config, "lwres", &lwreslist);
if (result != ISC_R_SUCCESS)
return (ISC_R_SUCCESS);
LOCK(&listeners_lock);
/*
* Run through the new lwres address list, noting sockets that
* are already being listened on and moving them to the new list.
*
* Identifying duplicates addr/port combinations is left to either
* the underlying config code, or to the bind attempt getting an
* address-in-use error.
*/
for (element = cfg_list_first(lwreslist);
element != NULL;
element = cfg_list_next(element))
{
in_port_t port;
lwres = cfg_listelt_value(element);
CHECK(ns_lwdmanager_create(mctx, lwres, &lwresd));
port = lwresd_g_listenport;
if (port == 0)
port = LWRES_UDP_PORT;
listenerslist = NULL;
(void)cfg_map_get(lwres, "listen-on", &listenerslist);
if (listenerslist == NULL) {
struct in_addr localhost;
isc_sockaddr_t address;
localhost.s_addr = htonl(INADDR_LOOPBACK);
isc_sockaddr_fromin(&address, &localhost, port);
CHECK(configure_listener(&address, lwresd, mctx,
&newlisteners));
} else {
isc_uint32_t i;
CHECK(ns_config_getiplist(config, listenerslist,
port, mctx, &addrs, &count));
for (i = 0; i < count; i++)
CHECK(configure_listener(&addrs[i], lwresd,
mctx, &newlisteners));
ns_config_putiplist(mctx, &addrs, count);
}
ns_lwdmanager_detach(&lwresd);
}
/*
* Shutdown everything on the listeners list, and remove them from
* the list. Then put all of the new listeners on it.
*/
while (!ISC_LIST_EMPTY(listeners)) {
listener = ISC_LIST_HEAD(listeners);
ISC_LIST_UNLINK(listeners, listener, link);
listener_shutdown(listener);
ns_lwreslistener_detach(&listener);
isc_sockaddr_format(&listener->address,
socktext, sizeof(socktext));
isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE,
"lwres no longer listening on %s", socktext);
}
cleanup:
ISC_LIST_APPENDLIST(listeners, newlisteners, link);
if (addrs != NULL)
ns_config_putiplist(mctx, &addrs, count);
if (lwresd != NULL)
ns_lwdmanager_detach(&lwresd);
UNLOCK(&listeners_lock);
return (result);
}
void
ns_lwresd_shutdown(void) {
ns_lwreslistener_t *listener;
RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
while (!ISC_LIST_EMPTY(listeners)) {
listener = ISC_LIST_HEAD(listeners);
ISC_LIST_UNLINK(listeners, listener, link);
ns_lwreslistener_detach(&listener);
}
}