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