* The daemon consists of global settings and a number of workers.
*/
-/** buffer size for network connections */
-#define BUFSZ 65552
-
#include "config.h"
#include "daemon/daemon.h"
#include "daemon/worker.h"
worker->cmd_send_fd = -1;
close_other_pipes(worker->daemon, worker->thread_num);
#endif
- if(!worker_init(worker, worker->daemon->cfg, worker->daemon->ports,
- BUFSZ, 0))
+ if(!worker_init(worker, worker->daemon->cfg, worker->daemon->ports, 0))
fatal_exit("Could not initialize thread");
worker_work(worker);
/* Special handling for the main thread. This is the thread
* that handles signals.
*/
- if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports,
- BUFSZ, 1))
+ if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports, 1))
fatal_exit("Could not initialize main thread");
signal_handling_playback(daemon->workers[0]);
checkrlimits(struct config_file* cfg)
{
int list = ((cfg->do_ip4?1:0) + (cfg->do_ip6?1:0)) *
- ((cfg->do_udp?1:0) + (cfg->do_tcp?1 + TCP_ACCEPT_COUNT:0));
+ ((cfg->do_udp?1:0) + (cfg->do_tcp?1 +
+ (int)cfg->incoming_num_tcp:0));
size_t ifs = (size_t)(cfg->num_ifs==0?1:cfg->num_ifs);
size_t listen_num = list*ifs;
size_t outnum = cfg->outgoing_num_ports*ifs + cfg->outgoing_num_tcp;
int
worker_init(struct worker* worker, struct config_file *cfg,
- struct listen_port* ports, size_t buffer_size, int do_sigs)
+ struct listen_port* ports, int do_sigs)
{
unsigned int seed;
int startport;
return 0;
}
worker->front = listen_create(worker->base, ports,
- buffer_size, worker_handle_request, worker);
+ cfg->msg_buffer_size, (int)cfg->incoming_num_tcp,
+ worker_handle_request, worker);
if(!worker->front) {
log_err("could not create listening sockets");
worker_delete(worker);
startport = cfg->outgoing_base_port +
cfg->outgoing_num_ports * worker->thread_num;
worker->back = outside_network_create(worker->base,
- buffer_size, (size_t)cfg->outgoing_num_ports, cfg->ifs,
- cfg->num_ifs, cfg->do_ip4, cfg->do_ip6, startport,
+ cfg->msg_buffer_size, (size_t)cfg->outgoing_num_ports,
+ cfg->ifs, cfg->num_ifs, cfg->do_ip4, cfg->do_ip6, startport,
cfg->do_tcp?cfg->outgoing_num_tcp:0,
worker->daemon->env->infra_cache, worker->rndstate);
if(!worker->back) {
if(worker->thread_num != 0) {
/* start listening to commands */
if(!(worker->cmd_com=comm_point_create_local(worker->base,
- worker->cmd_recv_fd, buffer_size,
+ worker->cmd_recv_fd, cfg->msg_buffer_size,
worker_handle_control_cmd, worker))) {
log_err("could not create control compt.");
worker_delete(worker);
return 0;
}
}
+ /* we use the msg_buffer_size as a good estimate for what the
+ * user wants for memory usage sizes */
worker->scratchpad = region_create_custom(malloc, free,
- 65536, 8192, 32, 1);
+ cfg->msg_buffer_size, cfg->msg_buffer_size/4, 32, 1);
if(!worker->scratchpad) {
log_err("malloc failure");
worker_delete(worker);
worker->env.attach_sub = &mesh_attach_sub;
worker->env.kill_sub = &mesh_state_delete;
worker->env.detect_cycle = &mesh_detect_cycle;
- worker->env.scratch_buffer = ldns_buffer_new(65536);
+ worker->env.scratch_buffer = ldns_buffer_new(cfg->msg_buffer_size);
if(!worker->env.mesh || !worker->env.scratch_buffer) {
worker_delete(worker);
return 0;
* @param worker: worker to initialize, created with worker_create.
* @param cfg: configuration settings.
* @param ports: list of shared query ports.
- * @param buffer_size: size of datagram buffer.
* @param do_sigs: if true, worker installs signal handlers.
* @return: false on error.
*/
int worker_init(struct worker* worker, struct config_file *cfg,
- struct listen_port* ports, size_t buffer_size, int do_sigs);
+ struct listen_port* ports, int do_sigs);
/**
* Make worker work.
+30 August 2007: Wouter
+ - fixup override date config option.
+ - config options to control memory usage.
+
29 August 2007: Wouter
- test tool to sign rrsets for testing validator with.
- added RSA and DSA test keys, public and private pairs, 512 bits.
# number of outgoing simultaneous tcp buffers to hold per thread.
# outgoing-num-tcp: 10
+ # number of incoming simultaneous tcp buffers to hold per thread.
+ # incoming-num-tcp: 10
+
+ # buffer size for handling DNS data. No messages larger than this
+ # size can be sent or received, by UDP or TCP. In bytes.
+ # msg-buffer-size: 65552
+
# the amount of memory to use for the message cache.
# in bytes. default is 4 Mb
# msg-cache-size: 4194304
.It \fBoutgoing-num-tcp:\fR <number>
Number of outgoing TCP buffers to allocate per thread. Default is 10. If set
to 0, or if do_tcp is "no", no TCP queries to authoritative servers are done.
+.It \fBincoming-num-tcp:\fR <number>
+Number of incoming TCP buffers to allocate per thread. Default is 10. If set
+to 0, or if do_tcp is "no", no TCP queries from clients are accepted.
+.It \fBmsg-buffer-size:\fR <number>
+Number of bytes size of the message buffers. Default is 65552 bytes, enough
+for 64 Kb packets, the maximum DNS message size. No message larger than this
+can be sent or received. Can be reduced to use less memory, but some requests
+for DNS data, such as for huge resource records, will result in a SERVFAIL
+reply to the client.
.It \fBmsg-cache-size:\fR <number>
Number of bytes size of the message cache. Default is 4 megabytes.
.It \fBmsg-cache-slabs:\fR <number>
To use a nondefault port for DNS communication append '@' with the port number.
.El
+.Sh MEMORY CONTROL EXAMPLE
+In the example config settings below memory usage is reduced. Some service
+levels are lower, notable very large data and a high TCP load are no longer
+supported. Very large data and high TCP loads are exceptional for the DNS.
+DNSSEC validation is enabled, just add trust anchors.
+If you do not have to worry about programs using more than 1 meg of memory,
+the below example is not for you. Use the defaults to receive full service.
+.nf
+
+# example settings that reduce memory usage
+server:
+ num-threads: 1
+ outgoing-num-tcp: 1 # this limits TCP service, uses less buffers.
+ incoming-num-tcp: 1
+ outgoing-range: 1 # uses less memory, but less port randomness.
+ msg-buffer-size: 8192 # note this limits service, 'no huge stuff'.
+ msg-cache-size: 102400 # 100 Kb.
+ msg-cache-slabs: 1
+ rrset-cache-size: 102400 # 100 Kb.
+ rrset-cache-slabs: 1
+ infra-cache-numhosts: 200
+ infra-cache-numlame: 10
+ num-queries-per-thread: 30
+ target-fetch-policy: "2 1 0 0 0 0"
+ harden-large-queries: "yes"
+ harden-short-bufsize: "yes"
+ do-ip6: no # save a bit of memory if not used.
+.fi
+
+.El
+
.Sh FILES
.Bl -tag -width indent
.It Pa /etc/unbound
struct listen_dnsport*
listen_create(struct comm_base* base, struct listen_port* ports,
- size_t bufsize, comm_point_callback_t* cb, void *cb_arg)
+ size_t bufsize, int tcp_accept_count,
+ comm_point_callback_t* cb, void *cb_arg)
{
struct listen_dnsport* front = (struct listen_dnsport*)
malloc(sizeof(struct listen_dnsport));
cp = comm_point_create_udp(base, ports->fd,
front->udp_buff, cb, cb_arg);
else cp = comm_point_create_tcp(base, ports->fd,
- TCP_ACCEPT_COUNT, bufsize, cb, cb_arg);
+ tcp_accept_count, bufsize, cb, cb_arg);
if(!cp) {
log_err("can't create commpoint");
listen_delete(front);
struct listen_port* list = NULL;
struct addrinfo hints;
int i, do_ip4, do_ip6;
+ int do_tcp;
char portbuf[32];
snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
do_ip4 = cfg->do_ip4;
do_ip6 = cfg->do_ip6;
+ do_tcp = cfg->do_tcp;
+ if(cfg->incoming_num_tcp == 0)
+ do_tcp = 0;
/* getaddrinfo */
memset(&hints, 0, sizeof(hints));
if(cfg->num_ifs == 0) {
if(do_ip6) {
hints.ai_family = AF_INET6;
- if(!ports_create_if(NULL, cfg->do_udp, cfg->do_tcp,
+ if(!ports_create_if(NULL, cfg->do_udp, do_tcp,
&hints, portbuf, &list)) {
listening_ports_free(list);
return NULL;
}
if(do_ip4) {
hints.ai_family = AF_INET;
- if(!ports_create_if(NULL, cfg->do_udp, cfg->do_tcp,
+ if(!ports_create_if(NULL, cfg->do_udp, do_tcp,
&hints, portbuf, &list)) {
listening_ports_free(list);
return NULL;
continue;
hints.ai_family = AF_INET6;
if(!ports_create_if(cfg->ifs[i], cfg->do_udp,
- cfg->do_tcp, &hints, portbuf, &list)) {
+ do_tcp, &hints, portbuf, &list)) {
listening_ports_free(list);
return NULL;
}
continue;
hints.ai_family = AF_INET;
if(!ports_create_if(cfg->ifs[i], cfg->do_udp,
- cfg->do_tcp, &hints, portbuf, &list)) {
+ do_tcp, &hints, portbuf, &list)) {
listening_ports_free(list);
return NULL;
}
struct addrinfo;
struct config_file;
-/** number of simultaneous open TCP connections for queries */
-#define TCP_ACCEPT_COUNT 10
-
/**
* Listening for queries structure.
* Contains list of query-listen sockets.
* for default all ifs.
* @param ports: the list of shared ports.
* @param bufsize: size of datagram buffer.
+ * @param tcp_accept_count: max number of simultaneous TCP connections
+ * from clients.
* @param cb: callback function when a request arrives. It is passed
* the packet and user argument. Return true to send a reply.
* @param cb_arg: user data argument for callback function.
* @return: the malloced listening structure, ready for use. NULL on error.
*/
struct listen_dnsport* listen_create(struct comm_base* base,
- struct listen_port* ports, size_t bufsize,
+ struct listen_port* ports, size_t bufsize, int tcp_accept_count,
comm_point_callback_t* cb, void* cb_arg);
/**
struct listen_dnsport*
listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
- size_t bufsize, comm_point_callback_t* cb, void* cb_arg)
+ size_t bufsize, int ATTR_UNUSED(tcp_accept_count),
+ comm_point_callback_t* cb, void* cb_arg)
{
struct replay_runtime* runtime = (struct replay_runtime*)base;
struct listen_dnsport* l= calloc(1, sizeof(struct listen_dnsport));
cfg->outgoing_base_port = cfg->port + 2000;
cfg->outgoing_num_ports = 16;
cfg->outgoing_num_tcp = 10;
+ cfg->incoming_num_tcp = 10;
+ cfg->msg_buffer_size = 65552; /* 64 k + a small margin */
cfg->msg_cache_size = 4 * 1024 * 1024;
cfg->msg_cache_slabs = 4;
cfg->num_queries_per_thread = 1024;
int outgoing_num_ports;
/** number of outgoing tcp buffers per (per thread) */
size_t outgoing_num_tcp;
+ /** number of incoming tcp buffers per (per thread) */
+ size_t incoming_num_tcp;
+ /** number of bytes buffer size for DNS messages */
+ size_t msg_buffer_size;
/** size of the message cache */
size_t msg_cache_size;
/** slabs in the message cache. */
outgoing-port{COLON} { YDOUT; return VAR_OUTGOING_PORT;}
outgoing-range{COLON} { YDOUT; return VAR_OUTGOING_RANGE;}
outgoing-num-tcp{COLON} { YDOUT; return VAR_OUTGOING_NUM_TCP;}
+incoming-num-tcp{COLON} { YDOUT; return VAR_INCOMING_NUM_TCP;}
do-ip4{COLON} { YDOUT; return VAR_DO_IP4;}
do-ip6{COLON} { YDOUT; return VAR_DO_IP6;}
do-udp{COLON} { YDOUT; return VAR_DO_UDP;}
directory{COLON} { YDOUT; return VAR_DIRECTORY;}
logfile{COLON} { YDOUT; return VAR_LOGFILE;}
pidfile{COLON} { YDOUT; return VAR_PIDFILE;}
+msg-buffer-size{COLON} { YDOUT; return VAR_MSG_BUFFER_SIZE;}
msg-cache-size{COLON} { YDOUT; return VAR_MSG_CACHE_SIZE;}
msg-cache-slabs{COLON} { YDOUT; return VAR_MSG_CACHE_SLABS;}
rrset-cache-size{COLON} { YDOUT; return VAR_RRSET_CACHE_SIZE;}
%token VAR_IDENTITY VAR_VERSION VAR_HARDEN_GLUE VAR_MODULE_CONF
%token VAR_TRUST_ANCHOR_FILE VAR_TRUST_ANCHOR VAR_VAL_OVERRIDE_DATE
%token VAR_BOGUS_TTL VAR_VAL_CLEAN_ADDITIONAL VAR_VAL_PERMISSIVE_MODE
+%token VAR_INCOMING_NUM_TCP VAR_MSG_BUFFER_SIZE
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
server_hide_version | server_identity | server_version |
server_harden_glue | server_module_conf | server_trust_anchor_file |
server_trust_anchor | server_val_override_date | server_bogus_ttl |
- server_val_clean_additional | server_val_permissive_mode
+ server_val_clean_additional | server_val_permissive_mode |
+ server_incoming_num_tcp | server_msg_buffer_size
;
stubstart: VAR_STUB_ZONE
{
free($2);
}
;
+server_incoming_num_tcp: VAR_INCOMING_NUM_TCP STRING
+ {
+ OUTYY(("P(server_incoming_num_tcp:%s)\n", $2));
+ if(atoi($2) == 0 && strcmp($2, "0") != 0)
+ yyerror("number expected");
+ else cfg_parser->cfg->incoming_num_tcp = atoi($2);
+ free($2);
+ }
+ ;
server_do_ip4: VAR_DO_IP4 STRING
{
OUTYY(("P(server_do_ip4:%s)\n", $2));
cfg_parser->cfg->version = $2;
}
;
+server_msg_buffer_size: VAR_MSG_BUFFER_SIZE STRING
+ {
+ OUTYY(("P(server_msg_buffer_size:%s)\n", $2));
+ if(atoi($2) == 0)
+ yyerror("number expected");
+ else if (atoi($2) < 4096)
+ yyerror("message buffer size too small (use 4096)");
+ else cfg_parser->cfg->msg_buffer_size = atoi($2);
+ free($2);
+ }
+ ;
server_msg_cache_size: VAR_MSG_CACHE_SIZE STRING
{
OUTYY(("P(server_msg_cache_size:%s)\n", $2));
} else {
if(atoi($2) == 0)
yyerror("number expected");
- cfg_parser->cfg->outgoing_num_ports = atoi($2);
+ cfg_parser->cfg->val_date_override = atoi($2);
}
free($2);
}