Пример #1
0
/*
** mo_ojoin
**      parv[1] = channel
*/
static void
mo_ojoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr;
	int move_me = 0;

	/* admins only */
	if(!IsOperAdmin(source_p))
	{
		sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin");
		return;
	}

	if(*parv[1] == '@' || *parv[1] == '+')
	{
		parv[1]++;
		move_me = 1;
	}

	if((chptr = find_channel(parv[1])) == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
				   form_str(ERR_NOSUCHCHANNEL), parv[1]);
		return;
	}

	if(IsMember(source_p, chptr))
	{
		sendto_one_notice(source_p, ":Please part %s before using OJOIN", parv[1]);
		return;
	}

	if(move_me == 1)
		parv[1]--;

	sendto_wallops_flags(UMODE_WALLOP, &me,
			     "OJOIN called for %s by %s!%s@%s",
			     parv[1], source_p->name, source_p->username, source_p->host);
	ilog(L_MAIN, "OJOIN called for %s by %s",
	     parv[1], get_oper_name(source_p));
	/* only sends stuff for #channels remotely */
	sendto_server(NULL, chptr, NOCAPS, NOCAPS,
			":%s WALLOPS :OJOIN called for %s by %s!%s@%s",
			me.name, parv[1],
			source_p->name, source_p->username, source_p->host);

	if(*parv[1] == '@')
	{
		add_user_to_channel(chptr, source_p, CHFL_CHANOP);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :@%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		send_channel_join(chptr, source_p);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s",
				     me.name, chptr->chname, source_p->name);

	}
	else if(*parv[1] == '+')
	{
		add_user_to_channel(chptr, source_p, CHFL_VOICE);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :+%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		send_channel_join(chptr, source_p);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +v %s",
				     me.name, chptr->chname, source_p->name);
	}
	else
	{
		add_user_to_channel(chptr, source_p, CHFL_PEON);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s JOIN %ld %s +",
			      source_p->id, (long) chptr->channelts, chptr->chname);
		send_channel_join(chptr, source_p);
	}

	/* send the topic... */
	if(chptr->topic != NULL)
	{
		sendto_one(source_p, form_str(RPL_TOPIC), me.name,
			   source_p->name, chptr->chname, chptr->topic);
		sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name,
			   source_p->name, chptr->chname, chptr->topic_info, chptr->topic_time);
	}

	source_p->localClient->last_join_time = rb_current_time();
	channel_member_names(chptr, source_p, 1);
}
Пример #2
0
int
m_scan_umodes(struct Client *cptr, struct Client *sptr, int parc, char *parv[], char *varparv[])
{
  char *umode_string = parv[2], *c;
  user_modes include_modes, exclude_modes;
  int what = MODE_ADD;
  int mode;
  int list_users = 1;
  int list_max = 0;
  int allowed = 1;
  int listed_so_far = 0, count = 0;
  char *mask = NULL;
  struct Client *acptr;
  int i;

  if (!HasUmode(sptr,UMODE_USER_AUSPEX))
    {
      if (SeesOperMessages(sptr))
	sendto_one(sptr,":%s NOTICE %s :You have no a umode", me.name, parv[0]);
      else
	sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }

  if (parc < 3)
    {
      if (!IsServer(sptr))
	sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
		   me.name, parv[0], "SCAN UMODES");
      return 0;
    }

  ClearBitfield(include_modes);
  ClearBitfield(exclude_modes);

  for (c = umode_string; *c; c++)
    switch(*c)
      {
      case '+':
	what = MODE_ADD;
	break;
      case '-':
	what = MODE_DEL;
	break;
      default:
	if ((mode = user_modes_from_c_to_bitmask[(unsigned char)*c]))
	  {
	    if (what == MODE_ADD)
	      SetBit(include_modes, mode);
	    else
	      SetBit(exclude_modes, mode);
	  }
	else
	  {
	    sendto_one(sptr, form_str(ERR_UNKNOWNMODE), me.name, sptr->name, *c);
	    return 0;
	  }
      }

  for (i = 3; i < parc; i++)
    {
      if (!irccmp(parv[i], "no-list"))
	list_users = 0;
      else if (!irccmp(parv[i], "list"))
	list_users = 1;
      else if (!irccmp(parv[i], "allowed"))
	allowed = 1;
      else if (!irccmp(parv[i], "current"))
	allowed = 0;
      else if (i < (parc - 1))
	{
	  if (!irccmp(parv[i], "list-max"))
	    {
	      list_max = atoi(parv[++i]);
	    }
	  else if (!irccmp(parv[i], "mask"))
	    {
	      mask = parv[++i];
	    }
	}
    }

  for (acptr = GlobalClientList; acptr; acptr = acptr->next)
    {
      char *s;
      user_modes working_umodes;

      if (!IsClient(acptr))
	continue;

      if (allowed)
	AndUmodes(working_umodes, acptr->allowed_umodes, include_modes);
      else
	AndUmodes(working_umodes, acptr->umodes, include_modes);

      if (!SameBits(working_umodes, include_modes))
	continue;

      if (allowed)
	AndUmodes(working_umodes, acptr->allowed_umodes, exclude_modes);
      else
	AndUmodes(working_umodes, acptr->umodes, exclude_modes);

      if (AnyBits(working_umodes))
	continue;

      s = make_nick_user_host(acptr->name, acptr->username,
			      acptr->host);

      if (mask && !match(mask, s))
	continue;

      if (list_users && (!list_max || (listed_so_far < list_max)))
	{
	  char buf[BUFSIZE];
	  char *m = buf;
	  int i;
	  *m++ = '+';
	  for (i = 0; user_mode_table[i].letter && (m - buf < BUFSIZE - 4);i++)
	    if (TestBit(allowed ? acptr->allowed_umodes : acptr->umodes, user_mode_table[i].mode))
	      *m++ = user_mode_table[i].letter;
	  *m = '\0';
	  listed_so_far++;
	  sendto_one(sptr, form_str(RPL_MODE),
		     me.name, sptr->name,
		     acptr->name, buf);
	}
      count++;
    }

  send_markup(sptr, &me, "UMODE-END", "End of user mode list");
/*   send_markup(sptr, &me, "SCAN-SUMMARY", "!begin<1>%d!end<1> matched", count); */
  send_markup(sptr, &me, "SCAN-SUMMARY", "%d matched", count);

  return 0;
}
Пример #3
0
/*
 * send_conf_options
 *
 * inputs	- client pointer to send to
 * output	- none
 * side effects	- send config options to client
 */
static void
send_conf_options(struct Client *source_p)
{
	Info *infoptr;
	int i = 0;

	/*
	 * Now send them a list of all our configuration options
	 * (mostly from config.h)
	 */
	for (infoptr = MyInformation; infoptr->name; infoptr++)
	{
		if(infoptr->intvalue)
		{
			sendto_one(source_p, ":%s %d %s :%-30s %-5d [%-30s]",
				   get_id(&me, source_p), RPL_INFO,
				   get_id(source_p, source_p),
				   infoptr->name, infoptr->intvalue, 
				   infoptr->desc);
		}
		else
		{
			sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]",
				   get_id(&me, source_p), RPL_INFO,
				   get_id(source_p, source_p),
				   infoptr->name, infoptr->strvalue, 
				   infoptr->desc);
		}
	}

	/*
	 * Parse the info_table[] and do the magic.
	 */
	for (i = 0; info_table[i].name; i++)
	{
		switch (info_table[i].output_type)
		{
			/*
			 * For "char *" references
			 */
		case OUTPUT_STRING:
			{
				char *option = *((char **) info_table[i].option);

				sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]",
					   get_id(&me, source_p), RPL_INFO,
					   get_id(source_p, source_p),
					   info_table[i].name,
					   option ? option : "NONE",
					   info_table[i].desc ? info_table[i].desc : "<none>");

				break;
			}
			/*
			 * For "char foo[]" references
			 */
		case OUTPUT_STRING_PTR:
			{
				char *option = (char *) info_table[i].option;

				sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]",
					   get_id(&me, source_p), RPL_INFO,
					   get_id(source_p, source_p),
					   info_table[i].name,
					   EmptyString(option) ? "NONE" : option,
					   info_table[i].desc ? info_table[i].desc : "<none>");

				break;
			}
			/*
			 * Output info_table[i].option as a decimal value.
			 */
		case OUTPUT_DECIMAL:
			{
				int option = *((int *) info_table[i].option);

				sendto_one(source_p, ":%s %d %s :%-30s %-5d [%-30s]",
					   get_id(&me, source_p), RPL_INFO,
					   get_id(source_p, source_p),
					   info_table[i].name,
					   option,
					   info_table[i].desc ? info_table[i].desc : "<none>");

				break;
			}

			/*
			 * Output info_table[i].option as "ON" or "OFF"
			 */
		case OUTPUT_BOOLEAN:
			{
				int option = *((int *) info_table[i].option);

				sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]",
					   get_id(&me, source_p), RPL_INFO,
					   get_id(source_p, source_p),
					   info_table[i].name,
					   option ? "ON" : "OFF",
					   info_table[i].desc ? info_table[i].desc : "<none>");

				break;
			}
			/*
			 * Output info_table[i].option as "YES" or "NO"
			 */
		case OUTPUT_BOOLEAN_YN:
			{
				int option = *((int *) info_table[i].option);

				sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]",
					   get_id(&me, source_p), RPL_INFO,
					   get_id(source_p, source_p),
					   info_table[i].name,
					   option ? "YES" : "NO",
					   info_table[i].desc ? info_table[i].desc : "<none>");

				break;
			}

		case OUTPUT_BOOLEAN2:
		{
			int option = *((int *) info_table[i].option);

			sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]",
				   me.name, RPL_INFO, source_p->name,
				   info_table[i].name,
				   option ? ((option == 1) ? "MASK" : "YES") : "NO",
				   info_table[i].desc ? info_table[i].desc : "<none>");
		}		/* switch (info_table[i].output_type) */
		}
	}			/* forloop */


	/* Don't send oper_only_umodes...it's a bit mask, we will have to decode it
	 ** in order for it to show up properly to opers who issue INFO
	 */

	sendto_one_numeric(source_p, RPL_INFO, form_str(RPL_INFO), "");
}
Пример #4
0
int
m_scan_cmodes(struct Client *cptr, struct Client *sptr, int parc, char *parv[], char *varparv[])
{
  char *cmode_string = parv[2], *c;
  unsigned int include_modes, exclude_modes;
  int require_autodline = 0, require_forward = 0;
  int what = MODE_ADD;
  int list_channels = 1;
  int list_max = 0;
  int listed_so_far = 0, count = 0;
  char *mask = NULL;
  struct Channel *achptr;
  int i;

  if (!HasUmode(sptr,UMODE_USER_AUSPEX))
    {
      if (SeesOperMessages(sptr))
	sendto_one(sptr,":%s NOTICE %s :You have no a umode", me.name, parv[0]);
      else
	sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }

  if (parc < 3)
    {
      if (!IsServer(sptr))
	sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
		   me.name, parv[0], "SCAN CMODES");
      return 0;
    }

  include_modes = exclude_modes = 0;

  for (c = cmode_string; *c; c++)
    switch(*c)
      {
      case '+':
	what = MODE_ADD;
	break;
      case '-':
	what = MODE_DEL;
	break;
      default:
        {
          int this_mode = 0;
          switch(*c)
            {
            case 'c':
              this_mode = MODE_NOCOLOR;
              break;
            case 'D':
	      require_autodline = what == MODE_ADD ? 1 : -1;
              break;
#ifdef INVITE_CHANNEL_FORWARDING
            case 'f':
	      require_forward = what == MODE_ADD ? 1 : -1;
              break;
#endif
            case 'g':
              this_mode = MODE_FREEINVITE;
              break;
            case 'i':
              this_mode = MODE_INVITEONLY;
              break;
#ifdef JUPE_CHANNEL
            case 'j':
              this_mode = MODE_JUPED;
              break;
#endif
            case 'L':
              this_mode = MODE_LARGEBANLIST;
              break;
            case 'm':
              this_mode = MODE_MODERATED;
              break;
            case 'n':
              this_mode = MODE_NOPRIVMSGS;
              break;
            case 'P':
              this_mode = MODE_PERM;
              break;
            case 'Q':
              this_mode = MODE_NOFORWARD;
              break;
            case 'r':
              this_mode = MODE_NOUNIDENT;
              break;
            case 'R':
              this_mode = MODE_QUIETUNIDENT;
              break;
            case 's':
              this_mode = MODE_SECRET;
              break;
            case 't':
              this_mode = MODE_TOPICLIMIT;
              break;
            case 'z':
              this_mode = MODE_OPMODERATE;
              break;
            default:
	      sendto_one(sptr, form_str(ERR_UNKNOWNMODE), me.name, sptr->name, *c);
	      return 0;
            }

          if (what == MODE_ADD)
            include_modes |= this_mode;
          else
            exclude_modes |= this_mode;
        }
      }

  for (i = 3; i < parc; i++)
    {
      if (!irccmp(parv[i], "no-list"))
	list_channels = 0;
      else if (!irccmp(parv[i], "list"))
	list_channels = 1;
      else if (i < (parc - 1))
	{
	  if (!irccmp(parv[i], "list-max"))
	    {
	      list_max = strtoul(parv[++i], NULL, 0);
	    }
	  else if (!irccmp(parv[i], "mask"))
	    {
	      mask = parv[++i];
	    }
	}
    }

  for (achptr = channel; achptr; achptr = achptr->nextch)
    {
      if ((achptr->mode.mode & include_modes) != include_modes)
        continue;

      if ((achptr->mode.mode & exclude_modes))
        continue;

#ifdef INVITE_CHANNEL_FORWARDING
      if (achptr->mode.invite_forward_channel_name[0] && require_forward == -1)
	continue;
      if (!achptr->mode.invite_forward_channel_name[0] && require_forward == 1)
	continue;
#endif

      if (achptr->mode.autodline_frequency && require_autodline == -1)
	continue;
      if (!achptr->mode.autodline_frequency && require_autodline == 1)
	continue;

      if (list_channels && (!list_max || (listed_so_far < list_max)))
	{
          static char     modebuf[MODEBUFLEN];
          static char     parabuf[MODEBUFLEN];
	  listed_so_far++;
          *modebuf = *parabuf = '\0';
          modebuf[1] = '\0';
          channel_modes(sptr, modebuf, parabuf, achptr);
	  sendto_one(sptr, form_str(RPL_CHANNELMODEIS),
                       me.name, sptr->name,
                       achptr->chname, modebuf, parabuf);
	}
      count++;
    }

  send_markup(sptr, &me, "CMODE-END", "End of channel mode list");
