示例#1
0
/*! \brief AWAY 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] = away message
 */
static int
ms_away(struct Client *source_p, int parc, char *parv[])
{
  const char *const message = parv[1];

  if (EmptyString(message))
  {
    /* Marking as not away */
    if (source_p->away[0])
    {
      source_p->away[0] = '\0';

      /* We now send this only if they were away before --is */
      sendto_server(source_p, 0, 0, ":%s AWAY", source_p->id);
      sendto_common_channels_local(source_p, 1, CAP_AWAY_NOTIFY, ":%s!%s@%s AWAY",
                                   source_p->name, source_p->username,
                                   source_p->host);
    }

    return 0;
  }

  strlcpy(source_p->away, message, sizeof(source_p->away));

  sendto_common_channels_local(source_p, 1, CAP_AWAY_NOTIFY, ":%s!%s@%s AWAY :%s",
                               source_p->name, source_p->username,
                               source_p->host, source_p->away);
  sendto_server(source_p, 0, 0, ":%s AWAY :%s",
                source_p->id, source_p->away);
  return 0;
}
/*
 * m_away
 *  parv[0] = sender prefix
 *  parv[1] = away message
 */
static void
m_away(struct Client *client_p, struct Client *source_p,
       int parc, char *parv[])
{
  if (!IsFloodDone(source_p))
    flood_endgrace(source_p);

  if (parc < 2 || EmptyString(parv[1]))
  {
    /* Marking as not away */
    if (source_p->away[0])
    {
      source_p->away[0] = '\0';
      /* we now send this only if they were away before --is */
      sendto_server(client_p, CAP_TS6, NOCAPS,
                    ":%s AWAY", ID(source_p));
      sendto_server(client_p, NOCAPS, CAP_TS6,
                    ":%s AWAY", source_p->name);
      sendto_common_channels_local(source_p, 1, CAP_AWAY_NOTIFY,
                                   ":%s!%s@%s AWAY",
                                   source_p->name, source_p->username,
                                   source_p->host);
    }

    sendto_one(source_p, form_str(RPL_UNAWAY),
               me.name, source_p->name);
    return;
  }

  if ((CurrentTime - source_p->localClient->last_away) < ConfigFileEntry.pace_wait)
  {
    sendto_one(source_p, form_str(RPL_LOAD2HI),
               me.name, source_p->name);
    return;
  }

  source_p->localClient->last_away = CurrentTime;
  sendto_one(source_p, form_str(RPL_NOWAWAY), me.name, source_p->name);

  if (!strncmp(source_p->away, parv[1], sizeof(source_p->away) - 1))
    return;

  strlcpy(source_p->away, parv[1], sizeof(source_p->away));

  sendto_common_channels_local(source_p, 1, CAP_AWAY_NOTIFY,
                               ":%s!%s@%s AWAY :%s",
                               source_p->name, source_p->username,
                               source_p->host, source_p->away);
  sendto_server(client_p, CAP_TS6, NOCAPS,
                ":%s AWAY :%s", ID(source_p), source_p->away);
  sendto_server(client_p, NOCAPS, CAP_TS6,
                ":%s AWAY :%s", source_p->name, source_p->away);
}
示例#3
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);
}
示例#4
0
/*! \brief AWAY 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] = away message
 */
