ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/ircd.c
Revision: 6393
Committed: Sun Aug 23 14:58:44 2015 UTC (10 years ago) by michael
Content type: text/x-csrc
File size: 15807 byte(s)
Log Message:
- Move userhost related code from hash.c to userhost.c

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2015 ircd-hybrid development team
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 2 of the License, or
9 * (at your option) 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 * USA
20 */
21
22 /*! \file ircd.c
23 * \brief Starts up and runs the ircd.
24 * \version $Id$
25 */
26
27 #include "stdinc.h"
28 #include "user.h"
29 #include "list.h"
30 #include "ircd.h"
31 #include "channel.h"
32 #include "client.h"
33 #include "event.h"
34 #include "fdlist.h"
35 #include "hash.h"
36 #include "id.h"
37 #include "irc_string.h"
38 #include "ircd_signal.h"
39 #include "motd.h"
40 #include "conf.h"
41 #include "hostmask.h"
42 #include "parse.h"
43 #include "res.h"
44 #include "restart.h"
45 #include "rng_mt.h"
46 #include "auth.h"
47 #include "s_bsd.h"
48 #include "log.h"
49 #include "server.h" /* try_connections */
50 #include "send.h"
51 #include "whowas.h"
52 #include "modules.h"
53 #include "memory.h"
54 #include "mempool.h"
55 #include "ircd_getopt.h"
56 #include "watch.h"
57 #include "conf_db.h"
58 #include "conf_class.h"
59 #include "ipcache.h"
60 #include "isupport.h"
61 #include "userhost.h"
62
63
64 #ifdef HAVE_LIBGEOIP
65 GeoIP *geoip_ctx;
66 #endif
67
68 struct SetOptions GlobalSetOptions; /* /quote set variables */
69 struct Counter Count;
70 struct ServerState_t server_state;
71 struct ServerStatistics ServerStats;
72 struct timeval SystemTime;
73 struct Connection meConnection; /* That's also part of me */
74 struct Client me = { .connection = &meConnection }; /* That's me */
75
76 char **myargv;
77 const char *logFileName = LPATH;
78 const char *pidFileName = PPATH;
79
80 unsigned int dorehash;
81 unsigned int doremotd;
82
83 static struct event event_cleanup_tklines =
84 {
85 .name = "cleanup_tklines",
86 .handler = cleanup_tklines,
87 .when = CLEANUP_TKLINES_TIME
88 };
89
90 static struct event event_try_connections =
91 {
92 .name = "try_connections",
93 .handler = try_connections,
94 .when = STARTUP_CONNECTIONS_TIME
95 };
96
97 static struct event event_comm_checktimeouts =
98 {
99 .name = "comm_checktimeouts",
100 .handler = comm_checktimeouts,
101 .when = 1
102 };
103
104 static struct event event_save_all_databases =
105 {
106 .name = "save_all_databases",
107 .handler = save_all_databases,
108 .when = DATABASE_UPDATE_TIMEOUT
109 };
110
111 struct event event_write_links_file =
112 {
113 .name = "write_links_file",
114 .handler = write_links_file,
115 };
116
117
118 /*
119 * print_startup - print startup information
120 */
121 static void
122 print_startup(int pid)
123 {
124 printf("ircd: version %s(%s)\n", ircd_version, serno);
125 printf("ircd: pid %d\n", pid);
126 printf("ircd: running in %s mode from %s\n", !server_state.foreground ? "background"
127 : "foreground", ConfigGeneral.dpath);
128 }
129
130 static void
131 make_daemon(void)
132 {
133 int pid;
134
135 if ((pid = fork()) < 0)
136 {
137 perror("fork");
138 exit(EXIT_FAILURE);
139 }
140 else if (pid > 0)
141 {
142 print_startup(pid);
143 exit(EXIT_SUCCESS);
144 }
145
146 setsid();
147 }
148
149 static int printVersion = 0;
150
151 static struct lgetopt myopts[] =
152 {
153 {"configfile", &ConfigGeneral.configfile,
154 STRING, "File to use for ircd.conf"},
155 {"klinefile", &ConfigGeneral.klinefile,
156 STRING, "File to use for kline database"},
157 {"dlinefile", &ConfigGeneral.dlinefile,
158 STRING, "File to use for dline database"},
159 {"xlinefile", &ConfigGeneral.xlinefile,
160 STRING, "File to use for xline database"},
161 {"resvfile", &ConfigGeneral.resvfile,
162 STRING, "File to use for resv database"},
163 {"logfile", &logFileName,
164 STRING, "File to use for ircd.log"},
165 {"pidfile", &pidFileName,
166 STRING, "File to use for process ID"},
167 {"foreground", &server_state.foreground,
168 YESNO, "Run in foreground (don't detach)"},
169 {"version", &printVersion,
170 YESNO, "Print version and exit"},
171 {"help", NULL, USAGE, "Print this text"},
172 {NULL, NULL, STRING, NULL},
173 };
174
175 void
176 set_time(void)
177 {
178 struct timeval newtime = { .tv_sec = 0, .tv_usec = 0 };
179
180 if (gettimeofday(&newtime, NULL) == -1)
181 {
182 ilog(LOG_TYPE_IRCD, "Clock Failure (%s), TS can be corrupted",
183 strerror(errno));
184 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
185 "Clock Failure (%s), TS can be corrupted",
186 strerror(errno));
187 server_die("Clock Failure", SERVER_SHUTDOWN);
188 }
189
190 if (newtime.tv_sec < CurrentTime)
191 {
192 ilog(LOG_TYPE_IRCD, "System clock is running backwards - (%lu < %lu)",
193 (unsigned long)newtime.tv_sec, (unsigned long)CurrentTime);
194 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
195 "System clock is running backwards - (%lu < %lu)",
196 (unsigned long)newtime.tv_sec,
197 (unsigned long)CurrentTime);
198 event_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)
209 {
210 if (listing_client_list.head)
211 {
212 dlink_node *node = NULL, *node_next = NULL;
213 DLINK_FOREACH_SAFE(node, node_next, listing_client_list.head)
214 safe_list_channels(node->data, 0);
215 }
216
217 /* Run pending events */
218 event_run();
219
220 comm_select();
221 exit_aborted_clients();
222 free_exited_clients();
223
224 /* Check to see whether we have to rehash the configuration .. */
225 if (dorehash)
226 {
227 conf_rehash(1);
228 dorehash = 0;
229 }
230
231 if (doremotd)
232 {
233 motd_recache();
234 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
235 "Got signal SIGUSR1, reloading motd file(s)");
236 doremotd = 0;
237 }
238 }
239 }
240
241 /* initalialize_global_set_options()
242 *
243 * inputs - none
244 * output - none
245 * side effects - This sets all global set options needed
246 */
247 static void
248 initialize_global_set_options(void)
249 {
250 GlobalSetOptions.maxclients = ConfigServerInfo.default_max_clients;
251 GlobalSetOptions.autoconn = 1;
252 GlobalSetOptions.spam_time = MIN_JOIN_LEAVE_TIME;
253 GlobalSetOptions.spam_num = MAX_JOIN_LEAVE_COUNT;
254 GlobalSetOptions.floodcount = ConfigGeneral.default_floodcount;
255 GlobalSetOptions.joinfloodcount = ConfigChannel.default_join_flood_count;
256 GlobalSetOptions.joinfloodtime = ConfigChannel.default_join_flood_time;
257 GlobalSetOptions.ident_timeout = IDENT_TIMEOUT;
258 }
259
260 /* initialize_server_capabs()
261 *
262 * inputs - none
263 * output - none
264 */
265 static void
266 initialize_server_capabs(void)
267 {
268 add_capability("QS", CAPAB_QS);
269 add_capability("EOB", CAPAB_EOB);
270 add_capability("CLUSTER", CAPAB_CLUSTER);
271 add_capability("SVS", CAPAB_SVS);
272 add_capability("CHW", CAPAB_CHW);
273 add_capability("HOPS", CAPAB_HOPS);
274 }
275
276 /* write_pidfile()
277 *
278 * inputs - filename+path of pid file
279 * output - NONE
280 * side effects - write the pid of the ircd to filename
281 */
282 static void
283 write_pidfile(const char *filename)
284 {
285 FILE *fb;
286
287 if ((fb = fopen(filename, "w")))
288 {
289 char buff[IRCD_BUFSIZE];
290 unsigned int pid = (unsigned int)getpid();
291
292 snprintf(buff, sizeof(buff), "%u\n", pid);
293
294 if (fputs(buff, fb) == -1)
295 ilog(LOG_TYPE_IRCD, "Error writing to pid file %s: %s",
296 filename, strerror(errno));
297
298 fclose(fb);
299 }
300 else
301 ilog(LOG_TYPE_IRCD, "Error opening pid file %s: %s",
302 filename, strerror(errno));
303 }
304
305 /* check_pidfile()
306 *
307 * inputs - filename+path of pid file
308 * output - none
309 * side effects - reads pid from pidfile and checks if ircd is in process
310 * list. if it is, gracefully exits
311 * -kre
312 */
313 static void
314 check_pidfile(const char *filename)
315 {
316 FILE *fb;
317 char buff[IRCD_BUFSIZE];
318 pid_t pidfromfile;
319
320 if ((fb = fopen(filename, "r")))
321 {
322 if (!fgets(buff, 20, fb))
323 ilog(LOG_TYPE_IRCD, "Error reading from pid file %s: %s",
324 filename, strerror(errno));
325 else
326 {
327 pidfromfile = atoi(buff);
328
329 if (!kill(pidfromfile, 0))
330 {
331 /* log(L_ERROR, "Server is already running"); */
332 printf("ircd: daemon is already running\n");
333 exit(-1);
334 }
335 }
336
337 fclose(fb);
338 }
339 else if (errno != ENOENT)
340 ilog(LOG_TYPE_IRCD, "Error opening pid file %s: %s",
341 filename, strerror(errno));
342 }
343
344 /* setup_corefile()
345 *
346 * inputs - nothing
347 * output - nothing
348 * side effects - setups corefile to system limits.
349 * -kre
350 */
351 static void
352 setup_corefile(void)
353 {
354 #ifdef HAVE_SYS_RESOURCE_H
355 struct rlimit rlim; /* resource limits */
356
357 /* Set corefilesize to maximum */
358 if (!getrlimit(RLIMIT_CORE, &rlim))
359 {
360 rlim.rlim_cur = rlim.rlim_max;
361 setrlimit(RLIMIT_CORE, &rlim);
362 }
363 #endif
364 }
365
366 #ifdef HAVE_LIBCRYPTO
367 static int
368 always_accept_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
369 {
370 return 1;
371 }
372 #endif
373
374 /* init_ssl()
375 *
376 * inputs - nothing
377 * output - nothing
378 * side effects - setups SSL context.
379 */
380 static void
381 ssl_init(void)
382 {
383 #ifdef HAVE_LIBCRYPTO
384 SSL_load_error_strings();
385 SSLeay_add_ssl_algorithms();
386
387 if (!(ConfigServerInfo.server_ctx = SSL_CTX_new(SSLv23_server_method())))
388 {
389 const char *s = ERR_lib_error_string(ERR_get_error());
390
391 fprintf(stderr, "ERROR: Could not initialize the SSL Server context -- %s\n", s);
392 ilog(LOG_TYPE_IRCD, "ERROR: Could not initialize the SSL Server context -- %s", s);
393 exit(EXIT_FAILURE);
394 return; /* Not reached */
395 }
396
397 SSL_CTX_set_options(ConfigServerInfo.server_ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TICKET);
398 SSL_CTX_set_options(ConfigServerInfo.server_ctx, SSL_OP_SINGLE_DH_USE|SSL_OP_CIPHER_SERVER_PREFERENCE);
399 SSL_CTX_set_verify(ConfigServerInfo.server_ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
400 always_accept_verify_cb);
401 SSL_CTX_set_session_cache_mode(ConfigServerInfo.server_ctx, SSL_SESS_CACHE_OFF);
402 SSL_CTX_set_cipher_list(ConfigServerInfo.server_ctx, "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL");
403
404 #if OPENSSL_VERSION_NUMBER >= 0x009080FFL && !defined(OPENSSL_NO_ECDH)
405 {
406 EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
407
408 if (key)
409 {
410 SSL_CTX_set_tmp_ecdh(ConfigServerInfo.server_ctx, key);
411 EC_KEY_free(key);
412 }
413 }
414
415 SSL_CTX_set_options(ConfigServerInfo.server_ctx, SSL_OP_SINGLE_ECDH_USE);
416 #endif
417
418 if (!(ConfigServerInfo.client_ctx = SSL_CTX_new(SSLv23_client_method())))
419 {
420 const char *s = ERR_lib_error_string(ERR_get_error());
421
422 fprintf(stderr, "ERROR: Could not initialize the SSL Client context -- %s\n", s);
423 ilog(LOG_TYPE_IRCD, "ERROR: Could not initialize the SSL Client context -- %s", s);
424 exit(EXIT_FAILURE);
425 return; /* Not reached */
426 }
427
428 SSL_CTX_set_options(ConfigServerInfo.client_ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TICKET);
429 SSL_CTX_set_options(ConfigServerInfo.client_ctx, SSL_OP_SINGLE_DH_USE);
430 SSL_CTX_set_verify(ConfigServerInfo.client_ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
431 always_accept_verify_cb);
432 SSL_CTX_set_session_cache_mode(ConfigServerInfo.client_ctx, SSL_SESS_CACHE_OFF);
433 #endif /* HAVE_LIBCRYPTO */
434 }
435
436 int
437 main(int argc, char *argv[])
438 {
439 /* Check to see if the user is running us as root, which is a nono */
440 if (!geteuid())
441 {
442 fprintf(stderr, "ERROR: This server won't run as root/superuser\n");
443 return -1;
444 }
445
446 /* Setup corefile size immediately after boot -kre */
447 setup_corefile();
448
449 /* Save server boot time right away, so getrusage works correctly */
450 set_time();
451
452 /* It's not random, but it ought to be a little harder to guess */
453 init_genrand(SystemTime.tv_sec ^ (SystemTime.tv_usec | (getpid() << 20)));
454
455 dlinkAdd(&me, &me.node, &global_client_list);
456
457 ConfigGeneral.dpath = DPATH;
458 ConfigGeneral.spath = SPATH;
459 ConfigGeneral.mpath = MPATH;
460 ConfigGeneral.configfile = CPATH; /* Server configuration file */
461 ConfigGeneral.klinefile = KPATH; /* Server kline file */
462 ConfigGeneral.xlinefile = XPATH; /* Server xline file */
463 ConfigGeneral.dlinefile = DLPATH; /* dline file */
464 ConfigGeneral.resvfile = RESVPATH; /* resv file */
465
466 myargv = argv;
467 umask(077); /* umask 077: u=rwx,g=,o= */
468
469 parseargs(&argc, &argv, myopts);
470
471 if (printVersion)
472 {
473 printf("ircd: version %s(%s)\n", ircd_version, serno);
474 exit(EXIT_SUCCESS);
475 }
476
477 if (chdir(ConfigGeneral.dpath))
478 {
479 perror("chdir");
480 exit(EXIT_FAILURE);
481 }
482
483 ssl_init();
484
485 if (!server_state.foreground)
486 {
487 make_daemon();
488 close_standard_fds(); /* this needs to be before init_netio()! */
489 }
490 else
491 print_startup(getpid());
492
493 setup_signals();
494
495 /* We need this to initialise the fd array before anything else */
496 fdlist_init();
497 log_set_file(LOG_TYPE_IRCD, 0, logFileName);
498
499 init_netio(); /* This needs to be setup early ! -- adrian */
500
501 /* Check if there is pidfile and daemon already running */
502 check_pidfile(pidFileName);
503
504 mp_pool_init();
505 init_dlink_nodes();
506 isupport_init();
507 dbuf_init();
508 hash_init();
509 userhost_init();
510 ipcache_init();
511 client_init();
512 class_init();
513 whowas_init();
514 watch_init();
515 auth_init(); /* Initialise the auth code */
516 init_resolver(); /* Needs to be setup before the io loop */
517 modules_init();
518 read_conf_files(1); /* cold start init conf files */
519 initialize_server_capabs(); /* Set up default_server_capabs */
520 initialize_global_set_options(); /* Has to be called after read_conf_files() */
521 channel_init();
522 read_links_file();
523 motd_init();
524 user_modes_init();
525 #ifdef HAVE_LIBGEOIP
526 geoip_ctx = GeoIP_new(GEOIP_MEMORY_CACHE);
527 #endif
528
529 if (EmptyString(ConfigServerInfo.name))
530 {
531 ilog(LOG_TYPE_IRCD, "ERROR: No server name specified in serverinfo block.");
532 exit(EXIT_FAILURE);
533 }
534
535 strlcpy(me.name, ConfigServerInfo.name, sizeof(me.name));
536
537 /* serverinfo{} description must exist. If not, error out.*/
538 if (EmptyString(ConfigServerInfo.description))
539 {
540 ilog(LOG_TYPE_IRCD, "ERROR: No server description specified in serverinfo block.");
541 exit(EXIT_FAILURE);
542 }
543
544 strlcpy(me.info, ConfigServerInfo.description, sizeof(me.info));
545
546 if (EmptyString(ConfigServerInfo.sid))
547 {
548 ilog(LOG_TYPE_IRCD, "Generating server ID");
549 generate_sid();
550 }
551 else
552 {
553 strlcpy(me.id, ConfigServerInfo.sid, sizeof(me.id));
554 }
555
556 me.from = &me;
557 me.servptr = &me;
558 me.connection->lasttime = CurrentTime;
559 me.connection->since = CurrentTime;
560 me.connection->firsttime = CurrentTime;
561
562 SetMe(&me);
563 make_server(&me);
564
565 hash_add_id(&me);
566 hash_add_client(&me);
567
568 dlinkAdd(&me, make_dlink_node(), &global_server_list);
569
570 init_uid();
571
572 load_kline_database();
573 load_dline_database();
574 load_xline_database();
575 load_resv_database();
576
577 load_all_modules(1);
578 load_conf_modules();
579 load_core_modules(1);
580
581 write_pidfile(pidFileName);
582
583 ilog(LOG_TYPE_IRCD, "Server Ready");
584
585 event_addish(&event_cleanup_tklines, NULL);
586
587 /* We want try_connections to be called as soon as possible now! -- adrian */
588 /* No, 'cause after a restart it would cause all sorts of nick collides */
589 event_addish(&event_try_connections, NULL);
590
591 /* Setup the timeout check. I'll shift it later :) -- adrian */
592 event_add(&event_comm_checktimeouts, NULL);
593
594 event_addish(&event_save_all_databases, NULL);
595
596 if (ConfigServerHide.links_delay > 0)
597 {
598 event_write_links_file.when = ConfigServerHide.links_delay;
599 event_addish(&event_write_links_file, NULL);
600 }
601 else
602 ConfigServerHide.links_disabled = 1;
603
604 io_loop();
605 return 0;
606 }

Properties

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