Esempio n. 1
0
/** Start sending upings to a server.
 * @param[in] sptr Client requesting the upings.
 * @param[in] aconf ConfItem containing the address to ping.
 * @param[in] port Port number to ping.
 * @param[in] count Number of times to ping (should be at least 20).
 * @return Zero.
 */
int uping_server(struct Client* sptr, struct ConfItem* aconf, int port, int count)
{
  int fd;
  struct UPing* pptr;

  assert(0 != sptr);
  assert(0 != aconf);

  if (INADDR_NONE == aconf->ipnum.s_addr) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Host lookup failed for "
		  "%s", sptr, aconf->name);
    return 0;
  }

  if (IsUPing(sptr))
    uping_cancel(sptr, sptr);  /* Cancel previous ping request */

  if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Unable to create udp "
		  "ping socket", sptr);
    return 0;
  }

  if (!os_set_nonblocking(fd)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Can't set fd non-"
		  "blocking", sptr);
    close(fd);
    return 0;
  }
  pptr = (struct UPing*) MyMalloc(sizeof(struct UPing));
  assert(0 != pptr);
  memset(pptr, 0, sizeof(struct UPing));

  if (!socket_add(&pptr->socket, uping_read_callback, (void*) pptr,
		  SS_DATAGRAM, SOCK_EVENT_READABLE, fd)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Can't queue fd for "
		  "reading", sptr);
    close(fd);
    MyFree(pptr);
    return 0;
  }

  pptr->fd                  = fd;
  pptr->sin.sin_port        = htons(port);
  pptr->sin.sin_addr.s_addr = aconf->ipnum.s_addr;
  pptr->sin.sin_family      = AF_INET;
  pptr->count               = IRCD_MIN(20, count);
  pptr->client              = sptr;
  pptr->index               = -1;
  pptr->freeable            = UPING_PENDING_SOCKET;
  strcpy(pptr->name, aconf->name);

  pptr->next = pingList;
  pingList   = pptr;

  SetUPing(sptr);
  uping_start(pptr);
  return 0;
}
Esempio n. 2
0
/** Start sending upings to a server.
 * @param[in] sptr Client requesting the upings.
 * @param[in] aconf ConfItem containing the address to ping.
 * @param[in] port Port number to ping.
 * @param[in] count Number of times to ping (should be at least 20).
 * @return Zero.
 */
int uping_server(struct Client* sptr, struct ConfItem* aconf, int port, int count)
{
  int fd;
  int family = 0;
  struct UPing* pptr;
  struct irc_sockaddr *local;

  assert(0 != sptr);
  assert(0 != aconf);

  if (!irc_in_addr_valid(&aconf->address.addr)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Host lookup failed for "
		  "%s", sptr, aconf->name);
    return 0;
  }

  if (IsUPing(sptr))
    uping_cancel(sptr, sptr);  /* Cancel previous ping request */

  if (irc_in_addr_is_ipv4(&aconf->address.addr)) {
    local = &VirtualHost_v4;
    family = AF_INET;
  } else {
    local = &VirtualHost_v6;
  }
  fd = os_socket(local, SOCK_DGRAM, "Outbound uping socket", family);
  if (fd < 0)
    return 0;

  pptr = (struct UPing*) MyMalloc(sizeof(struct UPing));
  assert(0 != pptr);
  memset(pptr, 0, sizeof(struct UPing));

  if (!socket_add(&pptr->socket, uping_read_callback, (void*) pptr,
		  SS_DATAGRAM, SOCK_EVENT_READABLE, fd)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Can't queue fd for "
		  "reading", sptr);
    close(fd);
    MyFree(pptr);
    return 0;
  }

  pptr->fd                  = fd;
  memcpy(&pptr->addr.addr, &aconf->address.addr, sizeof(pptr->addr.addr));
  pptr->addr.port           = port;
  pptr->count               = IRCD_MIN(20, count);
  pptr->client              = sptr;
  pptr->freeable            = UPING_PENDING_SOCKET;
  strcpy(pptr->name, aconf->name);

  pptr->next = pingList;
  pingList   = pptr;

  SetUPing(sptr);
  uping_start(pptr);
  return 0;
}
Esempio n. 3
0
/*! \brief NICK command handler (called by unregistered,
 *         locally connected clients)
 *
 * \param client_p Pointer to allocated Client struct with physical connection
 *                 to this server, i.e. with an open socket connected.
 * \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] = sender prefix
 *      - parv[1] = nickname
 */
static void
mr_nick(struct Client *client_p, struct Client *source_p,
        int parc, char *parv[])
{
  char nick[NICKLEN + 1] = { '\0' };
  char *s = NULL;
  struct Client *target_p = NULL;
  struct MaskItem *conf = NULL;

  if (parc < 2 || EmptyString(parv[1]))
  {
    sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN), me.name,
               source_p->name[0] ? source_p->name : "*");
    return;
  }

  /* Terminate the nick at the first ~ */
  if ((s = strchr(parv[1], '~')) != NULL)
    *s = '\0';

  /* Copy the nick and terminate it */
  strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ServerInfo.max_nick_length + 1));

  /* Check the nickname is ok */
  if (!valid_nickname(nick, 1))
  {
    sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name,
               source_p->name[0] ? source_p->name : "*", parv[1],
               "Erroneous Nickname");
    return;
  }

  /* Check if the nick is resv'd */
  if ((conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0)))
  {
    ++conf->count;
    sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name,
               source_p->name[0] ? source_p->name : "*", nick, conf->reason);
    sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
                         "Forbidding reserved nick [%s] from user %s",
                         nick, get_client_name(client_p, HIDE_IP));
    return;
  }

  if ((target_p = hash_find_client(nick)) == NULL)
    set_initial_nick(source_p, nick);
  else if (source_p == target_p)
    strlcpy(source_p->name, nick, sizeof(source_p->name));
  else
    sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name, "*", nick);
}
Esempio n. 4
0
/** Copy a single line from a data buffer.
 * If the output buffer cannot hold the whole line, or if there is no
 * EOL in the buffer, return 0.
 * @param[in,out] dyn Data buffer to copy from.
 * @param[out] buf Buffer to copy to.
 * @param[in] length Maximum number of bytes to copy.
 * @return Number of bytes copied to \a buf.
 */
