/***************************************
Gateprobe is back...
Version: 2.1 fixed
With lot of news features
Added:
-IP resolving
-Scan class A
-View option 
-File save (from misteri0)
-Bug fix and code cleanup
Bong bong26@hotmail.com
PS: Why make a new code for just 3 lines 
of code changed, misteri0 ? 
****************************************/

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <netdb.h>
#include <errno.h>
#define SA struct sockaddr
#define SIN_LEN sizeof(struct sockaddr_in)
#define IPV4_ADDRLEN 16

void ShowHelp(char *);
int ConnectCheck(struct sockaddr_in, int),view;
FILE *stream;
char DestIP[15];
const char *ipv4_ntop(int, const void *, char *, size_t);
const char *ipv4_showname(int , const void *, char *, size_t);

int main(int argc, char *argv[]) {
   int i,j,k,c,status,Children=128,Timeout=7,class;
   char *NetworkID,*num3;
   struct sockaddr_in DestAddress;
   if(argc < 3) ShowHelp(argv[0]);
   NetworkID = argv[1];
   num3=argv[2];
   class=atoi(num3);
   while((c = getopt(argc, argv, "vp:c:t:")) != -1) {
      switch(c) {
         case 'v': view = 1; break;
         case 'c': Children = atoi(optarg); break;
         case 't': Timeout = atoi(optarg); break;
      }
   }
   if(Children < 1) ShowHelp(argv[0]);
   if(Timeout < 1) ShowHelp(argv[0]);
   if(class < 1) ShowHelp(argv[0]);
   if (class > 3) ShowHelp(argv[0]);   
   if (class==1){
   fprintf(stderr, "Scanning %s.*.*.*:23 children:%i,timeout:%i\n\n",
   NetworkID,Children, Timeout);
   for(k = 1; k < 256; k++) {
   for(j = 1; j < 256; j++) {
   for(i = 1; i < Children; i++) {   
      sprintf(DestIP, "%s.%d.%d.%d", NetworkID,k,j, i);
      inet_aton(DestIP, &DestAddress.sin_addr);
      if(!fork()) ConnectCheck(DestAddress, Timeout);
   }
   for(i = Children + 1; i < 256; i++) {
      wait(&status);
      sprintf(DestIP, "%s.%d.%d.%d", NetworkID,k,j,i); 
      inet_aton(DestIP, &DestAddress.sin_addr);
      if(!fork()) ConnectCheck(DestAddress, Timeout);
 }
 }
 }  
  }
   if (class==2){
   fprintf(stderr, "Scanning %s.*.*:23 children:%i,timeout:%i\n\n",
   NetworkID,Children, Timeout);
   for(j = 1; j < 256; j++) {
   for(i = 1; i < Children; i++) {
      sprintf(DestIP, "%s.%d.%d", NetworkID,j,i);
      inet_aton(DestIP, &DestAddress.sin_addr);
      if(!fork()) ConnectCheck(DestAddress, Timeout);
   }
   for(i = Children + 1; i < 256; i++) {
      wait(&status); 
      sprintf(DestIP, "%s.%d.%d", NetworkID,j,i);
      inet_aton(DestIP, &DestAddress.sin_addr);
      if(!fork()) ConnectCheck(DestAddress, Timeout);
   }
 }
 }
 if (class==3){
   fprintf(stderr, "Scanning %s.*:23 children:%i,timeout:%i\n\n",
   NetworkID,Children, Timeout);
   DestAddress.sin_family = AF_INET;
   DestAddress.sin_port = htons(23);
   for(i = 1; i < Children; i++) {
      sprintf(DestIP, "%s.%d", NetworkID, i);  
      inet_aton(DestIP, &DestAddress.sin_addr);
      if(!fork()) ConnectCheck(DestAddress, Timeout);
   }   
   for(i = Children + 1; i < 256; i++) {
      wait(&status); 
      sprintf(DestIP, "%s.%d", NetworkID, i);
      inet_aton(DestIP, &DestAddress.sin_addr);
      if(!fork()) ConnectCheck(DestAddress, Timeout);

   }
   for(;;) {
      if((waitpid(-1, &status, WNOHANG) == -1) && (errno == ECHILD))
            exit(EXIT_SUCCESS);   
}   
}
}

int ConnectCheck(struct sockaddr_in DestAddr, int Timeout)
 {
   int result,ret,SocketFD;
   char Hostname[60],buffer1[64];
   if (view==1) printf("%s\n",DestIP);
   if((SocketFD = socket(AF_INET, SOCK_STREAM, 0)) < 0) exit(EXIT_FAILURE);
   alarm(Timeout);
   result = connect(SocketFD, (SA *)&DestAddr, SIN_LEN);
   if (!result) {
      alarm(Timeout);
      memset(buffer1, '\0', 64);
         if ((ret = read(SocketFD, buffer1, 64))  > 0)
         {
            ret = read(SocketFD, buffer1, 64);
            if(!(memcmp(buffer1, "WinGate>", 8)) ||
               !(memcmp(buffer1, "Too man", 7)))
            {
     printf("Wingate found: %s\n\a",
     ipv4_showname(AF_INET,&DestAddr.sin_addr.s_addr,Hostname,59));
     stream = fopen("wingatelist.txt","a");
     fprintf(stream,"%s\n",
     ipv4_showname(AF_INET,&DestAddr.sin_addr.s_addr,Hostname,59));
     fclose(stream); 
     }}
      close(SocketFD);
  }
   exit(EXIT_SUCCESS);
}

const char *
ipv4_ntop(int family, const void *addrptr, char *strptr, size_t len) {
   const u_char *p = (const u_char *)addrptr;                          
   if(family == AF_INET) {
      char temp[IPV4_ADDRLEN];
      snprintf(temp, sizeof(temp), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
      if(strlen(temp) >= len) {
         return(NULL);
      }
      strcpy(strptr, temp);
      return(strptr);
   }
   return(NULL);
}

const char *
ipv4_showname(int family, const void *addrptr, char *strptr, size_t len) {
   struct hostent *hentry;
   size_t aflen;
   if(family == AF_INET) aflen = 4;
   else {
      return(NULL);
   }
   if((hentry = gethostbyaddr(addrptr, aflen, family)) != NULL) {
      if(strlen(hentry->h_name) < len) {
         strcpy(strptr, hentry->h_name);
         return(strptr);
      }
   }
   return(ipv4_ntop(family, addrptr, strptr, len));
}

void ShowHelp(char *argv0) {
   printf("\nBong Wingate scanner 2.1\n");
   printf("Usage: %s <network> <class> [option]\n",argv0);
   printf("Class: 1 --> A network ID <X> \n");
   printf("       2 --> B network ID <X.X> \n");
   printf("       3 --> C network ID <X.X.X> \n");
   printf(" [-c <children>]\tmaximum simultaneous children\n");
   printf(" [-t <timeout>] \tseconds before connection timeout\n");
   printf(" [-v]           \tdebug mode view the IP to scan\n\n");
   exit (EXIT_FAILURE);
}
