File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / rfc1035.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Mon Jul 29 19:37:40 2013 UTC (10 years, 11 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    1: /* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
    2: 
    3:    This program is free software; you can redistribute it and/or modify
    4:    it under the terms of the GNU General Public License as published by
    5:    the Free Software Foundation; version 2 dated June, 1991, or
    6:    (at your option) version 3 dated 29 June, 2007.
    7:  
    8:    This program is distributed in the hope that it will be useful,
    9:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   10:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11:    GNU General Public License for more details.
   12:      
   13:    You should have received a copy of the GNU General Public License
   14:    along with this program.  If not, see <http://www.gnu.org/licenses/>.
   15: */
   16: 
   17: #include "dnsmasq.h"
   18: 
   19: 
   20: #define CHECK_LEN(header, pp, plen, len) \
   21:     ((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
   22: 
   23: #define ADD_RDLEN(header, pp, plen, len) \
   24:   (!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
   25: 
   26: int extract_name(struct dns_header *header, size_t plen, unsigned char **pp, 
   27: 		 char *name, int isExtract, int extrabytes)
   28: {
   29:   unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
   30:   unsigned int j, l, hops = 0;
   31:   int retvalue = 1;
   32:   
   33:   if (isExtract)
   34:     *cp = 0;
   35: 
   36:   while (1)
   37:     { 
   38:       unsigned int label_type;
   39: 
   40:       if (!CHECK_LEN(header, p, plen, 1))
   41: 	return 0;
   42:       
   43:       if ((l = *p++) == 0) 
   44: 	/* end marker */
   45: 	{
   46: 	  /* check that there are the correct no of bytes after the name */
   47: 	  if (!CHECK_LEN(header, p, plen, extrabytes))
   48: 	    return 0;
   49: 	  
   50: 	  if (isExtract)
   51: 	    {
   52: 	      if (cp != (unsigned char *)name)
   53: 		cp--;
   54: 	      *cp = 0; /* terminate: lose final period */
   55: 	    }
   56: 	  else if (*cp != 0)
   57: 	    retvalue = 2;
   58: 	  
   59: 	  if (p1) /* we jumped via compression */
   60: 	    *pp = p1;
   61: 	  else
   62: 	    *pp = p;
   63: 	  
   64: 	  return retvalue;
   65: 	}
   66: 
   67:       label_type = l & 0xc0;
   68:       
   69:       if (label_type == 0xc0) /* pointer */
   70: 	{ 
   71: 	  if (!CHECK_LEN(header, p, plen, 1))
   72: 	    return 0;
   73: 	      
   74: 	  /* get offset */
   75: 	  l = (l&0x3f) << 8;
   76: 	  l |= *p++;
   77: 	  
   78: 	  if (!p1) /* first jump, save location to go back to */
   79: 	    p1 = p;
   80: 	      
   81: 	  hops++; /* break malicious infinite loops */
   82: 	  if (hops > 255)
   83: 	    return 0;
   84: 	  
   85: 	  p = l + (unsigned char *)header;
   86: 	}
   87:       else if (label_type == 0x80)
   88: 	return 0; /* reserved */
   89:       else if (label_type == 0x40)
   90: 	{ /* ELT */
   91: 	  unsigned int count, digs;
   92: 	  
   93: 	  if ((l & 0x3f) != 1)
   94: 	    return 0; /* we only understand bitstrings */
   95: 
   96: 	  if (!isExtract)
   97: 	    return 0; /* Cannot compare bitsrings */
   98: 	  
   99: 	  count = *p++;
  100: 	  if (count == 0)
  101: 	    count = 256;
  102: 	  digs = ((count-1)>>2)+1;
  103: 	  
  104: 	  /* output is \[x<hex>/siz]. which is digs+9 chars */
  105: 	  if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME)
  106: 	    return 0;
  107: 	  if (!CHECK_LEN(header, p, plen, (count-1)>>3))
  108: 	    return 0;
  109: 
  110: 	  *cp++ = '\\';
  111: 	  *cp++ = '[';
  112: 	  *cp++ = 'x';
  113: 	  for (j=0; j<digs; j++)
  114: 	    {
  115: 	      unsigned int dig;
  116: 	      if (j%2 == 0)
  117: 		dig = *p >> 4;
  118: 	      else
  119: 		dig = *p++ & 0x0f;
  120: 	      
  121: 	      *cp++ = dig < 10 ? dig + '0' : dig + 'A' - 10;
  122: 	    } 
  123: 	  cp += sprintf((char *)cp, "/%d]", count);
  124: 	  /* do this here to overwrite the zero char from sprintf */
  125: 	  *cp++ = '.';
  126: 	}
  127:       else 
  128: 	{ /* label_type = 0 -> label. */
  129: 	  if (cp - (unsigned char *)name + l + 1 >= MAXDNAME)
  130: 	    return 0;
  131: 	  if (!CHECK_LEN(header, p, plen, l))
  132: 	    return 0;
  133: 	  
  134: 	  for(j=0; j<l; j++, p++)
  135: 	    if (isExtract)
  136: 	      {
  137: 		unsigned char c = *p;
  138: 		if (isascii(c) && !iscntrl(c) && c != '.')
  139: 		  *cp++ = *p;
  140: 		else
  141: 		  return 0;
  142: 	      }
  143: 	    else 
  144: 	      {
  145: 		unsigned char c1 = *cp, c2 = *p;
  146: 		
  147: 		if (c1 == 0)
  148: 		  retvalue = 2;
  149: 		else 
  150: 		  {
  151: 		    cp++;
  152: 		    if (c1 >= 'A' && c1 <= 'Z')
  153: 		      c1 += 'a' - 'A';
  154: 		    if (c2 >= 'A' && c2 <= 'Z')
  155: 		      c2 += 'a' - 'A';
  156: 		    
  157: 		    if (c1 != c2)
  158: 		      retvalue =  2;
  159: 		  }
  160: 	      }
  161: 	  
  162: 	  if (isExtract)
  163: 	    *cp++ = '.';
  164: 	  else if (*cp != 0 && *cp++ != '.')
  165: 	    retvalue = 2;
  166: 	}
  167:     }
  168: }
  169:  
  170: /* Max size of input string (for IPv6) is 75 chars.) */
  171: #define MAXARPANAME 75
  172: int in_arpa_name_2_addr(char *namein, struct all_addr *addrp)
  173: {
  174:   int j;
  175:   char name[MAXARPANAME+1], *cp1;
  176:   unsigned char *addr = (unsigned char *)addrp;
  177:   char *lastchunk = NULL, *penchunk = NULL;
  178:   
  179:   if (strlen(namein) > MAXARPANAME)
  180:     return 0;
  181: 
  182:   memset(addrp, 0, sizeof(struct all_addr));
  183: 
  184:   /* turn name into a series of asciiz strings */
  185:   /* j counts no of labels */
  186:   for(j = 1,cp1 = name; *namein; cp1++, namein++)
  187:     if (*namein == '.')
  188:       {
  189: 	penchunk = lastchunk;
  190:         lastchunk = cp1 + 1;
  191: 	*cp1 = 0;
  192: 	j++;
  193:       }
  194:     else
  195:       *cp1 = *namein;
  196:   
  197:   *cp1 = 0;
  198: 
  199:   if (j<3)
  200:     return 0;
  201: 
  202:   if (hostname_isequal(lastchunk, "arpa") && hostname_isequal(penchunk, "in-addr"))
  203:     {
  204:       /* IP v4 */
  205:       /* address arives as a name of the form
  206: 	 www.xxx.yyy.zzz.in-addr.arpa
  207: 	 some of the low order address octets might be missing
  208: 	 and should be set to zero. */
  209:       for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1)
  210: 	{
  211: 	  /* check for digits only (weeds out things like
  212: 	     50.0/24.67.28.64.in-addr.arpa which are used 
  213: 	     as CNAME targets according to RFC 2317 */
  214: 	  char *cp;
  215: 	  for (cp = cp1; *cp; cp++)
  216: 	    if (!isdigit((unsigned char)*cp))
  217: 	      return 0;
  218: 	  
  219: 	  addr[3] = addr[2];
  220: 	  addr[2] = addr[1];
  221: 	  addr[1] = addr[0];
  222: 	  addr[0] = atoi(cp1);
  223: 	}
  224: 
  225:       return F_IPV4;
  226:     }
  227: #ifdef HAVE_IPV6
  228:   else if (hostname_isequal(penchunk, "ip6") && 
  229: 	   (hostname_isequal(lastchunk, "int") || hostname_isequal(lastchunk, "arpa")))
  230:     {
  231:       /* IP v6:
  232:          Address arrives as 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.[int|arpa]
  233:     	 or \[xfedcba9876543210fedcba9876543210/128].ip6.[int|arpa]
  234:       
  235: 	 Note that most of these the various reprentations are obsolete and 
  236: 	 left-over from the many DNS-for-IPv6 wars. We support all the formats
  237: 	 that we can since there is no reason not to.
  238:       */
  239: 
  240:       if (*name == '\\' && *(name+1) == '[' && 
  241: 	  (*(name+2) == 'x' || *(name+2) == 'X'))
  242: 	{	  
  243: 	  for (j = 0, cp1 = name+3; *cp1 && isxdigit((unsigned char) *cp1) && j < 32; cp1++, j++)
  244: 	    {
  245: 	      char xdig[2];
  246: 	      xdig[0] = *cp1;
  247: 	      xdig[1] = 0;
  248: 	      if (j%2)
  249: 		addr[j/2] |= strtol(xdig, NULL, 16);
  250: 	      else
  251: 		addr[j/2] = strtol(xdig, NULL, 16) << 4;
  252: 	    }
  253: 	  
  254: 	  if (*cp1 == '/' && j == 32)
  255: 	    return F_IPV6;
  256: 	}
  257:       else
  258: 	{
  259: 	  for (cp1 = name; cp1 != penchunk; cp1 += strlen(cp1)+1)
  260: 	    {
  261: 	      if (*(cp1+1) || !isxdigit((unsigned char)*cp1))
  262: 		return 0;
  263: 	      
  264: 	      for (j = sizeof(struct all_addr)-1; j>0; j--)
  265: 		addr[j] = (addr[j] >> 4) | (addr[j-1] << 4);
  266: 	      addr[0] = (addr[0] >> 4) | (strtol(cp1, NULL, 16) << 4);
  267: 	    }
  268: 	  
  269: 	  return F_IPV6;
  270: 	}
  271:     }
  272: #endif
  273:   
  274:   return 0;
  275: }
  276: 
  277: static unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, size_t plen, int extrabytes)
  278: {
  279:   while(1)
  280:     {
  281:       unsigned int label_type;
  282:       
  283:       if (!CHECK_LEN(header, ansp, plen, 1))
  284: 	return NULL;
  285:       
  286:       label_type = (*ansp) & 0xc0;
  287: 
  288:       if (label_type == 0xc0)
  289: 	{
  290: 	  /* pointer for compression. */
  291: 	  ansp += 2;	
  292: 	  break;
  293: 	}
  294:       else if (label_type == 0x80)
  295: 	return NULL; /* reserved */
  296:       else if (label_type == 0x40)
  297: 	{
  298: 	  /* Extended label type */
  299: 	  unsigned int count;
  300: 	  
  301: 	  if (!CHECK_LEN(header, ansp, plen, 2))
  302: 	    return NULL;
  303: 	  
  304: 	  if (((*ansp++) & 0x3f) != 1)
  305: 	    return NULL; /* we only understand bitstrings */
  306: 	  
  307: 	  count = *(ansp++); /* Bits in bitstring */
  308: 	  
  309: 	  if (count == 0) /* count == 0 means 256 bits */
  310: 	    ansp += 32;
  311: 	  else
  312: 	    ansp += ((count-1)>>3)+1;
  313: 	}
  314:       else
  315: 	{ /* label type == 0 Bottom six bits is length */
  316: 	  unsigned int len = (*ansp++) & 0x3f;
  317: 	  
  318: 	  if (!ADD_RDLEN(header, ansp, plen, len))
  319: 	    return NULL;
  320: 
  321: 	  if (len == 0)
  322: 	    break; /* zero length label marks the end. */
  323: 	}
  324:     }
  325: 
  326:   if (!CHECK_LEN(header, ansp, plen, extrabytes))
  327:     return NULL;
  328:   
  329:   return ansp;
  330: }
  331: 
  332: unsigned char *skip_questions(struct dns_header *header, size_t plen)
  333: {
  334:   int q;
  335:   unsigned char *ansp = (unsigned char *)(header+1);
  336: 
  337:   for (q = ntohs(header->qdcount); q != 0; q--)
  338:     {
  339:       if (!(ansp = skip_name(ansp, header, plen, 4)))
  340: 	return NULL;
  341:       ansp += 4; /* class and type */
  342:     }
  343:   
  344:   return ansp;
  345: }
  346: 
  347: static unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *header, size_t plen)
  348: {
  349:   int i, rdlen;
  350:   
  351:   for (i = 0; i < count; i++)
  352:     {
  353:       if (!(ansp = skip_name(ansp, header, plen, 10)))
  354: 	return NULL; 
  355:       ansp += 8; /* type, class, TTL */
  356:       GETSHORT(rdlen, ansp);
  357:       if (!ADD_RDLEN(header, ansp, plen, rdlen))
  358: 	return NULL;
  359:     }
  360: 
  361:   return ansp;
  362: }
  363: 
  364: /* CRC the question section. This is used to safely detect query 
  365:    retransmision and to detect answers to questions we didn't ask, which 
  366:    might be poisoning attacks. Note that we decode the name rather 
  367:    than CRC the raw bytes, since replies might be compressed differently. 
  368:    We ignore case in the names for the same reason. Return all-ones
  369:    if there is not question section. */
  370: unsigned int questions_crc(struct dns_header *header, size_t plen, char *name)
  371: {
  372:   int q;
  373:   unsigned int crc = 0xffffffff;
  374:   unsigned char *p1, *p = (unsigned char *)(header+1);
  375: 
  376:   for (q = ntohs(header->qdcount); q != 0; q--) 
  377:     {
  378:       if (!extract_name(header, plen, &p, name, 1, 4))
  379: 	return crc; /* bad packet */
  380:       
  381:       for (p1 = (unsigned char *)name; *p1; p1++)
  382: 	{
  383: 	  int i = 8;
  384: 	  char c = *p1;
  385: 
  386: 	  if (c >= 'A' && c <= 'Z')
  387: 	    c += 'a' - 'A';
  388: 
  389: 	  crc ^= c << 24;
  390: 	  while (i--)
  391: 	    crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
  392: 	}
  393:       
  394:       /* CRC the class and type as well */
  395:       for (p1 = p; p1 < p+4; p1++)
  396: 	{
  397: 	  int i = 8;
  398: 	  crc ^= *p1 << 24;
  399: 	  while (i--)
  400: 	    crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
  401: 	}
  402: 
  403:       p += 4;
  404:       if (!CHECK_LEN(header, p, plen, 0))
  405: 	return crc; /* bad packet */
  406:     }
  407: 
  408:   return crc;
  409: }
  410: 
  411: 
  412: size_t resize_packet(struct dns_header *header, size_t plen, unsigned char *pheader, size_t hlen)
  413: {
  414:   unsigned char *ansp = skip_questions(header, plen);
  415:     
  416:   /* if packet is malformed, just return as-is. */
  417:   if (!ansp)
  418:     return plen;
  419:   
  420:   if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
  421: 			    header, plen)))
  422:     return plen;
  423:     
  424:   /* restore pseudoheader */
  425:   if (pheader && ntohs(header->arcount) == 0)
  426:     {
  427:       /* must use memmove, may overlap */
  428:       memmove(ansp, pheader, hlen);
  429:       header->arcount = htons(1);
  430:       ansp += hlen;
  431:     }
  432: 
  433:   return ansp - (unsigned char *)header;
  434: }
  435: 
  436: unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t  *len, unsigned char **p, int *is_sign)
  437: {
  438:   /* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it. 
  439:      also return length of pseudoheader in *len and pointer to the UDP size in *p
  440:      Finally, check to see if a packet is signed. If it is we cannot change a single bit before
  441:      forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
  442:   
  443:   int i, arcount = ntohs(header->arcount);
  444:   unsigned char *ansp = (unsigned char *)(header+1);
  445:   unsigned short rdlen, type, class;
  446:   unsigned char *ret = NULL;
  447: 
  448:   if (is_sign)
  449:     {
  450:       *is_sign = 0;
  451: 
  452:       if (OPCODE(header) == QUERY)
  453: 	{
  454: 	  for (i = ntohs(header->qdcount); i != 0; i--)
  455: 	    {
  456: 	      if (!(ansp = skip_name(ansp, header, plen, 4)))
  457: 		return NULL;
  458: 	      
  459: 	      GETSHORT(type, ansp); 
  460: 	      GETSHORT(class, ansp);
  461: 	      
  462: 	      if (class == C_IN && type == T_TKEY)
  463: 		*is_sign = 1;
  464: 	    }
  465: 	}
  466:     }
  467:   else
  468:     {
  469:       if (!(ansp = skip_questions(header, plen)))
  470: 	return NULL;
  471:     }
  472:     
  473:   if (arcount == 0)
  474:     return NULL;
  475:   
  476:   if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount), header, plen)))
  477:     return NULL; 
  478:   
  479:   for (i = 0; i < arcount; i++)
  480:     {
  481:       unsigned char *save, *start = ansp;
  482:       if (!(ansp = skip_name(ansp, header, plen, 10)))
  483: 	return NULL; 
  484: 
  485:       GETSHORT(type, ansp);
  486:       save = ansp;
  487:       GETSHORT(class, ansp);
  488:       ansp += 4; /* TTL */
  489:       GETSHORT(rdlen, ansp);
  490:       if (!ADD_RDLEN(header, ansp, plen, rdlen))
  491: 	return NULL;
  492:       if (type == T_OPT)
  493: 	{
  494: 	  if (len)
  495: 	    *len = ansp - start;
  496: 	  if (p)
  497: 	    *p = save;
  498: 	  ret = start;
  499: 	}
  500:       else if (is_sign && 
  501: 	       i == arcount - 1 && 
  502: 	       class == C_ANY && 
  503: 	       (type == T_SIG || type == T_TSIG))
  504: 	*is_sign = 1;
  505:     }
  506:   
  507:   return ret;
  508: }
  509: 
  510: struct macparm {
  511:   unsigned char *limit;
  512:   struct dns_header *header;
  513:   size_t plen;
  514:   union mysockaddr *l3;
  515: };
  516: 
  517: static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
  518: {
  519:   struct macparm *parm = parmv;
  520:   int match = 0;
  521:   unsigned short rdlen;
  522:   struct dns_header *header = parm->header;
  523:   unsigned char *lenp, *datap, *p;
  524:   
  525:   if (family == parm->l3->sa.sa_family)
  526:     {
  527:       if (family == AF_INET && memcmp (&parm->l3->in.sin_addr, addrp, INADDRSZ) == 0)
  528: 	match = 1;
  529: #ifdef HAVE_IPV6
  530:       else
  531: 	if (family == AF_INET6 && memcmp (&parm->l3->in6.sin6_addr, addrp, IN6ADDRSZ) == 0)
  532: 	  match = 1;
  533: #endif
  534:     }
  535:  
  536:   if (!match)
  537:     return 1; /* continue */
  538:   
  539:   if (ntohs(header->arcount) == 0)
  540:     {
  541:       /* We are adding the pseudoheader */
  542:       if (!(p = skip_questions(header, parm->plen)) ||
  543: 	  !(p = skip_section(p, 
  544: 			     ntohs(header->ancount) + ntohs(header->nscount), 
  545: 			     header, parm->plen)))
  546: 	return 0;
  547:       *p++ = 0; /* empty name */
  548:       PUTSHORT(T_OPT, p);
  549:       PUTSHORT(PACKETSZ, p); /* max packet length - is 512 suitable default for non-EDNS0 resolvers? */
  550:       PUTLONG(0, p);    /* extended RCODE */
  551:       lenp = p;
  552:       PUTSHORT(0, p);    /* RDLEN */
  553:       rdlen = 0;
  554:       if (((ssize_t)maclen) > (parm->limit - (p + 4)))
  555: 	return 0; /* Too big */
  556:       header->arcount = htons(1);
  557:       datap = p;
  558:     }
  559:   else
  560:     {
  561:       int i, is_sign;
  562:       unsigned short code, len;
  563:       
  564:       if (ntohs(header->arcount) != 1 ||
  565: 	  !(p = find_pseudoheader(header, parm->plen, NULL, NULL, &is_sign)) ||
  566: 	  is_sign ||
  567: 	  (!(p = skip_name(p, header, parm->plen, 10))))
  568: 	return 0;
  569:       
  570:       p += 8; /* skip UDP length and RCODE */
  571:       
  572:       lenp = p;
  573:       GETSHORT(rdlen, p);
  574:       if (!CHECK_LEN(header, p, parm->plen, rdlen))
  575: 	return 0; /* bad packet */
  576:       datap = p;
  577: 
  578:       /* check if option already there */
  579:       for (i = 0; i + 4 < rdlen; i += len + 4)
  580: 	{
  581: 	  GETSHORT(code, p);
  582: 	  GETSHORT(len, p);
  583: 	  if (code == EDNS0_OPTION_MAC)
  584: 	    return 0;
  585: 	  p += len;
  586: 	}
  587:       
  588:       if (((ssize_t)maclen) > (parm->limit - (p + 4)))
  589: 	return 0; /* Too big */
  590:     }
  591:   
  592:   PUTSHORT(EDNS0_OPTION_MAC, p);
  593:   PUTSHORT(maclen, p);
  594:   memcpy(p, mac, maclen);
  595:   p += maclen;  
  596: 
  597:   PUTSHORT(p - datap, lenp);
  598:   parm->plen = p - (unsigned char *)header;
  599:   
  600:   return 0; /* done */
  601: }	      
  602:      
  603: 
  604: size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3)
  605: {
  606:   struct macparm parm;
  607:      
  608: /* Must have an existing pseudoheader as the only ar-record, 
  609:    or have no ar-records. Must also not be signed */
  610:    
  611:   if (ntohs(header->arcount) > 1)
  612:     return plen;
  613: 
  614:   parm.header = header;
  615:   parm.limit = (unsigned char *)limit;
  616:   parm.plen = plen;
  617:   parm.l3 = l3;
  618: 
  619:   iface_enumerate(AF_UNSPEC, &parm, filter_mac);
  620:   
  621:   return parm.plen; 
  622: }
  623: 
  624:     
  625: /* is addr in the non-globally-routed IP space? */ 
  626: static int private_net(struct in_addr addr, int ban_localhost) 
  627: {
  628:   in_addr_t ip_addr = ntohl(addr.s_addr);
  629: 
  630:   return
  631:     (((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost)  /* 127.0.0.0/8    (loopback) */ || 
  632:     ((ip_addr & 0xFFFF0000) == 0xC0A80000)  /* 192.168.0.0/16 (private)  */ ||
  633:     ((ip_addr & 0xFF000000) == 0x0A000000)  /* 10.0.0.0/8     (private)  */ ||
  634:     ((ip_addr & 0xFFF00000) == 0xAC100000)  /* 172.16.0.0/12  (private)  */ ||
  635:     ((ip_addr & 0xFFFF0000) == 0xA9FE0000)  /* 169.254.0.0/16 (zeroconf) */ ;
  636: }
  637: 
  638: static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, char *name)
  639: {
  640:   int i, qtype, qclass, rdlen;
  641: 
  642:   for (i = count; i != 0; i--)
  643:     {
  644:       if (name && option_bool(OPT_LOG))
  645: 	{
  646: 	  if (!extract_name(header, qlen, &p, name, 1, 10))
  647: 	    return 0;
  648: 	}
  649:       else if (!(p = skip_name(p, header, qlen, 10)))
  650: 	return 0; /* bad packet */
  651:       
  652:       GETSHORT(qtype, p); 
  653:       GETSHORT(qclass, p);
  654:       p += 4; /* ttl */
  655:       GETSHORT(rdlen, p);
  656:       
  657:       if (qclass == C_IN && qtype == T_A)
  658: 	{
  659: 	  struct doctor *doctor;
  660: 	  struct in_addr addr;
  661: 	  
  662: 	  if (!CHECK_LEN(header, p, qlen, INADDRSZ))
  663: 	    return 0;
  664: 	  
  665: 	  /* alignment */
  666: 	  memcpy(&addr, p, INADDRSZ);
  667: 	  
  668: 	  for (doctor = daemon->doctors; doctor; doctor = doctor->next)
  669: 	    {
  670: 	      if (doctor->end.s_addr == 0)
  671: 		{
  672: 		  if (!is_same_net(doctor->in, addr, doctor->mask))
  673: 		    continue;
  674: 		}
  675: 	      else if (ntohl(doctor->in.s_addr) > ntohl(addr.s_addr) || 
  676: 		       ntohl(doctor->end.s_addr) < ntohl(addr.s_addr))
  677: 		continue;
  678: 	      
  679: 	      addr.s_addr &= ~doctor->mask.s_addr;
  680: 	      addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
  681: 	      /* Since we munged the data, the server it came from is no longer authoritative */
  682: 	      header->hb3 &= ~HB3_AA;
  683: 	      memcpy(p, &addr, INADDRSZ);
  684: 	      break;
  685: 	    }
  686: 	}
  687:       else if (qtype == T_TXT && name && option_bool(OPT_LOG))
  688: 	{
  689: 	  unsigned char *p1 = p;
  690: 	  if (!CHECK_LEN(header, p1, qlen, rdlen))
  691: 	    return 0;
  692: 	  while ((p1 - p) < rdlen)
  693: 	    {
  694: 	      unsigned int i, len = *p1;
  695: 	      unsigned char *p2 = p1;
  696: 	      /* make counted string zero-term  and sanitise */
  697: 	      for (i = 0; i < len; i++)
  698: 		{
  699: 		  if (!isprint((int)*(p2+1)))
  700: 		    break;
  701: 		  
  702: 		  *p2 = *(p2+1);
  703: 		  p2++;
  704: 		}
  705: 	      *p2 = 0;
  706: 	      my_syslog(LOG_INFO, "reply %s is %s", name, p1);
  707: 	      /* restore */
  708: 	      memmove(p1 + 1, p1, i);
  709: 	      *p1 = len;
  710: 	      p1 += len+1;
  711: 	    }
  712: 	}		  
  713:       
  714:       if (!ADD_RDLEN(header, p, qlen, rdlen))
  715: 	 return 0; /* bad packet */
  716:     }
  717:   
  718:   return p; 
  719: }
  720: 
  721: static int find_soa(struct dns_header *header, size_t qlen, char *name)
  722: {
  723:   unsigned char *p;
  724:   int qtype, qclass, rdlen;
  725:   unsigned long ttl, minttl = ULONG_MAX;
  726:   int i, found_soa = 0;
  727:   
  728:   /* first move to NS section and find TTL from any SOA section */
  729:   if (!(p = skip_questions(header, qlen)) ||
  730:       !(p = do_doctor(p, ntohs(header->ancount), header, qlen, name)))
  731:     return 0;  /* bad packet */
  732:   
  733:   for (i = ntohs(header->nscount); i != 0; i--)
  734:     {
  735:       if (!(p = skip_name(p, header, qlen, 10)))
  736: 	return 0; /* bad packet */
  737:       
  738:       GETSHORT(qtype, p); 
  739:       GETSHORT(qclass, p);
  740:       GETLONG(ttl, p);
  741:       GETSHORT(rdlen, p);
  742:       
  743:       if ((qclass == C_IN) && (qtype == T_SOA))
  744: 	{
  745: 	  found_soa = 1;
  746: 	  if (ttl < minttl)
  747: 	    minttl = ttl;
  748: 
  749: 	  /* MNAME */
  750: 	  if (!(p = skip_name(p, header, qlen, 0)))
  751: 	    return 0;
  752: 	  /* RNAME */
  753: 	  if (!(p = skip_name(p, header, qlen, 20)))
  754: 	    return 0;
  755: 	  p += 16; /* SERIAL REFRESH RETRY EXPIRE */
  756: 	  
  757: 	  GETLONG(ttl, p); /* minTTL */
  758: 	  if (ttl < minttl)
  759: 	    minttl = ttl;
  760: 	}
  761:       else if (!ADD_RDLEN(header, p, qlen, rdlen))
  762: 	return 0; /* bad packet */
  763:     }
  764:   
  765:   /* rewrite addresses in additioal section too */
  766:   if (!do_doctor(p, ntohs(header->arcount), header, qlen, NULL))
  767:     return 0;
  768:   
  769:   if (!found_soa)
  770:     minttl = daemon->neg_ttl;
  771: 
  772:   return minttl;
  773: }
  774: 
  775: /* Note that the following code can create CNAME chains that don't point to a real record,
  776:    either because of lack of memory, or lack of SOA records.  These are treated by the cache code as 
  777:    expired and cleaned out that way. 
  778:    Return 1 if we reject an address because it look like part of dns-rebinding attack. */
  779: int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now, 
  780: 		      char **ipsets, int is_sign, int check_rebind, int checking_disabled)
  781: {
  782:   unsigned char *p, *p1, *endrr, *namep;
  783:   int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
  784:   unsigned long ttl = 0;
  785:   struct all_addr addr;
  786: #ifdef HAVE_IPSET
  787:   char **ipsets_cur;
  788: #else
  789:   (void)ipsets; /* unused */
  790: #endif
  791:   
  792:   cache_start_insert();
  793: 
  794:   /* find_soa is needed for dns_doctor and logging side-effects, so don't call it lazily if there are any. */
  795:   if (daemon->doctors || option_bool(OPT_LOG))
  796:     {
  797:       searched_soa = 1;
  798:       ttl = find_soa(header, qlen, name);
  799:     }
  800:   
  801:   /* go through the questions. */
  802:   p = (unsigned char *)(header+1);
  803:   
  804:   for (i = ntohs(header->qdcount); i != 0; i--)
  805:     {
  806:       int found = 0, cname_count = 5;
  807:       struct crec *cpp = NULL;
  808:       int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
  809:       unsigned long cttl = ULONG_MAX, attl;
  810:       
  811:       namep = p;
  812:       if (!extract_name(header, qlen, &p, name, 1, 4))
  813: 	return 0; /* bad packet */
  814:            
  815:       GETSHORT(qtype, p); 
  816:       GETSHORT(qclass, p);
  817:       
  818:       if (qclass != C_IN)
  819: 	continue;
  820: 
  821:       /* PTRs: we chase CNAMEs here, since we have no way to 
  822: 	 represent them in the cache. */
  823:       if (qtype == T_PTR)
  824: 	{ 
  825: 	  int name_encoding = in_arpa_name_2_addr(name, &addr);
  826: 	  
  827: 	  if (!name_encoding)
  828: 	    continue;
  829: 
  830: 	  if (!(flags & F_NXDOMAIN))
  831: 	    {
  832: 	    cname_loop:
  833: 	      if (!(p1 = skip_questions(header, qlen)))
  834: 		return 0;
  835: 	      
  836: 	      for (j = ntohs(header->ancount); j != 0; j--) 
  837: 		{
  838: 		  unsigned char *tmp = namep;
  839: 		  /* the loop body overwrites the original name, so get it back here. */
  840: 		  if (!extract_name(header, qlen, &tmp, name, 1, 0) ||
  841: 		      !(res = extract_name(header, qlen, &p1, name, 0, 10)))
  842: 		    return 0; /* bad packet */
  843: 		  
  844: 		  GETSHORT(aqtype, p1); 
  845: 		  GETSHORT(aqclass, p1);
  846: 		  GETLONG(attl, p1);
  847: 		  if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
  848: 		    {
  849: 		      (p1) -= 4;
  850: 		      PUTLONG(daemon->max_ttl, p1);
  851: 		    }
  852: 		  GETSHORT(ardlen, p1);
  853: 		  endrr = p1+ardlen;
  854: 		  
  855: 		  /* TTL of record is minimum of CNAMES and PTR */
  856: 		  if (attl < cttl)
  857: 		    cttl = attl;
  858: 
  859: 		  if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == T_PTR))
  860: 		    {
  861: 		      if (!extract_name(header, qlen, &p1, name, 1, 0))
  862: 			return 0;
  863: 		      
  864: 		      if (aqtype == T_CNAME)
  865: 			{
  866: 			  if (!cname_count--)
  867: 			    return 0; /* looped CNAMES */
  868: 			  goto cname_loop;
  869: 			}
  870: 		      
  871: 		      cache_insert(name, &addr, now, cttl, name_encoding | F_REVERSE);
  872: 		      found = 1; 
  873: 		    }
  874: 		  
  875: 		  p1 = endrr;
  876: 		  if (!CHECK_LEN(header, p1, qlen, 0))
  877: 		    return 0; /* bad packet */
  878: 		}
  879: 	    }
  880: 	  
  881: 	   if (!found && !option_bool(OPT_NO_NEG))
  882: 	    {
  883: 	      if (!searched_soa)
  884: 		{
  885: 		  searched_soa = 1;
  886: 		  ttl = find_soa(header, qlen, NULL);
  887: 		}
  888: 	      if (ttl)
  889: 		cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags);	
  890: 	    }
  891: 	}
  892:       else
  893: 	{
  894: 	  /* everything other than PTR */
  895: 	  struct crec *newc;
  896: 	  int addrlen;
  897: 
  898: 	  if (qtype == T_A)
  899: 	    {
  900: 	      addrlen = INADDRSZ;
  901: 	      flags |= F_IPV4;
  902: 	    }
  903: #ifdef HAVE_IPV6
  904: 	  else if (qtype == T_AAAA)
  905: 	    {
  906: 	      addrlen = IN6ADDRSZ;
  907: 	      flags |= F_IPV6;
  908: 	    }
  909: #endif
  910: 	  else 
  911: 	    continue;
  912: 	    
  913: 	  if (!(flags & F_NXDOMAIN))
  914: 	    {
  915: 	    cname_loop1:
  916: 	      if (!(p1 = skip_questions(header, qlen)))
  917: 		return 0;
  918: 	      
  919: 	      for (j = ntohs(header->ancount); j != 0; j--) 
  920: 		{
  921: 		  if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
  922: 		    return 0; /* bad packet */
  923: 		  
  924: 		  GETSHORT(aqtype, p1); 
  925: 		  GETSHORT(aqclass, p1);
  926: 		  GETLONG(attl, p1);
  927: 		  if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
  928: 		    {
  929: 		      (p1) -= 4;
  930: 		      PUTLONG(daemon->max_ttl, p1);
  931: 		    }
  932: 		  GETSHORT(ardlen, p1);
  933: 		  endrr = p1+ardlen;
  934: 		  
  935: 		  if (aqclass == C_IN && res != 2 && (aqtype == T_CNAME || aqtype == qtype))
  936: 		    {
  937: 		      if (aqtype == T_CNAME)
  938: 			{
  939: 			  if (!cname_count--)
  940: 			    return 0; /* looped CNAMES */
  941: 			  newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD);
  942: 			  if (newc)
  943: 			    {
  944: 			      newc->addr.cname.cache = NULL;
  945: 			      if (cpp)
  946: 				{
  947: 				  cpp->addr.cname.cache = newc;
  948: 				  cpp->addr.cname.uid = newc->uid;
  949: 				}
  950: 			    }
  951: 
  952: 			  cpp = newc;
  953: 			  if (attl < cttl)
  954: 			    cttl = attl;
  955: 			  
  956: 			  if (!extract_name(header, qlen, &p1, name, 1, 0))
  957: 			    return 0;
  958: 			  goto cname_loop1;
  959: 			}
  960: 		      else
  961: 			{
  962: 			  found = 1;
  963: 			  
  964: 			  /* copy address into aligned storage */
  965: 			  if (!CHECK_LEN(header, p1, qlen, addrlen))
  966: 			    return 0; /* bad packet */
  967: 			  memcpy(&addr, p1, addrlen);
  968: 			  
  969: 			  /* check for returned address in private space */
  970: 			  if (check_rebind &&
  971: 			      (flags & F_IPV4) &&
  972: 			      private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
  973: 			    return 1;
  974: 
  975: #ifdef HAVE_IPSET
  976: 			  if (ipsets && (flags & (F_IPV4 | F_IPV6)))
  977: 			    {
  978: 			      ipsets_cur = ipsets;
  979: 			      while (*ipsets_cur)
  980: 				add_to_ipset(*ipsets_cur++, &addr, flags, 0);
  981: 			    }
  982: #endif
  983: 			  
  984: 			  newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD);
  985: 			  if (newc && cpp)
  986: 			    {
  987: 			      cpp->addr.cname.cache = newc;
  988: 			      cpp->addr.cname.uid = newc->uid;
  989: 			    }
  990: 			  cpp = NULL;
  991: 			}
  992: 		    }
  993: 		  
  994: 		  p1 = endrr;
  995: 		  if (!CHECK_LEN(header, p1, qlen, 0))
  996: 		    return 0; /* bad packet */
  997: 		}
  998: 	    }
  999: 	  
 1000: 	  if (!found && !option_bool(OPT_NO_NEG))
 1001: 	    {
 1002: 	      if (!searched_soa)
 1003: 		{
 1004: 		  searched_soa = 1;
 1005: 		  ttl = find_soa(header, qlen, NULL);
 1006: 		}
 1007: 	      /* If there's no SOA to get the TTL from, but there is a CNAME 
 1008: 		 pointing at this, inherit its TTL */
 1009: 	      if (ttl || cpp)
 1010: 		{
 1011: 		  newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags);	
 1012: 		  if (newc && cpp)
 1013: 		    {
 1014: 		      cpp->addr.cname.cache = newc;
 1015: 		      cpp->addr.cname.uid = newc->uid;
 1016: 		    }
 1017: 		}
 1018: 	    }
 1019: 	}
 1020:     }
 1021:   
 1022:   /* Don't put stuff from a truncated packet into the cache.
 1023:      Don't cache replies where DNSSEC validation was turned off, either
 1024:      the upstream server told us so, or the original query specified it. 
 1025:      Don't cache replies from non-recursive nameservers, since we may get a 
 1026:      reply containing a CNAME but not its target, even though the target 
 1027:      does exist. */
 1028:   if (!(header->hb3 & HB3_TC) && 
 1029:       !(header->hb4 & HB4_CD) &&
 1030:       (header->hb4 & HB4_RA) &&
 1031:       !checking_disabled)
 1032:     cache_end_insert();
 1033: 
 1034:   return 0;
 1035: }
 1036: 
 1037: /* If the packet holds exactly one query
 1038:    return F_IPV4 or F_IPV6  and leave the name from the query in name */
 1039: 
 1040: unsigned int extract_request(struct dns_header *header, size_t qlen, char *name, unsigned short *typep)
 1041: {
 1042:   unsigned char *p = (unsigned char *)(header+1);
 1043:   int qtype, qclass;
 1044: 
 1045:   if (typep)
 1046:     *typep = 0;
 1047: 
 1048:   if (ntohs(header->qdcount) != 1 || OPCODE(header) != QUERY)
 1049:     return 0; /* must be exactly one query. */
 1050:   
 1051:   if (!extract_name(header, qlen, &p, name, 1, 4))
 1052:     return 0; /* bad packet */
 1053:    
 1054:   GETSHORT(qtype, p); 
 1055:   GETSHORT(qclass, p);
 1056: 
 1057:   if (typep)
 1058:     *typep = qtype;
 1059: 
 1060:   if (qclass == C_IN)
 1061:     {
 1062:       if (qtype == T_A)
 1063: 	return F_IPV4;
 1064:       if (qtype == T_AAAA)
 1065: 	return F_IPV6;
 1066:       if (qtype == T_ANY)
 1067: 	return  F_IPV4 | F_IPV6;
 1068:     }
 1069:   
 1070:   return F_QUERY;
 1071: }
 1072: 
 1073: 
 1074: size_t setup_reply(struct dns_header *header, size_t qlen,
 1075: 		struct all_addr *addrp, unsigned int flags, unsigned long ttl)
 1076: {
 1077:   unsigned char *p = skip_questions(header, qlen);
 1078:   
 1079:   /* clear authoritative and truncated flags, set QR flag */
 1080:   header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
 1081:   /* set RA flag */
 1082:   header->hb4 |= HB4_RA;
 1083: 
 1084:   header->nscount = htons(0);
 1085:   header->arcount = htons(0);
 1086:   header->ancount = htons(0); /* no answers unless changed below */
 1087:   if (flags == F_NEG)
 1088:     SET_RCODE(header, SERVFAIL); /* couldn't get memory */
 1089:   else if (flags == F_NOERR)
 1090:     SET_RCODE(header, NOERROR); /* empty domain */
 1091:   else if (flags == F_NXDOMAIN)
 1092:     SET_RCODE(header, NXDOMAIN);
 1093:   else if (p && flags == F_IPV4)
 1094:     { /* we know the address */
 1095:       SET_RCODE(header, NOERROR);
 1096:       header->ancount = htons(1);
 1097:       header->hb3 |= HB3_AA;
 1098:       add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_A, C_IN, "4", addrp);
 1099:     }
 1100: #ifdef HAVE_IPV6
 1101:   else if (p && flags == F_IPV6)
 1102:     {
 1103:       SET_RCODE(header, NOERROR);
 1104:       header->ancount = htons(1);
 1105:       header->hb3 |= HB3_AA;
 1106:       add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_AAAA, C_IN, "6", addrp);
 1107:     }
 1108: #endif
 1109:   else /* nowhere to forward to */
 1110:     SET_RCODE(header, REFUSED);
 1111:  
 1112:   return p - (unsigned char *)header;
 1113: }
 1114: 
 1115: /* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */
 1116: int check_for_local_domain(char *name, time_t now)
 1117: {
 1118:   struct crec *crecp;
 1119:   struct mx_srv_record *mx;
 1120:   struct txt_record *txt;
 1121:   struct interface_name *intr;
 1122:   struct ptr_record *ptr;
 1123:   struct naptr *naptr;
 1124: 
 1125:   if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME)) &&
 1126:       (crecp->flags & (F_HOSTS | F_DHCP)))
 1127:     return 1;
 1128:   
 1129:   for (naptr = daemon->naptr; naptr; naptr = naptr->next)
 1130:      if (hostname_isequal(name, naptr->name))
 1131:       return 1;
 1132: 
 1133:    for (mx = daemon->mxnames; mx; mx = mx->next)
 1134:     if (hostname_isequal(name, mx->name))
 1135:       return 1;
 1136: 
 1137:   for (txt = daemon->txt; txt; txt = txt->next)
 1138:     if (hostname_isequal(name, txt->name))
 1139:       return 1;
 1140: 
 1141:   for (intr = daemon->int_names; intr; intr = intr->next)
 1142:     if (hostname_isequal(name, intr->name))
 1143:       return 1;
 1144: 
 1145:   for (ptr = daemon->ptr; ptr; ptr = ptr->next)
 1146:     if (hostname_isequal(name, ptr->name))
 1147:       return 1;
 1148:  
 1149:   return 0;
 1150: }
 1151: 
 1152: /* Is the packet a reply with the answer address equal to addr?
 1153:    If so mung is into an NXDOMAIN reply and also put that information
 1154:    in the cache. */
 1155: int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, 
 1156: 			     struct bogus_addr *baddr, time_t now)
 1157: {
 1158:   unsigned char *p;
 1159:   int i, qtype, qclass, rdlen;
 1160:   unsigned long ttl;
 1161:   struct bogus_addr *baddrp;
 1162: 
 1163:   /* skip over questions */
 1164:   if (!(p = skip_questions(header, qlen)))
 1165:     return 0; /* bad packet */
 1166: 
 1167:   for (i = ntohs(header->ancount); i != 0; i--)
 1168:     {
 1169:       if (!extract_name(header, qlen, &p, name, 1, 10))
 1170: 	return 0; /* bad packet */
 1171:   
 1172:       GETSHORT(qtype, p); 
 1173:       GETSHORT(qclass, p);
 1174:       GETLONG(ttl, p);
 1175:       GETSHORT(rdlen, p);
 1176:       
 1177:       if (qclass == C_IN && qtype == T_A)
 1178: 	{
 1179: 	  if (!CHECK_LEN(header, p, qlen, INADDRSZ))
 1180: 	    return 0;
 1181: 	  
 1182: 	  for (baddrp = baddr; baddrp; baddrp = baddrp->next)
 1183: 	    if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
 1184: 	      {
 1185: 		/* Found a bogus address. Insert that info here, since there no SOA record
 1186: 		   to get the ttl from in the normal processing */
 1187: 		cache_start_insert();
 1188: 		cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG);
 1189: 		cache_end_insert();
 1190: 		
 1191: 		return 1;
 1192: 	      }
 1193: 	}
 1194:       
 1195:       if (!ADD_RDLEN(header, p, qlen, rdlen))
 1196: 	return 0;
 1197:     }
 1198:   
 1199:   return 0;
 1200: }
 1201: 
 1202: int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp, 
 1203: 			unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
 1204: {
 1205:   va_list ap;
 1206:   unsigned char *sav, *p = *pp;
 1207:   int j;
 1208:   unsigned short usval;
 1209:   long lval;
 1210:   char *sval;
 1211: 
 1212:   if (truncp && *truncp)
 1213:     return 0;
 1214:  
 1215:   va_start(ap, format);   /* make ap point to 1st unamed argument */
 1216:   
 1217:   if (nameoffset > 0)
 1218:     {
 1219:       PUTSHORT(nameoffset | 0xc000, p);
 1220:     }
 1221:   else
 1222:     {
 1223:       char *name = va_arg(ap, char *);
 1224:       if (name)
 1225: 	p = do_rfc1035_name(p, name);
 1226:       if (nameoffset < 0)
 1227: 	{
 1228: 	  PUTSHORT(-nameoffset | 0xc000, p);
 1229: 	}
 1230:       else
 1231: 	*p++ = 0;
 1232:     }
 1233: 
 1234:   PUTSHORT(type, p);
 1235:   PUTSHORT(class, p);
 1236:   PUTLONG(ttl, p);      /* TTL */
 1237: 
 1238:   sav = p;              /* Save pointer to RDLength field */
 1239:   PUTSHORT(0, p);       /* Placeholder RDLength */
 1240: 
 1241:   for (; *format; format++)
 1242:     switch (*format)
 1243:       {
 1244: #ifdef HAVE_IPV6
 1245:       case '6':
 1246: 	sval = va_arg(ap, char *); 
 1247: 	memcpy(p, sval, IN6ADDRSZ);
 1248: 	p += IN6ADDRSZ;
 1249: 	break;
 1250: #endif
 1251: 	
 1252:       case '4':
 1253: 	sval = va_arg(ap, char *); 
 1254: 	memcpy(p, sval, INADDRSZ);
 1255: 	p += INADDRSZ;
 1256: 	break;
 1257: 	
 1258:       case 's':
 1259: 	usval = va_arg(ap, int);
 1260: 	PUTSHORT(usval, p);
 1261: 	break;
 1262: 	
 1263:       case 'l':
 1264: 	lval = va_arg(ap, long);
 1265: 	PUTLONG(lval, p);
 1266: 	break;
 1267: 	
 1268:       case 'd':
 1269: 	/* get domain-name answer arg and store it in RDATA field */
 1270: 	if (offset)
 1271: 	  *offset = p - (unsigned char *)header;
 1272: 	p = do_rfc1035_name(p, va_arg(ap, char *));
 1273: 	*p++ = 0;
 1274: 	break;
 1275: 	
 1276:       case 't':
 1277: 	usval = va_arg(ap, int);
 1278: 	sval = va_arg(ap, char *);
 1279: 	if (usval != 0)
 1280: 	  memcpy(p, sval, usval);
 1281: 	p += usval;
 1282: 	break;
 1283: 
 1284:       case 'z':
 1285: 	sval = va_arg(ap, char *);
 1286: 	usval = sval ? strlen(sval) : 0;
 1287: 	if (usval > 255)
 1288: 	  usval = 255;
 1289: 	*p++ = (unsigned char)usval;
 1290: 	memcpy(p, sval, usval);
 1291: 	p += usval;
 1292: 	break;
 1293:       }
 1294: 
 1295:   va_end(ap);	/* clean up variable argument pointer */
 1296:   
 1297:   j = p - sav - 2;
 1298:   PUTSHORT(j, sav);     /* Now, store real RDLength */
 1299:   
 1300:   /* check for overflow of buffer */
 1301:   if (limit && ((unsigned char *)limit - p) < 0)
 1302:     {
 1303:       if (truncp)
 1304: 	*truncp = 1;
 1305:       return 0;
 1306:     }
 1307:   
 1308:   *pp = p;
 1309:   return 1;
 1310: }
 1311: 
 1312: static unsigned long crec_ttl(struct crec *crecp, time_t now)
 1313: {
 1314:   /* Return 0 ttl for DHCP entries, which might change
 1315:      before the lease expires. */
 1316: 
 1317:   if  (crecp->flags & (F_IMMORTAL | F_DHCP))
 1318:     return daemon->local_ttl;
 1319:   
 1320:   /* Return the Max TTL value if it is lower then the actual TTL */
 1321:   if (daemon->max_ttl == 0 || ((unsigned)(crecp->ttd - now) < daemon->max_ttl))
 1322:     return crecp->ttd - now;
 1323:   else
 1324:     return daemon->max_ttl;
 1325: }
 1326:   
 1327: 
 1328: /* return zero if we can't answer from cache, or packet size if we can */
 1329: size_t answer_request(struct dns_header *header, char *limit, size_t qlen,  
 1330: 		      struct in_addr local_addr, struct in_addr local_netmask, time_t now) 
 1331: {
 1332:   char *name = daemon->namebuff;
 1333:   unsigned char *p, *ansp, *pheader;
 1334:   int qtype, qclass;
 1335:   struct all_addr addr;
 1336:   int nameoffset;
 1337:   unsigned short flag;
 1338:   int q, ans, anscount = 0, addncount = 0;
 1339:   int dryrun = 0, sec_reqd = 0;
 1340:   int is_sign;
 1341:   struct crec *crecp;
 1342:   int nxdomain = 0, auth = 1, trunc = 0;
 1343:   struct mx_srv_record *rec;
 1344:  
 1345:   /* If there is an RFC2671 pseudoheader then it will be overwritten by
 1346:      partial replies, so we have to do a dry run to see if we can answer
 1347:      the query. We check to see if the do bit is set, if so we always
 1348:      forward rather than answering from the cache, which doesn't include
 1349:      security information. */
 1350: 
 1351:   if (find_pseudoheader(header, qlen, NULL, &pheader, &is_sign))
 1352:     { 
 1353:       unsigned short udpsz, flags;
 1354:       unsigned char *psave = pheader;
 1355: 
 1356:       GETSHORT(udpsz, pheader);
 1357:       pheader += 2; /* ext_rcode */
 1358:       GETSHORT(flags, pheader);
 1359:       
 1360:       sec_reqd = flags & 0x8000; /* do bit */ 
 1361: 
 1362:       /* If our client is advertising a larger UDP packet size
 1363: 	 than we allow, trim it so that we don't get an overlarge
 1364: 	 response from upstream */
 1365: 
 1366:       if (!is_sign && (udpsz > daemon->edns_pktsz))
 1367: 	PUTSHORT(daemon->edns_pktsz, psave); 
 1368: 
 1369:       dryrun = 1;
 1370:     }
 1371: 
 1372:   if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
 1373:     return 0;
 1374:   
 1375:   for (rec = daemon->mxnames; rec; rec = rec->next)
 1376:     rec->offset = 0;
 1377:   
 1378:  rerun:
 1379:   /* determine end of question section (we put answers there) */
 1380:   if (!(ansp = skip_questions(header, qlen)))
 1381:     return 0; /* bad packet */
 1382:    
 1383:   /* now process each question, answers go in RRs after the question */
 1384:   p = (unsigned char *)(header+1);
 1385: 
 1386:   for (q = ntohs(header->qdcount); q != 0; q--)
 1387:     {
 1388:       /* save pointer to name for copying into answers */
 1389:       nameoffset = p - (unsigned char *)header;
 1390: 
 1391:       /* now extract name as .-concatenated string into name */
 1392:       if (!extract_name(header, qlen, &p, name, 1, 4))
 1393: 	return 0; /* bad packet */
 1394:             
 1395:       GETSHORT(qtype, p); 
 1396:       GETSHORT(qclass, p);
 1397: 
 1398:       ans = 0; /* have we answered this question */
 1399:       
 1400:       if (qtype == T_TXT || qtype == T_ANY)
 1401: 	{
 1402: 	  struct txt_record *t;
 1403: 	  for(t = daemon->txt; t ; t = t->next)
 1404: 	    {
 1405: 	      if (t->class == qclass && hostname_isequal(name, t->name))
 1406: 		{
 1407: 		  ans = 1;
 1408: 		  if (!dryrun)
 1409: 		    {
 1410: 		      log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
 1411: 		      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
 1412: 					      daemon->local_ttl, NULL,
 1413: 					      T_TXT, t->class, "t", t->len, t->txt))
 1414: 			anscount++;
 1415: 
 1416: 		    }
 1417: 		}
 1418: 	    }
 1419: 	}
 1420: 
 1421:       if (qclass == C_IN)
 1422: 	{
 1423: 	  struct txt_record *t;
 1424: 
 1425: 	  for (t = daemon->rr; t; t = t->next)
 1426: 	    if ((t->class == qtype || qtype == T_ANY) && hostname_isequal(name, t->name))
 1427: 	      {
 1428: 		ans = 1;
 1429: 		if (!dryrun)
 1430: 		  {
 1431: 		    log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
 1432: 		    if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
 1433: 					    daemon->local_ttl, NULL,
 1434: 					    t->class, C_IN, "t", t->len, t->txt))
 1435: 		      anscount ++;
 1436: 		  }
 1437: 	      }
 1438: 		
 1439: 	  if (qtype == T_PTR || qtype == T_ANY)
 1440: 	    {
 1441: 	      /* see if it's w.z.y.z.in-addr.arpa format */
 1442: 	      int is_arpa = in_arpa_name_2_addr(name, &addr);
 1443: 	      struct ptr_record *ptr;
 1444: 	      struct interface_name* intr = NULL;
 1445: 
 1446: 	      for (ptr = daemon->ptr; ptr; ptr = ptr->next)
 1447: 		if (hostname_isequal(name, ptr->name))
 1448: 		  break;
 1449: 
 1450: 	      if (is_arpa == F_IPV4)
 1451: 		for (intr = daemon->int_names; intr; intr = intr->next)
 1452: 		  {
 1453: 		    if (addr.addr.addr4.s_addr == get_ifaddr(intr->intr).s_addr)
 1454: 		      break;
 1455: 		    else
 1456: 		      while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
 1457: 			intr = intr->next;
 1458: 		  }
 1459: 	      
 1460: 	      if (intr)
 1461: 		{
 1462: 		  ans = 1;
 1463: 		  if (!dryrun)
 1464: 		    {
 1465: 		      log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
 1466: 		      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
 1467: 					      daemon->local_ttl, NULL,
 1468: 					      T_PTR, C_IN, "d", intr->name))
 1469: 			anscount++;
 1470: 		    }
 1471: 		}
 1472: 	      else if (ptr)
 1473: 		{
 1474: 		  ans = 1;
 1475: 		  if (!dryrun)
 1476: 		    {
 1477: 		      log_query(F_CONFIG | F_RRNAME, name, NULL, "<PTR>");
 1478: 		      for (ptr = daemon->ptr; ptr; ptr = ptr->next)
 1479: 			if (hostname_isequal(name, ptr->name) &&
 1480: 			    add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
 1481: 						daemon->local_ttl, NULL,
 1482: 						T_PTR, C_IN, "d", ptr->ptr))
 1483: 			  anscount++;
 1484: 			 
 1485: 		    }
 1486: 		}
 1487: 	      else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
 1488: 		do 
 1489: 		  { 
 1490: 		    /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */
 1491: 		    if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP)))
 1492: 		      continue;
 1493: 		    
 1494: 		    if (crecp->flags & F_NEG)
 1495: 		      {
 1496: 			ans = 1;
 1497: 			auth = 0;
 1498: 			if (crecp->flags & F_NXDOMAIN)
 1499: 			  nxdomain = 1;
 1500: 			if (!dryrun)
 1501: 			  log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL);
 1502: 		      }
 1503: 		    else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
 1504: 		      {
 1505: 			ans = 1;
 1506: 			if (!(crecp->flags & (F_HOSTS | F_DHCP)))
 1507: 			  auth = 0;
 1508: 			if (!dryrun)
 1509: 			  {
 1510: 			    log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr, 
 1511: 				      record_source(crecp->uid));
 1512: 			    
 1513: 			    if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
 1514: 						    crec_ttl(crecp, now), NULL,
 1515: 						    T_PTR, C_IN, "d", cache_get_name(crecp)))
 1516: 			      anscount++;
 1517: 			  }
 1518: 		      }
 1519: 		  } while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa)));
 1520: 	      else if (is_arpa == F_IPV4 && 
 1521: 		       option_bool(OPT_BOGUSPRIV) && 
 1522: 		       private_net(addr.addr.addr4, 1))
 1523: 		{
 1524: 		  /* if not in cache, enabled and private IPV4 address, return NXDOMAIN */
 1525: 		  ans = 1;
 1526: 		  nxdomain = 1;
 1527: 		  if (!dryrun)
 1528: 		    log_query(F_CONFIG | F_REVERSE | F_IPV4 | F_NEG | F_NXDOMAIN, 
 1529: 			      name, &addr, NULL);
 1530: 		}
 1531: 	    }
 1532: 	    
 1533: 	  for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0)
 1534: 	    {
 1535: 	      unsigned short type = T_A;
 1536: 	      
 1537: 	      if (flag == F_IPV6)
 1538: #ifdef HAVE_IPV6
 1539: 		type = T_AAAA;
 1540: #else
 1541: 	        break;
 1542: #endif
 1543: 	      
 1544: 	      if (qtype != type && qtype != T_ANY)
 1545: 		continue;
 1546: 	      
 1547: 	      /* Check for "A for A"  queries; be rather conservative 
 1548: 		 about what looks like dotted-quad.  */
 1549: 	      if (qtype == T_A)
 1550: 		{
 1551: 		  char *cp;
 1552: 		  unsigned int i, a;
 1553: 		  int x;
 1554: 
 1555: 		  for (cp = name, i = 0, a = 0; *cp; i++)
 1556: 		    {
 1557: 		      if (!isdigit((unsigned char)*cp) || (x = strtol(cp, &cp, 10)) > 255) 
 1558: 			{
 1559: 			  i = 5;
 1560: 			  break;
 1561: 			}
 1562: 		      
 1563: 		      a = (a << 8) + x;
 1564: 		      
 1565: 		      if (*cp == '.') 
 1566: 			cp++;
 1567: 		    }
 1568: 		  
 1569: 		  if (i == 4)
 1570: 		    {
 1571: 		      ans = 1;
 1572: 		      if (!dryrun)
 1573: 			{
 1574: 			  addr.addr.addr4.s_addr = htonl(a);
 1575: 			  log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
 1576: 			  if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
 1577: 						  daemon->local_ttl, NULL, type, C_IN, "4", &addr))
 1578: 			    anscount++;
 1579: 			}
 1580: 		      continue;
 1581: 		    }
 1582: 		}
 1583: 
 1584: 	      /* interface name stuff */
 1585: 	      if (qtype == T_A)
 1586: 		{
 1587: 		  struct interface_name *intr;
 1588: 
 1589: 		  for (intr = daemon->int_names; intr; intr = intr->next)
 1590: 		    if (hostname_isequal(name, intr->name))
 1591: 		      break;
 1592: 		  
 1593: 		  if (intr)
 1594: 		    {
 1595: 		      ans = 1;
 1596: 		      if (!dryrun)
 1597: 			{
 1598: 			  if ((addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr == (in_addr_t) -1)
 1599: 			    log_query(F_FORWARD | F_CONFIG | F_IPV4 | F_NEG, name, NULL, NULL);
 1600: 			  else
 1601: 			    {
 1602: 			      log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
 1603: 			      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
 1604: 						      daemon->local_ttl, NULL, type, C_IN, "4", &addr))
 1605: 				anscount++;
 1606: 			    }
 1607: 			}
 1608: 		      continue;
 1609: 		    }
 1610: 		}
 1611: 
 1612: 	    cname_restart:
 1613: 	      if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME)))
 1614: 		{
 1615: 		  int localise = 0;
 1616: 		  
 1617: 		  /* See if a putative address is on the network from which we recieved
 1618: 		     the query, is so we'll filter other answers. */
 1619: 		  if (local_addr.s_addr != 0 && option_bool(OPT_LOCALISE) && flag == F_IPV4)
 1620: 		    {
 1621: 		      struct crec *save = crecp;
 1622: 		      do {
 1623: 			if ((crecp->flags & F_HOSTS) &&
 1624: 			    is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask))
 1625: 			  {
 1626: 			    localise = 1;
 1627: 			    break;
 1628: 			  } 
 1629: 			} while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
 1630: 		      crecp = save;
 1631: 		    }
 1632: 			  
 1633: 		  do
 1634: 		    { 
 1635: 		      /* don't answer wildcard queries with data not from /etc/hosts
 1636: 			 or DHCP leases */
 1637: 		      if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP)))
 1638: 			break;
 1639: 		      
 1640: 		      if (crecp->flags & F_CNAME)
 1641: 			{
 1642: 			  if (!dryrun)
 1643: 			    {
 1644: 			      log_query(crecp->flags, name, NULL, record_source(crecp->uid));
 1645: 			      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
 1646: 						      crec_ttl(crecp, now), &nameoffset,
 1647: 						      T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
 1648: 				anscount++;
 1649: 			    }
 1650: 			  
 1651: 			  strcpy(name, cache_get_name(crecp->addr.cname.cache));
 1652: 			  goto cname_restart;
 1653: 			}
 1654: 		      
 1655: 		      if (crecp->flags & F_NEG)
 1656: 			{
 1657: 			  ans = 1;
 1658: 			  auth = 0;
 1659: 			  if (crecp->flags & F_NXDOMAIN)
 1660: 			    nxdomain = 1;
 1661: 			  if (!dryrun)
 1662: 			    log_query(crecp->flags, name, NULL, NULL);
 1663: 			}
 1664: 		      else if ((crecp->flags & (F_HOSTS | F_DHCP)) || !sec_reqd)
 1665: 			{
 1666: 			  /* If we are returning local answers depending on network,
 1667: 			     filter here. */
 1668: 			  if (localise && 
 1669: 			      (crecp->flags & F_HOSTS) &&
 1670: 			      !is_same_net(*((struct in_addr *)&crecp->addr), local_addr, local_netmask))
 1671: 			    continue;
 1672:        
 1673: 			  if (!(crecp->flags & (F_HOSTS | F_DHCP)))
 1674: 			    auth = 0;
 1675: 			  
 1676: 			  ans = 1;
 1677: 			  if (!dryrun)
 1678: 			    {
 1679: 			      log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr.addr,
 1680: 					record_source(crecp->uid));
 1681: 			      
 1682: 			      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
 1683: 						      crec_ttl(crecp, now), NULL, type, C_IN, 
 1684: 						      type == T_A ? "4" : "6", &crecp->addr))
 1685: 				anscount++;
 1686: 			    }
 1687: 			}
 1688: 		    } while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
 1689: 		}
 1690: 	    }
 1691: 
 1692: 	  if (qtype == T_CNAME || qtype == T_ANY)
 1693: 	    {
 1694: 	      if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)) &&
 1695: 		  (qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP))))
 1696: 		{
 1697: 		  ans = 1;
 1698: 		  if (!dryrun)
 1699: 		    {
 1700: 		      log_query(crecp->flags, name, NULL, record_source(crecp->uid));
 1701: 		      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
 1702: 					      crec_ttl(crecp, now), &nameoffset,
 1703: 					      T_CNAME, C_IN, "d", cache_get_name(crecp->addr.cname.cache)))
 1704: 			anscount++;
 1705: 		    }
 1706: 		}
 1707: 	    }
 1708: 	  
 1709: 	  if (qtype == T_MX || qtype == T_ANY)
 1710: 	    {
 1711: 	      int found = 0;
 1712: 	      for (rec = daemon->mxnames; rec; rec = rec->next)
 1713: 		if (!rec->issrv && hostname_isequal(name, rec->name))
 1714: 		  {
 1715: 		  ans = found = 1;
 1716: 		  if (!dryrun)
 1717: 		    {
 1718: 		      int offset;
 1719: 		      log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
 1720: 		      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
 1721: 					      &offset, T_MX, C_IN, "sd", rec->weight, rec->target))
 1722: 			{
 1723: 			  anscount++;
 1724: 			  if (rec->target)
 1725: 			    rec->offset = offset;
 1726: 			}
 1727: 		    }
 1728: 		  }
 1729: 	      
 1730: 	      if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) && 
 1731: 		  cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP))
 1732: 		{ 
 1733: 		  ans = 1;
 1734: 		  if (!dryrun)
 1735: 		    {
 1736: 		      log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
 1737: 		      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL, 
 1738: 					      T_MX, C_IN, "sd", 1, 
 1739: 					      option_bool(OPT_SELFMX) ? name : daemon->mxtarget))
 1740: 			anscount++;
 1741: 		    }
 1742: 		}
 1743: 	    }
 1744: 	  	  
 1745: 	  if (qtype == T_SRV || qtype == T_ANY)
 1746: 	    {
 1747: 	      int found = 0;
 1748: 	      struct mx_srv_record *move = NULL, **up = &daemon->mxnames;
 1749: 
 1750: 	      for (rec = daemon->mxnames; rec; rec = rec->next)
 1751: 		if (rec->issrv && hostname_isequal(name, rec->name))
 1752: 		  {
 1753: 		    found = ans = 1;
 1754: 		    if (!dryrun)
 1755: 		      {
 1756: 			int offset;
 1757: 			log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
 1758: 			if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, 
 1759: 						&offset, T_SRV, C_IN, "sssd", 
 1760: 						rec->priority, rec->weight, rec->srvport, rec->target))
 1761: 			  {
 1762: 			    anscount++;
 1763: 			    if (rec->target)
 1764: 			      rec->offset = offset;
 1765: 			  }
 1766: 		      }
 1767: 		    
 1768: 		    /* unlink first SRV record found */
 1769: 		    if (!move)
 1770: 		      {
 1771: 			move = rec;
 1772: 			*up = rec->next;
 1773: 		      }
 1774: 		    else
 1775: 		      up = &rec->next;      
 1776: 		  }
 1777: 		else
 1778: 		  up = &rec->next;
 1779: 
 1780: 	      /* put first SRV record back at the end. */
 1781: 	      if (move)
 1782: 		{
 1783: 		  *up = move;
 1784: 		  move->next = NULL;
 1785: 		}
 1786: 	      
 1787: 	      if (!found && option_bool(OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_'))))
 1788: 		{
 1789: 		  ans = 1;
 1790: 		  if (!dryrun)
 1791: 		    log_query(F_CONFIG | F_NEG, name, NULL, NULL);
 1792: 		}
 1793: 	    }
 1794: 
 1795: 	  if (qtype == T_NAPTR || qtype == T_ANY)
 1796: 	    {
 1797: 	      struct naptr *na;
 1798: 	      for (na = daemon->naptr; na; na = na->next)
 1799: 		if (hostname_isequal(name, na->name))
 1800: 		  {
 1801: 		    ans = 1;
 1802: 		    if (!dryrun)
 1803: 		      {
 1804: 			log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
 1805: 			if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, 
 1806: 						NULL, T_NAPTR, C_IN, "sszzzd", 
 1807: 						na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
 1808: 			  anscount++;
 1809: 		      }
 1810: 		  }
 1811: 	    }
 1812: 	  
 1813: 	  if (qtype == T_MAILB)
 1814: 	    ans = 1, nxdomain = 1;
 1815: 
 1816: 	  if (qtype == T_SOA && option_bool(OPT_FILTER))
 1817: 	    {
 1818: 	      ans = 1; 
 1819: 	      if (!dryrun)
 1820: 		log_query(F_CONFIG | F_NEG, name, &addr, NULL);
 1821: 	    }
 1822: 	}
 1823: 
 1824:       if (!ans)
 1825: 	return 0; /* failed to answer a question */
 1826:     }
 1827:   
 1828:   if (dryrun)
 1829:     {
 1830:       dryrun = 0;
 1831:       goto rerun;
 1832:     }
 1833:   
 1834:   /* create an additional data section, for stuff in SRV and MX record replies. */
 1835:   for (rec = daemon->mxnames; rec; rec = rec->next)
 1836:     if (rec->offset != 0)
 1837:       {
 1838: 	/* squash dupes */
 1839: 	struct mx_srv_record *tmp;
 1840: 	for (tmp = rec->next; tmp; tmp = tmp->next)
 1841: 	  if (tmp->offset != 0 && hostname_isequal(rec->target, tmp->target))
 1842: 	    tmp->offset = 0;
 1843: 	
 1844: 	crecp = NULL;
 1845: 	while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6)))
 1846: 	  {
 1847: #ifdef HAVE_IPV6
 1848: 	    int type =  crecp->flags & F_IPV4 ? T_A : T_AAAA;
 1849: #else
 1850: 	    int type = T_A;
 1851: #endif
 1852: 	    if (crecp->flags & F_NEG)
 1853: 	      continue;
 1854: 
 1855: 	    if (add_resource_record(header, limit, NULL, rec->offset, &ansp, 
 1856: 				    crec_ttl(crecp, now), NULL, type, C_IN, 
 1857: 				    crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr))
 1858: 	      addncount++;
 1859: 	  }
 1860:       }
 1861:   
 1862:   /* done all questions, set up header and return length of result */
 1863:   /* clear authoritative and truncated flags, set QR flag */
 1864:   header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
 1865:   /* set RA flag */
 1866:   header->hb4 |= HB4_RA;
 1867:    
 1868:   /* authoritive - only hosts and DHCP derived names. */
 1869:   if (auth)
 1870:     header->hb3 |= HB3_AA;
 1871:   
 1872:   /* truncation */
 1873:   if (trunc)
 1874:     header->hb3 |= HB3_TC;
 1875: 
 1876:   if (anscount == 0 && nxdomain)
 1877:     SET_RCODE(header, NXDOMAIN);
 1878:   else
 1879:     SET_RCODE(header, NOERROR); /* no error */
 1880:   header->ancount = htons(anscount);
 1881:   header->nscount = htons(0);
 1882:   header->arcount = htons(addncount);
 1883:   return ansp - (unsigned char *)header;
 1884: }
 1885: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>