#include "tcpip.h"

char *servport(int port) {
 struct servent *wewtz;
 char *wutez;

 if ((wewtz = getservbyport(htons(port), "tcp"))==NULL) {
   sprintf(wutez, "%d", port);
   return wutez;
 } else
   return wewtz->s_name;
}

void ssyn(int sendsock, u_long srcaddr, u_long dstaddr, u_short srcport, 
	u_short dstport, u_long seq)
{
  char *pack, *tpack;
  int sent;
  struct sockaddr_in stuffz;

  tpack = create_tcp(srcaddr, dstaddr, htons(srcport), htons(dstport), 
	seq, 0, TH_SYN, NULL, 0);
  pack  = create_ip (srcaddr, dstaddr, IPPROTO_TCP, 75, 1, tpack, 20);
  stuffz.sin_family      = AF_INET;
  stuffz.sin_port        = htons(dstport);
  stuffz.sin_addr.s_addr = dstaddr;
  sent  = sendto(sendsock, pack, 40, 0, (struct sockaddr *)&stuffz, 
            sizeof(stuffz));
  if (sent != 40) { perror("sending SYN"); exit(-1); }
}

void srst(int sendsock, u_long srcaddr, u_long dstaddr, u_short srcport, 
	u_short dstport, u_long seq)
{
  char *pack, *tpack;
  int sent;
  struct sockaddr_in stuffz;

  tpack = create_tcp(srcaddr, dstaddr, htons(srcport), htons(dstport), 
	seq, 0, TH_RST, NULL, 0);
  pack  = create_ip (srcaddr, dstaddr, IPPROTO_TCP, 75, 1,
            tpack, 20);
  stuffz.sin_family      = AF_INET;
  stuffz.sin_port        = htons(dstport);
  stuffz.sin_addr.s_addr = dstaddr;
  sent  = sendto(sendsock, pack, 40, 0, (struct sockaddr *)&stuffz, 
            sizeof(stuffz));
  if (sent != 40) { perror("sending RST"); exit(-1); }
}

main (int c, char *v[])
{
  int ssock, lsock, pid;
  struct hostent *hent;
  struct servent *srvent;
  u_long us, them;
  u_short sport, eport;
  u_short skrap;
  char mahname[80], *buggz, iphh[20], tcphh[20];
  struct tcphdr *tcphead;
  struct iphdr *iphead;

  if (c!=4) {
    printf("usage: %s <host> <start port> <end port>\n", v[0]);
    exit(-1);
  }
  gethostname(mahname, 79);
  if ((hent = gethostbyname(mahname)) == NULL) {
    printf("couldn't get my hostname!@#\n");
    exit(-1);
  }
  bcopy(hent->h_addr, (char *)&us, hent->h_length);
  if ((hent = gethostbyname(v[1]))!=NULL)
    bcopy(hent->h_addr, (char *)&them, hent->h_length);
  else {
    printf("could not resolve: %s\n", v[1]);
    exit(-1);
  }
  if ((sport=atoi(v[2]))==0) {
    printf("you can't use %s as a starting port..\n", v[2]);
    exit(-1);
  }
  if ((eport=atoi(v[3]))==0) {
    printf("you can't use %s as an ending port..\n", v[3]);
    exit(-1);
  }
  ssock = socket(AF_INET, SOCK_RAW, 255);
  if (ssock == -1) { perror("getting send socket"); exit(-1); }
  lsock = socket(AF_INET, SOCK_RAW, 6);
  if (lsock == -1) { perror("getting listen socket"); exit(-1); }
  printf("Active ports on %s between: %d and %d:\n", v[1], sport, eport);
  pid = getpid();
  for (skrap=sport;skrap<eport+1; skrap++) {
    ssyn(ssock, us, them, pid+skrap, skrap, (skrap * 1000));
    while ((ntohs(tcphead->th_dport) != pid+skrap) ||
      (ntohs(tcphead->th_sport) != skrap) ||
      (them != iphead->saddr) || (us != iphead->daddr)) {
        usleep(100);
        buggz = read_tcpip();
	bcopy(buggz, &iphh, 20);
	bcopy((buggz + 20), &tcphh, 20);
	iphead  = (struct iphdr  *)iphh;
	tcphead = (struct tcphdr *)tcphh;
    }
    if ((iphead->saddr == them) && (iphead->daddr == us) &&
        (ntohl(tcphead->th_ack) == ((skrap * 1000 )+ 1))) {
      if (tcphead->th_flags & TH_SYN) {
         printf("%s.%s\n", inet_ntoa(them), servport(skrap));
         srst(ssock, us, them, pid+skrap, skrap, ((skrap * 1000) + 1));
      }
    }
  }
}
