diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2015-02-03 10:24:36 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2015-02-03 10:24:36 +0000 |
commit | b971eadcda21aaa31efbb2cb2f47aee6c7c49bca (patch) | |
tree | dd7e1e4b95e1787ee0e87e11e1ec0af4b824a293 | |
parent | 87d547b74f3a496e0b66a9278c1df4715f1720fc (diff) |
update to NSD 4.1.1, ok sthen@
-rw-r--r-- | usr.sbin/nsd/configlexer.lex | 1 | ||||
-rw-r--r-- | usr.sbin/nsd/dbaccess.c | 1 | ||||
-rw-r--r-- | usr.sbin/nsd/difffile.h | 7 | ||||
-rw-r--r-- | usr.sbin/nsd/ipc.c | 30 | ||||
-rw-r--r-- | usr.sbin/nsd/ipc.h | 2 | ||||
-rw-r--r-- | usr.sbin/nsd/nsd-checkzone.8.in | 2 | ||||
-rw-r--r-- | usr.sbin/nsd/nsd-control.c | 2 | ||||
-rw-r--r-- | usr.sbin/nsd/nsd.conf.sample.in | 4 | ||||
-rw-r--r-- | usr.sbin/nsd/nsd.h | 33 | ||||
-rw-r--r-- | usr.sbin/nsd/options.c | 104 | ||||
-rw-r--r-- | usr.sbin/nsd/options.h | 20 |
11 files changed, 200 insertions, 6 deletions
diff --git a/usr.sbin/nsd/configlexer.lex b/usr.sbin/nsd/configlexer.lex index 87b96b3c3e7..44cabe8ca57 100644 --- a/usr.sbin/nsd/configlexer.lex +++ b/usr.sbin/nsd/configlexer.lex @@ -229,6 +229,7 @@ xfrd-reload-timeout{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_XFRD_RELOAD_ verbosity{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_VERBOSITY;} zone{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONE;} zonefile{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONEFILE;} +zonestats{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ZONESTATS;} allow-notify{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_ALLOW_NOTIFY;} request-xfr{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_REQUEST_XFR;} notify{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_NOTIFY;} diff --git a/usr.sbin/nsd/dbaccess.c b/usr.sbin/nsd/dbaccess.c index 3a60d517665..ad15448038a 100644 --- a/usr.sbin/nsd/dbaccess.c +++ b/usr.sbin/nsd/dbaccess.c @@ -272,6 +272,7 @@ namedb_zone_create(namedb_type* db, const dname_type* dname, zone->filename = NULL; zone->logstr = NULL; zone->mtime = 0; + zone->zonestatid = 0; zone->is_secure = 0; zone->is_changed = 0; zone->is_ok = 1; diff --git a/usr.sbin/nsd/difffile.h b/usr.sbin/nsd/difffile.h index e6a5d4eed17..ae0dbff921a 100644 --- a/usr.sbin/nsd/difffile.h +++ b/usr.sbin/nsd/difffile.h @@ -86,7 +86,9 @@ struct task_list_d { /** delete pattern */ task_del_pattern, /** options change */ - task_opt_change + task_opt_change, + /** zonestat increment */ + task_zonestat_inc } task_type; uint32_t size; /* size of this struct */ @@ -115,13 +117,14 @@ void task_new_write_zonefiles(udb_base* udb, udb_ptr* last, const dname_type* zone); void task_new_set_verbosity(udb_base* udb, udb_ptr* last, int v); void task_new_add_zone(udb_base* udb, udb_ptr* last, const char* zone, - const char* pattern); + const char* pattern, unsigned zonestatid); void task_new_del_zone(udb_base* udb, udb_ptr* last, const dname_type* dname); void task_new_add_key(udb_base* udb, udb_ptr* last, key_options_t* key); void task_new_del_key(udb_base* udb, udb_ptr* last, const char* name); void task_new_add_pattern(udb_base* udb, udb_ptr* last, pattern_options_t* p); void task_new_del_pattern(udb_base* udb, udb_ptr* last, const char* name); void task_new_opt_change(udb_base* udb, udb_ptr* last, nsd_options_t* opt); +void task_new_zonestat_inc(udb_base* udb, udb_ptr* last, unsigned sz); int task_new_apply_xfr(udb_base* udb, udb_ptr* last, const dname_type* zone, uint32_t old_serial, uint32_t new_serial, uint64_t filenumber); void task_process_in_reload(struct nsd* nsd, udb_base* udb, udb_ptr *last_task, diff --git a/usr.sbin/nsd/ipc.c b/usr.sbin/nsd/ipc.c index e1bf2d35b92..1f188e54951 100644 --- a/usr.sbin/nsd/ipc.c +++ b/usr.sbin/nsd/ipc.c @@ -277,6 +277,34 @@ stats_add(struct nsdst* total, struct nsdst* s) total->db_mem = s->db_mem; } +/** subtract stats from total */ +void +stats_subtract(struct nsdst* total, struct nsdst* s) +{ + unsigned i; + for(i=0; i<sizeof(total->qtype)/sizeof(stc_t); i++) + total->qtype[i] -= s->qtype[i]; + for(i=0; i<sizeof(total->qclass)/sizeof(stc_t); i++) + total->qclass[i] -= s->qclass[i]; + total->qudp -= s->qudp; + total->qudp6 -= s->qudp6; + total->ctcp -= s->ctcp; + total->ctcp6 -= s->ctcp6; + for(i=0; i<sizeof(total->rcode)/sizeof(stc_t); i++) + total->rcode[i] -= s->rcode[i]; + for(i=0; i<sizeof(total->opcode)/sizeof(stc_t); i++) + total->opcode[i] -= s->opcode[i]; + total->dropped -= s->dropped; + total->truncated -= s->truncated; + total->wrongzone -= s->wrongzone; + total->txerr -= s->txerr; + total->rxerr -= s->rxerr; + total->edns -= s->edns; + total->ednserr -= s->ednserr; + total->raxfr -= s->raxfr; + total->nona -= s->nona; +} + #define FINAL_STATS_TIMEOUT 10 /* seconds */ static void read_child_stats(struct nsd* nsd, struct nsd_child* child, int fd) @@ -717,12 +745,10 @@ xfrd_handle_ipc_read(struct event* handler, xfrd_state_t* xfrd) case NSD_RELOAD_DONE: /* reload has finished */ DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv RELOAD_DONE")); -#ifdef BIND8_STATS if(block_read(NULL, handler->ev_fd, &xfrd->reload_pid, sizeof(pid_t), -1) != sizeof(pid_t)) { log_msg(LOG_ERR, "xfrd cannot get reload_pid"); } -#endif /* BIND8_STATS */ /* read the not-mytask for the results and soainfo */ xfrd_process_task_result(xfrd, xfrd->nsd->task[1-xfrd->nsd->mytask]); diff --git a/usr.sbin/nsd/ipc.h b/usr.sbin/nsd/ipc.h index cb27db46063..b0d2dce2d2e 100644 --- a/usr.sbin/nsd/ipc.h +++ b/usr.sbin/nsd/ipc.h @@ -89,6 +89,8 @@ void parent_check_all_children_exited(struct nsd* nsd); /** add stats to total */ void stats_add(struct nsdst* total, struct nsdst* s); +/** subtract stats from total */ +void stats_subtract(struct nsdst* total, struct nsdst* s); /** set event to listen to given mode, no timeout, must be added already */ void ipc_xfrd_set_listening(struct xfrd_state* xfrd, short mode); diff --git a/usr.sbin/nsd/nsd-checkzone.8.in b/usr.sbin/nsd/nsd-checkzone.8.in index 1ab76bc5e2f..7a19e1677be 100644 --- a/usr.sbin/nsd/nsd-checkzone.8.in +++ b/usr.sbin/nsd/nsd-checkzone.8.in @@ -1,4 +1,4 @@ -.TH "nsd\-checkzone" "8" "@date@" "NLnet Labs" "nsd @version@" +.TH "nsd\-checkzone" "8" "Feb 3, 2015" "NLnet Labs" "nsd 4.1.1" .\" Copyright (c) 2014, NLnet Labs. All rights reserved. .\" See LICENSE for the license. .SH "NAME" diff --git a/usr.sbin/nsd/nsd-control.c b/usr.sbin/nsd/nsd-control.c index 4a9abbc69ca..2547489eb27 100644 --- a/usr.sbin/nsd/nsd-control.c +++ b/usr.sbin/nsd/nsd-control.c @@ -125,6 +125,8 @@ setup_ctx(nsd_options_t* cfg) ssl_err("could not allocate SSL_CTX pointer"); if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)) ssl_err("could not set SSL_OP_NO_SSLv2"); + if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)) + ssl_err("could not set SSL_OP_NO_SSLv3"); if(!SSL_CTX_use_certificate_file(ctx,c_cert,SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM) || !SSL_CTX_check_private_key(ctx)) diff --git a/usr.sbin/nsd/nsd.conf.sample.in b/usr.sbin/nsd/nsd.conf.sample.in index d6154526c07..a401db69219 100644 --- a/usr.sbin/nsd/nsd.conf.sample.in +++ b/usr.sbin/nsd/nsd.conf.sample.in @@ -236,6 +236,10 @@ remote-control: # default is let the OS choose. #outgoing-interface: 10.0.0.10 + # if compiled with --enable-zone-stats, give name of stat block for + # this zone (or group of zones). Output from nsd-control stats. + # zonestats: "%s" + # if you give another pattern name here, at this point the settings # from that pattern are inserted into this one (as if it were a # macro). The statement can be given in between other statements, diff --git a/usr.sbin/nsd/nsd.h b/usr.sbin/nsd/nsd.h index 14e2dae55f4..121e01ad91a 100644 --- a/usr.sbin/nsd/nsd.h +++ b/usr.sbin/nsd/nsd.h @@ -72,7 +72,6 @@ struct daemon_remote; #endif #ifdef BIND8_STATS - /* Counter for statistics */ typedef unsigned long stc_t; @@ -90,6 +89,21 @@ typedef unsigned long stc_t; #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 */ + struct nsd_socket { struct addrinfo * addr; @@ -221,6 +235,18 @@ struct nsd stc_t edns, ednserr, raxfr, nona; uint64_t db_disk, db_mem; } st; + /* 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; #endif /* BIND8_STATS */ struct nsd_options* options; @@ -246,6 +272,11 @@ struct event_base* nsd_child_event_base(void); /* extra domain numbers for temporary domains */ #define EXTRA_DOMAIN_NUMBERS 1024 #define SLOW_ACCEPT_TIMEOUT 2 /* in seconds */ +/* 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 and init xfrd variables */ void server_prepare_xfrd(struct nsd *nsd); /* start xfrdaemon (again) */ diff --git a/usr.sbin/nsd/options.c b/usr.sbin/nsd/options.c index c7ef346ec7a..8b8f3f5352e 100644 --- a/usr.sbin/nsd/options.c +++ b/usr.sbin/nsd/options.c @@ -28,6 +28,9 @@ void c_error(const char *message); static int rbtree_strcmp(const void* p1, const void* p2) { + if(p1 == NULL && p2 == NULL) return 0; + if(p1 == NULL) return -1; + if(p2 == NULL) return 1; return strcmp((const char*)p1, (const char*)p2); } @@ -40,6 +43,7 @@ nsd_options_create(region_type* region) opt->zone_options = rbtree_create(region, (int (*)(const void *, const void *)) dname_compare); opt->configfile = NULL; + opt->zonestatnames = rbtree_create(opt->region, rbtree_strcmp); opt->patterns = rbtree_create(region, rbtree_strcmp); opt->keys = rbtree_create(region, rbtree_strcmp); opt->ip_addresses = NULL; @@ -256,10 +260,34 @@ parse_options_file(nsd_options_t* opt, const char* file, return 1; } +void options_zonestatnames_create(nsd_options_t* opt) +{ + zone_options_t* zopt; + /* allocate "" as zonestat 0, for zones without a zonestat */ + if(!rbtree_search(opt->zonestatnames, "")) { + struct zonestatname* n; + n = (struct zonestatname*)xalloc(sizeof(*n)); + memset(n, 0, sizeof(*n)); + n->node.key = strdup(""); + if(!n->node.key) { + log_msg(LOG_ERR, "malloc failed: %s", strerror(errno)); + exit(1); + } + n->id = (unsigned)(opt->zonestatnames->count); + rbtree_insert(opt->zonestatnames, (rbnode_t*)n); + } + RBTREE_FOR(zopt, zone_options_t*, opt->zone_options) { + /* insert into tree, so that when read in later id exists */ + (void)getzonestatid(opt, zopt); + } +} + #define ZONELIST_HEADER "# NSD zone list\n# name pattern\n" static int comp_zonebucket(const void* a, const void* b) { + /* the line size is much smaller than max-int, and positive, + * so the subtraction works */ return *(const int*)b - *(const int*)a; } @@ -751,6 +779,7 @@ pattern_options_create(region_type* region) p->node = *RBTREE_NULL; p->pname = 0; p->zonefile = 0; + p->zonestats = 0; p->allow_notify = 0; p->request_xfr = 0; p->notify = 0; @@ -806,6 +835,9 @@ pattern_options_remove(nsd_options_t* opt, const char* name) if(p->zonefile) region_recycle(opt->region, (void*)p->zonefile, strlen(p->zonefile)+1); + if(p->zonestats) + region_recycle(opt->region, (void*)p->zonestats, + strlen(p->zonestats)+1); acl_list_delete(opt->region, p->allow_notify); acl_list_delete(opt->region, p->request_xfr); acl_list_delete(opt->region, p->notify); @@ -878,6 +910,9 @@ copy_pat_fixed(region_type* region, pattern_options_t* orig, if(p->zonefile) orig->zonefile = region_strdup(region, p->zonefile); else orig->zonefile = NULL; + if(p->zonestats) + orig->zonestats = region_strdup(region, p->zonestats); + else orig->zonestats = NULL; #ifdef RATELIMIT orig->rrl_whitelist = p->rrl_whitelist; #endif @@ -905,6 +940,9 @@ pattern_options_add_modify(nsd_options_t* opt, pattern_options_t* p) if(orig->zonefile) region_recycle(opt->region, (char*)orig->zonefile, strlen(orig->zonefile)+1); + if(orig->zonestats) + region_recycle(opt->region, (char*)orig->zonestats, + strlen(orig->zonestats)+1); copy_pat_fixed(opt->region, orig, p); copy_changed_acl(opt, &orig->allow_notify, p->allow_notify); copy_changed_acl(opt, &orig->request_xfr, p->request_xfr); @@ -930,6 +968,11 @@ pattern_options_equal(pattern_options_t* p, pattern_options_t* q) else if(p->zonefile && q->zonefile) { if(strcmp(p->zonefile, q->zonefile) != 0) return 0; } + if(!p->zonestats && q->zonestats) return 0; + else if(p->zonestats && !q->zonestats) return 0; + else if(p->zonestats && q->zonestats) { + if(strcmp(p->zonestats, q->zonestats) != 0) return 0; + } if(!booleq(p->allow_axfr_fallback, q->allow_axfr_fallback)) return 0; if(!booleq(p->allow_axfr_fallback_is_default, q->allow_axfr_fallback_is_default)) return 0; @@ -1055,6 +1098,7 @@ pattern_options_marshal(struct buffer* b, pattern_options_t* p) { marshal_str(b, p->pname); marshal_str(b, p->zonefile); + marshal_str(b, p->zonestats); #ifdef RATELIMIT marshal_u16(b, p->rrl_whitelist); #endif @@ -1076,6 +1120,7 @@ pattern_options_unmarshal(region_type* r, struct buffer* b) pattern_options_t* p = pattern_options_create(r); p->pname = unmarshal_str(r, b); p->zonefile = unmarshal_str(r, b); + p->zonestats = unmarshal_str(r, b); #ifdef RATELIMIT p->rrl_whitelist = unmarshal_u16(b); #endif @@ -1548,6 +1593,32 @@ replace_str(char* str, size_t len, const char* one, const char* two) } const char* +config_cook_string(zone_options_t* zone, const char* input) +{ + static char f[1024]; + /* if not a template, return as-is */ + if(!strchr(input, '%')) { + return input; + } + strlcpy(f, input, sizeof(f)); + if(strstr(f, "%1")) + replace_str(f, sizeof(f), "%1", get_char(zone->name, 0)); + if(strstr(f, "%2")) + replace_str(f, sizeof(f), "%2", get_char(zone->name, 1)); + if(strstr(f, "%3")) + replace_str(f, sizeof(f), "%3", get_char(zone->name, 2)); + if(strstr(f, "%z")) + replace_str(f, sizeof(f), "%z", get_end_label(zone, 1)); + if(strstr(f, "%y")) + replace_str(f, sizeof(f), "%y", get_end_label(zone, 2)); + if(strstr(f, "%x")) + replace_str(f, sizeof(f), "%x", get_end_label(zone, 3)); + if(strstr(f, "%s")) + replace_str(f, sizeof(f), "%s", zone->name); + return f; +} + +const char* config_make_zonefile(zone_options_t* zone, struct nsd* nsd) { static char f[1024]; @@ -1762,6 +1833,9 @@ config_apply_pattern(const char* name) if(pat->zonefile) a->zonefile = region_strdup(cfg_parser->opt->region, pat->zonefile); + if(pat->zonestats) + a->zonestats = region_strdup(cfg_parser->opt->region, + pat->zonestats); if(!pat->allow_axfr_fallback_is_default) { a->allow_axfr_fallback = pat->allow_axfr_fallback; a->allow_axfr_fallback_is_default = 0; @@ -1790,3 +1864,33 @@ nsd_options_destroy(nsd_options_t* opt) { region_destroy(opt->region); } + +unsigned getzonestatid(nsd_options_t* opt, zone_options_t* zopt) +{ +#ifdef USE_ZONE_STATS + const char* statname; + struct zonestatname* n; + rbnode_t* res; + /* try to find the instantiated zonestat name */ + if(!zopt->pattern->zonestats || zopt->pattern->zonestats[0]==0) + return 0; /* no zone stats */ + statname = config_cook_string(zopt, zopt->pattern->zonestats); + res = rbtree_search(opt->zonestatnames, statname); + if(res) + return ((struct zonestatname*)res)->id; + /* create it */ + n = (struct zonestatname*)xalloc(sizeof(*n)); + memset(n, 0, sizeof(*n)); + n->node.key = strdup(statname); + if(!n->node.key) { + log_msg(LOG_ERR, "malloc failed: %s", strerror(errno)); + exit(1); + } + n->id = (unsigned)(opt->zonestatnames->count); + rbtree_insert(opt->zonestatnames, (rbnode_t*)n); + return n->id; +#else /* USE_ZONE_STATS */ + (void)opt; (void)zopt; + return 0; +#endif /* USE_ZONE_STATS */ +} diff --git a/usr.sbin/nsd/options.h b/usr.sbin/nsd/options.h index f36b11f242f..da3d0979175 100644 --- a/usr.sbin/nsd/options.h +++ b/usr.sbin/nsd/options.h @@ -47,6 +47,12 @@ struct nsd_options { /* 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_t* zonestatnames; + /* rbtree of keys defined, by name */ rbtree_t* keys; @@ -133,6 +139,7 @@ struct pattern_options { acl_options_t* notify; acl_options_t* provide_xfr; acl_options_t* outgoing_interface; + const char* zonestats; #ifdef RATELIMIT uint16_t rrl_whitelist; /* bitmap with rrl types */ #endif @@ -232,6 +239,11 @@ struct zonelist_bucket { /* default zonefile write interval if database is "", in seconds */ #define ZONEFILES_WRITE_INTERVAL 3600 +struct zonestatname { + rbnode_t node; /* key is malloced string with cooked zonestat name */ + unsigned id; /* index in nsd.zonestat array */ +}; + /* * Used during options parsing */ @@ -300,6 +312,14 @@ void zone_list_del(nsd_options_t* opt, zone_options_t* zone); void zone_list_compact(nsd_options_t* opt); void zone_list_close(nsd_options_t* opt); +/* create zonestat name tree , for initially created zones */ +void options_zonestatnames_create(nsd_options_t* opt); +/* Get zonestat id for zone options, add new entry if necessary. + * instantiates the pattern's zonestat string */ +unsigned getzonestatid(nsd_options_t* opt, zone_options_t* zopt); +/* create string, same options as zonefile but no chroot changes */ +const char* config_cook_string(zone_options_t* zone, const char* input); + #if defined(HAVE_SSL) /* tsig must be inited, adds all keys in options to tsig. */ void key_options_tsig_add(nsd_options_t* opt); |