示例#1
0
文件: m_rping.c 项目: Niichan/snircd
/*
 * ms_rping - server message handler
 * -- by Run
 *
 *    parv[0] = sender (sptr->name thus)
 * if sender is a person: (traveling towards start server)
 *    parv[1] = pinged server[mask]
 *    parv[2] = start server (current target)
 *    parv[3] = optional remark
 * if sender is a server: (traveling towards pinged server)
 *    parv[1] = pinged server (current target)
 *    parv[2] = original sender (person)
 *    parv[3] = start time in s
 *    parv[4] = start time in us
 *    parv[5] = the optional remark
 */
int ms_rping(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Client* destination = 0;
  assert(0 != cptr);
  assert(0 != sptr);
  assert(IsServer(cptr));

  /*
   * shouldn't happen
   */
  if (!IsPrivileged(sptr))
    return 0;

  if (IsServer(sptr)) {
    if (parc < 6) {
      /*
       * PROTOCOL ERROR
       */
      return need_more_params(sptr, "RPING");
    }
    if ((destination = FindNServer(parv[1]))) {
      /*
       * if it's not for me, pass it on
       */
      if (IsMe(destination))
	sendcmdto_one(&me, CMD_RPONG, sptr, "%s %s %s %s :%s", cli_name(sptr),
		      parv[2], parv[3], parv[4], parv[5]);
      else
	sendcmdto_one(sptr, CMD_RPING, destination, "%C %s %s %s :%s",
		      destination, parv[2], parv[3], parv[4], parv[5]);
    }
  }
  else {
    if (parc < 3) {
      return need_more_params(sptr, "RPING");
    }
    /*
     * Haven't made it to the start server yet, if I'm not the start server
     * pass it on.
     */
    if (hunt_server_cmd(sptr, CMD_RPING, cptr, 1, "%s %C :%s", 2, parc, parv)
	!= HUNTED_ISME)
      return 0;
    /*
     * otherwise ping the destination from here
     */
    if ((destination = find_match_server(parv[1]))) {
      assert(IsServer(destination) || IsMe(destination));
      sendcmdto_one(&me, CMD_RPING, destination, "%C %C %s :%s", destination,
		    sptr, militime(0, 0), parv[3]);
    }
    else
      send_reply(sptr, ERR_NOSUCHSERVER, parv[1]);
  }
  return 0;
}
示例#2
0
文件: m_opmode.c 项目: mojadita/ircd
/** Handle an OPMODE message from a server connection.
 *
 * \a parv has the same elements as for ms_mode().
 *
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int ms_opmode(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Channel *chptr = 0;
  struct ModeBuf mbuf;

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

  if (IsLocalChannel(parv[1]))
    return 0;

  if ('#' != *parv[1] || !(chptr = FindChannel(parv[1])))
    return send_reply(sptr, ERR_NOSUCHCHANNEL, parv[1]);

  modebuf_init(&mbuf, sptr, cptr, chptr,
	       (MODEBUF_DEST_CHANNEL | /* Send MODE to channel */
		MODEBUF_DEST_SERVER  | /* And to server */
		MODEBUF_DEST_OPMODE  | /* Use OPMODE */
		MODEBUF_DEST_HACK4   | /* Generate a HACK(4) notice */
		MODEBUF_DEST_LOG));    /* Log the mode changes to OPATH */

  mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2,
	     (MODE_PARSE_SET    | /* Set the modes on the channel */
	      MODE_PARSE_STRICT | /* Be strict about it */
	      MODE_PARSE_FORCE),  /* And force them to be accepted */
	      NULL);

  modebuf_flush(&mbuf); /* flush the modes */

  return 0;
}
示例#3
0
/** Report the value of a log setting.
 * @param[in] from &Client asking for details.
 * @param[in] fields Array of parameters to get.
 * @param[in] count Number of fields in \a fields.
 */
static void
feature_log_get(struct Client* from, const char* const* fields, int count)
{
  struct LogTypes *desc;
  char *value, *subsys;

  assert(0 != from); /* never called by .conf parser */

  if (count < 1) /* return default facility */
    send_reply(from, SND_EXPLICIT | RPL_FEATURE, ":Log facility: %s",
	       log_get_default());
  else if (count < 2)
    need_more_params(from, "GET");
  else if (!(subsys = log_canon(fields[0]))) { /* no such subsystem */
    send_reply(from, ERR_BADLOGSYS, fields[0]);
  } else if ((desc = feature_log_desc(from, fields[1]))) {
    if ((value = (*desc->get)(fields[0]))) /* send along value */
      send_reply(from, SND_EXPLICIT | RPL_FEATURE,
		 ":Log %s for subsystem %s: %s", desc->type, subsys,
		 (*desc->get)(subsys));
    else
      send_reply(from, SND_EXPLICIT | RPL_FEATURE,
		 ":No log %s is set for subsystem %s", desc->type, subsys);
  }
}
示例#4
0
文件: m_asll.c 项目: Niichan/snircd
/*
 * mo_asll - oper message handler
 */
