From: Guilhem Moulin Date: Mon, 22 Oct 2018 04:15:52 +0200 Subject: Add ability to specify a list of destination ports --- nc.1 | 26 +++++++++++++++++--- netcat.c | 86 +++++++++++++++++++++++++++++++++------------------------------- 2 files changed, 68 insertions(+), 44 deletions(-) diff --git a/nc.1 b/nc.1 index 49a3d4d..80c654c 100644 --- a/nc.1 +++ b/nc.1 @@ -417,15 +417,35 @@ The flag can be used to tell .Nm to report open ports, -rather than initiate a connection. +rather than initiate a connection. Usually it's useful to turn on verbose +output to stderr by use this option in conjunction with +.Fl v +option. +.Pp For example: .Bd -literal -offset indent -$ nc -z host.example.com 20-30 +$ nc \-zv host.example.com 20-30 Connection to host.example.com 22 port [tcp/ssh] succeeded! Connection to host.example.com 25 port [tcp/smtp] succeeded! .Ed .Pp -The port range was specified to limit the search to ports 20 \- 30. +The port range was specified to limit the search to ports 20 \- 30, and is +scanned by increasing order (unless the +.Fl r +flag is set). +.Pp +You can also specify a list of ports to scan, for example: +.Bd -literal -offset indent +$ nc \-zv host.example.com http 20 22-23 +nc: connect to host.example.com 80 (tcp) failed: Connection refused +nc: connect to host.example.com 20 (tcp) failed: Connection refused +Connection to host.example.com port [tcp/ssh] succeeded! +nc: connect to host.example.com 23 (tcp) failed: Connection refused +.Ed +.Pp +The ports are scanned by the order you given (unless the +.Fl r +flag is set). .Pp Alternatively, it might be useful to know which server software is running, and which versions. diff --git a/netcat.c b/netcat.c index 990c31b..bef27a4 100644 --- a/netcat.c +++ b/netcat.c @@ -191,7 +191,7 @@ int minttl = -1; void atelnet(int, unsigned char *, unsigned int); int strtoport(char *portstr, int udp); -void build_ports(char *); +void build_ports(char **); void help(void) __attribute__((noreturn)); int local_listen(const char *, const char *, struct addrinfo); #ifdef HAVE_TLS @@ -241,7 +241,7 @@ int main(int argc, char *argv[]) { int ch, s = -1, ret, socksv; - char *host, *uport; + char *host, **uport; char ipaddr[NI_MAXHOST]; struct addrinfo hints; socklen_t len; @@ -521,10 +521,10 @@ main(int argc, char *argv[]) if (zflag) errx(1, "cannot use -z and -l"); } else if (argc == 1 && lflag) { - uport = argv[0]; + uport = &argv[0]; } else if (argc == 2) { host = argv[0]; - uport = argv[1]; + uport = &argv[1]; } else usage(1); @@ -723,7 +723,7 @@ main(int argc, char *argv[]) else s = unix_listen(host); } else - s = local_listen(host, uport, hints); + s = local_listen(host, *uport, hints); if (s < 0) err(1, NULL); @@ -1810,57 +1810,61 @@ strtoport(char *portstr, int udp) * that we should try to connect to. */ void -build_ports(char *p) +build_ports(char **p) { struct servent *sv; char *n; int hi, lo, cp; int x = 0; + int i; char *proto = proto_name(uflag, dccpflag); - sv = getservbyname(p, proto); - if (sv) { - if (asprintf(&portlist[0], "%d", ntohs(sv->s_port)) < 0) - err(1, "asprintf"); - } else if (isdigit((unsigned char)*p) && (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; - } - - /* - * 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) == -1) - err(1, "asprintf"); + for (i = 0; p[i] != NULL; i++) { + sv = getservbyname(p[i], proto); + if (sv) { + if (asprintf(&portlist[x], "%d", ntohs(sv->s_port)) < 0) + err(1, "asprintf"); + x++; + } else if (isdigit((unsigned char)*p[i]) && (n = strchr(p[i], '-')) != NULL) { + *n = '\0'; + n++; + + /* Make sure the ports are in order: lowest->highest. */ + hi = strtoport(n, uflag); + lo = strtoport(p[i], uflag); + if (lo > hi) { + cp = hi; + hi = lo; + lo = cp; } - } else { /* Load ports sequentially. */ + + /* Load ports sequentially. */ for (cp = lo; cp <= hi; cp++) { if (asprintf(&portlist[x], "%d", cp) == -1) err(1, "asprintf"); x++; } + } else { + hi = strtoport(p[i], uflag); + if (asprintf(&portlist[x], "%d", hi) < 0) + err(1, "asprintf"); + x++; } - } else { - char *tmp; + } - hi = strtoport(p, uflag); - if (asprintf(&tmp, "%d", hi) != -1) - portlist[0] = tmp; - else - err(1, NULL); + /* + * Initialize portlist with a random permutation using + * Fisher–Yates shuffle. + */ + if (rflag) { + for (i = x-1; i > 0; i--) { + cp = arc4random_uniform(i+1); + if (cp != i) { + n = portlist[i]; + portlist[i] = portlist[cp]; + portlist[cp] = n; + } + } } }