Home | History | Annotate | Line # | Download | only in named
      1 /*	$NetBSD: log.c,v 1.8 2025/01/26 16:24:33 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 <stdlib.h>
     19 
     20 #include <isc/result.h>
     21 #include <isc/util.h>
     22 
     23 #include <dns/log.h>
     24 
     25 #include <isccfg/log.h>
     26 
     27 #include <ns/log.h>
     28 
     29 #include <named/log.h>
     30 
     31 #ifndef ISC_FACILITY
     32 #define ISC_FACILITY LOG_DAEMON
     33 #endif /* ifndef ISC_FACILITY */
     34 
     35 /*%
     36  * When adding a new category, be sure to add the appropriate
     37  * \#define to <named/log.h> and to update the list in
     38  * bin/check/check-tool.c.
     39  */
     40 static isc_logcategory_t categories[] = { { "", 0 },
     41 					  { "unmatched", 0 },
     42 					  { NULL, 0 } };
     43 
     44 /*%
     45  * When adding a new module, be sure to add the appropriate
     46  * \#define to <dns/log.h>.
     47  */
     48 static isc_logmodule_t modules[] = {
     49 	{ "main", 0 }, { "server", 0 }, { "control", 0 }, { NULL, 0 }
     50 };
     51 
     52 isc_result_t
     53 named_log_init(bool safe) {
     54 	isc_result_t result;
     55 	isc_logconfig_t *lcfg = NULL;
     56 	isc_mem_t *log_mctx = NULL;
     57 
     58 	named_g_categories = categories;
     59 	named_g_modules = modules;
     60 
     61 	/*
     62 	 * Setup a logging context.
     63 	 */
     64 	isc_mem_create(&log_mctx);
     65 	isc_mem_setname(log_mctx, "named_log");
     66 	isc_log_create(log_mctx, &named_g_lctx, &lcfg);
     67 	isc_mem_detach(&log_mctx);
     68 
     69 	/*
     70 	 * named-checktool.c:setup_logging() needs to be kept in sync.
     71 	 */
     72 	isc_log_registercategories(named_g_lctx, named_g_categories);
     73 	isc_log_registermodules(named_g_lctx, named_g_modules);
     74 	isc_log_setcontext(named_g_lctx);
     75 	dns_log_init(named_g_lctx);
     76 	dns_log_setcontext(named_g_lctx);
     77 	cfg_log_init(named_g_lctx);
     78 	ns_log_init(named_g_lctx);
     79 	ns_log_setcontext(named_g_lctx);
     80 
     81 	if (safe) {
     82 		named_log_setsafechannels(lcfg);
     83 	} else {
     84 		named_log_setdefaultchannels(lcfg);
     85 	}
     86 
     87 	result = named_log_setdefaultcategory(lcfg);
     88 	if (result != ISC_R_SUCCESS) {
     89 		goto cleanup;
     90 	}
     91 
     92 	named_log_setdefaultsslkeylogfile(lcfg);
     93 
     94 	return ISC_R_SUCCESS;
     95 
     96 cleanup:
     97 	isc_log_destroy(&named_g_lctx);
     98 	isc_log_setcontext(NULL);
     99 	dns_log_setcontext(NULL);
    100 
    101 	return result;
    102 }
    103 
    104 void
    105 named_log_setdefaultchannels(isc_logconfig_t *lcfg) {
    106 	isc_logdestination_t destination;
    107 
    108 	/*
    109 	 * By default, the logging library makes "default_debug" log to
    110 	 * stderr.  In BIND, we want to override this and log to named.run
    111 	 * instead, unless the -g option was given.
    112 	 */
    113 	if (!named_g_logstderr) {
    114 		destination.file.stream = NULL;
    115 		destination.file.name = "named.run";
    116 		destination.file.versions = ISC_LOG_ROLLNEVER;
    117 		destination.file.maximum_size = 0;
    118 		isc_log_createchannel(lcfg, "default_debug", ISC_LOG_TOFILE,
    119 				      ISC_LOG_DYNAMIC, &destination,
    120 				      ISC_LOG_PRINTTIME | ISC_LOG_DEBUGONLY);
    121 	}
    122 
    123 	if (named_g_logfile != NULL) {
    124 		destination.file.stream = NULL;
    125 		destination.file.name = named_g_logfile;
    126 		destination.file.versions = ISC_LOG_ROLLNEVER;
    127 		destination.file.maximum_size = 0;
    128 		isc_log_createchannel(lcfg, "default_logfile", ISC_LOG_TOFILE,
    129 				      ISC_LOG_DYNAMIC, &destination,
    130 				      ISC_LOG_PRINTTIME |
    131 					      ISC_LOG_PRINTCATEGORY |
    132 					      ISC_LOG_PRINTLEVEL);
    133 	}
    134 
    135 #if ISC_FACILITY != LOG_DAEMON
    136 	destination.facility = ISC_FACILITY;
    137 	isc_log_createchannel(lcfg, "default_syslog", ISC_LOG_TOSYSLOG,
    138 			      ISC_LOG_INFO, &destination, 0);
    139 #endif /* if ISC_FACILITY != LOG_DAEMON */
    140 
    141 	/*
    142 	 * Set the initial debug level.
    143 	 */
    144 	isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel);
    145 }
    146 
    147 void
    148 named_log_setsafechannels(isc_logconfig_t *lcfg) {
    149 	isc_logdestination_t destination;
    150 
    151 	if (!named_g_logstderr) {
    152 		isc_log_createchannel(lcfg, "default_debug", ISC_LOG_TONULL,
    153 				      ISC_LOG_DYNAMIC, NULL, 0);
    154 
    155 		/*
    156 		 * Setting the debug level to zero should get the output
    157 		 * discarded a bit faster.
    158 		 */
    159 		isc_log_setdebuglevel(named_g_lctx, 0);
    160 	} else {
    161 		isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel);
    162 	}
    163 
    164 	if (named_g_logfile != NULL) {
    165 		destination.file.stream = NULL;
    166 		destination.file.name = named_g_logfile;
    167 		destination.file.versions = ISC_LOG_ROLLNEVER;
    168 		destination.file.maximum_size = 0;
    169 		isc_log_createchannel(lcfg, "default_logfile", ISC_LOG_TOFILE,
    170 				      ISC_LOG_DYNAMIC, &destination,
    171 				      ISC_LOG_PRINTTIME |
    172 					      ISC_LOG_PRINTCATEGORY |
    173 					      ISC_LOG_PRINTLEVEL);
    174 	}
    175 
    176 #if ISC_FACILITY != LOG_DAEMON
    177 	destination.facility = ISC_FACILITY;
    178 	isc_log_createchannel(lcfg, "default_syslog", ISC_LOG_TOSYSLOG,
    179 			      ISC_LOG_INFO, &destination, 0);
    180 #endif /* if ISC_FACILITY != LOG_DAEMON */
    181 }
    182 
    183 /*
    184  * If the SSLKEYLOGFILE environment variable is set, TLS pre-master secrets are
    185  * logged (for debugging purposes) to the file whose path is provided in that
    186  * variable.  Set up a default logging channel which maintains up to 10 files
    187  * containing TLS pre-master secrets, each up to 100 MB in size.  If the
    188  * SSLKEYLOGFILE environment variable is set to the string "config", suppress
    189  * creation of the default channel, allowing custom logging channel
    190  * configuration for TLS pre-master secrets to be provided via the "logging"
    191  * stanza in the configuration file.
    192  */
    193 void
    194 named_log_setdefaultsslkeylogfile(isc_logconfig_t *lcfg) {
    195 	const char *sslkeylogfile_path = getenv("SSLKEYLOGFILE");
    196 	isc_logdestination_t destination = {
    197 		.file = {
    198 			.name = sslkeylogfile_path,
    199 			.versions = 10,
    200 			.suffix = isc_log_rollsuffix_timestamp,
    201 			.maximum_size = 100 * 1024 * 1024,
    202 		},
    203 	};
    204 	isc_result_t result;
    205 
    206 	if (sslkeylogfile_path == NULL ||
    207 	    strcmp(sslkeylogfile_path, "config") == 0)
    208 	{
    209 		return;
    210 	}
    211 
    212 	isc_log_createchannel(lcfg, "default_sslkeylogfile", ISC_LOG_TOFILE,
    213 			      ISC_LOG_INFO, &destination, 0);
    214 	result = isc_log_usechannel(lcfg, "default_sslkeylogfile",
    215 				    ISC_LOGCATEGORY_SSLKEYLOG, NULL);
    216 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
    217 }
    218 
    219 isc_result_t
    220 named_log_setdefaultcategory(isc_logconfig_t *lcfg) {
    221 	isc_result_t result = ISC_R_SUCCESS;
    222 
    223 	result = isc_log_usechannel(lcfg, "default_debug",
    224 				    ISC_LOGCATEGORY_DEFAULT, NULL);
    225 	if (result != ISC_R_SUCCESS) {
    226 		goto cleanup;
    227 	}
    228 
    229 	if (!named_g_logstderr) {
    230 		if (named_g_logfile != NULL) {
    231 			result = isc_log_usechannel(lcfg, "default_logfile",
    232 						    ISC_LOGCATEGORY_DEFAULT,
    233 						    NULL);
    234 		} else if (!named_g_nosyslog) {
    235 			result = isc_log_usechannel(lcfg, "default_syslog",
    236 						    ISC_LOGCATEGORY_DEFAULT,
    237 						    NULL);
    238 		}
    239 	}
    240 
    241 cleanup:
    242 	return result;
    243 }
    244 
    245 isc_result_t
    246 named_log_setunmatchedcategory(isc_logconfig_t *lcfg) {
    247 	isc_result_t result;
    248 
    249 	result = isc_log_usechannel(lcfg, "null", NAMED_LOGCATEGORY_UNMATCHED,
    250 				    NULL);
    251 	return result;
    252 }
    253 
    254 void
    255 named_log_shutdown(void) {
    256 	isc_log_destroy(&named_g_lctx);
    257 	isc_log_setcontext(NULL);
    258 	dns_log_setcontext(NULL);
    259 }
    260