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
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
|
/*
* 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 <stdarg.h>
#include "region-allocator.h"
#include "rbtree.h"
struct query;
struct dname;
struct tsig_key;
struct buffer;
struct nsd;
struct proxy_protocol_port_list;
typedef struct nsd_options nsd_options_type;
typedef struct pattern_options pattern_options_type;
typedef struct zone_options zone_options_type;
typedef struct range_option range_option_type;
typedef struct ip_address_option ip_address_option_type;
typedef struct cpu_option cpu_option_type;
typedef struct cpu_map_option cpu_map_option_type;
typedef struct acl_options acl_options_type;
typedef struct key_options key_options_type;
typedef struct tls_auth_options tls_auth_options_type;
typedef struct config_parser_state config_parser_state_type;
#define VERIFY_ZONE_INHERIT (2)
#define VERIFIER_FEED_ZONE_INHERIT (2)
#define VERIFIER_TIMEOUT_INHERIT (-1)
#define CATALOG_ROLE_INHERIT (0)
#define CATALOG_ROLE_CONSUMER (1)
#define CATALOG_ROLE_PRODUCER (2)
/*
* 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;
/* rbtree of tls_auth defined, by name */
rbtree_type* tls_auths;
/* list of ip addresses to bind to (or NULL for all) */
struct ip_address_option* ip_addresses;
int ip_transparent;
int ip_freebind;
int send_buffer_size;
int receive_buffer_size;
int debug_mode;
int verbosity;
int hide_version;
int hide_identity;
int drop_updates;
int do_ip4;
int do_ip6;
const char* identity;
const char* version;
const char* logfile;
int log_only_syslog;
int server_count;
struct cpu_option* cpu_affinity;
struct cpu_map_option* service_cpu_affinity;
int tcp_count;
int tcp_reject_overflow;
int confine_to_zone;
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;
/* max number of xfrd tcp sockets */
int xfrd_tcp_max;
/* max number of simultaneous requests on xfrd tcp socket */
int xfrd_tcp_pipeline;
/* private key file for TLS */
char* tls_service_key;
/* ocsp stapling file for TLS */
char* tls_service_ocsp;
/* certificate file for TLS */
char* tls_service_pem;
/* TLS dedicated port */
const char* tls_port;
/* TLS certificate bundle */
const char* tls_cert_bundle;
/* proxy protocol port list */
struct proxy_protocol_port_list* proxy_protocol_port;
/** 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;
/** dnstap IP, if "", it uses socket path. */
char* dnstap_ip;
/** dnstap TLS enable */
int dnstap_tls;
/** dnstap tls server authentication name */
char* dnstap_tls_server_name;
/** dnstap server cert bundle */
char* dnstap_tls_cert_bundle;
/** dnstap client key for client authentication */
char* dnstap_tls_client_key_file;
/** dnstap client cert for client authentication */
char* dnstap_tls_client_cert_file;
/** 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;
/** do answer with server cookie when request contained cookie option */
int answer_cookie;
/** cookie secret */
char *cookie_secret;
/** path to cookie secret store */
char const* cookie_secret_file;
/** enable verify */
int verify_enable;
/** list of ip addresses used to serve zones for verification */
struct ip_address_option* verify_ip_addresses;
/** default port 5347 */
char *verify_port;
/** verify zones by default */
int verify_zones;
/** default command to verify zones with */
char **verifier;
/** maximum number of verifiers that may run simultaneously */
int verifier_count;
/** whether or not to feed the zone to the verifier over stdin */
uint8_t verifier_feed_zone;
/** maximum number of seconds that a verifier may take */
uint32_t verifier_timeout;
region_type* region;
};
struct range_option {
struct range_option* next;
int first;
int last;
};
struct ip_address_option {
struct ip_address_option* next;
char* address;
struct range_option* servers;
int dev;
int fib;
};
struct cpu_option {
struct cpu_option* next;
int cpu;
};
struct cpu_map_option {
struct cpu_map_option* next;
int service;
int cpu;
};
/*
* Defines for min_expire_time_expr value
*/
#define EXPIRE_TIME_HAS_VALUE 0
#define EXPIRE_TIME_IS_DEFAULT 1
#define REFRESHPLUSRETRYPLUS1 2
#define REFRESHPLUSRETRYPLUS1_STR "refresh+retry+1"
#define expire_time_is_default(x) (!( (x) == REFRESHPLUSRETRYPLUS1 \
|| (x) == EXPIRE_TIME_HAS_VALUE ))
/*
* 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* allow_query;
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;
uint32_t min_expire_time;
/* min_expir_time_expr is either a known value (REFRESHPLUSRETRYPLUS1
* or EXPIRE_EXPR_HAS_VALUE) or else min_expire_time is the default.
* This can be tested with expire_time_is_default(x) define.
*/
uint8_t min_expire_time_expr;
uint64_t size_limit_xfr;
uint8_t multi_primary_check;
uint8_t store_ixfr;
uint8_t store_ixfr_is_default;
uint64_t ixfr_size;
uint8_t ixfr_size_is_default;
uint32_t ixfr_number;
uint8_t ixfr_number_is_default;
uint8_t create_ixfr;
uint8_t create_ixfr_is_default;
uint8_t verify_zone;
uint8_t verify_zone_is_default;
char **verifier;
uint8_t verifier_feed_zone;
uint8_t verifier_feed_zone_is_default;
int32_t verifier_timeout;
uint8_t verifier_timeout_is_default;
uint8_t catalog_role;
uint8_t catalog_role_is_default;
const char* catalog_member_pattern;
const char* catalog_producer_zone;
} 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 */
unsigned part_of_config : 1;
unsigned is_catalog_member_zone: 1;
} ATTR_PACKED;
/*
* Options for catalog member zones
* assert(options->is_catalog_member_zone == 1)
* when options->pattern->catalog_producer_zone is set, this is a
* producer member zone, otherwise a consumer member zone.
* A catalog member zone is either a member zone of a catalog producer zone
* or a catalog consumer zone. They are mutually exclusive.
*/
struct catalog_member_zone {
struct zone_options options;
const struct dname* member_id;
/* node in the associated catalog consumer or producer zone */
rbnode_type node;
} ATTR_PACKED;
typedef void (*new_member_id_type)(struct catalog_member_zone* zone);
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;
/* tls_auth for XoT */
const char* tls_auth_name;
struct tls_auth_options* tls_auth_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;
/*
* TLS Auth definition for XoT
*/
struct tls_auth_options {
rbnode_type node; /* key of tree is name */
char* name;
char* auth_domain_name;
char* client_cert;
char* client_key;
char* client_key_pw;
};
/* proxy protocol port option list */
struct proxy_protocol_port_list {
struct proxy_protocol_port_list* next;
int port;
};
/** 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;
struct nsd_options* opt;
struct pattern_options *pattern;
struct zone_options *zone;
struct key_options *key;
struct tls_auth_options *tls_auth;
struct ip_address_option *ip;
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 nsd_options* old_opts);
struct zone_options* zone_options_create(region_type* region);
void zone_options_delete(struct nsd_options* opt, struct zone_options* zone);
struct catalog_member_zone* catalog_member_zone_create(region_type* region);
static inline struct catalog_member_zone* as_catalog_member_zone(struct zone_options* zopt)
{ return zopt && zopt->is_catalog_member_zone ? (struct catalog_member_zone*)zopt : NULL; }
/* 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);
/* TLS auth */
struct tls_auth_options* tls_auth_options_create(region_type* region);
void tls_auth_options_insert(struct nsd_options* opt, struct tls_auth_options* auth);
struct tls_auth_options* tls_auth_options_find(struct nsd_options* opt, const char* name);
/* read in zone list file. Returns false on failure */
int parse_zone_list_file(struct nsd_options* opt);
/* create (potential) catalog producer member entry and add to the zonelist */
struct zone_options* zone_list_add_or_cat(struct nsd_options* opt,
const char* zname, const char* pname, new_member_id_type new_member_id);
/* create zone entry and add to the zonelist file */
static inline struct zone_options* zone_list_add(struct nsd_options* opt,
const char* zname, const char* pname)
{ return zone_list_add_or_cat(opt, zname, pname, NULL); }
/* 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);
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_addr_matches_proxy(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_v6(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz);
int acl_addr_match_range_v4(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz);
/* check acl list for blocks on address, return 0 if none, -1 if blocked. */
int acl_check_incoming_block_proxy(struct acl_options* acl, struct query* q,
struct acl_options** reason);
/* 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);
/* see if a zone is a catalog consumer */
static inline int zone_is_catalog_consumer(struct zone_options* opt)
{ return opt && opt->pattern
&& opt->pattern->catalog_role == CATALOG_ROLE_CONSUMER; }
static inline int zone_is_catalog_producer(struct zone_options* opt)
{ return opt && opt->pattern
&& opt->pattern->catalog_role == CATALOG_ROLE_PRODUCER; }
static inline int zone_is_catalog_member(struct zone_options* opt)
{ return opt && opt->is_catalog_member_zone; }
static inline const char* zone_is_catalog_producer_member(struct zone_options* opt)
{ return opt && opt->pattern && opt->pattern->catalog_producer_zone
? opt->pattern->catalog_producer_zone : NULL; }
static inline int zone_is_catalog_consumer_member(struct zone_options* opt)
{ return zone_is_catalog_member(opt) && !zone_is_catalog_producer_member(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, ...) ATTR_FORMAT(printf, 1,2);
int c_wrap(void);
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(struct pattern_options *dest, const char* name);
/* if the file is a directory, print a warning, because flex just exit()s
* when a fileread fails because it is a directory, helps the user figure
* out what just happened */
void warn_if_directory(const char* filetype, FILE* f, const char* fname);
/* resolve interface names in the options "ip-address:" (or "interface:")
* and "control-interface:" into the ip-addresses associated with those
* names. */
void resolve_interface_names(struct nsd_options* options);
/* See if the sockaddr port number is listed in the proxy protocol ports. */
int sockaddr_uses_proxy_protocol_port(struct nsd_options* options,
struct sockaddr* addr);
#endif /* OPTIONS_H */
|