No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / bin / named / logconf.c
blob6010cb019dfb456b3dcc4bb20370a5918488eb5e
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2001 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: logconf.c,v 1.42 2007/06/19 23:46:59 tbox Exp */
22 /*! \file */
24 #include <config.h>
26 #include <isc/offset.h>
27 #include <isc/result.h>
28 #include <isc/stdio.h>
29 #include <isc/string.h>
30 #include <isc/syslog.h>
32 #include <isccfg/cfg.h>
33 #include <isccfg/log.h>
35 #include <named/log.h>
36 #include <named/logconf.h>
38 #define CHECK(op) \
39 do { result = (op); \
40 if (result != ISC_R_SUCCESS) goto cleanup; \
41 } while (0)
43 /*%
44 * Set up a logging category according to the named.conf data
45 * in 'ccat' and add it to 'lctx'.
47 static isc_result_t
48 category_fromconf(const cfg_obj_t *ccat, isc_logconfig_t *lctx) {
49 isc_result_t result;
50 const char *catname;
51 isc_logcategory_t *category;
52 isc_logmodule_t *module;
53 const cfg_obj_t *destinations = NULL;
54 const cfg_listelt_t *element = NULL;
56 catname = cfg_obj_asstring(cfg_tuple_get(ccat, "name"));
57 category = isc_log_categorybyname(ns_g_lctx, catname);
58 if (category == NULL) {
59 cfg_obj_log(ccat, ns_g_lctx, ISC_LOG_ERROR,
60 "unknown logging category '%s' ignored",
61 catname);
63 * Allow further processing by returning success.
65 return (ISC_R_SUCCESS);
68 module = NULL;
70 destinations = cfg_tuple_get(ccat, "destinations");
71 for (element = cfg_list_first(destinations);
72 element != NULL;
73 element = cfg_list_next(element))
75 const cfg_obj_t *channel = cfg_listelt_value(element);
76 const char *channelname = cfg_obj_asstring(channel);
78 result = isc_log_usechannel(lctx, channelname, category,
79 module);
80 if (result != ISC_R_SUCCESS) {
81 isc_log_write(ns_g_lctx, CFG_LOGCATEGORY_CONFIG,
82 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
83 "logging channel '%s': %s", channelname,
84 isc_result_totext(result));
85 return (result);
88 return (ISC_R_SUCCESS);
91 /*%
92 * Set up a logging channel according to the named.conf data
93 * in 'cchan' and add it to 'lctx'.
95 static isc_result_t
96 channel_fromconf(const cfg_obj_t *channel, isc_logconfig_t *lctx) {
97 isc_result_t result;
98 isc_logdestination_t dest;
99 unsigned int type;
100 unsigned int flags = 0;
101 int level;
102 const char *channelname;
103 const cfg_obj_t *fileobj = NULL;
104 const cfg_obj_t *syslogobj = NULL;
105 const cfg_obj_t *nullobj = NULL;
106 const cfg_obj_t *stderrobj = NULL;
107 const cfg_obj_t *severity = NULL;
108 int i;
110 channelname = cfg_obj_asstring(cfg_map_getname(channel));
112 (void)cfg_map_get(channel, "file", &fileobj);
113 (void)cfg_map_get(channel, "syslog", &syslogobj);
114 (void)cfg_map_get(channel, "null", &nullobj);
115 (void)cfg_map_get(channel, "stderr", &stderrobj);
117 i = 0;
118 if (fileobj != NULL)
119 i++;
120 if (syslogobj != NULL)
121 i++;
122 if (nullobj != NULL)
123 i++;
124 if (stderrobj != NULL)
125 i++;
127 if (i != 1) {
128 cfg_obj_log(channel, ns_g_lctx, ISC_LOG_ERROR,
129 "channel '%s': exactly one of file, syslog, "
130 "null, and stderr must be present", channelname);
131 return (ISC_R_FAILURE);
134 type = ISC_LOG_TONULL;
136 if (fileobj != NULL) {
137 const cfg_obj_t *pathobj = cfg_tuple_get(fileobj, "file");
138 const cfg_obj_t *sizeobj = cfg_tuple_get(fileobj, "size");
139 const cfg_obj_t *versionsobj =
140 cfg_tuple_get(fileobj, "versions");
141 isc_int32_t versions = ISC_LOG_ROLLNEVER;
142 isc_offset_t size = 0;
144 type = ISC_LOG_TOFILE;
146 if (versionsobj != NULL && cfg_obj_isuint32(versionsobj))
147 versions = cfg_obj_asuint32(versionsobj);
148 if (versionsobj != NULL && cfg_obj_isstring(versionsobj) &&
149 strcasecmp(cfg_obj_asstring(versionsobj), "unlimited") == 0)
150 versions = ISC_LOG_ROLLINFINITE;
151 if (sizeobj != NULL &&
152 cfg_obj_isuint64(sizeobj) &&
153 cfg_obj_asuint64(sizeobj) < ISC_OFFSET_MAXIMUM)
154 size = (isc_offset_t)cfg_obj_asuint64(sizeobj);
155 dest.file.stream = NULL;
156 dest.file.name = cfg_obj_asstring(pathobj);
157 dest.file.versions = versions;
158 dest.file.maximum_size = size;
159 } else if (syslogobj != NULL) {
160 int facility = LOG_DAEMON;
162 type = ISC_LOG_TOSYSLOG;
164 if (cfg_obj_isstring(syslogobj)) {
165 const char *facilitystr = cfg_obj_asstring(syslogobj);
166 (void)isc_syslog_facilityfromstring(facilitystr,
167 &facility);
169 dest.facility = facility;
170 } else if (stderrobj != NULL) {
171 type = ISC_LOG_TOFILEDESC;
172 dest.file.stream = stderr;
173 dest.file.name = NULL;
174 dest.file.versions = ISC_LOG_ROLLNEVER;
175 dest.file.maximum_size = 0;
179 * Munge flags.
182 const cfg_obj_t *printcat = NULL;
183 const cfg_obj_t *printsev = NULL;
184 const cfg_obj_t *printtime = NULL;
186 (void)cfg_map_get(channel, "print-category", &printcat);
187 (void)cfg_map_get(channel, "print-severity", &printsev);
188 (void)cfg_map_get(channel, "print-time", &printtime);
190 if (printcat != NULL && cfg_obj_asboolean(printcat))
191 flags |= ISC_LOG_PRINTCATEGORY;
192 if (printtime != NULL && cfg_obj_asboolean(printtime))
193 flags |= ISC_LOG_PRINTTIME;
194 if (printsev != NULL && cfg_obj_asboolean(printsev))
195 flags |= ISC_LOG_PRINTLEVEL;
198 level = ISC_LOG_INFO;
199 if (cfg_map_get(channel, "severity", &severity) == ISC_R_SUCCESS) {
200 if (cfg_obj_isstring(severity)) {
201 const char *str = cfg_obj_asstring(severity);
202 if (strcasecmp(str, "critical") == 0)
203 level = ISC_LOG_CRITICAL;
204 else if (strcasecmp(str, "error") == 0)
205 level = ISC_LOG_ERROR;
206 else if (strcasecmp(str, "warning") == 0)
207 level = ISC_LOG_WARNING;
208 else if (strcasecmp(str, "notice") == 0)
209 level = ISC_LOG_NOTICE;
210 else if (strcasecmp(str, "info") == 0)
211 level = ISC_LOG_INFO;
212 else if (strcasecmp(str, "dynamic") == 0)
213 level = ISC_LOG_DYNAMIC;
214 } else
215 /* debug */
216 level = cfg_obj_asuint32(severity);
219 result = isc_log_createchannel(lctx, channelname,
220 type, level, &dest, flags);
222 if (result == ISC_R_SUCCESS && type == ISC_LOG_TOFILE) {
223 FILE *fp;
226 * Test that the file can be opened, since isc_log_open()
227 * can't effectively report failures when called in
228 * isc_log_doit().
230 result = isc_stdio_open(dest.file.name, "a", &fp);
231 if (result != ISC_R_SUCCESS)
232 isc_log_write(ns_g_lctx, CFG_LOGCATEGORY_CONFIG,
233 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
234 "logging channel '%s' file '%s': %s",
235 channelname, dest.file.name,
236 isc_result_totext(result));
237 else
238 (void)isc_stdio_close(fp);
241 * Allow named to continue by returning success.
243 result = ISC_R_SUCCESS;
246 return (result);
249 isc_result_t
250 ns_log_configure(isc_logconfig_t *logconf, const cfg_obj_t *logstmt) {
251 isc_result_t result;
252 const cfg_obj_t *channels = NULL;
253 const cfg_obj_t *categories = NULL;
254 const cfg_listelt_t *element;
255 isc_boolean_t default_set = ISC_FALSE;
256 isc_boolean_t unmatched_set = ISC_FALSE;
257 const cfg_obj_t *catname;
259 CHECK(ns_log_setdefaultchannels(logconf));
261 (void)cfg_map_get(logstmt, "channel", &channels);
262 for (element = cfg_list_first(channels);
263 element != NULL;
264 element = cfg_list_next(element))
266 const cfg_obj_t *channel = cfg_listelt_value(element);
267 CHECK(channel_fromconf(channel, logconf));
270 (void)cfg_map_get(logstmt, "category", &categories);
271 for (element = cfg_list_first(categories);
272 element != NULL;
273 element = cfg_list_next(element))
275 const cfg_obj_t *category = cfg_listelt_value(element);
276 CHECK(category_fromconf(category, logconf));
277 if (!default_set) {
278 catname = cfg_tuple_get(category, "name");
279 if (strcmp(cfg_obj_asstring(catname), "default") == 0)
280 default_set = ISC_TRUE;
282 if (!unmatched_set) {
283 catname = cfg_tuple_get(category, "name");
284 if (strcmp(cfg_obj_asstring(catname), "unmatched") == 0)
285 unmatched_set = ISC_TRUE;
289 if (!default_set)
290 CHECK(ns_log_setdefaultcategory(logconf));
292 if (!unmatched_set)
293 CHECK(ns_log_setunmatchedcategory(logconf));
295 return (ISC_R_SUCCESS);
297 cleanup:
298 if (logconf != NULL)
299 isc_logconfig_destroy(&logconf);
300 return (result);