summaryrefslogtreecommitdiffstats
path: root/usr.sbin/nsd/options.h
blob: 1d30156bbbee2223cba22f2ed15aba65afc7815e (plain) (blame)
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
/*
 * options.h -- nsd.conf options definitions and prototypes
 *
 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
 *
 * See LICENSE for the license.
 *
 */

#ifndef OPTIONS_H
#define OPTIONS_H

#include "config.h"
#include <stdarg.h>
#include "region-allocator.h"
#include "rbtree.h"
struct query;
struct dname;
struct tsig_key;
struct buffer;
struct nsd;

typedef struct nsd_options nsd_options_type;
typedef struct pattern_options pattern_options_type;
typedef struct zone_options zone_options_type;
typedef struct ip_address_option ip_address_option_type;
typedef struct acl_options acl_options_type;
typedef struct key_options key_options_type;
typedef struct config_parser_state config_parser_state_type;
/*
 * Options global for nsd.
 */
struct nsd_options {
	/* config file name */
	char* configfile;
	/* options for zones, by apex, contains zone_options */
	rbtree_type* zone_options;
	/* patterns, by name, contains pattern_options */
	rbtree_type* patterns;

	/* free space in zonelist file, contains zonelist_bucket */
	rbtree_type* zonefree;
	/* number of free space lines in zonelist file */
	size_t zonefree_number;
	/* zonelist file if open */
	FILE* zonelist;
	/* last offset in file (or 0 if none) */
	off_t zonelist_off;

	/* tree of zonestat names and their id values, entries are struct
	 * zonestatname with malloced key=stringname. The number of items
	 * is the max statnameid, no items are freed from this. 
	 * kept correct in the xfrd process, and on startup. */
	rbtree_type* zonestatnames;

	/* rbtree of keys defined, by name */
	rbtree_type* keys;

	/* list of ip addresses to bind to (or NULL for all) */
	struct ip_address_option* ip_addresses;

	int ip_transparent;
	int ip_freebind;
	int debug_mode;
	int verbosity;
	int hide_version;
	int do_ip4;
	int do_ip6;
	const char* database;
	const char* identity;
	const char* version;
	const char* logfile;
	int server_count;
	int 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;
	const char* pidfile;
	const char* port;
	int statistics;
	const char* chroot;
	const char* username;
	const char* zonesdir;
	const char* xfrdfile;
	const char* xfrdir;
	const char* zonelistfile;
	const char* nsid;
	int xfrd_reload_timeout;
	int zonefiles_check;
	int zonefiles_write;
	int log_time_ascii;
	int round_robin;
	int minimal_responses;
	int refuse_any;
	int reuseport;

        /** remote control section. enable toggle. */
	int control_enable;
	/** the interfaces the remote control should listen on */
	struct ip_address_option* control_interface;
	/** port number for the control port */
	int control_port;
	/** private key file for server */
	char* server_key_file;
	/** certificate file for server */
	char* server_cert_file;
	/** private key file for nsd-control */
	char* control_key_file;
	/** certificate file for nsd-control */
	char* control_cert_file;

#ifdef RATELIMIT
	/** number of buckets in rrl hashtable */
	size_t rrl_size;
	/** max qps for queries, 0 is nolimit */
	size_t rrl_ratelimit;
	/** ratio of slipped responses, 0 is noslip */
	size_t rrl_slip;
	/** ip prefix length */
	size_t rrl_ipv4_prefix_length;
	size_t rrl_ipv6_prefix_length;
	/** max qps for whitelisted queries, 0 is nolimit */
	size_t rrl_whitelist_ratelimit;
#endif
	/** if dnstap is enabled */
	int dnstap_enable;
	/** dnstap socket path */
	char* dnstap_socket_path;
	/** true to send "identity" via dnstap */
	int dnstap_send_identity;
	/** true to send "version" via dnstap */
	int dnstap_send_version;
	/** dnstap "identity", hostname is used if "". */
	char* dnstap_identity;
	/** dnstap "version", package version is used if "". */
	char* dnstap_version;
	/** true to log dnstap AUTH_QUERY message events */
	int dnstap_log_auth_query_messages;
	/** true to log dnstap AUTH_RESPONSE message events */
	int dnstap_log_auth_response_messages;

	region_type* region;
};

struct ip_address_option {
	struct ip_address_option* next;
	char* address;
};

/*
 * Pattern of zone options, used to contain options for zone(s).
 */
struct pattern_options {
	rbnode_type node;
	const char* pname; /* name of the pattern, key of rbtree */
	const char* zonefile;
	struct acl_options* allow_notify;
	struct acl_options* request_xfr;
	struct acl_options* notify;
	struct acl_options* provide_xfr;
	struct acl_options* outgoing_interface;
	const char* zonestats;
#ifdef RATELIMIT
	uint16_t rrl_whitelist; /* bitmap with rrl types */
#endif
	uint8_t allow_axfr_fallback;
	uint8_t allow_axfr_fallback_is_default;
	uint8_t notify_retry;
	uint8_t notify_retry_is_default;
	uint8_t implicit; /* pattern is implicit, part_of_config zone used */
	uint8_t xfrd_flags;
	uint32_t max_refresh_time;
	uint8_t max_refresh_time_is_default;
	uint32_t min_refresh_time;
	uint8_t min_refresh_time_is_default;
	uint32_t max_retry_time;
	uint8_t max_retry_time_is_default;
	uint32_t min_retry_time;
	uint8_t min_retry_time_is_default;
	uint64_t size_limit_xfr;
	uint8_t multi_master_check;
} ATTR_PACKED;

#define PATTERN_IMPLICIT_MARKER "_implicit_"

/*
 * Options for a zone
 */
struct zone_options {
	/* key is dname of apex */
	rbnode_type node;

	/* is apex of the zone */
	const char* name;
	/* if not part of config, the offset and linesize of zonelist entry */
	off_t off;
	int linesize;
	/* pattern for the zone options, if zone is part_of_config, this is
	 * a anonymous pattern created in-place */
	struct pattern_options* pattern;
	/* zone is fixed into the main config, not in zonelist, cannot delete */
	uint8_t part_of_config;
} ATTR_PACKED;

union acl_addr_storage {
#ifdef INET6
	struct in_addr addr;
	struct in6_addr addr6;
#else
	struct in_addr addr;
#endif
};

/*
 * Access control list element
 */
struct acl_options {
	struct acl_options* next;

	/* options */
	time_t ixfr_disabled;
	int bad_xfr_count;
	uint8_t use_axfr_only;
	uint8_t allow_udp;

	/* ip address range */
	const char* ip_address_spec;
	uint8_t is_ipv6;
	unsigned int port;	/* is 0(no port) or suffix @port value */
	union acl_addr_storage addr;
	union acl_addr_storage range_mask;
	enum {
		acl_range_single = 0,	/* single address */
		acl_range_mask = 1,	/* 10.20.30.40&255.255.255.0 */
		acl_range_subnet = 2,	/* 10.20.30.40/28 */
		acl_range_minmax = 3	/* 10.20.30.40-10.20.30.60 (mask=max) */
	} rangetype;

	/* key */
	uint8_t nokey;
	uint8_t blocked;
	const char* key_name;
	struct key_options* key_options;
} ATTR_PACKED;

/*
 * Key definition
 */
struct key_options {
	rbnode_type node; /* key of tree is name */
	char* name;
	char* algorithm;
	char* secret;
	struct tsig_key* tsig_key;
} ATTR_PACKED;

/** zone list free space */
struct zonelist_free {
	struct zonelist_free* next;
	off_t off;
};
/** zonelist free bucket for a particular line length */
struct zonelist_bucket {
	rbnode_type node; /* key is ptr to linesize */
	int linesize;
	struct zonelist_free* list;
};

/* default zonefile write interval if database is "", in seconds */
#define ZONEFILES_WRITE_INTERVAL 3600

struct zonestatname {
	rbnode_type node; /* key is malloced string with cooked zonestat name */
	unsigned id; /* index in nsd.zonestat array */
};

/*
 * Used during options parsing
 */
struct config_parser_state {
	char* filename;
	const char* chroot;
	int line;
	int errors;
	int server_settings_seen;
	struct nsd_options* opt;
	struct pattern_options* current_pattern;
	struct zone_options* current_zone;
	struct key_options* current_key;
	struct ip_address_option* current_ip_address_option;
	struct acl_options* current_allow_notify;
	struct acl_options* current_request_xfr;
	struct acl_options* current_notify;
	struct acl_options* current_provide_xfr;
	struct acl_options* current_outgoing_interface;
	void (*err)(void*,const char*);
	void* err_arg;
};

extern config_parser_state_type* cfg_parser;

/* region will be put in nsd_options struct. Returns empty options struct. */
struct nsd_options* nsd_options_create(region_type* region);
/* the number of zones that are configured */
static inline size_t nsd_options_num_zones(struct nsd_options* opt)
{ return opt->zone_options->count; }
/* insert a zone into the main options tree, returns 0 on error */
int nsd_options_insert_zone(struct nsd_options* opt, struct zone_options* zone);
/* insert a pattern into the main options tree, returns 0 on error */
int nsd_options_insert_pattern(struct nsd_options* opt,
	struct pattern_options* pat);

/* parses options file. Returns false on failure. callback, if nonNULL,
 * gets called with error strings, default prints. */
int parse_options_file(struct nsd_options* opt, const char* file,
	void (*err)(void*,const char*), void* err_arg);
struct zone_options* zone_options_create(region_type* region);
void zone_options_delete(struct nsd_options* opt, struct zone_options* zone);
/* find a zone by apex domain name, or NULL if not found. */
struct zone_options* zone_options_find(struct nsd_options* opt,
	const struct dname* apex);
