1 /*------------------------------------------------------------------------------
2  *
3  * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4  * The YADIFA TM software product is provided under the BSD 3-clause license:
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *        * Redistributions in binary form must reproduce the above copyright
13  *          notice, this list of conditions and the following disclaimer in the
14  *          documentation and/or other materials provided with the distribution.
15  *        * Neither the name of EURid nor the names of its contributors may be
16  *          used to endorse or promote products derived from this software
17  *          without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  *------------------------------------------------------------------------------
32  *
33  */
34 
35 /** @defgroup config Configuration handling
36  *  @ingroup yadifad
37  *  @brief
38  *
39  * @{
40  */
41 
42 #define ZDB_JOURNAL_CODE 1
43 
44 #include "server-config.h"
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include <netdb.h>
50 #include <netinet/in.h>
51 #include <sys/socket.h>
52 #include <unistd.h>
53 #include <string.h>
54 
55 #include <dnscore/format.h>
56 #include <dnscore/sys_get_cpu_count.h>
57 #include <dnscore/config_settings.h>
58 #include <dnscore/parsing.h>
59 #include <dnscore/fdtools.h>
60 #include <dnscore/chroot.h>
61 
62 #include <dnsdb/journal.h>
63 #if ZDB_HAS_DNSSEC_SUPPORT
64 #include <dnsdb/dnssec.h>
65 #include <dnsdb/dnssec-keystore.h>
66 #endif
67 
68 #include "confs.h"
69 #include "config_error.h"
70 #include <dnscore/acl-config.h>
71 #include "server_error.h"
72 #include "process_class_ch.h"
73 #include "server_context.h"
74 
75 #include "server.h"
76 
77 #if HAS_EVENT_DYNAMIC_MODULE
78 #include "dynamic-module-handler.h"
79 #endif
80 
81 #if DNSCORE_HAS_TCP_MANAGER
82 #include <dnscore/tcp_manager.h>
83 #endif
84 
85 /*
86  *
87  */
88 
89 #define CONFS_MAIN_C_
90 
91 config_data						       *g_config = NULL;
92 
93 static value_name_table network_model_enum[]=
94 {
95     {0, "single"  },
96     {0, "0"  },
97     {1, "buffered"},
98     {1, "1"},
99     {2, "multi"   },
100     {2, "2"   },
101     {0, NULL}
102 };
103 
104 /*------------------------------------------------------------------------------
105  * MACROS */
106 
107 /*  Table with the parameters that can be set in the config file
108  *  main container
109  */
110 
111 #define CONFIG_TYPE config_data
112 
113 CONFIG_BEGIN(config_main_desc)
CONFIG_FILE(config_file,S_CONFIGDIR S_CONFIGFILE)114 CONFIG_FILE(     config_file                 , S_CONFIGDIR S_CONFIGFILE   )
115 
116 #ifndef WIN32
117 /* Path to chroot, will be used if chroot is on */
118 CONFIG_CHROOT(   chroot_path                 , S_CHROOTPATH               ) // doc
119 #endif
120 /* Path to data which will be used for relative data */
121 CONFIG_PATH(     data_path                   , S_DATAPATH                 ) // doc
122 /* Path which will be used for logs */
123 CONFIG_LOGPATH(  log_path                    , S_LOGPATH                  ) // doc
124 CONFIG_PATH(     xfr_path                    , S_XFRPATH                  ) // doc
125 /* Path to keys                                */
126 CONFIG_PATH(     keys_path                   , S_KEYSPATH                 ) // doc
127 /* PID file */
128 CONFIG_STRING(   pid_file                    , S_PIDFILE                  ) // doc
129 /* Switch for turning chroot, uid & gid off   */
130 CONFIG_FLAG16(   daemon                      , S_DAEMONRUN               , server_flags,  SERVER_FL_DAEMON              ) // doc
131 CONFIG_FLAG16(   chroot                      , S_CHROOT                  , server_flags,  SERVER_FL_CHROOT              ) // doc
132 CONFIG_FLAG16(   log_unprocessable           , S_LOG_UNPROCESSABLE       , server_flags,  SERVER_FL_LOG_UNPROCESSABLE   ) // doc
133 
134 CONFIG_FLAG16(   log_from_start              , S_LOG_FROM_START          , server_flags,  SERVER_FL_LOG_FROM_START      ) // for the command line
135 // if set, disables checking the log-path directory for existence and writing rights.
136 CONFIG_FLAG16(   log_files_disabled          , S_LOG_FILES_DISABLED      , server_flags,  SERVER_FL_LOG_FILE_DISABLED   ) // doc
137 CONFIG_UID(      uid                         , S_UID                      ) // doc
138 CONFIG_GID(      gid                         , S_GID                      ) // doc
139 
140 // Above settings probably cannot be changed at run time
141 
142 // Below settings may be changed at runtime
143 
144  /* string used for query of version            */
145 CONFIG_STRING(   version_chaos               , S_VERSION_CHAOS            ) // doc
146 CONFIG_STRING(   hostname_chaos              , S_HOSTNAME_CHAOS           ) // doc
147 CONFIG_STRING(   serverid_chaos              , S_SERVERID_CHAOS           ) // doc
148 #if ZDB_HAS_ACL_SUPPORT
149 CONFIG_ACL_PTR(  allow_query                 , S_ALLOW_QUERY              ) // doc
150 CONFIG_ACL_PTR(  allow_update                , S_ALLOW_UPDATE             ) // doc
151 CONFIG_ACL_PTR(  allow_transfer              , S_ALLOW_TRANSFER           ) // doc
152 CONFIG_ACL_PTR(  allow_update_forwarding     , S_ALLOW_UPDATE_FORWARDING  ) // doc
153 CONFIG_ACL_PTR(  allow_notify                , S_ALLOW_NOTIFY             ) // doc
154 CONFIG_ACL_PTR(  allow_control               , S_ALLOW_CONTROL            ) // doc
155 #endif
156 
157 /* Listening to interfaces                     */
158 CONFIG_HOST_LIST(listen                      , S_LISTEN                   ) // doc
159 CONFIG_HOST_LIST(do_not_listen               , S_DO_NOT_LISTEN            ) // doc
160 CONFIG_HOST_LIST(known_hosts                 , S_LISTEN                   )
161 /* size of an EDNS0 packet */
162 CONFIG_U32_RANGE(edns0_max_size              , S_EDNS0_MAX_SIZE          ,EDNS0_MIN_LENGTH, EDNS0_MAX_LENGTH ) // doc
163 // overrides the cpu detection
164 CONFIG_U32(      cpu_count_override          , S_CPU_COUNT_OVERRIDE       ) // doc
165 // how many threads by address (UDP)
166 CONFIG_S32(      thread_count_by_address     , S_THREAD_COUNT_BY_ADDRESS  ) // doc
167 
168 CONFIG_U32_RANGE(thread_affinity_base        , "0", 0, 3  )                 // first virtual cpu // doc
169 CONFIG_U32_RANGE(thread_affinity_multiplier  , "0", 0, 4  )                 // dual thread // doc
170 
171 // how many threads for the dnssec processing)
172 #if DATABASE_ZONE_RRSIG_THREAD_POOL
173 CONFIG_U32(      dnssec_thread_count         , S_DNSSEC_THREAD_COUNT      ) /// @note 20180712 edf -- THIS PARAMETER IS OBSOLETE
174 #else
175 CONFIG_OBSOLETE(dnssec_thread_count) /// @note 20180712 edf -- THIS PARAMETER IS OBSOLETE
176 #endif
177 
178 CONFIG_U32_RANGE(zone_load_thread_count      , S_ZONE_LOAD_THREAD_COUNT, ZONE_LOAD_THREAD_COUNT_MIN, ZONE_LOAD_THREAD_COUNT_MAX) // doc
179 CONFIG_U32_RANGE(zone_store_thread_count      , S_ZONE_SAVE_THREAD_COUNT, ZONE_SAVE_THREAD_COUNT_MIN, ZONE_SAVE_THREAD_COUNT_MAX) // doc
180 CONFIG_U32_RANGE(zone_download_thread_count  , S_ZONE_DOWNLOAD_THREAD_COUNT , ZONE_DOWNLOAD_THREAD_COUNT_MIN, ZONE_DOWNLOAD_THREAD_COUNT_MAX) // doc
181 CONFIG_U32_RANGE(zone_unload_thread_count    , S_ZONE_UNLOAD_THREAD_COUNT, ZONE_UNLOAD_THREAD_COUNT_MIN, ZONE_UNLOAD_THREAD_COUNT_MAX  ) // doc
182 CONFIG_ENUM(     network_model               ,S_NETWORK_MODEL, network_model_enum) // doc
183 /* Max number of TCP queries  */
184 CONFIG_U32_RANGE(max_tcp_queries             , S_MAX_TCP_QUERIES          ,TCP_QUERIES_MIN, TCP_QUERIES_MAX) // doc
185 CONFIG_U32_RANGE(max_tcp_queries_per_address , S_MAX_TCP_QUERIES_PER_ADDRESS,TCP_QUERIES_MIN, TCP_QUERIES_MAX) // doc
186 CONFIG_U32_RANGE(max_secondary_tcp_queries   , S_MAX_SECONDARY_TCP_QUERIES,TCP_QUERIES_MIN, TCP_QUERIES_MAX) // doc
187 CONFIG_U32(      tcp_query_min_rate          , S_TCP_QUERY_MIN_RATE       ) // doc
188 CONFIG_U32_RANGE(tcp_queue_size              , S_TCP_QUEUE_SIZE           , S_TCP_QUEUE_SIZE_MIN, S_TCP_QUEUE_SIZE_MAX)
189 /* Ignores messages that would be answered by a FORMERR */
190 CONFIG_FLAG16(   answer_formerr_packets      , S_ANSWER_FORMERR_PACKETS  , server_flags,  SERVER_FL_ANSWER_FORMERR) // doc
191 /* Listen to port (eg 53)                      */
192 CONFIG_STRING(   server_port                 , S_SERVERPORT               ) // doc
193 /* Switch for cache server or not              */
194 
195 CONFIG_FLAG16(   statistics                  , S_STATISTICS              , server_flags,  SERVER_FL_STATISTICS) /* Maximum number of seconds between two statistics lines */ // doc
196 
197 CONFIG_U32(      statistics_max_period       , S_STATISTICS_MAX_PERIOD    ) // doc
198 CONFIG_U32(      xfr_connect_timeout         , S_XFR_CONNECT_TIMEOUT      ) // doc
199 CONFIG_U32(      queries_log_type            , S_QUERIES_LOG_TYPE         ) // doc
200 
201 #if HAS_DNSSEC_SUPPORT
202 #if CONFIG_SIGNATURE_TYPE_CONFIGURABLE
203 CONFIG_U16(      sig_signing_type            , S_SIG_SIGNING_TYPE          )
204 #endif
205 CONFIG_U32_RANGE(sig_validity_interval       , S_SIG_VALIDITY_INTERVAL    , SIGNATURE_VALIDITY_INTERVAL_MIN     , SIGNATURE_VALIDITY_INTERVAL_MAX    ) /* 7 to 366 days = 30 */ // doc
206 CONFIG_U32_RANGE(sig_validity_regeneration   , S_SIG_VALIDITY_REGENERATION, SIGNATURE_VALIDITY_REGENERATION_MIN , SIGNATURE_VALIDITY_REGENERATION_MAX) /* 24 hours to 168 hours */ // doc
207 CONFIG_U32_RANGE(sig_validity_jitter         , S_SIG_VALIDITY_JITTER      , SIGNATURE_VALIDITY_JITTER_MIN       , SIGNATURE_VALIDITY_JITTER_MAX      ) /* 0 to 86400 = 3600*/ // doc
208 CONFIG_ALIAS(sig_jitter, sig_validity_jitter) // doc
209 #endif
210 
211 CONFIG_U32_RANGE(axfr_max_record_by_packet   , S_AXFR_MAX_RECORD_BY_PACKET , AXFR_RECORD_BY_PACKET_MIN , AXFR_RECORD_BY_PACKET_MAX ) // doc
212 CONFIG_U32_RANGE(axfr_max_packet_size        , S_AXFR_PACKET_SIZE_MAX      , AXFR_PACKET_SIZE_MIN      , AXFR_PACKET_SIZE_MAX      ) // doc
213 CONFIG_BOOL(axfr_compress_packets            , S_AXFR_COMPRESS_PACKETS    ) // doc
214 CONFIG_BOOL(axfr_strict_authority, S_AXFR_STRICT_AUTHORITY) // doc
215 CONFIG_U32_RANGE(axfr_retry_delay            , S_AXFR_RETRY_DELAY          , AXFR_RETRY_DELAY_MIN      , AXFR_RETRY_DELAY_MAX      ) // doc
216 CONFIG_U32(      axfr_retry_jitter           , S_AXFR_RETRY_JITTER        ) // doc
217 CONFIG_U32_RANGE(axfr_retry_failure_delay_multiplier, S_AXFR_RETRY_FAILURE_DELAY_MULTIPLIER, AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MIN, AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MAX) // doc
218 CONFIG_U32_RANGE(axfr_retry_failure_delay_max, S_AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MAX, AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MAX_MIN, AXFR_RETRY_FAILURE_DELAY_MULTIPLIER_MAX_MAX) // doc
219 CONFIG_U32_RANGE(worker_backlog_queue_size   , S_SERVER_RW_BACKLOG_QUEUE_SIZE, SERVER_RW_BACKLOG_QUEUE_SIZE_MIN, SERVER_RW_BACKLOG_QUEUE_SIZE_MAX ) // doc
220 CONFIG_S32(set_nofile, "-1")
221 CONFIG_BOOL(check_policies, "0")
222 
223 #if HAS_EVENT_DYNAMIC_MODULE
224 CONFIG_STRING_ARRAY(dynamic_modules, NULL,128)
225 CONFIG_ALIAS(module, dynamic_modules)
226 #endif
227 
228 CONFIG_BOOL(hidden_master, "0") // doc
229 
230 //CONFIG_U32_RANGE(multimaster_
231 
232           /* alias, aliased */
233 CONFIG_ALIAS(port, server_port) // doc
234 CONFIG_ALIAS(version, version_chaos) // doc
235 CONFIG_ALIAS(hostname, hostname_chaos) // doc
236 CONFIG_ALIAS(serverid, serverid_chaos) // doc
237 CONFIG_ALIAS(chrootpath, chroot_path) // doc
238 CONFIG_ALIAS(configfile, config_file) // cmdline
239 CONFIG_ALIAS(keyspath, keys_path) // doc
240 CONFIG_ALIAS(datapath, data_path) // doc
241 CONFIG_ALIAS(xfrpath, xfr_path) // doc
242 CONFIG_ALIAS(logpath, log_path) // doc
243 CONFIG_ALIAS(pidpath, pid_path)
244 CONFIG_ALIAS(pidfile, pid_file) // doc
245 CONFIG_ALIAS(daemonize, daemon) // doc
246 
247 //CONFIG_ALIAS(zone_save_thread_count, zone_store_thread_count)
248 
249 CONFIG_ALIAS(axfr_maxrecordbypacket, axfr_max_record_by_packet) // doc
250 CONFIG_ALIAS(axfr_maxpacketsize, axfr_max_packet_size) // doc
251 CONFIG_ALIAS(axfr_compresspackets, axfr_compress_packets) // doc
252 
253 #if HAS_DNSSEC_SUPPORT
254 CONFIG_ALIAS(signature_validity_interval, sig_validity_interval)
255 CONFIG_ALIAS(signature_regeneration, sig_validity_regeneration)
256 CONFIG_ALIAS(signature_jitter, sig_validity_jitter)
257 #endif
258 
259 CONFIG_ALIAS(xfr_maxrecordbypacket, axfr_max_record_by_packet) // doc
260 CONFIG_ALIAS(xfr_maxpacketsize, axfr_max_packet_size) // doc
261 CONFIG_ALIAS(xfr_compresspackets, axfr_compress_packets) // doc
262 CONFIG_ALIAS(xfr_retry_delay, axfr_retry_delay) // doc
263 CONFIG_ALIAS(xfr_retry_jitter, axfr_retry_jitter) // doc
264 CONFIG_ALIAS(xfr_retry_failure_delay_multiplier, axfr_retry_failure_delay_multiplier) // doc
265 CONFIG_ALIAS(xfr_retry_failure_delay_max, axfr_retry_failure_delay_max) // doc
266 
267 CONFIG_ALIAS(user, uid) // doc
268 CONFIG_ALIAS(group, gid) // doc
269 CONFIG_ALIAS(max_tcp_connections, max_tcp_queries) // doc
270 CONFIG_ALIAS(network_model_worker_backlog_size, worker_backlog_queue_size)
271 
272 CONFIG_END(config_main_desc)
273 #undef CONFIG_TYPE
274 
275 static ya_result
276 config_main_verify_and_update_directory(const char *base_path, char **dirp)
277 {
278     char fullpath[PATH_MAX];
279     char tempfile[PATH_MAX];
280 
281     if(dirp == NULL)
282     {
283         return UNEXPECTED_NULL_ARGUMENT_ERROR;
284     }
285 
286     char *dir = *dirp;
287 
288     if(dir == NULL)
289     {
290         return UNEXPECTED_NULL_ARGUMENT_ERROR;
291     }
292 
293     ya_result fullpath_len = snprintf(fullpath, sizeof(fullpath),"/%s/%s", base_path, dir);
294 
295     if(FAIL(fullpath_len))
296     {
297         return fullpath_len;
298     }
299 
300     bool dirsep = TRUE;
301     int j = 1;
302     for(int i = 1; i <= fullpath_len; i++)
303     {
304         char c = fullpath[i];
305         if(c == '/')
306         {
307             if(!dirsep)
308             {
309                 fullpath[j++] = c;
310             }
311             dirsep = TRUE;
312         }
313         else
314         {
315             fullpath[j++] = fullpath[i];
316             dirsep = FALSE;
317         }
318     }
319 
320     struct stat ds;
321 
322     if(stat(fullpath, &ds) < 0)
323     {
324         int err = errno;
325         ttylog_err("error: '%s': %s", fullpath, strerror(err));
326 
327         return MAKE_ERRNO_ERROR(err);
328     }
329 
330     if((ds.st_mode & S_IFMT) != S_IFDIR)
331     {
332         ttylog_err("error: '%s' is not a directory", dir);
333 
334         return INVALID_PATH;
335     }
336 
337     snformat(tempfile, sizeof(tempfile), "%s/ydf.XXXXXX", fullpath);
338     int tempfd;
339     if((tempfd = mkstemp_ex(tempfile)) < 0)
340     {
341         int ret = ERRNO_ERROR;
342 #ifndef WIN32
343         ttylog_err("error: '%s' is not writable as (%d:%d): %r", fullpath, getuid(), getgid(), ret);
344 #else
345         ttylog_err("error: '%s' is not writable: %r", fullpath, ret);
346 #endif
347         return ret;
348     }
349     unlink(tempfile);
350     close_ex(tempfd);
351 
352     free(dir);
353 #ifndef WIN32
354     *dirp = strdup(fullpath);
355     chroot_manage_path(dirp, fullpath, FALSE);
356 #endif
357     return SUCCESS;
358 }
359 
360 static ya_result
config_main_verify_and_update_file(const char * base_path,char ** dirp)361 config_main_verify_and_update_file(const char *base_path, char **dirp)
362 {
363     if(dirp == NULL)
364     {
365         return UNEXPECTED_NULL_ARGUMENT_ERROR;
366     }
367 
368     char *p = *dirp;
369 
370     if(p == NULL)
371     {
372         return UNEXPECTED_NULL_ARGUMENT_ERROR;
373     }
374 
375     char *e = p + strlen(p) - 1;
376     while((*e != '/') && (e > p))
377     {
378         e--;
379     }
380 
381     if((*e == '/') || (e == p))
382     {
383         char filename[PATH_MAX];
384 
385         if(*e == '/')
386         {
387             *e = '\0';
388             e++;
389             strcpy_ex(filename, e, sizeof(filename));
390             *e = '\0';
391         }
392         else
393         {
394             strcpy_ex(filename, e, sizeof(filename));
395             *e = '\0';
396         }
397 
398         ya_result ret;
399 
400         if(ISOK(ret = config_main_verify_and_update_directory(base_path, dirp)))
401         {
402             size_t pathlen = strlen(*dirp);
403             memmove(&filename[pathlen + 1], filename, strlen(filename) + 1);
404             memcpy(filename, *dirp, pathlen);
405             filename[pathlen] = '/';
406 #ifndef WIN32
407             chroot_unmanage_path(dirp);
408 #endif
409             free(*dirp);
410             *dirp = NULL;
411 #ifndef WIN32
412             *dirp = strdup(filename);
413             chroot_manage_path(dirp, filename, FALSE);
414 #endif
415             return SUCCESS;
416         }
417         else
418         {
419             return ret;
420         }
421     }
422 
423     return SUCCESS;
424 }
425 
426 #if DNSCORE_HAS_TCP_MANAGER
427 static ya_result
config_main_section_postprocess_tcp_manager_register_callback(const char * itf_name,const socketaddress * sa,void * data)428 config_main_section_postprocess_tcp_manager_register_callback(const char* itf_name, const socketaddress* sa, void* data)
429 {
430     (void)itf_name;
431     (void)data;
432     socklen_t sa_len;
433     if(sa->sa.sa_family == AF_INET)
434     {
435         sa_len = sizeof(sa->sa4);
436         tcp_manager_host_register(sa, sa_len, g_config->max_secondary_tcp_queries);
437     }
438     else if(sa->sa.sa_family == AF_INET6)
439     {
440         sa_len = sizeof(sa->sa6);
441         tcp_manager_host_register(sa, sa_len, g_config->max_secondary_tcp_queries);
442     }
443     return SUCCESS;
444 }
445 #else
446 static ya_result
config_main_section_postprocess_clients_register_callback(const char * itf_name,const socketaddress * sa,void * data)447 config_main_section_postprocess_clients_register_callback(const char* itf_name, const socketaddress* sa, void* data)
448 {
449 
450     (void)itf_name;
451     (void)data;
452     if((sa->sa.sa_family == AF_INET) || (sa->sa.sa_family == AF_INET6))
453     {
454         server_tcp_client_register(&sa->ss, g_config->max_secondary_tcp_queries);
455     }
456 
457     return SUCCESS;
458 }
459 #endif
460 
461 static ya_result
config_main_section_postprocess(struct config_section_descriptor_s * csd)462 config_main_section_postprocess(struct config_section_descriptor_s *csd)
463 {
464     (void)csd;
465 
466     const dnscore_meminfo_t *mi = dnscore_meminfo_get(NULL);
467 
468     u32 port = 0;
469     u32 cpu_per_core = (sys_has_hyperthreading())?2:1;
470     int ret;
471 #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200112L
472     char tmp[PATH_MAX];
473 #endif
474 
475 #if DNSCORE_HAS_TCP_MANAGER
476 /**
477  * Sets the allowed connections total for all unregistered connections.
478  */
479 
480     tcp_manager_connection_max(g_config->max_tcp_queries);
481 
482     for(host_address *ha = g_config->known_hosts; ha != NULL; ha = ha->next)
483     {
484         if((ha->version == HOST_ADDRESS_IPV4) || (ha->version == HOST_ADDRESS_IPV6))
485         {
486             network_interfaces_forall(config_main_section_postprocess_tcp_manager_register_callback, NULL);
487         }
488     }
489 #else
490     for(host_address *ha = g_config->known_hosts; ha != NULL; ha = ha->next)
491     {
492         if((ha->version == HOST_ADDRESS_IPV4) || (ha->version == HOST_ADDRESS_IPV6))
493         {
494             network_interfaces_forall(config_main_section_postprocess_clients_register_callback, NULL);
495         }
496     }
497 #endif
498 
499     g_server_context.worker_backlog_queue_size = g_config->worker_backlog_queue_size;
500 
501     if(FAIL(parse_u32_check_range(g_config->server_port, &port, 1, MAX_U16, BASE_10)))
502     {
503         port = DNS_DEFAULT_PORT;
504         ttylog_err("config: main: wrong dns port set in main '%s', defaulted to %d", g_config->server_port, port);
505     }
506 
507     g_config->server_port_value = port;
508 
509     if(g_config->hostname_chaos == NULL)
510     {
511 #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200112L
512         if(gethostname(tmp, sizeof(tmp)) == 0)
513         {
514             g_config->hostname_chaos = strdup(tmp);
515         }
516         else
517         {
518             osformatln(termerr,"config: main: unable to get hostname: %r", ERRNO_ERROR);
519             g_config->hostname_chaos = strdup("not disclosed");
520         }
521 #else
522         g_config->hostname_chaos = strdup("not disclosed");
523 #endif
524     }
525 
526     if(g_config->thread_affinity_multiplier == 0)
527     {
528         g_config->thread_affinity_multiplier = cpu_per_core;
529     }
530 
531     class_ch_set_hostname(g_config->hostname_chaos);
532     class_ch_set_id_server(g_config->serverid_chaos);
533     class_ch_set_version(g_config->version_chaos);
534 
535     host_address_set_default_port_value(g_config->listen, ntohs(port));
536     host_address_set_default_port_value(g_config->do_not_listen, ntohs(port));
537 
538     if(g_config->max_tcp_queries_per_address > g_config->max_tcp_queries)
539     {
540         ttylog_warn("config: main: max_tcp_queries_per_address higher than max_tcp_queries (%i)", g_config->max_tcp_queries);
541         g_config->max_tcp_queries_per_address = g_config->max_tcp_queries;
542     }
543 
544     if(g_config->max_secondary_tcp_queries > g_config->max_tcp_queries)
545     {
546         ttylog_warn("config: main: max_secondary_tcp_queries higher than max_tcp_queries (%i)", g_config->max_tcp_queries);
547         g_config->max_secondary_tcp_queries = g_config->max_tcp_queries;
548     }
549 
550 #ifndef WIN32
551     if(g_config->server_flags & SERVER_FL_CHROOT)
552     {
553         uid_t euid = geteuid();
554 
555         if(euid != 0)
556         {
557             ttylog_err("config: main: chroot has been enabled but euid is not root (%i != 0)", (int)euid);
558             return INVALID_STATE_ERROR;
559         }
560     }
561     else // disables the base-path/chroot-path feature
562     {
563         if(strcmp(g_config->chroot_path, "/") != 0)
564         {
565             free(g_config->chroot_path);
566             g_config->chroot_path = strdup("/");
567             chroot_set_path(g_config->chroot_path);
568         }
569     }
570 #endif
571     message_edns0_setmaxsize(g_config->edns0_max_size);
572 
573     g_config->total_interfaces = host_address_count(g_config->listen);
574 
575     if(g_config->total_interfaces > MAX_INTERFACES)
576     {
577         ttylog_err("error: more than %d listening addresses defined.", MAX_INTERFACES);
578         return CONFIG_TOO_MANY_HOSTS;
579     }
580 
581 #ifndef SO_REUSEPORT
582     if(g_config->network_model == 1)
583     {
584 #if 0 /* fix */
585 #else
586         ttylog_err("warning: network-model 1 requires SO_REUSEPORT which is not available on this system. Reducing worker units to 1");
587         g_config->thread_count_by_address = 1;
588 #endif
589     }
590 #endif
591 
592     g_config->axfr_retry_jitter = BOUND(AXFR_RETRY_JITTER_MIN, g_config->axfr_retry_jitter, g_config->axfr_retry_delay);
593 
594 #if DATABASE_ZONE_RRSIG_THREAD_POOL
595     g_config->dnssec_thread_count = BOUND(1, g_config->dnssec_thread_count, sys_get_cpu_count());
596 #endif
597 
598     if(g_config->cpu_count_override > 0)
599     {
600         sys_set_cpu_count(g_config->cpu_count_override);
601     }
602 
603     if(g_config->thread_count_by_address == 0)
604     {
605         ttylog_err("config: single thread engine has been removed, thread-count-by-address set to 1");
606         g_config->thread_count_by_address = 1;
607     }
608 
609     if(g_config->thread_count_by_address < 0)
610     {
611         g_config->thread_count_by_address = MAX(sys_get_cpu_count() / cpu_per_core, 1);
612     }
613     else if((g_config->thread_count_by_address > (s32)sys_get_cpu_count()))
614     {
615         g_config->thread_count_by_address = MAX(sys_get_cpu_count() / cpu_per_core, 1);
616         ttylog_warn("config: bounding down thread-count-by-address to the number of physical CPUs (%d)", g_config->thread_count_by_address);
617     }
618 
619     if(mi->program_memory_limit > 0)
620     {
621         const s64 estimated_usage_for_one_thread = (SERVER_POOL_BUFFER_SIZE + sizeof(message_data_with_buffer) + 0x8000 + 0x20000);
622         const double estimated_threshold = 0.50;
623         const s64 tcp_queries_soft_limit = 1024;
624         s64 estimated_current_memory_usage = 0;
625         s64 estimated_thread_count = g_config->max_tcp_queries + g_config->thread_count_by_address;
626         s64 estimated_memory_usage = estimated_thread_count * estimated_usage_for_one_thread + estimated_current_memory_usage;
627         double estimated_memory_usage_ratio = estimated_memory_usage;
628         estimated_memory_usage_ratio /= mi->program_memory_limit;
629         if(estimated_memory_usage_ratio > estimated_threshold)
630         {
631             ttylog_warn("config: estimated memory usage by both UDP and TCP threads seems high compared to the memory available.");
632             ttylog_warn("config: the program may be killed by OOM without notice.");
633             ttylog_warn("config: this doesn't take into account the memory used to load the zones.");
634 
635             s32 cpu_count = sys_get_cpu_count();
636             s64 suggested_thread_count_by_address = cpu_count;
637             if(g_config->thread_count_by_address > cpu_count)
638             {
639                 ttylog_warn("config: maybe reduce the thread-count-by-address from %i to %i", g_config->thread_count_by_address, suggested_thread_count_by_address);
640             }
641             double reverse = estimated_threshold * mi->program_memory_limit;
642             reverse /= estimated_usage_for_one_thread;
643             s64 suggested_max_tcp_queries = MAX(((s64)reverse) - suggested_thread_count_by_address, 1);
644             ttylog_warn("config: reducing the max-tcp-queries from %i to %lli will disable this warning", g_config->max_tcp_queries, suggested_max_tcp_queries);
645             if(suggested_max_tcp_queries > tcp_queries_soft_limit)
646             {
647                 ttylog_warn("config: in practice, a max-tcp-queries value of %lli is plenty", tcp_queries_soft_limit);
648             }
649         }
650     }
651 
652     g_config->tcp_query_min_rate_us = 0.000001 * g_config->tcp_query_min_rate;
653     message_set_minimum_troughput_default(g_config->tcp_query_min_rate_us);
654 
655 #if HAS_DNSSEC_SUPPORT
656 #if DATABASE_ZONE_RRSIG_THREAD_POOL
657     g_config->dnssec_thread_count = BOUND(1, g_config->dnssec_thread_count, sys_get_cpu_count());
658 #endif
659 
660 #if CONFIG_SIGNATURE_TYPE_CONFIGURABLE
661     if(!IS_TYPE_PRIVATE(g_config->sig_signing_type))
662     {
663         ttylog_err("error: signing type is not in the accepted range: %hx", g_config->sig_signing_type);
664         return CONFIG_WRONG_SIG_TYPE;
665     }
666 #endif
667 
668     if(g_config->sig_validity_interval > SIGNATURE_VALIDITY_INTERVAL_MAX)
669     {
670         ttylog_err("error: signature validity interval too high");
671         return CONFIG_WRONG_SIG_VALIDITY;
672     }
673 
674     if(g_config->sig_validity_regeneration * SIGNATURE_VALIDITY_REGENERATION_S * 2 >
675        g_config->sig_validity_interval * SIGNATURE_VALIDITY_INTERVAL_S)
676     {
677         ttylog_err("error: default signature regeneration is more than half the interval (%ds * 2 > %ds)",
678                 g_config->sig_validity_regeneration * SIGNATURE_VALIDITY_REGENERATION_S,
679                 g_config->sig_validity_interval * SIGNATURE_VALIDITY_INTERVAL_S);
680         return CONFIG_WRONG_SIG_REGEN;
681     }
682 #endif
683 
684     /// @note config_main_verify_and_update_directory updates the folder with the base_path
685 
686     /**
687      *
688      * @note All base paths are updated with the chroot variable so it does not
689      *       need to be added all the time.
690      *
691      */
692 #ifndef WIN32
693     const char *base_path = g_config->chroot_path;
694 #else
695     const char* base_path = "C:\\";
696 #endif
697 
698     if(FAIL(ret = config_main_verify_and_update_directory(base_path, &g_config->data_path)))
699     {
700         return ret;
701     }
702 
703     if(FAIL(ret = config_main_verify_and_update_directory(base_path, &g_config->keys_path)))
704     {
705         return ret;
706     }
707 
708     if((g_config->server_flags & SERVER_FL_LOG_FILE_DISABLED) == 0)
709     {
710         if(FAIL(ret = config_main_verify_and_update_directory(base_path, &g_config->log_path)))
711         {
712             return ret;
713         }
714     }
715 
716     if(FAIL(ret = config_main_verify_and_update_file(base_path, &g_config->pid_file)))
717     {
718         return ret;
719     }
720 
721     g_config->reloadable = TRUE;
722 
723 #ifndef WIN32
724     if((g_config->server_flags & SERVER_FL_CHROOT) != 0)
725     {
726         if(FAIL(chroot_manage_path(&g_config->config_file, g_config->config_file, FALSE)))
727         {
728             log_warn("config file '%s' will not be accessible within the chroot jail '%s' : config reload will not work", g_config->config_file, base_path);
729             g_config->reloadable = FALSE;
730         }
731     }
732 #endif
733     if(FAIL(ret = config_main_verify_and_update_directory(base_path, &g_config->xfr_path)))
734     {
735         return ret;
736     }
737 
738 #if ZDB_HAS_DNSSEC_SUPPORT
739     dnssec_keystore_setpath(g_config->keys_path);
740     journal_set_xfr_path(g_config->xfr_path);
741 #endif
742 
743 #if HAS_EVENT_DYNAMIC_MODULE
744     if(ptr_vector_last_index(&g_config->dynamic_modules) >= 0)
745     {
746         log_debug("config file: loading modules");
747 
748         for(int i = 0; i <= ptr_vector_last_index(&g_config->dynamic_modules); ++i)
749         {
750             const char *cmd = ptr_vector_get(&g_config->dynamic_modules, i);
751 
752             if(ISOK(ret = dynamic_module_handler_load_from_command(cmd)))
753             {
754                 log_info("config file: loaded %s", cmd);
755             }
756             else
757             {
758                 log_err("config file: failed to load %s", cmd);
759                 return ret;
760             }
761         }
762     }
763 #endif
764 
765     if((logger_get_uid() != g_config->uid) || (logger_get_gid() != g_config->gid))
766     {
767         logger_set_uid(g_config->uid);
768         logger_set_gid(g_config->gid);
769 
770         logger_reopen();
771     }
772 
773     return SUCCESS;
774 }
775 
776 ya_result
config_register_main(s32 priority)777 config_register_main(s32 priority)
778 {
779     MALLOC_OBJECT_OR_DIE(g_config, config_data, YGCONFIG_TAG);
780     ZEROMEMORY(g_config, sizeof(config_data));
781 
782     g_config->gid = getgid();
783     g_config->uid = getuid();
784 
785 #if HAS_EVENT_DYNAMIC_MODULE
786     ptr_vector_init(&g_config->dynamic_modules);
787 #endif
788     const char *section_name = "main";
789 
790     ya_result return_code = config_register_struct(section_name, config_main_desc, g_config, priority);
791 
792     if(ISOK(return_code))
793     {
794         // hook a new finaliser before the standard one
795 
796         config_section_descriptor_s *section_desc = config_section_get_descriptor(section_name);
797         config_section_descriptor_vtbl_s *vtbl = (config_section_descriptor_vtbl_s*)section_desc->vtbl;
798         vtbl->postprocess = config_main_section_postprocess;
799     }
800 
801     return return_code;
802 }
803 
config_unregister_main()804 void config_unregister_main()
805 {
806     //chroot_unmanage_all();
807     config_data *g_config = config_unregister_struct("main", config_main_desc);
808     free(g_config);
809 }
810 
811 /** @} */
812