Diff for /embedaddon/dnsmasq/src/bpf.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2013/07/29 19:37:40 version 1.1.1.2, 2014/06/15 16:31:38
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley/* dnsmasq is Copyright (c) 2000-2014 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 19 Line 19
 #if defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK)  #if defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
 #include <ifaddrs.h>  #include <ifaddrs.h>
   
 #if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)  
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/sysctl.h>  #include <sys/sysctl.h>
   #include <net/if.h>
 #include <net/route.h>  #include <net/route.h>
 #include <net/if_dl.h>  #include <net/if_dl.h>
 #include <netinet/if_ether.h>  #include <netinet/if_ether.h>
   #if defined(__FreeBSD__)
   #  include <net/if_var.h> 
   #endif
   #include <netinet/in_var.h>
   #ifdef HAVE_IPV6
   #  include <netinet6/in6_var.h>
   #endif
   
 #ifndef SA_SIZE  #ifndef SA_SIZE
 #define SA_SIZE(sa)                                             \  #define SA_SIZE(sa)                                             \
Line 33 Line 40
         1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )          1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
 #endif  #endif
   
   #ifdef HAVE_BSD_NETWORK
   static int del_family = 0;
   static struct all_addr del_addr;
   #endif
   
   #if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
   
 int arp_enumerate(void *parm, int (*callback)())  int arp_enumerate(void *parm, int (*callback)())
 {  {
   int mib[6];    int mib[6];
Line 83  int arp_enumerate(void *parm, int (*callback)()) Line 97  int arp_enumerate(void *parm, int (*callback)())
   
   return 1;    return 1;
 }  }
#endif#endif /* defined(HAVE_BSD_NETWORK) && !defined(__APPLE__) */
   
   
 int iface_enumerate(int family, void *parm, int (*callback)())  int iface_enumerate(int family, void *parm, int (*callback)())
 {  {
   struct ifaddrs *head, *addrs;    struct ifaddrs *head, *addrs;
  int errsav, ret = 0;  int errsav, fd = -1, ret = 0;
   
   if (family == AF_UNSPEC)    if (family == AF_UNSPEC)
 #if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)  #if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
Line 105  int iface_enumerate(int family, void *parm, int (*call Line 119  int iface_enumerate(int family, void *parm, int (*call
   if (getifaddrs(&head) == -1)    if (getifaddrs(&head) == -1)
     return 0;      return 0;
   
   #if defined(HAVE_BSD_NETWORK) && defined(HAVE_IPV6)
     if (family == AF_INET6)
       fd = socket(PF_INET6, SOCK_DGRAM, 0);
   #endif
     
   for (addrs = head; addrs; addrs = addrs->ifa_next)    for (addrs = head; addrs; addrs = addrs->ifa_next)
     {      {
       if (addrs->ifa_addr->sa_family == family)        if (addrs->ifa_addr->sa_family == family)
         {          {
           int iface_index = if_nametoindex(addrs->ifa_name);            int iface_index = if_nametoindex(addrs->ifa_name);
   
          if (iface_index == 0 || !addrs->ifa_addr || !addrs->ifa_netmask)          if (iface_index == 0 || !addrs->ifa_addr || 
               (!addrs->ifa_netmask && family != AF_LINK))
             continue;              continue;
   
           if (family == AF_INET)            if (family == AF_INET)
             {              {
               struct in_addr addr, netmask, broadcast;                struct in_addr addr, netmask, broadcast;
               addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;                addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
   #ifdef HAVE_BSD_NETWORK
                 if (del_family == AF_INET && del_addr.addr.addr4.s_addr == addr.s_addr)
                   continue;
   #endif
               netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;                netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
               if (addrs->ifa_broadaddr)                if (addrs->ifa_broadaddr)
                 broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;                   broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr; 
               else                 else 
                 broadcast.s_addr = 0;                           broadcast.s_addr = 0;         
              if (!((*callback)(addr, iface_index, netmask, broadcast, parm)))              if (!((*callback)(addr, iface_index, NULL, netmask, broadcast, parm)))
                 goto err;                  goto err;
             }              }
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
Line 133  int iface_enumerate(int family, void *parm, int (*call Line 157  int iface_enumerate(int family, void *parm, int (*call
               unsigned char *netmask = (unsigned char *) &((struct sockaddr_in6 *) addrs->ifa_netmask)->sin6_addr;                unsigned char *netmask = (unsigned char *) &((struct sockaddr_in6 *) addrs->ifa_netmask)->sin6_addr;
               int scope_id = ((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_scope_id;                int scope_id = ((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_scope_id;
               int i, j, prefix = 0;                int i, j, prefix = 0;
                 u32 valid = 0xffffffff, preferred = 0xffffffff;
                 int flags = 0;
   #ifdef HAVE_BSD_NETWORK
                 if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr.addr6, addr))
                   continue;
   #endif
   #if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
                 struct in6_ifreq ifr6;
   
                 memset(&ifr6, 0, sizeof(ifr6));
                 strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
                               
                 ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
                 if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
                   {
                     if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
                       flags |= IFACE_TENTATIVE;
                     
                     if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED)
                       flags |= IFACE_DEPRECATED;
   
   #ifdef IN6_IFF_TEMPORARY
                     if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY)))
                       flags |= IFACE_PERMANENT;
   #endif
   
   #ifdef IN6_IFF_PRIVACY
                     if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_PRIVACY)))
                       flags |= IFACE_PERMANENT;
   #endif
                   }
                 
                 ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
                 if (fd != -1 && ioctl(fd, SIOCGIFALIFETIME_IN6, &ifr6) != -1)
                   {
                     valid = ifr6.ifr_ifru.ifru_lifetime.ia6t_vltime;
                     preferred = ifr6.ifr_ifru.ifru_lifetime.ia6t_pltime;
                   }
   #endif
                         
               for (i = 0; i < IN6ADDRSZ; i++, prefix += 8)                 for (i = 0; i < IN6ADDRSZ; i++, prefix += 8) 
                 if (netmask[i] != 0xff)                  if (netmask[i] != 0xff)
                   break;                    break;
                     
               if (i != IN6ADDRSZ && netmask[i])                 if (i != IN6ADDRSZ && netmask[i]) 
                 for (j = 7; j > 0; j--, prefix++)                   for (j = 7; j > 0; j--, prefix++) 
                   if ((netmask[i] & (1 << j)) == 0)                    if ((netmask[i] & (1 << j)) == 0)
Line 148  int iface_enumerate(int family, void *parm, int (*call Line 211  int iface_enumerate(int family, void *parm, int (*call
                 {                  {
                   addr->s6_addr[2] = 0;                    addr->s6_addr[2] = 0;
                   addr->s6_addr[3] = 0;                    addr->s6_addr[3] = 0;
                }                } 
                           
              /* preferred and valid times == forever until we known how to dtermine them. */              if (!((*callback)(addr, prefix, scope_id, iface_index, flags,
              if (!((*callback)(addr, prefix, scope_id, iface_index, 0, -1, -1, parm)))                                (int) preferred, (int)valid, parm)))
                goto err;                goto err;             
        }            }
#endif#endif /* HAVE_IPV6 */
 
 #ifdef HAVE_DHCP6        #ifdef HAVE_DHCP6      
           else if (family == AF_LINK)            else if (family == AF_LINK)
             {               { 
Line 172  int iface_enumerate(int family, void *parm, int (*call Line 236  int iface_enumerate(int family, void *parm, int (*call
   
  err:   err:
   errsav = errno;    errsav = errno;
  freeifaddrs(head);    freeifaddrs(head); 
   if (fd != -1)
     close(fd);
   errno = errsav;    errno = errsav;
   
   return ret;    return ret;
 }  }
#endif#endif /* defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK) */
   
   
 #if defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP)  #if defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP)
Line 296  void send_via_bpf(struct dhcp_packet *mess, size_t len Line 362  void send_via_bpf(struct dhcp_packet *mess, size_t len
   while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());    while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
 }  }
   
   #endif /* defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) */
    
   
   #ifdef HAVE_BSD_NETWORK
   
   void route_init(void)
   {
     /* AF_UNSPEC: all addr families */
     daemon->routefd = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
     
     if (daemon->routefd == -1 || !fix_fd(daemon->routefd))
       die(_("cannot create PF_ROUTE socket: %s"), NULL, EC_BADNET);
   }
   
   void route_sock(time_t now)
   {
     struct if_msghdr *msg;
     int rc = recv(daemon->routefd, daemon->packet, daemon->packet_buff_sz, 0);
   
     if (rc < 4)
       return;
   
     msg = (struct if_msghdr *)daemon->packet;
     
     if (rc < msg->ifm_msglen)
       return;
   
      if (msg->ifm_version != RTM_VERSION)
        {
          static int warned = 0;
          if (!warned)
            {
              my_syslog(LOG_WARNING, _("Unknown protocol version from route socket"));
              warned = 1;
            }
        }
      else if (msg->ifm_type == RTM_NEWADDR)
        {
          del_family = 0;
          newaddress(now);
        }
      else if (msg->ifm_type == RTM_DELADDR)
        {
          /* There's a race in the kernel, such that if we run iface_enumerate() immediately
             we get a DELADDR event, the deleted address still appears. Here we store the deleted address
             in a static variable, and omit it from the set returned by iface_enumerate() */
          int mask = ((struct ifa_msghdr *)msg)->ifam_addrs;
          int maskvec[] = { RTA_DST, RTA_GATEWAY, RTA_NETMASK, RTA_GENMASK,
                            RTA_IFP, RTA_IFA, RTA_AUTHOR, RTA_BRD };
          int of;
          unsigned int i;
          
          for (i = 0,  of = sizeof(struct ifa_msghdr); of < rc && i < sizeof(maskvec)/sizeof(maskvec[0]); i++) 
            if (mask & maskvec[i]) 
              {
                struct sockaddr *sa = (struct sockaddr *)((char *)msg + of);
                size_t diff = (sa->sa_len != 0) ? sa->sa_len : sizeof(long);
                
                if (maskvec[i] == RTA_IFA)
                  {
                    del_family = sa->sa_family;
                    if (del_family == AF_INET)
                      del_addr.addr.addr4 = ((struct sockaddr_in *)sa)->sin_addr;
   #ifdef HAVE_IPV6
                    else if (del_family == AF_INET6)
                      del_addr.addr.addr6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
 #endif  #endif
                    else
                      del_family = 0;
                  }
                
                of += diff;
                /* round up as needed */
                if (diff & (sizeof(long) - 1)) 
                  of += sizeof(long) - (diff & (sizeof(long) - 1));
              }
          
          newaddress(now);
        }
   }
   
   #endif /* HAVE_BSD_NETWORK */
   
   

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


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