1 /************************************************************************
2  *   Unreal Internet Relay Chat Daemon, src/ircd.c
3  *   Copyright (C) 1990 Jarkko Oikarinen and
4  *                      University of Oulu, Computing Center
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 1, or (at your option)
9  *   any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 #ifndef CLEAN_COMPILE
22 static char sccsid[] =
23     "@(#)ircd.c	2.48 3/9/94 (C) 1988 University of Oulu, \
24 Computing Center and Jarkko Oikarinen";
25 #endif
26 
27 #include "config.h"
28 #include "struct.h"
29 #include "common.h"
30 #include "sys.h"
31 #include "numeric.h"
32 #include "msg.h"
33 #include <sys/stat.h>
34 #include <signal.h>
35 #include <fcntl.h>
36 #include <sys/types.h>
37 #ifndef _WIN32
38 #include <sys/file.h>
39 #include <pwd.h>
40 #include <grp.h>
41 #include <sys/time.h>
42 #else
43 #include <io.h>
44 #include <direct.h>
45 #endif
46 #ifdef HPUX
47 #define _KERNEL			/* HPUX has the world's worst headers... */
48 #endif
49 #ifndef _WIN32
50 #include <sys/resource.h>
51 #endif
52 #ifdef HPUX
53 #undef _KERNEL
54 #endif
55 #include <errno.h>
56 #ifdef HAVE_PSSTRINGS
57 #include <sys/exec.h>
58 #endif
59 #ifdef HAVE_PSTAT
60 #include <sys/pstat.h>
61 #endif
62 #include "h.h"
63 #ifndef NO_FDLIST
64 #include "fdlist.h"
65 #endif
66 #ifdef STRIPBADWORDS
67 #include "badwords.h"
68 #endif
69 #include "version.h"
70 #include "proto.h"
71 #ifdef _WIN32
72 extern BOOL IsService;
73 #endif
74 #ifdef USE_LIBCURL
75 #include <curl/curl.h>
76 #endif
77 ID_Copyright
78     ("(C) 1988 University of Oulu, Computing Center and Jarkko Oikarinen");
79 ID_Notes("2.48 3/9/94");
80 #ifdef __FreeBSD__
81 char *malloc_options = "h" MALLOC_FLAGS_EXTRA;
82 #endif
83 time_t TSoffset = 0;
84 
85 #ifndef _WIN32
86 extern char unreallogo[];
87 #endif
88 int  SVSNOOP = 0;
89 extern MODVAR char *buildid;
90 time_t timeofday = 0;
91 int  tainted = 0;
92 LoopStruct loop;
93 MODVAR MemoryInfo StatsZ;
94 #ifndef _WIN32
95 uid_t irc_uid = 0;
96 gid_t irc_gid = 0;
97 #endif
98 
99 int  R_do_dns, R_fin_dns, R_fin_dnsc, R_fail_dns, R_do_id, R_fin_id, R_fail_id;
100 
101 char REPORT_DO_DNS[256], REPORT_FIN_DNS[256], REPORT_FIN_DNSC[256],
102     REPORT_FAIL_DNS[256], REPORT_DO_ID[256], REPORT_FIN_ID[256],
103     REPORT_FAIL_ID[256];
104 extern ircstats IRCstats;
105 aClient me;			/* That's me */
106 MODVAR char *me_hash;
107 aClient *client = &me;		/* Pointer to beginning of Client list */
108 extern char backupbuf[8192];
109 #ifdef _WIN32
110 extern void CleanUpSegv(int sig);
111 extern SERVICE_STATUS_HANDLE IRCDStatusHandle;
112 extern SERVICE_STATUS IRCDStatus;
113 #endif
114 #ifndef NO_FDLIST
115 fdlist default_fdlist;
116 fdlist busycli_fdlist;
117 fdlist serv_fdlist;
118 fdlist oper_fdlist;
119 fdlist unknown_fdlist;
120 float currentrate;
121 float currentrate2;		/* outgoing */
122 float highest_rate = 0;
123 float highest_rate2 = 0;
124 int  lifesux = 0;
125 int  LRV = LOADRECV;
126 TS   LCF = LOADCFREQ;
127 int  currlife = 0;
128 int  HTMLOCK = 0;
129 int  noisy_htm = 1;
130 long lastrecvK = 0;
131 long lastsendK = 0;
132 
133 TS   check_fdlists();
134 #endif
135 
136 unsigned char conf_debuglevel = 0;
137 char trouble_info[1024];
138 
139 #ifdef USE_LIBCURL
140 extern void url_init(void);
141 #endif
142 
143 time_t highesttimeofday=0, oldtimeofday=0, lasthighwarn=0;
144 
145 
save_stats(void)146 void save_stats(void)
147 {
148 	FILE *stats = fopen("ircd.stats", "w");
149 	if (!stats)
150 		return;
151 	fprintf(stats, "%i\n", IRCstats.clients);
152 	fprintf(stats, "%i\n", IRCstats.invisible);
153 	fprintf(stats, "%i\n", IRCstats.servers);
154 	fprintf(stats, "%i\n", IRCstats.operators);
155 	fprintf(stats, "%i\n", IRCstats.unknown);
156 	fprintf(stats, "%i\n", IRCstats.me_clients);
157 	fprintf(stats, "%i\n", IRCstats.me_servers);
158 	fprintf(stats, "%i\n", IRCstats.me_max);
159 	fprintf(stats, "%i\n", IRCstats.global_max);
160 	fclose(stats);
161 }
162 
163 
164 void server_reboot(char *);
165 void restart(char *);
166 static void open_debugfile(), setup_signals();
167 extern void init_glines(void);
168 extern void tkl_init(void);
169 
170 MODVAR TS   last_garbage_collect = 0;
171 #ifndef _WIN32
172 MODVAR char **myargv;
173 #else
174 LPCSTR cmdLine;
175 #endif
176 int  portnum = -1;		/* Server port number, listening this */
177 char *configfile = CONFIGFILE;	/* Server configuration file */
178 int  debuglevel = 10;		/* Server debug level */
179 int  bootopt = 0;		/* Server boot option flags */
180 char *debugmode = "";		/*  -"-    -"-   -"-  */
181 char *sbrk0;			/* initial sbrk(0) */
182 static int dorehash = 0, dorestart = 0;
183 static char *dpath = DPATH;
184 MODVAR int  booted = FALSE;
185 MODVAR TS   nextconnect = 1;		/* time for next try_connections call */
186 MODVAR TS   nextping = 1;		/* same as above for check_pings() */
187 MODVAR TS   nextdnscheck = 0;		/* next time to poll dns to force timeouts */
188 MODVAR TS   nextexpire = 1;		/* next expire run on the dns cache */
189 MODVAR TS   lastlucheck = 0;
190 
191 #ifdef UNREAL_DEBUG
192 #undef CHROOTDIR
193 #define CHROOT
194 #endif
195 
196 MODVAR TS   NOW;
197 #if	defined(PROFIL) && !defined(_WIN32)
198 extern etext();
199 
s_monitor(void)200 VOIDSIG s_monitor(void)
201 {
202 	static int mon = 0;
203 #ifdef	POSIX_SIGNALS
204 	struct sigaction act;
205 #endif
206 
207 	(void)moncontrol(mon);
208 	mon = 1 - mon;
209 #ifdef	POSIX_SIGNALS
210 	act.sa_handler = s_rehash;
211 	act.sa_flags = 0;
212 	(void)sigemptyset(&act.sa_mask);
213 	(void)sigaddset(&act.sa_mask, SIGUSR1);
214 	(void)sigaction(SIGUSR1, &act, NULL);
215 #else
216 	(void)signal(SIGUSR1, s_monitor);
217 #endif
218 }
219 
220 #endif
221 
s_die()222 VOIDSIG s_die()
223 {
224 #ifdef _WIN32
225 	int  i;
226 	aClient *cptr;
227 	if (!IsService)
228 	{
229 		unload_all_modules();
230 		for (i = LastSlot; i >= 0; i--)
231 			if ((cptr = local[i]) && DBufLength(&cptr->sendQ) > 0)
232 				(void)send_queued(cptr);
233 
234 		exit(-1);
235 	}
236 	else {
237 		SERVICE_STATUS status;
238 		SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
239 		SC_HANDLE hService = OpenService(hSCManager, "UnrealIRCd", SERVICE_STOP);
240 		ControlService(hService, SERVICE_CONTROL_STOP, &status);
241 	}
242 #else
243 	unload_all_modules();
244 	flush_connections(&me);
245 	exit(-1);
246 #endif
247 }
248 
249 #ifndef _WIN32
s_rehash()250 static VOIDSIG s_rehash()
251 #else
252 VOIDSIG s_rehash()
253 #endif
254 {
255 #ifdef	POSIX_SIGNALS
256 	struct sigaction act;
257 #endif
258 	dorehash = 1;
259 #ifdef	POSIX_SIGNALS
260 	act.sa_handler = s_rehash;
261 	act.sa_flags = 0;
262 	(void)sigemptyset(&act.sa_mask);
263 	(void)sigaddset(&act.sa_mask, SIGHUP);
264 	(void)sigaction(SIGHUP, &act, NULL);
265 #else
266 # ifndef _WIN32
267 	(void)signal(SIGHUP, s_rehash);	/* sysV -argv */
268 # endif
269 #endif
270 }
271 
restart(char * mesg)272 void restart(char *mesg)
273 {
274 	server_reboot(mesg);
275 }
276 
s_restart()277 VOIDSIG s_restart()
278 {
279 	dorestart = 1;
280 #if 0
281 	static int restarting = 0;
282 
283 	if (restarting == 0) {
284 		/*
285 		 * Send (or attempt to) a dying scream to oper if present
286 		 */
287 
288 		restarting = 1;
289 		server_reboot("SIGINT");
290 	}
291 #endif
292 }
293 
294 
295 #ifndef _WIN32
dummy()296 VOIDSIG dummy()
297 {
298 #ifndef HAVE_RELIABLE_SIGNALS
299 	(void)signal(SIGALRM, dummy);
300 	(void)signal(SIGPIPE, dummy);
301 #ifndef HPUX			/* Only 9k/800 series require this, but don't know how to.. */
302 # ifdef SIGWINCH
303 	(void)signal(SIGWINCH, dummy);
304 # endif
305 #endif
306 #else
307 # ifdef POSIX_SIGNALS
308 	struct sigaction act;
309 
310 	act.sa_handler = dummy;
311 	act.sa_flags = 0;
312 	(void)sigemptyset(&act.sa_mask);
313 	(void)sigaddset(&act.sa_mask, SIGALRM);
314 	(void)sigaddset(&act.sa_mask, SIGPIPE);
315 #  ifdef SIGWINCH
316 	(void)sigaddset(&act.sa_mask, SIGWINCH);
317 #  endif
318 	(void)sigaction(SIGALRM, &act, (struct sigaction *)NULL);
319 	(void)sigaction(SIGPIPE, &act, (struct sigaction *)NULL);
320 #  ifdef SIGWINCH
321 	(void)sigaction(SIGWINCH, &act, (struct sigaction *)NULL);
322 #  endif
323 # endif
324 #endif
325 }
326 
327 #endif				/* _WIN32 */
328 
329 
server_reboot(char * mesg)330 void server_reboot(char *mesg)
331 {
332 	int  i;
333 #ifdef _WIN32
334 	aClient *cptr;
335 #endif
336 	sendto_realops("Aieeeee!!!  Restarting server... %s", mesg);
337 	Debug((DEBUG_NOTICE, "Restarting server... %s", mesg));
338 #ifndef _WIN32
339 	flush_connections(&me);
340 #else
341 	for (i = LastSlot; i >= 0; i--)
342 		if ((cptr = local[i]) && DBufLength(&cptr->sendQ) > 0)
343 			(void)send_queued(cptr);
344 #endif
345 	/*
346 	 * ** fd 0 must be 'preserved' if either the -d or -i options have
347 	 * ** been passed to us before restarting.
348 	 */
349 #ifdef HAVE_SYSLOG
350 	(void)closelog();
351 #endif
352 #ifndef _WIN32
353 	for (i = 3; i < MAXCONNECTIONS; i++)
354 		(void)close(i);
355 	if (!(bootopt & (BOOT_TTY | BOOT_DEBUG)))
356 		(void)close(2);
357 	(void)close(1);
358 	(void)close(0);
359 	(void)execv(MYNAME, myargv);
360 #else
361 	close_connections();
362 	if (!IsService)
363 	{
364 		CleanUp();
365 		WinExec(cmdLine, SW_SHOWDEFAULT);
366 	}
367 #endif
368 #ifndef _WIN32
369 	Debug((DEBUG_FATAL, "Couldn't restart server: %s", strerror(errno)));
370 #else
371 	Debug((DEBUG_FATAL, "Couldn't restart server: %s",
372 	    strerror(GetLastError())));
373 #endif
374 	unload_all_modules();
375 #ifdef _WIN32
376 	if (IsService)
377 	{
378 		SERVICE_STATUS status;
379 		PROCESS_INFORMATION pi;
380 		STARTUPINFO si;
381 		char fname[MAX_PATH];
382 		bzero(&status, sizeof(status));
383 		bzero(&si, sizeof(si));
384 		IRCDStatus.dwCurrentState = SERVICE_STOP_PENDING;
385 		SetServiceStatus(IRCDStatusHandle, &IRCDStatus);
386 		GetModuleFileName(GetModuleHandle(NULL), fname, MAX_PATH);
387 		CreateProcess(fname, "restartsvc", NULL, NULL, FALSE,
388 			0, NULL, NULL, &si, &pi);
389 		IRCDStatus.dwCurrentState = SERVICE_STOPPED;
390 		SetServiceStatus(IRCDStatusHandle, &IRCDStatus);
391 		ExitProcess(0);
392 	}
393 	else
394 #endif
395 	exit(-1);
396 }
397 
398 MODVAR char *areason;
399 
EVENT(loop_event)400 EVENT(loop_event)
401 {
402 	if (loop.do_garbage_collect == 1) {
403 		garbage_collect(NULL);
404 	}
405 }
406 
EVENT(garbage_collect)407 EVENT(garbage_collect)
408 {
409 	extern int freelinks;
410 	extern Link *freelink;
411 	Link p;
412 	int  ii;
413 
414 	if (loop.do_garbage_collect == 1)
415 		sendto_realops("Doing garbage collection ..");
416 	if (freelinks > HOW_MANY_FREELINKS_ALLOWED) {
417 		ii = freelinks;
418 		while (freelink && (freelinks > HOW_MANY_FREELINKS_ALLOWED)) {
419 			freelinks--;
420 			p.next = freelink;
421 			freelink = freelink->next;
422 			MyFree(p.next);
423 		}
424 		if (loop.do_garbage_collect == 1) {
425 			loop.do_garbage_collect = 0;
426 			sendto_realops
427 			    ("Cleaned up %i garbage blocks", (ii - freelinks));
428 		}
429 	}
430 	if (loop.do_garbage_collect == 1)
431 		loop.do_garbage_collect = 0;
432 }
433 
EVENT(deprecated_notice)434 EVENT(deprecated_notice)
435 {
436 	/* Send a warning to opers currently online every week after November 1, 2016 */
437 	if (TStime() > 1477954800)
438 	{
439 		sendto_realops("[WARNING] UnrealIRCd 3.2.x is no longer supported after December 31, 2016. "
440 					   "See https://www.unrealircd.org/docs/UnrealIRCd_3.2.x_deprecated");
441 		ircd_log(LOG_ERROR, "[WARNING] UnrealIRCd 3.2.x is no longer supported after December 31, 2016. "
442 		               "See https://www.unrealircd.org/docs/UnrealIRCd_3.2.x_deprecated");
443 	}
444 }
445 
446 /*
447 ** try_connections
448 **
449 **	Scan through configuration and try new connections.
450 **	Returns the calendar time when the next call to this
451 **	function should be made latest. (No harm done if this
452 **	is called earlier or later...)
453 */
try_connections(TS currenttime)454 static TS try_connections(TS currenttime)
455 {
456 	ConfigItem_link *aconf;
457 	ConfigItem_deny_link *deny;
458 	aClient *cptr;
459 	int  connecting, confrq;
460 	TS   next = 0;
461 	ConfigItem_class *cltmp;
462 
463 	connecting = FALSE;
464 	Debug((DEBUG_NOTICE, "Connection check at   : %s",
465 	    myctime(currenttime)));
466 	for (aconf = conf_link; aconf; aconf = (ConfigItem_link *) aconf->next) {
467 		/*
468 		 * Also when already connecting! (update holdtimes) --SRB
469 		 */
470 		if (!(aconf->options & CONNECT_AUTO) || (aconf->flag.temporary == 1))
471 			continue;
472 
473 		cltmp = aconf->class;
474 		/*
475 		 * ** Skip this entry if the use of it is still on hold until
476 		 * ** future. Otherwise handle this entry (and set it on hold
477 		 * ** until next time). Will reset only hold times, if already
478 		 * ** made one successfull connection... [this algorithm is
479 		 * ** a bit fuzzy... -- msa >;) ]
480 		 */
481 
482 		if ((aconf->hold > currenttime)) {
483 			if ((next > aconf->hold) || (next == 0))
484 				next = aconf->hold;
485 			continue;
486 		}
487 
488 		confrq = cltmp->connfreq;
489 		aconf->hold = currenttime + confrq;
490 		/*
491 		 * ** Found a CONNECT config with port specified, scan clients
492 		 * ** and see if this server is already connected?
493 		 */
494 		cptr = find_name(aconf->servername, (aClient *)NULL);
495 
496 		if (!cptr && (cltmp->clients < cltmp->maxclients)) {
497 			/*
498 			 * Check connect rules to see if we're allowed to try
499 			 */
500 			for (deny = conf_deny_link; deny;
501 			    deny = (ConfigItem_deny_link *) deny->next)
502 				if (!match(deny->mask, aconf->servername)
503 				    && crule_eval(deny->rule))
504 					break;
505 
506 			if (!deny && connect_server(aconf, (aClient *)NULL,
507 			    (struct hostent *)NULL) == 0)
508 				sendto_realops
509 				    ("Connection to %s[%s] activated.",
510 				    aconf->servername, aconf->hostname);
511 
512 		}
513 		if ((next > aconf->hold) || (next == 0))
514 			next = aconf->hold;
515 	}
516 	Debug((DEBUG_NOTICE, "Next connection check : %s", myctime(next)));
517 	return (next);
518 }
519 
520 
521 /* Now find_kill is only called when a kline-related command is used:
522    AKILL/RAKILL/KLINE/UNKLINE/REHASH.  Very significant CPU usage decrease.
523    -- Barubary */
524 
525 
526 
check_pings(TS currenttime)527 extern TS check_pings(TS currenttime)
528 {
529 	aClient *cptr = NULL;
530 	ConfigItem_ban *bconf = NULL;
531 	char killflag = 0;
532 	int  i = 0;
533 	char banbuf[1024];
534 	char scratch[64];
535 	int  ping = 0;
536 
537 	for (i = 0; i <= LastSlot; i++) {
538 		/*
539 		 * If something we should not touch ..
540 		 */
541 		if (!(cptr = local[i]) || IsMe(cptr) || IsLog(cptr))
542 			continue;
543 
544 		/*
545 		 * ** Note: No need to notify opers here. It's
546 		 * ** already done when "FLAGS_DEADSOCKET" is set.
547 		 */
548 		if (cptr->flags & FLAGS_DEADSOCKET) {
549 			(void)exit_client(cptr, cptr, &me, cptr->error_str ? cptr->error_str : "Dead socket");
550 			continue;
551 		}
552 		killflag = 0;
553 		/*
554 		 * Check if user is banned
555 		 */
556 		if (loop.do_bancheck) {
557 			if (find_tkline_match(cptr, 0) < 0) {
558 				/*
559 				 * Client exited
560 				 */
561 				continue;
562 			}
563 			find_shun(cptr);
564 			if (!killflag && IsPerson(cptr)) {
565 				/*
566 				 * If it's a user, we check for CONF_BAN_USER
567 				 */
568 				bconf =
569 				    Find_ban(cptr, make_user_host(cptr->
570 				    user ? cptr->user->username : cptr->
571 				    username,
572 				    cptr->user ? cptr->user->realhost : cptr->
573 				    sockhost), CONF_BAN_USER);
574 				if (bconf)
575 					killflag++;
576 
577 				if (!killflag && !IsAnOper(cptr) &&
578 				    (bconf =
579 				    Find_ban(NULL, cptr->info, CONF_BAN_REALNAME))) {
580 					killflag++;
581 				}
582 
583 			}
584 			/*
585 			 * If no cookie, we search for Z:lines
586 			 */
587 			if (!killflag)
588 				if ((bconf =
589 				    Find_ban(cptr, Inet_ia2p(&cptr->ip),
590 				    CONF_BAN_IP)))
591 					killflag++;
592 			if (killflag) {
593 				if (IsPerson(cptr))
594 					sendto_realops("Ban active for %s (%s)",
595 					    get_client_name(cptr, FALSE),
596 					    bconf->reason ? bconf->
597 					    reason : "no reason");
598 
599 				if (IsServer(cptr))
600 					sendto_realops
601 					    ("Ban active for server %s (%s)",
602 					    get_client_name(cptr, FALSE),
603 					    bconf->reason ? bconf->
604 					    reason : "no reason");
605 				if (bconf->reason) {
606 					if (IsPerson(cptr))
607 						snprintf(banbuf, sizeof banbuf - 1,
608 						         "User has been banned (%s)", bconf->reason);
609 					else
610 						snprintf(banbuf, sizeof banbuf - 1,
611 						         "Banned (%s)", bconf->reason);
612 					(void)exit_client(cptr, cptr, &me,
613 					    banbuf);
614 				} else {
615 					if (IsPerson(cptr))
616 						(void)exit_client(cptr, cptr,
617 						    &me,
618 						    "User has been banned");
619 					else
620 						(void)exit_client(cptr, cptr,
621 						    &me, "Banned");
622 				}
623 				continue;
624 			}
625 
626 		}
627 		/* Do spamfilter 'user' banchecks.. */
628 		if (loop.do_bancheck_spamf_user && IsPerson(cptr))
629 		{
630 			if (find_spamfilter_user(cptr, SPAMFLAG_NOWARN) == FLUSH_BUFFER)
631 				continue;
632 		}
633 		if (loop.do_bancheck_spamf_away && IsPerson(cptr) && cptr->user->away)
634 		{
635 			if (dospamfilter(cptr, cptr->user->away, SPAMF_AWAY, NULL, SPAMFLAG_NOWARN, NULL) == FLUSH_BUFFER)
636 				continue;
637 		}
638 		/*
639 		 * We go into ping phase
640 		 */
641 		ping =
642 		    IsRegistered(cptr) ? (cptr->class ? cptr->
643 		    class->pingfreq : CONNECTTIMEOUT) : CONNECTTIMEOUT;
644 		Debug((DEBUG_DEBUG, "c(%s)=%d p %d k %d a %d", cptr->name,
645 		    cptr->status, ping, killflag,
646 		    currenttime - cptr->lasttime));
647 
648 		/* If ping is less than or equal to the last time we received a command from them */
649 		if (ping <= (currenttime - cptr->lasttime))
650 		{
651 			if (
652 				/* If we have sent a ping */
653 				((cptr->flags & FLAGS_PINGSENT)
654 				/* And they had 2x ping frequency to respond */
655 				&& ((currenttime - cptr->lasttime) >= (2 * ping)))
656 				||
657 				/* Or isn't registered and time spent is larger than ping .. */
658 				(!IsRegistered(cptr) && (currenttime - cptr->since >= ping))
659 				)
660 			{
661 				/* if it's registered and doing dns/auth, timeout */
662 				if (!IsRegistered(cptr) && (DoingDNS(cptr) || DoingAuth(cptr)))
663 				{
664 					if (cptr->authfd >= 0) {
665 						CLOSE_SOCK(cptr->authfd);
666 						--OpenFiles;
667 						cptr->authfd = -1;
668 						cptr->count = 0;
669 						*cptr->buffer = '\0';
670 					}
671 					if (SHOWCONNECTINFO && !cptr->serv) {
672 						if (DoingDNS(cptr))
673 							sendto_one(cptr,
674 							    REPORT_FAIL_DNS);
675 						else if (DoingAuth(cptr))
676 							sendto_one(cptr,
677 							    REPORT_FAIL_ID);
678 					}
679 					Debug((DEBUG_NOTICE,
680 					    "DNS/AUTH timeout %s",
681 					    get_client_name(cptr, TRUE)));
682 					unrealdns_delreq_bycptr(cptr);
683 					ClearAuth(cptr);
684 					ClearDNS(cptr);
685 					SetAccess(cptr);
686 					cptr->firsttime = currenttime;
687 					cptr->lasttime = currenttime;
688 					continue;
689 				}
690 				if (IsServer(cptr) || IsConnecting(cptr) ||
691 				    IsHandshake(cptr)
692 #ifdef USE_SSL
693 					|| IsSSLConnectHandshake(cptr)
694 #endif
695 				    ) {
696 					sendto_realops
697 					    ("No response from %s, closing link",
698 					    get_client_name(cptr, FALSE));
699 					sendto_serv_butone(&me,
700 					    ":%s GLOBOPS :No response from %s, closing link",
701 					    me.name, get_client_name(cptr,
702 					    FALSE));
703 				}
704 #ifdef USE_SSL
705 				if (IsSSLAcceptHandshake(cptr))
706 					Debug((DEBUG_DEBUG, "ssl accept handshake timeout: %s (%li-%li > %li)", cptr->sockhost,
707 						currenttime, cptr->since, ping));
708 #endif
709 				(void)ircsprintf(scratch, "Ping timeout: %ld seconds",
710 					(long) (TStime() - cptr->lasttime));
711 				exit_client(cptr, cptr, &me, scratch);
712 				continue;
713 
714 			}
715 			else if (IsRegistered(cptr) &&
716 			    ((cptr->flags & FLAGS_PINGSENT) == 0)) {
717 				/*
718 				 * if we havent PINGed the connection and we havent
719 				 * heard from it in a while, PING it to make sure
720 				 * it is still alive.
721 				 */
722 				cptr->flags |= FLAGS_PINGSENT;
723 				/*
724 				 * not nice but does the job
725 				 */
726 				cptr->lasttime = currenttime - ping;
727 				sendto_one(cptr, "%s :%s",
728 				    IsToken(cptr) ? TOK_PING : MSG_PING,
729 				    me.name);
730 			}
731 		}
732 		/*
733 		 * Check UNKNOWN connections - if they have been in this state
734 		 * for > 100s, close them.
735 		 */
736 		if (IsUnknown(cptr)
737 #ifdef USE_SSL
738 			|| (IsSSLAcceptHandshake(cptr) || IsSSLConnectHandshake(cptr))
739 #endif
740 		)
741 			if (cptr->firsttime ? ((currenttime - cptr->firsttime) >
742 			    100) : 0)
743 				(void)exit_client(cptr, cptr, &me,
744 				    "Connection Timed Out");
745 	}
746 	/*
747 	 * EXPLANATION
748 	 * * on a server with a large volume of clients, at any given point
749 	 * * there may be a client which needs to be pinged the next second,
750 	 * * or even right away (a second may have passed while running
751 	 * * check_pings). Preserving CPU time is more important than
752 	 * * pinging clients out at exact times, IMO. Therefore, I am going to make
753 	 * * check_pings always return currenttime + 9. This means that it may take
754 	 * * a user up to 9 seconds more than pingfreq to timeout. Oh well.
755 	 * * Plus, the number is 9 to 'stagger' our check_pings calls out over
756 	 * * time, to avoid doing it and the other tasks ircd does at the same time
757 	 * * all the time (which are usually done on intervals of 5 seconds or so).
758 	 * * - lucas
759 	 * *
760 	 */
761 	loop.do_bancheck = loop.do_bancheck_spamf_user = loop.do_bancheck_spamf_away = 0;
762 	Debug((DEBUG_NOTICE, "Next check_ping() call at: %s, %d %d %d",
763 	    myctime(currenttime+9), ping, currenttime+9, currenttime));
764 
765 	return currenttime + 9;
766 }
767 
768 /*
769 ** bad_command
770 **	This is called when the commandline is not acceptable.
771 **	Give error message and exit without starting anything.
772 */
bad_command(void)773 static int bad_command(void)
774 {
775 #ifndef _WIN32
776 	(void)printf
777 	    ("Usage: ircd [-f config] [-h servername] [-p portnumber] [-x loglevel] [-t] [-H]\n");
778 	(void)printf("Server not started\n\n");
779 #else
780 	if (!IsService) {
781 		MessageBox(NULL,
782 		    "Usage: wircd [-h servername] [-p portnumber] [-x loglevel]\n",
783 		    "UnrealIRCD/32", MB_OK);
784 	}
785 #endif
786 	return (-1);
787 }
788 
789 char chess[] = {
790 	85, 110, 114, 101, 97, 108, 0
791 };
792 #ifndef NO_FDLIST
check_fdlists(TS now)793 inline TS check_fdlists(TS now)
794 {
795 	aClient *cptr;
796 	int  pri;		/* temp. for priority */
797 	int  i, j;
798 	j = 0;
799 	for (i = LastSlot; i >= 0; i--) {
800 		if (!(cptr = local[i]))
801 			continue;
802 		if (IsServer(cptr) || IsListening(cptr)
803 		    || IsOper(cptr) || DoingAuth(cptr)) {
804 			busycli_fdlist.entry[++j] = i;
805 			continue;
806 		}
807 		pri = cptr->priority;
808 		if (cptr->receiveM == cptr->lastrecvM)
809 			pri += 2;	/* lower a bit */
810 		else
811 			pri -= 30;
812 		if (pri < 0)
813 			pri = 0;
814 		if (pri > 80)
815 			pri = 80;
816 		cptr->lastrecvM = cptr->receiveM;
817 		cptr->priority = pri;
818 		if ((pri < 10) || (!lifesux && (pri < 25)))
819 			busycli_fdlist.entry[++j] = i;
820 	}
821 	busycli_fdlist.last_entry = j;	/* rest of the fdlist is garbage */
822 	return (now + FDLISTCHKFREQ + lifesux * FDLISTCHKFREQ);
823 }
824 
EVENT(e_check_fdlists)825 EVENT(e_check_fdlists)
826 {
827 	check_fdlists(TStime());
828 }
829 
830 #endif
831 
version_check_logerror(char * fmt,...)832 static void version_check_logerror(char *fmt, ...)
833 {
834 va_list va;
835 char buf[1024];
836 
837 	va_start(va, fmt);
838 	vsnprintf(buf, sizeof(buf), fmt, va);
839 	va_end(va);
840 #ifndef _WIN32
841 	fprintf(stderr, "[!!!] %s\n", buf);
842 #else
843 	win_log("[!!!] %s", buf);
844 #endif
845 }
846 
847 /** Ugly version checker that ensures zlib/ssl/curl runtime libraries match the
848  * version we compiled for.
849  */
do_version_check()850 static void do_version_check()
851 {
852 const char *compiledfor, *runtime;
853 int error = 0;
854 
855 #ifdef USE_SSL
856 	compiledfor = OPENSSL_VERSION_TEXT;
857 	runtime = SSLeay_version(SSLEAY_VERSION);
858 	if (strcasecmp(compiledfor, runtime))
859 	{
860 		version_check_logerror("OpenSSL version mismatch: compiled for '%s', library is '%s'",
861 			compiledfor, runtime);
862 		error=1;
863 	}
864 #endif
865 #ifdef ZIP_LINKS
866 	runtime = zlibVersion();
867 	compiledfor = ZLIB_VERSION;
868 	if (*compiledfor != *runtime)
869 	{
870 		version_check_logerror("Zlib version mismatch: compiled for '%s', library is '%s'",
871 			compiledfor, runtime);
872 		error = 1;
873 	}
874 #endif
875 #ifdef USE_LIBCURL
876 	/* Perhaps someone should tell them to do this a bit more easy ;)
877 	 * problem is runtime output is like: 'libcurl/7.11.1 zlib/1.2.1 c-ares/1.2.0'
878 	 * while header output is like: '7.11.1'.
879 	 */
880 	{
881 		char buf[128], *p;
882 
883 		runtime = curl_version();
884 		compiledfor = LIBCURL_VERSION;
885 		if (!strncmp(runtime, "libcurl/", 8))
886 		{
887 			strlcpy(buf, runtime+8, sizeof(buf));
888 			p = strchr(buf, ' ');
889 			if (p)
890 			{
891 				*p = '\0';
892 				if (strcmp(compiledfor, buf))
893 				{
894 					version_check_logerror("Curl version mismatch: compiled for '%s', library is '%s'",
895 						compiledfor, buf);
896 					error = 1;
897 				}
898 			}
899 		}
900 	}
901 #endif
902 
903 	if (error)
904 	{
905 #ifndef _WIN32
906 		version_check_logerror("Header<->library mismatches can make UnrealIRCd *CRASH*! "
907 		                "Make sure you don't have multiple versions of openssl or zlib installed (eg: "
908 		                "one in /usr and one in /usr/local). And, if you recently upgraded them, "
909 		                "be sure to recompile Unreal.");
910 #else
911 		version_check_logerror("Header<->library mismatches can make UnrealIRCd *CRASH*! "
912 		                "This should never happen with official Windows builds... unless "
913 		                "you overwrote any .dll files with newer/older ones or something.");
914 		win_error();
915 #endif
916 		tainted = 1;
917 	}
918 }
919 
920 extern time_t TSoffset;
921 
922 extern int unreal_time_synch(int timeout);
923 
924 extern MODVAR Event *events;
925 extern struct MODVAR ThrottlingBucket *ThrottlingHash[THROTTLING_HASH_SIZE+1];
926 
927 /** This functions resets a couple of timers and does other things that
928  * are absolutely cruicial when the clock is adjusted - particularly
929  * when the clock goes backwards. -- Syzop
930  */
fix_timers(void)931 void fix_timers(void)
932 {
933 int i, cnt;
934 aClient *acptr;
935 Event *e;
936 struct ThrottlingBucket *n;
937 struct ThrottlingBucket z = { NULL, NULL, {0}, 0, 0};
938 
939 	/* Client time stuff */
940 	for (i = 0; i <= LastSlot; i++)
941 	{
942 
943 	        if (!(acptr = local[i]) || IsMe(acptr))
944 	        	continue;
945 
946 		/* all (servers AND users) */
947 		if (MyConnect(acptr))
948 		{
949 			if (acptr->since > TStime())
950 			{
951 				Debug((DEBUG_DEBUG, "fix_timers(): %s: acptr->since %ld -> %ld",
952 					acptr->name, acptr->since, TStime()));
953 				acptr->since = TStime();
954 			}
955 			if (acptr->lasttime > TStime())
956 			{
957 				Debug((DEBUG_DEBUG, "fix_timers(): %s: acptr->lasttime %ld -> %ld",
958 					acptr->name, acptr->lasttime, TStime()));
959 				acptr->lasttime = TStime();
960 			}
961 			if (acptr->last > TStime())
962 			{
963 				Debug((DEBUG_DEBUG, "fix_timers(): %s: acptr->last %ld -> %ld",
964 					acptr->name, acptr->last, TStime()));
965 				acptr->last = TStime();
966 			}
967 		}
968 
969 		/* users */
970 		if (MyClient(acptr))
971 		{
972 			if (acptr->nextnick > TStime())
973 			{
974 				Debug((DEBUG_DEBUG, "fix_timers(): %s: acptr->nextnick %ld -> %ld",
975 					acptr->name, acptr->nextnick, TStime()));
976 				acptr->nextnick = TStime();
977 			}
978 			if (acptr->nexttarget > TStime())
979 			{
980 				Debug((DEBUG_DEBUG, "fix_timers(): %s: acptr->nexttarget %ld -> %ld",
981 					acptr->name, acptr->nexttarget, TStime()));
982 				acptr->nexttarget = TStime();
983 			}
984 
985 		}
986 	}
987 
988 	/* Reset all event timers */
989 	for (e = events; e; e = e->next)
990 	{
991 		if (e->last > TStime())
992 		{
993 			Debug((DEBUG_DEBUG, "fix_timers(): %s: e->last %ld -> %ld",
994 				e->name, e->last, TStime()-1));
995 			e->last = TStime()-1;
996 		}
997 	}
998 
999 	/* Just flush all throttle stuff... */
1000 	cnt = 0;
1001 	for (i = 0; i < THROTTLING_HASH_SIZE; i++)
1002 		for (n = ThrottlingHash[i]; n; n = n->next)
1003 		{
1004 			z.next = (struct ThrottlingBucket *) DelListItem(n, ThrottlingHash[i]);
1005 			cnt++;
1006 			MyFree(n);
1007 			n = &z;
1008 		}
1009 	Debug((DEBUG_DEBUG, "fix_timers(): removed %d throttling item(s)", cnt));
1010 
1011 	Debug((DEBUG_DEBUG, "fix_timers(): updating nextping/nextconnect/nextdnscheck/nextexpire (%ld/%ld/%ld/%ld)",
1012 		nextping, nextconnect, nextdnscheck, nextexpire));
1013 	nextping = nextconnect = nextdnscheck = nextexpire = 1;
1014 }
1015 
1016 
1017 #ifndef _WIN32
generate_cloakkeys()1018 static void generate_cloakkeys()
1019 {
1020 	/* Generate 3 cloak keys */
1021 #define GENERATE_CLOAKKEY_MINLEN 16
1022 #define GENERATE_CLOAKKEY_MAXLEN 32 /* Length of cloak keys to generate. */
1023 	char keyBuf[GENERATE_CLOAKKEY_MAXLEN + 1];
1024 	int keyNum;
1025 	int keyLen;
1026 	int charIndex;
1027 	int value;
1028 
1029 	short has_upper;
1030 	short has_lower;
1031 	short has_num;
1032 
1033 	fprintf(stderr, "Here are 3 random cloak keys:\n");
1034 
1035 	for (keyNum = 0; keyNum < 3; ++keyNum)
1036 	{
1037 		has_upper = 0;
1038 		has_lower = 0;
1039 		has_num = 0;
1040 
1041 		keyLen = (getrandom8() % (GENERATE_CLOAKKEY_MAXLEN - GENERATE_CLOAKKEY_MINLEN + 1)) + GENERATE_CLOAKKEY_MINLEN;
1042 		for (charIndex = 0; charIndex < keyLen; ++charIndex)
1043 		{
1044 			switch (getrandom8() % 3)
1045 			{
1046 				case 0: /* Uppercase. */
1047 					keyBuf[charIndex] = (char)('A' + (getrandom8() % ('Z' - 'A')));
1048 					has_upper = 1;
1049 					break;
1050 				case 1: /* Lowercase. */
1051 					keyBuf[charIndex] = (char)('a' + (getrandom8() % ('z' - 'a')));
1052 					has_lower = 1;
1053 					break;
1054 				case 2: /* Digit. */
1055 					keyBuf[charIndex] = (char)('0' + (getrandom8() % ('9' - '0')));
1056 					has_num = 1;
1057 					break;
1058 			}
1059 		}
1060 		keyBuf[keyLen] = '\0';
1061 
1062 		if (has_upper && has_lower && has_num)
1063 			(void)fprintf(stderr, "%s\n", keyBuf);
1064 		else
1065 			/* Try again. For this reason, keyNum must be signed. */
1066 			keyNum--;
1067 	}
1068 }
1069 #endif
1070 
1071 /* MY tdiff... because 'double' sucks.
1072  * This should work until 2038, and very likely after that as well
1073  * because 'long' should be 64 bit on all systems by then... -- Syzop
1074  */
1075 #define mytdiff(a, b)   ((long)a - (long)b)
1076 
1077 #ifndef _WIN32
main(int argc,char * argv[])1078 int main(int argc, char *argv[])
1079 #else
1080 int InitwIRCD(int argc, char *argv[])
1081 #endif
1082 {
1083 #ifdef _WIN32
1084 	WORD wVersionRequested = MAKEWORD(1, 1);
1085 	WSADATA wsaData;
1086 #else
1087 	uid_t uid, euid;
1088 	gid_t gid, egid;
1089 	TS   delay = 0;
1090 	struct passwd *pw;
1091 	struct group *gr;
1092 #endif
1093 #ifdef HAVE_PSTAT
1094 	union pstun pstats;
1095 #endif
1096 	int  portarg = 0;
1097 #ifdef  FORCE_CORE
1098 	struct rlimit corelim;
1099 #endif
1100 #ifndef NO_FDLIST
1101 	TS   nextfdlistcheck = 0;	/*end of priority code */
1102 #endif
1103 
1104 	memset(&botmotd, '\0', sizeof(aMotdFile));
1105 	memset(&rules, '\0', sizeof(aMotdFile));
1106 	memset(&opermotd, '\0', sizeof(aMotdFile));
1107 	memset(&motd, '\0', sizeof(aMotdFile));
1108 	memset(&smotd, '\0', sizeof(aMotdFile));
1109 	memset(&svsmotd, '\0', sizeof(aMotdFile));
1110 
1111 #ifdef _WIN32
1112 	CreateMutex(NULL, FALSE, "UnrealMutex");
1113 	SetErrorMode(SEM_FAILCRITICALERRORS);
1114 #endif
1115 #if !defined(_WIN32) && !defined(_AMIGA)
1116 	sbrk0 = (char *)sbrk((size_t)0);
1117 	uid = getuid();
1118 	euid = geteuid();
1119 	gid = getgid();
1120 	egid = getegid();
1121 
1122 #ifndef IRC_USER
1123 	if (!euid)
1124 	{
1125 		fprintf(stderr,
1126 			"WARNING: You are running UnrealIRCd as root and it is not\n"
1127 			"         configured to drop priviliges. This is _very_ dangerous,\n"
1128 			"         as any compromise of your UnrealIRCd is the same as\n"
1129 			"         giving a cracker root SSH access to your box.\n"
1130 			"         You should either start UnrealIRCd under a different\n"
1131 			"         account than root, or set IRC_USER in include/config.h\n"
1132 			"         to a nonprivileged username and recompile.\n");
1133 	}
1134 #endif /* IRC_USER */
1135 
1136 # ifdef	PROFIL
1137 	(void)monstartup(0, etext);
1138 	(void)moncontrol(1);
1139 	(void)signal(SIGUSR1, s_monitor);
1140 # endif
1141 #endif
1142 #if defined(IRC_USER) && defined(IRC_GROUP)
1143 	if ((int)getuid() == 0) {
1144 
1145 		pw = getpwnam(IRC_USER);
1146 		gr = getgrnam(IRC_GROUP);
1147 
1148 		if ((pw == NULL) || (gr == NULL)) {
1149 			fprintf(stderr, "ERROR: Unable to lookup to specified user (IRC_USER) or group (IRC_GROUP): %s\n", strerror(errno));
1150 			exit(-1);
1151 		} else {
1152 			irc_uid = pw->pw_uid;
1153 			irc_gid = gr->gr_gid;
1154 		}
1155 	}
1156 #endif
1157 #ifdef	CHROOTDIR
1158 	if (chdir(dpath)) {
1159 		perror("chdir");
1160 		fprintf(stderr, "ERROR: Unable to change to directory '%s'\n", dpath);
1161 		exit(-1);
1162 	}
1163 	if (geteuid() != 0)
1164 		fprintf(stderr, "WARNING: IRCd compiled with CHROOTDIR but effective user id is not root!? "
1165 		                "Booting is very likely to fail...\n");
1166 	init_resolver(1);
1167 	{
1168 		struct stat sb;
1169 		mode_t umaskold;
1170 
1171 		umaskold = umask(0);
1172 		if (mkdir("dev", S_IRUSR|S_IWUSR|S_IXUSR|S_IXGRP|S_IXOTH) != 0 && errno != EEXIST)
1173 		{
1174 			fprintf(stderr, "ERROR: Cannot mkdir dev: %s\n", strerror(errno));
1175 			exit(5);
1176 		}
1177 		if (stat("/dev/urandom", &sb) != 0)
1178 		{
1179 			fprintf(stderr, "ERROR: Cannot stat /dev/urandom: %s\n", strerror(errno));
1180 			exit(5);
1181 		}
1182 		if (mknod("dev/urandom", sb.st_mode, sb.st_rdev) != 0 && errno != EEXIST)
1183 		{
1184 			fprintf(stderr, "ERROR: Cannot mknod dev/urandom: %s\n", strerror(errno));
1185 			exit(5);
1186 		}
1187 		if (stat("/dev/null", &sb) != 0)
1188 		{
1189 			fprintf(stderr, "ERROR: Cannot stat /dev/null: %s\n", strerror(errno));
1190 			exit(5);
1191 		}
1192 		if (mknod("dev/null", sb.st_mode, sb.st_rdev) != 0 && errno != EEXIST)
1193 		{
1194 			fprintf(stderr, "ERROR: Cannot mknod dev/null: %s\n", strerror(errno));
1195 			exit(5);
1196 		}
1197 		if (stat("/dev/tty", &sb) != 0)
1198 		{
1199 			fprintf(stderr, "ERROR: Cannot stat /dev/tty: %s\n", strerror(errno));
1200 			exit(5);
1201 		}
1202 		if (mknod("dev/tty", sb.st_mode, sb.st_rdev) != 0 && errno != EEXIST)
1203 		{
1204 			fprintf(stderr, "ERROR: Cannot mknod dev/tty: %s\n", strerror(errno));
1205 			exit(5);
1206 		}
1207 		umask(umaskold);
1208 	}
1209 	if (chroot(DPATH)) {
1210 		(void)fprintf(stderr, "ERROR:  Cannot (chdir/)chroot to directory '%s'\n", dpath);
1211 		exit(5);
1212 	}
1213 #endif	 /*CHROOTDIR*/
1214 #ifndef _WIN32
1215 	myargv = argv;
1216 #else
1217 	cmdLine = GetCommandLine();
1218 #endif
1219 #ifndef _WIN32
1220 	(void)umask(077);	/* better safe than sorry --SRB */
1221 #else
1222 	WSAStartup(wVersionRequested, &wsaData);
1223 #endif
1224 	bzero((char *)&me, sizeof(me));
1225 	bzero(&StatsZ, sizeof(StatsZ));
1226 	setup_signals();
1227 	charsys_reset();
1228 	init_ircstats();
1229 #ifdef USE_LIBCURL
1230 	url_init();
1231 #endif
1232 	tkl_init();
1233 	umode_init();
1234 #ifdef EXTCMODE
1235 	extcmode_init();
1236 #endif
1237 	extban_init();
1238 	init_random(); /* needs to be done very early!! */
1239 	clear_scache_hash_table();
1240 #ifdef FORCE_CORE
1241 	corelim.rlim_cur = corelim.rlim_max = RLIM_INFINITY;
1242 	if (setrlimit(RLIMIT_CORE, &corelim))
1243 		printf("unlimit core size failed; errno = %d\n", errno);
1244 #endif
1245 	/*
1246 	 * ** All command line parameters have the syntax "-fstring"
1247 	 * ** or "-f string" (e.g. the space is optional). String may
1248 	 * ** be empty. Flag characters cannot be concatenated (like
1249 	 * ** "-fxyz"), it would conflict with the form "-fstring".
1250 	 */
1251 	while (--argc > 0 && (*++argv)[0] == '-') {
1252 		char *p = argv[0] + 1;
1253 		int  flag = *p++;
1254 		if (flag == '\0' || *p == '\0') {
1255 			if (argc > 1 && argv[1][0] != '-') {
1256 				p = *++argv;
1257 				argc -= 1;
1258 			} else
1259 				p = "";
1260 		}
1261 		switch (flag) {
1262 #ifndef _WIN32
1263 		  case 'a':
1264 			  bootopt |= BOOT_AUTODIE;
1265 			  break;
1266 		  case 'c':
1267 			  bootopt |= BOOT_CONSOLE;
1268 			  break;
1269 		  case 'q':
1270 			  bootopt |= BOOT_QUICK;
1271 			  break;
1272 		  case 'd':
1273 			  (void)setuid((uid_t) uid);
1274 #else
1275 		  case 'd':
1276 #endif
1277 			  dpath = p;
1278 			  break;
1279 		  case 'F':
1280 			  bootopt |= BOOT_NOFORK;
1281 			  break;
1282 #ifndef _WIN32
1283 		  case 'f':
1284 #ifndef CMDLINE_CONFIG
1285 		      if ((uid == euid) && (gid == egid))
1286 			       configfile = p;
1287 			  else
1288 			       printf("ERROR: Command line config with a setuid/setgid ircd is not allowed");
1289 #else
1290 			  (void)setuid((uid_t) uid);
1291 			  configfile = p;
1292 #endif
1293 			  break;
1294 		  case 'h':
1295 			  if (!strchr(p, '.')) {
1296 
1297 				  (void)printf
1298 				      ("ERROR: %s is not valid: Server names must contain at least 1 \".\"\n",
1299 				      p);
1300 				  exit(1);
1301 			  }
1302 			  strncpyzt(me.name, p, sizeof(me.name));
1303 			  break;
1304 #endif
1305 #ifndef _WIN32
1306 		  case 'P':{
1307 			  short type;
1308 			  char *result;
1309 			  srandom(TStime());
1310 			  if ((type = Auth_FindType(p)) == -1) {
1311 				  printf("No such auth type %s\n", p);
1312 				  exit(0);
1313 			  }
1314 			  p = *++argv;
1315 			  argc--;
1316 #ifdef AUTHENABLE_UNIXCRYPT
1317 			  if ((type == AUTHTYPE_UNIXCRYPT) && (strlen(p) > 8))
1318 			  {
1319 			      printf("WARNING: Password truncated to 8 characters due to 'crypt' algorithm. "
1320 		                 "You are suggested to use the 'md5' algorithm instead.");
1321 				  p[8] = '\0';
1322 			  }
1323 #endif
1324 			  if (!(result = Auth_Make(type, p))) {
1325 				  printf("Authentication failed\n");
1326 				  exit(0);
1327 			  }
1328 			  printf("Encrypted password is: %s\n", result);
1329 			  exit(0);
1330 		  }
1331 #endif
1332 
1333 		  case 'p':
1334 			  if ((portarg = atoi(p)) > 0)
1335 				  portnum = portarg;
1336 			  break;
1337 		  case 's':
1338 			  (void)printf("sizeof(aClient) == %ld\n",
1339 			      (long)sizeof(aClient));
1340 			  (void)printf("sizeof(aChannel) == %ld\n",
1341 			      (long)sizeof(aChannel));
1342 			  (void)printf("sizeof(aServer) == %ld\n",
1343 			      (long)sizeof(aServer));
1344 			  (void)printf("sizeof(Link) == %ld\n",
1345 			      (long)sizeof(Link));
1346 			  (void)printf("sizeof(anUser) == %ld\n",
1347 			      (long)sizeof(anUser));
1348 			  (void)printf("sizeof(aTKline) == %ld\n",
1349 			      (long)sizeof(aTKline));
1350 			  (void)printf("sizeof(struct ircstatsx) == %ld\n",
1351 			      (long)sizeof(struct ircstatsx));
1352 			  (void)printf("aClient remote == %ld\n",
1353 			      (long)CLIENT_REMOTE_SIZE);
1354 			  exit(0);
1355 			  break;
1356 #ifndef _WIN32
1357 		  case 't':
1358 			  (void)setuid((uid_t) uid);
1359 			  bootopt |= BOOT_TTY;
1360 			  break;
1361 		  case 'v':
1362 			  (void)printf("%s build %s\n", version, buildid);
1363 #else
1364 		  case 'v':
1365 			  if (!IsService) {
1366 				  MessageBox(NULL, version,
1367 				      "UnrealIRCD/Win32 version", MB_OK);
1368 			  }
1369 #endif
1370 			  exit(0);
1371 		  case 'C':
1372 			  config_verbose = atoi(p);
1373 			  break;
1374 		  case 'x':
1375 #ifdef	DEBUGMODE
1376 # ifndef _WIN32
1377 			  (void)setuid((uid_t) uid);
1378 # endif
1379 			  debuglevel = atoi(p);
1380 			  debugmode = *p ? p : "0";
1381 			  bootopt |= BOOT_DEBUG;
1382 			  break;
1383 #else
1384 # ifndef _WIN32
1385 			  (void)fprintf(stderr,
1386 			      "%s: DEBUGMODE must be defined for -x y\n",
1387 			      myargv[0]);
1388 # else
1389 			  if (!IsService) {
1390 				  MessageBox(NULL,
1391 				      "DEBUGMODE must be defined for -x option",
1392 				      "UnrealIRCD/32", MB_OK);
1393 			  }
1394 # endif
1395 			  exit(0);
1396 #endif
1397 #ifndef _WIN32
1398 		  case 'k':
1399 			  generate_cloakkeys();
1400 			  exit(0);
1401 #endif
1402 		  default:
1403 			  return bad_command();
1404 			  break;
1405 		}
1406 	}
1407 
1408 	do_version_check();
1409 
1410 #ifndef	CHROOTDIR
1411 	if (chdir(dpath)) {
1412 # ifndef _WIN32
1413 		perror("chdir");
1414 		fprintf(stderr, "ERROR: Unable to change to directory '%s'\n", dpath);
1415 # else
1416 		if (!IsService) {
1417 			MessageBox(NULL, strerror(GetLastError()),
1418 			    "UnrealIRCD/32: chdir()", MB_OK);
1419 		}
1420 # endif
1421 		exit(-1);
1422 	}
1423 #endif
1424 #ifndef _WIN32
1425 	mkdir("/var/run/ircd/tmp", S_IRUSR|S_IWUSR|S_IXUSR); /* Create the tmp dir, if it doesn't exist */
1426  #if defined(USE_LIBCURL) && defined(REMOTEINC_SPECIALCACHE)
1427  	mkdir("cache", S_IRUSR|S_IWUSR|S_IXUSR); /* Create the cache dir, if using curl and it doesn't exist */
1428  #endif
1429 #else
1430 	mkdir("/var/run/ircd/tmp");
1431  #if defined(USE_LIBCURL) && defined(REMOTEINC_SPECIALCACHE)
1432  	mkdir("cache");
1433  #endif
1434 #endif
1435 #ifndef _WIN32
1436 	/*
1437 	 * didn't set debuglevel
1438 	 */
1439 	/*
1440 	 * but asked for debugging output to tty
1441 	 */
1442 	if ((debuglevel < 0) && (bootopt & BOOT_TTY)) {
1443 		(void)fprintf(stderr,
1444 		    "you specified -t without -x. use -x <n>\n");
1445 		exit(-1);
1446 	}
1447 #endif
1448 
1449 	/* HACK! This ifndef should be removed when the restart-on-w32-brings-up-dialog bug
1450 	 * is fixed. This is just an ugly "ignore the invalid parameter" thing ;). -- Syzop
1451 	 */
1452 #ifndef _WIN32
1453 	if (argc > 0)
1454 		return bad_command();	/* This should exit out */
1455 #endif
1456 #ifndef _WIN32
1457 	fprintf(stderr, "%s", unreallogo);
1458 	fprintf(stderr, "                           v%s\n", VERSIONONLY);
1459 	fprintf(stderr, "                     using %s\n", tre_version());
1460 #ifdef USE_SSL
1461 	fprintf(stderr, "                     using %s\n", SSLeay_version(SSLEAY_VERSION));
1462 #endif
1463 #ifdef ZIP_LINKS
1464 	fprintf(stderr, "                     using zlib %s\n", zlibVersion());
1465 #endif
1466 #ifdef USE_LIBCURL
1467 	fprintf(stderr, "                     using %s\n", curl_version());
1468 #endif
1469 	fprintf(stderr, "\n");
1470 #endif
1471 	clear_client_hash_table();
1472 	clear_channel_hash_table();
1473 	clear_watch_hash_table();
1474 	bzero(&loop, sizeof(loop));
1475 	init_CommandHash();
1476 	initlists();
1477 	initwhowas();
1478 	initstats();
1479 	DeleteTempModules();
1480 	booted = FALSE;
1481 /* Hack to stop people from being able to read the config file */
1482 #if !defined(_WIN32) && !defined(_AMIGA) && !defined(OSXTIGER) && DEFAULT_PERMISSIONS != 0
1483 	chmod(CPATH, DEFAULT_PERMISSIONS);
1484 #endif
1485 	init_dynconf();
1486 #ifdef STATIC_LINKING
1487 	{
1488 		ModuleInfo ModCoreInfo;
1489 		ModCoreInfo.size = sizeof(ModuleInfo);
1490 		ModCoreInfo.module_load = 0;
1491 		ModCoreInfo.handle = NULL;
1492 		l_commands_Test(&ModCoreInfo);
1493 	}
1494 #endif
1495 	/*
1496 	 * Add default class
1497 	 */
1498 	default_class =
1499 	    (ConfigItem_class *) MyMallocEx(sizeof(ConfigItem_class));
1500 	default_class->flag.permanent = 1;
1501 	default_class->pingfreq = PINGFREQUENCY;
1502 	default_class->maxclients = 100;
1503 	default_class->sendq = MAXSENDQLENGTH;
1504 	default_class->name = "default";
1505 	AddListItem(default_class, conf_class);
1506 	if (init_conf(configfile, 0) < 0)
1507 	{
1508 		exit(-1);
1509 	}
1510 	booted = TRUE;
1511 	load_tunefile();
1512 	make_umodestr();
1513 	make_cmodestr();
1514 #ifdef EXTCMODE
1515 	make_extcmodestr();
1516 #endif
1517 	make_extbanstr();
1518 	isupport_init();
1519 	if (!find_Command_simple("AWAY") /*|| !find_Command_simple("KILL") ||
1520 		!find_Command_simple("OPER") || !find_Command_simple("PING")*/)
1521 	{
1522 		config_error("Someone forgot to load modules with proper commands in them. READ THE DOCUMENTATION");
1523 #ifdef _WIN32
1524 		/* Temporary! */
1525 		config_error("As of Unreal3.2.1 modules are supported on windows, "
1526 		    "therefore you MUST load the commands.dll module and a cloaking module. "
1527 		    "Just add 'loadmodule \"modules/commands.dll\"' and 'loadmodule \"modules/cloak.dll\"' "
1528 		    "to your unrealircd.conf and be sure to read the release notes!");
1529 		win_error();
1530 #endif
1531 		exit(-4);
1532 	}
1533 
1534 #ifdef USE_SSL
1535 #ifndef _WIN32
1536 	fprintf(stderr, "* Initializing SSL.\n");
1537 #endif
1538 	init_ssl();
1539 #endif
1540 #ifndef _WIN32
1541 	fprintf(stderr,
1542 	    "* Dynamic configuration initialized .. booting IRCd.\n");
1543 	fprintf(stderr,
1544 	    "---------------------------------------------------------------------\n");
1545 #endif
1546 	if (time(NULL) > 1459461600)
1547 	{
1548 		fprintf(stderr, "WARNING: UnrealIRCd 3.2.x is no longer supported after December 31, 2016.\n"
1549 		                "See https://www.unrealircd.org/docs/UnrealIRCd_3.2.x_deprecated\n");
1550 	}
1551 	open_debugfile();
1552 #ifndef NO_FDLIST
1553 	init_fdlist(&serv_fdlist);
1554 	init_fdlist(&busycli_fdlist);
1555 	init_fdlist(&default_fdlist);
1556 	init_fdlist(&oper_fdlist);
1557 	init_fdlist(&unknown_fdlist);
1558 	{
1559 		int  i;
1560 		for (i = MAXCONNECTIONS + 1; i > 0; i--)
1561 			default_fdlist.entry[i] = i;
1562 	}
1563 #endif
1564 	if (portnum < 0)
1565 		portnum = PORTNUM;
1566 	me.port = portnum;
1567 	(void)init_sys();
1568 	me.flags = FLAGS_LISTEN;
1569 	me.fd = -1;
1570 	SetMe(&me);
1571 	make_server(&me);
1572 #ifdef HAVE_SYSLOG
1573 	openlog("ircd", LOG_PID | LOG_NDELAY, LOG_DAEMON);
1574 #endif
1575 	/*
1576 	 * Put in our info
1577 	 */
1578 	strncpyzt(me.info, conf_me->info, sizeof(me.info));
1579 	strncpyzt(me.name, conf_me->name, sizeof(me.name));
1580 	/*
1581 	 * We accept the first listen record
1582 	 */
1583 	portnum = conf_listen->port;
1584 /*
1585  *      This is completely unneeded-Sts
1586    	me.ip.S_ADDR =
1587 	    *conf_listen->ip != '*' ? inet_addr(conf_listen->ip) : INADDR_ANY;
1588 */
1589 	Debug((DEBUG_ERROR, "Port = %d", portnum));
1590 	if (inetport(&me, conf_listen->ip, portnum))
1591 		exit(1);
1592 	set_non_blocking(me.fd, &me);
1593 	conf_listen->options |= LISTENER_BOUND;
1594 	me.umodes = conf_listen->options;
1595 	conf_listen->listener = &me;
1596 	run_configuration();
1597 	ircd_log(LOG_ERROR, "UnrealIRCd started.");
1598 
1599 	read_motd(conf_files->botmotd_file, &botmotd);
1600 	read_motd(conf_files->rules_file, &rules);
1601 	read_motd(conf_files->opermotd_file, &opermotd);
1602 	read_motd(conf_files->motd_file, &motd);
1603 	read_motd(conf_files->smotd_file, &smotd);
1604 	read_motd(conf_files->svsmotd_file, &svsmotd);
1605 
1606 	strncpy(me.sockhost, conf_listen->ip, sizeof(me.sockhost) - 1);
1607 	if (me.name[0] == '\0')
1608 		strncpyzt(me.name, me.sockhost, sizeof(me.name));
1609 	me.hopcount = 0;
1610 	me.authfd = -1;
1611 	me.next = NULL;
1612 	me.user = NULL;
1613 	me.from = &me;
1614 	me.class = (ConfigItem_class *) conf_listen;
1615 	/*
1616 	 * This listener will never go away
1617 	 */
1618 	conf_listen->clients++;
1619 	me_hash = find_or_add(me.name);
1620 	me.serv->up = me_hash;
1621 	me.serv->numeric = conf_me->numeric;
1622 	add_server_to_table(&me);
1623 	timeofday = time(NULL);
1624 	me.lasttime = me.since = me.firsttime = TStime();
1625 	(void)add_to_client_hash_table(me.name, &me);
1626 #if !defined(_AMIGA) && !defined(_WIN32) && !defined(NO_FORKING)
1627 	if (!(bootopt & BOOT_NOFORK))
1628 		if (fork())
1629 			exit(0);
1630 #endif
1631 	(void)ircsprintf(REPORT_DO_DNS, ":%s %s", me.name, BREPORT_DO_DNS);
1632 	(void)ircsprintf(REPORT_FIN_DNS, ":%s %s", me.name, BREPORT_FIN_DNS);
1633 	(void)ircsprintf(REPORT_FIN_DNSC, ":%s %s", me.name, BREPORT_FIN_DNSC);
1634 	(void)ircsprintf(REPORT_FAIL_DNS, ":%s %s", me.name, BREPORT_FAIL_DNS);
1635 	(void)ircsprintf(REPORT_DO_ID, ":%s %s", me.name, BREPORT_DO_ID);
1636 	(void)ircsprintf(REPORT_FIN_ID, ":%s %s", me.name, BREPORT_FIN_ID);
1637 	(void)ircsprintf(REPORT_FAIL_ID, ":%s %s", me.name, BREPORT_FAIL_ID);
1638 	R_do_dns = strlen(REPORT_DO_DNS);
1639 	R_fin_dns = strlen(REPORT_FIN_DNS);
1640 	R_fin_dnsc = strlen(REPORT_FIN_DNSC);
1641 	R_fail_dns = strlen(REPORT_FAIL_DNS);
1642 	R_do_id = strlen(REPORT_DO_ID);
1643 	R_fin_id = strlen(REPORT_FIN_ID);
1644 	R_fail_id = strlen(REPORT_FAIL_ID);
1645 
1646 #if !defined(IRC_USER) && !defined(_WIN32)
1647 	if ((uid != euid) && !euid) {
1648 		(void)fprintf(stderr,
1649 		    "ERROR: do not run ircd setuid root. Make it setuid a normal user.\n");
1650 		exit(-1);
1651 	}
1652 #endif
1653 
1654 #if defined(IRC_USER) && defined(IRC_GROUP)
1655 	if ((int)getuid() == 0) {
1656 		/* NOTE: irc_uid/irc_gid have been looked up earlier, before the chrooting code */
1657 
1658 		if ((irc_uid == 0) || (irc_gid == 0)) {
1659 			(void)fprintf(stderr,
1660 			    "ERROR: SETUID and SETGID have not been set properly"
1661 			    "\nPlease read your documentation\n(HINT: IRC_USER and IRC_GROUP in include/config.h cannot be root/wheel)\n");
1662 			exit(-1);
1663 		} else {
1664 			/*
1665 			 * run as a specified user
1666 			 */
1667 
1668 			(void)fprintf(stderr, "WARNING: ircd invoked as root\n");
1669 			(void)fprintf(stderr, "         changing to uid %d\n", irc_uid);
1670 			(void)fprintf(stderr, "         changing to gid %d\n", irc_gid);
1671 			if (setgid(irc_gid))
1672 			{
1673 				fprintf(stderr, "ERROR: Unable to change group: %s\n", strerror(errno));
1674 				exit(-1);
1675 			}
1676 			if (setuid(irc_uid))
1677 			{
1678 				fprintf(stderr, "ERROR: Unable to change userid: %s\n", strerror(errno));
1679 				exit(-1);
1680 			}
1681 		}
1682 	}
1683 #endif
1684 	if (TIMESYNCH)
1685 	{
1686 		if (!unreal_time_synch(TIMESYNCH_TIMEOUT))
1687 			ircd_log(LOG_ERROR, "TIME SYNCH: Unable to synchronize time: %s. "
1688 			                    "This means UnrealIRCd was unable to synchronize the IRCd clock to a known good time source. "
1689 			                    "As long as the server owner keeps the server clock synchronized through NTP, everything will be fine.",
1690 				unreal_time_synch_error());
1691 	}
1692 	fix_timers(); /* Fix timers AFTER reading tune file AND timesynch */
1693 	write_pidfile();
1694 	Debug((DEBUG_NOTICE, "Server ready..."));
1695 	SetupEvents();
1696 #ifdef THROTTLING
1697 	init_throttling_hash();
1698 #endif
1699 #ifdef NEWCHFLOODPROT
1700 	init_modef();
1701 #endif
1702 	loop.do_bancheck = 0;
1703 	loop.ircd_booted = 1;
1704 #if defined(HAVE_SETPROCTITLE)
1705 	setproctitle("%s", me.name);
1706 #elif defined(HAVE_PSTAT)
1707 	pstats.pst_command = me.name;
1708 	pstat(PSTAT_SETCMD, pstats, strlen(me.name), 0, 0);
1709 #elif defined(HAVE_PSSTRINGS)
1710 	PS_STRINGS->ps_nargvstr = 1;
1711 	PS_STRINGS->ps_argvstr = me.name;
1712 #endif
1713 	module_loadall(0);
1714 #ifdef STATIC_LINKING
1715 	l_commands_Load(0);
1716 #endif
1717 
1718 #ifndef NO_FDLIST
1719 	check_fdlists(TStime());
1720 #endif
1721 
1722 #ifdef _WIN32
1723 	return 1;
1724 }
1725 
1726 
SocketLoop(void * dummy)1727 void SocketLoop(void *dummy)
1728 {
1729 	TS   delay = 0;
1730 	static TS lastglinecheck = 0;
1731 	TS   last_tune;
1732 #ifndef NO_FDLIST
1733 	TS   nextfdlistcheck = 0;	/*end of priority code */
1734 #endif
1735 
1736 
1737 	while (1)
1738 #else
1739 	nextping = timeofday;
1740 	/*
1741 	 * Forever drunk .. forever drunk ..
1742 	 * * (Sorry Alphaville.)
1743 	 */
1744 	for (;;)
1745 #endif
1746 	{
1747 
1748 #define NEGATIVE_SHIFT_WARN	-15
1749 #define POSITIVE_SHIFT_WARN	20
1750 
1751 		timeofday = time(NULL) + TSoffset;
1752 		if (oldtimeofday == 0)
1753 			oldtimeofday = timeofday; /* pretend everything is ok the first time.. */
1754 		if (mytdiff(timeofday, oldtimeofday) < NEGATIVE_SHIFT_WARN) {
1755 			/* tdiff = # of seconds of time set backwards (positive number! eg: 60) */
1756 			long tdiff = oldtimeofday - timeofday;
1757 			ircd_log(LOG_ERROR, "WARNING: Time running backwards! Clock set back ~%ld seconds (%ld -> %ld)",
1758 				tdiff, oldtimeofday, timeofday);
1759 			ircd_log(LOG_ERROR, "[TimeShift] Resetting a few timers to prevent IRCd freeze!");
1760 			sendto_realops("WARNING: Time running backwards! Clock set back ~%ld seconds (%ld -> %ld)",
1761 				tdiff, oldtimeofday, timeofday);
1762 			sendto_realops("Incorrect time for IRC servers is a serious problem. "
1763 			               "Time being set backwards (either by TSCTL or by resetting the clock) is "
1764 			               "even more serious and can cause clients to freeze, channels to be "
1765 			               "taken over, and other issues.");
1766 			sendto_realops("Please be sure your clock is always synchronized before "
1767 			               "the IRCd is started or use the built-in timesynch feature.");
1768 			sendto_realops("[TimeShift] Resetting a few timers to prevent IRCd freeze!");
1769 			fix_timers();
1770 			nextfdlistcheck = 0;
1771 		} else
1772 		if (mytdiff(timeofday, oldtimeofday) > POSITIVE_SHIFT_WARN) /* do not set too low or you get false positives */
1773 		{
1774 			/* tdiff = # of seconds of time set forward (eg: 60) */
1775 			long tdiff = timeofday - oldtimeofday;
1776 			ircd_log(LOG_ERROR, "WARNING: Time jumped ~%ld seconds ahead! (%ld -> %ld)",
1777 				tdiff, oldtimeofday, timeofday);
1778 			ircd_log(LOG_ERROR, "[TimeShift] Resetting some timers!");
1779 			sendto_realops("WARNING: Time jumped ~%ld seconds ahead! (%ld -> %ld)",
1780 			        tdiff, oldtimeofday, timeofday);
1781 			sendto_realops("Incorrect time for IRC servers is a serious problem. "
1782 			               "Time being adjusted (either by TSCTL or by resetting the clock) "
1783 			               "more than a few seconds forward/backward can lead to serious issues.");
1784 			sendto_realops("Please be sure your clock is always synchronized before "
1785 			               "the IRCd is started or use the built-in timesynch feature.");
1786 			sendto_realops("[TimeShift] Resetting some timers!");
1787 			fix_timers();
1788 			nextfdlistcheck = 0;
1789 		}
1790 		if (highesttimeofday+NEGATIVE_SHIFT_WARN > timeofday)
1791 		{
1792 			if (lasthighwarn > timeofday)
1793 				lasthighwarn = timeofday;
1794 			if (timeofday - lasthighwarn > 300)
1795 			{
1796 				ircd_log(LOG_ERROR, "[TimeShift] The (IRCd) clock was set backwards. "
1797 					"Waiting for time to be OK again. This will be in %ld seconds",
1798 					highesttimeofday - timeofday);
1799 				sendto_realops("[TimeShift] The (IRCd) clock was set backwards. Timers, nick- "
1800 				               "and channel-timestamps are possibly incorrect. This message will "
1801 				               "repeat itself until we catch up with the original time, which will be "
1802 				               "in %ld seconds", highesttimeofday - timeofday);
1803 				lasthighwarn = timeofday;
1804 			}
1805 		} else {
1806 			highesttimeofday = timeofday;
1807 		}
1808 		oldtimeofday = timeofday;
1809 		LockEventSystem();
1810 		DoEvents();
1811 		UnlockEventSystem();
1812 		/*
1813 		 * ** Run through the hashes and check lusers every
1814 		 * ** second
1815 		 * ** also check for expiring glines
1816 		 */
1817 
1818 #ifndef NO_FDLIST
1819 		lastrecvK = me.receiveK;
1820 		lastsendK = me.sendK;
1821 #endif
1822 		if (IRCstats.clients > IRCstats.global_max)
1823 			IRCstats.global_max = IRCstats.clients;
1824 		if (IRCstats.me_clients > IRCstats.me_max)
1825 			IRCstats.me_max = IRCstats.me_clients;
1826 		/*
1827 		 * ** We only want to connect if a connection is due,
1828 		 * ** not every time through.  Note, if there are no
1829 		 * ** active C lines, this call to Tryconnections is
1830 		 * ** made once only; it will return 0. - avalon
1831 		 */
1832 		if (nextconnect && timeofday >= nextconnect)
1833 			nextconnect = try_connections(timeofday);
1834 
1835 		/*
1836 		 * ** take the smaller of the two 'timed' event times as
1837 		 * ** the time of next event (stops us being late :) - avalon
1838 		 * ** WARNING - nextconnect can return 0!
1839 		 */
1840 		if (nextconnect)
1841 			delay = MIN(nextping, nextconnect);
1842 		else
1843 			delay = nextping;
1844 		delay = MIN(nextdnscheck, delay);
1845 		delay = MIN(nextexpire, delay);
1846 		delay -= timeofday;
1847 		/*
1848 		 * ** Adjust delay to something reasonable [ad hoc values]
1849 		 * ** (one might think something more clever here... --msa)
1850 		 * ** We don't really need to check that often and as long
1851 		 * ** as we don't delay too long, everything should be ok.
1852 		 * ** waiting too long can cause things to timeout...
1853 		 * ** i.e. PINGS -> a disconnection :(
1854 		 * ** - avalon
1855 		 */
1856 		if (delay < 1)
1857 			delay = 1;
1858 		else
1859 			delay = MIN(delay, TIMESEC);
1860 #ifdef NO_FDLIST
1861 		(void)read_message(delay);
1862 		timeofday = time(NULL) + TSoffset;
1863 #else
1864 		(void)read_message(0, &serv_fdlist);	/* servers */
1865 		(void)read_message(1, &busycli_fdlist);	/* busy clients */
1866 		if (lifesux) {
1867 			static time_t alllasttime = 0;
1868 
1869 			(void)read_message(1, &serv_fdlist);
1870 			/*
1871 			 * read servs more often
1872 			 */
1873 			if (lifesux > 9) {	/* life really sucks */
1874 				(void)read_message(1, &busycli_fdlist);
1875 				(void)read_message(1, &serv_fdlist);
1876 			}
1877 			flush_fdlist_connections(&serv_fdlist);
1878 			timeofday = time(NULL) + TSoffset;
1879 			if ((alllasttime + (lifesux + 1)) < timeofday) {
1880 				read_message(delay, NULL);	/*  check everything */
1881 				alllasttime = timeofday;
1882 			}
1883 		} else {
1884 			read_message(delay, NULL);	/*  check everything */
1885 			timeofday = time(NULL) + TSoffset;
1886 		}
1887 
1888 #endif
1889 		/*
1890 		 * Debug((DEBUG_DEBUG, "Got message(s)"));
1891 		 */
1892 		/*
1893 		 * ** ...perhaps should not do these loops every time,
1894 		 * ** but only if there is some chance of something
1895 		 * ** happening (but, note that conf->hold times may
1896 		 * ** be changed elsewhere--so precomputed next event
1897 		 * ** time might be too far away... (similarly with
1898 		 * ** ping times) --msa
1899 		 */
1900 #ifdef NO_FDLIST
1901 		if (timeofday >= nextping || loop.do_bancheck)
1902 #else
1903 		if ((timeofday >= nextping && !lifesux) || loop.do_bancheck)
1904 #endif
1905 			nextping = check_pings(timeofday);
1906 		if (dorehash)
1907 		{
1908 			(void)rehash(&me, &me, 1);
1909 			dorehash = 0;
1910 		}
1911 		if (dorestart)
1912 		{
1913 			server_reboot("SIGINT");
1914 		}
1915 
1916 		/*
1917 		 * ** Flush output buffers on all connections timeofday if they
1918 		 * ** have data in them (or at least try to flush)
1919 		 * ** -avalon
1920 		 */
1921 
1922 #ifndef NO_FDLIST
1923 		/*
1924 		 * check which clients are active
1925 		 */
1926 		if (timeofday > nextfdlistcheck)
1927 			nextfdlistcheck = check_fdlists(timeofday);
1928 #endif
1929 		flush_connections(&me);
1930 
1931 		/* ThA UnReAl TrOuBlE RePoRtInG SyStEm!!! */
1932 		if (trouble_info[0] != '\0')
1933 		{
1934 			sendto_realops("*** TROUBLE: %s ***", trouble_info);
1935 			ircd_log(LOG_ERROR, "TROUBLE: %s", trouble_info);
1936 			trouble_info[0] = '\0';
1937 		}
1938 	}
1939 }
1940 
1941 /*
1942  * open_debugfile
1943  *
1944  * If the -t option is not given on the command line when the server is
1945  * started, all debugging output is sent to the file set by LPATH in config.h
1946  * Here we just open that file and make sure it is opened to fd 2 so that
1947  * any fprintf's to stderr also goto the logfile.  If the debuglevel is not
1948  * set from the command line by -x, use /dev/null as the dummy logfile as long
1949  * as DEBUGMODE has been defined, else dont waste the fd.
1950  */
open_debugfile(void)1951 static void open_debugfile(void)
1952 {
1953 #ifdef	DEBUGMODE
1954 	int  fd;
1955 	aClient *cptr;
1956 	if (debuglevel >= 0) {
1957 		cptr = make_client(NULL, NULL);
1958 		cptr->fd = 2;
1959 		SetLog(cptr);
1960 		cptr->port = debuglevel;
1961 		cptr->flags = 0;
1962 		cptr->listener = cptr;
1963 		/*
1964 		 * local[2] = cptr;  winlocal
1965 		 */
1966 		(void)strlcpy(cptr->sockhost, me.sockhost,
1967 		    sizeof cptr->sockhost);
1968 # ifndef _WIN32
1969 		(void)printf("isatty = %d ttyname = %#x\n",
1970 		    isatty(2), (u_int)ttyname(2));
1971 		if (!(bootopt & BOOT_TTY)) {	/* leave debugging output on fd 2 */
1972 			(void)truncate(LOGFILE, 0);
1973 			if ((fd = open(LOGFILE, O_WRONLY | O_CREAT, 0600)) < 0)
1974 				if ((fd = open("/dev/null", O_WRONLY)) < 0)
1975 					exit(-1);
1976 			if (fd != 2) {
1977 				(void)dup2(fd, 2);
1978 				(void)close(fd);
1979 			}
1980 			strncpyzt(cptr->name, LOGFILE, sizeof(cptr->name));
1981 		} else if (isatty(2) && ttyname(2))
1982 			strncpyzt(cptr->name, ttyname(2), sizeof(cptr->name));
1983 		else
1984 # endif
1985 			(void)strcpy(cptr->name, "FD2-Pipe");
1986 		Debug((DEBUG_FATAL,
1987 		    "Debug: File <%s> Level: %d at %s", cptr->name,
1988 		    cptr->port, myctime(time(NULL))));
1989 	} else
1990 		/*
1991 		 * local[2] = NULL; winlocal
1992 		 */
1993 #endif
1994 		return;
1995 }
1996 
setup_signals()1997 static void setup_signals()
1998 {
1999 #ifndef _WIN32
2000 #ifdef	POSIX_SIGNALS
2001 	struct sigaction act;
2002 	act.sa_handler = SIG_IGN;
2003 	act.sa_flags = 0;
2004 	(void)sigemptyset(&act.sa_mask);
2005 	(void)sigaddset(&act.sa_mask, SIGPIPE);
2006 	(void)sigaddset(&act.sa_mask, SIGALRM);
2007 # ifdef	SIGWINCH
2008 	(void)sigaddset(&act.sa_mask, SIGWINCH);
2009 	(void)sigaction(SIGWINCH, &act, NULL);
2010 # endif
2011 	(void)sigaction(SIGPIPE, &act, NULL);
2012 	act.sa_handler = dummy;
2013 	(void)sigaction(SIGALRM, &act, NULL);
2014 	act.sa_handler = s_rehash;
2015 	(void)sigemptyset(&act.sa_mask);
2016 	(void)sigaddset(&act.sa_mask, SIGHUP);
2017 	(void)sigaction(SIGHUP, &act, NULL);
2018 	act.sa_handler = s_restart;
2019 	(void)sigaddset(&act.sa_mask, SIGINT);
2020 	(void)sigaction(SIGINT, &act, NULL);
2021 	act.sa_handler = s_die;
2022 	(void)sigaddset(&act.sa_mask, SIGTERM);
2023 	(void)sigaction(SIGTERM, &act, NULL);
2024 #else
2025 # ifndef	HAVE_RELIABLE_SIGNALS
2026 	(void)signal(SIGPIPE, dummy);
2027 #  ifdef	SIGWINCH
2028 	(void)signal(SIGWINCH, dummy);
2029 #  endif
2030 # else
2031 #  ifdef	SIGWINCH
2032 	(void)signal(SIGWINCH, SIG_IGN);
2033 #  endif
2034 	(void)signal(SIGPIPE, SIG_IGN);
2035 # endif
2036 	(void)signal(SIGALRM, dummy);
2037 	(void)signal(SIGHUP, s_rehash);
2038 	(void)signal(SIGTERM, s_die);
2039 	(void)signal(SIGINT, s_restart);
2040 #endif
2041 #ifdef RESTARTING_SYSTEMCALLS
2042 	/*
2043 	 * ** At least on Apollo sr10.1 it seems continuing system calls
2044 	 * ** after signal is the default. The following 'siginterrupt'
2045 	 * ** should change that default to interrupting calls.
2046 	 */
2047 	(void)siginterrupt(SIGALRM, 1);
2048 #endif
2049 #else
2050 	(void)signal(SIGSEGV, CleanUpSegv);
2051 #endif
2052 }
2053