Diff for /embedaddon/dnsmasq/src/network.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2016/11/02 09:57:01 version 1.1.1.4, 2021/03/17 00:56:46
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
   
    This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
Line 29  int indextoname(int fd, int index, char *name) Line 29  int indextoname(int fd, int index, char *name)
   if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)    if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
     return 0;      return 0;
   
  strncpy(name, ifr.ifr_name, IF_NAMESIZE);  safe_strncpy(name, ifr.ifr_name, IF_NAMESIZE);
   
   return 1;    return 1;
 }  }
Line 82  int indextoname(int fd, int index, char *name) Line 82  int indextoname(int fd, int index, char *name)
   for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++)     for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++) 
     {      {
       struct lifreq lifr;        struct lifreq lifr;
      strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);      safe_strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
       if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)         if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0) 
         return 0;          return 0;
               
       if (lifr.lifr_index == index) {        if (lifr.lifr_index == index) {
        strncpy(name, lifr.lifr_name, IF_NAMESIZE);        safe_strncpy(name, lifr.lifr_name, IF_NAMESIZE);
         return 1;          return 1;
       }        }
     }      }
Line 109  int indextoname(int fd, int index, char *name) Line 109  int indextoname(int fd, int index, char *name)
   
 #endif  #endif
   
int iface_check(int family, struct all_addr *addr, char *name, int *auth)int iface_check(int family, union all_addr *addr, char *name, int *auth)
 {  {
   struct iname *tmp;    struct iname *tmp;
   int ret = 1, match_addr = 0;    int ret = 1, match_addr = 0;
Line 135  int iface_check(int family, struct all_addr *addr, cha Line 135  int iface_check(int family, struct all_addr *addr, cha
           if (tmp->addr.sa.sa_family == family)            if (tmp->addr.sa.sa_family == family)
             {              {
               if (family == AF_INET &&                if (family == AF_INET &&
                  tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)                  tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
                 ret = match_addr = tmp->used = 1;                  ret = match_addr = tmp->used = 1;
 #ifdef HAVE_IPV6  
               else if (family == AF_INET6 &&                else if (family == AF_INET6 &&
                        IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,                          IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, 
                                          &addr->addr.addr6))                                          &addr->addr6))
                 ret = match_addr = tmp->used = 1;                  ret = match_addr = tmp->used = 1;
 #endif  
             }                        }          
     }      }
       
Line 160  int iface_check(int family, struct all_addr *addr, cha Line 158  int iface_check(int family, struct all_addr *addr, cha
           break;            break;
       }        }
     else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&      else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
             tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)             tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
       break;        break;
 #ifdef HAVE_IPV6  
     else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&      else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
             IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))             IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr6))
       break;        break;
 #endif        
   
   if (tmp && auth)     if (tmp && auth) 
     {      {
Line 178  int iface_check(int family, struct all_addr *addr, cha Line 174  int iface_check(int family, struct all_addr *addr, cha
 }  }
   
   
/* Fix for problem that the kernel sometimes reports the loopback inerface as the/* Fix for problem that the kernel sometimes reports the loopback interface as the
    arrival interface when a packet originates locally, even when sent to address of      arrival interface when a packet originates locally, even when sent to address of 
    an interface other than the loopback. Accept packet if it arrived via a loopback      an interface other than the loopback. Accept packet if it arrived via a loopback 
    interface, even when we're not accepting packets that way, as long as the destination     interface, even when we're not accepting packets that way, as long as the destination
    address is one we're believing. Interface list must be up-to-date before calling. */     address is one we're believing. Interface list must be up-to-date before calling. */
int loopback_exception(int fd, int family, struct all_addr *addr, char *name)    int loopback_exception(int fd, int family, union all_addr *addr, char *name)    
 {  {
   struct ifreq ifr;    struct ifreq ifr;
   struct irec *iface;    struct irec *iface;
   
  strncpy(ifr.ifr_name, name, IF_NAMESIZE);  safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE);
   if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&    if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
       ifr.ifr_flags & IFF_LOOPBACK)        ifr.ifr_flags & IFF_LOOPBACK)
     {      {
Line 197  int loopback_exception(int fd, int family, struct all_ Line 193  int loopback_exception(int fd, int family, struct all_
           {            {
             if (family == AF_INET)              if (family == AF_INET)
               {                {
                if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)                if (iface->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
                   return 1;                    return 1;
               }                }
#ifdef HAVE_IPV6            else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr6))
            else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6)) 
               return 1;                return 1;
 #endif  
               
           }            }
     }      }
   return 0;    return 0;
Line 214  int loopback_exception(int fd, int family, struct all_ Line 207  int loopback_exception(int fd, int family, struct all_
    on the relevant address, but the name of the arrival interface, derived from the     on the relevant address, but the name of the arrival interface, derived from the
    index won't match the config. Check that we found an interface address for the arrival      index won't match the config. Check that we found an interface address for the arrival 
    interface: daemon->interfaces must be up-to-date. */     interface: daemon->interfaces must be up-to-date. */
int label_exception(int index, int family, struct all_addr *addr)int label_exception(int index, int family, union all_addr *addr)
 {  {
   struct irec *iface;    struct irec *iface;
   
Line 224  int label_exception(int index, int family, struct all_ Line 217  int label_exception(int index, int family, struct all_
   
   for (iface = daemon->interfaces; iface; iface = iface->next)    for (iface = daemon->interfaces; iface; iface = iface->next)
     if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&      if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
        iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)        iface->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
       return 1;        return 1;
   
   return 0;    return 0;
Line 244  static int iface_allowed(struct iface_param *param, in Line 237  static int iface_allowed(struct iface_param *param, in
   int tftp_ok = !!option_bool(OPT_TFTP);    int tftp_ok = !!option_bool(OPT_TFTP);
   int dhcp_ok = 1;    int dhcp_ok = 1;
   int auth_dns = 0;    int auth_dns = 0;
     int is_label = 0;
 #if defined(HAVE_DHCP) || defined(HAVE_TFTP)  #if defined(HAVE_DHCP) || defined(HAVE_TFTP)
   struct iname *tmp;    struct iname *tmp;
 #endif  #endif
Line 264  static int iface_allowed(struct iface_param *param, in Line 258  static int iface_allowed(struct iface_param *param, in
       
   if (!label)    if (!label)
     label = ifr.ifr_name;      label = ifr.ifr_name;
     else
       is_label = strcmp(label, ifr.ifr_name);
     
   /* maintain a list of all addresses on all interfaces for --local-service option */    /* maintain a list of all addresses on all interfaces for --local-service option */
   if (option_bool(OPT_LOCAL_SERVICE))    if (option_bool(OPT_LOCAL_SERVICE))
Line 286  static int iface_allowed(struct iface_param *param, in Line 282  static int iface_allowed(struct iface_param *param, in
                       
           if (addr->sa.sa_family == AF_INET)            if (addr->sa.sa_family == AF_INET)
             {              {
              al->addr.addr.addr4 = addr->in.sin_addr;              al->addr.addr4 = addr->in.sin_addr;
               al->flags = 0;                al->flags = 0;
             }              }
 #ifdef HAVE_IPV6  
           else            else
             {              {
              al->addr.addr.addr6 = addr->in6.sin6_addr;              al->addr.addr6 = addr->in6.sin6_addr;
               al->flags = ADDRLIST_IPV6;                al->flags = ADDRLIST_IPV6;
             }               } 
 #endif  
         }          }
     }      }
       
 #ifdef HAVE_IPV6  
   if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))    if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
 #endif  
     {      {
       struct interface_name *int_name;        struct interface_name *int_name;
       struct addrlist *al;        struct addrlist *al;
Line 329  static int iface_allowed(struct iface_param *param, in Line 321  static int iface_allowed(struct iface_param *param, in
                       al->next = zone->subnet;                        al->next = zone->subnet;
                       zone->subnet = al;                        zone->subnet = al;
                       al->prefixlen = prefixlen;                        al->prefixlen = prefixlen;
                      al->addr.addr.addr4 = addr->in.sin_addr;                      al->addr.addr4 = addr->in.sin_addr;
                       al->flags = 0;                        al->flags = 0;
                     }                      }
                 }                  }
                               
 #ifdef HAVE_IPV6  
               if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))                if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
                 {                  {
                   if (param->spare)                    if (param->spare)
Line 350  static int iface_allowed(struct iface_param *param, in Line 341  static int iface_allowed(struct iface_param *param, in
                       al->next = zone->subnet;                        al->next = zone->subnet;
                       zone->subnet = al;                        zone->subnet = al;
                       al->prefixlen = prefixlen;                        al->prefixlen = prefixlen;
                      al->addr.addr.addr6 = addr->in6.sin6_addr;                      al->addr.addr6 = addr->in6.sin6_addr;
                       al->flags = ADDRLIST_IPV6;                        al->flags = ADDRLIST_IPV6;
                     }                      }
                 }                   } 
 #endif  
                 
             }              }
 #endif  #endif
                 
Line 380  static int iface_allowed(struct iface_param *param, in Line 369  static int iface_allowed(struct iface_param *param, in
                                   
                 if (addr->sa.sa_family == AF_INET)                  if (addr->sa.sa_family == AF_INET)
                   {                    {
                    al->addr.addr.addr4 = addr->in.sin_addr;                    al->addr.addr4 = addr->in.sin_addr;
                     al->flags = 0;                      al->flags = 0;
                   }                    }
 #ifdef HAVE_IPV6  
                 else                  else
                  {                   {
                    al->addr.addr.addr6 = addr->in6.sin6_addr;                    al->addr.addr6 = addr->in6.sin6_addr;
                     al->flags = ADDRLIST_IPV6;                      al->flags = ADDRLIST_IPV6;
                     /* Privacy addresses and addresses still undergoing DAD and deprecated addresses                      /* Privacy addresses and addresses still undergoing DAD and deprecated addresses
                        don't appear in forward queries, but will in reverse ones. */                         don't appear in forward queries, but will in reverse ones. */
                     if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))                      if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
                       al->flags |= ADDRLIST_REVONLY;                        al->flags |= ADDRLIST_REVONLY;
                  }                    } 
 #endif  
               }                }
           }            }
     }      }