struct pattern_options* pattern_options_create(region_type* region);
struct pattern_options* pattern_options_find(struct nsd_options* opt, const char* name);
int pattern_options_equal(struct pattern_options* p, struct pattern_options* q);
void pattern_options_remove(struct nsd_options* opt, const char* name);
void pattern_options_add_modify(struct nsd_options* opt,
	struct pattern_options* p);
void pattern_options_marshal(struct buffer* buffer, struct pattern_options* p);
struct pattern_options* pattern_options_unmarshal(region_type* r,
	struct buffer* b);
struct key_options* key_options_create(region_type* region);
void key_options_insert(struct nsd_options* opt, struct key_options* key);
struct key_options* key_options_find(struct nsd_options* opt, const char* name);
void key_options_remove(struct nsd_options* opt, const char* name);
int key_options_equal(struct key_options* p, struct key_options* q);
void key_options_add_modify(struct nsd_options* opt, struct key_options* key);
void key_options_setup(region_type* region, struct key_options* key);
void key_options_desetup(region_type* region, struct key_options* key);
/* read in zone list file. Returns false on failure */
int parse_zone_list_file(struct nsd_options* opt);
/* create zone entry and add to the zonelist file */
struct zone_options* zone_list_add(struct nsd_options* opt, const char* zname,
	const char* pname);
/* create zonelist entry, do not insert in file (called by _add) */
struct zone_options* zone_list_zone_insert(struct nsd_options* opt,
	const char* nm, const char* patnm, int linesize, off_t off);
void zone_list_del(struct nsd_options* opt, struct zone_options* zone);
void zone_list_compact(struct nsd_options* opt);
void zone_list_close(struct nsd_options* opt);

/* create zonestat name tree , for initially created zones */
void options_zonestatnames_create(struct nsd_options* opt);
/* Get zonestat id for zone options, add new entry if necessary.
 * instantiates the pattern's zonestat string */
unsigned getzonestatid(struct nsd_options* opt, struct zone_options* zopt);
/* create string, same options as zonefile but no chroot changes */
const char* config_cook_string(struct zone_options* zone, const char* input);

/** check if config for remote control turns on IP-address interface
 * with certificates or a named pipe without certificates. */
int options_remote_is_address(struct nsd_options* cfg);

#if defined(HAVE_SSL)
/* tsig must be inited, adds all keys in options to tsig. */
void key_options_tsig_add(struct nsd_options* opt);
#endif

/* check acl list, acl number that matches if passed(0..),
 * or failure (-1) if dropped */
/* the reason why (the acl) is returned too (or NULL) */
int acl_check_incoming(struct acl_options* acl, struct query* q,
	struct acl_options** reason);
int acl_addr_matches_host(struct acl_options* acl, struct acl_options* host);
int acl_addr_matches(struct acl_options* acl, struct query* q);
int acl_key_matches(struct acl_options* acl, struct query* q);
int acl_addr_match_mask(uint32_t* a, uint32_t* b, uint32_t* mask, size_t sz);
int acl_addr_match_range(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz);

/* returns true if acls are both from the same host */
int acl_same_host(struct acl_options* a, struct acl_options* b);
/* find acl by number in the list */
struct acl_options* acl_find_num(struct acl_options* acl, int num);

/* see if two acl lists are the same (same elements in same order, or empty) */
int acl_list_equal(struct acl_options* p, struct acl_options* q);
/* see if two acl are the same */
int acl_equal(struct acl_options* p, struct acl_options* q);

/* see if a zone is a slave or a master zone */
int zone_is_slave(struct zone_options* opt);
/* create zonefile name, returns static pointer (perhaps to options data) */
const char* config_make_zonefile(struct zone_options* zone, struct nsd* nsd);

#define ZONEC_PCT_TIME 5 /* seconds, then it starts to print pcts */
#define ZONEC_PCT_COUNT 100000 /* elements before pct check is done */

/* parsing helpers */
void c_error(const char* msg);
void c_error_msg(const char* fmt, ...) ATTR_FORMAT(printf, 1, 2);
struct acl_options* parse_acl_info(region_type* region, char* ip,
	const char* key);
/* true if ipv6 address, false if ipv4 */
int parse_acl_is_ipv6(const char* p);
/* returns range type. mask is the 2nd part of the range */
int parse_acl_range_type(char* ip, char** mask);
/* parses subnet mask, fills 0 mask as well */
void parse_acl_range_subnet(char* p, void* addr, int maxbits);
/* clean up options */
void nsd_options_destroy(struct nsd_options* opt);
/* replace occurrences of one with two in buf, pass length of buffer */
void replace_str(char* buf, size_t len, const char* one, const char* two);
/* apply pattern to the existing pattern in the parser */
void config_apply_pattern(const char* name);

#endif /* OPTIONS_H */