void init_list(void)
{
  struct Client* cptr;
  struct Connection* con;
  int i;
  /*
   * pre-allocate MAXCONNECTIONS clients and connections
   */
  for (i = 0; i < MAXCONNECTIONS; ++i) {
    cptr = (struct Client*) MyMalloc(sizeof(struct Client));
    cli_next(cptr) = clientFreeList;
    clientFreeList = cptr;
    ++clientAllocCount;

    con = (struct Connection*) MyMalloc(sizeof(struct Connection));
    con_next(con) = connectionFreeList;
    connectionFreeList = con;
    ++connectionAllocCount;
  }

#ifdef DEBUGMODE
  memset(&clients, 0, sizeof(clients));
  memset(&connections, 0, sizeof(connections));
  memset(&users, 0, sizeof(users));
  memset(&servs, 0, sizeof(servs));
  memset(&links, 0, sizeof(links));
#endif
}
Example #2
0
/*
 * ms_links - server message handler
 *
 * parv[0] = sender prefix
 * parv[1] = servername mask
 *
 * or
 *
 * parv[0] = sender prefix
 * parv[1] = server to query
 * parv[2] = servername mask
 */
int
ms_links(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
   char *mask;
   struct Client *acptr;

   if (parc > 2)
   {
     if (hunt_server_cmd(sptr, CMD_LINKS, cptr, 1, "%C :%s", 1, parc, parv) !=
         HUNTED_ISME)
       return 0;
     mask = parv[2];
   }
   else
     mask = parc < 2 ? 0 : parv[1];
 
   for (acptr = GlobalClientList, collapse(mask); acptr; acptr = cli_next(acptr))
   {
     if (!IsServer(acptr) && !IsMe(acptr))
       continue;
     if (!BadPtr(mask) && match(mask, cli_name(acptr)))
       continue;
     send_reply(sptr, RPL_LINKS, cli_name(acptr), cli_name(cli_serv(acptr)->up),
                cli_hopcount(acptr), cli_serv(acptr)->prot,
                ((cli_info(acptr))[0] ? cli_info(acptr) : "(Unknown Location)"));
   }
 
   send_reply(sptr, RPL_ENDOFLINKS, BadPtr(mask) ? "*" : mask);
   return 0;
 }
Example #3
0
/** Count number of users who match \a mask.
 * @param[in] mask ip mask to check.
 * @param[in] flags Bitmask possibly containing the value ZLINE_LOCAL, to limit searches to this server.
 * @return Count of matching users.
 */
static int
count_users(char *mask, int flags)
{
  struct irc_in_addr ipmask;
  struct Client *acptr;
  int count = 0;
  int ipmask_valid;
  char ipbuf[SOCKIPLEN + 2];
  unsigned char ipmask_len;

  ipmask_valid = ipmask_parse(mask, &ipmask, &ipmask_len);
  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) {
    if (!IsUser(acptr))
      continue;
    if ((flags & ZLINE_LOCAL) && !MyConnect(acptr))
      continue;

    ircd_snprintf(0, ipbuf, sizeof(ipbuf), "%s", ircd_ntoa(&cli_ip(acptr)));

    if (!match(mask, ipbuf)
        || (ipmask_valid && ipmask_check(&cli_ip(acptr), &ipmask, ipmask_len)
            && (irc_in_addr_type_cmp(&cli_ip(acptr), &ipmask) && ipmask_len)))
      count++;
  }

  return count;
}
Example #4
0
/** Link \a cptr into #GlobalClientList.
 * @param[in] cptr Client to link into the global list.
 */
void add_client_to_list(struct Client *cptr)
{
  assert(cli_verify(cptr));
  assert(cli_next(cptr) == 0);
  assert(cli_prev(cptr) == 0);

  /*
   * Since we always insert new clients to the top of the list,
   * this should mean the "me" is the bottom most item in the list.
   * XXX - don't always count on the above, things change
   */
  cli_prev(cptr) = 0;
  cli_next(cptr) = GlobalClientList;
  GlobalClientList = cptr;
  if (cli_next(cptr))
    cli_prev(cli_next(cptr)) = cptr;
}
Example #5
0
/** Perform a very CPU-intensive verification of %GlobalClientList.
 * This checks the Client::cli_magic and Client::cli_prev field for
 * each element in the list, and also checks that there are no loops.
 * Any detected error will lead to an assertion failure.
 */
void verify_client_list(void)
{
  struct Client *client, *prev = 0;
  unsigned int visited = 0;

  for (client = GlobalClientList; client; client = cli_next(client), ++visited) {
    /* Verify that this is a valid client, not a free'd one */
    assert(cli_verify(client));
    /* Verify that the list hasn't suddenly jumped around */
    assert(cli_prev(client) == prev);
    /* Verify that the list hasn't become circular */
    assert(cli_next(client) != GlobalClientList);
    assert(visited <= clients.alloc);
    /* Remember what should precede us */
    prev = client;
  }
}
/* WARNING: Major CPU sink!
 *
 * This is a debugging routine meant to verify the integrity of the client
 * linked list.  It is meant to be comprehensive, to detect *any* corruption
 * of that list.  This means that it will be majorly CPU-intensive, and
 * should *only* be enabled on servers that have DEBUGMODE enabled.  Ignore
 * this warning at your peril!
 */
void verify_client_list(void)
{
  struct Client *client, *prev = 0, *sentinel = 0;
  extern unsigned int ircrandom(void);

  for (client = GlobalClientList; client; client = cli_next(client)) {
    /* Verify that this is a valid client, not a free'd one */
    assert(cli_verify(client));
    /* Verify that the list hasn't suddenly jumped around */
    assert(cli_prev(client) == prev);
    /* Verify that the list hasn't become circular */
    assert(cli_next(client) != GlobalClientList);
    assert(!sentinel || client != sentinel);

    prev = client; /* Remember what should preceed us */
    if (!(ircrandom() % 50)) /* probabilistic loop detector */
      sentinel = client;
  }
}
Example #7
0
/** Release a Client structure by prepending it to #clientFreeList.
 * @param[in] cptr Client that is no longer being used.
 */
static void dealloc_client(struct Client* cptr)
{
  assert(cli_verify(cptr));
  assert(0 == cli_connect(cptr));

  --clients.inuse;

  cli_next(cptr) = clientFreeList;
  clientFreeList = cptr;

  cli_magic(cptr) = 0;
}
Example #8
0
/** Release a Client.
 * In addition to the cleanup done by dealloc_client(), this will free
 * any pending auth request, free the connection for local clients,
 * and delete the processing timer for the client.
 * @param[in] cptr Client to free.
 */
