xref: /minix3/external/bsd/bind/dist/bin/named/lwdgabn.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: lwdgabn.c,v 1.4 2014/12/10 04:37:51 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004-2007, 2009  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 2000, 2001  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id: lwdgabn.c,v 1.24 2009/09/02 23:48:01 tbox Exp  */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek /*! \file */
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <config.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #include <stdlib.h>
27*00b67f09SDavid van Moolenbroek 
28*00b67f09SDavid van Moolenbroek #include <isc/netaddr.h>
29*00b67f09SDavid van Moolenbroek #include <isc/sockaddr.h>
30*00b67f09SDavid van Moolenbroek #include <isc/socket.h>
31*00b67f09SDavid van Moolenbroek #include <isc/string.h>		/* Required for HP/UX (and others?) */
32*00b67f09SDavid van Moolenbroek #include <isc/util.h>
33*00b67f09SDavid van Moolenbroek 
34*00b67f09SDavid van Moolenbroek #include <dns/adb.h>
35*00b67f09SDavid van Moolenbroek #include <dns/events.h>
36*00b67f09SDavid van Moolenbroek #include <dns/result.h>
37*00b67f09SDavid van Moolenbroek 
38*00b67f09SDavid van Moolenbroek #include <named/types.h>
39*00b67f09SDavid van Moolenbroek #include <named/lwaddr.h>
40*00b67f09SDavid van Moolenbroek #include <named/lwdclient.h>
41*00b67f09SDavid van Moolenbroek #include <named/lwresd.h>
42*00b67f09SDavid van Moolenbroek #include <named/lwsearch.h>
43*00b67f09SDavid van Moolenbroek #include <named/sortlist.h>
44*00b67f09SDavid van Moolenbroek 
45*00b67f09SDavid van Moolenbroek #define NEED_V4(c)	((((c)->find_wanted & LWRES_ADDRTYPE_V4) != 0) \
46*00b67f09SDavid van Moolenbroek 			 && ((c)->v4find == NULL))
47*00b67f09SDavid van Moolenbroek #define NEED_V6(c)	((((c)->find_wanted & LWRES_ADDRTYPE_V6) != 0) \
48*00b67f09SDavid van Moolenbroek 			 && ((c)->v6find == NULL))
49*00b67f09SDavid van Moolenbroek 
50*00b67f09SDavid van Moolenbroek static isc_result_t start_find(ns_lwdclient_t *);
51*00b67f09SDavid van Moolenbroek static void restart_find(ns_lwdclient_t *);
52*00b67f09SDavid van Moolenbroek static void init_gabn(ns_lwdclient_t *);
53*00b67f09SDavid van Moolenbroek 
54*00b67f09SDavid van Moolenbroek /*%
55*00b67f09SDavid van Moolenbroek  * Destroy any finds.  This can be used to "start over from scratch" and
56*00b67f09SDavid van Moolenbroek  * should only be called when events are _not_ being generated by the finds.
57*00b67f09SDavid van Moolenbroek  */
58*00b67f09SDavid van Moolenbroek static void
cleanup_gabn(ns_lwdclient_t * client)59*00b67f09SDavid van Moolenbroek cleanup_gabn(ns_lwdclient_t *client) {
60*00b67f09SDavid van Moolenbroek 	ns_lwdclient_log(50, "cleaning up client %p", client);
61*00b67f09SDavid van Moolenbroek 
62*00b67f09SDavid van Moolenbroek 	if (client->v6find != NULL) {
63*00b67f09SDavid van Moolenbroek 		if (client->v6find == client->v4find)
64*00b67f09SDavid van Moolenbroek 			client->v6find = NULL;
65*00b67f09SDavid van Moolenbroek 		else
66*00b67f09SDavid van Moolenbroek 			dns_adb_destroyfind(&client->v6find);
67*00b67f09SDavid van Moolenbroek 	}
68*00b67f09SDavid van Moolenbroek 	if (client->v4find != NULL)
69*00b67f09SDavid van Moolenbroek 		dns_adb_destroyfind(&client->v4find);
70*00b67f09SDavid van Moolenbroek }
71*00b67f09SDavid van Moolenbroek 
72*00b67f09SDavid van Moolenbroek static void
setup_addresses(ns_lwdclient_t * client,dns_adbfind_t * find,unsigned int at)73*00b67f09SDavid van Moolenbroek setup_addresses(ns_lwdclient_t *client, dns_adbfind_t *find, unsigned int at) {
74*00b67f09SDavid van Moolenbroek 	dns_adbaddrinfo_t *ai;
75*00b67f09SDavid van Moolenbroek 	lwres_addr_t *addr;
76*00b67f09SDavid van Moolenbroek 	int af;
77*00b67f09SDavid van Moolenbroek 	const struct sockaddr *sa;
78*00b67f09SDavid van Moolenbroek 	isc_result_t result;
79*00b67f09SDavid van Moolenbroek 
80*00b67f09SDavid van Moolenbroek 	if (at == DNS_ADBFIND_INET)
81*00b67f09SDavid van Moolenbroek 		af = AF_INET;
82*00b67f09SDavid van Moolenbroek 	else
83*00b67f09SDavid van Moolenbroek 		af = AF_INET6;
84*00b67f09SDavid van Moolenbroek 
85*00b67f09SDavid van Moolenbroek 	ai = ISC_LIST_HEAD(find->list);
86*00b67f09SDavid van Moolenbroek 	while (ai != NULL && client->gabn.naddrs < LWRES_MAX_ADDRS) {
87*00b67f09SDavid van Moolenbroek 		sa = &ai->sockaddr.type.sa;
88*00b67f09SDavid van Moolenbroek 		if (sa->sa_family != af)
89*00b67f09SDavid van Moolenbroek 			goto next;
90*00b67f09SDavid van Moolenbroek 
91*00b67f09SDavid van Moolenbroek 		addr = &client->addrs[client->gabn.naddrs];
92*00b67f09SDavid van Moolenbroek 
93*00b67f09SDavid van Moolenbroek 		result = lwaddr_lwresaddr_fromsockaddr(addr, &ai->sockaddr);
94*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
95*00b67f09SDavid van Moolenbroek 			goto next;
96*00b67f09SDavid van Moolenbroek 
97*00b67f09SDavid van Moolenbroek 		ns_lwdclient_log(50, "adding address %p, family %d, length %d",
98*00b67f09SDavid van Moolenbroek 				 addr->address, addr->family, addr->length);
99*00b67f09SDavid van Moolenbroek 
100*00b67f09SDavid van Moolenbroek 		client->gabn.naddrs++;
101*00b67f09SDavid van Moolenbroek 		REQUIRE(!LWRES_LINK_LINKED(addr, link));
102*00b67f09SDavid van Moolenbroek 		LWRES_LIST_APPEND(client->gabn.addrs, addr, link);
103*00b67f09SDavid van Moolenbroek 
104*00b67f09SDavid van Moolenbroek 	next:
105*00b67f09SDavid van Moolenbroek 		ai = ISC_LIST_NEXT(ai, publink);
106*00b67f09SDavid van Moolenbroek 	}
107*00b67f09SDavid van Moolenbroek }
108*00b67f09SDavid van Moolenbroek 
109*00b67f09SDavid van Moolenbroek typedef struct {
110*00b67f09SDavid van Moolenbroek 	isc_netaddr_t address;
111*00b67f09SDavid van Moolenbroek 	int rank;
112*00b67f09SDavid van Moolenbroek } rankedaddress;
113*00b67f09SDavid van Moolenbroek 
114*00b67f09SDavid van Moolenbroek static int
addr_compare(const void * av,const void * bv)115*00b67f09SDavid van Moolenbroek addr_compare(const void *av, const void *bv) {
116*00b67f09SDavid van Moolenbroek 	const rankedaddress *a = (const rankedaddress *) av;
117*00b67f09SDavid van Moolenbroek 	const rankedaddress *b = (const rankedaddress *) bv;
118*00b67f09SDavid van Moolenbroek 	return (a->rank - b->rank);
119*00b67f09SDavid van Moolenbroek }
120*00b67f09SDavid van Moolenbroek 
121*00b67f09SDavid van Moolenbroek static void
sort_addresses(ns_lwdclient_t * client)122*00b67f09SDavid van Moolenbroek sort_addresses(ns_lwdclient_t *client) {
123*00b67f09SDavid van Moolenbroek 	unsigned int naddrs;
124*00b67f09SDavid van Moolenbroek 	rankedaddress *addrs;
125*00b67f09SDavid van Moolenbroek 	isc_netaddr_t remote;
126*00b67f09SDavid van Moolenbroek 	dns_addressorderfunc_t order;
127*00b67f09SDavid van Moolenbroek 	const void *arg;
128*00b67f09SDavid van Moolenbroek 	ns_lwresd_t *lwresd = client->clientmgr->listener->manager;
129*00b67f09SDavid van Moolenbroek 	unsigned int i;
130*00b67f09SDavid van Moolenbroek 	isc_result_t result;
131*00b67f09SDavid van Moolenbroek 
132*00b67f09SDavid van Moolenbroek 	naddrs = client->gabn.naddrs;
133*00b67f09SDavid van Moolenbroek 
134*00b67f09SDavid van Moolenbroek 	if (naddrs <= 1 || lwresd->view->sortlist == NULL)
135*00b67f09SDavid van Moolenbroek 		return;
136*00b67f09SDavid van Moolenbroek 
137*00b67f09SDavid van Moolenbroek 	addrs = isc_mem_get(lwresd->mctx, sizeof(rankedaddress) * naddrs);
138*00b67f09SDavid van Moolenbroek 	if (addrs == NULL)
139*00b67f09SDavid van Moolenbroek 		return;
140*00b67f09SDavid van Moolenbroek 
141*00b67f09SDavid van Moolenbroek 	isc_netaddr_fromsockaddr(&remote, &client->address);
142*00b67f09SDavid van Moolenbroek 	ns_sortlist_byaddrsetup(lwresd->view->sortlist,
143*00b67f09SDavid van Moolenbroek 				&remote, &order, &arg);
144*00b67f09SDavid van Moolenbroek 	if (order == NULL) {
145*00b67f09SDavid van Moolenbroek 		isc_mem_put(lwresd->mctx, addrs,
146*00b67f09SDavid van Moolenbroek 			    sizeof(rankedaddress) * naddrs);
147*00b67f09SDavid van Moolenbroek 		return;
148*00b67f09SDavid van Moolenbroek 	}
149*00b67f09SDavid van Moolenbroek 	for (i = 0; i < naddrs; i++) {
150*00b67f09SDavid van Moolenbroek 		result = lwaddr_netaddr_fromlwresaddr(&addrs[i].address,
151*00b67f09SDavid van Moolenbroek 						      &client->addrs[i]);
152*00b67f09SDavid van Moolenbroek 		INSIST(result == ISC_R_SUCCESS);
153*00b67f09SDavid van Moolenbroek 		addrs[i].rank = (*order)(&addrs[i].address, arg);
154*00b67f09SDavid van Moolenbroek 	}
155*00b67f09SDavid van Moolenbroek 	qsort(addrs, naddrs, sizeof(rankedaddress), addr_compare);
156*00b67f09SDavid van Moolenbroek 	for (i = 0; i < naddrs; i++) {
157*00b67f09SDavid van Moolenbroek 		result = lwaddr_lwresaddr_fromnetaddr(&client->addrs[i],
158*00b67f09SDavid van Moolenbroek 						      &addrs[i].address);
159*00b67f09SDavid van Moolenbroek 		INSIST(result == ISC_R_SUCCESS);
160*00b67f09SDavid van Moolenbroek 	}
161*00b67f09SDavid van Moolenbroek 
162*00b67f09SDavid van Moolenbroek 	isc_mem_put(lwresd->mctx, addrs, sizeof(rankedaddress) * naddrs);
163*00b67f09SDavid van Moolenbroek }
164*00b67f09SDavid van Moolenbroek 
165*00b67f09SDavid van Moolenbroek static void
generate_reply(ns_lwdclient_t * client)166*00b67f09SDavid van Moolenbroek generate_reply(ns_lwdclient_t *client) {
167*00b67f09SDavid van Moolenbroek 	isc_result_t result;
168*00b67f09SDavid van Moolenbroek 	int lwres;
169*00b67f09SDavid van Moolenbroek 	isc_region_t r;
170*00b67f09SDavid van Moolenbroek 	lwres_buffer_t lwb;
171*00b67f09SDavid van Moolenbroek 	ns_lwdclientmgr_t *cm;
172*00b67f09SDavid van Moolenbroek 
173*00b67f09SDavid van Moolenbroek 	cm = client->clientmgr;
174*00b67f09SDavid van Moolenbroek 	lwb.base = NULL;
175*00b67f09SDavid van Moolenbroek 
176*00b67f09SDavid van Moolenbroek 	ns_lwdclient_log(50, "generating gabn reply for client %p", client);
177*00b67f09SDavid van Moolenbroek 
178*00b67f09SDavid van Moolenbroek 	/*
179*00b67f09SDavid van Moolenbroek 	 * We must make certain the client->find is not still active.
180*00b67f09SDavid van Moolenbroek 	 * If it is either the v4 or v6 answer, just set it to NULL and
181*00b67f09SDavid van Moolenbroek 	 * let the cleanup code destroy it.  Otherwise, destroy it now.
182*00b67f09SDavid van Moolenbroek 	 */
183*00b67f09SDavid van Moolenbroek 	if (client->find == client->v4find || client->find == client->v6find)
184*00b67f09SDavid van Moolenbroek 		client->find = NULL;
185*00b67f09SDavid van Moolenbroek 	else
186*00b67f09SDavid van Moolenbroek 		if (client->find != NULL)
187*00b67f09SDavid van Moolenbroek 			dns_adb_destroyfind(&client->find);
188*00b67f09SDavid van Moolenbroek 
189*00b67f09SDavid van Moolenbroek 	/*
190*00b67f09SDavid van Moolenbroek 	 * perhaps there are some here?
191*00b67f09SDavid van Moolenbroek 	 */
192*00b67f09SDavid van Moolenbroek 	if (NEED_V6(client) && client->v4find != NULL)
193*00b67f09SDavid van Moolenbroek 		client->v6find = client->v4find;
194*00b67f09SDavid van Moolenbroek 
195*00b67f09SDavid van Moolenbroek 	/*
196*00b67f09SDavid van Moolenbroek 	 * Run through the finds we have and wire them up to the gabn
197*00b67f09SDavid van Moolenbroek 	 * structure.
198*00b67f09SDavid van Moolenbroek 	 */
199*00b67f09SDavid van Moolenbroek 	LWRES_LIST_INIT(client->gabn.addrs);
200*00b67f09SDavid van Moolenbroek 	if (client->v4find != NULL)
201*00b67f09SDavid van Moolenbroek 		setup_addresses(client, client->v4find, DNS_ADBFIND_INET);
202*00b67f09SDavid van Moolenbroek 	if (client->v6find != NULL)
203*00b67f09SDavid van Moolenbroek 		setup_addresses(client, client->v6find, DNS_ADBFIND_INET6);
204*00b67f09SDavid van Moolenbroek 
205*00b67f09SDavid van Moolenbroek 	/*
206*00b67f09SDavid van Moolenbroek 	 * If there are no addresses, try the next element in the search
207*00b67f09SDavid van Moolenbroek 	 * path, if there are any more.  Otherwise, fall through into
208*00b67f09SDavid van Moolenbroek 	 * the error handling code below.
209*00b67f09SDavid van Moolenbroek 	 */
210*00b67f09SDavid van Moolenbroek 	if (client->gabn.naddrs == 0) {
211*00b67f09SDavid van Moolenbroek 		do {
212*00b67f09SDavid van Moolenbroek 			result = ns_lwsearchctx_next(&client->searchctx);
213*00b67f09SDavid van Moolenbroek 			if (result == ISC_R_SUCCESS) {
214*00b67f09SDavid van Moolenbroek 				cleanup_gabn(client);
215*00b67f09SDavid van Moolenbroek 				result = start_find(client);
216*00b67f09SDavid van Moolenbroek 				if (result == ISC_R_SUCCESS)
217*00b67f09SDavid van Moolenbroek 					return;
218*00b67f09SDavid van Moolenbroek 			}
219*00b67f09SDavid van Moolenbroek 		} while (result == ISC_R_SUCCESS);
220*00b67f09SDavid van Moolenbroek 	}
221*00b67f09SDavid van Moolenbroek 
222*00b67f09SDavid van Moolenbroek 	/*
223*00b67f09SDavid van Moolenbroek 	 * Render the packet.
224*00b67f09SDavid van Moolenbroek 	 */
225*00b67f09SDavid van Moolenbroek 	client->pkt.recvlength = LWRES_RECVLENGTH;
226*00b67f09SDavid van Moolenbroek 	client->pkt.authtype = 0; /* XXXMLG */
227*00b67f09SDavid van Moolenbroek 	client->pkt.authlength = 0;
228*00b67f09SDavid van Moolenbroek 
229*00b67f09SDavid van Moolenbroek 	/*
230*00b67f09SDavid van Moolenbroek 	 * If there are no addresses, return failure.
231*00b67f09SDavid van Moolenbroek 	 */
232*00b67f09SDavid van Moolenbroek 	if (client->gabn.naddrs != 0)
233*00b67f09SDavid van Moolenbroek 		client->pkt.result = LWRES_R_SUCCESS;
234*00b67f09SDavid van Moolenbroek 	else
235*00b67f09SDavid van Moolenbroek 		client->pkt.result = LWRES_R_NOTFOUND;
236*00b67f09SDavid van Moolenbroek 
237*00b67f09SDavid van Moolenbroek 	sort_addresses(client);
238*00b67f09SDavid van Moolenbroek 
239*00b67f09SDavid van Moolenbroek 	lwres = lwres_gabnresponse_render(cm->lwctx, &client->gabn,
240*00b67f09SDavid van Moolenbroek 					  &client->pkt, &lwb);
241*00b67f09SDavid van Moolenbroek 	if (lwres != LWRES_R_SUCCESS)
242*00b67f09SDavid van Moolenbroek 		goto out;
243*00b67f09SDavid van Moolenbroek 
244*00b67f09SDavid van Moolenbroek 	r.base = lwb.base;
245*00b67f09SDavid van Moolenbroek 	r.length = lwb.used;
246*00b67f09SDavid van Moolenbroek 	client->sendbuf = r.base;
247*00b67f09SDavid van Moolenbroek 	client->sendlength = r.length;
248*00b67f09SDavid van Moolenbroek 	result = ns_lwdclient_sendreply(client, &r);
249*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
250*00b67f09SDavid van Moolenbroek 		goto out;
251*00b67f09SDavid van Moolenbroek 
252*00b67f09SDavid van Moolenbroek 	NS_LWDCLIENT_SETSEND(client);
253*00b67f09SDavid van Moolenbroek 
254*00b67f09SDavid van Moolenbroek 	/*
255*00b67f09SDavid van Moolenbroek 	 * All done!
256*00b67f09SDavid van Moolenbroek 	 */
257*00b67f09SDavid van Moolenbroek 	cleanup_gabn(client);
258*00b67f09SDavid van Moolenbroek 
259*00b67f09SDavid van Moolenbroek 	return;
260*00b67f09SDavid van Moolenbroek 
261*00b67f09SDavid van Moolenbroek  out:
262*00b67f09SDavid van Moolenbroek 	cleanup_gabn(client);
263*00b67f09SDavid van Moolenbroek 
264*00b67f09SDavid van Moolenbroek 	if (lwb.base != NULL)
265*00b67f09SDavid van Moolenbroek 		lwres_context_freemem(client->clientmgr->lwctx,
266*00b67f09SDavid van Moolenbroek 				      lwb.base, lwb.length);
267*00b67f09SDavid van Moolenbroek 
268*00b67f09SDavid van Moolenbroek 	ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
269*00b67f09SDavid van Moolenbroek }
270*00b67f09SDavid van Moolenbroek 
271*00b67f09SDavid van Moolenbroek /*
272*00b67f09SDavid van Moolenbroek  * Take the current real name, move it to an alias slot (if any are
273*00b67f09SDavid van Moolenbroek  * open) then put this new name in as the real name for the target.
274*00b67f09SDavid van Moolenbroek  *
275*00b67f09SDavid van Moolenbroek  * Return success if it can be rendered, otherwise failure.  Note that
276*00b67f09SDavid van Moolenbroek  * not having enough alias slots open is NOT a failure.
277*00b67f09SDavid van Moolenbroek  */
278*00b67f09SDavid van Moolenbroek static isc_result_t
add_alias(ns_lwdclient_t * client)279*00b67f09SDavid van Moolenbroek add_alias(ns_lwdclient_t *client) {
280*00b67f09SDavid van Moolenbroek 	isc_buffer_t b;
281*00b67f09SDavid van Moolenbroek 	isc_result_t result;
282*00b67f09SDavid van Moolenbroek 	isc_uint16_t naliases;
283*00b67f09SDavid van Moolenbroek 
284*00b67f09SDavid van Moolenbroek 	b = client->recv_buffer;
285*00b67f09SDavid van Moolenbroek 
286*00b67f09SDavid van Moolenbroek 	/*
287*00b67f09SDavid van Moolenbroek 	 * Render the new name to the buffer.
288*00b67f09SDavid van Moolenbroek 	 */
289*00b67f09SDavid van Moolenbroek 	result = dns_name_totext(dns_fixedname_name(&client->target_name),
290*00b67f09SDavid van Moolenbroek 				 ISC_TRUE, &client->recv_buffer);
291*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
292*00b67f09SDavid van Moolenbroek 		return (result);
293*00b67f09SDavid van Moolenbroek 
294*00b67f09SDavid van Moolenbroek 	/*
295*00b67f09SDavid van Moolenbroek 	 * Are there any open slots?
296*00b67f09SDavid van Moolenbroek 	 */
297*00b67f09SDavid van Moolenbroek 	naliases = client->gabn.naliases;
298*00b67f09SDavid van Moolenbroek 	if (naliases < LWRES_MAX_ALIASES) {
299*00b67f09SDavid van Moolenbroek 		client->gabn.aliases[naliases] = client->gabn.realname;
300*00b67f09SDavid van Moolenbroek 		client->gabn.aliaslen[naliases] = client->gabn.realnamelen;
301*00b67f09SDavid van Moolenbroek 		client->gabn.naliases++;
302*00b67f09SDavid van Moolenbroek 	}
303*00b67f09SDavid van Moolenbroek 
304*00b67f09SDavid van Moolenbroek 	/*
305*00b67f09SDavid van Moolenbroek 	 * Save this name away as the current real name.
306*00b67f09SDavid van Moolenbroek 	 */
307*00b67f09SDavid van Moolenbroek 	client->gabn.realname = (char *)(b.base) + b.used;
308*00b67f09SDavid van Moolenbroek 	client->gabn.realnamelen = client->recv_buffer.used - b.used;
309*00b67f09SDavid van Moolenbroek 
310*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
311*00b67f09SDavid van Moolenbroek }
312*00b67f09SDavid van Moolenbroek 
313*00b67f09SDavid van Moolenbroek static isc_result_t
store_realname(ns_lwdclient_t * client)314*00b67f09SDavid van Moolenbroek store_realname(ns_lwdclient_t *client) {
315*00b67f09SDavid van Moolenbroek 	isc_buffer_t b;
316*00b67f09SDavid van Moolenbroek 	isc_result_t result;
317*00b67f09SDavid van Moolenbroek 	dns_name_t *tname;
318*00b67f09SDavid van Moolenbroek 
319*00b67f09SDavid van Moolenbroek 	b = client->recv_buffer;
320*00b67f09SDavid van Moolenbroek 
321*00b67f09SDavid van Moolenbroek 	tname = dns_fixedname_name(&client->target_name);
322*00b67f09SDavid van Moolenbroek 	result = ns_lwsearchctx_current(&client->searchctx, tname);
323*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
324*00b67f09SDavid van Moolenbroek 		return (result);
325*00b67f09SDavid van Moolenbroek 
326*00b67f09SDavid van Moolenbroek 	/*
327*00b67f09SDavid van Moolenbroek 	 * Render the new name to the buffer.
328*00b67f09SDavid van Moolenbroek 	 */
329*00b67f09SDavid van Moolenbroek 	result = dns_name_totext(tname, ISC_TRUE, &client->recv_buffer);
330*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
331*00b67f09SDavid van Moolenbroek 		return (result);
332*00b67f09SDavid van Moolenbroek 
333*00b67f09SDavid van Moolenbroek 	/*
334*00b67f09SDavid van Moolenbroek 	 * Save this name away as the current real name.
335*00b67f09SDavid van Moolenbroek 	 */
336*00b67f09SDavid van Moolenbroek 	client->gabn.realname = (char *) b.base + b.used;
337*00b67f09SDavid van Moolenbroek 	client->gabn.realnamelen = client->recv_buffer.used - b.used;
338*00b67f09SDavid van Moolenbroek 
339*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
340*00b67f09SDavid van Moolenbroek }
341*00b67f09SDavid van Moolenbroek 
342*00b67f09SDavid van Moolenbroek static void
process_gabn_finddone(isc_task_t * task,isc_event_t * ev)343*00b67f09SDavid van Moolenbroek process_gabn_finddone(isc_task_t *task, isc_event_t *ev) {
344*00b67f09SDavid van Moolenbroek 	ns_lwdclient_t *client = ev->ev_arg;
345*00b67f09SDavid van Moolenbroek 	isc_eventtype_t evtype;
346*00b67f09SDavid van Moolenbroek 	isc_boolean_t claimed;
347*00b67f09SDavid van Moolenbroek 
348*00b67f09SDavid van Moolenbroek 	ns_lwdclient_log(50, "find done for task %p, client %p", task, client);
349*00b67f09SDavid van Moolenbroek 
350*00b67f09SDavid van Moolenbroek 	evtype = ev->ev_type;
351*00b67f09SDavid van Moolenbroek 	isc_event_free(&ev);
352*00b67f09SDavid van Moolenbroek 
353*00b67f09SDavid van Moolenbroek 	/*
354*00b67f09SDavid van Moolenbroek 	 * No more info to be had?  If so, we have all the good stuff
355*00b67f09SDavid van Moolenbroek 	 * right now, so we can render things.
356*00b67f09SDavid van Moolenbroek 	 */
357*00b67f09SDavid van Moolenbroek 	claimed = ISC_FALSE;
358*00b67f09SDavid van Moolenbroek 	if (evtype == DNS_EVENT_ADBNOMOREADDRESSES) {
359*00b67f09SDavid van Moolenbroek 		if (NEED_V4(client)) {
360*00b67f09SDavid van Moolenbroek 			client->v4find = client->find;
361*00b67f09SDavid van Moolenbroek 			claimed = ISC_TRUE;
362*00b67f09SDavid van Moolenbroek 		}
363*00b67f09SDavid van Moolenbroek 		if (NEED_V6(client)) {
364*00b67f09SDavid van Moolenbroek 			client->v6find = client->find;
365*00b67f09SDavid van Moolenbroek 			claimed = ISC_TRUE;
366*00b67f09SDavid van Moolenbroek 		}
367*00b67f09SDavid van Moolenbroek 		if (client->find != NULL) {
368*00b67f09SDavid van Moolenbroek 			if (claimed)
369*00b67f09SDavid van Moolenbroek 				client->find = NULL;
370*00b67f09SDavid van Moolenbroek 			else
371*00b67f09SDavid van Moolenbroek 				dns_adb_destroyfind(&client->find);
372*00b67f09SDavid van Moolenbroek 
373*00b67f09SDavid van Moolenbroek 		}
374*00b67f09SDavid van Moolenbroek 		generate_reply(client);
375*00b67f09SDavid van Moolenbroek 		return;
376*00b67f09SDavid van Moolenbroek 	}
377*00b67f09SDavid van Moolenbroek 
378*00b67f09SDavid van Moolenbroek 	/*
379*00b67f09SDavid van Moolenbroek 	 * We probably don't need this find anymore.  We're either going to
380*00b67f09SDavid van Moolenbroek 	 * reissue it, or an error occurred.  Either way, we're done with
381*00b67f09SDavid van Moolenbroek 	 * it.
382*00b67f09SDavid van Moolenbroek 	 */
383*00b67f09SDavid van Moolenbroek 	if ((client->find != client->v4find)
384*00b67f09SDavid van Moolenbroek 	    && (client->find != client->v6find)) {
385*00b67f09SDavid van Moolenbroek 		dns_adb_destroyfind(&client->find);
386*00b67f09SDavid van Moolenbroek 	} else {
387*00b67f09SDavid van Moolenbroek 		client->find = NULL;
388*00b67f09SDavid van Moolenbroek 	}
389*00b67f09SDavid van Moolenbroek 
390*00b67f09SDavid van Moolenbroek 	/*
391*00b67f09SDavid van Moolenbroek 	 * We have some new information we can gather.  Run off and fetch
392*00b67f09SDavid van Moolenbroek 	 * it.
393*00b67f09SDavid van Moolenbroek 	 */
394*00b67f09SDavid van Moolenbroek 	if (evtype == DNS_EVENT_ADBMOREADDRESSES) {
395*00b67f09SDavid van Moolenbroek 		restart_find(client);
396*00b67f09SDavid van Moolenbroek 		return;
397*00b67f09SDavid van Moolenbroek 	}
398*00b67f09SDavid van Moolenbroek 
399*00b67f09SDavid van Moolenbroek 	/*
400*00b67f09SDavid van Moolenbroek 	 * An error or other strangeness happened.  Drop this query.
401*00b67f09SDavid van Moolenbroek 	 */
402*00b67f09SDavid van Moolenbroek 	cleanup_gabn(client);
403*00b67f09SDavid van Moolenbroek 	ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
404*00b67f09SDavid van Moolenbroek }
405*00b67f09SDavid van Moolenbroek 
406*00b67f09SDavid van Moolenbroek static void
restart_find(ns_lwdclient_t * client)407*00b67f09SDavid van Moolenbroek restart_find(ns_lwdclient_t *client) {
408*00b67f09SDavid van Moolenbroek 	unsigned int options;
409*00b67f09SDavid van Moolenbroek 	isc_result_t result;
410*00b67f09SDavid van Moolenbroek 	isc_boolean_t claimed;
411*00b67f09SDavid van Moolenbroek 
412*00b67f09SDavid van Moolenbroek 	ns_lwdclient_log(50, "starting find for client %p", client);
413*00b67f09SDavid van Moolenbroek 
414*00b67f09SDavid van Moolenbroek 	/*
415*00b67f09SDavid van Moolenbroek 	 * Issue a find for the name contained in the request.  We won't
416*00b67f09SDavid van Moolenbroek 	 * set the bit that says "anything is good enough" -- we want it
417*00b67f09SDavid van Moolenbroek 	 * all.
418*00b67f09SDavid van Moolenbroek 	 */
419*00b67f09SDavid van Moolenbroek 	options = 0;
420*00b67f09SDavid van Moolenbroek 	options |= DNS_ADBFIND_WANTEVENT;
421*00b67f09SDavid van Moolenbroek 	options |= DNS_ADBFIND_RETURNLAME;
422*00b67f09SDavid van Moolenbroek 
423*00b67f09SDavid van Moolenbroek 	/*
424*00b67f09SDavid van Moolenbroek 	 * Set the bits up here to mark that we want this address family
425*00b67f09SDavid van Moolenbroek 	 * and that we do not currently have a find pending.  We will
426*00b67f09SDavid van Moolenbroek 	 * set that bit again below if it turns out we will get an event.
427*00b67f09SDavid van Moolenbroek 	 */
428*00b67f09SDavid van Moolenbroek 	if (NEED_V4(client))
429*00b67f09SDavid van Moolenbroek 		options |= DNS_ADBFIND_INET;
430*00b67f09SDavid van Moolenbroek 	if (NEED_V6(client))
431*00b67f09SDavid van Moolenbroek 		options |= DNS_ADBFIND_INET6;
432*00b67f09SDavid van Moolenbroek 
433*00b67f09SDavid van Moolenbroek  find_again:
434*00b67f09SDavid van Moolenbroek 	INSIST(client->find == NULL);
435*00b67f09SDavid van Moolenbroek 	result = dns_adb_createfind(client->clientmgr->view->adb,
436*00b67f09SDavid van Moolenbroek 				    client->clientmgr->task,
437*00b67f09SDavid van Moolenbroek 				    process_gabn_finddone, client,
438*00b67f09SDavid van Moolenbroek 				    dns_fixedname_name(&client->target_name),
439*00b67f09SDavid van Moolenbroek 				    dns_rootname, 0, options, 0,
440*00b67f09SDavid van Moolenbroek 				    dns_fixedname_name(&client->target_name),
441*00b67f09SDavid van Moolenbroek 				    client->clientmgr->view->dstport,
442*00b67f09SDavid van Moolenbroek 				    &client->find);
443*00b67f09SDavid van Moolenbroek 
444*00b67f09SDavid van Moolenbroek 	/*
445*00b67f09SDavid van Moolenbroek 	 * Did we get an alias?  If so, save it and re-issue the query.
446*00b67f09SDavid van Moolenbroek 	 */
447*00b67f09SDavid van Moolenbroek 	if (result == DNS_R_ALIAS) {
448*00b67f09SDavid van Moolenbroek 		ns_lwdclient_log(50, "found alias, restarting query");
449*00b67f09SDavid van Moolenbroek 		dns_adb_destroyfind(&client->find);
450*00b67f09SDavid van Moolenbroek 		cleanup_gabn(client);
451*00b67f09SDavid van Moolenbroek 		result = add_alias(client);
452*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
453*00b67f09SDavid van Moolenbroek 			ns_lwdclient_log(50,
454*00b67f09SDavid van Moolenbroek 					 "out of buffer space adding alias");
455*00b67f09SDavid van Moolenbroek 			ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
456*00b67f09SDavid van Moolenbroek 			return;
457*00b67f09SDavid van Moolenbroek 		}
458*00b67f09SDavid van Moolenbroek 		goto find_again;
459*00b67f09SDavid van Moolenbroek 	}
460*00b67f09SDavid van Moolenbroek 
461*00b67f09SDavid van Moolenbroek 	ns_lwdclient_log(50, "find returned %d (%s)", result,
462*00b67f09SDavid van Moolenbroek 			 isc_result_totext(result));
463*00b67f09SDavid van Moolenbroek 
464*00b67f09SDavid van Moolenbroek 	/*
465*00b67f09SDavid van Moolenbroek 	 * Did we get an error?
466*00b67f09SDavid van Moolenbroek 	 */
467*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
468*00b67f09SDavid van Moolenbroek 		if (client->find != NULL)
469*00b67f09SDavid van Moolenbroek 			dns_adb_destroyfind(&client->find);
470*00b67f09SDavid van Moolenbroek 		cleanup_gabn(client);
471*00b67f09SDavid van Moolenbroek 		ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
472*00b67f09SDavid van Moolenbroek 		return;
473*00b67f09SDavid van Moolenbroek 	}
474*00b67f09SDavid van Moolenbroek 
475*00b67f09SDavid van Moolenbroek 	claimed = ISC_FALSE;
476*00b67f09SDavid van Moolenbroek 
477*00b67f09SDavid van Moolenbroek 	/*
478*00b67f09SDavid van Moolenbroek 	 * Did we get our answer to V4 addresses?
479*00b67f09SDavid van Moolenbroek 	 */
480*00b67f09SDavid van Moolenbroek 	if (NEED_V4(client)
481*00b67f09SDavid van Moolenbroek 	    && ((client->find->query_pending & DNS_ADBFIND_INET) == 0)) {
482*00b67f09SDavid van Moolenbroek 		ns_lwdclient_log(50, "client %p ipv4 satisfied by find %p",
483*00b67f09SDavid van Moolenbroek 				 client, client->find);
484*00b67f09SDavid van Moolenbroek 		claimed = ISC_TRUE;
485*00b67f09SDavid van Moolenbroek 		client->v4find = client->find;
486*00b67f09SDavid van Moolenbroek 	}
487*00b67f09SDavid van Moolenbroek 
488*00b67f09SDavid van Moolenbroek 	/*
489*00b67f09SDavid van Moolenbroek 	 * Did we get our answer to V6 addresses?
490*00b67f09SDavid van Moolenbroek 	 */
491*00b67f09SDavid van Moolenbroek 	if (NEED_V6(client)
492*00b67f09SDavid van Moolenbroek 	    && ((client->find->query_pending & DNS_ADBFIND_INET6) == 0)) {
493*00b67f09SDavid van Moolenbroek 		ns_lwdclient_log(50, "client %p ipv6 satisfied by find %p",
494*00b67f09SDavid van Moolenbroek 				 client, client->find);
495*00b67f09SDavid van Moolenbroek 		claimed = ISC_TRUE;
496*00b67f09SDavid van Moolenbroek 		client->v6find = client->find;
497*00b67f09SDavid van Moolenbroek 	}
498*00b67f09SDavid van Moolenbroek 
499*00b67f09SDavid van Moolenbroek 	/*
500*00b67f09SDavid van Moolenbroek 	 * If we're going to get an event, set our internal pending flag
501*00b67f09SDavid van Moolenbroek 	 * and return.  When we get an event back we'll do the right
502*00b67f09SDavid van Moolenbroek 	 * thing, basically by calling this function again, perhaps with a
503*00b67f09SDavid van Moolenbroek 	 * new target name.
504*00b67f09SDavid van Moolenbroek 	 *
505*00b67f09SDavid van Moolenbroek 	 * If we have both v4 and v6, and we are still getting an event,
506*00b67f09SDavid van Moolenbroek 	 * we have a programming error, so die hard.
507*00b67f09SDavid van Moolenbroek 	 */
508*00b67f09SDavid van Moolenbroek 	if ((client->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
509*00b67f09SDavid van Moolenbroek 		ns_lwdclient_log(50, "event will be sent");
510*00b67f09SDavid van Moolenbroek 		INSIST(client->v4find == NULL || client->v6find == NULL);
511*00b67f09SDavid van Moolenbroek 		return;
512*00b67f09SDavid van Moolenbroek 	}
513*00b67f09SDavid van Moolenbroek 	ns_lwdclient_log(50, "no event will be sent");
514*00b67f09SDavid van Moolenbroek 	if (claimed)
515*00b67f09SDavid van Moolenbroek 		client->find = NULL;
516*00b67f09SDavid van Moolenbroek 	else
517*00b67f09SDavid van Moolenbroek 		dns_adb_destroyfind(&client->find);
518*00b67f09SDavid van Moolenbroek 
519*00b67f09SDavid van Moolenbroek 	/*
520*00b67f09SDavid van Moolenbroek 	 * We seem to have everything we asked for, or at least we are
521*00b67f09SDavid van Moolenbroek 	 * able to respond with things we've learned.
522*00b67f09SDavid van Moolenbroek 	 */
523*00b67f09SDavid van Moolenbroek 
524*00b67f09SDavid van Moolenbroek 	generate_reply(client);
525*00b67f09SDavid van Moolenbroek }
526*00b67f09SDavid van Moolenbroek 
527*00b67f09SDavid van Moolenbroek static isc_result_t
start_find(ns_lwdclient_t * client)528*00b67f09SDavid van Moolenbroek start_find(ns_lwdclient_t *client) {
529*00b67f09SDavid van Moolenbroek 	isc_result_t result;
530*00b67f09SDavid van Moolenbroek 
531*00b67f09SDavid van Moolenbroek 	/*
532*00b67f09SDavid van Moolenbroek 	 * Initialize the real name and alias arrays in the reply we're
533*00b67f09SDavid van Moolenbroek 	 * going to build up.
534*00b67f09SDavid van Moolenbroek 	 */
535*00b67f09SDavid van Moolenbroek 	init_gabn(client);
536*00b67f09SDavid van Moolenbroek 
537*00b67f09SDavid van Moolenbroek 	result = store_realname(client);
538*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
539*00b67f09SDavid van Moolenbroek 		return (result);
540*00b67f09SDavid van Moolenbroek 	restart_find(client);
541*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
542*00b67f09SDavid van Moolenbroek 
543*00b67f09SDavid van Moolenbroek }
544*00b67f09SDavid van Moolenbroek 
545*00b67f09SDavid van Moolenbroek static void
init_gabn(ns_lwdclient_t * client)546*00b67f09SDavid van Moolenbroek init_gabn(ns_lwdclient_t *client) {
547*00b67f09SDavid van Moolenbroek 	int i;
548*00b67f09SDavid van Moolenbroek 
549*00b67f09SDavid van Moolenbroek 	/*
550*00b67f09SDavid van Moolenbroek 	 * Initialize the real name and alias arrays in the reply we're
551*00b67f09SDavid van Moolenbroek 	 * going to build up.
552*00b67f09SDavid van Moolenbroek 	 */
553*00b67f09SDavid van Moolenbroek 	for (i = 0; i < LWRES_MAX_ALIASES; i++) {
554*00b67f09SDavid van Moolenbroek 		client->aliases[i] = NULL;
555*00b67f09SDavid van Moolenbroek 		client->aliaslen[i] = 0;
556*00b67f09SDavid van Moolenbroek 	}
557*00b67f09SDavid van Moolenbroek 	for (i = 0; i < LWRES_MAX_ADDRS; i++) {
558*00b67f09SDavid van Moolenbroek 		client->addrs[i].family = 0;
559*00b67f09SDavid van Moolenbroek 		client->addrs[i].length = 0;
560*00b67f09SDavid van Moolenbroek 		memset(client->addrs[i].address, 0, LWRES_ADDR_MAXLEN);
561*00b67f09SDavid van Moolenbroek 		LWRES_LINK_INIT(&client->addrs[i], link);
562*00b67f09SDavid van Moolenbroek 	}
563*00b67f09SDavid van Moolenbroek 
564*00b67f09SDavid van Moolenbroek 	client->gabn.naliases = 0;
565*00b67f09SDavid van Moolenbroek 	client->gabn.naddrs = 0;
566*00b67f09SDavid van Moolenbroek 	client->gabn.realname = NULL;
567*00b67f09SDavid van Moolenbroek 	client->gabn.aliases = client->aliases;
568*00b67f09SDavid van Moolenbroek 	client->gabn.realnamelen = 0;
569*00b67f09SDavid van Moolenbroek 	client->gabn.aliaslen = client->aliaslen;
570*00b67f09SDavid van Moolenbroek 	LWRES_LIST_INIT(client->gabn.addrs);
571*00b67f09SDavid van Moolenbroek 	client->gabn.base = NULL;
572*00b67f09SDavid van Moolenbroek 	client->gabn.baselen = 0;
573*00b67f09SDavid van Moolenbroek 
574*00b67f09SDavid van Moolenbroek 	/*
575*00b67f09SDavid van Moolenbroek 	 * Set up the internal buffer to point to the receive region.
576*00b67f09SDavid van Moolenbroek 	 */
577*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH);
578*00b67f09SDavid van Moolenbroek }
579*00b67f09SDavid van Moolenbroek 
580*00b67f09SDavid van Moolenbroek /*
581*00b67f09SDavid van Moolenbroek  * When we are called, we can be assured that:
582*00b67f09SDavid van Moolenbroek  *
583*00b67f09SDavid van Moolenbroek  *	client->sockaddr contains the address we need to reply to,
584*00b67f09SDavid van Moolenbroek  *
585*00b67f09SDavid van Moolenbroek  *	client->pkt contains the packet header data,
586*00b67f09SDavid van Moolenbroek  *
587*00b67f09SDavid van Moolenbroek  *	the packet "checks out" overall -- any MD5 hashes or crypto
588*00b67f09SDavid van Moolenbroek  *	bits have been verified,
589*00b67f09SDavid van Moolenbroek  *
590*00b67f09SDavid van Moolenbroek  *	"b" points to the remaining data after the packet header
591*00b67f09SDavid van Moolenbroek  *	was parsed off.
592*00b67f09SDavid van Moolenbroek  *
593*00b67f09SDavid van Moolenbroek  *	We are in a the RECVDONE state.
594*00b67f09SDavid van Moolenbroek  *
595*00b67f09SDavid van Moolenbroek  * From this state we will enter the SEND state if we happen to have
596*00b67f09SDavid van Moolenbroek  * everything we need or we need to return an error packet, or to the
597*00b67f09SDavid van Moolenbroek  * FINDWAIT state if we need to look things up.
598*00b67f09SDavid van Moolenbroek  */
599*00b67f09SDavid van Moolenbroek void
ns_lwdclient_processgabn(ns_lwdclient_t * client,lwres_buffer_t * b)600*00b67f09SDavid van Moolenbroek ns_lwdclient_processgabn(ns_lwdclient_t *client, lwres_buffer_t *b) {
601*00b67f09SDavid van Moolenbroek 	isc_result_t result;
602*00b67f09SDavid van Moolenbroek 	lwres_gabnrequest_t *req;
603*00b67f09SDavid van Moolenbroek 	ns_lwdclientmgr_t *cm;
604*00b67f09SDavid van Moolenbroek 	isc_buffer_t namebuf;
605*00b67f09SDavid van Moolenbroek 
606*00b67f09SDavid van Moolenbroek 	REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
607*00b67f09SDavid van Moolenbroek 
608*00b67f09SDavid van Moolenbroek 	cm = client->clientmgr;
609*00b67f09SDavid van Moolenbroek 	req = NULL;
610*00b67f09SDavid van Moolenbroek 
611*00b67f09SDavid van Moolenbroek 	result = lwres_gabnrequest_parse(client->clientmgr->lwctx,
612*00b67f09SDavid van Moolenbroek 					 b, &client->pkt, &req);
613*00b67f09SDavid van Moolenbroek 	if (result != LWRES_R_SUCCESS)
614*00b67f09SDavid van Moolenbroek 		goto out;
615*00b67f09SDavid van Moolenbroek 	if (req->name == NULL)
616*00b67f09SDavid van Moolenbroek 		goto out;
617*00b67f09SDavid van Moolenbroek 
618*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&namebuf, req->name, req->namelen);
619*00b67f09SDavid van Moolenbroek 	isc_buffer_add(&namebuf, req->namelen);
620*00b67f09SDavid van Moolenbroek 
621*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&client->target_name);
622*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&client->query_name);
623*00b67f09SDavid van Moolenbroek 	result = dns_name_fromtext(dns_fixedname_name(&client->query_name),
624*00b67f09SDavid van Moolenbroek 				   &namebuf, NULL, 0, NULL);
625*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
626*00b67f09SDavid van Moolenbroek 		goto out;
627*00b67f09SDavid van Moolenbroek 	ns_lwsearchctx_init(&client->searchctx,
628*00b67f09SDavid van Moolenbroek 			    cm->listener->manager->search,
629*00b67f09SDavid van Moolenbroek 			    dns_fixedname_name(&client->query_name),
630*00b67f09SDavid van Moolenbroek 			    cm->listener->manager->ndots);
631*00b67f09SDavid van Moolenbroek 	ns_lwsearchctx_first(&client->searchctx);
632*00b67f09SDavid van Moolenbroek 
633*00b67f09SDavid van Moolenbroek 	client->find_wanted = req->addrtypes;
634*00b67f09SDavid van Moolenbroek 	ns_lwdclient_log(50, "client %p looking for addrtypes %08x",
635*00b67f09SDavid van Moolenbroek 			 client, client->find_wanted);
636*00b67f09SDavid van Moolenbroek 
637*00b67f09SDavid van Moolenbroek 	/*
638*00b67f09SDavid van Moolenbroek 	 * We no longer need to keep this around.
639*00b67f09SDavid van Moolenbroek 	 */
640*00b67f09SDavid van Moolenbroek 	lwres_gabnrequest_free(client->clientmgr->lwctx, &req);
641*00b67f09SDavid van Moolenbroek 
642*00b67f09SDavid van Moolenbroek 	/*
643*00b67f09SDavid van Moolenbroek 	 * Start the find.
644*00b67f09SDavid van Moolenbroek 	 */
645*00b67f09SDavid van Moolenbroek 	result = start_find(client);
646*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
647*00b67f09SDavid van Moolenbroek 		goto out;
648*00b67f09SDavid van Moolenbroek 
649*00b67f09SDavid van Moolenbroek 	return;
650*00b67f09SDavid van Moolenbroek 
651*00b67f09SDavid van Moolenbroek 	/*
652*00b67f09SDavid van Moolenbroek 	 * We're screwed.  Return an error packet to our caller.
653*00b67f09SDavid van Moolenbroek 	 */
654*00b67f09SDavid van Moolenbroek  out:
655*00b67f09SDavid van Moolenbroek 	if (req != NULL)
656*00b67f09SDavid van Moolenbroek 		lwres_gabnrequest_free(client->clientmgr->lwctx, &req);
657*00b67f09SDavid van Moolenbroek 
658*00b67f09SDavid van Moolenbroek 	ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
659*00b67f09SDavid van Moolenbroek }
660