Просмотр исходного кода

intermediate commit for logging

z3APA3A 5 лет назад
Родитель
Сommit
48b330da7c
7 измененных файлов с 569 добавлено и 293 удалено
  1. 2 1
      src/3proxy.c
  2. 0 1
      src/common.c
  3. 29 36
      src/conf.c
  4. 403 76
      src/log.c
  5. 4 3
      src/proxy.h
  6. 121 171
      src/proxymain.c
  7. 10 5
      src/structures.h

+ 2 - 1
src/3proxy.c

@@ -189,7 +189,7 @@ void dumpcounters(struct trafcount *tlin, int counterd){
 	if(cheader.updated && conf.countertype && timechanged(cheader.updated, conf.time, conf.countertype)){
 		FILE * cfp;
 				
-		cfp = fopen((char *)dologname(tmpbuf, (unsigned char *)conf.counterfile, NULL, conf.countertype, cheader.updated), "w");
+		cfp = fopen((char *)dologname(tmpbuf, sizeof(tmpbuf), (unsigned char *)conf.counterfile, NULL, conf.countertype, cheader.updated), "w");
 		if(cfp){
 			for(tl = tlin; cfp && tl; tl = tl->next){
 				if(tl->type >= conf.countertype)
@@ -229,6 +229,7 @@ void cyclestep(void){
  for(;;){
 	usleep(SLEEPTIME*999);
 	
+//	flushlogs();
 	conf.time = time(0);
 	if(conf.needreload) {
 		doschedule();

+ 0 - 1
src/common.c

@@ -522,7 +522,6 @@ unsigned long getip(unsigned char *name){
 	}
 	if((tmpresolv=resolvfunc)){
 		if((*tmpresolv)(AF_INET, name, (unsigned char *)&retval)) return retval;
-		if(conf.demanddialprog) system(conf.demanddialprog);
 		return (*tmpresolv)(AF_INET, name, (unsigned char *)&retval)?retval:0;
 	}
 #if !defined(_WIN32) && !defined(GETHOSTBYNAME_R)

+ 29 - 36
src/conf.c

@@ -552,12 +552,6 @@ static int h_nsrecord(int argc, unsigned char **argv){
 	return 0;
 }
 
-static int h_dialer(int argc, unsigned char **argv){
-	if(conf.demanddialprog) myfree(conf.demanddialprog);
-	conf.demanddialprog = mystrdup((char *)argv[1]);
-	return 0;
-}
-
 static int h_system(int argc, unsigned char **argv){
   int res;
 
@@ -1439,36 +1433,35 @@ struct commands commandhandlers[]={
 	{commandhandlers+28, "nscache", h_nscache, 2, 2},
 	{commandhandlers+29, "nscache6", h_nscache6, 2, 2},
 	{commandhandlers+30, "nsrecord", h_nsrecord, 3, 3},
-	{commandhandlers+31, "dialer", h_dialer, 2, 2},
-	{commandhandlers+32, "system", h_system, 2, 2},
-	{commandhandlers+33, "pidfile", h_pidfile, 2, 2},
-	{commandhandlers+34, "monitor", h_monitor, 2, 2},
-	{commandhandlers+35, "parent", h_parent, 5, 0},
-	{commandhandlers+36, "allow", h_ace, 1, 0},
-	{commandhandlers+37, "deny", h_ace, 1, 0},
-	{commandhandlers+38, "redirect", h_ace, 3, 0},
-	{commandhandlers+39, "bandlimin", h_ace, 2, 0},
-	{commandhandlers+40, "bandlimout", h_ace, 2, 0},
-	{commandhandlers+41, "nobandlimin", h_ace, 1, 0},
-	{commandhandlers+42, "nobandlimout", h_ace, 1, 0},
-	{commandhandlers+43, "countin", h_ace, 4, 0},
-	{commandhandlers+44, "nocountin", h_ace, 1, 0},
-	{commandhandlers+45, "countout", h_ace, 4, 0},
-	{commandhandlers+46, "nocountout", h_ace, 1, 0},
-	{commandhandlers+47, "connlim", h_ace, 4, 0},
-	{commandhandlers+48, "noconnlim", h_ace, 1, 0},
-	{commandhandlers+49, "plugin", h_plugin, 3, 0},
-	{commandhandlers+50, "logdump", h_logdump, 2, 3},
-	{commandhandlers+51, "filtermaxsize", h_filtermaxsize, 2, 2},
-	{commandhandlers+52, "nolog", h_nolog, 1, 1},
-	{commandhandlers+53, "weight", h_nolog, 2, 2},
-	{commandhandlers+54, "authcache", h_authcache, 2, 3},
-	{commandhandlers+55, "smtpp", h_proxy, 1, 0},
-	{commandhandlers+56, "delimchar",h_delimchar, 2, 2},
-	{commandhandlers+57, "authnserver", h_authnserver, 2, 2},
-	{commandhandlers+58, "stacksize", h_stacksize, 2, 2},
-	{commandhandlers+59, "force", h_force, 1, 1},
-	{commandhandlers+60, "noforce", h_noforce, 1, 1},
+	{commandhandlers+31, "system", h_system, 2, 2},
+	{commandhandlers+32, "pidfile", h_pidfile, 2, 2},
+	{commandhandlers+33, "monitor", h_monitor, 2, 2},
+	{commandhandlers+34, "parent", h_parent, 5, 0},
+	{commandhandlers+35, "allow", h_ace, 1, 0},
+	{commandhandlers+36, "deny", h_ace, 1, 0},
+	{commandhandlers+37, "redirect", h_ace, 3, 0},
+	{commandhandlers+38, "bandlimin", h_ace, 2, 0},
+	{commandhandlers+39, "bandlimout", h_ace, 2, 0},
+	{commandhandlers+40, "nobandlimin", h_ace, 1, 0},
+	{commandhandlers+41, "nobandlimout", h_ace, 1, 0},
+	{commandhandlers+42, "countin", h_ace, 4, 0},
+	{commandhandlers+43, "nocountin", h_ace, 1, 0},
+	{commandhandlers+44, "countout", h_ace, 4, 0},
+	{commandhandlers+45, "nocountout", h_ace, 1, 0},
+	{commandhandlers+46, "connlim", h_ace, 4, 0},
+	{commandhandlers+47, "noconnlim", h_ace, 1, 0},
+	{commandhandlers+48, "plugin", h_plugin, 3, 0},
+	{commandhandlers+49, "logdump", h_logdump, 2, 3},
+	{commandhandlers+50, "filtermaxsize", h_filtermaxsize, 2, 2},
+	{commandhandlers+51, "nolog", h_nolog, 1, 1},
+	{commandhandlers+52, "weight", h_nolog, 2, 2},
+	{commandhandlers+53, "authcache", h_authcache, 2, 3},
+	{commandhandlers+54, "smtpp", h_proxy, 1, 0},
+	{commandhandlers+55, "delimchar",h_delimchar, 2, 2},
+	{commandhandlers+56, "authnserver", h_authnserver, 2, 2},
+	{commandhandlers+57, "stacksize", h_stacksize, 2, 2},
+	{commandhandlers+58, "force", h_force, 1, 1},
+	{commandhandlers+59, "noforce", h_noforce, 1, 1},
 #ifndef NORADIUS
 	{commandhandlers+61, "radius", h_radius, 3, 0},
 #endif

+ 403 - 76
src/log.c

@@ -8,25 +8,24 @@
 
 #include "proxy.h"
 pthread_mutex_t log_mutex;
-/*
 #ifdef _WIN32
 HANDLE log_sem;
 #else
 sem_t log_sem;
 #endif
-*/
-#define MAXLOG 64
-#define MAXLOGGERS 64
-#define LOGBUFSIZE 4096
+#define MAXLOG 1024
+#define EVENTSIZE (4096 - sizeof(void *))
+#define LOGBUFSIZE (EVENTSIZE - sizeof(struct logevent))
+#define MAX_SEM_COUNT 256
 
-struct logqueue {
-	int event;
-	int inbuf;
-	char buf[LOGBUFSIZE];
-} logq[MAXLOG];
+typedef enum {
+	REGISTER,
+	UNREGISTER,
+	LOG,
+	FLUSH,
+	FREEPARAM
+} EVENTTYPE;
 
-int loghead=0;
-int logtail=0;
 
 
 struct clientparam logparam;
@@ -36,18 +35,39 @@ struct LOGGER;
 
 void(*prelog)(struct clientparam * param) = NULL;
 
+
+struct logevent {
+	struct logevent *next;
+	struct LOGGER *log;
+	EVENTTYPE event;
+	int inbuf;
+	struct clientparam *param;
+	char * logstring;
+	char buf[1];
+} *logtail=NULL, *loghead=NULL;
+
+
+
+static void delayflushlogs(void);
+static void delayunregisterlog (struct LOGGER * log);
+static void delayregisterlog (struct LOGGER * log);
+static void delaydolog(struct logevent *evt);
+static void delayfreeparam(struct clientparam *param);
+
+void logpush(struct logevent *evt);
+
 #ifdef WITHMAIN
 #define HAVERADIUS 0
 #define HAVESQL 0
 #else
-int raddobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s);
+int raddobuf(struct clientparam * param, unsigned char * buf, int bufsize, const unsigned char *s);
 void logradius(const char * buf, int len, struct LOGGER *logger);
 #define HAVERADIUS 1
 
 #ifndef NOODBC
 #define HAVESQL 1
 static int sqlinit(struct LOGGER *logger);
-static int sqldobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s);
+static int sqldobuf(struct clientparam * param, unsigned char * buf, int bufsize, const unsigned char *s);
 static void sqllog(const char * buf, int len, struct LOGGER *logger);
 static void sqlrotate(struct LOGGER *logger);
 static void sqlclose(struct LOGGER *logger);
@@ -67,24 +87,24 @@ static void syslogclose(struct LOGGER *logger);
 #endif
 
 static int stdloginit(struct LOGGER *logger);
-int stddobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s);
+int stddobuf(struct clientparam * param, unsigned char * buf, int bufsize, const unsigned char *s);
 static void stdlog(const char * buf, int len, struct LOGGER *logger);
 static void stdlogrotate(struct LOGGER *logger);
 static void stdlogclose(struct LOGGER *logger);
-
+static void stdlogflush(struct LOGGER *logger);
 
 
 struct LOGFUNC stdlogfuncs[] = {
 #if HAVESYSLOG > 0
-		{stdlogfuncs+1, sysloginit, stddobuf, logsyslog, syslogrotate, syslogclose, "@"},
+		{stdlogfuncs+1, sysloginit, stddobuf, logsyslog, syslogrotate, NULL, syslogclose, "@"},
 #endif
 #if HAVERADIUS > 0
-		{stdlogfuncs+1+HAVESYSLOG, NULL, raddobuf, logradius, NULL, NULL, "radius"},
+		{stdlogfuncs+1+HAVESYSLOG, NULL, raddobuf, logradius, NULL, NULL, NULL, "radius"},
 #endif
 #if HAVESQL > 0
-		{stdlogfuncs+1+HAVESYSLOG+HAVERADIUS, sqlinit, sqldobuf, sqllog, sqlrotate, sqlclose, "&"},
+		{stdlogfuncs+1+HAVESYSLOG+HAVERADIUS, sqlinit, sqldobuf, sqllog, sqlrotate, NULL, sqlclose, "&"},
 #endif
-		{NULL, stdloginit, stddobuf, stdlog, stdlogrotate, stdlogclose, ""}
+		{NULL, stdloginit, stddobuf, stdlog, stdlogrotate, stdlogflush, stdlogclose, ""}
 	     };
 
 struct LOGFUNC *logfuncs = stdlogfuncs;
@@ -93,43 +113,128 @@ struct stdlogdata{
 	FILE *fp;
 } errld;
 
-struct LOGGER errlogger = {NULL, "stderr", &errld, stdlogfuncs+1+HAVESYSLOG+HAVERADIUS+HAVESQL, 0, 0, 1};
+struct LOGGER errlogger = {NULL, NULL, "stderr", &errld, stdlogfuncs+1+HAVESYSLOG+HAVERADIUS+HAVESQL, 0, 0, 1};
 
 struct LOGGER *loggers = &errlogger;
 
-struct LOGGER * registerlog(const char * logstring, int logtype){
+
+
+static void delayflushlogs(void){
 	struct LOGGER *log;
+	for(log = loggers; log; log=log->next){
+		if(log->logfunc && log->logfunc->flush)log->logfunc->flush(log);
+	}
+}
+
+
+
+void flushlogs(void){
+	struct logevent * evt;
+	evt = malloc(sizeof(struct logevent));
+	evt->event = FLUSH;
+	logpush(evt);
+}
+
+
+void delayregisterlog(struct LOGGER *log){
 	struct LOGFUNC *funcs;
 
+
+printf("delayregisterlog %s\n", log->selector);
+fflush(stdout);
+	if(log->logfunc) return;
+	for(funcs = logfuncs; funcs; funcs=funcs->next){
+		if(!strncmp(log->selector, funcs->prefix, strlen(funcs->prefix))){
+			if(funcs->init && funcs->init(log)) break;
+			log->logfunc = funcs;
+printf("new log initialised\n");
+fflush(stdout);
+			return;
+		}
+	}
+}
+
+
+struct LOGGER * registerlog(const char * logstring, int logtype){
+	struct LOGGER *log;
+
+printf("registerlog %s\n", logstring);
+fflush(stdout);
 	if(!logstring || !strcmp(logstring, "NUL") || !strcmp(logstring, "/dev/null")) return NULL;
+	pthread_mutex_lock(&log_mutex);
 	for(log = loggers; log; log=log->next){
 		if(!strcmp(logstring, log->selector)){
 			if(logtype >= 0) log->rotate = logtype;
 			log->registered++;
+printf("log registered\n");
+fflush(stdout);
+			pthread_mutex_unlock(&log_mutex);
 			return log;
 		}
 	}
 	log = malloc(sizeof(struct LOGGER));
-	if(!log) return NULL;
+	if(!log) {
+		pthread_mutex_unlock(&log_mutex);
+		return NULL;
+	}
 	memset (log, 0, sizeof(struct LOGGER));
 	log->selector = mystrdup(logstring);
 	if(log->selector){
+		struct logevent *evt;
 		if(logtype)log->rotate = logtype;
-		for(funcs = logfuncs; funcs; funcs=funcs->next){
-			if(!strncmp(logstring, funcs->prefix, strlen(funcs->prefix))){
-				if(funcs->init && funcs->init(log)) break;
-				log->registered++;
-				return log;
-			}
-		}
-		myfree(log->selector);
+		log->registered++;
+		log->next = loggers;
+		if (log->next)log->next->prev = log;
+		loggers = log;
+		pthread_mutex_unlock(&log_mutex);
+
+		evt = malloc(sizeof(struct logevent));
+		evt->event = REGISTER;
+		evt->log = log;
+		logpush(evt);
+printf("new log registered\n");
+fflush(stdout);
+		return log;
 	}
+	pthread_mutex_unlock(&log_mutex);
 	myfree(log);
 	return NULL;
 }
 
+static void delayunregisterlog (struct LOGGER * log){
+	if(log){
+		pthread_mutex_lock(&log_mutex);
+		log->registered--;
+		if(!log->registered){
+			if(log->prev)log->prev->next = log->next;
+			else loggers = log->next;
+			if(log->next)log->next->prev = log->prev;
+			pthread_mutex_unlock(&log_mutex);
+
+			if(log->logfunc){
+				if(log->logfunc->flush) log->logfunc->flush(log);
+				if(log->logfunc->close) log->logfunc->close(log);
+			}
+			myfree(log->selector);
+			myfree(log);
+printf("log closed\n");
+fflush(stdout);
+		}
+		else pthread_mutex_unlock(&log_mutex);
+
+printf("log unregistered\n");
+fflush(stdout);
+	}
+}
+
 void unregisterlog (struct LOGGER * log){
-	if(log)log->registered--;
+	struct logevent *evt;
+
+	if(!log) return;
+	evt = malloc(sizeof(struct logevent));
+	evt->event = UNREGISTER;
+	evt->log = log;
+	logpush(evt);
 }
 
 #ifdef _WIN32
@@ -138,20 +243,102 @@ DWORD WINAPI logthreadfunc(LPVOID p) {
 void * logthreadfunc (void *p) {
 #endif
 
+printf("enter logthreadfunc\n");
+fflush(stdout);
+
+
+
+	for(;;){
+		struct logevent *evt;
+#ifdef _WIN32
+		WaitForSingleObject(log_sem, INFINITE);
+#else
+		sem_wait(&log_sem);
+#endif
+printf("got semaphore\n");
+fflush(stdout);
+
+		while(loghead){
+			pthread_mutex_lock(&log_mutex);
+			evt = loghead;
+			loghead = evt->next;
+			if(!loghead)logtail = NULL;
+			pthread_mutex_unlock(&log_mutex);
+			switch(evt->event){
+				case REGISTER:
+printf("got register\n");
+fflush(stdout);
+					delayregisterlog(evt->log);
+					break;
+				case UNREGISTER:
+printf("got unregister\n");
+fflush(stdout);
+					delayunregisterlog(evt->log);
+					break;
+				case FLUSH:
+printf("got flush\n");
+fflush(stdout);
+//					delayflushlogs();
+					break;
+				case LOG:
+printf("got log\n");
+fflush(stdout);
+					delaydolog(evt);
+					break;
+				case FREEPARAM:
+printf("got freeparam\n");
+fflush(stdout);
+					delayfreeparam(evt->param);
+					break;
+
+				default:
+					break;
+			}
+			myfree(evt);
+		}
+
+
+
+	}
+
+printf("finish logthreadfunc\n");
+fflush(stdout);
+	return 0;
+}
+
+
+
+void logpush(struct logevent *evt){
+printf("logpush\n");
+fflush(stdout);
+	pthread_mutex_lock(&log_mutex);
+	if(logtail) logtail->next = evt;
+	logtail = evt;
+	evt->next = NULL;
+	if(!loghead)loghead = evt;
+	
+	pthread_mutex_unlock(&log_mutex);
+printf("sending post\n");
+fflush(stdout);
+#ifdef _WIN32
+	ReleaseSemaphore(log_sem, 1, NULL);
+#else
+	sem_post(&log_sem);
+#endif
 }
 
 void initlog(void){
 	pthread_t thread;
 
+printf("initlog\n");
+fflush(stdout);
 	srvinit(&logsrv, &logparam);
 	pthread_mutex_init(&log_mutex, NULL);
 	errld.fp = stdout;
-/*
 #ifdef _WIN32
 	{
 		HANDLE h;
-		log_sem = CreateSemaphore(NULL, 0, MAX_SEM_COUNT, NULL);
-		sem_init(&log_sem, 0, 0);
+		if(!(log_sem = CreateSemaphore(NULL, 0, MAX_SEM_COUNT, NULL))) exit(11);
 #ifndef _WINCE
 		h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, 65536, (void *)logthreadfunc, NULL, 0, &thread);
 #else
@@ -168,39 +355,94 @@ void initlog(void){
 	{
 		pthread_attr_t pa;
 		pthread_attr_init(&pa);
+
 		pthread_attr_setstacksize(&pa,PTHREAD_STACK_MIN + 1024*256);
 		pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED);
 
+		if(sem_init(&log_sem, 0, 0)) exit(11);
 		if(pthread_create(&thread, &pa, logthreadfunc, (void *)newparam)) exit(10);
 	}
 #endif
-*/
+}
+
+static void delaydolog(struct logevent *evt){
+
+printf("delaylog\n");
+fflush(stdout);
+	if(!evt->log->logfunc || !evt->log->logfunc->log) return;
+	if(evt->inbuf){
+printf("havebuffer\n");
+fflush(stdout);
+		evt->log->logfunc->log(evt->buf, evt->inbuf, evt->log);
+	}
+	else if(evt->param && evt->log->logfunc->dobuf){
+		char buf[LOGBUFSIZE];
+
+printf("haveparam\n");
+fflush(stdout);
+		evt->log->logfunc->log(buf, evt->log->logfunc->dobuf(evt->param, buf, LOGBUFSIZE, evt->logstring), evt->log);
+	}
 }
 
 void dolog(struct clientparam * param, const unsigned char *s){
 	static int init = 0;
 
-/* TODO: dobuf */
-/* TODO: spooling */
+printf("dolog\n");
+fflush(stdout);
 	if(!param || !param->srv){
 		stdlog(s, strlen(s), &errlogger);
+		return;
 	}
-	else if(!param->nolog && param->srv->logtarget){
-		if(prelog)prelog(param);
-		if(param->srv->log && param->srv->log->logfunc && param->srv->log->logfunc->log){
-			char buf[LOGBUFSIZE];
-			int inbuf = 0;
-
-
-/*
-	int (*dobuf)(struct clientparam * param, unsigned char * buf, const unsigned char *s);
-	int (*log)(const char * buf, int len, struct LOGGER *logger);
-*/
+	if(prelog)prelog(param);
+	if(!param->nolog && param->srv->log) {
+		struct logevent *evt;
+
+		if(!param->srv->log->logfunc) {
+			int inbuf=0, len =0;
+			
+			if(!(evt = malloc(sizeof(struct logevent) + param->hostname?strlen(param->hostname)+1:0 + s? strlen(s)+1:0 + param->username?strlen(param->username):0))) return;
+			evt->inbuf = 0;
+			evt->param=param;
+			evt->logstring = NULL;
+			if(s){
+				len = strlen(s);
+				memcpy(evt->buf,s, len);
+				inbuf+=len;
+				evt->logstring = evt->buf;
+			}
+			if(param->hostname){
+				len = strlen(param->hostname);
+				memcpy(evt->buf+inbuf,param->hostname, len);
+				param->hostname = evt->buf + inbuf;
+				inbuf+=len;
+			}
+			if(param->username){
+				len = strlen(param->username);
+				memcpy(evt->buf+inbuf,param->username, len);
+				param->username = evt->buf + inbuf;
+				inbuf+=len;
+			}
+			evt->event = LOG;
+			evt->log = param->srv->log;
+			logpush(evt);
+		}
+		else if (param->srv->log->logfunc->log){
+
+printf("havelog\n");
+fflush(stdout);
+			if(!(evt = malloc(param->srv->log->logfunc->dobuf?EVENTSIZE:sizeof(struct logevent)))) return;
+			evt->inbuf = 0;
+			evt->param = NULL;
+			evt->logstring = NULL;
+		
 			if(param->srv->log->logfunc->dobuf){
-				param->srv->log->logfunc->dobuf(param, buf, s);
+				evt->inbuf = param->srv->log->logfunc->dobuf(param, evt->buf, LOGBUFSIZE, s);
 			}
-
-			param->srv->log->logfunc->log(buf, inbuf, param->srv->log);
+			evt->event = LOG;
+			evt->log = param->srv->log;
+printf("pushing event\n");
+fflush(stdout);
+			logpush(evt);
 		}
 	}
 	if(param->trafcountfunc)(*param->trafcountfunc)(param);
@@ -208,6 +450,73 @@ void dolog(struct clientparam * param, const unsigned char *s){
 }
 
 
+static void delayfreeparam(struct clientparam * param) {
+	if(param->res == 2) return;
+	if(param->ctrlsocksrv != INVALID_SOCKET && param->ctrlsocksrv != param->remsock) {
+		so._shutdown(param->ctrlsocksrv, SHUT_RDWR);
+		so._closesocket(param->ctrlsocksrv);
+	}
+	if(param->ctrlsock != INVALID_SOCKET && param->ctrlsock != param->clisock) {
+		so._shutdown(param->ctrlsock, SHUT_RDWR);
+		so._closesocket(param->ctrlsock);
+	}
+	if(param->remsock != INVALID_SOCKET) {
+		so._shutdown(param->remsock, SHUT_RDWR);
+		so._closesocket(param->remsock);
+	}
+	if(param->clisock != INVALID_SOCKET) {
+		so._shutdown(param->clisock, SHUT_RDWR);
+		so._closesocket(param->clisock);
+	}
+	myfree(param->clibuf);
+	myfree(param->srvbuf);
+	if(param->datfilterssrv) myfree(param->datfilterssrv);
+#ifndef STDMAIN
+	if(param->reqfilters) myfree(param->reqfilters);
+	if(param->hdrfilterscli) myfree(param->hdrfilterscli);
+	if(param->hdrfilterssrv) myfree(param->hdrfilterssrv);
+	if(param->predatfilters) myfree(param->predatfilters);
+	if(param->datfilterscli) myfree(param->datfilterscli);
+	if(param->filters){
+		if(param->nfilters)while(param->nfilters--){
+			if(param->filters[param->nfilters].filter->filter_clear)
+				(*param->filters[param->nfilters].filter->filter_clear)(param->filters[param->nfilters].data);
+		}
+		myfree(param->filters);
+	}
+	if(conf.connlimiter && (param->res != 95 || param->remsock != INVALID_SOCKET)) stopconnlims(param);
+#endif
+	if(param->srv){
+		pthread_mutex_lock(&param->srv->counter_mutex);
+		if(param->prev){
+			param->prev->next = param->next;
+		}
+		else
+			param->srv->child = param->next;
+		if(param->next){
+			param->next->prev = param->prev;
+		}
+		(param->srv->childcount)--;
+		if(param->srv->service == S_ZOMBIE && !param->srv->child)srvpostfree(param->srv);
+		pthread_mutex_unlock(&param->srv->counter_mutex);
+	}
+	if(param->hostname) myfree(param->hostname);
+	if(param->username) myfree(param->username);
+	if(param->password) myfree(param->password);
+	if(param->extusername) myfree(param->extusername);
+	if(param->extpassword) myfree(param->extpassword);
+	myfree(param);
+}
+
+void freeparam(struct clientparam * param) {
+	struct logevent *evt;
+
+	evt = malloc(sizeof(struct logevent));
+	evt->event = FREEPARAM;
+	evt->param = param;
+	logpush(evt);
+}
+
 void clearstat(struct clientparam * param) {
 
 #ifdef _WIN32
@@ -235,7 +544,7 @@ char months[12][4] = {
 	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 };
 
-unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t) {
+unsigned char * dologname (unsigned char *buf,  int bufsize, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t) {
 	struct tm *ts;
 
 	ts = localtime(&t);
@@ -243,7 +552,7 @@ unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsign
 		struct clientparam fakecli;
 
 		memset(&fakecli, 0, sizeof(fakecli));
-		dobuf2(&fakecli, buf, NULL, NULL, ts, (char *)name);
+		dobuf2(&fakecli, buf, bufsize - strlen(ext), NULL, NULL, ts, (char *)name);
 	}
 	else switch(lt){
 		case NONE:
@@ -279,7 +588,7 @@ unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsign
 	return buf;
 }
 
-int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format){
+int dobuf2(struct clientparam * param, unsigned char * buf, int bufsize, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format){
 	int i, j;
 	int len;
 	time_t sec;
@@ -314,7 +623,7 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
 
 	delay = param->time_start?((unsigned) ((sec - param->time_start))*1000 + msec) - param->msec_start : 0;
 	*buf = 0;
-	for(i=0, j=0; format[j] && i < (LOGBUFSIZE-70); j++){
+	for(i=0, j=0; format[j] && i < (bufsize-70); j++){
 		if(format[j] == '%' && format[j+1]){
 			j++;
 			switch(format[j]){
@@ -376,7 +685,7 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
 				 break;
 				case 'U':
 				 if(param->username && *param->username){
-					for(len = 0; i< (LOGBUFSIZE - 3) && param->username[len]; len++){
+					for(len = 0; i< (bufsize - 3) && param->username[len]; len++){
 					 buf[i] = param->username[len];
 					 if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
 					 if(doublec && strchr((char *)doublec, buf[i])) {
@@ -392,7 +701,7 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
 				 break;
 				case 'n':
 					len = param->hostname? (int)strlen((char *)param->hostname) : 0;
-					if (len > 0 && !strchr((char *)param->hostname, ':')) for(len = 0; param->hostname[len] && i < (LOGBUFSIZE-3); len++, i++){
+					if (len > 0 && !strchr((char *)param->hostname, ':')) for(len = 0; param->hostname[len] && i < (bufsize-3); len++, i++){
 						buf[i] = param->hostname[len];
 					 	if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
 						if(doublec && strchr((char *)doublec, buf[i])) {
@@ -421,7 +730,7 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
 				 break;
 				case 'T':
 				 if(s){
-					for(len = 0; i < (LOGBUFSIZE-3) && s[len]; len++){
+					for(len = 0; i < (bufsize-3) && s[len]; len++){
 					 buf[i] = s[len];
 					 if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
 					 if(doublec && strchr((char *)doublec, buf[i])) {
@@ -505,7 +814,7 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
 								while(isspace(s[len+1]))len++;
 								if(k == pmin) continue;
 							}
-							if(k>=pmin && k<=pmax && i < (LOGBUFSIZE-3)) {
+							if(k>=pmin && k<=pmax && i < (bufsize-3)) {
 								buf[i] = s[len];
 								if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
 								if(doublec && strchr((char *)doublec, buf[i])) {
@@ -528,7 +837,7 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
 	return i;
 }
 
-int dobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec){
+int dobuf(struct clientparam * param, unsigned char * buf, int bufsize, const unsigned char *s, const unsigned char * doublec){
 	struct tm* tm;
 	int i;
 	char * format;
@@ -539,7 +848,7 @@ int dobuf(struct clientparam * param, unsigned char * buf, const unsigned char *
 	format = param->srv->logformat?(char *)param->srv->logformat : DEFLOGFORMAT;
 	tm = (*format == 'G' || *format == 'g')?
 		gmtime(&t) : localtime(&t);
-	i = dobuf2(param, buf, s, doublec, tm, format + 1);
+	i = dobuf2(param, buf, bufsize, s, doublec, tm, format + 1);
 	return i;
 }
 
@@ -547,10 +856,13 @@ int dobuf(struct clientparam * param, unsigned char * buf, const unsigned char *
 static int stdloginit(struct LOGGER *logger){
 	char tmpbuf[1024];
 	struct stdlogdata *lp;
+
+printf("stdloginit %s\n", logger->selector);
+fflush(stdout);
 	lp = myalloc(sizeof(struct stdlogdata));
 	if(!lp) return 1;
 	logger->data = lp;
-	if(!*logger->selector || !strstr(logger->selector, "stdout")){
+	if(!*logger->selector || !strcmp(logger->selector, "stdout")){
 		logger->rotate = NONE;
 		lp->fp = stdout;
 	}
@@ -559,31 +871,38 @@ static int stdloginit(struct LOGGER *logger){
 		lp->fp = stderr;
 	}
 	else {
-		lp->fp = fopen((char *)dologname (tmpbuf, logger->selector, NULL, logger->rotate, time(NULL)), "a");
+		lp->fp = fopen((char *)dologname (tmpbuf, sizeof(tmpbuf) - 1, logger->selector, NULL, logger->rotate, time(NULL)), "a");
 		if(!lp->fp){
+printf("file not created: %s\n", tmpbuf);
 			myfree(lp);
 			return(2);
 		}
+printf("file created: %s\n", tmpbuf);
+fflush(stdout);
 	}
 	return 0;
 }
 
-static int stddobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s){
-	return dobuf(param, buf, s, NULL);
+static int stddobuf(struct clientparam * param, unsigned char * buf, int bufsize, const unsigned char *s){
+printf("stddobuf\n");
+fflush(stdout);
+	return dobuf(param, buf, bufsize, s, NULL);
 }
 
 static void stdlog(const char * buf, int len, struct LOGGER *logger) {
 	FILE *log = ((struct stdlogdata *)logger->data)->fp;
 
+printf("stdlog\n");
+fflush(stdout);
 	fprintf(log, "%s\n", buf);
-	if(log == stdout || log == stderr)fflush(log);
+fflush(log);
 }
 
 static void stdlogrotate(struct LOGGER *logger){
  char tmpbuf[1024];
  struct stdlogdata *lp = (struct stdlogdata *)logger->data;
- if(lp->fp) lp->fp = freopen((char *)dologname (tmpbuf, logger->selector, NULL, logger->rotate, conf.time), "a", lp->fp);
- else lp->fp = fopen((char *)dologname (tmpbuf, logger->selector, NULL, logger->rotate, conf.time), "a");
+ if(lp->fp) lp->fp = freopen((char *)dologname (tmpbuf, sizeof(tmpbuf) -1, logger->selector, NULL, logger->rotate, conf.time), "a", lp->fp);
+ else lp->fp = fopen((char *)dologname (tmpbuf, sizeof(tmpbuf) -1, logger->selector, NULL, logger->rotate, conf.time), "a");
  logger->rotated = conf.time;
  if(logger->rotate) {
 	int t;
@@ -604,7 +923,10 @@ static void stdlogrotate(struct LOGGER *logger){
 		default:
 			break;
 	}
-	dologname (tmpbuf, logger->selector, (conf.archiver)?conf.archiver[1]:NULL, logger->rotate, (logger->rotated - t * conf.rotate));
+/*
+	FIXME: move archiver to thread
+*/
+	dologname (tmpbuf, sizeof(tmpbuf) -1, logger->selector, (conf.archiver)?conf.archiver[1]:NULL, logger->rotate, (logger->rotated - t * conf.rotate));
 	remove ((char *) tmpbuf);
 	if(conf.archiver) {
 		int i;
@@ -613,12 +935,12 @@ static void stdlogrotate(struct LOGGER *logger){
 			strcat((char *)tmpbuf, " ");
 			if(!strcmp((char *)conf.archiver[i], "%A")){
 				strcat((char *)tmpbuf, "\"");
-				dologname (tmpbuf + strlen((char *)tmpbuf), logger->selector, conf.archiver[1], logger->rotate, (logger->rotated - t));
+				dologname (tmpbuf + strlen((char *)tmpbuf), sizeof(tmpbuf) - (strlen((char *)tmpbuf) + 1), logger->selector, conf.archiver[1], logger->rotate, (logger->rotated - t));
 				strcat((char *)tmpbuf, "\"");
 			}
 			else if(!strcmp((char *)conf.archiver[i], "%F")){
 				strcat((char *)tmpbuf, "\"");
-				dologname (tmpbuf+strlen((char *)tmpbuf), logger->selector, NULL, logger->rotate, (logger->rotated-t));
+				dologname (tmpbuf+strlen((char *)tmpbuf), sizeof(tmpbuf) - (strlen((char *)tmpbuf) + 1), logger->selector, NULL, logger->rotate, (logger->rotated-t));
 				strcat((char *)tmpbuf, "\"");
 			}
 			else
@@ -629,9 +951,14 @@ static void stdlogrotate(struct LOGGER *logger){
  }
 }
 
+static void stdlogflush(struct LOGGER *logger){
+	fflush(((struct stdlogdata *)logger->data)->fp);
+}
+
 static void stdlogclose(struct LOGGER *logger){
-	fclose(((struct stdlogdata *)logger->data)->fp);
-	myfree(((struct stdlogdata *)logger->data)->fp);
+	if(((struct stdlogdata *)logger->data)->fp != stdout && ((struct stdlogdata *)logger->data)->fp != stderr)
+		fclose(((struct stdlogdata *)logger->data)->fp);
+	myfree(logger->data);
 }
 
 #if HAVESYSLOG > 0
@@ -748,8 +1075,8 @@ static int sqlinit(struct LOGGER *logger){
 	return 0;
 }
 
-static int sqldobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s){
-	return dobuf(param, buf, s, (unsigned char *)"\'");
+static int sqldobuf(struct clientparam * param, unsigned char * buf, int bufsize, const unsigned char *s){
+	return dobuf(param, buf, bufsize, s, (unsigned char *)"\'");
 }
 
 

+ 4 - 3
src/proxy.h

@@ -169,8 +169,8 @@ int sockgetlinebuf(struct clientparam * param, DIRECTION which, unsigned char *
 
 void initlog(void);
 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);
+int dobuf(struct clientparam * param, unsigned char * buf, int bufsize, const unsigned char *s, const unsigned char * doublec);
+int dobuf2(struct clientparam * param, unsigned char * buf, int bufsize, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format);
 int doconnect(struct clientparam * param);
 int alwaysauth(struct clientparam * param);
 int ipauth(struct clientparam * param);
@@ -192,6 +192,7 @@ unsigned long myresolver(int, unsigned char *, unsigned char *);
 unsigned long fakeresolver (int, unsigned char *, unsigned char*);
 int inithashtable(struct hashtable *hashtable, unsigned nhashsize);
 void freeparam(struct clientparam * param);
+void srvpostfree(struct srvparam * srv);
 void clearstat(struct clientparam * param);
 void dumpcounters(struct trafcount *tl, int counterd);
 int startconnlims (struct clientparam *param);
@@ -263,7 +264,7 @@ FILTER_ACTION handledatfltsrv(struct clientparam *param, unsigned char ** buf_p,
 void srvinit(struct srvparam * srv, struct clientparam *param);
 void srvinit2(struct srvparam * srv, struct clientparam *param);
 void srvfree(struct srvparam * srv);
-unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t);
+unsigned char * dologname (unsigned char *buf, int bufsize, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t);
 int readconfig(FILE * fp);
 int connectwithpoll(SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
 

+ 121 - 171
src/proxymain.c

@@ -8,6 +8,8 @@
 
 #include "proxy.h"
 
+void srvpostfree(struct srvparam * srv);
+
 #define param ((struct clientparam *) p)
 #ifdef _WIN32
 DWORD WINAPI threadfunc(LPVOID p) {
@@ -179,7 +181,7 @@ int MODULEMAINFUNC (int argc, char** argv){
  SASIZETYPE size;
  pthread_t thread;
  struct clientparam defparam;
- struct srvparam srv;
+ struct srvparam *srv;
  struct clientparam * newparam;
  int error = 0;
  unsigned sleeptime;
@@ -271,20 +273,21 @@ int MODULEMAINFUNC (int argc, char** argv){
 
 #endif
 
- srvinit(&srv, &defparam);
- srv.pf = childdef.pf;
+ srv = malloc(sizeof(struct srvparam));
+ srvinit(srv, &defparam);
+ srv->pf = childdef.pf;
  isudp = childdef.isudp;
- srv.service = defparam.service = childdef.service;
+ srv->service = defparam.service = childdef.service;
  
 #ifndef STDMAIN
- copyacl(conf.acl, &srv);
- srv.authfuncs = copyauth(conf.authfuncs);
+ copyacl(conf.acl, srv);
+ srv->authfuncs = copyauth(conf.authfuncs);
  if(!conf.services){
-	conf.services = &srv;
+	conf.services = srv;
  }
  else {
-	srv.next = conf.services;
-	conf.services = conf.services->prev = &srv;
+	srv->next = conf.services;
+	conf.services = conf.services->prev = srv;
  }
 #ifndef _WIN32
  {
@@ -294,7 +297,7 @@ int MODULEMAINFUNC (int argc, char** argv){
  }
 #endif
 #else
- srv.needuser = 0;
+ srv->needuser = 0;
  initlog();
 #endif
 
@@ -307,16 +310,16 @@ int MODULEMAINFUNC (int argc, char** argv){
 			break;
 #ifdef SO_BINDTODEVICE
 		 case 'D':
-			if(argv[i][2] == 'i') srv.ibindtodevice = mystrdup(argv[i] + 3);
-			else srv.obindtodevice = mystrdup(argv[i] + 3);
+			if(argv[i][2] == 'i') srv->ibindtodevice = mystrdup(argv[i] + 3);
+			else srv->obindtodevice = mystrdup(argv[i] + 3);
 			break;
 #endif
 		 case 'l':
-			myfree(srv.logtarget);
-			srv.logtarget = (unsigned char *)mystrdup(argv[i] + 2);
+			myfree(srv->logtarget);
+			srv->logtarget = (unsigned char *)mystrdup(argv[i] + 2);
 			break;
 		 case 'i':
-			getip46(46, (unsigned char *)argv[i]+2, (struct sockaddr *)&srv.intsa);
+			getip46(46, (unsigned char *)argv[i]+2, (struct sockaddr *)&srv->intsa);
 			break;
 		 case 'e':
 			{
@@ -325,29 +328,29 @@ int MODULEMAINFUNC (int argc, char** argv){
 				memset(&sa6, 0, sizeof(sa6));
 				error = !getip46(46, (unsigned char *)argv[i]+2, (struct sockaddr *)&sa6);
 				if(!error) {
-					if (*SAFAMILY(&sa6)==AF_INET) srv.extsa = sa6;
-					else srv.extsa6 = sa6;
+					if (*SAFAMILY(&sa6)==AF_INET) srv->extsa = sa6;
+					else srv->extsa6 = sa6;
 				} 
 #else
-				error = !getip46(46, (unsigned char *)argv[i]+2, (struct sockaddr *)&srv.extsa);
+				error = !getip46(46, (unsigned char *)argv[i]+2, (struct sockaddr *)&srv->extsa);
 #endif
 			}
 			break;
 		 case 'N':
-			getip46(46, (unsigned char *)argv[i]+2, (struct sockaddr *)&srv.extNat);
+			getip46(46, (unsigned char *)argv[i]+2, (struct sockaddr *)&srv->extNat);
 			break;
 		 case 'p':
-			*SAPORT(&srv.intsa) = htons(atoi(argv[i]+2));
+			*SAPORT(&srv->intsa) = htons(atoi(argv[i]+2));
 			break;
 		 case '4':
 		 case '6':
-			srv.family = atoi(argv[i]+1);
+			srv->family = atoi(argv[i]+1);
 			break;
 		 case 'b':
-			srv.bufsize = atoi(argv[i]+2);
+			srv->bufsize = atoi(argv[i]+2);
 			break;
 		 case 'n':
-			srv.usentlm = atoi(argv[i]+2);
+			srv->usentlm = atoi(argv[i]+2);
 			break;
 #ifdef STDMAIN
 #ifndef _WIN32
@@ -361,11 +364,11 @@ int MODULEMAINFUNC (int argc, char** argv){
 #endif
 #endif
 		 case 'f':
-			if(srv.logformat)myfree(srv.logformat);
-			srv.logformat = (unsigned char *)mystrdup(argv[i] + 2);
+			if(srv->logformat)myfree(srv->logformat);
+			srv->logformat = (unsigned char *)mystrdup(argv[i] + 2);
 			break;
 		 case 't':
-			srv.silent = 1;
+			srv->silent = 1;
 			break;
 		 case 'h':
 			hostname = argv[i] + 2;
@@ -379,44 +382,44 @@ int MODULEMAINFUNC (int argc, char** argv){
 			iscbl = 1;
 			break;
 		 case 'u':
-			srv.needuser = 0;
-			if(*(argv[i] + 2)) srv.needuser = atoi(argv[i] + 2);
+			srv->needuser = 0;
+			if(*(argv[i] + 2)) srv->needuser = atoi(argv[i] + 2);
 			break;
 		 case 'T':
-			srv.transparent = 1;
+			srv->transparent = 1;
 			break;
 		 case 'S':
-			srv.stacksize = atoi(argv[i]+2);
+			srv->stacksize = atoi(argv[i]+2);
 			break;
 		case 'a':
-			srv.anonymous = 1 + atoi(argv[i]+2);
+			srv->anonymous = 1 + atoi(argv[i]+2);
 			break;
 		case 's':
 #ifdef WITHSPLICE
-			if(isudp || srv.service == S_ADMIN)
+			if(isudp || srv->service == S_ADMIN)
 #endif
-				srv.singlepacket = 1 + atoi(argv[i]+2);
+				srv->singlepacket = 1 + atoi(argv[i]+2);
 #ifdef WITHSPLICE
 			else
-				if(*(argv[i]+2)) srv.usesplice = atoi(argv[i]+2);
+				if(*(argv[i]+2)) srv->usesplice = atoi(argv[i]+2);
 #endif
 			break;
 		 case 'o':
 			switch(argv[i][2]){
 			 case 's':
-				srv.srvsockopts = getopts(argv[i]+3);
+				srv->srvsockopts = getopts(argv[i]+3);
 				break;
 			 case 'c':
-				srv.clisockopts = getopts(argv[i]+3);
+				srv->clisockopts = getopts(argv[i]+3);
 				break;
 			 case 'l':
-				srv.lissockopts = getopts(argv[i]+3);
+				srv->lissockopts = getopts(argv[i]+3);
 				break;
 			 case 'r':
-				srv.cbcsockopts = getopts(argv[i]+3);
+				srv->cbcsockopts = getopts(argv[i]+3);
 				break;
 			 case 'R':
-				srv.cbcsockopts = getopts(argv[i]+3);
+				srv->cbcsockopts = getopts(argv[i]+3);
 				break;
 			 default:
 				error = 1;
@@ -467,7 +470,7 @@ int MODULEMAINFUNC (int argc, char** argv){
  else {
 #endif
 #ifndef NOPORTMAP
-	if (error || argc != i+3 || *argv[i]=='-'|| (*SAPORT(&srv.intsa) = htons((unsigned short)atoi(argv[i])))==0 || (srv.targetport = htons((unsigned short)atoi(argv[i+2])))==0) {
+	if (error || argc != i+3 || *argv[i]=='-'|| (*SAPORT(&srv->intsa) = htons((unsigned short)atoi(argv[i])))==0 || (srv->targetport = htons((unsigned short)atoi(argv[i+2])))==0) {
 #ifndef STDMAIN
 		haveerror = 1;
 		conf.threadinit = 0;
@@ -493,7 +496,7 @@ int MODULEMAINFUNC (int argc, char** argv){
 		);
 		return (1);
 	}
-	srv.target = (unsigned char *)mystrdup(argv[i+1]);
+	srv->target = (unsigned char *)mystrdup(argv[i+1]);
 #endif
 #ifndef STDMAIN
  }
@@ -512,7 +515,7 @@ int MODULEMAINFUNC (int argc, char** argv){
 		return 2;
 	};
 	*newparam = defparam;
-	return((*srv.pf)((void *)newparam)? 1:0);
+	return((*srv->pf)((void *)newparam)? 1:0);
 	
  }
 #endif
@@ -521,19 +524,19 @@ int MODULEMAINFUNC (int argc, char** argv){
 #endif
 
  
- srvinit2(&srv, &defparam);
- if(!*SAFAMILY(&srv.intsa)) *SAFAMILY(&srv.intsa) = AF_INET;
- if(!*SAPORT(&srv.intsa)) *SAPORT(&srv.intsa) = htons(childdef.port);
- *SAFAMILY(&srv.extsa) = AF_INET;
+ srvinit2(srv, &defparam);
+ if(!*SAFAMILY(&srv->intsa)) *SAFAMILY(&srv->intsa) = AF_INET;
+ if(!*SAPORT(&srv->intsa)) *SAPORT(&srv->intsa) = htons(childdef.port);
+ *SAFAMILY(&srv->extsa) = AF_INET;
 #ifndef NOIPV6
- *SAFAMILY(&srv.extsa6) = AF_INET6;
+ *SAFAMILY(&srv->extsa6) = AF_INET6;
 #endif
  if(hostname)parsehostname(hostname, &defparam, childdef.port);
 
 
 #ifndef STDMAIN
 
- copyfilter(conf.filters, &srv);
+ copyfilter(conf.filters, srv);
  conf.threadinit = 0;
 
 
@@ -542,27 +545,27 @@ int MODULEMAINFUNC (int argc, char** argv){
 
 
  if (!iscbc) {
-	if(srv.srvsock == INVALID_SOCKET){
+	if(srv->srvsock == INVALID_SOCKET){
 
 		if(!isudp){
 			lg.l_onoff = 1;
 			lg.l_linger = conf.timeouts[STRING_L];
-			sock=so._socket(SASOCK(&srv.intsa), SOCK_STREAM, IPPROTO_TCP);
+			sock=so._socket(SASOCK(&srv->intsa), SOCK_STREAM, IPPROTO_TCP);
 		}
 		else {
-			sock=so._socket(SASOCK(&srv.intsa), SOCK_DGRAM, IPPROTO_UDP);
+			sock=so._socket(SASOCK(&srv->intsa), SOCK_DGRAM, IPPROTO_UDP);
 		}
 		if( sock == INVALID_SOCKET) {
 			perror("socket()");
 			return -2;
 		}
-		setopts(sock, srv.lissockopts);
+		setopts(sock, srv->lissockopts);
 #ifdef _WIN32
 		ioctlsocket(sock, FIONBIO, &ul);
 #else
 		fcntl(sock,F_SETFL,O_NONBLOCK | fcntl(sock,F_GETFL));
 #endif
-		srv.srvsock = sock;
+		srv->srvsock = sock;
 		opt = 1;
 		if(so._setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int)))perror("setsockopt()");
 #ifdef SO_REUSEPORT
@@ -570,13 +573,13 @@ int MODULEMAINFUNC (int argc, char** argv){
 		so._setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
 #endif
 #ifdef SO_BINDTODEVICE
-		if(srv.ibindtodevice) so._setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, srv.ibindtodevice, strlen(srv.ibindtodevice) + 1);
+		if(srv->ibindtodevice) so._setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, srv->ibindtodevice, strlen(srv->ibindtodevice) + 1);
 #endif
 	}
-	size = sizeof(srv.intsa);
-	for(sleeptime = SLEEPTIME * 100; so._bind(sock, (struct sockaddr*)&srv.intsa, SASIZE(&srv.intsa))==-1; usleep(sleeptime)) {
+	size = sizeof(srv->intsa);
+	for(sleeptime = SLEEPTIME * 100; so._bind(sock, (struct sockaddr*)&srv->intsa, SASIZE(&srv->intsa))==-1; usleep(sleeptime)) {
 		sprintf((char *)buf, "bind(): %s", strerror(errno));
-		if(!srv.silent)dolog(&defparam, buf);	
+		if(!srv->silent)dolog(&defparam, buf);	
 		sleeptime = (sleeptime<<1);	
 		if(!sleeptime) {
 			so._closesocket(sock);
@@ -584,69 +587,69 @@ int MODULEMAINFUNC (int argc, char** argv){
 		}
 	}
  	if(!isudp){
- 		if(so._listen (sock, 1 + (srv.maxchild>>4))==-1) {
+ 		if(so._listen (sock, 1 + (srv->maxchild>>4))==-1) {
 			sprintf((char *)buf, "listen(): %s", strerror(errno));
-			if(!srv.silent)dolog(&defparam, buf);
+			if(!srv->silent)dolog(&defparam, buf);
 			return -4;
 		}
 	}
 	else 
 		defparam.clisock = sock;
 
-	if(!srv.silent && !iscbc){
+	if(!srv->silent && !iscbc){
 		sprintf((char *)buf, "Accepting connections [%u/%u]", (unsigned)getpid(), (unsigned)pthread_self());
 		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) {
+	parsehost(srv->family, cbl_string, (struct sockaddr *)&cbsa);
+	if((srv->cbsock=so._socket(SASOCK(&cbsa), SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET) {
 		dolog(&defparam, (unsigned char *)"Failed to allocate connect back socket");
 		return -6;
 	}
 	opt = 1;
-	so._setsockopt(srv.cbsock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
+	so._setsockopt(srv->cbsock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
 #ifdef SO_REUSEPORT
 	opt = 1;
-	so._setsockopt(srv.cbsock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
+	so._setsockopt(srv->cbsock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
 #endif
 
-	setopts(srv.cbsock, srv.cbssockopts);
+	setopts(srv->cbsock, srv->cbssockopts);
 
-	if(so._bind(srv.cbsock, (struct sockaddr*)&cbsa, SASIZE(&cbsa))==-1) {
+	if(so._bind(srv->cbsock, (struct sockaddr*)&cbsa, SASIZE(&cbsa))==-1) {
 		dolog(&defparam, (unsigned char *)"Failed to bind connect back socket");
 		return -7;
 	}
-	if(so._listen(srv.cbsock, 1 + (srv.maxchild>>4))==-1) {
+	if(so._listen(srv->cbsock, 1 + (srv->maxchild>>4))==-1) {
 		dolog(&defparam, (unsigned char *)"Failed to listen connect back socket");
 		return -8;
 	}
  }
 
- srv.fds.fd = sock;
- srv.fds.events = POLLIN;
+ srv->fds.fd = sock;
+ srv->fds.events = POLLIN;
  
 #ifndef _WIN32
  pthread_attr_init(&pa);
- pthread_attr_setstacksize(&pa,PTHREAD_STACK_MIN + (32768 + srv.stacksize));
+ pthread_attr_setstacksize(&pa,PTHREAD_STACK_MIN + (32768 + srv->stacksize));
  pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED);
 #endif
 
  for (;;) {
 	for(;;){
-		while((conf.paused == srv.paused && srv.childcount >= srv.maxchild)){
+		while((conf.paused == srv->paused && srv->childcount >= srv->maxchild)){
 			nlog++;			
-			if(!srv.silent && nlog > 5000) {
-				sprintf((char *)buf, "Warning: too many connected clients (%d/%d)", srv.childcount, srv.maxchild);
+			if(!srv->silent && nlog > 5000) {
+				sprintf((char *)buf, "Warning: too many connected clients (%d/%d)", srv->childcount, srv->maxchild);
 				dolog(&defparam, buf);
 				nlog = 0;
 			}
 			usleep(SLEEPTIME);
 		}
 		if (iscbc) break;
-		if (conf.paused != srv.paused) break;
-		if (srv.fds.events & POLLIN) {
-			error = so._poll(&srv.fds, 1, 1000);
+		if (conf.paused != srv->paused) break;
+		if (srv->fds.events & POLLIN) {
+			error = so._poll(&srv->fds, 1, 1000);
 		}
 		else {
 			usleep(SLEEPTIME);
@@ -656,20 +659,20 @@ 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)dolog(&defparam, buf);
+			if(!srv->silent)dolog(&defparam, buf);
 			break;
 		}
 	}
-	if((conf.paused != srv.paused) || (error < 0)) break;
+	if((conf.paused != srv->paused) || (error < 0)) break;
 	error = 0;
 	if(!isudp){
 		size = sizeof(defparam.sincr);
 		if(iscbc){
 			new_sock=so._socket(SASOCK(&defparam.sincr), SOCK_STREAM, IPPROTO_TCP);
 			if(new_sock != INVALID_SOCKET){
-				setopts(new_sock, srv.cbcsockopts);
+				setopts(new_sock, srv->cbcsockopts);
 
-				parsehost(srv.family, cbc_string, (struct sockaddr *)&defparam.sincr);
+				parsehost(srv->family, cbc_string, (struct sockaddr *)&defparam.sincr);
 				if(connectwithpoll(new_sock,(struct sockaddr *)&defparam.sincr,SASIZE(&defparam.sincr),CONNBACK_TO)) {
 					so._closesocket(new_sock);
 					new_sock = INVALID_SOCKET;
@@ -727,7 +730,7 @@ int MODULEMAINFUNC (int argc, char** argv){
 				}
 #endif
 				nlog++;			
-				if(!srv.silent && (error || nlog > 5000)) {
+				if(!srv->silent && (error || nlog > 5000)) {
 					sprintf((char *)buf, "accept(): %s", strerror(errno));
 					dolog(&defparam, buf);
 					nlog = 0;
@@ -735,11 +738,11 @@ int MODULEMAINFUNC (int argc, char** argv){
 				continue;
 			}
 		}
-		setopts(new_sock, srv.clisockopts);
+		setopts(new_sock, srv->clisockopts);
 		size = sizeof(defparam.sincl);
 		if(so._getsockname(new_sock, (struct sockaddr *)&defparam.sincl, &size)){
 			sprintf((char *)buf, "getsockname(): %s", strerror(errno));
-			if(!srv.silent)dolog(&defparam, buf);
+			if(!srv->silent)dolog(&defparam, buf);
 			continue;
 		}
 #ifdef _WIN32
@@ -751,7 +754,7 @@ int MODULEMAINFUNC (int argc, char** argv){
 		so._setsockopt(new_sock, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
 	}
 	else {
-		srv.fds.events = 0;
+		srv->fds.events = 0;
 	}
 	
 #ifndef STDMAIN
@@ -763,7 +766,7 @@ int MODULEMAINFUNC (int argc, char** argv){
 	if(! (newparam = myalloc (sizeof(defparam)))){
 		if(!isudp) so._closesocket(new_sock);
 		defparam.res = 21;
-		if(!srv.silent)dolog(&defparam, (unsigned char *)"Memory Allocation Failed");
+		if(!srv->silent)dolog(&defparam, (unsigned char *)"Memory Allocation Failed");
 		usleep(SLEEPTIME);
 		continue;
 	};
@@ -773,68 +776,64 @@ int MODULEMAINFUNC (int argc, char** argv){
 
 	if(!isudp) newparam->clisock = new_sock;
 #ifndef STDMAIN
-	if(makefilters(&srv, newparam) > CONTINUE){
+	if(makefilters(srv, newparam) > CONTINUE){
 		freeparam(newparam);		
 		continue;
 	}
 #endif
 	newparam->prev = newparam->next = NULL;
 	error = 0;
-	pthread_mutex_lock(&srv.counter_mutex);
-	if(!srv.child){
-		srv.child = newparam;
+	pthread_mutex_lock(&srv->counter_mutex);
+	if(!srv->child){
+		srv->child = newparam;
 	}
 	else {
-		newparam->next = srv.child;
-		srv.child = srv.child->prev = newparam;
+		newparam->next = srv->child;
+		srv->child = srv->child->prev = newparam;
 	}
 #ifdef _WIN32
 #ifndef _WINCE
-	h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, (unsigned)(16384 + srv.stacksize), (void *)threadfunc, (void *) newparam, 0, &thread);
+	h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, (unsigned)(16384 + srv->stacksize), (void *)threadfunc, (void *) newparam, 0, &thread);
 #else
-	h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, (unsigned)(16384 + srv.stacksize), (void *)threadfunc, (void *) newparam, 0, &thread);
+	h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, (unsigned)(16384 + srv->stacksize), (void *)threadfunc, (void *) newparam, 0, &thread);
 #endif
-	srv.childcount++;
+	srv->childcount++;
 	if (h) {
 		newparam->threadid = (unsigned)thread;
 		CloseHandle(h);
 	}
 	else {
 		sprintf((char *)buf, "_beginthreadex(): %s", _strerror(NULL));
-		if(!srv.silent)dolog(&defparam, buf);
+		if(!srv->silent)dolog(&defparam, buf);
 		error = 1;
 	}
 #else
 
 	error = pthread_create(&thread, &pa, threadfunc, (void *)newparam);
-	srv.childcount++;
+	srv->childcount++;
 	if(error){
 		sprintf((char *)buf, "pthread_create(): %s", strerror(error));
-		if(!srv.silent)dolog(&defparam, buf);
+		if(!srv->silent)dolog(&defparam, buf);
 	}
 	else {
 		newparam->threadid = (unsigned)thread;
 	}
 #endif
-	pthread_mutex_unlock(&srv.counter_mutex);
+	pthread_mutex_unlock(&srv->counter_mutex);
 	if(error) freeparam(newparam);
 
 	memset(&defparam.sincl, 0, sizeof(defparam.sincl));
 	memset(&defparam.sincr, 0, sizeof(defparam.sincr));
-	if(isudp) while(!srv.fds.events)usleep(SLEEPTIME);
+	if(isudp) while(!srv->fds.events)usleep(SLEEPTIME);
  }
 
- if(!srv.silent) dolog(&defparam, (unsigned char *)"Exiting thread");
+ if(!srv->silent) dolog(&defparam, (unsigned char *)"Exiting thread");
 
- srvfree(&srv);
+ srvfree(srv);
+ pthread_mutex_lock(&srv->counter_mutex);
+ if(!srv->child)srvpostfree(srv);
+ pthread_mutex_unlock(&srv->counter_mutex);
 
-#ifndef STDMAIN
- pthread_mutex_lock(&config_mutex);
- if(srv.next)srv.next->prev = srv.prev;
- if(srv.prev)srv.prev->next = srv.next;
- else conf.services = srv.next;
- pthread_mutex_unlock(&config_mutex);
-#endif
 
 #ifndef _WIN32
  pthread_attr_destroy(&pa);
@@ -916,15 +915,15 @@ void srvinit2(struct srvparam * srv, struct clientparam *param){
 	param->sinsr = srv->extsa;
 }
 
-void srvfree(struct srvparam * srv){
- if(srv->srvsock != INVALID_SOCKET) so._closesocket(srv->srvsock);
- srv->srvsock = INVALID_SOCKET;
- if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->cbsock);
- srv->cbsock = INVALID_SOCKET;
- srv->service = S_ZOMBIE;
- while(srv->child) usleep(SLEEPTIME * 100);
+
+void srvpostfree(struct srvparam * srv){
  unregisterlog(srv->log);
 #ifndef STDMAIN
+ pthread_mutex_lock(&config_mutex);
+ if(srv->next)srv->next->prev = srv->prev;
+ if(srv->prev)srv->prev->next = srv->next;
+ else conf.services = srv->next;
+ pthread_mutex_unlock(&config_mutex);
  if(srv->filter){
 	while(srv->nfilters){
 		srv->nfilters--;
@@ -948,64 +947,15 @@ void srvfree(struct srvparam * srv){
  if(srv->ibindtodevice) myfree(srv->ibindtodevice);
  if(srv->obindtodevice) myfree(srv->obindtodevice);
 #endif
+ myfree(srv);
 }
 
-
-void freeparam(struct clientparam * param) {
-	if(param->res == 2) return;
-	if(param->ctrlsocksrv != INVALID_SOCKET && param->ctrlsocksrv != param->remsock) {
-		so._shutdown(param->ctrlsocksrv, SHUT_RDWR);
-		so._closesocket(param->ctrlsocksrv);
-	}
-	if(param->ctrlsock != INVALID_SOCKET && param->ctrlsock != param->clisock) {
-		so._shutdown(param->ctrlsock, SHUT_RDWR);
-		so._closesocket(param->ctrlsock);
-	}
-	if(param->remsock != INVALID_SOCKET) {
-		so._shutdown(param->remsock, SHUT_RDWR);
-		so._closesocket(param->remsock);
-	}
-	if(param->clisock != INVALID_SOCKET) {
-		so._shutdown(param->clisock, SHUT_RDWR);
-		so._closesocket(param->clisock);
-	}
-	myfree(param->clibuf);
-	myfree(param->srvbuf);
-	if(param->datfilterssrv) myfree(param->datfilterssrv);
-#ifndef STDMAIN
-	if(param->reqfilters) myfree(param->reqfilters);
-	if(param->hdrfilterscli) myfree(param->hdrfilterscli);
-	if(param->hdrfilterssrv) myfree(param->hdrfilterssrv);
-	if(param->predatfilters) myfree(param->predatfilters);
-	if(param->datfilterscli) myfree(param->datfilterscli);
-	if(param->filters){
-		if(param->nfilters)while(param->nfilters--){
-			if(param->filters[param->nfilters].filter->filter_clear)
-				(*param->filters[param->nfilters].filter->filter_clear)(param->filters[param->nfilters].data);
-		}
-		myfree(param->filters);
-	}
-	if(conf.connlimiter && (param->res != 95 || param->remsock != INVALID_SOCKET)) stopconnlims(param);
-#endif
-	if(param->srv){
-		pthread_mutex_lock(&param->srv->counter_mutex);
-		if(param->prev){
-			param->prev->next = param->next;
-		}
-		else
-			param->srv->child = param->next;
-		if(param->next){
-			param->next->prev = param->prev;
-		}
-		(param->srv->childcount)--;
-		pthread_mutex_unlock(&param->srv->counter_mutex);
-	}
-	if(param->hostname) myfree(param->hostname);
-	if(param->username) myfree(param->username);
-	if(param->password) myfree(param->password);
-	if(param->extusername) myfree(param->extusername);
-	if(param->extpassword) myfree(param->extpassword);
-	myfree(param);
+void srvfree(struct srvparam * srv){
+ if(srv->srvsock != INVALID_SOCKET) so._closesocket(srv->srvsock);
+ srv->srvsock = INVALID_SOCKET;
+ if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->cbsock);
+ srv->cbsock = INVALID_SOCKET;
+ srv->service = S_ZOMBIE;
 }
 
 

+ 10 - 5
src/structures.h

@@ -15,6 +15,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdint.h>
+#include <inttypes.h>
 #ifdef  __cplusplus
 extern "C" {
 #endif
@@ -195,6 +196,7 @@ struct symbol;
 struct pluginlink;
 struct srvparam;
 struct LOGFUNC;
+struct LOGGER;
 typedef int (*AUTHFUNC)(struct clientparam * param);
 typedef void * (*REDIRECTFUNC)(struct clientparam * param);
 typedef unsigned long (*RESOLVFUNC)(int af, unsigned char *name, unsigned char *value);
@@ -373,15 +375,18 @@ struct trafcount {
 struct LOGFUNC {
 	struct LOGFUNC* next;	
 	int (*init)(struct LOGGER *logger);
-	int (*dobuf)(struct clientparam * param, unsigned char * buf, const unsigned char *s);
+	int (*dobuf)(struct clientparam * param, unsigned char * buf, int bufsize, const unsigned char *s);
 	void (*log)(const char * buf, int len, struct LOGGER *logger);
 	void (*rotate)(struct LOGGER *logger);
+	void (*flush)(struct LOGGER *logger);
 	void (*close)(struct LOGGER *logger);
 	char* prefix;
 };
 extern struct LOGFUNC *logfuncs;
+extern void(*prelog)(struct clientparam * param);
 struct LOGGER {
 	struct LOGGER *next;
+	struct LOGGER *prev;
 	char * selector;
 	void * data;
 	struct LOGFUNC *logfunc;
@@ -389,9 +394,9 @@ struct LOGGER {
 	time_t rotated;
 	int registered;
 };
-extern void(*prelog)(struct clientparam * param);
 struct LOGGER * registerlog(const char * logstring, int logtype);
 void unregisterlog (struct LOGGER * log);
+void flushlogs(void);
 struct nserver {
 #ifndef NOIPV6
 	struct sockaddr_in6 addr;
@@ -764,8 +769,8 @@ struct pluginlink {
 	int (*sockgetcharsrv)(struct clientparam * param, int timeosec, int timeousec);
 	int (*sockgetlinebuf)(struct clientparam * param, DIRECTION which, unsigned char * buf, int bufsize, int delim, int to);
 	int (*myinet_ntop)(int af, void *src, char *dst, socklen_t size);
-	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);
+	int (*dobuf)(struct clientparam * param, unsigned char * buf, int bufsize, const unsigned char *s, const unsigned char * doublec);
+	int (*dobuf2)(struct clientparam * param, unsigned char * buf, int bufsize, 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 usesplice);
@@ -798,7 +803,7 @@ struct pluginlink {
 	int (*parseusername)(char *username, struct clientparam *param, int extpasswd);
 	int (*parseconnusername)(char *username, struct clientparam *param, int extpasswd, unsigned short port);
 	struct sockfuncs *so;
-	unsigned char * (*dologname) (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t);
+	unsigned char * (*dologname) (unsigned char *buf, int bufsize, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t);
 };
 
 struct counter_header {