"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/bin/named/logconf.c" (7 Sep 2020, 9372 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "logconf.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /* $Id: logconf.c,v 1.45 2011/03/05 23:52:29 tbox Exp $ */
   13 
   14 /*! \file */
   15 
   16 #include <config.h>
   17 
   18 #include <inttypes.h>
   19 #include <stdbool.h>
   20 
   21 #include <isc/file.h>
   22 #include <isc/offset.h>
   23 #include <isc/print.h>
   24 #include <isc/result.h>
   25 #include <isc/stdio.h>
   26 #include <isc/string.h>
   27 #include <isc/syslog.h>
   28 #include <isc/util.h>
   29 
   30 #include <isccfg/cfg.h>
   31 #include <isccfg/log.h>
   32 
   33 #include <named/log.h>
   34 #include <named/logconf.h>
   35 
   36 #define CHECK(op) \
   37     do { result = (op);                      \
   38            if (result != ISC_R_SUCCESS) goto cleanup;    \
   39     } while (0)
   40 
   41 /*%
   42  * Set up a logging category according to the named.conf data
   43  * in 'ccat' and add it to 'logconfig'.
   44  */
   45 static isc_result_t
   46 category_fromconf(const cfg_obj_t *ccat, isc_logconfig_t *logconfig) {
   47     isc_result_t result;
   48     const char *catname;
   49     isc_logcategory_t *category;
   50     isc_logmodule_t *module;
   51     const cfg_obj_t *destinations = NULL;
   52     const cfg_listelt_t *element = NULL;
   53 
   54     catname = cfg_obj_asstring(cfg_tuple_get(ccat, "name"));
   55     category = isc_log_categorybyname(ns_g_lctx, catname);
   56     if (category == NULL) {
   57         cfg_obj_log(ccat, ns_g_lctx, ISC_LOG_ERROR,
   58                 "unknown logging category '%s' ignored",
   59                 catname);
   60         /*
   61          * Allow further processing by returning success.
   62          */
   63         return (ISC_R_SUCCESS);
   64     }
   65 
   66     if (logconfig == NULL)
   67         return (ISC_R_SUCCESS);
   68 
   69     module = NULL;
   70 
   71     destinations = cfg_tuple_get(ccat, "destinations");
   72     for (element = cfg_list_first(destinations);
   73          element != NULL;
   74          element = cfg_list_next(element))
   75     {
   76         const cfg_obj_t *channel = cfg_listelt_value(element);
   77         const char *channelname = cfg_obj_asstring(channel);
   78 
   79         result = isc_log_usechannel(logconfig, channelname, category,
   80                         module);
   81         if (result != ISC_R_SUCCESS) {
   82             isc_log_write(ns_g_lctx, CFG_LOGCATEGORY_CONFIG,
   83                       NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
   84                       "logging channel '%s': %s", channelname,
   85                       isc_result_totext(result));
   86             return (result);
   87         }
   88     }
   89     return (ISC_R_SUCCESS);
   90 }
   91 
   92 /*%
   93  * Set up a logging channel according to the named.conf data
   94  * in 'cchan' and add it to 'logconfig'.
   95  */
   96 static isc_result_t
   97 channel_fromconf(const cfg_obj_t *channel, isc_logconfig_t *logconfig)
   98 {
   99     isc_result_t result;
  100     isc_logdestination_t dest;
  101     unsigned int type;
  102     unsigned int flags = 0;
  103     int level;
  104     const char *channelname;
  105     const cfg_obj_t *fileobj = NULL;
  106     const cfg_obj_t *syslogobj = NULL;
  107     const cfg_obj_t *nullobj = NULL;
  108     const cfg_obj_t *stderrobj = NULL;
  109     const cfg_obj_t *severity = NULL;
  110     int i;
  111 
  112     channelname = cfg_obj_asstring(cfg_map_getname(channel));
  113 
  114     (void)cfg_map_get(channel, "file", &fileobj);
  115     (void)cfg_map_get(channel, "syslog", &syslogobj);
  116     (void)cfg_map_get(channel, "null", &nullobj);
  117     (void)cfg_map_get(channel, "stderr", &stderrobj);
  118 
  119     i = 0;
  120     if (fileobj != NULL)
  121         i++;
  122     if (syslogobj != NULL)
  123         i++;
  124     if (nullobj != NULL)
  125         i++;
  126     if (stderrobj != NULL)
  127         i++;
  128 
  129     if (i != 1) {
  130         cfg_obj_log(channel, ns_g_lctx, ISC_LOG_ERROR,
  131                   "channel '%s': exactly one of file, syslog, "
  132                   "null, and stderr must be present", channelname);
  133         return (ISC_R_FAILURE);
  134     }
  135 
  136     type = ISC_LOG_TONULL;
  137 
  138     if (fileobj != NULL) {
  139         const cfg_obj_t *pathobj = cfg_tuple_get(fileobj, "file");
  140         const cfg_obj_t *sizeobj = cfg_tuple_get(fileobj, "size");
  141         const cfg_obj_t *versionsobj =
  142                  cfg_tuple_get(fileobj, "versions");
  143         int32_t versions = ISC_LOG_ROLLNEVER;
  144         isc_offset_t size = 0;
  145         uint64_t maxoffset;
  146 
  147         /*
  148          * isc_offset_t is a signed integer type, so the maximum
  149          * value is all 1s except for the MSB.
  150          */
  151         switch (sizeof(isc_offset_t)) {
  152         case 4:
  153             maxoffset = 0x7fffffffULL;
  154             break;
  155         case 8:
  156             maxoffset = 0x7fffffffffffffffULL;
  157             break;
  158         default:
  159             INSIST(0);
  160             ISC_UNREACHABLE();
  161         }
  162 
  163         type = ISC_LOG_TOFILE;
  164 
  165         if (versionsobj != NULL && cfg_obj_isuint32(versionsobj))
  166             versions = cfg_obj_asuint32(versionsobj);
  167         if (versionsobj != NULL && cfg_obj_isstring(versionsobj) &&
  168             strcasecmp(cfg_obj_asstring(versionsobj), "unlimited") == 0)
  169             versions = ISC_LOG_ROLLINFINITE;
  170         if (sizeobj != NULL &&
  171             cfg_obj_isuint64(sizeobj) &&
  172             cfg_obj_asuint64(sizeobj) < maxoffset)
  173             size = (isc_offset_t)cfg_obj_asuint64(sizeobj);
  174         dest.file.stream = NULL;
  175         dest.file.name = cfg_obj_asstring(pathobj);
  176         dest.file.versions = versions;
  177         dest.file.maximum_size = size;
  178     } else if (syslogobj != NULL) {
  179         int facility = LOG_DAEMON;
  180 
  181         type = ISC_LOG_TOSYSLOG;
  182 
  183         if (cfg_obj_isstring(syslogobj)) {
  184             const char *facilitystr = cfg_obj_asstring(syslogobj);
  185             (void)isc_syslog_facilityfromstring(facilitystr,
  186                                 &facility);
  187         }
  188         dest.facility = facility;
  189     } else if (stderrobj != NULL) {
  190         type = ISC_LOG_TOFILEDESC;
  191         dest.file.stream = stderr;
  192         dest.file.name = NULL;
  193         dest.file.versions = ISC_LOG_ROLLNEVER;
  194         dest.file.maximum_size = 0;
  195     }
  196 
  197     /*
  198      * Munge flags.
  199      */
  200     {
  201         const cfg_obj_t *printcat = NULL;
  202         const cfg_obj_t *printsev = NULL;
  203         const cfg_obj_t *printtime = NULL;
  204         const cfg_obj_t *buffered = NULL;
  205 
  206         (void)cfg_map_get(channel, "print-category", &printcat);
  207         (void)cfg_map_get(channel, "print-severity", &printsev);
  208         (void)cfg_map_get(channel, "print-time", &printtime);
  209         (void)cfg_map_get(channel, "buffered", &buffered);
  210 
  211         if (printcat != NULL && cfg_obj_asboolean(printcat))
  212             flags |= ISC_LOG_PRINTCATEGORY;
  213         if (printtime != NULL && cfg_obj_asboolean(printtime))
  214             flags |= ISC_LOG_PRINTTIME;
  215         if (printsev != NULL && cfg_obj_asboolean(printsev))
  216             flags |= ISC_LOG_PRINTLEVEL;
  217         if (buffered != NULL && cfg_obj_asboolean(buffered))
  218             flags |= ISC_LOG_BUFFERED;
  219     }
  220 
  221     level = ISC_LOG_INFO;
  222     if (cfg_map_get(channel, "severity", &severity) == ISC_R_SUCCESS) {
  223         if (cfg_obj_isstring(severity)) {
  224             const char *str = cfg_obj_asstring(severity);
  225             if (strcasecmp(str, "critical") == 0)
  226                 level = ISC_LOG_CRITICAL;
  227             else if (strcasecmp(str, "error") == 0)
  228                 level = ISC_LOG_ERROR;
  229             else if (strcasecmp(str, "warning") == 0)
  230                 level = ISC_LOG_WARNING;
  231             else if (strcasecmp(str, "notice") == 0)
  232                 level = ISC_LOG_NOTICE;
  233             else if (strcasecmp(str, "info") == 0)
  234                 level = ISC_LOG_INFO;
  235             else if (strcasecmp(str, "dynamic") == 0)
  236                 level = ISC_LOG_DYNAMIC;
  237         } else
  238             /* debug */
  239             level = cfg_obj_asuint32(severity);
  240     }
  241 
  242     if (logconfig == NULL)
  243         result = ISC_R_SUCCESS;
  244     else
  245         result = isc_log_createchannel(logconfig, channelname,
  246                            type, level, &dest, flags);
  247 
  248     if (result == ISC_R_SUCCESS && type == ISC_LOG_TOFILE) {
  249         FILE *fp;
  250 
  251         /*
  252          * Test to make sure that file is a plain file.
  253          * Fix defect #22771
  254         */
  255         result = isc_file_isplainfile(dest.file.name);
  256         if (result == ISC_R_SUCCESS || result == ISC_R_FILENOTFOUND) {
  257             /*
  258              * Test that the file can be opened, since
  259              * isc_log_open() can't effectively report
  260              * failures when called in isc_log_doit().
  261              */
  262             result = isc_stdio_open(dest.file.name, "a", &fp);
  263             if (result != ISC_R_SUCCESS) {
  264                 if (logconfig != NULL && !ns_g_nosyslog)
  265                     syslog(LOG_ERR,
  266                         "isc_stdio_open '%s' failed: "
  267                         "%s", dest.file.name,
  268                         isc_result_totext(result));
  269                 fprintf(stderr,
  270                     "isc_stdio_open '%s' failed: %s\n",
  271                     dest.file.name,
  272                     isc_result_totext(result));
  273             } else
  274                 (void)isc_stdio_close(fp);
  275             goto done;
  276         }
  277         if (logconfig != NULL && !ns_g_nosyslog)
  278             syslog(LOG_ERR, "isc_file_isplainfile '%s' failed: %s",
  279                    dest.file.name, isc_result_totext(result));
  280         fprintf(stderr, "isc_file_isplainfile '%s' failed: %s\n",
  281             dest.file.name, isc_result_totext(result));
  282     }
  283 
  284  done:
  285     return (result);
  286 }
  287 
  288 isc_result_t
  289 ns_log_configure(isc_logconfig_t *logconfig, const cfg_obj_t *logstmt) {
  290     isc_result_t result;
  291     const cfg_obj_t *channels = NULL;
  292     const cfg_obj_t *categories = NULL;
  293     const cfg_listelt_t *element;
  294     bool default_set = false;
  295     bool unmatched_set = false;
  296     const cfg_obj_t *catname;
  297 
  298     if (logconfig != NULL)
  299         CHECK(ns_log_setdefaultchannels(logconfig));
  300 
  301     (void)cfg_map_get(logstmt, "channel", &channels);
  302     for (element = cfg_list_first(channels);
  303          element != NULL;
  304          element = cfg_list_next(element))
  305     {
  306         const cfg_obj_t *channel = cfg_listelt_value(element);
  307         CHECK(channel_fromconf(channel, logconfig));
  308     }
  309 
  310     (void)cfg_map_get(logstmt, "category", &categories);
  311     for (element = cfg_list_first(categories);
  312          element != NULL;
  313          element = cfg_list_next(element))
  314     {
  315         const cfg_obj_t *category = cfg_listelt_value(element);
  316         CHECK(category_fromconf(category, logconfig));
  317         if (!default_set) {
  318             catname = cfg_tuple_get(category, "name");
  319             if (strcmp(cfg_obj_asstring(catname), "default") == 0)
  320                 default_set = true;
  321         }
  322         if (!unmatched_set) {
  323             catname = cfg_tuple_get(category, "name");
  324             if (strcmp(cfg_obj_asstring(catname), "unmatched") == 0)
  325                 unmatched_set = true;
  326         }
  327     }
  328 
  329     if (logconfig != NULL && !default_set)
  330         CHECK(ns_log_setdefaultcategory(logconfig));
  331 
  332     if (logconfig != NULL && !unmatched_set)
  333         CHECK(ns_log_setunmatchedcategory(logconfig));
  334 
  335     return (ISC_R_SUCCESS);
  336 
  337  cleanup:
  338     return (result);
  339 }