void free_client(struct Client* cptr)
{
  if (!cptr)
    return;
  /*
   * forget to remove the client from the hash table?
   */
  assert(cli_verify(cptr));
  assert(cli_hnext(cptr) == cptr);
  /* or from linked list? */
  assert(cli_next(cptr) == 0);
  assert(cli_prev(cptr) == 0);

  Debug((DEBUG_LIST, "Freeing client %s [%p], connection %p", cli_name(cptr),
	 cptr, cli_connect(cptr)));

  if (cli_auth(cptr))
    destroy_auth_request(cli_auth(cptr), 0);

  /* Make sure we didn't magically get re-added to the list */
  assert(cli_next(cptr) == 0);
  assert(cli_prev(cptr) == 0);

  if (cli_from(cptr) == cptr) { /* in other words, we're local */
    cli_from(cptr) = 0;
    /* timer must be marked as not active */
    if (!cli_freeflag(cptr) && !t_active(&(cli_proc(cptr))))
      dealloc_connection(cli_connect(cptr)); /* connection not open anymore */
    else {
      if (-1 < cli_fd(cptr) && cli_freeflag(cptr) & FREEFLAG_SOCKET)
	socket_del(&(cli_socket(cptr))); /* queue a socket delete */
      if (cli_freeflag(cptr) & FREEFLAG_TIMER)
	timer_del(&(cli_proc(cptr))); /* queue a timer delete */
    }
  }

  cli_connect(cptr) = 0;

  dealloc_client(cptr); /* actually destroy the client */
}
Example #9
0
static void move_marker(void)
{
  if (!++who_marker)
  {
    struct Client *cptr = GlobalClientList;
    while (cptr)
    {
      cli_marker(cptr) = 0;
      cptr = cli_next(cptr);
    }
    who_marker++;
  }
}
/*
 * Taken the code from ExitOneClient() for this and placed it here.
 * - avalon
 */
void remove_client_from_list(struct Client *cptr)
{
  assert(cli_verify(cptr));
  assert(con_verify(cli_connect(cptr)));
  assert(!cli_prev(cptr) || cli_verify(cli_prev(cptr)));
  assert(!cli_next(cptr) || cli_verify(cli_next(cptr)));
  assert(!IsMe(cptr));

  /* Only remove from the list if it actually IS in the list.
   * cli_next(cptr) cannot be NULL here if cptr is in the list,
   * only &me is at the end, and we never try to remove &me  -GW 
   */ 
  if(cli_next(cptr))
  {
    if (cli_prev(cptr))
      cli_next(cli_prev(cptr)) = cli_next(cptr);
    else {
      GlobalClientList = cli_next(cptr);
      cli_prev(GlobalClientList) = 0;
    }
    cli_prev(cli_next(cptr)) = cli_prev(cptr);
  }
  cli_next(cptr) = cli_prev(cptr) = 0;

  if (IsUser(cptr) && cli_user(cptr)) {
    add_history(cptr, 0);
    off_history(cptr);
  }
  if (cli_user(cptr)) {
    free_user(cli_user(cptr));
    cli_user(cptr) = 0;
  }

  if (cli_serv(cptr)) {
    if (cli_serv(cptr)->user) {
      free_user(cli_serv(cptr)->user);
      cli_serv(cptr)->user = 0;
    }
    if (cli_serv(cptr)->client_list)
      MyFree(cli_serv(cptr)->client_list);
    MyFree(cli_serv(cptr)->last_error_msg);
    MyFree(cli_serv(cptr));
#ifdef  DEBUGMODE
    --servs.inuse;
#endif
  }
  free_client(cptr);
}
Example #11
0
/** Remove \a cptr from lists that it is a member of.
 * Specifically, this delinks \a cptr from #GlobalClientList, updates
 * the whowas history list, frees its Client::cli_user and
 * Client::cli_serv fields, and finally calls free_client() on it.
 * @param[in] cptr Client to remove from lists and free.
 */
void remove_client_from_list(struct Client *cptr)
{
  assert(cli_verify(cptr));
  assert(con_verify(cli_connect(cptr)));
  assert(!cli_prev(cptr) || cli_verify(cli_prev(cptr)));
  assert(!cli_next(cptr) || cli_verify(cli_next(cptr)));
  assert(!IsMe(cptr));

  /* Only try remove cptr from the list if it IS in the list.
   * cli_next(cptr) cannot be NULL here, as &me is always the end
   * the list, and we never remove &me.    -GW 
   */
  if(cli_next(cptr))
  {
    if (cli_prev(cptr))
      cli_next(cli_prev(cptr)) = cli_next(cptr);
    else {
      GlobalClientList = cli_next(cptr);
      cli_prev(GlobalClientList) = 0;
    }
    cli_prev(cli_next(cptr)) = cli_prev(cptr);
  }
  cli_next(cptr) = cli_prev(cptr) = 0;

  if (IsUser(cptr) && cli_user(cptr)) {
    add_history(cptr, 0);
    off_history(cptr);
  }
  if (cli_user(cptr)) {
    free_user(cli_user(cptr));
    cli_user(cptr) = 0;
  }

  if (cli_serv(cptr)) {
    if (cli_serv(cptr)->user) {
      free_user(cli_serv(cptr)->user);
      cli_serv(cptr)->user = 0;
    }
    if (cli_serv(cptr)->client_list)
      MyFree(cli_serv(cptr)->client_list);
    MyFree(cli_serv(cptr)->last_error_msg);
    MyFree(cli_serv(cptr));
    --servs.inuse;
    --servs.alloc;
  }
  free_client(cptr);
}
static int crule_connected(int numargs, void *crulearg[])
{
  struct Client *acptr;

  /* taken from m_links */
  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr))
  {
    if (!IsServer(acptr) && !IsMe(acptr))
      continue;
    if (match((char *)crulearg[0], cli_name(acptr)))
      continue;
    return (1);
  }
  return (0);
}
Example #13
0
/** Allocate a new Client structure.
 * If #clientFreeList != NULL, use the head of that list.
 * Otherwise, allocate a new structure.
 * @return Newly allocated Client.
 */
static struct Client* alloc_client(void)
{
  struct Client* cptr = clientFreeList;

  if (!cptr) {
    cptr = (struct Client*) MyMalloc(sizeof(struct Client));
    clients.alloc++;
  } else
    clientFreeList = cli_next(cptr);

  clients.inuse++;

  memset(cptr, 0, sizeof(struct Client));

  return cptr;
}
Example #14
0
/*
 *  mo_squit (oper)
 *
 *    parv[0] = sender prefix
 *    parv[1] = server name
 *    parv[2] = comment (optional)
 *
 */
int mo_squit(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  const char* server;
  struct Client *acptr;
  struct Client *acptr2;
  char *comment;
      
  if (parc < 2) 
    return need_more_params(sptr, "SQUIT");

  if (parc < 3 || BadPtr(parv[2]))
    comment = cli_name(sptr);
  else
    comment = parv[2];

  server = parv[1];
  /*
   * The following allows wild cards in SQUIT. Only useful
   * when the command is issued by an oper.
   */
  for (acptr = GlobalClientList; (acptr = next_client(acptr, server));
      acptr = cli_next(acptr)) {
    if (IsServer(acptr) || IsMe(acptr))
      break;
  }
  
  /* Not found? Bugger. */
  if (!acptr || IsMe(acptr))
    return send_reply(sptr, ERR_NOSUCHSERVER, server);

  /*
   * Look for a matching server that is closer,
   * that way we won't accidentally squit two close
   * servers like davis.* and davis-r.* when typing
   * /SQUIT davis*
   */
  for (acptr2 = cli_serv(acptr)->up; acptr2 != &me;
      acptr2 = cli_serv(acptr2)->up)
    if (!match(server, cli_name(acptr2)))
      acptr = acptr2;
  
  /* Disallow local opers to squit remote servers */
  if (IsLocOp(sptr) && !MyConnect(acptr))
    return send_reply(sptr, ERR_NOPRIVILEGES);

  return exit_client(cptr, acptr, sptr, comment);
}
static int crule_via(int numargs, void *crulearg[])
{
  struct Client *acptr;

  /* adapted from m_links */
  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr))
  {
    if (!IsServer(acptr) && !IsMe(acptr))
      continue;
    if (match((char *)crulearg[1], cli_name(acptr)))
      continue;
    if (match((char *)crulearg[0],
	      cli_name(LocalClientArray[cli_fd(cli_from(acptr))])))
      continue;
    return (1);
  }
  return (0);
}
static struct Client* alloc_client(void)
{
  struct Client* cptr = clientFreeList;

