/* * parallel tcp port scanner */#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; voidcatch(void*, char *msg){ timedout = 1; if(strcmp(msg, "alarm") == 0){ noted(NCONT); } noted(NDFLT);} static longiodialt(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;} voidscanner(void *){ void *p; scan *s; Ioproc *io; io = ioproc(); while(recv(cin, &p) > 0){ s = p; threadsetname("scanner %s!%s!%s", s->proto, s->host, s->service); 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);} voidproduce(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);} voiddoscan(void){ int i; scan *res; for(i = 0; i < nio; i++){ threadcreate(scanner, nil, 8192); } 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); }} voidusage(void){ fprint(2, "%s [-6v] [-t timeoutms] [-n niothread] [-x netmtpt] host [port ...]\n", argv0); threadexitsall("usage");} voidthreadmain(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); /* try to resolve named services through cs if not integer */ for(i = 0; i < argc-1; i++){ if(atoi(argv[i+1]) != 0) theports[i] = strdup(argv[i+1]); else theports[i] = csgetvalue(netmtpt, "tcp", argv[i+1], "port", nil); if(theports[i] == nil) sysfatal("resolving port %s failed: %r", 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); cin = chancreate(sizeof(scan*), nio); cout = chancreate(sizeof(scan*), nio); doscan(); while(nio > 0) yield(); threadexitsall(nil);}
/*
* parallel tcp port scanner
*/
#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;
scan *s;
Ioproc *io;
io = ioproc();
while(recv(cin, &p) > 0){
s = p;
threadsetname("scanner %s!%s!%s", s->proto, s->host, s->service);
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
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;
for(i = 0; i < nio; i++){
threadcreate(scanner, nil, 8192);
}
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);
/* try to resolve named services through cs if not integer */
for(i = 0; i < argc-1; i++){
if(atoi(argv[i+1]) != 0)
theports[i] = strdup(argv[i+1]);
else
theports[i] = csgetvalue(netmtpt, "tcp", argv[i+1], "port", nil);
if(theports[i] == nil)
sysfatal("resolving port %s failed: %r", 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);
cin = chancreate(sizeof(scan*), nio);
cout = chancreate(sizeof(scan*), nio);
doscan();
while(nio > 0)
yield();
threadexitsall(nil);
}