1/* 2 * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2000, 2001 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: lwsearch.c,v 1.13 2007/06/19 23:46:59 tbox Exp $ */ 19 20/*! \file */ 21 22#include <config.h> 23 24#include <isc/magic.h> 25#include <isc/mem.h> 26#include <isc/mutex.h> 27#include <isc/result.h> 28#include <isc/types.h> 29#include <isc/util.h> 30 31#include <dns/name.h> 32#include <dns/types.h> 33 34#include <named/lwsearch.h> 35#include <named/types.h> 36 37#define LWSEARCHLIST_MAGIC ISC_MAGIC('L', 'W', 'S', 'L') 38#define VALID_LWSEARCHLIST(l) ISC_MAGIC_VALID(l, LWSEARCHLIST_MAGIC) 39 40isc_result_t 41ns_lwsearchlist_create(isc_mem_t *mctx, ns_lwsearchlist_t **listp) { 42 ns_lwsearchlist_t *list; 43 isc_result_t result; 44 45 REQUIRE(mctx != NULL); 46 REQUIRE(listp != NULL && *listp == NULL); 47 48 list = isc_mem_get(mctx, sizeof(ns_lwsearchlist_t)); 49 if (list == NULL) 50 return (ISC_R_NOMEMORY); 51 52 result = isc_mutex_init(&list->lock); 53 if (result != ISC_R_SUCCESS) { 54 isc_mem_put(mctx, list, sizeof(ns_lwsearchlist_t)); 55 return (result); 56 } 57 list->mctx = NULL; 58 isc_mem_attach(mctx, &list->mctx); 59 list->refs = 1; 60 ISC_LIST_INIT(list->names); 61 list->magic = LWSEARCHLIST_MAGIC; 62 63 *listp = list; 64 return (ISC_R_SUCCESS); 65} 66 67void 68ns_lwsearchlist_attach(ns_lwsearchlist_t *source, ns_lwsearchlist_t **target) { 69 REQUIRE(VALID_LWSEARCHLIST(source)); 70 REQUIRE(target != NULL && *target == NULL); 71 72 LOCK(&source->lock); 73 INSIST(source->refs > 0); 74 source->refs++; 75 INSIST(source->refs != 0); 76 UNLOCK(&source->lock); 77 78 *target = source; 79} 80 81void 82ns_lwsearchlist_detach(ns_lwsearchlist_t **listp) { 83 ns_lwsearchlist_t *list; 84 isc_mem_t *mctx; 85 86 REQUIRE(listp != NULL); 87 list = *listp; 88 REQUIRE(VALID_LWSEARCHLIST(list)); 89 90 LOCK(&list->lock); 91 INSIST(list->refs > 0); 92 list->refs--; 93 UNLOCK(&list->lock); 94 95 *listp = NULL; 96 if (list->refs != 0) 97 return; 98 99 mctx = list->mctx; 100 while (!ISC_LIST_EMPTY(list->names)) { 101 dns_name_t *name = ISC_LIST_HEAD(list->names); 102 ISC_LIST_UNLINK(list->names, name, link); 103 dns_name_free(name, list->mctx); 104 isc_mem_put(list->mctx, name, sizeof(dns_name_t)); 105 } 106 list->magic = 0; 107 isc_mem_put(mctx, list, sizeof(ns_lwsearchlist_t)); 108 isc_mem_detach(&mctx); 109} 110 111isc_result_t 112ns_lwsearchlist_append(ns_lwsearchlist_t *list, dns_name_t *name) { 113 dns_name_t *newname; 114 isc_result_t result; 115 116 REQUIRE(VALID_LWSEARCHLIST(list)); 117 REQUIRE(name != NULL); 118 119 newname = isc_mem_get(list->mctx, sizeof(dns_name_t)); 120 if (newname == NULL) 121 return (ISC_R_NOMEMORY); 122 dns_name_init(newname, NULL); 123 result = dns_name_dup(name, list->mctx, newname); 124 if (result != ISC_R_SUCCESS) { 125 isc_mem_put(list->mctx, newname, sizeof(dns_name_t)); 126 return (result); 127 } 128 ISC_LINK_INIT(newname, link); 129 ISC_LIST_APPEND(list->names, newname, link); 130 return (ISC_R_SUCCESS); 131} 132 133void 134ns_lwsearchctx_init(ns_lwsearchctx_t *sctx, ns_lwsearchlist_t *list, 135 dns_name_t *name, unsigned int ndots) 136{ 137 INSIST(sctx != NULL); 138 sctx->relname = name; 139 sctx->searchname = NULL; 140 sctx->doneexact = ISC_FALSE; 141 sctx->exactfirst = ISC_FALSE; 142 sctx->ndots = ndots; 143 if (dns_name_isabsolute(name) || list == NULL) { 144 sctx->list = NULL; 145 return; 146 } 147 sctx->list = list; 148 sctx->searchname = ISC_LIST_HEAD(sctx->list->names); 149 if (dns_name_countlabels(name) > ndots) 150 sctx->exactfirst = ISC_TRUE; 151} 152 153void 154ns_lwsearchctx_first(ns_lwsearchctx_t *sctx) { 155 REQUIRE(sctx != NULL); 156 UNUSED(sctx); 157} 158 159isc_result_t 160ns_lwsearchctx_next(ns_lwsearchctx_t *sctx) { 161 REQUIRE(sctx != NULL); 162 163 if (sctx->list == NULL) 164 return (ISC_R_NOMORE); 165 166 if (sctx->searchname == NULL) { 167 INSIST (!sctx->exactfirst || sctx->doneexact); 168 if (sctx->exactfirst || sctx->doneexact) 169 return (ISC_R_NOMORE); 170 sctx->doneexact = ISC_TRUE; 171 } else { 172 if (sctx->exactfirst && !sctx->doneexact) 173 sctx->doneexact = ISC_TRUE; 174 else { 175 sctx->searchname = ISC_LIST_NEXT(sctx->searchname, 176 link); 177 if (sctx->searchname == NULL && sctx->doneexact) 178 return (ISC_R_NOMORE); 179 } 180 } 181 182 return (ISC_R_SUCCESS); 183} 184 185isc_result_t 186ns_lwsearchctx_current(ns_lwsearchctx_t *sctx, dns_name_t *absname) { 187 dns_name_t *tname; 188 isc_boolean_t useexact = ISC_FALSE; 189 190 REQUIRE(sctx != NULL); 191 192 if (sctx->list == NULL || 193 sctx->searchname == NULL || 194 (sctx->exactfirst && !sctx->doneexact)) 195 useexact = ISC_TRUE; 196 197 if (useexact) { 198 if (dns_name_isabsolute(sctx->relname)) 199 tname = NULL; 200 else 201 tname = dns_rootname; 202 } else 203 tname = sctx->searchname; 204 205 return (dns_name_concatenate(sctx->relname, tname, absname, NULL)); 206} 207