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