aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-03-23 14:46:14 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-03-23 14:46:14 +0000
commit715c16ab0a73979dd23d0474756075a35fbc498c (patch)
tree50447ce765141dc0456fb67e64ecf684333e2f0c
parent69ca5a70fd4ae30f8a3beabec4d705f7dd32e3f3 (diff)
downloadbusybox-w32-715c16ab0a73979dd23d0474756075a35fbc498c.tar.gz
busybox-w32-715c16ab0a73979dd23d0474756075a35fbc498c.tar.bz2
busybox-w32-715c16ab0a73979dd23d0474756075a35fbc498c.zip
pscan: add -c, -b: report closed, blocked ports
-rw-r--r--include/usage.h4
-rw-r--r--networking/pscan.c46
2 files changed, 34 insertions, 16 deletions
diff --git a/include/usage.h b/include/usage.h
index aa1b8b6da..7918b24d8 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -3019,10 +3019,12 @@
3019 " 2990 andersen andersen R ps\n" 3019 " 2990 andersen andersen R ps\n"
3020 3020
3021#define pscan_trivial_usage \ 3021#define pscan_trivial_usage \
3022 "[-p MIN_PORT] [-P MAX_PORT] [-t TIMEOUT] [-T MIN_RTT] HOST" 3022 "[-cb] [-p MIN_PORT] [-P MAX_PORT] [-t TIMEOUT] [-T MIN_RTT] HOST"
3023#define pscan_full_usage \ 3023#define pscan_full_usage \
3024 "Scan a host, print all open ports\n" \ 3024 "Scan a host, print all open ports\n" \
3025 "\nOptions:" \ 3025 "\nOptions:" \
3026 "\n -c Show closed ports too" \
3027 "\n -c Show blocked ports too" \
3026 "\n -p Scan from this port (default 1)" \ 3028 "\n -p Scan from this port (default 1)" \
3027 "\n -P Scan up to this port (default 1024)" \ 3029 "\n -P Scan up to this port (default 1024)" \
3028 "\n -t Timeout (default 5000 ms)" \ 3030 "\n -t Timeout (default 5000 ms)" \
diff --git a/networking/pscan.c b/networking/pscan.c
index 022d21254..b332d7133 100644
--- a/networking/pscan.c
+++ b/networking/pscan.c
@@ -42,8 +42,10 @@ int pscan_main(int argc ATTRIBUTE_UNUSED, char **argv)
42 * Rule of thumb: with min_rtt of N msec, scanning 1000 ports 42 * Rule of thumb: with min_rtt of N msec, scanning 1000 ports
43 * will take N seconds at absolute minimum */ 43 * will take N seconds at absolute minimum */
44 const char *opt_min_rtt = "5"; /* -T: default min rtt in msec */ 44 const char *opt_min_rtt = "5"; /* -T: default min rtt in msec */
45 const char *result_str;
45 len_and_sockaddr *lsap; 46 len_and_sockaddr *lsap;
46 int s; 47 int s;
48 unsigned opt;
47 unsigned port, max_port, nports; 49 unsigned port, max_port, nports;
48 unsigned closed_ports = 0; 50 unsigned closed_ports = 0;
49 unsigned open_ports = 0; 51 unsigned open_ports = 0;
@@ -51,16 +53,18 @@ int pscan_main(int argc ATTRIBUTE_UNUSED, char **argv)
51 unsigned timeout; 53 unsigned timeout;
52 unsigned min_rtt; 54 unsigned min_rtt;
53 unsigned rtt_4; 55 unsigned rtt_4;
54 unsigned start; 56 unsigned start, diff;
55 57
56 opt_complementary = "=1"; /* exactly one non-option */ 58 opt_complementary = "=1"; /* exactly one non-option */
57 getopt32(argv, "p:P:t:T:", &opt_min_port, &opt_max_port, &opt_timeout, &opt_min_rtt); 59 opt = getopt32(argv, "cbp:P:t:T:", &opt_min_port, &opt_max_port, &opt_timeout, &opt_min_rtt);
58 argv += optind; 60 argv += optind;
59 max_port = xatou_range(opt_max_port, 1, 65535); 61 max_port = xatou_range(opt_max_port, 1, 65535);
60 port = xatou_range(opt_min_port, 1, max_port); 62 port = xatou_range(opt_min_port, 1, max_port);
61 nports = max_port - port + 1; 63 nports = max_port - port + 1;
62 rtt_4 = timeout = xatou_range(opt_timeout, 1, INT_MAX/1000 / 4) * 1000;
63 min_rtt = xatou_range(opt_min_rtt, 1, INT_MAX/1000 / 4) * 1000; 64 min_rtt = xatou_range(opt_min_rtt, 1, INT_MAX/1000 / 4) * 1000;
65 timeout = xatou_range(opt_timeout, 1, INT_MAX/1000 / 4) * 1000;
66 /* Initial rtt is BIG: */
67 rtt_4 = timeout;
64 68
65 DMSG("min_rtt %u timeout %u", min_rtt, timeout); 69 DMSG("min_rtt %u timeout %u", min_rtt, timeout);
66 70
@@ -74,11 +78,12 @@ int pscan_main(int argc ATTRIBUTE_UNUSED, char **argv)
74 /* The SOCK_STREAM socket type is implemented on the TCP/IP protocol. */ 78 /* The SOCK_STREAM socket type is implemented on the TCP/IP protocol. */
75 set_nport(lsap, htons(port)); 79 set_nport(lsap, htons(port));
76 s = xsocket(lsap->u.sa.sa_family, SOCK_STREAM, 0); 80 s = xsocket(lsap->u.sa.sa_family, SOCK_STREAM, 0);
77
78 /* We need unblocking socket so we don't need to wait for ETIMEOUT. */ 81 /* We need unblocking socket so we don't need to wait for ETIMEOUT. */
79 /* Nonblocking connect typically "fails" with errno == EINPROGRESS */ 82 /* Nonblocking connect typically "fails" with errno == EINPROGRESS */
80 ndelay_on(s); 83 ndelay_on(s);
84
81 DMSG("connect to port %u", port); 85 DMSG("connect to port %u", port);
86 result_str = NULL;
82 start = MONOTONIC_US(); 87 start = MONOTONIC_US();
83 if (connect(s, &lsap->u.sa, lsap->len) == 0) { 88 if (connect(s, &lsap->u.sa, lsap->len) == 0) {
84 /* Unlikely, for me even localhost fails :) */ 89 /* Unlikely, for me even localhost fails :) */
@@ -92,35 +97,46 @@ int pscan_main(int argc ATTRIBUTE_UNUSED, char **argv)
92 bb_perror_nomsg_and_die(); 97 bb_perror_nomsg_and_die();
93 } 98 }
94 99
100 diff = 0;
95 while (1) { 101 while (1) {
96 if (errno == ECONNREFUSED) { 102 if (errno == ECONNREFUSED) {
97 DMSG("port %u: ECONNREFUSED", port); 103 if (opt & 1) /* -c: show closed too */
104 result_str = "closed";
98 closed_ports++; 105 closed_ports++;
99 break; 106 break;
100 } 107 }
101 DERR("port %u errno %d @%u", port, errno, MONOTONIC_US() - start); 108 DERR("port %u errno %d @%u", port, errno, diff);
102 if ((MONOTONIC_US() - start) > rtt_4) 109
110 if (diff > rtt_4) {
111 if (opt & 2) /* -b: show blocked too */
112 result_str = "blocked";
103 break; 113 break;
114 }
104 /* Can sleep (much) longer than specified delay. 115 /* Can sleep (much) longer than specified delay.
105 * We check rtt BEFORE we usleep, otherwise 116 * We check rtt BEFORE we usleep, otherwise
106 * on localhost we'll do zero writes done (!) 117 * on localhost we'll have no writes done (!)
107 * before we exceed (rather small) rtt */ 118 * before we exceed (rather small) rtt */
108 usleep(rtt_4/8); 119 usleep(rtt_4/8);
109 DMSG("write to port %u @%u", port, MONOTONIC_US() - start);
110 if (write(s, " ", 1) >= 0) { /* We were able to write to the socket */
111 open: 120 open:
121 diff = MONOTONIC_US() - start;
122 DMSG("write to port %u @%u", port, diff - start);
123 if (write(s, " ", 1) >= 0) { /* We were able to write to the socket */
112 open_ports++; 124 open_ports++;
113 printf("%5u\ttcp\topen\t%s\n", port, port_name(port)); 125 result_str = "open";
114 break; 126 break;
115 } 127 }
116 } 128 }
117 DMSG("out of loop @%u", MONOTONIC_US() - start); 129 DMSG("out of loop @%u", diff);
130 if (result_str)
131 printf("%5u" "\t" "tcp" "\t" "%s" "\t" "%s" "\n",
132 port, result_str, port_name(port));
118 133
119 /* Estimate new rtt - we don't want to wait entire timeout 134 /* Estimate new rtt - we don't want to wait entire timeout
120 * for each port. *4 allows for rise in net delay. 135 * for each port. *4 allows for rise in net delay.
121 * We increase rtt quickly (*4), decrease slowly (4/8 == 1/2) 136 * We increase rtt quickly (rtt_4*4), decrease slowly
137 * (diff is at least rtt_4/8, *4 == rtt_4/2)
122 * because we don't want to accidentally miss ports. */ 138 * because we don't want to accidentally miss ports. */
123 rtt_4 = (MONOTONIC_US() - start) * 4; 139 rtt_4 = diff * 4;
124 if (rtt_4 < min_rtt) 140 if (rtt_4 < min_rtt)
125 rtt_4 = min_rtt; 141 rtt_4 = min_rtt;
126 if (rtt_4 > timeout) 142 if (rtt_4 > timeout)
@@ -130,7 +146,7 @@ int pscan_main(int argc ATTRIBUTE_UNUSED, char **argv)
130 } 146 }
131 if (ENABLE_FEATURE_CLEAN_UP) free(lsap); 147 if (ENABLE_FEATURE_CLEAN_UP) free(lsap);
132 148
133 printf("%d closed, %d open, %d timed out ports\n", 149 printf("%d closed, %d open, %d timed out (or blocked) ports\n",
134 closed_ports, 150 closed_ports,
135 open_ports, 151 open_ports,
136 nports - (closed_ports + open_ports)); 152 nports - (closed_ports + open_ports));