Paul Wouters afe9ba0
Index: services/outside_network.c
Paul Wouters afe9ba0
===================================================================
Paul Wouters afe9ba0
--- services/outside_network.c	(revision 2491)
Paul Wouters afe9ba0
+++ services/outside_network.c	(revision 2493)
Paul Wouters afe9ba0
@@ -1199,6 +1199,7 @@
Paul Wouters afe9ba0
 		if(sq->status == serviced_query_UDP_EDNS ||
Paul Wouters afe9ba0
 			sq->status == serviced_query_UDP ||
Paul Wouters afe9ba0
 			sq->status == serviced_query_PROBE_EDNS ||
Paul Wouters afe9ba0
+			sq->status == serviced_query_UDP_EDNS_FRAG ||
Paul Wouters afe9ba0
 			sq->status == serviced_query_UDP_EDNS_fallback) {
Paul Wouters afe9ba0
 			struct pending* p = (struct pending*)sq->pending;
Paul Wouters afe9ba0
 			if(p->pc)
Paul Wouters afe9ba0
@@ -1280,7 +1281,19 @@
Paul Wouters afe9ba0
 		edns.edns_present = 1;
Paul Wouters afe9ba0
 		edns.ext_rcode = 0;
Paul Wouters afe9ba0
 		edns.edns_version = EDNS_ADVERTISED_VERSION;
Paul Wouters afe9ba0
-		edns.udp_size = EDNS_ADVERTISED_SIZE;
Paul Wouters afe9ba0
+		if(sq->status == serviced_query_UDP_EDNS_FRAG) {
Paul Wouters afe9ba0
+			if(addr_is_ip6(&sq->addr, sq->addrlen)) {
Paul Wouters afe9ba0
+				if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE)
Paul Wouters afe9ba0
+					edns.udp_size = EDNS_FRAG_SIZE_IP6;
Paul Wouters afe9ba0
+				else	edns.udp_size = EDNS_ADVERTISED_SIZE;
Paul Wouters afe9ba0
+			} else {
Paul Wouters afe9ba0
+				if(EDNS_FRAG_SIZE_IP4 < EDNS_ADVERTISED_SIZE)
Paul Wouters afe9ba0
+					edns.udp_size = EDNS_FRAG_SIZE_IP4;
Paul Wouters afe9ba0
+				else	edns.udp_size = EDNS_ADVERTISED_SIZE;
Paul Wouters afe9ba0
+			}
Paul Wouters afe9ba0
+		} else {
Paul Wouters afe9ba0
+			edns.udp_size = EDNS_ADVERTISED_SIZE;
Paul Wouters afe9ba0
+		}
Paul Wouters afe9ba0
 		edns.bits = 0;
Paul Wouters afe9ba0
 		if(sq->dnssec & EDNS_DO)
Paul Wouters afe9ba0
 			edns.bits = EDNS_DO;
Paul Wouters afe9ba0
@@ -1324,7 +1337,8 @@
Paul Wouters afe9ba0
 			sq->status = serviced_query_UDP; 
Paul Wouters afe9ba0
 		}
Paul Wouters afe9ba0
 	}
Paul Wouters afe9ba0
-	serviced_encode(sq, buff, sq->status == serviced_query_UDP_EDNS);
Paul Wouters afe9ba0
+	serviced_encode(sq, buff, (sq->status == serviced_query_UDP_EDNS) ||
Paul Wouters afe9ba0
+		(sq->status == serviced_query_UDP_EDNS_FRAG));
Paul Wouters afe9ba0
 	sq->last_sent_time = *sq->outnet->now_tv;
Paul Wouters afe9ba0
 	sq->edns_lame_known = (int)edns_lame_known;
Paul Wouters afe9ba0
 	verbose(VERB_ALGO, "serviced query UDP timeout=%d msec", rtt);
Paul Wouters afe9ba0
@@ -1564,6 +1578,20 @@
Paul Wouters afe9ba0
 			 * by EDNS. */
Paul Wouters afe9ba0
 			sq->status = serviced_query_UDP_EDNS;
Paul Wouters afe9ba0
 		}
