int readTimeoutBlocked(int fd,PVStr(buf),int siz,int timeout) { int omask,nmask; int rcc; int serno; int serrno; alertVStr(buf,siz); rcc = -1; omask = sigblock(sigmask(SIGCHLD)); serno = ++readSERNO; if( 0 < PollIn(fd,timeout) ){ errno = 0; rcc = read(fd,(char*)buf,QVSSize(buf,siz)); serrno = errno; if( rcc != siz ){ sv1log("##ERROR: readTimeoutB insufficient read %d/%d (%d)%X\n", rcc,siz,errno,sigblock(0)); } errno = serrno; } if( serno != readSERNO ){ sv1log("##ERROR: readTimeoutB broken %d/%d (%d)%X\n", serno,readSERNO,errno,sigblock(0)); sleep(10); } nmask = sigsetmask(omask); return rcc; }
int IMAP_STARTTLS_withCL(Connection *Conn,FILE *fc,FILE *tc,PCStr(tag),PCStr(com),PCStr(arg)){ if( willSTLS_CL(Conn) == 0 ) return 0; if( strcaseeq(com,"STARTTLS") ){ int fcl; SSLstart = 1; fcl = insertTLS_CL(Conn,ToC,ToS); SSLstart = 0; if( 0 <= fcl ){ fprintf(tc,"%s OK Begin TLS negotiation\r\n",tag); fflush(tc); PollIn(fcl,TIMEOUT_STLS); dup2(fcl,fileno(tc)); dup2(fcl,fileno(fc)); close(fcl); }else{ fprintf(tc,"%s BAD\r\n",tag); } return 1; } return 0; }
int SMTP_STARTTLS_withCL(Connection *Conn,FILE *fc,FILE *tc){ CStr(stat,1024); int fcl; if( willSTLS_CL(Conn) ){ SSLstart = 1; fcl = insertTLS_CL(Conn,FromC,ToS); SSLstart = 0; if( 0 <= fcl ){ lfprintf(NULL,tc,"220 Ready to start TLS\r\n"); fflush(tc); fflush(fc); /* wait the completion of SSL negotiation and * initialization in SSLway thread for safety ... */ PollIn(fcl,TIMEOUT_STLS); dup2(fcl,fileno(tc)); dup2(fcl,fileno(fc)); close(fcl); return 1; } } lfprintf(NULL,tc,"454 A Don't start TLS\r\n"); fflush(tc); return 0; }
int POP_STARTTLS_withCL(Connection *Conn,FILE *fc,FILE *tc,PCStr(com),PCStr(arg)){ /* if( strcaseeq(com,"CAPA") ){ if( needSTLS(Conn) ){ fputs("+OK Capability list follows\r\n",tc); fputs("STLS\r\n",tc); fputs(".\r\n",tc); return 1; } } */ if( strcaseeq(com,"STLS") ){ if( willSTLS_CL(Conn) ){ int fcl; SSLstart = 1; fcl = insertTLS_CL(Conn,ToC,ToS); SSLstart = 0; if( 0 <= fcl ){ fputs("+OK\r\n",tc); fflush(tc); PollIn(fcl,TIMEOUT_STLS); dup2(fcl,fileno(tc)); dup2(fcl,fileno(fc)); close(fcl); }else{ fputs("-ERR\r\n",tc); } return 1; } } return 0; }
static int concat(RelayCtrl *relayCtrl,int s1,int nx,int tl,int rcode,int nready){ int oready = 0; int timeout; double St; St = Time(); if( 0 < rcode ) oready = inputReady(s1,NULL); else oready = 0; if( 0 < rcode ){ if( oready ){ syslog_DEBUG("## relaysx[%d]: concat+%d 0.000 %d /%d\n", s1,nx+1,tl,nready); return 1; } timeout = RELAY_concat; if( 0 < timeout && 0 < PollIn(s1,timeout) ){ syslog_DEBUG("## relaysx[%d]: concat+%d %.3f %d /%d\n", s1,nx+1,Time()-St,tl,nready); return 2; } } if( 0 < nx ){ syslog_DEBUG("## relaysx[%d]: concat*%d %.3f %d /%d %d\n", s1,nx,Time()-St,tl,nready,rcode); } return 0; }
void getCFI_IDENT(Connection *Conn,int cid[2],int sv){ double St = Time(); IStr(ids,1024); IStr(ident,128); int rcc; int nready; putenv("CFI_IDENT=-1"); /* if( PollIn(cid[0],1000) ){ } 9.9.4 */ errno = 0; nready = PollIn(cid[0],1000); if( nready <= 0 || errno != 0 ){ putfLog("getCFI_IDENT() nready=%d errno=%d",nready,errno); } if( 0 < nready ){ rcc = read(cid[0],ids,sizeof(ids)-1); if( 0 < rcc ){ setVStrEnd(ids,rcc); getFieldValue2(ids,"Ident",AVStr(ident),sizeof(ident)); sv1log("%s-Ident: %.3f %.3f %d <%s>\n",sv?"SV":"CL", Time()-ServConnTime,Time()-St,rcc,ident); } } close(cid[0]); close(cid[1]); }
static int isSSLrecord(unsigned PCStr(up),PCStr(spack),int rcc,int fd){ int sslv = 0; int len; int nready = 0; if( 0x14 <= up[0] && up[0] <= 0x17 && up[1] == 3 ){ len = 5 + ((up[3] <<8 ) | up[4]); sslv = 3; }else{ if( up[0] & 0x80 ){ len = 2 + (((up[0] & 0x7F) << 8) | up[1]); }else{ len = 3 + (((up[0] & 0x3F) << 8) | up[1]); } sslv = 2; } if( len <= rcc ){ syslog_DEBUG("# SSL record head[%s] SSL%d %d/%d\n", spack,sslv,rcc,len); }else{ if( PollIn(fd,1000) <= 0 ){ sslv = -sslv; } if( isupper(up[0]) && isupper(up[1]) && isupper(up[2]) ){ /* maybe bair HTTP, should be sslv == 0 ? */ syslog_DEBUG("# non-SSL record [%s] SSL%d %d%c/%d\n", spack,sslv,rcc,0<nready?'+':'?',len); }else syslog_ERROR("# SSL record head[%s] SSL%d %d%c/%d\n", spack,sslv,rcc,0<nready?'+':'?',len); } return sslv; }
int forkSUDO(int ac,const char *av[],Connection *Conn,int csock){ CStr(title,128); CStr(buf,1024); sprintf(title,"SUDO-%d",getppid()); ProcTitle(Conn,"%s",title); if( PollIn(csock,30*1000) == 0 ){ sv0log("--SU timeout to start\n"); return -1; } if( read(csock,portSUDO,sizeof(portSUDO)) < sizeof(portSUDO) ){ sv0log("--SU EOF on start\n"); return -1; } sprintf(title,"SUDO-%s",portSUDO); ProcTitle(Conn,"%s",title); passSUDO = getRand64(); IGNRETP write(csock,&passSUDO,sizeof(passSUDO)); iLog("--- being SUDO server"); isPrivateSUDO = csock; return 0; }
int sftpIsAlive(int fd){ double St = Time(); int rdy; int rcc; IStr(buf,128); refQStr(bp,buf); rdy = PollIn(fd,1000); sv1log("--rdy=%d alv=%d (%.3f)\n",rdy,IsAlive(fd),Time()-St); if( 0 < rdy ){ rcc = recvPeekTIMEOUT(fd,AVStr(buf),sizeof(buf)-1); if( 0 < rcc ){ setVStrEnd(buf,rcc); if( bp = strchr(buf,'\n') ) clearVStr(bp); } } sv1log("---- SFTPCC Alive? [%d] rdy=%d rcc=%d alv=%d [%s]\n", fd,rdy,rcc,IsAlive(fd),0<rcc?buf:""); if( 0 < IsAlive(fd) ){ return 1; } return 0; }
static void do_forward(Connection *Conn,PCStr(lport),PCStr(peername),int shared,int svsock,int priority,int fromC,int toC) { int cls,svs; CStr(host,MaxHostNameLen); int port; CStr(opt,256); CStr(clntname,1024); CStr(servname,1024); CStr(sockname,1024); if( svsock < 0 ){ SockPrintf(toC,"%s %d no socket to accept\r\n",VER,NO_ACCEPT); return; } SockPrintf(toC,"%s %d forwarding start.\r\n",VER,OK_FORWARD1); opt[0] = 0; Xsscanf(peername,"%[^:]:%d %s",AVStr(host),&port,AVStr(opt)); for(;;){ cls = do_accept(lport,"",shared,priority,fromC,toC); if( cls < 0 ){ if( 0 < PollIn(fromC,1) ){ if( intcom("",fromC,toC,NULL,NULL) == 0 ) continue; else break; } SockPrintf(toC,"%s %d could not accept at %s\r\n", VER,NO_ACCEPT,lport); break; } getpairName(cls,AVStr(sockname),AVStr(clntname)); SockPrintf(toC,"%s %d accepted %s %s\r\n",VER,OK_ACCEPT, sockname,clntname); svs = Socket1("VSAPdata",NEWSOCK,VStrANYPORT,host,port, 0,NULL,0); if( svs < 0 ){ SockPrintf(toC,"%s %d could not connect to %s\r\n", VER,NO_CONNECT,peername); break; }else{ if( strstr(opt,"TRACE") ){ getpairName(svs,AVStr(sockname),AVStr(servname)); SockPrintf(cls,"%s %d %s %s connected.\r\n", VER,OK_CONNECT,sockname,servname); SockPrintf(svs,"%s %d %s %s accepted.\r\n", VER,OK_ACCEPT,sockname,clntname); } relay2_cntl(60*1000,cls,svs,svs,cls,fromC,toC,(IFUNCP)intcom,0); close(svs); SockPrintf(toC,"%s %d relay done.\r\n",VER,OK_RELAYED); } close(cls); } SockPrintf(toC,"%s %d forwarding done.\r\n",VER,OK_FORWARD2); }
/* 9.9.2 timeout of FTPS data-SSL in non/half negotiatiated */ static int FTPS_detect_dataSSL(Connection *Conn,int cldata){ double Timeout; double Start,Elp; int timeout; int nready; int pbsz = 0; int prot = 0; if( !streq(iSERVER_PROTO,"ftps") ){ return 0; } if( FtpTLSX_VALID ){ pbsz = FtpTLSX->ftp_PBSZ; if( FtpTLSX->ftp_flags & FtpTLSX_PBSZ ) pbsz += 1; prot = FtpTLSX->ftp_PROT; } if( FtpTLSX->ftp_flags & FtpTLSX_PBSZ ){ /* got PBSZ (without PROT) */ if( ClientFlags & PF_STLS_OPT ){ /* STLS=-fcl */ Timeout = STLS_implicit_ftpdata / 10; }else{ Timeout = STLS_implicit_ftpdata; } if( STLS_implicit_wait < Timeout ){ /* ex. STLS=fcl,im.001 */ Timeout = STLS_implicit_wait; } }else{ if( STLS_wait_set ){ Timeout = STLS_implicit_wait; }else{ Timeout = 10.0; } } timeout = (int)(Timeout*1000); if( timeout <= 0 ) timeout = 1; Start = Time(); nready = PollIn(cldata,timeout); Elp = Time() - Start; if( nready <= 0 ){ sv1log("## FTP-data: NO SSL detected (%.3f/%.3f) %d %X\n", Elp,Timeout,pbsz,prot); return -1; } if( isinSSL(cldata) ){ sv1log("## FTP-data: SSL detected (%.3f/%.3f) %d %X\n", Elp,Timeout,pbsz,prot); return 1; }else{ /* maybe uploading */ sv1log("## FTP-data: detected NON SSL (%.3f/%.3f) %d %X\n", Elp,Timeout,pbsz,prot); return -2; } }
int FL_xPollIn(FL_PAR,int fd,int timeout) { int nready,ntry; int remain,timeout1; int closed; if( readyAlways(fd) ) return 1; timeout = IOTIMEOUT(timeout); nready = -1; remain = timeout; closed = 0; for( ntry = 0; timeout == 0 && ntry < 1 || 0 < remain; ntry++ ){ if( closed = checkCloseOnTimeout(1) ) timeout1 = remain; else if( CHECK_ITVL < remain ) timeout1 = CHECK_ITVL; else timeout1 = remain; errno = 0; nready = PollIn(fd,timeout1); if( 0 < nready ) break; /* this was introduced as a trial to reset possible POLL_PRI status at DeleGate/5.7.5 (17Nov98), but seemed useless, and was got rid of at DeleGate/5.9.1 because it is harmful; at least it cause blocking on slow I/O on Win32. if( nready == 0 ){ CStr(buf,1); if( RecvOOB(fd,buf,0) == 0 ) sv1log("#### POLL_PRI ? PollIn()==0, RecvOOB()==0\n"); } */ if( nready < 0 ){ if( errno == EINTR ) sv1log("#### INTERRUPTED PollIn()=%d <= %s:%d\n",nready,FL_BAR); else{ sv1log("#### xPollIn(%d,%d)=%d errno=%d\n", fd,timeout,nready,errno); break; } }else remain -= timeout1; } if( closed == 0 ) checkCloseOnTimeout(1); if( 100 < ntry ) sv1log("#### xPollIn(%d,%d)*%d : %d\n",fd,timeout,ntry,nready); return nready; }
void startSUDO(Connection *Conn,int csock){ CStr(port,128); if( csock < 0 ){ return; } if( PollIn(csock,1) != 0 ){ sv0log("--SU dead ?\n"); return; } IGNRETP write(csock,portSUDO,sizeof(portSUDO)); if( PollIn(csock,10*1000) <= 0 ){ sv0log("--SU no response\n"); return; } if( read(csock,&passSUDO,sizeof(passSUDO)) <= 0 ){ sv0log("--SU EOF response\n"); return; } sv0log("--SU started\n"); }
size_t CIOSocket::Read(void* pBuf, size_t bufLen, int timeout /*=-1*/) { if (!m_Descriptor) return -1; int result = PollIn(timeout); if (result < 0) // Error return result; int read = recv(m_Descriptor, pBuf, bufLen, 0); if (read == -1) return APC_SOCKET_RCV_ERROR; return read; }
CIOSocket* CServerSocket::Accept(int timeout /*=-1*/) { if (!m_Descriptor) return NULL; int result = PollIn(timeout); if (result < 0) // Error return NULL; int clientDesc = accept(m_Descriptor, NULL, 0); if (clientDesc == -1) return NULL; return new CIOSocket(clientDesc); }
int IsConnected(int sock,const char **reason) { int nready,rcc; CStr(buf,1); int len; VSAddr sab; len = sizeof(VSAddr); if( getpeername(sock,(SAP)&sab,&len) != 0 ){ int isconn = 0; if( errno == SUNBUG ) if( PollIn(sock,1) == 0 || 0 < Peek1(sock) ){ /* AF_UNIX/socketpair copied by dup2() on Solaris2.5 * results in ENAMETOOLONG if connected or not */ isconn = 1; } if( !isconn ){ if(reason) *reason = "cant_getpeername"; return 0; } } if(reason) *reason = "connected"; return 1; /* nready = rPollIn(sock,1); if( nready < 0 ){ if(reason) *reason = "peer_reset"; return 0; } if( nready == 0 ){ if(reason) *reason = "poll_none_ready"; return 1; } rcc = recv(sock,buf,1,MSG_PEEK); if( rcc == 1 ){ if(reason) *reason = "recv_ok"; return 1; } if(reason) *reason = "cant_recv"; return 0; */ }
int simple_relayTimeout(int src,int dst,int timeout) { int rcc,wcc,rcc1,wcc1,nio; rcc = wcc = 0; for( nio = 0;; nio++ ){ if( !IsWindows95() || file_ISSOCK(src) ) if( timeout != 0 ) if( PollIn(src,timeout) <= 0 ) break; if( relay1(NULL,src,dst,&rcc1,&wcc1) <= 0 ) break; rcc += rcc1; wcc += wcc1; } syslog_ERROR("simple_relay [%d -> %d] = (%d -> %d) / %d\n", src,dst,rcc,wcc,nio); return rcc; }
int waitSTLS_CL(Connection *Conn,int timeout){ if( (ClientFlags & PF_STLS_ON) == 0 ) { double St,Sr,Ss,Sn; St = Time(); if( 0 < PollIn(ClientSock,timeout) ){ Sr = Time(); if( isinSSL(ClientSock) ){ CStr(sts,128); int fcl; Ss = Time(); fcl = insertFCLX(Conn,"starttls",CLNT_PROTO,FromC,ToS); Sn = Time(); syslog_ERROR("## STLS ## IMPLICIT SSL ON %d,%d,%d,%d\n", ClientSock,FromC,ToC,fcl); sprintf(sts,"%.2f %.2f/%.2f %.2f %.2f = %.2f", St-ClntConnTime,Sr-St,timeout/1000.0, Ss-Sr,Sn-Ss, Sn-ClntConnTime); sv1log("OK: SSL/cl %s\n",sts); if( 0 <= fcl ){ if( strncaseeq(CLNT_PROTO,"ftp",3) ){ if( FromC == ClientSock ){ ClientSock = dup(ClientSock); } } if( streq(iSERVER_PROTO,"delegate") || ACT_GENERALIST ){ /* 9.9.7 for FTP-data via MASTER/ssl */ ClientSock = dup(ClientSock); sv1log("----ClientSock=[%d] <= [%d]\n", ClientSock,FromC); } dup2(fcl,FromC); close(fcl); ClientFlags |= PF_STLS_ON; return 1; } } } } return 0; }
static int wait_thread(int tid,int timeout){ double St; int xtid,rcc,xi,wcc; int xtids[128]; int xtidn = 0; int rcode; if( ThreadsWaitTO == 0 || ThreadsDone[0] < 0 ){ return 0; } St = Time(); rcode = -1; WaitingThreads++; for(;;){ if( PollIn(ThreadsDone[0],timeout) == 0 ){ daemonlog("F","thread_wait(%X,%d) timeout\n", tid,timeout); break; } xtid = -1; rcc = read(ThreadsDone[0],&xtid,sizeof(xtid)); if( lTHREAD() ){ syslog_ERROR("thread_wait(%X) = %d %X %d/%d\n", tid,rcc,xtid,(int)(1000*(Time()-St)),timeout); } if( xtid == tid ){ rcode = 0; break; } xtids[xtidn++] = xtid; } if( 0 < xtidn ){ for( xi = 0; xi < xtidn; xi++ ){ xtid = xtids[xi]; wcc = write(ThreadsDone[1],&xtid,sizeof(tid)); } } WaitingThreads--; return rcode; }
static size_t Zfread(void *b,size_t z,size_t n,FILE *fp){ int rcc; char *bp; /* if( !isWindowsCE() && z == 1 && ready_cc(fp) <= 0 ){ */ if( !isWindowsCE() && z == 1 ){ int rcc2; int fd = fileno(fp); /* rcc = read(fd,b,n); */ bp = (char*)b; rcc = fgetBuffered(ZVStr(bp,z),z,fp); if( 0 < rcc ){ GZDBG(stderr,"-- %X Zfread:buff=%d\n",TID,rcc); }else if( rcc < 0 ){ rcc = 0; } if( rcc < 32 && rcc < n ){ rcc += read(fd,bp+rcc,n-rcc); } if( 0 < rcc && rcc < 32 && rcc < n ){ if( 0 < PollIn(fd,30) ){ rcc2 = read(fd,((char*)b)+rcc,n-rcc); if( 0 < rcc2 ){ rcc += rcc2; }else{ } }else{ } }else{ } }else{ rcc = fread(b,z,n,fp); } GZDBG(stderr,"-- %X Zfread(%X,%d,%d)=%d\n",TID,fileno(fp),ll2i(z),ll2i(n),rcc); return rcc; }
static int NewPort(PCStr(lport),PVStr(host),int port,int toC,int nlisten) { int timeout1; int elapsed; int sock; int rcode; CStr(exlockpath,1024); bind_exlock = -1; bind_nlisten = -1; if( port == 0 ){ sock = Socket1("VSAP",NEWSOCK,AVStr(host),port,ANYPORT,nlisten,NULL,0); return sock; } bind_exlock = PortLocks(lport,1,AVStr(exlockpath)); if( bind_exlock < 0 ) return -1; /* don't listen just before accept() not to accept more than * a single connection... */ bind_nlisten = nlisten; nlisten = 0; sock = -1; timeout1 = 1000; for(;;){ rcode = lock_exclusiveTO(bind_exlock,timeout1,&elapsed); if( rcode == 0 ){ sock = Socket1("VSAP",NEWSOCK,AVStr(host),port,ANYPORT,nlisten,NULL,0); break; } if( elapsed < timeout1 ) break; if( PollIn(toC,1) != 0 ) break; } return sock; }
int SSL_isrecord(int fd,int timeout){ CStr(buf,8); unsigned char *up = (unsigned char *)buf; CStr(spack,64); int rcc; int sslv; if( PollIn(fd,timeout) <= 0 ){ return 0; } bzero(buf,sizeof(buf)); rcc = recvPEEK(fd,AVStr(buf),sizeof(buf)); if( rcc <= 0 ){ return 0; } sprintf(spack,"%2X %2X %2X %2X %2X",up[0],up[1],up[2],up[3],up[4]); syslog_DEBUG("SSL_isrecord? %d [%s]\n",rcc,spack); sslv = isSSLrecord((const unsigned char*)buf,spack,rcc,fd); if( sslv == 3 ){ return 1; } return 0; }
static int nonSSL_SV(Connection *Conn){ double Start; if( FromS <= 0 ){ return 1; } Start = Time(); if( 0 < PollIn(FromS,(int)(1000*STLS_implicit_waitSV)) ){ IStr(buf,8); int rcc; if( !IsAlive(FromS) ){ sv1log("-- nonSSL_SV ? [%d][%s] Disconnected (%.2f)\n", FromS,DST_PROTO,Time()-Start); } rcc = recvPeekTIMEOUT(FromS,AVStr(buf),sizeof(buf)); if( 0 < rcc ){ /* could be '2' in POP, '*' in IMAP, ... */ sv1log("%d [%X %X %X]\n",rcc,buf[0],buf[1],buf[2]); return 1; } } return 0; }
int pollIZ(const char *wh,double timeout,int in,int exsock){ int rem; int tom = 1000; int to1; int rdy1; int nrdy = 0; Verbose("---- poll(%s) [%d][%d] %.1f ...\n",wh,in,exsock,timeout); if( isWindows() && readyAlways(in) ){ /* 9.9.5 for Windows */ nrdy = 1; if( 0 <= exsock && !IsAlive(exsock) ){ nrdy |= 2; } }else for( rem = (int)(timeout*1000); 0 < rem; rem -= to1 ){ if( 0 <= exsock && !IsAlive(exsock) ){ nrdy |= 2; break; } if( tom < rem ) to1 = tom; else to1 = rem; rdy1 = PollIn(in,to1); if( rdy1 != 0 ){ nrdy |= 1; } Verbose("---- poll(%s) [%d][%d] %.1f %.1f rdy=%X\n",wh, in,exsock,timeout,rem/1000.0,nrdy); if( nrdy ){ break; } } if( LOG_VERBOSE || (nrdy == 0) || (nrdy & 2) ) sv1log("---- poll(%s) [%d][%d] %.1f (%.1f) rdy=%X\n",wh, in,exsock,timeout,rem/1000.0,nrdy); return nrdy; }
static int threadFilter(Connection *Conn,PCStr(fname),iFUNCP func,FILE *ioin,FILE *out,PCStr(args)){ int code; IStr(buf,1); int osock; setthreadgid(0,STX_tid); osock = ClientSock; //ClientSock = dup(ClientSock); Verbose("-- F openFilter: %s [%d][%d] [%d]>>[%d]\n", fname, osock,ClientSock, FromS,ToC); // write(fileno(ioin),"\n",1); /* for sync. of thread_fork */ PollIn(fileno(ioin),1000); clearConnPTR(Conn); code = (*func)(Conn,ioin,out,args); Verbose("-- F openFilter: DONE %d\n",code); fflush(out); ShutdownSocket(fileno(ioin)); /* close(fth.f_sync[1]); */ sv1log("-- F openFilter: EXIT(%d) %s\n",code,fname); return 0; }
/* int RIDENT_recv(int clsock,PVStr(sockname),PVStr(peername)) */ int RIDENT_recvX(int clsock,PVStr(sockname),PVStr(peername),int force) { CStr(rident,128); CStr(ver,128); CStr(user,128); int rcc; int ready; int timeout; /* if( RIDENT_CLIENT == 0 ){ */ if( RIDENT_CLIENT == 0 && force == 0 ){ getpairName(clsock,AVStr(sockname),AVStr(peername)); return 0; } rident[0] = 0; timeout = (int)(RIDENT_TIMEOUT*1000); if( timeout <= 0 ) timeout = 1; ready = PollIn(clsock,timeout); if( ready <= 0 ){ sv1log("####[%d] getRIDENT TIMEOUT(%dms)\n",clsock,timeout); /* close(clsock); return -1; */ goto EXIT; } if( isWindowsCE() ){ /* recv(MSG_PEEK) for only single byte is implemented */ rcc = recv(clsock,rident,1,MSG_PEEK); if( rcc == 1 && rident[0] == RIDENT_MAGIC[0] ){ rcc = recv(clsock,rident,RIDENT_SIZE,0); if( rcc != RIDENT_SIZE || strncmp(rident,RIDENT_MAGIC,RIDENT_MAGIC_LEN) != 0 ){ porting_dbg("## RIDENT_recv() failed %d/%d",rcc,RIDENT_SIZE); } } }else rcc = recv(clsock,rident,RIDENT_SIZE,MSG_PEEK); RIDENT_RCVD = rcc; if( RIDENT_MAGIC_LEN <= rcc ) if( strncmp(rident,RIDENT_MAGIC,RIDENT_MAGIC_LEN) == 0 ){ if( isWindowsCE() ){ /* recv() done already */ }else rcc = read(clsock,rident,RIDENT_SIZE); setVStrEnd(user,0); setVStrEnd(peername,0); setVStrEnd(sockname,0); if( rcc == RIDENT_SIZE ) if( 3 <= Xsscanf(rident+RIDENT_MAGIC_LEN,"%s %s %s %s",AVStr(ver),AVStr(sockname),AVStr(peername),AVStr(user)) ) if( strcmp(ver,RIDENT_VER) == 0 ){ sv1log("#### getRIDENT %d[%s][%s][%s]\n", rcc,sockname,peername,user); return 1; } sv1log("#### getRIDENT Version/Syntax Error\n"); return -1; } EXIT: getpairName(clsock,AVStr(sockname),AVStr(peername)); return 0; }
/* relay OOB (maybe SYNCH signal of Telnet) */ int relayOOB(int in,int out) { CStr(buff,128); int rcc; int pi,nready; CStr(oobb,128); int oobx = 0; int noob = 0; /* msleep(1); SetNonblockingIO("relayOOB",in,1); rcc = recvOOB(in,AVStr(buff),sizeof(buff)); SetNonblockingIO("relayOOB",in,0); if( rcc != 1 ) return 0; */ SetNonblockingIO("relayOOB",in,1); oobx = 0; rcc = recv(in,buff,sizeof(buff),MSG_PEEK|MSG_OOB); if( 0 < rcc ){ rcc = recv(in,oobb+oobx,sizeof(oobb)-oobx,MSG_OOB); oobx += rcc; while( 0 < withOOB(in) ){ errno = 0; rcc = recv(in,buff,sizeof(buff),MSG_PEEK); /* recv() even with MSG_PEEK seems to clear * "exceptfds" in select() */ if( rcc < 0 && errno == EAGAIN ){ syslog_ERROR("relay OOB: EAGAIN\n"); msleep(1); }else if( 0 < rcc && 0 < withOOB(in) ){ /* maybe skipping non-OOB before OOB ... */ CStr(vb,32); refQStr(vp,vb); int i; for( i = 0; i < rcc; i++ ){ if( sizeof(vb) <= (vp-vb)+3 ){ break; } if( 0 < i ) setVStrPtrInc(vp,' '); sprintf(vp,"%02X",0xFF&buff[i]); vp += strlen(vp); } syslog_DEBUG("relay pre-OOB: %d [%s]\n",rcc,vb); rcc = recv(in,buff,sizeof(buff),0); noob += rcc; send(out,buff,rcc,0); }else{ break; } } } if( 0 <= oobx ){ send(out,oobb,oobx,MSG_OOB); syslog_DEBUG("relay OOB: [%d]->[%d] %dbytes (%02X)\n", in,out,oobx,oobb[0]&0xFF); } SetNonblockingIO("relayOOB",in,0); return oobx; syslog_DEBUG("relay OOB: [%d]->[%d] %dbytes (%x)\n", in,out,rcc,buff[0]&0xFF); sendOOB(out,buff,rcc); /* if the protocol is Telnet, * in-band data should be ignored until the MARK(242) ... */ for( pi = 0; pi < 50; pi++ ){ if( nready = PollIn(in,1) ) break; msleep(10); } syslog_DEBUG("relay OOB: nready=%d after %dms\n",nready,pi*10); return 1; }
int service_vsap(Connection *Conn) { CStr(request,1024); CStr(reqver,128); const char *req; int svsock,shared,clsock,rcode; CStr(myport,256); CStr(sockname,MaxHostNameLen); CStr(peername,MaxHostNameLen); int wcc,rcc; CStr(com,1024); CStr(arg,1024); const char *argp; CStr(opt,32); const char *op; int timeout; int AuthOk; FILE *authout; minit_vsapsv(); if( ToS <= 0 || FromS <= 0 ){ /* If the DST_HOST is not local connect to the master and simple_relay... */ } if( !isMYSELF(DFLT_HOST) ){ daemonlog("E","VSAP relaying to %s:%d\n",DFLT_HOST,DFLT_PORT); if( ToS < 0 ) connect_to_serv(Conn,FromC,ToC,0); relay_svcl(Conn,FromC,ToC,FromS,ToS); close(ToS); return 0; } /* timeout = 300; */ timeout = IO_TIMEOUT; shared = 0; myport[0] = 0; SvSockN = 0; ClSockN = 0; clsock = -1; svsock = -1; reqver[0] = 0; authout = TMPFILE("VSAP-AUTH"); if( doAUTH(Conn,NULL,authout,"vsap","-",0,CVStr("user-xxxx:pass-xxxx"),CVStr("host-xxxx"),NULL,NULL) == EOF ){ AuthOk = 0; }else AuthOk = -1; if( ImMaster ){ sprintf(myport,"%s:%d",DST_HOST,DST_PORT); }else for(;;){ if( DDI_fgetsFromCbuf(Conn,AVStr(request),sizeof(request),NULL) == 0 ) { int closed = 0; for(;;){ if( PollIn(FromC,1*1000) != 0 ) break; closed |= checkCloseOnTimeout(1); if( 0 <= clsock && !IsAlive(clsock) ){ daemonlog("E","## disconnected by peer\n"); SockPrintf(ToC,"%s %d %s.\r\n",VER,NO_GENERIC_BYE,"disconnected by peer"); close(clsock);del_clsock(clsock); goto EXIT; } } if( (rcc = RecvLine(FromC,request,sizeof(request))) <= 0 ) break; } daemonlog("D","CLIENT-SAYS: %s",request); daemonlog("E","CLIENT-SAYS: %s",request); req = request; if( strncmp(req,"VSAP/",5) == 0 ) req = wordScan(req,reqver); argp = wordScan(req,com); arg[0] = 0; lineScan(argp,arg); if( strcasecmp(com,"AUTH") == 0 ){ CStr(ahost,MaxHostNameLen); ahost[0] = 0; if( doAUTH(Conn,NULL,authout,"vsap","-",0,AVStr(arg),AVStr(ahost),NULL,NULL) == EOF ){ }else{ AuthOk = 1; SockPrintf(ToC,"%s %d OK\r\n",VER,OK_GENERIC); continue; } } if( AuthOk == 0 ){ SockPrintf(ToC,"%s %d forbidden\r\n",VER,NO_PERMISSION); sv1log("WITH AUTHORIZER, but NO AUTH from client\n"); break; } if( strcasecmp(com,"ECHO") == 0 ){ CStr(stime,64); StrftimeLocal(AVStr(stime),sizeof(stime),TIMEFORM_HTTPD,time(0),0); SockPrintf(ToC,"%s %d [%s] %s\r\n",VER,OK_GENERIC, stime,arg); }else if( strcasecmp(com,"CONNECT") == 0 ){ strcpy(myport,arg); if( !vsap_permit(Conn,myport) ) break; clsock = do_connect(svsock,myport,ToC); if( clsock < 0 ) break; }else if( strcasecmp(com,"BIND") == 0 ){ CStr(opts,1024); opts[0] = 0; Xsscanf(arg,"%s %[^\r\n]",AVStr(myport),AVStr(opts)); if( !vsap_permit(Conn,myport) ) break; svsock = do_bind(-1,AVStr(myport),opts,&shared,AVStr(sockname),ToC); if( svsock < 0 ) break; }else if( strcasecmp(com,"LISTEN") == 0 ){ int nlisten = atoi(arg); Socket1("VSAP",svsock,NULL,NULL,NULL,VStrANYPORT,ANYPORT,nlisten,NULL,0); SockPrintf(ToC,"%s %d listen ok.\r\n",VER,OK_LISTEN); }else if( strcasecmp(com,"ACCEPT") == 0 ){ int priority; if( Conn->cl_count <= 1 ) priority = 0; else priority = 1; clsock = do_accept(myport,arg,shared,priority,FromC,ToC); if( !shared ) svsock = -1; if( clsock < 0 ){ wcc = SockPrintf(ToC,"%s %d accept fail\r\n", VER,NO_ACCEPT); break; } add_clsock(clsock); if( myport[0] == '/' ){ strcpy(sockname,myport); strcpy(peername,myport); }else getpairName(clsock,AVStr(sockname),AVStr(peername)); wcc = SockPrintf(ToC,"%s %d %d %s %s accepted.\r\n", VER,OK_ACCEPT,ClSockN,sockname,peername); }else if( strcasecmp(com,"QUIT") == 0 ){ SockPrintf(ToC,"%s %d bye.\r\n",VER,OK_BYE); break; }else if( strcasecmp(com,"FORWARD") == 0 ){ do_forward(Conn,myport,arg,shared,svsock,0,FromC,ToC); }else if( strcasecmp(com,"RELAY") == 0 ){ /* -t timeout */ for( op = arg; *op == '-'; ){ if( strneq(op,"-t=",3) ){ int to; op = numscanX(op+3,AVStr(opt),sizeof(opt)); to = atoi(opt); if( to < timeout ) timeout = to; }else{ break; } } tcp_relay2(timeout*1000,FromC,clsock,clsock,ToC); /* set_linger(clsock,10); */ set_linger(clsock,LIN_TIMEOUT); close(clsock);del_clsock(clsock); break; }else if( strcasecmp(com,"PROXY") == 0 ){ ToS = FromS = ToC; ToC = FromC = clsock; daemonlog("E","##### VSAP switch protocol to '%s'\n",arg); if( strcmp(arg,"http")==0 ) service_http(Conn); else if( strcmp(arg,"ftp")==0 ) service_ftp(Conn); set_linger(clsock,10); close(clsock);del_clsock(clsock); break; }else { /* wcc = write(clsock,req,rcc); tcp_relay2(timeout*1000,FromC,clsock,clsock,ToC); */ SockPrintf(ToC,"%s %d %s",VER,NO_GENERIC,request); } } EXIT: fclose(authout); return 0; }
int thread_PollIn(int fd,int timeout) { int ti,nth,fdv[8],rfv[8],fdx; int timeout1,remain,nready,efd; if( fd_polling == 0 ) fd_polling = (char*)StructAlloc(FD_SETSIZE); if( ThreadYield == NULL ) return PollIn(fd,timeout); if( FD_SETSIZE <= fd ){ porting_dbg("#### THREAD-POLL: too large fd (%d)",fd); exit(0); } if( fd_polling[fd] != 0 ){ /*porting_dbg("#### THREAD-POLL: another thread waiting on %d",fd);*/ exit(0); } if( 64 <= fd ) fprintf(stderr,"####[%d] thread_PollIn(%d)\n",getpid(),fd); fd_polling[fd] = 1; START: nth = 0; fdx = 0; for( ti = 0; ti < FD_SETSIZE; ti++ ) { if( 0 < fd_polling[ti] ){ if( ti == fd ) fdx = nth; fdv[nth++] = ti; } } if( nth == 0 ) goto EXIT; if( nth == 1 ) timeout1 = 100; /* waiting another thread be started */ else timeout1 = 5000; /* and more threads... */ for( remain = timeout; timeout == 0 || 0 < remain; remain -= timeout1 ){ nready = PollIns(timeout1,nth,fdv,rfv); if( 0 <= (efd = connHUP()) ){ if( efd == fd ){ nready = 1; goto EXIT; }else{ fd_polling[efd] = 0; goto START; } } if( nready < 0 ) break; if( nready == 0 ){ /*porting_dbg("#### yield 1");*/ (*ThreadYield)(); continue; } if( 0 < rfv[fdx] ){ nready = 1; goto EXIT; } for( ti = 0; ti < nth; ti++ ) if( 0 < rfv[ti] ){ /*porting_dbg("#### yield 2: %d",fdv[ti]);*/ if( (*ThreadYield)() == 0 ) break; } } EXIT: fd_polling[fd] = 0; return nready; }
/* int IsAlive(int sock){ */ int IsAlive_FL(FL_PAR,int sock){ int serrno,rdy1,rdy2; int r1,d1,r2,d2; if( IsConnected(sock,NULL) ){ if( isWindowsCE() ){ int exceptionReady(int sock); int rdy1,rdy2,rev2; if( rdy1 = exceptionReady(sock) ){ rdy2 = inputReady(sock,&rev2); /* syslog_DEBUG("## IsNotAlive[%d] %d,%d/%d <= %s:%d\n", sock,rdy1,rdy2,rev2,FL_BAR); */ return 0; } return 1; /* no MSG_PEEK on WinCE */ } if( !lSISALIVE() ){ SSigMask sMask; setSSigMask(sMask); /* rdy1 = PollIn(sock,1); 9.9.8 for faster IsAlive() */ rdy1 = PollIn(sock,TIMEOUT_IMM); serrno = errno; resetSSigMask(sMask); if( rdy1 < 0 ){ /* 9.9.4 MTSS interrupted by a signal ? */ putsLog("IsAlive PollIn failed"); rdy2 = PollIn(sock,1); syslog_ERROR("IsAlive[%d] rdy=%d,%d err=%d <= %s:%d\n", sock,rdy1,rdy2,serrno,FL_BAR); rdy1 = rdy2; } /* if( PollIn(sock,1) == 0 || 0 < Peek1(sock) ) */ if( rdy1 == 0 || 0 < rdy1 && Peek1(sock) ) return 1; else syslog_ERROR("## left connected but dead [%d] <= %s:%d\n", sock,FL_BAR); /* else syslog_ERROR("## left connected but dead [%d]\n",sock); */ }else{ errno = 0; rdy1 = PollIn(sock,1); serrno = errno; if( rdy1 == 0 ){ return 2; } msleep(1); r1 = inputReady(sock,&d1); rdy2 = PollIn(sock,1); r2 = inputReady(sock,&d2); if( rdy2 == 0 ){ porting_dbg("## IsAlive(%d) %d => %d (%d/%d %d/%d) e%d a%d <= %s:%d", sock,rdy1,rdy2,r1,d1,r2,d2,serrno, actthreads(),FL_BAR); return 3; } if( 0 < Peek1(sock) ){ return 4; } syslog_ERROR("## left connected but dead [%d]\n",sock); } } return 0; }