/* * nsd.h -- nsd(8) definitions and prototypes * * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. * * See LICENSE for the license. * */ #ifndef NSD_H #define NSD_H #include #include #ifndef IFNAMSIZ # ifdef IF_NAMESIZE # define IFNAMSIZ IF_NAMESIZE # else # define IFNAMSIZ 16 # endif #endif #ifdef HAVE_OPENSSL_SSL_H #include #endif #include "dns.h" #include "edns.h" #include "bitset.h" struct netio_handler; struct nsd_options; struct udb_base; struct daemon_remote; #ifdef USE_DNSTAP struct dt_collector; #endif /* The NSD runtime states and NSD ipc command values */ #define NSD_RUN 0 #define NSD_RELOAD 1 #define NSD_SHUTDOWN 2 #define NSD_STATS 3 #define NSD_REAP_CHILDREN 4 #define NSD_QUIT 5 /* * PASS_TO_XFRD is followed by the u16(len in network order) and * then network packet contents. packet is a notify(acl checked), or * xfr reply from a master(acl checked). * followed by u32(acl number that matched from notify/xfr acl). */ #define NSD_PASS_TO_XFRD 6 /* * RELOAD_REQ is sent when parent receives a SIGHUP and tells * xfrd that it wants to initiate a reload (and thus task swap). */ #define NSD_RELOAD_REQ 7 /* * RELOAD_DONE is sent at the end of a reload pass. * xfrd then knows that reload phase is over. */ #define NSD_RELOAD_DONE 8 /* * QUIT_SYNC is sent to signify a synchronisation of ipc * channel content during reload */ #define NSD_QUIT_SYNC 9 /* * QUIT_CHILD is sent at exit, to make sure the child has exited so that * port53 is free when all of nsd's processes have exited at shutdown time */ #define NSD_QUIT_CHILD 11 /* * This is the exit code of a nsd "new master" child process to indicate to * the master process that some zones failed verification and that it should * reload again, reprocessing the difffiles. The master process will resend * the command to xfrd so it will not reload from xfrd yet. */ #define NSD_RELOAD_FAILED 14 #define NSD_SERVER_MAIN 0x0U #define NSD_SERVER_UDP 0x1U #define NSD_SERVER_TCP 0x2U #define NSD_SERVER_BOTH (NSD_SERVER_UDP | NSD_SERVER_TCP) #ifdef INET6 #define DEFAULT_AI_FAMILY AF_UNSPEC #else #define DEFAULT_AI_FAMILY AF_INET #endif #ifdef BIND8_STATS /* Counter for statistics */ typedef unsigned long stc_type; #define LASTELEM(arr) (sizeof(arr) / sizeof(arr[0]) - 1) #define STATUP(nsd, stc) nsd->st->stc++ /* #define STATUP2(nsd, stc, i) ((i) <= (LASTELEM(nsd->st->stc) - 1)) ? nsd->st->stc[(i)]++ : \ nsd->st.stc[LASTELEM(nsd->st->stc)]++ */ #define STATUP2(nsd, stc, i) nsd->st->stc[(i) <= (LASTELEM(nsd->st->stc) - 1) ? i : LASTELEM(nsd->st->stc)]++ #else /* BIND8_STATS */ #define STATUP(nsd, stc) /* Nothing */ #define STATUP2(nsd, stc, i) /* Nothing */ #endif /* BIND8_STATS */ #ifdef USE_ZONE_STATS /* increment zone statistic, checks if zone-nonNULL and zone array bounds */ #define ZTATUP(nsd, zone, stc) ( \ (zone && zone->zonestatid < nsd->zonestatsizenow) ? \ nsd->zonestatnow[zone->zonestatid].stc++ \ : 0) #define ZTATUP2(nsd, zone, stc, i) ( \ (zone && zone->zonestatid < nsd->zonestatsizenow) ? \ (nsd->zonestatnow[zone->zonestatid].stc[(i) <= (LASTELEM(nsd->zonestatnow[zone->zonestatid].stc) - 1) ? i : LASTELEM(nsd->zonestatnow[zone->zonestatid].stc)]++ ) \ : 0) #else /* USE_ZONE_STATS */ #define ZTATUP(nsd, zone, stc) /* Nothing */ #define ZTATUP2(nsd, zone, stc, i) /* Nothing */ #endif /* USE_ZONE_STATS */ #ifdef BIND8_STATS /* Data structure to keep track of statistics */ struct nsdst { time_t boot; stc_type qtype[257]; /* Counters per qtype */ stc_type qclass[4]; /* Class IN or Class CH or other */ stc_type qudp, qudp6; /* Number of queries udp and udp6 */ stc_type ctcp, ctcp6; /* Number of tcp and tcp6 connections */ stc_type ctls, ctls6; /* Number of tls and tls6 connections */ stc_type rcode[17], opcode[6]; /* Rcodes & opcodes */ /* Dropped, truncated, queries for nonconfigured zone, tx errors */ stc_type dropped, truncated, wrongzone, txerr, rxerr; stc_type edns, ednserr, raxfr, nona, rixfr; uint64_t db_disk, db_mem; }; #endif /* BIND8_STATS */ #define NSD_SOCKET_IS_OPTIONAL (1<<0) #define NSD_BIND_DEVICE (1<<1) struct nsd_addrinfo { int ai_flags; int ai_family; int ai_socktype; socklen_t ai_addrlen; struct sockaddr_storage ai_addr; }; struct nsd_socket { struct nsd_addrinfo addr; int s; int flags; struct nsd_bitset *servers; char device[IFNAMSIZ]; int fib; }; struct nsd_child { #ifdef HAVE_CPUSET_T /* Processor(s) that child process must run on (if applicable). */ cpuset_t *cpuset; #endif /* The type of child process (UDP or TCP handler). */ int kind; /* The child's process id. */ pid_t pid; /* child number in child array */ int child_num; /* * Socket used by the parent process to send commands and * receive responses to/from this child process. */ int child_fd; /* * Socket used by the child process to receive commands and * send responses from/to the parent process. */ int parent_fd; /* * IPC info, buffered for nonblocking writes to the child */ uint8_t need_to_send_STATS, need_to_send_QUIT; uint8_t need_to_exit, has_exited; /* * The handler for handling the commands from the child. */ struct netio_handler* handler; #ifdef BIND8_STATS stc_type query_count; #endif }; #define NSD_COOKIE_HISTORY_SIZE 2 #define NSD_COOKIE_SECRET_SIZE 16 typedef struct cookie_secret cookie_secret_type; struct cookie_secret { /** cookie secret */ uint8_t cookie_secret[NSD_COOKIE_SECRET_SIZE]; }; /* NSD configuration and run-time variables */ typedef struct nsd nsd_type; struct nsd { /* * Global region that is not deallocated until NSD shuts down. */ region_type *region; /* Run-time variables */ pid_t pid; volatile sig_atomic_t mode; volatile sig_atomic_t signal_hint_reload_hup; volatile sig_atomic_t signal_hint_reload; volatile sig_atomic_t signal_hint_child; volatile sig_atomic_t signal_hint_quit; volatile sig_atomic_t signal_hint_shutdown; volatile sig_atomic_t signal_hint_stats; volatile sig_atomic_t signal_hint_statsusr; volatile sig_atomic_t quit_sync_done; unsigned server_kind; struct namedb *db; int debug; size_t child_count; struct nsd_child *children; int restart_children; int reload_failed; /* NULL if this is the parent process. */ struct nsd_child *this_child; /* mmaps with data exchange from xfrd and reload */ struct udb_base* task[2]; int mytask; /* the base used by this (child)process */ struct event_base* event_base; /* the server_region used by this (child)process */ region_type* server_region; struct netio_handler* xfrd_listener; struct daemon_remote* rc; /* Configuration */ const char *pidfile; const char *log_filename; const char *username; uid_t uid; gid_t gid; const char *chrootdir; const char *version; const char *identity; uint16_t nsid_len; unsigned char *nsid; uint8_t file_rotation_ok; #ifdef HAVE_CPUSET_T int use_cpu_affinity; cpuset_t* cpuset; cpuset_t* xfrd_cpuset; #endif /* number of interfaces */ size_t ifs; /* non0 if so_reuseport is in use, if so, tcp, udp array increased */ int reuseport; /* TCP specific configuration (array size ifs) */ struct nsd_socket* tcp; /* UDP specific configuration (array size ifs) */ struct nsd_socket* udp; /* Interfaces used for zone verification */ size_t verify_ifs; struct nsd_socket *verify_tcp; struct nsd_socket *verify_udp; struct zone *next_zone_to_verify; size_t verifier_count; /* Number of active verifiers */ size_t verifier_limit; /* Maximum number of active verifiers */ int verifier_pipe[2]; /* Pipe to trigger verifier exit handler */ struct verifier *verifiers; edns_data_type edns_ipv4; #if defined(INET6) edns_data_type edns_ipv6; #endif int maximum_tcp_count; int current_tcp_count; int tcp_query_count; int tcp_timeout; int tcp_mss; int outgoing_tcp_mss; size_t ipv4_edns_size; size_t ipv6_edns_size; #ifdef BIND8_STATS /* statistics for this server */ struct nsdst* st; /* Produce statistics dump every st_period seconds */ int st_period; /* per zone stats, each an array per zone-stat-idx, stats per zone is * add of [0][zoneidx] and [1][zoneidx]. */ struct nsdst* zonestat[2]; /* fd for zonestat mapping (otherwise mmaps cannot be shared between * processes and resized) */ int zonestatfd[2]; /* filenames */ char* zonestatfname[2]; /* size of the mmapped zone stat array (number of array entries) */ size_t zonestatsize[2], zonestatdesired, zonestatsizenow; /* current zonestat array to use */ struct nsdst* zonestatnow; /* filenames for stat file mappings */ char* statfname; /* fd for stat mapping (otherwise mmaps cannot be shared between * processes and resized) */ int statfd; /* statistics array, of size child_count*2, twice for old and new * server processes. */ struct nsdst* stat_map; /* statistics array of size child_count, twice */ struct nsdst* stats_per_child[2]; /* current stats_per_child array that is in use for the child set */ int stat_current; /* start value for per process statistics printout, to clear it */ struct nsdst stat_proc; #endif /* BIND8_STATS */ #ifdef USE_DNSTAP /* the dnstap collector process info */ struct dt_collector* dt_collector; /* the pipes from server processes to the dt_collector, * arrays of size child_count * 2. Kept open for (re-)forks. */ int *dt_collector_fd_send, *dt_collector_fd_recv; /* the pipes from server processes to the dt_collector. Initially * these point halfway into dt_collector_fd_send, but during reload * the pointer is swapped with dt_collector_fd_send in order to * to prevent writing to the dnstap collector by old serve childs * simultaneous with new serve childs. */ int *dt_collector_fd_swap; #endif /* USE_DNSTAP */ /* ratelimit for errors, time value */ time_t err_limit_time; /* ratelimit for errors, packet count */ unsigned int err_limit_count; /** do answer with server cookie when request contained cookie option */ int do_answer_cookie; /** how many cookies are there in the cookies array */ size_t cookie_count; /* keep track of the last `NSD_COOKIE_HISTORY_SIZE` * cookies as per rfc requirement .*/ cookie_secret_type cookie_secrets[NSD_COOKIE_HISTORY_SIZE]; struct nsd_options* options; #ifdef HAVE_SSL /* TLS specific configuration */ SSL_CTX *tls_ctx; #endif }; extern struct nsd nsd; /* nsd.c */ pid_t readpid(const char *file); int writepid(struct nsd *nsd); void unlinkpid(const char* file); void sig_handler(int sig); void bind8_stats(struct nsd *nsd); /* server.c */ int server_init(struct nsd *nsd); int server_prepare(struct nsd *nsd); void server_main(struct nsd *nsd); void server_child(struct nsd *nsd); void server_shutdown(struct nsd *nsd) ATTR_NORETURN; void server_close_all_sockets(struct nsd_socket sockets[], size_t n); const char* nsd_event_vs(void); const char* nsd_event_method(void); struct event_base* nsd_child_event_base(void); void service_remaining_tcp(struct nsd* nsd); /* extra domain numbers for temporary domains */ #define EXTRA_DOMAIN_NUMBERS 1024 #define SLOW_ACCEPT_TIMEOUT 2 /* in seconds */ /* ratelimit for error responses */ #define ERROR_RATELIMIT 100 /* qps */ /* allocate zonestat structures */ void server_zonestat_alloc(struct nsd* nsd); /* remap the mmaps for zonestat isx, to bytesize sz. Caller has to set * the zonestatsize */ void zonestat_remap(struct nsd* nsd, int idx, size_t sz); /* allocate stat structures */ void server_stat_alloc(struct nsd* nsd); /* free stat mmap file, unlinks it */ void server_stat_free(struct nsd* nsd); /* allocate and init xfrd variables */ void server_prepare_xfrd(struct nsd *nsd); /* start xfrdaemon (again) */ void server_start_xfrd(struct nsd *nsd, int del_db, int reload_active); /* send SOA serial numbers to xfrd */ void server_send_soa_xfrd(struct nsd *nsd, int shortsoa); #ifdef HAVE_SSL SSL_CTX* server_tls_ctx_setup(char* key, char* pem, char* verifypem); SSL_CTX* server_tls_ctx_create(struct nsd *nsd, char* verifypem, char* ocspfile); void perform_openssl_init(void); #endif ssize_t block_read(struct nsd* nsd, int s, void* p, ssize_t sz, int timeout); #endif /* NSD_H */