Annotation of embedaddon/dnsmasq/src/rfc1035.c, revision 1.1.1.4

1.1.1.4 ! misho       1: /* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
1.1       misho       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;
1.1.1.3   misho      23:   unsigned int j, l, namelen = 0, hops = 0;
1.1       misho      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:        {
1.1.1.4 ! misho      39:          /* check that there are the correct no. of bytes after the name */
        !            40:          if (!CHECK_LEN(header, p1 ? p1 : p, plen, extrabytes))
1.1       misho      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:        }
1.1.1.3   misho      80:       else if (label_type == 0x00)
1.1       misho      81:        { /* label_type = 0 -> label. */
1.1.1.3   misho      82:          namelen += l + 1; /* include period */
                     83:          if (namelen >= MAXDNAME)
1.1       misho      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;
1.1.1.3   misho      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;
1.1       misho     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';
1.1.1.3   misho     121: #ifdef HAVE_DNSSEC
                    122:                    if (option_bool(OPT_DNSSEC_VALID) && c1 == NAME_ESCAPE)
                    123:                      c1 = (*cp++)-1;
                    124: #endif
                    125:                    
1.1       misho     126:                    if (c2 >= 'A' && c2 <= 'Z')
                    127:                      c2 += 'a' - 'A';
1.1.1.3   misho     128:                     
1.1       misho     129:                    if (c1 != c2)
                    130:                      retvalue =  2;
                    131:                  }
                    132:              }
1.1.1.3   misho     133:            
1.1       misho     134:          if (isExtract)
                    135:            *cp++ = '.';
                    136:          else if (*cp != 0 && *cp++ != '.')
                    137:            retvalue = 2;
                    138:        }
1.1.1.3   misho     139:       else
                    140:        return 0; /* label types 0x40 and 0x80 not supported */
1.1       misho     141:     }
                    142: }
                    143:  
                    144: /* Max size of input string (for IPv6) is 75 chars.) */
                    145: #define MAXARPANAME 75
1.1.1.4 ! misho     146: int in_arpa_name_2_addr(char *namein, union all_addr *addrp)
1.1       misho     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: 
1.1.1.4 ! misho     156:   memset(addrp, 0, sizeof(union all_addr));
1.1       misho     157: 
                    158:   /* turn name into a series of asciiz strings */
1.1.1.4 ! misho     159:   /* j counts no. of labels */
1.1       misho     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 */
1.1.1.4 ! misho     179:       /* address arrives as a name of the form
1.1       misho     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:       
1.1.1.4 ! misho     208:         Note that most of these the various representations are obsolete and 
1.1       misho     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:              
1.1.1.4 ! misho     237:              for (j = sizeof(struct in6_addr)-1; j>0; j--)
1.1       misho     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: 
1.1.1.2   misho     249: unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, size_t plen, int extrabytes)
1.1       misho     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: 
1.1.1.2   misho     319: unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *header, size_t plen)
1.1       misho     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? */ 
1.1.1.2   misho     361: int private_net(struct in_addr addr, int ban_localhost) 
1.1       misho     362: {
                    363:   in_addr_t ip_addr = ntohl(addr.s_addr);
                    364: 
                    365:   return
1.1.1.3   misho     366:     (((ip_addr & 0xFF000000) == 0x7F000000) && ban_localhost)  /* 127.0.0.0/8    (loopback) */ ||
                    367:     ((ip_addr & 0xFF000000) == 0x00000000)  /* RFC 5735 section 3. "here" network */ ||
1.1       misho     368:     ((ip_addr & 0xFF000000) == 0x0A000000)  /* 10.0.0.0/8     (private)  */ ||
                    369:     ((ip_addr & 0xFFF00000) == 0xAC100000)  /* 172.16.0.0/12  (private)  */ ||
1.1.1.3   misho     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)*/ ;
1.1       misho     376: }
                    377: 
1.1.1.4 ! misho     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: 
1.1.1.2   misho     388: static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, char *name, int *doctored)
1.1       misho     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;
1.1.1.2   misho     433:              *doctored = 1;
1.1       misho     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;
1.1.1.4 ! misho     447:              if ((p1 + len - p) >= rdlen)
        !           448:                return 0; /* bad packet */
1.1       misho     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: 
1.1.1.2   misho     474: static int find_soa(struct dns_header *header, size_t qlen, char *name, int *doctored)
1.1       misho     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)) ||
1.1.1.2   misho     483:       !(p = do_doctor(p, ntohs(header->ancount), header, qlen, name, doctored)))
1.1       misho     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:   
1.1.1.2   misho     518:   /* rewrite addresses in additional section too */
                    519:   if (!do_doctor(p, ntohs(header->arcount), header, qlen, NULL, doctored))
1.1       misho     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, 
1.1.1.4 ! misho     533:                      char **ipsets, int is_sign, int check_rebind, int no_cache_dnssec,
        !           534:                      int secure, int *doctored)
1.1       misho     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;
1.1.1.4 ! misho     539:   union all_addr addr;
1.1       misho     540: #ifdef HAVE_IPSET
                    541:   char **ipsets_cur;
                    542: #else
                    543:   (void)ipsets; /* unused */
                    544: #endif
1.1.1.4 ! misho     545: 
1.1       misho     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. */
1.1.1.2   misho     550:   if (daemon->doctors || option_bool(OPT_LOG) || option_bool(OPT_DNSSEC_VALID))
1.1       misho     551:     {
                    552:       searched_soa = 1;
1.1.1.2   misho     553:       ttl = find_soa(header, qlen, name, doctored);
1.1.1.4 ! misho     554: 
        !           555:       if (*doctored)
        !           556:        {
        !           557:          if (secure)
        !           558:            return 0;
1.1.1.2   misho     559: #ifdef HAVE_DNSSEC
1.1.1.4 ! misho     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;
1.1.1.2   misho     564: #endif
1.1.1.4 ! misho     565:        }
1.1       misho     566:     }
                    567:   
                    568:   /* go through the questions. */
                    569:   p = (unsigned char *)(header+1);
                    570:   
                    571:   for (i = ntohs(header->qdcount); i != 0; i--)
                    572:     {
1.1.1.2   misho     573:       int found = 0, cname_count = CNAME_CHAIN;
1.1       misho     574:       struct crec *cpp = NULL;
                    575:       int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
1.1.1.4 ! misho     576: #ifdef HAVE_DNSSEC
        !           577:       int cname_short = 0;
        !           578: #endif
1.1       misho     579:       unsigned long cttl = ULONG_MAX, attl;
1.1.1.2   misho     580: 
1.1       misho     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:              
1.1.1.4 ! misho     606:              for (j = 0; j < ntohs(header->ancount); j++) 
1.1       misho     607:                {
1.1.1.4 ! misho     608:                  int secflag = 0;
1.1       misho     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;
1.1.1.4 ! misho     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: 
1.1       misho     648:                      if (aqtype == T_CNAME)
                    649:                        {
1.1.1.4 ! misho     650:                          if (!cname_count--)
        !           651:                            return 0; /* looped CNAMES, we can't cache. */
        !           652: #ifdef HAVE_DNSSEC
        !           653:                          cname_short = 1;
        !           654: #endif
1.1       misho     655:                          goto cname_loop;
                    656:                        }
                    657:                      
1.1.1.4 ! misho     658:                      cache_insert(name, &addr, C_IN, now, cttl, name_encoding | secflag | F_REVERSE);
1.1       misho     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;
1.1.1.2   misho     673:                  ttl = find_soa(header, qlen, NULL, doctored);
1.1       misho     674:                }
                    675:              if (ttl)
1.1.1.4 ! misho     676:                cache_insert(NULL, &addr, C_IN, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | (secure ?  F_DNSSECOK : 0));      
1.1       misho     677:            }
                    678:        }
                    679:       else
                    680:        {
                    681:          /* everything other than PTR */
                    682:          struct crec *newc;
1.1.1.4 ! misho     683:          int addrlen = 0;
1.1       misho     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:            }
1.1.1.4 ! misho     695:          else if (qtype == T_SRV)
        !           696:            flags |= F_SRV;
        !           697:          else
