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