1 /* $NetBSD: order.c,v 1.6 2021/02/19 16:42:16 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 https://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 mode == DNS_RDATASETATTR_NONE); 80 81 ent = isc_mem_get(order->mctx, sizeof(*ent)); 82 83 dns_fixedname_init(&ent->name); 84 dns_name_copynf(name, dns_fixedname_name(&ent->name)); 85 ent->rdtype = rdtype; 86 ent->rdclass = rdclass; 87 ent->mode = mode; 88 ISC_LINK_INIT(ent, link); 89 ISC_LIST_INITANDAPPEND(order->ents, ent, link); 90 return (ISC_R_SUCCESS); 91 } 92 93 static inline bool 94 match(const dns_name_t *name1, const dns_name_t *name2) { 95 if (dns_name_iswildcard(name2)) { 96 return (dns_name_matcheswildcard(name1, name2)); 97 } 98 return (dns_name_equal(name1, name2)); 99 } 100 101 unsigned int 102 dns_order_find(dns_order_t *order, const dns_name_t *name, 103 dns_rdatatype_t rdtype, dns_rdataclass_t rdclass) { 104 dns_order_ent_t *ent; 105 REQUIRE(DNS_ORDER_VALID(order)); 106 107 for (ent = ISC_LIST_HEAD(order->ents); ent != NULL; 108 ent = ISC_LIST_NEXT(ent, link)) 109 { 110 if (ent->rdtype != rdtype && ent->rdtype != dns_rdatatype_any) { 111 continue; 112 } 113 if (ent->rdclass != rdclass && 114 ent->rdclass != dns_rdataclass_any) { 115 continue; 116 } 117 if (match(name, dns_fixedname_name(&ent->name))) { 118 return (ent->mode); 119 } 120 } 121 return (DNS_RDATASETATTR_NONE); 122 } 123 124 void 125 dns_order_attach(dns_order_t *source, dns_order_t **target) { 126 REQUIRE(DNS_ORDER_VALID(source)); 127 REQUIRE(target != NULL && *target == NULL); 128 isc_refcount_increment(&source->references); 129 *target = source; 130 } 131 132 void 133 dns_order_detach(dns_order_t **orderp) { 134 REQUIRE(orderp != NULL && DNS_ORDER_VALID(*orderp)); 135 dns_order_t *order; 136 order = *orderp; 137 *orderp = NULL; 138 139 if (isc_refcount_decrement(&order->references) == 1) { 140 isc_refcount_destroy(&order->references); 141 order->magic = 0; 142 dns_order_ent_t *ent; 143 while ((ent = ISC_LIST_HEAD(order->ents)) != NULL) { 144 ISC_LIST_UNLINK(order->ents, ent, link); 145 isc_mem_put(order->mctx, ent, sizeof(*ent)); 146 } 147 isc_mem_putanddetach(&order->mctx, order, sizeof(*order)); 148 } 149 } 150