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