Annotation of embedaddon/dnsmasq/src/auth.c, revision 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>