static int
m_away(struct Client *source_p, int parc, char *parv[])
{
  const char *const message = parv[1];

  if (EmptyString(message))
  {
    /* Marking as not away */
    if (source_p->away[0])
    {
      source_p->away[0] = '\0';

      /* We now send this only if they were away before --is */
      sendto_server(source_p, 0, 0, ":%s AWAY", source_p->id);
      sendto_common_channels_local(source_p, 1, CAP_AWAY_NOTIFY, ":%s!%s@%s AWAY",
                                   source_p->name, source_p->username,
                                   source_p->host);
    }

    sendto_one_numeric(source_p, &me, RPL_UNAWAY);
    return 0;
  }

  if ((source_p->connection->away.last_attempt + ConfigGeneral.away_time) < CurrentTime)
    source_p->connection->away.count = 0;

  if (source_p->connection->away.count > ConfigGeneral.away_count)
  {
    sendto_one_numeric(source_p, &me, ERR_TOOMANYAWAY);
    return 0;
  }

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

  strlcpy(source_p->away, message, sizeof(source_p->away));

  sendto_one_numeric(source_p, &me, RPL_NOWAWAY);
  sendto_common_channels_local(source_p, 1, CAP_AWAY_NOTIFY, ":%s!%s@%s AWAY :%s",
                               source_p->name, source_p->username,
                               source_p->host, source_p->away);
  sendto_server(source_p, 0, 0, ":%s AWAY :%s",
                source_p->id, source_p->away);
  return 0;
}
static void
ms_away(struct Client *client_p, struct Client *source_p,
        int parc, char *parv[])
{
  if (parc < 2 || EmptyString(parv[1]))
  {
    /* Marking as not away */
    if (source_p->away[0])
    {
      source_p->away[0] = '\0';
      /* we now send this only if they were away before --is */
      sendto_server(client_p, CAP_TS6, NOCAPS,
                    ":%s AWAY", ID(source_p));
      sendto_server(client_p, NOCAPS, CAP_TS6,
                    ":%s AWAY", source_p->name);
      sendto_common_channels_local(source_p, 1, CAP_AWAY_NOTIFY,
                                   ":%s!%s@%s AWAY",
                                   source_p->name, source_p->username,
                                   source_p->host);
    }

    return;
  }

  if (!strncmp(source_p->away, parv[1], sizeof(source_p->away) - 1))
    return;

  strlcpy(source_p->away, parv[1], sizeof(source_p->away));

  sendto_common_channels_local(source_p, 1, CAP_AWAY_NOTIFY,
                               ":%s!%s@%s AWAY :%s",
                               source_p->name, source_p->username,
                               source_p->host, source_p->away);
  sendto_server(client_p, CAP_TS6, NOCAPS,
                ":%s AWAY :%s", ID(source_p), source_p->away);
  sendto_server(client_p, NOCAPS, CAP_TS6,
                ":%s AWAY :%s", source_p->name, source_p->away);
}
示例#6
0
static int
change_nick(struct Client *client_p, const char *newnick)
{
	char note[NICKLEN + 10];

	client_p->tsinfo = rb_current_time();

	monitor_signoff(client_p);

	invalidate_bancache_user(client_p);

	sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
			"Forced nick change: From %s to %s [%s@%s]",
			client_p->name, newnick, client_p->username,
			client_p->host);

	sendto_common_channels_local(client_p, NOCAPS, ":%s!%s@%s NICK :%s",
				client_p->name, client_p->username,
				client_p->host, newnick);

	add_history(client_p, 1);
	sendto_server(NULL, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld",
			use_id(client_p), newnick, (long) client_p->tsinfo);

	del_from_client_hash(client_p->name, client_p);
	strcpy(client_p->name, newnick);
	add_to_client_hash(client_p->name, client_p);

	monitor_signon(client_p);

	del_all_accepts(client_p);

	rb_snprintf(note, NICKLEN + 10, "Nick: %s", client_p->name);
	rb_note(client_p->localClient->F, note);
	return 0;
}
示例#7
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);
}
示例#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)
{
  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);
}
示例#9
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);
}
示例#10
0
/*! \brief SVSMODE 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
 *      - parv[2] = TS
 *      - parv[3] = mode
 *      - parv[4] = optional argument (services account, vhost)
 */
static int
ms_svsmode(struct Client *source_p, int parc, char *parv[])
{
  const struct user_modes *tab = NULL;
  struct Client *target_p = NULL;
  int what = MODE_ADD;
  unsigned int setmodes = 0;
  const char *modes = NULL, *extarg = NULL;
  time_t ts = 0;

  if (!HasFlag(source_p, FLAGS_SERVICE))
    return 0;

  modes  = parv[3];
  extarg = (parc > 4) ? parv[4] : NULL;

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

  ts = atol(parv[2]);
  if (ts && (ts != target_p->tsinfo))
    return 0;

  setmodes = target_p->umodes;

  for (const char *m = modes; *m; ++m)
  {
    switch (*m)
    {
      case '+':
        what = MODE_ADD;
        break;
      case '-':
        what = MODE_DEL;
        break;

      case 'd':
        if (!EmptyString(extarg))
        {
          strlcpy(target_p->account, extarg, sizeof(target_p->account));
          sendto_common_channels_local(target_p, 1, CAP_ACCOUNT_NOTIFY, ":%s!%s@%s ACCOUNT %s",
                                       target_p->name, target_p->username,
                                       target_p->host, target_p->account);
        }

        break;

      case 'x':
        if (!EmptyString(extarg) && valid_hostname(extarg))
          user_set_hostmask(target_p, extarg, what);
        break;

      case 'o':
        if (what == MODE_DEL && HasUMode(target_p, UMODE_OPER))
        {
          ClearOper(target_p);
          --Count.oper;

          if (MyConnect(target_p))
          {
            dlink_node *node = NULL;

            detach_conf(target_p, CONF_OPER);
            ClrOFlag(target_p);
            DelUMode(target_p, ConfigGeneral.oper_only_umodes);

            if ((node = dlinkFindDelete(&oper_list, target_p)))
              free_dlink_node(node);
          }
        }

        break;

      case 'i':
        if (what == MODE_ADD && !HasUMode(target_p, UMODE_INVISIBLE))
        {
          AddUMode(target_p, UMODE_INVISIBLE);
          ++Count.invisi;
        }

        if (what == MODE_DEL && HasUMode(target_p, UMODE_INVISIBLE))
        {
          DelUMode(target_p, UMODE_INVISIBLE);
          --Count.invisi;
        }

        break;

      case 'S':  /* Only servers may set +S in a burst */
      case 'W':  /* Only servers may set +W in a burst */
        break;

      default:
        if ((tab = umode_map[(unsigned char)*m]))
        {
          if (what == MODE_ADD)
            AddUMode(target_p, tab->flag);
          else
            DelUMode(target_p, tab->flag);
        }

        break;
    }
  }

  if (extarg)
    sendto_server(source_p, 0, 0, ":%s SVSMODE %s %lu %s %s",
                  source_p->id,
                  target_p->id, (unsigned long)target_p->tsinfo, modes, extarg);
  else
    sendto_server(source_p, 0, 0, ":%s SVSMODE %s %lu %s",
                  source_p->id,
                  target_p->id, (unsigned long)target_p->tsinfo, modes);

  if (MyConnect(target_p) && (setmodes != target_p->umodes))
  {
    char modebuf[IRCD_BUFSIZE] = "";

    send_umode(target_p, target_p, setmodes, modebuf);
  }

  return 0;
}
示例#11
0
/*
** Exit one client, local or remote. Assuming all dependents have
** been already removed, and socket closed for local client.
*/
static void exit_one_client(struct Client *client_p,
                            struct Client *source_p,
                            struct Client *from, const char *comment)
{
  struct Client* target_p;
  dlink_node *lp;
  dlink_node *next_lp;

