ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/ircd.c
Revision: 1236
Committed: Thu Sep 29 11:21:27 2011 UTC (13 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/ircd.c
File size: 17325 byte(s)
Log Message:
- Getting rid of rlimits.h. Relying on RLIMIT_NOFILE is
  more than enough nowadays

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

Properties

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