diff options
author | Stuart Henderson <sthen@cvs.openbsd.org> | 2018-03-06 21:01:57 +0000 |
---|---|---|
committer | Stuart Henderson <sthen@cvs.openbsd.org> | 2018-03-06 21:01:57 +0000 |
commit | 4157bfe853632fd5c5114d6aa129b82ab9750e1b (patch) | |
tree | 5aedbbf66c0d7bcfbc5e3eac4fc9b18fadef9e3f /usr.sbin/nsd | |
parent | 9a8f7b3dd87f2c34a24e399571c736f88059ec36 (diff) |
update to NSD 4.1.20, ok florian@
- Fix memory leak in zone file read of unknown rr formatted RRs.
- Fix memory leak when rehashing nsec3 after axfr or zonefile read,
in the selectively allocated precompiled nsec3 hashes.
Diffstat (limited to 'usr.sbin/nsd')
-rw-r--r-- | usr.sbin/nsd/Makefile.in | 12 | ||||
-rw-r--r-- | usr.sbin/nsd/configure | 32 | ||||
-rw-r--r-- | usr.sbin/nsd/configure.ac | 6 | ||||
-rw-r--r-- | usr.sbin/nsd/difffile.c | 1 | ||||
-rw-r--r-- | usr.sbin/nsd/ipc.c | 10 | ||||
-rw-r--r-- | usr.sbin/nsd/namedb.c | 10 | ||||
-rw-r--r-- | usr.sbin/nsd/nsd.c | 14 | ||||
-rw-r--r-- | usr.sbin/nsd/nsd.h | 6 | ||||
-rw-r--r-- | usr.sbin/nsd/nsec3.c | 2 | ||||
-rw-r--r-- | usr.sbin/nsd/options.c | 37 | ||||
-rw-r--r-- | usr.sbin/nsd/query.c | 2 | ||||
-rw-r--r-- | usr.sbin/nsd/rrl.c | 28 | ||||
-rw-r--r-- | usr.sbin/nsd/rrl.h | 19 | ||||
-rw-r--r-- | usr.sbin/nsd/server.c | 23 | ||||
-rw-r--r-- | usr.sbin/nsd/xfrd.c | 50 | ||||
-rw-r--r-- | usr.sbin/nsd/zonec.c | 7 | ||||
-rw-r--r-- | usr.sbin/nsd/zparser.y | 6 |
17 files changed, 219 insertions, 46 deletions
diff --git a/usr.sbin/nsd/Makefile.in b/usr.sbin/nsd/Makefile.in index 3468101c19d..5bd2364579c 100644 --- a/usr.sbin/nsd/Makefile.in +++ b/usr.sbin/nsd/Makefile.in @@ -373,7 +373,8 @@ edns.o: $(srcdir)/edns.c config.h $(srcdir)/dns.h $(srcdir)/edns.h $(srcdir)/buf $(srcdir)/nsd.h $(srcdir)/query.h $(srcdir)/namedb.h $(srcdir)/dname.h $(srcdir)/radtree.h $(srcdir)/rbtree.h $(srcdir)/packet.h $(srcdir)/tsig.h ipc.o: $(srcdir)/ipc.c config.h $(srcdir)/ipc.h $(srcdir)/netio.h $(srcdir)/region-allocator.h $(srcdir)/buffer.h $(srcdir)/util.h \ $(srcdir)/xfrd-tcp.h $(srcdir)/xfrd.h $(srcdir)/rbtree.h $(srcdir)/namedb.h $(srcdir)/dname.h $(srcdir)/dns.h $(srcdir)/radtree.h $(srcdir)/options.h \ - $(srcdir)/tsig.h $(srcdir)/nsd.h $(srcdir)/edns.h $(srcdir)/xfrd-notify.h $(srcdir)/difffile.h $(srcdir)/udb.h + $(srcdir)/tsig.h $(srcdir)/nsd.h $(srcdir)/edns.h $(srcdir)/xfrd-notify.h $(srcdir)/difffile.h $(srcdir)/udb.h $(srcdir)/rrl.h $(srcdir)/query.h \ + $(srcdir)/packet.h iterated_hash.o: $(srcdir)/iterated_hash.c config.h $(srcdir)/iterated_hash.h lookup3.o: $(srcdir)/lookup3.c config.h $(srcdir)/lookup3.h mini_event.o: $(srcdir)/mini_event.c config.h @@ -436,7 +437,7 @@ util.o: $(srcdir)/util.c config.h $(srcdir)/util.h $(srcdir)/region-allocator.h xfrd.o: $(srcdir)/xfrd.c config.h $(srcdir)/xfrd.h $(srcdir)/rbtree.h $(srcdir)/region-allocator.h $(srcdir)/namedb.h \ $(srcdir)/dname.h $(srcdir)/buffer.h $(srcdir)/util.h $(srcdir)/dns.h $(srcdir)/radtree.h $(srcdir)/options.h $(srcdir)/tsig.h $(srcdir)/xfrd-tcp.h \ $(srcdir)/xfrd-disk.h $(srcdir)/xfrd-notify.h $(srcdir)/netio.h $(srcdir)/nsd.h $(srcdir)/edns.h $(srcdir)/packet.h $(srcdir)/rdata.h \ - $(srcdir)/difffile.h $(srcdir)/udb.h $(srcdir)/ipc.h $(srcdir)/remote.h + $(srcdir)/difffile.h $(srcdir)/udb.h $(srcdir)/ipc.h $(srcdir)/remote.h $(srcdir)/rrl.h $(srcdir)/query.h xfrd-disk.o: $(srcdir)/xfrd-disk.c config.h $(srcdir)/xfrd-disk.h $(srcdir)/xfrd.h $(srcdir)/rbtree.h \ $(srcdir)/region-allocator.h $(srcdir)/namedb.h $(srcdir)/dname.h $(srcdir)/buffer.h $(srcdir)/util.h $(srcdir)/dns.h $(srcdir)/radtree.h \ $(srcdir)/options.h $(srcdir)/tsig.h $(srcdir)/nsd.h $(srcdir)/edns.h @@ -446,6 +447,9 @@ xfrd-notify.o: $(srcdir)/xfrd-notify.c config.h $(srcdir)/xfrd-notify.h $(srcdir xfrd-tcp.o: $(srcdir)/xfrd-tcp.c config.h $(srcdir)/nsd.h $(srcdir)/dns.h $(srcdir)/edns.h $(srcdir)/buffer.h \ $(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/xfrd-tcp.h $(srcdir)/xfrd.h $(srcdir)/rbtree.h $(srcdir)/namedb.h $(srcdir)/dname.h \ $(srcdir)/radtree.h $(srcdir)/options.h $(srcdir)/tsig.h $(srcdir)/packet.h $(srcdir)/xfrd-disk.h +xfr-inspect.o: $(srcdir)/xfr-inspect.c config.h $(srcdir)/udbzone.h $(srcdir)/udb.h $(srcdir)/dns.h $(srcdir)/udbradtree.h \ + $(srcdir)/util.h $(srcdir)/buffer.h $(srcdir)/region-allocator.h $(srcdir)/packet.h $(srcdir)/namedb.h $(srcdir)/dname.h $(srcdir)/radtree.h \ + $(srcdir)/rbtree.h $(srcdir)/rdata.h $(srcdir)/difffile.h $(srcdir)/options.h zlexer.o: zlexer.c config.h $(srcdir)/zonec.h $(srcdir)/namedb.h $(srcdir)/dname.h $(srcdir)/buffer.h \ $(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/dns.h $(srcdir)/radtree.h $(srcdir)/rbtree.h zparser.h zonec.o: $(srcdir)/zonec.c config.h $(srcdir)/zonec.h $(srcdir)/namedb.h $(srcdir)/dname.h $(srcdir)/buffer.h \ @@ -513,7 +517,3 @@ udb-inspect.o: $(srcdir)/tpkg/cutest/udb-inspect.c config.h $(srcdir)/udb.h $(sr $(srcdir)/udb.h $(srcdir)/udbzone.h $(srcdir)/dns.h $(srcdir)/udbradtree.h $(srcdir)/util.h $(srcdir)/buffer.h $(srcdir)/region-allocator.h \ $(srcdir)/util.h $(srcdir)/packet.h $(srcdir)/namedb.h $(srcdir)/dname.h $(srcdir)/buffer.h $(srcdir)/radtree.h $(srcdir)/rbtree.h $(srcdir)/rdata.h \ $(srcdir)/namedb.h $(srcdir)/difffile.h $(srcdir)/options.h config.h -xfr-inspect.o: $(srcdir)/xfr-inspect.c config.h $(srcdir)/udbzone.h $(srcdir)/udb.h $(srcdir)/dns.h \ - $(srcdir)/udbradtree.h $(srcdir)/util.h $(srcdir)/buffer.h $(srcdir)/region-allocator.h $(srcdir)/util.h $(srcdir)/packet.h $(srcdir)/namedb.h \ - $(srcdir)/dname.h $(srcdir)/buffer.h $(srcdir)/radtree.h $(srcdir)/rbtree.h $(srcdir)/rdata.h $(srcdir)/namedb.h $(srcdir)/difffile.h \ - $(srcdir)/options.h config.h diff --git a/usr.sbin/nsd/configure b/usr.sbin/nsd/configure index e73ca9121cd..8050504dd46 100644 --- a/usr.sbin/nsd/configure +++ b/usr.sbin/nsd/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for NSD 4.1.19. +# Generated by GNU Autoconf 2.69 for NSD 4.1.20. # # Report bugs to <nsd-bugs@nlnetlabs.nl>. # @@ -580,8 +580,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='NSD' PACKAGE_TARNAME='nsd' -PACKAGE_VERSION='4.1.19' -PACKAGE_STRING='NSD 4.1.19' +PACKAGE_VERSION='4.1.20' +PACKAGE_STRING='NSD 4.1.20' PACKAGE_BUGREPORT='nsd-bugs@nlnetlabs.nl' PACKAGE_URL='' @@ -725,6 +725,7 @@ enable_ipv6 enable_bind8_stats enable_zone_stats enable_checking +enable_memclean enable_ratelimit enable_ratelimit_default_is_off with_ssl @@ -1285,7 +1286,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures NSD 4.1.19 to adapt to many kinds of systems. +\`configure' configures NSD 4.1.20 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1346,7 +1347,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of NSD 4.1.19:";; + short | recursive ) echo "Configuration of NSD 4.1.20:";; esac cat <<\_ACEOF @@ -1370,6 +1371,7 @@ Optional Features: --enable-zone-stats Enable per-zone statistics gathering (needs --enable-bind8-stats) --enable-checking Enable internal runtime checks + --enable-memclean Cleanup memory (at exit) for eg. valgrind, memcheck --enable-ratelimit Enable rate limiting --enable-ratelimit-default-is-off Enable this to set default of ratelimit to off @@ -1494,7 +1496,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -NSD configure 4.1.19 +NSD configure 4.1.20 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2203,7 +2205,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by NSD $as_me 4.1.19, which was +It was created by NSD $as_me 4.1.20, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -8644,6 +8646,18 @@ $as_echo "#define NDEBUG /**/" >>confdefs.h ;; esac +# Check whether --enable-memclean was given. +if test "${enable_memclean+set}" = set; then : + enableval=$enable_memclean; +fi + +if test "$enable_memclean" = "yes"; then +cat >>confdefs.h <<_ACEOF +#define MEMCLEAN 1 +_ACEOF + +fi + # Check whether --enable-ratelimit was given. if test "${enable_ratelimit+set}" = set; then : enableval=$enable_ratelimit; @@ -9770,7 +9784,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by NSD $as_me 4.1.19, which was +This file was extended by NSD $as_me 4.1.20, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -9832,7 +9846,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -NSD config.status 4.1.19 +NSD config.status 4.1.20 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/usr.sbin/nsd/configure.ac b/usr.sbin/nsd/configure.ac index 7dd787eaed5..8c11b400c6a 100644 --- a/usr.sbin/nsd/configure.ac +++ b/usr.sbin/nsd/configure.ac @@ -4,7 +4,7 @@ dnl sinclude(acx_nlnetlabs.m4) -AC_INIT(NSD,4.1.19,nsd-bugs@nlnetlabs.nl) +AC_INIT(NSD,4.1.20,nsd-bugs@nlnetlabs.nl) AC_CONFIG_HEADER([config.h]) CFLAGS="$CFLAGS" @@ -800,6 +800,10 @@ case "$enable_checking" in ;; esac +AC_ARG_ENABLE(memclean, AC_HELP_STRING([--enable-memclean], [Cleanup memory (at exit) for eg. valgrind, memcheck])) +if test "$enable_memclean" = "yes"; then AC_DEFINE_UNQUOTED([MEMCLEAN], [1], [Define this to cleanup memory at exit (eg. for valgrind, etc.)]) +fi + AC_ARG_ENABLE(ratelimit, AC_HELP_STRING([--enable-ratelimit], [Enable rate limiting])) case "$enable_ratelimit" in yes) diff --git a/usr.sbin/nsd/difffile.c b/usr.sbin/nsd/difffile.c index 1fb5bda0003..3bcfba6d6e1 100644 --- a/usr.sbin/nsd/difffile.c +++ b/usr.sbin/nsd/difffile.c @@ -1333,6 +1333,7 @@ apply_ixfr_for_zone(nsd_type* nsd, zone_type* zonedb, FILE* in, udb_ptr z; DEBUG(DEBUG_XFRD,1, (LOG_INFO, "processing xfr: %s", zone_buf)); + memset(&z, 0, sizeof(z)); /* if udb==NULL, have &z defined */ if(nsd->db->udb) { if(udb_base_get_userflags(nsd->db->udb) != 0) { log_msg(LOG_ERR, "database corrupted, cannot update"); diff --git a/usr.sbin/nsd/ipc.c b/usr.sbin/nsd/ipc.c index 5466239265a..ff5bf07db1a 100644 --- a/usr.sbin/nsd/ipc.c +++ b/usr.sbin/nsd/ipc.c @@ -20,6 +20,7 @@ #include "xfrd.h" #include "xfrd-notify.h" #include "difffile.h" +#include "rrl.h" /* attempt to send NSD_STATS command to child fd */ static void send_stat_to_child(struct main_ipc_handler_data* data, int fd); @@ -39,9 +40,12 @@ ipc_child_quit(struct nsd* nsd) bind8_stats(nsd); #endif /* BIND8_STATS */ -#if 0 /* OS collects memory pages */ - event_base_free(event_base); - region_destroy(server_region); +#ifdef MEMCLEAN /* OS collects memory pages */ +#ifdef RATELIMIT + rrl_deinit(nsd->this_child->child_num); +#endif + event_base_free(nsd->event_base); + region_destroy(nsd->server_region); #endif server_shutdown(nsd); exit(0); diff --git a/usr.sbin/nsd/namedb.c b/usr.sbin/nsd/namedb.c index bc7690d87b6..4528b6e4f15 100644 --- a/usr.sbin/nsd/namedb.c +++ b/usr.sbin/nsd/namedb.c @@ -242,6 +242,16 @@ do_deldomain(namedb_type* db, domain_type* domain) if(domain->nsec3->ds_parent_hash && domain->nsec3->ds_parent_hash->node.key) zone_del_domain_in_hash_tree(nsec3_tree_dszone(db, domain) ->dshashtree, &domain->nsec3->ds_parent_hash->node); + if(domain->nsec3->hash_wc) { + region_recycle(db->domains->region, + domain->nsec3->hash_wc, + sizeof(nsec3_hash_wc_node_type)); + } + if(domain->nsec3->ds_parent_hash) { + region_recycle(db->domains->region, + domain->nsec3->ds_parent_hash, + sizeof(nsec3_hash_node_type)); + } region_recycle(db->domains->region, domain->nsec3, sizeof(struct nsec3_domain_data)); } diff --git a/usr.sbin/nsd/nsd.c b/usr.sbin/nsd/nsd.c index dfbc58696b3..44be84a9149 100644 --- a/usr.sbin/nsd/nsd.c +++ b/usr.sbin/nsd/nsd.c @@ -177,6 +177,9 @@ add_interface(char*** nodes, struct nsd* nsd, char* ip) nsd->udp = xalloc_zero(sizeof(*nsd->udp)); nsd->tcp = xalloc_zero(sizeof(*nsd->udp)); } else { + region_remove_cleanup(nsd->region, free, *nodes); + region_remove_cleanup(nsd->region, free, nsd->udp); + region_remove_cleanup(nsd->region, free, nsd->tcp); *nodes = xrealloc(*nodes, (nsd->ifs+1)*sizeof(*nodes)); nsd->udp = xrealloc(nsd->udp, (nsd->ifs+1)*sizeof(*nsd->udp)); nsd->tcp = xrealloc(nsd->tcp, (nsd->ifs+1)*sizeof(*nsd->udp)); @@ -184,6 +187,9 @@ add_interface(char*** nodes, struct nsd* nsd, char* ip) memset(&nsd->udp[nsd->ifs], 0, sizeof(*nsd->udp)); memset(&nsd->tcp[nsd->ifs], 0, sizeof(*nsd->tcp)); } + region_add_cleanup(nsd->region, free, *nodes); + region_add_cleanup(nsd->region, free, nsd->udp); + region_add_cleanup(nsd->region, free, nsd->tcp); /* add it */ (*nodes)[nsd->ifs] = ip; @@ -595,7 +601,7 @@ main(int argc, char *argv[]) } } argc -= optind; - argv += optind; + /* argv += optind; */ /* Commandline parse error */ if (argc != 0) { @@ -763,6 +769,9 @@ main(int argc, char *argv[]) nsd.children[i].need_to_send_QUIT = 0; nsd.children[i].need_to_exit = 0; nsd.children[i].has_exited = 0; +#ifdef BIND8_STATS + nsd.children[i].query_count = 0; +#endif } nsd.this_child = NULL; @@ -799,6 +808,7 @@ main(int argc, char *argv[]) } /* Set up the address info structures with real interface/port data */ + assert(nodes); for (i = 0; i < nsd.ifs; ++i) { int r; const char* node = NULL; @@ -1134,6 +1144,8 @@ main(int argc, char *argv[]) /* xfrd forks this before reading database, so it does not get * the memory size of the database */ server_start_xfrd(&nsd, 0, 0); + /* close zonelistfile in non-xfrd processes */ + zone_list_close(nsd.options); } if (server_prepare(&nsd) != 0) { unlinkpid(nsd.pidfile); diff --git a/usr.sbin/nsd/nsd.h b/usr.sbin/nsd/nsd.h index 0090100d00b..5133b1b7918 100644 --- a/usr.sbin/nsd/nsd.h +++ b/usr.sbin/nsd/nsd.h @@ -184,7 +184,11 @@ struct nsd /* mmaps with data exchange from xfrd and reload */ struct udb_base* task[2]; - int mytask; /* the base used by this process */ + 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; diff --git a/usr.sbin/nsd/nsec3.c b/usr.sbin/nsd/nsec3.c index dad4f23d7bf..716d2e72a62 100644 --- a/usr.sbin/nsd/nsec3.c +++ b/usr.sbin/nsd/nsec3.c @@ -537,7 +537,7 @@ nsec3_precompile_domain(struct namedb* db, struct domain* domain, else domain->nsec3->nsec3_is_exact = 0; /* find cover for *.domain for wildcard denial */ - exact = nsec3_find_cover(zone, domain->nsec3->hash_wc->wc.hash, + (void)nsec3_find_cover(zone, domain->nsec3->hash_wc->wc.hash, sizeof(domain->nsec3->hash_wc->wc.hash), &result); domain->nsec3->nsec3_wcard_child_cover = result; } diff --git a/usr.sbin/nsd/options.c b/usr.sbin/nsd/options.c index 026f8b91fac..dd6d29b446a 100644 --- a/usr.sbin/nsd/options.c +++ b/usr.sbin/nsd/options.c @@ -23,6 +23,7 @@ extern FILE* c_in, *c_out; int c_parse(void); int c_lex(void); int c_wrap(void); +int c_lex_destroy(void); void c_error(const char *message); extern char* c_text; @@ -280,9 +281,9 @@ void options_zonestatnames_create(struct nsd_options* opt) /* 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(""); + n = (struct zonestatname*)region_alloc_zero(opt->region, + sizeof(*n)); + n->node.key = region_strdup(opt->region, ""); if(!n->node.key) { log_msg(LOG_ERR, "malloc failed: %s", strerror(errno)); exit(1); @@ -692,8 +693,10 @@ zone_list_compact(struct nsd_options* opt) void zone_list_close(struct nsd_options* opt) { - fclose(opt->zonelist); - opt->zonelist = NULL; + if(opt->zonelist) { + fclose(opt->zonelist); + opt->zonelist = NULL; + } } void @@ -1887,11 +1890,15 @@ parse_acl_info(region_type* region, char* ip, const char* key) #ifdef INET6 if(inet_pton(AF_INET6, ip, &acl->addr.addr6) != 1) c_error_msg("Bad ip6 address '%s'", ip); - if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax) + if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax) { + assert(p); if(inet_pton(AF_INET6, p, &acl->range_mask.addr6) != 1) c_error_msg("Bad ip6 address mask '%s'", p); - if(acl->rangetype==acl_range_subnet) + } + if(acl->rangetype==acl_range_subnet) { + assert(p); parse_acl_range_subnet(p, &acl->range_mask.addr6, 128); + } #else c_error_msg("encountered IPv6 address '%s'.", ip); #endif /* INET6 */ @@ -1899,11 +1906,15 @@ parse_acl_info(region_type* region, char* ip, const char* key) acl->is_ipv6 = 0; if(inet_pton(AF_INET, ip, &acl->addr.addr) != 1) c_error_msg("Bad ip4 address '%s'", ip); - if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax) + if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax) { + assert(p); if(inet_pton(AF_INET, p, &acl->range_mask.addr) != 1) c_error_msg("Bad ip4 address mask '%s'", p); - if(acl->rangetype==acl_range_subnet) + } + if(acl->rangetype==acl_range_subnet) { + assert(p); parse_acl_range_subnet(p, &acl->range_mask.addr, 32); + } } /* key */ @@ -2005,6 +2016,9 @@ void nsd_options_destroy(struct nsd_options* opt) { region_destroy(opt->region); +#ifdef MEMCLEAN /* OS collects memory pages */ + c_lex_destroy(); +#endif } unsigned getzonestatid(struct nsd_options* opt, struct zone_options* zopt) @@ -2021,9 +2035,8 @@ unsigned getzonestatid(struct nsd_options* opt, struct zone_options* zopt) 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); + n = (struct zonestatname*)region_alloc_zero(opt->region, sizeof(*n)); + n->node.key = region_strdup(opt->region, statname); if(!n->node.key) { log_msg(LOG_ERR, "malloc failed: %s", strerror(errno)); exit(1); diff --git a/usr.sbin/nsd/query.c b/usr.sbin/nsd/query.c index 7b862a45bc7..834104e0761 100644 --- a/usr.sbin/nsd/query.c +++ b/usr.sbin/nsd/query.c @@ -1085,7 +1085,7 @@ answer_authoritative(struct nsd *nsd, } DEBUG(DEBUG_QUERY,2, (LOG_INFO, "->result is %s", dname_to_string(newname, NULL))); /* follow the DNAME */ - exact = namedb_lookup(nsd->db, newname, &closest_match, &closest_encloser); + (void)namedb_lookup(nsd->db, newname, &closest_match, &closest_encloser); /* synthesize CNAME record */ newnum = query_synthesize_cname(q, answer, name, newname, src, closest_encloser, &closest_match, rrset->rrs[0].ttl); diff --git a/usr.sbin/nsd/rrl.c b/usr.sbin/nsd/rrl.c index c8dec3fc908..69232a95f4a 100644 --- a/usr.sbin/nsd/rrl.c +++ b/usr.sbin/nsd/rrl.c @@ -100,6 +100,27 @@ void rrl_mmap_init(int numch, size_t numbuck, size_t lm, size_t wlm, size_t sm, #endif } +void rrl_mmap_deinit(void) +{ +#ifdef HAVE_MMAP + size_t i; + for(i=0; i<rrl_maps_num; i++) { + munmap(rrl_maps[i], sizeof(struct rrl_bucket)*rrl_array_size); + rrl_maps[i] = NULL; + } + free(rrl_maps); + rrl_maps = NULL; +#endif +} + +void rrl_mmap_deinit_keep_mmap(void) +{ +#ifdef HAVE_MMAP + free(rrl_maps); + rrl_maps = NULL; +#endif +} + void rrl_set_limit(size_t lm, size_t wlm, size_t sm) { rrl_ratelimit = lm*2; @@ -117,6 +138,13 @@ void rrl_init(size_t ch) #endif } +void rrl_deinit(size_t ch) +{ + if(!rrl_maps || ch >= rrl_maps_num) + free(rrl_array); + rrl_array = NULL; +} + /** return the source netblock of the query, this is the genuine source * for genuine queries and the target for reflected packets */ static uint64_t rrl_get_source(query_type* query, uint16_t* c2) diff --git a/usr.sbin/nsd/rrl.h b/usr.sbin/nsd/rrl.h index fae8fbf2343..8dbc3184d1a 100644 --- a/usr.sbin/nsd/rrl.h +++ b/usr.sbin/nsd/rrl.h @@ -30,20 +30,35 @@ enum rrl_type { #define RRL_BUCKETS 1000000 /** default rrl limit, in 2x qps , the default is 200 qps */ #define RRL_LIMIT 400 +/** default slip */ +#define RRL_SLIP 2 +/** default prefix lengths */ +#define RRL_IPV4_PREFIX_LENGTH 24 +#define RRL_IPV6_PREFIX_LENGTH 64 /** default whitelist rrl limit, in 2x qps, default is thus 2000 qps */ #define RRL_WLIST_LIMIT 4000 /** * Initialize for n children (optional, otherwise no mmaps used) * ratelimits lm and wlm are in qps (this routines x2s them for internal use). + * plf and pls are in prefix lengths. */ -void rrl_mmap_init(int numch, size_t numbuck, size_t lm, size_t wlm); +void rrl_mmap_init(int numch, size_t numbuck, size_t lm, size_t wlm, size_t sm, + size_t plf, size_t pls); /** * Initialize rate limiting (for this child server process) */ void rrl_init(size_t ch); +/** deinit (for this child server processs) */ +void rrl_deinit(size_t ch); + +/** deinit mmaps for n children */ +void rrl_mmap_deinit(void); +/** frees memory but keeps mmap in place (for other processes) */ +void rrl_mmap_deinit_keep_mmap(void); + /** * Process query that happens, the query structure contains the * information about the query and the answer. @@ -66,6 +81,6 @@ enum rrl_type rrlstr2type(const char* s); uint32_t rrl_update(query_type* query, uint32_t hash, uint64_t source, uint16_t flags, int32_t now, uint32_t lm); /** set the rate limit counters, pass variables in qps */ -void rrl_set_limit(size_t lm, size_t wlm); +void rrl_set_limit(size_t lm, size_t wlm, size_t sm); #endif /* RRL_H */ diff --git a/usr.sbin/nsd/server.c b/usr.sbin/nsd/server.c index fe74f9a1b56..2531ff6424b 100644 --- a/usr.sbin/nsd/server.c +++ b/usr.sbin/nsd/server.c @@ -308,6 +308,9 @@ restart_child_servers(struct nsd *nsd, region_type* region, netio_type* netio, /* the child need not be able to access the * nsd.db file */ namedb_close_udb(nsd->db); +#ifdef MEMCLEAN /* OS collects memory pages */ + region_destroy(region); +#endif if (pledge("stdio rpath inet", NULL) == -1) { log_msg(LOG_ERR, "pledge"); @@ -1079,7 +1082,14 @@ server_shutdown(struct nsd *nsd) daemon_remote_delete(nsd->rc); /* ssl-delete secret keys */ #endif -#if 0 /* OS collects memory pages */ +#ifdef MEMCLEAN /* OS collects memory pages */ +#ifdef RATELIMIT + rrl_mmap_deinit_keep_mmap(); +#endif + udb_base_free_keep_mmap(nsd->task[0]); + udb_base_free_keep_mmap(nsd->task[1]); + namedb_close_udb(nsd->db); /* keeps mmap */ + namedb_close(nsd->db); nsd_options_destroy(nsd->options); region_destroy(nsd->region); #endif @@ -1847,7 +1857,7 @@ server_main(struct nsd *nsd) /* only quit children after xfrd has acked */ send_children_quit(nsd); -#if 0 /* OS collects memory pages */ +#ifdef MEMCLEAN /* OS collects memory pages */ region_destroy(server_region); #endif server_shutdown(nsd); @@ -1926,7 +1936,7 @@ server_main(struct nsd *nsd) (void)kill(nsd->pid, SIGTERM); } -#if 0 /* OS collects memory pages */ +#ifdef MEMCLEAN /* OS collects memory pages */ region_destroy(server_region); #endif /* write the nsd.db to disk, wait for it to complete */ @@ -1996,6 +2006,8 @@ server_child(struct nsd *nsd) log_msg(LOG_ERR, "nsd server could not create event base"); exit(1); } + nsd->event_base = event_base; + nsd->server_region = server_region; #ifdef RATELIMIT rrl_init(nsd->this_child->child_num); @@ -2162,7 +2174,10 @@ server_child(struct nsd *nsd) bind8_stats(nsd); #endif /* BIND8_STATS */ -#if 0 /* OS collects memory pages */ +#ifdef MEMCLEAN /* OS collects memory pages */ +#ifdef RATELIMIT + rrl_deinit(nsd->this_child->child_num); +#endif event_base_free(event_base); region_destroy(server_region); #endif diff --git a/usr.sbin/nsd/xfrd.c b/usr.sbin/nsd/xfrd.c index 3520f5d3b1b..14fec35a28a 100644 --- a/usr.sbin/nsd/xfrd.c +++ b/usr.sbin/nsd/xfrd.c @@ -29,6 +29,7 @@ #include "difffile.h" #include "ipc.h" #include "remote.h" +#include "rrl.h" #define XFRD_UDP_TIMEOUT 10 /* seconds, before a udp request times out */ #define XFRD_NO_IXFR_CACHE 172800 /* 48h before retrying ixfr's after notimpl */ @@ -98,11 +99,15 @@ xfrd_signal_callback(int sig, short event, void* ATTR_UNUSED(arg)) sig_handler(sig); } +static struct event* xfrd_sig_evs[10]; +static int xfrd_sig_num = 0; + static void xfrd_sigsetup(int sig) { - /* no need to remember the event ; dealloc on process exit */ struct event *ev = xalloc_zero(sizeof(*ev)); + assert(xfrd_sig_num <= (int)(sizeof(xfrd_sig_evs)/sizeof(ev))); + xfrd_sig_evs[xfrd_sig_num++] = ev; signal_set(ev, sig, xfrd_signal_callback, NULL); if(event_base_set(xfrd->event_base, ev) != 0) { log_msg(LOG_ERR, "xfrd sig handler: event_base_set failed"); @@ -321,6 +326,7 @@ xfrd_shutdown() DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd shutdown")); event_del(&xfrd->ipc_handler); close(xfrd->ipc_handler.ev_fd); /* notifies parent we stop */ + zone_list_close(nsd.options); if(xfrd->nsd->options->xfrdfile != NULL && xfrd->nsd->options->xfrdfile[0]!=0) xfrd_write_state(xfrd); if(xfrd->reload_added) { @@ -379,9 +385,49 @@ xfrd_shutdown() /* unlink xfr files in not-yet-done task file */ xfrd_clean_pending_tasks(xfrd->nsd, xfrd->nsd->task[xfrd->nsd->mytask]); xfrd_del_tempdir(xfrd->nsd); +#ifdef HAVE_SSL + daemon_remote_delete(xfrd->nsd->rc); /* ssl-delete secret keys */ +#endif /* process-exit cleans up memory used by xfrd process */ DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd shutdown complete")); +#ifdef MEMCLEAN /* OS collects memory pages */ + if(xfrd->zones) { + xfrd_zone_type* z; + RBTREE_FOR(z, xfrd_zone_type*, xfrd->zones) { + tsig_delete_record(&z->tsig, NULL); + } + } + if(xfrd->notify_zones) { + struct notify_zone* n; + RBTREE_FOR(n, struct notify_zone*, xfrd->notify_zones) { + tsig_delete_record(&n->notify_tsig, NULL); + } + } + if(xfrd_sig_num > 0) { + int i; + for(i=0; i<xfrd_sig_num; i++) { + signal_del(xfrd_sig_evs[i]); + free(xfrd_sig_evs[i]); + } + for(i=0; i<(int)nsd.ifs; i++) { + if(nsd.udp[i].s != -1 && nsd.udp[i].addr) + freeaddrinfo(nsd.udp[i].addr); + if(nsd.tcp[i].s != -1 && nsd.tcp[i].addr) + freeaddrinfo(nsd.tcp[i].addr); + } + } +#ifdef RATELIMIT + rrl_mmap_deinit(); +#endif + udb_base_free(nsd.task[0]); + udb_base_free(nsd.task[1]); + event_base_free(xfrd->event_base); + region_destroy(xfrd->region); + nsd_options_destroy(nsd.options); + region_destroy(nsd.region); + log_finalize(); +#endif exit(0); } @@ -521,7 +567,7 @@ xfrd_process_soa_info_task(struct task_list_d* task) memmove(&soa.expire, p, sizeof(uint32_t)); p += sizeof(uint32_t); memmove(&soa.minimum, p, sizeof(uint32_t)); - p += sizeof(uint32_t); + /* p += sizeof(uint32_t); if we wanted to read further */ DEBUG(DEBUG_IPC,1, (LOG_INFO, "SOAINFO for %s %u", dname_to_string(task->zname,0), (unsigned)ntohl(soa.serial))); diff --git a/usr.sbin/nsd/zonec.c b/usr.sbin/nsd/zonec.c index de0a03ca4cd..0938c35a573 100644 --- a/usr.sbin/nsd/zonec.c +++ b/usr.sbin/nsd/zonec.c @@ -1260,6 +1260,8 @@ parse_unknown_rdata(uint16_t type, uint16_t *wireformat) zadd_rdata_wireformat(rdatas[i].data); } } + region_recycle(parser->region, rdatas, + rdata_count*sizeof(rdata_atom_type)); } @@ -1626,6 +1628,7 @@ zonec_read(const char* name, const char* zonefile, zone_type* zone) name, domain_to_string( parser->current_zone->soa_rrset->rrs[0].owner)); } + region_free_all(parser->rr_region); parser_flush(); fclose(yyin); @@ -1667,6 +1670,9 @@ zonec_desetup_parser(void) * region_recycle(parser->region, (void*)error_domain, 1); */ /* clear memory for exit, but this is not portable to * other versions of lex. yylex_destroy(); */ +#ifdef MEMCLEAN /* OS collects memory pages */ + yylex_destroy(); +#endif } } @@ -1719,6 +1725,7 @@ zonec_parse_string(region_type* region, domain_table_type* domains, /* remove origin if it was not used during the parse */ if(parser->origin != error_domain) domain_table_deldomain(parser->db, parser->origin); + region_free_all(parser->rr_region); zonec_desetup_string_parser(); parser_flush(); return errors; diff --git a/usr.sbin/nsd/zparser.y b/usr.sbin/nsd/zparser.y index 542142ea6d5..831ef39c51e 100644 --- a/usr.sbin/nsd/zparser.y +++ b/usr.sbin/nsd/zparser.y @@ -1078,16 +1078,16 @@ rdata_csync: STR sp STR nsec_seq rdata_unknown: URR sp STR sp str_sp_seq trail { /* $2 is the number of octets, currently ignored */ - $$ = zparser_conv_hex(parser->region, $5.str, $5.len); + $$ = zparser_conv_hex(parser->rr_region, $5.str, $5.len); } | URR sp STR trail { - $$ = zparser_conv_hex(parser->region, "", 0); + $$ = zparser_conv_hex(parser->rr_region, "", 0); } | URR error NL { - $$ = zparser_conv_hex(parser->region, "", 0); + $$ = zparser_conv_hex(parser->rr_region, "", 0); } ; %% |