mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
- Applied patch from Daisuke HIGASHI for rrset-roundrobin and
minimal-responses features. git-svn-id: file:///svn/unbound/trunk@2658 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
279f409636
commit
cf147df593
14 changed files with 1668 additions and 1479 deletions
|
|
@ -18,3 +18,4 @@ cz.nic - sponsoring 'summer of code' development by Zdenek and Marek.
|
|||
Brett Carr - windows beta testing.
|
||||
Luca Bruno - patch for windows support in libunbound hosts and resolvconf().
|
||||
Tom Hendrikx - contributed split-itar.sh a useful script to 5011-track ITAR.
|
||||
Daisuke HIGASHI - patch for rrset-roundrobin and minimal-responses.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
10 April 2012: Wouter
|
||||
- Applied patch from Daisuke HIGASHI for rrset-roundrobin and
|
||||
minimal-responses features.
|
||||
|
||||
5 April 2012: Wouter
|
||||
- fix bug #443: --with-chroot-dir not honoured by configure.
|
||||
- fix bug #444: setusercontext was called too late (thanks Bjorn
|
||||
|
|
|
|||
|
|
@ -309,6 +309,13 @@ server:
|
|||
# if yes, perform key lookups adjacent to normal lookups.
|
||||
# prefetch-key: no
|
||||
|
||||
# if yes, Unbound rotates RRSet order in response.
|
||||
# rrset-roundrobin: no
|
||||
|
||||
# if yes, Unbound doesn't insert authority/additional sections
|
||||
# into response messages when those sections are not required.
|
||||
# minimal-responses: no
|
||||
|
||||
# module configuration of the server. A string with identifiers
|
||||
# separated by spaces. "iterator" or "validator iterator"
|
||||
# module-config: "validator iterator"
|
||||
|
|
|
|||
|
|
@ -570,6 +570,18 @@ If yes, fetch the DNSKEYs earlier in the validation process, when a DS
|
|||
record is encountered. This lowers the latency of requests. It does use
|
||||
a little more CPU. Also if the cache is set to 0, it is no use. Default is no.
|
||||
.TP
|
||||
.B rrset-roundrobin: \fI<yes or no>
|
||||
If yes, Unbound rotates RRSet order in response (the random number is taken
|
||||
from the query ID, for speed and thread safety). Default is no.
|
||||
.TP
|
||||
.B minimal-responses: \fI<yes or no>
|
||||
If yes, Unbound doesn't insert authority/additional sections into response
|
||||
messages when those sections are not required. This reduces response
|
||||
size significantly, and may avoid TCP fallback for some responses.
|
||||
This may cause a slight speedup. The default is no, because the DNS
|
||||
protocol RFCs mandate these sections, and the additional content could
|
||||
be of use and save roundtrips for clients.
|
||||
.TP
|
||||
.B module\-config: \fI<"module names">
|
||||
Module configuration, a list of module names separated by spaces, surround
|
||||
the string with quotes (""). The modules can be validator, iterator.
|
||||
|
|
|
|||
|
|
@ -195,6 +195,8 @@ config_create(void)
|
|||
cfg->remote_control_enable = 0;
|
||||
cfg->control_ifs = NULL;
|
||||
cfg->control_port = UNBOUND_CONTROL_PORT;
|
||||
cfg->minimal_responses = 0;
|
||||
cfg->rrset_roundrobin = 0;
|
||||
if(!(cfg->server_key_file = strdup(RUN_DIR"/unbound_server.key")))
|
||||
goto error_exit;
|
||||
if(!(cfg->server_cert_file = strdup(RUN_DIR"/unbound_server.pem")))
|
||||
|
|
@ -399,6 +401,8 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
|||
else S_MEMSIZE("key-cache-size:", key_cache_size)
|
||||
else S_POW2("key-cache-slabs:", key_cache_slabs)
|
||||
else S_MEMSIZE("neg-cache-size:", neg_cache_size)
|
||||
else S_YNO("minimal-responses:", minimal_responses)
|
||||
else S_YNO("rrset-roundrobin:", rrset_roundrobin)
|
||||
else S_STRLIST("local-data:", local_data)
|
||||
else S_YNO("control-enable:", remote_control_enable)
|
||||
else S_STRLIST("control-interface:", control_ifs)
|
||||
|
|
@ -651,6 +655,8 @@ config_get_option(struct config_file* cfg, const char* opt,
|
|||
else O_LST(opt, "control-interface", control_ifs)
|
||||
else O_LST(opt, "domain-insecure", domain_insecure)
|
||||
else O_UNS(opt, "val-override-date", val_date_override)
|
||||
else O_YNO(opt, "minimal-responses", minimal_responses)
|
||||
else O_YNO(opt, "rrset-roundrobin", rrset_roundrobin)
|
||||
/* not here:
|
||||
* outgoing-permit, outgoing-avoid - have list of ports
|
||||
* local-zone - zones and nodefault variables
|
||||
|
|
@ -1079,6 +1085,8 @@ config_apply(struct config_file* config)
|
|||
MAX_TTL = (uint32_t)config->max_ttl;
|
||||
MIN_TTL = (uint32_t)config->min_ttl;
|
||||
EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size;
|
||||
MINIMAL_RESPONSES = config->minimal_responses;
|
||||
RRSET_ROUNDROBIN = config->rrset_roundrobin;
|
||||
log_set_time_asc(config->log_time_ascii);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -290,6 +290,12 @@ struct config_file {
|
|||
|
||||
/** daemonize, i.e. fork into the background. */
|
||||
int do_daemonize;
|
||||
|
||||
/* minimal response when positive answer */
|
||||
int minimal_responses;
|
||||
|
||||
/* RRSet roundrobin */
|
||||
int rrset_roundrobin;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
1983
util/configlexer.c
1983
util/configlexer.c
File diff suppressed because it is too large
Load diff
|
|
@ -241,6 +241,8 @@ control-cert-file{COLON} { YDVAR(1, VAR_CONTROL_CERT_FILE) }
|
|||
python-script{COLON} { YDVAR(1, VAR_PYTHON_SCRIPT) }
|
||||
python{COLON} { YDVAR(0, VAR_PYTHON) }
|
||||
domain-insecure{COLON} { YDVAR(1, VAR_DOMAIN_INSECURE) }
|
||||
minimal-responses{COLON} { YDVAR(1, VAR_MINIMAL_RESPONSES) }
|
||||
rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
|
||||
<INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
|
||||
|
||||
/* Quoted strings. Strip leading and ending quotes */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -161,7 +161,9 @@
|
|||
VAR_SSL_SERVICE_PEM = 379,
|
||||
VAR_SSL_PORT = 380,
|
||||
VAR_FORWARD_FIRST = 381,
|
||||
VAR_STUB_FIRST = 382
|
||||
VAR_STUB_FIRST = 382,
|
||||
VAR_MINIMAL_RESPONSES = 383,
|
||||
VAR_RRSET_ROUNDROBIN = 384
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
|
|
@ -290,6 +292,8 @@
|
|||
#define VAR_SSL_PORT 380
|
||||
#define VAR_FORWARD_FIRST 381
|
||||
#define VAR_STUB_FIRST 382
|
||||
#define VAR_MINIMAL_RESPONSES 383
|
||||
#define VAR_RRSET_ROUNDROBIN 384
|
||||
|
||||
|
||||
|
||||
|
|
@ -306,7 +310,7 @@ typedef union YYSTYPE
|
|||
|
||||
|
||||
/* Line 2068 of yacc.c */
|
||||
#line 310 "util/configparser.h"
|
||||
#line 314 "util/configparser.h"
|
||||
} YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ extern struct config_parser_state* cfg_parser;
|
|||
%token VAR_PREFETCH_KEY VAR_SO_SNDBUF VAR_HARDEN_BELOW_NXDOMAIN
|
||||
%token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM
|
||||
%token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST
|
||||
%token VAR_STUB_FIRST
|
||||
%token VAR_STUB_FIRST VAR_MINIMAL_RESPONSES VAR_RRSET_ROUNDROBIN
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
|
|
@ -160,7 +160,8 @@ content_server: server_num_threads | server_verbosity | server_port |
|
|||
server_edns_buffer_size | server_prefetch | server_prefetch_key |
|
||||
server_so_sndbuf | server_harden_below_nxdomain | server_ignore_cd_flag |
|
||||
server_log_queries | server_tcp_upstream | server_ssl_upstream |
|
||||
server_ssl_service_key | server_ssl_service_pem | server_ssl_port
|
||||
server_ssl_service_key | server_ssl_service_pem | server_ssl_port |
|
||||
server_minimal_responses | server_rrset_roundrobin
|
||||
;
|
||||
stubstart: VAR_STUB_ZONE
|
||||
{
|
||||
|
|
@ -1096,6 +1097,26 @@ server_local_data_ptr: VAR_LOCAL_DATA_PTR STRING_ARG
|
|||
}
|
||||
}
|
||||
;
|
||||
server_minimal_responses: VAR_MINIMAL_RESPONSES STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_minimal_responses:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else cfg_parser->cfg->minimal_responses =
|
||||
(strcmp($2, "yes")==0);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
server_rrset_roundrobin: VAR_RRSET_ROUNDROBIN STRING_ARG
|
||||
{
|
||||
OUTYY(("P(server_rrset_roundrobin:%s)\n", $2));
|
||||
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
|
||||
yyerror("expected yes or no.");
|
||||
else cfg_parser->cfg->rrset_roundrobin =
|
||||
(strcmp($2, "yes")==0);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
stub_name: VAR_NAME STRING_ARG
|
||||
{
|
||||
OUTYY(("P(name:%s)\n", $2));
|
||||
|
|
|
|||
|
|
@ -443,9 +443,9 @@ static int
|
|||
packed_rrset_encode(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
|
||||
uint16_t* num_rrs, uint32_t timenow, struct regional* region,
|
||||
int do_data, int do_sig, struct compress_tree_node** tree,
|
||||
ldns_pkt_section s, uint16_t qtype, int dnssec)
|
||||
ldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset)
|
||||
{
|
||||
size_t i, owner_pos;
|
||||
size_t i, j, owner_pos;
|
||||
int r, owner_labs;
|
||||
uint16_t owner_ptr = 0;
|
||||
struct packed_rrset_data* data = (struct packed_rrset_data*)
|
||||
|
|
@ -461,26 +461,28 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
|
|||
if(do_data) {
|
||||
const ldns_rr_descriptor* c = type_rdata_compressable(key);
|
||||
for(i=0; i<data->count; i++) {
|
||||
/* rrset roundrobin */
|
||||
j = (i + rr_offset) % data->count;
|
||||
if((r=compress_owner(key, pkt, region, tree,
|
||||
owner_pos, &owner_ptr, owner_labs))
|
||||
!= RETVAL_OK)
|
||||
return r;
|
||||
ldns_buffer_write(pkt, &key->rk.type, 2);
|
||||
ldns_buffer_write(pkt, &key->rk.rrset_class, 2);
|
||||
if(data->rr_ttl[i] < timenow)
|
||||
if(data->rr_ttl[j] < timenow)
|
||||
ldns_buffer_write_u32(pkt, 0);
|
||||
else ldns_buffer_write_u32(pkt,
|
||||
data->rr_ttl[i]-timenow);
|
||||
data->rr_ttl[j]-timenow);
|
||||
if(c) {
|
||||
if((r=compress_rdata(pkt, data->rr_data[i],
|
||||
data->rr_len[i], region, tree, c))
|
||||
if((r=compress_rdata(pkt, data->rr_data[j],
|
||||
data->rr_len[j], region, tree, c))
|
||||
!= RETVAL_OK)
|
||||
return r;
|
||||
} else {
|
||||
if(ldns_buffer_remaining(pkt) < data->rr_len[i])
|
||||
if(ldns_buffer_remaining(pkt) < data->rr_len[j])
|
||||
return RETVAL_TRUNC;
|
||||
ldns_buffer_write(pkt, data->rr_data[i],
|
||||
data->rr_len[i]);
|
||||
ldns_buffer_write(pkt, data->rr_data[j],
|
||||
data->rr_len[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -528,7 +530,7 @@ static int
|
|||
insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
||||
ldns_buffer* pkt, size_t rrsets_before, uint32_t timenow,
|
||||
struct regional* region, struct compress_tree_node** tree,
|
||||
ldns_pkt_section s, uint16_t qtype, int dnssec)
|
||||
ldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset)
|
||||
{
|
||||
int r;
|
||||
size_t i, setstart;
|
||||
|
|
@ -540,7 +542,7 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
|||
setstart = ldns_buffer_position(pkt);
|
||||
if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i],
|
||||
pkt, num_rrs, timenow, region, 1, 1, tree,
|
||||
s, qtype, dnssec))
|
||||
s, qtype, dnssec, rr_offset))
|
||||
!= RETVAL_OK) {
|
||||
/* Bad, but if due to size must set TC bit */
|
||||
/* trim off the rrset neatly. */
|
||||
|
|
@ -553,7 +555,7 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
|||
setstart = ldns_buffer_position(pkt);
|
||||
if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i],
|
||||
pkt, num_rrs, timenow, region, 1, 0, tree,
|
||||
s, qtype, dnssec))
|
||||
s, qtype, dnssec, rr_offset))
|
||||
!= RETVAL_OK) {
|
||||
ldns_buffer_set_position(pkt, setstart);
|
||||
return r;
|
||||
|
|
@ -564,7 +566,7 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
|||
setstart = ldns_buffer_position(pkt);
|
||||
if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i],
|
||||
pkt, num_rrs, timenow, region, 0, 1, tree,
|
||||
s, qtype, dnssec))
|
||||
s, qtype, dnssec, rr_offset))
|
||||
!= RETVAL_OK) {
|
||||
ldns_buffer_set_position(pkt, setstart);
|
||||
return r;
|
||||
|
|
@ -595,6 +597,31 @@ insert_query(struct query_info* qinfo, struct compress_tree_node** tree,
|
|||
return RETVAL_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
positive_answer(struct reply_info* rep, uint16_t qtype) {
|
||||
size_t i;
|
||||
if (FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NOERROR)
|
||||
return 0;
|
||||
|
||||
for(i=0;i<rep->an_numrrsets; i++) {
|
||||
if(ntohs(rep->rrsets[i]->rk.type) == qtype) {
|
||||
/* in case it is a wildcard with DNSSEC, there will
|
||||
* be NSEC/NSEC3 records in the authority section
|
||||
* that we cannot remove */
|
||||
for(i=rep->an_numrrsets; i<rep->an_numrrsets+
|
||||
rep->ns_numrrsets; i++) {
|
||||
if(ntohs(rep->rrsets[i]->rk.type) ==
|
||||
LDNS_RR_TYPE_NSEC ||
|
||||
ntohs(rep->rrsets[i]->rk.type) ==
|
||||
LDNS_RR_TYPE_NSEC3)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
||||
uint16_t id, uint16_t flags, ldns_buffer* buffer, uint32_t timenow,
|
||||
|
|
@ -603,6 +630,7 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
|||
uint16_t ancount=0, nscount=0, arcount=0;
|
||||
struct compress_tree_node* tree = 0;
|
||||
int r;
|
||||
size_t rr_offset;
|
||||
|
||||
ldns_buffer_clear(buffer);
|
||||
if(udpsize < ldns_buffer_limit(buffer))
|
||||
|
|
@ -630,11 +658,13 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
/* roundrobin offset. using query id for random number */
|
||||
rr_offset = RRSET_ROUNDROBIN?id:0;
|
||||
|
||||
/* insert answer section */
|
||||
if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer,
|
||||
0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype,
|
||||
dnssec)) != RETVAL_OK) {
|
||||
dnssec, rr_offset)) != RETVAL_OK) {
|
||||
if(r == RETVAL_TRUNC) {
|
||||
/* create truncated message */
|
||||
ldns_buffer_write_u16_at(buffer, 6, ancount);
|
||||
|
|
@ -646,35 +676,42 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
|||
}
|
||||
ldns_buffer_write_u16_at(buffer, 6, ancount);
|
||||
|
||||
/* insert auth section */
|
||||
if((r=insert_section(rep, rep->ns_numrrsets, &nscount, buffer,
|
||||
rep->an_numrrsets, timenow, region, &tree,
|
||||
LDNS_SECTION_AUTHORITY, qinfo->qtype, dnssec)) != RETVAL_OK) {
|
||||
if(r == RETVAL_TRUNC) {
|
||||
/* create truncated message */
|
||||
ldns_buffer_write_u16_at(buffer, 8, nscount);
|
||||
LDNS_TC_SET(ldns_buffer_begin(buffer));
|
||||
ldns_buffer_flip(buffer);
|
||||
return 1;
|
||||
/* if response is positive answer, auth/add sections are not required */
|
||||
if( ! (MINIMAL_RESPONSES && positive_answer(rep, qinfo->qtype)) ) {
|
||||
/* insert auth section */
|
||||
if((r=insert_section(rep, rep->ns_numrrsets, &nscount, buffer,
|
||||
rep->an_numrrsets, timenow, region, &tree,
|
||||
LDNS_SECTION_AUTHORITY, qinfo->qtype,
|
||||
dnssec, rr_offset)) != RETVAL_OK) {
|
||||
if(r == RETVAL_TRUNC) {
|
||||
/* create truncated message */
|
||||
ldns_buffer_write_u16_at(buffer, 8, nscount);
|
||||
LDNS_TC_SET(ldns_buffer_begin(buffer));
|
||||
ldns_buffer_flip(buffer);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ldns_buffer_write_u16_at(buffer, 8, nscount);
|
||||
ldns_buffer_write_u16_at(buffer, 8, nscount);
|
||||
|
||||
/* insert add section */
|
||||
if((r=insert_section(rep, rep->ar_numrrsets, &arcount, buffer,
|
||||
rep->an_numrrsets + rep->ns_numrrsets, timenow, region,
|
||||
&tree, LDNS_SECTION_ADDITIONAL, qinfo->qtype,
|
||||
dnssec)) != RETVAL_OK) {
|
||||
if(r == RETVAL_TRUNC) {
|
||||
/* no need to set TC bit, this is the additional */
|
||||
ldns_buffer_write_u16_at(buffer, 10, arcount);
|
||||
ldns_buffer_flip(buffer);
|
||||
return 1;
|
||||
/* insert add section */
|
||||
if((r=insert_section(rep, rep->ar_numrrsets, &arcount, buffer,
|
||||
rep->an_numrrsets + rep->ns_numrrsets, timenow, region,
|
||||
&tree, LDNS_SECTION_ADDITIONAL, qinfo->qtype,
|
||||
dnssec, rr_offset)) != RETVAL_OK) {
|
||||
if(r == RETVAL_TRUNC) {
|
||||
/* no need to set TC bit, this is the additional */
|
||||
ldns_buffer_write_u16_at(buffer, 10, arcount);
|
||||
ldns_buffer_flip(buffer);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
ldns_buffer_write_u16_at(buffer, 10, arcount);
|
||||
} else {
|
||||
ldns_buffer_write_u16_at(buffer, 8, nscount);
|
||||
ldns_buffer_write_u16_at(buffer, 10, arcount);
|
||||
}
|
||||
ldns_buffer_write_u16_at(buffer, 10, arcount);
|
||||
ldns_buffer_flip(buffer);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,12 @@
|
|||
/** default value for EDNS ADVERTISED size */
|
||||
uint16_t EDNS_ADVERTISED_SIZE = 4096;
|
||||
|
||||
/** minimal responses when positive answer: default is no */
|
||||
int MINIMAL_RESPONSES = 0;
|
||||
|
||||
/** rrset order roundrobin: default is no */
|
||||
int RRSET_ROUNDROBIN = 0;
|
||||
|
||||
/* returns true is string addr is an ip6 specced address */
|
||||
int
|
||||
str_is_ip6(const char* str)
|
||||
|
|
|
|||
|
|
@ -93,6 +93,12 @@ extern uint16_t EDNS_ADVERTISED_SIZE;
|
|||
/** DNSKEY secure entry point, KSK flag */
|
||||
#define DNSKEY_BIT_SEP 0x0001
|
||||
|
||||
/** minimal responses when positive answer */
|
||||
extern int MINIMAL_RESPONSES;
|
||||
|
||||
/** rrset order roundrobin */
|
||||
extern int RRSET_ROUNDROBIN;
|
||||
|
||||
/**
|
||||
* See if string is ip4 or ip6.
|
||||
* @param str: IP specification.
|
||||
|
|
|
|||
Loading…
Reference in a new issue