  if (IsServer(source_p))
    {
      if (source_p->servptr && source_p->servptr->serv)
        del_client_from_llist(&(source_p->servptr->serv->servers),
                                    source_p);
      else
        ts_warn("server %s without servptr!", source_p->name);

      if(!IsMe(source_p))
        remove_server_from_list(source_p);
    }
  else if (source_p->servptr && source_p->servptr->serv)
    {
      del_client_from_llist(&(source_p->servptr->serv->users), source_p);
    }
  /* there are clients w/o a servptr: unregistered ones */

  /*
  **  For a server or user quitting, propogate the information to
  **  other servers (except to the one where is came from (client_p))
  */
  if (IsMe(source_p))
    {
      sendto_realops_flags(FLAGS_ALL, L_ALL,
			   "ERROR: tried to exit me! : %s", comment);
      return;        /* ...must *never* exit self!! */
    }
  else if (IsServer(source_p))
    {
      /*
      ** Old sendto_serv_but_one() call removed because we now
      ** need to send different names to different servers
      ** (domain name matching)
      */
      /*
      ** The bulk of this is done in remove_dependents now, all
      ** we have left to do is send the SQUIT upstream.  -orabidoo
      */
      if (source_p->localClient)
      {
	if(source_p->localClient->ctrlfd > -1)
	{
          fd_close(source_p->localClient->ctrlfd);
	  source_p->localClient->ctrlfd = -1;

#ifndef HAVE_SOCKETPAIR
          fd_close(source_p->localClient->ctrlfd_r);
	  fd_close(source_p->localClient->fd_r);
	  
	  source_p->localClient->ctrlfd_r = -1;
	  source_p->localClient->fd_r = -1;
#endif
	}
      }

      target_p = source_p->from;
      if (target_p && IsServer(target_p) && target_p != client_p && !IsMe(target_p) &&
          (source_p->flags & FLAGS_KILLED) == 0)
        sendto_one(target_p, ":%s SQUIT %s :%s", from->name, source_p->name, comment);
    }
  else if (source_p->name[0]) /* ...just clean all others with QUIT... */
    {
      /*
      ** If this exit is generated from "m_kill", then there
      ** is no sense in sending the QUIT--KILL's have been
      ** sent instead.
      */
      if ((source_p->flags & FLAGS_KILLED) == 0)
        {
          sendto_server(client_p, source_p, NULL, NOCAPS, NOCAPS,
                        NOFLAGS, ":%s QUIT :%s", source_p->name, comment);
        }
      /*
      ** If a person is on a channel, send a QUIT notice
      ** to every client (person) on the same channel (so
      ** that the client can show the "**signoff" message).
      ** (Note: The notice is to the local clients *only*)
      */
      if (source_p->user)
        {
          sendto_common_channels_local(source_p, ":%s!%s@%s QUIT :%s",
				       source_p->name,
				       source_p->username,
				       source_p->host,
				       comment);

          for (lp = source_p->user->channel.head; lp; lp = next_lp)
	    {
	      next_lp = lp->next;
	      remove_user_from_channel(lp->data, source_p);
	    }
          /* Should not be in any channels now */
          assert(source_p->user->channel.head == NULL);
          
          /* Clean up invitefield */
          for (lp = source_p->user->invited.head; lp; lp = next_lp)
           {
              next_lp = lp->next;
              del_invite(lp->data, source_p);
           }

          /* Clean up allow lists */
          del_all_accepts(source_p);

	  add_history(source_p, 0);
	  off_history(source_p);

	  if (HasID(source_p))
	    del_from_id_hash_table(source_p->user->id, source_p);
  
          /* again, this is all that is needed */
        }
    }
  