/*   send_markup(sptr, &me, "SCAN-SUMMARY", "!begin<1>%d!end<1> matched", count); */
  send_markup(sptr, &me, "SCAN-SUMMARY", "%d matched", count);

  return 0;
}
Пример #5
0
int
m_scan_unklines(struct Client *cptr, struct Client *sptr, int parc, char *parv[], char *varparv[])
{
  char *mask = NULL;
  int list = 1, count = 0, listed_so_far = 0;
  int list_max = 100;
  int i;
  struct unkline_record **ukr, *ukr2;

  if (!HasUmode(sptr,UMODE_SEEKLINES))
    {
      if (SeesOperMessages(sptr))
	sendto_one(sptr,":%s NOTICE %s :You have no 2 umode", me.name, parv[0]);
      else
	sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }

  if (parc < 2)
    {
      if (!IsServer(sptr))
	sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
		   me.name, parv[0], "SCAN UNKLINES");
      return 0;
    }

  for (i = 2; i < parc; i++)
    {
      if (!irccmp(parv[i], "no-list"))
	list = 0;
      else if (!irccmp(parv[i], "list"))
	list = 1;
      else if (i < (parc - 1))
	{
	  if (!irccmp(parv[i], "list-max"))
	    {
	      list_max = atoi(parv[++i]);
	    }
	  else if (!irccmp(parv[i], "mask"))
	    {
	      mask = parv[++i];
	    }
	}
    }

  for (ukr = &recorded_unklines; (ukr2 = *ukr); ukr = &ukr2->next)
    {
      if ((ukr2->placed + UNKLINE_CACHE_TIME) < CurrentTime)
	  {
	    *ukr = ukr2->next;
	    MyFree(ukr2->mask);
	    MyFree(ukr2);
	    /* And put stuff back, safety in case we can't loop again */
	    if (!(ukr2 = *ukr))
	      break;
	  }
      else
        {
          if (mask && !match(mask, ukr2->mask))
            continue;
          count++;
          if (list && (list_max > ++listed_so_far))
/*             send_markup(sptr, &me, "SCAN-UNKLINE", */
/*                         "!begin<1>%s!end<1> unklined at !begin<2>!date<%ld>!end<2> (!begin<3>!time<%ld>!end<3>)", */
/*                         ukr2->mask, ukr2->placed, ukr2->placed - CurrentTime); */
            send_markup(sptr, &me, "SCAN-UNKLINE",
                        "%s unklined at %s (%s)",
                        ukr2->mask, smalldate(ukr2->placed), smalltime(ukr2->placed - CurrentTime));
        }
    }

  send_markup(sptr, &me, "UNKLINE-END", "End of unkline list");
/*   send_markup(sptr, &me, "SCAN-SUMMARY", "!begin<1>%d!end<1> matched", count); */
  send_markup(sptr, &me, "SCAN-SUMMARY", "%d matched", count);

  return 0;
}
Пример #6
0
void
m_registered(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	sendto_one(client_p, form_str(ERR_ALREADYREGISTRED), me.name, parv[0]);
}
Пример #7
0
/* msg_client()
 *
 * inputs	- flag 0 if PRIVMSG 1 if NOTICE. RFC
 *		  say NOTICE must not auto reply
 *		- pointer to command, "PRIVMSG" or "NOTICE"
 * 		- pointer to source_p source (struct Client *)
 *		- pointer to target_p target (struct Client *)
 *		- pointer to text
 * output	- NONE
 * side effects	- message given channel either chanop or voice
 */
static void
msg_client(int p_or_n, const char *command, struct Client *source_p,
           struct Client *target_p, const char *text)
{
  if (MyClient(source_p))
  {
    if (target_p->away[0] && p_or_n != NOTICE)
      sendto_one_numeric(source_p, &me, RPL_AWAY, target_p->name, target_p->away);

    if (HasUMode(target_p, UMODE_REGONLY) && target_p != source_p)
    {
      if (!HasUMode(source_p, UMODE_REGISTERED|UMODE_OPER))
      {
        if (p_or_n != NOTICE)
          sendto_one_numeric(source_p, &me, ERR_NONONREG, target_p->name);
        return;
      }
    }
  }

  if (MyClient(target_p))
  {
    if (!IsServer(source_p) && HasUMode(target_p, UMODE_CALLERID|UMODE_SOFTCALLERID))
    {
      /* Here is the anti-flood bot/spambot code -db */
      if (HasFlag(source_p, FLAGS_SERVICE) || accept_message(source_p, target_p) ||
         (HasUMode(source_p, UMODE_OPER) && ConfigGeneral.opers_bypass_callerid))
      {
        sendto_one(target_p, ":%s!%s@%s %s %s :%s",
                   source_p->name, source_p->username,
                   source_p->host, command, target_p->name, text);
      }
      else
      {
        int callerid = !!HasUMode(target_p, UMODE_CALLERID);

        /* check for accept, flag recipient incoming message */
        if (p_or_n != NOTICE)
          sendto_one_numeric(source_p, &me, RPL_TARGUMODEG,
                             target_p->name,
                             callerid ? "+g" : "+G",
                             callerid ? "server side ignore" :
                                        "server side ignore with the exception of common channels");

        if ((target_p->connection->last_caller_id_time +
             ConfigGeneral.caller_id_wait) < CurrentTime)
        {
          if (p_or_n != NOTICE)
            sendto_one_numeric(source_p, &me, RPL_TARGNOTIFY, target_p->name);

          sendto_one_numeric(target_p, &me, RPL_UMODEGMSG,
                             get_client_name(source_p, HIDE_IP),
                             callerid ? "+g" : "+G");

          target_p->connection->last_caller_id_time = CurrentTime;

        }

        /* Only so opers can watch for floods */
        flood_attack_client(p_or_n, source_p, target_p);
      }
    }
    else
    {
      /*
       * If the client is remote, we dont perform a special check for
       * flooding.. as we wouldn't block their message anyway.. this means
       * we dont give warnings.. we then check if theyre opered
       * (to avoid flood warnings), lastly if theyre our client
       * and flooding    -- fl
       */
      if (!MyClient(source_p) || HasUMode(source_p, UMODE_OPER) ||
          !flood_attack_client(p_or_n, source_p, target_p))
        sendto_anywhere(target_p, source_p, command, ":%s", text);
    }
  }
  else if (!MyClient(source_p) || HasUMode(source_p, UMODE_OPER) ||
           !flood_attack_client(p_or_n, source_p, target_p))
    sendto_anywhere(target_p, source_p, command, ":%s", text);
}
Пример #8
0
int m_alias(aClient *cptr, aClient *sptr, int parc, char *parv[], char *cmd)
{
ConfigItem_alias *alias;
aClient *acptr;
int ret;

	if (!(alias = Find_alias(cmd))) 
	{
		sendto_one(sptr, ":%s %d %s %s :Unknown command",
			me.name, ERR_UNKNOWNCOMMAND, parv[0], cmd);
		return 0;
	}
	
	/* If it isn't an ALIAS_COMMAND, we require a paramter ... We check ALIAS_COMMAND LATER */
	if (alias->type != ALIAS_COMMAND && (parc < 2 || *parv[1] == '\0'))
	{
		sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
		return -1;
	}

	if (alias->type == ALIAS_SERVICES) 
	{
		if (SERVICES_NAME && (acptr = find_person(alias->nick, NULL)))
		{
			if (alias->spamfilter && (ret = dospamfilter(sptr, parv[1], SPAMF_USERMSG, alias->nick, 0, NULL)) < 0)
				return ret;
			sendto_one(acptr, ":%s PRIVMSG %s@%s :%s", parv[0],
				alias->nick, SERVICES_NAME, parv[1]);
		}
		else
			sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
				parv[0], alias->nick);
	}
	else if (alias->type == ALIAS_STATS) 
	{
		if (STATS_SERVER && (acptr = find_person(alias->nick, NULL)))
		{
			if (alias->spamfilter && (ret = dospamfilter(sptr, parv[1], SPAMF_USERMSG, alias->nick, 0, NULL)) < 0)
				return ret;
			sendto_one(acptr, ":%s PRIVMSG %s@%s :%s", parv[0],
				alias->nick, STATS_SERVER, parv[1]);
		}
		else
			sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
				parv[0], alias->nick);
	}
	else if (alias->type == ALIAS_NORMAL) 
	{
		if ((acptr = find_person(alias->nick, NULL))) 
		{
			if (alias->spamfilter && (ret = dospamfilter(sptr, parv[1], SPAMF_USERMSG, alias->nick, 0, NULL)) < 0)
				return ret;
			if (MyClient(acptr))
				sendto_one(acptr, ":%s!%s@%s PRIVMSG %s :%s", parv[0], 
					sptr->user->username, GetHost(sptr),
					alias->nick, parv[1]);
			else
				sendto_one(acptr, ":%s PRIVMSG %s :%s", parv[0],
					alias->nick, parv[1]);
		}
		else
			sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name,
				parv[0], alias->nick);
	}
	else if (alias->type == ALIAS_CHANNEL)
	{
		aChannel *chptr;
		if ((chptr = find_channel(alias->nick, NULL)))
		{
			if (!can_send(sptr, chptr, parv[1], 0))
			{
				if (alias->spamfilter && (ret = dospamfilter(sptr, parv[1], SPAMF_CHANMSG, chptr->chname, 0, NULL)) < 0)
					return ret;
				sendto_channelprefix_butone(sptr,
				    sptr, chptr, PREFIX_ALL,
                                    ":%s PRIVMSG %s :%s", parv[0],
				    chptr->chname, parv[1]);
				return 0;
			}
		}
		sendto_one(sptr, err_str(ERR_CANNOTDOCOMMAND), me.name, parv[0],
				cmd, "You may not use this command at this time");
	}
	else if (alias->type == ALIAS_COMMAND) 
	{
		ConfigItem_alias_format *format;
		char *ptr = "";
		if (!(parc < 2 || *parv[1] == '\0'))
			ptr = parv[1]; 
		for (format = alias->format; format; format = (ConfigItem_alias_format *)format->next) 
		{
			if (regexec(&format->expr, ptr, 0, NULL, 0) == 0) 
			{
				/* Parse the parameters */
				int i = 0, j = 0, k = 1;
				char output[1024], current[1024];
				char nums[4];

				bzero(current, sizeof current);
				bzero(output, sizeof output);

				while(format->parameters[i] && j < 500) 
				{
					k = 0;
					if (format->parameters[i] == '%') 
					{
						i++;
						if (format->parameters[i] == '%') 
							output[j++] = '%';
						else if (isdigit(format->parameters[i])) 
						{
							for(; isdigit(format->parameters[i]) && k < 2; i++, k++) {
								nums[k] = format->parameters[i];
							}
							nums[k] = 0;
							i--;
							if (format->parameters[i+1] == '-') {
								strrangetok(ptr, current, ' ', atoi(nums),0);
								i++;
							}
							else 
								strrangetok(ptr, current, ' ', atoi(nums), atoi(nums));
							if (!*current)
								continue;
							if (j + strlen(current)+1 >= 500)
								break;
							strlcat(output, current, sizeof output);
							j += strlen(current);
							
						}
						else if (format->parameters[i] == 'n' ||
							 format->parameters[i] == 'N')
						{
							strlcat(output, parv[0], sizeof output);
							j += strlen(parv[0]);
						}
						else 
						{
							output[j++] = '%';
							output[j++] = format->parameters[i];
						}
						i++;
						continue;
					}
					output[j++] = format->parameters[i++];
				}
				output[j] = 0;
				/* Now check to make sure we have something to send */
				if (strlen(output) == 0)
				{
					sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, cmd);
					return -1;
				}
				
				if (format->type == ALIAS_SERVICES) 
				{
					if (SERVICES_NAME && (acptr = find_person(format->nick, NULL)))
					{
						if (alias->spamfilter && (ret = dospamfilter(sptr, output, SPAMF_USERMSG, format->nick, 0, NULL)) < 0)
							return ret;
						sendto_one(acptr, ":%s PRIVMSG %s@%s :%s", parv[0],
							format->nick, SERVICES_NAME, output);
					} else
						sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
							parv[0], format->nick);
				}
				else if (format->type == ALIAS_STATS) 
				{
					if (STATS_SERVER && (acptr = find_person(format->nick, NULL)))
					{
						if (alias->spamfilter && (ret = dospamfilter(sptr, output, SPAMF_USERMSG, format->nick, 0, NULL)) < 0)
							return ret;
						sendto_one(acptr, ":%s PRIVMSG %s@%s :%s", parv[0],
							format->nick, STATS_SERVER, output);
					} else
						sendto_one(sptr, err_str(ERR_SERVICESDOWN), me.name,
							parv[0], format->nick);
				}
				else if (format->type == ALIAS_NORMAL) 
				{
					if ((acptr = find_person(format->nick, NULL))) 
					{
						if (alias->spamfilter && (ret = dospamfilter(sptr, output, SPAMF_USERMSG, format->nick, 0, NULL)) < 0)
							return ret;
						if (MyClient(acptr))
							sendto_one(acptr, ":%s!%s@%s PRIVMSG %s :%s", parv[0], 
							sptr->user->username, IsHidden(sptr) ? sptr->user->virthost : sptr->user->realhost,
							format->nick, output);
						else
							sendto_one(acptr, ":%s PRIVMSG %s :%s", parv[0],
								format->nick, output);
					}
					else
						sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name,
							parv[0], format->nick);
				}
				else if (format->type == ALIAS_CHANNEL)
				{
					aChannel *chptr;
					if ((chptr = find_channel(format->nick, NULL)))
					{
						if (!can_send(sptr, chptr, output, 0))
						{
							if (alias->spamfilter && (ret = dospamfilter(sptr, output, SPAMF_CHANMSG, chptr->chname, 0, NULL)) < 0)
								return ret;
							sendto_channelprefix_butone(sptr,
							    sptr, chptr, PREFIX_ALL,
			                                    ":%s PRIVMSG %s :%s", parv[0],
							    chptr->chname, parv[1]);
							return 0;
						}
					}
					sendto_one(sptr, err_str(ERR_CANNOTDOCOMMAND), me.name,
						 parv[0], cmd, 
						"You may not use this command at this time");
				}
				else if (format->type == ALIAS_REAL)
				{
					int ret;
					char mybuf[500];
					
					snprintf(mybuf, sizeof(mybuf), "%s %s", format->nick, output);

					if (recursive_alias)
					{
						sendto_one(sptr, err_str(ERR_CANNOTDOCOMMAND), me.name, parv[0], cmd, "You may not use this command at this time -- recursion");
						return -1;
					}

					recursive_alias = 1;
					ret = parse(sptr, mybuf, mybuf+strlen(mybuf));
					recursive_alias = 0;

					return ret;
				}
				break;
			}
		}
		return 0;
	}
	return 0;
}
Пример #9
0
static int
m_displaymsg(struct Client *source_p, const char *channel, int underline, int action, const char *nick, const char *text)
{
    struct Channel *chptr;
    struct membership *msptr;
    char nick2[NICKLEN+1];
    char nick3[NICKLEN+1];
    char text2[BUFSIZE];

    if((chptr = find_channel(channel)) == NULL) {
        sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), channel);
        return 0;
    }

    if(!(msptr = find_channel_membership(chptr, source_p))) {
        sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
                           form_str(ERR_NOTONCHANNEL), chptr->chname);
        return 0;
    }

    if(!(chptr->mode.mode & chmode_flags['N'])) {
        sendto_one_numeric(source_p, 573, "%s :Roleplay commands are not enabled on this channel.", chptr->chname);
        return 0;
    }

    if(!can_send(chptr, source_p, msptr)) {
        sendto_one_numeric(source_p, 573, "%s :Cannot send to channel.", chptr->chname);
        return 0;
    }

    /* enforce flood stuff on roleplay commands */
    if(flood_attack_channel(0, source_p, chptr, chptr->chname))
        return 0;

    /* enforce target change on roleplay commands */
    if(!is_chanop_voiced(msptr) && !IsOper(source_p) && !add_channel_target(source_p, chptr)) {
        sendto_one(source_p, form_str(ERR_TARGCHANGE),
                   me.name, source_p->name, chptr->chname);
        return 0;
    }

    rb_strlcpy(nick3, nick, sizeof(nick3));

    if(underline)
        snprintf(nick2, sizeof(nick2), "\x1F%s\x1F", strip_unprintable(nick3));
    else
        snprintf(nick2, sizeof(nick2), "%s", strip_unprintable(nick3));

    /* don't allow nicks to be empty after stripping
     * this prevents nastiness like fake factions, etc. */
    if(EmptyString(nick3)) {
        sendto_one_numeric(source_p, 573, "%s :No visible non-stripped characters in nick.", chptr->chname);
        return 0;
    }

    if(action)
        snprintf(text2, sizeof(text2), "\1ACTION %s\1", text);
    else
        snprintf(text2, sizeof(text2), "%s", text);

    sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%[email protected] PRIVMSG %s :%s (%s)", nick2, source_p->name, channel, text2, source_p->name);
    sendto_match_servs(source_p, "*", CAP_ENCAP, NOCAPS, "ENCAP * ROLEPLAY %s %s :%s",
                       channel, nick2, text2);
    return 0;
}
Пример #10
0
/*
 * m_lljoin
 *      parv[0] = sender prefix
 *      parv[1] = channel
 *      parv[2] = nick ("!nick" == cjoin)
 *      parv[3] = key (optional)
 *
 * If a lljoin is received, from our uplink, join
 * the requested client to the given channel, or ignore it
 * if there is an error.
 *
 *   Ok, the way this works. Leaf client tries to join a channel, 
 * it doesn't exist so the join does a cburst request on behalf of the
 * client, and aborts that join. The cburst sjoin's the channel if it
 * exists on the hub, and sends back an LLJOIN to the leaf. Thats where
 * this is now..
 *
 */
