/*
- * ircd-ratbox: A slightly useful ircd.
+ * charybdis: A slightly useful ircd.
* ircd.c: Starts up and runs the ircd.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
- * Copyright (C) 2002-2005 ircd-ratbox development team
+ * Copyright (C) 2002-2008 ircd-ratbox development team
+ * Copyright (C) 2005-2008 charybdis development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
- * $Id: ircd.c 3380 2007-04-03 22:25:11Z jilles $
+ * $Id$
*/
#include "ratbox_lib.h"
#include "client.h"
#include "common.h"
#include "hash.h"
-#include "irc_string.h"
+#include "match.h"
#include "ircd_signal.h"
-#include "sprintf_irc.h"
-#include "s_gline.h"
#include "msg.h" /* msgtab */
#include "hostmask.h"
#include "numeric.h"
#include "patchlevel.h"
#include "serno.h"
#include "sslproc.h"
+#include "chmode.h"
+#include "privilege.h"
+#include "bandbi.h"
-/* /quote set variables */\r
+/* /quote set variables */
struct SetOptions GlobalSetOptions;
-\r
-/* configuration set from ircd.conf */\r
-struct config_file_entry ConfigFileEntry;\r
-/* server info set from ircd.conf */\r
-struct server_info ServerInfo;\r
-/* admin info set from ircd.conf */\r
+
+/* configuration set from ircd.conf */
+struct config_file_entry ConfigFileEntry;
+/* server info set from ircd.conf */
+struct server_info ServerInfo;
+/* admin info set from ircd.conf */
struct admin_info AdminInfo;
-struct Counter Count;\r
+struct Counter Count;
struct ServerStatistics ServerStats;
int maxconnections;
-struct timeval SystemTime;
-struct Client me; /* That's me */\r
+struct Client me; /* That's me */
struct LocalUser meLocalUser; /* That's also part of me */
-rb_dlink_list lclient_list = { NULL, NULL, 0 };\r
-rb_dlink_list global_client_list = { NULL, NULL, 0 };\r
-rb_dlink_list global_channel_list = { NULL, NULL, 0 };\r
-\r
-rb_dlink_list unknown_list; /* unknown clients ON this server only */\r
-rb_dlink_list serv_list; /* local servers to this server ONLY */\r
-rb_dlink_list global_serv_list; /* global servers on the network */\r
-rb_dlink_list local_oper_list; /* our opers, duplicated in lclient_list */\r
+rb_dlink_list global_client_list;
+
+/* unknown/client pointer lists */
+rb_dlink_list unknown_list; /* unknown clients ON this server only */
+rb_dlink_list lclient_list; /* local clients only ON this server */
+rb_dlink_list serv_list; /* local servers to this server ONLY */
+rb_dlink_list global_serv_list; /* global servers on the network */
+rb_dlink_list local_oper_list; /* our opers, duplicated in lclient_list */
rb_dlink_list oper_list; /* network opers */
-time_t startup_time;\r
-\r
-int default_server_capabs = CAP_MASK;\r
-\r
-int splitmode;\r
-int splitchecking;\r
-int split_users;\r
-int split_servers;\r
-int eob_count;\r
-\r
-unsigned long initialVMTop = 0; /* top of virtual memory at init */\r
-const char *logFileName = LPATH;\r
+const char *logFileName = LPATH;
const char *pidFileName = PPATH;
char **myargv;
-int dorehash = 0;\r
-int dorehashbans = 0;\r
-int doremotd = 0;\r
-int kline_queued = 0;\r
-int server_state_foreground = 0;\r
-int opers_see_all_users = 0;\r
-int ssl_ok = 0;\r
-int zlib_ok = 1;\r
-\r
-int testing_conf = 0;\r
-\r
-struct config_channel_entry ConfigChannel;\r
-rb_bh *channel_heap;\r
-rb_bh *ban_heap;\r
-rb_bh *topic_heap;\r
-rb_bh *member_heap;\r
-\r
-rb_bh *client_heap = NULL;\r
-rb_bh *lclient_heap = NULL;\r
-rb_bh *pclient_heap = NULL;\r
-\r
-char current_uid[IDLEN];\r
-\r
-/* patricia */\r
-rb_bh *prefix_heap;\r
-rb_bh *node_heap;\r
-rb_bh *patricia_heap;\r
-\r
-rb_bh *linebuf_heap;\r
-\r
-rb_bh *dnode_heap;
+int dorehash = 0;
+int dorehashbans = 0;
+int doremotd = 0;
+int kline_queued = 0;
+int server_state_foreground = 0;
+int opers_see_all_users = 0;
+int ssl_ok = 0;
+int zlib_ok = 1;
+
+int testing_conf = 0;
+time_t startup_time;
+
+int default_server_capabs;
+
+int splitmode;
+int splitchecking;
+int split_users;
+int split_servers;
+int eob_count;
+
+void
+ircd_shutdown(const char *reason)
+{
+ struct Client *target_p;
+ rb_dlink_node *ptr;
+
+ RB_DLINK_FOREACH(ptr, lclient_list.head)
+ {
+ target_p = ptr->data;
+
+ sendto_one(target_p, ":%s NOTICE %s :Server Terminating. %s",
+ me.name, target_p->name, reason);
+ }
+
+ RB_DLINK_FOREACH(ptr, serv_list.head)
+ {
+ target_p = ptr->data;
+
+ sendto_one(target_p, ":%s ERROR :Terminated by %s",
+ me.name, reason);
+ }
+
+ ilog(L_MAIN, "Server Terminating. %s", reason);
+ close_logfiles();
+
+ unlink(pidFileName);
+ exit(0);
+}
/*
* print_startup - print startup information
dup2(0, 2);
}
-static void
-ircd_log_cb(const char *str)
-{
- ilog(L_MAIN, "%s", str);
-}
-
-static void
-ircd_restart_cb(const char *str)
-{
- restart(str);
-}
-
-/*
- * Why EXIT_FAILURE here?
- * Because if ircd_die_cb() is called it's because of a fatal
- * error inside libcharybdis, and we don't know how to handle the
- * exception, so it is logical to return a FAILURE exit code here.
- * --nenolod
- */
-static void
-ircd_die_cb(const char *str)
-{
- if(str != NULL)\r
- {
- /* Try to get the message out to currently logged in operators. */
- sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Server panic! %s", str);
- inotice("server panic: %s", str);
- }
-
- unlink(pidFileName);
- exit(EXIT_FAILURE);
-}
-
/*
* init_sys
*
static void
init_sys(void)
{
-#if defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)\r
- struct rlimit limit;\r
-\r
- if(!getrlimit(RLIMIT_NOFILE, &limit))\r
- {\r
- maxconnections = limit.rlim_cur;\r
- if(maxconnections <= MAX_BUFFER)\r
- {\r
- fprintf(stderr, "ERROR: Shell FD limits are too low.\n");\r
- fprintf(stderr, "ERROR: ircd-ratbox reserves %d FDs, shell limits must be above this\n", MAX_BUFFER);\r
- exit(EXIT_FAILURE);\r
- }\r
- return;\r
- }\r
-#endif /* RLIMIT_FD_MAX */\r
+#if defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)
+ struct rlimit limit;
+
+ if(!getrlimit(RLIMIT_NOFILE, &limit))
+ {
+ maxconnections = limit.rlim_cur;
+ if(maxconnections <= MAX_BUFFER)
+ {
+ fprintf(stderr, "ERROR: Shell FD limits are too low.\n");
+ fprintf(stderr, "ERROR: charybdis reserves %d FDs, shell limits must be above this\n", MAX_BUFFER);
+ exit(EXIT_FAILURE);
+ }
+ return;
+ }
+#endif /* RLIMIT_FD_MAX */
maxconnections = MAXCONNECTIONS;
}
static int printVersion = 0;
struct lgetopt myopts[] = {
- {"dlinefile", &ConfigFileEntry.dlinefile,
- STRING, "File to use for dlines.conf"},
{"configfile", &ConfigFileEntry.configfile,
STRING, "File to use for ircd.conf"},
- {"klinefile", &ConfigFileEntry.klinefile,
- STRING, "File to use for kline.conf"},
- {"xlinefile", &ConfigFileEntry.xlinefile,
- STRING, "File to use for xline.conf"},
- {"resvfile", &ConfigFileEntry.resvfile,
- STRING, "File to use for resv.conf"},
{"logfile", &logFileName,
STRING, "File to use for ircd.log"},
{"pidfile", &pidFileName,
{
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"Got signal SIGUSR1, reloading ircd motd file");
- free_cachefile(user_motd);
- user_motd = cache_file(MPATH, "ircd.motd", 0);
+ cache_user_motd();
doremotd = 0;
}
}
memset(&GlobalSetOptions, 0, sizeof(GlobalSetOptions));
/* memset( &ConfigFileEntry, 0, sizeof(ConfigFileEntry)); */
- GlobalSetOptions.maxclients = ServerInfo.default_max_clients;\r
-\r
- if(GlobalSetOptions.maxclients > (maxconnections - MAX_BUFFER))\r
+ GlobalSetOptions.maxclients = ServerInfo.default_max_clients;
+
+ if(GlobalSetOptions.maxclients > (maxconnections - MAX_BUFFER) || (GlobalSetOptions.maxclients <= 0))
GlobalSetOptions.maxclients = maxconnections - MAX_BUFFER;
GlobalSetOptions.autoconn = 1;
splitchecking = 1;
}
- GlobalSetOptions.ident_timeout = IDENT_TIMEOUT;
+ if(ConfigFileEntry.default_ident_timeout)
+ GlobalSetOptions.ident_timeout = ConfigFileEntry.default_ident_timeout;
+ else
+ GlobalSetOptions.ident_timeout = IDENT_TIMEOUT;
- strlcpy(GlobalSetOptions.operstring,
+ rb_strlcpy(GlobalSetOptions.operstring,
ConfigFileEntry.default_operstring,
sizeof(GlobalSetOptions.operstring));
- strlcpy(GlobalSetOptions.adminstring,
+ rb_strlcpy(GlobalSetOptions.adminstring,
ConfigFileEntry.default_adminstring,
sizeof(GlobalSetOptions.adminstring));
#endif
}
+static void
+ircd_log_cb(const char *str)
+{
+ ilog(L_MAIN, "libratbox reports: %s", str);
+}
+
+static void
+ircd_restart_cb(const char *str)
+{
+ inotice("libratbox has called the restart callback: %s", str);
+ restart(str);
+}
+
+/*
+ * Why EXIT_FAILURE here?
+ * Because if ircd_die_cb() is called it's because of a fatal
+ * error inside libcharybdis, and we don't know how to handle the
+ * exception, so it is logical to return a FAILURE exit code here.
+ * --nenolod
+ */
+static void
+ircd_die_cb(const char *str)
+{
+ if(str != NULL)
+ {
+ /* Try to get the message out to currently logged in operators. */
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "libratbox has called the die callback..aborting: %s", str);
+ inotice("libratbox has called the die callback..aborting: %s", str);
+ }
+ else
+ inotice("libratbox has called the die callback..aborting");
+
+ unlink(pidFileName);
+ exit(EXIT_FAILURE);
+}
+
struct ev_entry *check_splitmode_ev = NULL;
+static int
+seed_with_urandom(void)
+{
+ unsigned int seed;
+ int fd;
+
+ fd = open("/dev/urandom", O_RDONLY);
+ if(fd >= 0)
+ {
+ if(read(fd, &seed, sizeof(seed)) == sizeof(seed))
+ {
+ close(fd);
+ srand(seed);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void
+seed_with_clock(void)
+{
+ const struct timeval *tv;
+ rb_set_time();
+ tv = rb_current_time_tv();
+ srand(tv->tv_sec ^ (tv->tv_usec | (getpid() << 20)));
+}
+
+static void
+seed_random(void *unused)
+{
+ unsigned int seed;
+ if(rb_get_random(&seed, sizeof(seed)) == -1)
+ {
+ if(!seed_with_urandom())
+ seed_with_clock();
+ return;
+ }
+ srand(seed);
+}
+
/*
* main
*
return -1;
}
+ init_sys();
+
+ ConfigFileEntry.dpath = DPATH;
+ ConfigFileEntry.configfile = CPATH; /* Server configuration file */
+ ConfigFileEntry.connect_timeout = 30; /* Default to 30 */
+
+ umask(077); /* better safe than sorry --SRB */
+
+ myargv = argv;
+ parseargs(&argc, &argv, myopts);
+
+ if(chdir(ConfigFileEntry.dpath))
+ {
+ fprintf(stderr, "Unable to chdir to %s: %s\n", ConfigFileEntry.dpath, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ rb_set_time();
+
/*
* Setup corefile size immediately after boot -kre
*/
setup_corefile();
- /* It ain't random, but it ought to be a little harder to guess */
- srand(SystemTime.tv_sec ^ (SystemTime.tv_usec | (getpid() << 20)));
memset(&me, 0, sizeof(me));
memset(&meLocalUser, 0, sizeof(meLocalUser));
me.localClient = &meLocalUser;
memset(&AdminInfo, 0, sizeof(AdminInfo));
memset(&ServerStats, 0, sizeof(struct ServerStatistics));
- /* Initialise the channel capability usage counts... */
- init_chcap_usage_counts();
-
- ConfigFileEntry.dpath = DPATH;
- ConfigFileEntry.configfile = CPATH; /* Server configuration file */
- ConfigFileEntry.klinefile = KPATH; /* Server kline file */
- ConfigFileEntry.dlinefile = DLPATH; /* dline file */
- ConfigFileEntry.xlinefile = XPATH;
- ConfigFileEntry.resvfile = RESVPATH;
- ConfigFileEntry.connect_timeout = 30; /* Default to 30 */
- myargv = argv;
- umask(077); /* better safe than sorry --SRB */
-
- parseargs(&argc, &argv, myopts);
-
if(printVersion)
{
- printf("ircd: version %s\n", ircd_version);
+ printf("ircd: version %s(%s)\n", ircd_version, serno);
+#ifdef CUSTOM_BRANDING
+ printf("ircd: based on %s-%s\n", PACKAGE_NAME, PACKAGE_VERSION);
+#endif
+ printf("ircd: %s\n", rb_lib_version());
exit(EXIT_SUCCESS);
}
- if(chdir(ConfigFileEntry.dpath))
- {
- fprintf(stderr, "Unable to chdir to %s: %s\n", ConfigFileEntry.dpath, strerror(errno));
- exit(EXIT_FAILURE);
- }
-
setup_signals();
-#ifdef __CYGWIN__
- server_state_foreground = 1;
-#endif
-
if (testing_conf)
server_state_foreground = 1;
if(!server_state_foreground)
make_daemon();
inotice("starting %s ...", ircd_version);
+ inotice("%s", rb_lib_version());
}
/* Init the event subsystem */
- init_sys();
rb_lib_init(ircd_log_cb, ircd_restart_cb, ircd_die_cb, !server_state_foreground, maxconnections, DNODE_HEAP_SIZE, FD_HEAP_SIZE);
rb_linebuf_init(LINEBUF_HEAP_SIZE);
+ if(ConfigFileEntry.use_egd && (ConfigFileEntry.egdpool_path != NULL))
+ {
+ rb_init_prng(ConfigFileEntry.egdpool_path, RB_PRNG_EGD);
+ } else
+ rb_init_prng(NULL, RB_PRNG_DEFAULT);
+
+ seed_random(NULL);
+
+ init_builtin_capabs();
+ default_server_capabs = CAP_MASK;
+
init_main_logfile();
newconf_init();
init_s_conf();
init_host_hash();
clear_hash_parse();
init_client();
- initUser();
init_hook();
init_channels();
initclass();
init_reject();
init_cache();
init_monitor();
- init_isupport();
+
+ construct_cflags_strings();
+
load_all_modules(1);
#ifndef STATIC_MODULES
load_core_modules(1);
#endif
init_auth(); /* Initialise the auth code */
init_resolver(); /* Needs to be setup before the io loop */
+ privilegeset_set_new("default", "", 0);
if (testing_conf)
fprintf(stderr, "\nBeginning config test\n");
read_conf_files(YES); /* cold start init conf files */
- rehash_bans(0);
#ifndef STATIC_MODULES
mod_add_path(MODULE_DIR);
mod_add_path(MODULE_DIR "/autoload");
#endif
+ init_isupport();
+
+ init_bandb();
init_ssld();
+ rehash_bans(0);
+
initialize_server_capabs(); /* Set up default_server_capabs */
initialize_global_set_options();
ierror("no server name specified in serverinfo block.");
return -1;
}
- strlcpy(me.name, ServerInfo.name, sizeof(me.name));
+ rb_strlcpy(me.name, ServerInfo.name, sizeof(me.name));
if(ServerInfo.sid[0] == '\0')
{
ierror("no server description specified in serverinfo block.");
return -3;
}
- strlcpy(me.info, ServerInfo.description, sizeof(me.info));
-
- if(ServerInfo.ssl_cert != NULL && ServerInfo.ssl_private_key != NULL)\r
- {\r
- /* just do the rb_setup_ssl_server to validate the config */\r
- if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params))\r
- {\r
- ilog(L_MAIN, "WARNING: Unable to setup SSL.");\r
- ssl_ok = 0;\r
- }\r
- else\r
- ssl_ok = 1;\r
+ rb_strlcpy(me.info, ServerInfo.description, sizeof(me.info));
+
+ if(ServerInfo.ssl_cert != NULL && ServerInfo.ssl_private_key != NULL)
+ {
+ /* just do the rb_setup_ssl_server to validate the config */
+ if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params))
+ {
+ ilog(L_MAIN, "WARNING: Unable to setup SSL.");
+ ssl_ok = 0;
+ }
+ else
+ ssl_ok = 1;
}
if (testing_conf)
ilog(L_MAIN, "Server Ready");
- rb_event_addish("cleanup_glines", cleanup_glines, NULL, CLEANUP_GLINES_TIME);
-
/* We want try_connections to be called as soon as possible now! -- adrian */
/* No, 'cause after a restart it would cause all sorts of nick collides */
/* um. by waiting even longer, that just means we have even *more*
* nick collisions. what a stupid idea. set an event for the IO loop --fl
*/
rb_event_addish("try_connections", try_connections, NULL, STARTUP_CONNECTIONS_TIME);
- rb_event_addonce("try_connections_startup", try_connections, NULL, 0);
-
- /* Setup the timeout check. I'll shift it later :) -- adrian */
- rb_event_addish("rb_checktimeouts", rb_checktimeouts, NULL, 1);
-
- rb_event_add("check_rehash", check_rehash, NULL, 1);
+ rb_event_addonce("try_connections_startup", try_connections, NULL, 2);
+ rb_event_add("check_rehash", check_rehash, NULL, 3);
+ rb_event_addish("reseed_srand", seed_random, NULL, 300); /* reseed every 10 minutes */
if(splitmode)
- check_splitmode_ev = rb_event_add("check_splitmode", check_splitmode, NULL, 2);
+ check_splitmode_ev = rb_event_add("check_splitmode", check_splitmode, NULL, 5);
print_startup(getpid());
- rb_lib_loop(250);
+ rb_lib_loop(0);
return 0;
}