struct outbound_entry*
worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
uint16_t qclass, uint16_t flags, int dnssec, int want_dnssec,
- struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, struct module_qstate* q)
+ int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
+ uint8_t* zone, size_t zonelen, struct module_qstate* q)
{
struct worker* worker = q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
return NULL;
e->qstate = q;
e->qsent = outnet_serviced_query(worker->back, qname,
- qnamelen, qtype, qclass, flags, dnssec, want_dnssec,
+ qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps,
q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
addrlen, zone, zonelen, worker_handle_service_reply, e,
worker->back->udp_buff);
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- struct sockaddr_storage* ATTR_UNUSED(addr),
+ int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
{
+24 June 2014: Wouter
+ - Fix caps-for-id fallback, and added fallback attempt when servers
+ drop 0x20 perturbed queries.
+
17 June 2014: Wouter
- iana portlist updated.
iq->qchase.qname, iq->qchase.qname_len,
iq->qchase.qtype, iq->qchase.qclass,
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), EDNS_DO|BIT_CD,
- iq->dnssec_expected, &target->addr, target->addrlen,
- iq->dp->name, iq->dp->namelen, qstate);
+ iq->dnssec_expected, iq->caps_fallback, &target->addr,
+ target->addrlen, iq->dp->name, iq->dp->namelen, qstate);
if(!outq) {
log_addr(VERB_DETAIL, "error sending query to auth server",
&target->addr, target->addrlen);
iq->response = NULL;
iq->state = QUERY_RESP_STATE;
if(event == module_event_noreply || event == module_event_error) {
+ if(event == module_event_noreply && iq->sent_count >= 3 &&
+ qstate->env->cfg->use_caps_bits_for_id &&
+ !iq->caps_fallback) {
+ /* start fallback */
+ iq->caps_fallback = 1;
+ iq->caps_server = 0;
+ iq->caps_reply = NULL;
+ iq->state = QUERYTARGETS_STATE;
+ iq->num_current_queries--;
+ /* need fresh attempts for the 0x20 fallback, if
+ * that was the cause for the failure */
+ iter_dec_attempts(iq->dp, 3);
+ verbose(VERB_DETAIL, "Capsforid: timeouts, starting fallback");
+ goto handle_it;
+ }
goto handle_it;
}
if( (event != module_event_reply && event != module_event_capsfail)
log_dns_msg("incoming scrubbed packet:", &iq->response->qinfo,
iq->response->rep);
- if(event == module_event_capsfail) {
+ if(event == module_event_capsfail || iq->caps_fallback) {
if(!iq->caps_fallback) {
/* start fallback */
iq->caps_fallback = 1;
goto handle_it;
} else {
/* check if reply is the same, otherwise, fail */
- if(!reply_equal(iq->response->rep, iq->caps_reply,
+ if(!iq->caps_reply) {
+ iq->caps_reply = iq->response->rep;
+ iq->caps_server = -1; /*become zero at ++,
+ so that we start the full set of trials */
+ } else if(!reply_equal(iq->response->rep, iq->caps_reply,
qstate->env->scratch)) {
verbose(VERB_DETAIL, "Capsforid fallback: "
"getting different replies, failed");
int caps_fallback;
/** state for capsfail: current server number to try */
size_t caps_server;
- /** state for capsfail: stored query for comparisons */
+ /** state for capsfail: stored query for comparisons. Can be NULL if
+ * no response had been seen prior to starting the fallback. */
struct reply_info* caps_reply;
/** Current delegation message - returned for non-RD queries */
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
- int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen, struct module_qstate* q)
+ int want_dnssec, int nocaps, struct sockaddr_storage* addr,
+ socklen_t addrlen, uint8_t* zone, size_t zonelen,
+ struct module_qstate* q)
{
struct libworker* w = (struct libworker*)q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
return NULL;
e->qstate = q;
e->qsent = outnet_serviced_query(w->back, qname,
- qnamelen, qtype, qclass, flags, dnssec, want_dnssec,
+ qnamelen, qtype, qclass, flags, dnssec, want_dnssec, nocaps,
q->env->cfg->tcp_upstream, q->env->cfg->ssl_upstream, addr,
addrlen, zone, zonelen, libworker_handle_service_reply, e,
w->back->udp_buff);
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- struct sockaddr_storage* ATTR_UNUSED(addr),
+ int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
{
* @param flags: host order flags word, with opcode and CD bit.
* @param dnssec: if set, EDNS record will have DO bit set.
* @param want_dnssec: signatures needed.
+ * @param nocaps: ignore capsforid(if in config), do not perturb qname.
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: delegation point name.
*/
struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
- int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen, struct module_qstate* q);
+ int want_dnssec, int nocaps, struct sockaddr_storage* addr,
+ socklen_t addrlen, uint8_t* zone, size_t zonelen,
+ struct module_qstate* q);
/** process incoming replies from the network */
int libworker_handle_reply(struct comm_point* c, void* arg, int error,
* @param flags: host order flags word, with opcode and CD bit.
* @param dnssec: if set, EDNS record will have DO bit set.
* @param want_dnssec: signatures needed.
+ * @param nocaps: ignore capsforid(if in config), do not perturb qname.
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: wireformat dname of the zone.
*/
struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
- int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen, struct module_qstate* q);
+ int want_dnssec, int nocaps, struct sockaddr_storage* addr,
+ socklen_t addrlen, uint8_t* zone, size_t zonelen,
+ struct module_qstate* q);
/**
* process control messages from the main thread. Frees the control
/** Create new serviced entry */
static struct serviced_query*
serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
- int want_dnssec, int tcp_upstream, int ssl_upstream,
+ int want_dnssec, int nocaps, int tcp_upstream, int ssl_upstream,
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
size_t zonelen, int qtype)
{
sq->qtype = qtype;
sq->dnssec = dnssec;
sq->want_dnssec = want_dnssec;
+ sq->nocaps = nocaps;
sq->tcp_upstream = tcp_upstream;
sq->ssl_upstream = ssl_upstream;
memcpy(&sq->addr, addr, addrlen);
serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns)
{
/* if we are using 0x20 bits for ID randomness, perturb them */
- if(sq->outnet->use_caps_for_id) {
+ if(sq->outnet->use_caps_for_id && !sq->nocaps) {
serviced_perturb_qname(sq->outnet->rnd, sq->qbuf, sq->qbuflen);
}
/* generate query */
struct serviced_query*
outnet_serviced_query(struct outside_network* outnet,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
- uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream,
- int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen, comm_point_callback_t* callback,
- void* callback_arg, sldns_buffer* buff)
+ uint16_t flags, int dnssec, int want_dnssec, int nocaps,
+ int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr,
+ socklen_t addrlen, uint8_t* zone, size_t zonelen,
+ comm_point_callback_t* callback, void* callback_arg,
+ sldns_buffer* buff)
{
struct serviced_query* sq;
struct service_callback* cb;
return NULL;
if(!sq) {
/* make new serviced query entry */
- sq = serviced_create(outnet, buff, dnssec, want_dnssec,
+ sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps,
tcp_upstream, ssl_upstream, addr, addrlen, zone,
zonelen, (int)qtype);
if(!sq) {
int dnssec;
/** We want signatures, or else the answer is likely useless */
int want_dnssec;
+ /** ignore capsforid */
+ int nocaps;
/** tcp upstream used, use tcp, or ssl_upstream for SSL */
int tcp_upstream, ssl_upstream;
/** where to send it */
* If the value includes BIT_DO, DO bit is set when in EDNS queries.
* @param want_dnssec: signatures are needed, without EDNS the answer is
* likely to be useless.
+ * @param nocaps: ignore use_caps_for_id and use unperturbed qname.
* @param tcp_upstream: use TCP for upstream queries.
* @param ssl_upstream: use SSL for upstream queries.
* @param callback: callback function.
*/
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
- uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream,
- int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen,
- uint8_t* zone, size_t zonelen, comm_point_callback_t* callback,
- void* callback_arg, struct sldns_buffer* buff);
+ uint16_t flags, int dnssec, int want_dnssec, int nocaps,
+ int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr,
+ socklen_t addrlen, uint8_t* zone, size_t zonelen,
+ comm_point_callback_t* callback, void* callback_arg,
+ struct sldns_buffer* buff);
/**
* Remove service query callback.
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- struct sockaddr_storage* ATTR_UNUSED(addr),
+ int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
{
size_t ATTR_UNUSED(qnamelen), uint16_t ATTR_UNUSED(qtype),
uint16_t ATTR_UNUSED(qclass), uint16_t ATTR_UNUSED(flags),
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
- struct sockaddr_storage* ATTR_UNUSED(addr),
+ int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
size_t ATTR_UNUSED(zonelen), struct module_qstate* ATTR_UNUSED(q))
{
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, int ATTR_UNUSED(want_dnssec),
- int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
- struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
- size_t zonelen, comm_point_callback_t* callback, void* callback_arg,
+ int ATTR_UNUSED(nocaps), int ATTR_UNUSED(tcp_upstream),
+ int ATTR_UNUSED(ssl_upstream), struct sockaddr_storage* addr,
+ socklen_t addrlen, uint8_t* zone, size_t zonelen,
+ comm_point_callback_t* callback, void* callback_arg,
sldns_buffer* ATTR_UNUSED(buff))
{
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
int
fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
- uint16_t flags, int dnssec, int want_dnssec,
+ uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen,
struct module_qstate* q))
*/
int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
- uint16_t flags, int dnssec, int want_dnssec,
+ uint16_t flags, int dnssec, int want_dnssec, int nocaps,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* zone, size_t zonelen,
struct module_qstate* q));
* If BIT_CD is set, CD bit is set in queries with EDNS records.
* @param want_dnssec: if set, the validator wants DNSSEC. Without
* EDNS, the answer is likely to be useless for this domain.
+ * @param nocaps: do not use caps_for_id, use the qname as given.
+ * (ignored if caps_for_id is disabled).
* @param addr: where to.
* @param addrlen: length of addr.
* @param zone: delegation point name.
*/
struct outbound_entry* (*send_query)(uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec,
- int want_dnssec, struct sockaddr_storage* addr,
+ int want_dnssec, int nocaps, struct sockaddr_storage* addr,
socklen_t addrlen, uint8_t* zone, size_t zonelen,
struct module_qstate* q);