Index: unbound-1.4.22/daemon/worker.c
===================================================================
--- unbound-1.4.22.orig/daemon/worker.c	2014-06-26 07:33:09.000000000 +0200
+++ unbound-1.4.22/daemon/worker.c	2014-06-26 07:35:47.000000000 +0200
@@ -1291,8 +1291,8 @@
 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(
@@ -1301,7 +1301,7 @@
 		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);
@@ -1347,7 +1347,7 @@
 	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), struct module_qstate* ATTR_UNUSED(q))
 {
 	log_assert(0);
Index: unbound-1.4.22/daemon/worker.h
===================================================================
--- unbound-1.4.22.orig/daemon/worker.h	2014-06-26 07:33:09.000000000 +0200
+++ unbound-1.4.22/daemon/worker.h	2014-06-26 07:35:09.000000000 +0200
@@ -173,6 +173,7 @@
  * @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: do not use capsforid.
  * @param addr: where to.
  * @param addrlen: length of addr.
  * @param zone: wireformat dname of the zone.
@@ -183,8 +184,9 @@
  */
 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 
Index: unbound-1.4.22/iterator/iterator.c
===================================================================
--- unbound-1.4.22.orig/iterator/iterator.c	2014-06-26 07:33:09.000000000 +0200
+++ unbound-1.4.22/iterator/iterator.c	2014-06-26 07:35:09.000000000 +0200
@@ -1846,8 +1846,8 @@
 		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);
@@ -2757,6 +2757,21 @@
 	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)
@@ -2805,7 +2820,7 @@
 		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;
@@ -2817,7 +2832,11 @@
 			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");
Index: unbound-1.4.22/iterator/iterator.h
===================================================================
--- unbound-1.4.22.orig/iterator/iterator.h	2014-06-26 07:33:09.000000000 +0200
+++ unbound-1.4.22/iterator/iterator.h	2014-06-26 07:35:09.000000000 +0200
@@ -234,7 +234,8 @@
 	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 */
Index: unbound-1.4.22/libunbound/libworker.c
===================================================================
--- unbound-1.4.22.orig/libunbound/libworker.c	2014-06-26 07:33:09.000000000 +0200
+++ unbound-1.4.22/libunbound/libworker.c	2014-06-26 07:35:39.000000000 +0200
@@ -819,8 +819,9 @@
 
 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(
@@ -829,7 +830,7 @@
 		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);
@@ -951,7 +952,7 @@
 	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), struct module_qstate* ATTR_UNUSED(q))
 {
 	log_assert(0);
Index: unbound-1.4.22/libunbound/libworker.h
===================================================================
--- unbound-1.4.22.orig/libunbound/libworker.h	2014-06-26 07:33:09.000000000 +0200
+++ unbound-1.4.22/libunbound/libworker.h	2014-06-26 07:35:09.000000000 +0200
@@ -145,6 +145,7 @@
  * @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.
@@ -155,8 +156,9 @@
  */
 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,
Index: unbound-1.4.22/services/outside_network.c
===================================================================
--- unbound-1.4.22.orig/services/outside_network.c	2014-06-26 07:33:09.000000000 +0200
+++ unbound-1.4.22/services/outside_network.c	2014-06-26 07:35:09.000000000 +0200
@@ -1205,7 +1205,7 @@
 /** 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)
 {
@@ -1232,6 +1232,7 @@
 	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);
@@ -1349,7 +1350,7 @@
 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 */
@@ -1827,10 +1828,11 @@
 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;
@@ -1843,7 +1845,7 @@
 		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) {
Index: unbound-1.4.22/services/outside_network.h
===================================================================
--- unbound-1.4.22.orig/services/outside_network.h	2014-06-26 07:33:09.000000000 +0200
+++ unbound-1.4.22/services/outside_network.h	2014-06-26 07:35:09.000000000 +0200
@@ -307,6 +307,8 @@
 	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 */
@@ -464,6 +466,7 @@
  *	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.
@@ -480,10 +483,11 @@
  */
 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.
Index: unbound-1.4.22/smallapp/worker_cb.c
===================================================================
--- unbound-1.4.22.orig/smallapp/worker_cb.c	2014-06-26 07:33:09.000000000 +0200
+++ unbound-1.4.22/smallapp/worker_cb.c	2014-06-26 07:35:29.000000000 +0200
@@ -104,7 +104,7 @@
 	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), struct module_qstate* ATTR_UNUSED(q))
 {
 	log_assert(0);
@@ -135,7 +135,7 @@
 	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), struct module_qstate* ATTR_UNUSED(q))
 {
 	log_assert(0);
Index: unbound-1.4.22/testcode/fake_event.c
===================================================================
--- unbound-1.4.22.orig/testcode/fake_event.c	2014-06-26 07:33:09.000000000 +0200
+++ unbound-1.4.22/testcode/fake_event.c	2014-06-26 07:35:09.000000000 +0200
@@ -1037,9 +1037,10 @@
 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;
Index: unbound-1.4.22/util/fptr_wlist.c
===================================================================
--- unbound-1.4.22.orig/util/fptr_wlist.c	2014-06-26 07:33:09.000000000 +0200
+++ unbound-1.4.22/util/fptr_wlist.c	2014-06-26 07:35:09.000000000 +0200
@@ -259,7 +259,7 @@
 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))
Index: unbound-1.4.22/util/fptr_wlist.h
===================================================================
--- unbound-1.4.22.orig/util/fptr_wlist.h	2014-06-26 07:33:09.000000000 +0200
+++ unbound-1.4.22/util/fptr_wlist.h	2014-06-26 07:35:09.000000000 +0200
@@ -211,7 +211,7 @@
  */
 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));
Index: unbound-1.4.22/util/module.h
===================================================================
--- unbound-1.4.22.orig/util/module.h	2014-06-26 07:33:09.000000000 +0200
+++ unbound-1.4.22/util/module.h	2014-06-26 07:35:56.000000000 +0200
@@ -212,6 +212,8 @@
 	 *	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.
@@ -224,7 +226,7 @@
 	 */
 	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);
 
