On Friday 15 June 2007 23:16:51 Tito wrote:
> On Thursday 14 June 2007 23:27:04 Denis Vlasenko wrote:
> > 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
> > 
> 
> Looks good to me, added some of the TODOs and changed all the time to msec.
> Please check if i fully understood your code. Sorry no time for a patch right 
> now,
> sending the file I've changed. If needed patch will follow tomorrow. ;-)
> 
> Ciao,
> Tito
> PS: change usage.h to
> 
> #define pscan_trivial_usage \
>        "[-p MIN_PORT][-P MAX_PORT][-t MIN_RTT][-T TIMEOUT] HOST"
> #define pscan_full_usage \
>        " Scan a host's ports printing all open ports." \
>        "\n\nOptions:\n" \
>        "      -p      scan from this port (default 1)\n" \
>        "      -P      scan up to this port (default 1024)\n" \
>        "      -t      minimum roundtrip time in msec (default 1000)"\
>        "      -T      timeout in msecs (default 5000)"
> 

Hi, here is patch V5, enjoy! ;-)

I tweaked a little the rtt code as i noticed problems with timed out ports
that should have been open (www.kernel.org) and I hope I was able to speed 
up the scan (just a feeling, not timed it yet). Seems to work fine also
on localhost. Please take one more look at it. Good weekend.

Ciao,
Tito
--- busybox.orig/networking/Config.in	2007-05-26 23:23:37.000000000 +0200
+++ busybox/networking/Config.in	2007-06-12 21:24:18.000000000 +0200
@@ -535,6 +535,12 @@
 	  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
--- busybox.orig/networking/Kbuild	2007-04-12 22:30:12.000000000 +0200
+++ busybox/networking/Kbuild	2007-06-12 21:24:18.000000000 +0200
@@ -25,6 +25,7 @@
 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
--- busybox.orig/include/applets.h	2007-05-19 23:33:51.000000000 +0200
+++ busybox/include/applets.h	2007-06-12 21:24:18.000000000 +0200
@@ -257,6 +257,7 @@
 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))
--- busybox.orig/networking/pscan.c	1970-01-01 01:00:00.000000000 +0100
+++ busybox/networking/pscan.c	2007-06-16 14:41:04.000000000 +0200
@@ -0,0 +1,139 @@
+/*
+ * 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"
+
+/* debugging */
+#ifdef DEBUG
+#define DMSG(...) bb_error_msg(__VA_ARGS__)
+#define DERR(...) bb_perror_msg(__VA_ARGS__)
+#else
+#define DMSG(...) ((void)0)
+#define DERR(...) ((void)0)
+#endif
+
+/* Returns time in msec */
+static unsigned long my_gettimeofday(void)
+{
+	struct timeval now;
+	
+	if (gettimeofday(&now, NULL))
+		return 0;
+	return (now.tv_sec * 1000 + now.tv_usec / 1000);
+}
+
+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_min_port = "1";             /* default min port */
+	const char *opt_max_timeout = "5000";       /* arbitrary default max timeout for roundtrip: 5000 mseconds */
+	const char *opt_min_timeout = "100";        /* arbitrary default max timeout for roundtrip: 100  mseconds */
+	unsigned port;
+	unsigned max_port;
+	unsigned closed_ports = 0;
+	unsigned open_ports = 0;
+	unsigned long timeout;                           /* in ms */
+	unsigned long min_timeout;                       /* in ms */
+	unsigned long rtt;                               /* in ms */
+	unsigned long start;                             /* in ms */
+	int s;
+	len_and_sockaddr *lsap;
+
+	opt_complementary = "-1";
+	getopt32(argc, argv, "p:P:t:T:", &opt_min_port, &opt_max_port, &opt_max_timeout, &opt_min_timeout);
+
+	max_port =  xatou_range(opt_max_port, 1, 65535);
+	port =  xatou_range(opt_min_port, 1, 65535);
+	rtt = timeout = xatou_range(opt_max_timeout, 1, ULONG_MAX);
+	min_timeout = xatou_range(opt_min_timeout, 1, ULONG_MAX);
+	argv += optind;
+	lsap = xhost2sockaddr(*argv, port);
+
+	printf("Scanning %s ports 1 to %d\n Port\tProto\tState\tService\n", *argv, max_port);
+
+	for (; port <= max_port; port++) {
+		DMSG("rtt %lu", 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 @%lu", port, errno, my_gettimeofday() - start);
+			/* (rtt * 4) allows for rise in net delay, because we don't 
+			 * want to accidentally miss ports. We don't do rtt*=4 as we want 
+			 * to keep our rtt as accurate as possible to speed up the scan.
+			 * We insist here until our timeout is reached. */
+			if ((my_gettimeofday() - start) > (rtt * 4) && rtt > timeout) {
+				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*1000);
+			DMSG("write to port %u @%lu", 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 @%lu", my_gettimeofday() - start);
+		/* Estimate new rtt - we don't want to wait entire timeout
+		 * for each port */
+		rtt = (my_gettimeofday() - start);
+		if (rtt < min_timeout)
+			rtt = min_timeout;
+		if (rtt > timeout)
+			rtt = timeout;
+		/* Clean up */
+		close(s);
+	}
+	if (ENABLE_FEATURE_CLEAN_UP) 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.orig/include/usage.h	2007-06-16 08:50:32.000000000 +0200
+++ busybox/include/usage.h	2007-06-16 14:48:37.000000000 +0200
@@ -2675,6 +2675,15 @@
        "  745 root     root     S [getty]\n" \
        " 2990 andersen andersen R ps\n"
 
+#define pscan_trivial_usage \
+       "[-p MIN_PORT][-P MAX_PORT][-t MIN_RTT][-T TIMEOUT] HOST"
+#define pscan_full_usage \
+       " Scan a host's ports printing all open ports." \
+       "\n\nOptions:\n" \
+       "	-p	scan from this port (default 1)\n" \
+       "	-P	scan up to this port (default 1024)\n" \
+       "	-t	minimum roundtrip time in msec (default 100)"\
+       "	-T	timeout in msecs (default 5000)"
 
 #define pwd_trivial_usage \
        ""
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox

Reply via email to