Annotation of embedaddon/dnsmasq/src/auth.c, revision 1.1.1.1

1.1       misho       1: /* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
                      2: 
                      3:    This program is free software; you can redistribute it and/or modify
                      4:    it under the terms of the GNU General Public License as published by
                      5:    the Free Software Foundation; version 2 dated June, 1991, or
                      6:    (at your option) version 3 dated 29 June, 2007.
                      7:  
                      8:    This program is distributed in the hope that it will be useful,
                      9:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     10:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     11:    GNU General Public License for more details.
                     12:      
                     13:    You should have received a copy of the GNU General Public License
                     14:    along with this program.  If not, see <http://www.gnu.org/licenses/>.
                     15: */
                     16: 
                     17: #include "dnsmasq.h"
                     18: 
                     19: #ifdef HAVE_AUTH
                     20: 
                     21: static struct subnet *filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
                     22: {
                     23:   struct subnet *subnet;
                     24: 
                     25:   for (subnet = zone->subnet; subnet; subnet = subnet->next)
                     26:     {
                     27:       if (subnet->is6 && (flag & F_IPV4))
                     28:        continue;
                     29: 
                     30:       if (!subnet->is6)
                     31:        {
                     32:          struct in_addr addr = addr_u->addr.addr4;
                     33:          struct in_addr mask;
                     34:          
                     35:          mask.s_addr = htonl(~((1 << (32 - subnet->prefixlen)) - 1));
                     36:          
                     37:          if  (is_same_net(addr, subnet->addr4, mask))
                     38:            return subnet;
                     39:        }
                     40: #ifdef HAVE_IPV6
                     41:       else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr6, subnet->prefixlen))
                     42:        return subnet;
                     43: #endif
                     44: 
                     45:     }
                     46:   return NULL;
                     47: }
                     48: 
                     49: static int filter_constructed_dhcp(struct auth_zone *zone, int flag, struct all_addr *addr_u)
                     50: {
                     51: #ifdef HAVE_DHCP6
                     52:   struct dhcp_context *context;
                     53: 
                     54:   if (flag & F_IPV6)
                     55:     for (context = daemon->dhcp6; context; context = context->next)
                     56:       if ((context->flags & CONTEXT_CONSTRUCTED) &&
                     57:          is_same_net6(&(addr_u->addr.addr6), &context->start6, context->prefix))
                     58:        return 1;
                     59: #endif
                     60:   
                     61:   return filter_zone(zone, flag, addr_u) != NULL;
                     62: }
                     63: 
                     64: static int in_zone(struct auth_zone *zone, char *name, char **cut)
                     65: {
                     66:   size_t namelen = strlen(name);
                     67:   size_t domainlen = strlen(zone->domain);
                     68: 
                     69:   if (cut)
                     70:     *cut = NULL;
                     71:   
                     72:   if (namelen >= domainlen && 
                     73:       hostname_isequal(zone->domain, &name[namelen - domainlen]))
                     74:     {
                     75:       
                     76:       if (namelen == domainlen)
                     77:        return 1;
                     78:       
                     79:       if (name[namelen - domainlen - 1] == '.')
                     80:        {
                     81:          if (cut)
                     82:            *cut = &name[namelen - domainlen - 1]; 
                     83:          return 1;
                     84:        }
                     85:     }
                     86: 
                     87:   return 0;
                     88: }
                     89: 
                     90: 
                     91: size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr) 
                     92: {
                     93:   char *name = daemon->namebuff;
                     94:   unsigned char *p, *ansp;
                     95:   int qtype, qclass;
                     96:   int nameoffset, axfroffset = 0;
                     97:   int q, anscount = 0, authcount = 0;
                     98:   struct crec *crecp;
                     99:   int  auth = 1, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0;
                    100:   struct auth_zone *zone = NULL;
                    101:   struct subnet *subnet = NULL;
                    102:   char *cut;
                    103:   struct mx_srv_record *rec, *move, **up;
                    104:   struct txt_record *txt;
                    105:   struct interface_name *intr;
                    106:   struct naptr *na;
                    107:   struct all_addr addr;
                    108:   struct cname *a;
                    109:   
                    110:   if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
                    111:     return 0;
                    112:   
                    113:   /* determine end of question section (we put answers there) */
                    114:   if (!(ansp = skip_questions(header, qlen)))
                    115:     return 0; /* bad packet */
                    116:   
                    117:   /* now process each question, answers go in RRs after the question */
                    118:   p = (unsigned char *)(header+1);
                    119: 
                    120:   for (q = ntohs(header->qdcount); q != 0; q--)
                    121:     {
                    122:       unsigned short flag = 0;
                    123:       int found = 0;
                    124:   
                    125:       /* save pointer to name for copying into answers */
                    126:       nameoffset = p - (unsigned char *)header;
                    127: 
                    128:       /* now extract name as .-concatenated string into name */
                    129:       if (!extract_name(header, qlen, &p, name, 1, 4))
                    130:        return 0; /* bad packet */
                    131:  
                    132:       GETSHORT(qtype, p); 
                    133:       GETSHORT(qclass, p);
                    134:       
                    135:       if (qclass != C_IN)
                    136:        {
                    137:          auth = 0;
                    138:          continue;
                    139:        }
                    140: 
                    141:       if (qtype == T_PTR)
                    142:        {
                    143:          if (!(flag = in_arpa_name_2_addr(name, &addr)))
                    144:            continue;
                    145: 
                    146:          for (zone = daemon->auth_zones; zone; zone = zone->next)
                    147:            if ((subnet = filter_zone(zone, flag, &addr)))
                    148:              break;
                    149: 
                    150:          if (!zone)
                    151:            {
                    152:              auth = 0;
                    153:              continue;
                    154:            }
                    155:          
                    156:          if (flag == F_IPV4)
                    157:            {
                    158:              for (intr = daemon->int_names; intr; intr = intr->next)
                    159:                {
                    160:                  if (addr.addr.addr4.s_addr == get_ifaddr(intr->intr).s_addr)
                    161:                    break;
                    162:                  else
                    163:                    while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
                    164:                      intr = intr->next;
                    165:                }
                    166: 
                    167:              if (intr)
                    168:                {
                    169:                  if (in_zone(zone, intr->name, NULL))
                    170:                    {   
                    171:                      found = 1;
                    172:                      log_query(F_IPV4 | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
                    173:                      if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                    174:                                              daemon->auth_ttl, NULL,
                    175:                                              T_PTR, C_IN, "d", intr->name))
                    176:                        anscount++;
                    177:                    }
                    178:                }
                    179:            }
                    180: 
                    181:          if ((crecp = cache_find_by_addr(NULL, &addr, now, flag)))
                    182:            do { 
                    183:              strcpy(name, cache_get_name(crecp));
                    184:              
                    185:              if (crecp->flags & F_DHCP && !option_bool(OPT_DHCP_FQDN))
                    186:                {
                    187:                  char *p = strchr(name, '.');
                    188:                  if (p)
                    189:                    *p = 0; /* must be bare name */
                    190:                  
                    191:                  /* add  external domain */
                    192:                  strcat(name, ".");
                    193:                  strcat(name, zone->domain);
                    194:                  log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid));
                    195:                  found = 1;
                    196:                  if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                    197:                                          daemon->auth_ttl, NULL,
                    198:                                          T_PTR, C_IN, "d", name))
                    199:                    anscount++;
                    200:                }
                    201:              else if (crecp->flags & (F_DHCP | F_HOSTS) && in_zone(zone, name, NULL))
                    202:                {
                    203:                  log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
                    204:                  found = 1;
                    205:                  if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                    206:                                          daemon->auth_ttl, NULL,
                    207:                                          T_PTR, C_IN, "d", name))
                    208:                    anscount++;
                    209:                }
                    210:              else
                    211:                continue;
                    212:                    
                    213:            } while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
                    214: 
                    215:          if (!found)
                    216:            log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | F_AUTH, NULL, &addr, NULL);
                    217: 
                    218:          continue;
                    219:        }
                    220:       
                    221:     cname_restart:
                    222:       for (zone = daemon->auth_zones; zone; zone = zone->next)
                    223:        if (in_zone(zone, name, &cut))
                    224:          break;
                    225:       
                    226:       if (!zone)
                    227:        {
                    228:          auth = 0;
                    229:          continue;
                    230:        }
                    231: 
                    232:       for (rec = daemon->mxnames; rec; rec = rec->next)
                    233:        if (!rec->issrv && hostname_isequal(name, rec->name))
                    234:          {
                    235:            nxdomain = 0;
                    236:                 
                    237:            if (qtype == T_MX)
                    238:              {
                    239:                found = 1;
                    240:                log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>"); 
                    241:                if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
                    242:                                        NULL, T_MX, C_IN, "sd", rec->weight, rec->target))
                    243:                  anscount++;
                    244:              }
                    245:          }
                    246:       
                    247:       for (move = NULL, up = &daemon->mxnames, rec = daemon->mxnames; rec; rec = rec->next)
                    248:        if (rec->issrv && hostname_isequal(name, rec->name))
                    249:          {
                    250:            nxdomain = 0;
                    251:            
                    252:            if (qtype == T_SRV)
                    253:              {
                    254:                found = 1;
                    255:                log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>"); 
                    256:                if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
                    257:                                        NULL, T_SRV, C_IN, "sssd", 
                    258:                                        rec->priority, rec->weight, rec->srvport, rec->target))
                    259: 
                    260:                  anscount++;
                    261:              } 
                    262:            
                    263:            /* unlink first SRV record found */
                    264:            if (!move)
                    265:              {
                    266:                move = rec;
                    267:                *up = rec->next;
                    268:              }
                    269:            else
                    270:              up = &rec->next;      
                    271:          }
                    272:        else
                    273:          up = &rec->next;
                    274:          
                    275:       /* put first SRV record back at the end. */
                    276:       if (move)
                    277:        {
                    278:          *up = move;
                    279:          move->next = NULL;
                    280:        }
                    281: 
                    282:       for (txt = daemon->rr; txt; txt = txt->next)
                    283:        if (hostname_isequal(name, txt->name))
                    284:          {
                    285:            nxdomain = 0;
                    286:            if (txt->class == qtype)
                    287:              {
                    288:                found = 1;
                    289:                log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>"); 
                    290:                if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
                    291:                                        NULL, txt->class, C_IN, "t", txt->len, txt->txt))
                    292:                  anscount++;
                    293:              }
                    294:          }
                    295:       
                    296:       for (txt = daemon->txt; txt; txt = txt->next)
                    297:        if (txt->class == C_IN && hostname_isequal(name, txt->name))
                    298:          {
                    299:            nxdomain = 0;
                    300:            if (qtype == T_TXT)
                    301:              {
                    302:                found = 1;
                    303:                log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>"); 
                    304:                if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
                    305:                                        NULL, T_TXT, C_IN, "t", txt->len, txt->txt))
                    306:                  anscount++;
                    307:              }
                    308:          }
                    309: 
                    310:        for (na = daemon->naptr; na; na = na->next)
                    311:         if (hostname_isequal(name, na->name))
                    312:           {
                    313:             nxdomain = 0;
                    314:             if (qtype == T_NAPTR)
                    315:               {
                    316:                 found = 1;
                    317:                 log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
                    318:                 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl, 
                    319:                                         NULL, T_NAPTR, C_IN, "sszzzd", 
                    320:                                         na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
                    321:                          anscount++;
                    322:               }
                    323:           }
                    324: 
                    325: 
                    326:        for (intr = daemon->int_names; intr; intr = intr->next)
                    327:         if (hostname_isequal(name, intr->name))
                    328:           {
                    329:             nxdomain = 0;
                    330:             if (qtype == T_A && (addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr != (in_addr_t) -1)
                    331:               {
                    332:                 found = 1;
                    333:                 log_query(F_FORWARD | F_CONFIG | F_IPV4, name, &addr, NULL);
                    334:                 if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                    335:                                         daemon->auth_ttl, NULL, T_A, C_IN, "4", &addr))
                    336:                   anscount++;
                    337:               }
                    338:           }
                    339:        
                    340:        for (a = daemon->cnames; a; a = a->next)
                    341:         if (hostname_isequal(name, a->alias) )
                    342:           {
                    343:             log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
                    344:             strcpy(name, a->target);
                    345:             if (!strchr(name, '.'))
                    346:               {
                    347:                 strcat(name, ".");
                    348:                 strcat(name, zone->domain);
                    349:               }
                    350:             found = 1;
                    351:             if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                    352:                                     daemon->auth_ttl, NULL,
                    353:                                     T_CNAME, C_IN, "d", name))
                    354:               anscount++;
                    355:             
                    356:             goto cname_restart;
                    357:           }
                    358: 
                    359:       if (qtype == T_A)
                    360:        flag = F_IPV4;
                    361: 
                    362: #ifdef HAVE_IPV6
                    363:       if (qtype == T_AAAA)
                    364:        flag = F_IPV6;
                    365: #endif
                    366: 
                    367:       if (!cut)
                    368:        {
                    369:          nxdomain = 0;
                    370:          
                    371:          if (qtype == T_SOA)
                    372:            {
                    373:              soa = 1; /* inhibits auth section */
                    374:              found = 1;
                    375:              log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>");
                    376:            }
                    377:          else if (qtype == T_AXFR)
                    378:            {
                    379:              struct iname *peers;
                    380:              
                    381:              if (peer_addr->sa.sa_family == AF_INET)
                    382:                peer_addr->in.sin_port = 0;
                    383: #ifdef HAVE_IPV6
                    384:              else
                    385:                peer_addr->in6.sin6_port = 0; 
                    386: #endif
                    387:              
                    388:              for (peers = daemon->auth_peers; peers; peers = peers->next)
                    389:                if (sockaddr_isequal(peer_addr, &peers->addr))
                    390:                  break;
                    391:              
                    392:              /* Refuse all AXFR unless --auth-sec-servers is set */
                    393:              if ((!peers && daemon->auth_peers) || !daemon->secondary_forward_server)
                    394:                {
                    395:                  if (peer_addr->sa.sa_family == AF_INET)
                    396:                    inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
                    397: #ifdef HAVE_IPV6
                    398:                  else
                    399:                    inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN); 
                    400: #endif
                    401:                  
                    402:                  my_syslog(LOG_WARNING, _("ignoring zone transfer request from %s"), daemon->addrbuff);
                    403:                  return 0;
                    404:                }
                    405:                      
                    406:              soa = 1; /* inhibits auth section */
                    407:              ns = 1; /* ensure we include NS records! */
                    408:              axfr = 1;
                    409:              found = 1;
                    410:              axfroffset = nameoffset;
                    411:              log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>");
                    412:            }
                    413:          else if (qtype == T_NS)
                    414:            {
                    415:              ns = 1; /* inhibits auth section */
                    416:              found = 1;
                    417:              log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>"); 
                    418:            }
                    419:        }
                    420:       
                    421:       if (!option_bool(OPT_DHCP_FQDN) && cut)
                    422:        {         
                    423:          *cut = 0; /* remove domain part */
                    424:          
                    425:          if (!strchr(name, '.') && (crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)))
                    426:            {
                    427:              if (crecp->flags & F_DHCP)
                    428:                do
                    429:                  { 
                    430:                    nxdomain = 0;
                    431:                    if ((crecp->flags & flag) && 
                    432:                        (filter_constructed_dhcp(zone, flag, &(crecp->addr.addr))))
                    433:                      {
                    434:                        *cut = '.'; /* restore domain part */
                    435:                        log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
                    436:                        *cut  = 0; /* remove domain part */
                    437:                        found = 1;
                    438:                        if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                    439:                                                daemon->auth_ttl, NULL, qtype, C_IN, 
                    440:                                                qtype == T_A ? "4" : "6", &crecp->addr))
                    441:                          anscount++;
                    442:                      }
                    443:                  } while ((crecp = cache_find_by_name(crecp, name, now,  F_IPV4 | F_IPV6)));
                    444:            }
                    445:                  
                    446:          *cut = '.'; /* restore domain part */     
                    447:        }
                    448:       
                    449:       if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6)))
                    450:        {
                    451:          if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
                    452:            do
                    453:              { 
                    454:                 nxdomain = 0;
                    455:                 if ((crecp->flags & flag) && filter_constructed_dhcp(zone, flag, &(crecp->addr.addr)))
                    456:                   {
                    457:                     log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
                    458:                     found = 1;
                    459:                     if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
                    460:                                             daemon->auth_ttl, NULL, qtype, C_IN, 
                    461:                                             qtype == T_A ? "4" : "6", &crecp->addr))
                    462:                       anscount++;
                    463:                   }
                    464:              } while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
                    465:        }
                    466:       
                    467:       if (!found)
                    468:        log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
                    469:       
                    470:     }
                    471:   
                    472:   /* Add auth section */
                    473:   if (auth && zone)
                    474:     {
                    475:       char *authname;
                    476:       int newoffset, offset = 0;
                    477: 
                    478:       if (!subnet)
                    479:        authname = zone->domain;
                    480:       else
                    481:        {
                    482:          /* handle NS and SOA for PTR records */
                    483:          
                    484:          authname = name;
                    485: 
                    486:          if (!subnet->is6)
                    487:            {
                    488:              in_addr_t a = ntohl(subnet->addr4.s_addr) >> 8;
                    489:              char *p = name;
                    490:              
                    491:              if (subnet->prefixlen == 24)
                    492:                p += sprintf(p, "%d.", a & 0xff);
                    493:              a = a >> 8;
                    494:              if (subnet->prefixlen != 8)
                    495:                p += sprintf(p, "%d.", a & 0xff);
                    496:              a = a >> 8;
                    497:              p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
                    498:              
                    499:            }
                    500: #ifdef HAVE_IPV6
                    501:          else
                    502:            {
                    503:              char *p = name;
                    504:              int i;
                    505:              
                    506:              for (i = subnet->prefixlen-1; i >= 0; i -= 4)
                    507:                { 
                    508:                  int dig = ((unsigned char *)&subnet->addr6)[i>>3];
                    509:                  p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
                    510:                }
                    511:              p += sprintf(p, "ip6.arpa");
                    512:              
                    513:            }
                    514: #endif
                    515:        }
                    516:       
                    517:       /* handle NS and SOA in auth section or for explicit queries */
                    518:        newoffset = ansp - (unsigned char *)header;
                    519:        if (((anscount == 0 && !ns) || soa) &&
                    520:          add_resource_record(header, limit, &trunc, 0, &ansp, 
                    521:                              daemon->auth_ttl, NULL, T_SOA, C_IN, "ddlllll",
                    522:                              authname, daemon->authserver,  daemon->hostmaster,
                    523:                              daemon->soa_sn, daemon->soa_refresh, 
                    524:                              daemon->soa_retry, daemon->soa_expiry, 
                    525:                              daemon->auth_ttl))
                    526:        {
                    527:          offset = newoffset;
                    528:          if (soa)
                    529:            anscount++;
                    530:          else
                    531:            authcount++;
                    532:        }
                    533:       
                    534:       if (anscount != 0 || ns)
                    535:        {
                    536:          struct name_list *secondary;
                    537:          
                    538:          newoffset = ansp - (unsigned char *)header;
                    539:          if (add_resource_record(header, limit, &trunc, -offset, &ansp, 
                    540:                                  daemon->auth_ttl, NULL, T_NS, C_IN, "d", offset == 0 ? authname : NULL, daemon->authserver))
                    541:            {
                    542:              if (offset == 0) 
                    543:                offset = newoffset;
                    544:              if (ns) 
                    545:                anscount++;
                    546:              else
                    547:                authcount++;
                    548:            }
                    549: 
                    550:          if (!subnet)
                    551:            for (secondary = daemon->secondary_forward_server; secondary; secondary = secondary->next)
                    552:              if (add_resource_record(header, limit, &trunc, offset, &ansp, 
                    553:                                      daemon->auth_ttl, NULL, T_NS, C_IN, "d", secondary->name))
                    554:                {
                    555:                  if (ns) 
                    556:                    anscount++;
                    557:                  else
                    558:                    authcount++;
                    559:                }
                    560:        }
                    561:       
                    562:       if (axfr)
                    563:        {
                    564:          for (rec = daemon->mxnames; rec; rec = rec->next)
                    565:            if (in_zone(zone, rec->name, &cut))
                    566:              {
                    567:                if (cut)
                    568:                   *cut = 0;
                    569: 
                    570:                if (rec->issrv)
                    571:                  {
                    572:                    if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
                    573:                                            NULL, T_SRV, C_IN, "sssd", cut ? rec->name : NULL,
                    574:                                            rec->priority, rec->weight, rec->srvport, rec->target))
                    575:                      
                    576:                      anscount++;
                    577:                  }
                    578:                else
                    579:                  {
                    580:                    if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
                    581:                                            NULL, T_MX, C_IN, "sd", cut ? rec->name : NULL, rec->weight, rec->target))
                    582:                      anscount++;
                    583:                  }
                    584:                
                    585:                /* restore config data */
                    586:                if (cut)
                    587:                  *cut = '.';
                    588:              }
                    589:              
                    590:          for (txt = daemon->rr; txt; txt = txt->next)
                    591:            if (in_zone(zone, txt->name, &cut))
                    592:              {
                    593:                if (cut)
                    594:                  *cut = 0;
                    595:                
                    596:                if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
                    597:                                        NULL, txt->class, C_IN, "t",  cut ? txt->name : NULL, txt->len, txt->txt))
                    598:                  anscount++;
                    599:                
                    600:                /* restore config data */
                    601:                if (cut)
                    602:                  *cut = '.';
                    603:              }
                    604:          
                    605:          for (txt = daemon->txt; txt; txt = txt->next)
                    606:            if (txt->class == C_IN && in_zone(zone, txt->name, &cut))
                    607:              {
                    608:                if (cut)
                    609:                  *cut = 0;
                    610:                
                    611:                if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl,
                    612:                                        NULL, T_TXT, C_IN, "t", cut ? txt->name : NULL, txt->len, txt->txt))
                    613:                  anscount++;
                    614:                
                    615:                /* restore config data */
                    616:                if (cut)
                    617:                  *cut = '.';
                    618:              }
                    619:          
                    620:          for (na = daemon->naptr; na; na = na->next)
                    621:            if (in_zone(zone, na->name, &cut))
                    622:              {
                    623:                if (cut)
                    624:                  *cut = 0;
                    625:                
                    626:                if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, daemon->auth_ttl, 
                    627:                                        NULL, T_NAPTR, C_IN, "sszzzd", cut ? na->name : NULL,
                    628:                                        na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
                    629:                  anscount++;
                    630:                
                    631:                /* restore config data */
                    632:                if (cut)
                    633:                  *cut = '.'; 
                    634:              }
                    635:          
                    636:          for (intr = daemon->int_names; intr; intr = intr->next)
                    637:            if (in_zone(zone, intr->name, &cut) && (addr.addr.addr4 = get_ifaddr(intr->intr)).s_addr != (in_addr_t) -1)
                    638:              {
                    639:                if (cut)
                    640:                  *cut = 0;
                    641:                
                    642:                if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, 
                    643:                                        daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addr))
                    644:                  anscount++;
                    645:                
                    646:                /* restore config data */
                    647:                if (cut)
                    648:                  *cut = '.'; 
                    649:              }
                    650:          
                    651:          for (a = daemon->cnames; a; a = a->next)
                    652:            if (in_zone(zone, a->alias, &cut))
                    653:              {
                    654:                strcpy(name, a->target);
                    655:                if (!strchr(name, '.'))
                    656:                  {
                    657:                    strcat(name, ".");
                    658:                    strcat(name, zone->domain);
                    659:                  }
                    660:                
                    661:                if (cut)
                    662:                  *cut = 0;
                    663:                
                    664:                if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, 
                    665:                                        daemon->auth_ttl, NULL,
                    666:                                        T_CNAME, C_IN, "d",  cut ? a->alias : NULL, name))
                    667:                  anscount++;
                    668:              }
                    669:        
                    670:          cache_enumerate(1);
                    671:          while ((crecp = cache_enumerate(0)))
                    672:            {
                    673:              if ((crecp->flags & (F_IPV4 | F_IPV6)) &&
                    674:                  !(crecp->flags & (F_NEG | F_NXDOMAIN)) &&
                    675:                  (crecp->flags & F_FORWARD))
                    676:                {
                    677:                  if ((crecp->flags & F_DHCP) && !option_bool(OPT_DHCP_FQDN))
                    678:                    {
                    679:                      char *cache_name = cache_get_name(crecp);
                    680:                      if (!strchr(cache_name, '.') && filter_constructed_dhcp(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr)))
                    681:                        {
                    682:                          qtype = T_A;
                    683: #ifdef HAVE_IPV6
                    684:                          if (crecp->flags & F_IPV6)
                    685:                            qtype = T_AAAA;
                    686: #endif
                    687:                          if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, 
                    688:                                                  daemon->auth_ttl, NULL, qtype, C_IN, 
                    689:                                                  (crecp->flags & F_IPV4) ? "4" : "6", cache_name, &crecp->addr))
                    690:                            anscount++;
                    691:                        }
                    692:                    }
                    693:                  
                    694:                  if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
                    695:                    {
                    696:                      strcpy(name, cache_get_name(crecp));
                    697:                      if (in_zone(zone, name, &cut) && filter_constructed_dhcp(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr)))
                    698:                        {
                    699:                          qtype = T_A;
                    700: #ifdef HAVE_IPV6
                    701:                          if (crecp->flags & F_IPV6)
                    702:                            qtype = T_AAAA;
                    703: #endif
                    704:                           if (cut)
                    705:                             *cut = 0;
                    706: 
                    707:                           if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp, 
                    708:                                                   daemon->auth_ttl, NULL, qtype, C_IN, 
                    709:                                                   (crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr))
                    710:                             anscount++;
                    711:                        }
                    712:                    }
                    713:                }
                    714:            }
                    715:           
                    716:          /* repeat SOA as last record */
                    717:          if (add_resource_record(header, limit, &trunc, axfroffset, &ansp, 
                    718:                                  daemon->auth_ttl, NULL, T_SOA, C_IN, "ddlllll",
                    719:                                  daemon->authserver,  daemon->hostmaster,
                    720:                                  daemon->soa_sn, daemon->soa_refresh, 
                    721:                                  daemon->soa_retry, daemon->soa_expiry, 
                    722:                                  daemon->auth_ttl))
                    723:            anscount++;
                    724:          
                    725:        }
                    726:       
                    727:     }
                    728:   
                    729:   /* done all questions, set up header and return length of result */
                    730:   /* clear authoritative and truncated flags, set QR flag */
                    731:   header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
                    732:   /* clear RA flag */
                    733:   header->hb4 &= ~HB4_RA;
                    734: 
                    735:   /* authoritive */
                    736:   if (auth)
                    737:     header->hb3 |= HB3_AA;
                    738:   
                    739:   /* truncation */
                    740:   if (trunc)
                    741:     header->hb3 |= HB3_TC;
                    742:   
                    743:   if (anscount == 0 && auth && nxdomain)
                    744:     SET_RCODE(header, NXDOMAIN);
                    745:   else
                    746:     SET_RCODE(header, NOERROR); /* no error */
                    747:   header->ancount = htons(anscount);
                    748:   header->nscount = htons(authcount);
                    749:   header->arcount = htons(0);
                    750:   return ansp - (unsigned char *)header;
                    751: }
                    752:   
                    753: #endif  
                    754:   
                    755: 
                    756: 

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