예제 #1
0
파일: parse.c 프로젝트: thors/ircd-ratbox
/*
 * handle_command
 *
 * inputs	- pointer to message block
 *		- pointer to client
 *		- pointer to client message is from
 *		- count of number of args
 *		- pointer to argv[] array
 * output	- -1 if error from server
 * side effects	-
 */
static int
handle_command(struct Message *mptr, struct Client *client_p, struct Client *from, int i, const char **hpara)
{
	struct MessageEntry ehandler;
	MessageHandler handler = 0;
	static time_t last_warning;

	if(IsAnyDead(client_p))
		return -1;

	if(IsServer(client_p))
		mptr->rcount++;

	mptr->count++;

	ehandler = mptr->handlers[from->handler];
	handler = ehandler.handler;

	/* check right amount of params is passed... --is */
	if(i < ehandler.min_para || (ehandler.min_para && EmptyString(hpara[ehandler.min_para - 1])))
	{
		if(!IsServer(client_p))
		{
			sendto_one_numeric(client_p, s_RPL(ERR_NEEDMOREPARAMS), mptr->cmd);
			if(MyClient(client_p))
				return (1);
			else
				return (-1);
		}

		sendto_realops_flags(UMODE_ALL, L_ALL,
				     "Dropping server %s due to (invalid) command '%s'"
				     " with only %d arguments (expecting %d).",
				     client_p->name, mptr->cmd, i, ehandler.min_para);
		ilog(L_SERVER, "Insufficient parameters (%d) for command '%s' from %s.", i, mptr->cmd, client_p->name);

		exit_client(client_p, client_p, client_p, "Not enough arguments to server command.");
		return (-1);
	}

	if(handler == NULL) /* module hasn't set a handler, just use m_ignore */
		handler = m_ignore; 

	(*handler) (client_p, from, i, hpara);
	if(!IsAnyDead(client_p) && IsCork(client_p) && !IsCapable(client_p, CAP_ZIP))
	{
		if(last_warning + 300 <= rb_current_time())
		{
			sendto_realops_flags(UMODE_DEBUG, L_ALL,
					     "Bug: client %s was left corked after command %s",
					     client_p->name, mptr->cmd);
			last_warning = rb_current_time();
		}
		client_p->localClient->cork_count = 0;
		send_pop_queue(client_p);
	}
	return (1);
}
예제 #2
0
파일: parse.c 프로젝트: kamilion/charybdis
/*
 * handle_command
 *
 * inputs	- pointer to message block
 * 		- pointer to message buffer
 *		- pointer to client
 *		- pointer to client message is from
 * output	- -1 if error from server
 * side effects	-
 */
static int
handle_command(struct Message *mptr, struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *from)
{
	struct MessageEntry ehandler;
	MessageHandler handler = 0;
	char squitreason[80];

	if(IsAnyDead(client_p))
		return -1;

	if(IsServer(client_p))
		mptr->rcount++;

	mptr->count++;

	ehandler = mptr->handlers[from->handler];
	handler = ehandler.handler;

	/* check right amount of params is passed... --is */
	if(msgbuf_p->n_para < ehandler.min_para ||
	   (ehandler.min_para && EmptyString(msgbuf_p->para[ehandler.min_para - 1])))
	{
		if(!IsServer(client_p))
		{
			sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
				   me.name,
				   EmptyString(client_p->name) ? "*" : client_p->name,
				   mptr->cmd);
			if(MyClient(client_p))
				return (1);
			else
				return (-1);
		}

		sendto_realops_snomask(SNO_GENERAL, L_ALL,
				     "Dropping server %s due to (invalid) command '%s'"
				     " with only %zu arguments (expecting %zu).",
				     client_p->name, mptr->cmd, msgbuf_p->n_para, ehandler.min_para);
		ilog(L_SERVER,
		     "Insufficient parameters (%zu < %zu) for command '%s' from %s.",
		     msgbuf_p->n_para, ehandler.min_para, mptr->cmd, client_p->name);
		snprintf(squitreason, sizeof squitreason,
				"Insufficient parameters (%zu < %zu) for command '%s'",
				msgbuf_p->n_para, ehandler.min_para, mptr->cmd);
		exit_client(client_p, client_p, client_p, squitreason);
		return (-1);
	}

	(*handler) (msgbuf_p, client_p, from, msgbuf_p->n_para, msgbuf_p->para);
	return (1);
}
예제 #3
0
파일: parse.c 프로젝트: kamilion/charybdis
/* parse()
 *
 * given a raw buffer, parses it and generates parv and parc
 */
