/***************************************************************************
                          spells.c  -  more spells
                             -------------------
    begin                : Sat Sep 22 2001
    copyright            : (C) 2001 by Josiah Zayner
    email                : phric@legions.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "wand.h"

struct in_addr wherefromto(const char *herefrom)
{
  struct in_addr addr;
  struct hostent *host;

  memset(&addr, '\0', sizeof(struct in_addr));


  if((host = gethostbyname(herefrom)) == NULL)
    { prterr("wheretofrom:gethostbyname"); }

  memcpy(&addr, host->h_addr_list[0], sizeof(struct in_addr));


  return addr;
}



/* standard Internet Protocol checksum*/
unsigned short in_cksum(unsigned short *addr, int len)
{
  unsigned short answer;
  unsigned int sum = 0;
  unsigned short oddbyte = 0;

  /*
   * Our algorithm is simple, using a 32 bit accumulator (sum), we add
   * sequential 16 bit words to it, and at the end, fold back all the
   * carry bits from the top 16 bits into the lower 16 bits.
   */

  while (len > 1)
  {
    sum += *addr++;
    len -= 2;
  }

  /* mop up an odd byte, if necessary */
  if (len == 1)
  {
    *((unsigned char *)&oddbyte) = *(unsigned char *)addr ;
    sum += oddbyte;
  }

  /* add back carry outs from top 16 bits to low 16 bits */
  sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
  sum += (sum >> 16); /* add carry */
  answer = ~sum; /* truncate to 16 bits */
  return answer;
}


/* clear and allocate memory */
void *clalloc(int bytes)
{
  void *ret;
  if((ret = malloc(bytes)) == NULL)
  {
    fprintf(stderr,"Cannot allocate %d bytes memory!", bytes);
    exit(-1);
  }
  memset(ret,'\0', bytes);

  return ret;
}


int pooper_snooper(int tosnooporpoop, struct in_addr dst, int dport, void *gtkwid)
{
   int snoop, recve = 0, recvf = 0, tries = 1;
   char *buff = clalloc(65535);
   struct looky looky;
   struct timeval tim;
   fd_set r;
   struct sockaddr sn;
   int sizer = sizeof(struct sockaddr);


/* right now we have no way to check if the src address is
    our address so should we snoop the packet? Make sure it
    doesn't snoop by default
 */
 if(tosnooporpoop) {

  /* open second socket for snooping them packets */
  if((snoop = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ALL))) == -1)
  {
    perror("snoop socket");
    exit(snoop);
  }
  memset(&looky, '\0', sizeof(struct looky));
  memset(&sn,'\0', sizeof(struct sockaddr));

  FD_ZERO(&r);
  FD_SET(snoop, &r);

  tim.tv_sec = 5;
  tim.tv_usec = 0;
  fcntl(snoop, F_SETFL, O_NONBLOCK);


  while(1) {
  recve = select(snoop + 1, &r, NULL, NULL, &tim);

  if(recve) break;
  else if(recve == -1)
     perror("select");
  else tries++;

  if(tries == 3)
    exit(-1);

  }

  while(1)
  {
    if((recvf = recvfrom(snoop, buff, 65535, 0, &sn, &sizer)) < 0)
    {
      switch(recvf)
      {
        case EAGAIN:
          if((recvf = recvfrom(snoop, buff, 65535, 0, &sn, &sizer)) < 0)
          {
             prterr("recvfrom EAGAIN"); return 0;
          }

        break;

        case -1:

          prterr("recvfrom: Resource Temporarily Unavailable"); return 0;
        break;
      }
    }


  /* ETH_P_ALL grabs ethernet header which is 14 bytes
     so we skip it!
  */
  looky.iph = (struct ip *)&buff[14];

 /* make sure they are coming from where we sent them */

 if(strstr(inet_ntoa(dst), inet_ntoa(looky.iph->ip_src)))
 {
  /* check if it is TCP */
  if(looky.iph->ip_p == 6)
  {
    looky.tcph = (struct tcphdr *)&buff[14 + sizeof(struct ip)];

    if(dport == looky.tcph->th_sport)
    {
      make_tcp_scroll(looky.tcph, tosnooporpoop, gtkwid);
      break;
    }

  }
  /* UDP blah blah, I need better checking to make sure it's
     the right packet so don't get pissed at mE!
  */
  else if(looky.iph->ip_p == 17)
  {
    looky.udph = (struct udphdr *)&buff[14 + sizeof(struct ip)];
    if(dport == looky.udph->uh_sport)
    {
   /*   make_udp_scroll(looky.udph, tosnooporpoop, gtkwid); */
    }

  }

 } /* if(strstr */
 }/*while(1) */


   close(snoop);
 } /* if(READ_IT) */

 return 0;

}


char *TCP_FLAGS(u_char flags)
{
    char *flagswho = clalloc(50);

    if(flags & TH_FIN) { strcat(flagswho, "FIN "); }
    if(flags & TH_SYN) { strcat(flagswho, "SYN "); }
    if(flags & TH_RST) { strcat(flagswho, "RST "); }
    if(flags & TH_PUSH) { strcat(flagswho, "PSH "); }
    if(flags & TH_ACK) { strcat(flagswho, "ACK "); }
    if(flags & TH_URG) { strcat(flagswho, "URG "); }
    if(flags & 0) { strcat(flagswho, "No Flags"); }


 return flagswho;
}