1.1       misho     698:            continue;
                    699:            
1.1.1.2   misho     700:        cname_loop1:
                    701:          if (!(p1 = skip_questions(header, qlen)))
                    702:            return 0;
                    703:          
1.1.1.4 ! misho     704:          for (j = 0; j < ntohs(header->ancount); j++) 
1.1       misho     705:            {
1.1.1.4 ! misho     706:              int secflag = 0;
        !           707:              
1.1.1.2   misho     708:              if (!(res = extract_name(header, qlen, &p1, name, 0, 10)))
                    709:                return 0; /* bad packet */
1.1       misho     710:              
1.1.1.2   misho     711:              GETSHORT(aqtype, p1); 
                    712:              GETSHORT(aqclass, p1);
                    713:              GETLONG(attl, p1);
                    714:              if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
1.1       misho     715:                {
1.1.1.2   misho     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:                {
1.1.1.4 ! misho     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           
1.1.1.2   misho     734:                  if (aqtype == T_CNAME)
1.1       misho     735:                    {
1.1.1.2   misho     736:                      if (!cname_count--)
                    737:                        return 0; /* looped CNAMES */
1.1.1.4 ! misho     738: 
        !           739:                      if ((newc = cache_insert(name, NULL, C_IN, now, attl, F_CNAME | F_FORWARD | secflag)))
1.1       misho     740:                        {
1.1.1.2   misho     741:                          newc->addr.cname.target.cache = NULL;
1.1.1.4 ! misho     742:                          newc->addr.cname.is_name_ptr = 0; 
1.1.1.2   misho     743:                          if (cpp)
1.1       misho     744:                            {
1.1.1.4 ! misho     745:                              next_uid(newc);
1.1.1.2   misho     746:                              cpp->addr.cname.target.cache = newc;
                    747:                              cpp->addr.cname.uid = newc->uid;
1.1       misho     748:                            }
                    749:                        }
1.1.1.2   misho     750:                      
                    751:                      cpp = newc;
                    752:                      if (attl < cttl)
                    753:                        cttl = attl;
                    754:                      
1.1.1.4 ! misho     755:                      namep = p1;
1.1.1.2   misho     756:                      if (!extract_name(header, qlen, &p1, name, 1, 0))
                    757:                        return 0;
1.1.1.4 ! misho     758:                      
1.1.1.2   misho     759:                      goto cname_loop1;
                    760:                    }
                    761:                  else if (!(flags & F_NXDOMAIN))
                    762:                    {
                    763:                      found = 1;
                    764:                      
1.1.1.4 ! misho     765:                      if (flags & F_SRV)
1.1.1.3   misho     766:                        {
1.1.1.4 ! misho     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)
1.1.1.3   misho     793:                            {
1.1.1.4 ! misho     794:                              if ((flags & F_IPV4) &&
        !           795:                                  private_net(addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
1.1.1.3   misho     796:                                return 1;
1.1.1.4 ! misho     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:                                }
1.1.1.3   misho     820:                            }
1.1.1.4 ! misho     821: 
1.1       misho     822: #ifdef HAVE_IPSET
1.1.1.4 ! misho     823:                          if (ipsets && (flags & (F_IPV4 | F_IPV6)))
1.1       misho     824:                            {
1.1.1.4 ! misho     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:                                }
1.1       misho     831:                            }
                    832: #endif
1.1.1.4 ! misho     833:                        }
1.1.1.2   misho     834:                      
1.1.1.4 ! misho     835:                      newc = cache_insert(name, &addr, C_IN, now, attl, flags | F_FORWARD | secflag);
1.1.1.2   misho     836:                      if (newc && cpp)
                    837:                        {
1.1.1.4 ! misho     838:                          next_uid(newc);
1.1.1.2   misho     839:                          cpp->addr.cname.target.cache = newc;
                    840:                          cpp->addr.cname.uid = newc->uid;
1.1       misho     841:                        }
1.1.1.2   misho     842:                      cpp = NULL;
1.1       misho     843:                    }
                    844:                }
1.1.1.2   misho     845:              
                    846:              p1 = endrr;
                    847:              if (!CHECK_LEN(header, p1, qlen, 0))
                    848:                return 0; /* bad packet */
1.1       misho     849:            }
                    850:          
                    851:          if (!found && !option_bool(OPT_NO_NEG))
                    852:            {
                    853:              if (!searched_soa)
                    854:                {
                    855:                  searched_soa = 1;
1.1.1.2   misho     856:                  ttl = find_soa(header, qlen, NULL, doctored);
1.1       misho     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:                {
1.1.1.4 ! misho     862:                  newc = cache_insert(name, NULL, C_IN, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));  
1.1       misho     863:                  if (newc && cpp)
                    864:                    {
1.1.1.4 ! misho     865:                      next_uid(newc);
1.1.1.2   misho     866:                      cpp->addr.cname.target.cache = newc;
1.1       misho     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) &&
1.1.1.2   misho     881:       !no_cache_dnssec)
1.1       misho     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:     }
1.1.1.4 ! misho     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;
1.1       misho     925:   
                    926:   return F_QUERY;
                    927: }
                    928: 
                    929: size_t setup_reply(struct dns_header *header, size_t qlen,
1.1.1.4 ! misho     930:                   union all_addr *addrp, unsigned int flags, unsigned long ttl)
1.1       misho     931: {
1.1.1.3   misho     932:   unsigned char *p;
1.1.1.4 ! misho     933:   
1.1.1.3   misho     934:   if (!(p = skip_questions(header, qlen)))
                    935:     return 0;
1.1       misho     936:   
                    937:   /* clear authoritative and truncated flags, set QR flag */
1.1.1.4 ! misho     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;
1.1       misho     941: 
                    942:   header->nscount = htons(0);
                    943:   header->arcount = htons(0);
                    944:   header->ancount = htons(0); /* no answers unless changed below */
1.1.1.3   misho     945:   if (flags == F_NOERR)
1.1       misho     946:     SET_RCODE(header, NOERROR); /* empty domain */
                    947:   else if (flags == F_NXDOMAIN)
                    948:     SET_RCODE(header, NXDOMAIN);
1.1.1.4 ! misho     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:        }
1.1       misho     973:     }
                    974:   else /* nowhere to forward to */
1.1.1.4 ! misho     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:   
1.1       misho     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)
1.1.1.4 ! misho     995:      if (hostname_issubdomain(name, naptr->name))
1.1       misho     996:       return 1;
                    997: 
                    998:    for (mx = daemon->mxnames; mx; mx = mx->next)
1.1.1.4 ! misho     999:     if (hostname_issubdomain(name, mx->name))
1.1       misho    1000:       return 1;
                   1001: 
                   1002:   for (txt = daemon->txt; txt; txt = txt->next)
1.1.1.4 ! misho    1003:     if (hostname_issubdomain(name, txt->name))
1.1       misho    1004:       return 1;
                   1005: 
                   1006:   for (intr = daemon->int_names; intr; intr = intr->next)
