Пример #1
0
unsigned int ip46_scan (char const *s, ip46_t_ref ip)
{
  unsigned int len = ip6_scan(s, ip->ip) ;
  if (len) ip->is6 = 1 ;
  else
  {
    len = ip4_scan(s, ip->ip) ;
    if (len) ip->is6 = 0 ;
  }
  return len ;
}
Пример #2
0
static int doit(stralloc *out,stralloc *fqdn)
{
  unsigned int i;
  char code;
  char ch;
  char ip[16];

  if (!stralloc_copys(out,"")) return -1;
  if (!stralloc_readyplus(fqdn,1)) return -1;
  fqdn->s[fqdn->len]=0;
  if ((i=ip6_scan(fqdn->s,ip))) {
    if (!fqdn->s[i]) {
      stralloc_copyb(out,ip,16);
      return 0;
    }
  }
  if ((i=ip4_scan(fqdn->s,ip+12))) {
    if (!fqdn->s[i]) {
      byte_zero(ip,10);
      ip[10]=ip[11]=0xff;
      stralloc_copyb(out,ip,16);
      return 0;
    }
  }
  code = 0;
  for (i = 0;i <= fqdn->len;++i) {
    if (i < fqdn->len)
      ch = fqdn->s[i];
    else
      ch = '.';

    if ((ch == '[') || (ch == ']')) continue;
    if (ch == '.') {
      if (!stralloc_append(out,&code)) return -1;
      code = 0;
      continue;
    }
    if ((ch >= '0') && (ch <= '9')) {
      code *= 10;
      code += ch - '0';
      continue;
    }

    if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1;
    if (dns_resolve(q,DNS_T_AAAA) == -1) return -1;
    if (dns_ip6_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1;
    dns_transmit_free(&dns_resolve_tx);
    dns_domain_free(&q);
    return 0;
  }

  out->len &= ~3;
  return 0;
}
Пример #3
0
unsigned int ip6_scanlist (char *out, unsigned int max, char const *s, unsigned int *num)
{
  unsigned int n = 0, w = 0 ;
  for (; s[w] && (n < max) ; n++)
  {
    char ip[16] ;
    register unsigned int i = ip6_scan(s + w, ip) ;
    if (!i) break ;
    byte_copy(out + (n << 4), 16, ip) ;
    w += i ;
    while (byte_chr(",; \t\r\n", 6, s[w]) < 6) w++ ;
  }
  *num = n ;
  return w ;
}
Пример #4
0
static int init2(DIR *dir)
{
  direntry *d;
  const char *fqdn;
  static char *q;
  static stralloc text;
  char servers[256];
  int serverslen;
  int i;
  int j;

  for (;;) {
    errno = 0;
    d = readdir(dir);
    if (!d) {
      if (errno) return 0;
      return 1;
    }

    if (d->d_name[0] != '.') {
      if (openreadclose(d->d_name,&text,32) != 1) return 0;
      if (!stralloc_append(&text,"\n")) return 0;

      fqdn = d->d_name;
      if (str_equal(fqdn,"@")) fqdn = ".";
      if (!dns_domain_fromdot(&q,fqdn,str_len(fqdn))) return 0;

      serverslen = 0;
      j = 0;
      for (i = 0;i < text.len;++i)
	if (text.s[i] == '\n') {
	  if (serverslen <= 60)
	    if (ip6_scan(text.s + j,servers + serverslen))
	      serverslen += 16;
	  j = i + 1;
	}
      byte_zero(servers + serverslen,256 - serverslen);

      if (!stralloc_catb(&data,q,dns_domain_length(q))) return 0;
      if (!stralloc_catb(&data,servers,256)) return 0;
    }
  }
}
Пример #5
0
int main()
{
  unsigned char *remotehost, *remoteip, *remoteport, *localip, *localport;
  unsigned char query[256] = {0};
  uint32 uid = 0xffffffff;          // that's our default for "not found"
  int query_len = 0;
  int pos = 0;
  char *problem = "ok";
  stralloc answer = {0};
  char strnum[FMT_ULONG];
  int  proto = 0;
  char *x;
  char lip[16] = {0};
  char rip[16] = {0};
  uint16 lport = 0;
  uint16 rport = 0;

  didentd_init();

  x = env_get("PROTO");
  if(x)
    {
      if(str_equal(x, "TCP")) proto = 4;
      if(str_equal(x, "TCP6")) proto = 6;
    }
  
  if(proto == 0)
    {
      buffer_puts(buffer_2, "warning: can't determine $PROTO\n");
      buffer_flush(buffer_2);
    }

  srandom(((long long) getpid () *
	    (long long) time(0) *
	    (long long) getppid() * 
	    (long long) random() * 
	    (long long) clock()) % 0xffffffff);

  /* since we run under tcpserver, we can get all info 
     about the remote side from the enviroment */
  remotehost = env_get("TCPREMOTEHOST");
  if (!remotehost) remotehost = "unknown";
  remoteport = env_get("TCPREMOTEPORT");  
  if (remoteport) scan_ushort(remoteport, &rport); else remoteport = "0";
  localport = env_get("TCPLOCALPORT");
  if (localport) scan_ushort(localport, &lport); else localport = "0";

  remoteip = env_get("TCPREMOTEIP");
  if (!remoteip) remoteip = "0.0.0.0";
  localip = env_get("TCPLOCALIP");
  if (!localip) localip = "0.0.0.0";
  
  if(proto == 4)
    {
      if(remoteip) 
	ip4_scan(remoteip, rip);

      if(localip) 
	ip4_scan(localip, lip);
      
      /* seed some entropy into the by IPv4 unsused bytes */
      rip[5] = (char) random() & 0xff;
      rip[6] = (char) random() & 0xff;
    }

  if(proto == 6)
    {
      if (remoteip) 
	ip6_scan(remoteip, rip);

      if (localip) 
	ip6_scan(localip, lip);
    }

  /* Read the request from the client and \0-terminate it */
  /* timeout after 60 seconds */
  query_len = timeoutread(60, stdin, query, sizeof(query) - 1);
  query[query_len] = '\0';
     
  /* If there was any data we can go on */
  problem = "empty query";
  if (query_len > 0)
    {
      problem = "illegal query";
      pos = scan_ushort(query, &lport);
      if(query[pos++] == ' ')
	if(query[pos++] == ',')
	  if(query[pos++] == ' ')
	    {
	      pos = scan_ushort(&query[pos], &rport);
	      problem = "ok";
	      
	      if(proto == 4)
		uid = get_connection_info4(lip, lport, rip, rport);
	      if(proto == 6)
		uid = get_connection_info6(lip, lport, rip, rport);
	      
	      stralloc_copyb(&answer, strnum, fmt_ulong(strnum, lport));
	      stralloc_cats(&answer, " , ");
	      stralloc_catb(&answer, strnum, fmt_ulong(strnum, rport));
	      
	      if(uid != 0xffffffff)
		problem = generate_answer(&answer, uid, lip, lport, rip, rport);
	      else
		generate_answer(&answer, uid, lip, lport, rip, rport);
	      
	      buffer_puts(buffer_1, answer.s);
	      buffer_flush(buffer_1);
	    }
    }

  /* Do logging */
  buffer_puts(buffer_2, localip);  
  buffer_puts(buffer_2, ":");
  buffer_put(buffer_2, strnum, fmt_ulong(strnum, lport));
  buffer_puts(buffer_2, " -> ");
  buffer_puts(buffer_2, remoteip);  
  buffer_puts(buffer_2, ":");
  buffer_put(buffer_2, strnum, fmt_ulong(strnum, rport));
  buffer_puts(buffer_2, " [");
  buffer_puts(buffer_2, problem);
  buffer_puts(buffer_2, "] ");
  if(uid < 0xffffffff)
      buffer_put(buffer_2, strnum, fmt_ulong(strnum,uid));
  else
       buffer_puts(buffer_2, "unknown");  
  buffer_puts(buffer_2, "\n");
  buffer_flush(buffer_2);

  return 0;
}
Пример #6
0
/* this is out work routine which is called by DJBs server code */
int respond(char *q, char qtype[2])
{
  int flaga;
  int flagaaaa;
  int flagloc;
  char ip[IP6_FMT];
  stralloc filename = { 0 };
  int fd;
  buffer b;
  char bspace[1024];
  static stralloc line;
  int match = 1;
  unsigned long linenum = 0;
  int data = 0;
  stralloc f[NUMFIELDS] = {{0}};

  /* check what the client is requesting */
  flaga = byte_equal(qtype,2,DNS_T_A);
  flagloc = byte_equal(qtype,2,DNS_T_LOC);
  flagaaaa = byte_equal(qtype,2,DNS_T_AAAA);
  if (byte_equal(qtype,2,DNS_T_ANY)) flaga = flagloc = flagaaaa = 1;
  
  /* find out in which file we should look */
  query2filename(q, &filename);

  buffer_put(buffer_2, filename.s, filename.len);
  buffer_puts(buffer_2, "\n");
  buffer_flush(buffer_2);

  fd = open_read(filename.s);
  if (fd == -1) 
    {
      strerr_warn3("unable to open file: ", filename.s, ": ", &strerr_sys);
      match = 0;
    }
  
  buffer_init(&b, read, fd, bspace, sizeof bspace);

  /* Work through the file and handout the data. */
   while(match) 
    {
      ++linenum;
      if(getln(&b, &line, &match, '\n') == -1)
	{
	  strerr_warn1("unable to read line: ", &strerr_sys);
	  break;
	}
  
      /* clean up line end */
      stralloc_cleanlineend(&line); 
      
      /* skip comments  & empty lines */
      if(line.s[0] == '#') continue;
      if(line.s[0] == 0) continue;
      
      /* seperate fields */
      fieldsep(f, NUMFIELDS, &line, ',');

      /* IPv4 */
      if(f[0].s[0] == '=')
	{
	  if (flaga) 
	    {
	      ip4_scan(f[2].s, ip);
	      data++;
	      /* put type and ttl (60s) */
	      if (!response_rstart(q, DNS_T_A, "\0\0\0\74")) return 0;
	      /* put ip */
	      if (!response_addbytes(ip, 4)) return 0;
	      /* record finished */
	      response_rfinish(RESPONSE_ANSWER);
	    }
	}

      /* IPv6 */
      if(f[0].s[0] == '6')
	{
	  if (flagaaaa) 
	    {
	      ip6_scan(f[0].s, ip);
	      data++;
	      /* put type and ttl (60s) */
	      if (!response_rstart(q, DNS_T_AAAA, "\0\0\0\74")) return 0;
	      /* put ip */
	      if (!response_addbytes(ip, 16)) return 0;
	      /* record finished */
	      response_rfinish(RESPONSE_ANSWER);
	    }
	}

      /* LOC */
      if(f[0].s[0] == 'L')
	{
	  if (flagloc) 
	    {
	      txtparse(&f[2]);
	      if(f[2].len <= 16)
		{		
		  buffer_puts(buffer_2, "filedns: warning: LOC record seems to short\n");
		  buffer_flush(buffer_2);
		}
	      data++;
	      /* put type and ttl (60s) */
	      if (!response_rstart(q, DNS_T_LOC, "\0\0\0\74")) return 0;
	      /* put ip */
	      if (!response_addbytes(f[2].s, 16)) return 0;
	      /* record finished */
	      response_rfinish(RESPONSE_ANSWER);
	    }
	}
    }
  
  /* Disclaimer ;-) */
  if (!response_rstart(q, DNS_T_TXT, "\0\0\0\74")) return 0;
  if (!response_addbytes("this is a response from an alpha quality dns-server", 51)) return 0;
  response_rfinish(RESPONSE_ADDITIONAL);
  if (!response_rstart(q, DNS_T_TXT, "\0\0\0\74")) return 0;
  if (!response_addbytes("filednes 0.00 - if problems arise contact [email protected]", 54)) return 0;
  response_rfinish(RESPONSE_ADDITIONAL);
  
  //  if (flaga || flagptr) 
  //    {
  //      if (dd(q,"",ip) == 4) 
  //	{
  //	  if (flaga) 
  //	    {
  //	      if (!response_rstart(q,DNS_T_A,"\0\12\0\0")) return 0;
  //	      if (!response_addbytes(ip,4)) return 0;
  //	      response_rfinish(RESPONSE_ANSWER);
  //	    }
  //	  return 1;
  //	}
  //      j = dd(q,"\7in-addr\4arpa",ip);
  //      if (j >= 0) 
  //	{
 
  if(data > 0) return 1;

  /* nothing found */
  buffer_puts(buffer_2, "notfound\n");
  buffer_flush(buffer_2);

  // XXX: this is somehow broken
  /* response 0-1 is transaction id */
  /* set response flags */
  /* clear authority bit */
  response[2] &= ~4;
  /* clear last 4 bits */
  response[3] &= ~15;
  /* flag not found */
  response[3] |= 3;
  
  /* response[4..5]:   nr of questions
   * response[6..7]:   nr of answers rr
   * response[8..9]:   nr of authority rr
   * response[10..11]: nr of additional rr
   */

  return 1;
}
Пример #7
0
int main(int argc,char **argv)
{
  unsigned long ttl;
  struct stat st;
  int i;
  int j;
  int k;
  char ch;

  if (!*argv) die_usage();

  if (!*++argv) die_usage();
  fn = *argv;

  if (!*++argv) die_usage();
  fnnew = *argv;

  if (!*++argv) die_usage();
  if (str_diff(*argv,"add")) die_usage();

  if (!*++argv) die_usage();
  if (str_equal(*argv,"ns")) mode = '.';
  else if (str_equal(*argv,"childns")) mode = '&';
  else if (str_equal(*argv,"host")) mode = '=';
  else if (str_equal(*argv,"host6")) mode = '6';
  else if (str_equal(*argv,"alias")) mode = '+';
  else if (str_equal(*argv,"alias6")) mode = '3';
  else if (str_equal(*argv,"mx")) mode = '@';
  else die_usage();

  if (!*++argv) die_usage();
  if (!dns_domain_fromdot(&target,*argv,str_len(*argv))) nomem();

  if (!*++argv) die_usage();
  if (mode == '6' || mode == '3') {
    if (!ip6_scan(*argv,targetip6)) die_usage();
  } else {
    if (!ip4_scan(*argv,targetip)) die_usage();
  }

  umask(077);

  fd = open_read(fn);
  if (fd == -1) die_read();
  if (fstat(fd,&st) == -1) die_read();
  buffer_init(&b,buffer_unixread,fd,bspace,sizeof bspace);

  fdnew = open_trunc(fnnew);
  if (fdnew == -1) die_write();
  if (fchmod(fdnew,st.st_mode & 0644) == -1) die_write();
  buffer_init(&bnew,buffer_unixwrite,fdnew,bnewspace,sizeof bnewspace);

  switch(mode) {
    case '.': case '&':
      ttl = TTL_NS;
      for (i = 0;i < 26;++i) {
	ch = 'a' + i;
	if (!stralloc_copyb(&f[0],&ch,1)) nomem();
	if (!stralloc_cats(&f[0],".ns.")) nomem();
	if (!dns_domain_todot_cat(&f[0],target)) nomem();
	if (!dns_domain_fromdot(&names[i],f[0].s,f[0].len)) nomem();
      }
      break;
    case '+': case '=': case '6': case '3':
      ttl = TTL_POSITIVE;
      break;
    case '@':
      ttl = TTL_POSITIVE;
      for (i = 0;i < 26;++i) {
	ch = 'a' + i;
	if (!stralloc_copyb(&f[0],&ch,1)) nomem();
	if (!stralloc_cats(&f[0],".mx.")) nomem();
	if (!dns_domain_todot_cat(&f[0],target)) nomem();
	if (!dns_domain_fromdot(&names[i],f[0].s,f[0].len)) nomem();
      }
      break;
  }

  while (match) {
    if (getln(&b,&line,&match,'\n') == -1) die_read();

    put(line.s,line.len);
    if (line.len && !match) put("\n",1);

    while (line.len) {
      ch = line.s[line.len - 1];
      if ((ch != ' ') && (ch != '\t') && (ch != '\n')) break;
      --line.len;
    }
    if (!line.len) continue;
    if (line.s[0] == '#') continue;

    j = 1;
    for (i = 0;i < NUMFIELDS;++i) {
      if (j >= line.len) {
	if (!stralloc_copys(&f[i],"")) nomem();
      }
      else {
        k = byte_chr(line.s + j,line.len - j,':');
	if (!stralloc_copyb(&f[i],line.s + j,k)) nomem();
	j += k + 1;
      }
    }

    switch(mode) {
      case '.': case '&':
	if (line.s[0] == mode) {
          if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
	  if (dns_domain_equal(d1,target)) {
	    if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) {
	      if (!stralloc_cats(&f[2],".ns.")) nomem();
	      if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem();
	    }
	    if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem();
	    if (!stralloc_0(&f[3])) nomem();
	    if (!scan_ulong(f[3].s,&ttl)) ttl = TTL_NS;
	    for (i = 0;i < 26;++i)
	      if (dns_domain_equal(d2,names[i])) {
	        used[i] = 1;
		break;
	      }
	  }
	}
	break;

      case '=':
	if (line.s[0] == '=') {
	  if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
	  if (dns_domain_equal(d1,target))
	    strerr_die2x(100,FATAL,"host name already used");
	  if (!stralloc_0(&f[1])) nomem();
	  if (ip4_scan(f[1].s,ip))
	    if (byte_equal(ip,4,targetip))
	      strerr_die2x(100,FATAL,"IP address already used");
	}
	break;

      case '6':
	if (line.s[0] == '6') {
	  if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
	  if (dns_domain_equal(d1,target))
	    strerr_die2x(100,FATAL,"host name already used");
	  if (!stralloc_0(&f[1])) nomem();
	  if (ip6_scan(f[1].s,ip6))
	    if (byte_equal(ip,16,targetip6))
	      strerr_die2x(100,FATAL,"IPv6 address already used");
	}
	break;

      case '@':
	if (line.s[0] == '@') {
          if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
	  if (dns_domain_equal(d1,target)) {
	    if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) {
	      if (!stralloc_cats(&f[2],".mx.")) nomem();
	      if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem();
	    }
	    if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem();
	    if (!stralloc_0(&f[4])) nomem();
	    if (!scan_ulong(f[4].s,&ttl)) ttl = TTL_POSITIVE;
	    for (i = 0;i < 26;++i)
	      if (dns_domain_equal(d2,names[i])) {
	        used[i] = 1;
		break;
	      }
	  }
	}
	break;
    }
  }

  if (!stralloc_copyb(&f[0],&mode,1)) nomem();
  if (!dns_domain_todot_cat(&f[0],target)) nomem();
  if (!stralloc_cats(&f[0],":")) nomem();
  if (mode == '6' || mode == '3') {
    if (!stralloc_catb(&f[0],ip6str,ip6_fmt_flat(ip6str,targetip6))) nomem();
  } else {
    if (!stralloc_catb(&f[0],ipstr,ip4_fmt(ipstr,targetip))) nomem();
  }
  switch(mode) {
    case '.': case '&': case '@':
      for (i = 0;i < 26;++i)
	if (!used[i])
	  break;
      if (i >= 26)
	strerr_die2x(100,FATAL,"too many records for that domain");
      ch = 'a' + i;
      if (!stralloc_cats(&f[0],":")) nomem();
      if (!stralloc_catb(&f[0],&ch,1)) nomem();
      if (mode == '@')
        if (!stralloc_cats(&f[0],":")) nomem();
      break;
  }
  if (!stralloc_cats(&f[0],":")) nomem();
  if (!stralloc_catb(&f[0],strnum,fmt_ulong(strnum,ttl))) nomem();
  if (!stralloc_cats(&f[0],"\n")) nomem();
  put(f[0].s,f[0].len);

  if (buffer_flush(&bnew) == -1) die_write();
  if (fsync(fdnew) == -1) die_write();
  if (close(fdnew) == -1) die_write(); /* NFS dorks */
  if (rename(fnnew,fn) == -1)
    strerr_die6sys(111,FATAL,"unable to move ",fnnew," to ",fn,": ");
  _exit(0);
}
Пример #8
0
int main()
{
  char *x;
  unsigned int i, j, k;
  unsigned long cachesize;
  static stralloc sa = {0};

  x = env_get("INTERFACE");
  if (x) scan_ulong(x,&interface);

  x = env_get("IP");
  if (!x)
    strerr_die2x(111,FATAL,"$IP not set");
  if (!ip6_scan(x,myipincoming))
    strerr_die3x(111,FATAL,"unable to parse IP address ",x);

#if 0
  /* if if IP is a mapped-IPv4 address, disable IPv6 functionality */
  /* this is actually a bad idea */
  if (ip6_isv4mapped(myipincoming))
    noipv6 = 1;
#endif

  udp53 = socket_udp6();
  if (udp53 == -1)
    strerr_die2sys(111,FATAL,"unable to create UDP socket: ");
  if (socket_bind6_reuse(udp53,myipincoming,53,interface) == -1)
    strerr_die2sys(111,FATAL,"unable to bind UDP socket: ");

  tcp53 = socket_tcp6();
  if (tcp53 == -1)
    strerr_die2sys(111,FATAL,"unable to create TCP socket: ");
  if (socket_bind6_reuse(tcp53,myipincoming,53,interface) == -1)
    strerr_die2sys(111,FATAL,"unable to bind TCP socket: ");

  droproot(FATAL);

  socket_tryreservein(udp53,131072);

  byte_zero(seed,sizeof seed);
  read(0,seed,sizeof seed);
  dns_random_init(seed);
  close(0);

  x = env_get("IPSEND");
  if (!x)
    strerr_die2x(111,FATAL,"$IPSEND not set");
  if (!ip6_scan(x,myipoutgoing))
    strerr_die3x(111,FATAL,"unable to parse IP address ",x);

  x = env_get("CACHESIZE");
  if (!x)
    strerr_die2x(111,FATAL,"$CACHESIZE not set");
  scan_ulong(x,&cachesize);
  if (!cache_init(cachesize))
    strerr_die3x(111,FATAL,"not enough memory for cache of size ",x);

  if (openreadclose("ignoreip",&sa,64) < 0) 
    strerr_die2x(111,FATAL,"trouble reading ignoreip");
  for(j = k = i = 0; i < sa.len; i++)
    if (sa.s[i] == '\n')  {
      sa.s[i] = '\0';
      if (!stralloc_readyplus(&ignoreip,16))
	strerr_die2x(111,FATAL,"out of memory parsing ignoreip");
      if (!ip6_scan(sa.s+k,ignoreip.s+j))
        strerr_die3x(111,FATAL,"unable to parse address in ignoreip ",ignoreip.s+k);
      j += 16;
      k = i + 1;
    }
  ignoreip.len = j;

  if (env_get("HIDETTL"))
    response_hidettl();
  if (env_get("FORWARDONLY"))
    query_forwardonly();

  if (!roots_init())
    strerr_die2sys(111,FATAL,"unable to read servers: ");

  if (socket_listen(tcp53,20) == -1)
    strerr_die2sys(111,FATAL,"unable to listen on TCP socket: ");

  log_startup();
  doit();
}
Пример #9
0
int main()
{
  unsigned int pos;
  char header[12];
  char qtype[2];
  char qclass[2];
  const char *x;

  droproot(FATAL);
  dns_random_init(seed);

  axfr = env_get("AXFR");
  
  x = env_get("TCPREMOTEIP");
  if (x && ip6_scan(x,ip))
    ;
  else
    byte_zero(ip,16);

  x = env_get("TCPREMOTEPORT");
  if (!x) x = "0";
  scan_ulong(x,&port);

  for (;;) {
    netread(tcpheader,2);
    uint16_unpack_big(tcpheader,&len);
    if (len > 512) strerr_die2x(111,FATAL,"excessively large request");
    netread(buf,len);

    pos = dns_packet_copy(buf,len,0,header,12); if (!pos) die_truncated();
    if (header[2] & 254) strerr_die2x(111,FATAL,"bogus query");
    if (header[4] || (header[5] != 1)) strerr_die2x(111,FATAL,"bogus query");

    pos = dns_packet_getname(buf,len,pos,&zone); if (!pos) die_truncated();
    zonelen = dns_domain_length(zone);
    pos = dns_packet_copy(buf,len,pos,qtype,2); if (!pos) die_truncated();
    pos = dns_packet_copy(buf,len,pos,qclass,2); if (!pos) die_truncated();

    if (byte_diff(qclass,2,DNS_C_IN) && byte_diff(qclass,2,DNS_C_ANY))
      strerr_die2x(111,FATAL,"bogus query: bad class");

    pos = check_edns0(header, buf, len, pos);
    if (!pos) die_truncated();

    qlog(ip,port,header,zone,qtype," ");

    if (byte_equal(qtype,2,DNS_T_AXFR)) {
      case_lowerb(zone,zonelen);
      fdcdb = open_read("data.cdb");
      if (fdcdb == -1) die_cdbread();
      doaxfr(header);
      close(fdcdb);
    }
    else {
      if (!response_query(zone,qtype,qclass)) nomem();
      response[2] |= 4;
      case_lowerb(zone,zonelen);
      response_id(header);
      response[3] &= ~128;
      if (!(header[2] & 1)) response[2] &= ~1;
      if (!respond(zone,qtype,ip)) die_outside();
      print(response,response_len);
    }
  }
}