コード例 #1
0
ファイル: client.c プロジェクト: Cloudxtreme/ircd-ratbox
/*
 * del_from_accept
 *
 * inputs	- pointer to source client
 * 		- pointer to target client
 * output	- NONE
 * side effects - Delete's source pointer to targets allow list
 *
 * Walk through the target's accept list, remove if source is found,
 * Then walk through the source's on_accept_list remove target if found.
 */
void del_from_accept(struct Client *source, struct Client *target)
{
  dlink_node *ptr;
  dlink_node *ptr2;
  dlink_node *next_ptr;
  dlink_node *next_ptr2;
  struct Client *target_p;

  for (ptr = target->allow_list.head; ptr; ptr = next_ptr)
    {
      next_ptr = ptr->next;

      target_p = ptr->data;
      if(source == target_p)
	{
	  dlinkDelete(ptr, &target->allow_list);
	  free_dlink_node(ptr);

	  for (ptr2 = source->on_allow_list.head; ptr2;
	       ptr2 = next_ptr2)
	    {
	      next_ptr2 = ptr2->next;

	      target_p = ptr2->data;
	      if (target == target_p)
		{
		  dlinkDelete(ptr2, &source->on_allow_list);
		  free_dlink_node(ptr2);
		}
	    }
	}
    }
}
コード例 #2
0
ファイル: dbuf.c プロジェクト: mdharris/ircd
void
dbuf_delete(struct dbuf_queue *qptr, size_t count)
{
  dlink_node *ptr;
  struct dbuf_block *first;

  assert(qptr->total_size >= count);
  if (count == 0)
    return;

  /* free whole blocks first.. */
  while (1)
  {
    if (!count)
      return;
    ptr = qptr->blocks.head;
    first = ptr->data;
    if (count < first->size)
      break;

    qptr->total_size -= first->size;
    count -= first->size;
    dlinkDelete(ptr, &qptr->blocks);
    free_dlink_node(ptr);
    BlockHeapFree(dbuf_heap, first);
  }

  /* ..then remove data from the beginning of the queue */
  first->size -= count;
  qptr->total_size -= count;
  memmove((void *) &first->data, (void *) &first->data[count], first->size);
}
コード例 #3
0
ファイル: client.c プロジェクト: Cloudxtreme/ircd-ratbox
void exit_aborted_clients(void)
{
  dlink_node *ptr, *next;
  struct Client *target_p;
  
  for(ptr = abort_list.head; ptr; ptr = next)
    {
      target_p = ptr->data;
      next = ptr->next;
      if (ptr->data == NULL)
        {
          sendto_realops_flags(FLAGS_ALL, L_ALL,
                        "Warning: null client on abort_list!");
          dlinkDelete(ptr, &abort_list);
          free_dlink_node(ptr);
          continue;
        }
      dlinkDelete(ptr, &abort_list);
      exit_client(target_p, target_p, &me, "Dead link");  
      free_dlink_node(ptr);
    }
}
コード例 #4
0
ファイル: client.c プロジェクト: Cloudxtreme/ircd-ratbox
static void
free_exited_clients(void *unused)
{
  dlink_node *ptr, *next;
  struct Client *target_p;
  
  for(ptr = dead_list.head; ptr; ptr = next)
    {
      target_p = ptr->data;
      next = ptr->next;
      if (ptr->data == NULL)
        {
          sendto_realops_flags(FLAGS_ALL, L_ALL,
                        "Warning: null client on dead_list!");
          dlinkDelete(ptr, &dead_list);
          free_dlink_node(ptr);
          continue;
        }
      release_client_state(target_p);
      free_client(target_p);
      dlinkDelete(ptr, &dead_list);
      free_dlink_node(ptr);
    }
}
コード例 #5
0
ファイル: m_clearchan.c プロジェクト: Cloudxtreme/ircd-3
/*
 * free_channel_list
 *
 * inputs       - pointer to dlink_list
 * output       - NONE
 * side effects -
 */
