/src/bind9/lib/dns/forward.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) Internet Systems Consortium, Inc. ("ISC") |
3 | | * |
4 | | * SPDX-License-Identifier: MPL-2.0 |
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 <isc/magic.h> |
17 | | #include <isc/mem.h> |
18 | | #include <isc/result.h> |
19 | | #include <isc/util.h> |
20 | | |
21 | | #include <dns/fixedname.h> |
22 | | #include <dns/forward.h> |
23 | | #include <dns/name.h> |
24 | | #include <dns/qp.h> |
25 | | #include <dns/types.h> |
26 | | #include <dns/view.h> |
27 | | |
28 | | struct dns_fwdtable { |
29 | | /* Unlocked. */ |
30 | | unsigned int magic; |
31 | | isc_mem_t *mctx; |
32 | | dns_qpmulti_t *table; |
33 | | }; |
34 | | |
35 | 2 | #define FWDTABLEMAGIC ISC_MAGIC('F', 'w', 'd', 'T') |
36 | | #define VALID_FWDTABLE(ft) ISC_MAGIC_VALID(ft, FWDTABLEMAGIC) |
37 | | |
38 | | static void |
39 | | qp_attach(void *uctx, void *pval, uint32_t ival); |
40 | | static void |
41 | | qp_detach(void *uctx, void *pval, uint32_t ival); |
42 | | static size_t |
43 | | qp_makekey(dns_qpkey_t key, void *uctx, void *pval, uint32_t ival); |
44 | | static void |
45 | | qp_triename(void *uctx, char *buf, size_t size); |
46 | | |
47 | | static dns_qpmethods_t qpmethods = { |
48 | | qp_attach, |
49 | | qp_detach, |
50 | | qp_makekey, |
51 | | qp_triename, |
52 | | }; |
53 | | |
54 | | void |
55 | | dns_fwdtable_create(isc_mem_t *mctx, dns_view_t *view, |
56 | 2 | dns_fwdtable_t **fwdtablep) { |
57 | 2 | dns_fwdtable_t *fwdtable = NULL; |
58 | | |
59 | 2 | REQUIRE(fwdtablep != NULL && *fwdtablep == NULL); |
60 | | |
61 | 2 | fwdtable = isc_mem_get(mctx, sizeof(*fwdtable)); |
62 | 2 | *fwdtable = (dns_fwdtable_t){ .magic = FWDTABLEMAGIC }; |
63 | | |
64 | 2 | dns_qpmulti_create(mctx, &qpmethods, view, &fwdtable->table); |
65 | | |
66 | 2 | isc_mem_attach(mctx, &fwdtable->mctx); |
67 | 2 | *fwdtablep = fwdtable; |
68 | 2 | } |
69 | | |
70 | | static dns_forwarders_t * |
71 | | new_forwarders(isc_mem_t *mctx, const dns_name_t *name, |
72 | 0 | dns_fwdpolicy_t fwdpolicy) { |
73 | 0 | dns_forwarders_t *forwarders = NULL; |
74 | |
|
75 | 0 | forwarders = isc_mem_get(mctx, sizeof(*forwarders)); |
76 | 0 | *forwarders = (dns_forwarders_t){ |
77 | 0 | .fwdpolicy = fwdpolicy, |
78 | 0 | .name = DNS_NAME_INITEMPTY, |
79 | 0 | .fwdrs = ISC_LIST_INITIALIZER, |
80 | 0 | }; |
81 | 0 | isc_mem_attach(mctx, &forwarders->mctx); |
82 | 0 | isc_refcount_init(&forwarders->references, 1); |
83 | |
|
84 | 0 | dns_name_dup(name, mctx, &forwarders->name); |
85 | |
|
86 | 0 | return forwarders; |
87 | 0 | } |
88 | | |
89 | | isc_result_t |
90 | | dns_fwdtable_addfwd(dns_fwdtable_t *fwdtable, const dns_name_t *name, |
91 | 0 | dns_forwarderlist_t *fwdrs, dns_fwdpolicy_t fwdpolicy) { |
92 | 0 | isc_result_t result; |
93 | 0 | dns_forwarders_t *forwarders = NULL; |
94 | 0 | dns_qp_t *qp = NULL; |
95 | |
|
96 | 0 | REQUIRE(VALID_FWDTABLE(fwdtable)); |
97 | |
|
98 | 0 | forwarders = new_forwarders(fwdtable->mctx, name, fwdpolicy); |
99 | |
|
100 | 0 | ISC_LIST_FOREACH(*fwdrs, fwd, link) { |
101 | 0 | dns_forwarder_t *nfwd = isc_mem_get(fwdtable->mctx, |
102 | 0 | sizeof(*nfwd)); |
103 | 0 | *nfwd = *fwd; |
104 | |
|
105 | 0 | if (fwd->tlsname != NULL) { |
106 | 0 | nfwd->tlsname = isc_mem_get(fwdtable->mctx, |
107 | 0 | sizeof(*nfwd->tlsname)); |
108 | 0 | dns_name_init(nfwd->tlsname); |
109 | 0 | dns_name_dup(fwd->tlsname, fwdtable->mctx, |
110 | 0 | nfwd->tlsname); |
111 | 0 | } |
112 | |
|
113 | 0 | ISC_LINK_INIT(nfwd, link); |
114 | 0 | ISC_LIST_APPEND(forwarders->fwdrs, nfwd, link); |
115 | 0 | } |
116 | |
|
117 | 0 | dns_qpmulti_write(fwdtable->table, &qp); |
118 | 0 | result = dns_qp_insert(qp, forwarders, 0); |
119 | 0 | dns_qp_compact(qp, DNS_QPGC_MAYBE); |
120 | 0 | dns_qpmulti_commit(fwdtable->table, &qp); |
121 | |
|
122 | 0 | dns_forwarders_detach(&forwarders); |
123 | |
|
124 | 0 | return result; |
125 | 0 | } |
126 | | |
127 | | isc_result_t |
128 | | dns_fwdtable_add(dns_fwdtable_t *fwdtable, const dns_name_t *name, |
129 | 0 | isc_sockaddrlist_t *addrs, dns_fwdpolicy_t fwdpolicy) { |
130 | 0 | isc_result_t result; |
131 | 0 | dns_forwarders_t *forwarders = NULL; |
132 | 0 | dns_qp_t *qp = NULL; |
133 | |
|
134 | 0 | REQUIRE(VALID_FWDTABLE(fwdtable)); |
135 | |
|
136 | 0 | forwarders = new_forwarders(fwdtable->mctx, name, fwdpolicy); |
137 | |
|
138 | 0 | ISC_LIST_FOREACH(*addrs, sa, link) { |
139 | 0 | dns_forwarder_t *fwd = isc_mem_get(fwdtable->mctx, |
140 | 0 | sizeof(*fwd)); |
141 | 0 | *fwd = (dns_forwarder_t){ .addr = *sa, |
142 | 0 | .link = ISC_LINK_INITIALIZER }; |
143 | 0 | ISC_LIST_APPEND(forwarders->fwdrs, fwd, link); |
144 | 0 | } |
145 | |
|
146 | 0 | dns_qpmulti_write(fwdtable->table, &qp); |
147 | 0 | result = dns_qp_insert(qp, forwarders, 0); |
148 | 0 | dns_qp_compact(qp, DNS_QPGC_MAYBE); |
149 | 0 | dns_qpmulti_commit(fwdtable->table, &qp); |
150 | |
|
151 | 0 | dns_forwarders_detach(&forwarders); |
152 | |
|
153 | 0 | return result; |
154 | 0 | } |
155 | | |
156 | | isc_result_t |
157 | | dns_fwdtable_find(dns_fwdtable_t *fwdtable, const dns_name_t *name, |
158 | 0 | dns_forwarders_t **forwardersp) { |
159 | 0 | isc_result_t result; |
160 | 0 | dns_qpread_t qpr; |
161 | 0 | void *pval = NULL; |
162 | |
|
163 | 0 | REQUIRE(VALID_FWDTABLE(fwdtable)); |
164 | |
|
165 | 0 | dns_qpmulti_query(fwdtable->table, &qpr); |
166 | 0 | result = dns_qp_lookup(&qpr, name, DNS_DBNAMESPACE_NORMAL, NULL, NULL, |
167 | 0 | &pval, NULL); |
168 | 0 | if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { |
169 | 0 | dns_forwarders_t *fwdrs = pval; |
170 | 0 | *forwardersp = fwdrs; |
171 | 0 | dns_forwarders_ref(fwdrs); |
172 | 0 | } |
173 | 0 | dns_qpread_destroy(fwdtable->table, &qpr); |
174 | |
|
175 | 0 | return result; |
176 | 0 | } |
177 | | |
178 | | void |
179 | 0 | dns_fwdtable_destroy(dns_fwdtable_t **fwdtablep) { |
180 | 0 | dns_fwdtable_t *fwdtable = NULL; |
181 | |
|
182 | 0 | REQUIRE(fwdtablep != NULL && VALID_FWDTABLE(*fwdtablep)); |
183 | |
|
184 | 0 | fwdtable = *fwdtablep; |
185 | 0 | *fwdtablep = NULL; |
186 | |
|
187 | 0 | dns_qpmulti_destroy(&fwdtable->table); |
188 | 0 | fwdtable->magic = 0; |
189 | |
|
190 | 0 | isc_mem_putanddetach(&fwdtable->mctx, fwdtable, sizeof(*fwdtable)); |
191 | 0 | } |
192 | | |
193 | | /*** |
194 | | *** Private |
195 | | ***/ |
196 | | |
197 | | static void |
198 | 0 | destroy_forwarders(dns_forwarders_t *forwarders) { |
199 | 0 | ISC_LIST_FOREACH(forwarders->fwdrs, fwd, link) { |
200 | 0 | ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link); |
201 | 0 | if (fwd->tlsname != NULL) { |
202 | 0 | dns_name_free(fwd->tlsname, forwarders->mctx); |
203 | 0 | isc_mem_put(forwarders->mctx, fwd->tlsname, |
204 | 0 | sizeof(*fwd->tlsname)); |
205 | 0 | } |
206 | 0 | isc_mem_put(forwarders->mctx, fwd, sizeof(*fwd)); |
207 | 0 | } |
208 | 0 | dns_name_free(&forwarders->name, forwarders->mctx); |
209 | 0 | isc_mem_putanddetach(&forwarders->mctx, forwarders, |
210 | 0 | sizeof(*forwarders)); |
211 | 0 | } |
212 | | |
213 | | #if DNS_FORWARD_TRACE |
214 | | ISC_REFCOUNT_TRACE_IMPL(dns_forwarders, destroy_forwarders); |
215 | | #else |
216 | 0 | ISC_REFCOUNT_IMPL(dns_forwarders, destroy_forwarders); Unexecuted instantiation: dns_forwarders_ref Unexecuted instantiation: dns_forwarders_unref Unexecuted instantiation: dns_forwarders_detach |
217 | 0 | #endif |
218 | 0 |
|
219 | 0 | static void |
220 | 0 | qp_attach(void *uctx ISC_ATTR_UNUSED, void *pval, |
221 | 0 | uint32_t ival ISC_ATTR_UNUSED) { |
222 | 0 | dns_forwarders_t *forwarders = pval; |
223 | 0 | dns_forwarders_ref(forwarders); |
224 | 0 | } |
225 | | |
226 | | static void |
227 | | qp_detach(void *uctx ISC_ATTR_UNUSED, void *pval, |
228 | 0 | uint32_t ival ISC_ATTR_UNUSED) { |
229 | 0 | dns_forwarders_t *forwarders = pval; |
230 | 0 | dns_forwarders_detach(&forwarders); |
231 | 0 | } |
232 | | |
233 | | static size_t |
234 | | qp_makekey(dns_qpkey_t key, void *uctx ISC_ATTR_UNUSED, void *pval, |
235 | 0 | uint32_t ival ISC_ATTR_UNUSED) { |
236 | 0 | dns_forwarders_t *fwd = pval; |
237 | 0 | return dns_qpkey_fromname(key, &fwd->name, DNS_DBNAMESPACE_NORMAL); |
238 | 0 | } |
239 | | |
240 | | static void |
241 | 0 | qp_triename(void *uctx, char *buf, size_t size) { |
242 | 0 | dns_view_t *view = uctx; |
243 | 0 | snprintf(buf, size, "view %s forwarder table", view->name); |
244 | 0 | } |