1 /* $NetBSD: order.c,v 1.5 2020/05/24 19:46:23 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * See the COPYRIGHT file distributed with this work for additional 11 * information regarding copyright ownership. 12 */ 13 14 /*! \file */ 15 16 #include <stdbool.h> 17 18 #include <isc/magic.h> 19 #include <isc/mem.h> 20 #include <isc/refcount.h> 21 #include <isc/types.h> 22 #include <isc/util.h> 23 24 #include <dns/fixedname.h> 25 #include <dns/name.h> 26 #include <dns/order.h> 27 #include <dns/rdataset.h> 28 #include <dns/types.h> 29 30 typedef struct dns_order_ent dns_order_ent_t; 31 struct dns_order_ent { 32 dns_fixedname_t name; 33 dns_rdataclass_t rdclass; 34 dns_rdatatype_t rdtype; 35 unsigned int mode; 36 ISC_LINK(dns_order_ent_t) link; 37 }; 38 39 struct dns_order { 40 unsigned int magic; 41 isc_refcount_t references; 42 ISC_LIST(dns_order_ent_t) ents; 43 isc_mem_t *mctx; 44 }; 45 46 #define DNS_ORDER_MAGIC ISC_MAGIC('O', 'r', 'd', 'r') 47 #define DNS_ORDER_VALID(order) ISC_MAGIC_VALID(order, DNS_ORDER_MAGIC) 48 49 isc_result_t 50 dns_order_create(isc_mem_t *mctx, dns_order_t **orderp) { 51 dns_order_t *order; 52 53 REQUIRE(orderp != NULL && *orderp == NULL); 54 55 order = isc_mem_get(mctx, sizeof(*order)); 56 57 ISC_LIST_INIT(order->ents); 58 59 /* Implicit attach. */ 60 isc_refcount_init(&order->references, 1); 61 62 order->mctx = NULL; 63 isc_mem_attach(mctx, &order->mctx); 64 order->magic = DNS_ORDER_MAGIC; 65 *orderp = order; 66 return (ISC_R_SUCCESS); 67 } 68 69 isc_result_t 70 dns_order_add(dns_order_t *order, const dns_name_t *name, 71 dns_rdatatype_t rdtype, dns_rdataclass_t rdclass, 72 unsigned int mode) { 73 dns_order_ent_t *ent; 74 75 REQUIRE(DNS_ORDER_VALID(order)); 76 REQUIRE(mode == DNS_RDATASETATTR_RANDOMIZE || 77 mode == DNS_RDATASETATTR_FIXEDORDER || 78 mode == DNS_RDATASETATTR_CYCLIC); 79 80 ent = isc_mem_get(order->mctx, sizeof(*ent)); 81 82 dns_fixedname_init(&ent->name); 83 dns_name_copynf(name, dns_fixedname_name(&ent->name)); 84 ent->rdtype = rdtype; 85 ent->rdclass = rdclass; 86 ent->mode = mode; 87 ISC_LINK_INIT(ent, link); 88 ISC_LIST_INITANDAPPEND(order->ents, ent, link); 89 return (ISC_R_SUCCESS); 90 } 91 92 static inline bool 93 match(const dns_name_t *name1, const dns_name_t *name2) { 94 if (dns_name_iswildcard(name2)) { 95 return (dns_name_matcheswildcard(name1, name2)); 96 } 97 return (dns_name_equal(name1, name2)); 98 } 99 100 unsigned int 101 dns_order_find(dns_order_t *order, const dns_name_t *name, 102 dns_rdatatype_t rdtype, dns_rdataclass_t rdclass) { 103 dns_order_ent_t *ent; 104 REQUIRE(DNS_ORDER_VALID(order)); 105 106 for (ent = ISC_LIST_HEAD(order->ents); ent != NULL; 107 ent = ISC_LIST_NEXT(ent, link)) 108 { 109 if (ent->rdtype != rdtype && ent->rdtype != dns_rdatatype_any) { 110 continue; 111 } 112 if (ent->rdclass != rdclass && 113 ent->rdclass != dns_rdataclass_any) { 114 continue; 115 } 116 if (match(name, dns_fixedname_name(&ent->name))) { 117 return (ent->mode); 118 } 119 } 120 return (DNS_RDATASETATTR_NONE); 121 } 122 123 void 124 dns_order_attach(dns_order_t *source, dns_order_t **target) { 125 REQUIRE(DNS_ORDER_VALID(source)); 126 REQUIRE(target != NULL && *target == NULL); 127 isc_refcount_increment(&source->references); 128 *target = source; 129 } 130 131 void 132 dns_order_detach(dns_order_t **orderp) { 133 REQUIRE(orderp != NULL && DNS_ORDER_VALID(*orderp)); 134 dns_order_t *order; 135 order = *orderp; 136 *orderp = NULL; 137 138 if (isc_refcount_decrement(&order->references) == 1) { 139 isc_refcount_destroy(&order->references); 140 order->magic = 0; 141 dns_order_ent_t *ent; 142 while ((ent = ISC_LIST_HEAD(order->ents)) != NULL) { 143 ISC_LIST_UNLINK(order->ents, ent, link); 144 isc_mem_put(order->mctx, ent, sizeof(*ent)); 145 } 146 isc_mem_putanddetach(&order->mctx, order, sizeof(*order)); 147 } 148 } 149