  if (!cptr) {
    cptr = (struct Client*) MyMalloc(sizeof(struct Client));
    ++clientAllocCount;
  } else
    clientFreeList = cli_next(cptr);

#ifdef DEBUGMODE
  clients.inuse++;
#endif

  memset(cptr, 0, sizeof(struct Client));

  return cptr;
}
Example #17
0
static void
stats_servers_verbose(struct Client* sptr, struct StatDesc* sd, int stat,
		      char* param)
{
  struct Client *acptr;

  /* lowercase 'v' is for human-readable,
   * uppercase 'V' is for machine-readable */
  if (stat == 'v')
    send_reply(sptr, SND_EXPLICIT | RPL_STATSVERBOSE,
	       "%-20s %-20s Flags Hops Numeric   Lag  RTT   Up Down "
	       "Clients/Max Proto %-10s :Info", "Servername", "Uplink",
	       "LinkTS");

  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) {
    if (!IsServer(acptr) && !IsMe(acptr))
      continue;
    if (param && match(param, cli_name(acptr))) /* narrow search */
      continue;
    send_reply(sptr, SND_EXPLICIT | RPL_STATSVERBOSE, stat == 'v' ?
	       "%-20s %-20s %c%c%c%c  %4i %s %-4i %5i %4i %4i %4i %5i %5i "
	       "P%-2i   %Tu :%s" :
	       "%s %s %c%c%c%c %i %s %i %i %i %i %i %i %i P%i %Tu :%s",
	       cli_name(acptr),
	       cli_name(cli_serv(acptr)->up),
	       IsBurst(acptr) ? 'B' : '-',
	       IsBurstAck(acptr) ? 'A' : '-',
	       IsHub(acptr) ? 'H' : '-',
	       IsService(acptr) ? 'S' : '-',
	       cli_hopcount(acptr),
	       NumServ(acptr),
	       base64toint(cli_yxx(acptr)),
	       cli_serv(acptr)->lag,
	       cli_serv(acptr)->asll_rtt,
	       cli_serv(acptr)->asll_to,
	       cli_serv(acptr)->asll_from,
	       cli_serv(acptr)->clients,
	       cli_serv(acptr)->nn_mask,
	       cli_serv(acptr)->prot,
	       cli_serv(acptr)->timestamp,
	       cli_info(acptr));
  }
}
Example #18
0
/** Check whether a connected server matching crulearg[1] is
 * connnected to me behind one matching crulearg[0].
 * @param[in] numargs Number of valid args in \a crulearg.
 * @param[in] crulearg Argument array.
 * @return Non-zero if the condition is true, zero if not.
 */
static int crule_via(int numargs, void *crulearg[])
{
#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
  struct Client *acptr;

  /* adapted from m_links */
  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr))
  {
    if (!IsServer(acptr) && !IsMe(acptr))
      continue;
    if (match((char *)crulearg[1], cli_name(acptr)))
      continue;
    if (match((char *)crulearg[0], cli_name(cli_from(acptr))))
      continue;
    return (1);
  }
#endif
  return (0);
}
Example #19
0
/** Initialize the list manipulation support system.
 * Pre-allocate MAXCONNECTIONS Client and Connection structures.
 */
void init_list(void)
{
  struct Client* cptr;
  struct Connection* con;
  int i;
  /*
   * pre-allocate MAXCONNECTIONS clients and connections
   */
  for (i = 0; i < MAXCONNECTIONS; ++i) {
    cptr = (struct Client*) MyMalloc(sizeof(struct Client));
    cli_next(cptr) = clientFreeList;
    clientFreeList = cptr;
    clients.alloc++;

    con = (struct Connection*) MyMalloc(sizeof(struct Connection));
    con_next(con) = connectionFreeList;
    connectionFreeList = con;
    connections.alloc++;
  }
}
Example #20
0
/** Send a (prefixed) command to all users matching \a to as \a who.
 * @warning \a pattern must not contain %v.
 * @param[in] from Source of the command.
 * @param[in] cmd Long name of command.
 * @param[in] tok Short name of command.
 * @param[in] to Destination host/server mask.
 * @param[in] one Client direction to skip (or NULL).
 * @param[in] who Type of match for \a to (either MATCH_HOST or MATCH_SERVER).
 * @param[in] pattern Format string for command arguments.
 */
void sendcmdto_match_butone(struct Client *from, const char *cmd,
			    const char *tok, const char *to,
			    struct Client *one, unsigned int who,
			    const char *pattern, ...)
{
  struct VarData vd;
  struct Client *cptr;
  struct MsgBuf *user_mb;
  struct MsgBuf *serv_mb;

  vd.vd_format = pattern;

  /* Build buffer to send to users */
  va_start(vd.vd_args, pattern);
  user_mb = msgq_make(0, "%:#C %s %v", from, cmd, &vd);
  va_end(vd.vd_args);

  /* Build buffer to send to servers */
  va_start(vd.vd_args, pattern);
  serv_mb = msgq_make(&me, "%C %s %v", from, tok, &vd);
  va_end(vd.vd_args);

  /* send buffer along */
  bump_sentalong(one);
  for (cptr = GlobalClientList; cptr; cptr = cli_next(cptr)) {
    if (!IsRegistered(cptr) || IsServer(cptr) || cli_fd(cli_from(cptr)) < 0 ||
        cli_sentalong(cptr) == sentalong_marker ||
        !match_it(from, cptr, to, who))
      continue; /* skip it */
    cli_sentalong(cptr) = sentalong_marker;

    if (MyConnect(cptr)) /* send right buffer */
      send_buffer(cptr, user_mb, 0);
    else
      send_buffer(cptr, serv_mb, 0);
  }

  msgq_clean(user_mb);
  msgq_clean(serv_mb);
}
Example #21
0
/*
 * m_links - generic message handler
 *
 * parv[0] = sender prefix
 * parv[1] = servername mask
 *
 * or
 *
 * parv[0] = sender prefix
 * parv[1] = server to query
 * parv[2] = servername mask
 */
