forward.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 2005, 2007, 2009, 2013  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000, 2001  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id: forward.c,v 1.14 2009/09/02 23:48:02 tbox Exp $ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <isc/magic.h>
00025 #include <isc/mem.h>
00026 #include <isc/rwlock.h>
00027 #include <isc/sockaddr.h>
00028 #include <isc/util.h>
00029 
00030 #include <dns/forward.h>
00031 #include <dns/rbt.h>
00032 #include <dns/result.h>
00033 #include <dns/types.h>
00034 
00035 struct dns_fwdtable {
00036         /* Unlocked. */
00037         unsigned int            magic;
00038         isc_mem_t               *mctx;
00039         isc_rwlock_t            rwlock;
00040         /* Locked by lock. */
00041         dns_rbt_t               *table;
00042 };
00043 
00044 #define FWDTABLEMAGIC           ISC_MAGIC('F', 'w', 'd', 'T')
00045 #define VALID_FWDTABLE(ft)      ISC_MAGIC_VALID(ft, FWDTABLEMAGIC)
00046 
00047 static void
00048 auto_detach(void *, void *);
00049 
00050 isc_result_t
00051 dns_fwdtable_create(isc_mem_t *mctx, dns_fwdtable_t **fwdtablep) {
00052         dns_fwdtable_t *fwdtable;
00053         isc_result_t result;
00054 
00055         REQUIRE(fwdtablep != NULL && *fwdtablep == NULL);
00056 
00057         fwdtable = isc_mem_get(mctx, sizeof(dns_fwdtable_t));
00058         if (fwdtable == NULL)
00059                 return (ISC_R_NOMEMORY);
00060 
00061         fwdtable->table = NULL;
00062         result = dns_rbt_create(mctx, auto_detach, fwdtable, &fwdtable->table);
00063         if (result != ISC_R_SUCCESS)
00064                 goto cleanup_fwdtable;
00065 
00066         result = isc_rwlock_init(&fwdtable->rwlock, 0, 0);
00067         if (result != ISC_R_SUCCESS)
00068                 goto cleanup_rbt;
00069 
00070         fwdtable->mctx = NULL;
00071         isc_mem_attach(mctx, &fwdtable->mctx);
00072         fwdtable->magic = FWDTABLEMAGIC;
00073         *fwdtablep = fwdtable;
00074 
00075         return (ISC_R_SUCCESS);
00076 
00077    cleanup_rbt:
00078         dns_rbt_destroy(&fwdtable->table);
00079 
00080    cleanup_fwdtable:
00081         isc_mem_put(mctx, fwdtable, sizeof(dns_fwdtable_t));
00082 
00083         return (result);
00084 }
00085 
00086 isc_result_t
00087 dns_fwdtable_addfwd(dns_fwdtable_t *fwdtable, dns_name_t *name,
00088                     dns_forwarderlist_t *fwdrs, dns_fwdpolicy_t fwdpolicy)
00089 {
00090         isc_result_t result;
00091         dns_forwarders_t *forwarders;
00092         dns_forwarder_t *fwd, *nfwd;
00093 
00094         REQUIRE(VALID_FWDTABLE(fwdtable));
00095 
00096         forwarders = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarders_t));
00097         if (forwarders == NULL)
00098                 return (ISC_R_NOMEMORY);
00099 
00100         ISC_LIST_INIT(forwarders->fwdrs);
00101         for (fwd = ISC_LIST_HEAD(*fwdrs);
00102              fwd != NULL;
00103              fwd = ISC_LIST_NEXT(fwd, link))
00104         {
00105                 nfwd = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarder_t));
00106                 if (nfwd == NULL) {
00107                         result = ISC_R_NOMEMORY;
00108                         goto cleanup;
00109                 }
00110                 *nfwd = *fwd;
00111                 ISC_LINK_INIT(nfwd, link);
00112                 ISC_LIST_APPEND(forwarders->fwdrs, nfwd, link);
00113         }
00114         forwarders->fwdpolicy = fwdpolicy;
00115 
00116         RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
00117         result = dns_rbt_addname(fwdtable->table, name, forwarders);
00118         RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
00119 
00120         if (result != ISC_R_SUCCESS)
00121                 goto cleanup;
00122 
00123         return (ISC_R_SUCCESS);
00124 
00125  cleanup:
00126         while (!ISC_LIST_EMPTY(forwarders->fwdrs)) {
00127                 fwd = ISC_LIST_HEAD(forwarders->fwdrs);
00128                 ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link);
00129                 isc_mem_put(fwdtable->mctx, fwd, sizeof(isc_sockaddr_t));
00130         }
00131         isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
00132         return (result);
00133 }
00134 
00135 isc_result_t
00136 dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name,
00137                  isc_sockaddrlist_t *addrs, dns_fwdpolicy_t fwdpolicy)
00138 {
00139         isc_result_t result;
00140         dns_forwarders_t *forwarders;
00141         dns_forwarder_t *fwd;
00142         isc_sockaddr_t *sa;
00143 
00144         REQUIRE(VALID_FWDTABLE(fwdtable));
00145 
00146         forwarders = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarders_t));
00147         if (forwarders == NULL)
00148                 return (ISC_R_NOMEMORY);
00149 
00150         ISC_LIST_INIT(forwarders->fwdrs);
00151         for (sa = ISC_LIST_HEAD(*addrs);
00152              sa != NULL;
00153              sa = ISC_LIST_NEXT(sa, link))
00154         {
00155                 fwd = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarder_t));
00156                 if (fwd == NULL) {
00157                         result = ISC_R_NOMEMORY;
00158                         goto cleanup;
00159                 }
00160                 fwd->addr = *sa;
00161                 fwd->dscp = -1;
00162                 ISC_LINK_INIT(fwd, link);
00163                 ISC_LIST_APPEND(forwarders->fwdrs, fwd, link);
00164         }
00165         forwarders->fwdpolicy = fwdpolicy;
00166 
00167         RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
00168         result = dns_rbt_addname(fwdtable->table, name, forwarders);
00169         RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
00170 
00171         if (result != ISC_R_SUCCESS)
00172                 goto cleanup;
00173 
00174         return (ISC_R_SUCCESS);
00175 
00176  cleanup:
00177         while (!ISC_LIST_EMPTY(forwarders->fwdrs)) {
00178                 fwd = ISC_LIST_HEAD(forwarders->fwdrs);
00179                 ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link);
00180                 isc_mem_put(fwdtable->mctx, fwd, sizeof(dns_forwarder_t));
00181         }
00182         isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
00183         return (result);
00184 }
00185 
00186 isc_result_t
00187 dns_fwdtable_delete(dns_fwdtable_t *fwdtable, dns_name_t *name) {
00188         isc_result_t result;
00189 
00190         REQUIRE(VALID_FWDTABLE(fwdtable));
00191 
00192         RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
00193         result = dns_rbt_deletename(fwdtable->table, name, ISC_FALSE);
00194         RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
00195 
00196         if (result == DNS_R_PARTIALMATCH)
00197                 result = ISC_R_NOTFOUND;
00198 
00199         return (result);
00200 }
00201 
00202 isc_result_t
00203 dns_fwdtable_find(dns_fwdtable_t *fwdtable, dns_name_t *name,
00204                   dns_forwarders_t **forwardersp)
00205 {
00206         return (dns_fwdtable_find2(fwdtable, name, NULL, forwardersp));
00207 }
00208 
00209 isc_result_t
00210 dns_fwdtable_find2(dns_fwdtable_t *fwdtable, dns_name_t *name,
00211                    dns_name_t *foundname, dns_forwarders_t **forwardersp)
00212 {
00213         isc_result_t result;
00214 
00215         REQUIRE(VALID_FWDTABLE(fwdtable));
00216 
00217         RWLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
00218 
00219         result = dns_rbt_findname(fwdtable->table, name, 0, foundname,
00220                                   (void **)forwardersp);
00221         if (result == DNS_R_PARTIALMATCH)
00222                 result = ISC_R_SUCCESS;
00223 
00224         RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
00225 
00226         return (result);
00227 }
00228 
00229 void
00230 dns_fwdtable_destroy(dns_fwdtable_t **fwdtablep) {
00231         dns_fwdtable_t *fwdtable;
00232         isc_mem_t *mctx;
00233 
00234         REQUIRE(fwdtablep != NULL && VALID_FWDTABLE(*fwdtablep));
00235 
00236         fwdtable = *fwdtablep;
00237 
00238         dns_rbt_destroy(&fwdtable->table);
00239         isc_rwlock_destroy(&fwdtable->rwlock);
00240         fwdtable->magic = 0;
00241         mctx = fwdtable->mctx;
00242         isc_mem_put(mctx, fwdtable, sizeof(dns_fwdtable_t));
00243         isc_mem_detach(&mctx);
00244 
00245         *fwdtablep = NULL;
00246 }
00247 
00248 /***
00249  *** Private
00250  ***/
00251 
00252 static void
00253 auto_detach(void *data, void *arg) {
00254         dns_forwarders_t *forwarders = data;
00255         dns_fwdtable_t *fwdtable = arg;
00256         dns_forwarder_t *fwd;
00257 
00258         UNUSED(arg);
00259 
00260         while (!ISC_LIST_EMPTY(forwarders->fwdrs)) {
00261                 fwd = ISC_LIST_HEAD(forwarders->fwdrs);
00262                 ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link);
00263                 isc_mem_put(fwdtable->mctx, fwd, sizeof(dns_forwarder_t));
00264         }
00265         isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
00266 }

Generated on Tue Apr 28 17:40:56 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha