summaryrefslogtreecommitdiff
path: root/usr.sbin/nsd/nsd.h
blob: 4bd8dcdc967d76520f4a96d92113e4c1b4aa104f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
/*
 * 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 <signal.h>
#include <net/if.h>
#ifndef IFNAMSIZ
#  ifdef IF_NAMESIZE
#    define IFNAMSIZ IF_NAMESIZE
#  else
#    define IFNAMSIZ 16
#  endif
#endif
#ifdef HAVE_OPENSSL_SSL_H
#include <openssl/ssl.h>
#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 */