1.1.1.4 ! misho    1007:     if (hostname_issubdomain(name, intr->name))
1.1       misho    1008:       return 1;
                   1009: 
                   1010:   for (ptr = daemon->ptr; ptr; ptr = ptr->next)
1.1.1.4 ! misho    1011:     if (hostname_issubdomain(name, ptr->name))
1.1       misho    1012:       return 1;
1.1.1.4 ! misho    1013: 
        !          1014:   if (cache_find_non_terminal(name, now))
        !          1015:     return 1;
        !          1016: 
1.1       misho    1017:   return 0;
                   1018: }
                   1019: 
                   1020: /* Is the packet a reply with the answer address equal to addr?
                   1021:    If so mung is into an NXDOMAIN reply and also put that information
                   1022:    in the cache. */
                   1023: int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, 
                   1024:                             struct bogus_addr *baddr, time_t now)
                   1025: {
                   1026:   unsigned char *p;
                   1027:   int i, qtype, qclass, rdlen;
                   1028:   unsigned long ttl;
                   1029:   struct bogus_addr *baddrp;
                   1030: 
                   1031:   /* skip over questions */
                   1032:   if (!(p = skip_questions(header, qlen)))
                   1033:     return 0; /* bad packet */
                   1034: 
                   1035:   for (i = ntohs(header->ancount); i != 0; i--)
                   1036:     {
                   1037:       if (!extract_name(header, qlen, &p, name, 1, 10))
                   1038:        return 0; /* bad packet */
                   1039:   
                   1040:       GETSHORT(qtype, p); 
                   1041:       GETSHORT(qclass, p);
                   1042:       GETLONG(ttl, p);
                   1043:       GETSHORT(rdlen, p);
                   1044:       
                   1045:       if (qclass == C_IN && qtype == T_A)
                   1046:        {
                   1047:          if (!CHECK_LEN(header, p, qlen, INADDRSZ))
                   1048:            return 0;
                   1049:          
                   1050:          for (baddrp = baddr; baddrp; baddrp = baddrp->next)
                   1051:            if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
                   1052:              {
                   1053:                /* Found a bogus address. Insert that info here, since there no SOA record
                   1054:                   to get the ttl from in the normal processing */
                   1055:                cache_start_insert();
1.1.1.4 ! misho    1056:                cache_insert(name, NULL, C_IN, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN);
1.1       misho    1057:                cache_end_insert();
                   1058:                
                   1059:                return 1;
                   1060:              }
                   1061:        }
                   1062:       
                   1063:       if (!ADD_RDLEN(header, p, qlen, rdlen))
                   1064:        return 0;
                   1065:     }
                   1066:   
                   1067:   return 0;
                   1068: }
                   1069: 
1.1.1.3   misho    1070: int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr)
                   1071: {
                   1072:   unsigned char *p;
                   1073:   int i, qtype, qclass, rdlen;
                   1074:   struct bogus_addr *baddrp;
                   1075: 
                   1076:   /* skip over questions */
                   1077:   if (!(p = skip_questions(header, qlen)))
                   1078:     return 0; /* bad packet */
                   1079: 
                   1080:   for (i = ntohs(header->ancount); i != 0; i--)
                   1081:     {
                   1082:       if (!(p = skip_name(p, header, qlen, 10)))
                   1083:        return 0; /* bad packet */
                   1084:       
                   1085:       GETSHORT(qtype, p); 
                   1086:       GETSHORT(qclass, p);
                   1087:       p += 4; /* TTL */
                   1088:       GETSHORT(rdlen, p);
                   1089:       
                   1090:       if (qclass == C_IN && qtype == T_A)
                   1091:        {
                   1092:          if (!CHECK_LEN(header, p, qlen, INADDRSZ))
                   1093:            return 0;
                   1094:          
                   1095:          for (baddrp = baddr; baddrp; baddrp = baddrp->next)
                   1096:            if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
                   1097:              return 1;
                   1098:        }
                   1099:       
                   1100:       if (!ADD_RDLEN(header, p, qlen, rdlen))
                   1101:        return 0;
                   1102:     }
                   1103:   
                   1104:   return 0;
                   1105: }
                   1106: 