int m_links(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  char *mask;
  struct Client *acptr;

  if (feature_bool(FEAT_HIS_LINKS) && !IsAnOper(sptr))
  {
    send_reply(sptr, RPL_ENDOFLINKS, parc < 2 ? "*" : parv[1]);
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :%s %s", sptr,
                  "/LINKS has been disabled, from CFV-165.  Visit ", 
                  feature_str(FEAT_HIS_URLSERVERS));
    return 0;
  }

  if (parc > 2)
  {
    if (hunt_server_cmd(sptr, CMD_LINKS, cptr, 1, "%C :%s", 1, parc, parv) !=
        HUNTED_ISME)
      return 0;
    mask = parv[2];
  }
  else
    mask = parc < 2 ? 0 : parv[1];

  for (acptr = GlobalClientList, collapse(mask); acptr; acptr = cli_next(acptr))
  {
    if (!IsServer(acptr) && !IsMe(acptr))
      continue;
    if (!BadPtr(mask) && match(mask, cli_name(acptr)))
      continue;
    send_reply(sptr, RPL_LINKS, cli_name(acptr), cli_name(cli_serv(acptr)->up),
        cli_hopcount(acptr), cli_serv(acptr)->prot,
        ((cli_info(acptr))[0] ? cli_info(acptr) : "(Unknown Location)"));
  }

  send_reply(sptr, RPL_ENDOFLINKS, BadPtr(mask) ? "*" : mask);

  return 0;
}
Example #22
0
int
count_users(char *mask)
{
  struct Client *acptr;
  int count = 0;
  char namebuf[USERLEN + HOSTLEN + 2];
  char ipbuf[USERLEN + 16 + 2];

  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) {
    if (!IsUser(acptr))
      continue;

    ircd_snprintf(0, namebuf, sizeof(namebuf), "%s@%s",
		  cli_user(acptr)->username, cli_user(acptr)->realhost);
    ircd_snprintf(0, ipbuf, sizeof(ipbuf), "%s@%s", cli_user(acptr)->username,
		  ircd_ntoa((const char *) &(cli_ip(acptr))));

    if (!match(mask, namebuf) || !match(mask, ipbuf))
      count++;
  }

  return count;
}
Example #23
0
/*
 * Search and return as many people as matched by the wild 'nick'.
 * returns the number of people found (or, obviously, 0, if none where
 * found).
 */
