summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2001-01-12 19:05:41 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2001-01-12 19:05:41 +0000
commitfdf11699038a3c29ccf1ca8d533167e4f59dba3b (patch)
tree5489095a7f48d6a21e31d5f0b7792f7df7705380 /sbin
parent685054b6c8bf1bb1b9f1e4c0fcee244263dd216b (diff)
minimize chance of signal handler race. big help from deraadt.
Diffstat (limited to 'sbin')
-rw-r--r--sbin/ping6/ping6.c122
1 files changed, 88 insertions, 34 deletions
diff --git a/sbin/ping6/ping6.c b/sbin/ping6/ping6.c
index 0d5e596cad7..58bb2255b76 100644
--- a/sbin/ping6/ping6.c
+++ b/sbin/ping6/ping6.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ping6.c,v 1.24 2001/01/12 18:53:37 itojun Exp $ */
-/* $KAME: ping6.c,v 1.109 2000/12/27 11:32:37 itojun Exp $ */
+/* $OpenBSD: ping6.c,v 1.25 2001/01/12 19:05:40 itojun Exp $ */
+/* $KAME: ping6.c,v 1.111 2001/01/12 19:04:03 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -242,11 +242,17 @@ struct msghdr smsghdr;
struct iovec smsgiov;
char *scmsg = 0;
+volatile int signo;
+volatile int seenalrm;
+volatile int seenint;
+volatile int seeninfo;
+
int main __P((int, char *[]));
void fill __P((char *, char *));
int get_hoplim __P((struct msghdr *));
struct in6_pktinfo *get_rcvpktinfo __P((struct msghdr *));
-void onalrm __P((int));
+void onsignal __P((int));
+void retransmit __P((void));
void oninfo __P((int));
void onint __P((int));
void pinger __P((void));
@@ -278,7 +284,7 @@ main(argc, argv)
{
struct itimerval itimer;
struct sockaddr_in6 from;
- struct timeval timeout;
+ struct timeval timeout, *tv;
struct addrinfo hints;
fd_set *fdmaskp;
int fdmasks;
@@ -294,9 +300,6 @@ main(argc, argv)
#ifdef USE_RFC2292BIS
struct ip6_rthdr *rthdr = NULL;
#endif
-#ifndef __OpenBSD__
- struct timeval tv;
-#endif
#ifdef IPSEC_POLICY_IPSEC
char *policy_in = NULL;
char *policy_out = NULL;
@@ -627,8 +630,8 @@ main(argc, argv)
ident = getpid() & 0xFFFF;
#ifndef __OpenBSD__
- gettimeofday(&tv, NULL);
- srand((unsigned int)(tv.tv_sec ^ tv.tv_usec ^ (long)ident));
+ gettimeofday(&timeout, NULL);
+ srand((unsigned int)(timeout.tv_sec ^ timeout.tv_usec ^ (long)ident));
memset(nonce, 0, sizeof(nonce));
for (i = 0; i < sizeof(nonce); i += sizeof(int))
*((int *)&nonce[i]) = rand();
@@ -957,23 +960,25 @@ main(argc, argv)
while (preload--) /* Fire off them quickies. */
pinger();
- (void)signal(SIGINT, onint);
+ (void)signal(SIGINT, onsignal);
#ifdef SIGINFO
- (void)signal(SIGINFO, oninfo);
+ (void)signal(SIGINFO, onsignal);
#endif
if ((options & F_FLOOD) == 0) {
- (void)signal(SIGALRM, onalrm);
+ (void)signal(SIGALRM, onsignal);
itimer.it_interval = interval;
- itimer.it_value.tv_sec = 0;
- itimer.it_value.tv_usec = 1;
+ itimer.it_value = interval;
(void)setitimer(ITIMER_REAL, &itimer, NULL);
+ retransmit();
}
fdmasks = howmany(s + 1, NFDBITS) * sizeof(fd_mask);
if ((fdmaskp = malloc(fdmasks)) == NULL)
err(1, "malloc");
+ signo = seenalrm = seenint = seeninfo = 0;
+
for (;;) {
struct msghdr m;
struct cmsghdr *cm;
@@ -984,11 +989,31 @@ main(argc, argv)
pinger();
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
- memset(fdmaskp, 0, fdmasks);
- FD_SET(s, fdmaskp);
- if (select(s + 1, fdmaskp, NULL, NULL, &timeout) < 1)
- continue;
- }
+ tv = &timeout;
+ } else
+ tv = NULL;
+ memset(fdmaskp, 0, fdmasks);
+ FD_SET(s, fdmaskp);
+ cc = select(s + 1, fdmaskp, NULL, NULL, tv);
+ if ((cc < 0 && errno == EINTR) || (options & F_FLOOD)) {
+ if (!signo)
+ break;
+ if (seenalrm) {
+ retransmit();
+ seenalrm = 0;
+ }
+ if (seenint) {
+ onint(SIGINT);
+ seenint = 0;
+ }
+ if (seeninfo) {
+ oninfo(SIGINFO);
+ seeninfo = 0;
+ }
+ continue;
+ } else if (cc == 0)
+ continue;
+
fromlen = sizeof(from);
m.msg_name = (caddr_t)&from;
@@ -1002,14 +1027,33 @@ main(argc, argv)
m.msg_control = (caddr_t)buf;
m.msg_controllen = sizeof(buf);
- if ((cc = recvmsg(s, &m, 0)) < 0) {
- if (errno == EINTR)
+ cc = recvmsg(s, &m, 0);
+ if (cc < 0) {
+ if (errno != EINTR) {
+ warn("recvmsg");
+ continue;
+ }
+ if (!signo)
continue;
- warn("recvfrom");
+ if (seenalrm) {
+ retransmit();
+ seenalrm = 0;
+ }
+ if (seenint) {
+ onint(SIGINT);
+ seenint = 0;
+ }
+ if (seeninfo) {
+ oninfo(SIGINFO);
+ seeninfo = 0;
+ }
continue;
+ } else {
+ /*
+ * an ICMPv6 message (probably an echoreply) arrived.
+ */
+ pr_pack(packet, cc, &m);
}
-
- pr_pack(packet, cc, &m);
if (npackets && nreceived >= npackets)
break;
}
@@ -1017,22 +1061,35 @@ main(argc, argv)
exit(nreceived == 0);
}
+void
+onsignal(sig)
+ int sig;
+{
+ signo = sig;
+ switch (sig) {
+ case SIGALRM:
+ seenalrm++;
+ break;
+ case SIGINT:
+ seenint++;
+ break;
+ case SIGINFO:
+ seeninfo++;
+ break;
+ }
+}
+
/*
- * onalrm --
+ * retransmit --
* This routine transmits another ping6.
- * XXX almost certainly not race-safe?
*/
-/* ARGSUSED */
void
-onalrm(signo)
- int signo;
+retransmit()
{
- int save_errno = errno;
struct itimerval itimer;
if (!npackets || ntransmitted < npackets) {
pinger();
- errno = save_errno;
return;
}
@@ -1054,7 +1111,6 @@ onalrm(signo)
(void)signal(SIGALRM, onint);
(void)setitimer(ITIMER_REAL, &itimer, NULL);
- errno = save_errno;
}
/*
@@ -1907,10 +1963,8 @@ void
oninfo(notused)
int notused;
{
- int save_errno = errno;
summary();
- errno = save_errno;
}
/*