On Thu, Sep 13, 2012 at 03:02:09PM -0400, Ted Unangst wrote:
> So sometimes a machine is hiding behind a firewall that blocks icmp
> (looking at you, amazon ec2), but I want to know if it's up and/or how
> long away it is. tcp to the rescue.
Seems like a bit of a "rude" method of testing whether a
host is up, especially if you leave it ping-ing in a
continuous loop.
telnet works just fine if you want to test if a host is up
and listening on a specific port, minus the timing info you
are looking for.
--patrick
> This adds a -T portnum option to ping. I haven't polished the output
> because I'm not sure if this is desirable or not, but I found it
> useful. If it's not a "hell no, never in base" I can finish it up some.
>
> Index: ping.c
> ===================================================================
> RCS file: /cvs/src/sbin/ping/ping.c,v
> retrieving revision 1.92
> diff -u -p -r1.92 ping.c
> --- ping.c 17 Mar 2012 10:16:40 -0000 1.92
> +++ ping.c 13 Sep 2012 18:57:06 -0000
> @@ -169,6 +169,7 @@ quad_t qsqrt(quad_t);
> void pr_iph(struct ip *);
> #ifndef SMALL
> int map_tos(char *, int *);
> +void tcpping(void);
> #endif /* SMALL */
> void usage(void);
>
> @@ -191,6 +192,7 @@ main(int argc, char *argv[])
> size_t fdmasks;
> uid_t uid;
> u_int rtableid;
> + unsigned short portnum = 0;
>
> if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
> err(1, "socket");
> @@ -203,7 +205,7 @@ main(int argc, char *argv[])
> preload = 0;
> datap = &outpack[8 + sizeof(struct tvi)];
> while ((ch = getopt(argc, argv,
> - "DEI:LRS:c:defi:l:np:qrs:T:t:V:vw:")) != -1)
> + "DEI:LRS:c:defi:l:nP:p:qrs:T:t:V:vw:")) != -1)
> switch(ch) {
> case 'c':
> npackets = (unsigned long)strtonum(optarg, 0,
> @@ -277,6 +279,13 @@ main(int argc, char *argv[])
> options |= F_PINGFILLED;
> fill((char *)datap, optarg);
> break;
> +#ifndef SMALL
> + case 'P':
> + portnum = strtonum(optarg, 1, 65535, &errstr);
> + if (errstr)
> + errx(1, "portnum is %s: %s", errstr, optarg);
> + break;
> +#endif
> case 'q':
> options |= F_QUIET;
> break;
> @@ -369,6 +378,17 @@ main(int argc, char *argv[])
> hostname = hnamebuf;
> }
>
> +#ifndef SMALL
> + if (portnum) {
> + close(s);
> + whereto.sin_port = htons(portnum);
> + while (!npackets || ntransmitted++ < npackets) {
> + tcpping();
> + sleep(1);
> + }
> + }
> +#endif
> +
> if (options & F_FLOOD && options & F_INTERVAL)
> errx(1, "-f and -i options are incompatible");
>
> @@ -1413,6 +1433,27 @@ map_tos(char *s, int *val)
> }
>
> return (0);
> +}
> +
> +void
> +tcpping(void)
> +{
> + struct timeval before, after, diff;
> + int rtt;
> +
> + s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
> + if (!s)
> + err(1, "can't open socket");
> + gettimeofday(&before, NULL);
> + if (connect(s, (const struct sockaddr *)&whereto,
> + sizeof(whereto)))
> + err(1, "can't connect");
> + gettimeofday(&after, NULL);
> + close(s);
> + timersub(&after, &before, &diff);
> +
> + rtt = diff.tv_sec * 10000000 + diff.tv_usec;
> + printf("tcpping %d.%d ms\n", rtt / 1000, rtt % 1000);
> }
> #endif /* SMALL */