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

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

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