2 * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001 Internet Software Consortium.
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.
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.
18 /* $Id: sortlist.c,v 1.17 2007/09/14 01:46:05 marka Exp $ */
28 #include <dns/result.h>
30 #include <named/globals.h>
31 #include <named/server.h>
32 #include <named/sortlist.h>
35 ns_sortlist_setup(dns_acl_t
*acl
, isc_netaddr_t
*clientaddr
,
43 for (i
= 0; i
< acl
->length
; i
++) {
45 * 'e' refers to the current 'top level statement'
46 * in the sortlist (see ARM).
48 dns_aclelement_t
*e
= &acl
->elements
[i
];
49 dns_aclelement_t
*try_elt
;
50 dns_aclelement_t
*order_elt
= NULL
;
51 const dns_aclelement_t
*matched_elt
= NULL
;
53 if (e
->type
== dns_aclelementtype_nestedacl
) {
54 dns_acl_t
*inner
= e
->nestedacl
;
56 if (inner
->length
== 0)
58 else if (inner
->length
> 2)
60 else if (inner
->elements
[0].negative
)
63 try_elt
= &inner
->elements
[0];
64 if (inner
->length
== 2)
65 order_elt
= &inner
->elements
[1];
69 * BIND 8 allows bare elements at the top level
70 * as an undocumented feature.
75 if (dns_aclelement_match(clientaddr
, NULL
, try_elt
,
78 if (order_elt
!= NULL
) {
79 if (order_elt
->type
==
80 dns_aclelementtype_nestedacl
) {
81 *argp
= order_elt
->nestedacl
;
82 return (NS_SORTLISTTYPE_2ELEMENT
);
83 } else if (order_elt
->type
==
84 dns_aclelementtype_localhost
&&
85 ns_g_server
->aclenv
.localhost
!= NULL
) {
86 *argp
= ns_g_server
->aclenv
.localhost
;
87 return (NS_SORTLISTTYPE_2ELEMENT
);
88 } else if (order_elt
->type
==
89 dns_aclelementtype_localnets
&&
90 ns_g_server
->aclenv
.localnets
!= NULL
) {
91 *argp
= ns_g_server
->aclenv
.localnets
;
92 return (NS_SORTLISTTYPE_2ELEMENT
);
95 * BIND 8 allows a bare IP prefix as
96 * the 2nd element of a 2-element
100 return (NS_SORTLISTTYPE_1ELEMENT
);
103 INSIST(matched_elt
!= NULL
);
105 return (NS_SORTLISTTYPE_1ELEMENT
);
110 /* No match; don't sort. */
113 return (NS_SORTLISTTYPE_NONE
);
117 ns_sortlist_addrorder2(const isc_netaddr_t
*addr
, const void *arg
) {
118 const dns_acl_t
*sortacl
= (const dns_acl_t
*) arg
;
121 (void)dns_acl_match(addr
, NULL
, sortacl
,
122 &ns_g_server
->aclenv
,
127 return (INT_MAX
- (-match
));
129 return (INT_MAX
/ 2);
133 ns_sortlist_addrorder1(const isc_netaddr_t
*addr
, const void *arg
) {
134 const dns_aclelement_t
*matchelt
= (const dns_aclelement_t
*) arg
;
135 if (dns_aclelement_match(addr
, NULL
, matchelt
,
136 &ns_g_server
->aclenv
,
145 ns_sortlist_byaddrsetup(dns_acl_t
*sortlist_acl
, isc_netaddr_t
*client_addr
,
146 dns_addressorderfunc_t
*orderp
,
149 ns_sortlisttype_t sortlisttype
;
151 sortlisttype
= ns_sortlist_setup(sortlist_acl
, client_addr
, argp
);
153 switch (sortlisttype
) {
154 case NS_SORTLISTTYPE_1ELEMENT
:
155 *orderp
= ns_sortlist_addrorder1
;
157 case NS_SORTLISTTYPE_2ELEMENT
:
158 *orderp
= ns_sortlist_addrorder2
;
160 case NS_SORTLISTTYPE_NONE
:
164 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
165 "unexpected return from ns_sortlist_setup(): "