#include "channel.h"
#include "class.h"
#include "client.h"
+#include "gline.h"
#include "hash.h"
#include "ircd.h"
#include "ircd_alloc.h"
#include "version.h"
#include "whowas.h"
+#include "handlers.h" /* m_motd and m_lusers */
+
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
}
else if (!(acptr = find_match_server(parv[server])))
{
- sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
- me.name, parv[0], parv[server]);
+ send_reply(sptr, ERR_NOSUCHSERVER, parv[server]);
return (HUNTED_NOSUCH);
}
}
if (MustBeOper && !IsPrivileged(sptr))
{
- sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name);
+ send_reply(sptr, ERR_NOPRIVILEGES);
return HUNTED_NOSUCH;
}
parv[server] = y;
assert(!IsServer(sptr));
- sendto_one(acptr, command, NumNick(sptr), parv[1], parv[2], parv[3], parv[4],
+ /* XXX sendto_one used with explicit command; must be very careful */
+ sendto_one(acptr, command, NumNick(sptr), parv[1], parv[2], parv[3], parv[4], /* XXX hunt_server */
parv[5], parv[6], parv[7], parv[8]);
return (HUNTED_PASS);
}
+int hunt_server_cmd(struct Client *from, const char *cmd, const char *tok,
+ struct Client *one, int MustBeOper, const char *pattern,
+ int server, int parc, char *parv[])
+{
+ struct Client *acptr;
+ char *to;
+
+ /* Assume it's me, if no server or an unregistered client */
+ if (parc <= server || EmptyString((to = parv[server])) || IsUnknown(from))
+ return (HUNTED_ISME);
+
+ /* Make sure it's a server */
+ if (MyUser(from)) {
+ /* Make sure it's a server */
+ if (!strchr(to, '*')) {
+ if (0 == (acptr = FindClient(to)))
+ return HUNTED_NOSUCH;
+
+ if (acptr->user)
+ acptr = acptr->user->server;
+ } else if (!(acptr = find_match_server(to))) {
+ send_reply(from, ERR_NOSUCHSERVER, to);
+ return (HUNTED_NOSUCH);
+ }
+ } else if (!(acptr = FindNServer(to)))
+ return (HUNTED_NOSUCH); /* Server broke off in the meantime */
+
+ if (IsMe(acptr))
+ return (HUNTED_ISME);
+
+ if (MustBeOper && !IsPrivileged(from)) {
+ send_reply(from, ERR_NOPRIVILEGES);
+ return HUNTED_NOSUCH;
+ }
+
+ assert(!IsServer(from));
+
+ parv[server] = (char *) acptr; /* HACK! HACK! HACK! ARGH! */
+
+ sendcmdto_one(from, cmd, tok, acptr, pattern, parv[1], parv[2], parv[3],
+ parv[4], parv[5], parv[6], parv[7], parv[8]);
+
+ return (HUNTED_PASS);
+}
+
/*
* 'do_nick_name' ensures that the given parameter (nick) is really a proper
* string for a nickname (note, the 'nick' may be modified in the process...)
* nick from local user or kill him/her...
*/
int register_user(struct Client *cptr, struct Client *sptr,
- const char *nick, char *username)
+ const char *nick, char *username, struct Gline *agline)
{
struct ConfItem* aconf;
char* parv[3];
case ACR_OK:
break;
case ACR_NO_AUTHORIZATION:
- sendto_op_mask(SNO_UNAUTH, "Unauthorized connection from %s.",
- get_client_name(sptr, HIDE_IP));
+ sendto_opmask_butone(0, SNO_UNAUTH, "Unauthorized connection from %s.",
+ get_client_name(sptr, HIDE_IP));
++ServerStats->is_ref;
return exit_client(cptr, sptr, &me,
- "No Authorization - use another server");
+ "No Authorization - use another server");
case ACR_TOO_MANY_IN_CLASS:
if (CurrentTime - last_too_many1 >= (time_t) 60)
{
last_too_many1 = CurrentTime;
- sendto_op_mask(SNO_TOOMANY, "Too many connections in class for %s.",
- get_client_name(sptr, HIDE_IP));
+ sendto_opmask_butone(0, SNO_TOOMANY, "Too many connections in "
+ "class for %s.",
+ get_client_name(sptr, HIDE_IP));
}
++ServerStats->is_ref;
- IPcheck_connect_fail(sptr->ip);
return exit_client(cptr, sptr, &me,
- "Sorry, your connection class is full - try again later or try another server");
+ "Sorry, your connection class is full - try "
+ "again later or try another server");
case ACR_TOO_MANY_FROM_IP:
if (CurrentTime - last_too_many2 >= (time_t) 60)
{
last_too_many2 = CurrentTime;
- sendto_op_mask(SNO_TOOMANY, "Too many connections from same IP for %s.",
- get_client_name(sptr, HIDE_IP));
+ sendto_opmask_butone(0, SNO_TOOMANY, "Too many connections from "
+ "same IP for %s.",
+ get_client_name(sptr, HIDE_IP));
}
++ServerStats->is_ref;
return exit_client(cptr, sptr, &me,
- "Too many connections from your host");
+ "Too many connections from your host");
case ACR_ALREADY_AUTHORIZED:
/* Can this ever happen? */
case ACR_BAD_SOCKET:
++ServerStats->is_ref;
- IPcheck_connect_fail(sptr->ip);
return exit_client(cptr, sptr, &me, "Unknown error -- Try again");
}
ircd_strncpy(user->host, sptr->sockhost, HOSTLEN);
if (!EmptyString(aconf->passwd)
&& !(IsDigit(*aconf->passwd) && !aconf->passwd[1])
-#ifdef USEONE
- && strcmp("ONE", aconf->passwd)
-#endif
&& strcmp(sptr->passwd, aconf->passwd))
{
ServerStats->is_ref++;
- IPcheck_connect_fail(sptr->ip);
- sendto_one(sptr, err_str(ERR_PASSWDMISMATCH), me.name, parv[0]);
+ send_reply(sptr, ERR_PASSWDMISMATCH);
return exit_client(cptr, sptr, &me, "Bad Password");
}
memset(sptr->passwd, 0, sizeof(sptr->passwd));
*/
if (find_kill(sptr)) {
ServerStats->is_ref++;
- IPcheck_connect_fail(sptr->ip);
return exit_client(cptr, sptr, &me, "K-lined");
}
/*
strcmp(sptr->username, username) != 0))
{
ServerStats->is_ref++;
- sendto_one(cptr, ":%s %d %s :Your username is invalid.",
- me.name, ERR_INVALIDUSERNAME, cptr->name);
- sendto_one(cptr,
- ":%s %d %s :Connect with your real username, in lowercase.",
- me.name, ERR_INVALIDUSERNAME, cptr->name);
- sendto_one(cptr, ":%s %d %s :If your mail address were foo@bar.com, "
- "your username would be foo.",
- me.name, ERR_INVALIDUSERNAME, cptr->name);
+
+ send_reply(cptr, SND_EXPLICIT | ERR_INVALIDUSERNAME,
+ ":Your username is invalid.");
+ send_reply(cptr, SND_EXPLICIT | ERR_INVALIDUSERNAME,
+ ":Connect with your real username, in lowercase.");
+ send_reply(cptr, SND_EXPLICIT | ERR_INVALIDUSERNAME,
+ ":If your mail address were foo@bar.com, your username "
+ "would be foo.");
return exit_client(cptr, sptr, &me, "USER: Bad username");
}
Count_unknownbecomesclient(sptr, UserStats);
}
SetUser(sptr);
+ /* a gline wasn't passed in, so find a matching global one that isn't
+ * a Uworld-set one, and propagate it if there is such an animal.
+ */
+ if (!agline &&
+ (agline = gline_lookup(sptr, GLINE_GLOBAL | GLINE_LASTMOD)) &&
+ !IsBurstOrBurstAck(cptr))
+ gline_resend(cptr, agline);
+
if (IsInvisible(sptr))
++UserStats.inv_clients;
if (IsOper(sptr))
sptr->handler = CLIENT_HANDLER;
release_dns_reply(sptr);
- sendto_one(sptr, rpl_str(RPL_WELCOME), me.name, nick, nick);
+ send_reply(sptr, RPL_WELCOME, nick);
/*
* This is a duplicate of the NOTICE but see below...
*/
- sendto_one(sptr, rpl_str(RPL_YOURHOST), me.name, nick,
- me.name, version);
- sendto_one(sptr, rpl_str(RPL_CREATED), me.name, nick, creation);
- sendto_one(sptr, rpl_str(RPL_MYINFO), me.name, parv[0], me.name, version);
+ send_reply(sptr, RPL_YOURHOST, me.name, version);
+ send_reply(sptr, RPL_CREATED, creation);
+ send_reply(sptr, RPL_MYINFO, me.name, version);
sprintf_irc(featurebuf,FEATURES,FEATURESVALUES);
- sendto_one(sptr, rpl_str(RPL_ISUPPORT), me.name, nick, featurebuf);
+ send_reply(sptr, RPL_ISUPPORT, featurebuf);
m_lusers(sptr, sptr, 1, parv);
update_load();
#ifdef NODEFAULTMOTD
nextping = CurrentTime;
if (sptr->snomask & SNO_NOISY)
set_snomask(sptr, sptr->snomask & SNO_NOISY, SNO_ADD);
-#ifdef ALLOW_SNO_CONNEXIT
-#ifdef SNO_CONNEXIT_IP
- sprintf_irc(sendbuf,
- ":%s NOTICE * :*** Notice -- Client connecting: %s (%s@%s) [%s] {%d}",
- me.name, nick, user->username, user->host, cptr->sock_ip,
- get_client_class(sptr));
- sendbufto_op_mask(SNO_CONNEXIT);
-#else /* SNO_CONNEXIT_IP */
- sprintf_irc(sendbuf,
- ":%s NOTICE * :*** Notice -- Client connecting: %s (%s@%s)",
- me.name, nick, user->username, user->host);
- sendbufto_op_mask(SNO_CONNEXIT);
-#endif /* SNO_CONNEXIT_IP */
-#endif /* ALLOW_SNO_CONNEXIT */
- IPcheck_connect_succeeded(sptr);
+ ip_registry_connect_succeeded(sptr);
}
else
/* if (IsServer(cptr)) */
acptr = user->server;
if (acptr->from != sptr->from)
{
- sendto_one(cptr, "%s " TOK_KILL " %s%s :%s (%s != %s[%s])",
- NumServ(&me), NumNick(sptr), me.name, user->server->name,
- acptr->from->name, acptr->from->sockhost);
+ sendcmdto_one(&me, CMD_KILL, cptr, "%C :%s (%s != %s[%s])",
+ sptr, me.name, user->server->name, acptr->from->name,
+ acptr->from->sockhost);
sptr->flags |= FLAGS_KILLED;
return exit_client(cptr, sptr, &me, "NICK server wrong direction");
}
if (IsBurst(acptr) || Protocol(acptr) < 10)
break;
}
- if (IPcheck_remote_connect(sptr, user->host, (acptr != &me)) == -1)
- /*
- * We ran out of bits to count this
- */
- return exit_client(cptr, sptr, &me, "More than 255 connections from this address");
}
-
tmpstr = umode_str(sptr);
- sendto_serv_butone(cptr, *tmpstr ?
- "%s " TOK_NICK " %s %d %d %s %s +%s %s %s%s :%s" :
- "%s " TOK_NICK " %s %d %d %s %s %s%s %s%s :%s",
- NumServ(user->server), nick, sptr->hopcount + 1, sptr->lastnick,
- user->username, user->host, tmpstr,
- inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6),
- NumNick(sptr), sptr->info);
-
+ if (agline)
+ sendcmdto_serv_butone(user->server, CMD_NICK, cptr,
+ "%s %d %Tu %s %s %s%s%s%%%Tu:%s@%s %s %s%s :%s",
+ nick, sptr->hopcount + 1, sptr->lastnick,
+ user->username, user->host,
+ *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "",
+ GlineLastMod(agline), GlineUser(agline),
+ GlineHost(agline),
+ inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6),
+ NumNick(sptr), sptr->info);
+ else
+ sendcmdto_serv_butone(user->server, CMD_NICK, cptr,
+ "%s %d %Tu %s %s %s%s%s%s %s%s :%s",
+ nick, sptr->hopcount + 1, sptr->lastnick,
+ user->username, user->host,
+ *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "",
+ inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6),
+ NumNick(sptr), sptr->info);
+
/* Send umode to client */
if (MyUser(sptr))
{
send_umode(cptr, sptr, 0, ALL_UMODES);
if (sptr->snomask != SNO_DEFAULT && (sptr->flags & FLAGS_SERVNOTICE))
- sendto_one(sptr, rpl_str(RPL_SNOMASK), me.name, sptr->name,
- sptr->snomask, sptr->snomask);
+ send_reply(sptr, RPL_SNOMASK, sptr->snomask, sptr->snomask);
}
return 0;
if (IsServer(sptr)) {
int i;
const char* p;
+ char *t;
+ struct Gline *agline = 0;
/*
* A server introducing a new client, change source
ircd_strncpy(new_client->username, parv[4], USERLEN);
ircd_strncpy(new_client->user->host, parv[5], HOSTLEN);
ircd_strncpy(new_client->info, parv[parc - 1], REALLEN);
- return register_user(cptr, new_client, new_client->name, parv[4]);
+
+ /* Deal with GLINE parameters... */
+ if (*parv[parc - 4] == '%' && (t = strchr(parv[parc - 4] + 1, ':'))) {
+ time_t lastmod;
+
+ *(t++) = '\0';
+ lastmod = atoi(parv[parc - 4] + 1);
+
+ if (lastmod &&
+ (agline = gline_find(t, GLINE_EXACT | GLINE_GLOBAL | GLINE_LASTMOD))
+ && GlineLastMod(agline) > lastmod && !IsBurstOrBurstAck(cptr))
+ gline_resend(cptr, agline);
+ }
+ if (!ip_registry_remote_connect(new_client)) {
+ sendcmdto_one(&me, CMD_KILL, new_client, "%C :%s (Too many connections from your host -- Ghost)",
+ new_client,me.name);
+ return exit_client(cptr,new_client,&me,"Too many connections from your host -- throttled");
+ }
+ sendto_ops("Registering new remote client");
+ return register_user(cptr, new_client, new_client->name, parv[4], agline);
}
else if (sptr->name[0]) {
/*
if (MyUser(sptr)) {
const char* channel_name;
if ((channel_name = find_no_nickchange_channel(sptr))) {
- sendto_one(cptr, err_str(ERR_BANNICKCHANGE), me.name, parv[0],
- channel_name);
- return 0;
+ return send_reply(cptr, ERR_BANNICKCHANGE, channel_name);
}
/*
* Refuse nick change if the last nick change was less
*/
if (CurrentTime < cptr->nextnick) {
cptr->nextnick += 2;
- sendto_one(cptr, err_str(ERR_NICKTOOFAST),
- me.name, parv[0], parv[1], cptr->nextnick - CurrentTime);
+ send_reply(cptr, ERR_NICKTOOFAST, parv[1],
+ cptr->nextnick - CurrentTime);
/* Send error message */
- sendto_prefix_one(cptr, cptr, ":%s NICK %s", parv[0], parv[0]);
+ sendcmdto_one(cptr, CMD_NICK, cptr, "%s", cptr->name);
/* bounce NICK to user */
return 0; /* ignore nick change! */
}
* on that channel. Propagate notice to other servers.
*/
if (IsUser(sptr)) {
- sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick);
+ sendcmdto_common_channels(sptr, CMD_NICK, ":%s", nick);
add_history(sptr, 1);
- sendto_serv_butone(cptr,
- "%s%s " TOK_NICK " %s " TIME_T_FMT, NumNick(sptr), nick, sptr->lastnick);
+ sendcmdto_serv_butone(sptr, CMD_NICK, cptr, "%s %Tu", nick,
+ sptr->lastnick);
}
else
- sendto_one(sptr, ":%s NICK :%s", parv[0], nick);
+ sendcmdto_one(sptr, CMD_NICK, sptr, ":%s", nick);
if (sptr->name[0])
hRemClient(sptr);
do {
sptr->cookie = (ircrandom() & 0x7fffffff);
} while (!sptr->cookie);
- sendto_one(cptr, "PING :%u", sptr->cookie);
+ sendrawto_one(cptr, MSG_PING " :%u", sptr->cookie);
}
else if (*sptr->user->host && sptr->cookie == COOKIE_VERIFIED) {
/*
* for it - must test this and exit m_nick too !
*/
sptr->lastnick = TStime(); /* Always local client */
- if (register_user(cptr, sptr, nick, sptr->user->username) == CPTR_KILLED)
+ if (register_user(cptr, sptr, nick, sptr->user->username, 0) == CPTR_KILLED)
return CPTR_KILLED;
}
}
* No server flooding
*/
sptr->nexttarget += 2;
- sendto_one(sptr, err_str(ERR_TARGETTOOFAST),
- me.name, sptr->name, name, sptr->nexttarget - CurrentTime);
+ send_reply(sptr, ERR_TARGETTOOFAST, name,
+ sptr->nexttarget - CurrentTime);
}
return 1;
}
else {
#ifdef GODMODE
- sendto_one(sptr, ":%s NOTICE %s :New target: %s; ft " TIME_T_FMT,
+ /* XXX Let's get rid of GODMODE */
+ sendto_one(sptr, ":%s NOTICE %s :New target: %s; ft " TIME_T_FMT, /* XXX Possibly DEAD */
me.name, sptr->name, name, (CurrentTime - sptr->nexttarget) / TARGET_DELAY);
#endif
sptr->nexttarget += TARGET_DELAY;
assert(MyUser(source));
if (!(dest = FindUser(nick))) {
- sendto_one(source, err_str(ERR_NOSUCHNICK), me.name, source->name, nick);
- return 0;
+ return send_reply(source, ERR_NOSUCHNICK, nick);
}
if (!(chptr = FindChannel(channel))) {
- sendto_one(source, err_str(ERR_NOSUCHCHANNEL), me.name, source->name, channel);
- return 0;
+ return send_reply(source, ERR_NOSUCHCHANNEL, channel);
}
/*
* compare both users channel lists, instead of the channels user list
break;
}
if (0 == membership) {
- sendto_one(source, err_str(ERR_NOTONCHANNEL), me.name, source->name, chptr->chname);
- return 0;
+ return send_reply(source, ERR_NOTONCHANNEL, chptr->chname);
}
if (!IsVoicedOrOpped(membership)) {
- sendto_one(source, err_str(ERR_VOICENEEDED), me.name, source->name, chptr->chname);
- return 0;
+ return send_reply(source, ERR_VOICENEEDED, chptr->chname);
}
/*
* lookup channel in destination
break;
}
if (0 == membership || IsZombie(membership)) {
- sendto_one(source, err_str(ERR_USERNOTINCHANNEL), me.name,
- source->name, dest->name, chptr->chname);
- return 0;
+ return send_reply(source, ERR_USERNOTINCHANNEL, dest->name, chptr->chname);
}
if (is_silenced(source, dest))
return 0;
if (dest->user->away)
- sendto_one(source, rpl_str(RPL_AWAY), me.name, source->name,
- dest->name, dest->user->away);
- if (MyUser(dest))
- sendto_prefix_one(dest, source, ":%s %s %s :%s",
- source->name, is_notice ? MSG_NOTICE : MSG_PRIVATE,
- dest->name, text);
+ send_reply(source, RPL_AWAY, dest->name, dest->user->away);
+ if (is_notice)
+ sendcmdto_one(source, CMD_NOTICE, dest, "%C :%s", dest, text);
else
- sendto_one(dest, "%s%s %s %s%s :%s",
- NumNick(source), is_notice ? TOK_NOTICE : TOK_PRIVATE,
- NumNick(dest), text);
+ sendcmdto_one(source, CMD_PRIVATE, dest, "%C :%s", dest, text);
return 0;
}
for (i = HighestFd; i >= 0; i--) {
if ((acptr = LocalClientArray[i]) && IsServer(acptr) &&
(acptr != cptr) && (acptr != sptr) && *umodeBuf)
- sendto_one(acptr, "%s%s " TOK_MODE " %s :%s", NumNick(sptr), sptr->name, umodeBuf);
+ sendcmdto_one(sptr, CMD_MODE, acptr, "%s :%s", sptr->name, umodeBuf);
}
if (cptr && MyUser(cptr))
send_umode(cptr, sptr, old, ALL_UMODES);
*sbuf++ = ' ';
sbuf = (*fmt)(acptr, sbuf);
}
- else
- send_error_to_client(sptr, ERR_NOSUCHNICK, name);
if (5 == ++arg_count)
break;
}
if (!(acptr = FindUser(parv[1])))
{
if (MyConnect(sptr))
- sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[1]);
+ send_reply(sptr, ERR_NOSUCHCHANNEL, parv[1]);
return 0;
}
if (IsServer(sptr) || sptr != acptr)
{
if (IsServer(cptr))
- sendto_ops_butone(NULL, &me, ":%s WALLOPS :MODE for User %s From %s!%s",
- me.name, parv[1], cptr->name, sptr->name);
+ sendcmdto_flag_butone(&me, CMD_WALLOPS, 0, FLAGS_WALLOP,
+ ":MODE for User %s from %s!%s", parv[1],
+ cptr->name, sptr->name);
else
- sendto_one(sptr, err_str(ERR_USERSDONTMATCH), me.name, parv[0]);
+ send_reply(sptr, ERR_USERSDONTMATCH);
return 0;
}
*m++ = userModeList[i].c;
}
*m = '\0';
- sendto_one(sptr, rpl_str(RPL_UMODEIS), me.name, parv[0], buf);
+ send_reply(sptr, RPL_UMODEIS, buf);
if ((sptr->flags & FLAGS_SERVNOTICE) && MyConnect(sptr)
&& sptr->snomask !=
(unsigned int)(IsOper(sptr) ? SNO_OPERDEFAULT : SNO_DEFAULT))
- sendto_one(sptr, rpl_str(RPL_SNOMASK), me.name, parv[0], sptr->snomask,
- sptr->snomask);
+ send_reply(sptr, RPL_SNOMASK, sptr->snomask, sptr->snomask);
return 0;
}
if (tmpmask != sptr->snomask)
set_snomask(sptr, tmpmask, SNO_SET);
if (sptr->snomask && snomask_given)
- sendto_one(sptr, rpl_str(RPL_SNOMASK), me.name, sptr->name,
- sptr->snomask, sptr->snomask);
+ send_reply(sptr, RPL_SNOMASK, sptr->snomask, sptr->snomask);
}
return 0;
}
*m = '\0';
if (*umodeBuf && cptr)
- sendto_one(cptr, ":%s MODE %s :%s", sptr->name, sptr->name, umodeBuf);
+ sendcmdto_one(sptr, CMD_MODE, cptr, "%s :%s", sptr->name, umodeBuf);
}
/*
else if (what == SNO_DEL)
newmask = oldmask & ~newmask;
else if (what != SNO_SET) /* absolute set, no math needed */
- sendto_ops("setsnomask called with %d ?!", what);
+ sendto_opmask_butone(0, SNO_OLDSNO, "setsnomask called with %d ?!", what);
newmask &= (IsAnOper(cptr) ? SNO_ALL : SNO_USER);
{
if (!MyConnect(sptr))
{
- if (Protocol(sptr->from) < 10)
- sendto_one(sptr->from, ":%s SILENCE %s %s", acptr->name,
- sptr->name, lp->value.cp);
- else
- sendto_one(sptr->from, ":%s SILENCE %s%s %s", acptr->name,
- NumNick(sptr), lp->value.cp);
+ sendcmdto_one(acptr, CMD_SILENCE, sptr->from, "%C %s", sptr,
+ lp->value.cp);
}
return 1;
}
len += strlen(lp->value.cp);
if ((len > MAXSILELENGTH) || (++cnt >= MAXSILES))
{
- sendto_one(sptr, err_str(ERR_SILELISTFULL), me.name, sptr->name, mask);
+ send_reply(sptr, ERR_SILELISTFULL, mask);
return -1;
}
else if (!mmatch(lp->value.cp, mask))