int mo_asll(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  char *mask;
  struct Client *acptr;
  int hits;
  int i;

  if (parc < 2)
    return need_more_params(sptr, "ASLL");

  if (parc == 2 && MyUser(sptr))
    parv[parc++] = cli_name(&me);

  if (hunt_server_prio_cmd(sptr, CMD_ASLL, cptr, 1, "%s %C", 2, parc, parv) != HUNTED_ISME)
    return 0;
  mask = parv[1];

  for (i = hits = 0; i <= HighestFd; i++) {
    acptr = LocalClientArray[i];
    if (!acptr || !IsServer(acptr) || !MyConnect(acptr) || match(mask, cli_name(acptr)))
      continue;
    send_asll_reply(&me, sptr, cli_name(acptr), cli_serv(acptr)->asll_rtt,
      cli_serv(acptr)->asll_to, cli_serv(acptr)->asll_from);
    hits++;
  }
  sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :AsLL for %s: %d local servers matched", sptr, mask, hits);
  return 0;
}
示例#5
0
文件: m_restart.c 项目: mojadita/ircd
/** Handle a RESTART message from a server connection.
 *
 * \a parv has the following elements:
 * \li \a parv[1] is the target server, or "*" for all.
 * \li \a parv[2] is either "cancel" or a time interval in seconds
 * \li \a parv[\a parc - 1] is the reason
 *
 * All fields must be present.  Additionally, the time interval should
 * not be 0 for messages sent to "*", as that may not function
 * reliably due to buffering in the server.
 *
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int ms_restart(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  const char *target, *when, *reason;

  if (parc < 4)
    return need_more_params(sptr, "RESTART");

  target = parv[1];
  when = parv[2];
  reason = parv[parc - 1];

  /* is it a message we should pay attention to? */
  if (target[0] != '*' || target[1] != '\0') {
    if (hunt_server_cmd(sptr, CMD_RESTART, cptr, 0, "%C %s :%s", 1, parc, parv)
    != HUNTED_ISME)
      return 0;
  } else /* must forward the message */
    sendcmdto_serv(sptr, CMD_RESTART, cptr, "* %s :%s", when, reason);

  /* OK, the message has been forwarded, but before we can act... */
  if (!feature_bool(FEAT_NETWORK_RESTART))
    return 0;

  /* is it a cancellation? */
  if (!ircd_strcmp(when, "cancel"))
    exit_cancel(sptr); /* cancel a pending exit */
  else /* schedule an exit */
    exit_schedule(1, atoi(when), sptr, reason);

  return 0;
}
示例#6
0
文件: m_pass.c 项目: Niichan/snircd
/*
 * mr_pass - registration message handler
 */
int mr_pass(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  char password[BUFSIZE];
  int arg, len;

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

  /* Some clients (brokenly) send "PASS x y" rather than "PASS :x y"
   * when the user enters "x y" as the password.  Unsplit arguments to
   * work around this.
   */
  for (arg = 1, len = 0; arg < parc; ++arg)
  {
    ircd_strncpy(password + len, parv[arg], sizeof(password) - len);
    len += strlen(parv[arg]);
    password[len++] = ' ';
  }
  if (len > 0)
    --len;
  password[len] = '\0';

  if (EmptyString(password))
    return need_more_params(cptr, "PASS");

  ircd_strncpy(cli_passwd(cptr), password, PASSWDLEN);
  return cli_auth(cptr) ? auth_set_password(cli_auth(cptr), password) : 0;
}
/*
 * ms_fakehost - fakehost server message handler
 *
 * parv[0] = sender prefix
 * parv[1] = target user numeric
 * parv[2] = target user's new fake host
 */
int ms_fakehost(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Client *target;

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

  /* Locate our target user; ignore the message if we can't */
  if(!(target = findNUser(parv[1])))
    return 0;

  /* Ignore the assignment if it changes nothing */
  if (HasFakeHost(target) &&
      ircd_strcmp(cli_user(target)->fakehost, parv[2]) == 0)
  {
    return 0;
  }

  /* Assign and propagate the fakehost */
  SetFakeHost(target);
  ircd_strncpy(cli_user(target)->fakehost, parv[2], HOSTLEN);
  hide_hostmask(target);

  sendcmdto_serv_butone(sptr, CMD_FAKEHOST, cptr, "%C %s", target,
                        cli_user(target)->fakehost);
  return 0;
}
示例#8
0
/** Reset a feature to its default values.
 * @param[in] from Client trying to reset the feature, or NULL.
 * @param[in] fields Parameters to set, starting with feature name.
 * @param[in] count Number of fields in \a fields.
 * @return Zero (or, theoretically, CPTR_KILLED).
 */
