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

version 1.1.1.2, 2014/06/15 16:31:38 version 1.1.1.3, 2016/11/02 09:57:01
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley/* dnsmasq is Copyright (c) 2000-2016 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 16 Line 16
   
 #include "dnsmasq.h"  #include "dnsmasq.h"
   
 #ifndef IN6_IS_ADDR_ULA  
 #define IN6_IS_ADDR_ULA(a) ((((__const uint32_t *) (a))[0] & htonl (0xfe00000)) == htonl (0xfc000000))  
 #endif  
   
 #ifdef HAVE_LINUX_NETWORK  #ifdef HAVE_LINUX_NETWORK
   
 int indextoname(int fd, int index, char *name)  int indextoname(int fd, int index, char *name)
Line 240  struct iface_param { Line 236  struct iface_param {
 };  };
   
 static int iface_allowed(struct iface_param *param, int if_index, char *label,  static int iface_allowed(struct iface_param *param, int if_index, char *label,
                         union mysockaddr *addr, struct in_addr netmask, int prefixlen, int dad)                          union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags) 
 {  {
   struct irec *iface;    struct irec *iface;
   int mtu = 0, loopback;    int mtu = 0, loopback;
Line 392  static int iface_allowed(struct iface_param *param, in Line 388  static int iface_allowed(struct iface_param *param, in
                  {                   {
                     al->addr.addr.addr6 = addr->in6.sin6_addr;                      al->addr.addr.addr6 = addr->in6.sin6_addr;
                     al->flags = ADDRLIST_IPV6;                      al->flags = ADDRLIST_IPV6;
                       /* Privacy addresses and addresses still undergoing DAD and deprecated addresses
                          don't appear in forward queries, but will in reverse ones. */
                       if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
                         al->flags |= ADDRLIST_REVONLY;
                  }                    } 
 #endif  #endif
               }                }
Line 403  static int iface_allowed(struct iface_param *param, in Line 403  static int iface_allowed(struct iface_param *param, in
   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->dad = dad;        iface->dad = !!(iface_flags & IFACE_TENTATIVE);
         iface->found = 1; /* for garbage collection */          iface->found = 1; /* for garbage collection */
         return 1;          return 1;
       }        }
Line 478  static int iface_allowed(struct iface_param *param, in Line 478  static int iface_allowed(struct iface_param *param, in
       iface->dhcp_ok = dhcp_ok;        iface->dhcp_ok = dhcp_ok;
       iface->dns_auth = auth_dns;        iface->dns_auth = auth_dns;
       iface->mtu = mtu;        iface->mtu = mtu;
      iface->dad = dad;      iface->dad = !!(iface_flags & IFACE_TENTATIVE);
       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;
Line 523  static int iface_allowed_v6(struct in6_addr *local, in Line 523  static int iface_allowed_v6(struct in6_addr *local, in
   else    else
     addr.in6.sin6_scope_id = 0;      addr.in6.sin6_scope_id = 0;
       
  return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, !!(flags & IFACE_TENTATIVE));  return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
 }  }
 #endif  #endif
   
Line 532  static int iface_allowed_v4(struct in_addr local, int  Line 532  static int iface_allowed_v4(struct in_addr local, int 
 {  {
   union mysockaddr addr;    union mysockaddr addr;
   int prefix, bit;    int prefix, bit;
    
     (void)broadcast; /* warning */
   
   memset(&addr, 0, sizeof(addr));    memset(&addr, 0, sizeof(addr));
 #ifdef HAVE_SOCKADDR_SA_LEN  #ifdef HAVE_SOCKADDR_SA_LEN
   addr.in.sin_len = sizeof(addr.in);    addr.in.sin_len = sizeof(addr.in);
 #endif  #endif
   addr.in.sin_family = AF_INET;    addr.in.sin_family = AF_INET;
   addr.in.sin_addr = broadcast; /* warning */  
   addr.in.sin_addr = local;    addr.in.sin_addr = local;
   addr.in.sin_port = htons(daemon->port);    addr.in.sin_port = htons(daemon->port);
   
Line 551  static int iface_allowed_v4(struct in_addr local, int  Line 552  static int iface_allowed_v4(struct in_addr local, int 
 int enumerate_interfaces(int reset)  int enumerate_interfaces(int reset)
 {  {
   static struct addrlist *spare = NULL;    static struct addrlist *spare = NULL;
  static int done = 0, active = 0;  static int done = 0;
   struct iface_param param;    struct iface_param param;
   int errsave, ret = 1;    int errsave, ret = 1;
   struct addrlist *addr, *tmp;    struct addrlist *addr, *tmp;
Line 570  int enumerate_interfaces(int reset) Line 571  int enumerate_interfaces(int reset)
       return 1;        return 1;
     }      }
   
  if (done || active)  if (done)
     return 1;      return 1;
   
   done = 1;    done = 1;
   
   /* protect against recusive calls from iface_enumerate(); */  
   active = 1;  
   
   if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)    if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
     return 0;      return 0;
     
Line 677  int enumerate_interfaces(int reset) Line 675  int enumerate_interfaces(int reset)
     }      }
       
   errno = errsave;    errno = errsave;
     
   spare = param.spare;    spare = param.spare;
  active = 0;    
   
   return ret;    return ret;
 }  }
   
Line 814  int tcp_interface(int fd, int af) Line 810  int tcp_interface(int fd, int af)
   int opt = 1;    int opt = 1;
   struct cmsghdr *cmptr;    struct cmsghdr *cmptr;
   struct msghdr msg;    struct msghdr msg;
     socklen_t len;
       
  /* use mshdr do that the CMSDG_* macros are available */  /* use mshdr so that the CMSDG_* macros are available */
   msg.msg_control = daemon->packet;    msg.msg_control = daemon->packet;
  msg.msg_controllen = daemon->packet_buff_sz;  msg.msg_controllen = len = daemon->packet_buff_sz;
       
   /* we overwrote the buffer... */    /* we overwrote the buffer... */
   daemon->srv_save = NULL;    daemon->srv_save = NULL;
Line 825  int tcp_interface(int fd, int af) Line 822  int tcp_interface(int fd, int af)
   if (af == AF_INET)    if (af == AF_INET)
     {      {
       if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&        if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
          getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)          getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
        for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))        {
          if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)          msg.msg_controllen = len;
            {          for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
              union {            if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
                unsigned char *c;              {
                struct in_pktinfo *p;                union {
              } p;                  unsigned char *c;
                                struct in_pktinfo *p;
              p.c = CMSG_DATA(cmptr);                } p;
              if_index = p.p->ipi_ifindex;                
            }                p.c = CMSG_DATA(cmptr);
                 if_index = p.p->ipi_ifindex;
               }
         }
     }      }
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
   else    else
