File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / network.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Mon Jul 29 19:37:40 2013 UTC (10 years, 11 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    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_LINUX_NETWORK
   20: 
   21: int indextoname(int fd, int index, char *name)
   22: {
   23:   struct ifreq ifr;
   24:   
   25:   if (index == 0)
   26:     return 0;
   27: 
   28:   ifr.ifr_ifindex = index;
   29:   if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
   30:     return 0;
   31: 
   32:   strncpy(name, ifr.ifr_name, IF_NAMESIZE);
   33: 
   34:   return 1;
   35: }
   36: 
   37: 
   38: #elif defined(HAVE_SOLARIS_NETWORK)
   39: 
   40: #include <zone.h>
   41: #include <alloca.h>
   42: #ifndef LIFC_UNDER_IPMP
   43: #  define LIFC_UNDER_IPMP 0
   44: #endif
   45: 
   46: int indextoname(int fd, int index, char *name)
   47: {
   48:   int64_t lifc_flags;
   49:   struct lifnum lifn;
   50:   int numifs, bufsize, i;
   51:   struct lifconf lifc;
   52:   struct lifreq *lifrp;
   53:   
   54:   if (index == 0)
   55:     return 0;
   56:   
   57:   if (getzoneid() == GLOBAL_ZONEID) 
   58:     {
   59:       if (!if_indextoname(index, name))
   60: 	return 0;
   61:       return 1;
   62:     }
   63:   
   64:   lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES | LIFC_UNDER_IPMP;
   65:   lifn.lifn_family = AF_UNSPEC;
   66:   lifn.lifn_flags = lifc_flags;
   67:   if (ioctl(fd, SIOCGLIFNUM, &lifn) < 0) 
   68:     return 0;
   69:   
   70:   numifs = lifn.lifn_count;
   71:   bufsize = numifs * sizeof(struct lifreq);
   72:   
   73:   lifc.lifc_family = AF_UNSPEC;
   74:   lifc.lifc_flags = lifc_flags;
   75:   lifc.lifc_len = bufsize;
   76:   lifc.lifc_buf = alloca(bufsize);
   77:   
   78:   if (ioctl(fd, SIOCGLIFCONF, &lifc) < 0)  
   79:     return 0;
   80:   
   81:   lifrp = lifc.lifc_req;
   82:   for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++) 
   83:     {
   84:       struct lifreq lifr;
   85:       strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
   86:       if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0) 
   87: 	return 0;
   88:       
   89:       if (lifr.lifr_index == index) {
   90: 	strncpy(name, lifr.lifr_name, IF_NAMESIZE);
   91: 	return 1;
   92:       }
   93:     }
   94:   return 0;
   95: }
   96: 
   97: 
   98: #else
   99: 
  100: int indextoname(int fd, int index, char *name)
  101: { 
  102:   if (index == 0 || !if_indextoname(index, name))
  103:     return 0;
  104: 
  105:   return 1;
  106: }
  107: 
  108: #endif
  109: 
  110: int iface_check(int family, struct all_addr *addr, char *name, int *auth)
  111: {
  112:   struct iname *tmp;
  113:   int ret = 1;
  114: 
  115:   /* Note: have to check all and not bail out early, so that we set the
  116:      "used" flags. */
  117:   
  118:   if (auth)
  119:     *auth = 0;
  120:   
  121:   if (daemon->if_names || daemon->if_addrs)
  122:     {
  123:       ret = 0;
  124: 
  125:       for (tmp = daemon->if_names; tmp; tmp = tmp->next)
  126: 	if (tmp->name && wildcard_match(tmp->name, name))
  127: 	  ret = tmp->used = 1;
  128: 	        
  129:       if (addr)
  130: 	for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
  131: 	  if (tmp->addr.sa.sa_family == family)
  132: 	    {
  133: 	      if (family == AF_INET &&
  134: 		  tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
  135: 		ret = tmp->used = 1;
  136: #ifdef HAVE_IPV6
  137: 	      else if (family == AF_INET6 &&
  138: 		       IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, 
  139: 					  &addr->addr.addr6))
  140: 		ret = tmp->used = 1;
  141: #endif
  142: 	    }          
  143:     }
  144:   
  145:   for (tmp = daemon->if_except; tmp; tmp = tmp->next)
  146:     if (tmp->name && wildcard_match(tmp->name, name))
  147:       ret = 0;
  148:     
  149: 
  150:   for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
  151:     if (tmp->name)
  152:       {
  153: 	if (strcmp(tmp->name, name) == 0)
  154: 	  break;
  155:       }
  156:     else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
  157: 	     tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
  158:       break;
  159: #ifdef HAVE_IPV6
  160:     else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
  161: 	     IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
  162:       break;
  163: #endif      
  164: 
  165:   if (tmp && auth) 
  166:     {
  167:       *auth = 1;
  168:       ret = 1;
  169:     }
  170: 
  171:   return ret; 
  172: }
  173: 
  174: 
  175: /* Fix for problem that the kernel sometimes reports the loopback inerface as the
  176:    arrival interface when a packet originates locally, even when sent to address of 
  177:    an interface other than the loopback. Accept packet if it arrived via a loopback 
  178:    interface, even when we're not accepting packets that way, as long as the destination
  179:    address is one we're believing. Interface list must be up-to-date before calling. */
  180: int loopback_exception(int fd, int family, struct all_addr *addr, char *name)    
  181: {
  182:   struct ifreq ifr;
  183:   struct irec *iface;
  184: 
  185:   strncpy(ifr.ifr_name, name, IF_NAMESIZE);
  186:   if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
  187:       ifr.ifr_flags & IFF_LOOPBACK)
  188:     {
  189:       for (iface = daemon->interfaces; iface; iface = iface->next)
  190: 	if (iface->addr.sa.sa_family == family)
  191: 	  {
  192: 	    if (family == AF_INET)
  193: 	      {
  194: 		if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
  195: 		  return 1;
  196: 	      }
  197: #ifdef HAVE_IPV6
  198: 	    else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
  199: 	      return 1;
  200: #endif
  201: 	    
  202: 	  }
  203:     }
  204:   return 0;
  205: }
  206: 
  207: static int iface_allowed(struct irec **irecp, int if_index, 
  208: 			 union mysockaddr *addr, struct in_addr netmask, int dad) 
  209: {
  210:   struct irec *iface;
  211:   int fd, mtu = 0, loopback;
  212:   struct ifreq ifr;
  213:   int tftp_ok = !!option_bool(OPT_TFTP);
  214:   int dhcp_ok = 1;
  215:   int auth_dns = 0;
  216: #ifdef HAVE_DHCP
  217:   struct iname *tmp;
  218: #endif
  219: 
  220:   /* check whether the interface IP has been added already 
  221:      we call this routine multiple times. */
  222:   for (iface = *irecp; iface; iface = iface->next) 
  223:     if (sockaddr_isequal(&iface->addr, addr))
  224:       {
  225: 	iface->dad = dad;
  226: 	return 1;
  227:       }
  228: 
  229:   if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ||
  230:       !indextoname(fd, if_index, ifr.ifr_name) ||
  231:       ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
  232:     {
  233:       if (fd != -1)
  234: 	{
  235: 	  int errsave = errno;
  236: 	  close(fd);
  237: 	  errno = errsave;
  238: 	}
  239:       return 0;
  240:     }
  241:    
  242:   loopback = ifr.ifr_flags & IFF_LOOPBACK;
  243:   
  244:   if (loopback)
  245:      dhcp_ok = 0;
  246: 
  247:   if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
  248:     mtu = ifr.ifr_mtu;
  249:   
  250:   close(fd);
  251:   
  252:   /* If we are restricting the set of interfaces to use, make
  253:      sure that loopback interfaces are in that set. */
  254:   if (daemon->if_names && loopback)
  255:     {
  256:       struct iname *lo;
  257:       for (lo = daemon->if_names; lo; lo = lo->next)
  258: 	if (lo->name && strcmp(lo->name, ifr.ifr_name) == 0)
  259: 	  break;
  260:       
  261:       if (!lo && (lo = whine_malloc(sizeof(struct iname)))) 
  262: 	{
  263: 	  if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
  264: 	    {
  265: 	      strcpy(lo->name, ifr.ifr_name);
  266: 	      lo->used = 1;
  267: 	      lo->next = daemon->if_names;
  268: 	      daemon->if_names = lo;
  269: 	    }
  270: 	  else
  271: 	    free(lo);
  272: 	}
  273:     }
  274:   
  275:   if (addr->sa.sa_family == AF_INET &&
  276:       !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, &auth_dns))
  277:     return 1;
  278: 
  279: #ifdef HAVE_IPV6
  280:   if (addr->sa.sa_family == AF_INET6 &&
  281:       !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, &auth_dns))
  282:     return 1;
  283: #endif
  284:     
  285: #ifdef HAVE_DHCP
  286:   /* No DHCP where we're doing auth DNS. */
  287:   if (auth_dns)
  288:     {
  289:       tftp_ok = 0;
  290:       dhcp_ok = 0;
  291:     }
  292:   else
  293:     for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
  294:       if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
  295: 	{
  296: 	  tftp_ok = 0;
  297: 	  dhcp_ok = 0;
  298: 	}
  299: #endif
  300:  
  301:   /* add to list */
  302:   if ((iface = whine_malloc(sizeof(struct irec))))
  303:     {
  304:       iface->addr = *addr;
  305:       iface->netmask = netmask;
  306:       iface->tftp_ok = tftp_ok;
  307:       iface->dhcp_ok = dhcp_ok;
  308:       iface->dns_auth = auth_dns;
  309:       iface->mtu = mtu;
  310:       iface->dad = dad;
  311:       iface->done = iface->multicast_done = 0;
  312:       iface->index = if_index;
  313:       if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
  314: 	{
  315: 	  strcpy(iface->name, ifr.ifr_name);
  316: 	  iface->next = *irecp;
  317: 	  *irecp = iface;
  318: 	  return 1;
  319: 	}
  320:       free(iface);
  321: 
  322:     }
  323:   
  324:   errno = ENOMEM; 
  325:   return 0;
  326: }
  327: 
  328: #ifdef HAVE_IPV6
  329: static int iface_allowed_v6(struct in6_addr *local, int prefix, 
  330: 			    int scope, int if_index, int flags, 
  331: 			    int preferred, int valid, void *vparam)
  332: {
  333:   union mysockaddr addr;
  334:   struct in_addr netmask; /* dummy */
  335:   netmask.s_addr = 0;
  336: 
  337:   (void)prefix; /* warning */
  338:   (void)scope; /* warning */
  339:   (void)preferred;
  340:   (void)valid;
  341:   
  342:   memset(&addr, 0, sizeof(addr));
  343: #ifdef HAVE_SOCKADDR_SA_LEN
  344:   addr.in6.sin6_len = sizeof(addr.in6);
  345: #endif
  346:   addr.in6.sin6_family = AF_INET6;
  347:   addr.in6.sin6_addr = *local;
  348:   addr.in6.sin6_port = htons(daemon->port);
  349:   addr.in6.sin6_scope_id = if_index;
  350:   
  351:   return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, !!(flags & IFACE_TENTATIVE));
  352: }
  353: #endif
  354: 
  355: static int iface_allowed_v4(struct in_addr local, int if_index, 
  356: 			    struct in_addr netmask, struct in_addr broadcast, void *vparam)
  357: {
  358:   union mysockaddr addr;
  359: 
  360:   memset(&addr, 0, sizeof(addr));
  361: #ifdef HAVE_SOCKADDR_SA_LEN
  362:   addr.in.sin_len = sizeof(addr.in);
  363: #endif
  364:   addr.in.sin_family = AF_INET;
  365:   addr.in.sin_addr = broadcast; /* warning */
  366:   addr.in.sin_addr = local;
  367:   addr.in.sin_port = htons(daemon->port);
  368: 
  369:   return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, 0);
  370: }
  371:    
  372: int enumerate_interfaces(void)
  373: {
  374: #ifdef HAVE_IPV6
  375:   if (!iface_enumerate(AF_INET6, &daemon->interfaces, iface_allowed_v6))
  376:     return 0; 
  377: #endif
  378: 
  379:   return iface_enumerate(AF_INET, &daemon->interfaces, iface_allowed_v4); 
  380: }
  381: 
  382: /* set NONBLOCK bit on fd: See Stevens 16.6 */
  383: int fix_fd(int fd)
  384: {
  385:   int flags;
  386: 
  387:   if ((flags = fcntl(fd, F_GETFL)) == -1 ||
  388:       fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
  389:     return 0;
  390:   
  391:   return 1;
  392: }
  393: 
  394: static int make_sock(union mysockaddr *addr, int type, int dienow)
  395: {
  396:   int family = addr->sa.sa_family;
  397:   int fd, rc, opt = 1;
  398:   
  399:   if ((fd = socket(family, type, 0)) == -1)
  400:     {
  401:       int port;
  402:       char *s;
  403: 
  404:       /* No error if the kernel just doesn't support this IP flavour */
  405:       if (errno == EPROTONOSUPPORT ||
  406: 	  errno == EAFNOSUPPORT ||
  407: 	  errno == EINVAL)
  408: 	return -1;
  409:       
  410:     err:
  411:       port = prettyprint_addr(addr, daemon->addrbuff);
  412:       if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
  413: 	sprintf(daemon->addrbuff, "port %d", port);
  414:       s = _("failed to create listening socket for %s: %s");
  415:       
  416:       if (fd != -1)
  417: 	close (fd);
  418:       
  419:       if (dienow)
  420: 	{
  421: 	  /* failure to bind addresses given by --listen-address at this point
  422: 	     is OK if we're doing bind-dynamic */
  423: 	  if (!option_bool(OPT_CLEVERBIND))
  424: 	    die(s, daemon->addrbuff, EC_BADNET);
  425: 	}
  426:       else
  427: 	my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
  428:       
  429:       return -1;
  430:     }	
  431:   
  432:   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
  433:     goto err;
  434:   
  435: #ifdef HAVE_IPV6
  436:   if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
  437:     goto err;
  438: #endif
  439:   
  440:   if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
  441:     goto err;
  442:   
  443:   if (type == SOCK_STREAM)
  444:     {
  445:       if (listen(fd, 5) == -1)
  446: 	goto err;
  447:     }
  448:   else if (!option_bool(OPT_NOWILD))
  449:     {
  450:       if (family == AF_INET)
  451: 	{
  452: #if defined(HAVE_LINUX_NETWORK) 
  453: 	  if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
  454: 	    goto err;
  455: #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
  456: 	  if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
  457: 	      setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
  458: 	    goto err;
  459: #endif
  460: 	}
  461: #ifdef HAVE_IPV6
  462:       else if (!set_ipv6pktinfo(fd))
  463: 	goto err;
  464: #endif
  465:     }
  466:   
  467:   return fd;
  468: }
  469: 
  470: #ifdef HAVE_IPV6  
  471: int set_ipv6pktinfo(int fd)
  472: {
  473:   int opt = 1;
  474: 
  475:   /* The API changed around Linux 2.6.14 but the old ABI is still supported:
  476:      handle all combinations of headers and kernel.
  477:      OpenWrt note that this fixes the problem addressed by your very broken patch. */
  478:   daemon->v6pktinfo = IPV6_PKTINFO;
  479:   
  480: #ifdef IPV6_RECVPKTINFO
  481:   if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) != -1)
  482:     return 1;
  483: # ifdef IPV6_2292PKTINFO
  484:   else if (errno == ENOPROTOOPT && setsockopt(fd, IPPROTO_IPV6, IPV6_2292PKTINFO, &opt, sizeof(opt)) != -1)
  485:     {
  486:       daemon->v6pktinfo = IPV6_2292PKTINFO;
  487:       return 1;
  488:     }
  489: # endif 
  490: #else
  491:   if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
  492:     return 1;
  493: #endif
  494: 
  495:   return 0;
  496: }
  497: #endif
  498: 
  499: 
  500: /* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
  501: int tcp_interface(int fd, int af)
  502: { 
  503:   int if_index = 0;
  504: 
  505: #ifdef HAVE_LINUX_NETWORK
  506:   int opt = 1;
  507:   struct cmsghdr *cmptr;
  508:   struct msghdr msg;
  509:   
  510:   /* use mshdr do that the CMSDG_* macros are available */
  511:   msg.msg_control = daemon->packet;
  512:   msg.msg_controllen = daemon->packet_buff_sz;
  513:   
  514:   /* we overwrote the buffer... */
  515:   daemon->srv_save = NULL;
  516:   
  517:   if (af == AF_INET)
  518:     {
  519:       if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
  520: 	  getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
  521: 	for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
  522: 	  if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
  523:             {
  524:               union {
  525:                 unsigned char *c;
  526:                 struct in_pktinfo *p;
  527:               } p;
  528: 	      
  529: 	      p.c = CMSG_DATA(cmptr);
  530: 	      if_index = p.p->ipi_ifindex;
  531: 	    }
  532:     }
  533: #ifdef HAVE_IPV6
  534:   else
  535:     {
  536:       /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
  537: 	 it was removed in RFC-3542 !!!! 
  538: 
  539: 	 Fortunately, Linux kept the 2292 ABI when it moved to 3542. The following code always
  540: 	 uses the old ABI, and should work with pre- and post-3542 kernel headers */
  541: 
  542: #ifdef IPV6_2292PKTOPTIONS   
  543: #  define PKTOPTIONS IPV6_2292PKTOPTIONS
  544: #else
  545: #  define PKTOPTIONS IPV6_PKTOPTIONS
  546: #endif
  547: 
  548:       if (set_ipv6pktinfo(fd) &&
  549: 	  getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
  550: 	{
  551:           for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
  552:             if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
  553:               {
  554:                 union {
  555:                   unsigned char *c;
  556:                   struct in6_pktinfo *p;
  557:                 } p;
  558:                 p.c = CMSG_DATA(cmptr);
  559: 		
  560: 		if_index = p.p->ipi6_ifindex;
  561:               }
  562: 	}
  563:     }
  564: #endif /* IPV6 */
  565: #endif /* Linux */
  566:  
  567:   return if_index;
  568: }
  569:       
  570: static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
  571: {
  572:   struct listener *l = NULL;
  573:   int fd = -1, tcpfd = -1, tftpfd = -1;
  574: 
  575:   if (daemon->port != 0)
  576:     {
  577:       fd = make_sock(addr, SOCK_DGRAM, dienow);
  578:       tcpfd = make_sock(addr, SOCK_STREAM, dienow);
  579:     }
  580:   
  581: #ifdef HAVE_TFTP
  582:   if (do_tftp)
  583:     {
  584:       if (addr->sa.sa_family == AF_INET)
  585: 	{
  586: 	  /* port must be restored to DNS port for TCP code */
  587: 	  short save = addr->in.sin_port;
  588: 	  addr->in.sin_port = htons(TFTP_PORT);
  589: 	  tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
  590: 	  addr->in.sin_port = save;
  591: 	}
  592: #  ifdef HAVE_IPV6
  593:       else
  594: 	{
  595: 	  short save = addr->in6.sin6_port;
  596: 	  addr->in6.sin6_port = htons(TFTP_PORT);
  597: 	  tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
  598: 	  addr->in6.sin6_port = save;
  599: 	}  
  600: #  endif
  601:     }
  602: #endif
  603: 
  604:   if (fd != -1 || tcpfd != -1 || tftpfd != -1)
  605:     {
  606:       l = safe_malloc(sizeof(struct listener));
  607:       l->next = NULL;
  608:       l->family = addr->sa.sa_family;
  609:       l->fd = fd;
  610:       l->tcpfd = tcpfd;
  611:       l->tftpfd = tftpfd;
  612:     }
  613: 
  614:   return l;
  615: }
  616: 
  617: void create_wildcard_listeners(void)
  618: {
  619:   union mysockaddr addr;
  620:   struct listener *l, *l6;
  621: 
  622:   memset(&addr, 0, sizeof(addr));
  623: #ifdef HAVE_SOCKADDR_SA_LEN
  624:   addr.in.sin_len = sizeof(addr.in);
  625: #endif
  626:   addr.in.sin_family = AF_INET;
  627:   addr.in.sin_addr.s_addr = INADDR_ANY;
  628:   addr.in.sin_port = htons(daemon->port);
  629: 
  630:   l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
  631: 
  632: #ifdef HAVE_IPV6
  633:   memset(&addr, 0, sizeof(addr));
  634: #  ifdef HAVE_SOCKADDR_SA_LEN
  635:   addr.in6.sin6_len = sizeof(addr.in6);
  636: #  endif
  637:   addr.in6.sin6_family = AF_INET6;
  638:   addr.in6.sin6_addr = in6addr_any;
  639:   addr.in6.sin6_port = htons(daemon->port);
  640:  
  641:   l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
  642:   if (l) 
  643:     l->next = l6;
  644:   else 
  645:     l = l6;
  646: #endif
  647: 
  648:   daemon->listeners = l;
  649: }
  650: 
  651: void create_bound_listeners(int dienow)
  652: {
  653:   struct listener *new;
  654:   struct irec *iface;
  655:   struct iname *if_tmp;
  656: 
  657:   for (iface = daemon->interfaces; iface; iface = iface->next)
  658:     if (!iface->done && !iface->dad && 
  659: 	(new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
  660:       {
  661: 	new->iface = iface;
  662: 	new->next = daemon->listeners;
  663: 	daemon->listeners = new;
  664: 	iface->done = 1;
  665:       }
  666: 
  667:   /* Check for --listen-address options that haven't been used because there's
  668:      no interface with a matching address. These may be valid: eg it's possible
  669:      to listen on 127.0.1.1 even if the loopback interface is 127.0.0.1
  670: 
  671:      If the address isn't valid the bind() will fail and we'll die() 
  672:      (except in bind-dynamic mode, when we'll complain but keep trying.)
  673: 
  674:      The resulting listeners have the ->iface field NULL, and this has to be
  675:      handled by the DNS and TFTP code. It disables --localise-queries processing
  676:      (no netmask) and some MTU login the tftp code. */
  677: 
  678:   for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
  679:     if (!if_tmp->used && 
  680: 	(new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
  681:       {
  682: 	new->iface = NULL;
  683: 	new->next = daemon->listeners;
  684: 	daemon->listeners = new;
  685:       }
  686: }
  687: 
  688: int is_dad_listeners(void)
  689: {
  690:   struct irec *iface;
  691:   
  692:   if (option_bool(OPT_NOWILD))
  693:     for (iface = daemon->interfaces; iface; iface = iface->next)
  694:       if (iface->dad && !iface->done)
  695: 	return 1;
  696:   
  697:   return 0;
  698: }
  699: 
  700: #ifdef HAVE_DHCP6
  701: void join_multicast(int dienow)      
  702: {
  703:   struct irec *iface, *tmp;
  704: 
  705:   for (iface = daemon->interfaces; iface; iface = iface->next)
  706:     if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
  707:       {
  708: 	/* There's an irec per address but we only want to join for multicast 
  709: 	   once per interface. Weed out duplicates. */
  710: 	for (tmp = daemon->interfaces; tmp; tmp = tmp->next)
  711: 	  if (tmp->multicast_done && tmp->index == iface->index)
  712: 	    break;
  713: 	
  714: 	iface->multicast_done = 1;
  715: 	
  716: 	if (!tmp)
  717: 	  {
  718: 	    struct ipv6_mreq mreq;
  719: 	    int err = 0;
  720: 
  721: 	    mreq.ipv6mr_interface = iface->index;
  722: 	    
  723: 	    inet_pton(AF_INET6, ALL_RELAY_AGENTS_AND_SERVERS, &mreq.ipv6mr_multiaddr);
  724: 	    
  725: 	    if (daemon->doing_dhcp6 &&
  726: 		setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
  727: 	      err = 1;
  728: 	    
  729: 	    inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
  730: 	    
  731: 	    if (daemon->doing_dhcp6 && 
  732: 		setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
  733: 	      err = 1;
  734: 	    
  735: 	    inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
  736: 	    
  737: 	    if (daemon->doing_ra &&
  738: 		setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
  739: 	      err = 1;
  740: 	    
  741: 	    if (err)
  742: 	      {
  743: 		char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
  744: 		if (dienow)
  745: 		  die(s, iface->name, EC_BADNET);
  746: 		else
  747: 		  my_syslog(LOG_ERR, s, iface->name, strerror(errno));
  748: 	      }
  749: 	  }
  750:       }
  751: }
  752: #endif
  753: 
  754: /* return a UDP socket bound to a random port, have to cope with straying into
  755:    occupied port nos and reserved ones. */
  756: int random_sock(int family)
  757: {
  758:   int fd;
  759: 
  760:   if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
  761:     {
  762:       union mysockaddr addr;
  763:       unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
  764:       int tries = ports_avail < 30 ? 3 * ports_avail : 100;
  765: 
  766:       memset(&addr, 0, sizeof(addr));
  767:       addr.sa.sa_family = family;
  768: 
  769:       /* don't loop forever if all ports in use. */
  770: 
  771:       if (fix_fd(fd))
  772: 	while(tries--)
  773: 	  {
  774: 	    unsigned short port = rand16();
  775: 	    
  776: 	    if (daemon->min_port != 0)
  777: 	      port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
  778: 	    
  779: 	    if (family == AF_INET) 
  780: 	      {
  781: 		addr.in.sin_addr.s_addr = INADDR_ANY;
  782: 		addr.in.sin_port = port;
  783: #ifdef HAVE_SOCKADDR_SA_LEN
  784: 		addr.in.sin_len = sizeof(struct sockaddr_in);
  785: #endif
  786: 	      }
  787: #ifdef HAVE_IPV6
  788: 	    else
  789: 	      {
  790: 		addr.in6.sin6_addr = in6addr_any; 
  791: 		addr.in6.sin6_port = port;
  792: #ifdef HAVE_SOCKADDR_SA_LEN
  793: 		addr.in6.sin6_len = sizeof(struct sockaddr_in6);
  794: #endif
  795: 	      }
  796: #endif
  797: 	    
  798: 	    if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
  799: 	      return fd;
  800: 	    
  801: 	    if (errno != EADDRINUSE && errno != EACCES)
  802: 	      break;
  803: 	  }
  804: 
  805:       close(fd);
  806:     }
  807: 
  808:   return -1; 
  809: }
  810:   
  811: 
  812: int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
  813: {
  814:   union mysockaddr addr_copy = *addr;
  815: 
  816:   /* cannot set source _port_ for TCP connections. */
  817:   if (is_tcp)
  818:     {
  819:       if (addr_copy.sa.sa_family == AF_INET)
  820: 	addr_copy.in.sin_port = 0;
  821: #ifdef HAVE_IPV6
  822:       else
  823: 	addr_copy.in6.sin6_port = 0;
  824: #endif
  825:     }
  826:   
  827:   if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
  828:     return 0;
  829:     
  830: #if defined(SO_BINDTODEVICE)
  831:   if (intname[0] != 0 &&
  832:       setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
  833:     return 0;
  834: #endif
  835: 
  836:   return 1;
  837: }
  838: 
  839: static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
  840: {
  841:   struct serverfd *sfd;
  842:   int errsave;
  843: 
  844:   /* when using random ports, servers which would otherwise use
  845:      the INADDR_ANY/port0 socket have sfd set to NULL */
  846:   if (!daemon->osport && intname[0] == 0)
  847:     {
  848:       errno = 0;
  849:       
  850:       if (addr->sa.sa_family == AF_INET &&
  851: 	  addr->in.sin_addr.s_addr == INADDR_ANY &&
  852: 	  addr->in.sin_port == htons(0)) 
  853: 	return NULL;
  854: 
  855: #ifdef HAVE_IPV6
  856:       if (addr->sa.sa_family == AF_INET6 &&
  857: 	  memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
  858: 	  addr->in6.sin6_port == htons(0)) 
  859: 	return NULL;
  860: #endif
  861:     }
  862:       
  863:   /* may have a suitable one already */
  864:   for (sfd = daemon->sfds; sfd; sfd = sfd->next )
  865:     if (sockaddr_isequal(&sfd->source_addr, addr) &&
  866: 	strcmp(intname, sfd->interface) == 0)
  867:       return sfd;
  868:   
  869:   /* need to make a new one. */
  870:   errno = ENOMEM; /* in case malloc fails. */
  871:   if (!(sfd = whine_malloc(sizeof(struct serverfd))))
  872:     return NULL;
  873:   
  874:   if ((sfd->fd = socket(addr->sa.sa_family, SOCK_DGRAM, 0)) == -1)
  875:     {
  876:       free(sfd);
  877:       return NULL;
  878:     }
  879:   
  880:   if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
  881:     { 
  882:       errsave = errno; /* save error from bind. */
  883:       close(sfd->fd);
  884:       free(sfd);
  885:       errno = errsave;
  886:       return NULL;
  887:     }
  888:     
  889:   strcpy(sfd->interface, intname); 
  890:   sfd->source_addr = *addr;
  891:   sfd->next = daemon->sfds;
  892:   daemon->sfds = sfd;
  893:   return sfd; 
  894: }
  895: 
  896: /* create upstream sockets during startup, before root is dropped which may be needed
  897:    this allows query_port to be a low port and interface binding */
  898: void pre_allocate_sfds(void)
  899: {
  900:   struct server *srv;
  901:   
  902:   if (daemon->query_port != 0)
  903:     {
  904:       union  mysockaddr addr;
  905:       memset(&addr, 0, sizeof(addr));
  906:       addr.in.sin_family = AF_INET;
  907:       addr.in.sin_addr.s_addr = INADDR_ANY;
  908:       addr.in.sin_port = htons(daemon->query_port);
  909: #ifdef HAVE_SOCKADDR_SA_LEN
  910:       addr.in.sin_len = sizeof(struct sockaddr_in);
  911: #endif
  912:       allocate_sfd(&addr, "");
  913: #ifdef HAVE_IPV6
  914:       memset(&addr, 0, sizeof(addr));
  915:       addr.in6.sin6_family = AF_INET6;
  916:       addr.in6.sin6_addr = in6addr_any;
  917:       addr.in6.sin6_port = htons(daemon->query_port);
  918: #ifdef HAVE_SOCKADDR_SA_LEN
  919:       addr.in6.sin6_len = sizeof(struct sockaddr_in6);
  920: #endif
  921:       allocate_sfd(&addr, "");
  922: #endif
  923:     }
  924:   
  925:   for (srv = daemon->servers; srv; srv = srv->next)
  926:     if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
  927: 	!allocate_sfd(&srv->source_addr, srv->interface) &&
  928: 	errno != 0 &&
  929: 	option_bool(OPT_NOWILD))
  930:       {
  931: 	prettyprint_addr(&srv->source_addr, daemon->namebuff);
  932: 	if (srv->interface[0] != 0)
  933: 	  {
  934: 	    strcat(daemon->namebuff, " ");
  935: 	    strcat(daemon->namebuff, srv->interface);
  936: 	  }
  937: 	die(_("failed to bind server socket for %s: %s"),
  938: 	    daemon->namebuff, EC_BADNET);
  939:       }  
  940: }
  941: 
  942: 
  943: void check_servers(void)
  944: {
  945:   struct irec *iface;
  946:   struct server *new, *tmp, *ret = NULL;
  947:   int port = 0;
  948: 
  949:   /* interface may be new since startup */
  950:   if (!option_bool(OPT_NOWILD))
  951:     enumerate_interfaces();
  952:   
  953:   for (new = daemon->servers; new; new = tmp)
  954:     {
  955:       tmp = new->next;
  956:       
  957:       if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
  958: 	{
  959: 	  port = prettyprint_addr(&new->addr, daemon->namebuff);
  960: 
  961: 	  /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
  962: 	  if (new->addr.sa.sa_family == AF_INET &&
  963: 	      new->addr.in.sin_addr.s_addr == 0)
  964: 	    {
  965: 	      free(new);
  966: 	      continue;
  967: 	    }
  968: 
  969: 	  for (iface = daemon->interfaces; iface; iface = iface->next)
  970: 	    if (sockaddr_isequal(&new->addr, &iface->addr))
  971: 	      break;
  972: 	  if (iface)
  973: 	    {
  974: 	      my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
  975: 	      free(new);
  976: 	      continue;
  977: 	    }
  978: 	  
  979: 	  /* Do we need a socket set? */
  980: 	  if (!new->sfd && 
  981: 	      !(new->sfd = allocate_sfd(&new->source_addr, new->interface)) &&
  982: 	      errno != 0)
  983: 	    {
  984: 	      my_syslog(LOG_WARNING, 
  985: 			_("ignoring nameserver %s - cannot make/bind socket: %s"),
  986: 			daemon->namebuff, strerror(errno));
  987: 	      free(new);
  988: 	      continue;
  989: 	    }
  990: 	}
  991:       
  992:       /* reverse order - gets it right. */
  993:       new->next = ret;
  994:       ret = new;
  995:       
  996:       if (!(new->flags & SERV_NO_REBIND))
  997: 	{
  998: 	  if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
  999: 	    {
 1000: 	      char *s1, *s2;
 1001: 	      if (!(new->flags & SERV_HAS_DOMAIN))
 1002: 		s1 = _("unqualified"), s2 = _("names");
 1003: 	      else if (strlen(new->domain) == 0)
 1004: 		s1 = _("default"), s2 = "";
 1005: 	      else
 1006: 		s1 = _("domain"), s2 = new->domain;
 1007: 	      
 1008: 	      if (new->flags & SERV_NO_ADDR)
 1009: 		my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
 1010: 	      else if (new->flags & SERV_USE_RESOLV)
 1011: 		my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
 1012: 	      else if (!(new->flags & SERV_LITERAL_ADDRESS))
 1013: 		my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
 1014: 	    }
 1015: 	  else if (new->interface[0] != 0)
 1016: 	    my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface); 
 1017: 	  else
 1018: 	    my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port); 
 1019: 	}
 1020:     }
 1021:   
 1022:   daemon->servers = ret;
 1023: }
 1024: 
 1025: /* Return zero if no servers found, in that case we keep polling.
 1026:    This is a protection against an update-time/write race on resolv.conf */
 1027: int reload_servers(char *fname)
 1028: {
 1029:   FILE *f;
 1030:   char *line;
 1031:   struct server *old_servers = NULL;
 1032:   struct server *new_servers = NULL;
 1033:   struct server *serv;
 1034:   int gotone = 0;
 1035: 
 1036:   /* buff happens to be MAXDNAME long... */
 1037:   if (!(f = fopen(fname, "r")))
 1038:     {
 1039:       my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
 1040:       return 0;
 1041:     }
 1042:   
 1043:   /* move old servers to free list - we can reuse the memory 
 1044:      and not risk malloc if there are the same or fewer new servers. 
 1045:      Servers which were specced on the command line go to the new list. */
 1046:   for (serv = daemon->servers; serv;)
 1047:     {
 1048:       struct server *tmp = serv->next;
 1049:       if (serv->flags & SERV_FROM_RESOLV)
 1050: 	{
 1051: 	  serv->next = old_servers;
 1052: 	  old_servers = serv; 
 1053: 	  /* forward table rules reference servers, so have to blow them away */
 1054: 	  server_gone(serv);
 1055: 	}
 1056:       else
 1057: 	{
 1058: 	  serv->next = new_servers;
 1059: 	  new_servers = serv;
 1060: 	}
 1061:       serv = tmp;
 1062:     }
 1063:   
 1064:   while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
 1065:     {
 1066:       union mysockaddr addr, source_addr;
 1067:       char *token = strtok(line, " \t\n\r");
 1068:       
 1069:       if (!token)
 1070: 	continue;
 1071:       if (strcmp(token, "nameserver") != 0 && strcmp(token, "server") != 0)
 1072: 	continue;
 1073:       if (!(token = strtok(NULL, " \t\n\r")))
 1074: 	continue;
 1075:       
 1076:       memset(&addr, 0, sizeof(addr));
 1077:       memset(&source_addr, 0, sizeof(source_addr));
 1078:       
 1079:       if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
 1080: 	{
 1081: #ifdef HAVE_SOCKADDR_SA_LEN
 1082: 	  source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
 1083: #endif
 1084: 	  source_addr.in.sin_family = addr.in.sin_family = AF_INET;
 1085: 	  addr.in.sin_port = htons(NAMESERVER_PORT);
 1086: 	  source_addr.in.sin_addr.s_addr = INADDR_ANY;
 1087: 	  source_addr.in.sin_port = htons(daemon->query_port);
 1088: 	}
 1089: #ifdef HAVE_IPV6
 1090:       else 
 1091: 	{	
 1092: 	  int scope_index = 0;
 1093: 	  char *scope_id = strchr(token, '%');
 1094: 	  
 1095: 	  if (scope_id)
 1096: 	    {
 1097: 	      *(scope_id++) = 0;
 1098: 	      scope_index = if_nametoindex(scope_id);
 1099: 	    }
 1100: 	  
 1101: 	  if (inet_pton(AF_INET6, token, &addr.in6.sin6_addr) > 0)
 1102: 	    {
 1103: #ifdef HAVE_SOCKADDR_SA_LEN
 1104: 	      source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(source_addr.in6);
 1105: #endif
 1106: 	      source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
 1107: 	      source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
 1108: 	      addr.in6.sin6_port = htons(NAMESERVER_PORT);
 1109: 	      addr.in6.sin6_scope_id = scope_index;
 1110: 	      source_addr.in6.sin6_addr = in6addr_any;
 1111: 	      source_addr.in6.sin6_port = htons(daemon->query_port);
 1112: 	      source_addr.in6.sin6_scope_id = 0;
 1113: 	    }
 1114: 	  else
 1115: 	    continue;
 1116: 	}
 1117: #else /* IPV6 */
 1118:       else
 1119: 	continue;
 1120: #endif 
 1121: 
 1122:       if (old_servers)
 1123: 	{
 1124: 	  serv = old_servers;
 1125: 	  old_servers = old_servers->next;
 1126: 	}
 1127:       else if (!(serv = whine_malloc(sizeof (struct server))))
 1128: 	continue;
 1129:       
 1130:       /* this list is reverse ordered: 
 1131: 	 it gets reversed again in check_servers */
 1132:       serv->next = new_servers;
 1133:       new_servers = serv;
 1134:       serv->addr = addr;
 1135:       serv->source_addr = source_addr;
 1136:       serv->domain = NULL;
 1137:       serv->interface[0] = 0;
 1138:       serv->sfd = NULL;
 1139:       serv->flags = SERV_FROM_RESOLV;
 1140:       serv->queries = serv->failed_queries = 0;
 1141:       gotone = 1;
 1142:     }
 1143:   
 1144:   /* Free any memory not used. */
 1145:   while (old_servers)
 1146:     {
 1147:       struct server *tmp = old_servers->next;
 1148:       free(old_servers);
 1149:       old_servers = tmp;
 1150:     }
 1151: 
 1152:   daemon->servers = new_servers;
 1153:   fclose(f);
 1154: 
 1155:   return gotone;
 1156: }
 1157: 
 1158: 
 1159: /* Use an IPv4 listener socket for ioctling */
 1160: struct in_addr get_ifaddr(char *intr)
 1161: {
 1162:   struct listener *l;
 1163:   struct ifreq ifr;
 1164:   struct sockaddr_in ret;
 1165:   
 1166:   ret.sin_addr.s_addr = -1;
 1167: 
 1168:   for (l = daemon->listeners; 
 1169:        l && (l->family != AF_INET || l->fd == -1);
 1170:        l = l->next);
 1171:   
 1172:   strncpy(ifr.ifr_name, intr, IF_NAMESIZE);
 1173:   ifr.ifr_addr.sa_family = AF_INET;
 1174:   
 1175:   if (l &&  ioctl(l->fd, SIOCGIFADDR, &ifr) != -1)
 1176:     memcpy(&ret, &ifr.ifr_addr, sizeof(ret)); 
 1177:   
 1178:   return ret.sin_addr;
 1179: }
 1180: 
 1181: 
 1182: 

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