Paul Wouters afe9ba0
+		if(sq->status == serviced_query_UDP_EDNS) {
Paul Wouters afe9ba0
+			/* fallback to 1480/1280 */
Paul Wouters afe9ba0
+			sq->status = serviced_query_UDP_EDNS_FRAG;
Paul Wouters afe9ba0
+			log_name_addr(VERB_ALGO, "try edns1xx0", sq->qbuf+10,
Paul Wouters afe9ba0
+				&sq->addr, sq->addrlen);
Paul Wouters afe9ba0
+			if(!serviced_udp_send(sq, c->buffer)) {
Paul Wouters afe9ba0
+				serviced_callbacks(sq, NETEVENT_CLOSED, c, rep);
Paul Wouters afe9ba0
+			}
Paul Wouters afe9ba0
+			return 0;
Paul Wouters afe9ba0
+		}
Paul Wouters afe9ba0
+		if(sq->status == serviced_query_UDP_EDNS_FRAG) {
Paul Wouters afe9ba0
+			/* fragmentation size did not fix it */
Paul Wouters afe9ba0
+			sq->status = serviced_query_UDP_EDNS;
Paul Wouters afe9ba0
+		}
Paul Wouters afe9ba0
 		sq->retry++;
Paul Wouters afe9ba0
 		if(!(rto=infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
Paul Wouters afe9ba0
 			-1, sq->last_rtt, (uint32_t)now.tv_sec)))
Paul Wouters afe9ba0
@@ -1589,7 +1617,8 @@
Paul Wouters afe9ba0
 		return 0;
Paul Wouters afe9ba0
 	}
Paul Wouters afe9ba0
 	if(!fallback_tcp) {
Paul Wouters afe9ba0
-	    if(sq->status == serviced_query_UDP_EDNS 
Paul Wouters afe9ba0
+	    if( (sq->status == serviced_query_UDP_EDNS 
Paul Wouters afe9ba0
+	        ||sq->status == serviced_query_UDP_EDNS_FRAG)
Paul Wouters afe9ba0
 		&& (LDNS_RCODE_WIRE(ldns_buffer_begin(c->buffer)) 
Paul Wouters afe9ba0
 			== LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(
Paul Wouters afe9ba0
 			ldns_buffer_begin(c->buffer)) == LDNS_RCODE_NOTIMPL)) {
Paul Wouters afe9ba0
@@ -1866,6 +1895,7 @@
Paul Wouters afe9ba0
 	if(sq->status == serviced_query_UDP_EDNS ||
Paul Wouters afe9ba0
 		sq->status == serviced_query_UDP ||
Paul Wouters afe9ba0
 		sq->status == serviced_query_PROBE_EDNS ||
Paul Wouters afe9ba0
+		sq->status == serviced_query_UDP_EDNS_FRAG ||
Paul Wouters afe9ba0
 		sq->status == serviced_query_UDP_EDNS_fallback) {
Paul Wouters afe9ba0
 		s += sizeof(struct pending);
Paul Wouters afe9ba0
 		s += comm_timer_get_mem(NULL);
Paul Wouters afe9ba0
Index: services/outside_network.h
Paul Wouters afe9ba0
===================================================================
Paul Wouters afe9ba0
--- services/outside_network.h	(revision 2491)
Paul Wouters afe9ba0
+++ services/outside_network.h	(revision 2493)
Paul Wouters afe9ba0
@@ -274,6 +274,11 @@
Paul Wouters afe9ba0
 	void* cb_arg;
Paul Wouters afe9ba0
 };
Paul Wouters afe9ba0
 
Paul Wouters afe9ba0
+/** fallback size for fragmentation for EDNS in IPv4 */
Paul Wouters afe9ba0
+#define EDNS_FRAG_SIZE_IP4 1480
Paul Wouters afe9ba0
+/** fallback size for EDNS in IPv6, fits one fragment with ip6-tunnel-ids */
Paul Wouters afe9ba0
+#define EDNS_FRAG_SIZE_IP6 1260
Paul Wouters afe9ba0
+
Paul Wouters afe9ba0
 /**
Paul Wouters afe9ba0
  * Query service record.
Paul Wouters afe9ba0
  * Contains query and destination. UDP, TCP, EDNS are all tried.
Paul Wouters afe9ba0
@@ -314,7 +319,9 @@
Paul Wouters afe9ba0
 		/** probe to test noEDNS0 (EDNS gives FORMERRorNOTIMP) */
Paul Wouters afe9ba0
 		serviced_query_UDP_EDNS_fallback,
Paul Wouters afe9ba0
 		/** probe to test TCP noEDNS0 (EDNS gives FORMERRorNOTIMP) */
Paul Wouters afe9ba0
-		serviced_query_TCP_EDNS_fallback
Paul Wouters afe9ba0
+		serviced_query_TCP_EDNS_fallback,
Paul Wouters afe9ba0
+		/** send UDP query with EDNS1480 (or 1280) */
Paul Wouters afe9ba0
+		serviced_query_UDP_EDNS_FRAG
Paul Wouters afe9ba0
 	} 	
Paul Wouters afe9ba0
 		/** variable with current status */ 
Paul Wouters afe9ba0
 		status;