diff options
Diffstat (limited to 'bin/named/server.c')
| -rw-r--r-- | bin/named/server.c | 252 |
1 files changed, 224 insertions, 28 deletions
diff --git a/bin/named/server.c b/bin/named/server.c index aef922bb..f2850475 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -1639,6 +1639,170 @@ configure_rpz(dns_view_t *view, const cfg_listelt_t *element, return (ISC_R_SUCCESS); } +#ifdef USE_RRL +#define CHECK_RRL(cond, pat, val1, val2) \ + do { \ + if (!(cond)) { \ + cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, \ + pat, val1, val2); \ + result = ISC_R_RANGE; \ + goto cleanup; \ + } \ + } while (0) + +#define CHECK_RRL_RATE(rate, def, max_rate, name) \ + do { \ + obj = NULL; \ + rrl->rate.str = name; \ + result = cfg_map_get(map, name, &obj); \ + if (result == ISC_R_SUCCESS) { \ + rrl->rate.r = cfg_obj_asuint32(obj); \ + CHECK_RRL(rrl->rate.r <= max_rate, \ + name" %d > %d", \ + rrl->rate.r, max_rate); \ + } else { \ + rrl->rate.r = def; \ + } \ + rrl->rate.scaled = rrl->rate.r; \ + } while (0) + +static isc_result_t +configure_rrl(dns_view_t *view, const cfg_obj_t *config, const cfg_obj_t *map) { + const cfg_obj_t *obj; + dns_rrl_t *rrl; + isc_result_t result; + int min_entries, i, j; + + /* + * Most DNS servers have few clients, but intentinally open + * recursive and authoritative servers often have many. + * So start with a small number of entries unless told otherwise + * to reduce cold-start costs. + */ + min_entries = 500; + obj = NULL; + result = cfg_map_get(map, "min-table-size", &obj); + if (result == ISC_R_SUCCESS) { + min_entries = cfg_obj_asuint32(obj); + if (min_entries < 1) + min_entries = 1; + } + result = dns_rrl_init(&rrl, view, min_entries); + if (result != ISC_R_SUCCESS) + return (result); + + i = ISC_MAX(20000, min_entries); + obj = NULL; + result = cfg_map_get(map, "max-table-size", &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + CHECK_RRL(i >= min_entries, + "max-table-size %d < min-table-size %d", + i, min_entries); + } + rrl->max_entries = i; + + CHECK_RRL_RATE(responses_per_second, 0, DNS_RRL_MAX_RATE, + "responses-per-second"); + CHECK_RRL_RATE(referrals_per_second, + rrl->responses_per_second.r, DNS_RRL_MAX_RATE, + "referrals-per-second"); + CHECK_RRL_RATE(nodata_per_second, + rrl->responses_per_second.r, DNS_RRL_MAX_RATE, + "nodata-per-second"); + CHECK_RRL_RATE(nxdomains_per_second, + rrl->responses_per_second.r, DNS_RRL_MAX_RATE, + "nxdomains-per-second"); + CHECK_RRL_RATE(errors_per_second, + rrl->responses_per_second.r, DNS_RRL_MAX_RATE, + "errors-per-second"); + + CHECK_RRL_RATE(all_per_second, 0, DNS_RRL_MAX_RATE, + "all-per-second"); + + CHECK_RRL_RATE(slip, 2, DNS_RRL_MAX_SLIP, + "slip"); + + i = 15; + obj = NULL; + result = cfg_map_get(map, "window", &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + CHECK_RRL(i >= 1 && i <= DNS_RRL_MAX_WINDOW, + "window %d < 1 or > %d", i, DNS_RRL_MAX_WINDOW); + } + rrl->window = i; + + i = 0; + obj = NULL; + result = cfg_map_get(map, "qps-scale", &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + CHECK_RRL(i >= 1, "invalid 'qps-scale %d'%s", i, ""); + } + rrl->qps_scale = i; + rrl->qps = 1.0; + + i = 24; + obj = NULL; + result = cfg_map_get(map, "ipv4-prefix-length", &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + CHECK_RRL(i >= 8 && i <= 32, + "invalid 'ipv4-prefix-length %d'%s", i, ""); + } + rrl->ipv4_prefixlen = i; + if (i == 32) + rrl->ipv4_mask = 0xffffffff; + else + rrl->ipv4_mask = htonl(0xffffffff << (32-i)); + + i = 56; + obj = NULL; + result = cfg_map_get(map, "ipv6-prefix-length", &obj); + if (result == ISC_R_SUCCESS) { + i = cfg_obj_asuint32(obj); + CHECK_RRL(i >= 16 && i <= DNS_RRL_MAX_PREFIX, + "ipv6-prefix-length %d < 16 or > %d", + i, DNS_RRL_MAX_PREFIX); + } + rrl->ipv6_prefixlen = i; + for (j = 0; j < 4; ++j) { + if (i <= 0) { + rrl->ipv6_mask[j] = 0; + } else if (i < 32) { + rrl->ipv6_mask[j] = htonl(0xffffffff << (32-i)); + } else { + rrl->ipv6_mask[j] = 0xffffffff; + } + i -= 32; + } + + obj = NULL; + result = cfg_map_get(map, "exempt-clients", &obj); + if (result == ISC_R_SUCCESS) { + result = cfg_acl_fromconfig(obj, config, ns_g_lctx, + ns_g_aclconfctx, ns_g_mctx, + 0, &rrl->exempt); + CHECK_RRL(result == ISC_R_SUCCESS, + "invalid %s%s", "address match list", ""); + } + + obj = NULL; + result = cfg_map_get(map, "log-only", &obj); + if (result == ISC_R_SUCCESS && cfg_obj_asboolean(obj)) + rrl->log_only = ISC_TRUE; + else + rrl->log_only = ISC_FALSE; + + return (ISC_R_SUCCESS); + + cleanup: + dns_rrl_view_destroy(view); + return (result); +} +#endif /* USE_RRL */ + /* * Configure 'view' according to 'vconfig', taking defaults from 'config' * where values are missing in 'vconfig'. @@ -3043,6 +3207,16 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, } } +#ifdef USE_RRL + obj = NULL; + result = ns_config_get(maps, "rate-limit", &obj); + if (result == ISC_R_SUCCESS) { + result = configure_rrl(view, config, obj); + if (result != ISC_R_SUCCESS) + goto cleanup; + } +#endif /* USE_RRL */ + result = ISC_R_SUCCESS; cleanup: @@ -4516,7 +4690,10 @@ load_configuration(const char *filename, ns_server_t *server, dns_viewlist_t viewlist, builtin_viewlist; in_port_t listen_port, udpport_low, udpport_high; int i; + int num_zones = 0; + isc_boolean_t exclusive = ISC_FALSE; isc_interval_t interval; + isc_logconfig_t *logc = NULL; isc_portset_t *v4portset = NULL; isc_portset_t *v6portset = NULL; isc_resourcevalue_t nfiles; @@ -4525,12 +4702,10 @@ load_configuration(const char *filename, ns_server_t *server, isc_uint32_t interface_interval; isc_uint32_t reserved; isc_uint32_t udpsize; - ns_cachelist_t cachelist, tmpcachelist; - unsigned int maxsocks; ns_cache_t *nsc; + ns_cachelist_t cachelist, tmpcachelist; struct cfg_context *nzctx; - int num_zones = 0; - isc_boolean_t exclusive = ISC_FALSE; + unsigned int maxsocks; ISC_LIST_INIT(viewlist); ISC_LIST_INIT(builtin_viewlist); @@ -4818,8 +4993,8 @@ load_configuration(const char *filename, ns_server_t *server, result = ns_config_get(maps, "tcp-listen-queue", &obj); INSIST(result == ISC_R_SUCCESS); ns_g_listen = cfg_obj_asuint32(obj); - if (ns_g_listen < 3) - ns_g_listen = 3; + if ((ns_g_listen > 0) && (ns_g_listen < 10)) + ns_g_listen = 10; /* * Configure the interface manager according to the "listen-on" @@ -5191,13 +5366,30 @@ load_configuration(const char *filename, ns_server_t *server, * unprivileged user, not root. */ if (ns_g_logstderr) { + const cfg_obj_t *logobj = NULL; + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, - "ignoring config file logging " - "statement due to -g option"); + "not using config file logging " + "statement for logging due to " + "-g option"); + + (void)cfg_map_get(config, "logging", &logobj); + if (logobj != NULL) { + result = ns_log_configure(NULL, logobj); + if (result != ISC_R_SUCCESS) { + isc_log_write(ns_g_lctx, + NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, + ISC_LOG_ERROR, + "checking logging configuration " + "failed: %s", + isc_result_totext(result)); + goto cleanup; + } + } } else { const cfg_obj_t *logobj = NULL; - isc_logconfig_t *logc = NULL; CHECKM(isc_logconfig_create(ns_g_lctx, &logc), "creating new logging configuration"); @@ -5216,11 +5408,9 @@ load_configuration(const char *filename, ns_server_t *server, "setting up default 'category default'"); } - result = isc_logconfig_use(ns_g_lctx, logc); - if (result != ISC_R_SUCCESS) { - isc_logconfig_destroy(&logc); - CHECKM(result, "installing logging configuration"); - } + CHECKM(isc_logconfig_use(ns_g_lctx, logc), + "installing logging configuration"); + logc = NULL; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1), @@ -5352,6 +5542,9 @@ load_configuration(const char *filename, ns_server_t *server, result = ISC_R_SUCCESS; cleanup: + if (logc != NULL) + isc_logconfig_destroy(&logc); + if (v4portset != NULL) isc_portset_destroy(ns_g_mctx, &v4portset); @@ -7750,11 +7943,13 @@ ns_server_add_zone(ns_server_t *server, char *args) { const char *viewname = NULL; dns_rdataclass_t rdclass; dns_view_t *view = 0; - isc_buffer_t buf, *nbuf = NULL; - dns_name_t dnsname; + isc_buffer_t buf; + dns_fixedname_t fname; + dns_name_t *dnsname; dns_zone_t *zone = NULL; FILE *fp = NULL; struct cfg_context *cfg = NULL; + char namebuf[DNS_NAME_FORMATSIZE]; /* Try to parse the argument string */ arglen = strlen(args); @@ -7768,10 +7963,10 @@ ns_server_add_zone(ns_server_t *server, char *args) { zonename = cfg_obj_asstring(cfg_tuple_get(parms, "name")); isc_buffer_constinit(&buf, zonename, strlen(zonename)); isc_buffer_add(&buf, strlen(zonename)); - dns_name_init(&dnsname, NULL); - isc_buffer_allocate(server->mctx, &nbuf, 256); - dns_name_setbuffer(&dnsname, nbuf); - CHECK(dns_name_fromtext(&dnsname, &buf, dns_rootname, ISC_FALSE, NULL)); + + dns_fixedname_init(&fname); + dnsname = dns_fixedname_name(&fname); + CHECK(dns_name_fromtext(dnsname, &buf, dns_rootname, ISC_FALSE, NULL)); /* Make sense of optional class argument */ obj = cfg_tuple_get(parms, "class"); @@ -7800,7 +7995,7 @@ ns_server_add_zone(ns_server_t *server, char *args) { } /* Zone shouldn't already exist */ - result = dns_zt_find(view->zonetable, &dnsname, 0, NULL, &zone); + result = dns_zt_find(view->zonetable, dnsname, 0, NULL, &zone); if (result == ISC_R_SUCCESS) { result = ISC_R_EXISTS; goto cleanup; @@ -7841,7 +8036,7 @@ ns_server_add_zone(ns_server_t *server, char *args) { goto cleanup; /* Is it there yet? */ - CHECK(dns_zt_find(view->zonetable, &dnsname, 0, NULL, &zone)); + CHECK(dns_zt_find(view->zonetable, dnsname, 0, NULL, &zone)); /* * Load the zone from the master file. If this fails, we'll @@ -7869,10 +8064,13 @@ ns_server_add_zone(ns_server_t *server, char *args) { /* Flag the zone as having been added at runtime */ dns_zone_setadded(zone, ISC_TRUE); - /* Emit just the zone name from args */ - CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); - CHECK(isc_stdio_write(zonename, strlen(zonename), 1, fp, NULL)); - CHECK(isc_stdio_write(" ", 1, 1, fp, NULL)); + /* Emit the zone name, quoted and escaped */ + isc_buffer_init(&buf, namebuf, sizeof(namebuf)); + CHECK(dns_name_totext(dnsname, ISC_TRUE, &buf)); + isc_buffer_putuint8(&buf, 0); + CHECK(isc_stdio_write("zone \"", 6, 1, fp, NULL)); + CHECK(isc_stdio_write(namebuf, strlen(namebuf), 1, fp, NULL)); + CHECK(isc_stdio_write("\" ", 2, 1, fp, NULL)); /* Classname, if not default */ if (classname != NULL && *classname != '\0') { @@ -7916,8 +8114,6 @@ ns_server_add_zone(ns_server_t *server, char *args) { dns_zone_detach(&zone); if (view != NULL) dns_view_detach(&view); - if (nbuf != NULL) - isc_buffer_free(&nbuf); return (result); } |