static void
ms_lljoin(struct Client *client_p, struct Client *source_p,
          int parc, char *parv[])
{
  char *chname = NULL;
  char *nick = NULL;
  char *key = NULL;
  int  flags;
  int  i;
  struct Client *target_p;
  struct Channel *chptr;

  if (uplink && !IsCapable(uplink,CAP_LL))
  {
      sendto_realops_flags(UMODE_ALL, L_ALL,
			   "*** LLJOIN requested from non LL server %s",
			   client_p->name);
      return;
  }

  chname = parv[1];
  if(chname == NULL)
    return;

  nick = parv[2];
  if(nick == NULL)
    return;

  if (parc >3)
    key = parv[3];

  flags = 0;

  target_p = find_person(client_p, nick);

  if (!target_p)
    return;

  if (!MyClient(target_p))
    return;

  if (!check_channel_name(chname, 0))
  {
    sendto_gnotice_flags(UMODE_DEBUG, L_ALL, me.name, &me, NULL,
                         "*** Too long or invalid channel name from %s: %s",
                         target_p->name, chname);
    return;
  }

  chptr = make_channel(chname);
  flags = CHFL_CHANOP;
   
  if(!chptr)
    return;

  if (dlink_list_length(&chptr->members) == 0)
    flags = CHFL_CHANOP;
  else
    flags = 0;

  /* XXX in m_join.c :( */
  /* check_spambot_warning(target_p, chname); */

  /* They _could_ join a channel twice due to lag */
  if(chptr)
  {
    if (IsMember(target_p, chptr))    /* already a member, ignore this */
      return;
  }
  else
  {
    sendto_one(target_p, form_str(ERR_UNAVAILRESOURCE),
               me.name, nick, chptr->chname);
    return;
  }

  if ((i = can_join(target_p, chptr, key)))
  {
    sendto_one(target_p, form_str(i),
               me.name, nick, chptr->chname);
    return;
  }

  if ((dlink_list_length(&target_p->channel) >= ConfigChannel.max_chans_per_user) &&
      (!IsOper(target_p) || (dlink_list_length(&target_p->channel) >=
                             ConfigChannel.max_chans_per_user*3)))
  {
      sendto_one(target_p, form_str(ERR_TOOMANYCHANNELS),
		 me.name, nick, chptr->chname );
      return; 
  }
  
  if (flags == CHFL_CHANOP)
  {
      chptr->channelts = CurrentTime;

      sendto_one(uplink,
		 ":%s SJOIN %lu %s + :@%s",
		 me.name,
		 (unsigned long) chptr->channelts,
		 chptr->chname,
		 nick);
  }

  sendto_one(uplink,
             ":%s SJOIN %lu %s + :%s",
	     me.name,
	     (unsigned long) chptr->channelts,
	     chptr->chname,
	     nick);

  add_user_to_channel(chptr, target_p, flags, YES);

  sendto_channel_local(ALL_MEMBERS, NO, chptr,
		       ":%s!%s@%s JOIN :%s",
		       target_p->name,
		       target_p->username,
		       target_p->host,
		       chptr->chname);
  
  if (flags & CHFL_CHANOP)
  {
    chptr->mode.mode |= MODE_TOPICLIMIT;
    chptr->mode.mode |= MODE_NOPRIVMSGS;
      
    sendto_channel_local(ALL_MEMBERS, NO, chptr,
                         ":%s MODE %s +nt",
                         me.name, chptr->chname);
    sendto_one(uplink, 
               ":%s MODE %s +nt",
               me.name, chptr->chname);
  }

  channel_member_names(target_p, chptr, 1);
}
Пример #11
0
/*
** mo_ojoin
**      parv[1] = channel
*/
static int
mo_ojoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr;
	int move_me = 0;

	/* admins only */
	if(!IsOperAdmin(source_p))
	{
		sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin");
		return 0;
	}

	if(*parv[1] == '@' || *parv[1] == '%' || *parv[1] == '+' || *parv[1] == '!'
	   || *parv[1] == '~')
	{
		parv[1]++;
		move_me = 1;
	}
	else
	{
		sendto_one_notice(source_p, ":Unrecognized op prefix '%c'", *parv[1]);
		return 0;
	}

	if((chptr = find_channel(parv[1])) == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
				   form_str(ERR_NOSUCHCHANNEL), parv[1]);
		return 0;
	}

	if(IsMember(source_p, chptr))
	{
		sendto_one_notice(source_p, ":Please part %s before using OJOIN", parv[1]);
		return 0;
	}

	if(move_me == 1)
		parv[1]--;

	/* only sends stuff for #channels remotely */

	if(*parv[1] == '!')
	{
		if(!ConfigChannel.use_admin)
		{
			sendto_one_notice(source_p,
					  ":This server's configuration file does not support admin prefix");
			return 0;
		}

		add_user_to_channel(chptr, source_p, CHFL_ADMIN);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :!%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN %s",
				     source_p->name,
				     source_p->username, source_p->host, chptr->chname);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +a %s",
				     me.name, chptr->chname, source_p->name);

	}
	else if(*parv[1] == '@')
	{
		add_user_to_channel(chptr, source_p, CHFL_CHANOP);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :@%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		send_channel_join(chptr, source_p);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s",
				     me.name, chptr->chname, source_p->name);

	}
	else if(*parv[1] == '%')
	{
		if(!ConfigChannel.use_halfop)
		{
			sendto_one_notice(source_p,
					  ":This server's configuration file does not support halfop prefix");
			return 0;
		}

		add_user_to_channel(chptr, source_p, CHFL_HALFOP);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :%s%s",
			      me.id, (long) chptr->channelts, chptr->chname, "%", source_p->id);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN %s",
				     source_p->name,
				     source_p->username, source_p->host, chptr->chname);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +h %s",
				     me.name, chptr->chname, source_p->name);
	}
	else if(*parv[1] == '+')
	{
		add_user_to_channel(chptr, source_p, CHFL_VOICE);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :+%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		send_channel_join(chptr, source_p);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +v %s",
				     me.name, chptr->chname, source_p->name);
	}
	else if(*parv[1] == '~')
	{
		if(!ConfigChannel.use_founder)
		{
			sendto_one_notice(source_p,
					  ":This server's configuration file does not support founder prefix");
			return 0;
		}

		add_user_to_channel(chptr, source_p, CHFL_FOUNDER);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s SJOIN %ld %s + :~%s",
			      me.id, (long) chptr->channelts, chptr->chname, source_p->id);
		send_channel_join(chptr, source_p);
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +u %s",
				     me.name, chptr->chname, source_p->name);
	}
	else
	{
		add_user_to_channel(chptr, source_p, CHFL_PEON);
		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s JOIN %ld %s +",
			      source_p->id, (long) chptr->channelts, chptr->chname);
		send_channel_join(chptr, source_p);
	}

	/* send the topic... */
	if(chptr->topic != NULL)
	{
		sendto_one(source_p, form_str(RPL_TOPIC), me.name,
			   source_p->name, chptr->chname, chptr->topic);
		sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name,
			   source_p->name, chptr->chname, chptr->topic_info, chptr->topic_time);
	}

	source_p->localClient->last_join_time = rb_current_time();
	channel_member_names(chptr, source_p, 1);

	sendto_realops_snomask(SNO_GENERAL, L_ALL,
			       "OJOIN called for %s by %s!%s@%s",
			       parv[1], source_p->name, source_p->username, source_p->host);
	ilog(L_MAIN, "OJOIN called for %s by %s", parv[1], get_oper_name(source_p));


	return 0;
}
Пример #12
0
static void
ms_cburst(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	char *name;
	char *nick;
	const char *key;
	struct Channel *chptr;

	if(parc < 2 || *parv[1] == '\0')
		return;

	name = parv[1];

	if(parc > 2)
		nick = parv[2];
	else
		nick = NULL;

	if(parc > 3)
		key = parv[3];
	else
		key = "";

#ifdef DEBUGLL
	sendto_realops_flags(UMODE_ALL, L_ALL, "CBURST called by %s for %s %s %s",
			     client_p->name, name, nick ? nick : "", key ? key : "");
#endif
	if((chptr = hash_find_channel(name)) == NULL)
	{
		if((!nick) || (nick && *nick != '!'))
		{
			if(!check_channel_name(name, 0))
			{
				sendto_realops_flags(UMODE_DEBUG, L_ALL,
						     "*** Too long or invalid channel name from %s: %s",
						     client_p->name, name);
				return;
			}

			chptr = make_channel(name);
			chptr->channelts = (time_t) (-1);	/* highest possible TS so its always
								 * over-ruled
								 */
		}
		else if(nick && *nick == '!')
		{
			sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), me.name, nick + 1, name);
			return;
		}
	}

	if(IsCapable(client_p, CAP_LL))
	{
		burst_channel(client_p, chptr);

		if(nick)
			sendto_one(client_p, ":%s LLJOIN %s %s %s", me.name, name, nick, key);
	}
	else
	{
		sendto_realops_flags(UMODE_ALL, L_ALL,
				     "*** CBURST request received from non LL capable server! [%s]",
				     client_p->name);
	}
}
Пример #13
0
static int
mo_testline(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct ConfItem *aconf;
	struct ConfItem *resv_p;
	struct rb_sockaddr_storage ip;
	char user_trunc[USERLEN + 1], notildeuser_trunc[USERLEN + 1];
	const char *name = NULL;
	const char *username = NULL;
	const char *host = NULL;
	char *mask;
	char *p;
	int host_mask;
	int type;
	int duration;
	char *puser, *phost, *reason, *operreason;
	char reasonbuf[BUFSIZE];

	mask = LOCAL_COPY(parv[1]);

	if (IsChannelName(mask))
	{
		resv_p = hash_find_resv(mask);
		if (resv_p != NULL)
		{
			sendto_one(source_p, form_str(RPL_TESTLINE),
					me.name, source_p->name,
					resv_p->hold ? 'q' : 'Q',
					resv_p->hold ? (long) ((resv_p->hold - rb_current_time()) / 60) : 0L,
					resv_p->host, resv_p->passwd);
			/* this is a false positive, so make sure it isn't counted in stats q
			 * --nenolod
			 */
			resv_p->port--;
		}
		else
			sendto_one(source_p, form_str(RPL_NOTESTLINE),
					me.name, source_p->name, parv[1]);
		return 0;
	}

	if((p = strchr(mask, '!')))
	{
		*p++ = '\0';
		name = mask;
		mask = p;

		if(EmptyString(mask))
			return 0;
	}

	if((p = strchr(mask, '@')))
	{
		*p++ = '\0';
		username = mask;
		host = p;

		if(EmptyString(host))
			return 0;
	}
	else
		host = mask;

	/* parses as an IP, check for a dline */
	if((type = parse_netmask(host, &ip, &host_mask)) != HM_HOST)
	{
#ifdef RB_IPV6
		if(type == HM_IPV6)
			aconf = find_dline((struct sockaddr *)&ip, AF_INET6);
		else
#endif
			aconf = find_dline((struct sockaddr *)&ip, AF_INET);

		if(aconf && aconf->status & CONF_DLINE)
		{
			get_printable_kline(source_p, aconf, &phost, &reason, &puser, &operreason);
			snprintf(reasonbuf, sizeof(reasonbuf), "%s%s%s", reason,
				operreason ? "|" : "", operreason ? operreason : "");
			sendto_one(source_p, form_str(RPL_TESTLINE),
				me.name, source_p->name,
				(aconf->flags & CONF_FLAGS_TEMPORARY) ? 'd' : 'D',
				(aconf->flags & CONF_FLAGS_TEMPORARY) ?
				 (long) ((aconf->hold - rb_current_time()) / 60) : 0L,
				phost, reasonbuf);

			return 0;
		}
		/* Otherwise, aconf is an exempt{} */
		if(aconf == NULL &&
				(duration = is_reject_ip((struct sockaddr *)&ip)))
			sendto_one(source_p, form_str(RPL_TESTLINE),
					me.name, source_p->name,
					'!',
					duration / 60L,
					host, "Reject cache");
		if(aconf == NULL &&
				(duration = is_throttle_ip((struct sockaddr *)&ip)))
			sendto_one(source_p, form_str(RPL_TESTLINE),
					me.name, source_p->name,
					'!',
					duration / 60L,
					host, "Throttled");
	}

	if (username != NULL)
	{
		rb_strlcpy(user_trunc, username, sizeof user_trunc);
		rb_strlcpy(notildeuser_trunc, *username == '~' ? username + 1 : username, sizeof notildeuser_trunc);
	}
	else
	{
		rb_strlcpy(user_trunc, "dummy", sizeof user_trunc);
		rb_strlcpy(notildeuser_trunc, "dummy", sizeof notildeuser_trunc);
	}
	/* now look for a matching I/K/G */
	if((aconf = find_address_conf(host, NULL, user_trunc, notildeuser_trunc,
				(type != HM_HOST) ? (struct sockaddr *)&ip : NULL,
				(type != HM_HOST) ? (
#ifdef RB_IPV6
				 (type == HM_IPV6) ? AF_INET6 :
#endif
				  AF_INET) : 0, NULL)))
	{
		static char buf[HOSTLEN+USERLEN+2];

		if(aconf->status & CONF_KILL)
		{
			get_printable_kline(source_p, aconf, &phost, &reason, &puser, &operreason);
			snprintf(buf, sizeof(buf), "%s@%s",
					puser, phost);
			snprintf(reasonbuf, sizeof(reasonbuf), "%s%s%s", reason,
				operreason ? "|" : "", operreason ? operreason : "");
			sendto_one(source_p, form_str(RPL_TESTLINE),
				me.name, source_p->name,
				(aconf->flags & CONF_FLAGS_TEMPORARY) ? 'k' : 'K',
				(aconf->flags & CONF_FLAGS_TEMPORARY) ?
				 (long) ((aconf->hold - rb_current_time()) / 60) : 0L,
				buf, reasonbuf);
			return 0;
		}
	}

	/* they asked us to check a nick, so hunt for resvs.. */
	if(name && (resv_p = find_nick_resv(name)))
	{
		sendto_one(source_p, form_str(RPL_TESTLINE),
				me.name, source_p->name,
				resv_p->hold ? 'q' : 'Q',
				resv_p->hold ? (long) ((resv_p->hold - rb_current_time()) / 60) : 0L,
				resv_p->host, resv_p->passwd);

		/* this is a false positive, so make sure it isn't counted in stats q
		 * --nenolod
		 */
		resv_p->port--;
		return 0;
	}

	/* no matching resv, we can print the I: if it exists */
	if(aconf && aconf->status & CONF_CLIENT)
	{
		sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE),
				aconf->info.name, EmptyString(aconf->spasswd) ? "<NULL>" : aconf->spasswd,
				show_iline_prefix(source_p, aconf, aconf->user),
				aconf->host, aconf->port, aconf->className);
		return 0;
	}

	/* nothing matches.. */
	sendto_one(source_p, form_str(RPL_NOTESTLINE),
			me.name, source_p->name, parv[1]);
	return 0;
}
Пример #14
0
/*
 * m_challenge - generate RSA challenge for wouldbe oper
 * parv[1] = operator to challenge for, or +response
 *
 */
