File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / auth.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 29 19:37:40 2013 UTC (11 years ago) by misho
Branches: elwix, dnsmasq, MAIN
CVS tags: v2_66p0, v2_66, HEAD
dnsmasq

    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>