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

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

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