"Fossies" - the Fresh Open Source Software Archive

Member "nsd-4.3.6/nsd.c" (6 Apr 2021, 43034 Bytes) of package /linux/misc/dns/nsd-4.3.6.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 "nsd.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.3.5_vs_4.3.6.

    1 /*
    2  * nsd.c -- nsd(8)
    3  *
    4  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
    5  *
    6  * See LICENSE for the license.
    7  *
    8  */
    9 
   10 #include "config.h"
   11 
   12 #include <sys/types.h>
   13 #include <sys/param.h>
   14 #include <sys/socket.h>
   15 #include <sys/stat.h>
   16 #include <sys/uio.h>
   17 #include <sys/wait.h>
   18 #include <netinet/in.h>
   19 #include <arpa/inet.h>
   20 #ifdef HAVE_GRP_H
   21 #include <grp.h>
   22 #endif /* HAVE_GRP_H */
   23 #ifdef HAVE_SETUSERCONTEXT
   24 #ifdef HAVE_LOGIN_CAP_H
   25 #include <login_cap.h>
   26 #endif /* HAVE_LOGIN_CAP_H */
   27 #endif /* HAVE_SETUSERCONTEXT */
   28 
   29 #include <assert.h>
   30 #include <ctype.h>
   31 #include <errno.h>
   32 #include <fcntl.h>
   33 #include <limits.h>
   34 #include <netdb.h>
   35 #include <pwd.h>
   36 #include <signal.h>
   37 #include <stdarg.h>
   38 #include <stddef.h>
   39 #include <stdio.h>
   40 #include <stdlib.h>
   41 #include <string.h>
   42 #include <time.h>
   43 #include <unistd.h>
   44 #ifdef HAVE_IFADDRS_H
   45 #include <ifaddrs.h>
   46 #endif
   47 
   48 #include "nsd.h"
   49 #include "options.h"
   50 #include "tsig.h"
   51 #include "remote.h"
   52 #include "xfrd-disk.h"
   53 #ifdef USE_DNSTAP
   54 #include "dnstap/dnstap_collector.h"
   55 #endif
   56 
   57 /* The server handler... */
   58 struct nsd nsd;
   59 static char hostname[MAXHOSTNAMELEN];
   60 extern config_parser_state_type* cfg_parser;
   61 static void version(void) ATTR_NORETURN;
   62 
   63 /*
   64  * Print the help text.
   65  *
   66  */
   67 static void
   68 usage (void)
   69 {
   70     fprintf(stderr, "Usage: nsd [OPTION]...\n");
   71     fprintf(stderr, "Name Server Daemon.\n\n");
   72     fprintf(stderr,
   73         "Supported options:\n"
   74         "  -4                   Only listen to IPv4 connections.\n"
   75         "  -6                   Only listen to IPv6 connections.\n"
   76         "  -a ip-address[@port] Listen to the specified incoming IP address (and port)\n"
   77         "                       May be specified multiple times).\n"
   78         "  -c configfile        Read specified configfile instead of %s.\n"
   79         "  -d                   do not fork as a daemon process.\n"
   80 #ifndef NDEBUG
   81         "  -F facilities        Specify the debug facilities.\n"
   82 #endif /* NDEBUG */
   83         "  -f database          Specify the database to load.\n"
   84         "  -h                   Print this help information.\n"
   85         , CONFIGFILE);
   86     fprintf(stderr,
   87         "  -i identity          Specify the identity when queried for id.server CHAOS TXT.\n"
   88         "  -I nsid              Specify the NSID. This must be a hex string.\n"
   89 #ifndef NDEBUG
   90         "  -L level             Specify the debug level.\n"
   91 #endif /* NDEBUG */
   92         "  -l filename          Specify the log file.\n"
   93         "  -N server-count      The number of servers to start.\n"
   94         "  -n tcp-count         The maximum number of TCP connections per server.\n"
   95         "  -P pidfile           Specify the PID file to write.\n"
   96         "  -p port              Specify the port to listen to.\n"
   97         "  -s seconds           Dump statistics every SECONDS seconds.\n"
   98         "  -t chrootdir         Change root to specified directory on startup.\n"
   99         );
  100     fprintf(stderr,
  101         "  -u user              Change effective uid to the specified user.\n"
  102         "  -V level             Specify verbosity level.\n"
  103         "  -v                   Print version information.\n"
  104         );
  105     fprintf(stderr, "Version %s. Report bugs to <%s>.\n",
  106         PACKAGE_VERSION, PACKAGE_BUGREPORT);
  107 }
  108 
  109 /*
  110  * Print the version exit.
  111  *
  112  */
  113 static void
  114 version(void)
  115 {
  116     fprintf(stderr, "%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
  117     fprintf(stderr, "Written by NLnet Labs.\n\n");
  118     fprintf(stderr, "Configure line: %s\n", CONFCMDLINE);
  119 #ifdef USE_MINI_EVENT
  120     fprintf(stderr, "Event loop: internal (uses select)\n");
  121 #else
  122 #  if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
  123     fprintf(stderr, "Event loop: %s %s (uses %s)\n",
  124         "libev",
  125         nsd_event_vs(),
  126         nsd_event_method());
  127 #  else
  128     fprintf(stderr, "Event loop: %s %s (uses %s)\n",
  129         "libevent",
  130         nsd_event_vs(),
  131         nsd_event_method());
  132 #  endif
  133 #endif
  134 #ifdef HAVE_SSL
  135     fprintf(stderr, "Linked with %s\n\n",
  136 #  ifdef SSLEAY_VERSION
  137         SSLeay_version(SSLEAY_VERSION)
  138 #  else
  139         OpenSSL_version(OPENSSL_VERSION)
  140 #  endif
  141         );
  142 #endif
  143     fprintf(stderr,
  144         "Copyright (C) 2001-2020 NLnet Labs.  This is free software.\n"
  145         "There is NO warranty; not even for MERCHANTABILITY or FITNESS\n"
  146         "FOR A PARTICULAR PURPOSE.\n");
  147     exit(0);
  148 }
  149 
  150 static void
  151 copyaddrinfo(struct nsd_addrinfo *dest, struct addrinfo *src)
  152 {
  153     dest->ai_flags = src->ai_flags;
  154     dest->ai_family = src->ai_family;
  155     dest->ai_socktype = src->ai_socktype;
  156     dest->ai_addrlen = src->ai_addrlen;
  157     memcpy(&dest->ai_addr, src->ai_addr, src->ai_addrlen);
  158 }
  159 
  160 static void
  161 setup_socket(
  162     struct nsd_socket *sock, const char *node, const char *port,
  163     struct addrinfo *hints)
  164 {
  165     int ret;
  166     char *host;
  167     char host_buf[sizeof("65535") + INET6_ADDRSTRLEN + 1 /* '\0' */];
  168     const char *service;
  169     struct addrinfo *addr = NULL;
  170 
  171     sock->fib = -1;
  172     if(node) {
  173         char *sep;
  174 
  175         if (strlcpy(host_buf, node, sizeof(host_buf)) >= sizeof(host_buf)) {
  176             error("cannot parse address '%s': %s", node,
  177                 strerror(ENAMETOOLONG));
  178         }
  179 
  180         host = host_buf;
  181         sep = strchr(host_buf, '@');
  182         if(sep != NULL) {
  183             *sep = '\0';
  184             service = sep + 1;
  185         } else {
  186             service = port;
  187         }
  188     } else {
  189         host = NULL;
  190         service = port;
  191     }
  192 
  193     if((ret = getaddrinfo(host, service, hints, &addr)) == 0) {
  194         copyaddrinfo(&sock->addr, addr);
  195         freeaddrinfo(addr);
  196     } else {
  197         error("cannot parse address '%s': getaddrinfo: %s %s",
  198               host ? host : "(null)",
  199               gai_strerror(ret),
  200               ret==EAI_SYSTEM ? strerror(errno) : "");
  201     }
  202 }
  203 
  204 static void
  205 figure_socket_servers(
  206     struct nsd_socket *sock, struct ip_address_option *ip)
  207 {
  208     int i;
  209     struct range_option *server;
  210 
  211     sock->servers = xalloc_zero(nsd_bitset_size(nsd.child_count));
  212     region_add_cleanup(nsd.region, free, sock->servers);
  213     nsd_bitset_init(sock->servers, nsd.child_count);
  214 
  215     if(!ip || !ip->servers) {
  216         /* every server must listen on this socket */
  217         for(i = 0; i < (int)nsd.child_count; i++) {
  218             nsd_bitset_set(sock->servers, i);
  219         }
  220         return;
  221     }
  222 
  223     /* only specific servers must listen on this socket */
  224     for(server = ip->servers; server; server = server->next) {
  225         if(server->first == server->last) {
  226             if(server->first <= 0) {
  227                 error("server %d specified for ip-address %s "
  228                       "is invalid; server ranges are 1-based",
  229                       server->first, ip->address);
  230             } else if(server->last > (int)nsd.child_count) {
  231                 error("server %d specified for ip-address %s "
  232                       "exceeds number of servers configured "
  233                       "in server-count",
  234                       server->first, ip->address);
  235             }
  236         } else {
  237             /* parse_range must ensure range itself is valid */
  238             assert(server->first < server->last);
  239             if(server->first <= 0) {
  240                 error("server range %d-%d specified for "
  241                       "ip-address %s is invalid; server "
  242                       "ranges are 1-based",
  243                       server->first, server->last, ip->address);
  244             } else if(server->last > (int)nsd.child_count) {
  245                 error("server range %d-%d specified for "
  246                       "ip-address %s exceeds number of servers "
  247                       "configured in server-count",
  248                       server->first, server->last, ip->address);
  249             }
  250         }
  251         for(i = server->first - 1; i < server->last; i++) {
  252             nsd_bitset_set(sock->servers, i);
  253         }
  254     }
  255 }
  256 
  257 static void
  258 figure_default_sockets(
  259     struct nsd_socket **udp, struct nsd_socket **tcp, size_t *ifs,
  260     const char *udp_port, const char *tcp_port,
  261     const struct addrinfo *hints)
  262 {
  263     int r;
  264     size_t i = 0, n = 1;
  265     struct addrinfo ai[2] = { *hints, *hints };
  266 
  267     assert(udp != NULL);
  268     assert(tcp != NULL);
  269     assert(ifs != NULL);
  270 
  271     ai[0].ai_socktype = SOCK_DGRAM;
  272     ai[1].ai_socktype = SOCK_STREAM;
  273 
  274 #ifdef INET6
  275 #ifdef IPV6_V6ONLY
  276     if (hints->ai_family == AF_UNSPEC) {
  277         ai[0].ai_family = AF_INET6;
  278         ai[1].ai_family = AF_INET6;
  279         n++;
  280     }
  281 #endif /* IPV6_V6ONLY */
  282 #endif /* INET6 */
  283 
  284     *udp = xalloc_zero((n + 1) * sizeof(struct nsd_socket));
  285     *tcp = xalloc_zero((n + 1) * sizeof(struct nsd_socket));
  286     region_add_cleanup(nsd.region, free, *udp);
  287     region_add_cleanup(nsd.region, free, *tcp);
  288 
  289 #ifdef INET6
  290     if(hints->ai_family == AF_UNSPEC) {
  291         /*
  292          * With IPv6 we'd like to open two separate sockets,
  293          * one for IPv4 and one for IPv6, both listening to
  294          * the wildcard address (unless the -4 or -6 flags are
  295          * specified).
  296          *
  297          * However, this is only supported on platforms where
  298          * we can turn the socket option IPV6_V6ONLY _on_.
  299          * Otherwise we just listen to a single IPv6 socket
  300          * and any incoming IPv4 connections will be
  301          * automatically mapped to our IPv6 socket.
  302          */
  303 #ifdef IPV6_V6ONLY
  304         struct addrinfo *addrs[2] = { NULL, NULL };
  305 
  306         if((r = getaddrinfo(NULL, udp_port, &ai[0], &addrs[0])) == 0 &&
  307            (r = getaddrinfo(NULL, tcp_port, &ai[1], &addrs[1])) == 0)
  308         {
  309             (*udp)[i].flags |= NSD_SOCKET_IS_OPTIONAL;
  310             (*udp)[i].fib = -1;
  311             copyaddrinfo(&(*udp)[i].addr, addrs[0]);
  312             figure_socket_servers(&(*udp)[i], NULL);
  313             (*tcp)[i].flags |= NSD_SOCKET_IS_OPTIONAL;
  314             (*tcp)[i].fib = -1;
  315             copyaddrinfo(&(*tcp)[i].addr, addrs[1]);
  316             figure_socket_servers(&(*tcp)[i], NULL);
  317             i++;
  318         } else {
  319             log_msg(LOG_WARNING, "No IPv6, fallback to IPv4. getaddrinfo: %s",
  320               r == EAI_SYSTEM ? strerror(errno) : gai_strerror(r));
  321         }
  322 
  323         if(addrs[0])
  324             freeaddrinfo(addrs[0]);
  325         if(addrs[1])
  326             freeaddrinfo(addrs[1]);
  327 
  328         ai[0].ai_family = AF_INET;
  329         ai[1].ai_family = AF_INET;
  330 #endif /* IPV6_V6ONLY */
  331     }
  332 #endif /* INET6 */
  333 
  334     *ifs = i + 1;
  335     setup_socket(&(*udp)[i], NULL, udp_port, &ai[0]);
  336     figure_socket_servers(&(*udp)[i], NULL);
  337     setup_socket(&(*tcp)[i], NULL, tcp_port, &ai[1]);
  338     figure_socket_servers(&(*tcp)[i], NULL);
  339 }
  340 
  341 #ifdef HAVE_GETIFADDRS
  342 static int
  343 find_device(
  344     struct nsd_socket *sock,
  345     const struct ifaddrs *ifa)
  346 {
  347     for(; ifa != NULL; ifa = ifa->ifa_next) {
  348         if((ifa->ifa_addr == NULL) ||
  349            (ifa->ifa_addr->sa_family != sock->addr.ai_family) ||
  350            ((ifa->ifa_flags & IFF_UP) == 0 ||
  351             (ifa->ifa_flags & IFF_LOOPBACK) != 0 ||
  352             (ifa->ifa_flags & IFF_RUNNING) == 0))
  353         {
  354             continue;
  355         }
  356 
  357 #ifdef INET6
  358         if(ifa->ifa_addr->sa_family == AF_INET6) {
  359             struct sockaddr_in6 *sa1, *sa2;
  360             size_t sz = sizeof(struct in6_addr);
  361             sa1 = (struct sockaddr_in6 *)ifa->ifa_addr;
  362             sa2 = (struct sockaddr_in6 *)&sock->addr.ai_addr;
  363             if(memcmp(&sa1->sin6_addr, &sa2->sin6_addr, sz) == 0) {
  364                 break;
  365             }
  366         } else
  367 #endif
  368         if(ifa->ifa_addr->sa_family == AF_INET) {
  369             struct sockaddr_in *sa1, *sa2;
  370             sa1 = (struct sockaddr_in *)ifa->ifa_addr;
  371             sa2 = (struct sockaddr_in *)&sock->addr.ai_addr;
  372             if(sa1->sin_addr.s_addr == sa2->sin_addr.s_addr) {
  373                 break;
  374             }
  375         }
  376     }
  377 
  378     if(ifa != NULL) {
  379         size_t len = strlcpy(sock->device, ifa->ifa_name, sizeof(sock->device));
  380         if(len < sizeof(sock->device)) {
  381             char *colon = strchr(sock->device, ':');
  382             if(colon != NULL)
  383                 *colon = '\0';
  384             return 1;
  385         }
  386     }
  387 
  388     return 0;
  389 }
  390 #endif /* HAVE_GETIFADDRS */
  391 
  392 static void
  393 figure_sockets(
  394     struct nsd_socket **udp, struct nsd_socket **tcp, size_t *ifs,
  395     struct ip_address_option *ips,
  396     const char *udp_port, const char *tcp_port,
  397     const struct addrinfo *hints)
  398 {
  399     size_t i = 0;
  400     struct addrinfo ai = *hints;
  401     struct ip_address_option *ip;
  402 #ifdef HAVE_GETIFADDRS
  403     struct ifaddrs *ifa = NULL;
  404 #endif
  405     int bind_device = 0;
  406 
  407     if(!ips) {
  408         figure_default_sockets(
  409             udp, tcp, ifs, udp_port, tcp_port, hints);
  410         return;
  411     }
  412 
  413     *ifs = 0;
  414     for(ip = ips; ip; ip = ip->next) {
  415         (*ifs)++;
  416         bind_device |= (ip->dev != 0);
  417     }
  418 
  419 #ifdef HAVE_GETIFADDRS
  420     if(bind_device && getifaddrs(&ifa) == -1) {
  421         error("getifaddrs failed: %s", strerror(errno));
  422     }
  423 #endif
  424 
  425     *udp = xalloc_zero((*ifs + 1) * sizeof(struct nsd_socket));
  426     *tcp = xalloc_zero((*ifs + 1) * sizeof(struct nsd_socket));
  427     region_add_cleanup(nsd.region, free, *udp);
  428     region_add_cleanup(nsd.region, free, *tcp);
  429 
  430     ai.ai_flags |= AI_NUMERICHOST;
  431     for(ip = ips, i = 0; ip; ip = ip->next, i++) {
  432         ai.ai_socktype = SOCK_DGRAM;
  433         setup_socket(&(*udp)[i], ip->address, udp_port, &ai);
  434         figure_socket_servers(&(*udp)[i], ip);
  435         ai.ai_socktype = SOCK_STREAM;
  436         setup_socket(&(*tcp)[i], ip->address, tcp_port, &ai);
  437         figure_socket_servers(&(*tcp)[i], ip);
  438         if(ip->fib != -1) {
  439             (*udp)[i].fib = ip->fib;
  440             (*tcp)[i].fib = ip->fib;
  441         }
  442 #ifdef HAVE_GETIFADDRS
  443         if(ip->dev != 0) {
  444             (*udp)[i].flags |= NSD_BIND_DEVICE;
  445             (*tcp)[i].flags |= NSD_BIND_DEVICE;
  446             if(ifa != NULL && (find_device(&(*udp)[i], ifa) == 0 ||
  447                                find_device(&(*tcp)[i], ifa) == 0))
  448             {
  449                 error("cannot find device for ip-address %s",
  450                       ip->address);
  451             }
  452         }
  453 #endif
  454     }
  455 
  456     assert(i == *ifs);
  457 
  458 #ifdef HAVE_GETIFADDRS
  459     if(ifa != NULL) {
  460         freeifaddrs(ifa);
  461     }
  462 #endif
  463 }
  464 
  465 /* print server affinity for given socket. "*" if socket has no affinity with
  466    any specific server, "x-y" if socket has affinity with more than two
  467    consecutively numbered servers, "x" if socket has affinity with a specific
  468    server number, which is not necessarily just one server. e.g. "1 3" is
  469    printed if socket has affinity with servers number one and three, but not
  470    server number two. */
  471 static ssize_t
  472 print_socket_servers(struct nsd_socket *sock, char *buf, size_t bufsz)
  473 {
  474     int i, x, y, z, n = (int)(sock->servers->size);
  475     char *sep = "";
  476     size_t off, tot;
  477     ssize_t cnt = 0;
  478 
  479     assert(bufsz != 0);
  480 
  481     off = tot = 0;
  482     x = y = z = -1;
  483     for (i = 0; i <= n; i++) {
  484         if (i == n || !nsd_bitset_isset(sock->servers, i)) {
  485             cnt = 0;
  486             if (i == n && x == -1) {
  487                 assert(y == -1);
  488                 assert(z == -1);
  489                 cnt = snprintf(buf, bufsz, "-");
  490             } else if (y > z) {
  491                 assert(x > z);
  492                 if (x == 0 && y == (n - 1)) {
  493                     assert(z == -1);
  494                     cnt = snprintf(buf+off, bufsz-off,
  495                                    "*");
  496                 } else if (x == y) {
  497                     cnt = snprintf(buf+off, bufsz-off,
  498                                    "%s%d", sep, x+1);
  499                 } else if (x == (y - 1)) {
  500                     cnt = snprintf(buf+off, bufsz-off,
  501                                    "%s%d %d", sep, x+1, y+1);
  502                 } else {
  503                     assert(y > (x + 1));
  504                     cnt = snprintf(buf+off, bufsz-off,
  505                                    "%s%d-%d", sep, x+1, y+1);
  506                 }
  507             }
  508             z = i;
  509             if (cnt > 0) {
  510                 tot += (size_t)cnt;
  511                 off = (tot < bufsz) ? tot : bufsz - 1;
  512                 sep = " ";
  513             } else if (cnt < 0) {
  514                 return -1;
  515             }
  516         } else if (x <= z) {
  517             x = y = i;
  518         } else {
  519             assert(x > z);
  520             y = i;
  521         }
  522     }
  523 
  524     return tot;
  525 }
  526 
  527 static void
  528 print_sockets(
  529     struct nsd_socket *udp, struct nsd_socket *tcp, size_t ifs)
  530 {
  531     char sockbuf[INET6_ADDRSTRLEN + 6 + 1];
  532     char *serverbuf;
  533     size_t i, serverbufsz, servercnt;
  534     const char *fmt = "listen on ip-address %s (%s) with server(s): %s";
  535     struct nsd_bitset *servers;
  536 
  537     if(ifs == 0) {
  538         return;
  539     }
  540 
  541     assert(udp != NULL);
  542     assert(tcp != NULL);
  543 
  544     servercnt = udp[0].servers->size;
  545     serverbufsz = (((servercnt / 10) * servercnt) + servercnt) + 1;
  546     serverbuf = xalloc(serverbufsz);
  547 
  548     /* warn user of unused servers */
  549     servers = xalloc(nsd_bitset_size(servercnt));
  550     nsd_bitset_init(servers, (size_t)servercnt);
  551 
  552     for(i = 0; i < ifs; i++) {
  553         assert(udp[i].servers->size == servercnt);
  554         addrport2str(&udp[i].addr.ai_addr, sockbuf, sizeof(sockbuf));
  555         print_socket_servers(&udp[i], serverbuf, serverbufsz);
  556         nsd_bitset_or(servers, servers, udp[i].servers);
  557         VERBOSITY(3, (LOG_NOTICE, fmt, sockbuf, "udp", serverbuf));
  558         assert(tcp[i].servers->size == servercnt);
  559         addrport2str(&tcp[i].addr.ai_addr, sockbuf, sizeof(sockbuf));
  560         print_socket_servers(&tcp[i], serverbuf, serverbufsz);
  561         nsd_bitset_or(servers, servers, tcp[i].servers);
  562         VERBOSITY(3, (LOG_NOTICE, fmt, sockbuf, "tcp", serverbuf));
  563     }
  564 
  565 
  566     /* warn user of unused servers */
  567     for(i = 0; i < servercnt; i++) {
  568         if(!nsd_bitset_isset(servers, i)) {
  569             log_msg(LOG_WARNING, "server %zu will not listen on "
  570                                  "any specified ip-address", i+1);
  571         }
  572     }
  573     free(serverbuf);
  574     free(servers);
  575 }
  576 
  577 #ifdef HAVE_CPUSET_T
  578 static void free_cpuset(void *ptr)
  579 {
  580     cpuset_t *set = (cpuset_t *)ptr;
  581     cpuset_destroy(set);
  582 }
  583 #endif
  584 
  585 /*
  586  * Fetch the nsd parent process id from the nsd pidfile
  587  *
  588  */
  589 pid_t
  590 readpid(const char *file)
  591 {
  592     int fd;
  593     pid_t pid;
  594     char pidbuf[16];
  595     char *t;
  596     int l;
  597 
  598     if ((fd = open(file, O_RDONLY)) == -1) {
  599         return -1;
  600     }
  601 
  602     if (((l = read(fd, pidbuf, sizeof(pidbuf)))) == -1) {
  603         close(fd);
  604         return -1;
  605     }
  606 
  607     close(fd);
  608 
  609     /* Empty pidfile means no pidfile... */
  610     if (l == 0) {
  611         errno = ENOENT;
  612         return -1;
  613     }
  614 
  615     pid = (pid_t) strtol(pidbuf, &t, 10);
  616 
  617     if (*t && *t != '\n') {
  618         return -1;
  619     }
  620     return pid;
  621 }
  622 
  623 /*
  624  * Store the nsd parent process id in the nsd pidfile
  625  *
  626  */
  627 int
  628 writepid(struct nsd *nsd)
  629 {
  630     int fd;
  631     char pidbuf[32];
  632     size_t count = 0;
  633     if(!nsd->pidfile || !nsd->pidfile[0])
  634         return 0;
  635 
  636     snprintf(pidbuf, sizeof(pidbuf), "%lu\n", (unsigned long) nsd->pid);
  637 
  638     if((fd = open(nsd->pidfile, O_WRONLY | O_CREAT | O_TRUNC
  639 #ifdef O_NOFOLLOW
  640         | O_NOFOLLOW
  641 #endif
  642         , 0644)) == -1) {
  643         log_msg(LOG_ERR, "cannot open pidfile %s: %s",
  644             nsd->pidfile, strerror(errno));
  645         return -1;
  646     }
  647 
  648     while(count < strlen(pidbuf)) {
  649         ssize_t r = write(fd, pidbuf+count, strlen(pidbuf)-count);
  650         if(r == -1) {
  651             if(errno == EAGAIN || errno == EINTR)
  652                 continue;
  653             log_msg(LOG_ERR, "cannot write pidfile %s: %s",
  654                 nsd->pidfile, strerror(errno));
  655             close(fd);
  656             return -1;
  657         } else if(r == 0) {
  658             log_msg(LOG_ERR, "cannot write any bytes to "
  659                 "pidfile %s: write returns 0 bytes written",
  660                 nsd->pidfile);
  661             close(fd);
  662             return -1;
  663         }
  664         count += r;
  665     }
  666     close(fd);
  667 
  668     if (chown(nsd->pidfile, nsd->uid, nsd->gid) == -1) {
  669         log_msg(LOG_ERR, "cannot chown %u.%u %s: %s",
  670             (unsigned) nsd->uid, (unsigned) nsd->gid,
  671             nsd->pidfile, strerror(errno));
  672         return -1;
  673     }
  674 
  675     return 0;
  676 }
  677 
  678 void
  679 unlinkpid(const char* file)
  680 {
  681     int fd = -1;
  682 
  683     if (file && file[0]) {
  684         /* truncate pidfile */
  685         fd = open(file, O_WRONLY | O_TRUNC, 0644);
  686         if (fd == -1) {
  687             /* Truncate the pid file.  */
  688             log_msg(LOG_ERR, "can not truncate the pid file %s: %s", file, strerror(errno));
  689         } else {
  690             close(fd);
  691         }
  692 
  693         /* unlink pidfile */
  694         if (unlink(file) == -1) {
  695             /* this unlink may not work if the pidfile is located
  696              * outside of the chroot/workdir or we no longer
  697              * have permissions */
  698             VERBOSITY(3, (LOG_WARNING,
  699                 "failed to unlink pidfile %s: %s",
  700                 file, strerror(errno)));
  701         }
  702     }
  703 }
  704 
  705 /*
  706  * Incoming signals, set appropriate actions.
  707  *
  708  */
  709 void
  710 sig_handler(int sig)
  711 {
  712     /* To avoid race cond. We really don't want to use log_msg() in this handler */
  713 
  714     /* Are we a child server? */
  715     if (nsd.server_kind != NSD_SERVER_MAIN) {
  716         switch (sig) {
  717         case SIGCHLD:
  718             nsd.signal_hint_child = 1;
  719             break;
  720         case SIGALRM:
  721             break;
  722         case SIGINT:
  723         case SIGTERM:
  724             nsd.signal_hint_quit = 1;
  725             break;
  726         case SIGILL:
  727         case SIGUSR1:   /* Dump stats on SIGUSR1.  */
  728             nsd.signal_hint_statsusr = 1;
  729             break;
  730         default:
  731             break;
  732         }
  733         return;
  734     }
  735 
  736     /* We are the main process */
  737     switch (sig) {
  738     case SIGCHLD:
  739         nsd.signal_hint_child = 1;
  740         return;
  741     case SIGHUP:
  742         nsd.signal_hint_reload_hup = 1;
  743         return;
  744     case SIGALRM:
  745         nsd.signal_hint_stats = 1;
  746         break;
  747     case SIGILL:
  748         /*
  749          * For backwards compatibility with BIND 8 and older
  750          * versions of NSD.
  751          */
  752         nsd.signal_hint_statsusr = 1;
  753         break;
  754     case SIGUSR1:
  755         /* Dump statistics.  */
  756         nsd.signal_hint_statsusr = 1;
  757         break;
  758     case SIGINT:
  759     case SIGTERM:
  760     default:
  761         nsd.signal_hint_shutdown = 1;
  762         break;
  763     }
  764 }
  765 
  766 /*
  767  * Statistic output...
  768  *
  769  */
  770 #ifdef BIND8_STATS
  771 void
  772 bind8_stats (struct nsd *nsd)
  773 {
  774     char buf[MAXSYSLOGMSGLEN];
  775     char *msg, *t;
  776     int i, len;
  777 
  778     /* Current time... */
  779     time_t now;
  780     if(!nsd->st.period)
  781         return;
  782     time(&now);
  783 
  784     /* NSTATS */
  785     t = msg = buf + snprintf(buf, MAXSYSLOGMSGLEN, "NSTATS %lld %lu",
  786                  (long long) now, (unsigned long) nsd->st.boot);
  787     for (i = 0; i <= 255; i++) {
  788         /* How much space left? */
  789         if ((len = buf + MAXSYSLOGMSGLEN - t) < 32) {
  790             log_msg(LOG_INFO, "%s", buf);
  791             t = msg;
  792             len = buf + MAXSYSLOGMSGLEN - t;
  793         }
  794 
  795         if (nsd->st.qtype[i] != 0) {
  796             t += snprintf(t, len, " %s=%lu", rrtype_to_string(i), nsd->st.qtype[i]);
  797         }
  798     }
  799     if (t > msg)
  800         log_msg(LOG_INFO, "%s", buf);
  801 
  802     /* XSTATS */
  803     /* Only print it if we're in the main daemon or have anything to report... */
  804     if (nsd->server_kind == NSD_SERVER_MAIN
  805         || nsd->st.dropped || nsd->st.raxfr || (nsd->st.qudp + nsd->st.qudp6 - nsd->st.dropped)
  806         || nsd->st.txerr || nsd->st.opcode[OPCODE_QUERY] || nsd->st.opcode[OPCODE_IQUERY]
  807         || nsd->st.wrongzone || nsd->st.ctcp + nsd->st.ctcp6 || nsd->st.rcode[RCODE_SERVFAIL]
  808         || nsd->st.rcode[RCODE_FORMAT] || nsd->st.nona || nsd->st.rcode[RCODE_NXDOMAIN]
  809         || nsd->st.opcode[OPCODE_UPDATE]) {
  810 
  811         log_msg(LOG_INFO, "XSTATS %lld %lu"
  812             " RR=%lu RNXD=%lu RFwdR=%lu RDupR=%lu RFail=%lu RFErr=%lu RErr=%lu RAXFR=%lu"
  813             " RLame=%lu ROpts=%lu SSysQ=%lu SAns=%lu SFwdQ=%lu SDupQ=%lu SErr=%lu RQ=%lu"
  814             " RIQ=%lu RFwdQ=%lu RDupQ=%lu RTCP=%lu SFwdR=%lu SFail=%lu SFErr=%lu SNaAns=%lu"
  815             " SNXD=%lu RUQ=%lu RURQ=%lu RUXFR=%lu RUUpd=%lu",
  816             (long long) now, (unsigned long) nsd->st.boot,
  817             nsd->st.dropped, (unsigned long)0, (unsigned long)0, (unsigned long)0, (unsigned long)0,
  818             (unsigned long)0, (unsigned long)0, nsd->st.raxfr, (unsigned long)0, (unsigned long)0,
  819             (unsigned long)0, nsd->st.qudp + nsd->st.qudp6 - nsd->st.dropped, (unsigned long)0,
  820             (unsigned long)0, nsd->st.txerr,
  821             nsd->st.opcode[OPCODE_QUERY], nsd->st.opcode[OPCODE_IQUERY], nsd->st.wrongzone,
  822             (unsigned long)0, nsd->st.ctcp + nsd->st.ctcp6,
  823             (unsigned long)0, nsd->st.rcode[RCODE_SERVFAIL], nsd->st.rcode[RCODE_FORMAT],
  824             nsd->st.nona, nsd->st.rcode[RCODE_NXDOMAIN],
  825             (unsigned long)0, (unsigned long)0, (unsigned long)0, nsd->st.opcode[OPCODE_UPDATE]);
  826     }
  827 
  828 }
  829 #endif /* BIND8_STATS */
  830 
  831 extern char *optarg;
  832 extern int optind;
  833 
  834 int
  835 main(int argc, char *argv[])
  836 {
  837     /* Scratch variables... */
  838     int c;
  839     pid_t   oldpid;
  840     size_t i;
  841     struct sigaction action;
  842 #ifdef HAVE_GETPWNAM
  843     struct passwd *pwd = NULL;
  844 #endif /* HAVE_GETPWNAM */
  845 
  846     struct ip_address_option *ip;
  847     struct addrinfo hints;
  848     const char *udp_port = 0;
  849     const char *tcp_port = 0;
  850 
  851     const char *configfile = CONFIGFILE;
  852 
  853     char* argv0 = (argv0 = strrchr(argv[0], '/')) ? argv0 + 1 : argv[0];
  854 
  855     log_init(argv0);
  856 
  857     /* Initialize the server handler... */
  858     memset(&nsd, 0, sizeof(struct nsd));
  859     nsd.region      = region_create(xalloc, free);
  860     nsd.dbfile  = 0;
  861     nsd.pidfile = 0;
  862     nsd.server_kind = NSD_SERVER_MAIN;
  863     memset(&hints, 0, sizeof(hints));
  864     hints.ai_family = DEFAULT_AI_FAMILY;
  865     hints.ai_flags = AI_PASSIVE;
  866     nsd.identity    = 0;
  867     nsd.version = VERSION;
  868     nsd.username    = 0;
  869     nsd.chrootdir   = 0;
  870     nsd.nsid    = NULL;
  871     nsd.nsid_len    = 0;
  872 
  873     nsd.child_count = 0;
  874     nsd.maximum_tcp_count = 0;
  875     nsd.current_tcp_count = 0;
  876     nsd.file_rotation_ok = 0;
  877 
  878     /* Set up our default identity to gethostname(2) */
  879     if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {
  880         nsd.identity = hostname;
  881     } else {
  882         log_msg(LOG_ERR,
  883             "failed to get the host name: %s - using default identity",
  884             strerror(errno));
  885         nsd.identity = IDENTITY;
  886     }
  887 
  888     /* Create region where options will be stored and set defaults */
  889     nsd.options = nsd_options_create(region_create_custom(xalloc, free,
  890         DEFAULT_CHUNK_SIZE, DEFAULT_LARGE_OBJECT_SIZE,
  891         DEFAULT_INITIAL_CLEANUP_SIZE, 1));
  892 
  893     /* Parse the command line... */
  894     while ((c = getopt(argc, argv, "46a:c:df:hi:I:l:N:n:P:p:s:u:t:X:V:v"
  895 #ifndef NDEBUG /* <mattthijs> only when configured with --enable-checking */
  896         "F:L:"
  897 #endif /* NDEBUG */
  898         )) != -1) {
  899         switch (c) {
  900         case '4':
  901             hints.ai_family = AF_INET;
  902             break;
  903         case '6':
  904 #ifdef INET6
  905             hints.ai_family = AF_INET6;
  906 #else /* !INET6 */
  907             error("IPv6 support not enabled.");
  908 #endif /* INET6 */
  909             break;
  910         case 'a':
  911             ip = region_alloc_zero(
  912                 nsd.options->region, sizeof(*ip));
  913             ip->address = region_strdup(
  914                 nsd.options->region, optarg);
  915             ip->next = nsd.options->ip_addresses;
  916             nsd.options->ip_addresses = ip;
  917             break;
  918         case 'c':
  919             configfile = optarg;
  920             break;
  921         case 'd':
  922             nsd.debug = 1;
  923             break;
  924         case 'f':
  925             nsd.dbfile = optarg;
  926             break;
  927         case 'h':
  928             usage();
  929             exit(0);
  930         case 'i':
  931             nsd.identity = optarg;
  932             break;
  933         case 'I':
  934             if (nsd.nsid_len != 0) {
  935                 /* can only be given once */
  936                 break;
  937             }
  938             if (strncasecmp(optarg, "ascii_", 6) == 0) {
  939                 nsd.nsid = xalloc(strlen(optarg+6));
  940                 nsd.nsid_len = strlen(optarg+6);
  941                 memmove(nsd.nsid, optarg+6, nsd.nsid_len);
  942             } else {
  943                 if (strlen(optarg) % 2 != 0) {
  944                     error("the NSID must be a hex string of an even length.");
  945                 }
  946                 nsd.nsid = xalloc(strlen(optarg) / 2);
  947                 nsd.nsid_len = strlen(optarg) / 2;
  948                 if (hex_pton(optarg, nsd.nsid, nsd.nsid_len) == -1) {
  949                     error("hex string cannot be parsed '%s' in NSID.", optarg);
  950                 }
  951             }
  952             break;
  953         case 'l':
  954             nsd.log_filename = optarg;
  955             break;
  956         case 'N':
  957             i = atoi(optarg);
  958             if (i <= 0) {
  959                 error("number of child servers must be greater than zero.");
  960             } else {
  961                 nsd.child_count = i;
  962             }
  963             break;
  964         case 'n':
  965             i = atoi(optarg);
  966             if (i <= 0) {
  967                 error("number of concurrent TCP connections must greater than zero.");
  968             } else {
  969                 nsd.maximum_tcp_count = i;
  970             }
  971             break;
  972         case 'P':
  973             nsd.pidfile = optarg;
  974             break;
  975         case 'p':
  976             if (atoi(optarg) == 0) {
  977                 error("port argument must be numeric.");
  978             }
  979             tcp_port = optarg;
  980             udp_port = optarg;
  981             break;
  982         case 's':
  983 #ifdef BIND8_STATS
  984             nsd.st.period = atoi(optarg);
  985 #else /* !BIND8_STATS */
  986             error("BIND 8 statistics not enabled.");
  987 #endif /* BIND8_STATS */
  988             break;
  989         case 't':
  990 #ifdef HAVE_CHROOT
  991             nsd.chrootdir = optarg;
  992 #else /* !HAVE_CHROOT */
  993             error("chroot not supported on this platform.");
  994 #endif /* HAVE_CHROOT */
  995             break;
  996         case 'u':
  997             nsd.username = optarg;
  998             break;
  999         case 'V':
 1000             verbosity = atoi(optarg);
 1001             break;
 1002         case 'v':
 1003             version();
 1004             /* version exits */
 1005             break;
 1006 #ifndef NDEBUG
 1007         case 'F':
 1008             sscanf(optarg, "%x", &nsd_debug_facilities);
 1009             break;
 1010         case 'L':
 1011             sscanf(optarg, "%d", &nsd_debug_level);
 1012             break;
 1013 #endif /* NDEBUG */
 1014         case '?':
 1015         default:
 1016             usage();
 1017             exit(1);
 1018         }
 1019     }
 1020     argc -= optind;
 1021     /* argv += optind; */
 1022 
 1023     /* Commandline parse error */
 1024     if (argc != 0) {
 1025         usage();
 1026         exit(1);
 1027     }
 1028 
 1029     if (strlen(nsd.identity) > UCHAR_MAX) {
 1030         error("server identity too long (%u characters)",
 1031               (unsigned) strlen(nsd.identity));
 1032     }
 1033     if(!tsig_init(nsd.region))
 1034         error("init tsig failed");
 1035 
 1036     /* Read options */
 1037     if(!parse_options_file(nsd.options, configfile, NULL, NULL)) {
 1038         error("could not read config: %s\n", configfile);
 1039     }
 1040     if(!parse_zone_list_file(nsd.options)) {
 1041         error("could not read zonelist file %s\n",
 1042             nsd.options->zonelistfile);
 1043     }
 1044     if(nsd.options->do_ip4 && !nsd.options->do_ip6) {
 1045         hints.ai_family = AF_INET;
 1046     }
 1047 #ifdef INET6
 1048     if(nsd.options->do_ip6 && !nsd.options->do_ip4) {
 1049         hints.ai_family = AF_INET6;
 1050     }
 1051 #endif /* INET6 */
 1052     if (verbosity == 0)
 1053         verbosity = nsd.options->verbosity;
 1054 #ifndef NDEBUG
 1055     if (nsd_debug_level > 0 && verbosity == 0)
 1056         verbosity = nsd_debug_level;
 1057 #endif /* NDEBUG */
 1058     if(nsd.options->debug_mode) nsd.debug=1;
 1059     if(!nsd.dbfile)
 1060     {
 1061         if(nsd.options->database)
 1062             nsd.dbfile = nsd.options->database;
 1063         else
 1064             nsd.dbfile = DBFILE;
 1065     }
 1066     if(!nsd.pidfile)
 1067     {
 1068         if(nsd.options->pidfile)
 1069             nsd.pidfile = nsd.options->pidfile;
 1070         else
 1071             nsd.pidfile = PIDFILE;
 1072     }
 1073     if(strcmp(nsd.identity, hostname)==0 || strcmp(nsd.identity,IDENTITY)==0)
 1074     {
 1075         if(nsd.options->identity)
 1076             nsd.identity = nsd.options->identity;
 1077     }
 1078     if(nsd.options->version) {
 1079         nsd.version = nsd.options->version;
 1080     }
 1081     if (nsd.options->logfile && !nsd.log_filename) {
 1082         nsd.log_filename = nsd.options->logfile;
 1083     }
 1084     if(nsd.child_count == 0) {
 1085         nsd.child_count = nsd.options->server_count;
 1086     }
 1087 
 1088 #ifdef SO_REUSEPORT
 1089     if(nsd.options->reuseport && nsd.child_count > 1) {
 1090         nsd.reuseport = nsd.child_count;
 1091     }
 1092 #endif /* SO_REUSEPORT */
 1093     if(nsd.maximum_tcp_count == 0) {
 1094         nsd.maximum_tcp_count = nsd.options->tcp_count;
 1095     }
 1096     nsd.tcp_timeout = nsd.options->tcp_timeout;
 1097     nsd.tcp_query_count = nsd.options->tcp_query_count;
 1098     nsd.tcp_mss = nsd.options->tcp_mss;
 1099     nsd.outgoing_tcp_mss = nsd.options->outgoing_tcp_mss;
 1100     nsd.ipv4_edns_size = nsd.options->ipv4_edns_size;
 1101     nsd.ipv6_edns_size = nsd.options->ipv6_edns_size;
 1102 #ifdef HAVE_SSL
 1103     nsd.tls_ctx = NULL;
 1104 #endif
 1105 
 1106     if(udp_port == 0)
 1107     {
 1108         if(nsd.options->port != 0) {
 1109             udp_port = nsd.options->port;
 1110             tcp_port = nsd.options->port;
 1111         } else {
 1112             udp_port = UDP_PORT;
 1113             tcp_port = TCP_PORT;
 1114         }
 1115     }
 1116 #ifdef BIND8_STATS
 1117     if(nsd.st.period == 0) {
 1118         nsd.st.period = nsd.options->statistics;
 1119     }
 1120 #endif /* BIND8_STATS */
 1121 #ifdef HAVE_CHROOT
 1122     if(nsd.chrootdir == 0) nsd.chrootdir = nsd.options->chroot;
 1123 #ifdef CHROOTDIR
 1124     /* if still no chrootdir, fallback to default */
 1125     if(nsd.chrootdir == 0) nsd.chrootdir = CHROOTDIR;
 1126 #endif /* CHROOTDIR */
 1127 #endif /* HAVE_CHROOT */
 1128     if(nsd.username == 0) {
 1129         if(nsd.options->username) nsd.username = nsd.options->username;
 1130         else nsd.username = USER;
 1131     }
 1132     if(nsd.options->zonesdir && nsd.options->zonesdir[0]) {
 1133         if(chdir(nsd.options->zonesdir)) {
 1134             error("cannot chdir to '%s': %s",
 1135                 nsd.options->zonesdir, strerror(errno));
 1136         }
 1137         DEBUG(DEBUG_IPC,1, (LOG_INFO, "changed directory to %s",
 1138             nsd.options->zonesdir));
 1139     }
 1140 
 1141     /* EDNS0 */
 1142     edns_init_data(&nsd.edns_ipv4, nsd.options->ipv4_edns_size);
 1143 #if defined(INET6)
 1144 #if defined(IPV6_USE_MIN_MTU) || defined(IPV6_MTU)
 1145     edns_init_data(&nsd.edns_ipv6, nsd.options->ipv6_edns_size);
 1146 #else /* no way to set IPV6 MTU, send no bigger than that. */
 1147     if (nsd.options->ipv6_edns_size < IPV6_MIN_MTU)
 1148         edns_init_data(&nsd.edns_ipv6, nsd.options->ipv6_edns_size);
 1149     else
 1150         edns_init_data(&nsd.edns_ipv6, IPV6_MIN_MTU);
 1151 #endif /* IPV6 MTU) */
 1152 #endif /* defined(INET6) */
 1153 
 1154     if (nsd.nsid_len == 0 && nsd.options->nsid) {
 1155         if (strlen(nsd.options->nsid) % 2 != 0) {
 1156             error("the NSID must be a hex string of an even length.");
 1157         }
 1158         nsd.nsid = xalloc(strlen(nsd.options->nsid) / 2);
 1159         nsd.nsid_len = strlen(nsd.options->nsid) / 2;
 1160         if (hex_pton(nsd.options->nsid, nsd.nsid, nsd.nsid_len) == -1) {
 1161             error("hex string cannot be parsed '%s' in NSID.", nsd.options->nsid);
 1162         }
 1163     }
 1164     edns_init_nsid(&nsd.edns_ipv4, nsd.nsid_len);
 1165 #if defined(INET6)
 1166     edns_init_nsid(&nsd.edns_ipv6, nsd.nsid_len);
 1167 #endif /* defined(INET6) */
 1168 
 1169 #ifdef HAVE_CPUSET_T
 1170     nsd.use_cpu_affinity = (nsd.options->cpu_affinity != NULL);
 1171     if(nsd.use_cpu_affinity) {
 1172         int ncpus;
 1173         struct cpu_option* opt = nsd.options->cpu_affinity;
 1174 
 1175         if((ncpus = number_of_cpus()) == -1) {
 1176             error("cannot retrieve number of cpus: %s",
 1177                   strerror(errno));
 1178         }
 1179         nsd.cpuset = cpuset_create();
 1180         region_add_cleanup(nsd.region, free_cpuset, nsd.cpuset);
 1181         for(; opt; opt = opt->next) {
 1182             assert(opt->cpu >= 0);
 1183             if(opt->cpu >= ncpus) {
 1184                 error("invalid cpu %d specified in "
 1185                       "cpu-affinity", opt->cpu);
 1186             }
 1187             cpuset_set((cpuid_t)opt->cpu, nsd.cpuset);
 1188         }
 1189     }
 1190     if(nsd.use_cpu_affinity) {
 1191         int cpu;
 1192         struct cpu_map_option *opt
 1193             = nsd.options->service_cpu_affinity;
 1194 
 1195         cpu = -1;
 1196         for(; opt && cpu == -1; opt = opt->next) {
 1197             if(opt->service == -1) {
 1198                 cpu = opt->cpu;
 1199                 assert(cpu >= 0);
 1200             }
 1201         }
 1202         nsd.xfrd_cpuset = cpuset_create();
 1203         region_add_cleanup(nsd.region, free_cpuset, nsd.xfrd_cpuset);
 1204         if(cpu == -1) {
 1205             cpuset_or(nsd.xfrd_cpuset,
 1206                       nsd.cpuset);
 1207         } else {
 1208             if(!cpuset_isset(cpu, nsd.cpuset)) {
 1209                 error("cpu %d specified in xfrd-cpu-affinity "
 1210                       "is not specified in cpu-affinity", cpu);
 1211             }
 1212             cpuset_set((cpuid_t)cpu, nsd.xfrd_cpuset);
 1213         }
 1214     }
 1215 #endif /* HAVE_CPUSET_T */
 1216 
 1217     /* Number of child servers to fork.  */
 1218     nsd.children = (struct nsd_child *) region_alloc_array(
 1219         nsd.region, nsd.child_count, sizeof(struct nsd_child));
 1220     for (i = 0; i < nsd.child_count; ++i) {
 1221         nsd.children[i].kind = NSD_SERVER_BOTH;
 1222         nsd.children[i].pid = -1;
 1223         nsd.children[i].child_fd = -1;
 1224         nsd.children[i].parent_fd = -1;
 1225         nsd.children[i].handler = NULL;
 1226         nsd.children[i].need_to_send_STATS = 0;
 1227         nsd.children[i].need_to_send_QUIT = 0;
 1228         nsd.children[i].need_to_exit = 0;
 1229         nsd.children[i].has_exited = 0;
 1230 #ifdef BIND8_STATS
 1231         nsd.children[i].query_count = 0;
 1232 #endif
 1233 
 1234 #ifdef HAVE_CPUSET_T
 1235         if(nsd.use_cpu_affinity) {
 1236             int cpu, server;
 1237             struct cpu_map_option *opt
 1238                 = nsd.options->service_cpu_affinity;
 1239 
 1240             cpu = -1;
 1241             server = i+1;
 1242             for(; opt && cpu == -1; opt = opt->next) {
 1243                 if(opt->service == server) {
 1244                     cpu = opt->cpu;
 1245                     assert(cpu >= 0);
 1246                 }
 1247             }
 1248             nsd.children[i].cpuset = cpuset_create();
 1249             region_add_cleanup(nsd.region,
 1250                                free_cpuset,
 1251                                nsd.children[i].cpuset);
 1252             if(cpu == -1) {
 1253                 cpuset_or(nsd.children[i].cpuset,
 1254                           nsd.cpuset);
 1255             } else {
 1256                 if(!cpuset_isset((cpuid_t)cpu, nsd.cpuset)) {
 1257                     error("cpu %d specified in "
 1258                           "server-%d-cpu-affinity is not "
 1259                           "specified in cpu-affinity",
 1260                           cpu, server);
 1261                 }
 1262                 cpuset_set(
 1263                     (cpuid_t)cpu, nsd.children[i].cpuset);
 1264             }
 1265         }
 1266 #endif /* HAVE_CPUSET_T */
 1267     }
 1268 
 1269     nsd.this_child = NULL;
 1270 
 1271     resolve_interface_names(nsd.options);
 1272     figure_sockets(&nsd.udp, &nsd.tcp, &nsd.ifs,
 1273         nsd.options->ip_addresses, udp_port, tcp_port, &hints);
 1274 
 1275     /* Parse the username into uid and gid */
 1276     nsd.gid = getgid();
 1277     nsd.uid = getuid();
 1278 #ifdef HAVE_GETPWNAM
 1279     /* Parse the username into uid and gid */
 1280     if (*nsd.username) {
 1281         if (isdigit((unsigned char)*nsd.username)) {
 1282             char *t;
 1283             nsd.uid = strtol(nsd.username, &t, 10);
 1284             if (*t != 0) {
 1285                 if (*t != '.' || !isdigit((unsigned char)*++t)) {
 1286                     error("-u user or -u uid or -u uid.gid");
 1287                 }
 1288                 nsd.gid = strtol(t, &t, 10);
 1289             } else {
 1290                 /* Lookup the group id in /etc/passwd */
 1291                 if ((pwd = getpwuid(nsd.uid)) == NULL) {
 1292                     error("user id %u does not exist.", (unsigned) nsd.uid);
 1293                 } else {
 1294                     nsd.gid = pwd->pw_gid;
 1295                 }
 1296             }
 1297         } else {
 1298             /* Lookup the user id in /etc/passwd */
 1299             if ((pwd = getpwnam(nsd.username)) == NULL) {
 1300                 error("user '%s' does not exist.", nsd.username);
 1301             } else {
 1302                 nsd.uid = pwd->pw_uid;
 1303                 nsd.gid = pwd->pw_gid;
 1304             }
 1305         }
 1306     }
 1307     /* endpwent(); */
 1308 #endif /* HAVE_GETPWNAM */
 1309 
 1310 #if defined(HAVE_SSL)
 1311     key_options_tsig_add(nsd.options);
 1312 #endif
 1313 
 1314     append_trailing_slash(&nsd.options->xfrdir, nsd.options->region);
 1315     /* Check relativity of pathnames to chroot */
 1316     if (nsd.chrootdir && nsd.chrootdir[0]) {
 1317         /* existing chrootdir: append trailing slash for strncmp checking */
 1318         append_trailing_slash(&nsd.chrootdir, nsd.region);
 1319         append_trailing_slash(&nsd.options->zonesdir, nsd.options->region);
 1320 
 1321         /* zonesdir must be absolute and within chroot,
 1322          * all other pathnames may be relative to zonesdir */
 1323         if (strncmp(nsd.options->zonesdir, nsd.chrootdir, strlen(nsd.chrootdir)) != 0) {
 1324             error("zonesdir %s has to be an absolute path that starts with the chroot path %s",
 1325                 nsd.options->zonesdir, nsd.chrootdir);
 1326         } else if (!file_inside_chroot(nsd.pidfile, nsd.chrootdir)) {
 1327             error("pidfile %s is not relative to %s: chroot not possible",
 1328                 nsd.pidfile, nsd.chrootdir);
 1329         } else if (!file_inside_chroot(nsd.dbfile, nsd.chrootdir)) {
 1330             error("database %s is not relative to %s: chroot not possible",
 1331                 nsd.dbfile, nsd.chrootdir);
 1332         } else if (!file_inside_chroot(nsd.options->xfrdfile, nsd.chrootdir)) {
 1333             error("xfrdfile %s is not relative to %s: chroot not possible",
 1334                 nsd.options->xfrdfile, nsd.chrootdir);
 1335         } else if (!file_inside_chroot(nsd.options->zonelistfile, nsd.chrootdir)) {
 1336             error("zonelistfile %s is not relative to %s: chroot not possible",
 1337                 nsd.options->zonelistfile, nsd.chrootdir);
 1338         } else if (!file_inside_chroot(nsd.options->xfrdir, nsd.chrootdir)) {
 1339             error("xfrdir %s is not relative to %s: chroot not possible",
 1340                 nsd.options->xfrdir, nsd.chrootdir);
 1341         }
 1342     }
 1343 
 1344     /* Set up the logging */
 1345     log_open(LOG_PID, FACILITY, nsd.log_filename);
 1346     if(nsd.options->log_only_syslog)
 1347         log_set_log_function(log_only_syslog);
 1348     else if (!nsd.log_filename)
 1349         log_set_log_function(log_syslog);
 1350     else if (nsd.uid && nsd.gid) {
 1351         if(chown(nsd.log_filename, nsd.uid, nsd.gid) != 0)
 1352             VERBOSITY(2, (LOG_WARNING, "chown %s failed: %s",
 1353                 nsd.log_filename, strerror(errno)));
 1354     }
 1355     log_msg(LOG_NOTICE, "%s starting (%s)", argv0, PACKAGE_STRING);
 1356 
 1357     /* Do we have a running nsd? */
 1358     if(nsd.pidfile && nsd.pidfile[0]) {
 1359         if ((oldpid = readpid(nsd.pidfile)) == -1) {
 1360             if (errno != ENOENT) {
 1361                 log_msg(LOG_ERR, "can't read pidfile %s: %s",
 1362                     nsd.pidfile, strerror(errno));
 1363             }
 1364         } else {
 1365             if (kill(oldpid, 0) == 0 || errno == EPERM) {
 1366                 log_msg(LOG_WARNING,
 1367                     "%s is already running as %u, continuing",
 1368                     argv0, (unsigned) oldpid);
 1369             } else {
 1370                 log_msg(LOG_ERR,
 1371                     "...stale pid file from process %u",
 1372                     (unsigned) oldpid);
 1373             }
 1374         }
 1375     }
 1376 
 1377 #ifdef HAVE_SETPROCTITLE
 1378     setproctitle("main");
 1379 #endif
 1380 #ifdef HAVE_CPUSET_T
 1381     if(nsd.use_cpu_affinity) {
 1382         set_cpu_affinity(nsd.cpuset);
 1383     }
 1384 #endif
 1385 
 1386     print_sockets(nsd.udp, nsd.tcp, nsd.ifs);
 1387 
 1388     /* Setup the signal handling... */
 1389     action.sa_handler = sig_handler;
 1390     sigfillset(&action.sa_mask);
 1391     action.sa_flags = 0;
 1392     sigaction(SIGTERM, &action, NULL);
 1393     sigaction(SIGHUP, &action, NULL);
 1394     sigaction(SIGINT, &action, NULL);
 1395     sigaction(SIGILL, &action, NULL);
 1396     sigaction(SIGUSR1, &action, NULL);
 1397     sigaction(SIGALRM, &action, NULL);
 1398     sigaction(SIGCHLD, &action, NULL);
 1399     action.sa_handler = SIG_IGN;
 1400     sigaction(SIGPIPE, &action, NULL);
 1401 
 1402     /* Initialize... */
 1403     nsd.mode = NSD_RUN;
 1404     nsd.signal_hint_child = 0;
 1405     nsd.signal_hint_reload = 0;
 1406     nsd.signal_hint_reload_hup = 0;
 1407     nsd.signal_hint_quit = 0;
 1408     nsd.signal_hint_shutdown = 0;
 1409     nsd.signal_hint_stats = 0;
 1410     nsd.signal_hint_statsusr = 0;
 1411     nsd.quit_sync_done = 0;
 1412 
 1413     /* Initialize the server... */
 1414     if (server_init(&nsd) != 0) {
 1415         error("server initialization failed, %s could "
 1416             "not be started", argv0);
 1417     }
 1418 #if defined(HAVE_SSL)
 1419     if(nsd.options->control_enable || (nsd.options->tls_service_key && nsd.options->tls_service_key[0])) {
 1420         perform_openssl_init();
 1421     }
 1422     if(nsd.options->control_enable) {
 1423         /* read ssl keys while superuser and outside chroot */
 1424         if(!(nsd.rc = daemon_remote_create(nsd.options)))
 1425             error("could not perform remote control setup");
 1426     }
 1427     if(nsd.options->tls_service_key && nsd.options->tls_service_key[0]
 1428        && nsd.options->tls_service_pem && nsd.options->tls_service_pem[0]) {
 1429         if(!(nsd.tls_ctx = server_tls_ctx_create(&nsd, NULL,
 1430             nsd.options->tls_service_ocsp)))
 1431             error("could not set up tls SSL_CTX");
 1432     }
 1433 #endif /* HAVE_SSL */
 1434 
 1435     /* Unless we're debugging, fork... */
 1436     if (!nsd.debug) {
 1437         int fd;
 1438 
 1439         /* Take off... */
 1440         switch (fork()) {
 1441         case 0:
 1442             /* Child */
 1443             break;
 1444         case -1:
 1445             error("fork() failed: %s", strerror(errno));
 1446             break;
 1447         default:
 1448             /* Parent is done */
 1449             server_close_all_sockets(nsd.udp, nsd.ifs);
 1450             server_close_all_sockets(nsd.tcp, nsd.ifs);
 1451             exit(0);
 1452         }
 1453 
 1454         /* Detach ourselves... */
 1455         if (setsid() == -1) {
 1456             error("setsid() failed: %s", strerror(errno));
 1457         }
 1458 
 1459         if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
 1460             (void)dup2(fd, STDIN_FILENO);
 1461             (void)dup2(fd, STDOUT_FILENO);
 1462             (void)dup2(fd, STDERR_FILENO);
 1463             if (fd > 2)
 1464                 (void)close(fd);
 1465         }
 1466     }
 1467 
 1468     /* Get our process id */
 1469     nsd.pid = getpid();
 1470 
 1471     /* Set user context */
 1472 #ifdef HAVE_GETPWNAM
 1473     if (*nsd.username) {
 1474 #ifdef HAVE_SETUSERCONTEXT
 1475         /* setusercontext does initgroups, setuid, setgid, and
 1476          * also resource limits from login config, but we
 1477          * still call setresuid, setresgid to be sure to set all uid */
 1478         if (setusercontext(NULL, pwd, nsd.uid,
 1479             LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0)
 1480             log_msg(LOG_WARNING, "unable to setusercontext %s: %s",
 1481                 nsd.username, strerror(errno));
 1482 #endif /* HAVE_SETUSERCONTEXT */
 1483     }
 1484 #endif /* HAVE_GETPWNAM */
 1485 
 1486     /* Chroot */
 1487 #ifdef HAVE_CHROOT
 1488     if (nsd.chrootdir && nsd.chrootdir[0]) {
 1489         int l = strlen(nsd.chrootdir)-1; /* ends in trailing slash */
 1490 
 1491         if (file_inside_chroot(nsd.log_filename, nsd.chrootdir))
 1492             nsd.file_rotation_ok = 1;
 1493 
 1494         /* strip chroot from pathnames if they're absolute */
 1495         nsd.options->zonesdir += l;
 1496         if (nsd.log_filename){
 1497             if (nsd.log_filename[0] == '/')
 1498                 nsd.log_filename += l;
 1499         }
 1500         if (nsd.pidfile && nsd.pidfile[0] == '/')
 1501             nsd.pidfile += l;
 1502         if (nsd.dbfile[0] == '/')
 1503             nsd.dbfile += l;
 1504         if (nsd.options->xfrdfile[0] == '/')
 1505             nsd.options->xfrdfile += l;
 1506         if (nsd.options->zonelistfile[0] == '/')
 1507             nsd.options->zonelistfile += l;
 1508         if (nsd.options->xfrdir[0] == '/')
 1509             nsd.options->xfrdir += l;
 1510 
 1511         /* strip chroot from pathnames of "include:" statements
 1512          * on subsequent repattern commands */
 1513         cfg_parser->chroot = nsd.chrootdir;
 1514 
 1515 #ifdef HAVE_TZSET
 1516         /* set timezone whilst not yet in chroot */
 1517         tzset();
 1518 #endif
 1519         if (chroot(nsd.chrootdir)) {
 1520             error("unable to chroot: %s", strerror(errno));
 1521         }
 1522         if (chdir("/")) {
 1523             error("unable to chdir to chroot: %s", strerror(errno));
 1524         }
 1525         DEBUG(DEBUG_IPC,1, (LOG_INFO, "changed root directory to %s",
 1526             nsd.chrootdir));
 1527         /* chdir to zonesdir again after chroot */
 1528         if(nsd.options->zonesdir && nsd.options->zonesdir[0]) {
 1529             if(chdir(nsd.options->zonesdir)) {
 1530                 error("unable to chdir to '%s': %s",
 1531                     nsd.options->zonesdir, strerror(errno));
 1532             }
 1533             DEBUG(DEBUG_IPC,1, (LOG_INFO, "changed directory to %s",
 1534                 nsd.options->zonesdir));
 1535         }
 1536     }
 1537     else
 1538 #endif /* HAVE_CHROOT */
 1539         nsd.file_rotation_ok = 1;
 1540 
 1541     DEBUG(DEBUG_IPC,1, (LOG_INFO, "file rotation on %s %sabled",
 1542         nsd.log_filename, nsd.file_rotation_ok?"en":"dis"));
 1543 
 1544     /* Write pidfile */
 1545     if (writepid(&nsd) == -1) {
 1546         log_msg(LOG_ERR, "cannot overwrite the pidfile %s: %s",
 1547             nsd.pidfile, strerror(errno));
 1548     }
 1549 
 1550     /* Drop the permissions */
 1551 #ifdef HAVE_GETPWNAM
 1552     if (*nsd.username) {
 1553 #ifdef HAVE_INITGROUPS
 1554         if(initgroups(nsd.username, nsd.gid) != 0)
 1555             log_msg(LOG_WARNING, "unable to initgroups %s: %s",
 1556                 nsd.username, strerror(errno));
 1557 #endif /* HAVE_INITGROUPS */
 1558         endpwent();
 1559 
 1560 #ifdef HAVE_SETRESGID
 1561         if(setresgid(nsd.gid,nsd.gid,nsd.gid) != 0)
 1562 #elif defined(HAVE_SETREGID) && !defined(DARWIN_BROKEN_SETREUID)
 1563             if(setregid(nsd.gid,nsd.gid) != 0)
 1564 #else /* use setgid */
 1565                 if(setgid(nsd.gid) != 0)
 1566 #endif /* HAVE_SETRESGID */
 1567                     error("unable to set group id of %s: %s",
 1568                         nsd.username, strerror(errno));
 1569 
 1570 #ifdef HAVE_SETRESUID
 1571         if(setresuid(nsd.uid,nsd.uid,nsd.uid) != 0)
 1572 #elif defined(HAVE_SETREUID) && !defined(DARWIN_BROKEN_SETREUID)
 1573             if(setreuid(nsd.uid,nsd.uid) != 0)
 1574 #else /* use setuid */
 1575                 if(setuid(nsd.uid) != 0)
 1576 #endif /* HAVE_SETRESUID */
 1577                     error("unable to set user id of %s: %s",
 1578                         nsd.username, strerror(errno));
 1579 
 1580         DEBUG(DEBUG_IPC,1, (LOG_INFO, "dropped user privileges, run as %s",
 1581             nsd.username));
 1582     }
 1583 #endif /* HAVE_GETPWNAM */
 1584     xfrd_make_tempdir(&nsd);
 1585 #ifdef USE_ZONE_STATS
 1586     options_zonestatnames_create(nsd.options);
 1587     server_zonestat_alloc(&nsd);
 1588 #endif /* USE_ZONE_STATS */
 1589 #ifdef USE_DNSTAP
 1590     if(nsd.options->dnstap_enable) {
 1591         nsd.dt_collector = dt_collector_create(&nsd);
 1592         dt_collector_start(nsd.dt_collector, &nsd);
 1593     }
 1594 #endif /* USE_DNSTAP */
 1595 
 1596     if(nsd.server_kind == NSD_SERVER_MAIN) {
 1597         server_prepare_xfrd(&nsd);
 1598         /* xfrd forks this before reading database, so it does not get
 1599          * the memory size of the database */
 1600         server_start_xfrd(&nsd, 0, 0);
 1601         /* close zonelistfile in non-xfrd processes */
 1602         zone_list_close(nsd.options);
 1603     }
 1604     if (server_prepare(&nsd) != 0) {
 1605         unlinkpid(nsd.pidfile);
 1606         error("server preparation failed, %s could "
 1607             "not be started", argv0);
 1608     }
 1609     if(nsd.server_kind == NSD_SERVER_MAIN) {
 1610         server_send_soa_xfrd(&nsd, 0);
 1611     }
 1612 
 1613     /* Really take off */
 1614     log_msg(LOG_NOTICE, "%s started (%s), pid %d",
 1615         argv0, PACKAGE_STRING, (int) nsd.pid);
 1616 
 1617     if (nsd.server_kind == NSD_SERVER_MAIN) {
 1618         server_main(&nsd);
 1619     } else {
 1620         server_child(&nsd);
 1621     }
 1622 
 1623     /* NOTREACH */
 1624     exit(0);
 1625 }