version.server and consorts support.

git-svn-id: file:///svn/unbound/trunk@438 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-07-19 13:50:00 +00:00
parent a96e895bc9
commit 5e48023c6c
8 changed files with 173 additions and 3 deletions

View file

@ -57,6 +57,7 @@
#include "services/mesh.h"
#include "util/data/msgparse.h"
#include "util/data/msgencode.h"
#include "util/data/dname.h"
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
@ -260,6 +261,94 @@ answer_from_cache(struct worker* worker, struct lruhash_entry* e, uint16_t id,
return 1;
}
/**
* Fill CH class answer into buffer. Keeps query.
* @param pkt: buffer
* @param str: string to put into text record (<255).
* @param edns: edns reply information.
*/
static void
chaos_replystr(ldns_buffer* pkt, const char* str, struct edns_data* edns)
{
int len = strlen(str);
int rd = LDNS_RD_WIRE(ldns_buffer_begin(pkt));
int cd = LDNS_CD_WIRE(ldns_buffer_begin(pkt));
if(len>255) len=255; /* cap size of TXT record */
ldns_buffer_clear(pkt);
ldns_buffer_skip(pkt, sizeof(uint16_t)); /* skip id */
ldns_buffer_write_u16(pkt, BIT_QR|BIT_RA); /* noerror, no flags */
if(rd) LDNS_RD_SET(ldns_buffer_begin(pkt));
if(cd) LDNS_CD_SET(ldns_buffer_begin(pkt));
ldns_buffer_write_u16(pkt, 1); /* qdcount */
ldns_buffer_write_u16(pkt, 1); /* ancount */
ldns_buffer_write_u16(pkt, 0); /* nscount */
ldns_buffer_write_u16(pkt, 0); /* arcount */
(void)query_dname_len(pkt); /* skip qname */
ldns_buffer_skip(pkt, sizeof(uint16_t)); /* skip qtype */
ldns_buffer_skip(pkt, sizeof(uint16_t)); /* skip qclass */
ldns_buffer_write_u16(pkt, 0xc00c); /* compr ptr to query */
ldns_buffer_write_u16(pkt, LDNS_RR_TYPE_TXT);
ldns_buffer_write_u16(pkt, LDNS_RR_CLASS_CH);
ldns_buffer_write_u32(pkt, 0); /* TTL */
ldns_buffer_write_u16(pkt, sizeof(uint8_t) + len);
ldns_buffer_write_u8(pkt, len);
ldns_buffer_write(pkt, str, len);
ldns_buffer_flip(pkt);
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->bits &= EDNS_DO;
attach_edns_record(pkt, edns);
}
/**
* Answer CH class queries.
* @param w: worker
* @param qinfo: query info. Pointer into packet buffer.
* @param edns: edns info from query.
* @param pkt: packet buffer.
* @return: true if a reply is to be sent.
*/
static int
answer_chaos(struct worker* w, struct query_info* qinfo,
struct edns_data* edns, ldns_buffer* pkt)
{
struct config_file* cfg = w->env.cfg;
if(qinfo->qtype != LDNS_RR_TYPE_ANY && qinfo->qtype != LDNS_RR_TYPE_TXT)
return 0;
if(query_dname_compare(qinfo->qname,
(uint8_t*)"\002id\006server") == 0 ||
query_dname_compare(qinfo->qname,
(uint8_t*)"\010hostname\004bind") == 0)
{
if(cfg->hide_identity)
return 0;
if(cfg->identity==NULL || cfg->identity[0]==0) {
char buf[MAXHOSTNAMELEN];
if (gethostname(buf, MAXHOSTNAMELEN) == 0)
chaos_replystr(pkt, buf, edns);
else {
log_err("gethostname: %s", strerror(errno));
chaos_replystr(pkt, "no hostname", edns);
}
}
else chaos_replystr(pkt, cfg->identity, edns);
return 1;
}
if(query_dname_compare(qinfo->qname,
(uint8_t*)"\007version\006server") == 0 ||
query_dname_compare(qinfo->qname,
(uint8_t*)"\007version\004bind") == 0)
{
if(cfg->hide_version)
return 0;
if(cfg->version==NULL || cfg->version[0]==0)
chaos_replystr(pkt, PACKAGE_STRING, edns);
else chaos_replystr(pkt, cfg->version, edns);
return 1;
}
return 0;
}
/** handles callbacks from listening event interface */
static int
worker_handle_request(struct comm_point* c, void* arg, int error,
@ -303,7 +392,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
LDNS_RCODE_REFUSED);
return 1;
}
h = query_info_hash(&qinfo);
if((ret=parse_edns_from_pkt(c->buffer, &edns)) != 0) {
verbose(VERB_ALGO, "worker parse edns: formerror.");
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
@ -340,6 +428,12 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
if(c->type != comm_udp)
edns.udp_size = 65535; /* max size for TCP replies */
if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo,
&edns, c->buffer)) {
verbose(VERB_ALGO, "class CH reply");
return 1;
}
h = query_info_hash(&qinfo);
if((e=slabhash_lookup(worker->env.msg_cache, h, &qinfo, 0))) {
/* answer from cache - we have acquired a readlock on it */
if(answer_from_cache(worker, e,

View file

@ -2,6 +2,7 @@
- shuffle NS selection when getting nameserver target addresses.
- fixup of deadlock warnings, yield cpu in checklock code so that
freebsd scheduler selects correct process to run.
- added identity and version config options and replies.
18 July 2007: Wouter
- do not query addresses, 127.0.0.1, and ::1 by default.

View file

@ -111,6 +111,18 @@ server:
# the pid file.
# pidfile: "unbound.pid"
# enable to not answer id.server and hostname.bind queries.
# hide-identity: no
# enable to not answer version.server and version.bind queries.
# hide-version: no
# the identity to report. Leave "" or default to return hostname.
# identity: ""
# the version to report. Leave "" or default to return package version.
# version: ""
# the target fetch policy.
# series of integers describing the policy per dependency depth.
# The number of values in the list determines the maximum dependency

View file

@ -117,6 +117,16 @@ The logfile is appended to, in the following format:
The process id is written to the file. Default is "unbound.pid". So,
kill -HUP `cat /etc/unbound/unbound.pid` will trigger a reload,
kill -QUIT `cat /etc/unbound/unbound.pid` will gracefully terminate.
.It \fBhide-identity:\fR <yes or no>
If enabled id.server and hostname.bind queries are refused.
.It \fBidentity:\fR <string>
Set the identity to report. If set to "", the default, then the hostname
of the server is returned.
.It \fBhide-version:\fR <yes or no>
If enabled version.server and version.bind queries are refused.
.It \fBversion:\fR <string>
Set the version to report. If set to "", the default, then the package
version is returned.
.It \fBtarget-fetch-policy:\fR <"list of numbers">
Set the target fetch policy used by unbound to determine if it should fetch
nameserver target addresses opportunistically. The policy is described per

View file

@ -106,6 +106,10 @@ config_create()
cfg->forwards = NULL;
cfg->harden_short_bufsize = 0;
cfg->harden_large_queries = 0;
cfg->hide_identity = 0;
cfg->hide_version = 0;
cfg->identity = NULL;
cfg->version = NULL;
return cfg;
error_exit:
config_delete(cfg);
@ -196,6 +200,8 @@ config_delete(struct config_file* cfg)
config_delstubs(cfg->stubs);
config_delstubs(cfg->forwards);
config_delstrlist(cfg->donotqueryaddrs);
free(cfg->identity);
free(cfg->version);
free(cfg);
}

View file

@ -124,6 +124,15 @@ struct config_file {
char* logfile;
/** pidfile to write pid to. */
char* pidfile;
/** do not report identity (id.server, hostname.bind) */
int hide_identity;
/** do not report version (version.server, version.bind) */
int hide_version;
/** identity, hostname is returned if "". */
char* identity;
/** version, package version returned if "". */
char* version;
/** daemonize, i.e. fork into the background. */
int do_daemonize;

View file

@ -136,6 +136,10 @@ forward-zone{COLON} { YDOUT; return VAR_FORWARD_ZONE;}
forward-addr{COLON} { YDOUT; return VAR_FORWARD_ADDR;}
forward-host{COLON} { YDOUT; return VAR_FORWARD_HOST;}
do-not-query-address{COLON} { YDOUT; return VAR_DO_NOT_QUERY_ADDRESS;}
hide-identity{COLON} { YDOUT; return VAR_HIDE_IDENTITY;}
hide-version{COLON} { YDOUT; return VAR_HIDE_VERSION;}
identity{COLON} { YDOUT; return VAR_IDENTITY;}
version{COLON} { YDOUT; return VAR_VERSION;}
{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;}
/* Quoted strings. Strip leading and ending quotes */

View file

@ -78,7 +78,8 @@ extern struct config_parser_state* cfg_parser;
%token VAR_STUB_ZONE VAR_STUB_HOST VAR_STUB_ADDR VAR_TARGET_FETCH_POLICY
%token VAR_HARDEN_SHORT_BUFSIZE VAR_HARDEN_LARGE_QUERIES
%token VAR_FORWARD_ZONE VAR_FORWARD_HOST VAR_FORWARD_ADDR
%token VAR_DO_NOT_QUERY_ADDRESS
%token VAR_DO_NOT_QUERY_ADDRESS VAR_HIDE_IDENTITY VAR_HIDE_VERSION
%token VAR_IDENTITY VAR_VERSION
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@ -109,7 +110,8 @@ content_server: server_num_threads | server_verbosity | server_port |
server_infra_cache_slabs | server_infra_cache_numhosts |
server_infra_cache_numlame | server_target_fetch_policy |
server_harden_short_bufsize | server_harden_large_queries |
server_do_not_query_address
server_do_not_query_address | server_hide_identity |
server_hide_version | server_identity | server_version
;
stubstart: VAR_STUB_ZONE
{
@ -281,6 +283,38 @@ server_pidfile: VAR_PIDFILE STRING
cfg_parser->cfg->pidfile = $2;
}
;
server_hide_identity: VAR_HIDE_IDENTITY STRING
{
OUTYY(("P(server_hide_identity:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->hide_identity = (strcmp($2, "yes")==0);
free($2);
}
;
server_hide_version: VAR_HIDE_VERSION STRING
{
OUTYY(("P(server_hide_version:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->hide_version = (strcmp($2, "yes")==0);
free($2);
}
;
server_identity: VAR_IDENTITY STRING
{
OUTYY(("P(server_identity:%s)\n", $2));
free(cfg_parser->cfg->identity);
cfg_parser->cfg->identity = $2;
}
;
server_version: VAR_VERSION STRING
{
OUTYY(("P(server_version:%s)\n", $2));
free(cfg_parser->cfg->version);
cfg_parser->cfg->version = $2;
}
;
server_msg_cache_size: VAR_MSG_CACHE_SIZE STRING
{
OUTYY(("P(server_msg_cache_size:%s)\n", $2));