1.1.1.4 ! misho    1107: 
1.1       misho    1108: int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp, 
                   1109:                        unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
                   1110: {
                   1111:   va_list ap;
                   1112:   unsigned char *sav, *p = *pp;
                   1113:   int j;
                   1114:   unsigned short usval;
                   1115:   long lval;
                   1116:   char *sval;
1.1.1.4 ! misho    1117:   
        !          1118: #define CHECK_LIMIT(size) \
        !          1119:   if (limit && p + (size) > (unsigned char*)limit) goto truncated;
1.1       misho    1120: 
                   1121:   va_start(ap, format);   /* make ap point to 1st unamed argument */
                   1122:   
1.1.1.4 ! misho    1123:   if (truncp && *truncp)
        !          1124:     goto truncated;
        !          1125:   
1.1       misho    1126:   if (nameoffset > 0)
                   1127:     {
1.1.1.4 ! misho    1128:       CHECK_LIMIT(2);
1.1       misho    1129:       PUTSHORT(nameoffset | 0xc000, p);
                   1130:     }
                   1131:   else
                   1132:     {
                   1133:       char *name = va_arg(ap, char *);
1.1.1.4 ! misho    1134:       if (name && !(p = do_rfc1035_name(p, name, limit)))
        !          1135:        goto truncated;
        !          1136:       
1.1       misho    1137:       if (nameoffset < 0)
                   1138:        {
1.1.1.4 ! misho    1139:          CHECK_LIMIT(2);
1.1       misho    1140:          PUTSHORT(-nameoffset | 0xc000, p);
                   1141:        }
                   1142:       else
1.1.1.4 ! misho    1143:        {
        !          1144:          CHECK_LIMIT(1);
        !          1145:          *p++ = 0;
        !          1146:        }
1.1       misho    1147:     }
                   1148: 
1.1.1.4 ! misho    1149:   /* type (2) + class (2) + ttl (4) + rdlen (2) */
        !          1150:   CHECK_LIMIT(10);
        !          1151:   
1.1       misho    1152:   PUTSHORT(type, p);
                   1153:   PUTSHORT(class, p);
                   1154:   PUTLONG(ttl, p);      /* TTL */
                   1155: 
                   1156:   sav = p;              /* Save pointer to RDLength field */
                   1157:   PUTSHORT(0, p);       /* Placeholder RDLength */
                   1158: 
                   1159:   for (; *format; format++)
                   1160:     switch (*format)
                   1161:       {
                   1162:       case '6':
1.1.1.4 ! misho    1163:         CHECK_LIMIT(IN6ADDRSZ);
1.1       misho    1164:        sval = va_arg(ap, char *); 
                   1165:        memcpy(p, sval, IN6ADDRSZ);
                   1166:        p += IN6ADDRSZ;
                   1167:        break;
                   1168:        
                   1169:       case '4':
1.1.1.4 ! misho    1170:         CHECK_LIMIT(INADDRSZ);
1.1       misho    1171:        sval = va_arg(ap, char *); 
                   1172:        memcpy(p, sval, INADDRSZ);
                   1173:        p += INADDRSZ;
                   1174:        break;
                   1175:        
1.1.1.2   misho    1176:       case 'b':
1.1.1.4 ! misho    1177:         CHECK_LIMIT(1);
1.1.1.2   misho    1178:        usval = va_arg(ap, int);
                   1179:        *p++ = usval;
                   1180:        break;
                   1181:        
1.1       misho    1182:       case 's':
1.1.1.4 ! misho    1183:         CHECK_LIMIT(2);
1.1       misho    1184:        usval = va_arg(ap, int);
                   1185:        PUTSHORT(usval, p);
                   1186:        break;
                   1187:        
                   1188:       case 'l':
1.1.1.4 ! misho    1189:         CHECK_LIMIT(4);
1.1       misho    1190:        lval = va_arg(ap, long);
                   1191:        PUTLONG(lval, p);
                   1192:        break;
                   1193:        
                   1194:       case 'd':
1.1.1.4 ! misho    1195:         /* get domain-name answer arg and store it in RDATA field */
        !          1196:         if (offset)
        !          1197:           *offset = p - (unsigned char *)header;
        !          1198:         if (!(p = do_rfc1035_name(p, va_arg(ap, char *), limit)))
        !          1199:          goto truncated;
        !          1200:        CHECK_LIMIT(1);
        !          1201:         *p++ = 0;
1.1       misho    1202:        break;
                   1203:        
                   1204:       case 't':
                   1205:        usval = va_arg(ap, int);
1.1.1.4 ! misho    1206:         CHECK_LIMIT(usval);
1.1       misho    1207:        sval = va_arg(ap, char *);
                   1208:        if (usval != 0)
                   1209:          memcpy(p, sval, usval);
                   1210:        p += usval;
                   1211:        break;
                   1212: 
                   1213:       case 'z':
                   1214:        sval = va_arg(ap, char *);
                   1215:        usval = sval ? strlen(sval) : 0;
                   1216:        if (usval > 255)
                   1217:          usval = 255;
1.1.1.4 ! misho    1218:         CHECK_LIMIT(usval + 1);
1.1       misho    1219:        *p++ = (unsigned char)usval;
                   1220:        memcpy(p, sval, usval);
                   1221:        p += usval;
                   1222:        break;
                   1223:       }
                   1224: 
                   1225:   va_end(ap);  /* clean up variable argument pointer */
                   1226:   
1.1.1.4 ! misho    1227:   /* Now, store real RDLength. sav already checked against limit. */
1.1       misho    1228:   j = p - sav - 2;
1.1.1.4 ! misho    1229:   PUTSHORT(j, sav);
1.1       misho    1230:   
                   1231:   *pp = p;
                   1232:   return 1;
1.1.1.4 ! misho    1233:   
        !          1234:  truncated:
        !          1235:   va_end(ap);
        !          1236:   if (truncp)
        !          1237:     *truncp = 1;
        !          1238:   return 0;
        !          1239: 
        !          1240: #undef CHECK_LIMIT
1.1       misho    1241: }
                   1242: 
                   1243: static unsigned long crec_ttl(struct crec *crecp, time_t now)
                   1244: {
                   1245:   /* Return 0 ttl for DHCP entries, which might change
1.1.1.3   misho    1246:      before the lease expires, unless configured otherwise. */
1.1       misho    1247: 
1.1.1.3   misho    1248:   if (crecp->flags & F_DHCP)
                   1249:     {
                   1250:       int conf_ttl = daemon->use_dhcp_ttl ? daemon->dhcp_ttl : daemon->local_ttl;
                   1251:       
                   1252:       /* Apply ceiling of actual lease length to configured TTL. */
                   1253:       if (!(crecp->flags & F_IMMORTAL) && (crecp->ttd - now) < conf_ttl)
                   1254:        return crecp->ttd - now;
                   1255:       
                   1256:       return conf_ttl;
                   1257:     }    
1.1       misho    1258:   
1.1.1.3   misho    1259:   /* Immortal entries other than DHCP are local, and hold TTL in TTD field. */
                   1260:   if (crecp->flags & F_IMMORTAL)
                   1261:     return crecp->ttd;
                   1262: 
1.1.1.4 ! misho    1263:   /* Return the Max TTL value if it is lower than the actual TTL */
1.1       misho    1264:   if (daemon->max_ttl == 0 || ((unsigned)(crecp->ttd - now) < daemon->max_ttl))
                   1265:     return crecp->ttd - now;
                   1266:   else
                   1267:     return daemon->max_ttl;
                   1268: }
1.1.1.4 ! misho    1269: 
        !          1270: static int cache_validated(const struct crec *crecp)
        !          1271: {
        !          1272:   return (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK));
        !          1273: }
1.1       misho    1274: 
                   1275: /* return zero if we can't answer from cache, or packet size if we can */
                   1276: size_t answer_request(struct dns_header *header, char *limit, size_t qlen,  
1.1.1.2   misho    1277:                      struct in_addr local_addr, struct in_addr local_netmask, 
1.1.1.3   misho    1278:                      time_t now, int ad_reqd, int do_bit, int have_pseudoheader) 
1.1       misho    1279: {
                   1280:   char *name = daemon->namebuff;
1.1.1.3   misho    1281:   unsigned char *p, *ansp;
1.1.1.2   misho    1282:   unsigned int qtype, qclass;
1.1.1.4 ! misho    1283:   union all_addr addr;
1.1       misho    1284:   int nameoffset;
                   1285:   unsigned short flag;
                   1286:   int q, ans, anscount = 0, addncount = 0;
1.1.1.3   misho    1287:   int dryrun = 0;
1.1       misho    1288:   struct crec *crecp;
1.1.1.4 ! misho    1289:   int nxdomain = 0, notimp = 0, auth = 1, trunc = 0, sec_data = 1;
1.1       misho    1290:   struct mx_srv_record *rec;
1.1.1.2   misho    1291:   size_t len;
1.1.1.4 ! misho    1292:   int rd_bit = (header->hb3 & HB3_RD);
        !          1293: 
        !          1294:   /* never answer queries with RD unset, to avoid cache snooping. */
1.1.1.3   misho    1295:   if (ntohs(header->ancount) != 0 ||
                   1296:       ntohs(header->nscount) != 0 ||
1.1.1.4 ! misho    1297:       ntohs(header->qdcount) == 0 ||
1.1.1.3   misho    1298:       OPCODE(header) != QUERY )
                   1299:     return 0;
1.1.1.4 ! misho    1300: 
1.1.1.2   misho    1301:   /* Don't return AD set if checking disabled. */
                   1302:   if (header->hb4 & HB4_CD)
                   1303:     sec_data = 0;
                   1304:   
1.1.1.3   misho    1305:   /* If there is an  additional data section then it will be overwritten by
1.1       misho    1306:      partial replies, so we have to do a dry run to see if we can answer
1.1.1.3   misho    1307:      the query. */
                   1308:   if (ntohs(header->arcount) != 0)
                   1309:     dryrun = 1;
1.1       misho    1310: 
                   1311:   for (rec = daemon->mxnames; rec; rec = rec->next)
                   1312:     rec->offset = 0;
                   1313:   
                   1314:  rerun:
                   1315:   /* determine end of question section (we put answers there) */
                   1316:   if (!(ansp = skip_questions(header, qlen)))
                   1317:     return 0; /* bad packet */
                   1318:    
                   1319:   /* now process each question, answers go in RRs after the question */
                   1320:   p = (unsigned char *)(header+1);
                   1321: 
                   1322:   for (q = ntohs(header->qdcount); q != 0; q--)
                   1323:     {
1.1.1.4 ! misho    1324:       int count = 255; /* catch loops */
        !          1325:       
1.1       misho    1326:       /* save pointer to name for copying into answers */
                   1327:       nameoffset = p - (unsigned char *)header;
                   1328: 
                   1329:       /* now extract name as .-concatenated string into name */
                   1330:       if (!extract_name(header, qlen, &p, name, 1, 4))
                   1331:        return 0; /* bad packet */
                   1332:             
                   1333:       GETSHORT(qtype, p); 
                   1334:       GETSHORT(qclass, p);
                   1335: 
                   1336:       ans = 0; /* have we answered this question */
1.1.1.4 ! misho    1337: 
        !          1338:       while (--count != 0 && (crecp = cache_find_by_name(NULL, name, now, F_CNAME)))
        !          1339:        {
        !          1340:          char *cname_target = cache_get_cname_target(crecp);
        !          1341: 
        !          1342:          /* If the client asked for DNSSEC  don't use cached data. */
        !          1343:          if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
        !          1344:              (rd_bit && (!do_bit || cache_validated(crecp))))
        !          1345:            {
        !          1346:              if (crecp->flags & F_CONFIG || qtype == T_CNAME)
        !          1347:                ans = 1;
        !          1348: 
        !          1349:              if (!(crecp->flags & F_DNSSECOK))
        !          1350:                sec_data = 0;
        !          1351: 
        !          1352:              if (!dryrun)
        !          1353:                {
        !          1354:                  log_query(crecp->flags, name, NULL, record_source(crecp->uid));
        !          1355:                  if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
        !          1356:                                          crec_ttl(crecp, now), &nameoffset,
        !          1357:                                          T_CNAME, C_IN, "d", cname_target))
        !          1358:                    anscount++;
        !          1359:                }
        !          1360: 
        !          1361:            }
        !          1362:          else
        !          1363:            return 0; /* give up if any cached CNAME in chain can't be used for DNSSEC reasons. */
        !          1364: 
        !          1365:          strcpy(name, cname_target);
        !          1366:        }
        !          1367:          
