/* ******************************************************************** */
/*  w00w00 functions for spoofing UDP                                   */
/*  ------------------------------------------------------------------- */
/*  w00w00 Security Development (WSD)					*/ 
/*  Email: w00w00@janova.org or WSD@janova.org				*/
/*  Sites: http://www.janova.org, ftp://ftp.janova.org/pub              */
/* ******************************************************************** */
  
#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <memory.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "ip.h"
#include "udp.h"

#define IPHDRSIZE     sizeof(struct iphdr)
#define UDPHDRSIZE    sizeof(struct udphdr)

/*****************************************************************************/
/*
 * in_cksum --
 *  Checksum routine for Internet Protocol family headers (C Version)
 */
/*****************************************************************************/

unsigned short in_cksum(addr, len)
    u_short *addr;
    int len;
{
    register int nleft = len;
    register u_short *w = addr;
    register int sum = 0;
    u_short answer = 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 (nleft > 1)  {
        sum += *w++;
        nleft -= 2;
    }
 
    /* mop up an odd byte, if necessary */
    if (nleft == 1) {
        *(u_char *)(&answer) = *(u_char *)w ;
        sum += answer;
    }
 
    /* 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);

}



int udp_send(s, saddr, daddr, sport, dport, datagram, datasize)      
  int s;
  unsigned long  saddr;
  unsigned long  daddr;
  unsigned short sport;
  unsigned short dport;
  char     *datagram;
  unsigned datasize;
{

  int x;

  unsigned char *data;
  unsigned char packet[4024];
 
  struct iphdr  *ip;
  struct udphdr *udp;
  struct sockaddr_in sin;


  ip   = (struct iphdr  *)packet; 
  udp  = (struct udphdr *)(packet+IPHDRSIZE);
  data = (unsigned char *)(packet+IPHDRSIZE+UDPHDRSIZE);
       
  memset(packet, 0, sizeof(packet));

  udp->source = htons(sport); 
  udp->dest   = htons(dport);
  udp->len    = htons(UDPHDRSIZE+datasize);
  udp->check  = 0;         

  memcpy(data, datagram, datasize);        
  memset(packet, 0, IPHDRSIZE);
        
  ip->saddr.s_addr  = saddr;
  ip->daddr.s_addr  = daddr;
  ip->version  = 4;
  ip->ihl      = 5;
  ip->ttl      = 245;
  ip->id       = random() % 5985 + 1; 
  ip->protocol = IPPROTO_UDP;
  ip->tot_len  = htons(IPHDRSIZE + UDPHDRSIZE + datasize);
  ip->check    = 0;
  ip->check    = in_cksum((char *)packet, IPHDRSIZE);
                                                                        
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr=daddr;
  sin.sin_port = udp->dest;
	
  x = sendto(s, packet, IPHDRSIZE+UDPHDRSIZE+datasize, 0, 
        		(struct sockaddr*)&sin, sizeof(struct sockaddr));

  return(x);
}



/*****************************************************************************/
/*                     RECV PAKET                                            */
/* get_pkt(socket, *buffer, size of the buffer);                             */
/*****************************************************************************/

int get_pkt(s, data, size)
  int s;
  unsigned char *data;
  int size;
{
 struct sockaddr_in sin;
 int len, resu;

 len = sizeof(sin);
 resu = recvfrom(s, data, size, 0, (struct sockaddr *)&sin, &len);

 return resu;
}        