static int do_wilds(struct Client* sptr, char *nick, int count, int parc)
{
  struct Client *acptr; /* Current client we're considering */
  struct User *user; 	/* the user portion of the client */
  const char *name; 	/* the name of this client */
  struct Membership* chan; 
  int invis; 		/* does +i apply? */
  int member;		/* Is this user on any channels? */
  int showperson;       /* Should we show this person? */
  int found = 0 ;	/* How many were found? */
  
  /* Ech! This is hideous! */
  for (acptr = GlobalClientList; (acptr = next_client(acptr, nick));
      acptr = cli_next(acptr))
  {
    if (!IsRegistered(acptr)) 
      continue;
      
    if (IsServer(acptr))
      continue;
    /*
     * I'm always last :-) and acptr->next == 0!!
     *
     * Isomer: Does this strike anyone else as being a horrible hideous
     *         hack?
     */
    if (IsMe(acptr)) {
      assert(!cli_next(acptr));
      break;
    }
    
    /*
     * 'Rules' established for sending a WHOIS reply:
     *
     * - if wildcards are being used don't send a reply if
     *   the querier isn't any common channels and the
     *   client in question is invisible.
     *
     * - only send replies about common or public channels
     *   the target user(s) are on;
     */
    user = cli_user(acptr);
    name = (!*(cli_name(acptr))) ? "?" : cli_name(acptr);
    assert(user);

    invis = (acptr != sptr) && IsInvisible(acptr);
    member = (user && user->channel) ? 1 : 0;
    showperson = !invis && !member;
    
    /* Should we show this person now? */
    if (showperson) {
    	found++;
    	do_whois(sptr, acptr, parc);
    	if (count+found>MAX_WHOIS_LINES)
    	  return found;
    	continue;
    }
    
    /* Step through the channels this user is on */
    for (chan = user->channel; chan; chan = chan->next_channel)
    {
      struct Channel *chptr = chan->channel;

      /* If this is a public channel, show the person */
      if (!invis && PubChannel(chptr)) {
        showperson = 1;
        break;
      }
      
      /* if this channel is +p and not +s, show them */
      if (!invis && HiddenChannel(chptr) && !SecretChannel(chptr)) {
          showperson = 1;
          break;
      }
      
      member = find_channel_member(sptr, chptr) ? 1 : 0;
      if (invis && !member)
        continue;

      /* If sptr isn't really on this channel, skip it */
      if (IsZombie(chan))
        continue;
       
      /* Is this a common channel? */ 
      if (member) {
        showperson = 1;
        break;
      }
    } /* of for (chan in channels) */
    
    /* Don't show this person */
    if (!showperson)
      continue;
      
    do_whois(sptr, acptr, parc);
    found++;
    if (count+found>MAX_WHOIS_LINES)
       return found;  
  } /* of global client list */
  
  return found;
}
Example #24
0
signed int checkHostmask(struct Client *sptr, char *hoststr, int flags) {
  struct Client *acptr;
  struct Channel *chptr;
  struct Membership *lp;
  int count = 0, found = 0, cidr_check_bits = 0;
  char outbuf[BUFSIZE];
  char targhost[NICKLEN + USERLEN + HOSTLEN + 3], curhost[NICKLEN + USERLEN + HOSTLEN + 3];
  char nickm[NICKLEN + 1], userm[USERLEN + 1], hostm[HOSTLEN + 1];
  char *p = NULL;
  struct in_addr cidr_check;

  strcpy(nickm,"*");
  strcpy(userm,"*");
  strcpy(hostm,"*");

  if (!strchr(hoststr, '!') && !strchr(hoststr, '@'))
    ircd_strncpy(hostm,hoststr,HOSTLEN);
  else {
    if ((p = strchr(hoststr, '@'))) {
      *p++ = '\0';
      if (*p) ircd_strncpy(hostm,p, HOSTLEN);
    }

    /* Get the nick!user mask */
    if ((p = strchr(hoststr, '!'))) {
      *p++ = '\0';
      if (*p) ircd_strncpy(userm,p,USERLEN);
      if (*hoststr) ircd_strncpy(nickm,hoststr,NICKLEN);
    }
    else if (*hoststr) {
      /* Durz: We should only do the following *IF* the hoststr has not already been
       * copied into hostm (ie. neither ! or @ specified).. otherwise, when we do
       * /quote check *.barrysworld.com - we end up with targhost as: *!*.barryswo@*.barrysworld.com
       */
      ircd_strncpy(userm,hoststr,USERLEN);
    }
  }
  
  if ((p = strchr(hostm, '/')) || inet_aton(hostm, &cidr_check)) {
    if (p)
      *p = '\0';
    if (inet_aton(hostm, &cidr_check)) {
      cidr_check_bits = p ? atoi(p + 1) : 32;
      if ((cidr_check_bits >= 0) && (cidr_check_bits <= 32)) {
        flags |= CHECK_CIDRMASK;
        cidr_check.s_addr &= NETMASK(cidr_check_bits);
      }
    }
    if (p)
      *p = '/';
  }

  /* Copy formatted string into "targhost" buffer */
  ircd_snprintf(0, targhost, sizeof(targhost),  "%s!%s@%s", nickm, userm, hostm);

  targhost[sizeof(targhost) - 1] = '\0';

  /* Note: we have to exclude the last client struct as it is not a real client
   * structure, and therefore any attempt to access elements in it would cause
   * a segfault.
   */

  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) {
    /* Dont process if acptr is a unregistered client, a server or a ping */
    if (!IsRegistered(acptr) || IsServer(acptr))
      continue;

    if (IsMe(acptr))   /* Always the last acptr record */
      break;

    if(count > feature_int(FEAT_MAX_CHECK_OUTPUT)) { /* sanity stuff */
      ircd_snprintf(0, outbuf, sizeof(outbuf), "More than %d results, truncating...", count);
      send_reply(sptr, RPL_DATASTR, outbuf);
      send_reply(sptr, RPL_ENDOFCHECK, " ");
      break;
    }

    /* Copy host info into buffer */
    curhost[0] = '\0';
    ircd_snprintf(0, curhost, sizeof(curhost), "%s!%s@%s", acptr->cli_name, acptr->cli_user->realusername, acptr->cli_user->realhost);

    if (flags & CHECK_CIDRMASK) {
      if (((cli_ip(acptr).s_addr & NETMASK(cidr_check_bits)) == cidr_check.s_addr) && !match(nickm, acptr->cli_name) 
            && (!match(userm, acptr->cli_user->realusername) || !match(userm, acptr->cli_user->username)))
        found = 1;
    }
    else {
      if(match((const char*)targhost,(const char*)curhost) == 0)
        found = 1;
      else {
        curhost[0] = '\0';
        ircd_snprintf(0, curhost, sizeof(curhost), "%s!%s@%s", acptr->cli_name, acptr->cli_user->username, acptr->cli_user->host);

        if(match((const char*)targhost,(const char*)curhost) == 0)
          found = 1;
      }
    }

    if (found == 1) {
      found = 0;  /* reset that so it doesn't get crazy go nuts */

      /* Show header if we've found at least 1 record */
      if (count == 0) {
        /* Output header */ 
        send_reply(sptr, RPL_DATASTR, " ");
        send_reply(sptr, RPL_CHKHEAD, "host", targhost);

        send_reply(sptr, RPL_DATASTR, " ");
        ircd_snprintf(0, outbuf, sizeof(outbuf),  "%s   %-*s%-*s%s", "No.", (NICKLEN + 2 ), "Nick",
                (USERLEN + 2), "User", "Host");
        send_reply(sptr, RPL_DATASTR, outbuf);
      }

      ircd_snprintf(0, outbuf, sizeof(outbuf), "%-4d  %-*s%-*s%s", (count+1), (NICKLEN + 2),
            acptr->cli_name, (USERLEN + 2), acptr->cli_user->realusername, 
            (flags & CHECK_SHOWIPS) ? ircd_ntoa((const char*)&(cli_ip(acptr))) : acptr->cli_user->realhost);
      send_reply(sptr, RPL_DATASTR, outbuf);

      /* Show channel output (if applicable) - the 50 channel limit sanity check
       * is specifically to prevent coredumping when someone lamely tries to /check
       * Q or some other channel service...
       */
      if (flags & CHECK_CHECKCHAN) {
        if (acptr->cli_user->joined > 0 && acptr->cli_user->joined <= 50) {
          char chntext[BUFSIZE];
          int len = strlen("      on channels: ");
          int mlen = strlen(me.cli_name) + len + strlen(sptr->cli_name);
          *chntext = '\0';

          strcpy(chntext, "      on channels: ");
          for (lp = acptr->cli_user->channel; lp; lp = lp->next_channel) {
            chptr = lp->channel;
            if (len + strlen(chptr->chname) + mlen > BUFSIZE - 5) {
              send_reply(sptr, RPL_DATASTR, chntext);
              *chntext = '\0';
              strcpy(chntext, "      on channels: ");
              len = strlen(chntext);
            }
            if (IsDeaf(acptr))
              *(chntext + len++) = '-';
            if (is_chan_op(acptr, chptr))
              *(chntext + len++) = '@';
            if (is_half_op(acptr, chptr))
              *(chntext + len++) = '%';
            if (IsOper(sptr) && !ShowChannel(sptr,chptr))
              *(chntext + len++) = '*';
            else if (has_voice(acptr, chptr))
              *(chntext + len++) = '+';
            else if (IsZombie(lp))
              *(chntext + len++) = '!';
            if (len)
              *(chntext + len) = '\0';

            strcpy(chntext + len, chptr->chname);
            len += strlen(chptr->chname);
            strcat(chntext + len, " ");
            len++;
          }
          if (chntext[0] != '\0')
            send_reply(sptr, RPL_DATASTR, chntext);

          send_reply(sptr, RPL_DATASTR, " ");
        }
      }
      count++;
    }
  }

  if (count > 0) {
    send_reply(sptr, RPL_DATASTR, " ");

    ircd_snprintf(0, outbuf, sizeof(outbuf), "Matching records found:: %d", count);
    send_reply(sptr, RPL_DATASTR, outbuf);

    send_reply(sptr, RPL_ENDOFCHECK, " ");
  }

  return count;
}
/* Rewritten by Run - 24 sept 94 */
static void exit_one_client(struct Client* bcptr, const char* comment)
{
  struct SLink *lp;
  struct Ban *bp;

  if (cli_serv(bcptr) && cli_serv(bcptr)->client_list)  /* Was SetServerYXX called ? */
    ClearServerYXX(bcptr);      /* Removes server from server_list[] */
  if (IsUser(bcptr)) {
    /*
     * clear out uping requests
     */
    if (IsUPing(bcptr))
      uping_cancel(bcptr, 0);
    /*
     * Stop a running /LIST clean
     */
    if (MyUser(bcptr) && cli_listing(bcptr)) {
      MyFree(cli_listing(bcptr));
      cli_listing(bcptr) = NULL;
    }
    /*
     * 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*)
     */
    sendcmdto_common_channels_butone(bcptr, CMD_QUIT, NULL, ":%s", comment);

    remove_user_from_all_channels(bcptr);

    /* Clean up invitefield */
    while ((lp = cli_user(bcptr)->invited))
      del_invite(bcptr, lp->value.chptr);

    /* Clean up silencefield */
    while ((bp = cli_user(bcptr)->silence)) {
      cli_user(bcptr)->silence = bp->next;
      free_ban(bp);
    }

    /* Clean up snotice lists */
    if (MyUser(bcptr))
      set_snomask(bcptr, ~0, SNO_DEL);

    if (IsInvisible(bcptr)) {
      assert(UserStats.inv_clients > 0);
      --UserStats.inv_clients;
    }
    if (IsOper(bcptr)) {
      assert(UserStats.opers > 0);
      --UserStats.opers;
    }
    if (MyConnect(bcptr))
      Count_clientdisconnects(bcptr, UserStats);
    else
      Count_remoteclientquits(UserStats, bcptr);
  }
  else if (IsServer(bcptr))
  {
    /* Remove downlink list node of uplink */
    remove_dlink(&(cli_serv(cli_serv(bcptr)->up))->down, cli_serv(bcptr)->updown);
    cli_serv(bcptr)->updown = 0;

    if (MyConnect(bcptr))
      Count_serverdisconnects(UserStats);
    else
      Count_remoteserverquits(UserStats);
  }
  else if (IsMe(bcptr))
  {
    sendto_opmask_butone(0, SNO_OLDSNO, "ERROR: tried to exit me! : %s",
			 comment);
    return;                     /* ...must *never* exit self! */
  }
  else if (IsUnknown(bcptr) || IsConnecting(bcptr) || IsHandshake(bcptr))
    Count_unknowndisconnects(UserStats);

  /*
   * Update IPregistry
   */
  if (IsIPChecked(bcptr))
    IPcheck_disconnect(bcptr);

  /* 
   * Remove from serv->client_list
   * NOTE: user is *always* NULL if this is a server
   */
  if (cli_user(bcptr)) {
    assert(!IsServer(bcptr));
    /* bcptr->user->server->serv->client_list[IndexYXX(bcptr)] = NULL; */
    RemoveYXXClient(cli_user(bcptr)->server, cli_yxx(bcptr));
  }

  /* Remove bcptr from the client list */
#ifdef DEBUGMODE
  if (hRemClient(bcptr) != 0)
    Debug((DEBUG_ERROR, "%p !in tab %s[%s] %p %p %p %d %d %p",
          bcptr, cli_name(bcptr), cli_from(bcptr) ? cli_sockhost(cli_from(bcptr)) : "??host",
          cli_from(bcptr), cli_next(bcptr), cli_prev(bcptr), cli_fd(bcptr),
          cli_status(bcptr), cli_user(bcptr)));
#else
  hRemClient(bcptr);
#endif
  remove_client_from_list(bcptr);
}
Example #26
0
/** Report memory usage statistics to a client.
 * @param cptr Client to send data to.
 * @param sd StatDesc that generated the stats request (ignored).
 * @param param Extra parameter from user (ignored).
 */