unsigned int dbuf_getmsg(struct DBuf *dyn, char *buf, unsigned int length)
{
  struct DBufBuffer *db;
  char *start;
  char *end;
  unsigned int count;
  unsigned int copied = 0;

  assert(0 != dyn);
  assert(0 != buf);

  if (0 == dbuf_flush(dyn))
    return 0;

  assert(0 != dyn->head);

  db = dyn->head;
  start = db->start;

  assert(start < db->end);

  if (length > dyn->length)
    length = dyn->length;
  /*
   * might as well copy it while we're here
   */
  while (length > 0)
  {
    end = IRCD_MIN(db->end, (start + length));
    while (start < end && !IsEol(*start))
      *buf++ = *start++;

    count = start - db->start;
    if (start < end)
    {
      *buf = '\0';
      copied += count;
      dbuf_delete(dyn, copied);
      dbuf_flush(dyn);
      return copied;
    }
    if (0 == (db = db->next))
      break;
    copied += count;
    length -= count;
    start = db->start;
  }
  return 0;
}
Esempio n. 5
0
/*! \brief NICK 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] = nickname
 */
static int
mr_nick(struct Client *source_p, int parc, char *parv[])
{
  char nick[NICKLEN + 1] = "";
  struct Client *target_p = NULL;
  struct MaskItem *conf = NULL;

  if (parc < 2 || EmptyString(parv[1]))
  {
    sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN);
    return 0;
  }

  /* Copy the nick and terminate it */
  strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ConfigServerInfo.max_nick_length + 1));

  /* Check the nickname is ok */
  if (!valid_nickname(nick, 1))
  {
    sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, parv[1], "Erroneous Nickname");
    return 0;
  }

  /* Check if the nick is resv'd */
  if ((conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0)))
  {
    ++conf->count;
    sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, conf->reason);
    sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
                         "Forbidding reserved nick %s from user %s",
                         nick, get_client_name(source_p, HIDE_IP));
    return 0;
  }

  if ((target_p = hash_find_client(nick)) == NULL || target_p == source_p)
    set_initial_nick(source_p, nick);
  else
    sendto_one_numeric(source_p, &me, ERR_NICKNAMEINUSE, target_p->name);

  return 0;
}
Esempio n. 6
0
/*! \brief PASS 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] = password
 *      - parv[2] = unused
 *      - parv[3] = TS protocol version
 *      - parv[4] = server ID (SID)
 */
static int
mr_pass(struct Client *source_p, int parc, char *parv[])
{
  assert(MyConnect(source_p));

  if (EmptyString(parv[1]))
  {
    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "PASS");
    return 0;
  }

  MyFree(source_p->connection->password);
  source_p->connection->password = xstrndup(parv[1], IRCD_MIN(strlen(parv[1]), PASSWDLEN));

  /* Only do this stuff if we are doing ts6 */
  if (parc > 4)
    if (atoi(parv[3]) >= 6 && valid_sid(parv[4]))
      strlcpy(source_p->id, parv[4], sizeof(source_p->id));

  return 0;
}
Esempio n. 7
0
/** Send a message to all of our nameservers.
 * @param[in] msg Message to send.
 * @param[in] len Length of message.
 * @param[in] rcount Maximum number of servers to ask.
 * @return Number of servers that were successfully asked.
 */
static int
send_res_msg(const char *msg, int len, int rcount)
{
  int i;
  int sent = 0;
  int max_queries = IRCD_MIN(irc_nscount, rcount);

  /* RES_PRIMARY option is not implemented
   * if (res.options & RES_PRIMARY || 0 == max_queries)
   */
  if (max_queries == 0)
    max_queries = 1;

  for (i = 0; i < max_queries; i++) {
    int fd = irc_in_addr_is_ipv4(&irc_nsaddr_list[i].addr) ? s_fd(&res_socket_v4) : s_fd(&res_socket_v6);
    if (os_sendto_nonb(fd, msg, len, NULL, 0, &irc_nsaddr_list[i]) == IO_SUCCESS)
      ++sent;
  }

  return(sent);
}
Esempio n. 8
0
/*! \brief PASS 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] = password
 *      - parv[2] = optional extra version information
 *      - parv[3] = TS protocol version
 *      - parv[4] = server ID (SID)
 */
static int
mr_pass(struct Client *source_p, int parc, char *parv[])
{
  assert(MyConnect(source_p));

  if (EmptyString(parv[1]))
  {
    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "PASS");
    return 0;
  }

  MyFree(source_p->connection->password);
  source_p->connection->password = xstrndup(parv[1], IRCD_MIN(strlen(parv[1]), PASSWDLEN));

  if (parc > 2)
  {
    /*
     * It looks to me as if orabidoo wanted to have more
     * than one set of option strings possible here...
     * i.e. ":AABBTS" as long as TS was the last two chars
     * however, as we are now using CAPAB, I think we can
     * safely assume if there is a ":TS" then it's a TS server
     * -Dianora
     */
    if (!irccmp(parv[2], "TS") && source_p->tsinfo == 0)
      source_p->tsinfo = TS_DOESTS;
  }

  /* Only do this stuff if we are doing ts6 */
  if (parc > 4)
  {
    if (atoi(parv[3]) >= 6 && valid_sid(parv[4]))
    {
      strlcpy(source_p->id, parv[4], sizeof(source_p->id));
      SetCapable(source_p, CAP_TS6);
    }
  }

  return 0;
}
Esempio n. 9
0
/*
 * m_pass() - Added Sat, 4 March 1989
 *
 *
 * mr_pass - PASS message handler
 *      parv[0] = sender prefix
 *      parv[1] = password
 *      parv[2] = optional extra version information
 */