int
feature_reset(struct Client* from, const char* const* fields, int count)
{
    int i, change = 0;
    struct FeatureDesc *feat;

    assert(0 != from);

    if (!HasPriv(from, PRIV_SET))
        return send_reply(from, ERR_NOPRIVILEGES);

    if (count < 1) /* check arguments */
        need_more_params(from, "RESET");
    else if ((feat = feature_desc(from, fields[0]))) { /* get descriptor */
        if (from && feat->flags & FEAT_READ)
            return send_reply(from, ERR_NOFEATURE, fields[0]);

        switch (feat->flags & FEAT_MASK) {
        case FEAT_NONE: /* None... */
            if (feat->reset && (i = (*feat->reset)(from, fields + 1, count - 1))) {
                change++; /* feature handler wants a change recorded */

                if (i > 0) /* call reset callback and parse mark return */
                    feat->flags |= FEAT_MARK;
                else /* i < 0 */
                    feat->flags &= ~FEAT_MARK;
            }
            break;

        case FEAT_INT:  /* Integer... */
        case FEAT_BOOL: /* Boolean... */
            if (feat->v_int != feat->def_int)
                change++; /* change will be made */

            feat->v_int = feat->def_int; /* set the default */
            feat->flags &= ~FEAT_MARK; /* unmark it */
            break;

        case FEAT_STR: /* string! */
            if (feat->v_str != feat->def_str) {
                change++; /* change has been made */
                if (feat->v_str)
                    MyFree(feat->v_str); /* free old value */
            }

            feat->v_str = feat->def_str; /* set it to default */
            feat->flags &= ~FEAT_MARK; /* unmark it */
            break;
        }

        if (change && feat->notify) /* call change notify function */
            (*feat->notify)();

        if (from)
            return feature_get(from, fields, count);
    }

    return 0;
}
示例#9
0
/** Handle a JOIN message from a client connection.
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct JoinBuf join;
  struct JoinBuf create;
  char *p = 0;
  char *chanlist;
  char *name;
  char *keys;

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

  if (!IsAnOper(sptr) && IsRestrictJoin(sptr)) {
    send_reply(sptr, ERR_BANNEDFROMCHAN, parv[1]);
    return 0;
  }

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

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

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

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

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

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

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

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

    do_join(cptr, sptr, &join, &create, name, key, 0);
  }

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

  return 0;
}
示例#10
0
int
ms_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Channel *chptr = 0;
  struct ModeBuf mbuf;
  struct Membership *member = 0;

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

  if (IsLocalChannel(parv[1]))
    return 0;

  if (!(chptr = FindChannel(parv[1])))
    return set_user_mode(cptr, sptr, parc, parv);

  ClrFlag(sptr, FLAG_TS8);

  if (IsServer(sptr)) {
    if (cli_uworld(sptr))
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_CHANNEL | /* Send mode to clients */
		    MODEBUF_DEST_SERVER  | /* Send mode to servers */
		    MODEBUF_DEST_HACK4));  /* Send a HACK(4) message */
    else
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_CHANNEL | /* Send mode to clients */
		    MODEBUF_DEST_SERVER  | /* Send mode to servers */
		    MODEBUF_DEST_HACK3));  /* Send a HACK(3) message */

    mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2,
	       (MODE_PARSE_SET    | /* Set the mode */
		MODE_PARSE_STRICT | /* Interpret it strictly */
		MODE_PARSE_FORCE), NULL); /* And force it to be accepted */
  } else {
    if (!IsChannelService(sptr) && (!(member = find_member_link(chptr, sptr)) || (!IsChanOp(member) && !IsHalfOp(member)))) {
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_SERVER |  /* Send mode to server */
		    MODEBUF_DEST_HACK2  |  /* Send a HACK(2) message */
		    MODEBUF_DEST_DEOP   |  /* Deop the source */
		    MODEBUF_DEST_BOUNCE)); /* And bounce the MODE */
      mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2,
		 (MODE_PARSE_STRICT |  /* Interpret it strictly */
		  MODE_PARSE_BOUNCE), member); /* And bounce the MODE */
    } else {
      modebuf_init(&mbuf, sptr, cptr, chptr,
		   (MODEBUF_DEST_CHANNEL | /* Send mode to clients */
		    MODEBUF_DEST_SERVER)); /* Send mode to servers */
      mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2,
		 (MODE_PARSE_SET    | /* Set the mode */
		  MODE_PARSE_STRICT | /* Interpret it strictly */
		  MODE_PARSE_FORCE), member); /* And force it to be accepted */
    }
  }

  return modebuf_flush(&mbuf);
}
示例#11
0
/*
 * ms_desynch - server message handler
 *
 * Writes to all +g users; for sending wall type debugging/anti-hack info.
 * Added 23 Apr 1998  --Run
 *
 * parv[0] - sender prefix
 * parv[parc-1] - message text
 */
