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