]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
version.server and consorts support.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 19 Jul 2007 13:50:00 +0000 (13:50 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 19 Jul 2007 13:50:00 +0000 (13:50 +0000)
git-svn-id: file:///svn/unbound/trunk@438 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/worker.c
doc/Changelog
doc/example.conf
doc/unbound.conf.5
util/config_file.c
util/config_file.h
util/configlexer.lex
util/configparser.y

index 8ac337512edd499f1be9993f8e32a0c6a2accca4..d48d486bbf14af3d3becedff68852a2cf4832472 100644 (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, 
index 9e8b64a03babe24774b692a25afff11172b5e536..e84d93a71ab2303c7a3e27f6e1f8e0f415bc3016 100644 (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.
index dbafea0d8dc090a08f647b263ed6c07b8d6118af..d18f0d38fe89939f224d1d214dbf7b4a48161745 100644 (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 
index f5064e8b59386533a2157704ec72792af01b008f..9d55faee44e2ed87f2e2cbe82a149702e53c183f 100644 (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
index c5300bd8b5743070f6c6e9c9add7323c0843b5b2..a4ab1cf449e052b7622fa89758dc012cff92ff7a 100644 (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);
 }
 
index c49fb7b1182dfdb300d3a3c6fc81b9332a8f41e8..f0a7996613b56d5e60d3e6cb19febbb446f9d2ed 100644 (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;
index a5ba7432cb5b9d4d3bb56de037fae0fb58ad600a..5631c04785725c62904afe11bda58ea594c9d09f 100644 (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 */
index 38335eefc93926eee9411b4c6c32e101a5a3bf50..31b982dd596c08182ebe12f8973b6e111d1cfce8 100644 (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));