2007-01-03 10:42:32 +00:00
/*
* daemon / unbound . c - main program for unbound DNS resolver daemon .
*
* Copyright ( c ) 2007 , NLnet Labs . All rights reserved .
*
2007-01-25 12:39:51 +00:00
* This software is open source .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
*
* Redistributions of source code must retain the above copyright notice ,
* this list of conditions and the following disclaimer .
*
* Redistributions in binary form must reproduce the above copyright notice ,
* this list of conditions and the following disclaimer in the documentation
* and / or other materials provided with the distribution .
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2014-02-07 13:28:39 +00:00
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED
* TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR
* PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING
* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
2007-01-03 10:42:32 +00:00
*
*/
2007-01-03 14:55:21 +00:00
/**
* \ file
*
* Main program to start the DNS resolver daemon .
*/
2007-01-03 10:42:32 +00:00
# include "config.h"
2010-03-12 15:17:48 +00:00
# ifdef HAVE_GETOPT_H
# include <getopt.h>
# endif
2010-07-05 14:20:24 +00:00
# include <sys/time.h>
2007-01-03 10:42:32 +00:00
# include "util/log.h"
2007-02-22 16:22:54 +00:00
# include "daemon/daemon.h"
2009-06-11 09:43:23 +00:00
# include "daemon/remote.h"
2007-02-20 16:19:00 +00:00
# include "util/config_file.h"
2007-03-26 10:33:41 +00:00
# include "util/storage/slabhash.h"
2007-05-09 07:58:57 +00:00
# include "services/listen_dnsport.h"
2007-05-16 12:48:48 +00:00
# include "services/cache/rrset.h"
2007-05-16 14:29:46 +00:00
# include "services/cache/infra.h"
2014-05-28 08:07:12 +00:00
# include "util/fptr_wlist.h"
2007-03-26 10:33:41 +00:00
# include "util/data/msgreply.h"
2007-05-16 12:48:48 +00:00
# include "util/module.h"
2011-10-31 14:48:48 +00:00
# include "util/net_help.h"
2016-03-07 14:10:06 +00:00
# include "util/ub_event.h"
2007-02-23 13:38:54 +00:00
# include <signal.h>
2007-02-22 16:22:54 +00:00
# include <fcntl.h>
2008-07-25 11:33:31 +00:00
# include <openssl/crypto.h>
2008-05-23 14:13:07 +00:00
# ifdef HAVE_PWD_H
2007-02-22 16:22:54 +00:00
# include <pwd.h>
2008-05-23 14:13:07 +00:00
# endif
2009-02-05 11:12:01 +00:00
# ifdef HAVE_GRP_H
# include <grp.h>
# endif
2019-01-23 08:37:00 +00:00
# include <openssl/ssl.h>
2007-01-25 12:39:51 +00:00
2014-01-24 13:23:45 +00:00
# ifndef S_SPLINT_S
/* splint chokes on this system header file */
2008-04-16 16:09:25 +00:00
# ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
# endif
2014-01-24 13:23:45 +00:00
# endif /* S_SPLINT_S */
2009-02-12 09:02:12 +00:00
# ifdef HAVE_LOGIN_CAP_H
# include <login_cap.h>
# endif
2008-02-13 13:24:41 +00:00
2009-02-27 16:29:40 +00:00
# ifdef UB_ON_WINDOWS
# include "winrc / win_svc.h"
# endif
2012-06-20 15:23:03 +00:00
# ifdef HAVE_NSS
2013-01-30 13:15:03 +00:00
/* nss3 */
# include "nss.h"
2012-06-20 15:23:03 +00:00
# endif
2020-03-17 10:32:13 +00:00
# ifdef HAVE_TARGETCONDITIONALS_H
# include <TargetConditionals.h>
# endif
2020-08-03 18:37:00 +00:00
# if (defined(TARGET_OS_TV) && TARGET_OS_TV) || (defined(TARGET_OS_WATCH) && TARGET_OS_WATCH)
2020-03-17 10:32:13 +00:00
# undef HAVE_FORK
# endif
2019-08-12 15:52:43 +00:00
/** print build options. */
static void
print_build_options ( void )
2007-01-25 12:39:51 +00:00
{
2009-03-26 15:47:45 +00:00
const char * * m ;
2010-07-05 13:10:49 +00:00
const char * evnm = " event " , * evsys = " " , * evmethod = " " ;
2016-06-13 07:06:23 +00:00
time_t t ;
struct timeval now ;
struct ub_event_base * base ;
2019-08-12 15:52:43 +00:00
printf ( " Version %s \n \n " , PACKAGE_VERSION ) ;
printf ( " Configure line: %s \n " , CONFCMDLINE ) ;
2016-06-13 07:06:23 +00:00
base = ub_default_event_base ( 0 , & t , & now ) ;
ub_get_event_sys ( base , & evnm , & evsys , & evmethod ) ;
2019-08-12 15:52:43 +00:00
printf ( " Linked libs: %s %s (it uses %s), %s \n " ,
2013-10-31 15:09:26 +00:00
evnm , evsys , evmethod ,
2012-06-20 15:23:03 +00:00
# ifdef HAVE_SSL
2016-09-02 09:59:09 +00:00
# ifdef SSLEAY_VERSION
2012-06-20 15:23:03 +00:00
SSLeay_version ( SSLEAY_VERSION )
2016-09-02 09:59:09 +00:00
# else
OpenSSL_version ( OPENSSL_VERSION )
# endif
2012-06-20 15:23:03 +00:00
# elif defined(HAVE_NSS)
NSS_GetVersion ( )
2015-11-17 10:02:17 +00:00
# elif defined(HAVE_NETTLE)
" nettle "
2012-06-20 15:23:03 +00:00
# endif
) ;
2019-08-12 15:52:43 +00:00
printf ( " Linked modules: " ) ;
2009-03-26 15:47:45 +00:00
for ( m = module_list_avail ( ) ; * m ; m + + )
printf ( " %s " , * m ) ;
printf ( " \n " ) ;
2017-08-10 07:13:44 +00:00
# ifdef USE_DNSCRYPT
2017-08-10 07:26:09 +00:00
printf ( " DNSCrypt feature available \n " ) ;
2019-08-15 15:04:38 +00:00
# endif
# ifdef USE_TCP_FASTOPEN
printf ( " TCP Fastopen feature available \n " ) ;
2017-08-10 07:13:44 +00:00
# endif
2019-08-12 15:52:43 +00:00
ub_event_base_free ( base ) ;
printf ( " \n BSD licensed, see LICENSE in source package for details. \n " ) ;
printf ( " Report bugs to %s \n " , PACKAGE_BUGREPORT ) ;
}
/** print usage. */
static void
usage ( void )
{
printf ( " usage: unbound [options] \n " ) ;
printf ( " start unbound daemon DNS resolver. \n " ) ;
printf ( " -h this help. \n " ) ;
printf ( " -c file config file to read instead of %s \n " , CONFIGFILE ) ;
printf ( " file format is described in unbound.conf(5). \n " ) ;
printf ( " -d do not fork into the background. \n " ) ;
printf ( " -p do not create a pidfile. \n " ) ;
printf ( " -v verbose (more times to increase verbosity). \n " ) ;
printf ( " -V show version number and build options. \n " ) ;
# ifdef UB_ON_WINDOWS
printf ( " -w opt windows option: \n " ) ;
printf ( " install, remove - manage the services entry \n " ) ;
printf ( " service - used to start from services control panel \n " ) ;
# endif
printf ( " \n Version %s \n " , PACKAGE_VERSION ) ;
2007-02-06 16:26:19 +00:00
printf ( " BSD licensed, see LICENSE in source package for details. \n " ) ;
printf ( " Report bugs to %s \n " , PACKAGE_BUGREPORT ) ;
2007-01-25 12:39:51 +00:00
}
2009-08-31 15:58:38 +00:00
# ifndef unbound_testbound
int replay_var_compare ( const void * ATTR_UNUSED ( a ) , const void * ATTR_UNUSED ( b ) )
{
log_assert ( 0 ) ;
return 0 ;
}
# endif
2007-05-09 07:58:57 +00:00
/** check file descriptor count */
static void
checkrlimits ( struct config_file * cfg )
{
2014-01-24 13:23:45 +00:00
# ifndef S_SPLINT_S
2008-05-23 14:13:07 +00:00
# ifdef HAVE_GETRLIMIT
2008-11-20 09:48:36 +00:00
/* list has number of ports to listen to, ifs number addresses */
2008-11-20 09:20:10 +00:00
int list = ( ( cfg - > do_udp ? 1 : 0 ) + ( cfg - > do_tcp ? 1 +
2007-08-30 08:36:41 +00:00
( int ) cfg - > incoming_num_tcp : 0 ) ) ;
2008-11-20 09:20:10 +00:00
size_t listen_ifs = ( size_t ) ( cfg - > num_ifs = = 0 ?
( ( cfg - > do_ip4 & & ! cfg - > if_automatic ? 1 : 0 ) +
( cfg - > do_ip6 ? 1 : 0 ) ) : cfg - > num_ifs ) ;
size_t listen_num = list * listen_ifs ;
2008-04-11 14:10:16 +00:00
size_t outudpnum = ( size_t ) cfg - > outgoing_num_ports ;
2008-04-08 15:02:52 +00:00
size_t outtcpnum = cfg - > outgoing_num_tcp ;
2007-05-09 07:58:57 +00:00
size_t misc = 4 ; /* logfile, pidfile, stdout... */
2008-04-08 15:02:52 +00:00
size_t perthread_noudp = listen_num + outtcpnum +
2 /*cmdpipe*/ + 2 /*libevent*/ + misc ;
size_t perthread = perthread_noudp + outudpnum ;
2007-05-09 07:58:57 +00:00
# if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
2007-05-09 09:04:11 +00:00
int numthread = 1 ; /* it forks */
2007-05-09 07:58:57 +00:00
# else
2011-08-26 06:50:23 +00:00
int numthread = ( cfg - > num_threads ? cfg - > num_threads : 1 ) ;
2007-05-09 07:58:57 +00:00
# endif
size_t total = numthread * perthread + misc ;
2008-04-08 15:02:52 +00:00
size_t avail ;
2007-05-09 07:58:57 +00:00
struct rlimit rlim ;
2021-02-24 13:14:33 +00:00
size_t memsize_expect = cfg - > msg_cache_size + cfg - > rrset_cache_size
+ ( cfg - > do_tcp ? cfg - > stream_wait_size : 0 )
+ ( cfg - > ip_ratelimit ? cfg - > ip_ratelimit_size : 0 )
+ ( cfg - > ratelimit ? cfg - > ratelimit_size : 0 )
+ ( cfg - > dnscrypt ? cfg - > dnscrypt_shared_secret_cache_size + cfg - > dnscrypt_nonce_cache_size : 0 )
+ cfg - > infra_cache_numhosts * ( sizeof ( struct infra_key ) + sizeof ( struct infra_data ) ) ;
if ( strstr ( cfg - > module_conf , " validator " ) & & ( cfg - > trust_anchor_file_list | | cfg - > trust_anchor_list | | cfg - > auto_trust_anchor_file_list | | cfg - > trusted_keys_file_list ) ) {
memsize_expect + = cfg - > key_cache_size + cfg - > neg_cache_size ;
}
# ifdef HAVE_NGHTTP2_NGHTTP2_H
if ( cfg_has_https ( cfg ) ) {
memsize_expect + = cfg - > http_query_buffer_size + cfg - > http_response_buffer_size ;
}
# endif
2021-05-08 15:12:39 +00:00
# ifdef RLIMIT_AS
2021-02-24 13:14:33 +00:00
if ( getrlimit ( RLIMIT_AS , & rlim ) = = 0 ) {
if ( rlim . rlim_cur ! = ( rlim_t ) RLIM_INFINITY & &
rlim . rlim_cur < ( rlim_t ) memsize_expect ) {
log_warn ( " the ulimit(max memory size) is smaller than the expected memory usage (added size of caches). %u < %u bytes " , ( unsigned ) rlim . rlim_cur , ( unsigned ) memsize_expect ) ;
}
}
2021-05-08 15:12:39 +00:00
# endif
2021-02-24 13:14:33 +00:00
if ( getrlimit ( RLIMIT_DATA , & rlim ) = = 0 ) {
if ( rlim . rlim_cur ! = ( rlim_t ) RLIM_INFINITY & &
2021-08-03 12:13:37 +00:00
rlim . rlim_cur < ( rlim_t ) memsize_expect ) {
2021-02-24 13:14:33 +00:00
log_warn ( " the ulimit(data seg size) is smaller than the expected memory usage (added size of caches). %u < %u bytes " , ( unsigned ) rlim . rlim_cur , ( unsigned ) memsize_expect ) ;
}
}
2008-04-09 15:07:37 +00:00
2010-07-15 13:08:45 +00:00
if ( total > 1024 & &
2016-03-07 14:10:06 +00:00
strncmp ( ub_event_get_version ( ) , " mini-event " , 10 ) = = 0 ) {
2010-07-15 13:08:45 +00:00
log_warn ( " too many file descriptors requested. The builtin "
" mini-event cannot handle more than 1024. Config "
" for less fds or compile with libevent " ) ;
if ( numthread * perthread_noudp + 15 > 1024 )
fatal_exit ( " too much tcp. not enough fds. " ) ;
cfg - > outgoing_num_ports = ( int ) ( ( 1024
- numthread * perthread_noudp
- 10 /* safety margin */ ) / numthread ) ;
log_warn ( " continuing with less udp ports: %u " ,
cfg - > outgoing_num_ports ) ;
total = 1024 ;
}
if ( perthread > 64 & &
2016-03-07 14:10:06 +00:00
strncmp ( ub_event_get_version ( ) , " winsock-event " , 13 ) = = 0 ) {
2010-07-15 13:08:45 +00:00
log_err ( " too many file descriptors requested. The winsock "
" event handler cannot handle more than 64 per "
" thread. Config for less fds " ) ;
if ( perthread_noudp + 2 > 64 )
fatal_exit ( " too much tcp. not enough fds. " ) ;
cfg - > outgoing_num_ports = ( int ) ( ( 64
- perthread_noudp
- 2 /* safety margin */ ) ) ;
log_warn ( " continuing with less udp ports: %u " ,
cfg - > outgoing_num_ports ) ;
total = numthread * ( perthread_noudp +
( size_t ) cfg - > outgoing_num_ports ) + misc ;
}
2007-05-09 07:58:57 +00:00
if ( getrlimit ( RLIMIT_NOFILE , & rlim ) < 0 ) {
log_warn ( " getrlimit: %s " , strerror ( errno ) ) ;
return ;
}
2007-06-20 13:01:30 +00:00
if ( rlim . rlim_cur = = ( rlim_t ) RLIM_INFINITY )
2007-06-20 07:47:56 +00:00
return ;
2007-05-09 07:58:57 +00:00
if ( ( size_t ) rlim . rlim_cur < total ) {
2008-04-08 15:02:52 +00:00
avail = ( size_t ) rlim . rlim_cur ;
rlim . rlim_cur = ( rlim_t ) ( total + 10 ) ;
rlim . rlim_max = ( rlim_t ) ( total + 10 ) ;
2010-07-05 14:20:24 +00:00
# ifdef HAVE_SETRLIMIT
2008-04-08 15:02:52 +00:00
if ( setrlimit ( RLIMIT_NOFILE , & rlim ) < 0 ) {
log_warn ( " setrlimit: %s " , strerror ( errno ) ) ;
2010-07-05 14:20:24 +00:00
# endif
2008-04-08 15:02:52 +00:00
log_warn ( " cannot increase max open fds from %u to %u " ,
( unsigned ) avail , ( unsigned ) total + 10 ) ;
2008-11-20 09:48:36 +00:00
/* check that calculation below does not underflow,
* with 15 as margin */
2008-11-20 09:20:10 +00:00
if ( numthread * perthread_noudp + 15 > avail )
fatal_exit ( " too much tcp. not enough fds. " ) ;
2008-04-08 15:02:52 +00:00
cfg - > outgoing_num_ports = ( int ) ( ( avail
- numthread * perthread_noudp
2008-04-11 14:10:16 +00:00
- 10 /* safety margin */ ) / numthread ) ;
2008-04-08 15:02:52 +00:00
log_warn ( " continuing with less udp ports: %u " ,
cfg - > outgoing_num_ports ) ;
2010-07-15 13:08:45 +00:00
log_warn ( " increase ulimit or decrease threads, "
" ports in config to remove this warning " ) ;
2008-04-08 15:02:52 +00:00
return ;
2014-07-29 11:48:43 +00:00
# ifdef HAVE_SETRLIMIT
2008-04-08 15:02:52 +00:00
}
2014-07-29 11:48:43 +00:00
# endif
2014-11-12 11:04:43 +00:00
verbose ( VERB_ALGO , " increased limit(open files) from %u to %u " ,
2008-04-08 15:02:52 +00:00
( unsigned ) avail , ( unsigned ) total + 10 ) ;
2007-05-09 07:58:57 +00:00
}
2008-05-23 14:13:07 +00:00
# else
( void ) cfg ;
# endif /* HAVE_GETRLIMIT */
2014-01-24 13:23:45 +00:00
# endif /* S_SPLINT_S */
2007-05-09 07:58:57 +00:00
}
2007-10-31 10:56:31 +00:00
/** set verbosity, check rlimits, cache settings */
2007-02-23 13:38:54 +00:00
static void
2020-02-10 12:56:22 +00:00
apply_settings ( struct daemon * daemon , struct config_file * cfg ,
int cmdline_verbose , int debug_mode )
2007-02-23 13:38:54 +00:00
{
2007-03-29 13:00:36 +00:00
/* apply if they have changed */
2007-02-23 13:38:54 +00:00
verbosity = cmdline_verbose + cfg - > verbosity ;
2014-07-29 11:48:43 +00:00
if ( debug_mode > 1 ) {
cfg - > use_syslog = 0 ;
2016-10-11 13:43:18 +00:00
free ( cfg - > logfile ) ;
2014-07-29 11:48:43 +00:00
cfg - > logfile = NULL ;
}
2009-02-27 16:29:40 +00:00
daemon_apply_cfg ( daemon , cfg ) ;
2007-05-09 07:58:57 +00:00
checkrlimits ( cfg ) ;
2017-01-03 13:43:29 +00:00
if ( cfg - > use_systemd & & cfg - > do_daemonize ) {
log_warn ( " use-systemd and do-daemonize should not be enabled at the same time " ) ;
}
2020-02-10 12:56:22 +00:00
log_ident_set_or_default ( cfg - > log_identity ) ;
2007-02-23 13:38:54 +00:00
}
2008-05-23 14:13:07 +00:00
# ifdef HAVE_KILL
2007-06-12 14:51:49 +00:00
/** Read existing pid from pidfile.
* @ param file : file name of pid file .
* @ return : the pid from the file or - 1 if none .
*/
2007-02-23 13:38:54 +00:00
static pid_t
readpid ( const char * file )
{
int fd ;
pid_t pid ;
char pidbuf [ 32 ] ;
char * t ;
2007-02-23 13:59:45 +00:00
ssize_t l ;
2007-02-23 13:38:54 +00:00
if ( ( fd = open ( file , O_RDONLY ) ) = = - 1 ) {
2007-03-29 13:00:36 +00:00
if ( errno ! = ENOENT )
log_err ( " Could not read pidfile %s: %s " ,
file , strerror ( errno ) ) ;
2007-02-23 13:38:54 +00:00
return - 1 ;
}
if ( ( ( l = read ( fd , pidbuf , sizeof ( pidbuf ) ) ) ) = = - 1 ) {
2007-03-29 13:00:36 +00:00
if ( errno ! = ENOENT )
log_err ( " Could not read pidfile %s: %s " ,
file , strerror ( errno ) ) ;
2007-02-23 13:38:54 +00:00
close ( fd ) ;
return - 1 ;
}
close ( fd ) ;
/* Empty pidfile means no pidfile... */
if ( l = = 0 ) {
return - 1 ;
}
2007-10-16 13:03:57 +00:00
pidbuf [ sizeof ( pidbuf ) - 1 ] = 0 ;
2007-09-26 11:15:42 +00:00
pid = ( pid_t ) strtol ( pidbuf , & t , 10 ) ;
2007-02-23 13:38:54 +00:00
if ( * t & & * t ! = ' \n ' ) {
return - 1 ;
}
return pid ;
}
2007-06-12 14:51:49 +00:00
/** write pid to file.
* @ param pidfile : file name of pid file .
* @ param pid : pid to write to file .
2020-11-23 12:48:04 +00:00
* @ return false on failure
2007-06-12 14:51:49 +00:00
*/
2020-11-23 12:48:04 +00:00
static int
2007-02-23 13:38:54 +00:00
writepid ( const char * pidfile , pid_t pid )
{
2020-11-23 12:42:11 +00:00
int fd ;
char pidbuf [ 32 ] ;
size_t count = 0 ;
snprintf ( pidbuf , sizeof ( pidbuf ) , " %lu \n " , ( unsigned long ) pid ) ;
2007-02-23 13:38:54 +00:00
2020-11-23 12:42:11 +00:00
if ( ( fd = open ( pidfile , O_WRONLY | O_CREAT | O_TRUNC
# ifdef O_NOFOLLOW
| O_NOFOLLOW
# endif
, 0644 ) ) = = - 1 ) {
2007-02-23 13:38:54 +00:00
log_err ( " cannot open pidfile %s: %s " ,
pidfile , strerror ( errno ) ) ;
2020-11-23 12:48:04 +00:00
return 0 ;
2007-02-23 13:38:54 +00:00
}
2020-11-23 12:42:11 +00:00
while ( count < strlen ( pidbuf ) ) {
ssize_t r = write ( fd , pidbuf + count , strlen ( pidbuf ) - count ) ;
if ( r = = - 1 ) {
if ( errno = = EAGAIN | | errno = = EINTR )
continue ;
log_err ( " cannot write to pidfile %s: %s " ,
pidfile , strerror ( errno ) ) ;
2020-11-23 12:48:04 +00:00
close ( fd ) ;
return 0 ;
2020-11-23 13:17:58 +00:00
} else if ( r = = 0 ) {
log_err ( " cannot write any bytes to pidfile %s: "
" write returns 0 bytes written " , pidfile ) ;
close ( fd ) ;
return 0 ;
2020-11-23 12:42:11 +00:00
}
count + = r ;
2007-02-23 13:38:54 +00:00
}
2020-11-23 12:42:11 +00:00
close ( fd ) ;
2020-11-23 12:48:04 +00:00
return 1 ;
2007-02-23 13:38:54 +00:00
}
2007-02-23 13:59:45 +00:00
/**
* check old pid file .
2008-08-27 11:29:46 +00:00
* @ param pidfile : the file name of the pid file .
* @ param inchroot : if pidfile is inchroot and we can thus expect to
* be able to delete it .
2007-02-23 13:59:45 +00:00
*/
2007-02-23 13:38:54 +00:00
static void
2008-08-27 11:29:46 +00:00
checkoldpid ( char * pidfile , int inchroot )
2007-02-23 13:38:54 +00:00
{
pid_t old ;
2008-08-27 11:29:46 +00:00
if ( ( old = readpid ( pidfile ) ) ! = - 1 ) {
2007-03-29 13:00:36 +00:00
/* see if it is still alive */
2007-02-23 13:38:54 +00:00
if ( kill ( old , 0 ) = = 0 | | errno = = EPERM )
2007-02-27 15:46:28 +00:00
log_warn ( " unbound is already running as pid %u. " ,
( unsigned ) old ) ;
2008-08-27 11:29:46 +00:00
else if ( inchroot )
log_warn ( " did not exit gracefully last time (%u) " ,
2007-02-27 15:46:28 +00:00
( unsigned ) old ) ;
2007-02-23 13:38:54 +00:00
}
}
2008-05-23 14:13:07 +00:00
# endif /* HAVE_KILL */
2007-02-23 13:38:54 +00:00
2007-03-29 13:00:36 +00:00
/** detach from command line */
static void
2008-08-27 11:29:46 +00:00
detach ( void )
2007-03-29 13:00:36 +00:00
{
2009-03-23 11:22:57 +00:00
# if defined(HAVE_DAEMON) && !defined(DEPRECATED_DAEMON)
2009-02-05 14:23:24 +00:00
/* use POSIX daemon(3) function */
if ( daemon ( 1 , 0 ) ! = 0 )
fatal_exit ( " daemon failed: %s " , strerror ( errno ) ) ;
# else /* no HAVE_DAEMON */
2010-03-11 13:28:53 +00:00
# ifdef HAVE_FORK
2008-08-27 11:29:46 +00:00
int fd ;
2007-03-29 13:00:36 +00:00
/* Take off... */
switch ( fork ( ) ) {
case 0 :
break ;
case - 1 :
2008-08-27 11:29:46 +00:00
fatal_exit ( " fork failed: %s " , strerror ( errno ) ) ;
2007-03-29 13:00:36 +00:00
default :
/* exit interactive session */
exit ( 0 ) ;
}
/* detach */
2008-05-23 14:13:07 +00:00
# ifdef HAVE_SETSID
2007-03-29 13:00:36 +00:00
if ( setsid ( ) = = - 1 )
fatal_exit ( " setsid() failed: %s " , strerror ( errno ) ) ;
2008-05-23 14:13:07 +00:00
# endif
2007-03-29 13:00:36 +00:00
if ( ( fd = open ( " /dev/null " , O_RDWR , 0 ) ) ! = - 1 ) {
( void ) dup2 ( fd , STDIN_FILENO ) ;
( void ) dup2 ( fd , STDOUT_FILENO ) ;
( void ) dup2 ( fd , STDERR_FILENO ) ;
if ( fd > 2 )
( void ) close ( fd ) ;
}
2010-03-11 13:28:53 +00:00
# endif /* HAVE_FORK */
2009-02-05 14:23:24 +00:00
# endif /* HAVE_DAEMON */
2007-03-29 13:00:36 +00:00
}
2017-09-15 14:29:28 +00:00
/** daemonize, drop user privileges and chroot if needed */
2007-02-22 16:22:54 +00:00
static void
2008-08-27 11:29:46 +00:00
perform_setup ( struct daemon * daemon , struct config_file * cfg , int debug_mode ,
2017-07-17 08:26:49 +00:00
const char * * cfgfile , int need_pidfile )
2007-02-22 16:22:54 +00:00
{
2016-01-26 09:00:06 +00:00
# ifdef HAVE_KILL
int pidinchroot ;
# endif
2008-07-15 15:05:12 +00:00
# ifdef HAVE_GETPWNAM
2009-02-12 08:06:47 +00:00
struct passwd * pwd = NULL ;
2007-02-22 16:22:54 +00:00
if ( cfg - > username & & cfg - > username [ 0 ] ) {
if ( ( pwd = getpwnam ( cfg - > username ) ) = = NULL )
fatal_exit ( " user '%s' does not exist. " , cfg - > username ) ;
2009-02-12 08:06:47 +00:00
/* endpwent below, in case we need pwd for setusercontext */
2007-02-22 16:22:54 +00:00
}
2008-05-23 14:13:07 +00:00
# endif
2015-12-01 09:26:02 +00:00
# ifdef UB_ON_WINDOWS
w_config_adjust_directory ( cfg ) ;
# endif
2008-08-27 11:29:46 +00:00
2009-06-11 09:43:23 +00:00
/* read ssl keys while superuser and outside chroot */
2012-07-04 12:33:32 +00:00
# ifdef HAVE_SSL
2009-06-11 09:43:23 +00:00
if ( ! ( daemon - > rc = daemon_remote_create ( cfg ) ) )
fatal_exit ( " could not set up remote-control " ) ;
2011-10-31 14:48:48 +00:00
if ( cfg - > ssl_service_key & & cfg - > ssl_service_key [ 0 ] ) {
if ( ! ( daemon - > listen_sslctx = listen_sslctx_create (
cfg - > ssl_service_key , cfg - > ssl_service_pem , NULL ) ) )
fatal_exit ( " could not set up listen SSL_CTX " ) ;
2019-01-23 08:37:00 +00:00
if ( cfg - > tls_ciphers & & cfg - > tls_ciphers [ 0 ] ) {
if ( ! SSL_CTX_set_cipher_list ( daemon - > listen_sslctx , cfg - > tls_ciphers ) ) {
2019-01-23 08:45:16 +00:00
fatal_exit ( " failed to set tls-cipher %s " , cfg - > tls_ciphers ) ;
2019-01-23 08:37:00 +00:00
}
}
2019-01-23 08:57:49 +00:00
# ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
2019-01-23 08:37:00 +00:00
if ( cfg - > tls_ciphersuites & & cfg - > tls_ciphersuites [ 0 ] ) {
if ( ! SSL_CTX_set_ciphersuites ( daemon - > listen_sslctx , cfg - > tls_ciphersuites ) ) {
2019-01-23 08:45:16 +00:00
fatal_exit ( " failed to set tls-ciphersuites %s " , cfg - > tls_ciphersuites ) ;
2019-01-23 08:37:00 +00:00
}
}
# endif
2019-03-25 08:47:14 +00:00
if ( cfg - > tls_session_ticket_keys . first & &
cfg - > tls_session_ticket_keys . first - > str [ 0 ] ! = 0 ) {
2019-01-23 10:41:03 +00:00
if ( ! listen_sslctx_setup_ticket_keys ( daemon - > listen_sslctx , cfg - > tls_session_ticket_keys . first ) ) {
2019-01-23 09:35:52 +00:00
fatal_exit ( " could not set session ticket SSL_CTX " ) ;
}
}
2011-10-31 14:48:48 +00:00
}
2018-02-13 10:35:09 +00:00
if ( ! ( daemon - > connect_sslctx = connect_sslctx_create ( NULL , NULL ,
2018-05-28 13:22:10 +00:00
cfg - > tls_cert_bundle , cfg - > tls_win_cert ) ) )
2011-10-31 14:48:48 +00:00
fatal_exit ( " could not set up connect SSL_CTX " ) ;
2012-07-04 12:33:32 +00:00
# endif
2009-06-11 09:43:23 +00:00
2018-01-23 15:59:18 +00:00
/* init syslog (as root) if needed, before daemonize, otherwise
* a fork error could not be printed since daemonize closed stderr . */
if ( cfg - > use_syslog ) {
log_init ( cfg - > logfile , cfg - > use_syslog , cfg - > chrootdir ) ;
}
/* if using a logfile, we cannot open it because the logfile would
* be created with the wrong permissions , we cannot chown it because
* we cannot chown system logfiles , so we do not open at all .
* So , using a logfile , the user does not see errors unless - d is
* given to unbound on the commandline . */
2008-08-27 11:29:46 +00:00
# ifdef HAVE_KILL
2016-01-26 08:05:04 +00:00
/* true if pidfile is inside chrootdir, or nochroot */
2017-07-17 08:26:49 +00:00
pidinchroot = need_pidfile & & ( ! ( cfg - > chrootdir & & cfg - > chrootdir [ 0 ] ) | |
2016-01-26 08:05:04 +00:00
( cfg - > chrootdir & & cfg - > chrootdir [ 0 ] & &
2016-02-08 08:17:00 +00:00
strncmp ( cfg - > pidfile , cfg - > chrootdir ,
2017-07-17 08:26:49 +00:00
strlen ( cfg - > chrootdir ) ) = = 0 ) ) ;
2016-01-26 08:05:04 +00:00
2008-08-27 11:29:46 +00:00
/* check old pid file before forking */
2017-07-17 08:26:49 +00:00
if ( cfg - > pidfile & & cfg - > pidfile [ 0 ] & & need_pidfile ) {
2008-08-27 11:29:46 +00:00
/* calculate position of pidfile */
if ( cfg - > pidfile [ 0 ] = = ' / ' )
daemon - > pidfile = strdup ( cfg - > pidfile ) ;
else daemon - > pidfile = fname_after_chroot ( cfg - > pidfile ,
cfg , 1 ) ;
if ( ! daemon - > pidfile )
fatal_exit ( " pidfile alloc: out of memory " ) ;
2016-01-26 08:05:04 +00:00
checkoldpid ( daemon - > pidfile , pidinchroot ) ;
2008-08-27 11:29:46 +00:00
}
# endif
/* daemonize because pid is needed by the writepid func */
if ( ! debug_mode & & cfg - > do_daemonize ) {
detach ( ) ;
}
/* write new pidfile (while still root, so can be outside chroot) */
# ifdef HAVE_KILL
2017-07-17 08:26:49 +00:00
if ( cfg - > pidfile & & cfg - > pidfile [ 0 ] & & need_pidfile ) {
2020-11-23 12:48:04 +00:00
if ( writepid ( daemon - > pidfile , getpid ( ) ) ) {
if ( cfg - > username & & cfg - > username [ 0 ] & & cfg_uid ! = ( uid_t ) - 1 & &
pidinchroot ) {
2015-01-23 15:23:58 +00:00
# ifdef HAVE_CHOWN
2020-11-23 12:48:04 +00:00
if ( chown ( daemon - > pidfile , cfg_uid , cfg_gid ) = = - 1 ) {
verbose ( VERB_QUERY , " cannot chown %u.%u %s: %s " ,
( unsigned ) cfg_uid , ( unsigned ) cfg_gid ,
daemon - > pidfile , strerror ( errno ) ) ;
}
2015-01-23 15:23:58 +00:00
# endif /* HAVE_CHOWN */
2020-11-23 12:48:04 +00:00
}
2008-08-27 11:29:46 +00:00
}
}
# else
( void ) daemon ;
2017-07-24 09:30:12 +00:00
( void ) need_pidfile ;
2015-01-23 15:23:58 +00:00
# endif /* HAVE_KILL */
2008-08-27 11:29:46 +00:00
2012-04-05 09:30:04 +00:00
/* Set user context */
# ifdef HAVE_GETPWNAM
2015-03-23 20:20:15 +00:00
if ( cfg - > username & & cfg - > username [ 0 ] & & cfg_uid ! = ( uid_t ) - 1 ) {
2012-04-05 09:30:04 +00:00
# ifdef HAVE_SETUSERCONTEXT
/* setusercontext does initgroups, setuid, setgid, and
* also resource limits from login config , but we
* still call setresuid , setresgid to be sure to set all uid */
2015-02-20 14:48:04 +00:00
if ( setusercontext ( NULL , pwd , cfg_uid , ( unsigned )
2012-04-05 09:30:04 +00:00
LOGIN_SETALL & ~ LOGIN_SETUSER & ~ LOGIN_SETGROUP ) ! = 0 )
log_warn ( " unable to setusercontext %s: %s " ,
cfg - > username , strerror ( errno ) ) ;
2020-07-16 13:41:25 +00:00
# else
( void ) pwd ;
2012-04-05 09:30:04 +00:00
# endif /* HAVE_SETUSERCONTEXT */
}
# endif /* HAVE_GETPWNAM */
2008-08-27 11:29:46 +00:00
/* box into the chroot */
2008-05-23 14:13:07 +00:00
# ifdef HAVE_CHROOT
2007-11-01 13:22:12 +00:00
if ( cfg - > chrootdir & & cfg - > chrootdir [ 0 ] ) {
2008-04-24 12:37:01 +00:00
if ( chdir ( cfg - > chrootdir ) ) {
fatal_exit ( " unable to chdir to chroot %s: %s " ,
cfg - > chrootdir , strerror ( errno ) ) ;
}
verbose ( VERB_QUERY , " chdir to %s " , cfg - > chrootdir ) ;
2007-11-01 12:48:37 +00:00
if ( chroot ( cfg - > chrootdir ) )
fatal_exit ( " unable to chroot to %s: %s " ,
cfg - > chrootdir , strerror ( errno ) ) ;
2012-09-21 07:13:51 +00:00
if ( chdir ( " / " ) )
fatal_exit ( " unable to chdir to / in chroot %s: %s " ,
cfg - > chrootdir , strerror ( errno ) ) ;
2008-02-07 09:46:49 +00:00
verbose ( VERB_QUERY , " chroot to %s " , cfg - > chrootdir ) ;
2008-04-21 11:34:25 +00:00
if ( strncmp ( * cfgfile , cfg - > chrootdir ,
strlen ( cfg - > chrootdir ) ) = = 0 )
( * cfgfile ) + = strlen ( cfg - > chrootdir ) ;
2008-10-02 08:47:21 +00:00
/* adjust stored pidfile for chroot */
if ( daemon - > pidfile & & daemon - > pidfile [ 0 ] & &
strncmp ( daemon - > pidfile , cfg - > chrootdir ,
strlen ( cfg - > chrootdir ) ) = = 0 ) {
char * old = daemon - > pidfile ;
daemon - > pidfile = strdup ( old + strlen ( cfg - > chrootdir ) ) ;
free ( old ) ;
if ( ! daemon - > pidfile )
log_err ( " out of memory in pidfile adjust " ) ;
}
2009-01-06 15:47:15 +00:00
daemon - > chroot = strdup ( cfg - > chrootdir ) ;
if ( ! daemon - > chroot )
log_err ( " out of memory in daemon chroot dir storage " ) ;
2007-11-01 13:22:12 +00:00
}
2008-05-23 14:13:07 +00:00
# else
( void ) cfgfile ;
# endif
2008-08-27 11:29:46 +00:00
/* change to working directory inside chroot */
2008-04-24 12:37:01 +00:00
if ( cfg - > directory & & cfg - > directory [ 0 ] ) {
char * dir = cfg - > directory ;
if ( cfg - > chrootdir & & cfg - > chrootdir [ 0 ] & &
strncmp ( dir , cfg - > chrootdir ,
strlen ( cfg - > chrootdir ) ) = = 0 )
dir + = strlen ( cfg - > chrootdir ) ;
2008-04-24 13:03:59 +00:00
if ( dir [ 0 ] ) {
if ( chdir ( dir ) ) {
fatal_exit ( " Could not chdir to %s: %s " ,
dir , strerror ( errno ) ) ;
}
verbose ( VERB_QUERY , " chdir to %s " , dir ) ;
2008-04-24 12:37:01 +00:00
}
}
2008-08-27 11:29:46 +00:00
/* drop permissions after chroot, getpwnam, pidfile, syslog done*/
2008-05-23 14:13:07 +00:00
# ifdef HAVE_GETPWNAM
2015-03-23 20:20:15 +00:00
if ( cfg - > username & & cfg - > username [ 0 ] & & cfg_uid ! = ( uid_t ) - 1 ) {
2009-02-12 08:06:47 +00:00
# ifdef HAVE_INITGROUPS
2015-02-20 14:48:04 +00:00
if ( initgroups ( cfg - > username , cfg_gid ) ! = 0 )
2009-02-05 11:12:01 +00:00
log_warn ( " unable to initgroups %s: %s " ,
cfg - > username , strerror ( errno ) ) ;
2009-02-12 08:06:47 +00:00
# endif /* HAVE_INITGROUPS */
2016-06-27 08:00:55 +00:00
# ifdef HAVE_ENDPWENT
2009-02-12 08:06:47 +00:00
endpwent ( ) ;
2016-06-27 08:00:55 +00:00
# endif
2009-02-12 08:06:47 +00:00
2008-08-26 12:11:42 +00:00
# ifdef HAVE_SETRESGID
2015-02-20 14:48:04 +00:00
if ( setresgid ( cfg_gid , cfg_gid , cfg_gid ) ! = 0 )
2008-11-07 09:24:39 +00:00
# elif defined(HAVE_SETREGID) && !defined(DARWIN_BROKEN_SETREUID)
2015-02-20 14:48:04 +00:00
if ( setregid ( cfg_gid , cfg_gid ) ! = 0 )
2008-08-26 12:11:42 +00:00
# else /* use setgid */
2015-02-20 14:48:04 +00:00
if ( setgid ( cfg_gid ) ! = 0 )
2008-08-26 12:11:42 +00:00
# endif /* HAVE_SETRESGID */
2007-11-15 14:27:47 +00:00
fatal_exit ( " unable to set group id of %s: %s " ,
cfg - > username , strerror ( errno ) ) ;
2008-08-26 12:11:42 +00:00
# ifdef HAVE_SETRESUID
2015-02-20 14:48:04 +00:00
if ( setresuid ( cfg_uid , cfg_uid , cfg_uid ) ! = 0 )
2008-11-07 09:24:39 +00:00
# elif defined(HAVE_SETREUID) && !defined(DARWIN_BROKEN_SETREUID)
2015-02-20 14:48:04 +00:00
if ( setreuid ( cfg_uid , cfg_uid ) ! = 0 )
2008-08-26 12:11:42 +00:00
# else /* use setuid */
2015-02-20 14:48:04 +00:00
if ( setuid ( cfg_uid ) ! = 0 )
2008-08-26 12:11:42 +00:00
# endif /* HAVE_SETRESUID */
2007-11-15 14:27:47 +00:00
fatal_exit ( " unable to set user id of %s: %s " ,
cfg - > username , strerror ( errno ) ) ;
2008-02-07 09:46:49 +00:00
verbose ( VERB_QUERY , " drop user privileges, run as %s " ,
2007-11-08 10:44:30 +00:00
cfg - > username ) ;
}
2009-02-12 08:06:47 +00:00
# endif /* HAVE_GETPWNAM */
2008-08-27 11:29:46 +00:00
/* file logging inited after chroot,chdir,setuid is done so that
* it would succeed on SIGHUP as well */
if ( ! cfg - > use_syslog )
log_init ( cfg - > logfile , cfg - > use_syslog , cfg - > chrootdir ) ;
2007-02-22 16:22:54 +00:00
}
2007-02-22 13:36:29 +00:00
/**
* Run the daemon .
* @ param cfgfile : the config file name .
* @ param cmdline_verbose : verbosity resulting from commandline - v .
* These increase verbosity as specified in the config file .
2007-02-23 15:23:33 +00:00
* @ param debug_mode : if set , do not daemonize .
2017-07-17 08:31:59 +00:00
* @ param need_pidfile : if false , no pidfile is checked or created .
2007-02-22 13:36:29 +00:00
*/
2007-03-29 13:00:36 +00:00
static void
2020-02-10 12:56:22 +00:00
run_daemon ( const char * cfgfile , int cmdline_verbose , int debug_mode , int need_pidfile )
2007-02-22 13:36:29 +00:00
{
2007-02-22 16:22:54 +00:00
struct config_file * cfg = NULL ;
struct daemon * daemon = NULL ;
2008-08-27 11:29:46 +00:00
int done_setup = 0 ;
2007-02-22 13:36:29 +00:00
2007-02-22 16:22:54 +00:00
if ( ! ( daemon = daemon_init ( ) ) )
fatal_exit ( " alloc failure " ) ;
while ( ! daemon - > need_to_exit ) {
2008-08-27 11:29:46 +00:00
if ( done_setup )
2007-11-28 09:34:06 +00:00
verbose ( VERB_OPS , " Restart of %s. " , PACKAGE_STRING ) ;
else verbose ( VERB_OPS , " Start of %s. " , PACKAGE_STRING ) ;
2007-02-22 13:36:29 +00:00
2007-02-22 16:22:54 +00:00
/* config stuff */
if ( ! ( cfg = config_create ( ) ) )
fatal_exit ( " Could not alloc config defaults " ) ;
2009-01-06 15:47:15 +00:00
if ( ! config_read ( cfg , cfgfile , daemon - > chroot ) ) {
2008-02-14 10:37:32 +00:00
if ( errno ! = ENOENT )
2018-07-20 05:42:38 +00:00
fatal_exit ( " Could not read config file: %s. "
2018-07-20 08:58:30 +00:00
" Maybe try unbound -dd, it stays on "
" the commandline to see more errors, "
2018-07-20 08:56:47 +00:00
" or unbound-checkconf " , cfgfile ) ;
2008-02-14 10:37:32 +00:00
log_warn ( " Continuing with default config settings " ) ;
}
2020-02-10 12:56:22 +00:00
apply_settings ( daemon , cfg , cmdline_verbose , debug_mode ) ;
2015-02-20 14:48:04 +00:00
if ( ! done_setup )
config_lookup_uid ( cfg ) ;
2007-02-22 13:36:29 +00:00
2007-02-22 16:22:54 +00:00
/* prepare */
2007-02-23 13:38:54 +00:00
if ( ! daemon_open_shared_ports ( daemon ) )
2007-02-22 16:22:54 +00:00
fatal_exit ( " could not open ports " ) ;
2008-08-27 11:29:46 +00:00
if ( ! done_setup ) {
2017-07-17 08:26:49 +00:00
perform_setup ( daemon , cfg , debug_mode , & cfgfile , need_pidfile ) ;
2008-08-27 11:29:46 +00:00
done_setup = 1 ;
2008-12-18 14:36:58 +00:00
} else {
/* reopen log after HUP to facilitate log rotation */
if ( ! cfg - > use_syslog )
log_init ( cfg - > logfile , 0 , cfg - > chrootdir ) ;
}
2007-02-22 16:22:54 +00:00
/* work */
daemon_fork ( daemon ) ;
2007-02-22 13:36:29 +00:00
2007-02-22 16:22:54 +00:00
/* clean up for restart */
verbose ( VERB_ALGO , " cleanup. " ) ;
daemon_cleanup ( daemon ) ;
config_delete ( cfg ) ;
}
2007-02-22 13:36:29 +00:00
verbose ( VERB_ALGO , " Exit cleanup. " ) ;
2008-08-27 11:29:46 +00:00
/* this unlink may not work if the pidfile is located outside
* of the chroot / workdir or we no longer have permissions */
if ( daemon - > pidfile ) {
int fd ;
/* truncate pidfile */
2008-10-02 08:47:21 +00:00
fd = open ( daemon - > pidfile , O_WRONLY | O_TRUNC , 0644 ) ;
2008-08-27 11:29:46 +00:00
if ( fd ! = - 1 )
close ( fd ) ;
/* delete pidfile */
2008-10-02 08:47:21 +00:00
unlink ( daemon - > pidfile ) ;
2008-08-27 11:29:46 +00:00
}
2007-02-22 16:22:54 +00:00
daemon_delete ( daemon ) ;
2007-02-22 13:36:29 +00:00
}
2007-01-25 12:50:40 +00:00
/** getopt global, in case header files fail to declare it. */
2007-01-25 12:39:51 +00:00
extern int optind ;
2007-01-25 12:50:40 +00:00
/** getopt global, in case header files fail to declare it. */
2007-01-25 12:39:51 +00:00
extern char * optarg ;
2007-01-03 10:42:32 +00:00
2007-01-03 14:55:21 +00:00
/**
* main program . Set options given commandline arguments .
* @ param argc : number of commandline arguments .
* @ param argv : array of commandline arguments .
2007-02-06 16:26:19 +00:00
* @ return : exit status of the program .
2007-01-03 14:55:21 +00:00
*/
2007-01-03 10:42:32 +00:00
int
main ( int argc , char * argv [ ] )
{
2007-01-25 12:39:51 +00:00
int c ;
2008-11-04 14:53:50 +00:00
const char * cfgfile = CONFIGFILE ;
2009-03-02 16:43:10 +00:00
const char * winopt = NULL ;
2016-11-03 08:51:40 +00:00
const char * log_ident_default ;
2007-02-22 13:36:29 +00:00
int cmdline_verbose = 0 ;
2007-02-23 15:23:33 +00:00
int debug_mode = 0 ;
2017-07-17 08:26:49 +00:00
int need_pidfile = 1 ;
2010-05-18 12:37:04 +00:00
# ifdef UB_ON_WINDOWS
2009-03-11 16:32:07 +00:00
int cmdline_cfg = 0 ;
2010-05-18 12:37:04 +00:00
# endif
2007-01-25 12:39:51 +00:00
2021-09-10 13:11:30 +00:00
checklock_start ( ) ;
2007-10-31 10:56:31 +00:00
log_init ( NULL , 0 , NULL ) ;
2016-11-03 08:51:40 +00:00
log_ident_default = strrchr ( argv [ 0 ] , ' / ' ) ? strrchr ( argv [ 0 ] , ' / ' ) + 1 : argv [ 0 ] ;
2020-02-10 12:56:22 +00:00
log_ident_set_default ( log_ident_default ) ;
2016-11-03 08:51:40 +00:00
log_ident_set ( log_ident_default ) ;
2007-01-25 12:39:51 +00:00
/* parse the options */
2019-08-12 15:52:43 +00:00
while ( ( c = getopt ( argc , argv , " c:dhpvw:V " ) ) ! = - 1 ) {
2007-01-25 12:39:51 +00:00
switch ( c ) {
2007-02-20 16:19:00 +00:00
case ' c ' :
cfgfile = optarg ;
2010-05-18 12:37:04 +00:00
# ifdef UB_ON_WINDOWS
2009-03-11 16:32:07 +00:00
cmdline_cfg = 1 ;
2010-05-18 12:37:04 +00:00
# endif
2007-02-20 16:19:00 +00:00
break ;
2007-01-25 12:39:51 +00:00
case ' v ' :
2016-01-29 08:06:51 +00:00
cmdline_verbose + + ;
2007-02-22 13:36:29 +00:00
verbosity + + ;
2007-01-25 12:39:51 +00:00
break ;
2017-07-17 08:26:49 +00:00
case ' p ' :
need_pidfile = 0 ;
break ;
2007-02-23 15:23:33 +00:00
case ' d ' :
2014-07-29 11:48:43 +00:00
debug_mode + + ;
2007-02-23 15:23:33 +00:00
break ;
2009-02-27 16:29:40 +00:00
case ' w ' :
2009-03-02 16:43:10 +00:00
winopt = optarg ;
2009-02-27 16:29:40 +00:00
break ;
2019-08-12 15:52:43 +00:00
case ' V ' :
print_build_options ( ) ;
return 0 ;
2007-01-25 12:39:51 +00:00
case ' ? ' :
case ' h ' :
default :
usage ( ) ;
return 1 ;
}
}
argc - = optind ;
2018-09-13 08:58:21 +00:00
/* argv += optind; not using further arguments */
2007-01-25 12:39:51 +00:00
2009-03-02 16:43:10 +00:00
if ( winopt ) {
# ifdef UB_ON_WINDOWS
2009-03-11 16:32:07 +00:00
wsvc_command_option ( winopt , cfgfile , cmdline_verbose ,
2016-11-29 15:49:37 +00:00
cmdline_cfg ) ;
2009-03-02 16:43:10 +00:00
# else
fatal_exit ( " option not supported " ) ;
# endif
}
2007-01-25 12:39:51 +00:00
if ( argc ! = 0 ) {
usage ( ) ;
2007-01-03 10:42:32 +00:00
return 1 ;
}
2007-01-25 12:39:51 +00:00
2020-02-10 12:56:22 +00:00
run_daemon ( cfgfile , cmdline_verbose , debug_mode , need_pidfile ) ;
2007-10-31 10:56:31 +00:00
log_init ( NULL , 0 , NULL ) ; /* close logfile */
2018-02-02 09:27:16 +00:00
# ifndef unbound_testbound
if ( log_get_lock ( ) ) {
2019-12-04 08:44:31 +00:00
lock_basic_destroy ( ( lock_basic_type * ) log_get_lock ( ) ) ;
2018-02-02 09:27:16 +00:00
}
# endif
2007-01-03 10:42:32 +00:00
return 0 ;
}