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
35 #include "s_serv.h" /* captab */
39 #include "s_conf.h" /* ConfigFileEntry, ConfigChannel */
40 #include "s_newconf.h"
42 #include "ipv4_from_ipv6.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 void free_topic(struct Channel
*chptr
);
54 static int h_can_join
;
55 static int h_can_send
;
56 int h_get_channel_access
;
62 * side effects - initialises the various blockheaps
67 channel_heap
= rb_bh_create(sizeof(struct Channel
), CHANNEL_HEAP_SIZE
, "channel_heap");
68 ban_heap
= rb_bh_create(sizeof(struct Ban
), BAN_HEAP_SIZE
, "ban_heap");
69 topic_heap
= rb_bh_create(TOPICLEN
+ 1 + USERHOST_REPLYLEN
, TOPIC_HEAP_SIZE
, "topic_heap");
70 member_heap
= rb_bh_create(sizeof(struct membership
), MEMBER_HEAP_SIZE
, "member_heap");
72 h_can_join
= register_hook("can_join");
73 h_can_send
= register_hook("can_send");
74 h_get_channel_access
= register_hook("get_channel_access");
78 * allocate_channel - Allocates a channel
81 allocate_channel(const char *chname
)
83 struct Channel
*chptr
;
84 chptr
= rb_bh_alloc(channel_heap
);
85 chptr
->chname
= rb_strdup(chname
);
90 free_channel(struct Channel
*chptr
)
92 rb_free(chptr
->chname
);
93 rb_free(chptr
->mode_lock
);
94 rb_bh_free(channel_heap
, chptr
);
98 allocate_ban(const char *banstr
, const char *who
, const char *forward
)
101 bptr
= rb_bh_alloc(ban_heap
);
102 bptr
->banstr
= rb_strdup(banstr
);
103 bptr
->who
= rb_strdup(who
);
104 bptr
->forward
= forward
? rb_strdup(forward
) : NULL
;
110 free_ban(struct Ban
*bptr
)
112 rb_free(bptr
->banstr
);
114 rb_free(bptr
->forward
);
115 rb_bh_free(ban_heap
, bptr
);
119 * send_channel_join()
121 * input - channel to join, client joining.
123 * side effects - none
126 send_channel_join(struct Channel
*chptr
, struct Client
*client_p
)
128 if (!IsClient(client_p
))
131 sendto_channel_local_with_capability(ALL_MEMBERS
, NOCAPS
, CLICAP_EXTENDED_JOIN
, chptr
, ":%s!%s@%s JOIN %s",
132 client_p
->name
, client_p
->username
, client_p
->host
, chptr
->chname
);
134 sendto_channel_local_with_capability(ALL_MEMBERS
, CLICAP_EXTENDED_JOIN
, NOCAPS
, chptr
, ":%s!%s@%s JOIN %s %s :%s",
135 client_p
->name
, client_p
->username
, client_p
->host
, chptr
->chname
,
136 EmptyString(client_p
->user
->suser
) ? "*" : client_p
->user
->suser
,
139 /* Send away message to away-notify enabled clients. */
140 if (client_p
->user
->away
)
141 sendto_channel_local_with_capability_butone(client_p
, ALL_MEMBERS
, CLICAP_AWAY_NOTIFY
, NOCAPS
, chptr
,
142 ":%s!%s@%s AWAY :%s", client_p
->name
, client_p
->username
,
143 client_p
->host
, client_p
->user
->away
);
146 /* find_channel_membership()
148 * input - channel to find them in, client to find
149 * output - membership of client in channel, else NULL
153 find_channel_membership(struct Channel
*chptr
, struct Client
*client_p
)
155 struct membership
*msptr
;
158 if(!IsClient(client_p
))
161 /* Pick the most efficient list to use to be nice to things like
162 * CHANSERV which could be in a large number of channels
164 if(rb_dlink_list_length(&chptr
->members
) < rb_dlink_list_length(&client_p
->user
->channel
))
166 RB_DLINK_FOREACH(ptr
, chptr
->members
.head
)
170 if(msptr
->client_p
== client_p
)
176 RB_DLINK_FOREACH(ptr
, client_p
->user
->channel
.head
)
180 if(msptr
->chptr
== chptr
)
188 /* find_channel_status()
190 * input - membership to get status for, whether we can combine flags
191 * output - flags of user on channel
195 find_channel_status(struct membership
*msptr
, int combine
)
197 static char buffer
[3];
216 /* add_user_to_channel()
218 * input - channel to add client to, client to add, channel flags
220 * side effects - user is added to channel
223 add_user_to_channel(struct Channel
*chptr
, struct Client
*client_p
, int flags
)
225 struct membership
*msptr
;
227 s_assert(client_p
->user
!= NULL
);
228 if(client_p
->user
== NULL
)
231 msptr
= rb_bh_alloc(member_heap
);
233 msptr
->chptr
= chptr
;
234 msptr
->client_p
= client_p
;
235 msptr
->flags
= flags
;
237 rb_dlinkAdd(msptr
, &msptr
->usernode
, &client_p
->user
->channel
);
238 rb_dlinkAdd(msptr
, &msptr
->channode
, &chptr
->members
);
240 if(MyClient(client_p
))
241 rb_dlinkAdd(msptr
, &msptr
->locchannode
, &chptr
->locmembers
);
244 /* remove_user_from_channel()
246 * input - membership pointer to remove from channel
248 * side effects - membership (thus user) is removed from channel
251 remove_user_from_channel(struct membership
*msptr
)
253 struct Client
*client_p
;
254 struct Channel
*chptr
;
255 s_assert(msptr
!= NULL
);
259 client_p
= msptr
->client_p
;
260 chptr
= msptr
->chptr
;
262 rb_dlinkDelete(&msptr
->usernode
, &client_p
->user
->channel
);
263 rb_dlinkDelete(&msptr
->channode
, &chptr
->members
);
265 if(client_p
->servptr
== &me
)
266 rb_dlinkDelete(&msptr
->locchannode
, &chptr
->locmembers
);
268 if(!(chptr
->mode
.mode
& MODE_PERMANENT
) && rb_dlink_list_length(&chptr
->members
) <= 0)
269 destroy_channel(chptr
);
271 rb_bh_free(member_heap
, msptr
);
276 /* remove_user_from_channels()
278 * input - user to remove from all channels
280 * side effects - user is removed from all channels
283 remove_user_from_channels(struct Client
*client_p
)
285 struct Channel
*chptr
;
286 struct membership
*msptr
;
288 rb_dlink_node
*next_ptr
;
293 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, client_p
->user
->channel
.head
)
296 chptr
= msptr
->chptr
;
298 rb_dlinkDelete(&msptr
->channode
, &chptr
->members
);
300 if(client_p
->servptr
== &me
)
301 rb_dlinkDelete(&msptr
->locchannode
, &chptr
->locmembers
);
303 if(!(chptr
->mode
.mode
& MODE_PERMANENT
) && rb_dlink_list_length(&chptr
->members
) <= 0)
304 destroy_channel(chptr
);
306 rb_bh_free(member_heap
, msptr
);
309 client_p
->user
->channel
.head
= client_p
->user
->channel
.tail
= NULL
;
310 client_p
->user
->channel
.length
= 0;
313 /* invalidate_bancache_user()
315 * input - user to invalidate ban cache for
317 * side effects - ban cache is invalidated for all memberships of that user
318 * to be used after a nick change
321 invalidate_bancache_user(struct Client
*client_p
)
323 struct membership
*msptr
;
329 RB_DLINK_FOREACH(ptr
, client_p
->user
->channel
.head
)
333 msptr
->flags
&= ~CHFL_BANNED
;
337 /* check_channel_name()
339 * input - channel name
340 * output - 1 if valid channel name, else 0
344 check_channel_name(const char *name
)
346 s_assert(name
!= NULL
);
350 for (; *name
; ++name
)
352 if(!IsChanChar(*name
))
359 /* free_channel_list()
361 * input - rb_dlink list to free
363 * side effects - list of b/e/I modes is cleared
366 free_channel_list(rb_dlink_list
* list
)
369 rb_dlink_node
*next_ptr
;
370 struct Ban
*actualBan
;
372 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, list
->head
)
374 actualBan
= ptr
->data
;
378 list
->head
= list
->tail
= NULL
;
384 * input - channel to destroy
386 * side effects - channel is obliterated
389 destroy_channel(struct Channel
*chptr
)
391 rb_dlink_node
*ptr
, *next_ptr
;
393 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, chptr
->invites
.head
)
395 del_invite(chptr
, ptr
->data
);
398 /* free all bans/exceptions/denies */
399 free_channel_list(&chptr
->banlist
);
400 free_channel_list(&chptr
->exceptlist
);
401 free_channel_list(&chptr
->invexlist
);
402 free_channel_list(&chptr
->quietlist
);
407 rb_dlinkDelete(&chptr
->node
, &global_channel_list
);
408 del_from_channel_hash(chptr
->chname
, chptr
);
412 /* channel_pub_or_secret()
415 * output - "=" if public, "@" if secret, else "*"
419 channel_pub_or_secret(struct Channel
*chptr
)
421 if(PubChannel(chptr
))
423 else if(SecretChannel(chptr
))
428 /* channel_member_names()
430 * input - channel to list, client to list to, show endofnames
432 * side effects - client is given list of users on channel
435 channel_member_names(struct Channel
*chptr
, struct Client
*client_p
, int show_eon
)
437 struct membership
*msptr
;
438 struct Client
*target_p
;
446 int stack
= IsCapable(client_p
, CLICAP_MULTI_PREFIX
);
448 if(ShowChannel(client_p
, chptr
))
450 is_member
= IsMember(client_p
, chptr
);
452 cur_len
= mlen
= sprintf(lbuf
, form_str(RPL_NAMREPLY
),
453 me
.name
, client_p
->name
,
454 channel_pub_or_secret(chptr
), chptr
->chname
);
458 RB_DLINK_FOREACH(ptr
, chptr
->members
.head
)
461 target_p
= msptr
->client_p
;
463 if(IsInvisible(target_p
) && !is_member
)
466 if (IsCapable(client_p
, CLICAP_USERHOST_IN_NAMES
))
468 /* space, possible "@+" prefix */
469 if (cur_len
+ strlen(target_p
->name
) + strlen(target_p
->username
) + strlen(target_p
->host
) + 5 >= BUFSIZE
- 5)
472 sendto_one(client_p
, "%s", lbuf
);
477 tlen
= sprintf(t
, "%s%s!%s@%s ", find_channel_status(msptr
, stack
),
478 target_p
->name
, target_p
->username
, target_p
->host
);
482 /* space, possible "@+" prefix */
483 if(cur_len
+ strlen(target_p
->name
) + 3 >= BUFSIZE
- 3)
486 sendto_one(client_p
, "%s", lbuf
);
491 tlen
= sprintf(t
, "%s%s ", find_channel_status(msptr
, stack
),
499 /* The old behaviour here was to always output our buffer,
500 * even if there are no clients we can show. This happens
501 * when a client does "NAMES" with no parameters, and all
502 * the clients on a -sp channel are +i. I dont see a good
503 * reason for keeping that behaviour, as it just wastes
509 sendto_one(client_p
, "%s", lbuf
);
514 sendto_one(client_p
, form_str(RPL_ENDOFNAMES
),
515 me
.name
, client_p
->name
, chptr
->chname
);
520 * input - channel to remove invite from, client to remove
522 * side effects - user is removed from invite list, if exists
525 del_invite(struct Channel
*chptr
, struct Client
*who
)
527 rb_dlinkFindDestroy(who
, &chptr
->invites
);
528 rb_dlinkFindDestroy(chptr
, &who
->user
->invited
);
533 * input - channel to check bans for, ban list (banlist or quietlist),
534 * user to check bans against, optional prebuilt buffers,
535 * optional forward channel pointer
536 * output - 1 if banned, else 0
540 is_banned_list(struct Channel
*chptr
, rb_dlink_list
*list
,
541 struct Client
*who
, struct membership
*msptr
,
542 const char *s
, const char *s2
, const char **forward
)
544 char src_host
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
545 char src_iphost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
546 char src_althost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
547 char src_ip4host
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
550 struct sockaddr_in ip4
;
552 struct Ban
*actualBan
= NULL
;
553 struct Ban
*actualExcept
= NULL
;
558 /* if the buffers havent been built, do it here */
561 sprintf(src_host
, "%s!%s@%s", who
->name
, who
->username
, who
->host
);
562 sprintf(src_iphost
, "%s!%s@%s", who
->name
, who
->username
, who
->sockhost
);
567 if(who
->localClient
->mangledhost
!= NULL
)
569 /* if host mangling mode enabled, also check their real host */
570 if(!strcmp(who
->host
, who
->localClient
->mangledhost
))
572 sprintf(src_althost
, "%s!%s@%s", who
->name
, who
->username
, who
->orighost
);
575 /* if host mangling mode not enabled and no other spoof,
576 * also check the mangled form of their host */
577 else if (!IsDynSpoof(who
))
579 sprintf(src_althost
, "%s!%s@%s", who
->name
, who
->username
, who
->localClient
->mangledhost
);
584 if(who
->localClient
->ip
.ss_family
== AF_INET6
&&
585 ipv4_from_ipv6((const struct sockaddr_in6
*)&who
->localClient
->ip
, &ip4
))
587 sprintf(src_ip4host
, "%s!%s@", who
->name
, who
->username
);
588 s4
= src_ip4host
+ strlen(src_ip4host
);
589 rb_inet_ntop_sock((struct sockaddr
*)&ip4
,
590 s4
, src_ip4host
+ sizeof src_ip4host
- s4
);
595 RB_DLINK_FOREACH(ptr
, list
->head
)
597 actualBan
= ptr
->data
;
598 if(match(actualBan
->banstr
, s
) ||
599 match(actualBan
->banstr
, s2
) ||
600 match_cidr(actualBan
->banstr
, s2
) ||
601 match_extban(actualBan
->banstr
, who
, chptr
, CHFL_BAN
) ||
602 (s3
!= NULL
&& match(actualBan
->banstr
, s3
))
605 (s4
!= NULL
&& (match(actualBan
->banstr
, s4
) || match_cidr(actualBan
->banstr
, s4
)))
613 if((actualBan
!= NULL
) && ConfigChannel
.use_except
)
615 RB_DLINK_FOREACH(ptr
, chptr
->exceptlist
.head
)
617 actualExcept
= ptr
->data
;
619 /* theyre exempted.. */
620 if(match(actualExcept
->banstr
, s
) ||
621 match(actualExcept
->banstr
, s2
) ||
622 match_cidr(actualExcept
->banstr
, s2
) ||
623 match_extban(actualExcept
->banstr
, who
, chptr
, CHFL_EXCEPTION
) ||
624 (s3
!= NULL
&& match(actualExcept
->banstr
, s3
)))
626 /* cache the fact theyre not banned */
629 msptr
->bants
= chptr
->bants
;
630 msptr
->flags
&= ~CHFL_BANNED
;
633 return CHFL_EXCEPTION
;
638 /* cache the banned/not banned status */
641 msptr
->bants
= chptr
->bants
;
643 if(actualBan
!= NULL
)
645 msptr
->flags
|= CHFL_BANNED
;
650 msptr
->flags
&= ~CHFL_BANNED
;
655 if (actualBan
&& actualBan
->forward
&& forward
)
656 *forward
= actualBan
->forward
;
658 return ((actualBan
? CHFL_BAN
: 0));
663 * input - channel to check bans for, user to check bans against
664 * optional prebuilt buffers, optional forward channel pointer
665 * output - 1 if banned, else 0
669 is_banned(struct Channel
*chptr
, struct Client
*who
, struct membership
*msptr
,
670 const char *s
, const char *s2
, const char **forward
)
672 if (chptr
->last_checked_client
!= NULL
&&
673 who
== chptr
->last_checked_client
&&
674 chptr
->last_checked_type
== CHFL_BAN
&&
675 chptr
->last_checked_ts
> chptr
->bants
)
676 return chptr
->last_checked_result
;
678 chptr
->last_checked_client
= who
;
679 chptr
->last_checked_type
= CHFL_BAN
;
680 chptr
->last_checked_result
= is_banned_list(chptr
, &chptr
->banlist
, who
, msptr
, s
, s2
, forward
);
681 chptr
->last_checked_ts
= rb_current_time();
683 return chptr
->last_checked_result
;
688 * input - channel to check bans for, user to check bans against
689 * optional prebuilt buffers
690 * output - 1 if banned, else 0
694 is_quieted(struct Channel
*chptr
, struct Client
*who
, struct membership
*msptr
,
695 const char *s
, const char *s2
)
697 if (chptr
->last_checked_client
!= NULL
&&
698 who
== chptr
->last_checked_client
&&
699 chptr
->last_checked_type
== CHFL_QUIET
&&
700 chptr
->last_checked_ts
> chptr
->bants
)
701 return chptr
->last_checked_result
;
703 chptr
->last_checked_client
= who
;
704 chptr
->last_checked_type
= CHFL_QUIET
;
705 chptr
->last_checked_result
= is_banned_list(chptr
, &chptr
->quietlist
, who
, msptr
, s
, s2
, NULL
);
706 chptr
->last_checked_ts
= rb_current_time();
708 return chptr
->last_checked_result
;
713 * input - client to check, channel to check for, key
714 * output - reason for not being able to join, else 0, channel name to forward to
716 * caveats - this function should only be called on a local user.
719 can_join(struct Client
*source_p
, struct Channel
*chptr
, const char *key
, const char **forward
)
721 rb_dlink_node
*invite
= NULL
;
723 struct Ban
*invex
= NULL
;
724 char src_host
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
725 char src_iphost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
726 char src_althost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
729 hook_data_channel moduledata
;
731 s_assert(source_p
->localClient
!= NULL
);
733 moduledata
.client
= source_p
;
734 moduledata
.chptr
= chptr
;
735 moduledata
.approved
= 0;
737 sprintf(src_host
, "%s!%s@%s", source_p
->name
, source_p
->username
, source_p
->host
);
738 sprintf(src_iphost
, "%s!%s@%s", source_p
->name
, source_p
->username
, source_p
->sockhost
);
739 if(source_p
->localClient
->mangledhost
!= NULL
)
741 /* if host mangling mode enabled, also check their real host */
742 if(!strcmp(source_p
->host
, source_p
->localClient
->mangledhost
))
744 sprintf(src_althost
, "%s!%s@%s", source_p
->name
, source_p
->username
, source_p
->orighost
);
747 /* if host mangling mode not enabled and no other spoof,
748 * also check the mangled form of their host */
749 else if (!IsDynSpoof(source_p
))
751 sprintf(src_althost
, "%s!%s@%s", source_p
->name
, source_p
->username
, source_p
->localClient
->mangledhost
);
756 if((is_banned(chptr
, source_p
, NULL
, src_host
, src_iphost
, forward
)) == CHFL_BAN
)
758 moduledata
.approved
= ERR_BANNEDFROMCHAN
;
759 goto finish_join_check
;
762 if(*chptr
->mode
.key
&& (EmptyString(key
) || irccmp(chptr
->mode
.key
, key
)))
764 moduledata
.approved
= ERR_BADCHANNELKEY
;
765 goto finish_join_check
;
768 /* All checks from this point on will forward... */
770 *forward
= chptr
->mode
.forward
;
772 if(chptr
->mode
.mode
& MODE_INVITEONLY
)
774 RB_DLINK_FOREACH(invite
, source_p
->user
->invited
.head
)
776 if(invite
->data
== chptr
)
781 if(!ConfigChannel
.use_invex
)
782 moduledata
.approved
= ERR_INVITEONLYCHAN
;
783 RB_DLINK_FOREACH(ptr
, chptr
->invexlist
.head
)
786 if(match(invex
->banstr
, src_host
)
787 || match(invex
->banstr
, src_iphost
)
788 || match_cidr(invex
->banstr
, src_iphost
)
789 || match_extban(invex
->banstr
, source_p
, chptr
, CHFL_INVEX
)
790 || (use_althost
&& match(invex
->banstr
, src_althost
)))
794 moduledata
.approved
= ERR_INVITEONLYCHAN
;
798 if(chptr
->mode
.limit
&&
799 rb_dlink_list_length(&chptr
->members
) >= (unsigned long) chptr
->mode
.limit
)
800 i
= ERR_CHANNELISFULL
;
801 if(chptr
->mode
.mode
& MODE_REGONLY
&& EmptyString(source_p
->user
->suser
))
802 i
= ERR_NEEDREGGEDNICK
;
803 /* join throttling stuff --nenolod */
804 else if(chptr
->mode
.join_num
> 0 && chptr
->mode
.join_time
> 0)
806 if ((rb_current_time() - chptr
->join_delta
<=
807 chptr
->mode
.join_time
) && (chptr
->join_count
>=
808 chptr
->mode
.join_num
))
812 /* allow /invite to override +l/+r/+j also -- jilles */
813 if (i
!= 0 && invite
== NULL
)
815 RB_DLINK_FOREACH(invite
, source_p
->user
->invited
.head
)
817 if(invite
->data
== chptr
)
821 moduledata
.approved
= i
;
825 call_hook(h_can_join
, &moduledata
);
827 return moduledata
.approved
;
832 * input - user to check in channel, membership pointer
833 * output - whether can explicitly send or not, else CAN_SEND_NONOP
837 can_send(struct Channel
*chptr
, struct Client
*source_p
, struct membership
*msptr
)
839 hook_data_channel_approval moduledata
;
841 moduledata
.approved
= CAN_SEND_NONOP
;
842 moduledata
.dir
= MODE_QUERY
;
844 if(IsServer(source_p
) || IsService(source_p
))
847 if(MyClient(source_p
) && hash_find_resv(chptr
->chname
) &&
848 !IsOper(source_p
) && !IsExemptResv(source_p
))
849 moduledata
.approved
= CAN_SEND_NO
;
853 msptr
= find_channel_membership(chptr
, source_p
);
857 /* if its +m or +n and theyre not in the channel,
858 * they cant send. we dont check bans here because
859 * theres no possibility of caching them --fl
861 if(chptr
->mode
.mode
& MODE_NOPRIVMSGS
|| chptr
->mode
.mode
& MODE_MODERATED
)
862 moduledata
.approved
= CAN_SEND_NO
;
864 moduledata
.approved
= CAN_SEND_NONOP
;
866 return moduledata
.approved
;
870 if(chptr
->mode
.mode
& MODE_MODERATED
)
871 moduledata
.approved
= CAN_SEND_NO
;
873 if(MyClient(source_p
))
875 /* cached can_send */
876 if(msptr
->bants
== chptr
->bants
)
878 if(can_send_banned(msptr
))
879 moduledata
.approved
= CAN_SEND_NO
;
881 else if(is_banned(chptr
, source_p
, msptr
, NULL
, NULL
, NULL
) == CHFL_BAN
882 || is_quieted(chptr
, source_p
, msptr
, NULL
, NULL
) == CHFL_BAN
)
883 moduledata
.approved
= CAN_SEND_NO
;
886 if(is_chanop_voiced(msptr
))
887 moduledata
.approved
= CAN_SEND_OPV
;
889 moduledata
.client
= source_p
;
890 moduledata
.chptr
= msptr
->chptr
;
891 moduledata
.msptr
= msptr
;
892 moduledata
.target
= NULL
;
893 moduledata
.dir
= (moduledata
.approved
== CAN_SEND_NO
) ? MODE_ADD
: MODE_QUERY
;
895 call_hook(h_can_send
, &moduledata
);
897 return moduledata
.approved
;
901 * flood_attack_channel
902 * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC
903 * says NOTICE must not auto reply
904 * - pointer to source Client
905 * - pointer to target channel
906 * output - 1 if target is under flood attack
907 * side effects - check for flood attack on target chptr
910 flood_attack_channel(int p_or_n
, struct Client
*source_p
, struct Channel
*chptr
, char *chname
)
914 if(GlobalSetOptions
.floodcount
&& MyClient(source_p
))
916 if((chptr
->first_received_message_time
+ 1) < rb_current_time())
918 delta
= rb_current_time() - chptr
->first_received_message_time
;
919 chptr
->received_number_of_privmsgs
-= delta
;
920 chptr
->first_received_message_time
= rb_current_time();
921 if(chptr
->received_number_of_privmsgs
<= 0)
923 chptr
->received_number_of_privmsgs
= 0;
924 chptr
->flood_noticed
= 0;
928 if((chptr
->received_number_of_privmsgs
>= GlobalSetOptions
.floodcount
)
929 || chptr
->flood_noticed
)
931 if(chptr
->flood_noticed
== 0)
933 sendto_realops_snomask(SNO_BOTS
, *chptr
->chname
== '&' ? L_ALL
: L_NETWIDE
,
934 "Possible Flooder %s[%s@%s] on %s target: %s",
935 source_p
->name
, source_p
->username
,
937 source_p
->servptr
->name
, chptr
->chname
);
938 chptr
->flood_noticed
= 1;
940 /* Add a bit of penalty */
941 chptr
->received_number_of_privmsgs
+= 2;
943 if(MyClient(source_p
) && (p_or_n
!= 1))
945 ":%s NOTICE %s :*** Message to %s throttled due to flooding",
946 me
.name
, source_p
->name
, chptr
->chname
);
950 chptr
->received_number_of_privmsgs
++;
956 /* find_bannickchange_channel()
957 * Input: client to check
958 * Output: channel preventing nick change
961 find_bannickchange_channel(struct Client
*client_p
)
963 struct Channel
*chptr
;
964 struct membership
*msptr
;
966 char src_host
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
967 char src_iphost
[NICKLEN
+ USERLEN
+ HOSTLEN
+ 6];
969 if (!MyClient(client_p
))
972 sprintf(src_host
, "%s!%s@%s", client_p
->name
, client_p
->username
, client_p
->host
);
973 sprintf(src_iphost
, "%s!%s@%s", client_p
->name
, client_p
->username
, client_p
->sockhost
);
975 RB_DLINK_FOREACH(ptr
, client_p
->user
->channel
.head
)
978 chptr
= msptr
->chptr
;
979 if (is_chanop_voiced(msptr
))
981 /* cached can_send */
982 if (msptr
->bants
== chptr
->bants
)
984 if (can_send_banned(msptr
))
987 else if (is_banned(chptr
, client_p
, msptr
, src_host
, src_iphost
, NULL
) == CHFL_BAN
988 || is_quieted(chptr
, client_p
, msptr
, src_host
, src_iphost
) == CHFL_BAN
)
994 /* void check_spambot_warning(struct Client *source_p)
995 * Input: Client to check, channel name or NULL if this is a part.
997 * Side-effects: Updates the client's oper_warn_count_down, warns the
998 * IRC operators if necessary, and updates join_leave_countdown as
1002 check_spambot_warning(struct Client
*source_p
, const char *name
)
1005 int decrement_count
;
1006 if((GlobalSetOptions
.spam_num
&&
1007 (source_p
->localClient
->join_leave_count
>= GlobalSetOptions
.spam_num
)))
1009 if(source_p
->localClient
->oper_warn_count_down
> 0)
1010 source_p
->localClient
->oper_warn_count_down
--;
1012 source_p
->localClient
->oper_warn_count_down
= 0;
1013 if(source_p
->localClient
->oper_warn_count_down
== 0 &&
1016 /* Its already known as a possible spambot */
1017 sendto_realops_snomask(SNO_BOTS
, L_NETWIDE
,
1018 "User %s (%s@%s) trying to join %s is a possible spambot",
1020 source_p
->username
, source_p
->orighost
, name
);
1021 source_p
->localClient
->oper_warn_count_down
= OPER_SPAM_COUNTDOWN
;
1027 (rb_current_time() - source_p
->localClient
->last_leave_time
)) >
1028 JOIN_LEAVE_COUNT_EXPIRE_TIME
)
1030 decrement_count
= (t_delta
/ JOIN_LEAVE_COUNT_EXPIRE_TIME
);
1033 else if(decrement_count
> source_p
->localClient
->join_leave_count
)
1034 source_p
->localClient
->join_leave_count
= 0;
1036 source_p
->localClient
->join_leave_count
-= decrement_count
;
1040 if((rb_current_time() -
1041 (source_p
->localClient
->last_join_time
)) < GlobalSetOptions
.spam_time
)
1043 /* oh, its a possible spambot */
1044 source_p
->localClient
->join_leave_count
++;
1048 source_p
->localClient
->last_join_time
= rb_current_time();
1050 source_p
->localClient
->last_leave_time
= rb_current_time();
1054 /* check_splitmode()
1058 * side effects - compares usercount and servercount against their split
1059 * values and adjusts splitmode accordingly
1062 check_splitmode(void *unused
)
1064 if(splitchecking
&& (ConfigChannel
.no_join_on_split
|| ConfigChannel
.no_create_on_split
))
1066 /* not split, we're being asked to check now because someone
1071 if(eob_count
< split_servers
|| Count
.total
< split_users
)
1074 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1075 "Network split, activating splitmode");
1076 check_splitmode_ev
= rb_event_addish("check_splitmode", check_splitmode
, NULL
, 2);
1079 /* in splitmode, check whether its finished */
1080 else if(eob_count
>= split_servers
&& Count
.total
>= split_users
)
1084 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1085 "Network rejoined, deactivating splitmode");
1087 rb_event_delete(check_splitmode_ev
);
1088 check_splitmode_ev
= NULL
;
1096 * input - channel to allocate topic for
1097 * output - 1 on success, else 0
1098 * side effects - channel gets a topic allocated
1101 allocate_topic(struct Channel
*chptr
)
1108 ptr
= rb_bh_alloc(topic_heap
);
1110 /* Basically we allocate one large block for the topic and
1111 * the topic info. We then split it up into two and shove it
1115 chptr
->topic_info
= (char *) ptr
+ TOPICLEN
+ 1;
1116 *chptr
->topic
= '\0';
1117 *chptr
->topic_info
= '\0';
1122 * input - channel which has topic to free
1124 * side effects - channels topic is free'd
1127 free_topic(struct Channel
*chptr
)
1131 if(chptr
== NULL
|| chptr
->topic
== NULL
)
1134 /* This is safe for now - If you change allocate_topic you
1135 * MUST change this as well
1138 rb_bh_free(topic_heap
, ptr
);
1139 chptr
->topic
= NULL
;
1140 chptr
->topic_info
= NULL
;
1143 /* set_channel_topic()
1145 * input - channel, topic to set, topic info and topic ts
1147 * side effects - channels topic, topic info and TS are set.
1150 set_channel_topic(struct Channel
*chptr
, const char *topic
, const char *topic_info
, time_t topicts
)
1152 if(strlen(topic
) > 0)
1154 if(chptr
->topic
== NULL
)
1155 allocate_topic(chptr
);
1156 rb_strlcpy(chptr
->topic
, topic
, TOPICLEN
+ 1);
1157 rb_strlcpy(chptr
->topic_info
, topic_info
, USERHOST_REPLYLEN
);
1158 chptr
->topic_time
= topicts
;
1162 if(chptr
->topic
!= NULL
)
1164 chptr
->topic_time
= 0;
1170 * inputs - pointer to channel
1171 * - pointer to client
1172 * output - string with simple modes
1173 * side effects - result from previous calls overwritten
1175 * Stolen from ShadowIRCd 4 --nenolod
1178 channel_modes(struct Channel
*chptr
, struct Client
*client_p
)
1183 static char final
[BUFSIZE
];
1190 for (i
= 0; i
< 256; i
++)
1192 if(chmode_table
[i
].set_func
== chm_hidden
&& (!IsOper(client_p
) || !IsClient(client_p
)))
1194 if(chptr
->mode
.mode
& chmode_flags
[i
])
1198 if(chptr
->mode
.limit
)
1202 if(!IsClient(client_p
) || IsMember(client_p
, chptr
))
1203 pbuf
+= sprintf(pbuf
, " %d", chptr
->mode
.limit
);
1206 if(*chptr
->mode
.key
)
1210 if(pbuf
> buf2
|| !IsClient(client_p
) || IsMember(client_p
, chptr
))
1211 pbuf
+= sprintf(pbuf
, " %s", chptr
->mode
.key
);
1214 if(chptr
->mode
.join_num
)
1218 if(pbuf
> buf2
|| !IsClient(client_p
) || IsMember(client_p
, chptr
))
1219 pbuf
+= sprintf(pbuf
, " %d:%d", chptr
->mode
.join_num
,
1220 chptr
->mode
.join_time
);
1223 if(*chptr
->mode
.forward
&&
1224 (ConfigChannel
.use_forward
|| !IsClient(client_p
)))
1228 if(pbuf
> buf2
|| !IsClient(client_p
) || IsMember(client_p
, chptr
))
1229 pbuf
+= sprintf(pbuf
, " %s", chptr
->mode
.forward
);
1234 rb_strlcpy(final
, buf1
, sizeof final
);
1235 rb_strlcat(final
, buf2
, sizeof final
);
1239 /* void send_cap_mode_changes(struct Client *client_p,
1240 * struct Client *source_p,
1241 * struct Channel *chptr, int cap, int nocap)
1242 * Input: The client sending(client_p), the source client(source_p),
1243 * the channel to send mode changes for(chptr)
1245 * Side-effects: Sends the appropriate mode changes to capable servers.
1247 * Reverted back to my original design, except that we now keep a count
1248 * of the number of servers which each combination as an optimisation, so
1249 * the capabs combinations which are not needed are not worked out. -A1kmm
1251 * Removed most code here because we don't need to be compatible with ircd
1252 * 2.8.21+CSr and stuff. --nenolod
1255 send_cap_mode_changes(struct Client
*client_p
, struct Client
*source_p
,
1256 struct Channel
*chptr
, struct ChModeChange mode_changes
[], int mode_count
)
1258 static char modebuf
[BUFSIZE
];
1259 static char parabuf
[BUFSIZE
];
1260 int i
, mbl
, pbl
, nc
, mc
, preflen
, len
;
1266 /* Now send to servers... */
1274 mbl
= preflen
= sprintf(modebuf
, ":%s TMODE %ld %s ",
1275 use_id(source_p
), (long) chptr
->channelts
,
1278 /* loop the list of - modes we have */
1279 for (i
= 0; i
< mode_count
; i
++)
1281 /* if they dont support the cap we need, or they do support a cap they
1282 * cant have, then dont add it to the modebuf.. that way they wont see
1285 if (mode_changes
[i
].letter
== 0)
1288 if (!EmptyString(mode_changes
[i
].id
))
1289 arg
= mode_changes
[i
].id
;
1291 arg
= mode_changes
[i
].arg
;
1295 arglen
= strlen(arg
);
1297 /* dont even think about it! --fl */
1298 if(arglen
> MODEBUFLEN
- 5)
1302 /* if we're creeping past the buf size, we need to send it and make
1303 * another line for the other modes
1304 * XXX - this could give away server topology with uids being
1305 * different lengths, but not much we can do, except possibly break
1306 * them as if they were the longest of the nick or uid at all times,
1307 * which even then won't work as we don't always know the uid -A1kmm.
1309 if(arg
&& ((mc
== MAXMODEPARAMSSERV
) ||
1310 ((mbl
+ pbl
+ arglen
+ 4) > (BUFSIZE
- 3))))
1313 sendto_server(client_p
, chptr
, NOCAPS
, NOCAPS
,
1314 "%s %s", modebuf
, parabuf
);
1325 if(dir
!= mode_changes
[i
].dir
)
1327 modebuf
[mbl
++] = (mode_changes
[i
].dir
== MODE_ADD
) ? '+' : '-';
1328 dir
= mode_changes
[i
].dir
;
1331 modebuf
[mbl
++] = mode_changes
[i
].letter
;
1337 len
= sprintf(pbuf
, "%s ", arg
);
1344 if(pbl
&& parabuf
[pbl
- 1] == ' ')
1345 parabuf
[pbl
- 1] = 0;
1348 sendto_server(client_p
, chptr
, NOCAPS
, NOCAPS
, "%s %s", modebuf
, parabuf
);
1352 resv_chan_forcepart(const char *name
, const char *reason
, int temp_time
)
1355 rb_dlink_node
*next_ptr
;
1356 struct Channel
*chptr
;
1357 struct membership
*msptr
;
1358 struct Client
*target_p
;
1360 if(!ConfigChannel
.resv_forcepart
)
1363 /* for each user on our server in the channel list
1364 * send them a PART, and notify opers.
1366 chptr
= find_channel(name
);
1369 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, chptr
->locmembers
.head
)
1372 target_p
= msptr
->client_p
;
1374 if(IsExemptResv(target_p
))
1377 sendto_server(target_p
, chptr
, CAP_TS6
, NOCAPS
,
1378 ":%s PART %s", target_p
->id
, chptr
->chname
);
1380 sendto_channel_local(ALL_MEMBERS
, chptr
, ":%s!%s@%s PART %s :%s",
1381 target_p
->name
, target_p
->username
,
1382 target_p
->host
, chptr
->chname
, target_p
->name
);
1384 remove_user_from_channel(msptr
);
1386 /* notify opers & user they were removed from the channel */
1387 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
1388 "Forced PART for %s!%s@%s from %s (%s)",
1389 target_p
->name
, target_p
->username
,
1390 target_p
->host
, name
, reason
);
1393 sendto_one_notice(target_p
, ":*** Channel %s is temporarily unavailable on this server.",
1396 sendto_one_notice(target_p
, ":*** Channel %s is no longer available on this server.",