int ms_desynch(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  if (parc >= 2)
    sendwallto_group_butone(sptr, WALL_DESYNCH, cptr, "%s", parv[parc - 1]);
  else
    need_more_params(sptr,"DESYNCH");			

  return 0;
}
示例#12
0
/*
 * m_cprivmsg - generic message handler
 *
 * parv[0] = sender prefix
 * parv[1] = nick
 * parv[2] = #channel
 * parv[3] = Private message text
 */
int m_cprivmsg(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  assert(0 != cptr);
  assert(cptr == sptr);

  if (parc < 4 || EmptyString(parv[3]))
    return need_more_params(sptr, "CPRIVMSG");

  return whisper(sptr, parv[1], parv[2], parv[3], 0);
}
示例#13
0
/*
 * m_cnotice - generic message handler
 *
 * parv[0] = sender prefix
 * parv[1] = nick
 * parv[2] = #channel
 * parv[3] = Private message text
 */
int m_cnotice(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  assert(0 != cptr);
  assert(cptr == sptr);

  if (parc < 4 || EmptyString(parv[3]))
    return need_more_params(sptr, "CNOTICE");

  return whisper(sptr, parv[1], parv[2], parv[3], 1);
}
/*
 * m_userip - generic message handler
 */
int m_userip(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  assert(0 != cptr);
  assert(cptr == sptr);

  if (parc < 2)
    return need_more_params(sptr, "USERIP");
  send_user_info(sptr, parv[1], RPL_USERIP, userip_formatter); 
  return 0;
}
/*
 * ms_kill - server message handler
 *
 * NOTE: IsServer(cptr) == true;
 *
 * parv[0]      = sender prefix
 * parv[1]      = kill victim
 * parv[parc-1] = kill path
 */
int ms_kill(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Client* victim;
  char*          path;
  char*          msg;

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

  /*
   * XXX - a server sending less than 3 params could really desync
   * things
   */
  if (parc < 3) {
    protocol_violation(sptr,"Too few arguments for KILL");
    return need_more_params(sptr, "KILL");
  }

  path = parv[parc - 1];        /* Either defined or NULL (parc >= 3) */

  if (!(msg = strchr(path, ' '))) /* Extract out the message */
    msg = "(No reason supplied)";
  else
    *(msg++) = '\0'; /* Remove first character (space) and terminate path */

  if (!(victim = findNUser(parv[1]))) {
    if (IsUser(sptr))
      sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :KILL target disconnected "
		    "before I got him :(", sptr);
    return 0;
  }

  /*
   * We *can* have crossed a NICK with this numeric... --Run
   *
   * Note the following situation:
   *  KILL SAA -->       X
   *  <-- S NICK ... SAA | <-- SAA QUIT <-- S NICK ... SAA <-- SQUIT S
   * Where the KILL reaches point X before the QUIT does.
   * This would then *still* cause an orphan because the KILL doesn't reach S
   * (because of the SQUIT), the QUIT is ignored (because of the KILL)
   * and the second NICK ... SAA causes an orphan on the server at the
   * right (which then isn't removed when the SQUIT arrives).
   * Therefore we still need to detect numeric nick collisions too.
   *
   * Bounce the kill back to the originator, if the client can't be found
   * by the next hop (short lag) the bounce won't propagate further.
   */
  if (MyConnect(victim)) {
    sendcmdto_one(&me, CMD_KILL, cptr, "%C :%s (Ghost 5 Numeric Collided)",
                  victim, path);
  }
  return do_kill(cptr, sptr, victim, cli_name(cptr), path, msg);
}
示例#16
0
/*
 * ms_smo
 *
 * parv[1] = mask
 * parv[2] = msg
 */
