"Fossies" - the Fresh Open Source Software Archive

Member "dnsmasq-2.85/src/rfc1035.c" (7 Apr 2021, 52287 Bytes) of package /linux/misc/dns/dnsmasq-2.85.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "rfc1035.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.84_vs_2.85.

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