Attachment 'query.c'

Download

   1 #include "error.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 "uint64.h"
   9 #include "uint32.h"
  10 #include "uint16.h"
  11 #include "dd.h"
  12 #include "alloc.h"
  13 #include "response.h"
  14 #include "query.h"
  15 
  16 static int flagforwardonly = 0;
  17 
  18 void query_forwardonly(void)
  19 {
  20   flagforwardonly = 1;
  21 }
  22 
  23 static void cachegeneric(const char type[2],const char *d,const char *data,unsigned int datalen,uint32 ttl)
  24 {
  25   unsigned int len;
  26   char key[257];
  27 
  28   len = dns_domain_length(d);
  29   if (len > 255) return;
  30 
  31   byte_copy(key,2,type);
  32   byte_copy(key + 2,len,d);
  33   case_lowerb(key + 2,len);
  34 
  35   cache_set(key,len + 2,data,datalen,ttl);
  36 }
  37 
  38 static char save_buf[8192];
  39 static unsigned int save_len;
  40 static unsigned int save_ok;
  41 
  42 static void save_start(void)
  43 {
  44   save_len = 0;
  45   save_ok = 1;
  46 }
  47 
  48 static void save_data(const char *buf,unsigned int len)
  49 {
  50   if (!save_ok) return;
  51   if (len > (sizeof save_buf) - save_len) { save_ok = 0; return; }
  52   byte_copy(save_buf + save_len,len,buf);
  53   save_len += len;
  54 }
  55 
  56 static void save_finish(const char type[2],const char *d,uint32 ttl)
  57 {
  58   if (!save_ok) return;
  59   cachegeneric(type,d,save_buf,save_len,ttl);
  60 }
  61 
  62 
  63 static int typematch(const char rtype[2],const char qtype[2])
  64 {
  65   return byte_equal(qtype,2,rtype) || byte_equal(qtype,2,DNS_T_ANY);
  66 }
  67 
  68 static uint32 ttlget(char buf[4])
  69 {
  70   uint32 ttl;
  71 
  72   uint32_unpack_big(buf,&ttl);
  73   if (ttl > 1000000000) return 0;
  74   if (ttl > 604800) return 604800;
  75   return ttl;
  76 }
  77 
  78 
  79 static void cleanup(struct query *z)
  80 {
  81   int j;
  82   int k;
  83 
  84   dns_transmit_free(&z->dt);
  85   for (j = 0;j < QUERY_MAXALIAS;++j)
  86     dns_domain_free(&z->alias[j]);
  87   for (j = 0;j < QUERY_MAXLEVEL;++j) {
  88     dns_domain_free(&z->name[j]);
  89     for (k = 0;k < QUERY_MAXNS;++k)
  90       dns_domain_free(&z->ns[j][k]);
  91   }
  92 }
  93 
  94 static int rqa(struct query *z)
  95 {
  96   int i;
  97 
  98   for (i = QUERY_MAXALIAS - 1;i >= 0;--i)
  99     if (z->alias[i]) {
 100       if (!response_query(z->alias[i],z->type,z->class)) return 0;
 101       while (i > 0) {
 102         if (!response_cname(z->alias[i],z->alias[i - 1],z->aliasttl[i])) return 0;
 103         --i;
 104       }
 105       if (!response_cname(z->alias[0],z->name[0],z->aliasttl[0])) return 0;
 106       return 1;
 107     }
 108 
 109   if (!response_query(z->name[0],z->type,z->class)) return 0;
 110   return 1;
 111 }
 112 
 113 static int globalip(char *d,char ip[4])
 114 {
 115   if (dns_domain_equal(d,"\011localhost\0")) {
 116     byte_copy(ip,4,"\177\0\0\1");
 117     return 1;
 118   }
 119   if (dd(d,"",ip) == 4) return 1;
 120   return 0;
 121 }
 122 
 123 static char *t1 = 0;
 124 static char *t2 = 0;
 125 static char *t3 = 0;
 126 static char *cname = 0;
 127 static char *referral = 0;
 128 static unsigned int *records = 0;
 129 
 130 static int smaller(char *buf,unsigned int len,unsigned int pos1,unsigned int pos2)
 131 {
 132   char header1[12];
 133   char header2[12];
 134   int r;
 135   unsigned int len1;
 136   unsigned int len2;
 137 
 138   pos1 = dns_packet_getname(buf,len,pos1,&t1);
 139   dns_packet_copy(buf,len,pos1,header1,10);
 140   pos2 = dns_packet_getname(buf,len,pos2,&t2);
 141   dns_packet_copy(buf,len,pos2,header2,10);
 142 
 143   r = byte_diff(header1,4,header2);
 144   if (r < 0) return 1;
 145   if (r > 0) return 0;
 146 
 147   len1 = dns_domain_length(t1);
 148   len2 = dns_domain_length(t2);
 149   if (len1 < len2) return 1;
 150   if (len1 > len2) return 0;
 151 
 152   r = case_diffb(t1,len1,t2);
 153   if (r < 0) return 1;
 154   if (r > 0) return 0;
 155 
 156   if (pos1 < pos2) return 1;
 157   return 0;
 158 }
 159 
 160 static int doit(struct query *z,int state)
 161 {
 162   char key[257];
 163   char *cached;
 164   unsigned int cachedlen;
 165   char *buf;
 166   unsigned int len;
 167   const char *whichserver;
 168   char header[12];
 169   char misc[20];
 170   unsigned int rcode;
 171   unsigned int posanswers;
 172   uint16 numanswers;
 173   unsigned int posauthority;
 174   uint16 numauthority;
 175   unsigned int posglue;
 176   uint16 numglue;
 177   unsigned int pos;
 178   unsigned int pos2;
 179   uint16 datalen;
 180   char *control;
 181   char *d;
 182   const char *dtype;
 183   unsigned int dlen;
 184   int flagout;
 185   int flagcname;
 186   int flagreferral;
 187   int flagsoa;
 188   uint32 ttl;
 189   uint32 soattl;
 190   uint32 cnamettl;
 191   int i;
 192   int j;
 193   int k;
 194   int p;
 195   int q;
 196 
 197   errno = error_io;
 198   if (state == 1) goto HAVEPACKET;
 199   if (state == -1) {
 200     log_servfail(z->name[z->level]);
 201     goto SERVFAIL;
 202   }
 203 
 204 
 205   NEWNAME:
 206   if (++z->loop == 100) goto DIE;
 207   d = z->name[z->level];
 208   dtype = z->level ? DNS_T_A : z->type;
 209   dlen = dns_domain_length(d);
 210 
 211   if (globalip(d,misc)) {
 212     if (z->level) {
 213       for (k = 0;k < 64;k += 4)
 214         if (byte_equal(z->servers[z->level - 1] + k,4,"\0\0\0\0")) {
 215 	  byte_copy(z->servers[z->level - 1] + k,4,misc);
 216 	  break;
 217 	}
 218       goto LOWERLEVEL;
 219     }
 220     if (!rqa(z)) goto DIE;
 221     if (typematch(DNS_T_A,dtype)) {
 222       if (!response_rstart(d,DNS_T_A,655360)) goto DIE;
 223       if (!response_addbytes(misc,4)) goto DIE;
 224       response_rfinish(RESPONSE_ANSWER);
 225     }
 226     cleanup(z);
 227     return 1;
 228   }
 229 
 230   if (dns_domain_equal(d,"\0011\0010\0010\003127\7in-addr\4arpa\0")) {
 231     if (z->level) goto LOWERLEVEL;
 232     if (!rqa(z)) goto DIE;
 233     if (typematch(DNS_T_PTR,dtype)) {
 234       if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
 235       if (!response_addname("\011localhost\0")) goto DIE;
 236       response_rfinish(RESPONSE_ANSWER);
 237     }
 238     cleanup(z);
 239     log_stats();
 240     return 1;
 241   }
 242 
 243   if (dlen <= 255) {
 244     byte_copy(key,2,DNS_T_ANY);
 245     byte_copy(key + 2,dlen,d);
 246     case_lowerb(key + 2,dlen);
 247     cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
 248     if (cached) {
 249       log_cachednxdomain(d);
 250       goto NXDOMAIN;
 251     }
 252 
 253     byte_copy(key,2,DNS_T_CNAME);
 254     cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
 255     if (cached) {
 256       if (typematch(DNS_T_CNAME,dtype)) {
 257         log_cachedanswer(d,DNS_T_CNAME);
 258         if (!rqa(z)) goto DIE;
 259 	if (!response_cname(z->name[0],cached,ttl)) goto DIE;
 260 	cleanup(z);
 261 	return 1;
 262       }
 263       log_cachedcname(d,cached);
 264       if (!dns_domain_copy(&cname,cached)) goto DIE;
 265       goto CNAME;
 266     }
 267 
 268     if (typematch(DNS_T_NS,dtype)) {
 269       byte_copy(key,2,DNS_T_NS);
 270       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
 271       if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
 272 	log_cachedanswer(d,DNS_T_NS);
 273 	if (!rqa(z)) goto DIE;
 274 	pos = 0;
 275 	while (pos = dns_packet_getname(cached,cachedlen,pos,&t2)) {
 276 	  if (!response_rstart(d,DNS_T_NS,ttl)) goto DIE;
 277 	  if (!response_addname(t2)) goto DIE;
 278 	  response_rfinish(RESPONSE_ANSWER);
 279 	}
 280 	cleanup(z);
 281 	return 1;
 282       }
 283     }
 284 
 285     if (typematch(DNS_T_PTR,dtype)) {
 286       byte_copy(key,2,DNS_T_PTR);
 287       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
 288       if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
 289 	log_cachedanswer(d,DNS_T_PTR);
 290 	if (!rqa(z)) goto DIE;
 291 	pos = 0;
 292 	while (pos = dns_packet_getname(cached,cachedlen,pos,&t2)) {
 293 	  if (!response_rstart(d,DNS_T_PTR,ttl)) goto DIE;
 294 	  if (!response_addname(t2)) goto DIE;
 295 	  response_rfinish(RESPONSE_ANSWER);
 296 	}
 297 	cleanup(z);
 298 	return 1;
 299       }
 300     }
 301 
 302     if (typematch(DNS_T_MX,dtype)) {
 303       byte_copy(key,2,DNS_T_MX);
 304       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
 305       if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
 306 	log_cachedanswer(d,DNS_T_MX);
 307 	if (!rqa(z)) goto DIE;
 308 	pos = 0;
 309 	while (pos = dns_packet_copy(cached,cachedlen,pos,misc,2)) {
 310 	  pos = dns_packet_getname(cached,cachedlen,pos,&t2);
 311 	  if (!pos) break;
 312 	  if (!response_rstart(d,DNS_T_MX,ttl)) goto DIE;
 313 	  if (!response_addbytes(misc,2)) goto DIE;
 314 	  if (!response_addname(t2)) goto DIE;
 315 	  response_rfinish(RESPONSE_ANSWER);
 316 	}
 317 	cleanup(z);
 318 	return 1;
 319       }
 320     }
 321 
 322     if (typematch(DNS_T_A,dtype)) {
 323       byte_copy(key,2,DNS_T_A);
 324       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
 325       if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
 326 	if (z->level) {
 327 	  log_cachedanswer(d,DNS_T_A);
 328 	  while (cachedlen >= 4) {
 329 	    for (k = 0;k < 64;k += 4)
 330 	      if (byte_equal(z->servers[z->level - 1] + k,4,"\0\0\0\0")) {
 331 		byte_copy(z->servers[z->level - 1] + k,4,cached);
 332 		break;
 333 	      }
 334 	    cached += 4;
 335 	    cachedlen -= 4;
 336 	  }
 337 	  goto LOWERLEVEL;
 338 	}
 339 
 340 	log_cachedanswer(d,DNS_T_A);
 341 	if (!rqa(z)) goto DIE;
 342 	while (cachedlen >= 4) {
 343 	  if (!response_rstart(d,DNS_T_A,ttl)) goto DIE;
 344 	  if (!response_addbytes(cached,4)) goto DIE;
 345 	  response_rfinish(RESPONSE_ANSWER);
 346 	  cached += 4;
 347 	  cachedlen -= 4;
 348 	}
 349 	cleanup(z);
 350 	return 1;
 351       }
 352     }
 353 
 354     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)) {
 355       byte_copy(key,2,dtype);
 356       cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
 357       if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
 358 	log_cachedanswer(d,dtype);
 359 	if (!rqa(z)) goto DIE;
 360 	while (cachedlen >= 2) {
 361 	  uint16_unpack_big(cached,&datalen);
 362 	  cached += 2;
 363 	  cachedlen -= 2;
 364 	  if (datalen > cachedlen) goto DIE;
 365 	  if (!response_rstart(d,dtype,ttl)) goto DIE;
 366 	  if (!response_addbytes(cached,datalen)) goto DIE;
 367 	  response_rfinish(RESPONSE_ANSWER);
 368 	  cached += datalen;
 369 	  cachedlen -= datalen;
 370 	}
 371 	cleanup(z);
 372 	return 1;
 373       }
 374     }
 375   }
 376 
 377   for (;;) {
 378     if (roots(z->servers[z->level],d)) {
 379       for (j = 0;j < QUERY_MAXNS;++j)
 380         dns_domain_free(&z->ns[z->level][j]);
 381       z->control[z->level] = d;
 382       break;
 383     }
 384 
 385     if (!flagforwardonly && (z->level < 2))
 386       if (dlen < 255) {
 387         byte_copy(key,2,DNS_T_NS);
 388         byte_copy(key + 2,dlen,d);
 389         case_lowerb(key + 2,dlen);
 390         cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
 391         if (cached && cachedlen) {
 392 	  z->control[z->level] = d;
 393           byte_zero(z->servers[z->level],64);
 394           for (j = 0;j < QUERY_MAXNS;++j)
 395             dns_domain_free(&z->ns[z->level][j]);
 396           pos = 0;
 397           j = 0;
 398           while (pos = dns_packet_getname(cached,cachedlen,pos,&t1)) {
 399 	    log_cachedns(d,t1);
 400             if (j < QUERY_MAXNS)
 401               if (!dns_domain_copy(&z->ns[z->level][j++],t1)) goto DIE;
 402 	  }
 403           break;
 404         }
 405       }
 406 
 407     if (!*d) goto DIE;
 408     j = 1 + (unsigned int) (unsigned char) *d;
 409     dlen -= j;
 410     d += j;
 411   }
 412 
 413 
 414   HAVENS:
 415   for (j = 0;j < QUERY_MAXNS;++j)
 416     if (z->ns[z->level][j]) {
 417       if (z->level + 1 < QUERY_MAXLEVEL) {
 418         if (!dns_domain_copy(&z->name[z->level + 1],z->ns[z->level][j])) goto DIE;
 419         dns_domain_free(&z->ns[z->level][j]);
 420         ++z->level;
 421         goto NEWNAME;
 422       }
 423       dns_domain_free(&z->ns[z->level][j]);
 424     }
 425 
 426   for (j = 0;j < 64;j += 4)
 427     if (byte_diff(z->servers[z->level] + j,4,"\0\0\0\0"))
 428       break;
 429   if (j == 64) goto SERVFAIL;
 430 
 431   dns_sortip(z->servers[z->level],64);
 432   if (z->level) {
 433     log_tx(z->name[z->level],DNS_T_A,z->control[z->level],z->servers[z->level],z->level);
 434     if (dns_transmit_start(&z->dt,z->servers[z->level],flagforwardonly,z->name[z->level],DNS_T_A,z->localip) == -1) goto DIE;
 435   }
 436   else {
 437     log_tx(z->name[0],z->type,z->control[0],z->servers[0],0);
 438     if (dns_transmit_start(&z->dt,z->servers[0],flagforwardonly,z->name[0],z->type,z->localip) == -1) goto DIE;
 439   }
 440   return 0;
 441 
 442 
 443   LOWERLEVEL:
 444   dns_domain_free(&z->name[z->level]);
 445   for (j = 0;j < QUERY_MAXNS;++j)
 446     dns_domain_free(&z->ns[z->level][j]);
 447   --z->level;
 448   goto HAVENS;
 449 
 450 
 451   HAVEPACKET:
 452   if (++z->loop == 100) goto DIE;
 453   buf = z->dt.packet;
 454   len = z->dt.packetlen;
 455 
 456   whichserver = z->dt.servers + 4 * z->dt.curserver;
 457   control = z->control[z->level];
 458   d = z->name[z->level];
 459   dtype = z->level ? DNS_T_A : z->type;
 460 
 461   pos = dns_packet_copy(buf,len,0,header,12); if (!pos) goto DIE;
 462   pos = dns_packet_skipname(buf,len,pos); if (!pos) goto DIE;
 463   pos += 4;
 464   posanswers = pos;
 465 
 466   uint16_unpack_big(header + 6,&numanswers);
 467   uint16_unpack_big(header + 8,&numauthority);
 468   uint16_unpack_big(header + 10,&numglue);
 469 
 470   rcode = header[3] & 15;
 471   if (rcode && (rcode != 3)) goto DIE; /* impossible; see irrelevant() */
 472 
 473   flagout = 0;
 474   flagcname = 0;
 475   flagreferral = 0;
 476   flagsoa = 0;
 477   soattl = 0;
 478   cnamettl = 0;
 479   for (j = 0;j < numanswers;++j) {
 480     pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
 481     pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
 482 
 483     if (dns_domain_equal(t1,d))
 484       if (byte_equal(header + 2,2,DNS_C_IN)) { /* should always be true */
 485         if (typematch(header,dtype))
 486           flagout = 1;
 487         else if (typematch(header,DNS_T_CNAME)) {
 488           if (!dns_packet_getname(buf,len,pos,&cname)) goto DIE;
 489           flagcname = 1;
 490 	  cnamettl = ttlget(header + 4);
 491         }
 492       }
 493   
 494     uint16_unpack_big(header + 8,&datalen);
 495     pos += datalen;
 496   }
 497   posauthority = pos;
 498 
 499   for (j = 0;j < numauthority;++j) {
 500     pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
 501     pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
 502 
 503     if (typematch(header,DNS_T_SOA)) {
 504       flagsoa = 1;
 505       soattl = ttlget(header + 4);
 506       if (soattl > 3600) soattl = 3600;
 507     }
 508     else if (typematch(header,DNS_T_NS)) {
 509       flagreferral = 1;
 510       if (!dns_domain_copy(&referral,t1)) goto DIE;
 511     }
 512 
 513     uint16_unpack_big(header + 8,&datalen);
 514     pos += datalen;
 515   }
 516   posglue = pos;
 517 
 518 
 519   if (!flagcname && !rcode && !flagout && flagreferral && !flagsoa)
 520     if (dns_domain_equal(referral,control) || !dns_domain_suffix(referral,control)) {
 521       log_lame(whichserver,control,referral);
 522       byte_zero(whichserver,4);
 523       goto HAVENS;
 524     }
 525 
 526 
 527   if (records) { alloc_free(records); records = 0; }
 528   k = numanswers;
 529   if (k==0)  k = numauthority + numglue;
 530   records = (unsigned int *) alloc(k * sizeof(unsigned int));
 531   if (!records) goto DIE;
 532 
 533   pos = posanswers;
 534   for (j = 0;j < k;++j) {
 535     records[j] = pos;
 536     pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
 537     pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
 538     uint16_unpack_big(header + 8,&datalen);
 539     pos += datalen;
 540   }
 541 
 542   i = j = k;
 543   while (j > 1) {
 544     if (i > 1) { --i; pos = records[i - 1]; }
 545     else { pos = records[j - 1]; records[j - 1] = records[i - 1]; --j; }
 546 
 547     q = i;
 548     while ((p = q * 2) < j) {
 549       if (!smaller(buf,len,records[p],records[p - 1])) ++p;
 550       records[q - 1] = records[p - 1]; q = p;
 551     }
 552     if (p == j) {
 553       records[q - 1] = records[p - 1]; q = p;
 554     }
 555     while ((q > i) && smaller(buf,len,records[(p = q/2) - 1],pos)) {
 556       records[q - 1] = records[p - 1]; q = p;
 557     }
 558     records[q - 1] = pos;
 559   }
 560 
 561   i = 0;
 562   while (i < k) {
 563     char type[2];
 564 
 565     pos = dns_packet_getname(buf,len,records[i],&t1); if (!pos) goto DIE;
 566     pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
 567     ttl = ttlget(header + 4);
 568 
 569     byte_copy(type,2,header);
 570     if (byte_diff(header + 2,2,DNS_C_IN)) { ++i; continue; }
 571 
 572     for (j = i + 1;j < k;++j) {
 573       pos = dns_packet_getname(buf,len,records[j],&t2); if (!pos) goto DIE;
 574       pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
 575       if (!dns_domain_equal(t1,t2)) break;
 576       if (byte_diff(header,2,type)) break;
 577       if (byte_diff(header + 2,2,DNS_C_IN)) break;
 578     }
 579 
 580     if (!dns_domain_suffix(t1,control)) { i = j; continue; }
 581     if (!roots_same(t1,control)) { i = j; continue; }
 582 
 583     if (byte_equal(type,2,DNS_T_ANY))
 584       ;
 585     else if (byte_equal(type,2,DNS_T_AXFR))
 586       ;
 587     else if (byte_equal(type,2,DNS_T_SOA)) {
 588       while (i < j) {
 589         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
 590         pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE;
 591         pos = dns_packet_getname(buf,len,pos,&t3); if (!pos) goto DIE;
 592         pos = dns_packet_copy(buf,len,pos,misc,20); if (!pos) goto DIE;
 593         if (records[i] < posauthority)
 594           log_rrsoa(whichserver,t1,t2,t3,misc,ttl);
 595         ++i;
 596       }
 597     }
 598     else if (byte_equal(type,2,DNS_T_CNAME)) {
 599       pos = dns_packet_skipname(buf,len,records[j - 1]); if (!pos) goto DIE;
 600       pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE;
 601       log_rrcname(whichserver,t1,t2,ttl);
 602       cachegeneric(DNS_T_CNAME,t1,t2,dns_domain_length(t2),ttl);
 603     }
 604     else if (byte_equal(type,2,DNS_T_PTR)) {
 605       save_start();
 606       while (i < j) {
 607         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
 608         pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE;
 609         log_rrptr(whichserver,t1,t2,ttl);
 610         save_data(t2,dns_domain_length(t2));
 611         ++i;
 612       }
 613       save_finish(DNS_T_PTR,t1,ttl);
 614     }
 615     else if (byte_equal(type,2,DNS_T_NS)) {
 616       save_start();
 617       while (i < j) {
 618         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
 619         pos = dns_packet_getname(buf,len,pos + 10,&t2); if (!pos) goto DIE;
 620         log_rrns(whichserver,t1,t2,ttl);
 621         save_data(t2,dns_domain_length(t2));
 622         ++i;
 623       }
 624       save_finish(DNS_T_NS,t1,ttl);
 625     }
 626     else if (byte_equal(type,2,DNS_T_MX)) {
 627       save_start();
 628       while (i < j) {
 629         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
 630         pos = dns_packet_copy(buf,len,pos + 10,misc,2); if (!pos) goto DIE;
 631         pos = dns_packet_getname(buf,len,pos,&t2); if (!pos) goto DIE;
 632         log_rrmx(whichserver,t1,t2,misc,ttl);
 633         save_data(misc,2);
 634         save_data(t2,dns_domain_length(t2));
 635         ++i;
 636       }
 637       save_finish(DNS_T_MX,t1,ttl);
 638     }
 639     else if (byte_equal(type,2,DNS_T_A)) {
 640       save_start();
 641       while (i < j) {
 642         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
 643         pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
 644         if (byte_equal(header + 8,2,"\0\4")) {
 645           pos = dns_packet_copy(buf,len,pos,header,4); if (!pos) goto DIE;
 646           save_data(header,4);
 647           log_rr(whichserver,t1,DNS_T_A,header,4,ttl);
 648         }
 649         ++i;
 650       }
 651       save_finish(DNS_T_A,t1,ttl);
 652     }
 653     else {
 654       save_start();
 655       while (i < j) {
 656         pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
 657         pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
 658         uint16_unpack_big(header + 8,&datalen);
 659         if (datalen > len - pos) goto DIE;
 660         save_data(header + 8,2);
 661         save_data(buf + pos,datalen);
 662         log_rr(whichserver,t1,type,buf + pos,datalen,ttl);
 663         ++i;
 664       }
 665       save_finish(type,t1,ttl);
 666     }
 667 
 668     i = j;
 669   }
 670 
 671   alloc_free(records); records = 0;
 672 
 673 
 674   if (flagcname) {
 675     ttl = cnamettl;
 676     CNAME:
 677     if (!z->level) {
 678       if (z->alias[QUERY_MAXALIAS - 1]) goto DIE;
 679       for (j = QUERY_MAXALIAS - 1;j > 0;--j)
 680         z->alias[j] = z->alias[j - 1];
 681       for (j = QUERY_MAXALIAS - 1;j > 0;--j)
 682         z->aliasttl[j] = z->aliasttl[j - 1];
 683       z->alias[0] = z->name[0];
 684       z->aliasttl[0] = ttl;
 685       z->name[0] = 0;
 686     }
 687     if (!dns_domain_copy(&z->name[z->level],cname)) goto DIE;
 688     goto NEWNAME;
 689   }
 690 
 691   if (rcode == 3) {
 692     log_nxdomain(whichserver,d,soattl);
 693     cachegeneric(DNS_T_ANY,d,"",0,soattl);
 694 
 695     NXDOMAIN:
 696     if (z->level) goto LOWERLEVEL;
 697     if (!rqa(z)) goto DIE;
 698     response_nxdomain();
 699     cleanup(z);
 700     return 1;
 701   }
 702 
 703   if (!flagout && flagsoa)
 704     if (byte_diff(DNS_T_ANY,2,dtype))
 705       if (byte_diff(DNS_T_AXFR,2,dtype))
 706         if (byte_diff(DNS_T_CNAME,2,dtype)) {
 707           save_start();
 708           save_finish(dtype,d,soattl);
 709 	  log_nodata(whichserver,d,dtype,soattl);
 710         }
 711 
 712   log_stats();
 713 
 714 
 715   if (flagout || flagsoa || !flagreferral) {
 716     if (z->level) {
 717       pos = posanswers;
 718       for (j = 0;j < numanswers;++j) {
 719         pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
 720         pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
 721         uint16_unpack_big(header + 8,&datalen);
 722         if (dns_domain_equal(t1,d))
 723           if (typematch(header,DNS_T_A))
 724             if (byte_equal(header + 2,2,DNS_C_IN)) /* should always be true */
 725               if (datalen == 4)
 726                 for (k = 0;k < 64;k += 4)
 727                   if (byte_equal(z->servers[z->level - 1] + k,4,"\0\0\0\0")) {
 728                     if (!dns_packet_copy(buf,len,pos,z->servers[z->level - 1] + k,4)) goto DIE;
 729                     break;
 730                   }
 731         pos += datalen;
 732       }
 733       goto LOWERLEVEL;
 734     }
 735 
 736     if (!rqa(z)) goto DIE;
 737 
 738     pos = posanswers;
 739     for (j = 0;j < numanswers;++j) {
 740       pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
 741       pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
 742       ttl = ttlget(header + 4);
 743       uint16_unpack_big(header + 8,&datalen);
 744       if (dns_domain_equal(t1,d))
 745         if (byte_equal(header + 2,2,DNS_C_IN)) /* should always be true */
 746           if (typematch(header,dtype)) {
 747             if (!response_rstart(t1,header,ttl)) goto DIE;
 748   
 749             if (typematch(header,DNS_T_NS) || typematch(header,DNS_T_CNAME) || typematch(header,DNS_T_PTR)) {
 750               if (!dns_packet_getname(buf,len,pos,&t2)) goto DIE;
 751               if (!response_addname(t2)) goto DIE;
 752             }
 753             else if (typematch(header,DNS_T_MX)) {
 754               pos2 = dns_packet_copy(buf,len,pos,misc,2); if (!pos2) goto DIE;
 755               if (!response_addbytes(misc,2)) goto DIE;
 756               if (!dns_packet_getname(buf,len,pos2,&t2)) goto DIE;
 757               if (!response_addname(t2)) goto DIE;
 758             }
 759             else if (typematch(header,DNS_T_SOA)) {
 760               pos2 = dns_packet_getname(buf,len,pos,&t2); if (!pos2) goto DIE;
 761               if (!response_addname(t2)) goto DIE;
 762               pos2 = dns_packet_getname(buf,len,pos2,&t3); if (!pos2) goto DIE;
 763               if (!response_addname(t3)) goto DIE;
 764               pos2 = dns_packet_copy(buf,len,pos2,misc,20); if (!pos2) goto DIE;
 765               if (!response_addbytes(misc,20)) goto DIE;
 766             }
 767             else {
 768               if (pos + datalen > len) goto DIE;
 769               if (!response_addbytes(buf + pos,datalen)) goto DIE;
 770             }
 771   
 772             response_rfinish(RESPONSE_ANSWER);
 773           }
 774 
 775       pos += datalen;
 776     }
 777 
 778     cleanup(z);
 779     return 1;
 780   }
 781 
 782 
 783   if (!dns_domain_suffix(d,referral)) goto DIE;
 784   control = d + dns_domain_suffixpos(d,referral);
 785   z->control[z->level] = control;
 786   byte_zero(z->servers[z->level],64);
 787   for (j = 0;j < QUERY_MAXNS;++j)
 788     dns_domain_free(&z->ns[z->level][j]);
 789   k = 0;
 790 
 791   pos = posauthority;
 792   for (j = 0;j < numauthority;++j) {
 793     pos = dns_packet_getname(buf,len,pos,&t1); if (!pos) goto DIE;
 794     pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
 795     uint16_unpack_big(header + 8,&datalen);
 796     if (dns_domain_equal(referral,t1)) /* should always be true */
 797       if (typematch(header,DNS_T_NS)) /* should always be true */
 798         if (byte_equal(header + 2,2,DNS_C_IN)) /* should always be true */
 799           if (k < QUERY_MAXNS)
 800             if (!dns_packet_getname(buf,len,pos,&z->ns[z->level][k++])) goto DIE;
 801     pos += datalen;
 802   }
 803 
 804   goto HAVENS;
 805 
 806 
 807   SERVFAIL:
 808   if (z->level) goto LOWERLEVEL;
 809   if (!rqa(z)) goto DIE;
 810   response_servfail();
 811   cleanup(z);
 812   return 1;
 813 
 814 
 815   DIE:
 816   cleanup(z);
 817   if (records) { alloc_free(records); records = 0; }
 818   return -1;
 819 }
 820 
 821 int query_start(struct query *z,char *dn,char type[2],char class[2],char localip[4])
 822 {
 823   if (byte_equal(type,2,DNS_T_AXFR)) { errno = error_perm; return -1; }
 824 
 825   cleanup(z);
 826   z->level = 0;
 827   z->loop = 0;
 828 
 829   if (!dns_domain_copy(&z->name[0],dn)) return -1;
 830   byte_copy(z->type,2,type);
 831   byte_copy(z->class,2,class);
 832   byte_copy(z->localip,4,localip);
 833 
 834   return doit(z,0);
 835 }
 836 
 837 int query_get(struct query *z,iopause_fd *x,struct taia *stamp)
 838 {
 839   switch(dns_transmit_get(&z->dt,x,stamp)) {
 840     case 1:
 841       return doit(z,1);
 842     case -1:
 843       return doit(z,-1);
 844   }
 845   return 0;
 846 }
 847 
 848 void query_io(struct query *z,iopause_fd *x,struct taia *deadline)
 849 {
 850   dns_transmit_io(&z->dt,x,deadline);
 851 }

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2020-08-12 06:11:32, 23.1 KB) [[attachment:query.c]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.