| 1 | /* |
| 2 | * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") |
| 3 | * Copyright (C) 2002 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 | |
| 18 | /* $Id: order.c,v 1.10 2007/06/19 23:47:16 tbox Exp $ */ |
| 19 | |
| 20 | /*! \file */ |
| 21 | |
| 22 | #include <config.h> |
| 23 | |
| 24 | #include <isc/magic.h> |
| 25 | #include <isc/mem.h> |
| 26 | #include <isc/types.h> |
| 27 | #include <isc/util.h> |
| 28 | #include <isc/refcount.h> |
| 29 | |
| 30 | #include <dns/fixedname.h> |
| 31 | #include <dns/name.h> |
| 32 | #include <dns/order.h> |
| 33 | #include <dns/rdataset.h> |
| 34 | #include <dns/types.h> |
| 35 | |
| 36 | typedef struct dns_order_ent dns_order_ent_t; |
| 37 | struct dns_order_ent { |
| 38 | dns_fixedname_t name; |
| 39 | dns_rdataclass_t rdclass; |
| 40 | dns_rdatatype_t rdtype; |
| 41 | unsigned int mode; |
| 42 | ISC_LINK(dns_order_ent_t) link; |
| 43 | }; |
| 44 | |
| 45 | struct dns_order { |
| 46 | unsigned int magic; |
| 47 | isc_refcount_t references; |
| 48 | ISC_LIST(dns_order_ent_t) ents; |
| 49 | isc_mem_t *mctx; |
| 50 | }; |
| 51 | |
| 52 | #define DNS_ORDER_MAGIC ISC_MAGIC('O','r','d','r') |
| 53 | #define DNS_ORDER_VALID(order) ISC_MAGIC_VALID(order, DNS_ORDER_MAGIC) |
| 54 | |
| 55 | isc_result_t |
| 56 | dns_order_create(isc_mem_t *mctx, dns_order_t **orderp) { |
| 57 | dns_order_t *order; |
| 58 | isc_result_t result; |
| 59 | |
| 60 | REQUIRE(orderp != NULL && *orderp == NULL); |
| 61 | |
| 62 | order = isc_mem_get(mctx, sizeof(*order)); |
| 63 | if (order == NULL) |
| 64 | return (ISC_R_NOMEMORY); |
| 65 | |
| 66 | ISC_LIST_INIT(order->ents); |
| 67 | |
| 68 | /* Implicit attach. */ |
| 69 | result = isc_refcount_init(&order->references, 1); |
| 70 | if (result != ISC_R_SUCCESS) { |
| 71 | isc_mem_put(mctx, order, sizeof(*order)); |
| 72 | return (result); |
| 73 | } |
| 74 | |
| 75 | order->mctx = NULL; |
| 76 | isc_mem_attach(mctx, &order->mctx); |
| 77 | order->magic = DNS_ORDER_MAGIC; |
| 78 | *orderp = order; |
| 79 | return (ISC_R_SUCCESS); |
| 80 | } |
| 81 | |
| 82 | isc_result_t |
| 83 | dns_order_add(dns_order_t *order, dns_name_t *name, |
| 84 | dns_rdatatype_t rdtype, dns_rdataclass_t rdclass, |
| 85 | unsigned int mode) |
| 86 | { |
| 87 | dns_order_ent_t *ent; |
| 88 | |
| 89 | REQUIRE(DNS_ORDER_VALID(order)); |
| 90 | REQUIRE(mode == DNS_RDATASETATTR_RANDOMIZE || |
| 91 | mode == DNS_RDATASETATTR_FIXEDORDER || |
| 92 | mode == 0 /* DNS_RDATASETATTR_CYCLIC */ ); |
| 93 | |
| 94 | ent = isc_mem_get(order->mctx, sizeof(*ent)); |
| 95 | if (ent == NULL) |
| 96 | return (ISC_R_NOMEMORY); |
| 97 | |
| 98 | dns_fixedname_init(&ent->name); |
| 99 | RUNTIME_CHECK(dns_name_copy(name, dns_fixedname_name(&ent->name), NULL) |
| 100 | == ISC_R_SUCCESS); |
| 101 | ent->rdtype = rdtype; |
| 102 | ent->rdclass = rdclass; |
| 103 | ent->mode = mode; |
| 104 | ISC_LINK_INIT(ent, link); |
| 105 | ISC_LIST_INITANDAPPEND(order->ents, ent, link); |
| 106 | return (ISC_R_SUCCESS); |
| 107 | } |
| 108 | |
| 109 | static inline isc_boolean_t |
| 110 | match(dns_name_t *name1, dns_name_t *name2) { |
| 111 | |
| 112 | if (dns_name_iswildcard(name2)) |
| 113 | return(dns_name_matcheswildcard(name1, name2)); |
| 114 | return (dns_name_equal(name1, name2)); |
| 115 | } |
| 116 | |
| 117 | unsigned int |
| 118 | dns_order_find(dns_order_t *order, dns_name_t *name, |
| 119 | dns_rdatatype_t rdtype, dns_rdataclass_t rdclass) |
| 120 | { |
| 121 | dns_order_ent_t *ent; |
| 122 | REQUIRE(DNS_ORDER_VALID(order)); |
| 123 | |
| 124 | for (ent = ISC_LIST_HEAD(order->ents); |
| 125 | ent != NULL; |
| 126 | ent = ISC_LIST_NEXT(ent, link)) { |
| 127 | if (ent->rdtype != rdtype && ent->rdtype != dns_rdatatype_any) |
| 128 | continue; |
| 129 | if (ent->rdclass != rdclass && |
| 130 | ent->rdclass != dns_rdataclass_any) |
| 131 | continue; |
| 132 | if (match(name, dns_fixedname_name(&ent->name))) |
| 133 | return (ent->mode); |
| 134 | } |
| 135 | return (0); |
| 136 | } |
| 137 | |
| 138 | void |
| 139 | dns_order_attach(dns_order_t *source, dns_order_t **target) { |
| 140 | REQUIRE(DNS_ORDER_VALID(source)); |
| 141 | REQUIRE(target != NULL && *target == NULL); |
| 142 | isc_refcount_increment(&source->references, NULL); |
| 143 | *target = source; |
| 144 | } |
| 145 | |
| 146 | void |
| 147 | dns_order_detach(dns_order_t **orderp) { |
| 148 | dns_order_t *order; |
| 149 | dns_order_ent_t *ent; |
| 150 | unsigned int references; |
| 151 | |
| 152 | REQUIRE(orderp != NULL); |
| 153 | order = *orderp; |
| 154 | REQUIRE(DNS_ORDER_VALID(order)); |
| 155 | isc_refcount_decrement(&order->references, &references); |
| 156 | *orderp = NULL; |
| 157 | if (references != 0) |
| 158 | return; |
| 159 | |
| 160 | order->magic = 0; |
| 161 | while ((ent = ISC_LIST_HEAD(order->ents)) != NULL) { |
| 162 | ISC_LIST_UNLINK(order->ents, ent, link); |
| 163 | isc_mem_put(order->mctx, ent, sizeof(*ent)); |
| 164 | } |
| 165 | isc_refcount_destroy(&order->references); |
| 166 | isc_mem_putanddetach(&order->mctx, order, sizeof(*order)); |
| 167 | } |