static int
m_challenge(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct oper_conf *oper_p;
	char *challenge = NULL; /* to placate gcc */
	char chal_line[CHALLENGE_WIDTH];
	unsigned char *b_response;
	size_t cnt;
	int len = 0;

	/* if theyre an oper, reprint oper motd and ignore */
	if(IsOper(source_p))
	{
		sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name);
		send_oper_motd(source_p);
		return 0;
	}

	if(*parv[1] == '+')
	{
		/* Ignore it if we aren't expecting this... -A1kmm */
		if(!source_p->localClient->challenge)
			return 0;

		if((rb_current_time() - source_p->localClient->chal_time) > CHALLENGE_EXPIRES)
		{
			sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name);
			ilog(L_FOPER, "EXPIRED CHALLENGE (%s) by (%s!%s@%s) (%s)",
			     source_p->localClient->opername, source_p->name,
			     source_p->username, source_p->host, source_p->sockhost);

			if(ConfigFileEntry.failed_oper_notice)
				sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
						     "Expired CHALLENGE attempt by %s (%s@%s)",
						     source_p->name, source_p->username,
						     source_p->host);
			cleanup_challenge(source_p);
			return 0;
		}

		parv[1]++;
		b_response = rb_base64_decode((const unsigned char *)parv[1], strlen(parv[1]), &len);

		if(len != SHA_DIGEST_LENGTH ||
		   memcmp(source_p->localClient->challenge, b_response, SHA_DIGEST_LENGTH))
		{
			sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name);
			ilog(L_FOPER, "FAILED CHALLENGE (%s) by (%s!%s@%s) (%s)",
			     source_p->localClient->opername, source_p->name,
			     source_p->username, source_p->host, source_p->sockhost);

			if(ConfigFileEntry.failed_oper_notice)
				sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
						     "Failed CHALLENGE attempt by %s (%s@%s)",
						     source_p->name, source_p->username,
						     source_p->host);

			rb_free(b_response);
			cleanup_challenge(source_p);
			return 0;
		}

		rb_free(b_response);

		oper_p = find_oper_conf(source_p->username, source_p->orighost,
					source_p->sockhost,
					source_p->localClient->opername);

		if(oper_p == NULL)
		{
			sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST));
			ilog(L_FOPER, "FAILED OPER (%s) by (%s!%s@%s) (%s)",
			     source_p->localClient->opername, source_p->name,
			     source_p->username, source_p->host,
			     source_p->sockhost);

			if(ConfigFileEntry.failed_oper_notice)
				sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
						     "Failed CHALLENGE attempt - host mismatch by %s (%s@%s)",
						     source_p->name, source_p->username,
						     source_p->host);
			return 0;
		}

		cleanup_challenge(source_p);

		oper_up(source_p, oper_p);

		ilog(L_OPERED, "OPER %s by %s!%s@%s (%s)",
		     source_p->localClient->opername, source_p->name,
		     source_p->username, source_p->host, source_p->sockhost);
		return 0;
	}

	cleanup_challenge(source_p);

	oper_p = find_oper_conf(source_p->username, source_p->orighost,
				source_p->sockhost, parv[1]);

	if(oper_p == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST));
		ilog(L_FOPER, "FAILED OPER (%s) by (%s!%s@%s) (%s)",
		     parv[1], source_p->name,
		     source_p->username, source_p->host, source_p->sockhost);

		if(ConfigFileEntry.failed_oper_notice)
			sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
					     "Failed CHALLENGE attempt - host mismatch by %s (%s@%s)",
					     source_p->name, source_p->username, source_p->host);
		return 0;
	}

	if(!oper_p->rsa_pubkey)
	{
		sendto_one_notice(source_p, ":I'm sorry, PK authentication is not enabled for your oper{} block.");
		return 0;
	}

	if(IsOperConfNeedSSL(oper_p) && !IsSSLClient(source_p))
	{
		sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST));
		ilog(L_FOPER, "FAILED CHALLENGE (%s) by (%s!%s@%s) (%s) -- requires SSL/TLS",
		     parv[1], source_p->name, source_p->username, source_p->host,
		     source_p->sockhost);

		if(ConfigFileEntry.failed_oper_notice)
		{
			sendto_realops_snomask(SNO_GENERAL, L_ALL,
					     "Failed CHALLENGE attempt - missing SSL/TLS by %s (%s@%s)",
					     source_p->name, source_p->username, source_p->host);
		}
		return 0;
	}

	if (oper_p->certfp != NULL)
	{
		if (source_p->certfp == NULL || strcasecmp(source_p->certfp, oper_p->certfp))
		{
			sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST));
			ilog(L_FOPER, "FAILED OPER (%s) by (%s!%s@%s) (%s) -- client certificate fingerprint mismatch",
			     parv[1], source_p->name,
			     source_p->username, source_p->host, source_p->sockhost);

			if(ConfigFileEntry.failed_oper_notice)
			{
				sendto_realops_snomask(SNO_GENERAL, L_ALL,
						     "Failed OPER attempt - client certificate fingerprint mismatch by %s (%s@%s)",
						     source_p->name, source_p->username, source_p->host);
			}
			return 0;
		}
	}

	if(!generate_challenge(&challenge, &(source_p->localClient->challenge), oper_p->rsa_pubkey))
	{
		char *chal = challenge;
		source_p->localClient->chal_time = rb_current_time();
		for(;;)
		{
			cnt = rb_strlcpy(chal_line, chal, CHALLENGE_WIDTH);
			sendto_one(source_p, form_str(RPL_RSACHALLENGE2), me.name, source_p->name, chal_line);
			if(cnt > CHALLENGE_WIDTH)
				chal += CHALLENGE_WIDTH - 1;
			else
				break;

		}
		sendto_one(source_p, form_str(RPL_ENDOFRSACHALLENGE2),
			   me.name, source_p->name);
		rb_free(challenge);
		source_p->localClient->opername = rb_strdup(oper_p->name);
	}
	else
		sendto_one_notice(source_p, ":Failed to generate challenge.");

	return 0;
}
Пример #15
0
/*
 *
 *      parc    number of arguments ('sender' counted as one!)
 *      parv[0] pointer to 'sender' (may point to empty string) (not used)
 *      parv[1]..parv[parc-1]
 *              pointers to additional parameters, this is a NULL
 *              terminated list (parv[parc] == NULL).
 *
 * *WARNING*
 *      Numerics are mostly error reports. If there is something
 *      wrong with the message, just *DROP* it! Don't even think of
 *      sending back a neat error message -- big danger of creating
 *      a ping pong error message...
 */
static void
do_numeric(char numeric[], struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	struct Client *target_p;
	struct Channel *chptr;

	if(parc < 2 || !IsServer(source_p))
		return;

	/* Remap low number numerics. */
	if(numeric[0] == '0')
		numeric[0] = '1';

	/*
	 * Prepare the parameter portion of the message into 'buffer'.
	 * (Because the buffer is twice as large as the message buffer
	 * for the socket, no overflow can occur here... ...on current
	 * assumptions--bets are off, if these are changed --msa)
	 * Note: if buffer is non-empty, it will begin with SPACE.
	 */
	if(parc > 1)
	{
		char *t = buffer;	/* Current position within the buffer */
		int i;
		int tl;		/* current length of presently being built string in t */
		for (i = 2; i < (parc - 1); i++)
		{
			tl = ircsprintf(t, " %s", parv[i]);
			t += tl;
		}
		ircsprintf(t, " :%s", parv[parc - 1]);
	}

	if((target_p = find_client(parv[1])) != NULL)
	{
		if(IsMe(target_p))
		{
			/*
			 * We shouldn't get numerics sent to us,
			 * any numerics we do get indicate a bug somewhere..
			 */
			/* ugh.  this is here because of nick collisions.  when two servers
			 * relink, they burst each other their nicks, then perform collides.
			 * if there is a nick collision, BOTH servers will kill their own
			 * nicks, and BOTH will kill the other servers nick, which wont exist,
			 * because it will have been already killed by the local server.
			 *
			 * unfortunately, as we cant guarantee other servers will do the
			 * "right thing" on a nick collision, we have to keep both kills.  
			 * ergo we need to ignore ERR_NOSUCHNICK. --fl_
			 */
			/* quick comment. This _was_ tried. i.e. assume the other servers
			 * will do the "right thing" and kill a nick that is colliding.
			 * unfortunately, it did not work. --Dianora
			 */
			if(atoi(numeric) != ERR_NOSUCHNICK)
				sendto_realops_flags(UMODE_ALL, L_ADMIN,
						     "*** %s(via %s) sent a %s numeric to me: %s",
						     source_p->name, client_p->name, numeric,
						     buffer);
			return;
		}
		else if(target_p->from == client_p)
		{
			/* This message changed direction (nick collision?)
			 * ignore it.
			 */
			return;
		}

		/* csircd will send out unknown umode flag for +a (admin), drop it here. */
		if((atoi(numeric) == ERR_UMODEUNKNOWNFLAG) && MyClient(target_p))
			return;

		/* Fake it for server hiding, if its our client */
		if(ConfigServerHide.hide_servers && MyClient(target_p) && !IsOper(target_p))
			sendto_one(target_p, ":%s %s %s%s", me.name, numeric, parv[1], buffer);
		else
			sendto_one(target_p, ":%s %s %s%s", source_p->name, numeric, parv[1],
				   buffer);
		return;
	}
	else if((chptr = hash_find_channel(parv[1])) != NULL)
		sendto_channel_local(ALL_MEMBERS, chptr,
				     ":%s %s %s %s",
				     source_p->name, numeric, chptr->chname, buffer);
}
Пример #16
0
/*
 * m_die - DIE command handler
 */
int m_die(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Client* acptr;
  int      i;

  if (!MyClient(sptr) || !IsAnOper(sptr))
    {
      sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }

  if (!IsOperDie(sptr))
    {
      sendto_one(sptr,":%s NOTICE %s :You have no D flag", me.name, parv[0]);
      return 0;
    }

  if (parc < 2)
    {
      sendto_one(sptr,":%s NOTICE %s :Need server name /die %s",
                 me.name,sptr->name,me.name);
      return 0;
    }
  else
    {
      if (irccmp(parv[1], me.name))
        {
          sendto_one(sptr,":%s NOTICE %s :Mismatch on /die %s",
                     me.name,sptr->name,me.name);
          return 0;
        }
    }

  for (i = 0; i <= highest_fd; i++)
    {
      if (!(acptr = local[i]))
        continue;
      if (IsClient(acptr))
        {
          if(IsAnOper(acptr))
            sendto_one(acptr,
                       ":%s NOTICE %s :Server Terminating. %s",
                       me.name, acptr->name,
                       get_client_name(sptr, HIDE_IP));
          else
            sendto_one(acptr,
                       ":%s NOTICE %s :Server Terminating. %s",
                       me.name, acptr->name,
                       get_client_name(sptr, MASK_IP));
        }
      else if (IsServer(acptr))
        sendto_one(acptr, ":%s ERROR :Terminated by %s",
                   me.name, get_client_name(sptr, MASK_IP));
    }
  flush_connections(0);
  irclog(L_NOTICE, "Server terminated by %s", get_client_name(sptr, HIDE_IP));
  /* 
   * this is a normal exit, tell the os it's ok 
   */
  exit(0);
  /* NOT REACHED */
  return 0;
}
Пример #17
0
/* 
 * m_not_oper
 * inputs	- 
 * output	-
 * side effects	- just returns a nastyogram to given user
 */
