Esempio n. 1
0
/*!
 *
 * \param source_p Pointer to allocated Client struct from which the message
 *                 originally comes from.  This can be a local or remote client.
 * \param parc     Integer holding the number of supplied arguments.
 * \param parv     Argument vector where parv[0] .. parv[parc-1] are non-NULL
 *                 pointers.
 * \note Valid arguments for this command are:
 *
 *      - parv[0] = command
 *      - parv[1] = nickname
 *      - parv[2] = timestamp
 */
static void
change_remote_nick(struct Client *source_p, char *parv[])
{
  int samenick = !irccmp(source_p->name, parv[1]);

  assert(!EmptyString(parv[1]));
  assert(IsClient(source_p));
  assert(source_p->name[0]);

  /* Client changing their nick */
  if (!samenick)
  {
    DelUMode(source_p, UMODE_REGISTERED);
    watch_check_hash(source_p, RPL_LOGOFF);
    source_p->tsinfo = atol(parv[2]);
    assert(source_p->tsinfo > 0);
  }

  sendto_common_channels_local(source_p, 1, 0, ":%s!%s@%s NICK :%s",
                               source_p->name, source_p->username,
                               source_p->host, parv[1]);

  whowas_add_history(source_p, 1);
  sendto_server(source_p, 0, 0, ":%s NICK %s :%lu",
                source_p->id, parv[1], (unsigned long)source_p->tsinfo);

  /* Set the new nick name */
  hash_del_client(source_p);
  strlcpy(source_p->name, parv[1], sizeof(source_p->name));
  hash_add_client(source_p);

  if (!samenick)
    watch_check_hash(source_p, RPL_LOGON);
}
Esempio n. 2
0
/* set_initial_nick()
 *
 * inputs
 * output
 * side effects -
 *
 * This function is only called to set up an initially registering
 * client.
 */
static void
set_initial_nick(struct Client *source_p, const char *nick)
{
  /* Client setting NICK the first time */

  /* This had to be copied here to avoid problems.. */
  source_p->tsinfo = CurrentTime;
  source_p->localClient->registration &= ~REG_NEED_NICK;

  if (source_p->name[0])
    hash_del_client(source_p);

  strlcpy(source_p->name, nick, sizeof(source_p->name));
  hash_add_client(source_p);

  /* fd_desc is long enough */
  fd_note(&source_p->localClient->fd, "Nick: %s", nick);

  if (!source_p->localClient->registration)
    register_local_user(source_p);
}
Esempio n. 3
0
/*
 * client_from_server()
 */
