On Thursday 14 June 2007 16:12, Tito wrote:
> > It's good that you added these comments,
> > but explanation is not clear enough (at least for me).
> >
> > Care to improve?
> > --
> > vda
> >
>
> Here a new version of the patch with improved comments. Enjoy! ;-D
>
> PS: fixed also a stupid typo in my_gettimeofday
> if (!gettimeofday(&now, NULL)) ==> if (gettimeofday(&now, NULL))
s = xsocket(lsap->sa.sa_family, SOCK_STREAM, 0);
ndelay_on(s);
t1 = my_gettimeofday();
connect(s, &lsap->sa, lsap->len);
Ok, here it can be successful, or can fail. You don't even look at return value.
It is useless or what?
These questions need to be explained in order to have understandable code.
Ok. I did a small experiment, added a few debug prints,
and changed it to start scanning from port 79.
# ./busybox pscan -p 80 195.66.192.167 2>2
Scanning 195.66.192.167 ports 1 to 80
Port Proto State Service
80 tcp open www
78 stealth, 1 closed, 1 open ports
logfile:
pscan: connect 45us: Operation now in progress
pscan: write:-1 4us
pscan: write:-1 2us
<15759 more write errors snipped>
pscan: connect 31us: Operation now in progress
pscan: write:-1 2us
<~140000 more write errors snipped>
pscan: write:1 18us
I don't like write() flood, with accompanying horde of gettimeofday calls.
Maybe this? (please see attched).
--
vda
diff -d -urpN busybox.1/include/applets.h busybox.2/include/applets.h
--- busybox.1/include/applets.h 2007-06-10 19:09:48.000000000 +0200
+++ busybox.2/include/applets.h 2007-06-14 21:01:47.000000000 +0200
@@ -257,6 +257,7 @@ USE_HALT(APPLET_ODDNAME(poweroff, halt,
USE_PRINTENV(APPLET(printenv, _BB_DIR_BIN, _BB_SUID_NEVER))
USE_PRINTF(APPLET(printf, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_PS(APPLET(ps, _BB_DIR_BIN, _BB_SUID_NEVER))
+USE_PSCAN(APPLET(pscan, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
USE_PWD(APPLET_NOFORK(pwd, pwd, _BB_DIR_BIN, _BB_SUID_NEVER, pwd))
USE_RAIDAUTORUN(APPLET(raidautorun, _BB_DIR_SBIN, _BB_SUID_NEVER))
USE_RDATE(APPLET(rdate, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
diff -d -urpN busybox.1/include/usage.h busybox.2/include/usage.h
--- busybox.1/include/usage.h 2007-06-10 19:09:48.000000000 +0200
+++ busybox.2/include/usage.h 2007-06-14 22:45:00.000000000 +0200
@@ -2668,6 +2668,13 @@
" 745 root root S [getty]\n" \
" 2990 andersen andersen R ps\n"
+#define pscan_trivial_usage \
+ "[-p PORT][-t TIMEOUT] HOST"
+#define pscan_full_usage \
+ " Scan a host's ports printing all open ports." \
+ "\n\nOptions:\n" \
+ " -p scan up to this port (default 1024)\n" \
+ " -t timeout in milliseconds (default 5000)"
#define pwd_trivial_usage \
""
diff -d -urpN busybox.1/networking/Config.in busybox.2/networking/Config.in
--- busybox.1/networking/Config.in 2007-06-10 19:09:34.000000000 +0200
+++ busybox.2/networking/Config.in 2007-06-14 21:01:47.000000000 +0200
@@ -535,6 +535,12 @@ config FEATURE_FANCY_PING
Make the output from the ping applet include statistics, and at the
same time provide full support for ICMP packets.
+config PSCAN
+ bool "pscan"
+ default n
+ help
+ Simple network port scanner.
+
config ROUTE
bool "route"
default n
diff -d -urpN busybox.1/networking/Kbuild busybox.2/networking/Kbuild
--- busybox.1/networking/Kbuild 2007-06-10 19:09:34.000000000 +0200
+++ busybox.2/networking/Kbuild 2007-06-14 21:01:47.000000000 +0200
@@ -25,6 +25,7 @@ lib-$(CONFIG_NETSTAT) += netstat.o
lib-$(CONFIG_NSLOOKUP) += nslookup.o
lib-$(CONFIG_PING) += ping.o
lib-$(CONFIG_PING6) += ping.o
+lib-$(CONFIG_PSCAN) += pscan.o
lib-$(CONFIG_ROUTE) += route.o
lib-$(CONFIG_TELNET) += telnet.o
lib-$(CONFIG_TELNETD) += telnetd.o
diff -d -urpN busybox.1/networking/pscan.c busybox.2/networking/pscan.c
--- busybox.1/networking/pscan.c 1970-01-01 01:00:00.000000000 +0100
+++ busybox.2/networking/pscan.c 2007-06-14 23:24:35.000000000 +0200
@@ -0,0 +1,136 @@
+/*
+ * Pscan is a mini port scanner implementation for busybox
+ *
+ * Copyright 2007 Tito Ragusa <[EMAIL PROTECTED]>
+ *
+ * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
+ */
+
+#include "libbb.h"
+
+#if 1
+#define DMSG(...) ((void)0)
+#define DERR(...) ((void)0)
+#else /* debugging */
+#define DMSG(...) bb_error_msg(__VA_ARGS__)
+#define DERR(...) bb_perror_msg(__VA_ARGS__)
+#endif
+
+static int my_gettimeofday(void)
+{
+ struct timeval now;
+
+ if (gettimeofday(&now, NULL))
+ return 0;
+ return (now.tv_sec * 1000000 + now.tv_usec);
+}
+
+static const char *my_getservbyport(int port)
+{
+ struct servent *server;
+
+ server = getservbyport(htons(port), NULL);
+ if (server)
+ return server->s_name;
+ return "unknown";
+}
+
+int pscan_main( int argc, char **argv);
+int pscan_main( int argc, char **argv)
+{
+ const char *opt_max_port = "1024"; /* default max port */
+ const char *opt_timeout = "5000"; /* arbitrary default timeout for roundtrip: 5 seconds */
+ unsigned port, max_port;
+ unsigned closed_ports = 0;
+ unsigned open_ports = 0;
+ unsigned timeout; /* in us */
+ unsigned rtt; /* in us */
+ unsigned start; /* in us */
+ int s;
+ len_and_sockaddr *lsap;
+
+ opt_complementary = "-1";
+ getopt32(argc, argv, "p:t:", &opt_max_port, &opt_timeout);
+
+// TODO: min port
+
+ max_port = xatou_range(opt_max_port, 1, 65535);
+ rtt = timeout = xatou_range(opt_timeout, 1, INT_MAX/1000) * 1000;
+ argv += optind;
+ lsap = xhost2sockaddr(*argv, max_port);
+
+ printf("Scanning %s ports 1 to %d\n Port\tProto\tState\tService\n", *argv, max_port);
+
+ for (port = 1; port <= max_port; port++) {
+ DMSG("rtt %u", rtt);
+
+ /* The SOCK_STREAM socket type is implemented on the TCP/IP protocol. */
+ set_nport(lsap, htons(port));
+ s = xsocket(lsap->sa.sa_family, SOCK_STREAM, 0);
+
+ /* We need unblocking socket so we don't need to wait for ETIMEOUT. */
+ /* Nonblocking connect typically "fails" with errno == EINPROGRESS */
+ ndelay_on(s);
+ DMSG("connect to port %u", port);
+ start = my_gettimeofday();
+ if (connect(s, &lsap->sa, lsap->len) == 0) {
+ /* Unlikely, for me even localhost fails :) */
+ DMSG("connect succeeded");
+ goto open;
+ }
+ /* Check for untypical errors... */
+ if (errno != EAGAIN && errno != EINPROGRESS
+ && errno != ECONNREFUSED
+ ) {
+ bb_perror_nomsg_and_die();
+ }
+
+ while (1) {
+ if (errno == ECONNREFUSED) {
+ DMSG("port %u: ECONNREFUSED", port);
+ closed_ports++;
+ break;
+ }
+ DERR("port %u errno %d @%u", port, errno, my_gettimeofday() - start);
+ if ((my_gettimeofday() - start) > rtt)
+ break;
+ /* Can sleep (much) longer than this.
+ * We check rtt BEFORE we usleep, otherwise
+ * on localhost we'll do zero writes done (!)
+ * before we exceed (rather small) rtt */
+ usleep(rtt/8);
+ DMSG("write to port %u @%u", port, my_gettimeofday() - start);
+ if (write(s, " ", 1) >= 0) { /* We were able to write to the socket */
+ open:
+ open_ports++;
+ printf("%5u\ttcp\topen\t%s\n", port, my_getservbyport(port));
+ break;
+ }
+ }
+ DMSG("out of loop @%u", my_gettimeofday() - start);
+
+ /* Estimate new rtt - we don't want to wait entire timeout
+ * for each port. *4 allows for rise in net delay.
+ * We increase rtt quickly (*4), decrease slowly (4/8 == 1/2)
+ * because we don't want to accidentally miss ports. */
+ rtt = (my_gettimeofday() - start) * 4;
+ if (rtt < 1000)
+ rtt = 1000;
+
+// TODO: instead of fixed 1000, it makes sense to have
+// option for *minimum* timeout. Heavily firewalled/shaped
+// links can be very jerky...
+
+ if (rtt > timeout)
+ rtt = timeout;
+
+ close(s);
+ }
+ /*free(lsap);*/
+
+ printf("%d closed, %d open, %d timed out ports\n",
+ closed_ports,
+ open_ports,
+ max_port - (closed_ports + open_ports));
+ return EXIT_SUCCESS;
+}
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox