|
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 */ |
| |
|
| |
|