1 /*
2    3APA3A simpliest proxy server
3    (c) 2002-2016 by Vladimir Dubrovin <3proxy@3proxy.ru>
4 
5    please read License Agreement
6 
7 */
8 
9 #include "proxy.h"
10 #ifndef _WIN32
11 #include <sys/resource.h>
12 #include <pwd.h>
13 #include <grp.h>
14 #ifndef NOPLUGINS
15 #include <dlfcn.h>
16 #endif
17 #endif
18 
19 #ifndef DEFAULTCONFIG
20 #define DEFAULTCONFIG conf.stringtable[25]
21 #endif
22 
23 pthread_mutex_t bandlim_mutex;
24 pthread_mutex_t connlim_mutex;
25 pthread_mutex_t tc_mutex;
26 pthread_mutex_t pwl_mutex;
27 pthread_mutex_t hash_mutex;
28 pthread_mutex_t config_mutex;
29 
30 int haveerror = 0;
31 int linenum = 0;
32 
33 FILE *writable;
34 struct counter_header cheader = {"3CF", (time_t)0};
35 struct counter_record crecord;
36 
37 int mainfunc (int argc, char** argv);
38 
39 struct proxydef childdef = {NULL, 0, 0, S_NOSERVICE, ""};
40 
41 #define STRINGBUF 65535
42 #define NPARAMS	  4096
43 
44 #ifndef _WIN32
45 char *chrootp = NULL;
46 static pthread_attr_t pa;
47 #endif
48 char * curconf = NULL;
49 
confopen()50 FILE * confopen(){
51 	curconf = conf.conffile;
52 #ifndef _WIN32
53 	if(chrootp){
54 		if(strstr(curconf, chrootp) == curconf)
55 			curconf += strlen(chrootp);
56 	}
57 #endif
58 	if(writable) {
59 		rewind(writable);
60 		return writable;
61 	}
62 	return fopen(curconf, "r");
63 }
64 
65 
66 #ifdef _WIN32
startsrv(LPVOID data)67 DWORD WINAPI startsrv(LPVOID data) {
68 #else
69 void * startsrv(void * data) {
70 #endif
71   struct child *d = (struct child *)data;
72   mainfunc(d->argc, (char **)d->argv);
73   return 0;
74 }
75 
76 int included =0;
77 
78 int getrotate(char c){
79 	switch(c){
80 	case 'c':
81 	case 'C':
82 		return MINUTELY;
83 	case 'h':
84 	case 'H':
85 		return HOURLY;
86 	case 'd':
87 	case 'D':
88 		return DAILY;
89 	case 'w':
90 	case 'W':
91 		return WEEKLY;
92 	case 'y':
93 	case 'Y':
94 		return ANNUALLY;
95 	case 'm':
96 	case 'M':
97 		return MONTHLY;
98 	default:
99 		return NEVER;
100 	}
101 }
102 
103 
104 unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t) {
105 	struct tm *ts;
106 
107 	ts = localtime(&t);
108 	if(strchr((char *)name, '%')){
109 		struct clientparam fakecli;
110 
111 		memset(&fakecli, 0, sizeof(fakecli));
112 		dobuf2(&fakecli, buf, NULL, NULL, ts, (char *)name);
113 	}
114 	else switch(lt){
115 		case NONE:
116 			sprintf((char *)buf, "%s", name);
117 			break;
118 		case ANNUALLY:
119 			sprintf((char *)buf, "%s.%04d", name, ts->tm_year+1900);
120 			break;
121 		case MONTHLY:
122 			sprintf((char *)buf, "%s.%04d.%02d", name, ts->tm_year+1900, ts->tm_mon+1);
123 			break;
124 		case WEEKLY:
125 			t = t - (ts->tm_wday * (60*60*24));
126 			ts = localtime(&t);
127 			sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday);
128 			break;
129 		case DAILY:
130 			sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday);
131 			break;
132 		case HOURLY:
133 			sprintf((char *)buf, "%s.%04d.%02d.%02d-%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour);
134 			break;
135 		case MINUTELY:
136 			sprintf((char *)buf, "%s.%04d.%02d.%02d-%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour, ts->tm_min);
137 			break;
138 		default:
139 			break;
140 	}
141 	if(ext){
142 		strcat((char *)buf, ".");
143 		strcat((char *)buf, (char *)ext);
144 	}
145 	return buf;
146 }
147 
148 int start_proxy_thread(struct child * chp){
149   pthread_t thread;
150 #ifdef _WIN32
151   HANDLE h;
152 #endif
153 
154 	conf.threadinit = 1;
155 #ifdef _WIN32
156 #ifndef _WINCE
157 	h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, 16384+conf.stacksize, (void *)startsrv, (void *) chp, (DWORD)0, &thread);
158 #else
159 	h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, 16384+conf.stacksize, (void *)startsrv, (void *) chp, (DWORD)0, &thread);
160 #endif
161 	if(h)CloseHandle(h);
162 #else
163 	pthread_attr_init(&pa);
164 	pthread_attr_setstacksize(&pa,PTHREAD_STACK_MIN + (32768+conf.stacksize));
165 	pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED);
166 	pthread_create(&thread, &pa, startsrv, (void *)chp);
167 	pthread_attr_destroy(&pa);
168 #endif
169 	while(conf.threadinit)usleep(SLEEPTIME);
170 	if(haveerror)  {
171 		fprintf(stderr, "Service not started on line: %d%s\n", linenum, haveerror == 2? ": insufficient memory":"");
172 		return(40);
173 	}
174 	return 0;
175 }
176 
177 static int h_proxy(int argc, unsigned char ** argv){
178   struct child ch;
179 
180 	ch.argc = argc;
181 	ch.argv = argv;
182 	if(!strcmp((char *)argv[0], "proxy")) {
183 		childdef.pf = proxychild;
184 		childdef.port = 3128;
185 		childdef.isudp = 0;
186 		childdef.service = S_PROXY;
187 		childdef.helpmessage = " -n - no NTLM support\n";
188 #ifdef NOIPV6
189 		if(!resolvfunc || (resolvfunc == myresolver && !dns_table.hashsize)){
190 			fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, proxy may run very slow\n", linenum);
191 		}
192 #endif
193 	}
194 	else if(!strcmp((char *)argv[0], "pop3p")) {
195 		childdef.pf = pop3pchild;
196 		childdef.port = 110;
197 		childdef.isudp = 0;
198 		childdef.service = S_POP3P;
199 		childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n";
200 	}
201 	else if(!strcmp((char *)argv[0], "smtpp")) {
202 		childdef.pf = smtppchild;
203 		childdef.port = 25;
204 		childdef.isudp = 0;
205 		childdef.service = S_SMTPP;
206 		childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n";
207 	}
208 	else if(!strcmp((char *)argv[0], "ftppr")) {
209 		childdef.pf = ftpprchild;
210 		childdef.port = 21;
211 		childdef.isudp = 0;
212 		childdef.service = S_FTPPR;
213 		childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n";
214 	}
215 	else if(!strcmp((char *)argv[0], "socks")) {
216 		childdef.pf = sockschild;
217 		childdef.port = 1080;
218 		childdef.isudp = 0;
219 		childdef.service = S_SOCKS;
220 		childdef.helpmessage = " -n - no NTLM support\n";
221 #ifdef NOIPV6
222 		if(!resolvfunc || (resolvfunc == myresolver && !dns_table.hashsize)){
223 			fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, socks may run very slow\n", linenum);
224 		}
225 #endif
226 	}
227 	else if(!strcmp((char *)argv[0], "tcppm")) {
228 		childdef.pf = tcppmchild;
229 		childdef.port = 0;
230 		childdef.isudp = 0;
231 		childdef.service = S_TCPPM;
232 		childdef.helpmessage = "";
233 	}
234 	else if(!strcmp((char *)argv[0], "udppm")) {
235 		childdef.pf = udppmchild;
236 		childdef.port = 0;
237 		childdef.isudp = 1;
238 		childdef.service = S_UDPPM;
239 		childdef.helpmessage = " -s single packet UDP service for request/reply (DNS-like) services\n";
240 	}
241 	else if(!strcmp((char *)argv[0], "admin")) {
242 		childdef.pf = adminchild;
243 		childdef.port = 80;
244 		childdef.isudp = 0;
245 		childdef.service = S_ADMIN;
246 	}
247 	else if(!strcmp((char *)argv[0], "dnspr")) {
248 		childdef.pf = dnsprchild;
249 		childdef.port = 53;
250 		childdef.isudp = 1;
251 		childdef.service = S_DNSPR;
252 		childdef.helpmessage = " -s - simple DNS forwarding - do not use 3proxy resolver / name cache\n";
253 #ifndef NOIPV6
254 		if(!resolvfunc || (resolvfunc == myresolver && !dns_table.hashsize) || resolvfunc == fakeresolver){
255 			fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, dnspr will not work as expected\n", linenum);
256 		}
257 #endif
258 	}
259 	return start_proxy_thread(&ch);
260 }
261 
262 static int h_internal(int argc, unsigned char ** argv){
263 	getip46(46, argv[1], (struct sockaddr *)&conf.intsa);
264 	return 0;
265 }
266 
267 static int h_external(int argc, unsigned char ** argv){
268 	int res;
269 #ifndef NOIPV6
270 	struct sockaddr_in6 sa6;
271 	memset(&sa6, 0, sizeof(sa6));
272 	res = getip46(46, argv[1], (struct sockaddr *)&sa6);
273 	if(!res) return 1;
274 	if (*SAFAMILY(&sa6)==AF_INET) conf.extsa = sa6;
275 	else conf.extsa6 = sa6;
276 #else
277 	res = getip46(46, argv[1], (struct sockaddr *)&conf.extsa);
278 #endif
279 	return 0;
280 }
281 
282 
283 static int h_log(int argc, unsigned char ** argv){
284 	unsigned char tmpbuf[8192];
285 	int notchanged = 0;
286 
287 
288 	havelog = 1;
289 	if(argc > 1 && conf.logtarget && !strcmp((char *)conf.logtarget, (char *)argv[1])) {
290 		notchanged = 1;
291 	}
292 	if(!notchanged && conf.logtarget){
293 		myfree(conf.logtarget);
294 		conf.logtarget = NULL;
295 	}
296 	if(argc > 1) {
297 		if(!strcmp((char *) argv[1], "/dev/null")) {
298 			conf.logfunc = lognone;
299 			return 0;
300 		}
301 		if(!notchanged) conf.logtarget = (unsigned char *)mystrdup((char *)argv[1]);
302 		if(*argv[1]=='@'){
303 #ifndef _WIN32
304 			conf.logfunc = logsyslog;
305 			if(notchanged) return 0;
306 			openlog((char *)conf.logtarget+1, LOG_PID, LOG_DAEMON);
307 #endif
308 		}
309 #ifndef NOODBC
310 		else if(*argv[1]=='&'){
311 			if(notchanged) return 0;
312 			conf.logfunc = logsql;
313 			pthread_mutex_lock(&log_mutex);
314 			close_sql();
315 			init_sql((char *)argv[1]+1);
316 			pthread_mutex_unlock(&log_mutex);
317 		}
318 #endif
319 #ifndef NORADIUS
320 		else if(!strcmp(argv[1],"radius")){
321 			conf.logfunc = logradius;
322 		}
323 #endif
324 		else {
325 			if(argc > 2) {
326 				conf.logtype = getrotate(*argv[2]);
327 			}
328 			conf.logfunc = logstdout;
329 			if(notchanged) return 0;
330 			conf.logtime = time(0);
331 			if(conf.logname)myfree(conf.logname);
332 			conf.logname = (unsigned char *)mystrdup((char *)argv[1]);
333 			if(conf.stdlog) conf.stdlog = freopen((char *)dologname (tmpbuf, conf.logname, NULL, conf.logtype, conf.logtime), "a", conf.stdlog);
334 			else conf.stdlog = fopen((char *)dologname (tmpbuf, conf.logname, NULL, conf.logtype, conf.logtime), "a");
335 			if(!conf.stdlog){
336 				perror((char *)tmpbuf);
337 				return 1;
338 			}
339 
340 		}
341 	}
342 	else conf.logfunc = logstdout;
343 	return 0;
344 }
345 
346 static int h_stacksize(int argc, unsigned char **argv){
347 	conf.stacksize = atoi((char *)argv[1]);
348 	return 0;
349 }
350 
351 
352 static int h_force(int argc, unsigned char **argv){
353 	conf.noforce = 0;
354 	return 0;
355 }
356 
357 static int h_noforce(int argc, unsigned char **argv){
358 	conf.noforce = 1;
359 	return 0;
360 }
361 
362 static int h_service(int argc, unsigned char **argv){
363 	return 0;
364 }
365 
366 static int h_daemon(int argc, unsigned char **argv){
367 	if(!conf.demon)daemonize();
368 	conf.demon = 1;
369 	return 0;
370 }
371 
372 static int h_config(int argc, unsigned char **argv){
373 	if(conf.conffile)myfree(conf.conffile);
374 	conf.conffile = mystrdup((char *)argv[1]);
375 	if(!conf.conffile) return 21;
376 	return 0;
377 }
378 
379 static int h_include(int argc, unsigned char **argv){
380 	int res;
381 	FILE *fp1;
382 
383 	fp1 = fopen((char *)argv[1], "r");
384 	if(!fp1){
385 		fprintf(stderr, "Unable to open included file: %s\n", argv[1]);
386 		return 1;
387 	}
388 	res = readconfig(fp1);
389 	fclose(fp1);
390 	return res;
391 }
392 
393 static int h_archiver(int argc, unsigned char **argv){
394 	int j;
395 
396 	conf.archiver = myalloc(argc * sizeof(char *));
397 	if(conf.archiver) {
398 		conf.archiverc = argc;
399 		for(j = 0; j < conf.archiverc; j++) conf.archiver[j] = (unsigned char *)mystrdup((char *)argv[j]);
400 	}
401 	return 0;
402 }
403 
404 static int h_counter(int argc, unsigned char **argv){
405 	struct counter_header ch1;
406 	if(conf.counterd >=0)close(conf.counterd);
407 	conf.counterd = open((char *)argv[1], O_BINARY|O_RDWR|O_CREAT, 0660);
408 	if(conf.counterd<0){
409 		fprintf(stderr, "Unable to open counter file %s, line %d\n", argv[1], linenum);
410 		return 1;
411 	}
412 	if(read(conf.counterd, &ch1, sizeof(ch1))==sizeof(ch1)){
413 		if(memcmp(&ch1, &cheader, 4)){
414 			fprintf(stderr, "Not a counter file %s, line %d\n", argv[1], linenum);
415 			return 2;
416 		}
417 #ifdef _TIME64_T_DEFINED
418 #ifdef _MAX__TIME64_T
419 #define MAX_COUNTER_TIME (_MAX__TIME64_T)
420 #elif defined (MAX__TIME64_T)
421 #define MAX_COUNTER_TIME (MAX__TIME64_T)
422 #else
423 #define MAX_COUNTER_TIME (0x793406fff)
424 #endif
425 #else
426 #define MAX_COUNTER_TIME ((sizeof(time_t)>4)?(time_t)0x793406fff:(time_t)0x7fffffff)
427 #endif
428 
429 		if(ch1.updated < 0 || ch1.updated >= MAX_COUNTER_TIME){
430 			fprintf(stderr, "Invalid or corrupted counter file %s. Use countersutil utility to convert from older version\n", argv[1]);
431 			return 3;
432 		}
433 		cheader.updated = ch1.updated;
434 	}
435 	if(argc >=4) {
436 		conf.countertype = getrotate(*argv[2]);
437 		if(conf.counterfile) myfree(conf.counterfile);
438 		conf.counterfile = mystrdup((char *)argv[3]);
439 	}
440 	return 0;
441 }
442 
443 static int h_rotate(int argc, unsigned char **argv){
444 	conf.rotate = atoi((char *)argv[1]);
445 	return 0;
446 }
447 
448 static int h_logformat(int argc, unsigned char **argv){
449 	unsigned char * old = conf.logformat;
450 	conf.logformat = (unsigned char *)mystrdup((char *)argv[1]);
451 	if(old) myfree(old);
452 	return 0;
453 }
454 
455 static int h_timeouts(int argc, unsigned char **argv){
456 	int j;
457 
458 	for(j = 0; conf.timeouts[j] && j + 1 < argc; j++) {
459 		if((conf.timeouts[j] = atoi((char *)argv[j + 1])) <= 0 || conf.timeouts[j] > 2000000){
460 			fprintf(stderr, "Invalid timeout: %s, line %d\n", argv[j + 1], linenum);
461 			return(1);
462 		}
463 	}
464 	return 0;
465 }
466 
467 static int h_noop(int argc, unsigned char **argv){
468 	return 0;
469 }
470 
471 static int h_auth(int argc, unsigned char **argv){
472 	struct auth *au, * newau;
473 
474 	freeauth(conf.authfuncs);
475 	conf.authfuncs = NULL;
476 	if(!conf.bandlimfunc)conf.bandlimfunc = bandlimitfunc;
477 	for(argc--; argc; argc--){
478 	  for(au = authfuncs; au; au=au->next){
479 		if(!strcmp((char *)argv[argc], au->desc)){
480 			newau = myalloc(sizeof(struct auth));
481 			if(!newau) {
482 				return 21;
483 			}
484 			newau->next = conf.authfuncs;
485 			conf.authfuncs = newau;
486 			conf.authfuncs->desc = au->desc;
487 			conf.authfuncs->authenticate = au->authenticate;
488 			conf.authfuncs->authorize = au->authorize;
489 			break;
490 		}
491 	  }
492 	  if(!au) return 1;
493 	}
494 	conf.authfunc = doauth;
495 	return 0;
496 }
497 
498 static int h_users(int argc, unsigned char **argv){
499   int j;
500   unsigned char *arg;
501   struct passwords *pwl = NULL;
502 
503 	for (j = 1; j<argc; j++) {
504 		if(!(pwl = myalloc(sizeof(struct passwords)))) {
505 			return(21);
506 		}
507 		memset(pwl, 0, sizeof(struct passwords));
508 
509 		arg = (unsigned char *)strchr((char *)argv[j], ':');
510 		if(!arg||!arg[1]||!arg[2]||arg[3]!=':')	{
511 			pwl->user = (unsigned char *)mystrdup((char *)argv[j]);
512 			pwl->pwtype = SYS;
513 		}
514 		else {
515 			*arg = 0;
516 			pwl->user = (unsigned char *)mystrdup((char *)argv[j]);
517 
518 			if((arg[1] == 'C' && arg[2] == 'L' && (pwl->pwtype = CL)) ||
519 				(arg[1] == 'C' && arg[2] == 'R' && (pwl->pwtype = CR)) ||
520 				(arg[1] == 'N' && arg[2] == 'T' && (pwl->pwtype = NT)) ||
521 				(arg[1] == 'L' && arg[2] == 'M' && (pwl->pwtype = LM))){
522 				pwl->password = (unsigned char *)mystrdup((char *)arg+4);
523 			}
524 			else {
525 				pwl->password = (unsigned char *) mystrdup((char *)arg + 1);
526 				pwl->pwtype = UN;
527 			}
528 			if(!pwl->password) return 3;
529 		}
530 		if(!pwl->user) return 21;
531 		pthread_mutex_lock(&pwl_mutex);
532 		pwl->next = conf.pwl;
533 		conf.pwl = pwl;
534 		pthread_mutex_unlock(&pwl_mutex);
535 
536 
537 	}
538 	return 0;
539 }
540 
541 static int h_maxconn(int argc, unsigned char **argv){
542 	conf.maxchild = atoi((char *)argv[1]);
543 	if(!conf.maxchild) {
544 		return(1);
545 	}
546 #ifndef _WIN32
547 	{
548 		struct rlimit rl;
549 		if(!getrlimit(RLIMIT_NOFILE, &rl)){
550 			if((conf.maxchild<<1) > rl.rlim_cur)
551 				fprintf(stderr, "[line %d] Warning: current open file ulimits are too low (cur: %d/max: %d),"
552 						" maxconn requires at least %d for every running service."
553 						" Configure ulimits according to system documentation\n",
554 						  linenum, (int)rl.rlim_cur, (int)rl.rlim_max, (conf.maxchild<<1));
555 		}
556 	}
557 #endif
558 	return 0;
559 }
560 
561 static int h_flush(int argc, unsigned char **argv){
562 	freeacl(conf.acl);
563 	conf.acl = NULL;
564 	return 0;
565 }
566 
567 /*
568 static int h_flushusers(int argc, unsigned char **argv){
569 	freepwl(conf.pwl);
570 	conf.pwl = NULL;
571 	return 0;
572 }
573 */
574 
575 static int h_nserver(int argc, unsigned char **argv){
576   char *str;
577 
578 	if(numservers < MAXNSERVERS) {
579 		if((str = strchr((char *)argv[1], '/')))
580 			*str = 0;
581 		*SAPORT(&nservers[numservers].addr) = htons(53);
582 		if(parsehost(46, argv[1], (struct sockaddr *)&nservers[numservers].addr)) return 1;
583 		if(str) {
584 			nservers[numservers].usetcp = strstr(str + 1, "tcp")? 1:0;
585 			*str = '/';
586 		}
587 		numservers++;
588 
589 	}
590 	resolvfunc = myresolver;
591 	return 0;
592 }
593 
594 static int h_authnserver(int argc, unsigned char **argv){
595   char *str;
596 
597 	if((str = strchr((char *)argv[1], '/')))
598 		*str = 0;
599 	if(parsehost(46, argv[1], (struct sockaddr *)&authnserver.addr)) return 1;
600 	*SAPORT(&authnserver.addr) = htons(53);
601 	if(str) {
602 		authnserver.usetcp = strstr(str + 1, "tcp")? 1:0;
603 		*str = '/';
604 	}
605 	return 0;
606 }
607 
608 static int h_fakeresolve(int argc, unsigned char **argv){
609 	resolvfunc = fakeresolver;
610 	return 0;
611 }
612 
613 static int h_nscache(int argc, unsigned char **argv){
614   int res;
615 
616 	res = atoi((char *)argv[1]);
617 	if(res < 256) {
618 		fprintf(stderr, "Invalid NS cache size: %d\n", res);
619 		return 1;
620 	}
621 	if(inithashtable(&dns_table, (unsigned)res)){
622 		fprintf(stderr, "Failed to initialize NS cache\n");
623 		return 2;
624 	}
625 	return 0;
626 }
627 
628 static int h_parentretries(int argc, unsigned char **argv){
629   int res;
630 
631 	res = atoi((char *)argv[1]);
632 	if(res > 0) conf.parentretries = res;
633 	return 0;
634 }
635 
636 static int h_nscache6(int argc, unsigned char **argv){
637   int res;
638 
639 	res = atoi((char *)argv[1]);
640 	if(res < 256) {
641 		fprintf(stderr, "Invalid NS cache size: %d\n", res);
642 		return 1;
643 	}
644 	if(inithashtable(&dns6_table, (unsigned)res)){
645 		fprintf(stderr, "Failed to initialize NS cache\n");
646 		return 2;
647 	}
648 	return 0;
649 }
650 
651 static int h_nsrecord(int argc, unsigned char **argv){
652 #ifndef NOIPV6
653 	struct sockaddr_in6 sa;
654 #else
655 	struct sockaddr_in sa;
656 #endif
657 	memset(&sa, 0, sizeof(sa));
658 	if(!getip46(46, argv[2], (struct sockaddr *)&sa)) return 1;
659 
660 	hashadd(*SAFAMILY(&sa)==AF_INET6?&dns6_table:&dns_table, argv[1], SAADDR(&sa), (time_t)0xffffffff);
661 	return 0;
662 }
663 
664 static int h_dialer(int argc, unsigned char **argv){
665 	if(conf.demanddialprog) myfree(conf.demanddialprog);
666 	conf.demanddialprog = mystrdup((char *)argv[1]);
667 	return 0;
668 }
669 
670 static int h_system(int argc, unsigned char **argv){
671   int res;
672 
673 	if((res = system((char *)argv[1])) == -1){
674 		fprintf(stderr, "Failed to start %s\n", argv[1]);
675 		return(1);
676 	}
677 	return 0;
678 }
679 
680 static int h_pidfile(int argc, unsigned char **argv){
681   FILE *pidf;
682 
683 	if(!(pidf = fopen((char *)argv[1], "w"))){
684 		fprintf(stderr, "Failed to open pid file %s\n", argv[1]);
685 		return(1);
686 	}
687 	fprintf(pidf,"%u", (unsigned)getpid());
688 	fclose(pidf);
689 	return 0;
690 }
691 
692 static int h_monitor(int argc, unsigned char **argv){
693   struct filemon * fm;
694 
695 	fm = myalloc(sizeof (struct filemon));
696 	if(!fm) return 21;
697 	if(stat((char *)argv[1], &fm->sb)){
698 		myfree(fm);
699 		fprintf(stderr, "Warning: file %s doesn't exist on line %d\n", argv[1], linenum);
700 	}
701 	else {
702 		fm->path = mystrdup((char *)argv[1]);
703 		if(!fm->path) return 21;
704 		fm->next = conf.fmon;
705 		conf.fmon = fm;
706 	}
707 	return 0;
708 }
709 
710 static int h_parent(int argc, unsigned char **argv){
711   struct ace *acl = NULL;
712   struct chain *chains;
713   char * cidr;
714 
715 	acl = conf.acl;
716 	while(acl && acl->next) acl = acl->next;
717 	if(!acl || (acl->action && acl->action != 2)) {
718 		fprintf(stderr, "Chaining error: last ACL entry was not \"allow\" or \"redirect\" on line %d\n", linenum);
719 		return(1);
720 	}
721 	acl->action = 2;
722 
723 	chains = myalloc(sizeof(struct chain));
724 	if(!chains){
725 		return(21);
726 	}
727 	memset(chains, 0, sizeof(struct chain));
728 	chains->weight = (unsigned)atoi((char *)argv[1]);
729 	if(chains->weight == 0 || chains->weight >1000) {
730 		fprintf(stderr, "Chaining error: bad chain weight %u line %d\n", chains->weight, linenum);
731 		return(3);
732 	}
733 	if(!strcmp((char *)argv[2], "tcp"))chains->type = R_TCP;
734 	else if(!strcmp((char *)argv[2], "http"))chains->type = R_HTTP;
735 	else if(!strcmp((char *)argv[2], "connect"))chains->type = R_CONNECT;
736 	else if(!strcmp((char *)argv[2], "socks4"))chains->type = R_SOCKS4;
737 	else if(!strcmp((char *)argv[2], "socks5"))chains->type = R_SOCKS5;
738 	else if(!strcmp((char *)argv[2], "connect+"))chains->type = R_CONNECTP;
739 	else if(!strcmp((char *)argv[2], "socks4+"))chains->type = R_SOCKS4P;
740 	else if(!strcmp((char *)argv[2], "socks5+"))chains->type = R_SOCKS5P;
741 	else if(!strcmp((char *)argv[2], "socks4b"))chains->type = R_SOCKS4B;
742 	else if(!strcmp((char *)argv[2], "socks5b"))chains->type = R_SOCKS5B;
743 	else if(!strcmp((char *)argv[2], "pop3"))chains->type = R_POP3;
744 	else if(!strcmp((char *)argv[2], "ftp"))chains->type = R_FTP;
745 	else if(!strcmp((char *)argv[2], "admin"))chains->type = R_ADMIN;
746 	else if(!strcmp((char *)argv[2], "extip"))chains->type = R_EXTIP;
747 	else if(!strcmp((char *)argv[2], "smtp"))chains->type = R_SMTP;
748 	else {
749 		fprintf(stderr, "Chaining error: bad chain type (%s)\n", argv[2]);
750 		return(4);
751 	}
752 	cidr = strchr(argv[3], '/');
753 	if(cidr) *cidr = 0;
754 	getip46(46, argv[3], (struct sockaddr *)&chains->addr);
755 	chains->exthost = (unsigned char *)mystrdup((char *)argv[3]);
756 	if(!chains->exthost) return 21;
757 	if(cidr){
758 		*cidr = '/';
759 		chains->cidr = atoi(cidr + 1);
760 	}
761 	*SAPORT(&chains->addr) = htons((unsigned short)atoi((char *)argv[4]));
762 	if(argc > 5) chains->extuser = (unsigned char *)mystrdup((char *)argv[5]);
763 	if(argc > 6) chains->extpass = (unsigned char *)mystrdup((char *)argv[6]);
764 	if(!acl->chains) {
765 		acl->chains = chains;
766 	}
767 	else {
768 		struct chain *tmpchain;
769 
770 		for(tmpchain = acl->chains; tmpchain->next; tmpchain = tmpchain->next);
771 		tmpchain->next = chains;
772 	}
773 	return 0;
774 
775 }
776 
777 static int h_nolog(int argc, unsigned char **argv){
778   struct ace *acl = NULL;
779 
780 	acl = conf.acl;
781 	if(!acl) {
782 		fprintf(stderr, "Chaining error: last ACL entry was not \"allow/deny\" on line %d\n", linenum);
783 		return(1);
784 	}
785 	while(acl->next) acl = acl->next;
786 	if(argc == 1) acl->nolog = 1;
787 	else acl->weight = atoi((char*)argv[1]);
788 	return 0;
789 }
790 
791 int scanipl(unsigned char *arg, struct iplist *dst){
792 #ifndef NOIPV6
793 	struct sockaddr_in6 sa;
794 #else
795 	struct sockaddr_in sa;
796 #endif
797         char * slash, *dash;
798 	int masklen, addrlen;
799 	int res;
800 
801 	if((slash = strchr((char *)arg, '/'))) *slash = 0;
802 	if((dash = strchr((char *)arg,'-'))) *dash = 0;
803 
804 	if(afdetect(arg) == -1) {
805 		if(slash)*slash = '/';
806 		if(dash)*dash = '-';
807 		return 1;
808 	}
809 	res = getip46(46, arg, (struct sockaddr *)&sa);
810 	if(dash)*dash = '-';
811 	if(!res) return 1;
812 	memcpy(&dst->ip_from, SAADDR(&sa), SAADDRLEN(&sa));
813 	dst->family = *SAFAMILY(&sa);
814 	if(dash){
815 		if(afdetect(dash+1) == -1) return 1;
816 		if(!getip46(46, (unsigned char *)dash+1, (struct sockaddr *)&sa)) return 2;
817 		memcpy(&dst->ip_to, SAADDR(&sa), SAADDRLEN(&sa));
818 		if(*SAFAMILY(&sa) != dst->family || memcmp(&dst->ip_to, &dst->ip_from, SAADDRLEN(&sa)) < 0) return 3;
819 		return 0;
820 	}
821 	memcpy(&dst->ip_to, &dst->ip_from, SAADDRLEN(&sa));
822 	if(slash){
823 		*slash = '/';
824 		addrlen = SAADDRLEN(&sa);
825 		masklen = atoi(slash+1);
826 		if(masklen < 0 || masklen > (addrlen*8)) return 4;
827 		else {
828 			int i, nbytes = masklen / 8, nbits = (8 - (masklen % 8)) % 8;
829 
830 			for(i = addrlen; i>(nbytes + (nbits > 0)); i--){
831 				((unsigned char *)&dst->ip_from)[i-1] = 0x00;
832 				((unsigned char *)&dst->ip_to)[i-1] = 0xff;
833 			}
834 			for(;nbits;nbits--){
835 				((unsigned char *)&dst->ip_from)[nbytes] &= ~(0x01<<(nbits-1));
836 				((unsigned char *)&dst->ip_to)[nbytes] |= (0x01<<(nbits-1));
837 			}
838 			return 0;
839 		}
840 	}
841 	return 0;
842 }
843 
844 struct ace * make_ace (int argc, unsigned char ** argv){
845 	struct ace * acl;
846 	unsigned char *arg;
847 	struct iplist *ipl=NULL;
848 	struct portlist *portl=NULL;
849 	struct userlist *userl=NULL;
850 	struct hostname *hostnamel=NULL;
851 	int res;
852 
853 	acl = myalloc(sizeof(struct ace));
854 	if(!acl) return acl;
855 	memset(acl, 0, sizeof(struct ace));
856 		if(argc > 0 && strcmp("*", (char *)argv[0])) {
857 			arg = argv[0];
858 			arg = (unsigned char *)strtok((char *)arg, ",");
859 			do {
860 				if(!acl->users) {
861 					acl->users = userl = myalloc(sizeof(struct userlist));
862 				}
863 				else {
864 					userl->next = myalloc(sizeof(struct userlist));
865 					userl = userl -> next;
866 				}
867 				if(!userl) {
868 					fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
869 					return(NULL);
870 				}
871 				memset(userl, 0, sizeof(struct userlist));
872 				userl->user=(unsigned char*)mystrdup((char *)arg);
873 				if(!userl->user) return NULL;
874 			} while((arg = (unsigned char *)strtok((char *)NULL, ",")));
875 		}
876 		if(argc > 1  && strcmp("*", (char *)argv[1])) {
877 			arg = (unsigned char *)strtok((char *)argv[1], ",");
878 			do {
879 				if(!acl->src) {
880 					acl->src = ipl = myalloc(sizeof(struct iplist));
881 				}
882 				else {
883 					ipl->next = myalloc(sizeof(struct iplist));
884 					ipl = ipl -> next;
885 				}
886 				if(!ipl) {
887 					fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
888 					return(NULL);
889 				}
890 				memset(ipl, 0, sizeof(struct iplist));
891 				if (scanipl(arg, ipl)) {
892 					fprintf(stderr, "Invalid IP, IP range or CIDR, line %d\n", linenum);
893 					return(NULL);
894 				}
895 			} while((arg = (unsigned char *)strtok((char *)NULL, ",")));
896 		}
897 		if(argc > 2 && strcmp("*", (char *)argv[2])) {
898 			arg = (unsigned char *)strtok((char *)argv[2], ",");
899 			do {
900 			 int arglen;
901 			 unsigned char *pattern;
902 			 struct iplist tmpip={NULL};
903 
904 			 arglen = (int)strlen((char *)arg);
905 			 if(scanipl(arg, &tmpip)){
906 				if(!arglen) continue;
907 				if(!acl->dstnames) {
908 					acl->dstnames = hostnamel = myalloc(sizeof(struct hostname));
909 				}
910 				else {
911 					hostnamel->next = myalloc(sizeof(struct hostname));
912 					hostnamel = hostnamel -> next;
913 				}
914 				if(!hostnamel){
915 					fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
916 					return(NULL);
917 				}
918 				memset(hostnamel, 0, sizeof(struct hostname));
919 				hostnamel->matchtype = 3;
920 				pattern = arg;
921 				if(pattern[arglen-1] == '*'){
922 					arglen --;
923 					pattern[arglen] = 0;
924 					hostnamel->matchtype ^= MATCHEND;
925 				}
926 				if(pattern[0] == '*'){
927 					pattern++;
928 					arglen--;
929 					hostnamel->matchtype ^= MATCHBEGIN;
930 				}
931 				hostnamel->name = (unsigned char *) mystrdup( (char *)pattern);
932 				if(!hostnamel->name) {
933 					fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
934 					return(NULL);
935 				}
936 			 }
937 			 else {
938 
939 				if(!acl->dst) {
940 					acl->dst = ipl = myalloc(sizeof(struct iplist));
941 				}
942 				else {
943 					ipl->next = myalloc(sizeof(struct iplist));
944 					ipl = ipl -> next;
945 				}
946 				if(!ipl) {
947 					fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
948 					return(NULL);
949 				}
950 				*ipl = tmpip;
951 			 }
952 			}while((arg = (unsigned char *)strtok((char *)NULL, ",")));
953 		}
954 		if(argc > 3 && strcmp("*", (char *)argv[3])) {
955 			arg = (unsigned char *)strtok((char *)argv[3], ",");
956 			do {
957 				if(!acl->ports) {
958 					acl->ports = portl = myalloc(sizeof(struct portlist));
959 				}
960 				else {
961 					portl->next = myalloc(sizeof(struct portlist));
962 					portl = portl -> next;
963 				}
964 				if(!portl) {
965 					fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
966 					return(NULL);
967 				}
968 				memset(portl, 0, sizeof(struct portlist));
969 				res = sscanf((char *)arg, "%hu-%hu", &portl->startport, &portl->endport);
970 				if(res < 1) {
971 					fprintf(stderr, "Invalid port or port range, line %d\n", linenum);
972 					return(NULL);
973 				}
974 				if (res == 1) portl->endport = portl->startport;
975 			} while((arg = (unsigned char *)strtok((char *)NULL, ",")));
976 		}
977 		if(argc > 4 && strcmp("*", (char *)argv[4])) {
978 			arg = (unsigned char *)strtok((char *)argv[4], ",");
979 			do {
980 				if(!strcmp((char *)arg, "CONNECT")){
981 					acl->operation |= CONNECT;
982 				}
983 				else if(!strcmp((char *)arg, "BIND")){
984 					acl->operation |= BIND;
985 				}
986 				else if(!strcmp((char *)arg, "UDPASSOC")){
987 					acl->operation |= UDPASSOC;
988 				}
989 				else if(!strcmp((char *)arg, "ICMPASSOC")){
990 					acl->operation |= ICMPASSOC;
991 				}
992 				else if(!strcmp((char *)arg, "HTTP_GET")){
993 					acl->operation |= HTTP_GET;
994 				}
995 				else if(!strcmp((char *)arg, "HTTP_PUT")){
996 					acl->operation |= HTTP_PUT;
997 				}
998 				else if(!strcmp((char *)arg, "HTTP_POST")){
999 					acl->operation |= HTTP_POST;
1000 				}
1001 				else if(!strcmp((char *)arg, "HTTP_HEAD")){
1002 					acl->operation |= HTTP_HEAD;
1003 				}
1004 				else if(!strcmp((char *)arg, "HTTP_OTHER")){
1005 					acl->operation |= HTTP_OTHER;
1006 				}
1007 				else if(!strcmp((char *)arg, "HTTP_CONNECT")){
1008 					acl->operation |= HTTP_CONNECT;
1009 				}
1010 				else if(!strcmp((char *)arg, "HTTP")){
1011 					acl->operation |= HTTP;
1012 				}
1013 				else if(!strcmp((char *)arg, "HTTPS")){
1014 					acl->operation |= HTTPS;
1015 				}
1016 				else if(!strcmp((char *)arg, "FTP_GET")){
1017 					acl->operation |= FTP_GET;
1018 				}
1019 				else if(!strcmp((char *)arg, "FTP_PUT")){
1020 					acl->operation |= FTP_PUT;
1021 				}
1022 				else if(!strcmp((char *)arg, "FTP_LIST")){
1023 					acl->operation |= FTP_LIST;
1024 				}
1025 				else if(!strcmp((char *)arg, "FTP_DATA")){
1026 					acl->operation |= FTP_DATA;
1027 				}
1028 				else if(!strcmp((char *)arg, "FTP")){
1029 					acl->operation |= FTP;
1030 				}
1031 				else if(!strcmp((char *)arg, "ADMIN")){
1032 					acl->operation |= ADMIN;
1033 				}
1034 				else if(!strcmp((char *)arg, "DNSRESOLVE")){
1035 					acl->operation |= DNSRESOLVE;
1036 				}
1037 				else {
1038 					fprintf(stderr, "Unknown operation type: %s line %d\n", arg, linenum);
1039 					return(NULL);
1040 				}
1041 			} while((arg = (unsigned char *)strtok((char *)NULL, ",")));
1042 		}
1043 		if(argc > 5){
1044 			for(arg = argv[5]; *arg;){
1045 				int val, val1;
1046 
1047 				if(!isnumber(*arg)){
1048 					arg++;
1049 					continue;
1050 				}
1051 				val1 = val = (*arg - '0');
1052 				arg++;
1053 				if(*arg == '-' && isnumber(*(arg+1)) && (*(arg+1) - '0') > val) {
1054 					val1 = (*(arg+1) - '0');
1055 					arg+=2;
1056 				}
1057 				for(; val<=val1; val++) acl->wdays |= (1 << (val % 7));
1058 			}
1059 
1060 		}
1061 		if(argc > 6){
1062 			for(arg = argv[6]; strlen((char *)arg) >= 17 &&
1063 							isdigit(arg[0]) &&
1064 							isdigit(arg[1]) &&
1065 							isdigit(arg[3]) &&
1066 							isdigit(arg[4]) &&
1067 							isdigit(arg[6]) &&
1068 							isdigit(arg[7]) &&
1069 							isdigit(arg[9]) &&
1070 							isdigit(arg[10]) &&
1071 							isdigit(arg[12]) &&
1072 							isdigit(arg[13]) &&
1073 							isdigit(arg[15]) &&
1074 							isdigit(arg[16])
1075 							; arg+=18){
1076 
1077 				int t1, t2;
1078 				struct period *sp;
1079 
1080 				t1 = (arg[0] - '0') * 10 + (arg[1] - '0');
1081 				t1 = (t1 * 60) + (arg[3] - '0') * 10 + (arg[4] - '0');
1082 				t1 = (t1 * 60) + (arg[6] - '0') * 10 + (arg[7] - '0');
1083 				t2 = (arg[9] - '0') * 10 + (arg[10] - '0');
1084 				t2 = (t2 * 60) + (arg[12] - '0') * 10 + (arg[13] - '0');
1085 				t2 = (t2 * 60) + (arg[15] - '0') * 10 + (arg[16] - '0');
1086 				if(t2 < t1) break;
1087 				sp = myalloc(sizeof(struct period));
1088 				if(sp){
1089 					sp->fromtime = t1;
1090 					sp->totime = t2;
1091 					sp->next = acl->periods;
1092 					acl->periods = sp;
1093 				}
1094 				if(arg[17]!=',') break;
1095 			}
1096 		}
1097 	if (argc > 7){
1098 		acl->weight = atoi((char *)argv[7]);
1099 	}
1100 
1101 	return acl;
1102 }
1103 
1104 
1105 static int h_ace(int argc, unsigned char **argv){
1106   int res = 0;
1107   int offset = 0;
1108   struct ace *acl = NULL;
1109   struct bandlim * nbl;
1110   struct trafcount * tl;
1111   struct connlim * ncl;
1112 
1113 	if(!strcmp((char *)argv[0], "allow")){
1114 		res = ALLOW;
1115 	}
1116 	else if(!strcmp((char *)argv[0], "deny")){
1117 		res = DENY;
1118 	}
1119 	else if(!strcmp((char *)argv[0], "redirect")){
1120 		res = REDIRECT;
1121 		offset = 2;
1122 	}
1123 	else if(!strcmp((char *)argv[0], "bandlimin")||!strcmp((char *)argv[0], "bandlimout")){
1124 		res = BANDLIM;
1125 		offset = 1;
1126 	}
1127 	else if(!strcmp((char *)argv[0], "nobandlimin")||!strcmp((char *)argv[0], "nobandlimout")){
1128 		res = NOBANDLIM;
1129 	}
1130 	else if(!strcmp((char *)argv[0], "countin")){
1131 		res = COUNTIN;
1132 		offset = 3;
1133 	}
1134 	else if(!strcmp((char *)argv[0], "nocountin")){
1135 		res = NOCOUNTIN;
1136 	}
1137 	else if(!strcmp((char *)argv[0], "countout")){
1138 		res = COUNTOUT;
1139 		offset = 3;
1140 	}
1141 	else if(!strcmp((char *)argv[0], "nocountout")){
1142 		res = NOCOUNTOUT;
1143 	}
1144 	else if(!strcmp((char *)argv[0], "countall")){
1145 		res = COUNTALL;
1146 		offset = 3;
1147 	}
1148 	else if(!strcmp((char *)argv[0], "nocountall")){
1149 		res = NOCOUNTALL;
1150 	}
1151 	else if(!strcmp((char *)argv[0], "connlim")){
1152 		res = CONNLIM;
1153 		offset = 2;
1154 	}
1155 	else if(!strcmp((char *)argv[0], "noconnlim")){
1156 		res = NOCONNLIM;
1157 	}
1158 	acl = make_ace(argc - (offset+1), argv + (offset + 1));
1159 	if(!acl) {
1160 		fprintf(stderr, "Unable to parse ACL entry, line %d\n", linenum);
1161 		return(1);
1162 	}
1163 	acl->action = res;
1164 	switch(acl->action){
1165 	case REDIRECT:
1166 		acl->chains = myalloc(sizeof(struct chain));
1167 		if(!acl->chains) {
1168 			freeacl(acl);
1169 			return(21);
1170 		}
1171 		memset(acl->chains, 0, sizeof(struct chain));
1172 		acl->chains->type = R_HTTP;
1173 		if(!getip46(46, argv[1], (struct sockaddr *)&acl->chains->addr)) return 5;
1174 		*SAPORT(&acl->chains->addr) = htons((unsigned short)atoi((char *)argv[2]));
1175 		acl->chains->weight = 1000;
1176 	case ALLOW:
1177 	case DENY:
1178 		if(!conf.acl){
1179 			conf.acl = acl;
1180 		}
1181 		else {
1182 			struct ace * acei;
1183 
1184 			for(acei = conf.acl; acei->next; acei = acei->next);
1185 			acei->next = acl;
1186 		}
1187 		break;
1188 	case CONNLIM:
1189 	case NOCONNLIM:
1190 		ncl = myalloc(sizeof(struct connlim));
1191 		if(!ncl) {
1192 			freeacl(acl);
1193 			return(21);
1194 		}
1195 		memset(ncl, 0, sizeof(struct connlim));
1196 		ncl->ace = acl;
1197 		if(acl->action == CONNLIM) {
1198 			sscanf((char *)argv[1], "%u", &ncl->rate);
1199 			sscanf((char *)argv[2], "%u", &ncl->period);
1200 		}
1201 		pthread_mutex_lock(&connlim_mutex);
1202 		if(!conf.connlimiter){
1203 			conf.connlimiter = ncl;
1204 		}
1205 		else {
1206 			struct connlim * cli;
1207 
1208 			for(cli = conf.connlimiter; cli->next; cli = cli->next);
1209 			cli->next = ncl;
1210 		}
1211 		pthread_mutex_unlock(&connlim_mutex);
1212 		break;
1213 
1214 	case BANDLIM:
1215 	case NOBANDLIM:
1216 
1217 		nbl = myalloc(sizeof(struct bandlim));
1218 		if(!nbl) {
1219 			freeacl(acl);
1220 			return(21);
1221 		}
1222 		memset(nbl, 0, sizeof(struct bandlim));
1223 		nbl->ace = acl;
1224 		if(acl->action == BANDLIM) {
1225 			sscanf((char *)argv[1], "%u", &nbl->rate);
1226 			if(nbl->rate < 300) {
1227 				myfree(nbl);
1228 				freeacl(acl);
1229 				fprintf(stderr, "Wrong bandwidth specified, line %d\n", linenum);
1230 				return(4);
1231 			}
1232 		}
1233 		pthread_mutex_lock(&bandlim_mutex);
1234 		if(!strcmp((char *)argv[0], "bandlimin") || !strcmp((char *)argv[0], "nobandlimin")){
1235 			if(!conf.bandlimiter){
1236 				conf.bandlimiter = nbl;
1237 			}
1238 			else {
1239 				struct bandlim * bli;
1240 
1241 				for(bli = conf.bandlimiter; bli->next; bli = bli->next);
1242 				bli->next = nbl;
1243 			}
1244 		}
1245 		else {
1246 			if(!conf.bandlimiterout){
1247 				conf.bandlimiterout = nbl;
1248 			}
1249 			else {
1250 				struct bandlim * bli;
1251 
1252 				for(bli = conf.bandlimiterout; bli->next; bli = bli->next);
1253 				bli->next = nbl;
1254 			}
1255 		}
1256 		conf.bandlimver++;
1257 		pthread_mutex_unlock(&bandlim_mutex);
1258 		break;
1259 
1260 	case COUNTIN:
1261 	case NOCOUNTIN:
1262 	case COUNTOUT:
1263 	case NOCOUNTOUT:
1264 	case COUNTALL:
1265 	case NOCOUNTALL:
1266 		if(!conf.trafcountfunc) conf.trafcountfunc = trafcountfunc;
1267 		tl = myalloc(sizeof(struct trafcount));
1268 		if(!tl) {
1269 			freeacl(acl);
1270 			return(21);
1271 		}
1272 		memset(tl, 0, sizeof(struct trafcount));
1273 		tl->ace = acl;
1274 
1275 		if((acl->action == COUNTIN)||(acl->action == COUNTOUT)||(acl->action == COUNTALL)) {
1276 			unsigned long lim;
1277 
1278 			tl->comment = ( char *)argv[1];
1279 			while(isdigit(*tl->comment))tl->comment++;
1280 			if(*tl->comment== '/')tl->comment++;
1281 			tl->comment = mystrdup(tl->comment);
1282 
1283 			sscanf((char *)argv[1], "%u", &tl->number);
1284 			sscanf((char *)argv[3], "%lu", &lim);
1285 			tl->type = getrotate(*argv[2]);
1286 			tl->traflim64 =  ((uint64_t)lim)*(1024*1024);
1287 			if(!tl->traflim64) {
1288 				myfree(tl);
1289 				freeacl(acl);
1290 				fprintf(stderr, "Wrong traffic limit specified, line %d\n", linenum);
1291 				return(6);
1292 			}
1293 			if(tl->number != 0 && conf.counterd >= 0) {
1294 				lseek(conf.counterd,
1295 					sizeof(struct counter_header) + (tl->number - 1) * sizeof(struct counter_record),
1296 					SEEK_SET);
1297 				memset(&crecord, 0, sizeof(struct counter_record));
1298 				read(conf.counterd, &crecord, sizeof(struct counter_record));
1299 				tl->traf64 = crecord.traf64;
1300 				tl->cleared = crecord.cleared;
1301 				tl->updated = crecord.updated;
1302 				if(tl->cleared < 0 || tl->cleared >=  MAX_COUNTER_TIME || tl->updated < 0 || tl->updated >=  MAX_COUNTER_TIME){
1303 					fprintf(stderr, "Invalid, incompatible or corrupted counter file.\n");
1304 					return(6);
1305 				}
1306 			}
1307 		}
1308 		pthread_mutex_lock(&tc_mutex);
1309 		if(!conf.trafcounter){
1310 			conf.trafcounter = tl;
1311 		}
1312 		else {
1313 			struct trafcount * ntl;
1314 
1315 			for(ntl = conf.trafcounter; ntl->next; ntl = ntl->next);
1316 			ntl->next = tl;
1317 		}
1318 		pthread_mutex_unlock(&tc_mutex);
1319 
1320 	}
1321 	return 0;
1322 }
1323 
1324 static int h_logdump(int argc, unsigned char **argv){
1325 	conf.logdumpsrv = (unsigned) atoi((char *) *(argv + 1));
1326 	if(argc > 2) conf.logdumpcli = (unsigned) atoi((char *) *(argv + 2));
1327 	return 0;
1328 }
1329 
1330 
1331 static int h_filtermaxsize(int argc, unsigned char **argv){
1332 	conf.filtermaxsize = atoi((char *) *(argv + 1));
1333 	return 0;
1334 }
1335 
1336 static int h_delimchar(int argc, unsigned char **argv){
1337 	conf.delimchar = *argv[1];
1338 	return 0;
1339 }
1340 
1341 
1342 #ifndef NORADIUS
1343 static int h_radius(int argc, unsigned char **argv){
1344 	unsigned short port;
1345 
1346 /*
1347 	int oldrad;
1348 #ifdef NOIPV6
1349 	struct  sockaddr_in bindaddr;
1350 #else
1351 	struct  sockaddr_in6 bindaddr;
1352 #endif
1353 
1354 	oldrad = nradservers;
1355 	nradservers = 0;
1356 	for(; oldrad; oldrad--){
1357 		if(radiuslist[oldrad].logsock >= 0) so._closesocket(radiuslist[oldrad].logsock);
1358 		radiuslist[oldrad].logsock = -1;
1359 	}
1360 */
1361 	memset(radiuslist, 0, sizeof(radiuslist));
1362 	if(strlen(argv[1]) > 63) argv[1][63] = 0;
1363 	strcpy(radiussecret, argv[1]);
1364 	for( nradservers=0; nradservers < MAXRADIUS && nradservers < argc -2; nradservers++){
1365 		char *s = 0;
1366 		if((s=strchr(argv[nradservers + 2], '/'))){
1367 			*s = 0;
1368 			s++;
1369 		}
1370 		if( !getip46(46, argv[nradservers + 2], (struct sockaddr *)&radiuslist[nradservers].authaddr)) return 1;
1371 		if( s && !getip46(46, s+1, (struct sockaddr *)&radiuslist[nradservers].localaddr)) return 2;
1372 		if(!*SAPORT(&radiuslist[nradservers].authaddr))*SAPORT(&radiuslist[nradservers].authaddr) = htons(1812);
1373 		port = ntohs(*SAPORT(&radiuslist[nradservers].authaddr));
1374 		radiuslist[nradservers].logaddr = radiuslist[nradservers].authaddr;
1375  	        *SAPORT(&radiuslist[nradservers].logaddr) = htons(port+1);
1376 /*
1377 		bindaddr = radiuslist[nradservers].localaddr;
1378 		if ((radiuslist[nradservers].logsock = so._socket(SASOCK(&radiuslist[nradservers].logaddr), SOCK_DGRAM, 0)) < 0) return 2;
1379 		if (so._bind(radiuslist[nradservers].logsock, (struct sockaddr *)&bindaddr, SASIZE(&bindaddr))) return 3;
1380 */
1381 	}
1382 	return 0;
1383 }
1384 #endif
1385 static int h_authcache(int argc, unsigned char **argv){
1386 	conf.authcachetype = 0;
1387 	if(strstr((char *) *(argv + 1), "ip")) conf.authcachetype |= 1;
1388 	if(strstr((char *) *(argv + 1), "user")) conf.authcachetype |= 2;
1389 	if(strstr((char *) *(argv + 1), "pass")) conf.authcachetype |= 4;
1390 	if(strstr((char *) *(argv + 1), "limit")) conf.authcachetype |= 8;
1391 	if(strstr((char *) *(argv + 1), "acl")) conf.authcachetype |= 16;
1392 	if(strstr((char *) *(argv + 1), "ext")) conf.authcachetype |= 32;
1393 	if(argc > 2) conf.authcachetime = (unsigned) atoi((char *) *(argv + 2));
1394 	if(!conf.authcachetype) conf.authcachetype = 6;
1395 	if(!conf.authcachetime) conf.authcachetime = 600;
1396 	return 0;
1397 }
1398 
1399 static int h_plugin(int argc, unsigned char **argv){
1400 #ifdef NOPLUGINS
1401 	return 999;
1402 #else
1403 #ifdef _WIN32
1404 	HINSTANCE hi;
1405 	FARPROC fp;
1406 
1407 #ifdef _WINCE
1408 	hi = LoadLibraryW((LPCWSTR)CEToUnicode(argv[1]));
1409 #else
1410 	hi = LoadLibrary((char *)argv[1]);
1411 #endif
1412 	if(!hi) {
1413 		fprintf(stderr, "Failed to load %s, code %d\n", argv[1], (int)GetLastError());
1414 		return 1;
1415 	}
1416 #ifdef _WINCE
1417 	fp = GetProcAddressW(hi, (LPCWSTR)CEToUnicode(argv[2]));
1418 #else
1419 	fp = GetProcAddress(hi, (char *)argv[2]);
1420 #endif
1421 	if(!fp) {
1422 		printf("%s not found in %s, code: %d\n", argv[2], argv[1], (int)GetLastError());
1423 		return 2;
1424 	}
1425 	return (*(PLUGINFUNC)fp)(&pluginlink, argc - 2, (char **)argv + 2);
1426 #else
1427 	void *hi, *fp;
1428 	hi = dlopen((char *)argv[1], RTLD_LAZY);
1429 	if(!hi) return 1;
1430 	fp = dlsym(hi, (char *)argv[2]);
1431 	if(!fp) return 2;
1432 	return (*(PLUGINFUNC)fp)(&pluginlink, argc - 2, (char **)argv + 2);
1433 #endif
1434 #endif
1435 }
1436 
1437 #ifndef _WIN32
1438 
1439 uid_t strtouid(unsigned char *str){
1440  uid_t res = 0;
1441 
1442 	if(!isnumber(*(char *)str)){
1443 		struct passwd *pw;
1444 		pw = getpwnam((char *)str);
1445 		if(pw) res = pw->pw_uid;
1446 	}
1447 	else res = atoi((char *)str);
1448 	return res;
1449 }
1450 
1451 
1452 static int h_setuid(int argc, unsigned char **argv){
1453   uid_t res = 0;
1454 	res = strtouid(argv[1]);
1455 	if(!res || setreuid(res,res)) {
1456 		fprintf(stderr, "Unable to set uid %d", res);
1457 		return(1);
1458 	}
1459 	return 0;
1460 }
1461 
1462 gid_t strtogid(unsigned char *str){
1463   gid_t res = 0;
1464 
1465 	if(!isnumber(*(char *)str)){
1466 		struct group *gr;
1467 		gr = getgrnam((char *)str);
1468 		if(gr) res = gr->gr_gid;
1469 	}
1470 	else res = atoi((char *)str);
1471 	return res;
1472 }
1473 
1474 static int h_setgid(int argc, unsigned char **argv){
1475   gid_t res = 0;
1476 
1477 	res = strtogid(argv[1]);
1478 	if(!res || setregid(res,res)) {
1479 		fprintf(stderr, "Unable to set gid %d", res);
1480 		return(1);
1481 	}
1482 	return 0;
1483 }
1484 
1485 
1486 static int h_chroot(int argc, unsigned char **argv){
1487 	uid_t uid = 0;
1488 	gid_t gid = 0;
1489 	if(argc > 2) {
1490 		uid = strtouid(argv[2]);
1491 		if(!uid){
1492 			fprintf(stderr, "Unable to resolve uid %s", argv[2]);
1493 			return(2);
1494 		}
1495         }
1496 	if(argc > 3) {
1497 		gid = strtogid(argv[3]);
1498 		if(!gid){
1499 			fprintf(stderr, "Unable to resolve gid %s", argv[3]);
1500 			return(3);
1501 		}
1502         }
1503 	if(!chrootp){
1504 		char *p;
1505 		if(chroot((char *)argv[1])) {
1506 			fprintf(stderr, "Unable to chroot %s", argv[1]);
1507 			return(1);
1508 		}
1509 		p = (char *)argv[1] + strlen((char *)argv[1]) ;
1510 		while (p > (char *)argv[1] && p[-1] == '/'){
1511 			p--;
1512 			*p = 0;
1513 		}
1514 		chrootp = mystrdup((char *)argv[1]);
1515 		if(!chrootp) return 21;
1516 	}
1517 	if (gid && setregid(gid,gid)) {
1518 		fprintf(stderr, "Unable to set gid %d", (int)gid);
1519 		return(4);
1520 	}
1521 	if (uid && setreuid(uid,uid)) {
1522 		fprintf(stderr, "Unable to set uid %d", (int)uid);
1523 		return(5);
1524 	}
1525 	chdir("/");
1526 	return 0;
1527 }
1528 #endif
1529 
1530 
1531 struct commands specificcommands[]={
1532 #ifndef _WIN32
1533 	{specificcommands+1, "setuid", h_setuid, 2, 2},
1534 	{specificcommands+2, "setgid", h_setgid, 2, 2},
1535 	{specificcommands+3, "chroot", h_chroot, 2, 4},
1536 #endif
1537 	{NULL, 		"", h_noop, 1, 0}
1538 };
1539 
1540 struct commands commandhandlers[]={
1541 	{commandhandlers+1,  "", h_noop, 1, 0},
1542 	{commandhandlers+2,  "proxy", h_proxy, 1, 0},
1543 	{commandhandlers+3,  "pop3p", h_proxy, 1, 0},
1544 	{commandhandlers+4,  "ftppr", h_proxy, 1, 0},
1545 	{commandhandlers+5,  "socks", h_proxy, 1, 0},
1546 	{commandhandlers+6,  "tcppm", h_proxy, 4, 0},
1547 	{commandhandlers+7,  "udppm", h_proxy, 4, 0},
1548 	{commandhandlers+8,  "admin", h_proxy, 1, 0},
1549 	{commandhandlers+9,  "dnspr", h_proxy, 1, 0},
1550 	{commandhandlers+10,  "internal", h_internal, 2, 2},
1551 	{commandhandlers+11, "external", h_external, 2, 2},
1552 	{commandhandlers+12, "log", h_log, 1, 0},
1553 	{commandhandlers+13, "service", h_service, 1, 1},
1554 	{commandhandlers+14, "daemon", h_daemon, 1, 1},
1555 	{commandhandlers+15, "config", h_config, 2, 2},
1556 	{commandhandlers+16, "include", h_include, 2, 2},
1557 	{commandhandlers+17, "archiver", h_archiver, 3, 0},
1558 	{commandhandlers+18, "counter", h_counter, 2, 4},
1559 	{commandhandlers+19, "rotate", h_rotate, 2, 2},
1560 	{commandhandlers+20, "logformat", h_logformat, 2, 2},
1561 	{commandhandlers+21, "timeouts", h_timeouts, 2, 0},
1562 	{commandhandlers+22, "auth", h_auth, 2, 0},
1563 	{commandhandlers+23, "users", h_users, 1, 0},
1564 	{commandhandlers+24, "maxconn", h_maxconn, 2, 2},
1565 	{commandhandlers+25, "flush", h_flush, 1, 1},
1566 	{commandhandlers+26, "nserver", h_nserver, 2, 2},
1567 	{commandhandlers+27, "fakeresolve", h_fakeresolve, 1, 1},
1568 	{commandhandlers+28, "nscache", h_nscache, 2, 2},
1569 	{commandhandlers+29, "nscache6", h_nscache6, 2, 2},
1570 	{commandhandlers+30, "nsrecord", h_nsrecord, 3, 3},
1571 	{commandhandlers+31, "dialer", h_dialer, 2, 2},
1572 	{commandhandlers+32, "system", h_system, 2, 2},
1573 	{commandhandlers+33, "pidfile", h_pidfile, 2, 2},
1574 	{commandhandlers+34, "monitor", h_monitor, 2, 2},
1575 	{commandhandlers+35, "parent", h_parent, 5, 0},
1576 	{commandhandlers+36, "allow", h_ace, 1, 0},
1577 	{commandhandlers+37, "deny", h_ace, 1, 0},
1578 	{commandhandlers+38, "redirect", h_ace, 3, 0},
1579 	{commandhandlers+39, "bandlimin", h_ace, 2, 0},
1580 	{commandhandlers+40, "bandlimout", h_ace, 2, 0},
1581 	{commandhandlers+41, "nobandlimin", h_ace, 1, 0},
1582 	{commandhandlers+42, "nobandlimout", h_ace, 1, 0},
1583 	{commandhandlers+43, "countin", h_ace, 4, 0},
1584 	{commandhandlers+44, "nocountin", h_ace, 1, 0},
1585 	{commandhandlers+45, "countout", h_ace, 4, 0},
1586 	{commandhandlers+46, "nocountout", h_ace, 1, 0},
1587 	{commandhandlers+47, "countall", h_ace, 4, 0},
1588 	{commandhandlers+48, "nocountall", h_ace, 1, 0},
1589 	{commandhandlers+49, "connlim", h_ace, 4, 0},
1590 	{commandhandlers+50, "noconnlim", h_ace, 1, 0},
1591 	{commandhandlers+51, "plugin", h_plugin, 3, 0},
1592 	{commandhandlers+52, "logdump", h_logdump, 2, 3},
1593 	{commandhandlers+53, "filtermaxsize", h_filtermaxsize, 2, 2},
1594 	{commandhandlers+54, "nolog", h_nolog, 1, 1},
1595 	{commandhandlers+55, "weight", h_nolog, 2, 2},
1596 	{commandhandlers+56, "authcache", h_authcache, 2, 3},
1597 	{commandhandlers+57, "smtpp", h_proxy, 1, 0},
1598 	{commandhandlers+58, "delimchar",h_delimchar, 2, 2},
1599 	{commandhandlers+59, "authnserver", h_authnserver, 2, 2},
1600 	{commandhandlers+60, "stacksize", h_stacksize, 2, 2},
1601 	{commandhandlers+61, "force", h_force, 1, 1},
1602 	{commandhandlers+62, "noforce", h_noforce, 1, 1},
1603 	{commandhandlers+63, "parentretries", h_parentretries, 2, 2},
1604 #ifndef NORADIUS
1605 	{commandhandlers+64, "radius", h_radius, 3, 0},
1606 #endif
1607 	{specificcommands, 	 "", h_noop, 1, 0}
1608 };
1609 
1610 int parsestr (unsigned char *str, unsigned char **argm, int nitems, unsigned char ** buff, int *inbuf, int *bufsize){
1611 #define buf (*buff)
1612 	int argc = 0;
1613 	int space = 1;
1614 	int comment = 0;
1615 	unsigned char * incbegin = 0;
1616 	int fd;
1617 	int res, len;
1618 	unsigned char *str1;
1619 
1620 	for(;;str++){
1621 	 if(*str == '\"'){
1622 		str1 = str;
1623 		do {
1624 			*str1 = *(str1 + 1);
1625 		}while(*(str1++));
1626 		if(!comment || *str != '\"'){
1627 			comment = !comment;
1628 		}
1629 	 }
1630          switch(*str){
1631 		case '\0':
1632 			if(comment) return -1;
1633 			argm[argc] = 0;
1634 			return argc;
1635 		case '$':
1636 			if(comment){
1637 				if(space){
1638 					argm[argc++] = str;
1639 					if(argc >= nitems) return argc;
1640 					space = 0;
1641 				}
1642 			}
1643 			else if(!included){
1644 				incbegin = str;
1645 				*str = 0;
1646 			}
1647 			break;
1648 		case '\r':
1649 		case '\n':
1650 		case '\t':
1651 		case ' ':
1652 			if(!comment){
1653 				*str = 0;
1654 				space = 1;
1655 				if(incbegin){
1656 					argc--;
1657 					if((fd = open((char *)incbegin+1, O_RDONLY)) <= 0){
1658 						fprintf(stderr, "Failed to open %s\n", incbegin+1);
1659 						break;
1660 					}
1661 					if((*bufsize - *inbuf) <STRINGBUF){
1662 						*bufsize += STRINGBUF;
1663 						if(!(buf = myrealloc(buf, *bufsize))){
1664 							fprintf(stderr, "Failed to allocate memory for %s\n", incbegin+1);
1665 							close(fd);
1666 							break;
1667 						}
1668 					}
1669 					len = 0;
1670 					if(argm[argc]!=(incbegin+1)) {
1671 						len = (int)strlen((char *)argm[argc]);
1672 						memmove(buf+*inbuf, argm[argc], len);
1673 					}
1674 					if((res = read(fd, buf+*inbuf+len, STRINGBUF-(1+len))) <= 0) {
1675 						perror((char *)incbegin+1);
1676 						close(fd);
1677 						break;
1678 					}
1679 					close(fd);
1680 					buf[*inbuf+res+len] = 0;
1681 					incbegin = buf + *inbuf;
1682 					(*inbuf) += (res + len + 1);
1683 					included++;
1684 					argc+=parsestr(incbegin, argm + argc, nitems - argc, buff, inbuf, bufsize);
1685 					included--;
1686 					incbegin = NULL;
1687 
1688 				}
1689 				break;
1690 			}
1691 		default:
1692 			if(space) {
1693 				if(comment && *str == '\"' && str[1] != '\"'){
1694 					str++;
1695 					comment = 0;
1696 				}
1697 				argm[argc++] = str;
1698 				if(argc >= nitems) return argc;
1699 				space = 0;
1700 			}
1701 	 }
1702 	}
1703 #undef buf
1704 }
1705 
1706 
1707 int readconfig(FILE * fp){
1708  unsigned char ** argv = NULL;
1709  unsigned char * buf = NULL;
1710   int bufsize = STRINGBUF*2;
1711   int inbuf = 0;
1712   int argc;
1713   struct commands * cm;
1714   int res = 0;
1715 
1716   if( !(buf = myalloc(bufsize)) || ! (argv = myalloc((NPARAMS + 1) * sizeof(unsigned char *))) ) {
1717 		fprintf(stderr, "No memory for configuration");
1718 		return(10);
1719   }
1720   for (linenum = 1; fgets((char *)buf, STRINGBUF, fp); linenum++){
1721 	if(!*buf || isspace(*buf) || (*buf) == '#')continue;
1722 
1723 	inbuf = (int)(strlen((char *)buf) + 1);
1724 	argc = parsestr (buf, argv, NPARAMS-1, &buf, &inbuf, &bufsize);
1725 	if(argc < 1) {
1726 		fprintf(stderr, "Parse error line %d\n", linenum);
1727 		return(11);
1728 	}
1729 	argv[argc] = NULL;
1730 	if(!strcmp((char *)argv[0], "end") && argc == 1) {
1731 		break;
1732 	}
1733 	else if(!strcmp((char *)argv[0], "writable") && argc == 1) {
1734 		if(!writable){
1735 			writable = freopen(curconf, "r+", fp);
1736 			if(!writable){
1737 				fprintf(stderr, "Unable to reopen config for writing: %s\n", curconf);
1738 				return 1;
1739 			}
1740 		}
1741 		continue;
1742 	}
1743 
1744 	res = 1;
1745 	for(cm = commandhandlers; cm; cm = cm->next){
1746 		if(!strcmp((char *)argv[0], (char *)cm->command) && argc >= cm->minargs && (!cm->maxargs || argc <= cm->maxargs)){
1747 			res = (*cm->handler)(argc, argv);
1748 			if(res > 0){
1749 				fprintf(stderr, "Command: '%s' failed with code %d, line %d\n", argv[0], res, linenum);
1750 				return(linenum);
1751 			}
1752 			if(!res) break;
1753 		}
1754 	}
1755 	if(res != 1)continue;
1756 	fprintf(stderr, "Unknown command: '%s' line %d\n", argv[0], linenum);
1757 	return(linenum);
1758   }
1759   myfree(buf);
1760   myfree(argv);
1761   return 0;
1762 
1763 }
1764 
1765 
1766 
1767 void freepwl(struct passwords *pwl){
1768 	for(; pwl; pwl = (struct passwords *)itfree(pwl, pwl->next)){
1769 		if(pwl->user)myfree(pwl->user);
1770 		if(pwl->password)myfree(pwl->password);
1771 	}
1772 }
1773 
1774 
1775 void freeconf(struct extparam *confp){
1776  struct bandlim * bl;
1777  struct bandlim * blout;
1778  struct connlim * cl;
1779  struct trafcount * tc;
1780  struct passwords *pw;
1781  struct ace *acl;
1782  struct filemon *fm;
1783  int counterd, archiverc;
1784  unsigned char *logname, *logtarget;
1785  unsigned char **archiver;
1786  unsigned char * logformat;
1787 
1788  int i;
1789 
1790 
1791 
1792 
1793  pthread_mutex_lock(&tc_mutex);
1794  confp->trafcountfunc = NULL;
1795  tc = confp->trafcounter;
1796  confp->trafcounter = NULL;
1797  counterd = confp->counterd;
1798  confp->counterd = -1;
1799  confp->countertype = NONE;
1800  pthread_mutex_unlock(&tc_mutex);
1801 
1802  pthread_mutex_lock(&bandlim_mutex);
1803  bl = confp->bandlimiter;
1804  blout = confp->bandlimiterout;
1805  confp->bandlimiter = NULL;
1806  confp->bandlimiterout = NULL;
1807  confp->bandlimfunc = NULL;
1808  confp->bandlimver++;
1809  pthread_mutex_unlock(&bandlim_mutex);
1810  pthread_mutex_lock(&connlim_mutex);
1811  cl = confp->connlimiter;
1812  confp->connlimiter = NULL;
1813  pthread_mutex_unlock(&connlim_mutex);
1814 
1815  pthread_mutex_lock(&pwl_mutex);
1816  pw = confp->pwl;
1817  confp->pwl = NULL;
1818  pthread_mutex_unlock(&pwl_mutex);
1819 
1820 
1821 /*
1822  logtarget = confp->logtarget;
1823  confp->logtarget = NULL;
1824  logname = confp->logname;
1825  confp->logname = NULL;
1826 */
1827  confp->logfunc = lognone;
1828  logformat = confp->logformat;
1829  confp->logformat = NULL;
1830  confp->rotate = 0;
1831  confp->logtype = NONE;
1832  confp->logtime = confp->time = 0;
1833 
1834  archiverc = confp->archiverc;
1835  confp->archiverc = 0;
1836  archiver = confp->archiver;
1837  confp->archiver = NULL;
1838  fm = confp->fmon;
1839  confp->fmon = NULL;
1840  confp->bandlimfunc = NULL;
1841  memset(&confp->intsa, 0, sizeof(confp->intsa));
1842  memset(&confp->extsa, 0, sizeof(confp->extsa));
1843 #ifndef NOIPV6
1844  memset(&confp->extsa6, 0, sizeof(confp->extsa6));
1845  *SAFAMILY(&confp->extsa6) = AF_INET6;
1846 #endif
1847  *SAFAMILY(&confp->intsa) = AF_INET;
1848  *SAFAMILY(&confp->extsa) = AF_INET;
1849  confp->maxchild = 100;
1850  resolvfunc = NULL;
1851  numservers = 0;
1852  acl = confp->acl;
1853  confp->acl = NULL;
1854 
1855  usleep(SLEEPTIME);
1856 
1857  {
1858 	char * args[] = {"auth", "iponly", NULL};
1859   	h_auth(2, (unsigned char **)args);
1860  }
1861  if(tc)dumpcounters(tc,counterd);
1862  for(; tc; tc = (struct trafcount *) itfree(tc, tc->next)){
1863 	if(tc->comment)myfree(tc->comment);
1864 	freeacl(tc->ace);
1865  }
1866 
1867 
1868  freeacl(acl);
1869  freepwl(pw);
1870  for(; bl; bl = (struct bandlim *) itfree(bl, bl->next)) freeacl(bl->ace);
1871  for(; blout; blout = (struct bandlim *) itfree(blout, blout->next))freeacl(blout->ace);
1872  for(; cl; cl = (struct connlim *) itfree(cl, cl->next)) freeacl(cl->ace);
1873 
1874  if(counterd != -1) {
1875 	close(counterd);
1876  }
1877  for(; fm; fm = (struct filemon *)itfree(fm, fm->next)){
1878 	if(fm->path) myfree(fm->path);
1879  }
1880 /*
1881  if(logtarget) {
1882 	myfree(logtarget);
1883  }
1884  if(logname) {
1885 	myfree(logname);
1886  }
1887 */
1888  if(logformat) {
1889 	myfree(logformat);
1890  }
1891  if(archiver) {
1892 	for(i = 0; i < archiverc; i++) myfree(archiver[i]);
1893 	myfree(archiver);
1894  }
1895  havelog = 0;
1896 }
1897 
1898 int reload (void){
1899 	FILE *fp;
1900 	int error = -2;
1901 
1902 	conf.paused++;
1903 	freeconf(&conf);
1904 	conf.paused++;
1905 
1906 	fp = confopen();
1907 	if(fp){
1908 		error = readconfig(fp);
1909 		conf.version++;
1910 		if(error) {
1911 			 freeconf(&conf);
1912 		}
1913 		if(!writable)fclose(fp);
1914 	}
1915 	return error;
1916 }
1917