diff --git a/doc/html/howtoe.html b/doc/html/howtoe.html index 7c29aa5..36b250b 100644 --- a/doc/html/howtoe.html +++ b/doc/html/howtoe.html @@ -870,6 +870,16 @@ You can control 3proxy service via "Services" administration ot via "net" comman
  • 50-69 - SOCKS5 PROXY REDIRECTION ERRORS
  • 70-79 PARENT PROXY CONNECTION ERRORS (identical to 1x)
  • 90-99 - established connection errors +
  • since 0.9 +
  • 90 - unexpected system error (should not happen) +
  • 91 - unexpected poll error (should not happen) +
  • 92 - connection terminated by timeout +
  • 93 - dirty connection termination by server or client (or network issue) with unsent data +
  • 94 - clear connection termination by server or client with unsent data +
  • 95 - dirty connection termination by client (or network issue) +
  • 96 - dirty connection termination by server (or network issue) +
  • 97 - dirty connection termination by both client and server (probably network issue) +
  • prior to 0.9:
  • 90 - socket error or connection broken
  • 91 - TCP/IP common failure
  • 92 - connection timed out diff --git a/doc/html/howtor.html b/doc/html/howtor.html index a97ecad..c34a9cc 100644 --- a/doc/html/howtor.html +++ b/doc/html/howtor.html @@ -1046,6 +1046,18 @@
  • 50-69 - ошибки перенаправления SOCKS5
  • 70-79 ошибки установки родительского соединения, аналогичны 1x
  • 90-99 - ошибки разрыва соединения +
  • с версии 0.9 +
  • 90 - неожиданная системная ошибка (не должно происходить) +
  • 91 - ошибка poll (не должно происходить) +
  • 92 - соединение прервано по таймауту +
  • 93 - клиент или сервер "грязно" закрыли соединение или произошла сетевая ошибка, остались неотправленные данные +
  • 94 - клиент или сервер "чисто" закрыли соединение или произошла сетевая ошибка, остались неотправленные данные +
  • 95 - клиент "грязно" закрыл соединение или сетевая ошибка +
  • 96 - сервер "грязно" закрыл соединение или сетевая ошибка +
  • 97 - клиент и сервер "грязно" закрыли соединение или сетевая ошибка +
  • 98 - исчерпан лимит данных сервера (не должно быть в журнале) +
  • 99 - исчерпан лимит данных клиента (не должно быть в журнале) +
  • до версии 0.9
  • 90 - ошибка сокета или соединение неожиданно прервано
  • 91 - общий сбой стека TCP/IP
  • 92 - соединение прервано по таймауту diff --git a/src/common.c b/src/common.c index abf3081..1bdf5d4 100644 --- a/src/common.c +++ b/src/common.c @@ -369,7 +369,7 @@ int connectwithpoll(SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to){ unsigned long ul = 1; ioctlsocket(sock, FIONBIO, &ul); #else - fcntl(sock,F_SETFL,O_NONBLOCK); + fcntl(sock,F_SETFL, O_NONBLOCK | fcntl(sock,F_GETFL)); #endif if(so._connect(sock,sa,size)) { if(errno != EAGAIN && errno != EINPROGRESS) return (13); diff --git a/src/dnspr.c b/src/dnspr.c index 041e0e2..bdf2e61 100644 --- a/src/dnspr.c +++ b/src/dnspr.c @@ -198,7 +198,7 @@ CLEANRET: if((ip && type == 0x01) || type == 0x1c){ myinet_ntop(type == 0x01? AF_INET:AF_INET6, addr, (char *)buf+strlen((char *)buf), 64); } - (*param->srv->logfunc)(param, buf); + dolog(param, buf); } if(bbuf)myfree(bbuf); if(host)myfree(host); diff --git a/src/ftppr.c b/src/ftppr.c index e22e66a..71eb8cc 100644 --- a/src/ftppr.c +++ b/src/ftppr.c @@ -295,7 +295,7 @@ void * ftpprchild(struct clientparam* param) { sasize = sizeof(param->sincr); if(so._getpeername(param->ctrlsock, (struct sockaddr *)¶m->sincr, &sasize)){RETURN(819);} if(req && (param->statscli64 || param->statssrv64)){ - (*param->srv->logfunc)(param, (unsigned char *)req); + dolog(param, (unsigned char *)req); } } @@ -316,7 +316,7 @@ CLEANRET: sasize = sizeof(param->sincr); so._getpeername(param->ctrlsock, (struct sockaddr *)¶m->sincr, &sasize); if(param->res != 0 || param->statscli64 || param->statssrv64 ){ - (*param->srv->logfunc)(param, (unsigned char *)((req && (param->res > 802))? req:NULL)); + dolog(param, (unsigned char *)((req && (param->res > 802))? req:NULL)); } if(req) myfree(req); if(buf) myfree(buf); diff --git a/src/log.c b/src/log.c index 1f765d5..7572565 100644 --- a/src/log.c +++ b/src/log.c @@ -1,18 +1,38 @@ /* 3APA3A simpliest proxy server - (c) 2002-2016 by Vladimir Dubrovin <3proxy@3proxy.ru> + (c) 2002-2020 by Vladimir Dubrovin <3proxy@3proxy.ru> please read License Agreement */ -pthread_mutex_t log_mutex; #include "proxy.h" +pthread_mutex_t log_mutex; int havelog = 0; + +struct clientparam logparam; +struct srvparam logsrv; + + + +void dolog(struct clientparam * param, const unsigned char *s){ + static int init = 0; + + if(param)param->srv->logfunc(param, s); + else { + if(!init){ + srvinit(&logsrv, &logparam); + init = 1; + } + logstdout(&logparam, s); + } +} + + void clearstat(struct clientparam * param) { #ifdef _WIN32 diff --git a/src/pop3p.c b/src/pop3p.c index 2db17aa..b433998 100644 --- a/src/pop3p.c +++ b/src/pop3p.c @@ -49,9 +49,9 @@ CLEANRET: if(param->hostname&¶m->extusername) { sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(¶m->sinsr)==110)?0:':', ntohs(*SAPORT(¶m->sinsr))); - (*param->srv->logfunc)(param, buf); + dolog(param, buf); } - else (*param->srv->logfunc)(param, NULL); + else dolog(param, NULL); if(param->clisock != INVALID_SOCKET) { if ((param->res > 0 && param->res < 100) || (param->res > 611 && param->res <700)) socksend(param->clisock, (unsigned char *)"-ERR\r\n", 6,conf.timeouts[STRING_S]); } diff --git a/src/proxy.c b/src/proxy.c index efcbe5d..0f530c2 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -152,7 +152,7 @@ static void logurl(struct clientparam * param, char * buf, char * req, int ftp){ strcpy(se, sb); } } - if(param->res != 555 && param->res != 508)(*param->srv->logfunc)(param, (unsigned char *)(req?buf:NULL)); + if(param->res != 555 && param->res != 508)dolog(param, (unsigned char *)(req?buf:NULL)); } void decodeurl(unsigned char *s, int allowcr){ diff --git a/src/proxy.h b/src/proxy.h index b09c901..2912962 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -151,8 +151,7 @@ extern int timetoexit; extern struct extparam conf; -int sockmap(struct clientparam * param, int timeo); -int splicemap(struct clientparam * param, int timeo); +int sockmap(struct clientparam * param, int timeo, int usesplice); int socksend(SOCKET sock, unsigned char * buf, int bufsize, int to); int socksendto(SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to); int sockrecvfrom(SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to); @@ -168,6 +167,7 @@ int sockgetlinebuf(struct clientparam * param, DIRECTION which, unsigned char * +void dolog(struct clientparam * param, const unsigned char *s); int dobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec); int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format); extern FILE * stdlog; @@ -312,9 +312,9 @@ extern struct datatype datatypes[64]; extern struct commands commandhandlers[]; #ifdef WITHSPLICE -#define mapsocket(a,b) (a->srv->usesplice && !a->ndatfilterssrv && !a->ndatfilterscli && !a->npredatfilters?splicemap(a,b):sockmap(a,b)) +#define mapsocket(a,b) ((a->srv->usesplice && !a->ndatfilterssrv && !a->ndatfilterscli)?sockmap(a,b,1):sockmap(a,b,0)) #else -#define mapsocket(a,b) sockmap(a,b) +#define mapsocket(a,b) sockmap(a,b, 0) #endif diff --git a/src/proxymain.c b/src/proxymain.c index deeb2c8..9388955 100644 --- a/src/proxymain.c +++ b/src/proxymain.c @@ -23,27 +23,27 @@ void * threadfunc (void *p) { fds.revents = 0; for(i=5+(param->srv->maxchild>>10); i; i--){ if(so._poll(&fds, 1, 1000*CONNBACK_TO)!=1){ - param->srv->logfunc(param, (unsigned char *)"Connect back not received, check connback client"); + dolog(param, (unsigned char *)"Connect back not received, check connback client"); i = 0; break; } param->remsock = so._accept(param->srv->cbsock, (struct sockaddr*)¶m->sinsr, &size); if(param->remsock == INVALID_SOCKET) { - param->srv->logfunc(param, (unsigned char *)"Connect back accept() failed"); + dolog(param, (unsigned char *)"Connect back accept() failed"); continue; } #ifndef WITHMAIN param->req = param->sinsr; if(param->srv->acl) param->res = checkACL(param); if(param->res){ - param->srv->logfunc(param, (unsigned char *)"Connect back ACL failed"); + dolog(param, (unsigned char *)"Connect back ACL failed"); so._closesocket(param->remsock); param->remsock = INVALID_SOCKET; continue; } #endif if(socksendto(param->remsock, (struct sockaddr*)¶m->sinsr, (unsigned char *)"C", 1, CONNBACK_TO) != 1){ - param->srv->logfunc(param, (unsigned char *)"Connect back sending command failed"); + dolog(param, (unsigned char *)"Connect back sending command failed"); so._closesocket(param->remsock); param->remsock = INVALID_SOCKET; continue; @@ -57,6 +57,13 @@ void * threadfunc (void *p) { freeparam(param); } else { + +#ifndef _WIN32 + sigset_t mask; + sigfillset(&mask); + pthread_sigmask(SIG_SETMASK, &mask, NULL); +#endif + ((struct clientparam *) p)->srv->pf((struct clientparam *)p); } #ifdef _WIN32 @@ -260,12 +267,8 @@ int MODULEMAINFUNC (int argc, char** argv){ WSADATA wd; WSAStartup(MAKEWORD( 1, 1 ), &wd); - - -#else - signal(SIGPIPE, SIG_IGN); - #endif + #endif srvinit(&srv, &defparam); @@ -288,6 +291,14 @@ int MODULEMAINFUNC (int argc, char** argv){ pthread_mutex_init(&log_mutex, NULL); #endif +#ifndef _WIN32 + { + sigset_t mask; + sigfillset(&mask); + pthread_sigmask(SIG_SETMASK, &mask, NULL); + } +#endif + for (i=1; i>4))==-1) { sprintf((char *)buf, "listen(): %s", strerror(errno)); - if(!srv.silent)(*srv.logfunc)(&defparam, buf); + if(!srv.silent)dolog(&defparam, buf); return -4; } } @@ -606,13 +617,13 @@ int MODULEMAINFUNC (int argc, char** argv){ if(!srv.silent && !iscbc){ sprintf((char *)buf, "Accepting connections [%u/%u]", (unsigned)getpid(), (unsigned)pthread_self()); - (*srv.logfunc)(&defparam, buf); + dolog(&defparam, buf); } } if(iscbl){ parsehost(srv.family, cbl_string, (struct sockaddr *)&cbsa); if((srv.cbsock=so._socket(SASOCK(&cbsa), SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET) { - (*srv.logfunc)(&defparam, (unsigned char *)"Failed to allocate connect back socket"); + dolog(&defparam, (unsigned char *)"Failed to allocate connect back socket"); return -6; } opt = 1; @@ -625,11 +636,11 @@ int MODULEMAINFUNC (int argc, char** argv){ setopts(srv.cbsock, srv.cbssockopts); if(so._bind(srv.cbsock, (struct sockaddr*)&cbsa, SASIZE(&cbsa))==-1) { - (*srv.logfunc)(&defparam, (unsigned char *)"Failed to bind connect back socket"); + dolog(&defparam, (unsigned char *)"Failed to bind connect back socket"); return -7; } if(so._listen(srv.cbsock, 1 + (srv.maxchild>>4))==-1) { - (*srv.logfunc)(&defparam, (unsigned char *)"Failed to listen connect back socket"); + dolog(&defparam, (unsigned char *)"Failed to listen connect back socket"); return -8; } } @@ -649,7 +660,7 @@ int MODULEMAINFUNC (int argc, char** argv){ nlog++; if(!srv.silent && nlog > 5000) { sprintf((char *)buf, "Warning: too many connected clients (%d/%d)", srv.childcount, srv.maxchild); - (*srv.logfunc)(&defparam, buf); + dolog(&defparam, buf); nlog = 0; } usleep(SLEEPTIME); @@ -667,7 +678,7 @@ int MODULEMAINFUNC (int argc, char** argv){ if (error == 0) continue; if (errno != EAGAIN && errno != EINTR) { sprintf((char *)buf, "poll(): %s/%d", strerror(errno), errno); - if(!srv.silent)(*srv.logfunc)(&defparam, buf); + if(!srv.silent)dolog(&defparam, buf); break; } } @@ -740,7 +751,7 @@ int MODULEMAINFUNC (int argc, char** argv){ nlog++; if(!srv.silent && (error || nlog > 5000)) { sprintf((char *)buf, "accept(): %s", strerror(errno)); - (*srv.logfunc)(&defparam, buf); + dolog(&defparam, buf); nlog = 0; } continue; @@ -750,13 +761,13 @@ int MODULEMAINFUNC (int argc, char** argv){ size = sizeof(defparam.sincl); if(so._getsockname(new_sock, (struct sockaddr *)&defparam.sincl, &size)){ sprintf((char *)buf, "getsockname(): %s", strerror(errno)); - if(!srv.silent)(*srv.logfunc)(&defparam, buf); + if(!srv.silent)dolog(&defparam, buf); continue; } #ifdef _WIN32 ioctlsocket(new_sock, FIONBIO, &ul); #else - fcntl(new_sock,F_SETFL,O_NONBLOCK); + fcntl(new_sock,F_SETFL,O_NONBLOCK | fcntl(new_sock,F_GETFL)); #endif so._setsockopt(new_sock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg)); so._setsockopt(new_sock, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int)); @@ -767,7 +778,7 @@ int MODULEMAINFUNC (int argc, char** argv){ if(! (newparam = myalloc (sizeof(defparam)))){ if(!isudp) so._closesocket(new_sock); defparam.res = 21; - if(!srv.silent)(*srv.logfunc)(&defparam, (unsigned char *)"Memory Allocation Failed"); + if(!srv.silent)dolog(&defparam, (unsigned char *)"Memory Allocation Failed"); usleep(SLEEPTIME); continue; }; @@ -804,7 +815,7 @@ int MODULEMAINFUNC (int argc, char** argv){ } else { sprintf((char *)buf, "_beginthreadex(): %s", _strerror(NULL)); - if(!srv.silent)(*srv.logfunc)(&defparam, buf); + if(!srv.silent)dolog(&defparam, buf); error = 1; } #else @@ -813,7 +824,7 @@ int MODULEMAINFUNC (int argc, char** argv){ srv.childcount++; if(error){ sprintf((char *)buf, "pthread_create(): %s", strerror(error)); - if(!srv.silent)(*srv.logfunc)(&defparam, buf); + if(!srv.silent)dolog(&defparam, buf); } else { newparam->threadid = (unsigned)thread; diff --git a/src/smtpp.c b/src/smtpp.c index c369ad7..01519ca 100644 --- a/src/smtpp.c +++ b/src/smtpp.c @@ -292,9 +292,9 @@ CLEANRET: if(param->hostname&¶m->extusername) { sprintf((char *)buf, "%.128s@%.128s%c%hu", param->extusername, param->hostname, *SAPORT(¶m->sinsr)==25?0:':',ntohs(*SAPORT(¶m->sinsr))); - (*param->srv->logfunc)(param, buf); + dolog(param, buf); } - else (*param->srv->logfunc)(param, NULL); + else dolog(param, NULL); if(param->clisock != INVALID_SOCKET) { if ((param->res > 0 && param->res < 100) || (param->res > 661 && param->res <700)) socksend(param->clisock, (unsigned char *)"571 \r\n", 6,conf.timeouts[STRING_S]); } diff --git a/src/sockmap.c b/src/sockmap.c index 559c2c5..b3c54b9 100644 --- a/src/sockmap.c +++ b/src/sockmap.c @@ -1,6 +1,6 @@ /* 3APA3A simpliest proxy server - (c) 2002-2016 by Vladimir Dubrovin <3proxy@3proxy.ru> + (c) 2002-2020 by Vladimir Dubrovin <3proxy@3proxy.ru> please read License Agreement @@ -8,6 +8,15 @@ #include "proxy.h" +#ifdef WITHLOG +#if WITHLOG > 1 +char logbuf[1024]; +#endif +#define log(X) dolog(param,X) +#else +#define log(X) +#endif + #ifdef WITHSPLICE #include @@ -25,565 +34,641 @@ ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t le #define SPLICE_F_GIFT 0x08 #endif -#define RETURN(xxx) { res = xxx; goto CLEANRET; } -#define MIN(a,b) ((a>b)?b:a) #define MAXSPLICE 65536 +#endif -int splicemap(struct clientparam * param, int timeo){ - struct pollfd fds[2]; +#define MIN(a,b) ((a>b)?b:a) +#define RETURN(xxx) { res = xxx; goto CLEANRET; } + +int sockmap(struct clientparam * param, int timeo, int usesplice){ + uint64_t fromclient=0x7fffffffffffffff, fromserver =0x7fffffffffffffff; + uint64_t inclientbuf = 0, inserverbuf = 0; + int FROMCLIENT = 1, TOCLIENTBUF = 1, FROMCLIENTBUF = 1, TOSERVER = 1, + FROMSERVER = 1, TOSERVERBUF = 1, FROMSERVERBUF = 1, TOCLIENT = 1; + int HASERROR=0; + int CLIENTTERM = 0, SERVERTERM = 0; + int after = 0; + struct pollfd fds[6]; struct pollfd *fdsp = fds; - int fdsc = 2; + int fdsc = 0; + int sleeptime = 0; + FILTER_ACTION action; + int res; + SASIZETYPE sasize; + +#ifdef WITHSPLICE + uint64_t inclientpipe = 0, inserverpipe = 0; + int TOCLIENTPIPE = 0, FROMCLIENTPIPE = 0, TOSERVERPIPE = 0, FROMSERVERPIPE = 0; int pipesrv[2] = {-1,-1}; int pipecli[2] = {-1,-1}; - uint64_t sent=0, received=0; - SASIZETYPE sasize; - int res = 0, stop = 0; - int srvstate = 0, clistate = 0; - int srvsockstate = 0, clisockstate = 0; - int insrvpipe = 0, inclipipe = 0; - int rfromserver = 0, rfromclient = 0; - int sleeptime = 0; - int needcontinue; - int tosend; - - tosend = param->srvinbuf - param->srvoffset; - if(!param->waitclient64 && tosend){ - needcontinue = 1; - if(param->waitserver64 && param->waitserver64 <= tosend){ - needcontinue = 0; - tosend = param->waitserver64; - } - if(socksend(param->clisock, param->srvbuf + param->srvoffset, tosend, conf.timeouts[STRING_S]) != tosend){ - return 96; - } - if(!needcontinue){ - param->srvoffset += tosend; - if(param->srvoffset == param->srvinbuf) param->srvoffset = param->srvinbuf = 0; - return 98; - } - received += tosend; - param->srvoffset = param->srvinbuf = 0; + if(param->operation == UDPASSOC) usesplice = 0; + if(usesplice){ + TOCLIENTPIPE = FROMCLIENTPIPE = TOSERVERPIPE = FROMSERVERPIPE = 1; + TOCLIENTBUF = TOSERVERBUF = 0; + if(pipe2(pipecli, O_NONBLOCK) < 0) RETURN (21); + if(pipe2(pipesrv, O_NONBLOCK) < 0) RETURN (21); } - tosend = param->cliinbuf - param->clioffset; - if(!param->waitserver64 && tosend){ - needcontinue = 1; - if(param->waitclient64 && param->waitclient64 <= tosend){ - needcontinue = 0; - tosend = param->waitclient64; - } - if(socksend(param->remsock, param->clibuf + param->clioffset, tosend, conf.timeouts[STRING_S]) != tosend){ - return 97; - } - param->nwrites++; - param->statscli64 += tosend; +#endif - if(!needcontinue){ - param->clioffset += tosend; - if(param->clioffset == param->cliinbuf) param->clioffset = param->cliinbuf = 0; - return 99; - } - sent += tosend; - param->clioffset = param->cliinbuf = 0; + inserverbuf = param->srvinbuf - param->srvoffset; + inclientbuf = param->cliinbuf - param->clioffset; + + if(param->waitclient64) { + fromclient = param->waitclient64; + fromserver = 0; + inserverbuf = 0; + TOCLIENT = 0; + FROMSERVER = 0; } - - if(!param->waitserver64 && !param->waitclient64){ - myfree(param->srvbuf); - param->srvbuf = NULL; - param->srvbufsize = 0; - myfree(param->clibuf); - param->clibuf = NULL; - param->clibufsize = 0; - param->srvinbuf = param->srvoffset = param->cliinbuf = param->clioffset = 0; + if(param->waitserver64) { + fromserver = param->waitserver64; + fromclient = 0; + inclientbuf = 0; + TOSERVER = 0; + FROMCLIENT = 0; } - - param->res = 0; - if(pipe(pipecli) < 0) RETURN(21); - if(pipe(pipesrv) < 0) RETURN(21); - - fds[0].fd = param->clisock; - fds[1].fd = param->remsock; - - while((!stop || (inclipipe && !srvsockstate) || (insrvpipe && !clisockstate)) && !conf.timetoexit){ - - param->cycles++; -#ifdef NOIPV6 - sasize = sizeof(struct sockaddr_in); -#else - sasize = sizeof(struct sockaddr_in6); -#endif - fds[0].events = fds[1].events = 0; - fds[0].revents = fds[1].revents = 0; - - if(srvstate && !clisockstate && !param->waitclient64 && param->clisock != INVALID_SOCKET){ -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "splice: will send to client"); -#endif - fds[0].events |= POLLOUT; - } - rfromserver = MAXSPLICE - insrvpipe; - if(param->waitserver64) rfromserver = MIN(MAXSPLICE, param->waitserver64 - (received + insrvpipe)); - if(srvstate < 2 && !srvsockstate && rfromserver > 0 && param->remsock != INVALID_SOCKET) { -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "splice: will recv from server"); -#endif - fds[1].events |= (POLLIN|POLLRDHUP); - } - if(clistate && !srvsockstate && !param->waitserver64 && param->remsock != INVALID_SOCKET){ -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "splice: will send to server"); -#endif - fds[1].events |= POLLOUT; - } - rfromclient = MAXSPLICE - inclipipe; - if(param->waitclient64) rfromclient = MIN(MAXSPLICE, param->waitclient64 - (sent + inclipipe)); - if(clistate < 2 && !clisockstate && rfromclient > 0 && param->clisock != INVALID_SOCKET) { -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "splice: will recv from client"); -#endif - fds[0].events |= (POLLIN|POLLRDHUP); - } - if(!fds[0].events && !fds[1].events) RETURN (666); - if(fds[0].fd == INVALID_SOCKET){ - fdsp = fds +1; - fdsc = 1; - } - else if(fds[1].fd == INVALID_SOCKET){ - fdsp = fds; - fdsc = 1; - } - else { - fdsp = fds; - fdsc = 2; - } - res = so._poll(fdsp, fdsc, timeo*1000); - if(res < 0){ - if(errno == EINTR) so._poll(NULL, 0, 1); - else if(errno != EAGAIN) RETURN(91); - continue; - } - if(res < 1){ - RETURN(92); - } - if( (fds[0].revents & (POLLERR|POLLNVAL)) || (fds[1].revents & (POLLERR|POLLNVAL))) { - RETURN(90); - } - if( (fds[0].revents & (POLLHUP|POLLRDHUP))) { - stop = clisockstate = 1; - } - if( (fds[1].revents & (POLLERR|POLLNVAL|POLLHUP|POLLRDHUP)) && !(fds[1].revents & POLLIN)){ - stop = srvsockstate = 1; - } - if((fds[0].revents & POLLOUT)){ -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "splice: spliced send to client"); -#endif - res = splice(pipesrv[0], NULL, param->clisock, NULL, MIN(MAXSPLICE, insrvpipe), SPLICE_F_NONBLOCK | SPLICE_F_MOVE); - if(res <= 0) { -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "splice: send to client error"); -#endif - if(errno == EINTR) so._poll(NULL, 0, 1); - else if(errno != EAGAIN) RETURN(96); - continue; - } - if(res){ - insrvpipe -= res; - received += res; - - if(param->bandlimfunc) { - sleeptime = (*param->bandlimfunc)(param, res, 0); - } - srvstate = 0; - } - if(param->waitserver64 && param->waitserver64 <= received){ - RETURN (98); - } - } - if((fds[1].revents & POLLOUT)){ -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "splice: spliced send to server"); -#endif - res = splice(pipecli[0], NULL, param->remsock, NULL, MIN(MAXSPLICE, inclipipe), SPLICE_F_NONBLOCK | SPLICE_F_MOVE); - if(res <= 0) { -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "splice: send to server error"); -#endif - if(errno == EINTR) so._poll(NULL, 0, 1); - else if(errno != EAGAIN) RETURN(97); - continue; - } - if(res){ - inclipipe -= res; - sent += res; - param->nwrites++; - param->statscli64 += res; - - if(param->bandlimfunc) { - int sl1; - sl1 = (*param->bandlimfunc)(param, 0, res); - if(sl1 > sleeptime) sleeptime = sl1; - } - clistate = 0; - } - if(param->waitclient64 && param->waitclient64 <= sent){ - RETURN (99); - } - } - if ((fds[0].revents & POLLIN) || clisockstate == 1) { -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "splice: recv from client"); -#endif - res = splice(param->clisock, NULL, pipecli[1], NULL, rfromclient, SPLICE_F_NONBLOCK | SPLICE_F_MOVE); - if (res < 0){ - if(errno == EINTR) so._poll(NULL, 0, 1); - else if(errno != EAGAIN) RETURN(94); - continue; - } - if (res==0) { - clisockstate = 2; - stop = 1; - } - else { - inclipipe += res; - clistate = 1; - if(insrvpipe >= MAXSPLICE) clistate = 2; - } - } - if ((fds[1].revents & POLLIN) || srvsockstate == 1) { -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "splice: recv from server"); -#endif - res = splice(param->remsock, NULL, pipesrv[1], NULL, rfromserver, SPLICE_F_NONBLOCK | SPLICE_F_MOVE); - if (res < 0){ - if(errno == EINTR) so._poll(NULL, 0, 1); - else if(errno != EAGAIN) RETURN(93); - continue; - } - if (res==0) { - srvsockstate = 2; - stop = 1; - } - else { - insrvpipe += res; - param->statssrv64 += res; - param->nreads++; - srvstate = 1; - if(insrvpipe >= MAXSPLICE) srvstate = 2; - } - } - if(sleeptime > 0) { - if(sleeptime > (timeo * 1000)){RETURN (95);} - so._poll(NULL, 0, sleeptime); - sleeptime = 0; - } + if(param->operation == UDPASSOC && param->srv->singlepacket){ + fromclient = inclientbuf; + FROMCLIENT = 0; } - -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "splice: finished with mapping"); + if(inserverbuf >= fromserver) FROMSERVER = 0; + if(inclientbuf >= fromclient) FROMCLIENT = 0; +#ifdef WITHSPLICE + if(!usesplice) #endif + { + if(fromserver && !param->srvbuf && (!(param->srvbuf=myalloc(SRVBUFSIZE)) || !(param->srvbufsize = SRVBUFSIZE))){ + RETURN (21); + } + if(fromclient && !param->clibuf && (!(param->clibuf=myalloc(SRVBUFSIZE)) || !(param->clibufsize = SRVBUFSIZE))){ + RETURN (21); + } + + } + if(param->srvinbuf == param->srvoffset) param->srvinbuf =param->srvoffset = 0; + if(param->cliinbuf == param->clioffset) param->cliinbuf =param->clioffset = 0; + if(param->clibufsize == param->cliinbuf) TOCLIENTBUF = 0; + if(param->srvbufsize == param->srvinbuf) TOSERVERBUF = 0; + + action = handlepredatflt(param); + if(action == HANDLED){ + RETURN(0); + } + if(action != PASS) RETURN(19); + + while( + ((!CLIENTTERM) && (inserverbuf +#ifdef WITHSPLICE + || inserverpipe +#endif + || (!SERVERTERM && fromserver))) + || + ((!SERVERTERM) && (inclientbuf +#ifdef WITHSPLICE + || inclientpipe +#endif + || (!CLIENTTERM && fromclient))) + ){ + + +#if WITHLOG > 1 +sprintf(logbuf, "int FROMCLIENT = %d, TOCLIENTBUF = %d, FROMCLIENTBUF = %d, TOSERVER = %d, " + "FROMSERVER = %d, TOSERVERBUF = %d, FROMSERVERBUF = %d, TOCLIENT = %d; inclientbuf=%d; " + "inserverbuf=%d, CLIENTTERM = %d, SERVERTERM =%d, fromserver=%u, fromclient=%u" +#ifdef WITHSPLICE + ", inserverpipe=%d, inclentpipe=%d " + "TOCLIENTPIPE=%d FROMCLIENTPIPE==%d TOSERVERPIPE==%d FROMSERVERPIPE=%d" +#endif + , + FROMCLIENT, TOCLIENTBUF, FROMCLIENTBUF, TOSERVER, + FROMSERVER, TOSERVERBUF, FROMSERVERBUF, TOCLIENT, + (int)inclientbuf, (int)inserverbuf, CLIENTTERM, SERVERTERM, + (unsigned)fromserver, (unsigned)fromclient +#ifdef WITHSPLICE + ,(int)inserverpipe, (int)inclientpipe, + TOCLIENTPIPE, FROMCLIENTPIPE, TOSERVERPIPE, FROMSERVERPIPE +#endif + ); +log(logbuf); +#endif + + if(sleeptime > 0) { + if(sleeptime > (timeo * 1000)){RETURN (92);} + memset(fds, 0, sizeof(fds)); + fds[0].fd = param->clisock; + fds[1].fd = param->remsock; +#ifdef POLLRDHUP + fds[0].events = POLLRDHUP; + fds[1].events = POLLRDHUP; +#endif + so._poll(fds, 2, sleeptime); + sleeptime = 0; + } + if((param->srv->logdumpsrv && (param->statssrv64 > param->srv->logdumpsrv)) || + (param->srv->logdumpcli && (param->statscli64 > param->srv->logdumpcli))) + dolog(param, NULL); + + if(param->version < conf.version){ + if(!param->srv->noforce && (res = (*param->srv->authfunc)(param)) && res != 2) {RETURN(res);} + param->paused = conf.paused; + param->version = conf.version; + } + + if((param->maxtrafin64 && param->statssrv64 >= param->maxtrafin64) || (param->maxtrafout64 && param->statscli64 >= param->maxtrafout64)){ + RETURN (10); + } + + if(inclientbuf && TOSERVER){ +#ifdef WITHLOG +log("send to server from buf"); +#endif + if(!param->nolongdatfilter){ + action = handledatfltcli(param, ¶m->clibuf, (int *)¶m->clibufsize, param->cliinbuf - res, (int *)¶m->cliinbuf); + if(action == HANDLED){ + RETURN(0); + } + if(action != PASS) RETURN(19); + inclientbuf=param->cliinbuf - param->clioffset; + } + if(!inclientbuf){ + param->clioffset = param->cliinbuf = 0; + if(fromclient) TOCLIENTBUF = 1; + } + sasize = sizeof(param->sinsr); + res = so._sendto(param->remsock, (char *)param->clibuf + param->clioffset, (int)MIN(inclientbuf, fromclient), 0, (struct sockaddr*)¶m->sinsr, sasize); + if(res <= 0) TOSERVER = 0; + else { +#ifdef WITHLOG +log("done send to server from buf"); +#endif + param->nwrites++; + param->statscli64 += res; + inclientbuf -= res; + fromclient -= res; + param->clioffset += res; + if(param->clioffset == param->cliinbuf)param->clioffset = param->cliinbuf = 0; + if(param->cliinbuf < param->clibufsize) TOCLIENTBUF = 1; + if(param->bandlimfunc) { + int sl1; + sl1 = (*param->bandlimfunc)(param, 0, res); + if(sl1 > sleeptime) sleeptime = sl1; + } + continue; + } + } + if(inserverbuf && TOCLIENT){ +#ifdef WITHLOG +log("send to client from buf"); +#endif + if(!param->nolongdatfilter){ + action = handledatfltsrv(param, ¶m->srvbuf, (int *)¶m->srvbufsize, param->srvinbuf - res, (int *)¶m->srvinbuf); + if(action == HANDLED){ + RETURN(0); + } + if(action != PASS) RETURN(19); + inserverbuf = param->srvinbuf - param->srvoffset; + } + if(!inserverbuf){ + param->srvinbuf = param->srvoffset = 0; + continue; + } + sasize = sizeof(param->sincr); + res = so._sendto(param->clisock, (char *)param->srvbuf + param->srvoffset, (int)MIN(inserverbuf,fromserver), 0, (struct sockaddr*)¶m->sincr, sasize); + if(res <= 0) TOCLIENT = 0; + else { +#ifdef WITHLOG +log("done send to client from buf"); +#endif + inserverbuf -= res; + fromserver -= res; + param->srvoffset += res; + if(param->srvoffset == param->srvinbuf)param->srvoffset = param->srvinbuf =0; + if(param->srvinbuf < param->srvbufsize) TOSERVERBUF = 1; + continue; + } + } +#ifdef WITHSPLICE + if(usesplice){ + if(inclientpipe && !inclientbuf && FROMCLIENTPIPE && TOSERVER){ +#ifdef WITHLOG +log("send to server from pipe"); +#endif + res = splice(pipecli[0], NULL, param->remsock, NULL, MIN(MAXSPLICE, inclientpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE); + if(res >0) { +#ifdef WITHLOG +log("done send to server from pipe"); +#endif + param->nwrites++; + param->statscli64 += res; + inclientpipe -= res; + fromclient -= res; + if(param->bandlimfunc) { + int sl1; + sl1 = (*param->bandlimfunc)(param, 0, res); + if(sl1 > sleeptime) sleeptime = sl1; + } + continue; + } + else { + FROMCLIENTPIPE = TOSERVER = 0; + } + } + if(inserverpipe && !inserverbuf && FROMSERVERPIPE && TOCLIENT){ +#ifdef WITHLOG +log("send to client from pipe"); +#endif + res = splice(pipesrv[0], NULL, param->clisock, NULL, MIN(MAXSPLICE, inserverpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE); + if(res > 0) { +#ifdef WITHLOG +log("done send to client from pipe"); +#endif + inserverpipe -= res; + fromserver -= res; + if(fromserver)TOSERVERPIPE = 1; + continue; + } + else { + FROMSERVERPIPE = TOCLIENT = 0; + } + } + if(fromclient>inclientpipe && FROMCLIENT && TOCLIENTPIPE){ + int error; + socklen_t len=sizeof(error); +#ifdef WITHLOG +log("read from client to pipe"); +#endif + res = splice(param->clisock, NULL, pipecli[1], NULL, (int)MIN((uint64_t)MAXSPLICE - inclientpipe, (uint64_t)fromclient-inclientpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE); + if(res <= 0) { +#ifdef WITHLOG +log("read failed"); +#endif + FROMCLIENT = TOCLIENTPIPE = 0; + } + else { +#ifdef WITHLOG +log("done read from client to pipe"); +#endif + inclientpipe += res; + if(inclientpipe >= MAXSPLICE) TOCLIENTPIPE = 0; + continue; + } + } + if(fromserver > inserverpipe && FROMSERVER && TOSERVERPIPE){ + int error; + socklen_t len=sizeof(error); +#ifdef WITHLOG +log("read from server to pipe\n"); +#endif + res = splice(param->remsock, NULL, pipesrv[1], NULL, MIN(MAXSPLICE - inclientpipe, fromserver - inserverpipe), SPLICE_F_NONBLOCK|SPLICE_F_MOVE); +#ifdef WITHLOG +log("splice finished\n"); +#endif + if(res <= 0) { + FROMSERVER = TOSERVERPIPE = 0; + } + else { +#ifdef WITHLOG +log("done read from server to pipe\n"); +#endif + param->nreads++; + param->statssrv64 += res; + inserverpipe += res; + if(inserverpipe >= MAXSPLICE) TOSERVERPIPE = 0; + if(param->bandlimfunc) { + int sl1; + sl1 = (*param->bandlimfunc)(param, 1, res); + if(sl1 > sleeptime) sleeptime = sl1; + } + if(param->operation == UDPASSOC && param->srv->singlepacket){ + fromserver = inserverpipe; + FROMSERVER = 0; + } + } + continue; + } + } + else +#endif + { + if(fromclient > inclientbuf && FROMCLIENT && TOCLIENTBUF){ +#ifdef WITHLOG +log("read from client to buf"); +#endif + sasize = sizeof(param->sincr); + res = so._recvfrom(param->clisock, (char *)param->clibuf + param->cliinbuf, (int)MIN((uint64_t)param->clibufsize - param->cliinbuf, fromclient-inclientbuf), 0, (struct sockaddr *)¶m->sincr, &sasize); + if(res <= 0) { + if(!errno)CLIENTTERM = 1; + FROMCLIENT = 0; + } + else { +#ifdef WITHLOG +log("done read from client to buf"); +#endif + inclientbuf += res; + param->cliinbuf += res; + if(param->clibufsize == param->cliinbuf) TOCLIENTBUF = 0; + continue; + } + } + + if(fromserver > inserverbuf && FROMSERVER && TOSERVERBUF){ +#ifdef WITHLOG +log("read from server to buf"); +#endif + sasize = sizeof(param->sinsr); + res = so._recvfrom(param->remsock, (char *)param->srvbuf + param->srvinbuf, (int)MIN((uint64_t)param->srvbufsize - param->srvinbuf, fromserver-inserverbuf), 0, (struct sockaddr *)¶m->sinsr, &sasize); + if(res <= 0) { + if(!errno) SERVERTERM = 1; + FROMSERVER = 0; + } + else { +#ifdef WITHLOG +log("done read from server to buf"); +#endif + param->nreads++; + param->statssrv64 += res; + inserverbuf += res; + param->srvinbuf += res; + if(param->bandlimfunc) { + int sl1; + sl1 = (*param->bandlimfunc)(param, 1, res); + if(sl1 > sleeptime) sleeptime = sl1; + } + if(param->srvbufsize == param->srvinbuf) TOSERVERBUF = 0; + if(param->operation == UDPASSOC && param->srv->singlepacket){ + fromserver = inserverbuf; + FROMSERVER = 0; + } + continue; + } + } + } + for(after = 0; after < 2; after ++){ + fdsc = 0; + if(!after){ + memset(fds, 0, sizeof(fds)); + } + if(!CLIENTTERM){ + if(!after){ + fds[fdsc].fd = param->clisock; + if(fromclient && !FROMCLIENT && (( +#ifdef WITHSPLICE + !usesplice && +#endif + TOCLIENTBUF) +#ifdef WITHSPLICE + || (usesplice) +#endif + )){ +#ifdef WITHLOG +log("wait reading from client"); +#endif + fds[fdsc].events |= (POLLIN +#ifdef POLLRDHUP + |POLLRDHUP +#endif + ); + } + if(!TOCLIENT && (inserverbuf +#ifdef WITHSPLICE + || inserverpipe +#endif + )){ +#ifdef WITHLOG +log("wait writing to client"); +#endif + fds[fdsc].events |= POLLOUT; + } + } + else{ + if(fds[fdsc].revents & (POLLERR|POLLNVAL)) { + CLIENTTERM = 1; + HASERROR |= 1; + } + else if(fds[fdsc].revents & (POLLHUP +#ifdef POLLRDHUP + |POLLRDHUP +#endif + )) { + CLIENTTERM = 1; + } + else { + if(fds[fdsc].revents & POLLIN) { +#ifdef WITHLOG +log("ready to read from client"); +#endif + FROMCLIENT = 1; + } + if(fds[fdsc].revents & POLLOUT) { +#ifdef WITHLOG +log("ready to write to client"); +#endif + TOCLIENT = 1; + } + } + } + fdsc++; + } + if(!SERVERTERM){ + if(!after){ + fds[fdsc].fd = param->remsock; + if(fromserver && !FROMSERVER && (( +#ifdef WITHSPLICE + !usesplice && +#endif + TOSERVERBUF) +#ifdef WITHSPLICE + || (usesplice) +#endif + )){ +#ifdef WITHLOG +log("wait reading from server"); +#endif + fds[fdsc].events |= (POLLIN +#ifdef POLLRDHUP + |POLLRDHUP +#endif + ); + } + if(!TOSERVER && (inclientbuf +#ifdef WITHSPLICE + || inclientpipe +#endif + )){ +#ifdef WITHLOG +log("wait writing from server"); +#endif + fds[fdsc].events |= POLLOUT; + } + } + else{ + if(fds[fdsc].revents & (POLLERR|POLLNVAL)) { +#ifdef WITHLOG +log("poll from server failed"); +#endif + + SERVERTERM = 1; + HASERROR |=2; + } + if(fds[fdsc].revents & (POLLHUP +#ifdef POLLRDHUP + |POLLRDHUP +#endif + )) { +#ifdef WITHLOG +log("server terminated connection"); +#endif + SERVERTERM = 1; + } + else { + if(fds[fdsc].revents & POLLIN) { +#ifdef WITHLOG +log("ready to read from server"); +#endif + FROMSERVER = 1; + } + if(fds[fdsc].revents & POLLOUT) { +#ifdef WITHLOG +log("ready to write to server"); +#endif + TOSERVER = 1; + } + } + } + fdsc++; + } +#ifdef WITHSPLICE + if(usesplice){ + if(fromclient>inclientpipe && !TOCLIENTPIPE && inclientpipe < MAXSPLICE){ + if(!after){ +#ifdef WITHLOG +log("wait writing to client pipe"); +#endif + fds[fdsc].fd = pipecli[1]; + fds[fdsc].events |= POLLOUT; + } + else { + if(fds[fdsc].revents & (POLLHUP|POLLERR|POLLNVAL)){ + RETURN(90); + } + if(fds[fdsc].revents & POLLOUT) { +#ifdef WITHLOG +log("ready to write to client pipe"); +#endif + TOCLIENTPIPE = 1; + } + } + fdsc++; + } + if(inclientpipe && !FROMCLIENTPIPE){ + if(!after){ +#ifdef WITHLOG +log("wait reading from client pipe"); +#endif + fds[fdsc].fd = pipecli[0]; + fds[fdsc].events |= (POLLIN); + } + else { + if(fds[fdsc].revents & (POLLHUP|POLLERR|POLLNVAL)){ + RETURN(90); + } +#ifdef WITHLOG +log("ready reading from client pipe"); +#endif + if(fds[fdsc].revents & POLLIN) FROMCLIENTPIPE = 1; + } + fdsc++; + } + if(fromserver>inserverpipe && !TOSERVERPIPE && inserverpipe < MAXSPLICE){ + if(!after){ +#ifdef WITHLOG +log("wait writing to server pipe"); +#endif + fds[fdsc].fd = pipesrv[1]; + fds[fdsc].events |= POLLOUT; + } + else { + if(fds[fdsc].revents & (POLLHUP|POLLERR|POLLNVAL)){ + RETURN(90); + } +#ifdef WITHLOG +log("ready writing to server pipe"); +#endif + if(fds[fdsc].revents & POLLOUT) TOSERVERPIPE = 1; + } + fdsc++; + } + if(inserverpipe && !FROMSERVERPIPE){ + if(!after){ +#ifdef WITHLOG +log("wait reading from server pipe"); +#endif + fds[fdsc].fd = pipesrv[0]; + fds[fdsc].events |= (POLLIN); + } + else { + if(fds[fdsc].revents & (POLLHUP|POLLERR|POLLNVAL)){ + RETURN(90); + } +#ifdef WITHLOG +log("ready reading from server pipe"); +#endif + if(fds[fdsc].revents & POLLIN) FROMSERVERPIPE = 1; + } + fdsc++; + } + } +#endif + if(!after){ + if(!fdsc) RETURN(90); + + + + +#ifdef WITHLOG +log("entering poll"); +#endif + res = so._poll(fds, fdsc, timeo*1000); +#ifdef WITHLOG +log("leaving poll"); +#endif + if(res < 0){ +#ifdef WITHLOG +log("poll error"); +#endif + if(errno != EAGAIN && errno != EINTR) RETURN(91); + break; + } + if(res < 1){ +#ifdef WITHLOG +log("timeout"); +#endif + RETURN (92); + } + } + } + + } + res = 0; + if(!fromserver) res = 98; + else if(!fromclient) res = 99; + else if((inclientbuf || inserverbuf)) res = HASERROR?93:94; +#ifdef WITHSPLICE + else if(inclientpipe || inserverpipe) res = HASERROR?93:94; +#endif + else if(HASERROR) res = 94+HASERROR; CLEANRET: +#ifdef WITHSPLICE if(pipecli[0] >= 0) close(pipecli[0]); if(pipecli[1] >= 0) close(pipecli[1]); if(pipesrv[0] >= 0) close(pipesrv[0]); if(pipesrv[1] >= 0) close(pipesrv[1]); +#endif return res; } - -#endif - - -int sockmap(struct clientparam * param, int timeo){ - int res=0; - uint64_t sent=0, received=0; - SASIZETYPE sasize; - struct pollfd fds[2]; - int sleeptime = 0, stop = 0; - unsigned minsize; - unsigned bufsize; - FILTER_ACTION action; - int retcode = 0; - - bufsize = SRVBUFSIZE; - - minsize = (param->service == S_UDPPM || param->service == S_TCPPM)? bufsize - 1 : (bufsize>>2); - - fds[0].fd = param->clisock; - fds[1].fd = param->remsock; - - - if(param->cliinbuf == param->clioffset) param->cliinbuf = param->clioffset = 0; - if(param->srvinbuf == param->srvoffset) param->srvinbuf = param->srvoffset = 0; -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "Starting sockets mapping"); -#endif - if(!param->waitclient64){ - if(!param->srvbuf && (!(param->srvbuf=myalloc(bufsize)) || !(param->srvbufsize = bufsize))){ - return (21); - } - } - if(!param->waitserver64){ - if(!param->clibuf && (!(param->clibuf=myalloc(bufsize)) || !(param->clibufsize = bufsize))){ - return (21); - } - } - - action = handlepredatflt(param); - if(action == HANDLED){ - return 0; - } - if(action != PASS) return 19; - if(!param->nolongdatfilter){ - if(param->cliinbuf > param->clioffset){ - action = handledatfltcli(param, ¶m->clibuf, (int *)¶m->clibufsize, param->clioffset, (int *)¶m->cliinbuf); - if(action == HANDLED){ - return 0; - } - if(action != PASS) return 19; - } - if(param->srvinbuf > param->srvoffset){ - action = handledatfltsrv(param, ¶m->srvbuf, (int *)¶m->srvbufsize, param->srvoffset, (int *)¶m->srvinbuf); - if(action == HANDLED){ - return 0; - } - if(action != PASS) return 19; - } - } - - - - while (!stop&&!conf.timetoexit){ - param->cycles++; -#ifdef NOIPV6 - sasize = sizeof(struct sockaddr_in); -#else - sasize = sizeof(struct sockaddr_in6); -#endif - if(param->version < conf.version){ - if((res = (*param->srv->authfunc)(param)) && res != 2 && !param->srv->noforce) {return(res);} - param->paused = conf.paused; - param->version = conf.version; - } - if((param->maxtrafin64 && param->statssrv64 >= param->maxtrafin64) || (param->maxtrafout64 && param->statscli64 >= param->maxtrafout64)){ - return (10); - } - if((param->srv->logdumpsrv && (param->statssrv64 > param->srv->logdumpsrv)) || - (param->srv->logdumpcli && (param->statscli64 > param->srv->logdumpcli))) - (*param->srv->logfunc)(param, NULL); - fds[0].events = fds[1].events = 0; - if(param->srvinbuf > param->srvoffset && !param->waitclient64) { -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "will send to client"); -#endif - fds[0].events |= POLLOUT; - } - if((param->srvbufsize - param->srvinbuf) > minsize && !param->waitclient64 && (!param->waitserver64 ||(received + param->srvinbuf - param->srvoffset < param->waitserver64))) { -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "Will recv from server"); -#endif - fds[1].events |= POLLIN; - } - - if(param->cliinbuf > param->clioffset && !param->waitserver64) { -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "Will send to server"); -#endif - fds[1].events |= POLLOUT; - } - if((param->clibufsize - param->cliinbuf) > minsize && !param->waitserver64 &&(!param->srv->singlepacket || param->service != S_UDPPM) ) { -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "Will recv from client"); -#endif - fds[0].events |= POLLIN; - } - if(!fds[0].events && !fds[1].events) return 666; - res = so._poll(fds, 2, timeo*1000); - if(res < 0){ - if(errno != EAGAIN && errno != EINTR) return 91; - if(errno == EINTR) usleep(SLEEPTIME); - continue; - } - if(res < 1){ - return 92; - } - if( (fds[0].revents & (POLLERR|POLLNVAL -#ifndef WITH_WSAPOLL - |POLLHUP -#endif - )) && !(fds[0].revents & POLLIN)) { - fds[0].revents = 0; - stop = 1; - retcode = 90; - } - if( (fds[1].revents & (POLLERR|POLLNVAL -#ifndef WITH_WSAPOLL - |POLLHUP -#endif - )) && !(fds[1].revents & POLLIN)){ - fds[1].revents = 0; - stop = 1; - retcode = 90; - } - if((fds[0].revents & POLLOUT)){ -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "send to client"); -#endif - if(param->bandlimfunc) { - sleeptime = (*param->bandlimfunc)(param, param->srvinbuf - param->srvoffset, 0); - } - res = so._sendto(param->clisock, (char *)param->srvbuf + param->srvoffset,(!param->waitserver64 || (param->waitserver64 - received) > (param->srvinbuf - param->srvoffset))? param->srvinbuf - param->srvoffset : (int)(param->waitserver64 - received), 0, (struct sockaddr*)¶m->sincr, sasize); - if(res < 0) { - if(errno != EAGAIN && errno != EINTR) return 96; - if(errno == EINTR) usleep(SLEEPTIME); - continue; - } - param->srvoffset += res; - received += res; - if(param->srvoffset == param->srvinbuf) param->srvoffset = param->srvinbuf = 0; - if(param->waitserver64 && param->waitserver64<= received){ - return (98); - } - if(param->service == S_UDPPM && param->srv->singlepacket) { - stop = 1; - } - } - if((fds[1].revents & POLLOUT)){ -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "send to server"); -#endif - if(param->bandlimfunc) { - int sl1; - - sl1 = (*param->bandlimfunc)(param, 0, param->cliinbuf - param->clioffset); - if(sl1 > sleeptime) sleeptime = sl1; - } - res = so._sendto(param->remsock, (char *)param->clibuf + param->clioffset, (!param->waitclient64 || (param->waitclient64 - sent) > (param->cliinbuf - param->clioffset))? param->cliinbuf - param->clioffset : (int)(param->waitclient64 - sent), 0, (struct sockaddr*)¶m->sinsr, sasize); - if(res < 0) { - if(errno != EAGAIN && errno != EINTR) return 97; - if(errno == EINTR) usleep(SLEEPTIME); - continue; - } - param->clioffset += res; - if(param->clioffset == param->cliinbuf) param->clioffset = param->cliinbuf = 0; - sent += res; - param->nwrites++; - param->statscli64 += res; - if(param->waitclient64 && param->waitclient64<= sent) { - return (99); - } - } - if ((fds[0].revents & POLLIN) -#ifdef WITH_WSAPOLL - ||(fds[0].revents & POLLHUP) -#endif - ) { -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "recv from client"); -#endif - res = so._recvfrom(param->clisock, (char *)param->clibuf + param->cliinbuf, param->clibufsize - param->cliinbuf, 0, (struct sockaddr *)¶m->sincr, &sasize); - if (res==0) { - so._shutdown(param->clisock, SHUT_RDWR); - so._closesocket(param->clisock); - fds[0].fd = param->clisock = INVALID_SOCKET; - stop = 1; - } - else { - if (res < 0){ - if(errno != EAGAIN && errno != EINTR) return 94; - if(errno == EINTR) usleep(SLEEPTIME); - continue; - } - param->cliinbuf += res; - if(!param->nolongdatfilter){ - action = handledatfltcli(param, ¶m->clibuf, (int *)¶m->clibufsize, param->cliinbuf - res, (int *)¶m->cliinbuf); - if(action == HANDLED){ - return 0; - } - if(action != PASS) return 19; - } - - } - } - if (!stop && ((fds[1].revents & POLLIN) -#ifdef WITH_WSAPOLL - ||(fds[1].revents & POLLHUP) -#endif - )) { -#ifdef NOIPV6 - struct sockaddr_in sin; -#else - struct sockaddr_in6 sin; -#endif -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "recv from server"); -#endif - - sasize = sizeof(sin); - res = so._recvfrom(param->remsock, (char *)param->srvbuf + param->srvinbuf, param->srvbufsize - param->srvinbuf, 0, (struct sockaddr *)&sin, &sasize); - if (res==0) { - so._shutdown(param->remsock, SHUT_RDWR); - so._closesocket(param->remsock); - fds[1].fd = param->remsock = INVALID_SOCKET; - stop = 2; - } - else { - if (res < 0){ - if(errno != EAGAIN && errno != EINTR) return 93; - if(errno == EINTR) usleep(SLEEPTIME); - continue; - } - param->srvinbuf += res; - param->nreads++; - param->statssrv64 += res; - if(!param->nolongdatfilter){ - action = handledatfltsrv(param, ¶m->srvbuf, (int *)¶m->srvbufsize, param->srvinbuf - res, (int *)¶m->srvinbuf); - if(action == HANDLED){ - return 0; - } - if(action != PASS) return 19; - } - - } - } - - if(sleeptime > 0) { - if(sleeptime > (timeo * 1000)){return (95);} - usleep(sleeptime * SLEEPTIME); - sleeptime = 0; - } - } - if(conf.timetoexit) return 89; -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "finished with mapping"); -#endif - while(!param->waitclient64 && param->srvinbuf > param->srvoffset && param->clisock != INVALID_SOCKET){ -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "flushing buffer to client"); -#endif - res = socksendto(param->clisock, (struct sockaddr *)¶m->sincr, param->srvbuf + param->srvoffset, param->srvinbuf - param->srvoffset, conf.timeouts[STRING_S] * 1000); - if(res > 0){ - param->srvoffset += res; - param->statssrv64 += res; - if(param->srvoffset == param->srvinbuf) param->srvoffset = param->srvinbuf = 0; - } - else break; - } - while(!param->waitserver64 && param->cliinbuf > param->clioffset && param->remsock != INVALID_SOCKET){ -#if DEBUGLEVEL > 2 -(*param->srv->logfunc)(param, "flushing buffer to server"); -#endif - res = socksendto(param->remsock, (struct sockaddr *)¶m->sinsr, param->clibuf + param->clioffset, param->cliinbuf - param->clioffset, conf.timeouts[STRING_S] * 1000); - if(res > 0){ - param->clioffset += res; - param->statscli64 += res; - if(param->cliinbuf == param->clioffset) param->cliinbuf = param->clioffset = 0; - } - else break; - } - return retcode; -} diff --git a/src/socks.c b/src/socks.c index 97f58d4..9b59a30 100644 --- a/src/socks.c +++ b/src/socks.c @@ -448,7 +448,7 @@ fflush(stderr); else myinet_ntop(*SAFAMILY(¶m->req), SAADDR(¶m->req), (char *)buf + strlen((char *)buf), 64); sprintf((char *)buf+strlen((char *)buf), ":%hu", ntohs(*SAPORT(¶m->req))); - (*param->srv->logfunc)(param, buf); + dolog(param, buf); myfree(buf); } freeparam(param); diff --git a/src/structures.h b/src/structures.h index 4df9e07..6e41a03 100644 --- a/src/structures.h +++ b/src/structures.h @@ -740,7 +740,7 @@ struct pluginlink { int (*dobuf2)(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format); int (*scanaddr)(const unsigned char *s, unsigned long * ip, unsigned long * mask); unsigned long (*getip46)(int family, unsigned char *name, struct sockaddr *sa); - int (*sockmap)(struct clientparam * param, int timeo); + int (*sockmap)(struct clientparam * param, int timeo, int usesplice); int (*ACLMatches)(struct ace* acentry, struct clientparam * param); int (*alwaysauth)(struct clientparam * param); int (*checkACL)(struct clientparam * param); diff --git a/src/tcppm.c b/src/tcppm.c index d39fd54..043807a 100644 --- a/src/tcppm.c +++ b/src/tcppm.c @@ -23,7 +23,7 @@ void * tcppmchild(struct clientparam* param) { RETURN (mapsocket(param, conf.timeouts[CONNECTION_L])); CLEANRET: - (*param->srv->logfunc)(param, param->hostname); + dolog(param, param->hostname); freeparam(param); return (NULL); } diff --git a/src/udppm.c b/src/udppm.c index 074b923..d4057e2 100644 --- a/src/udppm.c +++ b/src/udppm.c @@ -81,7 +81,7 @@ void * udppmchild(struct clientparam* param) { #ifdef _WIN32 ioctlsocket(param->remsock, FIONBIO, &ul); #else - fcntl(param->remsock,F_SETFL,O_NONBLOCK); + fcntl(param->remsock,F_SETFL,O_NONBLOCK | fcntl(param->remsock,F_GETFL)); #endif memcpy(¶m->sinsr, ¶m->req, sizeof(param->req)); @@ -91,7 +91,7 @@ void * udppmchild(struct clientparam* param) { param->srv->fds.events = POLLIN; } - param->res = sockmap(param, conf.timeouts[(param->srv->singlepacket)?SINGLEBYTE_L:STRING_L]); + param->res = mapsocket(param, conf.timeouts[(param->srv->singlepacket)?SINGLEBYTE_L:STRING_L]); if(!param->srv->singlepacket) { param->srv->fds.events = POLLIN; } @@ -99,7 +99,7 @@ void * udppmchild(struct clientparam* param) { CLEANRET: if(buf)myfree(buf); - (*param->srv->logfunc)(param, NULL); + dolog(param, NULL); #ifndef _WIN32 param->clisock = INVALID_SOCKET; #endif diff --git a/src/webadmin.c b/src/webadmin.c index 4ab39bf..8f29481 100644 --- a/src/webadmin.c +++ b/src/webadmin.c @@ -576,7 +576,7 @@ CLEANRET: printstr(&pp, NULL); if(buf) myfree(buf); - (*param->srv->logfunc)(param, (unsigned char *)req); + dolog(param, (unsigned char *)req); if(req)myfree(req); freeparam(param); return (NULL);