static void
mr_pass(struct Client *client_p, struct Client *source_p,
        int parc, char *parv[])
{
    assert(client_p == source_p);

    if (EmptyString(parv[1]))
    {
        sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name,
                   source_p->name[0] ? source_p->name : "*", "PASS");
        return;
    }

    MyFree(source_p->localClient->passwd);
    source_p->localClient->passwd = xstrndup(parv[1], IRCD_MIN(strlen(parv[1]), PASSWDLEN));

    if (parc > 2)
    {
        /* It looks to me as if orabidoo wanted to have more
         * than one set of option strings possible here...
         * i.e. ":AABBTS" as long as TS was the last two chars
         * however, as we are now using CAPAB, I think we can
         * safely assume if there is a ":TS" then its a TS server
         * -Dianora
         */
        if (!irccmp(parv[2], "TS") && source_p->tsinfo == 0)
            source_p->tsinfo = TS_DOESTS;
    }

    /* only do this stuff if we are doing ts6 */
    if (parc > 4)
    {
        if (atoi(parv[3]) >= 6 && valid_sid(parv[4]))
        {
            strlcpy(source_p->id, parv[4], sizeof(source_p->id));
            SetCapable(source_p, CAP_TS6);
        }
    }
}
Esempio n. 10
0
void
fdlist_init(void)
{
  int fdmax;
  struct rlimit limit;

  if (!getrlimit(RLIMIT_NOFILE, &limit))
  {
    limit.rlim_cur = limit.rlim_max;
    setrlimit(RLIMIT_NOFILE, &limit);
  }

  fdmax = getdtablesize();

  /* allow MAXCLIENTS_MIN clients even at the cost of MAX_BUFFER and
   * some not really LEAKED_FDS */
  fdmax = IRCD_MAX(fdmax, LEAKED_FDS + MAX_BUFFER + MAXCLIENTS_MIN);

  /* under no condition shall this raise over 65536
   * for example user ip heap is sized 2*hard_fdlimit */
  hard_fdlimit = IRCD_MIN(fdmax, 65536);
}
Esempio n. 11
0
/*
 * ms_svsnick - server message handler
 * parv[0] = sender prefix
 * parv[1] = Target numeric
 * parv[2] = New nickname
 */