void
parse(struct Client *client_p, char *pbuffer, char *bufend)
{
	struct Client *from = client_p;
	char *end;
	int res;
	int numeric = 0;
	struct Message *mptr;
	struct MsgBuf msgbuf;

	s_assert(MyConnect(client_p));
	s_assert(client_p->localClient->F != NULL);
	if(IsAnyDead(client_p))
		return;

	end = bufend - 1;

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

	res = msgbuf_parse(&msgbuf, pbuffer);
	if (res)
	{
		ServerStats.is_empt++;
		return;
	}

	if (msgbuf.origin != NULL && IsServer(client_p))
	{
		from = find_client(msgbuf.origin);

		/* didnt find any matching client, issue a kill */
		if(from == NULL)
		{
			ServerStats.is_unpf++;
			remove_unknown(client_p, msgbuf.origin, pbuffer);
			return;
		}

		/* fake direction, hmm. */
		if(from->from != client_p)
		{
			ServerStats.is_wrdi++;
			cancel_clients(client_p, from);
			return;
		}
	}

	if(IsDigit(*msgbuf.cmd) && IsDigit(*(msgbuf.cmd + 1)) && IsDigit(*(msgbuf.cmd + 2)))
	{
		mptr = NULL;
		numeric = atoi(msgbuf.cmd);
		ServerStats.is_num++;
	}
	else
	{
		mptr = rb_dictionary_retrieve(cmd_dict, msgbuf.cmd);

		/* no command or its encap only, error */
		if(!mptr || !mptr->cmd)
		{
			if(IsPerson(from))
			{
				sendto_one(from, form_str(ERR_UNKNOWNCOMMAND),
					   me.name, from->name, msgbuf.cmd);
			}
			ServerStats.is_unco++;
			return;
		}

		mptr->bytes += msgbuf.parselen;
	}

	if(mptr == NULL)
	{
		do_numeric(numeric, client_p, from, msgbuf.n_para, msgbuf.para);
		return;
	}

	if(handle_command(mptr, &msgbuf, client_p, from) < -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((p + 8) > end)
			{
				for (; p <= end; p++)
				{
					ilog(L_MAIN, "%02x |%c", p[0], p[0]);
				}
			}
			else
				ilog(L_MAIN,
				     "%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]);
		}
	}

}
예제 #4
0
/*
 * handle_command
 *
 * inputs	- pointer to message block
 *		- pointer to client
 *		- pointer to client message is from
 *		- count of number of args
 *		- pointer to argv[] array
 * output	- -1 if error from server
 * side effects	-
 */
static int
handle_command(struct Message *mptr, struct Client *client_p,
	       struct Client *from, int i, const char** hpara)
{
	struct MessageEntry ehandler;
	MessageHandler handler = 0;

	if(IsAnyDead(client_p))
		return -1;

	if(IsServer(client_p))
		mptr->rcount++;

	mptr->count++;

	/* New patch to avoid server flooding from unregistered connects
	   - Pie-Man 07/27/2000 */

	if(!IsRegistered(client_p))
	{
		/* if its from a possible server connection
		 * ignore it.. more than likely its a header thats sneaked through
		 */

		if(IsAnyServer(client_p) && !(mptr->flags & MFLG_UNREG))
			return (1);
	}

	ehandler = mptr->handlers[from->handler];
	handler = ehandler.handler;

	/* check right amount of params is passed... --is */
	if(i < ehandler.min_para || 
	   (ehandler.min_para && EmptyString(hpara[ehandler.min_para - 1])))
	{
		if(!IsServer(client_p))
		{
			sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
				   me.name, 
				   EmptyString(client_p->name) ? "*" : client_p->name, 
				   mptr->cmd);
			if(MyClient(client_p))
				return (1);
			else
				return (-1);
		}

		sendto_realops_flags(UMODE_ALL, L_ALL,
				     "Dropping server %s due to (invalid) command '%s'"
				     " with only %d arguments (expecting %d).",
				     client_p->name, mptr->cmd, i, ehandler.min_para);
		ilog(L_SERVER,
		     "Insufficient parameters (%d) for command '%s' from %s.",
		     i, mptr->cmd, client_p->name);

		exit_client(client_p, client_p, client_p,
			    "Not enough arguments to server command.");
		return (-1);
	}

	(*handler) (client_p, from, i, hpara);
	return (1);
}
예제 #5
0
/* parse()
 *
 * given a raw buffer, parses it and generates parv, parc and sender
 */
void
parse(struct Client *client_p, char *pbuffer, char *bufend)
{
	struct Client *from = client_p;
	char *ch;
	char *s;
	char *end;
	int i = 1;
	char *numeric = 0;
	struct Message *mptr;

	s_assert(MyConnect(client_p));
	s_assert(client_p->localClient->fd >= 0);
	if(IsAnyDead(client_p))
		return;

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

	para[0] = from->name;

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

		/* point sender to the sender param */
		sender = ch;

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

		if(*sender && IsServer(client_p))
		{
			from = find_any_client(sender);

			/* didnt find any matching client, issue a kill */
			if(from == NULL)
			{
				ServerStats->is_unpf++;
				remove_unknown(client_p, sender, pbuffer);
				return;
			}

			para[0] = from->name;

			/* fake direction, hmm. */
			if(from->from != client_p)
			{
				ServerStats->is_wrdi++;
				cancel_clients(client_p, from, pbuffer);
				return;
			}
		}
		while (*ch == ' ')
			ch++;
	}

	if(*ch == '\0')
	{
		ServerStats->is_empt++;
		return;
	}

	/* at this point there must be some sort of command parameter */

	/*
	 * 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 = NULL;
		numeric = ch;
		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);

		/* no command or its encap only, error */
		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, form_str(ERR_UNKNOWNCOMMAND),
						   me.name, from->name, ch);
			}
			ServerStats->is_unco++;
			return;
		}

		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';

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

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

	if(handle_command(mptr, client_p, from, i, /* XXX discards const!!! */ (const char **)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_MAIN, "%02x |%c", p[0], p[0]);
				}
			}
			else
				ilog(L_MAIN,
				     "%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]);
		}
	}

}