* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
- * $Id: ircd.c 3047 2006-12-26 23:18:05Z jilles $
+ * $Id: ircd.c 3380 2007-04-03 22:25:11Z jilles $
*/
+#include "ratbox_lib.h"
#include "stdinc.h"
#include "setup.h"
#include "config.h"
-
-#include "tools.h"
#include "ircd.h"
#include "channel.h"
#include "class.h"
#include "client.h"
#include "common.h"
-#include "event.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 "res.h"
#include "restart.h"
#include "s_auth.h"
-#include "commio.h"
#include "s_conf.h"
-#include "s_log.h"
+#include "logger.h"
#include "s_serv.h" /* try_connections */
#include "s_user.h"
#include "s_stats.h"
#include "supported.h"
#include "whowas.h"
#include "modules.h"
-#include "memory.h"
#include "hook.h"
#include "ircd_getopt.h"
-#include "balloc.h"
#include "newconf.h"
-#include "patricia.h"
#include "reject.h"
#include "s_conf.h"
#include "s_newconf.h"
#include "cache.h"
#include "monitor.h"
-#include "libcharybdis.h"
#include "patchlevel.h"
#include "serno.h"
+#include "sslproc.h"
+#include "chmode.h"
-/*
- * Try and find the correct name to use with getrlimit() for setting the max.
- * number of files allowed to be open by this process.
- */
-int _charybdis_data_version = CHARYBDIS_DV;
+/* /quote set variables */
+struct SetOptions GlobalSetOptions;
-extern int ServerRunning, initialVMTop;
-extern struct LocalUser meLocalUser;
-extern char **myargv;
+/* 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;
-/*
- * get_vm_top - get the operating systems notion of the resident set size
- */
-static unsigned long
-get_vm_top(void)
-{
- /*
- * NOTE: sbrk is not part of the ANSI C library or the POSIX.1 standard
- * however it seems that everyone defines it. Calling sbrk with a 0
- * argument will return a pointer to the top of the process virtual
- * memory without changing the process size, so this call should be
- * reasonably safe (sbrk returns the new value for the top of memory).
- * This code relies on the notion that the address returned will be an
- * offset from 0 (NULL), so the result of sbrk is cast to a size_t and
- * returned. We really shouldn't be using it here but...
- */
- void *vptr = sbrk(0);
- return (unsigned long) vptr;
-}
+struct Counter Count;
+struct ServerStatistics ServerStats;
-/*
- * get_maxrss - get the operating systems notion of the resident set size
- */
-unsigned long
-get_maxrss(void)
+int maxconnections;
+struct timeval SystemTime;
+struct Client me; /* That's me */
+struct LocalUser meLocalUser; /* That's also part of me */
+
+rb_dlink_list lclient_list = { NULL, NULL, 0 };
+rb_dlink_list global_client_list = { NULL, NULL, 0 };
+
+rb_dlink_list unknown_list; /* unknown clients ON this server only */
+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;
+
+int default_server_capabs = CAP_MASK;
+
+int splitmode;
+int splitchecking;
+int split_users;
+int split_servers;
+int eob_count;
+
+unsigned long initialVMTop = 0; /* top of virtual memory at init */
+const char *logFileName = LPATH;
+const char *pidFileName = PPATH;
+
+char **myargv;
+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;
+
+/* patricia */
+rb_bh *prefix_heap;
+rb_bh *node_heap;
+rb_bh *patricia_heap;
+
+rb_bh *linebuf_heap;
+
+rb_bh *dnode_heap;
+
+void
+ircd_shutdown(const char *reason)
{
- return get_vm_top() - initialVMTop;
+ 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);
}
/*
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
static void
ircd_die_cb(const char *str)
{
- /* 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);
+ if(str != NULL)
+ {
+ /* 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);
static void
init_sys(void)
{
-#if defined(RLIMIT_FD_MAX) && defined(HAVE_SYS_RLIMIT_H)
+#if defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)
struct rlimit limit;
- if(!getrlimit(RLIMIT_FD_MAX, &limit))
+ if(!getrlimit(RLIMIT_NOFILE, &limit))
{
-
- if(limit.rlim_max < MAXCONNECTIONS)
- {
- fprintf(stderr, "ircd fd table too big\n");
- fprintf(stderr, "Hard Limit: %ld IRC max: %d\n",
- (long) limit.rlim_max, MAXCONNECTIONS);
- fprintf(stderr, "Fix MAXCONNECTIONS\n");
- exit(-1);
- }
-
- limit.rlim_cur = limit.rlim_max; /* make soft limit the max */
- if(setrlimit(RLIMIT_FD_MAX, &limit) == -1)
+ maxconnections = limit.rlim_cur;
+ if(maxconnections <= MAX_BUFFER)
{
- fprintf(stderr, "error setting max fd's to %ld\n", (long) limit.rlim_cur);
+ fprintf(stderr, "ERROR: Shell FD limits are too low.\n");
+ fprintf(stderr, "ERROR: ircd-ratbox reserves %d FDs, shell limits must be above this\n", MAX_BUFFER);
exit(EXIT_FAILURE);
}
+ return;
}
#endif /* RLIMIT_FD_MAX */
+ maxconnections = MAXCONNECTIONS;
}
static int
{NULL, NULL, STRING, NULL},
};
-void
-set_time(void)
-{
- struct timeval newtime;
- newtime.tv_sec = 0;
- newtime.tv_usec = 0;
-#ifdef HAVE_GETTIMEOFDAY
- if(gettimeofday(&newtime, NULL) == -1)
- {
- ilog(L_MAIN, "Clock Failure (%d)", errno);
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
- "Clock Failure (%d), TS can be corrupted", errno);
-
- restart("Clock Failure");
- }
-#else
- newtime.tv_sec = time(NULL);
-
-#endif
- if(newtime.tv_sec < CurrentTime)
- set_back_events(CurrentTime - newtime.tv_sec);
-
- SystemTime.tv_sec = newtime.tv_sec;
- SystemTime.tv_usec = newtime.tv_usec;
-}
-
static void
check_rehash(void *unused)
{
{
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;
}
}
-void
-charybdis_io_loop(void)
-{
- time_t delay;
-
- while (ServerRunning)
- {
- /* Run pending events, then get the number of seconds to the next
- * event
- */
-
- delay = eventNextTime();
- if(delay <= CurrentTime)
- eventRun();
-
-
- comm_select(250);
- }
-}
-
/*
* initalialize_global_set_options
*
memset(&GlobalSetOptions, 0, sizeof(GlobalSetOptions));
/* memset( &ConfigFileEntry, 0, sizeof(ConfigFileEntry)); */
- GlobalSetOptions.maxclients = MAX_CLIENTS;
+ GlobalSetOptions.maxclients = ServerInfo.default_max_clients;
+
+ if(GlobalSetOptions.maxclients > (maxconnections - MAX_BUFFER) || (GlobalSetOptions.maxclients <= 0))
+ GlobalSetOptions.maxclients = maxconnections - MAX_BUFFER;
+
GlobalSetOptions.autoconn = 1;
GlobalSetOptions.spam_time = MIN_JOIN_LEAVE_TIME;
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));
{
unsigned int pid = (unsigned int) getpid();
- ircsnprintf(buff, sizeof(buff), "%u\n", pid);
+ rb_snprintf(buff, sizeof(buff), "%u\n", pid);
if((fputs(buff, fb) == -1))
{
ilog(L_MAIN, "Error writing %u to pid file %s (%s)",
#endif
}
+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;
}
- /*
- * save server boot time right away, so getrusage works correctly
- */
- set_time();
/*
* Setup corefile size immediately after boot -kre
*/
setup_corefile();
- /*
- * set initialVMTop before we allocate any memory
- */
- initialVMTop = get_vm_top();
-
- ServerRunning = 0;
/* 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(&local_oper_list, 0, sizeof(local_oper_list));
memset(&oper_list, 0, sizeof(oper_list));
- dlinkAddTail(&me, &me.node, &global_client_list);
+ rb_dlinkAddTail(&me, &me.node, &global_client_list);
- memset((void *) &Count, 0, sizeof(Count));
- memset((void *) &ServerInfo, 0, sizeof(ServerInfo));
- memset((void *) &AdminInfo, 0, sizeof(AdminInfo));
+ memset(&Count, 0, sizeof(Count));
+ memset(&ServerInfo, 0, sizeof(ServerInfo));
+ memset(&AdminInfo, 0, sizeof(AdminInfo));
+ memset(&ServerStats, 0, sizeof(struct ServerStatistics));
/* Initialise the channel capability usage counts... */
init_chcap_usage_counts();
if(printVersion)
{
- printf("ircd: version %s\n", ircd_version);
+ printf("ircd: version %s(%s)\n", ircd_version, serno);
exit(EXIT_SUCCESS);
}
}
/* Init the event subsystem */
- libcharybdis_init(ircd_log_cb, restart, ircd_die_cb);
init_sys();
-
- fdlist_init();
- if(!server_state_foreground)
- {
- comm_close_all();
- }
+ 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);
init_main_logfile();
- init_patricia();
newconf_init();
init_s_conf();
init_s_newconf();
init_channels();
initclass();
initwhowas();
- init_stats();
init_reject();
init_cache();
init_monitor();
mod_add_path(MODULE_DIR "/autoload");
#endif
+ init_ssld();
+
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));
+ 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)
{
me.servptr = &me;
SetMe(&me);
make_server(&me);
- me.serv->up = me.name;
- startup_time = CurrentTime;
+ startup_time = rb_current_time();
add_to_client_hash(me.name, &me);
add_to_id_hash(me.id, &me);
+ me.serv->nameinfo = scache_connect(me.name, me.info, 0);
- dlinkAddAlloc(&me, &global_serv_list);
+ rb_dlinkAddAlloc(&me, &global_serv_list);
construct_umodebuf();
+ construct_noparam_modes();
check_class();
write_pidfile(pidFileName);
ilog(L_MAIN, "Server Ready");
- eventAddIsh("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
*/
- eventAddIsh("try_connections", try_connections, NULL, STARTUP_CONNECTIONS_TIME);
- eventAddOnce("try_connections_startup", try_connections, NULL, 0);
-
- eventAddIsh("collect_zipstats", collect_zipstats, NULL, ZIPSTATS_TIME);
-
- /* Setup the timeout check. I'll shift it later :) -- adrian */
- eventAddIsh("comm_checktimeouts", comm_checktimeouts, NULL, 1);
-
- eventAdd("check_rehash", check_rehash, NULL, 1);
-
- if(ConfigServerHide.links_delay > 0)
- eventAdd("cache_links", cache_links, NULL,
- ConfigServerHide.links_delay);
- else
- ConfigServerHide.links_disabled = 1;
+ rb_event_addish("try_connections", try_connections, NULL, STARTUP_CONNECTIONS_TIME);
+ rb_event_addonce("try_connections_startup", try_connections, NULL, 0);
+ rb_event_add("check_rehash", check_rehash, NULL, 1);
+ rb_event_addish("reseed_srand", seed_random, NULL, 300); /* reseed every 10 minutes */
if(splitmode)
- eventAdd("check_splitmode", check_splitmode, NULL, 2);
-
- ServerRunning = 1;
+ check_splitmode_ev = rb_event_add("check_splitmode", check_splitmode, NULL, 2);
print_startup(getpid());
- charybdis_io_loop();
+ rb_lib_loop(0);
return 0;
}