int ms_svsnick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Client* acptr = NULL;
  struct Client* acptr2 = NULL;
  char		 nick[NICKLEN + 2];
  char*		 arg;

  if (parc < 3)
    return need_more_params(sptr, "SVSNICK"); 

  if (!(acptr = findNUser(parv[1])))
    return 0; /* Ignore SVSNICK for a user that has quit */

  if (ircd_strcmp(cli_name(acptr), parv[2]) == 0)
    return 0; /* Nick already set to what SVSNICK wants, ignoring... */

  /*
   * Basic sanity checks
   */

  /*
   * Don't let them make us send back a really long string of
   * garbage
   */
  arg = parv[2];
  if (strlen(arg) > IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN)))
    arg[IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN))] = '\0';

  strcpy(nick, arg);

  /*
   * If do_nick_name() returns a null name then reject it.
   */
  if (0 == do_nick_name(nick))
    return 0;

  /*
   * Check if this is a LOCAL user trying to use a reserved (Juped)
   * nick, if so tell him that it's a nick in use...
   */
  if (isNickJuped(nick))
    return 0;                        /* NICK message ignored */

  if (feature_bool(FEAT_OPER_SINGLELETTERNICK) && !IsAnOper(acptr)
      && nick[1] == '\0')
    return 0;

  /*
   * Set acptr2 to the client pointer of any user with nick's name.
   * If the user is the same as the person being svsnick'ed, let it
   * through as it is probably a change in the nickname's case.
   */
  if ((acptr2 = FindClient(nick))) {
    /*
     * If acptr == acptr2, then we have a client doing a nick
     * change between *equivalent* nicknames as far as server
     * is concerned (user is changing the case of his/her
     * nickname or somesuch), so we let it through :)
     */
    if (acptr != acptr2) {
      /* Nick collision occured, kill user with specific reason */
      ++ServerStats->is_kill;
      /* ??? - Why do we use cptr here? */
      SetFlag(cptr, FLAG_KILLED);
      exit_client(cptr, acptr2, &me, "Killed (Nickname Enforcement)");
    }
  }

  set_nick_name(acptr, acptr, nick, parc, parv, 1);
  sendcmdto_serv_butone(sptr, CMD_SVSNICK, cptr, "%s %s", parv[1], nick);
  return 0;
}
Esempio n. 12
0
/** Handle a JOIN message from a client connection.
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Channel *chptr;
  struct JoinBuf join;
  struct JoinBuf create;
  struct Gline *gline;
  char *p = 0;
  char *chanlist;
  char *name;
  char *keys;

  if (parc < 2 || *parv[1] == '\0')
    return need_more_params(sptr, "JOIN");

  joinbuf_init(&join, sptr, cptr, JOINBUF_TYPE_JOIN, 0, 0);
  joinbuf_init(&create, sptr, cptr, JOINBUF_TYPE_CREATE, 0, TStime());

  chanlist = last0(cptr, sptr, parv[1]); /* find last "JOIN 0" */

  keys = parv[2]; /* remember where keys are */

  for (name = ircd_strtok(&p, chanlist, ","); name;
       name = ircd_strtok(&p, 0, ",")) {
    char *key = 0;

    /* If we have any more keys, take the first for this channel. */
    if (!BadPtr(keys)
        && (keys = strchr(key = keys, ',')))
      *keys++ = '\0';

    /* Empty keys are the same as no keys. */
    if (key && !key[0])
      key = 0;

    if (!IsChannelName(name) || !strIsIrcCh(name))
    {
      /* bad channel name */
      send_reply(sptr, ERR_NOSUCHCHANNEL, name);
      continue;
    }

    if (cli_user(sptr)->joined >= feature_int(FEAT_MAXCHANNELSPERUSER)
	&& !HasPriv(sptr, PRIV_CHAN_LIMIT)) {
      send_reply(sptr, ERR_TOOMANYCHANNELS, name);
      break; /* no point processing the other channels */
    }

    /* BADCHANed channel */
    if ((gline = gline_find(name, GLINE_BADCHAN | GLINE_EXACT)) &&
	GlineIsActive(gline) && !IsAnOper(sptr)) {
      send_reply(sptr, ERR_BANNEDFROMCHAN, name);
      continue;
    }

    if (!(chptr = FindChannel(name))) {
      if (((name[0] == '&') && !feature_bool(FEAT_LOCAL_CHANNELS))
          || strlen(name) > IRCD_MIN(CHANNELLEN, feature_int(FEAT_CHANNELLEN))) {
        send_reply(sptr, ERR_NOSUCHCHANNEL, name);
        continue;
      }

      if (!(chptr = get_channel(sptr, name, CGT_CREATE)))
        continue;

      /* Try to add the new channel as a recent target for the user. */
      if (check_target_limit(sptr, chptr, chptr->chname, 0)) {
        chptr->members = 0;
        destruct_channel(chptr);
        continue;
      }

      joinbuf_join(&create, chptr, CHFL_CHANOP | CHFL_CHANNEL_MANAGER);
    } else if (find_member_link(chptr, sptr)) {
      continue; /* already on channel */
    } else if (check_target_limit(sptr, chptr, chptr->chname, 0)) {
      continue;
    } else {
      int flags = CHFL_DEOPPED;
      int err = 0;

      /* Check Apass/Upass -- since we only ever look at a single
       * "key" per channel now, this hampers brute force attacks. */
      if (key && !strcmp(key, chptr->mode.apass))
        flags = CHFL_CHANOP | CHFL_CHANNEL_MANAGER;
      else if (key && !strcmp(key, chptr->mode.upass))
        flags = CHFL_CHANOP;
      else if (chptr->users == 0 && !chptr->mode.apass[0]) {
        /* Joining a zombie channel (zannel): give ops and increment TS. */
        flags = CHFL_CHANOP;
        chptr->creationtime++;
      } else if (IsInvited(sptr, chptr)) {
        /* Invites bypass these other checks. */
      } else if (chptr->mode.mode & MODE_INVITEONLY)
        err = ERR_INVITEONLYCHAN;
      else if (chptr->mode.limit && (chptr->users >= chptr->mode.limit))
        err = ERR_CHANNELISFULL;
      else if ((chptr->mode.mode & MODE_REGONLY) && !IsAccount(sptr))
        err = ERR_NEEDREGGEDNICK;
      else if (find_ban(sptr, chptr->banlist))
        err = ERR_BANNEDFROMCHAN;
      else if (*chptr->mode.key && (!key || strcmp(key, chptr->mode.key)))
        err = ERR_BADCHANNELKEY;

      /* An oper with WALK_LCHAN privilege can join a local channel
       * he otherwise could not join by using "OVERRIDE" as the key.
       * This will generate a HACK(4) notice, but fails if the oper
       * could normally join the channel. */
      if (IsLocalChannel(chptr->chname)
          && HasPriv(sptr, PRIV_WALK_LCHAN)
          && !(flags & CHFL_CHANOP)
          && key && !strcmp(key, "OVERRIDE"))
      {
        switch (err) {
        case 0:
          if (strcmp(chptr->mode.key, "OVERRIDE")
              && strcmp(chptr->mode.apass, "OVERRIDE")
              && strcmp(chptr->mode.upass, "OVERRIDE")) {
            send_reply(sptr, ERR_DONTCHEAT, chptr->chname);
            continue;
          }
          break;
        case ERR_INVITEONLYCHAN: err = 'i'; break;
        case ERR_CHANNELISFULL:  err = 'l'; break;
        case ERR_BANNEDFROMCHAN: err = 'b'; break;
        case ERR_BADCHANNELKEY:  err = 'k'; break;
        case ERR_NEEDREGGEDNICK: err = 'r'; break;
        default: err = '?'; break;
        }
        /* send accountability notice */
        if (err)
          sendto_opmask_butone(0, SNO_HACK4, "OPER JOIN: %C JOIN %H "
                               "(overriding +%c)", sptr, chptr, err);
        err = 0;
      }

      /* Is there some reason the user may not join? */
      if (err) {
        switch(err) {
          case ERR_NEEDREGGEDNICK:
            send_reply(sptr, 
                       ERR_NEEDREGGEDNICK, 
                       chptr->chname, 
                       feature_str(FEAT_URLREG));            
            break;
          default:
            send_reply(sptr, err, chptr->chname);
            break;
        }
        continue;
      }

      joinbuf_join(&join, chptr, flags);
      if (flags & CHFL_CHANOP) {
        struct ModeBuf mbuf;
	/* Always let the server op him: this is needed on a net with older servers
	   because they 'destruct' channels immediately when they become empty without
	   sending out a DESTRUCT message. As a result, they would always bounce a mode
	   (as HACK(2)) when the user ops himself.
           (There is also no particularly good reason to have the user op himself.)
        */
	modebuf_init(&mbuf, &me, cptr, chptr, MODEBUF_DEST_SERVER);
	modebuf_mode_client(&mbuf, MODE_ADD | MODE_CHANOP, sptr,
                            chptr->mode.apass[0] ? ((flags & CHFL_CHANNEL_MANAGER) ? 0 : 1) : MAXOPLEVEL);
	modebuf_flush(&mbuf);
      }
    }

    del_invite(sptr, chptr);

    if (chptr->topic[0]) {
      send_reply(sptr, RPL_TOPIC, chptr->chname, chptr->topic);
      send_reply(sptr, RPL_TOPICWHOTIME, chptr->chname, chptr->topic_nick,
		 chptr->topic_time);
    }

    do_names(sptr, chptr, NAMES_ALL|NAMES_EON); /* send /names list */
  }

  joinbuf_flush(&join); /* must be first, if there's a JOIN 0 */
  joinbuf_flush(&create);

  return 0;
}
Esempio n. 13
0
/*! \brief NICK command handler (called by already registered,
 *         locally connected clients)
 *
 * \param client_p Pointer to allocated Client struct with physical connection
 *                 to this server, i.e. with an open socket connected.
 * \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] = sender prefix
 *      - parv[1] = nickname
 */