int ms_smo(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  char *message = parc > 2 ? parv[2] : 0;
  const char *mask = parc > 1 ? parv[1] : "o"; /* default to opers only if not specified */

  if (EmptyString(message) || !mask)
    return need_more_params(sptr, "SMO");

  sendto_allusers_butserv(cptr, sptr, mask, "%s", message);
  return 0;
}
示例#17
0
/** Handle a SILENCE command from a server.
 * See @ref m_functions for general discussion of parameters.
 *
 * \a parv[1] may be one of the following:
 * \li "*" to indicate a broadcast update (removing a SILENCE)
 * \li A client numnick that should be specifically SILENCEd.
 *
 * \a parv[2] is a comma-separated list of silence updates.
 *
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int ms_silence(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  if (IsServer(sptr))
    return protocol_violation(sptr, "Server trying to silence a user");
  if (parc < 3 || EmptyString(parv[2]))
    return need_more_params(sptr, "SILENCE");

  /* Figure out which silences can be forwarded. */
  forward_silences(sptr, parv[2], findNUser(parv[1]));
  return 0;
  (void)cptr;
}
示例#18
0
文件: m_topic.c 项目: mojadita/ircd
/** Handle a local user's attempt to get or set a channel topic.
 *
 * \a parv has the following elements:
 * \li \a parv[1] is the channel name
 * \li \a parv[\a parc - 1] is the topic (if \a parc > 2)
 *
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int m_topic(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Channel *chptr;
  char *topic = 0, *name, *p = 0;

  if (parc < 2)
    return need_more_params(sptr, "TOPIC");

  if (parc > 2)
    topic = parv[parc - 1];

  for (; (name = ircd_strtok(&p, parv[1], ",")); parv[1] = 0)
  {
    chptr = 0;
    /* Does the channel exist */
    if (!IsChannelName(name) || !(chptr = FindChannel(name)))
    {
    	send_reply(sptr,ERR_NOSUCHCHANNEL,name);
    	continue;
    }
    /* Trying to check a topic outside a secret channel */
    if ((topic || SecretChannel(chptr)) && !find_channel_member(sptr, chptr))
    {
      send_reply(sptr, ERR_NOTONCHANNEL, chptr->chname);
      continue;
    }

    /* only asking for topic */
    if (!topic)
    {
      if (chptr->topic[0] == '\0')
	send_reply(sptr, RPL_NOTOPIC, chptr->chname);
      else
      {
	send_reply(sptr, RPL_TOPIC, chptr->chname, chptr->topic);
	send_reply(sptr, RPL_TOPICWHOTIME, chptr->chname, chptr->topic_nick,
		   chptr->topic_time);
      }
    }
#if defined(DDB) || defined(SERVICES)
    else if ((chptr->mode.mode & MODE_TOPICLIMIT) &&
             !(is_chan_owner(sptr, chptr) || is_chan_op(sptr, chptr)))
#else
    else if ((chptr->mode.mode & MODE_TOPICLIMIT) && !is_chan_op(sptr, chptr))
#endif
      send_reply(sptr, ERR_CHANOPRIVSNEEDED, chptr->chname);
    else if (!client_can_send_to_channel(sptr, chptr, 1))
      send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
    else
      do_settopic(sptr,cptr,chptr,topic,0);
  }
  return 0;
}
示例#19
0
文件: m_wallops.c 项目: jast/ircu-now
/** Handle a WALLOPS message from an operator.
 *
 * \a parv has the following elements:
 * \li \a parv[\a parc - 1] is the message to send
 *
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int mo_wallops(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  char *message;

  message = parc > 1 ? parv[parc - 1] : 0;

  if (EmptyString(message))
    return need_more_params(sptr, "WALLOPS");

  sendwallto_group(sptr, WALL_WALLOPS, 0, "%s", message);
  return 0;
}
/*
 * mo_kill - oper message handler
 *
 * NOTE: IsPrivileged(sptr), IsAnOper(sptr) == true
 *       IsServer(cptr), IsServer(sptr) == false
 *
 * parv[0]      = sender prefix
 * parv[1]      = kill victim
 * parv[parc-1] = kill path
 */
int mo_kill(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Client* victim;
  char*          user;
  char           msg[TOPICLEN + 3]; /* (, ), and \0 */

  assert(0 != cptr);
  assert(0 != sptr);
  /*
   * oper connection to this server, cptr is always sptr
   */
  assert(cptr == sptr);
  assert(IsAnOper(sptr));

  if (parc < 3 || EmptyString(parv[parc - 1]))
    return need_more_params(sptr, "KILL");

  user = parv[1];
  ircd_snprintf(0, msg, sizeof(msg), "(%.*s)", TOPICLEN, parv[parc - 1]);

  if (!(victim = FindClient(user))) {
    /*
     * If the user has recently changed nick, we automaticly
     * rewrite the KILL for this new nickname--this keeps
     * servers in synch when nick change and kill collide
     */
    if (!(victim = get_history(user, (long)15)))
      return send_reply(sptr, ERR_NOSUCHNICK, user);

    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Changed KILL %s into %s", sptr,
		  user, cli_name(victim));
  }
  if (!HasPriv(sptr, MyConnect(victim) ? PRIV_LOCAL_KILL : PRIV_KILL))
    return send_reply(sptr, ERR_NOPRIVILEGES);

  if (IsServer(victim) || IsMe(victim)) {
    return send_reply(sptr, ERR_CANTKILLSERVER);
  }
  /*
   * if the user is +k, prevent a kill from local user
   */
  if (IsChannelService(victim))
    return send_reply(sptr, ERR_ISCHANSERVICE, "KILL", cli_name(victim));


  if (!MyConnect(victim) && !HasPriv(sptr, PRIV_KILL)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Nick %s isnt on your server",
		  sptr, cli_name(victim));
    return 0;
  }
  return do_kill(cptr, sptr, victim, cli_user(sptr)->host, cli_name(sptr),
		 msg);
}
示例#21
0
/*
 * m_part - generic message handler
 *
 * parv[0] = sender prefix
 * parv[1] = channel
 * parv[parc - 1] = comment
 */