static void
uid_from_server(struct Client *client_p, struct Client *source_p, int parc,
                char *parv[], time_t newts, const char *svsid, char *nick, char *ugecos)
{
  const char *m = NULL;
  const char *servername = source_p->name;

  source_p = make_client(client_p);
  dlinkAdd(source_p, &source_p->node, &global_client_list);

  source_p->hopcount = atoi(parv[2]);
  source_p->tsinfo = newts;
  strlcpy(source_p->svid, svsid, sizeof(source_p->svid));

  /* copy the nick in place */
  strlcpy(source_p->name, nick, sizeof(source_p->name));
  strlcpy(source_p->id, parv[8], sizeof(source_p->id));
  strlcpy(source_p->sockhost, parv[7], sizeof(source_p->sockhost));
  strlcpy(source_p->info, ugecos, sizeof(source_p->info));

  hash_add_client(source_p);
  hash_add_id(source_p);

  /* parse usermodes */
  for (m = &parv[4][1]; *m; ++m)
  {
    unsigned int flag = user_modes[(unsigned char)*m];

    if ((flag & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
      ++Count.invisi;
    if ((flag & UMODE_OPER) && !HasUMode(source_p, UMODE_OPER))
      ++Count.oper;

    source_p->umodes |= flag & SEND_UMODES;
  }

  register_remote_user(source_p, parv[5], parv[6],
                       servername, ugecos);
}
Esempio n. 4
0
/* set_initial_nick()
 *
 * inputs
 * output
 * side effects -
 *
 * This function is only called to set up an initially registering
 * client.
 */
static void
set_initial_nick(struct Client *source_p, const char *nick)
{
  const int samenick = !irccmp(source_p->name, nick);

  if (!samenick)
    source_p->tsinfo = CurrentTime;

  source_p->connection->registration &= ~REG_NEED_NICK;

  if (source_p->name[0])
    hash_del_client(source_p);

  strlcpy(source_p->name, nick, sizeof(source_p->name));
  hash_add_client(source_p);

  /* fd_desc is long enough */
  fd_note(&source_p->connection->fd, "Nick: %s", source_p->name);

  if (!source_p->connection->registration)
    register_local_user(source_p);
}
Esempio n. 5
0
/*!
 *
 * \param source_p Pointer to allocated Client struct from which the message
 *                 originally comes from.  This can be a local or remote client.
 * \param parc     Integer holding the number of supplied arguments.
 * \param parv     Argument vector where parv[0] .. parv[parc-1] are non-NULL
 *                 pointers.
 * \note Valid arguments for this command are:
 *
 * server introducing new nick/UID (without services support)
 *      - parv[0] = command
 *      - parv[1] = nickname
 *      - parv[2] = hop count
 *      - parv[3] = TS
 *      - parv[4] = umode
 *      - parv[5] = username
 *      - parv[6] = hostname
 *      - parv[7] = ip
 *      - parv[8] = uid
 *      - parv[9] = ircname (gecos)
 *
 * server introducing new nick/UID (with services support)
 *      - parv[ 0] = command
 *      - parv[ 1] = nickname
 *      - parv[ 2] = hop count
 *      - parv[ 3] = TS
 *      - parv[ 4] = umode
 *      - parv[ 5] = username
 *      - parv[ 6] = hostname
 *      - parv[ 7] = ip
 *      - parv[ 8] = uid
 *      - parv[ 9] = services account
 *      - parv[10] = ircname (gecos)
 */
static void
uid_from_server(struct Client *source_p, int parc, char *parv[])
{
  struct Client *client_p = NULL;

  client_p = make_client(source_p->from);
  client_p->servptr = source_p;
  client_p->hopcount = atoi(parv[2]);
  client_p->tsinfo = atol(parv[3]);

  strlcpy(client_p->account, (parc == 11 ? parv[9] : "*"), sizeof(client_p->account));
  strlcpy(client_p->name, parv[1], sizeof(client_p->name));
  strlcpy(client_p->id, parv[8], sizeof(client_p->id));
  strlcpy(client_p->sockhost, parv[7], sizeof(client_p->sockhost));
  strlcpy(client_p->info, parv[parc - 1], sizeof(client_p->info));
  strlcpy(client_p->host, parv[6], sizeof(client_p->host));
  strlcpy(client_p->username, parv[5], sizeof(client_p->username));

  hash_add_client(client_p);
  hash_add_id(client_p);

  /* Parse user modes */
  for (const char *m = &parv[4][1]; *m; ++m)
  {
    const struct user_modes *tab = umode_map[(unsigned char)*m];

    if (!tab)
      continue;
    if ((tab->flag & UMODE_INVISIBLE) && !HasUMode(client_p, UMODE_INVISIBLE))
      ++Count.invisi;
    if ((tab->flag & UMODE_OPER) && !HasUMode(client_p, UMODE_OPER))
      ++Count.oper;

    AddUMode(client_p, tab->flag);
  }

  register_remote_user(client_p);
}
Esempio n. 6
0
/*
 * nick_from_server()
 */
static void
nick_from_server(struct Client *client_p, struct Client *source_p, int parc,
                 char *parv[], time_t newts, const char *svsid, char *nick, char *ngecos)
{
  int samenick = 0;

  if (IsServer(source_p))
  {
    /* A server introducing a new client, change source */
    source_p = make_client(client_p);
    dlinkAdd(source_p, &source_p->node, &global_client_list);

    if (parc > 2)
      source_p->hopcount = atoi(parv[2]);
    if (newts)
      source_p->tsinfo = newts;
    else
    {
      newts = source_p->tsinfo = CurrentTime;
      ts_warn("Remote nick %s (%s) introduced without a TS", nick, parv[0]);
    }

    strlcpy(source_p->svid, svsid, sizeof(source_p->svid));
    strlcpy(source_p->info, ngecos, sizeof(source_p->info));
    /* copy the nick in place */
    strlcpy(source_p->name, nick, sizeof(source_p->name));
    hash_add_client(source_p);

    if (parc > 8)
    {
      const char *m;

      /* parse usermodes */
      for (m = &parv[4][1]; *m; ++m)
      {
        unsigned int flag = user_modes[(unsigned char)*m];

        if ((flag & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
          ++Count.invisi;
        if ((flag & UMODE_OPER) && !HasUMode(source_p, UMODE_OPER))
          ++Count.oper;

        source_p->umodes |= flag & SEND_UMODES;
      }

      register_remote_user(source_p, parv[5], parv[6],
                           parv[7], ngecos);
      return;
    }
  }
  else if (source_p->name[0])
  {
    samenick = !irccmp(source_p->name, nick);

    /* Client changing their nick */
    if (!samenick)
    {
      DelUMode(source_p, UMODE_REGISTERED);
      watch_check_hash(source_p, RPL_LOGOFF);
      source_p->tsinfo = newts ? newts : CurrentTime;
    }

    sendto_common_channels_local(source_p, 1, 0, ":%s!%s@%s NICK :%s",
                                 source_p->name,source_p->username,
                                 source_p->host, nick);

    add_history(source_p, 1);
    sendto_server(client_p, CAP_TS6, NOCAPS,
                  ":%s NICK %s :%lu",
                  ID(source_p), nick, (unsigned long)source_p->tsinfo);
    sendto_server(client_p, NOCAPS, CAP_TS6,
                  ":%s NICK %s :%lu",
                  source_p->name, nick, (unsigned long)source_p->tsinfo);
  }

  /* set the new nick name */
  if (source_p->name[0])
    hash_del_client(source_p);

  strlcpy(source_p->name, nick, sizeof(source_p->name));
  hash_add_client(source_p);

  if (!samenick)
    watch_check_hash(source_p, RPL_LOGON);
}
Esempio n. 7
0
/* change_local_nick()
 *
 * inputs       - pointer to server
 *              - pointer to client
 *              - nick
 * output       - 
 * side effects - changes nick of a LOCAL user
 */
static void
change_local_nick(struct Client *source_p, const char *nick)
{
  assert(source_p->name[0] && !EmptyString(nick));
  assert(MyConnect(source_p));

  /*
   * Client just changing his/her nick. If he/she is
   * on a channel, send note of change to all clients
   * on that channel. Propagate notice to other servers.
   */
  if ((source_p->localClient->last_nick_change +
       ConfigFileEntry.max_nick_time) < CurrentTime)
    source_p->localClient->number_of_nick_changes = 0;
  source_p->localClient->last_nick_change = CurrentTime;
  source_p->localClient->number_of_nick_changes++;

  if ((ConfigFileEntry.anti_nick_flood &&
      (source_p->localClient->number_of_nick_changes
       <= ConfigFileEntry.max_nick_changes)) ||
     !ConfigFileEntry.anti_nick_flood ||
     (HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.no_oper_flood))
  {
    int samenick = !irccmp(source_p->name, nick);

    if (!samenick)
    {
      source_p->tsinfo = CurrentTime;
      clear_ban_cache_client(source_p);
      watch_check_hash(source_p, RPL_LOGOFF);

      if (HasUMode(source_p, UMODE_REGISTERED))
      {
        unsigned int oldmodes = source_p->umodes;
        char modebuf[IRCD_BUFSIZE] = { '\0' };

        DelUMode(source_p, UMODE_REGISTERED);
        send_umode(source_p, source_p, oldmodes, 0xffffffff, modebuf);
      }
    }

    sendto_realops_flags(UMODE_NCHANGE, L_ALL, SEND_NOTICE,
                         "Nick change: From %s to %s [%s@%s]",
                         source_p->name, nick, source_p->username, source_p->host);
    sendto_common_channels_local(source_p, 1, 0, ":%s!%s@%s NICK :%s",
                                 source_p->name, source_p->username,
                                 source_p->host, nick);
    add_history(source_p, 1);

    sendto_server(source_p, CAP_TS6, NOCAPS,
                  ":%s NICK %s :%lu",
                  ID(source_p), nick, (unsigned long)source_p->tsinfo);
    sendto_server(source_p, NOCAPS, CAP_TS6,
                  ":%s NICK %s :%lu",
                  source_p->name, nick, (unsigned long)source_p->tsinfo);

    hash_del_client(source_p);
    strlcpy(source_p->name, nick, sizeof(source_p->name));
    hash_add_client(source_p);

    if (!samenick)
      watch_check_hash(source_p, RPL_LOGON);

    /* fd_desc is long enough */
    fd_note(&source_p->localClient->fd, "Nick: %s", nick);
  }
  else
    sendto_one(source_p, form_str(ERR_NICKTOOFAST), me.name,
               source_p->name, source_p->name, nick,
               ConfigFileEntry.max_nick_time);
}
Esempio n. 8
0
/* change_local_nick()
 *
 * inputs       - pointer to server
 *              - pointer to client
 *              - nick
 * output       -
 * side effects - changes nick of a LOCAL user
 */
static void
change_local_nick(struct Client *source_p, const char *nick)
{
  int samenick = 0;

  assert(source_p->name[0] && !EmptyString(nick));
  assert(MyClient(source_p));

  /*
   * Client just changing his/her nick. If he/she is
   * on a channel, send note of change to all clients
   * on that channel. Propagate notice to other servers.
   */
  if ((source_p->connection->nick.last_attempt +
       ConfigGeneral.max_nick_time) < CurrentTime)
    source_p->connection->nick.count = 0;

  if (ConfigGeneral.anti_nick_flood &&
      !HasUMode(source_p, UMODE_OPER) &&
      source_p->connection->nick.count >
      ConfigGeneral.max_nick_changes)
  {
    sendto_one_numeric(source_p, &me, ERR_NICKTOOFAST, nick,
                       ConfigGeneral.max_nick_time);
    return;
  }

  source_p->connection->nick.last_attempt = CurrentTime;
  source_p->connection->nick.count++;

  samenick = !irccmp(source_p->name, nick);

  if (!samenick)
  {
    source_p->tsinfo = CurrentTime;
    clear_ban_cache_client(source_p);
    watch_check_hash(source_p, RPL_LOGOFF);

    if (HasUMode(source_p, UMODE_REGISTERED))
    {
      unsigned int oldmodes = source_p->umodes;
      char modebuf[IRCD_BUFSIZE] = "";

      DelUMode(source_p, UMODE_REGISTERED);
      send_umode(source_p, source_p, oldmodes, modebuf);
    }
  }

  sendto_realops_flags(UMODE_NCHANGE, L_ALL, SEND_NOTICE,
                       "Nick change: From %s to %s [%s@%s]",
                       source_p->name, nick, source_p->username, source_p->host);
  sendto_common_channels_local(source_p, 1, 0, ":%s!%s@%s NICK :%s",
                               source_p->name, source_p->username,
                               source_p->host, nick);
  whowas_add_history(source_p, 1);

  sendto_server(source_p, 0, 0, ":%s NICK %s :%lu",
                source_p->id, nick, (unsigned long)source_p->tsinfo);

  hash_del_client(source_p);
  strlcpy(source_p->name, nick, sizeof(source_p->name));
  hash_add_client(source_p);

  if (!samenick)
    watch_check_hash(source_p, RPL_LOGON);

  /* fd_desc is long enough */
  fd_note(&source_p->connection->fd, "Nick: %s", source_p->name);
}
Esempio n. 9
0
int
main(int argc, char *argv[])
{
  /* Check to see if the user is running us as root, which is a nono */
  if (!geteuid())
  {
    fprintf(stderr, "ERROR: This server won't run as root/superuser\n");
    return -1;
  }

  /* Setup corefile size immediately after boot -kre */
  setup_corefile();

  /* Save server boot time right away, so getrusage works correctly */
  set_time();

  /* It's not random, but it ought to be a little harder to guess */
  init_genrand(SystemTime.tv_sec ^ (SystemTime.tv_usec | (getpid() << 20)));

  dlinkAdd(&me, &me.node, &global_client_list);

  ConfigGeneral.dpath      = DPATH;
  ConfigGeneral.spath      = SPATH;
  ConfigGeneral.mpath      = MPATH;
  ConfigGeneral.configfile = CPATH;    /* Server configuration file */
  ConfigGeneral.klinefile  = KPATH;    /* Server kline file         */
  ConfigGeneral.glinefile  = GPATH;    /* Server gline file         */
  ConfigGeneral.xlinefile  = XPATH;    /* Server xline file         */
  ConfigGeneral.dlinefile  = DLPATH;   /* dline file                */
  ConfigGeneral.resvfile   = RESVPATH; /* resv file                 */

  myargv = argv;
  umask(077);  /* umask 077: u=rwx,g=,o= */

  parseargs(&argc, &argv, myopts);

  if (printVersion)
  {
    printf("ircd: version %s(%s)\n", ircd_version, serno);
    exit(EXIT_SUCCESS);
  }

  if (chdir(ConfigGeneral.dpath))
  {
    perror("chdir");
    exit(EXIT_FAILURE);
  }

  ssl_init();

  if (!server_state.foreground)
  {
    make_daemon();
    close_standard_fds(); /* this needs to be before init_netio()! */
  }
  else
    print_startup(getpid());

  setup_signals();

  /* We need this to initialise the fd array before anything else */
  fdlist_init();
  log_set_file(LOG_TYPE_IRCD, 0, logFileName);

  init_netio();         /* This needs to be setup early ! -- adrian */

  /* Check if there is pidfile and daemon already running */
  check_pidfile(pidFileName);

  mp_pool_init();
  init_dlink_nodes();
  init_isupport();
  dbuf_init();
  hash_init();
  ipcache_init();
  client_init();
  class_init();
  whowas_init();
  watch_init();
  auth_init();          /* Initialise the auth code */
  init_resolver();      /* Needs to be setup before the io loop */
  modules_init();
  read_conf_files(1);   /* cold start init conf files */
  init_uid();
  initialize_server_capabs();   /* Set up default_server_capabs */
  initialize_global_set_options();  /* Has to be called after read_conf_files() */
  channel_init();
  read_links_file();
  motd_init();
  user_usermodes_init();
#ifdef HAVE_LIBGEOIP
  geoip_ctx = GeoIP_new(GEOIP_MEMORY_CACHE);
#endif

  if (EmptyString(ConfigServerInfo.sid))
  {
    ilog(LOG_TYPE_IRCD, "ERROR: No server id specified in serverinfo block.");
    exit(EXIT_FAILURE);
  }

  strlcpy(me.id, ConfigServerInfo.sid, sizeof(me.id));

  if (EmptyString(ConfigServerInfo.name))
  {
    ilog(LOG_TYPE_IRCD, "ERROR: No server name specified in serverinfo block.");
    exit(EXIT_FAILURE);
  }

  strlcpy(me.name, ConfigServerInfo.name, sizeof(me.name));

  /* serverinfo{} description must exist.  If not, error out.*/
  if (EmptyString(ConfigServerInfo.description))
  {
    ilog(LOG_TYPE_IRCD, "ERROR: No server description specified in serverinfo block.");
    exit(EXIT_FAILURE);
  }

  strlcpy(me.info, ConfigServerInfo.description, sizeof(me.info));

  me.from = &me;
  me.servptr = &me;
  me.connection->lasttime = CurrentTime;
  me.connection->since = CurrentTime;
  me.connection->firsttime = CurrentTime;

  SetMe(&me);
  make_server(&me);

  hash_add_id(&me);
  hash_add_client(&me);

  dlinkAdd(&me, make_dlink_node(), &global_server_list);

  load_kline_database();
  load_dline_database();
  load_gline_database();
  load_xline_database();
  load_resv_database();

  load_all_modules(1);
  load_conf_modules();
  load_core_modules(1);

  write_pidfile(pidFileName);

  ilog(LOG_TYPE_IRCD, "Server Ready");

  event_addish(&event_cleanup_glines, NULL);
  event_addish(&event_cleanup_tklines, NULL);

  /* 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 */
  event_addish(&event_try_connections, NULL);

  /* Setup the timeout check. I'll shift it later :)  -- adrian */
  event_add(&event_comm_checktimeouts, NULL);

  event_addish(&event_save_all_databases, NULL);

  if (ConfigServerHide.links_delay > 0)
  {
    event_write_links_file.when = ConfigServerHide.links_delay;
    event_addish(&event_write_links_file, NULL);
  }
  else
    ConfigServerHide.links_disabled = 1;

  if (splitmode)
    event_addish(&splitmode_event, NULL);

  io_loop();
  return 0;
}
Esempio n. 10
0
/*! \brief SVSNICK command handler
 *
 * \param source_p Pointer to allocated Client struct from which the message
 *                 originally comes from.  This can be a local or remote client.
 * \param parc     Integer holding the number of supplied arguments.
 * \param parv     Argument vector where parv[0] .. parv[parc-1] are non-NULL
 *                 pointers.
 * \note Valid arguments for this command are:
 *      - parv[0] = command
 *      - parv[1] = old nickname
 *      - parv[2] = new nickname
 *      - parv[3] = timestamp
 */
static int
ms_svsnick(struct Client *source_p, int parc, char *parv[])
{
  struct Client *target_p = NULL, *exists_p = NULL;

  if (!HasFlag(source_p, FLAGS_SERVICE) || !valid_nickname(parv[2], 1))
    return 0;

  if ((target_p = find_person(source_p, parv[1])) == NULL)
    return 0;

  if (!MyConnect(target_p))
  {
    if (target_p->from == source_p->from)
    {
      sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
                           "Received wrong-direction SVSNICK "
                           "for %s (behind %s) from %s",
                           target_p->name, source_p->from->name,
                           get_client_name(source_p, HIDE_IP));
      return 0;
    }

    sendto_one(target_p, ":%s SVSNICK %s %s %s", source_p->id,
               target_p->id, parv[2], parv[3]);
    return 0;
  }

  if ((exists_p = hash_find_client(parv[2])))
  {
    if (target_p == exists_p)
    {
      if (!strcmp(target_p->name, parv[2]))
        return 0;
    }
    else if (IsUnknown(exists_p))
      exit_client(exists_p, "SVSNICK Override");
    else
    {
      exit_client(target_p, "SVSNICK Collide");
      return 0;
    }
  }

  target_p->tsinfo = strtoimax(parv[3], NULL, 10);
  clear_ban_cache_client(target_p);
  watch_check_hash(target_p, RPL_LOGOFF);

  if (HasUMode(target_p, UMODE_REGISTERED))
  {
    const unsigned int oldmodes = target_p->umodes;
    char modebuf[IRCD_BUFSIZE] = "";

    DelUMode(target_p, UMODE_REGISTERED);
    send_umode(target_p, target_p, oldmodes, modebuf);
  }

  sendto_common_channels_local(target_p, 1, 0, 0, ":%s!%s@%s NICK :%s",
                               target_p->name, target_p->username,
                               target_p->host, parv[2]);

  whowas_add_history(target_p, 1);

  sendto_server(NULL, 0, 0, ":%s NICK %s :%ju",
                target_p->id, parv[2], target_p->tsinfo);
  hash_del_client(target_p);
  strlcpy(target_p->name, parv[2], sizeof(target_p->name));
  hash_add_client(target_p);

  watch_check_hash(target_p, RPL_LOGON);

  fd_note(&target_p->connection->fd, "Nick: %s", target_p->name);
  return 0;
}
Esempio n. 11
0
int
main (int argc, char *argv[])
{
  /* Check to see if the user is running
   * us as root, which is a nono
   */
  if (geteuid () == 0)
    {
      fprintf (stderr, "Don't run ircd as root!!!\n");
      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 (&meLocalUser, 0, sizeof (meLocalUser));
  me.localClient = &meLocalUser;
  dlinkAdd (&me, &me.node, &global_client_list);	/* Pointer to beginning
							   of Client list */

  memset (&ServerInfo, 0, sizeof (ServerInfo));

  /* 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.xlinefile = XPATH;	/* Server xline file         */
  ConfigFileEntry.dlinefile = DLPATH;	/* dline file                */
  ConfigFileEntry.cresvfile = CRESVPATH;	/* channel resv file      */
  ConfigFileEntry.nresvfile = NRESVPATH;	/* nick resv file         */
  myargv = argv;
  umask (077);			/* better safe than sorry --SRB */

  parseargs (&argc, &argv, myopts);

  build_version ();

  if (printVersion)
    {
      printf ("ircd: version %s\n", ircd_version);
      exit (EXIT_SUCCESS);
    }

  if (chdir (ConfigFileEntry.dpath))
    {
      perror ("chdir");
      exit (EXIT_FAILURE);
    }

  if (!server_state.foreground)
    make_daemon ();
  else
    print_startup (getpid ());

#ifdef HAVE_LIBCRYPTO
  dh_init();
  fprintf(stderr, "SSL: Initialize\n");

  SSL_load_error_strings();
  SSLeay_add_ssl_algorithms();
  ServerInfo.ctx = SSL_CTX_new(SSLv23_server_method());

  if (!ServerInfo.ctx) {
       ERR_print_errors_fp(stderr);
       return 0;
  }

  fprintf(stderr, "SSL: Client based SSL connections are enabled.\n");
#endif

  setup_signals ();
  /* We need this to initialise the fd array before anything else */
  fdlist_init ();

  if (!server_state.foreground)
    close_all_connections ();	/* this needs to be before init_netio()! */
  else
    check_can_use_v6 ();	/* Done in close_all_connections normally */

  init_log (logFileName);
  init_netio ();		/* This needs to be setup early ! -- adrian */
  /* Check if there is pidfile and daemon already running */
  check_pidfile (pidFileName);
  /* Init the event subsystem */
  eventInit ();
  init_sys ();

#ifndef NOBALLOC
  initBlockHeap ();
#endif
  init_dlink_nodes ();
  init_slink_nodes ();
  initialize_message_files ();
  dbuf_init ();
  init_hash ();
  init_ip_hash_table ();	/* client host ip hash table */
  init_host_hash ();		/* Host-hashtable. */
  clear_hash_parse ();
  init_client ();
  init_user ();
  init_channels ();
  init_class ();
  init_whowas ();
  init_stats ();
  init_hooks ();
  read_conf_files (1);		/* cold start init conf files */
  initServerMask ();
  init_uid ();
  init_auth ();			/* Initialise the auth code */
  init_resolver ();		/* Needs to be setup before the io loop */
  init_reject ();               /* Set up the reject code. */
  init_umodes ();               /* Set up the usermode system. */

  initialize_foundation_signals(); /* register things that modules need */

#ifdef HAVE_LIBCRYPTO
  bio_spare_fd = save_spare_fd ("SSL private key validation");
#endif /* HAVE_LIBCRYPTO */

  initialize_server_capabs ();	/* Set up default_server_capabs */
  initialize_global_set_options ();

  if (ServerInfo.name == NULL)
    {
      fprintf (stderr,
	       "ERROR: No server name specified in serverinfo block.\n");
      ilog (L_CRIT, "No server name specified in serverinfo block.");
      exit (EXIT_FAILURE);
    }
  strlcpy (me.name, ServerInfo.name, sizeof (me.name));

  /* serverinfo{} description must exist.  If not, error out. */
  if (ServerInfo.description == NULL)
    {
      fprintf (stderr,
	       "ERROR: No server description specified in serverinfo block.\n");
      ilog (L_CRIT,
	    "ERROR: No server description specified in serverinfo block.");
      exit (EXIT_FAILURE);
    }
  strlcpy (me.info, ServerInfo.description, sizeof (me.info));

  me.from = &me;
  me.servptr = &me;

  SetMe (&me);
  make_server (&me);

  strlcpy (me.serv->up, me.name, sizeof (me.serv->up));
  me.lasttime = me.since = me.firsttime = CurrentTime;
  hash_add_client (&me);

  /* add ourselves to global_serv_list */
  dlinkAdd (&me, make_dlink_node (), &global_serv_list);

  check_class ();

#ifndef STATIC_MODULES
  if (chdir (MODPATH))
    {
      ilog (L_CRIT, "Could not load core modules. Terminating!");
      exit (EXIT_FAILURE);
    }
  mod_set_base ();
  load_all_modules (1);
  load_core_modules (1);
  /* Go back to DPATH after checking to see if we can chdir to MODPATH */
  chdir (ConfigFileEntry.dpath);
#else
  load_all_modules (1);
#endif

  write_pidfile (pidFileName);

  ilog (L_NOTICE, "Server Ready");

  eventAddIsh ("cleanup_tklines", cleanup_tklines, NULL,
	       CLEANUP_TKLINES_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 */
  eventAddIsh ("try_connections", try_connections, NULL,
	       STARTUP_CONNECTIONS_TIME);

  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);

  if (splitmode)
    eventAddIsh ("check_splitmode", check_splitmode, NULL, 60);

  ServerRunning = 1;
  io_loop ();
  return (0);
}