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.

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 */

Reply via email to