/***************************************************************************
                          sorcery.c  -  for sorcery and GUI--
                             -------------------
    begin                : Tue Sep 11 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"



void ip_sorcery(struct ip *ip_sorc,
                struct in_addr source,
                struct in_addr dest,
                int proto,
                unsigned int hl,
                unsigned int ver,
                unsigned char tos,
                unsigned short len,
                unsigned short id,
                unsigned char ttl,
                int off
               )
{
  ip_sorc->ip_hl = hl;
  ip_sorc->ip_v = ver;
  ip_sorc->ip_tos = tos;
  ip_sorc->ip_len = len;
  ip_sorc->ip_id = id;
  ip_sorc->ip_ttl = ttl;
  ip_sorc->ip_p = proto;
  ip_sorc->ip_off = off;
  ip_sorc->ip_src = source;
  ip_sorc->ip_dst = dest;

}

int mix_ipoption(unsigned int opt,
                 unsigned int optlen,
                 unsigned int totlen,
                 struct ip *ip_p,
                 char *pack
                )
{
  static int oper;
  /* optlen = x8bits  we need to ocnvert to x32bits */
  if(optlen % 4){ oper = (optlen / 4) + (optlen % 4); }
  else { oper = (optlen / 4); }
  ip_p->ip_len = totlen;
  ip_p->ip_hl = 5 + oper; /* hl is in x32 bits */
  memcpy(pack, ip_p, S_IP);
  memcpy(pack + S_IP, &opt, (oper * 4));

  return (oper * 4);
}

int packet_sorcery(char *pack,
                   struct extra_ingredients exi,
                   struct in_addr daddr,
                   struct in_addr saddr
                  )
{

  static int a = 0;

  for(; exi.num > a; a++)
  {
    if(cast_spell(pack, exi, daddr, saddr) == -1)
    {
       perror("sendto");
       return -1;
    }
  }
  return 0;
}

int cast_spell(char *envelope,
               struct extra_ingredients exi,
               struct in_addr dst,
               struct in_addr src
              )
{
  int s, one = 1, recve, snoop, tries = 1;
  char *buff = clalloc(65535);
  struct sockaddr_in endup;
  struct sockaddr sn;
  struct looky looky;
  struct timeval tim;
  fd_set r;
  int sizer = sizeof(struct sockaddr);
 


  /* open a raw socket */
  if((s = socket(PF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
  {
    perror("socket");
    exit(s);
  }

  /* set socket options at IP level, so we can create our own IP header */
  if((setsockopt(s, SOL_IP, IP_HDRINCL, &one, sizeof(one))) == -1)
  {
    perror("setsockopt");
    exit(-1);
  }

  /* we need to set this socket option to send and recv broadcasts
     It is supposed to only be datagram broadcast but should I
     enforce this and even so I need to figure a way to extract
     the header values from the memory segment
  */
  if(src.s_addr & 0xff000000 || dst.s_addr & 0xff000000)
    {
      if((setsockopt(s, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one))) == -1)
        {
          perror("setsockopt");
          exit(-1);
        }
    }

  /* fill in sockaddr struct bLAH! */
  memset(&endup, '\0', sizeof(struct sockaddr_in));
  endup.sin_family = PF_INET;
  endup.sin_port = exi.dport;
  endup.sin_addr = dst;

 /* send packet woohooo! */
  sendto(s,
         envelope,
         exi.pack_sz,
         0,
         (struct sockaddr *)&endup,
         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(exi.READ_IT) {
 
  /* open second socket for snooping them packets */
  if((snoop = socket(PF_INET, SOCK_RAW, 0)) == -1)
  {
    perror("snoop socket");
    exit(snoop);
  }
  memset(&looky, '\0', sizeof(struct looky));
  memset(&sn,'\0', sizeof(struct sockaddr));
  memset(buff,'\0', 65535);
  FD_ZERO(&r);
  FD_SET(snoop, &r);

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

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

  if(FD_ISSET(snoop, &r)) break;
  else tries++;

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

  }
 if(recve)
 {
  while(1)
  {
    if((recve = recvfrom(snoop, buff, 65535, 0, &sn, &sizer)) < 0)
    {
      switch(recve)
      {
        case EAGAIN:
          if((recve = recvfrom(snoop, buff, 65535, 0, &sn, &sizer)) < 0)
          {
             perror("recvfrom EAGAIN"); exit(-1);
          }

        break;

        default:
          perror("recvfrom"); exit(-1);
        break;
      }
    }
  /* for printing packet in hex

  for(x =14; x< recve; x++) {

   printf(
         "%2x"
         ,ntohs((u_short)buff[x])
         );


    printf(" ");
  }
  */

  /* 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(exi.dport == looky.tcph->th_sport)
    {
      make_tcp_scroll(looky.tcph, exi.READ_IT);
      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(exi.dport == looky.udph->uh_sport)
    {
      make_udp_scroll(looky.udph, exi.READ_IT);
    }

  }

 } /* if(inet */
 }/*while(1) */
}
  close(snoop);
 } /* if(READ_IT) */

  close(s);
  return 0;
}


void prterr(char *message)
{ fprintf(stderr, message); }



syntax highlighted by Code2HTML, v. 0.9.1