void count_memory(struct Client *cptr, const struct StatDesc *sd,
                  char *param)
{
  struct Client *acptr;
  struct Invite *inv;
  struct SLink *link;
  struct Ban *ban;
  struct Channel *chptr;
  struct ConfItem *aconf;
  const struct ConnectionClass* cltmp;
  struct Membership* member;

  int acc = 0,                  /* accounts */
      c = 0,                    /* clients */
      cn = 0,                   /* connections */
      ch = 0,                   /* channels */
      lcc = 0,                  /* local client conf links */
      chb = 0,                  /* channel bans */
      wwu = 0,                  /* whowas users */
      cl = 0,                   /* classes */
      co = 0,                   /* conf lines */
      listeners = 0,            /* listeners */
      memberships = 0;          /* channel memberships */

  int usi = 0,                  /* users invited */
      aw = 0,                   /* aways set */
      wwa = 0,                  /* whowas aways */
      gl = 0,                   /* glines */
      ju = 0;                   /* jupes */

  size_t chm = 0,               /* memory used by channels */
      chbm = 0,                 /* memory used by channel bans */
      cm = 0,                   /* memory used by clients */
      cnm = 0,                  /* memory used by connections */
      us = 0,                   /* user structs */
      usm = 0,                  /* memory used by user structs */
      awm = 0,                  /* memory used by aways */
      wwam = 0,                 /* whowas away memory used */
      wwm = 0,                  /* whowas array memory used */
      wt = 0,                   /* watch entrys */
      wtm = 0,                  /* memory used by watchs */
#if defined(DDB)
      dbs = 0,                  /* keys of database */
      dbm = 0,                  /* memory used by DDB */
#endif
      glm = 0,                  /* memory used by glines */
      jum = 0,                  /* memory used by jupes */
      com = 0,                  /* memory used by conf lines */
      dbufs_allocated = 0,      /* memory used by dbufs */
      dbufs_used = 0,           /* memory used by dbufs */
      msg_allocated = 0,	/* memory used by struct Msg */
      msgbuf_allocated = 0,	/* memory used by struct MsgBuf */
      listenersm = 0,           /* memory used by listetners */
      rm = 0,                   /* res memory used */
      totcl = 0, totch = 0, totww = 0, tot = 0;

  count_whowas_memory(&wwu, &wwm, &wwa, &wwam);
  wwm += sizeof(struct Whowas) * feature_uint(FEAT_NICKNAMEHISTORYLENGTH);
  wwm += sizeof(struct Whowas *) * WW_MAX;

  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr))
  {
    c++;
    if (MyConnect(acptr))
    {
      cn++;
      for (link = cli_confs(acptr); link; link = link->next)
        lcc++;
    }
    if (cli_user(acptr))
    {
      for (inv = cli_user(acptr)->invited; inv; inv = inv->next_user)
        usi++;
      for (member = cli_user(acptr)->channel; member; member = member->next_channel)
        ++memberships;
      if (cli_user(acptr)->away)
      {
        aw++;
        awm += (strlen(cli_user(acptr)->away) + 1);
      }
    }
#if defined(UNDERNET)
    if (IsAccount(acptr))
      acc++;
#endif
  }
  cm = c * sizeof(struct Client);
  cnm = cn * sizeof(struct Connection);
  user_count_memory(&us, &usm);

  for (chptr = GlobalChannelList; chptr; chptr = chptr->next)
  {
    ch++;
    chm += (strlen(chptr->chname) + sizeof(struct Channel));
    for (ban = chptr->banlist; ban; ban = ban->next)
    {
      chb++;
      chbm += strlen(ban->who) + strlen(ban->banstr) + 2 + sizeof(*ban);
    }
  }

  for (aconf = GlobalConfList; aconf; aconf = aconf->next)
  {
    co++;
    com += aconf->host ? strlen(aconf->host) + 1 : 0;
    com += aconf->passwd ? strlen(aconf->passwd) + 1 : 0;
    com += aconf->name ? strlen(aconf->name) + 1 : 0;
    com += sizeof(struct ConfItem);
  }

  for (cltmp = get_class_list(); cltmp; cltmp = cltmp->next)
    cl++;

#if defined(USE_SSL)
  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
	     ":Clients %d(%zu) Connections %d(%zu) SSL %d", c, cm, cn, cnm, ssl_count());
#else
  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
	     ":Clients %d(%zu) Connections %d(%zu)", c, cm, cn, cnm);
#endif
  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
	     ":Users %zu(%zu) Accounts %d(%zu) Invites %d(%zu)",
             us, usm, acc, acc * (ACCOUNTLEN + 1),
	     usi, usi * sizeof(struct Invite));
  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
	     ":User channels %d(%zu) Aways %d(%zu)", memberships,
	     memberships * sizeof(struct Membership), aw, awm);

  totcl = cm + cnm + us * sizeof(struct User) + memberships * sizeof(struct Membership) + awm;
  totcl += lcc * sizeof(struct SLink) + usi * sizeof(struct SLink);

  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":Conflines %d(%zu) Attached %d(%zu) Classes %d(%zu)",
             co, com, lcc, lcc * sizeof(struct SLink),
             cl, cl * sizeof(struct ConnectionClass));

  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
	     ":Channels %d(%zu) Bans %d(%zu)", ch, chm, chb, chbm);
  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
	     ":Channel Members %d(%zu)", memberships,
	     memberships * sizeof(struct Membership));

  totch = chm + chbm;

  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
	     ":Whowas Users %d(%zu) Away %d(%zu) Array %u(%zu)",
             wwu, wwu * sizeof(struct User), wwa, wwam,
             feature_uint(FEAT_NICKNAMEHISTORYLENGTH), wwm);

  totww = wwu * sizeof(struct User) + wwam + wwm;

  watch_count_memory(&wt, &wtm);
  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
             ":Watchs %d(%zu)", wt, wtm);

  motd_memory_count(cptr);

  gl = gline_memory_count(&glm);
  ju = jupe_memory_count(&jum);
  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
	     ":Glines %d(%zu) Jupes %d(%zu)", gl, glm, ju, jum);

  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
	     ":Hash: client %d(%zu), chan is the same", HASHSIZE,
	     sizeof(void *) * HASHSIZE);

  count_listener_memory(&listeners, &listenersm);
  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
             ":Listeners allocated %d(%zu)", listeners, listenersm);

#if defined(DDB)
  ddb_count_memory(&dbs, &dbm);
  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
             ":DDB keys allocated %d(%zu)", dbs, dbm);
