ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/ircd.c
Revision: 1011
Committed: Fri Sep 18 10:14:09 2009 UTC (14 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 17593 byte(s)
Log Message:
- move list manipulation routines from tools.c to list.c
- mem_frob() goes to memory.c
- sort out redundant/unneeded header includes

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * ircd.c: Starts up and runs the ircd.
4 *
5 * Copyright (C) 2002 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include "s_user.h"
27 #include "list.h"
28 #include "ircd.h"
29 #include "channel.h"
30 #include "channel_mode.h"
31 #include "client.h"
32 #include "common.h"
33 #include "event.h"
34 #include "fdlist.h"
35 #include "hash.h"
36 #include "irc_string.h"
37 #include "sprintf_irc.h"
38 #include "ircd_signal.h"
39 #include "s_gline.h"
40 #include "motd.h"
41 #include "ircd_handler.h"
42 #include "msg.h" /* msgtab */
43 #include "hostmask.h"
44 #include "numeric.h"
45 #include "packet.h"
46 #include "parse.h"
47 #include "irc_res.h"
48 #include "restart.h"
49 #include "rng_mt.h"
50 #include "s_auth.h"
51 #include "s_bsd.h"
52 #include "s_conf.h"
53 #include "s_log.h"
54 #include "s_misc.h"
55 #include "s_serv.h" /* try_connections */
56 #include "send.h"
57 #include "whowas.h"
58 #include "modules.h"
59 #include "memory.h"
60 #include "hook.h"
61 #include "ircd_getopt.h"
62 #include "balloc.h"
63 #include "motd.h"
64 #include "supported.h"
65 #include "watch.h"
66
67 /* Try and find the correct name to use with getrlimit() for setting the max.
68 * number of files allowed to be open by this process.
69 */
70
71 /* /quote set variables */
72 struct SetOptions GlobalSetOptions;
73
74 /* configuration set from ircd.conf */
75 struct config_file_entry ConfigFileEntry;
76 /* server info set from ircd.conf */
77 struct server_info ServerInfo;
78 /* admin info set from ircd.conf */
79 struct admin_info AdminInfo = { NULL, NULL, NULL };
80 struct Counter Count = { 0, 0, 0, 0, 0, 0, 0, 0 };
81 struct ServerState_t server_state = { 0 };
82 struct logging_entry ConfigLoggingEntry = { 1, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0} };
83 struct ServerStatistics ServerStats;
84 struct timeval SystemTime;
85 struct Client me; /* That's me */
86 struct LocalUser meLocalUser; /* That's also part of me */
87
88 const char *logFileName = LPATH;
89 const char *pidFileName = PPATH;
90
91 char **myargv;
92 char ircd_platform[PLATFORMLEN];
93
94 int dorehash = 0;
95 int doremotd = 0;
96 time_t nextconnect = 1; /* time for next try_connections call */
97
98 /* Set to zero because it should be initialized later using
99 * initialize_server_capabs
100 */
101 int default_server_capabs = 0;
102
103 #ifdef HAVE_LIBCRYPTO
104 int bio_spare_fd = -1;
105 #endif
106
107 int splitmode;
108 int splitchecking;
109 int split_users;
110 unsigned int split_servers;
111
112 /* Do klines the same way hybrid-6 did them, i.e. at the
113 * top of the next io_loop instead of in the same loop as
114 * the klines are being applied.
115 *
116 * This should fix strange CPU starvation as very indirectly reported.
117 * (Why do you people not email bug reports? WHY? WHY?)
118 *
119 * - Dianora
120 */
121
122 int rehashed_klines = 0;
123
124
125 /*
126 * print_startup - print startup information
127 */
128 static void
129 print_startup(int pid)
130 {
131 printf("ircd: version %s\n", ircd_version);
132 printf("ircd: pid %d\n", pid);
133 printf("ircd: running in %s mode from %s\n", !server_state.foreground ? "background"
134 : "foreground", ConfigFileEntry.dpath);
135 }
136
137 static void
138 make_daemon(void)
139 {
140 int pid;
141
142 if ((pid = fork()) < 0)
143 {
144 perror("fork");
145 exit(EXIT_FAILURE);
146 }
147 else if (pid > 0)
148 {
149 print_startup(pid);
150 exit(EXIT_SUCCESS);
151 }
152
153 setsid();
154 }
155
156 static int printVersion = 0;
157
158 struct lgetopt myopts[] = {
159 {"dlinefile", &ConfigFileEntry.dlinefile,
160 STRING, "File to use for dline.conf"},
161 {"configfile", &ConfigFileEntry.configfile,
162 STRING, "File to use for ircd.conf"},
163 {"klinefile", &ConfigFileEntry.klinefile,
164 STRING, "File to use for kline.conf"},
165 {"xlinefile", &ConfigFileEntry.xlinefile,
166 STRING, "File to use for xline.conf"},
167 {"logfile", &logFileName,
168 STRING, "File to use for ircd.log"},
169 {"pidfile", &pidFileName,
170 STRING, "File to use for process ID"},
171 {"foreground", &server_state.foreground,
172 YESNO, "Run in foreground (don't detach)"},
173 {"version", &printVersion,
174 YESNO, "Print version and exit"},
175 {"help", NULL, USAGE, "Print this text"},
176 {NULL, NULL, STRING, NULL},
177 };
178
179 void
180 set_time(void)
181 {
182 static char to_send[200];
183 struct timeval newtime;
184 newtime.tv_sec = 0;
185 newtime.tv_usec = 0;
186
187 if (gettimeofday(&newtime, NULL) == -1)
188 {
189 ilog(L_ERROR, "Clock Failure (%s), TS can be corrupted",
190 strerror(errno));
191 sendto_realops_flags(UMODE_ALL, L_ALL,
192 "Clock Failure (%s), TS can be corrupted",
193 strerror(errno));
194 restart("Clock Failure");
195 }
196
197 if (newtime.tv_sec < CurrentTime)
198 {
199 ircsprintf(to_send, "System clock is running backwards - (%lu < %lu)",
200 (unsigned long)newtime.tv_sec, (unsigned long)CurrentTime);
201 report_error(L_ALL, to_send, me.name, 0);
202 set_back_events(CurrentTime - newtime.tv_sec);
203 }
204
205 SystemTime.tv_sec = newtime.tv_sec;
206 SystemTime.tv_usec = newtime.tv_usec;
207 }
208
209 static void
210 io_loop(void)
211 {
212 while (1 == 1)
213 {
214 /*
215 * Maybe we want a flags word?
216 * ie. if (REHASHED_KLINES(global_flags))
217 * SET_REHASHED_KLINES(global_flags)
218 * CLEAR_REHASHED_KLINES(global_flags)
219 *
220 * - Dianora
221 */
222 if (rehashed_klines)
223 {
224 check_conf_klines();
225 rehashed_klines = 0;
226 }
227
228 if (listing_client_list.head)
229 {
230 dlink_node *ptr = NULL, *ptr_next = NULL;
231 DLINK_FOREACH_SAFE(ptr, ptr_next, listing_client_list.head)
232 {
233 struct Client *client_p = ptr->data;
234 assert(client_p->localClient->list_task);
235 safe_list_channels(client_p, client_p->localClient->list_task, 0);
236 }
237 }
238
239 /* Run pending events, then get the number of seconds to the next
240 * event
241 */
242 while (eventNextTime() <= CurrentTime)
243 eventRun();
244
245 comm_select();
246 exit_aborted_clients();
247 free_exited_clients();
248 send_queued_all();
249
250 /* Check to see whether we have to rehash the configuration .. */
251 if (dorehash)
252 {
253 rehash(1);
254 dorehash = 0;
255 }
256 if (doremotd)
257 {
258 read_message_file(&ConfigFileEntry.motd);
259 sendto_realops_flags(UMODE_ALL, L_ALL,
260 "Got signal SIGUSR1, reloading ircd motd file");
261 doremotd = 0;
262 }
263 }
264 }
265
266 /* initalialize_global_set_options()
267 *
268 * inputs - none
269 * output - none
270 * side effects - This sets all global set options needed
271 */
272 static void
273 initialize_global_set_options(void)
274 {
275 memset(&GlobalSetOptions, 0, sizeof(GlobalSetOptions));
276
277 GlobalSetOptions.autoconn = 1;
278 GlobalSetOptions.spam_time = MIN_JOIN_LEAVE_TIME;
279 GlobalSetOptions.spam_num = MAX_JOIN_LEAVE_COUNT;
280
281 if (ConfigFileEntry.default_floodcount)
282 GlobalSetOptions.floodcount = ConfigFileEntry.default_floodcount;
283 else
284 GlobalSetOptions.floodcount = 10;
285
286 /* XXX I have no idea what to try here - Dianora */
287 GlobalSetOptions.joinfloodcount = 16;
288 GlobalSetOptions.joinfloodtime = 8;
289
290 split_servers = ConfigChannel.default_split_server_count;
291 split_users = ConfigChannel.default_split_user_count;
292
293 if (split_users && split_servers && (ConfigChannel.no_create_on_split ||
294 ConfigChannel.no_join_on_split))
295 {
296 splitmode = 1;
297 splitchecking = 1;
298 }
299
300 GlobalSetOptions.ident_timeout = IDENT_TIMEOUT;
301 GlobalSetOptions.idletime = ConfigFileEntry.idletime;
302 /* End of global set options */
303 }
304
305 /* initialize_message_files()
306 *
307 * inputs - none
308 * output - none
309 * side effects - Set up all message files needed, motd etc.
310 */
311 static void
312 initialize_message_files(void)
313 {
314 init_message_file(USER_MOTD, MPATH, &ConfigFileEntry.motd);
315 init_message_file(OPER_MOTD, OPATH, &ConfigFileEntry.opermotd);
316 init_message_file(USER_LINKS, LIPATH, &ConfigFileEntry.linksfile);
317
318 read_message_file(&ConfigFileEntry.motd);
319 read_message_file(&ConfigFileEntry.opermotd);
320 read_message_file(&ConfigFileEntry.linksfile);
321
322 init_isupport();
323 }
324
325 /* initialize_server_capabs()
326 *
327 * inputs - none
328 * output - none
329 */
330 static void
331 initialize_server_capabs(void)
332 {
333 add_capability("QS", CAP_QS, 1);
334 add_capability("EOB", CAP_EOB, 1);
335
336 if (ServerInfo.sid != NULL) /* only enable TS6 if we have an SID */
337 add_capability("TS6", CAP_TS6, 0);
338
339 add_capability("ZIP", CAP_ZIP, 0);
340 add_capability("CLUSTER", CAP_CLUSTER, 1);
341 #ifdef HALFOPS
342 add_capability("HOPS", CAP_HOPS, 1);
343 #endif
344 }
345
346 /* write_pidfile()
347 *
348 * inputs - filename+path of pid file
349 * output - NONE
350 * side effects - write the pid of the ircd to filename
351 */
352 static void
353 write_pidfile(const char *filename)
354 {
355 FBFILE *fb;
356
357 if ((fb = fbopen(filename, "w")))
358 {
359 char buff[32];
360 unsigned int pid = (unsigned int)getpid();
361 size_t nbytes = ircsprintf(buff, "%u\n", pid);
362
363 if ((fbputs(buff, fb, nbytes) == -1))
364 ilog(L_ERROR, "Error writing %u to pid file %s (%s)",
365 pid, filename, strerror(errno));
366
367 fbclose(fb);
368 return;
369 }
370 else
371 {
372 ilog(L_ERROR, "Error opening pid file %s", filename);
373 }
374 }
375
376 /* check_pidfile()
377 *
378 * inputs - filename+path of pid file
379 * output - none
380 * side effects - reads pid from pidfile and checks if ircd is in process
381 * list. if it is, gracefully exits
382 * -kre
383 */
384 static void
385 check_pidfile(const char *filename)
386 {
387 FBFILE *fb;
388 char buff[32];
389 pid_t pidfromfile;
390
391 /* Don't do logging here, since we don't have log() initialised */
392 if ((fb = fbopen(filename, "r")))
393 {
394 if (fbgets(buff, 20, fb) == NULL)
395 {
396 /* log(L_ERROR, "Error reading from pid file %s (%s)", filename,
397 * strerror(errno));
398 */
399 }
400 else
401 {
402 pidfromfile = atoi(buff);
403
404 if (!kill(pidfromfile, 0))
405 {
406 /* log(L_ERROR, "Server is already running"); */
407 printf("ircd: daemon is already running\n");
408 exit(-1);
409 }
410 }
411
412 fbclose(fb);
413 }
414 else if (errno != ENOENT)
415 {
416 /* log(L_ERROR, "Error opening pid file %s", filename); */
417 }
418 }
419
420 /* setup_corefile()
421 *
422 * inputs - nothing
423 * output - nothing
424 * side effects - setups corefile to system limits.
425 * -kre
426 */
427 static void
428 setup_corefile(void)
429 {
430 #ifdef HAVE_SYS_RESOURCE_H
431 struct rlimit rlim; /* resource limits */
432
433 /* Set corefilesize to maximum */
434 if (!getrlimit(RLIMIT_CORE, &rlim))
435 {
436 rlim.rlim_cur = rlim.rlim_max;
437 setrlimit(RLIMIT_CORE, &rlim);
438 }
439 #endif
440 }
441
442 /* init_ssl()
443 *
444 * inputs - nothing
445 * output - nothing
446 * side effects - setups SSL context.
447 */
448 static void
449 init_ssl(void)
450 {
451 #ifdef HAVE_LIBCRYPTO
452 SSL_load_error_strings();
453 SSLeay_add_ssl_algorithms();
454
455 if ((ServerInfo.server_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL)
456 {
457 const char *s;
458
459 fprintf(stderr, "ERROR: Could not initialize the SSL context -- %s\n",
460 s = ERR_lib_error_string(ERR_get_error()));
461 ilog(L_CRIT, "ERROR: Could not initialize the SSL context -- %s\n", s);
462 }
463
464 SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_NO_SSLv2);
465 SSL_CTX_set_options(ServerInfo.server_ctx, SSL_OP_TLS_ROLLBACK_BUG|SSL_OP_ALL);
466 SSL_CTX_set_verify(ServerInfo.server_ctx, SSL_VERIFY_NONE, NULL);
467
468 bio_spare_fd = save_spare_fd("SSL private key validation");
469 #endif /* HAVE_LIBCRYPTO */
470 }
471
472 /* init_callbacks()
473 *
474 * inputs - nothing
475 * output - nothing
476 * side effects - setups standard hook points
477 */
478 static void
479 init_callbacks(void)
480 {
481 iorecv_cb = register_callback("iorecv", iorecv_default);
482 iosend_cb = register_callback("iosend", iosend_default);
483 iorecvctrl_cb = register_callback("iorecvctrl", NULL);
484 iosendctrl_cb = register_callback("iosendctrl", NULL);
485 }
486
487 int
488 main(int argc, char *argv[])
489 {
490 /* Check to see if the user is running
491 * us as root, which is a nono
492 */
493 if (geteuid() == 0)
494 {
495 fprintf(stderr, "Don't run ircd as root!!!\n");
496 return -1;
497 }
498
499 /* Setup corefile size immediately after boot -kre */
500 setup_corefile();
501
502 /* save server boot time right away, so getrusage works correctly */
503 set_time();
504
505 /* It ain't random, but it ought to be a little harder to guess */
506 init_genrand(SystemTime.tv_sec ^ (SystemTime.tv_usec | (getpid() << 20)));
507
508 memset(&me, 0, sizeof(me));
509 memset(&meLocalUser, 0, sizeof(meLocalUser));
510 me.localClient = &meLocalUser;
511 dlinkAdd(&me, &me.node, &global_client_list); /* Pointer to beginning
512 of Client list */
513
514 memset(&ServerInfo, 0, sizeof(ServerInfo));
515 memset(&ServerStats, 0, sizeof(ServerStats));
516
517 /* Initialise the channel capability usage counts... */
518 init_chcap_usage_counts();
519
520 ConfigFileEntry.dpath = DPATH;
521 ConfigFileEntry.configfile = CPATH; /* Server configuration file */
522 ConfigFileEntry.klinefile = KPATH; /* Server kline file */
523 ConfigFileEntry.xlinefile = XPATH; /* Server xline file */
524 ConfigFileEntry.rxlinefile = RXPATH; /* Server regex xline file */
525 ConfigFileEntry.rklinefile = RKPATH; /* Server regex kline file */
526 ConfigFileEntry.dlinefile = DLPATH; /* dline file */
527 ConfigFileEntry.glinefile = GPATH; /* gline log file */
528 ConfigFileEntry.cresvfile = CRESVPATH; /* channel resv file */
529 ConfigFileEntry.nresvfile = NRESVPATH; /* nick resv file */
530 myargv = argv;
531 umask(077); /* better safe than sorry --SRB */
532
533 parseargs(&argc, &argv, myopts);
534
535 if (printVersion)
536 {
537 printf("ircd: version %s\n", ircd_version);
538 exit(EXIT_SUCCESS);
539 }
540
541 if (chdir(ConfigFileEntry.dpath))
542 {
543 perror("chdir");
544 exit(EXIT_FAILURE);
545 }
546
547 init_ssl();
548
549 if (!server_state.foreground)
550 {
551 make_daemon();
552 close_standard_fds(); /* this needs to be before init_netio()! */
553 }
554 else
555 print_startup(getpid());
556
557 setup_signals();
558
559 get_ircd_platform(ircd_platform);
560
561 /* Init the event subsystem */
562 eventInit();
563 /* We need this to initialise the fd array before anything else */
564 fdlist_init();
565 init_log(logFileName);
566 check_can_use_v6();
567 init_comm(); /* This needs to be setup early ! -- adrian */
568 /* Check if there is pidfile and daemon already running */
569 check_pidfile(pidFileName);
570
571 #ifndef NOBALLOC
572 initBlockHeap();
573 #endif
574 init_dlink_nodes();
575 init_callbacks();
576 initialize_message_files();
577 dbuf_init();
578 init_hash();
579 init_ip_hash_table(); /* client host ip hash table */
580 init_host_hash(); /* Host-hashtable. */
581 clear_tree_parse();
582 init_client();
583 init_class();
584 init_whowas();
585 watch_init();
586 init_auth(); /* Initialise the auth code */
587 init_resolver(); /* Needs to be setup before the io loop */
588 read_conf_files(1); /* cold start init conf files */
589 me.id[0] = '\0';
590 init_uid();
591 initialize_server_capabs(); /* Set up default_server_capabs */
592 initialize_global_set_options();
593 init_channels();
594
595 if (ServerInfo.name == NULL)
596 {
597 ilog(L_CRIT, "No server name specified in serverinfo block.");
598 exit(EXIT_FAILURE);
599 }
600
601 strlcpy(me.name, ServerInfo.name, sizeof(me.name));
602
603 /* serverinfo{} description must exist. If not, error out.*/
604 if (ServerInfo.description == NULL)
605 {
606 ilog(L_CRIT,
607 "ERROR: No server description specified in serverinfo block.");
608 exit(EXIT_FAILURE);
609 }
610
611 strlcpy(me.info, ServerInfo.description, sizeof(me.info));
612
613 me.from = &me;
614 me.servptr = &me;
615
616 SetMe(&me);
617 make_server(&me);
618
619 me.lasttime = me.since = me.firsttime = CurrentTime;
620 hash_add_client(&me);
621
622 /* add ourselves to global_serv_list */
623 dlinkAdd(&me, make_dlink_node(), &global_serv_list);
624
625 check_class();
626
627 #ifndef STATIC_MODULES
628 if (chdir(MODPATH))
629 {
630 ilog (L_CRIT, "Could not load core modules. Terminating!");
631 exit(EXIT_FAILURE);
632 }
633
634 load_all_modules(1);
635 load_conf_modules();
636 load_core_modules(1);
637 /* Go back to DPATH after checking to see if we can chdir to MODPATH */
638 chdir(ConfigFileEntry.dpath);
639 #else
640 load_all_modules(1);
641 #endif
642 /*
643 * assemble_umode_buffer() has to be called after
644 * reading conf/loading modules.
645 */
646 assemble_umode_buffer();
647
648 write_pidfile(pidFileName);
649
650 ilog(L_NOTICE, "Server Ready");
651
652 eventAddIsh("cleanup_glines", cleanup_glines, NULL, CLEANUP_GLINES_TIME);
653 eventAddIsh("cleanup_tklines", cleanup_tklines, NULL, CLEANUP_TKLINES_TIME);
654
655 /* We want try_connections to be called as soon as possible now! -- adrian */
656 /* No, 'cause after a restart it would cause all sorts of nick collides */
657 eventAddIsh("try_connections", try_connections, NULL, STARTUP_CONNECTIONS_TIME);
658
659 eventAddIsh("collect_zipstats", collect_zipstats, NULL, ZIPSTATS_TIME);
660
661 /* Setup the timeout check. I'll shift it later :) -- adrian */
662 eventAddIsh("comm_checktimeouts", comm_checktimeouts, NULL, 1);
663
664 if (ConfigServerHide.links_delay > 0)
665 eventAddIsh("write_links_file", write_links_file, NULL, ConfigServerHide.links_delay);
666 else
667 ConfigServerHide.links_disabled = 1;
668
669 if (splitmode)
670 eventAddIsh("check_splitmode", check_splitmode, NULL, 60);
671
672 io_loop();
673 return 0;
674 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision