Fix a problem that reply packets are not received when -i T option is set
and (T < RTT). - Use select(2) for timeout instead of interval timer. Remove poll(2) support. - Use sigaction(2) instead of signal(3). - Exit in SIGINT handler when two signals are received and doing reverse DNS lookup as ping(8) does. - Remove redundant variables used for getaddrinfo(3). PR: 151023
This commit is contained in:
parent
44e120581b
commit
b5317f446c
@ -4,7 +4,7 @@ PROG= ping6
|
|||||||
MAN= ping6.8
|
MAN= ping6.8
|
||||||
|
|
||||||
CFLAGS+=-DIPSEC -DKAME_SCOPEID -DUSE_RFC2292BIS \
|
CFLAGS+=-DIPSEC -DKAME_SCOPEID -DUSE_RFC2292BIS \
|
||||||
-DHAVE_POLL_H -DHAVE_ARC4RANDOM
|
-DHAVE_ARC4RANDOM
|
||||||
WARNS?= 2
|
WARNS?= 2
|
||||||
|
|
||||||
BINOWN= root
|
BINOWN= root
|
||||||
|
@ -125,10 +125,8 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sysexits.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#ifdef HAVE_POLL_H
|
|
||||||
#include <poll.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IPSEC
|
#ifdef IPSEC
|
||||||
#include <netipsec/ah.h>
|
#include <netipsec/ah.h>
|
||||||
@ -207,7 +205,6 @@ u_int options;
|
|||||||
int mx_dup_ck = MAX_DUP_CHK;
|
int mx_dup_ck = MAX_DUP_CHK;
|
||||||
char rcvd_tbl[MAX_DUP_CHK / 8];
|
char rcvd_tbl[MAX_DUP_CHK / 8];
|
||||||
|
|
||||||
struct addrinfo *res = NULL;
|
|
||||||
struct sockaddr_in6 dst; /* who to ping6 */
|
struct sockaddr_in6 dst; /* who to ping6 */
|
||||||
struct sockaddr_in6 src; /* src addr of this packet */
|
struct sockaddr_in6 src; /* src addr of this packet */
|
||||||
socklen_t srclen;
|
socklen_t srclen;
|
||||||
@ -223,12 +220,6 @@ u_int8_t nonce[8]; /* nonce field for node information */
|
|||||||
int hoplimit = -1; /* hoplimit */
|
int hoplimit = -1; /* hoplimit */
|
||||||
int pathmtu = 0; /* path MTU for the destination. 0 = unspec. */
|
int pathmtu = 0; /* path MTU for the destination. 0 = unspec. */
|
||||||
u_char *packet = NULL;
|
u_char *packet = NULL;
|
||||||
#ifdef HAVE_POLL_H
|
|
||||||
struct pollfd fdmaskp[1];
|
|
||||||
#else
|
|
||||||
fd_set *fdmaskp = NULL;
|
|
||||||
int fdmasks;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* counters */
|
/* counters */
|
||||||
long nmissedmax; /* max value of ntransmitted - nreceived - 1 */
|
long nmissedmax; /* max value of ntransmitted - nreceived - 1 */
|
||||||
@ -236,7 +227,7 @@ long npackets; /* max packets to transmit */
|
|||||||
long nreceived; /* # of packets we got back */
|
long nreceived; /* # of packets we got back */
|
||||||
long nrepeats; /* number of duplicates */
|
long nrepeats; /* number of duplicates */
|
||||||
long ntransmitted; /* sequence # for outbound packets = #sent */
|
long ntransmitted; /* sequence # for outbound packets = #sent */
|
||||||
struct timeval interval = {1, 0}; /* interval between packets */
|
int interval = 1000; /* interval between packets in ms */
|
||||||
|
|
||||||
/* timing */
|
/* timing */
|
||||||
int timing; /* flag to do timing */
|
int timing; /* flag to do timing */
|
||||||
@ -253,7 +244,6 @@ struct msghdr smsghdr;
|
|||||||
struct iovec smsgiov;
|
struct iovec smsgiov;
|
||||||
char *scmsg = 0;
|
char *scmsg = 0;
|
||||||
|
|
||||||
volatile sig_atomic_t seenalrm;
|
|
||||||
volatile sig_atomic_t seenint;
|
volatile sig_atomic_t seenint;
|
||||||
#ifdef SIGINFO
|
#ifdef SIGINFO
|
||||||
volatile sig_atomic_t seeninfo;
|
volatile sig_atomic_t seeninfo;
|
||||||
@ -265,7 +255,6 @@ int get_hoplim(struct msghdr *);
|
|||||||
int get_pathmtu(struct msghdr *);
|
int get_pathmtu(struct msghdr *);
|
||||||
struct in6_pktinfo *get_rcvpktinfo(struct msghdr *);
|
struct in6_pktinfo *get_rcvpktinfo(struct msghdr *);
|
||||||
void onsignal(int);
|
void onsignal(int);
|
||||||
void retransmit(void);
|
|
||||||
void onint(int);
|
void onint(int);
|
||||||
size_t pingerlen(void);
|
size_t pingerlen(void);
|
||||||
int pinger(void);
|
int pinger(void);
|
||||||
@ -293,19 +282,15 @@ void usage(void);
|
|||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct itimerval itimer;
|
struct timeval last, intvl;
|
||||||
struct sockaddr_in6 from;
|
struct sockaddr_in6 from, *sin6;
|
||||||
#ifndef HAVE_ARC4RANDOM
|
#ifndef HAVE_ARC4RANDOM
|
||||||
struct timeval seed;
|
struct timeval seed;
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_POLL_H
|
struct addrinfo hints, *res;
|
||||||
int timeout;
|
struct sigaction si_sa;
|
||||||
#else
|
|
||||||
struct timeval timeout, *tv;
|
|
||||||
#endif
|
|
||||||
struct addrinfo hints;
|
|
||||||
int cc, i;
|
int cc, i;
|
||||||
int ch, hold, packlen, preload, optval, ret_ga;
|
int almost_done, ch, hold, packlen, preload, optval, error;
|
||||||
int nig_oldmcprefix = -1;
|
int nig_oldmcprefix = -1;
|
||||||
u_char *datap;
|
u_char *datap;
|
||||||
char *e, *target, *ifname = NULL, *gateway = NULL;
|
char *e, *target, *ifname = NULL, *gateway = NULL;
|
||||||
@ -326,7 +311,7 @@ main(int argc, char *argv[])
|
|||||||
char *policy_in = NULL;
|
char *policy_in = NULL;
|
||||||
char *policy_out = NULL;
|
char *policy_out = NULL;
|
||||||
#endif
|
#endif
|
||||||
double intval;
|
double t;
|
||||||
size_t rthlen;
|
size_t rthlen;
|
||||||
#ifdef IPV6_USE_MIN_MTU
|
#ifdef IPV6_USE_MIN_MTU
|
||||||
int mflag = 0;
|
int mflag = 0;
|
||||||
@ -450,22 +435,22 @@ main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 'i': /* wait between sending packets */
|
case 'i': /* wait between sending packets */
|
||||||
intval = strtod(optarg, &e);
|
t = strtod(optarg, &e);
|
||||||
if (*optarg == '\0' || *e != '\0')
|
if (*optarg == '\0' || *e != '\0')
|
||||||
errx(1, "illegal timing interval %s", optarg);
|
errx(1, "illegal timing interval %s", optarg);
|
||||||
if (intval < 1 && getuid()) {
|
if (t < 1 && getuid()) {
|
||||||
errx(1, "%s: only root may use interval < 1s",
|
errx(1, "%s: only root may use interval < 1s",
|
||||||
strerror(EPERM));
|
strerror(EPERM));
|
||||||
}
|
}
|
||||||
interval.tv_sec = (long)intval;
|
intvl.tv_sec = (long)t;
|
||||||
interval.tv_usec =
|
intvl.tv_usec =
|
||||||
(long)((intval - interval.tv_sec) * 1000000);
|
(long)((t - intvl.tv_sec) * 1000000);
|
||||||
if (interval.tv_sec < 0)
|
if (intvl.tv_sec < 0)
|
||||||
errx(1, "illegal timing interval %s", optarg);
|
errx(1, "illegal timing interval %s", optarg);
|
||||||
/* less than 1/hz does not make sense */
|
/* less than 1/hz does not make sense */
|
||||||
if (interval.tv_sec == 0 && interval.tv_usec < 1) {
|
if (intvl.tv_sec == 0 && intvl.tv_usec < 1) {
|
||||||
warnx("too small interval, raised to .000001");
|
warnx("too small interval, raised to .000001");
|
||||||
interval.tv_usec = 1;
|
intvl.tv_usec = 1;
|
||||||
}
|
}
|
||||||
options |= F_INTERVAL;
|
options |= F_INTERVAL;
|
||||||
break;
|
break;
|
||||||
@ -516,10 +501,10 @@ main(int argc, char *argv[])
|
|||||||
hints.ai_socktype = SOCK_RAW;
|
hints.ai_socktype = SOCK_RAW;
|
||||||
hints.ai_protocol = IPPROTO_ICMPV6;
|
hints.ai_protocol = IPPROTO_ICMPV6;
|
||||||
|
|
||||||
ret_ga = getaddrinfo(optarg, NULL, &hints, &res);
|
error = getaddrinfo(optarg, NULL, &hints, &res);
|
||||||
if (ret_ga) {
|
if (error) {
|
||||||
errx(1, "invalid source address: %s",
|
errx(1, "invalid source address: %s",
|
||||||
gai_strerror(ret_ga));
|
gai_strerror(error));
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* res->ai_family must be AF_INET6 and res->ai_addrlen
|
* res->ai_family must be AF_INET6 and res->ai_addrlen
|
||||||
@ -622,9 +607,9 @@ main(int argc, char *argv[])
|
|||||||
hints.ai_socktype = SOCK_RAW;
|
hints.ai_socktype = SOCK_RAW;
|
||||||
hints.ai_protocol = IPPROTO_ICMPV6;
|
hints.ai_protocol = IPPROTO_ICMPV6;
|
||||||
|
|
||||||
ret_ga = getaddrinfo(target, NULL, &hints, &res);
|
error = getaddrinfo(target, NULL, &hints, &res);
|
||||||
if (ret_ga)
|
if (error)
|
||||||
errx(1, "%s", gai_strerror(ret_ga));
|
errx(1, "%s", gai_strerror(error));
|
||||||
if (res->ai_canonname)
|
if (res->ai_canonname)
|
||||||
hostname = res->ai_canonname;
|
hostname = res->ai_canonname;
|
||||||
else
|
else
|
||||||
@ -647,28 +632,25 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
/* set the gateway (next hop) if specified */
|
/* set the gateway (next hop) if specified */
|
||||||
if (gateway) {
|
if (gateway) {
|
||||||
struct addrinfo ghints, *gres;
|
memset(&hints, 0, sizeof(hints));
|
||||||
int error;
|
hints.ai_family = AF_INET6;
|
||||||
|
hints.ai_socktype = SOCK_RAW;
|
||||||
|
hints.ai_protocol = IPPROTO_ICMPV6;
|
||||||
|
|
||||||
memset(&ghints, 0, sizeof(ghints));
|
error = getaddrinfo(gateway, NULL, &hints, &res);
|
||||||
ghints.ai_family = AF_INET6;
|
|
||||||
ghints.ai_socktype = SOCK_RAW;
|
|
||||||
ghints.ai_protocol = IPPROTO_ICMPV6;
|
|
||||||
|
|
||||||
error = getaddrinfo(gateway, NULL, &hints, &gres);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
errx(1, "getaddrinfo for the gateway %s: %s",
|
errx(1, "getaddrinfo for the gateway %s: %s",
|
||||||
gateway, gai_strerror(error));
|
gateway, gai_strerror(error));
|
||||||
}
|
}
|
||||||
if (gres->ai_next && (options & F_VERBOSE))
|
if (res->ai_next && (options & F_VERBOSE))
|
||||||
warnx("gateway resolves to multiple addresses");
|
warnx("gateway resolves to multiple addresses");
|
||||||
|
|
||||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_NEXTHOP,
|
if (setsockopt(s, IPPROTO_IPV6, IPV6_NEXTHOP,
|
||||||
gres->ai_addr, gres->ai_addrlen)) {
|
res->ai_addr, res->ai_addrlen)) {
|
||||||
err(1, "setsockopt(IPV6_NEXTHOP)");
|
err(1, "setsockopt(IPV6_NEXTHOP)");
|
||||||
}
|
}
|
||||||
|
|
||||||
freeaddrinfo(gres);
|
freeaddrinfo(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -898,7 +880,7 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (argc > 1) { /* some intermediate addrs are specified */
|
if (argc > 1) { /* some intermediate addrs are specified */
|
||||||
int hops, error;
|
int hops;
|
||||||
#ifdef USE_RFC2292BIS
|
#ifdef USE_RFC2292BIS
|
||||||
int rthdrlen;
|
int rthdrlen;
|
||||||
#endif
|
#endif
|
||||||
@ -920,26 +902,25 @@ main(int argc, char *argv[])
|
|||||||
#endif /* USE_RFC2292BIS */
|
#endif /* USE_RFC2292BIS */
|
||||||
|
|
||||||
for (hops = 0; hops < argc - 1; hops++) {
|
for (hops = 0; hops < argc - 1; hops++) {
|
||||||
struct addrinfo *iaip;
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_INET6;
|
||||||
|
|
||||||
if ((error = getaddrinfo(argv[hops], NULL, &hints,
|
if ((error = getaddrinfo(argv[hops], NULL, &hints,
|
||||||
&iaip)))
|
&res)))
|
||||||
errx(1, "%s", gai_strerror(error));
|
errx(1, "%s", gai_strerror(error));
|
||||||
if (SIN6(iaip->ai_addr)->sin6_family != AF_INET6)
|
if (res->ai_addr->sa_family != AF_INET6)
|
||||||
errx(1,
|
errx(1,
|
||||||
"bad addr family of an intermediate addr");
|
"bad addr family of an intermediate addr");
|
||||||
|
sin6 = (struct sockaddr_in6 *)(void *)res->ai_addr;
|
||||||
#ifdef USE_RFC2292BIS
|
#ifdef USE_RFC2292BIS
|
||||||
if (inet6_rth_add(rthdr,
|
if (inet6_rth_add(rthdr, &sin6->sin6_addr))
|
||||||
&(SIN6(iaip->ai_addr))->sin6_addr))
|
|
||||||
errx(1, "can't add an intermediate node");
|
errx(1, "can't add an intermediate node");
|
||||||
#else /* old advanced API */
|
#else /* old advanced API */
|
||||||
if (inet6_rthdr_add(scmsgp,
|
if (inet6_rthdr_add(scmsg, &sin6->sin6_addr,
|
||||||
&(SIN6(iaip->ai_addr))->sin6_addr,
|
|
||||||
IPV6_RTHDR_LOOSE))
|
IPV6_RTHDR_LOOSE))
|
||||||
errx(1, "can't add an intermediate node");
|
errx(1, "can't add an intermediate node");
|
||||||
#endif /* USE_RFC2292BIS */
|
#endif /* USE_RFC2292BIS */
|
||||||
freeaddrinfo(iaip);
|
freeaddrinfo(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef USE_RFC2292BIS
|
#ifndef USE_RFC2292BIS
|
||||||
@ -1055,52 +1036,46 @@ main(int argc, char *argv[])
|
|||||||
printf("%s --> ", pr_addr((struct sockaddr *)&src, sizeof(src)));
|
printf("%s --> ", pr_addr((struct sockaddr *)&src, sizeof(src)));
|
||||||
printf("%s\n", pr_addr((struct sockaddr *)&dst, sizeof(dst)));
|
printf("%s\n", pr_addr((struct sockaddr *)&dst, sizeof(dst)));
|
||||||
|
|
||||||
while (preload--) /* Fire off them quickies. */
|
if (preload == 0)
|
||||||
(void)pinger();
|
pinger();
|
||||||
|
else {
|
||||||
(void)signal(SIGINT, onsignal);
|
if (npackets != 0 && preload > npackets)
|
||||||
#ifdef SIGINFO
|
preload = npackets;
|
||||||
(void)signal(SIGINFO, onsignal);
|
while (preload--)
|
||||||
#endif
|
pinger();
|
||||||
|
|
||||||
if ((options & F_FLOOD) == 0) {
|
|
||||||
(void)signal(SIGALRM, onsignal);
|
|
||||||
itimer.it_interval = interval;
|
|
||||||
itimer.it_value = interval;
|
|
||||||
(void)setitimer(ITIMER_REAL, &itimer, NULL);
|
|
||||||
if (ntransmitted == 0)
|
|
||||||
retransmit();
|
|
||||||
}
|
}
|
||||||
|
gettimeofday(&last, NULL);
|
||||||
|
|
||||||
#ifndef HAVE_POLL_H
|
sigemptyset(&si_sa.sa_mask);
|
||||||
fdmasks = howmany(s + 1, NFDBITS) * sizeof(fd_mask);
|
si_sa.sa_flags = 0;
|
||||||
if ((fdmaskp = malloc(fdmasks)) == NULL)
|
si_sa.sa_handler = onsignal;
|
||||||
err(1, "malloc");
|
if (sigaction(SIGINT, &si_sa, 0) == -1)
|
||||||
#endif
|
err(EX_OSERR, "sigaction SIGINT");
|
||||||
|
seenint = 0;
|
||||||
seenalrm = seenint = 0;
|
|
||||||
#ifdef SIGINFO
|
#ifdef SIGINFO
|
||||||
|
if (sigaction(SIGINFO, &si_sa, 0) == -1)
|
||||||
|
err(EX_OSERR, "sigaction SIGINFO");
|
||||||
seeninfo = 0;
|
seeninfo = 0;
|
||||||
#endif
|
#endif
|
||||||
|
if (options & F_FLOOD) {
|
||||||
|
intvl.tv_sec = 0;
|
||||||
|
intvl.tv_usec = 10000;
|
||||||
|
} else if ((options & F_INTERVAL) == 0) {
|
||||||
|
intvl.tv_sec = interval / 1000;
|
||||||
|
intvl.tv_usec = interval % 1000 * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
for (;;) {
|
almost_done = 0;
|
||||||
|
while (seenint == 0) {
|
||||||
|
struct timeval now, timeout;
|
||||||
struct msghdr m;
|
struct msghdr m;
|
||||||
struct iovec iov[2];
|
struct iovec iov[2];
|
||||||
|
fd_set rfds;
|
||||||
|
int n;
|
||||||
|
|
||||||
/* signal handling */
|
/* signal handling */
|
||||||
if (seenalrm) {
|
if (seenint)
|
||||||
/* last packet sent, timeout reached? */
|
|
||||||
if (npackets && ntransmitted >= npackets)
|
|
||||||
break;
|
|
||||||
retransmit();
|
|
||||||
seenalrm = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (seenint) {
|
|
||||||
onint(SIGINT);
|
onint(SIGINT);
|
||||||
seenint = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#ifdef SIGINFO
|
#ifdef SIGINFO
|
||||||
if (seeninfo) {
|
if (seeninfo) {
|
||||||
summary();
|
summary();
|
||||||
@ -1108,93 +1083,104 @@ main(int argc, char *argv[])
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
FD_ZERO(&rfds);
|
||||||
if (options & F_FLOOD) {
|
FD_SET(s, &rfds);
|
||||||
(void)pinger();
|
gettimeofday(&now, NULL);
|
||||||
#ifdef HAVE_POLL_H
|
timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;
|
||||||
timeout = 10;
|
timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;
|
||||||
#else
|
while (timeout.tv_usec < 0) {
|
||||||
timeout.tv_sec = 0;
|
timeout.tv_usec += 1000000;
|
||||||
timeout.tv_usec = 10000;
|
timeout.tv_sec--;
|
||||||
tv = &timeout;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
#ifdef HAVE_POLL_H
|
|
||||||
timeout = INFTIM;
|
|
||||||
#else
|
|
||||||
tv = NULL;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#ifdef HAVE_POLL_H
|
while (timeout.tv_usec > 1000000) {
|
||||||
fdmaskp[0].fd = s;
|
timeout.tv_usec -= 1000000;
|
||||||
fdmaskp[0].events = POLLIN;
|
timeout.tv_sec++;
|
||||||
cc = poll(fdmaskp, 1, timeout);
|
}
|
||||||
#else
|
if (timeout.tv_sec < 0)
|
||||||
memset(fdmaskp, 0, fdmasks);
|
timeout.tv_sec = timeout.tv_usec = 0;
|
||||||
FD_SET(s, fdmaskp);
|
|
||||||
cc = select(s + 1, fdmaskp, NULL, NULL, tv);
|
|
||||||
#endif
|
|
||||||
if (cc < 0) {
|
|
||||||
if (errno != EINTR) {
|
|
||||||
#ifdef HAVE_POLL_H
|
|
||||||
warn("poll");
|
|
||||||
#else
|
|
||||||
warn("select");
|
|
||||||
#endif
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else if (cc == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
m.msg_name = (caddr_t)&from;
|
n = select(s + 1, &rfds, NULL, NULL, &timeout);
|
||||||
m.msg_namelen = sizeof(from);
|
if (n < 0)
|
||||||
memset(&iov, 0, sizeof(iov));
|
continue; /* EINTR */
|
||||||
iov[0].iov_base = (caddr_t)packet;
|
if (n == 1) {
|
||||||
iov[0].iov_len = packlen;
|
m.msg_name = (caddr_t)&from;
|
||||||
m.msg_iov = iov;
|
m.msg_namelen = sizeof(from);
|
||||||
m.msg_iovlen = 1;
|
memset(&iov, 0, sizeof(iov));
|
||||||
memset(cm, 0, CONTROLLEN);
|
iov[0].iov_base = (caddr_t)packet;
|
||||||
m.msg_control = (void *)cm;
|
iov[0].iov_len = packlen;
|
||||||
m.msg_controllen = CONTROLLEN;
|
m.msg_iov = iov;
|
||||||
|
m.msg_iovlen = 1;
|
||||||
|
memset(cm, 0, CONTROLLEN);
|
||||||
|
m.msg_control = (void *)cm;
|
||||||
|
m.msg_controllen = CONTROLLEN;
|
||||||
|
|
||||||
cc = recvmsg(s, &m, 0);
|
cc = recvmsg(s, &m, 0);
|
||||||
if (cc < 0) {
|
if (cc < 0) {
|
||||||
if (errno != EINTR) {
|
if (errno != EINTR) {
|
||||||
warn("recvmsg");
|
warn("recvmsg");
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else if (cc == 0) {
|
|
||||||
int mtu;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* receive control messages only. Process the
|
|
||||||
* exceptions (currently the only possibility is
|
|
||||||
* a path MTU notification.)
|
|
||||||
*/
|
|
||||||
if ((mtu = get_pathmtu(&m)) > 0) {
|
|
||||||
if ((options & F_VERBOSE) != 0) {
|
|
||||||
printf("new path MTU (%d) is "
|
|
||||||
"notified\n", mtu);
|
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
} else if (cc == 0) {
|
||||||
|
int mtu;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* receive control messages only. Process the
|
||||||
|
* exceptions (currently the only possibility is
|
||||||
|
* a path MTU notification.)
|
||||||
|
*/
|
||||||
|
if ((mtu = get_pathmtu(&m)) > 0) {
|
||||||
|
if ((options & F_VERBOSE) != 0) {
|
||||||
|
printf("new path MTU (%d) is "
|
||||||
|
"notified\n", mtu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* an ICMPv6 message (probably an echoreply)
|
||||||
|
* arrived.
|
||||||
|
*/
|
||||||
|
pr_pack(packet, cc, &m);
|
||||||
}
|
}
|
||||||
continue;
|
if (((options & F_ONCE) != 0 && nreceived > 0) ||
|
||||||
} else {
|
(npackets > 0 && nreceived >= npackets))
|
||||||
/*
|
break;
|
||||||
* an ICMPv6 message (probably an echoreply) arrived.
|
|
||||||
*/
|
|
||||||
pr_pack(packet, cc, &m);
|
|
||||||
}
|
}
|
||||||
if (((options & F_ONCE) != 0 && nreceived > 0) ||
|
if (n == 0 || (options & F_FLOOD)) {
|
||||||
(npackets > 0 && nreceived >= npackets))
|
if (npackets == 0 || ntransmitted < npackets)
|
||||||
break;
|
pinger();
|
||||||
if (ntransmitted - nreceived - 1 > nmissedmax) {
|
else {
|
||||||
nmissedmax = ntransmitted - nreceived - 1;
|
if (almost_done)
|
||||||
if (options & F_MISSED)
|
break;
|
||||||
(void)write(STDOUT_FILENO, &BBELL, 1);
|
almost_done = 1;
|
||||||
|
/*
|
||||||
|
* If we're not transmitting any more packets,
|
||||||
|
* change the timer to wait two round-trip times
|
||||||
|
* if we've received any packets or ten seconds
|
||||||
|
* if we haven't.
|
||||||
|
*/
|
||||||
|
#define MAXWAIT 10
|
||||||
|
intvl.tv_usec = 0;
|
||||||
|
if (nreceived) {
|
||||||
|
intvl.tv_sec = 2 * tmax / 1000;
|
||||||
|
if (intvl.tv_sec == 0)
|
||||||
|
intvl.tv_sec = 1;
|
||||||
|
} else
|
||||||
|
intvl.tv_sec = MAXWAIT;
|
||||||
|
}
|
||||||
|
gettimeofday(&last, NULL);
|
||||||
|
if (ntransmitted - nreceived - 1 > nmissedmax) {
|
||||||
|
nmissedmax = ntransmitted - nreceived - 1;
|
||||||
|
if (options & F_MISSED)
|
||||||
|
(void)write(STDOUT_FILENO, &BBELL, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sigemptyset(&si_sa.sa_mask);
|
||||||
|
si_sa.sa_flags = 0;
|
||||||
|
si_sa.sa_handler = SIG_IGN;
|
||||||
|
sigaction(SIGINT, &si_sa, 0);
|
||||||
summary();
|
summary();
|
||||||
|
|
||||||
if (res != NULL)
|
if (res != NULL)
|
||||||
@ -1203,11 +1189,6 @@ main(int argc, char *argv[])
|
|||||||
if(packet != NULL)
|
if(packet != NULL)
|
||||||
free(packet);
|
free(packet);
|
||||||
|
|
||||||
#ifndef HAVE_POLL_H
|
|
||||||
if(fdmaskp != NULL)
|
|
||||||
free(fdmaskp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
exit(nreceived == 0 ? 2 : 0);
|
exit(nreceived == 0 ? 2 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1216,9 +1197,6 @@ onsignal(int sig)
|
|||||||
{
|
{
|
||||||
|
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case SIGALRM:
|
|
||||||
seenalrm++;
|
|
||||||
break;
|
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
seenint++;
|
seenint++;
|
||||||
break;
|
break;
|
||||||
@ -1230,38 +1208,6 @@ onsignal(int sig)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* retransmit --
|
|
||||||
* This routine transmits another ping6.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
retransmit(void)
|
|
||||||
{
|
|
||||||
struct itimerval itimer;
|
|
||||||
|
|
||||||
if (pinger() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we're not transmitting any more packets, change the timer
|
|
||||||
* to wait two round-trip times if we've received any packets or
|
|
||||||
* ten seconds if we haven't.
|
|
||||||
*/
|
|
||||||
#define MAXWAIT 10
|
|
||||||
if (nreceived) {
|
|
||||||
itimer.it_value.tv_sec = 2 * tmax / 1000;
|
|
||||||
if (itimer.it_value.tv_sec == 0)
|
|
||||||
itimer.it_value.tv_sec = 1;
|
|
||||||
} else
|
|
||||||
itimer.it_value.tv_sec = MAXWAIT;
|
|
||||||
itimer.it_interval.tv_sec = 0;
|
|
||||||
itimer.it_interval.tv_usec = 0;
|
|
||||||
itimer.it_value.tv_usec = 0;
|
|
||||||
|
|
||||||
(void)signal(SIGALRM, onsignal);
|
|
||||||
(void)setitimer(ITIMER_REAL, &itimer, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pinger --
|
* pinger --
|
||||||
* Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
|
* Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
|
||||||
@ -2241,24 +2187,12 @@ tvsub(struct timeval *out, struct timeval *in)
|
|||||||
void
|
void
|
||||||
onint(int notused __unused)
|
onint(int notused __unused)
|
||||||
{
|
{
|
||||||
summary();
|
/*
|
||||||
|
* When doing reverse DNS lookups, the seenint flag might not
|
||||||
if (res != NULL)
|
* be noticed for a while. Just exit if we get a second SIGINT.
|
||||||
freeaddrinfo(res);
|
*/
|
||||||
|
if ((options & F_HOSTNAME) && seenint != 0)
|
||||||
if(packet != NULL)
|
_exit(nreceived ? 0 : 2);
|
||||||
free(packet);
|
|
||||||
|
|
||||||
#ifndef HAVE_POLL_H
|
|
||||||
if(fdmaskp != NULL)
|
|
||||||
free(fdmaskp);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
(void)signal(SIGINT, SIG_DFL);
|
|
||||||
(void)kill(getpid(), SIGINT);
|
|
||||||
|
|
||||||
/* NOTREACHED */
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user