xref: /netbsd-src/external/mpl/bind/dist/lib/ns/server.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1 /*	$NetBSD: server.c,v 1.11 2025/01/26 16:25:46 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/mem.h>
21 #include <isc/stats.h>
22 #include <isc/util.h>
23 
24 #include <dns/stats.h>
25 #include <dns/tkey.h>
26 
27 #include <ns/query.h>
28 #include <ns/server.h>
29 #include <ns/stats.h>
30 
31 #define SCTX_MAGIC    ISC_MAGIC('S', 'c', 't', 'x')
32 #define SCTX_VALID(s) ISC_MAGIC_VALID(s, SCTX_MAGIC)
33 
34 #define CHECKFATAL(op)                                  \
35 	do {                                            \
36 		result = (op);                          \
37 		RUNTIME_CHECK(result == ISC_R_SUCCESS); \
38 	} while (0)
39 
40 void
41 ns_server_create(isc_mem_t *mctx, ns_matchview_t matchingview,
42 		 ns_server_t **sctxp) {
43 	ns_server_t *sctx = NULL;
44 
45 	REQUIRE(sctxp != NULL && *sctxp == NULL);
46 
47 	sctx = isc_mem_get(mctx, sizeof(*sctx));
48 	*sctx = (ns_server_t){
49 		.udpsize = 1232,
50 		.transfer_tcp_message_size = 20480,
51 
52 		.fuzztype = isc_fuzz_none,
53 
54 		.matchingview = matchingview,
55 		.answercookie = true,
56 	};
57 
58 	isc_mem_attach(mctx, &sctx->mctx);
59 
60 	/*
61 	 * See here for more details:
62 	 * https://github.com/jemalloc/jemalloc/issues/2483
63 	 */
64 
65 	isc_refcount_init(&sctx->references, 1);
66 
67 	isc_quota_init(&sctx->xfroutquota, 10);
68 	isc_quota_init(&sctx->tcpquota, 10);
69 	isc_quota_init(&sctx->recursionquota, 100);
70 	isc_quota_init(&sctx->updquota, 100);
71 	isc_quota_init(&sctx->sig0checksquota, 1);
72 	ISC_LIST_INIT(sctx->http_quotas);
73 	isc_mutex_init(&sctx->http_quotas_lock);
74 
75 	ns_stats_create(mctx, ns_statscounter_max, &sctx->nsstats);
76 
77 	dns_rdatatypestats_create(mctx, &sctx->rcvquerystats);
78 
79 	dns_opcodestats_create(mctx, &sctx->opcodestats);
80 
81 	dns_rcodestats_create(mctx, &sctx->rcodestats);
82 
83 	isc_histomulti_create(mctx, DNS_SIZEHISTO_SIGBITSIN,
84 			      &sctx->udpinstats4);
85 
86 	isc_histomulti_create(mctx, DNS_SIZEHISTO_SIGBITSOUT,
87 			      &sctx->udpoutstats4);
88 
89 	isc_histomulti_create(mctx, DNS_SIZEHISTO_SIGBITSIN,
90 			      &sctx->udpinstats6);
91 
92 	isc_histomulti_create(mctx, DNS_SIZEHISTO_SIGBITSOUT,
93 			      &sctx->udpoutstats6);
94 
95 	isc_histomulti_create(mctx, DNS_SIZEHISTO_SIGBITSIN,
96 			      &sctx->tcpinstats4);
97 
98 	isc_histomulti_create(mctx, DNS_SIZEHISTO_SIGBITSOUT,
99 			      &sctx->tcpoutstats4);
100 
101 	isc_histomulti_create(mctx, DNS_SIZEHISTO_SIGBITSIN,
102 			      &sctx->tcpinstats6);
103 
104 	isc_histomulti_create(mctx, DNS_SIZEHISTO_SIGBITSOUT,
105 			      &sctx->tcpoutstats6);
106 
107 	ISC_LIST_INIT(sctx->altsecrets);
108 
109 	sctx->magic = SCTX_MAGIC;
110 	*sctxp = sctx;
111 }
112 
113 void
114 ns_server_attach(ns_server_t *src, ns_server_t **dest) {
115 	REQUIRE(SCTX_VALID(src));
116 	REQUIRE(dest != NULL && *dest == NULL);
117 
118 	isc_refcount_increment(&src->references);
119 
120 	*dest = src;
121 }
122 
123 void
124 ns_server_detach(ns_server_t **sctxp) {
125 	ns_server_t *sctx;
126 
127 	REQUIRE(sctxp != NULL && SCTX_VALID(*sctxp));
128 	sctx = *sctxp;
129 	*sctxp = NULL;
130 
131 	if (isc_refcount_decrement(&sctx->references) == 1) {
132 		ns_altsecret_t *altsecret;
133 		isc_quota_t *http_quota;
134 
135 		while ((altsecret = ISC_LIST_HEAD(sctx->altsecrets)) != NULL) {
136 			ISC_LIST_UNLINK(sctx->altsecrets, altsecret, link);
137 			isc_mem_put(sctx->mctx, altsecret, sizeof(*altsecret));
138 		}
139 
140 		if (sctx->sig0checksquota_exempt != NULL) {
141 			dns_acl_detach(&sctx->sig0checksquota_exempt);
142 		}
143 
144 		isc_quota_destroy(&sctx->sig0checksquota);
145 		isc_quota_destroy(&sctx->updquota);
146 		isc_quota_destroy(&sctx->recursionquota);
147 		isc_quota_destroy(&sctx->tcpquota);
148 		isc_quota_destroy(&sctx->xfroutquota);
149 
150 		http_quota = ISC_LIST_HEAD(sctx->http_quotas);
151 		while (http_quota != NULL) {
152 			isc_quota_t *next = NULL;
153 
154 			next = ISC_LIST_NEXT(http_quota, link);
155 			ISC_LIST_DEQUEUE(sctx->http_quotas, http_quota, link);
156 			isc_quota_destroy(http_quota);
157 			isc_mem_put(sctx->mctx, http_quota,
158 				    sizeof(*http_quota));
159 			http_quota = next;
160 		}
161 		isc_mutex_destroy(&sctx->http_quotas_lock);
162 
163 		if (sctx->server_id != NULL) {
164 			isc_mem_free(sctx->mctx, sctx->server_id);
165 		}
166 
167 		if (sctx->blackholeacl != NULL) {
168 			dns_acl_detach(&sctx->blackholeacl);
169 		}
170 		if (sctx->tkeyctx != NULL) {
171 			dns_tkeyctx_destroy(&sctx->tkeyctx);
172 		}
173 
174 		if (sctx->nsstats != NULL) {
175 			ns_stats_detach(&sctx->nsstats);
176 		}
177 
178 		if (sctx->rcvquerystats != NULL) {
179 			dns_stats_detach(&sctx->rcvquerystats);
180 		}
181 		if (sctx->opcodestats != NULL) {
182 			dns_stats_detach(&sctx->opcodestats);
183 		}
184 		if (sctx->rcodestats != NULL) {
185 			dns_stats_detach(&sctx->rcodestats);
186 		}
187 
188 		if (sctx->udpinstats4 != NULL) {
189 			isc_histomulti_destroy(&sctx->udpinstats4);
190 		}
191 		if (sctx->tcpinstats4 != NULL) {
192 			isc_histomulti_destroy(&sctx->tcpinstats4);
193 		}
194 		if (sctx->udpoutstats4 != NULL) {
195 			isc_histomulti_destroy(&sctx->udpoutstats4);
196 		}
197 		if (sctx->tcpoutstats4 != NULL) {
198 			isc_histomulti_destroy(&sctx->tcpoutstats4);
199 		}
200 
201 		if (sctx->udpinstats6 != NULL) {
202 			isc_histomulti_destroy(&sctx->udpinstats6);
203 		}
204 		if (sctx->tcpinstats6 != NULL) {
205 			isc_histomulti_destroy(&sctx->tcpinstats6);
206 		}
207 		if (sctx->udpoutstats6 != NULL) {
208 			isc_histomulti_destroy(&sctx->udpoutstats6);
209 		}
210 		if (sctx->tcpoutstats6 != NULL) {
211 			isc_histomulti_destroy(&sctx->tcpoutstats6);
212 		}
213 
214 		sctx->magic = 0;
215 
216 		isc_mem_putanddetach(&sctx->mctx, sctx, sizeof(*sctx));
217 	}
218 }
219 
220 isc_result_t
221 ns_server_setserverid(ns_server_t *sctx, const char *serverid) {
222 	REQUIRE(SCTX_VALID(sctx));
223 
224 	if (sctx->server_id != NULL) {
225 		isc_mem_free(sctx->mctx, sctx->server_id);
226 		sctx->server_id = NULL;
227 	}
228 
229 	if (serverid != NULL) {
230 		sctx->server_id = isc_mem_strdup(sctx->mctx, serverid);
231 	}
232 
233 	return ISC_R_SUCCESS;
234 }
235 
236 void
237 ns_server_setoption(ns_server_t *sctx, unsigned int option, bool value) {
238 	REQUIRE(SCTX_VALID(sctx));
239 	if (value) {
240 		sctx->options |= option;
241 	} else {
242 		sctx->options &= ~option;
243 	}
244 }
245 
246 bool
247 ns_server_getoption(ns_server_t *sctx, unsigned int option) {
248 	REQUIRE(SCTX_VALID(sctx));
249 
250 	return (sctx->options & option) != 0;
251 }
252 
253 void
254 ns_server_append_http_quota(ns_server_t *sctx, isc_quota_t *http_quota) {
255 	REQUIRE(SCTX_VALID(sctx));
256 	REQUIRE(http_quota != NULL);
257 
258 	LOCK(&sctx->http_quotas_lock);
259 	ISC_LINK_INIT(http_quota, link);
260 	ISC_LIST_APPEND(sctx->http_quotas, http_quota, link);
261 	UNLOCK(&sctx->http_quotas_lock);
262 }
263