void
m_not_oper(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	sendto_one(source_p, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
}
Пример #18
0
/*
** m_sendumode - Stskeeps
**      parv[0] = sender prefix
**      parv[1] = target
**      parv[2] = message text
** Pretty handy proc.. 
** Servers can use this to f.x:
**   :server.unreal.net SENDUMODE F :Client connecting at server server.unreal.net port 4141 usw..
** or for sending msgs to locops.. :P
*/
DLLFUNC int m_sendumode(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	char *message;
	char *p;
	int i;
	long umode_s = 0;
	long snomask = 0;

	aClient* acptr;

	message = (parc > 3) ? parv[3] : parv[2];

	if (parc < 3)
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
		    me.name, parv[0], "SENDUMODE");
		return 0;
	}

	if (!IsServer(sptr))
	{
		sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
		return 0;
	}

	sendto_serv_butone(IsServer(cptr) ? cptr : NULL,
	    ":%s SMO %s :%s", parv[0], parv[1], message);

	for (p = parv[1]; *p; p++)
	{
		umode_s = 0;
		
		for(i = 0; i <= Usermode_highest; i++)
		{
			if (!Usermode_Table[i].flag)
				continue;
			if (Usermode_Table[i].flag == *p)
			{
				umode_s |= Usermode_Table[i].mode;
				break;
			}
		}
		if (i <= Usermode_highest)
			continue;

		for(i = 0; i <= Snomask_highest; i++)
		{
			if (Snomask_Table[i].flag == *p)
			{
				snomask |= Snomask_Table[i].mode;
				break;
			}
		}
	}

	if (parc > 3)
	    for(p = parv[2]; *p; p++)
	{
		for (i = 0; i <= Snomask_highest; i++)
		{
			if (Snomask_Table[i].flag == *p)
			{
				snomask |= Snomask_Table[i].mode;
				break;
			}
		}
	}

	for(i = 0; i <= LastSlot; i++)
	    if((acptr = local[i]) && IsPerson(acptr) && ((acptr->user->snomask & snomask) ||
		(acptr->umodes & umode_s)))
	{
		sendto_one(acptr, ":%s NOTICE %s :%s", me.name, acptr->name, message);
	}

	return 0;
}
Пример #19
0
/*
 * mo_omode - MODE command handler
 * parv[1] - channel
 */
static int
mo_omode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr = NULL;
	struct membership *msptr;
	char params[512];
	int i;
	int wasonchannel;

	/* admins only */
	if(!IsOperAdmin(source_p))
	{
		sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin");
		return 0;
	}

	/* Now, try to find the channel in question */
	if(!IsChanPrefix(parv[1][0]) || !check_channel_name(parv[1]))
	{
		sendto_one_numeric(source_p, ERR_BADCHANNAME,
				form_str(ERR_BADCHANNAME), parv[1]);
		return 0;
	}

	chptr = find_channel(parv[1]);

	if(chptr == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
				form_str(ERR_NOSUCHCHANNEL), parv[1]);
		return 0;
	}

	/* Now know the channel exists */
	msptr = find_channel_membership(chptr, source_p);
	wasonchannel = msptr != NULL;

	if (is_chanop(msptr))
	{
		sendto_one_notice(source_p, ":Use a normal MODE you idiot");
		return 0;
	}

	params[0] = '\0';
	for (i = 2; i < parc; i++)
	{
		if (i != 2)
			rb_strlcat(params, " ", sizeof params);
		rb_strlcat(params, parv[i], sizeof params);
	}

	sendto_wallops_flags(UMODE_WALLOP, &me, 
			     "OMODE called for [%s] [%s] by %s!%s@%s",
			     parv[1], params, source_p->name, source_p->username, source_p->host);
	ilog(L_MAIN, "OMODE called for [%s] [%s] by %s",
	     parv[1], params, get_oper_name(source_p));

	if(*chptr->chname != '&')
		sendto_server(NULL, NULL, NOCAPS, NOCAPS, 
			      ":%s WALLOPS :OMODE called for [%s] [%s] by %s!%s@%s",
			      me.name, parv[1], params, source_p->name, source_p->username,
			      source_p->host);

#if 0
	set_channel_mode(client_p, source_p->servptr, chptr, msptr, 
			 parc - 2, parv + 2);
#else
	if (parc == 4 && !strcmp(parv[2], "+o") && !irccmp(parv[3], source_p->name))
	{
		/* Opping themselves */
		if (!wasonchannel)
		{
			sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
					   form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname);
			return 0;
		}
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s",
				me.name, parv[1], source_p->name);
		sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
				":%s TMODE %ld %s +o %s",
				me.id, (long) chptr->channelts, parv[1],
				source_p->id);
		msptr->flags |= CHFL_CHANOP;
	}
	else
	{
		/* Hack it so set_channel_mode() will accept */
		if (wasonchannel)
			msptr->flags |= CHFL_CHANOP;
		else
		{
			add_user_to_channel(chptr, source_p, CHFL_CHANOP);
			msptr = find_channel_membership(chptr, source_p);
		}
		set_channel_mode(client_p, source_p, chptr, msptr, 
				parc - 2, parv + 2);
		/* We know they were not opped before and they can't have opped
		 * themselves as set_channel_mode() does not allow that
		 * -- jilles */
		if (wasonchannel)
			msptr->flags &= ~CHFL_CHANOP;
		else
			remove_user_from_channel(msptr);
	}
#endif
	return 0;
}
Пример #20
0
int build_searchopts(aClient *sptr, int parc, char *parv[])
{
  static char *who_oper_help[] =
  {
      "/WHO [+|-][acghilmnstuCM] [args]",
      "Flags are specified like channel modes,",
      "The flags cghimnsu all have arguments",
      "Flags are set to a positive check by +, a negative check by -",
      "The flags work as follows:",
      "Flag a: user is away",
      "Flag c <channel>: user is on <channel>,",
      "                  no wildcards accepted",
      "Flag g <gcos/realname>: user has string <gcos> in their GCOS,",
      "                        wildcards accepted, oper only",
      "Flag h <host>: user has string <host> in their hostname,",
      "               wildcards accepted",
      "Flag i <ip>: user is from <ip>, wildcards and cidr accepted,",
      "Flag m <usermodes>: user has <usermodes> set on them",
      "Flag n <nick>: user has string <nick> in their nickname,",
      "               wildcards accepted",
      "Flag s <server>: user is on server <server>,",
      "                 wildcards not accepted",
      "Flag t <seconds>: (+t) show nicks in use for more than or equal to <seconds> seconds",
      "                  (-t) show nicks in use for less than <seconds> seconds",
      "Flag u <user>: user has string <user> in their username,",
      "               wildcards accepted",
      "Flag T <type>: user is of type <type>, where type is assigned",
      "               by services.",
      "Behavior flags:",
      "Flag C: show first visible channel user is in",
      "Flag M: check for user in channels I am a member of",
      "Flag I: always show IPs instead of hosts",
      NULL
  };

  static char *who_user_help[] =
  {
      "/WHO [+|-][achmnsuCM] [args]",
      "Flags are specified like channel modes,",
      "The flags cghimnsu all have arguments",
      "Flags are set to a positive check by +, a negative check by -",
      "The flags work as follows:",
      "Flag a: user is away",
      "Flag c <channel>: user is on <channel>,",
      "                  no wildcards accepted",
      "Flag h <host>: user has string <host> in their hostname,",
      "               wildcards accepted",
      "Flag m <usermodes>: user has <usermodes> set on them,",
      "                    only usermodes o/O/a/A will return a result",
      "Flag n <nick>: user has string <nick> in their nickname,",
      "               wildcards accepted",
      "Flag s <server>: user is on server <server>,",
      "                 wildcards not accepted",
      "Flag u <user>: user has string <user> in their username,",
      "               wildcards accepted",
      "Behavior flags:",
      "Flag C: show first visible channel user is in",
      "Flag M: check for user in channels I am a member of",
      NULL
  };

  char *flags, change=1, *s, *err;
  int args=1, i, rval;

  memset((char *)&wsopts, '\0', sizeof(SOpts));
  /* if we got no extra arguments, send them the help. yeech. */
  /* if it's /who ?, send them the help */
  if(parc < 1 || parv[0][0]=='?')
  {
      /* So we don't confuse users with flags they cannot use,
         a different /who ? output will be given to users and
         opers -srd */

      char **ptr = NULL;

      if (!IsAnOper(sptr))
       ptr = who_user_help;
      else
       ptr = who_oper_help;

      for (; *ptr; ptr++)
	  sendto_one(sptr, getreply(RPL_COMMANDSYNTAX), me.name,
		     sptr->name, *ptr);
      sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, sptr->name, "?","WHO");
      return 0;
  }
  /* backwards compatibility */
  else if(parv[0][0]=='0' && parv[0][1]==0)
  {
      if(parc>1 && *parv[1]=='o')
      {
	  wsopts.check_umode=1;
	  wsopts.umode_plus=1;
	  wsopts.umodes=UMODE_o;
      }
      wsopts.host_plus=1;
      wsopts.host="*";
      return 1;
  }
  /* if the first argument isn't a list of stuff */
  else if(parv[0][0]!='+' && parv[0][0]!='-')
  {
      if(parv[0][0]=='#' || parv[0][0]=='&')
      {
	  wsopts.channel=find_channel(parv[0],NullChn);
	  if(wsopts.channel==NULL)
	  {
	      sendto_one(sptr, getreply(ERR_NOSUCHCHANNEL), me.name,
			 sptr->name, parv[0]);
	      return 0;
	  }
      }
      else if (IsAnOper(sptr))
      {
	  int bits;

	  bits = inet_parse_cidr(AF_INET, parv[0],
				 &wsopts.cidr_ip, sizeof(wsopts.cidr_ip));
	  if (bits > 0)
	  {
	      wsopts.cidr_family = AF_INET;
	      wsopts.cidr_bits = bits;
	      wsopts.cidr_plus = 1;
	  }
	  else
	  {
	      bits = inet_parse_cidr(AF_INET6, parv[0],
				     &wsopts.cidr_ip, sizeof(wsopts.cidr_ip));
	      if (bits > 0)
	      {
		  wsopts.cidr_family = AF_INET6;
		  wsopts.cidr_bits = bits;
		  wsopts.cidr_plus = 1;
	      }
	      else
	      {
		  /*
		   * The argument could be an IPv6 address with a wildcard, a
		   * hostname, or a nickname.
		   */
		  if (strchr(parv[0], ':'))
		  {
		      wsopts.ip_plus = 1;
		      wsopts.ip = parv[0];
		  }
		  else if (strchr(parv[0], '.'))
		  {
		      wsopts.host_plus = 1;
		      wsopts.host = parv[0];
		  }
		  else
		  {
		      wsopts.nick_plus = 1;
		      wsopts.nick = parv[0];
		  }
	      }
	  }
      }
      else
      {
	  /* The argument could be either a hostname or a nickname. */
	  if (strchr(parv[0], '.'))
	  {
	      wsopts.host_plus = 1;
	      wsopts.host = parv[0];
	  }
	  else
	  {
	      wsopts.nick_plus = 1;
	      wsopts.nick = parv[0];
	  }
      }
      return 1;
  }
  /* now walk the list (a lot like set_mode) and set arguments
   * as appropriate. */
  flags=parv[0];
  while(*flags)
  {
      switch(*flags)
      {
      case '+':
      case '-':
	  change=(*flags=='+' ? 1 : 0);
	  break;
      case 'a':
	  if(change)
	      wsopts.away_plus=1; /* they want here people */
	  else
	      wsopts.away_plus=0;
	  wsopts.check_away=1;
	  break;
      case 'C':
	  wsopts.show_chan = change;
	  break;
      case 'M':
	  wsopts.search_chan = change;
	  break;
      case 'c':
	  if(parv[args]==NULL || !change)
	  {
	      sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name,
			 sptr->name, "WHO", "who");
	      return 0;
	  }
	  if(*parv[args] == '@' || *parv[args] == '+')
	  {
	      char *cname = parv[args] + 1;

              if(*parv[args] == '@')
	      {
		  wsopts.channelflags = CHFL_CHANOP;
		  if(*cname == '+')
		  {
		      wsopts.channelflags |= CHFL_VOICE;
		      cname++;
		  }
	      }
	      else
		  wsopts.channelflags = CHFL_VOICE;

	      wsopts.channel=find_channel(cname, NullChn);
	  }
	  else
	  {
	      wsopts.channelflags = 0;
	      wsopts.channel=find_channel(parv[args],NullChn);
	  }
 
	  if(wsopts.channel==NULL)
	  {
	      sendto_one(sptr, getreply(ERR_NOSUCHCHANNEL), me.name,
			 sptr->name, parv[args]);
	      return 0;
	  }
	  wsopts.chan_plus=change;
	  args++;
	  break;
      case 'g':
          if(parv[args]==NULL)
          {
              sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name,
                         sptr->name, "WHO", "who");
              return 0;
          }
          else if(!IsAnOper(sptr))
          {
              sendto_one(sptr, getreply(ERR_NOPRIVILEGES), me.name, parv[0]);
              return 0;
          }
          wsopts.gcos=parv[args];
          wsopts.gcos_plus=change;
          args++;
          break;
      case 'h':
	  if(parv[args]==NULL)
	  {
	      sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name,
			 sptr->name, "WHO", "who");
	      return 0;
	  }
	  wsopts.host=parv[args];
	  wsopts.host_plus=change;
	  args++;
	  break;
       case 't':
          if(parv[args]==NULL || (rval = strtol(parv[args], &err, 0)) == 0 || *err != '\0')
          {
              sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name,
                         sptr->name, "WHO", "who");
              return 0;
          }
          else if(!IsAnOper(sptr))
          {
              sendto_one(sptr, getreply(ERR_NOPRIVILEGES), me.name, parv[0]);
              return 0;
          }
          wsopts.ts = rval;
          wsopts.ts_value = change ? 2 : 1;
          args++;
          break; 
       case 'T':
          if(parv[args]==NULL || (rval = strtol(parv[args], &err, 0)) == 0 || *err != '\0')
          {
              sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name,
                         sptr->name, "WHO", "who");
              return 0;
          }
          else if(!IsAnOper(sptr))
          {
              sendto_one(sptr, getreply(ERR_NOPRIVILEGES), me.name, parv[0]);
              return 0;
          }
          wsopts.client_type = rval;
          wsopts.client_type_plus = change ? 1 : 0;
          args++;
          break;
      case 'I':
          if(!IsAnOper(sptr))
          {
              sendto_one(sptr, getreply(ERR_NOPRIVILEGES), me.name, parv[0]);
              return 0;
          }
          wsopts.ip_show = change;
          break; 
      case 'i':
          if(parv[args]==NULL)
          {
              sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name,
                         sptr->name, "WHO", "who");
              return 0;
          }
          else if(!IsAnOper(sptr))
          {
              sendto_one(sptr, getreply(ERR_NOPRIVILEGES), me.name, parv[0]);
              return 0;
          }
          else
          {
	      if (strchr(parv[args], '/'))
	      {
		  int bits;

		  bits = inet_parse_cidr(AF_INET, parv[args],
					 &wsopts.cidr_ip,
					 sizeof(wsopts.cidr_ip));
		  if (bits > 0)
		      wsopts.cidr_family = AF_INET;
		  else
		  {
		      bits = inet_parse_cidr(AF_INET6, parv[args],
					     &wsopts.cidr_ip,
					     sizeof(wsopts.cidr_ip));
		      if (bits > 0)
			  wsopts.cidr_family = AF_INET6;
		  }
		  if (bits > 0)
		  {
		      wsopts.cidr_bits = bits;
		      wsopts.cidr_plus = change;
		  }
		  else
                  {
                      sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name,
                         "WHO", "who");
                      return 0;
                  }
		  args++;
	      }
              else
              {
                  wsopts.ip=parv[args];
                  wsopts.ip_plus=change;
                  args++;
              }
          }
          break;
      case 'm':
	  if(parv[args]==NULL)
	  {
	      sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name,
			 sptr->name, "WHO", "who");
	      return 0;
	  }
	  s=parv[args];
	  while(*s)
	  {
	      for(i=1;user_modes[i]!=0x0;i+=2)
	      {
		  if(*s==(char)user_modes[i])
		  {
		      wsopts.umodes|=user_modes[i-1];
		      break;
		  }
	      }
              if(!user_modes[i])
              {
                  sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name,
                             sptr->name, "WHO", "who");
                  return 0;
              }
	      s++;
	  }
	  if(!IsAnOper(sptr)) /* only let users search for +/-oOaA */
	      wsopts.umodes=(wsopts.umodes&(UMODE_o|UMODE_O|UMODE_a|UMODE_A));
	  wsopts.umode_plus=change;
	  if(wsopts.umodes)
	      wsopts.check_umode=1;
	  args++;
	  break;
      case 'n':
	  if(parv[args]==NULL)
	  {
	      sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name,
			 sptr->name, "WHO", "who");
	      return 0;
	  }
	  wsopts.nick=parv[args];
	  wsopts.nick_plus=change;
	  args++;
	  break;
      case 's':
	  if(parv[args]==NULL || !change)
	  {
	      sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name,
			 sptr->name, "WHO", "who");
	      return 0;
	  }
	  wsopts.server=find_server(parv[args],NULL);
	  if(wsopts.server==NULL)
	  {
	      sendto_one(sptr, getreply(ERR_NOSUCHSERVER), me.name,
			 sptr->name, parv[args]);
	      return 0;
	  }
	  wsopts.serv_plus=change;
	  args++;
	  break;
      case 'u':
	  if(parv[args]==NULL)
	  {
	      sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name,
			 sptr->name, "WHO", "who");
	      return 0;
	  }
	  wsopts.user=parv[args];
	  wsopts.user_plus=change;
	  args++;
	  break;
      default:
	  sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name,
		     sptr->name, "WHO", "who");
	  return 0;

      }
      flags++;
  }
  
  /* if we specified search_chan, we _must_ specify something useful 
   * to go with it. Specifying a channel makes no sense, and no params make no 
   * sense either, as does specifying a nick.
   */
  
  if(wsopts.search_chan && !(wsopts.check_away || wsopts.gcos_plus || 
			     wsopts.host_plus || wsopts.check_umode || 
			     wsopts.serv_plus || wsopts.nick_plus || 
			     wsopts.user_plus || wsopts.ts_value || 
                 wsopts.client_type_plus || wsopts.ip_plus))
  {
      if(parv[args]==NULL || wsopts.channel || wsopts.nick ||
	 parv[args][0] == '#' || parv[args][0] == '&')
      {
	  sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO",
                 "who");
	  return 0;
      }

      if (strchr(parv[args], '.'))
      {
	  wsopts.host_plus=1;
	  wsopts.host=parv[args];
      }
      else
      {
	  sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO",
                 "who");
	  return 0;
      }
  } 
  else /* can't show_chan if nothing else is set! */
      if(wsopts.show_chan && !(wsopts.check_away || wsopts.gcos_plus || 
			       wsopts.host_plus || wsopts.check_umode || 
			       wsopts.serv_plus || wsopts.nick_plus || 
			       wsopts.user_plus || wsopts.ts_value || 
                   wsopts.client_type_plus || wsopts.ip_plus || 
                   wsopts.chan_plus || wsopts.cidr_bits))
      {
	  if(parv[args]==NULL)
	  {
	      sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO",
                     "who");
	      return 0;
	  }
	  
	  if (strchr(parv[args], '.'))
	  {
	      wsopts.host_plus=1;
	      wsopts.host=parv[args];
	  }
	  else
	  {
	      wsopts.nick_plus=1;
	      wsopts.nick=parv[args];
	  }
      }

  if(parc > args)
  {
      /* Too many arguments */
      sendto_one(sptr, getreply(ERR_WHOSYNTAX), me.name, sptr->name, "WHO",
             "who");
      return 0;
  }

  /* hey cool, it all worked! */
  return 1;
}
Пример #21
0
/* handle_special()
 *
 * inputs	- client pointer
 *		- nick stuff to grok for opers
 *		- text to send if grok
 * output	- none
 * side effects	- old style username@server is handled here for non opers
 *		  opers are allowed username%hostname@server
 *		  all the traditional oper type messages are also parsed here.
 *		  i.e. "/msg #some.host."
 *		  However, syntax has been changed.
 *		  previous syntax "/msg #some.host.mask"
 *		  now becomes     "/msg $#some.host.mask"
 *		  previous syntax of: "/msg $some.server.mask" remains
 *		  This disambiguates the syntax.
 *
 * XXX		  N.B. dalnet changed it to nick@server as have other servers.
 *		  we will stick with tradition for now.
 *		- Dianora
 */