static void
m_nick(struct Client *client_p, struct Client *source_p,
       int parc, char *parv[])
{
  char nick[NICKLEN + 1] = { '\0' };
  struct Client *target_p = NULL;
  struct MaskItem *conf = NULL;

  assert(source_p == client_p);

  if (parc < 2 || EmptyString(parv[1]))
  {
    sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN),
               me.name, source_p->name);
    return;
  }

  /* mark end of grace period, to prevent nickflooding */
  if (!IsFloodDone(source_p))
    flood_endgrace(source_p);

  /* terminate nick to NICKLEN */
  strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ServerInfo.max_nick_length + 1));

  /* check the nickname is ok */
  if (!valid_nickname(nick, 1))
  {
    sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name,
               source_p->name, nick, "Erroneous Nickname");
    return;
  }

  if (!IsExemptResv(source_p) &&
      !(HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.oper_pass_resv) &&
      (conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0)))
  {
    ++conf->count;
    sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
               me.name, source_p->name, nick, conf->reason);
    sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
                         "Forbidding reserved nick [%s] from user %s",
                         nick, get_client_name(client_p, HIDE_IP));
    return;
  }

  if ((target_p = hash_find_client(nick)) == NULL)
    change_local_nick(source_p, nick);
  else if (target_p == source_p)
  {
    /*
     * If (target_p == source_p) the client is changing nicks between
     * equivalent nicknames ie: [nick] -> {nick}
     */

    /* Check the nick isn't exactly the same */
    if (strcmp(target_p->name, nick))
      change_local_nick(source_p, nick);
  }
  else if (IsUnknown(target_p))
  {
    /*
     * If the client that has the nick isn't registered yet (nick but no
     * user) then drop the unregged client
     */
    exit_client(target_p, &me, "Overridden");
    change_local_nick(source_p, nick);
  }
  else
    sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name,
               source_p->name, nick);
}
Esempio n. 14
0
void do_join(struct Client *cptr, struct Client *sptr, struct JoinBuf *join,
             struct JoinBuf *create, char *chan, char *key, int level)
{
  struct Channel *chptr;
  struct Gline *gline;

  /* BADCHANed channel */
  if ((gline = gline_find(chan, GLINE_BADCHAN | GLINE_EXACT)) &&
      GlineIsActive(gline) && !IsAnOper(sptr)) {
    send_reply(sptr, ERR_BANNEDFROMCHAN, chan);
    return;
  }

  /* Bouncy +L joins */
  if (level > feature_int(FEAT_MAX_BOUNCE)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :*** Couldn't join %s ! - Redirection (+L) setting was too bouncy", sptr, chan);
    return;
  }

