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