fspscan.c                                                                                           100644    3732     155        21775  5566527277  10064  0                                                                                                    ustar   rob                                                                                                                                                                                                                                                    /*********************************************************************\
*  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>

char *host = NULL;
char *outputfile = NULL;
/* Default values */
int  localport = 9191; 
int  remoteport = 21;
int  retries = 3;
int  client_trace = 0;
int  errno;

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 = { AF_INET };

#define DSIZE (sizeof(int)*8)
#define SAVE(A) { int sav; sav = errno; A; errno = sav; }

long inet_addr();

main(argc,argv)
int argc;
char **argv;
{
    int  i;
    UBUF *ub;
    FILE *logfile;
    extern char *optarg;

    while ((i = getopt(argc, argv, "htp:o:r:l:i:")) != 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 '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) {
        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();
    }
}

printhelp(argc,argv)
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]\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,"          (-r) retries = 3\n");
    fprintf(stderr,"          (-t) trace = off\n");
    fprintf(stderr,"          (-i) host-ip = none (host MUST be specified)\n");
    exit(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, mask, mlen;
    int retval, bytes, retry;

    sbuf.cmd = cmd;
    sbuf.len = htons(l1);
    sbuf.pos = htonl(pos);

    client_intr_state = 1;

    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,&server_addr,sizeof(server_addr)) == -1)
						{ perror("sendto"); exit(1); }
	mask = 1 << myfd;

	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,
					&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);
}


init_client(host,port,myport)
    char *host;
    int   port;
    int myport;
{
    if((myfd = _x_udp(&myport)) == -1)
		{ perror("socket open"); exit(1); }

    if(_x_adr(host,port,&server_addr) == -1)
		{ perror("server addr"); exit(1); } 
}

client_done()
{
    (void) client_interact(CC_BYE,0L,0,NULLP,0,NULLP);
}

void client_intr()
{
    switch(client_intr_state) {
        case 0: exit(2);
        case 1: client_intr_state = 2; break;
        case 2: exit(3);
    }
}

fdclose()
{
    close(myfd);
}


#ifndef EXOS_IPC

_x_udp(port)
    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,(int)&zz,sizeof(zz)) < 0 ||
        bind(f,(struct sockaddr *) &me,(len = sizeof(me))) < 0 ||
        getsockname(f,(char *)&sin,&len) < 0)
                                { SAVE(((void) close(f))); return(-1); }
    if(!*port) *port = ntohs((unsigned short) sin.sin_port); return(f);
}      

_x_adr(host,port,his)
    struct sockaddr_in *his;
    char *host;
    int port;
{
    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)) != -1) {   
	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);
}

_x_select(rf, tt)       /* tt is in unit of ms */
    int *rf;
    long tt;
{
    struct timeval timeout;
 
    if(tt != -1)
    {
        timeout.tv_sec  =  tt / 1000;
        timeout.tv_usec = (tt % 1000)*1000;
        return(select(DSIZE, rf, (int *) 0, (int *) 0, &timeout));
    }
       
    return(select(DSIZE, rf, (int *) 0, (int *) 0, (struct timeval *) 0));
}
#endif  /* not EXOS_IPC */


#ifdef EXOS_IPC

extern long rhost();

_x_udp(port)
    int *port;
{
    struct sockaddr_in sin; int f;

    sin = INET_ZERO;
    sin.sin_family = AF_INET;
    sin.sin_port   = htons((unsigned short) *port);
    if((f = socket(SOCK_DGRAM, (struct sockproto *) 0, &sin, SO_REUSEADDR))
							== -1) return(-1);
    sin = INET_ZERO;
    if(socketaddr(f,&sin) == -1) { SAVE(((void) close(f))); return(-1); }
    if(!*port) *port = ntohs((unsigned short) sin.sin_port); return(f);
}

_x_adr(host,port,his)
    char *host;
    int port;
    struct sockaddr_in *his;
{
    char myhost[128];
    int f;

    *his = INET_ZERO;
    if(!host) (void) gethostname(host = myhost,sizeof(myhost));

    his->sin_family = AF_INET;
    his->sin_port   = htons((unsigned short) port);

    if((his->sin_addr.s_addr = rhost(&host)) == -1) return(-1);

    return(0);
}

_x_select(readfds, tt)
    int *readfds;
    long tt;				/* Time to wait in miniseconds. */
{
    int  code;
    long mask = *readfds;

    if(tt & 0xc0000000) tt = 0x3fffffff;/* It does not like 0x7fffffff. */

    code = select(DSIZE, &mask, (long *) 0, tt);

    *readfds = mask;

    return(code);
}

recvfrom(s, msg, len, flags, from, fromlen)
    char *msg;
    int s, len, flags, *fromlen;
    struct sockaddr_in *from;
{
    return(receive(s,from,msg,len));
}

sendto(s, msg, len, flags, to, tolen)
    char *msg;
    int s, len, flags, tolen;
    struct sockaddr_in *to;
{
     to->sin_family = AF_INET;
     return(send(s,to,msg,len));
}