static void
handle_special(int p_or_n, const char *command, struct Client *source_p,
               const char *nick, const char *text)
{
  struct Client *target_p = NULL;
  const char *server = NULL, *s = NULL;

  /*
   * user[%host]@server addressed?
   */
  if ((server = strchr(nick, '@')))
  {
    if ((target_p = hash_find_server(server + 1)) == NULL)
    {
      sendto_one_numeric(source_p, &me, ERR_NOSUCHSERVER, server + 1);
      return;
    }

    if (!HasUMode(source_p, UMODE_OPER) && strchr(nick, '%'))
    {
      sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
      return;
    }

    if (!IsMe(target_p))
    {
      sendto_one(target_p, ":%s %s %s :%s", source_p->id, command, nick, text);
      return;
    }

    sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
    return;
  }

  if (!HasUMode(source_p, UMODE_OPER))
  {
    sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
    return;
  }

  /*
   * The following two cases allow masks in NOTICEs
   * (for OPERs only)
   *
   * Armin, 8Jun90 ([email protected])
   */
  if (*nick == '$')
  {
    if (*(nick + 1) == '$' || *(nick + 1) == '#')
      ++nick;
    else if (MyClient(source_p))
    {
      sendto_one_notice(source_p, &me, ":The command %s %s is no longer supported, please use $%s",
                        command, nick, nick);
      return;
    }

    if ((s = strrchr(nick, '.')) == NULL)
    {
      sendto_one_numeric(source_p, &me, ERR_NOTOPLEVEL, nick);
      return;
    }

    while (*++s)
      if (*s == '.' || *s == '*' || *s == '?')
        break;

    if (*s == '*' || *s == '?')
    {
      sendto_one_numeric(source_p, &me, ERR_WILDTOPLEVEL, nick);
      return;
    }

    sendto_match_butone(IsServer(source_p->from) ? source_p->from : NULL, source_p,
                        nick + 1, (*nick == '#') ? MATCH_HOST : MATCH_SERVER,
                        "%s $%s :%s", command, nick, text);
  }
}
Пример #22
0
int m_who(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    aClient *ac;
    chanMember *cm;
    Link *lp;
    int shown=0, i=0, showall=IsAnOper(sptr);
    char status[4];

    /* drop nonlocal clients */
    if(!MyClient(sptr))
	return 0;
    
    if(!build_searchopts(sptr, parc-1, parv+1))
	return 0; /* /who was no good */
    
    if(wsopts.gcos!=NULL && (strchr(wsopts.gcos, '?'))==NULL &&
       (strchr(wsopts.gcos, '*'))==NULL)
	gchkfn=mycmp;
    else
	gchkfn=match;
    if(wsopts.nick!=NULL && (strchr(wsopts.nick, '?'))==NULL &&
       (strchr(wsopts.nick, '*'))==NULL)
	nchkfn=mycmp;
    else
	nchkfn=match;
    if(wsopts.user!=NULL && (strchr(wsopts.user, '?'))==NULL &&
       (strchr(wsopts.user, '*'))==NULL)
	uchkfn=mycmp;
    else
	uchkfn=match;
    if(wsopts.host!=NULL && (strchr(wsopts.host, '?'))==NULL &&
       (strchr(wsopts.host, '*'))==NULL)
	hchkfn=mycmp;
    else
	hchkfn=match;

    if(wsopts.ip!=NULL && (strchr(wsopts.ip, '?'))==NULL &&
       (strchr(wsopts.ip, '*'))==NULL)
	ichkfn=mycmp;
    else
	ichkfn=match;

    if(wsopts.channel!=NULL)
    {
	if(IsMember(sptr,wsopts.channel) && (!(wsopts.channel->mode.mode & MODE_AUDITORIUM) ||
           is_chan_opvoice(sptr, wsopts.channel)))
	    showall=1;
	else if(SecretChannel(wsopts.channel) && IsAdmin(sptr))
	    showall=1;
	else if(!SecretChannel(wsopts.channel) && IsAnOper(sptr))
	    showall=1;
	else
	    showall=0;
	if(showall || !SecretChannel(wsopts.channel))
	{
	    for(cm=wsopts.channel->members; cm; cm=cm->next)
	    {
		ac=cm->cptr;
		i=0;
		if(!chk_who(ac,showall))
		    continue;
		/* If we have channel flags set, verify they match */
		if(wsopts.channelflags && ((cm->flags & wsopts.channelflags) == 0))
		    continue;
		/* get rid of the pidly stuff first */
		/* wow, they passed it all, give them the reply...
		 * IF they haven't reached the max, or they're an oper */
		status[i++]=(ac->user->away==NULL ? 'H' : 'G');
		status[i]=(IsAnOper(ac) ? '*' : ((IsInvisible(ac) &&
						  IsOper(sptr)) ? '%' : 0));
		status[((status[i]) ? ++i : i)]=((cm->flags&CHFL_CHANOP) ? '@'
						 : ((cm->flags&CHFL_VOICE) ? 
						    '+' : 0));
		status[++i]=0;
		sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name,
			   wsopts.channel->chname, ac->user->username,
			   WHO_HOST(ac), WHO_SERVER(sptr, ac), ac->name, status,
			   WHO_HOPCOUNT(sptr, ac),
			   ac->info);
	    }
	}
	sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, sptr->name,
		   wsopts.channel->chname, "WHO");
	return 0;
    }
    /* if (for whatever reason) they gave us a nick with no
     * wildcards, just do a find_person, bewm! */
    else if(nchkfn==mycmp)
    {
	ac=find_person(wsopts.nick,NULL);
	if(ac!=NULL)
	{
	    if(!chk_who(ac,1))
	    {
		sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, sptr->name,
			   wsopts.host!=NULL ? wsopts.host : wsopts.nick, "WHO");
		return 0;
	    }
	    else
	    {
		status[0]=(ac->user->away==NULL ? 'H' : 'G');
		status[1]=(IsAnOper(ac) ? '*' : (IsInvisible(ac) &&
						 IsAnOper(sptr) ? '%' : 0));
		status[2]=0;
		sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name,
			   wsopts.show_chan ? first_visible_channel(ac, sptr)
			   : "*", ac->user->username, WHO_HOST(ac),
			   WHO_SERVER(sptr, ac), ac->name, status,
			   WHO_HOPCOUNT(sptr, ac),
			   ac->info);
		sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, sptr->name,
			   wsopts.host!=NULL ? wsopts.host : wsopts.nick, "WHO");
		return 0;
	    }
	}
	sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, sptr->name,
		   wsopts.host!=NULL ? wsopts.host : wsopts.nick, "WHO");
	return 0;
    }
    
    if(wsopts.search_chan)
    {
	for(lp = sptr->user->channel; lp; lp = lp->next)
	{
	    for(cm = lp->value.chptr->members; cm; cm = cm->next)
	    {
		ac = cm->cptr;
		if(!chk_who(ac, 1))
		    continue;
		
		if(shown==MAXWHOREPLIES && !IsAnOper(sptr))
		{
		    sendto_one(sptr, getreply(ERR_WHOLIMEXCEED), me.name,
			       sptr->name, MAXWHOREPLIES, "WHO");
		    break;
		}
		
		i = 0;
		status[i++]=(ac->user->away==NULL ? 'H' : 'G');
		status[i]=(IsAnOper(ac) ? '*' : ((IsInvisible(ac) &&
						  IsOper(sptr)) ? '%' : 0));
		status[((status[i]) ? ++i : i)]=((cm->flags&CHFL_CHANOP) ? 
						 '@' : ((cm->flags&CHFL_VOICE)
							? '+' : 0));
		status[++i]=0;
		sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name,
			   lp->value.chptr->chname, ac->user->username,
			   WHO_HOST(ac),WHO_SERVER(sptr, ac), ac->name,
			   status, WHO_HOPCOUNT(sptr, ac), ac->info);
		shown++;
	    }
	}
    }
    else
    {
	for(ac=client;ac;ac=ac->next)
	{
	    if(!chk_who(ac,showall))
		continue;
	    /* wow, they passed it all, give them the reply...
	     * IF they haven't reached the max, or they're an oper */
	    if(shown==MAXWHOREPLIES && !IsAnOper(sptr))
	    {
		sendto_one(sptr, getreply(ERR_WHOLIMEXCEED), me.name, 
			   sptr->name, MAXWHOREPLIES, "WHO");
		break; /* break out of loop so we can send end of who */
	    }
	    status[0]=(ac->user->away==NULL ? 'H' : 'G');
	    status[1]=(IsAnOper(ac) ? '*' : (IsInvisible(ac) && 
					     IsAnOper(sptr) ? '%' : 0));
	    status[2]=0;
	    sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name,
		       wsopts.show_chan ? first_visible_channel(ac, sptr) :
		       "*", ac->user->username, WHO_HOST(ac),
		       WHO_SERVER(sptr, ac), ac->name, status,
		       WHO_HOPCOUNT(sptr, ac), ac->info);
	    shown++;
	}
    }
    sendto_one(sptr, getreply(RPL_ENDOFWHO), me.name, sptr->name,
	       (wsopts.host!=NULL ? wsopts.host :
		(wsopts.nick!=NULL ? wsopts.nick :
		 (wsopts.user!=NULL ? wsopts.user :
		  (wsopts.gcos!=NULL ? wsopts.gcos :
		   (wsopts.server!=NULL ? wsopts.server->name :
		    "*"))))), "WHO");
    return 0;
}
Пример #23
0
int
m_scan_klines(struct Client *cptr, struct Client *sptr, int parc, char *parv[], char *varparv[])
{
  char *host_mask = NULL, *user_mask = NULL;
  int list = 1, count = 0, listed_so_far = 0;
  int list_max = 100;
  int expired = 0;
  char *placed_by = NULL;
  int i;
  struct ConfItem *aconf;

  if (!HasUmode(sptr,UMODE_SEEKLINES))
    {
      if (SeesOperMessages(sptr))
	sendto_one(sptr,":%s NOTICE %s :You have no 2 umode", me.name, parv[0]);
      else
	sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }

  if (parc < 2)
    {
      if (!IsServer(sptr))
	sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
		   me.name, parv[0], "SCAN KLINES");
      return 0;
    }

  for (i = 2; i < parc; i++)
    {
      if (!irccmp(parv[i], "no-list"))
	list = 0;
      else if (!irccmp(parv[i], "list"))
	list = 1;
      else if (!irccmp(parv[i], "not-expired"))
	expired = 0;
      else if (!irccmp(parv[i], "expired"))
	expired = 1;
      else if (i < (parc - 1))
	{
	  if (!irccmp(parv[i], "list-max"))
	    {
	      list_max = strtoul(parv[++i], NULL, 0);
	    }
	  else if (!irccmp(parv[i], "host-mask"))
	    {
	      host_mask = parv[++i];
	    }
	  else if (!irccmp(parv[i], "user-mask"))
	    {
	      user_mask = parv[++i];
	    }
	  else if (!irccmp(parv[i], "placed-by"))
	    {
	      placed_by = parv[++i];
	    }
	}
    }

  for (aconf = kline_list; aconf; aconf = aconf->kline_next)
    {
      char *p;
      if (aconf->status != CONF_KILL)
	continue;
      if (host_mask && !match(host_mask, aconf->host))
	continue;
      if (user_mask && !match(user_mask, aconf->user))
	continue;
      /* extract the user who placed the K:line */
      if ((p = strchr(aconf->passwd, ';')))
	{
	  int skip = 0;
	  *p = '\0';
	  skip = placed_by && !match(placed_by, aconf->passwd);
	  *p = ';';
	  if (skip)
	    continue;
	}
      /* true if:
       *            (can expire     (and has expired           ))
       * (we want expired and have expired, or vice versa        )
       */
      if (expired ^ (aconf->hold && (aconf->hold <= CurrentTime)))
	continue;

      count++;
      if (list && (list_max > ++listed_so_far))
	{
          /* p points to the semicolon in the comment field, if there is one */
	  if (p)
	    *p = '\0';
          if (aconf->hold)
            {
              if (p)
                {
/*                   send_markup(sptr, &me, "SCAN-KLINE", */
/*                               "!begin<1>%s@%s!end<1> klined " */
/*                               "until !begin<2>!date<%ld>!end<2> (!begin<3>!time<%ld>!end<3>) " */
/*                               "by !begin<4>%s!end<4>, because: %s", */
/*                               aconf->user, aconf->host, aconf->hold, aconf->hold - CurrentTime, aconf->passwd, p + 2); */
                  send_markup(sptr, &me, "SCAN-KLINE",
                              "%s@%s klined "
                              "until %s (%s) "
                              "by %s, because: %s",
                              aconf->user, aconf->host, smalldate(aconf->hold), smalltime(aconf->hold - CurrentTime), aconf->passwd, p + 2);
                }
              else
                {
/*                   send_markup(sptr, &me, "SCAN-KLINE", */
/*                               "!begin<1>%s@%s!end<1> klined " */
/*                               "until !begin<2>!date<%ld>!end<2> (!begin<3>!time<%ld>!end<3>) " */
/*                               "by !begin<4>%s!end<4>", */
/*                               aconf->user, aconf->host, aconf->hold, aconf->hold - CurrentTime, aconf->passwd); */
                  send_markup(sptr, &me, "SCAN-KLINE",
                              "%s@%s klined "
                              "until %s (%s) "
                              "by %s",
                              aconf->user, aconf->host, smalldate(aconf->hold), smalltime(aconf->hold - CurrentTime), aconf->passwd);
                }
            }
          else
            {
              if (p)
                {
/*                   send_markup(sptr, &me, "SCAN-KLINE", */
/*                               "!begin<1>%s@%s!end<1> klined !begin<2>permanently!end<2> " */
/*                               "by !begin<4>%s!end<4>, because: %s", */
/*                               aconf->user, aconf->host, aconf->passwd, p + 2); */
                  send_markup(sptr, &me, "SCAN-KLINE",
                              "%s@%s klined permanently "
                              "by %s, because: %s",
                              aconf->user, aconf->host, aconf->passwd, p + 2);
                }
              else
                {
/*                   send_markup(sptr, &me, "SCAN-KLINE", */
/*                               "!begin<1>%s@%s!end<1> klined !begin<2>permanently!end<2> " */
/*                               "by !begin<4>%s!end<4>", */
/*                               aconf->user, aconf->host, aconf->passwd); */
                  send_markup(sptr, &me, "SCAN-KLINE",
                              "%s@%s klined permanently "
                              "by %s",
                              aconf->user, aconf->host, aconf->passwd);
                }
            }
	  if (p)
	    {
	      *p = ';';
	    }
	}
    }

  send_markup(sptr, &me, "KLINE-END", "End of kline list");
