#include "ircd_reply.h"
#include "ircd_signal.h"
#include "ircd_string.h"
+#include "ircd_crypt.h"
#include "jupe.h"
#include "list.h"
#include "match.h"
#include "msg.h"
#include "numeric.h"
#include "numnicks.h"
+#include "opercmds.h"
#include "parse.h"
#include "res.h"
#include "s_auth.h"
#include "s_conf.h"
#include "s_debug.h"
#include "s_misc.h"
+#include "s_stats.h"
#include "send.h"
#include "sys.h"
#include "uping.h"
* External stuff
*--------------------------------------------------------------------------*/
extern void init_counters(void);
+extern void mem_dbg_initialise(void);
/*----------------------------------------------------------------------------
* Constants / Enums
*--------------------------------------------------------------------------*/
enum {
BOOT_DEBUG = 1,
- BOOT_TTY = 2
+ BOOT_TTY = 2,
+ BOOT_CHKCONF = 4
};
/*----------------------------------------------------------------------------
* API: server_die
*--------------------------------------------------------------------------*/
-void server_die(const char* message) {
+void server_die(const char *message)
+{
/* log_write will send out message to both log file and as server notice */
log_write(LS_SYSTEM, L_CRIT, 0, "Server terminating: %s", message);
flush_connections(0);
running = 0;
}
+/*----------------------------------------------------------------------------
+ * API: server_panic
+ *--------------------------------------------------------------------------*/
+void server_panic(const char *message)
+{
+ /* inhibit sending server notice--we may be panicing due to low memory */
+ log_write(LS_SYSTEM, L_CRIT, LOG_NOSNOTICE, "Server panic: %s", message);
+ flush_connections(0);
+ log_close();
+ close_connections(1);
+ exit(1);
+}
/*----------------------------------------------------------------------------
* API: server_restart
*--------------------------------------------------------------------------*/
-void server_restart(const char* message) {
+void server_restart(const char *message)
+{
static int restarting = 0;
/* inhibit sending any server notices; we may be in a loop */
log_close();
- close_connections(!(thisServer.bootopt & (BOOT_TTY | BOOT_DEBUG)));
+ close_connections(!(thisServer.bootopt & (BOOT_TTY | BOOT_DEBUG | BOOT_CHKCONF)));
execv(SPATH, thisServer.argv);
struct ConnectionClass* cltmp;
struct ConfItem* con_conf = 0;
struct Jupe* ajupe;
- unsigned int con_class = 0;
+ const char* con_class = NULL;
assert(ET_EXPIRE == ev_type(ev));
assert(0 != ev_timer(ev));
Debug((DEBUG_NOTICE, "Connection check at : %s", myctime(CurrentTime)));
for (aconf = GlobalConfList; aconf; aconf = aconf->next) {
/* Also when already connecting! (update holdtimes) --SRB */
- if (!(aconf->status & CONF_SERVER) || aconf->port == 0)
+ if (!(aconf->status & CONF_SERVER) || aconf->address.port == 0 || aconf->hold == 0)
continue;
/* Also skip juped servers */
cltmp = aconf->conn_class;
confrq = get_con_freq(cltmp);
- aconf->hold = CurrentTime + confrq;
+ if(confrq == 0)
+ aconf->hold = next = 0;
+ else
+ aconf->hold = CurrentTime + confrq;
/* Found a CONNECT config with port specified, scan clients and see if
* this server is already connected?
cptr = FindServer(aconf->name);
if (!cptr && (Links(cltmp) < MaxLinks(cltmp)) &&
- (!connecting || (ConClass(cltmp) > con_class))) {
+ (!connecting /*|| (ConClass(cltmp) > con_class)*/)) {
/*
* Check connect rules to see if we're allowed to try
*/
(*pconf = con_conf)->next = 0;
}
- if (connect_server(con_conf, 0, 0))
+ if (connect_server(con_conf, 0))
sendto_opmask_butone(0, SNO_OLDSNO, "Connection to %s activated.",
con_conf->name);
}
Debug((DEBUG_DEBUG, "check_pings(%s)=status:%s limit: %d current: %d",
cli_name(cptr),
- (cli_flags(cptr) & FLAGS_PINGSENT) ? "[Ping Sent]" : "[]",
+ IsPingSent(cptr) ? "[Ping Sent]" : "[]",
max_ping, (int)(CurrentTime - cli_lasttime(cptr))));
-
/* Ok, the thing that will happen most frequently, is that someone will
* have sent something recently. Cover this first for speed.
+ * --
+ * If it's an unregisterd client and hasn't managed to register within
+ * max_ping then it's obviously having problems (broken client) or it's
+ * just up to no good, so we won't skip it, even if its been sending
+ * data to us.
+ * -- hikari
*/
- if (CurrentTime-cli_lasttime(cptr) < max_ping) {
+ if ((CurrentTime-cli_lasttime(cptr) < max_ping) && IsRegistered(cptr)) {
expire = cli_lasttime(cptr) + max_ping;
if (expire < next_check)
next_check = expire;
continue;
}
- /* Quit the client after max_ping*2 - they should have answered by now */
- if (CurrentTime-cli_lasttime(cptr) >= (max_ping*2) ) {
- /* If it was a server, then tell ops about it. */
- if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr))
- sendto_opmask_butone(0, SNO_OLDSNO,
- "No response from %s, closing link",
- cli_name(cptr));
- exit_client_msg(cptr, cptr, &me, "Ping timeout");
- continue;
- }
-
/* Unregistered clients pingout after max_ping seconds, they don't
* get given a second chance - if they were then people could not quite
* finish registration and hold resources without being subject to k/g
* lines
*/
if (!IsRegistered(cptr)) {
- /* Display message if they have sent a NICK and a USER but no
- * nospoof PONG.
- */
- if (*(cli_name(cptr)) && cli_user(cptr) && *(cli_user(cptr))->username) {
- send_reply(cptr, SND_EXPLICIT | ERR_BADPING,
- ":Your client may not be compatible with this server.");
- send_reply(cptr, SND_EXPLICIT | ERR_BADPING,
- ":Compatible clients are available at "
- URL_CLIENTS);
- }
- exit_client_msg(cptr,cptr,&me, "Ping Timeout");
+ assert(!IsServer(cptr));
+ if ((CurrentTime-cli_firsttime(cptr) >= max_ping)) {
+ /* Display message if they have sent a NICK and a USER but no
+ * nospoof PONG.
+ */
+ if (*(cli_name(cptr)) && cli_user(cptr) && *(cli_user(cptr))->username) {
+ send_reply(cptr, SND_EXPLICIT | ERR_BADPING,
+ ":Your client may not be compatible with this server.");
+ send_reply(cptr, SND_EXPLICIT | ERR_BADPING,
+ ":Compatible clients are available at %s",
+ feature_str(FEAT_URL_CLIENTS));
+ }
+ exit_client_msg(cptr,cptr,&me, "Registration Timeout");
+ continue;
+ } else {
+ /* OK, they still have enough time left, so we'll just skip to the
+ * next client. Set the next check to be when their time is up, if
+ * that's before the currently scheduled next check -- hikari */
+ expire = cli_firsttime(cptr) + max_ping;
+ if (expire < next_check)
+ next_check = expire;
+ continue;
+ }
+ }
+
+ /* Quit the client after max_ping*2 - they should have answered by now */
+ if (CurrentTime-cli_lasttime(cptr) >= (max_ping*2) )
+ {
+ /* If it was a server, then tell ops about it. */
+ if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr))
+ sendto_opmask_butone(0, SNO_OLDSNO,
+ "No response from %s, closing link",
+ cli_name(cptr));
+ exit_client_msg(cptr, cptr, &me, "Ping timeout");
continue;
}
- if (!(cli_flags(cptr) & FLAGS_PINGSENT)) {
+ if (!IsPingSent(cptr))
+ {
/* If we havent PINGed the connection and we havent heard from it in a
* while, PING it to make sure it is still alive.
*/
- cli_flags(cptr) |= FLAGS_PINGSENT;
+ SetPingSent(cptr);
/* If we're late in noticing don't hold it against them :) */
cli_lasttime(cptr) = CurrentTime - max_ping;
if (IsUser(cptr))
- sendrawto_one(cptr, MSG_PING " :%s", cli_name(&me));
+ sendrawto_one(cptr, MSG_PING " :%s", cli_name(&me));
else
- sendcmdto_one(&me, CMD_PING, cptr, ":%s", cli_name(&me));
+ {
+ char *asll_ts = militime_float(NULL);
+ sendcmdto_one(&me, CMD_PING, cptr, "!%s %s %s", asll_ts,
+ cli_name(cptr), asll_ts);
+ }
}
expire = cli_lasttime(cptr) + max_ping * 2;
* debugmode
*--------------------------------------------------------------------------*/
static void parse_command_line(int argc, char** argv) {
- const char *options = "d:f:h:ntvx:";
+ const char *options = "d:f:h:nktvx:";
int opt;
if (thisServer.euid != thisServer.uid)
*/
while ((opt = getopt(argc, argv, options)) != EOF)
switch (opt) {
+ case 'k': thisServer.bootopt |= BOOT_CHKCONF; break;
case 'n':
case 't': thisServer.bootopt |= BOOT_TTY; break;
case 'd': dpath = optarg; break;
case 'f': configfile = optarg; break;
case 'h': ircd_strncpy(cli_name(&me), optarg, HOSTLEN); break;
- case 'v': printf("ircd %s\n", version); exit(0);
+ case 'v':
+ printf("ircd %s\n", version);
+ printf("Event engines: ");
+#ifdef USE_KQUEUE
+ printf("kqueue() ");
+#endif
+#ifdef USE_DEVPOLL
+ printf("/dev/poll ");
+#endif
+#ifdef USE_POLL
+ printf("poll()");
+#else
+ printf("select()");
+#endif
+ printf("\nCompiled for a maximum of %d connections.\n", MAXCONNECTIONS);
+
+
+ exit(0);
+ break;
case 'x':
debuglevel = atoi(optarg);
break;
default:
- printf("Usage: ircd [-f config] [-h servername] [-x loglevel] [-ntv]\n");
- printf("\n -n -t\t Don't detach\n -v\t display version\n\n");
+ printf("Usage: ircd [-f config] [-h servername] [-x loglevel] [-ntvk]\n");
+ printf("\n -n -t\t Don't detach\n -v\t display version\n -k\t exit after checking config\n\n");
printf("Server not started.\n");
exit(1);
}
* daemon_init
*--------------------------------------------------------------------------*/
static void daemon_init(int no_fork) {
- if (!init_connection_limits())
- exit(9);
-
- close_connections(!(thisServer.bootopt & (BOOT_DEBUG | BOOT_TTY)));
-
if (no_fork)
return;
thisServer.uid = getuid();
thisServer.euid = geteuid();
+#ifdef MDEBUG
+ mem_dbg_initialise();
+#endif
+
#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_CORE)
set_core_limit();
#endif
!check_file_access(configfile, 'C', R_OK))
return 4;
- debug_init(thisServer.bootopt & BOOT_TTY);
- daemon_init(thisServer.bootopt & BOOT_TTY);
+ if (!init_connection_limits())
+ return 9;
+
+ close_connections(!(thisServer.bootopt & (BOOT_DEBUG | BOOT_TTY | BOOT_CHKCONF)));
+
event_init(MAXCONNECTIONS);
setup_signals();
feature_init(); /* initialize features... */
log_init(*argv);
- if (check_pid()) {
- Debug((DEBUG_FATAL, "Failed to acquire PID file lock after fork"));
- exit(2);
- }
set_nomem_handler(outofmemory);
-
+
if (!init_string()) {
log_write(LS_SYSTEM, L_CRIT, 0, "Failed to initialize string module");
return 6;
init_resolver();
+ /* we need this for now, when we're modular this
+ should be removed -- hikari */
+ ircd_crypt_init();
+
motd_init();
if (!init_conf()) {
return 7;
}
+ if(thisServer.bootopt & BOOT_CHKCONF) {
+ fprintf(stderr, "Configuration file checked okay.\n");
+ return 0;
+ }
+
+ debug_init(thisServer.bootopt & BOOT_TTY);
+ daemon_init(thisServer.bootopt & BOOT_TTY);
+ if (check_pid()) {
+ Debug((DEBUG_FATAL, "Failed to acquire PID file lock after fork"));
+ exit(2);
+ }
+
init_server_identity();
uping_init();
+ stats_init();
+
IPcheck_init();
timer_add(timer_init(&connect_timer), try_connections, 0, TT_RELATIVE, 1);
timer_add(timer_init(&ping_timer), check_pings, 0, TT_RELATIVE, 1);