2 * ircd-ratbox: A slightly useful ircd.
3 * s_user.c: User related functions.
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
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 2 of the License, or
12 * (at your option) any later version.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24 * $Id: s_user.c 23955 2007-05-14 17:22:36Z leeh $
35 #include "irc_string.h"
36 #include "sprintf_irc.h"
43 #include "s_newconf.h"
49 #include "supported.h"
58 static void report_and_set_user_flags(struct Client *, struct ConfItem *);
59 void user_welcome(struct Client *source_p);
63 /* table of ascii char letters to corresponding bitmask */
72 static struct flag_item user_modes[] = {
76 {UMODE_CCONNEXT, 'C'},
80 {UMODE_CALLERID, 'g'},
81 {UMODE_INVISIBLE, 'i'},
87 {UMODE_SERVNOTICE, 's'},
88 #ifdef ENABLE_SERVICES
93 {UMODE_EXTERNAL, 'x'},
95 {UMODE_OPERWALL, 'z'},
100 /* memory is cheap. map 0-255 to equivalent mode */
101 int user_modes_from_c_to_bitmask[] = {
102 /* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0F */
103 /* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1F */
104 /* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x2F */
105 /* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x3F */
109 UMODE_CCONNEXT, /* C */
125 #ifdef ENABLE_SERVICES
126 UMODE_SERVICE, /* S */
136 UMODE_OPERSPY, /* Z */
137 /* 0x5B */ 0, 0, 0, 0, 0, 0, /* 0x60 */
144 UMODE_CALLERID, /* g */
146 UMODE_INVISIBLE, /* i */
149 UMODE_LOCOPS, /* l */
151 UMODE_NCHANGE, /* n */
156 UMODE_SERVNOTICE, /* s */
158 UMODE_UNAUTH, /* u */
160 UMODE_WALLOP, /* w */
161 UMODE_EXTERNAL, /* x */
163 UMODE_OPERWALL, /* z */
164 /* 0x7B */ 0, 0, 0, 0, 0, /* 0x7F */
165 /* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9F */
166 /* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9F */
167 /* 0xA0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xAF */
168 /* 0xB0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xBF */
169 /* 0xC0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xCF */
170 /* 0xD0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xDF */
171 /* 0xE0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xEF */
172 /* 0xF0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xFF */
179 * inputs - pointer to client
181 * side effects - display to client user counts etc.
184 show_lusers(struct Client *source_p)
186 sendto_one_numeric(source_p, RPL_LUSERCLIENT, form_str(RPL_LUSERCLIENT),
187 (Count.total - Count.invisi),
188 Count.invisi, dlink_list_length(&global_serv_list));
191 sendto_one_numeric(source_p, RPL_LUSEROP,
192 form_str(RPL_LUSEROP), Count.oper);
194 if(dlink_list_length(&unknown_list) > 0)
195 sendto_one_numeric(source_p, RPL_LUSERUNKNOWN,
196 form_str(RPL_LUSERUNKNOWN),
197 dlink_list_length(&unknown_list));
199 if(dlink_list_length(&global_channel_list) > 0)
200 sendto_one_numeric(source_p, RPL_LUSERCHANNELS,
201 form_str(RPL_LUSERCHANNELS),
202 dlink_list_length(&global_channel_list));
204 sendto_one_numeric(source_p, RPL_LUSERME, form_str(RPL_LUSERME),
205 dlink_list_length(&lclient_list),
206 dlink_list_length(&serv_list));
208 sendto_one_numeric(source_p, RPL_LOCALUSERS,
209 form_str(RPL_LOCALUSERS),
210 dlink_list_length(&lclient_list),
212 dlink_list_length(&lclient_list),
215 sendto_one_numeric(source_p, RPL_GLOBALUSERS, form_str(RPL_GLOBALUSERS),
216 Count.total, Count.max_tot,
217 Count.total, Count.max_tot);
219 sendto_one_numeric(source_p, RPL_STATSCONN,
220 form_str(RPL_STATSCONN),
221 MaxConnectionCount, MaxClientCount,
222 Count.totalrestartcount);
224 if(dlink_list_length(&lclient_list) > (unsigned long)MaxClientCount)
225 MaxClientCount = dlink_list_length(&lclient_list);
227 if((dlink_list_length(&lclient_list) + dlink_list_length(&serv_list)) >
228 (unsigned long)MaxConnectionCount)
229 MaxConnectionCount = dlink_list_length(&lclient_list) +
230 dlink_list_length(&serv_list);
238 * inputs - pointer to client
240 * side effects - display to client what we support (for them)
243 show_isupport(struct Client *source_p)
245 char isupportbuffer[512];
247 ircsprintf(isupportbuffer, FEATURES, FEATURESVALUES);
248 sendto_one_numeric(source_p, RPL_ISUPPORT, form_str(RPL_ISUPPORT), isupportbuffer);
250 ircsprintf(isupportbuffer, FEATURES2, FEATURES2VALUES);
251 sendto_one_numeric(source_p, RPL_ISUPPORT, form_str(RPL_ISUPPORT), isupportbuffer);
253 ircsprintf(isupportbuffer, FEATURES3, FEATURES3VALUES);
254 sendto_one_numeric(source_p, RPL_ISUPPORT, form_str(RPL_ISUPPORT), isupportbuffer);
261 ** register_local_user
262 ** This function is called when both NICK and USER messages
263 ** have been accepted for the client, in whatever order. Only
264 ** after this, is the USER message propagated.
266 ** NICK's must be propagated at once when received, although
267 ** it would be better to delay them too until full info is
268 ** available. Doing it is not so simple though, would have
269 ** to implement the following:
271 ** (actually it has been implemented already for a while) -orabidoo
273 ** 1) user telnets in and gives only "NICK foobar" and waits
274 ** 2) another user far away logs in normally with the nick
275 ** "foobar" (quite legal, as this server didn't propagate
277 ** 3) now this server gets nick "foobar" from outside, but
278 ** has alread the same defined locally. Current server
279 ** would just issue "KILL foobar" to clean out dups. But,
280 ** this is not fair. It should actually request another
281 ** nick from local user or kill him/her...
285 register_local_user(struct Client *client_p, struct Client *source_p, const char *username)
287 struct ConfItem *aconf;
288 struct User *user = source_p->user;
289 char tmpstr2[IRCD_BUFSIZE];
290 char ipaddr[HOSTIPLEN];
291 char myusername[USERLEN+1];
294 s_assert(NULL != source_p);
295 s_assert(MyConnect(source_p));
296 s_assert(source_p->username != username);
301 if(IsAnyDead(source_p))
304 if(ConfigFileEntry.ping_cookie)
306 if(!(source_p->flags & FLAGS_PINGSENT) && source_p->localClient->random_ping == 0)
308 source_p->localClient->random_ping = (unsigned long) (rand() * rand()) << 1;
309 sendto_one(source_p, "PING :%08lX",
310 (unsigned long) source_p->localClient->random_ping);
311 source_p->flags |= FLAGS_PINGSENT;
314 if(!(source_p->flags2 & FLAGS2_PING_COOKIE))
320 /* hasnt finished client cap negotiation */
321 if(source_p->flags2 & FLAGS2_CLICAP)
324 client_p->localClient->last = CurrentTime;
325 /* Straight up the maximum rate of flooding... */
326 source_p->localClient->allow_read = MAX_FLOOD_BURST;
328 /* XXX - fixme. we shouldnt have to build a users buffer twice.. */
329 if(!IsGotId(source_p) && (strchr(username, '[') != NULL))
336 while(*p && i < USERLEN)
339 myusername[i++] = *p;
343 myusername[i] = '\0';
344 username = myusername;
347 if((status = check_client(client_p, source_p, username)) < 0)
348 return (CLIENT_EXITED);
350 if(!valid_hostname(source_p->host))
353 ":%s NOTICE %s :*** Notice -- You have an illegal character in your hostname",
354 me.name, source_p->name);
356 strlcpy(source_p->host, source_p->sockhost, sizeof(source_p->host));
359 if(ConfigFileEntry.dot_in_ip6_addr == 1)
360 strlcat(source_p->host, ".", sizeof(source_p->host));
365 aconf = source_p->localClient->att_conf;
369 exit_client(client_p, source_p, &me, "*** Not Authorised");
370 return (CLIENT_EXITED);
373 if(!IsGotId(source_p))
378 if(IsNeedIdentd(aconf))
380 ServerStats->is_ref++;
382 ":%s NOTICE %s :*** Notice -- You need to install identd to use this server",
383 me.name, client_p->name);
384 exit_client(client_p, source_p, &me, "Install identd");
385 return (CLIENT_EXITED);
388 /* dont replace username if its supposed to be spoofed --fl */
389 if(!IsConfDoSpoofIp(aconf) || !strchr(aconf->name, '@'))
393 if(!IsNoTilde(aconf))
394 source_p->username[i++] = '~';
396 while (*p && i < USERLEN)
399 source_p->username[i++] = *p;
403 source_p->username[i] = '\0';
408 if(!EmptyString(aconf->passwd))
412 if(EmptyString(source_p->localClient->passwd))
414 else if(IsConfEncrypted(aconf))
415 encr = crypt(source_p->localClient->passwd, aconf->passwd);
417 encr = source_p->localClient->passwd;
419 if(strcmp(encr, aconf->passwd))
421 ServerStats->is_ref++;
422 sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name);
423 exit_client(client_p, source_p, &me, "Bad Password");
424 return (CLIENT_EXITED);
428 if(source_p->localClient->passwd)
430 memset(source_p->localClient->passwd, 0, strlen(source_p->localClient->passwd));
431 MyFree(source_p->localClient->passwd);
432 source_p->localClient->passwd = NULL;
435 /* report if user has &^>= etc. and set flags as needed in source_p */
436 report_and_set_user_flags(source_p, aconf);
440 * We want to be able to have servers and F-line clients
441 * connect, so save room for "buffer" connections.
442 * Smaller servers may want to decrease this, and it should
443 * probably be just a percentage of the MAXCLIENTS...
446 /* Except "F:" clients */
447 if(((dlink_list_length(&lclient_list) + 1) >=
448 ((unsigned long)GlobalSetOptions.maxclients + MAX_BUFFER) ||
449 (dlink_list_length(&lclient_list) + 1) >=
450 ((unsigned long)GlobalSetOptions.maxclients - 5)) && !(IsExemptLimits(source_p)))
452 sendto_realops_flags(UMODE_FULL, L_ALL,
453 "Too many clients, rejecting %s[%s].", source_p->name, source_p->host);
455 ServerStats->is_ref++;
456 exit_client(client_p, source_p, &me, "Sorry, server is full - try later");
457 return (CLIENT_EXITED);
460 /* valid user name check */
462 if(!valid_username(source_p->username))
464 sendto_realops_flags(UMODE_REJ, L_ALL,
465 "Invalid username: %s (%s@%s)",
466 source_p->name, source_p->username, source_p->host);
467 ServerStats->is_ref++;
468 ircsprintf(tmpstr2, "Invalid username [%s]", source_p->username);
469 exit_client(client_p, source_p, &me, tmpstr2);
470 return (CLIENT_EXITED);
473 /* end of valid user name check */
475 /* kline exemption extends to xline too */
476 if(!IsExemptKline(source_p) &&
477 find_xline(source_p->info, 1) != NULL)
479 ServerStats->is_ref++;
480 add_reject(source_p);
481 exit_client(client_p, source_p, &me, "Bad user info");
482 return CLIENT_EXITED;
485 if(IsAnyDead(client_p))
486 return CLIENT_EXITED;
488 inetntop_sock((struct sockaddr *)&source_p->localClient->ip, ipaddr, sizeof(ipaddr));
490 sendto_realops_flags(UMODE_CCONN, L_ALL,
491 "Client connecting: %s (%s@%s) [%s] {%s} [%s]",
492 source_p->name, source_p->username, source_p->host,
493 show_ip(NULL, source_p) ? ipaddr : "255.255.255.255",
494 get_client_class(source_p), source_p->info);
496 sendto_realops_flags(UMODE_CCONNEXT, L_ALL,
497 "CLICONN %s %s %s %s %s %s 0 %s",
498 source_p->name, source_p->username, source_p->host,
499 show_ip(NULL, source_p) ? ipaddr : "255.255.255.255",
500 get_client_class(source_p),
501 /* mirc can sometimes send ips here */
502 show_ip(NULL, source_p) ? source_p->localClient->fullcaps :
506 /* If they have died in send_* don't do anything. */
507 if(IsAnyDead(source_p))
508 return CLIENT_EXITED;
510 add_to_hostname_hash(source_p->host, source_p);
512 strcpy(source_p->id, generate_uid());
513 add_to_id_hash(source_p->id, source_p);
515 if(ConfigFileEntry.default_invisible)
517 source_p->umodes |= UMODE_INVISIBLE;
521 s_assert(!IsClient(source_p));
522 del_unknown_ip(source_p);
523 dlinkMoveNode(&source_p->localClient->tnode, &unknown_list, &lclient_list);
526 /* XXX source_p->servptr is &me, since local client */
527 /* NO SHIT!^*($^, so lets not use the below. --fl */
528 /* source_p->servptr = find_server(NULL, user->server); */
529 source_p->servptr = &me;
531 dlinkAdd(source_p, &source_p->lnode, &source_p->servptr->serv->users);
532 /* Increment our total user count here */
533 if(++Count.total > Count.max_tot)
534 Count.max_tot = Count.total;
535 source_p->localClient->allow_read = MAX_FLOOD_BURST;
537 Count.totalrestartcount++;
539 s_assert(source_p->localClient != NULL);
541 if(dlink_list_length(&lclient_list) > (unsigned long)Count.max_loc)
543 Count.max_loc = dlink_list_length(&lclient_list);
544 if(!(Count.max_loc % 10))
545 sendto_realops_flags(UMODE_ALL, L_ALL,
546 "New Max Local Clients: %d", Count.max_loc);
549 /* they get a reduced limit */
550 if(find_tgchange(source_p->sockhost))
551 USED_TARGETS(source_p) = 6;
553 monitor_signon(source_p);
554 user_welcome(source_p);
555 return (introduce_client(client_p, source_p, user, source_p->name));
563 * side effects - This common function introduces a client to the rest
564 * of the net, either from a local client connect or
565 * from a remote connect.
568 introduce_client(struct Client *client_p, struct Client *source_p, struct User *user, const char *nick)
570 static char ubuf[12];
572 if(MyClient(source_p))
573 send_umode(source_p, source_p, 0, SEND_UMODES, ubuf);
575 send_umode(NULL, source_p, 0, SEND_UMODES, ubuf);
583 /* if it has an ID, introduce it with its id to TS6 servers,
584 * otherwise introduce it normally to all.
588 char sockhost[HOSTLEN];
589 if(source_p->sockhost[0] == ':')
593 strlcat(sockhost, source_p->sockhost, sizeof(sockhost));
595 strcpy(sockhost, source_p->sockhost);
597 sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
598 ":%s UID %s %d %ld %s %s %s %s %s :%s",
599 source_p->servptr->id, nick,
600 source_p->hopcount + 1,
601 (long) source_p->tsinfo, ubuf,
602 source_p->username, source_p->host,
603 IsIPSpoof(source_p) ? "0" : sockhost,
604 source_p->id, source_p->info);
606 sendto_server(client_p, NULL, NOCAPS, CAP_TS6,
607 "NICK %s %d %ld %s %s %s %s :%s",
608 nick, source_p->hopcount + 1,
609 (long) source_p->tsinfo,
610 ubuf, source_p->username, source_p->host,
611 source_p->servptr->name, source_p->info);
614 sendto_server(client_p, NULL, NOCAPS, NOCAPS,
615 "NICK %s %d %ld %s %s %s %s :%s",
616 nick, source_p->hopcount + 1,
617 (long) source_p->tsinfo,
618 ubuf, source_p->username, source_p->host,
619 source_p->servptr->name, source_p->info);
626 * valid_hostname - check hostname for validity
628 * Inputs - pointer to user
629 * Output - YES if valid, NO if not
630 * Side effects - NONE
632 * NOTE: this doesn't allow a hostname to begin with a dot and
633 * will not allow more dots than chars.
636 valid_hostname(const char *hostname)
638 const char *p = hostname;
646 if('.' == *p || ':' == *p)
653 if(*p == '.' || *p == ':')
665 * valid_username - check username for validity
667 * Inputs - pointer to user
668 * Output - YES if valid, NO if not
669 * Side effects - NONE
671 * Absolutely always reject any '*' '!' '?' '@' in an user name
672 * reject any odd control characters names.
673 * Allow '.' in username to allow for "first.last"
677 valid_username(const char *username)
680 const char *p = username;
690 /* reject usernames that don't start with an alphanum
691 * i.e. reject jokers who have '-@somehost' or '.@somehost'
692 * or "-hi-@somehost", "h-----@somehost" would still be accepted.
699 if((*p == '.') && ConfigFileEntry.dots_in_ident)
702 if(dots > ConfigFileEntry.dots_in_ident)
704 if(!IsUserChar(p[1]))
707 else if(!IsUserChar(*p))
713 /* report_and_set_user_flags
715 * Inputs - pointer to source_p
716 * - pointer to aconf for this user
719 * Report to user any special flags they are getting, and set them.
723 report_and_set_user_flags(struct Client *source_p, struct ConfItem *aconf)
725 /* If this user is being spoofed, tell them so */
726 if(IsConfDoSpoofIp(aconf))
729 ":%s NOTICE %s :*** Spoofing your IP. congrats.",
730 me.name, source_p->name);
733 /* If this user is in the exception class, Set it "E lined" */
734 if(IsConfExemptKline(aconf))
736 SetExemptKline(source_p);
738 ":%s NOTICE %s :*** You are exempt from K/D/G/X lines. congrats.",
739 me.name, source_p->name);
742 if(IsConfExemptGline(aconf))
744 SetExemptGline(source_p);
746 /* dont send both a kline and gline exempt notice */
747 if(!IsConfExemptKline(aconf))
749 ":%s NOTICE %s :*** You are exempt from G lines.",
750 me.name, source_p->name);
753 /* If this user is exempt from user limits set it F lined" */
754 if(IsConfExemptLimits(aconf))
756 SetExemptLimits(source_p);
758 ":%s NOTICE %s :*** You are exempt from user limits. congrats.",
759 me.name, source_p->name);
762 if(IsConfExemptFlood(aconf))
764 SetExemptFlood(source_p);
766 ":%s NOTICE %s :*** You are exempt from flood limits.",
767 me.name, source_p->name);
770 if(IsConfExemptSpambot(aconf))
772 SetExemptSpambot(source_p);
774 ":%s NOTICE %s :*** You are exempt from spambot checks.",
775 me.name, source_p->name);
778 if(IsConfExemptJupe(aconf))
780 SetExemptJupe(source_p);
782 ":%s NOTICE %s :*** You are exempt from juped channel warnings.",
783 me.name, source_p->name);
786 if(IsConfExemptResv(aconf))
788 SetExemptResv(source_p);
790 ":%s NOTICE %s :*** You are exempt from resvs.",
791 me.name, source_p->name);
794 if(IsConfExemptShide(aconf))
796 SetExemptShide(source_p);
798 ":%s NOTICE %s :*** You are exempt from serverhiding.",
799 me.name, source_p->name);
804 * user_mode - set get current users mode
806 * m_umode() added 15/10/91 By Darren Reed.
808 * parv[1] - username to change mode for
809 * parv[2] - modes to change
812 user_mode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
819 struct Client *target_p;
821 int badflag = NO; /* Only send one bad flag notice */
828 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "MODE");
832 if((target_p = MyClient(source_p) ? find_named_person(parv[1]) : find_person(parv[1])) == NULL)
834 if(MyConnect(source_p))
835 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
836 form_str(ERR_NOSUCHCHANNEL), parv[1]);
840 /* Dont know why these were commented out..
841 * put them back using new sendto() funcs
844 if(IsServer(source_p))
846 sendto_realops_flags(UMODE_ALL, L_ADMIN,
847 "*** Mode for User %s from %s", parv[1], source_p->name);
851 if(source_p != target_p || target_p->from != source_p->from)
853 sendto_one(source_p, form_str(ERR_USERSDONTMATCH), me.name, source_p->name);
863 for (i = 0; user_modes[i].letter && (m - buf < BUFSIZE - 4); i++)
864 if(source_p->umodes & user_modes[i].mode)
865 *m++ = user_modes[i].letter;
867 sendto_one(source_p, form_str(RPL_UMODEIS), me.name, source_p->name, buf);
871 /* find flags already set for user */
872 setflags = source_p->umodes;
875 * parse mode change string(s)
877 for (p = &parv[2]; p && *p; p++)
878 for (pm = *p; *pm; pm++)
891 if(IsServer(client_p) && !IsOper(source_p))
899 /* Only decrement the oper counts if an oper to begin with
900 * found by Pat Szuta, Perly , perly@xnet.com
903 if(!IsOper(source_p))
910 if(MyConnect(source_p))
912 source_p->umodes &= ~ConfigFileEntry.oper_only_umodes;
913 source_p->flags2 &= ~OPER_FLAGS;
915 MyFree(source_p->localClient->opername);
916 source_p->localClient->opername = NULL;
918 dlinkFindDestroy(source_p, &oper_list);
923 /* we may not get these,
924 * but they shouldnt be in default
927 /* can only be set on burst */
928 #ifdef ENABLE_SERVICES
938 if((flag = user_modes_from_c_to_bitmask[(unsigned char) *pm]))
940 if(MyConnect(source_p)
942 && (ConfigFileEntry.oper_only_umodes & flag))
949 source_p->umodes |= flag;
951 source_p->umodes &= ~flag;
956 if(MyConnect(source_p))
963 sendto_one(source_p, form_str(ERR_UMODEUNKNOWNFLAG), me.name, source_p->name);
965 if((source_p->umodes & UMODE_NCHANGE) && !IsOperN(source_p))
968 ":%s NOTICE %s :*** You need oper and N flag for +n", me.name, parv[0]);
969 source_p->umodes &= ~UMODE_NCHANGE; /* only tcm's really need this */
972 if(MyConnect(source_p) && (source_p->umodes & UMODE_ADMIN) &&
973 (!IsOperAdmin(source_p) || IsOperHiddenAdmin(source_p)))
976 ":%s NOTICE %s :*** You need oper and A flag for +a", me.name, parv[0]);
977 source_p->umodes &= ~UMODE_ADMIN;
981 if(!(setflags & UMODE_INVISIBLE) && IsInvisible(source_p))
983 if((setflags & UMODE_INVISIBLE) && !IsInvisible(source_p))
986 * compare new flags with old flags and send string which
987 * will cause servers to update correctly.
989 send_umode_out(client_p, source_p, setflags);
995 * send the MODE string for user (user) to connection client_p
999 send_umode(struct Client *client_p, struct Client *source_p, int old, int sendmask, char *umode_buf)
1007 * build a string in umode_buf to represent the change in the user's
1008 * mode between the new (source_p->flag) and 'old'.
1013 for (i = 0; user_modes[i].letter; i++)
1015 flag = user_modes[i].mode;
1017 if(MyClient(source_p) && !(flag & sendmask))
1019 if((flag & old) && !(source_p->umodes & flag))
1021 if(what == MODE_DEL)
1022 *m++ = user_modes[i].letter;
1027 *m++ = user_modes[i].letter;
1030 else if(!(flag & old) && (source_p->umodes & flag))
1032 if(what == MODE_ADD)
1033 *m++ = user_modes[i].letter;
1038 *m++ = user_modes[i].letter;
1043 if(*umode_buf && client_p)
1044 sendto_one(client_p, ":%s MODE %s :%s", source_p->name, source_p->name, umode_buf);
1055 send_umode_out(struct Client *client_p, struct Client *source_p, int old)
1057 struct Client *target_p;
1061 send_umode(NULL, source_p, old, SEND_UMODES, buf);
1063 DLINK_FOREACH(ptr, serv_list.head)
1065 target_p = ptr->data;
1067 if((target_p != client_p) && (target_p != source_p) && (*buf))
1069 sendto_one(target_p, ":%s MODE %s :%s",
1070 get_id(source_p, target_p),
1071 get_id(source_p, target_p), buf);
1075 if(client_p && MyClient(client_p))
1076 send_umode(client_p, source_p, old, ALL_UMODES, buf);
1082 * inputs - client pointer to client to welcome
1087 user_welcome(struct Client *source_p)
1089 sendto_one(source_p, form_str(RPL_WELCOME), me.name, source_p->name,
1090 ServerInfo.network_name, source_p->name);
1091 sendto_one(source_p, form_str(RPL_YOURHOST), me.name,
1093 get_listener_name(source_p->localClient->listener), ircd_version);
1095 sendto_one(source_p, form_str(RPL_CREATED), me.name, source_p->name, creation);
1096 sendto_one(source_p, form_str(RPL_MYINFO), me.name, source_p->name, me.name, ircd_version);
1098 show_isupport(source_p);
1100 show_lusers(source_p);
1102 if(ConfigFileEntry.short_motd)
1104 sendto_one(source_p,
1105 "NOTICE %s :*** Notice -- motd was last changed at %s",
1106 source_p->name, user_motd_changed);
1108 sendto_one(source_p,
1109 "NOTICE %s :*** Notice -- Please read the motd if you haven't read it",
1112 sendto_one(source_p, form_str(RPL_MOTDSTART),
1113 me.name, source_p->name, me.name);
1115 sendto_one(source_p, form_str(RPL_MOTD),
1116 me.name, source_p->name, "*** This is the short motd ***");
1118 sendto_one(source_p, form_str(RPL_ENDOFMOTD), me.name, source_p->name);
1121 send_user_motd(source_p);
1126 * inputs - pointer to given client to oper
1127 * - pointer to ConfItem to use
1129 * side effects - opers up source_p using aconf for reference
1132 oper_up(struct Client *source_p, struct oper_conf *oper_p)
1134 int old = (source_p->umodes & ALL_UMODES);
1139 source_p->umodes |= oper_p->umodes & ALL_UMODES;
1140 else if(ConfigFileEntry.oper_umodes)
1141 source_p->umodes |= ConfigFileEntry.oper_umodes & ALL_UMODES;
1143 source_p->umodes |= DEFAULT_OPER_UMODES & ALL_UMODES;
1147 SetExemptKline(source_p);
1149 source_p->flags2 |= oper_p->flags;
1150 MyFree(source_p->localClient->opername);
1151 DupString(source_p->localClient->opername, oper_p->name);
1153 dlinkAddAlloc(source_p, &oper_list);
1155 if(IsOperAdmin(source_p) && !IsOperHiddenAdmin(source_p))
1156 source_p->umodes |= UMODE_ADMIN;
1157 if(!IsOperN(source_p))
1158 source_p->umodes &= ~UMODE_NCHANGE;
1160 sendto_realops_flags(UMODE_ALL, L_ALL,
1161 "%s (%s@%s) is now an operator", source_p->name,
1162 source_p->username, source_p->host);
1163 if(!(old & UMODE_INVISIBLE) && IsInvisible(source_p))
1165 if((old & UMODE_INVISIBLE) && !IsInvisible(source_p))
1167 send_umode_out(source_p, source_p, old);
1168 sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name);
1169 sendto_one(source_p, ":%s NOTICE %s :*** Oper privs are %s", me.name,
1170 source_p->name, get_oper_privs(oper_p->flags));
1171 send_oper_motd(source_p);