/*   send_markup(sptr, &me, "SCAN-SUMMARY", "!begin<1>%d!end<1> matched", count); */
  send_markup(sptr, &me, "SCAN-SUMMARY", "%d matched", count);

  return 0;
}
Пример #24
0
/*
** m_whowas
**	parv[0] = sender prefix
**	parv[1] = nickname queried
*/
int	m_whowas(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	Reg	aName	*wp, *wp2 = NULL;
	Reg	int	j = 0;
	Reg	anUser	*up = NULL;
	int	max = -1;
	char	*p = NULL, *nick, *s;

 	if (parc < 2)
	    {
		sendto_one(sptr, replies[ERR_NONICKNAMEGIVEN], ME, BadTo(parv[0]));
		return 1;
	    }
	if (parc > 2)
		max = atoi(parv[2]);
	if (parc > 3)
		if (hunt_server(cptr,sptr,":%s WHOWAS %s %s :%s", 3,parc,parv))
			return 3;

	parv[1] = canonize(parv[1]);
	if (!MyConnect(sptr))
		max = MIN(max, 20);

	for (s = parv[1]; (nick = strtoken(&p, s, ",")); s = NULL)
	    {
		wp = wp2 = &was[(ww_index ? ww_index : ww_size) - 1];
		j = 0;

		do {
			if (mycmp(nick, wp->ww_nick) == 0)
			    {
				up = wp->ww_user;
				sendto_one(sptr, replies[RPL_WHOWASUSER],
					   ME, BadTo(parv[0]), wp->ww_nick, up->username,
					   up->host, wp->ww_info);
				sendto_one(sptr, replies[RPL_WHOISSERVER],
					   ME, BadTo(parv[0]), wp->ww_nick, up->server,
					   myctime(wp->ww_logout));
				j++;
			    }
			if (max > 0 && j >= max)
				break;
			if (wp == was)
				wp = &was[ww_size - 1];
			else
				wp--;
		} while (wp != wp2);

		if (up == NULL)
		    {
			if (strlen(nick) > (size_t) NICKLEN)
				nick[NICKLEN] = '\0';
			sendto_one(sptr, replies[ERR_WASNOSUCHNICK], ME, BadTo(parv[0]),
				   nick);
		    }
		else
			up = NULL;

		if (p)
			p[-1] = ',';
	    }
	sendto_one(sptr, replies[RPL_ENDOFWHOWAS], ME, BadTo(parv[0]), parv[1]);
	return 2;
    }
Пример #25
0
int
m_scan_idle(struct Client *cptr, struct Client *sptr, int parc, char *parv[], char *varparv[])
{
	struct Client *ptr, *target = NULL;
	char *eptr, buffer[321];
	int idle_time, check_time, len = 0, count = 0;

	if(MyClient(sptr) && !HasUmode(sptr, UMODE_USER_AUSPEX))
	{
		if(SeesOperMessages(sptr))
			sendto_one(sptr,":%s NOTICE %s :You have no a umode", me.name, parv[0]);
		else
			sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
		return 0;
	}

	if(parc < 3)
	{
		if (!IsServer(sptr))
			sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
					me.name, parv[0], "SCAN IDLE");
		return 0;
	}

	idle_time = strtoul(parv[2], &eptr, 10);
	if(eptr == parv[2])
		return 0;
	/* Store the timestamp which last_sent should be >= to save time */
	check_time = CurrentTime - idle_time;

	/* If the query is for another server, pass it on and return. */
	if(parc > 3)
	{
		if(MyClient(sptr) && !HasUmode(sptr, UMODE_REMOTEINFO))
		{
			if(SeesOperMessages(sptr))
				sendto_one(sptr,":%s NOTICE %s :You have no S umode(cannot send remote)", me.name, parv[0]);
			else
				sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
			return 0;
		}

		if(!irccmp(parv[3], "GLOBAL") || !irccmp(parv[3], "*"))
			sendto_serv_butone(cptr, ":%s SCAN IDLE %d *", parv[0], idle_time);
		else if((target = find_server(parv[3])) == NULL) {
			sendto_one(sptr, form_str(ERR_NOSUCHSERVER),
					me.name, parv[0], parv[3]);
			return 0;
		}else if(!IsMe(target)) { /* But only if the query is not on us... */

			sendto_prefix_one(target, sptr, ":%s SCAN IDLE %d %s", parv[0],
					idle_time, target->name);
			return 0;
		}
	}

	buffer[0] = '\0';
	for(ptr = local_cptr_list; ptr; ptr = ptr->next_local_client)
	{
		if(ptr->user->last_sent < check_time)
			continue;

		if(len + strlen(ptr->name) > 319)
		{
			buffer[len - 1] = '\0'; /* Strip the trailing space */
			send_markup(sptr, &me, "SCAN-IDLE", "%d %s", idle_time, buffer);
			buffer[0] = '\0';
			len = 0;
		}

		strcat(buffer, ptr->name);
		strcat(buffer, " ");
		len += strlen(ptr->name) + 1;
		count++;
	}

	if(buffer[0])
	{
		buffer[len - 1] = '\0';
		send_markup(sptr, &me, "SCAN-IDLE", "%d %s", idle_time, buffer);
	}

	send_markup(sptr, &me, "IDLE-END", "End of idle listing");
	if(count > 0 || target || parc == 3) /* Don't give a summary for globals if no results matched */
		send_markup(sptr, &me, "SCAN-SUMMARY", "%d matched", count);

	return 0;
}
Пример #26
0
/* m_knock
 *    parv[1] = channel
 *
 *  The KNOCK command has the following syntax:
 *   :<sender> KNOCK <channel>
 *
 *  If a user is not banned from the channel they can use the KNOCK
 *  command to have the server NOTICE the channel operators notifying
 *  they would like to join.  Helpful if the channel is invite-only, the
 *  key is forgotten, or the channel is full (INVITE can bypass each one
 *  of these conditions.  Concept by Dianora <*****@*****.**> and written by
 *  <anonymous>
 */
static int
m_knock(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct Channel *chptr;
    char *p, *name;

    if(MyClient(source_p) && ConfigChannel.use_knock == 0) {
        sendto_one(source_p, form_str(ERR_KNOCKDISABLED),
                   me.name, source_p->name);
        return 0;
    }

    name = LOCAL_COPY(parv[1]);

    /* dont allow one knock to multiple chans */
    if((p = strchr(name, ',')))
        *p = '\0';

    if(!IsChannelName(name)) {
        sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
                           form_str(ERR_NOSUCHCHANNEL), name);
        return 0;
    }

    if((chptr = find_channel(name)) == NULL) {
        sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
                           form_str(ERR_NOSUCHCHANNEL), name);
        return 0;
    }

    if(IsMember(source_p, chptr)) {
        if(MyClient(source_p))
            sendto_one(source_p, form_str(ERR_KNOCKONCHAN),
                       me.name, source_p->name, name);
        return 0;
    }

    if(!((chptr->mode.mode & MODE_INVITEONLY) || (*chptr->mode.key) ||
         (chptr->mode.limit &&
          rb_dlink_list_length(&chptr->members) >= (unsigned long)chptr->mode.limit))) {
        sendto_one_numeric(source_p, ERR_CHANOPEN,
                           form_str(ERR_CHANOPEN), name);
        return 0;
    }

    /* cant knock to a +p channel */
    if(HiddenChannel(chptr)) {
        sendto_one_numeric(source_p, ERR_CANNOTSENDTOCHAN,
                           form_str(ERR_CANNOTSENDTOCHAN), name, "channel does not accept knocks");
        return 0;
    }


    if(MyClient(source_p)) {
        /* don't allow a knock if the user is banned */
        if(is_banned(chptr, source_p, NULL, NULL, NULL) == CHFL_BAN ||
           is_quieted(chptr, source_p, NULL, NULL, NULL) == CHFL_BAN) {
            sendto_one_numeric(source_p, ERR_CANNOTSENDTOCHAN,
                               form_str(ERR_CANNOTSENDTOCHAN), name, "you are banned from this channel");
            return 0;
        }

        /* local flood protection:
         * allow one knock per user per knock_delay
         * allow one knock per channel per knock_delay_channel
         */
        if(!IsOper(source_p) &&
           (source_p->localClient->last_knock + ConfigChannel.knock_delay) > rb_current_time()) {
            sendto_one(source_p, form_str(ERR_TOOMANYKNOCK),
                       me.name, source_p->name, name, "user");
            return 0;
        } else if((chptr->last_knock + ConfigChannel.knock_delay_channel) > rb_current_time()) {
            sendto_one(source_p, form_str(ERR_TOOMANYKNOCK),
                       me.name, source_p->name, name, "channel");
            return 0;
        }

        /* ok, we actually can send the knock, tell client */
        source_p->localClient->last_knock = rb_current_time();

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

    chptr->last_knock = rb_current_time();

    if(ConfigChannel.use_knock)
        sendto_channel_local(chptr->mode.mode & MODE_FREEINVITE ? ALL_MEMBERS : ONLY_CHANOPS,
                             chptr, form_str(RPL_KNOCK),
                             me.name, name, name, source_p->name,
                             source_p->username, source_p->host);

    sendto_server(client_p, chptr, CAP_KNOCK|CAP_TS6, NOCAPS,
                  ":%s KNOCK %s", use_id(source_p), name);
    sendto_server(client_p, chptr, CAP_KNOCK, CAP_TS6,
                  ":%s KNOCK %s", source_p->name, name);
    return 0;
}
Пример #27
0
/*
 * m_topic
 *      parv[0] = sender prefix
 *      parv[1] = channel name
 *	parv[2] = new topic, if setting topic
 */
