ref: c647ac0337f82a8ee91b99972b10ef7caea71353
parent: 08a0d081614fed42903406b7731fe36168cb3892
author: Michael Misch <michaelmisch1985@gmail.com>
date: Mon May 8 02:14:21 PDT 2023
Make sure netscan is available, as it's in extra and may not be as accessible
--- /dev/null
+++ b/netscan.c
@@ -1,0 +1,270 @@
+/*
+ * parallel tcp port scanner
+ *
+ * TODO: make netscan.c:/^iodialt use scan->clone
+ */
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <bio.h>
+#include <ndb.h>
+
+typedef struct scan scan;
+typedef struct toscan toscan;
+
+struct scan
+{
+ char clone[NETPATHLEN];
+ char proto[64];
+ char host[256];
+ char service[64];
+
+ /* result */
+ char err[ERRMAX];
+ int waserror;
+};
+
+int debug;
+int flagv;
+int flag6;
+int flagt;
+char *netmtpt = "/net";
+long nio;
+Channel *cin;
+Channel *cout;
+
+/* global scanner state */
+char *theclone;
+char *thehost;
+char **theports;
+int thenports;
+
+int timedout;
+
+void
+catch(void*, char *msg){
+ timedout = 1;
+
+ if(strcmp(msg, "alarm") == 0){
+ noted(NCONT);
+ }
+
+ noted(NDFLT);
+}
+
+static long
+iodialt(va_list *arg)
+{
+ int fd, ms, ret;
+ scan *s;
+
+ s = va_arg(*arg, scan*);
+ ms = va_arg(*arg, int);
+
+ threadsetname("iodialt %s!%s!%s", s->proto, s->host, s->service);
+
+ timedout = 0;
+ ret = 0;
+
+ notify(catch);
+ alarm(ms);
+
+ fd = open(theclone, ORDWR);
+ if(fd < 0)
+ sysfatal("open: %r");
+ if(fprint(fd, "connect %s!%s", s->host, s->service) < 0)
+ ret = -1;
+
+ alarm(0);
+ if(timedout)
+ werrstr("connection timed out");
+
+ close(fd);
+ return ret;
+}
+
+void
+scanner(void *)
+{
+ void *p;
+ char addr[256];
+ scan *s;
+ Ioproc *io;
+
+ io = ioproc();
+
+ while(recv(cin, &p) > 0){
+ s = p;
+
+ threadsetname("scanner %s", addr);
+
+ if(iocall(io, iodialt, s, flagt) < 0){
+ s->waserror = 1;
+ errstr(s->err, ERRMAX);
+ } else {
+ s->waserror = 0;
+ s->err[0] = 0;
+ }
+
+ if(sendp(cout, s) < 0)
+ break;
+
+ threadsetname("scanner idle");
+ }
+
+ closeioproc(io);
+
+ adec(&nio);
+
+ threadexits(nil);
+}
+
+void
+initscan(void)
+{
+ int i;
+
+ cin = chancreate(sizeof(scan*), 0);
+ cout = chancreate(sizeof(scan*), 10);
+
+ for(i = 0; i < nio; i++){
+ threadcreate(scanner, nil, 8192);
+ }
+}
+
+void
+produce(void*)
+{
+ int i;
+ scan *res;
+
+ threadsetname("producer");
+
+ for(i = 0; i < thenports; i++){
+ res = mallocz(sizeof(scan), 1);
+ snprint(res->proto, sizeof(res->proto), "%s", "tcp");
+ snprint(res->host, sizeof(res->host), "%s", thehost);
+ snprint(res->service, sizeof(res->service), "%s", theports[i]);
+ sendp(cin, res);
+ }
+
+ chanclose(cin);
+ threadexits(nil);
+}
+
+void
+doscan(void)
+{
+ int i;
+ scan *res;
+ threadcreate(produce, nil, 8192);
+
+ for(i = 0; i < thenports; i++){
+ if((res = recvp(cout)) == nil)
+ break;
+
+ if(res->waserror == 0)
+ print("%s!%s!%-5s open\n", res->proto, res->host, res->service);
+ else if(flagv)
+ print("%s!%s!%-5s closed %s\n", res->proto, res->host, res->service, res->err);
+
+ free(res);
+ }
+}
+
+void
+usage(void)
+{
+ fprint(2, "%s [-6v] [-t timeoutms] [-n niothread] [-x netmtpt] host [port ...]\n", argv0);
+ threadexitsall("usage");
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+ int defports[] = { 7, 9, 21, 22, 23, 25, 80, 110, 143, 443, 564, 567, 993, 995, 5356, 8080, 17007, 17009, 17010 };
+ int fd, i;
+ char *f[3], buf[256];
+
+ debug = 0;
+ flagv = 0;
+ flag6 = 0;
+ flagt = 5000;
+ nio = 10;
+
+ ARGBEGIN{
+ case 'd':
+ debug = 1;
+ break;
+ case 'v':
+ flagv = 1;
+ break;
+ case '6':
+ flag6 = 1;
+ break;
+ case 't':
+ if((flagt = atoi(EARGF(usage()))) < 0)
+ usage();
+ break;
+ case 'n':
+ if((nio = atoi(EARGF(usage()))) < 1)
+ usage();
+ break;
+ case 'x':
+ netmtpt = EARGF(usage());
+ break;
+ default:
+ fprint(2, "unknown flag -%c\n", ARGC());
+ usage();
+ }ARGEND
+
+ if(argc < 1)
+ usage();
+
+ if(argc == 1){
+ /* default port list */
+ thenports = nelem(defports);
+ theports = mallocz(thenports * sizeof(char*), 1);
+ for(i = 0; i < nelem(defports); i++)
+ theports[i] = smprint("%d", defports[i]);
+ } else {
+ thenports = argc-1;
+ theports = mallocz(thenports * sizeof(char*), 1);
+ for(i = 0; i < argc-1; i++)
+ theports[i] = strdup(argv[i+1]);
+ }
+
+ if(thenports < nio)
+ nio = thenports;
+
+ /* resolve host */
+ snprint(buf, sizeof(buf), "%s/cs", netmtpt);
+ if((fd = open(buf, ORDWR)) < 0)
+ sysfatal("open: %r");
+
+ snprint(buf, sizeof(buf), "tcp!%s!0", argv[0]);
+ if(write(fd, buf, strlen(buf)) < 0)
+ sysfatal("write: %r");
+
+ seek(fd, 0, 0);
+ if((i = read(fd, buf, sizeof(buf)-1)) < 0)
+ sysfatal("read: %r");
+
+ buf[i] = 0;
+ if(getfields(buf, f, 3, 1, " !") < 2)
+ sysfatal("bad cs fields");
+
+ theclone = smprint("%s/%s/clone", netmtpt, "tcp");
+ thehost = strdup(f[1]);
+
+ if(flagv)
+ fprint(2, "dialing %s through %s\n", thehost, theclone);
+
+ initscan();
+ doscan();
+
+ while(nio > 0)
+ yield();
+
+ threadexitsall(nil);
+}