Line 401  static int iface_allowed(struct iface_param *param, in Line 388  static int iface_allowed(struct iface_param *param, in
   /* check whether the interface IP has been added already     /* check whether the interface IP has been added already 
      we call this routine multiple times. */       we call this routine multiple times. */
   for (iface = daemon->interfaces; iface; iface = iface->next)     for (iface = daemon->interfaces; iface; iface = iface->next) 
    if (sockaddr_isequal(&iface->addr, addr))    if (sockaddr_isequal(&iface->addr, addr) && iface->index == if_index)
       {        {
         iface->dad = !!(iface_flags & IFACE_TENTATIVE);          iface->dad = !!(iface_flags & IFACE_TENTATIVE);
         iface->found = 1; /* for garbage collection */          iface->found = 1; /* for garbage collection */
           iface->netmask = netmask;
         return 1;          return 1;
       }        }
   
Line 432  static int iface_allowed(struct iface_param *param, in Line 420  static int iface_allowed(struct iface_param *param, in
     }      }
       
   if (addr->sa.sa_family == AF_INET &&    if (addr->sa.sa_family == AF_INET &&
      !iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))      !iface_check(AF_INET, (union all_addr *)&addr->in.sin_addr, label, &auth_dns))
     return 1;      return 1;
   
 #ifdef HAVE_IPV6  
   if (addr->sa.sa_family == AF_INET6 &&    if (addr->sa.sa_family == AF_INET6 &&
      !iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns))      !iface_check(AF_INET6, (union all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
     return 1;      return 1;
 #endif  
           
 #ifdef HAVE_DHCP  #ifdef HAVE_DHCP
   /* No DHCP where we're doing auth DNS. */    /* No DHCP where we're doing auth DNS. */
Line 482  static int iface_allowed(struct iface_param *param, in Line 468  static int iface_allowed(struct iface_param *param, in
       iface->found = 1;        iface->found = 1;
       iface->done = iface->multicast_done = iface->warned = 0;        iface->done = iface->multicast_done = iface->warned = 0;
       iface->index = if_index;        iface->index = if_index;
         iface->label = is_label;
       if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))        if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
         {          {
           strcpy(iface->name, ifr.ifr_name);            strcpy(iface->name, ifr.ifr_name);
Line 497  static int iface_allowed(struct iface_param *param, in Line 484  static int iface_allowed(struct iface_param *param, in
   return 0;    return 0;
 }  }
   
 #ifdef HAVE_IPV6  
 static int iface_allowed_v6(struct in6_addr *local, int prefix,   static int iface_allowed_v6(struct in6_addr *local, int prefix, 
                             int scope, int if_index, int flags,                               int scope, int if_index, int flags, 
                             int preferred, int valid, void *vparam)                              int preferred, int valid, void *vparam)
Line 525  static int iface_allowed_v6(struct in6_addr *local, in Line 511  static int iface_allowed_v6(struct in6_addr *local, in
       
   return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);    return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
 }  }
 #endif  
   
 static int iface_allowed_v4(struct in_addr local, int if_index, char *label,  static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
                             struct in_addr netmask, struct in_addr broadcast, void *vparam)                              struct in_addr netmask, struct in_addr broadcast, void *vparam)
Line 548  static int iface_allowed_v4(struct in_addr local, int  Line 533  static int iface_allowed_v4(struct in_addr local, int 
   
   return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);    return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
 }  }
   
 /*
  * Clean old interfaces no longer found.
  */
 static void clean_interfaces()
 {
   struct irec *iface;
   struct irec **up = &daemon->interfaces;
 
   for (iface = *up; iface; iface = *up)
   {
     if (!iface->found && !iface->done)
       {
         *up = iface->next;
         free(iface->name);
         free(iface);
       }
     else
       {
         up = &iface->next;
       }
   }
 }
 
 /** Release listener if no other interface needs it.
  *
  * @return 1 if released, 0 if still required
  */
 static int release_listener(struct listener *l)
 {
   if (l->used > 1)
     {
       struct irec *iface;
       for (iface = daemon->interfaces; iface; iface = iface->next)
         if (iface->done && sockaddr_isequal(&l->addr, &iface->addr))
           {
             if (iface->found)
               {
                 /* update listener to point to active interface instead */
                 if (!l->iface->found)
                   l->iface = iface;
               }
             else
               {
                 l->used--;
                 iface->done = 0;
               }
           }
 
       /* Someone is still using this listener, skip its deletion */
       if (l->used > 0)
         return 0;
     }
 
   if (l->iface->done)
     {
       int port;
 
       port = prettyprint_addr(&l->iface->addr, daemon->addrbuff);
       my_syslog(LOG_DEBUG, _("stopped listening on %s(#%d): %s port %d"),
                 l->iface->name, l->iface->index, daemon->addrbuff, port);
       /* In case it ever returns */
       l->iface->done = 0;
     }
 
   if (l->fd != -1)
     close(l->fd);
   if (l->tcpfd != -1)
     close(l->tcpfd);
   if (l->tftpfd != -1)
     close(l->tftpfd);
 
   free(l);
   return 1;
 }
 
 int enumerate_interfaces(int reset)  int enumerate_interfaces(int reset)
 {  {
   static struct addrlist *spare = NULL;    static struct addrlist *spare = NULL;
Line 629  int enumerate_interfaces(int reset) Line 689  int enumerate_interfaces(int reset)
   
   param.spare = spare;    param.spare = spare;
       
 #ifdef HAVE_IPV6  
   ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);    ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
 #endif  
   
   if (ret)    if (ret)
     ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);       ret = iface_enumerate(AF_INET, &param, iface_allowed_v4); 
Line 644  int enumerate_interfaces(int reset) Line 702  int enumerate_interfaces(int reset)
       /* Garbage-collect listeners listening on addresses that no longer exist.        /* Garbage-collect listeners listening on addresses that no longer exist.
          Does nothing when not binding interfaces or for listeners on localhost,            Does nothing when not binding interfaces or for listeners on localhost, 
          since the ->iface field is NULL. Note that this needs the protections           since the ->iface field is NULL. Note that this needs the protections
         against re-entrancy, hence it's here.  It also means there's a possibility,         against reentrancy, hence it's here.  It also means there's a possibility,
          in OPT_CLEVERBIND mode, that at listener will just disappear after           in OPT_CLEVERBIND mode, that at listener will just disappear after
          a call to enumerate_interfaces, this is checked OK on all calls. */           a call to enumerate_interfaces, this is checked OK on all calls. */
       struct listener *l, *tmp, **up;        struct listener *l, *tmp, **up;
         int freed = 0;
               
       for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)        for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
         {          {
Line 655  int enumerate_interfaces(int reset) Line 714  int enumerate_interfaces(int reset)
                       
           if (!l->iface || l->iface->found)            if (!l->iface || l->iface->found)
             up = &l->next;              up = &l->next;
          else          else if (release_listener(l))
             {              {
              *up = l->next;              *up = tmp;
                            freed = 1;
              /* In case it ever returns */ 
              l->iface->done = 0; 
               
              if (l->fd != -1) 
                close(l->fd); 
              if (l->tcpfd != -1) 
                close(l->tcpfd); 
              if (l->tftpfd != -1) 
                close(l->tftpfd); 
               
              free(l); 
             }              }
         }          }
   
         if (freed)
           clean_interfaces();
     }      }
  
   errno = errsave;    errno = errsave;
   spare = param.spare;    spare = param.spare;
           