  if (!(chptr = FindChannel(chan))) {
    if (((chan[0] == '&') && !feature_bool(FEAT_LOCAL_CHANNELS))
        || strlen(chan) > IRCD_MIN(CHANNELLEN, feature_int(FEAT_CHANNELLEN))) {
      send_reply(sptr, ERR_NOSUCHCHANNEL, chan);
      return;
    }

    if (feature_bool(FEAT_CHANNEL_CREATE_IRCOPONLY) && !IsAnOper(sptr) && !IsChannelService(sptr)) {
      send_reply(sptr, ERR_NOSUCHCHANNEL, chan);
      return;
    }

    if (!(chptr = get_channel(sptr, chan, CGT_CREATE)))
      return;

    /* Try to add the new channel as a recent target for the user. */
    if (check_target_limit(sptr, chptr, chptr->chname, 0)) {
      chptr->members = 0;
      destruct_channel(chptr);
      return;
    }

    joinbuf_join(create, chptr, CHFL_CHANOP | CHFL_CHANNEL_MANAGER);
  } else if (find_member_link(chptr, sptr)) {
    return; /* already on channel */
  } else if (check_target_limit(sptr, chptr, chptr->chname, 0)) {
    return;
  } else {
    int flags = CHFL_DEOPPED;
    int err = 0;
    int excepted = 0;
    int exceptkli = 0;
    struct Ban *ban = NULL;

    if (*chptr->mode.redir && (*chptr->mode.redir != '\0')) {
      if (chptr->users >= chptr->mode.limit) {
        if (IsNoLink(sptr))
          send_reply(sptr, ERR_LINKCHAN, chptr->chname, chptr->mode.redir);
        else if (!IsChannelName(chptr->mode.redir) || !strIsIrcCh(chptr->mode.redir))
          send_reply(sptr, ERR_NOSUCHCHANNEL, chptr->mode.redir);
        else {
          send_reply(sptr, ERR_LINKSET, chptr->chname, chptr->chname, chptr->mode.redir);
          do_join(cptr, sptr, join, create, chptr->mode.redir, key, level+1);
        }
        return;
      }
    }

    if (find_ban(sptr, chptr->exceptlist, EBAN_EXCEPTLIST, 0)) {
      if (feature_bool(FEAT_CHMODE_e_CHMODEEXCEPTION))
        exceptkli = 1;
      excepted = 1;
    }

    /* Check Apass/Upass -- since we only ever look at a single
     * "key" per channel now, this hampers brute force attacks. */
    if (feature_bool(FEAT_CHMODE_Z_STRICT) && (chptr->mode.exmode & EXMODE_SSLONLY) && !IsSSL(sptr))
      err = ERR_SSLONLYCHAN;
    else if (key && !strcmp(key, chptr->mode.apass))
      flags = CHFL_CHANOP | CHFL_CHANNEL_MANAGER;
    else if (key && !strcmp(key, chptr->mode.upass))
      flags = CHFL_CHANOP;
    else if (chptr->users == 0 && !chptr->mode.apass[0] && !(chptr->mode.exmode & EXMODE_PERSIST)) {
      /* Joining a zombie channel (zannel): give ops and increment TS. */
      flags = CHFL_CHANOP;
      chptr->creationtime++;
    } else if (IsXtraOp(sptr)) {
      /* XtraOp bypasses all other checks. */
    } else if ((chptr->mode.exmode & EXMODE_SSLONLY) && !IsSSL(sptr))
      err = ERR_SSLONLYCHAN;
    else if (IsInvited(sptr, chptr)) {
      /* Invites bypass these other checks. */
    } else if (*chptr->mode.key && (!key || strcmp(key, chptr->mode.key)) && !exceptkli)
      err = ERR_BADCHANNELKEY;
    else if (*chptr->mode.key && feature_bool(FEAT_FLEXIBLEKEYS) && (key && !strcmp(key, chptr->mode.key))) {
      /* Assume key checked by previous condition was found to be correct
         and allow join because FEAT_FLEXIBLEKEYS was enabled */
    } else if ((chptr->mode.mode & MODE_INVITEONLY) && !exceptkli)
      err = ERR_INVITEONLYCHAN;
    else if (chptr->mode.limit && (chptr->users >= chptr->mode.limit) && !exceptkli)
      err = ERR_CHANNELISFULL;
    else if ((chptr->mode.mode & MODE_REGONLY) && !IsAccount(sptr))
      err = ERR_NEEDREGGEDNICK;
    else if ((chptr->mode.exmode & EXMODE_ADMINONLY) && !IsAdmin(sptr))
      err = ERR_ADMINONLYCHAN;
    else if ((chptr->mode.exmode & EXMODE_OPERONLY) && !IsAnOper(sptr))
      err = ERR_OPERONLYCHAN;
    else if ((ban = find_ban(sptr, chptr->banlist, EBAN_NONE, 0)) && !excepted)
      err = ERR_BANNEDFROMCHAN;

    /* An oper with WALK_LCHAN privilege can join a local channel
     * he otherwise could not join by using "OVERRIDE" as the key.
     * This will generate a HACK(4) notice, but fails if the oper
     * could normally join the channel. */
    if (IsLocalChannel(chptr->chname)
        && HasPriv(sptr, PRIV_WALK_LCHAN)
        && !(flags & CHFL_CHANOP)
        && key && !strcmp(key, "OVERRIDE"))
    {
      switch (err) {
      case 0:
        if (strcmp(chptr->mode.key, "OVERRIDE")
            && strcmp(chptr->mode.apass, "OVERRIDE")
            && strcmp(chptr->mode.upass, "OVERRIDE")) {
          send_reply(sptr, ERR_DONTCHEAT, chptr->chname);
          return;
        }
        break;
      case ERR_INVITEONLYCHAN: err = 'i'; break;
      case ERR_CHANNELISFULL:  err = 'l'; break;
      case ERR_BANNEDFROMCHAN: err = 'b'; break;
      case ERR_BADCHANNELKEY:  err = 'k'; break;
      case ERR_NEEDREGGEDNICK: err = 'r'; break;
      case ERR_ADMINONLYCHAN:  err = 'a'; break;
      case ERR_OPERONLYCHAN:   err = 'O'; break;
      case ERR_SSLONLYCHAN:    err = 'Z'; break;
      default: err = '?'; break;
      }
      /* send accountability notice */
      if (err)
        sendto_opmask_butone(0, SNO_HACK4, "OPER JOIN: %C JOIN %H "
                             "(overriding +%c)", sptr, chptr, err);
      err = 0;
    }

    /* Is there some reason the user may not join? */
    if (err) {
      switch(err) {
        case ERR_NEEDREGGEDNICK:
          send_reply(sptr,
                     ERR_NEEDREGGEDNICK,
                     chptr->chname,
                     feature_str(FEAT_URLREG));
          break;
        default:
          send_reply(sptr, err, chptr->chname);
          break;
      }
      return;
    }

    joinbuf_join(join, chptr, flags);
    if (flags & CHFL_CHANOP) {
      struct ModeBuf mbuf;
      /* Always let the server op him: this is needed on a net with older servers
         because they 'destruct' channels immediately when they become empty without
         sending out a DESTRUCT message. As a result, they would always bounce a mode
         (as HACK(2)) when the user ops himself.
         (There is also no particularly good reason to have the user op himself.)
      */
      modebuf_init(&mbuf, &me, cptr, chptr, MODEBUF_DEST_SERVER);
      modebuf_mode_client(&mbuf, MODE_ADD | MODE_CHANOP, sptr,
                          chptr->mode.apass[0] ? ((flags & CHFL_CHANNEL_MANAGER) ? 0 : 1) : MAXOPLEVEL);
      modebuf_flush(&mbuf);
    }
  }

  del_invite(sptr, chptr);

  if (chptr->topic[0]) {
    send_reply(sptr, RPL_TOPIC, chptr->chname, chptr->topic);
    send_reply(sptr, RPL_TOPICWHOTIME, chptr->chname, chptr->topic_nick,
               chptr->topic_time);
  }

  do_names(sptr, chptr, NAMES_ALL|NAMES_EON); /* send /names list */
}
Esempio n. 15
0
/*! \brief NICK 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] = nickname
 */