1.1       misho    1368:       if (qtype == T_TXT || qtype == T_ANY)
                   1369:        {
                   1370:          struct txt_record *t;
                   1371:          for(t = daemon->txt; t ; t = t->next)
                   1372:            {
                   1373:              if (t->class == qclass && hostname_isequal(name, t->name))
                   1374:                {
1.1.1.4 ! misho    1375:                  ans = 1, sec_data = 0;
1.1       misho    1376:                  if (!dryrun)
                   1377:                    {
1.1.1.2   misho    1378:                      unsigned long ttl = daemon->local_ttl;
                   1379:                      int ok = 1;
1.1.1.4 ! misho    1380: #ifndef NO_ID
1.1.1.2   misho    1381:                      /* Dynamically generate stat record */
                   1382:                      if (t->stat != 0)
                   1383:                        {
                   1384:                          ttl = 0;
                   1385:                          if (!cache_make_stat(t))
                   1386:                            ok = 0;
                   1387:                        }
1.1.1.4 ! misho    1388: #endif
        !          1389:                      if (ok)
        !          1390:                        {
        !          1391:                          log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
        !          1392:                          if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
        !          1393:                                                  ttl, NULL,
        !          1394:                                                  T_TXT, t->class, "t", t->len, t->txt))
        !          1395:                            anscount++;
        !          1396:                        }
        !          1397:                    }
        !          1398:                }
        !          1399:            }
        !          1400:        }
1.1       misho    1401: 
1.1.1.4 ! misho    1402:       if (qclass == C_CHAOS)
        !          1403:        {
        !          1404:          /* don't forward *.bind and *.server chaos queries - always reply with NOTIMP */
        !          1405:          if (hostname_issubdomain("bind", name) || hostname_issubdomain("server", name))
        !          1406:            {
        !          1407:              if (!ans)
        !          1408:                {
        !          1409:                  notimp = 1, auth = 0;
        !          1410:                  if (!dryrun)
        !          1411:                    {
        !          1412:                       addr.log.rcode = NOTIMP;
        !          1413:                       log_query(F_CONFIG | F_RCODE, name, &addr, NULL);
1.1       misho    1414:                    }
1.1.1.4 ! misho    1415:                  ans = 1, sec_data = 0;
1.1       misho    1416:                }
                   1417:            }
                   1418:        }
                   1419: 
                   1420:       if (qclass == C_IN)
                   1421:        {
                   1422:          struct txt_record *t;
                   1423: 
                   1424:          for (t = daemon->rr; t; t = t->next)
                   1425:            if ((t->class == qtype || qtype == T_ANY) && hostname_isequal(name, t->name))
                   1426:              {
                   1427:                ans = 1;
1.1.1.3   misho    1428:                sec_data = 0;
1.1       misho    1429:                if (!dryrun)
                   1430:                  {
1.1.1.4 ! misho    1431:                    log_query(F_CONFIG | F_RRNAME, name, NULL, querystr(NULL, t->class));
1.1       misho    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))
1.1.1.4 ! misho    1435:                      anscount++;
1.1       misho    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:                  {
1.1.1.2   misho    1453:                    struct addrlist *addrlist;
                   1454:                    
                   1455:                    for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
1.1.1.4 ! misho    1456:                      if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr4.s_addr == addrlist->addr.addr4.s_addr)
1.1.1.2   misho    1457:                        break;
                   1458:                    
                   1459:                    if (addrlist)
1.1       misho    1460:                      break;
                   1461:                    else
                   1462:                      while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
                   1463:                        intr = intr->next;
                   1464:                  }
1.1.1.2   misho    1465:              else if (is_arpa == F_IPV6)
                   1466:                for (intr = daemon->int_names; intr; intr = intr->next)
                   1467:                  {
                   1468:                    struct addrlist *addrlist;
                   1469:                    
                   1470:                    for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
1.1.1.4 ! misho    1471:                      if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr6, &addrlist->addr.addr6))
1.1.1.2   misho    1472:                        break;
                   1473:                    
                   1474:                    if (addrlist)
                   1475:                      break;
                   1476:                    else
                   1477:                      while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
                   1478:                        intr = intr->next;
                   1479:                  }
1.1       misho    1480:              
                   1481:              if (intr)
                   1482:                {
1.1.1.3   misho    1483:                  sec_data = 0;
1.1       misho    1484:                  ans = 1;
                   1485:                  if (!dryrun)
                   1486:                    {
1.1.1.2   misho    1487:                      log_query(is_arpa | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
1.1       misho    1488:                      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                   1489:                                              daemon->local_ttl, NULL,
                   1490:                                              T_PTR, C_IN, "d", intr->name))
                   1491:                        anscount++;
                   1492:                    }
                   1493:                }
                   1494:              else if (ptr)
                   1495:                {
                   1496:                  ans = 1;
1.1.1.3   misho    1497:                  sec_data = 0;
1.1       misho    1498:                  if (!dryrun)
                   1499:                    {
                   1500:                      log_query(F_CONFIG | F_RRNAME, name, NULL, "<PTR>");
                   1501:                      for (ptr = daemon->ptr; ptr; ptr = ptr->next)
                   1502:                        if (hostname_isequal(name, ptr->name) &&
                   1503:                            add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                   1504:                                                daemon->local_ttl, NULL,
                   1505:                                                T_PTR, C_IN, "d", ptr->ptr))
                   1506:                          anscount++;
                   1507:                         
                   1508:                    }
                   1509:                }
                   1510:              else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
