File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / forward.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: static struct frec *lookup_frec(unsigned short id, unsigned int crc);
   20: static struct frec *lookup_frec_by_sender(unsigned short id,
   21: 					  union mysockaddr *addr,
   22: 					  unsigned int crc);
   23: static unsigned short get_id(unsigned int crc);
   24: static void free_frec(struct frec *f);
   25: static struct randfd *allocate_rfd(int family);
   26: 
   27: /* Send a UDP packet with its source address set as "source" 
   28:    unless nowild is true, when we just send it with the kernel default */
   29: int send_from(int fd, int nowild, char *packet, size_t len, 
   30: 	      union mysockaddr *to, struct all_addr *source,
   31: 	      unsigned int iface)
   32: {
   33:   struct msghdr msg;
   34:   struct iovec iov[1]; 
   35:   union {
   36:     struct cmsghdr align; /* this ensures alignment */
   37: #if defined(HAVE_LINUX_NETWORK)
   38:     char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
   39: #elif defined(IP_SENDSRCADDR)
   40:     char control[CMSG_SPACE(sizeof(struct in_addr))];
   41: #endif
   42: #ifdef HAVE_IPV6
   43:     char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
   44: #endif
   45:   } control_u;
   46:   
   47:   iov[0].iov_base = packet;
   48:   iov[0].iov_len = len;
   49: 
   50:   msg.msg_control = NULL;
   51:   msg.msg_controllen = 0;
   52:   msg.msg_flags = 0;
   53:   msg.msg_name = to;
   54:   msg.msg_namelen = sa_len(to);
   55:   msg.msg_iov = iov;
   56:   msg.msg_iovlen = 1;
   57:   
   58:   if (!nowild)
   59:     {
   60:       struct cmsghdr *cmptr;
   61:       msg.msg_control = &control_u;
   62:       msg.msg_controllen = sizeof(control_u);
   63:       cmptr = CMSG_FIRSTHDR(&msg);
   64: 
   65:       if (to->sa.sa_family == AF_INET)
   66: 	{
   67: #if defined(HAVE_LINUX_NETWORK)
   68: 	  struct in_pktinfo p;
   69: 	  p.ipi_ifindex = 0;
   70: 	  p.ipi_spec_dst = source->addr.addr4;
   71: 	  memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
   72: 	  msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
   73: 	  cmptr->cmsg_level = IPPROTO_IP;
   74: 	  cmptr->cmsg_type = IP_PKTINFO;
   75: #elif defined(IP_SENDSRCADDR)
   76: 	  memcpy(CMSG_DATA(cmptr), &(source->addr.addr4), sizeof(source->addr.addr4));
   77: 	  msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
   78: 	  cmptr->cmsg_level = IPPROTO_IP;
   79: 	  cmptr->cmsg_type = IP_SENDSRCADDR;
   80: #endif
   81: 	}
   82:       else
   83: #ifdef HAVE_IPV6
   84: 	{
   85: 	  struct in6_pktinfo p;
   86: 	  p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
   87: 	  p.ipi6_addr = source->addr.addr6;
   88: 	  memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
   89: 	  msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
   90: 	  cmptr->cmsg_type = daemon->v6pktinfo;
   91: 	  cmptr->cmsg_level = IPPROTO_IPV6;
   92: 	}
   93: #else
   94:       (void)iface; /* eliminate warning */
   95: #endif
   96:     }
   97:   
   98:   while (sendmsg(fd, &msg, 0) == -1)
   99:     {
  100:       if (retry_send())
  101: 	continue;
  102:       
  103:       /* If interface is still in DAD, EINVAL results - ignore that. */
  104:       if (errno == EINVAL)
  105: 	break;
  106:       
  107:       my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
  108:       return 0;
  109:     }
  110:   
  111:   return 1;
  112: }
  113:           
  114: static unsigned int search_servers(time_t now, struct all_addr **addrpp, 
  115: 				     unsigned int qtype, char *qdomain, int *type, char **domain, int *norebind)
  116: 			      
  117: {
  118:   /* If the query ends in the domain in one of our servers, set
  119:      domain to point to that name. We find the largest match to allow both
  120:      domain.org and sub.domain.org to exist. */
  121:   
  122:   unsigned int namelen = strlen(qdomain);
  123:   unsigned int matchlen = 0;
  124:   struct server *serv;
  125:   unsigned int flags = 0;
  126:   
  127:   for (serv = daemon->servers; serv; serv=serv->next)
  128:     /* domain matches take priority over NODOTS matches */
  129:     if ((serv->flags & SERV_FOR_NODOTS) && *type != SERV_HAS_DOMAIN && !strchr(qdomain, '.') && namelen != 0)
  130:       {
  131: 	unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6; 
  132: 	*type = SERV_FOR_NODOTS;
  133: 	if (serv->flags & SERV_NO_ADDR)
  134: 	  flags = F_NXDOMAIN;
  135: 	else if (serv->flags & SERV_LITERAL_ADDRESS) 
  136: 	  { 
  137: 	    if (sflag & qtype)
  138: 	      {
  139: 		flags = sflag;
  140: 		if (serv->addr.sa.sa_family == AF_INET) 
  141: 		  *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
  142: #ifdef HAVE_IPV6
  143: 		else
  144: 		  *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
  145: #endif 
  146: 	      }
  147: 	    else if (!flags || (flags & F_NXDOMAIN))
  148: 	      flags = F_NOERR;
  149: 	  } 
  150:       }
  151:     else if (serv->flags & SERV_HAS_DOMAIN)
  152:       {
  153: 	unsigned int domainlen = strlen(serv->domain);
  154: 	char *matchstart = qdomain + namelen - domainlen;
  155: 	if (namelen >= domainlen &&
  156: 	    hostname_isequal(matchstart, serv->domain) &&
  157: 	    (domainlen == 0 || namelen == domainlen || *(matchstart-1) == '.' ))
  158: 	  {
  159: 	    if (serv->flags & SERV_NO_REBIND)	
  160: 	      *norebind = 1;
  161: 	    else
  162: 	      {
  163: 		unsigned int sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6;
  164: 		/* implement priority rules for --address and --server for same domain.
  165: 		   --address wins if the address is for the correct AF
  166: 		   --server wins otherwise. */
  167: 		if (domainlen != 0 && domainlen == matchlen)
  168: 		  {
  169: 		    if ((serv->flags & SERV_LITERAL_ADDRESS))
  170: 		      {
  171: 			if (!(sflag & qtype) && flags == 0)
  172: 			  continue;
  173: 		      }
  174: 		    else
  175: 		      {
  176: 			if (flags & (F_IPV4 | F_IPV6))
  177: 			  continue;
  178: 		      }
  179: 		  }
  180: 		
  181: 		if (domainlen >= matchlen)
  182: 		  {
  183: 		    *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND);
  184: 		    *domain = serv->domain;
  185: 		    matchlen = domainlen;
  186: 		    if (serv->flags & SERV_NO_ADDR)
  187: 		      flags = F_NXDOMAIN;
  188: 		    else if (serv->flags & SERV_LITERAL_ADDRESS)
  189: 		      {
  190: 			if (sflag & qtype)
  191: 			  {
  192: 			    flags = sflag;
  193: 			    if (serv->addr.sa.sa_family == AF_INET) 
  194: 			      *addrpp = (struct all_addr *)&serv->addr.in.sin_addr;
  195: #ifdef HAVE_IPV6
  196: 			    else
  197: 			      *addrpp = (struct all_addr *)&serv->addr.in6.sin6_addr;
  198: #endif
  199: 			  }
  200: 			else if (!flags || (flags & F_NXDOMAIN))
  201: 			  flags = F_NOERR;
  202: 		      }
  203: 		    else
  204: 		      flags = 0;
  205: 		  } 
  206: 	      }
  207: 	  }
  208:       }
  209:   
  210:   if (flags == 0 && !(qtype & F_QUERY) && 
  211:       option_bool(OPT_NODOTS_LOCAL) && !strchr(qdomain, '.') && namelen != 0)
  212:     /* don't forward A or AAAA queries for simple names, except the empty name */
  213:     flags = F_NOERR;
  214:   
  215:   if (flags == F_NXDOMAIN && check_for_local_domain(qdomain, now))
  216:     flags = F_NOERR;
  217: 
  218:   if (flags)
  219:     {
  220:       int logflags = 0;
  221:       
  222:       if (flags == F_NXDOMAIN || flags == F_NOERR)
  223: 	logflags = F_NEG | qtype;
  224:   
  225:       log_query(logflags | flags | F_CONFIG | F_FORWARD, qdomain, *addrpp, NULL);
  226:     }
  227:   else if ((*type) & SERV_USE_RESOLV)
  228:     {
  229:       *type = 0; /* use normal servers for this domain */
  230:       *domain = NULL;
  231:     }
  232:   return  flags;
  233: }
  234: 
  235: static int forward_query(int udpfd, union mysockaddr *udpaddr,
  236: 			 struct all_addr *dst_addr, unsigned int dst_iface,
  237: 			 struct dns_header *header, size_t plen, time_t now, struct frec *forward)
  238: {
  239:   char *domain = NULL;
  240:   int type = 0, norebind = 0;
  241:   struct all_addr *addrp = NULL;
  242:   unsigned int crc = questions_crc(header, plen, daemon->namebuff);
  243:   unsigned int flags = 0;
  244:   unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
  245:   struct server *start = NULL;
  246:   
  247:   /* RFC 4035: sect 4.6 para 2 */
  248:   header->hb4 &= ~HB4_AD;
  249:   
  250:   /* may be no servers available. */
  251:   if (!daemon->servers)
  252:     forward = NULL;
  253:   else if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, crc)))
  254:     {
  255:       /* retry on existing query, send to all available servers  */
  256:       domain = forward->sentto->domain;
  257:       forward->sentto->failed_queries++;
  258:       if (!option_bool(OPT_ORDER))
  259: 	{
  260: 	  forward->forwardall = 1;
  261: 	  daemon->last_server = NULL;
  262: 	}
  263:       type = forward->sentto->flags & SERV_TYPE;
  264:       if (!(start = forward->sentto->next))
  265: 	start = daemon->servers; /* at end of list, recycle */
  266:       header->id = htons(forward->new_id);
  267:     }
  268:   else 
  269:     {
  270:       if (gotname)
  271: 	flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
  272:       
  273:       if (!flags && !(forward = get_new_frec(now, NULL)))
  274: 	/* table full - server failure. */
  275: 	flags = F_NEG;
  276:       
  277:       if (forward)
  278: 	{
  279: 	  forward->source = *udpaddr;
  280: 	  forward->dest = *dst_addr;
  281: 	  forward->iface = dst_iface;
  282: 	  forward->orig_id = ntohs(header->id);
  283: 	  forward->new_id = get_id(crc);
  284: 	  forward->fd = udpfd;
  285: 	  forward->crc = crc;
  286: 	  forward->forwardall = 0;
  287: 	  if (norebind)
  288: 	    forward->flags |= FREC_NOREBIND;
  289: 	  if (header->hb4 & HB4_CD)
  290: 	    forward->flags |= FREC_CHECKING_DISABLED;
  291: 
  292: 	  header->id = htons(forward->new_id);
  293: 	  
  294: 	  /* In strict_order mode, always try servers in the order 
  295: 	     specified in resolv.conf, if a domain is given 
  296: 	     always try all the available servers,
  297: 	     otherwise, use the one last known to work. */
  298: 	  
  299: 	  if (type == 0)
  300: 	    {
  301: 	      if (option_bool(OPT_ORDER))
  302: 		start = daemon->servers;
  303: 	      else if (!(start = daemon->last_server) ||
  304: 		       daemon->forwardcount++ > FORWARD_TEST ||
  305: 		       difftime(now, daemon->forwardtime) > FORWARD_TIME)
  306: 		{
  307: 		  start = daemon->servers;
  308: 		  forward->forwardall = 1;
  309: 		  daemon->forwardcount = 0;
  310: 		  daemon->forwardtime = now;
  311: 		}
  312: 	    }
  313: 	  else
  314: 	    {
  315: 	      start = daemon->servers;
  316: 	      if (!option_bool(OPT_ORDER))
  317: 		forward->forwardall = 1;
  318: 	    }
  319: 	}
  320:     }
  321: 
  322:   /* check for send errors here (no route to host) 
  323:      if we fail to send to all nameservers, send back an error
  324:      packet straight away (helps modem users when offline)  */
  325:   
  326:   if (!flags && forward)
  327:     {
  328:       struct server *firstsentto = start;
  329:       int forwarded = 0;
  330:       
  331:       if (udpaddr && option_bool(OPT_ADD_MAC))
  332: 	plen = add_mac(header, plen, ((char *) header) + PACKETSZ, udpaddr);
  333:       
  334:       while (1)
  335: 	{ 
  336: 	  /* only send to servers dealing with our domain.
  337: 	     domain may be NULL, in which case server->domain 
  338: 	     must be NULL also. */
  339: 	  
  340: 	  if (type == (start->flags & SERV_TYPE) &&
  341: 	      (type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
  342: 	      !(start->flags & SERV_LITERAL_ADDRESS))
  343: 	    {
  344: 	      int fd;
  345: 
  346: 	      /* find server socket to use, may need to get random one. */
  347: 	      if (start->sfd)
  348: 		fd = start->sfd->fd;
  349: 	      else 
  350: 		{
  351: #ifdef HAVE_IPV6
  352: 		  if (start->addr.sa.sa_family == AF_INET6)
  353: 		    {
  354: 		      if (!forward->rfd6 &&
  355: 			  !(forward->rfd6 = allocate_rfd(AF_INET6)))
  356: 			break;
  357: 		      daemon->rfd_save = forward->rfd6;
  358: 		      fd = forward->rfd6->fd;
  359: 		    }
  360: 		  else
  361: #endif
  362: 		    {
  363: 		      if (!forward->rfd4 &&
  364: 			  !(forward->rfd4 = allocate_rfd(AF_INET)))
  365: 			break;
  366: 		      daemon->rfd_save = forward->rfd4;
  367: 		      fd = forward->rfd4->fd;
  368: 		    }
  369: 
  370: #ifdef HAVE_CONNTRACK
  371: 		  /* Copy connection mark of incoming query to outgoing connection. */
  372: 		  if (option_bool(OPT_CONNTRACK))
  373: 		    {
  374: 		      unsigned int mark;
  375: 		      if (get_incoming_mark(udpaddr, dst_addr, 0, &mark))
  376: 			setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
  377: 		    }
  378: #endif
  379: 		}
  380: 	      
  381: 	      if (sendto(fd, (char *)header, plen, 0,
  382: 			 &start->addr.sa,
  383: 			 sa_len(&start->addr)) == -1)
  384: 		{
  385: 		  if (retry_send())
  386: 		    continue;
  387: 		}
  388: 	      else
  389: 		{
  390: 		  /* Keep info in case we want to re-send this packet */
  391: 		  daemon->srv_save = start;
  392: 		  daemon->packet_len = plen;
  393: 		  
  394: 		  if (!gotname)
  395: 		    strcpy(daemon->namebuff, "query");
  396: 		  if (start->addr.sa.sa_family == AF_INET)
  397: 		    log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, 
  398: 			      (struct all_addr *)&start->addr.in.sin_addr, NULL); 
  399: #ifdef HAVE_IPV6
  400: 		  else
  401: 		    log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, 
  402: 			      (struct all_addr *)&start->addr.in6.sin6_addr, NULL);
  403: #endif 
  404: 		  start->queries++;
  405: 		  forwarded = 1;
  406: 		  forward->sentto = start;
  407: 		  if (!forward->forwardall) 
  408: 		    break;
  409: 		  forward->forwardall++;
  410: 		}
  411: 	    } 
  412: 	  
  413: 	  if (!(start = start->next))
  414:  	    start = daemon->servers;
  415: 	  
  416: 	  if (start == firstsentto)
  417: 	    break;
  418: 	}
  419:       
  420:       if (forwarded)
  421: 	return 1;
  422:       
  423:       /* could not send on, prepare to return */ 
  424:       header->id = htons(forward->orig_id);
  425:       free_frec(forward); /* cancel */
  426:     }	  
  427:   
  428:   /* could not send on, return empty answer or address if known for whole domain */
  429:   if (udpfd != -1)
  430:     {
  431:       plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
  432:       send_from(udpfd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND), (char *)header, plen, udpaddr, dst_addr, dst_iface);
  433:     }
  434: 
  435:   return 0;
  436: }
  437: 
  438: static size_t process_reply(struct dns_header *header, time_t now, 
  439: 			    struct server *server, size_t n, int check_rebind, int checking_disabled)
  440: {
  441:   unsigned char *pheader, *sizep;
  442:   char **sets = 0;
  443:   int munged = 0, is_sign;
  444:   size_t plen; 
  445: 
  446: #ifdef HAVE_IPSET
  447:   /* Similar algorithm to search_servers. */
  448:   struct ipsets *ipset_pos;
  449:   unsigned int namelen = strlen(daemon->namebuff);
  450:   unsigned int matchlen = 0;
  451:   for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next) 
  452:     {
  453:       unsigned int domainlen = strlen(ipset_pos->domain);
  454:       char *matchstart = daemon->namebuff + namelen - domainlen;
  455:       if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
  456: 	  (domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
  457: 	  domainlen >= matchlen) {
  458: 	matchlen = domainlen;
  459: 	sets = ipset_pos->sets;
  460:       }
  461:     }
  462: #endif
  463:   
  464:   /* If upstream is advertising a larger UDP packet size
  465:      than we allow, trim it so that we don't get overlarge
  466:      requests for the client. We can't do this for signed packets. */
  467: 
  468:   if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign)) && !is_sign)
  469:     {
  470:       unsigned short udpsz;
  471:       unsigned char *psave = sizep;
  472:       
  473:       GETSHORT(udpsz, sizep);
  474:       if (udpsz > daemon->edns_pktsz)
  475: 	PUTSHORT(daemon->edns_pktsz, psave);
  476:     }
  477: 
  478:   /* RFC 4035 sect 4.6 para 3 */
  479:   if (!is_sign && !option_bool(OPT_DNSSEC))
  480:      header->hb4 &= ~HB4_AD;
  481: 
  482:   if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
  483:     return n;
  484:   
  485:   /* Complain loudly if the upstream server is non-recursive. */
  486:   if (!(header->hb4 & HB4_RA) && RCODE(header) == NOERROR && ntohs(header->ancount) == 0 &&
  487:       server && !(server->flags & SERV_WARNED_RECURSIVE))
  488:     {
  489:       prettyprint_addr(&server->addr, daemon->namebuff);
  490:       my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
  491:       if (!option_bool(OPT_LOG))
  492: 	server->flags |= SERV_WARNED_RECURSIVE;
  493:     }  
  494:     
  495:   if (daemon->bogus_addr && RCODE(header) != NXDOMAIN &&
  496:       check_for_bogus_wildcard(header, n, daemon->namebuff, daemon->bogus_addr, now))
  497:     {
  498:       munged = 1;
  499:       SET_RCODE(header, NXDOMAIN);
  500:       header->hb3 &= ~HB3_AA;
  501:     }
  502:   else 
  503:     {
  504:       if (RCODE(header) == NXDOMAIN && 
  505: 	  extract_request(header, n, daemon->namebuff, NULL) &&
  506: 	  check_for_local_domain(daemon->namebuff, now))
  507: 	{
  508: 	  /* if we forwarded a query for a locally known name (because it was for 
  509: 	     an unknown type) and the answer is NXDOMAIN, convert that to NODATA,
  510: 	     since we know that the domain exists, even if upstream doesn't */
  511: 	  munged = 1;
  512: 	  header->hb3 |= HB3_AA;
  513: 	  SET_RCODE(header, NOERROR);
  514: 	}
  515:       
  516:       if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, checking_disabled))
  517: 	{
  518: 	  my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
  519: 	  munged = 1;
  520: 	}
  521:     }
  522:   
  523:   /* do this after extract_addresses. Ensure NODATA reply and remove
  524:      nameserver info. */
  525:   
  526:   if (munged)
  527:     {
  528:       header->ancount = htons(0);
  529:       header->nscount = htons(0);
  530:       header->arcount = htons(0);
  531:     }
  532:   
  533:   /* the bogus-nxdomain stuff, doctor and NXDOMAIN->NODATA munging can all elide
  534:      sections of the packet. Find the new length here and put back pseudoheader
  535:      if it was removed. */
  536:   return resize_packet(header, n, pheader, plen);
  537: }
  538: 
  539: /* sets new last_server */
  540: void reply_query(int fd, int family, time_t now)
  541: {
  542:   /* packet from peer server, extract data for cache, and send to
  543:      original requester */
  544:   struct dns_header *header;
  545:   union mysockaddr serveraddr;
  546:   struct frec *forward;
  547:   socklen_t addrlen = sizeof(serveraddr);
  548:   ssize_t n = recvfrom(fd, daemon->packet, daemon->edns_pktsz, 0, &serveraddr.sa, &addrlen);
  549:   size_t nn;
  550:   struct server *server;
  551:   
  552:   /* packet buffer overwritten */
  553:   daemon->srv_save = NULL;
  554:   
  555:   /* Determine the address of the server replying  so that we can mark that as good */
  556:   serveraddr.sa.sa_family = family;
  557: #ifdef HAVE_IPV6
  558:   if (serveraddr.sa.sa_family == AF_INET6)
  559:     serveraddr.in6.sin6_flowinfo = 0;
  560: #endif
  561:   
  562:   /* spoof check: answer must come from known server, */
  563:   for (server = daemon->servers; server; server = server->next)
  564:     if (!(server->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR)) &&
  565: 	sockaddr_isequal(&server->addr, &serveraddr))
  566:       break;
  567:    
  568:   header = (struct dns_header *)daemon->packet;
  569:   
  570:   if (!server ||
  571:       n < (int)sizeof(struct dns_header) || !(header->hb3 & HB3_QR) ||
  572:       !(forward = lookup_frec(ntohs(header->id), questions_crc(header, n, daemon->namebuff))))
  573:     return;
  574:    
  575:   server = forward->sentto;
  576:   
  577:   if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
  578:       !option_bool(OPT_ORDER) &&
  579:       forward->forwardall == 0)
  580:     /* for broken servers, attempt to send to another one. */
  581:     {
  582:       unsigned char *pheader;
  583:       size_t plen;
  584:       int is_sign;
  585:       
  586:       /* recreate query from reply */
  587:       pheader = find_pseudoheader(header, (size_t)n, &plen, NULL, &is_sign);
  588:       if (!is_sign)
  589: 	{
  590: 	  header->ancount = htons(0);
  591: 	  header->nscount = htons(0);
  592: 	  header->arcount = htons(0);
  593: 	  if ((nn = resize_packet(header, (size_t)n, pheader, plen)))
  594: 	    {
  595: 	      header->hb3 &= ~(HB3_QR | HB3_TC);
  596: 	      forward_query(-1, NULL, NULL, 0, header, nn, now, forward);
  597: 	      return;
  598: 	    }
  599: 	}
  600:     }   
  601:   
  602:   if ((forward->sentto->flags & SERV_TYPE) == 0)
  603:     {
  604:       if (RCODE(header) == SERVFAIL || RCODE(header) == REFUSED)
  605: 	server = NULL;
  606:       else
  607: 	{
  608: 	  struct server *last_server;
  609: 	  
  610: 	  /* find good server by address if possible, otherwise assume the last one we sent to */ 
  611: 	  for (last_server = daemon->servers; last_server; last_server = last_server->next)
  612: 	    if (!(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_NO_ADDR)) &&
  613: 		sockaddr_isequal(&last_server->addr, &serveraddr))
  614: 	      {
  615: 		server = last_server;
  616: 		break;
  617: 	      }
  618: 	} 
  619:       if (!option_bool(OPT_ALL_SERVERS))
  620: 	daemon->last_server = server;
  621:     }
  622:   
  623:   /* If the answer is an error, keep the forward record in place in case
  624:      we get a good reply from another server. Kill it when we've
  625:      had replies from all to avoid filling the forwarding table when
  626:      everything is broken */
  627:   if (forward->forwardall == 0 || --forward->forwardall == 1 || 
  628:       (RCODE(header) != REFUSED && RCODE(header) != SERVFAIL))
  629:     {
  630:       int check_rebind = !(forward->flags & FREC_NOREBIND);
  631: 
  632:       if (!option_bool(OPT_NO_REBIND))
  633: 	check_rebind = 0;
  634:       
  635:       if ((nn = process_reply(header, now, server, (size_t)n, check_rebind, forward->flags & FREC_CHECKING_DISABLED)))
  636: 	{
  637: 	  header->id = htons(forward->orig_id);
  638: 	  header->hb4 |= HB4_RA; /* recursion if available */
  639: 	  send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn, 
  640: 		    &forward->source, &forward->dest, forward->iface);
  641: 	}
  642:       free_frec(forward); /* cancel */
  643:     }
  644: }
  645: 
  646: 
  647: void receive_query(struct listener *listen, time_t now)
  648: {
  649:   struct dns_header *header = (struct dns_header *)daemon->packet;
  650:   union mysockaddr source_addr;
  651:   unsigned short type;
  652:   struct all_addr dst_addr;
  653:   struct in_addr netmask, dst_addr_4;
  654:   size_t m;
  655:   ssize_t n;
  656:   int if_index = 0;
  657:   int auth_dns = 0;
  658:   struct iovec iov[1];
  659:   struct msghdr msg;
  660:   struct cmsghdr *cmptr;
  661:   union {
  662:     struct cmsghdr align; /* this ensures alignment */
  663: #ifdef HAVE_IPV6
  664:     char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
  665: #endif
  666: #if defined(HAVE_LINUX_NETWORK)
  667:     char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
  668: #elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK)
  669:     char control[CMSG_SPACE(sizeof(struct in_addr)) +
  670: 		 CMSG_SPACE(sizeof(unsigned int))];
  671: #elif defined(IP_RECVDSTADDR)
  672:     char control[CMSG_SPACE(sizeof(struct in_addr)) +
  673: 		 CMSG_SPACE(sizeof(struct sockaddr_dl))];
  674: #endif
  675:   } control_u;
  676:   
  677:   /* packet buffer overwritten */
  678:   daemon->srv_save = NULL;
  679:   
  680:   dst_addr_4.s_addr = 0;
  681:   netmask.s_addr = 0;
  682:   
  683:   if (option_bool(OPT_NOWILD) && listen->iface)
  684:     {
  685:       auth_dns = listen->iface->dns_auth;
  686:      
  687:       if (listen->family == AF_INET)
  688: 	{
  689: 	  dst_addr_4 = listen->iface->addr.in.sin_addr;
  690: 	  netmask = listen->iface->netmask;
  691: 	}
  692:     }
  693:   
  694:   iov[0].iov_base = daemon->packet;
  695:   iov[0].iov_len = daemon->edns_pktsz;
  696:     
  697:   msg.msg_control = control_u.control;
  698:   msg.msg_controllen = sizeof(control_u);
  699:   msg.msg_flags = 0;
  700:   msg.msg_name = &source_addr;
  701:   msg.msg_namelen = sizeof(source_addr);
  702:   msg.msg_iov = iov;
  703:   msg.msg_iovlen = 1;
  704:   
  705:   if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
  706:     return;
  707:   
  708:   if (n < (int)sizeof(struct dns_header) || 
  709:       (msg.msg_flags & MSG_TRUNC) ||
  710:       (header->hb3 & HB3_QR))
  711:     return;
  712:   
  713:   source_addr.sa.sa_family = listen->family;
  714: #ifdef HAVE_IPV6
  715:   if (listen->family == AF_INET6)
  716:     source_addr.in6.sin6_flowinfo = 0;
  717: #endif
  718: 
  719:   if (!option_bool(OPT_NOWILD))
  720:     {
  721:       struct ifreq ifr;
  722: 
  723:       if (msg.msg_controllen < sizeof(struct cmsghdr))
  724: 	return;
  725: 
  726: #if defined(HAVE_LINUX_NETWORK)
  727:       if (listen->family == AF_INET)
  728: 	for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
  729: 	  if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
  730: 	    {
  731: 	      union {
  732: 		unsigned char *c;
  733: 		struct in_pktinfo *p;
  734: 	      } p;
  735: 	      p.c = CMSG_DATA(cmptr);
  736: 	      dst_addr_4 = dst_addr.addr.addr4 = p.p->ipi_spec_dst;
  737: 	      if_index = p.p->ipi_ifindex;
  738: 	    }
  739: #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
  740:       if (listen->family == AF_INET)
  741: 	{
  742: 	  for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
  743: 	    {
  744: 	      union {
  745: 		unsigned char *c;
  746: 		unsigned int *i;
  747: 		struct in_addr *a;
  748: #ifndef HAVE_SOLARIS_NETWORK
  749: 		struct sockaddr_dl *s;
  750: #endif
  751: 	      } p;
  752: 	       p.c = CMSG_DATA(cmptr);
  753: 	       if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
  754: 		 dst_addr_4 = dst_addr.addr.addr4 = *(p.a);
  755: 	       else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
  756: #ifdef HAVE_SOLARIS_NETWORK
  757: 		 if_index = *(p.i);
  758: #else
  759:   	         if_index = p.s->sdl_index;
  760: #endif
  761: 	    }
  762: 	}
  763: #endif
  764:       
  765: #ifdef HAVE_IPV6
  766:       if (listen->family == AF_INET6)
  767: 	{
  768: 	  for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
  769: 	    if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
  770: 	      {
  771: 		union {
  772: 		  unsigned char *c;
  773: 		  struct in6_pktinfo *p;
  774: 		} p;
  775: 		p.c = CMSG_DATA(cmptr);
  776: 		  
  777: 		dst_addr.addr.addr6 = p.p->ipi6_addr;
  778: 		if_index = p.p->ipi6_ifindex;
  779: 	      }
  780: 	}
  781: #endif
  782:       
  783:       /* enforce available interface configuration */
  784:       
  785:       if (!indextoname(listen->fd, if_index, ifr.ifr_name))
  786: 	return;
  787:       
  788:       if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
  789: 	{
  790: 	   if (!option_bool(OPT_CLEVERBIND))
  791: 	     enumerate_interfaces(); 
  792: 	   if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name))
  793: 	     return;
  794: 	}
  795: 
  796:       if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
  797: 	{
  798: 	  struct irec *iface;
  799: 	  
  800: 	  /* get the netmask of the interface whch has the address we were sent to.
  801: 	     This is no neccessarily the interface we arrived on. */
  802: 	  
  803: 	  for (iface = daemon->interfaces; iface; iface = iface->next)
  804: 	    if (iface->addr.sa.sa_family == AF_INET &&
  805: 		iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
  806: 	      break;
  807: 	  
  808: 	  /* interface may be new */
  809: 	  if (!iface && !option_bool(OPT_CLEVERBIND))
  810: 	    enumerate_interfaces(); 
  811: 	  
  812: 	  for (iface = daemon->interfaces; iface; iface = iface->next)
  813: 	    if (iface->addr.sa.sa_family == AF_INET &&
  814: 		iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
  815: 	      break;
  816: 	  
  817: 	  /* If we failed, abandon localisation */
  818: 	  if (iface)
  819: 	    netmask = iface->netmask;
  820: 	  else
  821: 	    dst_addr_4.s_addr = 0;
  822: 	}
  823:     }
  824:   
  825:   if (extract_request(header, (size_t)n, daemon->namebuff, &type))
  826:     {
  827:       char types[20];
  828: 
  829:       querystr(auth_dns ? "auth" : "query", types, type);
  830: 
  831:       if (listen->family == AF_INET) 
  832: 	log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, 
  833: 		  (struct all_addr *)&source_addr.in.sin_addr, types);
  834: #ifdef HAVE_IPV6
  835:       else
  836: 	log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, 
  837: 		  (struct all_addr *)&source_addr.in6.sin6_addr, types);
  838: #endif
  839:     }
  840: 
  841: #ifdef HAVE_AUTH
  842:   if (auth_dns)
  843:     {
  844:       m = answer_auth(header, ((char *) header) + PACKETSZ, (size_t)n, now, &source_addr);
  845:       if (m >= 1)
  846: 	send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
  847: 		  (char *)header, m, &source_addr, &dst_addr, if_index);
  848:     }
  849:   else
  850: #endif
  851:     {
  852:       m = answer_request(header, ((char *) header) + PACKETSZ, (size_t)n, 
  853: 			 dst_addr_4, netmask, now);
  854:       
  855:       if (m >= 1)
  856: 	{
  857: 	  send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
  858: 		    (char *)header, m, &source_addr, &dst_addr, if_index);
  859: 	  daemon->local_answer++;
  860: 	}
  861:       else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
  862: 			     header, (size_t)n, now, NULL))
  863: 	daemon->queries_forwarded++;
  864:       else
  865: 	daemon->local_answer++;
  866:     }
  867: }
  868: 
  869: /* The daemon forks before calling this: it should deal with one connection,
  870:    blocking as neccessary, and then return. Note, need to be a bit careful
  871:    about resources for debug mode, when the fork is suppressed: that's
  872:    done by the caller. */
  873: unsigned char *tcp_request(int confd, time_t now,
  874: 			   union mysockaddr *local_addr, struct in_addr netmask, int auth_dns)
  875: {
  876:   size_t size = 0;
  877:   int norebind = 0;
  878:   int checking_disabled;
  879:   size_t m;
  880:   unsigned short qtype;
  881:   unsigned int gotname;
  882:   unsigned char c1, c2;
  883:   /* Max TCP packet + slop */
  884:   unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ);
  885:   struct dns_header *header;
  886:   struct server *last_server;
  887:   struct in_addr dst_addr_4;
  888:   union mysockaddr peer_addr;
  889:   socklen_t peer_len = sizeof(union mysockaddr);
  890:   
  891:   if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
  892:     return packet;
  893: 
  894:   while (1)
  895:     {
  896:       if (!packet ||
  897: 	  !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) ||
  898: 	  !(size = c1 << 8 | c2) ||
  899: 	  !read_write(confd, packet, size, 1))
  900:        	return packet; 
  901:   
  902:       if (size < (int)sizeof(struct dns_header))
  903: 	continue;
  904:       
  905:       header = (struct dns_header *)packet;
  906: 
  907:       /* save state of "cd" flag in query */
  908:       checking_disabled = header->hb4 & HB4_CD;
  909:        
  910:       /* RFC 4035: sect 4.6 para 2 */
  911:       header->hb4 &= ~HB4_AD;
  912:       
  913:       if ((gotname = extract_request(header, (unsigned int)size, daemon->namebuff, &qtype)))
  914: 	{
  915: 	  char types[20];
  916: 	  
  917: 	  querystr(auth_dns ? "auth" : "query", types, qtype);
  918: 	  
  919: 	  if (peer_addr.sa.sa_family == AF_INET) 
  920: 	    log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, 
  921: 		      (struct all_addr *)&peer_addr.in.sin_addr, types);
  922: #ifdef HAVE_IPV6
  923: 	  else
  924: 	    log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, 
  925: 		      (struct all_addr *)&peer_addr.in6.sin6_addr, types);
  926: #endif
  927: 	}
  928:       
  929:       if (local_addr->sa.sa_family == AF_INET)
  930: 	dst_addr_4 = local_addr->in.sin_addr;
  931:       else
  932: 	dst_addr_4.s_addr = 0;
  933:       
  934: #ifdef HAVE_AUTH
  935:       if (auth_dns)
  936: 	m = answer_auth(header, ((char *) header) + 65536, (size_t)size, now, &peer_addr);
  937:       else
  938: #endif
  939: 	{
  940: 	  /* m > 0 if answered from cache */
  941: 	  m = answer_request(header, ((char *) header) + 65536, (size_t)size, 
  942: 			     dst_addr_4, netmask, now);
  943: 	  
  944: 	  /* Do this by steam now we're not in the select() loop */
  945: 	  check_log_writer(NULL); 
  946: 	  
  947: 	  if (m == 0)
  948: 	    {
  949: 	      unsigned int flags = 0;
  950: 	      struct all_addr *addrp = NULL;
  951: 	      int type = 0;
  952: 	      char *domain = NULL;
  953: 	      
  954: 	      if (option_bool(OPT_ADD_MAC))
  955: 		size = add_mac(header, size, ((char *) header) + 65536, &peer_addr);
  956: 	      
  957: 	      if (gotname)
  958: 		flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
  959: 	      
  960: 	      if (type != 0  || option_bool(OPT_ORDER) || !daemon->last_server)
  961: 		last_server = daemon->servers;
  962: 	      else
  963: 		last_server = daemon->last_server;
  964: 	      
  965: 	      if (!flags && last_server)
  966: 		{
  967: 		  struct server *firstsendto = NULL;
  968: 		  unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
  969: 		  
  970: 		  /* Loop round available servers until we succeed in connecting to one.
  971: 		     Note that this code subtley ensures that consecutive queries on this connection
  972: 		     which can go to the same server, do so. */
  973: 		  while (1) 
  974: 		    {
  975: 		      if (!firstsendto)
  976: 			firstsendto = last_server;
  977: 		      else
  978: 			{
  979: 			  if (!(last_server = last_server->next))
  980: 			    last_server = daemon->servers;
  981: 			  
  982: 			  if (last_server == firstsendto)
  983: 			    break;
  984: 			}
  985: 		      
  986: 		      /* server for wrong domain */
  987: 		      if (type != (last_server->flags & SERV_TYPE) ||
  988: 			  (type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)))
  989: 			continue;
  990: 		      
  991: 		      if (last_server->tcpfd == -1)
  992: 			{
  993: 			  if ((last_server->tcpfd = socket(last_server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
  994: 			    continue;
  995: 			  
  996: 			  if ((!local_bind(last_server->tcpfd,  &last_server->source_addr, last_server->interface, 1) ||
  997: 			       connect(last_server->tcpfd, &last_server->addr.sa, sa_len(&last_server->addr)) == -1))
  998: 			    {
  999: 			      close(last_server->tcpfd);
 1000: 			      last_server->tcpfd = -1;
 1001: 			      continue;
 1002: 			    }
 1003: 			  
 1004: #ifdef HAVE_CONNTRACK
 1005: 			  /* Copy connection mark of incoming query to outgoing connection. */
 1006: 			  if (option_bool(OPT_CONNTRACK))
 1007: 			    {
 1008: 			      unsigned int mark;
 1009: 			      struct all_addr local;
 1010: #ifdef HAVE_IPV6		      
 1011: 			      if (local_addr->sa.sa_family == AF_INET6)
 1012: 				local.addr.addr6 = local_addr->in6.sin6_addr;
 1013: 			      else
 1014: #endif
 1015: 				local.addr.addr4 = local_addr->in.sin_addr;
 1016: 			      
 1017: 			      if (get_incoming_mark(&peer_addr, &local, 1, &mark))
 1018: 				setsockopt(last_server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
 1019: 			    }
 1020: #endif	
 1021: 			}
 1022: 		      
 1023: 		      c1 = size >> 8;
 1024: 		      c2 = size;
 1025: 		      
 1026: 		      if (!read_write(last_server->tcpfd, &c1, 1, 0) ||
 1027: 			  !read_write(last_server->tcpfd, &c2, 1, 0) ||
 1028: 			  !read_write(last_server->tcpfd, packet, size, 0) ||
 1029: 			  !read_write(last_server->tcpfd, &c1, 1, 1) ||
 1030: 			  !read_write(last_server->tcpfd, &c2, 1, 1))
 1031: 			{
 1032: 			  close(last_server->tcpfd);
 1033: 			  last_server->tcpfd = -1;
 1034: 			  continue;
 1035: 			} 
 1036: 		      
 1037: 		      m = (c1 << 8) | c2;
 1038: 		      if (!read_write(last_server->tcpfd, packet, m, 1))
 1039: 			return packet;
 1040: 		      
 1041: 		      if (!gotname)
 1042: 			strcpy(daemon->namebuff, "query");
 1043: 		      if (last_server->addr.sa.sa_family == AF_INET)
 1044: 			log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff, 
 1045: 				  (struct all_addr *)&last_server->addr.in.sin_addr, NULL); 
 1046: #ifdef HAVE_IPV6
 1047: 		      else
 1048: 			log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff, 
 1049: 				  (struct all_addr *)&last_server->addr.in6.sin6_addr, NULL);
 1050: #endif 
 1051: 		      
 1052: 		      /* There's no point in updating the cache, since this process will exit and
 1053: 			 lose the information after a few queries. We make this call for the alias and 
 1054: 			 bogus-nxdomain side-effects. */
 1055: 		      /* If the crc of the question section doesn't match the crc we sent, then
 1056: 			 someone might be attempting to insert bogus values into the cache by 
 1057: 			 sending replies containing questions and bogus answers. */
 1058: 		      if (crc == questions_crc(header, (unsigned int)m, daemon->namebuff))
 1059: 			m = process_reply(header, now, last_server, (unsigned int)m, 
 1060: 					  option_bool(OPT_NO_REBIND) && !norebind, checking_disabled);
 1061: 		      
 1062: 		      break;
 1063: 		    }
 1064: 		}
 1065: 	
 1066: 	      /* In case of local answer or no connections made. */
 1067: 	      if (m == 0)
 1068: 		m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
 1069: 	    }
 1070: 	}
 1071: 	  
 1072:       check_log_writer(NULL);
 1073:       
 1074:       c1 = m>>8;
 1075:       c2 = m;
 1076:       if (m == 0 ||
 1077: 	  !read_write(confd, &c1, 1, 0) ||
 1078: 	  !read_write(confd, &c2, 1, 0) || 
 1079: 	  !read_write(confd, packet, m, 0))
 1080: 	return packet;
 1081:     }
 1082: }
 1083: 
 1084: static struct frec *allocate_frec(time_t now)
 1085: {
 1086:   struct frec *f;
 1087:   
 1088:   if ((f = (struct frec *)whine_malloc(sizeof(struct frec))))
 1089:     {
 1090:       f->next = daemon->frec_list;
 1091:       f->time = now;
 1092:       f->sentto = NULL;
 1093:       f->rfd4 = NULL;
 1094:       f->flags = 0;
 1095: #ifdef HAVE_IPV6
 1096:       f->rfd6 = NULL;
 1097: #endif
 1098:       daemon->frec_list = f;
 1099:     }
 1100: 
 1101:   return f;
 1102: }
 1103: 
 1104: static struct randfd *allocate_rfd(int family)
 1105: {
 1106:   static int finger = 0;
 1107:   int i;
 1108: 
 1109:   /* limit the number of sockets we have open to avoid starvation of 
 1110:      (eg) TFTP. Once we have a reasonable number, randomness should be OK */
 1111: 
 1112:   for (i = 0; i < RANDOM_SOCKS; i++)
 1113:     if (daemon->randomsocks[i].refcount == 0)
 1114:       {
 1115: 	if ((daemon->randomsocks[i].fd = random_sock(family)) == -1)
 1116: 	  break;
 1117:       
 1118: 	daemon->randomsocks[i].refcount = 1;
 1119: 	daemon->randomsocks[i].family = family;
 1120: 	return &daemon->randomsocks[i];
 1121:       }
 1122: 
 1123:   /* No free ones or cannot get new socket, grab an existing one */
 1124:   for (i = 0; i < RANDOM_SOCKS; i++)
 1125:     {
 1126:       int j = (i+finger) % RANDOM_SOCKS;
 1127:       if (daemon->randomsocks[j].refcount != 0 &&
 1128: 	  daemon->randomsocks[j].family == family && 
 1129: 	  daemon->randomsocks[j].refcount != 0xffff)
 1130: 	{
 1131: 	  finger = j;
 1132: 	  daemon->randomsocks[j].refcount++;
 1133: 	  return &daemon->randomsocks[j];
 1134: 	}
 1135:     }
 1136: 
 1137:   return NULL; /* doom */
 1138: }
 1139: 
 1140: static void free_frec(struct frec *f)
 1141: {
 1142:   if (f->rfd4 && --(f->rfd4->refcount) == 0)
 1143:     close(f->rfd4->fd);
 1144:     
 1145:   f->rfd4 = NULL;
 1146:   f->sentto = NULL;
 1147:   f->flags = 0;
 1148:   
 1149: #ifdef HAVE_IPV6
 1150:   if (f->rfd6 && --(f->rfd6->refcount) == 0)
 1151:     close(f->rfd6->fd);
 1152:     
 1153:   f->rfd6 = NULL;
 1154: #endif
 1155: }
 1156: 
 1157: /* if wait==NULL return a free or older than TIMEOUT record.
 1158:    else return *wait zero if one available, or *wait is delay to
 1159:    when the oldest in-use record will expire. Impose an absolute
 1160:    limit of 4*TIMEOUT before we wipe things (for random sockets) */
 1161: struct frec *get_new_frec(time_t now, int *wait)
 1162: {
 1163:   struct frec *f, *oldest, *target;
 1164:   int count;
 1165:   
 1166:   if (wait)
 1167:     *wait = 0;
 1168: 
 1169:   for (f = daemon->frec_list, oldest = NULL, target =  NULL, count = 0; f; f = f->next, count++)
 1170:     if (!f->sentto)
 1171:       target = f;
 1172:     else 
 1173:       {
 1174: 	if (difftime(now, f->time) >= 4*TIMEOUT)
 1175: 	  {
 1176: 	    free_frec(f);
 1177: 	    target = f;
 1178: 	  }
 1179: 	
 1180: 	if (!oldest || difftime(f->time, oldest->time) <= 0)
 1181: 	  oldest = f;
 1182:       }
 1183: 
 1184:   if (target)
 1185:     {
 1186:       target->time = now;
 1187:       return target;
 1188:     }
 1189:   
 1190:   /* can't find empty one, use oldest if there is one
 1191:      and it's older than timeout */
 1192:   if (oldest && ((int)difftime(now, oldest->time)) >= TIMEOUT)
 1193:     { 
 1194:       /* keep stuff for twice timeout if we can by allocating a new
 1195: 	 record instead */
 1196:       if (difftime(now, oldest->time) < 2*TIMEOUT && 
 1197: 	  count <= daemon->ftabsize &&
 1198: 	  (f = allocate_frec(now)))
 1199: 	return f;
 1200: 
 1201:       if (!wait)
 1202: 	{
 1203: 	  free_frec(oldest);
 1204: 	  oldest->time = now;
 1205: 	}
 1206:       return oldest;
 1207:     }
 1208:   
 1209:   /* none available, calculate time 'till oldest record expires */
 1210:   if (count > daemon->ftabsize)
 1211:     {
 1212:       if (oldest && wait)
 1213: 	*wait = oldest->time + (time_t)TIMEOUT - now;
 1214:       return NULL;
 1215:     }
 1216:   
 1217:   if (!(f = allocate_frec(now)) && wait)
 1218:     /* wait one second on malloc failure */
 1219:     *wait = 1;
 1220: 
 1221:   return f; /* OK if malloc fails and this is NULL */
 1222: }
 1223:  
 1224: /* crc is all-ones if not known. */
 1225: static struct frec *lookup_frec(unsigned short id, unsigned int crc)
 1226: {
 1227:   struct frec *f;
 1228: 
 1229:   for(f = daemon->frec_list; f; f = f->next)
 1230:     if (f->sentto && f->new_id == id && 
 1231: 	(f->crc == crc || crc == 0xffffffff))
 1232:       return f;
 1233:       
 1234:   return NULL;
 1235: }
 1236: 
 1237: static struct frec *lookup_frec_by_sender(unsigned short id,
 1238: 					  union mysockaddr *addr,
 1239: 					  unsigned int crc)
 1240: {
 1241:   struct frec *f;
 1242:   
 1243:   for(f = daemon->frec_list; f; f = f->next)
 1244:     if (f->sentto &&
 1245: 	f->orig_id == id && 
 1246: 	f->crc == crc &&
 1247: 	sockaddr_isequal(&f->source, addr))
 1248:       return f;
 1249:    
 1250:   return NULL;
 1251: }
 1252: 
 1253: /* A server record is going away, remove references to it */
 1254: void server_gone(struct server *server)
 1255: {
 1256:   struct frec *f;
 1257:   
 1258:   for (f = daemon->frec_list; f; f = f->next)
 1259:     if (f->sentto && f->sentto == server)
 1260:       free_frec(f);
 1261:   
 1262:   if (daemon->last_server == server)
 1263:     daemon->last_server = NULL;
 1264: 
 1265:   if (daemon->srv_save == server)
 1266:     daemon->srv_save = NULL;
 1267: }
 1268: 
 1269: /* return unique random ids. */
 1270: static unsigned short get_id(unsigned int crc)
 1271: {
 1272:   unsigned short ret = 0;
 1273:   
 1274:   do 
 1275:     ret = rand16();
 1276:   while (lookup_frec(ret, crc));
 1277:   
 1278:   return ret;
 1279: }
 1280: 
 1281: 
 1282: 
 1283: 
 1284: 

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