Line 699  static int make_sock(union mysockaddr *addr, int type, Line 750  static int make_sock(union mysockaddr *addr, int type,
       
   if ((fd = socket(family, type, 0)) == -1)    if ((fd = socket(family, type, 0)) == -1)
     {      {
      int port, errsav;      int port, errsave;
       char *s;        char *s;
   
       /* No error if the kernel just doesn't support this IP flavour */        /* No error if the kernel just doesn't support this IP flavour */
Line 709  static int make_sock(union mysockaddr *addr, int type, Line 760  static int make_sock(union mysockaddr *addr, int type,
         return -1;          return -1;
               
     err:      err:
      errsav = errno;      errsave = errno;
       port = prettyprint_addr(addr, daemon->addrbuff);        port = prettyprint_addr(addr, daemon->addrbuff);
       if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))        if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
         sprintf(daemon->addrbuff, "port %d", port);          sprintf(daemon->addrbuff, "port %d", port);
Line 718  static int make_sock(union mysockaddr *addr, int type, Line 769  static int make_sock(union mysockaddr *addr, int type,
       if (fd != -1)        if (fd != -1)
         close (fd);          close (fd);
                   
      errno = errsav;      errno = errsave;
   
       if (dienow)        if (dienow)
         {          {
Line 736  static int make_sock(union mysockaddr *addr, int type, Line 787  static int make_sock(union mysockaddr *addr, int type,
   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
     goto err;      goto err;
       
 #ifdef HAVE_IPV6  
   if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)    if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
     goto err;      goto err;
 #endif  
       
   if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)    if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
     goto err;      goto err;
       
   if (type == SOCK_STREAM)    if (type == SOCK_STREAM)
     {      {
      if (listen(fd, 5) == -1)#ifdef TCP_FASTOPEN
       int qlen = 5;                           
       setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
 #endif
       
       if (listen(fd, TCP_BACKLOG) == -1)
         goto err;          goto err;
     }      }
   else if (family == AF_INET)    else if (family == AF_INET)
Line 763  static int make_sock(union mysockaddr *addr, int type, Line 817  static int make_sock(union mysockaddr *addr, int type,
 #endif  #endif
         }          }
     }      }
 #ifdef HAVE_IPV6  
   else if (!set_ipv6pktinfo(fd))    else if (!set_ipv6pktinfo(fd))
     goto err;      goto err;
 #endif  
       
   return fd;    return fd;
 }  }
   
 #ifdef HAVE_IPV6    
 int set_ipv6pktinfo(int fd)  int set_ipv6pktinfo(int fd)
 {  {
   int opt = 1;    int opt = 1;
Line 798  int set_ipv6pktinfo(int fd) Line 849  int set_ipv6pktinfo(int fd)
   
   return 0;    return 0;
 }  }
 #endif  
   
   
 /* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */  /* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
 int tcp_interface(int fd, int af)  int tcp_interface(int fd, int af)
 {   { 
     (void)fd; /* suppress potential unused warning */
     (void)af; /* suppress potential unused warning */
   int if_index = 0;    int if_index = 0;
   
 #ifdef HAVE_LINUX_NETWORK  #ifdef HAVE_LINUX_NETWORK
Line 838  int tcp_interface(int fd, int af) Line 890  int tcp_interface(int fd, int af)
               }                }
         }          }
     }      }
 #ifdef HAVE_IPV6  
   else    else
     {      {
       /* Only the RFC-2292 API has the ability to find the interface for TCP connections,        /* Only the RFC-2292 API has the ability to find the interface for TCP connections,
Line 870  int tcp_interface(int fd, int af) Line 921  int tcp_interface(int fd, int af)
               }                }
         }          }
     }      }
 #endif /* IPV6 */  
 #endif /* Linux */  #endif /* Linux */
     
   return if_index;    return if_index;
Line 900  static struct listener *create_listeners(union mysocka Line 950  static struct listener *create_listeners(union mysocka
           tftpfd = make_sock(addr, SOCK_DGRAM, dienow);            tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
           addr->in.sin_port = save;            addr->in.sin_port = save;
         }          }
 #  ifdef HAVE_IPV6  
       else        else
         {          {
           short save = addr->in6.sin6_port;            short save = addr->in6.sin6_port;
Line 908  static struct listener *create_listeners(union mysocka Line 957  static struct listener *create_listeners(union mysocka
           tftpfd = make_sock(addr, SOCK_DGRAM, dienow);            tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
           addr->in6.sin6_port = save;            addr->in6.sin6_port = save;
         }            }  
 #  endif  
     }      }
 #endif  #endif
   
Line 916  static struct listener *create_listeners(union mysocka Line 964  static struct listener *create_listeners(union mysocka
     {      {
       l = safe_malloc(sizeof(struct listener));        l = safe_malloc(sizeof(struct listener));
       l->next = NULL;        l->next = NULL;
       l->family = addr->sa.sa_family;  
       l->fd = fd;        l->fd = fd;
       l->tcpfd = tcpfd;        l->tcpfd = tcpfd;
      l->tftpfd = tftpfd;             l->tftpfd = tftpfd;
       l->addr = *addr;
       l->used = 1;
       l->iface = NULL;        l->iface = NULL;
     }      }
   
Line 941  void create_wildcard_listeners(void) Line 990  void create_wildcard_listeners(void)
   
   l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);    l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
   
 #ifdef HAVE_IPV6  
   memset(&addr, 0, sizeof(addr));    memset(&addr, 0, sizeof(addr));
#  ifdef HAVE_SOCKADDR_SA_LEN#ifdef HAVE_SOCKADDR_SA_LEN
   addr.in6.sin6_len = sizeof(addr.in6);    addr.in6.sin6_len = sizeof(addr.in6);
#  endif#endif
   addr.in6.sin6_family = AF_INET6;    addr.in6.sin6_family = AF_INET6;
   addr.in6.sin6_addr = in6addr_any;    addr.in6.sin6_addr = in6addr_any;
   addr.in6.sin6_port = htons(daemon->port);    addr.in6.sin6_port = htons(daemon->port);
Line 955  void create_wildcard_listeners(void) Line 1003  void create_wildcard_listeners(void)
     l->next = l6;      l->next = l6;
   else     else 
     l = l6;      l = l6;
 #endif  
   
   daemon->listeners = l;    daemon->listeners = l;
 }  }
   
   static struct listener *find_listener(union mysockaddr *addr)
   {
     struct listener *l;
     for (l = daemon->listeners; l; l = l->next)
       if (sockaddr_isequal(&l->addr, addr))
         return l;
     return NULL;
   }
   
 void create_bound_listeners(int dienow)  void create_bound_listeners(int dienow)
 {  {
   struct listener *new;    struct listener *new;
   struct irec *iface;    struct irec *iface;
   struct iname *if_tmp;    struct iname *if_tmp;
     struct listener *existing;
   
   for (iface = daemon->interfaces; iface; iface = iface->next)    for (iface = daemon->interfaces; iface; iface = iface->next)
    if (!iface->done && !iface->dad && iface->found &&    if (!iface->done && !iface->dad && iface->found)
        (new = create_listeners(&iface->addr, iface->tftp_ok, dienow))) 
       {        {
        new->iface = iface;        existing = find_listener(&iface->addr);
        new->next = daemon->listeners;        if (existing)
        daemon->listeners = new;          {
        iface->done = 1;            iface->done = 1;
             existing->used++; /* increase usage counter */
           }
         else if ((new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
           {
             new->iface = iface;
             new->next = daemon->listeners;
             daemon->listeners = new;
             iface->done = 1;
 
             /* Don't log the initial set of listen addresses created
                at startup, since this is happening before the logging
                system is initialised and the sign-on printed. */
             if (!dienow)
               {
                 int port = prettyprint_addr(&iface->addr, daemon->addrbuff);
                 my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s port %d"),
                           iface->name, iface->index, daemon->addrbuff, port);
               }
           }
       }        }
   
   /* Check for --listen-address options that haven't been used because there's    /* Check for --listen-address options that haven't been used because there's
Line 993  void create_bound_listeners(int dienow) Line 1068  void create_bound_listeners(int dienow)
       {        {
         new->next = daemon->listeners;          new->next = daemon->listeners;
         daemon->listeners = new;          daemon->listeners = new;
   
           if (!dienow)
             {
               int port = prettyprint_addr(&if_tmp->addr, daemon->addrbuff);
               my_syslog(LOG_DEBUG, _("listening on %s port %d"), daemon->addrbuff, port);
             }
       }        }
 }  }
   
Line 1034  void warn_bound_listeners(void) Line 1115  void warn_bound_listeners(void)
     my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"));       my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)")); 
 }  }
   
   void warn_wild_labels(void)
   {
     struct irec *iface;
   
     for (iface = daemon->interfaces; iface; iface = iface->next)
       if (iface->found && iface->name && iface->label)
         my_syslog(LOG_WARNING, _("warning: using interface %s instead"), iface->name);
   }
   
 void warn_int_names(void)  void warn_int_names(void)
 {  {
   struct interface_name *intname;    struct interface_name *intname;
Line 1136  int random_sock(int family) Line 1226  int random_sock(int family)
       if (fix_fd(fd))        if (fix_fd(fd))
         while(tries--)          while(tries--)
           {            {
            unsigned short port = rand16();            unsigned short port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
                           
             if (daemon->min_port != 0 || daemon->max_port != MAX_PORT)  
               port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));  
               
             if (family == AF_INET)               if (family == AF_INET) 
               {                {
                 addr.in.sin_addr.s_addr = INADDR_ANY;                  addr.in.sin_addr.s_addr = INADDR_ANY;
Line 1149  int random_sock(int family) Line 1236  int random_sock(int family)
                 addr.in.sin_len = sizeof(struct sockaddr_in);                  addr.in.sin_len = sizeof(struct sockaddr_in);
 #endif  #endif
               }                }
 #ifdef HAVE_IPV6  
             else              else
               {                {
                 addr.in6.sin6_addr = in6addr_any;                   addr.in6.sin6_addr = in6addr_any; 
Line 1158  int random_sock(int family) Line 1244  int random_sock(int family)
                 addr.in6.sin6_len = sizeof(struct sockaddr_in6);                  addr.in6.sin6_len = sizeof(struct sockaddr_in6);
 #endif  #endif
               }                }
 #endif  
                           
             if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)              if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
               return fd;                return fd;
Line 1174  int random_sock(int family) Line 1259  int random_sock(int family)
 }  }
       
   
int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp)
 {  {
   union mysockaddr addr_copy = *addr;    union mysockaddr addr_copy = *addr;
     unsigned short port;
     int tries = 1, done = 0;
     unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
    
     if (addr_copy.sa.sa_family == AF_INET)
       port = addr_copy.in.sin_port;
     else
       port = addr_copy.in6.sin6_port;
   
   /* cannot set source _port_ for TCP connections. */    /* cannot set source _port_ for TCP connections. */
   if (is_tcp)    if (is_tcp)
       port = 0;
   
     /* Bind a random port within the range given by min-port and max-port */
     if (port == 0)
     {      {
         tries = ports_avail < 30 ? 3 * ports_avail : 100;
         port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
       }
     
     while (tries--)
       {
       if (addr_copy.sa.sa_family == AF_INET)        if (addr_copy.sa.sa_family == AF_INET)
        addr_copy.in.sin_port = 0;        addr_copy.in.sin_port = port;
#ifdef HAVE_IPV6 
       else        else
        addr_copy.in6.sin6_port = 0;        addr_copy.in6.sin6_port = port;
#endif
       if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) != -1)
         {
           done = 1;
           break;
         }
       
       if (errno != EADDRINUSE && errno != EACCES)
         return 0;
       
       port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
     }      }
  
  if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)  if (!done)
     return 0;      return 0;
    
   if (!is_tcp && ifindex > 0)
     {
 #if defined(IP_UNICAST_IF)
       if (addr_copy.sa.sa_family == AF_INET)
         {
           uint32_t ifindex_opt = htonl(ifindex);
           return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
         }
 #endif
 #if defined (IPV6_UNICAST_IF)
       if (addr_copy.sa.sa_family == AF_INET6)
         {
           uint32_t ifindex_opt = htonl(ifindex);
           return setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
         }
 #endif
     }
 
   (void)intname; /* suppress potential unused warning */
 #if defined(SO_BINDTODEVICE)  #if defined(SO_BINDTODEVICE)
   if (intname[0] != 0 &&    if (intname[0] != 0 &&
       setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)        setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
Line 1204  int local_bind(int fd, union mysockaddr *addr, char *i Line 1335  int local_bind(int fd, union mysockaddr *addr, char *i
 static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)  static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
 {  {
   struct serverfd *sfd;    struct serverfd *sfd;
     unsigned int ifindex = 0;
   int errsave;    int errsave;
  int opt = 1;
   
   /* when using random ports, servers which would otherwise use    /* when using random ports, servers which would otherwise use
      the INADDR_ANY/port0 socket have sfd set to NULL */       the INADDR_ANY/port0 socket have sfd set to NULL */
   if (!daemon->osport && intname[0] == 0)    if (!daemon->osport && intname[0] == 0)
Line 1217  static struct serverfd *allocate_sfd(union mysockaddr  Line 1350  static struct serverfd *allocate_sfd(union mysockaddr 
           addr->in.sin_port == htons(0)            addr->in.sin_port == htons(0)
         return NULL;          return NULL;
   
 #ifdef HAVE_IPV6  
       if (addr->sa.sa_family == AF_INET6 &&        if (addr->sa.sa_family == AF_INET6 &&
           memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&            memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
           addr->in6.sin6_port == htons(0)            addr->in6.sin6_port == htons(0)
         return NULL;          return NULL;
 #endif  
     }      }
   
     if (intname && strlen(intname) != 0)
       ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
               
   /* may have a suitable one already */    /* may have a suitable one already */
   for (sfd = daemon->sfds; sfd; sfd = sfd->next )    for (sfd = daemon->sfds; sfd; sfd = sfd->next )
     if (sockaddr_isequal(&sfd->source_addr, addr) &&      if (sockaddr_isequal(&sfd->source_addr, addr) &&
        strcmp(intname, sfd->interface) == 0)        strcmp(intname, sfd->interface) == 0 &&
         ifindex == sfd->ifindex) 
       return sfd;        return sfd;
       
   /* need to make a new one. */    /* need to make a new one. */
Line 1241  static struct serverfd *allocate_sfd(union mysockaddr  Line 1376  static struct serverfd *allocate_sfd(union mysockaddr 
       free(sfd);        free(sfd);
       return NULL;        return NULL;
     }      }
  
  if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))  if ((addr->sa.sa_family == AF_INET6 && setsockopt(sfd->fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) ||
       !local_bind(sfd->fd, addr, intname, ifindex, 0) || !fix_fd(sfd->fd))
     {       { 
      errsave = errno; /* save error from bind. */      errsave = errno; /* save error from bind/setsockopt. */
       close(sfd->fd);        close(sfd->fd);
       free(sfd);        free(sfd);
       errno = errsave;        errno = errsave;
       return NULL;        return NULL;
     }      }
    
  strcpy(sfd->interface, intname);   safe_strncpy(sfd->interface, intname, sizeof(sfd->interface)); 
   sfd->source_addr = *addr;    sfd->source_addr = *addr;
   sfd->next = daemon->sfds;    sfd->next = daemon->sfds;
     sfd->ifindex = ifindex;
     sfd->preallocated = 0;
   daemon->sfds = sfd;    daemon->sfds = sfd;
   
   return sfd;     return sfd; 
 }  }
   
Line 1263  static struct serverfd *allocate_sfd(union mysockaddr  Line 1402  static struct serverfd *allocate_sfd(union mysockaddr 
 void pre_allocate_sfds(void)  void pre_allocate_sfds(void)
 {  {
   struct server *srv;    struct server *srv;
     struct serverfd *sfd;
       
   if (daemon->query_port != 0)    if (daemon->query_port != 0)
     {      {
Line 1274  void pre_allocate_sfds(void) Line 1414  void pre_allocate_sfds(void)
 #ifdef HAVE_SOCKADDR_SA_LEN  #ifdef HAVE_SOCKADDR_SA_LEN
       addr.in.sin_len = sizeof(struct sockaddr_in);        addr.in.sin_len = sizeof(struct sockaddr_in);
 #endif  #endif
      allocate_sfd(&addr, "");      if ((sfd = allocate_sfd(&addr, "")))
#ifdef HAVE_IPV6        sfd->preallocated = 1;
 
       memset(&addr, 0, sizeof(addr));        memset(&addr, 0, sizeof(addr));
       addr.in6.sin6_family = AF_INET6;        addr.in6.sin6_family = AF_INET6;
       addr.in6.sin6_addr = in6addr_any;        addr.in6.sin6_addr = in6addr_any;
Line 1283  void pre_allocate_sfds(void) Line 1424  void pre_allocate_sfds(void)
 #ifdef HAVE_SOCKADDR_SA_LEN  #ifdef HAVE_SOCKADDR_SA_LEN
       addr.in6.sin6_len = sizeof(struct sockaddr_in6);        addr.in6.sin6_len = sizeof(struct sockaddr_in6);
 #endif  #endif
      allocate_sfd(&addr, "");      if ((sfd = allocate_sfd(&addr, "")))
#endif        sfd->preallocated = 1;
     }      }
       
   for (srv = daemon->servers; srv; srv = srv->next)    for (srv = daemon->servers; srv; srv = srv->next)
Line 1293  void pre_allocate_sfds(void) Line 1434  void pre_allocate_sfds(void)
         errno != 0 &&          errno != 0 &&
         option_bool(OPT_NOWILD))          option_bool(OPT_NOWILD))
       {        {
        prettyprint_addr(&srv->source_addr, daemon->namebuff);        (void)prettyprint_addr(&srv->source_addr, daemon->namebuff);
         if (srv->interface[0] != 0)          if (srv->interface[0] != 0)
           {            {
             strcat(daemon->namebuff, " ");              strcat(daemon->namebuff, " ");
Line 1417  void add_update_server(int flags, Line 1558  void add_update_server(int flags,
         serv->flags |= SERV_HAS_DOMAIN;          serv->flags |= SERV_HAS_DOMAIN;
               
       if (interface)        if (interface)
        strcpy(serv->interface, interface);              safe_strncpy(serv->interface, interface, sizeof(serv->interface));
       if (addr)        if (addr)
         serv->addr = *addr;          serv->addr = *addr;
       if (source_addr)        if (source_addr)
Line 1429  void check_servers(void) Line 1570  void check_servers(void)
 {  {
   struct irec *iface;    struct irec *iface;
   struct server *serv;    struct server *serv;
     struct serverfd *sfd, *tmp, **up;
   int port = 0, count;    int port = 0, count;
     int locals = 0;
   
   /* interface may be new since startup */    /* interface may be new since startup */
   if (!option_bool(OPT_NOWILD))    if (!option_bool(OPT_NOWILD))
     enumerate_interfaces(0);      enumerate_interfaces(0);
     
 #ifdef HAVE_DNSSEC  
  /* Disable DNSSEC validation when using server=/domain/.... servers  
     unless there's a configured trust anchor. */  
   for (serv = daemon->servers; serv; serv = serv->next)  
     serv->flags |= SERV_DO_DNSSEC;  
 #endif  
   
     /* don't garbage collect pre-allocated sfds. */
     for (sfd = daemon->sfds; sfd; sfd = sfd->next)
       sfd->used = sfd->preallocated;
   
   for (count = 0, serv = daemon->servers; serv; serv = serv->next)    for (count = 0, serv = daemon->servers; serv; serv = serv->next)
     {      {
       if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))        if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
Line 1453  void check_servers(void) Line 1593  void check_servers(void)
 #ifdef HAVE_DNSSEC  #ifdef HAVE_DNSSEC
           if (option_bool(OPT_DNSSEC_VALID))            if (option_bool(OPT_DNSSEC_VALID))
             {               { 
                 if (!(serv->flags & SERV_FOR_NODOTS))
                   serv->flags |= SERV_DO_DNSSEC;
                 
                 /* Disable DNSSEC validation when using server=/domain/.... servers
                    unless there's a configured trust anchor. */
               if (serv->flags & SERV_HAS_DOMAIN)                if (serv->flags & SERV_HAS_DOMAIN)
                 {                  {
                   struct ds_config *ds;                    struct ds_config *ds;
Line 1469  void check_servers(void) Line 1614  void check_servers(void)
                   if (!ds)                    if (!ds)
                     serv->flags &= ~SERV_DO_DNSSEC;                      serv->flags &= ~SERV_DO_DNSSEC;
                 }                  }
               else if (serv->flags & SERV_FOR_NODOTS)   
                 serv->flags &= ~SERV_DO_DNSSEC;  
             }              }
 #endif  #endif
   
Line 1505  void check_servers(void) Line 1648  void check_servers(void)
               serv->flags |= SERV_MARK;                serv->flags |= SERV_MARK;
               continue;                continue;
             }              }
             
             if (serv->sfd)
               serv->sfd->used = 1;
         }          }
               
       if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))        if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
Line 1527  void check_servers(void) Line 1673  void check_servers(void)
                 s1 = _("domain"), s2 = serv->domain;                  s1 = _("domain"), s2 = serv->domain;
                               
               if (serv->flags & SERV_NO_ADDR)                if (serv->flags & SERV_NO_ADDR)
                my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);                {
                   count--;
                   if (++locals <= LOCALS_LOGGED)
                         my_syslog(LOG_INFO, _("using only locally-known addresses for %s %s"), s1, s2);
                 }
               else if (serv->flags & SERV_USE_RESOLV)                else if (serv->flags & SERV_USE_RESOLV)
                 my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);                  my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
               else                 else 
Line 1544  void check_servers(void) Line 1694  void check_servers(void)
         }          }
     }      }
       
     if (locals > LOCALS_LOGGED)
       my_syslog(LOG_INFO, _("using %d more local addresses"), locals - LOCALS_LOGGED);
   if (count - 1 > SERVERS_LOGGED)    if (count - 1 > SERVERS_LOGGED)
     my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);      my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
   
     /* Remove unused sfds */
     for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
       {
          tmp = sfd->next;
          if (!sfd->used) 
           {
             *up = sfd->next;
             close(sfd->fd);
             free(sfd);
           } 
         else
           up = &sfd->next;
       }
     
   cleanup_servers();    cleanup_servers();
 }  }
   
Line 1592  int reload_servers(char *fname) Line 1758  int reload_servers(char *fname)
           source_addr.in.sin_addr.s_addr = INADDR_ANY;            source_addr.in.sin_addr.s_addr = INADDR_ANY;
           source_addr.in.sin_port = htons(daemon->query_port);            source_addr.in.sin_port = htons(daemon->query_port);
         }          }
 #ifdef HAVE_IPV6  
       else         else 
         {                 {       
           int scope_index = 0;            int scope_index = 0;
Line 1620  int reload_servers(char *fname) Line 1785  int reload_servers(char *fname)
           else            else
             continue;              continue;
         }          }
 #else /* IPV6 */  
       else  
         continue;  
 #endif   
   
       add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);        add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
       gotone = 1;        gotone = 1;

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.4


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