mischiefinitial commitf855ef311 years agoHistory
269 lines · 4.4 KB · C
RawDownload
/* * 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);}