PageRenderTime 54ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/bind-9.9.1-P1/bin/named/logconf.c

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