xref: /netbsd-src/external/mpl/bind/dist/lib/dns/order.c (revision b5c47949a45ac972130c38cf13dfd8afb1f09285)
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