#endif

  /*
   * NOTE: this count will be accurate only for the exact instant that this
   * message is being sent, so the count is affected by the dbufs that
   * are being used to send this message out. If this is not desired, move
   * the dbuf_count_memory call to a place before we start sending messages
   * and cache DBufAllocCount and DBufUsedCount in variables until they
   * are sent.
   */
  dbuf_count_memory(&dbufs_allocated, &dbufs_used);
  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
	     ":DBufs allocated %u(%zu) used %u(%zu)", DBufAllocCount,
	     dbufs_allocated, DBufUsedCount, dbufs_used);

  /* The DBuf caveats now count for this, but this routine now sends
   * replies all on its own.
   */
  msgq_count_memory(cptr, &msg_allocated, &msgbuf_allocated);

  rm = cres_mem(cptr);

  tot =
      totww + totch + totcl + com + cl * sizeof(struct ConnectionClass) +
      dbufs_allocated + msg_allocated + msgbuf_allocated + rm;
  tot += sizeof(void *) * HASHSIZE * 3;

#if defined(MDEBUG)
  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG, ":Allocations: %zu(%zu)",
	     fda_get_block_count(), fda_get_byte_count());
#endif

  send_reply(cptr, SND_EXPLICIT | RPL_STATSDEBUG,
	     ":Total: ww %zu ch %zu cl %zu co %zu db %zu ms %zu mb %zu",
	     totww, totch, totcl, com, dbufs_allocated, msg_allocated,
	     msgbuf_allocated);
}
Example #27
0
int m_names(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Channel *chptr; 
  struct Channel *ch2ptr; 
  struct Client *c2ptr;
  struct Membership* member; 
  char* s;
  char* para = parc > 1 ? parv[1] : 0; 
  int showingdelayed = 0;

  if (parc > 1 && !ircd_strcmp(parv[1], "-D")) {
    para = (parc > 2) ? parv[2] : 0;
    showingdelayed = NAMES_DEL;
    if (parc > 3 && hunt_server_cmd(sptr, CMD_NAMES, cptr, 1, "%s %s %C", 3, parc, parv))
      return 0;
  } else if (parc > 2 && hunt_server_cmd(sptr, CMD_NAMES, cptr, 1, "%s %C", 2, parc, parv))
    return 0;

  if (EmptyString(para)) {
    send_reply(sptr, RPL_ENDOFNAMES, "*");
    return 0;
  }

  do {
    s = strchr(para, ',');
    if (s)
      *s++ = '\0';
    /*
     * Special Case 1: "/names 0". 
     * Full list as per RFC. 
     */
    if ((*para == '0') || (*para == '\0'))
    {
      int idx; 
      int mlen;
      int flag;
      struct Channel *ch3ptr;
      char buf[BUFSIZE]; 

      mlen = strlen(cli_name(&me)) + 10 + strlen(cli_name(sptr));

      /* List all visible channels/visible members */ 

      for (ch2ptr = GlobalChannelList; ch2ptr; ch2ptr = ch2ptr->next)
      { 
        if (!ShowChannel(sptr, ch2ptr))
          continue;                 /* Don't show secret chans. */ 
        else if (find_channel_member(sptr, ch2ptr))
          do_names(sptr, ch2ptr, showingdelayed|NAMES_ALL); /* Full list if we're in this chan. */
        else
          do_names(sptr, ch2ptr, showingdelayed|NAMES_VIS);
      } 

      /* List all remaining users on channel '*' */

      strcpy(buf, "* * :");
      idx = 5;
      flag = 0;

      for (c2ptr = GlobalClientList; c2ptr; c2ptr = cli_next(c2ptr))
      {
        int showflag = 0;

        if (!IsUser(c2ptr) || (sptr != c2ptr && IsInvisible(c2ptr)))
          continue;

        member = cli_user(c2ptr)->channel;

        while (member)
        {
          ch3ptr = member->channel;
  
          if (PubChannel(ch3ptr) || find_channel_member(sptr, ch3ptr))
            showflag = 1;
 
          member = member->next_channel;
        }

        if (showflag)               /* Have we already shown them? */
          continue;
 
        strcpy(buf + idx, cli_name(c2ptr));
        idx += strlen(cli_name(c2ptr));
        buf[idx++] = ' ';
        flag = 1;

        if (mlen + idx + NICKLEN + 3 > BUFSIZE)     /* space, \r\n\0 */
        {
          send_reply(sptr, RPL_NAMREPLY, buf);
          strcpy(buf, "* * :");
          idx = 5;
          flag = 0;
        }
      }
      if (flag)
        send_reply(sptr, RPL_NAMREPLY, buf);
      send_reply(sptr, RPL_ENDOFNAMES, "*");
    }
    else if ((chptr = FindChannel(para)) != NULL)
    {
      member = find_member_link(chptr, sptr);
      if (member)
      {
        /*
         *  Special Case 2: User is on this channel, requesting full names list.
         *  (As performed with each /join) - ** High frequency usage **
         */
        do_names(sptr, chptr, showingdelayed|NAMES_ALL|NAMES_EON);
      }
      else
      {
        /*
         *  Special Case 3: User isn't on this channel, show all visible users, in 
         *  non secret channels.
         */ 
        do_names(sptr, chptr, showingdelayed|NAMES_VIS|NAMES_EON);
      } 
    }
    else
        send_reply(sptr, RPL_ENDOFNAMES, para);
  } while ((para = s) != NULL);

  return 1;
}
Example #28
0
static
void do_trace(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
    int i;
    struct Client *acptr;
    struct Client *acptr2;
    const struct ConnectionClass* cl;
    char* tname;
    int doall;
    int *link_s;
    int *link_u;
    int cnt = 0;
    int wilds;
    int dow;

    if (parc < 2 || BadPtr(parv[1]))
    {
        /* just "TRACE" without parameters. Must be from local client */
        parc = 1;
        acptr = &me;
        tname = cli_name(&me);
        i = HUNTED_ISME;
    }
    else if (parc < 3 || BadPtr(parv[2]))
    {
        /* No target specified. Make one before propagating. */
        parc = 2;
        tname = parv[1];
        if ((acptr = find_match_server(parv[1])) ||
                ((acptr = FindClient(parv[1])) && !MyUser(acptr)))
        {
            if (IsUser(acptr))
                parv[2] = cli_name(cli_user(acptr)->server);
            else
                parv[2] = cli_name(acptr);
            parc = 3;
            parv[3] = 0;
            if ((i = hunt_server_cmd(sptr, CMD_TRACE, cptr, IsServer(acptr),
                                     "%s :%C", 2, parc, parv)) == HUNTED_NOSUCH)
                return;
        }
        else
            i = HUNTED_ISME;
    } else {
        /* Got "TRACE <tname> :<target>" */
        parc = 3;
        if (MyUser(sptr) || Protocol(cptr) < 10)
            acptr = find_match_server(parv[2]);
        else
            acptr = FindNServer(parv[2]);
        if ((i = hunt_server_cmd(sptr, CMD_TRACE, cptr, 0, "%s :%C", 2, parc,
                                 parv)) == HUNTED_NOSUCH)
            return;
        tname = parv[1];
    }

    if (i == HUNTED_PASS) {
        if (!acptr)
            acptr = next_client(GlobalClientList, tname);
        else
            acptr = cli_from(acptr);
        send_reply(sptr, RPL_TRACELINK,
                   version, debugmode, tname,
                   acptr ? cli_name(cli_from(acptr)) : "<No_match>");
        return;
    }

    doall = (parv[1] && (parc > 1)) ? !match(tname, cli_name(&me)) : 1;
    wilds = !parv[1] || strchr(tname, '*') || strchr(tname, '?');
    dow = wilds || doall;

    /* Don't give (long) remote listings to lusers */
    if (dow && !MyConnect(sptr) && !IsAnOper(sptr)) {
        send_reply(sptr, RPL_TRACEEND);
        return;
    }

    link_s = MyCalloc(2 * maxconnections, sizeof(link_s[0]));
    link_u = link_s + maxconnections;

    if (doall) {
        for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) {
            if (IsUser(acptr))
                link_u[cli_fd(cli_from(acptr))]++;
            else if (IsServer(acptr))
                link_s[cli_fd(cli_from(acptr))]++;
        }
    }

    /* report all direct connections */

    for (i = 0; i <= HighestFd; i++) {
        const char *conClass;

        if (!(acptr = LocalClientArray[i])) /* Local Connection? */
            continue;
        if (IsInvisible(acptr) && dow && !(MyConnect(sptr) && IsOper(sptr)) &&
                !IsAnOper(acptr) && (acptr != sptr))
            continue;
        if (!doall && wilds && match(tname, cli_name(acptr)))
            continue;
        if (!dow && 0 != ircd_strcmp(tname, cli_name(acptr)))
            continue;

        conClass = get_client_class(acptr);

        switch (cli_status(acptr)) {
        case STAT_CONNECTING:
            send_reply(sptr, RPL_TRACECONNECTING, conClass, cli_name(acptr));
            cnt++;
            break;
        case STAT_HANDSHAKE:
            send_reply(sptr, RPL_TRACEHANDSHAKE, conClass, cli_name(acptr));
            cnt++;
            break;
        case STAT_ME:
            break;
        case STAT_UNKNOWN:
        case STAT_UNKNOWN_USER:
            send_reply(sptr, RPL_TRACEUNKNOWN, conClass,
                       get_client_name(acptr, HIDE_IP));
            cnt++;
            break;
        case STAT_UNKNOWN_SERVER:
            send_reply(sptr, RPL_TRACEUNKNOWN, conClass, "Unknown Server");
            cnt++;
            break;
        case STAT_USER:
            /* Only opers see users if there is a wildcard
               but anyone can see all the opers. */
            if ((IsAnOper(sptr) && (MyUser(sptr) ||
                                    !(dow && IsInvisible(acptr)))) || !dow || IsAnOper(acptr)) {
                if (IsAnOper(acptr))
                    send_reply(sptr, RPL_TRACEOPERATOR, conClass,
                               get_client_name(acptr, SHOW_IP),
                               CurrentTime - cli_lasttime(acptr));
                else
                    send_reply(sptr, RPL_TRACEUSER, conClass,
                               get_client_name(acptr, SHOW_IP),
                               CurrentTime - cli_lasttime(acptr));
                cnt++;
            }
            break;
        /*
         * Connection is a server
         *
         * Serv <class> <nS> <nC> <name> <ConnBy> <last> <age>
         *
         * class        Class the server is in
         * nS           Number of servers reached via this link
         * nC           Number of clients reached via this link
         * name         Name of the server linked
         * ConnBy       Who established this link
         * last         Seconds since we got something from this link
         * age          Seconds this link has been alive
         *
         * Additional comments etc......        -Cym-<*****@*****.**>
         */

        case STAT_SERVER:
            if (cli_serv(acptr)->user) {
                if (!cli_serv(acptr)->by[0]
                        || !(acptr2 = findNUser(cli_serv(acptr)->by))
                        || (cli_user(acptr2) != cli_serv(acptr)->user))
                    acptr2 = NULL;
                send_reply(sptr, RPL_TRACESERVER, conClass, link_s[i],
                           link_u[i], cli_name(acptr),
                           acptr2 ? cli_name(acptr2) : "*",
                           cli_serv(acptr)->user->username,
                           cli_serv(acptr)->user->host,
                           CurrentTime - cli_lasttime(acptr),
                           CurrentTime - cli_serv(acptr)->timestamp);
            } else
                send_reply(sptr, RPL_TRACESERVER, conClass, link_s[i],
                           link_u[i], cli_name(acptr),
                           (*(cli_serv(acptr))->by) ?  cli_serv(acptr)->by : "*", "*",
                           cli_name(&me), CurrentTime - cli_lasttime(acptr),
                           CurrentTime - cli_serv(acptr)->timestamp);
            cnt++;
            break;
        default:                  /* We actually shouldn't come here, -msa */
            send_reply(sptr, RPL_TRACENEWTYPE, get_client_name(acptr, HIDE_IP));
            cnt++;
            break;
        }
    }
    /*
     * Add these lines to summarize the above which can get rather long
     * and messy when done remotely - Avalon
     */
    if (IsAnOper(sptr) && doall) {
        for (cl = get_class_list(); cl; cl = cl->next) {
            if (Links(cl) > 1)
                send_reply(sptr, RPL_TRACECLASS, ConClass(cl), Links(cl) - 1);
        }
    }
    send_reply(sptr, RPL_TRACEEND);
    MyFree(link_s);
}
Example #29
0
File: send.c Project: mojadita/ircd
/** Send a (prefixed) command to all users matching \a to as \a who.
 * @warning \a pattern must not contain %v.
 * @param[in] from Source of the command.
 * @param[in] cmd Long name of command.
 * @param[in] tok Short name of command.
 * @param[in] to Destination host/server mask.
 * @param[in] one Client direction to skip (or NULL).
 * @param[in] who Type of match for \a to (either MATCH_HOST or MATCH_SERVER).
 * @param[in] pattern Format string for command arguments.
 */