int m_part(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Channel *chptr;
  struct Membership *member;
  struct JoinBuf parts;
  unsigned int flags = 0;
  char *p = 0;
  char *name;

  ClrFlag(sptr, FLAG_TS8);

  /* check number of arguments */
  if (parc < 2 || parv[1][0] == '\0')
    return need_more_params(sptr, "PART");

  /* init join/part buffer */
  joinbuf_init(&parts, sptr, cptr, JOINBUF_TYPE_PART,
	       (parc > 2 && !EmptyString(parv[parc - 1])) ? parv[parc - 1] : 0,
	       0);

  /* scan through channel list */
  for (name = ircd_strtok(&p, parv[1], ","); name;
       name = ircd_strtok(&p, 0, ",")) {

    chptr = get_channel(sptr, name, CGT_NO_CREATE); /* look up channel */

    if (!chptr) { /* complain if there isn't such a channel */
      send_reply(sptr, ERR_NOSUCHCHANNEL, name);
      continue;
    }

    if (!(member = find_member_link(chptr, sptr))) { /* complain if not on */
      send_reply(sptr, ERR_NOTONCHANNEL, chptr->chname);
      continue;
    }

    assert(!IsZombie(member)); /* Local users should never zombie */

    if (!member_can_send_to_channel(member, 0))
    {
      flags |= CHFL_BANNED;
      /* Remote clients don't want to see a comment either. */
      parts.jb_comment = 0;
    }

    if (IsDelayedJoin(member))
      flags |= CHFL_DELAYED;

    joinbuf_join(&parts, chptr, flags); /* part client from channel */
  }

  return joinbuf_flush(&parts); /* flush channel parts */
}
示例#22
0
/*
 * mo_wallusers - oper message handler
 */
int mo_wallusers(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  char *message;

  message = parc > 1 ? parv[1] : 0;

  if (EmptyString(message))
    return need_more_params(sptr, "WALLUSERS");

  sendwallto_group_butone(sptr, WALL_WALLUSERS, 0, "%s", message);
  return 0;
}
/*
 * ms_jupe - server message handler
 *
 * parv[0] = Send prefix
 *
 * From server:
 *
 * parv[1] = Target: server numeric or *
 * parv[2] = (+|-)<server name>
 * parv[3] = Expiration offset
 * parv[4] = Last modification time
 * parv[5] = Comment
 *
 */
int ms_jupe(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
    struct Client *acptr = 0;
    struct Jupe *ajupe;
    unsigned int flags = 0;
    time_t expire_off, lastmod;
    char *server = parv[2], *target = parv[1], *reason = parv[5];

    if (parc < 6)
        return need_more_params(sptr, "JUPE");

    if (!(target[0] == '*' && target[1] == '\0')) {
        if (!(acptr = FindNServer(target)))
            return 0; /* no such server */

        if (!IsMe(acptr)) { /* manually propagate, since we don't set it */
            sendcmdto_one(sptr, CMD_JUPE, acptr, "%s %s %s %s :%s", target, server,
                          parv[3], parv[4], reason);
            return 0;
        }

        flags |= JUPE_LOCAL;
    }

    if (*server == '-')
        server++;
    else if (*server == '+') {
        flags |= JUPE_ACTIVE;
        server++;
    }

    expire_off = atoi(parv[3]);
    lastmod = atoi(parv[4]);

    ajupe = jupe_find(server);

    if (ajupe) {
        if (JupeIsLocal(ajupe) && !(flags & JUPE_LOCAL)) /* global over local */
            jupe_free(ajupe);
        else if (JupeLastMod(ajupe) < lastmod) { /* new modification */
            if (flags & JUPE_ACTIVE)
                return jupe_activate(cptr, sptr, ajupe, lastmod, flags);
            else
                return jupe_deactivate(cptr, sptr, ajupe, lastmod, flags);
        } else if (JupeLastMod(ajupe) == lastmod || IsBurstOrBurstAck(cptr))
            return 0;
        else
            return jupe_resend(cptr, ajupe); /* other server desynched WRT jupes */
    }

    return jupe_add(cptr, sptr, server, reason, expire_off, lastmod, flags);
}
示例#24
0
/*
 * m_sethost - generic message handler
 *
 * mimic old lain syntax:
 *
 * (Oper) /SETHOST ident host.cc [quit-message]
 * (User) /SETHOST host.cc password
 * (Both) /SETHOST undo
 *
 * check for undo, prepend parv w. <nick> -h or +h
 */
