]> jfr.im git - solanum.git/blob - src/channel.c
chanroles: instead of checking for chanop + CHANROLE_UNSET combination, grant a defau...
[solanum.git] / src / channel.c
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * channel.c: Controls channels.
4 *
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
8 *
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.
13 *
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.
18 *
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
22 * USA
23 *
24 * $Id: channel.c 3580 2007-11-07 23:45:14Z jilles $
25 */
26
27 #include "stdinc.h"
28 #include "channel.h"
29 #include "chmode.h"
30 #include "client.h"
31 #include "common.h"
32 #include "hash.h"
33 #include "hook.h"
34 #include "match.h"
35 #include "ircd.h"
36 #include "numeric.h"
37 #include "s_serv.h" /* captab */
38 #include "s_user.h"
39 #include "send.h"
40 #include "whowas.h"
41 #include "s_conf.h" /* ConfigFileEntry, ConfigChannel */
42 #include "s_newconf.h"
43 #include "logger.h"
44
45 struct config_channel_entry ConfigChannel;
46 rb_dlink_list global_channel_list;
47 static rb_bh *channel_heap;
48 static rb_bh *ban_heap;
49 static rb_bh *topic_heap;
50 static rb_bh *member_heap;
51
52 static int channel_capabs[] = { CAP_EX, CAP_IE,
53 CAP_SERVICE,
54 CAP_TS6
55 };
56
57 #define NCHCAPS (sizeof(channel_capabs)/sizeof(int))
58 #define NCHCAP_COMBOS (1 << NCHCAPS)
59
60 static struct ChCapCombo chcap_combos[NCHCAP_COMBOS];
61
62 static void free_topic(struct Channel *chptr);
63
64 static int h_can_join;
65 static int h_can_send;
66 int h_get_channel_access;
67
68 /* init_channels()
69 *
70 * input -
71 * output -
72 * side effects - initialises the various blockheaps
73 */
74 void
75 init_channels(void)
76 {
77 channel_heap = rb_bh_create(sizeof(struct Channel), CHANNEL_HEAP_SIZE, "channel_heap");
78 ban_heap = rb_bh_create(sizeof(struct Ban), BAN_HEAP_SIZE, "ban_heap");
79 topic_heap = rb_bh_create(TOPICLEN + 1 + USERHOST_REPLYLEN, TOPIC_HEAP_SIZE, "topic_heap");
80 member_heap = rb_bh_create(sizeof(struct membership), MEMBER_HEAP_SIZE, "member_heap");
81
82 h_can_join = register_hook("can_join");
83 h_can_send = register_hook("can_send");
84 h_get_channel_access = register_hook("get_channel_access");
85 }
86
87 /*
88 * allocate_channel - Allocates a channel
89 */
90 struct Channel *
91 allocate_channel(const char *chname)
92 {
93 struct Channel *chptr;
94 chptr = rb_bh_alloc(channel_heap);
95 chptr->chname = rb_strdup(chname);
96 return (chptr);
97 }
98
99 void
100 free_channel(struct Channel *chptr)
101 {
102 rb_free(chptr->chname);
103 rb_free(chptr->mode_lock);
104 rb_bh_free(channel_heap, chptr);
105 }
106
107 struct Ban *
108 allocate_ban(const char *banstr, const char *who)
109 {
110 struct Ban *bptr;
111 bptr = rb_bh_alloc(ban_heap);
112 bptr->banstr = rb_strdup(banstr);
113 bptr->who = rb_strdup(who);
114
115 return (bptr);
116 }
117
118 void
119 free_ban(struct Ban *bptr)
120 {
121 rb_free(bptr->banstr);
122 rb_free(bptr->who);
123 rb_bh_free(ban_heap, bptr);
124 }
125
126 /*
127 * send_channel_join()
128 *
129 * input - channel to join, client joining.
130 * output - none
131 * side effects - none
132 */
133 void
134 send_channel_join(struct Channel *chptr, struct Client *client_p)
135 {
136 if (!IsClient(client_p))
137 return;
138
139 sendto_channel_local_with_capability(ALL_MEMBERS, NOCAPS, CLICAP_EXTENDED_JOIN, chptr, ":%s!%s@%s JOIN %s",
140 client_p->name, client_p->username, client_p->host, chptr->chname);
141
142 sendto_channel_local_with_capability(ALL_MEMBERS, CLICAP_EXTENDED_JOIN, NOCAPS, chptr, ":%s!%s@%s JOIN %s %s :%s",
143 client_p->name, client_p->username, client_p->host, chptr->chname,
144 EmptyString(client_p->user->suser) ? "*" : client_p->user->suser,
145 client_p->info);
146 }
147
148 /* find_channel_membership()
149 *
150 * input - channel to find them in, client to find
151 * output - membership of client in channel, else NULL
152 * side effects -
153 */
154 struct membership *
155 find_channel_membership(struct Channel *chptr, struct Client *client_p)
156 {
157 struct membership *msptr;
158 rb_dlink_node *ptr;
159
160 if(!IsClient(client_p))
161 return NULL;
162
163 /* Pick the most efficient list to use to be nice to things like
164 * CHANSERV which could be in a large number of channels
165 */
166 if(rb_dlink_list_length(&chptr->members) < rb_dlink_list_length(&client_p->user->channel))
167 {
168 RB_DLINK_FOREACH(ptr, chptr->members.head)
169 {
170 msptr = ptr->data;
171
172 if(msptr->client_p == client_p)
173 return msptr;
174 }
175 }
176 else
177 {
178 RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
179 {
180 msptr = ptr->data;
181
182 if(msptr->chptr == chptr)
183 return msptr;
184 }
185 }
186
187 return NULL;
188 }
189
190 /* find_channel_status()
191 *
192 * input - membership to get status for, whether we can combine flags
193 * output - flags of user on channel
194 * side effects -
195 */
196 const char *
197 find_channel_status(struct membership *msptr, int combine)
198 {
199 static char buffer[3];
200 char *p;
201
202 p = buffer;
203
204 if(is_chanop(msptr))
205 {
206 if(!combine)
207 return "@";
208 *p++ = '@';
209 }
210
211 if(is_voiced(msptr))
212 *p++ = '+';
213
214 *p = '\0';
215 return buffer;
216 }
217
218 /* add_user_to_channel()
219 *
220 * input - channel to add client to, client to add, channel flags
221 * output -
222 * side effects - user is added to channel
223 */
224 void
225 add_user_to_channel(struct Channel *chptr, struct Client *client_p, int flags)
226 {
227 struct membership *msptr;
228
229 s_assert(client_p->user != NULL);
230 if(client_p->user == NULL)
231 return;
232
233 msptr = rb_bh_alloc(member_heap);
234
235 msptr->chptr = chptr;
236 msptr->client_p = client_p;
237 msptr->flags = flags;
238
239 /* Default to no chanroles until services says we're something else */
240 if (flags == CHFL_CHANOP)
241 msptr->roles = CHANROLE_INITIAL;
242 else
243 msptr->roles = CHANROLE_UNSET;
244
245 rb_dlinkAdd(msptr, &msptr->usernode, &client_p->user->channel);
246 rb_dlinkAdd(msptr, &msptr->channode, &chptr->members);
247
248 if(MyClient(client_p))
249 rb_dlinkAdd(msptr, &msptr->locchannode, &chptr->locmembers);
250 }
251
252 /* remove_user_from_channel()
253 *
254 * input - membership pointer to remove from channel
255 * output -
256 * side effects - membership (thus user) is removed from channel
257 */
258 void
259 remove_user_from_channel(struct membership *msptr)
260 {
261 struct Client *client_p;
262 struct Channel *chptr;
263 s_assert(msptr != NULL);
264 if(msptr == NULL)
265 return;
266
267 client_p = msptr->client_p;
268 chptr = msptr->chptr;
269
270 rb_dlinkDelete(&msptr->usernode, &client_p->user->channel);
271 rb_dlinkDelete(&msptr->channode, &chptr->members);
272
273 if(client_p->servptr == &me)
274 rb_dlinkDelete(&msptr->locchannode, &chptr->locmembers);
275
276 if(!(chptr->mode.mode & MODE_PERMANENT) && rb_dlink_list_length(&chptr->members) <= 0)
277 destroy_channel(chptr);
278
279 rb_bh_free(member_heap, msptr);
280
281 return;
282 }
283
284 /* remove_user_from_channels()
285 *
286 * input - user to remove from all channels
287 * output -
288 * side effects - user is removed from all channels
289 */
290 void
291 remove_user_from_channels(struct Client *client_p)
292 {
293 struct Channel *chptr;
294 struct membership *msptr;
295 rb_dlink_node *ptr;
296 rb_dlink_node *next_ptr;
297
298 if(client_p == NULL)
299 return;
300
301 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->user->channel.head)
302 {
303 msptr = ptr->data;
304 chptr = msptr->chptr;
305
306 rb_dlinkDelete(&msptr->channode, &chptr->members);
307
308 if(client_p->servptr == &me)
309 rb_dlinkDelete(&msptr->locchannode, &chptr->locmembers);
310
311 if(!(chptr->mode.mode & MODE_PERMANENT) && rb_dlink_list_length(&chptr->members) <= 0)
312 destroy_channel(chptr);
313
314 rb_bh_free(member_heap, msptr);
315 }
316
317 client_p->user->channel.head = client_p->user->channel.tail = NULL;
318 client_p->user->channel.length = 0;
319 }
320
321 /* invalidate_bancache_user()
322 *
323 * input - user to invalidate ban cache for
324 * output -
325 * side effects - ban cache is invalidated for all memberships of that user
326 * to be used after a nick change
327 */
328 void
329 invalidate_bancache_user(struct Client *client_p)
330 {
331 struct membership *msptr;
332 rb_dlink_node *ptr;
333
334 if(client_p == NULL)
335 return;
336
337 RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
338 {
339 msptr = ptr->data;
340 msptr->bants = 0;
341 msptr->flags &= ~CHFL_BANNED;
342 }
343 }
344
345 /* check_channel_name()
346 *
347 * input - channel name
348 * output - 1 if valid channel name, else 0
349 * side effects -
350 */
351 int
352 check_channel_name(const char *name)
353 {
354 s_assert(name != NULL);
355 if(name == NULL)
356 return 0;
357
358 for (; *name; ++name)
359 {
360 if(!IsChanChar(*name))
361 return 0;
362 }
363
364 return 1;
365 }
366
367 /* free_channel_list()
368 *
369 * input - rb_dlink list to free
370 * output -
371 * side effects - list of b/e/I modes is cleared
372 */
373 void
374 free_channel_list(rb_dlink_list * list)
375 {
376 rb_dlink_node *ptr;
377 rb_dlink_node *next_ptr;
378 struct Ban *actualBan;
379
380 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
381 {
382 actualBan = ptr->data;
383 free_ban(actualBan);
384 }
385
386 list->head = list->tail = NULL;
387 list->length = 0;
388 }
389
390 /* destroy_channel()
391 *
392 * input - channel to destroy
393 * output -
394 * side effects - channel is obliterated
395 */
396 void
397 destroy_channel(struct Channel *chptr)
398 {
399 rb_dlink_node *ptr, *next_ptr;
400
401 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
402 {
403 del_invite(chptr, ptr->data);
404 }
405
406 /* free all bans/exceptions/denies */
407 free_channel_list(&chptr->banlist);
408 free_channel_list(&chptr->exceptlist);
409 free_channel_list(&chptr->invexlist);
410 free_channel_list(&chptr->quietlist);
411
412 /* Free the topic */
413 free_topic(chptr);
414
415 rb_dlinkDelete(&chptr->node, &global_channel_list);
416 del_from_channel_hash(chptr->chname, chptr);
417 free_channel(chptr);
418 }
419
420 /* channel_pub_or_secret()
421 *
422 * input - channel
423 * output - "=" if public, "@" if secret, else "*"
424 * side effects -
425 */
426 static const char *
427 channel_pub_or_secret(struct Channel *chptr)
428 {
429 if(PubChannel(chptr))
430 return ("=");
431 else if(SecretChannel(chptr))
432 return ("@");
433 return ("*");
434 }
435
436 /* channel_member_names()
437 *
438 * input - channel to list, client to list to, show endofnames
439 * output -
440 * side effects - client is given list of users on channel
441 */
442 void
443 channel_member_names(struct Channel *chptr, struct Client *client_p, int show_eon)
444 {
445 struct membership *msptr;
446 struct Client *target_p;
447 rb_dlink_node *ptr;
448 char lbuf[BUFSIZE];
449 char *t;
450 int mlen;
451 int tlen;
452 int cur_len;
453 int is_member;
454 int stack = IsCapable(client_p, CLICAP_MULTI_PREFIX);
455
456 if(ShowChannel(client_p, chptr))
457 {
458 is_member = IsMember(client_p, chptr);
459
460 cur_len = mlen = rb_sprintf(lbuf, form_str(RPL_NAMREPLY),
461 me.name, client_p->name,
462 channel_pub_or_secret(chptr), chptr->chname);
463
464 t = lbuf + cur_len;
465
466 RB_DLINK_FOREACH(ptr, chptr->members.head)
467 {
468 msptr = ptr->data;
469 target_p = msptr->client_p;
470
471 if(IsInvisible(target_p) && !is_member)
472 continue;
473
474 /* space, possible "@+" prefix */
475 if(cur_len + strlen(target_p->name) + 3 >= BUFSIZE - 3)
476 {
477 *(t - 1) = '\0';
478 sendto_one(client_p, "%s", lbuf);
479 cur_len = mlen;
480 t = lbuf + mlen;
481 }
482
483 tlen = rb_sprintf(t, "%s%s ", find_channel_status(msptr, stack),
484 target_p->name);
485
486 cur_len += tlen;
487 t += tlen;
488 }
489
490 /* The old behaviour here was to always output our buffer,
491 * even if there are no clients we can show. This happens
492 * when a client does "NAMES" with no parameters, and all
493 * the clients on a -sp channel are +i. I dont see a good
494 * reason for keeping that behaviour, as it just wastes
495 * bandwidth. --anfl
496 */
497 if(cur_len != mlen)
498 {
499 *(t - 1) = '\0';
500 sendto_one(client_p, "%s", lbuf);
501 }
502 }
503
504 if(show_eon)
505 sendto_one(client_p, form_str(RPL_ENDOFNAMES),
506 me.name, client_p->name, chptr->chname);
507 }
508
509 /* del_invite()
510 *
511 * input - channel to remove invite from, client to remove
512 * output -
513 * side effects - user is removed from invite list, if exists
514 */
515 void
516 del_invite(struct Channel *chptr, struct Client *who)
517 {
518 rb_dlinkFindDestroy(who, &chptr->invites);
519 rb_dlinkFindDestroy(chptr, &who->user->invited);
520 }
521
522 /* is_banned()
523 *
524 * input - channel to check bans for, user to check bans against
525 * optional prebuilt buffers
526 * output - 1 if banned, else 0
527 * side effects -
528 */
529 int
530 is_banned(struct Channel *chptr, struct Client *who, struct membership *msptr,
531 const char *s, const char *s2)
532 {
533 char src_host[NICKLEN + USERLEN + HOSTLEN + 6];
534 char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6];
535 char src_althost[NICKLEN + USERLEN + HOSTLEN + 6];
536 char *s3 = NULL;
537 rb_dlink_node *ptr;
538 struct Ban *actualBan = NULL;
539 struct Ban *actualExcept = NULL;
540
541 if(!MyClient(who))
542 return 0;
543
544 /* if the buffers havent been built, do it here */
545 if(s == NULL)
546 {
547 rb_sprintf(src_host, "%s!%s@%s", who->name, who->username, who->host);
548 rb_sprintf(src_iphost, "%s!%s@%s", who->name, who->username, who->sockhost);
549
550 s = src_host;
551 s2 = src_iphost;
552 }
553 if(who->localClient->mangledhost != NULL)
554 {
555 /* if host mangling mode enabled, also check their real host */
556 if(!strcmp(who->host, who->localClient->mangledhost))
557 {
558 rb_sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->orighost);
559 s3 = src_althost;
560 }
561 /* if host mangling mode not enabled and no other spoof,
562 * also check the mangled form of their host */
563 else if (!IsDynSpoof(who))
564 {
565 rb_sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->localClient->mangledhost);
566 s3 = src_althost;
567 }
568 }
569
570 RB_DLINK_FOREACH(ptr, chptr->banlist.head)
571 {
572 actualBan = ptr->data;
573 if(match(actualBan->banstr, s) ||
574 match(actualBan->banstr, s2) ||
575 match_cidr(actualBan->banstr, s2) ||
576 match_extban(actualBan->banstr, who, chptr, CHFL_BAN) ||
577 (s3 != NULL && match(actualBan->banstr, s3)))
578 break;
579 else
580 actualBan = NULL;
581 }
582
583 if((actualBan != NULL) && ConfigChannel.use_except)
584 {
585 RB_DLINK_FOREACH(ptr, chptr->exceptlist.head)
586 {
587 actualExcept = ptr->data;
588
589 /* theyre exempted.. */
590 if(match(actualExcept->banstr, s) ||
591 match(actualExcept->banstr, s2) ||
592 match_cidr(actualExcept->banstr, s2) ||
593 match_extban(actualExcept->banstr, who, chptr, CHFL_EXCEPTION) ||
594 (s3 != NULL && match(actualExcept->banstr, s3)))
595 {
596 /* cache the fact theyre not banned */
597 if(msptr != NULL)
598 {
599 msptr->bants = chptr->bants;
600 msptr->flags &= ~CHFL_BANNED;
601 }
602
603 return CHFL_EXCEPTION;
604 }
605 }
606 }
607
608 /* cache the banned/not banned status */
609 if(msptr != NULL)
610 {
611 msptr->bants = chptr->bants;
612
613 if(actualBan != NULL)
614 {
615 msptr->flags |= CHFL_BANNED;
616 return CHFL_BAN;
617 }
618 else
619 {
620 msptr->flags &= ~CHFL_BANNED;
621 return 0;
622 }
623 }
624
625 return ((actualBan ? CHFL_BAN : 0));
626 }
627
628 /* is_quieted()
629 *
630 * input - channel to check bans for, user to check bans against
631 * optional prebuilt buffers
632 * output - 1 if banned, else 0
633 * side effects -
634 */
635 int
636 is_quieted(struct Channel *chptr, struct Client *who, struct membership *msptr,
637 const char *s, const char *s2)
638 {
639 char src_host[NICKLEN + USERLEN + HOSTLEN + 6];
640 char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6];
641 char src_althost[NICKLEN + USERLEN + HOSTLEN + 6];
642 char *s3 = NULL;
643 rb_dlink_node *ptr;
644 struct Ban *actualBan = NULL;
645 struct Ban *actualExcept = NULL;
646
647 if(!MyClient(who))
648 return 0;
649
650 /* if the buffers havent been built, do it here */
651 if(s == NULL)
652 {
653 rb_sprintf(src_host, "%s!%s@%s", who->name, who->username, who->host);
654 rb_sprintf(src_iphost, "%s!%s@%s", who->name, who->username, who->sockhost);
655
656 s = src_host;
657 s2 = src_iphost;
658 }
659 if(who->localClient->mangledhost != NULL)
660 {
661 /* if host mangling mode enabled, also check their real host */
662 if(!strcmp(who->host, who->localClient->mangledhost))
663 {
664 rb_sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->orighost);
665 s3 = src_althost;
666 }
667 /* if host mangling mode not enabled and no other spoof,
668 * also check the mangled form of their host */
669 else if (!IsDynSpoof(who))
670 {
671 rb_sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->localClient->mangledhost);
672 s3 = src_althost;
673 }
674 }
675
676 RB_DLINK_FOREACH(ptr, chptr->quietlist.head)
677 {
678 actualBan = ptr->data;
679 if(match(actualBan->banstr, s) ||
680 match(actualBan->banstr, s2) ||
681 match_cidr(actualBan->banstr, s2) ||
682 match_extban(actualBan->banstr, who, chptr, CHFL_QUIET) ||
683 (s3 != NULL && match(actualBan->banstr, s3)))
684 break;
685 else
686 actualBan = NULL;
687 }
688
689 if((actualBan != NULL) && ConfigChannel.use_except)
690 {
691 RB_DLINK_FOREACH(ptr, chptr->exceptlist.head)
692 {
693 actualExcept = ptr->data;
694
695 /* theyre exempted.. */
696 if(match(actualExcept->banstr, s) ||
697 match(actualExcept->banstr, s2) ||
698 match_cidr(actualExcept->banstr, s2) ||
699 match_extban(actualExcept->banstr, who, chptr, CHFL_EXCEPTION) ||
700 (s3 != NULL && match(actualExcept->banstr, s3)))
701 {
702 /* cache the fact theyre not banned */
703 if(msptr != NULL)
704 {
705 msptr->bants = chptr->bants;
706 msptr->flags &= ~CHFL_BANNED;
707 }
708
709 return CHFL_EXCEPTION;
710 }
711 }
712 }
713
714 /* cache the banned/not banned status */
715 if(msptr != NULL)
716 {
717 msptr->bants = chptr->bants;
718
719 if(actualBan != NULL)
720 {
721 msptr->flags |= CHFL_BANNED;
722 return CHFL_BAN;
723 }
724 else
725 {
726 msptr->flags &= ~CHFL_BANNED;
727 return 0;
728 }
729 }
730
731 return ((actualBan ? CHFL_BAN : 0));
732 }
733
734 /* can_join()
735 *
736 * input - client to check, channel to check for, key
737 * output - reason for not being able to join, else 0
738 * side effects -
739 * caveats - this function should only be called on a local user.
740 */
741 int
742 can_join(struct Client *source_p, struct Channel *chptr, char *key)
743 {
744 rb_dlink_node *invite = NULL;
745 rb_dlink_node *ptr;
746 struct Ban *invex = NULL;
747 char src_host[NICKLEN + USERLEN + HOSTLEN + 6];
748 char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6];
749 char src_althost[NICKLEN + USERLEN + HOSTLEN + 6];
750 int use_althost = 0;
751 int i = 0;
752 hook_data_channel moduledata;
753
754 s_assert(source_p->localClient != NULL);
755
756 moduledata.client = source_p;
757 moduledata.chptr = chptr;
758 moduledata.approved = 0;
759
760 rb_sprintf(src_host, "%s!%s@%s", source_p->name, source_p->username, source_p->host);
761 rb_sprintf(src_iphost, "%s!%s@%s", source_p->name, source_p->username, source_p->sockhost);
762 if(source_p->localClient->mangledhost != NULL)
763 {
764 /* if host mangling mode enabled, also check their real host */
765 if(!strcmp(source_p->host, source_p->localClient->mangledhost))
766 {
767 rb_sprintf(src_althost, "%s!%s@%s", source_p->name, source_p->username, source_p->orighost);
768 use_althost = 1;
769 }
770 /* if host mangling mode not enabled and no other spoof,
771 * also check the mangled form of their host */
772 else if (!IsDynSpoof(source_p))
773 {
774 rb_sprintf(src_althost, "%s!%s@%s", source_p->name, source_p->username, source_p->localClient->mangledhost);
775 use_althost = 1;
776 }
777 }
778
779 if((is_banned(chptr, source_p, NULL, src_host, src_iphost)) == CHFL_BAN)
780 {
781 moduledata.approved = ERR_BANNEDFROMCHAN;
782 goto finish_join_check;
783 }
784
785 if(chptr->mode.mode & MODE_INVITEONLY)
786 {
787 RB_DLINK_FOREACH(invite, source_p->user->invited.head)
788 {
789 if(invite->data == chptr)
790 break;
791 }
792 if(invite == NULL)
793 {
794 if(!ConfigChannel.use_invex)
795 moduledata.approved = ERR_INVITEONLYCHAN;
796 RB_DLINK_FOREACH(ptr, chptr->invexlist.head)
797 {
798 invex = ptr->data;
799 if(match(invex->banstr, src_host)
800 || match(invex->banstr, src_iphost)
801 || match_cidr(invex->banstr, src_iphost)
802 || match_extban(invex->banstr, source_p, chptr, CHFL_INVEX)
803 || (use_althost && match(invex->banstr, src_althost)))
804 break;
805 }
806 if(ptr == NULL)
807 moduledata.approved = ERR_INVITEONLYCHAN;
808 }
809 }
810
811 if(*chptr->mode.key && (EmptyString(key) || irccmp(chptr->mode.key, key)))
812 moduledata.approved = ERR_BADCHANNELKEY;
813
814 if(chptr->mode.limit &&
815 rb_dlink_list_length(&chptr->members) >= (unsigned long) chptr->mode.limit)
816 i = ERR_CHANNELISFULL;
817 if(chptr->mode.mode & MODE_REGONLY && EmptyString(source_p->user->suser))
818 i = ERR_NEEDREGGEDNICK;
819 /* join throttling stuff --nenolod */
820 else if(chptr->mode.join_num > 0 && chptr->mode.join_time > 0)
821 {
822 if ((rb_current_time() - chptr->join_delta <=
823 chptr->mode.join_time) && (chptr->join_count >=
824 chptr->mode.join_num))
825 i = ERR_THROTTLE;
826 }
827
828 /* allow /invite to override +l/+r/+j also -- jilles */
829 if (i != 0 && invite == NULL)
830 {
831 RB_DLINK_FOREACH(invite, source_p->user->invited.head)
832 {
833 if(invite->data == chptr)
834 break;
835 }
836 if (invite == NULL)
837 moduledata.approved = i;
838 }
839
840 finish_join_check:
841 call_hook(h_can_join, &moduledata);
842
843 return moduledata.approved;
844 }
845
846 /* can_send()
847 *
848 * input - user to check in channel, membership pointer
849 * output - whether can explicitly send or not, else CAN_SEND_NONOP
850 * side effects -
851 */
852 int
853 can_send(struct Channel *chptr, struct Client *source_p, struct membership *msptr)
854 {
855 hook_data_channel_approval moduledata;
856
857 moduledata.approved = CAN_SEND_NONOP;
858
859 if(IsServer(source_p) || IsService(source_p))
860 return CAN_SEND_OPV;
861
862 if(MyClient(source_p) && hash_find_resv(chptr->chname) &&
863 !IsOper(source_p) && !IsExemptResv(source_p))
864 moduledata.approved = CAN_SEND_NO;
865
866 if(msptr == NULL)
867 {
868 msptr = find_channel_membership(chptr, source_p);
869
870 if(msptr == NULL)
871 {
872 /* if its +m or +n and theyre not in the channel,
873 * they cant send. we dont check bans here because
874 * theres no possibility of caching them --fl
875 */
876 if(chptr->mode.mode & MODE_NOPRIVMSGS || chptr->mode.mode & MODE_MODERATED)
877 moduledata.approved = CAN_SEND_NO;
878 else
879 moduledata.approved = CAN_SEND_NONOP;
880
881 return moduledata.approved;
882 }
883 }
884
885 if(chptr->mode.mode & MODE_MODERATED)
886 moduledata.approved = CAN_SEND_NO;
887
888 if(MyClient(source_p))
889 {
890 /* cached can_send */
891 if(msptr->bants == chptr->bants)
892 {
893 if(can_send_banned(msptr))
894 moduledata.approved = CAN_SEND_NO;
895 }
896 else if(is_banned(chptr, source_p, msptr, NULL, NULL) == CHFL_BAN
897 || is_quieted(chptr, source_p, msptr, NULL, NULL) == CHFL_BAN)
898 moduledata.approved = CAN_SEND_NO;
899 }
900
901 if(is_chanop_voiced(msptr))
902 moduledata.approved = CAN_SEND_OPV;
903
904 moduledata.client = source_p;
905 moduledata.chptr = msptr->chptr;
906 moduledata.msptr = msptr;
907 moduledata.target = NULL;
908
909 call_hook(h_can_send, &moduledata);
910
911 return moduledata.approved;
912 }
913
914 /*
915 * flood_attack_channel
916 * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
917 * says NOTICE must not auto reply
918 * - pointer to source Client
919 * - pointer to target channel
920 * output - 1 if target is under flood attack
921 * side effects - check for flood attack on target chptr
922 */
923 int
924 flood_attack_channel(int p_or_n, struct Client *source_p, struct Channel *chptr, char *chname)
925 {
926 int delta;
927
928 if(GlobalSetOptions.floodcount && MyClient(source_p))
929 {
930 if((chptr->first_received_message_time + 1) < rb_current_time())
931 {
932 delta = rb_current_time() - chptr->first_received_message_time;
933 chptr->received_number_of_privmsgs -= delta;
934 chptr->first_received_message_time = rb_current_time();
935 if(chptr->received_number_of_privmsgs <= 0)
936 {
937 chptr->received_number_of_privmsgs = 0;
938 chptr->flood_noticed = 0;
939 }
940 }
941
942 if((chptr->received_number_of_privmsgs >= GlobalSetOptions.floodcount)
943 || chptr->flood_noticed)
944 {
945 if(chptr->flood_noticed == 0)
946 {
947 sendto_realops_snomask(SNO_BOTS, *chptr->chname == '&' ? L_ALL : L_NETWIDE,
948 "Possible Flooder %s[%s@%s] on %s target: %s",
949 source_p->name, source_p->username,
950 source_p->orighost,
951 source_p->servptr->name, chptr->chname);
952 chptr->flood_noticed = 1;
953
954 /* Add a bit of penalty */
955 chptr->received_number_of_privmsgs += 2;
956 }
957 if(MyClient(source_p) && (p_or_n != 1))
958 sendto_one(source_p,
959 ":%s NOTICE %s :*** Message to %s throttled due to flooding",
960 me.name, source_p->name, chptr->chname);
961 return 1;
962 }
963 else
964 chptr->received_number_of_privmsgs++;
965 }
966
967 return 0;
968 }
969
970 /* find_bannickchange_channel()
971 * Input: client to check
972 * Output: channel preventing nick change
973 */
974 struct Channel *
975 find_bannickchange_channel(struct Client *client_p)
976 {
977 struct Channel *chptr;
978 struct membership *msptr;
979 rb_dlink_node *ptr;
980 char src_host[NICKLEN + USERLEN + HOSTLEN + 6];
981 char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6];
982
983 if (!MyClient(client_p))
984 return NULL;
985
986 rb_sprintf(src_host, "%s!%s@%s", client_p->name, client_p->username, client_p->host);
987 rb_sprintf(src_iphost, "%s!%s@%s", client_p->name, client_p->username, client_p->sockhost);
988
989 RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
990 {
991 msptr = ptr->data;
992 chptr = msptr->chptr;
993 if (is_chanop_voiced(msptr))
994 continue;
995 /* cached can_send */
996 if (msptr->bants == chptr->bants)
997 {
998 if (can_send_banned(msptr))
999 return chptr;
1000 }
1001 else if (is_banned(chptr, client_p, msptr, src_host, src_iphost) == CHFL_BAN
1002 || is_quieted(chptr, client_p, msptr, src_host, src_iphost) == CHFL_BAN)
1003 return chptr;
1004 }
1005 return NULL;
1006 }
1007
1008 /* void check_spambot_warning(struct Client *source_p)
1009 * Input: Client to check, channel name or NULL if this is a part.
1010 * Output: none
1011 * Side-effects: Updates the client's oper_warn_count_down, warns the
1012 * IRC operators if necessary, and updates join_leave_countdown as
1013 * needed.
1014 */
1015 void
1016 check_spambot_warning(struct Client *source_p, const char *name)
1017 {
1018 int t_delta;
1019 int decrement_count;
1020 if((GlobalSetOptions.spam_num &&
1021 (source_p->localClient->join_leave_count >= GlobalSetOptions.spam_num)))
1022 {
1023 if(source_p->localClient->oper_warn_count_down > 0)
1024 source_p->localClient->oper_warn_count_down--;
1025 else
1026 source_p->localClient->oper_warn_count_down = 0;
1027 if(source_p->localClient->oper_warn_count_down == 0 &&
1028 name != NULL)
1029 {
1030 /* Its already known as a possible spambot */
1031 sendto_realops_snomask(SNO_BOTS, L_NETWIDE,
1032 "User %s (%s@%s) trying to join %s is a possible spambot",
1033 source_p->name,
1034 source_p->username, source_p->orighost, name);
1035 source_p->localClient->oper_warn_count_down = OPER_SPAM_COUNTDOWN;
1036 }
1037 }
1038 else
1039 {
1040 if((t_delta =
1041 (rb_current_time() - source_p->localClient->last_leave_time)) >
1042 JOIN_LEAVE_COUNT_EXPIRE_TIME)
1043 {
1044 decrement_count = (t_delta / JOIN_LEAVE_COUNT_EXPIRE_TIME);
1045 if(name != NULL)
1046 ;
1047 else if(decrement_count > source_p->localClient->join_leave_count)
1048 source_p->localClient->join_leave_count = 0;
1049 else
1050 source_p->localClient->join_leave_count -= decrement_count;
1051 }
1052 else
1053 {
1054 if((rb_current_time() -
1055 (source_p->localClient->last_join_time)) < GlobalSetOptions.spam_time)
1056 {
1057 /* oh, its a possible spambot */
1058 source_p->localClient->join_leave_count++;
1059 }
1060 }
1061 if(name != NULL)
1062 source_p->localClient->last_join_time = rb_current_time();
1063 else
1064 source_p->localClient->last_leave_time = rb_current_time();
1065 }
1066 }
1067
1068 /* check_splitmode()
1069 *
1070 * input -
1071 * output -
1072 * side effects - compares usercount and servercount against their split
1073 * values and adjusts splitmode accordingly
1074 */
1075 void
1076 check_splitmode(void *unused)
1077 {
1078 if(splitchecking && (ConfigChannel.no_join_on_split || ConfigChannel.no_create_on_split))
1079 {
1080 /* not split, we're being asked to check now because someone
1081 * has left
1082 */
1083 if(!splitmode)
1084 {
1085 if(eob_count < split_servers || Count.total < split_users)
1086 {
1087 splitmode = 1;
1088 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1089 "Network split, activating splitmode");
1090 check_splitmode_ev = rb_event_addish("check_splitmode", check_splitmode, NULL, 2);
1091 }
1092 }
1093 /* in splitmode, check whether its finished */
1094 else if(eob_count >= split_servers && Count.total >= split_users)
1095 {
1096 splitmode = 0;
1097
1098 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1099 "Network rejoined, deactivating splitmode");
1100
1101 rb_event_delete(check_splitmode_ev);
1102 check_splitmode_ev = NULL;
1103 }
1104 }
1105 }
1106
1107
1108 /* allocate_topic()
1109 *
1110 * input - channel to allocate topic for
1111 * output - 1 on success, else 0
1112 * side effects - channel gets a topic allocated
1113 */
1114 static void
1115 allocate_topic(struct Channel *chptr)
1116 {
1117 void *ptr;
1118
1119 if(chptr == NULL)
1120 return;
1121
1122 ptr = rb_bh_alloc(topic_heap);
1123
1124 /* Basically we allocate one large block for the topic and
1125 * the topic info. We then split it up into two and shove it
1126 * in the chptr
1127 */
1128 chptr->topic = ptr;
1129 chptr->topic_info = (char *) ptr + TOPICLEN + 1;
1130 *chptr->topic = '\0';
1131 *chptr->topic_info = '\0';
1132 }
1133
1134 /* free_topic()
1135 *
1136 * input - channel which has topic to free
1137 * output -
1138 * side effects - channels topic is free'd
1139 */
1140 static void
1141 free_topic(struct Channel *chptr)
1142 {
1143 void *ptr;
1144
1145 if(chptr == NULL || chptr->topic == NULL)
1146 return;
1147
1148 /* This is safe for now - If you change allocate_topic you
1149 * MUST change this as well
1150 */
1151 ptr = chptr->topic;
1152 rb_bh_free(topic_heap, ptr);
1153 chptr->topic = NULL;
1154 chptr->topic_info = NULL;
1155 }
1156
1157 /* set_channel_topic()
1158 *
1159 * input - channel, topic to set, topic info and topic ts
1160 * output -
1161 * side effects - channels topic, topic info and TS are set.
1162 */
1163 void
1164 set_channel_topic(struct Channel *chptr, const char *topic, const char *topic_info, time_t topicts)
1165 {
1166 if(strlen(topic) > 0)
1167 {
1168 if(chptr->topic == NULL)
1169 allocate_topic(chptr);
1170 rb_strlcpy(chptr->topic, topic, TOPICLEN + 1);
1171 rb_strlcpy(chptr->topic_info, topic_info, USERHOST_REPLYLEN);
1172 chptr->topic_time = topicts;
1173 }
1174 else
1175 {
1176 if(chptr->topic != NULL)
1177 free_topic(chptr);
1178 chptr->topic_time = 0;
1179 }
1180 }
1181
1182 /* channel_modes()
1183 *
1184 * inputs - pointer to channel
1185 * - pointer to client
1186 * output - string with simple modes
1187 * side effects - result from previous calls overwritten
1188 *
1189 * Stolen from ShadowIRCd 4 --nenolod
1190 */
1191 const char *
1192 channel_modes(struct Channel *chptr, struct Client *client_p)
1193 {
1194 int i;
1195 char buf1[BUFSIZE];
1196 char buf2[BUFSIZE];
1197 static char final[BUFSIZE];
1198 char *mbuf = buf1;
1199 char *pbuf = buf2;
1200
1201 *mbuf++ = '+';
1202 *pbuf = '\0';
1203
1204 for (i = 0; i < 256; i++)
1205 if(chptr->mode.mode & chmode_flags[i])
1206 *mbuf++ = i;
1207
1208 if(chptr->mode.limit)
1209 {
1210 *mbuf++ = 'l';
1211
1212 if(!IsClient(client_p) || IsMember(client_p, chptr))
1213 pbuf += rb_sprintf(pbuf, " %d", chptr->mode.limit);
1214 }
1215
1216 if(*chptr->mode.key)
1217 {
1218 *mbuf++ = 'k';
1219
1220 if(pbuf > buf2 || !IsClient(client_p) || IsMember(client_p, chptr))
1221 pbuf += rb_sprintf(pbuf, " %s", chptr->mode.key);
1222 }
1223
1224 if(chptr->mode.join_num)
1225 {
1226 *mbuf++ = 'j';
1227
1228 if(pbuf > buf2 || !IsClient(client_p) || IsMember(client_p, chptr))
1229 pbuf += rb_sprintf(pbuf, " %d:%d", chptr->mode.join_num,
1230 chptr->mode.join_time);
1231 }
1232
1233 if(*chptr->mode.forward && (ConfigChannel.use_forward || !IsClient(client_p)))
1234 {
1235 *mbuf++ = 'f';
1236
1237 if(pbuf > buf2 || !IsClient(client_p) || IsMember(client_p, chptr))
1238 pbuf += rb_sprintf(pbuf, " %s", chptr->mode.forward);
1239 }
1240
1241 *mbuf = '\0';
1242
1243 rb_strlcpy(final, buf1, sizeof final);
1244 rb_strlcat(final, buf2, sizeof final);
1245 return final;
1246 }
1247
1248 /* Now lets do some stuff to keep track of what combinations of
1249 * servers exist...
1250 * Note that the number of combinations doubles each time you add
1251 * something to this list. Each one is only quick if no servers use that
1252 * combination, but if the numbers get too high here MODE will get too
1253 * slow. I suggest if you get more than 7 here, you consider getting rid
1254 * of some and merging or something. If it wasn't for irc+cs we would
1255 * probably not even need to bother about most of these, but unfortunately
1256 * we do. -A1kmm
1257 */
1258
1259 /* void init_chcap_usage_counts(void)
1260 *
1261 * Inputs - none
1262 * Output - none
1263 * Side-effects - Initialises the usage counts to zero. Fills in the
1264 * chcap_yes and chcap_no combination tables.
1265 */
1266 void
1267 init_chcap_usage_counts(void)
1268 {
1269 unsigned long m, c, y, n;
1270
1271 memset(chcap_combos, 0, sizeof(chcap_combos));
1272
1273 /* For every possible combination */
1274 for (m = 0; m < NCHCAP_COMBOS; m++)
1275 {
1276 /* Check each capab */
1277 for (c = y = n = 0; c < NCHCAPS; c++)
1278 {
1279 if((m & (1 << c)) == 0)
1280 n |= channel_capabs[c];
1281 else
1282 y |= channel_capabs[c];
1283 }
1284 chcap_combos[m].cap_yes = y;
1285 chcap_combos[m].cap_no = n;
1286 }
1287 }
1288
1289 /* void set_chcap_usage_counts(struct Client *serv_p)
1290 * Input: serv_p; The client whose capabs to register.
1291 * Output: none
1292 * Side-effects: Increments the usage counts for the correct capab
1293 * combination.
1294 */
1295 void
1296 set_chcap_usage_counts(struct Client *serv_p)
1297 {
1298 int n;
1299
1300 for (n = 0; n < NCHCAP_COMBOS; n++)
1301 {
1302 if(IsCapable(serv_p, chcap_combos[n].cap_yes) &&
1303 NotCapable(serv_p, chcap_combos[n].cap_no))
1304 {
1305 chcap_combos[n].count++;
1306 return;
1307 }
1308 }
1309
1310 /* This should be impossible -A1kmm. */
1311 s_assert(0);
1312 }
1313
1314 /* void set_chcap_usage_counts(struct Client *serv_p)
1315 *
1316 * Inputs - serv_p; The client whose capabs to register.
1317 * Output - none
1318 * Side-effects - Decrements the usage counts for the correct capab
1319 * combination.
1320 */
1321 void
1322 unset_chcap_usage_counts(struct Client *serv_p)
1323 {
1324 int n;
1325
1326 for (n = 0; n < NCHCAP_COMBOS; n++)
1327 {
1328 if(IsCapable(serv_p, chcap_combos[n].cap_yes) &&
1329 NotCapable(serv_p, chcap_combos[n].cap_no))
1330 {
1331 /* Hopefully capabs can't change dynamically or anything... */
1332 s_assert(chcap_combos[n].count > 0);
1333
1334 if(chcap_combos[n].count > 0)
1335 chcap_combos[n].count--;
1336 return;
1337 }
1338 }
1339
1340 /* This should be impossible -A1kmm. */
1341 s_assert(0);
1342 }
1343
1344 /* void send_cap_mode_changes(struct Client *client_p,
1345 * struct Client *source_p,
1346 * struct Channel *chptr, int cap, int nocap)
1347 * Input: The client sending(client_p), the source client(source_p),
1348 * the channel to send mode changes for(chptr)
1349 * Output: None.
1350 * Side-effects: Sends the appropriate mode changes to capable servers.
1351 *
1352 * Reverted back to my original design, except that we now keep a count
1353 * of the number of servers which each combination as an optimisation, so
1354 * the capabs combinations which are not needed are not worked out. -A1kmm
1355 */
1356 void
1357 send_cap_mode_changes(struct Client *client_p, struct Client *source_p,
1358 struct Channel *chptr, struct ChModeChange mode_changes[], int mode_count)
1359 {
1360 static char modebuf[BUFSIZE];
1361 static char parabuf[BUFSIZE];
1362 int i, mbl, pbl, nc, mc, preflen, len;
1363 char *pbuf;
1364 const char *arg;
1365 int dir;
1366 int j;
1367 int cap;
1368 int nocap;
1369 int arglen;
1370
1371 /* Now send to servers... */
1372 for (j = 0; j < NCHCAP_COMBOS; j++)
1373 {
1374 if(chcap_combos[j].count == 0)
1375 continue;
1376
1377 mc = 0;
1378 nc = 0;
1379 pbl = 0;
1380 parabuf[0] = 0;
1381 pbuf = parabuf;
1382 dir = MODE_QUERY;
1383
1384 cap = chcap_combos[j].cap_yes;
1385 nocap = chcap_combos[j].cap_no;
1386
1387 mbl = preflen = rb_sprintf(modebuf, ":%s TMODE %ld %s ",
1388 use_id(source_p), (long) chptr->channelts,
1389 chptr->chname);
1390
1391 /* loop the list of - modes we have */
1392 for (i = 0; i < mode_count; i++)
1393 {
1394 /* if they dont support the cap we need, or they do support a cap they
1395 * cant have, then dont add it to the modebuf.. that way they wont see
1396 * the mode
1397 */
1398 if((mode_changes[i].letter == 0) ||
1399 ((cap & mode_changes[i].caps) != mode_changes[i].caps)
1400 || ((nocap & mode_changes[i].nocaps) != mode_changes[i].nocaps))
1401 continue;
1402
1403 if(!EmptyString(mode_changes[i].id))
1404 arg = mode_changes[i].id;
1405 else
1406 arg = mode_changes[i].arg;
1407
1408 if(arg)
1409 {
1410 arglen = strlen(arg);
1411
1412 /* dont even think about it! --fl */
1413 if(arglen > MODEBUFLEN - 5)
1414 continue;
1415 }
1416
1417 /* if we're creeping past the buf size, we need to send it and make
1418 * another line for the other modes
1419 * XXX - this could give away server topology with uids being
1420 * different lengths, but not much we can do, except possibly break
1421 * them as if they were the longest of the nick or uid at all times,
1422 * which even then won't work as we don't always know the uid -A1kmm.
1423 */
1424 if(arg && ((mc == MAXMODEPARAMSSERV) ||
1425 ((mbl + pbl + arglen + 4) > (BUFSIZE - 3))))
1426 {
1427 if(nc != 0)
1428 sendto_server(client_p, chptr, cap, nocap,
1429 "%s %s", modebuf, parabuf);
1430 nc = 0;
1431 mc = 0;
1432
1433 mbl = preflen;
1434 pbl = 0;
1435 pbuf = parabuf;
1436 parabuf[0] = 0;
1437 dir = MODE_QUERY;
1438 }
1439
1440 if(dir != mode_changes[i].dir)
1441 {
1442 modebuf[mbl++] = (mode_changes[i].dir == MODE_ADD) ? '+' : '-';
1443 dir = mode_changes[i].dir;
1444 }
1445
1446 modebuf[mbl++] = mode_changes[i].letter;
1447 modebuf[mbl] = 0;
1448 nc++;
1449
1450 if(arg != NULL)
1451 {
1452 len = rb_sprintf(pbuf, "%s ", arg);
1453 pbuf += len;
1454 pbl += len;
1455 mc++;
1456 }
1457 }
1458
1459 if(pbl && parabuf[pbl - 1] == ' ')
1460 parabuf[pbl - 1] = 0;
1461
1462 if(nc != 0)
1463 sendto_server(client_p, chptr, cap, nocap, "%s %s", modebuf, parabuf);
1464 }
1465 }
1466
1467 void
1468 resv_chan_forcepart(const char *name, const char *reason, int temp_time)
1469 {
1470 rb_dlink_node *ptr;
1471 rb_dlink_node *next_ptr;
1472 struct Channel *chptr;
1473 struct membership *msptr;
1474 struct Client *target_p;
1475
1476 if(!ConfigChannel.resv_forcepart)
1477 return;
1478
1479 /* for each user on our server in the channel list
1480 * send them a PART, and notify opers.
1481 */
1482 chptr = find_channel(name);
1483 if(chptr != NULL)
1484 {
1485 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
1486 {
1487 msptr = ptr->data;
1488 target_p = msptr->client_p;
1489
1490 if(IsExemptResv(target_p))
1491 continue;
1492
1493 sendto_server(target_p, chptr, CAP_TS6, NOCAPS,
1494 ":%s PART %s", target_p->id, chptr->chname);
1495
1496 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s",
1497 target_p->name, target_p->username,
1498 target_p->host, chptr->chname, target_p->name);
1499
1500 remove_user_from_channel(msptr);
1501
1502 /* notify opers & user they were removed from the channel */
1503 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1504 "Forced PART for %s!%s@%s from %s (%s)",
1505 target_p->name, target_p->username,
1506 target_p->host, name, reason);
1507
1508 if(temp_time > 0)
1509 sendto_one_notice(target_p, ":*** Channel %s is temporarily unavailable on this server.",
1510 name);
1511 else
1512 sendto_one_notice(target_p, ":*** Channel %s is no longer available on this server.",
1513 name);
1514 }
1515 }
1516 }