311 lines
8.1 KiB
C
311 lines
8.1 KiB
C
/*
|
|
This is an FSP port scanner that I wrote in late '92. It's not very fast,
|
|
but that was a limit of the original fver code (and of current versions
|
|
of fver). Just type "fspscan -h" to get help on how it's used.
|
|
My appologies for the nasty code...I just wanted something that worked.
|
|
|
|
-Cuda
|
|
*/
|
|
/*
|
|
I have ported it in September 2003 to modern C and added to FSP software
|
|
suite. Don't blame me for the code, i have not touched it.
|
|
|
|
-Radim
|
|
*/
|
|
/*********************************************************************\
|
|
* Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu) *
|
|
* *
|
|
* You may copy or modify this file in any manner you wish, provided *
|
|
* that this notice is always included, and that you hold the author *
|
|
* harmless for any loss or damage resulting from the installation or *
|
|
* use of this software. *
|
|
\*********************************************************************/
|
|
|
|
|
|
/****************************************************************
|
|
* FindPort -- hack of fver to find valid ports on a FSP server *
|
|
* by Cuda. Yes, it's ugly, but it works for me. *
|
|
* Type "fspscan -h" to see how it is used. *
|
|
****************************************************************/
|
|
|
|
#include "fspscan.h"
|
|
#include <netdb.h>
|
|
#include <errno.h>
|
|
#include <getopt.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
char *host = NULL;
|
|
char *outputfile = NULL;
|
|
/* Default values */
|
|
int localport = 9191;
|
|
int remoteport = 21;
|
|
int endport = 65535;
|
|
int retries = 3;
|
|
int client_trace = 0;
|
|
|
|
static int myfd;
|
|
static struct sockaddr_in server_addr;
|
|
static unsigned short myseq = 0;
|
|
static unsigned short key;
|
|
int client_intr_state = 0;
|
|
|
|
static struct sockaddr_in INET_ZERO;
|
|
|
|
#define DSIZE (sizeof(int)*8)
|
|
#define SAVE(A) { int sav; sav = errno; A; errno = sav; }
|
|
|
|
static void printhelp(int argc,char **argv)
|
|
{
|
|
fprintf(stderr,"%s - an fsp port scanner\n",argv[0]);
|
|
fprintf(stderr,"Usage: %s [-h]\n",argv[0]);
|
|
fprintf(stderr," (prints this help screen)\n");
|
|
fprintf(stderr," %s [-t][-o file][-r retries][-l local port][-i ip address][-p starting port][-e ending port]\n\n",argv[0]);
|
|
fprintf(stderr,"Defaults: (-o) file = stdout\n");
|
|
fprintf(stderr," (-l) local port = 9191\n");
|
|
fprintf(stderr," (-p) starting port = 21\n");
|
|
fprintf(stderr," (-e) ending port = 65535\n");
|
|
fprintf(stderr," (-r) retries = 3\n");
|
|
fprintf(stderr," (-t) trace = off\n");
|
|
fprintf(stderr," (-i) host-ip = none (host MUST be specified)\n");
|
|
exit(0);
|
|
}
|
|
|
|
static void fdclose(void)
|
|
{
|
|
close(myfd);
|
|
}
|
|
|
|
static void client_done(void)
|
|
{
|
|
(void) client_interact(CC_BYE,0L,0,NULLP,0,NULLP);
|
|
}
|
|
|
|
int main(int argc,char **argv)
|
|
{
|
|
int i;
|
|
UBUF *ub;
|
|
FILE *logfile;
|
|
|
|
while ((i = getopt(argc, argv, "htp:o:r:l:i:e:")) != EOF) {
|
|
switch(i) {
|
|
case 'h':
|
|
printhelp(argc, argv);
|
|
break;
|
|
case 't':
|
|
client_trace=1;
|
|
break;
|
|
case 'r':
|
|
retries=atoi(optarg);
|
|
break;
|
|
case 'p':
|
|
remoteport=atoi(optarg);
|
|
break;
|
|
case 'e':
|
|
endport=atoi(optarg);
|
|
break;
|
|
case 'l':
|
|
localport=atoi(optarg);
|
|
break;
|
|
case 'i':
|
|
host = (char *) malloc(strlen(optarg)+1);
|
|
strcpy(host, optarg);
|
|
break;
|
|
case 'o':
|
|
outputfile = (char *) malloc(strlen(optarg)+1);
|
|
strcpy(outputfile, optarg);
|
|
break;
|
|
case '?':
|
|
printhelp(argc, argv);
|
|
break;
|
|
default:
|
|
fprintf(stderr,"This error should not happen\n");
|
|
}
|
|
}
|
|
|
|
if (host == NULL) {
|
|
fprintf(stderr, "host/ip not specified, unable to continue\n");
|
|
printhelp(argc, argv);
|
|
exit(1);
|
|
}
|
|
|
|
if (outputfile == NULL) {
|
|
logfile=stdout;
|
|
} else {
|
|
logfile=fopen(outputfile,"a+");
|
|
}
|
|
|
|
fprintf(logfile,"Scanning %s\n",host);
|
|
|
|
for ( ; remoteport<=endport; ++remoteport) {
|
|
init_client(host,remoteport,localport);
|
|
signal(SIGINT,client_intr);
|
|
|
|
ub = client_interact(CC_VERSION,0L, 0,NULLP, 0,NULLP);
|
|
if (ub)
|
|
/* success! */
|
|
fprintf(logfile,"Found FSP ver: %s on port %0d\n",
|
|
ub->buf,remoteport);
|
|
else
|
|
fprintf(logfile,"%0d...nada\n",remoteport);
|
|
fflush(logfile);
|
|
fdclose();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
UBUF *client_interact(cmd,pos,l1,p1,l2,p2)
|
|
unsigned cmd, l1, l2;
|
|
unsigned long pos;
|
|
unsigned char *p1, *p2;
|
|
{
|
|
struct sockaddr_in from;
|
|
UBUF sbuf;
|
|
static UBUF rbuf;
|
|
unsigned char *s, *t, *d;
|
|
unsigned u, n, sum, mlen;
|
|
fd_set mask;
|
|
int retval, bytes, retry;
|
|
|
|
sbuf.cmd = cmd;
|
|
sbuf.len = htons(l1);
|
|
sbuf.pos = htonl(pos);
|
|
|
|
client_intr_state = 1;
|
|
FD_ZERO(&mask);
|
|
|
|
for(u = l1, d = (unsigned char *) sbuf.buf; u--; *d++ = *p1++);
|
|
for(u = l2 ; u--; *d++ = *p2++);
|
|
mlen = d - (unsigned char *) &sbuf;
|
|
|
|
for(retry = 0; retry < retries; retry++) {
|
|
sbuf.key = key;
|
|
sbuf.seq = myseq;
|
|
sbuf.sum = 0;
|
|
|
|
for(t = (unsigned char *) &sbuf, sum = n = mlen; n--; sum += *t++);
|
|
sbuf.sum = sum + (sum >> 8);
|
|
if(client_trace && retry)
|
|
write(2,"R",1);
|
|
|
|
if(sendto(myfd,&sbuf,mlen,0,(struct sockaddr*)&server_addr,sizeof(server_addr)) == -1)
|
|
{ perror("sendto"); exit(1); }
|
|
FD_SET(myfd,&mask);
|
|
|
|
while(1) {
|
|
retval = _x_select(&mask, 3000L);
|
|
|
|
if((retval == -1) && (errno = EINTR)) continue;
|
|
|
|
if(retval == 1) { /* an incoming message is waiting */
|
|
bytes = sizeof(from);
|
|
if((bytes = recvfrom(myfd,(char*)&rbuf,sizeof(rbuf),0,
|
|
(struct sockaddr*)&from,&bytes)) < UBUF_HSIZE) continue;
|
|
|
|
s = (unsigned char *) &rbuf;
|
|
d = s + bytes;
|
|
u = rbuf.sum; rbuf.sum = 0;
|
|
for(t = s, sum = 0; t < d; sum += *t++);
|
|
sum = (sum + (sum >> 8)) & 0xff;
|
|
if(sum != u) continue; /* wrong check sum */
|
|
|
|
rbuf.len = htons(rbuf.len);
|
|
rbuf.pos = htonl(rbuf.pos);
|
|
|
|
if(rbuf.seq != myseq) continue; /* wrong seq # */
|
|
if(rbuf.len+UBUF_HSIZE > bytes) continue; /* truncated. */
|
|
|
|
myseq++; key = rbuf.key; /* update seq and keys. */
|
|
|
|
if(client_intr_state == 2) { client_done(); exit(1); }
|
|
|
|
return(&rbuf);
|
|
|
|
} else break; /* go back to re-transmit buffer again */
|
|
}
|
|
}
|
|
/* return NULL if there have been too many retries - ffindport hack */
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
void init_client(char *myhost,int port,int myport)
|
|
{
|
|
if((myfd = _x_udp(&myport)) == -1)
|
|
{ perror("socket open"); exit(1); }
|
|
|
|
if(_x_adr(myhost,port,&server_addr) == -1)
|
|
{ perror("server addr"); exit(1); }
|
|
}
|
|
|
|
|
|
void client_intr(int sig)
|
|
{
|
|
switch(client_intr_state) {
|
|
case 0: exit(2);
|
|
case 1: client_intr_state = 2; break;
|
|
case 2: exit(3);
|
|
}
|
|
}
|
|
|
|
|
|
int _x_udp(int *port)
|
|
{
|
|
int f, len, zz;
|
|
struct sockaddr_in me ;
|
|
struct sockaddr_in sin;
|
|
|
|
me = sin = INET_ZERO;
|
|
|
|
me.sin_port = htons((unsigned short) *port);
|
|
me.sin_family = AF_INET;
|
|
|
|
if((f=socket(AF_INET,SOCK_DGRAM,0)) == -1) return(-1);
|
|
|
|
if( setsockopt(f,SOL_SOCKET,SO_REUSEADDR,&zz,sizeof(zz)) < 0 ||
|
|
bind(f,(struct sockaddr *) &me,(len = sizeof(me))) < 0 ||
|
|
getsockname(f,(struct sockaddr*)&sin,&len) < 0)
|
|
{ SAVE(((void) close(f))); return(-1); }
|
|
if(!*port) *port = ntohs((unsigned short) sin.sin_port); return(f);
|
|
}
|
|
|
|
int _x_adr(char *host,int port,struct sockaddr_in *his)
|
|
{
|
|
char myhost[128];
|
|
struct hostent *H;
|
|
int i;
|
|
char *s, *d;
|
|
|
|
*his = INET_ZERO;
|
|
if(!host) (void) gethostname(host = myhost,sizeof(myhost));
|
|
|
|
if((his->sin_addr.s_addr = inet_addr(host)) != INADDR_NONE) {
|
|
his->sin_family = AF_INET;
|
|
} else
|
|
if(H = gethostbyname(host)) {
|
|
for(s = (char *)H->h_addr,
|
|
d = (char *)&his->sin_addr,
|
|
i = H->h_length; i--; *d++ = *s++);
|
|
his->sin_family = H->h_addrtype;
|
|
} else return(-1);
|
|
his->sin_port = htons((unsigned short) port);
|
|
|
|
return(0);
|
|
}
|
|
|
|
int _x_select(fd_set *rf, long tt) /* tt is in unit of ms */
|
|
{
|
|
struct timeval timeout;
|
|
|
|
if(tt != -1)
|
|
{
|
|
timeout.tv_sec = tt / 1000;
|
|
timeout.tv_usec = (tt % 1000)*1000;
|
|
return(select(DSIZE, rf, NULL, NULL, &timeout));
|
|
}
|
|
|
|
return(select(DSIZE, rf, NULL, NULL, (struct timeval *) 0));
|
|
}
|