Home | History | Annotate | Line # | Download | only in ns
      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