* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* @file
+/** @file
* @brief Miscellaneous user-related helper functions.
* @version $Id$
*/
#include "s_serv.h" /* max_client_count */
#include "send.h"
#include "struct.h"
-#include "support.h"
#include "supported.h"
#include "sys.h"
#include "userload.h"
#include "handlers.h" /* m_motd and m_lusers */
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
static time_t last_too_many2;
assert(cptr == sptr);
+ assert(cli_unreg(sptr) == 0);
if (!IsIAuthed(sptr)) {
if (iauth_active)
return iauth_start_client(iauth_active, sptr);
get_client_name(sptr, SHOW_IP));
}
++ServerStats->is_ref;
- IPcheck_connect_fail(&cli_ip(sptr));
+ IPcheck_connect_fail(sptr);
return exit_client(cptr, sptr, &me,
"Sorry, your connection class is full - try "
"again later or try another server");
/* Can this ever happen? */
case ACR_BAD_SOCKET:
++ServerStats->is_ref;
- IPcheck_connect_fail(&cli_ip(sptr));
+ IPcheck_connect_fail(sptr);
return exit_client(cptr, sptr, &me, "Unknown error -- Try again");
}
ircd_strncpy(user->host, cli_sockhost(sptr), HOSTLEN);
return exit_client(cptr, sptr, &me, "USER: Bogus userid.");
if (!EmptyString(aconf->passwd)
- && !(IsDigit(*aconf->passwd) && !aconf->passwd[1])
&& strcmp(cli_passwd(sptr), aconf->passwd))
{
ServerStats->is_ref++;
*/
send_reply(sptr, RPL_YOURHOST, cli_name(&me), version);
send_reply(sptr, RPL_CREATED, creation);
- send_reply(sptr, RPL_MYINFO, cli_name(&me), infousermodes, infochanmodes,
- infochanmodeswithparams, version);
+ send_reply(sptr, RPL_MYINFO, cli_name(&me), version, infousermodes,
+ infochanmodes, infochanmodeswithparams);
send_supported(sptr);
m_lusers(sptr, sptr, 1, parv);
update_load();
SetFlag(sptr, FLAG_TS8);
/*
- * Check to see if this user is being propogated
+ * Check to see if this user is being propagated
* as part of a net.burst, or is using protocol 9.
- * FIXME: This can be speeded up - its stupid to check it for
+ * FIXME: This can be sped up - its stupid to check it for
* every NICK message in a burst again --Run.
*/
for (acptr = user->server; acptr != &me; acptr = cli_serv(acptr)->up)
}
}
tmpstr = umode_str(sptr);
- sendcmdto_serv_butone(user->server, CMD_NICK, cptr,
- "%s %d %Tu %s %s %s%s%s%s %s%s :%s",
- nick, cli_hopcount(sptr) + 1, cli_lastnick(sptr),
- user->username, user->realhost,
- *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "",
- iptobase64(ip_base64, &cli_ip(sptr), sizeof(ip_base64)),
- NumNick(sptr), cli_info(sptr));
+ /* Send full IP address to IPv6-grokking servers. */
+ sendcmdto_flag_serv_butone(user->server, CMD_NICK, cptr,
+ FLAG_IPV6, FLAG_LAST_FLAG,
+ "%s %d %Tu %s %s %s%s%s%s %s%s :%s",
+ nick, cli_hopcount(sptr) + 1, cli_lastnick(sptr),
+ user->username, user->realhost,
+ *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "",
+ iptobase64(ip_base64, &cli_ip(sptr), sizeof(ip_base64), 1),
+ NumNick(sptr), cli_info(sptr));
+ /* Send fake IPv6 addresses to pre-IPv6 servers. */
+ sendcmdto_flag_serv_butone(user->server, CMD_NICK, cptr,
+ FLAG_LAST_FLAG, FLAG_IPV6,
+ "%s %d %Tu %s %s %s%s%s%s %s%s :%s",
+ nick, cli_hopcount(sptr) + 1, cli_lastnick(sptr),
+ user->username, user->realhost,
+ *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "",
+ iptobase64(ip_base64, &cli_ip(sptr), sizeof(ip_base64), 0),
+ NumNick(sptr), cli_info(sptr));
/* Send server notice mask to client */
if (MyUser(sptr) && (cli_snomask(sptr) != SNO_DEFAULT) && HasFlag(sptr, FLAG_SERVNOTICE))
}
hAddClient(sptr);
+ cli_unreg(sptr) &= ~CLIREG_NICK; /* nickname now set */
+
/*
* If the client hasn't gotten a cookie-ping yet,
* choose a cookie and send it. -record!jegelhof@cloud9.net
} while (!cli_cookie(sptr));
sendrawto_one(cptr, MSG_PING " :%u", cli_cookie(sptr));
}
- else if (*(cli_user(sptr))->host && cli_cookie(sptr) == COOKIE_VERIFIED) {
+ else if (!cli_unreg(sptr)) {
/*
* USER and PONG already received, now we have NICK.
* register_user may reject the client and call exit_client
for (chan = (cli_user(cptr))->channel; chan;
chan = chan->next_channel)
ClearBanValid(chan);
+ break;
default:
return 0;
}
{
if (IsZombie(chan))
continue;
- /* For a user with no modes in a join-delayed channel, do not show
- * the rejoin. */
- if (!IsChanOp(chan) && !HasVoice(chan)
- && (chan->channel->mode.mode & MODE_DELJOINS))
- SetDelayedJoin(chan);
- else
+ /* Send a JOIN unless the user's join has been delayed. */
+ if (!IsDelayedJoin(chan))
sendcmdto_channel_butserv_butone(cptr, CMD_JOIN, chan->channel, cptr, 0,
"%H", chan->channel);
if (IsChanOp(chan) && HasVoice(chan))
/** Check whether \a sptr is allowed to send a message to \a acptr.
* If \a sptr is a remote user, it means some server has an outdated
- * SILENCE list for \a acptr, so send the missing SILENCE back in the
- * direction of \a sptr.
+ * SILENCE list for \a acptr, so send the missing SILENCE mask(s) back
+ * in the direction of \a sptr. Skip the check if \a sptr is a server.
* @param[in] sptr Client trying to send a message.
* @param[in] acptr Destination of message.
* @return Non-zero if \a sptr is SILENCEd by \a acptr, zero if not.
*/
int is_silenced(struct Client *sptr, struct Client *acptr)
{
- struct SLink *lp;
+ struct Ban *found;
struct User *user;
- static char sender[HOSTLEN + NICKLEN + USERLEN + 5];
- static char senderip[16 + NICKLEN + USERLEN + 5];
- static char senderh[HOSTLEN + ACCOUNTLEN + USERLEN + 6];
+ size_t buf_used, slen;
+ char buf[BUFSIZE];
- if (!cli_user(acptr) || !(lp = cli_user(acptr)->silence) || !(user = cli_user(sptr)))
+ if (IsServer(sptr) || !(user = cli_user(acptr))
+ || !(found = find_ban(sptr, user->silence)))
return 0;
- ircd_snprintf(0, sender, sizeof(sender), "%s!%s@%s", cli_name(sptr),
- user->username, user->host);
- ircd_snprintf(0, senderip, sizeof(senderip), "%s!%s@%s", cli_name(sptr),
- user->username, ircd_ntoa(&cli_ip(sptr)));
- if (HasHiddenHost(sptr))
- ircd_snprintf(0, senderh, sizeof(senderh), "%s!%s@%s", cli_name(sptr),
- user->username, user->realhost);
- for (; lp; lp = lp->next)
- {
- if ((!(lp->flags & CHFL_SILENCE_IPMASK) && (!match(lp->value.cp, sender) ||
- (HasHiddenHost(sptr) && !match(lp->value.cp, senderh)))) ||
- ((lp->flags & CHFL_SILENCE_IPMASK) && !match(lp->value.cp, senderip)))
- {
- if (!MyConnect(sptr))
- {
- sendcmdto_one(acptr, CMD_SILENCE, cli_from(sptr), "%C %s", sptr,
- lp->value.cp);
+ assert(!(found->flags & BAN_EXCEPTION));
+ if (!MyConnect(sptr)) {
+ /* Buffer positive silence to send back. */
+ buf_used = strlen(found->banstr);
+ memcpy(buf, found->banstr, buf_used);
+ /* Add exceptions to buffer. */
+ for (found = user->silence; found; found = found->next) {
+ if (!(found->flags & BAN_EXCEPTION))
+ continue;
+ slen = strlen(found->banstr);
+ if (buf_used + slen + 4 > 400) {
+ buf[buf_used] = '\0';
+ sendcmdto_one(acptr, CMD_SILENCE, cli_from(sptr), "%C %s", sptr, buf);
+ buf_used = 0;
}
- return 1;
- }
- }
- return 0;
-}
-
-/** Remove all silence masks from \a sptr that match \a mask.
- * @param[in,out] sptr Client to update.
- * @param[in] mask Silence mask to remove.
- * @return Zero if any silence masks were removed; non-zero if all were kept.
- */
-int del_silence(struct Client *sptr, char *mask)
-{
- struct SLink **lp;
- struct SLink *tmp;
- int ret = -1;
-
- for (lp = &(cli_user(sptr))->silence; *lp;) {
- if (!mmatch(mask, (*lp)->value.cp))
- {
- tmp = *lp;
- *lp = tmp->next;
- MyFree(tmp->value.cp);
- free_link(tmp);
- ret = 0;
- }
- else
- lp = &(*lp)->next;
- }
- return ret;
-}
-
-/** Add \a mask to the silence masks for \a sptr.
- * Removes any silence masks that are subsets of \a mask.
- * @param[in,out] sptr Client adding silence mask.
- * @param[in] mask Silence mask to add.
- * @return Zero on success; non-zero on any failure.
- */
-int add_silence(struct Client* sptr, const char* mask)
-{
- struct SLink *lp, **lpp;
- int cnt = 0, len = strlen(mask);
- char *ip_start;
-
- for (lpp = &(cli_user(sptr))->silence, lp = *lpp; lp;)
- {
- if (0 == ircd_strcmp(mask, lp->value.cp))
- return -1;
- if (!mmatch(mask, lp->value.cp))
- {
- struct SLink *tmp = lp;
- *lpp = lp = lp->next;
- MyFree(tmp->value.cp);
- free_link(tmp);
- continue;
+ if (buf_used)
+ buf[buf_used++] = ',';
+ buf[buf_used++] = '+';
+ buf[buf_used++] = '~';
+ memcpy(buf + buf_used, found->banstr, slen);
+ buf_used += slen;
}
- if (MyUser(sptr))
- {
- len += strlen(lp->value.cp);
- if ((len > (feature_int(FEAT_AVBANLEN) * feature_int(FEAT_MAXSILES))) ||
- (++cnt >= feature_int(FEAT_MAXSILES)))
- {
- send_reply(sptr, ERR_SILELISTFULL, mask);
- return -1;
- }
- else if (!mmatch(lp->value.cp, mask))
- return -1;
+ /* Flush silence buffer. */
+ if (buf_used) {
+ buf[buf_used] = '\0';
+ sendcmdto_one(acptr, CMD_SILENCE, cli_from(sptr), "%C %s", sptr, buf);
+ buf_used = 0;
}
- lpp = &lp->next;
- lp = *lpp;
}
- lp = make_link();
- memset(lp, 0, sizeof(struct SLink));
- lp->next = cli_user(sptr)->silence;
- lp->value.cp = (char*) MyMalloc(strlen(mask) + 1);
- assert(0 != lp->value.cp);
- strcpy(lp->value.cp, mask);
- if ((ip_start = strrchr(mask, '@')) && check_if_ipmask(ip_start + 1))
- lp->flags = CHFL_SILENCE_IPMASK;
- cli_user(sptr)->silence = lp;
- return 0;
+ return 1;
}
/** Send RPL_ISUPPORT lines to \a cptr.