static void free_channel_list(dlink_list *list)
{
  dlink_node *ptr;
  dlink_node *next_ptr;
  struct Ban *actualBan;

  for (ptr = list->head; ptr; ptr = next_ptr)
    {
      next_ptr = ptr->next;

      actualBan = ptr->data;
      MyFree(actualBan->banstr);
      MyFree(actualBan->who);
      BlockHeapFree(ban_heap, actualBan);

      free_dlink_node(ptr);
    }
}
コード例 #6
0
ファイル: m_jupe.c プロジェクト: Cloudxtreme/ircd-ratbox
/*
** mo_jupe
**      parv[0] = sender prefix
**      parv[1] = server we're juping
**      parv[2] = reason for jupe
*/
static void mo_jupe(struct Client *client_p, struct Client *source_p,
                    int parc, char *parv[])
{
  struct Client *target_p;
  struct Client *ajupe;
  dlink_node *m;
  char reason[REALLEN+2];

  if(!ServerInfo.hub)
    return;

  if(!IsOperAdmin(source_p))
    {
      sendto_one(source_p, ":%s NOTICE %s :You must be an admin to use this command",
                 me.name, parv[0]);
      return;
    }

  if (bogus_host(parv[1]))
    {
      sendto_one(source_p, ":%s NOTICE %s :Invalid servername: %s",
                 me.name, parv[0], parv[1]);
      return;
    }

  if(match(parv[1], me.name))
  {
    sendto_one(source_p, ":%s NOTICE %s :I cant jupe myself!",
	       me.name, source_p->name);
    return;
  }

  sendto_wallops_flags(UMODE_WALLOP, &me,
                       "JUPE for %s requested by %s: %s",
			 parv[1], get_oper_name(source_p), parv[2]);

  sendto_server(NULL, NOCAPS, NOCAPS, 
                ":%s WALLOPS :JUPE for %s requested by %s!%s@%s: %s",
                parv[0], parv[1], source_p->name, 
                source_p->username, source_p->host, parv[2]);
  ilog(L_NOTICE, "JUPE for %s requested by %s: %s",
                parv[1], get_oper_name(source_p), parv[2]);

  target_p= find_server(parv[1]);

  if(target_p)
    exit_client(client_p, target_p, &me, parv[2]);

  sendto_server(NULL, NOCAPS, NOCAPS,
                ":%s SERVER %s 1 :JUPED: %s",
                me.name, parv[1], parv[2]);

  sendto_realops_flags(UMODE_ALL, L_ALL,
                       "Link with %s established: (JUPED) link",
		       parv[1]);

  ajupe = make_client(NULL);

  /* make_client() adds client to unknown_list */
  m = dlinkFind(&unknown_list, ajupe);
  if(m != NULL)
    dlinkDelete(m, &unknown_list);
  free_dlink_node(m);

  make_server(ajupe);
  ajupe->hopcount = 1;
  strlcpy(ajupe->name,parv[1],HOSTLEN);

  /* we need to give 7 chars to prepend "JUPED: " */
  if(strlen(parv[2]) > (REALLEN-7))
    parv[2][REALLEN-7] = '\0';
  ircsprintf(reason, "%s %s", "JUPED:", parv[2]);
  
  strlcpy(ajupe->info,reason,REALLEN);
  ajupe->serv->up = me.name;
  ajupe->servptr = &me;
  SetServer(ajupe);
  SetDead(ajupe);
  
  Count.server++;
  Count.myserver++;

  /* Some day, all these lists will be consolidated *sigh* */
  add_client_to_list(ajupe);
  add_to_client_hash_table(ajupe->name, ajupe);
  dlinkAdd(ajupe, &ajupe->lnode, &ajupe->servptr->serv->servers);
  add_server_to_list(ajupe);
}
コード例 #7
0
ファイル: m_svsmode.c プロジェクト: nask0/ircd-hybrid
/*! \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;

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

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

  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));
        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;
}
コード例 #8
0
ファイル: m_svsmode.c プロジェクト: mindspeaker/oftc-hybrid
/*! \brief SVSMODE command handler (called by services)
 *
 * \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
 *      - parv[2] = TS (or mode, depending on svs version)
 *      - parv[3] = mode (or services id if old svs version)
 *      - parv[4] = optional argument (services id)
 */
