File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / auth.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 16:31:38 2014 UTC (10 years, 2 months ago) by misho
Branches: elwix, dnsmasq, MAIN
CVS tags: v2_71, HEAD
dnsmasq 2.71

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

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