2 * IRC - Internet Relay Chat, ircd/ircd.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
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)
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.
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.
34 #include <sys/resource.h>
47 #include <netinet/in.h>
48 #include <arpa/nameser.h>
52 #include <sys/socket.h> /* Needed for AF_INET on some OS */
77 extern void init_counters(void);
79 aClient me; /* That's me */
80 aClient *client = &me; /* Pointer to beginning of Client list */
81 time_t TSoffset = 0; /* Global variable; Offset of timestamps to
85 unsigned short int portnum = 0; /* Server port number, listening this */
86 char *configfile = CPATH; /* Server configuration file */
87 int debuglevel = -1; /* Server debug level */
88 unsigned int bootopt = 0; /* Server boot option flags */
89 char *debugmode = ""; /* -"- -"- -"- */
92 static char *dpath = DPATH;
94 time_t nextconnect = 1; /* time for next try_connections call */
95 time_t nextping = 1; /* same as above for check_pings() */
96 time_t nextdnscheck = 0; /* next time to poll dns to force timeouts */
97 time_t nextexpire = 1; /* next expire run on the dns cache */
99 time_t now; /* Updated every time we leave select(),
100 and used everywhere else */
105 RETSIGTYPE s_monitor(HANDLER_ARG(int UNUSED(sig)))
109 struct sigaction act;
115 act.sa_handler = s_rehash;
117 sigemptyset(&act.sa_mask);
118 sigaddset(&act.sa_mask, SIGUSR1);
119 sigaction(SIGUSR1, &act, NULL);
121 signal(SIGUSR1, s_monitor);
127 RETSIGTYPE s_die(HANDLER_ARG(int UNUSED(sig)))
130 syslog(LOG_CRIT, "Server Killed By SIGTERM");
132 flush_connections(me.fd);
136 static RETSIGTYPE s_rehash(HANDLER_ARG(int UNUSED(sig)))
139 struct sigaction act;
143 act.sa_handler = s_rehash;
145 sigemptyset(&act.sa_mask);
146 sigaddset(&act.sa_mask, SIGHUP);
147 sigaction(SIGHUP, &act, NULL);
149 signal(SIGHUP, s_rehash); /* sysV -argv */
154 void restart(char *mesg)
156 void restart(char *UNUSED(mesg))
160 syslog(LOG_WARNING, "Restarting Server because: %s", mesg);
165 RETSIGTYPE s_restart(HANDLER_ARG(int UNUSED(sig)))
170 void server_reboot(void)
174 sendto_ops("Aieeeee!!! Restarting server...");
175 Debug((DEBUG_NOTICE, "Restarting server..."));
176 flush_connections(me.fd);
178 * fd 0 must be 'preserved' if either the -d or -i options have
179 * been passed to us before restarting.
184 for (i = 3; i < MAXCONNECTIONS; i++)
186 if (!(bootopt & (BOOT_TTY | BOOT_DEBUG)))
189 if ((bootopt & BOOT_CONSOLE) || isatty(0))
191 if (!(bootopt & BOOT_INETD))
192 execv(SPATH, myargv);
194 /* Have to reopen since it has been closed above */
196 openlog(myargv[0], LOG_PID | LOG_NDELAY, LOG_FACILITY);
197 syslog(LOG_CRIT, "execv(%s,%s) failed: %m\n", SPATH, myargv[0]);
200 Debug((DEBUG_FATAL, "Couldn't restart server \"%s\": %s",
201 SPATH, strerror(errno)));
208 * Scan through configuration and try new connections.
210 * Returns the calendar time when the next call to this
211 * function should be made latest. (No harm done if this
212 * is called earlier or later...)
214 static time_t try_connections(void)
216 Reg1 aConfItem *aconf;
219 int connecting, confrq;
222 aConfItem *cconf, *con_conf = NULL;
223 unsigned int con_class = 0;
226 Debug((DEBUG_NOTICE, "Connection check at : %s", myctime(now)));
227 for (aconf = conf; aconf; aconf = aconf->next)
229 /* Also when already connecting! (update holdtimes) --SRB */
230 if (!(aconf->status & CONF_CONNECT_SERVER) || aconf->port == 0)
232 cltmp = aconf->confClass;
234 * Skip this entry if the use of it is still on hold until
235 * future. Otherwise handle this entry (and set it on hold
236 * until next time). Will reset only hold times, if already
237 * made one successfull connection... [this algorithm is
238 * a bit fuzzy... -- msa >;) ]
241 if ((aconf->hold > now))
243 if ((next > aconf->hold) || (next == 0))
248 confrq = get_con_freq(cltmp);
249 aconf->hold = now + confrq;
251 * Found a CONNECT config with port specified, scan clients
252 * and see if this server is already connected?
254 cptr = FindServer(aconf->name);
256 if (!cptr && (Links(cltmp) < MaxLinks(cltmp)) &&
257 (!connecting || (ConClass(cltmp) > con_class)))
259 /* Check connect rules to see if we're allowed to try */
260 for (cconf = conf; cconf; cconf = cconf->next)
261 if ((cconf->status & CONF_CRULE) &&
262 (match(cconf->host, aconf->name) == 0))
263 if (crule_eval(cconf->passwd))
267 con_class = ConClass(cltmp);
269 /* We connect only one at time... */
273 if ((next > aconf->hold) || (next == 0))
278 if (con_conf->next) /* are we already last? */
280 /* Put the current one at the end and make sure we try all connections */
281 for (pconf = &conf; (aconf = *pconf); pconf = &(aconf->next))
282 if (aconf == con_conf)
283 *pconf = aconf->next;
284 (*pconf = con_conf)->next = 0;
286 if (connect_server(con_conf, (aClient *)NULL, (struct hostent *)NULL) == 0)
287 sendto_ops("Connection to %s activated.", con_conf->name);
289 Debug((DEBUG_NOTICE, "Next connection check : %s", myctime(next)));
293 static time_t check_pings(void)
296 int ping = 0, i, rflag = 0;
297 time_t oldest = 0, timeout;
299 for (i = 0; i <= highest_fd; i++)
301 if (!(cptr = loc_clients[i]) || IsMe(cptr) || IsLog(cptr) || IsPing(cptr))
305 * Note: No need to notify opers here.
306 * It's already done when "FLAGS_DEADSOCKET" is set.
310 exit_client(cptr, cptr, &me, LastDeadComment(cptr));
314 #if defined(R_LINES) && defined(R_LINES_OFTEN)
315 rflag = IsUser(cptr) ? find_restrict(cptr) : 0;
317 ping = IsRegistered(cptr) ? get_client_ping(cptr) : CONNECTTIMEOUT;
318 Debug((DEBUG_DEBUG, "c(%s)=%d p %d r %d a %d",
319 cptr->name, cptr->status, ping, rflag, (int)(now - cptr->lasttime)));
321 * Ok, so goto's are ugly and can be avoided here but this code
322 * is already indented enough so I think its justified. -avalon
324 if (!rflag && IsRegistered(cptr) && (ping >= now - cptr->lasttime))
327 * If the server hasnt talked to us in 2*ping seconds
328 * and it has a ping time, then close its connection.
329 * If the client is a user and a KILL line was found
330 * to be active, close this connection too.
333 ((now - cptr->lasttime) >= (2 * ping) &&
334 (cptr->flags & FLAGS_PINGSENT)) ||
335 (!IsRegistered(cptr) && !IsHandshake(cptr) &&
336 (now - cptr->firsttime) >= ping))
338 if (!IsRegistered(cptr) && (DoingDNS(cptr) || DoingAuth(cptr)))
340 Debug((DEBUG_NOTICE, "%s/%s timeout %s", DoingDNS(cptr) ? "DNS" : "",
341 DoingAuth(cptr) ? "AUTH" : "", get_client_name(cptr, FALSE)));
342 if (cptr->authfd >= 0)
347 *cptr->buffer = '\0';
349 del_queries((char *)cptr);
353 cptr->firsttime = now;
354 cptr->lasttime = now;
357 if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr))
359 sendto_ops("No response from %s, closing link", cptr->name);
360 exit_client(cptr, cptr, &me, "Ping timeout");
364 * This is used for KILL lines with time restrictions
365 * on them - send a messgae to the user being killed first.
367 #if defined(R_LINES) && defined(R_LINES_OFTEN)
368 else if (IsUser(cptr) && rflag)
370 sendto_ops("Restricting %s, closing link.",
371 get_client_name(cptr, FALSE));
372 exit_client(cptr, cptr, &me, "R-lined");
377 if (!IsRegistered(cptr) && *cptr->name && *cptr->user->username)
380 ":%s %d %s :Your client may not be compatible with this server.",
381 me.name, ERR_BADPING, cptr->name);
383 ":%s %d %s :Compatible clients are available at "
384 "ftp://ftp.undernet.org/pub/irc/clients",
385 me.name, ERR_BADPING, cptr->name);
387 exit_client_msg(cptr, cptr, &me, "Ping timeout for %s",
388 IsServer(cptr) ? cptr->name : get_client_name(cptr, FALSE));
392 else if (IsRegistered(cptr) && (cptr->flags & FLAGS_PINGSENT) == 0)
395 * If we havent PINGed the connection and we havent
396 * heard from it in a while, PING it to make sure
399 cptr->flags |= FLAGS_PINGSENT;
400 /* not nice but does the job */
401 cptr->lasttime = now - ping;
403 sendto_one(cptr, "PING :%s", me.name);
405 sendto_one(cptr, ":%s PING :%s", me.name, me.name);
408 timeout = cptr->lasttime + ping;
409 while (timeout <= now)
411 if (timeout < oldest || !oldest)
414 if (!oldest || oldest < now)
415 oldest = now + PINGFREQUENCY;
417 "Next check_ping() call at: %s, %d " TIME_T_FMT " " TIME_T_FMT,
418 myctime(oldest), ping, oldest, now));
426 * This is called when the commandline is not acceptable.
427 * Give error message and exit without starting anything.
429 static int bad_command(void)
431 printf("Usage: ircd %s[-h servername] [-p portnumber] [-x loglevel] [-t]\n",
432 #ifdef CMDLINE_CONFIG
438 printf("Server not started\n\n");
442 static void setup_signals(void)
445 struct sigaction act;
447 act.sa_handler = SIG_IGN;
449 sigemptyset(&act.sa_mask);
450 sigaddset(&act.sa_mask, SIGPIPE);
451 sigaddset(&act.sa_mask, SIGALRM);
453 sigaddset(&act.sa_mask, SIGWINCH);
454 sigaction(SIGWINCH, &act, NULL);
456 sigaction(SIGPIPE, &act, NULL);
457 act.sa_handler = dummy;
458 sigaction(SIGALRM, &act, NULL);
459 act.sa_handler = s_rehash;
460 sigemptyset(&act.sa_mask);
461 sigaddset(&act.sa_mask, SIGHUP);
462 sigaction(SIGHUP, &act, NULL);
463 act.sa_handler = s_restart;
464 sigaddset(&act.sa_mask, SIGINT);
465 sigaction(SIGINT, &act, NULL);
466 act.sa_handler = s_die;
467 sigaddset(&act.sa_mask, SIGTERM);
468 sigaction(SIGTERM, &act, NULL);
471 #ifndef HAVE_RELIABLE_SIGNALS
472 signal(SIGPIPE, dummy);
474 signal(SIGWINCH, dummy);
478 signal(SIGWINCH, SIG_IGN);
480 signal(SIGPIPE, SIG_IGN);
482 signal(SIGALRM, dummy);
483 signal(SIGHUP, s_rehash);
484 signal(SIGTERM, s_die);
485 signal(SIGINT, s_restart);
488 #ifdef HAVE_RESTARTABLE_SYSCALLS
490 * At least on Apollo sr10.1 it seems continuing system calls
491 * after signal is the default. The following 'siginterrupt'
492 * should change that default to interrupting calls.
494 siginterrupt(SIGALRM, 1);
501 * If the -t option is not given on the command line when the server is
502 * started, all debugging output is sent to the file set by LPATH in config.h
503 * Here we just open that file and make sure it is opened to fd 2 so that
504 * any fprintf's to stderr also goto the logfile. If the debuglevel is not
505 * set from the command line by -x, use /dev/null as the dummy logfile as long
506 * as DEBUGMODE has been defined, else dont waste the fd.
508 static void open_debugfile(void)
516 cptr = make_client(NULL, STAT_LOG);
518 cptr->port = debuglevel;
521 loc_clients[2] = cptr;
522 strcpy(cptr->sockhost, me.name);
524 printf("isatty = %d ttyname = %#x\n", isatty(2), (unsigned int)ttyname(2));
525 if (!(bootopt & BOOT_TTY)) /* leave debugging output on fd 2 */
527 if ((fd = creat(LOGFILE, 0600)) < 0)
528 if ((fd = open("/dev/null", O_WRONLY)) < 0)
535 strncpy(cptr->name, LOGFILE, sizeof(cptr->name));
536 cptr->name[sizeof(cptr->name) - 1] = 0;
538 else if (isatty(2) && ttyname(2))
540 strncpy(cptr->name, ttyname(2), sizeof(cptr->name));
541 cptr->name[sizeof(cptr->name) - 1] = 0;
544 strcpy(cptr->name, "FD2-Pipe");
545 Debug((DEBUG_FATAL, "Debug: File <%s> Level: %u at %s",
546 cptr->name, cptr->port, myctime(now)));
549 loc_clients[2] = NULL;
554 int main(int argc, char *argv[])
556 unsigned short int portarg = 0;
560 #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_CORE)
561 struct rlimit corelim;
568 monstartup(0, etext);
570 signal(SIGUSR1, s_monitor);
576 fprintf(stderr, "Fail: Cannot chdir(%s): %s\n", DPATH, strerror(errno));
582 fprintf(stderr, "Fail: Cannot chroot(%s): %s\n", DPATH, strerror(errno));
586 #endif /*CHROOTDIR */
589 umask(077); /* better safe than sorry --SRB */
590 memset(&me, 0, sizeof(me));
592 memset(&vserv, 0, sizeof(vserv));
598 #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_CORE)
599 if (getrlimit(RLIMIT_CORE, &corelim))
601 fprintf(stderr, "Read of rlimit core size failed: %s\n", strerror(errno));
602 corelim.rlim_max = RLIM_INFINITY; /* Try to recover */
604 corelim.rlim_cur = corelim.rlim_max;
605 if (setrlimit(RLIMIT_CORE, &corelim))
606 fprintf(stderr, "Setting rlimit core size failed: %s\n", strerror(errno));
610 * All command line parameters have the syntax "-fstring"
611 * or "-f string" (e.g. the space is optional). String may
612 * be empty. Flag characters cannot be concatenated (like
613 * "-fxyz"), it would conflict with the form "-fstring".
615 while (--argc > 0 && (*++argv)[0] == '-')
617 char *p = argv[0] + 1;
620 if (flag == '\0' || *p == '\0')
622 if (argc > 1 && argv[1][0] != '-')
634 bootopt |= BOOT_AUTODIE;
637 bootopt |= BOOT_CONSOLE;
640 bootopt |= BOOT_QUICK;
647 #ifdef CMDLINE_CONFIG
655 strncpy(me.name, p, sizeof(me.name));
656 me.name[sizeof(me.name) - 1] = 0;
659 bootopt |= BOOT_INETD | BOOT_AUTODIE;
662 if ((portarg = atoi(p)) > 0)
671 printf("ircd %s\n", version);
677 if (!(hep = gethostbyname(p)))
679 fprintf(stderr, "%s: Error creating virtual host \"%s\": %d",
680 argv[0], p, h_errno);
683 if (hep->h_addrtype == AF_INET && hep->h_addr_list[0] &&
684 !hep->h_addr_list[1])
686 memcpy(&vserv.sin_addr, hep->h_addr_list[0], sizeof(struct in_addr));
687 vserv.sin_family = AF_INET;
691 fprintf(stderr, "%s: Error creating virtual host \"%s\": "
692 "Use -w <IP-number of interface>\n", argv[0], p);
702 debuglevel = atoi(p);
703 debugmode = *p ? p : "0";
704 bootopt |= BOOT_DEBUG;
707 fprintf(stderr, "%s: DEBUGMODE must be defined for -x y\n", myargv[0]);
718 fprintf(stderr, "Fail: Cannot chdir(%s): %s\n", dpath, strerror(errno));
723 if ((uid != euid) && !euid)
726 "ERROR: do not run ircd setuid root. Make it setuid a normal user.\n");
731 #if !defined(CHROOTDIR) || (defined(IRC_UID) && defined(IRC_GID))
736 setuid((uid_t) euid);
740 if ((int)getuid() == 0)
742 #if defined(IRC_UID) && defined(IRC_GID)
744 /* run as a specified user */
745 fprintf(stderr, "WARNING: running ircd with uid = %d\n", IRC_UID);
746 fprintf(stderr, " changing to gid %d.\n", IRC_GID);
750 /* check for setuid root as usual */
752 "ERROR: do not run ircd setuid root. Make it setuid a normal user.\n");
756 #endif /*CHROOTDIR/UID/GID */
759 return bad_command(); /* This should exit out */
769 if (access(path, X_OK) == 0)
773 if (access(path, R_OK) == 0)
777 if (access(path, R_OK) == 0)
781 if (access(path, R_OK) == 0)
788 if (access(path, W_OK) == 0)
797 fprintf(stderr, "Check on %cPATH (%s) failed: %s\n",
798 c, path, strerror(errno));
800 "Please create file and/or rerun `make config' and recompile to correct this.\n");
803 "Keep in mind that all paths are relative to CHROOTDIR.\n");
823 me.flags = FLAGS_LISTEN;
824 if ((bootopt & BOOT_INETD))
827 loc_clients[0] = &me;
828 me.flags = FLAGS_LISTEN;
834 openlog(myargv[0], LOG_PID | LOG_NDELAY, LOG_FACILITY);
836 if (initconf(bootopt) == -1)
838 Debug((DEBUG_FATAL, "Failed in reading configuration file %s", configfile));
839 printf("Couldn't open configuration file %s\n", configfile);
844 if (!(bootopt & BOOT_INETD))
846 static char star[] = "*";
849 if ((aconf = find_me()) && portarg == 0 && aconf->port != 0)
850 portnum = aconf->port;
851 Debug((DEBUG_ERROR, "Port = %u", portnum));
852 if (inetport(&me, star, portnum))
855 else if (inetport(&me, "*", 0))
859 rmotd = read_motd(RPATH);
860 motd = read_motd(MPATH);
871 /* Abuse own link timestamp as start timestamp: */
872 me.serv->timestamp = TStime();
873 me.serv->prot = atoi(MAJOR_PROTOCOL);
875 me.serv->down = NULL;
877 SetYXXCapacity(&me, MAXCLIENTS);
879 me.lasttime = me.since = me.firsttime = now;
887 Debug((DEBUG_NOTICE, "Server ready..."));
889 syslog(LOG_NOTICE, "Server Ready");
895 * We only want to connect if a connection is due,
896 * not every time through. Note, if there are no
897 * active C lines, this call to Tryconnections is
898 * made once only; it will return 0. - avalon
900 if (nextconnect && now >= nextconnect)
901 nextconnect = try_connections();
903 * DNS checks. One to timeout queries, one for cache expiries.
905 if (now >= nextdnscheck)
906 nextdnscheck = timeout_query_list();
907 if (now >= nextexpire)
908 nextexpire = expire_cache();
910 * Take the smaller of the two 'timed' event times as
911 * the time of next event (stops us being late :) - avalon
912 * WARNING - nextconnect can return 0!
915 delay = MIN(nextping, nextconnect);
918 delay = MIN(nextdnscheck, delay);
919 delay = MIN(nextexpire, delay);
922 * Adjust delay to something reasonable [ad hoc values]
923 * (one might think something more clever here... --msa)
924 * We don't really need to check that often and as long
925 * as we don't delay too long, everything should be ok.
926 * waiting too long can cause things to timeout...
927 * i.e. PINGS -> a disconnection :(
933 delay = MIN(delay, TIMESEC);
936 Debug((DEBUG_DEBUG, "Got message(s)"));
939 * ...perhaps should not do these loops every time,
940 * but only if there is some chance of something
941 * happening (but, note that conf->hold times may
942 * be changed elsewhere--so precomputed next event
943 * time might be too far away... (similarly with
947 nextping = check_pings();