diff options
-rw-r--r-- | include/usage.h | 4 | ||||
-rw-r--r-- | networking/pscan.c | 46 |
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)); |