static int
m_topic(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr = NULL;
	struct membership *msptr;
	char *p = NULL;

	if((p = strchr(parv[1], ',')))
		*p = '\0';

	if(MyClient(source_p) && !IsFloodDone(source_p))
		flood_endgrace(source_p);

	if(!IsChannelName(parv[1]))
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
				   form_str(ERR_NOSUCHCHANNEL), parv[1]);
		return 0;
	}

	chptr = find_channel(parv[1]);

	if(chptr == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
				form_str(ERR_NOSUCHCHANNEL), parv[1]);
		return 0;
	}

	/* setting topic */
	if(parc > 2)
	{
		msptr = find_channel_membership(chptr, source_p);

		if(msptr == NULL)
		{
			sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
					form_str(ERR_NOTONCHANNEL), parv[1]);
			return 0;
		}

		if((chptr->mode.mode & MODE_TOPICLIMIT) == 0 || is_chanop(msptr))
		{
			char topic_info[USERHOST_REPLYLEN];
			ircsprintf(topic_info, "%s!%s@%s",
					source_p->name, source_p->username, source_p->host);
			set_channel_topic(chptr, parv[2], topic_info, CurrentTime);

			sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
					":%s TOPIC %s :%s",
					use_id(source_p), chptr->chname,
					chptr->topic == NULL ? "" : chptr->topic);
			sendto_server(client_p, chptr, NOCAPS, CAP_TS6,
					":%s TOPIC %s :%s",
					source_p->name, chptr->chname,
					chptr->topic == NULL ? "" : chptr->topic);
			sendto_channel_local(ALL_MEMBERS,
					chptr, ":%s!%s@%s TOPIC %s :%s",
					source_p->name, source_p->username,
					source_p->host, chptr->chname,
					chptr->topic == NULL ? "" : chptr->topic);
		}
		else
			sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
					me.name, source_p->name, parv[1]);
	}
	else if(MyClient(source_p))
	{
		if(!IsMember(source_p, chptr) && SecretChannel(chptr))
		{
			sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
					form_str(ERR_NOTONCHANNEL), parv[1]);
			return 0;
		}
		if(chptr->topic == NULL)
			sendto_one(source_p, form_str(RPL_NOTOPIC),
					me.name, source_p->name, parv[1]);
		else
		{
			sendto_one(source_p, form_str(RPL_TOPIC),
					me.name, source_p->name, chptr->chname, chptr->topic);

			sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
					me.name, source_p->name, chptr->chname,
					chptr->topic_info, chptr->topic_time);
		}
	}

	return 0;
}
Пример #28
0
/*
 * parse a buffer.
 *
 * NOTE: parse() should not be called recusively by any other functions!
 */
void
parse(struct Client *client_p, char *pbuffer, char *bufend)
{
	struct Client *from = client_p;
	char *ch;
	char *s;
	char *end;
	int i;
	int paramcount, mpara = 0;
	char *numeric = 0;
	struct Message *mptr;

	Debug((DEBUG_DEBUG, "Parsing %s:", pbuffer));

	s_assert(!IsDead(client_p));
	s_assert(client_p->localClient->fd >= 0);
	if(IsDead(client_p) || client_p->localClient->fd < 0)
		return;
	s_assert(bufend-pbuffer < 512);

	for (ch = pbuffer; *ch == ' '; ch++)	/* skip spaces */
		/* null statement */ ;

	para[0] = from->name;

	if(*ch == ':')
	{
		ch++;

		/*
		 * Copy the prefix to 'sender' assuming it terminates
		 * with SPACE (or NULL, which is an error, though).
		 */

		sender = ch;

		if((s = strchr(ch, ' ')))
		{
			*s = '\0';
			s++;
			ch = s;
		}

		i = 0;

		if(*sender && IsServer(client_p))
		{
			from = find_client(sender);
			if(from == NULL)
			{
				from = find_server(sender);
			}

			/* Hmm! If the client corresponding to the
			 * prefix is not found--what is the correct
			 * action??? Now, I will ignore the message
			 * (old IRC just let it through as if the
			 * prefix just wasn't there...) --msa
			 */
			if(from == NULL)
			{
				Debug((DEBUG_ERROR, "Unknown prefix (%s)(%s) from (%s)",
				       sender, pbuffer, client_p->name));
				ServerStats->is_unpf++;

				remove_unknown(client_p, sender, pbuffer);

				return;
			}

			para[0] = from->name;

			if(from->from != client_p)
			{
				ServerStats->is_wrdi++;
				Debug((DEBUG_ERROR, "Message (%s) coming from (%s)",
				       pbuffer, client_p->name));

				cancel_clients(client_p, from, pbuffer);
				return;
			}
		}
		while (*ch == ' ')
			ch++;
	}

	if(*ch == '\0')
	{
		ServerStats->is_empt++;
		Debug((DEBUG_NOTICE, "Empty message from host %s:%s", client_p->name, from->name));
		return;
	}

	/*
	 * Extract the command code from the packet.  Point s to the end
	 * of the command code and calculate the length using pointer
	 * arithmetic.  Note: only need length for numerics and *all*
	 * numerics must have parameters and thus a space after the command
	 * code. -avalon
	 */

	/* EOB is 3 chars long but is not a numeric */

	if(*(ch + 3) == ' ' &&	/* ok, lets see if its a possible numeric.. */
	   IsDigit(*ch) && IsDigit(*(ch + 1)) && IsDigit(*(ch + 2)))
	{
		mptr = (struct Message *) NULL;
		numeric = ch;
		paramcount = MAXPARA;
		ServerStats->is_num++;
		s = ch + 3;	/* I know this is ' ' from above if */
		*s++ = '\0';	/* blow away the ' ', and point s to next part */
	}
	else
	{
		int ii = 0;

		if((s = strchr(ch, ' ')))
			*s++ = '\0';

		mptr = hash_parse(ch);

		if(!mptr || !mptr->cmd)
		{
			/*
			 * Note: Give error message *only* to recognized
			 * persons. It's a nightmare situation to have
			 * two programs sending "Unknown command"'s or
			 * equivalent to each other at full blast....
			 * If it has got to person state, it at least
			 * seems to be well behaving. Perhaps this message
			 * should never be generated, though...  --msa
			 * Hm, when is the buffer empty -- if a command
			 * code has been found ?? -Armin
			 */
			if(pbuffer[0] != '\0')
			{
				if(IsPerson(from))
					sendto_one(from,
						   ":%s %d %s %s :Unknown command",
						   me.name, ERR_UNKNOWNCOMMAND, from->name, ch);
				Debug((DEBUG_ERROR, "Unknown (%s) from %s",
				       ch, get_client_name(client_p, HIDE_IP)));
			}
			ServerStats->is_unco++;
			return;
		}

		paramcount = mptr->parameters;
		mpara = mptr->maxpara;

		ii = bufend - ((s) ? s : ch);
		mptr->bytes += ii;
	}

	end = bufend - 1;

	/* XXX this should be done before parse() is called */
	if(*end == '\n')
		*end-- = '\0';
	if(*end == '\r')
		*end = '\0';

	i = 0;

	if(s != NULL)
		i = string_to_array(s, para);

	if(mptr == (struct Message *) NULL)
	{
		do_numeric(numeric, client_p, from, i, para);
		return;
	}

	if(handle_command(mptr, client_p, from, i, para) < -1)
	{
		char *p;
		for (p = pbuffer; p <= end; p += 8)
		{
			/* HACK HACK */
			/* Its expected this nasty code can be removed
			 * or rewritten later if still needed.
			 */
			if((unsigned long) (p + 8) > (unsigned long) end)
			{
				for (; p <= end; p++)
				{
					ilog(L_CRIT, "%02x |%c", p[0], p[0]);
				}
			}
			else
				ilog(L_CRIT,
				     "%02x %02x %02x %02x %02x %02x %02x %02x |%c%c%c%c%c%c%c%c",
				     p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
				     p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
		}
	}
}
Пример #29
0
/*
 * mr_webirc - webirc message handler
 *      parv[1] = password
 *      parv[2] = fake username (we ignore this)
 *	parv[3] = fake hostname
 *	parv[4] = fake ip
 */
static int
mr_webirc(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct ConfItem *aconf;
	const char *encr;

	if (!strchr(parv[4], '.') && !strchr(parv[4], ':'))
	{
		sendto_one(source_p, "NOTICE * :Invalid IP");
		return 0;
	}

	aconf = find_address_conf(client_p->host, client_p->sockhost,
				IsGotId(client_p) ? client_p->username : "******",
				IsGotId(client_p) ? client_p->username : "******",
				(struct sockaddr *) &client_p->localClient->ip,
				client_p->localClient->ip.ss_family, NULL);
	if (aconf == NULL || !(aconf->status & CONF_CLIENT))
		return 0;
	if (!IsConfDoSpoofIp(aconf) || irccmp(aconf->info.name, "webirc."))
	{
		/* XXX */
		sendto_one(source_p, "NOTICE * :Not a CGI:IRC auth block");
		return 0;
	}
	if (EmptyString(aconf->passwd))
	{
		sendto_one(source_p, "NOTICE * :CGI:IRC auth blocks must have a password");
		return 0;
	}

	if (EmptyString(parv[1]))
		encr = "";
	else if (IsConfEncrypted(aconf))
		encr = rb_crypt(parv[1], aconf->passwd);
	else
		encr = parv[1];

	if (strcmp(encr, aconf->passwd))
	{
		sendto_one(source_p, "NOTICE * :CGI:IRC password incorrect");
		return 0;
	}


	rb_strlcpy(source_p->sockhost, parv[4], sizeof(source_p->sockhost));

	if(strlen(parv[3]) <= HOSTLEN)
		rb_strlcpy(source_p->host, parv[3], sizeof(source_p->host));
	else
		rb_strlcpy(source_p->host, source_p->sockhost, sizeof(source_p->host));

	rb_inet_pton_sock(parv[4], (struct sockaddr *)&source_p->localClient->ip);

	/* Check dlines now, klines will be checked on registration */
	if((aconf = find_dline((struct sockaddr *)&source_p->localClient->ip,
			       source_p->localClient->ip.ss_family)))
	{
		if(!(aconf->status & CONF_EXEMPTDLINE))
		{
			exit_client(client_p, source_p, &me, "D-lined");
			return 0;
		}
	}

	sendto_one(source_p, "NOTICE * :Congratulations, your host is reset via I:line: %s %s", parv[3], parv[4]);
	return 0;
}
Пример #30
0
static void
send_usage(aClient *cptr, char *nick)
{

#if defined( HAVE_GETRUSAGE )
    struct rusage rus;
    time_t      secs, rup;

#ifdef  hz
#define hzz hz
#else
#ifdef HZ
#define hzz HZ
#else
    int         hzz = 1;

#endif
#endif

    if (getrusage(RUSAGE_SELF, &rus) == -1) {
        sendto_one(cptr, ":%s NOTICE %s :Getruseage error: %s.",
                   me.name, nick, sys_errlist[errno]);
        return;
    }
    secs = rus.ru_utime.tv_sec + rus.ru_stime.tv_sec;
    rup = timeofday - me.since;
    if (secs == 0)
        secs = 1;

    sendto_one(cptr,
               ":%s %d %s :CPU Secs %d:%d User %d:%d System %d:%d",
               me.name, RPL_STATSDEBUG, nick, secs / 60, secs % 60,
               rus.ru_utime.tv_sec / 60, rus.ru_utime.tv_sec % 60,
               rus.ru_stime.tv_sec / 60, rus.ru_stime.tv_sec % 60);
    sendto_one(cptr, ":%s %d %s :RSS %d ShMem %d Data %d Stack %d",
               me.name, RPL_STATSDEBUG, nick, rus.ru_maxrss,
               rus.ru_ixrss / (rup * hzz), rus.ru_idrss / (rup * hzz),
               rus.ru_isrss / (rup * hzz));
    sendto_one(cptr, ":%s %d %s :Swaps %d Reclaims %d Faults %d",
               me.name, RPL_STATSDEBUG, nick, rus.ru_nswap,
               rus.ru_minflt, rus.ru_majflt);
    sendto_one(cptr, ":%s %d %s :Block in %d out %d",
               me.name, RPL_STATSDEBUG, nick, rus.ru_inblock,
               rus.ru_oublock);
    sendto_one(cptr, ":%s %d %s :Msg Rcv %d Send %d",
               me.name, RPL_STATSDEBUG, nick, rus.ru_msgrcv, rus.ru_msgsnd);
    sendto_one(cptr, ":%s %d %s :Signals %d Context Vol. %d Invol %d",
               me.name, RPL_STATSDEBUG, nick, rus.ru_nsignals,
               rus.ru_nvcsw, rus.ru_nivcsw);
#else
#if defined( HAVE_TIMES )
    struct tms  tmsbuf;
    time_t      secs, mins;
    int         hzz = 1, ticpermin;
    int         umin, smin, usec, ssec;

    ticpermin = hzz * 60;

    umin = tmsbuf.tms_utime / ticpermin;
    usec = (tmsbuf.tms_utime % ticpermin) / (float) hzz;
    smin = tmsbuf.tms_stime / ticpermin;
    ssec = (tmsbuf.tms_stime % ticpermin) / (float) hzz;
    secs = usec + ssec;
    mins = (secs / 60) + umin + smin;
    secs %= hzz;
    if (times(&tmsbuf) == -1) {
        sendto_one(cptr, ":%s %d %s :times(2) error: %s.",
                   me.name, RPL_STATSDEBUG, nick, strerror(errno));
        return;
    }
    secs = tmsbuf.tms_utime + tmsbuf.tms_stime;

    sendto_one(cptr,
               ":%s %d %s :CPU Secs %d:%d User %d:%d System %d:%d",
               me.name, RPL_STATSDEBUG, nick, mins, secs, umin, usec,
               smin, ssec);
#endif /* HAVE_TIMES */
#endif /* HAVE_GETRUSAGE */
    sendto_one(cptr, ":%s %d %s :Reads %d Writes %d",
               me.name, RPL_STATSDEBUG, nick, readcalls, writecalls);
/*    sendto_one(cptr, ":%s %d %s :DBUF alloc %d used %d",
               me.name, RPL_STATSDEBUG, nick, DBufCount, DBufUsedCount);
               */
    sendto_one(cptr,
               ":%s %d %s :Writes:  <0 %d 0 %d <16 %d <32 %d <64 %d",
               me.name, RPL_STATSDEBUG, nick,
               writeb[0], writeb[1], writeb[2], writeb[3], writeb[4]);
    sendto_one(cptr,
               ":%s %d %s :<128 %d <256 %d <512 %d <1024 %d >1024 %d",
               me.name, RPL_STATSDEBUG, nick,
               writeb[5], writeb[6], writeb[7], writeb[8], writeb[9]);
    return;
}