1 #include "e.h"
2 #include "roots.h"
3 #include "log.h"
4 #include "case.h"
5 #include "cache.h"
6 #include "byte.h"
7 #include "dns.h"
8 #include "uint32_unpack_big.h"
9 #include "uint16_unpack_big.h"
10 #include "alloc.h"
11 #include "response.h"
12 #include "query.h"
13 #include "strtoip.h"
14 #include "iptostr.h"
15 #include "xsocket.h"
16 #include "crypto.h"
17 #include "purge.h"
18 
19 static unsigned char secretkey[32];
20 static unsigned char publickey[32];
21 
query_init(const unsigned char * sk)22 void query_init(const unsigned char *sk)
23 {
24   byte_copy(secretkey,32,sk);
25   crypto_scalarmult_curve25519_base(publickey, secretkey);
26   log_dnscurvekey(publickey);
27   return;
28 }
29 
query_purge(void)30 void query_purge(void) {
31     purge(secretkey, sizeof secretkey);
32     purge(publickey, sizeof publickey);
33 }
34 
35 static int flagforwardonly = 0;
36 
query_forwardonly(void)37 void query_forwardonly(void)
38 {
39   flagforwardonly = 1;
40 }
41 
42 static int flagtcponly = 0;
43 
query_tcponly(void)44 void query_tcponly(void) {
45     flagtcponly = 1;
46 }
47 
48 static int flagipv4only = 0;
49 
query_ipv4only(void)50 void query_ipv4only(void) {
51     flagipv4only = 1;
52 }
53 
54 static crypto_uint32 minttl = 0;
55 
query_minttl(long long x)56 void query_minttl(long long x) {
57     if (x < 0) x = 0;
58     if (x > 300) x = 300;
59     minttl = x;
60 }
61 
62 unsigned char remoteport[2] = { 0, 53 };
query_remoteport(unsigned char * port)63 void query_remoteport(unsigned char *port) {
64     byte_copy(remoteport, 2, port);
65 }
66 
67 static int flagdnscurvetype1 = 1;
68 static int flagdnscurvetype2 = 2;
69 
query_dnscurvetype(char * x)70 void query_dnscurvetype(char *x)
71 {
72   if (!x) return;
73 
74   if (*x == '1') {
75     /* streamlined only */
76     flagdnscurvetype1 = 1;
77     flagdnscurvetype2 = 0;
78   }
79   else if (*x == '2') {
80     /* txt only */
81     flagdnscurvetype1 = 2;
82     flagdnscurvetype2 = 0;
83   }
84   else {
85     /* mixed */
86     flagdnscurvetype1 = 1;
87     flagdnscurvetype2 = 2;
88   }
89 }
90 
cachegeneric(const unsigned char type[2],const unsigned char * d,const unsigned char * data,long long datalen,crypto_uint32 ttl,unsigned char flagns)91 static void cachegeneric(const unsigned char type[2],const unsigned char *d,const unsigned char *data,long long datalen,crypto_uint32 ttl, unsigned char flagns)
92 {
93   long long len;
94   unsigned char key[257];
95 
96   len = dns_domain_length(d);
97   if (len > 255) return;
98 
99   byte_copy(key,2,type);
100   byte_copy(key + 2,len,d);
101   case_lowerb(key + 2,len);
102 
103   cache_set(key,len + 2,data,datalen,ttl,flagns);
104 }
105 
cachegeneric2(const unsigned char type[2],const unsigned char dtype[2],const unsigned char * d,const unsigned char * data,long long datalen,crypto_uint32 ttl,unsigned char flagns)106 static void cachegeneric2(const unsigned char type[2],const unsigned char dtype[2], const unsigned char *d,const unsigned char *data,long long datalen,crypto_uint32 ttl, unsigned char flagns)
107 {
108   long long len;
109   unsigned char key[259];
110 
111   len = dns_domain_length(d);
112   if (len > 255) return;
113 
114   byte_copy(key,2,type);
115   byte_copy(key + 2,len,d);
116   byte_copy(key + 2 + len,2,dtype);
117   case_lowerb(key + 2,len);
118 
119   cache_set(key,len + 4,data,datalen,ttl,flagns);
120 }
121 
122 
123 static unsigned char save_buf[8192];
124 static long long save_len;
125 static long long save_ok;
126 
save_start(void)127 static void save_start(void)
128 {
129   save_len = 0;
130   save_ok = 1;
131 }
132 
save_data(const unsigned char * buf,long long len)133 static void save_data(const unsigned char *buf,long long len)
134 {
135   if (!save_ok) return;
136   if (len > (sizeof save_buf) - save_len) { save_ok = 0; return; }
137   byte_copy(save_buf + save_len,len,buf);
138   save_len += len;
139 }
140 
save_finish(const unsigned char type[2],const unsigned char * d,crypto_uint32 ttl,unsigned char flagns)141 static void save_finish(const unsigned char type[2],const unsigned char *d,crypto_uint32 ttl,unsigned char flagns)
142 {
143   if (!save_ok) return;
144   cachegeneric(type,d,save_buf,save_len,ttl,flagns);
145 }
146 
typematch(const unsigned char rtype[2],const unsigned char qtype[2])147 static int typematch(const unsigned char rtype[2],const unsigned char qtype[2])
148 {
149   return byte_isequal(qtype,2,rtype) || byte_isequal(qtype,2,DNS_T_ANY);
150 }
151 
ttlget(unsigned char buf[4])152 static long long ttlget(unsigned char buf[4])
153 {
154   crypto_uint32 ttl;
155 
156   ttl=uint32_unpack_big(buf);
157   if (ttl < minttl) ttl = minttl;
158   if (ttl > 1000000000) return 0;
159   if (ttl > 604800) return 604800;
160   return ttl;
161 }
162 
163 
cleanup(struct query * z)164 static void cleanup(struct query *z)
165 {
166   int j;
167   int k;
168 
169   dns_transmit_free(&z->dt);
170   for (j = 0;j < QUERY_MAXALIAS;++j)
171     dns_domain_free(&z->alias[j]);
172   for (j = 0;j < QUERY_MAXLEVEL;++j) {
173     dns_domain_free(&z->name[j]);
174     for (k = 0;k < QUERY_MAXNS;++k)
175       dns_domain_free(&z->ns[j][k]);
176   }
177 }
178 
rqa(struct query * z)179 static int rqa(struct query *z)
180 {
181   int i;
182 
183   for (i = QUERY_MAXALIAS - 1;i >= 0;--i)
184     if (z->alias[i]) {
185       if (!response_query(z->alias[i],z->type,z->class)) return 0;
186       while (i > 0) {
187         if (!response_cname(z->alias[i],z->alias[i - 1],z->aliasttl[i])) return 0;
188         --i;
189       }
190       if (!response_cname(z->alias[0],z->name[0],z->aliasttl[0])) return 0;
191       return 1;
192     }
193 
194   if (!response_query(z->name[0],z->type,z->class)) return 0;
195   return 1;
196 }
197 
dtis(char * out,long long outlen,const unsigned char * d)198 static int dtis(char *out, long long outlen, const unsigned char *d) {
199 
200     long long pos = 0;
201     char ch;
202     char ch2;
203 
204     if (!*d) return 0;
205 
206     for (;;) {
207         ch = *d++;
208         while (ch--) {
209             ch2 = *d++;
210             if (((ch2 >= '0') && (ch2 <= '9')) || (ch2 == ':')) {
211                 if (pos >= outlen) return 0;
212                 out[pos++] = ch2;
213                 continue;
214             }
215             return 0;
216         }
217         if (!*d) {
218             if (pos >= outlen) return 0;
219             out[pos++] = 0;
220             return 1;
221         }
222         if (pos >= outlen) return 0;
223         out[pos++] = '.';
224     }
225     return 0;
226 }
227 
globalip(unsigned char * d,unsigned char ip[16])228 static int globalip(unsigned char *d,unsigned char ip[16])
229 {
230 
231   char xbuf[100];
232   if (dns_domain_equal(d,(unsigned char *)"\011localhost\0")) {
233     byte_copy(ip,16,"\0\0\0\0\0\0\0\0\0\0\377\377\177\0\0\1");
234     return 1;
235   }
236   if (!dtis(xbuf, sizeof xbuf, d)) return 0;
237   return strtoip4(ip, xbuf);
238 }
239 
globalip6(unsigned char * d,unsigned char ip[16])240 static int globalip6(unsigned char *d,unsigned char ip[16]) {
241   char xbuf[100];
242   if (dns_domain_equal(d,(unsigned char *)"\011localhost\0")) {
243     byte_copy(ip,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1");
244     return 1;
245   }
246   if (!dtis(xbuf, sizeof xbuf, d)) return 0;
247   return strtoip6(ip, xbuf);
248 }
249 
250 
findkey(const unsigned char * dn,unsigned char key[32])251 static int findkey(const unsigned char *dn,unsigned char key[32])
252 {
253   unsigned char c;
254 
255   while (c = *dn++) {
256     if (c == 54)
257       if (!case_diffb(dn,3,"uz5"))
258         if (base32_decode(key,dn + 3,51,1) == 32)
259           return 1;
260     dn += (unsigned int) c;
261   }
262 
263   return 0;
264 }
265 
266 static unsigned char *t1 = 0;
267 static unsigned char *t2 = 0;
268 static unsigned char *t3 = 0;
269 static unsigned char *cname = 0;
270 static unsigned char *referral = 0;
271 static long long *records = 0;
272 
smaller(unsigned char * buf,long long len,long long pos1,long long pos2)273 static int smaller(unsigned char *buf,long long len,long long pos1,long long pos2)
274 {
275   unsigned char header1[12];
276   unsigned char header2[12];
277   int r;
278   long long len1;
279   long long len2;
280 
281   pos1 = dns_packet_getname(buf,len,pos1,&t1);
282   dns_packet_copy(buf,len,pos1,header1,10);
283   pos2 = dns_packet_getname(buf,len,pos2,&t2);
284   dns_packet_copy(buf,len,pos2,header2,10);
285 
286   r = byte_diff(header1,4,header2);
287   if (r < 0) return 1;
288   if (r > 0) return 0;
289 
290   len1 = dns_domain_length(t1);
291   len2 = dns_domain_length(t2);
292   if (len1 < len2) return 1;
293   if (len1 > len2) return 0;
294 
295   r = case_diffb(t1,len1,t2);
296   if (r < 0) return 1;
297   if (r > 0) return 0;
298 
299   if (pos1 < pos2) return 1;
300   return 0;
301 }
302 
addserver(struct query * z,const unsigned char * addr,const unsigned char * key)303 static void addserver(struct query *z,const unsigned char *addr,const unsigned char *key)
304 {
305   int k;
306   int i;
307   unsigned char *kk;
308 
309   if (key) z->flaghavekeys[z->level - 1] = 1;
310 
311   for (k = 0;k < 256;k += 16) {
312     i = k >> 4;
313     if (byte_isequal(z->servers[z->level - 1] + k,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) {
314       byte_copy(z->servers[z->level - 1] + k,16,addr);
315       kk = z->keys[z->level - 1] + 33 * i;
316       if (key) {
317         byte_copy(kk + 1,32,key);
318         kk[0] = flagdnscurvetype1;
319       }
320       else {
321         kk[0] = 0;
322       }
323       break;
324     }
325   }
326 
327   /* add txt */
328   if (!key || !flagdnscurvetype2) return;
329   for (k = 0;k < 256;k += 16) {
330     i = k >> 4;
331     kk = z->keys[z->level - 1] + 33 * i;
332     if (byte_isequal(z->servers[z->level - 1] + k,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) {
333       byte_copy(z->servers[z->level - 1] + k,16,addr);
334       byte_copy(kk + 1,32,key);
335       kk[0] = flagdnscurvetype2;
336       break;
337     }
338   }
339 }
340 
341 crypto_uint64 tx4 = 0;
342 crypto_uint64 tx6 = 0;
343 
doit(struct query * z,int state)344 static int doit(struct query *z,int state)
345 {
346   unsigned char key[259];
347   unsigned char *cached;
348   long long cachedlen;
349   unsigned char *buf;
350   long long len;
351   unsigned char *whichserver;
352   unsigned char *whichkey;
353   unsigned char header[16];
354   unsigned char misc[20];
355   unsigned char pubkey[32];
356   int flaghaskey;
357   long long rcode;
358   long long posanswers;
359   crypto_uint16 numanswers;
360   long long posauthority;
361   crypto_uint16 numauthority;
362   /* long long posglue; */
363   crypto_uint16 numglue;
364   long long pos;
365   long long pos2;
366   crypto_uint16 datalen;
367   unsigned char *control;
368   unsigned char *d;
369   const unsigned char *dtype;
370   long long dlen;
371   int flagout;
372   int flagcname;
373   int flagreferral;
374   unsigned char flagns;
375   int flagsoa;
376   long long ttl;
377   long long soattl;
378   long long cnamettl;
379   long long cachedttl;
380   unsigned char cachedflag;
381   long long i;
382   long long j;
383   long long k;
384   long long p;
385   long long q;
386   int flaghavekeys;
387 
388   errno = EIO;
389   if (state == 1) goto HAVEPACKET;
390   if (state == -1) {
391     cachegeneric2(DNS_T_AXFR, z->type, z->name[z->level], (unsigned char *)"", 0, 10, 0);
392     log_servfail(z->name[z->level]);
393     goto SERVFAIL;
394   }
395 
396 
397   NEWNAME:
398   if (++z->loop == QUERY_MAXLOOP) goto DIE;
399   d = z->name[z->level];
400   /* dtype = z->level ? DNS_T_A : z->type; */
401   dtype = z->level ? (z->ipv6[z->level] ? DNS_T_AAAA : DNS_T_A) : z->type;
402   dlen = dns_domain_length(d);
403 
404   if (globalip(d,misc) && typematch(DNS_T_A,dtype)) {
405     if (z->level) {
406       addserver(z,misc,0);
407       goto LOWERLEVEL;
408     }
409     if (!rqa(z)) goto DIE;
410     if (typematch(DNS_T_A,dtype)) {
411       if (!response_rstart(d,DNS_T_A,655360)) goto DIE;
412       if (!response_addbytes(misc + 12,4)) goto DIE;
413       response_rfinish(RESPONSE_ANSWER);
414     }
415     cleanup(z);
416     return 1;
417   }
418 
419   if (globalip6(d,misc) && typematch(DNS_T_AAAA,dtype)) {
420     if (z->level) {
421       addserver(z,misc,0);
422       goto LOWERLEVEL;
423     }
424     if (!rqa(z)) goto DIE;
425     if (typematch(DNS_T_AAAA,dtype)) {
426       if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE;
427       if (!response_addbytes(misc,16)) goto DIE;
428       response_rfinish(RESPONSE_ANSWER);
429     }
430     cleanup(z);
431     return 1;
432   }
433 
434   if (dns_domain_equal(d,(unsigned char *)"\0011\0010\0010\003127\7in-addr\4arpa\0")) {
435     if (z->level) goto LOWERLEVEL;
436     if (!rqa(z)) goto DIE;
437     if (typematch(DNS_T_PTR,dtype)) {
438       if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
439       if (!response_addname((unsigned char *)"\011localhost\0")) goto DIE;
440       response_rfinish(RESPONSE_ANSWER);
441     }
442     cleanup(z);
443     log_stats();
444     return 1;
445   }
446 
447   if (dlen <= 255) {
448     byte_copy(key,2,DNS_T_ANY);
449     byte_copy(key + 2,dlen,d);
450     case_lowerb(key + 2,dlen);
451     cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0);
452     if (cached) {
453       log_cachednxdomain(d);
454       goto NXDOMAIN;
455     }
456 
457     byte_copy(key,2,DNS_T_AXFR);
458     byte_copy(key + 2 + dlen,2,dtype);
459     cached = cache_get(key,dlen + 4,&cachedlen,&ttl,0);
460     if (cached && cachedlen == 0) {
461       log_cachedservfail(d, dtype);
462       goto SERVFAIL;
463     }
464 
465     byte_copy(key,2,DNS_T_CNAME);
466     cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0);
467     if (cached) {
468       if (typematch(DNS_T_CNAME,dtype)) {
469         log_cachedanswer(d,DNS_T_CNAME);
470         if (!rqa(z)) goto DIE;
471 	if (!response_cname(z->name[0],cached,ttl)) goto DIE;
472 	cleanup(z);
473 	return 1;
474       }
475       log_cachedcname(d,cached);
476       if (!dns_domain_copy(&cname,cached)) goto DIE;
477       goto CNAME;
478     }
479 
480     if (typematch(DNS_T_NS,dtype)) {
481       byte_copy(key,2,DNS_T_NS);
482       cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0);
483       if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) {
484 	log_cachedanswer(d,DNS_T_NS);
485 	if (!rqa(z)) goto DIE;
486 	pos = 0;
487 	while (pos = dns_packet_getname(cached,cachedlen,pos,&t2)) {
488 	  if (!response_rstart(d,DNS_T_NS,ttl)) goto DIE;
489 	  if (!response_addname(t2)) goto DIE;
490 	  response_rfinish(RESPONSE_ANSWER);
491 	}
492 	cleanup(z);
493 	return 1;
494       }
495     }
496 
497     if (typematch(DNS_T_PTR,dtype)) {
498       byte_copy(key,2,DNS_T_PTR);
499       cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0);
500       if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) {
501 	log_cachedanswer(d,DNS_T_PTR);
502 	if (!rqa(z)) goto DIE;
503 	pos = 0;
504 	while (pos = dns_packet_getname(cached,cachedlen,pos,&t2)) {
505 	  if (!response_rstart(d,DNS_T_PTR,ttl)) goto DIE;
506 	  if (!response_addname(t2)) goto DIE;
507 	  response_rfinish(RESPONSE_ANSWER);
508 	}
509 	cleanup(z);
510 	return 1;
511       }
512     }
513 
514     if (typematch(DNS_T_MX,dtype)) {
515       byte_copy(key,2,DNS_T_MX);
516       cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0);
517       if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) {
518 	log_cachedanswer(d,DNS_T_MX);
519 	if (!rqa(z)) goto DIE;
520 	pos = 0;
521 	while (pos = dns_packet_copy(cached,cachedlen,pos,misc,2)) {
522 	  pos = dns_packet_getname(cached,cachedlen,pos,&t2);
523 	  if (!pos) break;
524 	  if (!response_rstart(d,DNS_T_MX,ttl)) goto DIE;
525 	  if (!response_addbytes(misc,2)) goto DIE;
526 	  if (!response_addname(t2)) goto DIE;
527 	  response_rfinish(RESPONSE_ANSWER);
528 	}
529 	cleanup(z);
530 	return 1;
531       }
532     }
533 
534     if (typematch(DNS_T_SOA,dtype)) {
535       byte_copy(key,2,DNS_T_SOA);
536       cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0);
537       if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
538         log_cachedanswer(d,DNS_T_SOA);
539         if (!rqa(z)) goto DIE;
540         pos = 0;
541         while (pos = dns_packet_copy(cached,cachedlen,pos,misc,20)) {
542           pos = dns_packet_getname(cached,cachedlen,pos,&t2);
543           if (!pos) break;
544           pos = dns_packet_getname(cached,cachedlen,pos,&t3);
545           if (!pos) break;
546           if (!response_rstart(d,DNS_T_SOA,ttl)) goto DIE;
547           if (!response_addname(t2)) goto DIE;
548           if (!response_addname(t3)) goto DIE;
549           if (!response_addbytes(misc,20)) goto DIE;
550           response_rfinish(RESPONSE_ANSWER);
551         }
552         cleanup(z);
553         return 1;
554       }
555     }
556 
557 
558     if (typematch(DNS_T_A,dtype)) {
559       byte_copy(key,2,DNS_T_A);
560       cached = cache_get(key,dlen + 2,&cachedlen,&ttl,&flagns);
561       if (cached && !cachedlen && z->level) { /* if we were looking the A record up to find an NS, try IPv6 too */
562         z->ipv6[z->level]=1;
563         goto NEWNAME;
564       }
565       if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) {
566 	if (z->level) {
567           flaghaskey = findkey(d,pubkey);
568       dns_sortip4(cached, cachedlen);
569 	  log_cachedanswer(d,DNS_T_A);
570 	  while (cachedlen >= 4) {
571             byte_copy(misc, 12, "\0\0\0\0\0\0\0\0\0\0\377\377");
572             byte_copy(misc + 12, 4, cached);
573             addserver(z,misc,flaghaskey ? pubkey : 0);
574 	    cached += 4;
575 	    cachedlen -= 4;
576 	  }
577           /* if we were looking the A record up to find an NS, try IPv6 too */
578           byte_copy(key,2,DNS_T_AAAA);
579           cached = cache_get(key,dlen + 2,&cachedlen,&ttl,&flagns);
580           if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) {
581               flaghaskey = findkey(d,pubkey);
582               dns_sortip(cached, cachedlen);
583               log_cachedanswer(d,DNS_T_AAAA);
584               while (cachedlen >= 16) {
585                 addserver(z,cached,flaghaskey ? pubkey : 0);
586 	        cached += 16;
587 	        cachedlen -= 16;
588               }
589           }
590 	  goto LOWERLEVEL;
591 	}
592 
593     dns_sortip4(cached, cachedlen);
594 	log_cachedanswer(d,DNS_T_A);
595 	if (!rqa(z)) goto DIE;
596 	while (cachedlen >= 4) {
597 	  if (!response_rstart(d,DNS_T_A,ttl)) goto DIE;
598 	  if (!response_addbytes(cached,4)) goto DIE;
599 	  response_rfinish(RESPONSE_ANSWER);
600 	  cached += 4;
601 	  cachedlen -= 4;
602 	}
603         if (!flagns){
604           cleanup(z);
605           return 1;
606         }
607         byte_copy(key,2,DNS_T_NS);
608         cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0);
609         if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) {
610           pos = 0;
611           while (pos = dns_packet_getname(cached,cachedlen,pos,&t2)) {
612             if (!response_rstart(d,DNS_T_NS,ttl)) goto DIE;
613             if (!response_addname(t2)) goto DIE;
614             response_rfinish(RESPONSE_AUTHORITY);
615           }
616           cleanup(z);
617           return 1;
618         }
619       }
620     }
621 
622     if (typematch(DNS_T_AAAA,dtype)) {
623       byte_copy(key,2,DNS_T_AAAA);
624       cached = cache_get(key,dlen + 2,&cachedlen,&ttl,&flagns);
625       if (cached && !cachedlen && z->level) { /* if we were looking the AAAA record up to find an NS, go to LOWERLEVEL */
626         goto LOWERLEVEL;
627       }
628       if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) {
629         if (z->level) {
630           flaghaskey = findkey(d,pubkey);
631           dns_sortip(cached, cachedlen);
632           log_cachedanswer(d,DNS_T_AAAA);
633           while (cachedlen >= 16) {
634             byte_copy(misc, 16, cached);
635             addserver(z,misc,flaghaskey ? pubkey : 0);
636             cached += 16;
637             cachedlen -= 16;
638           }
639           goto LOWERLEVEL;
640         }
641 
642         dns_sortip(cached, cachedlen);
643         log_cachedanswer(d,DNS_T_AAAA);
644         if (!rqa(z)) goto DIE;
645         while (cachedlen >= 16) {
646           if (!response_rstart(d,DNS_T_AAAA,ttl)) goto DIE;
647           if (!response_addbytes(cached,16)) goto DIE;
648           response_rfinish(RESPONSE_ANSWER);
649           cached += 16;
650           cachedlen -= 16;
651         }
652         if (!flagns){
653           cleanup(z);
654           return 1;
655         }
656         byte_copy(key,2,DNS_T_NS);
657         cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0);
658         if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) {
659           pos = 0;
660           while (pos = dns_packet_getname(cached,cachedlen,pos,&t2)) {
661             if (!response_rstart(d,DNS_T_NS,ttl)) goto DIE;
662             if (!response_addname(t2)) goto DIE;
663             response_rfinish(RESPONSE_AUTHORITY);
664           }
665           cleanup(z);
666           return 1;
667         }
668       }
669     }
670 
671     if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_CNAME,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype) && !typematch(DNS_T_AAAA,dtype) && !typematch(DNS_T_SOA,dtype)) {
672       byte_copy(key,2,dtype);
673       cached = cache_get(key,dlen + 2,&cachedlen,&ttl,&flagns);
674       if (cached && (cachedlen || !byte_isequal(dtype,2,DNS_T_ANY))) {
675 	log_cachedanswer(d,dtype);
676 	if (!rqa(z)) goto DIE;
677 	while (cachedlen >= 2) {
678 	  datalen = uint16_unpack_big(cached);
679 	  cached += 2;
680 	  cachedlen -= 2;
681 	  if (datalen > cachedlen) goto DIE;
682 	  if (!response_rstart(d,dtype,ttl)) goto DIE;
683 	  if (!response_addbytes(cached,datalen)) goto DIE;
684 	  response_rfinish(RESPONSE_ANSWER);
685 	  cached += datalen;
686 	  cachedlen -= datalen;
687 	}
688         cleanup(z);
689         return 1;
690       }
691     }
692   }
693 
694 
695   for (;;) {
696     if (roots(z->servers[z->level],z->keys[z->level],&flaghavekeys,d)) {
697       z->flaghavekeys[z->level] = flaghavekeys;
698       for (j = 0;j < QUERY_MAXNS;++j)
699         dns_domain_free(&z->ns[z->level][j]);
700       z->control[z->level] = d;
701       break;
702     }
703 
704     if (!flagforwardonly && (z->level < 2))
705       if (dlen < 255) {
706         byte_copy(key,2,DNS_T_NS);
707         byte_copy(key + 2,dlen,d);
708         case_lowerb(key + 2,dlen);
709         cached = cache_get(key,dlen + 2,&cachedlen,&ttl,0);
710         if (cached && cachedlen) {
711 	  z->control[z->level] = d;
712           byte_zero(z->servers[z->level],256);
713           byte_zero(z->keys[z->level],528);
714           z->flaghavekeys[z->level] = 0;
715           for (j = 0;j < QUERY_MAXNS;++j)
716             dns_domain_free(&z->ns[z->level][j]);
717           pos = 0;
718           j = 0;
719           while (pos = dns_packet_getname(cached,cachedlen,pos,&t1)) {
720 	    log_cachedns(d,t1);
721             if (j < QUERY_MAXNS)
722               if (!dns_domain_copy(&z->ns[z->level][j++],t1)) goto DIE;
723 	  }
724           break;
725         }
726       }
727 
728     if (!*d) goto DIE;
729     j = 1 + (unsigned int) (unsigned char) *d;
730     dlen -= j;
731     d += j;
732   }
733 
734 
735   HAVENS:
736   for (j = 0;j < QUERY_MAXNS;++j)
737     if (z->ns[z->level][j]) {
738       if (z->level + 1 < QUERY_MAXLEVEL) {
739         if (!dns_domain_copy(&z->name[z->level + 1],z->ns[z->level][j])) goto DIE;
740         dns_domain_free(&z->ns[z->level][j]);
741         ++z->level;
742         z->ipv6[z->level]=0;
743         goto NEWNAME;
744       }
745       dns_domain_free(&z->ns[z->level][j]);
746     }
747 
748 
749   for (j = 0;j < 256;j += 16)
750     if (!byte_isequal(z->servers[z->level] + j,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"))
751       break;
752   if (j == 256) { log_servfail(z->name[z->level]); goto SERVFAIL; }
753 
754 
755   byte_copy(key,2,DNS_T_AXFR);
756   for (j = 0;j < 256;j += 16) {
757     k = j >> 4;
758     if (!byte_isequal(z->servers[z->level] + j,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) {
759       whichkey = z->keys[z->level] + 33 * k;
760       if (whichkey[0]) {
761         byte_copy(key + 2,32,whichkey + 1);
762         cached = cache_get(key,34,&cachedlen,&ttl,0);
763         if (cached && (cachedlen == 32)) {
764           byte_copy(whichkey + 1,32,cached);
765           continue;
766         }
767         crypto_box_curve25519xsalsa20poly1305_beforenm((unsigned char *) whichkey + 1,(const unsigned char *) whichkey + 1,(const unsigned char *) secretkey);
768         cache_set(key,34,whichkey + 1,32,655360,0);
769       }
770     }
771   }
772 
773   dns_sortipkey(z->servers[z->level],z->keys[z->level],256);
774   /* dtype = z->level ? DNS_T_A : z->type; */
775   dtype = z->level ? (z->ipv6[z->level] ? DNS_T_AAAA : DNS_T_A) : z->type;
776   log_tx(z->name[z->level],dtype,z->control[z->level],z->servers[z->level],z->keys[z->level],z->flaghavekeys[z->level],z->level);
777   if (dns_transmit_startext(&z->dt,z->servers[z->level],flagforwardonly,flagtcponly,flagipv4only,z->name[z->level],dtype,z->localip,remoteport,z->keys[z->level],publickey,z->control[z->level]) == -1) goto DIE;
778   return 0;
779 
780 
781   LOWERLEVEL:
782   dns_domain_free(&z->name[z->level]);
783   for (j = 0;j < QUERY_MAXNS;++j)
784     dns_domain_free(&z->ns[z->level][j]);
785   --z->level;
786   goto HAVENS;
787 
788 
789   HAVEPACKET:
790   if (++z->loop == QUERY_MAXLOOP) goto DIE;
791   buf = z->dt.packet;
792   len = z->dt.packetlen;
793 
794   whichserver = (unsigned char *)z->dt.servers + 16 * z->dt.curserver;
795   whichkey = (unsigned char *)z->dt.keys + 33 * z->dt.curserver;
796   if (xsocket_type(whichserver) == XSOCKET_V4) ++tx4;
797   if (xsocket_type(whichserver) == XSOCKET_V6) ++tx6;
798   control = z->control[z->level];
799   d = z->name[z->level];
800   /* dtype = z->level ? DNS_T_A : z->type; */
801   dtype = z->level ? (z->ipv6[z->level] ? DNS_T_AAAA : DNS_T_A) : z->type;
802 
803   pos = dns_packet_copy(buf,len,0,header,12); if (!pos) goto DIE;
804   pos = dns_packet_skipname(buf,len,pos); if (!pos) goto DIE;
805   pos += 4;
806   posanswers = pos;
807 
808   numanswers = uint16_unpack_big(header + 6);
809   numauthority = uint16_unpack_big(header + 8);
810   numglue = uint16_unpack_big(header + 10);
811 
812   rcode = header[3] & 15;
813   if (rcode && (rcode != 3)) goto DIE; /* impossible; see irrelevant() */
814 
815   flagout = 0;
816   flagcname = 0;
817   flagreferral = 0;
818   flagns = 0;
819   flagsoa = 0;
820   soattl = 0;
821   cnamettl = 0;
822   for (j = 0;j < numanswers;++j) {
823     pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
824     pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
825 
826     if (dns_domain_equal(t1,d))
827       if (byte_isequal(header + 2,2,DNS_C_IN)) { /* should always be true */
828         if (byte_isequal(dtype,2,DNS_T_ANY))
829           if (byte_isequal(header,2,DNS_T_NS))
830             flagns = 1;
831         if (typematch(header,dtype))
832           flagout = 1;
833         else if (typematch(header,DNS_T_CNAME)) {
834           if (!dns_packet_getname(buf,len,pos,&cname)) goto DIE;
835           flagcname = 1;
836 	  cnamettl = ttlget(header + 4);
837         }
838       }
839 
840     datalen=uint16_unpack_big(header + 8);
841     pos += datalen;
842   }
843   posauthority = pos;
844 
845   for (j = 0;j < numauthority;++j) {
846     pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
847     pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
848 
849     if (typematch(header,DNS_T_SOA)) {
850       flagsoa = 1;
851       soattl = ttlget(header + 4);
852       if (soattl > 3600) soattl = 3600;
853     }
854     else if (typematch(header,DNS_T_NS)) {
855       flagreferral = 1;
856       if (dns_domain_equal(t1,d)) flagns = 1;
857       if (!dns_domain_copy(&referral,t1)) goto DIE;
858     }
859 
860     datalen=uint16_unpack_big(header + 8);
861     pos += datalen;
862   }
863   /* posglue = pos; */
864 
865 
866   if (!flagcname && !rcode && !flagout && flagreferral && !flagsoa)
867     if (dns_domain_equal(referral,control) || !dns_domain_suffix(referral,control)) {
868       log_lame(whichserver,control,referral);
869       byte_zero(whichserver,16);
870       goto HAVENS;
871     }
872 
873 
874   if (records) { alloc_free(records); records = 0; }
875 
876   k = numanswers + numauthority + numglue;
877   records = (long long *) alloc(k * sizeof(long long));
878   if (!records) goto DIE;
879 
880   pos = posanswers;
881   for (j = 0;j < k;++j) {
882     records[j] = pos;
883     pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
884     pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
885     datalen=uint16_unpack_big(header + 8);
886     pos += datalen;
887   }
888 
889   i = j = k;
890   while (j > 1) {
891     if (i > 1) { --i; pos = records[i - 1]; }
892     else { pos = records[j - 1]; records[j - 1] = records[i - 1]; --j; }
893 
894     q = i;
895     while ((p = q * 2) < j) {
896       if (!smaller(buf,len,records[p],records[p - 1])) ++p;
897       records[q - 1] = records[p - 1]; q = p;
898     }
899     if (p == j) {
900       records[q - 1] = records[p - 1]; q = p;
901     }
902     while ((q > i) && smaller(buf,len,records[(p = q/2) - 1],pos)) {
903       records[q - 1] = records[p - 1]; q = p;
904     }
905     records[q - 1] = pos;
906   }
907 
908   i = 0;
909   while (i < k) {
910     unsigned char type[2];
911 
912     pos = dns_packet_getname(buf,len,records[i],&t1); if (!pos) goto DIE;
913     pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
914     ttl = ttlget(header + 4);
915 
916     byte_copy(type,2,header);
917     if (!byte_isequal(header + 2,2,DNS_C_IN)) { ++i; continue; }
918 
919     for (j = i + 1;j < k;++j) {
920       pos = dns_packet_getname(buf,len,records[j],&t2); if (!pos) goto DIE;
921       pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
922       if (!dns_domain_equal(t1,t2)) break;
923       if (!byte_isequal(header,2,type)) break;
924       if (!byte_isequal(header + 2,2,DNS_C_IN)) break;
925     }
926 
927     if (!dns_domain_suffix(t1,control)) { i = j; continue; }
928     if (!roots_same(t1,control)) { i = j; continue; }
929 
930     if (byte_isequal(type,2,DNS_T_ANY))
931       ;
932     else if (byte_isequal(type,2,DNS_T_AXFR))
933       ;
934     else if (byte_isequal(type,2,DNS_T_SOA)) {
935       int non_authority = 0;
936       save_start();
937       while (i < j) {
938         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
939         pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE;
940         pos = dns_packet_getname(buf,len,pos,&t3); if (!pos) goto DIE;
941         pos = dns_packet_copy(buf,len,pos,misc,20); if (!pos) goto DIE;
942         if (records[i] < posauthority) {
943           log_rrsoa(whichserver,t1,t2,t3,misc,ttl,whichkey[0]);
944           save_data(misc,20);
945           save_data(t2,dns_domain_length(t2));
946           save_data(t3,dns_domain_length(t3));
947           non_authority++;
948         }
949         ++i;
950       }
951       if (non_authority)
952         save_finish(DNS_T_SOA,t1,ttl,0);
953     }
954     else if (byte_isequal(type,2,DNS_T_CNAME)) {
955       pos = dns_packet_skipname(buf,len,records[j - 1]); if (!pos) goto DIE;
956       pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE;
957       log_rrcname(whichserver,t1,t2,ttl,whichkey[0]);
958       cachegeneric(DNS_T_CNAME,t1,t2,dns_domain_length(t2),ttl,0);
959     }
960     else if (byte_isequal(type,2,DNS_T_PTR)) {
961       save_start();
962       while (i < j) {
963         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
964         pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE;
965         log_rrptr(whichserver,t1,t2,ttl,whichkey[0]);
966         save_data(t2,dns_domain_length(t2));
967         ++i;
968       }
969       save_finish(DNS_T_PTR,t1,ttl,0);
970     }
971     else if (byte_isequal(type,2,DNS_T_NS)) {
972       cachedflag = 0;
973       if (posauthority <= records[i]) {
974         dlen = dns_domain_length(t1);
975         byte_copy(key,2,DNS_T_NS);
976         byte_copy(key + 2,dlen,t1);
977         case_lowerb(key + 2,dlen);
978         if (dns_domain_equal(t1,control)) {
979           if (cache_get(key,dlen + 2,&cachedlen,&cachedttl,&cachedflag)) {
980             if (cachedflag) if (cachedttl < ttl) ttl = cachedttl;
981           }
982         }
983       }
984       save_start();
985       while (i < j) {
986         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
987         pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE;
988         log_rrns(whichserver,t1,t2,ttl,whichkey[0]);
989         save_data(t2,dns_domain_length(t2));
990         ++i;
991       }
992       save_finish(DNS_T_NS,t1,ttl,dns_domain_equal(t1,control));
993     }
994     else if (byte_isequal(type,2,DNS_T_MX)) {
995       save_start();
996       while (i < j) {
997         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
998         pos = dns_packet_copy(buf,len,pos + 10,misc,2); if (!pos) goto DIE;
999         pos = dns_packet_getname(buf,len,pos,&t2); if (!pos) goto DIE;
1000         log_rrmx(whichserver,t1,t2,misc,ttl,whichkey[0]);
1001         save_data(misc,2);
1002         save_data(t2,dns_domain_length(t2));
1003         ++i;
1004       }
1005       save_finish(DNS_T_MX,t1,ttl,0);
1006     }
1007     else if (byte_isequal(type,2,DNS_T_A)) {
1008       save_start();
1009       while (i < j) {
1010         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
1011         pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
1012         if (byte_isequal(header + 8,2,"\0\4")) {
1013           pos = dns_packet_copy(buf,len,pos,header,4); if (!pos) goto DIE;
1014           save_data(header,4);
1015           log_rra(whichserver,t1,header,ttl,whichkey[0]);
1016         }
1017         ++i;
1018       }
1019       save_finish(DNS_T_A,t1,ttl,flagns);
1020     }
1021     else if (byte_isequal(type,2,DNS_T_AAAA)) {
1022       save_start();
1023       while (i < j) {
1024         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
1025         pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
1026         if (uint16_unpack_big(header + 8) == 16) {
1027           pos = dns_packet_copy(buf,len,pos,header,16); if (!pos) goto DIE;
1028           save_data(header,16);
1029           log_rraaaa(whichserver,t1,header,ttl,whichkey[0]);
1030         }
1031         ++i;
1032       }
1033       save_finish(DNS_T_AAAA,t1,ttl,flagns);
1034     }
1035     else {
1036       save_start();
1037       while (i < j) {
1038         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
1039         pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
1040         datalen=uint16_unpack_big(header + 8);
1041         if (datalen > len - pos) goto DIE;
1042         save_data(header + 8,2);
1043         save_data(buf + pos,datalen);
1044         log_rr(whichserver,t1,type,buf + pos,datalen,ttl,whichkey[0]);
1045         ++i;
1046       }
1047       save_finish(type,t1,ttl,0);
1048     }
1049 
1050     i = j;
1051   }
1052 
1053   alloc_free(records); records = 0;
1054 
1055   if (flagcname) {
1056     ttl = cnamettl;
1057     CNAME:
1058     if (!z->level) {
1059       if (z->alias[QUERY_MAXALIAS - 1]) goto DIE;
1060       for (j = QUERY_MAXALIAS - 1;j > 0;--j)
1061         z->alias[j] = z->alias[j - 1];
1062       for (j = QUERY_MAXALIAS - 1;j > 0;--j)
1063         z->aliasttl[j] = z->aliasttl[j - 1];
1064       z->alias[0] = z->name[0];
1065       z->aliasttl[0] = ttl;
1066       z->name[0] = 0;
1067     }
1068     if (!dns_domain_copy(&z->name[z->level],cname)) goto DIE;
1069     goto NEWNAME;
1070   }
1071 
1072   if (rcode == 3) {
1073     log_nxdomain(whichserver,d,soattl);
1074     cachegeneric(DNS_T_ANY,d,(unsigned char *)"",0,soattl,0);
1075 
1076     NXDOMAIN:
1077     if (z->level) goto LOWERLEVEL;
1078     if (!rqa(z)) goto DIE;
1079     response_nxdomain();
1080     cleanup(z);
1081     return 1;
1082   }
1083 
1084   if (!flagout && flagsoa)
1085     if (!byte_isequal(DNS_T_ANY,2,dtype))
1086       if (!byte_isequal(DNS_T_AXFR,2,dtype))
1087         if (!byte_isequal(DNS_T_CNAME,2,dtype)) {
1088           save_start();
1089           save_finish(dtype,d,soattl,0);
1090 	  log_nodata(whichserver,d,dtype,soattl);
1091           if (z->level && byte_isequal(DNS_T_A,2,dtype)) {
1092             d = z->name[z->level];
1093             z->ipv6[z->level] = 1;
1094             goto NEWNAME; /* retry, will ask for AAAA next */
1095           }
1096         }
1097 
1098   log_stats();
1099 
1100   if (flagout || flagsoa || !flagreferral) {
1101     if (z->level) {
1102       flaghaskey = findkey(d,pubkey);
1103       pos = posanswers;
1104       for (j = 0;j < numanswers;++j) {
1105         pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
1106         pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
1107         datalen=uint16_unpack_big(header + 8);
1108         if (dns_domain_equal(t1,d)) {
1109           if (typematch(header,DNS_T_A))
1110             if (byte_isequal(header + 2,2,DNS_C_IN)) /* should always be true */
1111               if (datalen == 4) {
1112                 byte_copy(misc, 12, "\0\0\0\0\0\0\0\0\0\0\377\377");
1113                 if (!dns_packet_copy(buf,len,pos,misc+12,4)) goto DIE;
1114                 addserver(z,misc,flaghaskey ? pubkey : 0);
1115               }
1116           if (typematch(header,DNS_T_AAAA))
1117             if (byte_isequal(header + 2,2,DNS_C_IN)) /* should always be true */
1118               if (datalen == 16) {
1119                 if (!dns_packet_copy(buf,len,pos,misc,16)) goto DIE;
1120                 addserver(z,misc,flaghaskey ? pubkey : 0);
1121               }
1122         }
1123         pos += datalen;
1124       }
1125       goto LOWERLEVEL;
1126     }
1127 
1128 
1129     if (!rqa(z)) goto DIE;
1130 
1131     pos = posanswers;
1132     for (j = 0;j < numanswers;++j) {
1133       pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
1134       pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
1135       ttl = ttlget(header + 4);
1136       datalen=uint16_unpack_big(header + 8);
1137       if (dns_domain_equal(t1,d))
1138         if (byte_isequal(header + 2,2,DNS_C_IN)) /* should always be true */
1139           if (typematch(header,dtype)) {
1140             if (!response_rstart(t1,header,ttl)) goto DIE;
1141 
1142             if (typematch(header,DNS_T_NS) || typematch(header,DNS_T_CNAME) || typematch(header,DNS_T_PTR)) {
1143               if (!dns_packet_getname(buf,len,pos,&t2)) goto DIE;
1144               if (!response_addname(t2)) goto DIE;
1145             }
1146             else if (typematch(header,DNS_T_MX)) {
1147               pos2 = dns_packet_copy(buf,len,pos,misc,2); if (!pos2) goto DIE;
1148               if (!response_addbytes(misc,2)) goto DIE;
1149               if (!dns_packet_getname(buf,len,pos2,&t2)) goto DIE;
1150               if (!response_addname(t2)) goto DIE;
1151             }
1152             else if (typematch(header,DNS_T_SOA)) {
1153               pos2 = dns_packet_getname(buf,len,pos,&t2); if (!pos2) goto DIE;
1154               if (!response_addname(t2)) goto DIE;
1155               pos2 = dns_packet_getname(buf,len,pos2,&t3); if (!pos2) goto DIE;
1156               if (!response_addname(t3)) goto DIE;
1157               pos2 = dns_packet_copy(buf,len,pos2,misc,20); if (!pos2) goto DIE;
1158               if (!response_addbytes(misc,20)) goto DIE;
1159             }
1160             else {
1161               if (pos + datalen > len) goto DIE;
1162               if (!response_addbytes(buf + pos,datalen)) goto DIE;
1163             }
1164 
1165             response_rfinish(RESPONSE_ANSWER);
1166           }
1167       pos += datalen;
1168     }
1169 
1170     pos = posauthority;
1171     for (j = 0;j < numauthority;++j) {
1172       pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
1173       pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
1174       ttl = ttlget(header + 4);
1175       datalen = uint16_unpack_big(header + 8);
1176       if (dns_domain_equal(t1,d))
1177         if (byte_isequal(header + 2,2,DNS_C_IN)) /* should always be true */
1178           if (typematch(header,DNS_T_NS)) {
1179             if (!response_rstart(t1,header,ttl)) goto DIE;
1180             if (!dns_packet_getname(buf,len,pos,&t2)) goto DIE;
1181             if (!response_addname(t2)) goto DIE;
1182             response_rfinish(RESPONSE_AUTHORITY);
1183           }
1184       pos += datalen;
1185     }
1186 
1187 
1188     cleanup(z);
1189     return 1;
1190   }
1191 
1192   if (!dns_domain_suffix(d,referral)) goto DIE;
1193 
1194   /* In strict "forwardonly" mode, we don't, as the manual states,
1195   ** contact a chain of servers according to "NS" resource records.
1196   ** We don't obey any referral responses, therefore.  Instead, we
1197   ** eliminate the server from the list and try the next one.
1198   */
1199   if (flagforwardonly) {
1200       log_ignore_referral(whichserver,control,referral);
1201       byte_zero(whichserver,16);
1202       goto HAVENS;
1203   }
1204 
1205   control = d + dns_domain_suffixpos(d,referral);
1206   z->control[z->level] = control;
1207   byte_zero(z->servers[z->level],256);
1208   z->flaghavekeys[z->level] = 0;
1209   for (j = 0;j < QUERY_MAXNS;++j)
1210     dns_domain_free(&z->ns[z->level][j]);
1211   k = 0;
1212 
1213   pos = posauthority;
1214   for (j = 0;j < numauthority;++j) {
1215     pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
1216     pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
1217     datalen = uint16_unpack_big(header + 8);
1218     if (dns_domain_equal(referral,t1)) /* should always be true */
1219       if (typematch(header,DNS_T_NS)) /* should always be true */
1220         if (byte_isequal(header + 2,2,DNS_C_IN)) /* should always be true */
1221           if (k < QUERY_MAXNS)
1222             if (!dns_packet_getname(buf,len,pos,&z->ns[z->level][k++])) goto DIE;
1223     pos += datalen;
1224   }
1225 
1226 
1227   goto HAVENS;
1228 
1229 
1230   SERVFAIL:
1231   if (z->level) goto LOWERLEVEL;
1232   if (!rqa(z)) goto DIE;
1233   response_servfail();
1234   cleanup(z);
1235   return 1;
1236 
1237 
1238   DIE:
1239   cleanup(z);
1240   if (records) { alloc_free(records); records = 0; }
1241   return -1;
1242 }
1243 
query_start(struct query * z,unsigned char * dn,unsigned char type[2],unsigned char class[2],unsigned char localip[32])1244 int query_start(struct query *z,unsigned char *dn,unsigned char type[2],unsigned char class[2],unsigned char localip[32])
1245 {
1246   if (byte_isequal(type,2,DNS_T_AXFR)) { errno = EPERM; return -1; }
1247 
1248   cleanup(z);
1249   z->level = 0;
1250   z->loop = 0;
1251 
1252   if (!dns_domain_copy(&z->name[0],dn)) return -1;
1253   byte_copy(z->type,2,type);
1254   byte_copy(z->class,2,class);
1255   byte_copy(z->localip,32,localip);
1256   z->ipv6[0]=0;
1257 
1258   return doit(z,0);
1259 }
1260 
query_get(struct query * z,struct pollfd * x,long long stamp)1261 int query_get(struct query *z,struct pollfd *x,long long stamp)
1262 {
1263   switch(dns_transmit_get(&z->dt,x,stamp)) {
1264     case 1:
1265       return doit(z,1);
1266     case -1:
1267       return doit(z,-1);
1268   }
1269   return 0;
1270 }
1271 
query_io(struct query * z,struct pollfd * x,long long * deadline)1272 void query_io(struct query *z,struct pollfd *x,long long *deadline)
1273 {
1274   dns_transmit_io(&z->dt,x,deadline);
1275 }
1276