1.1.1.2   misho    1511:                {
1.1.1.3   misho    1512:                  /* Don't use cache when DNSSEC data required, unless we know that
                   1513:                     the zone is unsigned, which implies that we're doing
                   1514:                     validation. */
1.1.1.4 ! misho    1515:                  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
        !          1516:                      (rd_bit && (!do_bit || cache_validated(crecp)) ))
1.1.1.2   misho    1517:                    {
                   1518:                      do 
                   1519:                        { 
                   1520:                          /* don't answer wildcard queries with data not from /etc/hosts or dhcp leases */
                   1521:                          if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP)))
                   1522:                            continue;
                   1523:                          
                   1524:                          if (!(crecp->flags & F_DNSSECOK))
                   1525:                            sec_data = 0;
1.1.1.3   misho    1526:                           
                   1527:                          ans = 1;
                   1528:                           
1.1.1.2   misho    1529:                          if (crecp->flags & F_NEG)
                   1530:                            {
                   1531:                              auth = 0;
                   1532:                              if (crecp->flags & F_NXDOMAIN)
                   1533:                                nxdomain = 1;
                   1534:                              if (!dryrun)
                   1535:                                log_query(crecp->flags & ~F_FORWARD, name, &addr, NULL);
                   1536:                            }
1.1.1.3   misho    1537:                          else
1.1.1.2   misho    1538:                            {
                   1539:                              if (!(crecp->flags & (F_HOSTS | F_DHCP)))
                   1540:                                auth = 0;
                   1541:                              if (!dryrun)
                   1542:                                {
                   1543:                                  log_query(crecp->flags & ~F_FORWARD, cache_get_name(crecp), &addr, 
                   1544:                                            record_source(crecp->uid));
                   1545:                                  
                   1546:                                  if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                   1547:                                                          crec_ttl(crecp, now), NULL,
                   1548:                                                          T_PTR, C_IN, "d", cache_get_name(crecp)))
                   1549:                                    anscount++;
                   1550:                                }
                   1551:                            }
                   1552:                        } while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa)));
                   1553:                    }
                   1554:                }
                   1555:              else if (is_rev_synth(is_arpa, &addr, name))
                   1556:                {
                   1557:                  ans = 1;
1.1.1.3   misho    1558:                  sec_data = 0;
1.1.1.2   misho    1559:                  if (!dryrun)
                   1560:                    {
                   1561:                      log_query(F_CONFIG | F_REVERSE | is_arpa, name, &addr, NULL); 
                   1562:                      
                   1563:                      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                   1564:                                              daemon->local_ttl, NULL,
                   1565:                                              T_PTR, C_IN, "d", name))
1.1       misho    1566:                              anscount++;
1.1.1.2   misho    1567:                    }
                   1568:                }
1.1.1.4 ! misho    1569:              else if (option_bool(OPT_BOGUSPRIV) && (
        !          1570:                       (is_arpa == F_IPV6 && private_net6(&addr.addr6)) ||
        !          1571:                       (is_arpa == F_IPV4 && private_net(addr.addr4, 1))))
        !          1572:                {
        !          1573:                  struct server *serv;
        !          1574:                  unsigned int namelen = strlen(name);
        !          1575:                  char *nameend = name + namelen;
1.1.1.2   misho    1576: 
1.1.1.4 ! misho    1577:                  /* see if have rev-server set */
        !          1578:                  for (serv = daemon->servers; serv; serv = serv->next)
1.1       misho    1579:                    {
1.1.1.4 ! misho    1580:                      unsigned int domainlen;
        !          1581:                      char *matchstart;
        !          1582: 
        !          1583:                      if ((serv->flags & (SERV_HAS_DOMAIN | SERV_NO_ADDR)) != SERV_HAS_DOMAIN)
        !          1584:                        continue;
        !          1585: 
        !          1586:                      domainlen = strlen(serv->domain);
        !          1587:                      if (domainlen == 0 || domainlen > namelen)
        !          1588:                        continue;
        !          1589: 
        !          1590:                      matchstart = nameend - domainlen;
        !          1591:                      if (hostname_isequal(matchstart, serv->domain) &&
        !          1592:                          (namelen == domainlen || *(matchstart-1) == '.' ))
        !          1593:                        break;
1.1       misho    1594:                    }
1.1.1.4 ! misho    1595: 
        !          1596:                  /* if no configured server, not in cache, enabled and private IPV4 address, return NXDOMAIN */
        !          1597:                  if (!serv)
1.1       misho    1598:                    {
                   1599:                      ans = 1;
1.1.1.3   misho    1600:                      sec_data = 0;
1.1.1.4 ! misho    1601:                      nxdomain = 1;
1.1       misho    1602:                      if (!dryrun)
1.1.1.4 ! misho    1603:                        log_query(F_CONFIG | F_REVERSE | is_arpa | F_NEG | F_NXDOMAIN,
        !          1604:                                  name, &addr, NULL);
1.1       misho    1605:                    }
                   1606:                }
1.1.1.4 ! misho    1607:            }
1.1       misho    1608: 
1.1.1.4 ! misho    1609:          for (flag = F_IPV4; flag; flag = (flag == F_IPV4) ? F_IPV6 : 0)
        !          1610:            {
        !          1611:              unsigned short type = (flag == F_IPV6) ? T_AAAA : T_A;
        !          1612:              struct interface_name *intr;
        !          1613: 
        !          1614:              if (qtype != type && qtype != T_ANY)
        !          1615:                continue;
        !          1616:              
1.1       misho    1617:              /* interface name stuff */
1.1.1.2   misho    1618:              for (intr = daemon->int_names; intr; intr = intr->next)
                   1619:                if (hostname_isequal(name, intr->name))
                   1620:                  break;
                   1621:              
                   1622:              if (intr)
1.1       misho    1623:                {
1.1.1.2   misho    1624:                  struct addrlist *addrlist;
1.1.1.4 ! misho    1625:                  int gotit = 0, localise = 0;
1.1       misho    1626: 
1.1.1.2   misho    1627:                  enumerate_interfaces(0);
1.1.1.4 ! misho    1628:                    
        !          1629:                  /* See if a putative address is on the network from which we received
        !          1630:                     the query, is so we'll filter other answers. */
        !          1631:                  if (local_addr.s_addr != 0 && option_bool(OPT_LOCALISE) && type == T_A)
        !          1632:                    for (intr = daemon->int_names; intr; intr = intr->next)
        !          1633:                      if (hostname_isequal(name, intr->name))
        !          1634:                        for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
        !          1635:                          if (!(addrlist->flags & ADDRLIST_IPV6) && 
        !          1636:                              is_same_net(addrlist->addr.addr4, local_addr, local_netmask))
        !          1637:                            {
        !          1638:                              localise = 1;
        !          1639:                              break;
        !          1640:                            }
1.1.1.2   misho    1641:                  
1.1       misho    1642:                  for (intr = daemon->int_names; intr; intr = intr->next)
                   1643:                    if (hostname_isequal(name, intr->name))
1.1.1.2   misho    1644:                      {
1.1.1.3   misho    1645:                        for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
                   1646:                          if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type)
                   1647:                            {
1.1.1.4 ! misho    1648:                              if (localise && 
        !          1649:                                  !is_same_net(addrlist->addr.addr4, local_addr, local_netmask))
        !          1650:                                continue;
        !          1651: 
1.1.1.3   misho    1652:                              if (addrlist->flags & ADDRLIST_REVONLY)
                   1653:                                continue;
1.1.1.4 ! misho    1654: 
1.1.1.3   misho    1655:                              ans = 1;  
                   1656:                              sec_data = 0;
                   1657:                              if (!dryrun)
1.1.1.2   misho    1658:                                {
                   1659:                                  gotit = 1;
                   1660:                                  log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
                   1661:                                  if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                   1662:                                                          daemon->local_ttl, NULL, type, C_IN, 
                   1663:                                                          type == T_A ? "4" : "6", &addrlist->addr))
                   1664:                                    anscount++;
                   1665:                                }
1.1.1.3   misho    1666:                            }
1.1.1.2   misho    1667:                      }
1.1       misho    1668:                  
1.1.1.2   misho    1669:                  if (!dryrun && !gotit)
                   1670:                    log_query(F_FORWARD | F_CONFIG | flag | F_NEG, name, NULL, NULL);
                   1671:                     
                   1672:                  continue;