static int
m_nick(struct Client *source_p, int parc, char *parv[])
{
  char nick[NICKLEN + 1] = "";
  struct Client *target_p = NULL;
  struct MaskItem *conf = NULL;

  assert(MyClient(source_p));

  if (parc < 2 || EmptyString(parv[1]))
  {
    sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN);
    return 0;
  }

  /* Mark end of grace period, to prevent nickflooding */
  if (!IsFloodDone(source_p))
    flood_endgrace(source_p);

  /* Terminate nick to NICKLEN */
  strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ConfigServerInfo.max_nick_length + 1));

  /* Check the nickname is ok */
  if (!valid_nickname(nick, 1))
  {
    sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, "Erroneous Nickname");
    return 0;
  }

  if (!HasFlag(source_p, FLAGS_EXEMPTRESV) &&
      !(HasUMode(source_p, UMODE_OPER) && HasOFlag(source_p, OPER_FLAG_NICK_RESV)) &&
      (conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0)))
  {
    ++conf->count;
    sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, conf->reason);
    sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
                         "Forbidding reserved nick %s from user %s",
                         nick, get_client_name(source_p, HIDE_IP));
    return 0;
  }

  if ((target_p = hash_find_client(nick)) == NULL)
    change_local_nick(source_p, nick);
  else if (target_p == source_p)
  {
    /*
     * If (target_p == source_p) the client is changing nicks between
     * equivalent nicknames ie: [nick] -> {nick}
     */

    /* Check the nick isn't exactly the same */
    if (strcmp(target_p->name, nick))
      change_local_nick(source_p, nick);
  }
  else if (IsUnknown(target_p))
  {
    /*
     * If the client that has the nick isn't registered yet (nick but no
     * user) then drop the unregged client
     */
    exit_client(target_p, "Overridden by other sign on");
    change_local_nick(source_p, nick);
  }
  else
    sendto_one_numeric(source_p, &me, ERR_NICKNAMEINUSE, target_p->name);

  return 0;
}
Esempio n. 16
0
/*
 * m_nick - message handler for local clients
 * parv[0] = sender prefix
 * parv[1] = nickname
 */
