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);
}