Compare commits

...
5 Commits
Author SHA1 Message Date
Wouter Wijngaards 82e4110e09 moved from trunk.
git-svn-id: file:///svn/unbound/tags/release-0.9@947 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-11 15:46:40 +00:00
Wouter Wijngaards fb57492c0a makedist fixup.
git-svn-id: file:///svn/unbound/tags/release-0.9@940 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-08 13:09:25 +00:00
Wouter Wijngaards bde1ce87d5 doc_layout
git-svn-id: file:///svn/unbound/tags/release-0.9@939 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-08 12:59:36 +00:00
Wouter Wijngaards b7a627b8cc Tests fixup.
git-svn-id: file:///svn/unbound/tags/release-0.9@938 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-08 12:46:21 +00:00
Wouter Wijngaards ea7630845f tag 0.9
git-svn-id: file:///svn/unbound/tags/release-0.9@937 be551aaa-1e26-0410-a405-d3ace91eadb9
2008-02-08 12:27:41 +00:00
27 changed files with 736 additions and 320 deletions
+4 -2
View File
@@ -59,10 +59,12 @@ void server_stats_querymiss(struct server_stats* stats, struct worker* worker)
void server_stats_log(struct server_stats* stats, int threadnum)
{
log_info("server stats for thread %d: %u queries, %u from cache",
log_info("server stats for thread %d: %u queries, "
"%u answers from cache, %u recursions",
threadnum, (unsigned)stats->num_queries,
(unsigned)(stats->num_queries -
stats->num_queries_missed_cache));
stats->num_queries_missed_cache),
(unsigned)stats->num_queries_missed_cache);
log_info("server stats for thread %d: requestlist max %u avg %g "
"exceeded %u", threadnum, (unsigned)stats->max_query_list_size,
stats->num_queries_missed_cache?
+2 -2
View File
@@ -874,8 +874,8 @@ worker_restart_timer(struct worker* worker)
void worker_stat_timer_cb(void* arg)
{
struct worker* worker = (struct worker*)arg;
mesh_stats(worker->env.mesh, "mesh has");
server_stats_log(&worker->stats, worker->thread_num);
mesh_stats(worker->env.mesh, "mesh has");
worker_mem_report(worker, NULL);
server_stats_init(&worker->stats);
mesh_stats_clear(worker->env.mesh);
@@ -1046,8 +1046,8 @@ worker_delete(struct worker* worker)
if(!worker)
return;
if(worker->env.mesh && verbosity >= VERB_OPS) {
mesh_stats(worker->env.mesh, "mesh has");
server_stats_log(&worker->stats, worker->thread_num);
mesh_stats(worker->env.mesh, "mesh has");
worker_mem_report(worker, NULL);
}
mesh_delete(worker->env.mesh);
+8
View File
@@ -1,7 +1,15 @@
11 February 2008: Wouter
- nicer statistic output (from trunk).
- ub_val to ub_ for library API (from trunk).
- (from trunk) set_option, set_debugout, etc/hosts handling.
8 February 2008: Wouter
- test program for multiple queries over a TCP channel.
- tpkg test for stream tcp queries.
- unbound replies to multiple TCP queries on a TCP channel.
- fixup misclassification of root referral with NS in answer
when validating a nonrec query.
- tag 0.9
7 February 2008: Wouter
- moved up all current level 2 to be level 3. And 3 to 4.
+117 -85
View File
@@ -11,101 +11,109 @@
.LP
.B libunbound,
.B unbound.h,
.B ub_val_ctx,
.B ub_val_result,
.B ub_val_callback_t,
.B ub_val_ctx_create,
.B ub_val_ctx_delete,
.B ub_val_ctx_config,
.B ub_val_ctx_set_fwd,
.B ub_val_ctx_resolvconf,
.B ub_val_ctx_add_ta,
.B ub_val_ctx_add_ta_file,
.B ub_val_ctx_trustedkeys,
.B ub_val_ctx_debuglevel,
.B ub_val_ctx_async,
.B ub_val_poll,
.B ub_val_wait,
.B ub_val_fd,
.B ub_val_process,
.B ub_val_resolve,
.B ub_val_resolve_async,
.B ub_val_cancel,
.B ub_val_resolve_free,
.B ub_val_strerror
.B ub_ctx,
.B ub_result,
.B ub_callback_t,
.B ub_ctx_create,
.B ub_ctx_delete,
.B ub_ctx_set_option,
.B ub_ctx_config,
.B ub_ctx_set_fwd,
.B ub_ctx_resolvconf,
.B ub_ctx_hosts,
.B ub_ctx_add_ta,
.B ub_ctx_add_ta_file,
.B ub_ctx_trustedkeys,
.B ub_ctx_debugout,
.B ub_ctx_debuglevel,
.B ub_ctx_async,
.B ub_poll,
.B ub_wait,
.B ub_fd,
.B ub_process,
.B ub_resolve,
.B ub_resolve_async,
.B ub_cancel,
.B ub_resolve_free,
.B ub_strerror
\- Unbound DNS validating resolver @version@ functions.
.SH "SYNOPSIS"
.LP
.B #include <unbound.h>
.LP
\fIstruct ub_val_ctx *\fR
\fBub_val_ctx_create\fR(\fIvoid\fR);
\fIstruct ub_ctx *\fR
\fBub_ctx_create\fR(\fIvoid\fR);
.LP
\fIvoid\fR
\fBub_val_ctx_delete\fR(\fIstruct ub_val_ctx*\fR ctx);
\fBub_ctx_delete\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_val_ctx_config\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR fname);
\fBub_ctx_set_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar*\fR val);
.LP
\fIint\fR
\fBub_val_ctx_set_fwd\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR addr);
\fBub_ctx_config\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_val_ctx_resolvconf\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR fname);
\fBub_ctx_set_fwd\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR addr);
.LP
\fIint\fR
\fBub_val_ctx_add_ta\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR ta);
\fBub_ctx_resolvconf\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_val_ctx_add_ta_file\fR(\fIstruct ub_val_ctx*\fR ctx,
.br
\fIchar*\fR fname);
\fBub_ctx_hosts\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_val_ctx_trustedkeys\fR(\fIstruct ub_val_ctx*\fR ctx,
.br
\fIchar*\fR fname);
\fBub_ctx_add_ta\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR ta);
.LP
\fIint\fR
\fBub_val_ctx_debuglevel\fR(\fIstruct ub_val_ctx*\fR ctx, \fIint\fR d);
\fBub_ctx_add_ta_file\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_val_ctx_async\fR(\fIstruct ub_val_ctx*\fR ctx, \fIint\fR dothread);
\fBub_ctx_trustedkeys\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
.LP
\fIint\fR
\fBub_val_poll\fR(\fIstruct ub_val_ctx*\fR ctx);
\fBub_ctx_debugout\fR(\fIstruct ub_ctx*\fR ctx, \fIFILE*\fR out);
.LP
\fIint\fR
\fBub_val_wait\fR(\fIstruct ub_val_ctx*\fR ctx);
\fBub_ctx_debuglevel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR d);
.LP
\fIint\fR
\fBub_val_fd\fR(\fIstruct ub_val_ctx*\fR ctx);
\fBub_ctx_async\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR dothread);
.LP
\fIint\fR
\fBub_val_process\fR(\fIstruct ub_val_ctx*\fR ctx);
\fBub_poll\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_val_resolve\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR name,
\fBub_wait\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_fd\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_process\fR(\fIstruct ub_ctx*\fR ctx);
.LP
\fIint\fR
\fBub_resolve\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name,
.br
\fIint\fR rrtype, \fIint\fR rrclass, \fIint*\fR secure,
.br
\fIint*\fR data, \fIstruct ub_val_result**\fR result);
\fIint*\fR data, \fIstruct ub_result**\fR result);
.LP
\fIint\fR
\fBub_val_resolve_async\fR(\fIstruct ub_val_ctx*\fR ctx, \fIchar*\fR name,
\fBub_resolve_async\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name,
.br
\fIint\fR rrtype, \fIint\fR rrclass, \fIvoid*\fR mydata,
.br
\fIub_val_callback_t\fR callback, \fIint*\fR async_id);
\fIub_callback_t\fR callback, \fIint*\fR async_id);
.LP
\fIint\fR
\fBub_val_cancel\fR(\fIstruct ub_val_ctx*\fR ctx, \fIint\fR async_id);
\fBub_cancel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR async_id);
.LP
\fIvoid\fR
\fBub_val_resolve_free\fR(\fIstruct ub_val_result*\fR result);
\fBub_resolve_free\fR(\fIstruct ub_result*\fR result);
.LP
\fIconst char *\fR
\fBub_val_strerror\fR(\fIint\fR err);
\fBub_strerror\fR(\fIint\fR err);
.SH "DESCRIPTION"
.LP
.B Unbound
@@ -116,11 +124,11 @@ The library can be used to convert hostnames to ip addresses, and back,
and obtain other information from the DNS. The library performs public\-key
validation of results with DNSSEC.
.P
The library uses a variable of type \fIstruct ub_val_ctx\fR to keep context
The library uses a variable of type \fIstruct ub_ctx\fR to keep context
between calls. The user must maintain it, creating it with
.B ub_val_ctx_create
.B ub_ctx_create
and deleting it with
.B ub_val_ctx_delete\fR.
.B ub_ctx_delete\fR.
It can be created and deleted at any time. Creating it anew removes any
previous configuration (such as trusted keys) and clears any cached results.
.P
@@ -133,20 +141,32 @@ can go on, while the results become available later.
The functions are discussed in turn below.
.SH "FUNCTIONS"
.TP
.B ub_val_ctx_create
.B ub_ctx_create
Create a new context, initialised with defaults.
The information from /etc/resolv.conf and /etc/hosts is not utilised
by default. Use
.B ub_ctx_resolvconf
and
.B ub_ctx_hosts
to read them.
.TP
.B ub_val_ctx_delete
.B ub_ctx_delete
Delete validation context and free associated resources.
Outstanding async queries are killed and callbacks are not called for them.
.TP
.B ub_val_ctx_config
.B ub_ctx_set_option
A power\-user interface that lets you specify one of the options from the
config file format, see \fIunbound.conf\fR(5). Not all options are
relevant. For some specific options, such as adding trust anchors, special
routines exist. Pass the option name with the trailing ':'.
.TP
.B ub_ctx_config
A power\-user interface that lets you specify an unbound config file, see
\fIunbound.conf\fR(5), which is read for configuration. Not all options are
relevant. For some specific options, such as adding trust anchors, special
routines exist.
.TP
.B ub_val_ctx_set_fwd
.B ub_ctx_set_fwd
Set machine to forward DNS queries to, the caching resolver to use.
IP4 or IP6 address. Forwards all DNS requests to that machine, which
is expected to run a recursive resolver. If the proxy is not
@@ -155,7 +175,7 @@ that case the addresses are used as backup servers.
At this time it is only possible to set configuration before the
first resolve is done.
.TP
.B ub_val_ctx_resolvconf
.B ub_ctx_resolvconf
Read list of nameservers to use from the filename given.
Usually "/etc/resolv.conf". Uses those nameservers as caching proxies.
If they do not support DNSSEC, validation may fail.
@@ -165,67 +185,79 @@ If fname NULL is passed, "/etc/resolv.conf" is used.
At this time it is only possible to set configuration before the
first resolve is done.
.TP
.B ub_ctx_hosts
Read list of hosts from the filename given.
Usually "/etc/hosts". When queried for, these addresses are not marked
DNSSEC secure. If fname NULL is passed, "/etc/hosts" is used.
At this time it is only possible to set configuration before the
first resolve is done.
.TP
.B
ub_val_ctx_add_ta
ub_ctx_add_ta
Add a trust anchor to the given context.
At this time it is only possible to add trusted keys before the
first resolve is done.
The format is a string, similar to the zone-file format,
[domainname] [type] [rdata contents]. Both DS and DNSKEY records are accepted.
.TP
.B ub_val_ctx_add_ta_file
.B ub_ctx_add_ta_file
Add trust anchors to the given context.
Pass name of a file with DS and DNSKEY records in zone file format.
At this time it is only possible to add trusted keys before the
first resolve is done.
.TP
.B ub_val_ctx_trustedkeys
.B ub_ctx_trustedkeys
Add trust anchors to the given context.
Pass the name of a bind-style config file with trusted-keys{}.
At this time it is only possible to add trusted keys before the
first resolve is done.
.TP
.B ub_val_ctx_debuglevel
.B ub_ctx_debugout
Set debug and error log output to the given stream. Pass NULL to disable
output. Default is stderr. File-names or using syslog can be enabled
using config options, this routine is for using your own stream.
.TP
.B ub_ctx_debuglevel
Set debug verbosity for the context. Output is directed to stderr.
Higher debug level gives more output.
.TP
.B ub_val_ctx_async
.B ub_ctx_async
Set a context behaviour for asynchronous action.
if set to true, enables threading and a call to
.B ub_val_resolve_async
.B ub_resolve_async
creates a thread to handle work in the background.
If false, a process is forked to handle work in the background.
Changes to this setting after
.B ub_val_resolve_async
.B ub_resolve_async
calls have been made have no effect (delete and re\-create the context
to change).
.TP
.B ub_val_poll
.B ub_poll
Poll a context to see if it has any new results.
Do not poll in a loop, instead extract the fd below to poll for readiness,
and then check, or wait using the wait routine.
Returns 0 if nothing to read, or nonzero if a result is available.
If nonzero, call
.B ub_val_process
.B ub_process
to do callbacks.
.TP
.B ub_val_wait
.B ub_wait
Wait for a context to finish with results. Calls
.B ub_val_process
.B ub_process
after the wait for you. After the wait, there are no more outstanding
asynchronous queries.
.TP
.B ub_val_fd
.B ub_fd
Get file descriptor. Wait for it to become readable, at this point
answers are returned from the asynchronous validating resolver.
Then call the \fBub_val_process\fR to continue processing.
Then call the \fBub_process\fR to continue processing.
.TP
.B ub_val_process
.B ub_process
Call this routine to continue processing results from the validating
resolver (when the fd becomes readable).
Will perform necessary callbacks.
.TP
.B ub_val_resolve
.B ub_resolve
Perform resolution and validation of the target name.
The name is a domain name in a zero terminated text string.
The rrtype and rrclass are DNS type and class codes.
@@ -233,9 +265,9 @@ The value secure returns true if the answer validated securely.
The value data returns true if there was data.
The result structure is newly allocated with the resulting data.
.TP
.B ub_val_resolve_async
.B ub_resolve_async
Perform asynchronous resolution and validation of the target name.
Arguments mean the same as for \fBub_val_resolve\fR except no
Arguments mean the same as for \fBub_resolve\fR except no
data is returned immediately, instead a callback is called later.
The callback receives a copy of the mydata pointer, that you can use to pass
information to the callback. The callback type is a function pointer to
@@ -243,27 +275,27 @@ a function declared as
.IP
void my_callback_function(void* my_arg, int err,
.br
struct ub_val_result* result);
struct ub_result* result);
.IP
The async_id is returned so you can (at your option) decide to track it
and cancel the request if needed.
.TP
.B ub_val_cancel
.B ub_cancel
Cancel an async query in progress.
.TP
.B ub_val_resolve_free
Free struct ub_val_result contents after use.
.B ub_resolve_free
Free struct ub_result contents after use.
.TP
.B ub_val_strerror
.B ub_strerror
Convert error value from one of the unbound library functions
to a human readable string.
.SH "RESULT DATA STRUCTURE"
.LP
The result of the DNS resolution and validation is returned as
\fIstruct ub_val_result\fR. The result structure contains the following entries.
\fIstruct ub_result\fR. The result structure contains the following entries.
.P
.nf
struct ub_val_result {
struct ub_result {
char* qname; /* text string, original question */
int qtype; /* type code asked for */
int qclass; /* class code asked for */
@@ -283,15 +315,15 @@ domain of the query.
.SH "RETURN VALUES"
Many routines return an error code. The value 0 (zero) denotes no error
happened. Other values can be passed to
.B ub_val_strerror
.B ub_strerror
to obtain a readable error string.
.B ub_val_strerror
.B ub_strerror
returns a zero terminated string.
.B ub_val_ctx_create
.B ub_ctx_create
returns NULL on an error (a malloc failure).
.B ub_val_poll
.B ub_poll
returns true if some information may be available, false otherwise.
.B ub_val_fd
.B ub_fd
returns a file descriptor or -1 on error.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
+19 -8
View File
@@ -467,7 +467,8 @@ for completeness and to satisfy some DNS update tools. Default content:
.nf
local\-zone: "localhost." static
local\-data: "localhost. 10800 IN NS localhost."
local\-data: "localhost. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
local\-data: "localhost. 10800 IN
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
local\-data: "localhost. 10800 IN A 127.0.0.1"
local\-data: "localhost. 10800 IN AAAA ::1"
.fi
@@ -477,17 +478,26 @@ Default content:
.nf
local\-zone: "127.in\-addr.arpa." static
local\-data: "127.in\-addr.arpa. 10800 IN NS localhost."
local\-data: "127.in\-addr.arpa. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
local\-data: "1.0.0.127.in\-addr.arpa. 10800 IN PTR localhost."
local\-data: "127.in\-addr.arpa. 10800 IN
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
local\-data: "1.0.0.127.in\-addr.arpa. 10800 IN
PTR localhost."
.fi
.TP 10
\h'5'\fIreverse IPv6 loopback\fR
Default content:
.nf
local\-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." static
local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN NS localhost."
local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN PTR localhost."
local\-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." static
local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN
NS localhost."
local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN
PTR localhost."
.fi
.TP 10
\h'5'\fIreverse RFC1918 local use zones\fR
@@ -503,7 +513,8 @@ Reverse data for zones 0.in\-addr.arpa, 254.169.in\-addr.arpa,
\h'5'\fIreverse RFC4291 IP6 unspecified\fR
Reverse data for zone
.nf
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.
.fi
.TP 10
\h'5'\fIreverse RFC4193 IPv6 Locally Assigned Local Addresses\fR
+16 -14
View File
@@ -51,11 +51,13 @@
#include "util/storage/slabhash.h"
int
context_finalize(struct ub_val_ctx* ctx)
context_finalize(struct ub_ctx* ctx)
{
struct config_file* cfg = ctx->env->cfg;
verbosity = cfg->verbosity;
log_init(cfg->logfile, cfg->use_syslog, NULL);
if(ctx->logfile_override)
log_file(ctx->log_out);
else log_init(cfg->logfile, cfg->use_syslog, NULL);
config_apply(cfg);
if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env))
return UB_INITFAIL;
@@ -99,7 +101,7 @@ void
context_query_delete(struct ctx_query* q)
{
if(!q) return;
ub_val_resolve_free(q->res);
ub_resolve_free(q->res);
free(q->msg);
free(q);
}
@@ -108,7 +110,7 @@ context_query_delete(struct ctx_query* q)
#define NUM_ID_TRIES 100000
/** find next useful id number of 0 on error */
static int
find_id(struct ub_val_ctx* ctx, int* id)
find_id(struct ub_ctx* ctx, int* id)
{
size_t tries = 0;
ctx->next_querynum++;
@@ -122,8 +124,8 @@ find_id(struct ub_val_ctx* ctx, int* id)
}
struct ctx_query*
context_new(struct ub_val_ctx* ctx, char* name, int rrtype, int rrclass,
ub_val_callback_t cb, void* cbarg)
context_new(struct ub_ctx* ctx, char* name, int rrtype, int rrclass,
ub_callback_t cb, void* cbarg)
{
struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q));
if(!q) return NULL;
@@ -138,7 +140,7 @@ context_new(struct ub_val_ctx* ctx, char* name, int rrtype, int rrclass,
q->async = (cb != NULL);
q->cb = cb;
q->cb_arg = cbarg;
q->res = (struct ub_val_result*)calloc(1, sizeof(*q->res));
q->res = (struct ub_result*)calloc(1, sizeof(*q->res));
if(!q->res) {
free(q);
return NULL;
@@ -162,7 +164,7 @@ context_new(struct ub_val_ctx* ctx, char* name, int rrtype, int rrclass,
}
struct alloc_cache*
context_obtain_alloc(struct ub_val_ctx* ctx, int locking)
context_obtain_alloc(struct ub_ctx* ctx, int locking)
{
struct alloc_cache* a;
int tnum = 0;
@@ -188,7 +190,7 @@ context_obtain_alloc(struct ub_val_ctx* ctx, int locking)
}
void
context_release_alloc(struct ub_val_ctx* ctx, struct alloc_cache* alloc,
context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc,
int locking)
{
if(!ctx || !alloc)
@@ -227,7 +229,7 @@ context_serialize_new_query(struct ctx_query* q, uint32_t* len)
}
struct ctx_query*
context_deserialize_new_query(struct ub_val_ctx* ctx, uint8_t* p, uint32_t len)
context_deserialize_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len)
{
struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q));
if(!q) return NULL;
@@ -239,7 +241,7 @@ context_deserialize_new_query(struct ub_val_ctx* ctx, uint8_t* p, uint32_t len)
q->querynum = (int)ldns_read_uint32(p+sizeof(uint32_t));
q->node.key = &q->querynum;
q->async = 1;
q->res = (struct ub_val_result*)calloc(1, sizeof(*q->res));
q->res = (struct ub_result*)calloc(1, sizeof(*q->res));
if(!q->res) {
free(q);
return NULL;
@@ -260,7 +262,7 @@ context_deserialize_new_query(struct ub_val_ctx* ctx, uint8_t* p, uint32_t len)
}
struct ctx_query*
context_lookup_new_query(struct ub_val_ctx* ctx, uint8_t* p, uint32_t len)
context_lookup_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len)
{
struct ctx_query* q;
int querynum;
@@ -304,7 +306,7 @@ context_serialize_answer(struct ctx_query* q, int err, ldns_buffer* pkt,
}
struct ctx_query*
context_deserialize_answer(struct ub_val_ctx* ctx,
context_deserialize_answer(struct ub_ctx* ctx,
uint8_t* p, uint32_t len, int* err)
{
struct ctx_query* q = NULL ;
@@ -343,7 +345,7 @@ context_serialize_cancel(struct ctx_query* q, uint32_t* len)
return p;
}
struct ctx_query* context_deserialize_cancel(struct ub_val_ctx* ctx,
struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx,
uint8_t* p, uint32_t len)
{
struct ctx_query* q;
+16 -12
View File
@@ -55,7 +55,7 @@ struct libworker;
* qq : write queries to the async service pid/tid.
* rr : read results from the async service pid/tid.
*/
struct ub_val_ctx {
struct ub_ctx {
/* --- pipes --- */
/** mutex on query write pipe */
lock_basic_t qqpipe_lock;
@@ -87,6 +87,10 @@ struct ub_val_ctx {
int dothread;
/** next thread number for new threads */
int thr_next_num;
/** if logfile is overriden */
int logfile_override;
/** what logfile to use instead */
FILE* log_out;
/**
* List of alloc-cache-id points per threadnum for notinuse threads.
* Simply the entire struct alloc_cache with the 'super' member used
@@ -137,7 +141,7 @@ struct ctx_query {
int cancelled;
/** for async query, the callback function */
ub_val_callback_t cb;
ub_callback_t cb;
/** for async query, the callback user arg */
void* cb_arg;
@@ -152,7 +156,7 @@ struct ctx_query {
/** result structure, also contains original query, type, class.
* malloced ptr ready to hand to the client. */
struct ub_val_result* res;
struct ub_result* res;
};
/**
@@ -206,7 +210,7 @@ enum ub_ctx_cmd {
* @param ctx: context to finalize. creates shared data.
* @return 0 if OK, or errcode.
*/
int context_finalize(struct ub_val_ctx* ctx);
int context_finalize(struct ub_ctx* ctx);
/** compare two ctx_query elements */
int context_query_cmp(const void* a, const void* b);
@@ -227,8 +231,8 @@ void context_query_delete(struct ctx_query* q);
* @param cbarg: user arg for async queries.
* @return new ctx_query or NULL for malloc failure.
*/
struct ctx_query* context_new(struct ub_val_ctx* ctx, char* name, int rrtype,
int rrclass, ub_val_callback_t cb, void* cbarg);
struct ctx_query* context_new(struct ub_ctx* ctx, char* name, int rrtype,
int rrclass, ub_callback_t cb, void* cbarg);
/**
* Get a new alloc. Creates a new one or uses a cached one.
@@ -236,7 +240,7 @@ struct ctx_query* context_new(struct ub_val_ctx* ctx, char* name, int rrtype,
* @param locking: if true, cfglock is locked while getting alloc.
* @return an alloc, or NULL on mem error.
*/
struct alloc_cache* context_obtain_alloc(struct ub_val_ctx* ctx, int locking);
struct alloc_cache* context_obtain_alloc(struct ub_ctx* ctx, int locking);
/**
* Release an alloc. Puts it into the cache.
@@ -244,7 +248,7 @@ struct alloc_cache* context_obtain_alloc(struct ub_val_ctx* ctx, int locking);
* @param locking: if true, cfglock is locked while releasing alloc.
* @param alloc: alloc to relinquish.
*/
void context_release_alloc(struct ub_val_ctx* ctx, struct alloc_cache* alloc,
void context_release_alloc(struct ub_ctx* ctx, struct alloc_cache* alloc,
int locking);
/**
@@ -301,7 +305,7 @@ enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len);
* @param len: length of buffer.
* @return looked up ctx_query or NULL for malloc failure.
*/
struct ctx_query* context_lookup_new_query(struct ub_val_ctx* ctx,
struct ctx_query* context_lookup_new_query(struct ub_ctx* ctx,
uint8_t* p, uint32_t len);
/**
@@ -311,7 +315,7 @@ struct ctx_query* context_lookup_new_query(struct ub_val_ctx* ctx,
* @param len: length of buffer.
* @return new ctx_query or NULL for malloc failure.
*/
struct ctx_query* context_deserialize_new_query(struct ub_val_ctx* ctx,
struct ctx_query* context_deserialize_new_query(struct ub_ctx* ctx,
uint8_t* p, uint32_t len);
/**
@@ -322,7 +326,7 @@ struct ctx_query* context_deserialize_new_query(struct ub_val_ctx* ctx,
* @param err: error code to be returned to client is passed.
* @return ctx_query with answer added or NULL for malloc failure.
*/
struct ctx_query* context_deserialize_answer(struct ub_val_ctx* ctx,
struct ctx_query* context_deserialize_answer(struct ub_ctx* ctx,
uint8_t* p, uint32_t len, int* err);
/**
@@ -332,7 +336,7 @@ struct ctx_query* context_deserialize_answer(struct ub_val_ctx* ctx,
* @param len: length of buffer.
* @return ctx_query to cancel or NULL for failure.
*/
struct ctx_query* context_deserialize_cancel(struct ub_val_ctx* ctx,
struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx,
uint8_t* p, uint32_t len);
#endif /* LIBUNBOUND_CONTEXT_H */
+138 -36
View File
@@ -59,16 +59,16 @@
#include "services/cache/infra.h"
#include "services/cache/rrset.h"
struct ub_val_ctx*
ub_val_ctx_create()
struct ub_ctx*
ub_ctx_create()
{
struct ub_val_ctx* ctx;
struct ub_ctx* ctx;
unsigned int seed;
log_init(NULL, 0, NULL); /* logs to stderr */
log_ident_set("libunbound");
verbosity = 0; /* errors only */
checklock_start();
ctx = (struct ub_val_ctx*)calloc(1, sizeof(*ctx));
ctx = (struct ub_ctx*)calloc(1, sizeof(*ctx));
if(!ctx) {
errno = ENOMEM;
return NULL;
@@ -154,7 +154,7 @@ delq(rbnode_t* n, void* ATTR_UNUSED(arg))
}
void
ub_val_ctx_delete(struct ub_val_ctx* ctx)
ub_ctx_delete(struct ub_ctx* ctx)
{
struct alloc_cache* a, *na;
if(!ctx) return;
@@ -234,7 +234,23 @@ ub_val_ctx_delete(struct ub_val_ctx* ctx)
}
int
ub_val_ctx_config(struct ub_val_ctx* ctx, char* fname)
ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val)
{
lock_basic_lock(&ctx->cfglock);
if(ctx->finalized) {
lock_basic_unlock(&ctx->cfglock);
return UB_AFTERFINAL;
}
if(!config_set_option(ctx->env->cfg, opt, val)) {
lock_basic_unlock(&ctx->cfglock);
return UB_SYNTAX;
}
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
int
ub_ctx_config(struct ub_ctx* ctx, char* fname)
{
lock_basic_lock(&ctx->cfglock);
if(ctx->finalized) {
@@ -250,7 +266,7 @@ ub_val_ctx_config(struct ub_val_ctx* ctx, char* fname)
}
int
ub_val_ctx_add_ta(struct ub_val_ctx* ctx, char* ta)
ub_ctx_add_ta(struct ub_ctx* ctx, char* ta)
{
char* dup = strdup(ta);
if(!dup) return UB_NOMEM;
@@ -269,7 +285,7 @@ ub_val_ctx_add_ta(struct ub_val_ctx* ctx, char* ta)
}
int
ub_val_ctx_add_ta_file(struct ub_val_ctx* ctx, char* fname)
ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname)
{
char* dup = strdup(fname);
if(!dup) return UB_NOMEM;
@@ -288,7 +304,7 @@ ub_val_ctx_add_ta_file(struct ub_val_ctx* ctx, char* fname)
}
int
ub_val_ctx_trustedkeys(struct ub_val_ctx* ctx, char* fname)
ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname)
{
char* dup = strdup(fname);
if(!dup) return UB_NOMEM;
@@ -307,7 +323,7 @@ ub_val_ctx_trustedkeys(struct ub_val_ctx* ctx, char* fname)
}
int
ub_val_ctx_debuglevel(struct ub_val_ctx* ctx, int d)
ub_ctx_debuglevel(struct ub_ctx* ctx, int d)
{
lock_basic_lock(&ctx->cfglock);
verbosity = d;
@@ -316,8 +332,18 @@ ub_val_ctx_debuglevel(struct ub_val_ctx* ctx, int d)
return UB_NOERROR;
}
int ub_ctx_debugout(struct ub_ctx* ctx, void* out)
{
lock_basic_lock(&ctx->cfglock);
log_file((FILE*)out);
ctx->logfile_override = 1;
ctx->log_out = out;
lock_basic_unlock(&ctx->cfglock);
return UB_NOERROR;
}
int
ub_val_ctx_async(struct ub_val_ctx* ctx, int dothread)
ub_ctx_async(struct ub_ctx* ctx, int dothread)
{
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
if(dothread) /* cannot do threading */
@@ -335,7 +361,7 @@ ub_val_ctx_async(struct ub_val_ctx* ctx, int dothread)
/** perform a select() on the result read pipe */
static int
pollit(struct ub_val_ctx* ctx, struct timeval* t)
pollit(struct ub_ctx* ctx, struct timeval* t)
{
fd_set r;
#ifndef S_SPLINT_S
@@ -350,7 +376,7 @@ pollit(struct ub_val_ctx* ctx, struct timeval* t)
}
int
ub_val_poll(struct ub_val_ctx* ctx)
ub_poll(struct ub_ctx* ctx)
{
struct timeval t;
memset(&t, 0, sizeof(t));
@@ -359,16 +385,16 @@ ub_val_poll(struct ub_val_ctx* ctx)
}
int
ub_val_fd(struct ub_val_ctx* ctx)
ub_fd(struct ub_ctx* ctx)
{
return ctx->rrpipe[0];
}
/** process answer from bg worker */
static int
process_answer_detail(struct ub_val_ctx* ctx, uint8_t* msg, uint32_t len,
ub_val_callback_t* cb, void** cbarg, int* err,
struct ub_val_result** res)
process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len,
ub_callback_t* cb, void** cbarg, int* err,
struct ub_result** res)
{
struct ctx_query* q;
if(context_serial_getcmd(msg, len) != UB_LIBCMD_ANSWER) {
@@ -397,7 +423,7 @@ process_answer_detail(struct ub_val_ctx* ctx, uint8_t* msg, uint32_t len,
}
if(*err) {
*res = NULL;
ub_val_resolve_free(q->res);
ub_resolve_free(q->res);
} else {
/* parse the message, extract rcode, fill result */
ldns_buffer* buf = ldns_buffer_new(q->msg_len);
@@ -427,12 +453,12 @@ process_answer_detail(struct ub_val_ctx* ctx, uint8_t* msg, uint32_t len,
/** process answer from bg worker */
static int
process_answer(struct ub_val_ctx* ctx, uint8_t* msg, uint32_t len)
process_answer(struct ub_ctx* ctx, uint8_t* msg, uint32_t len)
{
int err;
ub_val_callback_t cb;
ub_callback_t cb;
void* cbarg;
struct ub_val_result* res;
struct ub_result* res;
int r;
r = process_answer_detail(ctx, msg, len, &cb, &cbarg, &err, &res);
@@ -446,7 +472,7 @@ process_answer(struct ub_val_ctx* ctx, uint8_t* msg, uint32_t len)
}
int
ub_val_process(struct ub_val_ctx* ctx)
ub_process(struct ub_ctx* ctx)
{
int r;
uint8_t* msg;
@@ -470,12 +496,12 @@ ub_val_process(struct ub_val_ctx* ctx)
}
int
ub_val_wait(struct ub_val_ctx* ctx)
ub_wait(struct ub_ctx* ctx)
{
int err;
ub_val_callback_t cb;
ub_callback_t cb;
void* cbarg;
struct ub_val_result* res;
struct ub_result* res;
int r;
uint8_t* msg;
uint32_t len;
@@ -523,8 +549,8 @@ ub_val_wait(struct ub_val_ctx* ctx)
}
int
ub_val_resolve(struct ub_val_ctx* ctx, char* name, int rrtype,
int rrclass, struct ub_val_result** result)
ub_resolve(struct ub_ctx* ctx, char* name, int rrtype,
int rrclass, struct ub_result** result)
{
struct ctx_query* q;
int r;
@@ -564,8 +590,8 @@ ub_val_resolve(struct ub_val_ctx* ctx, char* name, int rrtype,
}
int
ub_val_resolve_async(struct ub_val_ctx* ctx, char* name, int rrtype,
int rrclass, void* mydata, ub_val_callback_t callback, int* async_id)
ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype,
int rrclass, void* mydata, ub_callback_t callback, int* async_id)
{
struct ctx_query* q;
uint8_t* msg = NULL;
@@ -627,7 +653,7 @@ ub_val_resolve_async(struct ub_val_ctx* ctx, char* name, int rrtype,
}
int
ub_val_cancel(struct ub_val_ctx* ctx, int async_id)
ub_cancel(struct ub_ctx* ctx, int async_id)
{
struct ctx_query* q;
uint8_t* msg = NULL;
@@ -668,7 +694,7 @@ ub_val_cancel(struct ub_val_ctx* ctx, int async_id)
}
void
ub_val_resolve_free(struct ub_val_result* result)
ub_resolve_free(struct ub_result* result)
{
char** p;
if(!result) return;
@@ -684,7 +710,7 @@ ub_val_resolve_free(struct ub_val_result* result)
}
const char*
ub_val_strerror(int err)
ub_strerror(int err)
{
switch(err) {
case UB_NOERROR: return "no error";
@@ -702,7 +728,7 @@ ub_val_strerror(int err)
}
int
ub_val_ctx_set_fwd(struct ub_val_ctx* ctx, char* addr)
ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr)
{
struct sockaddr_storage storage;
socklen_t stlen;
@@ -774,7 +800,7 @@ ub_val_ctx_set_fwd(struct ub_val_ctx* ctx, char* addr)
}
int
ub_val_ctx_resolvconf(struct ub_val_ctx* ctx, char* fname)
ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname)
{
FILE* in;
int numserv = 0;
@@ -806,7 +832,7 @@ ub_val_ctx_resolvconf(struct ub_val_ctx* ctx, char* fname)
/* terminate after the address, remove newline */
*parse = 0;
if((r = ub_val_ctx_set_fwd(ctx, addr)) != UB_NOERROR) {
if((r = ub_ctx_set_fwd(ctx, addr)) != UB_NOERROR) {
fclose(in);
return r;
}
@@ -815,7 +841,83 @@ ub_val_ctx_resolvconf(struct ub_val_ctx* ctx, char* fname)
fclose(in);
if(numserv == 0) {
/* from resolv.conf(5) if none given, use localhost */
return ub_val_ctx_set_fwd(ctx, "127.0.0.1");
return ub_ctx_set_fwd(ctx, "127.0.0.1");
}
return UB_NOERROR;
}
int
ub_ctx_hosts(struct ub_ctx* ctx, char* fname)
{
FILE* in;
char buf[1024], ldata[1024];
char* parse, *addr, *name, *ins;
lock_basic_lock(&ctx->cfglock);
if(ctx->finalized) {
lock_basic_unlock(&ctx->cfglock);
errno=EINVAL;
return UB_AFTERFINAL;
}
lock_basic_unlock(&ctx->cfglock);
if(fname == NULL)
fname = "/etc/hosts";
in = fopen(fname, "r");
if(!in) {
/* error in errno! perror(fname) */
return UB_READFILE;
}
while(fgets(buf, (int)sizeof(buf), in)) {
buf[sizeof(buf)-1] = 0;
parse=buf;
while(*parse == ' ' || *parse == '\t')
parse++;
if(*parse == '#')
continue; /* skip comment */
/* format: <addr> spaces <name> spaces <name> ... */
addr = parse;
/* skip addr */
while(isxdigit(*parse) || *parse == '.' || *parse == ':')
parse++;
if(*parse != ' ' && *parse != '\t') {
/* must have whitespace after address */
fclose(in);
errno=EINVAL;
return UB_SYNTAX;
}
*parse++ = 0; /* end delimiter for addr ... */
/* go to names and add them */
while(*parse) {
while(*parse == ' ' || *parse == '\t' || *parse=='\n')
parse++;
if(*parse == 0 || *parse == '#')
break;
/* skip name, allows (too) many printable characters */
name = parse;
while('!' <= *parse && *parse <= '~')
parse++;
if(*parse)
*parse++ = 0; /* end delimiter for name */
snprintf(ldata, sizeof(ldata), "%s %s %s",
name, str_is_ip6(addr)?"AAAA":"A", addr);
ins = strdup(ldata);
if(!ins) {
/* out of memory */
fclose(in);
errno=ENOMEM;
return UB_NOMEM;
}
lock_basic_lock(&ctx->cfglock);
if(!cfg_strlist_insert(&ctx->env->cfg->local_data,
ins)) {
lock_basic_unlock(&ctx->cfglock);
fclose(in);
free(ins);
errno=ENOMEM;
return UB_NOMEM;
}
lock_basic_unlock(&ctx->cfglock);
}
}
fclose(in);
return UB_NOERROR;
}
+8 -8
View File
@@ -88,7 +88,7 @@ libworker_delete(struct libworker* w)
/** setup fresh libworker struct */
static struct libworker*
libworker_setup(struct ub_val_ctx* ctx, int is_bg)
libworker_setup(struct ub_ctx* ctx, int is_bg)
{
unsigned int seed;
struct libworker* w = (struct libworker*)calloc(1, sizeof(*w));
@@ -354,7 +354,7 @@ libworker_dobg(void* arg)
uint32_t m;
int fd;
struct libworker* w = (struct libworker*)arg;
struct ub_val_ctx* ctx = w->ctx;
struct ub_ctx* ctx = w->ctx;
log_thread_set(&w->thread_num);
#if !defined(HAVE_PTHREAD) && !defined(HAVE_SOLARIS_THREADS)
/* we are forked */
@@ -399,7 +399,7 @@ libworker_dobg(void* arg)
return NULL;
}
int libworker_bg(struct ub_val_ctx* ctx)
int libworker_bg(struct ub_ctx* ctx)
{
struct libworker* w;
/* fork or threadcreate */
@@ -457,7 +457,7 @@ parse_reply(ldns_buffer* pkt, struct regional* region, struct query_info* qi)
/** insert canonname */
static int
fill_canon(struct ub_val_result* res, uint8_t* s)
fill_canon(struct ub_result* res, uint8_t* s)
{
char buf[255+2];
dname_str(s, buf);
@@ -467,7 +467,7 @@ fill_canon(struct ub_val_result* res, uint8_t* s)
/** fill data into result */
static int
fill_res(struct ub_val_result* res, struct ub_packed_rrset_key* answer,
fill_res(struct ub_result* res, struct ub_packed_rrset_key* answer,
uint8_t* finalcname, struct query_info* rq)
{
size_t i;
@@ -504,7 +504,7 @@ fill_res(struct ub_val_result* res, struct ub_packed_rrset_key* answer,
/** fill result from parsed message, on error fills servfail */
void
libworker_enter_result(struct ub_val_result* res, ldns_buffer* buf,
libworker_enter_result(struct ub_result* res, ldns_buffer* buf,
struct regional* temp, enum sec_status msg_security)
{
struct query_info rq;
@@ -591,7 +591,7 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q,
return 1;
}
int libworker_fg(struct ub_val_ctx* ctx, struct ctx_query* q)
int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
{
struct libworker* w = libworker_setup(ctx, 0);
uint16_t qflags, qid;
@@ -690,7 +690,7 @@ libworker_bg_done_cb(void* arg, int rcode, ldns_buffer* buf, enum sec_status s)
if(q->cancelled) {
if(q->w->is_bg_thread) {
/* delete it now */
struct ub_val_ctx* ctx = q->w->ctx;
struct ub_ctx* ctx = q->w->ctx;
lock_basic_lock(&ctx->cfglock);
(void)rbtree_delete(&ctx->queries, q->node.key);
ctx->num_async--;
+6 -6
View File
@@ -44,8 +44,8 @@
#ifndef LIBUNBOUND_WORKER_H
#define LIBUNBOUND_WORKER_H
#include "util/data/packed_rrset.h"
struct ub_val_ctx;
struct ub_val_result;
struct ub_ctx;
struct ub_result;
struct module_env;
struct comm_base;
struct outside_network;
@@ -66,7 +66,7 @@ struct libworker {
/** every worker has a unique thread_num. (first in struct) */
int thread_num;
/** context we are operating under */
struct ub_val_ctx* ctx;
struct ub_ctx* ctx;
/** is this the bg worker? */
int is_bg;
@@ -122,7 +122,7 @@ struct libworker_res_list {
* @return 0 if OK, else error.
* Further communication is done via the pipes in ctx.
*/
int libworker_bg(struct ub_val_ctx* ctx);
int libworker_bg(struct ub_ctx* ctx);
/**
* Create a foreground worker.
@@ -133,7 +133,7 @@ int libworker_bg(struct ub_val_ctx* ctx);
* @param q: query (result is stored in here).
* @return 0 if finished OK, else error.
*/
int libworker_fg(struct ub_val_ctx* ctx, struct ctx_query* q);
int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q);
/** cleanup the cache to remove all rrset IDs from it, arg is libworker */
void libworker_alloc_cleanup(void* arg);
@@ -230,7 +230,7 @@ int libworker_read_msg(int fd, uint8_t** buf, uint32_t* len, int nonblock);
* On error, the res may contain a different status
* (out of memory is not secure, not bogus).
*/
void libworker_enter_result(struct ub_val_result* res, ldns_buffer* buf,
void libworker_enter_result(struct ub_result* res, ldns_buffer* buf,
struct regional* temp, enum sec_status msg_security);
#endif /* LIBUNBOUND_WORKER_H */
+22 -19
View File
@@ -1,19 +1,22 @@
ub_val_ctx_create
ub_val_ctx_delete
ub_val_ctx_config
ub_val_ctx_set_fwd
ub_val_ctx_resolvconf
ub_val_ctx_add_ta
ub_val_ctx_add_ta_file
ub_val_ctx_trustedkeys
ub_val_ctx_debuglevel
ub_val_ctx_async
ub_val_poll
ub_val_wait
ub_val_fd
ub_val_process
ub_val_resolve
ub_val_resolve_async
ub_val_cancel
ub_val_resolve_free
ub_val_strerror
ub_ctx_create
ub_ctx_delete
ub_ctx_set_option
ub_ctx_config
ub_ctx_set_fwd
ub_ctx_resolvconf
ub_ctx_hosts
ub_ctx_add_ta
ub_ctx_add_ta_file
ub_ctx_trustedkeys
ub_ctx_debugout
ub_ctx_debuglevel
ub_ctx_async
ub_poll
ub_wait
ub_fd
ub_process
ub_resolve
ub_resolve_async
ub_cancel
ub_resolve_free
ub_strerror
+84 -44
View File
@@ -43,29 +43,29 @@
* to perform (validated) DNS lookups.
*
* All start with
* ctx = ub_val_ctx_create();
* err = ub_val_ctx_add_ta(ctx, "...");
* err = ub_val_ctx_add_ta(ctx, "...");
* ctx = ub_ctx_create();
* err = ub_ctx_add_ta(ctx, "...");
* err = ub_ctx_add_ta(ctx, "...");
* ... some lookups
* ... call ub_val_ctx_delete(ctx); when you want to stop.
* ... call ub_ctx_delete(ctx); when you want to stop.
*
* Application not threaded. Blocking.
* int err = ub_val_resolve(ctx, "www.example.com", ...
* if(err) fprintf(stderr, "lookup error: %s\n", ub_val_strerror(err));
* int err = ub_resolve(ctx, "www.example.com", ...
* if(err) fprintf(stderr, "lookup error: %s\n", ub_strerror(err));
* ... use the answer
*
* Application not threaded. Non-blocking ('asynchronous').
* err = ub_val_resolve_async(ctx, "www.example.com", ... my_callback);
* err = ub_resolve_async(ctx, "www.example.com", ... my_callback);
* ... application resumes processing ...
* ... and when either ub_val_poll(ctx) is true
* ... or when the file descriptor ub_val_fd(ctx) is readable,
* ... and when either ub_poll(ctx) is true
* ... or when the file descriptor ub_fd(ctx) is readable,
* ... or whenever, the app calls ...
* ub_val_process(ctx);
* ub_process(ctx);
* ... if no result is ready, the app resumes processing above,
* ... or process() calls my_callback() with results.
*
* ... if the application has nothing more to do, wait for answer
* ub_val_wait(ctx);
* ub_wait(ctx);
*
* Application threaded. Blocking.
* Blocking, same as above. The current thread does the work.
@@ -74,7 +74,7 @@
*
* Application threaded. Non-blocking ('asynchronous').
* ... setup threaded-asynchronous config option
* err = ub_val_ctx_async(ctx, 1);
* err = ub_ctx_async(ctx, 1);
* ... same as async for non-threaded
* ... the callbacks are called in the thread that calls process(ctx)
*
@@ -84,7 +84,7 @@
* Otherwise, for asynchronous with threading, a worker thread is created.
*
* The blocking calls use shared ctx-cache when threaded. Thus
* ub_val_resolve() and ub_val_resolve_async() && ub_val_wait() are
* ub_resolve() and ub_resolve_async() && ub_wait() are
* not the same. The first makes the current thread do the work, setting
* up buffers, etc, to perform the work (but using shared cache data).
* The second calls another worker thread (or process) to perform the work.
@@ -100,14 +100,14 @@
*
* Its contents are internally defined.
*/
struct ub_val_ctx;
struct ub_ctx;
/**
* The validation and resolution results.
* Allocated by the resolver, and need to be freed by the application
* with ub_val_resolve_free().
* with ub_resolve_free().
*/
struct ub_val_result {
struct ub_result {
/** The original question, name text string. */
char* qname;
/** the type asked for */
@@ -179,7 +179,7 @@ struct ub_val_result {
/**
* Callback for results of async queries.
* The readable function definition looks like:
* void my_callback(void* my_arg, int err, struct ub_val_result* result);
* void my_callback(void* my_arg, int err, struct ub_result* result);
* It is called with
* void* my_arg: your pointer to a (struct of) data of your choice,
* or NULL.
@@ -187,23 +187,40 @@ struct ub_val_result {
* are forthcoming.
* struct result: pointer to more detailed result structure.
* This structure is allocated on the heap and needs to be
* freed with ub_val_resolve_free(result);
* freed with ub_resolve_free(result);
*/
typedef void (*ub_val_callback_t)(void*, int, struct ub_val_result*);
typedef void (*ub_callback_t)(void*, int, struct ub_result*);
/**
* Create a resolving and validation context.
* The information from /etc/resolv.conf and /etc/hosts is not utilised by
* default. Use ub_ctx_resolvconf and ub_ctx_hosts to read them.
* @return a new context. default initialisation.
* returns NULL on error.
*/
struct ub_val_ctx* ub_val_ctx_create(void);
struct ub_ctx* ub_ctx_create(void);
/**
* Destroy a validation context and free all its resources.
* Outstanding async queries are killed and callbacks are not called for them.
* @param ctx: context to delete.
*/
void ub_val_ctx_delete(struct ub_val_ctx* ctx);
void ub_ctx_delete(struct ub_ctx* ctx);
/**
* Set an option for the context.
* @param ctx: context.
* @param opt: option name from the unbound.conf config file format.
* (not all settings applicable). The name includes the trailing ':'
* for example ub_ctx_set_option("logfile:", "mylog.txt");
* This is a power-users interface that lets you specify all sorts
* of options.
* For some specific options, such as adding trust anchors, special
* routines exist.
* @param val: value of the option.
* @return: 0 if OK, else error.
*/
int ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val);
/**
* setup configuration for the given context.
@@ -215,7 +232,7 @@ void ub_val_ctx_delete(struct ub_val_ctx* ctx);
* routines exist.
* @return: 0 if OK, else error.
*/
int ub_val_ctx_config(struct ub_val_ctx* ctx, char* fname);
int ub_ctx_config(struct ub_ctx* ctx, char* fname);
/**
* Set machine to forward DNS queries to, the caching resolver to use.
@@ -225,7 +242,7 @@ int ub_val_ctx_config(struct ub_val_ctx* ctx, char* fname);
* that case the addresses are used as backup servers.
*
* To read the list of nameservers from /etc/resolv.conf (from DHCP or so),
* use the call ub_val_ctx_resolvconf.
* use the call ub_ctx_resolvconf.
*
* @param ctx: context.
* At this time it is only possible to set configuration before the
@@ -234,7 +251,7 @@ int ub_val_ctx_config(struct ub_val_ctx* ctx, char* fname);
* If the addr is NULL, forwarding is disabled.
* @return 0 if OK, else error.
*/
int ub_val_ctx_set_fwd(struct ub_val_ctx* ctx, char* addr);
int ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr);
/**
* Read list of nameservers to use from the filename given.
@@ -250,7 +267,20 @@ int ub_val_ctx_set_fwd(struct ub_val_ctx* ctx, char* addr);
* @param fname: file name string. If NULL "/etc/resolv.conf" is used.
* @return 0 if OK, else error.
*/
int ub_val_ctx_resolvconf(struct ub_val_ctx* ctx, char* fname);
int ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname);
/**
* Read list of hosts from the filename given.
* Usually "/etc/hosts".
* These addresses are not flagged as DNSSEC secure when queried for.
*
* @param ctx: context.
* At this time it is only possible to set configuration before the
* first resolve is done.
* @param fname: file name string. If NULL "/etc/hosts" is used.
* @return 0 if OK, else error.
*/
int ub_ctx_hosts(struct ub_ctx* ctx, char* fname);
/**
* Add a trust anchor to the given context.
@@ -263,7 +293,7 @@ int ub_val_ctx_resolvconf(struct ub_val_ctx* ctx, char* fname);
* [domainname] [TTL optional] [type] [class optional] [rdata contents]
* @return 0 if OK, else error.
*/
int ub_val_ctx_add_ta(struct ub_val_ctx* ctx, char* ta);
int ub_ctx_add_ta(struct ub_ctx* ctx, char* ta);
/**
* Add trust anchors to the given context.
@@ -274,7 +304,7 @@ int ub_val_ctx_add_ta(struct ub_val_ctx* ctx, char* ta);
* @param fname: filename of file with keyfile with trust anchors.
* @return 0 if OK, else error.
*/
int ub_val_ctx_add_ta_file(struct ub_val_ctx* ctx, char* fname);
int ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname);
/**
* Add trust anchors to the given context.
@@ -286,7 +316,17 @@ int ub_val_ctx_add_ta_file(struct ub_val_ctx* ctx, char* fname);
* anchors.
* @return 0 if OK, else error.
*/
int ub_val_ctx_trustedkeys(struct ub_val_ctx* ctx, char* fname);
int ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname);
/**
* Set debug output (and error output) to the specified stream.
* Pass NULL to disable. Default is stderr.
* @param ctx: context.
* @param out: FILE* out file stream to log to.
* Type void* to avoid stdio dependency of this header file.
* @return 0 if OK, else error.
*/
int ub_ctx_debugout(struct ub_ctx* ctx, void* out);
/**
* Set debug verbosity for the context
@@ -296,7 +336,7 @@ int ub_val_ctx_trustedkeys(struct ub_val_ctx* ctx, char* fname);
* and 3 is lots.
* @return 0 if OK, else error.
*/
int ub_val_ctx_debuglevel(struct ub_val_ctx* ctx, int d);
int ub_ctx_debuglevel(struct ub_ctx* ctx, int d);
/**
* Set a context behaviour for asynchronous action.
@@ -308,7 +348,7 @@ int ub_val_ctx_debuglevel(struct ub_val_ctx* ctx, int d);
* no effect (delete and re-create the context to change).
* @return 0 if OK, else error.
*/
int ub_val_ctx_async(struct ub_val_ctx* ctx, int dothread);
int ub_ctx_async(struct ub_ctx* ctx, int dothread);
/**
* Poll a context to see if it has any new results
@@ -318,27 +358,27 @@ int ub_val_ctx_async(struct ub_val_ctx* ctx, int dothread);
* @return: 0 if nothing to read, or nonzero if a result is available.
* If nonzero, call ctx_process() to do callbacks.
*/
int ub_val_poll(struct ub_val_ctx* ctx);
int ub_poll(struct ub_ctx* ctx);
/**
* Wait for a context to finish with results. Calls ub_val_process() after
* Wait for a context to finish with results. Calls ub_process() after
* the wait for you. After the wait, there are no more outstanding
* asynchronous queries.
* @param ctx: context.
* @return: 0 if OK, else error.
*/
int ub_val_wait(struct ub_val_ctx* ctx);
int ub_wait(struct ub_ctx* ctx);
/**
* Get file descriptor. Wait for it to become readable, at this point
* answers are returned from the asynchronous validating resolver.
* Then call the ub_val_process to continue processing.
* Then call the ub_process to continue processing.
* This routine works immediately after context creation, the fd
* does not change.
* @param ctx: context.
* @return: -1 on error, or file descriptor to use select(2) with.
*/
int ub_val_fd(struct ub_val_ctx* ctx);
int ub_fd(struct ub_ctx* ctx);
/**
* Call this routine to continue processing results from the validating
@@ -347,7 +387,7 @@ int ub_val_fd(struct ub_val_ctx* ctx);
* @param ctx: context
* @return: 0 if OK, else error.
*/
int ub_val_process(struct ub_val_ctx* ctx);
int ub_process(struct ub_ctx* ctx);
/**
* Perform resolution and validation of the target name.
@@ -361,8 +401,8 @@ int ub_val_process(struct ub_val_ctx* ctx);
* in that case (out of memory).
* @return 0 if OK, else error.
*/
int ub_val_resolve(struct ub_val_ctx* ctx, char* name, int rrtype,
int rrclass, struct ub_val_result** result);
int ub_resolve(struct ub_ctx* ctx, char* name, int rrtype,
int rrclass, struct ub_result** result);
/**
* Perform resolution and validation of the target name.
@@ -379,7 +419,7 @@ int ub_val_resolve(struct ub_val_ctx* ctx, char* name, int rrtype,
* and is passed on to the callback function.
* @param callback: this is called on completion of the resolution.
* It is called as:
* void callback(void* mydata, int err, struct ub_val_result* result)
* void callback(void* mydata, int err, struct ub_result* result)
* with mydata: the same as passed here, you may pass NULL,
* with err: is 0 when a result has been found.
* with result: a newly allocated result structure.
@@ -392,8 +432,8 @@ int ub_val_resolve(struct ub_val_ctx* ctx, char* name, int rrtype,
* cancel the query.
* @return 0 if OK, else error.
*/
int ub_val_resolve_async(struct ub_val_ctx* ctx, char* name, int rrtype,
int rrclass, void* mydata, ub_val_callback_t callback, int* async_id);
int ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype,
int rrclass, void* mydata, ub_callback_t callback, int* async_id);
/**
* Cancel an async query in progress.
@@ -403,19 +443,19 @@ int ub_val_resolve_async(struct ub_val_ctx* ctx, char* name, int rrtype,
* @param async_id: which query to cancel.
* @return 0 if OK, else error.
*/
int ub_val_cancel(struct ub_val_ctx* ctx, int async_id);
int ub_cancel(struct ub_ctx* ctx, int async_id);
/**
* Free storage associated with a result structure.
* @param result: to free
*/
void ub_val_resolve_free(struct ub_val_result* result);
void ub_resolve_free(struct ub_result* result);
/**
* Convert error value to a human readable string.
* @param err: error code from one of the ub_val* functions.
* @return pointer to constant text string, zero terminated.
*/
const char* ub_val_strerror(int err);
const char* ub_strerror(int err);
#endif /* _UB_UNBOUND_H */
+4
View File
@@ -213,6 +213,10 @@ fi
replace_all doc/README
replace_all doc/unbound.8
replace_all doc/unbound.conf.5
replace_all doc/unbound-checkconf.8
replace_all doc/unbound-host.1
replace_all doc/libunbound.3
info "Renaming Unbound directory to unbound-$version."
cd ..
+9 -8
View File
@@ -768,20 +768,21 @@ mesh_log_list(struct mesh_area* mesh)
void
mesh_stats(struct mesh_area* mesh, const char* str)
{
log_info("%s %u states (%u with reply, %u detached), "
"%u waiting replies", str, (unsigned)mesh->all.count,
verbose(VERB_DETAIL, "%s %u recursion states (%u with reply, "
"%u detached), %u waiting replies, %u recursion replies "
"sent", str, (unsigned)mesh->all.count,
(unsigned)mesh->num_reply_states,
(unsigned)mesh->num_detached_states,
(unsigned)mesh->num_reply_addrs);
(unsigned)mesh->num_reply_addrs,
(unsigned)mesh->replies_sent);
if(mesh->replies_sent > 0) {
struct timeval avg;
timeval_divide(&avg, &mesh->replies_sum_wait,
mesh->replies_sent);
log_info("sent %u replies, with average wait "
"of %d.%6.6d sec", (unsigned)mesh->replies_sent,
(int)avg.tv_sec, (int)avg.tv_usec);
log_info("histogram of reply wait times");
timehist_log(mesh->histogram);
log_info("average recursion processing time "
"%d.%6.6d sec", (int)avg.tv_sec, (int)avg.tv_usec);
log_info("histogram of recursion processing times");
timehist_log(mesh->histogram, "recursions");
}
}
+15 -15
View File
@@ -176,7 +176,7 @@ massage_class(const char* c)
/** nice security status string */
static const char*
secure_str(struct ub_val_result* result)
secure_str(struct ub_result* result)
{
if(result->secure) return "(secure)";
if(result->bogus) return "(BOGUS (security failure))";
@@ -274,7 +274,7 @@ pretty_rdata(char* q, char* cstr, char* tstr, int t, const char* sec,
/** pretty line of output for results */
static void
pretty_output(char* q, int t, int c, struct ub_val_result* result, int docname)
pretty_output(char* q, int t, int c, struct ub_result* result, int docname)
{
int i;
const char *secstatus = secure_str(result);
@@ -337,25 +337,25 @@ pretty_output(char* q, int t, int c, struct ub_val_result* result, int docname)
/** perform a lookup and printout return if domain existed */
static int
dnslook(struct ub_val_ctx* ctx, char* q, int t, int c, int docname)
dnslook(struct ub_ctx* ctx, char* q, int t, int c, int docname)
{
int ret;
struct ub_val_result* result;
struct ub_result* result;
ret = ub_val_resolve(ctx, q, t, c, &result);
ret = ub_resolve(ctx, q, t, c, &result);
if(ret != 0) {
fprintf(stderr, "resolve error: %s\n", ub_val_strerror(ret));
fprintf(stderr, "resolve error: %s\n", ub_strerror(ret));
exit(1);
}
pretty_output(q, t, c, result, docname);
ret = result->nxdomain;
ub_val_resolve_free(result);
ub_resolve_free(result);
return ret;
}
/** perform host lookup */
static void
lookup(struct ub_val_ctx* ctx, const char* nm, const char* qt, const char* qc)
lookup(struct ub_ctx* ctx, const char* nm, const char* qt, const char* qc)
{
/* massage input into a query name, type and class */
int multi = 0; /* no type, so do A, AAAA, MX */
@@ -374,7 +374,7 @@ lookup(struct ub_val_ctx* ctx, const char* nm, const char* qt, const char* qc)
} else {
(void)dnslook(ctx, realq, t, c, 1);
}
ub_val_ctx_delete(ctx);
ub_ctx_delete(ctx);
free(realq);
}
@@ -389,10 +389,10 @@ int main(int argc, char* argv[])
int c;
char* qclass = NULL;
char* qtype = NULL;
struct ub_val_ctx* ctx = NULL;
struct ub_ctx* ctx = NULL;
int debuglevel = 0;
ctx = ub_val_ctx_create();
ctx = ub_ctx_create();
if(!ctx) {
fprintf(stderr, "error: out of memory\n");
exit(1);
@@ -408,7 +408,7 @@ int main(int argc, char* argv[])
debuglevel++;
if(debuglevel < 2)
debuglevel = 2; /* at least VERB_DETAIL */
ub_val_ctx_debuglevel(ctx, debuglevel);
ub_ctx_debuglevel(ctx, debuglevel);
break;
case 't':
qtype = optarg;
@@ -417,13 +417,13 @@ int main(int argc, char* argv[])
verb++;
break;
case 'y':
ub_val_ctx_add_ta(ctx, optarg);
ub_ctx_add_ta(ctx, optarg);
break;
case 'f':
ub_val_ctx_add_ta_file(ctx, optarg);
ub_ctx_add_ta_file(ctx, optarg);
break;
case 'F':
ub_val_ctx_trustedkeys(ctx, optarg);
ub_ctx_trustedkeys(ctx, optarg);
break;
case '?':
case 'h':
+56 -45
View File
@@ -56,7 +56,7 @@ struct lookinfo {
/** error code from libunbound */
int err;
/** result from lookup */
struct ub_val_result* result;
struct ub_result* result;
};
/** global variable to see how many queries we have left */
@@ -72,6 +72,7 @@ void usage(char* argv[])
printf(" -d : enable debug output\n");
printf(" -f addr : use addr, forward to that server\n");
printf(" -h : this help message\n");
printf(" -H fname : read hosts from fname\n");
printf(" -r fname : read resolv.conf from fname\n");
printf(" -t : use a resolver thread instead of forking a process\n");
printf(" -x : perform extended threaded test\n");
@@ -85,7 +86,7 @@ print_result(struct lookinfo* info)
char buf[100];
if(info->err) /* error (from libunbound) */
printf("%s: error %s\n", info->name,
ub_val_strerror(info->err));
ub_strerror(info->err));
else if(!info->result)
printf("%s: cancelled\n", info->name);
else if(info->result->havedata)
@@ -105,9 +106,9 @@ print_result(struct lookinfo* info)
}
}
/** this is a function of type ub_val_callback_t */
/** this is a function of type ub_callback_t */
static void
lookup_is_done(void* mydata, int err, struct ub_val_result* result)
lookup_is_done(void* mydata, int err, struct ub_result* result)
{
/* cast mydata back to the correct type */
struct lookinfo* info = (struct lookinfo*)mydata;
@@ -123,7 +124,7 @@ static void
checkerr(const char* desc, int err)
{
if(err != 0) {
printf("%s error: %s\n", desc, ub_val_strerror(err));
printf("%s error: %s\n", desc, ub_strerror(err));
exit(1);
}
}
@@ -143,7 +144,7 @@ struct ext_thr_info {
/** thread id */
ub_thread_t tid;
/** context */
struct ub_val_ctx* ctx;
struct ub_ctx* ctx;
/** size of array to query */
int argc;
/** array of names to query */
@@ -157,7 +158,7 @@ static int q_is_localhost = 0;
/** check result structure for the 'correct' answer */
static void
ext_check_result(const char* desc, int err, struct ub_val_result* result)
ext_check_result(const char* desc, int err, struct ub_result* result)
{
checkerr(desc, err);
if(result == NULL) {
@@ -218,9 +219,9 @@ ext_check_result(const char* desc, int err, struct ub_val_result* result)
}
}
/** extended bg result callback, this function is ub_val_callback_t */
/** extended bg result callback, this function is ub_callback_t */
static void
ext_callback(void* mydata, int err, struct ub_val_result* result)
ext_callback(void* mydata, int err, struct ub_result* result)
{
int* my_id = (int*)mydata;
int doprint = 0;
@@ -243,7 +244,7 @@ ext_callback(void* mydata, int err, struct ub_val_result* result)
pi.err = 0;
print_result(&pi);
}
ub_val_resolve_free(result);
ub_resolve_free(result);
}
/** extended thread worker */
@@ -252,7 +253,7 @@ ext_thread(void* arg)
{
struct ext_thr_info* inf = (struct ext_thr_info*)arg;
int i, r;
struct ub_val_result* result;
struct ub_result* result;
int* async_ids = NULL;
log_thread_set(&inf->thread_num);
if(inf->thread_num > NUMTHR*2/3) {
@@ -264,32 +265,32 @@ ext_thread(void* arg)
}
for(i=0; i<inf->numq; i++) {
if(async_ids) {
r = ub_val_resolve_async(inf->ctx,
r = ub_resolve_async(inf->ctx,
inf->argv[i%inf->argc], LDNS_RR_TYPE_A,
LDNS_RR_CLASS_IN, &async_ids[i], ext_callback,
&async_ids[i]);
checkerr("ub_val_resolve_async", r);
checkerr("ub_resolve_async", r);
if(i > 100) {
r = ub_val_cancel(inf->ctx, async_ids[i-100]);
checkerr("ub_val_cancel", r);
r = ub_cancel(inf->ctx, async_ids[i-100]);
checkerr("ub_cancel", r);
async_ids[i-100]=0;
}
} else if(inf->thread_num > NUMTHR/2) {
/* async */
r = ub_val_resolve_async(inf->ctx,
r = ub_resolve_async(inf->ctx,
inf->argv[i%inf->argc], LDNS_RR_TYPE_A,
LDNS_RR_CLASS_IN, NULL, ext_callback, NULL);
checkerr("ub_val_resolve_async", r);
checkerr("ub_resolve_async", r);
} else {
/* blocking */
r = ub_val_resolve(inf->ctx, inf->argv[i%inf->argc],
r = ub_resolve(inf->ctx, inf->argv[i%inf->argc],
LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, &result);
ext_check_result("ub_val_resolve", r, result);
ext_check_result("ub_resolve", r, result);
}
}
if(inf->thread_num > NUMTHR/2) {
r = ub_val_wait(inf->ctx);
checkerr("ub_val_ctx_wait", r);
r = ub_wait(inf->ctx);
checkerr("ub_ctx_wait", r);
}
free(async_ids);
@@ -298,7 +299,7 @@ ext_thread(void* arg)
/** perform extended threaded test */
static int
ext_test(struct ub_val_ctx* ctx, int argc, char** argv)
ext_test(struct ub_ctx* ctx, int argc, char** argv)
{
struct ext_thr_info inf[NUMTHR];
int i;
@@ -319,7 +320,7 @@ ext_test(struct ub_val_ctx* ctx, int argc, char** argv)
ub_thread_join(inf[i].tid);
}
printf("extended test end\n");
ub_val_ctx_delete(ctx);
ub_ctx_delete(ctx);
checklock_stop();
return 0;
}
@@ -333,7 +334,7 @@ extern char* optarg;
int main(int argc, char** argv)
{
int c;
struct ub_val_ctx* ctx;
struct ub_ctx* ctx;
struct lookinfo* lookups;
int i, r, cancel=0, blocking=0, ext=0;
@@ -341,7 +342,7 @@ int main(int argc, char** argv)
checklock_start();
/* create context */
ctx = ub_val_ctx_create();
ctx = ub_ctx_create();
if(!ctx) {
printf("could not create context, %s\n", strerror(errno));
return 1;
@@ -351,15 +352,15 @@ int main(int argc, char** argv)
if(argc == 1) {
usage(argv);
}
while( (c=getopt(argc, argv, "bcdf:hr:tx")) != -1) {
while( (c=getopt(argc, argv, "bcdf:hH:r:tx")) != -1) {
switch(c) {
case 'd':
r = ub_val_ctx_debuglevel(ctx, 3);
checkerr("ub_val_ctx_debuglevel", r);
r = ub_ctx_debuglevel(ctx, 3);
checkerr("ub_ctx_debuglevel", r);
break;
case 't':
r = ub_val_ctx_async(ctx, 1);
checkerr("ub_val_ctx_async", r);
r = ub_ctx_async(ctx, 1);
checkerr("ub_ctx_async", r);
break;
case 'c':
cancel = 1;
@@ -368,18 +369,28 @@ int main(int argc, char** argv)
blocking = 1;
break;
case 'r':
r = ub_val_ctx_resolvconf(ctx, optarg);
r = ub_ctx_resolvconf(ctx, optarg);
if(r != 0) {
printf("ub_val_ctx_resolvconf "
printf("ub_ctx_resolvconf "
"error: %s : %s\n",
ub_val_strerror(r),
ub_strerror(r),
strerror(errno));
return 1;
}
break;
case 'H':
r = ub_ctx_hosts(ctx, optarg);
if(r != 0) {
printf("ub_ctx_hosts "
"error: %s : %s\n",
ub_strerror(r),
strerror(errno));
return 1;
}
break;
case 'f':
r = ub_val_ctx_set_fwd(ctx, optarg);
checkerr("ub_val_ctx_set_fwd", r);
r = ub_ctx_set_fwd(ctx, optarg);
checkerr("ub_ctx_set_fwd", r);
break;
case 'x':
ext = 1;
@@ -410,15 +421,15 @@ int main(int argc, char** argv)
lookups[i].name = argv[i];
if(blocking) {
fprintf(stderr, "lookup %s\n", argv[i]);
r = ub_val_resolve(ctx, argv[i], LDNS_RR_TYPE_A,
r = ub_resolve(ctx, argv[i], LDNS_RR_TYPE_A,
LDNS_RR_CLASS_IN, &lookups[i].result);
checkerr("ub_val_resolve", r);
checkerr("ub_resolve", r);
} else {
fprintf(stderr, "start async lookup %s\n", argv[i]);
r = ub_val_resolve_async(ctx, argv[i], LDNS_RR_TYPE_A,
r = ub_resolve_async(ctx, argv[i], LDNS_RR_TYPE_A,
LDNS_RR_CLASS_IN, &lookups[i], &lookup_is_done,
&lookups[i].async_id);
checkerr("ub_val_resolve_async", r);
checkerr("ub_resolve_async", r);
}
}
if(blocking)
@@ -426,8 +437,8 @@ int main(int argc, char** argv)
else if(cancel) {
for(i=0; i<argc; i++) {
fprintf(stderr, "cancel %s\n", argv[i]);
r = ub_val_cancel(ctx, lookups[i].async_id);
checkerr("ub_val_cancel", r);
r = ub_cancel(ctx, lookups[i].async_id);
checkerr("ub_cancel", r);
}
num_wait = 0;
}
@@ -437,8 +448,8 @@ int main(int argc, char** argv)
for(i=0; i<1000; i++) {
usleep(100000);
fprintf(stderr, "%g seconds passed\n", 0.1*(double)i);
r = ub_val_process(ctx);
checkerr("ub_val_process", r);
r = ub_process(ctx);
checkerr("ub_process", r);
if(num_wait == 0)
break;
}
@@ -451,10 +462,10 @@ int main(int argc, char** argv)
/* print lookup results */
for(i=0; i<argc; i++) {
print_result(&lookups[i]);
ub_val_resolve_free(lookups[i].result);
ub_resolve_free(lookups[i].result);
}
ub_val_ctx_delete(ctx);
ub_ctx_delete(ctx);
free(lookups);
checklock_stop();
return 0;
+1 -1
View File
@@ -2,7 +2,7 @@
NEED_SPLINT='00-lint.tpkg'
NEED_DOXYGEN='01-doc.tpkg'
NEED_LDNS_TESTNS='fwd_no_edns.tpkg fwd_tcp_tc.tpkg fwd_tcp.tpkg fwd_three_service.tpkg fwd_three.tpkg fwd_ttlexpire.tpkg fwd_udp.tpkg fwd_tcp_tc6.tpkg fwd_compress_c00c.tpkg fwd_ancil.tpkg stat_timer.tpkg'
NEED_LDNS_TESTNS='fwd_no_edns.tpkg fwd_tcp_tc.tpkg fwd_tcp.tpkg fwd_three_service.tpkg fwd_three.tpkg fwd_ttlexpire.tpkg fwd_udp.tpkg fwd_tcp_tc6.tpkg fwd_compress_c00c.tpkg fwd_ancil.tpkg stat_timer.tpkg 05-asynclook.tpkg stream_tcp.tpkg'
NEED_XXD='fwd_compress_c00c.tpkg'
NEED_NC='fwd_compress_c00c.tpkg'
BIN
View File
Binary file not shown.
+162
View File
@@ -164,6 +164,168 @@ struct config_file* config_create_forlib()
return cfg;
}
/** check that the value passed is >= 0 */
#define IS_NUMBER_OR_ZERO \
if(atoi(val) == 0 && strcmp(val, "0") != 0) return 0
/** check that the value passed is > 0 */
#define IS_NONZERO_NUMBER \
if(atoi(val) == 0) return 0
/** check that the value passed is not 0 and a power of 2 */
#define IS_POW2_NUMBER \
if(atoi(val) == 0 || !is_pow2((size_t)atoi(val))) return 0
/** check that the value passed is yes or no */
#define IS_YES_OR_NO \
if(strcmp(val, "yes") != 0 && strcmp(val, "no") != 0) return 0
int config_set_option(struct config_file* cfg, const char* opt,
const char* val)
{
if(strcmp(opt, "verbosity:") == 0) {
IS_NUMBER_OR_ZERO;
cfg->verbosity = atoi(val);
} else if(strcmp(opt, "statistics-interval:") == 0) {
if(strcmp(val, "0") == 0 || strcmp(val, "") == 0)
cfg->stat_interval = 0;
else if(atoi(val) == 0)
return 0;
else cfg->stat_interval = atoi(val);
} else if(strcmp(opt, "num_threads:") == 0) {
/* not supported, library must have 1 thread in bgworker */
return 0;
} else if(strcmp(opt, "do-ip4:") == 0) {
IS_YES_OR_NO;
cfg->do_ip4 = (strcmp(val, "yes") == 0);
} else if(strcmp(opt, "do-ip6:") == 0) {
IS_YES_OR_NO;
cfg->do_ip6 = (strcmp(val, "yes") == 0);
} else if(strcmp(opt, "do-udp:") == 0) {
IS_YES_OR_NO;
cfg->do_udp = (strcmp(val, "yes") == 0);
} else if(strcmp(opt, "do-tcp:") == 0) {
IS_YES_OR_NO;
cfg->do_tcp = (strcmp(val, "yes") == 0);
} else if(strcmp(opt, "outgoing-port:") == 0) {
IS_NUMBER_OR_ZERO;
cfg->outgoing_base_port = atoi(val);
} else if(strcmp(opt, "outgoing-range:") == 0) {
IS_NONZERO_NUMBER;
cfg->outgoing_num_ports = atoi(val);
} else if(strcmp(opt, "outgoing-num-tcp:") == 0) {
IS_NUMBER_OR_ZERO;
cfg->outgoing_num_tcp = (size_t)atoi(val);
} else if(strcmp(opt, "incoming-num-tcp:") == 0) {
IS_NUMBER_OR_ZERO;
cfg->incoming_num_tcp = (size_t)atoi(val);
} else if(strcmp(opt, "msg-buffer-size:") == 0) {
IS_NONZERO_NUMBER;
cfg->msg_buffer_size = (size_t)atoi(val);
} else if(strcmp(opt, "msg-cache-size:") == 0) {
return cfg_parse_memsize(val, &cfg->msg_cache_size);
} else if(strcmp(opt, "msg-cache-slabs:") == 0) {
IS_POW2_NUMBER;
cfg->msg_cache_slabs = (size_t)atoi(val);
} else if(strcmp(opt, "num-queries-per-thread:") == 0) {
IS_NONZERO_NUMBER;
cfg->num_queries_per_thread = (size_t)atoi(val);
} else if(strcmp(opt, "rrset-cache-size:") == 0) {
return cfg_parse_memsize(val, &cfg->rrset_cache_size);
} else if(strcmp(opt, "rrset-cache-slabs:") == 0) {
IS_POW2_NUMBER;
cfg->rrset_cache_slabs = (size_t)atoi(val);
} else if(strcmp(opt, "cache-max-ttl:") == 0) {
IS_NUMBER_OR_ZERO;
cfg->max_ttl = atoi(val);
} else if(strcmp(opt, "infra-host-ttl:") == 0) {
IS_NUMBER_OR_ZERO;
cfg->host_ttl = atoi(val);
} else if(strcmp(opt, "infra-lame-ttl:") == 0) {
IS_NUMBER_OR_ZERO;
cfg->lame_ttl = atoi(val);
} else if(strcmp(opt, "infra-cache-slabs:") == 0) {
IS_POW2_NUMBER;
cfg->infra_cache_slabs = (size_t)atoi(val);
} else if(strcmp(opt, "infra-cache-numhosts:") == 0) {
IS_NONZERO_NUMBER;
cfg->infra_cache_numhosts = (size_t)atoi(val);
} else if(strcmp(opt, "infra-cache-lame-size:") == 0) {
return cfg_parse_memsize(val, &cfg->infra_cache_lame_size);
} else if(strcmp(opt, "logfile:") == 0) {
cfg->use_syslog = 0;
free(cfg->logfile);
return (cfg->logfile = strdup(val)) != NULL;
} else if(strcmp(opt, "use-syslog:") == 0) {
IS_YES_OR_NO;
cfg->use_syslog = (strcmp(val, "yes") == 0);
} else if(strcmp(opt, "root-hints:") == 0) {
return cfg_strlist_insert(&cfg->root_hints, strdup(val));
} else if(strcmp(opt, "target-fetch-policy:") == 0) {
free(cfg->target_fetch_policy);
return (cfg->target_fetch_policy = strdup(val)) != NULL;
} else if(strcmp(opt, "harden-glue:") == 0) {
IS_YES_OR_NO;
cfg->harden_glue = (strcmp(val, "yes") == 0);
} else if(strcmp(opt, "harden-short-bufsize:") == 0) {
IS_YES_OR_NO;
cfg->harden_short_bufsize = (strcmp(val, "yes") == 0);
} else if(strcmp(opt, "harden-large-queries:") == 0) {
IS_YES_OR_NO;
cfg->harden_large_queries = (strcmp(val, "yes") == 0);
} else if(strcmp(opt, "harden-dnssec-stripped:") == 0) {
IS_YES_OR_NO;
cfg->harden_dnssec_stripped = (strcmp(val, "yes") == 0);
} else if(strcmp(opt, "do-not-query-localhost:") == 0) {
IS_YES_OR_NO;
cfg->donotquery_localhost = (strcmp(val, "yes") == 0);
} else if(strcmp(opt, "do-not-query-address:") == 0) {
return cfg_strlist_insert(&cfg->donotqueryaddrs, strdup(val));
} else if(strcmp(opt, "trust-anchor-file:") == 0) {
return cfg_strlist_insert(&cfg->trust_anchor_file_list,
strdup(val));
} else if(strcmp(opt, "trust-anchor:") == 0) {
return cfg_strlist_insert(&cfg->trust_anchor_list,
strdup(val));
} else if(strcmp(opt, "trusted-keys-file:") == 0) {
return cfg_strlist_insert(&cfg->trusted_keys_file_list,
strdup(val));
} else if(strcmp(opt, "val-override-date:") == 0) {
if(strcmp(val, "") == 0 || strcmp(val, "0") == 0) {
cfg->val_date_override = 0;
} else if(strlen(val) == 14) {
cfg->val_date_override = cfg_convert_timeval(val);
return cfg->val_date_override != 0;
} else {
if(atoi(val) == 0) return 0;
cfg->val_date_override = (uint32_t)atoi(val);
}
} else if(strcmp(opt, "val-bogus-ttl:") == 0) {
IS_NUMBER_OR_ZERO;
cfg->bogus_ttl = atoi(val);
} else if(strcmp(opt, "val-clean-additional:") == 0) {
IS_YES_OR_NO;
cfg->val_clean_additional = (strcmp(val, "yes") == 0);
} else if(strcmp(opt, "val-permissive-mode:") == 0) {
IS_YES_OR_NO;
cfg->val_permissive_mode = (strcmp(val, "yes") == 0);
} else if(strcmp(opt, "val-nsec3-keysize-iterations:") == 0) {
free(cfg->val_nsec3_key_iterations);
return (cfg->val_nsec3_key_iterations = strdup(val)) != NULL;
} else if(strcmp(opt, "key-cache-size:") == 0) {
return cfg_parse_memsize(val, &cfg->key_cache_size);
} else if(strcmp(opt, "key-cache-slabs:") == 0) {
IS_POW2_NUMBER;
cfg->key_cache_slabs = (size_t)atoi(val);
} else if(strcmp(opt, "local-data:") == 0) {
return cfg_strlist_insert(&cfg->local_data, strdup(val));
} else if(strcmp(opt, "module-config:") == 0) {
free(cfg->module_conf);
return (cfg->module_conf = strdup(val)) != NULL;
} else {
/* unknown or unsupported (from the library interface) */
return 0;
}
return 1;
}
/** initialize the global cfg_parser object */
static void
create_cfg_parser(struct config_file* cfg, char* filename)
+11
View File
@@ -271,6 +271,17 @@ void config_delete(struct config_file* config);
*/
void config_apply(struct config_file* config);
/**
* Set the given keyword to the given value.
* @param config: where to store config
* @param option: option name, including the ':' character.
* @param value: value, this string is copied if needed, or parsed.
* The caller owns the value string.
* @return 0 on error (malloc or syntax error).
*/
int config_set_option(struct config_file* config, const char* option,
const char* value);
/**
* Insert string into strlist.
* @param head: pointer to strlist head variable.
+7 -1
View File
@@ -104,7 +104,7 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)
}
/* open the file for logging */
if(chrootdir && chrootdir[0] && strncmp(filename, chrootdir,
strlen(chrootdir)) == 0)
strlen(chrootdir)) == 0)
filename += strlen(chrootdir);
f = fopen(filename, "a");
if(!f) {
@@ -115,6 +115,11 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)
logfile = f;
}
void log_file(FILE *f)
{
logfile = f;
}
void log_thread_set(int* num)
{
ub_thread_key_set(logkey, num);
@@ -140,6 +145,7 @@ log_vmsg(int pri, const char* type,
return;
}
#endif /* HAVE_SYSLOG_H */
if(!logfile) return;
fprintf(logfile, "[%d] %s[%d:%x] %s: %s\n", (int)time(NULL),
ident, (int)getpid(), tid?*tid:0, type, message);
fflush(logfile);
+7
View File
@@ -84,6 +84,13 @@ void verbose(enum verbosity_value level,
*/
void log_init(const char* filename, int use_syslog, const char* chrootdir);
/**
* Set logging to go to the specified file *.
* This setting does not affect the use_syslog setting.
* @param f: to that file, or pass NULL to disable logging.
*/
void log_file(FILE *f);
/**
* Init a thread (will print this number for the thread log entries).
* Must be called from the thread itself. If not called 0 is printed.
+2 -2
View File
@@ -156,7 +156,7 @@ void timehist_print(struct timehist* hist)
#endif
}
void timehist_log(struct timehist* hist)
void timehist_log(struct timehist* hist, const char* name)
{
#ifndef S_SPLINT_S
size_t i;
@@ -165,7 +165,7 @@ void timehist_log(struct timehist* hist)
timehist_quartile(hist, 0.50),
timehist_quartile(hist, 0.75));
/* 0000.000000 0000.000000 0 */
log_info("lower(secs) upper(secs) replycount");
log_info("lower(secs) upper(secs) %s", name);
for(i=0; i<hist->num; i++) {
if(hist->buckets[i].count != 0) {
log_info("%4d.%6.6d %4d.%6.6d %u",
+2 -1
View File
@@ -108,7 +108,8 @@ void timehist_print(struct timehist* hist);
/**
* Log histogram, print it to the logfile.
* @param hist: histogram
* @param name: the name of the value column
*/
void timehist_log(struct timehist* hist);
void timehist_log(struct timehist* hist, const char* name);
#endif /* UTIL_TIMEHIST_H */
+10 -3
View File
@@ -53,8 +53,8 @@
#include "util/regional.h"
enum val_classification
val_classify_response(uint16_t query_flags, struct query_info* qinf,
struct reply_info* rep, size_t skip)
val_classify_response(uint16_t query_flags, struct query_info* origqinf,
struct query_info* qinf, struct reply_info* rep, size_t skip)
{
int rcode = (int)FLAGS_GET_RCODE(rep->flags);
size_t i;
@@ -82,7 +82,14 @@ val_classify_response(uint16_t query_flags, struct query_info* qinf,
}
return saw_ns?VAL_CLASS_REFERRAL:VAL_CLASS_NODATA;
}
/* root referral where NS set is in the answer section */
if(!(query_flags&BIT_RD) && rep->ns_numrrsets == 0 &&
rep->an_numrrsets == 1 && rcode == LDNS_RCODE_NOERROR &&
ntohs(rep->rrsets[0]->rk.type) == LDNS_RR_TYPE_NS &&
query_dname_compare(rep->rrsets[0]->rk.dname,
origqinf->qname) != 0)
return VAL_CLASS_REFERRAL;
/* dump bad messages */
if(rcode != LDNS_RCODE_NOERROR)
return VAL_CLASS_UNKNOWN;
+3 -1
View File
@@ -80,6 +80,7 @@ enum val_classification {
/**
* Given a response, classify ANSWER responses into a subtype.
* @param query_flags: query flags for the original query.
* @param origqinf: query info. The original query name.
* @param qinf: query info. The chased query name.
* @param rep: response. The original response.
* @param skip: offset into the original response answer section.
@@ -88,7 +89,8 @@ enum val_classification {
* Then, another CNAME type, CNAME_NOANSWER or POSITIVE are possible.
*/
enum val_classification val_classify_response(uint16_t query_flags,
struct query_info* qinf, struct reply_info* rep, size_t skip);
struct query_info* origqinf, struct query_info* qinf,
struct reply_info* rep, size_t skip);
/**
* Given a response, determine the name of the "signer". This is primarily
+7 -7
View File
@@ -1090,8 +1090,8 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
uint8_t* lookup_name;
size_t lookup_len;
enum val_classification subtype = val_classify_response(
qstate->query_flags, &vq->qchase, vq->orig_msg->rep,
vq->rrset_skip);
qstate->query_flags, &qstate->qinfo, &vq->qchase,
vq->orig_msg->rep, vq->rrset_skip);
verbose(VERB_ALGO, "validator classification %s",
val_classification_to_string(subtype));
if(subtype == VAL_CLASS_REFERRAL &&
@@ -1388,8 +1388,8 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
return 1;
}
subtype = val_classify_response(qstate->query_flags, &vq->qchase,
vq->orig_msg->rep, vq->rrset_skip);
subtype = val_classify_response(qstate->query_flags, &qstate->qinfo,
&vq->qchase, vq->orig_msg->rep, vq->rrset_skip);
switch(subtype) {
case VAL_CLASS_POSITIVE:
verbose(VERB_ALGO, "Validating a positive response");
@@ -1478,8 +1478,8 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
struct val_env* ve, int id)
{
enum val_classification subtype = val_classify_response(
qstate->query_flags, &vq->qchase, vq->orig_msg->rep,
vq->rrset_skip);
qstate->query_flags, &qstate->qinfo, &vq->qchase,
vq->orig_msg->rep, vq->rrset_skip);
/* store overall validation result in orig_msg */
if(vq->rrset_skip == 0)
@@ -1787,7 +1787,7 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
goto return_bogus;
}
subtype = val_classify_response(BIT_RD, qinfo, msg->rep, 0);
subtype = val_classify_response(BIT_RD, qinfo, qinfo, msg->rep, 0);
if(subtype == VAL_CLASS_POSITIVE) {
struct ub_packed_rrset_key* ds;
enum sec_status sec;