Line 854  int tcp_interface(int fd, int af) Line 854  int tcp_interface(int fd, int af)
 #endif  #endif
   
       if (set_ipv6pktinfo(fd) &&        if (set_ipv6pktinfo(fd) &&
          getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)          getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, &len) != -1)
         {          {
          for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))          msg.msg_controllen = len;
           for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
             if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)              if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
               {                {
                 union {                  union {
Line 1081  void join_multicast(int dienow)       Line 1082  void join_multicast(int dienow)      
                           
             if ((daemon->doing_dhcp6 || daemon->relay6) &&              if ((daemon->doing_dhcp6 || daemon->relay6) &&
                 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)                  setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
              err = 1;              err = errno;
                           
             inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);              inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
                           
             if (daemon->doing_dhcp6 &&               if (daemon->doing_dhcp6 && 
                 setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)                  setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
              err = 1;              err = errno;
                           
             inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);              inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
                           
             if (daemon->doing_ra &&              if (daemon->doing_ra &&
                 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)                  setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
              err = 1;              err = errno;
                           
             if (err)              if (err)
               {                {
                 char *s = _("interface %s failed to join DHCPv6 multicast group: %s");                  char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
                   errno = err;
   
   #ifdef HAVE_LINUX_NETWORK
                   if (errno == ENOMEM)
                     my_syslog(LOG_ERR, _("try increasing /proc/sys/net/core/optmem_max"));
   #endif
   
                 if (dienow)                  if (dienow)
                   die(s, iface->name, EC_BADNET);                    die(s, iface->name, EC_BADNET);
                 else                  else
Line 1117  int random_sock(int family) Line 1125  int random_sock(int family)
   if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)    if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
     {      {
       union mysockaddr addr;        union mysockaddr addr;
      unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;      unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
       int tries = ports_avail < 30 ? 3 * ports_avail : 100;        int tries = ports_avail < 30 ? 3 * ports_avail : 100;
   
       memset(&addr, 0, sizeof(addr));        memset(&addr, 0, sizeof(addr));
Line 1130  int random_sock(int family) Line 1138  int random_sock(int family)
           {            {
             unsigned short port = rand16();              unsigned short port = rand16();
                           
            if (daemon->min_port != 0)            if (daemon->min_port != 0 || daemon->max_port != MAX_PORT)
              port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));              port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
                           
             if (family == AF_INET)               if (family == AF_INET) 
               {                {
Line 1302  void mark_servers(int flag) Line 1310  void mark_servers(int flag)
   
   /* mark everything with argument flag */    /* mark everything with argument flag */
   for (serv = daemon->servers; serv; serv = serv->next)    for (serv = daemon->servers; serv; serv = serv->next)
    if (serv->flags & flag)    {
      serv->flags |= SERV_MARK;      if (serv->flags & flag)
         serv->flags |= SERV_MARK;
 #ifdef HAVE_LOOP
       /* Give looped servers another chance */
       serv->flags &= ~SERV_LOOP;
 #endif
     }
 }  }
   
 void cleanup_servers(void)  void cleanup_servers(void)
Line 1325  void cleanup_servers(void) Line 1339  void cleanup_servers(void)
       else         else 
        up = &serv->next;         up = &serv->next;
     }      }
   
   #ifdef HAVE_LOOP
     /* Now we have a new set of servers, test for loops. */
     loop_send_probes();
   #endif
 }  }
   
 void add_update_server(int flags,  void add_update_server(int flags,
Line 1390  void add_update_server(int flags, Line 1409  void add_update_server(int flags,
       serv->domain = domain_str;        serv->domain = domain_str;
       serv->next = next;        serv->next = next;
       serv->queries = serv->failed_queries = 0;        serv->queries = serv->failed_queries = 0;
      #ifdef HAVE_LOOP
       serv->uid = rand32();
 #endif      
 
       if (domain)        if (domain)
         serv->flags |= SERV_HAS_DOMAIN;          serv->flags |= SERV_HAS_DOMAIN;
               
Line 1407  void check_servers(void) Line 1429  void check_servers(void)
 {  {
   struct irec *iface;    struct irec *iface;
   struct server *serv;    struct server *serv;
  int port = 0;  int port = 0, count;
   
   /* 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)    for (serv = daemon->servers; serv; serv = serv->next)
       serv->flags |= SERV_DO_DNSSEC;
   #endif
   
     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)))
         {          {
          port = prettyprint_addr(&serv->addr, daemon->namebuff);          /* Init edns_pktsz for newly created server records. */
           if (serv->edns_pktsz == 0)
             serv->edns_pktsz = daemon->edns_pktsz;
           
 #ifdef HAVE_DNSSEC
           if (option_bool(OPT_DNSSEC_VALID))
             { 
               if (serv->flags & SERV_HAS_DOMAIN)
                 {
                   struct ds_config *ds;
                   char *domain = serv->domain;
                   
                   /* .example.com is valid */
                   while (*domain == '.')
                     domain++;
                   
                   for (ds = daemon->ds; ds; ds = ds->next)
                     if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
                       break;
                   
                   if (!ds)
                     serv->flags &= ~SERV_DO_DNSSEC;
                 }
               else if (serv->flags & SERV_FOR_NODOTS) 
                 serv->flags &= ~SERV_DO_DNSSEC;
             }
 #endif
   
             port = prettyprint_addr(&serv->addr, daemon->namebuff);
             
           /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */            /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
           if (serv->addr.sa.sa_family == AF_INET &&            if (serv->addr.sa.sa_family == AF_INET &&
               serv->addr.in.sin_addr.s_addr == 0)                serv->addr.in.sin_addr.s_addr == 0)
Line 1450  void check_servers(void) Line 1507  void check_servers(void)
             }              }
         }          }
               
      if (!(serv->flags & SERV_NO_REBIND))      if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
         {          {
             if (++count > SERVERS_LOGGED)
               continue;
             
           if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))            if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
             {              {
              char *s1, *s2;              char *s1, *s2, *s3 = "";
 #ifdef HAVE_DNSSEC
               if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
                 s3 = _("(no DNSSEC)");
 #endif
               if (!(serv->flags & SERV_HAS_DOMAIN))                if (!(serv->flags & SERV_HAS_DOMAIN))
                 s1 = _("unqualified"), s2 = _("names");                  s1 = _("unqualified"), s2 = _("names");
               else if (strlen(serv->domain) == 0)                else if (strlen(serv->domain) == 0)
Line 1466  void check_servers(void) Line 1530  void check_servers(void)
                 my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);                  my_syslog(LOG_INFO, _("using local addresses only 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 if (!(serv->flags & SERV_LITERAL_ADDRESS))              else 
                my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);                my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s %s"), daemon->namebuff, port, s1, s2, s3);
             }              }
   #ifdef HAVE_LOOP
             else if (serv->flags & SERV_LOOP)
               my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port); 
   #endif
           else if (serv->interface[0] != 0)            else if (serv->interface[0] != 0)
             my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);               my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface); 
           else            else
             my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);               my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port); 
         }          }
     }      }
     
     if (count - 1 > SERVERS_LOGGED)
       my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
   
   cleanup_servers();    cleanup_servers();
 }  }
Line 1564  int reload_servers(char *fname) Line 1635  int reload_servers(char *fname)
   return gotone;    return gotone;
 }  }
   
 #if defined(HAVE_LINUX_NETWORK) || defined(HAVE_BSD_NETWORK)  
 /* Called when addresses are added or deleted from an interface */  /* Called when addresses are added or deleted from an interface */
 void newaddress(time_t now)  void newaddress(time_t now)
 {  {
Line 1589  void newaddress(time_t now) Line 1659  void newaddress(time_t now)
 #endif  #endif
 }  }
   
 #endif  
   
   
   

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


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