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