/contrib/bind9/bin/named/sortlist.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 170 lines · 118 code · 20 blank · 32 comment · 34 complexity · 5cab73b3c16961ffdab1cc8ab21b900e MD5 · raw file

  1. /*
  2. * Copyright (C) 2004-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. /* $Id: sortlist.c,v 1.17 2007/09/14 01:46:05 marka Exp $ */
  18. /*! \file */
  19. #include <config.h>
  20. #include <isc/mem.h>
  21. #include <isc/util.h>
  22. #include <dns/acl.h>
  23. #include <dns/result.h>
  24. #include <named/globals.h>
  25. #include <named/server.h>
  26. #include <named/sortlist.h>
  27. ns_sortlisttype_t
  28. ns_sortlist_setup(dns_acl_t *acl, isc_netaddr_t *clientaddr,
  29. const void **argp)
  30. {
  31. unsigned int i;
  32. if (acl == NULL)
  33. goto dont_sort;
  34. for (i = 0; i < acl->length; i++) {
  35. /*
  36. * 'e' refers to the current 'top level statement'
  37. * in the sortlist (see ARM).
  38. */
  39. dns_aclelement_t *e = &acl->elements[i];
  40. dns_aclelement_t *try_elt;
  41. dns_aclelement_t *order_elt = NULL;
  42. const dns_aclelement_t *matched_elt = NULL;
  43. if (e->type == dns_aclelementtype_nestedacl) {
  44. dns_acl_t *inner = e->nestedacl;
  45. if (inner->length == 0)
  46. try_elt = e;
  47. else if (inner->length > 2)
  48. goto dont_sort;
  49. else if (inner->elements[0].negative)
  50. goto dont_sort;
  51. else {
  52. try_elt = &inner->elements[0];
  53. if (inner->length == 2)
  54. order_elt = &inner->elements[1];
  55. }
  56. } else {
  57. /*
  58. * BIND 8 allows bare elements at the top level
  59. * as an undocumented feature.
  60. */
  61. try_elt = e;
  62. }
  63. if (dns_aclelement_match(clientaddr, NULL, try_elt,
  64. &ns_g_server->aclenv,
  65. &matched_elt)) {
  66. if (order_elt != NULL) {
  67. if (order_elt->type ==
  68. dns_aclelementtype_nestedacl) {
  69. *argp = order_elt->nestedacl;
  70. return (NS_SORTLISTTYPE_2ELEMENT);
  71. } else if (order_elt->type ==
  72. dns_aclelementtype_localhost &&
  73. ns_g_server->aclenv.localhost != NULL) {
  74. *argp = ns_g_server->aclenv.localhost;
  75. return (NS_SORTLISTTYPE_2ELEMENT);
  76. } else if (order_elt->type ==
  77. dns_aclelementtype_localnets &&
  78. ns_g_server->aclenv.localnets != NULL) {
  79. *argp = ns_g_server->aclenv.localnets;
  80. return (NS_SORTLISTTYPE_2ELEMENT);
  81. } else {
  82. /*
  83. * BIND 8 allows a bare IP prefix as
  84. * the 2nd element of a 2-element
  85. * sortlist statement.
  86. */
  87. *argp = order_elt;
  88. return (NS_SORTLISTTYPE_1ELEMENT);
  89. }
  90. } else {
  91. INSIST(matched_elt != NULL);
  92. *argp = matched_elt;
  93. return (NS_SORTLISTTYPE_1ELEMENT);
  94. }
  95. }
  96. }
  97. /* No match; don't sort. */
  98. dont_sort:
  99. *argp = NULL;
  100. return (NS_SORTLISTTYPE_NONE);
  101. }
  102. int
  103. ns_sortlist_addrorder2(const isc_netaddr_t *addr, const void *arg) {
  104. const dns_acl_t *sortacl = (const dns_acl_t *) arg;
  105. int match;
  106. (void)dns_acl_match(addr, NULL, sortacl,
  107. &ns_g_server->aclenv,
  108. &match, NULL);
  109. if (match > 0)
  110. return (match);
  111. else if (match < 0)
  112. return (INT_MAX - (-match));
  113. else
  114. return (INT_MAX / 2);
  115. }
  116. int
  117. ns_sortlist_addrorder1(const isc_netaddr_t *addr, const void *arg) {
  118. const dns_aclelement_t *matchelt = (const dns_aclelement_t *) arg;
  119. if (dns_aclelement_match(addr, NULL, matchelt,
  120. &ns_g_server->aclenv,
  121. NULL)) {
  122. return (0);
  123. } else {
  124. return (INT_MAX);
  125. }
  126. }
  127. void
  128. ns_sortlist_byaddrsetup(dns_acl_t *sortlist_acl, isc_netaddr_t *client_addr,
  129. dns_addressorderfunc_t *orderp,
  130. const void **argp)
  131. {
  132. ns_sortlisttype_t sortlisttype;
  133. sortlisttype = ns_sortlist_setup(sortlist_acl, client_addr, argp);
  134. switch (sortlisttype) {
  135. case NS_SORTLISTTYPE_1ELEMENT:
  136. *orderp = ns_sortlist_addrorder1;
  137. break;
  138. case NS_SORTLISTTYPE_2ELEMENT:
  139. *orderp = ns_sortlist_addrorder2;
  140. break;
  141. case NS_SORTLISTTYPE_NONE:
  142. *orderp = NULL;
  143. break;
  144. default:
  145. UNEXPECTED_ERROR(__FILE__, __LINE__,
  146. "unexpected return from ns_sortlist_setup(): "
  147. "%d", sortlisttype);
  148. break;
  149. }
  150. }