1.1       misho    1673:                }
                   1674: 
1.1.1.4 ! misho    1675:              if ((crecp = cache_find_by_name(NULL, name, now, flag | (dryrun ? F_NO_RR : 0))))
1.1       misho    1676:                {
                   1677:                  int localise = 0;
                   1678:                  
1.1.1.4 ! misho    1679:                  /* See if a putative address is on the network from which we received
1.1       misho    1680:                     the query, is so we'll filter other answers. */
                   1681:                  if (local_addr.s_addr != 0 && option_bool(OPT_LOCALISE) && flag == F_IPV4)
                   1682:                    {
                   1683:                      struct crec *save = crecp;
                   1684:                      do {
                   1685:                        if ((crecp->flags & F_HOSTS) &&
1.1.1.4 ! misho    1686:                            is_same_net(crecp->addr.addr4, local_addr, local_netmask))
1.1       misho    1687:                          {
                   1688:                            localise = 1;
                   1689:                            break;
                   1690:                          } 
1.1.1.4 ! misho    1691:                        } while ((crecp = cache_find_by_name(crecp, name, now, flag)));
1.1       misho    1692:                      crecp = save;
                   1693:                    }
1.1.1.2   misho    1694: 
1.1.1.3   misho    1695:                  /* If the client asked for DNSSEC  don't use cached data. */
1.1.1.4 ! misho    1696:                  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
        !          1697:                      (rd_bit && (!do_bit || cache_validated(crecp)) ))
1.1.1.2   misho    1698:                    do
                   1699:                      { 
                   1700:                        /* don't answer wildcard queries with data not from /etc/hosts
                   1701:                           or DHCP leases */
                   1702:                        if (qtype == T_ANY && !(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
                   1703:                          break;
                   1704:                        
                   1705:                        if (!(crecp->flags & F_DNSSECOK))
                   1706:                          sec_data = 0;
                   1707:                        
                   1708:                        if (crecp->flags & F_NEG)
                   1709:                          {
1.1.1.3   misho    1710:                            ans = 1;
                   1711:                            auth = 0;
                   1712:                            if (crecp->flags & F_NXDOMAIN)
                   1713:                              nxdomain = 1;
                   1714:                            if (!dryrun)
                   1715:                              log_query(crecp->flags, name, NULL, NULL);
1.1.1.2   misho    1716:                          }
                   1717:                        else 
                   1718:                          {
                   1719:                            /* If we are returning local answers depending on network,
                   1720:                               filter here. */
                   1721:                            if (localise && 
                   1722:                                (crecp->flags & F_HOSTS) &&
1.1.1.4 ! misho    1723:                                !is_same_net(crecp->addr.addr4, local_addr, local_netmask))
1.1.1.2   misho    1724:                              continue;
                   1725:                            
                   1726:                            if (!(crecp->flags & (F_HOSTS | F_DHCP)))
                   1727:                              auth = 0;
                   1728:                            
                   1729:                            ans = 1;
                   1730:                            if (!dryrun)
                   1731:                              {
1.1.1.4 ! misho    1732:                                log_query(crecp->flags & ~F_REVERSE, name, &crecp->addr,
1.1.1.2   misho    1733:                                          record_source(crecp->uid));
                   1734:                                
                   1735:                                if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                   1736:                                                        crec_ttl(crecp, now), NULL, type, C_IN, 
                   1737:                                                        type == T_A ? "4" : "6", &crecp->addr))
                   1738:                                  anscount++;
                   1739:                              }
                   1740:                          }
1.1.1.4 ! misho    1741:                      } while ((crecp = cache_find_by_name(crecp, name, now, flag)));
1.1.1.2   misho    1742:                }
                   1743:              else if (is_name_synthetic(flag, name, &addr))
                   1744:                {
1.1.1.4 ! misho    1745:                  ans = 1, sec_data = 0;
1.1.1.2   misho    1746:                  if (!dryrun)
                   1747:                    {
                   1748:                      log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL);
                   1749:                      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                   1750:                                              daemon->local_ttl, NULL, type, C_IN, type == T_A ? "4" : "6", &addr))
                   1751:                        anscount++;
                   1752:                    }
1.1       misho    1753:                }
                   1754:            }
                   1755: 
                   1756:          if (qtype == T_MX || qtype == T_ANY)
                   1757:            {
                   1758:              int found = 0;
                   1759:              for (rec = daemon->mxnames; rec; rec = rec->next)
                   1760:                if (!rec->issrv && hostname_isequal(name, rec->name))
                   1761:                  {
1.1.1.4 ! misho    1762:                    ans = found = 1;
        !          1763:                    sec_data = 0;
        !          1764:                    if (!dryrun)
        !          1765:                      {
        !          1766:                        int offset;
        !          1767:                        log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
        !          1768:                        if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl,
        !          1769:                                                &offset, T_MX, C_IN, "sd", rec->weight, rec->target))
        !          1770:                          {
        !          1771:                            anscount++;
        !          1772:                            if (rec->target)
        !          1773:                              rec->offset = offset;
        !          1774:                          }
        !          1775:                      }
1.1       misho    1776:                  }
                   1777:              
1.1.1.4 ! misho    1778:              if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) &&
1.1.1.2   misho    1779:                  cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP | F_NO_RR))
1.1       misho    1780:                { 
                   1781:                  ans = 1;
1.1.1.4 ! misho    1782:                  sec_data = 0;
1.1       misho    1783:                  if (!dryrun)
                   1784:                    {
                   1785:                      log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
                   1786:                      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, NULL, 
                   1787:                                              T_MX, C_IN, "sd", 1, 
                   1788:                                              option_bool(OPT_SELFMX) ? name : daemon->mxtarget))
                   1789:                        anscount++;
                   1790:                    }
                   1791:                }
                   1792:            }
                   1793:                  
                   1794:          if (qtype == T_SRV || qtype == T_ANY)
                   1795:            {
                   1796:              int found = 0;
                   1797:              struct mx_srv_record *move = NULL, **up = &daemon->mxnames;
                   1798: 
                   1799:              for (rec = daemon->mxnames; rec; rec = rec->next)
                   1800:                if (rec->issrv && hostname_isequal(name, rec->name))
                   1801:                  {
                   1802:                    found = ans = 1;
1.1.1.4 ! misho    1803:                    sec_data = 0;
1.1       misho    1804:                    if (!dryrun)
                   1805:                      {
                   1806:                        int offset;
                   1807:                        log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
                   1808:                        if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, 
                   1809:                                                &offset, T_SRV, C_IN, "sssd", 
                   1810:                                                rec->priority, rec->weight, rec->srvport, rec->target))
                   1811:                          {
                   1812:                            anscount++;
                   1813:                            if (rec->target)
                   1814:                              rec->offset = offset;
                   1815:                          }
                   1816:                      }
                   1817:                    
                   1818:                    /* unlink first SRV record found */
                   1819:                    if (!move)
                   1820:                      {
                   1821:                        move = rec;
                   1822:                        *up = rec->next;
                   1823:                      }
                   1824:                    else
                   1825:                      up = &rec->next;      
                   1826:                  }
                   1827:                else
                   1828:                  up = &rec->next;
                   1829: 
                   1830:              /* put first SRV record back at the end. */
                   1831:              if (move)
                   1832:                {
                   1833:                  *up = move;
                   1834:                  move->next = NULL;
                   1835:                }