int m_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Client* acptr;
  char           nick[NICKLEN + 2];
  char*          arg;
  char*          s;
  const char*    client_name;

  assert(0 != cptr);
  assert(cptr == sptr);

  if (IsServerPort(cptr))
    return exit_client(cptr, cptr, &me, "Use a different port");

  /*
   * parv[0] will be empty for clients connecting for the first time
   */
  client_name = (*(cli_name(sptr))) ? cli_name(sptr) : "*";

  if (parc < 2) {
    send_reply(sptr, ERR_NONICKNAMEGIVEN);
    return 0;
  }

  /*
   * Don't let them send make us send back a really long string of
   * garbage
   */
  arg = parv[1];
  if (strlen(arg) > IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN)))
    arg[IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN))] = '\0';

  if ((s = strchr(arg, '~')))
    *s = '\0';

  strcpy(nick, arg);

  /*
   * If do_nick_name() returns a null name then reject it.
   */
  if (0 == do_nick_name(nick)) {
    send_reply(sptr, ERR_ERRONEUSNICKNAME, arg);
    return 0;
  }

  /* 
   * Check if this is a LOCAL user trying to use a reserved (Juped)
   * nick, if so tell him that it's a nick in use...
   */
  if (isNickJuped(nick)) {
    send_reply(sptr, ERR_NICKNAMEINUSE, nick);
    return 0;                        /* NICK message ignored */
  }

  if (!(acptr = FindClient(nick))) {
    /*
     * No collisions, all clear...
     */
    return set_nick_name(cptr, sptr, nick, parc, parv);
  }
  if (IsServer(acptr)) {
    send_reply(sptr, ERR_NICKNAMEINUSE, nick);
    return 0;                        /* NICK message ignored */
  }
  /*
   * If acptr == sptr, then we have a client doing a nick
   * change between *equivalent* nicknames as far as server
   * is concerned (user is changing the case of his/her
   * nickname or somesuch)
   */
  if (acptr == sptr) {
    /*
     * If acptr == sptr, then we have a client doing a nick
     * change between *equivalent* nicknames as far as server
     * is concerned (user is changing the case of his/her
     * nickname or somesuch)
     */
    if (0 != strcmp(cli_name(acptr), nick)) {
      /*
       * Allows change of case in his/her nick
       */
      return set_nick_name(cptr, sptr, nick, parc, parv);
    }
    /*
     * This is just ':old NICK old' type thing.
     * Just forget the whole thing here. There is
     * no point forwarding it to anywhere,
     * especially since servers prior to this
     * version would treat it as nick collision.
     */
    return 0;
  }
  /*
   * Note: From this point forward it can be assumed that
   * acptr != sptr (point to different client structures).
   */
  assert(acptr != sptr);
  /*
   * If the older one is "non-person", the new entry is just
   * allowed to overwrite it. Just silently drop non-person,
   * and proceed with the nick. This should take care of the
   * "dormant nick" way of generating collisions...
   *
   * XXX - hmmm can this happen after one is registered?
   *
   * Yes, client 1 connects to IRC and registers, client 2 connects and
   * sends "NICK foo" but doesn't send anything more.  client 1 now does
   * /nick foo, they should succeed and client 2 gets disconnected with
   * the message below.
   */
  if (IsUnknown(acptr) && MyConnect(acptr)) {
    ServerStats->is_ref++;
    IPcheck_connect_fail(acptr);
    exit_client(cptr, acptr, &me, "Overridden by other sign on");
    return set_nick_name(cptr, sptr, nick, parc, parv);
  }
  /*
   * NICK is coming from local client connection. Just
   * send error reply and ignore the command.
   */
  send_reply(sptr, ERR_NICKNAMEINUSE, nick);
  return 0;                        /* NICK message ignored */
}
Esempio n. 17
0
static time_t io_loop(time_t delay)
{
  static char   to_send[200];
  static time_t lasttime  = 0;
  static long   lastrecvK = 0;
  static int    lrv       = 0;
  time_t        lasttimeofday;
  lasttimeofday = CurrentTime;

  if (CurrentTime < lasttimeofday)
    {
      ircsprintf(to_send, "System clock is running backwards - (%d < %d)",
                 CurrentTime, lasttimeofday);
      report_error(to_send, me.name, 0);
    }
  if(!next_gc)
    {
  	next_gc = CurrentTime + 600;
    }

  /*
   * This chunk of code determines whether or not
   * "life sucks", that is to say if the traffic
   * level is so high that standard server
   * commands should be restricted
   *
   * Changed by Taner so that it tells you what's going on
   * as well as allows forced on (long LCF), etc...
   */
  
  if ((CurrentTime - lasttime) >= LCF)
    {
      lrv = LRV * LCF;
      lasttime = CurrentTime;
      currlife = (float)((long)me.receiveK - lastrecvK)/(float)LCF;
      if (((long)me.receiveK - lrv) > lastrecvK )
        {
          if (!LIFESUX)
            {
              LIFESUX = 1;

              if (NOISYHTM)
                {
                  sprintf(to_send, 
                        "Entering high-traffic mode - (%.1fk/s > %dk/s)",
                                (float)currlife, LRV);
                  sendto_ops("%s", to_send);
                }
            }
          else
            {
              LIFESUX++;                /* Ok, life really sucks! */
              LCF += 2;                 /* Wait even longer */
              if (NOISYHTM) 
                {
                  sprintf(to_send,
                        "Still high-traffic mode %d%s (%d delay): %.1fk/s",
                                LIFESUX,
                                (LIFESUX & 0x04) ?  " (TURBO)" : "",
                                (int)LCF, (float)currlife);
                  sendto_ops("%s", to_send);
                }
            }
        }
      else
        {
          LCF = LOADCFREQ;
          if (LIFESUX)
            {
              LIFESUX = 0;
              if (NOISYHTM)
                sendto_ops("Resuming standard operation . . . .");
            }
        }
      lastrecvK = (long)me.receiveK;
    }

  /*
  ** We only want to connect if a connection is due,
  ** not every time through.  Note, if there are no
  ** active C lines, this call to Tryconnections is
  ** made once only; it will return 0. - avalon
  */
  if (nextconnect && CurrentTime >= nextconnect)
    nextconnect = try_connections(CurrentTime);

  /*
  ** take the smaller of the two 'timed' event times as
  ** the time of next event (stops us being late :) - avalon
  ** WARNING - nextconnect can return 0!
  */
  if (nextconnect)
    delay = IRCD_MIN(nextping, nextconnect);
  delay -= CurrentTime;
  /*
  ** Adjust delay to something reasonable [ad hoc values]
  ** (one might think something more clever here... --msa)
  ** We don't really need to check that often and as long
  ** as we don't delay too long, everything should be ok.
  ** waiting too long can cause things to timeout...
  ** i.e. PINGS -> a disconnection :(
  ** - avalon
  */
  if (delay < 1)
    delay = 1;
  else
    delay = IRCD_MIN(delay, TIMESEC);
  /*
   * We want to read servers on every io_loop, as well
   * as "busy" clients (which again, includes servers.
   * If "lifesux", then we read servers AGAIN, and then
   * flush any data to servers.
   *    -Taner
   */

#ifndef NO_PRIORITY
  read_message(0, FDL_SERVER);
  read_message(0, FDL_BUSY);
  if (LIFESUX)
    {
      read_message(0, FDL_SERVER);
      if (LIFESUX & 0x4)
        {       /* life really sucks */
          read_message(0, FDL_BUSY);
          read_message(0, FDL_SERVER);
        }
      flush_server_connections();
    }

  /*
   * CLIENT_SERVER = TRUE:
   *    If we're in normal mode, or if "lifesux" and a few
   *    seconds have passed, then read everything.
   * CLIENT_SERVER = FALSE:
   *    If it's been more than lifesux*2 seconds (that is, 
   *    at most 1 second, or at least 2s when lifesux is
   *    != 0) check everything.
   *    -Taner
   */
  {
    static time_t lslasttime=0;
#ifdef CLIENT_SERVER
    if (!LIFESUX || (lslasttime + LIFESUX) < CurrentTime)
      {
#else
    if ((lslasttime + (LIFESUX + 1)) < CurrentTime)
      {
#endif
        read_message(0, FDL_ALL); /*  check everything! */
        lslasttime = CurrentTime;
      }
   }
#else
  read_message(0, FDL_ALL); /*  check everything! */
  flush_server_connections();
#endif

  /*
  ** ...perhaps should not do these loops every time,
  ** but only if there is some chance of something
  ** happening (but, note that conf->hold times may
  ** be changed elsewhere--so precomputed next event
  ** time might be too far away... (similarly with
  ** ping times) --msa
  */

  if (CurrentTime >= nextping) {
    nextping = check_pings(CurrentTime);
    timeout_auth_queries(CurrentTime);
  }

  if (dorehash && !LIFESUX)
    {
      rehash(&me, &me, 1);
      dorehash = 0;
    }
  /*
  ** Flush output buffers on all connections now if they
  ** have data in them (or at least try to flush)
  ** -avalon
  */
  flush_connections(0);

#ifndef NO_PRIORITY
  fdlist_check(CurrentTime);
#endif
  
  if(CurrentTime >= next_gc)
  {
     block_garbage_collect();
     next_gc = CurrentTime + 600;
  }

  return delay;

}

/*
 * initalialize_global_set_options
 *
 * inputs       - none
 * output       - none
 * side effects - This sets all global set options needed 
 */

static void initialize_global_set_options(void)
{
  memset( &GlobalSetOptions, 0, sizeof(GlobalSetOptions));

  MAXCLIENTS = MAX_CLIENTS;
  NOISYHTM = NOISY_HTM;
  GlobalSetOptions.autoconn = 1;

#ifdef FLUD
  FLUDNUM = FLUD_NUM;
  FLUDTIME = FLUD_TIME;
  FLUDBLOCK = FLUD_BLOCK;
#endif

#ifdef IDLE_CHECK
  IDLETIME = MIN_IDLETIME;
#endif

#ifdef ANTI_SPAMBOT
  SPAMTIME = MIN_JOIN_LEAVE_TIME;
  SPAMNUM = MAX_JOIN_LEAVE_COUNT;
#endif

#ifdef ANTI_DRONE_FLOOD
  DRONETIME = DEFAULT_DRONE_TIME;
  DRONECOUNT = DEFAULT_DRONE_COUNT;
#endif

#ifdef NEED_SPLITCODE
 SPLITDELAY = (DEFAULT_SERVER_SPLIT_RECOVERY_TIME * 60);
 SPLITNUM = SPLIT_SMALLNET_SIZE;
 SPLITUSERS = SPLIT_SMALLNET_USER_SIZE;
 server_split_time = CurrentTime;
#endif

 /* End of global set options */

}