Hi,

I am using netcat to write tests that send and receive UDP packets.
Unfortunately I can terminate nc only with a timeout.  This takes
either too long or is unreliable.

So I implemented nc -W recvlimit.  It works a bit like ping -c
count.  So I can quickly check for UDP responses.

# echo request | nc -u -W 1 host port | grep reply

Is this a useful addition?  ok?

bluhm

Index: usr.bin/nc/nc.1
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.bin/nc/nc.1,v
retrieving revision 1.84
diff -u -p -r1.84 nc.1
--- usr.bin/nc/nc.1     5 Apr 2017 06:55:59 -0000       1.84
+++ usr.bin/nc/nc.1     10 May 2017 16:07:12 -0000
@@ -50,6 +50,7 @@
 .Op Fl s Ar source
 .Op Fl T Ar keyword
 .Op Fl V Ar rtable
+.Op Fl W Ar recvlimit
 .Op Fl w Ar timeout
 .Op Fl X Ar proxy_protocol
 .Op Fl x Ar proxy_address Ns Op : Ns Ar port
@@ -288,6 +289,8 @@ Set the routing table to be used.
 Have
 .Nm
 give more verbose output.
+.It Fl W Ar recvlimit
+Terminate after receiving a number of packets from the network.
 .It Fl w Ar timeout
 Connections which cannot be established or are idle timeout after
 .Ar timeout
Index: usr.bin/nc/netcat.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.bin/nc/netcat.c,v
retrieving revision 1.181
diff -u -p -r1.181 netcat.c
--- usr.bin/nc/netcat.c 16 Apr 2017 15:11:01 -0000      1.181
+++ usr.bin/nc/netcat.c 10 May 2017 15:52:47 -0000
@@ -108,6 +108,7 @@ char        *tls_expectname;                        /* 
required name
 char   *tls_expecthash;                        /* required hash of peer cert */
 FILE   *Zflag;                                 /* file to save peer cert */
 
+int recvcount, recvlimit;
 int timeout = -1;
 int family = AF_UNSPEC;
 char *portlist[PORT_MAX+1];
@@ -167,7 +168,8 @@ main(int argc, char *argv[])
        signal(SIGPIPE, SIG_IGN);
 
        while ((ch = getopt(argc, argv,
-           "46C:cDde:FH:hI:i:K:klM:m:NnO:o:P:p:R:rSs:T:tUuV:vw:X:x:Z:z")) != 
-1) {
+           "46C:cDde:FH:hI:i:K:klM:m:NnO:o:P:p:R:rSs:T:tUuV:vW:w:X:x:Z:z"))
+           != -1) {
                switch (ch) {
                case '4':
                        family = AF_INET;
@@ -270,6 +272,11 @@ main(int argc, char *argv[])
                case 'v':
                        vflag = 1;
                        break;
+               case 'W':
+                       recvlimit = strtonum(optarg, 1, INT_MAX, &errstr);
+                       if (errstr)
+                               errx(1, "receive limit %s: %s", errstr, optarg);
+                       break;
                case 'w':
                        timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
                        if (errstr)
@@ -1166,6 +1173,12 @@ readwrite(int net_fd, struct tls *tls_ct
                                shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
                                pfd[POLL_NETIN].fd = -1;
                        }
+                       if (recvlimit > 0 && ++recvcount >= recvlimit) {
+                               if (pfd[POLL_NETIN].fd != -1)
+                                       shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
+                               pfd[POLL_NETIN].fd = -1;
+                               pfd[POLL_STDIN].fd = -1;
+                       }
                        /* read something - poll stdout */
                        if (netinbufpos > 0)
                                pfd[POLL_STDOUT].events = POLLOUT;
@@ -1706,6 +1719,7 @@ help(void)
        \t-u            UDP mode\n\
        \t-V rtable     Specify alternate routing table\n\
        \t-v            Verbose\n\
+       \t-W recvlimit  Terminate after receiving a number of packets\n\
        \t-w timeout    Timeout for connects and final net reads\n\
        \t-X proto      Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
        \t-x addr[:port]\tSpecify proxy address and port\n\
@@ -1724,10 +1738,11 @@ usage(int ret)
            "\t  [-i interval] [-K keyfile] [-M ttl] [-m minttl] [-O length]\n"
            "\t  [-o staplefile] [-P proxy_username] [-p source_port] "
            "[-R CAfile]\n"
-           "\t  [-s source] [-T keyword] [-V rtable] [-w timeout] "
-           "[-X proxy_protocol]\n"
-           "\t  [-x proxy_address[:port]] [-Z peercertfile] "
-           "[destination] [port]\n");
+           "\t  [-s source] [-T keyword] [-V rtable] [-W recvlimit ] "
+           "[-w timeout]\n"
+           "\t  [-X proxy_protocol] [-x proxy_address[:port]] "
+           "[-Z peercertfile]\n"
+           "\t  [destination] [port]\n");
        if (ret)
                exit(1);
 }

Reply via email to