int m_sethost(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
    char hostmask[512];
    struct Flags setflags;

    /* Back up the flags first */
    setflags = cli_flags(sptr);

    if (parc < 2)
        return need_more_params(sptr, "SETHOST");

    if (0 == ircd_strcmp("undo", parv[1])) {
        set_hostmask(sptr, sptr, NULL, NULL);
    } else {
        if (parc<3)
            return need_more_params(sptr, "SETHOST");
        if (IsAnOper(sptr)) {
            ircd_snprintf(0, hostmask, USERLEN + HOSTLEN + 1, "%s@%s", parv[1], parv[2]);
            if (!is_hostmask(hostmask)) {
                send_reply(sptr, ERR_BADHOSTMASK, hostmask);
                return 0;
            }
            if (set_hostmask(sptr, sptr, hostmask, NULL))
                FlagClr(&setflags, FLAG_SETHOST);
        } else {
            if (!is_hostmask(parv[1])) {
                send_reply(sptr, ERR_BADHOSTMASK, parv[1]);
                return 0;
            }
            if (set_hostmask(sptr, sptr, parv[1], parv[2]))
                FlagClr(&setflags, FLAG_SETHOST);
        }
    }

    send_umode_out(cptr, sptr, &setflags, 0);

    return 0;
}
示例#25
0
文件: m_opmode.c 项目: mojadita/ircd
/** Handle an OPMODE message from an operator.
 *
 * \a parv has the same elements as for m_mode().
 *
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int mo_opmode(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Channel *chptr = 0;
  struct ModeBuf mbuf;
  char *chname;
  const char *qreason;
  int force = 0;

  if (!feature_bool(FEAT_CONFIG_OPERCMDS))
    return send_reply(sptr, ERR_DISABLED, "OPMODE");

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

  chname = parv[1];
  if (*chname == '!')
  {
    chname++;
    if (!HasPriv(sptr, IsLocalChannel(chname) ? PRIV_FORCE_LOCAL_OPMODE
                                              : PRIV_FORCE_OPMODE))
      return send_reply(sptr, ERR_NOPRIVILEGES);
    force = 1;
  }

  if (!HasPriv(sptr,
	       IsLocalChannel(chname) ? PRIV_LOCAL_OPMODE : PRIV_OPMODE))
    return send_reply(sptr, ERR_NOPRIVILEGES);

  if (!IsChannelName(chname) || !(chptr = FindChannel(chname)))
    return send_reply(sptr, ERR_NOSUCHCHANNEL, chname);

  if (!force && (qreason = find_quarantine(chptr->chname)))
    return send_reply(sptr, ERR_QUARANTINED, chptr->chname, qreason);

  modebuf_init(&mbuf, sptr, cptr, chptr,
	       (MODEBUF_DEST_CHANNEL | /* Send MODE to channel */
		MODEBUF_DEST_SERVER  | /* And to server */
		MODEBUF_DEST_OPMODE  | /* Use OPMODE */
		MODEBUF_DEST_HACK4   | /* Generate a HACK(4) notice */
		MODEBUF_DEST_LOG));    /* Log the mode changes to OPATH */

  mode_parse(&mbuf, cptr, sptr, chptr, parc - 2, parv + 2,
	     (MODE_PARSE_SET |    /* set the modes on the channel */
	      MODE_PARSE_FORCE),  /* And force them to be accepted */
	      NULL);

  modebuf_flush(&mbuf); /* flush the modes */

  return 0;
}
示例#26
0
int ms_set(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
    struct Client *acptr;
    if (parc < 4)
        return need_more_params(sptr, "SET");
    if (!(acptr = FindNServer(parv[1])))
        return 0;
    if (!IsMe(acptr)) {
        sendcmdto_serv_butone(sptr, CMD_SET, cptr, "%C %s :%s",
                              acptr, parv[2], parv[3]);
        return 0;
    }
    return feature_set(sptr, (const char* const*)parv + 2, parc - 2);
}
示例#27
0
/** Gets the value of a specific feature and reports it to the user.
 * @param[in] from Client trying to get the feature.
 * @param[in] fields Parameters to set, starting with feature name.
 * @param[in] count Number of fields in \a fields.
 * @return Zero (or, theoretically, CPTR_KILLED).
 */
