2 * ircd-ratbox: A slightly useful ircd.
3 * channel.c: Controls channels.
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: channel.c 3580 2007-11-07 23:45:14Z jilles $
37 #include "s_serv.h" /* captab */
41 #include "s_conf.h" /* ConfigFileEntry, ConfigChannel */
42 #include "s_newconf.h"
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
;
52 static int channel_capabs
[] = { CAP_EX
, CAP_IE
,
57 #define NCHCAPS (sizeof(channel_capabs)/sizeof(int))
58 #define NCHCAP_COMBOS (1 << NCHCAPS)
60 static struct ChCapCombo chcap_combos
[NCHCAP_COMBOS
];
62 static void free_topic(struct Channel
*chptr
);
64 static int h_can_join
;
65 static int h_can_send
;
66 int h_get_channel_access
;
72 * side effects - initialises the various blockheaps
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");
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");
88 * allocate_channel - Allocates a channel
91 allocate_channel(const char *chname
)
93 struct Channel
*chptr
;
94 chptr
= rb_bh_alloc(channel_heap
);
95 chptr
->chname
= rb_strdup(chname
);
100 free_channel(struct Channel
*chptr
)
102 rb_free(chptr
->chname
);
103 rb_free(chptr
->mode_lock
);
104 rb_bh_free(channel_heap
, chptr
);
108 allocate_ban(const char *banstr
, const char *who
)
111 bptr
= rb_bh_alloc(ban_heap
);
112 bptr
->banstr
= rb_strdup(banstr
);
113 bptr
->who
= rb_strdup(who
);
119 free_ban(struct Ban
*bptr
)
121 rb_free(bptr
->banstr
);
123 rb_bh_free(ban_heap
, bptr
);
127 * send_channel_join()
129 * input - channel to join, client joining.
131 * side effects - none
134 send_channel_join(struct Channel
*chptr
, struct Client
*client_p
)
136 if (!IsClient(client_p
))
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
);
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
,
148 /* find_channel_membership()
150 * input - channel to find them in, client to find
151 * output - membership of client in channel, else NULL
155 find_channel_membership(struct Channel
*chptr
, struct Client
*client_p
)
157 struct membership
*msptr
;
160 if(!IsClient(client_p
))
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
166 if(rb_dlink_list_length(&chptr
->members
) < rb_dlink_list_length(&client_p
->user
->channel
))
168 RB_DLINK_FOREACH(ptr
, chptr
->members
.head
)
172 if(msptr
->client_p
== client_p
)
178 RB_DLINK_FOREACH(ptr
, client_p
->user
->channel
.head
)
182 if(msptr
->chptr
== chptr
)
190 /* find_channel_status()
192 * input - membership to get status for, whether we can combine flags
193 * output - flags of user on channel
197 find_channel_status(struct membership
*msptr
, int combine
)
199 static char buffer
[3];
218 /* add_user_to_channel()
220 * input - channel to add client to, client to add, channel flags
222 * side effects - user is added to channel
225 add_user_to_channel(struct Channel
*chptr
, struct Client
*client_p
, int flags
)
227 struct membership
*msptr
;
229 s_assert(client_p
->user
!= NULL
);
230 if(client_p
->user
== NULL
)
233 msptr
= rb_bh_alloc(member_heap
);
235 msptr
->chptr
= chptr
;
236 msptr
->client_p
= client_p
;
237 msptr
->flags
= flags
;
239 /* Default to no chanroles until services says we're something else */
240 if (flags
== CHFL_CHANOP
)
241 msptr
->roles
= CHANROLE_INITIAL
;
243 msptr
->roles
= CHANROLE_UNSET
;
245 rb_dlinkAdd(msptr
, &msptr
->usernode
, &client_p
->user
->channel
);
246 rb_dlinkAdd(msptr
, &msptr
->channode
, &chptr
->members
);
248 if(MyClient(client_p
))
249 rb_dlinkAdd(msptr
, &msptr
->locchannode
, &chptr
->locmembers
);
252 /* remove_user_from_channel()
254 * input - membership pointer to remove from channel
256 * side effects - membership (thus user) is removed from channel
259 remove_user_from_channel(struct membership
*msptr
)
261 struct Client
*client_p
;
262 struct Channel
*chptr
;
263 s_assert(msptr
!= NULL
);
267 client_p
= msptr
->client_p
;
268 chptr
= msptr
->chptr
;
270 rb_dlinkDelete(&msptr
->usernode
, &client_p
->user
->channel
);
271 rb_dlinkDelete(&msptr
->channode
, &chptr
->members
);
273 if(client_p
->servptr
== &me
)
274 rb_dlinkDelete(&msptr
->locchannode
, &chptr
->locmembers
);
276 if(!(chptr
->mode
.mode
& MODE_PERMANENT
) && rb_dlink_list_length(&chptr
->members
) <= 0)
277 destroy_channel(chptr
);
279 rb_bh_free(member_heap
, msptr
);
284 /* remove_user_from_channels()
286 * input - user to remove from all channels
288 * side effects - user is removed from all channels
291 remove_user_from_channels(struct Client
*client_p
)
293 struct Channel
*chptr
;
294 struct membership
*msptr
;
296 rb_dlink_node
*next_ptr
;
301 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, client_p
->user
->channel
.head
)
304 chptr
= msptr
->chptr
;
306 rb_dlinkDelete(&msptr
->channode
, &chptr
->members
);
308 if(client_p
->servptr
== &me
)
309 rb_dlinkDelete(&msptr
->locchannode
, &chptr
->locmembers
);
311 if(!(chptr
->mode
.mode
& MODE_PERMANENT
) && rb_dlink_list_length(&chptr
->members
) <= 0)
312 destroy_channel(chptr
);
314 rb_bh_free(member_heap
, msptr
);
317 client_p
->user
->channel
.head
= client_p
->user
->channel
.tail
= NULL
;
318 client_p
->user
->channel
.length
= 0;
321 /* invalidate_bancache_user()
323 * input - user to invalidate ban cache for
325 * side effects - ban cache is invalidated for all memberships of that user
326 * to be used after a nick change
329 invalidate_bancache_user(struct Client
*client_p
)
331 struct membership
*msptr
;
337 RB_DLINK_FOREACH(ptr
, client_p
->user
->channel
.head
)
341 msptr
->flags
&= ~CHFL_BANNED
;
345 /* check_channel_name()
347 * input - channel name
348 * output - 1 if valid channel name, else 0
352 check_channel_name(const char *name
)
354 s_assert(name
!= NULL
);
358 for (; *name
; ++name
)
360 if(!IsChanChar(*name
))
367 /* free_channel_list()
369 * input - rb_dlink list to free
371 * side effects - list of b/e/I modes is cleared
374 free_channel_list(rb_dlink_list
* list
)
377 rb_dlink_node
*next_ptr
;
378 struct Ban
*actualBan
;
380 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, list
->head
)
382 actualBan
= ptr
->data
;
386 list
->head
= list
->tail
= NULL
;
392 * input - channel to destroy
394 * side effects - channel is obliterated
397 destroy_channel(struct Channel
*chptr
)
399 rb_dlink_node
*ptr
, *next_ptr
;
401 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, chptr
->invites
.head
)
403 del_invite(chptr
, ptr
->data
);
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
);
415 rb_dlinkDelete(&chptr
->node
, &global_channel_list
);
416 del_from_channel_hash(chptr
->chname
, chptr
);
420 /* channel_pub_or_secret()
423 * output - "=" if public, "@" if secret, else "*"
427 channel_pub_or_secret(struct Channel
*chptr
)
429 if(PubChannel(chptr
))
431 else if(SecretChannel(chptr
))
436 /* channel_member_names()
438 * input - channel to list, client to list to, show endofnames
440 * side effects - client is given list of users on channel
443 channel_member_names(struct Channel
*chptr
, struct Client
*client_p
, int show_eon
)
445 struct membership
*msptr
;
446 struct Client
*target_p
;
454 int stack
= IsCapable(client_p
, CLICAP_MULTI_PREFIX
);
456 if(ShowChannel(client_p
, chptr
))
458 is_member
= IsMember(client_p
, chptr
);
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
);
466 RB_DLINK_FOREACH(ptr
, chptr
->members
.head
)
469 target_p
= msptr
->client_p
;
471 if(IsInvisible(target_p
) && !is_member
)
474 /* space, possible "@+" prefix */
475 if(cur_len
+ strlen(target_p
->name
) + 3 >= BUFSIZE
- 3)
478 sendto_one(client_p
, "%s", lbuf
);
483 tlen
= rb_sprintf(t
, "%s%s ", find_channel_status(msptr
, stack
),
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
500 sendto_one(client_p
, "%s", lbuf
);
505 sendto_one(client_p
, form_str(RPL_ENDOFNAMES
),
506 me
.name
, client_p
->name
, chptr
->chname
);
511 * input - channel to remove invite from, client to remove
513 * side effects - user is removed from invite list, if exists
516 del_invite(struct Channel
*chptr
, struct Client
*who
)
518 rb_dlinkFindDestroy(who
, &chptr
->invites
);
519 rb_dlinkFindDestroy(chptr
, &who
->user
->invited
);
524 * input - channel to check bans for, user to check bans against
525 * optional prebuilt buffers
526 * output - 1 if banned, else 0
530 is_banned(struct Channel
*chptr
, struct Client
*who
, struct membership
*msptr
,
531 const char *s
, const char *s2
)
533 char src_host
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
534 char src_iphost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
535 char src_althost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
538 struct Ban
*actualBan
= NULL
;
539 struct Ban
*actualExcept
= NULL
;
544 /* if the buffers havent been built, do it here */
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
);
553 if(who
->localClient
->mangledhost
!= NULL
)
555 /* if host mangling mode enabled, also check their real host */
556 if(!strcmp(who
->host
, who
->localClient
->mangledhost
))
558 rb_sprintf(src_althost
, "%s!%s@%s", who
->name
, who
->username
, who
->orighost
);
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
))
565 rb_sprintf(src_althost
, "%s!%s@%s", who
->name
, who
->username
, who
->localClient
->mangledhost
);
570 RB_DLINK_FOREACH(ptr
, chptr
->banlist
.head
)
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
)))
583 if((actualBan
!= NULL
) && ConfigChannel
.use_except
)
585 RB_DLINK_FOREACH(ptr
, chptr
->exceptlist
.head
)
587 actualExcept
= ptr
->data
;
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
)))
596 /* cache the fact theyre not banned */
599 msptr
->bants
= chptr
->bants
;
600 msptr
->flags
&= ~CHFL_BANNED
;
603 return CHFL_EXCEPTION
;
608 /* cache the banned/not banned status */
611 msptr
->bants
= chptr
->bants
;
613 if(actualBan
!= NULL
)
615 msptr
->flags
|= CHFL_BANNED
;
620 msptr
->flags
&= ~CHFL_BANNED
;
625 return ((actualBan
? CHFL_BAN
: 0));
630 * input - channel to check bans for, user to check bans against
631 * optional prebuilt buffers
632 * output - 1 if banned, else 0
636 is_quieted(struct Channel
*chptr
, struct Client
*who
, struct membership
*msptr
,
637 const char *s
, const char *s2
)
639 char src_host
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
640 char src_iphost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
641 char src_althost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
644 struct Ban
*actualBan
= NULL
;
645 struct Ban
*actualExcept
= NULL
;
650 /* if the buffers havent been built, do it here */
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
);
659 if(who
->localClient
->mangledhost
!= NULL
)
661 /* if host mangling mode enabled, also check their real host */
662 if(!strcmp(who
->host
, who
->localClient
->mangledhost
))
664 rb_sprintf(src_althost
, "%s!%s@%s", who
->name
, who
->username
, who
->orighost
);
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
))
671 rb_sprintf(src_althost
, "%s!%s@%s", who
->name
, who
->username
, who
->localClient
->mangledhost
);
676 RB_DLINK_FOREACH(ptr
, chptr
->quietlist
.head
)
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
)))
689 if((actualBan
!= NULL
) && ConfigChannel
.use_except
)
691 RB_DLINK_FOREACH(ptr
, chptr
->exceptlist
.head
)
693 actualExcept
= ptr
->data
;
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
)))
702 /* cache the fact theyre not banned */
705 msptr
->bants
= chptr
->bants
;
706 msptr
->flags
&= ~CHFL_BANNED
;
709 return CHFL_EXCEPTION
;
714 /* cache the banned/not banned status */
717 msptr
->bants
= chptr
->bants
;
719 if(actualBan
!= NULL
)
721 msptr
->flags
|= CHFL_BANNED
;
726 msptr
->flags
&= ~CHFL_BANNED
;
731 return ((actualBan
? CHFL_BAN
: 0));
736 * input - client to check, channel to check for, key
737 * output - reason for not being able to join, else 0
739 * caveats - this function should only be called on a local user.
742 can_join(struct Client
*source_p
, struct Channel
*chptr
, char *key
)
744 rb_dlink_node
*invite
= NULL
;
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];
752 hook_data_channel moduledata
;
754 s_assert(source_p
->localClient
!= NULL
);
756 moduledata
.client
= source_p
;
757 moduledata
.chptr
= chptr
;
758 moduledata
.approved
= 0;
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
)
764 /* if host mangling mode enabled, also check their real host */
765 if(!strcmp(source_p
->host
, source_p
->localClient
->mangledhost
))
767 rb_sprintf(src_althost
, "%s!%s@%s", source_p
->name
, source_p
->username
, source_p
->orighost
);
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
))
774 rb_sprintf(src_althost
, "%s!%s@%s", source_p
->name
, source_p
->username
, source_p
->localClient
->mangledhost
);
779 if((is_banned(chptr
, source_p
, NULL
, src_host
, src_iphost
)) == CHFL_BAN
)
781 moduledata
.approved
= ERR_BANNEDFROMCHAN
;
782 goto finish_join_check
;
785 if(chptr
->mode
.mode
& MODE_INVITEONLY
)
787 RB_DLINK_FOREACH(invite
, source_p
->user
->invited
.head
)
789 if(invite
->data
== chptr
)
794 if(!ConfigChannel
.use_invex
)
795 moduledata
.approved
= ERR_INVITEONLYCHAN
;
796 RB_DLINK_FOREACH(ptr
, chptr
->invexlist
.head
)
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
)))
807 moduledata
.approved
= ERR_INVITEONLYCHAN
;
811 if(*chptr
->mode
.key
&& (EmptyString(key
) || irccmp(chptr
->mode
.key
, key
)))
812 moduledata
.approved
= ERR_BADCHANNELKEY
;
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)
822 if ((rb_current_time() - chptr
->join_delta
<=
823 chptr
->mode
.join_time
) && (chptr
->join_count
>=
824 chptr
->mode
.join_num
))
828 /* allow /invite to override +l/+r/+j also -- jilles */
829 if (i
!= 0 && invite
== NULL
)
831 RB_DLINK_FOREACH(invite
, source_p
->user
->invited
.head
)
833 if(invite
->data
== chptr
)
837 moduledata
.approved
= i
;
841 call_hook(h_can_join
, &moduledata
);
843 return moduledata
.approved
;
848 * input - user to check in channel, membership pointer
849 * output - whether can explicitly send or not, else CAN_SEND_NONOP
853 can_send(struct Channel
*chptr
, struct Client
*source_p
, struct membership
*msptr
)
855 hook_data_channel_approval moduledata
;
857 moduledata
.approved
= CAN_SEND_NONOP
;
859 if(IsServer(source_p
) || IsService(source_p
))
862 if(MyClient(source_p
) && hash_find_resv(chptr
->chname
) &&
863 !IsOper(source_p
) && !IsExemptResv(source_p
))
864 moduledata
.approved
= CAN_SEND_NO
;
868 msptr
= find_channel_membership(chptr
, source_p
);
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
876 if(chptr
->mode
.mode
& MODE_NOPRIVMSGS
|| chptr
->mode
.mode
& MODE_MODERATED
)
877 moduledata
.approved
= CAN_SEND_NO
;
879 moduledata
.approved
= CAN_SEND_NONOP
;
881 return moduledata
.approved
;
885 if(chptr
->mode
.mode
& MODE_MODERATED
)
886 moduledata
.approved
= CAN_SEND_NO
;
888 if(MyClient(source_p
))
890 /* cached can_send */
891 if(msptr
->bants
== chptr
->bants
)
893 if(can_send_banned(msptr
))
894 moduledata
.approved
= CAN_SEND_NO
;
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
;
901 if(is_chanop_voiced(msptr
))
902 moduledata
.approved
= CAN_SEND_OPV
;
904 moduledata
.client
= source_p
;
905 moduledata
.chptr
= msptr
->chptr
;
906 moduledata
.msptr
= msptr
;
907 moduledata
.target
= NULL
;
909 call_hook(h_can_send
, &moduledata
);
911 return moduledata
.approved
;
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
924 flood_attack_channel(int p_or_n
, struct Client
*source_p
, struct Channel
*chptr
, char *chname
)
928 if(GlobalSetOptions
.floodcount
&& MyClient(source_p
))
930 if((chptr
->first_received_message_time
+ 1) < rb_current_time())
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)
937 chptr
->received_number_of_privmsgs
= 0;
938 chptr
->flood_noticed
= 0;
942 if((chptr
->received_number_of_privmsgs
>= GlobalSetOptions
.floodcount
)
943 || chptr
->flood_noticed
)
945 if(chptr
->flood_noticed
== 0)
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
,
951 source_p
->servptr
->name
, chptr
->chname
);
952 chptr
->flood_noticed
= 1;
954 /* Add a bit of penalty */
955 chptr
->received_number_of_privmsgs
+= 2;
957 if(MyClient(source_p
) && (p_or_n
!= 1))
959 ":%s NOTICE %s :*** Message to %s throttled due to flooding",
960 me
.name
, source_p
->name
, chptr
->chname
);
964 chptr
->received_number_of_privmsgs
++;
970 /* find_bannickchange_channel()
971 * Input: client to check
972 * Output: channel preventing nick change
975 find_bannickchange_channel(struct Client
*client_p
)
977 struct Channel
*chptr
;
978 struct membership
*msptr
;
980 char src_host
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
981 char src_iphost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
983 if (!MyClient(client_p
))
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
);
989 RB_DLINK_FOREACH(ptr
, client_p
->user
->channel
.head
)
992 chptr
= msptr
->chptr
;
993 if (is_chanop_voiced(msptr
))
995 /* cached can_send */
996 if (msptr
->bants
== chptr
->bants
)
998 if (can_send_banned(msptr
))
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
)
1008 /* void check_spambot_warning(struct Client *source_p)
1009 * Input: Client to check, channel name or NULL if this is a part.
1011 * Side-effects: Updates the client's oper_warn_count_down, warns the
1012 * IRC operators if necessary, and updates join_leave_countdown as
1016 check_spambot_warning(struct Client
*source_p
, const char *name
)
1019 int decrement_count
;
1020 if((GlobalSetOptions
.spam_num
&&
1021 (source_p
->localClient
->join_leave_count
>= GlobalSetOptions
.spam_num
)))
1023 if(source_p
->localClient
->oper_warn_count_down
> 0)
1024 source_p
->localClient
->oper_warn_count_down
--;
1026 source_p
->localClient
->oper_warn_count_down
= 0;
1027 if(source_p
->localClient
->oper_warn_count_down
== 0 &&
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",
1034 source_p
->username
, source_p
->orighost
, name
);
1035 source_p
->localClient
->oper_warn_count_down
= OPER_SPAM_COUNTDOWN
;
1041 (rb_current_time() - source_p
->localClient
->last_leave_time
)) >
1042 JOIN_LEAVE_COUNT_EXPIRE_TIME
)
1044 decrement_count
= (t_delta
/ JOIN_LEAVE_COUNT_EXPIRE_TIME
);
1047 else if(decrement_count
> source_p
->localClient
->join_leave_count
)
1048 source_p
->localClient
->join_leave_count
= 0;
1050 source_p
->localClient
->join_leave_count
-= decrement_count
;
1054 if((rb_current_time() -
1055 (source_p
->localClient
->last_join_time
)) < GlobalSetOptions
.spam_time
)
1057 /* oh, its a possible spambot */
1058 source_p
->localClient
->join_leave_count
++;
1062 source_p
->localClient
->last_join_time
= rb_current_time();
1064 source_p
->localClient
->last_leave_time
= rb_current_time();
1068 /* check_splitmode()
1072 * side effects - compares usercount and servercount against their split
1073 * values and adjusts splitmode accordingly
1076 check_splitmode(void *unused
)
1078 if(splitchecking
&& (ConfigChannel
.no_join_on_split
|| ConfigChannel
.no_create_on_split
))
1080 /* not split, we're being asked to check now because someone
1085 if(eob_count
< split_servers
|| Count
.total
< split_users
)
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);
1093 /* in splitmode, check whether its finished */
1094 else if(eob_count
>= split_servers
&& Count
.total
>= split_users
)
1098 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1099 "Network rejoined, deactivating splitmode");
1101 rb_event_delete(check_splitmode_ev
);
1102 check_splitmode_ev
= NULL
;
1110 * input - channel to allocate topic for
1111 * output - 1 on success, else 0
1112 * side effects - channel gets a topic allocated
1115 allocate_topic(struct Channel
*chptr
)
1122 ptr
= rb_bh_alloc(topic_heap
);
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
1129 chptr
->topic_info
= (char *) ptr
+ TOPICLEN
+ 1;
1130 *chptr
->topic
= '\0';
1131 *chptr
->topic_info
= '\0';
1136 * input - channel which has topic to free
1138 * side effects - channels topic is free'd
1141 free_topic(struct Channel
*chptr
)
1145 if(chptr
== NULL
|| chptr
->topic
== NULL
)
1148 /* This is safe for now - If you change allocate_topic you
1149 * MUST change this as well
1152 rb_bh_free(topic_heap
, ptr
);
1153 chptr
->topic
= NULL
;
1154 chptr
->topic_info
= NULL
;
1157 /* set_channel_topic()
1159 * input - channel, topic to set, topic info and topic ts
1161 * side effects - channels topic, topic info and TS are set.
1164 set_channel_topic(struct Channel
*chptr
, const char *topic
, const char *topic_info
, time_t topicts
)
1166 if(strlen(topic
) > 0)
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
;
1176 if(chptr
->topic
!= NULL
)
1178 chptr
->topic_time
= 0;
1184 * inputs - pointer to channel
1185 * - pointer to client
1186 * output - string with simple modes
1187 * side effects - result from previous calls overwritten
1189 * Stolen from ShadowIRCd 4 --nenolod
1192 channel_modes(struct Channel
*chptr
, struct Client
*client_p
)
1197 static char final
[BUFSIZE
];
1204 for (i
= 0; i
< 256; i
++)
1205 if(chptr
->mode
.mode
& chmode_flags
[i
])
1208 if(chptr
->mode
.limit
)
1212 if(!IsClient(client_p
) || IsMember(client_p
, chptr
))
1213 pbuf
+= rb_sprintf(pbuf
, " %d", chptr
->mode
.limit
);
1216 if(*chptr
->mode
.key
)
1220 if(pbuf
> buf2
|| !IsClient(client_p
) || IsMember(client_p
, chptr
))
1221 pbuf
+= rb_sprintf(pbuf
, " %s", chptr
->mode
.key
);
1224 if(chptr
->mode
.join_num
)
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
);
1233 if(*chptr
->mode
.forward
&& (ConfigChannel
.use_forward
|| !IsClient(client_p
)))
1237 if(pbuf
> buf2
|| !IsClient(client_p
) || IsMember(client_p
, chptr
))
1238 pbuf
+= rb_sprintf(pbuf
, " %s", chptr
->mode
.forward
);
1243 rb_strlcpy(final
, buf1
, sizeof final
);
1244 rb_strlcat(final
, buf2
, sizeof final
);
1248 /* Now lets do some stuff to keep track of what combinations of
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
1259 /* void init_chcap_usage_counts(void)
1263 * Side-effects - Initialises the usage counts to zero. Fills in the
1264 * chcap_yes and chcap_no combination tables.
1267 init_chcap_usage_counts(void)
1269 unsigned long m
, c
, y
, n
;
1271 memset(chcap_combos
, 0, sizeof(chcap_combos
));
1273 /* For every possible combination */
1274 for (m
= 0; m
< NCHCAP_COMBOS
; m
++)
1276 /* Check each capab */
1277 for (c
= y
= n
= 0; c
< NCHCAPS
; c
++)
1279 if((m
& (1 << c
)) == 0)
1280 n
|= channel_capabs
[c
];
1282 y
|= channel_capabs
[c
];
1284 chcap_combos
[m
].cap_yes
= y
;
1285 chcap_combos
[m
].cap_no
= n
;
1289 /* void set_chcap_usage_counts(struct Client *serv_p)
1290 * Input: serv_p; The client whose capabs to register.
1292 * Side-effects: Increments the usage counts for the correct capab
1296 set_chcap_usage_counts(struct Client
*serv_p
)
1300 for (n
= 0; n
< NCHCAP_COMBOS
; n
++)
1302 if(IsCapable(serv_p
, chcap_combos
[n
].cap_yes
) &&
1303 NotCapable(serv_p
, chcap_combos
[n
].cap_no
))
1305 chcap_combos
[n
].count
++;
1310 /* This should be impossible -A1kmm. */
1314 /* void set_chcap_usage_counts(struct Client *serv_p)
1316 * Inputs - serv_p; The client whose capabs to register.
1318 * Side-effects - Decrements the usage counts for the correct capab
1322 unset_chcap_usage_counts(struct Client
*serv_p
)
1326 for (n
= 0; n
< NCHCAP_COMBOS
; n
++)
1328 if(IsCapable(serv_p
, chcap_combos
[n
].cap_yes
) &&
1329 NotCapable(serv_p
, chcap_combos
[n
].cap_no
))
1331 /* Hopefully capabs can't change dynamically or anything... */
1332 s_assert(chcap_combos
[n
].count
> 0);
1334 if(chcap_combos
[n
].count
> 0)
1335 chcap_combos
[n
].count
--;
1340 /* This should be impossible -A1kmm. */
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)
1350 * Side-effects: Sends the appropriate mode changes to capable servers.
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
1357 send_cap_mode_changes(struct Client
*client_p
, struct Client
*source_p
,
1358 struct Channel
*chptr
, struct ChModeChange mode_changes
[], int mode_count
)
1360 static char modebuf
[BUFSIZE
];
1361 static char parabuf
[BUFSIZE
];
1362 int i
, mbl
, pbl
, nc
, mc
, preflen
, len
;
1371 /* Now send to servers... */
1372 for (j
= 0; j
< NCHCAP_COMBOS
; j
++)
1374 if(chcap_combos
[j
].count
== 0)
1384 cap
= chcap_combos
[j
].cap_yes
;
1385 nocap
= chcap_combos
[j
].cap_no
;
1387 mbl
= preflen
= rb_sprintf(modebuf
, ":%s TMODE %ld %s ",
1388 use_id(source_p
), (long) chptr
->channelts
,
1391 /* loop the list of - modes we have */
1392 for (i
= 0; i
< mode_count
; i
++)
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
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
))
1403 if(!EmptyString(mode_changes
[i
].id
))
1404 arg
= mode_changes
[i
].id
;
1406 arg
= mode_changes
[i
].arg
;
1410 arglen
= strlen(arg
);
1412 /* dont even think about it! --fl */
1413 if(arglen
> MODEBUFLEN
- 5)
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.
1424 if(arg
&& ((mc
== MAXMODEPARAMSSERV
) ||
1425 ((mbl
+ pbl
+ arglen
+ 4) > (BUFSIZE
- 3))))
1428 sendto_server(client_p
, chptr
, cap
, nocap
,
1429 "%s %s", modebuf
, parabuf
);
1440 if(dir
!= mode_changes
[i
].dir
)
1442 modebuf
[mbl
++] = (mode_changes
[i
].dir
== MODE_ADD
) ? '+' : '-';
1443 dir
= mode_changes
[i
].dir
;
1446 modebuf
[mbl
++] = mode_changes
[i
].letter
;
1452 len
= rb_sprintf(pbuf
, "%s ", arg
);
1459 if(pbl
&& parabuf
[pbl
- 1] == ' ')
1460 parabuf
[pbl
- 1] = 0;
1463 sendto_server(client_p
, chptr
, cap
, nocap
, "%s %s", modebuf
, parabuf
);
1468 resv_chan_forcepart(const char *name
, const char *reason
, int temp_time
)
1471 rb_dlink_node
*next_ptr
;
1472 struct Channel
*chptr
;
1473 struct membership
*msptr
;
1474 struct Client
*target_p
;
1476 if(!ConfigChannel
.resv_forcepart
)
1479 /* for each user on our server in the channel list
1480 * send them a PART, and notify opers.
1482 chptr
= find_channel(name
);
1485 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, chptr
->locmembers
.head
)
1488 target_p
= msptr
->client_p
;
1490 if(IsExemptResv(target_p
))
1493 sendto_server(target_p
, chptr
, CAP_TS6
, NOCAPS
,
1494 ":%s PART %s", target_p
->id
, chptr
->chname
);
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
);
1500 remove_user_from_channel(msptr
);
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
);
1509 sendto_one_notice(target_p
, ":*** Channel %s is temporarily unavailable on this server.",
1512 sendto_one_notice(target_p
, ":*** Channel %s is no longer available on this server.",