/*
 *	$Header: /homes/facility/long/src/severed_fingerd/RCS/probe_tcp_ports.c,v 1.5 1996/04/17 18:48:05 long Exp $
 *
 *	probe_tcp_ports [-dhv] [hostname [hostname ...] ]
 *
 *	H. Morrow Long, Manager of Development, Yale U CS Computing Facility
 * 	P. O. Box 208285,			INET: Long-Morrow@CS.Yale.EDU
 * 	New Haven, CT  06520-8285		BITNET: Long-Morrow@YaleCS
 * 	(203)-432-{1248,1254}			FAX:	(203)-432-0593
 *
 *	$Log: probe_tcp_ports.c,v $
 * Revision 1.5  1996/04/17  18:48:05  long
 * Added starting port ( -s# ) and ending port ( -e# )
 * command line options:
 *     probe_tcp_ports -s1000 -e2000 hostname
 *
 * Revision 1.4  94/07/22  15:32:55  long
 * Added call to htons() for Port numbers passed to getservbyport()
 * calls - change dated Apr 14 94.
 * 
 * Revision 1.3  93/10/01  12:54:46  long
 * Added RCS Keywords.
 * 
 *
 */


#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define	RETURN_ERR	-1
#define	RETURN_FAIL	0
#define	RETURN_SUCCESS	1

int             StartPort = 0;		/* default to MINPORT */
int             EndPort = 65536;	/* default to MAXPORT */

int             Debug;
int             Hack;
int             Verbose;

main(ArgC, ArgV)
	int             ArgC;
	char          **ArgV;
{
	int             Index;
	int             SubIndex;
	int		Cont_Options_Proc;		/* Continue Options Processing */

	for (Index = 1; (Index < ArgC) && (ArgV[Index][0] == '-'); Index++)
	    {
	    Cont_Options_Proc++;
	    for (SubIndex = 1; Cont_Options_Proc && ArgV[Index][SubIndex]; SubIndex++)
		switch (ArgV[Index][SubIndex])
		{
		case 'd':
			Debug++;
			break;
		case 'h':
			Hack++;
			break;
		case 'v':
			Verbose++;
			break;
		case 's':
			StartPort = atoi( &(ArgV[Index][SubIndex+1] ) );
			Cont_Options_Proc = 0;
			break;
		case 'e':
			EndPort = atoi( &(ArgV[Index][SubIndex+1] ) );
			Cont_Options_Proc = 0;
			break;
		default:
			(void) fprintf(stderr,
		"Usage: probe_tcp_ports [-dhv] [hostname [hostname ...] ]\n");
			exit(1);
		}
	    }

	for (; Index < ArgC; Index++)
		(void) Probe_TCP_Ports(ArgV[Index]);
	exit(0);
}

Probe_TCP_Ports(Name)
	char           *Name;
{
	unsigned        Port;
	char           *Host;
	struct hostent *HostEntryPointer;
	struct sockaddr_in SocketInetAddr;
	struct hostent  TargetHost;
	struct in_addr  TargetHostAddr;
	char           *AddressList[1];
	char            NameBuffer[128];

	extern int      inet_addr();
	extern char    *rindex();

	if (Name == NULL)
		return (RETURN_FAIL);
	Host = Name;
	if (Host == NULL)
		return (RETURN_FAIL);
	HostEntryPointer = gethostbyname(Host);
	if (HostEntryPointer == NULL)
		{
		TargetHostAddr.s_addr = inet_addr(Host);
		if (TargetHostAddr.s_addr == -1)
			{
			(void) printf("unknown host: %s\n", Host);
			return (RETURN_FAIL);
			}
		(void) strcpy(NameBuffer, Host);
		TargetHost.h_name = NameBuffer;
		TargetHost.h_addr_list = AddressList, TargetHost.h_addr = 
			(char *) &TargetHostAddr;
		TargetHost.h_length = sizeof(struct in_addr);
		TargetHost.h_addrtype = AF_INET;
		TargetHost.h_aliases = 0;
		HostEntryPointer = &TargetHost;
		}
	SocketInetAddr.sin_family = HostEntryPointer->h_addrtype;
	bcopy(HostEntryPointer->h_addr, (char *) &SocketInetAddr.sin_addr,
		HostEntryPointer->h_length);


	for (Port = StartPort; Port < EndPort; Port++)
		(void) Probe_TCP_Port(Port, HostEntryPointer, SocketInetAddr);
	return (RETURN_SUCCESS);
}

Probe_TCP_Port(Port, HostEntryPointer, SocketInetAddr)
	unsigned        Port;
	struct hostent *HostEntryPointer;
	struct sockaddr_in SocketInetAddr;
{
	char            Buffer[BUFSIZ];
	int             SocketDescriptor;
	struct servent *ServiceEntryPointer;


	SocketInetAddr.sin_port = htons(Port);
	SocketDescriptor = socket(AF_INET, SOCK_STREAM, 6);
	if (SocketDescriptor < 0)
		{
		perror("socket");
		return (RETURN_ERR);
		}
	if (Verbose)
		{
		(void) printf("Host %s, Port %d ", HostEntryPointer->h_name,
			      Port);
		if ((ServiceEntryPointer = getservbyport(htons(Port), "tcp")) !=
		    (struct servent *) NULL)
			(void) printf(" (\"%s\" service) ",
				      ServiceEntryPointer->s_name);
		(void) printf("connection ... ");
		(void) fflush(stdout);
		}
	if (connect(SocketDescriptor, (char *) &SocketInetAddr,
		    sizeof(SocketInetAddr)) < 0)
		{
		if (Verbose)
			(void) printf("NOT open.\n");
		if (Debug)
			perror("connect");
		}
	else
		{
		if (!Verbose)
			{
			(void) printf("Host %s, Port %d ",
				      HostEntryPointer->h_name, Port);
			if ((ServiceEntryPointer = getservbyport(htons(Port),"tcp")) !=
			    (struct servent *) NULL)
				(void) printf(" (\"%s\" service) ",
					      ServiceEntryPointer->s_name);
			(void) printf("connection ... ");
			(void) fflush(stdout);
			}
		(void) printf("open.\n");
		if (Hack)
			{
			(void) sprintf(Buffer, "/usr/ucb/telnet %s %d",
				       HostEntryPointer->h_name, Port);
			(void) system(Buffer);
			}
		}

	(void) close(SocketDescriptor);
	return (RETURN_SUCCESS);
}
