diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2001-01-12 19:05:41 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2001-01-12 19:05:41 +0000 |
commit | fdf11699038a3c29ccf1ca8d533167e4f59dba3b (patch) | |
tree | 5489095a7f48d6a21e31d5f0b7792f7df7705380 /sbin | |
parent | 685054b6c8bf1bb1b9f1e4c0fcee244263dd216b (diff) |
minimize chance of signal handler race. big help from deraadt.
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/ping6/ping6.c | 122 |
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; } /* |