1135446Strhodes/*
2193149Sdougb * Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
3135446Strhodes * Copyright (C) 2000, 2001  Internet Software Consortium.
4135446Strhodes *
5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any
6135446Strhodes * purpose with or without fee is hereby granted, provided that the above
7135446Strhodes * copyright notice and this permission notice appear in all copies.
8135446Strhodes *
9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11135446Strhodes * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15135446Strhodes * PERFORMANCE OF THIS SOFTWARE.
16135446Strhodes */
17135446Strhodes
18234010Sdougb/* $Id: lwsearch.c,v 1.13 2007/06/19 23:46:59 tbox Exp $ */
19135446Strhodes
20170222Sdougb/*! \file */
21170222Sdougb
22135446Strhodes#include <config.h>
23135446Strhodes
24135446Strhodes#include <isc/magic.h>
25135446Strhodes#include <isc/mem.h>
26135446Strhodes#include <isc/mutex.h>
27135446Strhodes#include <isc/result.h>
28135446Strhodes#include <isc/types.h>
29135446Strhodes#include <isc/util.h>
30135446Strhodes
31135446Strhodes#include <dns/name.h>
32135446Strhodes#include <dns/types.h>
33135446Strhodes
34135446Strhodes#include <named/lwsearch.h>
35135446Strhodes#include <named/types.h>
36135446Strhodes
37135446Strhodes#define LWSEARCHLIST_MAGIC		ISC_MAGIC('L', 'W', 'S', 'L')
38135446Strhodes#define VALID_LWSEARCHLIST(l)		ISC_MAGIC_VALID(l, LWSEARCHLIST_MAGIC)
39135446Strhodes
40135446Strhodesisc_result_t
41135446Strhodesns_lwsearchlist_create(isc_mem_t *mctx, ns_lwsearchlist_t **listp) {
42135446Strhodes	ns_lwsearchlist_t *list;
43170222Sdougb	isc_result_t result;
44135446Strhodes
45135446Strhodes	REQUIRE(mctx != NULL);
46135446Strhodes	REQUIRE(listp != NULL && *listp == NULL);
47135446Strhodes
48135446Strhodes	list = isc_mem_get(mctx, sizeof(ns_lwsearchlist_t));
49135446Strhodes	if (list == NULL)
50135446Strhodes		return (ISC_R_NOMEMORY);
51135446Strhodes
52170222Sdougb	result = isc_mutex_init(&list->lock);
53170222Sdougb	if (result != ISC_R_SUCCESS) {
54170222Sdougb		isc_mem_put(mctx, list, sizeof(ns_lwsearchlist_t));
55170222Sdougb		return (result);
56170222Sdougb	}
57135446Strhodes	list->mctx = NULL;
58135446Strhodes	isc_mem_attach(mctx, &list->mctx);
59135446Strhodes	list->refs = 1;
60135446Strhodes	ISC_LIST_INIT(list->names);
61135446Strhodes	list->magic = LWSEARCHLIST_MAGIC;
62135446Strhodes
63135446Strhodes	*listp = list;
64135446Strhodes	return (ISC_R_SUCCESS);
65135446Strhodes}
66135446Strhodes
67135446Strhodesvoid
68135446Strhodesns_lwsearchlist_attach(ns_lwsearchlist_t *source, ns_lwsearchlist_t **target) {
69135446Strhodes	REQUIRE(VALID_LWSEARCHLIST(source));
70135446Strhodes	REQUIRE(target != NULL && *target == NULL);
71135446Strhodes
72135446Strhodes	LOCK(&source->lock);
73135446Strhodes	INSIST(source->refs > 0);
74135446Strhodes	source->refs++;
75135446Strhodes	INSIST(source->refs != 0);
76135446Strhodes	UNLOCK(&source->lock);
77135446Strhodes
78135446Strhodes	*target = source;
79135446Strhodes}
80135446Strhodes
81135446Strhodesvoid
82135446Strhodesns_lwsearchlist_detach(ns_lwsearchlist_t **listp) {
83135446Strhodes	ns_lwsearchlist_t *list;
84135446Strhodes	isc_mem_t *mctx;
85135446Strhodes
86135446Strhodes	REQUIRE(listp != NULL);
87135446Strhodes	list = *listp;
88135446Strhodes	REQUIRE(VALID_LWSEARCHLIST(list));
89135446Strhodes
90135446Strhodes	LOCK(&list->lock);
91135446Strhodes	INSIST(list->refs > 0);
92135446Strhodes	list->refs--;
93135446Strhodes	UNLOCK(&list->lock);
94135446Strhodes
95135446Strhodes	*listp = NULL;
96135446Strhodes	if (list->refs != 0)
97135446Strhodes		return;
98135446Strhodes
99135446Strhodes	mctx = list->mctx;
100135446Strhodes	while (!ISC_LIST_EMPTY(list->names)) {
101135446Strhodes		dns_name_t *name = ISC_LIST_HEAD(list->names);
102135446Strhodes		ISC_LIST_UNLINK(list->names, name, link);
103135446Strhodes		dns_name_free(name, list->mctx);
104135446Strhodes		isc_mem_put(list->mctx, name, sizeof(dns_name_t));
105135446Strhodes	}
106135446Strhodes	list->magic = 0;
107135446Strhodes	isc_mem_put(mctx, list, sizeof(ns_lwsearchlist_t));
108135446Strhodes	isc_mem_detach(&mctx);
109135446Strhodes}
110135446Strhodes
111135446Strhodesisc_result_t
112135446Strhodesns_lwsearchlist_append(ns_lwsearchlist_t *list, dns_name_t *name) {
113135446Strhodes	dns_name_t *newname;
114135446Strhodes	isc_result_t result;
115135446Strhodes
116135446Strhodes	REQUIRE(VALID_LWSEARCHLIST(list));
117135446Strhodes	REQUIRE(name != NULL);
118135446Strhodes
119135446Strhodes	newname = isc_mem_get(list->mctx, sizeof(dns_name_t));
120135446Strhodes	if (newname == NULL)
121135446Strhodes		return (ISC_R_NOMEMORY);
122135446Strhodes	dns_name_init(newname, NULL);
123135446Strhodes	result = dns_name_dup(name, list->mctx, newname);
124135446Strhodes	if (result != ISC_R_SUCCESS) {
125135446Strhodes		isc_mem_put(list->mctx, newname, sizeof(dns_name_t));
126135446Strhodes		return (result);
127135446Strhodes	}
128135446Strhodes	ISC_LINK_INIT(newname, link);
129135446Strhodes	ISC_LIST_APPEND(list->names, newname, link);
130135446Strhodes	return (ISC_R_SUCCESS);
131135446Strhodes}
132135446Strhodes
133135446Strhodesvoid
134135446Strhodesns_lwsearchctx_init(ns_lwsearchctx_t *sctx, ns_lwsearchlist_t *list,
135135446Strhodes		    dns_name_t *name, unsigned int ndots)
136135446Strhodes{
137135446Strhodes	INSIST(sctx != NULL);
138135446Strhodes	sctx->relname = name;
139135446Strhodes	sctx->searchname = NULL;
140135446Strhodes	sctx->doneexact = ISC_FALSE;
141135446Strhodes	sctx->exactfirst = ISC_FALSE;
142135446Strhodes	sctx->ndots = ndots;
143135446Strhodes	if (dns_name_isabsolute(name) || list == NULL) {
144135446Strhodes		sctx->list = NULL;
145135446Strhodes		return;
146135446Strhodes	}
147135446Strhodes	sctx->list = list;
148135446Strhodes	sctx->searchname = ISC_LIST_HEAD(sctx->list->names);
149135446Strhodes	if (dns_name_countlabels(name) > ndots)
150135446Strhodes		sctx->exactfirst = ISC_TRUE;
151135446Strhodes}
152135446Strhodes
153135446Strhodesvoid
154135446Strhodesns_lwsearchctx_first(ns_lwsearchctx_t *sctx) {
155135446Strhodes	REQUIRE(sctx != NULL);
156135446Strhodes	UNUSED(sctx);
157135446Strhodes}
158135446Strhodes
159135446Strhodesisc_result_t
160135446Strhodesns_lwsearchctx_next(ns_lwsearchctx_t *sctx) {
161135446Strhodes	REQUIRE(sctx != NULL);
162135446Strhodes
163135446Strhodes	if (sctx->list == NULL)
164135446Strhodes		return (ISC_R_NOMORE);
165135446Strhodes
166135446Strhodes	if (sctx->searchname == NULL) {
167135446Strhodes		INSIST (!sctx->exactfirst || sctx->doneexact);
168135446Strhodes		if (sctx->exactfirst || sctx->doneexact)
169135446Strhodes			return (ISC_R_NOMORE);
170135446Strhodes		sctx->doneexact = ISC_TRUE;
171135446Strhodes	} else {
172135446Strhodes		if (sctx->exactfirst && !sctx->doneexact)
173135446Strhodes			sctx->doneexact = ISC_TRUE;
174135446Strhodes		else {
175135446Strhodes			sctx->searchname = ISC_LIST_NEXT(sctx->searchname,
176135446Strhodes							 link);
177135446Strhodes			if (sctx->searchname == NULL && sctx->doneexact)
178135446Strhodes				return (ISC_R_NOMORE);
179135446Strhodes		}
180135446Strhodes	}
181135446Strhodes
182135446Strhodes	return (ISC_R_SUCCESS);
183135446Strhodes}
184135446Strhodes
185135446Strhodesisc_result_t
186135446Strhodesns_lwsearchctx_current(ns_lwsearchctx_t *sctx, dns_name_t *absname) {
187135446Strhodes	dns_name_t *tname;
188135446Strhodes	isc_boolean_t useexact = ISC_FALSE;
189135446Strhodes
190135446Strhodes	REQUIRE(sctx != NULL);
191135446Strhodes
192135446Strhodes	if (sctx->list == NULL ||
193135446Strhodes	    sctx->searchname == NULL ||
194135446Strhodes	    (sctx->exactfirst && !sctx->doneexact))
195135446Strhodes		useexact = ISC_TRUE;
196135446Strhodes
197135446Strhodes	if (useexact) {
198135446Strhodes		if (dns_name_isabsolute(sctx->relname))
199135446Strhodes			tname = NULL;
200135446Strhodes		else
201135446Strhodes			tname = dns_rootname;
202135446Strhodes	} else
203135446Strhodes		tname = sctx->searchname;
204135446Strhodes
205135446Strhodes	return (dns_name_concatenate(sctx->relname, tname, absname, NULL));
206135446Strhodes}
207