1 /* $NetBSD: log.c,v 1.8 2020/05/25 20:47:20 christos Exp $ */
2
3 /*
4 * Copyright (C) 2004-2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
6 *
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.
10 *
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.
18 */
19
20 /* Id */
21
22 /*! \file
23 * \author Principal Authors: DCL */
24
25 #include <config.h>
26
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <limits.h>
30 #include <time.h>
31
32 #include <sys/types.h> /* dev_t FreeBSD 2.1 */
33
34 #include <isc/dir.h>
35 #include <isc/file.h>
36 #include <isc/log.h>
37 #include <isc/magic.h>
38 #include <isc/mem.h>
39 #include <isc/msgs.h>
40 #include <isc/print.h>
41 #include <isc/stat.h>
42 #include <isc/stdio.h>
43 #include <isc/string.h>
44 #include <isc/time.h>
45 #include <isc/util.h>
46 #include "ntp_stdlib.h" /* NTP change for strlcpy, strlcat */
47
48 #define LCTX_MAGIC ISC_MAGIC('L', 'c', 't', 'x')
49 #define VALID_CONTEXT(lctx) ISC_MAGIC_VALID(lctx, LCTX_MAGIC)
50
51 #define LCFG_MAGIC ISC_MAGIC('L', 'c', 'f', 'g')
52 #define VALID_CONFIG(lcfg) ISC_MAGIC_VALID(lcfg, LCFG_MAGIC)
53
54 /*
55 * XXXDCL make dynamic?
56 */
57 #define LOG_BUFFER_SIZE (8 * 1024)
58
59 #ifndef PATH_MAX
60 #define PATH_MAX 1024 /* AIX and others don't define this. */
61 #endif
62
63 /*!
64 * This is the structure that holds each named channel. A simple linked
65 * list chains all of the channels together, so an individual channel is
66 * found by doing strcmp()s with the names down the list. Their should
67 * be no performance penalty from this as it is expected that the number
68 * of named channels will be no more than a dozen or so, and name lookups
69 * from the head of the list are only done when isc_log_usechannel() is
70 * called, which should also be very infrequent.
71 */
72 typedef struct isc_logchannel isc_logchannel_t;
73
74 struct isc_logchannel {
75 char * name;
76 unsigned int type;
77 int level;
78 unsigned int flags;
79 isc_logdestination_t destination;
80 ISC_LINK(isc_logchannel_t) link;
81 };
82
83 /*!
84 * The logchannellist structure associates categories and modules with
85 * channels. First the appropriate channellist is found based on the
86 * category, and then each structure in the linked list is checked for
87 * a matching module. It is expected that the number of channels
88 * associated with any given category will be very short, no more than
89 * three or four in the more unusual cases.
90 */
91 typedef struct isc_logchannellist isc_logchannellist_t;
92
93 struct isc_logchannellist {
94 const isc_logmodule_t * module;
95 isc_logchannel_t * channel;
96 ISC_LINK(isc_logchannellist_t) link;
97 };
98
99 /*!
100 * This structure is used to remember messages for pruning via
101 * isc_log_[v]write1().
102 */
103 typedef struct isc_logmessage isc_logmessage_t;
104
105 struct isc_logmessage {
106 char * text;
107 isc_time_t time;
108 ISC_LINK(isc_logmessage_t) link;
109 };
110
111 /*!
112 * The isc_logconfig structure is used to store the configurable information
113 * about where messages are actually supposed to be sent -- the information
114 * that could changed based on some configuration file, as opposed to the
115 * the category/module specification of isc_log_[v]write[1] that is compiled
116 * into a program, or the debug_level which is dynamic state information.
117 */
118 struct isc_logconfig {
119 unsigned int magic;
120 isc_log_t * lctx;
121 ISC_LIST(isc_logchannel_t) channels;
122 ISC_LIST(isc_logchannellist_t) *channellists;
123 unsigned int channellist_count;
124 unsigned int duplicate_interval;
125 int highest_level;
126 char * tag;
127 isc_boolean_t dynamic;
128 };
129
130 /*!
131 * This isc_log structure provides the context for the isc_log functions.
132 * The log context locks itself in isc_log_doit, the internal backend to
133 * isc_log_write. The locking is necessary both to provide exclusive access
134 * to the buffer into which the message is formatted and to guard against
135 * competing threads trying to write to the same syslog resource. (On
136 * some systems, such as BSD/OS, stdio is thread safe but syslog is not.)
137 * Unfortunately, the lock cannot guard against a _different_ logging
138 * context in the same program competing for syslog's attention. Thus
139 * There Can Be Only One, but this is not enforced.
140 * XXXDCL enforce it?
141 *
142 * Note that the category and module information is not locked.
143 * This is because in the usual case, only one isc_log_t is ever created
144 * in a program, and the category/module registration happens only once.
145 * XXXDCL it might be wise to add more locking overall.
146 */
147 struct isc_log {
148 /* Not locked. */
149 unsigned int magic;
150 isc_mem_t * mctx;
151 isc_logcategory_t * categories;
152 unsigned int category_count;
153 isc_logmodule_t * modules;
154 unsigned int module_count;
155 int debug_level;
156 isc_mutex_t lock;
157 /* Locked by isc_log lock. */
158 isc_logconfig_t * logconfig;
159 char buffer[LOG_BUFFER_SIZE];
160 ISC_LIST(isc_logmessage_t) messages;
161 };
162
163 /*!
164 * Used when ISC_LOG_PRINTLEVEL is enabled for a channel.
165 */
166 static const char *log_level_strings[] = {
167 "debug",
168 "info",
169 "notice",
170 "warning",
171 "error",
172 "critical"
173 };
174
175 /*!
176 * Used to convert ISC_LOG_* priorities into syslog priorities.
177 * XXXDCL This will need modification for NT.
178 */
179 static const int syslog_map[] = {
180 LOG_DEBUG,
181 LOG_INFO,
182 LOG_NOTICE,
183 LOG_WARNING,
184 LOG_ERR,
185 LOG_CRIT
186 };
187
188 /*!
189 * When adding new categories, a corresponding ISC_LOGCATEGORY_foo
190 * definition needs to be added to <isc/log.h>.
191 *
192 * The default category is provided so that the internal default can
193 * be overridden. Since the default is always looked up as the first
194 * channellist in the log context, it must come first in isc_categories[].
195 */
196 LIBISC_EXTERNAL_DATA isc_logcategory_t isc_categories[] = {
197 { "default", 0 }, /* "default" must come first. */
198 { "general", 0 },
199 { NULL, 0 }
200 };
201
202 /*!
203 * See above comment for categories on LIBISC_EXTERNAL_DATA, and apply it to modules.
204 */
205 LIBISC_EXTERNAL_DATA isc_logmodule_t isc_modules[] = {
206 { "socket", 0 },
207 { "time", 0 },
208 { "interface", 0 },
209 { "timer", 0 },
210 { "file", 0 },
211 { NULL, 0 }
212 };
213
214 /*!
215 * This essentially constant structure must be filled in at run time,
216 * because its channel member is pointed to a channel that is created
217 * dynamically with isc_log_createchannel.
218 */
219 static isc_logchannellist_t default_channel;
220
221 /*!
222 * libisc logs to this context.
223 */
224 LIBISC_EXTERNAL_DATA isc_log_t *isc_lctx = NULL;
225
226 /*!
227 * Forward declarations.
228 */
229 static isc_result_t
230 assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
231 const isc_logmodule_t *module, isc_logchannel_t *channel);
232
233 static isc_result_t
234 sync_channellist(isc_logconfig_t *lcfg);
235
236 static isc_result_t
237 greatest_version(isc_logchannel_t *channel, int *greatest);
238
239 static isc_result_t
240 roll_log(isc_logchannel_t *channel);
241
242 static void
243 isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
244 isc_logmodule_t *module, int level, isc_boolean_t write_once,
245 isc_msgcat_t *msgcat, int msgset, int msg,
246 const char *format, va_list args)
247 ISC_FORMAT_PRINTF(9, 0);
248
249 /*@{*/
250 /*!
251 * Convenience macros.
252 */
253
254 #define FACILITY(channel) (channel->destination.facility)
255 #define FILE_NAME(channel) (channel->destination.file.name)
256 #define FILE_STREAM(channel) (channel->destination.file.stream)
257 #define FILE_VERSIONS(channel) (channel->destination.file.versions)
258 #define FILE_MAXSIZE(channel) (channel->destination.file.maximum_size)
259 #define FILE_MAXREACHED(channel) (channel->destination.file.maximum_reached)
260
261 /*@}*/
262 /****
263 **** Public interfaces.
264 ****/
265
266 /*
267 * Establish a new logging context, with default channels.
268 */
269 isc_result_t
isc_log_create(isc_mem_t * mctx,isc_log_t ** lctxp,isc_logconfig_t ** lcfgp)270 isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) {
271 isc_log_t *lctx;
272 isc_logconfig_t *lcfg = NULL;
273 isc_result_t result;
274
275 REQUIRE(mctx != NULL);
276 REQUIRE(lctxp != NULL && *lctxp == NULL);
277 REQUIRE(lcfgp == NULL || *lcfgp == NULL);
278
279 lctx = isc_mem_get(mctx, sizeof(*lctx));
280 if (lctx != NULL) {
281 lctx->mctx = mctx;
282 lctx->categories = NULL;
283 lctx->category_count = 0;
284 lctx->modules = NULL;
285 lctx->module_count = 0;
286 lctx->debug_level = 0;
287
288 ISC_LIST_INIT(lctx->messages);
289
290 result = isc_mutex_init(&lctx->lock);
291 if (result != ISC_R_SUCCESS) {
292 isc_mem_put(mctx, lctx, sizeof(*lctx));
293 return (result);
294 }
295
296 /*
297 * Normally setting the magic number is the last step done
298 * in a creation function, but a valid log context is needed
299 * by isc_log_registercategories and isc_logconfig_create.
300 * If either fails, the lctx is destroyed and not returned
301 * to the caller.
302 */
303 lctx->magic = LCTX_MAGIC;
304
305 isc_log_registercategories(lctx, isc_categories);
306 isc_log_registermodules(lctx, isc_modules);
307 result = isc_logconfig_create(lctx, &lcfg);
308
309 } else
310 result = ISC_R_NOMEMORY;
311
312 if (result == ISC_R_SUCCESS)
313 result = sync_channellist(lcfg);
314
315 if (result == ISC_R_SUCCESS) {
316 lctx->logconfig = lcfg;
317
318 *lctxp = lctx;
319 if (lcfgp != NULL)
320 *lcfgp = lcfg;
321
322 } else {
323 if (lcfg != NULL)
324 isc_logconfig_destroy(&lcfg);
325 if (lctx != NULL)
326 isc_log_destroy(&lctx);
327 }
328
329 return (result);
330 }
331
332 isc_result_t
isc_logconfig_create(isc_log_t * lctx,isc_logconfig_t ** lcfgp)333 isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp) {
334 isc_logconfig_t *lcfg;
335 isc_logdestination_t destination;
336 isc_result_t result = ISC_R_SUCCESS;
337 int level = ISC_LOG_INFO;
338
339 REQUIRE(lcfgp != NULL && *lcfgp == NULL);
340 REQUIRE(VALID_CONTEXT(lctx));
341
342 lcfg = isc_mem_get(lctx->mctx, sizeof(*lcfg));
343
344 if (lcfg != NULL) {
345 lcfg->lctx = lctx;
346 lcfg->channellists = NULL;
347 lcfg->channellist_count = 0;
348 lcfg->duplicate_interval = 0;
349 lcfg->highest_level = level;
350 lcfg->tag = NULL;
351 lcfg->dynamic = ISC_FALSE;
352
353 ISC_LIST_INIT(lcfg->channels);
354
355 /*
356 * Normally the magic number is the last thing set in the
357 * structure, but isc_log_createchannel() needs a valid
358 * config. If the channel creation fails, the lcfg is not
359 * returned to the caller.
360 */
361 lcfg->magic = LCFG_MAGIC;
362
363 } else
364 result = ISC_R_NOMEMORY;
365
366 /*
367 * Create the default channels:
368 * default_syslog, default_stderr, default_debug and null.
369 */
370 if (result == ISC_R_SUCCESS) {
371 destination.facility = LOG_DAEMON;
372 result = isc_log_createchannel(lcfg, "default_syslog",
373 ISC_LOG_TOSYSLOG, level,
374 &destination, 0);
375 }
376
377 if (result == ISC_R_SUCCESS) {
378 destination.file.stream = stderr;
379 destination.file.name = NULL;
380 destination.file.versions = ISC_LOG_ROLLNEVER;
381 destination.file.maximum_size = 0;
382 result = isc_log_createchannel(lcfg, "default_stderr",
383 ISC_LOG_TOFILEDESC,
384 level,
385 &destination,
386 ISC_LOG_PRINTTIME);
387 }
388
389 if (result == ISC_R_SUCCESS) {
390 /*
391 * Set the default category's channel to default_stderr,
392 * which is at the head of the channels list because it was
393 * just created.
394 */
395 default_channel.channel = ISC_LIST_HEAD(lcfg->channels);
396
397 destination.file.stream = stderr;
398 destination.file.name = NULL;
399 destination.file.versions = ISC_LOG_ROLLNEVER;
400 destination.file.maximum_size = 0;
401 result = isc_log_createchannel(lcfg, "default_debug",
402 ISC_LOG_TOFILEDESC,
403 ISC_LOG_DYNAMIC,
404 &destination,
405 ISC_LOG_PRINTTIME);
406 }
407
408 if (result == ISC_R_SUCCESS)
409 result = isc_log_createchannel(lcfg, "null",
410 ISC_LOG_TONULL,
411 ISC_LOG_DYNAMIC,
412 NULL, 0);
413
414 if (result == ISC_R_SUCCESS)
415 *lcfgp = lcfg;
416
417 else
418 if (lcfg != NULL)
419 isc_logconfig_destroy(&lcfg);
420
421 return (result);
422 }
423
424 isc_logconfig_t *
isc_logconfig_get(isc_log_t * lctx)425 isc_logconfig_get(isc_log_t *lctx) {
426 REQUIRE(VALID_CONTEXT(lctx));
427
428 ENSURE(lctx->logconfig != NULL);
429
430 return (lctx->logconfig);
431 }
432
433 isc_result_t
isc_logconfig_use(isc_log_t * lctx,isc_logconfig_t * lcfg)434 isc_logconfig_use(isc_log_t *lctx, isc_logconfig_t *lcfg) {
435 isc_logconfig_t *old_cfg;
436 isc_result_t result;
437
438 REQUIRE(VALID_CONTEXT(lctx));
439 REQUIRE(VALID_CONFIG(lcfg));
440 REQUIRE(lcfg->lctx == lctx);
441
442 /*
443 * Ensure that lcfg->channellist_count == lctx->category_count.
444 * They won't be equal if isc_log_usechannel has not been called
445 * since any call to isc_log_registercategories.
446 */
447 result = sync_channellist(lcfg);
448 if (result != ISC_R_SUCCESS)
449 return (result);
450
451 LOCK(&lctx->lock);
452
453 old_cfg = lctx->logconfig;
454 lctx->logconfig = lcfg;
455
456 UNLOCK(&lctx->lock);
457
458 isc_logconfig_destroy(&old_cfg);
459
460 return (ISC_R_SUCCESS);
461 }
462
463 void
isc_log_destroy(isc_log_t ** lctxp)464 isc_log_destroy(isc_log_t **lctxp) {
465 isc_log_t *lctx;
466 isc_logconfig_t *lcfg;
467 isc_mem_t *mctx;
468 isc_logmessage_t *message;
469
470 REQUIRE(lctxp != NULL && VALID_CONTEXT(*lctxp));
471
472 lctx = *lctxp;
473 mctx = lctx->mctx;
474
475 if (lctx->logconfig != NULL) {
476 lcfg = lctx->logconfig;
477 lctx->logconfig = NULL;
478 isc_logconfig_destroy(&lcfg);
479 }
480
481 DESTROYLOCK(&lctx->lock);
482
483 while ((message = ISC_LIST_HEAD(lctx->messages)) != NULL) {
484 ISC_LIST_UNLINK(lctx->messages, message, link);
485
486 isc_mem_put(mctx, message,
487 sizeof(*message) + strlen(message->text) + 1);
488 }
489
490 lctx->buffer[0] = '\0';
491 lctx->debug_level = 0;
492 lctx->categories = NULL;
493 lctx->category_count = 0;
494 lctx->modules = NULL;
495 lctx->module_count = 0;
496 lctx->mctx = NULL;
497 lctx->magic = 0;
498
499 isc_mem_put(mctx, lctx, sizeof(*lctx));
500
501 *lctxp = NULL;
502 }
503
504 void
isc_logconfig_destroy(isc_logconfig_t ** lcfgp)505 isc_logconfig_destroy(isc_logconfig_t **lcfgp) {
506 isc_logconfig_t *lcfg;
507 isc_mem_t *mctx;
508 isc_logchannel_t *channel;
509 isc_logchannellist_t *item;
510 char *filename;
511 unsigned int i;
512
513 REQUIRE(lcfgp != NULL && VALID_CONFIG(*lcfgp));
514
515 lcfg = *lcfgp;
516
517 /*
518 * This function cannot be called with a logconfig that is in
519 * use by a log context.
520 */
521 REQUIRE(lcfg->lctx != NULL && lcfg->lctx->logconfig != lcfg);
522
523 mctx = lcfg->lctx->mctx;
524
525 while ((channel = ISC_LIST_HEAD(lcfg->channels)) != NULL) {
526 ISC_LIST_UNLINK(lcfg->channels, channel, link);
527
528 if (channel->type == ISC_LOG_TOFILE) {
529 /*
530 * The filename for the channel may have ultimately
531 * started its life in user-land as a const string,
532 * but in isc_log_createchannel it gets copied
533 * into writable memory and is not longer truly const.
534 */
535 DE_CONST(FILE_NAME(channel), filename);
536 isc_mem_free(mctx, filename);
537
538 if (FILE_STREAM(channel) != NULL)
539 (void)fclose(FILE_STREAM(channel));
540 }
541
542 isc_mem_free(mctx, channel->name);
543 isc_mem_put(mctx, channel, sizeof(*channel));
544 }
545
546 for (i = 0; i < lcfg->channellist_count; i++)
547 while ((item = ISC_LIST_HEAD(lcfg->channellists[i])) != NULL) {
548 ISC_LIST_UNLINK(lcfg->channellists[i], item, link);
549 isc_mem_put(mctx, item, sizeof(*item));
550 }
551
552 if (lcfg->channellist_count > 0)
553 isc_mem_put(mctx, lcfg->channellists,
554 lcfg->channellist_count *
555 sizeof(ISC_LIST(isc_logchannellist_t)));
556
557 lcfg->dynamic = ISC_FALSE;
558 if (lcfg->tag != NULL)
559 isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
560 lcfg->tag = NULL;
561 lcfg->highest_level = 0;
562 lcfg->duplicate_interval = 0;
563 lcfg->magic = 0;
564
565 isc_mem_put(mctx, lcfg, sizeof(*lcfg));
566
567 *lcfgp = NULL;
568 }
569
570 void
isc_log_registercategories(isc_log_t * lctx,isc_logcategory_t categories[])571 isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]) {
572 isc_logcategory_t *catp;
573
574 REQUIRE(VALID_CONTEXT(lctx));
575 REQUIRE(categories != NULL && categories[0].name != NULL);
576
577 /*
578 * XXXDCL This somewhat sleazy situation of using the last pointer
579 * in one category array to point to the next array exists because
580 * this registration function returns void and I didn't want to have
581 * change everything that used it by making it return an isc_result_t.
582 * It would need to do that if it had to allocate memory to store
583 * pointers to each array passed in.
584 */
585 if (lctx->categories == NULL)
586 lctx->categories = categories;
587
588 else {
589 /*
590 * Adjust the last (NULL) pointer of the already registered
591 * categories to point to the incoming array.
592 */
593 for (catp = lctx->categories; catp->name != NULL; )
594 if (catp->id == UINT_MAX)
595 /*
596 * The name pointer points to the next array.
597 * Ick.
598 */
599 DE_CONST(catp->name, catp);
600 else
601 catp++;
602
603 catp->name = (void *)categories;
604 catp->id = UINT_MAX;
605 }
606
607 /*
608 * Update the id number of the category with its new global id.
609 */
610 for (catp = categories; catp->name != NULL; catp++)
611 catp->id = lctx->category_count++;
612 }
613
614 isc_logcategory_t *
isc_log_categorybyname(isc_log_t * lctx,const char * name)615 isc_log_categorybyname(isc_log_t *lctx, const char *name) {
616 isc_logcategory_t *catp;
617
618 REQUIRE(VALID_CONTEXT(lctx));
619 REQUIRE(name != NULL);
620
621 for (catp = lctx->categories; catp->name != NULL; )
622 if (catp->id == UINT_MAX)
623 /*
624 * catp is neither modified nor returned to the
625 * caller, so removing its const qualifier is ok.
626 */
627 DE_CONST(catp->name, catp);
628 else {
629 if (strcmp(catp->name, name) == 0)
630 return (catp);
631 catp++;
632 }
633
634 return (NULL);
635 }
636
637 void
isc_log_registermodules(isc_log_t * lctx,isc_logmodule_t modules[])638 isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]) {
639 isc_logmodule_t *modp;
640
641 REQUIRE(VALID_CONTEXT(lctx));
642 REQUIRE(modules != NULL && modules[0].name != NULL);
643
644 /*
645 * XXXDCL This somewhat sleazy situation of using the last pointer
646 * in one category array to point to the next array exists because
647 * this registration function returns void and I didn't want to have
648 * change everything that used it by making it return an isc_result_t.
649 * It would need to do that if it had to allocate memory to store
650 * pointers to each array passed in.
651 */
652 if (lctx->modules == NULL)
653 lctx->modules = modules;
654
655 else {
656 /*
657 * Adjust the last (NULL) pointer of the already registered
658 * modules to point to the incoming array.
659 */
660 for (modp = lctx->modules; modp->name != NULL; )
661 if (modp->id == UINT_MAX)
662 /*
663 * The name pointer points to the next array.
664 * Ick.
665 */
666 DE_CONST(modp->name, modp);
667 else
668 modp++;
669
670 modp->name = (void *)modules;
671 modp->id = UINT_MAX;
672 }
673
674 /*
675 * Update the id number of the module with its new global id.
676 */
677 for (modp = modules; modp->name != NULL; modp++)
678 modp->id = lctx->module_count++;
679 }
680
681 isc_logmodule_t *
isc_log_modulebyname(isc_log_t * lctx,const char * name)682 isc_log_modulebyname(isc_log_t *lctx, const char *name) {
683 isc_logmodule_t *modp;
684
685 REQUIRE(VALID_CONTEXT(lctx));
686 REQUIRE(name != NULL);
687
688 for (modp = lctx->modules; modp->name != NULL; )
689 if (modp->id == UINT_MAX)
690 /*
691 * modp is neither modified nor returned to the
692 * caller, so removing its const qualifier is ok.
693 */
694 DE_CONST(modp->name, modp);
695 else {
696 if (strcmp(modp->name, name) == 0)
697 return (modp);
698 modp++;
699 }
700
701 return (NULL);
702 }
703
704 isc_result_t
isc_log_createchannel(isc_logconfig_t * lcfg,const char * name,unsigned int type,int level,const isc_logdestination_t * destination,unsigned int flags)705 isc_log_createchannel(isc_logconfig_t *lcfg, const char *name,
706 unsigned int type, int level,
707 const isc_logdestination_t *destination,
708 unsigned int flags)
709 {
710 isc_logchannel_t *channel;
711 isc_mem_t *mctx;
712
713 REQUIRE(VALID_CONFIG(lcfg));
714 REQUIRE(name != NULL);
715 REQUIRE(type == ISC_LOG_TOSYSLOG || type == ISC_LOG_TOFILE ||
716 type == ISC_LOG_TOFILEDESC || type == ISC_LOG_TONULL);
717 REQUIRE(destination != NULL || type == ISC_LOG_TONULL);
718 REQUIRE(level >= ISC_LOG_CRITICAL);
719 REQUIRE((flags &
720 (unsigned int)~(ISC_LOG_PRINTALL | ISC_LOG_DEBUGONLY)) == 0);
721
722 /* XXXDCL find duplicate names? */
723
724 mctx = lcfg->lctx->mctx;
725
726 channel = isc_mem_get(mctx, sizeof(*channel));
727 if (channel == NULL)
728 return (ISC_R_NOMEMORY);
729
730 channel->name = isc_mem_strdup(mctx, name);
731 if (channel->name == NULL) {
732 isc_mem_put(mctx, channel, sizeof(*channel));
733 return (ISC_R_NOMEMORY);
734 }
735
736 channel->type = type;
737 channel->level = level;
738 channel->flags = flags;
739 ISC_LINK_INIT(channel, link);
740
741 switch (type) {
742 case ISC_LOG_TOSYSLOG:
743 FACILITY(channel) = destination->facility;
744 break;
745
746 case ISC_LOG_TOFILE:
747 /*
748 * The file name is copied because greatest_version wants
749 * to scribble on it, so it needs to be definitely in
750 * writable memory.
751 */
752 FILE_NAME(channel) =
753 isc_mem_strdup(mctx, destination->file.name);
754 FILE_STREAM(channel) = NULL;
755 FILE_VERSIONS(channel) = destination->file.versions;
756 FILE_MAXSIZE(channel) = destination->file.maximum_size;
757 FILE_MAXREACHED(channel) = ISC_FALSE;
758 break;
759
760 case ISC_LOG_TOFILEDESC:
761 FILE_NAME(channel) = NULL;
762 FILE_STREAM(channel) = destination->file.stream;
763 FILE_MAXSIZE(channel) = 0;
764 FILE_VERSIONS(channel) = ISC_LOG_ROLLNEVER;
765 break;
766
767 case ISC_LOG_TONULL:
768 /* Nothing. */
769 break;
770
771 default:
772 isc_mem_put(mctx, channel->name, strlen(channel->name) + 1);
773 isc_mem_put(mctx, channel, sizeof(*channel));
774 return (ISC_R_UNEXPECTED);
775 }
776
777 ISC_LIST_PREPEND(lcfg->channels, channel, link);
778
779 /*
780 * If default_stderr was redefined, make the default category
781 * point to the new default_stderr.
782 */
783 if (strcmp(name, "default_stderr") == 0)
784 default_channel.channel = channel;
785
786 return (ISC_R_SUCCESS);
787 }
788
789 isc_result_t
isc_log_usechannel(isc_logconfig_t * lcfg,const char * name,const isc_logcategory_t * category,const isc_logmodule_t * module)790 isc_log_usechannel(isc_logconfig_t *lcfg, const char *name,
791 const isc_logcategory_t *category,
792 const isc_logmodule_t *module)
793 {
794 isc_log_t *lctx;
795 isc_logchannel_t *channel;
796 isc_result_t result = ISC_R_SUCCESS;
797 unsigned int i;
798
799 REQUIRE(VALID_CONFIG(lcfg));
800 REQUIRE(name != NULL);
801
802 lctx = lcfg->lctx;
803
804 REQUIRE(category == NULL || category->id < lctx->category_count);
805 REQUIRE(module == NULL || module->id < lctx->module_count);
806
807 for (channel = ISC_LIST_HEAD(lcfg->channels); channel != NULL;
808 channel = ISC_LIST_NEXT(channel, link))
809 if (strcmp(name, channel->name) == 0)
810 break;
811
812 if (channel == NULL)
813 return (ISC_R_NOTFOUND);
814
815 if (category != NULL)
816 result = assignchannel(lcfg, category->id, module, channel);
817
818 else
819 /*
820 * Assign to all categories. Note that this includes
821 * the default channel.
822 */
823 for (i = 0; i < lctx->category_count; i++) {
824 result = assignchannel(lcfg, i, module, channel);
825 if (result != ISC_R_SUCCESS)
826 break;
827 }
828
829 return (result);
830 }
831
832 void
isc_log_write(isc_log_t * lctx,isc_logcategory_t * category,isc_logmodule_t * module,int level,const char * format,...)833 isc_log_write(isc_log_t *lctx, isc_logcategory_t *category,
834 isc_logmodule_t *module, int level, const char *format, ...)
835 {
836 va_list args;
837
838 /*
839 * Contract checking is done in isc_log_doit().
840 */
841
842 va_start(args, format);
843 isc_log_doit(lctx, category, module, level, ISC_FALSE,
844 NULL, 0, 0, format, args);
845 va_end(args);
846 }
847
848 void
isc_log_vwrite(isc_log_t * lctx,isc_logcategory_t * category,isc_logmodule_t * module,int level,const char * format,va_list args)849 isc_log_vwrite(isc_log_t *lctx, isc_logcategory_t *category,
850 isc_logmodule_t *module, int level,
851 const char *format, va_list args)
852 {
853 /*
854 * Contract checking is done in isc_log_doit().
855 */
856 isc_log_doit(lctx, category, module, level, ISC_FALSE,
857 NULL, 0, 0, format, args);
858 }
859
860 void
isc_log_write1(isc_log_t * lctx,isc_logcategory_t * category,isc_logmodule_t * module,int level,const char * format,...)861 isc_log_write1(isc_log_t *lctx, isc_logcategory_t *category,
862 isc_logmodule_t *module, int level, const char *format, ...)
863 {
864 va_list args;
865
866 /*
867 * Contract checking is done in isc_log_doit().
868 */
869
870 va_start(args, format);
871 isc_log_doit(lctx, category, module, level, ISC_TRUE,
872 NULL, 0, 0, format, args);
873 va_end(args);
874 }
875
876 void
isc_log_vwrite1(isc_log_t * lctx,isc_logcategory_t * category,isc_logmodule_t * module,int level,const char * format,va_list args)877 isc_log_vwrite1(isc_log_t *lctx, isc_logcategory_t *category,
878 isc_logmodule_t *module, int level,
879 const char *format, va_list args)
880 {
881 /*
882 * Contract checking is done in isc_log_doit().
883 */
884 isc_log_doit(lctx, category, module, level, ISC_TRUE,
885 NULL, 0, 0, format, args);
886 }
887
888 void
isc_log_iwrite(isc_log_t * lctx,isc_logcategory_t * category,isc_logmodule_t * module,int level,isc_msgcat_t * msgcat,int msgset,int msg,const char * format,...)889 isc_log_iwrite(isc_log_t *lctx, isc_logcategory_t *category,
890 isc_logmodule_t *module, int level,
891 isc_msgcat_t *msgcat, int msgset, int msg,
892 const char *format, ...)
893 {
894 va_list args;
895
896 /*
897 * Contract checking is done in isc_log_doit().
898 */
899
900 va_start(args, format);
901 isc_log_doit(lctx, category, module, level, ISC_FALSE,
902 msgcat, msgset, msg, format, args);
903 va_end(args);
904 }
905
906 void
isc_log_ivwrite(isc_log_t * lctx,isc_logcategory_t * category,isc_logmodule_t * module,int level,isc_msgcat_t * msgcat,int msgset,int msg,const char * format,va_list args)907 isc_log_ivwrite(isc_log_t *lctx, isc_logcategory_t *category,
908 isc_logmodule_t *module, int level,
909 isc_msgcat_t *msgcat, int msgset, int msg,
910 const char *format, va_list args)
911 {
912 /*
913 * Contract checking is done in isc_log_doit().
914 */
915 isc_log_doit(lctx, category, module, level, ISC_FALSE,
916 msgcat, msgset, msg, format, args);
917 }
918
919 void
isc_log_iwrite1(isc_log_t * lctx,isc_logcategory_t * category,isc_logmodule_t * module,int level,isc_msgcat_t * msgcat,int msgset,int msg,const char * format,...)920 isc_log_iwrite1(isc_log_t *lctx, isc_logcategory_t *category,
921 isc_logmodule_t *module, int level,
922 isc_msgcat_t *msgcat, int msgset, int msg,
923 const char *format, ...)
924 {
925 va_list args;
926
927 /*
928 * Contract checking is done in isc_log_doit().
929 */
930
931 va_start(args, format);
932 isc_log_doit(lctx, category, module, level, ISC_TRUE,
933 msgcat, msgset, msg, format, args);
934 va_end(args);
935 }
936
937 void
isc_log_ivwrite1(isc_log_t * lctx,isc_logcategory_t * category,isc_logmodule_t * module,int level,isc_msgcat_t * msgcat,int msgset,int msg,const char * format,va_list args)938 isc_log_ivwrite1(isc_log_t *lctx, isc_logcategory_t *category,
939 isc_logmodule_t *module, int level,
940 isc_msgcat_t *msgcat, int msgset, int msg,
941 const char *format, va_list args)
942 {
943 /*
944 * Contract checking is done in isc_log_doit().
945 */
946 isc_log_doit(lctx, category, module, level, ISC_TRUE,
947 msgcat, msgset, msg, format, args);
948 }
949
950 void
isc_log_setcontext(isc_log_t * lctx)951 isc_log_setcontext(isc_log_t *lctx) {
952 isc_lctx = lctx;
953 }
954
955 void
isc_log_setdebuglevel(isc_log_t * lctx,unsigned int level)956 isc_log_setdebuglevel(isc_log_t *lctx, unsigned int level) {
957 isc_logchannel_t *channel;
958
959 REQUIRE(VALID_CONTEXT(lctx));
960
961 LOCK(&lctx->lock);
962
963 lctx->debug_level = level;
964 /*
965 * Close ISC_LOG_DEBUGONLY channels if level is zero.
966 */
967 if (lctx->debug_level == 0)
968 for (channel = ISC_LIST_HEAD(lctx->logconfig->channels);
969 channel != NULL;
970 channel = ISC_LIST_NEXT(channel, link))
971 if (channel->type == ISC_LOG_TOFILE &&
972 (channel->flags & ISC_LOG_DEBUGONLY) != 0 &&
973 FILE_STREAM(channel) != NULL) {
974 (void)fclose(FILE_STREAM(channel));
975 FILE_STREAM(channel) = NULL;
976 }
977 UNLOCK(&lctx->lock);
978 }
979
980 unsigned int
isc_log_getdebuglevel(isc_log_t * lctx)981 isc_log_getdebuglevel(isc_log_t *lctx) {
982 REQUIRE(VALID_CONTEXT(lctx));
983
984 return (lctx->debug_level);
985 }
986
987 void
isc_log_setduplicateinterval(isc_logconfig_t * lcfg,unsigned int interval)988 isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval) {
989 REQUIRE(VALID_CONFIG(lcfg));
990
991 lcfg->duplicate_interval = interval;
992 }
993
994 unsigned int
isc_log_getduplicateinterval(isc_logconfig_t * lcfg)995 isc_log_getduplicateinterval(isc_logconfig_t *lcfg) {
996 REQUIRE(VALID_CONTEXT(lcfg));
997
998 return (lcfg->duplicate_interval);
999 }
1000
1001 isc_result_t
isc_log_settag(isc_logconfig_t * lcfg,const char * tag)1002 isc_log_settag(isc_logconfig_t *lcfg, const char *tag) {
1003 REQUIRE(VALID_CONFIG(lcfg));
1004
1005 if (tag != NULL && *tag != '\0') {
1006 if (lcfg->tag != NULL)
1007 isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
1008 lcfg->tag = isc_mem_strdup(lcfg->lctx->mctx, tag);
1009 if (lcfg->tag == NULL)
1010 return (ISC_R_NOMEMORY);
1011
1012 } else {
1013 if (lcfg->tag != NULL)
1014 isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
1015 lcfg->tag = NULL;
1016 }
1017
1018 return (ISC_R_SUCCESS);
1019 }
1020
1021 char *
isc_log_gettag(isc_logconfig_t * lcfg)1022 isc_log_gettag(isc_logconfig_t *lcfg) {
1023 REQUIRE(VALID_CONFIG(lcfg));
1024
1025 return (lcfg->tag);
1026 }
1027
1028 /* XXXDCL NT -- This interface will assuredly be changing. */
1029 void
isc_log_opensyslog(const char * tag,int options,int facility)1030 isc_log_opensyslog(const char *tag, int options, int facility) {
1031 (void)openlog(tag, options, facility);
1032 }
1033
1034 void
isc_log_closefilelogs(isc_log_t * lctx)1035 isc_log_closefilelogs(isc_log_t *lctx) {
1036 isc_logchannel_t *channel;
1037
1038 REQUIRE(VALID_CONTEXT(lctx));
1039
1040 LOCK(&lctx->lock);
1041 for (channel = ISC_LIST_HEAD(lctx->logconfig->channels);
1042 channel != NULL;
1043 channel = ISC_LIST_NEXT(channel, link))
1044
1045 if (channel->type == ISC_LOG_TOFILE &&
1046 FILE_STREAM(channel) != NULL) {
1047 (void)fclose(FILE_STREAM(channel));
1048 FILE_STREAM(channel) = NULL;
1049 }
1050 UNLOCK(&lctx->lock);
1051 }
1052
1053 /****
1054 **** Internal functions
1055 ****/
1056
1057 static isc_result_t
assignchannel(isc_logconfig_t * lcfg,unsigned int category_id,const isc_logmodule_t * module,isc_logchannel_t * channel)1058 assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
1059 const isc_logmodule_t *module, isc_logchannel_t *channel)
1060 {
1061 isc_logchannellist_t *new_item;
1062 isc_log_t *lctx;
1063 isc_result_t result;
1064
1065 REQUIRE(VALID_CONFIG(lcfg));
1066
1067 lctx = lcfg->lctx;
1068
1069 REQUIRE(category_id < lctx->category_count);
1070 REQUIRE(module == NULL || module->id < lctx->module_count);
1071 REQUIRE(channel != NULL);
1072
1073 /*
1074 * Ensure lcfg->channellist_count == lctx->category_count.
1075 */
1076 result = sync_channellist(lcfg);
1077 if (result != ISC_R_SUCCESS)
1078 return (result);
1079
1080 new_item = isc_mem_get(lctx->mctx, sizeof(*new_item));
1081 if (new_item == NULL)
1082 return (ISC_R_NOMEMORY);
1083
1084 new_item->channel = channel;
1085 new_item->module = module;
1086 ISC_LIST_INITANDPREPEND(lcfg->channellists[category_id],
1087 new_item, link);
1088
1089 /*
1090 * Remember the highest logging level set by any channel in the
1091 * logging config, so isc_log_doit() can quickly return if the
1092 * message is too high to be logged by any channel.
1093 */
1094 if (channel->type != ISC_LOG_TONULL) {
1095 if (lcfg->highest_level < channel->level)
1096 lcfg->highest_level = channel->level;
1097 if (channel->level == ISC_LOG_DYNAMIC)
1098 lcfg->dynamic = ISC_TRUE;
1099 }
1100
1101 return (ISC_R_SUCCESS);
1102 }
1103
1104 /*
1105 * This would ideally be part of isc_log_registercategories(), except then
1106 * that function would have to return isc_result_t instead of void.
1107 */
1108 static isc_result_t
sync_channellist(isc_logconfig_t * lcfg)1109 sync_channellist(isc_logconfig_t *lcfg) {
1110 unsigned int bytes;
1111 isc_log_t *lctx;
1112 void *lists;
1113
1114 REQUIRE(VALID_CONFIG(lcfg));
1115
1116 lctx = lcfg->lctx;
1117
1118 REQUIRE(lctx->category_count != 0);
1119
1120 if (lctx->category_count == lcfg->channellist_count)
1121 return (ISC_R_SUCCESS);
1122
1123 bytes = lctx->category_count * sizeof(ISC_LIST(isc_logchannellist_t));
1124
1125 lists = isc_mem_get(lctx->mctx, bytes);
1126
1127 if (lists == NULL)
1128 return (ISC_R_NOMEMORY);
1129
1130 memset(lists, 0, bytes);
1131
1132 if (lcfg->channellist_count != 0) {
1133 bytes = lcfg->channellist_count *
1134 sizeof(ISC_LIST(isc_logchannellist_t));
1135 memcpy(lists, lcfg->channellists, bytes);
1136 isc_mem_put(lctx->mctx, lcfg->channellists, bytes);
1137 }
1138
1139 lcfg->channellists = lists;
1140 lcfg->channellist_count = lctx->category_count;
1141
1142 return (ISC_R_SUCCESS);
1143 }
1144
1145 static isc_result_t
greatest_version(isc_logchannel_t * channel,int * greatestp)1146 greatest_version(isc_logchannel_t *channel, int *greatestp) {
1147 /* XXXDCL HIGHLY NT */
1148 char *basenam, *digit_end;
1149 const char *dirname;
1150 int version, greatest = -1;
1151 size_t basenamelen;
1152 isc_dir_t dir;
1153 isc_result_t result;
1154 char sep = '/';
1155 #ifdef _WIN32
1156 char *basename2;
1157 #endif
1158
1159 REQUIRE(channel->type == ISC_LOG_TOFILE);
1160
1161 /*
1162 * It is safe to DE_CONST the file.name because it was copied
1163 * with isc_mem_strdup in isc_log_createchannel.
1164 */
1165 basenam = strrchr(FILE_NAME(channel), sep);
1166 #ifdef _WIN32
1167 basename2 = strrchr(FILE_NAME(channel), '\\');
1168 if ((basenam != NULL && basename2 != NULL && basename2 > basenam) ||
1169 (basenam == NULL && basename2 != NULL)) {
1170 basenam = basename2;
1171 sep = '\\';
1172 }
1173 #endif
1174 if (basenam != NULL) {
1175 *basenam++ = '\0';
1176 dirname = FILE_NAME(channel);
1177 } else {
1178 DE_CONST(FILE_NAME(channel), basenam);
1179 dirname = ".";
1180 }
1181 basenamelen = strlen(basenam);
1182
1183 isc_dir_init(&dir);
1184 result = isc_dir_open(&dir, dirname);
1185
1186 /*
1187 * Replace the file separator if it was taken out.
1188 */
1189 if (basenam != FILE_NAME(channel))
1190 *(basenam - 1) = sep;
1191
1192 /*
1193 * Return if the directory open failed.
1194 */
1195 if (result != ISC_R_SUCCESS)
1196 return (result);
1197
1198 while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
1199 if (dir.entry.length > basenamelen &&
1200 strncmp(dir.entry.name, basenam, basenamelen) == 0 &&
1201 dir.entry.name[basenamelen] == '.') {
1202
1203 version = strtol(&dir.entry.name[basenamelen + 1],
1204 &digit_end, 10);
1205 if (*digit_end == '\0' && version > greatest)
1206 greatest = version;
1207 }
1208 }
1209 isc_dir_close(&dir);
1210
1211 *greatestp = ++greatest;
1212
1213 return (ISC_R_SUCCESS);
1214 }
1215
1216 static isc_result_t
roll_log(isc_logchannel_t * channel)1217 roll_log(isc_logchannel_t *channel) {
1218 int i, n, greatest;
1219 char current[PATH_MAX + 1];
1220 char new[PATH_MAX + 1];
1221 const char *path;
1222 isc_result_t result;
1223
1224 /*
1225 * Do nothing (not even excess version trimming) if ISC_LOG_ROLLNEVER
1226 * is specified. Apparently complete external control over the log
1227 * files is desired.
1228 */
1229 if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER)
1230 return (ISC_R_SUCCESS);
1231
1232 path = FILE_NAME(channel);
1233
1234 /*
1235 * Set greatest_version to the greatest existing version
1236 * (not the maximum requested version). This is 1 based even
1237 * though the file names are 0 based, so an oldest log of log.1
1238 * is a greatest_version of 2.
1239 */
1240 result = greatest_version(channel, &greatest);
1241 if (result != ISC_R_SUCCESS)
1242 return (result);
1243
1244 /*
1245 * Now greatest should be set to the highest version number desired.
1246 * Since the highest number is one less than FILE_VERSIONS(channel)
1247 * when not doing infinite log rolling, greatest will need to be
1248 * decremented when it is equal to -- or greater than --
1249 * FILE_VERSIONS(channel). When greatest is less than
1250 * FILE_VERSIONS(channel), it is already suitable for use as
1251 * the maximum version number.
1252 */
1253
1254 if (FILE_VERSIONS(channel) == ISC_LOG_ROLLINFINITE ||
1255 FILE_VERSIONS(channel) > greatest)
1256 ; /* Do nothing. */
1257 else
1258 /*
1259 * When greatest is >= FILE_VERSIONS(channel), it needs to
1260 * be reduced until it is FILE_VERSIONS(channel) - 1.
1261 * Remove any excess logs on the way to that value.
1262 */
1263 while (--greatest >= FILE_VERSIONS(channel)) {
1264 n = snprintf(current, sizeof(current), "%s.%d",
1265 path, greatest);
1266 if (n >= (int)sizeof(current) || n < 0)
1267 result = ISC_R_NOSPACE;
1268 else
1269 result = isc_file_remove(current);
1270 if (result != ISC_R_SUCCESS &&
1271 result != ISC_R_FILENOTFOUND)
1272 syslog(LOG_ERR,
1273 "unable to remove log file '%s.%d': %s",
1274 path, greatest,
1275 isc_result_totext(result));
1276 }
1277
1278 for (i = greatest; i > 0; i--) {
1279 result = ISC_R_SUCCESS;
1280 n = snprintf(current, sizeof(current), "%s.%d", path, i - 1);
1281 if (n >= (int)sizeof(current) || n < 0)
1282 result = ISC_R_NOSPACE;
1283 if (result == ISC_R_SUCCESS) {
1284 n = snprintf(new, sizeof(new), "%s.%d", path, i);
1285 if (n >= (int)sizeof(new) || n < 0)
1286 result = ISC_R_NOSPACE;
1287 }
1288 if (result == ISC_R_SUCCESS)
1289 result = isc_file_rename(current, new);
1290 if (result != ISC_R_SUCCESS &&
1291 result != ISC_R_FILENOTFOUND)
1292 syslog(LOG_ERR,
1293 "unable to rename log file '%s.%d' to "
1294 "'%s.%d': %s", path, i - 1, path, i,
1295 isc_result_totext(result));
1296 }
1297
1298 if (FILE_VERSIONS(channel) != 0) {
1299 n = snprintf(new, sizeof(new), "%s.0", path);
1300 if (n >= (int)sizeof(new) || n < 0)
1301 result = ISC_R_NOSPACE;
1302 else
1303 result = isc_file_rename(path, new);
1304 if (result != ISC_R_SUCCESS &&
1305 result != ISC_R_FILENOTFOUND)
1306 syslog(LOG_ERR,
1307 "unable to rename log file '%s' to '%s.0': %s",
1308 path, path, isc_result_totext(result));
1309 } else {
1310 result = isc_file_remove(path);
1311 if (result != ISC_R_SUCCESS &&
1312 result != ISC_R_FILENOTFOUND)
1313 syslog(LOG_ERR, "unable to remove log file '%s': %s",
1314 path, isc_result_totext(result));
1315 }
1316
1317 return (ISC_R_SUCCESS);
1318 }
1319
1320 static isc_result_t
isc_log_open(isc_logchannel_t * channel)1321 isc_log_open(isc_logchannel_t *channel) {
1322 struct stat statbuf;
1323 isc_boolean_t regular_file;
1324 isc_boolean_t roll = ISC_FALSE;
1325 isc_result_t result = ISC_R_SUCCESS;
1326 const char *path;
1327
1328 REQUIRE(channel->type == ISC_LOG_TOFILE);
1329 REQUIRE(FILE_STREAM(channel) == NULL);
1330
1331 path = FILE_NAME(channel);
1332
1333 REQUIRE(path != NULL && *path != '\0');
1334
1335 /*
1336 * Determine type of file; only regular files will be
1337 * version renamed, and only if the base file exists
1338 * and either has no size limit or has reached its size limit.
1339 */
1340 if (stat(path, &statbuf) == 0) {
1341 regular_file = S_ISREG(statbuf.st_mode) ? ISC_TRUE : ISC_FALSE;
1342 /* XXXDCL if not regular_file complain? */
1343 if ((FILE_MAXSIZE(channel) == 0 &&
1344 FILE_VERSIONS(channel) != ISC_LOG_ROLLNEVER) ||
1345 (FILE_MAXSIZE(channel) > 0 &&
1346 statbuf.st_size >= FILE_MAXSIZE(channel)))
1347 roll = regular_file;
1348 } else if (errno == ENOENT) {
1349 regular_file = ISC_TRUE;
1350 POST(regular_file);
1351 } else
1352 result = ISC_R_INVALIDFILE;
1353
1354 /*
1355 * Version control.
1356 */
1357 if (result == ISC_R_SUCCESS && roll) {
1358 if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER)
1359 return (ISC_R_MAXSIZE);
1360 result = roll_log(channel);
1361 if (result != ISC_R_SUCCESS) {
1362 if ((channel->flags & ISC_LOG_OPENERR) == 0) {
1363 syslog(LOG_ERR,
1364 "isc_log_open: roll_log '%s' "
1365 "failed: %s",
1366 FILE_NAME(channel),
1367 isc_result_totext(result));
1368 channel->flags |= ISC_LOG_OPENERR;
1369 }
1370 return (result);
1371 }
1372 }
1373
1374 result = isc_stdio_open(path, "a", &FILE_STREAM(channel));
1375
1376 return (result);
1377 }
1378
1379 isc_boolean_t
isc_log_wouldlog(isc_log_t * lctx,int level)1380 isc_log_wouldlog(isc_log_t *lctx, int level) {
1381 /*
1382 * Try to avoid locking the mutex for messages which can't
1383 * possibly be logged to any channels -- primarily debugging
1384 * messages that the debug level is not high enough to print.
1385 *
1386 * If the level is (mathematically) less than or equal to the
1387 * highest_level, or if there is a dynamic channel and the level is
1388 * less than or equal to the debug level, the main loop must be
1389 * entered to see if the message should really be output.
1390 *
1391 * NOTE: this is UNLOCKED access to the logconfig. However,
1392 * the worst thing that can happen is that a bad decision is made
1393 * about returning without logging, and that's not a big concern,
1394 * because that's a risk anyway if the logconfig is being
1395 * dynamically changed.
1396 */
1397
1398 if (lctx == NULL || lctx->logconfig == NULL)
1399 return (ISC_FALSE);
1400
1401 return (ISC_TF(level <= lctx->logconfig->highest_level ||
1402 (lctx->logconfig->dynamic &&
1403 level <= lctx->debug_level)));
1404 }
1405
1406 static void
isc_log_doit(isc_log_t * lctx,isc_logcategory_t * category,isc_logmodule_t * module,int level,isc_boolean_t write_once,isc_msgcat_t * msgcat,int msgset,int msg,const char * format,va_list args)1407 isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
1408 isc_logmodule_t *module, int level, isc_boolean_t write_once,
1409 isc_msgcat_t *msgcat, int msgset, int msg,
1410 const char *format, va_list args)
1411 {
1412 int syslog_level;
1413 char time_string[64];
1414 char level_string[24];
1415 size_t octets;
1416 const char *iformat;
1417 struct stat statbuf;
1418 isc_boolean_t matched = ISC_FALSE;
1419 isc_boolean_t printtime, printtag;
1420 isc_boolean_t printcategory, printmodule, printlevel;
1421 isc_logconfig_t *lcfg;
1422 isc_logchannel_t *channel;
1423 isc_logchannellist_t *category_channels;
1424 isc_result_t result;
1425
1426 REQUIRE(lctx == NULL || VALID_CONTEXT(lctx));
1427 REQUIRE(category != NULL);
1428 REQUIRE(module != NULL);
1429 REQUIRE(level != ISC_LOG_DYNAMIC);
1430 REQUIRE(format != NULL);
1431
1432 /*
1433 * Programs can use libraries that use this logging code without
1434 * wanting to do any logging, thus the log context is allowed to
1435 * be non-existent.
1436 */
1437 if (lctx == NULL)
1438 return;
1439
1440 REQUIRE(category->id < lctx->category_count);
1441 REQUIRE(module->id < lctx->module_count);
1442
1443 if (! isc_log_wouldlog(lctx, level))
1444 return;
1445
1446 if (msgcat != NULL)
1447 iformat = isc_msgcat_get(msgcat, msgset, msg, format);
1448 else
1449 iformat = format;
1450
1451 time_string[0] = '\0';
1452 level_string[0] = '\0';
1453
1454 LOCK(&lctx->lock);
1455
1456 lctx->buffer[0] = '\0';
1457
1458 lcfg = lctx->logconfig;
1459
1460 category_channels = ISC_LIST_HEAD(lcfg->channellists[category->id]);
1461
1462 /*
1463 * XXXDCL add duplicate filtering? (To not write multiple times to
1464 * the same source via various channels).
1465 */
1466 do {
1467 /*
1468 * If the channel list end was reached and a match was made,
1469 * everything is finished.
1470 */
1471 if (category_channels == NULL && matched)
1472 break;
1473
1474 if (category_channels == NULL && ! matched &&
1475 category_channels != ISC_LIST_HEAD(lcfg->channellists[0]))
1476 /*
1477 * No category/module pair was explicitly configured.
1478 * Try the category named "default".
1479 */
1480 category_channels =
1481 ISC_LIST_HEAD(lcfg->channellists[0]);
1482
1483 if (category_channels == NULL && ! matched)
1484 /*
1485 * No matching module was explicitly configured
1486 * for the category named "default". Use the internal
1487 * default channel.
1488 */
1489 category_channels = &default_channel;
1490
1491 if (category_channels->module != NULL &&
1492 category_channels->module != module) {
1493 category_channels = ISC_LIST_NEXT(category_channels,
1494 link);
1495 continue;
1496 }
1497
1498 matched = ISC_TRUE;
1499
1500 channel = category_channels->channel;
1501 category_channels = ISC_LIST_NEXT(category_channels, link);
1502
1503 if (((channel->flags & ISC_LOG_DEBUGONLY) != 0) &&
1504 lctx->debug_level == 0)
1505 continue;
1506
1507 if (channel->level == ISC_LOG_DYNAMIC) {
1508 if (lctx->debug_level < level)
1509 continue;
1510 } else if (channel->level < level)
1511 continue;
1512
1513 if ((channel->flags & ISC_LOG_PRINTTIME) != 0 &&
1514 time_string[0] == '\0') {
1515 isc_time_t isctime;
1516
1517 TIME_NOW(&isctime);
1518 isc_time_formattimestamp(&isctime, time_string,
1519 sizeof(time_string));
1520 }
1521
1522 if ((channel->flags & ISC_LOG_PRINTLEVEL) != 0 &&
1523 level_string[0] == '\0') {
1524 if (level < ISC_LOG_CRITICAL)
1525 snprintf(level_string, sizeof(level_string),
1526 "%s %d: ",
1527 isc_msgcat_get(isc_msgcat,
1528 ISC_MSGSET_LOG,
1529 ISC_MSG_LEVEL,
1530 "level"),
1531 level);
1532 else if (level > ISC_LOG_DYNAMIC)
1533 snprintf(level_string, sizeof(level_string),
1534 "%s %d: ", log_level_strings[0],
1535 level);
1536 else
1537 snprintf(level_string, sizeof(level_string),
1538 "%s: ", log_level_strings[-level]);
1539 }
1540
1541 /*
1542 * Only format the message once.
1543 */
1544 if (lctx->buffer[0] == '\0') {
1545 (void)vsnprintf(lctx->buffer, sizeof(lctx->buffer),
1546 iformat, args);
1547
1548 /*
1549 * Check for duplicates.
1550 */
1551 if (write_once) {
1552 isc_logmessage_t *message, *new;
1553 isc_time_t oldest;
1554 isc_interval_t interval;
1555
1556 isc_interval_set(&interval,
1557 lcfg->duplicate_interval, 0);
1558
1559 /*
1560 * 'oldest' is the age of the oldest messages
1561 * which fall within the duplicate_interval
1562 * range.
1563 */
1564 TIME_NOW(&oldest);
1565 if (isc_time_subtract(&oldest, &interval, &oldest)
1566 != ISC_R_SUCCESS)
1567 /*
1568 * Can't effectively do the checking
1569 * without having a valid time.
1570 */
1571 message = NULL;
1572 else
1573 message =ISC_LIST_HEAD(lctx->messages);
1574
1575 while (message != NULL) {
1576 if (isc_time_compare(&message->time,
1577 &oldest) < 0) {
1578 /*
1579 * This message is older
1580 * than the duplicate_interval,
1581 * so it should be dropped from
1582 * the history.
1583 *
1584 * Setting the interval to be
1585 * to be longer will obviously
1586 * not cause the expired
1587 * message to spring back into
1588 * existence.
1589 */
1590 new = ISC_LIST_NEXT(message,
1591 link);
1592
1593 ISC_LIST_UNLINK(lctx->messages,
1594 message, link);
1595
1596 isc_mem_put(lctx->mctx,
1597 message,
1598 sizeof(*message) + 1 +
1599 strlen(message->text));
1600
1601 message = new;
1602 continue;
1603 }
1604
1605 /*
1606 * This message is in the duplicate
1607 * filtering interval ...
1608 */
1609 if (strcmp(lctx->buffer, message->text)
1610 == 0) {
1611 /*
1612 * ... and it is a duplicate.
1613 * Unlock the mutex and
1614 * get the hell out of Dodge.
1615 */
1616 UNLOCK(&lctx->lock);
1617 return;
1618 }
1619
1620 message = ISC_LIST_NEXT(message, link);
1621 }
1622
1623 /*
1624 * It wasn't in the duplicate interval,
1625 * so add it to the message list.
1626 */
1627 octets = strlen(lctx->buffer) + 1;
1628 new = isc_mem_get(lctx->mctx,
1629 sizeof(isc_logmessage_t) +
1630 octets);
1631 if (new != NULL) {
1632 /*
1633 * Put the text immediately after
1634 * the struct. The strcpy is safe.
1635 */
1636 new->text = (char *)(new + 1);
1637 strlcpy(new->text, lctx->buffer, octets);
1638
1639 TIME_NOW(&new->time);
1640
1641 ISC_LIST_APPEND(lctx->messages,
1642 new, link);
1643 }
1644 }
1645 }
1646
1647 printtime = ISC_TF((channel->flags & ISC_LOG_PRINTTIME)
1648 != 0);
1649 printtag = ISC_TF((channel->flags & ISC_LOG_PRINTTAG)
1650 != 0 && lcfg->tag != NULL);
1651 printcategory = ISC_TF((channel->flags & ISC_LOG_PRINTCATEGORY)
1652 != 0);
1653 printmodule = ISC_TF((channel->flags & ISC_LOG_PRINTMODULE)
1654 != 0);
1655 printlevel = ISC_TF((channel->flags & ISC_LOG_PRINTLEVEL)
1656 != 0);
1657
1658 switch (channel->type) {
1659 case ISC_LOG_TOFILE:
1660 if (FILE_MAXREACHED(channel)) {
1661 /*
1662 * If the file can be rolled, OR
1663 * If the file no longer exists, OR
1664 * If the file is less than the maximum size,
1665 * (such as if it had been renamed and
1666 * a new one touched, or it was truncated
1667 * in place)
1668 * ... then close it to trigger reopening.
1669 */
1670 if (FILE_VERSIONS(channel) !=
1671 ISC_LOG_ROLLNEVER ||
1672 (stat(FILE_NAME(channel), &statbuf) != 0 &&
1673 errno == ENOENT) ||
1674 statbuf.st_size < FILE_MAXSIZE(channel)) {
1675 (void)fclose(FILE_STREAM(channel));
1676 FILE_STREAM(channel) = NULL;
1677 FILE_MAXREACHED(channel) = ISC_FALSE;
1678 } else
1679 /*
1680 * Eh, skip it.
1681 */
1682 break;
1683 }
1684
1685 if (FILE_STREAM(channel) == NULL) {
1686 result = isc_log_open(channel);
1687 if (result != ISC_R_SUCCESS &&
1688 result != ISC_R_MAXSIZE &&
1689 (channel->flags & ISC_LOG_OPENERR) == 0) {
1690 syslog(LOG_ERR,
1691 "isc_log_open '%s' failed: %s",
1692 FILE_NAME(channel),
1693 isc_result_totext(result));
1694 channel->flags |= ISC_LOG_OPENERR;
1695 }
1696 if (result != ISC_R_SUCCESS)
1697 break;
1698 channel->flags &= ~ISC_LOG_OPENERR;
1699 }
1700 /* FALLTHROUGH */
1701
1702 case ISC_LOG_TOFILEDESC:
1703 fprintf(FILE_STREAM(channel), "%s%s%s%s%s%s%s%s%s%s\n",
1704 printtime ? time_string : "",
1705 printtime ? " " : "",
1706 printtag ? lcfg->tag : "",
1707 printtag ? ": " : "",
1708 printcategory ? category->name : "",
1709 printcategory ? ": " : "",
1710 printmodule ? (module != NULL ? module->name
1711 : "no_module")
1712 : "",
1713 printmodule ? ": " : "",
1714 printlevel ? level_string : "",
1715 lctx->buffer);
1716
1717 fflush(FILE_STREAM(channel));
1718
1719 /*
1720 * If the file now exceeds its maximum size
1721 * threshold, note it so that it will not be logged
1722 * to any more.
1723 */
1724 if (FILE_MAXSIZE(channel) > 0) {
1725 INSIST(channel->type == ISC_LOG_TOFILE);
1726
1727 /* XXXDCL NT fstat/fileno */
1728 /* XXXDCL complain if fstat fails? */
1729 if (fstat(fileno(FILE_STREAM(channel)),
1730 &statbuf) >= 0 &&
1731 statbuf.st_size > FILE_MAXSIZE(channel))
1732 FILE_MAXREACHED(channel) = ISC_TRUE;
1733 }
1734
1735 break;
1736
1737 case ISC_LOG_TOSYSLOG:
1738 if (level > 0)
1739 syslog_level = LOG_DEBUG;
1740 else if (level < ISC_LOG_CRITICAL)
1741 syslog_level = LOG_CRIT;
1742 else
1743 syslog_level = syslog_map[-level];
1744
1745 (void)syslog(FACILITY(channel) | syslog_level,
1746 "%s%s%s%s%s%s%s%s%s%s",
1747 printtime ? time_string : "",
1748 printtime ? " " : "",
1749 printtag ? lcfg->tag : "",
1750 printtag ? ": " : "",
1751 printcategory ? category->name : "",
1752 printcategory ? ": " : "",
1753 printmodule ? (module != NULL ? module->name
1754 : "no_module")
1755 : "",
1756 printmodule ? ": " : "",
1757 printlevel ? level_string : "",
1758 lctx->buffer);
1759 break;
1760
1761 case ISC_LOG_TONULL:
1762 break;
1763
1764 }
1765
1766 } while (1);
1767
1768 UNLOCK(&lctx->lock);
1769 }
1770