void sendcmdto_match(struct Client *from, const char *cmd,
                     const char *tok, const char *to,
                     struct Client *one, unsigned int who,
                     const char *pattern, ...)
{
  struct VarData vd;
  struct irc_in_addr addr;
  struct Client *cptr;
  struct MsgBuf *user_mb;
  struct MsgBuf *serv_mb;
  unsigned char nbits;

  vd.vd_format = pattern;

  /* See if destination looks like an IP mask. */
  if (!ipmask_parse(to, &addr, &nbits))
    nbits = 255;

  /* Build buffer to send to users */
  va_start(vd.vd_args, pattern);
/*
TODO-ZOLTAN: Revisar el tema de Globales
  if (IsUser(from) && IsService(cli_user(from)->server))
*/
  user_mb = msgq_make(0, "%:#C %s %v", from, cmd, &vd);
/*
  else
  {
    char *mask, *msg;
    mask = (char *)va_arg(vd.vd_args, char *);
    msg = (char *)va_arg(vd.vd_args, char *);

    user_mb = msgq_make(0, "%:#C %s :*** Global Message -> (%s): %s",
                        from, cmd, mask, msg);
  }
*/
  va_end(vd.vd_args);

  /* Build buffer to send to servers */
  va_start(vd.vd_args, pattern);
  serv_mb = msgq_make(&me, "%C %s %v", from, tok, &vd);
  va_end(vd.vd_args);

  /* send buffer along */
  bump_sentalong(one);
  for (cptr = GlobalClientList; cptr; cptr = cli_next(cptr)) {
    if (cli_sentalong(cptr) == sentalong_marker ||
        !IsRegistered(cptr) ||
        IsServer(cptr) ||
    !match_it(from, cptr, to, &addr, nbits, who) ||
        cli_fd(cli_from(cptr)) < 0)
      continue; /* skip it */
    cli_sentalong(cptr) = sentalong_marker;

    if (MyConnect(cptr)) /* send right buffer */
      send_buffer(cptr, user_mb, 0);
    else
      send_buffer(cptr, serv_mb, 0);
  }

  msgq_clean(user_mb);
  msgq_clean(serv_mb);
}