static void
ms_svsmode(struct Client *client_p, struct Client *source_p,
           int parc, char *parv[])
{
  struct Client *target_p = NULL;
  int what = MODE_ADD;
  unsigned int flag = 0, setflags = 0;
  char *m = NULL, *modes = NULL, *extarg = NULL;
  time_t ts = 0;

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

  if ((parc >= 4) && ((*parv[3] == '+') || (*parv[3] == '-')))
  {
    ts     = atol(parv[2]);
    modes  = parv[3];
    extarg = (parc > 4) ? parv[4] : NULL;
  }
  else
  {
    modes  = parv[2];
    extarg = (parc > 3) ? parv[3] : NULL;
  }

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

  if (ts && (ts != target_p->tsinfo))
    return;

  setflags = target_p->umodes;

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

      case '-':
        what = MODE_DEL;
        break;

      case 'x':
        if (what == MODE_ADD && extarg)
          user_set_hostmask(target_p, extarg);

        break;

      case 'd':
        if (!EmptyString(extarg))
          strlcpy(target_p->svid, extarg, sizeof(target_p->svid));

        break;

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

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

            detach_conf(target_p, OPER_TYPE);
            ClrOFlag(target_p);
            DelUMode(target_p, ConfigFileEntry.oper_only_umodes);

            if ((dm = dlinkFindDelete(&oper_list, target_p)) != NULL)
              free_dlink_node(dm);
          }
        }

        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 ' ':
      case '\n':
      case '\r':
      case '\t':
        break;

      default:
        if ((flag = user_modes[(unsigned char) * m]))
          execute_callback(umode_cb, client_p, target_p, what, flag);

        break;
    }
  }

  if (extarg)
  {
    sendto_server(client_p, CAP_TS6, NOCAPS,
                  ":%s SVSMODE %s %lu %s %s", ID(source_p),
                  ID(target_p), (unsigned long)target_p->tsinfo, modes, extarg);
    sendto_server(client_p, NOCAPS, CAP_TS6,
                  ":%s SVSMODE %s %lu %s %s", source_p->name,
                  target_p->name, (unsigned long)target_p->tsinfo, modes, extarg);
  }
  else
  {
    sendto_server(client_p, CAP_TS6, NOCAPS,
                  ":%s SVSMODE %s %lu %s", ID(source_p),
                  ID(target_p), (unsigned long)target_p->tsinfo, modes);
    sendto_server(client_p, NOCAPS, CAP_TS6,
                  ":%s SVSMODE %s %lu %s", source_p->name,
                  target_p->name, (unsigned long)target_p->tsinfo, modes);
  }

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

    send_umode(target_p, target_p, setflags, 0xffffffff, modebuf);
  }
}
コード例 #9
0
ファイル: client.c プロジェクト: Cloudxtreme/ircd-ratbox
/*
** exit_client - This is old "m_bye". Name  changed, because this is not a
**        protocol function, but a general server utility function.
**
**        This function exits a client of *any* type (user, server, etc)
**        from this server. Also, this generates all necessary prototol
**        messages that this exit may cause.
**
**   1) If the client is a local client, then this implicitly
**        exits all other clients depending on this connection (e.g.
**        remote clients having 'from'-field that points to this.
**
**   2) If the client is a remote client, then only this is exited.
**
** For convenience, this function returns a suitable value for
** m_function return value:
**
**        CLIENT_EXITED        if (client_p == source_p)
**        0                if (client_p != source_p)
*/
int exit_client(
                struct Client* client_p, /* The local client originating the
                                          * exit or NULL, if this exit is
                                          * generated by this server for
                                          * internal reasons.
                                          * This will not get any of the
                                          * generated messages. */
                struct Client* source_p, /* Client exiting */
                struct Client* from,     /* Client firing off this Exit,
                                          * never NULL! */
                const char* comment      /* Reason for the exit */
               )
{
  char comment1[HOSTLEN + HOSTLEN + 2];
  dlink_node *m;
  fprintf(stderr, "Exiting client: %s\n", comment);
  if (MyConnect(source_p))
    {
      /* DO NOT REMOVE. exit_client can be called twice after a failed
       * read/write.
       */
      if(IsClosing(source_p))
        return 0;

      SetClosing(source_p);
      if (source_p->flags & FLAGS_IPHASH)
        remove_one_ip(&source_p->localClient->ip);

      delete_adns_queries(source_p->localClient->dns_query);
      delete_identd_queries(source_p);
      client_flush_input(source_p);

      /* This source_p could have status of one of STAT_UNKNOWN, STAT_CONNECTING
       * STAT_HANDSHAKE or STAT_UNKNOWN
       * all of which are lumped together into unknown_list
       *
       * In all above cases IsRegistered() will not be true.
       */
      if (!IsRegistered(source_p))
	{
	  m = dlinkFind(&unknown_list,source_p);
	  if(m != NULL)
	    {
	      dlinkDelete(m, &unknown_list);
	      free_dlink_node(m);
	    }
	}
      if (IsOper(source_p))
        {
	  m = dlinkFind(&oper_list,source_p);
	  if(m != NULL)
	    {
	      dlinkDelete(m, &oper_list);
	      free_dlink_node(m);
	    }
        }
      if (IsClient(source_p))
        {
          Count.local--;

          if(IsPerson(source_p))        /* a little extra paranoia */
            {
	      m = dlinkFind(&lclient_list,source_p);
	      if(m != NULL)
		{
		  dlinkDelete(m,&lclient_list);
		  free_dlink_node(m);
		}
            }
        }

      /* As soon as a client is known to be a server of some sort
       * it has to be put on the serv_list, or SJOIN's to this new server
       * from the connect burst will not be seen.
       */
      if (IsServer(source_p) || IsConnecting(source_p) ||
          IsHandshake(source_p))
	{
	  m = dlinkFind(&serv_list,source_p);
	  if(m != NULL)
	    {
	      dlinkDelete(m,&serv_list);
	      free_dlink_node(m);
              unset_chcap_usage_counts(source_p);
	    }
	}

      if (IsServer(source_p))
        {
          Count.myserver--;
	  if(ServerInfo.hub)
	    remove_lazylink_flags(source_p->localClient->serverMask);
	  else
	    uplink = NULL;
        }

      if (IsPerson(source_p))
        sendto_realops_flags(FLAGS_CCONN, L_ALL,
                             "Client exiting: %s (%s@%s) [%s] [%s]",
                             source_p->name, source_p->username, source_p->host,
                             comment, source_p->localClient->sockhost);

      log_user_exit(source_p);

      if (source_p->localClient->fd >= 0)
	{
	  if (client_p != NULL && source_p != client_p)
	    sendto_one(source_p, "ERROR :Closing Link: %s %s (%s)",
		       source_p->host, source_p->name, comment);
	  else
	    sendto_one(source_p, "ERROR :Closing Link: %s (%s)",
		       source_p->host, comment);
	}
      /*
      ** Currently only server connections can have
      ** depending remote clients here, but it does no
      ** harm to check for all local clients. In
      ** future some other clients than servers might
      ** have remotes too...
      **
      ** Close the Client connection first and mark it
      ** so that no messages are attempted to send to it.
      ** (The following *must* make MyConnect(source_p) == FALSE!).
      ** It also makes source_p->from == NULL, thus it's unnecessary
      ** to test whether "source_p != target_p" in the following loops.
      */
     close_connection(source_p);
    }

  if(IsServer(source_p))
    {        
      if(ConfigServerHide.hide_servers)
	{
          /* set netsplit message to "me.name *.split" to still show 
	   * that its a split, but hide the servers splitting
	   */
	  ircsprintf(comment1,"%s *.split", me.name);
	}
      else
	{
	  if((source_p->serv) && (source_p->serv->up))
	    strcpy(comment1, source_p->serv->up);
	  else
	    strcpy(comment1, "<Unknown>");

	  strcat(comment1," ");
	  strcat(comment1, source_p->name);
	}

      remove_dependents(client_p, source_p, from, comment, comment1);

      if (source_p->servptr == &me)
        {
          sendto_realops_flags(FLAGS_ALL, L_ALL,
		       "%s was connected for %d seconds.  %d/%d sendK/recvK.",
			       source_p->name, (int)(CurrentTime - source_p->firsttime),
			       source_p->localClient->sendK,
			       source_p->localClient->receiveK);
          ilog(L_NOTICE, "%s was connected for %d seconds.  %d/%d sendK/recvK.",
              source_p->name, CurrentTime - source_p->firsttime, 
              source_p->localClient->sendK, source_p->localClient->receiveK);
        }
    }
  exit_one_client(client_p, source_p, from, comment);
  return client_p == source_p ? CLIENT_EXITED : 0;
}
コード例 #10
0
ファイル: m_mode.c プロジェクト: jmdh/ircd-hybrid
/* set_user_mode()
 *
 * added 15/10/91 By Darren Reed.
 * parv[0] - command
 * parv[1] - username to change mode for
 * parv[2] - modes to change
 */
