summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2015-02-03 10:24:36 +0000
committerBrad Smith <brad@cvs.openbsd.org>2015-02-03 10:24:36 +0000
commitb971eadcda21aaa31efbb2cb2f47aee6c7c49bca (patch)
treedd7e1e4b95e1787ee0e87e11e1ec0af4b824a293
parent87d547b74f3a496e0b66a9278c1df4715f1720fc (diff)
update to NSD 4.1.1, ok sthen@
-rw-r--r--usr.sbin/nsd/configlexer.lex1
-rw-r--r--usr.sbin/nsd/dbaccess.c1
-rw-r--r--usr.sbin/nsd/difffile.h7
-rw-r--r--usr.sbin/nsd/ipc.c30
-rw-r--r--usr.sbin/nsd/ipc.h2
-rw-r--r--usr.sbin/nsd/nsd-checkzone.8.in2
-rw-r--r--usr.sbin/nsd/nsd-control.c2
-rw-r--r--usr.sbin/nsd/nsd.conf.sample.in4
-rw-r--r--usr.sbin/nsd/nsd.h33
-rw-r--r--usr.sbin/nsd/options.c104
-rw-r--r--usr.sbin/nsd/options.h20
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);