1.1.1.4 ! misho    1836: 
        !          1837:              if (!found)
        !          1838:                {
        !          1839:                  if ((crecp = cache_find_by_name(NULL, name, now, F_SRV | (dryrun ? F_NO_RR : 0))) &&
        !          1840:                      rd_bit && (!do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
        !          1841:                    {
        !          1842:                      if (!(crecp->flags & F_DNSSECOK))
        !          1843:                        sec_data = 0;
        !          1844:                      
        !          1845:                      auth = 0;
        !          1846:                      found = ans = 1;
        !          1847:                      
        !          1848:                      do {
        !          1849:                        if (crecp->flags & F_NEG)
        !          1850:                          {
        !          1851:                            if (crecp->flags & F_NXDOMAIN)
        !          1852:                              nxdomain = 1;
        !          1853:                            if (!dryrun)
        !          1854:                              log_query(crecp->flags, name, NULL, NULL);
        !          1855:                          }
        !          1856:                        else if (!dryrun)
        !          1857:                          {
        !          1858:                            char *target = blockdata_retrieve(crecp->addr.srv.target, crecp->addr.srv.targetlen, NULL);
        !          1859:                            log_query(crecp->flags, name, NULL, 0);
        !          1860:                            
        !          1861:                            if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
        !          1862:                                                    crec_ttl(crecp, now), NULL, T_SRV, C_IN, "sssd",
        !          1863:                                                    crecp->addr.srv.priority, crecp->addr.srv.weight, crecp->addr.srv.srvport,
        !          1864:                                                    target))
        !          1865:                              anscount++;
        !          1866:                          }
        !          1867:                      } while ((crecp = cache_find_by_name(crecp, name, now, F_SRV)));
        !          1868:                    }
        !          1869:                }
        !          1870: 
1.1       misho    1871:              if (!found && option_bool(OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_'))))
                   1872:                {
                   1873:                  ans = 1;
1.1.1.4 ! misho    1874:                  sec_data = 0;
1.1       misho    1875:                  if (!dryrun)
                   1876:                    log_query(F_CONFIG | F_NEG, name, NULL, NULL);
                   1877:                }
                   1878:            }
                   1879: 
                   1880:          if (qtype == T_NAPTR || qtype == T_ANY)
                   1881:            {
                   1882:              struct naptr *na;
                   1883:              for (na = daemon->naptr; na; na = na->next)
                   1884:                if (hostname_isequal(name, na->name))
                   1885:                  {
                   1886:                    ans = 1;
1.1.1.4 ! misho    1887:                    sec_data = 0;
1.1       misho    1888:                    if (!dryrun)
                   1889:                      {
                   1890:                        log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
                   1891:                        if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->local_ttl, 
                   1892:                                                NULL, T_NAPTR, C_IN, "sszzzd", 
                   1893:                                                na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
                   1894:                          anscount++;
                   1895:                      }
                   1896:                  }
                   1897:            }
                   1898:          
                   1899:          if (qtype == T_MAILB)
1.1.1.4 ! misho    1900:            ans = 1, nxdomain = 1, sec_data = 0;
1.1       misho    1901: 
                   1902:          if (qtype == T_SOA && option_bool(OPT_FILTER))
                   1903:            {
1.1.1.4 ! misho    1904:              ans = 1;
        !          1905:              sec_data = 0;
1.1       misho    1906:              if (!dryrun)
                   1907:                log_query(F_CONFIG | F_NEG, name, &addr, NULL);
                   1908:            }
                   1909:        }
                   1910: 
                   1911:       if (!ans)
                   1912:        return 0; /* failed to answer a question */
                   1913:     }
                   1914:   
                   1915:   if (dryrun)
                   1916:     {
                   1917:       dryrun = 0;
                   1918:       goto rerun;
                   1919:     }
                   1920:   
                   1921:   /* create an additional data section, for stuff in SRV and MX record replies. */
                   1922:   for (rec = daemon->mxnames; rec; rec = rec->next)
                   1923:     if (rec->offset != 0)
                   1924:       {
                   1925:        /* squash dupes */
                   1926:        struct mx_srv_record *tmp;
                   1927:        for (tmp = rec->next; tmp; tmp = tmp->next)
                   1928:          if (tmp->offset != 0 && hostname_isequal(rec->target, tmp->target))
                   1929:            tmp->offset = 0;
                   1930:        
                   1931:        crecp = NULL;
                   1932:        while ((crecp = cache_find_by_name(crecp, rec->target, now, F_IPV4 | F_IPV6)))
                   1933:          {
                   1934:            int type =  crecp->flags & F_IPV4 ? T_A : T_AAAA;
1.1.1.4 ! misho    1935: 
1.1       misho    1936:            if (crecp->flags & F_NEG)
                   1937:              continue;
                   1938: 
                   1939:            if (add_resource_record(header, limit, NULL, rec->offset, &ansp, 
                   1940:                                    crec_ttl(crecp, now), NULL, type, C_IN, 
                   1941:                                    crecp->flags & F_IPV4 ? "4" : "6", &crecp->addr))
                   1942:              addncount++;
                   1943:          }
                   1944:       }
                   1945:   
                   1946:   /* done all questions, set up header and return length of result */
                   1947:   /* clear authoritative and truncated flags, set QR flag */
                   1948:   header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
                   1949:   /* set RA flag */
                   1950:   header->hb4 |= HB4_RA;
                   1951:    
1.1.1.4 ! misho    1952:   /* authoritative - only hosts and DHCP derived names. */
1.1       misho    1953:   if (auth)
                   1954:     header->hb3 |= HB3_AA;
                   1955:   
                   1956:   /* truncation */
                   1957:   if (trunc)
                   1958:     header->hb3 |= HB3_TC;
1.1.1.2   misho    1959:   
                   1960:   if (nxdomain)
1.1       misho    1961:     SET_RCODE(header, NXDOMAIN);
1.1.1.4 ! misho    1962:   else if (notimp)
        !          1963:     SET_RCODE(header, NOTIMP);
1.1       misho    1964:   else
                   1965:     SET_RCODE(header, NOERROR); /* no error */
                   1966:   header->ancount = htons(anscount);
                   1967:   header->nscount = htons(0);
                   1968:   header->arcount = htons(addncount);
1.1.1.2   misho    1969: 
                   1970:   len = ansp - (unsigned char *)header;
                   1971:   
1.1.1.3   misho    1972:   /* Advertise our packet size limit in our reply */
1.1.1.2   misho    1973:   if (have_pseudoheader)
1.1.1.3   misho    1974:     len = add_pseudoheader(header, len, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
1.1.1.2   misho    1975:   
1.1.1.3   misho    1976:   if (ad_reqd && sec_data)
1.1.1.2   misho    1977:     header->hb4 |= HB4_AD;
                   1978:   else
                   1979:     header->hb4 &= ~HB4_AD;
                   1980:   
                   1981:   return len;
1.1       misho    1982: }

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