2 * IRC - Internet Relay Chat, ircd/s_user.c (formerly ircd/s_msg.c)
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
6 * See file AUTHORS in IRC package for additional names of
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 1, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
62 #include "sprintf_irc.h"
63 #include "querycmds.h"
71 /* This is not ANSI, but we have it anyway... */
73 char *crypt(const char *key, const char *salt);
78 static char buf[BUFSIZE], buf2[BUFSIZE];
81 * m_functions execute protocol messages on this server:
83 * cptr is always NON-NULL, pointing to a *LOCAL* client
84 * structure (with an open socket connected!). This
85 * identifies the physical socket where the message
86 * originated (or which caused the m_function to be
87 * executed--some m_functions may call others...).
89 * sptr is the source of the message, defined by the
90 * prefix part of the message if present. If not
91 * or prefix not found, then sptr==cptr.
93 * (!IsServer(cptr)) => (cptr == sptr), because
94 * prefixes are taken *only* from servers...
97 * (sptr == cptr) => the message didn't
100 * (sptr != cptr && IsServer(sptr) means
101 * the prefix specified servername. (?)
103 * (sptr != cptr && !IsServer(sptr) means
104 * that message originated from a remote
109 * (!IsServer(sptr)) means that, sptr can safely
110 * taken as defining the target structure of the
111 * message in this server.
113 * *Always* true (if 'parse' and others are working correct):
115 * 1) sptr->from == cptr (note: cptr->from == cptr)
117 * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
118 * *cannot* be a local connection, unless it's
119 * actually cptr!). [MyConnect(x) should probably
120 * be defined as (x == x->from) --msa ]
122 * parc number of variable parameter strings (if zero,
123 * parv is allowed to be NULL)
125 * parv a NULL terminated list of parameter pointers,
127 * parv[0], sender (prefix string), if not present
128 * this points to an empty string.
129 * parv[1]...parv[parc-1]
130 * pointers to additional parameters
131 * parv[parc] == NULL, *always*
133 * note: it is guaranteed that parv[0]..parv[parc-1] are all
140 * Local function to find the next matching client. The search
141 * can be continued from the specified client entry. Normal
144 * for (x = client; x = next_client(x,mask); x = x->next)
145 * HandleMatchingClient;
148 aClient *next_client(aClient *next, char *ch)
150 Reg3 aClient *tmp = next;
155 next = FindClient(ch);
156 next = next ? next : tmp;
157 if (tmp->prev == next)
161 for (; next; next = next->next)
162 if (!match(ch, next->name))
170 * Do the basic thing in delivering the message (command)
171 * across the relays to the specific server (server) for
174 * Note: The command is a format string and *MUST* be
175 * of prefixed style (e.g. ":%s COMMAND %s ...").
176 * Command can have only max 8 parameters.
178 * server parv[server] is the parameter identifying the
182 * parv[server] is replaced with the pointer to the
183 * real servername from the matched client (I'm lazy
186 * returns: (see #defines)
188 int hunt_server(int MustBeOper, aClient *cptr, aClient *sptr, char *command,
189 int server, int parc, char *parv[])
194 /* Assume it's me, if no server or an unregistered client */
195 if (parc <= server || BadPtr(parv[server]) || IsUnknown(sptr))
196 return (HUNTED_ISME);
198 /* Make sure it's a server */
199 if (MyUser(sptr) || Protocol(cptr) < 10)
201 /* Make sure it's a server */
202 if (!strchr(parv[server], '*'))
204 if (0 == (acptr = FindClient(parv[server])))
205 return HUNTED_NOSUCH;
207 acptr = acptr->user->server;
209 else if (!(acptr = find_match_server(parv[server])))
211 sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
212 me.name, parv[0], parv[server]);
213 return (HUNTED_NOSUCH);
216 else if (!(acptr = FindNServer(parv[server])))
217 return (HUNTED_NOSUCH); /* Server broke off in the meantime */
220 return (HUNTED_ISME);
222 if (MustBeOper && !IsPrivileged(sptr))
224 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name);
225 return HUNTED_NOSUCH;
231 strcpy(y, acptr->yxx);
235 if (Protocol(acptr->from) > 9)
237 strcpy(y, acptr->yxx);
241 parv[server] = acptr->name;
244 sendto_one(acptr, command, parv[0], parv[1], parv[2], parv[3], parv[4],
245 parv[5], parv[6], parv[7], parv[8]);
247 return (HUNTED_PASS);
251 * 'do_nick_name' ensures that the given parameter (nick) is really a proper
252 * string for a nickname (note, the 'nick' may be modified in the process...)
254 * RETURNS the length of the final NICKNAME (0, if nickname is invalid)
256 * Nickname characters are in range 'A'..'}', '_', '-', '0'..'9'
257 * anything outside the above set will terminate nickname.
258 * In addition, the first character cannot be '-' or a Digit.
261 * The '~'-character should be allowed, but a change should be global,
262 * some confusion would result if only few servers allowed it...
265 static int do_nick_name(char *nick)
269 if (*nick == '-' || isDigit(*nick)) /* first character in [0..9-] */
272 for (ch = nick; *ch && (ch - nick) < NICKLEN; ch++)
284 * reduce a string of duplicate list entries to contain only the unique
285 * items. Unavoidably O(n^2).
287 char *canonize(char *buffer)
289 static char cbuf[BUFSIZ];
290 register char *s, *t, *cp = cbuf;
296 for (s = strtoken(&p, buffer, ","); s; s = strtoken(&p, NULL, ","))
301 for (t = strtoken(&p2, cbuf, ","); t; t = strtoken(&p2, NULL, ","))
302 if (!strCasediff(s, t))
328 * Copy `source' to `dest', replacing all occurances of '~' and characters that
329 * are not `isIrcUi' by an underscore.
330 * Copies at most USERLEN - 1 characters or up till the first control character.
331 * If `tilde' is true, then a tilde is prepended to `dest'.
332 * Note that `dest' and `source' can point to the same area or to different
333 * non-overlapping areas.
336 static char *clean_user_id(char *dest, char *source, int tilde)
343 ch = *s++; /* Store first character to copy: */
346 *d++ = '~'; /* If `dest' == `source', then this overwrites `ch' */
349 while (ch && !isCntrl(ch) && rlen--)
351 register char nch = *s++; /* Store next character to copy */
352 *d++ = isIrcUi(ch) ? ch : '_'; /* This possibly overwrites it */
365 * This function is called when both NICK and USER messages
366 * have been accepted for the client, in whatever order. Only
367 * after this the USER message is propagated.
369 * NICK's must be propagated at once when received, although
370 * it would be better to delay them too until full info is
371 * available. Doing it is not so simple though, would have
372 * to implement the following:
374 * 1) user telnets in and gives only "NICK foobar" and waits
375 * 2) another user far away logs in normally with the nick
376 * "foobar" (quite legal, as this server didn't propagate it).
377 * 3) now this server gets nick "foobar" from outside, but
378 * has already the same defined locally. Current server
379 * would just issue "KILL foobar" to clean out dups. But,
380 * this is not fair. It should actually request another
381 * nick from local user or kill him/her...
384 static int register_user(aClient *cptr, aClient *sptr,
385 char *nick, char *username)
387 Reg1 aConfItem *aconf;
388 char *parv[3], *tmpstr, *tmpstr2;
389 char c = 0 /* not alphanum */ , d = 'a' /* not a digit */ ;
390 short oldstatus_ismaster = IsMaster(sptr), upper = 0, lower = 0;
391 short pos = 0, leadcaps = 0, other = 0, digits = 0, badid = 0;
392 short digitgroups = 0;
393 anUser *user = sptr->user;
398 parv[0] = sptr->name;
399 parv[1] = parv[2] = NULL;
403 static time_t last_too_many1, last_too_many2;
404 switch (check_client(sptr))
408 case ACR_NO_AUTHORIZATION:
409 sendto_op_mask(SNO_UNAUTH, "Unauthorized connection from %s.",
410 get_client_host(sptr));
412 return exit_client(cptr, sptr, &me,
413 "No Authorization - use another server");
414 case ACR_TOO_MANY_IN_CLASS:
415 if (now - last_too_many1 >= (time_t) 60)
417 last_too_many1 = now;
418 sendto_op_mask(SNO_TOOMANY, "Too many connections in class for %s.",
419 get_client_host(sptr));
421 IPcheck_connect_fail(sptr);
423 return exit_client(cptr, sptr, &me,
424 "Sorry, your connection class is full - try again later or try another server");
425 case ACR_TOO_MANY_FROM_IP:
426 if (now - last_too_many2 >= (time_t) 60)
428 last_too_many2 = now;
429 sendto_op_mask(SNO_TOOMANY,
430 "Too many connections from same IP for %s.",
431 get_client_host(sptr));
434 return exit_client(cptr, sptr, &me,
435 "Too many connections from your host");
436 case ACR_ALREADY_AUTHORIZED:
437 /* Can this ever happen? */
439 IPcheck_connect_fail(sptr);
440 return exit_client(cptr, sptr, &me, "Unknown error -- Try again");
442 if (IsUnixSocket(sptr))
443 strncpy(user->host, me.sockhost, HOSTLEN);
445 strncpy(user->host, sptr->sockhost, HOSTLEN);
446 aconf = sptr->confs->value.aconf;
448 clean_user_id(user->username,
449 (sptr->flags & FLAGS_GOTID) ? sptr->username : username,
450 (sptr->flags & FLAGS_DOID) && !(sptr->flags & FLAGS_GOTID));
452 if ((user->username[0] == '\000')
453 || ((user->username[0] == '~') && (user->username[1] == '\000')))
454 return exit_client(cptr, sptr, &me, "USER: Bogus userid.");
456 if (!BadPtr(aconf->passwd)
457 && !(isDigit(*aconf->passwd) && !aconf->passwd[1])
459 && strcmp("ONE", aconf->passwd)
461 && strcmp(sptr->passwd, aconf->passwd))
464 sendto_one(sptr, err_str(ERR_PASSWDMISMATCH), me.name, parv[0]);
465 IPcheck_connect_fail(sptr);
466 return exit_client(cptr, sptr, &me, "Bad Password");
468 memset(sptr->passwd, 0, sizeof(sptr->passwd));
470 * following block for the benefit of time-dependent K:-lines
475 return exit_client(cptr, sptr, &me, "K-lined");
478 if (find_restrict(sptr))
481 return exit_client(cptr, sptr, &me, "R-lined");
486 * Check for mixed case usernames, meaning probably hacked. Jon2 3-94
487 * Summary of rules now implemented in this patch: Ensor 11-94
488 * In a mixed-case name, if first char is upper, one more upper may
489 * appear anywhere. (A mixed-case name *must* have an upper first
490 * char, and may have one other upper.)
491 * A third upper may appear if all 3 appear at the beginning of the
492 * name, separated only by "others" (-/_/.).
493 * A single group of digits is allowed anywhere.
494 * Two groups of digits are allowed if at least one of the groups is
495 * at the beginning or the end.
496 * Only one '-', '_', or '.' is allowed (or two, if not consecutive).
497 * But not as the first or last char.
498 * No other special characters are allowed.
499 * Name must contain at least one letter.
501 tmpstr2 = tmpstr = (username[0] == '~' ? &username[1] : username);
502 while (*tmpstr && !badid)
514 if ((leadcaps || pos == 1) && !lower && !digits)
520 if (pos == 1 || !isDigit(d))
527 else if (c == '-' || c == '_' || c == '.')
532 else if (d == '-' || d == '_' || d == '.' || other > 2)
541 if (lower && upper && (!leadcaps || leadcaps > 3 ||
542 (upper > 2 && upper > leadcaps)))
544 else if (digitgroups == 2 && !(isDigit(tmpstr2[0]) || isDigit(c)))
546 else if ((!lower && !upper) || !isAlnum(c))
549 if (badid && (!(sptr->flags & FLAGS_GOTID) ||
550 strcmp(sptr->username, username) != 0))
553 sendto_one(cptr, ":%s %d %s :Your username is invalid.",
554 me.name, ERR_INVALIDUSERNAME, cptr->name);
556 ":%s %d %s :Connect with your real username, in lowercase.",
557 me.name, ERR_INVALIDUSERNAME, cptr->name);
558 sendto_one(cptr, ":%s %d %s :If your mail address were foo@bar.com, "
559 "your username would be foo.",
560 me.name, ERR_INVALIDUSERNAME, cptr->name);
561 return exit_client(cptr, sptr, &me, "USER: Bad username");
564 if (oldstatus_ismaster && MyConnect(sptr))
565 m_oper(&me, sptr, 1, parv);
567 Count_unknownbecomesclient(sptr, nrof);
571 strncpy(user->username, username, USERLEN);
572 Count_newremoteclient(nrof);
575 if (IsInvisible(sptr))
582 sendto_one(sptr, rpl_str(RPL_WELCOME), me.name, nick, nick);
583 /* This is a duplicate of the NOTICE but see below... */
584 sendto_one(sptr, rpl_str(RPL_YOURHOST), me.name, nick,
585 get_client_name(&me, FALSE), version);
586 sendto_one(sptr, rpl_str(RPL_CREATED), me.name, nick, creation);
587 sendto_one(sptr, rpl_str(RPL_MYINFO), me.name, parv[0], me.name, version);
588 m_lusers(sptr, sptr, 1, parv);
591 m_motd(sptr, NULL, 1, parv);
593 m_motd(sptr, sptr, 1, parv);
596 if (sptr->snomask & SNO_NOISY)
597 set_snomask(sptr, sptr->snomask & SNO_NOISY, SNO_ADD);
598 #ifdef ALLOW_SNO_CONNEXIT
599 #ifdef SNO_CONNEXIT_IP
601 ":%s NOTICE * :*** Notice -- Client connecting: %s (%s@%s) [%s] {%d}",
602 me.name, nick, user->username, user->host, inetntoa(sptr->ip),
603 get_client_class(sptr));
604 sendbufto_op_mask(SNO_CONNEXIT);
605 #else /* SNO_CONNEXIT_IP */
607 ":%s NOTICE * :*** Notice -- Client connecting: %s (%s@%s)",
608 me.name, nick, user->username, user->host);
609 sendbufto_op_mask(SNO_CONNEXIT);
610 #endif /* SNO_CONNEXIT_IP */
611 #endif /* ALLOW_SNO_CONNEXIT */
612 IPcheck_connect_succeeded(sptr);
615 /* if (IsServer(cptr)) */
619 acptr = user->server;
620 if (acptr->from != sptr->from)
622 if (Protocol(cptr) < 10)
623 sendto_one(cptr, ":%s KILL %s :%s (%s != %s[%s])",
624 me.name, sptr->name, me.name, user->server->name, acptr->from->name,
625 acptr->from->sockhost);
627 sendto_one(cptr, "%s KILL %s%s :%s (%s != %s[%s])",
628 NumServ(&me), NumNick(sptr), me.name, user->server->name,
629 acptr->from->name, acptr->from->sockhost);
630 sptr->flags |= FLAGS_KILLED;
631 return exit_client(cptr, sptr, &me, "NICK server wrong direction");
634 sptr->flags |= (acptr->flags & FLAGS_TS8);
637 * Check to see if this user is being propogated
638 * as part of a net.burst, or is using protocol 9.
639 * FIXME: This can be speeded up - its stupid to check it for
640 * every NICK message in a burst again --Run.
642 for (acptr = user->server; acptr != &me; acptr = acptr->serv->up)
643 if (IsBurst(acptr) || Protocol(acptr) < 10)
645 if (IPcheck_remote_connect(sptr, user->host, (acptr != &me)) == -1)
646 /* We ran out of bits to count this */
647 return exit_client(cptr, sptr, &me,
648 "More then 255 connections from this IP number");
650 #ifdef NO_PROTOCOL9 /* Use this when all servers are 2.10 (but test it first) --Run */
652 tmpstr = umode_str(sptr);
653 sendto_serv_butone(cptr, *tmpstr ?
654 "%s NICK %s %d %d %s %s +%s %s %s%s :%s" :
655 "%s NICK %s %d %d %s %s %s%s %s%s :%s",
656 NumServ(user->server), nick, sptr->hopcount + 1, sptr->lastnick,
657 user->username, user->host, tmpstr,
658 inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6),
659 NumNick(sptr), sptr->info);
661 #else /* Remove the following when all servers are 2.10 */
663 /* First send message to all 2.9 servers */
664 sprintf_irc(sendbuf, ":%s NICK %s %d " TIME_T_FMT " %s %s %s :%s",
665 user->server->name, nick, sptr->hopcount + 1, sptr->lastnick,
666 user->username, user->host, user->server->name, sptr->info);
667 for (lp = me.serv->down; lp; lp = lp->next)
669 if (lp->value.cptr == cptr)
671 if (Protocol(lp->value.cptr) < 10)
672 sendbufto_one(lp->value.cptr);
675 /* If the user has no umode, no need to generate a user MODE */
676 if (*(tmpstr = umode_str(sptr)) && (MyConnect(sptr) || Protocol(cptr) > 9))
677 /* Is it necessary to generate an user MODE message ? */
679 for (lp = me.serv->down; lp; lp = lp->next)
681 if (lp->value.cptr == cptr)
683 if (Protocol(lp->value.cptr) < 10)
684 sendto_one(lp->value.cptr, ":%s MODE %s :%s", sptr->name,
689 /* Now send message to all 2.10 servers */
690 sprintf_irc(sendbuf, *tmpstr ?
691 "%s NICK %s %d %d %s %s +%s %s %s%s :%s" :
692 "%s NICK %s %d %d %s %s %s%s %s%s :%s",
693 NumServ(user->server), nick, sptr->hopcount + 1, sptr->lastnick,
694 user->username, user->host, tmpstr,
695 inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6),
696 NumNick(sptr), sptr->info);
697 for (lp = me.serv->down; lp; lp = lp->next)
699 if (lp->value.cptr == cptr || Protocol(lp->value.cptr) < 10)
701 sendbufto_one(lp->value.cptr);
706 /* Send umode to client */
709 send_umode(cptr, sptr, 0, ALL_UMODES);
710 if (sptr->snomask != SNO_DEFAULT && (sptr->flags & FLAGS_SERVNOTICE))
711 sendto_one(sptr, rpl_str(RPL_SNOMASK), me.name, sptr->name,
712 sptr->snomask, sptr->snomask);
720 static int user_modes[] = {
723 FLAGS_INVISIBLE, 'i',
725 FLAGS_SERVNOTICE, 's',
734 #define COOKIE_VERIFIED ((unsigned int)-1)
739 * parv[0] = sender prefix
742 * If from server, source is client:
743 * parv[2] = timestamp
747 * parv[3] = timestamp
750 * parv[6] = umode (optional)
751 * parv[parc-3] = IP# <- Only Protocol >= 10
752 * parv[parc-2] = YXX, numeric nick <- Only Protocol >= 10
753 * parv[parc-1] = info
756 int m_nick(aClient *cptr, aClient *sptr, int parc, char *parv[])
759 aClient *server = NULL;
760 char nick[NICKLEN + 2];
763 time_t lastnick = (time_t) 0;
768 sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]);
771 else if ((IsServer(sptr) && parc < 8) || (IsServer(cptr) && parc < 3))
773 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "NICK");
774 sendto_ops("bad NICK param count for %s from %s",
775 parv[1], get_client_name(cptr, FALSE));
778 if (MyConnect(sptr) && (s = strchr(parv[1], '~')))
780 strncpy(nick, parv[1], NICKLEN + 1);
781 nick[sizeof(nick) - 1] = 0;
783 * If do_nick_name() returns a null name OR if the server sent a nick
784 * name and do_nick_name() changed it in some way (due to rules of nick
785 * creation) then reject it. If from a server and we reject it,
786 * and KILL it. -avalon 4/4/92
788 if (do_nick_name(nick) == 0 || (IsServer(cptr) && strcmp(nick, parv[1])))
790 sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name, parv[0], parv[1]);
795 sendto_ops("Bad Nick: %s From: %s %s",
796 parv[1], parv[0], get_client_name(cptr, FALSE));
797 if (Protocol(cptr) < 10)
798 sendto_one(cptr, ":%s KILL %s :%s (%s <- %s[%s])",
799 me.name, parv[1], me.name, parv[1], nick, cptr->name);
801 sendto_one(cptr, "%s KILL %s :%s (%s <- %s[%s])",
802 NumServ(&me), IsServer(sptr) ? parv[parc - 2] : parv[0], me.name,
803 parv[1], nick, cptr->name);
804 if (!IsServer(sptr)) /* bad nick _change_ */
806 sendto_lowprot_butone(cptr, 9, ":%s KILL %s :%s (%s <- %s!%s@%s)",
807 me.name, parv[0], me.name, get_client_name(cptr, FALSE), parv[0],
808 sptr->user ? sptr->username : "",
809 sptr->user ? sptr->user->server->name : cptr->name);
810 sendto_highprot_butone(cptr, 10, "%s KILL %s :%s (%s <- %s!%s@%s)",
811 NumServ(&me), parv[0], me.name, get_client_name(cptr, FALSE),
812 parv[0], sptr->user ? sptr->username : "",
813 sptr->user ? sptr->user->server->name : cptr->name);
814 sptr->flags |= FLAGS_KILLED;
815 return exit_client(cptr, sptr, &me, "BadNick");
822 * Check if this is a LOCAL user trying to use a reserved (Juped)
823 * nick, if so tell him that it's a nick in use...
826 if ((!IsServer(cptr)) && isNickJuped(nick))
828 sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
829 /* parv[0] is empty when connecting */
830 BadPtr(parv[0]) ? "*" : parv[0], nick);
831 return 0; /* NICK message ignored */
835 * Check against nick name collisions.
837 * Put this 'if' here so that the nesting goes nicely on the screen :)
838 * We check against server name list before determining if the nickname
839 * is present in the nicklist (due to the way the below for loop is
840 * constructed). -avalon
842 if ((acptr = FindServer(nick)))
845 sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
846 BadPtr(parv[0]) ? "*" : parv[0], nick);
847 return 0; /* NICK message ignored */
850 * acptr already has result from previous FindServer()
855 * We have a nickname trying to use the same name as
856 * a server. Send out a nick collision KILL to remove
857 * the nickname. As long as only a KILL is sent out,
858 * there is no danger of the server being disconnected.
859 * Ultimate way to jupiter a nick ? >;-). -avalon
861 sendto_ops("Nick collision on %s(%s <- %s)",
862 sptr->name, acptr->from->name, get_client_name(cptr, FALSE));
864 if (Protocol(cptr) < 10)
865 sendto_one(cptr, ":%s KILL %s :%s (%s <- %s)",
866 me.name, sptr->name, me.name, acptr->from->name,
867 get_client_name(cptr, FALSE));
869 sendto_one(cptr, "%s KILL %s%s :%s (%s <- %s)",
870 NumServ(&me), NumNick(sptr), me.name, acptr->from->name,
872 * NOTE: Cannot use get_client_name twice here, it returns static
873 * string pointer--the other info would be lost.
875 get_client_name(cptr, FALSE));
876 sptr->flags |= FLAGS_KILLED;
877 return exit_client(cptr, sptr, &me, "Nick/Server collision");
880 if (!(acptr = FindClient(nick)))
881 goto nickkilldone; /* No collisions, all clear... */
883 * If acptr == sptr, then we have a client doing a nick
884 * change between *equivalent* nicknames as far as server
885 * is concerned (user is changing the case of his/her
886 * nickname or somesuch)
890 if (strcmp(acptr->name, nick) != 0)
892 * Allows change of case in his/her nick
894 goto nickkilldone; /* -- go and process change */
897 * This is just ':old NICK old' type thing.
898 * Just forget the whole thing here. There is
899 * no point forwarding it to anywhere,
900 * especially since servers prior to this
901 * version would treat it as nick collision.
903 return 0; /* NICK Message ignored */
907 * Note: From this point forward it can be assumed that
908 * acptr != sptr (point to different client structures).
911 * If the older one is "non-person", the new entry is just
912 * allowed to overwrite it. Just silently drop non-person,
913 * and proceed with the nick. This should take care of the
914 * "dormant nick" way of generating collisions...
916 if (IsUnknown(acptr) && MyConnect(acptr))
918 IPcheck_connect_fail(acptr);
919 exit_client(cptr, acptr, &me, "Overridden by other sign on");
923 * Decide, we really have a nick collision and deal with it
928 * NICK is coming from local client connection. Just
929 * send error reply and ignore the command.
931 sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
932 /* parv[0] is empty when connecting */
933 BadPtr(parv[0]) ? "*" : parv[0], nick);
934 return 0; /* NICK message ignored */
937 * NICK was coming from a server connection.
938 * This means we have a race condition (two users signing on
939 * at the same time), or two net fragments reconnecting with the same nick.
940 * The latter can happen because two different users connected
941 * or because one and the same user switched server during a net break.
942 * If the TimeStamps are equal, we kill both (or only 'new'
943 * if it was a ":server NICK new ...").
944 * Otherwise we kill the youngest when user@host differ,
945 * or the oldest when they are the same.
946 * We treat user and ~user as different, because if it wasn't
947 * a faked ~user the AUTH wouldn't have added the '~'.
954 * A new NICK being introduced by a neighbouring
955 * server (e.g. message type ":server NICK new ..." received)
957 lastnick = atoi(parv[3]);
958 differ = (strCasediff(acptr->user->username, parv[4]) ||
959 strCasediff(acptr->user->host, parv[5]));
960 sendto_ops("Nick collision on %s (%s " TIME_T_FMT " <- %s " TIME_T_FMT
961 " (%s user@host))", acptr->name, acptr->from->name, acptr->lastnick,
962 get_client_name(cptr, FALSE), lastnick, differ ? "Different" : "Same");
967 * A NICK change has collided (e.g. message type ":old NICK new").
969 lastnick = atoi(parv[2]);
970 differ = (strCasediff(acptr->user->username, sptr->user->username) ||
971 strCasediff(acptr->user->host, sptr->user->host));
972 sendto_ops("Nick change collision from %s to %s (%s " TIME_T_FMT " <- %s "
973 TIME_T_FMT ")", sptr->name, acptr->name, acptr->from->name,
974 acptr->lastnick, get_client_name(cptr, FALSE), lastnick);
977 * Now remove (kill) the nick on our side if it is the youngest.
978 * If no timestamp was received, we ignore the incoming nick
979 * (and expect a KILL for our legit nick soon ):
980 * When the timestamps are equal we kill both nicks. --Run
981 * acptr->from != cptr should *always* be true (?).
983 if (acptr->from != cptr)
985 if ((differ && lastnick >= acptr->lastnick) ||
986 (!differ && lastnick <= acptr->lastnick))
991 sendto_lowprot_butone(cptr, 9, /* Kill old from outgoing servers */
992 ":%s KILL %s :%s (%s <- %s (Nick collision))",
993 me.name, sptr->name, me.name, acptr->from->name,
994 get_client_name(cptr, FALSE));
995 sendto_highprot_butone(cptr, 10, /* Kill old from outgoing servers */
996 "%s KILL %s%s :%s (%s <- %s (Nick collision))",
997 NumServ(&me), NumNick(sptr), me.name, acptr->from->name,
998 get_client_name(cptr, FALSE));
999 if (MyConnect(sptr) && IsServer(cptr) && Protocol(cptr) > 9)
1000 sendto_one(cptr, "%s KILL %s%s :%s (Ghost2)",
1001 NumServ(&me), NumNick(sptr), me.name);
1002 sptr->flags |= FLAGS_KILLED;
1003 exit_client(cptr, sptr, &me, "Nick collision (you're a ghost)");
1005 if (lastnick != acptr->lastnick)
1006 return 0; /* Ignore the NICK */
1008 sendto_one(acptr, err_str(ERR_NICKCOLLISION), me.name, acptr->name, nick);
1011 acptr->flags |= FLAGS_KILLED;
1014 sendto_lowprot_butone(cptr, 9, /* Kill our old from outgoing servers */
1015 ":%s KILL %s :%s (%s <- %s (older nick overruled))",
1016 me.name, acptr->name, me.name, acptr->from->name,
1017 get_client_name(cptr, FALSE));
1018 sendto_highprot_butone(cptr, 10, /* Kill our old from outgoing servers */
1019 "%s KILL %s%s :%s (%s <- %s (older nick overruled))",
1020 NumServ(&me), NumNick(acptr), me.name, acptr->from->name,
1021 get_client_name(cptr, FALSE));
1022 if (MyConnect(acptr) && IsServer(cptr) && Protocol(cptr) > 9)
1023 sendto_one(cptr, "%s%s QUIT :Local kill by %s (Ghost)",
1024 NumNick(acptr), me.name);
1025 exit_client(cptr, acptr, &me, "Nick collision (older nick overruled)");
1029 sendto_lowprot_butone(cptr, 9, /* Kill our old from outgoing servers */
1030 ":%s KILL %s :%s (%s <- %s (nick collision from same user@host))",
1031 me.name, acptr->name, me.name, acptr->from->name,
1032 get_client_name(cptr, FALSE));
1033 sendto_highprot_butone(cptr, 10, /* Kill our old from outgoing servers */
1034 "%s KILL %s%s :%s (%s <- %s (nick collision from same user@host))",
1035 NumServ(&me), NumNick(acptr), me.name, acptr->from->name,
1036 get_client_name(cptr, FALSE));
1037 if (MyConnect(acptr) && IsServer(cptr) && Protocol(cptr) > 9)
1039 "%s%s QUIT :Local kill by %s (Ghost: switched servers too fast)",
1040 NumNick(acptr), me.name);
1041 exit_client(cptr, acptr, &me, "Nick collision (You collided yourself)");
1043 if (lastnick == acptr->lastnick)
1051 #ifndef NO_PROTOCOL9
1052 const char *nnp9 = NULL; /* Init. to avoid compiler warning */
1055 /* A server introducing a new client, change source */
1058 #ifndef NO_PROTOCOL9
1060 * Numeric Nicks does, in contrast to all other protocol enhancements,
1061 * translation from protocol 9 -> protocol 10 !
1062 * The reason is that I just can't know what protocol it is when I
1063 * receive a "MODE #channel +o Run", because I can't 'find' "Run"
1064 * before I know the protocol, and I can't know the protocol if I
1065 * first have to find the server of "Run".
1066 * Therefore, in THIS case, the protocol is determined by the Connected
1069 if (Protocol(cptr) < 10 && !(nnp9 = CreateNNforProtocol9server(server)))
1070 return exit_client_msg(cptr, server, &me,
1071 "Too many clients (> %d) from P09 server (%s)", 64, server->name);
1073 sptr = make_client(cptr, STAT_UNKNOWN);
1074 sptr->hopcount = atoi(parv[2]);
1075 sptr->lastnick = atoi(parv[3]);
1076 if (Protocol(cptr) > 9 && parc > 7 && *parv[6] == '+')
1077 for (p = parv[6] + 1; *p; p++)
1078 for (s = user_modes; (flag = *s); s += 2)
1079 if (((char)*(s + 1)) == *p)
1081 sptr->flags |= flag;
1085 * Set new nick name.
1087 strcpy(sptr->name, nick);
1088 sptr->user = make_user(sptr);
1089 sptr->user->server = server;
1090 #ifndef NO_PROTOCOL9
1091 if (Protocol(cptr) < 10)
1093 if (!SetRemoteNumNick(sptr, nnp9))
1096 * if this fails squit the server and free the client
1099 return exit_client_msg(cptr, server, &me, "Invalid numeric index");
1101 sptr->ip.s_addr = 0;
1106 if (!SetRemoteNumNick(sptr, parv[parc - 2]))
1109 * if this fails squit the server and free the client
1112 return exit_client_msg(cptr, server, &me, "Invalid numeric index");
1114 sptr->ip.s_addr = htonl(base64toint(parv[parc - 3]));
1115 /* IP# of remote client */
1116 #ifndef NO_PROTOCOL9
1119 add_client_to_list(sptr);
1122 server->serv->ghost = 0; /* :server NICK means end of net.burst */
1123 strncpy(sptr->info, parv[parc - 1], sizeof(sptr->info) - 1);
1124 strncpy(sptr->user->host, parv[5], sizeof(sptr->user->host) - 1);
1125 return register_user(cptr, sptr, sptr->name, parv[4]);
1127 else if (sptr->name[0])
1130 * Client changing its nick
1132 * If the client belongs to me, then check to see
1133 * if client is on any channels where it is currently
1134 * banned. If so, do not allow the nick change to occur.
1138 for (lp = cptr->user->channel; lp; lp = lp->next)
1139 if (can_send(cptr, lp->value.chptr) == MODE_BAN)
1141 sendto_one(cptr, err_str(ERR_BANNICKCHANGE), me.name, parv[0],
1142 lp->value.chptr->chname);
1146 * Refuse nick change if the last nick change was less
1147 * then 30 seconds ago. This is intended to get rid of
1148 * clone bots doing NICK FLOOD. -SeKs
1149 * If someone didn't change their nick for more then 60 seconds
1150 * however, allow to do two nick changes immedately after another
1151 * before limiting the nick flood. -Run
1153 if (now < cptr->nextnick)
1155 cptr->nextnick += 2;
1156 sendto_one(cptr, err_str(ERR_NICKTOOFAST),
1157 me.name, parv[0], parv[1], cptr->nextnick - now);
1158 /* Send error message */
1159 sendto_prefix_one(cptr, cptr, ":%s NICK %s", parv[0], parv[0]);
1160 /* bounce NICK to user */
1161 return 0; /* ignore nick change! */
1165 /* Limit total to 1 change per NICK_DELAY seconds: */
1166 cptr->nextnick += NICK_DELAY;
1167 /* However allow _maximal_ 1 extra consecutive nick change: */
1168 if (cptr->nextnick < now)
1169 cptr->nextnick = now;
1173 * Also set 'lastnick' to current time, if changed.
1175 if (strCasediff(parv[0], nick))
1176 sptr->lastnick = (sptr == cptr) ? TStime() : atoi(parv[2]);
1179 * Client just changing his/her nick. If he/she is
1180 * on a channel, send note of change to all clients
1181 * on that channel. Propagate notice to other servers.
1185 sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick);
1186 add_history(sptr, 1);
1188 sendto_serv_butone(cptr,
1189 "%s%s NICK %s " TIME_T_FMT, NumNick(sptr), nick, sptr->lastnick);
1191 sendto_lowprot_butone(cptr, 9,
1192 ":%s NICK %s " TIME_T_FMT, parv[0], nick, sptr->lastnick);
1193 sendto_highprot_butone(cptr, 10,
1194 "%s%s NICK %s " TIME_T_FMT, NumNick(sptr), nick, sptr->lastnick);
1198 sendto_one(sptr, ":%s NICK :%s", parv[0], nick);
1201 strcpy(sptr->name, nick);
1206 /* Local client setting NICK the first time */
1208 strcpy(sptr->name, nick);
1211 sptr->user = make_user(sptr);
1212 sptr->user->server = &me;
1214 SetLocalNumNick(sptr);
1218 * If the client hasn't gotten a cookie-ping yet,
1219 * choose a cookie and send it. -record!jegelhof@cloud9.net
1224 sptr->cookie = (ircrandom() & 0x7fffffff);
1225 while (!sptr->cookie);
1226 sendto_one(cptr, "PING :%u", sptr->cookie);
1228 else if (*sptr->user->host && sptr->cookie == COOKIE_VERIFIED)
1231 * USER and PONG already received, now we have NICK.
1232 * register_user may reject the client and call exit_client
1233 * for it - must test this and exit m_nick too !
1235 sptr->lastnick = TStime(); /* Always local client */
1236 if (register_user(cptr, sptr, nick, sptr->user->username) == CPTR_KILLED)
1246 * sptr must be a local client!
1248 * Cannonifies target for client `sptr'.
1250 void add_target(aClient *sptr, void *target)
1252 register unsigned char *p;
1253 register unsigned int tmp = ((size_t)target & 0xffff00) >> 8;
1254 unsigned char hash = (tmp * tmp) >> 12;
1255 if (sptr->targets[0] == hash) /* Last person that we messaged ourself? */
1257 for (p = sptr->targets; p < &sptr->targets[MAXTARGETS - 1];)
1259 return; /* Already in table */
1262 memmove(&sptr->targets[RESERVEDTARGETS + 1],
1263 &sptr->targets[RESERVEDTARGETS], MAXTARGETS - RESERVEDTARGETS - 1);
1264 sptr->targets[RESERVEDTARGETS] = hash;
1269 * check_target_limit
1271 * sptr must be a local client !
1273 * Returns 'true' (1) when too many targets are addressed.
1274 * Returns 'false' (0) when it's ok to send to this target.
1276 int check_target_limit(aClient *sptr, void *target, const char *name,
1279 register unsigned char *p;
1280 register unsigned int tmp = ((size_t)target & 0xffff00) >> 8;
1281 unsigned char hash = (tmp * tmp) >> 12;
1282 if (sptr->targets[0] == hash) /* Same target as last time ? */
1284 for (p = sptr->targets; p < &sptr->targets[MAXTARGETS - 1];)
1287 memmove(&sptr->targets[1], &sptr->targets[0], p - sptr->targets);
1288 sptr->targets[0] = hash;
1295 if (now < sptr->nexttarget)
1297 if (sptr->nexttarget - now < TARGET_DELAY + 8) /* No server flooding */
1299 sptr->nexttarget += 2;
1300 sendto_one(sptr, err_str(ERR_TARGETTOOFAST),
1301 me.name, sptr->name, name, sptr->nexttarget - now);
1308 sendto_one(sptr, ":%s NOTICE %s :New target: %s; ft " TIME_T_FMT,
1309 me.name, sptr->name, name, (now - sptr->nexttarget) / TARGET_DELAY);
1311 sptr->nexttarget += TARGET_DELAY;
1312 if (sptr->nexttarget < now - (TARGET_DELAY * (MAXTARGETS - 1)))
1313 sptr->nexttarget = now - (TARGET_DELAY * (MAXTARGETS - 1));
1316 memmove(&sptr->targets[1], &sptr->targets[0], MAXTARGETS - 1);
1317 sptr->targets[0] = hash;
1322 * m_message (used in m_private() and m_notice())
1324 * The general function to deliver MSG's between users/channels
1326 * parv[0] = sender prefix
1327 * parv[1] = receiver list
1328 * parv[parc-1] = message text
1333 static int m_message(aClient *cptr, aClient *sptr,
1334 int parc, char *parv[], int notice)
1336 Reg1 aClient *acptr;
1339 char *nick, *server, *p, *cmd, *host;
1341 sptr->flags &= ~FLAGS_TS8;
1343 cmd = notice ? MSG_NOTICE : MSG_PRIVATE;
1345 if (parc < 2 || *parv[1] == '\0')
1347 sendto_one(sptr, err_str(ERR_NORECIPIENT), me.name, parv[0], cmd);
1351 if (parc < 3 || *parv[parc - 1] == '\0')
1353 sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
1358 parv[1] = canonize(parv[1]);
1359 for (p = NULL, nick = strtoken(&p, parv[1], ","); nick;
1360 nick = strtoken(&p, NULL, ","))
1365 if (IsChannelName(nick))
1367 if ((chptr = FindChannel(nick)))
1369 if (can_send(sptr, chptr) == 0 /* This first: Almost never a server/service */
1370 || IsChannelService(sptr) || IsServer(sptr))
1372 if (MyUser(sptr) && (chptr->mode.mode & MODE_NOPRIVMSGS) &&
1373 check_target_limit(sptr, chptr, chptr->chname, 0))
1375 sendto_channel_butone(cptr, sptr, chptr,
1376 ":%s %s %s :%s", parv[0], cmd, chptr->chname, parv[parc - 1]);
1379 sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN),
1380 me.name, parv[0], chptr->chname);
1384 else if (*nick != '$' && !strchr(nick, '@'))
1387 * nickname addressed?
1389 if (MyUser(sptr) || Protocol(cptr) < 10)
1390 acptr = FindUser(nick);
1391 else if ((acptr = findNUser(nick)) && !IsUser(acptr))
1395 if (MyUser(sptr) && check_target_limit(sptr, acptr, acptr->name, 0))
1397 if (!is_silenced(sptr, acptr))
1399 if (!notice && MyConnect(sptr) && acptr->user && acptr->user->away)
1400 sendto_one(sptr, rpl_str(RPL_AWAY),
1401 me.name, parv[0], acptr->name, acptr->user->away);
1402 if (MyUser(acptr) || Protocol(acptr->from) < 10)
1405 add_target(acptr, sptr);
1406 sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
1407 parv[0], cmd, acptr->name, parv[parc - 1]);
1410 sendto_prefix_one(acptr, sptr, ":%s %s %s%s :%s",
1411 parv[0], cmd, NumNick(acptr), parv[parc - 1]);
1414 else if (MyUser(sptr) || Protocol(cptr) < 10)
1415 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick);
1418 ":%s %d %s * :Target left UnderNet. Failed to deliver: [%.50s]",
1419 me.name, ERR_NOSUCHNICK, sptr->name, parv[parc - 1]);
1423 * The following two cases allow masks in NOTICEs
1426 * Armin, 8Jun90 (gruner@informatik.tu-muenchen.de)
1428 if ((*nick == '$' || *nick == '#') && IsAnOper(sptr))
1430 if (MyConnect(sptr))
1432 if (!(s = strrchr(nick, '.')))
1434 sendto_one(sptr, err_str(ERR_NOTOPLEVEL), me.name, parv[0], nick);
1438 if (*s == '.' || *s == '*' || *s == '?')
1440 if (*s == '*' || *s == '?')
1442 sendto_one(sptr, err_str(ERR_WILDTOPLEVEL), me.name, parv[0], nick);
1446 sendto_match_butone(IsServer(cptr) ? cptr : NULL,
1447 sptr, nick + 1, (*nick == '#') ? MATCH_HOST : MATCH_SERVER,
1448 ":%s %s %s :%s", parv[0], cmd, nick, parv[parc - 1]);
1451 else if ((server = strchr(nick, '@')) && (acptr = FindServer(server + 1)))
1454 * NICK[%host]@server addressed? See if <server> is me first
1458 sendto_one(acptr, ":%s %s %s :%s", parv[0], cmd, nick, parv[parc - 1]);
1462 /* Look for an user whose NICK is equal to <nick> and then
1463 * check if it's hostname matches <host> and if it's a local
1466 if ((host = strchr(nick, '%')))
1469 if ((!(acptr = FindUser(nick))) ||
1470 (!(MyUser(acptr))) ||
1471 ((!(BadPtr(host))) && match(host, acptr->user->host)))
1480 if (!(is_silenced(sptr, acptr)))
1481 sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
1482 parv[0], cmd, nick, parv[parc - 1]);
1486 if (IsChannelName(nick))
1487 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], nick);
1489 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick);
1497 * parv[0] = sender prefix
1498 * parv[1] = receiver list
1499 * parv[parc-1] = message text
1501 int m_private(aClient *cptr, aClient *sptr, int parc, char *parv[])
1503 return m_message(cptr, sptr, parc, parv, 0);
1509 * parv[0] = sender prefix
1510 * parv[1] = receiver list
1511 * parv[parc-1] = notice text
1513 int m_notice(aClient *cptr, aClient *sptr, int parc, char *parv[])
1515 if (MyUser(sptr) && parv[1] && parv[1][0] == '@' &&
1516 IsChannelName(&parv[1][1]))
1518 parv[1]++; /* Get rid of '@' */
1519 return m_wallchops(cptr, sptr, parc, parv);
1521 return m_message(cptr, sptr, parc, parv, 1);
1526 * whisper - called from m_cnotice and m_cprivmsg.
1528 * parv[0] = sender prefix
1530 * parv[2] = #channel
1531 * parv[3] = Private message text
1533 * Added 971023 by Run.
1534 * Reason: Allows channel operators to sent an arbitrary number of private
1535 * messages to users on their channel, avoiding the max.targets limit.
1536 * Building this into m_private would use too much cpu because we'd have
1537 * to a cross channel lookup for every private message!
1538 * Note that we can't allow non-chan ops to use this command, it would be
1539 * abused by mass advertisers.
1541 int whisper(aClient *sptr, int parc, char *parv[], int notice)
1543 int s_is_member = 0, s_is_voiced = 0, t_is_member = 0;
1550 if (parc < 4 || BadPtr(parv[3]))
1552 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
1553 me.name, parv[0], notice ? "CNOTICE" : "CPRIVMSG");
1556 if (!(chptr = FindChannel(parv[2])))
1558 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[2]);
1561 if (!(tcptr = FindUser(parv[1])))
1563 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
1566 for (lp = chptr->members; lp; lp = lp->next)
1568 register aClient *mcptr = lp->value.cptr;
1572 if ((lp->flags & (CHFL_CHANOP | CHFL_VOICE)))
1588 sendto_one(sptr, err_str(s_is_member ? ERR_VOICENEEDED : ERR_NOTONCHANNEL),
1589 me.name, parv[0], chptr->chname);
1594 sendto_one(sptr, err_str(ERR_USERNOTINCHANNEL),
1595 me.name, parv[0], tcptr->name, chptr->chname);
1598 if (is_silenced(sptr, tcptr))
1601 if (tcptr->user && tcptr->user->away)
1602 sendto_one(sptr, rpl_str(RPL_AWAY),
1603 me.name, parv[0], tcptr->name, tcptr->user->away);
1604 if (MyUser(tcptr) || Protocol(tcptr->from) < 10)
1605 sendto_prefix_one(tcptr, sptr, ":%s %s %s :%s",
1606 parv[0], notice ? "NOTICE" : "PRIVMSG", tcptr->name, parv[3]);
1608 sendto_prefix_one(tcptr, sptr, ":%s %s %s%s :%s",
1609 parv[0], notice ? "NOTICE" : "PRIVMSG", NumNick(tcptr), parv[3]);
1614 int m_cnotice(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
1616 return whisper(sptr, parc, parv, 1);
1619 int m_cprivmsg(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
1621 return whisper(sptr, parc, parv, 0);
1627 * parv[0] = sender prefix
1628 * parv[1] = target channel
1629 * parv[parc - 1] = wallchops text
1631 int m_wallchops(aClient *cptr, aClient *sptr, int parc, char *parv[])
1635 sptr->flags &= ~FLAGS_TS8;
1637 if (parc < 2 || *parv[1] == '\0')
1639 sendto_one(sptr, err_str(ERR_NORECIPIENT), me.name, parv[0], "WALLCHOPS");
1643 if (parc < 3 || *parv[parc - 1] == '\0')
1645 sendto_one(sptr, err_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
1650 parv[1] = canonize(parv[1]);
1652 if (IsChannelName(parv[1]))
1654 if ((chptr = FindChannel(parv[1])))
1656 if (can_send(sptr, chptr) == 0)
1658 if (MyUser(sptr) && (chptr->mode.mode & MODE_NOPRIVMSGS) &&
1659 check_target_limit(sptr, chptr, chptr->chname, 0))
1661 /* Send to local clients: */
1662 sendto_lchanops_butone(cptr, sptr, chptr,
1663 ":%s NOTICE @%s :%s", parv[0], parv[1], parv[parc - 1]);
1665 /* And to other servers: */
1666 sendto_chanopsserv_butone(cptr, sptr, chptr,
1667 ":%s WC %s :%s", parv[0], parv[1], parv[parc - 1]);
1670 * WARNING: `sendto_chanopsserv_butone' is heavily hacked when
1671 * `NO_PROTOCOL9' is not defined ! Therefore this is the ONLY
1672 * place you may use `sendto_chanopsserv_butone', until all
1675 sendto_chanopsserv_butone(cptr, sptr, chptr,
1676 ":%s WC %s :%s", parv[0], parv[1], parv[parc - 1]);
1680 sendto_one(sptr, err_str(ERR_CANNOTSENDTOCHAN),
1681 me.name, parv[0], parv[1]);
1685 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[1]);
1693 * parv[0] = sender prefix
1694 * parv[1] = username (login name, account)
1695 * parv[2] = umode mask
1696 * parv[3] = server notice mask
1697 * parv[4] = users real name info
1699 int m_user(aClient *cptr, aClient *sptr, int parc, char *parv[])
1701 #define UFLAGS (FLAGS_INVISIBLE|FLAGS_WALLOP|FLAGS_SERVNOTICE)
1702 char *username, *host, *server, *realname;
1708 if (IsServerPort(cptr))
1709 return exit_client(cptr, cptr, &me, "Use a different port");
1711 if (parc > 2 && (username = strchr(parv[1], '@')))
1713 if (parc < 5 || *parv[1] == '\0' || *parv[2] == '\0' ||
1714 *parv[3] == '\0' || *parv[4] == '\0')
1716 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "USER");
1720 /* Copy parameters into better documenting variables */
1722 username = (parc < 2 || BadPtr(parv[1])) ? "<bad-boy>" : parv[1];
1723 host = (parc < 3 || BadPtr(parv[2])) ? "<nohost>" : parv[2];
1724 server = (parc < 4 || BadPtr(parv[3])) ? "<noserver>" : parv[3];
1725 realname = (parc < 5 || BadPtr(parv[4])) ? "<bad-realname>" : parv[4];
1727 user = make_user(sptr);
1729 if (!IsUnknown(sptr))
1731 sendto_one(sptr, err_str(ERR_ALREADYREGISTRED), me.name, parv[0]);
1735 if (!strchr(host, '.')) /* Not an IP# as hostname ? */
1736 sptr->flags |= (UFLAGS & atoi(host));
1737 if ((sptr->flags & FLAGS_SERVNOTICE))
1738 set_snomask(sptr, (isDigit(*server) && !strchr(server, '.')) ?
1739 (atoi(server) & SNO_USER) : SNO_DEFAULT, SNO_SET);
1741 strncpy(sptr->info, realname, sizeof(sptr->info) - 1);
1742 if (sptr->name[0] && sptr->cookie == COOKIE_VERIFIED)
1743 /* NICK and PONG already received, now we have USER... */
1744 return register_user(cptr, sptr, sptr->name, username);
1747 strncpy(sptr->user->username, username, USERLEN);
1748 strncpy(user->host, host, sizeof(user->host) - 1);
1756 * parv[0] = sender prefix
1757 * parv[parc-1] = comment
1759 int m_quit(aClient *cptr, aClient *sptr, int parc, char *parv[])
1761 register char *comment = (parc > 1
1762 && parv[parc - 1]) ? parv[parc - 1] : cptr->name;
1766 if (!strncmp("Local Kill", comment, 10) || !strncmp(comment, "Killed", 6))
1771 for (lp = sptr->user->channel; lp; lp = lp->next)
1772 if (can_send(sptr, lp->value.chptr) != 0)
1773 return exit_client(cptr, sptr, sptr, "Signed off");
1776 if (strlen(comment) > (size_t)TOPICLEN)
1777 comment[TOPICLEN] = '\0';
1778 return IsServer(sptr) ? 0 : exit_client(cptr, sptr, sptr, comment);
1784 * parv[0] = sender prefix
1785 * parv[1] = kill victim
1786 * parv[parc-1] = kill path
1788 int m_kill(aClient *cptr, aClient *sptr, int parc, char *parv[])
1791 char *inpath = get_client_name(cptr, FALSE);
1792 char *user, *path, *killer;
1795 if (parc < 3 || *parv[1] == '\0')
1797 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "KILL");
1802 path = parv[parc - 1]; /* Either defined or NULL (parc >= 3) */
1805 if (!IsPrivileged(cptr))
1807 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
1811 if (!IsServer(cptr))
1813 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
1821 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "KILL");
1824 if (strlen(path) > (size_t)TOPICLEN)
1825 path[TOPICLEN] = '\0';
1828 if (MyUser(sptr) || Protocol(cptr) < 10)
1830 if (!(acptr = FindClient(user)))
1833 * If the user has recently changed nick, we automaticly
1834 * rewrite the KILL for this new nickname--this keeps
1835 * servers in synch when nick change and kill collide
1837 if (!(acptr = get_history(user, (long)15)))
1839 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], user);
1842 sendto_one(sptr, ":%s NOTICE %s :Changed KILL %s into %s",
1843 me.name, parv[0], user, acptr->name);
1847 else if (!(acptr = findNUser(user)))
1849 if (Protocol(cptr) < 10 && IsUser(sptr))
1851 ":%s NOTICE %s :KILL target disconnected before I got him :(",
1853 else if (IsUser(sptr))
1855 "%s NOTICE %s%s :KILL target disconnected before I got him :(",
1856 NumServ(&me), NumNick(sptr));
1859 if (!MyConnect(acptr) && IsLocOp(cptr))
1861 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
1864 if (IsServer(acptr) || IsMe(acptr))
1866 sendto_one(sptr, err_str(ERR_CANTKILLSERVER), me.name, parv[0]);
1870 /* if the user is +k, prevent a kill from local user */
1871 if (IsChannelService(acptr) && MyUser(sptr))
1873 sendto_one(sptr, err_str(ERR_ISCHANSERVICE), me.name,
1874 parv[0], "KILL", acptr->name);
1878 #ifdef LOCAL_KILL_ONLY
1879 if (MyConnect(sptr) && !MyConnect(acptr))
1881 sendto_one(sptr, ":%s NOTICE %s :Nick %s isnt on your server",
1882 me.name, parv[0], acptr->name);
1886 if (!IsServer(cptr))
1889 * The kill originates from this server, initialize path.
1890 * (In which case the 'path' may contain user suplied
1891 * explanation ...or some nasty comment, sigh... >;-)
1894 * ...!operhost!oper (comment)
1896 if (IsUnixSocket(cptr)) /* Don't use get_client_name syntax */
1897 inpath = me.sockhost;
1899 inpath = cptr->sockhost;
1903 "%s%s (%s)", cptr->name, IsOper(sptr) ? "" : "(L)", path);
1909 else if (BadPtr(path))
1910 path = "*no-path*"; /* Bogus server sending??? */
1912 * Notify all *local* opers about the KILL (this includes the one
1913 * originating the kill, if from this server--the special numeric
1914 * reply message is not generated anymore).
1916 * Note: "acptr->name" is used instead of "user" because we may
1917 * have changed the target because of the nickname change.
1919 if (IsLocOp(sptr) && !MyConnect(acptr))
1921 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
1924 sendto_op_mask(IsServer(sptr) ? SNO_SERVKILL : SNO_OPERKILL,
1925 "Received KILL message for %s. From %s Path: %s!%s",
1926 acptr->name, parv[0], inpath, path);
1927 #if defined(USE_SYSLOG) && defined(SYSLOG_KILL)
1929 { /* get more infos when your local
1930 clients are killed -- _dl */
1933 "A local client %s!%s@%s KILLED from %s [%s] Path: %s!%s)",
1934 acptr->name, acptr->user->username, acptr->user->host,
1935 parv[0], sptr->name, inpath, path);
1938 "A local client %s!%s@%s KILLED by %s [%s!%s@%s] (%s!%s)",
1939 acptr->name, acptr->user->username, acptr->user->host,
1940 parv[0], sptr->name, sptr->user->username, sptr->user->host,
1943 else if (IsOper(sptr))
1944 syslog(LOG_DEBUG, "KILL From %s For %s Path %s!%s",
1945 parv[0], acptr->name, inpath, path);
1948 * And pass on the message to other servers. Note, that if KILL
1949 * was changed, the message has to be sent to all links, also
1951 * Suicide kills are NOT passed on --SRB
1953 if (!MyConnect(acptr) || !MyConnect(sptr) || !IsAnOper(sptr))
1955 sendto_lowprot_butone(cptr, 9, ":%s KILL %s :%s!%s",
1956 parv[0], acptr->name, inpath, path);
1957 sendto_highprot_butone(cptr, 10, ":%s KILL %s%s :%s!%s",
1958 parv[0], NumNick(acptr), inpath, path);
1959 #ifndef NO_PROTOCOL9
1960 if (chasing && IsServer(cptr)) /* Can be removed when all are Protocol 10 */
1961 sendto_one(cptr, ":%s KILL %s :%s!%s",
1962 me.name, acptr->name, inpath, path);
1964 /* We *can* have crossed a NICK with this numeric... --Run */
1965 /* Note the following situation:
1967 * <-- S NICK ... SAA | <-- SAA QUIT <-- S NICK ... SAA <-- SQUIT S
1968 * Where the KILL reaches point X before the QUIT does.
1969 * This would then *still* cause an orphan because the KILL doesn't reach S
1970 * (because of the SQUIT), the QUIT is ignored (because of the KILL)
1971 * and the second NICK ... SAA causes an orphan on the server at the
1972 * right (which then isn't removed when the SQUIT arrives).
1973 * Therefore we still need to detect numeric nick collisions too.
1975 if (MyConnect(acptr) && IsServer(cptr) && Protocol(cptr) > 9)
1976 sendto_one(cptr, "%s KILL %s%s :%s!%s (Ghost5)",
1977 NumServ(&me), NumNick(acptr), inpath, path);
1978 acptr->flags |= FLAGS_KILLED;
1982 * Tell the victim she/he has been zapped, but *only* if
1983 * the victim is on current server--no sense in sending the
1984 * notification chasing the above kill, it won't get far
1985 * anyway (as this user don't exist there any more either)
1987 if (MyConnect(acptr))
1988 sendto_prefix_one(acptr, sptr, ":%s KILL %s :%s!%s",
1989 parv[0], acptr->name, inpath, path);
1991 * Set FLAGS_KILLED. This prevents exit_one_client from sending
1992 * the unnecessary QUIT for this. (This flag should never be
1993 * set in any other place)
1995 if (MyConnect(acptr) && MyConnect(sptr) && IsAnOper(sptr))
1996 sprintf_irc(buf2, "Local kill by %s (%s)", sptr->name,
1997 BadPtr(parv[parc - 1]) ? sptr->name : parv[parc - 1]);
2000 if ((killer = strchr(path, ' ')))
2002 while (*killer && *killer != '!')
2011 sprintf_irc(buf2, "Killed (%s)", killer);
2013 return exit_client(cptr, acptr, sptr, buf2);
2017 * m_away - Added 14 Dec 1988 by jto.
2019 * parv[0] = sender prefix
2020 * parv[1] = away message
2022 int m_away(aClient *cptr, aClient *sptr, int parc, char *parv[])
2024 Reg1 char *away, *awy2 = parv[1];
2026 away = sptr->user->away;
2028 if (parc < 2 || !*awy2)
2030 /* Marking as not away */
2034 sptr->user->away = NULL;
2036 sendto_serv_butone(cptr, ":%s AWAY", parv[0]);
2037 if (MyConnect(sptr))
2038 sendto_one(sptr, rpl_str(RPL_UNAWAY), me.name, parv[0]);
2042 /* Marking as away */
2044 if (strlen(awy2) > (size_t)TOPICLEN)
2045 awy2[TOPICLEN] = '\0';
2046 sendto_serv_butone(cptr, ":%s AWAY :%s", parv[0], awy2);
2049 away = (char *)RunRealloc(away, strlen(awy2) + 1);
2051 away = (char *)RunMalloc(strlen(awy2) + 1);
2053 sptr->user->away = away;
2055 if (MyConnect(sptr))
2056 sendto_one(sptr, rpl_str(RPL_NOWAWAY), me.name, parv[0]);
2063 * parv[0] = sender prefix
2065 * parv[2] = destination
2067 int m_ping(aClient *cptr, aClient *sptr, int parc, char *parv[])
2070 char *origin, *destination;
2072 if (parc < 2 || *parv[1] == '\0')
2074 sendto_one(sptr, err_str(ERR_NOORIGIN), me.name, parv[0]);
2078 destination = parv[2]; /* Will get NULL or pointer (parc >= 2!!) */
2080 acptr = FindClient(origin);
2081 if (acptr && acptr != sptr)
2082 origin = cptr->name;
2084 if (!BadPtr(destination) && strCasediff(destination, me.name) != 0)
2086 if ((acptr = FindServer(destination)))
2087 sendto_one(acptr, ":%s PING %s :%s", parv[0], origin, destination);
2090 sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
2091 me.name, parv[0], destination);
2096 sendto_one(sptr, ":%s PONG %s :%s", me.name, me.name, origin);
2103 * parv[0] = sender prefix
2105 * parv[2] = destination
2107 int m_pong(aClient *cptr, aClient *sptr, int parc, char *parv[])
2110 char *origin, *destination;
2115 /* Check to see if this is a PONG :cookie reply from an
2116 * unregistered user. If so, process it. -record */
2118 if ((!IsRegistered(sptr)) && (sptr->cookie != 0) &&
2119 (sptr->cookie != COOKIE_VERIFIED) && (parc > 1))
2121 if (atol(parv[parc - 1]) == (long)sptr->cookie)
2123 sptr->cookie = COOKIE_VERIFIED;
2124 if (sptr->user && *sptr->user->host && sptr->name[0]) /* NICK and
2126 return register_user(cptr, sptr, sptr->name, sptr->user->username);
2129 sendto_one(sptr, ":%s %d %s :To connect, type /QUOTE PONG %u",
2130 me.name, ERR_BADPING, sptr->name, sptr->cookie);
2135 if (parc < 2 || *parv[1] == '\0')
2137 sendto_one(sptr, err_str(ERR_NOORIGIN), me.name, parv[0]);
2142 destination = parv[2];
2143 cptr->flags &= ~FLAGS_PINGSENT;
2144 sptr->flags &= ~FLAGS_PINGSENT;
2146 if (!BadPtr(destination) && strCasediff(destination, me.name) != 0)
2148 if ((acptr = FindClient(destination)))
2149 sendto_one(acptr, ":%s PONG %s %s", parv[0], origin, destination);
2152 sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
2153 me.name, parv[0], destination);
2159 Debug((DEBUG_NOTICE, "PONG: %s %s",
2160 origin, destination ? destination : "*"));
2165 static char umode_buf[2 * sizeof(user_modes) / sizeof(int)];
2168 * added Sat Jul 25 07:30:42 EST 1992
2170 static void send_umode_out(aClient *cptr, aClient *sptr, int old)
2173 Reg2 aClient *acptr;
2175 send_umode(NULL, sptr, old, SEND_UMODES);
2177 for (i = highest_fd; i >= 0; i--)
2178 if ((acptr = loc_clients[i]) && IsServer(acptr) &&
2179 (acptr != cptr) && (acptr != sptr) && *umode_buf)
2180 sendto_one(acptr, ":%s MODE %s :%s", sptr->name, sptr->name, umode_buf);
2182 if (cptr && MyUser(cptr))
2183 send_umode(cptr, sptr, old, ALL_UMODES);
2188 * parv[0] = sender prefix
2189 * parv[1] = oper name
2190 * parv[2] = oper password
2192 int m_oper(aClient *cptr, aClient *sptr, int parc, char *parv[])
2195 char *name, *password, *encr;
2196 #ifdef CRYPT_OPER_PASSWORD
2198 #endif /* CRYPT_OPER_PASSWORD */
2200 name = parc > 1 ? parv[1] : NULL;
2201 password = parc > 2 ? parv[2] : NULL;
2203 if (!IsServer(cptr) && (BadPtr(name) || BadPtr(password)))
2205 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "OPER");
2209 /* if message arrived from server, trust it, and set to oper */
2211 if ((IsServer(cptr) || IsMe(cptr)) && !IsOper(sptr))
2214 sptr->flags |= FLAGS_OPER;
2215 sendto_serv_butone(cptr, ":%s MODE %s :+o", parv[0], parv[0]);
2217 sendto_one(sptr, rpl_str(RPL_YOUREOPER), me.name, parv[0]);
2220 else if (IsAnOper(sptr))
2222 if (MyConnect(sptr))
2223 sendto_one(sptr, rpl_str(RPL_YOUREOPER), me.name, parv[0]);
2226 if (!(aconf = find_conf_exact(name, sptr->username, sptr->sockhost,
2227 CONF_OPS)) && !(aconf = find_conf_exact(name, sptr->username,
2228 inetntoa(cptr->ip), CONF_OPS)))
2230 sendto_one(sptr, err_str(ERR_NOOPERHOST), me.name, parv[0]);
2231 sendto_realops("Failed OPER attempt by %s (%s@%s)",
2232 parv[0], sptr->user->username, sptr->sockhost);
2235 #ifdef CRYPT_OPER_PASSWORD
2236 /* use first two chars of the password they send in as salt */
2238 /* passwd may be NULL. Head it off at the pass... */
2240 if (password && aconf->passwd)
2242 salt[0] = aconf->passwd[0];
2243 salt[1] = aconf->passwd[1];
2245 encr = crypt(password, salt);
2251 #endif /* CRYPT_OPER_PASSWORD */
2253 if ((aconf->status & CONF_OPS) &&
2254 !strcmp(encr, aconf->passwd) && attach_conf(sptr, aconf) == ACR_OK)
2256 int old = (sptr->flags & ALL_UMODES);
2259 s = strchr(aconf->host, '@');
2262 if (aconf->status == CONF_LOCOP)
2265 if ((match(s, me.sockhost) && !IsLocal(sptr)) ||
2266 aconf->status == CONF_LOCOP)
2274 /* prevent someone from being both oper and local oper */
2280 sendto_ops("%s (%s@%s) is now operator (%c)", parv[0],
2281 sptr->user->username, sptr->sockhost, IsOper(sptr) ? 'O' : 'o');
2282 sptr->flags |= (FLAGS_WALLOP | FLAGS_SERVNOTICE | FLAGS_DEBUG);
2283 set_snomask(sptr, SNO_OPERDEFAULT, SNO_ADD);
2284 send_umode_out(cptr, sptr, old);
2285 sendto_one(sptr, rpl_str(RPL_YOUREOPER), me.name, parv[0]);
2286 #if !defined(CRYPT_OPER_PASSWORD) && (defined(FNAME_OPERLOG) ||\
2287 (defined(USE_SYSLOG) && defined(SYSLOG_OPER)))
2290 #if defined(USE_SYSLOG) && defined(SYSLOG_OPER)
2291 syslog(LOG_INFO, "OPER (%s) (%s) by (%s!%s@%s)",
2292 name, encr, parv[0], sptr->user->username, sptr->sockhost);
2294 #ifdef FNAME_OPERLOG
2296 write_log(FNAME_OPERLOG,
2297 "%s OPER (%s) (%s) by (%s!%s@%s)\n", myctime(now), name,
2298 encr, parv[0], sptr->user->username, sptr->sockhost);
2303 detach_conf(sptr, aconf);
2304 sendto_one(sptr, err_str(ERR_PASSWDMISMATCH), me.name, parv[0]);
2305 sendto_realops("Failed OPER attempt by %s (%s@%s)",
2306 parv[0], sptr->user->username, sptr->sockhost);
2314 * parv[0] = sender prefix
2315 * parv[1] = password
2317 int m_pass(aClient *cptr, aClient *sptr, int parc, char *parv[])
2319 char *password = parc > 1 ? parv[1] : NULL;
2321 if (BadPtr(password))
2323 sendto_one(cptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "PASS");
2326 if (!MyConnect(sptr) || (!IsUnknown(cptr) && !IsHandshake(cptr)))
2328 sendto_one(cptr, err_str(ERR_ALREADYREGISTRED), me.name, parv[0]);
2331 strncpy(cptr->passwd, password, sizeof(cptr->passwd) - 1);
2338 * Added by Darren Reed 13/8/91 to aid clients and reduce the need for
2339 * complicated requests like WHOIS.
2341 * Returns user/host information only (no spurious AWAY labels or channels).
2343 * Rewritten to speed it up by Carlo Wood 3/8/97.
2345 int m_userhost(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
2349 char *p = NULL, *sbuf;
2354 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "USERHOST");
2358 sbuf = sprintf_irc(sendbuf, rpl_str(RPL_USERHOST), me.name, parv[0]);
2359 for (i = j, s = strtoken(&p, parv[1], " "); i && s;
2360 s = strtoken(&p, (char *)NULL, " "), i--)
2361 if ((acptr = FindUser(s)))
2365 sbuf = sprintf_irc(sbuf, "%s%s=%c%s@%s", acptr->name,
2366 IsAnOper(acptr) ? "*" : "", (acptr->user->away) ? '-' : '+',
2367 acptr->user->username, acptr->user->host);
2372 sendbufto_one(sptr);
2373 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], s);
2374 sbuf = sprintf_irc(sendbuf, rpl_str(RPL_USERHOST), me.name, parv[0]);
2378 sendbufto_one(sptr);
2383 * m_userip added by Carlo Wood 3/8/97.
2385 * The same as USERHOST, but with the IP-number instead of the hostname.
2387 int m_userip(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
2391 char *p = NULL, *sbuf;
2396 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "USERIP");
2400 sbuf = sprintf_irc(sendbuf, rpl_str(RPL_USERIP), me.name, parv[0]);
2401 for (i = j, s = strtoken(&p, parv[1], " "); i && s;
2402 s = strtoken(&p, (char *)NULL, " "), i--)
2403 if ((acptr = FindUser(s)))
2407 sbuf = sprintf_irc(sbuf, "%s%s=%c%s@%s", acptr->name,
2408 IsAnOper(acptr) ? "*" : "", (acptr->user->away) ? '-' : '+',
2409 acptr->user->username, inetntoa(acptr->ip));
2414 sendbufto_one(sptr);
2415 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], s);
2416 sbuf = sprintf_irc(sendbuf, rpl_str(RPL_USERIP), me.name, parv[0]);
2420 sendbufto_one(sptr);
2427 * Added by Darren Reed 13/8/91 to act as an efficent user indicator
2428 * with respect to cpu/bandwidth used. Implemented for NOTIFY feature in
2429 * clients. Designed to reduce number of whois requests. Can process
2430 * nicknames in batches as long as the maximum buffer length.
2436 int m_ison(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
2438 Reg1 aClient *acptr;
2439 Reg2 char *s, **pav = parv;
2445 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "ISON");
2449 sprintf_irc(buf, rpl_str(RPL_ISON), me.name, *parv);
2451 buf[sizeof(buf) - 1] = 0;
2453 for (s = strtoken(&p, *++pav, " "); s; s = strtoken(&p, NULL, " "))
2454 if ((acptr = FindUser(s)))
2456 strncat(buf, acptr->name, sizeof(buf) - 1 - len);
2457 len += strlen(acptr->name);
2458 if (len >= sizeof(buf) - 1)
2463 sendto_one(sptr, "%s", buf);
2468 * m_umode() added 15/10/91 By Darren Reed.
2471 * parv[1] - username to change mode for
2472 * parv[2] - modes to change
2474 int m_umode(aClient *cptr, aClient *sptr, int parc, char *parv[])
2481 snomask_t tmpmask = 0;
2482 int snomask_given = 0;
2488 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "MODE");
2492 if (!(acptr = FindUser(parv[1])))
2494 if (MyConnect(sptr))
2495 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[1]);
2499 if (IsServer(sptr) || sptr != acptr)
2502 sendto_ops_butone(NULL, &me, ":%s WALLOPS :MODE for User %s From %s!%s",
2503 me.name, parv[1], get_client_name(cptr, FALSE), sptr->name);
2505 sendto_one(sptr, err_str(ERR_USERSDONTMATCH), me.name, parv[0]);
2513 for (s = user_modes; (flag = *s) && (m - buf < BUFSIZE - 4); s += 2)
2514 if (sptr->flags & flag)
2515 *m++ = (char)(*(s + 1));
2517 sendto_one(sptr, rpl_str(RPL_UMODEIS), me.name, parv[0], buf);
2518 if ((sptr->flags & FLAGS_SERVNOTICE) && MyConnect(sptr)
2520 (unsigned int)(IsOper(sptr) ? SNO_OPERDEFAULT : SNO_DEFAULT))
2521 sendto_one(sptr, rpl_str(RPL_SNOMASK), me.name, parv[0], sptr->snomask,
2526 /* find flags already set for user */
2528 for (s = user_modes; (flag = *s); s += 2)
2529 if (sptr->flags & flag)
2531 if (MyConnect(sptr))
2532 tmpmask = sptr->snomask;
2535 * parse mode change string(s)
2537 for (p = &parv[2]; *p; p++) /* p is changed in loop too */
2538 for (m = *p; *m; m++)
2548 if (*(p + 1) && is_snomask(*(p + 1)))
2551 tmpmask = umode_make_snomask(tmpmask, *++p, what);
2552 tmpmask &= (IsAnOper(sptr) ? SNO_ALL : SNO_USER);
2555 tmpmask = (what == MODE_ADD) ?
2556 (IsAnOper(sptr) ? SNO_OPERDEFAULT : SNO_DEFAULT) : 0;
2558 sptr->flags |= FLAGS_SERVNOTICE;
2560 sptr->flags &= ~FLAGS_SERVNOTICE;
2563 * We may not get these, but they shouldnt be in default:
2571 for (s = user_modes; (flag = *s); s += 2)
2572 if (*m == (char)(*(s + 1)))
2574 if (what == MODE_ADD)
2575 sptr->flags |= flag;
2576 else if ((flag & (FLAGS_OPER | FLAGS_LOCOP)))
2578 sptr->flags &= ~(FLAGS_OPER | FLAGS_LOCOP);
2579 if (MyConnect(sptr))
2580 tmpmask = sptr->snomask & ~SNO_OPER;
2582 /* allow either -o or -O to reset all operator status's... */
2584 sptr->flags &= ~flag;
2587 if (flag == 0 && MyConnect(sptr))
2588 sendto_one(sptr, err_str(ERR_UMODEUNKNOWNFLAG), me.name, parv[0]);
2592 * Stop users making themselves operators too easily:
2594 if (!(setflags & FLAGS_OPER) && IsOper(sptr) && !IsServer(cptr))
2596 if (!(setflags & FLAGS_LOCOP) && IsLocOp(sptr) && !IsServer(cptr))
2597 sptr->flags &= ~FLAGS_LOCOP;
2598 if ((setflags & (FLAGS_OPER | FLAGS_LOCOP)) && !IsAnOper(sptr) &&
2600 det_confs_butmask(sptr, CONF_CLIENT & ~CONF_OPS);
2601 /* new umode; servers can set it, local users cannot;
2602 * prevents users from /kick'ing or /mode -o'ing */
2603 if (!(setflags & FLAGS_CHSERV) && !IsServer(cptr))
2604 sptr->flags &= ~FLAGS_CHSERV;
2606 * Compare new flags with old flags and send string which
2607 * will cause servers to update correctly.
2609 if ((setflags & FLAGS_OPER) && !IsOper(sptr))
2611 if (!(setflags & FLAGS_OPER) && IsOper(sptr))
2613 if ((setflags & FLAGS_INVISIBLE) && !IsInvisible(sptr))
2615 if (!(setflags & FLAGS_INVISIBLE) && IsInvisible(sptr))
2617 send_umode_out(cptr, sptr, setflags);
2619 if (MyConnect(sptr))
2621 if (tmpmask != sptr->snomask)
2622 set_snomask(sptr, tmpmask, SNO_SET);
2623 if (sptr->snomask && snomask_given)
2624 sendto_one(sptr, rpl_str(RPL_SNOMASK), me.name, sptr->name,
2625 sptr->snomask, sptr->snomask);
2632 * Build umode string for BURST command
2635 char *umode_str(aClient *cptr)
2637 char *m = umode_buf; /* Maximum string size: "owidg\0" */
2638 int *s, flag, c_flags;
2640 c_flags = cptr->flags & SEND_UMODES; /* cleaning up the original code */
2642 for (s = user_modes; (flag = *s); s += 2)
2643 if ((c_flags & flag))
2647 return umode_buf; /* Note: static buffer, gets
2648 overwritten by send_umode() */
2652 * Send the MODE string for user (user) to connection cptr
2655 void send_umode(aClient *cptr, aClient *sptr, int old, int sendmask)
2659 int what = MODE_NULL;
2662 * Build a string in umode_buf to represent the change in the user's
2663 * mode between the new (sptr->flag) and 'old'.
2667 for (s = user_modes; (flag = *s); s += 2)
2669 if (MyUser(sptr) && !(flag & sendmask))
2671 if ((flag & old) && !(sptr->flags & flag))
2673 if (what == MODE_DEL)
2682 else if (!(flag & old) && (sptr->flags & flag))
2684 if (what == MODE_ADD)
2695 if (*umode_buf && cptr)
2696 sendto_one(cptr, ":%s MODE %s :%s", sptr->name, sptr->name, umode_buf);
2700 * Check to see if this resembles a sno_mask. It is if 1) there is
2701 * at least one digit and 2) The first digit occurs before the first
2702 * alphabetic character.
2704 int is_snomask(char *word)
2708 for (; *word; word++)
2711 else if (isAlpha(*word))
2718 * If it begins with a +, count this as an additive mask instead of just
2719 * a replacement. If what == MODE_DEL, "+" has no special effect.
2721 snomask_t umode_make_snomask(snomask_t oldmask, char *arg, int what)
2728 if (what == MODE_ADD)
2733 else if (*arg == '-')
2736 if (what == MODE_ADD)
2742 sno_what = (what == MODE_ADD) ? SNO_SET : SNO_DEL;
2743 /* pity we don't have strtoul everywhere */
2744 newmask = (snomask_t)atoi(arg);
2745 if (sno_what == SNO_DEL)
2746 newmask = oldmask & ~newmask;
2747 else if (sno_what == SNO_ADD)
2753 * This function sets a Client's server notices mask, according to
2754 * the parameter 'what'. This could be even faster, but the code
2755 * gets mighty hard to read :)
2757 void delfrom_list(aClient *, Link **);
2758 void set_snomask(aClient *cptr, snomask_t newmask, int what)
2760 snomask_t oldmask, diffmask; /* unsigned please */
2764 oldmask = cptr->snomask;
2766 if (what == SNO_ADD)
2768 else if (what == SNO_DEL)
2769 newmask = oldmask & ~newmask;
2770 else if (what != SNO_SET) /* absolute set, no math needed */
2771 sendto_ops("setsnomask called with %d ?!", what);
2773 newmask &= (IsAnOper(cptr) ? SNO_ALL : SNO_USER);
2775 diffmask = oldmask ^ newmask;
2777 for (i = 0; diffmask >> i; i++)
2778 if (((diffmask >> i) & 1))
2780 if (((newmask >> i) & 1))
2783 tmp->next = opsarray[i];
2784 tmp->value.cptr = cptr;
2788 /* not real portable :( */
2789 delfrom_list(cptr, &opsarray[i]);
2791 cptr->snomask = newmask;
2794 void delfrom_list(aClient *cptr, Link **list)
2796 Link *tmp, *prv = NULL;
2797 for (tmp = *list; tmp; tmp = tmp->next)
2799 if (tmp->value.cptr == cptr)
2802 prv->next = tmp->next;
2813 * is_silenced : Does the actual check wether sptr is allowed
2814 * to send a message to acptr.
2815 * Both must be registered persons.
2816 * If sptr is silenced by acptr, his message should not be propagated,
2817 * but more over, if this is detected on a server not local to sptr
2818 * the SILENCE mask is sent upstream.
2820 int is_silenced(aClient *sptr, aClient *acptr)
2824 static char sender[HOSTLEN + NICKLEN + USERLEN + 5];
2825 static char senderip[16 + NICKLEN + USERLEN + 5];
2827 if (!(acptr->user) || !(lp = acptr->user->silence) || !(user = sptr->user))
2829 sprintf_irc(sender, "%s!%s@%s", sptr->name, user->username, user->host);
2830 sprintf_irc(senderip, "%s!%s@%s", sptr->name, user->username,
2831 inetntoa(sptr->ip));
2832 for (; lp; lp = lp->next)
2834 if ((!(lp->flags & CHFL_SILENCE_IPMASK) && !match(lp->value.cp, sender)) ||
2835 ((lp->flags & CHFL_SILENCE_IPMASK) && !match(lp->value.cp, senderip)))
2837 if (!MyConnect(sptr))
2839 if (Protocol(sptr->from) < 10)
2840 sendto_one(sptr->from, ":%s SILENCE %s %s", acptr->name,
2841 sptr->name, lp->value.cp);
2843 sendto_one(sptr->from, ":%s SILENCE %s%s %s", acptr->name,
2844 NumNick(sptr), lp->value.cp);
2855 * Removes all silence masks from the list of sptr that fall within `mask'
2856 * Returns -1 if none where found, 0 otherwise.
2858 int del_silence(aClient *sptr, char *mask)
2864 for (lp = &sptr->user->silence; *lp;)
2865 if (!mmatch(mask, (*lp)->value.cp))
2869 RunFree(tmp->value.cp);
2879 static int add_silence(aClient *sptr, char *mask)
2881 Reg1 Link *lp, **lpp;
2882 Reg3 int cnt = 0, len = strlen(mask);
2885 for (lpp = &sptr->user->silence, lp = *lpp; lp;)
2887 if (!strCasediff(mask, lp->value.cp))
2889 if (!mmatch(mask, lp->value.cp))
2892 *lpp = lp = lp->next;
2893 RunFree(tmp->value.cp);
2899 len += strlen(lp->value.cp);
2900 if ((len > MAXSILELENGTH) || (++cnt >= MAXSILES))
2902 sendto_one(sptr, err_str(ERR_SILELISTFULL), me.name, sptr->name, mask);
2905 else if (!mmatch(lp->value.cp, mask))
2912 memset(lp, 0, sizeof(Link));
2913 lp->next = sptr->user->silence;
2914 lp->value.cp = (char *)RunMalloc(strlen(mask) + 1);
2915 strcpy(lp->value.cp, mask);
2916 if ((ip_start = strrchr(mask, '@')) && check_if_ipmask(ip_start + 1))
2917 lp->flags = CHFL_SILENCE_IPMASK;
2918 sptr->user->silence = lp;
2923 * m_silence() - Added 19 May 1994 by Run.
2925 * parv[0] = sender prefix
2926 * From local client:
2927 * parv[1] = mask (NULL sends the list)
2928 * From remote client:
2929 * parv[1] = Numeric nick that must be silenced
2932 int m_silence(aClient *cptr, aClient *sptr, int parc, char *parv[])
2941 if (parc < 2 || *parv[1] == '\0' || (acptr = FindUser(parv[1])))
2945 for (lp = acptr->user->silence; lp; lp = lp->next)
2946 sendto_one(sptr, rpl_str(RPL_SILELIST), me.name,
2947 sptr->name, acptr->name, lp->value.cp);
2948 sendto_one(sptr, rpl_str(RPL_ENDOFSILELIST), me.name, sptr->name,
2954 if (c == '-' || c == '+')
2956 else if (!(strchr(cp, '@') || strchr(cp, '.') ||
2957 strchr(cp, '!') || strchr(cp, '*')))
2959 sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
2964 cp = pretty_mask(cp);
2965 if ((c == '-' && !del_silence(sptr, cp)) ||
2966 (c != '-' && !add_silence(sptr, cp)))
2968 sendto_prefix_one(sptr, sptr, ":%s SILENCE %c%s", parv[0], c, cp);
2970 sendto_serv_butone(NULL, ":%s SILENCE * -%s", sptr->name, cp);
2973 else if (parc < 3 || *parv[2] == '\0')
2975 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SILENCE");
2980 if (Protocol(cptr) < 10)
2981 acptr = FindClient(parv[1]); /* In case of NOTE notice, parv[1] */
2982 else if (parv[1][1]) /* can be a server */
2983 acptr = findNUser(parv[1]);
2985 acptr = FindNServer(parv[1]);
2987 if (*parv[2] == '-')
2989 if (!del_silence(sptr, parv[2] + 1))
2990 sendto_serv_butone(cptr, ":%s SILENCE * %s", parv[0], parv[2]);
2994 add_silence(sptr, parv[2]);
2995 if (acptr && IsServer(acptr->from))
2997 if (Protocol(acptr->from) < 10)
2998 sendto_one(acptr, ":%s SILENCE %s %s", parv[0], acptr->name, parv[2]);
2999 else if (IsServer(acptr))
3000 sendto_one(acptr, ":%s SILENCE %s %s",
3001 parv[0], NumServ(acptr), parv[2]);
3003 sendto_one(acptr, ":%s SILENCE %s%s %s",
3004 parv[0], NumNick(acptr), parv[2]);