  /* 
   * Remove source_p from the client lists
   */
  del_from_client_hash_table(source_p->name, source_p);

  /* remove from global client list */
  remove_client_from_list(source_p);

  /* Check to see if the client isn't already on the dead list */
  assert(dlinkFind(&dead_list, source_p) == NULL);
  /* add to dead client dlist */
  lp = make_dlink_node();
  SetDead(source_p);
  dlinkAdd(source_p, lp, &dead_list);
}
示例#12
0
/*
 * change_local_nick
 * inputs	- pointer to server
 *		- pointer to client
 * output	- 
 * side effects	- changes nick of a LOCAL user
 *
 */
int change_local_nick(struct Client *client_p, struct Client *source_p,
                      char *nick)
{
  /*
  ** 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.
  */

  source_p->tsinfo = CurrentTime;

  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 || 
     (IsOper(source_p) && ConfigFileEntry.no_oper_flood))
    {
      sendto_realops_flags(FLAGS_NCHANGE, L_ALL,
			   "Nick change: From %s to %s [%s@%s]",
			   source_p->name, nick, source_p->username,
			   source_p->host);

      sendto_common_channels_local(source_p, ":%s!%s@%s NICK :%s",
				   source_p->name, source_p->username, source_p->host,
				   nick);
      if (source_p->user)
	{
	  add_history(source_p, 1);
	  
	  /* Only hubs care about lazy link nicks not being sent on yet
	   * lazylink leafs/leafs always send their nicks up to hub,
	   * hence must always propogate nick changes.
	   * hubs might not propogate a nick change, if the leaf
	   * does not know about that client yet.
	   */
          sendto_server(client_p, source_p, NULL, NOCAPS, NOCAPS,
                        NOFLAGS, ":%s NICK %s :%lu", source_p->name,
                        nick, (unsigned long) source_p->tsinfo);
	}
    }
  else
    {
      sendto_one(source_p,
                 form_str(ERR_NICKTOOFAST),me.name, source_p->name,
                 source_p->name, nick, ConfigFileEntry.max_nick_time);
      return 0;
    }

  /* Finally, add to hash */
  del_from_client_hash_table(source_p->name, source_p);
  strcpy(source_p->name, nick);
  add_to_client_hash_table(nick, source_p);

  /* Make sure everyone that has this client on its accept list
   * loses that reference. 
   */

  del_all_accepts(source_p);

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

  return 1;
}
示例#13
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;
}
示例#14
0
/*
 * nick_from_server()
 */
static int
nick_from_server(struct Client *client_p, struct Client *source_p, int parc,
		 char *parv[], time_t newts, char *nick)
{
	if(IsServer(source_p))
	{
		/* A server introducing a new client, change source */
		source_p = make_client(client_p);
		add_client_to_list(source_p);

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

		/* copy the nick in place */
		(void) strcpy(source_p->name, nick);
		(void) add_to_client_hash_table(nick, source_p);

		if(parc > 8)
		{
			int flag;
			char *m;

			/* parse usermodes */
			m = &parv[4][1];
			while (*m)
			{
				flag = user_modes_from_c_to_bitmask[(unsigned char) *m];
				if(!(source_p->umodes & UMODE_INVISIBLE)
				   && (flag & UMODE_INVISIBLE))
					Count.invisi++;
				if(!(source_p->umodes & UMODE_OPER) && (flag & UMODE_OPER))
					Count.oper++;

				source_p->umodes |= flag & SEND_UMODES;
				m++;
			}

			return do_remote_user(nick, client_p, source_p, parv[5], parv[6],
					      parv[7], (parc > 9)? parv[8] : NULL,
						parv[(parc > 9)? 9 : 8]);
		}
	}
	else if(source_p->name[0])
	{
		/* client changing their nick */
		if(irccmp(parv[0], nick))
			source_p->tsinfo = newts ? newts : CurrentTime;

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

		if(source_p->user)
		{
			add_history(source_p, 1);
			sendto_server(client_p, NULL, NOCAPS, NOCAPS,
				      ":%s NICK %s :%lu",
				      parv[0], nick, (unsigned long) source_p->tsinfo);
		}
	}

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

	strcpy(source_p->name, nick);
	add_to_client_hash_table(nick, source_p);

	/* remove all accepts pointing to the client */
	del_all_accepts(source_p);

	return 0;
}