PageRenderTime 31ms CodeModel.GetById 20ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/bind9/lib/dns/forward.c

https://bitbucket.org/freebsd/freebsd-head/
C | 215 lines | 145 code | 47 blank | 23 comment | 25 complexity | 4edac8bff093d00be8341c4f44766f8c MD5 | raw file
  1/*
  2 * Copyright (C) 2004, 2005, 2007, 2009  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: forward.c,v 1.14 2009/09/02 23:48:02 tbox Exp $ */
 19
 20/*! \file */
 21
 22#include <config.h>
 23
 24#include <isc/magic.h>
 25#include <isc/mem.h>
 26#include <isc/rwlock.h>
 27#include <isc/sockaddr.h>
 28#include <isc/util.h>
 29
 30#include <dns/forward.h>
 31#include <dns/rbt.h>
 32#include <dns/result.h>
 33#include <dns/types.h>
 34
 35struct dns_fwdtable {
 36	/* Unlocked. */
 37	unsigned int		magic;
 38	isc_mem_t		*mctx;
 39	isc_rwlock_t		rwlock;
 40	/* Locked by lock. */
 41	dns_rbt_t		*table;
 42};
 43
 44#define FWDTABLEMAGIC		ISC_MAGIC('F', 'w', 'd', 'T')
 45#define VALID_FWDTABLE(ft) 	ISC_MAGIC_VALID(ft, FWDTABLEMAGIC)
 46
 47static void
 48auto_detach(void *, void *);
 49
 50isc_result_t
 51dns_fwdtable_create(isc_mem_t *mctx, dns_fwdtable_t **fwdtablep) {
 52	dns_fwdtable_t *fwdtable;
 53	isc_result_t result;
 54
 55	REQUIRE(fwdtablep != NULL && *fwdtablep == NULL);
 56
 57	fwdtable = isc_mem_get(mctx, sizeof(dns_fwdtable_t));
 58	if (fwdtable == NULL)
 59		return (ISC_R_NOMEMORY);
 60
 61	fwdtable->table = NULL;
 62	result = dns_rbt_create(mctx, auto_detach, fwdtable, &fwdtable->table);
 63	if (result != ISC_R_SUCCESS)
 64		goto cleanup_fwdtable;
 65
 66	result = isc_rwlock_init(&fwdtable->rwlock, 0, 0);
 67	if (result != ISC_R_SUCCESS)
 68		goto cleanup_rbt;
 69
 70	fwdtable->mctx = NULL;
 71	isc_mem_attach(mctx, &fwdtable->mctx);
 72	fwdtable->magic = FWDTABLEMAGIC;
 73	*fwdtablep = fwdtable;
 74
 75	return (ISC_R_SUCCESS);
 76
 77   cleanup_rbt:
 78	dns_rbt_destroy(&fwdtable->table);
 79
 80   cleanup_fwdtable:
 81	isc_mem_put(mctx, fwdtable, sizeof(dns_fwdtable_t));
 82
 83	return (result);
 84}
 85
 86isc_result_t
 87dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name,
 88		 isc_sockaddrlist_t *addrs, dns_fwdpolicy_t fwdpolicy)
 89{
 90	isc_result_t result;
 91	dns_forwarders_t *forwarders;
 92	isc_sockaddr_t *sa, *nsa;
 93
 94	REQUIRE(VALID_FWDTABLE(fwdtable));
 95
 96	forwarders = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarders_t));
 97	if (forwarders == NULL)
 98		return (ISC_R_NOMEMORY);
 99
100	ISC_LIST_INIT(forwarders->addrs);
101	for (sa = ISC_LIST_HEAD(*addrs);
102	     sa != NULL;
103	     sa = ISC_LIST_NEXT(sa, link))
104	{
105		nsa = isc_mem_get(fwdtable->mctx, sizeof(isc_sockaddr_t));
106		if (nsa == NULL) {
107			result = ISC_R_NOMEMORY;
108			goto cleanup;
109		}
110		*nsa = *sa;
111		ISC_LINK_INIT(nsa, link);
112		ISC_LIST_APPEND(forwarders->addrs, nsa, link);
113	}
114	forwarders->fwdpolicy = fwdpolicy;
115
116	RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
117	result = dns_rbt_addname(fwdtable->table, name, forwarders);
118	RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
119
120	if (result != ISC_R_SUCCESS)
121		goto cleanup;
122
123	return (ISC_R_SUCCESS);
124
125 cleanup:
126	while (!ISC_LIST_EMPTY(forwarders->addrs)) {
127		sa = ISC_LIST_HEAD(forwarders->addrs);
128		ISC_LIST_UNLINK(forwarders->addrs, sa, link);
129		isc_mem_put(fwdtable->mctx, sa, sizeof(isc_sockaddr_t));
130	}
131	isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
132	return (result);
133}
134
135isc_result_t
136dns_fwdtable_delete(dns_fwdtable_t *fwdtable, dns_name_t *name) {
137	isc_result_t result;
138
139	REQUIRE(VALID_FWDTABLE(fwdtable));
140
141	RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
142	result = dns_rbt_deletename(fwdtable->table, name, ISC_FALSE);
143	RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
144
145	if (result == DNS_R_PARTIALMATCH)
146		result = ISC_R_NOTFOUND;
147
148	return (result);
149}
150
151isc_result_t
152dns_fwdtable_find(dns_fwdtable_t *fwdtable, dns_name_t *name,
153		  dns_forwarders_t **forwardersp)
154{
155	return (dns_fwdtable_find2(fwdtable, name, NULL, forwardersp));
156}
157
158isc_result_t
159dns_fwdtable_find2(dns_fwdtable_t *fwdtable, dns_name_t *name,
160		   dns_name_t *foundname, dns_forwarders_t **forwardersp)
161{
162	isc_result_t result;
163
164	REQUIRE(VALID_FWDTABLE(fwdtable));
165
166	RWLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
167
168	result = dns_rbt_findname(fwdtable->table, name, 0, foundname,
169				  (void **)forwardersp);
170	if (result == DNS_R_PARTIALMATCH)
171		result = ISC_R_SUCCESS;
172
173	RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
174
175	return (result);
176}
177
178void
179dns_fwdtable_destroy(dns_fwdtable_t **fwdtablep) {
180	dns_fwdtable_t *fwdtable;
181	isc_mem_t *mctx;
182
183	REQUIRE(fwdtablep != NULL && VALID_FWDTABLE(*fwdtablep));
184
185	fwdtable = *fwdtablep;
186
187	dns_rbt_destroy(&fwdtable->table);
188	isc_rwlock_destroy(&fwdtable->rwlock);
189	fwdtable->magic = 0;
190	mctx = fwdtable->mctx;
191	isc_mem_put(mctx, fwdtable, sizeof(dns_fwdtable_t));
192	isc_mem_detach(&mctx);
193
194	*fwdtablep = NULL;
195}
196
197/***
198 *** Private
199 ***/
200
201static void
202auto_detach(void *data, void *arg) {
203	dns_forwarders_t *forwarders = data;
204	dns_fwdtable_t *fwdtable = arg;
205	isc_sockaddr_t *sa;
206
207	UNUSED(arg);
208
209	while (!ISC_LIST_EMPTY(forwarders->addrs)) {
210		sa = ISC_LIST_HEAD(forwarders->addrs);
211		ISC_LIST_UNLINK(forwarders->addrs, sa, link);
212		isc_mem_put(fwdtable->mctx, sa, sizeof(isc_sockaddr_t));
213	}
214	isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
215}