sortlist.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2007  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: sortlist.c,v 1.17 2007/09/14 01:46:05 marka Exp $ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <isc/mem.h>
00025 #include <isc/util.h>
00026 
00027 #include <dns/acl.h>
00028 #include <dns/result.h>
00029 
00030 #include <named/globals.h>
00031 #include <named/server.h>
00032 #include <named/sortlist.h>
00033 
00034 ns_sortlisttype_t
00035 ns_sortlist_setup(dns_acl_t *acl, isc_netaddr_t *clientaddr,
00036                   const void **argp)
00037 {
00038         unsigned int i;
00039 
00040         if (acl == NULL)
00041                 goto dont_sort;
00042 
00043         for (i = 0; i < acl->length; i++) {
00044                 /*
00045                  * 'e' refers to the current 'top level statement'
00046                  * in the sortlist (see ARM).
00047                  */
00048                 dns_aclelement_t *e = &acl->elements[i];
00049                 dns_aclelement_t *try_elt;
00050                 dns_aclelement_t *order_elt = NULL;
00051                 const dns_aclelement_t *matched_elt = NULL;
00052 
00053                 if (e->type == dns_aclelementtype_nestedacl) {
00054                         dns_acl_t *inner = e->nestedacl;
00055 
00056                         if (inner->length == 0)
00057                                 try_elt = e;
00058                         else if (inner->length > 2)
00059                                 goto dont_sort;
00060                         else if (inner->elements[0].negative)
00061                                 goto dont_sort;
00062                         else {
00063                                 try_elt = &inner->elements[0];
00064                                 if (inner->length == 2)
00065                                         order_elt = &inner->elements[1];
00066                         }
00067                 } else {
00068                         /*
00069                          * BIND 8 allows bare elements at the top level
00070                          * as an undocumented feature.
00071                          */
00072                         try_elt = e;
00073                 }
00074 
00075                 if (dns_aclelement_match(clientaddr, NULL, try_elt,
00076                                          &ns_g_server->aclenv,
00077                                          &matched_elt)) {
00078                         if (order_elt != NULL) {
00079                                 if (order_elt->type ==
00080                                     dns_aclelementtype_nestedacl) {
00081                                         *argp = order_elt->nestedacl;
00082                                         return (NS_SORTLISTTYPE_2ELEMENT);
00083                                 } else if (order_elt->type ==
00084                                            dns_aclelementtype_localhost &&
00085                                            ns_g_server->aclenv.localhost != NULL) {
00086                                         *argp = ns_g_server->aclenv.localhost;
00087                                         return (NS_SORTLISTTYPE_2ELEMENT);
00088                                 } else if (order_elt->type ==
00089                                            dns_aclelementtype_localnets &&
00090                                            ns_g_server->aclenv.localnets != NULL) {
00091                                         *argp = ns_g_server->aclenv.localnets;
00092                                         return (NS_SORTLISTTYPE_2ELEMENT);
00093                                 } else {
00094                                         /*
00095                                          * BIND 8 allows a bare IP prefix as
00096                                          * the 2nd element of a 2-element
00097                                          * sortlist statement.
00098                                          */
00099                                         *argp = order_elt;
00100                                         return (NS_SORTLISTTYPE_1ELEMENT);
00101                                 }
00102                         } else {
00103                                 INSIST(matched_elt != NULL);
00104                                 *argp = matched_elt;
00105                                 return (NS_SORTLISTTYPE_1ELEMENT);
00106                         }
00107                 }
00108         }
00109 
00110         /* No match; don't sort. */
00111  dont_sort:
00112         *argp = NULL;
00113         return (NS_SORTLISTTYPE_NONE);
00114 }
00115 
00116 int
00117 ns_sortlist_addrorder2(const isc_netaddr_t *addr, const void *arg) {
00118         const dns_acl_t *sortacl = (const dns_acl_t *) arg;
00119         int match;
00120 
00121         (void)dns_acl_match(addr, NULL, sortacl,
00122                             &ns_g_server->aclenv,
00123                             &match, NULL);
00124         if (match > 0)
00125                 return (match);
00126         else if (match < 0)
00127                 return (INT_MAX - (-match));
00128         else
00129                 return (INT_MAX / 2);
00130 }
00131 
00132 int
00133 ns_sortlist_addrorder1(const isc_netaddr_t *addr, const void *arg) {
00134         const dns_aclelement_t *matchelt = (const dns_aclelement_t *) arg;
00135         if (dns_aclelement_match(addr, NULL, matchelt,
00136                                  &ns_g_server->aclenv,
00137                                  NULL)) {
00138                 return (0);
00139         } else {
00140                 return (INT_MAX);
00141         }
00142 }
00143 
00144 void
00145 ns_sortlist_byaddrsetup(dns_acl_t *sortlist_acl, isc_netaddr_t *client_addr,
00146                        dns_addressorderfunc_t *orderp,
00147                        const void **argp)
00148 {
00149         ns_sortlisttype_t sortlisttype;
00150 
00151         sortlisttype = ns_sortlist_setup(sortlist_acl, client_addr, argp);
00152 
00153         switch (sortlisttype) {
00154         case NS_SORTLISTTYPE_1ELEMENT:
00155                 *orderp = ns_sortlist_addrorder1;
00156                 break;
00157         case NS_SORTLISTTYPE_2ELEMENT:
00158                 *orderp = ns_sortlist_addrorder2;
00159                 break;
00160         case NS_SORTLISTTYPE_NONE:
00161                 *orderp = NULL;
00162                 break;
00163         default:
00164                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00165                                  "unexpected return from ns_sortlist_setup(): "
00166                                  "%d", sortlisttype);
00167                 break;
00168         }
00169 }
00170 

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