1 /* dnsmasq is Copyright (c) 2000-2006 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
15 static char *compile_opts
=
20 #ifndef HAVE_GETOPT_LONG
24 #ifdef HAVE_BROKEN_RTC
27 #ifndef HAVE_ISC_READER
43 static int set_dns_listeners(struct daemon
*daemon
, fd_set
*set
, int maxfd
);
44 static void check_dns_listeners(struct daemon
*daemon
, fd_set
*set
, time_t now
);
45 static void sig_handler(int sig
);
47 int main (int argc
, char **argv
)
49 struct daemon
*daemon
;
50 int bind_fallback
= 0;
51 int bad_capabilities
= 0;
53 struct sigaction sigact
;
55 int piperead
, pipefd
[2];
59 setlocale(LC_ALL
, "");
60 bindtextdomain("dnsmasq", LOCALEDIR
);
61 textdomain("dnsmasq");
66 sigact
.sa_handler
= sig_handler
;
68 sigemptyset(&sigact
.sa_mask
);
69 sigaction(SIGUSR1
, &sigact
, NULL
);
70 sigaction(SIGHUP
, &sigact
, NULL
);
71 sigaction(SIGTERM
, &sigact
, NULL
);
72 sigaction(SIGALRM
, &sigact
, NULL
);
73 sigaction(SIGCHLD
, &sigact
, NULL
);
76 sigact
.sa_handler
= SIG_IGN
;
77 sigaction(SIGPIPE
, &sigact
, NULL
);
79 daemon
= read_opts(argc
, argv
, compile_opts
);
81 if (daemon
->edns_pktsz
< PACKETSZ
)
82 daemon
->edns_pktsz
= PACKETSZ
;
83 daemon
->packet_buff_sz
= daemon
->edns_pktsz
> DNSMASQ_PACKETSZ
?
84 daemon
->edns_pktsz
: DNSMASQ_PACKETSZ
;
85 daemon
->packet
= safe_malloc(daemon
->packet_buff_sz
);
87 if (!daemon
->lease_file
)
90 daemon
->lease_file
= LEASEFILE
;
92 #ifndef HAVE_ISC_READER
93 else if (!daemon
->dhcp
)
94 die(_("ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h"), NULL
);
97 #ifdef HAVE_LINUX_NETWORK
99 #elif !(defined(IP_RECVDSTADDR) && \
100 defined(IP_RECVIF) && \
101 defined(IP_SENDSRCADDR))
102 if (!(daemon
->options
& OPT_NOWILD
))
105 daemon
->options
|= OPT_NOWILD
;
109 daemon
->interfaces
= NULL
;
110 if (!enumerate_interfaces(daemon
))
111 die(_("failed to find list of interfaces: %s"), NULL
);
113 if (daemon
->options
& OPT_NOWILD
)
115 daemon
->listeners
= create_bound_listeners(daemon
);
117 for (if_tmp
= daemon
->if_names
; if_tmp
; if_tmp
= if_tmp
->next
)
118 if (if_tmp
->name
&& !if_tmp
->used
)
119 die(_("unknown interface %s"), if_tmp
->name
);
121 for (if_tmp
= daemon
->if_addrs
; if_tmp
; if_tmp
= if_tmp
->next
)
124 prettyprint_addr(&if_tmp
->addr
, daemon
->namebuff
);
125 die(_("no interface with address %s"), daemon
->namebuff
);
128 else if (!(daemon
->listeners
= create_wildcard_listeners(daemon
->port
)))
129 die(_("failed to create listening socket: %s"), NULL
);
131 cache_init(daemon
->cachesize
, daemon
->options
& OPT_LOG
);
133 now
= dnsmasq_time();
137 #if !defined(HAVE_LINUX_NETWORK) && !defined(IP_RECVIF)
140 for (c
= 0, tmp
= daemon
->if_names
; tmp
; tmp
= tmp
->next
)
144 die(_("must set exactly one interface on broken systems without IP_RECVIF"), NULL
);
147 lease_init(daemon
, now
);
150 if (daemon
->options
& OPT_DBUS
)
155 daemon
->watches
= NULL
;
156 if ((err
= dbus_init(daemon
)))
157 die(_("DBus error: %s"), err
);
160 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL
);
163 /* If query_port is set then create a socket now, before dumping root
164 for use to access nameservers without more specific source addresses.
165 This allows query_port to be a low port */
166 if (daemon
->query_port
)
168 union mysockaddr addr
;
169 memset(&addr
, 0, sizeof(addr
));
170 addr
.in
.sin_family
= AF_INET
;
171 addr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
172 addr
.in
.sin_port
= htons(daemon
->query_port
);
173 #ifdef HAVE_SOCKADDR_SA_LEN
174 addr
.in
.sin_len
= sizeof(struct sockaddr_in
);
176 allocate_sfd(&addr
, &daemon
->sfds
);
178 memset(&addr
, 0, sizeof(addr
));
179 addr
.in6
.sin6_family
= AF_INET6
;
180 addr
.in6
.sin6_addr
= in6addr_any
;
181 addr
.in6
.sin6_port
= htons(daemon
->query_port
);
182 #ifdef HAVE_SOCKADDR_SA_LEN
183 addr
.in6
.sin6_len
= sizeof(struct sockaddr_in6
);
185 allocate_sfd(&addr
, &daemon
->sfds
);
189 /* Use a pipe to carry signals back to the event loop in a race-free manner */
190 if (pipe(pipefd
) == -1 || !fix_fd(pipefd
[0]) || !fix_fd(pipefd
[1]))
191 die(_("cannot create pipe: %s"), NULL
);
193 piperead
= pipefd
[0];
194 pipewrite
= pipefd
[1];
195 /* prime the pipe to load stuff first time. */
197 write(pipewrite
, &sig
, 1);
199 if (daemon
->options
& OPT_DEBUG
)
202 openlog("dnsmasq", LOG_PERROR
, daemon
->log_fac
);
204 openlog("dnsmasq", 0, daemon
->log_fac
);
207 #ifdef HAVE_LINUX_NETWORK
208 prctl(PR_SET_DUMPABLE
, 1);
214 struct passwd
*ent_pw
= daemon
->username
? getpwnam(daemon
->username
) : NULL
;
217 int nullfd
= open("/dev/null", O_RDWR
);
219 #ifdef HAVE_LINUX_NETWORK
220 cap_user_header_t hdr
= NULL
;
221 cap_user_data_t data
= NULL
;
223 /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
224 CAP_NET_RAW (for icmp) if we're doing dhcp */
225 if (ent_pw
&& ent_pw
->pw_uid
!= 0)
227 hdr
= safe_malloc(sizeof(*hdr
));
228 data
= safe_malloc(sizeof(*data
));
229 hdr
->version
= _LINUX_CAPABILITY_VERSION
;
230 hdr
->pid
= 0; /* this process */
231 data
->effective
= data
->permitted
= data
->inheritable
=
232 (1 << CAP_NET_ADMIN
) | (1 << CAP_NET_RAW
) |
233 (1 << CAP_SETGID
) | (1 << CAP_SETUID
);
235 /* Tell kernel to not clear capabilities when dropping root */
236 if (capset(hdr
, data
) == -1 || prctl(PR_SET_KEEPCAPS
, 1) == -1)
238 bad_capabilities
= errno
;
245 maxfd
= set_dns_listeners(daemon
, &test_set
, -1);
247 maxfd
= set_dbus_listeners(daemon
, maxfd
, &test_set
, &test_set
, &test_set
);
250 /* The following code "daemonizes" the process.
251 See Stevens section 12.4 */
254 if (!(daemon
->options
& OPT_NO_FORK
))
267 umask(022); /* make pidfile 0644 */
269 /* write pidfile _after_ forking ! */
270 if (daemon
->runfile
&& (pidfile
= fopen(daemon
->runfile
, "w")))
272 fprintf(pidfile
, "%d\n", (int) getpid());
280 if (i
== piperead
|| i
== pipewrite
)
283 #ifdef HAVE_LINUX_NETWORK
284 if (i
== daemon
->netlinkfd
)
289 ((daemon
->lease_stream
&& i
== fileno(daemon
->lease_stream
)) ||
290 #ifndef HAVE_LINUX_NETWORK
291 i
== daemon
->dhcp_raw_fd
||
292 i
== daemon
->dhcp_icmp_fd
||
294 i
== daemon
->dhcpfd
))
297 if (i
<= maxfd
&& FD_ISSET(i
, &test_set
))
300 /* open stdout etc to /dev/null */
301 if (i
== STDOUT_FILENO
|| i
== STDERR_FILENO
|| i
== STDIN_FILENO
)
307 if (daemon
->groupname
|| ent_pw
)
312 /* change group for /etc/ppp/resolv.conf otherwise get the group for "nobody" */
313 if ((daemon
->groupname
&& (gp
= getgrnam(daemon
->groupname
))) ||
314 (ent_pw
&& (gp
= getgrgid(ent_pw
->pw_gid
))))
316 /* remove all supplimentary groups */
317 setgroups(0, &dummy
);
322 if (ent_pw
&& ent_pw
->pw_uid
!= 0)
324 /* finally drop root */
325 setuid(ent_pw
->pw_uid
);
327 #ifdef HAVE_LINUX_NETWORK
328 data
->effective
= data
->permitted
=
329 (1 << CAP_NET_ADMIN
) | (1 << CAP_NET_RAW
);
330 data
->inheritable
= 0;
332 /* lose the setuid and setgid capbilities */
337 openlog("dnsmasq", LOG_PID
, daemon
->log_fac
);
340 if (daemon
->cachesize
!= 0)
341 syslog(LOG_INFO
, _("started, version %s cachesize %d"), VERSION
, daemon
->cachesize
);
343 syslog(LOG_INFO
, _("started, version %s cache disabled"), VERSION
);
345 syslog(LOG_INFO
, _("compile time options: %s"), compile_opts
);
348 if (daemon
->options
& OPT_DBUS
)
351 syslog(LOG_INFO
, _("DBus support enabled: connected to system bus"));
353 syslog(LOG_INFO
, _("DBus support enabled: bus connection pending"));
358 syslog(LOG_WARNING
, _("setting --bind-interfaces option because of OS limitations"));
360 if (!(daemon
->options
& OPT_NOWILD
))
361 for (if_tmp
= daemon
->if_names
; if_tmp
; if_tmp
= if_tmp
->next
)
362 if (if_tmp
->name
&& !if_tmp
->used
)
363 syslog(LOG_WARNING
, _("warning: interface %s does not currently exist"), if_tmp
->name
);
365 if (daemon
->options
& OPT_NO_RESOLV
)
367 if (daemon
->resolv_files
&& !daemon
->resolv_files
->is_default
)
368 syslog(LOG_WARNING
, _("warning: ignoring resolv-file flag because no-resolv is set"));
369 daemon
->resolv_files
= NULL
;
374 struct dhcp_context
*dhcp_tmp
;
376 for (dhcp_tmp
= daemon
->dhcp
; dhcp_tmp
; dhcp_tmp
= dhcp_tmp
->next
)
378 prettyprint_time(daemon
->dhcp_buff2
, dhcp_tmp
->lease_time
);
379 strcpy(daemon
->dhcp_buff
, inet_ntoa(dhcp_tmp
->start
));
381 (dhcp_tmp
->flags
& CONTEXT_STATIC
) ?
382 _("DHCP, static leases only on %.0s%s, lease time %s") :
383 _("DHCP, IP range %s -- %s, lease time %s"),
384 daemon
->dhcp_buff
, inet_ntoa(dhcp_tmp
->end
), daemon
->dhcp_buff2
);
388 if (!(daemon
->options
& OPT_DEBUG
) && (getuid() == 0 || geteuid() == 0))
390 if (bad_capabilities
)
392 errno
= bad_capabilities
;
393 syslog(LOG_WARNING
, _("warning: setting capabilities failed: %m"));
395 syslog(LOG_WARNING
, _("running as root"));
398 check_servers(daemon
);
402 /* Start lease-change script */
404 lease_collect(daemon
);
409 struct timeval t
, *tp
= NULL
;
410 fd_set rset
, wset
, eset
;
412 t
.tv_sec
= 0; /* no warning */
418 maxfd
= set_dns_listeners(daemon
, &rset
, -1);
421 /* Whilst polling for the dbus, wake every quarter second */
422 if ((daemon
->options
& OPT_DBUS
) && !daemon
->dbus
)
426 tp
->tv_usec
= 250000;
429 maxfd
= set_dbus_listeners(daemon
, maxfd
, &rset
, &wset
, &eset
);
434 FD_SET(daemon
->dhcpfd
, &rset
);
435 if (daemon
->dhcpfd
> maxfd
)
436 maxfd
= daemon
->dhcpfd
;
439 #ifdef HAVE_LINUX_NETWORK
440 FD_SET(daemon
->netlinkfd
, &rset
);
441 if (daemon
->netlinkfd
> maxfd
)
442 maxfd
= daemon
->netlinkfd
;
445 FD_SET(piperead
, &rset
);
446 if (piperead
> maxfd
)
449 if (select(maxfd
+1, &rset
, &wset
, &eset
, tp
) < 0)
451 /* otherwise undefined after error */
452 FD_ZERO(&rset
); FD_ZERO(&wset
); FD_ZERO(&eset
);
455 now
= dnsmasq_time();
457 /* Check for changes to resolv files once per second max. */
458 /* Don't go silent for long periods if the clock goes backwards. */
459 if (last
== 0 || difftime(now
, last
) > 1.0 || difftime(now
, last
) < -1.0)
463 #ifdef HAVE_ISC_READER
464 if (daemon
->lease_file
&& !daemon
->dhcp
)
465 load_dhcp(daemon
, now
);
468 if (!(daemon
->options
& OPT_NO_POLL
))
470 struct resolvc
*res
, *latest
;
472 time_t last_change
= 0;
473 /* There may be more than one possible file.
474 Go through and find the one which changed _last_.
475 Warn of any which can't be read. */
476 for (latest
= NULL
, res
= daemon
->resolv_files
; res
; res
= res
->next
)
477 if (stat(res
->name
, &statbuf
) == -1)
480 syslog(LOG_WARNING
, _("failed to access %s: %m"), res
->name
);
486 if (statbuf
.st_mtime
!= res
->mtime
)
488 res
->mtime
= statbuf
.st_mtime
;
489 if (difftime(statbuf
.st_mtime
, last_change
) > 0.0)
491 last_change
= statbuf
.st_mtime
;
499 static int warned
= 0;
500 if (reload_servers(latest
->name
, daemon
))
502 syslog(LOG_INFO
, _("reading %s"), latest
->name
);
504 check_servers(daemon
);
511 syslog(LOG_WARNING
, _("no servers found in %s, will retry"), latest
->name
);
519 if (FD_ISSET(piperead
, &rset
))
523 if (read(piperead
, &sig
, 1) == 1)
527 clear_cache_and_reload(daemon
, now
);
528 if (daemon
->resolv_files
&& (daemon
->options
& OPT_NO_POLL
))
530 reload_servers(daemon
->resolv_files
->name
, daemon
);
531 check_servers(daemon
);
536 dump_cache(daemon
, now
);
542 lease_prune(NULL
, now
);
543 lease_update_file(daemon
, now
);
544 lease_collect(daemon
);
551 syslog(LOG_INFO
, _("exiting on receipt of SIGTERM"));
552 /* Knock all our children on the head. */
553 for (i
= 0; i
< MAX_PROCS
; i
++)
554 if (daemon
->tcp_pids
[i
] != 0)
555 kill(daemon
->tcp_pids
[i
], SIGALRM
);
557 if (daemon
->lease_stream
)
558 fclose(daemon
->lease_stream
);
564 /* See Stevens 5.10 */
565 /* Note that if a script process forks and then exits
566 without waiting for its child, we will reap that child.
567 It is not therefore safe to assume that any dieing children
568 whose pid != script_pid are TCP server threads. */
569 while ((p
= waitpid(-1, NULL
, WNOHANG
)) > 0)
571 if (p
== daemon
->script_pid
)
573 daemon
->script_pid
= 0;
574 lease_collect(daemon
);
579 for (i
= 0 ; i
< MAX_PROCS
; i
++)
580 if (daemon
->tcp_pids
[i
] == p
)
582 daemon
->tcp_pids
[i
] = 0;
592 #ifdef HAVE_LINUX_NETWORK
593 if (FD_ISSET(daemon
->netlinkfd
, &rset
))
594 netlink_multicast(daemon
);
598 /* if we didn't create a DBus connection, retry now. */
599 if ((daemon
->options
& OPT_DBUS
) && !daemon
->dbus
)
602 if ((err
= dbus_init(daemon
)))
603 syslog(LOG_WARNING
, _("DBus error: %s"), err
);
605 syslog(LOG_INFO
, _("connected to system DBus"));
607 check_dbus_listeners(daemon
, &rset
, &wset
, &eset
);
610 check_dns_listeners(daemon
, &rset
, now
);
612 if (daemon
->dhcp
&& FD_ISSET(daemon
->dhcpfd
, &rset
))
613 dhcp_packet(daemon
, now
);
617 static void sig_handler(int sig
)
621 /* ignore anything other than TERM during startup */
625 else if (pid
== getpid())
628 unsigned char sigchr
= sig
;
630 write(pipewrite
, &sigchr
, 1);
635 /* alarm is used to kill children after a fixed time. */
642 void clear_cache_and_reload(struct daemon
*daemon
, time_t now
)
644 cache_reload(daemon
->options
, daemon
->namebuff
, daemon
->domain_suffix
, daemon
->addn_hosts
);
647 if (daemon
->options
& OPT_ETHERS
)
648 dhcp_read_ethers(daemon
);
649 dhcp_update_configs(daemon
->dhcp_conf
);
650 lease_update_from_configs(daemon
);
651 lease_update_file(daemon
, now
);
652 lease_update_dns(daemon
);
656 static int set_dns_listeners(struct daemon
*daemon
, fd_set
*set
, int maxfd
)
658 struct serverfd
*serverfdp
;
659 struct listener
*listener
;
661 for (serverfdp
= daemon
->sfds
; serverfdp
; serverfdp
= serverfdp
->next
)
663 FD_SET(serverfdp
->fd
, set
);
664 if (serverfdp
->fd
> maxfd
)
665 maxfd
= serverfdp
->fd
;
668 for (listener
= daemon
->listeners
; listener
; listener
= listener
->next
)
670 FD_SET(listener
->fd
, set
);
671 if (listener
->fd
> maxfd
)
672 maxfd
= listener
->fd
;
673 FD_SET(listener
->tcpfd
, set
);
674 if (listener
->tcpfd
> maxfd
)
675 maxfd
= listener
->tcpfd
;
681 static void check_dns_listeners(struct daemon
*daemon
, fd_set
*set
, time_t now
)
683 struct serverfd
*serverfdp
;
684 struct listener
*listener
;
686 for (serverfdp
= daemon
->sfds
; serverfdp
; serverfdp
= serverfdp
->next
)
687 if (FD_ISSET(serverfdp
->fd
, set
))
688 reply_query(serverfdp
, daemon
, now
);
690 for (listener
= daemon
->listeners
; listener
; listener
= listener
->next
)
692 if (FD_ISSET(listener
->fd
, set
))
693 receive_query(listener
, daemon
, now
);
695 if (FD_ISSET(listener
->tcpfd
, set
))
698 struct irec
*iface
= NULL
;
701 while((confd
= accept(listener
->tcpfd
, NULL
, NULL
)) == -1 && errno
== EINTR
);
706 if (daemon
->options
& OPT_NOWILD
)
707 iface
= listener
->iface
;
710 union mysockaddr tcp_addr
;
711 socklen_t tcp_len
= sizeof(union mysockaddr
);
712 /* Check for allowed interfaces when binding the wildcard address:
713 we do this by looking for an interface with the same address as
714 the local address of the TCP connection, then looking to see if that's
715 an allowed interface. As a side effect, we get the netmask of the
716 interface too, for localisation. */
718 /* interface may be new since startup */
719 if (enumerate_interfaces(daemon
) &&
720 getsockname(confd
, (struct sockaddr
*)&tcp_addr
, &tcp_len
) != -1)
721 for (iface
= daemon
->interfaces
; iface
; iface
= iface
->next
)
722 if (sockaddr_isequal(&iface
->addr
, &tcp_addr
))
726 if ((daemon
->num_kids
>= MAX_PROCS
) || !iface
)
728 shutdown(confd
, SHUT_RDWR
);
732 else if (!(daemon
->options
& OPT_DEBUG
) && (p
= fork()) != 0)
737 for (i
= 0; i
< MAX_PROCS
; i
++)
738 if (daemon
->tcp_pids
[i
] == 0)
740 daemon
->tcp_pids
[i
] = p
;
753 struct in_addr dst_addr_4
;
755 dst_addr_4
.s_addr
= 0;
757 /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
758 terminate the process. */
759 if (!(daemon
->options
& OPT_DEBUG
))
760 alarm(CHILD_LIFETIME
);
762 /* start with no upstream connections. */
763 for (s
= daemon
->servers
; s
; s
= s
->next
)
766 /* The connected socket inherits non-blocking
767 attribute from the listening socket.
769 if ((flags
= fcntl(confd
, F_GETFL
, 0)) != -1)
770 fcntl(confd
, F_SETFL
, flags
& ~O_NONBLOCK
);
772 if (listener
->family
== AF_INET
)
773 dst_addr_4
= iface
->addr
.in
.sin_addr
;
775 buff
= tcp_request(daemon
, confd
, now
, dst_addr_4
, iface
->netmask
);
777 shutdown(confd
, SHUT_RDWR
);
783 for (s
= daemon
->servers
; s
; s
= s
->next
)
786 shutdown(s
->tcpfd
, SHUT_RDWR
);
790 if (!(daemon
->options
& OPT_DEBUG
))
799 int make_icmp_sock(void)
804 if ((fd
= socket (AF_INET
, SOCK_RAW
, IPPROTO_ICMP
)) != -1)
807 setsockopt(fd
, SOL_SOCKET
, SO_DONTROUTE
, &zeroopt
, sizeof(zeroopt
)) == -1)
817 int icmp_ping(struct daemon
*daemon
, struct in_addr addr
)
819 /* Try and get an ICMP echo from a machine. */
821 /* Note that whilst in the three second wait, we check for
822 (and service) events on the DNS sockets, (so doing that
823 better not use any resources our caller has in use...)
824 but we remain deaf to signals or further DHCP packets. */
827 struct sockaddr_in saddr
;
832 unsigned short id
= rand16();
837 #ifdef HAVE_LINUX_NETWORK
838 if ((fd
= make_icmp_sock()) == -1)
842 fd
= daemon
->dhcp_icmp_fd
;
843 setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &opt
, sizeof(opt
));
846 saddr
.sin_family
= AF_INET
;
848 saddr
.sin_addr
= addr
;
849 #ifdef HAVE_SOCKADDR_SA_LEN
850 saddr
.sin_len
= sizeof(struct sockaddr_in
);
853 memset(&packet
.icmp
, 0, sizeof(packet
.icmp
));
854 packet
.icmp
.icmp_type
= ICMP_ECHO
;
855 packet
.icmp
.icmp_id
= id
;
856 for (j
= 0, i
= 0; i
< sizeof(struct icmp
) / 2; i
++)
857 j
+= ((u16
*)&packet
.icmp
)[i
];
859 j
= (j
& 0xffff) + (j
>> 16);
860 packet
.icmp
.icmp_cksum
= (j
== 0xffff) ? j
: ~j
;
862 while (sendto(fd
, (char *)&packet
.icmp
, sizeof(struct icmp
), 0,
863 (struct sockaddr
*)&saddr
, sizeof(saddr
)) == -1 &&
866 for (now
= start
= dnsmasq_time();
867 difftime(now
, start
) < (float)PING_WAIT
;)
871 struct sockaddr_in faddr
;
873 socklen_t len
= sizeof(faddr
);
880 maxfd
= set_dns_listeners(daemon
, &rset
, fd
);
882 if (select(maxfd
+1, &rset
, NULL
, NULL
, &tv
) < 0)
885 now
= dnsmasq_time();
886 check_dns_listeners(daemon
, &rset
, now
);
888 if (FD_ISSET(fd
, &rset
) &&
889 recvfrom(fd
, &packet
, sizeof(packet
), 0,
890 (struct sockaddr
*)&faddr
, &len
) == sizeof(packet
) &&
891 saddr
.sin_addr
.s_addr
== faddr
.sin_addr
.s_addr
&&
892 packet
.icmp
.icmp_type
== ICMP_ECHOREPLY
&&
893 packet
.icmp
.icmp_seq
== 0 &&
894 packet
.icmp
.icmp_id
== id
)
901 #ifdef HAVE_LINUX_NETWORK
905 setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &opt
, sizeof(opt
));