static void
set_user_mode(struct Client *source_p, const int parc, char *parv[])
{
  const struct user_modes *tab = NULL;
  const unsigned int setmodes = source_p->umodes;
  const struct Client *target_p = NULL;
  int what = MODE_ADD, badmode = 0;

  if ((target_p = find_person(source_p, parv[1])) == NULL)
  {
    if (MyConnect(source_p))
      sendto_one_numeric(source_p, &me, ERR_NOSUCHCHANNEL, parv[1]);
    return;
  }

  if (source_p != target_p)
  {
     sendto_one_numeric(source_p, &me, ERR_USERSDONTMATCH);
     return;
  }

  if (parc < 3)
  {
    char buf[IRCD_BUFSIZE] = "";
    char *m = buf;

    *m++ = '+';
    for (tab = umode_tab; tab->c; ++tab)
      if (HasUMode(source_p, tab->flag))
        *m++ = tab->c;
    *m = '\0';

    sendto_one_numeric(source_p, &me, RPL_UMODEIS, buf);
    return;
  }

  /* Parse user mode change string */
  for (const char *m = parv[2]; *m; ++m)
  {
    switch (*m)
    {
      case '+':
        what = MODE_ADD;
        break;
      case '-':
        what = MODE_DEL;
        break;
      case 'o':
        if (what == MODE_ADD)
        {
          if (!MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER))
          {
            ++Count.oper;
            SetOper(source_p);
          }
        }
        else
        {
          if (!HasUMode(source_p, UMODE_OPER))
            break;

          ClearOper(source_p);
          --Count.oper;

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

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

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

        break;

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

      default:
        if ((tab = umode_map[(unsigned char)*m]))
        {
          if (MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER) &&
              (ConfigGeneral.oper_only_umodes & tab->flag))
            badmode = 1;
          else
          {
            if (what == MODE_ADD)
              AddUMode(source_p, tab->flag);
            else
              DelUMode(source_p, tab->flag);
          }
        }
        else if (MyConnect(source_p))
          badmode = 1;

        break;
    }
  }

  if (badmode)
    sendto_one_numeric(source_p, &me, ERR_UMODEUNKNOWNFLAG);

  if (MyConnect(source_p) && HasUMode(source_p, UMODE_ADMIN) &&
      !HasOFlag(source_p, OPER_FLAG_ADMIN))
  {
    sendto_one_notice(source_p, &me, ":*** You have no admin flag;");
    DelUMode(source_p, UMODE_ADMIN);
  }

  if (!(setmodes & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE))
    ++Count.invisi;
  if ((setmodes & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
    --Count.invisi;

  /*
   * Compare new modes with old modes and send string which will cause
   * servers to update correctly.
   */
  send_umode_out(source_p, setmodes);
}