"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/bin/named/logconf.c" (4 Sep 2020, 10262 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.tar.xz:


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