import of dnsmasq-2.28.tar.gz

This commit is contained in:
Simon Kelley
2006-04-17 14:24:29 +01:00
parent cdeda28f82
commit 5e9e0efb01
31 changed files with 3191 additions and 2712 deletions

View File

@@ -10,8 +10,6 @@
GNU General Public License for more details.
*/
/* Author's email: simon@thekelleys.org.uk */
#include "dnsmasq.h"
static char *compile_opts =
@@ -26,9 +24,6 @@ static char *compile_opts =
#ifdef HAVE_BROKEN_RTC
"no-RTC "
#endif
#ifdef HAVE_RTNETLINK
"RTNetlink "
#endif
#ifndef HAVE_ISC_READER
"no-"
#endif
@@ -42,7 +37,8 @@ static char *compile_opts =
#endif
"I18N ";
static volatile int sigterm, sighup, sigusr1, sigalarm, num_kids, in_child;
static pid_t pid;
static int pipewrite;
static int set_dns_listeners(struct daemon *daemon, fd_set *set, int maxfd);
static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now);
@@ -51,12 +47,12 @@ static void sig_handler(int sig);
int main (int argc, char **argv)
{
struct daemon *daemon;
int first_loop = 1;
int bind_fallback = 0;
time_t now, last = 0;
struct sigaction sigact;
sigset_t sigmask;
struct iname *if_tmp;
int flags, piperead, pipefd[2];
unsigned char sig;
#ifndef NO_GETTEXT
setlocale(LC_ALL, "");
@@ -64,16 +60,7 @@ int main (int argc, char **argv)
textdomain("dnsmasq");
#endif
sighup = 1; /* init cache the first time through */
sigusr1 = 0; /* but don't dump */
sigterm = 0; /* or die */
#ifdef HAVE_BROKEN_RTC
sigalarm = 1; /* need regular lease dumps */
#else
sigalarm = 0; /* or not */
#endif
num_kids = 0;
in_child = 0;
pid = 0;
sigact.sa_handler = sig_handler;
sigact.sa_flags = 0;
@@ -88,15 +75,6 @@ int main (int argc, char **argv)
sigact.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sigact, NULL);
/* now block all the signals, they stay that way except
during the call to pselect */
sigaddset(&sigact.sa_mask, SIGUSR1);
sigaddset(&sigact.sa_mask, SIGTERM);
sigaddset(&sigact.sa_mask, SIGHUP);
sigaddset(&sigact.sa_mask, SIGALRM);
sigaddset(&sigact.sa_mask, SIGCHLD);
sigprocmask(SIG_BLOCK, &sigact.sa_mask, &sigmask);
daemon = read_opts(argc, argv, compile_opts);
if (daemon->edns_pktsz < PACKETSZ)
@@ -115,7 +93,12 @@ int main (int argc, char **argv)
die(_("ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h"), NULL);
#endif
if (!enumerate_interfaces(daemon, &daemon->interfaces, NULL, NULL))
#ifdef HAVE_LINUX_NETWORK
netlink_init(daemon);
#endif
daemon->interfaces = NULL;
if (!enumerate_interfaces(daemon))
die(_("failed to find list of interfaces: %s"), NULL);
if (!(daemon->options & OPT_NOWILD) &&
@@ -127,7 +110,7 @@ int main (int argc, char **argv)
if (daemon->options & OPT_NOWILD)
{
daemon->listeners = create_bound_listeners(daemon->interfaces, daemon->port);
daemon->listeners = create_bound_listeners(daemon);
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
if (if_tmp->name && !if_tmp->used)
@@ -144,16 +127,11 @@ int main (int argc, char **argv)
forward_init(1);
cache_init(daemon->cachesize, daemon->options & OPT_LOG);
#ifdef HAVE_BROKEN_RTC
if ((daemon->uptime_fd = open(UPTIME, O_RDONLY)) == -1)
die(_("cannot open %s:%s"), UPTIME);
#endif
now = dnsmasq_time(daemon->uptime_fd);
now = dnsmasq_time();
if (daemon->dhcp)
{
#if !defined(IP_PKTINFO) && !defined(IP_RECVIF)
#if !defined(HAVE_LINUX_NETWORK) && !defined(IP_RECVIF)
int c;
struct iname *tmp;
for (c = 0, tmp = daemon->if_names; tmp; tmp = tmp->next)
@@ -196,7 +174,8 @@ int main (int argc, char **argv)
addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = in6addr_any;
addr.in6.sin6_port = htons(daemon->query_port);
addr.in6.sin6_flowinfo = htonl(0);
addr.in6.sin6_flowinfo = 0;
addr.in6.sin6_scope_id = 0;
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif
@@ -204,15 +183,49 @@ int main (int argc, char **argv)
#endif
}
setbuf(stdout, NULL);
if (!(daemon->options & OPT_DEBUG))
/* Use a pipe to carry signals back to the event loop in a race-free manner */
if (pipe(pipefd) == -1 ||
(flags = fcntl(pipefd[0], F_GETFL)) == -1 ||
fcntl(pipefd[0], F_SETFL, flags | O_NONBLOCK) == -1 ||
(flags = fcntl(pipefd[1], F_GETFL)) == -1 ||
fcntl(pipefd[1], F_SETFL, flags | O_NONBLOCK) == -1)
die(_("cannot create pipe: %s"), NULL);
piperead = pipefd[0];
pipewrite = pipefd[1];
/* prime the pipe to load stuff first time. */
sig = SIGHUP;
write(pipewrite, &sig, 1);
if (!(daemon->options & OPT_DEBUG))
{
FILE *pidfile;
struct passwd *ent_pw;
struct passwd *ent_pw = daemon->username ? getpwnam(daemon->username) : NULL;
fd_set test_set;
int maxfd, i;
int maxfd, i;
#ifdef HAVE_LINUX_NETWORK
cap_user_header_t hdr = NULL;
cap_user_data_t data = NULL;
/* On linux, we keep CAP_NETADMIN (for ARP-injection) and
CAP_NET_RAW (for icmp) if we're doing dhcp */
if (ent_pw)
{
hdr = safe_malloc(sizeof(*hdr));
data = safe_malloc(sizeof(*data));
hdr->version = _LINUX_CAPABILITY_VERSION;
hdr->pid = 0; /* this process */
data->effective = data->permitted = data->inheritable =
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
(1 << CAP_SETGID) | (1 << CAP_SETUID);
/* Tell kernel to not clear capabilities when dropping root */
if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1) == -1)
die(_("Cannot set capabilities: %s"), NULL);
}
#endif
FD_ZERO(&test_set);
maxfd = set_dns_listeners(daemon, &test_set, -1);
#ifdef HAVE_DBUS
@@ -249,16 +262,21 @@ int main (int argc, char **argv)
for (i=0; i<64; i++)
{
#ifdef HAVE_BROKEN_RTC
if (i == daemon->uptime_fd)
if (i == piperead || i == pipewrite)
continue;
#ifdef HAVE_LINUX_NETWORK
if (i == daemon->netlinkfd)
continue;
#endif
if (daemon->dhcp &&
(i == fileno(daemon->lease_stream) ||
i == daemon->dhcpfd ||
#ifndef HAVE_LINUX_NETWORK
i == daemon->dhcp_raw_fd ||
i == daemon->dhcp_icmp_fd))
i == daemon->dhcp_icmp_fd ||
#endif
i == daemon->dhcpfd))
continue;
if (i <= maxfd && FD_ISSET(i, &test_set))
@@ -268,10 +286,11 @@ int main (int argc, char **argv)
}
/* Change uid and gid for security */
if (daemon->username && (ent_pw = getpwnam(daemon->username)))
if (ent_pw)
{
gid_t dummy;
struct group *gp;
/* remove all supplimentary groups */
setgroups(0, &dummy);
/* change group for /etc/ppp/resolv.conf
@@ -281,8 +300,21 @@ int main (int argc, char **argv)
setgid(gp->gr_gid);
/* finally drop root */
setuid(ent_pw->pw_uid);
#ifdef HAVE_LINUX_NETWORK
data->effective = data->permitted =
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
data->inheritable = 0;
/* lose the setuid and setgid capbilities */
capset(hdr, data);
#endif
}
}
#ifdef HAVE_LINUX_NETWORK
else
prctl(PR_SET_DUMPABLE, 1);
#endif
openlog("dnsmasq",
DNSMASQ_LOG_OPT(daemon->options & OPT_DEBUG),
@@ -312,12 +344,7 @@ int main (int argc, char **argv)
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
if (if_tmp->name && !if_tmp->used)
syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
#ifdef HAVE_RTNETLINK
/* Must do this after daemonizing so that the pid is right */
netlink_init(daemon);
#endif
if (daemon->dhcp)
{
struct dhcp_context *dhcp_tmp;
@@ -332,16 +359,6 @@ int main (int argc, char **argv)
_("DHCP, IP range %s -- %s, lease time %s"),
daemon->dhcp_buff, inet_ntoa(dhcp_tmp->end), daemon->dhcp_buff2);
}
#ifdef HAVE_BROKEN_RTC
daemon->min_leasetime = daemon->min_leasetime/3;
if (daemon->min_leasetime > (60 * 60 * 24))
daemon->min_leasetime = 60 * 60 * 24;
if (daemon->min_leasetime < 60)
daemon->min_leasetime = 60;
prettyprint_time(daemon->dhcp_buff2, daemon->min_leasetime);
syslog(LOG_INFO, _("DHCP, %s will be written every %s"), daemon->lease_file, daemon->dhcp_buff2);
#endif
}
if (!(daemon->options & OPT_DEBUG) && (getuid() == 0 || geteuid() == 0))
@@ -349,111 +366,58 @@ int main (int argc, char **argv)
check_servers(daemon);
while (sigterm == 0)
pid = getpid();
while (1)
{
int maxfd;
struct timeval t, *tp = NULL;
fd_set rset, wset, eset;
if (sighup)
{
clear_cache_and_reload(daemon, now);
if (daemon->resolv_files && (daemon->options & OPT_NO_POLL))
{
reload_servers(daemon->resolv_files->name, daemon);
check_servers(daemon);
}
sighup = 0;
}
if (sigusr1)
{
dump_cache(daemon);
sigusr1 = 0;
}
if (sigalarm)
{
if (daemon->dhcp)
{
lease_update_file(daemon, 1, now);
#ifdef HAVE_BROKEN_RTC
alarm(daemon->min_leasetime);
#endif
}
sigalarm = 0;
}
t.tv_sec = 0; /* no warning */
FD_ZERO(&rset);
FD_ZERO(&wset);
FD_ZERO(&eset);
if (!first_loop)
maxfd = set_dns_listeners(daemon, &rset, -1);
#ifdef HAVE_DBUS
/* Whilst polling for the dbus, wake every quarter second */
if ((daemon->options & OPT_DBUS) && !daemon->dbus)
{
int maxfd = set_dns_listeners(daemon, &rset, -1);
#ifdef HAVE_DBUS
maxfd = set_dbus_listeners(daemon, maxfd, &rset, &wset, &eset);
#endif
if (daemon->dhcp)
{
FD_SET(daemon->dhcpfd, &rset);
if (daemon->dhcpfd > maxfd)
maxfd = daemon->dhcpfd;
}
#ifdef HAVE_RTNETLINK
if (daemon->netlinkfd != -1)
{
FD_SET(daemon->netlinkfd, &rset);
if (daemon->netlinkfd > maxfd)
maxfd = daemon->netlinkfd;
}
#endif
/* Whilst polling for the dbus, wake every quarter second */
#ifdef HAVE_PSELECT
{
struct timespec *tp = NULL;
#ifdef HAVE_DBUS
struct timespec t;
if ((daemon->options & OPT_DBUS) && !daemon->dbus)
{
tp = &t;
tp->tv_sec = 0;
tp->tv_nsec = 250000000;
}
#endif
if (pselect(maxfd+1, &rset, &wset, &eset, tp, &sigmask) < 0)
{
/* otherwise undefined after error */
FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
}
}
#else
{
sigset_t save_mask;
struct timeval *tp = NULL;
#ifdef HAVE_DBUS
struct timeval t;
if ((daemon->options & OPT_DBUS) && !daemon->dbus)
{
tp = &t;
tp->tv_sec = 0;
tp->tv_usec = 250000;
}
#endif
sigprocmask(SIG_SETMASK, &sigmask, &save_mask);
if (select(maxfd+1, &rset, &wset, &eset, tp) < 0)
{
/* otherwise undefined after error */
FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
}
sigprocmask(SIG_SETMASK, &save_mask, NULL);
}
#endif
tp = &t;
tp->tv_sec = 0;
tp->tv_usec = 250000;
}
maxfd = set_dbus_listeners(daemon, maxfd, &rset, &wset, &eset);
#endif
if (daemon->dhcp)
{
FD_SET(daemon->dhcpfd, &rset);
if (daemon->dhcpfd > maxfd)
maxfd = daemon->dhcpfd;
}
#ifdef HAVE_LINUX_NETWORK
FD_SET(daemon->netlinkfd, &rset);
if (daemon->netlinkfd > maxfd)
maxfd = daemon->netlinkfd;
#endif
first_loop = 0;
now = dnsmasq_time(daemon->uptime_fd);
FD_SET(piperead, &rset);
if (piperead > maxfd)
maxfd = piperead;
if (select(maxfd+1, &rset, &wset, &eset, tp) < 0)
{
/* otherwise undefined after error */
FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
}
now = dnsmasq_time();
/* Check for changes to resolv files once per second max. */
/* Don't go silent for long periods if the clock goes backwards. */
@@ -506,8 +470,46 @@ int main (int argc, char **argv)
}
}
#ifdef HAVE_RTNETLINK
if (daemon->netlinkfd != -1 && FD_ISSET(daemon->netlinkfd, &rset))
if (FD_ISSET(piperead, &rset))
{
if (read(piperead, &sig, 1) == 1)
switch (sig)
{
case SIGHUP:
clear_cache_and_reload(daemon);
if (daemon->resolv_files && (daemon->options & OPT_NO_POLL))
{
reload_servers(daemon->resolv_files->name, daemon);
check_servers(daemon);
}
break;
case SIGUSR1:
dump_cache(daemon, now);
break;
case SIGALRM:
if (daemon->dhcp)
lease_update_file(daemon);
break;
case SIGTERM:
syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
if (daemon->dhcp)
fclose(daemon->lease_stream);
exit(0);
case SIGCHLD:
/* See Stevens 5.10 */
while (waitpid(-1, NULL, WNOHANG) > 0)
daemon->num_kids--;
break;
}
}
#ifdef HAVE_LINUX_NETWORK
if (FD_ISSET(daemon->netlinkfd, &rset))
netlink_multicast(daemon);
#endif
@@ -529,47 +531,34 @@ int main (int argc, char **argv)
if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
dhcp_packet(daemon, now);
}
syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
if (daemon->dhcp)
{
#ifdef HAVE_BROKEN_RTC
lease_update_file(daemon, 1, now);
#endif
fclose(daemon->lease_stream);
}
return 0;
}
static void sig_handler(int sig)
{
if (sig == SIGTERM)
sigterm = 1;
else if (sig == SIGHUP)
sighup = 1;
else if (sig == SIGUSR1)
sigusr1 = 1;
else if (sig == SIGALRM)
if (pid == 0)
{
/* ignore anything other than TERM during startup */
if (sig == SIGTERM)
exit(0);
}
else if (pid == getpid())
{
/* master process */
unsigned char sigchr = sig;
int errsave = errno;
write(pipewrite, &sigchr, 1);
errno = errsave;
}
else
{
/* alarm is used to kill children after a fixed time. */
if (in_child)
if (sig == SIGALRM)
exit(0);
else
sigalarm = 1;
}
else if (sig == SIGCHLD)
{
/* See Stevens 5.10 */
while (waitpid(-1, NULL, WNOHANG) > 0)
num_kids--;
}
}
void clear_cache_and_reload(struct daemon *daemon, time_t now)
void clear_cache_and_reload(struct daemon *daemon)
{
cache_reload(daemon->options, daemon->namebuff, daemon->domain_suffix, daemon->addn_hosts);
if (daemon->dhcp)
@@ -578,7 +567,7 @@ void clear_cache_and_reload(struct daemon *daemon, time_t now)
dhcp_read_ethers(daemon);
dhcp_update_configs(daemon->dhcp_conf);
lease_update_from_configs(daemon);
lease_update_file(daemon, 0, now);
lease_update_file(daemon);
lease_update_dns(daemon);
}
}
@@ -625,30 +614,39 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now)
if (FD_ISSET(listener->tcpfd, set))
{
int confd;
struct in_addr netmask, dst_addr_4;
while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
if (confd != -1)
{
union mysockaddr tcp_addr;
socklen_t tcp_len = sizeof(union mysockaddr);
/* Check for allowed interfaces when binding the wildcard address:
we do this by looking for an interface with the same address as
the local address of the TCP connection, then looking to see if that's
an allowed interface. As a side effect, we get the netmask of the
interface too, for localisation. */
if ((num_kids >= MAX_PROCS) ||
(!(daemon->options & OPT_NOWILD) &&
(getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1 ||
!enumerate_interfaces(daemon, NULL, &tcp_addr, &netmask))))
struct irec *iface = NULL;
if (daemon->options & OPT_NOWILD)
iface = listener->iface;
else
{
union mysockaddr tcp_addr;
socklen_t tcp_len = sizeof(union mysockaddr);
/* Check for allowed interfaces when binding the wildcard address:
we do this by looking for an interface with the same address as
the local address of the TCP connection, then looking to see if that's
an allowed interface. As a side effect, we get the netmask of the
interface too, for localisation. */
/* interface may be new since startup */
if (enumerate_interfaces(daemon) &&
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) != -1)
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr))
break;
}
if ((daemon->num_kids >= MAX_PROCS) || !iface)
close(confd);
#ifndef NO_FORK
else if (!(daemon->options & OPT_DEBUG) && fork())
{
num_kids++;
daemon->num_kids++;
close(confd);
}
#endif
@@ -657,18 +655,14 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now)
unsigned char *buff;
struct server *s;
int flags;
struct in_addr dst_addr_4;
dst_addr_4.s_addr = 0;
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to
terminate the process. */
if (!(daemon->options & OPT_DEBUG))
{
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGALRM);
sigprocmask(SIG_UNBLOCK, &mask, NULL);
alarm(CHILD_LIFETIME);
in_child = 1;
}
alarm(CHILD_LIFETIME);
/* start with no upstream connections. */
for (s = daemon->servers; s; s = s->next)
@@ -681,20 +675,9 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now)
fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
if (listener->family == AF_INET)
{
if (daemon->options & OPT_NOWILD)
{
netmask = listener->iface->netmask;
dst_addr_4 = listener->iface->addr.in.sin_addr;
}
else
/* netmask already set by enumerate_interfaces */
dst_addr_4 = tcp_addr.in.sin_addr;
}
else
dst_addr_4.s_addr = 0;
dst_addr_4 = iface->addr.in.sin_addr;
buff = tcp_request(daemon, confd, now, dst_addr_4, netmask);
buff = tcp_request(daemon, confd, now, dst_addr_4, iface->netmask);
if (!(daemon->options & OPT_DEBUG))
exit(0);
@@ -711,21 +694,35 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now)
}
}
int make_icmp_sock(void)
{
int fd, flags;
int zeroopt = 0;
if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
{
if ((flags = fcntl(fd, F_GETFL, 0)) == -1 ||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
{
close(fd);
fd = -1;
}
}
return fd;
}
int icmp_ping(struct daemon *daemon, struct in_addr addr)
{
/* Try and get an ICMP echo from a machine.
Note that we can't create the raw socket each time
we do this, since that needs root. Therefore the socket has to hang
around all the time. Since most of the time we won't read the
socket, it will accumulate buffers full of ICMP messages,
wasting memory. To avoid that we set the receive buffer
length to zero except when we're actively pinging. */
/* Try and get an ICMP echo from a machine. */
/* Note that whilst in the three second wait, we check for
(and service) events on the DNS sockets, (so doing that
better not use any resources our caller has in use...)
but we remain deaf to signals or further DHCP packets. */
int fd;
struct sockaddr_in saddr;
struct {
struct ip ip;
@@ -733,9 +730,18 @@ int icmp_ping(struct daemon *daemon, struct in_addr addr)
} packet;
unsigned short id = rand16();
unsigned int i, j;
int opt = 2000, gotreply = 0;
int gotreply = 0;
time_t start, now;
#ifdef HAVE_LINUX_NETWORK
if ((fd = make_icmp_sock()) == -1)
return 0;
#else
int opt = 2000;
fd = daemon->dhcp_icmp_fd;
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
#endif
saddr.sin_family = AF_INET;
saddr.sin_port = 0;
saddr.sin_addr = addr;
@@ -752,13 +758,12 @@ int icmp_ping(struct daemon *daemon, struct in_addr addr)
j = (j & 0xffff) + (j >> 16);
packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
while (sendto(daemon->dhcp_icmp_fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
while (sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
(struct sockaddr *)&saddr, sizeof(saddr)) == -1 &&
retry_send());
for (now = start = dnsmasq_time(daemon->uptime_fd); difftime(now, start) < 3.0;)
for (now = start = dnsmasq_time();
difftime(now, start) < (float)PING_WAIT;)
{
struct timeval tv;
fd_set rset;
@@ -770,17 +775,17 @@ int icmp_ping(struct daemon *daemon, struct in_addr addr)
tv.tv_sec = 0;
FD_ZERO(&rset);
FD_SET(daemon->dhcp_icmp_fd, &rset);
maxfd = set_dns_listeners(daemon, &rset, daemon->dhcp_icmp_fd);
FD_SET(fd, &rset);
maxfd = set_dns_listeners(daemon, &rset, fd);
if (select(maxfd+1, &rset, NULL, NULL, &tv) < 0)
FD_ZERO(&rset);
now = dnsmasq_time(daemon->uptime_fd);
now = dnsmasq_time();
check_dns_listeners(daemon, &rset, now);
if (FD_ISSET(daemon->dhcp_icmp_fd, &rset) &&
recvfrom(daemon->dhcp_icmp_fd, &packet, sizeof(packet), 0,
if (FD_ISSET(fd, &rset) &&
recvfrom(fd, &packet, sizeof(packet), 0,
(struct sockaddr *)&faddr, &len) == sizeof(packet) &&
saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
packet.icmp.icmp_type == ICMP_ECHOREPLY &&
@@ -792,9 +797,13 @@ int icmp_ping(struct daemon *daemon, struct in_addr addr)
}
}
#ifdef HAVE_LINUX_NETWORK
close(fd);
#else
opt = 1;
setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
#endif
return gotreply;
}