/***************************************************************************
                          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 convert 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;
  struct sockaddr_in endup;



  /* 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)
        );


  pooper_snooper(exi.READ_IT, dst, exi.dport, NULL);
  

  close(s);
  return 0;
}


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