#endif /* EXOS_IPC */


   Makefile                                                                                            100644    3732     155          613  5566527335   7642  0                                                                                                    ustar   rob                                                                                                                                                                                                                                                    # Makefile for the FSP Port Scanner  -  by Cuda
#############################################################################
# This is where the version number string comes from:
#
VERSION_STR="Original Caltech version 1.0, Dec 1991"

CFLAGS=-O

PROGS=	fspscan

all:	  ${PROGS}

fspscan: fspscan.o
	cc ${CFLAGS} -o ${PROGS} ${PROGS}.o ${LIB}

fspscan.o: fspscan.c 

clean:
	rm -f *.o ${PROGS}

                                                                                                                     README                                                                                              100644    3732     155          444  5566530266   7061  0                                                                                                    ustar   rob                                                                                                                                                                                                                                                    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

                                                                                                                                                                                                                            fspscan.h                                                                                           100644    3732     155        11620  5566527433  10047  0                                                                                                    ustar   rob                                                                                                                                                                                                                                                    #include <stdio.h>
#include <sys/param.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <signal.h>

/****************************************************************************
*  UBUF is the structure of message exchanged between server and clients. 
*
*    The 'buf' part of the buffer is variable lenght up to max of 1024.
*    The 'key' field is used by the server for sequence identification.
*    The 'seq' field is used by the client for sequence identification.
*
*  Client's message to server contain a key value that is the same as the
*  key value of the previous message received from the server.  Similarly,
*  the server's message to client contains a seq value that is the same
*  as the seq value of the previous message from the client. 
*
*  The buf field is logically partitioned into two parts by the len field.
*  The len field indicate the size of the first part of the buffer starting
*  at buf[0].  The rest of the buffer is the second field.  In some cases
*  both fields can contain information.
*
****************************************************************************/

#define UBUF_HSIZE 12                           /* 12 bytes for the header */
#define UBUF_SPACE 1024			        /* maximum payload.        */

typedef struct UBUF {            char   cmd;  /* message code.             */
                        unsigned char   sum;  /* message checksum.         */
                        unsigned short  key;  /* message key.              */
                        unsigned short  seq;  /* message sequence number.  */
                        unsigned short  len;  /* number of bytes in buf 1. */
                        unsigned long   pos;  /* location in the file.     */

                        char   buf[UBUF_SPACE];
                    } UBUF;

/* definition of cmd */

#define CC_VERSION	0x10	/* return server's version string.	*/
#define CC_ERR          0x40    /* error response from server.          */
#define CC_GET_DIR      0x41    /* get a directory listing.             */
#define CC_GET_FILE     0x42    /* get a file.                          */
#define CC_UP_LOAD      0x43    /* open a file for writing.             */
#define CC_INSTALL      0x44    /* close a file opened for writing.     */
#define CC_DEL_FILE     0x45    /* delete a file.                       */
#define CC_DEL_DIR      0x46    /* delete a directory.                  */
#define CC_GET_PRO      0x47    /* get directory protection.            */
#define CC_SET_PRO      0x48    /* set directory protection.            */
#define CC_MAKE_DIR     0x49    /* create a directory.                  */
#define CC_BYE          0x4A    /* finish a session.                    */

/****************************************************************************
*  RDIRENT is the structure of a directory entry contained in a .FSP_CONTENT
*  file.  Each entry contains a 4 bytes quantity 'time', a 4 bytes quentity
*  'size', and 1 byte of 'type'.  Then followed by x number of bytes of
*  'name'.  'name' is null terminated.  Then followed by enough number of
*  padding to fill to an 4-byte boundary.  At this point, if the next entry
*  to follow will spread across 1k boundary, then two possible things will
*  happen.  1) if the header fits between this entry and the 1k boundary,
*  a complete header will be filled in with a 'type' set to RDTYPE_SKIP.
*  And then enough bytes to padd to 1k boundary.  2) if the header does
*  not fit, then simply pad to the 1k boundary.  This will make sure that
*  messages carrying directory information carry only complete directory
*  entries and no fragmented entries.  The last entry is type RDTYPE_END.
****************************************************************************/

#define RDHSIZE (2*sizeof(unsigned long)+sizeof(unsigned char))

typedef struct RDIRENT { unsigned long  time;
                         unsigned long  size;
                         unsigned char  type;
                         char        name[1]; } RDIRENT;

#define RDTYPE_END      0x00
#define RDTYPE_FILE     0x01
#define RDTYPE_DIR      0x02
#define RDTYPE_SKIP     0x2A

#define NULLP ((char *) 0)


/****************************************************************************
* These structures are used to implement a opendir/readdir mechanism similar
* to that of the normal opendir/reader mechanism in unix.
****************************************************************************/

typedef struct DDLIST {	struct DDLIST *next;
			char          *path;
			RDIRENT  **dep_root;
			int         ref_cnt; } DDLIST;

typedef struct RDIR { DDLIST   *ddp;
		      RDIRENT **dep; } RDIR;

typedef struct rdirent { unsigned long  d_fileno;
			 unsigned short d_reclen;
			 unsigned short d_namlen;
			 char          *d_name; } rdirent;

UBUF     *client_interact();
void     client_intr();
long     inet_addr();

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                