Daniel Jakots wrote: > Hi, > > With nc(1) you can do: > nc -zv example.com 80 > or > nc -zv example.com http > which does the same. This works well unless the service name has a dash: > $ nc -zv example.com syslog-tls > nc: service "tls" unknown > > This is because nc(1) is able to do some port scanning and the > delimiter used for the range is the dash. When it sees a dash, it > thinks it's a port range. > > nc(1) is not the only software that takes an input that can be a port, > a range or a service name: pf is in this case too. In pf the delimiter > used is ":" so this works fine. > > Here's a diff that change the delimiter to ":". This breaks existing > scripts but it would make the syntax like pf.conf instead of using > another symbol for a port range. > > If you have a better idea how to solve this problem, please share!
This preserves the low-high syntax, adds low:high syntax, and also tries to be smarter about service-name. First look for :. That's a range. Next look for -. Then check it's not a service name. That's a range. Otherwise it's a port. It may work, but needs testing. Index: netcat.c =================================================================== RCS file: /cvs/src/usr.bin/nc/netcat.c,v retrieving revision 1.199 diff -u -p -r1.199 netcat.c --- netcat.c 29 Nov 2018 14:25:06 -0000 1.199 +++ netcat.c 22 Dec 2018 22:27:47 -0000 @@ -1426,46 +1426,53 @@ build_ports(char *p) char *n; int hi, lo, cp; int x = 0; + char *tmp; - if ((n = strchr(p, '-')) != NULL) { - *n = '\0'; - n++; - - /* Make sure the ports are in order: lowest->highest. */ - hi = strtoport(n, uflag); - lo = strtoport(p, uflag); - if (lo > hi) { - cp = hi; - hi = lo; - lo = cp; - } + if ((n = strchr(p, ':')) != NULL) + goto range; - /* - * Initialize portlist with a random permutation. Based on - * Knuth, as in ip_randomid() in sys/netinet/ip_id.c. - */ - if (rflag) { - for (x = 0; x <= hi - lo; x++) { - cp = arc4random_uniform(x + 1); - portlist[x] = portlist[cp]; - if (asprintf(&portlist[cp], "%d", x + lo) < 0) - err(1, "asprintf"); - } - } else { /* Load ports sequentially. */ - for (cp = lo; cp <= hi; cp++) { - if (asprintf(&portlist[x], "%d", cp) < 0) - err(1, "asprintf"); - x++; - } - } - } else { - char *tmp; + if ((n = strchr(p, '-')) != NULL) + if (getservbyname(p, uflag ? "udp" : "tcp") == NULL) + goto range; + + hi = strtoport(p, uflag); + if (asprintf(&tmp, "%d", hi) != -1) + portlist[0] = tmp; + else + err(1, NULL); + + return; - hi = strtoport(p, uflag); - if (asprintf(&tmp, "%d", hi) != -1) - portlist[0] = tmp; - else - err(1, NULL); +range: + *n = '\0'; + n++; + + /* Make sure the ports are in order: lowest->highest. */ + hi = strtoport(n, uflag); + lo = strtoport(p, uflag); + if (lo > hi) { + cp = hi; + hi = lo; + lo = cp; + } + + /* + * Initialize portlist with a random permutation. Based on + * Knuth, as in ip_randomid() in sys/netinet/ip_id.c. + */ + if (rflag) { + for (x = 0; x <= hi - lo; x++) { + cp = arc4random_uniform(x + 1); + portlist[x] = portlist[cp]; + if (asprintf(&portlist[cp], "%d", x + lo) < 0) + err(1, "asprintf"); + } + } else { /* Load ports sequentially. */ + for (cp = lo; cp <= hi; cp++) { + if (asprintf(&portlist[x], "%d", cp) < 0) + err(1, "asprintf"); + x++; + } } }