int
feature_get(struct Client* from, const char* const* fields, int count)
{
  struct FeatureDesc *feat;

  assert(0 != from);

  if (count < 1) /* check parameters */
    need_more_params(from, "GET");
  else if ((feat = feature_desc(from, fields[0]))) {
    if ((feat->flags & FEAT_NODISP) ||
	(feat->flags & FEAT_MYOPER && !MyOper(from)) ||
	(feat->flags & FEAT_OPER && !IsAnOper(from))) /* check privs */
      return send_reply(from, ERR_NOPRIVILEGES);

    switch (feat_type(feat)) {
    case FEAT_NONE: /* none, call the callback... */
      if (feat->get) /* if there's a callback, use it */
	(*feat->get)(from, fields + 1, count - 1);
      break;

    case FEAT_INT: /* integer, report integer value */
      send_reply(from, SND_EXPLICIT | RPL_FEATURE,
		 ":Integer value of %s: %d", feat->type, feat->v_int);
      break;

    case FEAT_UINT: /* unsigned integer, report its value */
      send_reply(from, SND_EXPLICIT | RPL_FEATURE,
                 ":Unsigned value of %s: %u", feat->type, feat->v_int);
      break;

    case FEAT_BOOL: /* boolean, report boolean value */
      send_reply(from, SND_EXPLICIT | RPL_FEATURE,
		 ":Boolean value of %s: %s", feat->type,
		 feat->v_int ? "TRUE" : "FALSE");
      break;

    case FEAT_STR: /* string, report string value */
      if (feat->v_str) /* deal with null case */
	send_reply(from, SND_EXPLICIT | RPL_FEATURE,
		   ":String value of %s: %s", feat->type, feat->v_str);
      else
	send_reply(from, SND_EXPLICIT | RPL_FEATURE,
		   ":String value for %s not set", feat->type);
      break;
    }
  }

  return 0;
}
示例#28
0
文件: random.c 项目: mojadita/ircd
/** Seed the PRNG with a string.
 * @param[in] from Client setting the seed (may be NULL).
 * @param[in] fields Input arguments (fields[0] is used).
 * @param[in] count Number of input arguments.
 * @return Non-zero on success, zero on error.
 */
int
random_seed_set(struct Client* from, const char* const* fields, int count)
{
  if (count < 1) {
    if (from) /* send an error */
      return need_more_params(from, "SET");
    else {
      log_write(LS_CONFIG, L_ERROR, 0, "Not enough fields in F line");
      return 0;
    }
  }

  random_add_entropy(fields[0], strlen(fields[0]));
  return 1;
}
示例#29
0
/*
 * ms_wallusers - server message handler
 */
int ms_wallusers(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  char *message;

  message = parc > 1 ? parv[1] : 0;

  /*
   * XXX - PROTOCOL ERROR (shouldn't happen)
   */
  if (EmptyString(message))
    return need_more_params(sptr, "WALLUSERS");

  sendwallto_group_butone(sptr, WALL_WALLUSERS, cptr, "%s",
			message);
  return 0;
}
示例#30
0
文件: m_pass.c 项目: mojadita/ircd
/** Handle a PASS message from an unregistered connection.
 *
 * \a parv[1..\a parc-1] is a possibly broken-up password.  Since some
 * clients do not prefix the password with ':', this functions stitches
 * the elements back together before using it.
 *
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int mr_pass(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  char password[BUFSIZE];
  int arg, len;

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

  /* Some clients (brokenly) send "PASS x y" rather than "PASS :x y"
   * when the user enters "x y" as the password.  Unsplit arguments to
   * work around this.
   */
  for (arg = 1, len = 0; arg < parc; ++arg)
  {
    ircd_strncpy(password + len, parv[arg], sizeof(password) - len);
    len += strlen(parv[arg]);
    password[len++] = ' ';
  }
  if (len > 0)
    --len;
  password[len] = '\0';

  if (EmptyString(password))
    return need_more_params(cptr, "PASS");

#if defined(DDB)
  if (IsUserPort(cptr))
  {
    /*
     *   PASS :server_pass[:ddb_pass]
     *   PASS :ddb_pass
     */
    char *ddb_pwd;

    ddb_pwd = strchr(password, ':');
    if (ddb_pwd)
      *ddb_pwd++ = '\0';
    else
      ddb_pwd = password;

    ircd_strncpy(cli_ddb_passwd(cptr), ddb_pwd, DDBPWDLEN);
  }
#endif
  ircd_strncpy(cli_passwd(cptr), password, PASSWDLEN);
  return cli_auth(cptr) ? auth_set_password(cli_auth(cptr), password) : 0;
}